stitchkit 0.86.0 → 0.87.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 +83 -0
- package/dist/agent-runtime/conversations.d.ts +11 -0
- package/dist/agent-runtime/conversations.d.ts.map +1 -1
- package/dist/agent-runtime/schedules.d.ts.map +1 -1
- package/dist/agent-runtime/sqlite.d.ts.map +1 -1
- package/dist/agent-runtime/store-migrations/v1-to-v2.d.ts.map +1 -1
- package/dist/agent-runtime-harness.js +2 -3
- package/dist/agent-runtime-sqlite-bun.js +4 -4
- package/dist/agent-runtime-sqlite-node.js +4 -4
- package/dist/agent-runtime.js +72 -33
- package/dist/{index-33xckd7h.js → index-35aefxby.js} +2 -4
- package/dist/{index-b7qwhbzq.js → index-3yrqvza8.js} +55 -27
- package/dist/{index-hber83mk.js → index-5wezxcxx.js} +24 -44
- package/dist/index-9553432s.js +26 -0
- package/dist/{index-vfgb58nf.js → index-z1m86vc8.js} +83 -1
- package/dist/internal/sqlite.d.ts +13 -0
- package/dist/internal/sqlite.d.ts.map +1 -1
- package/dist/testing/agent-store-conformance.d.ts.map +1 -1
- package/dist/testing.js +38 -3
- package/llms-full.txt +55 -6
- package/package.json +1 -1
- package/dist/index-y2s6h5bf.js +0 -83
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,89 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
|
|
|
15
15
|
|
|
16
16
|
## [Unreleased]
|
|
17
17
|
|
|
18
|
+
## [0.87.0] — 2026-09-08
|
|
19
|
+
|
|
20
|
+
### ⚠️ Breaking changes
|
|
21
|
+
|
|
22
|
+
**Who must act:** applications that implement `AgentConversationReader`
|
|
23
|
+
themselves. Applications that only call the reader returned by the SQLite store
|
|
24
|
+
need no change.
|
|
25
|
+
|
|
26
|
+
- **A message page says which of its messages compaction removed.**
|
|
27
|
+
`AgentConversationMessagePage` gains a required `compacted: string[]`, so a
|
|
28
|
+
reader that builds the page itself now names the ids in `items` that are no
|
|
29
|
+
longer part of the model's history — an empty array when it does not page
|
|
30
|
+
them at all.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
// before
|
|
34
|
+
return { items, ...(nextCursor && { nextCursor }) }
|
|
35
|
+
|
|
36
|
+
// after
|
|
37
|
+
return { items, compacted: [], ...(nextCursor && { nextCursor }) }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- **The history compaction removed can be read.** `conversations.messages`
|
|
43
|
+
takes `includeCompacted`, off by default. With it the page carries the whole
|
|
44
|
+
conversation in the order it happened, and `compacted` names the ids the
|
|
45
|
+
model no longer sees. Those rows were always in the store and no public read
|
|
46
|
+
reached them — every path filtered the active history — so an application
|
|
47
|
+
that shows a person their own long conversation had to keep a second copy of
|
|
48
|
+
it beside the store, which is the copy the event ledger exists to make
|
|
49
|
+
unnecessary. Paging is exact across a compaction boundary: a summary is
|
|
50
|
+
written at the position of the first message it replaced, so position alone
|
|
51
|
+
stopped identifying a row, and the page cursor now carries the row identity
|
|
52
|
+
beside it. A cursor issued by an earlier version still means what it meant.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- **The v1 → v2 baseline carries the compacted history.** The migration built
|
|
57
|
+
each conversation's `runtime/baseline` from the active messages only, so for
|
|
58
|
+
exactly the conversations long enough to have been compacted the ledger could
|
|
59
|
+
not reconstruct what the person had said, while the normalized table still
|
|
60
|
+
held it. The baseline now records the whole sequence with `compacted` naming
|
|
61
|
+
what had been folded away. A file already migrated by 0.86.0 keeps the
|
|
62
|
+
baseline it got — one event cannot be rewritten after the fact — and its
|
|
63
|
+
compacted messages remain readable through `includeCompacted`.
|
|
64
|
+
- **A conversation that has a turn in it can be imported again.**
|
|
65
|
+
`importConversation` refused every archive whose snapshot carried a run —
|
|
66
|
+
that is, every conversation anyone actually had — with `Conversation archive
|
|
67
|
+
snapshot target is not empty`, into a target it had just reported empty. The
|
|
68
|
+
SQLite head compare-and-swap read its outcome from the driver's `changes`
|
|
69
|
+
count, and `bun:sqlite` counts what the event table's `AFTER INSERT` trigger
|
|
70
|
+
and FTS5's deferred index flush wrote during the same statement: an import
|
|
71
|
+
appends the whole archived ledger before it writes the head, so a swap that
|
|
72
|
+
moved one row reported five and was read as a conflict. The swap now reads
|
|
73
|
+
the version, compares it, and writes unconditionally inside the store's
|
|
74
|
+
`BEGIN IMMEDIATE` transaction. Export was never affected, and the memory
|
|
75
|
+
store never had the defect. Reported from a real consumer against published
|
|
76
|
+
0.86.0.
|
|
77
|
+
- **A first head write is a compare-and-swap.** The same conditional upsert
|
|
78
|
+
guarded only its update branch, so a swap against a conversation with no head
|
|
79
|
+
row applied whatever `expectedVersion` it was given instead of conflicting.
|
|
80
|
+
No path in the runtime reaches it — a version above zero implies the row —
|
|
81
|
+
but the shipped Prisma example adapter carried the same shape and is fixed
|
|
82
|
+
with it.
|
|
83
|
+
|
|
84
|
+
### Changed
|
|
85
|
+
|
|
86
|
+
- **`SqliteStatement.run`'s `changes` is documented as advisory.** The boundary
|
|
87
|
+
is satisfied structurally by a raw driver handle, so the number is that
|
|
88
|
+
driver's, and it may count trigger and virtual-table writes. Nothing in the
|
|
89
|
+
runtime decides correctness by it any more: the schedule claim, the firing
|
|
90
|
+
finalize and the cancellation each read their row and then write, the way the
|
|
91
|
+
head swap does. No input reached those three — each wrote before it appended
|
|
92
|
+
its event — and their observable behaviour is unchanged.
|
|
93
|
+
- **`runAgentStoreConformance` imports a conversation that has a run.** The kit
|
|
94
|
+
now announces an eighth conversation identity and carries a reference archive
|
|
95
|
+
with one accepted turn into the adapter under test, then compares the
|
|
96
|
+
restored snapshot and ledger against it. Adapters that provision from
|
|
97
|
+
`context.conversationIds`, as the kit has always required, need no change; an
|
|
98
|
+
adapter that cannot import a run-bearing archive now fails the kit instead of
|
|
99
|
+
passing it.
|
|
100
|
+
|
|
18
101
|
## [0.86.0] — 2026-09-08
|
|
19
102
|
|
|
20
103
|
### ⚠️ Breaking changes
|
|
@@ -107,6 +107,7 @@ export declare const AgentConversationMessagePageSchema: z.ZodObject<{
|
|
|
107
107
|
createdAt: z.ZodISODateTime;
|
|
108
108
|
updatedAt: z.ZodISODateTime;
|
|
109
109
|
}, z.core.$strip>>;
|
|
110
|
+
compacted: z.ZodArray<z.ZodString>;
|
|
110
111
|
nextCursor: z.ZodOptional<z.ZodString>;
|
|
111
112
|
}, z.core.$strict>;
|
|
112
113
|
export type AgentConversationSummary = z.infer<typeof AgentConversationSummarySchema>;
|
|
@@ -123,6 +124,16 @@ export interface AgentConversationReader {
|
|
|
123
124
|
cursor?: string;
|
|
124
125
|
limit: number;
|
|
125
126
|
direction: 'before' | 'after';
|
|
127
|
+
/**
|
|
128
|
+
* Include the messages compaction removed from the model's history.
|
|
129
|
+
*
|
|
130
|
+
* Off by default: the model's view is what most callers page. A person
|
|
131
|
+
* reading back their own conversation needs the other one — the store
|
|
132
|
+
* keeps those rows, and without this they were reachable by no public
|
|
133
|
+
* read, which left an application keeping a second copy of its own
|
|
134
|
+
* history beside the store.
|
|
135
|
+
*/
|
|
136
|
+
includeCompacted?: boolean;
|
|
126
137
|
}): Promise<AgentConversationMessagePage>;
|
|
127
138
|
}
|
|
128
139
|
//# sourceMappingURL=conversations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,8BAA8B;;;;;;kBAQhC,CAAC;AAEZ,eAAO,MAAM,2BAA2B;;;;;;;;;kBAK7B,CAAC;AAEZ,eAAO,MAAM,kCAAkC
|
|
1
|
+
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,8BAA8B;;;;;;kBAQhC,CAAC;AAEZ,eAAO,MAAM,2BAA2B;;;;;;;;;kBAK7B,CAAC;AAEZ,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAepC,CAAC;AAEZ,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AACtF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAChF,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAC;QAC9B;;;;;;;;WAQG;QACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;CAC3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/schedules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;kBAcrB,CAAC;AACZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,OAAO,EAAE;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3B,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,aAAa,EAAE,CAAC;IAChE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"schedules.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/schedules.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;kBAcrB,CAAC;AACZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,OAAO,EAAE;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3B,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,aAAa,EAAE,CAAC;IAChE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf;AA+DD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IAChD,MAAM,EAAE,uBAAuB,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9B,QAAQ,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC;KAChE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IACpF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,CAAC;IAC5D;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,GAAG,oBAAoB,CA4UvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/sqlite.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EAML,uBAAuB,EACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,KAAK,uBAAuB,EAG5B,KAAK,qBAAqB,EAG3B,MAAM,gBAAgB,CAAC;AAMxB,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEvF,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,cAAc,CAAC;IACzB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,cAAc,CAAC,CAAC,CAAC;IAClE,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;;;OAOG;IACH,QAAQ,EAAE,cAAc,CAAC;IACzB;;;;;;;;;OASG;IACH,WAAW,CAAC,MAAM,EAChB,IAAI,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,MAAM,CAAC,GACvD,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,oFAAoF;IACpF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,4DAA4D;AAC5D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC7E;
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/sqlite.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EAML,uBAAuB,EACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,KAAK,uBAAuB,EAG5B,KAAK,qBAAqB,EAG3B,MAAM,gBAAgB,CAAC;AAMxB,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEvF,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,cAAc,CAAC;IACzB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,cAAc,CAAC,CAAC,CAAC;IAClE,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;;;OAOG;IACH,QAAQ,EAAE,cAAc,CAAC;IACzB;;;;;;;;;OASG;IACH,WAAW,CAAC,MAAM,EAChB,IAAI,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,MAAM,CAAC,GACvD,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,oFAAoF;IACpF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,4DAA4D;AAC5D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC7E;AAwKD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAqG3E;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,6BAA6B,GACpC,uBAAuB,CAwqBzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v1-to-v2.d.ts","sourceRoot":"","sources":["../../../src/agent-runtime/store-migrations/v1-to-v2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"v1-to-v2.d.ts","sourceRoot":"","sources":["../../../src/agent-runtime/store-migrations/v1-to-v2.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AA8N5D,8EAA8E;AAC9E,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,cAAc,EACxB,UAAU,GAAE,MAAiC,GAC5C,IAAI,CAQN;AAED,8DAA8D;AAC9D,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAE/E"}
|
|
@@ -6,14 +6,13 @@ import {
|
|
|
6
6
|
composeAgentPrompt,
|
|
7
7
|
createAgentRuntime,
|
|
8
8
|
createAgentRuntimeEventSink
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-35aefxby.js";
|
|
10
10
|
import"./index-p13mwz16.js";
|
|
11
11
|
import"./index-hkm6wysp.js";
|
|
12
12
|
import {
|
|
13
13
|
AgentModelDescriptorSchema
|
|
14
14
|
} from "./index-tg3m2ec5.js";
|
|
15
|
-
import"./index-
|
|
16
|
-
import"./index-vfgb58nf.js";
|
|
15
|
+
import"./index-z1m86vc8.js";
|
|
17
16
|
import"./index-p1b1y93x.js";
|
|
18
17
|
import"./index-wnfk50r0.js";
|
|
19
18
|
import {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSqliteAgentRuntimeStore,
|
|
3
3
|
initializeAgentRuntimeSqlite
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
7
|
-
import"./index-
|
|
4
|
+
} from "./index-3yrqvza8.js";
|
|
5
|
+
import"./index-9553432s.js";
|
|
6
|
+
import"./index-5wezxcxx.js";
|
|
7
|
+
import"./index-z1m86vc8.js";
|
|
8
8
|
import"./index-p1b1y93x.js";
|
|
9
9
|
|
|
10
10
|
// src/agent-runtime-sqlite-bun.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSqliteAgentRuntimeStore,
|
|
3
3
|
initializeAgentRuntimeSqlite
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
7
|
-
import"./index-
|
|
4
|
+
} from "./index-3yrqvza8.js";
|
|
5
|
+
import"./index-9553432s.js";
|
|
6
|
+
import"./index-5wezxcxx.js";
|
|
7
|
+
import"./index-z1m86vc8.js";
|
|
8
8
|
import"./index-p1b1y93x.js";
|
|
9
9
|
|
|
10
10
|
// src/agent-runtime-sqlite-node.ts
|
package/dist/agent-runtime.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ACTIVE_AGENT_RUN_STATES,
|
|
3
|
-
AgentAdmissionReceiptSchema,
|
|
4
2
|
AgentConversationMessagePageSchema,
|
|
5
3
|
AgentConversationPageSchema,
|
|
4
|
+
AgentConversationSummarySchema
|
|
5
|
+
} from "./index-9553432s.js";
|
|
6
|
+
import {
|
|
7
|
+
ACTIVE_AGENT_RUN_STATES,
|
|
8
|
+
AgentAdmissionReceiptSchema,
|
|
6
9
|
AgentConversationPurgeInputSchema,
|
|
7
10
|
AgentConversationPurgeResultSchema,
|
|
8
11
|
AgentConversationPurgedError,
|
|
9
|
-
AgentConversationSummarySchema,
|
|
10
12
|
AgentHistoryMutationSchema,
|
|
11
13
|
AgentRuntimeHeadSchema,
|
|
12
14
|
AgentStoredRunSchema,
|
|
13
15
|
createAgentRuntimeStore,
|
|
14
16
|
createMemoryAgentRuntimeStore,
|
|
15
17
|
purgeAgentConversation
|
|
16
|
-
} from "./index-
|
|
18
|
+
} from "./index-5wezxcxx.js";
|
|
17
19
|
import {
|
|
18
20
|
AgentContextOverflowError,
|
|
19
21
|
AgentProviderStreamCutError,
|
|
@@ -40,7 +42,7 @@ import {
|
|
|
40
42
|
renderAgentStateSlots,
|
|
41
43
|
repairedSearchCall,
|
|
42
44
|
selectAgentHistory
|
|
43
|
-
} from "./index-
|
|
45
|
+
} from "./index-35aefxby.js";
|
|
44
46
|
import"./index-p13mwz16.js";
|
|
45
47
|
import {
|
|
46
48
|
AgentAdmissionEventSchema,
|
|
@@ -76,10 +78,6 @@ import {
|
|
|
76
78
|
searchAgentModelCatalog,
|
|
77
79
|
validateAgentModelSnapshot
|
|
78
80
|
} from "./index-tg3m2ec5.js";
|
|
79
|
-
import {
|
|
80
|
-
isAssistantHistoryEvidence,
|
|
81
|
-
isCompleteAgentHistoryTurn
|
|
82
|
-
} from "./index-y2s6h5bf.js";
|
|
83
81
|
import {
|
|
84
82
|
AcceptInputAndAssignRunSchema,
|
|
85
83
|
AcquireAgentRunSchema,
|
|
@@ -107,8 +105,10 @@ import {
|
|
|
107
105
|
canonicalAgentJson,
|
|
108
106
|
decodeAgentConversationArchive,
|
|
109
107
|
decodeAgentStoreEvent,
|
|
110
|
-
encodeAgentConversationArchive
|
|
111
|
-
|
|
108
|
+
encodeAgentConversationArchive,
|
|
109
|
+
isAssistantHistoryEvidence,
|
|
110
|
+
isCompleteAgentHistoryTurn
|
|
111
|
+
} from "./index-z1m86vc8.js";
|
|
112
112
|
import {
|
|
113
113
|
AgentAssistantPlaceholderSchema,
|
|
114
114
|
AgentControlPartSchema,
|
|
@@ -1771,6 +1771,17 @@ var ScheduleRowSchema = z9.object({
|
|
|
1771
1771
|
created_at: z9.string(),
|
|
1772
1772
|
updated_at: z9.string()
|
|
1773
1773
|
});
|
|
1774
|
+
var ClaimRowSchema = z9.object({
|
|
1775
|
+
state: z9.enum(["scheduled", "cancelled", "completed"]),
|
|
1776
|
+
claim_until: z9.string().nullable()
|
|
1777
|
+
});
|
|
1778
|
+
var FinalizeRowSchema = z9.object({
|
|
1779
|
+
state: z9.enum(["scheduled", "cancelled", "completed"]),
|
|
1780
|
+
claim_owner: z9.string().nullable()
|
|
1781
|
+
});
|
|
1782
|
+
var StateRowSchema = z9.object({
|
|
1783
|
+
state: z9.enum(["scheduled", "cancelled", "completed"])
|
|
1784
|
+
});
|
|
1774
1785
|
function parseSchedule(raw) {
|
|
1775
1786
|
const row = ScheduleRowSchema.parse(raw);
|
|
1776
1787
|
return AgentScheduleSchema.parse({
|
|
@@ -1828,11 +1839,24 @@ function createAgentScheduleService(input) {
|
|
|
1828
1839
|
const owner = randomUUID2();
|
|
1829
1840
|
const CLAIM_MS = 60000;
|
|
1830
1841
|
let ticking;
|
|
1831
|
-
const claim = (id, until, at) => input.sqlite.transaction(async (scope) =>
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1842
|
+
const claim = (id, until, at) => input.sqlite.transaction(async (scope) => {
|
|
1843
|
+
const raw = scope.database.prepare(`
|
|
1844
|
+
SELECT state, claim_until FROM stitchkit_agent_runtime_schedules WHERE id = ?
|
|
1845
|
+
`).get(id);
|
|
1846
|
+
if (raw === null || raw === undefined)
|
|
1847
|
+
return false;
|
|
1848
|
+
const row = ClaimRowSchema.parse(raw);
|
|
1849
|
+
if (row.state !== "scheduled")
|
|
1850
|
+
return false;
|
|
1851
|
+
if (row.claim_until !== null && row.claim_until >= at)
|
|
1852
|
+
return false;
|
|
1853
|
+
scope.database.prepare(`
|
|
1854
|
+
UPDATE stitchkit_agent_runtime_schedules
|
|
1855
|
+
SET claim_owner = ?, claim_until = ?, updated_at = ?
|
|
1856
|
+
WHERE id = ?
|
|
1857
|
+
`).run(owner, until, at, id);
|
|
1858
|
+
return true;
|
|
1859
|
+
});
|
|
1836
1860
|
const runTick = async () => {
|
|
1837
1861
|
if (closed)
|
|
1838
1862
|
return;
|
|
@@ -1886,12 +1910,21 @@ function createAgentScheduleService(input) {
|
|
|
1886
1910
|
}
|
|
1887
1911
|
const state = schedule.kind === "every" ? "scheduled" : "completed";
|
|
1888
1912
|
await input.sqlite.transaction(async (scope) => {
|
|
1889
|
-
const
|
|
1913
|
+
const held = scope.database.prepare(`
|
|
1914
|
+
SELECT state, claim_owner FROM stitchkit_agent_runtime_schedules WHERE id = ?
|
|
1915
|
+
`).get(schedule.id);
|
|
1916
|
+
const settled = held !== null && held !== undefined && (() => {
|
|
1917
|
+
const row = FinalizeRowSchema.parse(held);
|
|
1918
|
+
return row.state === "scheduled" && row.claim_owner === owner;
|
|
1919
|
+
})();
|
|
1920
|
+
if (settled) {
|
|
1921
|
+
scope.database.prepare(`
|
|
1890
1922
|
UPDATE stitchkit_agent_runtime_schedules
|
|
1891
1923
|
SET state = ?, occurrence = ?, next_at = ?, updated_at = ?,
|
|
1892
1924
|
claim_owner = NULL, claim_until = NULL
|
|
1893
|
-
WHERE id = ?
|
|
1894
|
-
`).run(state, occurrence, nextAt, at, schedule.id
|
|
1925
|
+
WHERE id = ?
|
|
1926
|
+
`).run(state, occurrence, nextAt, at, schedule.id);
|
|
1927
|
+
}
|
|
1895
1928
|
if (lateByMs > 0) {
|
|
1896
1929
|
await scope.appendEvent({
|
|
1897
1930
|
conversationId: schedule.conversationId,
|
|
@@ -1983,23 +2016,29 @@ function createAgentScheduleService(input) {
|
|
|
1983
2016
|
const cancelSchedule = async (conversationId, id) => {
|
|
1984
2017
|
const observedAt = now().toISOString();
|
|
1985
2018
|
const changed = await input.sqlite.transaction(async (scope) => {
|
|
1986
|
-
const
|
|
2019
|
+
const raw = scope.database.prepare(`
|
|
2020
|
+
SELECT state FROM stitchkit_agent_runtime_schedules
|
|
2021
|
+
WHERE id = ? AND conversation_id = ?
|
|
2022
|
+
`).get(id, conversationId);
|
|
2023
|
+
if (raw === null || raw === undefined)
|
|
2024
|
+
return false;
|
|
2025
|
+
if (StateRowSchema.parse(raw).state !== "scheduled")
|
|
2026
|
+
return false;
|
|
2027
|
+
scope.database.prepare(`
|
|
1987
2028
|
UPDATE stitchkit_agent_runtime_schedules SET state = 'cancelled', updated_at = ?
|
|
1988
|
-
WHERE id = ? AND conversation_id = ?
|
|
1989
|
-
`).run(observedAt, id, conversationId)
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
}
|
|
1998
|
-
return count;
|
|
2029
|
+
WHERE id = ? AND conversation_id = ?
|
|
2030
|
+
`).run(observedAt, id, conversationId);
|
|
2031
|
+
await scope.appendEvent({
|
|
2032
|
+
conversationId,
|
|
2033
|
+
kind: "schedule/cancelled",
|
|
2034
|
+
occurredAt: observedAt,
|
|
2035
|
+
payload: { id }
|
|
2036
|
+
});
|
|
2037
|
+
return true;
|
|
1999
2038
|
});
|
|
2000
|
-
if (changed
|
|
2039
|
+
if (changed)
|
|
2001
2040
|
arm();
|
|
2002
|
-
return changed
|
|
2041
|
+
return changed;
|
|
2003
2042
|
};
|
|
2004
2043
|
return {
|
|
2005
2044
|
scheduleInput,
|
|
@@ -9,13 +9,11 @@ import {
|
|
|
9
9
|
advanceToolChronology,
|
|
10
10
|
assistantStatus,
|
|
11
11
|
canProjectToolChronology,
|
|
12
|
+
canonicalAgentJson,
|
|
12
13
|
createToolChronology,
|
|
13
14
|
isAssistantHistoryEvidence,
|
|
14
15
|
isCompleteAgentHistoryTurn
|
|
15
|
-
} from "./index-
|
|
16
|
-
import {
|
|
17
|
-
canonicalAgentJson
|
|
18
|
-
} from "./index-vfgb58nf.js";
|
|
16
|
+
} from "./index-z1m86vc8.js";
|
|
19
17
|
import {
|
|
20
18
|
AgentAssistantPlaceholderSchema,
|
|
21
19
|
AgentJsonObjectSchema,
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AgentAdmissionReceiptSchema,
|
|
3
2
|
AgentConversationMessagePageSchema,
|
|
4
|
-
AgentConversationPageSchema
|
|
3
|
+
AgentConversationPageSchema
|
|
4
|
+
} from "./index-9553432s.js";
|
|
5
|
+
import {
|
|
6
|
+
AgentAdmissionReceiptSchema,
|
|
5
7
|
AgentConversationPurgedError,
|
|
6
8
|
AgentHistoryMutationSchema,
|
|
7
9
|
AgentRuntimeHeadSchema,
|
|
8
10
|
AgentStoredRunSchema,
|
|
9
11
|
createAgentRuntimeStore
|
|
10
|
-
} from "./index-
|
|
12
|
+
} from "./index-5wezxcxx.js";
|
|
11
13
|
import {
|
|
12
14
|
AgentRecoverableDescriptorSchema,
|
|
13
15
|
AgentRecoverablePageSchema,
|
|
@@ -16,7 +18,7 @@ import {
|
|
|
16
18
|
AppendAgentStoreEventSchema,
|
|
17
19
|
agentStoreEventDraft,
|
|
18
20
|
canonicalAgentJson
|
|
19
|
-
} from "./index-
|
|
21
|
+
} from "./index-z1m86vc8.js";
|
|
20
22
|
import {
|
|
21
23
|
AgentMessageSchema,
|
|
22
24
|
AgentRunSchema
|
|
@@ -87,6 +89,10 @@ var PayloadRowSchema = z.object({
|
|
|
87
89
|
payload: z.string(),
|
|
88
90
|
terminal_assistant_payload: z.string().nullable().optional()
|
|
89
91
|
});
|
|
92
|
+
var HistoryRowSchema = z.object({
|
|
93
|
+
payload: z.string(),
|
|
94
|
+
active: z.union([z.literal(0), z.literal(1)])
|
|
95
|
+
});
|
|
90
96
|
var AdmissionRowSchema = z.object({
|
|
91
97
|
conversation_id: z.string(),
|
|
92
98
|
idempotency_key: z.string(),
|
|
@@ -202,7 +208,15 @@ function writeBaselines(database, migratedAt) {
|
|
|
202
208
|
) VALUES (?, 1, ?, 1, 'runtime/baseline', ?, 0, ?)
|
|
203
209
|
`);
|
|
204
210
|
for (const conversation of conversations) {
|
|
205
|
-
const
|
|
211
|
+
const rows = database.prepare("SELECT payload, active FROM stitchkit_agent_runtime_messages WHERE conversation_id = ? ORDER BY position, rowid").all(conversation.conversation_id).map((row) => {
|
|
212
|
+
const parsed = HistoryRowSchema.parse(row);
|
|
213
|
+
return {
|
|
214
|
+
message: AgentMessageSchema.parse(parseJson(parsed.payload)),
|
|
215
|
+
active: parsed.active === 1
|
|
216
|
+
};
|
|
217
|
+
});
|
|
218
|
+
const messages = rows.map((row) => row.message);
|
|
219
|
+
const compacted = rows.filter((row) => !row.active).map((row) => row.message.id);
|
|
206
220
|
const runs = database.prepare("SELECT payload, terminal_assistant_payload FROM stitchkit_agent_runtime_runs WHERE conversation_id = ? ORDER BY created_at, run_id").all(conversation.conversation_id).map((value) => {
|
|
207
221
|
const row = PayloadRowSchema.parse(value);
|
|
208
222
|
return {
|
|
@@ -234,6 +248,7 @@ function writeBaselines(database, migratedAt) {
|
|
|
234
248
|
version: conversation.version
|
|
235
249
|
},
|
|
236
250
|
messages,
|
|
251
|
+
...compacted.length > 0 && { compacted },
|
|
237
252
|
runs,
|
|
238
253
|
admissions
|
|
239
254
|
}));
|
|
@@ -276,7 +291,9 @@ var ConversationHeadRowSchema = z2.object({
|
|
|
276
291
|
});
|
|
277
292
|
var CountRowSchema = z2.object({ count: z2.number().int().nonnegative() });
|
|
278
293
|
var MessagePageRowSchema = z2.object({
|
|
294
|
+
row_id: z2.number().int().positive(),
|
|
279
295
|
position: z2.number().int().nonnegative(),
|
|
296
|
+
active: z2.union([z2.literal(0), z2.literal(1)]),
|
|
280
297
|
payload: z2.string()
|
|
281
298
|
});
|
|
282
299
|
var EventRowSchema = z2.object({
|
|
@@ -367,11 +384,16 @@ function conversationCursor(conversationId) {
|
|
|
367
384
|
function parseConversationCursor(cursor) {
|
|
368
385
|
return z2.tuple([z2.string().min(1)]).parse(parseJson2(cursor))[0];
|
|
369
386
|
}
|
|
370
|
-
function messageCursor(position) {
|
|
371
|
-
return encodeJson([position]);
|
|
387
|
+
function messageCursor(position, rowId) {
|
|
388
|
+
return encodeJson([position, rowId]);
|
|
372
389
|
}
|
|
373
390
|
function parseMessageCursor(cursor) {
|
|
374
|
-
|
|
391
|
+
const parsed = z2.union([
|
|
392
|
+
z2.tuple([z2.int().nonnegative(), z2.int().positive()]),
|
|
393
|
+
z2.tuple([z2.int().nonnegative()])
|
|
394
|
+
]).parse(parseJson2(cursor));
|
|
395
|
+
const [position, rowId] = parsed;
|
|
396
|
+
return { position, ...rowId !== undefined && { rowId } };
|
|
375
397
|
}
|
|
376
398
|
function messagePreview(message) {
|
|
377
399
|
const text = message.parts.find((part) => part.type === "text");
|
|
@@ -516,19 +538,16 @@ function createSqliteAgentRuntimeStore(config) {
|
|
|
516
538
|
});
|
|
517
539
|
},
|
|
518
540
|
async compareAndSwap(transaction, input) {
|
|
519
|
-
const
|
|
541
|
+
const current = transaction.prepare("SELECT version FROM stitchkit_agent_runtime_heads WHERE conversation_id = ?").get(input.conversationId);
|
|
542
|
+
const actualVersion = missing(current) ? 0 : HeadRowSchema.parse(current).version;
|
|
543
|
+
if (actualVersion !== input.expectedVersion)
|
|
544
|
+
return { outcome: "conflict", actualVersion };
|
|
545
|
+
transaction.prepare(`
|
|
520
546
|
INSERT INTO stitchkit_agent_runtime_heads (conversation_id, version)
|
|
521
547
|
VALUES (?, ?)
|
|
522
548
|
ON CONFLICT (conversation_id) DO UPDATE SET version = excluded.version
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
if (result.changes === 1)
|
|
526
|
-
return { outcome: "applied" };
|
|
527
|
-
const current = transaction.prepare("SELECT version FROM stitchkit_agent_runtime_heads WHERE conversation_id = ?").get(input.conversationId);
|
|
528
|
-
return {
|
|
529
|
-
outcome: "conflict",
|
|
530
|
-
actualVersion: missing(current) ? 0 : HeadRowSchema.parse(current).version
|
|
531
|
-
};
|
|
549
|
+
`).run(input.conversationId, input.next.version);
|
|
550
|
+
return { outcome: "applied" };
|
|
532
551
|
}
|
|
533
552
|
},
|
|
534
553
|
runs: {
|
|
@@ -873,14 +892,14 @@ function createSqliteAgentRuntimeStore(config) {
|
|
|
873
892
|
const pageRows = rows.slice(0, input.limit);
|
|
874
893
|
const items = pageRows.map((row) => {
|
|
875
894
|
const latestRaw = database.prepare(`
|
|
876
|
-
SELECT
|
|
895
|
+
SELECT payload FROM stitchkit_agent_runtime_messages
|
|
877
896
|
WHERE conversation_id = ? AND active = 1
|
|
878
897
|
ORDER BY position DESC LIMIT 1
|
|
879
898
|
`).get(row.conversation_id);
|
|
880
899
|
if (missing(latestRaw)) {
|
|
881
900
|
throw new Error("Agent conversation head has no active history");
|
|
882
901
|
}
|
|
883
|
-
const latest = AgentMessageSchema.parse(parseJson2(
|
|
902
|
+
const latest = AgentMessageSchema.parse(parseJson2(MessageRowSchema.parse(latestRaw).payload));
|
|
884
903
|
const active = CountRowSchema.parse(database.prepare(`
|
|
885
904
|
SELECT count(*) AS count FROM stitchkit_agent_runtime_runs
|
|
886
905
|
WHERE conversation_id = ?
|
|
@@ -906,19 +925,28 @@ function createSqliteAgentRuntimeStore(config) {
|
|
|
906
925
|
}
|
|
907
926
|
const cursor = input.cursor ? parseMessageCursor(input.cursor) : undefined;
|
|
908
927
|
const before = input.direction === "before";
|
|
928
|
+
const direction = before ? "DESC" : "ASC";
|
|
929
|
+
const comparison = cursor === undefined ? "" : cursor.rowId === undefined ? `AND position ${before ? "<" : ">"} ?` : `AND (position, rowid) ${before ? "<" : ">"} (?, ?)`;
|
|
909
930
|
const rows = database.prepare(`
|
|
910
|
-
SELECT position, payload
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
931
|
+
SELECT rowid AS row_id, position, active, payload
|
|
932
|
+
FROM stitchkit_agent_runtime_messages
|
|
933
|
+
WHERE conversation_id = ?
|
|
934
|
+
${input.includeCompacted === true ? "" : "AND active = 1"}
|
|
935
|
+
${comparison}
|
|
936
|
+
ORDER BY position ${direction}, rowid ${direction} LIMIT ?
|
|
937
|
+
`).all(input.conversationId, ...cursor === undefined ? [] : cursor.rowId === undefined ? [cursor.position] : [cursor.position, cursor.rowId], input.limit + 1).map((row) => MessagePageRowSchema.parse(row));
|
|
915
938
|
const hasMore = rows.length > input.limit;
|
|
916
939
|
const pageRows = rows.slice(0, input.limit);
|
|
917
940
|
const ordered = before ? [...pageRows].reverse() : pageRows;
|
|
918
941
|
const boundary = pageRows.at(-1);
|
|
942
|
+
const items = ordered.map((row) => ({
|
|
943
|
+
message: AgentMessageSchema.parse(parseJson2(row.payload)),
|
|
944
|
+
active: row.active === 1
|
|
945
|
+
}));
|
|
919
946
|
return AgentConversationMessagePageSchema.parse({
|
|
920
|
-
items:
|
|
921
|
-
|
|
947
|
+
items: items.map((entry) => entry.message),
|
|
948
|
+
compacted: items.filter((entry) => !entry.active).map((entry) => entry.message.id),
|
|
949
|
+
...hasMore && boundary ? { nextCursor: messageCursor(boundary.position, boundary.row_id) } : {}
|
|
922
950
|
});
|
|
923
951
|
})
|
|
924
952
|
},
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
assistantStatus
|
|
3
|
-
} from "./index-y2s6h5bf.js";
|
|
4
1
|
import {
|
|
5
2
|
AcceptInputAndAssignRunSchema,
|
|
6
3
|
AcquireAgentRunSchema,
|
|
@@ -18,10 +15,11 @@ import {
|
|
|
18
15
|
ReplaceCompactedRangeSchema,
|
|
19
16
|
RequestRunInterruptSchema,
|
|
20
17
|
agentStoreEventDraft,
|
|
18
|
+
assistantStatus,
|
|
21
19
|
canonicalAgentJson,
|
|
22
20
|
decodeAgentConversationArchive,
|
|
23
21
|
encodeAgentConversationArchive
|
|
24
|
-
} from "./index-
|
|
22
|
+
} from "./index-z1m86vc8.js";
|
|
25
23
|
import {
|
|
26
24
|
AgentMessageSchema,
|
|
27
25
|
AgentRecordIdSchema,
|
|
@@ -61,27 +59,9 @@ async function purgeAgentConversation(store, input) {
|
|
|
61
59
|
return AgentConversationPurgeResultSchema.parse(await store.purgeConversation(parsed));
|
|
62
60
|
}
|
|
63
61
|
|
|
64
|
-
// src/agent-runtime/conversations.ts
|
|
65
|
-
import { z as z2 } from "zod";
|
|
66
|
-
var AgentConversationSummarySchema = z2.object({
|
|
67
|
-
conversationId: AgentRecordIdSchema,
|
|
68
|
-
version: AgentRecordVersionSchema,
|
|
69
|
-
updatedAt: z2.iso.datetime({ offset: true }),
|
|
70
|
-
preview: z2.string(),
|
|
71
|
-
activeRuns: z2.int().nonnegative()
|
|
72
|
-
}).strict();
|
|
73
|
-
var AgentConversationPageSchema = z2.object({
|
|
74
|
-
items: z2.array(AgentConversationSummarySchema),
|
|
75
|
-
nextCursor: z2.string().min(1).optional()
|
|
76
|
-
}).strict();
|
|
77
|
-
var AgentConversationMessagePageSchema = z2.object({
|
|
78
|
-
items: z2.array(AgentMessageSchema),
|
|
79
|
-
nextCursor: z2.string().min(1).optional()
|
|
80
|
-
}).strict();
|
|
81
|
-
|
|
82
62
|
// src/agent-runtime/store-driver.ts
|
|
83
63
|
import { createHash } from "node:crypto";
|
|
84
|
-
import { z as
|
|
64
|
+
import { z as z2 } from "zod";
|
|
85
65
|
|
|
86
66
|
// src/agent-runtime/store-purge.ts
|
|
87
67
|
function createStoreConversationPurge(driver, conversations) {
|
|
@@ -107,39 +87,39 @@ function createStoreConversationPurge(driver, conversations) {
|
|
|
107
87
|
}
|
|
108
88
|
|
|
109
89
|
// src/agent-runtime/store-driver.ts
|
|
110
|
-
var AgentRuntimeHeadSchema =
|
|
111
|
-
schemaVersion:
|
|
90
|
+
var AgentRuntimeHeadSchema = z2.object({
|
|
91
|
+
schemaVersion: z2.literal(1),
|
|
112
92
|
conversationId: AgentRecordIdSchema,
|
|
113
93
|
version: AgentRecordVersionSchema
|
|
114
94
|
});
|
|
115
|
-
var AgentStoredRunSchema =
|
|
116
|
-
schemaVersion:
|
|
95
|
+
var AgentStoredRunSchema = z2.object({
|
|
96
|
+
schemaVersion: z2.literal(1),
|
|
117
97
|
run: AgentRunSchema,
|
|
118
98
|
terminalAssistant: AgentMessageSchema.optional()
|
|
119
99
|
});
|
|
120
|
-
var AgentAdmissionReceiptSchema =
|
|
121
|
-
schemaVersion:
|
|
100
|
+
var AgentAdmissionReceiptSchema = z2.object({
|
|
101
|
+
schemaVersion: z2.literal(1),
|
|
122
102
|
conversationId: AgentRecordIdSchema,
|
|
123
|
-
idempotencyKey:
|
|
103
|
+
idempotencyKey: z2.string().min(1),
|
|
124
104
|
input: AgentMessageSchema,
|
|
125
105
|
runId: AgentRecordIdSchema,
|
|
126
106
|
assistantMessageId: AgentRecordIdSchema
|
|
127
107
|
});
|
|
128
|
-
var AgentHistoryMutationSchema =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
type:
|
|
108
|
+
var AgentHistoryMutationSchema = z2.discriminatedUnion("type", [
|
|
109
|
+
z2.object({ type: z2.literal("admit"), input: AgentMessageSchema }),
|
|
110
|
+
z2.object({
|
|
111
|
+
type: z2.literal("upsert-assistant"),
|
|
132
112
|
message: AgentMessageSchema
|
|
133
113
|
}),
|
|
134
|
-
|
|
135
|
-
type:
|
|
136
|
-
replacedMessageIds:
|
|
114
|
+
z2.object({
|
|
115
|
+
type: z2.literal("replace-compacted-range"),
|
|
116
|
+
replacedMessageIds: z2.array(AgentRecordIdSchema).min(1),
|
|
137
117
|
summary: AgentMessageSchema
|
|
138
118
|
})
|
|
139
119
|
]);
|
|
140
|
-
var AgentRecoverableScanInputSchema =
|
|
141
|
-
cursor:
|
|
142
|
-
limit:
|
|
120
|
+
var AgentRecoverableScanInputSchema = z2.object({
|
|
121
|
+
cursor: z2.string().min(1).optional(),
|
|
122
|
+
limit: z2.number().int().min(1).max(1000)
|
|
143
123
|
});
|
|
144
124
|
function transitionRecord(operation) {
|
|
145
125
|
if (operation.type !== "checkpoint")
|
|
@@ -262,7 +242,7 @@ function validateSnapshot(head, messages, records) {
|
|
|
262
242
|
}
|
|
263
243
|
}
|
|
264
244
|
}
|
|
265
|
-
var RecoverableCursorSchema =
|
|
245
|
+
var RecoverableCursorSchema = z2.tuple([AgentRecordIdSchema, AgentRecordIdSchema]);
|
|
266
246
|
function recoverableCursor(input) {
|
|
267
247
|
return JSON.stringify([input.conversationId, input.run.id]);
|
|
268
248
|
}
|
|
@@ -738,7 +718,7 @@ function createAgentRuntimeStore(driver) {
|
|
|
738
718
|
await driver.events.append(transaction, agentStoreEventDraft({
|
|
739
719
|
conversationId,
|
|
740
720
|
kind: "runtime/transition",
|
|
741
|
-
payload:
|
|
721
|
+
payload: z2.json().parse(transitionRecord(operation))
|
|
742
722
|
}));
|
|
743
723
|
return { outcome: "applied", snapshot: reduced.snapshot };
|
|
744
724
|
});
|
|
@@ -778,7 +758,7 @@ function createAgentRuntimeStore(driver) {
|
|
|
778
758
|
conversationId,
|
|
779
759
|
events,
|
|
780
760
|
projections: [
|
|
781
|
-
{ archiveType: "runtime-snapshot", snapshot:
|
|
761
|
+
{ archiveType: "runtime-snapshot", snapshot: z2.json().parse(snapshot) },
|
|
782
762
|
...durable.projections
|
|
783
763
|
],
|
|
784
764
|
spills: durable.spills
|
|
@@ -1111,4 +1091,4 @@ function createMemoryAgentRuntimeStore() {
|
|
|
1111
1091
|
return createAgentRuntimeStore(driver);
|
|
1112
1092
|
}
|
|
1113
1093
|
|
|
1114
|
-
export { AgentConversationPurgeInputSchema, AgentConversationPurgeResultSchema, AgentConversationPurgedError, purgeAgentConversation,
|
|
1094
|
+
export { AgentConversationPurgeInputSchema, AgentConversationPurgeResultSchema, AgentConversationPurgedError, purgeAgentConversation, AgentRuntimeHeadSchema, AgentStoredRunSchema, AgentAdmissionReceiptSchema, AgentHistoryMutationSchema, ACTIVE_AGENT_RUN_STATES, createAgentRuntimeStore, createMemoryAgentRuntimeStore };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentMessageSchema,
|
|
3
|
+
AgentRecordIdSchema,
|
|
4
|
+
AgentRecordVersionSchema
|
|
5
|
+
} from "./index-p1b1y93x.js";
|
|
6
|
+
|
|
7
|
+
// src/agent-runtime/conversations.ts
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
var AgentConversationSummarySchema = z.object({
|
|
10
|
+
conversationId: AgentRecordIdSchema,
|
|
11
|
+
version: AgentRecordVersionSchema,
|
|
12
|
+
updatedAt: z.iso.datetime({ offset: true }),
|
|
13
|
+
preview: z.string(),
|
|
14
|
+
activeRuns: z.int().nonnegative()
|
|
15
|
+
}).strict();
|
|
16
|
+
var AgentConversationPageSchema = z.object({
|
|
17
|
+
items: z.array(AgentConversationSummarySchema),
|
|
18
|
+
nextCursor: z.string().min(1).optional()
|
|
19
|
+
}).strict();
|
|
20
|
+
var AgentConversationMessagePageSchema = z.object({
|
|
21
|
+
items: z.array(AgentMessageSchema),
|
|
22
|
+
compacted: z.array(z.string().min(1)),
|
|
23
|
+
nextCursor: z.string().min(1).optional()
|
|
24
|
+
}).strict();
|
|
25
|
+
|
|
26
|
+
export { AgentConversationSummarySchema, AgentConversationPageSchema, AgentConversationMessagePageSchema };
|
|
@@ -9,6 +9,88 @@ import {
|
|
|
9
9
|
AgentUsageSchema
|
|
10
10
|
} from "./index-p1b1y93x.js";
|
|
11
11
|
|
|
12
|
+
// src/agent-runtime/history-chronology.ts
|
|
13
|
+
function createToolChronology() {
|
|
14
|
+
return { calls: new Map, approvals: new Map, pending: 0, resultsStarted: false };
|
|
15
|
+
}
|
|
16
|
+
function advanceToolChronology(previous, parts) {
|
|
17
|
+
const calls = new Map(previous.calls);
|
|
18
|
+
const approvals = new Map(previous.approvals);
|
|
19
|
+
let { pending, resultsStarted } = previous;
|
|
20
|
+
for (const part of parts) {
|
|
21
|
+
if (part.type === "tool-call") {
|
|
22
|
+
if (calls.has(part.callId) || resultsStarted && pending > 0)
|
|
23
|
+
return;
|
|
24
|
+
if (pending === 0)
|
|
25
|
+
resultsStarted = false;
|
|
26
|
+
calls.set(part.callId, { toolName: part.toolName, phase: "called" });
|
|
27
|
+
pending += 1;
|
|
28
|
+
} else if (part.type === "tool-approval-request") {
|
|
29
|
+
const call = calls.get(part.callId);
|
|
30
|
+
if (call?.phase !== "called" || approvals.has(part.approvalId))
|
|
31
|
+
return;
|
|
32
|
+
approvals.set(part.approvalId, part.callId);
|
|
33
|
+
calls.set(part.callId, { ...call, phase: "requested" });
|
|
34
|
+
} else if (part.type === "tool-approval-response") {
|
|
35
|
+
const callId = approvals.get(part.approvalId);
|
|
36
|
+
const call = callId === undefined ? undefined : calls.get(callId);
|
|
37
|
+
if (callId === undefined || !call || call.phase !== "requested")
|
|
38
|
+
return;
|
|
39
|
+
calls.set(callId, { ...call, phase: part.approved ? "approved" : "denied" });
|
|
40
|
+
} else if (part.type === "tool-result") {
|
|
41
|
+
const call = calls.get(part.callId);
|
|
42
|
+
if (!call || call.toolName !== part.toolName || call.phase === "result" || call.phase === "requested" || call.phase === "denied" && part.outcome === "success")
|
|
43
|
+
return;
|
|
44
|
+
calls.set(part.callId, { ...call, phase: "result" });
|
|
45
|
+
pending -= 1;
|
|
46
|
+
resultsStarted = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { calls, approvals, pending, resultsStarted };
|
|
50
|
+
}
|
|
51
|
+
function canProjectToolChronology(state) {
|
|
52
|
+
return [...state.calls.values()].every(({ phase }) => phase !== "called");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/agent-runtime/terminal-status.ts
|
|
56
|
+
function isSpeakableAssistantStatus(status) {
|
|
57
|
+
return status === "completed" || status === "interrupted" || status === "committed";
|
|
58
|
+
}
|
|
59
|
+
function isAssistantHistoryEvidence(status, policy) {
|
|
60
|
+
return isSpeakableAssistantStatus(status) || status === "failed" && policy?.failedAssistant === "assistant-marked";
|
|
61
|
+
}
|
|
62
|
+
function isCompleteAgentHistoryTurn(messages, policy) {
|
|
63
|
+
if (messages[0]?.role !== "user")
|
|
64
|
+
return false;
|
|
65
|
+
let chronology = createToolChronology();
|
|
66
|
+
let assistantCount = 0;
|
|
67
|
+
for (const message of messages) {
|
|
68
|
+
if (message.role === "assistant") {
|
|
69
|
+
if (!isAssistantHistoryEvidence(message.status, policy))
|
|
70
|
+
return false;
|
|
71
|
+
assistantCount += 1;
|
|
72
|
+
}
|
|
73
|
+
const next = advanceToolChronology(chronology, message.parts);
|
|
74
|
+
if (!next)
|
|
75
|
+
return false;
|
|
76
|
+
chronology = next;
|
|
77
|
+
}
|
|
78
|
+
return assistantCount > 0 && chronology.pending === 0;
|
|
79
|
+
}
|
|
80
|
+
function assistantStatus(reason) {
|
|
81
|
+
if (reason === "success" || reason === "policy_stop" || reason === "provider_stop") {
|
|
82
|
+
return "completed";
|
|
83
|
+
}
|
|
84
|
+
if (reason === "superseded")
|
|
85
|
+
return "superseded";
|
|
86
|
+
if (reason === "absorbed")
|
|
87
|
+
return "superseded";
|
|
88
|
+
if (reason === "interrupted" || reason === "cancelled" || reason === "shutdown") {
|
|
89
|
+
return "interrupted";
|
|
90
|
+
}
|
|
91
|
+
return "failed";
|
|
92
|
+
}
|
|
93
|
+
|
|
12
94
|
// src/agent-runtime/store.ts
|
|
13
95
|
import { z } from "zod";
|
|
14
96
|
var AgentStoreConflictSchema = z.object({
|
|
@@ -249,4 +331,4 @@ function decodeAgentConversationArchive(bytes) {
|
|
|
249
331
|
return archive;
|
|
250
332
|
}
|
|
251
333
|
|
|
252
|
-
export { AgentStoreConflictSchema, AgentStoreNotFoundSchema, AgentStoreAppliedSchema, AgentStoreDuplicateSchema, AgentStoreMutationResultSchema, AgentRunViewSchema, AcceptInputAndAssignRunSchema, AcquireAgentRunSchema, CheckpointRunAssistantSchema, RecordRunOperationSchema, CommitRunTerminalSchema, RequestRunInterruptSchema, RecoverAgentRunSchema, ReplaceCompactedRangeSchema, AgentRecoverableDescriptorSchema, AgentRecoverablePageSchema, AgentStoreEventKindSchema, AgentStoreTransitionSchema, AgentStoreEventEnvelopeSchema, AppendAgentStoreEventSchema, ReadAgentStoreEventsSchema, AgentStoreEventPageSchema, decodeAgentStoreEvent, agentStoreEventDraft, canonicalAgentJson, AgentConversationArchiveSchema, encodeAgentConversationArchive, decodeAgentConversationArchive };
|
|
334
|
+
export { createToolChronology, advanceToolChronology, canProjectToolChronology, isAssistantHistoryEvidence, isCompleteAgentHistoryTurn, assistantStatus, AgentStoreConflictSchema, AgentStoreNotFoundSchema, AgentStoreAppliedSchema, AgentStoreDuplicateSchema, AgentStoreMutationResultSchema, AgentRunViewSchema, AcceptInputAndAssignRunSchema, AcquireAgentRunSchema, CheckpointRunAssistantSchema, RecordRunOperationSchema, CommitRunTerminalSchema, RequestRunInterruptSchema, RecoverAgentRunSchema, ReplaceCompactedRangeSchema, AgentRecoverableDescriptorSchema, AgentRecoverablePageSchema, AgentStoreEventKindSchema, AgentStoreTransitionSchema, AgentStoreEventEnvelopeSchema, AppendAgentStoreEventSchema, ReadAgentStoreEventsSchema, AgentStoreEventPageSchema, decodeAgentStoreEvent, agentStoreEventDraft, canonicalAgentJson, AgentConversationArchiveSchema, encodeAgentConversationArchive, decodeAgentConversationArchive };
|
|
@@ -15,6 +15,19 @@ export type SqliteValue = string | number | bigint | null | Uint8Array;
|
|
|
15
15
|
export interface SqliteStatement {
|
|
16
16
|
get(...parameters: SqliteValue[]): unknown;
|
|
17
17
|
all(...parameters: SqliteValue[]): readonly unknown[];
|
|
18
|
+
/**
|
|
19
|
+
* `changes` is the driver's own count and is advisory: never decide
|
|
20
|
+
* correctness by it.
|
|
21
|
+
*
|
|
22
|
+
* Because this boundary is satisfied structurally by a raw handle, the
|
|
23
|
+
* number is whatever that driver reports. `bun:sqlite` includes rows written
|
|
24
|
+
* by an AFTER INSERT trigger and by FTS5's deferred index flush during the
|
|
25
|
+
* same statement, so a statement that moved one row can report five, and one
|
|
26
|
+
* that moved none can report more than zero. A guarded `UPDATE`/upsert whose
|
|
27
|
+
* outcome is read back from `changes` is therefore not a compare-and-swap.
|
|
28
|
+
* Read the row, compare, then write unconditionally — inside the store's
|
|
29
|
+
* `BEGIN IMMEDIATE` transaction that is atomic.
|
|
30
|
+
*/
|
|
18
31
|
run(...parameters: SqliteValue[]): {
|
|
19
32
|
changes: number;
|
|
20
33
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/internal/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,UAAU,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,UAAU,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAC3C,GAAG,CAAC,GAAG,UAAU,EAAE,WAAW,EAAE,GAAG,SAAS,OAAO,EAAE,CAAC;IACtD,GAAG,CAAC,GAAG,UAAU,EAAE,WAAW,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC,KAAK,IAAI,IAAI,CAAC;CACf"}
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/internal/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,UAAU,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,UAAU,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAC3C,GAAG,CAAC,GAAG,UAAU,EAAE,WAAW,EAAE,GAAG,SAAS,OAAO,EAAE,CAAC;IACtD;;;;;;;;;;;;OAYG;IACH,GAAG,CAAC,GAAG,UAAU,EAAE,WAAW,EAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC,KAAK,IAAI,IAAI,CAAC;CACf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-store-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/agent-store-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-store-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/agent-store-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE;;;;;;;;;GASG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,WAAW,CACT,OAAO,EAAE,4BAA4B,GACpC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAClD;;;;;;;;OAQG;IACH,OAAO,CAAC,CAAC,OAAO,EAAE,4BAA4B,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAwCD,gFAAgF;AAChF,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,IAAI,CAAC,CAoCf"}
|
package/dist/testing.js
CHANGED
|
@@ -4,6 +4,9 @@ import {
|
|
|
4
4
|
import"./index-2k4yrqkc.js";
|
|
5
5
|
import"./index-3gye9wzb.js";
|
|
6
6
|
import"./index-3z73fh2c.js";
|
|
7
|
+
import {
|
|
8
|
+
createMemoryAgentRuntimeStore
|
|
9
|
+
} from "./index-5wezxcxx.js";
|
|
7
10
|
import {
|
|
8
11
|
createAgentRaceBarrier,
|
|
9
12
|
createAgentRaceDriver,
|
|
@@ -11,7 +14,7 @@ import {
|
|
|
11
14
|
} from "./index-cnyk6te3.js";
|
|
12
15
|
import {
|
|
13
16
|
decodeAgentConversationArchive
|
|
14
|
-
} from "./index-
|
|
17
|
+
} from "./index-z1m86vc8.js";
|
|
15
18
|
import {
|
|
16
19
|
AgentMessageSchema,
|
|
17
20
|
AgentRunSchema
|
|
@@ -93,7 +96,8 @@ async function runAgentStoreConformance(config) {
|
|
|
93
96
|
`${run}-causal-history`,
|
|
94
97
|
`${run}-causal-active`,
|
|
95
98
|
`${run}-interrupt-priority`,
|
|
96
|
-
`${run}-ledger
|
|
99
|
+
`${run}-ledger`,
|
|
100
|
+
`${run}-archive`
|
|
97
101
|
]
|
|
98
102
|
};
|
|
99
103
|
const store = await config.createStore(context);
|
|
@@ -121,10 +125,13 @@ async function conformanceScenario(store, conversationIds) {
|
|
|
121
125
|
causalHistoryConversationId,
|
|
122
126
|
causalActiveConversationId,
|
|
123
127
|
interruptPriorityConversationId,
|
|
124
|
-
ledgerConversationId
|
|
128
|
+
ledgerConversationId,
|
|
129
|
+
archiveConversationId
|
|
125
130
|
] = conversationIds;
|
|
126
131
|
if (ledgerConversationId)
|
|
127
132
|
await ledgerScenario(store, ledgerConversationId);
|
|
133
|
+
if (archiveConversationId)
|
|
134
|
+
await archiveScenario(store, archiveConversationId);
|
|
128
135
|
if (!conversationId || !recoveryConversationId || !absorbConversationId || !causalHistoryConversationId || !causalActiveConversationId || !interruptPriorityConversationId) {
|
|
129
136
|
throw new Error("Agent store conformance requires six conversation identities");
|
|
130
137
|
}
|
|
@@ -819,6 +826,34 @@ async function ledgerScenario(store, conversationId) {
|
|
|
819
826
|
throw new Error(`Agent store conformance expected 22 archived events, received ${decoded.events.length}`);
|
|
820
827
|
}
|
|
821
828
|
}
|
|
829
|
+
async function archiveScenario(store, conversationId) {
|
|
830
|
+
const origin = createMemoryAgentRuntimeStore();
|
|
831
|
+
const inputMessage = userMessage(conversationId, "archived-input");
|
|
832
|
+
const run = queuedRun(conversationId, inputMessage.id, "archived-run");
|
|
833
|
+
requireOutcome(await origin.acceptInputAndAssignRun({
|
|
834
|
+
idempotencyKey: "archived-request",
|
|
835
|
+
input: inputMessage,
|
|
836
|
+
run
|
|
837
|
+
}), "applied");
|
|
838
|
+
await origin.appendEvent({
|
|
839
|
+
conversationId,
|
|
840
|
+
kind: "state/set",
|
|
841
|
+
payload: { name: "topic", value: "archive" }
|
|
842
|
+
});
|
|
843
|
+
const imported = await store.importConversation(await origin.exportConversation(conversationId));
|
|
844
|
+
if (imported.conversationId !== conversationId || imported.events !== 2) {
|
|
845
|
+
throw new Error(`Agent store conformance expected 2 imported events for ${conversationId}, received ${imported.events} for ${imported.conversationId}`);
|
|
846
|
+
}
|
|
847
|
+
const restored = await store.loadSnapshot(conversationId);
|
|
848
|
+
const expected = await origin.loadSnapshot(conversationId);
|
|
849
|
+
if (restored.version !== expected.version || restored.messages.map((message) => message.id).join(",") !== expected.messages.map((message) => message.id).join(",") || restored.runs.map((entry) => `${entry.id}:${entry.state}`).join(",") !== expected.runs.map((entry) => `${entry.id}:${entry.state}`).join(",")) {
|
|
850
|
+
throw new Error(`Agent store conformance expected the imported snapshot to match its archive, received version ${restored.version} with ${restored.messages.length} messages and ${restored.runs.length} runs`);
|
|
851
|
+
}
|
|
852
|
+
const events = await store.readEvents({ conversationId, limit: 10 });
|
|
853
|
+
if (events.items.map((event) => event.kind).join(",") !== "runtime/transition,state/set") {
|
|
854
|
+
throw new Error(`Agent store conformance expected the imported ledger to keep its kinds, received ${events.items.map((event) => event.kind).join(",")}`);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
822
857
|
// src/testing/managed-resource-conformance-contract.ts
|
|
823
858
|
import { z } from "zod";
|
|
824
859
|
var ManagedResourceConformanceScenarioIdSchema = z.enum([
|
package/llms-full.txt
CHANGED
|
@@ -63,11 +63,11 @@ own, recorded as an ADR.
|
|
|
63
63
|
| `stitchkit/tracking/server` | server (Bun or Node) | evolving | the decisions a tracking backend makes — dispositions, visit lease over an application-owned store, active intervals, presence; no database |
|
|
64
64
|
| `stitchkit/release` | browser **and** server | evolving | a page follows the release it was built for — `createReleaseMarker` on the server, `createReleaseWatcher` in the browser, the `X-Build-Id` header and a socket event between them |
|
|
65
65
|
| `stitchkit/geo` | server (Bun or Node) | evolving | managed GeoIP reader generations, last-known-good reload and the optional MaxMind adapter |
|
|
66
|
-
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the
|
|
66
|
+
| `stitchkit/observability` | server | stable<br>_redefined in 1 of the 32 minors since 0.56.2, most recently 0.83.0_ | request/tool event projections — `createObservability`, trace context, sanitisation |
|
|
67
67
|
| `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 |
|
|
68
68
|
| `stitchkit/declaration` | browser + build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
69
69
|
| `stitchkit/react` | browser + server rendering | stable | `createCursorQuery`, `createCacheBridge`, QueryClient and `ApiError` retry policy |
|
|
70
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in
|
|
70
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 18 of the 32 minors since 0.56.2, most recently 0.87.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
71
71
|
| `stitchkit/agent-runtime/testing` | tests on Bun or Node | evolving | credential-free replay, scripted provider faults and deterministic race controls |
|
|
72
72
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
73
73
|
| `stitchkit/agent-runtime/coding-tools` | server (Bun or Node) | evolving | bounded host-authorized direct file and shell tools; a root boundary, not an OS sandbox |
|
|
@@ -76,7 +76,7 @@ own, recorded as an ADR.
|
|
|
76
76
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
77
77
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
78
78
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
79
|
-
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the
|
|
79
|
+
| `stitchkit/application` | browser + server | evolving<br>_redefined in 7 of the 32 minors since 0.56.2, most recently 0.83.0_ | managed resource graph, readiness, admission, schedules, subtree restart and bounded shutdown |
|
|
80
80
|
| `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
|
|
81
81
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
82
82
|
| `stitchkit/application/schemas` | browser + server | evolving | the application's snapshot, health and shutdown schemas alone, without the kernel |
|
|
@@ -4855,8 +4855,14 @@ and supplies atomicity; Stitchkit owns transition validation and revision
|
|
|
4855
4855
|
arithmetic. The executable reference is
|
|
4856
4856
|
[`examples/agent-store-prisma/adapter.ts`](../../examples/agent-store-prisma/adapter.ts).
|
|
4857
4857
|
`compareAndSwap` returns either `{ outcome: 'applied' }` or
|
|
4858
|
-
`{ outcome: 'conflict', actualVersion }`.
|
|
4859
|
-
|
|
4858
|
+
`{ outcome: 'conflict', actualVersion }`. Decide that outcome by reading the
|
|
4859
|
+
version, comparing it and then writing unconditionally — inside the transaction
|
|
4860
|
+
the adapter supplies, that is atomic. A conditional upsert is the shorter thing
|
|
4861
|
+
to write and it is wrong twice: `ON CONFLICT ... WHERE` guards the update branch
|
|
4862
|
+
only, so the first write to a conversation applies whatever `expectedVersion` it
|
|
4863
|
+
was given, and the affected-row count that would report the outcome is the
|
|
4864
|
+
driver's, which need not be the rows the statement moved. The head contains only
|
|
4865
|
+
schema version, conversation identity and monotonic version. Runs and admission receipts are normalized records;
|
|
4860
4866
|
recovery queries active run states directly instead of maintaining a second projection.
|
|
4861
4867
|
An admission receipt retains its canonical input, and a terminal run retains its canonical
|
|
4862
4868
|
assistant, so physical product-history compaction cannot break idempotent retries.
|
|
@@ -4929,6 +4935,31 @@ companions — `createSqliteAgentProjectionStore`, `createSqliteAgentSpillStore`
|
|
|
4929
4935
|
and write their rows and events through it, so a row and its event land
|
|
4930
4936
|
together or not at all.
|
|
4931
4937
|
|
|
4938
|
+
`conversations.messages` pages the model's history: what compaction removed is
|
|
4939
|
+
not in it, which is the point of compaction. A person reading back their own
|
|
4940
|
+
conversation needs the other view, and asks for it explicitly:
|
|
4941
|
+
|
|
4942
|
+
```ts
|
|
4943
|
+
const page = await conversations.messages({
|
|
4944
|
+
conversationId,
|
|
4945
|
+
limit: 50,
|
|
4946
|
+
direction: 'after',
|
|
4947
|
+
includeCompacted: true,
|
|
4948
|
+
})
|
|
4949
|
+
const removed = new Set(page.compacted)
|
|
4950
|
+
```
|
|
4951
|
+
|
|
4952
|
+
`items` stays one sequence in the order it happened, and `compacted` names the
|
|
4953
|
+
ids inside it that the model no longer sees — the boundary is a mark on the
|
|
4954
|
+
conversation, not a second list. A compaction summary sits at the position of
|
|
4955
|
+
the first message it replaced, so it appears at the head of the block it
|
|
4956
|
+
stands for. Without the flag the page is exactly what it was, `compacted`
|
|
4957
|
+
empty. The v1 → v2 migration baseline records the same thing: the whole
|
|
4958
|
+
sequence, with `compacted` naming what had been folded away. A file migrated
|
|
4959
|
+
by 0.86.0 has a baseline built from the active history only — the messages
|
|
4960
|
+
themselves are still in the store and this read reaches them, but that one
|
|
4961
|
+
event cannot be rewritten after the fact.
|
|
4962
|
+
|
|
4932
4963
|
### Retried provider streams
|
|
4933
4964
|
|
|
4934
4965
|
With `loop.retry` set, a provider stream that fails before any tool call in the
|
|
@@ -11196,6 +11227,24 @@ of the range if you want a different one.
|
|
|
11196
11227
|
So upgrading is: read the `### ⚠️ Breaking changes` of every version *above* your
|
|
11197
11228
|
current one *up to* your target, and apply each snippet.
|
|
11198
11229
|
|
|
11230
|
+
## Released migration: 0.87.0
|
|
11231
|
+
|
|
11232
|
+
Only if your project implements `AgentConversationReader` itself. A message page
|
|
11233
|
+
now names which of its messages compaction removed:
|
|
11234
|
+
|
|
11235
|
+
```ts
|
|
11236
|
+
// before
|
|
11237
|
+
return { items, ...(nextCursor && { nextCursor }) }
|
|
11238
|
+
|
|
11239
|
+
// after
|
|
11240
|
+
return { items, compacted: [], ...(nextCursor && { nextCursor }) }
|
|
11241
|
+
```
|
|
11242
|
+
|
|
11243
|
+
An empty array is the honest answer for a reader that pages only the active
|
|
11244
|
+
history; it is what the SQLite reader returns unless the caller asks for
|
|
11245
|
+
`includeCompacted`. Calling the reader needs no change, and no data migration is
|
|
11246
|
+
involved.
|
|
11247
|
+
|
|
11199
11248
|
## Released migration: 0.86.0
|
|
11200
11249
|
|
|
11201
11250
|
Only if you branch on `AgentTerminalReason` or show it to a person. Three
|
|
@@ -15437,7 +15486,7 @@ Server-only optional application runtime. See the
|
|
|
15437
15486
|
| `searchAgentModelCatalog` | function | deterministic bounded search over a loaded canonical catalog |
|
|
15438
15487
|
| `AgentModelSelectionSchema` / `AgentModelSelection` / `AgentModelSelectionStore` | schema / _type_ | durable per-conversation model choice; runtime resolvers receive run and snapshot to recover the model pinned to input metadata |
|
|
15439
15488
|
| `createMemoryAgentModelSelectionStore` | function | process-local selection reference adapter |
|
|
15440
|
-
| `AgentConversationReader` | _type_ | optional bounded conversation-summary and message-history reader; not part of the required runtime store contract |
|
|
15489
|
+
| `AgentConversationReader` | _type_ | optional bounded conversation-summary and message-history reader; `messages` takes `includeCompacted` and every page names its `compacted` ids; not part of the required runtime store contract |
|
|
15441
15490
|
| `AgentConversationSummarySchema` / `AgentConversationSummary` | schema / _type_ | bounded durable conversation list item with version, activity and preview |
|
|
15442
15491
|
| `AgentConversationPageSchema` / `AgentConversationPage` | schema / _type_ | cursor-paged conversation summaries |
|
|
15443
15492
|
| `AgentConversationMessagePageSchema` / `AgentConversationMessagePage` | schema / _type_ | cursor-paged durable message history |
|
package/package.json
CHANGED
package/dist/index-y2s6h5bf.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
// src/agent-runtime/history-chronology.ts
|
|
2
|
-
function createToolChronology() {
|
|
3
|
-
return { calls: new Map, approvals: new Map, pending: 0, resultsStarted: false };
|
|
4
|
-
}
|
|
5
|
-
function advanceToolChronology(previous, parts) {
|
|
6
|
-
const calls = new Map(previous.calls);
|
|
7
|
-
const approvals = new Map(previous.approvals);
|
|
8
|
-
let { pending, resultsStarted } = previous;
|
|
9
|
-
for (const part of parts) {
|
|
10
|
-
if (part.type === "tool-call") {
|
|
11
|
-
if (calls.has(part.callId) || resultsStarted && pending > 0)
|
|
12
|
-
return;
|
|
13
|
-
if (pending === 0)
|
|
14
|
-
resultsStarted = false;
|
|
15
|
-
calls.set(part.callId, { toolName: part.toolName, phase: "called" });
|
|
16
|
-
pending += 1;
|
|
17
|
-
} else if (part.type === "tool-approval-request") {
|
|
18
|
-
const call = calls.get(part.callId);
|
|
19
|
-
if (call?.phase !== "called" || approvals.has(part.approvalId))
|
|
20
|
-
return;
|
|
21
|
-
approvals.set(part.approvalId, part.callId);
|
|
22
|
-
calls.set(part.callId, { ...call, phase: "requested" });
|
|
23
|
-
} else if (part.type === "tool-approval-response") {
|
|
24
|
-
const callId = approvals.get(part.approvalId);
|
|
25
|
-
const call = callId === undefined ? undefined : calls.get(callId);
|
|
26
|
-
if (callId === undefined || !call || call.phase !== "requested")
|
|
27
|
-
return;
|
|
28
|
-
calls.set(callId, { ...call, phase: part.approved ? "approved" : "denied" });
|
|
29
|
-
} else if (part.type === "tool-result") {
|
|
30
|
-
const call = calls.get(part.callId);
|
|
31
|
-
if (!call || call.toolName !== part.toolName || call.phase === "result" || call.phase === "requested" || call.phase === "denied" && part.outcome === "success")
|
|
32
|
-
return;
|
|
33
|
-
calls.set(part.callId, { ...call, phase: "result" });
|
|
34
|
-
pending -= 1;
|
|
35
|
-
resultsStarted = true;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return { calls, approvals, pending, resultsStarted };
|
|
39
|
-
}
|
|
40
|
-
function canProjectToolChronology(state) {
|
|
41
|
-
return [...state.calls.values()].every(({ phase }) => phase !== "called");
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// src/agent-runtime/terminal-status.ts
|
|
45
|
-
function isSpeakableAssistantStatus(status) {
|
|
46
|
-
return status === "completed" || status === "interrupted" || status === "committed";
|
|
47
|
-
}
|
|
48
|
-
function isAssistantHistoryEvidence(status, policy) {
|
|
49
|
-
return isSpeakableAssistantStatus(status) || status === "failed" && policy?.failedAssistant === "assistant-marked";
|
|
50
|
-
}
|
|
51
|
-
function isCompleteAgentHistoryTurn(messages, policy) {
|
|
52
|
-
if (messages[0]?.role !== "user")
|
|
53
|
-
return false;
|
|
54
|
-
let chronology = createToolChronology();
|
|
55
|
-
let assistantCount = 0;
|
|
56
|
-
for (const message of messages) {
|
|
57
|
-
if (message.role === "assistant") {
|
|
58
|
-
if (!isAssistantHistoryEvidence(message.status, policy))
|
|
59
|
-
return false;
|
|
60
|
-
assistantCount += 1;
|
|
61
|
-
}
|
|
62
|
-
const next = advanceToolChronology(chronology, message.parts);
|
|
63
|
-
if (!next)
|
|
64
|
-
return false;
|
|
65
|
-
chronology = next;
|
|
66
|
-
}
|
|
67
|
-
return assistantCount > 0 && chronology.pending === 0;
|
|
68
|
-
}
|
|
69
|
-
function assistantStatus(reason) {
|
|
70
|
-
if (reason === "success" || reason === "policy_stop" || reason === "provider_stop") {
|
|
71
|
-
return "completed";
|
|
72
|
-
}
|
|
73
|
-
if (reason === "superseded")
|
|
74
|
-
return "superseded";
|
|
75
|
-
if (reason === "absorbed")
|
|
76
|
-
return "superseded";
|
|
77
|
-
if (reason === "interrupted" || reason === "cancelled" || reason === "shutdown") {
|
|
78
|
-
return "interrupted";
|
|
79
|
-
}
|
|
80
|
-
return "failed";
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export { createToolChronology, advanceToolChronology, canProjectToolChronology, isAssistantHistoryEvidence, isCompleteAgentHistoryTurn, assistantStatus };
|