From 274c9c3da9691448c104887014f33e9af87f0af9 Mon Sep 17 00:00:00 2001 From: musistudio Date: Thu, 30 Jul 2026 18:53:37 +0800 Subject: [PATCH] Add profile context to fallback model diagnostics --- package.json | 4 -- packages/core/src/routing/config-compiler.ts | 5 ++- .../gateway/routing-architecture.test.mjs | 40 +++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 2a22fea5..986e6684 100644 --- a/package.json +++ b/package.json @@ -48,10 +48,6 @@ "prepublishOnly": "npm run typecheck", "preview": "npm run build:assets && electron .", "version": "npm run models:update", - "bench:context-archive": "node benchmarks/run-context-archive-benchmark.mjs", - "bench:context-archive-agent": "node benchmarks/run-context-archive-real-agent-benchmark.mjs", - "bench:context-archive-real": "node benchmarks/run-context-archive-real-agent-benchmark.mjs", - "bench:claude-compact-real": "node benchmarks/claude-code-real-compact.mjs", "docker:build": "docker build -t claude-code-router:local .", "docker:run": "docker run --rm -p 3458:8080 -v ccr-data:/data claude-code-router:local", "test": "npm run test:packages && npm run test:architecture", diff --git a/packages/core/src/routing/config-compiler.ts b/packages/core/src/routing/config-compiler.ts index 57c1cd2c..00f3fa00 100644 --- a/packages/core/src/routing/config-compiler.ts +++ b/packages/core/src/routing/config-compiler.ts @@ -92,6 +92,7 @@ function compileProfileRoutings( const rules = (routing?.rules ?? []).map((rule) => compileRouterRule(rule, modelRegistry, options, { allowScript: false, label: `Profile "${profile.name}" route "${rule.name}"`, + profile, source: "profile" })); return { @@ -121,7 +122,7 @@ function compileRouterRule( rule: RouterRule, modelRegistry: ModelRegistry, options: CompileRouterConfigOptions, - diagnostic: { allowScript?: boolean; label: string; source: "profile" | "rule" } + diagnostic: { allowScript?: boolean; label: string; profile?: ProfileConfig; source: "profile" | "rule" } ): CompiledRouterRule { const rewriteResults = routerRuleRewrites(rule).map(compileConfiguredRouteRewrite); const rewrites = rewriteResults.flatMap((result) => result.rewrite ? [result.rewrite] : []); @@ -168,7 +169,7 @@ function compileRouterRule( } } } - diagnostics.push(...fallbackModelDiagnostics(rule.fallback, modelRegistry, diagnostic.source, rule)); + diagnostics.push(...fallbackModelDiagnostics(rule.fallback, modelRegistry, diagnostic.source, rule, diagnostic.profile)); return { active: (rule.type === "script" ? Boolean(rule.script) : rewrites.length > 0) && diagnostics.length === 0, diagnostics, diff --git a/packages/core/test/unit/gateway/routing-architecture.test.mjs b/packages/core/test/unit/gateway/routing-architecture.test.mjs index 96e6848f..557d1e11 100644 --- a/packages/core/test/unit/gateway/routing-architecture.test.mjs +++ b/packages/core/test/unit/gateway/routing-architecture.test.mjs @@ -132,6 +132,46 @@ test("router config compilation filters invalid global fallback models", () => { assert.equal(compiled.diagnostics[0].code, "fallback-model-not-configured"); }); +test("router config compilation reports profile route fallback model diagnostics with profile context", () => { + const config = routingConfig({ + profile: { + enabled: true, + profiles: [{ + agent: "claude-code", + enabled: true, + id: "profile-a", + model: "Primary/alpha", + name: "Profile A", + routing: { + enabled: true, + enhancedRoute: true, + rules: [{ + condition: { left: "request.header.x-task", operator: "==", right: "heavy" }, + enabled: true, + fallback: { + mode: "model-chain", + models: ["Primary/missing"], + retryCount: 1 + }, + id: "profile-fallback", + name: "Profile fallback", + rewrites: [{ key: "request.body.model", operation: "set", value: "Primary/alpha" }], + type: "condition" + }] + }, + scope: "ccr" + }] + } + }); + + const compiled = compileRouterConfig(config); + const diagnostic = compiled.profileRoutings[0].rules[0].diagnostics[0]; + + assert.equal(diagnostic.code, "fallback-model-not-configured"); + assert.equal(diagnostic.message, 'Profile "Profile A" route "Profile fallback" references unconfigured fallback model "Primary/missing".'); + assert.equal(diagnostic.source, "profile"); +}); + test("router config compilation rejects conflicting provider and model targets", () => { const config = routingConfig(); config.Router.rules = [{