Skip to content

Vendor @intx/types, @intx/storage-isogit, and @intx/inference at Interchange head - #411

Merged
TheGreatAxios merged 4 commits into
mainfrom
cl-5696-vendor-intxtypes-and-intxstorage-isogit-at-interchange-head
Aug 8, 2026
Merged

Vendor @intx/types, @intx/storage-isogit, and @intx/inference at Interchange head#411
TheGreatAxios merged 4 commits into
mainfrom
cl-5696-vendor-intxtypes-and-intxstorage-isogit-at-interchange-head

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Vendors @intx/types, @intx/storage-isogit, and @intx/inference as source at Interchange upstream head (cd7c5a37747dc39713d1efd24296ea861e6ac82a), replacing the published npm 0.2.2 installs for the first two and re-syncing the already-vendored third.

Why all three together

The staged plan treated @intx/types/@intx/storage-isogit (stage 2) and @intx/inference (stage 3) as separately landable. They are not. The reactor's approval-suspend primitive (upstream 06d39dc6) changes PendingOperation and the BeforeToolDecision return contract across all three packages in one upstream commit — @intx/inference's exported signatures reference types that only exist in the newer @intx/types. Vendoring either side alone does not typecheck by construction, so splitting them across two PRs would require an intermediate broken-build state.

This disproves the plan's §5 claim that "no stage depends on a later one being merged first for main to stay shippable" for this pair. docs/plans/interchange-vendoring-plan.md is corrected in this PR rather than left to mislead the next reader.

Local patches

@intx/types and @intx/storage-isogit are verbatim copies — zero local modifications, so a diff against any later upstream checkout shows 100% upstream-authored lines.

@intx/inference carries local patches. vendor/intx-inference/PATCHES.md is new and records, per file, what each patch fixes and why it is not yet upstream. All 9 previously-carried files were reapplied against the new source; every patch site now carries a one-line Locally patched — see vendor/intx-inference/PATCHES.md#<anchor> marker, so grep -rn "Locally patched" vendor/intx-inference/src enumerates every intentional divergence.

Two patches were dropped as genuinely superseded, verified by reading the new upstream source rather than assuming:

  • deliver()'s unhandled-rejection guard — upstream now wraps the whole correlation dispatch in try/catch and routes failures through closeMessageRun, which is stricter than what we carried.
  • The reactor-level inference.retry emission — retry moved entirely into harness.ts's runInference wrapper, which emits the event itself; keeping ours would double-emit.

The security- and leak-sensitive patches are all still carried: the correlatingIds unbounded-Set leak on every successful correlated resume, the 16 MiB SSE line cap (OOM vector), and the OpenAI Responses stream-terminal detection (hang).

Consequent migrations in our own source

These are real semantic migrations, not casts to satisfy the type checker:

  • inference.thinking.signatureinference.block.signature; upstream generalized signatures from thinking blocks to every signable block kind. Updated the Responses adapters' emission and the perf span classifier.
  • ProviderAdapter gained a required parseJSONResponse. The three Responses adapters always request stream: true, so a JSON body reaching them means the response kind was misdetected — they throw ProtocolMismatchError rather than pretend to support a mode never requested.
  • ContentBlock gained a safety_rating variant (Gemini promptFeedback content-filter signals); the context-size estimator now counts its blockReason text like every other block kind.
  • The vendored (unpatched) OpenAI chat-completions adapter now wraps text as a { type: "text", text } part instead of a bare string when a turn mixes text and images, matching the API's own content-parts contract; the adapter test's expectation was updated to match.

Side effect: arktype duplication resolved

Every published @intx/* package previously carried its own nested arktype install, distinct from the root's — so an instanceof check against a type built by one instance silently returned false against the other. Resolving these packages as workspace members removes the nested installs; bun.lock now shows a single arktype resolution across the tree. Closes CL-5665.

Verification

  • bun run typecheck clean
  • bun run build clean
  • Full suite: 4221 pass / 0 fail across 318 files
  • Upstream clone at /Users/thegreataxios/abklabs/interchange was read-only throughout — confirmed clean working tree, HEAD unchanged, zero commits ahead of origin

Reviewed by greybeard (approach) and critique (execution). Critique verified the reapplied tryCorrelate try/finally closes the leak on every exit path, the commitment-boundary retry redesign is coherent, both dropped patches are legitimately superseded, and the src/ migrations are honest fixes rather than stubs.

Docs

docs/VENDORING.md is new: what's vendored, from which commit, patched vs. verbatim, and the re-sync procedure — including the caveat that a vendored package.json's "version": "0.2.2" is a carried-over convention and does not describe the checked-out source. AGENTS.md's Interchange section points at it.

Not in scope: @intx/authz, @intx/agent, @intx/tools-posix, @intx/log remain on published releases.

…head

Both packages are the dependency floor the reactor's approval-suspend
primitive needs (PendingOperation lives in @intx/types, its persistence
hook in @intx/storage-isogit), and neither carries local patches, so they
sync as verbatim copies of the upstream source tree. Resolving them as
workspace packages instead of npm installs also collapses a duplicate
arktype install that previously desynced instanceof checks between the
root's arktype and the nested copy every published @intx/* package carried.
The approval-suspend primitive (upstream 06d39dc6) changes PendingOperation
and BeforeToolDecision shapes that @intx/inference, @intx/types, and
@intx/storage-isogit all share, so @intx/inference cannot stay on the old
published type shapes once @intx/types moves to head — the two must sync
together. Reapplied all 9 locally patched files against the new source
(correlatingIds leak fix, ephemeralTurns, checkpoint-after-tool-cycle,
single-checkpoint-per-decide guard, turns-revision checkpoint skip, SSE line
cap, stream-terminal detection, abort-reason propagation, and the
commitment-boundary streaming redesign in the retry wrapper) and dropped two
patches upstream has since absorbed on its own (deliver()'s unhandled-
rejection guard, and the reactor-level inference.retry emission, both now
implemented natively — see vendor/intx-inference/PATCHES.md for the full
per-file ledger and what changed).
…hapes

@intx/types renamed the block-signature event from
inference.thinking.signature to inference.block.signature and generalized
signatures to every signable block kind, not just thinking blocks. Updated
the Responses adapters' signature emission and the perf span classifier's
event set, plus test fixtures asserting the old event name.

ProviderAdapter also gained a required parseJSONResponse for non-streaming
JSON bodies. The three Responses adapters here always request stream: true,
so a JSON body reaching them means the response kind was misdetected or the
provider ignored the streaming request; parseJSONResponse for these throws
a protocol-mismatch error rather than pretending to support a mode never
requested.

ContentBlock gained a safety_rating variant (structured content-filter
signals from Gemini's promptFeedback); the context-size estimator now
counts its blockReason text like the other block kinds.

The OpenAI chat-completions adapter (vendored, unpatched) now wraps text
content as a { type: "text", text } part instead of a bare string when a
turn mixes text and image blocks, matching the API's own content-parts
contract; updated the adapter test's expectation to match.
Adds docs/VENDORING.md as the authoritative record of what's vendored, from
which upstream commit, and how to re-sync — the pattern established by the
original @intx/inference vendoring stops scaling once three packages share
one sync cadence. Points AGENTS.md's Interchange table at it. Also corrects
the vendoring plan's claim that no vendoring stage depends on another: this
sync found that @intx/types and @intx/inference are typed against each
other via one upstream commit and cannot land as separately shippable PRs.
@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown

CL-5665

CL-5696

@TheGreatAxios
TheGreatAxios merged commit c986948 into main Aug 8, 2026
3 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