Spaces:
Running
Running
File size: 6,810 Bytes
f9a28cd 96bdf6c f9a28cd b1cfe1b f9a28cd 96bdf6c f9a28cd 96bdf6c f9a28cd 96bdf6c f9a28cd 6c12d18 96bdf6c f9a28cd 96bdf6c f9a28cd 96bdf6c f9a28cd 96bdf6c f9a28cd b1cfe1b f9a28cd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | import {
DEFAULT_CHANNEL_REQUEST_MODE_PRIORITY as SHARED_DEFAULT_CHANNEL_REQUEST_MODE_PRIORITY,
CHANNEL_REQUEST_MODES as SHARED_CHANNEL_REQUEST_MODES,
CHANNEL_REQUEST_MODE_ADMIN_CONTROL as SHARED_CHANNEL_REQUEST_MODE_ADMIN_CONTROL
} from './channel-request-mode-values.mjs';
import { RequestValidationError } from './image-request-utils';
export const CHANNEL_REQUEST_MODES = SHARED_CHANNEL_REQUEST_MODES as readonly [
'images-non-stream',
'images-sse',
'responses-non-stream',
'responses-sse'
];
export type ChannelRequestMode = (typeof CHANNEL_REQUEST_MODES)[number];
export type ChannelRequestModeBackend = 'images-api' | 'responses-image-generation';
export type ChannelRequestModeDecision = {
requested_backend: ChannelRequestModeBackend;
candidate_channel_request_modes?: readonly ChannelRequestMode[];
request_mode_priority?: readonly ChannelRequestMode[];
preferred_channel_request_mode?: ChannelRequestMode;
fallback_channel_request_mode?: ChannelRequestMode;
selected_channel_request_mode?: ChannelRequestMode;
fallback_applied: boolean;
selected_channel_id?: string;
upstream_host?: string;
no_channel_reason?: string;
};
export type ChannelRequestModeHealthSummary = {
configuredRequestModes: readonly ChannelRequestMode[];
effectiveRequestModes: readonly ChannelRequestMode[];
defaultRequestModePriority: readonly ChannelRequestMode[];
modes: Array<{
mode: ChannelRequestMode;
configuredCredentialCount: number;
healthyCredentialCount: number;
configuredChannelCount: number;
healthyChannelCount: number;
}>;
effectiveRequestModesByChannel: Array<{
channelId: string;
requestModes: readonly ChannelRequestMode[];
requestModePriority: readonly ChannelRequestMode[];
}>;
};
export const DEFAULT_CHANNEL_REQUEST_MODES: readonly ChannelRequestMode[] = ['images-non-stream'];
export const DEFAULT_CHANNEL_REQUEST_MODE_PRIORITY = SHARED_DEFAULT_CHANNEL_REQUEST_MODE_PRIORITY as readonly [
'images-non-stream',
'images-sse',
'responses-non-stream',
'responses-sse'
];
export const CHANNEL_REQUEST_MODE_ADMIN_CONTROL = SHARED_CHANNEL_REQUEST_MODE_ADMIN_CONTROL as {
readonly source: 'admin_env_whitelist';
readonly globalEnv: 'OPENAI_UPSTREAM_REQUEST_MODES';
readonly channelEnvPattern: 'OPENAI_CHANNEL_N_REQUEST_MODES';
readonly globalPriorityEnv: 'OPENAI_UPSTREAM_REQUEST_MODE_PRIORITY';
readonly channelPriorityEnvPattern: 'OPENAI_CHANNEL_N_REQUEST_MODE_PRIORITY';
readonly defaultPriority: readonly ChannelRequestMode[];
readonly defaultPriorityPolicy: 'lowest_cost_first';
readonly mutableAtRuntime: false;
readonly finalGateCommand: string;
readonly smokeGateCommands: Record<ChannelRequestMode, readonly string[]>;
};
const CHANNEL_REQUEST_MODE_SET = new Set<string>(CHANNEL_REQUEST_MODES);
const CHANNEL_REQUEST_MODE_ALIASES: Record<string, ChannelRequestMode> = {
'images-api': 'images-non-stream',
'images-api-non-stream': 'images-non-stream',
'images-api-json': 'images-non-stream',
'images-json': 'images-non-stream',
'images-nonstream': 'images-non-stream',
'images-api-sse': 'images-sse',
'images-stream': 'images-sse',
'images-api-stream': 'images-sse',
responses: 'responses-non-stream',
'responses-json': 'responses-non-stream',
'responses-nonstream': 'responses-non-stream',
'responses-image-generation': 'responses-non-stream',
'responses-image-generation-non-stream': 'responses-non-stream',
'responses-image-generation-sse': 'responses-sse',
'responses-stream': 'responses-sse'
};
export function parseChannelRequestModes(
value: string | undefined,
fieldName: string
): ChannelRequestMode[] | undefined {
if (!value?.trim()) return undefined;
const modes: ChannelRequestMode[] = [];
for (const rawPart of value.split(/[,\s]+/)) {
const normalized = normalizeChannelRequestMode(rawPart);
if (!normalized) continue;
if (!modes.includes(normalized)) {
modes.push(normalized);
}
}
if (modes.length === 0) {
throw new RequestValidationError(`${fieldName} 至少需要包含一个请求方式。`, 500);
}
return modes;
}
export function parseChannelRequestModePriority(
value: string | undefined,
fieldName: string
): ChannelRequestMode[] | undefined {
return parseChannelRequestModes(value, fieldName);
}
export function getEffectiveChannelRequestModes(input: {
requestModes?: readonly ChannelRequestMode[];
}): readonly ChannelRequestMode[] {
return input.requestModes?.length ? input.requestModes : DEFAULT_CHANNEL_REQUEST_MODES;
}
export function orderChannelRequestModesByPriority(input: {
requestModes: readonly ChannelRequestMode[];
requestModePriority?: readonly ChannelRequestMode[];
}): ChannelRequestMode[] {
const allowed = new Set(input.requestModes);
const ordered: ChannelRequestMode[] = [];
appendAllowedRequestModes(ordered, allowed, input.requestModePriority ?? []);
appendAllowedRequestModes(ordered, allowed, DEFAULT_CHANNEL_REQUEST_MODE_PRIORITY);
appendAllowedRequestModes(ordered, allowed, input.requestModes);
return ordered;
}
function appendAllowedRequestModes(
ordered: ChannelRequestMode[],
allowed: ReadonlySet<ChannelRequestMode>,
modes: readonly ChannelRequestMode[]
): void {
for (const mode of modes) {
if (allowed.has(mode) && !ordered.includes(mode)) ordered.push(mode);
}
}
export function channelSupportsRequestMode(
input: { requestModes?: readonly ChannelRequestMode[] },
mode: ChannelRequestMode
): boolean {
return getEffectiveChannelRequestModes(input).includes(mode);
}
export function resolveChannelRequestMode(input: {
imageBackend: ChannelRequestModeBackend;
streamEnabled: boolean;
}): ChannelRequestMode {
if (input.imageBackend === 'responses-image-generation') {
return input.streamEnabled ? 'responses-sse' : 'responses-non-stream';
}
return input.streamEnabled ? 'images-sse' : 'images-non-stream';
}
export function isStreamingChannelRequestMode(mode: ChannelRequestMode): boolean {
return mode.endsWith('-sse');
}
function normalizeChannelRequestMode(value: string): ChannelRequestMode | undefined {
const normalized = value.trim().toLowerCase().replace(/_/g, '-');
if (!normalized) return undefined;
if (CHANNEL_REQUEST_MODE_SET.has(normalized)) return normalized as ChannelRequestMode;
const aliased = CHANNEL_REQUEST_MODE_ALIASES[normalized];
if (aliased) return aliased;
throw new RequestValidationError(`请求方式 ${value} 无效,必须是 ${CHANNEL_REQUEST_MODES.join(', ')} 之一。`, 500);
}
|