Skip to content

fix(core): shorten compound tool-call ids on the generate fallback - #144

Open
pierreraby wants to merge 2 commits into
mainfrom
fix/generate-tool-call-id-limit
Open

pierreraby wants to merge 2 commits into
mainfrom
fix/generate-tool-call-id-limit

Conversation

@pierreraby

Copy link
Copy Markdown
Collaborator

Closes #141.

Hosts store Responses tool-call ids compounded as <call_id>|<item_id> (73 characters for the observed call_<32hex>|fc_<32hex> shape). The /alpha/generate backend rejects call_id values longer than 64 characters with 400 input[N].call_id, so the fallback maps every referenced id to a deterministic per-request wire form shared by calls and their results: pairing is preserved, distinct ids never collide, and short ids pass through unchanged. The Provider API path is untouched.

Verified: reporter's session replays to max 64 (was 73), 0 raw ids, pairing intact; unit suite green (pure 68/68 incl. 5 new, stream 42/42); typecheck + prettier clean.

Hosts store Responses tool-call ids compounded as <call_id>|<item_id>
(73 characters for the observed call_<32hex>|fc_<32hex> shape). The
/alpha/generate backend rejects call_id values longer than 64 characters
with 400 input[N].call_id, so the fallback maps every referenced id to a
deterministic per-request wire form shared by calls and results: pairing
is preserved, distinct ids never collide, and short ids pass through
unchanged. The Provider API path is untouched.

Closes #141
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Memory benchmark

Compared base 0126bc5 with PR head 12085c3 on the same GitHub-hosted darwin runner. Lower values are better.

Metric Base PR PR − Base Change
Stable RSS 120.0 MiB ± 0.8 MiB 120.4 MiB ± 0.8 MiB +0.2 MiB ± 1.0 MiB +0.2%
Physical footprint 66.0 MiB ± 0.9 MiB 67.1 MiB ± 0.8 MiB +0.9 MiB ± 0.8 MiB +1.3%
Physical peak 77.6 MiB ± 0.9 MiB 78.4 MiB ± 0.9 MiB +0.9 MiB ± 0.8 MiB +1.2%

Interpretation: Differences larger than their measured MAD: Physical footprint +0.9 MiB ± 0.8 MiB, Physical peak +0.9 MiB ± 0.8 MiB.

Extension overhead above pi baseline

Metric Base overhead PR overhead Difference
Stable RSS +5.8 MiB ± 1.7 MiB +7.0 MiB ± 0.6 MiB +0.2 MiB ± 1.0 MiB
Physical footprint +4.0 MiB ± 0.4 MiB +4.5 MiB ± 0.5 MiB +0.9 MiB ± 0.8 MiB
Physical peak +4.9 MiB ± 1.0 MiB +5.3 MiB ± 0.7 MiB +0.9 MiB ± 0.8 MiB

Values are medians of 6 alternating, paired runs. The value after ± is the median absolute deviation (MAD). Each process was sampled 12 times after a 2500 ms warm-up.

Environment: pi 0.84.4, Bun 1.4.0, darwin arm64. RSS comes from ps; physical footprint and peak come from macOS footprint.

This is a comparative signal, not a pass/fail threshold. GitHub-hosted runner noise can affect absolute values.

@karaaslanz karaaslanz 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.

Thanks for fixing #141 and adding call/result pairing coverage. I found one deterministic edge case in the exact PR head (b9a7233):

When an existing <=64-character tool-call ID equals the shortened candidate generated for an earlier overlong ID, generateToolCallIdMap can allocate that candidate to the long ID first. The existing short ID is then renamed, contradicting the documented guarantee that short IDs pass through unchanged. The outcome depends on message ordering.

Requested change: Reserve all pre-existing <=64-character IDs before allocating shortened wire IDs for long IDs; use the existing hash-suffix fallback for long-ID collisions. Add a regression with both orderings of the same colliding pair, asserting (1) the original short ID stays unchanged, (2) all distinct wire IDs remain distinct and <=64 characters, and (3) tool-call/result references still match.

I validated this bounded approach against the PR head in a local-only patch: 329/329 unit tests, TypeScript typecheck, Prettier, and 250 additional seeded shuffled-ID scenarios passed. The patch has not been pushed; these results are not upstream CI results for the patch.

Requesting changes until this short-ID pass-through edge case is handled.

Reserve every pre-existing generate tool-call id within the 64-character limit before allocating shortened wire ids. Long-id collisions keep using the hash-suffix fallback, so short ids remain unchanged regardless of message order.

Add both-order regressions covering short-id preservation, distinct bounded wire ids, and call/result pairing. Addresses the edge case reported by @karaaslanz on PR #144.
@pierreraby

Copy link
Copy Markdown
Collaborator Author

Thanks Ömer — good catch. I independently reproduced it on b9a7233: long-first renamed the existing short ID, while short-first preserved it. Pairing and the length bound remained intact, but the short-ID pass-through guarantee was indeed violated.

Fixed in 12085c3: all referenced IDs of ≤64 characters are reserved before allocating shortened IDs; long-ID collisions still use the existing hash-suffix fallback. Added regressions for both orderings of the same colliding pair, asserting the original short ID is unchanged, wire IDs remain distinct and ≤64 characters, and call/result references match. The long-first regression fails on the previous head and both pass with the fix.

Local validation: 330/330 unit tests; full npm test (including real pi and OMP against local mocks), TypeScript typecheck, Prettier, and git diff --check all passed. These are local results; CI for the new head is separate.

@karaaslanz could you take another look when you have a moment? Thanks for the thorough review!

@pierreraby
pierreraby requested a review from karaaslanz October 9, 2026 01:28
@pierreraby

Copy link
Copy Markdown
Collaborator Author

Hi @karaaslanz, when you have a moment, could you re-review the collision fix in 12085c3? It reserves existing short IDs before shortening long ones, adds regression coverage for both orderings, and CI is green.

We’d like to include this fix alongside #145 and #148 in the next release. Thanks again for catching that edge case!

This branch has not been deployed

No deployments
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.

Error 400 when using muse spark 1.3 contributor on some longer threads

2 participants