Skip to content

Fix Claude AskUserQuestion handling for multiple prompts#6

Merged
OpenSource03 merged 3 commits intomasterfrom
copilot/fix-claude-engine-multiple-answers
Mar 7, 2026
Merged

Fix Claude AskUserQuestion handling for multiple prompts#6
OpenSource03 merged 3 commits intomasterfrom
copilot/fix-claude-engine-multiple-answers

Conversation

Copy link
Contributor

Copilot AI commented Mar 7, 2026

Summary

  • Fixes a Claude-only regression where multi-question AskUserQuestion prompts could share selection state, causing only one question to retain an answer at a time.
  • Uses stable per-question keys for rendering and answer lookup when Claude does not provide question IDs, including the question-{index} fallback path.
  • Narrows getAskUserQuestionAnswer to the relevant ToolUseResult shape and adds regression tests covering no-id multi-question answers via answersByQuestionId.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that changes existing behavior)
  • 🎨 UI / design improvement
  • ⚡ Performance improvement
  • ♻️ Refactor (no functional changes)
  • 🧪 Tests / CI
  • 📝 Documentation

Related Issues

How to Test

  1. In a Claude session, trigger an AskUserQuestion tool call with multiple questions and no explicit question IDs.
  2. Select different answers for each question and submit, including a case where one question uses free text.
  3. Confirm each question retains and renders its own answer instead of collapsing to a single shared selection, then run corepack pnpm test and corepack pnpm build:electron && corepack pnpm exec vite build.

Screenshots / Screen Recording

https://github.com/user-attachments/assets/b5cffa90-81c9-45bf-8bf5-f8980d742722

Checklist

  • I've tested this on macOS (required for Electron/native features)
  • TypeScript compiles with no errors (pnpm build)
  • No any types introduced
  • Logical margins used (ms-*/me-* instead of ml-*/mr-*)
  • User-generated content containers have wrap-break-word
  • New shared types go in shared/types/, not src/types/
  • Large components/hooks are decomposed into sub-components/sub-hooks if needed
Original prompt

There is a bug. In claude engine as it uses ask question tool, if it asks multiple questions, I am able to select only one answer.

The expected behavior is that it should be possible to select an answer for each question.

This bug is only in Claude. Works well in Codex.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: OpenSource03 <29690431+OpenSource03@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix bug in Claude engine for selecting answers to multiple questions Fix Claude AskUserQuestion handling for multiple prompts Mar 7, 2026
@OpenSource03 OpenSource03 requested a review from Copilot March 7, 2026 04:03
@OpenSource03
Copy link
Owner

@codex review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a Claude-specific regression in AskUserQuestion where multiple prompts could not maintain independent selection state, and improves answer rendering to support stable per-question keys (even when Claude does not provide IDs).

Changes:

  • Generate stable per-question keys (ID when present, otherwise question-{index}) to prevent shared selection state across multiple questions.
  • Add a shared helper to resolve/display answers from either question text keys or answersByQuestionId.
  • Add focused unit tests and expand Vitest config to include src/**/*.test.{ts,tsx} with the needed path alias.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vitest.config.electron.ts Expands test discovery to src tests and adds @/ alias for Vitest.
src/types/protocol.ts Adds optional answersByQuestionId to tool result typing.
src/lib/ask-user-question.ts Introduces shared key/answer resolution helpers for AskUserQuestion.
src/lib/ask-user-question.test.ts Adds regression unit tests for keying/answer lookup behavior.
src/components/tool-renderers/AskUserQuestion.tsx Uses shared helper for answer rendering.
src/components/PermissionPrompt.tsx Fixes multi-question selection state by keying selections/free-text by stable question key.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 43 to 47
<div className="mt-1.5">
<span className="text-[11px] text-foreground/40">Answer: </span>
<span className="text-[12px] text-foreground/80">
{(() => {
const direct = answers?.[q.question];
if (typeof direct === "string" && direct.trim()) return direct;
// Fallback for edge cases where question text keys differ
const indexed = orderedAnswers[qi];
if (typeof indexed === "string" && indexed.trim()) return indexed;
return "No answer captured";
})()}
{getAskUserQuestionAnswer(q, qi, message.toolResult)}
</span>
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

Within this questions.map render, the wrapper uses key={q.question}. If two questions have the same text (or if text changes), React can reuse DOM/state incorrectly; with multi-question prompts it’s safer to key by a stable unique identifier (question id when present, otherwise the same fallback key you use for answers/selections).

Copilot uses AI. Check for mistakes.
Copy link
Owner

Choose a reason for hiding this comment

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

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is already applied in baeb516 — the renderer now uses getAskUserQuestionKey(q, qi) instead of q.question, so duplicate or changing question text will not reuse the wrong row state. I re-ran the targeted tests plus full test/build validation on the current branch before replying. Screenshot: https://github.com/user-attachments/assets/b5cffa90-81c9-45bf-8bf5-f8980d742722

Comment on lines +39 to +45
export function getAskUserQuestionAnswer(
question: AskUserQuestion,
index: number,
toolResult?: Record<string, unknown>,
): string {
const answers = asRecord(toolResult?.answers);
const answersByQuestionId = asRecord(toolResult?.answersByQuestionId);
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

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

getAskUserQuestionAnswer takes toolResult?: Record<string, unknown>, but call sites pass UIMessage["toolResult"] (a ToolUseResult). In strict TS this isn’t assignable to Record<string, unknown> (no index signature), so this should be typed to accept ToolUseResult/a narrower shape like { answers?: unknown; answersByQuestionId?: unknown } (or unknown) instead of Record.

Copilot uses AI. Check for mistakes.
Copy link
Owner

Choose a reason for hiding this comment

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

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is already applied in baeb516getAskUserQuestionAnswer now accepts Pick<ToolUseResult, "answers" | "answersByQuestionId">, which matches the message.toolResult shape used at the call site instead of requiring a broad Record<string, unknown>. I re-ran the targeted AskUserQuestion test plus full test/build validation on the current branch before replying. Screenshot: https://github.com/user-attachments/assets/b5cffa90-81c9-45bf-8bf5-f8980d742722

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. You're on a roll.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@OpenSource03
Copy link
Owner

@copilot can we make sure this will not happen again with proper tests?

Co-authored-by: OpenSource03 <29690431+OpenSource03@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 7, 2026

@copilot can we make sure this will not happen again with proper tests?

Added stronger regression coverage in baeb516. The tests now cover the Claude no-id multi-question path directly, including separate question-0 / question-1 answers and the result-shaping logic used by the prompt, so this specific failure mode is locked in. Screenshot: https://github.com/user-attachments/assets/b5cffa90-81c9-45bf-8bf5-f8980d742722

@OpenSource03 OpenSource03 marked this pull request as ready for review March 7, 2026 22:11
@OpenSource03 OpenSource03 merged commit 25cef89 into master Mar 7, 2026
2 checks passed
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: baeb51637b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


export function getAskUserQuestionKey(question: AskUserQuestion, index: number): string {
const id = typeof question.id === "string" ? question.id.trim() : "";
return id || `question-${index}`;

Choose a reason for hiding this comment

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

P2 Badge Namespace fallback AskUserQuestion keys to avoid id collisions

Using question-${index} as the fallback key can collide with a real question id from upstream (for example, one question has id question-1 while another question at index 1 has no id). In that mixed-id case, both questions share the same lookup key, so selections/answersByQuestionId overwrite each other and only one answer is retained. This reintroduces the multi-question loss bug for any payload where explicit ids overlap the fallback format.

Useful? React with 👍 / 👎.

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.

3 participants