Problem
Gemini appends the same vibecad_state_after after every tool call, even when the CAD context is unchanged. These copies accumulate in the message history and are transmitted again on subsequent API requests.
The helper already supports suppressing unchanged state, and the Anthropic/Codex callers use that support. The Gemini caller does not pass previous_context.
Evidence and reproduction
Audited main at 7289751459ceace471ac771f3a0ec39b972d1949. Area: AI provider orchestration. Findings come from source inspection and isolated Python execution of the relevant source functions with mocked CAD/model boundaries; no paid model requests or live CAD mutations were made.
- State helper returns an empty payload when the previous and current state match. Native-engine contexts already return no state; this finding concerns the VibeScript path.
- Gemini call site calls the helper without its previous-context argument and serializes the resulting state into each tool message.
- Anthropic comparison supplies
previous_context.
In an isolated run of _gemini_child_main, return three identical read-tool results with an unchanged VibeScript surface and an 8,192-character synthetic inventory. The final request contains three copies of that state: 24,978 bytes of repeated state JSON. Directly calling the existing helper with equal current/previous contexts returns {}.
This is a deterministic payload measurement, not a tokenizer or billing measurement. The production result projection was exercised; CAD dispatch and SDK streaming were mocked.
Proposed fix
Capture the pre-tool context and use the existing comparison argument at the Gemini call site. Keep the first-turn context and emit changed state when it actually changes. Use immutable snapshots where necessary so in-place updates cannot hide changes.
Keep all public tools and schemas intact. This follows the existing optional-state behavior in the other provider paths and extends the optimization in #130.
Acceptance tests
- Unchanged VibeScript state adds no repeated state block after reads.
- Changed workbench, surface, revision, and active-domain state are delivered correctly.
- Native contexts continue to omit this block.
- Tool results, tool-call IDs, Gemini thought signatures, and state transitions remain intact.
- A multi-call payload comparison shows the reduction without dropping useful tool output.
Suggested priority: medium; a small, independently reviewable optimization PR.
Problem
Gemini appends the same
vibecad_state_afterafter every tool call, even when the CAD context is unchanged. These copies accumulate in the message history and are transmitted again on subsequent API requests.The helper already supports suppressing unchanged state, and the Anthropic/Codex callers use that support. The Gemini caller does not pass
previous_context.Evidence and reproduction
Audited
mainat7289751459ceace471ac771f3a0ec39b972d1949. Area: AI provider orchestration. Findings come from source inspection and isolated Python execution of the relevant source functions with mocked CAD/model boundaries; no paid model requests or live CAD mutations were made.previous_context.In an isolated run of
_gemini_child_main, return three identical read-tool results with an unchanged VibeScript surface and an 8,192-character synthetic inventory. The final request contains three copies of that state: 24,978 bytes of repeated state JSON. Directly calling the existing helper with equal current/previous contexts returns{}.This is a deterministic payload measurement, not a tokenizer or billing measurement. The production result projection was exercised; CAD dispatch and SDK streaming were mocked.
Proposed fix
Capture the pre-tool context and use the existing comparison argument at the Gemini call site. Keep the first-turn context and emit changed state when it actually changes. Use immutable snapshots where necessary so in-place updates cannot hide changes.
Keep all public tools and schemas intact. This follows the existing optional-state behavior in the other provider paths and extends the optimization in #130.
Acceptance tests
Suggested priority: medium; a small, independently reviewable optimization PR.