stitchkit 0.114.2 → 0.116.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 +54 -0
- package/dist/agent-runtime/coding-tool-files.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-paths.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-refusals.d.ts +6 -0
- package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/contained-scan.d.ts +1 -1
- package/dist/agent-runtime/contained-scan.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox-broker.d.ts.map +1 -1
- package/dist/agent-runtime/sandbox-bubblewrap-storage.d.ts.map +1 -1
- package/dist/application/directory-inbox-files.d.ts.map +1 -1
- package/dist/application/file-state-store.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/coding-tools.js +6 -4
- package/dist/entrypoints/agent-runtime/harness.js +2 -1
- package/dist/entrypoints/agent-runtime/sandbox.js +13 -8
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +8 -6
- package/dist/entrypoints/agent-runtime/sqlite/node.js +8 -6
- package/dist/entrypoints/agent-runtime/testing.js +8 -6
- package/dist/entrypoints/agent-runtime.js +8 -6
- package/dist/entrypoints/application/diagnostic-journal.js +2 -2
- package/dist/entrypoints/application/directory-inbox.js +10 -7
- package/dist/entrypoints/cli/publish.js +11 -8
- package/dist/entrypoints/cli.js +6 -3
- package/dist/entrypoints/files.js +10 -7
- package/dist/entrypoints/process/owner-loss.js +1 -1
- package/dist/entrypoints/process.js +3 -3
- package/dist/entrypoints/react/keyboard/testing.js +1 -1
- package/dist/entrypoints/react/keyboard.js +11 -11
- package/dist/entrypoints/server.js +4 -4
- package/dist/entrypoints/telegram/grammy.js +2 -2
- package/dist/entrypoints/telegram.d.ts +1 -1
- package/dist/entrypoints/telegram.d.ts.map +1 -1
- package/dist/entrypoints/telegram.js +30 -14
- package/dist/entrypoints/tools.js +5 -2
- package/dist/files/chunk-spool.d.ts.map +1 -1
- package/dist/{index-2f9r0jgr.js → index-364k2zwa.js} +4 -4
- package/dist/{index-dc9ere5p.js → index-4g6qmgdx.js} +1 -1
- package/dist/index-6f49krb5.js +107 -0
- package/dist/{index-912sza5h.js → index-90p34rts.js} +1 -1
- package/dist/{index-07dcf2yn.js → index-ac6vvm30.js} +5 -2
- package/dist/{index-zrtrjkbf.js → index-arjmb6de.js} +183 -172
- package/dist/{index-7r4knwf8.js → index-dr3t5n1v.js} +14 -4
- package/dist/{index-84bf5spd.js → index-f6m4c545.js} +5 -2
- package/dist/{index-qj1sy4ep.js → index-fa435yq2.js} +1 -1
- package/dist/{index-hy802jnr.js → index-fdk4r4r6.js} +6 -3
- package/dist/index-jj9228tt.js +6 -0
- package/dist/{index-a3462dqf.js → index-jq2ky8fw.js} +1 -1
- package/dist/{index-s47ac8zt.js → index-n5sv4z0w.js} +142 -156
- package/dist/{index-bh2ht9y5.js → index-n8z3rvzw.js} +4 -1
- package/dist/index-q968hy6y.js +100 -0
- package/dist/{index-j4zh647a.js → index-tt30h7mr.js} +4 -1
- package/dist/{index-tnxsq7cw.js → index-w7jq3fz9.js} +113 -38
- package/dist/{index-p02zgk8x.js → index-y4rxnvgp.js} +6 -0
- package/dist/{index-5v5a9k2n.js → index-z3d6smer.js} +1 -1
- package/dist/{index-6b3pcq5z.js → index-zqkz4af9.js} +1 -1
- package/dist/internal/atomic-file.d.ts.map +1 -1
- package/dist/internal/atomic-staging.d.ts.map +1 -1
- package/dist/internal/contained-directory.d.ts +20 -0
- package/dist/internal/contained-directory.d.ts.map +1 -0
- package/dist/{agent-runtime → internal}/contained-files.d.ts +24 -13
- package/dist/internal/contained-files.d.ts.map +1 -0
- package/dist/internal/contained-handle.d.ts +30 -0
- package/dist/internal/contained-handle.d.ts.map +1 -0
- package/dist/internal/contained-write.d.ts +12 -0
- package/dist/internal/contained-write.d.ts.map +1 -0
- package/dist/internal/darwin-binding.d.ts +1 -1
- package/dist/internal/darwin-binding.d.ts.map +1 -1
- package/dist/internal/errno.d.ts +3 -0
- package/dist/internal/errno.d.ts.map +1 -0
- package/dist/internal/process-instance.d.ts.map +1 -1
- package/dist/internal/write-download.d.ts +5 -14
- package/dist/internal/write-download.d.ts.map +1 -1
- package/dist/process/group-diagnostics.d.ts +1 -0
- package/dist/process/group-diagnostics.d.ts.map +1 -1
- package/dist/process/group-settlement.d.ts +2 -0
- package/dist/process/group-settlement.d.ts.map +1 -1
- package/dist/process/group.d.ts.map +1 -1
- package/dist/process/owner-loss-control.d.ts.map +1 -1
- package/dist/react/keyboard/hooks.d.ts +2 -2
- package/dist/react/keyboard/hooks.d.ts.map +1 -1
- package/dist/react/keyboard/layers.d.ts +2 -0
- package/dist/react/keyboard/layers.d.ts.map +1 -1
- package/dist/telegram/broadcast-state.d.ts.map +1 -1
- package/dist/telegram/budget-transformer.d.ts +5 -2
- package/dist/telegram/budget-transformer.d.ts.map +1 -1
- package/dist/telegram/outbound-budget.d.ts +26 -11
- package/dist/telegram/outbound-budget.d.ts.map +1 -1
- package/dist/tools/cli/download.d.ts.map +1 -1
- package/dist/tools/cli/publication-storage.d.ts.map +1 -1
- package/dist/tools/cli/publication.d.ts.map +1 -1
- package/dist/tools/cli/view.d.ts +7 -1
- package/dist/tools/cli/view.d.ts.map +1 -1
- package/llms/agent-runtime.txt +16 -6
- package/llms/cli.txt +37 -3
- package/llms/process.txt +2 -2
- package/llms/react-keyboard.txt +18 -2
- package/llms/stitchkit.txt +3 -3
- package/llms/telegram.txt +10 -3
- package/llms/{upgrading-0.104.0-0.114.0.txt → upgrading-0.105.0-0.116.0.txt} +85 -124
- package/llms/{upgrading-0.44.0-0.61.0.txt → upgrading-0.44.0-0.62.0.txt} +120 -3
- package/llms/{upgrading-0.62.0-0.78.0.txt → upgrading-0.63.0-0.83.0.txt} +181 -120
- package/llms/{upgrading-0.79.0-0.103.13.txt → upgrading-0.84.0-0.104.0.txt} +124 -181
- package/llms/upgrading.txt +4 -4
- package/llms-full.txt +168 -19
- package/llms.txt +9 -9
- package/native/darwin-arm64.node +0 -0
- package/native/darwin-x64.node +0 -0
- package/native-assets.json +4 -4
- package/package.json +1 -1
- package/dist/agent-runtime/contained-darwin.d.ts +0 -21
- package/dist/agent-runtime/contained-darwin.d.ts.map +0 -1
- package/dist/agent-runtime/contained-files.d.ts.map +0 -1
- package/dist/agent-runtime/contained-write.d.ts +0 -9
- package/dist/agent-runtime/contained-write.d.ts.map +0 -1
|
@@ -1,14 +1,96 @@
|
|
|
1
|
-
# Upgrading 0.
|
|
1
|
+
# Upgrading 0.105.0 → 0.116.0 — stitchkit docs slice
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
5
|
|
|
6
|
-
Contains: Guide: Upgrading, 0.
|
|
6
|
+
Contains: Guide: Upgrading, 0.105.0 → 0.116.0 (docs/guide/upgrading.md)
|
|
7
7
|
|
|
8
8
|
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.
|
|
9
|
+
# Guide: Upgrading, 0.105.0 → 0.116.0 (docs/guide/upgrading.md)
|
|
10
10
|
==============================================================================
|
|
11
11
|
|
|
12
|
+
## Released migration: 0.116.0
|
|
13
|
+
|
|
14
|
+
### send-only-telegram-pause
|
|
15
|
+
|
|
16
|
+
**Who must act:** code that relied on a 429 from `editMessage*`, `deleteMessage` or a read to stop a
|
|
17
|
+
token's sends. Code that only sends needs no change.
|
|
18
|
+
|
|
19
|
+
`run` pauses the token only on a method that spends the budget
|
|
20
|
+
([ADR 0277](../decisions/0277-a-telegram-budget-serves-replies-first.md)). Where an edit must still stop
|
|
21
|
+
the sends, say so:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// before
|
|
25
|
+
await budget.run('editMessageText', payload, signal, send)
|
|
26
|
+
// after
|
|
27
|
+
await budget.run('editMessageText', payload, signal, send).catch((error) => {
|
|
28
|
+
budget.pauseAfter(error)
|
|
29
|
+
throw error
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Search pattern: `budget.run` next to edit and read methods.
|
|
34
|
+
|
|
35
|
+
## Released migration: 0.115.0
|
|
36
|
+
|
|
37
|
+
### contained-cli-downloads
|
|
38
|
+
|
|
39
|
+
**Who must act:** a CLI that uses `--output-dir` on Windows, from a macOS bundle or compiled binary
|
|
40
|
+
built without `createNativePackaging`, into a directory it cannot write or over bind-mounted files;
|
|
41
|
+
a coding-tools host that allows `edit` but refuses `read` for a path; and code or CSS that reads
|
|
42
|
+
`aria-orientation` of a `role: 'none'` zone. A CLI writing into its own directory on Linux or
|
|
43
|
+
unbundled macOS, and every CLI command without a download, need no change.
|
|
44
|
+
|
|
45
|
+
`--output-dir` now writes through a pinned directory descriptor
|
|
46
|
+
([ADR 0276](../decisions/0276-a-download-writes-through-its-root-capability.md)). There is no
|
|
47
|
+
path-based fallback, so a platform without that backend refuses the download: the operation still
|
|
48
|
+
succeeds, its result stays on stdout, stderr names the refusal and the exit is non-zero.
|
|
49
|
+
|
|
50
|
+
1. On macOS, build a bundled or compiled CLI with the native packaging plugin:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
// before
|
|
54
|
+
await Bun.build({
|
|
55
|
+
entrypoints: ['src/cli.ts'],
|
|
56
|
+
compile: { target: 'bun-darwin-arm64', outfile: 'dist/cli' },
|
|
57
|
+
})
|
|
58
|
+
// after
|
|
59
|
+
import { createNativePackaging } from 'stitchkit/files/packaging'
|
|
60
|
+
|
|
61
|
+
const native = createNativePackaging({
|
|
62
|
+
platform: 'darwin', architecture: 'arm64', delivery: 'embedded',
|
|
63
|
+
})
|
|
64
|
+
if (native.state !== 'ready') throw new Error(native.code)
|
|
65
|
+
await Bun.build({
|
|
66
|
+
entrypoints: ['src/cli.ts'],
|
|
67
|
+
compile: { target: 'bun-darwin-arm64', outfile: 'dist/cli' },
|
|
68
|
+
plugins: [native.plugin],
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
A JS bundle uses `delivery: 'companion'`; every shape is in the [native I/O guide](./native-io.md). Search pattern:
|
|
73
|
+
`createCli` with a `download` option in a project that runs `bun build` for macOS.
|
|
74
|
+
2. On Windows, run the download through Linux or macOS, or read the URLs from the operation's
|
|
75
|
+
JSON result and fetch them yourself. Stitchkit offers no weaker path on that platform.
|
|
76
|
+
3. A download now replaces a file rather than rewriting it. Give the process write permission on
|
|
77
|
+
the output directory, and do not point it at a bind-mounted file: that refuses with `EBUSY`. A
|
|
78
|
+
replaced file belongs to the process user, and a read-only file is replaced like any other.
|
|
79
|
+
4. Read the orientation you configured. A zone with `role: 'none'` has no attribute, and a default
|
|
80
|
+
would silently turn a horizontal zone vertical:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// before
|
|
84
|
+
const axis: ZoneOrientation = zone.zoneProps['aria-orientation']
|
|
85
|
+
// after
|
|
86
|
+
const axis: ZoneOrientation = options.orientation ?? 'vertical'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Search pattern: `aria-orientation` next to `useNavZone`, and `[aria-orientation]` in CSS and
|
|
90
|
+
test selectors. Type-check: a read typed as `ZoneOrientation` fails to compile.
|
|
91
|
+
5. In a coding-tools `authorize`, answer `read` for every path you answer `edit` for. `edit_file`
|
|
92
|
+
asks both, `read` first.
|
|
93
|
+
|
|
12
94
|
## Released migration: 0.114.0
|
|
13
95
|
|
|
14
96
|
**Who must act:** code with an exhaustive `switch` or `Record` over
|
|
@@ -735,124 +817,3 @@ in the second position is a type error.
|
|
|
735
817
|
|
|
736
818
|
4. Both classes accept the standard `cause`, which `error.cause` returns; omit the option to
|
|
737
819
|
leave the property absent.
|
|
738
|
-
|
|
739
|
-
## Released migration: 0.104.0
|
|
740
|
-
|
|
741
|
-
JS bundles carrying Darwin native capabilities also need the
|
|
742
|
-
[delivery migration first affected in 0.103.13](#released-migration-010313).
|
|
743
|
-
Consumers upgrading from 0.103.12 or earlier must apply it even if their TypeScript API is unchanged.
|
|
744
|
-
|
|
745
|
-
### CLI runtime-tool construction
|
|
746
|
-
|
|
747
|
-
**Who must act:** callers writing a schema-dependent handler or MCP/AI `present` directly
|
|
748
|
-
inside an annotated `CliConfig.runtimeTools` or `CliInvokerConfig.runtimeTools` object.
|
|
749
|
-
Native `commands` and values returned by `defineRuntimeTool` / `createRuntimeToolFactory`
|
|
750
|
-
remain valid. Execution, auth, validation and the invocation result envelope keep their behavior.
|
|
751
|
-
|
|
752
|
-
Construct a CLI-only managed definition with the neutral schema-aware type before registration:
|
|
753
|
-
|
|
754
|
-
```ts
|
|
755
|
-
import type { CliInvokerConfig, RuntimeToolExecutionWithOutput } from 'stitchkit/cli'
|
|
756
|
-
import { z } from 'zod'
|
|
757
|
-
|
|
758
|
-
const input = z.object({ text: z.string() })
|
|
759
|
-
const output = z.object({ size: z.number() })
|
|
760
|
-
// Before: handler receives the heterogeneous registry context.
|
|
761
|
-
const config: CliInvokerConfig = {
|
|
762
|
-
name: 'app',
|
|
763
|
-
runtimeTools: [{
|
|
764
|
-
name: 'measure', description: 'Measure text',
|
|
765
|
-
identity: { serviceName: 'text', action: 'measure', method: 'POST' },
|
|
766
|
-
transports: ['CLI'], input, output,
|
|
767
|
-
handler: ({ input }) => ({ size: String(input.text).length }),
|
|
768
|
-
}],
|
|
769
|
-
}
|
|
770
|
-
// After: handler input and output derive from the construction schemas.
|
|
771
|
-
const measure = {
|
|
772
|
-
name: 'measure', description: 'Measure text',
|
|
773
|
-
identity: { serviceName: 'text', action: 'measure', method: 'POST' },
|
|
774
|
-
transports: ['CLI'], input, output,
|
|
775
|
-
handler: ({ input }) => ({ size: input.text.length }),
|
|
776
|
-
} satisfies RuntimeToolExecutionWithOutput<typeof input, typeof output>
|
|
777
|
-
const nextConfig: CliInvokerConfig = { name: 'app', runtimeTools: [measure] }
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
For a shared MCP/AI tool, construct the definition with `defineRuntimeTool` from
|
|
781
|
-
`stitchkit/tools`, including its typed SDK `present` callbacks, then pass the returned value
|
|
782
|
-
to `runtimeTools`. Install the corresponding SDK peers for that integration. A CLI-only
|
|
783
|
-
consumer needs `stitchkit`, `zod` and its ordinary Node type tooling.
|
|
784
|
-
|
|
785
|
-
`RuntimeToolExecution` names the heterogeneous registration contract. Call a registered
|
|
786
|
-
operation through `createCli` or `createCliInvoker`; its erased handler input is `never`
|
|
787
|
-
because the managed runner owns schema validation before execution. For a managed void
|
|
788
|
-
definition, use `RuntimeToolDefinitionWithoutOutput<typeof input>`.
|
|
789
|
-
|
|
790
|
-
### MCP construction, state stores and delivery
|
|
791
|
-
|
|
792
|
-
**Who must act:** schema-dependent runtime tool literals written directly inside MCP mount
|
|
793
|
-
configuration, MCP presenters returning malformed content or metadata, custom `StateStore`
|
|
794
|
-
implementations, file-store consumers using retired lock
|
|
795
|
-
options, broadcast consumers reading `halt` or retrying unknown send outcomes, and consumers
|
|
796
|
-
that validate HTTP error envelopes with a closed schema. Applications collecting raw tool
|
|
797
|
-
causes from `console.error` must configure an internal tool hook sink.
|
|
798
|
-
|
|
799
|
-
MCP-only code can import the existing server factories from `stitchkit/tools/mcp` and
|
|
800
|
-
construct its schema-aware tool before heterogeneous registration:
|
|
801
|
-
|
|
802
|
-
```ts
|
|
803
|
-
import { buildMcpServer, type RuntimeMcpToolDefinitionWithOutput } from 'stitchkit/tools/mcp'
|
|
804
|
-
import { z } from 'zod'
|
|
805
|
-
const input = z.object({ value: z.number() })
|
|
806
|
-
const output = z.object({ doubled: z.number() })
|
|
807
|
-
// Before: runtimeTools: [{ input, output, handler, present }]
|
|
808
|
-
const double = {
|
|
809
|
-
name: 'double', description: 'Double a number',
|
|
810
|
-
identity: { serviceName: 'numbers', action: 'double', method: 'POST' },
|
|
811
|
-
input, output,
|
|
812
|
-
handler: ({ input }) => ({ doubled: input.value * 2 }),
|
|
813
|
-
present: { mcp: ({ doubled }) => ({ content: [{ type: 'text', text: String(doubled) }] }) },
|
|
814
|
-
} satisfies RuntimeMcpToolDefinitionWithOutput<typeof input, typeof output>
|
|
815
|
-
const server = buildMcpServer({ serverInfo: { name: 'numbers', version: '1' }, services: [], runtimeTools: [double] })
|
|
816
|
-
```
|
|
817
|
-
|
|
818
|
-
Full MCP/AI integrations keep `defineRuntimeTool` from `stitchkit/tools`; those typed values
|
|
819
|
-
remain accepted by the MCP leaf and CLI. The leaf requires the MCP SDK and Zod, with no AI peer.
|
|
820
|
-
|
|
821
|
-
`RuntimeMcpPresentation` preserves the official SDK's required `content` and typed `_meta`
|
|
822
|
-
fields. A presenter returning `{}` must return `{ content: [] }`; text blocks require string
|
|
823
|
-
text, and metadata must be an object. `structuredContent` and `isError` remain framework-owned.
|
|
824
|
-
This restores SDK checks that an indexed mapped type previously erased.
|
|
825
|
-
|
|
826
|
-
Unexpected tool causes remain in `hooks.onToolError` and the `error` field of
|
|
827
|
-
`hooks.afterToolCall`. Protocol stderr carries safe errors. MCP resolver failures use those
|
|
828
|
-
same observers without executing the handler or its lifecycle again. HTTP's default
|
|
829
|
-
unexpected-error logging retains its behavior.
|
|
830
|
-
|
|
831
|
-
A custom state adapter's `update` must invoke `transition(current, context)` while it still
|
|
832
|
-
owns the serialized transaction. `context.assertHeld()` checks the actual transaction or lock
|
|
833
|
-
generation and refuses after completion, rollback or ownership loss. A no-op guard cannot
|
|
834
|
-
satisfy this contract. Existing transition callbacks may keep one parameter. For the owning
|
|
835
|
-
file adapter, replace `{ staleLockMs, retryMs, lockTimeoutMs }` with `{ lockTimeoutMs }`:
|
|
836
|
-
the remaining budget controls acquisition waiting, never expiry of a live transaction.
|
|
837
|
-
Unknown legacy PID locks and historical temporary files are preserved; recover them only
|
|
838
|
-
after independently proving their owner is gone.
|
|
839
|
-
|
|
840
|
-
Broadcast consumers change `report.halt.reason` checks to the closed `halt.kind` union:
|
|
841
|
-
`retry-after`, `transient`, `permanent` or `ambiguous`. A custom MTProto adapter can classify
|
|
842
|
-
an acknowledged flood refusal as `{ kind: 'retry-after', retryAfterMs: wait }`; the exact
|
|
843
|
-
provider wait is respected. A wait over `maxRetryDelayMs` halts with the recipient pending.
|
|
844
|
-
Unknown write outcome becomes `uncertain`; restarting the same broadcast does not send it
|
|
845
|
-
again. A retry classification must certify that the attempt did not apply the external effect.
|
|
846
|
-
|
|
847
|
-
HTTP errors gain optional boolean `error.retryable`; framed contract streams use the same
|
|
848
|
-
field. Update closed consumer schemas before producers declaring it. `false` on 502 and
|
|
849
|
-
`true` on 409 remain explicit recommendations through the remote tool path. An absent field
|
|
850
|
-
retains prior status-derived defaults; the field does not change the HTTP client's retry policy.
|
|
851
|
-
The existing seventh `ApiError` constructor argument remains `ErrorOptions`; retryability is
|
|
852
|
-
the new eighth argument.
|
|
853
|
-
|
|
854
|
-
Caller cancellation now reaches `implementRemote`'s existing HTTP call. Applications bind
|
|
855
|
-
signals to `createCli` / `createCliInvoker` and cooperative handlers observe `ctx.signal`.
|
|
856
|
-
`REQUEST_ABORTED` is nonretryable and exits 130. A disconnected caller does not prove that
|
|
857
|
-
an origin ignoring cancellation or an external provider stopped; keep resource leases until
|
|
858
|
-
that work actually completes.
|
|
@@ -1,14 +1,131 @@
|
|
|
1
|
-
# Upgrading 0.44.0 → 0.
|
|
1
|
+
# Upgrading 0.44.0 → 0.62.0 — stitchkit docs slice
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
5
|
|
|
6
|
-
Contains: Guide: Upgrading, 0.44.0 → 0.
|
|
6
|
+
Contains: Guide: Upgrading, 0.44.0 → 0.62.0 (docs/guide/upgrading.md)
|
|
7
7
|
|
|
8
8
|
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.44.0 → 0.
|
|
9
|
+
# Guide: Upgrading, 0.44.0 → 0.62.0 (docs/guide/upgrading.md)
|
|
10
10
|
==============================================================================
|
|
11
11
|
|
|
12
|
+
## Released migration: 0.62.0
|
|
13
|
+
|
|
14
|
+
Two groups of behaviour changes. Nothing moves an export — the surface is
|
|
15
|
+
strictly additive — and every item changes what a running system reports or
|
|
16
|
+
sends, which is what this heading is for. One of them changes a number you may
|
|
17
|
+
already be billing against.
|
|
18
|
+
|
|
19
|
+
### A run reports what it spent
|
|
20
|
+
|
|
21
|
+
Three changes to what the runtime says about cost and tokens. Nothing moves an
|
|
22
|
+
export; all three change numbers a running system reports, and one of them
|
|
23
|
+
changes a number you may already be billing against.
|
|
24
|
+
|
|
25
|
+
#### Multi-step cost was under-reported and is now summed
|
|
26
|
+
|
|
27
|
+
No code change is needed to get the fix — but check any predicate that reads
|
|
28
|
+
`provenance`:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// before — accepted a number that was one step's cost, not the run's
|
|
32
|
+
if (usage.cost?.provenance === 'provider-reported') bill(usage.cost.value)
|
|
33
|
+
|
|
34
|
+
// after — a sum stitchkit performed says so
|
|
35
|
+
if (usage.cost && usage.cost.provenance !== 'unavailable') bill(usage.cost.value)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`'computed'` means stitchkit added up provider-reported parts. It is not a guess
|
|
39
|
+
— `'estimated'` is the word for that — but it is deliberately not
|
|
40
|
+
`'provider-reported'`, because that label is what a caller filters on when it
|
|
41
|
+
wants a figure it can bill against unchanged, and a sum is not one.
|
|
42
|
+
|
|
43
|
+
Token totals moved with it. The AI SDK's `totalUsage` is a sum *it* performed
|
|
44
|
+
over per-step provider figures — not a run total any provider handed over — so
|
|
45
|
+
labelling it `provider-reported` was the same overstatement. **A run total on a
|
|
46
|
+
terminal event is always `computed`.** If you want a figure with the provider's
|
|
47
|
+
own word on it, read `step-finished`: each step carries what that call reported.
|
|
48
|
+
|
|
49
|
+
#### `usage` is always present on a terminal event
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// before — absent when the run ended before the provider's `finish`
|
|
53
|
+
const spent = event.usage?.cost?.value ?? 0 // silently 0 for a real spend
|
|
54
|
+
|
|
55
|
+
// after — present, and it says what it does not know
|
|
56
|
+
event.usage?.cost?.provenance === 'unavailable' // we spent, and cannot say how much
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Keep the optional chaining: one `AgentRunEvent` shape covers `run-started`,
|
|
60
|
+
`step-finished` and `run-terminal`, so `usage` stays optional on the type. The
|
|
61
|
+
guarantee is about terminal events, and a schema shared with `run-started`
|
|
62
|
+
cannot express it.
|
|
63
|
+
|
|
64
|
+
**Do not read `unavailable` as zero.** A run aborted mid-stream has spent real
|
|
65
|
+
money that nobody has counted; a run that never reached the provider has not.
|
|
66
|
+
Both used to look the same and now do not.
|
|
67
|
+
|
|
68
|
+
#### A losing executor reports its own spend
|
|
69
|
+
|
|
70
|
+
An execution that loses the terminal compare-and-swap now emits an operator
|
|
71
|
+
`run-terminal` event, because it ran and it spent. If a sink treated those events
|
|
72
|
+
as "runs this process committed", that is no longer true — `AgentRuntimeResult.metrics`
|
|
73
|
+
is still `undefined` for a losing executor and remains the way to tell.
|
|
74
|
+
|
|
75
|
+
The *delivery* `terminal` event is unchanged and still fires only for the winner,
|
|
76
|
+
so nothing delivers a turn twice.
|
|
77
|
+
|
|
78
|
+
### An interrupted answer stops passing as a finished one
|
|
79
|
+
|
|
80
|
+
Two behaviour changes, one shared cause: a run ended by a newer input used to
|
|
81
|
+
leave its half-written answer in the conversation with no sign that it was cut
|
|
82
|
+
off, and the next request to the provider carried it as an ordinary assistant
|
|
83
|
+
turn.
|
|
84
|
+
|
|
85
|
+
#### The projection marks an interrupted turn
|
|
86
|
+
|
|
87
|
+
Nothing to change to adopt the fix — the default is the fixed behaviour. What to
|
|
88
|
+
check is whether the marker is the *right* form for your surface, and the
|
|
89
|
+
question that decides it is not "was the run interrupted" but **"did anyone see
|
|
90
|
+
what it produced"**.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// after — pick the form; the default is 'assistant-marked'
|
|
94
|
+
createAgentRuntime({ history: { interruptedAssistant: 'system-note' } })
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
- **The user pressed stop and the text was on their screen** — keep
|
|
98
|
+
`'assistant-marked'`. The assistant turn is the truthful record of what the
|
|
99
|
+
human read, and the model should stay consistent with it.
|
|
100
|
+
- **The partial never reached anyone** — a surface that sends nothing until the
|
|
101
|
+
run is done — prefer `'system-note'`. An assistant turn in provider history is
|
|
102
|
+
a commitment the model stays consistent with; a system line is context.
|
|
103
|
+
|
|
104
|
+
If you pass `history.project` you own the projection outright and none of this
|
|
105
|
+
applies — but the same question does.
|
|
106
|
+
|
|
107
|
+
#### A run ended by a newer input can now say so
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
// before
|
|
111
|
+
runs: { inputPolicy: 'interrupt' } // ends the run, keeps its partial answer
|
|
112
|
+
|
|
113
|
+
// after — for a surface where a follow-up message invalidates the answer
|
|
114
|
+
// in flight rather than merely stopping it
|
|
115
|
+
runs: { inputPolicy: 'supersede' } // ends the run, discards its partial answer
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`inputPolicy` also accepts `(input) => policy`, which is how one application
|
|
119
|
+
gives two conversation surfaces different rules without the runtime learning
|
|
120
|
+
which is which.
|
|
121
|
+
|
|
122
|
+
A superseded run terminates with `terminalReason: 'superseded'`, state
|
|
123
|
+
`'superseded'` and an assistant message of status `'superseded'`. **If you switch
|
|
124
|
+
exhaustively on any of those enums, add the arm** — that is the part of this
|
|
125
|
+
release that can break a build rather than a behaviour. The record itself is
|
|
126
|
+
kept: it is excluded from the projection, not deleted, so an operator can still
|
|
127
|
+
see what was thrown away.
|
|
128
|
+
|
|
12
129
|
## Released migration: 0.61.0
|
|
13
130
|
|
|
14
131
|
Three behaviour changes between versions. None moves an export — the surface is
|
|
@@ -1,14 +1,192 @@
|
|
|
1
|
-
# Upgrading 0.
|
|
1
|
+
# Upgrading 0.63.0 → 0.83.0 — stitchkit docs slice
|
|
2
2
|
|
|
3
3
|
> Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
|
|
4
4
|
> `llms.txt` in this package.
|
|
5
5
|
|
|
6
|
-
Contains: Guide: Upgrading, 0.
|
|
6
|
+
Contains: Guide: Upgrading, 0.63.0 → 0.83.0 (docs/guide/upgrading.md)
|
|
7
7
|
|
|
8
8
|
==============================================================================
|
|
9
|
-
# Guide: Upgrading, 0.
|
|
9
|
+
# Guide: Upgrading, 0.63.0 → 0.83.0 (docs/guide/upgrading.md)
|
|
10
10
|
==============================================================================
|
|
11
11
|
|
|
12
|
+
## Released migration: 0.83.0
|
|
13
|
+
|
|
14
|
+
Two things, both mechanical, and only if you touch an observability sink.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
rg -n "createObservability|createApplicationEventSink|createApplicationSnapshotSink|createAgentRuntimeEventSink|createAgentObservability"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**1. `flush()` returns `Promise<boolean>`.** `await sink.flush()` needs no
|
|
21
|
+
change. Only a declared type does:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// before
|
|
25
|
+
const flushAudit: () => Promise<void> = observability.flush
|
|
26
|
+
// after
|
|
27
|
+
const flushAudit: () => Promise<boolean> = observability.flush
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**2. `ObservabilityDrainReport` carries `drained`.** The framework builds it, so
|
|
31
|
+
reading code is unchanged. A hand-built report — a test double, or one persisted
|
|
32
|
+
and re-parsed through `ObservabilityDrainReportSchema` — needs the field:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// before
|
|
36
|
+
{ request, tools, total, durationMs }
|
|
37
|
+
// after
|
|
38
|
+
{ request, tools, total, durationMs, drained: true }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then take the thing this release exists for. Every drain now accepts
|
|
42
|
+
`{ timeoutMs?, signal? }`, so a shutdown can give the audit drain the same
|
|
43
|
+
deadline it gives every other step:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
const report = await observability.close({ timeoutMs: 5_000 })
|
|
47
|
+
if (!report.drained) {
|
|
48
|
+
logger.warn('audit drain incomplete', {
|
|
49
|
+
unwritten: report.total.received - report.total.filtered - report.total.completed,
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The bound ends the **waiting**, not the writes: a sink's `write` is handed no
|
|
55
|
+
cancellation, so an outstanding one keeps running against whatever you close
|
|
56
|
+
next. Racing `close()` against your own timer looks equivalent and is not — it
|
|
57
|
+
discards the report along with the wait.
|
|
58
|
+
|
|
59
|
+
## Released migration: 0.82.0
|
|
60
|
+
|
|
61
|
+
One thing, and only if you mount MCP or agent tools from a `createTrackingContract` contract.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
rg -n "createTrackingContract"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The event ingest (`track`, `POST /events`) is now `expose: ['HTTP']`, which is
|
|
68
|
+
what its sibling `bootstrap` always declared. Before, it declared nothing — and
|
|
69
|
+
an endpoint with no `expose` is a tool on MCP and AGENT by default, so the
|
|
70
|
+
mounted surface carried a `track_<prefix>` tool. Since this contract is built
|
|
71
|
+
inside the framework, an application that had made every tool opt-in for the
|
|
72
|
+
endpoints *it* authors could not have opted this one out.
|
|
73
|
+
|
|
74
|
+
**If you pin a tool-surface digest or count**, it moves by one; re-record it.
|
|
75
|
+
**If you assert on tool names**, `track_<prefix>` is gone. **If nothing in your
|
|
76
|
+
project mounts tools from this contract**, there is nothing to do — the HTTP
|
|
77
|
+
routes, the client and the schemas are unchanged.
|
|
78
|
+
|
|
79
|
+
Un-declaring the tool was never the intent, so there is no option to keep it. If
|
|
80
|
+
an agent in your system genuinely needs to record something, give it your own
|
|
81
|
+
endpoint with your own schema: the browser ingest trusts a client-minted event
|
|
82
|
+
id and a visit lease, and an agent holds neither.
|
|
83
|
+
|
|
84
|
+
## Released migration: 0.81.0
|
|
85
|
+
|
|
86
|
+
**Path literals own string params.**
|
|
87
|
+
|
|
88
|
+
An endpoint whose path contains `:id` or a terminal `*rest` no longer needs a
|
|
89
|
+
duplicate `params: z.object({ …string() })` declaration. Remove schemas that do
|
|
90
|
+
nothing beyond repeating path names:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// before
|
|
94
|
+
{ path: '/projects/:projectId/*filePath',
|
|
95
|
+
params: z.object({ projectId: z.string(), filePath: z.string() }) }
|
|
96
|
+
|
|
97
|
+
// after
|
|
98
|
+
{ path: '/projects/:projectId/*filePath' }
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Keep an explicit schema when it validates or coerces. It must cover every name
|
|
102
|
+
in the path — an explicit schema that misses one now fails at `defineContract`
|
|
103
|
+
with the path and the missing field named. Client calls and handler contexts
|
|
104
|
+
infer the string fields from the literal, so a call that omitted one becomes a
|
|
105
|
+
compile error instead of building a URL with an unresolved segment. Measured
|
|
106
|
+
across three consuming applications before release (373 endpoints with path
|
|
107
|
+
segments), no explicit schema missed a field: the migration is deleting
|
|
108
|
+
schemas that only repeated the path, or nothing.
|
|
109
|
+
|
|
110
|
+
## Released migration: 0.80.0
|
|
111
|
+
|
|
112
|
+
One thing, and only if you parse an async-operation snapshot.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
rg -n "createAsyncOperationSnapshotSchema"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`progress` on a parsed snapshot used to be `unknown`. The factory built its
|
|
119
|
+
object shapes with a conditional spread, and the narrowing inside it widened
|
|
120
|
+
your schema back to a bare `ZodType`, so the emitted declaration threw the type
|
|
121
|
+
argument away. It is now the output of the schema you configured.
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
const schema = createAsyncOperationSnapshotSchema({
|
|
125
|
+
progress: z.object({ done: z.number(), total: z.number() }),
|
|
126
|
+
failure: z.object({ code: z.string() }),
|
|
127
|
+
})
|
|
128
|
+
const snap = schema.parse(body)
|
|
129
|
+
if (snap.phase === 'running') {
|
|
130
|
+
// before: `snap.progress` was `unknown` — this needed a cast or a narrow
|
|
131
|
+
// after: it is `{ done: number; total: number } | undefined`
|
|
132
|
+
console.log(snap.progress?.done)
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**If you cast it**, delete the cast — it was working around the erased type.
|
|
137
|
+
**If you assigned something else to it**, the compiler now refuses, and it was
|
|
138
|
+
already a value the schema rejected at run time.
|
|
139
|
+
|
|
140
|
+
**If you pass explicit type arguments**, the no-progress form takes one now, not
|
|
141
|
+
two: the factory is two overloads. Pass none.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
// before: createAsyncOperationSnapshotSchema<undefined, typeof Failure>({ failure: Failure })
|
|
145
|
+
// after: createAsyncOperationSnapshotSchema({ failure: Failure })
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Nothing about parsing moves. A snapshot configured without `progress` still
|
|
149
|
+
strips an unexpected `progress` rather than refusing it — that behaviour is why
|
|
150
|
+
this is overloads and not one normalised key.
|
|
151
|
+
|
|
152
|
+
**If you compile with `skipLibCheck: false`**, this is also the release that
|
|
153
|
+
makes `stitchkit/tools/contract` compile at all: it carried five `TS2344`
|
|
154
|
+
errors, one per phase, from the same conditional spread.
|
|
155
|
+
|
|
156
|
+
## Released migration: 0.79.0
|
|
157
|
+
|
|
158
|
+
One thing, and only if you assert on the whole snapshot.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
rg -n "getSnapshot\(\)|projectApplicationStatus|status\(\)" --glob '*.test.ts' --glob '*.spec.ts'
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`ApplicationSnapshot` and `ApplicationStatusProjection` each gained a
|
|
165
|
+
`restarting` field — ids in the snapshot, a count in the projection. A reader
|
|
166
|
+
that names the fields it wants is unaffected. A test that compares the whole
|
|
167
|
+
object with `toEqual` fails until it adds the field:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
// before
|
|
171
|
+
expect(body).toEqual({ id, lifecycle: 'ready', /* … */ resources: { total: 1, ready: 1, degraded: 0, failed: 0 } })
|
|
172
|
+
// after
|
|
173
|
+
expect(body).toEqual({ id, lifecycle: 'ready', /* … */ resources: { total: 1, ready: 1, degraded: 0, failed: 0 }, restarting: 0 })
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
It is zero except while a restart is running, and then it names the subtree being
|
|
177
|
+
replaced. That is the point: a snapshot taken mid-restart used to be
|
|
178
|
+
indistinguishable from a resource that had failed on its own, so a dashboard read
|
|
179
|
+
a planned replacement as an outage.
|
|
180
|
+
|
|
181
|
+
**If you watch a hub across a restart**, nothing to change, but the behaviour is
|
|
182
|
+
different and better: closing a hub now tells its subscribers `unavailable` /
|
|
183
|
+
`source-unavailable` instead of dropping them, so a page stops showing a value
|
|
184
|
+
that will never update again.
|
|
185
|
+
|
|
186
|
+
**If you need a tool contract in a browser**, `stitchkit/tools/contract` now
|
|
187
|
+
carries the async-operation helpers, its schemas and the view-file input/output
|
|
188
|
+
without the runtime. `stitchkit/tools` still exports all of them.
|
|
189
|
+
|
|
12
190
|
## Released migration: 0.78.0
|
|
13
191
|
|
|
14
192
|
Two mechanical edits. Find them both:
|
|
@@ -974,120 +1152,3 @@ const spent = checkpoints.at(-1)?.metrics.usage?.cost?.value
|
|
|
974
1152
|
`AgentRun.usage` is written at every checkpoint and with the terminal record, so
|
|
975
1153
|
a dropped observability event no longer loses the number, and a process that dies
|
|
976
1154
|
mid-stream leaves behind what it had already spent.
|
|
977
|
-
|
|
978
|
-
## Released migration: 0.62.0
|
|
979
|
-
|
|
980
|
-
Two groups of behaviour changes. Nothing moves an export — the surface is
|
|
981
|
-
strictly additive — and every item changes what a running system reports or
|
|
982
|
-
sends, which is what this heading is for. One of them changes a number you may
|
|
983
|
-
already be billing against.
|
|
984
|
-
|
|
985
|
-
### A run reports what it spent
|
|
986
|
-
|
|
987
|
-
Three changes to what the runtime says about cost and tokens. Nothing moves an
|
|
988
|
-
export; all three change numbers a running system reports, and one of them
|
|
989
|
-
changes a number you may already be billing against.
|
|
990
|
-
|
|
991
|
-
#### Multi-step cost was under-reported and is now summed
|
|
992
|
-
|
|
993
|
-
No code change is needed to get the fix — but check any predicate that reads
|
|
994
|
-
`provenance`:
|
|
995
|
-
|
|
996
|
-
```ts
|
|
997
|
-
// before — accepted a number that was one step's cost, not the run's
|
|
998
|
-
if (usage.cost?.provenance === 'provider-reported') bill(usage.cost.value)
|
|
999
|
-
|
|
1000
|
-
// after — a sum stitchkit performed says so
|
|
1001
|
-
if (usage.cost && usage.cost.provenance !== 'unavailable') bill(usage.cost.value)
|
|
1002
|
-
```
|
|
1003
|
-
|
|
1004
|
-
`'computed'` means stitchkit added up provider-reported parts. It is not a guess
|
|
1005
|
-
— `'estimated'` is the word for that — but it is deliberately not
|
|
1006
|
-
`'provider-reported'`, because that label is what a caller filters on when it
|
|
1007
|
-
wants a figure it can bill against unchanged, and a sum is not one.
|
|
1008
|
-
|
|
1009
|
-
Token totals moved with it. The AI SDK's `totalUsage` is a sum *it* performed
|
|
1010
|
-
over per-step provider figures — not a run total any provider handed over — so
|
|
1011
|
-
labelling it `provider-reported` was the same overstatement. **A run total on a
|
|
1012
|
-
terminal event is always `computed`.** If you want a figure with the provider's
|
|
1013
|
-
own word on it, read `step-finished`: each step carries what that call reported.
|
|
1014
|
-
|
|
1015
|
-
#### `usage` is always present on a terminal event
|
|
1016
|
-
|
|
1017
|
-
```ts
|
|
1018
|
-
// before — absent when the run ended before the provider's `finish`
|
|
1019
|
-
const spent = event.usage?.cost?.value ?? 0 // silently 0 for a real spend
|
|
1020
|
-
|
|
1021
|
-
// after — present, and it says what it does not know
|
|
1022
|
-
event.usage?.cost?.provenance === 'unavailable' // we spent, and cannot say how much
|
|
1023
|
-
```
|
|
1024
|
-
|
|
1025
|
-
Keep the optional chaining: one `AgentRunEvent` shape covers `run-started`,
|
|
1026
|
-
`step-finished` and `run-terminal`, so `usage` stays optional on the type. The
|
|
1027
|
-
guarantee is about terminal events, and a schema shared with `run-started`
|
|
1028
|
-
cannot express it.
|
|
1029
|
-
|
|
1030
|
-
**Do not read `unavailable` as zero.** A run aborted mid-stream has spent real
|
|
1031
|
-
money that nobody has counted; a run that never reached the provider has not.
|
|
1032
|
-
Both used to look the same and now do not.
|
|
1033
|
-
|
|
1034
|
-
#### A losing executor reports its own spend
|
|
1035
|
-
|
|
1036
|
-
An execution that loses the terminal compare-and-swap now emits an operator
|
|
1037
|
-
`run-terminal` event, because it ran and it spent. If a sink treated those events
|
|
1038
|
-
as "runs this process committed", that is no longer true — `AgentRuntimeResult.metrics`
|
|
1039
|
-
is still `undefined` for a losing executor and remains the way to tell.
|
|
1040
|
-
|
|
1041
|
-
The *delivery* `terminal` event is unchanged and still fires only for the winner,
|
|
1042
|
-
so nothing delivers a turn twice.
|
|
1043
|
-
|
|
1044
|
-
### An interrupted answer stops passing as a finished one
|
|
1045
|
-
|
|
1046
|
-
Two behaviour changes, one shared cause: a run ended by a newer input used to
|
|
1047
|
-
leave its half-written answer in the conversation with no sign that it was cut
|
|
1048
|
-
off, and the next request to the provider carried it as an ordinary assistant
|
|
1049
|
-
turn.
|
|
1050
|
-
|
|
1051
|
-
#### The projection marks an interrupted turn
|
|
1052
|
-
|
|
1053
|
-
Nothing to change to adopt the fix — the default is the fixed behaviour. What to
|
|
1054
|
-
check is whether the marker is the *right* form for your surface, and the
|
|
1055
|
-
question that decides it is not "was the run interrupted" but **"did anyone see
|
|
1056
|
-
what it produced"**.
|
|
1057
|
-
|
|
1058
|
-
```ts
|
|
1059
|
-
// after — pick the form; the default is 'assistant-marked'
|
|
1060
|
-
createAgentRuntime({ history: { interruptedAssistant: 'system-note' } })
|
|
1061
|
-
```
|
|
1062
|
-
|
|
1063
|
-
- **The user pressed stop and the text was on their screen** — keep
|
|
1064
|
-
`'assistant-marked'`. The assistant turn is the truthful record of what the
|
|
1065
|
-
human read, and the model should stay consistent with it.
|
|
1066
|
-
- **The partial never reached anyone** — a surface that sends nothing until the
|
|
1067
|
-
run is done — prefer `'system-note'`. An assistant turn in provider history is
|
|
1068
|
-
a commitment the model stays consistent with; a system line is context.
|
|
1069
|
-
|
|
1070
|
-
If you pass `history.project` you own the projection outright and none of this
|
|
1071
|
-
applies — but the same question does.
|
|
1072
|
-
|
|
1073
|
-
#### A run ended by a newer input can now say so
|
|
1074
|
-
|
|
1075
|
-
```ts
|
|
1076
|
-
// before
|
|
1077
|
-
runs: { inputPolicy: 'interrupt' } // ends the run, keeps its partial answer
|
|
1078
|
-
|
|
1079
|
-
// after — for a surface where a follow-up message invalidates the answer
|
|
1080
|
-
// in flight rather than merely stopping it
|
|
1081
|
-
runs: { inputPolicy: 'supersede' } // ends the run, discards its partial answer
|
|
1082
|
-
```
|
|
1083
|
-
|
|
1084
|
-
`inputPolicy` also accepts `(input) => policy`, which is how one application
|
|
1085
|
-
gives two conversation surfaces different rules without the runtime learning
|
|
1086
|
-
which is which.
|
|
1087
|
-
|
|
1088
|
-
A superseded run terminates with `terminalReason: 'superseded'`, state
|
|
1089
|
-
`'superseded'` and an assistant message of status `'superseded'`. **If you switch
|
|
1090
|
-
exhaustively on any of those enums, add the arm** — that is the part of this
|
|
1091
|
-
release that can break a build rather than a behaviour. The record itself is
|
|
1092
|
-
kept: it is excluded from the projection, not deleted, so an operator can still
|
|
1093
|
-
see what was thrown away.
|