mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
Compare commits
3 Commits
@@ -888,6 +888,13 @@ export function VisualConfigEditor({
|
||||
}
|
||||
/>
|
||||
</FieldShell>
|
||||
<Input
|
||||
label={t('config_management.visual.sections.network.session_affinity_ttl')}
|
||||
placeholder="1h"
|
||||
value={values.routingSessionAffinityTTL}
|
||||
onChange={(e) => onChange({ routingSessionAffinityTTL: e.target.value })}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</SectionGrid>
|
||||
|
||||
<SectionGrid>
|
||||
@@ -900,6 +907,12 @@ export function VisualConfigEditor({
|
||||
disabled={disabled}
|
||||
onChange={(forceModelPrefix) => onChange({ forceModelPrefix })}
|
||||
/>
|
||||
<ToggleRow
|
||||
title={t('config_management.visual.sections.network.session_affinity')}
|
||||
checked={values.routingSessionAffinity}
|
||||
disabled={disabled}
|
||||
onChange={(routingSessionAffinity) => onChange({ routingSessionAffinity })}
|
||||
/>
|
||||
<ToggleRow
|
||||
title={t('config_management.visual.sections.network.ws_auth')}
|
||||
description={t('config_management.visual.sections.network.ws_auth_desc')}
|
||||
|
||||
@@ -974,6 +974,13 @@ const resolveClaudePlanType = (profile: ClaudeProfileResponse | null): string |
|
||||
const hasClaudePro = normalizeFlagValue(profile.account?.has_claude_pro);
|
||||
if (hasClaudePro) return 'plan_pro';
|
||||
|
||||
const organizationType = normalizeStringValue(profile.organization?.organization_type)?.toLowerCase();
|
||||
const subscriptionStatus = normalizeStringValue(profile.organization?.subscription_status)?.toLowerCase();
|
||||
|
||||
if (organizationType === 'claude_team' && subscriptionStatus === 'active') {
|
||||
return 'plan_team';
|
||||
}
|
||||
|
||||
if (hasClaudeMax === false && hasClaudePro === false) return 'plan_free';
|
||||
|
||||
return null;
|
||||
|
||||
@@ -656,6 +656,18 @@ function getNextDirtyFields(
|
||||
if (Object.prototype.hasOwnProperty.call(patch, 'routingStrategy')) {
|
||||
updateDirty('routingStrategy', nextValues.routingStrategy === baselineValues.routingStrategy);
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(patch, 'routingSessionAffinity')) {
|
||||
updateDirty(
|
||||
'routingSessionAffinity',
|
||||
nextValues.routingSessionAffinity === baselineValues.routingSessionAffinity
|
||||
);
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(patch, 'routingSessionAffinityTTL')) {
|
||||
updateDirty(
|
||||
'routingSessionAffinityTTL',
|
||||
nextValues.routingSessionAffinityTTL === baselineValues.routingSessionAffinityTTL
|
||||
);
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(patch, 'payloadDefaultRules')) {
|
||||
updateDirty(
|
||||
'payloadDefaultRules',
|
||||
@@ -836,6 +848,19 @@ export function useVisualConfig() {
|
||||
quotaAntigravityCredits: Boolean(quotaExceeded?.['antigravity-credits'] ?? true),
|
||||
|
||||
routingStrategy: routing?.strategy === 'fill-first' ? 'fill-first' : 'round-robin',
|
||||
routingSessionAffinity: Boolean(
|
||||
routing?.['session-affinity'] ??
|
||||
routing?.sessionAffinity ??
|
||||
routing?.['sessionAffinity']
|
||||
),
|
||||
routingSessionAffinityTTL:
|
||||
typeof routing?.['session-affinity-ttl'] === 'string'
|
||||
? routing['session-affinity-ttl']
|
||||
: typeof routing?.sessionAffinityTTL === 'string'
|
||||
? routing.sessionAffinityTTL
|
||||
: typeof routing?.['sessionAffinityTTL'] === 'string'
|
||||
? routing['sessionAffinityTTL']
|
||||
: '',
|
||||
|
||||
payloadDefaultRules: parsePayloadRules(payload?.default),
|
||||
payloadDefaultRawRules: parseRawPayloadRules(payload?.['default-raw']),
|
||||
@@ -949,9 +974,20 @@ export function useVisualConfig() {
|
||||
deleteIfMapEmpty(doc, ['quota-exceeded']);
|
||||
}
|
||||
|
||||
if (docHas(doc, ['routing']) || values.routingStrategy !== 'round-robin') {
|
||||
if (
|
||||
docHas(doc, ['routing']) ||
|
||||
values.routingStrategy !== 'round-robin' ||
|
||||
values.routingSessionAffinity ||
|
||||
values.routingSessionAffinityTTL.trim()
|
||||
) {
|
||||
ensureMapInDoc(doc, ['routing']);
|
||||
doc.setIn(['routing', 'strategy'], values.routingStrategy);
|
||||
setBooleanInDoc(doc, ['routing', 'session-affinity'], values.routingSessionAffinity);
|
||||
setStringInDoc(
|
||||
doc,
|
||||
['routing', 'session-affinity-ttl'],
|
||||
values.routingSessionAffinityTTL
|
||||
);
|
||||
deleteIfMapEmpty(doc, ['routing']);
|
||||
}
|
||||
|
||||
|
||||
@@ -645,7 +645,8 @@
|
||||
"plan_pro": "Pro",
|
||||
"plan_max": "Max",
|
||||
"plan_max5": "Max 5x",
|
||||
"plan_max20": "Max 20x"
|
||||
"plan_max20": "Max 20x",
|
||||
"plan_team": "Team"
|
||||
},
|
||||
"codex_quota": {
|
||||
"title": "Codex Quota",
|
||||
@@ -1231,8 +1232,10 @@
|
||||
"routing_strategy_hint": "Select credential selection strategy",
|
||||
"strategy_round_robin": "Round Robin",
|
||||
"strategy_fill_first": "Fill First",
|
||||
"session_affinity_ttl": "Session Affinity TTL",
|
||||
"force_model_prefix": "Force Model Prefix",
|
||||
"force_model_prefix_desc": "Unprefixed model requests only use credentials without prefix",
|
||||
"session_affinity": "Session Affinity Routing",
|
||||
"ws_auth": "WebSocket Authentication",
|
||||
"ws_auth_desc": "Enable WebSocket authentication (/v1/ws)"
|
||||
},
|
||||
|
||||
@@ -642,7 +642,8 @@
|
||||
"plan_pro": "Pro",
|
||||
"plan_max": "Max",
|
||||
"plan_max5": "Max 5x",
|
||||
"plan_max20": "Max 20x"
|
||||
"plan_max20": "Max 20x",
|
||||
"plan_team": "Team"
|
||||
},
|
||||
"codex_quota": {
|
||||
"title": "Квота Codex",
|
||||
@@ -1230,8 +1231,10 @@
|
||||
"routing_strategy_hint": "Выберите стратегию подбора учётных данных",
|
||||
"strategy_round_robin": "По кругу",
|
||||
"strategy_fill_first": "Сначала заполнить",
|
||||
"session_affinity_ttl": "TTL привязки сессии",
|
||||
"force_model_prefix": "Принудительный префикс модели",
|
||||
"force_model_prefix_desc": "Запросы к моделям без префикса используют только учётные данные без префикса",
|
||||
"session_affinity": "Маршрутизация с привязкой к сессии",
|
||||
"ws_auth": "Аутентификация WebSocket",
|
||||
"ws_auth_desc": "Включить аутентификацию WebSocket (/v1/ws)"
|
||||
},
|
||||
|
||||
@@ -645,7 +645,8 @@
|
||||
"plan_pro": "专业版",
|
||||
"plan_max": "Max",
|
||||
"plan_max5": "Max 5x",
|
||||
"plan_max20": "Max 20x"
|
||||
"plan_max20": "Max 20x",
|
||||
"plan_team": "团队版"
|
||||
},
|
||||
"codex_quota": {
|
||||
"title": "Codex 额度",
|
||||
@@ -1231,8 +1232,10 @@
|
||||
"routing_strategy_hint": "选择凭据选择策略",
|
||||
"strategy_round_robin": "轮询 (Round Robin)",
|
||||
"strategy_fill_first": "填充优先 (Fill First)",
|
||||
"session_affinity_ttl": "会话粘性 TTL",
|
||||
"force_model_prefix": "强制模型前缀",
|
||||
"force_model_prefix_desc": "未带前缀的模型请求只使用无前缀凭据",
|
||||
"session_affinity": "会话粘性路由",
|
||||
"ws_auth": "WebSocket 认证",
|
||||
"ws_auth_desc": "启用 WebSocket 连接认证 (/v1/ws)"
|
||||
},
|
||||
|
||||
@@ -645,7 +645,8 @@
|
||||
"plan_pro": "專業版",
|
||||
"plan_max": "Max",
|
||||
"plan_max5": "Max 5x",
|
||||
"plan_max20": "Max 20x"
|
||||
"plan_max20": "Max 20x",
|
||||
"plan_team": "團隊版"
|
||||
},
|
||||
"codex_quota": {
|
||||
"title": "Codex 配額",
|
||||
@@ -1259,8 +1260,10 @@
|
||||
"routing_strategy_hint": "選擇憑證選擇策略",
|
||||
"strategy_round_robin": "輪詢(Round Robin)",
|
||||
"strategy_fill_first": "填充優先(Fill First)",
|
||||
"session_affinity_ttl": "會話黏性 TTL",
|
||||
"force_model_prefix": "強制模型前綴",
|
||||
"force_model_prefix_desc": "未帶前綴的模型請求只使用無前綴憑證",
|
||||
"session_affinity": "會話黏性路由",
|
||||
"ws_auth": "WebSocket 驗證",
|
||||
"ws_auth_desc": "啟用 WebSocket 連線驗證(/v1/ws)"
|
||||
},
|
||||
|
||||
@@ -77,6 +77,8 @@ export type VisualConfigValues = {
|
||||
quotaSwitchPreviewModel: boolean;
|
||||
quotaAntigravityCredits: boolean;
|
||||
routingStrategy: 'round-robin' | 'fill-first';
|
||||
routingSessionAffinity: boolean;
|
||||
routingSessionAffinityTTL: string;
|
||||
wsAuth: boolean;
|
||||
payloadDefaultRules: PayloadRule[];
|
||||
payloadDefaultRawRules: PayloadRule[];
|
||||
@@ -117,6 +119,8 @@ export const DEFAULT_VISUAL_VALUES: VisualConfigValues = {
|
||||
quotaSwitchPreviewModel: true,
|
||||
quotaAntigravityCredits: true,
|
||||
routingStrategy: 'round-robin',
|
||||
routingSessionAffinity: false,
|
||||
routingSessionAffinityTTL: '',
|
||||
wsAuth: false,
|
||||
payloadDefaultRules: [],
|
||||
payloadDefaultRawRules: [],
|
||||
|
||||
Reference in New Issue
Block a user