Skip to content

feat(core): auto-append "Comments" text question after every question tool call - #1

Open
airvzxf wants to merge 2 commits into
devfrom
add-comments
Open

airvzxf wants to merge 2 commits into
devfrom
add-comments

Conversation

@airvzxf

@airvzxf airvzxf commented Jul 29, 2026 •

Copy link
Copy Markdown
Owner

Auto-append “Comments” text question after every question tool call

Closes anomalyco#39410

What

Every invocation of the question tool now ends with a trailing free-form text question — "Any comments?" (header Comments, textOnly: true). The auto-append is unconditional: it fires for single-question prompts, multi-question prompts, and prompts that never reach a Confirm tab. The model sees one extra answer in the reply, so it has a free-text feedback channel without having to request it itself.

Why this approach over the issue's proposal

The original issue proposes a dedicated Comments tab before Confirm plus a new comments?: string field on Question.Reply. This PR ships a different—and I think cleaner—shape:

Aspect Issue proposal This PR
Wire change Additive comments?: string on Reply None—reuses existing Answer array (one extra entry)
UI surface New tab before Confirm Same tab flow; trailing textOnly question
Visible for 1-question prompts? No (matches Confirm's single-question suppression) Yes—auto-append fires unconditionally
Always-visible “Type your own answer” Yes (per-question override) Yes (custom default is unchanged; textOnly tabs use a textarea-only render)
Migration risk New wire field, all clients need to opt-in Drop-in—old clients see one extra Answer entry
Per-option vs. global comments Global only Global only

The shape change was deliberately avoided: the new field would require coordinated SDK regenerations, an HTTP API change (POST /:requestID/reply payload), and a migration window for any third-party integration. Reusing Answer means the change is purely runtime + UI—schemas, SDKs, and HTTP APIs are all untouched.

Changes

  • packages/schema/src/question.ts (+ V1 mirror): add optional textOnly?: boolean to QuestionV2.Info / QuestionInfo. Default behavior unchanged.
  • packages/core/src/tool/question.ts: withComments() helper appends a constant COMMENTS_INFO to the questions array before the QuestionV2.Service.ask call. toModelOutput reads the same wrapped list so the auto-appended question and its answer round-trip back to the model.
  • packages/opencode/src/tool/question.ts (V1 mirror): same withComments wrap applied to the OpenCode CLI's V1 tool.
  • Tool description strings updated in both layers.
  • TUI + CLI: textOnly branch renders a textarea-only view (no option list), with enter to commit and esc to reject. Tab navigation still works between questions.
  • fix(core): surface appended Comments question in tool summary — second commit fixes the four render paths (CLI scrollback, structured snapshots, transcript JSON, session-ui timeline) that were iterating input.questions (N) against metadata.answers (N+1) and silently dropping the trailing entry.

Screenshots & demo

9 PNGs (5 CLI/TUI + 4 Web) are attached to the release assets/comments-screenshots-2026-07-29 in the fork (asset bucket only—no code or branch changes).

TUI / CLI (bun dev)

Comments tab active with textarea focused Review tab showing Comments answer alongside the rest
Comments tab active—textarea focused, footer hints tab enter next esc dismiss Review tab—the trailing Comments: entry is included alongside the per-question answers
Multi-question flow with Comments tab Comments answer recorded in scrollback
Multi-question flow navigating past Comments Post-submit scrollback showing the typed comment
Tool summary in CLI
CLI scrollback tool summary (Asked N questions, with the trailing comment entry visible)

Web / Desktop (localhost:4444)

Web dock on 7-of-7, Comments question active Web textarea open with comment typed
Question dock on the 7th tab — Any comments? with Selecciona una respuesta placeholder Textarea open with the comment typed in
Web answer rendering after submit Web answered entry in the transcript
Comments answer stored as part of the answered list Comments entry in the answered transcript

Terminal recording

asciicast

Tests

  • packages/core/test/tool-question.test.ts: existing assertions extended for the auto-append; new case asserts the trailing Comments shape.
  • packages/opencode/test/cli/run/question.shared.test.ts: three new cases (single text-only submit, empty-input commit, multi-question advance).
  • packages/opencode/test/tool/question.test.ts: V1 tool expectations updated for the auto-append.
  • fix(core): surface appended Comments question in tool summary commit adds packages/opencode/test/cli/run/scrollback.surface.test.ts, packages/tui/test/util/transcript.test.ts, packages/session-ui/src/components/message-part.test.ts for the summary-view fix.

All passing locally:

$ bun test test/cli/run/question.shared.test.ts test/cli/run/scrollback.surface.test.ts test/tool/question.test.ts
23 pass, 0 fail, 42 expect() calls
$ bun test test/question.test.ts test/tool-question.test.ts
8 pass, 0 fail, 24 expect() calls

bun typecheck is clean across core, opencode, tui, schema, protocol, server, client, sdk/js, app.

Notes for the maintainer

  • The release tag assets/comments-screenshots-2026-07-29 is asset-only (no code commits, no branch). It's a CDN bucket for the screenshots referenced above. Happy to delete it after the PR is reviewed if you prefer.
  • The change is opt-out by reverting the withComments wrap; no schema migration is required.
  • If the team would rather follow the issue's proposal (a comments?: string field + dedicated tab), I can rework on top of this branch—the fixup commit would then become a clean revert.

airvzxf added 2 commits July 29, 2026 14:46
… tool call

Every invocation of the question tool now ends with a final free-form text
question ("Any comments?", header "Comments", textOnly: true). The auto-append
guarantees the runtime always collects feedback regardless of whether the
caller's own questions already used a confirmation step.

Schema additions:
- schema/question.ts (V2) and schema/v1/question.ts: add optional
  textOnly?: boolean to QuestionV2.Info / QuestionInfo. The field stays
  optional so existing prompts decode unchanged; consumers that branch on
  textOnly treat absence as the existing select behavior.

Tool layer:
- core/tool/question.ts: withComments appends a constant COMMENTS_INFO to
  the questions array before the QuestionV2.Service.ask call, and the
  toModelOutput formatter reads the same wrapped list so the model also
  sees the auto-appended question in its reply (with whatever answer the
  user typed, empty string included).
- opencode/tool/question.ts (V1 mirror): same withComments wrap applied to
  the opencode CLI's V1 tool. Both the V1 and V2 runtime paths now behave
  identically.
- Tool description strings updated in both layers to advertise the new
  textOnly flag and the always-on Comments question.

UI rendering:
- tui/routes/session/question.tsx: textOnly memo drives an unconditional
  edit-mode (textarea only, no option list) for those tabs, with the
  editing memo derived as textOnly() || store.editing. Edit-mode bindings
  gain tab navigation so users can still skip to the next question, and
  escape rejects instead of cancelling the edit on a text-only tab.
- opencode/cli/cmd/run/question.shared.ts + footer.question.tsx: the pure
  state machine gains questionTextOnly() and routes questionSelect to
  questionSave on text-only tabs; questionSetTab now takes the request
  and flips editing on when landing on a text-only tab. The footer UI
  renders the textarea directly (no scrollbox) when textOnly is active.

Tests:
- core/test/tool-question.test.ts: existing assertions extended to reflect
  the auto-appended Comments entry; new case asserts the trailing shape.
- opencode/test/cli/run/question.shared.test.ts: three new cases cover
  text-only submit, empty input handling, and the multi-question advance
  path.
- opencode/test/tool/question.test.ts: V1 tool expectations updated for
  the auto-append (2 questions instead of 1).

SDK regenerated via bun run generate (packages/client) and
./packages/sdk/js/script/build.ts.
The auto-appended Comments text question added by `withComments`
(see b77c8ce8f) was invisible in the UI summary views: the scrollback
titles, structured snapshots, transcript JSON, and the timeline's
question list all iterated the original `input.questions` (N items)
but matched against `metadata.answers` (N+1 items), so the trailing
entry and its answer fell off the rendered list.

Three coordinated changes:

1. V1 tool now stores the full list (including Comments) in
   `metadata.questions` alongside `metadata.answers`, so consumers
   have a single source of truth without re-deriving it.

2. Extracted the synthetic Comments literal into a browser-safe
   `COMMENTS_QUESTION_INFO` constant in
   `packages/core/src/tool/question-shared.ts`, re-exported by the
   V1 and V2 tool modules. UI packages (session-ui, tui) and the
   opencode CLI import this constant directly — no more literal
   duplication across the four render paths.

3. Each render path now prefers `metadata.questions` when present
   and falls back to a synthetic Comments entry derived from the
   constant when only `metadata.answers` is available (V2 sessions
   and older V1 sessions persisted before the new metadata field).
Copilot AI review requested due to automatic review settings July 29, 2026 21:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: Add a "Comments" tab before Confirm in the question prompt, and always show "Type your own answer"

2 participants