[codex] expose more payload-rule upstream types (#474)

* Expose more payload-rule upstream types in Settings

The first payload-rules UI only offered a narrow set of protocol labels, which
made live troubleshooting confusing once real playground traffic routed through
platforms like sub2api instead of codex. This expands the selectable upstream
types, extracts the option list into one small helper, and renames the field to
上游类型 so the UI matches what the runtime matcher actually uses.

Constraint: Must preserve the existing payload-rules schema key (`protocol`) even though the UI wording is now upstream-type oriented
Rejected: Leaving the dropdown codex/openai-only and telling operators to hand-edit JSON | too easy to misconfigure during live routing diagnosis
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If new canonical site platforms are added, update payloadRuleProtocolOptions.ts so the visual editor stays aligned with runtime matching
Tested: npx vitest run --root . src/web/pages/settings.payload-rules.test.tsx src/web/pages/settings.payload-rule-platform-options.test.ts
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual dropdown interaction in a browser

* Keep payload-rule upstream types aligned with one-api backend support

Code review caught that the visual editor still omitted one-api even though the
backend continues to treat it as a valid upstream platform. This adds the
missing option and extends the focused option-set test so operators can create
payload rules for one-api without dropping to raw JSON.

Constraint: Must preserve the runtime payload-rules schema and only close the UI/backend option gap
Rejected: Removing one-api from the backend in this PR | unrelated behavioral change and broader migration risk
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: When backend platform support changes, update payloadRuleProtocolOptions.ts and its focused test in the same PR
Tested: npx vitest run --root . src/web/pages/settings.payload-rules.test.tsx src/web/pages/settings.payload-rule-platform-options.test.ts
Tested: npm run typecheck:web
Tested: npm run typecheck:web:test
Tested: npm run repo:drift-check
Not-tested: Manual browser check of the expanded dropdown list
This commit is contained in:
Cita
2026-04-10 16:13:56 +08:00
committed by GitHub
parent 9c766dec1c
commit a2c2ae614a
3 changed files with 46 additions and 11 deletions
+3 -11
View File
@@ -8,6 +8,7 @@ import ModernSelect from '../components/ModernSelect.js';
import ResponsiveFormGrid from '../components/ResponsiveFormGrid.js'; import ResponsiveFormGrid from '../components/ResponsiveFormGrid.js';
import FactoryResetModal from './settings/FactoryResetModal.js'; import FactoryResetModal from './settings/FactoryResetModal.js';
import ModelAvailabilityProbeConfirmModal from './settings/ModelAvailabilityProbeConfirmModal.js'; import ModelAvailabilityProbeConfirmModal from './settings/ModelAvailabilityProbeConfirmModal.js';
import { PAYLOAD_RULE_PROTOCOL_OPTIONS } from './settings/payloadRuleProtocolOptions.js';
import { import {
createCodexDefaultHighReasoningVisualPreset, createCodexDefaultHighReasoningVisualPreset,
createVisualPayloadRule, createVisualPayloadRule,
@@ -209,15 +210,6 @@ const PAYLOAD_RULE_ACTION_OPTIONS: Array<{ value: PayloadRuleAction; label: stri
{ value: 'filter', label: '删除字段' }, { value: 'filter', label: '删除字段' },
]; ];
const PAYLOAD_RULE_PROTOCOL_OPTIONS = [
{ value: '', label: '全部协议' },
{ value: 'codex', label: 'Codex' },
{ value: 'openai', label: 'OpenAI' },
{ value: 'claude', label: 'Claude' },
{ value: 'gemini', label: 'Gemini' },
{ value: 'antigravity', label: 'Antigravity' },
];
const PAYLOAD_RULE_VALUE_MODE_OPTIONS: Array<{ value: VisualPayloadRuleValueMode; label: string }> = [ const PAYLOAD_RULE_VALUE_MODE_OPTIONS: Array<{ value: VisualPayloadRuleValueMode; label: string }> = [
{ value: 'text', label: '文本' }, { value: 'text', label: '文本' },
{ value: 'json', label: 'JSON' }, { value: 'json', label: 'JSON' },
@@ -1637,14 +1629,14 @@ export default function Settings() {
/> />
</div> </div>
<div> <div>
<div style={{ fontSize: 12, color: 'var(--color-text-muted)', marginBottom: 6 }}>协议</div> <div style={{ fontSize: 12, color: 'var(--color-text-muted)', marginBottom: 6 }}>上游类型</div>
<ModernSelect <ModernSelect
size="sm" size="sm"
data-testid={`payload-rule-protocol-${index + 1}`} data-testid={`payload-rule-protocol-${index + 1}`}
value={rule.protocol} value={rule.protocol}
onChange={(value) => updatePayloadVisualRule(rule.id, { protocol: String(value || '') })} onChange={(value) => updatePayloadVisualRule(rule.id, { protocol: String(value || '') })}
options={PAYLOAD_RULE_PROTOCOL_OPTIONS} options={PAYLOAD_RULE_PROTOCOL_OPTIONS}
placeholder="全部协议" placeholder="全部上游类型"
/> />
</div> </div>
<div> <div>
@@ -0,0 +1,26 @@
import { describe, expect, it } from 'vitest';
import { PAYLOAD_RULE_PROTOCOL_OPTIONS } from './settings/payloadRuleProtocolOptions.js';
describe('payload rule platform options', () => {
it('includes non-codex upstream platforms that payload rules can match in production routing', () => {
const values = PAYLOAD_RULE_PROTOCOL_OPTIONS.map((option) => option.value);
expect(values).toEqual(expect.arrayContaining([
'',
'codex',
'sub2api',
'new-api',
'one-api',
'cliproxyapi',
'openai',
'claude',
'gemini',
'gemini-cli',
'antigravity',
'anyrouter',
'done-hub',
'one-hub',
'veloera',
]));
});
});
@@ -0,0 +1,17 @@
export const PAYLOAD_RULE_PROTOCOL_OPTIONS: Array<{ value: string; label: string }> = [
{ value: '', label: '全部平台' },
{ value: 'codex', label: 'Codex' },
{ value: 'sub2api', label: 'Sub2API' },
{ value: 'new-api', label: 'New API' },
{ value: 'one-api', label: 'One API' },
{ value: 'cliproxyapi', label: 'CLIProxyAPI' },
{ value: 'openai', label: 'OpenAI' },
{ value: 'claude', label: 'Claude' },
{ value: 'gemini', label: 'Gemini' },
{ value: 'gemini-cli', label: 'Gemini CLI' },
{ value: 'antigravity', label: 'Antigravity' },
{ value: 'anyrouter', label: 'AnyRouter' },
{ value: 'done-hub', label: 'Done Hub' },
{ value: 'one-hub', label: 'One Hub' },
{ value: 'veloera', label: 'Veloera' },
];