Skip to content

fix(status): treat slash-command and bash user-role lines as synthetic#112

Merged
graykode merged 2 commits into
graykode:mainfrom
BruceWW:fix/think_status
May 10, 2026
Merged

fix(status): treat slash-command and bash user-role lines as synthetic#112
graykode merged 2 commits into
graykode:mainfrom
BruceWW:fix/think_status

Conversation

@BruceWW
Copy link
Copy Markdown
Contributor

@BruceWW BruceWW commented May 9, 2026

Sessions could pin in Thinking ("◉ Think generating reply") forever after /plugin update (and other pure-local slash commands or !bash invocations). Claude Code flushes 2-3 user-role lines for these — a <local-command-caveat> (isMeta:true), a <command-name> line, and a <local-command-stdout> line — none of which prompt the model, so no assistant reply ever arrives to clear last_user_ts_ms.

is_tool_result_user_msg only filtered tool_result block arrays and let every string-content user line through, so the trailing local- command line opened a thinking window that never closed.

Rename to is_synthetic_user_msg and additionally treat as synthetic:

  • entries with isMeta: true
  • string content starting with <local-command-stdout|stderr|caveat>,   <command-name>, or <bash-input|stdout|stderr>

Also skip these lines when extracting the session's initial_prompt so the title isn't a <command-name>/plugin... dump.

Add regression tests for the /plugin three-line sequence and the !bash <bash-input>/<bash-stdout> sequence.

Sessions could pin in Thinking ("◉ Think generating reply") forever
after `/plugin update` (and other pure-local slash commands or `!bash`
invocations). Claude Code flushes 2-3 user-role lines for these — a
`<local-command-caveat>` (isMeta:true), a `<command-name>` line, and a
`<local-command-stdout>` line — none of which prompt the model, so no
assistant reply ever arrives to clear `last_user_ts_ms`.

`is_tool_result_user_msg` only filtered tool_result block arrays and
let every string-content user line through, so the trailing local-
command line opened a thinking window that never closed.

Rename to `is_synthetic_user_msg` and additionally treat as synthetic:
- entries with `isMeta: true`
- string content starting with `<local-command-stdout|stderr|caveat>`,
  `<command-name>`, or `<bash-input|stdout|stderr>`

Also skip these lines when extracting the session's initial_prompt so
the title isn't a `<command-name>/plugin...` dump.

Add regression tests for the /plugin three-line sequence and the
`!bash` `<bash-input>/<bash-stdout>` sequence.
Copy link
Copy Markdown
Owner

@graykode graykode left a comment

Choose a reason for hiding this comment

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

lgtm — security clean (single-file parser refactor, no new deps/network/shell). the rename to is_synthetic_user_msg and lifting it to take the whole entry reads right since isMeta lives at the entry level, and keeping the "all blocks are tool_result" check conservative (mixed → still a real prompt) preserves the prior safety. nice catch also gating initial_prompt extraction so titles don't end up as <command-name>/plugin... or a bash stdout dump. the two regression tests exercise the exact 3-line /plugin sequence and the <bash-input>/<bash-stdout> pair from the bug report. merged main locally and cargo test is green (123/123).

@graykode graykode merged commit 84dbf17 into graykode:main May 10, 2026
7 checks passed
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.

2 participants