@astralyn/pi 0.99.0 → 1.0.0

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 (512) hide show
  1. package/CHANGELOG.md +39 -3
  2. package/dist/bundle/chunks/anthropic-messages-CG2BSDQS.js +6 -0
  3. package/dist/bundle/chunks/anthropic.js +2 -2
  4. package/dist/bundle/chunks/{azure-openai-responses-RPBERDXD.js → azure-openai-responses-PBA4QKCM.js} +1 -1
  5. package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
  6. package/dist/bundle/chunks/{chunk-ABVRAYXT.js → chunk-6UFFVA7M.js} +2 -2
  7. package/dist/bundle/chunks/chunk-GIG5IHES.js +2 -0
  8. package/dist/bundle/chunks/{chunk-VW2P3X6P.js → chunk-HESRDUKO.js} +414 -666
  9. package/dist/bundle/chunks/{chunk-A576H74Y.js → chunk-PFZKRUMO.js} +1 -1
  10. package/dist/bundle/chunks/chunk-SGLYRVQL.js +2 -0
  11. package/dist/bundle/chunks/chunk-TRHTWM3C.js +2 -0
  12. package/dist/bundle/chunks/{chunk-DEWXBB6W.js → chunk-V66VGGOM.js} +1 -1
  13. package/dist/bundle/chunks/chunk-Z2RKSI3O.js +2 -0
  14. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-ZYSAFXXL.js → cloudflare-workers-ai-system-one-YB7XPPP4.js} +1 -1
  15. package/dist/bundle/chunks/codemode-worker.js +67 -8
  16. package/dist/bundle/chunks/github-copilot.js +1 -1
  17. package/dist/bundle/chunks/{google-generative-ai-SDNQVVXA.js → google-generative-ai-V5ZM5MCL.js} +1 -1
  18. package/dist/bundle/chunks/{google-vertex-LZXOLBIO.js → google-vertex-22THOFP5.js} +1 -1
  19. package/dist/bundle/chunks/{llama-cpp-classify-7IYGGPND.js → llama-cpp-classify-R7DQLTQN.js} +1 -1
  20. package/dist/bundle/chunks/{mistral-conversations-VYKPSSAM.js → mistral-conversations-WHSCJJWP.js} +1 -1
  21. package/dist/bundle/chunks/openai-chatgpt.js +1 -1
  22. package/dist/bundle/chunks/{openai-codex-responses-HZ4VUDXD.js → openai-codex-responses-N7GDPBPP.js} +1 -1
  23. package/dist/bundle/chunks/openai-codex.js +1 -1
  24. package/dist/bundle/chunks/{openai-completions-SKDGF6OE.js → openai-completions-RGGQK5UW.js} +1 -1
  25. package/dist/bundle/chunks/{openai-responses-FPML4SSG.js → openai-responses-3ZLD5JYI.js} +1 -1
  26. package/dist/bundle/chunks/{openrouter-images-5524IQHX.js → openrouter-images-YP3YVB54.js} +1 -1
  27. package/dist/bundle/chunks/openrouter.js +1 -1
  28. package/dist/bundle/chunks/radius.js +1 -1
  29. package/dist/bundle/chunks/{typesafe-system-one-Z2CDLKEY.js → typesafe-system-one-RREJAKWB.js} +1 -1
  30. package/dist/bundle/chunks/virtual-modules-4RQ2L6W4.js +2 -0
  31. package/dist/bundle/cli.js +1 -1
  32. package/dist/bundle/index.js +1 -1
  33. package/dist/bundle/rpc-entry.js +1 -1
  34. package/dist/cli/args.js +1 -1
  35. package/dist/cli/args.js.map +1 -1
  36. package/dist/config.d.ts +5 -8
  37. package/dist/config.d.ts.map +1 -1
  38. package/dist/config.js +16 -13
  39. package/dist/config.js.map +1 -1
  40. package/dist/core/agent-session.d.ts +21 -1
  41. package/dist/core/agent-session.d.ts.map +1 -1
  42. package/dist/core/agent-session.js +64 -11
  43. package/dist/core/agent-session.js.map +1 -1
  44. package/dist/core/extensions/index.d.ts +1 -1
  45. package/dist/core/extensions/index.d.ts.map +1 -1
  46. package/dist/core/extensions/index.js.map +1 -1
  47. package/dist/core/extensions/loader.d.ts.map +1 -1
  48. package/dist/core/extensions/loader.js +13 -1
  49. package/dist/core/extensions/loader.js.map +1 -1
  50. package/dist/core/extensions/types.d.ts +6 -1
  51. package/dist/core/extensions/types.d.ts.map +1 -1
  52. package/dist/core/extensions/types.js.map +1 -1
  53. package/dist/core/keybindings.d.ts +51 -11
  54. package/dist/core/keybindings.d.ts.map +1 -1
  55. package/dist/core/keybindings.js +11 -3
  56. package/dist/core/keybindings.js.map +1 -1
  57. package/dist/core/mcp-servers.d.ts +34 -7
  58. package/dist/core/mcp-servers.d.ts.map +1 -1
  59. package/dist/core/mcp-servers.js +52 -11
  60. package/dist/core/mcp-servers.js.map +1 -1
  61. package/dist/core/model-registry.d.ts +3 -1
  62. package/dist/core/model-registry.d.ts.map +1 -1
  63. package/dist/core/model-registry.js +4 -0
  64. package/dist/core/model-registry.js.map +1 -1
  65. package/dist/core/model-runtime.d.ts +6 -0
  66. package/dist/core/model-runtime.d.ts.map +1 -1
  67. package/dist/core/model-runtime.js +22 -18
  68. package/dist/core/model-runtime.js.map +1 -1
  69. package/dist/core/radius.d.ts +2 -0
  70. package/dist/core/radius.d.ts.map +1 -1
  71. package/dist/core/radius.js +2 -0
  72. package/dist/core/radius.js.map +1 -1
  73. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  74. package/dist/core/remote-catalog-provider.js +4 -9
  75. package/dist/core/remote-catalog-provider.js.map +1 -1
  76. package/dist/core/sdk.d.ts.map +1 -1
  77. package/dist/core/sdk.js +1 -0
  78. package/dist/core/sdk.js.map +1 -1
  79. package/dist/core/settings-manager.d.ts +7 -5
  80. package/dist/core/settings-manager.d.ts.map +1 -1
  81. package/dist/core/settings-manager.js +2 -1
  82. package/dist/core/settings-manager.js.map +1 -1
  83. package/dist/core/system-prompt.js +1 -1
  84. package/dist/core/system-prompt.js.map +1 -1
  85. package/dist/core/tasks/format.d.ts +7 -0
  86. package/dist/core/tasks/format.d.ts.map +1 -0
  87. package/dist/core/tasks/format.js +14 -0
  88. package/dist/core/tasks/format.js.map +1 -0
  89. package/dist/core/tasks/history.d.ts.map +1 -1
  90. package/dist/core/tasks/history.js +0 -19
  91. package/dist/core/tasks/history.js.map +1 -1
  92. package/dist/core/tasks/output.d.ts +8 -0
  93. package/dist/core/tasks/output.d.ts.map +1 -1
  94. package/dist/core/tasks/output.js +19 -0
  95. package/dist/core/tasks/output.js.map +1 -1
  96. package/dist/core/tasks/presentation.d.ts +1 -3
  97. package/dist/core/tasks/presentation.d.ts.map +1 -1
  98. package/dist/core/tasks/presentation.js +79 -166
  99. package/dist/core/tasks/presentation.js.map +1 -1
  100. package/dist/core/tasks/runtime.d.ts +16 -9
  101. package/dist/core/tasks/runtime.d.ts.map +1 -1
  102. package/dist/core/tasks/runtime.js +89 -106
  103. package/dist/core/tasks/runtime.js.map +1 -1
  104. package/dist/core/tasks/session.d.ts.map +1 -1
  105. package/dist/core/tasks/session.js +13 -4
  106. package/dist/core/tasks/session.js.map +1 -1
  107. package/dist/core/tasks/store.d.ts +20 -6
  108. package/dist/core/tasks/store.d.ts.map +1 -1
  109. package/dist/core/tasks/store.js +45 -18
  110. package/dist/core/tasks/store.js.map +1 -1
  111. package/dist/core/tasks/types.d.ts +14 -54
  112. package/dist/core/tasks/types.d.ts.map +1 -1
  113. package/dist/core/tasks/types.js +1 -5
  114. package/dist/core/tasks/types.js.map +1 -1
  115. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  116. package/dist/core/tools/renderers/bash.js +11 -34
  117. package/dist/core/tools/renderers/bash.js.map +1 -1
  118. package/dist/core/tools/shell-execution.d.ts +0 -1
  119. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  120. package/dist/core/tools/shell-execution.js +3 -10
  121. package/dist/core/tools/shell-execution.js.map +1 -1
  122. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  123. package/dist/core/tools/shell-tool.js +2 -4
  124. package/dist/core/tools/shell-tool.js.map +1 -1
  125. package/dist/core/tools/tasks/actions.d.ts +1 -1
  126. package/dist/core/tools/tasks/actions.d.ts.map +1 -1
  127. package/dist/core/tools/tasks/actions.js +26 -12
  128. package/dist/core/tools/tasks/actions.js.map +1 -1
  129. package/dist/core/tools/tasks/constants.d.ts +2 -6
  130. package/dist/core/tools/tasks/constants.d.ts.map +1 -1
  131. package/dist/core/tools/tasks/constants.js +2 -6
  132. package/dist/core/tools/tasks/constants.js.map +1 -1
  133. package/dist/core/tools/tasks/schema.d.ts +1 -1
  134. package/dist/core/tools/tasks/schema.d.ts.map +1 -1
  135. package/dist/core/tools/tasks/schema.js +8 -7
  136. package/dist/core/tools/tasks/schema.js.map +1 -1
  137. package/dist/core/tools/tasks/types.d.ts +8 -38
  138. package/dist/core/tools/tasks/types.d.ts.map +1 -1
  139. package/dist/core/tools/tasks/types.js +6 -11
  140. package/dist/core/tools/tasks/types.js.map +1 -1
  141. package/dist/core/virtual-models.d.ts +2 -0
  142. package/dist/core/virtual-models.d.ts.map +1 -1
  143. package/dist/core/virtual-models.js +19 -12
  144. package/dist/core/virtual-models.js.map +1 -1
  145. package/dist/extensions/btw/agent.d.ts +17 -8
  146. package/dist/extensions/btw/agent.d.ts.map +1 -1
  147. package/dist/extensions/btw/agent.js +74 -76
  148. package/dist/extensions/btw/agent.js.map +1 -1
  149. package/dist/extensions/btw/controller.d.ts +0 -1
  150. package/dist/extensions/btw/controller.d.ts.map +1 -1
  151. package/dist/extensions/btw/controller.js +26 -33
  152. package/dist/extensions/btw/controller.js.map +1 -1
  153. package/dist/extensions/btw/panel.d.ts +13 -14
  154. package/dist/extensions/btw/panel.d.ts.map +1 -1
  155. package/dist/extensions/btw/panel.js +38 -29
  156. package/dist/extensions/btw/panel.js.map +1 -1
  157. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  158. package/dist/extensions/codemode/execute.js +197 -51
  159. package/dist/extensions/codemode/execute.js.map +1 -1
  160. package/dist/extensions/codemode/renderer.d.ts.map +1 -1
  161. package/dist/extensions/codemode/renderer.js +43 -25
  162. package/dist/extensions/codemode/renderer.js.map +1 -1
  163. package/dist/extensions/codemode/tool.d.ts +12 -11
  164. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  165. package/dist/extensions/codemode/tool.js +73 -129
  166. package/dist/extensions/codemode/tool.js.map +1 -1
  167. package/dist/extensions/codemode/worker.d.ts +1 -1
  168. package/dist/extensions/codemode/worker.js +1 -1
  169. package/dist/extensions/codemode/worker.js.map +1 -1
  170. package/dist/extensions/deepwiki/schema.d.ts +1 -1
  171. package/dist/extensions/index.d.ts.map +1 -1
  172. package/dist/extensions/index.js +0 -2
  173. package/dist/extensions/index.js.map +1 -1
  174. package/dist/extensions/mcp/cli.d.ts.map +1 -1
  175. package/dist/extensions/mcp/cli.js +20 -5
  176. package/dist/extensions/mcp/cli.js.map +1 -1
  177. package/dist/extensions/mcp/config.d.ts +4 -2
  178. package/dist/extensions/mcp/config.d.ts.map +1 -1
  179. package/dist/extensions/mcp/config.js +14 -2
  180. package/dist/extensions/mcp/config.js.map +1 -1
  181. package/dist/extensions/mcp/index.d.ts +32 -8
  182. package/dist/extensions/mcp/index.d.ts.map +1 -1
  183. package/dist/extensions/mcp/index.js +235 -61
  184. package/dist/extensions/mcp/index.js.map +1 -1
  185. package/dist/extensions/mcp/oauth.d.ts +10 -7
  186. package/dist/extensions/mcp/oauth.d.ts.map +1 -1
  187. package/dist/extensions/mcp/oauth.js +56 -31
  188. package/dist/extensions/mcp/oauth.js.map +1 -1
  189. package/dist/extensions/mcp/runtime.d.ts +2 -0
  190. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  191. package/dist/extensions/mcp/runtime.js +16 -9
  192. package/dist/extensions/mcp/runtime.js.map +1 -1
  193. package/dist/extensions/mcp/tools.d.ts +5 -4
  194. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  195. package/dist/extensions/mcp/tools.js +33 -15
  196. package/dist/extensions/mcp/tools.js.map +1 -1
  197. package/dist/extensions/mcp/ui.d.ts.map +1 -1
  198. package/dist/extensions/mcp/ui.js +4 -2
  199. package/dist/extensions/mcp/ui.js.map +1 -1
  200. package/dist/extensions/provider/catalog.d.ts +8 -1
  201. package/dist/extensions/provider/catalog.d.ts.map +1 -1
  202. package/dist/extensions/provider/catalog.js +31 -0
  203. package/dist/extensions/provider/catalog.js.map +1 -1
  204. package/dist/extensions/provider/connection.d.ts +4 -1
  205. package/dist/extensions/provider/connection.d.ts.map +1 -1
  206. package/dist/extensions/provider/connection.js +1 -5
  207. package/dist/extensions/provider/connection.js.map +1 -1
  208. package/dist/extensions/provider/editing.d.ts +36 -0
  209. package/dist/extensions/provider/editing.d.ts.map +1 -0
  210. package/dist/extensions/provider/editing.js +99 -0
  211. package/dist/extensions/provider/editing.js.map +1 -0
  212. package/dist/extensions/provider/json-fields.d.ts +5 -0
  213. package/dist/extensions/provider/json-fields.d.ts.map +1 -0
  214. package/dist/extensions/provider/json-fields.js +31 -0
  215. package/dist/extensions/provider/json-fields.js.map +1 -0
  216. package/dist/extensions/provider/store.d.ts +1 -4
  217. package/dist/extensions/provider/store.d.ts.map +1 -1
  218. package/dist/extensions/provider/store.js +2 -30
  219. package/dist/extensions/provider/store.js.map +1 -1
  220. package/dist/extensions/provider/ui/builtin-data.d.ts +0 -2
  221. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  222. package/dist/extensions/provider/ui/builtin-data.js +14 -79
  223. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  224. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  225. package/dist/extensions/provider/ui/compat.js +6 -9
  226. package/dist/extensions/provider/ui/compat.js.map +1 -1
  227. package/dist/extensions/provider/ui/controls.d.ts +48 -0
  228. package/dist/extensions/provider/ui/controls.d.ts.map +1 -0
  229. package/dist/extensions/provider/ui/controls.js +108 -0
  230. package/dist/extensions/provider/ui/controls.js.map +1 -0
  231. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  232. package/dist/extensions/provider/ui/dictionary.js +6 -9
  233. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  234. package/dist/extensions/provider/ui/editor.d.ts +3 -3
  235. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  236. package/dist/extensions/provider/ui/editor.js +35 -140
  237. package/dist/extensions/provider/ui/editor.js.map +1 -1
  238. package/dist/extensions/provider/ui/fetch-models.d.ts +0 -3
  239. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  240. package/dist/extensions/provider/ui/fetch-models.js +49 -44
  241. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  242. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  243. package/dist/extensions/provider/ui/model-fields.js +11 -14
  244. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  245. package/dist/extensions/provider/ui/model-options.d.ts +4 -34
  246. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  247. package/dist/extensions/provider/ui/model-options.js +90 -271
  248. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  249. package/dist/extensions/provider/ui/pane.d.ts +4 -18
  250. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  251. package/dist/extensions/provider/ui/pane.js.map +1 -1
  252. package/dist/extensions/provider/ui/provider-fields.d.ts +2 -19
  253. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  254. package/dist/extensions/provider/ui/provider-fields.js +58 -171
  255. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  256. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  257. package/dist/extensions/provider/ui/thinking-map.js +6 -9
  258. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  259. package/dist/extensions/question/detail-pane.d.ts +7 -2
  260. package/dist/extensions/question/detail-pane.d.ts.map +1 -1
  261. package/dist/extensions/question/detail-pane.js +16 -5
  262. package/dist/extensions/question/detail-pane.js.map +1 -1
  263. package/dist/extensions/question/dialog-view.d.ts +41 -0
  264. package/dist/extensions/question/dialog-view.d.ts.map +1 -0
  265. package/dist/extensions/question/dialog-view.js +329 -0
  266. package/dist/extensions/question/dialog-view.js.map +1 -0
  267. package/dist/extensions/question/dialog.d.ts +3 -3
  268. package/dist/extensions/question/dialog.d.ts.map +1 -1
  269. package/dist/extensions/question/dialog.js +220 -634
  270. package/dist/extensions/question/dialog.js.map +1 -1
  271. package/dist/extensions/question/index.d.ts.map +1 -1
  272. package/dist/extensions/question/index.js +2 -3
  273. package/dist/extensions/question/index.js.map +1 -1
  274. package/dist/extensions/question/render.d.ts.map +1 -1
  275. package/dist/extensions/question/render.js +22 -32
  276. package/dist/extensions/question/render.js.map +1 -1
  277. package/dist/extensions/question/results.d.ts.map +1 -1
  278. package/dist/extensions/question/results.js +56 -12
  279. package/dist/extensions/question/results.js.map +1 -1
  280. package/dist/extensions/question/schema.d.ts +21 -6
  281. package/dist/extensions/question/schema.d.ts.map +1 -1
  282. package/dist/extensions/question/schema.js.map +1 -1
  283. package/dist/extensions/question/state.d.ts +9 -7
  284. package/dist/extensions/question/state.d.ts.map +1 -1
  285. package/dist/extensions/question/state.js +63 -54
  286. package/dist/extensions/question/state.js.map +1 -1
  287. package/dist/extensions/question/types.d.ts +41 -18
  288. package/dist/extensions/question/types.d.ts.map +1 -1
  289. package/dist/extensions/question/types.js.map +1 -1
  290. package/dist/extensions/statusline/index.d.ts +4 -0
  291. package/dist/extensions/statusline/index.d.ts.map +1 -1
  292. package/dist/extensions/statusline/index.js +18 -355
  293. package/dist/extensions/statusline/index.js.map +1 -1
  294. package/dist/extensions/statusline/render.d.ts +19 -0
  295. package/dist/extensions/statusline/render.d.ts.map +1 -0
  296. package/dist/extensions/statusline/render.js +163 -0
  297. package/dist/extensions/statusline/render.js.map +1 -0
  298. package/dist/extensions/statusline/usage.d.ts +12 -0
  299. package/dist/extensions/statusline/usage.d.ts.map +1 -0
  300. package/dist/extensions/statusline/usage.js +36 -0
  301. package/dist/extensions/statusline/usage.js.map +1 -0
  302. package/dist/extensions/tool-search/tool.d.ts +5 -4
  303. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  304. package/dist/extensions/tool-search/tool.js +7 -28
  305. package/dist/extensions/tool-search/tool.js.map +1 -1
  306. package/dist/extensions/web-search/execute.d.ts +1 -5
  307. package/dist/extensions/web-search/execute.d.ts.map +1 -1
  308. package/dist/extensions/web-search/execute.js +4 -9
  309. package/dist/extensions/web-search/execute.js.map +1 -1
  310. package/dist/extensions/web-search/format.d.ts +12 -3
  311. package/dist/extensions/web-search/format.d.ts.map +1 -1
  312. package/dist/extensions/web-search/format.js +33 -25
  313. package/dist/extensions/web-search/format.js.map +1 -1
  314. package/dist/extensions/web-search/index.d.ts.map +1 -1
  315. package/dist/extensions/web-search/index.js +6 -29
  316. package/dist/extensions/web-search/index.js.map +1 -1
  317. package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -1
  318. package/dist/extensions/web-search/providers/deepseek.js +0 -1
  319. package/dist/extensions/web-search/providers/deepseek.js.map +1 -1
  320. package/dist/extensions/web-search/providers/http.d.ts +1 -1
  321. package/dist/extensions/web-search/providers/http.d.ts.map +1 -1
  322. package/dist/extensions/web-search/providers/http.js.map +1 -1
  323. package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -1
  324. package/dist/extensions/web-search/providers/minimax.js +0 -1
  325. package/dist/extensions/web-search/providers/minimax.js.map +1 -1
  326. package/dist/extensions/web-search/render.d.ts +7 -2
  327. package/dist/extensions/web-search/render.d.ts.map +1 -1
  328. package/dist/extensions/web-search/render.js +32 -4
  329. package/dist/extensions/web-search/render.js.map +1 -1
  330. package/dist/extensions/web-search/results.d.ts.map +1 -1
  331. package/dist/extensions/web-search/results.js +3 -8
  332. package/dist/extensions/web-search/results.js.map +1 -1
  333. package/dist/extensions/web-search/types.d.ts +4 -2
  334. package/dist/extensions/web-search/types.d.ts.map +1 -1
  335. package/dist/extensions/web-search/types.js.map +1 -1
  336. package/dist/index.d.ts +2 -4
  337. package/dist/index.d.ts.map +1 -1
  338. package/dist/index.js +0 -1
  339. package/dist/index.js.map +1 -1
  340. package/dist/main.d.ts.map +1 -1
  341. package/dist/main.js +6 -0
  342. package/dist/main.js.map +1 -1
  343. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  344. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  345. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  346. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  347. package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
  348. package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
  349. package/dist/modes/interactive/components/pi-logo-animation.js +1076 -0
  350. package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
  351. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
  352. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
  353. package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
  354. package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
  355. package/dist/modes/interactive/components/pi-logo.d.ts +7 -0
  356. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
  357. package/dist/modes/interactive/components/pi-logo.js +13 -1
  358. package/dist/modes/interactive/components/pi-logo.js.map +1 -1
  359. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  360. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  361. package/dist/modes/interactive/components/radius-login-selector.js +83 -0
  362. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  363. package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
  364. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  365. package/dist/modes/interactive/components/settings-selector.js +5 -5
  366. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  367. package/dist/modes/interactive/components/status-marker.d.ts +0 -2
  368. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  369. package/dist/modes/interactive/components/status-marker.js +0 -4
  370. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  371. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  372. package/dist/modes/interactive/components/user-message.js +5 -4
  373. package/dist/modes/interactive/components/user-message.js.map +1 -1
  374. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  375. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  376. package/dist/modes/interactive/components/visual-truncate.js +36 -6
  377. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  378. package/dist/modes/interactive/interactive-mode.d.ts +10 -0
  379. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  380. package/dist/modes/interactive/interactive-mode.js +167 -40
  381. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  382. package/dist/modes/interactive/tasks/completion-render.d.ts +1 -1
  383. package/dist/modes/interactive/tasks/completion-render.d.ts.map +1 -1
  384. package/dist/modes/interactive/tasks/completion-render.js +28 -82
  385. package/dist/modes/interactive/tasks/completion-render.js.map +1 -1
  386. package/dist/modes/interactive/tasks/index.d.ts.map +1 -1
  387. package/dist/modes/interactive/tasks/index.js +18 -13
  388. package/dist/modes/interactive/tasks/index.js.map +1 -1
  389. package/dist/modes/interactive/tasks/inspector.d.ts +35 -0
  390. package/dist/modes/interactive/tasks/inspector.d.ts.map +1 -0
  391. package/dist/modes/interactive/tasks/inspector.js +93 -0
  392. package/dist/modes/interactive/tasks/inspector.js.map +1 -0
  393. package/dist/modes/interactive/tasks/layout.d.ts +40 -0
  394. package/dist/modes/interactive/tasks/layout.d.ts.map +1 -0
  395. package/dist/modes/interactive/tasks/layout.js +212 -0
  396. package/dist/modes/interactive/tasks/layout.js.map +1 -0
  397. package/dist/modes/interactive/tasks/list.d.ts +21 -0
  398. package/dist/modes/interactive/tasks/list.d.ts.map +1 -0
  399. package/dist/modes/interactive/tasks/list.js +96 -0
  400. package/dist/modes/interactive/tasks/list.js.map +1 -0
  401. package/dist/modes/interactive/tasks/manager.d.ts +29 -36
  402. package/dist/modes/interactive/tasks/manager.d.ts.map +1 -1
  403. package/dist/modes/interactive/tasks/manager.js +315 -315
  404. package/dist/modes/interactive/tasks/manager.js.map +1 -1
  405. package/dist/modes/interactive/tasks/model.d.ts +21 -0
  406. package/dist/modes/interactive/tasks/model.d.ts.map +1 -0
  407. package/dist/modes/interactive/tasks/model.js +41 -0
  408. package/dist/modes/interactive/tasks/model.js.map +1 -0
  409. package/dist/modes/interactive/tasks/render.d.ts +5 -19
  410. package/dist/modes/interactive/tasks/render.d.ts.map +1 -1
  411. package/dist/modes/interactive/tasks/render.js +18 -102
  412. package/dist/modes/interactive/tasks/render.js.map +1 -1
  413. package/dist/modes/interactive/tasks/task-view.d.ts +8 -48
  414. package/dist/modes/interactive/tasks/task-view.d.ts.map +1 -1
  415. package/dist/modes/interactive/tasks/task-view.js +11 -51
  416. package/dist/modes/interactive/tasks/task-view.js.map +1 -1
  417. package/dist/modes/interactive/tasks/text.d.ts +1 -7
  418. package/dist/modes/interactive/tasks/text.d.ts.map +1 -1
  419. package/dist/modes/interactive/tasks/text.js +6 -29
  420. package/dist/modes/interactive/tasks/text.js.map +1 -1
  421. package/dist/modes/interactive/tasks/viewport.d.ts +2 -0
  422. package/dist/modes/interactive/tasks/viewport.d.ts.map +1 -1
  423. package/dist/modes/interactive/tasks/viewport.js +17 -7
  424. package/dist/modes/interactive/tasks/viewport.js.map +1 -1
  425. package/dist/modes/interactive/tasks/views.d.ts +9 -0
  426. package/dist/modes/interactive/tasks/views.d.ts.map +1 -0
  427. package/dist/modes/interactive/tasks/views.js +42 -0
  428. package/dist/modes/interactive/tasks/views.js.map +1 -0
  429. package/dist/modes/interactive/theme/system-theme.d.ts +2 -1
  430. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
  431. package/dist/modes/interactive/theme/system-theme.js +16 -5
  432. package/dist/modes/interactive/theme/system-theme.js.map +1 -1
  433. package/docs/bundled/README.md +0 -1
  434. package/docs/bundled/extensions/question.md +2 -2
  435. package/docs/bundled/extensions/statusline.md +24 -15
  436. package/docs/bundled/tasks.md +34 -48
  437. package/docs/codemode.md +207 -0
  438. package/docs/docs.json +4 -4
  439. package/docs/environment-variables.md +1 -1
  440. package/docs/extensions.md +7 -9
  441. package/docs/keybindings.md +13 -6
  442. package/docs/mcp.md +142 -82
  443. package/docs/models.md +21 -0
  444. package/docs/providers.md +8 -0
  445. package/docs/sdk.md +2 -2
  446. package/docs/session-format.md +12 -22
  447. package/docs/settings.md +4 -2
  448. package/docs/tui.md +1 -1
  449. package/docs/usage.md +6 -16
  450. package/examples/README.md +1 -1
  451. package/examples/extensions/README.md +1 -2
  452. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  453. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  454. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  455. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  456. package/examples/extensions/gondolin/package-lock.json +2 -2
  457. package/examples/extensions/gondolin/package.json +1 -1
  458. package/examples/extensions/minimal-mode.ts +24 -96
  459. package/examples/extensions/sandbox/package-lock.json +2 -2
  460. package/examples/extensions/sandbox/package.json +1 -1
  461. package/examples/extensions/with-deps/package-lock.json +2 -2
  462. package/examples/extensions/with-deps/package.json +1 -1
  463. package/examples/sdk/14-codemode-mcp.ts +2 -2
  464. package/npm-shrinkwrap.json +69 -58
  465. package/package.json +11 -10
  466. package/dist/bundle/chunks/anthropic-messages-KIXY7EDT.js +0 -6
  467. package/dist/bundle/chunks/chunk-CLLDCO64.js +0 -2
  468. package/dist/bundle/chunks/chunk-UUSTLCVC.js +0 -2
  469. package/dist/bundle/chunks/chunk-VWCWZD6E.js +0 -2
  470. package/dist/bundle/chunks/virtual-modules-TQRORWJQ.js +0 -2
  471. package/dist/core/tasks/view-data.d.ts +0 -8
  472. package/dist/core/tasks/view-data.d.ts.map +0 -1
  473. package/dist/core/tasks/view-data.js +0 -61
  474. package/dist/core/tasks/view-data.js.map +0 -1
  475. package/dist/core/tasks/view.d.ts +0 -30
  476. package/dist/core/tasks/view.d.ts.map +0 -1
  477. package/dist/core/tasks/view.js +0 -50
  478. package/dist/core/tasks/view.js.map +0 -1
  479. package/dist/core/tools/renderers/shell-task.d.ts +0 -4
  480. package/dist/core/tools/renderers/shell-task.d.ts.map +0 -1
  481. package/dist/core/tools/renderers/shell-task.js +0 -35
  482. package/dist/core/tools/renderers/shell-task.js.map +0 -1
  483. package/dist/extensions/todo/constants.d.ts +0 -16
  484. package/dist/extensions/todo/constants.d.ts.map +0 -1
  485. package/dist/extensions/todo/constants.js +0 -30
  486. package/dist/extensions/todo/constants.js.map +0 -1
  487. package/dist/extensions/todo/index.d.ts +0 -3
  488. package/dist/extensions/todo/index.d.ts.map +0 -1
  489. package/dist/extensions/todo/index.js +0 -98
  490. package/dist/extensions/todo/index.js.map +0 -1
  491. package/dist/extensions/todo/schema.d.ts +0 -60
  492. package/dist/extensions/todo/schema.d.ts.map +0 -1
  493. package/dist/extensions/todo/schema.js +0 -56
  494. package/dist/extensions/todo/schema.js.map +0 -1
  495. package/dist/extensions/todo/state.d.ts +0 -34
  496. package/dist/extensions/todo/state.d.ts.map +0 -1
  497. package/dist/extensions/todo/state.js +0 -425
  498. package/dist/extensions/todo/state.js.map +0 -1
  499. package/dist/extensions/todo/view.d.ts +0 -36
  500. package/dist/extensions/todo/view.d.ts.map +0 -1
  501. package/dist/extensions/todo/view.js +0 -580
  502. package/dist/extensions/todo/view.js.map +0 -1
  503. package/dist/extensions/todo/widget.d.ts +0 -15
  504. package/dist/extensions/todo/widget.d.ts.map +0 -1
  505. package/dist/extensions/todo/widget.js +0 -50
  506. package/dist/extensions/todo/widget.js.map +0 -1
  507. package/dist/modes/interactive/tasks/fallback-view.d.ts +0 -4
  508. package/dist/modes/interactive/tasks/fallback-view.d.ts.map +0 -1
  509. package/dist/modes/interactive/tasks/fallback-view.js +0 -27
  510. package/dist/modes/interactive/tasks/fallback-view.js.map +0 -1
  511. package/docs/bundled/extensions/todo.md +0 -104
  512. package/examples/extensions/todo.ts +0 -297
@@ -0,0 +1,14 @@
1
+ /** Compact elapsed time shared by tool responses and interactive views. */
2
+ export function formatDuration(ms) {
3
+ const seconds = Math.max(0, Math.round(ms / 1000));
4
+ if (seconds < 60)
5
+ return `${seconds}s`;
6
+ const minutes = Math.floor(seconds / 60);
7
+ if (minutes < 60)
8
+ return `${minutes}m${String(seconds % 60).padStart(2, "0")}s`;
9
+ return `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, "0")}m`;
10
+ }
11
+ export function runtimeLabel(task, now = Date.now()) {
12
+ return formatDuration((task.endedAt ?? now) - task.startedAt);
13
+ }
14
+ //# sourceMappingURL=format.js.map
@@ -0,0 +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,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,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;QAAE,OAAO,GAAG,OAAO,IAAI,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;IAChF,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;AAChF,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\tconst seconds = Math.max(0, Math.round(ms / 1000));\n\tif (seconds < 60) return `${seconds}s`;\n\tconst minutes = Math.floor(seconds / 60);\n\tif (minutes < 60) return `${minutes}m${String(seconds % 60).padStart(2, \"0\")}s`;\n\treturn `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, \"0\")}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 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/history.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAuBtC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAsG1E"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/history.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAuBtC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAuF1E"}
@@ -1,6 +1,4 @@
1
1
  import { boundedResult, boundText, TASK_RESULT_BYTES, TASK_TITLE_BYTES } from "./output.js";
2
- import { readTaskProjection } from "./presentation.js";
3
- import { readTaskViewData } from "./view-data.js";
4
2
  export const TASK_HISTORY_VERSION = 2;
5
3
  /** Read persisted data properties only; never invoke getters or custom serialization. */
6
4
  function dataObject(value) {
@@ -35,9 +33,6 @@ export function parseTaskHistory(record) {
35
33
  const status = field(source, "status");
36
34
  if (typeof kind !== "string" || !/^[a-z][a-z0-9-]{0,63}$/.test(kind))
37
35
  return undefined;
38
- const format = field(source, "format");
39
- if (format !== undefined && format !== "log" && format !== "report")
40
- return undefined;
41
36
  if (mode !== "foreground" && mode !== "background")
42
37
  return undefined;
43
38
  if (status !== "completed" &&
@@ -59,7 +54,6 @@ export function parseTaskHistory(record) {
59
54
  const task = {
60
55
  id: historyString(field(source, "id"), 512, true),
61
56
  kind,
62
- format: format ?? "report",
63
57
  mode,
64
58
  status,
65
59
  startedAt,
@@ -94,19 +88,6 @@ export function parseTaskHistory(record) {
94
88
  }
95
89
  if (task.command !== undefined && task.command !== field(source, "command"))
96
90
  task.commandTruncated = true;
97
- const projection = field(source, "projection");
98
- const viewData = field(source, "viewData");
99
- if (viewData !== undefined) {
100
- try {
101
- task.viewData = readTaskViewData(viewData);
102
- }
103
- catch {
104
- /* Keep the readable result if custom view data is invalid. */
105
- }
106
- }
107
- if (projection !== undefined) {
108
- task.projection = readTaskProjection(projection);
109
- }
110
91
  const result = field(source, "result");
111
92
  if (result !== undefined) {
112
93
  const object = dataObject(result);
@@ -1 +1 @@
1
- {"version":3,"file":"history.js","sourceRoot":"","sources":["../../../src/core/tasks/history.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { boundedResult, boundText, TASK_RESULT_BYTES, TASK_TITLE_BYTES } from \"./output.ts\";\nimport { readTaskProjection } from \"./presentation.ts\";\nimport type { TaskSnapshot } from \"./types.ts\";\nimport { readTaskViewData } from \"./view-data.ts\";\n\nexport const TASK_HISTORY_VERSION = 2;\n\n/** Read persisted data properties only; never invoke getters or custom serialization. */\nfunction dataObject(value: unknown): Record<string, unknown> {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Expected object\");\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (prototype !== Object.prototype && prototype !== null) throw new Error(\"Expected plain object\");\n\treturn value as Record<string, unknown>;\n}\n\nfunction field(object: object, key: string): unknown {\n\tconst descriptor = Object.getOwnPropertyDescriptor(object, key);\n\tif (descriptor && !(\"value\" in descriptor)) throw new Error(\"Unexpected accessor\");\n\treturn descriptor?.value;\n}\n\nfunction historyString(value: unknown, bytes: number, exact = false): string {\n\tif (typeof value !== \"string\") throw new Error(\"Expected string\");\n\tif (exact && (!value || value.length > bytes || Buffer.byteLength(value) > bytes || value.includes(\"\\0\")))\n\t\tthrow new Error(\"Invalid identity or path\");\n\treturn boundText(value, bytes);\n}\n\nexport function parseTaskHistory(record: unknown): TaskSnapshot | undefined {\n\ttry {\n\t\tconst envelope = dataObject(record);\n\t\tif (field(envelope, \"version\") !== TASK_HISTORY_VERSION) return undefined;\n\t\tconst source = dataObject(field(envelope, \"task\"));\n\t\tconst kind = field(source, \"kind\");\n\t\tconst mode = field(source, \"mode\");\n\t\tconst status = field(source, \"status\");\n\t\tif (typeof kind !== \"string\" || !/^[a-z][a-z0-9-]{0,63}$/.test(kind)) return undefined;\n\t\tconst format = field(source, \"format\");\n\t\tif (format !== undefined && format !== \"log\" && format !== \"report\") return undefined;\n\t\tif (mode !== \"foreground\" && mode !== \"background\") return undefined;\n\t\tif (\n\t\t\tstatus !== \"completed\" &&\n\t\t\tstatus !== \"partial\" &&\n\t\t\tstatus !== \"failed\" &&\n\t\t\tstatus !== \"cancelled\" &&\n\t\t\tstatus !== \"timeout\"\n\t\t)\n\t\t\treturn undefined;\n\t\tconst startedAt = field(source, \"startedAt\");\n\t\tconst endedAt = field(source, \"endedAt\");\n\t\tif (\n\t\t\ttypeof startedAt !== \"number\" ||\n\t\t\t!Number.isSafeInteger(startedAt) ||\n\t\t\tstartedAt < 0 ||\n\t\t\ttypeof endedAt !== \"number\" ||\n\t\t\t!Number.isSafeInteger(endedAt) ||\n\t\t\tendedAt < startedAt\n\t\t)\n\t\t\treturn undefined;\n\t\tconst anchor = field(source, \"anchorId\");\n\t\tconst task: TaskSnapshot = {\n\t\t\tid: historyString(field(source, \"id\"), 512, true),\n\t\t\tkind,\n\t\t\tformat: format ?? \"report\",\n\t\t\tmode,\n\t\t\tstatus,\n\t\t\tstartedAt,\n\t\t\tendedAt,\n\t\t\ttitle: historyString(field(source, \"title\"), TASK_TITLE_BYTES),\n\t\t\ttoolCallId: historyString(field(source, \"toolCallId\"), 512, true),\n\t\t\tanchorId: anchor === null ? null : historyString(anchor, 8192, true),\n\t\t};\n\t\tif (!task.id.startsWith(`${kind}-`) || task.id.length <= kind.length + 1) return undefined;\n\t\tfor (const [key, bytes] of [\n\t\t\t[\"command\", 8192],\n\t\t\t[\"cwd\", 4096],\n\t\t\t[\"error\", 4096],\n\t\t\t[\"outputPath\", 8192],\n\t\t] as const) {\n\t\t\tconst value = field(source, key);\n\t\t\tif (value !== undefined) task[key] = historyString(value, bytes, key === \"outputPath\");\n\t\t}\n\t\tfor (const key of [\"commandTruncated\", \"resultTruncated\"] as const) {\n\t\t\tconst value = field(source, key);\n\t\t\tif (value !== undefined && typeof value !== \"boolean\") return undefined;\n\t\t\ttask[key] = value;\n\t\t}\n\t\tconst exitCode = field(source, \"exitCode\");\n\t\tif (exitCode !== undefined) {\n\t\t\tif (exitCode !== null && (typeof exitCode !== \"number\" || !Number.isSafeInteger(exitCode))) return undefined;\n\t\t\ttask.exitCode = exitCode;\n\t\t}\n\t\tif (task.command !== undefined && task.command !== field(source, \"command\")) task.commandTruncated = true;\n\t\tconst projection = field(source, \"projection\");\n\t\tconst viewData = field(source, \"viewData\");\n\t\tif (viewData !== undefined) {\n\t\t\ttry {\n\t\t\t\ttask.viewData = readTaskViewData(viewData);\n\t\t\t} catch {\n\t\t\t\t/* Keep the readable result if custom view data is invalid. */\n\t\t\t}\n\t\t}\n\t\tif (projection !== undefined) {\n\t\t\ttask.projection = readTaskProjection(projection);\n\t\t}\n\t\tconst result = field(source, \"result\");\n\t\tif (result !== undefined) {\n\t\t\tconst object = dataObject(result);\n\t\t\tconst blocks = field(object, \"content\");\n\t\t\tif (!Array.isArray(blocks)) return undefined;\n\t\t\tconst content: AgentToolResult<unknown>[\"content\"] = [];\n\t\t\tlet remaining = TASK_RESULT_BYTES;\n\t\t\tfor (let index = 0; index < blocks.length && remaining > 0; index++) {\n\t\t\t\tconst block = dataObject(field(blocks, String(index)));\n\t\t\t\tconst type = field(block, \"type\");\n\t\t\t\tif (type !== \"text\" && type !== \"image\") return undefined;\n\t\t\t\tconst original = type === \"text\" ? field(block, \"text\") : undefined;\n\t\t\t\tconst text =\n\t\t\t\t\ttype === \"text\" ? historyString(original, remaining) : \"[Image omitted from background history]\";\n\t\t\t\tif (text !== original) task.resultTruncated = true;\n\t\t\t\tcontent.push({ type: \"text\", text });\n\t\t\t\tremaining -= Math.max(1, Buffer.byteLength(text));\n\t\t\t}\n\t\t\tif (content.length < blocks.length) task.resultTruncated = true;\n\t\t\ttask.result = boundedResult({ content, details: undefined });\n\t\t}\n\t\treturn task;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../../src/core/tasks/history.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { boundedResult, boundText, TASK_RESULT_BYTES, TASK_TITLE_BYTES } from \"./output.ts\";\nimport type { TaskSnapshot } from \"./types.ts\";\n\nexport const TASK_HISTORY_VERSION = 2;\n\n/** Read persisted data properties only; never invoke getters or custom serialization. */\nfunction dataObject(value: unknown): Record<string, unknown> {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Expected object\");\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (prototype !== Object.prototype && prototype !== null) throw new Error(\"Expected plain object\");\n\treturn value as Record<string, unknown>;\n}\n\nfunction field(object: object, key: string): unknown {\n\tconst descriptor = Object.getOwnPropertyDescriptor(object, key);\n\tif (descriptor && !(\"value\" in descriptor)) throw new Error(\"Unexpected accessor\");\n\treturn descriptor?.value;\n}\n\nfunction historyString(value: unknown, bytes: number, exact = false): string {\n\tif (typeof value !== \"string\") throw new Error(\"Expected string\");\n\tif (exact && (!value || value.length > bytes || Buffer.byteLength(value) > bytes || value.includes(\"\\0\")))\n\t\tthrow new Error(\"Invalid identity or path\");\n\treturn boundText(value, bytes);\n}\n\nexport function parseTaskHistory(record: unknown): TaskSnapshot | undefined {\n\ttry {\n\t\tconst envelope = dataObject(record);\n\t\tif (field(envelope, \"version\") !== TASK_HISTORY_VERSION) return undefined;\n\t\tconst source = dataObject(field(envelope, \"task\"));\n\t\tconst kind = field(source, \"kind\");\n\t\tconst mode = field(source, \"mode\");\n\t\tconst status = field(source, \"status\");\n\t\tif (typeof kind !== \"string\" || !/^[a-z][a-z0-9-]{0,63}$/.test(kind)) return undefined;\n\t\tif (mode !== \"foreground\" && mode !== \"background\") return undefined;\n\t\tif (\n\t\t\tstatus !== \"completed\" &&\n\t\t\tstatus !== \"partial\" &&\n\t\t\tstatus !== \"failed\" &&\n\t\t\tstatus !== \"cancelled\" &&\n\t\t\tstatus !== \"timeout\"\n\t\t)\n\t\t\treturn undefined;\n\t\tconst startedAt = field(source, \"startedAt\");\n\t\tconst endedAt = field(source, \"endedAt\");\n\t\tif (\n\t\t\ttypeof startedAt !== \"number\" ||\n\t\t\t!Number.isSafeInteger(startedAt) ||\n\t\t\tstartedAt < 0 ||\n\t\t\ttypeof endedAt !== \"number\" ||\n\t\t\t!Number.isSafeInteger(endedAt) ||\n\t\t\tendedAt < startedAt\n\t\t)\n\t\t\treturn undefined;\n\t\tconst anchor = field(source, \"anchorId\");\n\t\tconst task: TaskSnapshot = {\n\t\t\tid: historyString(field(source, \"id\"), 512, true),\n\t\t\tkind,\n\t\t\tmode,\n\t\t\tstatus,\n\t\t\tstartedAt,\n\t\t\tendedAt,\n\t\t\ttitle: historyString(field(source, \"title\"), TASK_TITLE_BYTES),\n\t\t\ttoolCallId: historyString(field(source, \"toolCallId\"), 512, true),\n\t\t\tanchorId: anchor === null ? null : historyString(anchor, 8192, true),\n\t\t};\n\t\tif (!task.id.startsWith(`${kind}-`) || task.id.length <= kind.length + 1) return undefined;\n\t\tfor (const [key, bytes] of [\n\t\t\t[\"command\", 8192],\n\t\t\t[\"cwd\", 4096],\n\t\t\t[\"error\", 4096],\n\t\t\t[\"outputPath\", 8192],\n\t\t] as const) {\n\t\t\tconst value = field(source, key);\n\t\t\tif (value !== undefined) task[key] = historyString(value, bytes, key === \"outputPath\");\n\t\t}\n\t\tfor (const key of [\"commandTruncated\", \"resultTruncated\"] as const) {\n\t\t\tconst value = field(source, key);\n\t\t\tif (value !== undefined && typeof value !== \"boolean\") return undefined;\n\t\t\ttask[key] = value;\n\t\t}\n\t\tconst exitCode = field(source, \"exitCode\");\n\t\tif (exitCode !== undefined) {\n\t\t\tif (exitCode !== null && (typeof exitCode !== \"number\" || !Number.isSafeInteger(exitCode))) return undefined;\n\t\t\ttask.exitCode = exitCode;\n\t\t}\n\t\tif (task.command !== undefined && task.command !== field(source, \"command\")) task.commandTruncated = true;\n\t\tconst result = field(source, \"result\");\n\t\tif (result !== undefined) {\n\t\t\tconst object = dataObject(result);\n\t\t\tconst blocks = field(object, \"content\");\n\t\t\tif (!Array.isArray(blocks)) return undefined;\n\t\t\tconst content: AgentToolResult<unknown>[\"content\"] = [];\n\t\t\tlet remaining = TASK_RESULT_BYTES;\n\t\t\tfor (let index = 0; index < blocks.length && remaining > 0; index++) {\n\t\t\t\tconst block = dataObject(field(blocks, String(index)));\n\t\t\t\tconst type = field(block, \"type\");\n\t\t\t\tif (type !== \"text\" && type !== \"image\") return undefined;\n\t\t\t\tconst original = type === \"text\" ? field(block, \"text\") : undefined;\n\t\t\t\tconst text =\n\t\t\t\t\ttype === \"text\" ? historyString(original, remaining) : \"[Image omitted from background history]\";\n\t\t\t\tif (text !== original) task.resultTruncated = true;\n\t\t\t\tcontent.push({ type: \"text\", text });\n\t\t\t\tremaining -= Math.max(1, Buffer.byteLength(text));\n\t\t\t}\n\t\t\tif (content.length < blocks.length) task.resultTruncated = true;\n\t\t\ttask.result = boundedResult({ content, details: undefined });\n\t\t}\n\t\treturn task;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
2
+ import type { TaskSnapshot } from "./types.ts";
2
3
  export declare const TASK_RESULT_BYTES: number;
3
4
  export declare const TASK_DETAILS_BYTES: number;
4
5
  export declare const TASK_READ_BYTES: number;
@@ -6,8 +7,15 @@ export declare const TASK_READ_BYTES: number;
6
7
  export declare const TASK_TITLE_BYTES = 1024;
7
8
  export declare function finiteLimit(value: number | undefined, fallback: number, ceiling: number): number;
8
9
  export declare function boundText(text: string, bytes?: number): string;
10
+ /** The end of a bounded text, codepoint aligned: a command's outcome is at its end. */
11
+ export declare function boundTail(text: string, bytes: number): {
12
+ text: string;
13
+ truncated: boolean;
14
+ };
9
15
  /** Keep valid structured details intact or omit them, never truncate serialized JSON. */
10
16
  export declare function boundedResult(result: AgentToolResult<unknown>): AgentToolResult<unknown>;
17
+ /** Store the bounded public part of a result; private details never enter task history. */
18
+ export declare function retainResult(task: TaskSnapshot, result: AgentToolResult<unknown>, truncated?: boolean): void;
11
19
  export interface OutputSlice {
12
20
  text: string;
13
21
  totalBytes: number;
@@ -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;AAErE,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,eAAe,QAAW,CAAC;AACxC,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,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,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,OAAO,CAAC,CAwBxF;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;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAC7C,eAAO,MAAM,eAAe,QAAW,CAAC;AACxC,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,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,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,yFAAyF;AACzF,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,OAAO,CAAC,CAwBxF;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,SAAS,UAAQ,GAAG,IAAI,CAU1G;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"}
@@ -34,6 +34,13 @@ export function boundText(text, bytes = TASK_RESULT_BYTES) {
34
34
  const buffer = Buffer.from(prefix);
35
35
  return alignedSlice(buffer, 0, Math.min(limit, buffer.length)).toString("utf8");
36
36
  }
37
+ /** The end of a bounded text, codepoint aligned: a command's outcome is at its end. */
38
+ export function boundTail(text, bytes) {
39
+ const buffer = Buffer.from(text);
40
+ if (buffer.length <= bytes)
41
+ return { text, truncated: false };
42
+ return { text: alignedSlice(buffer, buffer.length - bytes, buffer.length).toString("utf8"), truncated: true };
43
+ }
37
44
  /** Keep valid structured details intact or omit them, never truncate serialized JSON. */
38
45
  export function boundedResult(result) {
39
46
  let remaining = TASK_RESULT_BYTES;
@@ -64,6 +71,18 @@ export function boundedResult(result) {
64
71
  }
65
72
  return { content, details };
66
73
  }
74
+ /** Store the bounded public part of a result; private details never enter task history. */
75
+ export function retainResult(task, result, truncated = false) {
76
+ const bounded = boundedResult({ content: result.content, details: undefined });
77
+ task.result = bounded;
78
+ task.resultTruncated =
79
+ truncated ||
80
+ bounded.content.length !== result.content.length ||
81
+ bounded.content.some((block, index) => {
82
+ const original = result.content[index];
83
+ return original?.type !== "text" || block.type !== "text" || block.text !== original.text;
84
+ });
85
+ }
67
86
  /** Positioned, bounded reads only. The executor owns the path and its cleanup. */
68
87
  export async function readOutputSlice(path, options = {}) {
69
88
  const bytes = finiteLimit(options.bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/core/tasks/output.ts"],"names":[],"mappings":"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","sourcesContent":["import { open } from \"node:fs/promises\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\n\nexport const TASK_RESULT_BYTES = 48 * 1024;\nexport const TASK_DETAILS_BYTES = 120 * 1024;\nexport const TASK_READ_BYTES = 8 * 1024;\n/** Task title budget, independent of notification wording and rendering. */\nexport const TASK_TITLE_BYTES = 1024;\n\nexport function finiteLimit(value: number | undefined, fallback: number, ceiling: number): number {\n\treturn value === undefined || !Number.isFinite(value) ? fallback : Math.max(0, Math.min(ceiling, Math.floor(value)));\n}\n\n/** Both ends are codepoint aligned, including a head read ending inside a character. */\nfunction alignedSlice(buffer: Buffer, start: number, end: number): Buffer {\n\twhile (start < end && (buffer[start]! & 0xc0) === 0x80) start++;\n\tif (end < buffer.length) {\n\t\twhile (end > start && (buffer[end]! & 0xc0) === 0x80) end--;\n\t}\n\t// A concurrently written file can itself end in an incomplete UTF-8 sequence.\n\tlet lead = end - 1;\n\twhile (lead >= start && (buffer[lead]! & 0xc0) === 0x80) lead--;\n\tif (lead >= start) {\n\t\tconst byte = buffer[lead]!;\n\t\tconst width = byte >= 0xf0 ? 4 : byte >= 0xe0 ? 3 : byte >= 0xc0 ? 2 : 1;\n\t\tif (end - lead < width) end = lead;\n\t}\n\treturn buffer.subarray(start, end);\n}\n\nexport function boundText(text: string, bytes = TASK_RESULT_BYTES): string {\n\t// Avoid allocating a buffer proportional to an unbounded source.\n\tconst limit = finiteLimit(bytes, TASK_RESULT_BYTES, TASK_RESULT_BYTES);\n\tconst prefix = text.slice(0, limit + 1);\n\tconst buffer = Buffer.from(prefix);\n\treturn alignedSlice(buffer, 0, Math.min(limit, buffer.length)).toString(\"utf8\");\n}\n\n/** Keep valid structured details intact or omit them, never truncate serialized JSON. */\nexport function boundedResult(result: AgentToolResult<unknown>): AgentToolResult<unknown> {\n\tlet remaining = TASK_RESULT_BYTES;\n\tconst content: AgentToolResult<unknown>[\"content\"] = [];\n\tfor (const block of result.content) {\n\t\tif (remaining <= 0) break;\n\t\tconst text = boundText(block.type === \"text\" ? block.text : \"[Image omitted from background history]\", remaining);\n\t\tcontent.push({ type: \"text\", text });\n\t\tremaining -= Math.max(1, Buffer.byteLength(text));\n\t}\n\tlet details: unknown;\n\ttry {\n\t\tlet budget = TASK_DETAILS_BYTES;\n\t\tconst json = JSON.stringify(result.details, (key, value: unknown) => {\n\t\t\t// Stop visiting an oversized structure before constructing an unbounded JSON string.\n\t\t\tbudget -= Buffer.byteLength(key) + 3;\n\t\t\tbudget -= typeof value === \"string\" ? Buffer.byteLength(value) + 2 : 8;\n\t\t\tif (budget < 0) throw new Error(\"Background details exceed the storage budget\");\n\t\t\treturn value;\n\t\t});\n\t\tif (json !== undefined && Buffer.byteLength(json) <= TASK_DETAILS_BYTES) details = JSON.parse(json);\n\t} catch {\n\t\t// Runtime handles and cyclic details cannot enter a serializable snapshot.\n\t}\n\treturn { content, details };\n}\n\nexport interface OutputSlice {\n\ttext: string;\n\ttotalBytes: number;\n\ttruncated: boolean;\n\tfromByte: number;\n}\n\n/** Positioned, bounded reads only. The executor owns the path and its cleanup. */\nexport async function readOutputSlice(\n\tpath: string,\n\toptions: { mode?: \"head\" | \"tail\"; bytes?: number; sinceBytes?: number } = {},\n): Promise<OutputSlice> {\n\tconst bytes = finiteLimit(options.bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);\n\tconst file = await open(path, \"r\");\n\ttry {\n\t\tconst { size } = await file.stat();\n\t\tconst since = finiteLimit(options.sinceBytes, 0, Number.MAX_SAFE_INTEGER);\n\t\tconst floor = since > size ? 0 : since;\n\t\tconst start =\n\t\t\toptions.sinceBytes !== undefined\n\t\t\t\t? Math.max(floor, size - bytes)\n\t\t\t\t: options.mode === \"head\"\n\t\t\t\t\t? 0\n\t\t\t\t\t: Math.max(0, size - bytes);\n\t\tconst length = Math.min(bytes, size - start);\n\t\t// One extra byte lets alignment distinguish a complete last codepoint.\n\t\tconst buffer = Buffer.alloc(Math.min(length + 1, size - start));\n\t\tconst { bytesRead } = await file.read(buffer, 0, buffer.length, start);\n\t\tconst slice = alignedSlice(buffer.subarray(0, bytesRead), 0, Math.min(length, bytesRead));\n\t\treturn {\n\t\t\ttext: slice.toString(\"utf8\"),\n\t\t\ttotalBytes: size,\n\t\t\ttruncated: options.sinceBytes !== undefined ? start > floor || slice.length < length : slice.length < size,\n\t\t\tfromByte: start + slice.byteOffset - buffer.byteOffset,\n\t\t};\n\t} finally {\n\t\tawait file.close();\n\t}\n}\n\nexport function sliceText(\n\ttext: string,\n\toptions: { mode?: \"head\" | \"tail\"; bytes?: number; sinceBytes?: number } = {},\n): OutputSlice {\n\tconst buffer = Buffer.from(text);\n\tconst bytes = finiteLimit(options.bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);\n\tconst since = finiteLimit(options.sinceBytes, 0, Number.MAX_SAFE_INTEGER);\n\tconst floor = since > buffer.length ? 0 : since;\n\tconst start =\n\t\toptions.sinceBytes !== undefined\n\t\t\t? Math.max(floor, buffer.length - bytes)\n\t\t\t: options.mode === \"head\"\n\t\t\t\t? 0\n\t\t\t\t: Math.max(0, buffer.length - bytes);\n\tconst slice = alignedSlice(buffer, start, Math.min(buffer.length, start + bytes));\n\treturn {\n\t\ttext: slice.toString(\"utf8\"),\n\t\ttotalBytes: buffer.length,\n\t\ttruncated: slice.length < buffer.length - floor,\n\t\tfromByte: slice.byteOffset - buffer.byteOffset,\n\t};\n}\n"]}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/core/tasks/output.ts"],"names":[],"mappings":"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","sourcesContent":["import { open } from \"node:fs/promises\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { TaskSnapshot } from \"./types.ts\";\n\nexport const TASK_RESULT_BYTES = 48 * 1024;\nexport const TASK_DETAILS_BYTES = 120 * 1024;\nexport const TASK_READ_BYTES = 8 * 1024;\n/** Task title budget, independent of notification wording and rendering. */\nexport const TASK_TITLE_BYTES = 1024;\n\nexport function finiteLimit(value: number | undefined, fallback: number, ceiling: number): number {\n\treturn value === undefined || !Number.isFinite(value) ? fallback : Math.max(0, Math.min(ceiling, Math.floor(value)));\n}\n\n/** Both ends are codepoint aligned, including a head read ending inside a character. */\nfunction alignedSlice(buffer: Buffer, start: number, end: number): Buffer {\n\twhile (start < end && (buffer[start]! & 0xc0) === 0x80) start++;\n\tif (end < buffer.length) {\n\t\twhile (end > start && (buffer[end]! & 0xc0) === 0x80) end--;\n\t}\n\t// A concurrently written file can itself end in an incomplete UTF-8 sequence.\n\tlet lead = end - 1;\n\twhile (lead >= start && (buffer[lead]! & 0xc0) === 0x80) lead--;\n\tif (lead >= start) {\n\t\tconst byte = buffer[lead]!;\n\t\tconst width = byte >= 0xf0 ? 4 : byte >= 0xe0 ? 3 : byte >= 0xc0 ? 2 : 1;\n\t\tif (end - lead < width) end = lead;\n\t}\n\treturn buffer.subarray(start, end);\n}\n\nexport function boundText(text: string, bytes = TASK_RESULT_BYTES): string {\n\t// Avoid allocating a buffer proportional to an unbounded source.\n\tconst limit = finiteLimit(bytes, TASK_RESULT_BYTES, TASK_RESULT_BYTES);\n\tconst prefix = text.slice(0, limit + 1);\n\tconst buffer = Buffer.from(prefix);\n\treturn alignedSlice(buffer, 0, Math.min(limit, buffer.length)).toString(\"utf8\");\n}\n\n/** The end of a bounded text, codepoint aligned: a command's outcome is at its end. */\nexport function boundTail(text: string, bytes: number): { text: string; truncated: boolean } {\n\tconst buffer = Buffer.from(text);\n\tif (buffer.length <= bytes) return { text, truncated: false };\n\treturn { text: alignedSlice(buffer, buffer.length - bytes, buffer.length).toString(\"utf8\"), truncated: true };\n}\n\n/** Keep valid structured details intact or omit them, never truncate serialized JSON. */\nexport function boundedResult(result: AgentToolResult<unknown>): AgentToolResult<unknown> {\n\tlet remaining = TASK_RESULT_BYTES;\n\tconst content: AgentToolResult<unknown>[\"content\"] = [];\n\tfor (const block of result.content) {\n\t\tif (remaining <= 0) break;\n\t\tconst text = boundText(block.type === \"text\" ? block.text : \"[Image omitted from background history]\", remaining);\n\t\tcontent.push({ type: \"text\", text });\n\t\tremaining -= Math.max(1, Buffer.byteLength(text));\n\t}\n\tlet details: unknown;\n\ttry {\n\t\tlet budget = TASK_DETAILS_BYTES;\n\t\tconst json = JSON.stringify(result.details, (key, value: unknown) => {\n\t\t\t// Stop visiting an oversized structure before constructing an unbounded JSON string.\n\t\t\tbudget -= Buffer.byteLength(key) + 3;\n\t\t\tbudget -= typeof value === \"string\" ? Buffer.byteLength(value) + 2 : 8;\n\t\t\tif (budget < 0) throw new Error(\"Background details exceed the storage budget\");\n\t\t\treturn value;\n\t\t});\n\t\tif (json !== undefined && Buffer.byteLength(json) <= TASK_DETAILS_BYTES) details = JSON.parse(json);\n\t} catch {\n\t\t// Runtime handles and cyclic details cannot enter a serializable snapshot.\n\t}\n\treturn { content, details };\n}\n\n/** Store the bounded public part of a result; private details never enter task history. */\nexport function retainResult(task: TaskSnapshot, result: AgentToolResult<unknown>, truncated = false): void {\n\tconst bounded = boundedResult({ content: result.content, details: undefined });\n\ttask.result = bounded;\n\ttask.resultTruncated =\n\t\ttruncated ||\n\t\tbounded.content.length !== result.content.length ||\n\t\tbounded.content.some((block, index) => {\n\t\t\tconst original = result.content[index];\n\t\t\treturn original?.type !== \"text\" || block.type !== \"text\" || block.text !== original.text;\n\t\t});\n}\n\nexport interface OutputSlice {\n\ttext: string;\n\ttotalBytes: number;\n\ttruncated: boolean;\n\tfromByte: number;\n}\n\n/** Positioned, bounded reads only. The executor owns the path and its cleanup. */\nexport async function readOutputSlice(\n\tpath: string,\n\toptions: { mode?: \"head\" | \"tail\"; bytes?: number; sinceBytes?: number } = {},\n): Promise<OutputSlice> {\n\tconst bytes = finiteLimit(options.bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);\n\tconst file = await open(path, \"r\");\n\ttry {\n\t\tconst { size } = await file.stat();\n\t\tconst since = finiteLimit(options.sinceBytes, 0, Number.MAX_SAFE_INTEGER);\n\t\tconst floor = since > size ? 0 : since;\n\t\tconst start =\n\t\t\toptions.sinceBytes !== undefined\n\t\t\t\t? Math.max(floor, size - bytes)\n\t\t\t\t: options.mode === \"head\"\n\t\t\t\t\t? 0\n\t\t\t\t\t: Math.max(0, size - bytes);\n\t\tconst length = Math.min(bytes, size - start);\n\t\t// One extra byte lets alignment distinguish a complete last codepoint.\n\t\tconst buffer = Buffer.alloc(Math.min(length + 1, size - start));\n\t\tconst { bytesRead } = await file.read(buffer, 0, buffer.length, start);\n\t\tconst slice = alignedSlice(buffer.subarray(0, bytesRead), 0, Math.min(length, bytesRead));\n\t\treturn {\n\t\t\ttext: slice.toString(\"utf8\"),\n\t\t\ttotalBytes: size,\n\t\t\ttruncated: options.sinceBytes !== undefined ? start > floor || slice.length < length : slice.length < size,\n\t\t\tfromByte: start + slice.byteOffset - buffer.byteOffset,\n\t\t};\n\t} finally {\n\t\tawait file.close();\n\t}\n}\n\nexport function sliceText(\n\ttext: string,\n\toptions: { mode?: \"head\" | \"tail\"; bytes?: number; sinceBytes?: number } = {},\n): OutputSlice {\n\tconst buffer = Buffer.from(text);\n\tconst bytes = finiteLimit(options.bytes, TASK_READ_BYTES, TASK_RESULT_BYTES);\n\tconst since = finiteLimit(options.sinceBytes, 0, Number.MAX_SAFE_INTEGER);\n\tconst floor = since > buffer.length ? 0 : since;\n\tconst start =\n\t\toptions.sinceBytes !== undefined\n\t\t\t? Math.max(floor, buffer.length - bytes)\n\t\t\t: options.mode === \"head\"\n\t\t\t\t? 0\n\t\t\t\t: Math.max(0, buffer.length - bytes);\n\tconst slice = alignedSlice(buffer, start, Math.min(buffer.length, start + bytes));\n\treturn {\n\t\ttext: slice.toString(\"utf8\"),\n\t\ttotalBytes: buffer.length,\n\t\ttruncated: slice.length < buffer.length - floor,\n\t\tfromByte: slice.byteOffset - buffer.byteOffset,\n\t};\n}\n"]}
@@ -1,7 +1,5 @@
1
1
  import type { CustomMessage } from "../messages.ts";
2
- import type { TaskCompletionSnapshot, TaskProjection, TaskSnapshot } from "./types.ts";
3
- /** Shared by live publication and history restoration; never imports an executor's private details. */
4
- export declare function readTaskProjection(value: unknown): TaskProjection;
2
+ import type { TaskCompletionSnapshot, TaskSnapshot } from "./types.ts";
5
3
  /** Only this format is understood. Invalid/older details receive the renderer's bounded plain-text fallback. */
6
4
  export declare function readTaskCompletion(value: unknown): TaskCompletionSnapshot | undefined;
7
5
  export declare function taskCompletionSnapshot(task: TaskSnapshot): TaskCompletionSnapshot;
@@ -1 +1 @@
1
- {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,KAAK,EACX,sBAAsB,EAGtB,cAAc,EACd,YAAY,EAGZ,MAAM,YAAY,CAAC;AAoEpB,uGAAuG;AACvG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CA4BjE;AAcD,gHAAgH;AAChH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,GAAG,SAAS,CAmFrF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CA+CjF;AAsED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC,sBAAsB,CAAC,CAU/F"}
1
+ {"version":3,"file":"presentation.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAgC,MAAM,YAAY,CAAC;AA0ErG,gHAAgH;AAChH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,GAAG,SAAS,CA+DrF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,sBAAsB,CAyBjF;AAyDD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC,sBAAsB,CAAC,CAU/F"}
@@ -1,8 +1,6 @@
1
- import { truncateHead } from "../tools/truncate.js";
2
- import { boundText, TASK_DETAILS_BYTES, TASK_RESULT_BYTES, TASK_TITLE_BYTES } from "./output.js";
1
+ import { truncateHead, truncateTail } from "../tools/truncate.js";
2
+ import { boundTail, boundText, TASK_DETAILS_BYTES, TASK_RESULT_BYTES, TASK_TITLE_BYTES } from "./output.js";
3
3
  const OUTPUT_BYTES = 40 * 1024;
4
- const REPORT_BYTES = 4 * 1024;
5
- const MAX_ITEMS = 8;
6
4
  const MODEL_LINES = 2000;
7
5
  /** Read data properties only, including at the persisted-message boundary. */
8
6
  function object(value) {
@@ -37,6 +35,22 @@ function string(value, bytes) {
37
35
  }
38
36
  return boundText(prefix, low);
39
37
  }
38
+ /** The end of a text whose escaped JSON fits `bytes`: a command's outcome is at its end. */
39
+ function tail(value, bytes) {
40
+ const fits = (size) => Buffer.byteLength(JSON.stringify(boundTail(value, size).text)) <= bytes;
41
+ let low = 0;
42
+ let high = Buffer.byteLength(value);
43
+ if (fits(high))
44
+ return { text: value, truncated: false };
45
+ while (low < high) {
46
+ const middle = Math.ceil((low + high) / 2);
47
+ if (fits(middle))
48
+ low = middle;
49
+ else
50
+ high = middle - 1;
51
+ }
52
+ return boundTail(value, low);
53
+ }
40
54
  function optionalString(source, key, bytes) {
41
55
  const value = field(source, key);
42
56
  return value === undefined ? undefined : string(value, bytes);
@@ -50,53 +64,6 @@ function text(value, bytes) {
50
64
  const bounded = string(original, bytes);
51
65
  return { text: bounded, truncated: truncated || bounded !== original };
52
66
  }
53
- function itemReport(value) {
54
- const source = object(value);
55
- return {
56
- id: string(field(source, "id"), 256),
57
- label: string(field(source, "label"), 512),
58
- category: string(field(source, "category"), 128),
59
- description: string(field(source, "description"), 512),
60
- status: string(field(source, "status"), 128),
61
- report: text(field(source, "report"), REPORT_BYTES),
62
- error: optionalString(source, "error", 1024),
63
- };
64
- }
65
- function items(value, read) {
66
- if (!Array.isArray(value))
67
- throw new Error("Expected items");
68
- return Array.from({ length: Math.min(value.length, MAX_ITEMS) }, (_, index) => read(field(value, String(index))));
69
- }
70
- /** Shared by live publication and history restoration; never imports an executor's private details. */
71
- export function readTaskProjection(value) {
72
- const source = object(value);
73
- const projection = {
74
- nextStep: optionalString(source, "nextStep", 2048),
75
- text: optionalString(source, "text", 16 * 1024),
76
- };
77
- const shell = field(source, "shell");
78
- if (shell !== undefined) {
79
- const fields = object(shell);
80
- projection.shell = {
81
- name: string(field(fields, "name"), 128),
82
- output: text(field(fields, "output"), OUTPUT_BYTES),
83
- };
84
- }
85
- const reports = field(source, "items");
86
- if (reports !== undefined) {
87
- projection.items = items(reports, (value) => {
88
- const fields = object(value);
89
- return {
90
- ...itemReport(value),
91
- input: string(field(fields, "input"), 4096),
92
- activity: string(field(fields, "activity"), 1024),
93
- context: optionalString(fields, "context", 256),
94
- usage: optionalString(fields, "usage", 256),
95
- };
96
- });
97
- }
98
- return projection;
99
- }
100
67
  function terminalStatus(value) {
101
68
  if (value === "completed" ||
102
69
  value === "partial" ||
@@ -110,15 +77,12 @@ function terminalStatus(value) {
110
77
  export function readTaskCompletion(value) {
111
78
  try {
112
79
  const source = object(value);
113
- if (field(source, "version") !== 1)
80
+ if (field(source, "version") !== 2)
114
81
  return undefined;
115
82
  const taskId = field(source, "taskId");
116
83
  const kind = field(source, "kind");
117
84
  if (typeof kind !== "string" || !/^[a-z][a-z0-9-]{0,63}$/.test(kind))
118
85
  return undefined;
119
- const format = field(source, "format");
120
- if (format !== "log" && format !== "report")
121
- return undefined;
122
86
  if (typeof taskId !== "string" ||
123
87
  !taskId.startsWith(`${kind}-`) ||
124
88
  taskId.length <= kind.length + 1 ||
@@ -135,55 +99,36 @@ export function readTaskCompletion(value) {
135
99
  !Number.isSafeInteger(endedAt) ||
136
100
  endedAt < startedAt)
137
101
  return undefined;
138
- const common = {
139
- version: 1,
102
+ const command = field(source, "command");
103
+ const outputPath = field(source, "outputPath");
104
+ const exitCode = field(source, "exitCode");
105
+ if (exitCode !== undefined &&
106
+ exitCode !== null &&
107
+ (typeof exitCode !== "number" || !Number.isSafeInteger(exitCode)))
108
+ return undefined;
109
+ // A clipped path would name a different file. Omit oversized paths intact.
110
+ if (outputPath !== undefined && typeof outputPath !== "string")
111
+ return undefined;
112
+ const snapshot = {
113
+ version: 2,
114
+ kind,
140
115
  taskId,
141
116
  title: string(field(source, "title"), TASK_TITLE_BYTES),
142
117
  status: terminalStatus(field(source, "status")),
143
118
  startedAt,
144
119
  endedAt,
145
120
  error: optionalString(source, "error", 4096),
146
- nextStep: optionalString(source, "nextStep", 2048),
121
+ command: command === undefined ? undefined : text(command, 8192),
122
+ cwd: optionalString(source, "cwd", 4096),
123
+ outputPath: outputPath &&
124
+ !outputPath.includes("\0") &&
125
+ outputPath.length <= 8192 &&
126
+ Buffer.byteLength(JSON.stringify(outputPath)) <= 8192
127
+ ? outputPath
128
+ : undefined,
129
+ ...(exitCode !== undefined ? { exitCode } : {}),
130
+ output: text(field(source, "output"), OUTPUT_BYTES),
147
131
  };
148
- let snapshot;
149
- if (format === "log") {
150
- const command = field(source, "command");
151
- const outputPath = field(source, "outputPath");
152
- const exitCode = field(source, "exitCode");
153
- if (exitCode !== undefined &&
154
- exitCode !== null &&
155
- (typeof exitCode !== "number" || !Number.isSafeInteger(exitCode)))
156
- return undefined;
157
- // A clipped path would name a different file. Omit oversized paths intact.
158
- if (outputPath !== undefined && typeof outputPath !== "string")
159
- return undefined;
160
- snapshot = {
161
- ...common,
162
- kind,
163
- format,
164
- shell: optionalString(source, "shell", 128),
165
- command: command === undefined ? undefined : text(command, 8192),
166
- cwd: optionalString(source, "cwd", 4096),
167
- ...(exitCode !== undefined ? { exitCode } : {}),
168
- outputPath: outputPath &&
169
- !outputPath.includes("\0") &&
170
- outputPath.length <= 8192 &&
171
- Buffer.byteLength(JSON.stringify(outputPath)) <= 8192
172
- ? outputPath
173
- : undefined,
174
- output: text(field(source, "output"), OUTPUT_BYTES),
175
- };
176
- }
177
- else {
178
- const output = field(source, "output");
179
- snapshot = {
180
- ...common,
181
- kind,
182
- format,
183
- items: items(field(source, "items"), itemReport),
184
- output: output === undefined ? undefined : text(output, OUTPUT_BYTES),
185
- };
186
- }
187
132
  return Buffer.byteLength(JSON.stringify(snapshot)) <= TASK_DETAILS_BYTES ? snapshot : undefined;
188
133
  }
189
134
  catch {
@@ -191,48 +136,28 @@ export function readTaskCompletion(value) {
191
136
  }
192
137
  }
193
138
  export function taskCompletionSnapshot(task) {
194
- const output = {
195
- text: task.result?.content
196
- .filter((block) => block.type === "text")
197
- .map((block) => block.text)
198
- .join("\n") ||
199
- task.projection?.text ||
200
- "",
201
- truncated: task.resultTruncated ?? false,
202
- };
203
- const common = {
204
- version: 1,
139
+ const result = task.result?.content
140
+ .filter((block) => block.type === "text")
141
+ .map((block) => block.text)
142
+ .join("\n") ?? "";
143
+ const output = tail(result, OUTPUT_BYTES);
144
+ const snapshot = readTaskCompletion({
145
+ version: 2,
146
+ kind: task.kind,
205
147
  taskId: task.id,
206
148
  title: task.title,
207
149
  status: task.status,
208
150
  startedAt: task.startedAt,
209
151
  endedAt: task.endedAt,
210
152
  error: task.error,
211
- nextStep: task.projection?.nextStep,
212
- };
213
- const snapshot = readTaskCompletion(task.format === "log"
214
- ? {
215
- ...common,
216
- kind: task.kind,
217
- format: "log",
218
- shell: task.projection?.shell?.name,
219
- command: task.command === undefined
220
- ? undefined
221
- : { text: task.command, truncated: task.commandTruncated ?? false },
222
- cwd: task.cwd,
223
- outputPath: task.outputPath,
224
- ...(task.exitCode !== undefined ? { exitCode: task.exitCode } : {}),
225
- output: task.projection?.shell?.output ?? output,
226
- }
227
- : {
228
- ...common,
229
- kind: task.kind,
230
- format: "report",
231
- items: task.projection?.items ?? [],
232
- output: task.projection?.items?.length ? undefined : output,
233
- });
153
+ command: task.command === undefined ? undefined : { text: task.command, truncated: task.commandTruncated ?? false },
154
+ cwd: task.cwd,
155
+ outputPath: task.outputPath,
156
+ ...(task.exitCode !== undefined ? { exitCode: task.exitCode } : {}),
157
+ output: { text: output.text, truncated: output.truncated || (task.resultTruncated ?? false) },
158
+ });
234
159
  if (!snapshot)
235
- throw new Error("Invalid background completion snapshot");
160
+ throw new Error("Invalid task completion snapshot");
236
161
  return snapshot;
237
162
  }
238
163
  const singleLine = (value) => value.replace(/\s+/gu, " ").trim();
@@ -244,19 +169,25 @@ function modelText(value, bytes, lines) {
244
169
  });
245
170
  return result.content + (value.truncated || result.truncated ? OMISSION : "");
246
171
  }
172
+ const EARLIER_OMISSION = "[Earlier output truncated; use tasks read for retained task details.]\n";
173
+ /** Output keeps its end, where the outcome is. */
174
+ function modelTail(value, bytes, lines) {
175
+ const result = truncateTail(value.text, {
176
+ maxBytes: Math.max(0, bytes - Buffer.byteLength(EARLIER_OMISSION)),
177
+ maxLines: Math.max(1, lines - 1),
178
+ });
179
+ return (value.truncated || result.truncated ? EARLIER_OMISSION : "") + result.content;
180
+ }
247
181
  /** One bounded action hint per terminal outcome; completed work needs none. */
248
- function nextStepLine(snapshot) {
249
- switch (snapshot.status) {
182
+ function nextStepLine(status) {
183
+ switch (status) {
250
184
  case "cancelled":
251
185
  return "Next step: the task was cancelled — do not restart it unless the user asks.";
252
186
  case "timeout":
253
187
  return "Next step: the task hit its timeout; inspect the partial output above, then rerun with a longer timeout or in smaller pieces if still needed.";
254
188
  case "failed":
255
- case "partial": {
256
- if (snapshot.nextStep)
257
- return snapshot.nextStep;
189
+ case "partial":
258
190
  return "Next step: diagnose from the output above before retrying; rerun only what is still needed.";
259
- }
260
191
  default:
261
192
  return "";
262
193
  }
@@ -264,40 +195,22 @@ function nextStepLine(snapshot) {
264
195
  /** The context and the card share facts; only the context receives this prose projection. */
265
196
  function notificationText(snapshot) {
266
197
  const header = [
267
- `Background ${snapshot.kind} ${snapshot.taskId}: ${snapshot.status} — ${singleLine(snapshot.title)}`,
198
+ `Background ${snapshot.kind} ${snapshot.taskId}: ${snapshot.status}${snapshot.command ? "" : ` — ${singleLine(snapshot.title)}`}`,
268
199
  snapshot.error ? `Error: ${singleLine(snapshot.error)}` : "",
269
200
  ].filter(Boolean);
270
- if (snapshot.format === "log") {
271
- if (snapshot.command)
272
- header.push(`Command:\n${modelText(snapshot.command, 8192, 128)}`);
273
- if (snapshot.cwd)
274
- header.push(`cwd: ${singleLine(snapshot.cwd)}`);
275
- if (snapshot.outputPath)
276
- header.push(`Output: ${singleLine(snapshot.outputPath)}`);
277
- }
201
+ if (snapshot.command)
202
+ header.push(`Command:\n${modelText(snapshot.command, 8192, 128)}`);
203
+ if (snapshot.cwd)
204
+ header.push(`cwd: ${singleLine(snapshot.cwd)}`);
205
+ if (snapshot.outputPath)
206
+ header.push(`Output: ${singleLine(snapshot.outputPath)}`);
278
207
  const prefix = `${header.join("\n")}\n\n`;
279
- const guidance = nextStepLine(snapshot);
208
+ const guidance = nextStepLine(snapshot.status);
280
209
  const suffix = guidance ? `\n\n${guidance}` : "";
281
210
  const remaining = TASK_RESULT_BYTES - Buffer.byteLength(prefix) - Buffer.byteLength(suffix);
282
211
  const lines = MODEL_LINES - prefix.split("\n").length - (guidance ? 3 : 0);
283
- if (snapshot.format === "report" && snapshot.items.length) {
284
- // Allocate before formatting, so one verbose report cannot erase later items.
285
- const budget = Math.floor((remaining - 8 * snapshot.items.length) / snapshot.items.length);
286
- const lineBudget = Math.floor((lines - 4 * snapshot.items.length) / snapshot.items.length);
287
- return (prefix +
288
- snapshot.items
289
- .map((worker, index) => {
290
- const heading = `### ${index + 1}. ${singleLine(worker.description)} (${singleLine(worker.category)}) — ${singleLine(worker.status)}\n\n`;
291
- const reason = worker.error ? `Error: ${singleLine(worker.error)}\n\n` : "";
292
- const body = worker.report.text
293
- ? worker.report
294
- : { text: "No report returned.", truncated: worker.report.truncated };
295
- return heading + reason + modelText(body, budget - Buffer.byteLength(heading + reason), lineBudget);
296
- })
297
- .join("\n\n---\n\n") +
298
- suffix);
299
- }
300
- return (prefix + modelText(snapshot.output ?? { text: "No text result.", truncated: false }, remaining, lines) + suffix);
212
+ const output = snapshot.output.text ? snapshot.output : { text: "No text result.", truncated: false };
213
+ return prefix + modelTail(output, remaining, lines) + suffix;
301
214
  }
302
215
  export function taskCompletionMessage(task) {
303
216
  const details = taskCompletionSnapshot(task);