Changelog
Source:
CHANGELOG.mdat the repo root.
0.3.0
Changed
createRouterFromToolsnow throws[ToolRoute] Tool '<name>' lists '<successor>' more than once in nextAllowed.instead of silently deduping. A duplicate successor was the one malformed input that was accepted at construction while every other bad shape (unknown tool, duplicate tool name) already threw; this is a behavior change for any config that relied on the old silent dedup.nextTools(router, null)now callslegalNextFor(router.adjacency, null)instead of recomputing the entry-tool set with a second copy of the same filter. No observable output changed; this removes the risk of the two functions drifting apart.
0.2.2
Fixed
- Widened
peerDependencies.aito>=6.0.0 <8. Verified the full suite against both the lockedai@6.0.174andai@7.0.107:LanguageModelV3requires the raw stream'sfinishpart to carryfinishReason: { unified, raw }instead of a bare string. The router and guard (src/guard.ts,src/router.ts,src/narrow.ts) never touch that shape and needed no change; only the hand-rolled mock inexamples/code-review-agent/run.tsdid. Closes #6, #7, #8, #9. .github/workflows/sdk-compat.yml: the weekly test step hadcontinue-on-error: true, so every run since 2026-08-24 filed ansdk-driftissue while still reporting green. The test step now fails the job for real; the issue-filing step runs onif: failure().
0.2.1
Audit hardening pass. No public API changes.
Fixed
TOOLROUTE_VERSIONwas still'0.1.0'while the package shipped as0.2.0, so every runtimerouterVersiondiagnostic mislabelled the version. It is now kept in lockstep withpackage.json(a unit test asserts the const matches) so a release can no longer drift it.tsupno longer strips thenode:import prefix (removeNodeProtocol: false). The previous build rewrotenode:moduleto baremodule, which breaks Cloudflare Workersnodejs_compat.package.json#repository.urlnow uses the canonicalgit+https://github.com/nkwib/toolroute.gitform.
Changed
- CI now runs
pnpm smoke(the dist-tarball consumer test) after build. - Documented two known limitations in the README: a router instance holds
one
state.prev(use one router per concurrent run, orreset()between sequential runs), and entry tools are those with a non-emptynextAllowed(a terminal tool can never be the first call, by design). - Docs site: version badges are now generated from the root
package.json, the changelog and compatibility tables carry the0.2.0rows, and staletoolroute@0.1.0example output was refreshed to0.2.0.
0.2.0 — 2026-05-06
Changed
createRouterFromToolsnow throws at construction when no tool is reachable as an entry point (every tool listed under another tool'snextAllowed). The previous behaviour silently produced a router that would throw on every call.- Adjacency entries with duplicate names in
nextAllowedare now de-duplicated (preserving first-seen order).printRouterGraphno longer emits duplicates. legalNextFor(null)now returns entry tools in insertion order, matchingnextTools(router, null).
Fixed
- Replaced
as nevercast inrouter.tswith a properly typed cast. .gitignorenow ignores.env/.env.*(with!.env.example).
0.1.0 — 2026-05-04
Initial public release. Treated as a pre-1.0 calling card; a 1.0.0 cut will follow once the API has been used in anger.
defineTool({ name, inputSchema, nextAllowed, execute })— collocates the legality graph with the tool itself.createRouterFromTools(tools, options)— derives the name set from the tool array; one source of truth.- Per-step narrowing helper
nextTools(router, prevName)and the underlyingNextTools<R, Prev>type. ToolRouteViolationwithprev/next/legalNext/routerVersiondiagnostic fields.strictMode: truethrows,strictMode: falsewarns.- Edge-runtime detection (Vercel Edge, Cloudflare Workers,
NEXT_RUNTIME=edge) with a one-time init warning. printRouterGraph(router)— deterministic plain-text adjacency dump, zero deps.COMPATIBILITY.mdrow stamped againstai@6.0.174. Weekly CI cron runs the suite againstai@latest; failures open an issue taggedsdk-drift.- README hero recording showing both type-level red squiggle and
runtime
ToolRouteViolationfor the same offending call.