From 2f4bc4c2065cef02b89ff7fb2e0953cc7b95eb89 Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Thu, 3 Sep 2026 13:08:13 +0000 Subject: [PATCH] fix(cli): restore OpenCode provider request headers Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com> --- .changeset/fix-opencode-provider-headers.md | 5 ++ packages/opencode/src/session/llm/request.ts | 12 +-- .../test/kilocode/session-llm-request.test.ts | 83 +++++++++++++++++++ 3 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 .changeset/fix-opencode-provider-headers.md diff --git a/.changeset/fix-opencode-provider-headers.md b/.changeset/fix-opencode-provider-headers.md new file mode 100644 index 000000000000..7455d9b085fc --- /dev/null +++ b/.changeset/fix-opencode-provider-headers.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Restore OpenCode-specific request headers for OpenCode providers instead of Kilo providers. diff --git a/packages/opencode/src/session/llm/request.ts b/packages/opencode/src/session/llm/request.ts index 91da911f23cf..104839d2d08e 100644 --- a/packages/opencode/src/session/llm/request.ts +++ b/packages/opencode/src/session/llm/request.ts @@ -220,7 +220,7 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre }) } - const kiloProjectID = input.model.providerID.startsWith("kilo") // kilocode_change + const opencodeProjectID = input.model.providerID.startsWith("opencode") ? (yield* InstanceState.context).project.id : undefined @@ -231,12 +231,12 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre params, messageTransformOptions: options, headers: { - ...(input.model.providerID.startsWith("kilo") // kilocode_change + ...(input.model.providerID.startsWith("opencode") ? { - ...(kiloProjectID ? { "x-kilo-project": kiloProjectID } : {}), - "x-kilo-session": input.sessionID, - "x-kilo-request": input.user.id, - "x-kilo-client": input.flags.client, + ...(opencodeProjectID ? { "x-opencode-project": opencodeProjectID } : {}), + "x-opencode-session": input.sessionID, + "x-opencode-request": input.user.id, + "x-opencode-client": input.flags.client, "User-Agent": USER_AGENT, } : { diff --git a/packages/opencode/test/kilocode/session-llm-request.test.ts b/packages/opencode/test/kilocode/session-llm-request.test.ts index cef2db3a4e21..965a4a788bab 100644 --- a/packages/opencode/test/kilocode/session-llm-request.test.ts +++ b/packages/opencode/test/kilocode/session-llm-request.test.ts @@ -6,12 +6,16 @@ import { ModelV2 } from "@opencode-ai/core/model" import { SessionV1 } from "@opencode-ai/core/v1/session" import type { Agent } from "@/agent/agent" import type { Auth } from "@/auth" +import { InstanceState } from "@/effect/instance-state" import { RuntimeFlags } from "@/effect/runtime-flags" import type { Plugin } from "@/plugin" import type { Provider } from "@/provider/provider" import { LLMRequestPrep } from "@/session/llm/request" import { MessageID, SessionID } from "@/session/schema" import { SystemPrompt } from "@/session/system" +import { testEffect } from "../lib/effect" + +const it = testEffect(RuntimeFlags.layer({ client: "test" })) const model: Provider.Model = { id: ModelV2.ID.make("test-model"), @@ -125,3 +129,82 @@ describe("Kilo persona in generated metadata requests", () => { expect(oauth.params.options.instructions).toContain(SystemPrompt.soul()) }) }) + +describe("LLM request headers", () => { + for (const name of ["opencode", "opencode-go"]) { + it.instance( + `uses OpenCode headers for ${name}`, + () => + Effect.gen(function* () { + const id = ProviderV2.ID.make(name) + const ctx = yield* InstanceState.context + const result = yield* LLMRequestPrep.prepare({ + user: { ...user("code"), model: { providerID: id, modelID: model.id } }, + sessionID: "ses_test", + model: { ...model, providerID: id }, + agent: agent("code"), + system: [], + messages: [], + tools: {}, + provider: { id, name, source: "config", env: [], options: {}, models: {} }, + auth: undefined, + plugin, + flags: yield* RuntimeFlags.Service, + isWorkflow: false, + }) + + expect(result.headers).toMatchObject({ + "x-opencode-project": ctx.project.id, + "x-opencode-session": "ses_test", + "x-opencode-request": "msg_test", + "x-opencode-client": "test", + }) + expect(Object.keys(result.headers).filter((key) => /^x-kilo-/i.test(key))).toEqual([]) + expect(result.headers).not.toHaveProperty("x-session-affinity") + expect(result.headers).not.toHaveProperty("X-Session-Id") + }), + { git: true }, + ) + } + + for (const entry of [ + { name: "kilo", npm: model.api.npm }, + { name: "test", npm: model.api.npm }, + { name: "kilo", npm: "@kilocode/kilo-gateway" }, + ]) { + it.instance(`uses generic headers for ${entry.name} with ${entry.npm}`, () => + Effect.gen(function* () { + const id = ProviderV2.ID.make(entry.name) + const result = yield* LLMRequestPrep.prepare({ + user: { ...user("code"), model: { providerID: id, modelID: model.id } }, + sessionID: "ses_test", + parentSessionID: "ses_parent", + model: { ...model, providerID: id, api: { ...model.api, npm: entry.npm } }, + agent: agent("code"), + system: [], + messages: [], + tools: {}, + provider: { id, name: entry.name, source: "config", env: [], options: {}, models: {} }, + auth: undefined, + plugin, + flags: yield* RuntimeFlags.Service, + isWorkflow: false, + }) + + expect(result.headers).toMatchObject({ + "x-session-affinity": "ses_test", + "X-Session-Id": "ses_test", + "x-parent-session-id": "ses_parent", + }) + expect(Object.keys(result.headers).filter((key) => /^x-(kilo|opencode)-/i.test(key))).toEqual([]) + if (entry.npm === "@kilocode/kilo-gateway") { + expect(result.headers).toMatchObject({ + "x-kilocode-mode": "code", + "X-KILOCODE-TASKID": "ses_test", + "X-KILOCODE-PARENT-TASKID": "ses_parent", + }) + } + }), + ) + } +})