stitchkit 0.56.5 → 0.57.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.
@@ -2,6 +2,34 @@ import {
2
2
  ToolExecutionControlError,
3
3
  isToolExecutionControlError
4
4
  } from "./index-sa2mbwa7.js";
5
+ import {
6
+ AgentAssistantPlaceholderSchema,
7
+ AgentControlPartSchema,
8
+ AgentCostValueSchema,
9
+ AgentFilePartSchema,
10
+ AgentJsonObjectSchema,
11
+ AgentMessagePartSchema,
12
+ AgentMessageRoleSchema,
13
+ AgentMessageSchema,
14
+ AgentMessageStatusSchema,
15
+ AgentOpaquePartSchema,
16
+ AgentProviderEnvelopeSchema,
17
+ AgentReasoningPartSchema,
18
+ AgentRecordIdSchema,
19
+ AgentRecordVersionSchema,
20
+ AgentRunMetricsSchema,
21
+ AgentRunSchema,
22
+ AgentRunStateSchema,
23
+ AgentSnapshotSchema,
24
+ AgentSourcePartSchema,
25
+ AgentTerminalReasonSchema,
26
+ AgentTextPartSchema,
27
+ AgentTimestampSchema,
28
+ AgentToolCallPartSchema,
29
+ AgentToolResultPartSchema,
30
+ AgentUsageSchema,
31
+ AgentUsageValueSchema
32
+ } from "./index-1f4fcj0b.js";
5
33
  import"./index-6djpbnda.js";
6
34
  import"./index-cby4ar3v.js";
7
35
  import {
@@ -226,210 +254,78 @@ function createAgentSessionCoordinator() {
226
254
  };
227
255
  }
228
256
  // src/agent-runtime/events.ts
229
- import { z as z2 } from "zod";
230
-
231
- // src/agent-runtime/schemas.ts
232
257
  import { z } from "zod";
233
- var AgentRecordIdSchema = z.string().min(1);
234
- var AgentRecordVersionSchema = z.int().nonnegative();
235
- var AgentTimestampSchema = z.iso.datetime({ offset: true });
236
- var AgentJsonObjectSchema = z.record(z.string(), z.json());
237
- var AgentProviderEnvelopeSchema = z.object({
238
- schemaVersion: z.int().positive(),
239
- provider: z.string().min(1),
240
- data: AgentJsonObjectSchema
241
- });
242
- var AgentTextPartSchema = z.object({
243
- type: z.literal("text"),
244
- text: z.string()
245
- });
246
- var AgentReasoningPartSchema = z.object({
247
- type: z.literal("reasoning"),
248
- text: z.string(),
249
- provider: AgentProviderEnvelopeSchema.optional()
250
- });
251
- var AgentFilePartSchema = z.object({
252
- type: z.literal("file"),
253
- mediaType: z.string().min(1),
254
- reference: z.string().min(1),
255
- filename: z.string().min(1).optional()
256
- });
257
- var AgentSourcePartSchema = z.object({
258
- type: z.literal("source"),
259
- sourceId: z.string().min(1),
260
- url: z.url().optional(),
261
- title: z.string().optional()
262
- });
263
- var AgentToolCallPartSchema = z.object({
264
- type: z.literal("tool-call"),
265
- callId: z.string().min(1),
266
- toolName: z.string().min(1),
267
- input: z.json(),
268
- provider: AgentProviderEnvelopeSchema.optional()
269
- });
270
- var AgentToolResultPartSchema = z.object({
271
- type: z.literal("tool-result"),
272
- callId: z.string().min(1),
273
- toolName: z.string().min(1),
274
- outcome: z.enum(["success", "error", "interrupted"]),
275
- output: z.json().optional()
276
- });
277
- var AgentOpaquePartSchema = z.object({
278
- type: z.literal("provider"),
279
- envelope: AgentProviderEnvelopeSchema
280
- });
281
- var AgentControlPartSchema = z.object({
282
- type: z.literal("control"),
283
- reason: z.enum(["run-interrupted", "stale-run"])
284
- });
285
- var AgentMessagePartSchema = z.discriminatedUnion("type", [
286
- AgentTextPartSchema,
287
- AgentReasoningPartSchema,
288
- AgentFilePartSchema,
289
- AgentSourcePartSchema,
290
- AgentToolCallPartSchema,
291
- AgentToolResultPartSchema,
292
- AgentOpaquePartSchema,
293
- AgentControlPartSchema
294
- ]);
295
- var AgentMessageRoleSchema = z.enum(["user", "assistant", "system", "summary"]);
296
- var AgentMessageStatusSchema = z.enum([
297
- "committed",
298
- "streaming",
299
- "completed",
300
- "interrupted",
301
- "failed"
302
- ]);
303
- var AgentMessageSchema = z.object({
304
- schemaVersion: z.literal(1),
305
- id: AgentRecordIdSchema,
306
- conversationId: AgentRecordIdSchema,
307
- runId: AgentRecordIdSchema.optional(),
308
- role: AgentMessageRoleSchema,
309
- status: AgentMessageStatusSchema,
310
- parts: z.array(AgentMessagePartSchema),
311
- metadata: AgentJsonObjectSchema.optional(),
312
- createdAt: AgentTimestampSchema,
313
- updatedAt: AgentTimestampSchema
314
- });
315
- var AgentRunStateSchema = z.enum([
316
- "queued",
317
- "running",
318
- "interrupt_requested",
319
- "completed",
320
- "interrupted",
321
- "failed",
322
- "cancelled",
323
- "abandoned"
324
- ]);
325
- var AgentTerminalReasonSchema = z.enum([
326
- "success",
327
- "policy_stop",
328
- "interrupted",
329
- "cancelled",
330
- "timeout",
331
- "shutdown",
332
- "provider_failure",
333
- "tool_failure",
334
- "abandoned"
335
- ]);
336
- var AgentRunSchema = z.object({
337
- schemaVersion: z.literal(1),
338
- id: AgentRecordIdSchema,
339
- conversationId: AgentRecordIdSchema,
340
- inputMessageIds: z.array(AgentRecordIdSchema).min(1),
341
- assistantMessageId: AgentRecordIdSchema,
342
- state: AgentRunStateSchema,
343
- revision: AgentRecordVersionSchema,
344
- ownerId: z.string().min(1).optional(),
345
- terminalReason: AgentTerminalReasonSchema.optional(),
346
- terminalPolicyName: z.string().min(1).optional(),
347
- createdAt: AgentTimestampSchema,
348
- updatedAt: AgentTimestampSchema
349
- });
350
- var AgentSnapshotSchema = z.object({
351
- schemaVersion: z.literal(1),
258
+ var AgentAdmissionEventSchema = z.object({
259
+ type: z.literal("admission"),
260
+ eventId: AgentRecordIdSchema,
352
261
  conversationId: AgentRecordIdSchema,
353
- version: AgentRecordVersionSchema,
354
- messages: z.array(AgentMessageSchema),
355
- runs: z.array(AgentRunSchema)
356
- });
357
- var AgentUsageValueSchema = z.object({
358
- value: z.number().nonnegative().optional(),
359
- provenance: z.enum(["provider-reported", "computed", "estimated", "unavailable"])
360
- });
361
- var AgentCostValueSchema = z.object({
362
- value: z.number().nonnegative().optional(),
363
- currency: z.string().length(3).optional(),
364
- provenance: z.enum(["provider-reported", "computed", "estimated", "unavailable"])
365
- });
366
- var AgentUsageSchema = z.object({
367
- inputTokens: AgentUsageValueSchema,
368
- outputTokens: AgentUsageValueSchema,
369
- reasoningTokens: AgentUsageValueSchema.optional(),
370
- cacheReadTokens: AgentUsageValueSchema.optional(),
371
- cacheWriteTokens: AgentUsageValueSchema.optional(),
372
- cost: AgentCostValueSchema.optional()
262
+ runId: AgentRecordIdSchema,
263
+ snapshotVersion: AgentRecordVersionSchema,
264
+ input: AgentMessageSchema,
265
+ run: AgentRunSchema,
266
+ assistant: z.union([AgentAssistantPlaceholderSchema, AgentMessageSchema]),
267
+ emittedAt: AgentTimestampSchema
373
268
  });
374
-
375
- // src/agent-runtime/events.ts
376
- var EventIdentitySchema = z2.object({
269
+ var EventIdentitySchema = z.object({
377
270
  conversationId: AgentRecordIdSchema,
378
271
  runId: AgentRecordIdSchema,
379
272
  emittedAt: AgentTimestampSchema
380
273
  });
381
274
  var AgentTransientDeltaEventSchema = EventIdentitySchema.extend({
382
- type: z2.literal("assistant-delta"),
383
- runtimeEpoch: z2.string().min(1),
384
- sequence: z2.int().nonnegative(),
385
- textDelta: z2.string()
275
+ type: z.literal("assistant-delta"),
276
+ runtimeEpoch: z.string().min(1),
277
+ sequence: z.int().nonnegative(),
278
+ textDelta: z.string()
386
279
  });
387
280
  var AgentTransientReasoningIdentitySchema = EventIdentitySchema.extend({
388
- runtimeEpoch: z2.string().min(1),
389
- sequence: z2.int().nonnegative(),
281
+ runtimeEpoch: z.string().min(1),
282
+ sequence: z.int().nonnegative(),
390
283
  provider: AgentProviderEnvelopeSchema.optional()
391
284
  });
392
285
  var AgentReasoningStartEventSchema = AgentTransientReasoningIdentitySchema.extend({
393
- type: z2.literal("reasoning-start")
286
+ type: z.literal("reasoning-start")
394
287
  });
395
288
  var AgentReasoningDeltaEventSchema = AgentTransientReasoningIdentitySchema.extend({
396
- type: z2.literal("reasoning-delta"),
397
- textDelta: z2.string()
289
+ type: z.literal("reasoning-delta"),
290
+ textDelta: z.string()
398
291
  });
399
292
  var AgentReasoningEndEventSchema = AgentTransientReasoningIdentitySchema.extend({
400
- type: z2.literal("reasoning-end")
293
+ type: z.literal("reasoning-end")
401
294
  });
402
295
  var AgentCheckpointEventSchema = EventIdentitySchema.extend({
403
- type: z2.literal("assistant-checkpoint"),
296
+ type: z.literal("assistant-checkpoint"),
404
297
  eventId: AgentRecordIdSchema,
405
298
  snapshotVersion: AgentRecordVersionSchema,
406
- message: AgentMessageSchema
299
+ message: AgentMessageSchema,
300
+ metrics: AgentRunMetricsSchema.optional()
407
301
  });
408
302
  var AgentRunStateEventSchema = EventIdentitySchema.extend({
409
- type: z2.literal("run-state"),
303
+ type: z.literal("run-state"),
410
304
  eventId: AgentRecordIdSchema,
411
305
  snapshotVersion: AgentRecordVersionSchema,
412
306
  state: AgentRunStateSchema
413
307
  });
414
308
  var AgentToolStatusEventSchema = EventIdentitySchema.extend({
415
- type: z2.literal("tool-status"),
416
- runtimeEpoch: z2.string().min(1),
417
- sequence: z2.int().nonnegative(),
309
+ type: z.literal("tool-status"),
310
+ runtimeEpoch: z.string().min(1),
311
+ sequence: z.int().nonnegative(),
418
312
  callId: AgentRecordIdSchema,
419
- toolName: z2.string().min(1),
420
- status: z2.enum(["started", "completed", "failed", "interrupted"]),
421
- input: z2.json().optional(),
422
- output: z2.json().optional()
313
+ toolName: z.string().min(1),
314
+ status: z.enum(["started", "completed", "failed", "interrupted"]),
315
+ input: z.json().optional(),
316
+ output: z.json().optional()
423
317
  });
424
318
  var AgentTerminalEventSchema = EventIdentitySchema.extend({
425
- type: z2.literal("terminal"),
319
+ type: z.literal("terminal"),
426
320
  eventId: AgentRecordIdSchema,
427
321
  snapshotVersion: AgentRecordVersionSchema,
428
322
  reason: AgentTerminalReasonSchema,
429
- policyName: z2.string().min(1).optional(),
430
- message: AgentMessageSchema
323
+ policyName: z.string().min(1).optional(),
324
+ message: AgentMessageSchema,
325
+ metrics: AgentRunMetricsSchema.optional()
431
326
  });
432
- var AgentRuntimeEventSchema = z2.discriminatedUnion("type", [
327
+ var AgentRuntimeEventSchema = z.discriminatedUnion("type", [
328
+ AgentAdmissionEventSchema,
433
329
  AgentTransientDeltaEventSchema,
434
330
  AgentReasoningStartEventSchema,
435
331
  AgentReasoningDeltaEventSchema,
@@ -565,15 +461,15 @@ function createAgentToolFenceLifecycle(config) {
565
461
  };
566
462
  }
567
463
  // src/agent-runtime/models.ts
568
- import { z as z3 } from "zod";
569
- var AgentModelCapabilitySchema = z3.enum(["tools", "vision", "reasoning", "files"]);
570
- var AgentModelDescriptorSchema = z3.object({
571
- provider: z3.string().min(1),
572
- modelId: z3.string().min(1),
573
- contextWindow: z3.int().positive(),
574
- capabilities: z3.array(AgentModelCapabilitySchema),
575
- observedAt: z3.iso.datetime({ offset: true }).optional(),
576
- source: z3.string().min(1).optional()
464
+ import { z as z2 } from "zod";
465
+ var AgentModelCapabilitySchema = z2.enum(["tools", "vision", "reasoning", "files"]);
466
+ var AgentModelDescriptorSchema = z2.object({
467
+ provider: z2.string().min(1),
468
+ modelId: z2.string().min(1),
469
+ contextWindow: z2.int().positive(),
470
+ capabilities: z2.array(AgentModelCapabilitySchema),
471
+ observedAt: z2.iso.datetime({ offset: true }).optional(),
472
+ source: z2.string().min(1).optional()
577
473
  });
578
474
  function defineModelRegistry(config) {
579
475
  const descriptors = new Map;
@@ -613,25 +509,25 @@ function defineModelRegistry(config) {
613
509
  };
614
510
  }
615
511
  // src/agent-runtime/observability.ts
616
- import { z as z4 } from "zod";
617
- var AgentRunEventSchema = z4.object({
618
- schemaVersion: z4.literal(1),
512
+ import { z as z3 } from "zod";
513
+ var AgentRunEventSchema = z3.object({
514
+ schemaVersion: z3.literal(1),
619
515
  eventId: AgentRecordIdSchema,
620
- type: z4.enum(["run-started", "step-finished", "run-terminal"]),
516
+ type: z3.enum(["run-started", "step-finished", "run-terminal"]),
621
517
  conversationId: AgentRecordIdSchema,
622
518
  runId: AgentRecordIdSchema,
623
- traceId: z4.string().min(1),
624
- spanId: z4.string().min(1),
625
- parentSpanId: z4.string().min(1).optional(),
519
+ traceId: z3.string().min(1),
520
+ spanId: z3.string().min(1),
521
+ parentSpanId: z3.string().min(1).optional(),
626
522
  state: AgentRunStateSchema,
627
523
  terminalReason: AgentTerminalReasonSchema.optional(),
628
- modelId: z4.string().min(1).optional(),
629
- step: z4.int().nonnegative().optional(),
630
- queueWaitMs: z4.number().nonnegative().optional(),
631
- durationMs: z4.number().nonnegative().optional(),
632
- ttftMs: z4.number().nonnegative().optional(),
524
+ modelId: z3.string().min(1).optional(),
525
+ step: z3.int().nonnegative().optional(),
526
+ queueWaitMs: z3.number().nonnegative().optional(),
527
+ durationMs: z3.number().nonnegative().optional(),
528
+ ttftMs: z3.number().nonnegative().optional(),
633
529
  usage: AgentUsageSchema.optional(),
634
- internalCause: z4.unknown().optional(),
530
+ internalCause: z3.unknown().optional(),
635
531
  emittedAt: AgentTimestampSchema
636
532
  });
637
533
  function createAgentObservability(config) {
@@ -656,10 +552,10 @@ function createAgentObservability(config) {
656
552
  };
657
553
  }
658
554
  // src/agent-runtime/prompt.ts
659
- import { z as z5 } from "zod";
660
- var AgentTokenCountSchema = z5.object({
661
- value: z5.int().nonnegative().optional(),
662
- provenance: z5.enum(["measured", "estimated", "unavailable"])
555
+ import { z as z4 } from "zod";
556
+ var AgentTokenCountSchema = z4.object({
557
+ value: z4.int().nonnegative().optional(),
558
+ provenance: z4.enum(["measured", "estimated", "unavailable"])
663
559
  });
664
560
  function knownValue(value) {
665
561
  return value.provenance === "unavailable" ? undefined : value.value;
@@ -738,7 +634,7 @@ import {
738
634
  stepCountIs,
739
635
  streamText
740
636
  } from "ai";
741
- import { z as z6 } from "zod";
637
+ import { z as z5 } from "zod";
742
638
  class AgentRuntimeConflictError extends Error {
743
639
  constructor(operation) {
744
640
  super(`Agent runtime store conflict during ${operation}`);
@@ -757,7 +653,7 @@ function findRun(runs, runId) {
757
653
  return run;
758
654
  }
759
655
  function jsonValue(value) {
760
- const parsed = z6.json().safeParse(value);
656
+ const parsed = z5.json().safeParse(value);
761
657
  return parsed.success ? parsed.data : { message: "Non-JSON tool output omitted" };
762
658
  }
763
659
  function providerEnvelope(value) {
@@ -1002,6 +898,12 @@ function createAgentRuntime(config) {
1002
898
  assistant
1003
899
  }), "assistant checkpoint");
1004
900
  run = findRun(snapshot.runs, run.id);
901
+ const checkpointMetrics = {
902
+ partial: true,
903
+ durationMs: performance.now() - runStartedAt,
904
+ ...usage && { usage },
905
+ ...firstOutputAt !== undefined && { ttftMs: firstOutputAt - runStartedAt }
906
+ };
1005
907
  await publish({
1006
908
  type: "assistant-checkpoint",
1007
909
  eventId: generateId(),
@@ -1009,6 +911,7 @@ function createAgentRuntime(config) {
1009
911
  runId: run.id,
1010
912
  snapshotVersion: snapshot.version,
1011
913
  message: assistant,
914
+ metrics: checkpointMetrics,
1012
915
  emittedAt: now().toISOString()
1013
916
  });
1014
917
  };
@@ -1378,6 +1281,12 @@ function createAgentRuntime(config) {
1378
1281
  ...terminalPolicyName && { policyName: terminalPolicyName }
1379
1282
  }), "terminal commit");
1380
1283
  run = findRun(snapshot.runs, run.id);
1284
+ const terminalMetrics = {
1285
+ partial: false,
1286
+ durationMs: performance.now() - runStartedAt,
1287
+ ...usage && { usage },
1288
+ ...firstOutputAt !== undefined && { ttftMs: firstOutputAt - runStartedAt }
1289
+ };
1381
1290
  config.observe?.emit({
1382
1291
  schemaVersion: 1,
1383
1292
  eventId: generateId(),
@@ -1390,7 +1299,7 @@ function createAgentRuntime(config) {
1390
1299
  state: run.state,
1391
1300
  terminalReason,
1392
1301
  ...selectedModel && { modelId: selectedModel.descriptor.modelId },
1393
- durationMs: performance.now() - runStartedAt,
1302
+ durationMs: terminalMetrics.durationMs,
1394
1303
  ...usage && { usage },
1395
1304
  ...internalCause !== undefined && { internalCause },
1396
1305
  ...firstOutputAt !== undefined && { ttftMs: firstOutputAt - runStartedAt },
@@ -1405,6 +1314,7 @@ function createAgentRuntime(config) {
1405
1314
  reason: terminalReason,
1406
1315
  ...terminalPolicyName && { policyName: terminalPolicyName },
1407
1316
  message: assistant,
1317
+ metrics: terminalMetrics,
1408
1318
  emittedAt: now().toISOString()
1409
1319
  });
1410
1320
  return {
@@ -1412,9 +1322,38 @@ function createAgentRuntime(config) {
1412
1322
  message: assistant,
1413
1323
  reason: terminalReason,
1414
1324
  snapshotVersion: snapshot.version,
1325
+ metrics: terminalMetrics,
1415
1326
  ...terminalPolicyName && { policyName: terminalPolicyName }
1416
1327
  };
1417
1328
  };
1329
+ const resume = (rawInput) => {
1330
+ const context = config.protocol.parseContext(rawInput.context);
1331
+ const accepted = Promise.withResolvers();
1332
+ const result = Promise.withResolvers();
1333
+ (async () => {
1334
+ try {
1335
+ const snapshot = await config.store.loadSnapshot(rawInput.conversationId);
1336
+ const recoveredRun = findRun(snapshot.runs, rawInput.runId);
1337
+ if (recoveredRun.state !== "queued") {
1338
+ throw new Error("Only a queued recovered agent run can be resumed");
1339
+ }
1340
+ accepted.resolve();
1341
+ const ticket = coordinator.submit({
1342
+ key: rawInput.conversationKey ?? rawInput.conversationId,
1343
+ policy: "queue",
1344
+ create: (signal) => ({
1345
+ runId: recoveredRun.id,
1346
+ execute: () => executeRun({ acceptedRun: recoveredRun, context, signal })
1347
+ })
1348
+ });
1349
+ ticket.result.then(result.resolve, result.reject);
1350
+ } catch (error) {
1351
+ accepted.reject(error);
1352
+ result.reject(error);
1353
+ }
1354
+ })();
1355
+ return { accepted: accepted.promise, result: result.promise };
1356
+ };
1418
1357
  return {
1419
1358
  submit(rawInput) {
1420
1359
  const metadata = rawInput.metadata === undefined ? undefined : config.protocol.parseInputMetadata(rawInput.metadata);
@@ -1505,10 +1444,41 @@ function createAgentRuntime(config) {
1505
1444
  const acceptedSnapshot = appliedSnapshot(acceptance, "input acceptance");
1506
1445
  const assignedRunId = acceptance.outcome === "duplicate" ? acceptance.runId : reservation?.admission.runId ?? runId;
1507
1446
  const acceptedRun = findRun(acceptedSnapshot.runs, assignedRunId);
1508
- outerAdmission.resolve({
1447
+ const actualInputMessageId = acceptance.outcome === "duplicate" ? acceptance.inputMessageId : userMessage2.id;
1448
+ const acceptedInput = acceptance.outcome === "duplicate" ? acceptance.input : acceptedSnapshot.messages.find((candidate) => candidate.id === actualInputMessageId);
1449
+ if (!acceptedInput) {
1450
+ throw new AgentRuntimeConflictError("admission input projection");
1451
+ }
1452
+ const assistantPlaceholder = AgentAssistantPlaceholderSchema.parse({
1453
+ schemaVersion: 1,
1454
+ id: acceptedRun.assistantMessageId,
1455
+ conversationId: acceptedRun.conversationId,
1456
+ runId: acceptedRun.id,
1457
+ status: "pending",
1458
+ createdAt: acceptedRun.createdAt,
1459
+ updatedAt: acceptedRun.updatedAt
1460
+ });
1461
+ const acceptedAssistant = acceptance.outcome === "duplicate" ? acceptedSnapshot.messages.find((candidate) => candidate.id === acceptedRun.assistantMessageId) ?? assistantPlaceholder : assistantPlaceholder;
1462
+ const admission = {
1463
+ inputMessageId: acceptedInput.id,
1509
1464
  runId: acceptedRun.id,
1510
- assistantMessageId: acceptedRun.assistantMessageId,
1465
+ assistantMessageId: assistantPlaceholder.id,
1466
+ input: acceptedInput,
1467
+ run: acceptedRun,
1468
+ assistant: acceptedAssistant,
1511
1469
  snapshotVersion: acceptedSnapshot.version
1470
+ };
1471
+ outerAdmission.resolve(admission);
1472
+ await publish({
1473
+ type: "admission",
1474
+ eventId: generateId(),
1475
+ conversationId: acceptedRun.conversationId,
1476
+ runId: acceptedRun.id,
1477
+ snapshotVersion: acceptedSnapshot.version,
1478
+ input: acceptedInput,
1479
+ run: acceptedRun,
1480
+ assistant: acceptedAssistant,
1481
+ emittedAt: now().toISOString()
1512
1482
  });
1513
1483
  await publish({
1514
1484
  type: "run-state",
@@ -1597,34 +1567,7 @@ function createAgentRuntime(config) {
1597
1567
  })();
1598
1568
  return publicTicket;
1599
1569
  },
1600
- resume(rawInput) {
1601
- const context = config.protocol.parseContext(rawInput.context);
1602
- const accepted = Promise.withResolvers();
1603
- const result = Promise.withResolvers();
1604
- (async () => {
1605
- try {
1606
- const snapshot = await config.store.loadSnapshot(rawInput.conversationId);
1607
- const recoveredRun = findRun(snapshot.runs, rawInput.runId);
1608
- if (recoveredRun.state !== "queued") {
1609
- throw new Error("Only a queued recovered agent run can be resumed");
1610
- }
1611
- accepted.resolve();
1612
- const ticket = coordinator.submit({
1613
- key: rawInput.conversationKey ?? rawInput.conversationId,
1614
- policy: "queue",
1615
- create: (signal) => ({
1616
- runId: recoveredRun.id,
1617
- execute: () => executeRun({ acceptedRun: recoveredRun, context, signal })
1618
- })
1619
- });
1620
- ticket.result.then(result.resolve, result.reject);
1621
- } catch (error) {
1622
- accepted.reject(error);
1623
- result.reject(error);
1624
- }
1625
- })();
1626
- return { accepted: accepted.promise, result: result.promise };
1627
- },
1570
+ resume,
1628
1571
  async interrupt(input) {
1629
1572
  const snapshot = await config.store.loadSnapshot(input.conversationId);
1630
1573
  const run = findRun(snapshot.runs, input.runId);
@@ -1648,101 +1591,298 @@ function createAgentRuntime(config) {
1648
1591
  }
1649
1592
  return requested;
1650
1593
  },
1594
+ async recover(options) {
1595
+ if (!config.store.scanRecoverablePage) {
1596
+ throw new Error("The configured agent store does not support bounded recovery scans");
1597
+ }
1598
+ const pageSize = options.pageSize ?? 100;
1599
+ const maxRuns = options.maxRuns ?? 1000;
1600
+ if (!Number.isSafeInteger(pageSize) || pageSize < 1 || pageSize > 1000) {
1601
+ throw new TypeError("Recovery pageSize must be an integer between 1 and 1000");
1602
+ }
1603
+ if (!Number.isSafeInteger(maxRuns) || maxRuns < 1) {
1604
+ throw new TypeError("Recovery maxRuns must be a positive safe integer");
1605
+ }
1606
+ const outcomes = [];
1607
+ let cursor;
1608
+ while (outcomes.length < maxRuns && !options.signal?.aborted) {
1609
+ const page = await config.store.scanRecoverablePage({
1610
+ ...cursor && { cursor },
1611
+ limit: Math.min(pageSize, maxRuns - outcomes.length)
1612
+ });
1613
+ for (const item of page.items) {
1614
+ if (options.signal?.aborted)
1615
+ break;
1616
+ try {
1617
+ if (item.run.state === "queued") {
1618
+ const snapshot = await config.store.loadSnapshot(item.conversationId);
1619
+ const blockedByAcquiredPredecessor = snapshot.runs.some((run) => run.id !== item.run.id && (run.state === "running" || run.state === "interrupt_requested"));
1620
+ if (blockedByAcquiredPredecessor) {
1621
+ outcomes.push({
1622
+ conversationId: item.conversationId,
1623
+ runId: item.run.id,
1624
+ outcome: "skipped"
1625
+ });
1626
+ continue;
1627
+ }
1628
+ }
1629
+ const decision = await options.decide?.(item) ?? (item.run.state === "queued" ? { action: "resume" } : { action: "skip" });
1630
+ if (decision.action === "skip") {
1631
+ outcomes.push({
1632
+ conversationId: item.conversationId,
1633
+ runId: item.run.id,
1634
+ outcome: "skipped"
1635
+ });
1636
+ continue;
1637
+ }
1638
+ if (decision.action === "abandon") {
1639
+ const abandoned = await config.store.recoverRun({
1640
+ conversationId: item.conversationId,
1641
+ runId: item.run.id,
1642
+ expectedRevision: item.run.revision,
1643
+ action: "abandon"
1644
+ });
1645
+ if (abandoned.outcome !== "applied") {
1646
+ throw new AgentRuntimeConflictError("recovery abandon");
1647
+ }
1648
+ outcomes.push({
1649
+ conversationId: item.conversationId,
1650
+ runId: item.run.id,
1651
+ outcome: "abandoned"
1652
+ });
1653
+ continue;
1654
+ }
1655
+ if (decision.action === "requeue") {
1656
+ const requeued = await config.store.recoverRun({
1657
+ conversationId: item.conversationId,
1658
+ runId: item.run.id,
1659
+ expectedRevision: item.run.revision,
1660
+ action: "requeue",
1661
+ replaySafe: true
1662
+ });
1663
+ if (requeued.outcome !== "applied") {
1664
+ throw new AgentRuntimeConflictError("recovery requeue");
1665
+ }
1666
+ }
1667
+ const context = await options.resolveContext(item);
1668
+ const resumed = resume({
1669
+ conversationId: item.conversationId,
1670
+ runId: item.run.id,
1671
+ context
1672
+ });
1673
+ resumed.result.catch(() => {
1674
+ return;
1675
+ });
1676
+ await resumed.accepted;
1677
+ outcomes.push({
1678
+ conversationId: item.conversationId,
1679
+ runId: item.run.id,
1680
+ outcome: decision.action === "requeue" ? "requeued" : "resumed"
1681
+ });
1682
+ } catch (error) {
1683
+ outcomes.push({
1684
+ conversationId: item.conversationId,
1685
+ runId: item.run.id,
1686
+ outcome: "failed",
1687
+ error
1688
+ });
1689
+ }
1690
+ }
1691
+ cursor = page.nextCursor;
1692
+ if (!cursor || page.items.length === 0)
1693
+ break;
1694
+ }
1695
+ return outcomes;
1696
+ },
1651
1697
  stop: (conversationKey, reason) => coordinator.stop(conversationKey, reason),
1652
1698
  close: (options) => coordinator.close(options)
1653
1699
  };
1654
1700
  }
1655
1701
  // src/agent-runtime/store.ts
1656
- import { z as z7 } from "zod";
1657
- var AgentStoreConflictSchema = z7.object({
1658
- outcome: z7.literal("conflict"),
1702
+ import { z as z6 } from "zod";
1703
+ var AgentStoreConflictSchema = z6.object({
1704
+ outcome: z6.literal("conflict"),
1659
1705
  actualVersion: AgentRecordVersionSchema
1660
1706
  });
1661
- var AgentStoreNotFoundSchema = z7.object({
1662
- outcome: z7.literal("not_found")
1663
- });
1664
- var AgentStoreAppliedSchema = z7.object({
1665
- outcome: z7.literal("applied"),
1707
+ var AgentStoreNotFoundSchema = z6.object({ outcome: z6.literal("not_found") });
1708
+ var AgentStoreAppliedSchema = z6.object({
1709
+ outcome: z6.literal("applied"),
1666
1710
  snapshot: AgentSnapshotSchema
1667
1711
  });
1668
- var AgentStoreDuplicateSchema = z7.object({
1669
- outcome: z7.literal("duplicate"),
1712
+ var AgentStoreDuplicateSchema = z6.object({
1713
+ outcome: z6.literal("duplicate"),
1714
+ input: AgentMessageSchema,
1715
+ inputMessageId: AgentRecordIdSchema,
1670
1716
  runId: AgentRecordIdSchema,
1717
+ assistantMessageId: AgentRecordIdSchema,
1671
1718
  snapshot: AgentSnapshotSchema
1672
1719
  });
1673
- var AgentStoreMutationResultSchema = z7.discriminatedUnion("outcome", [
1720
+ var AgentStoreMutationResultSchema = z6.discriminatedUnion("outcome", [
1674
1721
  AgentStoreAppliedSchema,
1675
1722
  AgentStoreDuplicateSchema,
1676
1723
  AgentStoreConflictSchema,
1677
1724
  AgentStoreNotFoundSchema
1678
1725
  ]);
1679
- var AcceptInputAndAssignRunSchema = z7.object({
1680
- idempotencyKey: z7.string().min(1),
1726
+ var AcceptInputAndAssignRunSchema = z6.object({
1727
+ idempotencyKey: z6.string().min(1),
1681
1728
  expectedVersion: AgentRecordVersionSchema.optional(),
1682
1729
  input: AgentMessageSchema,
1683
1730
  run: AgentRunSchema,
1684
1731
  coalesceIntoRunId: AgentRecordIdSchema.optional()
1685
1732
  });
1686
- var AcquireAgentRunSchema = z7.object({
1733
+ var AcquireAgentRunSchema = z6.object({
1687
1734
  conversationId: AgentRecordIdSchema,
1688
1735
  runId: AgentRecordIdSchema,
1689
1736
  expectedRevision: AgentRecordVersionSchema,
1690
- ownerId: z7.string().min(1)
1737
+ ownerId: z6.string().min(1)
1691
1738
  });
1692
- var CheckpointRunAssistantSchema = z7.object({
1739
+ var CheckpointRunAssistantSchema = z6.object({
1693
1740
  conversationId: AgentRecordIdSchema,
1694
1741
  runId: AgentRecordIdSchema,
1695
1742
  expectedRevision: AgentRecordVersionSchema,
1696
- ownerId: z7.string().min(1),
1743
+ ownerId: z6.string().min(1),
1697
1744
  assistant: AgentMessageSchema
1698
1745
  });
1699
- var CommitRunTerminalSchema = z7.object({
1746
+ var CommitRunTerminalSchema = z6.object({
1700
1747
  conversationId: AgentRecordIdSchema,
1701
1748
  runId: AgentRecordIdSchema,
1702
1749
  expectedRevision: AgentRecordVersionSchema,
1703
- ownerId: z7.string().min(1),
1750
+ ownerId: z6.string().min(1),
1704
1751
  assistant: AgentMessageSchema,
1705
1752
  reason: AgentTerminalReasonSchema,
1706
- policyName: z7.string().min(1).optional()
1753
+ policyName: z6.string().min(1).optional()
1707
1754
  });
1708
- var RequestRunInterruptSchema = z7.object({
1755
+ var RequestRunInterruptSchema = z6.object({
1709
1756
  conversationId: AgentRecordIdSchema,
1710
1757
  runId: AgentRecordIdSchema,
1711
1758
  expectedRevision: AgentRecordVersionSchema
1712
1759
  });
1713
- var RecoverAgentRunSchema = z7.object({
1760
+ var RecoverAgentRunSchema = z6.object({
1714
1761
  conversationId: AgentRecordIdSchema,
1715
1762
  runId: AgentRecordIdSchema,
1716
1763
  expectedRevision: AgentRecordVersionSchema,
1717
- action: z7.enum(["requeue", "abandon"]),
1718
- replaySafe: z7.boolean().optional()
1764
+ action: z6.enum(["requeue", "abandon"]),
1765
+ replaySafe: z6.boolean().optional()
1719
1766
  });
1720
- var ReplaceCompactedRangeSchema = z7.object({
1767
+ var ReplaceCompactedRangeSchema = z6.object({
1721
1768
  conversationId: AgentRecordIdSchema,
1722
1769
  expectedVersion: AgentRecordVersionSchema,
1723
- replacedMessageIds: z7.array(AgentRecordIdSchema).min(1),
1770
+ replacedMessageIds: z6.array(AgentRecordIdSchema).min(1),
1724
1771
  summary: AgentMessageSchema
1725
1772
  });
1726
- function emptySnapshot(conversationId) {
1727
- return AgentSnapshotSchema.parse({
1773
+ // src/agent-runtime/store-driver.ts
1774
+ import { z as z7 } from "zod";
1775
+ var AgentAdmissionIdentitySchema = z7.object({
1776
+ idempotencyKey: z7.string().min(1),
1777
+ inputMessageId: AgentRecordIdSchema,
1778
+ runId: AgentRecordIdSchema,
1779
+ assistantMessageId: AgentRecordIdSchema
1780
+ });
1781
+ var AgentStoredStateSchema = z7.object({
1782
+ schemaVersion: z7.literal(1),
1783
+ conversationId: AgentRecordIdSchema,
1784
+ version: AgentRecordVersionSchema,
1785
+ runs: z7.array(AgentRunSchema),
1786
+ admissions: z7.array(AgentAdmissionIdentitySchema)
1787
+ });
1788
+ var AgentHistoryMutationSchema = z7.discriminatedUnion("type", [
1789
+ z7.object({ type: z7.literal("admit"), input: AgentMessageSchema }),
1790
+ z7.object({
1791
+ type: z7.literal("upsert-assistant"),
1792
+ message: AgentMessageSchema
1793
+ }),
1794
+ z7.object({
1795
+ type: z7.literal("replace-compacted-range"),
1796
+ replacedMessageIds: z7.array(AgentRecordIdSchema).min(1),
1797
+ summary: AgentMessageSchema
1798
+ })
1799
+ ]);
1800
+ var AgentRecoverableDescriptorSchema = z7.object({
1801
+ conversationId: AgentRecordIdSchema,
1802
+ run: AgentRunSchema
1803
+ });
1804
+ var AgentRecoverablePageSchema = z7.object({
1805
+ items: z7.array(AgentRecoverableDescriptorSchema),
1806
+ nextCursor: z7.string().min(1).optional()
1807
+ });
1808
+ var AgentRecoverableScanInputSchema = z7.object({
1809
+ cursor: z7.string().min(1).optional(),
1810
+ limit: z7.number().int().min(1).max(1000)
1811
+ });
1812
+ function emptyState(conversationId) {
1813
+ return AgentStoredStateSchema.parse({
1728
1814
  schemaVersion: 1,
1729
1815
  conversationId,
1730
1816
  version: 0,
1731
- messages: [],
1732
- runs: []
1817
+ runs: [],
1818
+ admissions: []
1733
1819
  });
1734
1820
  }
1735
- function cloneSnapshot(snapshot) {
1736
- return AgentSnapshotSchema.parse(structuredClone(snapshot));
1821
+ function snapshotOf(state, messages) {
1822
+ validateAggregate(state, messages);
1823
+ return AgentSnapshotSchema.parse({
1824
+ schemaVersion: 1,
1825
+ conversationId: state.conversationId,
1826
+ version: state.version,
1827
+ messages,
1828
+ runs: state.runs
1829
+ });
1830
+ }
1831
+ function validateAggregate(state, messages) {
1832
+ const runIds = new Set;
1833
+ const assistantIds = new Set;
1834
+ const messageIds = new Set;
1835
+ const idempotencyKeys = new Set;
1836
+ const admittedInputIds = new Set;
1837
+ for (const run of state.runs) {
1838
+ if (run.conversationId !== state.conversationId || runIds.has(run.id) || assistantIds.has(run.assistantMessageId)) {
1839
+ throw new TypeError("Stored agent state contains inconsistent run identities");
1840
+ }
1841
+ runIds.add(run.id);
1842
+ assistantIds.add(run.assistantMessageId);
1843
+ }
1844
+ for (const message of messages) {
1845
+ if (message.conversationId !== state.conversationId || messageIds.has(message.id)) {
1846
+ throw new TypeError("Stored agent history contains inconsistent message identities");
1847
+ }
1848
+ messageIds.add(message.id);
1849
+ if (assistantIds.has(message.id) && message.runId === undefined) {
1850
+ throw new TypeError("Stored history occupies a reserved assistant identity");
1851
+ }
1852
+ if (message.runId !== undefined) {
1853
+ const run = state.runs.find((candidate) => candidate.id === message.runId);
1854
+ if (!run || message.role !== "assistant" || run.assistantMessageId !== message.id) {
1855
+ throw new TypeError("Stored assistant history does not match its reserved run identity");
1856
+ }
1857
+ }
1858
+ }
1859
+ for (const admission of state.admissions) {
1860
+ const run = state.runs.find((candidate) => candidate.id === admission.runId);
1861
+ if (idempotencyKeys.has(admission.idempotencyKey) || admittedInputIds.has(admission.inputMessageId) || !run || run.assistantMessageId !== admission.assistantMessageId || !run.inputMessageIds.includes(admission.inputMessageId)) {
1862
+ throw new TypeError("Stored admission identity is inconsistent with its assigned run");
1863
+ }
1864
+ idempotencyKeys.add(admission.idempotencyKey);
1865
+ admittedInputIds.add(admission.inputMessageId);
1866
+ }
1867
+ }
1868
+ function recoverableDescriptors(state) {
1869
+ return state.runs.filter((run) => ["queued", "running", "interrupt_requested"].includes(run.state)).map((run) => ({ conversationId: state.conversationId, run }));
1870
+ }
1871
+ var RecoverableCursorSchema = z7.tuple([AgentRecordIdSchema, AgentRecordIdSchema]);
1872
+ function recoverableCursor(input) {
1873
+ return JSON.stringify([input.conversationId, input.run.id]);
1874
+ }
1875
+ function parseRecoverableCursor(cursor) {
1876
+ return RecoverableCursorSchema.parse(JSON.parse(cursor));
1737
1877
  }
1738
1878
  function replaceRun(runs, next) {
1739
1879
  return runs.map((run) => run.id === next.id ? next : run);
1740
1880
  }
1741
1881
  function replaceMessage(messages, next) {
1742
- const exists = messages.some((message) => message.id === next.id);
1743
- if (!exists)
1744
- return [...messages, next];
1745
- return messages.map((message) => message.id === next.id ? next : message);
1882
+ return messages.some((message) => message.id === next.id) ? messages.map((message) => message.id === next.id ? next : message) : [...messages, next];
1883
+ }
1884
+ function conflict(actualVersion) {
1885
+ return { outcome: "conflict", actualVersion };
1746
1886
  }
1747
1887
  function terminalState(reason) {
1748
1888
  if (reason === "success" || reason === "policy_stop")
@@ -1764,217 +1904,426 @@ function terminalMessageStatus(reason) {
1764
1904
  }
1765
1905
  return "failed";
1766
1906
  }
1767
- function createMemoryAgentRuntimeStore() {
1768
- const conversations = new Map;
1769
- const get = (conversationId) => {
1770
- const existing = conversations.get(conversationId);
1771
- if (existing)
1772
- return existing;
1773
- const created = { snapshot: emptySnapshot(conversationId), idempotency: new Map };
1774
- conversations.set(conversationId, created);
1775
- return created;
1776
- };
1777
- const conflict = (actualVersion) => ({
1778
- outcome: "conflict",
1779
- actualVersion
1780
- });
1781
- const apply = (entry, snapshot) => {
1782
- entry.snapshot = AgentSnapshotSchema.parse(snapshot);
1783
- return { outcome: "applied", snapshot: cloneSnapshot(entry.snapshot) };
1784
- };
1907
+ function applied(current, admissions, input, historyMutation) {
1785
1908
  return {
1786
- async loadSnapshot(conversationId) {
1787
- return cloneSnapshot(get(conversationId).snapshot);
1788
- },
1789
- async acceptInputAndAssignRun(rawInput) {
1790
- const input = AcceptInputAndAssignRunSchema.parse(rawInput);
1791
- const entry = get(input.input.conversationId);
1792
- const duplicateRunId = entry.idempotency.get(input.idempotencyKey);
1793
- if (duplicateRunId !== undefined) {
1794
- return {
1795
- outcome: "duplicate",
1796
- runId: duplicateRunId,
1797
- snapshot: cloneSnapshot(entry.snapshot)
1798
- };
1799
- }
1800
- if (input.expectedVersion !== undefined && input.expectedVersion !== entry.snapshot.version) {
1801
- return conflict(entry.snapshot.version);
1802
- }
1803
- const coalescedRun = input.coalesceIntoRunId ? entry.snapshot.runs.find((candidate) => candidate.id === input.coalesceIntoRunId) : undefined;
1804
- if (input.coalesceIntoRunId !== undefined && (!coalescedRun || coalescedRun.conversationId !== input.input.conversationId || coalescedRun.state !== "queued" || coalescedRun.ownerId !== undefined || coalescedRun.terminalReason !== undefined)) {
1805
- return coalescedRun ? conflict(coalescedRun.revision) : { outcome: "not_found" };
1806
- }
1807
- if (input.run.conversationId !== input.input.conversationId || input.run.inputMessageIds.length !== 1 || input.run.inputMessageIds[0] !== input.input.id || input.run.state !== "queued" || input.run.revision !== 0 || input.run.ownerId !== undefined || input.run.terminalReason !== undefined || input.run.terminalPolicyName !== undefined || input.input.role !== "user" || input.input.status !== "committed" || input.input.runId !== undefined || entry.snapshot.messages.some((message) => message.id === input.input.id) || !coalescedRun && (input.run.assistantMessageId === input.input.id || entry.snapshot.runs.some((candidate) => candidate.id === input.run.id) || entry.snapshot.runs.some((candidate) => candidate.assistantMessageId === input.run.assistantMessageId) || entry.snapshot.messages.some((message) => message.id === input.run.assistantMessageId))) {
1808
- throw new TypeError("Input and queued run do not form one valid assignment");
1909
+ outcome: "applied",
1910
+ snapshot: AgentSnapshotSchema.parse({
1911
+ ...current,
1912
+ version: current.version + 1,
1913
+ runs: input.runs ?? current.runs,
1914
+ messages: input.messages ?? current.messages
1915
+ }),
1916
+ admissions,
1917
+ ...historyMutation && { historyMutation }
1918
+ };
1919
+ }
1920
+ function reduceStore(current, currentAdmissions, operation, duplicateInput) {
1921
+ if (operation.type === "accept") {
1922
+ const input = operation.input;
1923
+ const duplicate = currentAdmissions.find((candidate) => candidate.idempotencyKey === input.idempotencyKey);
1924
+ if (duplicate) {
1925
+ if (!duplicateInput) {
1926
+ throw new Error("Duplicate admission input is unavailable from canonical history");
1809
1927
  }
1810
- const assignedRun = coalescedRun ? AgentRunSchema.parse({
1811
- ...coalescedRun,
1812
- inputMessageIds: [...coalescedRun.inputMessageIds, input.input.id],
1813
- revision: coalescedRun.revision + 1,
1928
+ return {
1929
+ outcome: "duplicate",
1930
+ input: duplicateInput,
1931
+ inputMessageId: duplicate.inputMessageId,
1932
+ runId: duplicate.runId,
1933
+ assistantMessageId: duplicate.assistantMessageId,
1934
+ snapshot: current
1935
+ };
1936
+ }
1937
+ if (input.expectedVersion !== undefined && input.expectedVersion !== current.version) {
1938
+ return conflict(current.version);
1939
+ }
1940
+ const coalescedRun = input.coalesceIntoRunId ? current.runs.find((candidate) => candidate.id === input.coalesceIntoRunId) : undefined;
1941
+ if (input.coalesceIntoRunId !== undefined && (!coalescedRun || coalescedRun.conversationId !== input.input.conversationId || coalescedRun.state !== "queued" || coalescedRun.ownerId !== undefined || coalescedRun.terminalReason !== undefined)) {
1942
+ return coalescedRun ? conflict(coalescedRun.revision) : { outcome: "not_found" };
1943
+ }
1944
+ if (input.run.conversationId !== input.input.conversationId || input.run.inputMessageIds.length !== 1 || input.run.inputMessageIds[0] !== input.input.id || input.run.state !== "queued" || input.run.revision !== 0 || input.run.ownerId !== undefined || input.run.terminalReason !== undefined || input.run.terminalPolicyName !== undefined || input.input.role !== "user" || input.input.status !== "committed" || input.input.runId !== undefined || current.messages.some((message) => message.id === input.input.id) || coalescedRun !== undefined && input.input.id === coalescedRun.assistantMessageId || !coalescedRun && (input.run.assistantMessageId === input.input.id || current.runs.some((candidate) => candidate.id === input.run.id) || current.runs.some((candidate) => candidate.assistantMessageId === input.run.assistantMessageId) || current.messages.some((message) => message.id === input.run.assistantMessageId))) {
1945
+ throw new TypeError("Input and queued run do not form one valid assignment");
1946
+ }
1947
+ const assignedRun = coalescedRun ? AgentRunSchema.parse({
1948
+ ...coalescedRun,
1949
+ inputMessageIds: [...coalescedRun.inputMessageIds, input.input.id],
1950
+ revision: coalescedRun.revision + 1,
1951
+ updatedAt: new Date().toISOString()
1952
+ }) : input.run;
1953
+ const admission = AgentAdmissionIdentitySchema.parse({
1954
+ idempotencyKey: input.idempotencyKey,
1955
+ inputMessageId: input.input.id,
1956
+ runId: assignedRun.id,
1957
+ assistantMessageId: assignedRun.assistantMessageId
1958
+ });
1959
+ return applied(current, [...currentAdmissions, admission], {
1960
+ messages: [...current.messages, input.input],
1961
+ runs: coalescedRun ? replaceRun(current.runs, assignedRun) : [...current.runs, assignedRun]
1962
+ }, { type: "admit", input: input.input });
1963
+ }
1964
+ const conversationId = operation.input.conversationId;
1965
+ const run = operation.type === "compact" ? undefined : current.runs.find((candidate) => candidate.id === operation.input.runId);
1966
+ if (operation.type !== "compact" && !run)
1967
+ return { outcome: "not_found" };
1968
+ if (operation.type === "acquire" && run) {
1969
+ const runPosition = current.runs.findIndex((candidate) => candidate.id === run.id);
1970
+ const acquisitionBlocked = current.runs.some((candidate, index) => candidate.id !== run.id && (candidate.state === "running" || candidate.state === "interrupt_requested" || index < runPosition && candidate.state === "queued"));
1971
+ if (run.revision !== operation.input.expectedRevision || run.state !== "queued" || acquisitionBlocked) {
1972
+ return conflict(run.revision);
1973
+ }
1974
+ const next = AgentRunSchema.parse({
1975
+ ...run,
1976
+ state: "running",
1977
+ ownerId: operation.input.ownerId,
1978
+ revision: run.revision + 1,
1979
+ updatedAt: new Date().toISOString()
1980
+ });
1981
+ return applied(current, currentAdmissions, {
1982
+ runs: replaceRun(current.runs, next)
1983
+ });
1984
+ }
1985
+ if (operation.type === "checkpoint" && run) {
1986
+ const input = operation.input;
1987
+ if (run.revision !== input.expectedRevision || run.state !== "running" || run.ownerId !== input.ownerId || input.assistant.runId !== run.id || input.assistant.id !== run.assistantMessageId || input.assistant.conversationId !== run.conversationId || input.assistant.role !== "assistant" || input.assistant.status !== "streaming") {
1988
+ return conflict(run.revision);
1989
+ }
1990
+ const next = AgentRunSchema.parse({
1991
+ ...run,
1992
+ revision: run.revision + 1,
1993
+ updatedAt: new Date().toISOString()
1994
+ });
1995
+ return applied(current, currentAdmissions, {
1996
+ runs: replaceRun(current.runs, next),
1997
+ messages: replaceMessage(current.messages, input.assistant)
1998
+ }, { type: "upsert-assistant", message: input.assistant });
1999
+ }
2000
+ if (operation.type === "interrupt" && run) {
2001
+ if (run.revision !== operation.input.expectedRevision || run.state !== "running") {
2002
+ return conflict(run.revision);
2003
+ }
2004
+ const next = AgentRunSchema.parse({
2005
+ ...run,
2006
+ state: "interrupt_requested",
2007
+ revision: run.revision + 1,
2008
+ updatedAt: new Date().toISOString()
2009
+ });
2010
+ return applied(current, currentAdmissions, {
2011
+ runs: replaceRun(current.runs, next)
2012
+ });
2013
+ }
2014
+ if (operation.type === "recover" && run) {
2015
+ const input = operation.input;
2016
+ if (run.revision !== input.expectedRevision || !["queued", "running", "interrupt_requested"].includes(run.state)) {
2017
+ return conflict(run.revision);
2018
+ }
2019
+ if (input.action === "requeue" && run.state !== "queued" && input.replaySafe !== true) {
2020
+ throw new TypeError("Recovering an acquired run requires explicit replaySafe evidence");
2021
+ }
2022
+ const next = AgentRunSchema.parse({
2023
+ schemaVersion: 1,
2024
+ id: run.id,
2025
+ conversationId: run.conversationId,
2026
+ inputMessageIds: run.inputMessageIds,
2027
+ assistantMessageId: run.assistantMessageId,
2028
+ state: input.action === "requeue" ? "queued" : "abandoned",
2029
+ revision: run.revision + 1,
2030
+ ...input.action === "abandon" && { terminalReason: "abandoned" },
2031
+ createdAt: run.createdAt,
2032
+ updatedAt: new Date().toISOString()
2033
+ });
2034
+ if (input.action === "abandon") {
2035
+ const existingAssistant = current.messages.find((message) => message.id === run.assistantMessageId);
2036
+ const assistant = AgentMessageSchema.parse({
2037
+ ...existingAssistant ?? {
2038
+ schemaVersion: 1,
2039
+ id: run.assistantMessageId,
2040
+ conversationId: run.conversationId,
2041
+ runId: run.id,
2042
+ role: "assistant",
2043
+ parts: [],
2044
+ createdAt: run.createdAt
2045
+ },
2046
+ status: "failed",
1814
2047
  updatedAt: new Date().toISOString()
1815
- }) : input.run;
1816
- const next = AgentSnapshotSchema.parse({
1817
- ...entry.snapshot,
1818
- version: entry.snapshot.version + 1,
1819
- messages: [...entry.snapshot.messages, input.input],
1820
- runs: coalescedRun ? replaceRun(entry.snapshot.runs, assignedRun) : [...entry.snapshot.runs, assignedRun]
1821
2048
  });
1822
- entry.idempotency.set(input.idempotencyKey, assignedRun.id);
1823
- return apply(entry, next);
2049
+ return applied(current, currentAdmissions, {
2050
+ runs: replaceRun(current.runs, next),
2051
+ messages: replaceMessage(current.messages, assistant)
2052
+ }, { type: "upsert-assistant", message: assistant });
2053
+ }
2054
+ return applied(current, currentAdmissions, {
2055
+ runs: replaceRun(current.runs, next)
2056
+ });
2057
+ }
2058
+ if (operation.type === "terminal" && run) {
2059
+ const input = operation.input;
2060
+ if (run.revision !== input.expectedRevision || run.state !== "running" && run.state !== "interrupt_requested" || run.ownerId !== input.ownerId || input.assistant.runId !== run.id || input.assistant.id !== run.assistantMessageId || input.assistant.conversationId !== run.conversationId || input.assistant.role !== "assistant" || input.assistant.status !== terminalMessageStatus(input.reason)) {
2061
+ return conflict(run.revision);
2062
+ }
2063
+ const next = AgentRunSchema.parse({
2064
+ ...run,
2065
+ state: terminalState(input.reason),
2066
+ terminalReason: input.reason,
2067
+ ...input.policyName && { terminalPolicyName: input.policyName },
2068
+ revision: run.revision + 1,
2069
+ updatedAt: new Date().toISOString()
2070
+ });
2071
+ return applied(current, currentAdmissions, {
2072
+ runs: replaceRun(current.runs, next),
2073
+ messages: replaceMessage(current.messages, input.assistant)
2074
+ }, { type: "upsert-assistant", message: input.assistant });
2075
+ }
2076
+ if (operation.type === "compact") {
2077
+ const input = operation.input;
2078
+ if (current.conversationId !== conversationId)
2079
+ return { outcome: "not_found" };
2080
+ if (current.version !== input.expectedVersion)
2081
+ return conflict(current.version);
2082
+ const replaced = new Set(input.replacedMessageIds);
2083
+ if (!input.replacedMessageIds.every((id) => current.messages.some((m) => m.id === id))) {
2084
+ return { outcome: "not_found" };
2085
+ }
2086
+ const positions = current.messages.map((message, index) => replaced.has(message.id) ? index : undefined).filter((index) => index !== undefined);
2087
+ const first = positions[0];
2088
+ if (first === undefined || positions.some((position, offset) => position !== first + offset) || input.summary.conversationId !== input.conversationId || input.summary.runId !== undefined || input.summary.role !== "summary" || input.summary.status !== "committed" || current.messages.some((message) => message.id === input.summary.id) || current.runs.some((candidate) => candidate.assistantMessageId === input.summary.id)) {
2089
+ throw new TypeError("Compaction replacement must be one valid contiguous history range");
2090
+ }
2091
+ const messages = [
2092
+ ...current.messages.slice(0, first),
2093
+ input.summary,
2094
+ ...current.messages.slice(first + positions.length)
2095
+ ];
2096
+ return applied(current, currentAdmissions, { messages }, {
2097
+ type: "replace-compacted-range",
2098
+ replacedMessageIds: input.replacedMessageIds,
2099
+ summary: input.summary
2100
+ });
2101
+ }
2102
+ return { outcome: "not_found" };
2103
+ }
2104
+ function operationConversationId(operation) {
2105
+ return operation.type === "accept" ? operation.input.input.conversationId : operation.input.conversationId;
2106
+ }
2107
+ function createAgentRuntimeStore(driver) {
2108
+ const loadSnapshot = (conversationId) => driver.transaction(async (transaction) => {
2109
+ const [stored, messages] = await Promise.all([
2110
+ driver.state.load(transaction, conversationId),
2111
+ driver.history.load(transaction, conversationId)
2112
+ ]);
2113
+ return snapshotOf(stored ?? emptyState(conversationId), messages);
2114
+ });
2115
+ const mutate = (operation) => driver.transaction(async (transaction) => {
2116
+ const conversationId = operationConversationId(operation);
2117
+ const [stored, messages] = await Promise.all([
2118
+ driver.state.load(transaction, conversationId),
2119
+ driver.history.load(transaction, conversationId)
2120
+ ]);
2121
+ const state = AgentStoredStateSchema.parse(stored ?? emptyState(conversationId));
2122
+ const current = snapshotOf(state, messages);
2123
+ const duplicateIdentity = operation.type === "accept" ? state.admissions.find((candidate) => candidate.idempotencyKey === operation.input.idempotencyKey) : undefined;
2124
+ const duplicateInput = duplicateIdentity ? await driver.history.loadById(transaction, {
2125
+ conversationId,
2126
+ messageId: duplicateIdentity.inputMessageId
2127
+ }) : undefined;
2128
+ if (duplicateIdentity && duplicateInput && (duplicateInput.id !== duplicateIdentity.inputMessageId || duplicateInput.conversationId !== conversationId || duplicateInput.role !== "user" || duplicateInput.status !== "committed" || duplicateInput.runId !== undefined)) {
2129
+ throw new TypeError("Canonical duplicate input does not match its admission identity");
2130
+ }
2131
+ const reduced = reduceStore(current, state.admissions, operation, duplicateInput);
2132
+ if (reduced.outcome !== "applied")
2133
+ return reduced;
2134
+ const nextState = AgentStoredStateSchema.parse({
2135
+ schemaVersion: 1,
2136
+ conversationId,
2137
+ version: reduced.snapshot.version,
2138
+ runs: reduced.snapshot.runs,
2139
+ admissions: reduced.admissions
2140
+ });
2141
+ const outcome = await driver.state.compareAndSwap(transaction, {
2142
+ conversationId,
2143
+ expectedVersion: current.version,
2144
+ next: nextState,
2145
+ recoverable: recoverableDescriptors(nextState)
2146
+ });
2147
+ if (outcome.outcome === "conflict")
2148
+ return conflict(outcome.actualVersion);
2149
+ if (reduced.historyMutation) {
2150
+ await driver.history.apply(transaction, reduced.historyMutation);
2151
+ }
2152
+ return { outcome: "applied", snapshot: reduced.snapshot };
2153
+ });
2154
+ return {
2155
+ loadSnapshot,
2156
+ acceptInputAndAssignRun: (input) => mutate({
2157
+ type: "accept",
2158
+ input: AcceptInputAndAssignRunSchema.parse(input)
2159
+ }),
2160
+ acquireRun: (input) => mutate({ type: "acquire", input: AcquireAgentRunSchema.parse(input) }),
2161
+ checkpointRunAssistant: (input) => mutate({
2162
+ type: "checkpoint",
2163
+ input: CheckpointRunAssistantSchema.parse(input)
2164
+ }),
2165
+ requestRunInterrupt: (input) => mutate({
2166
+ type: "interrupt",
2167
+ input: RequestRunInterruptSchema.parse(input)
2168
+ }),
2169
+ recoverRun: (input) => mutate({ type: "recover", input: RecoverAgentRunSchema.parse(input) }),
2170
+ commitRunTerminal: (input) => mutate({ type: "terminal", input: CommitRunTerminalSchema.parse(input) }),
2171
+ replaceCompactedRange: (input) => mutate({
2172
+ type: "compact",
2173
+ input: ReplaceCompactedRangeSchema.parse(input)
2174
+ }),
2175
+ async scanRecoverable() {
2176
+ const snapshots = [];
2177
+ const seenConversationIds = new Set;
2178
+ let cursor;
2179
+ do {
2180
+ const page = AgentRecoverablePageSchema.parse(await driver.scanRecoverable({
2181
+ ...cursor && { cursor },
2182
+ limit: 100
2183
+ }));
2184
+ const conversationIds = [
2185
+ ...new Set(page.items.map((item) => item.conversationId))
2186
+ ].filter((conversationId) => !seenConversationIds.has(conversationId));
2187
+ for (const conversationId of conversationIds)
2188
+ seenConversationIds.add(conversationId);
2189
+ snapshots.push(...await Promise.all(conversationIds.map(loadSnapshot)));
2190
+ cursor = page.nextCursor;
2191
+ } while (cursor !== undefined);
2192
+ return snapshots;
1824
2193
  },
1825
- async acquireRun(rawInput) {
1826
- const input = AcquireAgentRunSchema.parse(rawInput);
1827
- const entry = get(input.conversationId);
1828
- const run = entry.snapshot.runs.find((candidate) => candidate.id === input.runId);
1829
- if (!run)
1830
- return { outcome: "not_found" };
1831
- if (run.revision !== input.expectedRevision || run.state !== "queued") {
1832
- return conflict(run.revision);
1833
- }
1834
- const nextRun = AgentRunSchema.parse({
1835
- ...run,
1836
- state: "running",
1837
- ownerId: input.ownerId,
1838
- revision: run.revision + 1,
1839
- updatedAt: new Date().toISOString()
2194
+ async scanRecoverablePage(input) {
2195
+ const parsed = AgentRecoverableScanInputSchema.parse(input);
2196
+ return AgentRecoverablePageSchema.parse(await driver.scanRecoverable(parsed));
2197
+ }
2198
+ };
2199
+ }
2200
+ function cloneStateMap(source) {
2201
+ return new Map([...source].map(([key, value]) => [
2202
+ key,
2203
+ AgentStoredStateSchema.parse(structuredClone(value))
2204
+ ]));
2205
+ }
2206
+ function cloneHistoryMap(source) {
2207
+ return new Map([...source].map(([key, value]) => [
2208
+ key,
2209
+ value.map((message) => AgentMessageSchema.parse(structuredClone(message)))
2210
+ ]));
2211
+ }
2212
+ function createMemoryAgentRuntimeStore() {
2213
+ let states = new Map;
2214
+ let histories = new Map;
2215
+ let archivedMessages = new Map;
2216
+ let transactionTail = Promise.resolve();
2217
+ const driver = {
2218
+ async transaction(work) {
2219
+ const previous = transactionTail;
2220
+ const release = Promise.withResolvers();
2221
+ transactionTail = previous.catch(() => {
2222
+ return;
2223
+ }).then(() => release.promise);
2224
+ await previous.catch(() => {
2225
+ return;
1840
2226
  });
1841
- return apply(entry, AgentSnapshotSchema.parse({
1842
- ...entry.snapshot,
1843
- version: entry.snapshot.version + 1,
1844
- runs: replaceRun(entry.snapshot.runs, nextRun)
1845
- }));
1846
- },
1847
- async checkpointRunAssistant(rawInput) {
1848
- const input = CheckpointRunAssistantSchema.parse(rawInput);
1849
- const entry = get(input.conversationId);
1850
- const run = entry.snapshot.runs.find((candidate) => candidate.id === input.runId);
1851
- if (!run)
1852
- return { outcome: "not_found" };
1853
- if (run.revision !== input.expectedRevision || run.state !== "running" || run.ownerId !== input.ownerId || input.assistant.runId !== run.id || input.assistant.id !== run.assistantMessageId || input.assistant.conversationId !== run.conversationId || input.assistant.role !== "assistant" || input.assistant.status !== "streaming") {
1854
- return conflict(run.revision);
2227
+ const transaction = {
2228
+ states: cloneStateMap(states),
2229
+ histories: cloneHistoryMap(histories),
2230
+ archivedMessages: new Map([...archivedMessages].map(([conversationId, messages]) => [
2231
+ conversationId,
2232
+ new Map([...messages].map(([messageId, message]) => [
2233
+ messageId,
2234
+ AgentMessageSchema.parse(structuredClone(message))
2235
+ ]))
2236
+ ]))
2237
+ };
2238
+ try {
2239
+ const result = await work(transaction);
2240
+ states = transaction.states;
2241
+ histories = transaction.histories;
2242
+ archivedMessages = transaction.archivedMessages;
2243
+ return result;
2244
+ } finally {
2245
+ release.resolve();
1855
2246
  }
1856
- const nextRun = AgentRunSchema.parse({
1857
- ...run,
1858
- revision: run.revision + 1,
1859
- updatedAt: new Date().toISOString()
1860
- });
1861
- return apply(entry, AgentSnapshotSchema.parse({
1862
- ...entry.snapshot,
1863
- version: entry.snapshot.version + 1,
1864
- messages: replaceMessage(entry.snapshot.messages, input.assistant),
1865
- runs: replaceRun(entry.snapshot.runs, nextRun)
1866
- }));
1867
2247
  },
1868
- async requestRunInterrupt(rawInput) {
1869
- const input = RequestRunInterruptSchema.parse(rawInput);
1870
- const entry = get(input.conversationId);
1871
- const run = entry.snapshot.runs.find((candidate) => candidate.id === input.runId);
1872
- if (!run)
1873
- return { outcome: "not_found" };
1874
- if (run.revision !== input.expectedRevision || run.state !== "running") {
1875
- return conflict(run.revision);
2248
+ state: {
2249
+ async load(transaction, conversationId) {
2250
+ const state = transaction.states.get(conversationId);
2251
+ return state ? AgentStoredStateSchema.parse(structuredClone(state)) : undefined;
2252
+ },
2253
+ async compareAndSwap(transaction, input) {
2254
+ const current = transaction.states.get(input.conversationId);
2255
+ const actualVersion = current?.version ?? 0;
2256
+ if (actualVersion !== input.expectedVersion) {
2257
+ return { outcome: "conflict", actualVersion };
2258
+ }
2259
+ transaction.states.set(input.conversationId, AgentStoredStateSchema.parse(structuredClone(input.next)));
2260
+ return { outcome: "applied" };
1876
2261
  }
1877
- const nextRun = AgentRunSchema.parse({
1878
- ...run,
1879
- state: "interrupt_requested",
1880
- revision: run.revision + 1,
1881
- updatedAt: new Date().toISOString()
1882
- });
1883
- return apply(entry, AgentSnapshotSchema.parse({
1884
- ...entry.snapshot,
1885
- version: entry.snapshot.version + 1,
1886
- runs: replaceRun(entry.snapshot.runs, nextRun)
1887
- }));
1888
2262
  },
1889
- async recoverRun(rawInput) {
1890
- const input = RecoverAgentRunSchema.parse(rawInput);
1891
- const entry = get(input.conversationId);
1892
- const run = entry.snapshot.runs.find((candidate) => candidate.id === input.runId);
1893
- if (!run)
1894
- return { outcome: "not_found" };
1895
- if (run.revision !== input.expectedRevision || !["queued", "running", "interrupt_requested"].includes(run.state)) {
1896
- return conflict(run.revision);
1897
- }
1898
- if (input.action === "requeue" && run.state !== "queued" && input.replaySafe !== true) {
1899
- throw new TypeError("Recovering an acquired run requires explicit replaySafe evidence");
2263
+ history: {
2264
+ async load(transaction, conversationId) {
2265
+ return (transaction.histories.get(conversationId) ?? []).map((message) => AgentMessageSchema.parse(structuredClone(message)));
2266
+ },
2267
+ async loadById(transaction, input) {
2268
+ const active = (transaction.histories.get(input.conversationId) ?? []).find((message2) => message2.id === input.messageId);
2269
+ const message = active ?? transaction.archivedMessages.get(input.conversationId)?.get(input.messageId);
2270
+ return message ? AgentMessageSchema.parse(structuredClone(message)) : undefined;
2271
+ },
2272
+ async apply(transaction, rawMutation) {
2273
+ const mutation = AgentHistoryMutationSchema.parse(rawMutation);
2274
+ const conversationId = mutation.type === "admit" ? mutation.input.conversationId : mutation.type === "upsert-assistant" ? mutation.message.conversationId : mutation.summary.conversationId;
2275
+ const current = transaction.histories.get(conversationId) ?? [];
2276
+ if (mutation.type === "admit") {
2277
+ transaction.histories.set(conversationId, [...current, mutation.input]);
2278
+ return;
2279
+ }
2280
+ if (mutation.type === "upsert-assistant") {
2281
+ transaction.histories.set(conversationId, replaceMessage(current, mutation.message));
2282
+ return;
2283
+ }
2284
+ const replaced = new Set(mutation.replacedMessageIds);
2285
+ const positions = current.map((message, index) => replaced.has(message.id) ? index : undefined).filter((index) => index !== undefined);
2286
+ const first = positions[0];
2287
+ if (first === undefined)
2288
+ throw new Error("Compaction history range disappeared");
2289
+ const archive = transaction.archivedMessages.get(conversationId) ?? new Map;
2290
+ for (const message of current.filter((candidate) => replaced.has(candidate.id))) {
2291
+ archive.set(message.id, AgentMessageSchema.parse(structuredClone(message)));
2292
+ }
2293
+ transaction.archivedMessages.set(conversationId, archive);
2294
+ transaction.histories.set(conversationId, [
2295
+ ...current.slice(0, first),
2296
+ mutation.summary,
2297
+ ...current.slice(first + positions.length)
2298
+ ]);
1900
2299
  }
1901
- const nextRun = AgentRunSchema.parse({
1902
- schemaVersion: 1,
1903
- id: run.id,
1904
- conversationId: run.conversationId,
1905
- inputMessageIds: run.inputMessageIds,
1906
- assistantMessageId: run.assistantMessageId,
1907
- state: input.action === "requeue" ? "queued" : "abandoned",
1908
- revision: run.revision + 1,
1909
- ...input.action === "abandon" && { terminalReason: "abandoned" },
1910
- createdAt: run.createdAt,
1911
- updatedAt: new Date().toISOString()
1912
- });
1913
- return apply(entry, AgentSnapshotSchema.parse({
1914
- ...entry.snapshot,
1915
- version: entry.snapshot.version + 1,
1916
- runs: replaceRun(entry.snapshot.runs, nextRun)
1917
- }));
1918
2300
  },
1919
- async commitRunTerminal(rawInput) {
1920
- const input = CommitRunTerminalSchema.parse(rawInput);
1921
- const entry = get(input.conversationId);
1922
- const run = entry.snapshot.runs.find((candidate) => candidate.id === input.runId);
1923
- if (!run)
1924
- return { outcome: "not_found" };
1925
- if (run.revision !== input.expectedRevision || run.state !== "running" && run.state !== "interrupt_requested" || run.ownerId !== input.ownerId || input.assistant.runId !== run.id || input.assistant.id !== run.assistantMessageId || input.assistant.conversationId !== run.conversationId || input.assistant.role !== "assistant" || input.assistant.status !== terminalMessageStatus(input.reason)) {
1926
- return conflict(run.revision);
1927
- }
1928
- const nextRun = AgentRunSchema.parse({
1929
- ...run,
1930
- state: terminalState(input.reason),
1931
- terminalReason: input.reason,
1932
- ...input.policyName && { terminalPolicyName: input.policyName },
1933
- revision: run.revision + 1,
1934
- updatedAt: new Date().toISOString()
2301
+ async scanRecoverable(input) {
2302
+ const descriptors = [...states.values()].flatMap((state) => state.runs.filter((run) => ["queued", "running", "interrupt_requested"].includes(run.state)).map((run) => ({ conversationId: state.conversationId, run }))).sort((left, right) => left.conversationId.localeCompare(right.conversationId) || left.run.id.localeCompare(right.run.id));
2303
+ const cursorTuple = input.cursor ? parseRecoverableCursor(input.cursor) : undefined;
2304
+ const start = cursorTuple ? descriptors.findIndex((item) => item.conversationId === cursorTuple[0] && item.run.id === cursorTuple[1]) + 1 : 0;
2305
+ const items = descriptors.slice(start, start + input.limit);
2306
+ const last = items.at(-1);
2307
+ const hasMore = start + items.length < descriptors.length;
2308
+ return AgentRecoverablePageSchema.parse({
2309
+ items,
2310
+ ...hasMore && last && { nextCursor: recoverableCursor(last) }
1935
2311
  });
1936
- return apply(entry, AgentSnapshotSchema.parse({
1937
- ...entry.snapshot,
1938
- version: entry.snapshot.version + 1,
1939
- messages: replaceMessage(entry.snapshot.messages, input.assistant),
1940
- runs: replaceRun(entry.snapshot.runs, nextRun)
1941
- }));
1942
- },
1943
- async replaceCompactedRange(rawInput) {
1944
- const input = ReplaceCompactedRangeSchema.parse(rawInput);
1945
- const entry = get(input.conversationId);
1946
- if (entry.snapshot.version !== input.expectedVersion) {
1947
- return conflict(entry.snapshot.version);
1948
- }
1949
- const replaced = new Set(input.replacedMessageIds);
1950
- if (!input.replacedMessageIds.every((id) => entry.snapshot.messages.some((m) => m.id === id))) {
1951
- return { outcome: "not_found" };
1952
- }
1953
- const positions = entry.snapshot.messages.map((message, index) => replaced.has(message.id) ? index : undefined).filter((index) => index !== undefined);
1954
- const first = positions[0];
1955
- if (first === undefined || positions.some((position, offset) => position !== first + offset) || input.summary.conversationId !== input.conversationId || input.summary.runId !== undefined || input.summary.role !== "summary" || input.summary.status !== "committed") {
1956
- throw new TypeError("Compaction replacement must be one valid contiguous history range");
1957
- }
1958
- const before = entry.snapshot.messages.slice(0, first);
1959
- const after = entry.snapshot.messages.slice(first + positions.length);
1960
- return apply(entry, AgentSnapshotSchema.parse({
1961
- ...entry.snapshot,
1962
- version: entry.snapshot.version + 1,
1963
- messages: [...before, input.summary, ...after]
1964
- }));
1965
- },
1966
- async scanRecoverable() {
1967
- return [...conversations.values()].filter((entry) => entry.snapshot.runs.some((run) => ["queued", "running", "interrupt_requested"].includes(run.state))).map((entry) => cloneSnapshot(entry.snapshot));
1968
2312
  }
1969
2313
  };
2314
+ return createAgentRuntimeStore(driver);
1970
2315
  }
1971
2316
  export {
1972
2317
  AcceptInputAndAssignRunSchema,
1973
2318
  AcquireAgentRunSchema,
2319
+ AgentAdmissionEventSchema,
2320
+ AgentAdmissionIdentitySchema,
2321
+ AgentAssistantPlaceholderSchema,
1974
2322
  AgentCheckpointEventSchema,
1975
2323
  AgentControlPartSchema,
1976
2324
  AgentCostValueSchema,
1977
2325
  AgentFilePartSchema,
2326
+ AgentHistoryMutationSchema,
1978
2327
  AgentJsonObjectSchema,
1979
2328
  AgentMessagePartSchema,
1980
2329
  AgentMessageRoleSchema,
@@ -1990,7 +2339,10 @@ export {
1990
2339
  AgentReasoningStartEventSchema,
1991
2340
  AgentRecordIdSchema,
1992
2341
  AgentRecordVersionSchema,
2342
+ AgentRecoverableDescriptorSchema,
2343
+ AgentRecoverablePageSchema,
1993
2344
  AgentRunEventSchema,
2345
+ AgentRunMetricsSchema,
1994
2346
  AgentRunSchema,
1995
2347
  AgentRunStateEventSchema,
1996
2348
  AgentRunStateSchema,
@@ -2002,6 +2354,7 @@ export {
2002
2354
  AgentStoreDuplicateSchema,
2003
2355
  AgentStoreMutationResultSchema,
2004
2356
  AgentStoreNotFoundSchema,
2357
+ AgentStoredStateSchema,
2005
2358
  AgentTerminalEventSchema,
2006
2359
  AgentTerminalReasonSchema,
2007
2360
  AgentTextPartSchema,
@@ -2021,6 +2374,7 @@ export {
2021
2374
  composeAgentPrompt,
2022
2375
  createAgentObservability,
2023
2376
  createAgentRuntime,
2377
+ createAgentRuntimeStore,
2024
2378
  createAgentSessionCoordinator,
2025
2379
  createAgentToolFenceLifecycle,
2026
2380
  createMemoryAgentRuntimeStore,