Skip to content

fix(decopilot): decode Gemini thought signatures out of tool-call ids#4005

Merged
viktormarinho merged 2 commits into
mainfrom
viktormarinho/remove-tool-id-hashing
Jun 22, 2026
Merged

fix(decopilot): decode Gemini thought signatures out of tool-call ids#4005
viktormarinho merged 2 commits into
mainfrom
viktormarinho/remove-tool-id-hashing

Conversation

@viktormarinho

@viktormarinho viktormarinho commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What is this contribution about?

OpenAI-format gateways (LiteLLM et al.) fronting Gemini-thinking pack the model's thoughtSignature into the tool-call id (call_<base>__thought__<sig>), bloating it to multiple KB — which overflowed a Postgres btree key and broke the chat UI's tool-call id matching ("No tool invocation found for tool call ID …"). A new portable language-model middleware (thought-signature.ts) strips the signature into providerMetadata.google.thoughtSignature on the way in — the same shape the native Google provider already emits and conversation.ts preserves — and re-embeds it into the id on the way out, gated to OpenAI-format gateways (openai-compatible/openrouter/deco) and a strict no-op for any id without the separator. Because ids now reach storage and the UI small, this removes the #3973 storageKey sha256 hashing from async-research-jobs.ts and hardens dropRedundantStubs to match a stub by its part's toolCallId rather than the message-id suffix.

Screenshots/Demonstration

N/A — no UI changes (fixes an error toast; no visual surface added).

How to Test

  1. Run a deep-research / web_search flow through a Gemini-thinking model behind a LiteLLM (OpenAI-compatible) gateway, so the upstream tool_call_id is call_<base>__thought__<multi-KB-sig>.
  2. Confirm the durable async_research_jobs insert + stub message succeed (no Postgres 54000 btree error) and the chat no longer throws "No tool invocation found for tool call ID …" on completion/refresh.
  3. bun test packages/harness/src/decopilot/thought-signature.test.ts and bun test apps/mesh/src/web/components/chat/store/thread-connection.test.ts pass; bun run check is green.

Migration Notes

None — no schema or config changes. Short ids were already stored verbatim; oversized ids are now prevented upstream rather than hashed, so no data migration is required.

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • Documentation is updated (if needed)
  • No breaking changes

Summary by cubic

Decode Gemini thought signatures out of gateway tool-call IDs and store them in metadata to keep IDs small. This prevents Postgres index overflows and fixes chat tool-call matching.

  • Bug Fixes
    • Added middleware packages/harness/src/decopilot/thought-signature.ts to strip call_<base>__thought__<sig> into providerMetadata.google.thoughtSignature on inbound and re-embed on outbound; enabled for openai-compatible, openrouter, and deco.
    • Removed sha256 storageKey keying and its tests; persist/query by the real tool_call_id, keep main’s v2 thread_message_parts polling-stub migration, and key async stub messages by the raw id.
    • dropRedundantStubs now matches by a part’s toolCallId (covers legacy hashed stub ids); added a targeted test.

Written for commit 6372833. Summary will update on new commits.

Review in cubic

viktormarinho and others added 2 commits June 18, 2026 12:10
OpenAI-format gateways (LiteLLM et al.) fronting Gemini-thinking pack the
model's thoughtSignature into the tool-call id (`call_<base>__thought__<sig>`),
bloating it to multiple KB. That overflowed a Postgres btree key and broke the
chat UI's tool-call id matching ("No tool invocation found for tool call ID …").

A new language-model middleware strips the signature into
providerMetadata.google.thoughtSignature on the way in (matching the native
Google provider) and re-embeds it on the way out, gated to OpenAI-format
gateways (openai-compatible/openrouter/deco). Ids now reach storage and the UI
small, so this removes the #3973 storageKey sha256 hashing and hardens
dropRedundantStubs to match a stub by its part's toolCallId.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve async-research-jobs.ts conflict: keep main's v2 thread_message_parts
polling-stub migration, drop the storageKey/sha256 hashing (this branch strips
oversized tool-call ids upstream via the thought-signature middleware).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@viktormarinho viktormarinho enabled auto-merge (squash) June 22, 2026 15:06
@viktormarinho viktormarinho merged commit f86fddb into main Jun 22, 2026
15 checks passed
@viktormarinho viktormarinho deleted the viktormarinho/remove-tool-id-hashing branch June 22, 2026 15:07
decocms Bot pushed a commit that referenced this pull request Jun 22, 2026
PR: #4005 fix(decopilot): decode Gemini thought signatures out of tool-call ids
Bump type: patch

- decocms (apps/mesh/package.json): 3.37.9 -> 3.37.10
- @decocms/harness (packages/harness/package.json): 1.6.6 -> 1.6.7

Deploy-Scope: both
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