diff --git a/packages/server/src/server/agent/providers/opencode/v2/permissions.test.ts b/packages/server/src/server/agent/providers/opencode/v2/permissions.test.ts index 451bdf81c6..50a6d98549 100644 --- a/packages/server/src/server/agent/providers/opencode/v2/permissions.test.ts +++ b/packages/server/src/server/agent/providers/opencode/v2/permissions.test.ts @@ -66,6 +66,71 @@ describe("OpenCode v2 questions", () => { }); }); +describe("OpenCode v2 question tool", () => { + test("shows the question text and accepts a typed answer", async () => { + const harness = new V2Harness(); + harness.api.session.form.list = async () => [ + { + id: "question", + sessionID: "session", + title: "Questions", + fields: [ + { + key: "q0", + title: "Next task", + description: "What would you like me to work on next?", + type: "string", + options: [ + { value: "Explore", label: "Explore", description: "Map the codebase" }, + { value: "Fix a bug", label: "Fix a bug", description: "Track down a bug" }, + ], + custom: true, + }, + ], + }, + ]; + const answers: Parameters[0][] = []; + harness.api.session.form.reply = async (input) => { + answers.push(input); + }; + const client = new OpenCodeV2AgentClient({ + logger: createTestLogger(), + runtime: harness.runtime, + }); + const session = await client.createSession({ provider: "opencode", cwd: "/tmp/project" }); + try { + const [request] = session.getPendingPermissions(); + expect(request.input).toEqual({ + questions: [ + { + header: "Next task", + question: "What would you like me to work on next?", + options: [ + { value: "Explore", label: "Explore", description: "Map the codebase" }, + { value: "Fix a bug", label: "Fix a bug", description: "Track down a bug" }, + ], + multiple: false, + allowOther: true, + }, + ], + }); + await session.respondToPermission("question", { + behavior: "allow", + updatedInput: { answers: { "Next task": "Write the release notes" } }, + }); + expect(answers).toEqual([ + { + sessionID: "session", + formID: "question", + answer: { q0: "Write the release notes" }, + }, + ]); + } finally { + await session.close(); + } + }); +}); + describe("OpenCode v2 permission routing", () => { test("routes a child approval back to its owning session", async () => { const harness = new V2Harness(); diff --git a/packages/server/src/server/agent/providers/opencode/v2/permissions.ts b/packages/server/src/server/agent/providers/opencode/v2/permissions.ts index fcd0213282..176fc455be 100644 --- a/packages/server/src/server/agent/providers/opencode/v2/permissions.ts +++ b/packages/server/src/server/agent/providers/opencode/v2/permissions.ts @@ -100,10 +100,11 @@ export class SessionPermissions { title: form.title, input: { questions: form.fields.map((field) => ({ - header: field.key, - question: field.title ?? field.key, + header: field.title ?? field.key, + question: field.description ?? field.title ?? field.key, options: "options" in field ? field.options : undefined, multiple: field.type === "multiselect", + allowOther: "custom" in field && field.custom === true, })), }, };