gpt-image-playground deploy
Deploy 4770498 to Docker Space
a2c232b
Raw
History Blame Contribute Delete
7.93 kB
import { CHANNEL_REQUEST_MODES, CHANNEL_REQUEST_MODE_ADMIN_CONTROL } from '@/lib/channel-request-mode';
import { getChannelPoolSummary, toPublicChannelFailure } from '@/lib/channel-router';
import { summarizeImageUpstreamProfile } from '@/lib/image-upstream-profile';
import {
readImageGenerationBackend,
readImageStreamMode,
readImageStreamingStrategy
} from '@/lib/image-upstream-strategy';
import { summarizeOpenAIImageTransport } from '@/lib/openai-image-transport';
import { getServerChannelState } from '@/lib/server-channel-router';
import { readBooleanEnv, readPositiveIntegerEnv } from '@/lib/server-runtime';
import { computeStreamingBatchRecommendation } from '@/lib/streaming-batch';
import { getWebuiImageCleanupSummary } from '@/lib/webui-image-cleanup-runtime';
import { NextResponse } from 'next/server';
const RESPONSES_IMAGE_BACKEND_REQUIRED_ENV = ['ENABLE_RESPONSES_IMAGE_BACKEND'] as const;
const RESPONSES_IMAGE_BACKEND_OPTIONAL_ENV = ['OPENAI_RESPONSES_API_MODEL'] as const;
export async function GET() {
try {
const serverChannelState = getServerChannelState();
const summary = getChannelPoolSummary(serverChannelState.config);
const healthSummary = serverChannelState.router?.getHealthSummary();
const requestModeHealthSummary = serverChannelState.router?.getRequestModeHealthSummary();
const maxStreamsPerCredential = readPositiveIntegerEnv(process.env, 'OPENAI_MAX_STREAMS_PER_CREDENTIAL', 1);
const channelQueueSummary = serverChannelState.channelCapacityQueue.summary();
const responsesImageBackendEnabled = readBooleanEnv(process.env, 'ENABLE_RESPONSES_IMAGE_BACKEND');
const responsesImageBackendHasDefaultModel = Boolean(process.env.OPENAI_RESPONSES_API_MODEL?.trim());
const responsesImageBackendMissingEnv = readResponsesImageBackendMissingEnv(process.env);
const recommendedStreamingConcurrency = computeStreamingBatchRecommendation({
credentialCount: healthSummary?.healthyCredentialCount ?? summary.credentialCount,
maxStreamsPerCredential,
strategy: summary.strategy
});
const upstreamProfile = summarizeImageUpstreamProfile({
serverProfiles: summary.channels.map((channel) => channel.effectiveProfile)
});
const providerManifests = summary.channels
.filter((channel) => channel.providerManifest)
.map((channel) => ({
channelId: channel.id,
manifest: channel.providerManifest
}));
return NextResponse.json({
streaming: {
defaultBackend: readImageGenerationBackend(new FormData(), process.env),
defaultMode: readImageStreamMode(new FormData(), process.env),
defaultStrategy: readImageStreamingStrategy(new FormData(), process.env),
unavailableMarkScope: 'channel+backend+strategy+operation',
availability: serverChannelState.streamingAvailability.summary()
},
streamingBatch: {
enabled: true,
recommendedConcurrency: recommendedStreamingConcurrency,
requestCredentialConcurrency: maxStreamsPerCredential,
healthyCredentialCount: healthSummary?.healthyCredentialCount ?? summary.credentialCount,
unhealthyCredentialCount: healthSummary?.unhealthyCredentialCount ?? 0,
channelCount: healthSummary?.channelCount ?? summary.channelCount,
healthyChannelCount: healthSummary?.healthyChannelCount ?? summary.channelCount,
unhealthyChannelCount: healthSummary?.unhealthyChannelCount ?? 0,
lastFailure: toPublicChannelFailure(healthSummary?.lastFailure)
},
channelQueue: {
enabled: channelQueueSummary.enabled,
capacityPerCredential: channelQueueSummary.capacityPerKey,
maxWaitMs: channelQueueSummary.maxWaitMs,
maxSize: channelQueueSummary.maxSize,
active: channelQueueSummary.active,
queued: channelQueueSummary.queued,
credentials: channelQueueSummary.keys.map((item) => ({
credentialId: item.key,
active: item.active,
queued: item.queued
}))
},
channelRecovery: {
failureCooldownEnabled: serverChannelState.channelRecovery.failureCooldownEnabled,
failureCooldownMs: serverChannelState.channelRecovery.failureCooldownMs,
requireProbeForRecovery: serverChannelState.channelRecovery.requireProbeForRecovery,
pendingProbeCredentialCount: healthSummary?.pendingRecoveryProbeCredentialCount ?? 0,
pendingProbeChannelCount: healthSummary?.pendingRecoveryProbeChannelCount ?? 0,
probe: serverChannelState.channelRecoveryProber?.summary()
},
channelRouting: {
strategy: summary.strategy,
credentialCount: summary.credentialCount,
channelCount: summary.channelCount,
supportedRequestModes: CHANNEL_REQUEST_MODES,
configuredRequestModes:
requestModeHealthSummary?.configuredRequestModes ??
(summary.credentialCount > 0 ? CHANNEL_REQUEST_MODES : []),
effectiveRequestModes:
requestModeHealthSummary?.effectiveRequestModes ??
(summary.credentialCount > 0 ? CHANNEL_REQUEST_MODES : []),
defaultRequestModePriority:
requestModeHealthSummary?.defaultRequestModePriority ??
CHANNEL_REQUEST_MODE_ADMIN_CONTROL.defaultPriority,
requestModeControls: CHANNEL_REQUEST_MODE_ADMIN_CONTROL,
requestModeHealth: requestModeHealthSummary?.modes ?? [],
upstreamProxyByChannel: summary.channels.map((channel) => ({
channelId: channel.id,
upstreamProxy: channel.upstreamProxy
})),
requestModesByChannel: summary.channels.map((channel) => ({
channelId: channel.id,
requestModes: channel.requestModes,
requestModePriority: channel.requestModePriority
})),
effectiveRequestModesByChannel:
requestModeHealthSummary?.effectiveRequestModesByChannel ??
summary.channels.map((channel) => ({
channelId: channel.id,
requestModes: channel.requestModes,
requestModePriority: channel.requestModePriority
}))
},
upstreamProfile,
imageTransport: summarizeOpenAIImageTransport(process.env),
providerManifests,
webuiImageCleanup: await getWebuiImageCleanupSummary(process.env),
responsesImageBackend: {
enabled: responsesImageBackendEnabled,
mode: 'experimental',
requiredEnv: [...RESPONSES_IMAGE_BACKEND_REQUIRED_ENV],
optionalEnv: [...RESPONSES_IMAGE_BACKEND_OPTIONAL_ENV],
hasDefaultModel: responsesImageBackendHasDefaultModel,
missingEnv: responsesImageBackendMissingEnv
}
});
} catch (error) {
return NextResponse.json({ error: error instanceof Error ? error.message : '配置错误' }, { status: 500 });
}
}
function readResponsesImageBackendMissingEnv(env: Record<string, string | undefined>): string[] {
const missing: string[] = [];
if (!readBooleanEnv(env, 'ENABLE_RESPONSES_IMAGE_BACKEND')) {
missing.push('ENABLE_RESPONSES_IMAGE_BACKEND');
}
return missing;
}