From 25bd04e400db32e8c7f4254ecbc1eb93bbda9ce1 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Sun, 12 Apr 2026 18:43:19 -0300 Subject: [PATCH] feat(settings): unify routing rules and model aliases controls Move model routing management into Settings and add a unified model alias editor for exact and wildcard remaps. Sync combo defaults with global routing strategy settings, add localized combo onboarding copy, and expand routing i18n across supported locales. Also fix supporting routing behavior by accepting all strategy values in settings schemas, preserving connection ids in combo tests, honoring non-stream JSON requests for CC-compatible providers, and handling hashed external package subpaths. --- .vscode/settings.json | 3 +- next.config.mjs | 14 +- open-sse/executors/base.ts | 4 +- open-sse/executors/default.ts | 2 +- open-sse/handlers/chatCore.ts | 5 +- open-sse/services/combo.ts | 29 +- src/app/(dashboard)/dashboard/combos/page.tsx | 99 +++-- .../settings/components/ComboDefaultsTab.tsx | 142 ++++++- .../components/ModelAliasesUnified.tsx | 366 ++++++++++++++++++ .../settings/components/RoutingTab.tsx | 190 +-------- .../(dashboard)/dashboard/settings/page.tsx | 6 +- src/app/api/combos/test/route.ts | 1 + src/app/api/openapi/spec/route.ts | 7 +- src/i18n/messages/ar.json | 41 +- src/i18n/messages/bg.json | 41 +- src/i18n/messages/cs.json | 41 +- src/i18n/messages/da.json | 41 +- src/i18n/messages/de.json | 41 +- src/i18n/messages/en.json | 39 +- src/i18n/messages/es.json | 41 +- src/i18n/messages/fi.json | 41 +- src/i18n/messages/fr.json | 41 +- src/i18n/messages/he.json | 41 +- src/i18n/messages/hi.json | 41 +- src/i18n/messages/hu.json | 41 +- src/i18n/messages/id.json | 41 +- src/i18n/messages/it.json | 41 +- src/i18n/messages/ja.json | 41 +- src/i18n/messages/ko.json | 41 +- src/i18n/messages/ms.json | 41 +- src/i18n/messages/nl.json | 41 +- src/i18n/messages/no.json | 41 +- src/i18n/messages/phi.json | 41 +- src/i18n/messages/pl.json | 41 +- src/i18n/messages/pt-BR.json | 39 +- src/i18n/messages/pt.json | 41 +- src/i18n/messages/ro.json | 41 +- src/i18n/messages/ru.json | 41 +- src/i18n/messages/sk.json | 41 +- src/i18n/messages/sv.json | 41 +- src/i18n/messages/th.json | 41 +- src/i18n/messages/tr.json | 41 +- src/i18n/messages/uk-UA.json | 41 +- src/i18n/messages/vi.json | 41 +- src/i18n/messages/zh-CN.json | 39 +- src/shared/components/ModelRoutingSection.tsx | 69 ++-- src/shared/utils/machineId.ts | 11 +- src/shared/utils/maskEmail.ts | 25 +- src/shared/validation/schemas.ts | 28 +- src/shared/validation/settingsSchemas.ts | 20 +- src/sse/handlers/chat.ts | 26 +- tests/e2e/combo-unification.spec.ts | 6 +- tests/unit/cc-compatible-provider.test.mjs | 6 +- .../unit/chatcore-translation-paths.test.mjs | 4 +- tests/unit/combo-circuit-breaker.test.mjs | 87 +++-- tests/unit/combo-context-relay.test.mjs | 20 +- tests/unit/combo-test-route.test.mjs | 2 + tests/unit/executor-default-base.test.mjs | 8 + tests/unit/machine-id.test.mjs | 9 +- tests/unit/mask-email.test.mjs | 16 +- ...ettings-schema-routing-strategies.test.mjs | 17 + 61 files changed, 2036 insertions(+), 492 deletions(-) create mode 100644 src/app/(dashboard)/dashboard/settings/components/ModelAliasesUnified.tsx create mode 100644 tests/unit/settings-schema-routing-strategies.test.mjs diff --git a/.vscode/settings.json b/.vscode/settings.json index 8e3d0f161b..fae48f28c7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ "javascript:S3776": { "level": "off" } - } + }, + "git.ignoreLimitWarning": true } diff --git a/next.config.mjs b/next.config.mjs index a8589b8cc7..18a2be156d 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -67,10 +67,10 @@ const nextConfig = { // // We use two strategies: // 1. Exact-name externals for all known server-side packages. - // 2. Hash-strip catch-all: any require('-<16hexchars>' strips the - // suffix and falls through to the real package name. + // 2. Hash-strip catch-all: any require('-<16hexchars>[/subpath]') + // strips the hash suffix and falls through to the real package name. // - const HASH_PATTERN = /^(.+)-[0-9a-f]{16}$/; + const HASH_PATTERN = /^(.+)-[0-9a-f]{16}(\/.*)?$/; const KNOWN_EXTERNALS = new Set([ "better-sqlite3", @@ -102,13 +102,15 @@ const nextConfig = { if (KNOWN_EXTERNALS.has(request)) { return callback(null, `commonjs ${request}`); } - // Case 2: Hash-suffixed name — strip hash, use base name + // Case 2: Hash-suffixed name — strip hash, preserve subpath // e.g. "better-sqlite3-90e2652d1716b047" → "better-sqlite3" // "zod-dcb22c6336e0bc69" → "zod" + // "zod-dcb22c6336e0bc69/v3" → "zod/v3" + // "zod-dcb22c6336e0bc69/v4-mini" → "zod/v4-mini" const hashMatch = request?.match?.(HASH_PATTERN); if (hashMatch) { - const baseName = hashMatch[1]; - return callback(null, `commonjs ${baseName}`); + const resolved = hashMatch[2] ? `${hashMatch[1]}${hashMatch[2]}` : hashMatch[1]; + return callback(null, `commonjs ${resolved}`); } callback(); }, diff --git a/open-sse/executors/base.ts b/open-sse/executors/base.ts index f57e4010e0..58301632d3 100644 --- a/open-sse/executors/base.ts +++ b/open-sse/executors/base.ts @@ -206,9 +206,7 @@ export class BaseExecutor { headers["Authorization"] = `Bearer ${effectiveKey}`; } - if (stream) { - headers["Accept"] = "text/event-stream"; - } + headers["Accept"] = stream ? "text/event-stream" : "application/json"; return headers; } diff --git a/open-sse/executors/default.ts b/open-sse/executors/default.ts index aa55d1ffaf..15e2c0ff64 100644 --- a/open-sse/executors/default.ts +++ b/open-sse/executors/default.ts @@ -179,7 +179,7 @@ export class DefaultExecutor extends BaseExecutor { } } - if (stream) headers["Accept"] = "text/event-stream"; + headers["Accept"] = stream ? "text/event-stream" : "application/json"; // Qwen header cleanup: Remove X-Dashscope-* headers if using an API key (DashScope compatible mode). // If using OAuth (Qwen Code), we MUST keep them for portal.qwen.ai to accept the request. diff --git a/open-sse/handlers/chatCore.ts b/open-sse/handlers/chatCore.ts index cd73d3a122..4dcb362d1c 100644 --- a/open-sse/handlers/chatCore.ts +++ b/open-sse/handlers/chatCore.ts @@ -957,7 +957,10 @@ export async function handleChatCore({ let translatedBody = body; const isClaudePassthrough = sourceFormat === FORMATS.CLAUDE && targetFormat === FORMATS.CLAUDE; const isClaudeCodeCompatible = isClaudeCodeCompatibleProvider(provider); - const upstreamStream = stream || isClaudeCodeCompatible; + // Respect the client's explicit non-streaming intent for CC-compatible providers. + // Most upstreams can answer JSON directly; the SSE->JSON fallback remains as a + // compatibility path when an upstream still responds with event-stream. + const upstreamStream = stream; let ccSessionId: string | null = null; // Determine if we should preserve client-side cache_control headers diff --git a/open-sse/services/combo.ts b/open-sse/services/combo.ts index 83a60f567b..ad23e8ca2c 100644 --- a/open-sse/services/combo.ts +++ b/open-sse/services/combo.ts @@ -1730,22 +1730,21 @@ async function handleRoundRobinCombo({ }); recordedAttempts++; if (provider) { - import("../../src/lib/localDb") - .then(({ setLKGP }) => - Promise.all([ - setLKGP(combo.name, target.executionKey, provider), - setLKGP(combo.name, combo.id || combo.name, provider), - ]) - ) - .catch((err) => - log.warn( - "COMBO-RR", - "Failed to record Last Known Good Provider. This is non-fatal.", - { - err, - } - ) + try { + const { setLKGP } = await import("../../src/lib/localDb"); + await Promise.all([ + setLKGP(combo.name, target.executionKey, provider), + setLKGP(combo.name, combo.id || combo.name, provider), + ]); + } catch (err) { + log.warn( + "COMBO-RR", + "Failed to record Last Known Good Provider. This is non-fatal.", + { + err, + } ); + } } return result; } diff --git a/src/app/(dashboard)/dashboard/combos/page.tsx b/src/app/(dashboard)/dashboard/combos/page.tsx index a988deaa6a..9e46f4d163 100644 --- a/src/app/(dashboard)/dashboard/combos/page.tsx +++ b/src/app/(dashboard)/dashboard/combos/page.tsx @@ -45,20 +45,6 @@ const ModelSelectModal = dynamic(() => import("@/shared/components/ModelSelectMo const ProxyConfigModal = dynamic(() => import("@/shared/components/ProxyConfigModal"), { ssr: false, }); -const ModelRoutingSection = dynamic(() => import("@/shared/components/ModelRoutingSection"), { - ssr: false, - loading: () => ( -
-
- route -
-
-
-
-
-
- ), -}); // Validate combo name: letters, numbers, -, _, /, . const VALID_NAME_REGEX = /^[a-zA-Z0-9_/.-]+$/; @@ -883,6 +869,7 @@ export default function CombosPage() { setShowUsageGuide(false)} onHideForever={handleHideUsageGuideForever} + onCreateCombo={() => setShowCreateModal(true)} /> )} @@ -930,10 +917,6 @@ export default function CombosPage() {
)} - - {/* Model Routing Rules (#563) */} - -
{[ { @@ -1116,9 +1099,35 @@ export default function CombosPage() { ); } -function ComboUsageGuide({ onHide, onHideForever }) { +const COMBO_WIZARD_STEPS = [ + { + step: 1, + icon: "badge", + titleKey: "wizardStep1Title", + descKey: "wizardStep1Desc", + }, + { + step: 2, + icon: "hub", + titleKey: "wizardStep2Title", + descKey: "wizardStep2Desc", + }, + { + step: 3, + icon: "route", + titleKey: "wizardStep3Title", + descKey: "wizardStep3Desc", + }, + { + step: 4, + icon: "check_circle", + titleKey: "wizardStep4Title", + descKey: "wizardStep4Desc", + }, +]; + +function ComboUsageGuide({ onHide, onHideForever, onCreateCombo }) { const t = useTranslations("combos"); - const guideStrategies = ["priority", "cost-optimized", "least-used"]; return ( @@ -1130,8 +1139,16 @@ function ComboUsageGuide({ onHide, onHideForever }) {
-

{t("routingStrategy")}

-

{t("description")}

+

+ {getI18nOrFallback(t, "wizardGuideTitle", "Getting Started with Combos")} +

+

+ {getI18nOrFallback( + t, + "wizardGuideDesc", + "Create model combos to route AI traffic intelligently" + )} +

@@ -1149,27 +1166,45 @@ function ComboUsageGuide({ onHide, onHideForever }) {
-
- {guideStrategies.map((strategyValue) => { - const strategyMeta = getStrategyMeta(strategyValue); +
+ {COMBO_WIZARD_STEPS.map((step, index) => { return (
-
+
+ + {step.step} + - {strategyMeta.icon} + {step.icon} - {getStrategyLabel(t, strategyValue)}
-

- {getStrategyDescription(t, strategyValue)} +

+ {getI18nOrFallback(t, step.titleKey, step.titleKey)}

+

+ {getI18nOrFallback(t, step.descKey, step.descKey)} +

+ {index < COMBO_WIZARD_STEPS.length - 1 && ( + + arrow_forward + + )}
); })}
+ +
+ + + {getI18nOrFallback(t, "wizardGuideHint", "or click + Create Combo above")} + +
); } diff --git a/src/app/(dashboard)/dashboard/settings/components/ComboDefaultsTab.tsx b/src/app/(dashboard)/dashboard/settings/components/ComboDefaultsTab.tsx index 222b6820f6..afb37e2986 100644 --- a/src/app/(dashboard)/dashboard/settings/components/ComboDefaultsTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/ComboDefaultsTab.tsx @@ -31,10 +31,15 @@ export default function ComboDefaultsTab() { handoffThreshold: 0.85, handoffModel: "", maxMessagesForSummary: 30, + stickyRoundRobinLimit: 3, }); const [providerOverrides, setProviderOverrides] = useState({}); const [newOverrideProvider, setNewOverrideProvider] = useState(""); const [saving, setSaving] = useState(false); + const [status, setStatus] = useState<{ type: "success" | "error" | ""; message: string }>({ + type: "", + message: "", + }); const t = useTranslations("settings"); const tc = useTranslations("common"); const strategyOptions = ROUTING_STRATEGIES.map((strategy) => ({ @@ -54,27 +59,75 @@ export default function ComboDefaultsTab() { ]; useEffect(() => { - fetch("/api/settings/combo-defaults") - .then((res) => res.json()) - .then((data) => { - if (data.comboDefaults) { - setComboDefaults((prev) => ({ ...prev, ...data.comboDefaults })); - } - if (data.providerOverrides) setProviderOverrides(data.providerOverrides); + Promise.all([ + fetch("/api/settings/combo-defaults").then((res) => res.json()), + fetch("/api/settings").then((res) => res.json()), + ]) + .then(([comboData, settingsData]) => { + setComboDefaults((prev) => ({ + ...prev, + ...(comboData.comboDefaults || {}), + strategy: + settingsData.fallbackStrategy ?? comboData.comboDefaults?.strategy ?? prev.strategy, + stickyRoundRobinLimit: + settingsData.stickyRoundRobinLimit ?? + comboData.comboDefaults?.stickyRoundRobinLimit ?? + prev.stickyRoundRobinLimit, + })); + if (comboData.providerOverrides) setProviderOverrides(comboData.providerOverrides); }) .catch((err) => console.error("Failed to fetch combo defaults:", err)); }, []); + const showStatus = (type: "success" | "error", message: string) => { + setStatus({ type, message }); + setTimeout(() => setStatus({ type: "", message: "" }), 2500); + }; + + const syncGlobalRoutingSettings = async (patch: Record) => { + const keys = Object.keys(patch); + if (keys.length === 0) return true; + + const res = await fetch("/api/settings", { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(patch), + }); + + if (!res.ok) { + throw new Error("Failed to sync global routing settings"); + } + + return true; + }; + const saveComboDefaults = async () => { setSaving(true); try { - await fetch("/api/settings/combo-defaults", { + const { stickyRoundRobinLimit, ...comboDefaultsPayload } = comboDefaults; + const settingsPatch: Record = {}; + if (comboDefaults.strategy) { + settingsPatch.fallbackStrategy = comboDefaults.strategy; + } + if (comboDefaults.strategy === "round-robin" && stickyRoundRobinLimit !== undefined) { + settingsPatch.stickyRoundRobinLimit = stickyRoundRobinLimit; + } + + const comboDefaultsRes = await fetch("/api/settings/combo-defaults", { method: "PATCH", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ comboDefaults, providerOverrides }), + body: JSON.stringify({ comboDefaults: comboDefaultsPayload, providerOverrides }), }); + + if (!comboDefaultsRes.ok) { + throw new Error("Failed to save combo defaults"); + } + + await syncGlobalRoutingSettings(settingsPatch); + showStatus("success", t("savedSuccessfully")); } catch (err) { console.error("Failed to save combo defaults:", err); + showStatus("error", t("errorOccurred")); } finally { setSaving(false); } @@ -103,8 +156,38 @@ export default function ComboDefaultsTab() { tune
-

{t("comboDefaultsTitle")}

+

+ {translateOrFallback(t, "comboDefaultsTitle", "Default Routing & Combo Settings")} +

{t("globalComboConfig")} + {status.message && ( + + {status.message} + + )} +
+
+

+ {translateOrFallback(t, "routingAdvancedGuideTitle", "Advanced routing guidance")} +

+

+ {translateOrFallback( + t, + "routingAdvancedGuideHint1", + "Use Fill First for predictable priority, Round Robin for fairness, and P2C for latency resilience." + )} +

+

+ {translateOrFallback( + t, + "routingAdvancedGuideHint2", + "If providers vary in quality or cost, start with Cost Opt for background work and Least Used for balanced wear." + )} +

@@ -130,7 +213,15 @@ export default function ComboDefaultsTab() { key={s.value} role="tab" aria-selected={comboDefaults.strategy === s.value} - onClick={() => setComboDefaults((prev) => ({ ...prev, strategy: s.value }))} + onClick={async () => { + setComboDefaults((prev) => ({ ...prev, strategy: s.value })); + try { + await syncGlobalRoutingSettings({ fallbackStrategy: s.value }); + } catch (error) { + console.error("Failed to sync fallback strategy:", error); + showStatus("error", t("errorOccurred")); + } + }} className={cn( "px-2 py-1 rounded text-xs font-medium transition-all flex items-center justify-center gap-0.5", comboDefaults.strategy === s.value @@ -145,6 +236,35 @@ export default function ComboDefaultsTab() {

+ {comboDefaults.strategy === "round-robin" && ( +
+
+

{t("stickyLimit")}

+

{t("stickyLimitDesc")}

+
+ { + const nextLimit = parseInt(e.target.value) || 3; + setComboDefaults((prev) => ({ + ...prev, + stickyRoundRobinLimit: nextLimit, + })); + try { + await syncGlobalRoutingSettings({ stickyRoundRobinLimit: nextLimit }); + } catch (error) { + console.error("Failed to sync sticky round robin limit:", error); + showStatus("error", t("errorOccurred")); + } + }} + className="w-20 text-center" + /> +
+ )} + {/* Numeric settings */}
{numericSettings.map(({ key, label, min, max, step }) => ( diff --git a/src/app/(dashboard)/dashboard/settings/components/ModelAliasesUnified.tsx b/src/app/(dashboard)/dashboard/settings/components/ModelAliasesUnified.tsx new file mode 100644 index 0000000000..f7e7ae265c --- /dev/null +++ b/src/app/(dashboard)/dashboard/settings/components/ModelAliasesUnified.tsx @@ -0,0 +1,366 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { Button, Card, Input } from "@/shared/components"; +import { useTranslations } from "next-intl"; + +interface WildcardAlias { + pattern: string; + target: string; +} + +type AliasMode = "exact" | "wildcard"; + +function translateOrFallback( + t: ReturnType, + key: string, + fallback: string +): string { + return typeof t.has === "function" && t.has(key) ? t(key) : fallback; +} + +export default function ModelAliasesUnified() { + const [wildcardAliases, setWildcardAliases] = useState([]); + const [builtInAliases, setBuiltInAliases] = useState>({}); + const [customAliases, setCustomAliases] = useState>({}); + const [aliasMode, setAliasMode] = useState("exact"); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [status, setStatus] = useState<{ type: "success" | "error" | ""; message: string }>({ + type: "", + message: "", + }); + const [fromValue, setFromValue] = useState(""); + const [toValue, setToValue] = useState(""); + const t = useTranslations("settings"); + const builtInEntries = Object.entries(builtInAliases); + const customEntries = Object.entries(customAliases); + + useEffect(() => { + const loadAliases = async () => { + try { + const [settingsRes, aliasesRes] = await Promise.all([ + fetch("/api/settings"), + fetch("/api/settings/model-aliases"), + ]); + const settingsData = settingsRes.ok ? await settingsRes.json() : {}; + const aliasesData = aliasesRes.ok ? await aliasesRes.json() : {}; + setWildcardAliases(settingsData.wildcardAliases || []); + setBuiltInAliases(aliasesData.builtIn || {}); + setCustomAliases(aliasesData.custom || {}); + } catch (error) { + console.error("Failed to load model aliases:", error); + } finally { + setLoading(false); + } + }; + + loadAliases(); + }, []); + + const showStatus = (type: "success" | "error", message: string) => { + setStatus({ type, message }); + setTimeout(() => setStatus({ type: "", message: "" }), 2500); + }; + + const addExactAlias = async () => { + if (!fromValue.trim() || !toValue.trim()) return; + setSaving(true); + try { + const res = await fetch("/api/settings/model-aliases", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ from: fromValue.trim(), to: toValue.trim() }), + }); + if (!res.ok) throw new Error("Failed to save exact alias"); + const data = await res.json(); + setCustomAliases(data.custom || {}); + setFromValue(""); + setToValue(""); + showStatus("success", translateOrFallback(t, "saved", "Saved")); + } catch (error) { + console.error("Failed to save exact alias:", error); + showStatus("error", translateOrFallback(t, "errorOccurred", "An error occurred")); + } finally { + setSaving(false); + } + }; + + const removeExactAlias = async (from: string) => { + setSaving(true); + try { + const res = await fetch("/api/settings/model-aliases", { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ from }), + }); + if (!res.ok) throw new Error("Failed to remove exact alias"); + const data = await res.json(); + setCustomAliases(data.custom || {}); + showStatus("success", translateOrFallback(t, "saved", "Saved")); + } catch (error) { + console.error("Failed to remove exact alias:", error); + showStatus("error", translateOrFallback(t, "errorOccurred", "An error occurred")); + } finally { + setSaving(false); + } + }; + + const addWildcardAlias = async () => { + if (!fromValue.trim() || !toValue.trim()) return; + setSaving(true); + try { + const updated = [...wildcardAliases, { pattern: fromValue.trim(), target: toValue.trim() }]; + const res = await fetch("/api/settings", { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ wildcardAliases: updated }), + }); + if (!res.ok) throw new Error("Failed to save wildcard alias"); + setWildcardAliases(updated); + setFromValue(""); + setToValue(""); + showStatus("success", translateOrFallback(t, "saved", "Saved")); + } catch (error) { + console.error("Failed to save wildcard alias:", error); + showStatus("error", translateOrFallback(t, "errorOccurred", "An error occurred")); + } finally { + setSaving(false); + } + }; + + const removeWildcardAlias = async (index: number) => { + setSaving(true); + try { + const updated = wildcardAliases.filter((_, currentIndex) => currentIndex !== index); + const res = await fetch("/api/settings", { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ wildcardAliases: updated }), + }); + if (!res.ok) throw new Error("Failed to remove wildcard alias"); + setWildcardAliases(updated); + showStatus("success", translateOrFallback(t, "saved", "Saved")); + } catch (error) { + console.error("Failed to remove wildcard alias:", error); + showStatus("error", translateOrFallback(t, "errorOccurred", "An error occurred")); + } finally { + setSaving(false); + } + }; + + const handleAdd = async () => { + if (aliasMode === "wildcard") { + await addWildcardAlias(); + return; + } + await addExactAlias(); + }; + + return ( + +
+
+ +
+
+

+ {translateOrFallback(t, "modelAliasesTitle", "Model Aliases")} +

+

+ {translateOrFallback( + t, + "modelAliasesDesc", + "Remap model names using exact matches or wildcard patterns." + )} +

+
+ {status.message && ( + + + {status.message} + + )} +
+ +
+
+ {[ + { + value: "exact", + label: translateOrFallback(t, "exactMatchMode", "Exact Match"), + }, + { + value: "wildcard", + label: translateOrFallback(t, "wildcardPatternMode", "Wildcard Pattern"), + }, + ].map((mode) => ( + + ))} +
+ +

+ {aliasMode === "exact" + ? translateOrFallback( + t, + "exactMatchModeDesc", + "Use exact aliases for deprecated or renamed model IDs." + ) + : translateOrFallback( + t, + "wildcardPatternModeDesc", + "Use wildcard aliases with * and ? when a family of models should map to one target." + )} +

+ +
+ setFromValue(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && void handleAdd()} + disabled={loading || saving} + /> +
+ +
+ setToValue(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && void handleAdd()} + disabled={loading || saving} + /> + +
+
+ +
+

+ {translateOrFallback(t, "customAliases", "Custom Aliases")} +

+
+ {customEntries.length === 0 ? ( +
+ {translateOrFallback( + t, + "noExactAliasesConfigured", + "No exact-match aliases configured." + )} +
+ ) : ( + customEntries.map(([from, to]) => ( +
+ {from} + + arrow_forward + + {to} + +
+ )) + )} +
+
+ +
+

+ {translateOrFallback(t, "wildcardRulesTitle", "Wildcard Rules")} +

+
+ {wildcardAliases.length === 0 ? ( +
+ {translateOrFallback( + t, + "noWildcardAliasesConfigured", + "No wildcard aliases configured." + )} +
+ ) : ( + wildcardAliases.map((alias, index) => ( +
+ {alias.pattern} + + arrow_forward + + {alias.target} + +
+ )) + )} +
+
+ +
+ + + chevron_right + + {translateOrFallback(t, "builtInAliases", "Built-in Aliases")} ({builtInEntries.length}) + +
+ {builtInEntries.map(([from, to]) => ( +
+ {from} + + arrow_forward + + {to} + lock +
+ ))} +
+
+
+ ); +} diff --git a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx index 8b5cadaf3b..869d54603f 100644 --- a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx @@ -1,46 +1,24 @@ "use client"; -import { useState, useEffect } from "react"; -import { Card, Input, Button } from "@/shared/components"; -import FallbackChainsEditor from "./FallbackChainsEditor"; -import { - ROUTING_STRATEGIES, - SETTINGS_FALLBACK_STRATEGY_VALUES, -} from "@/shared/constants/routingStrategies"; +import { useEffect, useState } from "react"; +import { Button, Card } from "@/shared/components"; import { useTranslations } from "next-intl"; - -const STRATEGIES = ROUTING_STRATEGIES.filter((strategy) => - SETTINGS_FALLBACK_STRATEGY_VALUES.includes(strategy.value) -).map((strategy) => ({ - value: strategy.value, - labelKey: strategy.labelKey, - descKey: strategy.settingsDescKey, - icon: strategy.icon, -})); +import FallbackChainsEditor from "./FallbackChainsEditor"; export default function RoutingTab() { const [settings, setSettings] = useState({ - fallbackStrategy: "fill-first", alwaysPreserveClientCache: "auto", }); const [loading, setLoading] = useState(true); - const [aliases, setAliases] = useState([]); const [lkgpCacheLoading, setLkgpCacheLoading] = useState(false); const [lkgpCacheStatus, setLkgpCacheStatus] = useState({ type: "", message: "" }); - const [newPattern, setNewPattern] = useState(""); - const [newTarget, setNewTarget] = useState(""); const t = useTranslations("settings"); - const strategyHintKeyByValue = STRATEGIES.reduce>((acc, strategy) => { - acc[strategy.value] = strategy.descKey; - return acc; - }, {}); useEffect(() => { fetch("/api/settings") .then((res) => res.json()) .then((data) => { setSettings(data); - setAliases(data.wildcardAliases || []); setLoading(false); }) .catch(() => setLoading(false)); @@ -61,100 +39,8 @@ export default function RoutingTab() { } }; - const addAlias = async () => { - if (!newPattern.trim() || !newTarget.trim()) return; - const updated = [...aliases, { pattern: newPattern.trim(), target: newTarget.trim() }]; - await updateSetting({ wildcardAliases: updated }); - setAliases(updated); - setNewPattern(""); - setNewTarget(""); - }; - - const removeAlias = async (idx) => { - const updated = aliases.filter((_, i) => i !== idx); - await updateSetting({ wildcardAliases: updated }); - setAliases(updated); - }; - return (
- {/* Strategy Selection */} - -
-
- -
-

{t("routingStrategy")}

-
- -
-

- {t("routingAdvancedGuideTitle")} -

-

{t("routingAdvancedGuideHint1")}

-

{t("routingAdvancedGuideHint2")}

-
- -
- {STRATEGIES.map((s) => ( - - ))} -
- - {settings.fallbackStrategy === "round-robin" && ( -
-
-

{t("stickyLimit")}

-

{t("stickyLimitDesc")}

-
- updateSetting({ stickyRoundRobinLimit: parseInt(e.target.value) })} - disabled={loading} - className="w-20 text-center" - /> -
- )} - -

- {t(strategyHintKeyByValue[settings.fallbackStrategy] || "fillFirstDesc")} -

-
- - {/* Adaptive Volume Routing */}
@@ -188,7 +74,6 @@ export default function RoutingTab() {
- {/* LKGP Toggle */}
@@ -268,77 +153,8 @@ export default function RoutingTab() {
- {/* Wildcard Aliases */} - -
-
- -
-
-

{t("modelAliases")}

-

{t("modelAliasesDesc")}

-
-
- - {aliases.length > 0 && ( -
- {aliases.map((a, i) => ( -
-
- {a.pattern} - - arrow_forward - - {a.target} -
- -
- ))} -
- )} - -
-
- setNewPattern(e.target.value)} - /> -
-
- setNewTarget(e.target.value)} - /> -
- -
-
- - {/* Fallback Chains */} - {/* Client Cache Control */}
diff --git a/src/app/(dashboard)/dashboard/settings/page.tsx b/src/app/(dashboard)/dashboard/settings/page.tsx index 286ff5d3b2..e7a11c27a6 100644 --- a/src/app/(dashboard)/dashboard/settings/page.tsx +++ b/src/app/(dashboard)/dashboard/settings/page.tsx @@ -14,13 +14,14 @@ import AppearanceTab from "./components/AppearanceTab"; import ThinkingBudgetTab from "./components/ThinkingBudgetTab"; import CodexServiceTierTab from "./components/CodexServiceTierTab"; import SystemPromptTab from "./components/SystemPromptTab"; -import ModelAliasesTab from "./components/ModelAliasesTab"; +import ModelAliasesUnified from "./components/ModelAliasesUnified"; import BackgroundDegradationTab from "./components/BackgroundDegradationTab"; import CacheSettingsTab from "./components/CacheSettingsTab"; import MemorySkillsTab from "./components/MemorySkillsTab"; import ModelsDevSyncTab from "./components/ModelsDevSyncTab"; import ResilienceTab from "./components/ResilienceTab"; import CliproxyapiSettingsTab from "./components/CliproxyapiSettingsTab"; +import ModelRoutingSection from "@/shared/components/ModelRoutingSection"; const tabs = [ { id: "general", labelKey: "general", icon: "settings" }, @@ -105,8 +106,9 @@ export default function SettingsPage() { {activeTab === "routing" && (
+ - +
)} diff --git a/src/app/api/combos/test/route.ts b/src/app/api/combos/test/route.ts index d13952fa7e..01a0962168 100644 --- a/src/app/api/combos/test/route.ts +++ b/src/app/api/combos/test/route.ts @@ -40,6 +40,7 @@ async function testComboTarget(target, internalUrl) { // Force a fresh execution path so combo tests cannot be satisfied by // OmniRoute's semantic cache or other request reuse layers. "X-OmniRoute-No-Cache": "true", + ...(target.connectionId ? { "X-OmniRoute-Connection": target.connectionId } : {}), "X-Request-Id": `combo-test-${randomUUID()}`, }, body: JSON.stringify(testBody), diff --git a/src/app/api/openapi/spec/route.ts b/src/app/api/openapi/spec/route.ts index d48f748ab6..ca51698fe6 100644 --- a/src/app/api/openapi/spec/route.ts +++ b/src/app/api/openapi/spec/route.ts @@ -6,15 +6,12 @@ import { NextResponse } from "next/server"; import fs from "fs"; import path from "path"; -import { fileURLToPath } from "url"; import yaml from "js-yaml"; let cachedSpec: { data: any; mtime: number } | null = null; -const ROUTE_DIR = path.dirname(fileURLToPath(import.meta.url)); -const PROJECT_ROOT = path.resolve(ROUTE_DIR, "../../../../../"); const OPENAPI_SPEC_CANDIDATES = [ - path.join(PROJECT_ROOT, "docs", "openapi.yaml"), - path.join(PROJECT_ROOT, "app", "docs", "openapi.yaml"), + path.join(process.cwd(), "docs", "openapi.yaml"), + path.join(process.cwd(), "app", "docs", "openapi.yaml"), ]; export async function GET() { diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 3472f48804..4881aafc9c 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "التكاليف", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "المكالمات لكل حساب قبل التبديل", "modelAliases": "الأسماء المستعارة النموذجية", "modelAliasesTitle": "أسماء بديلة للنماذج", - "modelAliasesDesc": "أنماط أحرف البدل لإعادة تعيين أسماء النماذج • استخدم * و؟", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "إضافة اسم بديل مخصص", "deprecatedModelId": "معرف النموذج المهمل", "newModelId": "معرف النموذج الجديد", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "مترجم", diff --git a/src/i18n/messages/bg.json b/src/i18n/messages/bg.json index dd49e0b5d2..be554a6def 100644 --- a/src/i18n/messages/bg.json +++ b/src/i18n/messages/bg.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Разходи", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Обаждания на акаунт преди превключване", "modelAliases": "Псевдоними на модела", "modelAliasesTitle": "Псевдоними на модели", - "modelAliasesDesc": "Шаблони за заместващи символи за пренасочване на имена на модели • Използвайте * и ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Добави потребителски псевдоним", "deprecatedModelId": "Остарял ID на модел", "newModelId": "Нов ID на модел", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Преводач", diff --git a/src/i18n/messages/cs.json b/src/i18n/messages/cs.json index db9b005624..b134a12cb8 100644 --- a/src/i18n/messages/cs.json +++ b/src/i18n/messages/cs.json @@ -997,7 +997,19 @@ "auto": "Auto Kombo", "autoDesc": "Samoopravný inteligentní směrovací pool (Optimalizovaný výkon)", "lkgp": "Režim LKGP", - "lkgpDesc": "Poslední známý dobrý poskytovatel (Predikovatelná odolnost)" + "lkgpDesc": "Poslední známý dobrý poskytovatel (Predikovatelná odolnost)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Náklady", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Volání účtem před přepnutím", "modelAliases": "Aliasy modelů", "modelAliasesTitle": "Aliasy modelů", - "modelAliasesDesc": "Vzory zástupných znaků pro přemapování názvů modelů • Použijte * a ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Přidat vlastní alias", "deprecatedModelId": "ID zastupovaného modelu", "newModelId": "Nové ID modelu", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Poslední známý dobrý poskytovatel (Predikovatelná odolnost)", "maintenance": "Údržba", "purgeExpiredLogs": "Vymazat expirované protokoly", - "purgeLogsFailed": "Nepodařilo se vymazat protokoly" + "purgeLogsFailed": "Nepodařilo se vymazat protokoly", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Překladatel", diff --git a/src/i18n/messages/da.json b/src/i18n/messages/da.json index 74621601c1..c155d098f0 100644 --- a/src/i18n/messages/da.json +++ b/src/i18n/messages/da.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Omkostninger", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Opkald pr. konto før skift", "modelAliases": "Model aliaser", "modelAliasesTitle": "Model Aliaser", - "modelAliasesDesc": "Wildcard-mønstre til omlægning af modelnavne • Brug * og ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Tilføj Tilpasset Alias", "deprecatedModelId": "Forældet model-ID", "newModelId": "Nyt model-ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Oversætter", diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index 5a84fe4850..9b0cf2622e 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Kosten", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Anrufe pro Konto vor dem Wechsel", "modelAliases": "Modell-Aliase", "modelAliasesTitle": "Modell-Aliase", - "modelAliasesDesc": "Platzhaltermuster zum Neuzuordnen von Modellnamen • Verwenden Sie * und ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Benutzerdefinierten Alias hinzufügen", "deprecatedModelId": "Veraltete Modell-ID", "newModelId": "Neue Modell-ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Übersetzer", diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index fdca460b08..6dacc1d433 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -1050,7 +1050,19 @@ "auto": "Intelligent Auto", "autoDesc": "Self-healing smart routing pool with multi-factor scoring", "lkgp": "LKGP Mode", - "lkgpDesc": "Prioritizes the last provider that successfully completed a request" + "lkgpDesc": "Prioritizes the last provider that successfully completed a request", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Costs", @@ -2101,7 +2113,7 @@ "stickyLimitDesc": "Calls per account before switching", "modelAliases": "Model Aliases", "modelAliasesTitle": "Model Aliases", - "modelAliasesDesc": "Wildcard patterns to remap model names • Use * and ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Add Custom Alias", "deprecatedModelId": "Deprecated model ID", "newModelId": "New model ID", @@ -2354,7 +2366,28 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Translator", diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index 279c2271bd..1398393d8c 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Costos", @@ -1947,7 +1959,7 @@ "stickyLimitDesc": "Llamadas por cuenta antes de cambiar", "modelAliases": "Alias de modelo", "modelAliasesTitle": "Aliases de Modelo", - "modelAliasesDesc": "Patrones comodín para reasignar nombres de modelos • Utilice * y ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Agregar Alias Personalizado", "deprecatedModelId": "ID del modelo obsoleto", "newModelId": "Nuevo ID del modelo", @@ -2236,7 +2248,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Traductor", diff --git a/src/i18n/messages/fi.json b/src/i18n/messages/fi.json index fc0972a70f..313b81c00a 100644 --- a/src/i18n/messages/fi.json +++ b/src/i18n/messages/fi.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Kustannukset", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Puhelut tilikohtaisesti ennen vaihtamista", "modelAliases": "Mallin aliakset", "modelAliasesTitle": "Mallialias", - "modelAliasesDesc": "Jokerimerkkikuviot mallien nimien yhdistämiseen • Käytä * ja ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Lisää Mukautettu Alias", "deprecatedModelId": "Vanhentunut malli-ID", "newModelId": "Uusi malli-ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Kääntäjä", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index f18ad6e00a..3072df5553 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Coûts", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Appels par compte avant de changer", "modelAliases": "Alias de modèle", "modelAliasesTitle": "Alias de Modèles", - "modelAliasesDesc": "Modèles génériques pour remapper les noms de modèles • Utilisez * et ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Ajouter un Alias Personnalisé", "deprecatedModelId": "ID du modèle obsolète", "newModelId": "Nouvel ID de modèle", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Traducteur", diff --git a/src/i18n/messages/he.json b/src/i18n/messages/he.json index e2b9af068f..515b907964 100644 --- a/src/i18n/messages/he.json +++ b/src/i18n/messages/he.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "עלויות", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "שיחות לכל חשבון לפני המעבר", "modelAliases": "כינויי דגם", "modelAliasesTitle": "כינויי מודלים", - "modelAliasesDesc": "תבניות תווים כלליים למיפוי מחדש של שמות מודלים • השתמש ב-* וב-?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "הוסף כינוי מותאם אישית", "deprecatedModelId": "מזהה מודל מיושן", "newModelId": "מזהה מודל חדש", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "מתרגם", diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index 23e1a71e02..efb23337e5 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "लागत", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "स्विच करने से पहले प्रति खाता कॉल", "modelAliases": "मॉडल उपनाम", "modelAliasesTitle": "Model Alias", - "modelAliasesDesc": "मॉडल नामों को रीमैप करने के लिए वाइल्डकार्ड पैटर्न • * और ? का उपयोग करें", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Kustom Alias Tambahkan", "deprecatedModelId": "ID model yang tidak digunakan lagi", "newModelId": "ID model baru", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "अनुवादक", diff --git a/src/i18n/messages/hu.json b/src/i18n/messages/hu.json index 4495e05c18..38d83d27a5 100644 --- a/src/i18n/messages/hu.json +++ b/src/i18n/messages/hu.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Költségek", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Hívások fiókonként váltás előtt", "modelAliases": "Modell álnevek", "modelAliasesTitle": "Modell aliasok", - "modelAliasesDesc": "Helyettesítő karakter minták a modellnevek újratervezéséhez • Használja a * és a ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Egyéni Alias Hozzáadása", "deprecatedModelId": "Elavult modell ID", "newModelId": "Új modell ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Fordító", diff --git a/src/i18n/messages/id.json b/src/i18n/messages/id.json index 31ed9455a6..6f0175dfb2 100644 --- a/src/i18n/messages/id.json +++ b/src/i18n/messages/id.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Biaya", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Panggilan per akun sebelum beralih", "modelAliases": "Alias Model", "modelAliasesTitle": "Alias Model", - "modelAliasesDesc": "Pola karakter pengganti untuk memetakan ulang nama model • Gunakan * dan ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Tambah Alias Kustom", "deprecatedModelId": "ID model yang sudah usang", "newModelId": "ID model baru", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Penerjemah", diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index 51e9f04854..b648335ffb 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Costi", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Chiamate per account prima del cambio", "modelAliases": "Alias ​​del modello", "modelAliasesTitle": "Alias dei Modelli", - "modelAliasesDesc": "Modelli di caratteri jolly per rimappare i nomi dei modelli • Utilizzare * e ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Aggiungi Alias Personalizzato", "deprecatedModelId": "ID modello deprecato", "newModelId": "Nuovo ID modello", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Traduttore", diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index 3aeac027c7..95879f738e 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "コスト", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "切り替える前のアカウントごとの通話数", "modelAliases": "モデルのエイリアス", "modelAliasesTitle": "モデルエイリアス", - "modelAliasesDesc": "モデル名を再マッピングするワイルドカード パターン • * と ? を使用します。", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "カスタムエイリアスを追加", "deprecatedModelId": "非推奨モデルID", "newModelId": "新しいモデルID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "翻訳者", diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index a6d52a34a8..7c38183270 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "비용", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "전환 전 계정당 통화", "modelAliases": "모델 별칭", "modelAliasesTitle": "모델 별칭", - "modelAliasesDesc": "모델 이름을 다시 매핑하는 와일드카드 패턴 • * 및 ?를 사용합니다.", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "사용자 지정 별칭 추가", "deprecatedModelId": "사용 중단된 모델 ID", "newModelId": "새 모델 ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "번역기", diff --git a/src/i18n/messages/ms.json b/src/i18n/messages/ms.json index 06e64f696e..ad85d77910 100644 --- a/src/i18n/messages/ms.json +++ b/src/i18n/messages/ms.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Kos", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Panggilan setiap akaun sebelum bertukar", "modelAliases": "Alias Model", "modelAliasesTitle": "Alias Model", - "modelAliasesDesc": "Corak kad liar untuk memetakan semula nama model • Gunakan * dan ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Tambah Alias Tersuai", "deprecatedModelId": "ID model yang ditamatkan", "newModelId": "ID model baharu", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Penterjemah", diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json index 48e8596b7b..d6283c8f04 100644 --- a/src/i18n/messages/nl.json +++ b/src/i18n/messages/nl.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Kosten", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Gesprekken per account voordat u overstapt", "modelAliases": "Modelaliassen", "modelAliasesTitle": "Model Aliases", - "modelAliasesDesc": "Jokertekenpatronen om modelnamen opnieuw toe te wijzen • Gebruik * en ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Aangepast Alias Toevoegen", "deprecatedModelId": "Verouderd model-ID", "newModelId": "Nieuw model-ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Vertaler", diff --git a/src/i18n/messages/no.json b/src/i18n/messages/no.json index c49ab844d0..c7d339ad33 100644 --- a/src/i18n/messages/no.json +++ b/src/i18n/messages/no.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Kostnader", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Anrop per konto før bytte", "modelAliases": "Modellaliaser", "modelAliasesTitle": "Modellaliaser", - "modelAliasesDesc": "Jokertegnmønstre for å tilordne modellnavn på nytt • Bruk * og ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Legg til Tilpasset Alias", "deprecatedModelId": "Utdatert modell-ID", "newModelId": "Ny modell-ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Oversetter", diff --git a/src/i18n/messages/phi.json b/src/i18n/messages/phi.json index 90fcf91ea4..838dd61629 100644 --- a/src/i18n/messages/phi.json +++ b/src/i18n/messages/phi.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Mga gastos", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Mga tawag sa bawat account bago lumipat", "modelAliases": "Mga Alyas ng Modelo", "modelAliasesTitle": "Mga Alias ng Model", - "modelAliasesDesc": "Mga pattern ng wildcard para i-remap ang mga pangalan ng modelo • Gamitin ang * at ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Magdagdag ng Custom na Alias", "deprecatedModelId": "Deprecated na Model ID", "newModelId": "Bagong Model ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Tagasalin", diff --git a/src/i18n/messages/pl.json b/src/i18n/messages/pl.json index 39d72ece2c..02e8c5c0a5 100644 --- a/src/i18n/messages/pl.json +++ b/src/i18n/messages/pl.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Koszty", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Połączenia na konto przed zmianą", "modelAliases": "Aliasy modeli", "modelAliasesTitle": "Aliasy modeli", - "modelAliasesDesc": "Wzorce wieloznaczne do zmiany nazw modeli • Użyj * i ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Dodaj niestandardowy alias", "deprecatedModelId": "Przestarzały ID modelu", "newModelId": "Nowy ID modelu", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Tłumacz", diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index de02bbf2a1..d64a16585b 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -1006,7 +1006,19 @@ "auto": "Auto Combo", "autoDesc": "Pool de roteamento inteligente (Otimizado)", "lkgp": "Modo LKGP", - "lkgpDesc": "Último Provedor Bom Conhecido (Resiliência previsível)" + "lkgpDesc": "Último Provedor Bom Conhecido (Resiliência previsível)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Custos", @@ -2006,7 +2018,7 @@ "stickyLimitDesc": "Chamadas por conta antes de trocar", "modelAliases": "Aliases de Modelo", "modelAliasesTitle": "Aliases de Modelo", - "modelAliasesDesc": "Padrões coringa para remapear nomes de modelos • Use * e ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Adicionar Alias Personalizado", "deprecatedModelId": "ID do modelo depreciado", "newModelId": "Novo ID do modelo", @@ -2301,7 +2313,28 @@ "clearLkgpCache": "Clear LKGP Cache", "lkgpCacheCleared": "LKGP cache cleared successfully", "lkgpCacheClearFailed": "Failed to clear LKGP cache", - "maintenance": "Maintenance" + "maintenance": "Maintenance", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Tradutor", diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index ba64dcbe49..237ae659be 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Pool de roteamento inteligente (Otimizado)", "lkgp": "Modo LKGP", - "lkgpDesc": "Último Provedor Bom Conhecido (Resiliência previsível)" + "lkgpDesc": "Último Provedor Bom Conhecido (Resiliência previsível)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Custos", @@ -1997,7 +2009,7 @@ "stickyLimitDesc": "Chamadas por conta antes de mudar", "modelAliases": "Aliases de modelo", "modelAliasesTitle": "Aliases de Modelo", - "modelAliasesDesc": "Padrões curinga para remapear nomes de modelos • Use * e ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Adicionar Alias Personalizado", "deprecatedModelId": "ID do modelo depreciado", "newModelId": "Novo ID do modelo", @@ -2286,7 +2298,30 @@ "clearLkgpCache": "Clear LKGP Cache", "lkgpCacheCleared": "LKGP cache cleared successfully", "lkgpCacheClearFailed": "Failed to clear LKGP cache", - "maintenance": "Maintenance" + "maintenance": "Maintenance", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Tradutor", diff --git a/src/i18n/messages/ro.json b/src/i18n/messages/ro.json index 92fc3ebad7..d5fca1461b 100644 --- a/src/i18n/messages/ro.json +++ b/src/i18n/messages/ro.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Costuri", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Apeluri pe cont înainte de a comuta", "modelAliases": "Aliasuri de model", "modelAliasesTitle": "Aliasuri de model", - "modelAliasesDesc": "Modele wildcard pentru a remapa numele modelelor • Utilizați * și ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Adaugă Alias Personalizat", "deprecatedModelId": "ID model depreciat", "newModelId": "ID model nou", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Traducător", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index e4eacef3d6..eb382eb6da 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -1021,7 +1021,19 @@ "auto": "Авто", "autoDesc": "Автоматическая стратегия - система сама выбирает подходящее поведение.", "lkgp": "LKGP", - "lkgpDesc": "Маршрутизация по последней известной хорошей политике" + "lkgpDesc": "Маршрутизация по последней известной хорошей политике", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Затраты", @@ -1985,7 +1997,7 @@ "stickyLimitDesc": "Звонки на аккаунт до переключения", "modelAliases": "Псевдонимы моделей", "modelAliasesTitle": "Псевдонимы моделей", - "modelAliasesDesc": "Шаблоны подстановочных знаков для переназначения названий моделей • Используйте * и ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Добавить пользовательский псевдоним", "deprecatedModelId": "Устаревший ID модели", "newModelId": "Новый ID модели", @@ -2260,7 +2272,30 @@ "skillsComingSoon": "Маркетплейс навыков скоро появится.", "memorySkillsTitle": "Память и навыки", "memorySkillsDesc": "Постоянный контекст и возможности", - "days": "Дни" + "days": "Дни", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Переводчик", diff --git a/src/i18n/messages/sk.json b/src/i18n/messages/sk.json index d764a2dcf9..554117f98e 100644 --- a/src/i18n/messages/sk.json +++ b/src/i18n/messages/sk.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "náklady", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Hovory na účet pred prepnutím", "modelAliases": "Aliasy modelov", "modelAliasesTitle": "Aliasy modelov", - "modelAliasesDesc": "Vzory zástupných znakov na premapovanie názvov modelov • Použite * a ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Pridať vlastný alias", "deprecatedModelId": "Zastaraný ID modelu", "newModelId": "Nový ID modelu", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Prekladateľ", diff --git a/src/i18n/messages/sv.json b/src/i18n/messages/sv.json index 68cfcd7381..11c95d46c3 100644 --- a/src/i18n/messages/sv.json +++ b/src/i18n/messages/sv.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Kostnader", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Samtal per konto innan byte", "modelAliases": "Modellalias", "modelAliasesTitle": "Modellalias", - "modelAliasesDesc": "Jokerteckenmönster för att mappa om modellnamn • Använd * och ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Lägg Till Anpassat Alias", "deprecatedModelId": "Föråldrat modell-ID", "newModelId": "Nytt modell-ID", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Översättare", diff --git a/src/i18n/messages/th.json b/src/i18n/messages/th.json index d2cefd55c1..4b1f35c9bd 100644 --- a/src/i18n/messages/th.json +++ b/src/i18n/messages/th.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "ค่าใช้จ่าย", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "โทรต่อบัญชีก่อนที่จะเปลี่ยน", "modelAliases": "นามแฝงของโมเดล", "modelAliasesTitle": "นามแฝงโมเดล", - "modelAliasesDesc": "รูปแบบไวด์การ์ดเพื่อทำการแมปชื่อโมเดลใหม่ • ใช้ * และ ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "เพิ่มนามแฝงที่กำหนดเอง", "deprecatedModelId": "ID โมเดลที่เลิกใช้", "newModelId": "ID โมเดลใหม่", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "นักแปล", diff --git a/src/i18n/messages/tr.json b/src/i18n/messages/tr.json index b5869178ee..c1c3fdacb5 100644 --- a/src/i18n/messages/tr.json +++ b/src/i18n/messages/tr.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Maliyetler", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Geçişten önce hesap başına çağrı sayısı", "modelAliases": "Model Takma Adları", "modelAliasesTitle": "Model Takma Adları", - "modelAliasesDesc": "Model adlarını yeniden eşlemek için joker karakter desenleri • * ve ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Özel Takma Ad Ekle", "deprecatedModelId": "Kullanımdan kaldırılan model kimliği", "newModelId": "Yeni model kimliği", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Çeviri", diff --git a/src/i18n/messages/uk-UA.json b/src/i18n/messages/uk-UA.json index 0e5a01ea65..f915ec7747 100644 --- a/src/i18n/messages/uk-UA.json +++ b/src/i18n/messages/uk-UA.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Витрати", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Дзвінки на обліковий запис перед переходом", "modelAliases": "Псевдоніми моделі", "modelAliasesTitle": "Псевдоніми моделей", - "modelAliasesDesc": "Шаблони шаблонів узагальнення для зміни назв моделей • Використовуйте * та ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Додати власний псевдонім", "deprecatedModelId": "Застарілий ID моделі", "newModelId": "Новий ID моделі", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Перекладач", diff --git a/src/i18n/messages/vi.json b/src/i18n/messages/vi.json index 5cadd9e835..1f8e77dc66 100644 --- a/src/i18n/messages/vi.json +++ b/src/i18n/messages/vi.json @@ -997,7 +997,19 @@ "auto": "Auto Combo", "autoDesc": "Self-healing smart routing pool (Performance optimized)", "lkgp": "LKGP Mode", - "lkgpDesc": "Last Known Good Provider (Predictable resilience)" + "lkgpDesc": "Last Known Good Provider (Predictable resilience)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "Chi phí", @@ -1942,7 +1954,7 @@ "stickyLimitDesc": "Cuộc gọi trên mỗi tài khoản trước khi chuyển đổi", "modelAliases": "Bí danh mẫu", "modelAliasesTitle": "Bí danh mô hình", - "modelAliasesDesc": "Các mẫu ký tự đại diện để ánh xạ lại tên mẫu máy • Sử dụng * và ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "Thêm Bí Danh Tùy Chỉnh", "deprecatedModelId": "ID mô hình ngừng sử dụng", "newModelId": "ID mô hình mới", @@ -2231,7 +2243,30 @@ "lkgpDesc": "Last Known Good Provider (Predictable resilience)", "maintenance": "Maintenance", "purgeExpiredLogs": "Purge Expired Logs", - "purgeLogsFailed": "Failed to purge logs" + "purgeLogsFailed": "Failed to purge logs", + "contextRelay": "Context Relay", + "contextRelayDesc": "Hands off context between providers with automatic summarization", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "Người phiên dịch", diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index d679824d4d..92b43c8081 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -1006,7 +1006,19 @@ "auto": "自动组合", "autoDesc": "自愈型智能路由池(性能优化)", "lkgp": "LKGP 模式", - "lkgpDesc": "最后已知良好提供商(可预测的弹性)" + "lkgpDesc": "最后已知良好提供商(可预测的弹性)", + "wizardGuideTitle": "Getting Started with Combos", + "wizardGuideDesc": "Create model combos to route AI traffic intelligently", + "wizardGuideHint": "or click + Create Combo above", + "createFirstCombo": "Create Your First Combo", + "wizardStep1Title": "Name Your Combo", + "wizardStep1Desc": "Give your combo a unique name to identify it in routing rules", + "wizardStep2Title": "Add Models", + "wizardStep2Desc": "Select AI models and arrange their fallback priority order", + "wizardStep3Title": "Choose Strategy", + "wizardStep3Desc": "Pick how requests are distributed across your models - 13 strategies available", + "wizardStep4Title": "Review & Save", + "wizardStep4Desc": "Review your configuration and activate the combo" }, "costs": { "title": "成本", @@ -2000,7 +2012,7 @@ "stickyLimitDesc": "切换前每个账户连续处理的请求次数", "modelAliases": "模型别名", "modelAliasesTitle": "模型别名", - "modelAliasesDesc": "重新映射模型名称的通配符模式 • 使用 * 和 ?", + "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", "addCustomAlias": "添加自定义别名", "deprecatedModelId": "已弃用的模型 ID", "newModelId": "新模型 ID", @@ -2253,7 +2265,28 @@ "lkgpDesc": "最后已知良好提供商(可预测的弹性)", "maintenance": "维护", "purgeExpiredLogs": "清理过期日志", - "purgeLogsFailed": "清理日志失败" + "purgeLogsFailed": "清理日志失败", + "contextOpt": "Context Optimized", + "contextOptDesc": "Routes based on context window requirements and conversation length", + "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", + "weightedDesc": "Distributes traffic by percentage weights across providers", + "modelRoutingTitle": "Model Routing Rules", + "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", + "addRule": "Add Rule", + "routeToCombo": "Route to Combo", + "selectCombo": "Select combo...", + "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", + "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", + "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", + "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", + "deleteRoutingRule": "Delete this model routing rule?", + "exactMatchMode": "Exact Match", + "wildcardPatternMode": "Wildcard Pattern", + "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", + "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", + "noExactAliasesConfigured": "No exact-match aliases configured.", + "wildcardRulesTitle": "Wildcard Rules", + "noWildcardAliasesConfigured": "No wildcard aliases configured." }, "translator": { "title": "翻译器", diff --git a/src/shared/components/ModelRoutingSection.tsx b/src/shared/components/ModelRoutingSection.tsx index 063f2435ac..20f763cc01 100644 --- a/src/shared/components/ModelRoutingSection.tsx +++ b/src/shared/components/ModelRoutingSection.tsx @@ -1,6 +1,7 @@ "use client"; import { useState, useEffect } from "react"; +import { useTranslations } from "next-intl"; export interface ModelMapping { id: string; @@ -17,11 +18,14 @@ interface Combo { name: string; } -export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[] }) { +export default function ModelRoutingSection({ combos: externalCombos }: { combos?: Combo[] } = {}) { + const t = useTranslations("settings"); const [mappings, setMappings] = useState([]); + const [internalCombos, setInternalCombos] = useState([]); const [loading, setLoading] = useState(true); const [adding, setAdding] = useState(false); const [editingId, setEditingId] = useState(null); + const combos = externalCombos || internalCombos; // Form state const [pattern, setPattern] = useState(""); @@ -53,6 +57,22 @@ export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[] }; }, []); + useEffect(() => { + if (externalCombos !== undefined) return; + let cancelled = false; + fetch("/api/combos") + .then((res) => (res.ok ? res.json() : { combos: [] })) + .then((data) => { + if (!cancelled) { + setInternalCombos(Array.isArray(data?.combos) ? data.combos : []); + } + }) + .catch(() => {}); + return () => { + cancelled = true; + }; + }, [externalCombos]); + const refetchMappings = async () => { const data = await loadMappings(); setMappings(data); @@ -100,7 +120,7 @@ export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[] }; const handleDelete = async (id: string) => { - if (!confirm("Delete this model routing rule?")) return; + if (!confirm(t("deleteRoutingRule"))) return; try { await fetch(`/api/model-combo-mappings/${id}`, { method: "DELETE" }); setMappings((prev) => prev.filter((m) => m.id !== id)); @@ -126,10 +146,8 @@ export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[]
route
-

Model Routing Rules

-

- Automatically route models to specific combos using glob patterns -

+

{t("modelRoutingTitle")}

+

{t("modelRoutingDesc")}

{!adding && ( @@ -139,7 +157,7 @@ export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[] bg-primary/10 text-primary hover:bg-primary/20 transition-colors" > add - Add Rule + {t("addRule")} )}
@@ -150,7 +168,7 @@ export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[]
-

- Use * for any chars, ? for single char. Case-insensitive. -

+

{t("patternHint")}

-

- Higher = checked first. Use 10+ for specific patterns. -

+

{t("priorityHint")}

- {editingId ? "Update" : "Save"} + {editingId ? t("update") : t("save")}
@@ -231,18 +245,11 @@ export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[] {/* Mappings list */} {loading ? ( -
Loading...
+
{t("loading")}
) : mappings.length === 0 ? (
-

- No routing rules configured. Requests use the global combo by default. -

-

- Add a rule like{" "} - claude-opus* - {" → "} frontier-combo to automatically route - requests. -

+

{t("noRoutingRules")}

+

{t("routingRuleHint")}

) : (
@@ -277,7 +284,7 @@ export default function ModelRoutingSection({ combos = [] }: { combos?: Combo[]