stitchkit 0.85.2 → 0.86.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 (111) hide show
  1. package/CHANGELOG.md +160 -0
  2. package/README.md +3 -0
  3. package/dist/agent-runtime/agent-tool.d.ts +25 -0
  4. package/dist/agent-runtime/agent-tool.d.ts.map +1 -0
  5. package/dist/agent-runtime/child-tools.d.ts +69 -0
  6. package/dist/agent-runtime/child-tools.d.ts.map +1 -0
  7. package/dist/agent-runtime/children.d.ts +113 -0
  8. package/dist/agent-runtime/children.d.ts.map +1 -0
  9. package/dist/agent-runtime/coding-tool-contract.d.ts +29 -0
  10. package/dist/agent-runtime/coding-tool-contract.d.ts.map +1 -1
  11. package/dist/agent-runtime/coding-tool-refusals.d.ts +2 -0
  12. package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
  13. package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
  14. package/dist/agent-runtime/coding-tools.d.ts +1 -0
  15. package/dist/agent-runtime/coding-tools.d.ts.map +1 -1
  16. package/dist/agent-runtime/control-schema.d.ts +17 -0
  17. package/dist/agent-runtime/control-schema.d.ts.map +1 -1
  18. package/dist/agent-runtime/event-schema.d.ts +34 -0
  19. package/dist/agent-runtime/event-schema.d.ts.map +1 -1
  20. package/dist/agent-runtime/event-search-tools.d.ts +53 -0
  21. package/dist/agent-runtime/event-search-tools.d.ts.map +1 -0
  22. package/dist/agent-runtime/event-search.d.ts +23 -0
  23. package/dist/agent-runtime/event-search.d.ts.map +1 -0
  24. package/dist/agent-runtime/fault-bench.d.ts +45 -0
  25. package/dist/agent-runtime/fault-bench.d.ts.map +1 -0
  26. package/dist/agent-runtime/observability.d.ts +6 -0
  27. package/dist/agent-runtime/observability.d.ts.map +1 -1
  28. package/dist/agent-runtime/projections.d.ts +69 -0
  29. package/dist/agent-runtime/projections.d.ts.map +1 -0
  30. package/dist/agent-runtime/provider-failure.d.ts +5 -1
  31. package/dist/agent-runtime/provider-failure.d.ts.map +1 -1
  32. package/dist/agent-runtime/provider-origin.d.ts +12 -0
  33. package/dist/agent-runtime/provider-origin.d.ts.map +1 -0
  34. package/dist/agent-runtime/retry-policy.d.ts +27 -0
  35. package/dist/agent-runtime/retry-policy.d.ts.map +1 -0
  36. package/dist/agent-runtime/run-execution.d.ts +0 -9
  37. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  38. package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
  39. package/dist/agent-runtime/runtime.d.ts +15 -0
  40. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  41. package/dist/agent-runtime/sandbox.d.ts +66 -0
  42. package/dist/agent-runtime/sandbox.d.ts.map +1 -0
  43. package/dist/agent-runtime/schedule-tools.d.ts +35 -0
  44. package/dist/agent-runtime/schedule-tools.d.ts.map +1 -0
  45. package/dist/agent-runtime/schedules.d.ts +63 -0
  46. package/dist/agent-runtime/schedules.d.ts.map +1 -0
  47. package/dist/agent-runtime/schemas.d.ts +9 -0
  48. package/dist/agent-runtime/schemas.d.ts.map +1 -1
  49. package/dist/agent-runtime/spill.d.ts +24 -0
  50. package/dist/agent-runtime/spill.d.ts.map +1 -0
  51. package/dist/agent-runtime/sqlite-purge.d.ts.map +1 -1
  52. package/dist/agent-runtime/sqlite.d.ts +26 -0
  53. package/dist/agent-runtime/sqlite.d.ts.map +1 -1
  54. package/dist/agent-runtime/state-slots.d.ts +48 -0
  55. package/dist/agent-runtime/state-slots.d.ts.map +1 -0
  56. package/dist/agent-runtime/state-tools.d.ts +58 -0
  57. package/dist/agent-runtime/state-tools.d.ts.map +1 -0
  58. package/dist/agent-runtime/store-driver.d.ts +13 -0
  59. package/dist/agent-runtime/store-driver.d.ts.map +1 -1
  60. package/dist/agent-runtime/store-events.d.ts +829 -0
  61. package/dist/agent-runtime/store-events.d.ts.map +1 -0
  62. package/dist/agent-runtime/store-migrations/v1-to-v2.d.ts +6 -0
  63. package/dist/agent-runtime/store-migrations/v1-to-v2.d.ts.map +1 -0
  64. package/dist/agent-runtime/store.d.ts +45 -0
  65. package/dist/agent-runtime/store.d.ts.map +1 -1
  66. package/dist/agent-runtime/terminal-commit.d.ts +1 -1
  67. package/dist/agent-runtime-browser.js +5 -3
  68. package/dist/agent-runtime-coding-tools.js +144 -15
  69. package/dist/agent-runtime-harness.js +12 -10
  70. package/dist/agent-runtime-sqlite-bun.d.ts +1 -1
  71. package/dist/agent-runtime-sqlite-bun.d.ts.map +1 -1
  72. package/dist/agent-runtime-sqlite-bun.js +4 -3
  73. package/dist/agent-runtime-sqlite-node.d.ts +1 -1
  74. package/dist/agent-runtime-sqlite-node.d.ts.map +1 -1
  75. package/dist/agent-runtime-sqlite-node.js +4 -3
  76. package/dist/agent-runtime-testing.d.ts +3 -0
  77. package/dist/agent-runtime-testing.d.ts.map +1 -0
  78. package/dist/agent-runtime-testing.js +156 -0
  79. package/dist/agent-runtime.d.ts +16 -2
  80. package/dist/agent-runtime.d.ts.map +1 -1
  81. package/dist/agent-runtime.js +1591 -154
  82. package/dist/application.js +14 -14
  83. package/dist/cli.js +6 -6
  84. package/dist/{index-fwbkp2jn.js → index-0vfdh685.js} +2 -2
  85. package/dist/{index-5z8tezpx.js → index-0ydchz76.js} +3 -3
  86. package/dist/{index-3ds42w1w.js → index-1szetq6f.js} +33 -4
  87. package/dist/{index-2jg7b11j.js → index-33xckd7h.js} +879 -422
  88. package/dist/{index-27487ay5.js → index-9hw9eq48.js} +4 -4
  89. package/dist/{index-66nxrgy0.js → index-b7qwhbzq.js} +428 -46
  90. package/dist/index-cnyk6te3.js +77 -0
  91. package/dist/index-gskm1k5a.js +50 -0
  92. package/dist/{index-fq492hg0.js → index-hber83mk.js} +254 -157
  93. package/dist/{index-4hk633vz.js → index-hkm6wysp.js} +9 -2
  94. package/dist/{index-dx9xehwt.js → index-kc6h6hg0.js} +1 -1
  95. package/dist/{index-x15ss2dx.js → index-p1b1y93x.js} +3 -0
  96. package/dist/{index-mgtxfe6b.js → index-r159gjwy.js} +8 -1
  97. package/dist/{index-s4ckmrac.js → index-rcgsnrr6.js} +3 -3
  98. package/dist/index-vfgb58nf.js +252 -0
  99. package/dist/{index-dggwnnjv.js → index-wn9cb82y.js} +1 -1
  100. package/dist/{index-ff0kcqvp.js → index-z2452tsw.js} +3 -3
  101. package/dist/testing/agent-store-conformance.d.ts.map +1 -1
  102. package/dist/testing.js +54 -80
  103. package/dist/tool-invoker.js +4 -4
  104. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  105. package/dist/tools/manifest.d.ts +16 -0
  106. package/dist/tools/manifest.d.ts.map +1 -1
  107. package/dist/tools.d.ts +1 -1
  108. package/dist/tools.d.ts.map +1 -1
  109. package/dist/tools.js +10 -8
  110. package/llms-full.txt +321 -13
  111. package/package.json +6 -1
@@ -3,19 +3,19 @@ import {
3
3
  } from "./index-sbdmyz75.js";
4
4
  import {
5
5
  collectToolSurface
6
- } from "./index-s4ckmrac.js";
6
+ } from "./index-rcgsnrr6.js";
7
7
  import {
8
8
  createToolRunner,
9
9
  formatToolError
10
- } from "./index-fwbkp2jn.js";
10
+ } from "./index-0vfdh685.js";
11
11
  import {
12
12
  toolResultFromError
13
- } from "./index-dggwnnjv.js";
13
+ } from "./index-wn9cb82y.js";
14
14
  import {
15
15
  assertUniqueToolName,
16
16
  buildToolPresentationSchema,
17
17
  objectShapeKeys
18
- } from "./index-mgtxfe6b.js";
18
+ } from "./index-r159gjwy.js";
19
19
  import {
20
20
  jsonSchemaFields
21
21
  } from "./index-cby4ar3v.js";
@@ -2,23 +2,37 @@ import {
2
2
  AgentAdmissionReceiptSchema,
3
3
  AgentConversationMessagePageSchema,
4
4
  AgentConversationPageSchema,
5
+ AgentConversationPurgedError,
5
6
  AgentHistoryMutationSchema,
6
- AgentRecoverableDescriptorSchema,
7
- AgentRecoverablePageSchema,
8
7
  AgentRuntimeHeadSchema,
9
8
  AgentStoredRunSchema,
10
9
  createAgentRuntimeStore
11
- } from "./index-fq492hg0.js";
10
+ } from "./index-hber83mk.js";
11
+ import {
12
+ AgentRecoverableDescriptorSchema,
13
+ AgentRecoverablePageSchema,
14
+ AgentStoreEventEnvelopeSchema,
15
+ AgentStoreEventPageSchema,
16
+ AppendAgentStoreEventSchema,
17
+ agentStoreEventDraft,
18
+ canonicalAgentJson
19
+ } from "./index-vfgb58nf.js";
12
20
  import {
13
21
  AgentMessageSchema,
14
22
  AgentRunSchema
15
- } from "./index-x15ss2dx.js";
23
+ } from "./index-p1b1y93x.js";
16
24
 
17
25
  // src/agent-runtime/sqlite.ts
18
- import { z } from "zod";
26
+ import { AsyncLocalStorage } from "node:async_hooks";
27
+ import { createHash } from "node:crypto";
28
+ import { z as z2 } from "zod";
19
29
 
20
30
  // src/agent-runtime/sqlite-purge.ts
21
31
  var OWNED_TABLES = [
32
+ "stitchkit_agent_runtime_spills",
33
+ "stitchkit_agent_runtime_schedules",
34
+ "stitchkit_agent_runtime_projections",
35
+ "stitchkit_agent_runtime_events",
22
36
  "stitchkit_agent_runtime_messages",
23
37
  "stitchkit_agent_runtime_admissions",
24
38
  "stitchkit_agent_runtime_runs",
@@ -57,15 +71,21 @@ function sqliteConversationPurge(database) {
57
71
  for (const table2 of OWNED_TABLES) {
58
72
  transaction.prepare(`DELETE FROM ${table2} WHERE conversation_id = ?`).run(conversationId);
59
73
  }
74
+ transaction.prepare("DELETE FROM stitchkit_agent_runtime_children WHERE parent_conversation_id = ? OR child_conversation_id = ?").run(conversationId, conversationId);
60
75
  }
61
76
  };
62
77
  }
63
78
 
64
- // src/agent-runtime/sqlite.ts
65
- var HeadRowSchema = z.object({ version: z.number().int().nonnegative() });
66
- var RunRowSchema = z.object({
79
+ // src/agent-runtime/store-migrations/v1-to-v2.ts
80
+ import { randomUUID } from "node:crypto";
81
+ import { z } from "zod";
82
+ var ConversationRowSchema = z.object({
83
+ conversation_id: z.string().min(1),
84
+ version: z.int().nonnegative()
85
+ });
86
+ var PayloadRowSchema = z.object({
67
87
  payload: z.string(),
68
- terminal_assistant_payload: z.string().nullable()
88
+ terminal_assistant_payload: z.string().nullable().optional()
69
89
  });
70
90
  var AdmissionRowSchema = z.object({
71
91
  conversation_id: z.string(),
@@ -74,32 +94,233 @@ var AdmissionRowSchema = z.object({
74
94
  run_id: z.string(),
75
95
  assistant_message_id: z.string()
76
96
  });
77
- var MessageRowSchema = z.object({ payload: z.string() });
78
- var PositionedMessageRowSchema = z.object({ position: z.number().int().nonnegative() });
79
- var RecoverableRowSchema = z.object({
80
- conversation_id: z.string(),
81
- run_id: z.string(),
82
- payload: z.string()
97
+ function parseJson(value) {
98
+ return JSON.parse(value);
99
+ }
100
+ function createDurableTables(database) {
101
+ database.exec(`
102
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_events (
103
+ row_id INTEGER PRIMARY KEY AUTOINCREMENT,
104
+ conversation_id TEXT NOT NULL,
105
+ seq INTEGER NOT NULL CHECK (seq > 0),
106
+ event_id TEXT NOT NULL UNIQUE,
107
+ schema_version INTEGER NOT NULL CHECK (schema_version > 0),
108
+ kind TEXT NOT NULL,
109
+ occurred_at TEXT NOT NULL,
110
+ ignorable INTEGER NOT NULL DEFAULT 0 CHECK (ignorable IN (0, 1)),
111
+ payload TEXT NOT NULL,
112
+ UNIQUE (conversation_id, seq)
113
+ );
114
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_events_time
115
+ ON stitchkit_agent_runtime_events (conversation_id, occurred_at, seq);
116
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_projections (
117
+ conversation_id TEXT NOT NULL,
118
+ name TEXT NOT NULL,
119
+ version INTEGER NOT NULL CHECK (version > 0),
120
+ upto_seq INTEGER NOT NULL CHECK (upto_seq >= 0),
121
+ payload TEXT NOT NULL,
122
+ updated_at TEXT NOT NULL,
123
+ PRIMARY KEY (conversation_id, name)
124
+ );
125
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_projection_updates
126
+ ON stitchkit_agent_runtime_projections (name, updated_at, conversation_id);
127
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_spills (
128
+ reference_id TEXT PRIMARY KEY,
129
+ conversation_id TEXT NOT NULL,
130
+ run_id TEXT,
131
+ tool_call_id TEXT,
132
+ media_type TEXT NOT NULL,
133
+ bytes INTEGER NOT NULL CHECK (bytes >= 0),
134
+ sha256 TEXT NOT NULL,
135
+ created_at TEXT NOT NULL,
136
+ expires_at TEXT,
137
+ authorization_payload TEXT,
138
+ payload BLOB NOT NULL
139
+ );
140
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_spills_owner
141
+ ON stitchkit_agent_runtime_spills (conversation_id, created_at);
142
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_schedules (
143
+ id TEXT PRIMARY KEY,
144
+ conversation_id TEXT NOT NULL,
145
+ kind TEXT NOT NULL,
146
+ next_at TEXT NOT NULL,
147
+ interval_ms INTEGER,
148
+ time_zone TEXT,
149
+ input_payload TEXT NOT NULL,
150
+ state TEXT NOT NULL,
151
+ occurrence INTEGER NOT NULL DEFAULT 0 CHECK (occurrence >= 0),
152
+ claim_owner TEXT,
153
+ claim_until TEXT,
154
+ created_at TEXT NOT NULL,
155
+ updated_at TEXT NOT NULL
156
+ );
157
+ CREATE INDEX IF NOT EXISTS stitchkit_agent_runtime_schedules_due
158
+ ON stitchkit_agent_runtime_schedules (state, next_at);
159
+ CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_children (
160
+ parent_conversation_id TEXT NOT NULL,
161
+ child_conversation_id TEXT NOT NULL UNIQUE,
162
+ seed_upto_seq INTEGER,
163
+ state TEXT NOT NULL,
164
+ budget_payload TEXT NOT NULL,
165
+ usage_payload TEXT NOT NULL,
166
+ result_reference TEXT,
167
+ created_at TEXT NOT NULL,
168
+ updated_at TEXT NOT NULL,
169
+ PRIMARY KEY (parent_conversation_id, child_conversation_id)
170
+ );
171
+ `);
172
+ try {
173
+ database.exec(`
174
+ CREATE VIRTUAL TABLE IF NOT EXISTS stitchkit_agent_runtime_events_fts
175
+ USING fts5(
176
+ conversation_id UNINDEXED,
177
+ event_seq UNINDEXED,
178
+ occurred_at UNINDEXED,
179
+ body,
180
+ tokenize = 'unicode61 remove_diacritics 2'
181
+ );
182
+ CREATE TRIGGER IF NOT EXISTS stitchkit_agent_runtime_events_fts_insert
183
+ AFTER INSERT ON stitchkit_agent_runtime_events BEGIN
184
+ INSERT INTO stitchkit_agent_runtime_events_fts(
185
+ rowid, conversation_id, event_seq, occurred_at, body
186
+ ) VALUES (new.row_id, new.conversation_id, new.seq, new.occurred_at, new.payload);
187
+ END;
188
+ CREATE TRIGGER IF NOT EXISTS stitchkit_agent_runtime_events_fts_delete
189
+ AFTER DELETE ON stitchkit_agent_runtime_events BEGIN
190
+ DELETE FROM stitchkit_agent_runtime_events_fts WHERE rowid = old.row_id;
191
+ END;
192
+ `);
193
+ } catch (error) {
194
+ throw new Error("SQLite agent-runtime requires FTS5 support", { cause: error });
195
+ }
196
+ }
197
+ function writeBaselines(database, migratedAt) {
198
+ const conversations = database.prepare("SELECT conversation_id, version FROM stitchkit_agent_runtime_heads ORDER BY conversation_id").all().map((row) => ConversationRowSchema.parse(row));
199
+ const insert = database.prepare(`
200
+ INSERT INTO stitchkit_agent_runtime_events (
201
+ conversation_id, seq, event_id, schema_version, kind, occurred_at, ignorable, payload
202
+ ) VALUES (?, 1, ?, 1, 'runtime/baseline', ?, 0, ?)
203
+ `);
204
+ for (const conversation of conversations) {
205
+ const messages = database.prepare("SELECT payload FROM stitchkit_agent_runtime_messages WHERE conversation_id = ? AND active = 1 ORDER BY position").all(conversation.conversation_id).map((row) => AgentMessageSchema.parse(parseJson(PayloadRowSchema.parse(row).payload)));
206
+ 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
+ const row = PayloadRowSchema.parse(value);
208
+ return {
209
+ schemaVersion: 1,
210
+ run: AgentRunSchema.parse(parseJson(row.payload)),
211
+ ...row.terminal_assistant_payload ? {
212
+ terminalAssistant: AgentMessageSchema.parse(parseJson(row.terminal_assistant_payload))
213
+ } : {}
214
+ };
215
+ });
216
+ 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) => {
217
+ const row = AdmissionRowSchema.parse(value);
218
+ return {
219
+ schemaVersion: 1,
220
+ conversationId: row.conversation_id,
221
+ idempotencyKey: row.idempotency_key,
222
+ input: AgentMessageSchema.parse(parseJson(row.input_payload)),
223
+ runId: row.run_id,
224
+ assistantMessageId: row.assistant_message_id
225
+ };
226
+ });
227
+ const asOf = messages.at(-1)?.createdAt ?? runs.at(-1)?.run.createdAt;
228
+ insert.run(conversation.conversation_id, randomUUID(), migratedAt, canonicalAgentJson({
229
+ migratedAt,
230
+ ...asOf !== undefined && { asOf },
231
+ head: {
232
+ schemaVersion: 1,
233
+ conversationId: conversation.conversation_id,
234
+ version: conversation.version
235
+ },
236
+ messages,
237
+ runs,
238
+ admissions
239
+ }));
240
+ }
241
+ }
242
+ function migrateAgentRuntimeSqliteV1ToV2(database, migratedAt = new Date().toISOString()) {
243
+ createDurableTables(database);
244
+ writeBaselines(database, migratedAt);
245
+ database.prepare("UPDATE stitchkit_agent_runtime_meta SET value = '2' WHERE key = 'schema_version'").run();
246
+ }
247
+ function createAgentRuntimeSqliteV2Tables(database) {
248
+ createDurableTables(database);
249
+ }
250
+
251
+ // src/agent-runtime/sqlite.ts
252
+ var HeadRowSchema = z2.object({ version: z2.number().int().nonnegative() });
253
+ var RunRowSchema = z2.object({
254
+ payload: z2.string(),
255
+ terminal_assistant_payload: z2.string().nullable()
83
256
  });
84
- var MetaRowSchema = z.object({ value: z.string() });
85
- var TableRowSchema = z.object({ name: z.string() });
86
- var ConversationHeadRowSchema = z.object({
87
- conversation_id: z.string(),
88
- version: z.number().int().nonnegative()
257
+ var AdmissionRowSchema2 = z2.object({
258
+ conversation_id: z2.string(),
259
+ idempotency_key: z2.string(),
260
+ input_payload: z2.string(),
261
+ run_id: z2.string(),
262
+ assistant_message_id: z2.string()
263
+ });
264
+ var MessageRowSchema = z2.object({ payload: z2.string() });
265
+ var PositionedMessageRowSchema = z2.object({ position: z2.number().int().nonnegative() });
266
+ var RecoverableRowSchema = z2.object({
267
+ conversation_id: z2.string(),
268
+ run_id: z2.string(),
269
+ payload: z2.string()
270
+ });
271
+ var MetaRowSchema = z2.object({ value: z2.string() });
272
+ var TableRowSchema = z2.object({ name: z2.string() });
273
+ var ConversationHeadRowSchema = z2.object({
274
+ conversation_id: z2.string(),
275
+ version: z2.number().int().nonnegative()
89
276
  });
90
- var CountRowSchema = z.object({ count: z.number().int().nonnegative() });
91
- var MessagePageRowSchema = z.object({
92
- position: z.number().int().nonnegative(),
93
- payload: z.string()
277
+ var CountRowSchema = z2.object({ count: z2.number().int().nonnegative() });
278
+ var MessagePageRowSchema = z2.object({
279
+ position: z2.number().int().nonnegative(),
280
+ payload: z2.string()
94
281
  });
95
- var SCHEMA_VERSION = 1;
282
+ var EventRowSchema = z2.object({
283
+ event_id: z2.string(),
284
+ conversation_id: z2.string(),
285
+ seq: z2.int().positive(),
286
+ schema_version: z2.int().positive(),
287
+ kind: z2.string(),
288
+ occurred_at: z2.string(),
289
+ ignorable: z2.union([z2.literal(0), z2.literal(1)]),
290
+ payload: z2.string()
291
+ });
292
+ var ArchiveProjectionRowSchema = z2.object({
293
+ name: z2.string(),
294
+ version: z2.int().positive(),
295
+ upto_seq: z2.int().nonnegative(),
296
+ payload: z2.string(),
297
+ updated_at: z2.string()
298
+ });
299
+ var ArchiveSpillRowSchema = z2.object({
300
+ reference_id: z2.string(),
301
+ run_id: z2.string().nullable(),
302
+ tool_call_id: z2.string().nullable(),
303
+ media_type: z2.string(),
304
+ bytes: z2.int().nonnegative(),
305
+ sha256: z2.string(),
306
+ created_at: z2.string(),
307
+ expires_at: z2.string().nullable(),
308
+ authorization_payload: z2.string().nullable(),
309
+ payload: z2.instanceof(Uint8Array)
310
+ });
311
+ var SCHEMA_VERSION = 2;
96
312
  var TABLES = [
97
313
  "stitchkit_agent_runtime_heads",
98
314
  "stitchkit_agent_runtime_runs",
99
315
  "stitchkit_agent_runtime_admissions",
100
- "stitchkit_agent_runtime_messages"
316
+ "stitchkit_agent_runtime_messages",
317
+ "stitchkit_agent_runtime_events",
318
+ "stitchkit_agent_runtime_projections",
319
+ "stitchkit_agent_runtime_spills",
320
+ "stitchkit_agent_runtime_schedules",
321
+ "stitchkit_agent_runtime_children"
101
322
  ];
102
- function parseJson(value) {
323
+ function parseJson2(value) {
103
324
  return JSON.parse(value);
104
325
  }
105
326
  function encodeJson(value) {
@@ -115,42 +336,55 @@ function parseRunRow(value) {
115
336
  const row = RunRowSchema.parse(value);
116
337
  return AgentStoredRunSchema.parse({
117
338
  schemaVersion: 1,
118
- run: AgentRunSchema.parse(parseJson(row.payload)),
339
+ run: AgentRunSchema.parse(parseJson2(row.payload)),
119
340
  ...row.terminal_assistant_payload === null ? {} : {
120
- terminalAssistant: AgentMessageSchema.parse(parseJson(row.terminal_assistant_payload))
341
+ terminalAssistant: AgentMessageSchema.parse(parseJson2(row.terminal_assistant_payload))
121
342
  }
122
343
  });
123
344
  }
345
+ function parseEventRow(value) {
346
+ const row = EventRowSchema.parse(value);
347
+ return AgentStoreEventEnvelopeSchema.parse({
348
+ schemaVersion: row.schema_version,
349
+ eventId: row.event_id,
350
+ conversationId: row.conversation_id,
351
+ seq: row.seq,
352
+ kind: row.kind,
353
+ occurredAt: row.occurred_at,
354
+ payload: parseJson2(row.payload),
355
+ ...row.ignorable === 1 && { ignorable: true }
356
+ });
357
+ }
124
358
  function recoveryCursor(conversationId, runId) {
125
359
  return encodeJson([conversationId, runId]);
126
360
  }
127
361
  function parseRecoveryCursor(cursor) {
128
- return z.tuple([z.string().min(1), z.string().min(1)]).parse(parseJson(cursor));
362
+ return z2.tuple([z2.string().min(1), z2.string().min(1)]).parse(parseJson2(cursor));
129
363
  }
130
364
  function conversationCursor(conversationId) {
131
365
  return encodeJson([conversationId]);
132
366
  }
133
367
  function parseConversationCursor(cursor) {
134
- return z.tuple([z.string().min(1)]).parse(parseJson(cursor))[0];
368
+ return z2.tuple([z2.string().min(1)]).parse(parseJson2(cursor))[0];
135
369
  }
136
370
  function messageCursor(position) {
137
371
  return encodeJson([position]);
138
372
  }
139
373
  function parseMessageCursor(cursor) {
140
- return z.tuple([z.int().nonnegative()]).parse(parseJson(cursor))[0];
374
+ return z2.tuple([z2.int().nonnegative()]).parse(parseJson2(cursor))[0];
141
375
  }
142
376
  function messagePreview(message) {
143
377
  const text = message.parts.find((part) => part.type === "text");
144
378
  return text?.type === "text" ? text.text.slice(0, 160) : message.role;
145
379
  }
146
380
  function initializeAgentRuntimeSqlite(database) {
147
- 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);
148
- const hasMeta = existing.includes("stitchkit_agent_runtime_meta");
149
- if (!hasMeta && existing.length > 0) {
150
- throw new Error("Refusing an unversioned partial Stitchkit agent-runtime SQLite schema");
151
- }
152
381
  database.exec("BEGIN IMMEDIATE");
153
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
+ }
154
388
  database.exec(`
155
389
  CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_meta (
156
390
  key TEXT PRIMARY KEY,
@@ -160,6 +394,12 @@ function initializeAgentRuntimeSqlite(database) {
160
394
  const versionRow = database.prepare("SELECT value FROM stitchkit_agent_runtime_meta WHERE key = 'schema_version'").get();
161
395
  if (!missing(versionRow)) {
162
396
  const version = Number(MetaRowSchema.parse(versionRow).value);
397
+ if (version === 1) {
398
+ migrateAgentRuntimeSqliteV1ToV2(database);
399
+ initializeSqliteConversationPurge(database);
400
+ database.exec("COMMIT");
401
+ return;
402
+ }
163
403
  if (version !== SCHEMA_VERSION) {
164
404
  throw new Error(`Unsupported Stitchkit agent-runtime SQLite schema version ${version}; expected ${SCHEMA_VERSION}`);
165
405
  }
@@ -210,8 +450,9 @@ function initializeAgentRuntimeSqlite(database) {
210
450
  payload TEXT NOT NULL,
211
451
  PRIMARY KEY (conversation_id, id)
212
452
  );
213
- INSERT INTO stitchkit_agent_runtime_meta (key, value) VALUES ('schema_version', '1');
214
453
  `);
454
+ createAgentRuntimeSqliteV2Tables(database);
455
+ database.prepare("INSERT INTO stitchkit_agent_runtime_meta (key, value) VALUES ('schema_version', '2')").run();
215
456
  initializeSqliteConversationPurge(database);
216
457
  database.exec("COMMIT");
217
458
  } catch (error) {
@@ -232,10 +473,14 @@ function createSqliteAgentRuntimeStore(config) {
232
473
  let closing = false;
233
474
  let closed = false;
234
475
  let tail = Promise.resolve();
476
+ const insideScope = new AsyncLocalStorage;
235
477
  const serial = (work) => {
236
478
  if (closing || closed) {
237
479
  return Promise.reject(new Error("SQLite agent-runtime store is closing"));
238
480
  }
481
+ if (insideScope.getStore()) {
482
+ return Promise.reject(new Error("SQLite agent-runtime store called from inside its own transaction scope; use scope.database and scope.appendEvent"));
483
+ }
239
484
  const result = tail.then(work, work);
240
485
  tail = result.then(() => {
241
486
  return;
@@ -344,12 +589,12 @@ function createSqliteAgentRuntimeStore(config) {
344
589
  `).get(input.conversationId, input.idempotencyKey);
345
590
  if (missing(value))
346
591
  return;
347
- const row = AdmissionRowSchema.parse(value);
592
+ const row = AdmissionRowSchema2.parse(value);
348
593
  return AgentAdmissionReceiptSchema.parse({
349
594
  schemaVersion: 1,
350
595
  conversationId: row.conversation_id,
351
596
  idempotencyKey: row.idempotency_key,
352
- input: AgentMessageSchema.parse(parseJson(row.input_payload)),
597
+ input: AgentMessageSchema.parse(parseJson2(row.input_payload)),
353
598
  runId: row.run_id,
354
599
  assistantMessageId: row.assistant_message_id
355
600
  });
@@ -362,12 +607,12 @@ function createSqliteAgentRuntimeStore(config) {
362
607
  `).get(input.conversationId, input.inputMessageId);
363
608
  if (missing(value))
364
609
  return;
365
- const row = AdmissionRowSchema.parse(value);
610
+ const row = AdmissionRowSchema2.parse(value);
366
611
  return AgentAdmissionReceiptSchema.parse({
367
612
  schemaVersion: 1,
368
613
  conversationId: row.conversation_id,
369
614
  idempotencyKey: row.idempotency_key,
370
- input: AgentMessageSchema.parse(parseJson(row.input_payload)),
615
+ input: AgentMessageSchema.parse(parseJson2(row.input_payload)),
371
616
  runId: row.run_id,
372
617
  assistantMessageId: row.assistant_message_id
373
618
  });
@@ -387,7 +632,7 @@ function createSqliteAgentRuntimeStore(config) {
387
632
  return transaction.prepare(`
388
633
  SELECT payload FROM stitchkit_agent_runtime_messages
389
634
  WHERE conversation_id = ? AND active = 1 ORDER BY position ASC
390
- `).all(conversationId).map((value) => AgentMessageSchema.parse(parseJson(MessageRowSchema.parse(value).payload)));
635
+ `).all(conversationId).map((value) => AgentMessageSchema.parse(parseJson2(MessageRowSchema.parse(value).payload)));
391
636
  },
392
637
  async apply(transaction, rawMutation) {
393
638
  const mutation = AgentHistoryMutationSchema.parse(rawMutation);
@@ -438,6 +683,132 @@ function createSqliteAgentRuntimeStore(config) {
438
683
  `).run(message.conversationId, message.id, position, encodeJson(message));
439
684
  }
440
685
  },
686
+ events: {
687
+ async append(transaction, rawEvent) {
688
+ const event = rawEvent;
689
+ const last = transaction.prepare("SELECT COALESCE(MAX(seq), 0) AS count FROM stitchkit_agent_runtime_events WHERE conversation_id = ?").get(event.conversationId);
690
+ const seq = CountRowSchema.parse(last).count + 1;
691
+ transaction.prepare(`
692
+ INSERT INTO stitchkit_agent_runtime_events (
693
+ conversation_id, seq, event_id, schema_version, kind, occurred_at, ignorable, payload
694
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
695
+ `).run(event.conversationId, seq, event.eventId, event.schemaVersion, event.kind, event.occurredAt, event.ignorable ? 1 : 0, encodeJson(event.payload));
696
+ return AgentStoreEventEnvelopeSchema.parse({ ...event, seq });
697
+ },
698
+ async list(transaction, input) {
699
+ const clauses = ["conversation_id = ?"];
700
+ const values = [input.conversationId];
701
+ if (input.fromSeq !== undefined) {
702
+ clauses.push("seq >= ?");
703
+ values.push(input.fromSeq);
704
+ }
705
+ if (input.toSeq !== undefined) {
706
+ clauses.push("seq <= ?");
707
+ values.push(input.toSeq);
708
+ }
709
+ const rows = transaction.prepare(`
710
+ SELECT event_id, conversation_id, seq, schema_version, kind, occurred_at,
711
+ ignorable, payload
712
+ FROM stitchkit_agent_runtime_events
713
+ WHERE ${clauses.join(" AND ")}
714
+ ORDER BY seq ASC LIMIT ?
715
+ `).all(...values, input.limit + 1).map(parseEventRow);
716
+ const hasMore = rows.length > input.limit;
717
+ const items = rows.slice(0, input.limit);
718
+ const lastEvent = items.at(-1);
719
+ return AgentStoreEventPageSchema.parse({
720
+ items,
721
+ ...hasMore && lastEvent ? { nextSeq: lastEvent.seq + 1 } : {}
722
+ });
723
+ }
724
+ },
725
+ archive: {
726
+ async export(transaction, conversationId) {
727
+ const projections = transaction.prepare(`
728
+ SELECT name, version, upto_seq, payload, updated_at
729
+ FROM stitchkit_agent_runtime_projections
730
+ WHERE conversation_id = ? ORDER BY name
731
+ `).all(conversationId).map((raw) => {
732
+ const row = ArchiveProjectionRowSchema.parse(raw);
733
+ return {
734
+ name: row.name,
735
+ version: row.version,
736
+ uptoSeq: row.upto_seq,
737
+ value: z2.json().parse(parseJson2(row.payload)),
738
+ updatedAt: row.updated_at
739
+ };
740
+ });
741
+ const spills = transaction.prepare(`
742
+ SELECT reference_id, run_id, tool_call_id, media_type, bytes, sha256,
743
+ created_at, expires_at, authorization_payload, payload
744
+ FROM stitchkit_agent_runtime_spills
745
+ WHERE conversation_id = ? ORDER BY created_at, reference_id
746
+ `).all(conversationId).map((raw) => {
747
+ const row = ArchiveSpillRowSchema.parse(raw);
748
+ return {
749
+ reference: row.reference_id,
750
+ ...row.run_id && { runId: row.run_id },
751
+ ...row.tool_call_id && { toolCallId: row.tool_call_id },
752
+ mediaType: row.media_type,
753
+ bytes: row.bytes,
754
+ sha256: row.sha256,
755
+ createdAt: row.created_at,
756
+ ...row.expires_at && { expiresAt: row.expires_at },
757
+ ...row.authorization_payload && {
758
+ authorization: z2.json().parse(parseJson2(row.authorization_payload))
759
+ },
760
+ base64: Buffer.from(row.payload).toString("base64")
761
+ };
762
+ });
763
+ return { projections, spills };
764
+ },
765
+ async import(transaction, archive) {
766
+ for (const raw of archive.projections) {
767
+ if (typeof raw === "object" && raw !== null && !Array.isArray(raw) && raw.archiveType === "runtime-snapshot") {
768
+ continue;
769
+ }
770
+ const projection = z2.object({
771
+ name: z2.string(),
772
+ version: z2.int().positive(),
773
+ uptoSeq: z2.int().nonnegative(),
774
+ value: z2.json(),
775
+ updatedAt: z2.string()
776
+ }).strict().parse(raw);
777
+ transaction.prepare(`
778
+ INSERT INTO stitchkit_agent_runtime_projections
779
+ (conversation_id, name, version, upto_seq, payload, updated_at)
780
+ VALUES (?, ?, ?, ?, ?, ?)
781
+ `).run(archive.conversationId, projection.name, projection.version, projection.uptoSeq, encodeJson(projection.value), projection.updatedAt);
782
+ }
783
+ for (const raw of archive.spills) {
784
+ const spill = z2.object({
785
+ reference: z2.string(),
786
+ runId: z2.string().optional(),
787
+ toolCallId: z2.string().optional(),
788
+ mediaType: z2.string(),
789
+ bytes: z2.int().nonnegative(),
790
+ sha256: z2.string(),
791
+ createdAt: z2.string(),
792
+ expiresAt: z2.string().optional(),
793
+ authorization: z2.json().optional(),
794
+ base64: z2.string()
795
+ }).strict().parse(raw);
796
+ const payload = Buffer.from(spill.base64, "base64");
797
+ if (payload.byteLength !== spill.bytes) {
798
+ throw new TypeError("Conversation archive spill byte count is inconsistent");
799
+ }
800
+ if (createHash("sha256").update(payload).digest("hex") !== spill.sha256) {
801
+ throw new TypeError("Conversation archive spill digest is inconsistent");
802
+ }
803
+ transaction.prepare(`
804
+ INSERT INTO stitchkit_agent_runtime_spills (
805
+ reference_id, conversation_id, run_id, tool_call_id, media_type,
806
+ bytes, sha256, created_at, expires_at, authorization_payload, payload
807
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
808
+ `).run(spill.reference, archive.conversationId, spill.runId ?? null, spill.toolCallId ?? null, spill.mediaType, spill.bytes, spill.sha256, spill.createdAt, spill.expiresAt ?? null, spill.authorization ? encodeJson(spill.authorization) : null, payload);
809
+ }
810
+ }
811
+ },
441
812
  scanRecoverable: (input) => runTransaction("read", async () => {
442
813
  const cursor = input.cursor ? parseRecoveryCursor(input.cursor) : undefined;
443
814
  const values = cursor ? [cursor[0], cursor[0], cursor[1], input.limit + 1] : [input.limit + 1];
@@ -451,7 +822,7 @@ function createSqliteAgentRuntimeStore(config) {
451
822
  const hasMore = rows.length > input.limit;
452
823
  const pageRows = rows.slice(0, input.limit);
453
824
  const items = pageRows.map((row) => {
454
- const run = AgentRunSchema.parse(parseJson(row.payload));
825
+ const run = AgentRunSchema.parse(parseJson2(row.payload));
455
826
  return AgentRecoverableDescriptorSchema.parse({
456
827
  conversationId: row.conversation_id,
457
828
  run
@@ -466,6 +837,17 @@ function createSqliteAgentRuntimeStore(config) {
466
837
  };
467
838
  return {
468
839
  store: createAgentRuntimeStore(driver),
840
+ database,
841
+ transaction: (work) => runTransaction("write", (transaction) => insideScope.run(true, () => work({
842
+ database: transaction,
843
+ appendEvent: async (input) => {
844
+ const parsed = AppendAgentStoreEventSchema.parse(input);
845
+ if (await driver.conversations?.isPurged(transaction, parsed.conversationId)) {
846
+ throw new AgentConversationPurgedError;
847
+ }
848
+ return driver.events.append(transaction, agentStoreEventDraft(parsed));
849
+ }
850
+ }))),
469
851
  conversations: {
470
852
  list: (input) => runTransaction("read", async () => {
471
853
  if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 1000) {
@@ -498,7 +880,7 @@ function createSqliteAgentRuntimeStore(config) {
498
880
  if (missing(latestRaw)) {
499
881
  throw new Error("Agent conversation head has no active history");
500
882
  }
501
- const latest = AgentMessageSchema.parse(parseJson(MessagePageRowSchema.parse(latestRaw).payload));
883
+ const latest = AgentMessageSchema.parse(parseJson2(MessagePageRowSchema.parse(latestRaw).payload));
502
884
  const active = CountRowSchema.parse(database.prepare(`
503
885
  SELECT count(*) AS count FROM stitchkit_agent_runtime_runs
504
886
  WHERE conversation_id = ?
@@ -535,7 +917,7 @@ function createSqliteAgentRuntimeStore(config) {
535
917
  const ordered = before ? [...pageRows].reverse() : pageRows;
536
918
  const boundary = pageRows.at(-1);
537
919
  return AgentConversationMessagePageSchema.parse({
538
- items: ordered.map((row) => AgentMessageSchema.parse(parseJson(row.payload))),
920
+ items: ordered.map((row) => AgentMessageSchema.parse(parseJson2(row.payload))),
539
921
  ...hasMore && boundary ? { nextCursor: messageCursor(boundary.position) } : {}
540
922
  });
541
923
  })