@bastani/atomic 0.9.40 → 0.9.41-alpha.2

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 (323) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +1 -1
  3. package/dist/builtin/intercom/CHANGELOG.md +12 -0
  4. package/dist/builtin/intercom/README.md +1 -1
  5. package/dist/builtin/intercom/broker/broker.ts +24 -21
  6. package/dist/builtin/intercom/broker/client.ts +97 -6
  7. package/dist/builtin/intercom/broker/list-reply.ts +53 -0
  8. package/dist/builtin/intercom/index.bundle.mjs +278 -46
  9. package/dist/builtin/intercom/package.json +2 -2
  10. package/dist/builtin/intercom/recoverable-disconnect.ts +27 -1
  11. package/dist/builtin/intercom/types.ts +8 -1
  12. package/dist/builtin/mcp/package.json +1 -1
  13. package/dist/builtin/subagents/CHANGELOG.md +14 -0
  14. package/dist/builtin/subagents/README.md +14 -0
  15. package/dist/builtin/subagents/package.json +3 -3
  16. package/dist/builtin/subagents/src/extension/index.bundle.mjs +99 -19
  17. package/dist/builtin/web-access/package.json +2 -2
  18. package/dist/builtin/workflows/CHANGELOG.md +33 -0
  19. package/dist/builtin/workflows/README.md +2 -0
  20. package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
  21. package/dist/builtin/workflows/builtin/{chunk-qjqn389g.js → chunk-2jfst7e4.js} +72 -10
  22. package/dist/builtin/workflows/builtin/{chunk-4bwtzyjq.js → chunk-49kkbdpr.js} +1 -1
  23. package/dist/builtin/workflows/builtin/{chunk-qdd897wm.js → chunk-apagcs4r.js} +1 -1
  24. package/dist/builtin/workflows/builtin/{chunk-454hz1qt.js → chunk-dcxscfnb.js} +1 -1
  25. package/dist/builtin/workflows/builtin/{chunk-bjva9j5k.js → chunk-hx8v4p97.js} +1 -1
  26. package/dist/builtin/workflows/builtin/{chunk-85mx6wcf.js → chunk-k5q3t7je.js} +1 -1
  27. package/dist/builtin/workflows/builtin/{chunk-8kkv04hz.js → chunk-n2gkzkty.js} +1 -1
  28. package/dist/builtin/workflows/builtin/{chunk-y45tkftg.js → chunk-txbc93t6.js} +1 -1
  29. package/dist/builtin/workflows/builtin/{chunk-x0vvjyzg.js → chunk-w4xp1w1f.js} +1 -1
  30. package/dist/builtin/workflows/builtin/{chunk-5eh0brtd.js → chunk-z3pajrfs.js} +1 -1
  31. package/dist/builtin/workflows/builtin/classify-and-act.js +2 -2
  32. package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +2 -2
  33. package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
  34. package/dist/builtin/workflows/builtin/goal.js +2 -2
  35. package/dist/builtin/workflows/builtin/index.js +10 -10
  36. package/dist/builtin/workflows/builtin/loop-until-done.js +2 -2
  37. package/dist/builtin/workflows/builtin/open-claude-design.js +2 -2
  38. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  39. package/dist/builtin/workflows/builtin/tournament.js +2 -2
  40. package/dist/builtin/workflows/package.json +2 -2
  41. package/dist/builtin/workflows/src/authoring.d.ts +1 -1
  42. package/dist/builtin/workflows/src/durable/journal/internal.d.ts +16 -0
  43. package/dist/builtin/workflows/src/durable/journal/legacy-journal-tables.d.ts +9 -0
  44. package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +6 -0
  45. package/dist/builtin/workflows/src/extension/index.bundle.mjs +950 -116
  46. package/dist/builtin/workflows/src/index.js +806 -131
  47. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +17 -1
  48. package/dist/cli/credential-print.d.ts.map +1 -1
  49. package/dist/cli/credential-print.js +1 -1
  50. package/dist/cli/credential-print.js.map +1 -1
  51. package/dist/config.d.ts +1 -0
  52. package/dist/config.d.ts.map +1 -1
  53. package/dist/config.js +1 -0
  54. package/dist/config.js.map +1 -1
  55. package/dist/core/agent-session-extension-bindings.d.ts +2 -1
  56. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  57. package/dist/core/agent-session-extension-bindings.js +33 -18
  58. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  59. package/dist/core/agent-session-methods.d.ts +2 -1
  60. package/dist/core/agent-session-methods.d.ts.map +1 -1
  61. package/dist/core/agent-session-methods.js.map +1 -1
  62. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  63. package/dist/core/agent-session-prompt.js +114 -21
  64. package/dist/core/agent-session-prompt.js.map +1 -1
  65. package/dist/core/agent-session-runtime.d.ts +1 -1
  66. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  67. package/dist/core/agent-session-runtime.js +6 -0
  68. package/dist/core/agent-session-runtime.js.map +1 -1
  69. package/dist/core/agent-session-state.d.ts +19 -1
  70. package/dist/core/agent-session-state.d.ts.map +1 -1
  71. package/dist/core/agent-session-state.js +41 -6
  72. package/dist/core/agent-session-state.js.map +1 -1
  73. package/dist/core/auth-storage-backends.d.ts +3 -1
  74. package/dist/core/auth-storage-backends.d.ts.map +1 -1
  75. package/dist/core/auth-storage-backends.js +79 -12
  76. package/dist/core/auth-storage-backends.js.map +1 -1
  77. package/dist/core/client-identity.d.ts +8 -0
  78. package/dist/core/client-identity.d.ts.map +1 -0
  79. package/dist/core/client-identity.js +16 -0
  80. package/dist/core/client-identity.js.map +1 -0
  81. package/dist/core/compaction/planner-outcome.d.ts.map +1 -1
  82. package/dist/core/compaction/planner-outcome.js +2 -1
  83. package/dist/core/compaction/planner-outcome.js.map +1 -1
  84. package/dist/core/execution-model-router.d.ts +18 -0
  85. package/dist/core/execution-model-router.d.ts.map +1 -1
  86. package/dist/core/execution-model-router.js +14 -8
  87. package/dist/core/execution-model-router.js.map +1 -1
  88. package/dist/core/extension-oauth-refresh-rejection.d.ts +12 -0
  89. package/dist/core/extension-oauth-refresh-rejection.d.ts.map +1 -0
  90. package/dist/core/extension-oauth-refresh-rejection.js +70 -0
  91. package/dist/core/extension-oauth-refresh-rejection.js.map +1 -0
  92. package/dist/core/extension-startup-failure.d.ts +30 -0
  93. package/dist/core/extension-startup-failure.d.ts.map +1 -0
  94. package/dist/core/extension-startup-failure.js +62 -0
  95. package/dist/core/extension-startup-failure.js.map +1 -0
  96. package/dist/core/extensions/context-types.d.ts +2 -0
  97. package/dist/core/extensions/context-types.d.ts.map +1 -1
  98. package/dist/core/extensions/context-types.js.map +1 -1
  99. package/dist/core/extensions/provider-types.d.ts +2 -0
  100. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  101. package/dist/core/extensions/provider-types.js.map +1 -1
  102. package/dist/core/extensions/runner-context.d.ts +1 -0
  103. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  104. package/dist/core/extensions/runner-context.js +8 -0
  105. package/dist/core/extensions/runner-context.js.map +1 -1
  106. package/dist/core/extensions/runner.d.ts +1 -0
  107. package/dist/core/extensions/runner.d.ts.map +1 -1
  108. package/dist/core/extensions/runner.js +3 -0
  109. package/dist/core/extensions/runner.js.map +1 -1
  110. package/dist/core/extensions/runtime-types.d.ts +1 -0
  111. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  112. package/dist/core/extensions/runtime-types.js.map +1 -1
  113. package/dist/core/extensions/workflow-run-control-hub.d.ts +1 -0
  114. package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -1
  115. package/dist/core/extensions/workflow-run-control-hub.js +3 -0
  116. package/dist/core/extensions/workflow-run-control-hub.js.map +1 -1
  117. package/dist/core/extensions/workflow-run-control.d.ts +8 -0
  118. package/dist/core/extensions/workflow-run-control.d.ts.map +1 -1
  119. package/dist/core/extensions/workflow-run-control.js.map +1 -1
  120. package/dist/core/model-config.d.ts +28 -0
  121. package/dist/core/model-config.d.ts.map +1 -1
  122. package/dist/core/model-fallback-failures.d.ts.map +1 -1
  123. package/dist/core/model-fallback-failures.js +12 -0
  124. package/dist/core/model-fallback-failures.js.map +1 -1
  125. package/dist/core/model-resolver-defaults.js +1 -1
  126. package/dist/core/model-resolver-defaults.js.map +1 -1
  127. package/dist/core/model-runtime-streaming.d.ts.map +1 -1
  128. package/dist/core/model-runtime-streaming.js +9 -3
  129. package/dist/core/model-runtime-streaming.js.map +1 -1
  130. package/dist/core/model-runtime.d.ts +5 -0
  131. package/dist/core/model-runtime.d.ts.map +1 -1
  132. package/dist/core/model-runtime.js +6 -0
  133. package/dist/core/model-runtime.js.map +1 -1
  134. package/dist/core/provider-composer-internal.d.ts +8 -6
  135. package/dist/core/provider-composer-internal.d.ts.map +1 -1
  136. package/dist/core/provider-composer-internal.js +21 -8
  137. package/dist/core/provider-composer-internal.js.map +1 -1
  138. package/dist/core/sdk.d.ts.map +1 -1
  139. package/dist/core/sdk.js +12 -4
  140. package/dist/core/sdk.js.map +1 -1
  141. package/dist/core/storage/session/sql-session-store.d.ts +35 -0
  142. package/dist/core/storage/session/sql-session-store.d.ts.map +1 -1
  143. package/dist/core/storage/session/sql-session-store.js +158 -42
  144. package/dist/core/storage/session/sql-session-store.js.map +1 -1
  145. package/dist/core/structured-output/deadline.d.ts +40 -0
  146. package/dist/core/structured-output/deadline.d.ts.map +1 -0
  147. package/dist/core/structured-output/deadline.js +110 -0
  148. package/dist/core/structured-output/deadline.js.map +1 -0
  149. package/dist/core/structured-output/index.d.ts.map +1 -1
  150. package/dist/core/structured-output/index.js +103 -47
  151. package/dist/core/structured-output/index.js.map +1 -1
  152. package/dist/core/structured-output/rejection-detail.d.ts +9 -0
  153. package/dist/core/structured-output/rejection-detail.d.ts.map +1 -0
  154. package/dist/core/structured-output/rejection-detail.js +129 -0
  155. package/dist/core/structured-output/rejection-detail.js.map +1 -0
  156. package/dist/core/structured-output/types.d.ts +8 -1
  157. package/dist/core/structured-output/types.d.ts.map +1 -1
  158. package/dist/core/structured-output/types.js.map +1 -1
  159. package/dist/core/tasks/completion.d.ts +7 -1
  160. package/dist/core/tasks/completion.d.ts.map +1 -1
  161. package/dist/core/tasks/completion.js +28 -6
  162. package/dist/core/tasks/completion.js.map +1 -1
  163. package/dist/core/tasks/contracts.d.ts +6 -1
  164. package/dist/core/tasks/contracts.d.ts.map +1 -1
  165. package/dist/core/tasks/contracts.js.map +1 -1
  166. package/dist/core/tasks/pause.d.ts +2 -1
  167. package/dist/core/tasks/pause.d.ts.map +1 -1
  168. package/dist/core/tasks/pause.js +3 -2
  169. package/dist/core/tasks/pause.js.map +1 -1
  170. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  171. package/dist/core/tools/bash-pty-native.js +10 -5
  172. package/dist/core/tools/bash-pty-native.js.map +1 -1
  173. package/dist/core/tools/bash.d.ts.map +1 -1
  174. package/dist/core/tools/bash.js +16 -32
  175. package/dist/core/tools/bash.js.map +1 -1
  176. package/dist/core/tools/grep.js +1 -1
  177. package/dist/core/tools/grep.js.map +1 -1
  178. package/dist/core/tools/kill.d.ts.map +1 -1
  179. package/dist/core/tools/kill.js +17 -3
  180. package/dist/core/tools/kill.js.map +1 -1
  181. package/dist/core/tools/shell-task-render.d.ts +55 -0
  182. package/dist/core/tools/shell-task-render.d.ts.map +1 -0
  183. package/dist/core/tools/shell-task-render.js +123 -0
  184. package/dist/core/tools/shell-task-render.js.map +1 -0
  185. package/dist/core/tools/shell-task-status.d.ts +52 -0
  186. package/dist/core/tools/shell-task-status.d.ts.map +1 -0
  187. package/dist/core/tools/shell-task-status.js +184 -0
  188. package/dist/core/tools/shell-task-status.js.map +1 -0
  189. package/dist/core/tools/structured-output.d.ts +5 -0
  190. package/dist/core/tools/structured-output.d.ts.map +1 -1
  191. package/dist/core/tools/structured-output.js +3 -0
  192. package/dist/core/tools/structured-output.js.map +1 -1
  193. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  194. package/dist/extensions/codemode/execute.js +134 -57
  195. package/dist/extensions/codemode/execute.js.map +1 -1
  196. package/dist/extensions/mcp/config.d.ts.map +1 -1
  197. package/dist/extensions/mcp/config.js +3 -2
  198. package/dist/extensions/mcp/config.js.map +1 -1
  199. package/dist/index-extensions.d.ts +1 -0
  200. package/dist/index-extensions.d.ts.map +1 -1
  201. package/dist/index-extensions.js +3 -0
  202. package/dist/index-extensions.js.map +1 -1
  203. package/dist/index.d.ts +3 -1
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +3 -1
  206. package/dist/index.js.map +1 -1
  207. package/dist/main.d.ts.map +1 -1
  208. package/dist/main.js +19 -6
  209. package/dist/main.js.map +1 -1
  210. package/dist/modes/interactive/components/task-row.d.ts.map +1 -1
  211. package/dist/modes/interactive/components/task-row.js +11 -1
  212. package/dist/modes/interactive/components/task-row.js.map +1 -1
  213. package/dist/modes/interactive/interactive-auth-routing.js +12 -10
  214. package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
  215. package/dist/modes/interactive/interactive-extension-custom-ui.js +20 -30
  216. package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
  217. package/dist/modes/interactive/interactive-extension-dialogs.js +23 -96
  218. package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
  219. package/dist/modes/interactive/interactive-extension-runtime.js +7 -8
  220. package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
  221. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  222. package/dist/modes/interactive/interactive-input-handling.js +27 -4
  223. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  224. package/dist/modes/interactive/interactive-mode-base.d.ts +20 -10
  225. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  226. package/dist/modes/interactive/interactive-mode-base.js +40 -5
  227. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  228. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  229. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  230. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  231. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  232. package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -4
  233. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  234. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  235. package/dist/modes/interactive/interactive-mode-types.d.ts +4 -1
  236. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  237. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  238. package/dist/modes/interactive/interactive-prompt-restore.d.ts +3 -0
  239. package/dist/modes/interactive/interactive-prompt-restore.d.ts.map +1 -1
  240. package/dist/modes/interactive/interactive-prompt-restore.js +9 -1
  241. package/dist/modes/interactive/interactive-prompt-restore.js.map +1 -1
  242. package/dist/modes/interactive/interactive-prompt-turn.js +30 -2
  243. package/dist/modes/interactive/interactive-prompt-turn.js.map +1 -1
  244. package/dist/modes/interactive/interactive-queueing.js +43 -8
  245. package/dist/modes/interactive/interactive-queueing.js.map +1 -1
  246. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  247. package/dist/modes/interactive/interactive-startup.js +12 -3
  248. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  249. package/dist/modes/interactive/theme/color-utils.d.ts +6 -1
  250. package/dist/modes/interactive/theme/color-utils.d.ts.map +1 -1
  251. package/dist/modes/interactive/theme/color-utils.js +39 -17
  252. package/dist/modes/interactive/theme/color-utils.js.map +1 -1
  253. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  254. package/dist/modes/interactive/theme/theme-class.js +2 -2
  255. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  256. package/dist/modes/interactive/theme/theme-tokens.d.ts +6 -0
  257. package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -1
  258. package/dist/modes/interactive/theme/theme-tokens.js +7 -3
  259. package/dist/modes/interactive/theme/theme-tokens.js.map +1 -1
  260. package/dist/modes/interactive-engine/isolated-auth.d.ts +3 -0
  261. package/dist/modes/interactive-engine/isolated-auth.d.ts.map +1 -1
  262. package/dist/modes/interactive-engine/isolated-auth.js +13 -1
  263. package/dist/modes/interactive-engine/isolated-auth.js.map +1 -1
  264. package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
  265. package/dist/modes/interactive-engine/isolated-runtime.js +11 -2
  266. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  267. package/dist/modes/interactive-engine/remote-model-catalog.d.ts +8 -0
  268. package/dist/modes/interactive-engine/remote-model-catalog.d.ts.map +1 -1
  269. package/dist/modes/interactive-engine/remote-model-catalog.js +54 -0
  270. package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
  271. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  272. package/dist/modes/rpc/rpc-command-handler.js +4 -13
  273. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  274. package/dist/modes/rpc/rpc-model-catalog.d.ts +9 -0
  275. package/dist/modes/rpc/rpc-model-catalog.d.ts.map +1 -0
  276. package/dist/modes/rpc/rpc-model-catalog.js +19 -0
  277. package/dist/modes/rpc/rpc-model-catalog.js.map +1 -0
  278. package/dist/modes/rpc/rpc-provider-auth.d.ts.map +1 -1
  279. package/dist/modes/rpc/rpc-provider-auth.js +2 -6
  280. package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
  281. package/dist/modes/rpc/rpc-types.d.ts +6 -0
  282. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  283. package/dist/modes/rpc/rpc-types.js.map +1 -1
  284. package/dist/utils/changelog.d.ts +6 -0
  285. package/dist/utils/changelog.d.ts.map +1 -1
  286. package/dist/utils/changelog.js +11 -0
  287. package/dist/utils/changelog.js.map +1 -1
  288. package/dist/utils/clipboard.d.ts.map +1 -1
  289. package/dist/utils/clipboard.js +4 -0
  290. package/dist/utils/clipboard.js.map +1 -1
  291. package/dist/utils/tools-manager.d.ts.map +1 -1
  292. package/dist/utils/tools-manager.js +3 -2
  293. package/dist/utils/tools-manager.js.map +1 -1
  294. package/docs/background-tasks.md +5 -3
  295. package/docs/codemode.md +2 -2
  296. package/docs/custom-provider/oauth.md +42 -1
  297. package/docs/custom-provider/registration.md +2 -0
  298. package/docs/environment-variables.md +1 -0
  299. package/docs/extensions/api-reference.md +3 -4
  300. package/docs/extensions/authoring.md +1 -1
  301. package/docs/extensions/events.md +1 -1
  302. package/docs/models-configuration.md +9 -0
  303. package/docs/models.md +3 -1
  304. package/docs/providers.md +4 -4
  305. package/docs/rpc/protocol.md +4 -2
  306. package/docs/sdk/reference.md +2 -0
  307. package/docs/sdk/structured-decisions.md +7 -5
  308. package/docs/sdk.md +5 -2
  309. package/docs/settings.md +4 -2
  310. package/docs/subagents/reference.md +1 -1
  311. package/docs/subagents.md +15 -1
  312. package/docs/themes/reference.md +3 -1
  313. package/docs/usage.md +3 -1
  314. package/docs/workflows/api-reference.md +28 -0
  315. package/docs/workflows/authoring.md +1 -1
  316. package/docs/workflows/operations.md +2 -2
  317. package/npm-shrinkwrap.json +67 -54
  318. package/package.json +6 -6
  319. package/schemas/models.schema.json +21 -0
  320. package/dist/core/provider-attribution.d.ts +0 -4
  321. package/dist/core/provider-attribution.d.ts.map +0 -1
  322. package/dist/core/provider-attribution.js +0 -87
  323. package/dist/core/provider-attribution.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"kill.js","sourceRoot":"","sources":["../../../src/core/tools/kill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAC;AAGtE,OAAO,EAAE,eAAe,EAA+B,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,0EAA0E,EAAE,CAAC;CAC5G,CAAC,CAAC;AAOH,MAAM,UAAU,wBAAwB,CAAC,OAAyB;IACjE,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,WAAW,EACV,+PAA+P;QAChQ,UAAU,EAAE,UAAU;QACtB,GAAG,gCAAgC,EAAE;QACrC,aAAa,EAAE,gDAAgD;QAC/D,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;YACtC,MAAM,OAAO,GAAG,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACtE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;YACtC,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACpF,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC;gBACrF,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS;oBAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBAClF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACzD,IAAI,CAAC,MAAM,CAAC,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBACjF,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;gBAC7B,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC1D,OAAO,EAAE,OAAO;oBAChB,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC/D,CAAC;YACH,CAAC;oBAAS,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACzB,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAyB;IACvD,OAAO,kBAAkB,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["import { Type } from \"typebox\";\nimport { experimentalToolSamplingProperty } from \"../experimental.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { CancelReceipt } from \"../tasks/contracts.js\";\nimport { lookupOwnedTask, type SupervisedCommandOwner } from \"./bash-pty-native.js\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst killSchema = Type.Object({\n\tid: Type.String({ description: \"Task ID returned by a background or auto-yielded bash or powershell call\" }),\n});\n\nexport interface KillToolOptions {\n\t/** Resolve the live trusted owner at execution time, including after session switches. */\n\ttaskOwner?: () => SupervisedCommandOwner | undefined;\n}\n\nexport function createKillToolDefinition(options?: KillToolOptions): ToolDefinition<typeof killSchema, CancelReceipt> {\n\treturn {\n\t\tname: \"kill\",\n\t\tlabel: \"Kill\",\n\t\tdescription:\n\t\t\t\"Stop an owned background bash or PowerShell task by its task ID, not a PID. Does not stop subagents or other owners' tasks. Returns the cancellation decision and current execution/cleanup state; a cancellation request alone does not confirm termination.\",\n\t\tparameters: killSchema,\n\t\t...experimentalToolSamplingProperty(),\n\t\tpromptSnippet: \"Stop an owned background shell task by task ID\",\n\t\texecute: async (_toolCallId, { id }) => {\n\t\t\tconst binding = options?.taskOwner?.();\n\t\t\tif (!binding) throw new Error(\"kill requires a supported task owner\");\n\t\t\tconst { supervisor, owner } = binding;\n\t\t\tconst task = lookupOwnedTask(binding, id);\n\t\t\tconst watched = supervisor.watchOwnerTasks(owner);\n\t\t\tif (!watched.ok) throw new Error(`${watched.error.code}: ${watched.error.message}`);\n\t\t\ttry {\n\t\t\t\tconst record = watched.value.snapshot.tasks.find((entry) => entry.ref.taskId === id);\n\t\t\t\tif (record?.kind !== \"command\") throw new Error(\"kill only supports shell tasks\");\n\t\t\t\tconst result = await supervisor.cancelTask(task, \"user\");\n\t\t\t\tif (!result.ok) throw new Error(`${result.error.code}: ${result.error.message}`);\n\t\t\t\tconst receipt = result.value;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: JSON.stringify(receipt) }],\n\t\t\t\t\tdetails: receipt,\n\t\t\t\t\t...(receipt.cleanup.kind === \"failed\" ? { isError: true } : {}),\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\twatched.value.dispose();\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport function createKillTool(options?: KillToolOptions) {\n\treturn wrapToolDefinition(createKillToolDefinition(options));\n}\n"]}
1
+ {"version":3,"file":"kill.js","sourceRoot":"","sources":["../../../src/core/tools/kill.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, Text } from \"@earendil-works/pi-tui\";\nimport { Type } from \"typebox\";\nimport { experimentalToolSamplingProperty } from \"../experimental.ts\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { CancelReceipt } from \"../tasks/contracts.js\";\nimport { lookupOwnedTask, type SupervisedCommandOwner } from \"./bash-pty-native.js\";\nimport { formatKillCall, rebuildKillResult } from \"./shell-task-render.ts\";\nimport { cancelReceiptSentence, TaskToolError } from \"./shell-task-status.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst killSchema = Type.Object({\n\tid: Type.String({ description: \"Task ID returned by a background or auto-yielded bash or powershell call\" }),\n});\n\nexport interface KillToolOptions {\n\t/** Resolve the live trusted owner at execution time, including after session switches. */\n\ttaskOwner?: () => SupervisedCommandOwner | undefined;\n}\n\nexport function createKillToolDefinition(options?: KillToolOptions): ToolDefinition<typeof killSchema, CancelReceipt> {\n\treturn {\n\t\tname: \"kill\",\n\t\tlabel: \"Kill\",\n\t\tdescription:\n\t\t\t\"Stop an owned background bash or PowerShell task by its task ID, not a PID. Does not stop subagents or other owners' tasks. Returns the cancellation decision and current execution/cleanup state; a cancellation request alone does not confirm termination.\",\n\t\tparameters: killSchema,\n\t\t...experimentalToolSamplingProperty(),\n\t\tpromptSnippet: \"Stop an owned background shell task by task ID\",\n\t\texecute: async (_toolCallId, { id }) => {\n\t\t\tconst binding = options?.taskOwner?.();\n\t\t\tif (!binding) throw new Error(\"kill requires a supported task owner\");\n\t\t\tconst { supervisor, owner } = binding;\n\t\t\tconst task = lookupOwnedTask(binding, id);\n\t\t\tconst watched = supervisor.watchOwnerTasks(owner);\n\t\t\tif (!watched.ok) throw new TaskToolError(watched.error, id);\n\t\t\ttry {\n\t\t\t\tconst record = watched.value.snapshot.tasks.find((entry) => entry.ref.taskId === id);\n\t\t\t\tif (record?.kind !== \"command\") throw new Error(\"kill only supports shell tasks\");\n\t\t\t\tconst result = await supervisor.cancelTask(task, \"user\");\n\t\t\t\tif (!result.ok) throw new TaskToolError(result.error, id);\n\t\t\t\tconst receipt = result.value;\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: cancelReceiptSentence(receipt) }],\n\t\t\t\t\tdetails: receipt,\n\t\t\t\t\t...(receipt.cleanup.kind === \"failed\" ? { isError: true } : {}),\n\t\t\t\t};\n\t\t\t} finally {\n\t\t\t\twatched.value.dispose();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatKillCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, _options, _theme, context) {\n\t\t\tconst component = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\trebuildKillResult(component, result, { isError: context.isError, taskId: context.args.id });\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createKillTool(options?: KillToolOptions) {\n\treturn wrapToolDefinition(createKillToolDefinition(options));\n}\n"]}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Transcript presentation for shell task results: a `wait` observation and a `kill` receipt each become one status
3
+ * line, with the task's output (when it has any) below it. Raw observation envelopes and internal ids never appear.
4
+ *
5
+ * Roles follow DESIGN.md: success, error, warning and dim carry the state, `·` separates facts, and only the glyphs
6
+ * `✓ ✗ ● ○` are used. The status reads the same without color; with `NO_COLOR` set it drops foreground color and
7
+ * keeps the weight.
8
+ */
9
+ import { type Container } from "@earendil-works/pi-tui";
10
+ import type { ToolRenderResultOptions } from "../extensions/types.ts";
11
+ import type { CancelReceipt, WaitOutcome } from "../tasks/contracts.js";
12
+ import { type TruncationResult } from "./truncate.ts";
13
+ /** Output lines shown before a shell result collapses behind the expand hint. */
14
+ export declare const SHELL_OUTPUT_PREVIEW_LINES = 5;
15
+ type ResultContent = Array<{
16
+ type: string;
17
+ text?: string;
18
+ data?: string;
19
+ mimeType?: string;
20
+ }>;
21
+ /** The output block of a shell result: everything when expanded, otherwise the last few lines and an expand hint. */
22
+ export declare function addShellOutputPreview(component: Container, output: string, expanded: boolean): void;
23
+ export declare function formatTruncationNotice(truncation: TruncationResult): string;
24
+ export interface ShellWaitResultView {
25
+ content: ResultContent;
26
+ details?: {
27
+ observation?: WaitOutcome;
28
+ truncation?: TruncationResult;
29
+ fullOutputPath?: string;
30
+ };
31
+ }
32
+ /**
33
+ * Rebuild the row of a `wait` result: status line, output, a dim note when the output was cut short, then the timer.
34
+ * An error that is not a task failure, or a result without an observation, is left to the generic shell renderer;
35
+ * the return value says whether this renderer handled the result.
36
+ */
37
+ export declare function rebuildShellWaitResult(component: Container, result: ShellWaitResultView, options: Pick<ToolRenderResultOptions, "expanded">, view: {
38
+ showImages: boolean;
39
+ isError: boolean;
40
+ taskId: string | undefined;
41
+ timerText: string | undefined;
42
+ }): boolean;
43
+ export declare function formatKillCall(args: {
44
+ id?: unknown;
45
+ } | undefined): string;
46
+ /** Rebuild the row of a `kill` result from its receipt, or from the failure text when the call was rejected. */
47
+ export declare function rebuildKillResult(component: Container, result: {
48
+ content: ResultContent;
49
+ details?: CancelReceipt;
50
+ }, view: {
51
+ isError: boolean;
52
+ taskId: string | undefined;
53
+ }): void;
54
+ export {};
55
+ //# sourceMappingURL=shell-task-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-task-render.d.ts","sourceRoot":"","sources":["../../../src/core/tools/shell-task-render.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,wBAAwB,CAAC;AAItE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAWxE,OAAO,EAAiC,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAErF,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,KAAK,aAAa,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAiB9F,qHAAqH;AACrH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAmBnG;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,gBAAgB,GAAG,MAAM,CAI3E;AAMD,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE;QACT,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,UAAU,CAAC,EAAE,gBAAgB,CAAC;QAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACrC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,EAClD,IAAI,EAAE;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACxG,OAAO,CA4BT;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,EAAE,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAAG,MAAM,CAIzE;AAED,gHAAgH;AAChH,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAA;CAAE,EAC3D,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACpD,IAAI,CAoBN"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Transcript presentation for shell task results: a `wait` observation and a `kill` receipt each become one status
3
+ * line, with the task's output (when it has any) below it. Raw observation envelopes and internal ids never appear.
4
+ *
5
+ * Roles follow DESIGN.md: success, error, warning and dim carry the state, `·` separates facts, and only the glyphs
6
+ * `✓ ✗ ● ○` are used. The status reads the same without color; with `NO_COLOR` set it drops foreground color and
7
+ * keeps the weight.
8
+ */
9
+ import { Spacer, Text } from "@earendil-works/pi-tui";
10
+ import { parenthesizedKeyHint } from "../../modes/interactive/components/keybinding-hints.js";
11
+ import { VisualLinePreview } from "../../modes/interactive/components/visual-truncate.js";
12
+ import { theme } from "../../modes/interactive/theme/theme.js";
13
+ import { getTextOutput, invalidArgText, str } from "./render-utils.js";
14
+ import { cancelReceiptStatus, cleanupFailureSummary, EMPTY_OUTPUT_TEXT, presentTaskError, waitResultTail, waitStatus, } from "./shell-task-status.js";
15
+ import { DEFAULT_MAX_BYTES, formatSize } from "./truncate.js";
16
+ /** Output lines shown before a shell result collapses behind the expand hint. */
17
+ export const SHELL_OUTPUT_PREVIEW_LINES = 5;
18
+ const noColor = () => process.env.NO_COLOR !== undefined;
19
+ function statusLine(status) {
20
+ const head = `${status.glyph} ${status.label}`;
21
+ if (noColor())
22
+ return theme.bold(head) + (status.detail ? ` · ${status.detail}` : "");
23
+ const detail = status.detail ? theme.fg("dim", " · ") + theme.fg("muted", status.detail) : "";
24
+ return theme.fg(status.tone, head) + detail;
25
+ }
26
+ function addErrorLines(component, headline, hint) {
27
+ const heading = `✗ ${headline}`;
28
+ component.addChild(new Text(noColor() ? theme.bold(heading) : theme.fg("error", heading), 0, 0));
29
+ if (hint)
30
+ component.addChild(new Text(noColor() ? hint : theme.fg("dim", hint), 0, 0));
31
+ }
32
+ /** The output block of a shell result: everything when expanded, otherwise the last few lines and an expand hint. */
33
+ export function addShellOutputPreview(component, output, expanded) {
34
+ const styledOutput = output
35
+ .split("\n")
36
+ .map((line) => theme.fg("toolOutput", line))
37
+ .join("\n");
38
+ if (expanded) {
39
+ component.addChild(new Text(`\n${styledOutput}`, 0, 0));
40
+ return;
41
+ }
42
+ component.addChild(new Spacer(1));
43
+ component.addChild(new VisualLinePreview({
44
+ text: styledOutput,
45
+ maxVisualLines: SHELL_OUTPUT_PREVIEW_LINES,
46
+ keep: "end",
47
+ formatHint: (hidden) => theme.fg("muted", "... ") + parenthesizedKeyHint("app.tools.expand", "Expand", `${hidden} earlier lines`),
48
+ }));
49
+ }
50
+ export function formatTruncationNotice(truncation) {
51
+ return truncation.truncatedBy === "lines"
52
+ ? `Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`
53
+ : `Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`;
54
+ }
55
+ function addTimer(component, timerText) {
56
+ if (timerText)
57
+ component.addChild(new Text(`\n${theme.fg("muted", timerText)}`, 0, 0));
58
+ }
59
+ /**
60
+ * Rebuild the row of a `wait` result: status line, output, a dim note when the output was cut short, then the timer.
61
+ * An error that is not a task failure, or a result without an observation, is left to the generic shell renderer;
62
+ * the return value says whether this renderer handled the result.
63
+ */
64
+ export function rebuildShellWaitResult(component, result, options, view) {
65
+ const text = getTextOutput(result, view.showImages).trim();
66
+ if (view.isError) {
67
+ const error = presentTaskError(text, view.taskId);
68
+ if (!error)
69
+ return false;
70
+ component.clear();
71
+ addErrorLines(component, error.headline, error.hint);
72
+ addTimer(component, view.timerText);
73
+ return true;
74
+ }
75
+ const observation = result.details?.observation;
76
+ if (!observation)
77
+ return false;
78
+ const truncation = result.details?.truncation;
79
+ const fullOutputPath = result.details?.fullOutputPath;
80
+ const tail = waitResultTail({ observation, truncated: truncation?.truncated === true, fullOutputPath });
81
+ const output = (text.endsWith(tail) ? text.slice(0, -tail.length) : text).trim();
82
+ const hasOutput = output !== "" && output !== EMPTY_OUTPUT_TEXT;
83
+ component.clear();
84
+ component.addChild(new Text(statusLine(waitStatus(observation, hasOutput)), 0, 0));
85
+ if (hasOutput)
86
+ addShellOutputPreview(component, output, options.expanded);
87
+ else
88
+ component.addChild(new Text(theme.fg("dim", EMPTY_OUTPUT_TEXT), 0, 0));
89
+ const notes = [
90
+ truncation?.truncated ? formatTruncationNotice(truncation) : undefined,
91
+ fullOutputPath ? `Full output: ${fullOutputPath}` : undefined,
92
+ ].filter((note) => note !== undefined);
93
+ if (notes.length > 0)
94
+ component.addChild(new Text(theme.fg("dim", notes.join(" · ")), 0, 0));
95
+ addTimer(component, view.timerText);
96
+ return true;
97
+ }
98
+ export function formatKillCall(args) {
99
+ const id = str(args?.id);
100
+ const target = id === null ? invalidArgText(theme) : id || theme.fg("toolOutput", "...");
101
+ return theme.fg("toolTitle", theme.bold(`kill ${target}`));
102
+ }
103
+ /** Rebuild the row of a `kill` result from its receipt, or from the failure text when the call was rejected. */
104
+ export function rebuildKillResult(component, result, view) {
105
+ component.clear();
106
+ const text = getTextOutput(result, false).trim();
107
+ const error = view.isError ? presentTaskError(text, view.taskId) : undefined;
108
+ if (error) {
109
+ addErrorLines(component, error.headline, error.hint);
110
+ return;
111
+ }
112
+ const receipt = result.details;
113
+ // A rejected call carries empty details, so only a real receipt has an execution to describe.
114
+ if (!receipt?.execution) {
115
+ component.addChild(new Text(theme.fg("toolOutput", text), 0, 0));
116
+ return;
117
+ }
118
+ component.addChild(new Text(statusLine(cancelReceiptStatus(receipt)), 0, 0));
119
+ const failure = cleanupFailureSummary(receipt.cleanup);
120
+ if (failure)
121
+ component.addChild(new Text(statusLine({ glyph: "✗", tone: "error", label: "cleanup failed", detail: failure }), 0, 0));
122
+ }
123
+ //# sourceMappingURL=shell-task-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-task-render.js","sourceRoot":"","sources":["../../../src/core/tools/shell-task-render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Transcript presentation for shell task results: a `wait` observation and a `kill` receipt each become one status\n * line, with the task's output (when it has any) below it. Raw observation envelopes and internal ids never appear.\n *\n * Roles follow DESIGN.md: success, error, warning and dim carry the state, `·` separates facts, and only the glyphs\n * `✓ ✗ ● ○` are used. The status reads the same without color; with `NO_COLOR` set it drops foreground color and\n * keeps the weight.\n */\nimport { type Container, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport { parenthesizedKeyHint } from \"../../modes/interactive/components/keybinding-hints.js\";\nimport { VisualLinePreview } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.js\";\nimport type { ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport type { CancelReceipt, WaitOutcome } from \"../tasks/contracts.js\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport {\n\tcancelReceiptStatus,\n\tcleanupFailureSummary,\n\tEMPTY_OUTPUT_TEXT,\n\tpresentTaskError,\n\ttype TaskStatus,\n\twaitResultTail,\n\twaitStatus,\n} from \"./shell-task-status.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\n/** Output lines shown before a shell result collapses behind the expand hint. */\nexport const SHELL_OUTPUT_PREVIEW_LINES = 5;\n\ntype ResultContent = Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\nconst noColor = (): boolean => process.env.NO_COLOR !== undefined;\n\nfunction statusLine(status: TaskStatus): string {\n\tconst head = `${status.glyph} ${status.label}`;\n\tif (noColor()) return theme.bold(head) + (status.detail ? ` · ${status.detail}` : \"\");\n\tconst detail = status.detail ? theme.fg(\"dim\", \" · \") + theme.fg(\"muted\", status.detail) : \"\";\n\treturn theme.fg(status.tone, head) + detail;\n}\n\nfunction addErrorLines(component: Container, headline: string, hint: string | undefined): void {\n\tconst heading = `✗ ${headline}`;\n\tcomponent.addChild(new Text(noColor() ? theme.bold(heading) : theme.fg(\"error\", heading), 0, 0));\n\tif (hint) component.addChild(new Text(noColor() ? hint : theme.fg(\"dim\", hint), 0, 0));\n}\n\n/** The output block of a shell result: everything when expanded, otherwise the last few lines and an expand hint. */\nexport function addShellOutputPreview(component: Container, output: string, expanded: boolean): void {\n\tconst styledOutput = output\n\t\t.split(\"\\n\")\n\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t.join(\"\\n\");\n\tif (expanded) {\n\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\treturn;\n\t}\n\tcomponent.addChild(new Spacer(1));\n\tcomponent.addChild(\n\t\tnew VisualLinePreview({\n\t\t\ttext: styledOutput,\n\t\t\tmaxVisualLines: SHELL_OUTPUT_PREVIEW_LINES,\n\t\t\tkeep: \"end\",\n\t\t\tformatHint: (hidden) =>\n\t\t\t\ttheme.fg(\"muted\", \"... \") + parenthesizedKeyHint(\"app.tools.expand\", \"Expand\", `${hidden} earlier lines`),\n\t\t}),\n\t);\n}\n\nexport function formatTruncationNotice(truncation: TruncationResult): string {\n\treturn truncation.truncatedBy === \"lines\"\n\t\t? `Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`\n\t\t: `Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`;\n}\n\nfunction addTimer(component: Container, timerText: string | undefined): void {\n\tif (timerText) component.addChild(new Text(`\\n${theme.fg(\"muted\", timerText)}`, 0, 0));\n}\n\nexport interface ShellWaitResultView {\n\tcontent: ResultContent;\n\tdetails?: {\n\t\tobservation?: WaitOutcome;\n\t\ttruncation?: TruncationResult;\n\t\tfullOutputPath?: string;\n\t};\n}\n\n/**\n * Rebuild the row of a `wait` result: status line, output, a dim note when the output was cut short, then the timer.\n * An error that is not a task failure, or a result without an observation, is left to the generic shell renderer;\n * the return value says whether this renderer handled the result.\n */\nexport function rebuildShellWaitResult(\n\tcomponent: Container,\n\tresult: ShellWaitResultView,\n\toptions: Pick<ToolRenderResultOptions, \"expanded\">,\n\tview: { showImages: boolean; isError: boolean; taskId: string | undefined; timerText: string | undefined },\n): boolean {\n\tconst text = getTextOutput(result, view.showImages).trim();\n\tif (view.isError) {\n\t\tconst error = presentTaskError(text, view.taskId);\n\t\tif (!error) return false;\n\t\tcomponent.clear();\n\t\taddErrorLines(component, error.headline, error.hint);\n\t\taddTimer(component, view.timerText);\n\t\treturn true;\n\t}\n\tconst observation = result.details?.observation;\n\tif (!observation) return false;\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tconst tail = waitResultTail({ observation, truncated: truncation?.truncated === true, fullOutputPath });\n\tconst output = (text.endsWith(tail) ? text.slice(0, -tail.length) : text).trim();\n\tconst hasOutput = output !== \"\" && output !== EMPTY_OUTPUT_TEXT;\n\tcomponent.clear();\n\tcomponent.addChild(new Text(statusLine(waitStatus(observation, hasOutput)), 0, 0));\n\tif (hasOutput) addShellOutputPreview(component, output, options.expanded);\n\telse component.addChild(new Text(theme.fg(\"dim\", EMPTY_OUTPUT_TEXT), 0, 0));\n\tconst notes = [\n\t\ttruncation?.truncated ? formatTruncationNotice(truncation) : undefined,\n\t\tfullOutputPath ? `Full output: ${fullOutputPath}` : undefined,\n\t].filter((note) => note !== undefined);\n\tif (notes.length > 0) component.addChild(new Text(theme.fg(\"dim\", notes.join(\" · \")), 0, 0));\n\taddTimer(component, view.timerText);\n\treturn true;\n}\n\nexport function formatKillCall(args: { id?: unknown } | undefined): string {\n\tconst id = str(args?.id);\n\tconst target = id === null ? invalidArgText(theme) : id || theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`kill ${target}`));\n}\n\n/** Rebuild the row of a `kill` result from its receipt, or from the failure text when the call was rejected. */\nexport function rebuildKillResult(\n\tcomponent: Container,\n\tresult: { content: ResultContent; details?: CancelReceipt },\n\tview: { isError: boolean; taskId: string | undefined },\n): void {\n\tcomponent.clear();\n\tconst text = getTextOutput(result, false).trim();\n\tconst error = view.isError ? presentTaskError(text, view.taskId) : undefined;\n\tif (error) {\n\t\taddErrorLines(component, error.headline, error.hint);\n\t\treturn;\n\t}\n\tconst receipt = result.details;\n\t// A rejected call carries empty details, so only a real receipt has an execution to describe.\n\tif (!receipt?.execution) {\n\t\tcomponent.addChild(new Text(theme.fg(\"toolOutput\", text), 0, 0));\n\t\treturn;\n\t}\n\tcomponent.addChild(new Text(statusLine(cancelReceiptStatus(receipt)), 0, 0));\n\tconst failure = cleanupFailureSummary(receipt.cleanup);\n\tif (failure)\n\t\tcomponent.addChild(\n\t\t\tnew Text(statusLine({ glyph: \"✗\", tone: \"error\", label: \"cleanup failed\", detail: failure }), 0, 0),\n\t\t);\n}\n"]}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Plain-language wording for shell task observations (`wait`) and cancellations (`kill`).
3
+ *
4
+ * One source of truth for two audiences: the model reads compact sentences in the tool result text, and the
5
+ * transcript renders the same facts as a single status line. Structured data stays in the result `details`.
6
+ */
7
+ import type { CancelError, CancelReceipt, Cleanup, Failure, OutputError, TaskResult, WaitError, WaitOutcome, WatchError } from "../tasks/contracts.js";
8
+ export type TaskStatusTone = "success" | "error" | "warning" | "dim";
9
+ /** One line of task state: `✓ completed · exit 0`. The glyph and label alone carry the meaning without color. */
10
+ export interface TaskStatus {
11
+ glyph: "✓" | "✗" | "●" | "○";
12
+ tone: TaskStatusTone;
13
+ label: string;
14
+ detail?: string;
15
+ }
16
+ export declare const EMPTY_OUTPUT_TEXT = "(no output)";
17
+ export declare function taskResultStatus(result: TaskResult): TaskStatus;
18
+ /** Status line for a `wait` result. `hasOutput` says whether any output is shown below it. */
19
+ export declare function waitStatus(observation: WaitOutcome, hasOutput: boolean): TaskStatus;
20
+ export interface WaitResultTail {
21
+ observation: WaitOutcome;
22
+ truncated: boolean;
23
+ fullOutputPath?: string;
24
+ }
25
+ /**
26
+ * Everything the model reads after a wait's output: the truncation marker, one sentence with the task's state and
27
+ * exit code, and the path of the full output when it was truncated. The renderer strips the same tail.
28
+ */
29
+ export declare function waitResultTail({ observation, truncated, fullOutputPath }: WaitResultTail): string;
30
+ /** Model-facing text of a `kill` result. The receipt itself stays in the result details. */
31
+ export declare function cancelReceiptSentence(receipt: CancelReceipt): string;
32
+ /** Status line for a `kill` result, describing the task rather than the request. */
33
+ export declare function cancelReceiptStatus(receipt: CancelReceipt): TaskStatus;
34
+ /** The first resource that could not be cleaned up, for a status line; undefined when cleanup did not fail. */
35
+ export declare function cleanupFailureSummary(cleanup: Cleanup): string | undefined;
36
+ export type TaskToolFailureCode = WaitError["code"] | CancelError["code"] | OutputError["code"] | WatchError["code"];
37
+ /**
38
+ * A task failure on the `wait`/`kill` path. The message is `<Code>: <plain-language headline naming the task>`;
39
+ * callers that branch on the failure read `code` instead of parsing it.
40
+ */
41
+ export declare class TaskToolError extends Error {
42
+ readonly code: TaskToolFailureCode;
43
+ readonly taskId: string;
44
+ constructor(failure: Failure<TaskToolFailureCode>, taskId: string);
45
+ }
46
+ export interface TaskErrorPresentation {
47
+ headline: string;
48
+ hint?: string;
49
+ }
50
+ /** How the transcript presents the text of a thrown {@link TaskToolError}; undefined for any other error text. */
51
+ export declare function presentTaskError(text: string, taskId: string | undefined): TaskErrorPresentation | undefined;
52
+ //# sourceMappingURL=shell-task-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-task-status.d.ts","sourceRoot":"","sources":["../../../src/core/tools/shell-task-status.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAEX,WAAW,EACX,aAAa,EACb,OAAO,EACP,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC;AAErE,iHAAiH;AACjH,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAiC/C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAiB/D;AAmBD,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,UAAU,CAMnF;AAQD,MAAM,WAAW,cAAc;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,cAAc,GAAG,MAAM,CAEjG;AAUD,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAepE;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,UAAU,CAYtE;AAED,+GAA+G;AAC/G,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM1E;AAED,MAAM,MAAM,mBAAmB,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAyCrH;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,MAAM,EAOhE;CACD;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,kHAAkH;AAClH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,qBAAqB,GAAG,SAAS,CAS5G"}
@@ -0,0 +1,184 @@
1
+ export const EMPTY_OUTPUT_TEXT = "(no output)";
2
+ const CANCEL_CAUSE_TEXT = {
3
+ user: "stop requested",
4
+ "owner-close": "session closed",
5
+ "execution-timeout": "timed out",
6
+ "output-limit": "output limit reached",
7
+ "parent-handoff": "handed off",
8
+ pause: "paused · awaiting resume",
9
+ quit: "quit · paused · awaiting resume",
10
+ shutdown: "Atomic shut down",
11
+ };
12
+ function firstLine(text) {
13
+ return text.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
14
+ }
15
+ function withoutTrailingPeriods(text) {
16
+ let end = text.length;
17
+ while (end > 0 && (text[end - 1] === "." || /\s/.test(text[end - 1] ?? "")))
18
+ end--;
19
+ return text.slice(0, end);
20
+ }
21
+ /** The message of a failure, unless it only repeats the failure code. */
22
+ function informativeMessage(code, message) {
23
+ const line = firstLine(message);
24
+ return line && line !== code ? line : undefined;
25
+ }
26
+ function withDetail(status, detail) {
27
+ return detail === undefined ? status : { ...status, detail };
28
+ }
29
+ export function taskResultStatus(result) {
30
+ switch (result.kind) {
31
+ case "completed":
32
+ if (result.exitCode === 0)
33
+ return { glyph: "✓", tone: "success", label: "completed", detail: "exit 0" };
34
+ if (result.exitCode === undefined)
35
+ return { glyph: "✗", tone: "error", label: "ended without an exit code" };
36
+ return { glyph: "✗", tone: "error", label: `exited ${result.exitCode}` };
37
+ case "failed":
38
+ return withDetail({ glyph: "✗", tone: "error", label: "failed" }, informativeMessage(result.code, result.message));
39
+ case "cancelled":
40
+ return withDetail({ glyph: "○", tone: "dim", label: "cancelled" }, result.cause === "user" ? undefined : CANCEL_CAUSE_TEXT[result.cause]);
41
+ }
42
+ }
43
+ /** What happened to a task, as a verb phrase that follows its subject: `exited with code 1`. */
44
+ function taskResultPhrase(result) {
45
+ switch (result.kind) {
46
+ case "completed":
47
+ if (result.exitCode === 0)
48
+ return "completed with exit code 0";
49
+ if (result.exitCode === undefined)
50
+ return "ended without an exit code";
51
+ return `exited with code ${result.exitCode}`;
52
+ case "failed": {
53
+ const message = informativeMessage(result.code, result.message);
54
+ const reason = message === undefined ? undefined : withoutTrailingPeriods(message);
55
+ return `failed (${result.code})${reason ? `: ${reason}` : ""}${result.exitCode === undefined ? "" : ` (exit code ${result.exitCode})`}`;
56
+ }
57
+ case "cancelled":
58
+ return `was cancelled (${CANCEL_CAUSE_TEXT[result.cause]})`;
59
+ }
60
+ }
61
+ /** Status line for a `wait` result. `hasOutput` says whether any output is shown below it. */
62
+ export function waitStatus(observation, hasOutput) {
63
+ if (observation.kind === "settled")
64
+ return taskResultStatus(observation.result);
65
+ return withDetail({ glyph: "●", tone: "warning", label: "still running" }, hasOutput ? "showing output so far" : undefined);
66
+ }
67
+ function waitSentence(observation) {
68
+ if (observation.kind === "yielded")
69
+ return `Task ${observation.taskId} is still running (yielded: ${observation.reason}).`;
70
+ return `Task ${observation.taskId} ${taskResultPhrase(observation.result)}.`;
71
+ }
72
+ /**
73
+ * Everything the model reads after a wait's output: the truncation marker, one sentence with the task's state and
74
+ * exit code, and the path of the full output when it was truncated. The renderer strips the same tail.
75
+ */
76
+ export function waitResultTail({ observation, truncated, fullOutputPath }) {
77
+ return `${truncated ? "\n[Output truncated.]" : ""}\n\n${waitSentence(observation)}${fullOutputPath ? `\nFull output: ${fullOutputPath}` : ""}`;
78
+ }
79
+ function cleanupSentence(cleanup) {
80
+ if (cleanup.kind !== "failed")
81
+ return `Cleanup: ${cleanup.kind}.`;
82
+ const resources = cleanup.resources.map((entry) => `${entry.resource} (${entry.code}): ${withoutTrailingPeriods(firstLine(entry.message))}`);
83
+ return `Cleanup failed: ${resources.join("; ")}.`;
84
+ }
85
+ /** Model-facing text of a `kill` result. The receipt itself stays in the result details. */
86
+ export function cancelReceiptSentence(receipt) {
87
+ const { taskId, execution } = receipt;
88
+ let lead;
89
+ if (execution.kind === "settled") {
90
+ const phrase = taskResultPhrase(execution.result);
91
+ lead =
92
+ receipt.decision === "already-settled"
93
+ ? `Task ${taskId} had already finished; nothing to stop. It ${phrase}.`
94
+ : `Task ${taskId} ${phrase}.`;
95
+ }
96
+ else if (execution.kind === "cancelling") {
97
+ lead = `Cancellation requested for task ${taskId}; it has not stopped yet.`;
98
+ }
99
+ else {
100
+ lead = `Cancellation requested for task ${taskId}; it is still ${execution.kind}.`;
101
+ }
102
+ return `${lead} ${cleanupSentence(receipt.cleanup)}`;
103
+ }
104
+ /** Status line for a `kill` result, describing the task rather than the request. */
105
+ export function cancelReceiptStatus(receipt) {
106
+ const { execution } = receipt;
107
+ if (execution.kind === "settled") {
108
+ const status = taskResultStatus(execution.result);
109
+ return receipt.decision === "already-settled" ? { ...status, label: `already ${status.label}` } : status;
110
+ }
111
+ return {
112
+ glyph: "●",
113
+ tone: "warning",
114
+ label: execution.kind === "cancelling" ? "stopping" : "still running",
115
+ detail: "cancellation requested",
116
+ };
117
+ }
118
+ /** The first resource that could not be cleaned up, for a status line; undefined when cleanup did not fail. */
119
+ export function cleanupFailureSummary(cleanup) {
120
+ if (cleanup.kind !== "failed")
121
+ return undefined;
122
+ const [first, ...rest] = cleanup.resources;
123
+ if (!first)
124
+ return undefined;
125
+ const message = informativeMessage(first.code, first.message);
126
+ return `${first.resource}${message ? `: ${message}` : ""}${rest.length ? ` (+${rest.length} more)` : ""}`;
127
+ }
128
+ const TASKS_HINT = "Run /tasks to check on it.";
129
+ const TASK_ERROR_COPY = {
130
+ UnknownTask: {
131
+ headline: (taskId) => `No background task "${taskId}" in this session`,
132
+ hint: "It may have finished and been cleaned up, or belong to another session. Run /tasks to see current tasks.",
133
+ },
134
+ ScopeMismatch: {
135
+ headline: (taskId) => `Task "${taskId}" belongs to another session`,
136
+ hint: "Run /tasks to see the tasks in this session.",
137
+ },
138
+ OwnerClosed: {
139
+ headline: () => "This session's background tasks are closed",
140
+ hint: "Run the command again to start a new task.",
141
+ },
142
+ EnvironmentClosing: { headline: () => "Atomic is shutting down" },
143
+ ObserverCancelled: { headline: (taskId) => `Stopped waiting for task "${taskId}"`, hint: TASKS_HINT },
144
+ OutputUnavailable: {
145
+ headline: (taskId) => `Output for task "${taskId}" is no longer available`,
146
+ hint: "Run /tasks to check on the task.",
147
+ },
148
+ CleanupFailed: {
149
+ headline: (taskId, detail) => `Could not stop task "${taskId}"${detail ? `: ${detail}` : ""}`,
150
+ hint: "Run /tasks to check whether it is still running.",
151
+ },
152
+ StaleGeneration: { headline: () => "The task list changed while it was being read", hint: "Try again." },
153
+ };
154
+ function isTaskToolFailureCode(code) {
155
+ return Object.hasOwn(TASK_ERROR_COPY, code);
156
+ }
157
+ /**
158
+ * A task failure on the `wait`/`kill` path. The message is `<Code>: <plain-language headline naming the task>`;
159
+ * callers that branch on the failure read `code` instead of parsing it.
160
+ */
161
+ export class TaskToolError extends Error {
162
+ code;
163
+ taskId;
164
+ constructor(failure, taskId) {
165
+ super(`${failure.code}: ${TASK_ERROR_COPY[failure.code].headline(taskId, informativeMessage(failure.code, failure.message))}`);
166
+ this.name = "TaskToolError";
167
+ this.code = failure.code;
168
+ this.taskId = taskId;
169
+ }
170
+ }
171
+ /** How the transcript presents the text of a thrown {@link TaskToolError}; undefined for any other error text. */
172
+ export function presentTaskError(text, taskId) {
173
+ const match = /^(\w+): ([^\n]*)$/.exec(text.trim());
174
+ if (!match)
175
+ return undefined;
176
+ const [, code, rest] = match;
177
+ if (code === undefined || rest === undefined || !isTaskToolFailureCode(code))
178
+ return undefined;
179
+ const copy = TASK_ERROR_COPY[code];
180
+ // Sessions saved before the message was plain language hold only the code, repeated as the message.
181
+ const headline = rest === code && taskId ? copy.headline(taskId, undefined) : rest;
182
+ return copy.hint ? { headline, hint: copy.hint } : { headline };
183
+ }
184
+ //# sourceMappingURL=shell-task-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-task-status.js","sourceRoot":"","sources":["../../../src/core/tools/shell-task-status.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Plain-language wording for shell task observations (`wait`) and cancellations (`kill`).\n *\n * One source of truth for two audiences: the model reads compact sentences in the tool result text, and the\n * transcript renders the same facts as a single status line. Structured data stays in the result `details`.\n */\nimport type {\n\tCancelCause,\n\tCancelError,\n\tCancelReceipt,\n\tCleanup,\n\tFailure,\n\tOutputError,\n\tTaskResult,\n\tWaitError,\n\tWaitOutcome,\n\tWatchError,\n} from \"../tasks/contracts.js\";\n\nexport type TaskStatusTone = \"success\" | \"error\" | \"warning\" | \"dim\";\n\n/** One line of task state: `✓ completed · exit 0`. The glyph and label alone carry the meaning without color. */\nexport interface TaskStatus {\n\tglyph: \"✓\" | \"✗\" | \"●\" | \"○\";\n\ttone: TaskStatusTone;\n\tlabel: string;\n\tdetail?: string;\n}\n\nexport const EMPTY_OUTPUT_TEXT = \"(no output)\";\n\nconst CANCEL_CAUSE_TEXT: Record<CancelCause, string> = {\n\tuser: \"stop requested\",\n\t\"owner-close\": \"session closed\",\n\t\"execution-timeout\": \"timed out\",\n\t\"output-limit\": \"output limit reached\",\n\t\"parent-handoff\": \"handed off\",\n\tpause: \"paused · awaiting resume\",\n\tquit: \"quit · paused · awaiting resume\",\n\tshutdown: \"Atomic shut down\",\n};\n\nfunction firstLine(text: string): string {\n\treturn text.trim().split(/\\r?\\n/, 1)[0]?.trim() ?? \"\";\n}\n\nfunction withoutTrailingPeriods(text: string): string {\n\tlet end = text.length;\n\twhile (end > 0 && (text[end - 1] === \".\" || /\\s/.test(text[end - 1] ?? \"\"))) end--;\n\treturn text.slice(0, end);\n}\n\n/** The message of a failure, unless it only repeats the failure code. */\nfunction informativeMessage(code: string, message: string): string | undefined {\n\tconst line = firstLine(message);\n\treturn line && line !== code ? line : undefined;\n}\n\nfunction withDetail(status: Omit<TaskStatus, \"detail\">, detail: string | undefined): TaskStatus {\n\treturn detail === undefined ? status : { ...status, detail };\n}\n\nexport function taskResultStatus(result: TaskResult): TaskStatus {\n\tswitch (result.kind) {\n\t\tcase \"completed\":\n\t\t\tif (result.exitCode === 0) return { glyph: \"✓\", tone: \"success\", label: \"completed\", detail: \"exit 0\" };\n\t\t\tif (result.exitCode === undefined) return { glyph: \"✗\", tone: \"error\", label: \"ended without an exit code\" };\n\t\t\treturn { glyph: \"✗\", tone: \"error\", label: `exited ${result.exitCode}` };\n\t\tcase \"failed\":\n\t\t\treturn withDetail(\n\t\t\t\t{ glyph: \"✗\", tone: \"error\", label: \"failed\" },\n\t\t\t\tinformativeMessage(result.code, result.message),\n\t\t\t);\n\t\tcase \"cancelled\":\n\t\t\treturn withDetail(\n\t\t\t\t{ glyph: \"○\", tone: \"dim\", label: \"cancelled\" },\n\t\t\t\tresult.cause === \"user\" ? undefined : CANCEL_CAUSE_TEXT[result.cause],\n\t\t\t);\n\t}\n}\n\n/** What happened to a task, as a verb phrase that follows its subject: `exited with code 1`. */\nfunction taskResultPhrase(result: TaskResult): string {\n\tswitch (result.kind) {\n\t\tcase \"completed\":\n\t\t\tif (result.exitCode === 0) return \"completed with exit code 0\";\n\t\t\tif (result.exitCode === undefined) return \"ended without an exit code\";\n\t\t\treturn `exited with code ${result.exitCode}`;\n\t\tcase \"failed\": {\n\t\t\tconst message = informativeMessage(result.code, result.message);\n\t\t\tconst reason = message === undefined ? undefined : withoutTrailingPeriods(message);\n\t\t\treturn `failed (${result.code})${reason ? `: ${reason}` : \"\"}${result.exitCode === undefined ? \"\" : ` (exit code ${result.exitCode})`}`;\n\t\t}\n\t\tcase \"cancelled\":\n\t\t\treturn `was cancelled (${CANCEL_CAUSE_TEXT[result.cause]})`;\n\t}\n}\n\n/** Status line for a `wait` result. `hasOutput` says whether any output is shown below it. */\nexport function waitStatus(observation: WaitOutcome, hasOutput: boolean): TaskStatus {\n\tif (observation.kind === \"settled\") return taskResultStatus(observation.result);\n\treturn withDetail(\n\t\t{ glyph: \"●\", tone: \"warning\", label: \"still running\" },\n\t\thasOutput ? \"showing output so far\" : undefined,\n\t);\n}\n\nfunction waitSentence(observation: WaitOutcome): string {\n\tif (observation.kind === \"yielded\")\n\t\treturn `Task ${observation.taskId} is still running (yielded: ${observation.reason}).`;\n\treturn `Task ${observation.taskId} ${taskResultPhrase(observation.result)}.`;\n}\n\nexport interface WaitResultTail {\n\tobservation: WaitOutcome;\n\ttruncated: boolean;\n\tfullOutputPath?: string;\n}\n\n/**\n * Everything the model reads after a wait's output: the truncation marker, one sentence with the task's state and\n * exit code, and the path of the full output when it was truncated. The renderer strips the same tail.\n */\nexport function waitResultTail({ observation, truncated, fullOutputPath }: WaitResultTail): string {\n\treturn `${truncated ? \"\\n[Output truncated.]\" : \"\"}\\n\\n${waitSentence(observation)}${fullOutputPath ? `\\nFull output: ${fullOutputPath}` : \"\"}`;\n}\n\nfunction cleanupSentence(cleanup: Cleanup): string {\n\tif (cleanup.kind !== \"failed\") return `Cleanup: ${cleanup.kind}.`;\n\tconst resources = cleanup.resources.map(\n\t\t(entry) => `${entry.resource} (${entry.code}): ${withoutTrailingPeriods(firstLine(entry.message))}`,\n\t);\n\treturn `Cleanup failed: ${resources.join(\"; \")}.`;\n}\n\n/** Model-facing text of a `kill` result. The receipt itself stays in the result details. */\nexport function cancelReceiptSentence(receipt: CancelReceipt): string {\n\tconst { taskId, execution } = receipt;\n\tlet lead: string;\n\tif (execution.kind === \"settled\") {\n\t\tconst phrase = taskResultPhrase(execution.result);\n\t\tlead =\n\t\t\treceipt.decision === \"already-settled\"\n\t\t\t\t? `Task ${taskId} had already finished; nothing to stop. It ${phrase}.`\n\t\t\t\t: `Task ${taskId} ${phrase}.`;\n\t} else if (execution.kind === \"cancelling\") {\n\t\tlead = `Cancellation requested for task ${taskId}; it has not stopped yet.`;\n\t} else {\n\t\tlead = `Cancellation requested for task ${taskId}; it is still ${execution.kind}.`;\n\t}\n\treturn `${lead} ${cleanupSentence(receipt.cleanup)}`;\n}\n\n/** Status line for a `kill` result, describing the task rather than the request. */\nexport function cancelReceiptStatus(receipt: CancelReceipt): TaskStatus {\n\tconst { execution } = receipt;\n\tif (execution.kind === \"settled\") {\n\t\tconst status = taskResultStatus(execution.result);\n\t\treturn receipt.decision === \"already-settled\" ? { ...status, label: `already ${status.label}` } : status;\n\t}\n\treturn {\n\t\tglyph: \"●\",\n\t\ttone: \"warning\",\n\t\tlabel: execution.kind === \"cancelling\" ? \"stopping\" : \"still running\",\n\t\tdetail: \"cancellation requested\",\n\t};\n}\n\n/** The first resource that could not be cleaned up, for a status line; undefined when cleanup did not fail. */\nexport function cleanupFailureSummary(cleanup: Cleanup): string | undefined {\n\tif (cleanup.kind !== \"failed\") return undefined;\n\tconst [first, ...rest] = cleanup.resources;\n\tif (!first) return undefined;\n\tconst message = informativeMessage(first.code, first.message);\n\treturn `${first.resource}${message ? `: ${message}` : \"\"}${rest.length ? ` (+${rest.length} more)` : \"\"}`;\n}\n\nexport type TaskToolFailureCode = WaitError[\"code\"] | CancelError[\"code\"] | OutputError[\"code\"] | WatchError[\"code\"];\n\ninterface TaskErrorCopy {\n\t/** Names the id and what went wrong; `detail` is the supervisor's message when it says more than the code. */\n\theadline: (taskId: string, detail: string | undefined) => string;\n\t/** The next step. Shown in the transcript only, not sent to the model. */\n\thint?: string;\n}\n\nconst TASKS_HINT = \"Run /tasks to check on it.\";\n\nconst TASK_ERROR_COPY: Record<TaskToolFailureCode, TaskErrorCopy> = {\n\tUnknownTask: {\n\t\theadline: (taskId) => `No background task \"${taskId}\" in this session`,\n\t\thint: \"It may have finished and been cleaned up, or belong to another session. Run /tasks to see current tasks.\",\n\t},\n\tScopeMismatch: {\n\t\theadline: (taskId) => `Task \"${taskId}\" belongs to another session`,\n\t\thint: \"Run /tasks to see the tasks in this session.\",\n\t},\n\tOwnerClosed: {\n\t\theadline: () => \"This session's background tasks are closed\",\n\t\thint: \"Run the command again to start a new task.\",\n\t},\n\tEnvironmentClosing: { headline: () => \"Atomic is shutting down\" },\n\tObserverCancelled: { headline: (taskId) => `Stopped waiting for task \"${taskId}\"`, hint: TASKS_HINT },\n\tOutputUnavailable: {\n\t\theadline: (taskId) => `Output for task \"${taskId}\" is no longer available`,\n\t\thint: \"Run /tasks to check on the task.\",\n\t},\n\tCleanupFailed: {\n\t\theadline: (taskId, detail) => `Could not stop task \"${taskId}\"${detail ? `: ${detail}` : \"\"}`,\n\t\thint: \"Run /tasks to check whether it is still running.\",\n\t},\n\tStaleGeneration: { headline: () => \"The task list changed while it was being read\", hint: \"Try again.\" },\n};\n\nfunction isTaskToolFailureCode(code: string): code is TaskToolFailureCode {\n\treturn Object.hasOwn(TASK_ERROR_COPY, code);\n}\n\n/**\n * A task failure on the `wait`/`kill` path. The message is `<Code>: <plain-language headline naming the task>`;\n * callers that branch on the failure read `code` instead of parsing it.\n */\nexport class TaskToolError extends Error {\n\treadonly code: TaskToolFailureCode;\n\treadonly taskId: string;\n\n\tconstructor(failure: Failure<TaskToolFailureCode>, taskId: string) {\n\t\tsuper(\n\t\t\t`${failure.code}: ${TASK_ERROR_COPY[failure.code].headline(taskId, informativeMessage(failure.code, failure.message))}`,\n\t\t);\n\t\tthis.name = \"TaskToolError\";\n\t\tthis.code = failure.code;\n\t\tthis.taskId = taskId;\n\t}\n}\n\nexport interface TaskErrorPresentation {\n\theadline: string;\n\thint?: string;\n}\n\n/** How the transcript presents the text of a thrown {@link TaskToolError}; undefined for any other error text. */\nexport function presentTaskError(text: string, taskId: string | undefined): TaskErrorPresentation | undefined {\n\tconst match = /^(\\w+): ([^\\n]*)$/.exec(text.trim());\n\tif (!match) return undefined;\n\tconst [, code, rest] = match;\n\tif (code === undefined || rest === undefined || !isTaskToolFailureCode(code)) return undefined;\n\tconst copy = TASK_ERROR_COPY[code];\n\t// Sessions saved before the message was plain language hold only the code, repeated as the message.\n\tconst headline = rest === code && taskId ? copy.headline(taskId, undefined) : rest;\n\treturn copy.hint ? { headline, hint: copy.hint } : { headline };\n}\n"]}
@@ -18,6 +18,11 @@ export interface StructuredOutputToolOptions<TSchemaDef extends TSchema> {
18
18
  capture?: StructuredOutputCapture<Static<TSchemaDef>>;
19
19
  output?: StructuredOutputFileCapture;
20
20
  name?: string;
21
+ /**
22
+ * Wall-clock limit in milliseconds for each call's whole decision, covering every repair attempt, transport retry
23
+ * and model fallback. Defaults to the session's `httpIdleTimeoutMs` setting. The calling model cannot change it.
24
+ */
25
+ timeoutMs?: number;
21
26
  }
22
27
  export declare const StructuredOutputParameters: Type.TObject<{
23
28
  instructions: Type.TString;
@@ -1 +1 @@
1
- {"version":3,"file":"structured-output.d.ts","sourceRoot":"","sources":["../../../src/core/tools/structured-output.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEzE,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAE/D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAC7D,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,EAAE,CAAC;AACjE,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE/D,MAAM,WAAW,uBAAuB,CAAC,MAAM,GAAG,OAAO;IACxD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC3C,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,2BAA2B,CAAC,UAAU,SAAS,OAAO;IACtE,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,uBAAuB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IACtD,MAAM,CAAC,EAAE,2BAA2B,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,0BAA0B;;;;;EAyBtC,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AA6B/E,wBAAgB,6BAA6B,CAAC,MAAM,GAAG,OAAO,KAAK,uBAAuB,CAAC,MAAM,CAAC,CAEjG;AAED,wBAAgB,0BAA0B,CAAC,UAAU,SAAS,OAAO,EACpE,OAAO,EAAE,2BAA2B,CAAC,UAAU,CAAC,GAC9C,cAAc,CAAC,OAAO,0BAA0B,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CA8CvE"}
1
+ {"version":3,"file":"structured-output.d.ts","sourceRoot":"","sources":["../../../src/core/tools/structured-output.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGzE,eAAO,MAAM,2BAA2B,sBAAsB,CAAC;AAE/D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAC7D,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,EAAE,CAAC;AACjE,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE/D,MAAM,WAAW,uBAAuB,CAAC,MAAM,GAAG,OAAO;IACxD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,2BAA2B;IAC3C,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,2BAA2B,CAAC,UAAU,SAAS,OAAO;IACtE,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,uBAAuB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IACtD,MAAM,CAAC,EAAE,2BAA2B,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,0BAA0B;;;;;EAyBtC,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AA6B/E,wBAAgB,6BAA6B,CAAC,MAAM,GAAG,OAAO,KAAK,uBAAuB,CAAC,MAAM,CAAC,CAEjG;AAED,wBAAgB,0BAA0B,CAAC,UAAU,SAAS,OAAO,EACpE,OAAO,EAAE,2BAA2B,CAAC,UAAU,CAAC,GAC9C,cAAc,CAAC,OAAO,0BAA0B,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAgDvE"}
@@ -2,6 +2,7 @@ import * as fs from "node:fs/promises";
2
2
  import * as path from "node:path";
3
3
  import { Type } from "typebox";
4
4
  import { defineTool } from "../extensions/types.js";
5
+ import { resolveDecisionDeadlineMs, validateTimeoutOverride } from "../structured-output/deadline.js";
5
6
  export const STRUCTURED_OUTPUT_TOOL_NAME = "structured_output";
6
7
  export const StructuredOutputParameters = Type.Object({
7
8
  instructions: Type.String({ minLength: 1, description: "Complete judgment instructions for the result." }),
@@ -44,6 +45,7 @@ export function createStructuredOutputCapture() {
44
45
  }
45
46
  export function createStructuredOutputTool(options) {
46
47
  const name = options.name ?? STRUCTURED_OUTPUT_TOOL_NAME;
48
+ validateTimeoutOverride(options.timeoutMs);
47
49
  return defineTool({
48
50
  name,
49
51
  label: "Structured Output",
@@ -67,6 +69,7 @@ export function createStructuredOutputTool(options) {
67
69
  ...(params.fallbackModels !== undefined ? { fallbackModels: params.fallbackModels } : {}),
68
70
  currentModel: ctx.model,
69
71
  modelRegistry: ctx.modelRegistry,
72
+ timeoutMs: resolveDecisionDeadlineMs(options.timeoutMs, ctx.getHttpIdleTimeoutMs?.()),
70
73
  ...(signal ? { signal } : {}),
71
74
  });
72
75
  const value = result.value;
@@ -1 +1 @@
1
- {"version":3,"file":"structured-output.js","sourceRoot":"","sources":["../../../src/core/tools/structured-output.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { type Static, type TSchema, Type } from \"typebox\";\nimport { defineTool, type ToolDefinition } from \"../extensions/types.ts\";\n\nexport const STRUCTURED_OUTPUT_TOOL_NAME = \"structured_output\";\n\nexport type JsonPrimitive = string | number | boolean | null;\nexport type JsonValue = JsonPrimitive | JsonObject | JsonValue[];\nexport type JsonObject = { readonly [key: string]: JsonValue };\n\nexport interface StructuredOutputCapture<TValue = unknown> {\n\tvalue: TValue | undefined;\n\tcalled: boolean;\n}\n\nexport interface StructuredOutputFileCapture {\n\toutputPath: string;\n}\n\nexport interface StructuredOutputToolOptions<TSchemaDef extends TSchema> {\n\tschema: TSchemaDef;\n\tcapture?: StructuredOutputCapture<Static<TSchemaDef>>;\n\toutput?: StructuredOutputFileCapture;\n\tname?: string;\n}\n\nexport const StructuredOutputParameters = Type.Object(\n\t{\n\t\tinstructions: Type.String({ minLength: 1, description: \"Complete judgment instructions for the result.\" }),\n\t\tstate: Type.Object(\n\t\t\t{},\n\t\t\t{\n\t\t\t\tadditionalProperties: true,\n\t\t\t\tminProperties: 1,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Named finite JSON values holding the task, relevant context, constraints and reference text. Never include secrets.\",\n\t\t\t},\n\t\t),\n\t\tmodel: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Exact provider/model ID of a chat or classifier model, such as typesafe/jev-latest. Omit to use the current chat model.\",\n\t\t\t}),\n\t\t),\n\t\tfallbackModels: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Ordered exact fallback model IDs. The current chat model is always tried last.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\nexport type StructuredOutputParams = Static<typeof StructuredOutputParameters>;\n\nfunction stringifyParams<TSchemaDef extends TSchema>(params: Static<TSchemaDef>): string {\n\ttry {\n\t\treturn JSON.stringify(params, null, 2);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Structured output must be JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\nasync function writePrivateJsonFile(filePath: string, serializedJson: string): Promise<void> {\n\tawait fs.mkdir(path.dirname(filePath), { recursive: true });\n\tawait fs.writeFile(filePath, serializedJson, { mode: 0o600 });\n\t// Re-apply the private mode after writing so pre-existing looser files are tightened too.\n\tawait fs.chmod(filePath, 0o600);\n}\n\nasync function writeCapturedOutput(output: StructuredOutputFileCapture, serializedParams: string): Promise<void> {\n\ttry {\n\t\tawait writePrivateJsonFile(output.outputPath, serializedParams);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to write structured output capture: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\nexport function createStructuredOutputCapture<TValue = unknown>(): StructuredOutputCapture<TValue> {\n\treturn { value: undefined, called: false };\n}\n\nexport function createStructuredOutputTool<TSchemaDef extends TSchema>(\n\toptions: StructuredOutputToolOptions<TSchemaDef>,\n): ToolDefinition<typeof StructuredOutputParameters, Static<TSchemaDef>> {\n\tconst name = options.name ?? STRUCTURED_OUTPUT_TOOL_NAME;\n\n\treturn defineTool({\n\t\tname,\n\t\tlabel: \"Structured Output\",\n\t\tdescription:\n\t\t\t\"Infer the final machine-readable result from instructions and named state using the selected model, then any fallbacks, then the current chat model.\",\n\t\tpromptSnippet: \"Return final machine-readable output\",\n\t\tpromptGuidelines: [\n\t\t\t`${name} is the final machine-readable result channel; call ${name} exactly once when done.`,\n\t\t\t\"Pass complete instructions and named state; omit model to use the current chat model.\",\n\t\t\t`Do not write a prose final answer after calling ${name}.`,\n\t\t],\n\t\tparameters: StructuredOutputParameters,\n\t\tmaxResultSizeChars: Infinity,\n\t\tstructuredOutput: true,\n\t\tasync execute(_toolCallId, params, signal, _onUpdate, ctx): Promise<AgentToolResult<Static<TSchemaDef>>> {\n\t\t\tconst { generateStructuredOutput } = await import(\"../structured-output/index.js\");\n\t\t\tconst result = await generateStructuredOutput({\n\t\t\t\tschema: options.schema,\n\t\t\t\tinstructions: params.instructions,\n\t\t\t\tstate: params.state as JsonObject,\n\t\t\t\t...(params.model !== undefined ? { model: params.model } : {}),\n\t\t\t\t...(params.fallbackModels !== undefined ? { fallbackModels: params.fallbackModels } : {}),\n\t\t\t\tcurrentModel: ctx.model,\n\t\t\t\tmodelRegistry: ctx.modelRegistry,\n\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t});\n\t\t\tconst value = result.value;\n\t\t\tconst serializedValue = stringifyParams(value);\n\t\t\tif (options.output) {\n\t\t\t\tawait writeCapturedOutput(options.output, serializedValue);\n\t\t\t}\n\t\t\tif (options.capture) {\n\t\t\t\toptions.capture.value = value;\n\t\t\t\toptions.capture.called = true;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: serializedValue }],\n\t\t\t\tdetails: value,\n\t\t\t\tterminate: true,\n\t\t\t};\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"structured-output.js","sourceRoot":"","sources":["../../../src/core/tools/structured-output.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { type Static, type TSchema, Type } from \"typebox\";\nimport { defineTool, type ToolDefinition } from \"../extensions/types.ts\";\nimport { resolveDecisionDeadlineMs, validateTimeoutOverride } from \"../structured-output/deadline.js\";\n\nexport const STRUCTURED_OUTPUT_TOOL_NAME = \"structured_output\";\n\nexport type JsonPrimitive = string | number | boolean | null;\nexport type JsonValue = JsonPrimitive | JsonObject | JsonValue[];\nexport type JsonObject = { readonly [key: string]: JsonValue };\n\nexport interface StructuredOutputCapture<TValue = unknown> {\n\tvalue: TValue | undefined;\n\tcalled: boolean;\n}\n\nexport interface StructuredOutputFileCapture {\n\toutputPath: string;\n}\n\nexport interface StructuredOutputToolOptions<TSchemaDef extends TSchema> {\n\tschema: TSchemaDef;\n\tcapture?: StructuredOutputCapture<Static<TSchemaDef>>;\n\toutput?: StructuredOutputFileCapture;\n\tname?: string;\n\t/**\n\t * Wall-clock limit in milliseconds for each call's whole decision, covering every repair attempt, transport retry\n\t * and model fallback. Defaults to the session's `httpIdleTimeoutMs` setting. The calling model cannot change it.\n\t */\n\ttimeoutMs?: number;\n}\n\nexport const StructuredOutputParameters = Type.Object(\n\t{\n\t\tinstructions: Type.String({ minLength: 1, description: \"Complete judgment instructions for the result.\" }),\n\t\tstate: Type.Object(\n\t\t\t{},\n\t\t\t{\n\t\t\t\tadditionalProperties: true,\n\t\t\t\tminProperties: 1,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Named finite JSON values holding the task, relevant context, constraints and reference text. Never include secrets.\",\n\t\t\t},\n\t\t),\n\t\tmodel: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Exact provider/model ID of a chat or classifier model, such as typesafe/jev-latest. Omit to use the current chat model.\",\n\t\t\t}),\n\t\t),\n\t\tfallbackModels: Type.Optional(\n\t\t\tType.Array(Type.String(), {\n\t\t\t\tdescription: \"Ordered exact fallback model IDs. The current chat model is always tried last.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\nexport type StructuredOutputParams = Static<typeof StructuredOutputParameters>;\n\nfunction stringifyParams<TSchemaDef extends TSchema>(params: Static<TSchemaDef>): string {\n\ttry {\n\t\treturn JSON.stringify(params, null, 2);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Structured output must be JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\nasync function writePrivateJsonFile(filePath: string, serializedJson: string): Promise<void> {\n\tawait fs.mkdir(path.dirname(filePath), { recursive: true });\n\tawait fs.writeFile(filePath, serializedJson, { mode: 0o600 });\n\t// Re-apply the private mode after writing so pre-existing looser files are tightened too.\n\tawait fs.chmod(filePath, 0o600);\n}\n\nasync function writeCapturedOutput(output: StructuredOutputFileCapture, serializedParams: string): Promise<void> {\n\ttry {\n\t\tawait writePrivateJsonFile(output.outputPath, serializedParams);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to write structured output capture: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\nexport function createStructuredOutputCapture<TValue = unknown>(): StructuredOutputCapture<TValue> {\n\treturn { value: undefined, called: false };\n}\n\nexport function createStructuredOutputTool<TSchemaDef extends TSchema>(\n\toptions: StructuredOutputToolOptions<TSchemaDef>,\n): ToolDefinition<typeof StructuredOutputParameters, Static<TSchemaDef>> {\n\tconst name = options.name ?? STRUCTURED_OUTPUT_TOOL_NAME;\n\tvalidateTimeoutOverride(options.timeoutMs);\n\n\treturn defineTool({\n\t\tname,\n\t\tlabel: \"Structured Output\",\n\t\tdescription:\n\t\t\t\"Infer the final machine-readable result from instructions and named state using the selected model, then any fallbacks, then the current chat model.\",\n\t\tpromptSnippet: \"Return final machine-readable output\",\n\t\tpromptGuidelines: [\n\t\t\t`${name} is the final machine-readable result channel; call ${name} exactly once when done.`,\n\t\t\t\"Pass complete instructions and named state; omit model to use the current chat model.\",\n\t\t\t`Do not write a prose final answer after calling ${name}.`,\n\t\t],\n\t\tparameters: StructuredOutputParameters,\n\t\tmaxResultSizeChars: Infinity,\n\t\tstructuredOutput: true,\n\t\tasync execute(_toolCallId, params, signal, _onUpdate, ctx): Promise<AgentToolResult<Static<TSchemaDef>>> {\n\t\t\tconst { generateStructuredOutput } = await import(\"../structured-output/index.js\");\n\t\t\tconst result = await generateStructuredOutput({\n\t\t\t\tschema: options.schema,\n\t\t\t\tinstructions: params.instructions,\n\t\t\t\tstate: params.state as JsonObject,\n\t\t\t\t...(params.model !== undefined ? { model: params.model } : {}),\n\t\t\t\t...(params.fallbackModels !== undefined ? { fallbackModels: params.fallbackModels } : {}),\n\t\t\t\tcurrentModel: ctx.model,\n\t\t\t\tmodelRegistry: ctx.modelRegistry,\n\t\t\t\ttimeoutMs: resolveDecisionDeadlineMs(options.timeoutMs, ctx.getHttpIdleTimeoutMs?.()),\n\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t});\n\t\t\tconst value = result.value;\n\t\t\tconst serializedValue = stringifyParams(value);\n\t\t\tif (options.output) {\n\t\t\t\tawait writeCapturedOutput(options.output, serializedValue);\n\t\t\t}\n\t\t\tif (options.capture) {\n\t\t\t\toptions.capture.value = value;\n\t\t\t\toptions.capture.called = true;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: serializedValue }],\n\t\t\t\tdetails: value,\n\t\t\t\tterminate: true,\n\t\t\t};\n\t\t},\n\t});\n}\n"]}