Skip to content

Fix token-split message issue on session reload#7962

Closed
jh-block wants to merge 2 commits into
mainfrom
jhugo/fix-token-split-msgs
Closed

Fix token-split message issue on session reload#7962
jh-block wants to merge 2 commits into
mainfrom
jhugo/fix-token-split-msgs

Conversation

@jh-block
Copy link
Copy Markdown
Collaborator

Summary

Fixed regression from commit bc7e063 where each streaming text delta was individually persisted to the database, causing every token to appear as a separate message when reopening Goose.

Instead of immediately persisting each text delta, the fix accumulates text messages in a buffer and flushes the final complete message:

  • Before tool request processing transitions from text to tools
  • After the stream loop ends (for text-only responses)

This preserves live streaming UI updates while ensuring only the final message is stored in the database.

Testing

Existing tests pass (176 passed). Manual testing confirms streaming messages no longer split into individual tokens on session reload.

Related Issues

Regression from #7850

After streaming completion, accumulate text deltas in a buffer instead of
persisting each one individually. This prevents each token from appearing
as a separate message when reopening Goose. The pending message is flushed
when tool requests are encountered or after the stream ends.

Fixes the regression from commit bc7e063.
Copy link
Copy Markdown

@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: af13ebd850

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/goose/src/agents/agent.rs
Each streaming text delta only contains a single token/word, not the full
text. The previous fix stored the last delta message, which would truncate
the response to just the final token. Now we accumulate all delta text
into a buffer and replace the message content with the full text at flush.
Copy link
Copy Markdown

@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: 7e238a76fd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// Flush any pending text message before processing tool requests
if let Some(mut text_msg) = pending_text_message.take() {
// Replace delta content with full accumulated text
text_msg.content = vec![MessageContent::text(&accumulated_text)];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve non-text assistant content when flushing text buffer

Replacing text_msg.content with a single Text block drops any non-text assistant content that arrived in the buffered message. This is observable with providers that stream reasoning separately from text (for example, responses_api_to_streaming_message can emit a final no-tool message containing MessageContent::Reasoning), so after this flush the persisted conversation loses reasoning data on reload and for subsequent turns even though downstream formatters (e.g. OpenAI formatting) consume reasoning content when present.

Useful? React with 👍 / 👎.

@jh-block jh-block closed this Mar 17, 2026
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.

1 participant