From 4f5d92680836f83da9a4f9b14826bfc5efdc7809 Mon Sep 17 00:00:00 2001 From: Ingo Wagner Date: Mon, 21 Sep 2026 17:27:40 +0000 Subject: [PATCH] fix: treat local models as deployment key for run gate PI_DEFAULT_PROVIDER=local with RAKAZO_LOCAL_MODELS had no deployment key, so clearing OpenRouter credentials left needsModel true and blocked sends. --- .../adapters/src/deployment-model.test.ts | 19 +++++++++++++++++++ packages/adapters/src/deployment-model.ts | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/packages/adapters/src/deployment-model.test.ts b/packages/adapters/src/deployment-model.test.ts index 319f7e8..2e33dfd 100644 --- a/packages/adapters/src/deployment-model.test.ts +++ b/packages/adapters/src/deployment-model.test.ts @@ -20,4 +20,23 @@ describe("resolveDeploymentModel", () => { resolveDeploymentModel({ OPENROUTER_API_KEY: "or-key", PI_DEFAULT_PROVIDER: "anthropic" }), ).toEqual({ provider: "anthropic", model: "claude-sonnet-5", key: undefined }); }); + + it("treats configured local models as a keyless deployment", () => { + expect( + resolveDeploymentModel({ + PI_DEFAULT_PROVIDER: "local", + PI_DEFAULT_MODEL: "qwen3-coder-30b-a3b", + RAKAZO_LOCAL_MODELS: "qwen3-coder-30b-a3b", + }), + ).toEqual({ + provider: "local", + model: "qwen3-coder-30b-a3b", + key: "local", + }); + expect(resolveDeploymentModel({ PI_DEFAULT_PROVIDER: "local" })).toEqual({ + provider: "local", + model: "qwen3-coder-30b-a3b", + key: undefined, + }); + }); }); diff --git a/packages/adapters/src/deployment-model.ts b/packages/adapters/src/deployment-model.ts index 9535761..ff49cfd 100644 --- a/packages/adapters/src/deployment-model.ts +++ b/packages/adapters/src/deployment-model.ts @@ -11,13 +11,17 @@ export function resolveDeploymentModel(env: NodeJS.ProcessEnv = process.env) { // A row per provider that ships a deployment key. A third one adds a row here, not a // branch at each call site — and an unknown provider gets no key rather than another // vendor's, which a ternary on one provider would not give. + // Local OpenAI-compatible servers are keyless; a placeholder still counts as a + // deployment key so the model gate and executor fallback treat them as configured. const keys: Record = { openrouter: env.OPENROUTER_API_KEY, anthropic: env.ANTHROPIC_API_KEY, + local: env.RAKAZO_LOCAL_MODELS?.trim() ? "local" : undefined, }; const models: Record = { openrouter: DEFAULT_OPENROUTER_MODEL_ID, anthropic: "claude-sonnet-5", + local: "qwen3-coder-30b-a3b", }; return { provider,