Skip to content

Commit 82fb38d

Browse files
Forward OpenCode Go worker session IDs without a catalog (#884)
No-catalog subagent Go sources were built through the OpenAI-compatible path and omitted opencodeSessionId, so Go Console rejected the worker. Generate one worker session ID up front, route no-catalog Go through buildGoSource, and require sessionId on that builder.
1 parent 22d53b4 commit 82fb38d

4 files changed

Lines changed: 92 additions & 25 deletions

File tree

src/config.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,7 @@ describe("buildGoSource", () => {
14231423
id: "opencode-go",
14241424
apiKey: "sk-go",
14251425
model: "kimi-k2.7-code",
1426+
sessionId: "sess-1",
14261427
});
14271428

14281429
expect(source.provider).toBe("opencode-go");

src/config/index.ts

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ export function buildGoSource(fields: {
383383
id: string;
384384
apiKey?: string;
385385
model: string;
386-
sessionId?: string;
386+
sessionId: string;
387387
reasoningEffort?: ReasoningEffort;
388388
}): InferenceSource {
389389
const endpoint = resolveGoEndpoint(fields.model);
@@ -400,13 +400,9 @@ export function buildGoSource(fields: {
400400
model: fields.model,
401401
defaults: {
402402
maxTokens: SOURCE_MAX_TOKENS,
403-
...(fields.sessionId !== undefined
404-
? {
405-
providerOptions: {
406-
[OPENCODE_SESSION_ID_OPTION]: fields.sessionId,
407-
},
408-
}
409-
: {}),
403+
providerOptions: {
404+
[OPENCODE_SESSION_ID_OPTION]: fields.sessionId,
405+
},
410406
},
411407
};
412408
}
@@ -419,14 +415,10 @@ export function buildGoSource(fields: {
419415
model: fields.model,
420416
defaults: {
421417
maxTokens: SOURCE_MAX_TOKENS,
422-
...(fields.sessionId !== undefined
423-
? {
424-
providerOptions: {
425-
[OPENAI_SESSION_ID_OPTION]: fields.sessionId,
426-
[OPENCODE_SESSION_ID_OPTION]: fields.sessionId,
427-
},
428-
}
429-
: {}),
418+
providerOptions: {
419+
[OPENAI_SESSION_ID_OPTION]: fields.sessionId,
420+
[OPENCODE_SESSION_ID_OPTION]: fields.sessionId,
421+
},
430422
},
431423
};
432424
}
@@ -446,14 +438,10 @@ export function buildGoSource(fields: {
446438
provider: OPENCODE_GO_PROVIDER_ID,
447439
defaults: {
448440
...source.defaults,
449-
...(fields.sessionId !== undefined
450-
? {
451-
providerOptions: {
452-
...(source.defaults?.providerOptions ?? {}),
453-
[OPENCODE_SESSION_ID_OPTION]: fields.sessionId,
454-
},
455-
}
456-
: {}),
441+
providerOptions: {
442+
...(source.defaults?.providerOptions ?? {}),
443+
[OPENCODE_SESSION_ID_OPTION]: fields.sessionId,
444+
},
457445
},
458446
};
459447
}

src/subagent/run-source.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { describe, expect, test } from "bun:test";
22

33
import { KEYLESS_API_KEY } from "../config/index.js";
4+
import { OPENCODE_GO_BASE_URL } from "../../packages/opencode-go/src/index.js";
45
import { buildSubAgentPrimarySource } from "./run.js";
56

67
describe("buildSubAgentPrimarySource", () => {
@@ -22,4 +23,61 @@ describe("buildSubAgentPrimarySource", () => {
2223
model: "qwen3",
2324
});
2425
});
26+
27+
test.each([
28+
["canonical provider id", "opencode-go", "https://example.com/v1"],
29+
["canonical base URL", "custom-go", OPENCODE_GO_BASE_URL],
30+
])(
31+
"routes no-catalog OpenCode Go by %s with a non-empty session ID",
32+
(_, providerName, baseURL) => {
33+
const bundle = buildSubAgentPrimarySource({
34+
providerName,
35+
baseURL,
36+
apiKey: "sk-go",
37+
model: "gpt-5.6-luna",
38+
});
39+
40+
const source = bundle.sources[0];
41+
const sessionId = source?.defaults?.providerOptions?.opencodeSessionId;
42+
expect(bundle.defaultSource).toBe(providerName);
43+
expect(source).toMatchObject({
44+
id: providerName,
45+
provider: "openai-responses",
46+
apiKey: "sk-go",
47+
model: "gpt-5.6-luna",
48+
});
49+
expect(typeof sessionId).toBe("string");
50+
expect(sessionId).not.toHaveLength(0);
51+
expect(source?.defaults?.providerOptions?.openaiSessionId).toBe(
52+
sessionId,
53+
);
54+
},
55+
);
56+
57+
test("forwards a session ID through the catalog OpenCode Go path", () => {
58+
const bundle = buildSubAgentPrimarySource(
59+
{
60+
providerName: "opencode-go",
61+
baseURL: OPENCODE_GO_BASE_URL,
62+
apiKey: "sk-go",
63+
model: "kimi-k2.7-code",
64+
},
65+
[
66+
{
67+
name: "opencode-go",
68+
baseURL: OPENCODE_GO_BASE_URL,
69+
apiKey: "sk-go",
70+
models: ["kimi-k2.7-code"],
71+
opencodeGo: true,
72+
},
73+
],
74+
);
75+
76+
const source = bundle.sources[0];
77+
const sessionId = source?.defaults?.providerOptions?.opencodeSessionId;
78+
expect(bundle.defaultSource).toBe("opencode-go");
79+
expect(source?.provider).toBe("opencode-go");
80+
expect(typeof sessionId).toBe("string");
81+
expect(sessionId).not.toHaveLength(0);
82+
});
2583
});

src/subagent/run.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import type {
3636

3737
import {
3838
buildBifrostSource,
39+
buildGoSource,
3940
buildOpenAISource,
4041
type ProviderCatalogEntry,
4142
} from "../config/index.js";
@@ -63,6 +64,7 @@ import {
6364
import { createCodexReadRawFile } from "../agent/codex-read-raw-file.js";
6465

6566
import { isCodexProviderName } from "../config/codex-providers.js";
67+
import { isOpenCodeGoProvider } from "../../packages/opencode-go/src/index.js";
6668
import { createCompositeBlobReader } from "../agent/lazy-blob-reader.js";
6769

6870
import { buildSubAgentSystemPrompt } from "../agent/prompts.js";
@@ -216,11 +218,12 @@ export function buildSubAgentPrimarySource(
216218
catalog?: readonly ProviderCatalogEntry[],
217219
settings?: Settings,
218220
) {
221+
const sessionId = generateSessionId();
219222
if (catalog !== undefined) {
220223
const source = buildInferenceSourceForRef(
221224
{ provider: provider.providerName, model: provider.model },
222225
{
223-
sessionId: generateSessionId(),
226+
sessionId,
224227
catalog,
225228
...(provider.reasoningEffort !== undefined
226229
? { reasoningEffort: provider.reasoningEffort }
@@ -230,6 +233,23 @@ export function buildSubAgentPrimarySource(
230233
);
231234
if (source !== null) return { sources: [source], defaultSource: source.id };
232235
}
236+
if (
237+
isOpenCodeGoProvider({
238+
name: provider.providerName,
239+
baseURL: provider.baseURL,
240+
})
241+
) {
242+
const source = buildGoSource({
243+
id: provider.providerName,
244+
...(provider.apiKey !== undefined ? { apiKey: provider.apiKey } : {}),
245+
model: provider.model,
246+
sessionId,
247+
...(provider.reasoningEffort !== undefined
248+
? { reasoningEffort: provider.reasoningEffort }
249+
: {}),
250+
});
251+
return { sources: [source], defaultSource: source.id };
252+
}
233253
const build =
234254
provider.bifrostVirtualKey === true
235255
? buildBifrostSource

0 commit comments

Comments
 (0)