diff --git a/src/web/pages/Settings.tsx b/src/web/pages/Settings.tsx
index 17ebc6d..1043685 100644
--- a/src/web/pages/Settings.tsx
+++ b/src/web/pages/Settings.tsx
@@ -8,6 +8,7 @@ import ModernSelect from '../components/ModernSelect.js';
import ResponsiveFormGrid from '../components/ResponsiveFormGrid.js';
import FactoryResetModal from './settings/FactoryResetModal.js';
import ModelAvailabilityProbeConfirmModal from './settings/ModelAvailabilityProbeConfirmModal.js';
+import { PAYLOAD_RULE_PROTOCOL_OPTIONS } from './settings/payloadRuleProtocolOptions.js';
import {
createCodexDefaultHighReasoningVisualPreset,
createVisualPayloadRule,
@@ -209,15 +210,6 @@ const PAYLOAD_RULE_ACTION_OPTIONS: Array<{ value: PayloadRuleAction; label: stri
{ 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 }> = [
{ value: 'text', label: '文本' },
{ value: 'json', label: 'JSON' },
@@ -1637,14 +1629,14 @@ export default function Settings() {
/>
-
协议
+
上游类型
updatePayloadVisualRule(rule.id, { protocol: String(value || '') })}
options={PAYLOAD_RULE_PROTOCOL_OPTIONS}
- placeholder="全部协议"
+ placeholder="全部上游类型"
/>
diff --git a/src/web/pages/settings.payload-rule-platform-options.test.ts b/src/web/pages/settings.payload-rule-platform-options.test.ts
new file mode 100644
index 0000000..ff05058
--- /dev/null
+++ b/src/web/pages/settings.payload-rule-platform-options.test.ts
@@ -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',
+ ]));
+ });
+});
diff --git a/src/web/pages/settings/payloadRuleProtocolOptions.ts b/src/web/pages/settings/payloadRuleProtocolOptions.ts
new file mode 100644
index 0000000..bdb195f
--- /dev/null
+++ b/src/web/pages/settings/payloadRuleProtocolOptions.ts
@@ -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' },
+];