@stigmer/runner 3.12.6 → 3.12.8

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 (73) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/activities/call-agent-status.d.ts +14 -2
  3. package/dist/activities/call-agent-status.js +24 -7
  4. package/dist/activities/call-agent-status.js.map +1 -1
  5. package/dist/activities/execute-cursor/index.d.ts +10 -0
  6. package/dist/activities/execute-cursor/index.js +26 -0
  7. package/dist/activities/execute-cursor/index.js.map +1 -1
  8. package/dist/activities/execute-cursor/prompt-builder.d.ts +12 -0
  9. package/dist/activities/execute-cursor/prompt-builder.js +11 -0
  10. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  11. package/dist/activities/execute-deep-agent/mcp-gate.d.ts +2 -0
  12. package/dist/activities/execute-deep-agent/mcp-gate.js +2 -1
  13. package/dist/activities/execute-deep-agent/mcp-gate.js.map +1 -1
  14. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +9 -0
  15. package/dist/activities/execute-deep-agent/prompt-builder.js +10 -0
  16. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  17. package/dist/activities/execute-deep-agent/setup.js +27 -0
  18. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  19. package/dist/config.d.ts +10 -0
  20. package/dist/config.js +3 -0
  21. package/dist/config.js.map +1 -1
  22. package/dist/main.js +3 -0
  23. package/dist/main.js.map +1 -1
  24. package/dist/runner-manager.d.ts +2 -0
  25. package/dist/runner-manager.js +1 -0
  26. package/dist/runner-manager.js.map +1 -1
  27. package/dist/runner.d.ts +2 -0
  28. package/dist/runner.js +33 -6
  29. package/dist/runner.js.map +1 -1
  30. package/dist/shared/artifact-storage.js +7 -4
  31. package/dist/shared/artifact-storage.js.map +1 -1
  32. package/dist/shared/memory-attachment.d.ts +97 -0
  33. package/dist/shared/memory-attachment.js +136 -0
  34. package/dist/shared/memory-attachment.js.map +1 -0
  35. package/dist/shared/recalled-memories.d.ts +55 -0
  36. package/dist/shared/recalled-memories.js +70 -0
  37. package/dist/shared/recalled-memories.js.map +1 -0
  38. package/dist/shared/tool-kind.js +9 -0
  39. package/dist/shared/tool-kind.js.map +1 -1
  40. package/dist/workflows/call-agent-orchestrator.d.ts +14 -2
  41. package/dist/workflows/call-agent-orchestrator.js +55 -18
  42. package/dist/workflows/call-agent-orchestrator.js.map +1 -1
  43. package/package.json +2 -2
  44. package/src/__tests__/golden-e2e.test.ts +1 -1
  45. package/src/activities/__tests__/call-agent-status.test.ts +30 -5
  46. package/src/activities/__tests__/classify-tool-approvals.test.ts +1 -0
  47. package/src/activities/__tests__/discover-mcp-server.test.ts +1 -0
  48. package/src/activities/call-agent-status.ts +25 -8
  49. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +79 -0
  50. package/src/activities/execute-cursor/index.ts +43 -0
  51. package/src/activities/execute-cursor/prompt-builder.ts +28 -0
  52. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +1 -0
  53. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +1 -0
  54. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +1 -0
  55. package/src/activities/execute-deep-agent/__tests__/index.test.ts +1 -0
  56. package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +7 -0
  57. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +48 -0
  58. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
  59. package/src/activities/execute-deep-agent/mcp-gate.ts +4 -1
  60. package/src/activities/execute-deep-agent/prompt-builder.ts +22 -0
  61. package/src/activities/execute-deep-agent/setup.ts +40 -0
  62. package/src/config.ts +13 -0
  63. package/src/main.ts +3 -0
  64. package/src/runner-manager.ts +5 -0
  65. package/src/runner.ts +42 -6
  66. package/src/shared/__tests__/artifact-storage.test.ts +21 -0
  67. package/src/shared/__tests__/memory-attachment.test.ts +167 -0
  68. package/src/shared/__tests__/recalled-memories.test.ts +88 -0
  69. package/src/shared/artifact-storage.ts +9 -4
  70. package/src/shared/memory-attachment.ts +167 -0
  71. package/src/shared/recalled-memories.ts +90 -0
  72. package/src/shared/tool-kind.ts +10 -0
  73. package/src/workflows/call-agent-orchestrator.ts +60 -24
@@ -16,8 +16,20 @@
16
16
  * and pure logic. No Node.js built-ins.
17
17
  */
18
18
  import type { AgentCallConfig, AgentCallResult } from "../workflow-engine/types.js";
19
- import type { ChildApprovalNotification } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
20
- export declare const childApprovalRequired: import("@temporalio/workflow").SignalDefinition<[ChildApprovalNotification], string>;
19
+ /**
20
+ * Identity-only "go look" trigger (DD-012, stigmer-cloud#509): the child's
21
+ * server signals just the gated child's execution id, and this workflow
22
+ * derives the gate from the child's persisted record. The payload MUST stay a
23
+ * bare string: it crosses the polyglot boundary from the Java server, whose
24
+ * client serializes proto messages as `json/protobuf` — an encoding this
25
+ * worker's default converter cannot decode, which poisoned the workflow task
26
+ * in a permanent retry loop (the original cloud#509 failure). The object
27
+ * shape is tolerated for a future Go sender's natural `{executionId}` JSON,
28
+ * mirroring child_execution_started's both-shapes handling below.
29
+ */
30
+ export declare const childApprovalRequired: import("@temporalio/workflow").SignalDefinition<[string | {
31
+ executionId?: string;
32
+ }], string>;
21
33
  /** Sent by the platform immediately after the child AgentExecution starts. */
22
34
  export declare const childExecutionStarted: import("@temporalio/workflow").SignalDefinition<[{
23
35
  executionId: string;
@@ -20,6 +20,17 @@ import { AgentCallError } from "../workflow-engine/types.js";
20
20
  // ─────────────────────────────────────────────────────────────────────
21
21
  // Signal Definitions
22
22
  // ─────────────────────────────────────────────────────────────────────
23
+ /**
24
+ * Identity-only "go look" trigger (DD-012, stigmer-cloud#509): the child's
25
+ * server signals just the gated child's execution id, and this workflow
26
+ * derives the gate from the child's persisted record. The payload MUST stay a
27
+ * bare string: it crosses the polyglot boundary from the Java server, whose
28
+ * client serializes proto messages as `json/protobuf` — an encoding this
29
+ * worker's default converter cannot decode, which poisoned the workflow task
30
+ * in a permanent retry loop (the original cloud#509 failure). The object
31
+ * shape is tolerated for a future Go sender's natural `{executionId}` JSON,
32
+ * mirroring child_execution_started's both-shapes handling below.
33
+ */
23
34
  export const childApprovalRequired = defineSignal("child_approval_required");
24
35
  /** Sent by the platform immediately after the child AgentExecution starts. */
25
36
  export const childExecutionStarted = defineSignal("child_execution_started");
@@ -61,14 +72,26 @@ export async function orchestrateAgentCall(input) {
61
72
  let activityDone = false;
62
73
  let activityResult = {};
63
74
  let activityError = undefined;
64
- let pendingNotification;
75
+ // Child ids whose approval gates await derivation. A set (not a flag)
76
+ // because one workflow has ONE live handler per signal name: with parallel
77
+ // agent_call tasks, whichever orchestration registered last receives every
78
+ // child's signal, and each gate must be derived under its OWN child id for
79
+ // the per-child status merge to file it correctly.
80
+ const pendingApprovalChildIds = new Set();
65
81
  let childExecId;
66
82
  let initialProgressEmitted = false;
67
- setHandler(childApprovalRequired, (notification) => {
68
- pendingNotification = notification;
69
- if (!childExecId && notification.executionId) {
70
- childExecId = notification.executionId;
83
+ setHandler(childApprovalRequired, (payload) => {
84
+ // Identity-only signal (see the definition above): note the child and
85
+ // mark its gate for derivation in the main loop — approval details never
86
+ // travel through the signal itself.
87
+ const signaledId = typeof payload === "string" ? payload : payload?.executionId;
88
+ if (!signaledId) {
89
+ return;
90
+ }
91
+ if (!childExecId) {
92
+ childExecId = signaledId;
71
93
  }
94
+ pendingApprovalChildIds.add(signaledId);
72
95
  });
73
96
  setHandler(childExecutionStarted, (payload) => {
74
97
  // The Go server sends { executionId: "aex_xxx" } (struct with json tag).
@@ -159,7 +182,7 @@ export async function orchestrateAgentCall(input) {
159
182
  while (!activityDone) {
160
183
  // Wait for a signal, activity completion, or periodic timeout for progress polling.
161
184
  // condition() returns false on timeout, true when the predicate became true.
162
- const conditionMet = await condition(() => activityDone || pendingNotification !== undefined || (!!childExecId && !initialProgressEmitted), PROGRESS_POLL_INTERVAL);
185
+ const conditionMet = await condition(() => activityDone || pendingApprovalChildIds.size > 0 || (!!childExecId && !initialProgressEmitted), PROGRESS_POLL_INTERVAL);
163
186
  if (activityDone)
164
187
  break;
165
188
  // Emit initial progress with childExecutionId as soon as it's known
@@ -185,18 +208,32 @@ export async function orchestrateAgentCall(input) {
185
208
  }
186
209
  await syncFileReviews(childExecId);
187
210
  }
188
- // Handle HITL approval notification
189
- if (pendingNotification) {
190
- const notification = pendingNotification;
191
- pendingNotification = undefined;
192
- try {
193
- await statusProxy.UpdateWorkflowTaskApprovalStatus(input.workflowExecutionId, input.taskName, notification);
194
- }
195
- catch (statusErr) {
196
- log.warn("Failed to update workflow approval status (non-fatal)", {
197
- error: String(statusErr),
198
- taskName: input.taskName,
199
- });
211
+ // Handle HITL approval notifications: derive each signaled child's gate
212
+ // from its persisted record (identity-only signal, DD-012). The child's
213
+ // server persists the gate BEFORE signaling, so an empty derivation means
214
+ // the gate already resolved — the activity answers false and there is
215
+ // deliberately no retry (see updateWorkflowTaskApprovalStatus).
216
+ if (pendingApprovalChildIds.size > 0) {
217
+ // Drain a deterministic snapshot: insertion order is replay-stable, and
218
+ // ids signaled during the awaits below land in the set for the next pass.
219
+ const toDerive = [...pendingApprovalChildIds];
220
+ pendingApprovalChildIds.clear();
221
+ for (const signaledChildId of toDerive) {
222
+ try {
223
+ const surfaced = await statusProxy.UpdateWorkflowTaskApprovalStatus(input.workflowExecutionId, input.taskName, signaledChildId);
224
+ if (!surfaced) {
225
+ log.info("Child approval gate already resolved before derivation; nothing surfaced", {
226
+ taskName: input.taskName,
227
+ childExecId: signaledChildId,
228
+ });
229
+ }
230
+ }
231
+ catch (statusErr) {
232
+ log.warn("Failed to update workflow approval status (non-fatal)", {
233
+ error: String(statusErr),
234
+ taskName: input.taskName,
235
+ });
236
+ }
200
237
  }
201
238
  }
202
239
  }
@@ -1 +1 @@
1
- {"version":3,"file":"call-agent-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/call-agent-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,GAAG,EAEH,cAAc,GACf,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,wEAAwE;AACxE,qBAAqB;AACrB,wEAAwE;AAExE,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAC/C,yBAAyB,CAC1B,CAAC;AAEF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAC/C,yBAAyB,CAC1B,CAAC;AAUF,yEAAyE;AACzE,0EAA0E;AAC1E,0EAA0E;AAC1E,qEAAqE;AACrE,0BAA0B;AAC1B,MAAM,UAAU,GAAG,eAAe,CAAkB;IAClD,mBAAmB,EAAE,IAAI;IACzB,KAAK,EAAE;QACL,eAAe,EAAE,CAAC;KACnB;CACF,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,oBAAoB,CAAmB;IACzD,mBAAmB,EAAE,KAAK;IAC1B,KAAK,EAAE;QACL,eAAe,EAAE,CAAC;QAClB,eAAe,EAAE,IAAI;QACrB,kBAAkB,EAAE,CAAC;KACtB;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,oBAAoB,CAAkB;IACvD,mBAAmB,EAAE,KAAK;IAC1B,KAAK,EAAE;QACL,eAAe,EAAE,CAAC;QAClB,eAAe,EAAE,OAAO;KACzB;CACF,CAAC,CAAC;AAuBH;;;;;;GAMG;AACH,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAkC;IAElC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,cAAc,GAAoB,EAAE,CAAC;IACzC,IAAI,aAAa,GAAY,SAAS,CAAC;IACvC,IAAI,mBAA0D,CAAC;IAC/D,IAAI,WAA+B,CAAC;IACpC,IAAI,sBAAsB,GAAG,KAAK,CAAC;IAEnC,UAAU,CAAC,qBAAqB,EAAE,CAAC,YAAuC,EAAE,EAAE;QAC5E,mBAAmB,GAAG,YAAY,CAAC;QACnC,IAAI,CAAC,WAAW,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC;YAC7C,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,qBAAqB,EAAE,CAAC,OAAyC,EAAE,EAAE;QAC9E,yEAAyE;QACzE,iFAAiF;QACjF,0DAA0D;QAC1D,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,WAAW,GAAG,OAAO,CAAC;QACxB,CAAC;aAAM,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,aAAa,IAAI,OAAO,EAAE,CAAC;YAC9E,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG;QACrB,GAAG,KAAK,CAAC,MAAM;QACf,UAAU,EAAE,KAAK,CAAC,QAAQ;QAC1B,UAAU,EAAE,KAAK,CAAC,mBAAmB;KACtC,CAAC;IAEF,GAAG,CAAC,IAAI,CAAC,8CAA8C,EAAE;QACvD,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,cAAc,CAAC,MAAM,KAAK,SAAS;QAC9C,eAAe,EAAE,cAAc,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS;QAC5D,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACjD,WAAW,EAAE,CAAC,CAAC,cAAc,CAAC,UAAU;KACzC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,UAAU;SAC/B,SAAS,CAAC,cAAc,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,gBAAgB,CAAC;SACnE,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QACf,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAoB,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,cAAc,GAAG,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,CAAC,MAAM,IAAI,EAAE,CAAoB,CAAC;QACrD,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,+CAA+C,EAAE;YACxD,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,aAAa,EAAE,cAAc,CAAC,UAAU,KAAK,SAAS;YACtD,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;SAClD,CAAC,CAAC;QACH,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACb,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,YAAY,GAAG,IAAI,CAAC;YACpB,OAAO;QACT,CAAC;QACD,aAAa,GAAG,GAAG,CAAC;QACpB,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC,CAAC,CAAC;IAEL,gFAAgF;IAChF,kFAAkF;IAClF,+DAA+D;IAC/D,IAAI,iBAAqC,CAAC;IAE1C,kFAAkF;IAClF,gFAAgF;IAChF,gFAAgF;IAChF,KAAK,UAAU,eAAe,CAAC,OAAe;QAC5C,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,WAAW,CAAC,iCAAiC,CAAC,OAAO,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,sDAAsD,EAAE;gBAC/D,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;gBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,yEAAyE;QACzE,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,GAAG,KAAK,iBAAiB;YAAE,OAAO;QACtC,iBAAiB,GAAG,GAAG,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,8BAA8B,CAAC,KAAK,CAAC,mBAAmB,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;QAC5F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,0DAA0D,EAAE;gBACnE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;gBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,CAAC,YAAY,EAAE,CAAC;QACrB,oFAAoF;QACpF,6EAA6E;QAC7E,MAAM,YAAY,GAAG,MAAM,SAAS,CAClC,GAAG,EAAE,CAAC,YAAY,IAAI,mBAAmB,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,sBAAsB,CAAC,EACrG,sBAAsB,CACvB,CAAC;QAEF,IAAI,YAAY;YAAE,MAAM;QAExB,oEAAoE;QACpE,IAAI,WAAW,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC3C,sBAAsB,GAAG,IAAI,CAAC;YAC9B,MAAM,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;YAC7C,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QAED,wEAAwE;QACxE,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC;YACjC,IAAI,QAAQ,GAAgC,IAAI,CAAC;YACjD,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,WAAW,CAAC,yBAAyB,CAAC,WAAW,CAAC,CAAC;YACtE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,GAAG,CAAC,IAAI,CAAC,4CAA4C,EAAE;oBACrD,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;oBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;iBACzB,CAAC,CAAC;YACL,CAAC;YACD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;YACnD,CAAC;YACD,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;QAED,oCAAoC;QACpC,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,YAAY,GAAG,mBAAmB,CAAC;YACzC,mBAAmB,GAAG,SAAS,CAAC;YAEhC,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC,gCAAgC,CAChD,KAAK,CAAC,mBAAmB,EACzB,KAAK,CAAC,QAAQ,EACd,YAAY,CACb,CAAC;YACJ,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACnB,GAAG,CAAC,IAAI,CAAC,uDAAuD,EAAE;oBAChE,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC;oBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;iBACzB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,0EAA0E;IAC1E,gFAAgF;IAChF,IAAI,WAAW,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC3C,MAAM,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,gFAAgF;IAChF,+EAA+E;IAC/E,8CAA8C;IAC9C,IAAI,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,2BAA2B,CAAC,KAAK,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;QACxF,CAAC;QAAC,OAAO,QAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC,sDAAsD,EAAE;gBAC/D,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC;aACxB,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,8BAA8B,CAAC,KAAK,CAAC,mBAAmB,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QAC/F,CAAC;QAAC,OAAO,QAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC,yDAAyD,EAAE;gBAClE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,aAAa,YAAY,KAAK;gBACxC,CAAC,CAAC,aAAa,CAAC,OAAO;gBACvB,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAC1B,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,aAAa,CAAC;IACtB,CAAC;IAED,mEAAmE;IACnE,8DAA8D;IAC9D,IAAI,WAAW,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE,CAAC;QACtD,cAAc,GAAG,EAAE,GAAG,cAAc,EAAE,kBAAkB,EAAE,WAAW,EAAE,CAAC;IAC1E,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,KAAkC,EAClC,WAAmB,EACnB,QAAqC;IAErC,IAAI,CAAC;QACH,MAAM,aAAa,GAA4B;YAC7C,IAAI,EAAE,qBAAqB;YAC3B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,cAAc,EAAE,KAAK,CAAC,iBAAiB,EAAE,EAAE;YAC3C,gBAAgB,EAAE,WAAW;YAC7B,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YACnC,UAAU,EAAE,QAAQ,EAAE,UAAU,IAAI,CAAC;YACrC,eAAe,EAAE,QAAQ,EAAE,eAAe,IAAI,EAAE;YAChD,cAAc,EAAE,QAAQ,EAAE,cAAc,IAAI,CAAC;YAC7C,aAAa,EAAE,QAAQ,EAAE,aAAa,IAAI,CAAC;YAC3C,cAAc,EAAE,QAAQ,EAAE,cAAc,IAAI,CAAC;SAC9C,CAAC;QACF,MAAM,UAAU,CAAC,kBAAkB,CAAC,KAAK,CAAC,mBAAmB,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC;IACtF,CAAC;IAAC,OAAO,OAAO,EAAE,CAAC;QACjB,GAAG,CAAC,IAAI,CAAC,gDAAgD,EAAE;YACzD,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"call-agent-orchestrator.js","sourceRoot":"","sources":["../../src/workflows/call-agent-orchestrator.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/runner",
3
- "version": "3.12.6",
3
+ "version": "3.12.8",
4
4
  "description": "Embeddable Temporal worker for the Stigmer AI agent platform — handles agent execution, workflow orchestration, and MCP server management",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -94,7 +94,7 @@
94
94
  "@opentelemetry/sdk-metrics": "^2.0.0",
95
95
  "@opentelemetry/sdk-trace-base": "^2.0.0",
96
96
  "@opentelemetry/sdk-trace-node": "^2.0.0",
97
- "@stigmer/protos": "3.12.6",
97
+ "@stigmer/protos": "3.12.8",
98
98
  "@temporalio/activity": "1.16.2",
99
99
  "@temporalio/common": "1.16.2",
100
100
  "@temporalio/interceptors-opentelemetry": "1.16.2",
@@ -76,7 +76,7 @@ function createMockActivities() {
76
76
  }),
77
77
  RunScript: async (): Promise<unknown> => ({ computed: 4 }),
78
78
  RunShell: async (): Promise<unknown> => "hello from shell",
79
- UpdateWorkflowTaskApprovalStatus: async (): Promise<void> => {},
79
+ UpdateWorkflowTaskApprovalStatus: async (): Promise<boolean> => false,
80
80
  ClearWorkflowApprovalStatus: async (): Promise<void> => {},
81
81
  UpdateWorkflowFileReviewStatus: async (): Promise<void> => {},
82
82
  GetAwaitingFileReviewChangeSetIds: async (): Promise<string[]> => [],
@@ -104,17 +104,42 @@ describe("call-agent-status file-review activities", () => {
104
104
  });
105
105
 
106
106
  describe("approval activities are scoped per-child (unify)", () => {
107
- it("updateWorkflowTaskApprovalStatus scopes the write to the notifying child", async () => {
108
- await updateWorkflowTaskApprovalStatus("wfx_1", "task_a", {
109
- executionId: "aex_child",
110
- pendingApprovals: [{ toolCallId: "tc_1", toolName: "deploy" } as any],
111
- } as any);
107
+ it("updateWorkflowTaskApprovalStatus derives the gate from the child record and scopes the write to it", async () => {
108
+ // Identity-only contract (DD-012, stigmer-cloud#509): the activity
109
+ // receives just the child id and reads the gate from the child's
110
+ // persisted status the signal never carries approval details.
111
+ mockGetExecutionResult = {
112
+ status: {
113
+ pendingApprovals: [{ toolCallId: "tc_1", toolName: "deploy" } as any],
114
+ },
115
+ };
112
116
 
117
+ const surfaced = await updateWorkflowTaskApprovalStatus("wfx_1", "task_a", "aex_child");
118
+
119
+ expect(surfaced).toBe(true);
113
120
  expect(capturedUpdates).toHaveLength(1);
114
121
  const { status, options } = capturedUpdates[0];
115
122
  expect(options.updatePendingApprovals).toBe(true);
116
123
  expect(options.pendingUpdateChildAgentExecutionId).toBe("aex_child");
117
124
  expect(status.pendingApprovals[0].childAgentExecutionId).toBe("aex_child");
125
+ expect(status.pendingApprovals[0].approval.toolCallId).toBe("tc_1");
126
+ });
127
+
128
+ it("updateWorkflowTaskApprovalStatus answers false and writes nothing when the child's gate already resolved", async () => {
129
+ // The child persists its gate before signaling, so an empty read means
130
+ // the gate resolved in the interim — surfacing it would show a stale
131
+ // approval card, and the orchestrator deliberately does not retry.
132
+ mockGetExecutionResult = { status: { pendingApprovals: [] } };
133
+
134
+ const surfaced = await updateWorkflowTaskApprovalStatus("wfx_1", "task_a", "aex_child");
135
+
136
+ expect(surfaced).toBe(false);
137
+ expect(capturedUpdates).toHaveLength(0);
138
+ });
139
+
140
+ it("updateWorkflowTaskApprovalStatus is a no-op without a child id", async () => {
141
+ expect(await updateWorkflowTaskApprovalStatus("wfx_1", "task_a", "")).toBe(false);
142
+ expect(capturedUpdates).toHaveLength(0);
118
143
  });
119
144
 
120
145
  it("clearWorkflowApprovalStatus scopes the clear to the given child", async () => {
@@ -737,6 +737,7 @@ function makeConfig() {
737
737
  runnerId: null,
738
738
  checkpointerType: "memory" as const,
739
739
  checkpointerProxyEndpoint: null,
740
+ artifactProxyEndpoint: null,
740
741
  primaryModel: "gpt-4.1",
741
742
  cursorStreamStallTimeoutMs: 180000,
742
743
  agentResolveTimeoutMs: 120000,
@@ -913,6 +913,7 @@ function makeConfig() {
913
913
  runnerId: null,
914
914
  checkpointerType: "memory" as const,
915
915
  checkpointerProxyEndpoint: null,
916
+ artifactProxyEndpoint: null,
916
917
  primaryModel: "gpt-4.1",
917
918
  cursorStreamStallTimeoutMs: 180000,
918
919
  agentResolveTimeoutMs: 120000,
@@ -16,7 +16,6 @@ import { StigmerClient } from "../client/stigmer-client.js";
16
16
  import { loadConfig } from "../config.js";
17
17
  import { create } from "@bufbuild/protobuf";
18
18
  import { WorkflowExecutionStatusSchema, WorkflowPendingApprovalSchema, WorkflowPendingFileReviewSchema } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/api_pb";
19
- import type { ChildApprovalNotification } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
20
19
  import { ToolCallStatus, FileChangeSetStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
21
20
 
22
21
  function buildClient(): StigmerClient {
@@ -27,23 +26,40 @@ function buildClient(): StigmerClient {
27
26
  });
28
27
  }
29
28
 
29
+ /**
30
+ * Derives the child's approval gate onto the parent (DD-012: identity-only
31
+ * signal, derive-from-child). The signal carries only the child execution id;
32
+ * this activity reads the child's persisted `status.pending_approvals` — the
33
+ * single source of truth the child's server wrote BEFORE signaling — and
34
+ * mirrors it onto the parent as reference entries.
35
+ *
36
+ * Returns true when a gate was surfaced, false when the child currently has
37
+ * no pending approvals. The child persists its gate before the signal is
38
+ * sent (both editions), so an empty read means the gate already resolved
39
+ * (e.g. approved on the agent surface in the interim) — the caller must NOT
40
+ * retry: surfacing a resolved gate would show users a stale approval card.
41
+ */
30
42
  export async function updateWorkflowTaskApprovalStatus(
31
43
  executionId: string,
32
44
  _taskName: string,
33
- notification: ChildApprovalNotification,
34
- ): Promise<void> {
35
- if (!executionId) return;
45
+ childExecutionId: string,
46
+ ): Promise<boolean> {
47
+ if (!executionId || !childExecutionId) return false;
36
48
 
37
- const childExecId = notification.executionId;
38
49
  const client = buildClient();
39
- const pendingApprovals = (notification.pendingApprovals ?? []).map(
50
+ const child = await client.getExecution(childExecutionId);
51
+ const pendingApprovals = (child?.status?.pendingApprovals ?? []).map(
40
52
  (approval) =>
41
53
  create(WorkflowPendingApprovalSchema, {
42
54
  approval,
43
- childAgentExecutionId: childExecId,
55
+ childAgentExecutionId: childExecutionId,
44
56
  }),
45
57
  );
46
58
 
59
+ if (pendingApprovals.length === 0) {
60
+ return false;
61
+ }
62
+
47
63
  const status = create(WorkflowExecutionStatusSchema, {
48
64
  pendingApprovals,
49
65
  });
@@ -52,8 +68,9 @@ export async function updateWorkflowTaskApprovalStatus(
52
68
  // approvals and preserves every parallel sibling's entries.
53
69
  await client.updateWorkflowExecutionStatus(executionId, status, {
54
70
  updatePendingApprovals: true,
55
- pendingUpdateChildAgentExecutionId: childExecId,
71
+ pendingUpdateChildAgentExecutionId: childExecutionId,
56
72
  });
73
+ return true;
57
74
  }
58
75
 
59
76
  export async function clearWorkflowApprovalStatus(
@@ -251,6 +251,85 @@ describe("buildPrompt", () => {
251
251
  expect(prompt).not.toContain("<declared_preferences>");
252
252
  });
253
253
 
254
+ it("carries the recalled memories on the first execution, framed as user-confirmed background", () => {
255
+ const prompt = buildPrompt(
256
+ input({
257
+ resolution: resolution("local", "created_first_execution"),
258
+ recalledMemories: {
259
+ facts: ["Deploys to us-east-1.", "Prefers OpenTofu."],
260
+ },
261
+ }),
262
+ );
263
+ expect(prompt).toContain("<recalled_memories>");
264
+ expect(prompt).toContain("- Deploys to us-east-1.");
265
+ expect(prompt).toContain("- Prefers OpenTofu.");
266
+ // Memories are CONTEXT like the bridge; the approval protocol keeps
267
+ // its pinned last-before-task slot.
268
+ expect(prompt.indexOf("<recalled_memories>"))
269
+ .toBeLessThan(prompt.indexOf("<tool_approval_protocol>"));
270
+ });
271
+
272
+ it("orders remembered facts after declared preferences, before the embedder's session context (DD-006 D4)", () => {
273
+ const prompt = buildPrompt(
274
+ input({
275
+ resolution: resolution("local", "created_first_execution"),
276
+ declaredPreferences: { orgContext: "We deploy to us-east-1." },
277
+ recalledMemories: { facts: ["Prefers OpenTofu."] },
278
+ sessionContext: "Role: platform admin",
279
+ }),
280
+ );
281
+ const preferences = prompt.indexOf("<declared_preferences>");
282
+ const memories = prompt.indexOf("<recalled_memories>");
283
+ const context = prompt.indexOf("<session_context>");
284
+ expect(preferences).toBeGreaterThan(-1);
285
+ expect(memories).toBeGreaterThan(preferences);
286
+ expect(context).toBeGreaterThan(memories);
287
+ });
288
+
289
+ it("never re-sends the memories to a successfully resumed agent — frozen per session by design (DD-002 D3, inherited by DD-006 D4)", () => {
290
+ const prompt = buildPrompt(
291
+ input({
292
+ resolution: resolution("local", "resumed_successfully"),
293
+ recalledMemories: { facts: ["Prefers OpenTofu."] },
294
+ }),
295
+ );
296
+ expect(prompt).toBe(USER_MESSAGE);
297
+ });
298
+
299
+ it("omits the memories section when the execution carries none", () => {
300
+ const prompt = buildPrompt(
301
+ input({ resolution: resolution("local", "created_first_execution") }),
302
+ );
303
+ expect(prompt).not.toContain("<recalled_memories>");
304
+ });
305
+
306
+ it("carries the recalled memories through the HITL-recovery shape — the standing-context drop hazard (the buildFromPlan lesson)", () => {
307
+ // A fresh agent replacing a lost one mid-HITL gets the full recovery
308
+ // shape. Standing context is hand-copied into that shape's options at
309
+ // the buildPrompt routing — a missed copy would silently lose the
310
+ // memories for the session's whole life (frozen per session).
311
+ const approvalDecisions = new Map<string, ApprovalAction>([
312
+ ["tool-call-1", ApprovalAction.APPROVE],
313
+ ]);
314
+ const prompt = buildPrompt(
315
+ input({
316
+ resolution: resolution("local", "created_after_resume_failure"),
317
+ approvalDecisions,
318
+ recalledMemories: { facts: ["Prefers OpenTofu."] },
319
+ pendingApprovals: [
320
+ create(PendingApprovalSchema, {
321
+ toolCallId: "tool-call-1",
322
+ toolName: "Write",
323
+ message: "Write file: gated.txt",
324
+ }),
325
+ ],
326
+ }),
327
+ );
328
+ expect(prompt).toContain("<recalled_memories>");
329
+ expect(prompt).toContain("- Prefers OpenTofu.");
330
+ expect(prompt).toContain("APPROVED");
331
+ });
332
+
254
333
  it("uses the reinvocation prompt for a HITL reinvocation (human-meaningful, no opaque ids)", () => {
255
334
  const approvalDecisions = new Map<string, ApprovalAction>([
256
335
  ["tool-call-1", ApprovalAction.APPROVE],
@@ -57,6 +57,7 @@ import {
57
57
  } from "../../shared/caller-identity.js";
58
58
  import { readSessionContext } from "../../shared/session-context.js";
59
59
  import { readDeclaredPreferences } from "../../shared/declared-preferences.js";
60
+ import { readRecalledMemories } from "../../shared/recalled-memories.js";
60
61
  import { withholdSecretContentFromMessages } from "../../shared/tool-row.js";
61
62
  import { StallTimeoutError, formatStallFailure } from "../../shared/stall-watchdog.js";
62
63
  import { resolveUsableArtifactStorage, loadArtifactStorageConfig, type ArtifactStorage } from "../../shared/artifact-storage.js";
@@ -83,6 +84,7 @@ import {
83
84
  readChannelConversationId,
84
85
  synthesizeConversationAttachment,
85
86
  } from "../../shared/conversation-attachment.js";
87
+ import { synthesizeMemoryAttachment } from "../../shared/memory-attachment.js";
86
88
  import { injectSynthesizedAttachment } from "../../shared/synthesized-attachment.js";
87
89
  import { mergeApprovalPolicies } from "./approval-policy.js";
88
90
  import { deriveActiveLeases, isUnattendedApprovalMode } from "../../shared/approval-policy.js";
@@ -716,6 +718,33 @@ async function executeCursorInner(
716
718
  resolvedMcpServers, conversationAttachment, "conversation participation",
717
719
  );
718
720
  }
721
+
722
+ // Phase 4a5: Synthesize the memory capture attachment (DD-005 D1) —
723
+ // the fourth sibling. The recall snapshot's enabled bit IS the
724
+ // attachment decision (server-stamped at execution create; a free
725
+ // local read, like the conversation attachment's session label). The
726
+ // capture context is attribution the server verifies or trusts per
727
+ // edition (Stage 3 provenance decision); the subject is never
728
+ // threaded — it derives from the credential.
729
+ const memoryAttachment = synthesizeMemoryAttachment(
730
+ execution.spec?.recalledMemories,
731
+ {
732
+ org: session.metadata?.org ?? "",
733
+ agentId: blueprint.agent.metadata?.id ?? "",
734
+ sessionId,
735
+ agentExecutionId: executionId,
736
+ },
737
+ {
738
+ bridgeEndpoint: config.mcpBridgeEndpoint,
739
+ credential: attachmentCredential,
740
+ backendEndpoint: config.stigmerBackendEndpoint,
741
+ },
742
+ );
743
+ if (memoryAttachment) {
744
+ resolvedMcpServers = injectSynthesizedAttachment(
745
+ resolvedMcpServers, memoryAttachment, "memory capture",
746
+ );
747
+ }
719
748
  // The one projection point: every mutation above is now visible in the
720
749
  // Cursor SDK config by construction (no per-mutation rebuild to forget).
721
750
  const mcpConfig = toCursorMcpConfig(resolvedMcpServers);
@@ -1179,6 +1208,7 @@ async function executeCursorInner(
1179
1208
  senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
1180
1209
  sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
1181
1210
  declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
1211
+ recalledMemories: readRecalledMemories(spec.recalledMemories),
1182
1212
  conversationCatchup: readConversationCatchup(spec.conversationCatchup),
1183
1213
  // The turn's recorded transcript, seeded from the persisted execution
1184
1214
  // on a reinvocation (Phase 3). Consumed only by the HITL-recovery
@@ -1886,6 +1916,7 @@ async function executeCursorInner(
1886
1916
  senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
1887
1917
  sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
1888
1918
  declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
1919
+ recalledMemories: readRecalledMemories(spec.recalledMemories),
1889
1920
  conversationCatchup: readConversationCatchup(spec.conversationCatchup),
1890
1921
  // Composed fresh (not reused from Phase 10): the failed primary
1891
1922
  // stream may have appended partial work onto status.messages,
@@ -2486,6 +2517,16 @@ export interface BuildPromptInput {
2486
2517
  * store with identical content.
2487
2518
  */
2488
2519
  declaredPreferences?: import("../../shared/declared-preferences.js").DeclaredPreferencesContent;
2520
+ /**
2521
+ * The subject's confirmed memories from the execution spec's
2522
+ * `recalled_memories` (stigmer/stigmer#293 Phase 2, DD-006). Like the
2523
+ * preferences, only the enhanced-prompt path consumes it — deliberately
2524
+ * frozen per Cursor session (DD-002 D3, inherited by DD-006 D4): the
2525
+ * first turn delivers it into the agent's own conversation store, and
2526
+ * repeating it on resumed turns would bloat the store with identical
2527
+ * content.
2528
+ */
2529
+ recalledMemories?: import("../../shared/recalled-memories.js").RecalledMemoriesContent;
2489
2530
  /**
2490
2531
  * Conversation catchup from the execution spec's `conversation_catchup`
2491
2532
  * (cloud DD-006): what happened on the channel conversation that the
@@ -2625,6 +2666,7 @@ export function buildPrompt(input: BuildPromptInput): string {
2625
2666
  senderIdentity: input.senderIdentity,
2626
2667
  sessionContext: input.sessionContext,
2627
2668
  declaredPreferences: input.declaredPreferences,
2669
+ recalledMemories: input.recalledMemories,
2628
2670
  conversationCatchup,
2629
2671
  },
2630
2672
  {
@@ -2692,6 +2734,7 @@ export function buildPrompt(input: BuildPromptInput): string {
2692
2734
  senderIdentity: input.senderIdentity,
2693
2735
  sessionContext: input.sessionContext,
2694
2736
  declaredPreferences: input.declaredPreferences,
2737
+ recalledMemories: input.recalledMemories,
2695
2738
  conversationCatchup,
2696
2739
  });
2697
2740
  }
@@ -35,6 +35,10 @@ import {
35
35
  formatDeclaredPreferencesText,
36
36
  type DeclaredPreferencesContent,
37
37
  } from "../../shared/declared-preferences.js";
38
+ import {
39
+ formatRecalledMemoriesText,
40
+ type RecalledMemoriesContent,
41
+ } from "../../shared/recalled-memories.js";
38
42
  import {
39
43
  visionDisclosureLines,
40
44
  type NotViewableEntry,
@@ -160,6 +164,16 @@ export interface EnhancedPromptOptions {
160
164
  * it every resumed turn would bloat the store with identical content.
161
165
  */
162
166
  declaredPreferences?: DeclaredPreferencesContent;
167
+ /**
168
+ * The subject's confirmed memories (stigmer/stigmer#293 Phase 2, DD-006):
169
+ * consent-gated facts server-snapshotted onto the execution spec's
170
+ * `recalled_memories` at create. Like the preferences, it lands in the
171
+ * first message and persists in the cursor agent's own conversation
172
+ * store — deliberately frozen per Cursor session (DD-002 D3, inherited
173
+ * by DD-006 D4): repeating it every resumed turn would bloat the store
174
+ * with identical content.
175
+ */
176
+ recalledMemories?: RecalledMemoriesContent;
163
177
  /**
164
178
  * Conversation catchup (cloud DD-006): what happened on the channel
165
179
  * conversation that the agent has not seen, read from the execution
@@ -253,6 +267,14 @@ export function buildEnhancedPrompt(options: EnhancedPromptOptions): string {
253
267
  sections.push(formatDeclaredPreferencesSection(options.declaredPreferences));
254
268
  }
255
269
 
270
+ // Declared-by-humans precedes learned-and-confirmed (DD-006 D4): both
271
+ // are platform-authored standing background, but a preference is the
272
+ // user's exact words while a memory is an agent's confirmed inference —
273
+ // the exact statement reads first.
274
+ if (options.recalledMemories) {
275
+ sections.push(formatRecalledMemoriesSection(options.recalledMemories));
276
+ }
277
+
256
278
  // Standing facts about the user (session context) come before the
257
279
  // carried conversation (bridge): the bridge may refer back to them.
258
280
  if (options.sessionContext) {
@@ -472,6 +494,12 @@ export function formatDeclaredPreferencesSection(
472
494
  return `<declared_preferences>\n${formatDeclaredPreferencesText(preferences)}\n</declared_preferences>`;
473
495
  }
474
496
 
497
+ export function formatRecalledMemoriesSection(
498
+ memories: RecalledMemoriesContent,
499
+ ): string {
500
+ return `<recalled_memories>\n${formatRecalledMemoriesText(memories)}\n</recalled_memories>`;
501
+ }
502
+
475
503
  export function formatSessionContextSection(context: string): string {
476
504
  return `<session_context>\n${formatSessionContextText(context)}\n</session_context>`;
477
505
  }
@@ -251,6 +251,7 @@ const httpConfig: Config = {
251
251
  cloudModeEnabled: true,
252
252
  checkpointerType: "http",
253
253
  checkpointerProxyEndpoint: "http://localhost:7234",
254
+ artifactProxyEndpoint: null,
254
255
  primaryModel: "claude-sonnet",
255
256
  cursorStreamStallTimeoutMs: 180000,
256
257
  agentResolveTimeoutMs: 120000,
@@ -296,6 +296,7 @@ const baseConfig: Config = {
296
296
  cloudModeEnabled: true,
297
297
  checkpointerType: "http",
298
298
  checkpointerProxyEndpoint: "http://localhost:7234",
299
+ artifactProxyEndpoint: null,
299
300
  primaryModel: "claude-sonnet",
300
301
  cursorStreamStallTimeoutMs: 180000,
301
302
  agentResolveTimeoutMs: 120000,
@@ -250,6 +250,7 @@ const baseConfig: Config = {
250
250
  cloudModeEnabled: true,
251
251
  checkpointerType: "http",
252
252
  checkpointerProxyEndpoint: "http://localhost:7234",
253
+ artifactProxyEndpoint: null,
253
254
  primaryModel: "claude-sonnet",
254
255
  cursorStreamStallTimeoutMs: 180000,
255
256
  agentResolveTimeoutMs: 120000,
@@ -47,6 +47,7 @@ describe("ExecuteDeepAgent activity", () => {
47
47
  cloudModeEnabled: false,
48
48
  checkpointerType: "memory",
49
49
  checkpointerProxyEndpoint: null,
50
+ artifactProxyEndpoint: null,
50
51
  primaryModel: "gpt-4.1",
51
52
  cursorStreamStallTimeoutMs: 180000,
52
53
  agentResolveTimeoutMs: 120000,
@@ -14,6 +14,7 @@ const nothing = {
14
14
  mcpServerUsageCount: 0,
15
15
  channelMessagingCount: 0,
16
16
  conversationChannelId: undefined,
17
+ memoryCaptureEnabled: false,
17
18
  };
18
19
 
19
20
  describe("shouldConnectMcp", () => {
@@ -34,4 +35,10 @@ describe("shouldConnectMcp", () => {
34
35
  // channel — the escalation tool is the ONLY source.
35
36
  expect(shouldConnectMcp({ ...nothing, conversationChannelId: "agch_1" })).toBe(true);
36
37
  });
38
+
39
+ it("enters on memory capture alone (the memory attachment)", () => {
40
+ // A tool-less agent whose user has memory on: the remember tool is
41
+ // the ONLY source, and skipping the block would silently drop it.
42
+ expect(shouldConnectMcp({ ...nothing, memoryCaptureEnabled: true })).toBe(true);
43
+ });
37
44
  });