Skip to content

fix(google): keep thought parts out of visible text - #1508

Merged
lidge-jun merged 3 commits into
devfrom
agent/fix-1503-google-thought-visibility
Aug 12, 2026
Merged

fix(google): keep thought parts out of visible text#1508
lidge-jun merged 3 commits into
devfrom
agent/fix-1503-google-thought-visibility

Conversation

@Ingwannu

@Ingwannu Ingwannu commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • Keep Google response parts marked thought: true out of ordinary assistant text in both SSE and buffered JSON parsing.
  • Route provider-marked thought text through reasoning_raw_delta while preserving ordinary text, function-call ordering, inline images, and Antigravity/Vertex thought-signature observation.
  • Share one classifier across both response modes and document the visibility boundary and decision rationale.

Closes #1503

Verification

  • bun test tests/google-hardening.test.ts tests/google-antigravity-wire.test.ts tests/google-vertex-thought-signature.test.ts — 81 passed, 0 failed.
  • bun run typecheck — passed.
  • bun run privacy:scan — passed.
  • bun run test — the repository-wide run reached the 600-second local resource limit before completion. The new Google regressions passed in that run; unrelated existing timing/environment failures were observed in Claude replay, native-main ownership, server auth, and npm-cache preflight tests. A focused rerun of those unrelated files still reproduced baseline failures and did not involve the Google adapter paths changed here.
  • All local checks ran with a 2-CPU, 8-GB memory cap.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features

    • Google responses now distinguish internal thought text from visible assistant messages.
    • Thought content is surfaced as reasoning events while ordinary text remains visible.
    • Streaming and non-streaming responses now apply the same classification consistently.
  • Bug Fixes

    • Prevented thought-only content from appearing as visible text.
    • Improved handling of response ordering and suppressed unnecessary synthetic heartbeats.
  • Documentation

    • Documented Google thought-text visibility and reasoning behavior.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 548793f9-3909-44e2-b616-d47fdd57a3c1

📥 Commits

Reviewing files that changed from the base of the PR and between 4e0ffb2 and e0d2df3.

📒 Files selected for processing (4)
  • src/adapters/google.ts
  • structure/04_transports-and-sidecars.md
  • tests/google-antigravity-wire.test.ts
  • tests/google-hardening.test.ts

📝 Walkthrough

Walkthrough

The Google adapter now preserves the thought flag on response parts and emits thought text as reasoning_raw_delta events in streaming and buffered parsing. Tests cover visibility, ordering, heartbeat suppression, and thought-signature replay. Documentation describes the behavior.

Changes

Google thought-text handling

Layer / File(s) Summary
Shared thought-aware event classification
src/adapters/google.ts
GoogleResponsePart models the optional thought flag. googlePartTextEvent emits reasoning_raw_delta for thought text and text_delta for ordinary text. Streaming and buffered parsers use the shared classifier.
Visibility, ordering, and signature validation
tests/google-antigravity-wire.test.ts, tests/google-hardening.test.ts, structure/04_transports-and-sidecars.md
Tests verify reasoning output, ordinary-text visibility, ordering before function calls, heartbeat suppression, and thought-signature replay. Documentation records the shared streaming and buffered behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GoogleResponse
  participant GoogleAdapter
  participant ResponseEvents
  GoogleResponse->>GoogleAdapter: return streaming or buffered response part
  GoogleAdapter->>GoogleAdapter: inspect thought flag
  GoogleAdapter->>ResponseEvents: emit reasoning_raw_delta for thought text
  GoogleAdapter->>ResponseEvents: emit text_delta for ordinary text
Loading

Possibly related PRs

Suggested reviewers: lidge-jun

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The adapter, shared classifier, documentation, and regression tests satisfy issue #1503 for both parsing modes and preserve text, tool ordering, and signature replay.
Out of Scope Changes check ✅ Passed All changes support issue #1503 by modifying Google parsing, documenting the behavior, and adding focused regression tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: excluding Google thought parts from visible text.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/fix-1503-google-thought-visibility

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 the bug Something isn't working label Aug 12, 2026
@Ingwannu
Ingwannu requested review from Wibias and lidge-jun August 12, 2026 02:55
@Ingwannu
Ingwannu force-pushed the agent/fix-1503-google-thought-visibility branch from 320f905 to b3ba283 Compare August 12, 2026 03:11

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

First review on exact head b3ba2838e2d226cd7967e2a17b0545f8a653d260.

The implementation matches #1503's visibility-boundary requirement. The shared classifier maps text-bearing thought: true parts to reasoning_raw_delta in both SSE and buffered JSON parsing, ordinary text remains text_delta, and function-call ordering remains intact. The focused regressions exercise standalone thought text, thought-before-tool ordering, ordinary visible text, and both response modes. I did not find a code-level blocker in this patch.

The exact-head validation is also real here: Cross-platform CI completed successfully with 18 jobs, including the macOS test job and the gates job, and React Doctor completed successfully.

The only remaining blocker is integration freshness. Current dev is 70d2e1758c180188a729dd63812703b76cfeeba6; this head is 11 commits behind with merge base 4fed8d3fe431ad23be83f3aff2af18ef8b8ecd71. The intervening production changes do not touch src/adapters/google.ts or the focused Google test, but the combined tree has not been exercised by CI, and structure/04_transports-and-sidecars.md has advanced on dev.

Please rebase onto current dev and rerun exact-head CI. If the integrated diff remains equivalent and CI stays green, I see no remaining blocker and would approve on re-review.

@Ingwannu
Ingwannu force-pushed the agent/fix-1503-google-thought-visibility branch from b3ba283 to 219e7f3 Compare August 12, 2026 07:17
@Ingwannu

Copy link
Copy Markdown
Owner Author

Rebased onto current dev@fd59bd2708c0594fd749bc75ed4aad5528b30ca8 as exact head 219e7f365a7cf4ce8334dc9216880d0921a04a53. The rebase was conflict-free. Local exact-head validation is green: tests/google-hardening.test.ts 29/29, bun run typecheck, bun run privacy:scan, and git diff --check. GitHub CI is rerunning on the integrated head; I will leave this draft and wait for independent re-review rather than self-approving or merging.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor

The current dev head is now d5824814853eea68ceb4417403b22000a935cef8, while this PR head is 219e7f365a... and remains 11 commits behind. The latest exact-head CI run completed all other jobs but macOS failed in the unrelated Cursor blob ID key channel bounds test (11,304 passed, 8 skipped, 1 failed; timeout after 10s). Please rebase this maintainer-owned branch onto current dev and rerun exact-head CI; I will not force-push a branch I do not own.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor

I prepared a current fork-side integration candidate without touching the maintainer-owned PR branch. Fork branch Yuxin-Qiao:codex/fix-1503-google-thought-visibility-rebased is now rebased onto dev@cbbfdd8773e68a5dc2391ddeb32f33a225373c1a at head a3b8a389a412. Exact-head local proof: tests/google-hardening.test.ts 29/29, typecheck, privacy scan, and diff check passed. Please rebase/cherry-pick this candidate into #1508 and rerun CI; I will not force-push the maintainer-owned branch.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor

Correction to my previous status note: the repository dev head has since advanced to cbbfdd8773e68a5dc2391ddeb32f33a225373c1a. The current fork-side candidate remains Yuxin-Qiao:codex/fix-1503-google-thought-visibility-rebased@a3b8a389a412, rebased onto that head and locally verified with 29/29 Google hardening tests, typecheck, privacy scan, and diff check. The maintainer-owned #1508 branch is still untouched; please rebase it onto the current dev and rerun CI there.

Yuxin-Qiao commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Superseded by the final current-dev update below. The authoritative fork-side candidate is now based on dev@59da369f1aba7996c518a72ff6c3add04aa2cedb at head 091933282; the earlier 84c012243/203545dc7 note is retained only as historical progress.

Copy link
Copy Markdown
Contributor

Updated candidate after the final current-dev rebase:

Base: dev@59da369f1aba7996c518a72ff6c3add04aa2cedb
Head: 091933282 on fork branch codex/fix-1503-google-thought-visibility-rebased.

Post-rebase proof: all three Google regression files passed — 81 tests, 0 failures, 226 expect calls; typecheck, privacy scan, and diff check passed. Please cherry-pick 091933282 or rebase the maintainer branch to it and rerun CI. I did not rewrite the maintainer-owned branch.

Copy link
Copy Markdown
Contributor

Current candidate for this maintainer-owned PR: rebased onto upstream dev@abe82212a7983cb5b5e97d94e958843068303241, fork head 95bad7ede on codex/fix-1503-google-thought-visibility-rebased.

Post-rebase proof: Google hardening, Antigravity wire, and Vertex thought-signature tests 81 passed, 0 failed, 226 expect calls; typecheck, privacy scan, and diff check passed. Please cherry-pick/rebase this candidate into the maintainer branch and rerun exact-head CI. I have not rewritten the maintainer-owned branch.

…hought parts

Two contracts the thought-visibility change touches implicitly, made
explicit so neither can drift.

emittedContentEvent decides content vs continue, and its only consumer is
the synthetic-heartbeat suppression in the read loop. A thought delta is
real upstream activity, so it must count as content — emitting a heartbeat
alongside it would claim the stream was idle while the model was working.
The visible-text case is asserted next to it as the control.

Gemini 3 rejects a follow-up turn whose first function-call part lost its
thoughtSignature, so a classification change that also dropped replay
would trade a visible-text bug for a hard 400. The new case observes a
payload mixing a thought part with a signed function call and asserts the
signature is still replayed, rather than inferring safety from unrelated
fixtures that happen to still pass.
@lidge-jun

Copy link
Copy Markdown
Owner

Reviewed and verified this against current dev. The classifier is correct and the shared googlePartTextEvent helper is the right shape: one decision point for both parsers, so they cannot drift.

I pushed two tests on top of your commits rather than changing your implementation, because the change touches two contracts implicitly and neither was pinned:

  1. Heartbeat classification. emittedContentEvent decides "content" vs "continue", and its only consumer is the synthetic-heartbeat suppression in the read loop. Setting it for reasoning_raw_delta is the right call — a thought delta is real upstream activity, and emitting a heartbeat alongside it would claim the stream was idle while the model was demonstrably working. I initially thought this was a defect and was wrong; reading the consumer settled it. The test now pins that decision, with the visible-text case next to it as the control.

  2. Thought-signature replay. Gemini 3 returns 400 when the first function-call part of a step loses its thoughtSignature, so a classification change that also disturbed replay would trade a visible-text bug for a hard failure. The existing fixtures pass, but they do not exercise a payload that mixes a thought part with a signed function call. The new case does, and asserts the signature is still replayed.

Verification at the merged head (e0d2df3b3, your branch merged with current dev), on a Linux runner with Bun 1.3.14:

  • bun x tsc --noEmit — exit 0
  • bun test tests/google-hardening.test.ts tests/google-antigravity-wire.test.ts — 79 pass, 0 fail

Red-before check for the new tests: reverting only src/adapters/google.ts to origin/dev makes 2 of them fail, so they exercise your change rather than passing vacuously.

Marking ready for review.

@lidge-jun
lidge-jun marked this pull request as ready for review August 12, 2026 11:12

Copy link
Copy Markdown
Contributor

Final current candidate: upstream dev@4e0ffb2cbef0d3724a3aa9ebef26279aed44b694, fork head 00edd24e8 on codex/fix-1503-google-thought-visibility-rebased.

Final local proof: 81/81 Google/Antigravity/Vertex tests, 226 expect calls, plus typecheck, privacy scan, and diff check. Please cherry-pick/rebase this candidate into the maintainer-owned branch and rerun exact-head CI; the maintainer branch remains untouched.

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

Copy link
Copy Markdown

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: e0d2df3b35

ℹ️ 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".

Comment thread src/adapters/google.ts
Comment on lines +318 to +322
function googlePartTextEvent(part: GoogleResponsePart): AdapterEvent | undefined {
if (!part.text) return undefined;
return part.thought === true
? { type: "reasoning_raw_delta", text: part.text }
: { type: "text_delta", text: part.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 Document the Google thought-output mapping

When Google returns a thought: true part, this changes the public Responses/Chat contract from ordinary assistant text to reasoning output (and Responses requests with reasoning.summary: "none" suppress it entirely), but docs-site/src/content/docs/reference/adapters.md and its translations still omit this behavior. Add the visibility and output-channel rule to the Google adapter documentation and synchronize the translated pages.

AGENTS.md reference: src/AGENTS.md:L24-L28

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Final CI status: the exact merged head e0d2df3b35734a793fcdea03e655d485206797da is now green across the full cross-platform workflow, including macOS, all test shards, gates, service lifecycle, keyring, packaging, and CodeRabbit. The maintainer-added heartbeat/signature regressions are included and pass. The PR is non-draft and mergeable; the remaining recorded state is the earlier CHANGES_REQUESTED review, so please submit the re-review/approval when ready.

@lidge-jun
lidge-jun merged commit 567a6d4 into dev Aug 12, 2026
32 of 33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants