stitchkit 0.85.2 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CHANGELOG.md +243 -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/conversations.d.ts +11 -0
  19. package/dist/agent-runtime/conversations.d.ts.map +1 -1
  20. package/dist/agent-runtime/event-schema.d.ts +34 -0
  21. package/dist/agent-runtime/event-schema.d.ts.map +1 -1
  22. package/dist/agent-runtime/event-search-tools.d.ts +53 -0
  23. package/dist/agent-runtime/event-search-tools.d.ts.map +1 -0
  24. package/dist/agent-runtime/event-search.d.ts +23 -0
  25. package/dist/agent-runtime/event-search.d.ts.map +1 -0
  26. package/dist/agent-runtime/fault-bench.d.ts +45 -0
  27. package/dist/agent-runtime/fault-bench.d.ts.map +1 -0
  28. package/dist/agent-runtime/observability.d.ts +6 -0
  29. package/dist/agent-runtime/observability.d.ts.map +1 -1
  30. package/dist/agent-runtime/projections.d.ts +69 -0
  31. package/dist/agent-runtime/projections.d.ts.map +1 -0
  32. package/dist/agent-runtime/provider-failure.d.ts +5 -1
  33. package/dist/agent-runtime/provider-failure.d.ts.map +1 -1
  34. package/dist/agent-runtime/provider-origin.d.ts +12 -0
  35. package/dist/agent-runtime/provider-origin.d.ts.map +1 -0
  36. package/dist/agent-runtime/retry-policy.d.ts +27 -0
  37. package/dist/agent-runtime/retry-policy.d.ts.map +1 -0
  38. package/dist/agent-runtime/run-execution.d.ts +0 -9
  39. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  40. package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
  41. package/dist/agent-runtime/runtime.d.ts +15 -0
  42. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  43. package/dist/agent-runtime/sandbox.d.ts +66 -0
  44. package/dist/agent-runtime/sandbox.d.ts.map +1 -0
  45. package/dist/agent-runtime/schedule-tools.d.ts +35 -0
  46. package/dist/agent-runtime/schedule-tools.d.ts.map +1 -0
  47. package/dist/agent-runtime/schedules.d.ts +63 -0
  48. package/dist/agent-runtime/schedules.d.ts.map +1 -0
  49. package/dist/agent-runtime/schemas.d.ts +9 -0
  50. package/dist/agent-runtime/schemas.d.ts.map +1 -1
  51. package/dist/agent-runtime/spill.d.ts +24 -0
  52. package/dist/agent-runtime/spill.d.ts.map +1 -0
  53. package/dist/agent-runtime/sqlite-purge.d.ts.map +1 -1
  54. package/dist/agent-runtime/sqlite.d.ts +26 -0
  55. package/dist/agent-runtime/sqlite.d.ts.map +1 -1
  56. package/dist/agent-runtime/state-slots.d.ts +48 -0
  57. package/dist/agent-runtime/state-slots.d.ts.map +1 -0
  58. package/dist/agent-runtime/state-tools.d.ts +58 -0
  59. package/dist/agent-runtime/state-tools.d.ts.map +1 -0
  60. package/dist/agent-runtime/store-driver.d.ts +13 -0
  61. package/dist/agent-runtime/store-driver.d.ts.map +1 -1
  62. package/dist/agent-runtime/store-events.d.ts +829 -0
  63. package/dist/agent-runtime/store-events.d.ts.map +1 -0
  64. package/dist/agent-runtime/store-migrations/v1-to-v2.d.ts +6 -0
  65. package/dist/agent-runtime/store-migrations/v1-to-v2.d.ts.map +1 -0
  66. package/dist/agent-runtime/store.d.ts +45 -0
  67. package/dist/agent-runtime/store.d.ts.map +1 -1
  68. package/dist/agent-runtime/terminal-commit.d.ts +1 -1
  69. package/dist/agent-runtime-browser.js +5 -3
  70. package/dist/agent-runtime-coding-tools.js +144 -15
  71. package/dist/agent-runtime-harness.js +12 -11
  72. package/dist/agent-runtime-sqlite-bun.d.ts +1 -1
  73. package/dist/agent-runtime-sqlite-bun.d.ts.map +1 -1
  74. package/dist/agent-runtime-sqlite-bun.js +5 -4
  75. package/dist/agent-runtime-sqlite-node.d.ts +1 -1
  76. package/dist/agent-runtime-sqlite-node.d.ts.map +1 -1
  77. package/dist/agent-runtime-sqlite-node.js +5 -4
  78. package/dist/agent-runtime-testing.d.ts +3 -0
  79. package/dist/agent-runtime-testing.d.ts.map +1 -0
  80. package/dist/agent-runtime-testing.js +156 -0
  81. package/dist/agent-runtime.d.ts +16 -2
  82. package/dist/agent-runtime.d.ts.map +1 -1
  83. package/dist/agent-runtime.js +1632 -156
  84. package/dist/application.js +14 -14
  85. package/dist/cli.js +6 -6
  86. package/dist/{index-fwbkp2jn.js → index-0vfdh685.js} +2 -2
  87. package/dist/{index-5z8tezpx.js → index-0ydchz76.js} +3 -3
  88. package/dist/{index-3ds42w1w.js → index-1szetq6f.js} +33 -4
  89. package/dist/{index-2jg7b11j.js → index-35aefxby.js} +879 -424
  90. package/dist/index-3yrqvza8.js +964 -0
  91. package/dist/{index-fq492hg0.js → index-5wezxcxx.js} +238 -161
  92. package/dist/index-9553432s.js +26 -0
  93. package/dist/{index-27487ay5.js → index-9hw9eq48.js} +4 -4
  94. package/dist/index-cnyk6te3.js +77 -0
  95. package/dist/index-gskm1k5a.js +50 -0
  96. package/dist/{index-4hk633vz.js → index-hkm6wysp.js} +9 -2
  97. package/dist/{index-dx9xehwt.js → index-kc6h6hg0.js} +1 -1
  98. package/dist/{index-x15ss2dx.js → index-p1b1y93x.js} +3 -0
  99. package/dist/{index-mgtxfe6b.js → index-r159gjwy.js} +8 -1
  100. package/dist/{index-s4ckmrac.js → index-rcgsnrr6.js} +3 -3
  101. package/dist/{index-dggwnnjv.js → index-wn9cb82y.js} +1 -1
  102. package/dist/index-z1m86vc8.js +334 -0
  103. package/dist/{index-ff0kcqvp.js → index-z2452tsw.js} +3 -3
  104. package/dist/internal/sqlite.d.ts +13 -0
  105. package/dist/internal/sqlite.d.ts.map +1 -1
  106. package/dist/testing/agent-store-conformance.d.ts.map +1 -1
  107. package/dist/testing.js +89 -80
  108. package/dist/tool-invoker.js +4 -4
  109. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  110. package/dist/tools/manifest.d.ts +16 -0
  111. package/dist/tools/manifest.d.ts.map +1 -1
  112. package/dist/tools.d.ts +1 -1
  113. package/dist/tools.d.ts.map +1 -1
  114. package/dist/tools.js +10 -8
  115. package/llms-full.txt +373 -16
  116. package/package.json +6 -1
  117. package/dist/index-66nxrgy0.js +0 -554
  118. package/dist/index-y2s6h5bf.js +0 -83
@@ -1,554 +0,0 @@
1
- import {
2
- AgentAdmissionReceiptSchema,
3
- AgentConversationMessagePageSchema,
4
- AgentConversationPageSchema,
5
- AgentHistoryMutationSchema,
6
- AgentRecoverableDescriptorSchema,
7
- AgentRecoverablePageSchema,
8
- AgentRuntimeHeadSchema,
9
- AgentStoredRunSchema,
10
- createAgentRuntimeStore
11
- } from "./index-fq492hg0.js";
12
- import {
13
- AgentMessageSchema,
14
- AgentRunSchema
15
- } from "./index-x15ss2dx.js";
16
-
17
- // src/agent-runtime/sqlite.ts
18
- import { z } from "zod";
19
-
20
- // src/agent-runtime/sqlite-purge.ts
21
- var OWNED_TABLES = [
22
- "stitchkit_agent_runtime_messages",
23
- "stitchkit_agent_runtime_admissions",
24
- "stitchkit_agent_runtime_runs",
25
- "stitchkit_agent_runtime_heads"
26
- ];
27
- function initializeSqliteConversationPurge(database) {
28
- database.exec(`
29
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_purged (
30
- conversation_id TEXT PRIMARY KEY
31
- );
32
- `);
33
- for (const table of OWNED_TABLES) {
34
- for (const operation of ["INSERT", "UPDATE"]) {
35
- database.exec(`
36
- CREATE TRIGGER IF NOT EXISTS ${table}_purge_${operation.toLowerCase()}
37
- BEFORE ${operation} ON ${table}
38
- WHEN EXISTS (
39
- SELECT 1 FROM stitchkit_agent_runtime_purged WHERE conversation_id = NEW.conversation_id
40
- )
41
- BEGIN SELECT RAISE(ABORT, 'Agent conversation has been purged'); END;
42
- `);
43
- }
44
- }
45
- }
46
- function sqliteConversationPurge(database) {
47
- const table = database.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'stitchkit_agent_runtime_purged'").get();
48
- if (table === null || table === undefined)
49
- return;
50
- return {
51
- async isPurged(transaction, conversationId) {
52
- const row = transaction.prepare("SELECT conversation_id FROM stitchkit_agent_runtime_purged WHERE conversation_id = ?").get(conversationId);
53
- return row !== null && row !== undefined;
54
- },
55
- async remove(transaction, conversationId) {
56
- transaction.prepare("INSERT INTO stitchkit_agent_runtime_purged (conversation_id) VALUES (?)").run(conversationId);
57
- for (const table2 of OWNED_TABLES) {
58
- transaction.prepare(`DELETE FROM ${table2} WHERE conversation_id = ?`).run(conversationId);
59
- }
60
- }
61
- };
62
- }
63
-
64
- // src/agent-runtime/sqlite.ts
65
- var HeadRowSchema = z.object({ version: z.number().int().nonnegative() });
66
- var RunRowSchema = z.object({
67
- payload: z.string(),
68
- terminal_assistant_payload: z.string().nullable()
69
- });
70
- var AdmissionRowSchema = z.object({
71
- conversation_id: z.string(),
72
- idempotency_key: z.string(),
73
- input_payload: z.string(),
74
- run_id: z.string(),
75
- assistant_message_id: z.string()
76
- });
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()
83
- });
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()
89
- });
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()
94
- });
95
- var SCHEMA_VERSION = 1;
96
- var TABLES = [
97
- "stitchkit_agent_runtime_heads",
98
- "stitchkit_agent_runtime_runs",
99
- "stitchkit_agent_runtime_admissions",
100
- "stitchkit_agent_runtime_messages"
101
- ];
102
- function parseJson(value) {
103
- return JSON.parse(value);
104
- }
105
- function encodeJson(value) {
106
- return JSON.stringify(value);
107
- }
108
- function missing(value) {
109
- return value === null || value === undefined;
110
- }
111
- function placeholders(count) {
112
- return Array.from({ length: count }, () => "?").join(", ");
113
- }
114
- function parseRunRow(value) {
115
- const row = RunRowSchema.parse(value);
116
- return AgentStoredRunSchema.parse({
117
- schemaVersion: 1,
118
- run: AgentRunSchema.parse(parseJson(row.payload)),
119
- ...row.terminal_assistant_payload === null ? {} : {
120
- terminalAssistant: AgentMessageSchema.parse(parseJson(row.terminal_assistant_payload))
121
- }
122
- });
123
- }
124
- function recoveryCursor(conversationId, runId) {
125
- return encodeJson([conversationId, runId]);
126
- }
127
- function parseRecoveryCursor(cursor) {
128
- return z.tuple([z.string().min(1), z.string().min(1)]).parse(parseJson(cursor));
129
- }
130
- function conversationCursor(conversationId) {
131
- return encodeJson([conversationId]);
132
- }
133
- function parseConversationCursor(cursor) {
134
- return z.tuple([z.string().min(1)]).parse(parseJson(cursor))[0];
135
- }
136
- function messageCursor(position) {
137
- return encodeJson([position]);
138
- }
139
- function parseMessageCursor(cursor) {
140
- return z.tuple([z.int().nonnegative()]).parse(parseJson(cursor))[0];
141
- }
142
- function messagePreview(message) {
143
- const text = message.parts.find((part) => part.type === "text");
144
- return text?.type === "text" ? text.text.slice(0, 160) : message.role;
145
- }
146
- 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
- database.exec("BEGIN IMMEDIATE");
153
- try {
154
- database.exec(`
155
- CREATE TABLE IF NOT EXISTS stitchkit_agent_runtime_meta (
156
- key TEXT PRIMARY KEY,
157
- value TEXT NOT NULL
158
- );
159
- `);
160
- const versionRow = database.prepare("SELECT value FROM stitchkit_agent_runtime_meta WHERE key = 'schema_version'").get();
161
- if (!missing(versionRow)) {
162
- const version = Number(MetaRowSchema.parse(versionRow).value);
163
- if (version !== SCHEMA_VERSION) {
164
- throw new Error(`Unsupported Stitchkit agent-runtime SQLite schema version ${version}; expected ${SCHEMA_VERSION}`);
165
- }
166
- const missingTables = TABLES.filter((table) => !existing.includes(table));
167
- if (missingTables.length > 0) {
168
- throw new Error(`Refusing a partial Stitchkit agent-runtime SQLite schema; missing ${missingTables.join(", ")}`);
169
- }
170
- initializeSqliteConversationPurge(database);
171
- database.exec("COMMIT");
172
- return;
173
- }
174
- if (existing.some((table) => table !== "stitchkit_agent_runtime_meta")) {
175
- throw new Error("Refusing an unversioned partial Stitchkit agent-runtime SQLite schema");
176
- }
177
- database.exec(`
178
- CREATE TABLE stitchkit_agent_runtime_heads (
179
- conversation_id TEXT PRIMARY KEY,
180
- version INTEGER NOT NULL CHECK (version >= 0)
181
- );
182
- CREATE TABLE stitchkit_agent_runtime_runs (
183
- conversation_id TEXT NOT NULL,
184
- run_id TEXT NOT NULL,
185
- assistant_message_id TEXT NOT NULL,
186
- state TEXT NOT NULL,
187
- created_at TEXT NOT NULL,
188
- payload TEXT NOT NULL,
189
- terminal_assistant_payload TEXT,
190
- PRIMARY KEY (conversation_id, run_id),
191
- UNIQUE (conversation_id, assistant_message_id)
192
- );
193
- CREATE INDEX stitchkit_agent_runtime_recoverable
194
- ON stitchkit_agent_runtime_runs (state, conversation_id, run_id);
195
- CREATE TABLE stitchkit_agent_runtime_admissions (
196
- conversation_id TEXT NOT NULL,
197
- idempotency_key TEXT NOT NULL,
198
- input_message_id TEXT NOT NULL,
199
- run_id TEXT NOT NULL,
200
- assistant_message_id TEXT NOT NULL,
201
- input_payload TEXT NOT NULL,
202
- PRIMARY KEY (conversation_id, idempotency_key),
203
- UNIQUE (conversation_id, input_message_id)
204
- );
205
- CREATE TABLE stitchkit_agent_runtime_messages (
206
- conversation_id TEXT NOT NULL,
207
- id TEXT NOT NULL,
208
- position INTEGER NOT NULL CHECK (position >= 0),
209
- active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)),
210
- payload TEXT NOT NULL,
211
- PRIMARY KEY (conversation_id, id)
212
- );
213
- INSERT INTO stitchkit_agent_runtime_meta (key, value) VALUES ('schema_version', '1');
214
- `);
215
- initializeSqliteConversationPurge(database);
216
- database.exec("COMMIT");
217
- } catch (error) {
218
- database.exec("ROLLBACK");
219
- throw error;
220
- }
221
- }
222
- function createSqliteAgentRuntimeStore(config) {
223
- const database = config.database;
224
- if (config.initialize !== false) {
225
- try {
226
- initializeAgentRuntimeSqlite(database);
227
- } catch (error) {
228
- database.close();
229
- throw error;
230
- }
231
- }
232
- let closing = false;
233
- let closed = false;
234
- let tail = Promise.resolve();
235
- const serial = (work) => {
236
- if (closing || closed) {
237
- return Promise.reject(new Error("SQLite agent-runtime store is closing"));
238
- }
239
- const result = tail.then(work, work);
240
- tail = result.then(() => {
241
- return;
242
- }, () => {
243
- return;
244
- });
245
- return result;
246
- };
247
- const runTransaction = (access, work) => serial(async () => {
248
- database.exec(access === "read" ? "BEGIN" : "BEGIN IMMEDIATE");
249
- try {
250
- const result = await work(database);
251
- database.exec("COMMIT");
252
- return result;
253
- } catch (error) {
254
- database.exec("ROLLBACK");
255
- throw error;
256
- }
257
- });
258
- const driver = {
259
- conversations: sqliteConversationPurge(database),
260
- transaction: (work, options) => runTransaction(options?.access ?? "write", work),
261
- head: {
262
- async load(transaction, conversationId) {
263
- const value = transaction.prepare("SELECT version FROM stitchkit_agent_runtime_heads WHERE conversation_id = ?").get(conversationId);
264
- if (missing(value))
265
- return;
266
- const row = HeadRowSchema.parse(value);
267
- return AgentRuntimeHeadSchema.parse({
268
- schemaVersion: 1,
269
- conversationId,
270
- version: row.version
271
- });
272
- },
273
- async compareAndSwap(transaction, input) {
274
- const result = transaction.prepare(`
275
- INSERT INTO stitchkit_agent_runtime_heads (conversation_id, version)
276
- VALUES (?, ?)
277
- ON CONFLICT (conversation_id) DO UPDATE SET version = excluded.version
278
- WHERE stitchkit_agent_runtime_heads.version = ?
279
- `).run(input.conversationId, input.next.version, input.expectedVersion);
280
- if (result.changes === 1)
281
- return { outcome: "applied" };
282
- const current = transaction.prepare("SELECT version FROM stitchkit_agent_runtime_heads WHERE conversation_id = ?").get(input.conversationId);
283
- return {
284
- outcome: "conflict",
285
- actualVersion: missing(current) ? 0 : HeadRowSchema.parse(current).version
286
- };
287
- }
288
- },
289
- runs: {
290
- async load(transaction, input) {
291
- const row = transaction.prepare(`
292
- SELECT payload, terminal_assistant_payload
293
- FROM stitchkit_agent_runtime_runs
294
- WHERE conversation_id = ? AND run_id = ?
295
- `).get(input.conversationId, input.runId);
296
- return missing(row) ? undefined : parseRunRow(row);
297
- },
298
- async loadByAssistantMessageId(transaction, input) {
299
- const row = transaction.prepare(`
300
- SELECT payload, terminal_assistant_payload
301
- FROM stitchkit_agent_runtime_runs
302
- WHERE conversation_id = ? AND assistant_message_id = ?
303
- `).get(input.conversationId, input.assistantMessageId);
304
- return missing(row) ? undefined : parseRunRow(row);
305
- },
306
- async loadMany(transaction, input) {
307
- if (input.runIds.length === 0)
308
- return [];
309
- return transaction.prepare(`
310
- SELECT payload, terminal_assistant_payload
311
- FROM stitchkit_agent_runtime_runs
312
- WHERE conversation_id = ? AND run_id IN (${placeholders(input.runIds.length)})
313
- `).all(input.conversationId, ...input.runIds).map(parseRunRow);
314
- },
315
- async listActive(transaction, conversationId) {
316
- return transaction.prepare(`
317
- SELECT payload, terminal_assistant_payload
318
- FROM stitchkit_agent_runtime_runs
319
- WHERE conversation_id = ? AND state IN ('queued', 'running', 'interrupt_requested')
320
- `).all(conversationId).map(parseRunRow);
321
- },
322
- async save(transaction, rawRecord) {
323
- const record = AgentStoredRunSchema.parse(rawRecord);
324
- transaction.prepare(`
325
- INSERT INTO stitchkit_agent_runtime_runs (
326
- conversation_id, run_id, assistant_message_id, state, created_at, payload,
327
- terminal_assistant_payload
328
- ) VALUES (?, ?, ?, ?, ?, ?, ?)
329
- ON CONFLICT (conversation_id, run_id) DO UPDATE SET
330
- assistant_message_id = excluded.assistant_message_id,
331
- state = excluded.state,
332
- created_at = excluded.created_at,
333
- payload = excluded.payload,
334
- terminal_assistant_payload = excluded.terminal_assistant_payload
335
- `).run(record.run.conversationId, record.run.id, record.run.assistantMessageId, record.run.state, record.run.createdAt, encodeJson(record.run), record.terminalAssistant ? encodeJson(record.terminalAssistant) : null);
336
- }
337
- },
338
- admissions: {
339
- async load(transaction, input) {
340
- const value = transaction.prepare(`
341
- SELECT conversation_id, idempotency_key, input_payload, run_id, assistant_message_id
342
- FROM stitchkit_agent_runtime_admissions
343
- WHERE conversation_id = ? AND idempotency_key = ?
344
- `).get(input.conversationId, input.idempotencyKey);
345
- if (missing(value))
346
- return;
347
- const row = AdmissionRowSchema.parse(value);
348
- return AgentAdmissionReceiptSchema.parse({
349
- schemaVersion: 1,
350
- conversationId: row.conversation_id,
351
- idempotencyKey: row.idempotency_key,
352
- input: AgentMessageSchema.parse(parseJson(row.input_payload)),
353
- runId: row.run_id,
354
- assistantMessageId: row.assistant_message_id
355
- });
356
- },
357
- async loadByInputMessageId(transaction, input) {
358
- const value = transaction.prepare(`
359
- SELECT conversation_id, idempotency_key, input_payload, run_id, assistant_message_id
360
- FROM stitchkit_agent_runtime_admissions
361
- WHERE conversation_id = ? AND input_message_id = ?
362
- `).get(input.conversationId, input.inputMessageId);
363
- if (missing(value))
364
- return;
365
- const row = AdmissionRowSchema.parse(value);
366
- return AgentAdmissionReceiptSchema.parse({
367
- schemaVersion: 1,
368
- conversationId: row.conversation_id,
369
- idempotencyKey: row.idempotency_key,
370
- input: AgentMessageSchema.parse(parseJson(row.input_payload)),
371
- runId: row.run_id,
372
- assistantMessageId: row.assistant_message_id
373
- });
374
- },
375
- async create(transaction, rawReceipt) {
376
- const receipt = AgentAdmissionReceiptSchema.parse(rawReceipt);
377
- transaction.prepare(`
378
- INSERT INTO stitchkit_agent_runtime_admissions (
379
- conversation_id, idempotency_key, input_message_id, run_id,
380
- assistant_message_id, input_payload
381
- ) VALUES (?, ?, ?, ?, ?, ?)
382
- `).run(receipt.conversationId, receipt.idempotencyKey, receipt.input.id, receipt.runId, receipt.assistantMessageId, encodeJson(receipt.input));
383
- }
384
- },
385
- history: {
386
- async load(transaction, conversationId) {
387
- return transaction.prepare(`
388
- SELECT payload FROM stitchkit_agent_runtime_messages
389
- WHERE conversation_id = ? AND active = 1 ORDER BY position ASC
390
- `).all(conversationId).map((value) => AgentMessageSchema.parse(parseJson(MessageRowSchema.parse(value).payload)));
391
- },
392
- async apply(transaction, rawMutation) {
393
- const mutation = AgentHistoryMutationSchema.parse(rawMutation);
394
- const message = mutation.type === "admit" ? mutation.input : mutation.type === "upsert-assistant" ? mutation.message : mutation.summary;
395
- if (mutation.type === "replace-compacted-range") {
396
- const parameters = mutation.replacedMessageIds;
397
- const rows = transaction.prepare(`
398
- SELECT position FROM stitchkit_agent_runtime_messages
399
- WHERE conversation_id = ? AND active = 1
400
- AND id IN (${placeholders(parameters.length)})
401
- ORDER BY position ASC
402
- `).all(message.conversationId, ...parameters).map((row) => PositionedMessageRowSchema.parse(row));
403
- const first = rows[0];
404
- if (!first || rows.length !== parameters.length) {
405
- throw new Error("Compaction range changed inside the transaction");
406
- }
407
- transaction.prepare(`
408
- UPDATE stitchkit_agent_runtime_messages SET active = 0
409
- WHERE conversation_id = ? AND id IN (${placeholders(parameters.length)})
410
- `).run(message.conversationId, ...parameters);
411
- transaction.prepare(`
412
- INSERT INTO stitchkit_agent_runtime_messages
413
- (conversation_id, id, position, active, payload)
414
- VALUES (?, ?, ?, 1, ?)
415
- `).run(message.conversationId, message.id, first.position, encodeJson(message));
416
- return;
417
- }
418
- const existing = transaction.prepare(`
419
- SELECT position FROM stitchkit_agent_runtime_messages
420
- WHERE conversation_id = ? AND id = ?
421
- `).get(message.conversationId, message.id);
422
- if (!missing(existing)) {
423
- transaction.prepare(`
424
- UPDATE stitchkit_agent_runtime_messages SET payload = ?, active = 1
425
- WHERE conversation_id = ? AND id = ?
426
- `).run(encodeJson(message), message.conversationId, message.id);
427
- return;
428
- }
429
- const last = transaction.prepare(`
430
- SELECT position FROM stitchkit_agent_runtime_messages
431
- WHERE conversation_id = ? ORDER BY position DESC LIMIT 1
432
- `).get(message.conversationId);
433
- const position = missing(last) ? 0 : PositionedMessageRowSchema.parse(last).position + 1;
434
- transaction.prepare(`
435
- INSERT INTO stitchkit_agent_runtime_messages
436
- (conversation_id, id, position, active, payload)
437
- VALUES (?, ?, ?, 1, ?)
438
- `).run(message.conversationId, message.id, position, encodeJson(message));
439
- }
440
- },
441
- scanRecoverable: (input) => runTransaction("read", async () => {
442
- const cursor = input.cursor ? parseRecoveryCursor(input.cursor) : undefined;
443
- const values = cursor ? [cursor[0], cursor[0], cursor[1], input.limit + 1] : [input.limit + 1];
444
- const rows = database.prepare(`
445
- SELECT conversation_id, run_id, payload
446
- FROM stitchkit_agent_runtime_runs
447
- WHERE state IN ('queued', 'running', 'interrupt_requested')
448
- ${cursor ? "AND (conversation_id > ? OR (conversation_id = ? AND run_id > ?))" : ""}
449
- ORDER BY conversation_id ASC, run_id ASC LIMIT ?
450
- `).all(...values).map((row) => RecoverableRowSchema.parse(row));
451
- const hasMore = rows.length > input.limit;
452
- const pageRows = rows.slice(0, input.limit);
453
- const items = pageRows.map((row) => {
454
- const run = AgentRunSchema.parse(parseJson(row.payload));
455
- return AgentRecoverableDescriptorSchema.parse({
456
- conversationId: row.conversation_id,
457
- run
458
- });
459
- });
460
- const last = pageRows.at(-1);
461
- return AgentRecoverablePageSchema.parse({
462
- items,
463
- ...hasMore && last ? { nextCursor: recoveryCursor(last.conversation_id, last.run_id) } : {}
464
- });
465
- })
466
- };
467
- return {
468
- store: createAgentRuntimeStore(driver),
469
- conversations: {
470
- list: (input) => runTransaction("read", async () => {
471
- if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 1000) {
472
- throw new TypeError("Conversation page limit must be between 1 and 1000");
473
- }
474
- const cursor = input.cursor ? parseConversationCursor(input.cursor) : undefined;
475
- const search = input.search?.trim();
476
- const clauses = [
477
- ...cursor ? ["conversation_id > ?"] : [],
478
- ...search ? ["instr(conversation_id, ?) > 0"] : []
479
- ];
480
- const parameters = [
481
- ...cursor ? [cursor] : [],
482
- ...search ? [search] : [],
483
- input.limit + 1
484
- ];
485
- const rows = database.prepare(`
486
- SELECT conversation_id, version FROM stitchkit_agent_runtime_heads
487
- ${clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : ""}
488
- ORDER BY conversation_id ASC LIMIT ?
489
- `).all(...parameters).map((row) => ConversationHeadRowSchema.parse(row));
490
- const hasMore = rows.length > input.limit;
491
- const pageRows = rows.slice(0, input.limit);
492
- const items = pageRows.map((row) => {
493
- const latestRaw = database.prepare(`
494
- SELECT position, payload FROM stitchkit_agent_runtime_messages
495
- WHERE conversation_id = ? AND active = 1
496
- ORDER BY position DESC LIMIT 1
497
- `).get(row.conversation_id);
498
- if (missing(latestRaw)) {
499
- throw new Error("Agent conversation head has no active history");
500
- }
501
- const latest = AgentMessageSchema.parse(parseJson(MessagePageRowSchema.parse(latestRaw).payload));
502
- const active = CountRowSchema.parse(database.prepare(`
503
- SELECT count(*) AS count FROM stitchkit_agent_runtime_runs
504
- WHERE conversation_id = ?
505
- AND state IN ('queued', 'running', 'interrupt_requested')
506
- `).get(row.conversation_id));
507
- return {
508
- conversationId: row.conversation_id,
509
- version: row.version,
510
- updatedAt: latest.updatedAt,
511
- preview: messagePreview(latest),
512
- activeRuns: active.count
513
- };
514
- });
515
- const last = pageRows.at(-1);
516
- return AgentConversationPageSchema.parse({
517
- items,
518
- ...hasMore && last ? { nextCursor: conversationCursor(last.conversation_id) } : {}
519
- });
520
- }),
521
- messages: (input) => runTransaction("read", async () => {
522
- if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 1000) {
523
- throw new TypeError("Conversation message page limit must be between 1 and 1000");
524
- }
525
- const cursor = input.cursor ? parseMessageCursor(input.cursor) : undefined;
526
- const before = input.direction === "before";
527
- const rows = database.prepare(`
528
- SELECT position, payload FROM stitchkit_agent_runtime_messages
529
- WHERE conversation_id = ? AND active = 1
530
- ${cursor === undefined ? "" : before ? "AND position < ?" : "AND position > ?"}
531
- ORDER BY position ${before ? "DESC" : "ASC"} LIMIT ?
532
- `).all(input.conversationId, ...cursor === undefined ? [] : [cursor], input.limit + 1).map((row) => MessagePageRowSchema.parse(row));
533
- const hasMore = rows.length > input.limit;
534
- const pageRows = rows.slice(0, input.limit);
535
- const ordered = before ? [...pageRows].reverse() : pageRows;
536
- const boundary = pageRows.at(-1);
537
- return AgentConversationMessagePageSchema.parse({
538
- items: ordered.map((row) => AgentMessageSchema.parse(parseJson(row.payload))),
539
- ...hasMore && boundary ? { nextCursor: messageCursor(boundary.position) } : {}
540
- });
541
- })
542
- },
543
- async close() {
544
- if (closed)
545
- return;
546
- closing = true;
547
- await tail;
548
- database.close();
549
- closed = true;
550
- }
551
- };
552
- }
553
-
554
- export { initializeAgentRuntimeSqlite, createSqliteAgentRuntimeStore };
@@ -1,83 +0,0 @@
1
- // src/agent-runtime/history-chronology.ts
2
- function createToolChronology() {
3
- return { calls: new Map, approvals: new Map, pending: 0, resultsStarted: false };
4
- }
5
- function advanceToolChronology(previous, parts) {
6
- const calls = new Map(previous.calls);
7
- const approvals = new Map(previous.approvals);
8
- let { pending, resultsStarted } = previous;
9
- for (const part of parts) {
10
- if (part.type === "tool-call") {
11
- if (calls.has(part.callId) || resultsStarted && pending > 0)
12
- return;
13
- if (pending === 0)
14
- resultsStarted = false;
15
- calls.set(part.callId, { toolName: part.toolName, phase: "called" });
16
- pending += 1;
17
- } else if (part.type === "tool-approval-request") {
18
- const call = calls.get(part.callId);
19
- if (call?.phase !== "called" || approvals.has(part.approvalId))
20
- return;
21
- approvals.set(part.approvalId, part.callId);
22
- calls.set(part.callId, { ...call, phase: "requested" });
23
- } else if (part.type === "tool-approval-response") {
24
- const callId = approvals.get(part.approvalId);
25
- const call = callId === undefined ? undefined : calls.get(callId);
26
- if (callId === undefined || !call || call.phase !== "requested")
27
- return;
28
- calls.set(callId, { ...call, phase: part.approved ? "approved" : "denied" });
29
- } else if (part.type === "tool-result") {
30
- const call = calls.get(part.callId);
31
- if (!call || call.toolName !== part.toolName || call.phase === "result" || call.phase === "requested" || call.phase === "denied" && part.outcome === "success")
32
- return;
33
- calls.set(part.callId, { ...call, phase: "result" });
34
- pending -= 1;
35
- resultsStarted = true;
36
- }
37
- }
38
- return { calls, approvals, pending, resultsStarted };
39
- }
40
- function canProjectToolChronology(state) {
41
- return [...state.calls.values()].every(({ phase }) => phase !== "called");
42
- }
43
-
44
- // src/agent-runtime/terminal-status.ts
45
- function isSpeakableAssistantStatus(status) {
46
- return status === "completed" || status === "interrupted" || status === "committed";
47
- }
48
- function isAssistantHistoryEvidence(status, policy) {
49
- return isSpeakableAssistantStatus(status) || status === "failed" && policy?.failedAssistant === "assistant-marked";
50
- }
51
- function isCompleteAgentHistoryTurn(messages, policy) {
52
- if (messages[0]?.role !== "user")
53
- return false;
54
- let chronology = createToolChronology();
55
- let assistantCount = 0;
56
- for (const message of messages) {
57
- if (message.role === "assistant") {
58
- if (!isAssistantHistoryEvidence(message.status, policy))
59
- return false;
60
- assistantCount += 1;
61
- }
62
- const next = advanceToolChronology(chronology, message.parts);
63
- if (!next)
64
- return false;
65
- chronology = next;
66
- }
67
- return assistantCount > 0 && chronology.pending === 0;
68
- }
69
- function assistantStatus(reason) {
70
- if (reason === "success" || reason === "policy_stop" || reason === "provider_stop") {
71
- return "completed";
72
- }
73
- if (reason === "superseded")
74
- return "superseded";
75
- if (reason === "absorbed")
76
- return "superseded";
77
- if (reason === "interrupted" || reason === "cancelled" || reason === "shutdown") {
78
- return "interrupted";
79
- }
80
- return "failed";
81
- }
82
-
83
- export { createToolChronology, advanceToolChronology, canProjectToolChronology, isAssistantHistoryEvidence, isCompleteAgentHistoryTurn, assistantStatus };