Skip to content

fix(web): switch to plainText mode for composer due to glitching skill invocation in question tool - #7818

Open
patriksimms wants to merge 3 commits into
pingdotgg:mainfrom
patriksimms:fix/question-answer-plain-input
Open

fix(web): switch to plainText mode for composer due to glitching skill invocation in question tool#7818
patriksimms wants to merge 3 commits into
pingdotgg:mainfrom
patriksimms:fix/question-answer-plain-input

Conversation

@patriksimms

@patriksimms patriksimms commented Aug 21, 2026

Copy link
Copy Markdown

Closes #7805

When a provider asks a question, the custom-answer composer reused the full prompt editor, so $skill syntax turned into skill tokens and opened the picker, even though question responses only ever send plain answer strings. That desynced Lexical cursor state (recursive update crashes), left the picker open after submit, and leaked the previous answer into the next question.

This makes question answers plain text end to end, the way mobile already handles them. The prompt editor gets a plainText mode that renders the value as raw text with no inline-token plugins mounted; with no token nodes, collapsed and expanded cursor offsets coincide, so all cursor mapping reduces to a raw clamp. While a question is active, the chat composer enables that mode and keeps every trigger menu (skills, slash commands, file paths) closed over answers, then re-derives normal composer state from the regular draft when the question ends. The editor remounts when the mode flips, which also stops undo history from leaking between an answer and the main draft.

Compared to #7812 (which this replaces), the shared tokenizer and cursor logic stay untouched, and the fix removes the bug class structurally instead of special-casing skill tokens. The trade-off is intentional: no mention/slash pickers inside question answers, matching mobile.

Tests:

  • 77 focused web tests (composer-logic, composer-editor-mentions, ComposerPromptEditor, composerSubmission, ComposerPendingUserInputPanel)
  • Web typecheck, targeted lint and formatting

Evidence:

Implemented with Anthropic Claude Fable 5 using Claude Code in T3 Code.

🤖 Generated with Claude Code


Note

Medium Risk
Touches composer cursor mapping, remount/focus, and draft vs answer state during pending questions—easy to regress caret, menus, or draft clobbering, but not auth or data-plane.

Overview
Stops pending-question answers from being tokenized as skills/mentions, which previously desynced Lexical cursor state, left pickers open, and leaked answers between questions.

ComposerPromptEditor gains a plainText mode that inserts raw text, skips token plugins, and treats collapsed/expanded cursors as the same offset. The Lexical tree remounts when the mode flips (clearing undo history) and restores focus so a question opening mid-type does not drop keystrokes.

While a question is active, ChatComposer enables that mode, keeps trigger menus closed, and parks the real draft in draftPromptRef so trait/stash writes do not move the answer caret. When the question ends, it restores the draft with token-aware cursor/trigger state.

Reviewed by Cursor Bugbot for commit 9674662. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix glitching skill invocation in question tool by adding plainText mode to ComposerPromptEditor

  • Adds a plainText prop to ComposerPromptEditor in ComposerPromptEditor.tsx. When true, the editor remounts (via a -plain/-rich key suffix), renders prompts as raw text without mention/skill/terminal-context token nodes, and disables token-aware cursor mapping and token-related plugins (arrow, backspace, paste, chip selection).
  • ChatComposer in ChatComposer.tsx sets plainAnswerMode when a pending question is active, passing plainText={true} and skills={[]} to the editor. Trigger menus are suppressed and cursor offsets are raw during this mode.
  • Draft edits (traits, stash restore, external sync) during a question are parked in draftPromptRef so they do not disturb the answer caret. When the question resolves, the draft is restored into promptRef and token-aware behavior resumes.
  • Behavioral Change: $setComposerEditorPrompt now requires a plainText boolean parameter; all internal callers were updated. Editor remounts on mode toggle, with a layout effect restoring focus to end-of-text.

Macroscope summarized 9674662.

Summary:
- Add a plainText mode to ComposerPromptEditor: the value renders as raw
  text with no mention/skill/terminal-context chips and none of the
  inline-token plugins mounted. With no token nodes, collapsed and
  expanded cursor offsets coincide, so cursor mapping reduces to a raw
  clamp. The Lexical editor remounts when the mode flips, which also
  keeps undo history from leaking between an answer and the main draft.
- Enable plainText in ChatComposer while a pending question is active:
  trigger menus (skills, slash commands, file paths) stay closed over
  answers, cursor state uses raw offsets, and composer state is
  re-derived from the regular draft when the question ends.

Rationale:
- Pending question responses only send plain answer strings; nothing is
  invoked. Rendering `$skill` syntax as tokens desynced Lexical cursor
  state (recursive update crashes), left the picker open after submit,
  and leaked answers into the next question. Treating the whole answer
  as plain text, as mobile already does, removes the bug class instead
  of special-casing skill tokens, and leaves the shared tokenizer and
  cursor logic untouched.
- Alternative to the includeSkillTokens flag threading in PR pingdotgg#7812.

Tests:
- vp test run on composer-logic, composer-editor-mentions,
  ComposerPromptEditor, composerSubmission, and
  ComposerPendingUserInputPanel suites (77 passed)
- web typecheck (tsgo) and vp lint on both changed files

Closes pingdotgg#7805

AI-Assisted-By: Codex
AI-Assisted: true
AI-Agent: claude-code
AI-Model: anthropic/claude-fable-5
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d57dc08-98bc-469e-803f-5f2e4683ad10

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 21, 2026
@patriksimms patriksimms changed the title fix(web): answer agent questions with a plain text composer fix(web): composer in question tool uses plain text only Aug 21, 2026
Comment thread apps/web/src/components/chat/ChatComposer.tsx
Comment thread apps/web/src/components/ComposerPromptEditor.tsx
@macroscopeapp

macroscopeapp Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces significant runtime behavior changes including editor remounting, focus management, and conditional plugin rendering for question-answer mode. The changes affect complex cursor and state management logic in core composer components and warrant human review.

You can add or adjust custom eligibility rules. Learn more.

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

UI consistency review: one interaction regression found in apps/web/src/components/ComposerPromptEditor.tsx (editor remount on mode flip drops composer focus). Details inline.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/ComposerPromptEditor.tsx
@patriksimms patriksimms changed the title fix(web): composer in question tool uses plain text only fix(web): switch to plainText mode for composer due to glitching skill invocation in question tool Aug 21, 2026
Summary:
- Add a draftPromptRef in ChatComposer that always tracks the draft
  prompt; promptRef keeps meaning "what the editor shows" (the answer
  text while a question is open).
- Ref-sync and pending-sync effects no longer clamp or reset the answer
  caret when the draft changes underneath an open question; the
  question-ended handoff reads the draft from the ref instead of a
  `prompt` effect dep.
- Trait toggles and stash restore now write the parked draft without
  moving the answer caret or stealing focus; stash restore also appends
  to the actual draft instead of the visible answer text.
- ComposerPromptEditor records focus ownership when the plainText flip
  unmounts the editor and refocuses the remounted instance, so a
  question opening or resolving mid-typing no longer drops focus.

Rationale:
- PR pingdotgg#7818 review bots (Cursor Bugbot, Macroscope) flagged two real
  regressions: draft writes yanked the caret to the end of the answer,
  and the keyed LexicalComposer remount silently dropped focus (closing
  the keyboard on mobile).
- Kept the deliberate remount and restored focus across it instead of
  rewriting editor state in place; smaller change, same behavior.

Tests:
- vp test run src/components/ComposerPromptEditor.test.ts (5 passed)
- tsc --noEmit on apps/web clean; oxlint on both files clean
- Focus behavior not covered by jsdom tests (needs real browser focus
  semantics); not verified in a browser

AI-Assisted-By: Codex
AI-Assisted: true
AI-Agent: claude-code
AI-Model: anthropic/claude-fable-5

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fdea833. Configure here.

Comment thread apps/web/src/components/ComposerPromptEditor.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new plainText plugin gate also disables the non-token surround-selection typing behavior for question answers. Details inline.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/ComposerPromptEditor.tsx Outdated
…wers

Summary:
- The focus restore after a plainText remount now places the caret at
  the end of the current value instead of the snapshot cursor, which
  was seeded from the previous mode's stale cursor prop. Both mode
  transitions settle the caret at the end anyway, so this removes the
  brief window where a keystroke could land at a stale offset.
- ComposerSurroundSelectionPlugin is mounted in both modes: wrapping a
  selection by typing brackets/quotes is plain typing behavior, not
  token behavior. The plugin takes a plainText prop and uses raw cursor
  clamps in plain mode; the mention-boundary guard is skipped there so
  answer text that merely looks like a mention still wraps.

Rationale:
- Follow-up to PR pingdotgg#7818 bot re-review: Cursor Bugbot flagged the stale
  caret on mode remount, Macroscope flagged the surround-typing
  regression for question answers introduced by the plugin gate.

Tests:
- vp test run src/components/ComposerPromptEditor.test.ts (5 passed)
- tsc --noEmit on apps/web clean; oxlint on both touched files clean

AI-Assisted-By: Codex
AI-Assisted: true
AI-Agent: claude-code
AI-Model: anthropic/claude-fable-5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: Dollar Skill invocation in question tool UI glitches out

1 participant