anomalyco / anomalyco/opencode
question tool: custom answer option cannot be disabled because "custom" is missing from the Prompt schema
@nexxeln is already working on this.
Since Aug 26, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Description
The question tool renders a "Type your own answer" option, and the TUI honours a custom: false flag to hide it — but nothing can ever set that flag, because it is missing from the schema the tool accepts.
packages/schema/src/question.ts:
const base = {
question: ...,
header: ...,
options: ...,
multiple: ...,
}
export const Info = Schema.Struct({
...base,
custom: Schema.Boolean.pipe(optional).annotate({
description: "Allow typing a custom answer (default: true)",
}),
}).annotate({ identifier: "QuestionV2.Info" })
export const Prompt = Schema.Struct(base).annotate({ identifier: "QuestionV2.Prompt" })
custom lives on Info. Both tools take Prompt:
packages/opencode/src/tool/question.ts:7—questions: Schema.mutable(Schema.Array(Question.Prompt))packages/core/src/tool/question.ts:26—questions: Schema.Array(QuestionV2.Prompt)
So custom never reaches the JSON schema the model sees, and a custom: false the model emitted anyway would be dropped as an excess property. Grepping the repo, nothing assigns custom anywhere — the only reader is the renderer:
packages/tui/src/routes/session/question.tsx:38
const custom = createMemo(() => question()?.custom !== false)
Since the value is always undefined, custom !== false is always true, and the input is always shown. The Info.custom field, its description, and the !== false guard are all live code for a state that cannot occur.
The tool description compounds it. packages/opencode/src/tool/question.txt:
When
customis enabled (default), a "Type your own answer" option is added automatically; don't include "Other" or catch-all options
"(default)" tells the model this is a setting with a non-default alternative. There is no way to reach it.
Which way to fix it
Two options, and I picked the first:
- Move
customintobaseso it reachesPromptand the capability the renderer already implements becomes usable. One-line change;Infois unchanged in shape sincebaseis spread into it. - Drop
customfromInfo, delete the!== falseguard, and remove the sentence from both tool descriptions — i.e. admit the option does not exist.
(1) seemed right because the rendering side is complete and correct; only the input schema is missing the field. Happy to switch to (2) if the intent was for custom to be host-controlled rather than model-controlled.
Steps to reproduce
- Call the
questiontool withcustom: falseon a question. - The "Type your own answer" input is still rendered.
- Inspect the tool's JSON schema —
customis not among the accepted properties.
Operating System
Windows 11 (platform independent)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.