stitchkit 0.118.1 → 0.120.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.
Files changed (180) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/README.md +10 -7
  3. package/dist/browser/http.d.ts.map +1 -1
  4. package/dist/contract/client-types.d.ts +6 -3
  5. package/dist/contract/client-types.d.ts.map +1 -1
  6. package/dist/contract/define-validation.d.ts.map +1 -1
  7. package/dist/contract/define.d.ts +18 -12
  8. package/dist/contract/define.d.ts.map +1 -1
  9. package/dist/contract/endpoint-capabilities.d.ts +28 -0
  10. package/dist/contract/endpoint-capabilities.d.ts.map +1 -0
  11. package/dist/contract/factory.d.ts +49 -19
  12. package/dist/contract/factory.d.ts.map +1 -1
  13. package/dist/contract/tool-view.d.ts +1 -1
  14. package/dist/contract/tool-view.d.ts.map +1 -1
  15. package/dist/contract/transports.d.ts +5 -0
  16. package/dist/contract/transports.d.ts.map +1 -0
  17. package/dist/entrypoints/agent-runtime/coding-tools.js +9 -8
  18. package/dist/entrypoints/agent-runtime/harness.js +9 -8
  19. package/dist/entrypoints/agent-runtime/realtime.js +3 -3
  20. package/dist/entrypoints/agent-runtime/sandbox.js +10 -9
  21. package/dist/entrypoints/agent-runtime/sqlite/bun.js +12 -11
  22. package/dist/entrypoints/agent-runtime/sqlite/node.js +12 -11
  23. package/dist/entrypoints/agent-runtime/testing.js +12 -11
  24. package/dist/entrypoints/agent-runtime.js +22 -19
  25. package/dist/entrypoints/application/diagnostic-journal.js +3 -3
  26. package/dist/entrypoints/application/directory-inbox.js +4 -4
  27. package/dist/entrypoints/application/opentelemetry.js +1 -1
  28. package/dist/entrypoints/application.js +10 -10
  29. package/dist/entrypoints/cli/publish.js +4 -4
  30. package/dist/entrypoints/cli.js +13 -12
  31. package/dist/entrypoints/contract.d.ts +1 -1
  32. package/dist/entrypoints/contract.d.ts.map +1 -1
  33. package/dist/entrypoints/contract.js +6 -4
  34. package/dist/entrypoints/files.js +3 -3
  35. package/dist/entrypoints/geo/contract.d.ts +7 -0
  36. package/dist/entrypoints/geo/contract.d.ts.map +1 -0
  37. package/dist/entrypoints/geo/contract.js +6 -0
  38. package/dist/entrypoints/geo.js +60 -23
  39. package/dist/entrypoints/http.js +3 -3
  40. package/dist/entrypoints/index.js +9 -7
  41. package/dist/entrypoints/live.js +1 -1
  42. package/dist/entrypoints/node.js +7 -6
  43. package/dist/entrypoints/primitives.js +1 -1
  44. package/dist/entrypoints/process/owner-loss.js +1 -1
  45. package/dist/entrypoints/process.js +3 -3
  46. package/dist/entrypoints/react.js +1 -1
  47. package/dist/entrypoints/remote.js +4 -3
  48. package/dist/entrypoints/server.js +16 -15
  49. package/dist/entrypoints/telegram/screens.js +5 -5
  50. package/dist/entrypoints/telegram.js +7 -7
  51. package/dist/entrypoints/testing.js +7 -6
  52. package/dist/entrypoints/tools/agent.d.ts +9 -0
  53. package/dist/entrypoints/tools/agent.d.ts.map +1 -0
  54. package/dist/entrypoints/tools/agent.js +16 -0
  55. package/dist/entrypoints/tools/connections.js +7 -6
  56. package/dist/entrypoints/tools/contract.js +1 -1
  57. package/dist/entrypoints/tools/invoker.js +5 -4
  58. package/dist/entrypoints/tools/mcp.js +110 -9
  59. package/dist/entrypoints/tools/toolkit.d.ts +9 -0
  60. package/dist/entrypoints/tools/toolkit.d.ts.map +1 -0
  61. package/dist/entrypoints/tools/toolkit.js +40 -0
  62. package/dist/entrypoints/tools.d.ts +0 -10
  63. package/dist/entrypoints/tools.d.ts.map +1 -1
  64. package/dist/entrypoints/tools.js +38 -80
  65. package/dist/entrypoints/tracking/contract.js +5 -3
  66. package/dist/entrypoints/tracking/performance.js +3 -3
  67. package/dist/entrypoints/tracking.d.ts +1 -1
  68. package/dist/entrypoints/tracking.d.ts.map +1 -1
  69. package/dist/entrypoints/tracking.js +63 -83
  70. package/dist/entrypoints/xlsx.js +1 -1
  71. package/dist/geo/index.d.ts +2 -1
  72. package/dist/geo/index.d.ts.map +1 -1
  73. package/dist/geo/record.d.ts +8 -0
  74. package/dist/geo/record.d.ts.map +1 -0
  75. package/dist/geo/resolver.d.ts +1 -3
  76. package/dist/geo/resolver.d.ts.map +1 -1
  77. package/dist/geo/schema.d.ts +44 -0
  78. package/dist/geo/schema.d.ts.map +1 -0
  79. package/dist/geo/types.d.ts +2 -13
  80. package/dist/geo/types.d.ts.map +1 -1
  81. package/dist/{index-n5sv4z0w.js → index-0qyrcjfs.js} +16 -18
  82. package/dist/index-1psbyyhj.js +21 -0
  83. package/dist/{index-tsngj2b5.js → index-2fc1k9k2.js} +206 -206
  84. package/dist/index-3prvb42w.js +30 -0
  85. package/dist/{index-073nw9qr.js → index-3yb5kft5.js} +524 -522
  86. package/dist/{index-d9hq291n.js → index-4jpykzvw.js} +70 -81
  87. package/dist/index-568w258r.js +76 -0
  88. package/dist/index-69t14s4a.js +39 -0
  89. package/dist/{index-dky0dcmf.js → index-72r9k0av.js} +6 -2
  90. package/dist/{index-6p3frkv5.js → index-7zwtbak8.js} +9 -50
  91. package/dist/{index-90p34rts.js → index-8ryydawp.js} +7 -5
  92. package/dist/{index-vv1sch8a.js → index-8vzh5wpv.js} +13 -8
  93. package/dist/{index-75ns2ybj.js → index-8xyf8h2k.js} +1 -1
  94. package/dist/{index-xx1j310k.js → index-8yxgcyt6.js} +171 -169
  95. package/dist/{index-p6apg0jg.js → index-9frf01t9.js} +16 -9
  96. package/dist/{index-q0th8q0z.js → index-9mjrnqxs.js} +1 -3
  97. package/dist/{index-6f49krb5.js → index-aa50qwv4.js} +1 -1
  98. package/dist/{index-ega3yz4c.js → index-aqwg2dm5.js} +1 -1
  99. package/dist/{index-p0rf7sq9.js → index-bgcwxhxh.js} +225 -223
  100. package/dist/index-bph35vpy.js +77 -0
  101. package/dist/{index-tdpmfks8.js → index-bz479f0x.js} +1 -1
  102. package/dist/index-d3xdyjt6.js +38 -0
  103. package/dist/{index-q968hy6y.js → index-e452syyh.js} +1 -1
  104. package/dist/{index-86nbfysb.js → index-ff39f9dr.js} +3 -3
  105. package/dist/index-h1j71dr1.js +48 -0
  106. package/dist/{index-mgb7r8b8.js → index-jswst0h3.js} +1 -1
  107. package/dist/{index-095ya5hm.js → index-knmnj11j.js} +22 -191
  108. package/dist/{index-vwhrnp67.js → index-kz9734jc.js} +3 -3
  109. package/dist/{index-txg1npmg.js → index-mtwh9hyp.js} +1 -1
  110. package/dist/{index-dr3t5n1v.js → index-nn9qvkww.js} +46 -46
  111. package/dist/{index-ghtpfz4z.js → index-nyyam9ce.js} +2 -2
  112. package/dist/{index-qezhmp51.js → index-nz06qw5a.js} +3 -1
  113. package/dist/{index-1bx1xv1k.js → index-pfvde2fz.js} +5 -2
  114. package/dist/{index-w7jq3fz9.js → index-pq2m7t46.js} +1142 -1212
  115. package/dist/{index-yk4g8805.js → index-pq7rkwkk.js} +1 -30
  116. package/dist/{index-s80awwsw.js → index-qch1vcaa.js} +3 -1
  117. package/dist/{index-hdjmdwsj.js → index-qctbzmg9.js} +521 -511
  118. package/dist/{index-n8z3rvzw.js → index-qevqn3d3.js} +3 -5
  119. package/dist/{index-nqxrm176.js → index-r3db01kh.js} +1 -1
  120. package/dist/{index-v6vb5qx8.js → index-s3yxw6kt.js} +1 -1
  121. package/dist/{index-cqmqyjax.js → index-sa99p98w.js} +1 -1
  122. package/dist/index-sb9dr3tq.js +14 -0
  123. package/dist/{index-0gxvns6s.js → index-sba3e6m4.js} +1 -0
  124. package/dist/{index-f24bdt13.js → index-v1swr26p.js} +3 -1
  125. package/dist/{index-rhzkndr5.js → index-x4p3kw1p.js} +533 -530
  126. package/dist/{index-cycp3r3e.js → index-yb9n4pgj.js} +2 -2
  127. package/dist/{index-htxh46ej.js → index-ycqhyars.js} +2 -2
  128. package/dist/{index-9bwcthxw.js → index-yj6saztf.js} +31 -13
  129. package/dist/{index-f6m4c545.js → index-zrdcmg6j.js} +4 -6
  130. package/dist/{index-tvtacc9a.js → index-zyc64nbh.js} +1 -34
  131. package/dist/process/bun-child.d.ts +3 -2
  132. package/dist/process/bun-child.d.ts.map +1 -1
  133. package/dist/server/contract-method.d.ts.map +1 -1
  134. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  135. package/dist/tools/operations/async-operation-canonical-types.d.ts +1 -1
  136. package/dist/tracking/attribution.d.ts +21 -25
  137. package/dist/tracking/attribution.d.ts.map +1 -1
  138. package/dist/tracking/client-visit.d.ts +5 -7
  139. package/dist/tracking/client-visit.d.ts.map +1 -1
  140. package/dist/tracking/client.d.ts +2 -2
  141. package/dist/tracking/client.d.ts.map +1 -1
  142. package/dist/tracking/contract.d.ts +1 -1
  143. package/dist/tracking/host.d.ts +0 -1
  144. package/dist/tracking/host.d.ts.map +1 -1
  145. package/dist/tracking/privacy.d.ts +6 -0
  146. package/dist/tracking/privacy.d.ts.map +1 -1
  147. package/dist/tracking/schemas.d.ts +2 -2
  148. package/dist/tracking/schemas.d.ts.map +1 -1
  149. package/llms/agent-runtime-harness.txt +4 -3
  150. package/llms/agent-runtime-sandbox.txt +1 -1
  151. package/llms/agent-runtime.2.txt +3 -2
  152. package/llms/agent-runtime.3.txt +4 -46
  153. package/llms/agent-runtime.4.txt +113 -0
  154. package/llms/agent-runtime.txt +11 -13
  155. package/llms/cli.txt +1 -1
  156. package/llms/contract.txt +46 -24
  157. package/llms/geo-contract.txt +23 -0
  158. package/llms/geo.txt +40 -4
  159. package/llms/stitchkit.txt +16 -9
  160. package/llms/testing.txt +4 -6
  161. package/llms/tools-agent.txt +24 -0
  162. package/llms/tools-mcp.txt +71 -6
  163. package/llms/tools-toolkit.txt +23 -0
  164. package/llms/tools.2.txt +8 -5
  165. package/llms/tools.3.txt +9 -78
  166. package/llms/tools.txt +8 -8
  167. package/llms/tracking-contract.txt +1 -1
  168. package/llms/tracking.txt +27 -5
  169. package/llms/{upgrading-0.105.0-0.118.0.txt → upgrading-0.106.0-0.120.0.txt} +152 -410
  170. package/llms/upgrading-0.37.0-0.53.0.txt +969 -0
  171. package/llms/{upgrading-0.44.0-0.62.0.txt → upgrading-0.55.0-0.68.0.txt} +509 -528
  172. package/llms/{upgrading-0.63.0-0.83.0.txt → upgrading-0.69.0-0.95.0.txt} +506 -509
  173. package/llms/{upgrading-0.84.0-0.104.0.txt → upgrading-0.96.0-0.105.0.txt} +410 -506
  174. package/llms/upgrading.txt +5 -5
  175. package/llms-full.txt +475 -154
  176. package/llms.txt +17 -14
  177. package/package.json +32 -20
  178. package/llms/upgrading-0.37.0-0.44.0.txt +0 -444
  179. package/dist/{index-arjmb6de.js → index-1jwsfkfz.js} +0 -0
  180. package/dist/{index-qndsr7f0.js → index-5efrpfmj.js} +3 -3
@@ -10,81 +10,24 @@ import {
10
10
  AgentAdmissionReceiptSchema2,
11
11
  AgentSeedReceiptSchema2,
12
12
  AgentHistoryMutationSchema2
13
- } from "./index-xx1j310k.js";
14
- import {
15
- AgentMessageSchema2,
16
- AgentRunSchema2
17
- } from "./index-8kzct1d6.js";
13
+ } from "./index-8yxgcyt6.js";
18
14
  import {
19
15
  appendEventIn,
20
16
  ArchiveProjectionSchema,
21
17
  createAgentRuntimeStore2
22
- } from "./index-cycp3r3e.js";
18
+ } from "./index-yb9n4pgj.js";
19
+ import {
20
+ AgentMessageSchema2,
21
+ AgentRunSchema2
22
+ } from "./index-8kzct1d6.js";
23
23
  import {
24
24
  AgentConversationPageSchema2,
25
25
  AgentConversationMessagePageSchema2
26
26
  } from "./index-kqnd6a85.js";
27
27
 
28
- // src/agent-runtime/sqlite-schema.ts
29
- import { z as z3 } from "zod";
30
-
31
- // src/agent-runtime/sqlite-purge.ts
32
- var OWNED_TABLES = [
33
- "stitchkit_agent_runtime_spills",
34
- "stitchkit_agent_runtime_schedules",
35
- "stitchkit_agent_runtime_projections",
36
- "stitchkit_agent_runtime_events",
37
- "stitchkit_agent_runtime_messages",
38
- "stitchkit_agent_runtime_seeds",
39
- "stitchkit_agent_runtime_admissions",
40
- "stitchkit_agent_runtime_runs",
41
- "stitchkit_agent_runtime_heads"
42
- ];
43
- function initializeSqliteConversationPurge(database) {
44
- database.exec(`
45
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_purged (
46
- conversation_id TEXT PRIMARY KEY
47
- );
48
- `);
49
- for (const table of OWNED_TABLES) {
50
- for (const operation of ["INSERT", "UPDATE"]) {
51
- database.exec(`
52
- CREATE TRIGGER IF NOT EXISTS ${table}_purge_${operation.toLowerCase()}
53
- BEFORE ${operation} ON ${table}
54
- WHEN EXISTS (
55
- SELECT 1 FROM stitchkit_agent_runtime_purged WHERE conversation_id = NEW.conversation_id
56
- )
57
- BEGIN SELECT RAISE(ABORT, 'Agent conversation has been purged'); END;
58
- `);
59
- }
60
- }
61
- }
62
- function sqliteConversationPurge(database) {
63
- const table = database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'stitchkit_agent_runtime_purged'").get();
64
- if (table === null || table === undefined)
65
- return;
66
- return {
67
- async isEmpty(transaction, conversationId) {
68
- for (const table of OWNED_TABLES) {
69
- const row = transaction.prepare(`SELECT 1 FROM ${table} WHERE conversation_id = ? LIMIT 1`).get(conversationId);
70
- if (row !== null && row !== undefined)
71
- return false;
72
- }
73
- return transaction.prepare("SELECT 1 FROM stitchkit_agent_runtime_children WHERE parent_conversation_id = ? OR child_conversation_id = ? LIMIT 1").get(conversationId, conversationId) == null;
74
- },
75
- async isPurged(transaction, conversationId) {
76
- const row = transaction.prepare("SELECT conversation_id FROM stitchkit_agent_runtime_purged WHERE conversation_id = ?").get(conversationId);
77
- return row !== null && row !== undefined;
78
- },
79
- async remove(transaction, conversationId) {
80
- transaction.prepare("INSERT INTO stitchkit_agent_runtime_purged (conversation_id) VALUES (?)").run(conversationId);
81
- for (const table of OWNED_TABLES) {
82
- transaction.prepare(`DELETE FROM ${table} WHERE conversation_id = ?`).run(conversationId);
83
- }
84
- transaction.prepare("DELETE FROM stitchkit_agent_runtime_children WHERE parent_conversation_id = ? OR child_conversation_id = ?").run(conversationId, conversationId);
85
- }
86
- };
87
- }
28
+ // src/agent-runtime/sqlite-events.ts
29
+ import { createHash } from "node:crypto";
30
+ import { z as z2 } from "zod";
88
31
 
89
32
  // src/agent-runtime/sqlite-rows.ts
90
33
  import { z } from "zod";
@@ -144,424 +87,88 @@ function parseEventRow(value) {
144
87
  });
145
88
  }
146
89
 
147
- // src/agent-runtime/store-migrations/v1-to-v2.ts
148
- import { randomUUID } from "node:crypto";
149
- import { z as z2 } from "zod";
150
- var ConversationRowSchema = z2.object({
151
- conversation_id: z2.string().min(1),
152
- version: z2.int().nonnegative()
153
- });
154
- var PayloadRowSchema = z2.object({
155
- payload: z2.string(),
156
- terminal_assistant_payload: z2.string().nullable().optional()
157
- });
158
- var HistoryRowSchema = z2.object({
90
+ // src/agent-runtime/sqlite-events.ts
91
+ var ArchiveProjectionRowSchema = z2.object({
92
+ name: z2.string(),
93
+ version: z2.int().positive(),
94
+ upto_seq: z2.int().nonnegative(),
159
95
  payload: z2.string(),
160
- active: z2.union([z2.literal(0), z2.literal(1)])
96
+ updated_at: z2.string()
161
97
  });
162
- var AdmissionRowSchema = z2.object({
163
- conversation_id: z2.string(),
164
- idempotency_key: z2.string(),
165
- input_payload: z2.string(),
166
- run_id: z2.string(),
167
- assistant_message_id: z2.string()
98
+ var ArchiveSpillRowSchema = z2.object({
99
+ reference_id: z2.string(),
100
+ run_id: z2.string().nullable(),
101
+ tool_call_id: z2.string().nullable(),
102
+ media_type: z2.string(),
103
+ bytes: z2.int().nonnegative(),
104
+ sha256: z2.string(),
105
+ created_at: z2.string(),
106
+ expires_at: z2.string().nullable(),
107
+ authorization_payload: z2.string().nullable(),
108
+ payload: z2.instanceof(Uint8Array)
168
109
  });
169
- function parseJson2(value) {
170
- return JSON.parse(value);
171
- }
172
- function createDurableTables(database) {
173
- database.exec(`
174
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_events (
175
- row_id INTEGER PRIMARY KEY AUTOINCREMENT,
176
- conversation_id TEXT NOT NULL,
177
- seq INTEGER NOT NULL CHECK (seq > 0),
178
- event_id TEXT NOT NULL UNIQUE,
179
- schema_version INTEGER NOT NULL CHECK (schema_version > 0),
180
- kind TEXT NOT NULL,
181
- occurred_at TEXT NOT NULL,
182
- ignorable INTEGER NOT NULL DEFAULT 0 CHECK (ignorable IN (0, 1)),
183
- payload TEXT NOT NULL,
184
- UNIQUE (conversation_id, seq)
185
- );
186
- CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_events_time
187
- ON stitchkit_agent_runtime_events (conversation_id, occurred_at, seq);
188
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_projections (
189
- conversation_id TEXT NOT NULL,
190
- name TEXT NOT NULL,
191
- version INTEGER NOT NULL CHECK (version > 0),
192
- upto_seq INTEGER NOT NULL CHECK (upto_seq >= 0),
193
- payload TEXT NOT NULL,
194
- updated_at TEXT NOT NULL,
195
- PRIMARY KEY (conversation_id, name)
196
- );
197
- CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_projection_updates
198
- ON stitchkit_agent_runtime_projections (name, updated_at, conversation_id);
199
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_spills (
200
- reference_id TEXT PRIMARY KEY,
201
- conversation_id TEXT NOT NULL,
202
- run_id TEXT,
203
- tool_call_id TEXT,
204
- media_type TEXT NOT NULL,
205
- bytes INTEGER NOT NULL CHECK (bytes >= 0),
206
- sha256 TEXT NOT NULL,
207
- created_at TEXT NOT NULL,
208
- expires_at TEXT,
209
- authorization_payload TEXT,
210
- payload BLOB NOT NULL
211
- );
212
- CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_spills_owner
213
- ON stitchkit_agent_runtime_spills (conversation_id, created_at);
214
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_schedules (
215
- id TEXT PRIMARY KEY,
216
- conversation_id TEXT NOT NULL,
217
- kind TEXT NOT NULL,
218
- next_at TEXT NOT NULL,
219
- interval_ms INTEGER,
220
- time_zone TEXT,
221
- input_payload TEXT NOT NULL,
222
- state TEXT NOT NULL,
223
- occurrence INTEGER NOT NULL DEFAULT 0 CHECK (occurrence >= 0),
224
- claim_owner TEXT,
225
- claim_until TEXT,
226
- created_at TEXT NOT NULL,
227
- updated_at TEXT NOT NULL
228
- );
229
- CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_schedules_due
230
- ON stitchkit_agent_runtime_schedules (state, next_at);
231
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_children (
232
- parent_conversation_id TEXT NOT NULL,
233
- child_conversation_id TEXT NOT NULL UNIQUE,
234
- seed_upto_seq INTEGER,
235
- state TEXT NOT NULL,
236
- budget_payload TEXT NOT NULL,
237
- usage_payload TEXT NOT NULL,
238
- result_reference TEXT,
239
- created_at TEXT NOT NULL,
240
- updated_at TEXT NOT NULL,
241
- PRIMARY KEY (parent_conversation_id, child_conversation_id)
242
- );
243
- `);
244
- try {
245
- database.exec(`
246
- CREATE VIRTUAL TABLE IF NOT EXISTS stitchkit_agent_runtime_events_fts
247
- USING fts5(
248
- conversation_id UNINDEXED,
249
- event_seq UNINDEXED,
250
- occurred_at UNINDEXED,
251
- body,
252
- tokenize = 'unicode61 remove_diacritics 2'
253
- );
254
- CREATE TRIGGER IF NOT EXISTS stitchkit_agent_runtime_events_fts_insert
255
- AFTER INSERT ON stitchkit_agent_runtime_events BEGIN
256
- INSERT INTO stitchkit_agent_runtime_events_fts(
257
- rowid, conversation_id, event_seq, occurred_at, body
258
- ) VALUES (new.row_id, new.conversation_id, new.seq, new.occurred_at, new.payload);
259
- END;
260
- CREATE TRIGGER IF NOT EXISTS stitchkit_agent_runtime_events_fts_delete
261
- AFTER DELETE ON stitchkit_agent_runtime_events BEGIN
262
- DELETE FROM stitchkit_agent_runtime_events_fts WHERE rowid = old.row_id;
263
- END;
264
- `);
265
- } catch (error) {
266
- throw new Error("SQLite agent-runtime requires FTS5 support", { cause: error });
110
+ var sqliteEvents = {
111
+ async append(transaction, rawEvent) {
112
+ const event = rawEvent;
113
+ const last = transaction.prepare("SELECT COALESCE(MAX(seq), 0) AS count FROM stitchkit_agent_runtime_events WHERE conversation_id = ?").get(event.conversationId);
114
+ const seq = CountRowSchema.parse(last).count + 1;
115
+ transaction.prepare(`
116
+ INSERT INTO stitchkit_agent_runtime_events (
117
+ conversation_id, seq, event_id, schema_version, kind, occurred_at, ignorable, payload
118
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
119
+ `).run(event.conversationId, seq, event.eventId, event.schemaVersion, event.kind, event.occurredAt, event.ignorable ? 1 : 0, encodeJson(event.payload));
120
+ return AgentStoreEventEnvelopeSchema2.parse({ ...event, seq });
121
+ },
122
+ async list(transaction, input) {
123
+ const clauses = ["conversation_id = ?"];
124
+ const values = [input.conversationId];
125
+ if (input.fromSeq !== undefined) {
126
+ clauses.push("seq >= ?");
127
+ values.push(input.fromSeq);
128
+ }
129
+ if (input.toSeq !== undefined) {
130
+ clauses.push("seq <= ?");
131
+ values.push(input.toSeq);
132
+ }
133
+ const rows = transaction.prepare(`
134
+ SELECT event_id, conversation_id, seq, schema_version, kind, occurred_at,
135
+ ignorable, payload
136
+ FROM stitchkit_agent_runtime_events
137
+ WHERE ${clauses.join(" AND ")}
138
+ ORDER BY seq ASC LIMIT ?
139
+ `).all(...values, input.limit + 1).map(parseEventRow);
140
+ const hasMore = rows.length > input.limit;
141
+ const items = rows.slice(0, input.limit);
142
+ const lastEvent = items.at(-1);
143
+ return AgentStoreEventPageSchema2.parse({
144
+ items,
145
+ ...hasMore && lastEvent ? { nextSeq: lastEvent.seq + 1 } : {}
146
+ });
147
+ },
148
+ async find(transaction, input) {
149
+ const row = transaction.prepare(`
150
+ SELECT event_id, conversation_id, seq, schema_version, kind, occurred_at,
151
+ ignorable, payload
152
+ FROM stitchkit_agent_runtime_events
153
+ WHERE event_id = ? AND conversation_id = ?
154
+ `).get(input.eventId, input.conversationId);
155
+ return row === null || row === undefined ? undefined : parseEventRow(row);
267
156
  }
268
- }
269
- function writeBaselines(database, migratedAt) {
270
- const conversations = database.prepare("SELECT conversation_id, version FROM stitchkit_agent_runtime_heads ORDER BY conversation_id").all().map((row) => ConversationRowSchema.parse(row));
271
- const insert = database.prepare(`
272
- INSERT INTO stitchkit_agent_runtime_events (
273
- conversation_id, seq, event_id, schema_version, kind, occurred_at, ignorable, payload
274
- ) VALUES (?, 1, ?, 1, 'runtime/baseline', ?, 0, ?)
275
- `);
276
- for (const conversation of conversations) {
277
- 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) => {
278
- const parsed = HistoryRowSchema.parse(row);
157
+ };
158
+ var sqliteArchive = {
159
+ async export(transaction, conversationId) {
160
+ const projections = transaction.prepare(`
161
+ SELECT name, version, upto_seq, payload, updated_at
162
+ FROM stitchkit_agent_runtime_projections
163
+ WHERE conversation_id = ? ORDER BY name
164
+ `).all(conversationId).map((raw) => {
165
+ const row = ArchiveProjectionRowSchema.parse(raw);
279
166
  return {
280
- message: AgentMessageSchema2.parse(parseJson2(parsed.payload)),
281
- active: parsed.active === 1
282
- };
283
- });
284
- const messages = rows.map((row) => row.message);
285
- const compacted = rows.filter((row) => !row.active).map((row) => row.message.id);
286
- 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) => {
287
- const row = PayloadRowSchema.parse(value);
288
- return {
289
- schemaVersion: 1,
290
- run: AgentRunSchema2.parse(parseJson2(row.payload)),
291
- ...row.terminal_assistant_payload ? {
292
- terminalAssistant: AgentMessageSchema2.parse(parseJson2(row.terminal_assistant_payload))
293
- } : {}
294
- };
295
- });
296
- const admissions = database.prepare("SELECT conversation_id, idempotency_key, input_payload, run_id, assistant_message_id FROM stitchkit_agent_runtime_admissions WHERE conversation_id = ? ORDER BY idempotency_key").all(conversation.conversation_id).map((value) => {
297
- const row = AdmissionRowSchema.parse(value);
298
- return {
299
- schemaVersion: 1,
300
- conversationId: row.conversation_id,
301
- idempotencyKey: row.idempotency_key,
302
- input: AgentMessageSchema2.parse(parseJson2(row.input_payload)),
303
- runId: row.run_id,
304
- assistantMessageId: row.assistant_message_id
305
- };
306
- });
307
- const asOf = messages.at(-1)?.createdAt ?? runs.at(-1)?.run.createdAt;
308
- insert.run(conversation.conversation_id, randomUUID(), migratedAt, canonicalAgentJson2({
309
- migratedAt,
310
- ...asOf !== undefined && { asOf },
311
- head: {
312
- schemaVersion: 1,
313
- conversationId: conversation.conversation_id,
314
- version: conversation.version
315
- },
316
- messages,
317
- ...compacted.length > 0 && { compacted },
318
- runs,
319
- admissions
320
- }));
321
- }
322
- }
323
- function migrateAgentRuntimeSqliteV1ToV2(database, migratedAt = new Date().toISOString()) {
324
- createDurableTables(database);
325
- writeBaselines(database, migratedAt);
326
- database.prepare("UPDATE stitchkit_agent_runtime_meta SET value = '2' WHERE key = 'schema_version'").run();
327
- }
328
- function createAgentRuntimeSqliteV2Tables(database) {
329
- createDurableTables(database);
330
- }
331
-
332
- // src/agent-runtime/store-migrations/v2-to-v3.ts
333
- function createAgentRuntimeSqliteV3Tables(database) {
334
- database.exec(`
335
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_seeds (
336
- conversation_id TEXT NOT NULL,
337
- seed_key TEXT NOT NULL,
338
- message_ids TEXT NOT NULL,
339
- created_at TEXT NOT NULL,
340
- PRIMARY KEY (conversation_id, seed_key)
341
- );
342
- `);
343
- }
344
- function migrateAgentRuntimeSqliteV2ToV3(database) {
345
- createAgentRuntimeSqliteV3Tables(database);
346
- database.prepare("UPDATE stitchkit_agent_runtime_meta SET value = '3' WHERE key = 'schema_version'").run();
347
- }
348
-
349
- // src/agent-runtime/store-migrations/v3-to-v4.ts
350
- function migrateAgentRuntimeSqliteV3ToV4(database) {
351
- database.exec(`
352
- ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN retry_at TEXT;
353
- ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN attempts INTEGER NOT NULL DEFAULT 0;
354
- ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN last_error TEXT;
355
- ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN eligible_at TEXT
356
- GENERATED ALWAYS AS (MAX(next_at, COALESCE(retry_at, next_at), COALESCE(claim_until, next_at))) VIRTUAL;
357
- DROP INDEX stitchkit_agent_runtime_schedules_due;
358
- CREATE INDEX stitchkit_agent_runtime_schedules_due
359
- ON stitchkit_agent_runtime_schedules (eligible_at, id) WHERE state = 'scheduled';
360
- UPDATE stitchkit_agent_runtime_meta SET value = '4' WHERE key = 'schema_version';
361
- `);
362
- }
363
-
364
- // src/agent-runtime/sqlite-schema.ts
365
- var MetaRowSchema = z3.object({ value: z3.string() });
366
- var TableRowSchema = z3.object({ name: z3.string() });
367
- var SCHEMA_VERSION = 4;
368
- var TABLES = [
369
- "stitchkit_agent_runtime_heads",
370
- "stitchkit_agent_runtime_runs",
371
- "stitchkit_agent_runtime_admissions",
372
- "stitchkit_agent_runtime_messages",
373
- "stitchkit_agent_runtime_seeds",
374
- "stitchkit_agent_runtime_events",
375
- "stitchkit_agent_runtime_projections",
376
- "stitchkit_agent_runtime_spills",
377
- "stitchkit_agent_runtime_schedules",
378
- "stitchkit_agent_runtime_children"
379
- ];
380
- function initializeAgentRuntimeSqlite2(database) {
381
- database.exec("BEGIN IMMEDIATE");
382
- try {
383
- const existing = database.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE 'stitchkit_agent_runtime_%' ORDER BY name`).all().map((row) => TableRowSchema.parse(row).name);
384
- const hasMeta = existing.includes("stitchkit_agent_runtime_meta");
385
- if (!hasMeta && existing.length > 0) {
386
- throw new Error("Refusing an unversioned partial Stitchkit agent-runtime SQLite schema");
387
- }
388
- database.exec(`
389
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_meta (
390
- key TEXT PRIMARY KEY,
391
- value TEXT NOT NULL
392
- );
393
- `);
394
- const versionRow = database.prepare("SELECT value FROM stitchkit_agent_runtime_meta WHERE key = 'schema_version'").get();
395
- if (!missing(versionRow)) {
396
- const version = Number(MetaRowSchema.parse(versionRow).value);
397
- if (version === 1) {
398
- migrateAgentRuntimeSqliteV1ToV2(database);
399
- migrateAgentRuntimeSqliteV2ToV3(database);
400
- migrateAgentRuntimeSqliteV3ToV4(database);
401
- initializeSqliteConversationPurge(database);
402
- database.exec("COMMIT");
403
- return;
404
- }
405
- if (version === 2) {
406
- migrateAgentRuntimeSqliteV2ToV3(database);
407
- migrateAgentRuntimeSqliteV3ToV4(database);
408
- initializeSqliteConversationPurge(database);
409
- database.exec("COMMIT");
410
- return;
411
- }
412
- if (version === 3) {
413
- migrateAgentRuntimeSqliteV3ToV4(database);
414
- initializeSqliteConversationPurge(database);
415
- database.exec("COMMIT");
416
- return;
417
- }
418
- if (version !== SCHEMA_VERSION) {
419
- throw new Error(`Unsupported Stitchkit agent-runtime SQLite schema version ${version}; expected ${SCHEMA_VERSION}`);
420
- }
421
- const missingTables = TABLES.filter((table) => !existing.includes(table));
422
- if (missingTables.length > 0) {
423
- throw new Error(`Refusing a partial Stitchkit agent-runtime SQLite schema; missing ${missingTables.join(", ")}`);
424
- }
425
- initializeSqliteConversationPurge(database);
426
- database.exec("COMMIT");
427
- return;
428
- }
429
- if (existing.some((table) => table !== "stitchkit_agent_runtime_meta")) {
430
- throw new Error("Refusing an unversioned partial Stitchkit agent-runtime SQLite schema");
431
- }
432
- database.exec(`
433
- CREATE TABLE stitchkit_agent_runtime_heads (
434
- conversation_id TEXT PRIMARY KEY,
435
- version INTEGER NOT NULL CHECK (version >= 0)
436
- );
437
- CREATE TABLE stitchkit_agent_runtime_runs (
438
- conversation_id TEXT NOT NULL,
439
- run_id TEXT NOT NULL,
440
- assistant_message_id TEXT NOT NULL,
441
- state TEXT NOT NULL,
442
- created_at TEXT NOT NULL,
443
- payload TEXT NOT NULL,
444
- terminal_assistant_payload TEXT,
445
- PRIMARY KEY (conversation_id, run_id),
446
- UNIQUE (conversation_id, assistant_message_id)
447
- );
448
- CREATE INDEX stitchkit_agent_runtime_recoverable
449
- ON stitchkit_agent_runtime_runs (state, conversation_id, run_id);
450
- CREATE TABLE stitchkit_agent_runtime_admissions (
451
- conversation_id TEXT NOT NULL,
452
- idempotency_key TEXT NOT NULL,
453
- input_message_id TEXT NOT NULL,
454
- run_id TEXT NOT NULL,
455
- assistant_message_id TEXT NOT NULL,
456
- input_payload TEXT NOT NULL,
457
- PRIMARY KEY (conversation_id, idempotency_key),
458
- UNIQUE (conversation_id, input_message_id)
459
- );
460
- CREATE TABLE stitchkit_agent_runtime_messages (
461
- conversation_id TEXT NOT NULL,
462
- id TEXT NOT NULL,
463
- position INTEGER NOT NULL CHECK (position >= 0),
464
- active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)),
465
- payload TEXT NOT NULL,
466
- PRIMARY KEY (conversation_id, id)
467
- );
468
- `);
469
- createAgentRuntimeSqliteV2Tables(database);
470
- createAgentRuntimeSqliteV3Tables(database);
471
- database.prepare("INSERT INTO stitchkit_agent_runtime_meta (key, value) VALUES ('schema_version', '3')").run();
472
- migrateAgentRuntimeSqliteV3ToV4(database);
473
- initializeSqliteConversationPurge(database);
474
- database.exec("COMMIT");
475
- } catch (error) {
476
- database.exec("ROLLBACK");
477
- throw error;
478
- }
479
- }
480
-
481
- // src/agent-runtime/sqlite-events.ts
482
- import { createHash } from "node:crypto";
483
- import { z as z4 } from "zod";
484
- var ArchiveProjectionRowSchema = z4.object({
485
- name: z4.string(),
486
- version: z4.int().positive(),
487
- upto_seq: z4.int().nonnegative(),
488
- payload: z4.string(),
489
- updated_at: z4.string()
490
- });
491
- var ArchiveSpillRowSchema = z4.object({
492
- reference_id: z4.string(),
493
- run_id: z4.string().nullable(),
494
- tool_call_id: z4.string().nullable(),
495
- media_type: z4.string(),
496
- bytes: z4.int().nonnegative(),
497
- sha256: z4.string(),
498
- created_at: z4.string(),
499
- expires_at: z4.string().nullable(),
500
- authorization_payload: z4.string().nullable(),
501
- payload: z4.instanceof(Uint8Array)
502
- });
503
- var sqliteEvents = {
504
- async append(transaction, rawEvent) {
505
- const event = rawEvent;
506
- const last = transaction.prepare("SELECT COALESCE(MAX(seq), 0) AS count FROM stitchkit_agent_runtime_events WHERE conversation_id = ?").get(event.conversationId);
507
- const seq = CountRowSchema.parse(last).count + 1;
508
- transaction.prepare(`
509
- INSERT INTO stitchkit_agent_runtime_events (
510
- conversation_id, seq, event_id, schema_version, kind, occurred_at, ignorable, payload
511
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
512
- `).run(event.conversationId, seq, event.eventId, event.schemaVersion, event.kind, event.occurredAt, event.ignorable ? 1 : 0, encodeJson(event.payload));
513
- return AgentStoreEventEnvelopeSchema2.parse({ ...event, seq });
514
- },
515
- async list(transaction, input) {
516
- const clauses = ["conversation_id = ?"];
517
- const values = [input.conversationId];
518
- if (input.fromSeq !== undefined) {
519
- clauses.push("seq >= ?");
520
- values.push(input.fromSeq);
521
- }
522
- if (input.toSeq !== undefined) {
523
- clauses.push("seq <= ?");
524
- values.push(input.toSeq);
525
- }
526
- const rows = transaction.prepare(`
527
- SELECT event_id, conversation_id, seq, schema_version, kind, occurred_at,
528
- ignorable, payload
529
- FROM stitchkit_agent_runtime_events
530
- WHERE ${clauses.join(" AND ")}
531
- ORDER BY seq ASC LIMIT ?
532
- `).all(...values, input.limit + 1).map(parseEventRow);
533
- const hasMore = rows.length > input.limit;
534
- const items = rows.slice(0, input.limit);
535
- const lastEvent = items.at(-1);
536
- return AgentStoreEventPageSchema2.parse({
537
- items,
538
- ...hasMore && lastEvent ? { nextSeq: lastEvent.seq + 1 } : {}
539
- });
540
- },
541
- async find(transaction, input) {
542
- const row = transaction.prepare(`
543
- SELECT event_id, conversation_id, seq, schema_version, kind, occurred_at,
544
- ignorable, payload
545
- FROM stitchkit_agent_runtime_events
546
- WHERE event_id = ? AND conversation_id = ?
547
- `).get(input.eventId, input.conversationId);
548
- return row === null || row === undefined ? undefined : parseEventRow(row);
549
- }
550
- };
551
- var sqliteArchive = {
552
- async export(transaction, conversationId) {
553
- const projections = transaction.prepare(`
554
- SELECT name, version, upto_seq, payload, updated_at
555
- FROM stitchkit_agent_runtime_projections
556
- WHERE conversation_id = ? ORDER BY name
557
- `).all(conversationId).map((raw) => {
558
- const row = ArchiveProjectionRowSchema.parse(raw);
559
- return {
560
- name: row.name,
561
- version: row.version,
562
- uptoSeq: row.upto_seq,
563
- value: z4.json().parse(parseJson(row.payload)),
564
- updatedAt: row.updated_at
167
+ name: row.name,
168
+ version: row.version,
169
+ uptoSeq: row.upto_seq,
170
+ value: z2.json().parse(parseJson(row.payload)),
171
+ updatedAt: row.updated_at
565
172
  };
566
173
  });
567
174
  const spills = transaction.prepare(`
@@ -581,7 +188,7 @@ var sqliteArchive = {
581
188
  createdAt: row.created_at,
582
189
  ...row.expires_at && { expiresAt: row.expires_at },
583
190
  ...row.authorization_payload && {
584
- authorization: z4.json().parse(parseJson(row.authorization_payload))
191
+ authorization: z2.json().parse(parseJson(row.authorization_payload))
585
192
  },
586
193
  base64: Buffer.from(row.payload).toString("base64")
587
194
  };
@@ -601,17 +208,17 @@ var sqliteArchive = {
601
208
  `).run(archive.conversationId, projection.name, projection.version, projection.uptoSeq, encodeJson(projection.value), projection.updatedAt);
602
209
  }
603
210
  for (const raw of archive.spills) {
604
- const spill = z4.object({
605
- reference: z4.string(),
606
- runId: z4.string().optional(),
607
- toolCallId: z4.string().optional(),
608
- mediaType: z4.string(),
609
- bytes: z4.int().nonnegative(),
610
- sha256: z4.string(),
611
- createdAt: z4.string(),
612
- expiresAt: z4.string().optional(),
613
- authorization: z4.json().optional(),
614
- base64: z4.string()
211
+ const spill = z2.object({
212
+ reference: z2.string(),
213
+ runId: z2.string().optional(),
214
+ toolCallId: z2.string().optional(),
215
+ mediaType: z2.string(),
216
+ bytes: z2.int().nonnegative(),
217
+ sha256: z2.string(),
218
+ createdAt: z2.string(),
219
+ expiresAt: z2.string().optional(),
220
+ authorization: z2.json().optional(),
221
+ base64: z2.string()
615
222
  }).strict().parse(raw);
616
223
  const payload = Buffer.from(spill.base64, "base64");
617
224
  if (payload.byteLength !== spill.bytes) {
@@ -740,21 +347,21 @@ var sqliteHistory = {
740
347
  };
741
348
 
742
349
  // src/agent-runtime/sqlite-ledger.ts
743
- import { z as z5 } from "zod";
744
- var AdmissionRowSchema2 = z5.object({
745
- conversation_id: z5.string(),
746
- idempotency_key: z5.string(),
747
- input_payload: z5.string(),
748
- run_id: z5.string(),
749
- assistant_message_id: z5.string()
350
+ import { z as z3 } from "zod";
351
+ var AdmissionRowSchema = z3.object({
352
+ conversation_id: z3.string(),
353
+ idempotency_key: z3.string(),
354
+ input_payload: z3.string(),
355
+ run_id: z3.string(),
356
+ assistant_message_id: z3.string()
750
357
  });
751
- var SeedRowSchema = z5.object({
752
- conversation_id: z5.string(),
753
- seed_key: z5.string(),
754
- message_ids: z5.string()
358
+ var SeedRowSchema = z3.object({
359
+ conversation_id: z3.string(),
360
+ seed_key: z3.string(),
361
+ message_ids: z3.string()
755
362
  });
756
363
  function parseAdmissionRow(value) {
757
- const row = AdmissionRowSchema2.parse(value);
364
+ const row = AdmissionRowSchema.parse(value);
758
365
  return AgentAdmissionReceiptSchema2.parse({
759
366
  schemaVersion: 1,
760
367
  conversationId: row.conversation_id,
@@ -879,7 +486,7 @@ var sqliteSeeds = {
879
486
  schemaVersion: 1,
880
487
  conversationId: row.conversation_id,
881
488
  seedKey: row.seed_key,
882
- messageIds: z5.array(z5.string().min(1)).parse(parseJson(row.message_ids))
489
+ messageIds: z3.array(z3.string().min(1)).parse(parseJson(row.message_ids))
883
490
  });
884
491
  },
885
492
  async create(transaction, rawReceipt) {
@@ -892,8 +499,66 @@ var sqliteSeeds = {
892
499
  }
893
500
  };
894
501
 
502
+ // src/agent-runtime/sqlite-purge.ts
503
+ var OWNED_TABLES = [
504
+ "stitchkit_agent_runtime_spills",
505
+ "stitchkit_agent_runtime_schedules",
506
+ "stitchkit_agent_runtime_projections",
507
+ "stitchkit_agent_runtime_events",
508
+ "stitchkit_agent_runtime_messages",
509
+ "stitchkit_agent_runtime_seeds",
510
+ "stitchkit_agent_runtime_admissions",
511
+ "stitchkit_agent_runtime_runs",
512
+ "stitchkit_agent_runtime_heads"
513
+ ];
514
+ function initializeSqliteConversationPurge(database) {
515
+ database.exec(`
516
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_purged (
517
+ conversation_id TEXT PRIMARY KEY
518
+ );
519
+ `);
520
+ for (const table of OWNED_TABLES) {
521
+ for (const operation of ["INSERT", "UPDATE"]) {
522
+ database.exec(`
523
+ CREATE TRIGGER IF NOT EXISTS ${table}_purge_${operation.toLowerCase()}
524
+ BEFORE ${operation} ON ${table}
525
+ WHEN EXISTS (
526
+ SELECT 1 FROM stitchkit_agent_runtime_purged WHERE conversation_id = NEW.conversation_id
527
+ )
528
+ BEGIN SELECT RAISE(ABORT, 'Agent conversation has been purged'); END;
529
+ `);
530
+ }
531
+ }
532
+ }
533
+ function sqliteConversationPurge(database) {
534
+ const table = database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'stitchkit_agent_runtime_purged'").get();
535
+ if (table === null || table === undefined)
536
+ return;
537
+ return {
538
+ async isEmpty(transaction, conversationId) {
539
+ for (const table of OWNED_TABLES) {
540
+ const row = transaction.prepare(`SELECT 1 FROM ${table} WHERE conversation_id = ? LIMIT 1`).get(conversationId);
541
+ if (row !== null && row !== undefined)
542
+ return false;
543
+ }
544
+ return transaction.prepare("SELECT 1 FROM stitchkit_agent_runtime_children WHERE parent_conversation_id = ? OR child_conversation_id = ? LIMIT 1").get(conversationId, conversationId) == null;
545
+ },
546
+ async isPurged(transaction, conversationId) {
547
+ const row = transaction.prepare("SELECT conversation_id FROM stitchkit_agent_runtime_purged WHERE conversation_id = ?").get(conversationId);
548
+ return row !== null && row !== undefined;
549
+ },
550
+ async remove(transaction, conversationId) {
551
+ transaction.prepare("INSERT INTO stitchkit_agent_runtime_purged (conversation_id) VALUES (?)").run(conversationId);
552
+ for (const table of OWNED_TABLES) {
553
+ transaction.prepare(`DELETE FROM ${table} WHERE conversation_id = ?`).run(conversationId);
554
+ }
555
+ transaction.prepare("DELETE FROM stitchkit_agent_runtime_children WHERE parent_conversation_id = ? OR child_conversation_id = ?").run(conversationId, conversationId);
556
+ }
557
+ };
558
+ }
559
+
895
560
  // src/agent-runtime/sqlite-reads.ts
896
- import { z as z6 } from "zod";
561
+ import { z as z4 } from "zod";
897
562
 
898
563
  // src/agent-runtime/sqlite-transactions.ts
899
564
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -951,40 +616,40 @@ async function closeSqliteStore(state) {
951
616
  }
952
617
 
953
618
  // src/agent-runtime/sqlite-reads.ts
954
- var RecoverableRowSchema = z6.object({
955
- conversation_id: z6.string(),
956
- run_id: z6.string(),
957
- payload: z6.string()
619
+ var RecoverableRowSchema = z4.object({
620
+ conversation_id: z4.string(),
621
+ run_id: z4.string(),
622
+ payload: z4.string()
958
623
  });
959
- var ConversationHeadRowSchema = z6.object({
960
- conversation_id: z6.string(),
961
- version: z6.number().int().nonnegative()
624
+ var ConversationHeadRowSchema = z4.object({
625
+ conversation_id: z4.string(),
626
+ version: z4.number().int().nonnegative()
962
627
  });
963
- var MessagePageRowSchema = z6.object({
964
- row_id: z6.number().int().positive(),
965
- position: z6.number().int().nonnegative(),
966
- active: z6.union([z6.literal(0), z6.literal(1)]),
967
- payload: z6.string()
628
+ var MessagePageRowSchema = z4.object({
629
+ row_id: z4.number().int().positive(),
630
+ position: z4.number().int().nonnegative(),
631
+ active: z4.union([z4.literal(0), z4.literal(1)]),
632
+ payload: z4.string()
968
633
  });
969
634
  function recoveryCursor(conversationId, runId) {
970
635
  return encodeJson([conversationId, runId]);
971
636
  }
972
637
  function parseRecoveryCursor(cursor) {
973
- return z6.tuple([z6.string().min(1), z6.string().min(1)]).parse(parseJson(cursor));
638
+ return z4.tuple([z4.string().min(1), z4.string().min(1)]).parse(parseJson(cursor));
974
639
  }
975
640
  function conversationCursor(conversationId) {
976
641
  return encodeJson([conversationId]);
977
642
  }
978
643
  function parseConversationCursor(cursor) {
979
- return z6.tuple([z6.string().min(1)]).parse(parseJson(cursor))[0];
644
+ return z4.tuple([z4.string().min(1)]).parse(parseJson(cursor))[0];
980
645
  }
981
646
  function messageCursor(position, rowId) {
982
647
  return encodeJson([position, rowId]);
983
648
  }
984
649
  function parseMessageCursor(cursor) {
985
- const parsed = z6.union([
986
- z6.tuple([z6.int().nonnegative(), z6.int().positive()]),
987
- z6.tuple([z6.int().nonnegative()])
650
+ const parsed = z4.union([
651
+ z4.tuple([z4.int().nonnegative(), z4.int().positive()]),
652
+ z4.tuple([z4.int().nonnegative()])
988
653
  ]).parse(parseJson(cursor));
989
654
  const [position, rowId] = parsed;
990
655
  return { position, ...rowId !== undefined && { rowId } };
@@ -1109,6 +774,343 @@ function pageSqliteConversationMessages(state, input) {
1109
774
  });
1110
775
  }
1111
776
 
777
+ // src/agent-runtime/sqlite-schema.ts
778
+ import { z as z6 } from "zod";
779
+
780
+ // src/agent-runtime/store-migrations/v1-to-v2.ts
781
+ import { randomUUID } from "node:crypto";
782
+ import { z as z5 } from "zod";
783
+ var ConversationRowSchema = z5.object({
784
+ conversation_id: z5.string().min(1),
785
+ version: z5.int().nonnegative()
786
+ });
787
+ var PayloadRowSchema = z5.object({
788
+ payload: z5.string(),
789
+ terminal_assistant_payload: z5.string().nullable().optional()
790
+ });
791
+ var HistoryRowSchema = z5.object({
792
+ payload: z5.string(),
793
+ active: z5.union([z5.literal(0), z5.literal(1)])
794
+ });
795
+ var AdmissionRowSchema2 = z5.object({
796
+ conversation_id: z5.string(),
797
+ idempotency_key: z5.string(),
798
+ input_payload: z5.string(),
799
+ run_id: z5.string(),
800
+ assistant_message_id: z5.string()
801
+ });
802
+ function parseJson2(value) {
803
+ return JSON.parse(value);
804
+ }
805
+ function createDurableTables(database) {
806
+ database.exec(`
807
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_events (
808
+ row_id INTEGER PRIMARY KEY AUTOINCREMENT,
809
+ conversation_id TEXT NOT NULL,
810
+ seq INTEGER NOT NULL CHECK (seq > 0),
811
+ event_id TEXT NOT NULL UNIQUE,
812
+ schema_version INTEGER NOT NULL CHECK (schema_version > 0),
813
+ kind TEXT NOT NULL,
814
+ occurred_at TEXT NOT NULL,
815
+ ignorable INTEGER NOT NULL DEFAULT 0 CHECK (ignorable IN (0, 1)),
816
+ payload TEXT NOT NULL,
817
+ UNIQUE (conversation_id, seq)
818
+ );
819
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_events_time
820
+ ON stitchkit_agent_runtime_events (conversation_id, occurred_at, seq);
821
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_projections (
822
+ conversation_id TEXT NOT NULL,
823
+ name TEXT NOT NULL,
824
+ version INTEGER NOT NULL CHECK (version > 0),
825
+ upto_seq INTEGER NOT NULL CHECK (upto_seq >= 0),
826
+ payload TEXT NOT NULL,
827
+ updated_at TEXT NOT NULL,
828
+ PRIMARY KEY (conversation_id, name)
829
+ );
830
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_projection_updates
831
+ ON stitchkit_agent_runtime_projections (name, updated_at, conversation_id);
832
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_spills (
833
+ reference_id TEXT PRIMARY KEY,
834
+ conversation_id TEXT NOT NULL,
835
+ run_id TEXT,
836
+ tool_call_id TEXT,
837
+ media_type TEXT NOT NULL,
838
+ bytes INTEGER NOT NULL CHECK (bytes >= 0),
839
+ sha256 TEXT NOT NULL,
840
+ created_at TEXT NOT NULL,
841
+ expires_at TEXT,
842
+ authorization_payload TEXT,
843
+ payload BLOB NOT NULL
844
+ );
845
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_spills_owner
846
+ ON stitchkit_agent_runtime_spills (conversation_id, created_at);
847
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_schedules (
848
+ id TEXT PRIMARY KEY,
849
+ conversation_id TEXT NOT NULL,
850
+ kind TEXT NOT NULL,
851
+ next_at TEXT NOT NULL,
852
+ interval_ms INTEGER,
853
+ time_zone TEXT,
854
+ input_payload TEXT NOT NULL,
855
+ state TEXT NOT NULL,
856
+ occurrence INTEGER NOT NULL DEFAULT 0 CHECK (occurrence >= 0),
857
+ claim_owner TEXT,
858
+ claim_until TEXT,
859
+ created_at TEXT NOT NULL,
860
+ updated_at TEXT NOT NULL
861
+ );
862
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_schedules_due
863
+ ON stitchkit_agent_runtime_schedules (state, next_at);
864
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_children (
865
+ parent_conversation_id TEXT NOT NULL,
866
+ child_conversation_id TEXT NOT NULL UNIQUE,
867
+ seed_upto_seq INTEGER,
868
+ state TEXT NOT NULL,
869
+ budget_payload TEXT NOT NULL,
870
+ usage_payload TEXT NOT NULL,
871
+ result_reference TEXT,
872
+ created_at TEXT NOT NULL,
873
+ updated_at TEXT NOT NULL,
874
+ PRIMARY KEY (parent_conversation_id, child_conversation_id)
875
+ );
876
+ `);
877
+ try {
878
+ database.exec(`
879
+ CREATE VIRTUAL TABLE IF NOT EXISTS stitchkit_agent_runtime_events_fts
880
+ USING fts5(
881
+ conversation_id UNINDEXED,
882
+ event_seq UNINDEXED,
883
+ occurred_at UNINDEXED,
884
+ body,
885
+ tokenize = 'unicode61 remove_diacritics 2'
886
+ );
887
+ CREATE TRIGGER IF NOT EXISTS stitchkit_agent_runtime_events_fts_insert
888
+ AFTER INSERT ON stitchkit_agent_runtime_events BEGIN
889
+ INSERT INTO stitchkit_agent_runtime_events_fts(
890
+ rowid, conversation_id, event_seq, occurred_at, body
891
+ ) VALUES (new.row_id, new.conversation_id, new.seq, new.occurred_at, new.payload);
892
+ END;
893
+ CREATE TRIGGER IF NOT EXISTS stitchkit_agent_runtime_events_fts_delete
894
+ AFTER DELETE ON stitchkit_agent_runtime_events BEGIN
895
+ DELETE FROM stitchkit_agent_runtime_events_fts WHERE rowid = old.row_id;
896
+ END;
897
+ `);
898
+ } catch (error) {
899
+ throw new Error("SQLite agent-runtime requires FTS5 support", { cause: error });
900
+ }
901
+ }
902
+ function writeBaselines(database, migratedAt) {
903
+ const conversations = database.prepare("SELECT conversation_id, version FROM stitchkit_agent_runtime_heads ORDER BY conversation_id").all().map((row) => ConversationRowSchema.parse(row));
904
+ const insert = database.prepare(`
905
+ INSERT INTO stitchkit_agent_runtime_events (
906
+ conversation_id, seq, event_id, schema_version, kind, occurred_at, ignorable, payload
907
+ ) VALUES (?, 1, ?, 1, 'runtime/baseline', ?, 0, ?)
908
+ `);
909
+ for (const conversation of conversations) {
910
+ 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) => {
911
+ const parsed = HistoryRowSchema.parse(row);
912
+ return {
913
+ message: AgentMessageSchema2.parse(parseJson2(parsed.payload)),
914
+ active: parsed.active === 1
915
+ };
916
+ });
917
+ const messages = rows.map((row) => row.message);
918
+ const compacted = rows.filter((row) => !row.active).map((row) => row.message.id);
919
+ 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) => {
920
+ const row = PayloadRowSchema.parse(value);
921
+ return {
922
+ schemaVersion: 1,
923
+ run: AgentRunSchema2.parse(parseJson2(row.payload)),
924
+ ...row.terminal_assistant_payload ? {
925
+ terminalAssistant: AgentMessageSchema2.parse(parseJson2(row.terminal_assistant_payload))
926
+ } : {}
927
+ };
928
+ });
929
+ const admissions = database.prepare("SELECT conversation_id, idempotency_key, input_payload, run_id, assistant_message_id FROM stitchkit_agent_runtime_admissions WHERE conversation_id = ? ORDER BY idempotency_key").all(conversation.conversation_id).map((value) => {
930
+ const row = AdmissionRowSchema2.parse(value);
931
+ return {
932
+ schemaVersion: 1,
933
+ conversationId: row.conversation_id,
934
+ idempotencyKey: row.idempotency_key,
935
+ input: AgentMessageSchema2.parse(parseJson2(row.input_payload)),
936
+ runId: row.run_id,
937
+ assistantMessageId: row.assistant_message_id
938
+ };
939
+ });
940
+ const asOf = messages.at(-1)?.createdAt ?? runs.at(-1)?.run.createdAt;
941
+ insert.run(conversation.conversation_id, randomUUID(), migratedAt, canonicalAgentJson2({
942
+ migratedAt,
943
+ ...asOf !== undefined && { asOf },
944
+ head: {
945
+ schemaVersion: 1,
946
+ conversationId: conversation.conversation_id,
947
+ version: conversation.version
948
+ },
949
+ messages,
950
+ ...compacted.length > 0 && { compacted },
951
+ runs,
952
+ admissions
953
+ }));
954
+ }
955
+ }
956
+ function migrateAgentRuntimeSqliteV1ToV2(database, migratedAt = new Date().toISOString()) {
957
+ createDurableTables(database);
958
+ writeBaselines(database, migratedAt);
959
+ database.prepare("UPDATE stitchkit_agent_runtime_meta SET value = '2' WHERE key = 'schema_version'").run();
960
+ }
961
+ function createAgentRuntimeSqliteV2Tables(database) {
962
+ createDurableTables(database);
963
+ }
964
+
965
+ // src/agent-runtime/store-migrations/v2-to-v3.ts
966
+ function createAgentRuntimeSqliteV3Tables(database) {
967
+ database.exec(`
968
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_seeds (
969
+ conversation_id TEXT NOT NULL,
970
+ seed_key TEXT NOT NULL,
971
+ message_ids TEXT NOT NULL,
972
+ created_at TEXT NOT NULL,
973
+ PRIMARY KEY (conversation_id, seed_key)
974
+ );
975
+ `);
976
+ }
977
+ function migrateAgentRuntimeSqliteV2ToV3(database) {
978
+ createAgentRuntimeSqliteV3Tables(database);
979
+ database.prepare("UPDATE stitchkit_agent_runtime_meta SET value = '3' WHERE key = 'schema_version'").run();
980
+ }
981
+
982
+ // src/agent-runtime/store-migrations/v3-to-v4.ts
983
+ function migrateAgentRuntimeSqliteV3ToV4(database) {
984
+ database.exec(`
985
+ ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN retry_at TEXT;
986
+ ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN attempts INTEGER NOT NULL DEFAULT 0;
987
+ ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN last_error TEXT;
988
+ ALTER TABLE stitchkit_agent_runtime_schedules ADD COLUMN eligible_at TEXT
989
+ GENERATED ALWAYS AS (MAX(next_at, COALESCE(retry_at, next_at), COALESCE(claim_until, next_at))) VIRTUAL;
990
+ DROP INDEX stitchkit_agent_runtime_schedules_due;
991
+ CREATE INDEX stitchkit_agent_runtime_schedules_due
992
+ ON stitchkit_agent_runtime_schedules (eligible_at, id) WHERE state = 'scheduled';
993
+ UPDATE stitchkit_agent_runtime_meta SET value = '4' WHERE key = 'schema_version';
994
+ `);
995
+ }
996
+
997
+ // src/agent-runtime/sqlite-schema.ts
998
+ var MetaRowSchema = z6.object({ value: z6.string() });
999
+ var TableRowSchema = z6.object({ name: z6.string() });
1000
+ var SCHEMA_VERSION = 4;
1001
+ var TABLES = [
1002
+ "stitchkit_agent_runtime_heads",
1003
+ "stitchkit_agent_runtime_runs",
1004
+ "stitchkit_agent_runtime_admissions",
1005
+ "stitchkit_agent_runtime_messages",
1006
+ "stitchkit_agent_runtime_seeds",
1007
+ "stitchkit_agent_runtime_events",
1008
+ "stitchkit_agent_runtime_projections",
1009
+ "stitchkit_agent_runtime_spills",
1010
+ "stitchkit_agent_runtime_schedules",
1011
+ "stitchkit_agent_runtime_children"
1012
+ ];
1013
+ function initializeAgentRuntimeSqlite2(database) {
1014
+ database.exec("BEGIN IMMEDIATE");
1015
+ try {
1016
+ const existing = database.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE 'stitchkit_agent_runtime_%' ORDER BY name`).all().map((row) => TableRowSchema.parse(row).name);
1017
+ const hasMeta = existing.includes("stitchkit_agent_runtime_meta");
1018
+ if (!hasMeta && existing.length > 0) {
1019
+ throw new Error("Refusing an unversioned partial Stitchkit agent-runtime SQLite schema");
1020
+ }
1021
+ database.exec(`
1022
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_meta (
1023
+ key TEXT PRIMARY KEY,
1024
+ value TEXT NOT NULL
1025
+ );
1026
+ `);
1027
+ const versionRow = database.prepare("SELECT value FROM stitchkit_agent_runtime_meta WHERE key = 'schema_version'").get();
1028
+ if (!missing(versionRow)) {
1029
+ const version = Number(MetaRowSchema.parse(versionRow).value);
1030
+ if (version === 1) {
1031
+ migrateAgentRuntimeSqliteV1ToV2(database);
1032
+ migrateAgentRuntimeSqliteV2ToV3(database);
1033
+ migrateAgentRuntimeSqliteV3ToV4(database);
1034
+ initializeSqliteConversationPurge(database);
1035
+ database.exec("COMMIT");
1036
+ return;
1037
+ }
1038
+ if (version === 2) {
1039
+ migrateAgentRuntimeSqliteV2ToV3(database);
1040
+ migrateAgentRuntimeSqliteV3ToV4(database);
1041
+ initializeSqliteConversationPurge(database);
1042
+ database.exec("COMMIT");
1043
+ return;
1044
+ }
1045
+ if (version === 3) {
1046
+ migrateAgentRuntimeSqliteV3ToV4(database);
1047
+ initializeSqliteConversationPurge(database);
1048
+ database.exec("COMMIT");
1049
+ return;
1050
+ }
1051
+ if (version !== SCHEMA_VERSION) {
1052
+ throw new Error(`Unsupported Stitchkit agent-runtime SQLite schema version ${version}; expected ${SCHEMA_VERSION}`);
1053
+ }
1054
+ const missingTables = TABLES.filter((table) => !existing.includes(table));
1055
+ if (missingTables.length > 0) {
1056
+ throw new Error(`Refusing a partial Stitchkit agent-runtime SQLite schema; missing ${missingTables.join(", ")}`);
1057
+ }
1058
+ initializeSqliteConversationPurge(database);
1059
+ database.exec("COMMIT");
1060
+ return;
1061
+ }
1062
+ if (existing.some((table) => table !== "stitchkit_agent_runtime_meta")) {
1063
+ throw new Error("Refusing an unversioned partial Stitchkit agent-runtime SQLite schema");
1064
+ }
1065
+ database.exec(`
1066
+ CREATE TABLE stitchkit_agent_runtime_heads (
1067
+ conversation_id TEXT PRIMARY KEY,
1068
+ version INTEGER NOT NULL CHECK (version >= 0)
1069
+ );
1070
+ CREATE TABLE stitchkit_agent_runtime_runs (
1071
+ conversation_id TEXT NOT NULL,
1072
+ run_id TEXT NOT NULL,
1073
+ assistant_message_id TEXT NOT NULL,
1074
+ state TEXT NOT NULL,
1075
+ created_at TEXT NOT NULL,
1076
+ payload TEXT NOT NULL,
1077
+ terminal_assistant_payload TEXT,
1078
+ PRIMARY KEY (conversation_id, run_id),
1079
+ UNIQUE (conversation_id, assistant_message_id)
1080
+ );
1081
+ CREATE INDEX stitchkit_agent_runtime_recoverable
1082
+ ON stitchkit_agent_runtime_runs (state, conversation_id, run_id);
1083
+ CREATE TABLE stitchkit_agent_runtime_admissions (
1084
+ conversation_id TEXT NOT NULL,
1085
+ idempotency_key TEXT NOT NULL,
1086
+ input_message_id TEXT NOT NULL,
1087
+ run_id TEXT NOT NULL,
1088
+ assistant_message_id TEXT NOT NULL,
1089
+ input_payload TEXT NOT NULL,
1090
+ PRIMARY KEY (conversation_id, idempotency_key),
1091
+ UNIQUE (conversation_id, input_message_id)
1092
+ );
1093
+ CREATE TABLE stitchkit_agent_runtime_messages (
1094
+ conversation_id TEXT NOT NULL,
1095
+ id TEXT NOT NULL,
1096
+ position INTEGER NOT NULL CHECK (position >= 0),
1097
+ active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)),
1098
+ payload TEXT NOT NULL,
1099
+ PRIMARY KEY (conversation_id, id)
1100
+ );
1101
+ `);
1102
+ createAgentRuntimeSqliteV2Tables(database);
1103
+ createAgentRuntimeSqliteV3Tables(database);
1104
+ database.prepare("INSERT INTO stitchkit_agent_runtime_meta (key, value) VALUES ('schema_version', '3')").run();
1105
+ migrateAgentRuntimeSqliteV3ToV4(database);
1106
+ initializeSqliteConversationPurge(database);
1107
+ database.exec("COMMIT");
1108
+ } catch (error) {
1109
+ database.exec("ROLLBACK");
1110
+ throw error;
1111
+ }
1112
+ }
1113
+
1112
1114
  // src/agent-runtime/sqlite.ts
1113
1115
  function createSqliteAgentRuntimeStore2(config) {
1114
1116
  const database = config.database;