Skip to content

fix(core): make turn and tool-call IDs unique across sessions - #59

Merged
austinchennn merged 2 commits into
mainfrom
codex/global-session-identifiers
Oct 19, 2026
Merged

austinchennn merged 2 commits into
mainfrom
codex/global-session-identifiers

Conversation

@austinchennn

@austinchennn austinchennn commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Opening a fresh agent session reused turn-1, and model call IDs were exposed unchanged. Applications which retain edit history or deduplication keys across voice sessions could therefore confuse two unrelated turns/calls. Core now generates opaque UUID-based public turn and call identities, keeps one call identity across fragments/lifecycle/hooks/tool contexts/results, and translates settled results back to the provider's original ID. Reused raw IDs in later responses get new public identities; response-scoped lookup state is released with its response and cleared on close.

Issue association

Refs #56 and Q-cell2/vdoc-server#13. This delivers the runtime/protocol repair for #56; package release remains a separate, explicitly unapproved step. Related normative prose correction: #57.

Based directly on current main f5e0825, independent of open PR #58. Both touch the argument-fragment dispatch point, so that small overlap needs resolution when merging the second PR.

Behaviours Completed

  • Different sessions and later responses never restart an application's public turn/call key. Long or application-unsafe provider IDs stay internal; generated IDs fit consumers' 128-character limit.
  • All call-facing SDK surfaces share the public identity; the application cannot submit a provider raw ID as an alternative result key. Duplicate issuance and previous/foreign results do not execute or settle a later call.
  • A resumed wire call retains its exact seq, callId, turnId and envelope, rather than being re-identified during replay.
  • Adds draft global-tool-ids-v1 and GLOBAL_TOOL_IDS_V1 in protocol revision 1.3. This optional capability exposes the stronger guarantee without tightening the baseline rules forbidden by §3.1/§3.2. The reference SDK generates stronger IDs for baseline peers too; old servers may decline the capability.
  • Registry, negotiation, shared vectors and SDK consumer checks are updated. The obsolete §3.3 sentence saying no capabilities exist now points to the registry, preserving all existing negotiation/gating semantics.
  • Existing tool-stream conformance instrumentation now keeps application fixture labels separate from opaque wire identities. All existing lifecycle/fault/replay checks remain active.

Files Changed

  • packages/core: public identity allocation, provider-result translation, response/close cleanup and regression coverage; existing tests echo observed IDs instead of assuming provider IDs.
  • packages/protocol, packages/server, packages/client: exported capability and negotiation coverage.
  • spec/: revision 1.3, draft registry entry and two shared negotiation vectors; message schemas/shapes unchanged.
  • conformance: real WebSocket cross-session/replay/result-isolation regression and opaque-identity fixture adaptation.
  • scripts/consumer-smoke.mjs, example assertions and docs/GLOBAL_IDENTIFIERS.md: actual tarball checks and integration/guarantee documentation.

Testing

  • Red before implementation: all three initial regression cases failed (identical first turns, raw/long provider IDs exposed, and reused raw IDs across responses).
  • npm test: 473 passed, including four new core identity cases, capability/resume coverage and the shared vectors.
  • npm run typecheck and npm run check:spec: passed (23 schemas, 2 draft capabilities, 158 control vectors, 9 audio vectors).
  • npm run test:conformance: 169 passed, including all existing fault/timeout/cleanup checks and the new real WebSocket regression.
  • npm run test:e2e: 7 passed. npm run test:workers: 2 passed in real workerd.
  • npm run test:conformance:consumer: passed with the actual installed standalone CLI tarball and embedded reference drivers.
  • PYTHONPATH=python/src python3 -m pytest python/tests: 467 passed on Python 3.14 against the source tree, including the shared spec vectors.
  • npm run pack, npm run check:budgets, npm run test:consumer: passed, including clean installation of the 13 local tarballs outside the checkout and both TypeScript resolution modes. Core 5.22 KB gzip / 15 KB; protocol 2.18 / 5; client 5.27 / 20. No dependency or manifest/lockfile changes.

Hosted PR checks also pass: core checks, conformance profile and actual CLI consumer, Node e2e, Workers, Python 3.10/3.14, docs build, and the CI release dry-run job. The docs deployment is skipped for this PR; no actual release workflow was dispatched.

Unsure About / Limits

  • UUIDv4 provides collision-resistant random identities, not deterministic global coordination or authorization. IDs do not replace durable deduplication/transactions in the application.
  • The new conformance regression is a raw-wire test with the public SDK as driver. It is not a new reusable CLI profile, second-language certification, or a complete conformance claim. The capability remains draft.
  • Open provider response/call state still follows the existing lifecycle; this does not impose a new limit on arbitrary unfinished work or invalid late provider traffic.
  • No version bump, tag, publication, release workflow dispatch or production deployment. All package manifests remain at 0.1.0 until the separately approved release.

Implementation Order and Acceptance

@austinchennn
austinchennn merged commit 55cc537 into main Oct 19, 2026
9 checks passed
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