@astralyn/pi 1.4.6 → 1.4.7

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 (242) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/bundle/chunks/{chunk-KDO6L76C.js → chunk-FODCTZXW.js} +4 -4
  3. package/dist/bundle/chunks/{chunk-EYKC6ESU.js → chunk-FYKNSJG6.js} +1 -1
  4. package/dist/bundle/chunks/{chunk-AXFWZIHH.js → chunk-MG5XDTXV.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-ALHAFUHP.js → chunk-PU2IWWXV.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-5M3YJ54Z.js → chunk-RO2VH6UZ.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-RBTJBQWX.js → chunk-YJTSOLP2.js} +73 -74
  8. package/dist/bundle/chunks/{cli-FH77R7JR.js → cli-MEL7SGJD.js} +1 -1
  9. package/dist/bundle/chunks/{execute-5ZQUS52M.js → execute-4CWRNHPO.js} +1 -1
  10. package/dist/bundle/chunks/{runtime-R5CMHJ5P.js → runtime-R3X67XMR.js} +1 -1
  11. package/dist/bundle/chunks/{virtual-modules-KCQU7LOC.js → virtual-modules-PKEOKGYI.js} +1 -1
  12. package/dist/bundle/cli.js +1 -1
  13. package/dist/bundle/index.js +1 -1
  14. package/dist/bundle/rpc-entry.js +1 -1
  15. package/dist/core/agent-session.d.ts +0 -3
  16. package/dist/core/agent-session.d.ts.map +1 -1
  17. package/dist/core/agent-session.js +0 -4
  18. package/dist/core/agent-session.js.map +1 -1
  19. package/dist/core/extensions/index.d.ts +1 -1
  20. package/dist/core/extensions/index.d.ts.map +1 -1
  21. package/dist/core/extensions/index.js.map +1 -1
  22. package/dist/core/package-manager.d.ts +7 -1
  23. package/dist/core/package-manager.d.ts.map +1 -1
  24. package/dist/core/package-manager.js +72 -1
  25. package/dist/core/package-manager.js.map +1 -1
  26. package/dist/core/resource-loader.d.ts +1 -0
  27. package/dist/core/resource-loader.d.ts.map +1 -1
  28. package/dist/core/resource-loader.js +23 -7
  29. package/dist/core/resource-loader.js.map +1 -1
  30. package/dist/core/settings-manager.d.ts +4 -2
  31. package/dist/core/settings-manager.d.ts.map +1 -1
  32. package/dist/core/settings-manager.js +11 -0
  33. package/dist/core/settings-manager.js.map +1 -1
  34. package/dist/core/settings-schema.d.ts +7 -0
  35. package/dist/core/settings-schema.d.ts.map +1 -1
  36. package/dist/core/settings-schema.js +6 -0
  37. package/dist/core/settings-schema.js.map +1 -1
  38. package/dist/core/skills.d.ts +10 -0
  39. package/dist/core/skills.d.ts.map +1 -1
  40. package/dist/core/skills.js +23 -0
  41. package/dist/core/skills.js.map +1 -1
  42. package/dist/core/tasks/delivery.d.ts +11 -4
  43. package/dist/core/tasks/delivery.d.ts.map +1 -1
  44. package/dist/core/tasks/delivery.js +9 -9
  45. package/dist/core/tasks/delivery.js.map +1 -1
  46. package/dist/core/tasks/execution.d.ts +10 -3
  47. package/dist/core/tasks/execution.d.ts.map +1 -1
  48. package/dist/core/tasks/execution.js +72 -52
  49. package/dist/core/tasks/execution.js.map +1 -1
  50. package/dist/core/tasks/format.d.ts +0 -2
  51. package/dist/core/tasks/format.d.ts.map +1 -1
  52. package/dist/core/tasks/format.js +1 -16
  53. package/dist/core/tasks/format.js.map +1 -1
  54. package/dist/core/tasks/limits.d.ts +12 -1
  55. package/dist/core/tasks/limits.d.ts.map +1 -1
  56. package/dist/core/tasks/limits.js +20 -1
  57. package/dist/core/tasks/limits.js.map +1 -1
  58. package/dist/core/tasks/output.d.ts +6 -12
  59. package/dist/core/tasks/output.d.ts.map +1 -1
  60. package/dist/core/tasks/output.js +35 -32
  61. package/dist/core/tasks/output.js.map +1 -1
  62. package/dist/core/tasks/record.d.ts +45 -0
  63. package/dist/core/tasks/record.d.ts.map +1 -0
  64. package/dist/core/tasks/record.js +80 -0
  65. package/dist/core/tasks/record.js.map +1 -0
  66. package/dist/core/tasks/runtime.d.ts +14 -14
  67. package/dist/core/tasks/runtime.d.ts.map +1 -1
  68. package/dist/core/tasks/runtime.js +111 -93
  69. package/dist/core/tasks/runtime.js.map +1 -1
  70. package/dist/core/tasks/session.d.ts +0 -1
  71. package/dist/core/tasks/session.d.ts.map +1 -1
  72. package/dist/core/tasks/session.js +7 -8
  73. package/dist/core/tasks/session.js.map +1 -1
  74. package/dist/core/tasks/store.d.ts +18 -25
  75. package/dist/core/tasks/store.d.ts.map +1 -1
  76. package/dist/core/tasks/store.js +42 -40
  77. package/dist/core/tasks/store.js.map +1 -1
  78. package/dist/core/tasks/types.d.ts +96 -17
  79. package/dist/core/tasks/types.d.ts.map +1 -1
  80. package/dist/core/tasks/types.js.map +1 -1
  81. package/dist/core/tools/shell-execution.d.ts +8 -7
  82. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  83. package/dist/core/tools/shell-execution.js +18 -26
  84. package/dist/core/tools/shell-execution.js.map +1 -1
  85. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  86. package/dist/core/tools/shell-tool.js +31 -29
  87. package/dist/core/tools/shell-tool.js.map +1 -1
  88. package/dist/core/usage-totals.d.ts +3 -0
  89. package/dist/core/usage-totals.d.ts.map +1 -1
  90. package/dist/core/usage-totals.js +15 -0
  91. package/dist/core/usage-totals.js.map +1 -1
  92. package/dist/extensions/agent/progress.d.ts.map +1 -1
  93. package/dist/extensions/agent/progress.js +1 -11
  94. package/dist/extensions/agent/progress.js.map +1 -1
  95. package/dist/extensions/agent/tool.d.ts.map +1 -1
  96. package/dist/extensions/agent/tool.js +9 -5
  97. package/dist/extensions/agent/tool.js.map +1 -1
  98. package/dist/extensions/agent/worker.d.ts.map +1 -1
  99. package/dist/extensions/agent/worker.js +3 -5
  100. package/dist/extensions/agent/worker.js.map +1 -1
  101. package/dist/extensions/btw/agent.d.ts +1 -1
  102. package/dist/extensions/btw/agent.d.ts.map +1 -1
  103. package/dist/extensions/btw/agent.js +3 -20
  104. package/dist/extensions/btw/agent.js.map +1 -1
  105. package/dist/extensions/cached-compaction/index.d.ts.map +1 -1
  106. package/dist/extensions/cached-compaction/index.js +3 -22
  107. package/dist/extensions/cached-compaction/index.js.map +1 -1
  108. package/dist/extensions/cached-compaction/render.d.ts +1 -0
  109. package/dist/extensions/cached-compaction/render.d.ts.map +1 -1
  110. package/dist/extensions/cached-compaction/render.js +42 -14
  111. package/dist/extensions/cached-compaction/render.js.map +1 -1
  112. package/dist/extensions/deepwiki/client.d.ts.map +1 -1
  113. package/dist/extensions/deepwiki/client.js +6 -78
  114. package/dist/extensions/deepwiki/client.js.map +1 -1
  115. package/dist/extensions/deepwiki/transport.d.ts +3 -0
  116. package/dist/extensions/deepwiki/transport.d.ts.map +1 -0
  117. package/dist/extensions/deepwiki/transport.js +96 -0
  118. package/dist/extensions/deepwiki/transport.js.map +1 -0
  119. package/dist/extensions/provider/ui/builtin-data.d.ts +3 -3
  120. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  121. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  122. package/dist/extensions/provider/ui/compat.d.ts +3 -3
  123. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  124. package/dist/extensions/provider/ui/compat.js.map +1 -1
  125. package/dist/extensions/provider/ui/controls.d.ts +2 -2
  126. package/dist/extensions/provider/ui/controls.d.ts.map +1 -1
  127. package/dist/extensions/provider/ui/controls.js.map +1 -1
  128. package/dist/extensions/provider/ui/dialogs.d.ts +3 -3
  129. package/dist/extensions/provider/ui/dialogs.d.ts.map +1 -1
  130. package/dist/extensions/provider/ui/dialogs.js.map +1 -1
  131. package/dist/extensions/provider/ui/dictionary.d.ts +2 -2
  132. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  133. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  134. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  135. package/dist/extensions/provider/ui/editor.js +1 -3
  136. package/dist/extensions/provider/ui/editor.js.map +1 -1
  137. package/dist/extensions/provider/ui/fetch-models.d.ts +2 -2
  138. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  139. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  140. package/dist/extensions/provider/ui/model-fields.d.ts +2 -2
  141. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  142. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  143. package/dist/extensions/provider/ui/model-options.d.ts +6 -6
  144. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  145. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  146. package/dist/extensions/provider/ui/pane.d.ts +21 -12
  147. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  148. package/dist/extensions/provider/ui/pane.js.map +1 -1
  149. package/dist/extensions/provider/ui/provider-fields.d.ts +3 -3
  150. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  151. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  152. package/dist/extensions/provider/ui/thinking-map.d.ts +2 -2
  153. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  154. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  155. package/dist/extensions/run-summary/format.js +1 -1
  156. package/dist/extensions/run-summary/format.js.map +1 -1
  157. package/dist/extensions/statusline/usage.d.ts.map +1 -1
  158. package/dist/extensions/statusline/usage.js +2 -6
  159. package/dist/extensions/statusline/usage.js.map +1 -1
  160. package/dist/extensions/tasks/tool/actions.d.ts +1 -1
  161. package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
  162. package/dist/extensions/tasks/tool/actions.js +49 -106
  163. package/dist/extensions/tasks/tool/actions.js.map +1 -1
  164. package/dist/extensions/tasks/tool/constants.d.ts +1 -6
  165. package/dist/extensions/tasks/tool/constants.d.ts.map +1 -1
  166. package/dist/extensions/tasks/tool/constants.js +1 -6
  167. package/dist/extensions/tasks/tool/constants.js.map +1 -1
  168. package/dist/extensions/tasks/tool/schema.d.ts +0 -3
  169. package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
  170. package/dist/extensions/tasks/tool/schema.js +4 -13
  171. package/dist/extensions/tasks/tool/schema.js.map +1 -1
  172. package/dist/extensions/tasks/tool.d.ts.map +1 -1
  173. package/dist/extensions/tasks/tool.js +2 -2
  174. package/dist/extensions/tasks/tool.js.map +1 -1
  175. package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
  176. package/dist/extensions/tasks/ui/completion-render.js +31 -33
  177. package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
  178. package/dist/extensions/tasks/ui/layout.d.ts +7 -7
  179. package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
  180. package/dist/extensions/tasks/ui/layout.js +17 -19
  181. package/dist/extensions/tasks/ui/layout.js.map +1 -1
  182. package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
  183. package/dist/extensions/tasks/ui/list.js +2 -3
  184. package/dist/extensions/tasks/ui/list.js.map +1 -1
  185. package/dist/extensions/tasks/ui/manager.d.ts +16 -7
  186. package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
  187. package/dist/extensions/tasks/ui/manager.js +163 -131
  188. package/dist/extensions/tasks/ui/manager.js.map +1 -1
  189. package/dist/extensions/tasks/ui/model.d.ts +25 -0
  190. package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
  191. package/dist/extensions/tasks/ui/model.js +4 -0
  192. package/dist/extensions/tasks/ui/model.js.map +1 -1
  193. package/dist/extensions/tasks/ui/render.d.ts +1 -1
  194. package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
  195. package/dist/extensions/tasks/ui/render.js +11 -7
  196. package/dist/extensions/tasks/ui/render.js.map +1 -1
  197. package/dist/extensions/tasks/ui/status.d.ts +15 -0
  198. package/dist/extensions/tasks/ui/status.d.ts.map +1 -0
  199. package/dist/extensions/tasks/ui/status.js +16 -0
  200. package/dist/extensions/tasks/ui/status.js.map +1 -0
  201. package/dist/index.d.ts +1 -1
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js.map +1 -1
  204. package/dist/modes/interactive/components/config-selector.d.ts +14 -1
  205. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  206. package/dist/modes/interactive/components/config-selector.js +258 -7
  207. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  208. package/dist/modes/interactive/components/status-marker.d.ts +2 -1
  209. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  210. package/dist/modes/interactive/components/status-marker.js +0 -1
  211. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  212. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  213. package/dist/modes/interactive/interactive-mode.js +7 -1
  214. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  215. package/dist/utils/duration.d.ts +3 -0
  216. package/dist/utils/duration.d.ts.map +1 -0
  217. package/dist/utils/duration.js +17 -0
  218. package/dist/utils/duration.js.map +1 -0
  219. package/dist/utils/number.d.ts +3 -0
  220. package/dist/utils/number.d.ts.map +1 -0
  221. package/dist/utils/number.js +5 -0
  222. package/dist/utils/number.js.map +1 -0
  223. package/docs/bundled/extensions/agent.md +3 -3
  224. package/docs/bundled/extensions/cached-compaction.md +13 -4
  225. package/docs/bundled/extensions/deepwiki.md +3 -1
  226. package/docs/extensions.md +5 -5
  227. package/docs/packages.md +5 -3
  228. package/docs/sdk.md +1 -1
  229. package/docs/session-format.md +1 -1
  230. package/docs/settings.md +11 -0
  231. package/docs/skills.md +23 -0
  232. package/npm-shrinkwrap.json +2 -2
  233. package/package.json +1 -1
  234. package/schemas/settings.schema.json +36 -0
  235. package/dist/extensions/deepwiki/http.d.ts +0 -13
  236. package/dist/extensions/deepwiki/http.d.ts.map +0 -1
  237. package/dist/extensions/deepwiki/http.js +0 -88
  238. package/dist/extensions/deepwiki/http.js.map +0 -1
  239. package/dist/extensions/tasks/ui/task-view.d.ts +0 -8
  240. package/dist/extensions/tasks/ui/task-view.d.ts.map +0 -1
  241. package/dist/extensions/tasks/ui/task-view.js +0 -13
  242. package/dist/extensions/tasks/ui/task-view.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/execution.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAE1D,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAEX,WAAW,EACX,aAAa,EAGb,YAAY,EAGZ,eAAe,EAEf,MAAM,YAAY,CAAC;AAEpB,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,IAAI,IAAI,IAAI,CAAC;IACb,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3D,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAMhD;AAeD;;;;;GAKG;AACH,qBAAa,SAAS,CAAC,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA0B;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;IACrE,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,CAAuC;IACxD,OAAO,CAAC,mBAAmB,CAAwB;IACnD,OAAO,CAAC,KAAK,CAAC,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAU;gBAErB,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;IAuChF,IAAI,IAAI,IAAI,YAAY,CAEvB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,+EAA+E;IAC/E,OAAO,KAAK,cAAc,GAEzB;IAED,6EAA6E;IAC7E,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,uGAAuG;IACvG,aAAa,IAAI,IAAI;IAMrB,KAAK,IAAI,IAAI;IAoBb,OAAO,IAAI,IAAI;IAmBf,aAAa,IAAI,IAAI;IAOrB,cAAc,IAAI,IAAI;IAWtB,MAAM,IAAI,OAAO;IAUjB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,OAAO;IAgBf,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,MAAM;CAiDd"}
1
+ {"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/execution.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAU1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAEX,WAAW,EACX,aAAa,EAGb,YAAY,EAGZ,eAAe,EAEf,MAAM,YAAY,CAAC;AAEpB,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,IAAI,IAAI,IAAI,CAAC;IACb,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3D,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9C;AAeD;;;;;GAKG;AACH,qBAAa,SAAS,CAAC,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA0B;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;IACrE,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,CAAuC;IACxD,OAAO,CAAC,mBAAmB,CAAwB;IACnD,OAAO,CAAC,KAAK,CAAC,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAU;IACjC,iDAAiD;IACjD,OAAO,CAAC,OAAO,CAAC,CAA6B;gBAEjC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;IAuChF,IAAI,IAAI,IAAI,QAAQ,CAAC,YAAY,CAAC,CAEjC;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,+EAA+E;IAC/E,OAAO,KAAK,cAAc,GAEzB;IAED,6EAA6E;IAC7E,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,uGAAuG;IACvG,aAAa,IAAI,IAAI;IAMrB,KAAK,IAAI,IAAI;IAsBb,OAAO,IAAI,IAAI;IAoBf,aAAa,IAAI,IAAI;IAQrB,cAAc,IAAI,IAAI;IAWtB,MAAM,IAAI,OAAO;IAWjB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,MAAM;IAUd;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,OAAO;IAiBf,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,MAAM;CAoDd"}
@@ -1,13 +1,4 @@
1
- import { boundFacts, boundTaskText, boundText, resultText, TASK_ERROR_BYTES, TASK_PATH_BYTES } from "./output.js";
2
- import { changed, snapshotOf } from "./store.js";
3
- export function errorText(error) {
4
- try {
5
- return boundText(error instanceof Error ? error.message : String(error), TASK_ERROR_BYTES);
6
- }
7
- catch {
8
- return "Task execution failed (unprintable error)";
9
- }
10
- }
1
+ import { boundFacts, boundTaskText, boundText, errorText, resultText, TASK_ERROR_BYTES, TASK_PATH_BYTES, } from "./output.js";
11
2
  function prependText(text, result) {
12
3
  return {
13
4
  text: boundText(result?.text ? `${text}\n${result.text}` : text),
@@ -102,11 +93,13 @@ export class Execution {
102
93
  return;
103
94
  }
104
95
  this.started = true;
105
- this.task.status = "running";
106
- changed(this.record);
96
+ this.record.update((task) => {
97
+ task.status = "running";
98
+ });
107
99
  // The rejection handler is installed immediately, including for synchronous preflight throws.
108
100
  try {
109
- void Promise.resolve(this.run(this.control)).then((completion) => this.finish(completion), (error) => this.finish(undefined, error));
101
+ this.running = Promise.resolve(this.run(this.control));
102
+ void this.running.then((completion) => this.finish(completion), (error) => this.finish(undefined, error));
110
103
  }
111
104
  catch (error) {
112
105
  this.finish(undefined, error);
@@ -122,16 +115,18 @@ export class Execution {
122
115
  this.aborted)
123
116
  return;
124
117
  this.handedOff = true;
125
- this.task.mode = "background";
126
- changed(this.record);
118
+ this.record.update((task) => {
119
+ task.mode = "background";
120
+ });
127
121
  this.releaseParent();
128
- this.resolveCaller({ kind: "background", task: snapshotOf(this.record) });
122
+ this.resolveCaller({ kind: "background", task: this.record.snapshot() });
129
123
  this.host.emit();
130
124
  }
131
125
  requestDetach() {
132
126
  this.detachRequested = true;
133
- this.task.mode = "background";
134
- changed(this.record);
127
+ this.record.update((task) => {
128
+ task.mode = "background";
129
+ });
135
130
  if (this.accepted)
136
131
  this.releaseParent();
137
132
  }
@@ -149,8 +144,9 @@ export class Execution {
149
144
  cancel() {
150
145
  if (this.record.settled || this.aborted)
151
146
  return false;
152
- this.task.status = "stopping";
153
- changed(this.record);
147
+ this.record.update((task) => {
148
+ task.status = "stopping";
149
+ });
154
150
  this.controller.abort();
155
151
  if (!this.started)
156
152
  this.finish(undefined, new Error("Task cancelled before it started."));
@@ -171,17 +167,35 @@ export class Execution {
171
167
  this.accepted = true;
172
168
  if (this.detachRequested)
173
169
  this.releaseParent();
174
- // Let an already available final result win over a handoff.
175
- queueMicrotask(() => queueMicrotask(() => this.handoff()));
170
+ // An already available final result wins over a handoff, so decide only once the
171
+ // executor's own synchronous code has yielded.
172
+ queueMicrotask(() => this.handoffIfRunning());
176
173
  this.host.emit();
177
174
  }
175
+ /**
176
+ * Hand off unless `run` has already settled. A reaction on an already settled promise is
177
+ * queued at once, ahead of the pending-check below whatever the promise's chain depth, so
178
+ * the outcome never depends on how `start()` chains its own handlers.
179
+ */
180
+ handoffIfRunning() {
181
+ let settled = false;
182
+ const markSettled = () => {
183
+ settled = true;
184
+ };
185
+ this.running?.then(markSettled, markSettled);
186
+ void Promise.resolve().then(() => {
187
+ if (!settled)
188
+ this.handoff();
189
+ });
190
+ }
178
191
  publish(update) {
179
192
  if (this.record.settled || this.host.closed)
180
193
  return;
181
- this.task.result = resultText(update.result);
182
- if (update.display !== undefined)
183
- this.task.display = boundTaskText(update.display);
184
- changed(this.record);
194
+ this.record.update((task) => {
195
+ task.result = resultText(update.result);
196
+ if (update.display !== undefined)
197
+ task.display = boundTaskText(update.display);
198
+ });
185
199
  if (update.usage !== undefined)
186
200
  this.usage = structuredClone(update.usage);
187
201
  if (!this.detachRequested && !this.handedOff) {
@@ -206,52 +220,58 @@ export class Execution {
206
220
  if (Buffer.byteLength(path) > TASK_PATH_BYTES)
207
221
  throw new Error("Task output path is too large");
208
222
  this.record.cleanup = cleanup;
209
- this.task.outputPath = path;
210
- changed(this.record);
223
+ this.record.update((task) => {
224
+ task.outputPath = path;
225
+ });
211
226
  this.host.emit();
212
227
  }
213
228
  finish(completion, error) {
214
229
  const record = this.record;
215
- const task = this.task;
216
230
  if (record.settled)
217
231
  return;
218
232
  record.settled = true;
219
233
  this.modeListeners.clear();
220
234
  this.releaseParent();
221
- task.endedAt = Date.now();
222
235
  const status = completion
223
236
  ? (completion.status ?? (this.aborted ? "cancelled" : "completed"))
224
237
  : this.aborted
225
238
  ? "cancelled"
226
239
  : "failed";
227
- task.status = status;
228
- if (completion) {
229
- task.result = resultText(completion.result);
230
- if (completion.display !== undefined)
231
- task.display = boundTaskText(completion.display);
232
- if (completion.error !== undefined)
233
- task.error = boundText(completion.error, TASK_ERROR_BYTES);
234
- if (completion.facts)
235
- task.facts = mergeFacts(task.facts, completion.facts);
236
- }
237
- else {
238
- task.error = errorText(error);
239
- task.result = prependText(task.error, task.result);
240
- }
241
- changed(record);
240
+ record.update((task) => {
241
+ task.endedAt = Date.now();
242
+ task.status = status;
243
+ if (completion) {
244
+ task.result = resultText(completion.result);
245
+ if (completion.display !== undefined)
246
+ task.display = boundTaskText(completion.display);
247
+ if (completion.error !== undefined)
248
+ task.error = boundText(completion.error, TASK_ERROR_BYTES);
249
+ if (completion.facts)
250
+ task.facts = mergeFacts(task.facts, completion.facts);
251
+ }
252
+ else {
253
+ task.error = errorText(error);
254
+ task.result = prependText(task.error, task.result);
255
+ }
256
+ });
242
257
  let warning;
243
258
  try {
244
- this.host.settle(snapshotOf(record), completion?.usage ?? completion?.result.usage ?? this.usage);
259
+ this.host.settle(record.snapshot(), completion?.usage ?? completion?.result.usage ?? this.usage);
245
260
  }
246
261
  catch (accountingError) {
247
- warning = `Usage settlement failed: ${errorText(accountingError)}`;
248
- task.error = boundText([task.error, warning].filter(Boolean).join("\n"), 2 * TASK_ERROR_BYTES);
249
- task.result = prependText(warning, task.result);
250
- changed(record);
262
+ const notice = `Usage settlement failed: ${errorText(accountingError)}`;
263
+ warning = notice;
264
+ record.update((task) => {
265
+ task.error = boundText([task.error, notice].filter(Boolean).join("\n"), 2 * TASK_ERROR_BYTES);
266
+ task.result = prependText(notice, task.result);
267
+ });
251
268
  }
252
269
  this.usage = undefined;
253
270
  // Delivery becomes eligible only after settlement is persisted.
254
- record.delivery = this.handedOff ? "pending" : "delivered";
271
+ if (this.handedOff)
272
+ record.queueDelivery();
273
+ else
274
+ record.acknowledge();
255
275
  if (!this.handedOff) {
256
276
  if (!completion)
257
277
  this.rejectCaller(error);
@@ -260,7 +280,7 @@ export class Execution {
260
280
  const { usage: _usage, ...result } = completion.result;
261
281
  if (warning)
262
282
  result.content = [{ type: "text", text: warning }, ...result.content];
263
- this.resolveCaller({ kind: "result", result, status, error: task.error });
283
+ this.resolveCaller({ kind: "result", result, status, error: record.task.error });
264
284
  }
265
285
  }
266
286
  for (const waiter of [...record.waiters])
@@ -1 +1 @@
1
- {"version":3,"file":"execution.js","sourceRoot":"","sources":["../../../src/core/tasks/execution.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport { boundFacts, boundTaskText, boundText, resultText, TASK_ERROR_BYTES, TASK_PATH_BYTES } from \"./output.ts\";\nimport { changed, snapshotOf, type TaskRecord } from \"./store.ts\";\nimport type {\n\tTaskCompletion,\n\tTaskControl,\n\tTaskExecution,\n\tTaskFact,\n\tTaskMode,\n\tTaskSnapshot,\n\tTaskTerminalStatus,\n\tTaskText,\n\tTaskToolOutcome,\n\tTaskUpdate,\n} from \"./types.ts\";\n\n/** The runtime services one execution needs; it never reaches into the runtime itself. */\nexport interface ExecutionHost {\n\treadonly closed: boolean;\n\temit(): void;\n\t/** Synchronous persistence before terminal observers or notifications. */\n\tsettle(task: TaskSnapshot, usage: Usage | undefined): void;\n\t/** The execution settled and holds no slot, parent listener or caller any more. */\n\treleased(execution: Execution<unknown>): void;\n}\n\nexport function errorText(error: unknown): string {\n\ttry {\n\t\treturn boundText(error instanceof Error ? error.message : String(error), TASK_ERROR_BYTES);\n\t} catch {\n\t\treturn \"Task execution failed (unprintable error)\";\n\t}\n}\n\nfunction prependText(text: string, result: TaskText | undefined): TaskText {\n\treturn {\n\t\ttext: boundText(result?.text ? `${text}\\n${result.text}` : text),\n\t\ttruncated: result?.truncated ?? false,\n\t};\n}\n\n/** Terminal rows replace launch rows with the same label and append new ones. */\nfunction mergeFacts(base: readonly TaskFact[] = [], terminal: readonly TaskFact[]): TaskFact[] {\n\tconst labels = new Set(terminal.map(([label]) => label));\n\treturn boundFacts([...base.filter(([label]) => !labels.has(label)), ...terminal]);\n}\n\n/**\n * One live task: its caller, controller, parent link and executor callbacks.\n *\n * A caller may be handed off to the background whenever no executor preflight is in\n * progress: before `run` starts (queued) or after the executor calls `accept()`.\n */\nexport class Execution<T> {\n\treadonly record: TaskRecord;\n\treadonly concurrency?: { key: string; limit: number };\n\treadonly caller: Promise<TaskToolOutcome<T>>;\n\treadonly done: Promise<void>;\n\treadonly control: TaskControl<T>;\n\tprivate readonly host: ExecutionHost;\n\tprivate readonly run: TaskExecution<T>[\"run\"];\n\tprivate readonly controller = new AbortController();\n\tprivate readonly modeListeners = new Set<(mode: TaskMode) => void>();\n\tprivate resolveCaller!: (outcome: TaskToolOutcome<T>) => void;\n\tprivate rejectCaller!: (error: unknown) => void;\n\tprivate resolveDone!: () => void;\n\tprivate onUpdate?: (result: AgentToolResult<T>) => void;\n\tprivate releaseParentSignal: () => void = () => {};\n\tprivate usage?: Usage;\n\tprivate started = false;\n\tprivate accepted = false;\n\tprivate handedOff = false;\n\tprivate detachRequested: boolean;\n\n\tconstructor(host: ExecutionHost, record: TaskRecord, execution: TaskExecution<T>) {\n\t\tthis.host = host;\n\t\tthis.record = record;\n\t\tthis.run = execution.run;\n\t\tthis.concurrency = execution.concurrency;\n\t\tthis.detachRequested = execution.background ?? false;\n\t\tthis.onUpdate = execution.background ? undefined : execution.onUpdate;\n\t\tthis.caller = new Promise<TaskToolOutcome<T>>((resolve, reject) => {\n\t\t\tthis.resolveCaller = resolve;\n\t\t\tthis.rejectCaller = reject;\n\t\t});\n\t\tthis.done = new Promise<void>((resolve) => {\n\t\t\tthis.resolveDone = resolve;\n\t\t});\n\t\tconst parent = execution.signal;\n\t\tif (parent) {\n\t\t\tconst abort = () => {\n\t\t\t\tif (!this.detachRequested || !this.handoffAllowed) this.cancel();\n\t\t\t};\n\t\t\tparent.addEventListener(\"abort\", abort, { once: true });\n\t\t\tthis.releaseParentSignal = () => parent.removeEventListener(\"abort\", abort);\n\t\t}\n\t\tconst task = record.task;\n\t\tthis.control = {\n\t\t\tid: task.id,\n\t\t\tsignal: this.controller.signal,\n\t\t\tget mode() {\n\t\t\t\treturn task.mode;\n\t\t\t},\n\t\t\tonModeChange: (listener) => this.onModeChange(listener),\n\t\t\taccept: () => this.accept(),\n\t\t\tpublish: (update) => this.publish(update),\n\t\t\tattachOutput: (path, cleanup) => this.attachOutput(path, cleanup),\n\t\t\tcancel: () => {\n\t\t\t\tthis.cancel();\n\t\t\t},\n\t\t};\n\t}\n\n\tget task(): TaskSnapshot {\n\t\treturn this.record.task;\n\t}\n\n\tget aborted(): boolean {\n\t\treturn this.controller.signal.aborted;\n\t}\n\n\t/** Executor preflight never races a handoff; queued work has not begun any. */\n\tprivate get handoffAllowed(): boolean {\n\t\treturn !this.started || this.accepted;\n\t}\n\n\t/** Waiting for a concurrency slot: registered, but `run` has not started. */\n\tget queued(): boolean {\n\t\treturn !this.started && !this.record.settled;\n\t}\n\n\tget detachable(): boolean {\n\t\treturn !this.record.settled && !this.detachRequested && !this.aborted;\n\t}\n\n\t/** Stop forwarding to the launching tool call: parent cancellation and progress no longer reach it. */\n\treleaseParent(): void {\n\t\tthis.releaseParentSignal();\n\t\tthis.releaseParentSignal = () => {};\n\t\tthis.onUpdate = undefined;\n\t}\n\n\tstart(): void {\n\t\tif (this.started || this.record.settled) return;\n\t\tif (this.host.closed) {\n\t\t\tthis.cancel();\n\t\t\treturn;\n\t\t}\n\t\tthis.started = true;\n\t\tthis.task.status = \"running\";\n\t\tchanged(this.record);\n\t\t// The rejection handler is installed immediately, including for synchronous preflight throws.\n\t\ttry {\n\t\t\tvoid Promise.resolve(this.run(this.control)).then(\n\t\t\t\t(completion) => this.finish(completion),\n\t\t\t\t(error: unknown) => this.finish(undefined, error),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthis.finish(undefined, error);\n\t\t}\n\t}\n\n\thandoff(): void {\n\t\tif (\n\t\t\t!this.handoffAllowed ||\n\t\t\t!this.detachRequested ||\n\t\t\tthis.record.settled ||\n\t\t\tthis.handedOff ||\n\t\t\tthis.host.closed ||\n\t\t\t!this.record.visible ||\n\t\t\tthis.aborted\n\t\t)\n\t\t\treturn;\n\t\tthis.handedOff = true;\n\t\tthis.task.mode = \"background\";\n\t\tchanged(this.record);\n\t\tthis.releaseParent();\n\t\tthis.resolveCaller({ kind: \"background\", task: snapshotOf(this.record) });\n\t\tthis.host.emit();\n\t}\n\n\trequestDetach(): void {\n\t\tthis.detachRequested = true;\n\t\tthis.task.mode = \"background\";\n\t\tchanged(this.record);\n\t\tif (this.accepted) this.releaseParent();\n\t}\n\n\tcompleteDetach(): void {\n\t\tthis.handoff();\n\t\tfor (const listener of this.modeListeners) {\n\t\t\ttry {\n\t\t\t\tlistener(this.task.mode);\n\t\t\t} catch {\n\t\t\t\t/* Executors own their diagnostics. */\n\t\t\t}\n\t\t}\n\t}\n\n\tcancel(): boolean {\n\t\tif (this.record.settled || this.aborted) return false;\n\t\tthis.task.status = \"stopping\";\n\t\tchanged(this.record);\n\t\tthis.controller.abort();\n\t\tif (!this.started) this.finish(undefined, new Error(\"Task cancelled before it started.\"));\n\t\tthis.host.emit();\n\t\treturn true;\n\t}\n\n\tprivate onModeChange(listener: (mode: TaskMode) => void): () => void {\n\t\tif (this.record.settled || this.host.closed) return () => {};\n\t\tthis.modeListeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.modeListeners.delete(listener);\n\t\t};\n\t}\n\n\tprivate accept(): void {\n\t\tif (this.record.settled || this.accepted || this.host.closed || this.aborted) return;\n\t\tthis.accepted = true;\n\t\tif (this.detachRequested) this.releaseParent();\n\t\t// Let an already available final result win over a handoff.\n\t\tqueueMicrotask(() => queueMicrotask(() => this.handoff()));\n\t\tthis.host.emit();\n\t}\n\n\tprivate publish(update: TaskUpdate<T>): void {\n\t\tif (this.record.settled || this.host.closed) return;\n\t\tthis.task.result = resultText(update.result);\n\t\tif (update.display !== undefined) this.task.display = boundTaskText(update.display);\n\t\tchanged(this.record);\n\t\tif (update.usage !== undefined) this.usage = structuredClone(update.usage);\n\t\tif (!this.detachRequested && !this.handedOff) {\n\t\t\ttry {\n\t\t\t\tthis.onUpdate?.(update.result);\n\t\t\t} catch {\n\t\t\t\t/* UI observers cannot stop execution. */\n\t\t\t}\n\t\t}\n\t\tthis.host.emit();\n\t}\n\n\tprivate attachOutput(path: string, cleanup?: () => void | Promise<void>): void {\n\t\tif (this.record.settled) {\n\t\t\tif (cleanup) throw new Error(\"Task execution has settled\");\n\t\t\treturn;\n\t\t}\n\t\tif (this.record.cleanup) throw new Error(\"Managed output is already registered\");\n\t\t// Never truncate a real filesystem path into a different path.\n\t\tif (Buffer.byteLength(path) > TASK_PATH_BYTES) throw new Error(\"Task output path is too large\");\n\t\tthis.record.cleanup = cleanup;\n\t\tthis.task.outputPath = path;\n\t\tchanged(this.record);\n\t\tthis.host.emit();\n\t}\n\n\tprivate finish(completion: TaskCompletion<T> | undefined, error?: unknown): void {\n\t\tconst record = this.record;\n\t\tconst task = this.task;\n\t\tif (record.settled) return;\n\t\trecord.settled = true;\n\t\tthis.modeListeners.clear();\n\t\tthis.releaseParent();\n\t\ttask.endedAt = Date.now();\n\t\tconst status: TaskTerminalStatus = completion\n\t\t\t? (completion.status ?? (this.aborted ? \"cancelled\" : \"completed\"))\n\t\t\t: this.aborted\n\t\t\t\t? \"cancelled\"\n\t\t\t\t: \"failed\";\n\t\ttask.status = status;\n\t\tif (completion) {\n\t\t\ttask.result = resultText(completion.result);\n\t\t\tif (completion.display !== undefined) task.display = boundTaskText(completion.display);\n\t\t\tif (completion.error !== undefined) task.error = boundText(completion.error, TASK_ERROR_BYTES);\n\t\t\tif (completion.facts) task.facts = mergeFacts(task.facts, completion.facts);\n\t\t} else {\n\t\t\ttask.error = errorText(error);\n\t\t\ttask.result = prependText(task.error, task.result);\n\t\t}\n\t\tchanged(record);\n\t\tlet warning: string | undefined;\n\t\ttry {\n\t\t\tthis.host.settle(snapshotOf(record), completion?.usage ?? completion?.result.usage ?? this.usage);\n\t\t} catch (accountingError) {\n\t\t\twarning = `Usage settlement failed: ${errorText(accountingError)}`;\n\t\t\ttask.error = boundText([task.error, warning].filter(Boolean).join(\"\\n\"), 2 * TASK_ERROR_BYTES);\n\t\t\ttask.result = prependText(warning, task.result);\n\t\t\tchanged(record);\n\t\t}\n\t\tthis.usage = undefined;\n\t\t// Delivery becomes eligible only after settlement is persisted.\n\t\trecord.delivery = this.handedOff ? \"pending\" : \"delivered\";\n\t\tif (!this.handedOff) {\n\t\t\tif (!completion) this.rejectCaller(error);\n\t\t\telse {\n\t\t\t\t// The task ledger owns usage; a tool result never carries it a second time.\n\t\t\t\tconst { usage: _usage, ...result } = completion.result;\n\t\t\t\tif (warning) result.content = [{ type: \"text\", text: warning }, ...result.content];\n\t\t\t\tthis.resolveCaller({ kind: \"result\", result, status, error: task.error });\n\t\t\t}\n\t\t}\n\t\tfor (const waiter of [...record.waiters]) waiter();\n\t\tthis.resolveDone();\n\t\tthis.host.released(this as Execution<unknown>);\n\t}\n}\n"]}
1
+ {"version":3,"file":"execution.js","sourceRoot":"","sources":["../../../src/core/tasks/execution.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport {\n\tboundFacts,\n\tboundTaskText,\n\tboundText,\n\terrorText,\n\tresultText,\n\tTASK_ERROR_BYTES,\n\tTASK_PATH_BYTES,\n} from \"./output.ts\";\nimport type { TaskRecord } from \"./record.ts\";\nimport type {\n\tTaskCompletion,\n\tTaskControl,\n\tTaskExecution,\n\tTaskFact,\n\tTaskMode,\n\tTaskSnapshot,\n\tTaskTerminalStatus,\n\tTaskText,\n\tTaskToolOutcome,\n\tTaskUpdate,\n} from \"./types.ts\";\n\n/** The runtime services one execution needs; it never reaches into the runtime itself. */\nexport interface ExecutionHost {\n\treadonly closed: boolean;\n\temit(): void;\n\t/** Synchronous persistence before terminal observers or notifications. */\n\tsettle(task: TaskSnapshot, usage: Usage | undefined): void;\n\t/** The execution settled and holds no slot, parent listener or caller any more. */\n\treleased(execution: Execution<unknown>): void;\n}\n\nfunction prependText(text: string, result: TaskText | undefined): TaskText {\n\treturn {\n\t\ttext: boundText(result?.text ? `${text}\\n${result.text}` : text),\n\t\ttruncated: result?.truncated ?? false,\n\t};\n}\n\n/** Terminal rows replace launch rows with the same label and append new ones. */\nfunction mergeFacts(base: readonly TaskFact[] = [], terminal: readonly TaskFact[]): TaskFact[] {\n\tconst labels = new Set(terminal.map(([label]) => label));\n\treturn boundFacts([...base.filter(([label]) => !labels.has(label)), ...terminal]);\n}\n\n/**\n * One live task: its caller, controller, parent link and executor callbacks.\n *\n * A caller may be handed off to the background whenever no executor preflight is in\n * progress: before `run` starts (queued) or after the executor calls `accept()`.\n */\nexport class Execution<T> {\n\treadonly record: TaskRecord;\n\treadonly concurrency?: { key: string; limit: number };\n\treadonly caller: Promise<TaskToolOutcome<T>>;\n\treadonly done: Promise<void>;\n\treadonly control: TaskControl<T>;\n\tprivate readonly host: ExecutionHost;\n\tprivate readonly run: TaskExecution<T>[\"run\"];\n\tprivate readonly controller = new AbortController();\n\tprivate readonly modeListeners = new Set<(mode: TaskMode) => void>();\n\tprivate resolveCaller!: (outcome: TaskToolOutcome<T>) => void;\n\tprivate rejectCaller!: (error: unknown) => void;\n\tprivate resolveDone!: () => void;\n\tprivate onUpdate?: (result: AgentToolResult<T>) => void;\n\tprivate releaseParentSignal: () => void = () => {};\n\tprivate usage?: Usage;\n\tprivate started = false;\n\tprivate accepted = false;\n\tprivate handedOff = false;\n\tprivate detachRequested: boolean;\n\t/** The executor's `run` promise once started. */\n\tprivate running?: Promise<TaskCompletion<T>>;\n\n\tconstructor(host: ExecutionHost, record: TaskRecord, execution: TaskExecution<T>) {\n\t\tthis.host = host;\n\t\tthis.record = record;\n\t\tthis.run = execution.run;\n\t\tthis.concurrency = execution.concurrency;\n\t\tthis.detachRequested = execution.background ?? false;\n\t\tthis.onUpdate = execution.background ? undefined : execution.onUpdate;\n\t\tthis.caller = new Promise<TaskToolOutcome<T>>((resolve, reject) => {\n\t\t\tthis.resolveCaller = resolve;\n\t\t\tthis.rejectCaller = reject;\n\t\t});\n\t\tthis.done = new Promise<void>((resolve) => {\n\t\t\tthis.resolveDone = resolve;\n\t\t});\n\t\tconst parent = execution.signal;\n\t\tif (parent) {\n\t\t\tconst abort = () => {\n\t\t\t\tif (!this.detachRequested || !this.handoffAllowed) this.cancel();\n\t\t\t};\n\t\t\tparent.addEventListener(\"abort\", abort, { once: true });\n\t\t\tthis.releaseParentSignal = () => parent.removeEventListener(\"abort\", abort);\n\t\t}\n\t\tconst task = record.task;\n\t\tthis.control = {\n\t\t\tid: task.id,\n\t\t\tsignal: this.controller.signal,\n\t\t\tget mode() {\n\t\t\t\treturn task.mode;\n\t\t\t},\n\t\t\tonModeChange: (listener) => this.onModeChange(listener),\n\t\t\taccept: () => this.accept(),\n\t\t\tpublish: (update) => this.publish(update),\n\t\t\tattachOutput: (path, cleanup) => this.attachOutput(path, cleanup),\n\t\t\tcancel: () => {\n\t\t\t\tthis.cancel();\n\t\t\t},\n\t\t};\n\t}\n\n\tget task(): Readonly<TaskSnapshot> {\n\t\treturn this.record.task;\n\t}\n\n\tget aborted(): boolean {\n\t\treturn this.controller.signal.aborted;\n\t}\n\n\t/** Executor preflight never races a handoff; queued work has not begun any. */\n\tprivate get handoffAllowed(): boolean {\n\t\treturn !this.started || this.accepted;\n\t}\n\n\t/** Waiting for a concurrency slot: registered, but `run` has not started. */\n\tget queued(): boolean {\n\t\treturn !this.started && !this.record.settled;\n\t}\n\n\tget detachable(): boolean {\n\t\treturn !this.record.settled && !this.detachRequested && !this.aborted;\n\t}\n\n\t/** Stop forwarding to the launching tool call: parent cancellation and progress no longer reach it. */\n\treleaseParent(): void {\n\t\tthis.releaseParentSignal();\n\t\tthis.releaseParentSignal = () => {};\n\t\tthis.onUpdate = undefined;\n\t}\n\n\tstart(): void {\n\t\tif (this.started || this.record.settled) return;\n\t\tif (this.host.closed) {\n\t\t\tthis.cancel();\n\t\t\treturn;\n\t\t}\n\t\tthis.started = true;\n\t\tthis.record.update((task) => {\n\t\t\ttask.status = \"running\";\n\t\t});\n\t\t// The rejection handler is installed immediately, including for synchronous preflight throws.\n\t\ttry {\n\t\t\tthis.running = Promise.resolve(this.run(this.control));\n\t\t\tvoid this.running.then(\n\t\t\t\t(completion) => this.finish(completion),\n\t\t\t\t(error: unknown) => this.finish(undefined, error),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthis.finish(undefined, error);\n\t\t}\n\t}\n\n\thandoff(): void {\n\t\tif (\n\t\t\t!this.handoffAllowed ||\n\t\t\t!this.detachRequested ||\n\t\t\tthis.record.settled ||\n\t\t\tthis.handedOff ||\n\t\t\tthis.host.closed ||\n\t\t\t!this.record.visible ||\n\t\t\tthis.aborted\n\t\t)\n\t\t\treturn;\n\t\tthis.handedOff = true;\n\t\tthis.record.update((task) => {\n\t\t\ttask.mode = \"background\";\n\t\t});\n\t\tthis.releaseParent();\n\t\tthis.resolveCaller({ kind: \"background\", task: this.record.snapshot() });\n\t\tthis.host.emit();\n\t}\n\n\trequestDetach(): void {\n\t\tthis.detachRequested = true;\n\t\tthis.record.update((task) => {\n\t\t\ttask.mode = \"background\";\n\t\t});\n\t\tif (this.accepted) this.releaseParent();\n\t}\n\n\tcompleteDetach(): void {\n\t\tthis.handoff();\n\t\tfor (const listener of this.modeListeners) {\n\t\t\ttry {\n\t\t\t\tlistener(this.task.mode);\n\t\t\t} catch {\n\t\t\t\t/* Executors own their diagnostics. */\n\t\t\t}\n\t\t}\n\t}\n\n\tcancel(): boolean {\n\t\tif (this.record.settled || this.aborted) return false;\n\t\tthis.record.update((task) => {\n\t\t\ttask.status = \"stopping\";\n\t\t});\n\t\tthis.controller.abort();\n\t\tif (!this.started) this.finish(undefined, new Error(\"Task cancelled before it started.\"));\n\t\tthis.host.emit();\n\t\treturn true;\n\t}\n\n\tprivate onModeChange(listener: (mode: TaskMode) => void): () => void {\n\t\tif (this.record.settled || this.host.closed) return () => {};\n\t\tthis.modeListeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.modeListeners.delete(listener);\n\t\t};\n\t}\n\n\tprivate accept(): void {\n\t\tif (this.record.settled || this.accepted || this.host.closed || this.aborted) return;\n\t\tthis.accepted = true;\n\t\tif (this.detachRequested) this.releaseParent();\n\t\t// An already available final result wins over a handoff, so decide only once the\n\t\t// executor's own synchronous code has yielded.\n\t\tqueueMicrotask(() => this.handoffIfRunning());\n\t\tthis.host.emit();\n\t}\n\n\t/**\n\t * Hand off unless `run` has already settled. A reaction on an already settled promise is\n\t * queued at once, ahead of the pending-check below whatever the promise's chain depth, so\n\t * the outcome never depends on how `start()` chains its own handlers.\n\t */\n\tprivate handoffIfRunning(): void {\n\t\tlet settled = false;\n\t\tconst markSettled = () => {\n\t\t\tsettled = true;\n\t\t};\n\t\tthis.running?.then(markSettled, markSettled);\n\t\tvoid Promise.resolve().then(() => {\n\t\t\tif (!settled) this.handoff();\n\t\t});\n\t}\n\n\tprivate publish(update: TaskUpdate<T>): void {\n\t\tif (this.record.settled || this.host.closed) return;\n\t\tthis.record.update((task) => {\n\t\t\ttask.result = resultText(update.result);\n\t\t\tif (update.display !== undefined) task.display = boundTaskText(update.display);\n\t\t});\n\t\tif (update.usage !== undefined) this.usage = structuredClone(update.usage);\n\t\tif (!this.detachRequested && !this.handedOff) {\n\t\t\ttry {\n\t\t\t\tthis.onUpdate?.(update.result);\n\t\t\t} catch {\n\t\t\t\t/* UI observers cannot stop execution. */\n\t\t\t}\n\t\t}\n\t\tthis.host.emit();\n\t}\n\n\tprivate attachOutput(path: string, cleanup?: () => void | Promise<void>): void {\n\t\tif (this.record.settled) {\n\t\t\tif (cleanup) throw new Error(\"Task execution has settled\");\n\t\t\treturn;\n\t\t}\n\t\tif (this.record.cleanup) throw new Error(\"Managed output is already registered\");\n\t\t// Never truncate a real filesystem path into a different path.\n\t\tif (Buffer.byteLength(path) > TASK_PATH_BYTES) throw new Error(\"Task output path is too large\");\n\t\tthis.record.cleanup = cleanup;\n\t\tthis.record.update((task) => {\n\t\t\ttask.outputPath = path;\n\t\t});\n\t\tthis.host.emit();\n\t}\n\n\tprivate finish(completion: TaskCompletion<T> | undefined, error?: unknown): void {\n\t\tconst record = this.record;\n\t\tif (record.settled) return;\n\t\trecord.settled = true;\n\t\tthis.modeListeners.clear();\n\t\tthis.releaseParent();\n\t\tconst status: TaskTerminalStatus = completion\n\t\t\t? (completion.status ?? (this.aborted ? \"cancelled\" : \"completed\"))\n\t\t\t: this.aborted\n\t\t\t\t? \"cancelled\"\n\t\t\t\t: \"failed\";\n\t\trecord.update((task) => {\n\t\t\ttask.endedAt = Date.now();\n\t\t\ttask.status = status;\n\t\t\tif (completion) {\n\t\t\t\ttask.result = resultText(completion.result);\n\t\t\t\tif (completion.display !== undefined) task.display = boundTaskText(completion.display);\n\t\t\t\tif (completion.error !== undefined) task.error = boundText(completion.error, TASK_ERROR_BYTES);\n\t\t\t\tif (completion.facts) task.facts = mergeFacts(task.facts, completion.facts);\n\t\t\t} else {\n\t\t\t\ttask.error = errorText(error);\n\t\t\t\ttask.result = prependText(task.error, task.result);\n\t\t\t}\n\t\t});\n\t\tlet warning: string | undefined;\n\t\ttry {\n\t\t\tthis.host.settle(record.snapshot(), completion?.usage ?? completion?.result.usage ?? this.usage);\n\t\t} catch (accountingError) {\n\t\t\tconst notice = `Usage settlement failed: ${errorText(accountingError)}`;\n\t\t\twarning = notice;\n\t\t\trecord.update((task) => {\n\t\t\t\ttask.error = boundText([task.error, notice].filter(Boolean).join(\"\\n\"), 2 * TASK_ERROR_BYTES);\n\t\t\t\ttask.result = prependText(notice, task.result);\n\t\t\t});\n\t\t}\n\t\tthis.usage = undefined;\n\t\t// Delivery becomes eligible only after settlement is persisted.\n\t\tif (this.handedOff) record.queueDelivery();\n\t\telse record.acknowledge();\n\t\tif (!this.handedOff) {\n\t\t\tif (!completion) this.rejectCaller(error);\n\t\t\telse {\n\t\t\t\t// The task ledger owns usage; a tool result never carries it a second time.\n\t\t\t\tconst { usage: _usage, ...result } = completion.result;\n\t\t\t\tif (warning) result.content = [{ type: \"text\", text: warning }, ...result.content];\n\t\t\t\tthis.resolveCaller({ kind: \"result\", result, status, error: record.task.error });\n\t\t\t}\n\t\t}\n\t\tfor (const waiter of [...record.waiters]) waiter();\n\t\tthis.resolveDone();\n\t\tthis.host.released(this as Execution<unknown>);\n\t}\n}\n"]}
@@ -1,5 +1,3 @@
1
- /** Compact elapsed time shared by tool responses and interactive views. */
2
- export declare function formatDuration(ms: number): string;
3
1
  export declare function runtimeLabel(task: {
4
2
  startedAt: number;
5
3
  endedAt?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/format.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAYjD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,SAAa,GAAG,MAAM,CAEpG"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/format.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,SAAa,GAAG,MAAM,CAEpG"}
@@ -1,19 +1,4 @@
1
- /** Compact elapsed time shared by tool responses and interactive views. */
2
- export function formatDuration(ms) {
3
- if (ms < 500)
4
- return "<1s";
5
- const seconds = Math.round(ms / 1000);
6
- if (seconds < 60)
7
- return `${seconds}s`;
8
- const minutes = Math.floor(seconds / 60);
9
- if (minutes < 60) {
10
- const remainder = seconds % 60;
11
- return remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;
12
- }
13
- const hours = Math.floor(minutes / 60);
14
- const remainder = minutes % 60;
15
- return remainder === 0 ? `${hours}h` : `${hours}h ${remainder}m`;
16
- }
1
+ import { formatDuration } from "../../utils/duration.js";
17
2
  export function runtimeLabel(task, now = Date.now()) {
18
3
  return formatDuration((task.endedAt ?? now) - task.startedAt);
19
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/core/tasks/format.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,EAAU;IACxC,IAAI,EAAE,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,GAAG,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,OAAO,GAAG,EAAE,CAAC;QAC/B,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,SAAS,GAAG,CAAC;IACtE,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,OAAO,GAAG,EAAE,CAAC;IAC/B,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,SAAS,GAAG,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAA6C,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC3F,OAAO,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["/** Compact elapsed time shared by tool responses and interactive views. */\nexport function formatDuration(ms: number): string {\n\tif (ms < 500) return \"<1s\";\n\tconst seconds = Math.round(ms / 1000);\n\tif (seconds < 60) return `${seconds}s`;\n\tconst minutes = Math.floor(seconds / 60);\n\tif (minutes < 60) {\n\t\tconst remainder = seconds % 60;\n\t\treturn remainder === 0 ? `${minutes}m` : `${minutes}m ${remainder}s`;\n\t}\n\tconst hours = Math.floor(minutes / 60);\n\tconst remainder = minutes % 60;\n\treturn remainder === 0 ? `${hours}h` : `${hours}h ${remainder}m`;\n}\n\nexport function runtimeLabel(task: { startedAt: number; endedAt?: number }, now = Date.now()): string {\n\treturn formatDuration((task.endedAt ?? now) - task.startedAt);\n}\n"]}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/core/tasks/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,MAAM,UAAU,YAAY,CAAC,IAA6C,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC3F,OAAO,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["import { formatDuration } from \"../../utils/duration.ts\";\n\nexport function runtimeLabel(task: { startedAt: number; endedAt?: number }, now = Date.now()): string {\n\treturn formatDuration((task.endedAt ?? now) - task.startedAt);\n}\n"]}
@@ -1,5 +1,16 @@
1
- /** Shared observation-window limits; execution timeouts are configured separately by each executor. */
1
+ /**
2
+ * Shared observation-window limits, the one definition used by the runtime and the tasks tool.
3
+ * Execution timeouts are configured separately by each executor.
4
+ */
2
5
  export declare const TASKS_WAIT_DEFAULT_MS = 20000;
3
6
  export declare const TASKS_WAIT_MIN_MS = 1000;
4
7
  export declare const TASKS_WAIT_MAX_MS: number;
8
+ /** Floor for a model-requested read slice; the default and ceiling are TASK_READ_BYTES and TASK_RESULT_BYTES. */
9
+ export declare const TASKS_READ_MIN_BYTES = 256;
10
+ /** The wait window the runtime honours: any finite value up to the ceiling, including 0. */
11
+ export declare function boundWaitMs(waitMs: number | undefined): number;
12
+ /** The wait window a tool call runs, which the pending-call renderer also shows. */
13
+ export declare function clampWaitMs(waitMs: number | undefined): number;
14
+ /** The read size a tool call runs. */
15
+ export declare function clampReadBytes(bytes: number | undefined): number;
5
16
  //# sourceMappingURL=limits.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/limits.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAC5C,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,iBAAiB,QAAc,CAAC"}
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/limits.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAC5C,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAC7C,iHAAiH;AACjH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE9D;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE9D;AAED,sCAAsC;AACtC,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEhE"}
@@ -1,5 +1,24 @@
1
- /** Shared observation-window limits; execution timeouts are configured separately by each executor. */
1
+ import { finiteLimit } from "../../utils/number.js";
2
+ import { boundReadBytes } from "./output.js";
3
+ /**
4
+ * Shared observation-window limits, the one definition used by the runtime and the tasks tool.
5
+ * Execution timeouts are configured separately by each executor.
6
+ */
2
7
  export const TASKS_WAIT_DEFAULT_MS = 20_000;
3
8
  export const TASKS_WAIT_MIN_MS = 1_000;
4
9
  export const TASKS_WAIT_MAX_MS = 10 * 60_000;
10
+ /** Floor for a model-requested read slice; the default and ceiling are TASK_READ_BYTES and TASK_RESULT_BYTES. */
11
+ export const TASKS_READ_MIN_BYTES = 256;
12
+ /** The wait window the runtime honours: any finite value up to the ceiling, including 0. */
13
+ export function boundWaitMs(waitMs) {
14
+ return finiteLimit(waitMs, TASKS_WAIT_DEFAULT_MS, TASKS_WAIT_MAX_MS);
15
+ }
16
+ /** The wait window a tool call runs, which the pending-call renderer also shows. */
17
+ export function clampWaitMs(waitMs) {
18
+ return Math.max(TASKS_WAIT_MIN_MS, boundWaitMs(waitMs));
19
+ }
20
+ /** The read size a tool call runs. */
21
+ export function clampReadBytes(bytes) {
22
+ return Math.max(TASKS_READ_MIN_BYTES, boundReadBytes(bytes));
23
+ }
5
24
  //# sourceMappingURL=limits.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../../src/core/tasks/limits.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,MAAM,CAAC","sourcesContent":["/** Shared observation-window limits; execution timeouts are configured separately by each executor. */\nexport const TASKS_WAIT_DEFAULT_MS = 20_000;\nexport const TASKS_WAIT_MIN_MS = 1_000;\nexport const TASKS_WAIT_MAX_MS = 10 * 60_000;\n"]}
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../../../src/core/tasks/limits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,MAAM,CAAC;AAC7C,iHAAiH;AACjH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC,4FAA4F;AAC5F,MAAM,UAAU,WAAW,CAAC,MAA0B;IACrD,OAAO,WAAW,CAAC,MAAM,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,CAAC;AACtE,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,WAAW,CAAC,MAA0B;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,cAAc,CAAC,KAAyB;IACvD,OAAO,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["import { finiteLimit } from \"../../utils/number.ts\";\nimport { boundReadBytes } from \"./output.ts\";\n\n/**\n * Shared observation-window limits, the one definition used by the runtime and the tasks tool.\n * Execution timeouts are configured separately by each executor.\n */\nexport const TASKS_WAIT_DEFAULT_MS = 20_000;\nexport const TASKS_WAIT_MIN_MS = 1_000;\nexport const TASKS_WAIT_MAX_MS = 10 * 60_000;\n/** Floor for a model-requested read slice; the default and ceiling are TASK_READ_BYTES and TASK_RESULT_BYTES. */\nexport const TASKS_READ_MIN_BYTES = 256;\n\n/** The wait window the runtime honours: any finite value up to the ceiling, including 0. */\nexport function boundWaitMs(waitMs: number | undefined): number {\n\treturn finiteLimit(waitMs, TASKS_WAIT_DEFAULT_MS, TASKS_WAIT_MAX_MS);\n}\n\n/** The wait window a tool call runs, which the pending-call renderer also shows. */\nexport function clampWaitMs(waitMs: number | undefined): number {\n\treturn Math.max(TASKS_WAIT_MIN_MS, boundWaitMs(waitMs));\n}\n\n/** The read size a tool call runs. */\nexport function clampReadBytes(bytes: number | undefined): number {\n\treturn Math.max(TASKS_READ_MIN_BYTES, boundReadBytes(bytes));\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
2
- import type { TaskFact, TaskInput, TaskText } from "./types.ts";
2
+ import type { TaskFact, TaskInput, TaskReadOptions, TaskText } from "./types.ts";
3
3
  export declare const TASK_RESULT_BYTES: number;
4
4
  export declare const TASK_DETAILS_BYTES: number;
5
5
  export declare const TASK_READ_BYTES: number;
@@ -11,7 +11,9 @@ export declare const TASK_FACTS = 16;
11
11
  export declare const TASK_FACT_BYTES = 1024;
12
12
  export declare const TASK_ERROR_BYTES = 4096;
13
13
  export declare const TASK_PATH_BYTES = 8192;
14
- export declare function finiteLimit(value: number | undefined, fallback: number, ceiling: number): number;
14
+ /** A bounded, printable message for any thrown value. */
15
+ export declare function errorText(error: unknown, fallback?: string): string;
16
+ export declare function boundReadBytes(bytes: number | undefined): number;
15
17
  export declare function boundText(text: string, bytes?: number): string;
16
18
  export declare function boundTaskText(text: string, bytes?: number): TaskText;
17
19
  export declare function boundInput(input: TaskInput): TaskInput;
@@ -30,14 +32,6 @@ export interface OutputSlice {
30
32
  fromByte: number;
31
33
  }
32
34
  /** Positioned, bounded reads only. The executor owns the path and its cleanup. */
33
- export declare function readOutputSlice(path: string, options?: {
34
- mode?: "head" | "tail";
35
- bytes?: number;
36
- sinceBytes?: number;
37
- }): Promise<OutputSlice>;
38
- export declare function sliceText(text: string, options?: {
39
- mode?: "head" | "tail";
40
- bytes?: number;
41
- sinceBytes?: number;
42
- }): OutputSlice;
35
+ export declare function readOutputSlice(path: string, options?: TaskReadOptions): Promise<OutputSlice>;
36
+ export declare function sliceText(text: string, options?: TaskReadOptions): OutputSlice;
43
37
  //# sourceMappingURL=output.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/output.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEhE,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,eAAe,QAAW,CAAC;AACxC,eAAO,MAAM,gBAAgB,QAAY,CAAC;AAC1C,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhG;AAmBD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAoB,GAAG,MAAM,CAMzE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAoB,GAAG,QAAQ,CAG/E;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAQtD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAIjE;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAI3F;AAED,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,QAAQ,CAgBrE;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,kFAAkF;AAClF,wBAAsB,eAAe,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3E,OAAO,CAAC,WAAW,CAAC,CA2BtB;AAED,wBAAgB,SAAS,CACxB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3E,WAAW,CAkBb"}
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/output.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEjF,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,eAAe,QAAW,CAAC;AACxC,eAAO,MAAM,gBAAgB,QAAY,CAAC;AAC1C,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,eAAO,MAAM,eAAe,OAAO,CAAC;AAEpC,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAA8C,GAAG,MAAM,CAMxG;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEhE;AAmBD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAoB,GAAG,MAAM,CAMzE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAoB,GAAG,QAAQ,CAG/E;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAQtD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAIjE;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAI3F;AAED,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,QAAQ,CAgBrE;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAuBD,kFAAkF;AAClF,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAavG;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,WAAW,CAKlF"}
@@ -1,4 +1,5 @@
1
1
  import { open } from "node:fs/promises";
2
+ import { finiteLimit } from "../../utils/number.js";
2
3
  export const TASK_RESULT_BYTES = 48 * 1024;
3
4
  export const TASK_DETAILS_BYTES = 120 * 1024;
4
5
  export const TASK_READ_BYTES = 8 * 1024;
@@ -10,8 +11,17 @@ export const TASK_FACTS = 16;
10
11
  export const TASK_FACT_BYTES = 1024;
11
12
  export const TASK_ERROR_BYTES = 4096;
12
13
  export const TASK_PATH_BYTES = 8192;
13
- export function finiteLimit(value, fallback, ceiling) {
14
- return value === undefined || !Number.isFinite(value) ? fallback : Math.max(0, Math.min(ceiling, Math.floor(value)));
14
+ /** A bounded, printable message for any thrown value. */
15
+ export function errorText(error, fallback = "Task execution failed (unprintable error)") {
16
+ try {
17
+ return boundText(error instanceof Error ? error.message : String(error), TASK_ERROR_BYTES);
18
+ }
19
+ catch {
20
+ return fallback;
21
+ }
22
+ }
23
+ export function boundReadBytes(bytes) {
24
+ return finiteLimit(bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);
15
25
  }
16
26
  /** Both ends are codepoint aligned, including a head read ending inside a character. */
17
27
  function alignedSlice(buffer, start, end) {
@@ -84,30 +94,35 @@ export function resultText(result) {
84
94
  }
85
95
  return { text: boundText(parts.join("\n")), truncated };
86
96
  }
97
+ /**
98
+ * The byte window a read covers in an output of `size` bytes. `floor` is the first byte the
99
+ * caller has not seen yet; anything before it never counts as truncated.
100
+ */
101
+ function readWindow(size, options) {
102
+ const bytes = boundReadBytes(options.bytes);
103
+ const since = finiteLimit(options.sinceBytes, 0, Number.MAX_SAFE_INTEGER);
104
+ const floor = since > size ? 0 : since;
105
+ const start = options.sinceBytes !== undefined
106
+ ? Math.max(floor, size - bytes)
107
+ : options.mode === "head"
108
+ ? 0
109
+ : Math.max(0, size - bytes);
110
+ return { start, length: Math.min(bytes, size - start), floor };
111
+ }
112
+ function outputSlice(size, floor, slice, fromByte) {
113
+ return { text: slice.toString("utf8"), totalBytes: size, truncated: slice.length < size - floor, fromByte };
114
+ }
87
115
  /** Positioned, bounded reads only. The executor owns the path and its cleanup. */
88
116
  export async function readOutputSlice(path, options = {}) {
89
- const bytes = finiteLimit(options.bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);
90
117
  const file = await open(path, "r");
91
118
  try {
92
119
  const { size } = await file.stat();
93
- const since = finiteLimit(options.sinceBytes, 0, Number.MAX_SAFE_INTEGER);
94
- const floor = since > size ? 0 : since;
95
- const start = options.sinceBytes !== undefined
96
- ? Math.max(floor, size - bytes)
97
- : options.mode === "head"
98
- ? 0
99
- : Math.max(0, size - bytes);
100
- const length = Math.min(bytes, size - start);
120
+ const { start, length, floor } = readWindow(size, options);
101
121
  // One extra byte lets alignment distinguish a complete last codepoint.
102
122
  const buffer = Buffer.alloc(Math.min(length + 1, size - start));
103
123
  const { bytesRead } = await file.read(buffer, 0, buffer.length, start);
104
124
  const slice = alignedSlice(buffer.subarray(0, bytesRead), 0, Math.min(length, bytesRead));
105
- return {
106
- text: slice.toString("utf8"),
107
- totalBytes: size,
108
- truncated: options.sinceBytes !== undefined ? start > floor || slice.length < length : slice.length < size,
109
- fromByte: start + slice.byteOffset - buffer.byteOffset,
110
- };
125
+ return outputSlice(size, floor, slice, start + slice.byteOffset - buffer.byteOffset);
111
126
  }
112
127
  finally {
113
128
  await file.close();
@@ -115,20 +130,8 @@ export async function readOutputSlice(path, options = {}) {
115
130
  }
116
131
  export function sliceText(text, options = {}) {
117
132
  const buffer = Buffer.from(text);
118
- const bytes = finiteLimit(options.bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);
119
- const since = finiteLimit(options.sinceBytes, 0, Number.MAX_SAFE_INTEGER);
120
- const floor = since > buffer.length ? 0 : since;
121
- const start = options.sinceBytes !== undefined
122
- ? Math.max(floor, buffer.length - bytes)
123
- : options.mode === "head"
124
- ? 0
125
- : Math.max(0, buffer.length - bytes);
126
- const slice = alignedSlice(buffer, start, Math.min(buffer.length, start + bytes));
127
- return {
128
- text: slice.toString("utf8"),
129
- totalBytes: buffer.length,
130
- truncated: slice.length < buffer.length - floor,
131
- fromByte: slice.byteOffset - buffer.byteOffset,
132
- };
133
+ const { start, length, floor } = readWindow(buffer.length, options);
134
+ const slice = alignedSlice(buffer, start, start + length);
135
+ return outputSlice(buffer.length, floor, slice, slice.byteOffset - buffer.byteOffset);
133
136
  }
134
137
  //# sourceMappingURL=output.js.map