@stigmer/runner 3.10.0 → 3.11.1-dev.20260812192248

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 (355) hide show
  1. package/README.md +14 -1
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/activities/call-llm.js +9 -10
  4. package/dist/activities/call-llm.js.map +1 -1
  5. package/dist/activities/classify-tool-approvals.d.ts +2 -1
  6. package/dist/activities/classify-tool-approvals.js +28 -2
  7. package/dist/activities/classify-tool-approvals.js.map +1 -1
  8. package/dist/activities/discover-mcp-server.d.ts +39 -0
  9. package/dist/activities/discover-mcp-server.js +165 -28
  10. package/dist/activities/discover-mcp-server.js.map +1 -1
  11. package/dist/activities/emit-event.d.ts +14 -2
  12. package/dist/activities/emit-event.js +52 -17
  13. package/dist/activities/emit-event.js.map +1 -1
  14. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +8 -0
  15. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +1 -1
  16. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -1
  17. package/dist/activities/execute-cursor/approval-state.d.ts +28 -2
  18. package/dist/activities/execute-cursor/approval-state.js +7 -1
  19. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  20. package/dist/activities/execute-cursor/attachment-resolver.d.ts +14 -0
  21. package/dist/activities/execute-cursor/attachment-resolver.js +18 -4
  22. package/dist/activities/execute-cursor/attachment-resolver.js.map +1 -1
  23. package/dist/activities/execute-cursor/blueprint-resolver.d.ts +1 -9
  24. package/dist/activities/execute-cursor/blueprint-resolver.js +6 -22
  25. package/dist/activities/execute-cursor/blueprint-resolver.js.map +1 -1
  26. package/dist/activities/execute-cursor/env-resolver.js +3 -1
  27. package/dist/activities/execute-cursor/env-resolver.js.map +1 -1
  28. package/dist/activities/execute-cursor/error-classifier.d.ts +59 -3
  29. package/dist/activities/execute-cursor/error-classifier.js +115 -6
  30. package/dist/activities/execute-cursor/error-classifier.js.map +1 -1
  31. package/dist/activities/execute-cursor/extract-structured-output.d.ts +29 -0
  32. package/dist/activities/execute-cursor/extract-structured-output.js +58 -0
  33. package/dist/activities/execute-cursor/extract-structured-output.js.map +1 -0
  34. package/dist/activities/execute-cursor/hook-script.d.ts +14 -3
  35. package/dist/activities/execute-cursor/hook-script.js +72 -10
  36. package/dist/activities/execute-cursor/hook-script.js.map +1 -1
  37. package/dist/activities/execute-cursor/index.d.ts +51 -11
  38. package/dist/activities/execute-cursor/index.js +177 -93
  39. package/dist/activities/execute-cursor/index.js.map +1 -1
  40. package/dist/activities/execute-cursor/mcp-resolver.d.ts +24 -1
  41. package/dist/activities/execute-cursor/mcp-resolver.js +5 -2
  42. package/dist/activities/execute-cursor/mcp-resolver.js.map +1 -1
  43. package/dist/activities/execute-cursor/model-pricing-data.d.ts +2 -0
  44. package/dist/activities/execute-cursor/model-pricing-data.js +13 -3
  45. package/dist/activities/execute-cursor/model-pricing-data.js.map +1 -1
  46. package/dist/activities/execute-cursor/prompt-builder.d.ts +51 -4
  47. package/dist/activities/execute-cursor/prompt-builder.js +49 -7
  48. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  49. package/dist/activities/execute-cursor/turn-recovery.d.ts +52 -0
  50. package/dist/activities/execute-cursor/turn-recovery.js +193 -0
  51. package/dist/activities/execute-cursor/turn-recovery.js.map +1 -0
  52. package/dist/activities/execute-cursor/turn-stream.js +4 -1
  53. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  54. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +18 -1
  55. package/dist/activities/execute-deep-agent/attachment-injector.js +68 -23
  56. package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
  57. package/dist/activities/execute-deep-agent/environment.js +3 -1
  58. package/dist/activities/execute-deep-agent/environment.js.map +1 -1
  59. package/dist/activities/execute-deep-agent/index.js +15 -0
  60. package/dist/activities/execute-deep-agent/index.js.map +1 -1
  61. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +7 -7
  62. package/dist/activities/execute-deep-agent/prompt-builder.js +8 -2
  63. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  64. package/dist/activities/execute-deep-agent/setup.d.ts +10 -0
  65. package/dist/activities/execute-deep-agent/setup.js +65 -24
  66. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  67. package/dist/activities/execute-deep-agent/shell-env.d.ts +5 -1
  68. package/dist/activities/execute-deep-agent/shell-env.js +7 -9
  69. package/dist/activities/execute-deep-agent/shell-env.js.map +1 -1
  70. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +18 -1
  71. package/dist/activities/execute-deep-agent/subagent-transformer.js +15 -2
  72. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  73. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +27 -6
  74. package/dist/activities/execute-deep-agent/subagent-wiring.js +26 -5
  75. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  76. package/dist/activities/hydrate-workflow-execution.js +8 -3
  77. package/dist/activities/hydrate-workflow-execution.js.map +1 -1
  78. package/dist/activities/run-command.d.ts +5 -2
  79. package/dist/activities/run-command.js +22 -10
  80. package/dist/activities/run-command.js.map +1 -1
  81. package/dist/activities/run-env.d.ts +40 -0
  82. package/dist/activities/run-env.js +66 -0
  83. package/dist/activities/run-env.js.map +1 -0
  84. package/dist/activities/workflow-event-activities.d.ts +28 -10
  85. package/dist/activities/workflow-event-activities.js +87 -58
  86. package/dist/activities/workflow-event-activities.js.map +1 -1
  87. package/dist/bootstrap.js +5 -0
  88. package/dist/bootstrap.js.map +1 -1
  89. package/dist/claimcheck/payload-codec.js +21 -1
  90. package/dist/claimcheck/payload-codec.js.map +1 -1
  91. package/dist/client/stigmer-client.d.ts +83 -21
  92. package/dist/client/stigmer-client.js +106 -29
  93. package/dist/client/stigmer-client.js.map +1 -1
  94. package/dist/encryption/config.d.ts +64 -0
  95. package/dist/encryption/config.js +108 -0
  96. package/dist/encryption/config.js.map +1 -0
  97. package/dist/encryption/index.d.ts +3 -0
  98. package/dist/encryption/index.js +3 -0
  99. package/dist/encryption/index.js.map +1 -0
  100. package/dist/encryption/payload-codec.d.ts +41 -0
  101. package/dist/encryption/payload-codec.js +130 -0
  102. package/dist/encryption/payload-codec.js.map +1 -0
  103. package/dist/middleware/index.d.ts +3 -0
  104. package/dist/middleware/index.js +7 -0
  105. package/dist/middleware/index.js.map +1 -1
  106. package/dist/middleware/path-normalization.d.ts +57 -0
  107. package/dist/middleware/path-normalization.js +109 -0
  108. package/dist/middleware/path-normalization.js.map +1 -0
  109. package/dist/middleware/types.d.ts +8 -0
  110. package/dist/payload-codecs.d.ts +17 -0
  111. package/dist/payload-codecs.js +42 -0
  112. package/dist/payload-codecs.js.map +1 -0
  113. package/dist/preflight.d.ts +31 -0
  114. package/dist/preflight.js +43 -0
  115. package/dist/preflight.js.map +1 -1
  116. package/dist/runner-manager.js +21 -17
  117. package/dist/runner-manager.js.map +1 -1
  118. package/dist/runner.js +11 -18
  119. package/dist/runner.js.map +1 -1
  120. package/dist/shared/approval-policy.d.ts +9 -3
  121. package/dist/shared/approval-policy.js +15 -6
  122. package/dist/shared/approval-policy.js.map +1 -1
  123. package/dist/shared/artifact-storage.d.ts +23 -1
  124. package/dist/shared/artifact-storage.js +51 -10
  125. package/dist/shared/artifact-storage.js.map +1 -1
  126. package/dist/shared/attachment-naming.d.ts +53 -0
  127. package/dist/shared/attachment-naming.js +59 -0
  128. package/dist/shared/attachment-naming.js.map +1 -0
  129. package/dist/shared/caller-identity.d.ts +23 -2
  130. package/dist/shared/caller-identity.js +36 -5
  131. package/dist/shared/caller-identity.js.map +1 -1
  132. package/dist/shared/channel-attachment.js +1 -0
  133. package/dist/shared/channel-attachment.js.map +1 -1
  134. package/dist/shared/checkpointer/http-saver.d.ts +26 -1
  135. package/dist/shared/checkpointer/http-saver.js +54 -8
  136. package/dist/shared/checkpointer/http-saver.js.map +1 -1
  137. package/dist/shared/conversation-attachment.js +1 -0
  138. package/dist/shared/conversation-attachment.js.map +1 -1
  139. package/dist/shared/conversation-catchup.d.ts +9 -2
  140. package/dist/shared/conversation-catchup.js +39 -6
  141. package/dist/shared/conversation-catchup.js.map +1 -1
  142. package/dist/shared/datastore-attachment.d.ts +50 -7
  143. package/dist/shared/datastore-attachment.js +93 -11
  144. package/dist/shared/datastore-attachment.js.map +1 -1
  145. package/dist/shared/grpc-retry.d.ts +5 -1
  146. package/dist/shared/grpc-retry.js +5 -1
  147. package/dist/shared/grpc-retry.js.map +1 -1
  148. package/dist/shared/http-retry.d.ts +85 -0
  149. package/dist/shared/http-retry.js +101 -0
  150. package/dist/shared/http-retry.js.map +1 -0
  151. package/dist/shared/llm-backend.d.ts +275 -0
  152. package/dist/shared/llm-backend.js +425 -0
  153. package/dist/shared/llm-backend.js.map +1 -0
  154. package/dist/shared/llm-proxy.d.ts +8 -0
  155. package/dist/shared/llm-proxy.js +15 -0
  156. package/dist/shared/llm-proxy.js.map +1 -1
  157. package/dist/shared/mcp-enabled-tools.d.ts +57 -0
  158. package/dist/shared/mcp-enabled-tools.js +86 -0
  159. package/dist/shared/mcp-enabled-tools.js.map +1 -0
  160. package/dist/shared/mcp-manager.d.ts +11 -5
  161. package/dist/shared/mcp-manager.js +47 -8
  162. package/dist/shared/mcp-manager.js.map +1 -1
  163. package/dist/shared/mcp-resolver.d.ts +39 -2
  164. package/dist/shared/mcp-resolver.js +38 -2
  165. package/dist/shared/mcp-resolver.js.map +1 -1
  166. package/dist/shared/mcp-schema-sanitizer.d.ts +70 -0
  167. package/dist/shared/mcp-schema-sanitizer.js +197 -0
  168. package/dist/shared/mcp-schema-sanitizer.js.map +1 -0
  169. package/dist/shared/model-client.d.ts +18 -5
  170. package/dist/shared/model-client.js +149 -18
  171. package/dist/shared/model-client.js.map +1 -1
  172. package/dist/shared/model-error.js +198 -5
  173. package/dist/shared/model-error.js.map +1 -1
  174. package/dist/shared/model-pricing-data.d.ts +2 -0
  175. package/dist/shared/model-pricing-data.js +13 -3
  176. package/dist/shared/model-pricing-data.js.map +1 -1
  177. package/dist/shared/model-registry.js +3 -2
  178. package/dist/shared/model-registry.js.map +1 -1
  179. package/dist/shared/plan-mode-permissions.d.ts +33 -0
  180. package/dist/shared/plan-mode-permissions.js +35 -0
  181. package/dist/shared/plan-mode-permissions.js.map +1 -0
  182. package/dist/shared/registry-endpoint.d.ts +20 -0
  183. package/dist/shared/registry-endpoint.js +25 -0
  184. package/dist/shared/registry-endpoint.js.map +1 -1
  185. package/dist/shared/runner-credential-keys.d.ts +24 -0
  186. package/dist/shared/runner-credential-keys.js +47 -0
  187. package/dist/shared/runner-credential-keys.js.map +1 -0
  188. package/dist/worker.d.ts +2 -1
  189. package/dist/worker.js +2 -4
  190. package/dist/worker.js.map +1 -1
  191. package/dist/workflow-engine/resolve.d.ts +19 -1
  192. package/dist/workflow-engine/resolve.js +37 -2
  193. package/dist/workflow-engine/resolve.js.map +1 -1
  194. package/dist/workflow-engine/types.d.ts +18 -0
  195. package/dist/workflow-engine/types.js.map +1 -1
  196. package/dist/workflows/call-agent-orchestrator.d.ts +9 -0
  197. package/dist/workflows/call-agent-orchestrator.js +1 -0
  198. package/dist/workflows/call-agent-orchestrator.js.map +1 -1
  199. package/dist/workflows/connect-mcp-server.js +9 -0
  200. package/dist/workflows/connect-mcp-server.js.map +1 -1
  201. package/dist/workflows/engine-core.js +23 -2
  202. package/dist/workflows/engine-core.js.map +1 -1
  203. package/dist/workflows/execute-from-execution.d.ts +1 -1
  204. package/dist/workflows/execute-from-execution.js +11 -1
  205. package/dist/workflows/execute-from-execution.js.map +1 -1
  206. package/dist/workflows/types.d.ts +8 -0
  207. package/package.json +9 -4
  208. package/src/__test-utils__/__tests__/vitest-global-setup.test.ts +37 -0
  209. package/src/__test-utils__/vitest-global-setup.ts +50 -0
  210. package/src/__tests__/bootstrap.test.ts +43 -0
  211. package/src/__tests__/claimcheck-codec.test.ts +36 -0
  212. package/src/__tests__/encryption-codec.test.ts +287 -0
  213. package/src/__tests__/fixtures/encrypted-payload-fixture.json +15 -0
  214. package/src/__tests__/history-encryption-e2e.test.ts +243 -0
  215. package/src/__tests__/preflight.test.ts +65 -2
  216. package/src/activities/__tests__/call-llm.test.ts +75 -0
  217. package/src/activities/__tests__/classify-tool-approvals.test.ts +117 -1
  218. package/src/activities/__tests__/discover-mcp-server.hang.test.ts +103 -0
  219. package/src/activities/__tests__/discover-mcp-server.test.ts +242 -1
  220. package/src/activities/__tests__/error-classifier.test.ts +94 -2
  221. package/src/activities/__tests__/run-command.test.ts +221 -0
  222. package/src/activities/__tests__/workflow-event-activities.test.ts +107 -8
  223. package/src/activities/call-llm.ts +9 -16
  224. package/src/activities/classify-tool-approvals.ts +34 -4
  225. package/src/activities/discover-mcp-server.ts +203 -31
  226. package/src/activities/emit-event.ts +65 -21
  227. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +9 -0
  228. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +14 -0
  229. package/src/activities/execute-cursor/__tests__/attachment-resolver.test.ts +53 -0
  230. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +151 -16
  231. package/src/activities/execute-cursor/__tests__/error-classifier-extraction.test.ts +208 -0
  232. package/src/activities/execute-cursor/__tests__/extract-structured-output.test.ts +120 -0
  233. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +93 -0
  234. package/src/activities/execute-cursor/__tests__/mcp-resolver.test.ts +125 -0
  235. package/src/activities/execute-cursor/__tests__/model-pricing.test.ts +62 -1
  236. package/src/activities/execute-cursor/__tests__/prompt-builder-delegation.test.ts +1 -1
  237. package/src/activities/execute-cursor/__tests__/turn-recovery.test.ts +160 -0
  238. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +13 -0
  239. package/src/activities/execute-cursor/approval-state.ts +30 -1
  240. package/src/activities/execute-cursor/attachment-resolver.ts +31 -3
  241. package/src/activities/execute-cursor/blueprint-resolver.ts +7 -27
  242. package/src/activities/execute-cursor/env-resolver.ts +3 -1
  243. package/src/activities/execute-cursor/error-classifier.ts +131 -7
  244. package/src/activities/execute-cursor/extract-structured-output.ts +72 -0
  245. package/src/activities/execute-cursor/hook-script.ts +74 -10
  246. package/src/activities/execute-cursor/index.ts +209 -109
  247. package/src/activities/execute-cursor/mcp-resolver.ts +36 -2
  248. package/src/activities/execute-cursor/model-pricing-data.ts +22 -3
  249. package/src/activities/execute-cursor/prompt-builder.ts +85 -9
  250. package/src/activities/execute-cursor/turn-recovery.ts +208 -0
  251. package/src/activities/execute-cursor/turn-stream.ts +5 -2
  252. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +110 -8
  253. package/src/activities/execute-deep-agent/__tests__/datastore-degradation.test.ts +104 -0
  254. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +2 -0
  255. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +1 -0
  256. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +1 -0
  257. package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +174 -0
  258. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +34 -5
  259. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
  260. package/src/activities/execute-deep-agent/__tests__/shell-env.test.ts +24 -10
  261. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +178 -0
  262. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +12 -7
  263. package/src/activities/execute-deep-agent/attachment-injector.ts +94 -30
  264. package/src/activities/execute-deep-agent/environment.ts +3 -1
  265. package/src/activities/execute-deep-agent/index.ts +20 -0
  266. package/src/activities/execute-deep-agent/prompt-builder.ts +20 -10
  267. package/src/activities/execute-deep-agent/setup.ts +85 -29
  268. package/src/activities/execute-deep-agent/shell-env.ts +8 -9
  269. package/src/activities/execute-deep-agent/subagent-transformer.ts +30 -2
  270. package/src/activities/execute-deep-agent/subagent-wiring.ts +39 -6
  271. package/src/activities/hydrate-workflow-execution.ts +8 -3
  272. package/src/activities/run-command.ts +25 -12
  273. package/src/activities/run-env.ts +79 -0
  274. package/src/activities/workflow-event-activities.ts +96 -69
  275. package/src/bootstrap.ts +5 -0
  276. package/src/claimcheck/payload-codec.ts +33 -1
  277. package/src/client/__tests__/stigmer-client.test.ts +110 -11
  278. package/src/client/stigmer-client.ts +150 -37
  279. package/src/encryption/config.ts +155 -0
  280. package/src/encryption/index.ts +3 -0
  281. package/src/encryption/payload-codec.ts +152 -0
  282. package/src/middleware/__tests__/path-normalization.test.ts +140 -0
  283. package/src/middleware/index.ts +8 -0
  284. package/src/middleware/path-normalization.ts +125 -0
  285. package/src/middleware/types.ts +11 -0
  286. package/src/payload-codecs.ts +62 -0
  287. package/src/preflight.ts +45 -0
  288. package/src/runner-manager.ts +26 -26
  289. package/src/runner.ts +12 -27
  290. package/src/shared/__tests__/approval-policy.test.ts +82 -39
  291. package/src/shared/__tests__/artifact-storage.test.ts +145 -2
  292. package/src/shared/__tests__/attachment-naming.test.ts +159 -0
  293. package/src/shared/__tests__/bedrock-adapter.test.ts +213 -0
  294. package/src/shared/__tests__/bedrock-seam.test.ts +390 -0
  295. package/src/shared/__tests__/caller-identity.test.ts +25 -0
  296. package/src/shared/__tests__/channel-attachment.test.ts +1 -1
  297. package/src/shared/__tests__/connect-backfill.test.ts +1 -0
  298. package/src/shared/__tests__/conversation-attachment.test.ts +1 -1
  299. package/src/shared/__tests__/conversation-catchup.test.ts +24 -0
  300. package/src/shared/__tests__/datastore-attachment.test.ts +129 -1
  301. package/src/shared/__tests__/foundry-adapter.test.ts +276 -0
  302. package/src/shared/__tests__/foundry-seam.test.ts +482 -0
  303. package/src/shared/__tests__/http-retry.test.ts +68 -0
  304. package/src/shared/__tests__/llm-backend.test.ts +616 -0
  305. package/src/shared/__tests__/mcp-enabled-tools.test.ts +86 -0
  306. package/src/shared/__tests__/mcp-manager.test.ts +137 -15
  307. package/src/shared/__tests__/mcp-resolver.test.ts +146 -3
  308. package/src/shared/__tests__/mcp-schema-sanitizer.test.ts +267 -0
  309. package/src/shared/__tests__/model-client.test.ts +200 -0
  310. package/src/shared/__tests__/model-error.test.ts +289 -1
  311. package/src/shared/__tests__/model-pricing.test.ts +62 -2
  312. package/src/shared/__tests__/model-registry.test.ts +22 -0
  313. package/src/shared/__tests__/synthesized-attachment.test.ts +1 -0
  314. package/src/shared/__tests__/vertex-adapter.test.ts +169 -0
  315. package/src/shared/__tests__/vertex-seam.test.ts +295 -0
  316. package/src/shared/approval-policy.ts +14 -7
  317. package/src/shared/artifact-storage.ts +75 -10
  318. package/src/shared/attachment-naming.ts +78 -0
  319. package/src/shared/caller-identity.ts +40 -5
  320. package/src/shared/channel-attachment.ts +1 -0
  321. package/src/shared/checkpointer/__tests__/http-saver.test.ts +196 -1
  322. package/src/shared/checkpointer/http-saver.ts +71 -8
  323. package/src/shared/conversation-attachment.ts +1 -0
  324. package/src/shared/conversation-catchup.ts +39 -6
  325. package/src/shared/datastore-attachment.ts +106 -11
  326. package/src/shared/grpc-retry.ts +5 -1
  327. package/src/shared/http-retry.ts +139 -0
  328. package/src/shared/llm-backend.ts +544 -0
  329. package/src/shared/llm-proxy.ts +15 -0
  330. package/src/shared/mcp-enabled-tools.ts +105 -0
  331. package/src/shared/mcp-manager.ts +56 -8
  332. package/src/shared/mcp-resolver.ts +73 -2
  333. package/src/shared/mcp-schema-sanitizer.ts +224 -0
  334. package/src/shared/model-client.ts +179 -19
  335. package/src/shared/model-error.ts +222 -4
  336. package/src/shared/model-pricing-data.ts +22 -3
  337. package/src/shared/model-registry.ts +7 -2
  338. package/src/shared/plan-mode-permissions.ts +37 -0
  339. package/src/shared/registry-endpoint.ts +27 -0
  340. package/src/shared/runner-credential-keys.ts +46 -0
  341. package/src/worker.ts +4 -5
  342. package/src/workflow-engine/__tests__/tasks/emit-event.test.ts +127 -49
  343. package/src/workflow-engine/resolve.ts +48 -2
  344. package/src/workflow-engine/types.ts +18 -0
  345. package/src/workflows/__tests__/connect-mcp-server.test.ts +25 -0
  346. package/src/workflows/__tests__/execute-serverless-workflow.test.ts +68 -2
  347. package/src/workflows/call-agent-orchestrator.ts +10 -0
  348. package/src/workflows/connect-mcp-server.ts +9 -0
  349. package/src/workflows/engine-core.ts +23 -2
  350. package/src/workflows/execute-from-execution.ts +12 -2
  351. package/src/workflows/types.ts +8 -0
  352. package/dist/activities/execute-cursor/mcp-config.d.ts +0 -30
  353. package/dist/activities/execute-cursor/mcp-config.js +0 -39
  354. package/dist/activities/execute-cursor/mcp-config.js.map +0 -1
  355. package/src/activities/execute-cursor/mcp-config.ts +0 -66
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Payload-encryption configuration (stigmer-cloud#227, stigmer#398).
3
+ *
4
+ * Two key sources, strict precedence:
5
+ *
6
+ * 1. Environment (STIGMER_PAYLOAD_ENCRYPTION_KEY(_ID)) — the operator's
7
+ * explicit choice: self-hosted deployments sharing one key with their
8
+ * server, and cloud sandboxes injected with the platform key. When the
9
+ * env key is set, bootstrap-delivered material is ignored entirely.
10
+ * 2. Bootstrap-delivered — server-managed per-identity keys handed to
11
+ * desktop-class runners by getRunnerBootstrapConfig. Held in memory
12
+ * only; persistence lives server-side, which is what makes Temporal
13
+ * replay work across runner restarts (every boot re-fetches the SAME
14
+ * key).
15
+ *
16
+ * Encryption is enabled iff a key is present from either source — the same
17
+ * enabled-iff-configured pattern as the claim-check codec. A malformed key
18
+ * fails the boot rather than silently running plaintext: an operator who set
19
+ * the key (or a server that minted one) intended history to be encrypted.
20
+ *
21
+ * Key rotation: payloads carry the id of the key that encrypted them.
22
+ * During a rotation window the previous key stays readable via the
23
+ * secondary pair while new payloads are written under the primary key.
24
+ * Workers capture keys at construction, so a rotated bootstrap key lands
25
+ * on the next runner boot — there is no live re-key.
26
+ */
27
+ const KEY_ENV = "STIGMER_PAYLOAD_ENCRYPTION_KEY";
28
+ const KEY_ID_ENV = "STIGMER_PAYLOAD_ENCRYPTION_KEY_ID";
29
+ const SECONDARY_KEY_ENV = "STIGMER_PAYLOAD_ENCRYPTION_SECONDARY_KEY";
30
+ const SECONDARY_KEY_ID_ENV = "STIGMER_PAYLOAD_ENCRYPTION_SECONDARY_KEY_ID";
31
+ const AES_256_KEY_BYTES = 32;
32
+ /**
33
+ * Returns the encryption config, or undefined when encryption is not
34
+ * configured (the codec is then simply not installed).
35
+ *
36
+ * Source precedence: the env key wins outright; bootstrap-delivered
37
+ * material applies only when no env key is set (see the module doc).
38
+ *
39
+ * @throws when a key is present but malformed, or a key id is missing —
40
+ * key misconfiguration must stop the boot, not degrade to plaintext.
41
+ * This applies equally to bootstrap material: a server that hands out
42
+ * a bad key or omits its id has broken the protocol contract, and
43
+ * running plaintext against a server that manages keys would silently
44
+ * defeat the feature.
45
+ */
46
+ export function loadPayloadEncryptionConfig(bootstrap) {
47
+ const rawKey = process.env[KEY_ENV];
48
+ if (rawKey) {
49
+ const primary = {
50
+ keyId: requireKeyId(KEY_ID_ENV),
51
+ key: parseKey(rawKey, KEY_ENV),
52
+ };
53
+ const rawSecondary = process.env[SECONDARY_KEY_ENV];
54
+ const secondary = rawSecondary
55
+ ? {
56
+ keyId: requireKeyId(SECONDARY_KEY_ID_ENV),
57
+ key: parseKey(rawSecondary, SECONDARY_KEY_ENV),
58
+ }
59
+ : undefined;
60
+ return { primary, secondary };
61
+ }
62
+ if (bootstrap?.key) {
63
+ const primary = {
64
+ keyId: requireBootstrapKeyId(bootstrap.keyId, "payload_encryption_key_id"),
65
+ key: parseKey(bootstrap.key, "bootstrap payload_encryption_key"),
66
+ };
67
+ const secondary = bootstrap.secondaryKey
68
+ ? {
69
+ keyId: requireBootstrapKeyId(bootstrap.secondaryKeyId, "payload_encryption_secondary_key_id"),
70
+ key: parseKey(bootstrap.secondaryKey, "bootstrap payload_encryption_secondary_key"),
71
+ }
72
+ : undefined;
73
+ return { primary, secondary };
74
+ }
75
+ return undefined;
76
+ }
77
+ function requireKeyId(envName) {
78
+ const keyId = process.env[envName];
79
+ // An explicit id is required (no default): during rotation two keys
80
+ // coexist, and payloads must name which one encrypted them.
81
+ if (!keyId) {
82
+ throw new Error(`Payload encryption misconfigured: ${envName} is required when the ` +
83
+ `corresponding key is set`);
84
+ }
85
+ return keyId;
86
+ }
87
+ function requireBootstrapKeyId(keyId, fieldName) {
88
+ if (!keyId) {
89
+ throw new Error(`Runner bootstrap returned a payload encryption key without its ${fieldName} — ` +
90
+ `refusing to encrypt under an unidentified key (server contract violation)`);
91
+ }
92
+ return keyId;
93
+ }
94
+ function parseKey(rawBase64, envName) {
95
+ let key;
96
+ try {
97
+ key = Buffer.from(rawBase64, "base64");
98
+ }
99
+ catch {
100
+ throw new Error(`Payload encryption misconfigured: ${envName} is not valid base64`);
101
+ }
102
+ if (key.length !== AES_256_KEY_BYTES) {
103
+ throw new Error(`Payload encryption misconfigured: ${envName} must decode to ` +
104
+ `${AES_256_KEY_BYTES} bytes (AES-256), got ${key.length}`);
105
+ }
106
+ return key;
107
+ }
108
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/encryption/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { EncryptionPayloadCodec } from "./payload-codec.js";
2
+ export { loadPayloadEncryptionConfig } from "./config.js";
3
+ export type { PayloadEncryptionConfig, EncryptionKey } from "./config.js";
@@ -0,0 +1,3 @@
1
+ export { EncryptionPayloadCodec } from "./payload-codec.js";
2
+ export { loadPayloadEncryptionConfig } from "./config.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/encryption/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Temporal PayloadCodec that encrypts payloads at rest in workflow
3
+ * history (stigmer-cloud#227).
4
+ *
5
+ * Why: the workflow engine runs inside the Temporal deterministic
6
+ * sandbox, so decrypted execution-context values cross the history
7
+ * boundary in many places — the hydrate activity result, the runtime
8
+ * env passed as an input to every per-task activity, and expression
9
+ * results recorded as local-activity markers. Encrypting at the payload
10
+ * codec layer closes the entire class with one mechanism instead of
11
+ * chasing each crossing.
12
+ *
13
+ * Envelope (cross-SDK contract — the Java decode-only codec in
14
+ * stigmer-cloud's temporal-starter must match it byte-for-byte, pinned
15
+ * by the conformance fixture in __tests__/fixtures/):
16
+ *
17
+ * metadata: encoding = "binary/encrypted"
18
+ * encryption-key-id = <key id that encrypted this payload>
19
+ * data: iv (12 bytes) ‖ AES-256-GCM(ciphertext ‖ tag (16 bytes))
20
+ *
21
+ * The plaintext is the serialized ORIGINAL Payload proto (metadata AND
22
+ * data), so decode restores the payload exactly — including its
23
+ * original encoding — with no side channel.
24
+ *
25
+ * Decode passes through payloads it did not encode. This is what keeps
26
+ * plaintext signals from the Java/Go orchestrators and pre-rollout
27
+ * in-flight histories working with zero migration. Everything else
28
+ * fails closed: unknown key id, missing key id, and ciphertext tampering
29
+ * all throw rather than surfacing bogus payloads.
30
+ */
31
+ import type { Payload, PayloadCodec } from "@temporalio/common";
32
+ import type { PayloadEncryptionConfig } from "./config.js";
33
+ export declare class EncryptionPayloadCodec implements PayloadCodec {
34
+ private readonly config;
35
+ private readonly decryptKeysById;
36
+ constructor(config: PayloadEncryptionConfig);
37
+ encode(payloads: Payload[]): Promise<Payload[]>;
38
+ decode(payloads: Payload[]): Promise<Payload[]>;
39
+ private encodePayload;
40
+ private decodePayload;
41
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Temporal PayloadCodec that encrypts payloads at rest in workflow
3
+ * history (stigmer-cloud#227).
4
+ *
5
+ * Why: the workflow engine runs inside the Temporal deterministic
6
+ * sandbox, so decrypted execution-context values cross the history
7
+ * boundary in many places — the hydrate activity result, the runtime
8
+ * env passed as an input to every per-task activity, and expression
9
+ * results recorded as local-activity markers. Encrypting at the payload
10
+ * codec layer closes the entire class with one mechanism instead of
11
+ * chasing each crossing.
12
+ *
13
+ * Envelope (cross-SDK contract — the Java decode-only codec in
14
+ * stigmer-cloud's temporal-starter must match it byte-for-byte, pinned
15
+ * by the conformance fixture in __tests__/fixtures/):
16
+ *
17
+ * metadata: encoding = "binary/encrypted"
18
+ * encryption-key-id = <key id that encrypted this payload>
19
+ * data: iv (12 bytes) ‖ AES-256-GCM(ciphertext ‖ tag (16 bytes))
20
+ *
21
+ * The plaintext is the serialized ORIGINAL Payload proto (metadata AND
22
+ * data), so decode restores the payload exactly — including its
23
+ * original encoding — with no side channel.
24
+ *
25
+ * Decode passes through payloads it did not encode. This is what keeps
26
+ * plaintext signals from the Java/Go orchestrators and pre-rollout
27
+ * in-flight histories working with zero migration. Everything else
28
+ * fails closed: unknown key id, missing key id, and ciphertext tampering
29
+ * all throw rather than surfacing bogus payloads.
30
+ */
31
+ import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
32
+ // Default-import + destructure, NOT `import { temporal } from …`:
33
+ // @temporalio/proto is CommonJS and its `temporal` export defeats Node's
34
+ // cjs-module-lexer named-export detection, so the named form loads under
35
+ // tsx/vitest (their interop is looser) but crashes plain `node dist/main.js`
36
+ // at startup with "Named export 'temporal' not found" (stigmer/stigmer#399
37
+ // boot regression). Pinned by scripts/verify-dist-boot.mjs in CI.
38
+ import proto from "@temporalio/proto";
39
+ const { temporal } = proto;
40
+ const ENCODING_METADATA_KEY = "encoding";
41
+ const ENCRYPTED_ENCODING_VALUE = "binary/encrypted";
42
+ const KEY_ID_METADATA_KEY = "encryption-key-id";
43
+ /** AES-GCM parameters shared with the Java implementation. */
44
+ const IV_BYTES = 12;
45
+ const AUTH_TAG_BYTES = 16;
46
+ export class EncryptionPayloadCodec {
47
+ config;
48
+ decryptKeysById;
49
+ constructor(config) {
50
+ this.config = config;
51
+ this.decryptKeysById = new Map([[config.primary.keyId, config.primary.key]]);
52
+ if (config.secondary) {
53
+ this.decryptKeysById.set(config.secondary.keyId, config.secondary.key);
54
+ }
55
+ }
56
+ async encode(payloads) {
57
+ return payloads.map((p) => this.encodePayload(p));
58
+ }
59
+ async decode(payloads) {
60
+ return payloads.map((p) => this.decodePayload(p));
61
+ }
62
+ encodePayload(payload) {
63
+ // Data-less payloads (binary/null from void results) stay as-is:
64
+ // there is nothing to protect, and the cross-language parents that
65
+ // await our workflows as void must be able to read them without a key.
66
+ if (!payload.data || payload.data.length === 0) {
67
+ return payload;
68
+ }
69
+ const plaintext = temporal.api.common.v1.Payload.encode(payload).finish();
70
+ return {
71
+ metadata: {
72
+ [ENCODING_METADATA_KEY]: Buffer.from(ENCRYPTED_ENCODING_VALUE),
73
+ [KEY_ID_METADATA_KEY]: Buffer.from(this.config.primary.keyId),
74
+ },
75
+ data: encrypt(plaintext, this.config.primary),
76
+ };
77
+ }
78
+ decodePayload(payload) {
79
+ if (!isEncryptedPayload(payload)) {
80
+ return payload;
81
+ }
82
+ const keyIdBytes = payload.metadata?.[KEY_ID_METADATA_KEY];
83
+ if (!keyIdBytes) {
84
+ throw new Error("Encrypted payload is missing its encryption-key-id metadata — refusing to decode");
85
+ }
86
+ const keyId = Buffer.from(keyIdBytes).toString("utf-8");
87
+ const key = this.decryptKeysById.get(keyId);
88
+ if (!key) {
89
+ throw new Error(`Encrypted payload uses unknown key id '${keyId}' — configure it as the ` +
90
+ `primary or secondary payload encryption key (rotation window?)`);
91
+ }
92
+ const plaintext = decrypt(payload.data, key, keyId);
93
+ return temporal.api.common.v1.Payload.decode(plaintext);
94
+ }
95
+ }
96
+ function isEncryptedPayload(payload) {
97
+ const encoding = payload.metadata?.[ENCODING_METADATA_KEY];
98
+ if (!encoding)
99
+ return false;
100
+ return Buffer.from(encoding).toString("utf-8") === ENCRYPTED_ENCODING_VALUE;
101
+ }
102
+ function encrypt(plaintext, key) {
103
+ const iv = randomBytes(IV_BYTES);
104
+ const cipher = createCipheriv("aes-256-gcm", key.key, iv);
105
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
106
+ // Layout iv ‖ ciphertext ‖ tag matches Java's AES/GCM/NoPadding, whose
107
+ // doFinal() output is ciphertext ‖ tag.
108
+ return Buffer.concat([iv, ciphertext, cipher.getAuthTag()]);
109
+ }
110
+ function decrypt(data, key, keyId) {
111
+ if (data.length < IV_BYTES + AUTH_TAG_BYTES) {
112
+ throw new Error(`Encrypted payload under key id '${keyId}' is truncated (${data.length} bytes)`);
113
+ }
114
+ const buf = Buffer.from(data);
115
+ const iv = buf.subarray(0, IV_BYTES);
116
+ const ciphertext = buf.subarray(IV_BYTES, buf.length - AUTH_TAG_BYTES);
117
+ const tag = buf.subarray(buf.length - AUTH_TAG_BYTES);
118
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
119
+ decipher.setAuthTag(tag);
120
+ try {
121
+ return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
122
+ }
123
+ catch {
124
+ // GCM auth failure: tampered ciphertext or a key that does not match
125
+ // its advertised id. Never surface partially decrypted bytes.
126
+ throw new Error(`Failed to decrypt payload under key id '${keyId}' — ciphertext is ` +
127
+ `corrupt or the configured key does not match`);
128
+ }
129
+ }
130
+ //# sourceMappingURL=payload-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-codec.js","sourceRoot":"","sources":["../../src/encryption/payload-codec.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,9 @@
4
4
  * Assembles the ordered middleware array from a MiddlewareStackConfig.
5
5
  * The composition order matches the Python create_deep_agent injection:
6
6
  *
7
+ * 0. Path normalization (conditional: only on permission-rule-bearing
8
+ * graphs — FIRST, so every downstream middleware observes canonical
9
+ * workspace-absolute paths)
7
10
  * 1. Loop detection (always)
8
11
  * 2. Execution budget (always)
9
12
  * 3. Tool truncation (always)
@@ -4,6 +4,9 @@
4
4
  * Assembles the ordered middleware array from a MiddlewareStackConfig.
5
5
  * The composition order matches the Python create_deep_agent injection:
6
6
  *
7
+ * 0. Path normalization (conditional: only on permission-rule-bearing
8
+ * graphs — FIRST, so every downstream middleware observes canonical
9
+ * workspace-absolute paths)
7
10
  * 1. Loop detection (always)
8
11
  * 2. Execution budget (always)
9
12
  * 3. Tool truncation (always)
@@ -12,6 +15,7 @@
12
15
  * 6. Error hints (always)
13
16
  * 7. OTel spans (always, no-op when OTel not configured)
14
17
  */
18
+ import { createPathNormalizationMiddleware } from "./path-normalization.js";
15
19
  import { createLoopDetectionMiddleware } from "./loop-detection.js";
16
20
  import { createExecutionBudgetMiddleware } from "./execution-budget.js";
17
21
  import { createToolTruncationMiddleware } from "./tool-truncation.js";
@@ -22,6 +26,9 @@ import { createErrorHintsMiddleware } from "./error-hints.js";
22
26
  import { createOtelSpansMiddleware } from "./otel-spans.js";
23
27
  export function buildMiddlewareStack(config = {}) {
24
28
  const stack = [];
29
+ if (config.pathNormalization) {
30
+ stack.push(createPathNormalizationMiddleware(config.pathNormalization));
31
+ }
25
32
  stack.push(createLoopDetectionMiddleware(config.loopDetection));
26
33
  stack.push(createExecutionBudgetMiddleware(config.executionBudget));
27
34
  stack.push(createToolTruncationMiddleware(config.toolTruncation));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAY5D,MAAM,UAAU,oBAAoB,CAClC,SAAgC,EAAE;IAElC,MAAM,KAAK,GAAwB,EAAE,CAAC;IAEtC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;IAEhE,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;IAEpE,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;IAElE,MAAM,YAAY,GAAG,4BAA4B,EAAE,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAEzB,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAE9B,KAAK,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAExD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC,CAAC;IACzC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IAExD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC5D,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAE,iCAAiC,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAA0B,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAY5D,MAAM,UAAU,oBAAoB,CAClC,SAAgC,EAAE;IAElC,MAAM,KAAK,GAAwB,EAAE,CAAC;IAEtC,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;IAEhE,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;IAEpE,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;IAElE,MAAM,YAAY,GAAG,4BAA4B,EAAE,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAEzB,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAE9B,KAAK,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAExD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,0BAA0B,EAAE,CAAC,CAAC;IACzC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IAExD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Workspace-relative path normalization for permission-rule-bearing graphs
3
+ * (issue #429).
4
+ *
5
+ * deepagents' permission enforcement canonicalizes tool-call paths BEFORE any
6
+ * rule or backend runs, and its validation refuses non-absolute paths — on
7
+ * EVERY filesystem tool call once a graph carries any permission rules, reads
8
+ * included. Plan mode is the only rule-bearing production configuration
9
+ * (shared/plan-mode-permissions.ts), so there a workspace-relative path —
10
+ * the shape the multi-workspace prompt explicitly mandates, and one models
11
+ * routinely choose in single-workspace sessions — fails with
12
+ * `path must be absolute` instead of just working, burning tool rounds until
13
+ * the model adapts by switching to absolute paths.
14
+ *
15
+ * This middleware repairs the contract at our own seam: it rewrites
16
+ * workspace-relative paths on the deepagents built-in filesystem tools to
17
+ * workspace-absolute before the tool (and therefore enforcement) runs. The
18
+ * write-deny rule then fires as designed and reads succeed on the first try.
19
+ * Rule-less (act-mode) graphs never install it — the legacy backend already
20
+ * resolves relative paths under the workspace root, so act mode keeps a
21
+ * byte-zero delta.
22
+ *
23
+ * Invariant — nothing becomes newly reachable: only paths whose resolution
24
+ * stays INSIDE the workspace root are rewritten. Escaping relatives (`../x`)
25
+ * and `~`-carrying paths are left raw so today's validation refusal keeps
26
+ * speaking (a naive join would resolve `..` away and smuggle an out-of-root
27
+ * read past validation), and absolute paths pass through byte-untouched.
28
+ * The middleware converts false errors into correct behavior — never a
29
+ * refusal into an allowance the rules didn't decide.
30
+ *
31
+ * Tool matching is by bare built-in name, the house doctrine (an MCP server
32
+ * is not expected to shadow a built-in name — see shared/tool-kind.ts); the
33
+ * rewrite touches only the tool's path-bearing argument, never glob/grep
34
+ * patterns. Install FIRST in the stack so every downstream middleware
35
+ * (approval gate, error hints, otel spans) observes canonical paths.
36
+ */
37
+ import type { StigmerMiddleware } from "./types.js";
38
+ export interface PathNormalizationConfig {
39
+ /** The workspace root the graph's filesystem backend resolves against. */
40
+ readonly rootDir: string;
41
+ }
42
+ /**
43
+ * Rewrite `raw` to its workspace-absolute form, or return undefined when the
44
+ * value must be left untouched (absolute already, `~`-carrying, or escaping
45
+ * the workspace root). Exported for direct unit testing of the mapping table.
46
+ */
47
+ export declare function normalizeWorkspacePathArg(raw: string, rootDir: string): string | undefined;
48
+ /**
49
+ * Create middleware that normalizes workspace-relative paths on the built-in
50
+ * filesystem tools before permission enforcement sees them.
51
+ *
52
+ * Installed only on graphs that carry filesystem permission rules — derive
53
+ * the install condition from the same expression that supplies the rules
54
+ * (setup.ts / compileSubagents) so the rules and their normalization shim
55
+ * cannot drift apart.
56
+ */
57
+ export declare function createPathNormalizationMiddleware(config: PathNormalizationConfig): StigmerMiddleware;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Workspace-relative path normalization for permission-rule-bearing graphs
3
+ * (issue #429).
4
+ *
5
+ * deepagents' permission enforcement canonicalizes tool-call paths BEFORE any
6
+ * rule or backend runs, and its validation refuses non-absolute paths — on
7
+ * EVERY filesystem tool call once a graph carries any permission rules, reads
8
+ * included. Plan mode is the only rule-bearing production configuration
9
+ * (shared/plan-mode-permissions.ts), so there a workspace-relative path —
10
+ * the shape the multi-workspace prompt explicitly mandates, and one models
11
+ * routinely choose in single-workspace sessions — fails with
12
+ * `path must be absolute` instead of just working, burning tool rounds until
13
+ * the model adapts by switching to absolute paths.
14
+ *
15
+ * This middleware repairs the contract at our own seam: it rewrites
16
+ * workspace-relative paths on the deepagents built-in filesystem tools to
17
+ * workspace-absolute before the tool (and therefore enforcement) runs. The
18
+ * write-deny rule then fires as designed and reads succeed on the first try.
19
+ * Rule-less (act-mode) graphs never install it — the legacy backend already
20
+ * resolves relative paths under the workspace root, so act mode keeps a
21
+ * byte-zero delta.
22
+ *
23
+ * Invariant — nothing becomes newly reachable: only paths whose resolution
24
+ * stays INSIDE the workspace root are rewritten. Escaping relatives (`../x`)
25
+ * and `~`-carrying paths are left raw so today's validation refusal keeps
26
+ * speaking (a naive join would resolve `..` away and smuggle an out-of-root
27
+ * read past validation), and absolute paths pass through byte-untouched.
28
+ * The middleware converts false errors into correct behavior — never a
29
+ * refusal into an allowance the rules didn't decide.
30
+ *
31
+ * Tool matching is by bare built-in name, the house doctrine (an MCP server
32
+ * is not expected to shadow a built-in name — see shared/tool-kind.ts); the
33
+ * rewrite touches only the tool's path-bearing argument, never glob/grep
34
+ * patterns. Install FIRST in the stack so every downstream middleware
35
+ * (approval gate, error hints, otel spans) observes canonical paths.
36
+ */
37
+ import { isAbsolute, relative } from "node:path";
38
+ import { resolveWorkspacePath } from "../shared/file-change.js";
39
+ /**
40
+ * The path-bearing argument of each deepagents built-in filesystem tool.
41
+ * `ls`/`glob`/`grep` take a base directory `path` (defaulting to "/" when
42
+ * omitted — absolute, so untouched here); the file tools take `file_path`.
43
+ * Confirmed against the installed deepagents' tool definitions.
44
+ */
45
+ const PATH_ARG_BY_TOOL = new Map([
46
+ ["ls", "path"],
47
+ ["glob", "path"],
48
+ ["grep", "path"],
49
+ ["read_file", "file_path"],
50
+ ["write_file", "file_path"],
51
+ ["edit_file", "file_path"],
52
+ ]);
53
+ /**
54
+ * Rewrite `raw` to its workspace-absolute form, or return undefined when the
55
+ * value must be left untouched (absolute already, `~`-carrying, or escaping
56
+ * the workspace root). Exported for direct unit testing of the mapping table.
57
+ */
58
+ export function normalizeWorkspacePathArg(raw, rootDir) {
59
+ if (raw.length === 0 || isAbsolute(raw))
60
+ return undefined;
61
+ // Upstream validation refuses `~` segments even in absolute paths, so a
62
+ // rewrite could not make such a call succeed — leave the raw shape (and
63
+ // therefore the honest refusal) intact.
64
+ if (raw.split("/").includes("~"))
65
+ return undefined;
66
+ const { absolutePath } = resolveWorkspacePath(raw, rootDir, false);
67
+ // No-new-reachability guard: `join` inside the resolver normalizes `..`
68
+ // segments away, so an escaping relative would otherwise pass upstream
69
+ // validation as a clean out-of-root absolute path. Today that shape is
70
+ // refused; keep it that way.
71
+ const rel = relative(rootDir, absolutePath);
72
+ if (rel.startsWith("..") || isAbsolute(rel))
73
+ return undefined;
74
+ return absolutePath;
75
+ }
76
+ /**
77
+ * Create middleware that normalizes workspace-relative paths on the built-in
78
+ * filesystem tools before permission enforcement sees them.
79
+ *
80
+ * Installed only on graphs that carry filesystem permission rules — derive
81
+ * the install condition from the same expression that supplies the rules
82
+ * (setup.ts / compileSubagents) so the rules and their normalization shim
83
+ * cannot drift apart.
84
+ */
85
+ export function createPathNormalizationMiddleware(config) {
86
+ const { rootDir } = config;
87
+ return {
88
+ name: "PathNormalizationMiddleware",
89
+ wrapToolCall(request, handler) {
90
+ const argKey = PATH_ARG_BY_TOOL.get(request.toolCall.name);
91
+ if (!argKey)
92
+ return handler(request);
93
+ const raw = request.toolCall.args[argKey];
94
+ if (typeof raw !== "string")
95
+ return handler(request);
96
+ const normalized = normalizeWorkspacePathArg(raw, rootDir);
97
+ if (normalized === undefined)
98
+ return handler(request);
99
+ return handler({
100
+ ...request,
101
+ toolCall: {
102
+ ...request.toolCall,
103
+ args: { ...request.toolCall.args, [argKey]: normalized },
104
+ },
105
+ });
106
+ },
107
+ };
108
+ }
109
+ //# sourceMappingURL=path-normalization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-normalization.js","sourceRoot":"","sources":["../../src/middleware/path-normalization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGhE;;;;;GAKG;AACH,MAAM,gBAAgB,GAAgC,IAAI,GAAG,CAAC;IAC5D,CAAC,IAAI,EAAE,MAAM,CAAC;IACd,CAAC,MAAM,EAAE,MAAM,CAAC;IAChB,CAAC,MAAM,EAAE,MAAM,CAAC;IAChB,CAAC,WAAW,EAAE,WAAW,CAAC;IAC1B,CAAC,YAAY,EAAE,WAAW,CAAC;IAC3B,CAAC,WAAW,EAAE,WAAW,CAAC;CAC3B,CAAC,CAAC;AAOH;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,GAAW,EACX,OAAe;IAEf,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1D,wEAAwE;IACxE,wEAAwE;IACxE,wCAAwC;IACxC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAEnD,MAAM,EAAE,YAAY,EAAE,GAAG,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAEnE,wEAAwE;IACxE,uEAAuE;IACvE,uEAAuE;IACvE,6BAA6B;IAC7B,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC5C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAE9D,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iCAAiC,CAC/C,MAA+B;IAE/B,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAE3B,OAAO;QACL,IAAI,EAAE,6BAA6B;QAEnC,YAAY,CAAC,OAAO,EAAE,OAAO;YAC3B,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;YAErC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;YAErD,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC3D,IAAI,UAAU,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;YAEtD,OAAO,OAAO,CAAC;gBACb,GAAG,OAAO;gBACV,QAAQ,EAAE;oBACR,GAAG,OAAO,CAAC,QAAQ;oBACnB,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE;iBACzD;aACF,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -83,6 +83,8 @@ export interface OtelSpansConfig {
83
83
  }
84
84
  import type { ApprovalGateConfig } from "./approval-gate.js";
85
85
  export type { ApprovalGateConfig };
86
+ import type { PathNormalizationConfig } from "./path-normalization.js";
87
+ export type { PathNormalizationConfig };
86
88
  /**
87
89
  * Top-level configuration for buildMiddlewareStack().
88
90
  * All sections are optional — the factory applies sensible defaults.
@@ -94,4 +96,10 @@ export interface MiddlewareStackConfig {
94
96
  readonly costCap?: CostCapConfig | null;
95
97
  readonly otelSpans?: Partial<OtelSpansConfig>;
96
98
  readonly approvalGate?: ApprovalGateConfig | null;
99
+ /**
100
+ * Workspace-relative path normalization (issue #429). Set iff the graph
101
+ * carries filesystem permission rules — derive from the same expression
102
+ * that supplies the rules so the two cannot drift apart.
103
+ */
104
+ readonly pathNormalization?: PathNormalizationConfig | null;
97
105
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Single assembly point for the worker's payload codec chain, shared by
3
+ * the standalone runner (runner.ts) and the runner manager
4
+ * (runner-manager.ts) so the two entrypoints cannot drift.
5
+ *
6
+ * Codec order is a correctness property, not a style choice. Temporal
7
+ * applies codecs in array order on encode and in reverse on decode, so
8
+ * with [encryption, claimcheck]:
9
+ *
10
+ * encode: encrypt → claim-check (payloads the claim-check codec
11
+ * relocates to object storage are already ciphertext)
12
+ * decode: claim-check → decrypt (restore the blob, then decrypt)
13
+ */
14
+ import type { PayloadCodec } from "@temporalio/common";
15
+ import type { Config } from "./config.js";
16
+ import type { BootstrapKeyMaterial } from "./encryption/config.js";
17
+ export declare function createPayloadCodecs(config: Config, bootstrapKeys?: BootstrapKeyMaterial): Promise<PayloadCodec[] | undefined>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Single assembly point for the worker's payload codec chain, shared by
3
+ * the standalone runner (runner.ts) and the runner manager
4
+ * (runner-manager.ts) so the two entrypoints cannot drift.
5
+ *
6
+ * Codec order is a correctness property, not a style choice. Temporal
7
+ * applies codecs in array order on encode and in reverse on decode, so
8
+ * with [encryption, claimcheck]:
9
+ *
10
+ * encode: encrypt → claim-check (payloads the claim-check codec
11
+ * relocates to object storage are already ciphertext)
12
+ * decode: claim-check → decrypt (restore the blob, then decrypt)
13
+ */
14
+ export async function createPayloadCodecs(config, bootstrapKeys) {
15
+ const codecs = [];
16
+ const { loadPayloadEncryptionConfig, EncryptionPayloadCodec } = await import("./encryption/index.js");
17
+ // Env-configured keys win outright; server-managed (bootstrap) keys apply
18
+ // only when the env is silent — see encryption/config.ts for the rationale.
19
+ const encryptionConfig = loadPayloadEncryptionConfig(bootstrapKeys);
20
+ if (encryptionConfig) {
21
+ codecs.push(new EncryptionPayloadCodec(encryptionConfig));
22
+ const source = process.env.STIGMER_PAYLOAD_ENCRYPTION_KEY ? "env" : "bootstrap";
23
+ console.log(`[runner] Payload encryption enabled (source=${source}, ` +
24
+ `key_id=${encryptionConfig.primary.keyId}` +
25
+ (encryptionConfig.secondary
26
+ ? `, secondary_key_id=${encryptionConfig.secondary.keyId})`
27
+ : ")"));
28
+ }
29
+ const { loadClaimcheckConfig, ClaimcheckPayloadCodec } = await import("./claimcheck/index.js");
30
+ const claimcheckConfig = loadClaimcheckConfig();
31
+ if (claimcheckConfig.enabled) {
32
+ const { loadArtifactStorageConfig, createArtifactStorage } = await import("./shared/artifact-storage.js");
33
+ const storageConfig = loadArtifactStorageConfig(config);
34
+ const storage = createArtifactStorage(storageConfig);
35
+ codecs.push(new ClaimcheckPayloadCodec(storage, claimcheckConfig));
36
+ console.log(`[runner] Claimcheck enabled (threshold=${claimcheckConfig.thresholdBytes}B, ` +
37
+ `compression=${claimcheckConfig.compressionEnabled}, ` +
38
+ `storage=${storageConfig.type})`);
39
+ }
40
+ return codecs.length > 0 ? codecs : undefined;
41
+ }
42
+ //# sourceMappingURL=payload-codecs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-codecs.js","sourceRoot":"","sources":["../src/payload-codecs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAc,EACd,aAAoC;IAEpC,MAAM,MAAM,GAAmB,EAAE,CAAC;IAElC,MAAM,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAC1E,uBAAuB,CACxB,CAAC;IACF,0EAA0E;IAC1E,4EAA4E;IAC5E,MAAM,gBAAgB,GAAG,2BAA2B,CAAC,aAAa,CAAC,CAAC;IACpE,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;QAChF,OAAO,CAAC,GAAG,CACT,+CAA+C,MAAM,IAAI;YACvD,UAAU,gBAAgB,CAAC,OAAO,CAAC,KAAK,EAAE;YAC1C,CAAC,gBAAgB,CAAC,SAAS;gBACzB,CAAC,CAAC,sBAAsB,gBAAgB,CAAC,SAAS,CAAC,KAAK,GAAG;gBAC3D,CAAC,CAAC,GAAG,CAAC,CACX,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CACnE,uBAAuB,CACxB,CAAC;IACF,MAAM,gBAAgB,GAAG,oBAAoB,EAAE,CAAC;IAChD,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC7B,MAAM,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CACvE,8BAA8B,CAC/B,CAAC;QACF,MAAM,aAAa,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,CAAC,IAAI,CAAC,IAAI,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CACT,0CAA0C,gBAAgB,CAAC,cAAc,KAAK;YAC5E,eAAe,gBAAgB,CAAC,kBAAkB,IAAI;YACtD,WAAW,aAAa,CAAC,IAAI,GAAG,CACnC,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC"}