stitchkit 0.90.8 → 0.91.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +75 -0
- package/dist/agent-runtime-coding-tools.js +4 -4
- package/dist/agent-runtime-harness.js +6 -6
- package/dist/agent-runtime-sandbox.js +4 -4
- package/dist/agent-runtime.js +18 -17
- package/dist/application-grammy.js +1 -1
- package/dist/application.js +3 -3
- package/dist/cli.js +7 -7
- package/dist/contract/errors-factory.d.ts +12 -0
- package/dist/contract/errors-factory.d.ts.map +1 -1
- package/dist/contract/errors.d.ts +35 -1
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +4 -2
- package/dist/{index-nrqg8tks.js → index-0a349c33.js} +3 -3
- package/dist/{index-adj0pc9r.js → index-137jjs4v.js} +2 -2
- package/dist/{index-42f33bzd.js → index-13cjtmrw.js} +1 -1
- package/dist/{index-qd8gs6nf.js → index-13e1k7v9.js} +2 -2
- package/dist/{index-dggfq62w.js → index-1qvdwnp2.js} +10 -3
- package/dist/{index-scs3f1eg.js → index-2vtcmrj9.js} +8 -2
- package/dist/{index-xbppf54a.js → index-6kyksz9y.js} +12 -7
- package/dist/{index-aj9geeez.js → index-709nh7z7.js} +37 -17
- package/dist/{index-zkcqhxx8.js → index-a11g2kry.js} +1 -1
- package/dist/{index-zjze12x8.js → index-b971qjes.js} +1 -1
- package/dist/{index-03bvcv7r.js → index-bh70rk41.js} +3 -3
- package/dist/{index-bva395we.js → index-bv7mytab.js} +2 -2
- package/dist/{index-4yktadec.js → index-bx6yq2m4.js} +23 -495
- package/dist/{index-p48nc8g9.js → index-f4p4b8f6.js} +10 -11
- package/dist/index-kw9t5ayn.js +507 -0
- package/dist/{index-1ft2wrv0.js → index-mqhjmadk.js} +43 -21
- package/dist/{index-3yqgj323.js → index-qjeyx5t2.js} +2 -2
- package/dist/{index-gte38nbm.js → index-qmy6zq75.js} +1 -1
- package/dist/{index-w58rfj2d.js → index-qrbdq8jk.js} +1 -1
- package/dist/{index-mthq65vn.js → index-ya611vx3.js} +4 -4
- package/dist/{index-xrwgzjw8.js → index-zsqy3xfn.js} +5 -5
- package/dist/index.js +8 -6
- package/dist/node.js +6 -6
- package/dist/observability/bounded-logger.d.ts +2 -0
- package/dist/observability/bounded-logger.d.ts.map +1 -1
- package/dist/observability/index.js +7 -4
- package/dist/observability/sanitize.d.ts +15 -0
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/primitives.js +2 -2
- package/dist/remote.js +5 -5
- package/dist/server/implement.d.ts +33 -7
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +8 -8
- package/dist/testing.js +6 -6
- package/dist/tool-invoker.js +6 -6
- package/dist/tools/agent.d.ts +12 -0
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli-format.d.ts +1 -1
- package/dist/tools/connections/index.js +1 -1
- package/dist/tools/durability-context.d.ts +1 -1
- package/dist/tools/durability-context.d.ts.map +1 -1
- package/dist/tools/durability-port.d.ts +55 -0
- package/dist/tools/durability-port.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +59 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +2 -2
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +1 -1
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +21 -14
- package/dist/tracking.js +2 -2
- package/llms-full.txt +203 -8
- package/package.json +2 -2
- package/dist/index-7rkhw9ec.js +0 -34
package/llms-full.txt
CHANGED
|
@@ -66,11 +66,11 @@ own, recorded as an ADR.
|
|
|
66
66
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
67
67
|
| `stitchkit/oauth` | browser **and** server | evolving | provider-neutral Authorization Code + PKCE request and one-shot callback transaction mechanics |
|
|
68
68
|
| `stitchkit/google` | server (Bun or Node) | evolving | optional Google code exchange and verified OIDC identity adapter |
|
|
69
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the
|
|
69
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the 36 minors since 0.56.2, most recently 0.83.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
70
70
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the store and managed-resource conformance kits |
|
|
71
71
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
72
72
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
73
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 20 of the
|
|
73
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 20 of the 36 minors since 0.56.2, most recently 0.89.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
74
74
|
| `stitchkit/agent-runtime/sandbox` | server | evolving | optional Linux Bubblewrap sessions, durable workspaces and a host HTTP credential gateway; see [sandbox guide](sandbox.md) |
|
|
75
75
|
| `stitchkit/agent-runtime/testing` | tests on Bun or Node | evolving | credential-free replay, scripted provider faults and deterministic race controls |
|
|
76
76
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
@@ -80,7 +80,7 @@ own, recorded as an ADR.
|
|
|
80
80
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
81
81
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
82
82
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
83
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the
|
|
83
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the 36 minors since 0.56.2, most recently 0.83.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
84
84
|
| `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
|
|
85
85
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
86
86
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
|
@@ -1252,6 +1252,43 @@ scope** — the same prefix under two different group scopes is legal (their URL
|
|
|
1252
1252
|
are separated by `scopePrefixes`, and a genuine path clash is the router's own
|
|
1253
1253
|
construction error).
|
|
1254
1254
|
|
|
1255
|
+
#### A dev stand that survives half a feature — `onMissingHandler`
|
|
1256
|
+
|
|
1257
|
+
Adding an endpoint is two edits by construction: the contract, then the handler.
|
|
1258
|
+
An editor saves one file at a time and a watcher restarts on the first save, so
|
|
1259
|
+
between the two the application refuses to start — and on a shared dev stand that
|
|
1260
|
+
is everyone's stand, not just yours. A project rule ("make both edits at once")
|
|
1261
|
+
cannot outrun the filesystem.
|
|
1262
|
+
|
|
1263
|
+
```ts
|
|
1264
|
+
implementRegistry(apiContractRegistry, handlers, {
|
|
1265
|
+
onMissingHandler: process.env.NODE_ENV === 'production' ? 'throw' : 'stub',
|
|
1266
|
+
})
|
|
1267
|
+
```
|
|
1268
|
+
|
|
1269
|
+
With `'stub'` the application starts, the unimplemented endpoint answers `501` and
|
|
1270
|
+
names itself in the log at every mount, so it cannot be forgotten. Both save
|
|
1271
|
+
orders are covered: a contract ahead of its handler, and a handler ahead of its
|
|
1272
|
+
contract. The option is accepted by `implement`, `implementRegistry`,
|
|
1273
|
+
`createImplement`, `createScopedImplement`, `createImplementRegistry` and
|
|
1274
|
+
`createScopedImplementRegistry`.
|
|
1275
|
+
|
|
1276
|
+
Three things it deliberately does not do. It stays `'throw'` by default, and
|
|
1277
|
+
`'throw'` is the only right answer in production: a release is atomic, so there is
|
|
1278
|
+
no window to protect, and a surface with a hole must not ship. It does not relax
|
|
1279
|
+
the **compile-time** exactness check — that lives in the generic constraint, your
|
|
1280
|
+
editor still shows the missing handler, and a watcher that only transpiles is
|
|
1281
|
+
precisely why the runtime refusal was the one that bit. And it does not stub a
|
|
1282
|
+
streaming multipart endpoint, which needs `defineMultipartStream()` receivers; the
|
|
1283
|
+
stand still stops on one of those.
|
|
1284
|
+
|
|
1285
|
+
The stub answers `NOT_IMPLEMENTED` with status `501` everywhere — over HTTP and on
|
|
1286
|
+
a tool call that crosses a process boundary alike, because the code is registered
|
|
1287
|
+
in `STITCH_ERROR_STATUS`. One consequence follows from that and is worth knowing:
|
|
1288
|
+
a stubbed endpoint keeps its `expose`, so on a dev stand it is advertised to a
|
|
1289
|
+
model as a real tool that always refuses. The refusal is not retryable, so a model
|
|
1290
|
+
stops rather than loops; it still costs one turn to find out.
|
|
1291
|
+
|
|
1255
1292
|
The registry is intentionally flat: every key must point to one concrete
|
|
1256
1293
|
`defineContract()` result. Composed namespace arrays are mounted explicitly with
|
|
1257
1294
|
`implement()` because they do not have a one-key-to-one-handler-map boundary.
|
|
@@ -3482,6 +3519,102 @@ schema and annotations, and nothing else — it moves when the contract moves an
|
|
|
3482
3519
|
not when a handler does. Raw SDK registrations stay consumer-owned and are
|
|
3483
3520
|
outside it.
|
|
3484
3521
|
|
|
3522
|
+
### Shaping arguments before validation — `beforeToolCall`
|
|
3523
|
+
|
|
3524
|
+
`beforeToolCall` sees the arguments as they arrived and may **replace** them:
|
|
3525
|
+
|
|
3526
|
+
```ts
|
|
3527
|
+
hooks: {
|
|
3528
|
+
beforeToolCall: async ({ args }) =>
|
|
3529
|
+
typeof args.id === 'string' && args.id.startsWith('@')
|
|
3530
|
+
? { ...args, id: await resolveReference(args.id) }
|
|
3531
|
+
: undefined, // undefined / null / nothing → unchanged
|
|
3532
|
+
}
|
|
3533
|
+
```
|
|
3534
|
+
|
|
3535
|
+
The replacement is validated by the contract schema like any other input, so this
|
|
3536
|
+
shapes a call and never bypasses the schema — a hook returning something the
|
|
3537
|
+
contract refuses produces an ordinary `VALIDATION_ERROR`. It runs before the
|
|
3538
|
+
params/input split, before argument coercion and before both schemas, which is
|
|
3539
|
+
why a field declared `z.string()` can receive a reference and still be a string by
|
|
3540
|
+
the time it is checked. `lifecycle.beforeHandle` is too late for this: the schemas
|
|
3541
|
+
have already answered.
|
|
3542
|
+
|
|
3543
|
+
The audit trail is unaffected. `afterToolCall` reports what the caller sent as
|
|
3544
|
+
`args` and the replacement separately as `effectiveArgs`, so a rewrite is visible
|
|
3545
|
+
as a rewrite rather than by overwriting the evidence.
|
|
3546
|
+
|
|
3547
|
+
### Knowing the outcome of a call — `afterToolCall` and `toolCallId`
|
|
3548
|
+
|
|
3549
|
+
`afterToolCall` receives the whole `ToolResult` — `{ok: true, data}` or
|
|
3550
|
+
`{ok: false, code, …}` — on every exit, including a validation failure that never
|
|
3551
|
+
reached the handler, and on all three transports. It is the answer to "did this
|
|
3552
|
+
call fail"; deriving that from the serialized error text instead is the mistake
|
|
3553
|
+
this section exists to prevent, and it is a mistake that does not announce itself:
|
|
3554
|
+
one consumer had five places asking the question and getting five answers.
|
|
3555
|
+
|
|
3556
|
+
To correlate an outcome with the call the model made, read `context.toolCallId`:
|
|
3557
|
+
|
|
3558
|
+
```ts
|
|
3559
|
+
hooks: {
|
|
3560
|
+
afterToolCall: ({ context, result }) => {
|
|
3561
|
+
loop.record(context.toolCallId, result.ok ? 'ok' : result.code);
|
|
3562
|
+
},
|
|
3563
|
+
}
|
|
3564
|
+
```
|
|
3565
|
+
|
|
3566
|
+
Two exits are deliberately **not** reported: a runtime tool presenter that throws
|
|
3567
|
+
on the agent surface (the AI SDK calls it after `execute` has already returned)
|
|
3568
|
+
and `ToolExecutionControlError`, which is a run being stopped rather than a tool
|
|
3569
|
+
failing — check it with `isToolExecutionControlError`.
|
|
3570
|
+
|
|
3571
|
+
### Restartable tool bodies — `durability`
|
|
3572
|
+
|
|
3573
|
+
A tool that starts slow work and must report exactly once, including after a host
|
|
3574
|
+
restart, can keep that bookkeeping **inside** the tool:
|
|
3575
|
+
|
|
3576
|
+
```ts
|
|
3577
|
+
mountAgent(services, {
|
|
3578
|
+
durability: (toolCallId, signal) => myLedgerFor(toolCallId, signal),
|
|
3579
|
+
});
|
|
3580
|
+
|
|
3581
|
+
// in the handler
|
|
3582
|
+
const asset = await ctx.step('render', () => renderAsset(ctx.input));
|
|
3583
|
+
await ctx.waitFor({ event: 'render-done', id: assetId });
|
|
3584
|
+
```
|
|
3585
|
+
|
|
3586
|
+
`ToolDurability` is the port a tool body sees — `step`, `sleep`, `waitFor`. You
|
|
3587
|
+
do not have to implement it: the engine ships from `stitchkit/tools`, and it needs
|
|
3588
|
+
a ledger of two methods over storage you already have:
|
|
3589
|
+
|
|
3590
|
+
```ts
|
|
3591
|
+
import { createLocalStepDurability, type StepDurabilityLedger } from 'stitchkit/tools';
|
|
3592
|
+
|
|
3593
|
+
const ledger: StepDurabilityLedger = {
|
|
3594
|
+
appendEvent: (event) => db.durabilityEvents.insert(event), // returns the row with `seq`
|
|
3595
|
+
readEvents: ({ conversationId, fromSeq, toSeq }) => db.durabilityEvents.page(…),
|
|
3596
|
+
};
|
|
3597
|
+
|
|
3598
|
+
mountAgent(services, {
|
|
3599
|
+
durability: (toolCallId, signal) =>
|
|
3600
|
+
createLocalStepDurability({ store: ledger, conversationId, runId: toolCallId, signal }),
|
|
3601
|
+
});
|
|
3602
|
+
```
|
|
3603
|
+
|
|
3604
|
+
That gives replay, absolute deadlines and decode refusal without writing them.
|
|
3605
|
+
The port is there for an application that already has its own ledger engine.
|
|
3606
|
+
|
|
3607
|
+
One thing the port deliberately leaves out: **delivery**. `waitFor` parks until
|
|
3608
|
+
`{ event, id }` arrives, and a tool body has no business delivering to itself —
|
|
3609
|
+
so `deliver` lives on the engine object you constructed, not in the handler
|
|
3610
|
+
context. Whatever produces the event (a webhook, a queue consumer, a cron) calls
|
|
3611
|
+
`engine.deliver({ event, id, payload })` against the same ledger; the parked
|
|
3612
|
+
`waitFor` resolves, and a `waitFor` that starts after the delivery returns at
|
|
3613
|
+
once. Taking `agent-runtime` is not required and nothing of the runtime proper
|
|
3614
|
+
enters the `stitchkit/tools` graph. An application that *does* run on
|
|
3615
|
+
`agent-runtime` gets durability through the run context and needs no option;
|
|
3616
|
+
where both exist the runtime's wins, because the run is recorded in its ledger.
|
|
3617
|
+
|
|
3485
3618
|
### Typed MCP call metadata
|
|
3486
3619
|
|
|
3487
3620
|
Contract handlers, runtime-tool handlers/factories, lifecycle and tool hooks all
|
|
@@ -5511,7 +5644,7 @@ or it keeps the failed attempt's partial text on screen.
|
|
|
5511
5644
|
usage, files and sources do not count;
|
|
5512
5645
|
- `tool-status` is transient lifecycle presentation with JSON-safe input on
|
|
5513
5646
|
start and output on completion. A mounted typed failure carries the same safe
|
|
5514
|
-
`{ error, details?, _hint? }` envelope as the durable result; an unknown
|
|
5647
|
+
`{ error, retryable, details?, _hint? }` envelope as the durable result; an unknown
|
|
5515
5648
|
internal cause remains generic and stays in local observability only;
|
|
5516
5649
|
- `terminal` follows the winning terminal CAS.
|
|
5517
5650
|
|
|
@@ -9903,7 +10036,8 @@ core never models them (ADR 0002). But stitchkit itself emits a set of its own:
|
|
|
9903
10036
|
`CONFLICT`, `RATE_LIMITED`, `VALIDATION_ERROR`, `FILE_INVALID_PATH`,
|
|
9904
10037
|
`FILE_OUTSIDE_ROOT`, `FILE_NOT_FOUND`, `FILE_NOT_REGULAR`,
|
|
9905
10038
|
`FILE_INSPECTION_REJECTED`, `FILE_TOO_LARGE`, `FILE_EXISTS`,
|
|
9906
|
-
`REALTIME_CONTRACT_VIOLATION`, `APPLICATION_NOT_ACCEPTING`, `
|
|
10039
|
+
`REALTIME_CONTRACT_VIOLATION`, `APPLICATION_NOT_ACCEPTING`, `NOT_IMPLEMENTED`,
|
|
10040
|
+
`WAIT_TIMEOUT`,
|
|
9907
10041
|
`WAIT_FAILED`, `DOWNLOAD_NOT_FOUND`, `VIEW_HTTP_ERROR`,
|
|
9908
10042
|
`OPERATION_NOT_SUCCEEDED`, `STREAM_ITEM_INVALID`, `STREAM_FRAME_TOO_LARGE`,
|
|
9909
10043
|
`STREAM_TERMINAL_MISSING`, `STREAM_LIFETIME_EXCEEDED`,
|
|
@@ -10031,7 +10165,7 @@ whether the code declares `details`:
|
|
|
10031
10165
|
| code **with** a `details` schema | the declared message | no text at all — only `details` and `hint` |
|
|
10032
10166
|
| code **without** one | the declared message | the same text, delivered as `details.message` |
|
|
10033
10167
|
|
|
10034
|
-
The model-facing envelope is `{ error, details?, _hint? }`; for a code with no
|
|
10168
|
+
The model-facing envelope is `{ error, retryable, details?, _hint? }`; for a code with no
|
|
10035
10169
|
details schema the framework fills `details` with `{ message }`, so declaring a
|
|
10036
10170
|
message changes what the model reads there — it used to be the code itself. Put
|
|
10037
10171
|
anything the model must reliably read in `details` or `hint`, not in `message`.
|
|
@@ -11003,6 +11137,24 @@ applied. Active trace, span, user and dimensions are reserved framework fields;
|
|
|
11003
11137
|
caller data cannot overwrite them. A throwing getter, cyclic value or failing
|
|
11004
11138
|
sink never escapes into application code.
|
|
11005
11139
|
|
|
11140
|
+
One string bound for the whole record cuts an error's stack from the bottom —
|
|
11141
|
+
which is exactly where your own frames are. Raise the ceiling for that key alone,
|
|
11142
|
+
wherever it sits (`stack` at the top of one record and under `errorDetail` in the
|
|
11143
|
+
next is the same field), without touching the bound for everything else:
|
|
11144
|
+
|
|
11145
|
+
```ts
|
|
11146
|
+
createBoundedLogger({
|
|
11147
|
+
sink,
|
|
11148
|
+
bounds: { stringLength: 4_000, stringLengthByKey: { stack: 32_000 } },
|
|
11149
|
+
})
|
|
11150
|
+
// or directly: redact(value, { maxStringLength: 4_000, maxStringLengthByKey: { stack: 32_000 } })
|
|
11151
|
+
```
|
|
11152
|
+
|
|
11153
|
+
Keyed by name, not by path — the question is "what is this field", not "where is
|
|
11154
|
+
it". The entry ceiling (`entryBytes`) keeps the last word: a record that does not
|
|
11155
|
+
fit still collapses, but the decision is made for the record, not by cutting one
|
|
11156
|
+
field short in advance.
|
|
11157
|
+
|
|
11006
11158
|
|
|
11007
11159
|
==============================================================================
|
|
11008
11160
|
# Guide: Testing & deployment (docs/guide/testing-and-deployment.md)
|
|
@@ -11971,6 +12123,23 @@ analytics policy belong to the application.
|
|
|
11971
12123
|
|
|
11972
12124
|
# Upgrading stitchkit
|
|
11973
12125
|
|
|
12126
|
+
## Released migration: 0.91.0
|
|
12127
|
+
|
|
12128
|
+
1. `STITCH_ERROR_STATUS` gained `NOT_IMPLEMENTED` (501). An **exhaustive** error
|
|
12129
|
+
vocabulary must name it — without the row `defineErrors({ mapping: { exhaustive:
|
|
12130
|
+
true } })` stops compiling and then throws at startup. Nothing else in this
|
|
12131
|
+
release requires action.
|
|
12132
|
+
|
|
12133
|
+
```ts
|
|
12134
|
+
// before
|
|
12135
|
+
map: { …, WAIT_TIMEOUT: 'timeout' }
|
|
12136
|
+
// after
|
|
12137
|
+
map: { …, NOT_IMPLEMENTED: 'not_implemented', WAIT_TIMEOUT: 'timeout' }
|
|
12138
|
+
```
|
|
12139
|
+
|
|
12140
|
+
The code is thrown only by the new dev-only `onMissingHandler: 'stub'` policy;
|
|
12141
|
+
a vocabulary that is not exhaustive is unaffected.
|
|
12142
|
+
|
|
11974
12143
|
## Released migration: 0.90.0
|
|
11975
12144
|
|
|
11976
12145
|
1. `stitchkit.watch.value` is a discriminated union on `kind` — `full`, `delta`,
|
|
@@ -15702,6 +15871,7 @@ from the root `stitchkit`.
|
|
|
15702
15871
|
| `STITCH_ERROR_STATUS` | const | `code → HTTP status` map for stitchkit's own error codes — [guide](../guide/auth-and-errors.md#stitch-codes-vs-your-codes) |
|
|
15703
15872
|
| `StitchErrorCode` | _type_ | a code stitchkit itself emits (`keyof STITCH_ERROR_STATUS`) |
|
|
15704
15873
|
| `isStitchErrorCode` | function | type guard — is a code one of stitchkit's own? |
|
|
15874
|
+
| `isRetryableStatus` | function | whether a status class means "the same call could work later" — `408`, `429`, `502`, `503`, `504`, and deliberately not every `5xx` |
|
|
15705
15875
|
|
|
15706
15876
|
### Pagination
|
|
15707
15877
|
|
|
@@ -15813,6 +15983,8 @@ Also re-exports the error helpers from `stitchkit/contract`.
|
|
|
15813
15983
|
| `implementRegistry` | function | bind one exact contract registry to one exact backend handler registry |
|
|
15814
15984
|
| `createImplementRegistry` | function | context-typed factory for `implementRegistry` |
|
|
15815
15985
|
| `ImplementationRegistry` | _type_ | flat literal registry of concrete contracts accepted by `implementRegistry` |
|
|
15986
|
+
| `ImplementOptions` | _type_ | `{ onMissingHandler }` — how a binding treats a contract endpoint with no handler |
|
|
15987
|
+
| `MissingHandlerPolicy` | _type_ | `'throw'` (default) or `'stub'`, the dev-stand policy that mounts a `501` instead of refusing to start |
|
|
15816
15988
|
| `KeyedServices` | _type_ | registry result: the mount-ordered `ServiceDef[]` carrying the same services under `.byKey` |
|
|
15817
15989
|
| `RegistryHandlers` | _type_ | exact backend handler registry inferred from a contract registry |
|
|
15818
15990
|
| `ExactRegistryHandlers` | _type_ | fail-first handler shape that rejects extra registry and endpoint keys |
|
|
@@ -16766,7 +16938,7 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
16766
16938
|
| `DimensionCollision` / `SetRequestDimensionsOptions` | _type_ | explicit overwrite, preserve or error policy for dimension keys |
|
|
16767
16939
|
| `createBoundedLogger` | function | decorate a `StitchLogger` with request context, shared sanitisation, redaction and total bounds |
|
|
16768
16940
|
| `DEFAULT_REDACT_PATHS` | constant | baseline credential/token paths added to the sanitizer's sensitive-key policy |
|
|
16769
|
-
| `BoundedLoggerBounds` / `BoundedLoggerOptions` | _type_ | per-value and total record ceilings plus sink/redaction configuration |
|
|
16941
|
+
| `BoundedLoggerBounds` / `BoundedLoggerOptions` | _type_ | per-value and total record ceilings (`stringLengthByKey` raises the string bound for named keys such as `stack`) plus sink/redaction configuration |
|
|
16770
16942
|
| `RequestEvent` | _type_ | the normalised audit event handed to the sink; opt-in HTTP cancellation rows carry `outcome: 'cancelled'` |
|
|
16771
16943
|
| `ObservabilityConfig` | _type_ | independent request and tool sink configuration |
|
|
16772
16944
|
| `Observability` | _type_ | `{ request?, toolCall, getStatus(), flush(bound?): Promise<boolean>, close(bound?) }` with bounded sink lifecycle |
|
|
@@ -16820,7 +16992,7 @@ audit event. See the [Observability guide](../guide/observability.md).
|
|
|
16820
16992
|
| `truncatePreview` | function | cap a value by serialised size |
|
|
16821
16993
|
| `measureSize` | function | item count + byte size of a result |
|
|
16822
16994
|
| `JsonValue` | _type_ | a JSON-serialisable value |
|
|
16823
|
-
| `SanitizeOptions` | _type_ | tuning for `redact` / `sanitizePayload` |
|
|
16995
|
+
| `SanitizeOptions` | _type_ | tuning for `redact` / `sanitizePayload` — `maxStringLengthByKey` bounds a named key wherever it sits without changing the record-wide bound |
|
|
16824
16996
|
| `SizeMeasure` | _type_ | the result of `measureSize` |
|
|
16825
16997
|
|
|
16826
16998
|
---
|
|
@@ -17044,6 +17216,29 @@ A native remote-connector auth surface for MCP — [guide](../guide/mcp-and-agen
|
|
|
17044
17216
|
| `RefreshData` | _type_ | a stored refresh-token record |
|
|
17045
17217
|
| `RegisteredClient` | _type_ | a registered OAuth client |
|
|
17046
17218
|
|
|
17219
|
+
### Durable tool bodies
|
|
17220
|
+
|
|
17221
|
+
A mounted tool body can be made restartable without adopting `agent-runtime`: declare a
|
|
17222
|
+
factory and `step` / `sleep` / `waitFor` appear in the handler context, backed by whatever
|
|
17223
|
+
ledger the application already has.
|
|
17224
|
+
|
|
17225
|
+
```ts
|
|
17226
|
+
mountAgent(services, { durability: (toolCallId) => myLedgerFor(toolCallId) });
|
|
17227
|
+
```
|
|
17228
|
+
|
|
17229
|
+
| Export | Kind | Summary |
|
|
17230
|
+
|--------|------|---------|
|
|
17231
|
+
| `ToolDurability` | _type_ | the port a tool body needs: `step`, `sleep`, `waitFor` |
|
|
17232
|
+
| `ToolDurabilityFactory` | _type_ | `(toolCallId, signal) => ToolDurability`, called once per call |
|
|
17233
|
+
| `DurableJsonValue` | _type_ | what a durable step result may hold — a record is read back in another process, so it must be JSON |
|
|
17234
|
+
| `createLocalStepDurability` | function | the durability engine — replay, absolute deadlines, park/deliver — over a two-method ledger the application owns |
|
|
17235
|
+
| `StepDurabilityLedger` | _type_ | the two methods an engine needs: `appendEvent`, `readEvents` |
|
|
17236
|
+
| `LocalStepDurability` | _type_ | what the engine returns; satisfies `ToolDurability` and adds `deliver` and record introspection for the ledger's owner |
|
|
17237
|
+
| `LocalStepDurabilityOptions` | _type_ | `{ store, conversationId, runId, signal?, subscribe?, clock? }` |
|
|
17238
|
+
| `AppendAgentStoreEvent` / `ReadAgentStoreEvents` / `AgentStoreEventEnvelope` / `AgentStoreEventPage` | _type_ | the ledger's row shapes, re-exported so a ledger is typed from the entrypoint that consumes it |
|
|
17239
|
+
| `AgentToolError` | class | the model-safe envelope a failed agent tool throws |
|
|
17240
|
+
| `isAgentToolError` | function | brand check for it — a consumer running its own loop no longer parses the message |
|
|
17241
|
+
|
|
17047
17242
|
### Catalog stamp
|
|
17048
17243
|
|
|
17049
17244
|
Every advertised tool and every tool result carries the fingerprint of the catalog it came
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stitchkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.91.0",
|
|
4
4
|
"description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -211,7 +211,7 @@
|
|
|
211
211
|
"build:js": "bun run build:entrypoints && bun scripts/preserve-webpack-ignore.mjs",
|
|
212
212
|
"build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly && bun scripts/rewrite-declaration-specifiers.mjs",
|
|
213
213
|
"build": "bun ../../scripts/package-build-lock.ts -- bun run build:unlocked",
|
|
214
|
-
"build:unlocked": "rm -rf dist && cp ../../CHANGELOG.md ./CHANGELOG.md && bun run build:js && chmod +x dist/upgrade-cli.js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-browser-executes.mjs && bun scripts/check-env-live.mjs && bun scripts/check-public-types.mjs && bun scripts/check-declarations-strict.mjs",
|
|
214
|
+
"build:unlocked": "rm -rf dist && cp ../../CHANGELOG.md ./CHANGELOG.md && bun run build:js && chmod +x dist/upgrade-cli.js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-browser-executes.mjs && bun scripts/check-env-live.mjs && bun scripts/check-public-types.mjs && bun scripts/check-durability-port-standalone.mjs && bun scripts/check-declarations-strict.mjs",
|
|
215
215
|
"dev": "bun run build:entrypoints -- --watch",
|
|
216
216
|
"prepack": "cp ../../README.md ./README.md && bun ../../scripts/gen-llms.ts && bun run build",
|
|
217
217
|
"test": "bun test",
|
package/dist/index-7rkhw9ec.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// src/tools/agent-tool-error.ts
|
|
2
|
-
var AGENT_TOOL_ERROR_BRAND = Symbol.for("stitchkit.AgentToolError");
|
|
3
|
-
|
|
4
|
-
class AgentToolError extends Error {
|
|
5
|
-
output;
|
|
6
|
-
constructor(output, cause) {
|
|
7
|
-
let message = "Tool execution failed";
|
|
8
|
-
try {
|
|
9
|
-
message = JSON.stringify(output);
|
|
10
|
-
} catch {}
|
|
11
|
-
super(message, cause === undefined ? undefined : { cause });
|
|
12
|
-
this.name = "AgentToolError";
|
|
13
|
-
this.output = output;
|
|
14
|
-
Object.defineProperty(this, AGENT_TOOL_ERROR_BRAND, { value: true });
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
function isAgentToolError(value) {
|
|
18
|
-
return typeof value === "object" && value !== null && AGENT_TOOL_ERROR_BRAND in value;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// src/tools/durability-context.ts
|
|
22
|
-
var contexts = new WeakMap;
|
|
23
|
-
function createToolDurabilityContext(factory) {
|
|
24
|
-
const context = {};
|
|
25
|
-
contexts.set(context, factory);
|
|
26
|
-
return context;
|
|
27
|
-
}
|
|
28
|
-
function resolveToolDurability(context, callId, signal) {
|
|
29
|
-
if (typeof context !== "object" || context === null)
|
|
30
|
-
return;
|
|
31
|
-
return contexts.get(context)?.(callId, signal);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export { AgentToolError, isAgentToolError, createToolDurabilityContext, resolveToolDurability };
|