You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
workspace,studio: offer the person's likely next message in an empty box - #191
After a chat's turn ends, the empty reply box can now show one suggested next message, in gray where "Talk to Instrument" usually is, with a small Tab key after it. Tab, or a click on the key, puts it in as your own words, ready to send or change. Typing anything hides it, and it never sends by itself.
How it's made
When a chat settles (its agent and every task are done), the app asks the model the last reply ran on what you'd most likely send next.
The ask is the last reply's own request again (same messages, tools and cache session) with one instruction added after it, so the provider's cache covers the conversation and the call only adds the instruction and a one-line answer. It's the same trick the context-rollover summary already uses.
The suggestion lives in memory on this computer and reaches the window through a new chats.live.nextMessage stream. Sending a message or a new turn starting takes it away.
Each ask shows in Settings › Activity as "Suggested reply".
When it doesn't suggest
Code skips the ask entirely when:
you stopped the turn yourself;
a card is waiting on you (permission, sign-in, a question);
the last reply failed;
something in the chat is still running (it only runs once the chat settles).
The model answers NONE, and code shows nothing, when:
the agent's last message asked you something, even in passing;
something failed;
you just said thanks or goodbye;
it would mean guessing at someone else's private life.
Code also drops an answer that's empty, longer than 120 characters, or talks about the suggestion instead of being one. In Studio it's shown only in the chat's own box, and not while you're replying to a specific message, dictating, or have something attached.
The instruction
It's NEXT_MESSAGE_INSTRUCTION in packages/workspace/src/lib/chat/next-message.ts. It started from a replay over 41 real chats, then was loosened to suggest on most turns, since a wrong suggestion costs nothing when you have to take it.
Answers were 5 to 25 output tokens. Examples: "What about a lightweight rain shell option instead of a jacket?", "Which shoes do you pack when yours don't have any waterproof ones?". GLM once invented "What's on my calendar tomorrow?" after a thank-you.
Not done yet
Not checked in the running app. The gray line's alignment with the box's first line is only tested in jsdom.
Not tried on ChatGPT or OpenRouter models.
No back-off when suggestions keep being ignored, and no setting to turn it off.
Summary by CodeRabbit
New Features
Chats can display an AI-generated suggested reply in the message composer when it’s empty and no reply is selected.
Accept a suggestion with Tab or its on-screen control. The suggestion is hidden while you type and can reappear after you clear the composer.
Suggestions are unavailable when attachments are present, a reply is selected, or the chat is actively working.
Once a chat settles, the app asks the model its last reply ran on what
the person would most likely send next, and the chat's empty box shows
it in gray where the placeholder goes, with a Tab key after it. Tab, or a
click on the key, puts it in as the person's words to send or change;
typing anything puts it away, and a new message or turn takes it back.
The ask is the last reply's own request again, its messages, tools and
cache session, with one instruction after it, so the provider's cache
serves the conversation and the call adds the instruction and a line.
It is not asked when the person stopped the turn, a card or question
waits on them, or the reply failed, and the model answers NONE after a
question, a failure, or a thank-you. The suggestion is kept in memory on
this computer and reaches the window through `chats.live.nextMessage`;
the request is logged as "Suggested reply".
Rejected: the decision model | not everyone has it; the chat's own model always answers
Rejected: a separate prompt over a text rendering of the chat | none of it is cached, and it is not the voice the chat has
Rejected: two or three chips under the reply | one gray line in the box is quieter, and a press never sends it
Rejected: staying quiet after greetings and when the next step is unclear | a suggestion the person has to take costs nothing when wrong
Commits-to: a suggestion is never sent without the person taking it and sending it
Commits-to: the ask reuses the last reply's request byte for byte up to its instruction
Tested: evals/cases/next-message.ts, 2 trials each: Workers AI glm-5.3-flash offers one after a finished answer 2/2, none after thanks 1/2 (once invented "What's on my calendar tomorrow?"); Claude Haiku 5.5 via the Claude account 1/2 and 2/2, 24,185 of about 29,700 input tokens read from the cache, 5 to 25 output tokens
Tested: the instruction's rules replayed over 41 real chats on Haiku 5.5 before it moved into the request
Not-tested: seen in the running app; the overlay's alignment with the box's first line is checked only in jsdom
Not-tested: ChatGPT and OpenRouter models, and backing off after suggestions left untaken
The change generates suggestions for the next user message after eligible chat settlements. It exposes suggestions through a live chat route and offers them in the composer when the draft is empty and eligible. It also adds evaluation cases and tests for suggestion parsing and editor behavior.
Changes: Next-message suggestions
Layer / File(s)
Summary
Generate and validate suggestions packages/workspace/src/lib/chat/next-message.ts, packages/workspace/src/lib/chat/attach.ts, packages/workspace/src/lib/chat/next-message.test.ts, packages/workspace/src/lib/activity/schema.ts, apps/studio/src/client/components/settings/activity-section.tsx, packages/workspace/evals/cases/*
Chat attachment starts suggestion generation for eligible settlements. The generator prepares model input, parses the response, records usage, and publishes valid suggestions. Evaluation cases and unit tests cover generation and parsing.
Expose suggestions through the live chat route packages/workspace/src/rpc/publisher.ts, packages/workspace/src/rpc/routes/chats.ts
The new publisher event identifies a chat with an updated suggestion. The live route returns the current suggestion or null and rereads after matching events or chat message changes.
Offer and accept suggestions in the composer apps/studio/src/client/components/task/chat.tsx, apps/studio/src/client/components/prompt-input.tsx, apps/studio/src/client/components/prompt-editor.tsx, apps/studio/src/client/components/prompt-editor-suggestion.test.tsx
The chat passes suggestions to eligible prompt inputs. The editor displays an offer when the document is empty and dictation is inactive, and accepts it through Tab or a button. Tests cover display, acceptance, and visibility updates.
sequenceDiagram
participant ChatSettlement
participant SuggestionGenerator
participant AIGateway
participant LiveChatRoute
participant ChatConversation
participant PromptEditor
ChatSettlement->>SuggestionGenerator: start generation for an eligible settlement
SuggestionGenerator->>AIGateway: request a next-message suggestion
AIGateway-->>SuggestionGenerator: return answer and usage
SuggestionGenerator->>LiveChatRoute: publish chat.nextMessage when valid
LiveChatRoute-->>ChatConversation: stream the current suggestion
ChatConversation->>PromptEditor: pass suggestion to an eligible prompt input
PromptEditor-->>ChatConversation: insert suggestion on Tab or button click
Loading
Possibly related PRs
instrument-org/instrument#158: Adds dictation state and composer behavior that determines when the suggestion offer is hidden.
instrument-org/instrument#185: Changes when an asks.choose card ends a turn; this relates to settled-chat eligibility and open-question checks.
instrument-org/instrument#172: Changes prepareModelMessages, which next-message generation calls to prepare model input.
Merge Risk: Moderate · previous review 39b71
Suggestion generation can change which chat history the next turn uses, and outdated suggestions can appear in the composer. Fix those behaviors and remove the conversation-derived log before merging.
Pre-merge checks: 4 · 1
Failed checks: 1 warning
Check name
Status
Explanation
Resolution
Docstring Coverage
Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta…
Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed checks: 4 passed
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
The title names two of the main changes: a suggested next message (workspace and Studio) and its display in an empty input box. It is a real, specific summary of the feature. It does not name the Tab-…
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Title check
Explanation
The title names two of the main changes: a suggested next message (workspace and Studio) and its display in an empty input box. It is a real, specific summary of the feature. It does not name the Tab-to-accept behavior, the Activity log entry, or the in-memory storage, which is acceptable because a title need not cover every detail.
Full details: Docstring Coverage
Explanation
Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 9 functions across 13 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
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.
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
The next-message ask prepares its request read-only: where the request
would first record a model change, a rollover or a tool-result clearing,
`prepareModelMessages` refuses and no suggestion is made, so the side
call never reshapes the history the person's next turn is sent with. A
request about to be reshaped is one the cache no longer serves anyway.
Each chat's latest settle is kept, and an ask a later settle overtook
publishes nothing. Studio hides the suggestion while a sent message is
still on its way to the records, and a debug line printing the model's
answer is gone.
Rejected: rebuilding `empty` when the editor view is built | the view is built once at mount, from the same default value the state starts from
Rejected: guarding the baseline rewrite too | it is due only after a rollover, refused first, or for a baseline older than the build that just wrote the reply
Commits-to: a side call built from a turn's request records nothing in the chat
Review: CodeRabbit on #191
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
After a chat's turn ends, the empty reply box can now show one suggested next message, in gray where "Talk to Instrument" usually is, with a small Tab key after it. Tab, or a click on the key, puts it in as your own words, ready to send or change. Typing anything hides it, and it never sends by itself.
How it's made
chats.live.nextMessagestream. Sending a message or a new turn starting takes it away.When it doesn't suggest
Code skips the ask entirely when:
The model answers
NONE, and code shows nothing, when:Code also drops an answer that's empty, longer than 120 characters, or talks about the suggestion instead of being one. In Studio it's shown only in the chat's own box, and not while you're replying to a specific message, dictating, or have something attached.
The instruction
It's
NEXT_MESSAGE_INSTRUCTIONinpackages/workspace/src/lib/chat/next-message.ts. It started from a replay over 41 real chats, then was loosened to suggest on most turns, since a wrong suggestion costs nothing when you have to take it.Evals (
evals/cases/next-message.ts, 2 trials each)Answers were 5 to 25 output tokens. Examples: "What about a lightweight rain shell option instead of a jacket?", "Which shoes do you pack when yours don't have any waterproof ones?". GLM once invented "What's on my calendar tomorrow?" after a thank-you.
Not done yet
Summary by CodeRabbit