@bastani/atomic 0.9.35-alpha.2 → 0.9.35-alpha.3

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 (172) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/package.json +1 -1
  5. package/dist/builtin/web-access/package.json +1 -1
  6. package/dist/builtin/workflows/CHANGELOG.md +13 -0
  7. package/dist/builtin/workflows/builtin/{chunk-s7y3hw0n.js → chunk-3xffzzbg.js} +1 -1
  8. package/dist/builtin/workflows/builtin/{chunk-0d0pd4fz.js → chunk-7fvrnzhb.js} +1 -1
  9. package/dist/builtin/workflows/builtin/{chunk-119gt64q.js → chunk-8c3ae7tt.js} +8 -1
  10. package/dist/builtin/workflows/builtin/{chunk-y68758re.js → chunk-rhkg3d8e.js} +1 -1
  11. package/dist/builtin/workflows/builtin/goal.js +2 -2
  12. package/dist/builtin/workflows/builtin/index.js +3 -3
  13. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  14. package/dist/builtin/workflows/package.json +1 -1
  15. package/dist/builtin/workflows/src/extension/index.bundle.mjs +510 -35
  16. package/dist/builtin/workflows/src/index.js +87 -29
  17. package/dist/core/agent-session-accessors.d.ts.map +1 -1
  18. package/dist/core/agent-session-accessors.js +7 -1
  19. package/dist/core/agent-session-accessors.js.map +1 -1
  20. package/dist/core/agent-session-custom-message-commit.js +15 -15
  21. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  22. package/dist/core/agent-session-events.d.ts.map +1 -1
  23. package/dist/core/agent-session-events.js +4 -0
  24. package/dist/core/agent-session-events.js.map +1 -1
  25. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  26. package/dist/core/agent-session-extension-bindings.js +61 -1
  27. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  28. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  29. package/dist/core/agent-session-message-queue.js +3 -1
  30. package/dist/core/agent-session-message-queue.js.map +1 -1
  31. package/dist/core/agent-session-methods.d.ts +5 -3
  32. package/dist/core/agent-session-methods.d.ts.map +1 -1
  33. package/dist/core/agent-session-methods.js.map +1 -1
  34. package/dist/core/agent-session-persistent-custom-messages.js +1 -1
  35. package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
  36. package/dist/core/agent-session-prompt.d.ts +3 -1
  37. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  38. package/dist/core/agent-session-prompt.js +79 -9
  39. package/dist/core/agent-session-prompt.js.map +1 -1
  40. package/dist/core/agent-session-summary.d.ts.map +1 -1
  41. package/dist/core/agent-session-summary.js +17 -2
  42. package/dist/core/agent-session-summary.js.map +1 -1
  43. package/dist/core/agent-session-tree.js +1 -1
  44. package/dist/core/agent-session-tree.js.map +1 -1
  45. package/dist/core/agent-session.d.ts +1 -0
  46. package/dist/core/agent-session.d.ts.map +1 -1
  47. package/dist/core/agent-session.js +1 -0
  48. package/dist/core/agent-session.js.map +1 -1
  49. package/dist/core/auth-storage-backends.d.ts +1 -0
  50. package/dist/core/auth-storage-backends.d.ts.map +1 -1
  51. package/dist/core/auth-storage-backends.js +37 -23
  52. package/dist/core/auth-storage-backends.js.map +1 -1
  53. package/dist/core/compaction/session-summarization.d.ts +1 -0
  54. package/dist/core/compaction/session-summarization.d.ts.map +1 -1
  55. package/dist/core/compaction/session-summarization.js +7 -1
  56. package/dist/core/compaction/session-summarization.js.map +1 -1
  57. package/dist/core/extensions/agent-events.d.ts +15 -7
  58. package/dist/core/extensions/agent-events.d.ts.map +1 -1
  59. package/dist/core/extensions/agent-events.js.map +1 -1
  60. package/dist/core/extensions/context-types.d.ts +6 -0
  61. package/dist/core/extensions/context-types.d.ts.map +1 -1
  62. package/dist/core/extensions/context-types.js.map +1 -1
  63. package/dist/core/extensions/index.d.ts +1 -1
  64. package/dist/core/extensions/index.d.ts.map +1 -1
  65. package/dist/core/extensions/index.js.map +1 -1
  66. package/dist/core/extensions/runner-context.d.ts +4 -0
  67. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  68. package/dist/core/extensions/runner-context.js +8 -0
  69. package/dist/core/extensions/runner-context.js.map +1 -1
  70. package/dist/core/extensions/runner-events.d.ts +1 -1
  71. package/dist/core/extensions/runner-events.d.ts.map +1 -1
  72. package/dist/core/extensions/runner-events.js +4 -3
  73. package/dist/core/extensions/runner-events.js.map +1 -1
  74. package/dist/core/extensions/runner.d.ts +3 -1
  75. package/dist/core/extensions/runner.d.ts.map +1 -1
  76. package/dist/core/extensions/runner.js +8 -2
  77. package/dist/core/extensions/runner.js.map +1 -1
  78. package/dist/core/extensions/runtime-types.d.ts +4 -0
  79. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  80. package/dist/core/extensions/runtime-types.js.map +1 -1
  81. package/dist/core/extensions/workflow-run-control.d.ts +12 -2
  82. package/dist/core/extensions/workflow-run-control.d.ts.map +1 -1
  83. package/dist/core/extensions/workflow-run-control.js.map +1 -1
  84. package/dist/core/package-manager-resource-patterns.d.ts.map +1 -1
  85. package/dist/core/package-manager-resource-patterns.js +4 -2
  86. package/dist/core/package-manager-resource-patterns.js.map +1 -1
  87. package/dist/core/session-manager-archive.d.ts +2 -0
  88. package/dist/core/session-manager-archive.d.ts.map +1 -1
  89. package/dist/core/session-manager-archive.js +41 -19
  90. package/dist/core/session-manager-archive.js.map +1 -1
  91. package/dist/core/session-manager-core.d.ts +1 -0
  92. package/dist/core/session-manager-core.d.ts.map +1 -1
  93. package/dist/core/session-manager-core.js +8 -4
  94. package/dist/core/session-manager-core.js.map +1 -1
  95. package/dist/core/session-manager-list.d.ts.map +1 -1
  96. package/dist/core/session-manager-list.js +4 -10
  97. package/dist/core/session-manager-list.js.map +1 -1
  98. package/dist/core/session-manager-types.d.ts +2 -1
  99. package/dist/core/session-manager-types.d.ts.map +1 -1
  100. package/dist/core/session-manager-types.js.map +1 -1
  101. package/dist/core/session-manager.d.ts +1 -1
  102. package/dist/core/session-manager.d.ts.map +1 -1
  103. package/dist/core/session-manager.js.map +1 -1
  104. package/dist/core/workflow-summary-lifecycle.d.ts +4 -0
  105. package/dist/core/workflow-summary-lifecycle.d.ts.map +1 -0
  106. package/dist/core/workflow-summary-lifecycle.js +40 -0
  107. package/dist/core/workflow-summary-lifecycle.js.map +1 -0
  108. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  109. package/dist/extensions/codemode/execute.js +20 -6
  110. package/dist/extensions/codemode/execute.js.map +1 -1
  111. package/dist/extensions/mcp/cli.d.ts.map +1 -1
  112. package/dist/extensions/mcp/cli.js +4 -7
  113. package/dist/extensions/mcp/cli.js.map +1 -1
  114. package/dist/extensions/mcp/client/client.d.ts.map +1 -1
  115. package/dist/extensions/mcp/client/client.js +5 -4
  116. package/dist/extensions/mcp/client/client.js.map +1 -1
  117. package/dist/extensions/mcp/client/index.d.ts +2 -2
  118. package/dist/extensions/mcp/client/index.d.ts.map +1 -1
  119. package/dist/extensions/mcp/client/index.js.map +1 -1
  120. package/dist/extensions/mcp/client/protocol/content.d.ts +4 -1
  121. package/dist/extensions/mcp/client/protocol/content.d.ts.map +1 -1
  122. package/dist/extensions/mcp/client/protocol/content.js.map +1 -1
  123. package/dist/extensions/mcp/client/transports/streamable-http.d.ts +2 -2
  124. package/dist/extensions/mcp/client/transports/streamable-http.d.ts.map +1 -1
  125. package/dist/extensions/mcp/client/transports/streamable-http.js +7 -5
  126. package/dist/extensions/mcp/client/transports/streamable-http.js.map +1 -1
  127. package/dist/extensions/mcp/client/transports/transport.d.ts +4 -1
  128. package/dist/extensions/mcp/client/transports/transport.d.ts.map +1 -1
  129. package/dist/extensions/mcp/client/transports/transport.js.map +1 -1
  130. package/dist/extensions/mcp/index.d.ts.map +1 -1
  131. package/dist/extensions/mcp/index.js +2 -4
  132. package/dist/extensions/mcp/index.js.map +1 -1
  133. package/dist/extensions/mcp/runtime.d.ts +1 -8
  134. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  135. package/dist/extensions/mcp/runtime.js +2 -41
  136. package/dist/extensions/mcp/runtime.js.map +1 -1
  137. package/dist/extensions/mcp/tools.js +1 -1
  138. package/dist/extensions/mcp/tools.js.map +1 -1
  139. package/dist/index-extensions.d.ts +1 -1
  140. package/dist/index-extensions.d.ts.map +1 -1
  141. package/dist/index-extensions.js.map +1 -1
  142. package/dist/index.d.ts +1 -1
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js.map +1 -1
  145. package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
  146. package/dist/modes/interactive/components/session-selector-list.js +2 -1
  147. package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
  148. package/dist/modes/print-mode.d.ts.map +1 -1
  149. package/dist/modes/print-mode.js +5 -0
  150. package/dist/modes/print-mode.js.map +1 -1
  151. package/dist/modes/rpc/rpc-client-api.d.ts +7 -2
  152. package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
  153. package/dist/modes/rpc/rpc-client-api.js +13 -0
  154. package/dist/modes/rpc/rpc-client-api.js.map +1 -1
  155. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  156. package/dist/modes/rpc/rpc-command-handler.js +19 -0
  157. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  158. package/dist/modes/rpc/rpc-types.d.ts +50 -1
  159. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  160. package/dist/modes/rpc/rpc-types.js.map +1 -1
  161. package/docs/extensions/authoring.md +2 -0
  162. package/docs/extensions/events.md +9 -3
  163. package/docs/guides/non-interactive.md +2 -0
  164. package/docs/mcp-servers.md +2 -0
  165. package/docs/packages/reference.md +2 -0
  166. package/docs/rpc/protocol.md +15 -0
  167. package/docs/rpc.md +1 -0
  168. package/docs/sdk.md +9 -1
  169. package/docs/sessions.md +2 -2
  170. package/docs/workflows/operations.md +11 -3
  171. package/npm-shrinkwrap.json +32 -32
  172. package/package.json +3 -3
@@ -998,6 +998,7 @@ class InMemoryDurableBackend {
998
998
  inputs: handle.inputs,
999
999
  createdAt: handle.createdAt,
1000
1000
  status: handle.status,
1001
+ transitionClaimId: handle.transitionClaimId ?? existing?.handle.transitionClaimId,
1001
1002
  ...handle.invocationCwd !== undefined ? { invocationCwd: handle.invocationCwd } : existing?.handle.invocationCwd !== undefined ? { invocationCwd: existing.handle.invocationCwd } : {},
1002
1003
  ...handle.origin !== undefined ? { origin: handle.origin } : existing?.handle.origin !== undefined ? { origin: existing.handle.origin } : {},
1003
1004
  modelOwner: authoritativeOwner ? handle.modelOwner : existing?.handle.modelOwner ?? handle.modelOwner,
@@ -1011,7 +1012,11 @@ class InMemoryDurableBackend {
1011
1012
  completedCheckpoints,
1012
1013
  pendingPrompts,
1013
1014
  updatedAt,
1014
- ...handle.label !== undefined ? { label: handle.label } : {},
1015
+ ...(handle.label ?? existing?.handle.label) !== undefined ? { label: handle.label ?? existing?.handle.label } : {},
1016
+ ...(handle.summary ?? existing?.handle.summary) !== undefined ? {
1017
+ summary: handle.summary ?? existing?.handle.summary,
1018
+ summarizedThrough: handle.summarizedThrough ?? existing?.handle.summarizedThrough
1019
+ } : {},
1015
1020
  ...handle.rootWorkflowId !== undefined ? { rootWorkflowId: handle.rootWorkflowId } : {},
1016
1021
  ...handle.resumable !== undefined ? { resumable: handle.resumable } : {},
1017
1022
  ...workflowFailureFields(hasWorkflowFailureMetadata(handle) ? handle : handle.status === "running" ? undefined : existing?.handle),
@@ -1081,6 +1086,13 @@ class InMemoryDurableBackend {
1081
1086
  return this.stickyReceipts.get(workflowId)?.has(name) ?? false;
1082
1087
  });
1083
1088
  }
1089
+ async persistSummary(workflowId, summary, summarizedThrough) {
1090
+ const handle = this.getWorkflow(workflowId);
1091
+ if (!handle || (handle.summarizedThrough ?? -Infinity) > summarizedThrough)
1092
+ return false;
1093
+ this.registerWorkflow({ ...handle, summary, summarizedThrough });
1094
+ return true;
1095
+ }
1084
1096
  async persistPendingStageMessages(workflowId, messages, logicalRunId = workflowId) {
1085
1097
  const handle = this.getWorkflow(workflowId);
1086
1098
  if (handle === undefined)
@@ -1207,6 +1219,7 @@ class InMemoryDurableBackend {
1207
1219
  failureDisposition: undefined,
1208
1220
  failedToolNodeId: undefined,
1209
1221
  status,
1222
+ transitionClaimId: status === rec.handle.status ? rec.handle.transitionClaimId : crypto.randomUUID(),
1210
1223
  updatedAt: Math.max(Date.now(), rec.handle.updatedAt + 1),
1211
1224
  ...pendingPrompts !== undefined ? { pendingPrompts } : {},
1212
1225
  ...resumable !== undefined ? { resumable } : {},
@@ -1295,6 +1308,7 @@ class InMemoryDurableBackend {
1295
1308
  name: h.name,
1296
1309
  inputs: h.inputs,
1297
1310
  status: h.status,
1311
+ ...h.transitionClaimId !== undefined ? { transitionClaimId: h.transitionClaimId } : {},
1298
1312
  createdAt: h.createdAt,
1299
1313
  completedCheckpoints: h.completedCheckpoints,
1300
1314
  pendingPrompts: h.pendingPrompts,
@@ -1304,6 +1318,7 @@ class InMemoryDurableBackend {
1304
1318
  ...h.legacyRecoveryPending === true ? { legacyRecoveryPending: true } : {},
1305
1319
  ...h.sessionFile !== undefined ? { sessionFile: h.sessionFile } : {},
1306
1320
  ...h.label !== undefined ? { label: h.label } : {},
1321
+ ...h.summary !== undefined ? { summary: h.summary, summarizedThrough: h.summarizedThrough } : {},
1307
1322
  ...h.rootWorkflowId !== undefined ? { rootWorkflowId: h.rootWorkflowId } : {},
1308
1323
  ...h.resumable !== undefined ? { resumable: h.resumable } : {},
1309
1324
  ...workflowFailureFields(h),
@@ -1385,6 +1400,7 @@ function toResumableEntry(handle) {
1385
1400
  pendingPrompts: handle.pendingPrompts,
1386
1401
  ...handle.sessionFile !== undefined ? { sessionFile: handle.sessionFile } : {},
1387
1402
  ...handle.label !== undefined ? { label: handle.label } : {},
1403
+ ...handle.summary !== undefined ? { summary: handle.summary, summarizedThrough: handle.summarizedThrough } : {},
1388
1404
  ...handle.rootWorkflowId !== undefined ? { rootWorkflowId: handle.rootWorkflowId } : {},
1389
1405
  ...handle.resumable !== undefined ? { resumable: handle.resumable } : {},
1390
1406
  ...workflowFailureFields(handle),
@@ -4340,6 +4356,8 @@ function encodeMetadata(metadata) {
4340
4356
  ...metadata.legacyRecoveryPending === true ? { legacyRecoveryPending: true } : {},
4341
4357
  ...metadata.sessionFile !== undefined ? { sessionFile: metadata.sessionFile } : {},
4342
4358
  ...metadata.label !== undefined ? { label: metadata.label } : {},
4359
+ ...metadata.summary !== undefined ? { summary: metadata.summary } : {},
4360
+ ...metadata.summarizedThrough !== undefined ? { summarizedThrough: metadata.summarizedThrough } : {},
4343
4361
  ...metadata.rootWorkflowId !== undefined ? { rootWorkflowId: metadata.rootWorkflowId } : {},
4344
4362
  ...metadata.resumable !== undefined ? { resumable: metadata.resumable } : {},
4345
4363
  ...metadata.exited !== undefined ? { exited: metadata.exited } : {},
@@ -4401,7 +4419,7 @@ function parseDurableWorkflowMetadata(value2, workflowId) {
4401
4419
  return;
4402
4420
  const possibleStages = coercePossibleStages(serialized.possibleStages);
4403
4421
  const metadata = value2;
4404
- if (metadata.workflowId !== workflowId || typeof metadata.workflowId !== "string" || typeof metadata.name !== "string" || typeof metadata.inputs !== "object" || metadata.inputs === null || Array.isArray(metadata.inputs) || typeof metadata.status !== "string" || !isDurableWorkflowStatus(metadata.status) || typeof metadata.completedCheckpoints !== "number" || typeof metadata.createdAt !== "number" || typeof metadata.pendingPrompts !== "number" || typeof metadata.promptReservationEpoch !== "string" || typeof metadata.updatedAt !== "number" || metadata.ownerExecutorId !== undefined && typeof metadata.ownerExecutorId !== "string" || metadata.transitionClaimId !== undefined && typeof metadata.transitionClaimId !== "string" || metadata.legacyRecoveryPending !== undefined && metadata.legacyRecoveryPending !== true || metadata.sessionFile !== undefined && typeof metadata.sessionFile !== "string" || metadata.label !== undefined && typeof metadata.label !== "string" || metadata.rootWorkflowId !== undefined && typeof metadata.rootWorkflowId !== "string" || metadata.resumable !== undefined && typeof metadata.resumable !== "boolean" || metadata.exited !== undefined && typeof metadata.exited !== "boolean" || metadata.exitReason !== undefined && typeof metadata.exitReason !== "string" || metadata.error !== undefined && typeof metadata.error !== "string" || metadata.failureKind !== undefined && !isWorkflowFailureKind(metadata.failureKind) || metadata.failureCode !== undefined && !isWorkflowFailureCode(metadata.failureCode) || metadata.failureRecoverability !== undefined && !isWorkflowFailureRecoverability(metadata.failureRecoverability) || metadata.failureDisposition !== undefined && !isWorkflowFailureDisposition(metadata.failureDisposition) || metadata.failedToolNodeId !== undefined && typeof metadata.failedToolNodeId !== "string" || metadata.releasedModelOwner !== undefined && typeof metadata.releasedModelOwner !== "string" || metadata.invocationCwd !== undefined && typeof metadata.invocationCwd !== "string" || metadata.workflowCwd !== undefined && typeof metadata.workflowCwd !== "string" || metadata.repositoryRoot !== undefined && typeof metadata.repositoryRoot !== "string" || metadata.gitWorktreeRoot !== undefined && typeof metadata.gitWorktreeRoot !== "string")
4422
+ if (metadata.workflowId !== workflowId || typeof metadata.workflowId !== "string" || typeof metadata.name !== "string" || typeof metadata.inputs !== "object" || metadata.inputs === null || Array.isArray(metadata.inputs) || typeof metadata.status !== "string" || !isDurableWorkflowStatus(metadata.status) || typeof metadata.completedCheckpoints !== "number" || typeof metadata.createdAt !== "number" || typeof metadata.pendingPrompts !== "number" || typeof metadata.promptReservationEpoch !== "string" || typeof metadata.updatedAt !== "number" || metadata.ownerExecutorId !== undefined && typeof metadata.ownerExecutorId !== "string" || metadata.transitionClaimId !== undefined && typeof metadata.transitionClaimId !== "string" || metadata.legacyRecoveryPending !== undefined && metadata.legacyRecoveryPending !== true || metadata.sessionFile !== undefined && typeof metadata.sessionFile !== "string" || metadata.label !== undefined && typeof metadata.label !== "string" || metadata.summary !== undefined && typeof metadata.summary !== "string" || metadata.summarizedThrough !== undefined && (typeof metadata.summarizedThrough !== "number" || !Number.isFinite(metadata.summarizedThrough)) || metadata.rootWorkflowId !== undefined && typeof metadata.rootWorkflowId !== "string" || metadata.resumable !== undefined && typeof metadata.resumable !== "boolean" || metadata.exited !== undefined && typeof metadata.exited !== "boolean" || metadata.exitReason !== undefined && typeof metadata.exitReason !== "string" || metadata.error !== undefined && typeof metadata.error !== "string" || metadata.failureKind !== undefined && !isWorkflowFailureKind(metadata.failureKind) || metadata.failureCode !== undefined && !isWorkflowFailureCode(metadata.failureCode) || metadata.failureRecoverability !== undefined && !isWorkflowFailureRecoverability(metadata.failureRecoverability) || metadata.failureDisposition !== undefined && !isWorkflowFailureDisposition(metadata.failureDisposition) || metadata.failedToolNodeId !== undefined && typeof metadata.failedToolNodeId !== "string" || metadata.releasedModelOwner !== undefined && typeof metadata.releasedModelOwner !== "string" || metadata.invocationCwd !== undefined && typeof metadata.invocationCwd !== "string" || metadata.workflowCwd !== undefined && typeof metadata.workflowCwd !== "string" || metadata.repositoryRoot !== undefined && typeof metadata.repositoryRoot !== "string" || metadata.gitWorktreeRoot !== undefined && typeof metadata.gitWorktreeRoot !== "string")
4405
4423
  return;
4406
4424
  const { origin, possibleStages: rawPossibleStages, ...metadataWithoutOrigin } = metadata;
4407
4425
  return {
@@ -36484,9 +36502,9 @@ async function configureDbosDurableBackend(config) {
36484
36502
  backend = new DbosDurableBackend(createRealDbosHandle(sdk, mainWorkflow, checkpointWorkflow, backendFence), { checkReady });
36485
36503
  }
36486
36504
  },
36487
- shutdown: async () => {
36505
+ shutdown: async (options) => {
36488
36506
  const results = await Promise.allSettled([
36489
- sdk.shutdown(),
36507
+ sdk.shutdown(options),
36490
36508
  ...[...owner.executorFences ?? []].map((fence) => fence.close())
36491
36509
  ]);
36492
36510
  const errors = results.filter((result) => result.status === "rejected").map((result) => result.reason instanceof Error ? result.reason : new Error(String(result.reason)));
@@ -36783,6 +36801,36 @@ class DbosDurableBackend {
36783
36801
  }
36784
36802
  return false;
36785
36803
  }
36804
+ async persistSummary(workflowId, summary, summarizedThrough) {
36805
+ let persisted = false;
36806
+ await this.enqueueBestEffortWrite(workflowId, async () => {
36807
+ const handle = this.mem.getWorkflow(workflowId);
36808
+ const value2 = this.mem.toMetadata(workflowId);
36809
+ if (!handle || !value2 || !this.isWorkflowLoadable(workflowId))
36810
+ return;
36811
+ if ((handle.summarizedThrough ?? -Infinity) > summarizedThrough)
36812
+ return;
36813
+ const updatedAt = Math.max(Date.now(), handle.updatedAt + 1);
36814
+ const metadata = {
36815
+ ...this.promptReservations.metadata(workflowId, value2),
36816
+ summary,
36817
+ summarizedThrough,
36818
+ updatedAt
36819
+ };
36820
+ await this.sdk.recordStepOutput(workflowId, metadataStepName(updatedAt), encodeMetadata(metadata));
36821
+ const current = this.mem.getWorkflow(workflowId);
36822
+ if (current) {
36823
+ this.mem.registerWorkflow({
36824
+ ...current,
36825
+ summary,
36826
+ summarizedThrough,
36827
+ updatedAt: Math.max(updatedAt, current.updatedAt)
36828
+ });
36829
+ }
36830
+ persisted = true;
36831
+ });
36832
+ return persisted;
36833
+ }
36786
36834
  async persistPendingStageMessages(workflowId, messages, logicalRunId = workflowId) {
36787
36835
  let persisted = false;
36788
36836
  await this.enqueueWrite(workflowId, async () => {
@@ -40578,7 +40626,7 @@ async function shutdownDbos() {
40578
40626
  const errors = [];
40579
40627
  const actions = [
40580
40628
  ...wasReady ? [() => durability.backend.flush()] : [],
40581
- ...slot.launchPromise !== undefined ? [() => durability.shutdown()] : [],
40629
+ ...slot.launchPromise !== undefined ? [() => durability.shutdown({ deregister: true })] : [],
40582
40630
  shutdownLocalDbos
40583
40631
  ];
40584
40632
  for (const shutdown of actions) {
@@ -40594,6 +40642,7 @@ async function shutdownDbos() {
40594
40642
  slot.state = "shut_down";
40595
40643
  slot.configured = undefined;
40596
40644
  slot.active = undefined;
40645
+ slot.wrappers = undefined;
40597
40646
  }
40598
40647
  })().catch(async (error) => {
40599
40648
  slot.failure = await durabilityFailure("shutdown", error);
@@ -86933,6 +86982,13 @@ function createRunStoreMethods(context) {
86933
86982
  state.runs[index] = run;
86934
86983
  context.bumpAndNotify();
86935
86984
  },
86985
+ recordRunSummary(runId, summary, summarizedThrough) {
86986
+ const run = context.findRun(runId);
86987
+ if (!run)
86988
+ return;
86989
+ Object.assign(run, { summary, summarizedThrough });
86990
+ context.bumpAndNotify();
86991
+ },
86936
86992
  recordRunExecutionState(runId, update) {
86937
86993
  const run = context.findRun(runId);
86938
86994
  if (run === undefined || run.endedAt !== undefined)
@@ -91838,8 +91894,8 @@ function canonicalDirectory(path) {
91838
91894
  return process.platform === "win32" ? absolute.toLowerCase() : absolute;
91839
91895
  }
91840
91896
  }
91841
- function isSdkDurableRunInScope(handle, cwd) {
91842
- return cwd !== undefined && handle.invocationCwd !== undefined && canonicalDirectory(cwd) === canonicalDirectory(handle.invocationCwd) && handle.modelOwner !== undefined && (handle.rootWorkflowId === undefined || handle.rootWorkflowId === handle.workflowId);
91897
+ function isSdkDurableRunInScope(handle, cwd, canonicalize = canonicalDirectory) {
91898
+ return cwd !== undefined && handle.invocationCwd !== undefined && handle.modelOwner !== undefined && (handle.rootWorkflowId === undefined || handle.rootWorkflowId === handle.workflowId) && canonicalize(cwd) === canonicalize(handle.invocationCwd);
91843
91899
  }
91844
91900
  function isSdkCrashedRunAdoptable(handle, cwd) {
91845
91901
  return isSdkDurableRunInScope(handle, cwd) && handle.status === "running" && handle.ownerExecutorId !== undefined && handle.ownerExecutorId !== getAtomicExecutorId() && !isLiveRunningWorkflow(handle) && isDatabaseExecutor(handle.ownerExecutorId) && handle.ownerLiveness === "dead";
@@ -94202,6 +94258,12 @@ function stickyStageDeliveryStatuses(runs, rootRunId) {
94202
94258
  return result;
94203
94259
  }
94204
94260
 
94261
+ // dist/builtin/workflows/src/shared/workflow-identity.ts
94262
+ function workflowIdentity(id, label, inputs) {
94263
+ const text = label?.trim() || [inputs?.objective, inputs?.prompt, inputs?.task, inputs?.request, ...Object.values(inputs ?? {})].find((value2) => typeof value2 === "string" && value2.trim().length > 0) || id;
94264
+ return text.replace(/\s+/g, " ").trim();
94265
+ }
94266
+
94205
94267
  // dist/builtin/workflows/src/runs/background/run-inspect.ts
94206
94268
  function inspectRun(runId, opts) {
94207
94269
  const activeStore = opts?.store ?? store;
@@ -94220,6 +94282,10 @@ function inspectRun(runId, opts) {
94220
94282
  runId: copy.id,
94221
94283
  ...copy.rootRunId === undefined ? {} : { rootRunId: copy.rootRunId },
94222
94284
  name: copy.name,
94285
+ label: copy.label,
94286
+ identity: workflowIdentity(copy.id, copy.label, copy.inputs),
94287
+ summary: copy.summary,
94288
+ summarizedThrough: copy.summarizedThrough,
94223
94289
  status: effectiveRunStatus(copy),
94224
94290
  mode: expandedStages.length > 1 ? "chain" : "single",
94225
94291
  startedAt: copy.startedAt,
@@ -109228,6 +109294,132 @@ init_dbos_admission();
109228
109294
  init_dbos_sdk_handle();
109229
109295
  init_factory();
109230
109296
 
109297
+ // dist/builtin/workflows/src/durable/fork-workflow.ts
109298
+ import { randomUUID as randomUUID8 } from "node:crypto";
109299
+ import { SessionManager as SessionManager3 } from "@bastani/atomic";
109300
+ async function forkDurableWorkflow(backend, source, cwd, modelOwner) {
109301
+ source = structuredClone(source);
109302
+ const workflowId = randomUUID8();
109303
+ const ids = new Map([[source.workflowId, workflowId]]);
109304
+ const mapId = (id) => {
109305
+ let mapped = ids.get(id);
109306
+ if (mapped === undefined) {
109307
+ mapped = randomUUID8();
109308
+ ids.set(id, mapped);
109309
+ }
109310
+ return mapped;
109311
+ };
109312
+ const mapTarget = (target) => {
109313
+ const parsed = parseWorkflowStageTarget(target);
109314
+ if (parsed === undefined || parsed.rootRunId !== source.workflowId)
109315
+ return target;
109316
+ return formatWorkflowStageTarget(workflowId, ...parsed.segments.map((segment) => ids.get(segment) ?? segment));
109317
+ };
109318
+ const mapRun = (run) => ({
109319
+ ...run,
109320
+ runId: mapId(run.runId),
109321
+ ...run.parentRunId === undefined ? {} : { parentRunId: mapId(run.parentRunId) },
109322
+ ...run.rootRunId === undefined ? {} : { rootRunId: workflowId }
109323
+ });
109324
+ const sessions = new Map;
109325
+ const checkpoints = [];
109326
+ for (const checkpoint of backend.listCheckpoints(source.workflowId)) {
109327
+ const copy = structuredClone(checkpoint);
109328
+ if (copy.kind === "ui") {
109329
+ checkpoints.push({ ...copy, workflowId });
109330
+ continue;
109331
+ }
109332
+ const topology = copy.topology;
109333
+ if (copy.kind === "tool") {
109334
+ checkpoints.push({
109335
+ ...copy,
109336
+ workflowId,
109337
+ ...topology === undefined ? {} : {
109338
+ topology: {
109339
+ ...copy.topology,
109340
+ ...copy.topology?.run === undefined ? {} : { run: mapRun(copy.topology.run) }
109341
+ }
109342
+ }
109343
+ });
109344
+ continue;
109345
+ }
109346
+ const stageTopology = copy.topology;
109347
+ const boundary = stageTopology?.boundary;
109348
+ const taskOutput = isToolPayloadObject(copy.output) && typeof copy.output.text === "string" ? copy.output : undefined;
109349
+ const sessionFile = copy.sessionFile ?? (typeof taskOutput?.sessionFile === "string" ? taskOutput.sessionFile : undefined);
109350
+ let session = sessionFile === undefined ? undefined : sessions.get(sessionFile);
109351
+ if (session === undefined && sessionFile !== undefined) {
109352
+ session = await SessionManager3.forkFromAsync(sessionFile, cwd, undefined, {
109353
+ internal: true,
109354
+ workflow: { runId: workflowId, stageId: stageTopology?.stageId ?? copy.checkpointId, stageName: copy.name }
109355
+ });
109356
+ sessions.set(sessionFile, session);
109357
+ }
109358
+ const childOutput = boundary === undefined ? undefined : parseWorkflowChildResult(copy.output);
109359
+ checkpoints.push({
109360
+ ...copy,
109361
+ workflowId,
109362
+ ...childOutput === undefined ? {} : { output: { ...childOutput, runId: mapId(childOutput.runId) } },
109363
+ ...taskOutput === undefined ? {} : {
109364
+ output: { ...taskOutput, sessionId: session?.getSessionId(), sessionFile: session?.getSessionFile() }
109365
+ },
109366
+ sessionId: session?.getSessionId(),
109367
+ sessionFile: session?.getSessionFile(),
109368
+ ...stageTopology === undefined ? {} : {
109369
+ topology: {
109370
+ ...stageTopology,
109371
+ intercomGroup: undefined,
109372
+ ...stageTopology.run === undefined ? {} : { run: mapRun(stageTopology.run) },
109373
+ ...boundary === undefined ? {} : {
109374
+ boundary: {
109375
+ ...boundary,
109376
+ child: {
109377
+ ...boundary.child,
109378
+ runId: mapId(boundary.child.runId),
109379
+ parentRunId: mapId(boundary.child.parentRunId),
109380
+ rootRunId: workflowId
109381
+ }
109382
+ }
109383
+ }
109384
+ }
109385
+ }
109386
+ });
109387
+ }
109388
+ const fork = {
109389
+ ...source,
109390
+ workflowId,
109391
+ rootWorkflowId: undefined,
109392
+ invocationCwd: cwd,
109393
+ workflowCwd: undefined,
109394
+ repositoryRoot: undefined,
109395
+ gitWorktreeRoot: undefined,
109396
+ sessionFile: undefined,
109397
+ modelOwner,
109398
+ releasedModelOwner: undefined,
109399
+ ownerExecutorId: undefined,
109400
+ createdAt: Date.now(),
109401
+ updatedAt: Date.now(),
109402
+ completedCheckpoints: 0,
109403
+ pendingStageMessages: source.pendingStageMessages?.map((message) => ({
109404
+ ...message,
109405
+ runId: mapId(message.runId),
109406
+ stageKey: mapTarget(message.stageKey),
109407
+ ...message.targetPath === undefined ? {} : { targetPath: mapTarget(message.targetPath) }
109408
+ }))
109409
+ };
109410
+ backend.registerWorkflow({ ...fork, status: "running", resumable: false });
109411
+ await backend.flush(workflowId);
109412
+ for (const checkpoint of checkpoints)
109413
+ await backend.recordCheckpointAsync(checkpoint);
109414
+ await backend.flush(workflowId);
109415
+ backend.registerWorkflow({
109416
+ ...fork,
109417
+ resumable: source.resumable ?? true,
109418
+ completedCheckpoints: backend.getWorkflow(workflowId).completedCheckpoints
109419
+ });
109420
+ await backend.flush(workflowId);
109421
+ return workflowId;
109422
+ }
109231
109423
  // dist/builtin/workflows/src/durable/tool-resume-frontier.ts
109232
109424
  function resolveToolResumeFrontier(source, backend) {
109233
109425
  const fail = (detail) => ({
@@ -109309,6 +109501,9 @@ function resolveDurableEntry(workflowId, catalog) {
109309
109501
  return resolution;
109310
109502
  return catalog.find((entry) => entry.workflowId === resolution.runId);
109311
109503
  }
109504
+ function crossProjectResumeMessage(workflowId, cwd) {
109505
+ return `Workflow run found in different project: ${cwd}. Run /workflow resume ${workflowId} in an interactive session to fork it into the current directory, or open the original project to resume it.`;
109506
+ }
109312
109507
  var pendingResumes = new WeakMap;
109313
109508
  var unsettledResumeClaims = new WeakMap;
109314
109509
  async function resumeDurableWorkflow(workflowId, deps, catalog) {
@@ -109348,11 +109543,15 @@ async function resumeDurableWorkflowClaimed(workflowId, deps, catalog) {
109348
109543
  } else {
109349
109544
  workflowId = target.runId;
109350
109545
  }
109546
+ const initial = backend.getWorkflow(workflowId);
109547
+ const currentCwd = deps.baseRunOpts.cwd;
109548
+ const crossProject = initial?.invocationCwd !== undefined && currentCwd !== undefined && canonicalDirectory(initial.invocationCwd) !== canonicalDirectory(currentCwd);
109351
109549
  const recovering = backend.isAdmissionUnavailable?.(workflowId) || backend.isCheckpointUnavailable?.(workflowId);
109352
109550
  if (recovering && hasActiveLiveRun(deps.baseRunOpts.store, workflowId)) {
109353
109551
  return alreadyRunningResult(backend.getWorkflow(workflowId)?.name ?? workflowId, workflowId, deps.baseRunOpts.store);
109354
109552
  }
109355
- await backend.reconcileWorkflowAdmission?.(workflowId, deps.signal);
109553
+ if (!crossProject)
109554
+ await backend.reconcileWorkflowAdmission?.(workflowId, deps.signal);
109356
109555
  const resolvedCatalog = recovering ? backend.listResumableWorkflows() : catalog ?? backend.listResumableWorkflows();
109357
109556
  const resolved = resolveDurableEntry(workflowId, resolvedCatalog);
109358
109557
  if (resolved === undefined) {
@@ -109416,7 +109615,21 @@ async function resumeDurableWorkflowClaimed(workflowId, deps, catalog) {
109416
109615
  if (adopting && !isSdkRunAdoptable(handle, deps.baseRunOpts.cwd)) {
109417
109616
  return { ok: false, reason: "owned_elsewhere", message: foreignInstanceMessage(backend, resolved.workflowId) };
109418
109617
  }
109419
- const def = handle.invocationCwd === undefined ? deps.registry.get(handle.name) : await deps.resolveDefinition?.(handle.name, handle.invocationCwd) ?? deps.registry.get(handle.name);
109618
+ if (crossProject) {
109619
+ if (deps.confirmCrossProjectFork === undefined)
109620
+ return {
109621
+ ok: false,
109622
+ reason: "different_project",
109623
+ message: crossProjectResumeMessage(workflowId, initial.invocationCwd)
109624
+ };
109625
+ if (!await deps.confirmCrossProjectFork(initial.invocationCwd))
109626
+ return {
109627
+ ok: false,
109628
+ reason: "different_project",
109629
+ message: "Workflow resume cancelled; the source run was not changed."
109630
+ };
109631
+ }
109632
+ const def = crossProject ? deps.registry.get(handle.name) ?? await deps.resolveDefinition?.(handle.name, handle.invocationCwd) : handle.invocationCwd === undefined ? deps.registry.get(handle.name) : await deps.resolveDefinition?.(handle.name, handle.invocationCwd) ?? deps.registry.get(handle.name);
109420
109633
  if (def === undefined) {
109421
109634
  return { ok: false, reason: "workflow_not_found", message: `Workflow definition not found: ${handle.name}` };
109422
109635
  }
@@ -109437,6 +109650,18 @@ async function resumeDurableWorkflowClaimed(workflowId, deps, catalog) {
109437
109650
  message: `invalid_inputs: ${err instanceof Error ? err.message : String(err)}`
109438
109651
  };
109439
109652
  }
109653
+ if (crossProject) {
109654
+ deps.signal?.throwIfAborted();
109655
+ const forkId = await forkDurableWorkflow(backend, handle, currentCwd, deps.forkModelOwner ?? requestedOwner);
109656
+ const fork = backend.getWorkflow(forkId);
109657
+ const result = await resumeDurableWorkflow(forkId, {
109658
+ ...deps,
109659
+ confirmCrossProjectFork: undefined,
109660
+ resolveDefinition: async () => def,
109661
+ onBeforeResume: deps.onBeforeResume === undefined ? undefined : (runId) => deps.onBeforeResume(runId, handle.workflowId)
109662
+ }, [resumableEntryFromHandle(fork)]);
109663
+ return result.ok ? { ...result, message: `Forked workflow ${workflowId} into the current directory. ${result.message}` } : result;
109664
+ }
109440
109665
  let toolContinuation = deps.baseRunOpts.continuation;
109441
109666
  if (handle.status === "failed" && (handle.failedToolNodeId !== undefined || /^atomic-workflows: ctx\.tool .* aborted by node abort$/s.test(handle.error ?? ""))) {
109442
109667
  const source = durableWorkflowRunSnapshots(backend, handle).find((run) => run.id === handle.workflowId);
@@ -109481,6 +109706,7 @@ async function resumeDurableWorkflowClaimed(workflowId, deps, catalog) {
109481
109706
  onRestored?.();
109482
109707
  return true;
109483
109708
  };
109709
+ await deps.onBeforeResume?.(resolved.workflowId);
109484
109710
  let claimed;
109485
109711
  try {
109486
109712
  claimed = await boundedAdmission((signal) => dbosAdmissionContext.run(signal, async () => {
@@ -109732,6 +109958,9 @@ function rootSnapshot(backend, handle, graph) {
109732
109958
  const terminalDurationMs = priorDurationMs ?? Math.max(0, handle.updatedAt - handle.createdAt);
109733
109959
  return {
109734
109960
  id: handle.workflowId,
109961
+ label: handle.label,
109962
+ summary: handle.summary,
109963
+ summarizedThrough: handle.summarizedThrough,
109735
109964
  name: handle.name,
109736
109965
  inputs: { ...handle.inputs },
109737
109966
  status: handle.status,
@@ -110407,43 +110636,45 @@ function workflowStatusPresentation(status, kind) {
110407
110636
  return { label: "crashed", color: "error" };
110408
110637
  return { label: status };
110409
110638
  }
110410
- function liveRunSession(run) {
110639
+ function liveRunSession(run, saved) {
110411
110640
  const completed = completedStageCount(run);
110412
110641
  const total = run.stages.length;
110413
110642
  const modified = new Date(latestRunTimestamp(run));
110414
110643
  const presentation = workflowStatusPresentation(run.status, "live");
110415
110644
  const stageText = `${completed}/${total} stages`;
110645
+ const identity = workflowIdentity(run.id, run.label ?? saved?.label, run.inputs);
110646
+ const summary = run.summary ?? saved?.summary;
110416
110647
  return {
110417
110648
  result: { kind: "live", runId: run.id },
110418
110649
  session: {
110419
110650
  path: `workflow-live:${run.id}`,
110420
110651
  id: run.id,
110421
- cwd: "Live workflow runs",
110652
+ cwd: "Live",
110422
110653
  created: new Date(run.startedAt),
110423
110654
  modified,
110424
110655
  messageCount: total,
110425
- firstMessage: run.id,
110426
- summary: `${presentation.label} ${stageText} ${run.name}`,
110427
- allMessagesText: `${run.id} ${run.name} ${presentation.label} ${stageText}`,
110656
+ firstMessage: summary ? `${presentation.label} ${completed}/${total} ${run.name} ${identity}` : identity,
110657
+ summary: summary || `${presentation.label} ${stageText} ${run.name}`,
110658
+ allMessagesText: `${run.id} ${identity} ${summary ?? ""} ${run.name} ${presentation.label} ${stageText}`,
110428
110659
  ...presentation.color !== undefined ? { messageColor: presentation.color } : {}
110429
110660
  }
110430
110661
  };
110431
110662
  }
110432
110663
  function durableWorkflowSession(entry, kind) {
110433
- const checkpointText = `${entry.completedCheckpoints} checkpoints`;
110434
110664
  const presentation = workflowStatusPresentation(entry.status, kind);
110665
+ const identity = workflowIdentity(entry.workflowId, entry.label, entry.inputs);
110435
110666
  return {
110436
110667
  result: { kind, workflowId: entry.workflowId },
110437
110668
  session: {
110438
110669
  path: `workflow-${kind}:${entry.workflowId}`,
110439
110670
  id: entry.workflowId,
110440
- cwd: kind === "completed" ? "Completed workflow runs" : "Durable workflow runs",
110671
+ cwd: kind === "completed" ? "Completed" : "Durable",
110441
110672
  created: new Date(entry.createdAt),
110442
110673
  modified: new Date(entry.updatedAt),
110443
110674
  messageCount: entry.completedCheckpoints,
110444
- firstMessage: entry.workflowId,
110445
- summary: `${presentation.label} ${checkpointText} ${entry.name}`,
110446
- allMessagesText: `${entry.workflowId} ${entry.name} ${presentation.label} ${checkpointText}`,
110675
+ firstMessage: entry.summary ? `${presentation.label} ${entry.name} ${identity}` : identity,
110676
+ summary: entry.summary || `${presentation.label} ${entry.name}`,
110677
+ allMessagesText: `${entry.workflowId} ${identity} ${entry.summary ?? ""} ${entry.name} ${presentation.label}`,
110447
110678
  ...presentation.color !== undefined ? { messageColor: presentation.color } : {}
110448
110679
  }
110449
110680
  };
@@ -110462,8 +110693,11 @@ function workflowResumeSelectorItems(liveRuns, durableEntries, completedEntries
110462
110693
  const suppressedLiveIds = new Set(classifiedLiveRuns.filter(({ run, resumable }) => resumable || !(run.status === "running" && run.endedAt === undefined)).map(({ run }) => run.id));
110463
110694
  const visibleDurableEntries = durableEntries.filter((entry) => !suppressedLiveIds.has(entry.workflowId));
110464
110695
  const durableIds = new Set(visibleDurableEntries.map((entry) => entry.workflowId));
110696
+ const savedEntries = new Map(completedEntries.map((entry) => [entry.workflowId, entry]));
110697
+ for (const entry of durableEntries)
110698
+ savedEntries.set(entry.workflowId, entry);
110465
110699
  return [
110466
- ...eligibleLiveRuns.map(liveRunSession),
110700
+ ...eligibleLiveRuns.map((run) => liveRunSession(run, savedEntries.get(run.id))),
110467
110701
  ...visibleDurableEntries.map((entry) => durableWorkflowSession(entry, "durable")),
110468
110702
  ...completedEntries.filter((entry) => !visibleLiveIds.has(entry.workflowId) && !durableIds.has(entry.workflowId)).map((entry) => durableWorkflowSession(entry, "completed"))
110469
110703
  ].sort(compareResumeItemsByRecency);
@@ -110670,6 +110904,45 @@ function workflowPolicyFromContext(ctx) {
110670
110904
  return ctx?.hasUI === false ? HEADLESS_WORKFLOW_POLICY : INTERACTIVE_WORKFLOW_POLICY;
110671
110905
  }
110672
110906
 
110907
+ // dist/builtin/workflows/src/extension/workflow-resume-summary.ts
110908
+ init_factory();
110909
+ var delivered = new WeakMap;
110910
+ async function injectWorkflowResumeSummary(pi, ctx, runId, run, forkedFrom) {
110911
+ if (ctx.isSessionSummaryEnabled?.() === false || pi.sendMessage === undefined)
110912
+ return;
110913
+ const owner = ("sessionManager" in ctx && typeof ctx.sessionManager === "object" ? ctx.sessionManager : undefined) ?? ctx;
110914
+ const manager = "sessionManager" in ctx ? ctx.sessionManager : undefined;
110915
+ const sessionId = manager && typeof manager.getSessionId === "function" ? manager.getSessionId() : "";
110916
+ const key = `${sessionId}:${runId}`;
110917
+ const seen = delivered.get(owner) ?? new Map;
110918
+ let handle;
110919
+ try {
110920
+ handle = getAvailableDurableBackend()?.getLoadableWorkflow(runId);
110921
+ } catch {}
110922
+ const boundary = run?.pausedAt ?? (handle?.status !== "running" ? handle?.transitionClaimId : undefined);
110923
+ if (seen.has(key) && (boundary === undefined || seen.get(key) === boundary))
110924
+ return;
110925
+ const summary = handle?.summary ?? run?.summary;
110926
+ if (!summary)
110927
+ return;
110928
+ const through = handle?.summarizedThrough ?? run?.summarizedThrough;
110929
+ const content = [
110930
+ `Workflow resume context: ${runId}${forkedFrom === undefined ? "" : ` (forked from ${forkedFrom})`}`,
110931
+ `Workflow: ${handle?.name ?? run?.name ?? runId}`,
110932
+ `Status: ${handle?.status ?? run?.status ?? "unknown"}`,
110933
+ `Summarized through: ${through === undefined ? "unknown" : new Date(through).toISOString()}`,
110934
+ summary
110935
+ ].join(`
110936
+ `);
110937
+ seen.set(key, boundary);
110938
+ delivered.set(owner, seen);
110939
+ try {
110940
+ await pi.sendMessage({ customType: "workflow-resume-summary", content, display: true }, { triggerTurn: false, deliverAs: "steer", persistWhenStreaming: true });
110941
+ } catch {
110942
+ seen.delete(key);
110943
+ }
110944
+ }
110945
+
110673
110946
  // dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts
110674
110947
  function stageScopedDurableResumeMessage(workflowId) {
110675
110948
  return `Stage-scoped resume is not supported for durable workflow ${workflowId}. Omit the stage selector to resume the whole run.`;
@@ -110726,6 +110999,8 @@ async function handleDurableResume(target, ctx, reporter, deps, preparedCatalog)
110726
110999
  const result = await runtime.resumeDurableWorkflow(target, {
110727
111000
  policy,
110728
111001
  actor: "user",
111002
+ ...crossProjectConfirmation(ctx),
111003
+ onBeforeResume: (runId, forkedFrom) => injectWorkflowResumeSummary(deps.pi, ctx, runId, undefined, forkedFrom),
110729
111004
  ...releasedRunAdoption("workflowId" in resolved ? resolved.workflowId : target, ctx)
110730
111005
  });
110731
111006
  if (result.ok) {
@@ -110806,10 +111081,19 @@ function releasedRunAdoption(workflowId, ctx) {
110806
111081
  const handle = getDurableBackend().getLoadableWorkflow(workflowId);
110807
111082
  return handle !== undefined && isSdkReleasedRunAdoptable(handle, ctx.cwd) ? { modelOwner: workflowCaller(ctx) } : {};
110808
111083
  }
111084
+ function crossProjectConfirmation(ctx) {
111085
+ const confirm = ctx.ui.confirm;
111086
+ return workflowPolicyFromContext(ctx).allowInputPicker && confirm !== undefined ? {
111087
+ forkModelOwner: workflowCaller(ctx),
111088
+ confirmCrossProjectFork: (cwd) => confirm("Resume workflow", `Workflow run found in different project: ${cwd}. Fork it into the current directory?`)
111089
+ } : {};
111090
+ }
110809
111091
  async function resumeDurableTarget(workflowId, ctx, reporter, deps, runtime) {
110810
111092
  const result = await runtime.resumeDurableWorkflow(workflowId, {
110811
111093
  policy: workflowPolicyFromContext(ctx),
110812
111094
  actor: "user",
111095
+ ...crossProjectConfirmation(ctx),
111096
+ onBeforeResume: (runId, forkedFrom) => injectWorkflowResumeSummary(deps.pi, ctx, runId, undefined, forkedFrom),
110813
111097
  ...releasedRunAdoption(workflowId, ctx)
110814
111098
  });
110815
111099
  if (!result.ok)
@@ -111832,12 +112116,12 @@ async function warm_first_fan_out(ctx, steps, prefixKeyOf, options = {}) {
111832
112116
  }
111833
112117
 
111834
112118
  // dist/builtin/workflows/builtin/pattern-artifact-root.ts
111835
- import { randomUUID as randomUUID8 } from "node:crypto";
112119
+ import { randomUUID as randomUUID9 } from "node:crypto";
111836
112120
  import { mkdir as mkdir4 } from "node:fs/promises";
111837
112121
  import { join as join16 } from "node:path";
111838
112122
  async function stableArtifactRoot(ctx, workflowName) {
111839
112123
  const cwd = ctx.cwd ?? process.cwd();
111840
- const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join16(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID8()}`));
112124
+ const artifactDir = await ctx.tool("artifact-root", { workflow: workflowName }, async () => join16(cwd, ".atomic", "workflows", "runs", `${workflowName}-${randomUUID9()}`));
111841
112125
  await mkdir4(artifactDir, { recursive: true });
111842
112126
  return artifactDir;
111843
112127
  }
@@ -113096,7 +113380,7 @@ async function writeReviewRoundArtifact(artifactDir, reviews, consolidatedFindin
113096
113380
  }
113097
113381
 
113098
113382
  // dist/builtin/workflows/builtin/goal-ledger.ts
113099
- import { randomUUID as randomUUID9 } from "node:crypto";
113383
+ import { randomUUID as randomUUID10 } from "node:crypto";
113100
113384
  import { readFile as readFile4, rename as rename2, rm as rm3, writeFile as writeFile8 } from "node:fs/promises";
113101
113385
  import { dirname as dirname12, join as join22 } from "node:path";
113102
113386
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
@@ -113426,7 +113710,7 @@ async function createGoalLedger(objective, acceptanceCriteria, artifactDir) {
113426
113710
  await writeGoalLedger(ledgerPath, existing);
113427
113711
  return { ledger: existing, ledgerPath, artifactDir };
113428
113712
  }
113429
- const goalId = randomUUID9();
113713
+ const goalId = randomUUID10();
113430
113714
  const now = new Date().toISOString();
113431
113715
  const ledger = {
113432
113716
  goal_id: goalId,
@@ -113455,7 +113739,7 @@ async function writeGoalLedger(ledgerPath, ledger) {
113455
113739
  const stateContents = `${JSON.stringify(ledger, null, 2)}
113456
113740
  `;
113457
113741
  const statePath = goalLedgerStatePath(ledgerPath);
113458
- const pendingStatePath = `${statePath}.${randomUUID9()}.tmp`;
113742
+ const pendingStatePath = `${statePath}.${randomUUID10()}.tmp`;
113459
113743
  await writeFile8(pendingStatePath, stateContents, { encoding: "utf8" });
113460
113744
  try {
113461
113745
  await rename2(pendingStatePath, statePath);
@@ -117211,7 +117495,7 @@ __export(exports_sdk_surface, {
117211
117495
  import {
117212
117496
  isStaleExtensionContextError as isStaleExtensionContextError5,
117213
117497
  resolveRestoredModelReference,
117214
- SessionManager as SessionManager3
117498
+ SessionManager as SessionManager4
117215
117499
  } from "@bastani/atomic";
117216
117500
 
117217
117501
  // dist/builtin/workflows/src/extension/atomic-stage-session.ts
@@ -117810,7 +118094,7 @@ function createAgentSessionAdapter(baseOptions = {}) {
117810
118094
  if (value2 !== undefined)
117811
118095
  Object.assign(options, { [key]: value2 });
117812
118096
  }
117813
- options.sessionManager ??= SessionManager3.inMemory(options.cwd ?? process.cwd());
118097
+ options.sessionManager ??= SessionManager4.inMemory(options.cwd ?? process.cwd());
117814
118098
  return options;
117815
118099
  }
117816
118100
  }, { createAgentSession: (options, prepareOptions) => createPiSdkAgentSession(options, prepareOptions) });
@@ -118313,6 +118597,119 @@ function discoverBundledManifest() {
118313
118597
  return { registry, sources, errors: diagnostics };
118314
118598
  }
118315
118599
 
118600
+ // dist/builtin/workflows/src/extension/workflow-summary.ts
118601
+ init_factory();
118602
+ var services = new WeakMap;
118603
+ function ensureWorkflowSummaryService(store, context) {
118604
+ const existing = services.get(store);
118605
+ if (existing) {
118606
+ existing.context = context;
118607
+ return;
118608
+ }
118609
+ const entry = {
118610
+ context,
118611
+ service: createWorkflowSummaryService({
118612
+ store,
118613
+ resolveContext: () => services.get(store)?.context ?? context,
118614
+ persist: async (runId, summary, summarizedThrough) => {
118615
+ await getAvailableDurableBackend()?.persistSummary?.(runId, summary, summarizedThrough);
118616
+ store.recordRunSummary?.(runId, summary, summarizedThrough);
118617
+ }
118618
+ })
118619
+ };
118620
+ services.set(store, entry);
118621
+ }
118622
+ function disposeWorkflowSummaryService(store) {
118623
+ services.get(store)?.service.dispose();
118624
+ services.delete(store);
118625
+ }
118626
+ function requestWorkflowSummary(store, runId) {
118627
+ services.get(store)?.service.request(runId);
118628
+ }
118629
+ function createWorkflowSummaryService(options) {
118630
+ const contexts = new Map;
118631
+ const pending = new Map;
118632
+ const finalized = new Map;
118633
+ let disposed = false;
118634
+ const request = (runId) => {
118635
+ const run = options.store.runs().find((entry) => entry.id === runId);
118636
+ const context = contexts.get(runId) ?? options.resolveContext();
118637
+ if (disposed || !run || !context?.generateWorkflowSummary || context.isSessionSummaryEnabled?.() === false || pending.has(runId))
118638
+ return;
118639
+ contexts.set(runId, context);
118640
+ const controller = new AbortController;
118641
+ pending.set(runId, controller);
118642
+ const through = Date.now();
118643
+ const text = workflowSummaryInput(run);
118644
+ (async () => {
118645
+ const summary = await context.generateWorkflowSummary(text, controller.signal, { terminal: terminal(run) });
118646
+ if (summary && !controller.signal.aborted && !disposed && context.isSessionSummaryEnabled?.() !== false) {
118647
+ await options.persist(runId, summary, through);
118648
+ }
118649
+ })().catch(() => {}).finally(() => {
118650
+ if (pending.get(runId) === controller)
118651
+ pending.delete(runId);
118652
+ });
118653
+ };
118654
+ const refresh = () => {
118655
+ for (const run of options.store.runs()) {
118656
+ if (run.parentRunId)
118657
+ continue;
118658
+ if (!contexts.has(run.id)) {
118659
+ const context = options.resolveContext();
118660
+ if (context)
118661
+ contexts.set(run.id, context);
118662
+ }
118663
+ const status = effectiveRunStatus(run);
118664
+ if (!terminal(run))
118665
+ finalized.delete(run.id);
118666
+ else if (finalized.get(run.id) !== status) {
118667
+ finalized.set(run.id, status);
118668
+ pending.get(run.id)?.abort();
118669
+ pending.delete(run.id);
118670
+ request(run.id);
118671
+ }
118672
+ }
118673
+ };
118674
+ const unsubscribe = subscribeStoreInvalidation(options.store, refresh);
118675
+ refresh();
118676
+ return {
118677
+ request,
118678
+ dispose: () => {
118679
+ disposed = true;
118680
+ unsubscribe();
118681
+ for (const controller of pending.values())
118682
+ controller.abort();
118683
+ pending.clear();
118684
+ contexts.clear();
118685
+ }
118686
+ };
118687
+ }
118688
+ function terminal(run) {
118689
+ const status = effectiveRunStatus(run);
118690
+ return status === "blocked" || isTerminalRunStatus(status);
118691
+ }
118692
+ function workflowSummaryInput(run) {
118693
+ const preferred = ["objective", "prompt", "task", "request", "input"];
118694
+ const keys = [...new Set([...preferred.filter((key) => (key in run.inputs)), ...Object.keys(run.inputs)])].slice(0, 20);
118695
+ const objective = keys.map((key) => {
118696
+ const value2 = run.inputs[key];
118697
+ const text = typeof value2 === "string" ? value2.slice(0, 2000) : typeof value2 === "object" && value2 !== null ? "[structured input]" : String(value2);
118698
+ return `${key.slice(0, 100)}: ${text}`;
118699
+ }).join(`
118700
+ `).slice(0, 4000);
118701
+ const stages = run.stages.slice(-40).map((stage) => `${stage.name.slice(0, 100)}: ${stage.status}
118702
+ ${(stage.result ?? stage.error ?? "").slice(-1500)}`).join(`
118703
+ `).slice(-11000);
118704
+ return `Workflow: ${run.name.slice(0, 200)}
118705
+ Run: ${run.id}
118706
+ Status: ${effectiveRunStatus(run)}
118707
+ Objective/inputs:
118708
+ ${objective}
118709
+ Latest stages and outputs:
118710
+ ${stages}`.slice(0, 16000);
118711
+ }
118712
+
118316
118713
  // dist/builtin/workflows/src/extension/runtime.ts
118317
118714
  init_backend();
118318
118715
  init_factory();
@@ -118639,6 +119036,9 @@ function createDurableResumeRuntime(deps) {
118639
119036
  registry: deps.registry,
118640
119037
  signal: options?.signal,
118641
119038
  onRunAccepted: options?.onRunAccepted,
119039
+ onBeforeResume: options?.onBeforeResume,
119040
+ confirmCrossProjectFork: options?.confirmCrossProjectFork,
119041
+ forkModelOwner: options?.forkModelOwner,
118642
119042
  baseRunOpts: {
118643
119043
  ...deps.baseRunOpts(options?.policy),
118644
119044
  ...options?.budget === undefined ? {} : { budget: options.budget },
@@ -118739,6 +119139,8 @@ function createExtensionRuntime(opts = {}) {
118739
119139
  const registry = opts.registry ?? createRegistry(opts.definitions ?? []);
118740
119140
  const adapters = opts.adapters;
118741
119141
  const activeStore = opts.store ?? currentWorkflowStore();
119142
+ if (opts.summaryContext)
119143
+ ensureWorkflowSummaryService(activeStore, opts.summaryContext);
118742
119144
  const cancellation = opts.cancellation ?? currentCancellationRegistry();
118743
119145
  const stageControlRegistry = opts.stageControlRegistry ?? currentStageControlRegistry();
118744
119146
  const toolControlRegistry = opts.toolControlRegistry ?? currentToolControlRegistry();
@@ -119582,7 +119984,7 @@ function installWorkflowHeartbeatScheduler(options) {
119582
119984
  continue;
119583
119985
  }
119584
119986
  observed.add(run.id);
119585
- if (state.pending.has(run.id) || !isWorkflowHeartbeatEligibleRun(run)) {
119987
+ if (state.pending.has(run.id) && options.onSummaryBoundary === undefined || !isWorkflowHeartbeatEligibleRun(run)) {
119586
119988
  state.scheduled.delete(run.id);
119587
119989
  continue;
119588
119990
  }
@@ -119651,6 +120053,7 @@ function installWorkflowHeartbeatScheduler(options) {
119651
120053
  const run = findRun(snapshot, details.runId);
119652
120054
  if (run === undefined || !isWorkflowHeartbeatEligibleRun(run))
119653
120055
  continue;
120056
+ options.onSummaryBoundary?.(run.id);
119654
120057
  enqueueWorkflowHeartbeat(details);
119655
120058
  }
119656
120059
  refresh();
@@ -120042,6 +120445,7 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
120042
120445
  });
120043
120446
  });
120044
120447
  pi.on?.("session_shutdown", () => {
120448
+ disposeWorkflowSummaryService(store);
120045
120449
  detachHumanInput?.();
120046
120450
  detachHumanInput = undefined;
120047
120451
  });
@@ -120140,6 +120544,7 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
120140
120544
  store,
120141
120545
  state: workflowHeartbeatSchedulerState,
120142
120546
  sendMessage: sendWorkflowNotificationMessage,
120547
+ onSummaryBoundary: (runId) => requestWorkflowSummary(store, runId),
120143
120548
  resolveIntervalMinutes: (workflowName) => runtimeProxy.registry.get(workflowName)?.heartbeatIntervalMinutes,
120144
120549
  parentAvailabilityReported,
120145
120550
  anchorStore: durableWorkflowHeartbeatAnchorStore()
@@ -120254,7 +120659,7 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
120254
120659
  function runtimeForContext(ctx) {
120255
120660
  const models = workflowModelCatalogFromContext(ctx, resolveLiveModelContext);
120256
120661
  const durabilityWarningSink = durabilityWarningSinkFromContext(ctx);
120257
- if (models === undefined && durabilityWarningSink === undefined)
120662
+ if (models === undefined && durabilityWarningSink === undefined && !ctx?.generateWorkflowSummary)
120258
120663
  return runtimeProxy;
120259
120664
  return createExtensionRuntime({
120260
120665
  registry: runtimeRef.current.registry,
@@ -120268,6 +120673,7 @@ function createWorkflowExtensionRuntimeState(pi, adapters, options = {}) {
120268
120673
  config: runtimeConfigRef.current,
120269
120674
  resolvePossibleStageEntry,
120270
120675
  ...models === undefined ? {} : { models },
120676
+ summaryContext: ctx,
120271
120677
  ...durabilityWarningSink === undefined ? {} : { durabilityWarningSink },
120272
120678
  resolveDefaultStageSessionDir,
120273
120679
  beforeRestoreCompleted,
@@ -122446,6 +122852,7 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
122446
122852
  return true;
122447
122853
  }
122448
122854
  const run = store.runs().find((r) => r.id === resolved.runId);
122855
+ await injectWorkflowResumeSummary(deps.pi, ctx, resolved.runId, run);
122449
122856
  const isPaused = run !== undefined && workflowHasPausedState(store, resolved.runId);
122450
122857
  const isDurableAuthorExit = run?.exited === true && run.status === "failed" && run.resumable === true;
122451
122858
  const isResumableContinuation = run !== undefined && !isPaused && run.exitReason !== "quit" && isWorkflowRunResumable(workflowRunResumeCandidate(run, store.runs()));
@@ -122604,6 +123011,7 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
122604
123011
  fail(`Workflow ${stageRunId} is already running in this session. Attach with \`/workflow connect ${stageRunId}\` instead of resuming.`);
122605
123012
  return true;
122606
123013
  }
123014
+ await injectWorkflowResumeSummary(deps.pi, ctx, stageRunId, run);
122607
123015
  if (isDurableAuthorExit) {
122608
123016
  return await handleDurableResume(stageRunId, ctx, reporter, deps);
122609
123017
  }
@@ -122946,6 +123354,7 @@ function resumeFailureCode(reason) {
122946
123354
  case "run_not_found":
122947
123355
  return "run_not_found";
122948
123356
  case "workflow_not_found":
123357
+ case "different_project":
122949
123358
  case "invalid_inputs":
122950
123359
  case "startup_failed":
122951
123360
  case "insufficient_state":
@@ -122965,6 +123374,7 @@ function executeContext(ctx) {
122965
123374
  hasHumanInput: ctx.hasHumanInput,
122966
123375
  model: ctx.model,
122967
123376
  modelRegistry: ctx.modelRegistry,
123377
+ isSessionSummaryEnabled: ctx.isSessionSummaryEnabled,
122968
123378
  cwd: ctx.cwd
122969
123379
  };
122970
123380
  }
@@ -123051,7 +123461,55 @@ function createSessionRunControl(host) {
123051
123461
  });
123052
123462
  if (result.action !== "status")
123053
123463
  throw failure3("control_failed", `Unexpected workflow result: ${result.action}`, undefined);
123054
- return result.runs;
123464
+ const catalog = filter?.includeDurable ? await host.catalog?.() : undefined;
123465
+ const cwd = host.context()?.cwd;
123466
+ const canonicalPaths = new Map;
123467
+ const canonicalize = (path) => {
123468
+ const cached = canonicalPaths.get(path);
123469
+ if (cached !== undefined)
123470
+ return cached;
123471
+ const canonical = canonicalDirectory(path);
123472
+ canonicalPaths.set(path, canonical);
123473
+ return canonical;
123474
+ };
123475
+ const entries = [...catalog?.resumable ?? [], ...catalog?.completed ?? []].filter((entry) => isSdkDurableRunInScope(entry, cwd, canonicalize));
123476
+ const saved = new Map(entries.map((entry) => [entry.workflowId, entry]));
123477
+ const snapshots = new Map(host.store.runs().map((run) => [run.id, run]));
123478
+ const runs = result.runs.map((run) => {
123479
+ const snapshot = snapshots.get(run.runId);
123480
+ const entry = saved.get(run.runId);
123481
+ const label = snapshot?.label ?? entry?.label;
123482
+ return {
123483
+ ...run,
123484
+ label,
123485
+ identity: workflowIdentity(run.runId, label, snapshot?.inputs ?? entry?.inputs),
123486
+ summary: snapshot?.summary ?? entry?.summary,
123487
+ summarizedThrough: snapshot?.summarizedThrough ?? entry?.summarizedThrough
123488
+ };
123489
+ });
123490
+ const seen = new Set(runs.map((run) => run.runId));
123491
+ for (const entry of entries) {
123492
+ if (seen.has(entry.workflowId))
123493
+ continue;
123494
+ if (filter?.status === "awaiting_input" ? entry.pendingPrompts === 0 : filter?.status !== undefined && filter.status !== entry.status)
123495
+ continue;
123496
+ seen.add(entry.workflowId);
123497
+ runs.push({
123498
+ runId: entry.workflowId,
123499
+ name: entry.name,
123500
+ status: entry.status,
123501
+ startedAt: entry.createdAt,
123502
+ elapsedMs: Math.max(0, entry.updatedAt - entry.createdAt),
123503
+ activeStages: [],
123504
+ awaitingInputCount: entry.pendingPrompts,
123505
+ awaitingInput: [],
123506
+ label: entry.label,
123507
+ identity: workflowIdentity(entry.workflowId, entry.label, entry.inputs),
123508
+ summary: entry.summary,
123509
+ summarizedThrough: entry.summarizedThrough
123510
+ });
123511
+ }
123512
+ return runs;
123055
123513
  },
123056
123514
  async getRun(runId) {
123057
123515
  const result = await request({ action: "status", runId });
@@ -124223,6 +124681,7 @@ async function workflowResumeAction(args, deps) {
124223
124681
  warning = formatWorkflowResourceLoadWarning(error);
124224
124682
  }
124225
124683
  deps.signal?.throwIfAborted();
124684
+ await deps.beforeResume?.(stageRunId);
124226
124685
  const continuation = await deps.getRuntime().resumeFailedRun(stageRunId, stage.stageId, {
124227
124686
  policy: deps.policy,
124228
124687
  actor: "agent",
@@ -124242,6 +124701,7 @@ ${continuation.message}`;
124242
124701
  };
124243
124702
  }
124244
124703
  try {
124704
+ await deps.beforeResume?.(stageRunId);
124245
124705
  const result = await resumeRun(stageRunId, {
124246
124706
  ...owner,
124247
124707
  stageId: stage.stageId,
@@ -124598,7 +125058,7 @@ function durableInspectionError(action, runId, message) {
124598
125058
  truncated: false
124599
125059
  };
124600
125060
  }
124601
- function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflowResourcesLoaded = () => {}, owner = captureWorkflowOwnerResources()) {
125061
+ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflowResourcesLoaded = () => {}, owner = captureWorkflowOwnerResources(), pi = {}) {
124602
125062
  const { store, toolControlRegistry } = owner;
124603
125063
  return async function executeWorkflowTool(args, ctx, signal, onRunAccepted, access) {
124604
125064
  signal?.throwIfAborted();
@@ -124632,6 +125092,9 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
124632
125092
  if (access === "sdk" && isFullRunId(args.runId?.trim() ?? "") && (action === "status" || action === "stages" || action === "resume" && handle !== undefined && isSdkCrashedRunAdoptable(handle, recoveryCwd)) && !store.runs().some((run) => run.id === id) && handle !== undefined && isSdkDurableRunInScope(handle, recoveryCwd))
124633
125093
  return;
124634
125094
  assertWorkflowInstanceOwner(id, ctx, store);
125095
+ if (action === "resume" && recoveryCwd !== undefined && handle?.invocationCwd !== undefined && canonicalDirectory(recoveryCwd) !== canonicalDirectory(handle.invocationCwd)) {
125096
+ throw new Error(crossProjectResumeMessage(id, handle.invocationCwd));
125097
+ }
124635
125098
  };
124636
125099
  if (action === "status" && args.runId === undefined) {
124637
125100
  for (const run of topLevelWorkflowRuns(store.runs()))
@@ -124652,7 +125115,10 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
124652
125115
  const resolved = typeof runtime === "function" ? runtime(ctx) : runtime;
124653
125116
  return {
124654
125117
  ...resolved,
124655
- resumeDurableWorkflow: (id, options) => resolved.resumeDurableWorkflow(id, access === "sdk" || adoptsReleasedRun(id) ? { ...options, modelOwner: workflowCaller(ctx) } : options)
125118
+ resumeDurableWorkflow: async (id, options) => {
125119
+ await injectWorkflowResumeSummary(pi, ctx, id);
125120
+ return resolved.resumeDurableWorkflow(id, access === "sdk" || adoptsReleasedRun(id) ? { ...options, modelOwner: workflowCaller(ctx) } : options);
125121
+ }
124656
125122
  };
124657
125123
  };
124658
125124
  const ensureWorkflowResourcesVisible = async () => {
@@ -124770,7 +125236,8 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
124770
125236
  signal,
124771
125237
  onRunAccepted,
124772
125238
  owner,
124773
- authorize
125239
+ authorize,
125240
+ beforeResume: (id) => injectWorkflowResumeSummary(pi, ctx, id, store.runs().find((run) => run.id === id))
124774
125241
  }));
124775
125242
  default: {
124776
125243
  const _exhaustive = action;
@@ -125402,7 +125869,7 @@ function factory(pi) {
125402
125869
  const workflowCommands = new Map;
125403
125870
  const storeWidgetRef = { current: null };
125404
125871
  const intercomControlRef = { current: null };
125405
- const executeWorkflowTool = makeExecuteWorkflowTool((ctx) => runtimeState.runtimeForContext(ctx), runtimeState.reloadWorkflowResources, runtimeState.ensureWorkflowResourcesLoaded, owner);
125872
+ const executeWorkflowTool = makeExecuteWorkflowTool((ctx) => runtimeState.runtimeForContext(ctx), runtimeState.reloadWorkflowResources, runtimeState.ensureWorkflowResourcesLoaded, owner, pi);
125406
125873
  let sessionContext;
125407
125874
  pi.on?.("session_start", (_event, ctx) => {
125408
125875
  sessionContext = ctx;
@@ -125410,7 +125877,15 @@ function factory(pi) {
125410
125877
  pi.on?.("session_shutdown", () => {
125411
125878
  sessionContext = undefined;
125412
125879
  });
125413
- pi.registerWorkflowRunControl?.(createSessionRunControl({ execute: executeWorkflowTool, context: () => sessionContext, store: owner.store }));
125880
+ pi.registerWorkflowRunControl?.(createSessionRunControl({
125881
+ execute: executeWorkflowTool,
125882
+ context: () => sessionContext,
125883
+ store: owner.store,
125884
+ catalog: async () => {
125885
+ const runtime = runtimeState.runtimeForContext(sessionContext);
125886
+ return await runtime.prepareDurableCatalog?.() ?? { resumable: [], completed: [] };
125887
+ }
125888
+ }));
125414
125889
  const executeWorkflowToolWithAutoAttach = async (args, ctx, signal, onRunAccepted) => {
125415
125890
  const result = await executeWorkflowTool(args, ctx, signal, onRunAccepted);
125416
125891
  if (workflowPolicyFromContext(ctx).allowInputPicker && result.action === "run" && result.status === "running" && result.runId.length > 0 && result.name !== undefined && runtimeState.runtimeProxy.registry.get(result.name)?.autoAttach === true) {