fix(provider): 修正媒体请求转换与上游错误透传
按上游协议能力延迟处理媒体资源:OpenAI 兼容平台默认使用 multipart,显式配置后才发送 JSON URL;Gemini 官方协议使用 Files API,兼容协议使用内嵌 Base64,并同步覆盖相关媒体客户端。\n\n安全的上游 400/422 原始错误会作为下游 message 返回,同时保留结构化诊断信息和历史任务兼容。\n\n验证:API 全量无缓存测试、go vet、pnpm lint、pnpm test、pnpm build、pnpm openapi、git diff --check。
This commit is contained in:
@@ -504,6 +504,16 @@ export function PlatformManagementPanel(props: {
|
||||
<ToggleField checked={form.supportBase64Input} label="支持 Base64 输入" onChange={(checked) => setForm({ ...form, supportBase64Input: checked })} />
|
||||
<ToggleField checked={form.supportUrlInput} label="支持 URL 输入" onChange={(checked) => setForm({ ...form, supportUrlInput: checked })} />
|
||||
</div>
|
||||
<Label>
|
||||
OpenAI 图片编辑请求格式
|
||||
<Select
|
||||
value={form.imageEditRequestFormat}
|
||||
onChange={(event) => setForm({ ...form, imageEditRequestFormat: event.target.value as PlatformWizardForm['imageEditRequestFormat'] })}
|
||||
>
|
||||
<option value="multipart">Multipart 文件(默认)</option>
|
||||
<option value="json_url">JSON URL(仅平台明确支持)</option>
|
||||
</Select>
|
||||
</Label>
|
||||
</FormSection>
|
||||
|
||||
<FormSection icon={<Boxes size={16} />} title={`模型绑定 · ${selectedModels.length}/${availableModels.length}`}>
|
||||
@@ -1192,6 +1202,7 @@ function platformToForm(
|
||||
httpProxy: networkProxy.httpProxy,
|
||||
supportBase64Input: readBoolean(config, 'supportBase64Input', true),
|
||||
supportUrlInput: readBoolean(config, 'supportUrlInput', true),
|
||||
imageEditRequestFormat: readImageEditRequestFormat(config),
|
||||
selectedModelIds: platformModelBaseIds(platform, baseModels, currentModels),
|
||||
modelDiscountFactors: platformModelDiscountFactors(platform, baseModels, currentModels),
|
||||
modelNameMappings: platformModelNameMappings(platform, baseModels, currentModels),
|
||||
@@ -1210,6 +1221,11 @@ function platformToForm(
|
||||
};
|
||||
}
|
||||
|
||||
function readImageEditRequestFormat(config: Record<string, unknown>): PlatformWizardForm['imageEditRequestFormat'] {
|
||||
const value = String(config.imageEditRequestFormat ?? '').trim().toLowerCase().replaceAll('-', '_').replaceAll(' ', '_');
|
||||
return value === 'json' || value === 'json_url' ? 'json_url' : 'multipart';
|
||||
}
|
||||
|
||||
function defaultSelectedModelIds(models: BaseModelCatalogItem[], provider: string) {
|
||||
return modelsForProvider(models, provider).map((model) => model.id);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,14 @@ function selectedForm() {
|
||||
}
|
||||
|
||||
describe('platform model rate limit payload', () => {
|
||||
it('uses multipart unless JSON URL image edits are explicitly configured', () => {
|
||||
const defaultConfig = platformPayload(selectedForm()).config ?? {};
|
||||
expect(defaultConfig.imageEditRequestFormat).toBeUndefined();
|
||||
|
||||
const jsonConfig = platformPayload({ ...selectedForm(), imageEditRequestFormat: 'json_url' }).config ?? {};
|
||||
expect(jsonConfig.imageEditRequestFormat).toBe('json_url');
|
||||
});
|
||||
|
||||
it('preserves an existing model policy when the edit form was not touched', () => {
|
||||
const [payload] = platformModelPayloads([baseModel], selectedForm());
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ export interface PlatformWizardForm {
|
||||
httpProxy: string;
|
||||
supportBase64Input: boolean;
|
||||
supportUrlInput: boolean;
|
||||
imageEditRequestFormat: 'multipart' | 'json_url';
|
||||
modelDiscountFactor: string;
|
||||
modelDiscountFactors: Record<string, string>;
|
||||
modelNameMappings: Record<string, string>;
|
||||
@@ -109,6 +110,7 @@ export function createEmptyPlatformForm(provider = '', defaults?: ProviderConnec
|
||||
httpProxy: '',
|
||||
supportBase64Input: true,
|
||||
supportUrlInput: true,
|
||||
imageEditRequestFormat: 'multipart',
|
||||
modelDiscountFactor: '',
|
||||
modelDiscountFactors: {},
|
||||
modelNameMappings: {},
|
||||
@@ -171,6 +173,7 @@ export function platformPayload(form: PlatformWizardForm, options: { preserveEmp
|
||||
networkProxy: networkProxyPayload(form),
|
||||
supportBase64Input: form.supportBase64Input,
|
||||
supportUrlInput: form.supportUrlInput,
|
||||
...(form.imageEditRequestFormat === 'json_url' ? { imageEditRequestFormat: 'json_url' } : {}),
|
||||
source: 'gateway-admin',
|
||||
},
|
||||
retryPolicy: {
|
||||
|
||||
Reference in New Issue
Block a user