@astralyn/pi 0.99.0 → 1.0.1

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 (569) hide show
  1. package/CHANGELOG.md +58 -3
  2. package/dist/bundle/chunks/anthropic-messages-YET4T7BO.js +6 -0
  3. package/dist/bundle/chunks/anthropic.js +2 -2
  4. package/dist/bundle/chunks/azure-openai-responses-SBLL5YN3.js +2 -0
  5. package/dist/bundle/chunks/bedrock-converse-stream.js +3 -3
  6. package/dist/bundle/chunks/chunk-4TT2QGFL.js +2 -0
  7. package/dist/bundle/chunks/chunk-GIG5IHES.js +2 -0
  8. package/dist/bundle/chunks/{chunk-VW2P3X6P.js → chunk-H2N2THAO.js} +436 -668
  9. package/dist/bundle/chunks/{chunk-A576H74Y.js → chunk-IZ3S3GDX.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-ABVRAYXT.js → chunk-NY3CWK44.js} +2 -2
  11. package/dist/bundle/chunks/chunk-SVJ7OGEB.js +2 -0
  12. package/dist/bundle/chunks/chunk-TRHTWM3C.js +2 -0
  13. package/dist/bundle/chunks/{chunk-DEWXBB6W.js → chunk-V66VGGOM.js} +1 -1
  14. package/dist/bundle/chunks/chunk-XDYM2567.js +20 -0
  15. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-ZYSAFXXL.js → cloudflare-workers-ai-system-one-QI46LUZ6.js} +1 -1
  16. package/dist/bundle/chunks/codemode-worker.js +90 -10
  17. package/dist/bundle/chunks/github-copilot.js +1 -1
  18. package/dist/bundle/chunks/{google-generative-ai-SDNQVVXA.js → google-generative-ai-YTZCSHQN.js} +1 -1
  19. package/dist/bundle/chunks/{google-vertex-LZXOLBIO.js → google-vertex-OTFZJJXQ.js} +1 -1
  20. package/dist/bundle/chunks/{llama-cpp-classify-7IYGGPND.js → llama-cpp-classify-R7DQLTQN.js} +1 -1
  21. package/dist/bundle/chunks/{mistral-conversations-VYKPSSAM.js → mistral-conversations-ELH4V4TY.js} +1 -1
  22. package/dist/bundle/chunks/node-USQQ7C6M.js +16 -0
  23. package/dist/bundle/chunks/openai-chatgpt.js +2 -2
  24. package/dist/bundle/chunks/{openai-codex-responses-HZ4VUDXD.js → openai-codex-responses-OLVTU4UA.js} +1 -1
  25. package/dist/bundle/chunks/openai-codex.js +1 -1
  26. package/dist/bundle/chunks/openai-completions-53M2KJ67.js +7 -0
  27. package/dist/bundle/chunks/openai-responses-4ABDEL4Z.js +3 -0
  28. package/dist/bundle/chunks/{openrouter-images-5524IQHX.js → openrouter-images-YP3YVB54.js} +1 -1
  29. package/dist/bundle/chunks/openrouter.js +1 -1
  30. package/dist/bundle/chunks/radius.js +1 -1
  31. package/dist/bundle/chunks/{typesafe-system-one-Z2CDLKEY.js → typesafe-system-one-RREJAKWB.js} +1 -1
  32. package/dist/bundle/chunks/virtual-modules-YFKU7JZF.js +2 -0
  33. package/dist/bundle/cli.js +1 -1
  34. package/dist/bundle/index.js +1 -1
  35. package/dist/bundle/rpc-entry.js +1 -1
  36. package/dist/cli/args.d.ts.map +1 -1
  37. package/dist/cli/args.js +5 -2
  38. package/dist/cli/args.js.map +1 -1
  39. package/dist/config.d.ts +5 -8
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js +19 -13
  42. package/dist/config.js.map +1 -1
  43. package/dist/core/agent-session.d.ts +21 -1
  44. package/dist/core/agent-session.d.ts.map +1 -1
  45. package/dist/core/agent-session.js +65 -12
  46. package/dist/core/agent-session.js.map +1 -1
  47. package/dist/core/export-html/tool-renderer.d.ts +3 -3
  48. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  49. package/dist/core/export-html/tool-renderer.js +3 -3
  50. package/dist/core/export-html/tool-renderer.js.map +1 -1
  51. package/dist/core/extensions/index.d.ts +2 -2
  52. package/dist/core/extensions/index.d.ts.map +1 -1
  53. package/dist/core/extensions/index.js.map +1 -1
  54. package/dist/core/extensions/loader.d.ts.map +1 -1
  55. package/dist/core/extensions/loader.js +18 -1
  56. package/dist/core/extensions/loader.js.map +1 -1
  57. package/dist/core/extensions/runner.d.ts +3 -1
  58. package/dist/core/extensions/runner.d.ts.map +1 -1
  59. package/dist/core/extensions/runner.js +6 -0
  60. package/dist/core/extensions/runner.js.map +1 -1
  61. package/dist/core/extensions/types.d.ts +15 -1
  62. package/dist/core/extensions/types.d.ts.map +1 -1
  63. package/dist/core/extensions/types.js.map +1 -1
  64. package/dist/core/keybindings.d.ts +51 -11
  65. package/dist/core/keybindings.d.ts.map +1 -1
  66. package/dist/core/keybindings.js +11 -3
  67. package/dist/core/keybindings.js.map +1 -1
  68. package/dist/core/mcp-servers.d.ts +40 -7
  69. package/dist/core/mcp-servers.d.ts.map +1 -1
  70. package/dist/core/mcp-servers.js +63 -11
  71. package/dist/core/mcp-servers.js.map +1 -1
  72. package/dist/core/model-config.d.ts +36 -0
  73. package/dist/core/model-config.d.ts.map +1 -1
  74. package/dist/core/model-config.js +14 -2
  75. package/dist/core/model-config.js.map +1 -1
  76. package/dist/core/model-registry.d.ts +3 -1
  77. package/dist/core/model-registry.d.ts.map +1 -1
  78. package/dist/core/model-registry.js +4 -0
  79. package/dist/core/model-registry.js.map +1 -1
  80. package/dist/core/model-resolver.js +1 -1
  81. package/dist/core/model-resolver.js.map +1 -1
  82. package/dist/core/model-runtime.d.ts +6 -0
  83. package/dist/core/model-runtime.d.ts.map +1 -1
  84. package/dist/core/model-runtime.js +22 -18
  85. package/dist/core/model-runtime.js.map +1 -1
  86. package/dist/core/provider-composer.d.ts +2 -1
  87. package/dist/core/provider-composer.d.ts.map +1 -1
  88. package/dist/core/provider-composer.js +13 -0
  89. package/dist/core/provider-composer.js.map +1 -1
  90. package/dist/core/radius.d.ts +2 -0
  91. package/dist/core/radius.d.ts.map +1 -1
  92. package/dist/core/radius.js +2 -0
  93. package/dist/core/radius.js.map +1 -1
  94. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  95. package/dist/core/remote-catalog-provider.js +4 -9
  96. package/dist/core/remote-catalog-provider.js.map +1 -1
  97. package/dist/core/sdk.d.ts.map +1 -1
  98. package/dist/core/sdk.js +1 -0
  99. package/dist/core/sdk.js.map +1 -1
  100. package/dist/core/settings-manager.d.ts +7 -5
  101. package/dist/core/settings-manager.d.ts.map +1 -1
  102. package/dist/core/settings-manager.js +2 -1
  103. package/dist/core/settings-manager.js.map +1 -1
  104. package/dist/core/system-prompt.js +1 -1
  105. package/dist/core/system-prompt.js.map +1 -1
  106. package/dist/core/tasks/format.d.ts +7 -0
  107. package/dist/core/tasks/format.d.ts.map +1 -0
  108. package/dist/core/tasks/format.js +14 -0
  109. package/dist/core/tasks/format.js.map +1 -0
  110. package/dist/core/tasks/history.d.ts.map +1 -1
  111. package/dist/core/tasks/history.js +0 -19
  112. package/dist/core/tasks/history.js.map +1 -1
  113. package/dist/core/tasks/output.d.ts +8 -0
  114. package/dist/core/tasks/output.d.ts.map +1 -1
  115. package/dist/core/tasks/output.js +19 -0
  116. package/dist/core/tasks/output.js.map +1 -1
  117. package/dist/core/tasks/presentation.d.ts +1 -3
  118. package/dist/core/tasks/presentation.d.ts.map +1 -1
  119. package/dist/core/tasks/presentation.js +79 -166
  120. package/dist/core/tasks/presentation.js.map +1 -1
  121. package/dist/core/tasks/runtime.d.ts +16 -9
  122. package/dist/core/tasks/runtime.d.ts.map +1 -1
  123. package/dist/core/tasks/runtime.js +89 -106
  124. package/dist/core/tasks/runtime.js.map +1 -1
  125. package/dist/core/tasks/session.d.ts.map +1 -1
  126. package/dist/core/tasks/session.js +13 -4
  127. package/dist/core/tasks/session.js.map +1 -1
  128. package/dist/core/tasks/store.d.ts +20 -6
  129. package/dist/core/tasks/store.d.ts.map +1 -1
  130. package/dist/core/tasks/store.js +45 -18
  131. package/dist/core/tasks/store.js.map +1 -1
  132. package/dist/core/tasks/types.d.ts +14 -54
  133. package/dist/core/tasks/types.d.ts.map +1 -1
  134. package/dist/core/tasks/types.js +1 -5
  135. package/dist/core/tasks/types.js.map +1 -1
  136. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  137. package/dist/core/tools/renderers/bash.js +11 -34
  138. package/dist/core/tools/renderers/bash.js.map +1 -1
  139. package/dist/core/tools/renderers/index.d.ts +2 -2
  140. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  141. package/dist/core/tools/renderers/index.js.map +1 -1
  142. package/dist/core/tools/shell-execution.d.ts +0 -1
  143. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  144. package/dist/core/tools/shell-execution.js +3 -10
  145. package/dist/core/tools/shell-execution.js.map +1 -1
  146. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  147. package/dist/core/tools/shell-tool.js +2 -4
  148. package/dist/core/tools/shell-tool.js.map +1 -1
  149. package/dist/core/tools/tasks/actions.d.ts +1 -1
  150. package/dist/core/tools/tasks/actions.d.ts.map +1 -1
  151. package/dist/core/tools/tasks/actions.js +26 -12
  152. package/dist/core/tools/tasks/actions.js.map +1 -1
  153. package/dist/core/tools/tasks/constants.d.ts +2 -6
  154. package/dist/core/tools/tasks/constants.d.ts.map +1 -1
  155. package/dist/core/tools/tasks/constants.js +2 -6
  156. package/dist/core/tools/tasks/constants.js.map +1 -1
  157. package/dist/core/tools/tasks/schema.d.ts +1 -1
  158. package/dist/core/tools/tasks/schema.d.ts.map +1 -1
  159. package/dist/core/tools/tasks/schema.js +8 -7
  160. package/dist/core/tools/tasks/schema.js.map +1 -1
  161. package/dist/core/tools/tasks/types.d.ts +8 -38
  162. package/dist/core/tools/tasks/types.d.ts.map +1 -1
  163. package/dist/core/tools/tasks/types.js +6 -11
  164. package/dist/core/tools/tasks/types.js.map +1 -1
  165. package/dist/core/virtual-models.d.ts +2 -0
  166. package/dist/core/virtual-models.d.ts.map +1 -1
  167. package/dist/core/virtual-models.js +19 -12
  168. package/dist/core/virtual-models.js.map +1 -1
  169. package/dist/extensions/btw/agent.d.ts +17 -8
  170. package/dist/extensions/btw/agent.d.ts.map +1 -1
  171. package/dist/extensions/btw/agent.js +74 -76
  172. package/dist/extensions/btw/agent.js.map +1 -1
  173. package/dist/extensions/btw/controller.d.ts +0 -1
  174. package/dist/extensions/btw/controller.d.ts.map +1 -1
  175. package/dist/extensions/btw/controller.js +26 -33
  176. package/dist/extensions/btw/controller.js.map +1 -1
  177. package/dist/extensions/btw/panel.d.ts +13 -14
  178. package/dist/extensions/btw/panel.d.ts.map +1 -1
  179. package/dist/extensions/btw/panel.js +38 -29
  180. package/dist/extensions/btw/panel.js.map +1 -1
  181. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  182. package/dist/extensions/codemode/execute.js +197 -51
  183. package/dist/extensions/codemode/execute.js.map +1 -1
  184. package/dist/extensions/codemode/renderer.d.ts.map +1 -1
  185. package/dist/extensions/codemode/renderer.js +43 -25
  186. package/dist/extensions/codemode/renderer.js.map +1 -1
  187. package/dist/extensions/codemode/tool.d.ts +12 -11
  188. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  189. package/dist/extensions/codemode/tool.js +73 -129
  190. package/dist/extensions/codemode/tool.js.map +1 -1
  191. package/dist/extensions/codemode/worker.d.ts +1 -1
  192. package/dist/extensions/codemode/worker.js +1 -1
  193. package/dist/extensions/codemode/worker.js.map +1 -1
  194. package/dist/extensions/deepwiki/schema.d.ts +1 -1
  195. package/dist/extensions/index.d.ts.map +1 -1
  196. package/dist/extensions/index.js +0 -2
  197. package/dist/extensions/index.js.map +1 -1
  198. package/dist/extensions/mcp/cli.d.ts.map +1 -1
  199. package/dist/extensions/mcp/cli.js +23 -5
  200. package/dist/extensions/mcp/cli.js.map +1 -1
  201. package/dist/extensions/mcp/config.d.ts +19 -5
  202. package/dist/extensions/mcp/config.d.ts.map +1 -1
  203. package/dist/extensions/mcp/config.js +60 -12
  204. package/dist/extensions/mcp/config.js.map +1 -1
  205. package/dist/extensions/mcp/index.d.ts +36 -9
  206. package/dist/extensions/mcp/index.d.ts.map +1 -1
  207. package/dist/extensions/mcp/index.js +309 -100
  208. package/dist/extensions/mcp/index.js.map +1 -1
  209. package/dist/extensions/mcp/oauth.d.ts +14 -8
  210. package/dist/extensions/mcp/oauth.d.ts.map +1 -1
  211. package/dist/extensions/mcp/oauth.js +105 -36
  212. package/dist/extensions/mcp/oauth.js.map +1 -1
  213. package/dist/extensions/mcp/runtime.d.ts +2 -0
  214. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  215. package/dist/extensions/mcp/runtime.js +17 -9
  216. package/dist/extensions/mcp/runtime.js.map +1 -1
  217. package/dist/extensions/mcp/tools.d.ts +8 -5
  218. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  219. package/dist/extensions/mcp/tools.js +50 -26
  220. package/dist/extensions/mcp/tools.js.map +1 -1
  221. package/dist/extensions/mcp/ui.d.ts.map +1 -1
  222. package/dist/extensions/mcp/ui.js +7 -1
  223. package/dist/extensions/mcp/ui.js.map +1 -1
  224. package/dist/extensions/provider/catalog.d.ts +8 -1
  225. package/dist/extensions/provider/catalog.d.ts.map +1 -1
  226. package/dist/extensions/provider/catalog.js +31 -0
  227. package/dist/extensions/provider/catalog.js.map +1 -1
  228. package/dist/extensions/provider/connection.d.ts +4 -1
  229. package/dist/extensions/provider/connection.d.ts.map +1 -1
  230. package/dist/extensions/provider/connection.js +1 -5
  231. package/dist/extensions/provider/connection.js.map +1 -1
  232. package/dist/extensions/provider/editing.d.ts +36 -0
  233. package/dist/extensions/provider/editing.d.ts.map +1 -0
  234. package/dist/extensions/provider/editing.js +99 -0
  235. package/dist/extensions/provider/editing.js.map +1 -0
  236. package/dist/extensions/provider/json-fields.d.ts +5 -0
  237. package/dist/extensions/provider/json-fields.d.ts.map +1 -0
  238. package/dist/extensions/provider/json-fields.js +31 -0
  239. package/dist/extensions/provider/json-fields.js.map +1 -0
  240. package/dist/extensions/provider/store.d.ts +1 -4
  241. package/dist/extensions/provider/store.d.ts.map +1 -1
  242. package/dist/extensions/provider/store.js +2 -30
  243. package/dist/extensions/provider/store.js.map +1 -1
  244. package/dist/extensions/provider/ui/builtin-data.d.ts +0 -2
  245. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  246. package/dist/extensions/provider/ui/builtin-data.js +14 -79
  247. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  248. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  249. package/dist/extensions/provider/ui/compat.js +6 -9
  250. package/dist/extensions/provider/ui/compat.js.map +1 -1
  251. package/dist/extensions/provider/ui/controls.d.ts +48 -0
  252. package/dist/extensions/provider/ui/controls.d.ts.map +1 -0
  253. package/dist/extensions/provider/ui/controls.js +108 -0
  254. package/dist/extensions/provider/ui/controls.js.map +1 -0
  255. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  256. package/dist/extensions/provider/ui/dictionary.js +6 -9
  257. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  258. package/dist/extensions/provider/ui/editor.d.ts +3 -3
  259. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  260. package/dist/extensions/provider/ui/editor.js +35 -140
  261. package/dist/extensions/provider/ui/editor.js.map +1 -1
  262. package/dist/extensions/provider/ui/fetch-models.d.ts +0 -3
  263. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  264. package/dist/extensions/provider/ui/fetch-models.js +49 -44
  265. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  266. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  267. package/dist/extensions/provider/ui/model-fields.js +11 -14
  268. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  269. package/dist/extensions/provider/ui/model-options.d.ts +4 -34
  270. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  271. package/dist/extensions/provider/ui/model-options.js +90 -271
  272. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  273. package/dist/extensions/provider/ui/pane.d.ts +4 -18
  274. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  275. package/dist/extensions/provider/ui/pane.js.map +1 -1
  276. package/dist/extensions/provider/ui/provider-fields.d.ts +2 -19
  277. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  278. package/dist/extensions/provider/ui/provider-fields.js +58 -171
  279. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  280. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  281. package/dist/extensions/provider/ui/thinking-map.js +6 -9
  282. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  283. package/dist/extensions/question/detail-pane.d.ts +7 -2
  284. package/dist/extensions/question/detail-pane.d.ts.map +1 -1
  285. package/dist/extensions/question/detail-pane.js +16 -5
  286. package/dist/extensions/question/detail-pane.js.map +1 -1
  287. package/dist/extensions/question/dialog-view.d.ts +41 -0
  288. package/dist/extensions/question/dialog-view.d.ts.map +1 -0
  289. package/dist/extensions/question/dialog-view.js +329 -0
  290. package/dist/extensions/question/dialog-view.js.map +1 -0
  291. package/dist/extensions/question/dialog.d.ts +3 -3
  292. package/dist/extensions/question/dialog.d.ts.map +1 -1
  293. package/dist/extensions/question/dialog.js +220 -634
  294. package/dist/extensions/question/dialog.js.map +1 -1
  295. package/dist/extensions/question/index.d.ts.map +1 -1
  296. package/dist/extensions/question/index.js +2 -3
  297. package/dist/extensions/question/index.js.map +1 -1
  298. package/dist/extensions/question/render.d.ts.map +1 -1
  299. package/dist/extensions/question/render.js +22 -32
  300. package/dist/extensions/question/render.js.map +1 -1
  301. package/dist/extensions/question/results.d.ts.map +1 -1
  302. package/dist/extensions/question/results.js +56 -12
  303. package/dist/extensions/question/results.js.map +1 -1
  304. package/dist/extensions/question/schema.d.ts +21 -6
  305. package/dist/extensions/question/schema.d.ts.map +1 -1
  306. package/dist/extensions/question/schema.js.map +1 -1
  307. package/dist/extensions/question/state.d.ts +9 -7
  308. package/dist/extensions/question/state.d.ts.map +1 -1
  309. package/dist/extensions/question/state.js +63 -54
  310. package/dist/extensions/question/state.js.map +1 -1
  311. package/dist/extensions/question/types.d.ts +41 -18
  312. package/dist/extensions/question/types.d.ts.map +1 -1
  313. package/dist/extensions/question/types.js.map +1 -1
  314. package/dist/extensions/statusline/index.d.ts +4 -0
  315. package/dist/extensions/statusline/index.d.ts.map +1 -1
  316. package/dist/extensions/statusline/index.js +18 -355
  317. package/dist/extensions/statusline/index.js.map +1 -1
  318. package/dist/extensions/statusline/render.d.ts +19 -0
  319. package/dist/extensions/statusline/render.d.ts.map +1 -0
  320. package/dist/extensions/statusline/render.js +163 -0
  321. package/dist/extensions/statusline/render.js.map +1 -0
  322. package/dist/extensions/statusline/usage.d.ts +12 -0
  323. package/dist/extensions/statusline/usage.d.ts.map +1 -0
  324. package/dist/extensions/statusline/usage.js +36 -0
  325. package/dist/extensions/statusline/usage.js.map +1 -0
  326. package/dist/extensions/tool-search/tool.d.ts +5 -4
  327. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  328. package/dist/extensions/tool-search/tool.js +7 -28
  329. package/dist/extensions/tool-search/tool.js.map +1 -1
  330. package/dist/extensions/web-search/execute.d.ts +1 -5
  331. package/dist/extensions/web-search/execute.d.ts.map +1 -1
  332. package/dist/extensions/web-search/execute.js +4 -9
  333. package/dist/extensions/web-search/execute.js.map +1 -1
  334. package/dist/extensions/web-search/format.d.ts +12 -3
  335. package/dist/extensions/web-search/format.d.ts.map +1 -1
  336. package/dist/extensions/web-search/format.js +33 -25
  337. package/dist/extensions/web-search/format.js.map +1 -1
  338. package/dist/extensions/web-search/index.d.ts.map +1 -1
  339. package/dist/extensions/web-search/index.js +6 -29
  340. package/dist/extensions/web-search/index.js.map +1 -1
  341. package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -1
  342. package/dist/extensions/web-search/providers/deepseek.js +0 -1
  343. package/dist/extensions/web-search/providers/deepseek.js.map +1 -1
  344. package/dist/extensions/web-search/providers/http.d.ts +1 -1
  345. package/dist/extensions/web-search/providers/http.d.ts.map +1 -1
  346. package/dist/extensions/web-search/providers/http.js.map +1 -1
  347. package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -1
  348. package/dist/extensions/web-search/providers/minimax.js +0 -1
  349. package/dist/extensions/web-search/providers/minimax.js.map +1 -1
  350. package/dist/extensions/web-search/render.d.ts +7 -2
  351. package/dist/extensions/web-search/render.d.ts.map +1 -1
  352. package/dist/extensions/web-search/render.js +32 -4
  353. package/dist/extensions/web-search/render.js.map +1 -1
  354. package/dist/extensions/web-search/results.d.ts.map +1 -1
  355. package/dist/extensions/web-search/results.js +3 -8
  356. package/dist/extensions/web-search/results.js.map +1 -1
  357. package/dist/extensions/web-search/types.d.ts +4 -2
  358. package/dist/extensions/web-search/types.d.ts.map +1 -1
  359. package/dist/extensions/web-search/types.js.map +1 -1
  360. package/dist/index.d.ts +3 -5
  361. package/dist/index.d.ts.map +1 -1
  362. package/dist/index.js +0 -1
  363. package/dist/index.js.map +1 -1
  364. package/dist/main.d.ts.map +1 -1
  365. package/dist/main.js +6 -0
  366. package/dist/main.js.map +1 -1
  367. package/dist/modes/interactive/components/armin.d.ts +3 -0
  368. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  369. package/dist/modes/interactive/components/armin.js +7 -5
  370. package/dist/modes/interactive/components/armin.js.map +1 -1
  371. package/dist/modes/interactive/components/auth-url.d.ts +14 -0
  372. package/dist/modes/interactive/components/auth-url.d.ts.map +1 -0
  373. package/dist/modes/interactive/components/auth-url.js +34 -0
  374. package/dist/modes/interactive/components/auth-url.js.map +1 -0
  375. package/dist/modes/interactive/components/easter-egg-3d.d.ts +104 -0
  376. package/dist/modes/interactive/components/easter-egg-3d.d.ts.map +1 -0
  377. package/dist/modes/interactive/components/easter-egg-3d.js +1123 -0
  378. package/dist/modes/interactive/components/easter-egg-3d.js.map +1 -0
  379. package/dist/modes/interactive/components/easter-egg-3d.lazy.d.ts +6 -0
  380. package/dist/modes/interactive/components/easter-egg-3d.lazy.d.ts.map +1 -0
  381. package/dist/modes/interactive/components/easter-egg-3d.lazy.js +24 -0
  382. package/dist/modes/interactive/components/easter-egg-3d.lazy.js.map +1 -0
  383. package/dist/modes/interactive/components/index.d.ts +0 -1
  384. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  385. package/dist/modes/interactive/components/index.js +0 -1
  386. package/dist/modes/interactive/components/index.js.map +1 -1
  387. package/dist/modes/interactive/components/login-dialog.d.ts +2 -0
  388. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  389. package/dist/modes/interactive/components/login-dialog.js +9 -5
  390. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  391. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  392. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  393. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  394. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  395. package/dist/modes/interactive/components/pi-logo.d.ts +7 -0
  396. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/pi-logo.js +13 -1
  398. package/dist/modes/interactive/components/pi-logo.js.map +1 -1
  399. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  400. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  401. package/dist/modes/interactive/components/radius-login-selector.js +83 -0
  402. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  403. package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
  404. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  405. package/dist/modes/interactive/components/settings-selector.js +5 -5
  406. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  407. package/dist/modes/interactive/components/status-marker.d.ts +0 -2
  408. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  409. package/dist/modes/interactive/components/status-marker.js +0 -4
  410. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  411. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  412. package/dist/modes/interactive/components/user-message.js +5 -4
  413. package/dist/modes/interactive/components/user-message.js.map +1 -1
  414. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  415. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  416. package/dist/modes/interactive/components/visual-truncate.js +36 -6
  417. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  418. package/dist/modes/interactive/interactive-mode.d.ts +12 -2
  419. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  420. package/dist/modes/interactive/interactive-mode.js +180 -55
  421. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  422. package/dist/modes/interactive/tasks/completion-render.d.ts +1 -1
  423. package/dist/modes/interactive/tasks/completion-render.d.ts.map +1 -1
  424. package/dist/modes/interactive/tasks/completion-render.js +28 -82
  425. package/dist/modes/interactive/tasks/completion-render.js.map +1 -1
  426. package/dist/modes/interactive/tasks/index.d.ts.map +1 -1
  427. package/dist/modes/interactive/tasks/index.js +18 -13
  428. package/dist/modes/interactive/tasks/index.js.map +1 -1
  429. package/dist/modes/interactive/tasks/inspector.d.ts +35 -0
  430. package/dist/modes/interactive/tasks/inspector.d.ts.map +1 -0
  431. package/dist/modes/interactive/tasks/inspector.js +93 -0
  432. package/dist/modes/interactive/tasks/inspector.js.map +1 -0
  433. package/dist/modes/interactive/tasks/layout.d.ts +40 -0
  434. package/dist/modes/interactive/tasks/layout.d.ts.map +1 -0
  435. package/dist/modes/interactive/tasks/layout.js +212 -0
  436. package/dist/modes/interactive/tasks/layout.js.map +1 -0
  437. package/dist/modes/interactive/tasks/list.d.ts +21 -0
  438. package/dist/modes/interactive/tasks/list.d.ts.map +1 -0
  439. package/dist/modes/interactive/tasks/list.js +96 -0
  440. package/dist/modes/interactive/tasks/list.js.map +1 -0
  441. package/dist/modes/interactive/tasks/manager.d.ts +29 -36
  442. package/dist/modes/interactive/tasks/manager.d.ts.map +1 -1
  443. package/dist/modes/interactive/tasks/manager.js +315 -315
  444. package/dist/modes/interactive/tasks/manager.js.map +1 -1
  445. package/dist/modes/interactive/tasks/model.d.ts +21 -0
  446. package/dist/modes/interactive/tasks/model.d.ts.map +1 -0
  447. package/dist/modes/interactive/tasks/model.js +41 -0
  448. package/dist/modes/interactive/tasks/model.js.map +1 -0
  449. package/dist/modes/interactive/tasks/render.d.ts +5 -19
  450. package/dist/modes/interactive/tasks/render.d.ts.map +1 -1
  451. package/dist/modes/interactive/tasks/render.js +18 -102
  452. package/dist/modes/interactive/tasks/render.js.map +1 -1
  453. package/dist/modes/interactive/tasks/task-view.d.ts +8 -48
  454. package/dist/modes/interactive/tasks/task-view.d.ts.map +1 -1
  455. package/dist/modes/interactive/tasks/task-view.js +11 -51
  456. package/dist/modes/interactive/tasks/task-view.js.map +1 -1
  457. package/dist/modes/interactive/tasks/text.d.ts +1 -7
  458. package/dist/modes/interactive/tasks/text.d.ts.map +1 -1
  459. package/dist/modes/interactive/tasks/text.js +6 -29
  460. package/dist/modes/interactive/tasks/text.js.map +1 -1
  461. package/dist/modes/interactive/tasks/viewport.d.ts +2 -0
  462. package/dist/modes/interactive/tasks/viewport.d.ts.map +1 -1
  463. package/dist/modes/interactive/tasks/viewport.js +17 -7
  464. package/dist/modes/interactive/tasks/viewport.js.map +1 -1
  465. package/dist/modes/interactive/tasks/views.d.ts +9 -0
  466. package/dist/modes/interactive/tasks/views.d.ts.map +1 -0
  467. package/dist/modes/interactive/tasks/views.js +42 -0
  468. package/dist/modes/interactive/tasks/views.js.map +1 -0
  469. package/dist/modes/interactive/theme/system-theme.d.ts +2 -1
  470. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
  471. package/dist/modes/interactive/theme/system-theme.js +16 -5
  472. package/dist/modes/interactive/theme/system-theme.js.map +1 -1
  473. package/dist/modes/interactive/tool-view/tool-execution.d.ts +4 -19
  474. package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -1
  475. package/dist/modes/interactive/tool-view/tool-execution.js +23 -67
  476. package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
  477. package/dist/utils/image-convert.d.ts +12 -0
  478. package/dist/utils/image-convert.d.ts.map +1 -1
  479. package/dist/utils/image-convert.js +45 -6
  480. package/dist/utils/image-convert.js.map +1 -1
  481. package/docs/bundled/README.md +0 -1
  482. package/docs/bundled/extensions/question.md +2 -2
  483. package/docs/bundled/extensions/statusline.md +24 -15
  484. package/docs/bundled/tasks.md +34 -48
  485. package/docs/codemode.md +207 -0
  486. package/docs/docs.json +4 -4
  487. package/docs/environment-variables.md +1 -1
  488. package/docs/extensions.md +11 -9
  489. package/docs/keybindings.md +14 -7
  490. package/docs/mcp.md +164 -82
  491. package/docs/models.md +51 -3
  492. package/docs/providers.md +8 -0
  493. package/docs/sdk.md +2 -2
  494. package/docs/session-format.md +12 -22
  495. package/docs/settings.md +4 -2
  496. package/docs/tui.md +1 -1
  497. package/docs/usage.md +6 -16
  498. package/examples/README.md +1 -1
  499. package/examples/extensions/README.md +1 -2
  500. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  501. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  502. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  503. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  504. package/examples/extensions/gondolin/package-lock.json +2 -2
  505. package/examples/extensions/gondolin/package.json +1 -1
  506. package/examples/extensions/minimal-mode.ts +24 -96
  507. package/examples/extensions/sandbox/package-lock.json +2 -2
  508. package/examples/extensions/sandbox/package.json +1 -1
  509. package/examples/extensions/with-deps/package-lock.json +2 -2
  510. package/examples/extensions/with-deps/package.json +1 -1
  511. package/examples/sdk/14-codemode-mcp.ts +2 -2
  512. package/npm-shrinkwrap.json +73 -62
  513. package/package.json +11 -10
  514. package/dist/bundle/chunks/anthropic-messages-KIXY7EDT.js +0 -6
  515. package/dist/bundle/chunks/azure-openai-responses-RPBERDXD.js +0 -2
  516. package/dist/bundle/chunks/chunk-CLLDCO64.js +0 -2
  517. package/dist/bundle/chunks/chunk-PJVFYVHE.js +0 -42
  518. package/dist/bundle/chunks/chunk-UUSTLCVC.js +0 -2
  519. package/dist/bundle/chunks/chunk-VWCWZD6E.js +0 -2
  520. package/dist/bundle/chunks/node-CXWYTK2I.js +0 -16
  521. package/dist/bundle/chunks/openai-completions-SKDGF6OE.js +0 -7
  522. package/dist/bundle/chunks/openai-responses-FPML4SSG.js +0 -3
  523. package/dist/bundle/chunks/virtual-modules-TQRORWJQ.js +0 -2
  524. package/dist/core/tasks/view-data.d.ts +0 -8
  525. package/dist/core/tasks/view-data.d.ts.map +0 -1
  526. package/dist/core/tasks/view-data.js +0 -61
  527. package/dist/core/tasks/view-data.js.map +0 -1
  528. package/dist/core/tasks/view.d.ts +0 -30
  529. package/dist/core/tasks/view.d.ts.map +0 -1
  530. package/dist/core/tasks/view.js +0 -50
  531. package/dist/core/tasks/view.js.map +0 -1
  532. package/dist/core/tools/renderers/shell-task.d.ts +0 -4
  533. package/dist/core/tools/renderers/shell-task.d.ts.map +0 -1
  534. package/dist/core/tools/renderers/shell-task.js +0 -35
  535. package/dist/core/tools/renderers/shell-task.js.map +0 -1
  536. package/dist/extensions/todo/constants.d.ts +0 -16
  537. package/dist/extensions/todo/constants.d.ts.map +0 -1
  538. package/dist/extensions/todo/constants.js +0 -30
  539. package/dist/extensions/todo/constants.js.map +0 -1
  540. package/dist/extensions/todo/index.d.ts +0 -3
  541. package/dist/extensions/todo/index.d.ts.map +0 -1
  542. package/dist/extensions/todo/index.js +0 -98
  543. package/dist/extensions/todo/index.js.map +0 -1
  544. package/dist/extensions/todo/schema.d.ts +0 -60
  545. package/dist/extensions/todo/schema.d.ts.map +0 -1
  546. package/dist/extensions/todo/schema.js +0 -56
  547. package/dist/extensions/todo/schema.js.map +0 -1
  548. package/dist/extensions/todo/state.d.ts +0 -34
  549. package/dist/extensions/todo/state.d.ts.map +0 -1
  550. package/dist/extensions/todo/state.js +0 -425
  551. package/dist/extensions/todo/state.js.map +0 -1
  552. package/dist/extensions/todo/view.d.ts +0 -36
  553. package/dist/extensions/todo/view.d.ts.map +0 -1
  554. package/dist/extensions/todo/view.js +0 -580
  555. package/dist/extensions/todo/view.js.map +0 -1
  556. package/dist/extensions/todo/widget.d.ts +0 -15
  557. package/dist/extensions/todo/widget.d.ts.map +0 -1
  558. package/dist/extensions/todo/widget.js +0 -50
  559. package/dist/extensions/todo/widget.js.map +0 -1
  560. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  561. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  562. package/dist/modes/interactive/components/daxnuts.js +0 -138
  563. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  564. package/dist/modes/interactive/tasks/fallback-view.d.ts +0 -4
  565. package/dist/modes/interactive/tasks/fallback-view.d.ts.map +0 -1
  566. package/dist/modes/interactive/tasks/fallback-view.js +0 -27
  567. package/dist/modes/interactive/tasks/fallback-view.js.map +0 -1
  568. package/docs/bundled/extensions/todo.md +0 -104
  569. package/examples/extensions/todo.ts +0 -297
@@ -1,6 +1,6 @@
1
- /** Management only: execution and delivery belong to the session Background service. */
2
- import { runtimeLabel } from "../../../modes/interactive/tasks/task-view.js";
1
+ /** Management only: execution and delivery belong to the session task runtime. */
3
2
  import { sanitizeBinaryOutput } from "../../../utils/shell.js";
3
+ import { runtimeLabel } from "../../tasks/format.js";
4
4
  import { boundText } from "../../tasks/output.js";
5
5
  import { isTaskTerminal, TaskLookupError, } from "../../tasks/types.js";
6
6
  import { truncateHead } from "../truncate.js";
@@ -52,17 +52,33 @@ function lookupFailure(background, id, error) {
52
52
  return error instanceof Error ? error : new Error(String(error));
53
53
  if (error.kind === "ambiguous") {
54
54
  const lines = error.matches.map((task) => describeTaskLine(task)).join("\n");
55
- return new Error(`Ambiguous background task ID "${id}" matches ${error.matches.length} tasks:\n${lines}`);
55
+ return new Error(`Ambiguous task ID "${id}" matches ${error.matches.length} tasks:\n${lines}`);
56
56
  }
57
57
  const { tasks, foregroundOmitted } = listedTasks(background);
58
58
  const active = tasks.filter((task) => !isTaskTerminal(task.status));
59
59
  const finished = recentFinishedFirst(tasks.filter((task) => isTaskTerminal(task.status)));
60
60
  const shown = [...active, ...finished].slice(0, LOOKUP_LIST_LIMIT);
61
61
  if (shown.length === 0) {
62
- return new Error(`No background task "${id}" in this session. No background tasks in this session.`);
62
+ return new Error(`No task "${id}" in this session. No background tasks in this session.`);
63
63
  }
64
64
  const lines = shown.map((task) => describeTaskLine(task)).join("\n");
65
- return new Error(`No background task "${id}" in this session. IDs from other sessions are not valid here.\nCurrent tasks:\n${lines}${foregroundOmissionNote(foregroundOmitted)}`);
65
+ return new Error(`No task "${id}" in this session. IDs from other sessions are not valid here.\nCurrent background tasks:\n${lines}${foregroundOmissionNote(foregroundOmitted)}`);
66
+ }
67
+ /**
68
+ * Where this slice sits in the output, so the next wait can continue from it.
69
+ * A wait whose new output exceeds its budget returns the newest bytes and says what it skipped.
70
+ */
71
+ function rangeText(slice, sinceBytes) {
72
+ const from = slice.fromByte ?? 0;
73
+ const to = from + Buffer.byteLength(slice.text);
74
+ const floor = sinceBytes === undefined || sinceBytes > slice.totalBytes ? 0 : sinceBytes;
75
+ return [
76
+ `bytes ${from}–${to} of ${slice.totalBytes}`,
77
+ sinceBytes !== undefined && from > floor ? `skipped ${from - floor} bytes after sinceBytes ${floor}` : "",
78
+ `next sinceBytes ${to}`,
79
+ ]
80
+ .filter(Boolean)
81
+ .join(" · ");
66
82
  }
67
83
  /** Reserve space for each independent diagnostic before allowing raw output to fill the budget. */
68
84
  function readText(header, slice) {
@@ -82,7 +98,7 @@ export async function runRead(background, input) {
82
98
  try {
83
99
  const mode = input.mode ?? "tail";
84
100
  const slice = await background.read(id, { mode, bytes: clampReadBytes(input.bytes) });
85
- return result(readText(`[${describeTaskLine(slice.task)} · ${slice.totalBytes} bytes${slice.truncated ? " · truncated" : ""}]`, slice), {
101
+ return result(readText(`[${describeTaskLine(slice.task)} · ${rangeText(slice)}]`, slice), {
86
102
  action: "read",
87
103
  taskId: slice.task.id,
88
104
  mode,
@@ -112,20 +128,18 @@ export async function runWait(background, input, signal, onReady) {
112
128
  : timedOut
113
129
  ? " · wait window expired; execution continues"
114
130
  : "";
115
- const slice = await background.read(id, {
116
- bytes: TASKS_WAIT_DELTA_BYTES,
117
- sinceBytes: clampSinceBytes(input.sinceBytes),
118
- });
131
+ const sinceBytes = clampSinceBytes(input.sinceBytes);
132
+ const slice = await background.read(id, { bytes: TASKS_WAIT_DELTA_BYTES, sinceBytes });
119
133
  signal?.throwIfAborted();
120
134
  if (!timedOut)
121
135
  onReady?.(task.id);
122
- return result(readText(`[${describeTaskLine(task)}${windowNote}]`, slice), {
136
+ return result(readText(`[${describeTaskLine(task)}${windowNote} · ${rangeText(slice, sinceBytes)}]`, slice), {
123
137
  action: "wait",
124
138
  taskId: task.id,
125
139
  status: task.status,
126
140
  kind: task.kind,
127
141
  timedOut,
128
- exitCode: undefined,
142
+ exitCode: task.exitCode,
129
143
  waitedMs: Date.now() - start,
130
144
  deltaBytes: Buffer.byteLength(slice.text),
131
145
  totalBytes: slice.totalBytes,
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/actions.ts"],"names":[],"mappings":"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","sourcesContent":["/** Management only: execution and delivery belong to the session Background service. */\n\nimport { runtimeLabel } from \"../../../modes/interactive/tasks/task-view.ts\";\nimport { sanitizeBinaryOutput } from \"../../../utils/shell.ts\";\nimport type { AgentToolResult } from \"../../extensions/types.ts\";\nimport { boundText } from \"../../tasks/output.ts\";\nimport {\n\tisTaskTerminal,\n\tTaskLookupError,\n\ttype TaskRead,\n\ttype TaskSnapshot,\n\ttype TasksContext,\n} from \"../../tasks/types.ts\";\nimport { truncateHead } from \"../truncate.ts\";\nimport { TASKS_LIST_FINISHED_SHOWN, TASKS_WAIT_DELTA_BYTES } from \"./constants.ts\";\nimport { clampReadBytes, clampSinceBytes, clampWaitMs, requireTaskId, type TasksInput } from \"./schema.ts\";\nimport type { TasksDetails, TasksKillDetails, TasksListDetails, TasksReadDetails, TasksWaitDetails } from \"./types.ts\";\n\nexport function boundedText(text: string): string {\n\treturn truncateHead(sanitizeBinaryOutput(text), { maxBytes: 50 * 1024, maxLines: 2000 }).content;\n}\nfunction result<T extends TasksDetails>(text: string, details: T): AgentToolResult<T> {\n\treturn { content: [{ type: \"text\", text: boundedText(text) }], details };\n}\nexport function describeTaskLine(task: TaskSnapshot, now = Date.now()): string {\n\treturn `${task.id} ${task.kind} ${task.status} (${task.mode}) ${runtimeLabel(task, now)} ${task.title.slice(0, 200)}`;\n}\n\nconst LOOKUP_LIST_LIMIT = 10;\n\n/**\n * Finished rows sort most-recent first. list() is creation-ordered, so an\n * unsorted slice would surface the oldest completions rather than the recent\n * finishes a caller is most likely looking for.\n */\nfunction recentFinishedFirst(tasks: TaskSnapshot[]): TaskSnapshot[] {\n\treturn tasks.sort((left, right) => (right.endedAt ?? 0) - (left.endedAt ?? 0));\n}\n\n/**\n * Listings cover backgrounded work only; foreground executions deliver inline\n * in the transcript, so they are counted rather than shown. Every listing\n * (tasks list output and lookup-failure messages) shares this scope.\n */\nfunction listedTasks(background: TasksContext): { tasks: TaskSnapshot[]; foregroundOmitted: number } {\n\tconst all = background.list();\n\tconst tasks = all.filter((task) => task.mode === \"background\");\n\treturn { tasks, foregroundOmitted: all.length - tasks.length };\n}\n\nfunction foregroundOmissionNote(omitted: number): string {\n\treturn omitted > 0\n\t\t? `\\n${omitted} foreground ${omitted === 1 ? \"execution\" : \"executions\"} omitted — foreground work is delivered inline in the transcript.`\n\t\t: \"\";\n}\n\n/**\n * Rewrite the service's bare lookup failure into an actionable one: an\n * unknown id gets the session's current tasks (active first, then recent\n * finishes) so the next call can use a real id without a separate list call,\n * and an ambiguous prefix gets exactly the tasks it matched — including\n * records outside the current branch, which listings hide but the prefix\n * still collides with.\n */\nfunction lookupFailure(background: TasksContext, id: string, error: unknown): Error {\n\tif (!(error instanceof TaskLookupError)) return error instanceof Error ? error : new Error(String(error));\n\tif (error.kind === \"ambiguous\") {\n\t\tconst lines = error.matches.map((task) => describeTaskLine(task)).join(\"\\n\");\n\t\treturn new Error(`Ambiguous background task ID \"${id}\" matches ${error.matches.length} tasks:\\n${lines}`);\n\t}\n\tconst { tasks, foregroundOmitted } = listedTasks(background);\n\tconst active = tasks.filter((task) => !isTaskTerminal(task.status));\n\tconst finished = recentFinishedFirst(tasks.filter((task) => isTaskTerminal(task.status)));\n\tconst shown = [...active, ...finished].slice(0, LOOKUP_LIST_LIMIT);\n\tif (shown.length === 0) {\n\t\treturn new Error(`No background task \"${id}\" in this session. No background tasks in this session.`);\n\t}\n\tconst lines = shown.map((task) => describeTaskLine(task)).join(\"\\n\");\n\treturn new Error(\n\t\t`No background task \"${id}\" in this session. IDs from other sessions are not valid here.\\nCurrent tasks:\\n${lines}${foregroundOmissionNote(foregroundOmitted)}`,\n\t);\n}\n/** Reserve space for each independent diagnostic before allowing raw output to fill the budget. */\nfunction readText(header: string, slice: TaskRead): string {\n\tconst boundedField = (text: string, maxBytes: number) =>\n\t\ttruncateHead(boundText(sanitizeBinaryOutput(text), maxBytes), { maxBytes, maxLines: 100 }).content;\n\treturn [\n\t\tboundedField(header, 4096),\n\t\tslice.task.error ? `Task error: ${boundedField(slice.task.error, 4096)}` : \"\",\n\t\tslice.readError ? `Output read error: ${boundedField(slice.readError, 4096)}` : \"\",\n\t\tboundedField(slice.task.outputPath ?? \"\", 8192),\n\t\tslice.text || \"(no output yet)\",\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\");\n}\nexport async function runRead(background: TasksContext, input: TasksInput): Promise<AgentToolResult<TasksReadDetails>> {\n\tconst id = requireTaskId(input);\n\ttry {\n\t\tconst mode = input.mode ?? \"tail\";\n\t\tconst slice = await background.read(id, { mode, bytes: clampReadBytes(input.bytes) });\n\t\treturn result(\n\t\t\treadText(\n\t\t\t\t`[${describeTaskLine(slice.task)} · ${slice.totalBytes} bytes${slice.truncated ? \" · truncated\" : \"\"}]`,\n\t\t\t\tslice,\n\t\t\t),\n\t\t\t{\n\t\t\t\taction: \"read\",\n\t\t\t\ttaskId: slice.task.id,\n\t\t\t\tmode,\n\t\t\t\tsliceBytes: Buffer.byteLength(slice.text),\n\t\t\t\ttotalBytes: slice.totalBytes,\n\t\t\t\toutputPath: slice.task.outputPath ?? \"\",\n\t\t\t\tkind: slice.task.kind,\n\t\t\t\tstatus: slice.task.status,\n\t\t\t},\n\t\t);\n\t} catch (error) {\n\t\tthrow lookupFailure(background, id, error);\n\t}\n}\nexport async function runWait(\n\tbackground: TasksContext,\n\tinput: TasksInput,\n\tsignal?: AbortSignal,\n\tonReady?: (taskId: string) => void,\n): Promise<AgentToolResult<TasksWaitDetails>> {\n\tconst id = requireTaskId(input);\n\ttry {\n\t\tconst release = background.holdDelivery(id);\n\t\ttry {\n\t\t\tconst start = Date.now();\n\t\t\tconst task = await background.wait(id, clampWaitMs(input.waitMs), signal);\n\t\t\tconst timedOut = !isTaskTerminal(task.status);\n\t\t\t// A closed host resolves waits early without settling anything; do not claim\n\t\t\t// the execution merely outlived the wait window.\n\t\t\tconst windowNote = background.closed\n\t\t\t\t? \" · host closed; execution state unconfirmed\"\n\t\t\t\t: timedOut\n\t\t\t\t\t? \" · wait window expired; execution continues\"\n\t\t\t\t\t: \"\";\n\t\t\tconst slice = await background.read(id, {\n\t\t\t\tbytes: TASKS_WAIT_DELTA_BYTES,\n\t\t\t\tsinceBytes: clampSinceBytes(input.sinceBytes),\n\t\t\t});\n\t\t\tsignal?.throwIfAborted();\n\t\t\tif (!timedOut) onReady?.(task.id);\n\t\t\treturn result(readText(`[${describeTaskLine(task)}${windowNote}]`, slice), {\n\t\t\t\taction: \"wait\",\n\t\t\t\ttaskId: task.id,\n\t\t\t\tstatus: task.status,\n\t\t\t\tkind: task.kind,\n\t\t\t\ttimedOut,\n\t\t\t\texitCode: undefined,\n\t\t\t\twaitedMs: Date.now() - start,\n\t\t\t\tdeltaBytes: Buffer.byteLength(slice.text),\n\t\t\t\ttotalBytes: slice.totalBytes,\n\t\t\t\tdeltaTruncated: slice.truncated,\n\t\t\t\toutputPath: task.outputPath ?? \"\",\n\t\t\t});\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t} catch (error) {\n\t\tthrow lookupFailure(background, id, error);\n\t}\n}\nexport function runKill(background: TasksContext, input: TasksInput): AgentToolResult<TasksKillDetails> {\n\tconst id = requireTaskId(input);\n\ttry {\n\t\tconst task = background.get(id);\n\t\tconst requested = background.kill(task.id);\n\t\treturn result(\n\t\t\trequested\n\t\t\t\t? `Cancellation requested for ${task.id}. The task or whole group is stopping; cleanup may still be in progress.`\n\t\t\t\t: `No new cancellation requested for ${task.id} (${background.get(task.id).status}).`,\n\t\t\t{\n\t\t\t\taction: \"kill\",\n\t\t\t\ttaskId: task.id,\n\t\t\t\tcommand: task.command ?? task.title,\n\t\t\t\trequested,\n\t\t\t\tstatus: background.get(task.id).status,\n\t\t\t},\n\t\t);\n\t} catch (error) {\n\t\tthrow lookupFailure(background, id, error);\n\t}\n}\nexport function runList(background: TasksContext): AgentToolResult<TasksListDetails> {\n\tconst { tasks, foregroundOmitted } = listedTasks(background);\n\tconst active = tasks.filter((task) => !isTaskTerminal(task.status));\n\tconst finished = recentFinishedFirst(tasks.filter((task) => isTaskTerminal(task.status)));\n\tconst shown = [...active, ...finished.slice(0, TASKS_LIST_FINISHED_SHOWN)].slice(0, 100);\n\tconst hidden = tasks.length - shown.length;\n\treturn result(\n\t\tshown.length\n\t\t\t? `${shown.map((task) => describeTaskLine(task)).join(\"\\n\")}${hidden > 0 ? `\\n${hidden} more records not shown.` : \"\"}${foregroundOmissionNote(foregroundOmitted)}`\n\t\t\t: `No background tasks. Start work through its owning tool with background: true.${foregroundOmissionNote(foregroundOmitted)}`,\n\t\t{\n\t\t\taction: \"list\",\n\t\t\trunning: active.length,\n\t\t\tfinished: finished.length,\n\t\t\tshown: shown.length,\n\t\t\thidden,\n\t\t\t...(foregroundOmitted > 0 ? { foregroundOmitted } : {}),\n\t\t},\n\t);\n}\n"]}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/actions.ts"],"names":[],"mappings":"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","sourcesContent":["/** Management only: execution and delivery belong to the session task runtime. */\n\nimport { sanitizeBinaryOutput } from \"../../../utils/shell.ts\";\nimport type { AgentToolResult } from \"../../extensions/types.ts\";\nimport { runtimeLabel } from \"../../tasks/format.ts\";\nimport { boundText } from \"../../tasks/output.ts\";\nimport {\n\tisTaskTerminal,\n\tTaskLookupError,\n\ttype TaskRead,\n\ttype TaskSnapshot,\n\ttype TasksContext,\n} from \"../../tasks/types.ts\";\nimport { truncateHead } from \"../truncate.ts\";\nimport { TASKS_LIST_FINISHED_SHOWN, TASKS_WAIT_DELTA_BYTES } from \"./constants.ts\";\nimport { clampReadBytes, clampSinceBytes, clampWaitMs, requireTaskId, type TasksInput } from \"./schema.ts\";\nimport type { TasksDetails, TasksKillDetails, TasksListDetails, TasksReadDetails, TasksWaitDetails } from \"./types.ts\";\n\nexport function boundedText(text: string): string {\n\treturn truncateHead(sanitizeBinaryOutput(text), { maxBytes: 50 * 1024, maxLines: 2000 }).content;\n}\nfunction result<T extends TasksDetails>(text: string, details: T): AgentToolResult<T> {\n\treturn { content: [{ type: \"text\", text: boundedText(text) }], details };\n}\nexport function describeTaskLine(task: TaskSnapshot, now = Date.now()): string {\n\treturn `${task.id} ${task.kind} ${task.status} (${task.mode}) ${runtimeLabel(task, now)} ${task.title.slice(0, 200)}`;\n}\n\nconst LOOKUP_LIST_LIMIT = 10;\n\n/**\n * Finished rows sort most-recent first. list() is creation-ordered, so an\n * unsorted slice would surface the oldest completions rather than the recent\n * finishes a caller is most likely looking for.\n */\nfunction recentFinishedFirst(tasks: TaskSnapshot[]): TaskSnapshot[] {\n\treturn tasks.sort((left, right) => (right.endedAt ?? 0) - (left.endedAt ?? 0));\n}\n\n/**\n * Listings cover backgrounded work only; foreground executions deliver inline\n * in the transcript, so they are counted rather than shown. Every listing\n * (tasks list output and lookup-failure messages) shares this scope.\n */\nfunction listedTasks(background: TasksContext): { tasks: TaskSnapshot[]; foregroundOmitted: number } {\n\tconst all = background.list();\n\tconst tasks = all.filter((task) => task.mode === \"background\");\n\treturn { tasks, foregroundOmitted: all.length - tasks.length };\n}\n\nfunction foregroundOmissionNote(omitted: number): string {\n\treturn omitted > 0\n\t\t? `\\n${omitted} foreground ${omitted === 1 ? \"execution\" : \"executions\"} omitted — foreground work is delivered inline in the transcript.`\n\t\t: \"\";\n}\n\n/**\n * Rewrite the service's bare lookup failure into an actionable one: an\n * unknown id gets the session's current tasks (active first, then recent\n * finishes) so the next call can use a real id without a separate list call,\n * and an ambiguous prefix gets exactly the tasks it matched — including\n * records outside the current branch, which listings hide but the prefix\n * still collides with.\n */\nfunction lookupFailure(background: TasksContext, id: string, error: unknown): Error {\n\tif (!(error instanceof TaskLookupError)) return error instanceof Error ? error : new Error(String(error));\n\tif (error.kind === \"ambiguous\") {\n\t\tconst lines = error.matches.map((task) => describeTaskLine(task)).join(\"\\n\");\n\t\treturn new Error(`Ambiguous task ID \"${id}\" matches ${error.matches.length} tasks:\\n${lines}`);\n\t}\n\tconst { tasks, foregroundOmitted } = listedTasks(background);\n\tconst active = tasks.filter((task) => !isTaskTerminal(task.status));\n\tconst finished = recentFinishedFirst(tasks.filter((task) => isTaskTerminal(task.status)));\n\tconst shown = [...active, ...finished].slice(0, LOOKUP_LIST_LIMIT);\n\tif (shown.length === 0) {\n\t\treturn new Error(`No task \"${id}\" in this session. No background tasks in this session.`);\n\t}\n\tconst lines = shown.map((task) => describeTaskLine(task)).join(\"\\n\");\n\treturn new Error(\n\t\t`No task \"${id}\" in this session. IDs from other sessions are not valid here.\\nCurrent background tasks:\\n${lines}${foregroundOmissionNote(foregroundOmitted)}`,\n\t);\n}\n\n/**\n * Where this slice sits in the output, so the next wait can continue from it.\n * A wait whose new output exceeds its budget returns the newest bytes and says what it skipped.\n */\nfunction rangeText(slice: TaskRead, sinceBytes?: number): string {\n\tconst from = slice.fromByte ?? 0;\n\tconst to = from + Buffer.byteLength(slice.text);\n\tconst floor = sinceBytes === undefined || sinceBytes > slice.totalBytes ? 0 : sinceBytes;\n\treturn [\n\t\t`bytes ${from}–${to} of ${slice.totalBytes}`,\n\t\tsinceBytes !== undefined && from > floor ? `skipped ${from - floor} bytes after sinceBytes ${floor}` : \"\",\n\t\t`next sinceBytes ${to}`,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" · \");\n}\n\n/** Reserve space for each independent diagnostic before allowing raw output to fill the budget. */\nfunction readText(header: string, slice: TaskRead): string {\n\tconst boundedField = (text: string, maxBytes: number) =>\n\t\ttruncateHead(boundText(sanitizeBinaryOutput(text), maxBytes), { maxBytes, maxLines: 100 }).content;\n\treturn [\n\t\tboundedField(header, 4096),\n\t\tslice.task.error ? `Task error: ${boundedField(slice.task.error, 4096)}` : \"\",\n\t\tslice.readError ? `Output read error: ${boundedField(slice.readError, 4096)}` : \"\",\n\t\tboundedField(slice.task.outputPath ?? \"\", 8192),\n\t\tslice.text || \"(no output yet)\",\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\");\n}\nexport async function runRead(background: TasksContext, input: TasksInput): Promise<AgentToolResult<TasksReadDetails>> {\n\tconst id = requireTaskId(input);\n\ttry {\n\t\tconst mode = input.mode ?? \"tail\";\n\t\tconst slice = await background.read(id, { mode, bytes: clampReadBytes(input.bytes) });\n\t\treturn result(readText(`[${describeTaskLine(slice.task)} · ${rangeText(slice)}]`, slice), {\n\t\t\taction: \"read\",\n\t\t\ttaskId: slice.task.id,\n\t\t\tmode,\n\t\t\tsliceBytes: Buffer.byteLength(slice.text),\n\t\t\ttotalBytes: slice.totalBytes,\n\t\t\toutputPath: slice.task.outputPath ?? \"\",\n\t\t\tkind: slice.task.kind,\n\t\t\tstatus: slice.task.status,\n\t\t});\n\t} catch (error) {\n\t\tthrow lookupFailure(background, id, error);\n\t}\n}\nexport async function runWait(\n\tbackground: TasksContext,\n\tinput: TasksInput,\n\tsignal?: AbortSignal,\n\tonReady?: (taskId: string) => void,\n): Promise<AgentToolResult<TasksWaitDetails>> {\n\tconst id = requireTaskId(input);\n\ttry {\n\t\tconst release = background.holdDelivery(id);\n\t\ttry {\n\t\t\tconst start = Date.now();\n\t\t\tconst task = await background.wait(id, clampWaitMs(input.waitMs), signal);\n\t\t\tconst timedOut = !isTaskTerminal(task.status);\n\t\t\t// A closed host resolves waits early without settling anything; do not claim\n\t\t\t// the execution merely outlived the wait window.\n\t\t\tconst windowNote = background.closed\n\t\t\t\t? \" · host closed; execution state unconfirmed\"\n\t\t\t\t: timedOut\n\t\t\t\t\t? \" · wait window expired; execution continues\"\n\t\t\t\t\t: \"\";\n\t\t\tconst sinceBytes = clampSinceBytes(input.sinceBytes);\n\t\t\tconst slice = await background.read(id, { bytes: TASKS_WAIT_DELTA_BYTES, sinceBytes });\n\t\t\tsignal?.throwIfAborted();\n\t\t\tif (!timedOut) onReady?.(task.id);\n\t\t\treturn result(readText(`[${describeTaskLine(task)}${windowNote} · ${rangeText(slice, sinceBytes)}]`, slice), {\n\t\t\t\taction: \"wait\",\n\t\t\t\ttaskId: task.id,\n\t\t\t\tstatus: task.status,\n\t\t\t\tkind: task.kind,\n\t\t\t\ttimedOut,\n\t\t\t\texitCode: task.exitCode,\n\t\t\t\twaitedMs: Date.now() - start,\n\t\t\t\tdeltaBytes: Buffer.byteLength(slice.text),\n\t\t\t\ttotalBytes: slice.totalBytes,\n\t\t\t\tdeltaTruncated: slice.truncated,\n\t\t\t\toutputPath: task.outputPath ?? \"\",\n\t\t\t});\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t} catch (error) {\n\t\tthrow lookupFailure(background, id, error);\n\t}\n}\nexport function runKill(background: TasksContext, input: TasksInput): AgentToolResult<TasksKillDetails> {\n\tconst id = requireTaskId(input);\n\ttry {\n\t\tconst task = background.get(id);\n\t\tconst requested = background.kill(task.id);\n\t\treturn result(\n\t\t\trequested\n\t\t\t\t? `Cancellation requested for ${task.id}. The task or whole group is stopping; cleanup may still be in progress.`\n\t\t\t\t: `No new cancellation requested for ${task.id} (${background.get(task.id).status}).`,\n\t\t\t{\n\t\t\t\taction: \"kill\",\n\t\t\t\ttaskId: task.id,\n\t\t\t\tcommand: task.command ?? task.title,\n\t\t\t\trequested,\n\t\t\t\tstatus: background.get(task.id).status,\n\t\t\t},\n\t\t);\n\t} catch (error) {\n\t\tthrow lookupFailure(background, id, error);\n\t}\n}\nexport function runList(background: TasksContext): AgentToolResult<TasksListDetails> {\n\tconst { tasks, foregroundOmitted } = listedTasks(background);\n\tconst active = tasks.filter((task) => !isTaskTerminal(task.status));\n\tconst finished = recentFinishedFirst(tasks.filter((task) => isTaskTerminal(task.status)));\n\tconst shown = [...active, ...finished.slice(0, TASKS_LIST_FINISHED_SHOWN)].slice(0, 100);\n\tconst hidden = tasks.length - shown.length;\n\treturn result(\n\t\tshown.length\n\t\t\t? `${shown.map((task) => describeTaskLine(task)).join(\"\\n\")}${hidden > 0 ? `\\n${hidden} more records not shown.` : \"\"}${foregroundOmissionNote(foregroundOmitted)}`\n\t\t\t: `No background tasks. Start work through its owning tool with background: true.${foregroundOmissionNote(foregroundOmitted)}`,\n\t\t{\n\t\t\taction: \"list\",\n\t\t\trunning: active.length,\n\t\t\tfinished: finished.length,\n\t\t\tshown: shown.length,\n\t\t\thidden,\n\t\t\t...(foregroundOmitted > 0 ? { foregroundOmitted } : {}),\n\t\t},\n\t);\n}\n"]}
@@ -1,14 +1,10 @@
1
1
  /**
2
- * background — shared limits and identity.
2
+ * Shared limits of the `tasks` tool.
3
3
  *
4
4
  * Numbers that more than one module needs live here so a change lands in one
5
5
  * place; execution and retention limits belong to the core service.
6
6
  */
7
- /** Historical extension-owned completion/stall messages. */
8
- export declare const TASKS_NOTIFICATION_TYPE = "background-task";
9
- /** Session-owned completions; model content and delivery are unchanged by rendering. */
10
- export declare const TASKS_COMPLETION_TYPE = "task-completion";
11
- /** Default and floor for a `read` slice; the ceiling is truncate.ts's DEFAULT_MAX_BYTES. */
7
+ /** Default and floor for a `read` slice; the ceiling is the core's TASK_RESULT_BYTES. */
12
8
  export declare const TASKS_LOGS_DEFAULT_BYTES: number;
13
9
  export declare const TASKS_LOGS_MIN_BYTES = 256;
14
10
  /** Finished tasks shown by `list` before the rest fold into a count. */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/tasks/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AACzD,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD,4FAA4F;AAC5F,eAAO,MAAM,wBAAwB,QAAW,CAAC;AACjD,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAEhD,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAC5C,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAExC,4FAA4F;AAC5F,eAAO,MAAM,0BAA0B,QAAS,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/tasks/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yFAAyF;AACzF,eAAO,MAAM,wBAAwB,QAAW,CAAC;AACjD,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAEhD,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAC5C,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAExC,4FAA4F;AAC5F,eAAO,MAAM,0BAA0B,QAAS,CAAC"}
@@ -1,14 +1,10 @@
1
1
  /**
2
- * background — shared limits and identity.
2
+ * Shared limits of the `tasks` tool.
3
3
  *
4
4
  * Numbers that more than one module needs live here so a change lands in one
5
5
  * place; execution and retention limits belong to the core service.
6
6
  */
7
- /** Historical extension-owned completion/stall messages. */
8
- export const TASKS_NOTIFICATION_TYPE = "background-task";
9
- /** Session-owned completions; model content and delivery are unchanged by rendering. */
10
- export const TASKS_COMPLETION_TYPE = "task-completion";
11
- /** Default and floor for a `read` slice; the ceiling is truncate.ts's DEFAULT_MAX_BYTES. */
7
+ /** Default and floor for a `read` slice; the ceiling is the core's TASK_RESULT_BYTES. */
12
8
  export const TASKS_LOGS_DEFAULT_BYTES = 8 * 1024;
13
9
  export const TASKS_LOGS_MIN_BYTES = 256;
14
10
  /** Finished tasks shown by `list` before the rest fold into a count. */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AACzD,wFAAwF;AACxF,MAAM,CAAC,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AAEvD,4FAA4F;AAC5F,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC,wEAAwE;AACxE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC,4FAA4F;AAC5F,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC","sourcesContent":["/**\n * background — shared limits and identity.\n *\n * Numbers that more than one module needs live here so a change lands in one\n * place; execution and retention limits belong to the core service.\n */\n\n/** Historical extension-owned completion/stall messages. */\nexport const TASKS_NOTIFICATION_TYPE = \"background-task\";\n/** Session-owned completions; model content and delivery are unchanged by rendering. */\nexport const TASKS_COMPLETION_TYPE = \"task-completion\";\n\n/** Default and floor for a `read` slice; the ceiling is truncate.ts's DEFAULT_MAX_BYTES. */\nexport const TASKS_LOGS_DEFAULT_BYTES = 8 * 1024;\nexport const TASKS_LOGS_MIN_BYTES = 256;\n\n/** Finished tasks shown by `list` before the rest fold into a count. */\nexport const TASKS_LIST_FINISHED_SHOWN = 5;\n\n/** Bounded output delta returned by a successful wait. */\nexport const TASKS_WAIT_DELTA_BYTES = 32 * 1024;\n\n/** Wait-window bounds shared by execution and the pending-call renderer. */\nexport const TASKS_WAIT_DEFAULT_MS = 20_000;\nexport const TASKS_WAIT_MIN_MS = 1_000;\nexport const TASKS_WAIT_MAX_MS = 60_000;\n\n/** How long a foreground execution runs before the statusline advertises the detach key. */\nexport const TASKS_DETACH_HINT_DELAY_MS = 10_000;\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yFAAyF;AACzF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC,wEAAwE;AACxE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC,4FAA4F;AAC5F,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC","sourcesContent":["/**\n * Shared limits of the `tasks` tool.\n *\n * Numbers that more than one module needs live here so a change lands in one\n * place; execution and retention limits belong to the core service.\n */\n\n/** Default and floor for a `read` slice; the ceiling is the core's TASK_RESULT_BYTES. */\nexport const TASKS_LOGS_DEFAULT_BYTES = 8 * 1024;\nexport const TASKS_LOGS_MIN_BYTES = 256;\n\n/** Finished tasks shown by `list` before the rest fold into a count. */\nexport const TASKS_LIST_FINISHED_SHOWN = 5;\n\n/** Bounded output delta returned by a successful wait. */\nexport const TASKS_WAIT_DELTA_BYTES = 32 * 1024;\n\n/** Wait-window bounds shared by execution and the pending-call renderer. */\nexport const TASKS_WAIT_DEFAULT_MS = 20_000;\nexport const TASKS_WAIT_MIN_MS = 1_000;\nexport const TASKS_WAIT_MAX_MS = 60_000;\n\n/** How long a foreground execution runs before the statusline advertises the detach key. */\nexport const TASKS_DETACH_HINT_DELAY_MS = 10_000;\n"]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * background — the `bg` tool's wire contract: one flat schema whose `action`
2
+ * The `tasks` tool's wire contract: one flat schema whose `action`
3
3
  * selects which of the remaining fields apply, plus the model-facing copy.
4
4
  *
5
5
  * The schema stays flat deliberately: a single tool keeps the model's tool list
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/tasks/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAU5C,eAAO,MAAM,WAAW;;;;;;;EA6BtB,CAAC;AAEH,uFAAuF;AACvF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAOpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMvD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGhE;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG9D;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAElF;AAED,eAAO,MAAM,sBAAsB,QAO+E,CAAC;AACnH,eAAO,MAAM,oBAAoB,qDAAqD,CAAC;AACvF,eAAO,MAAM,uBAAuB,UAGnC,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/tasks/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAW5C,eAAO,MAAM,WAAW;;;;;;;EA6BtB,CAAC;AAEH,uFAAuF;AACvF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAOpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMvD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGhE;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG9D;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAElF;AAED,eAAO,MAAM,sBAAsB,QAOiJ,CAAC;AACrL,eAAO,MAAM,oBAAoB,qDAAqD,CAAC;AACvF,eAAO,MAAM,uBAAuB,UAGnC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * background — the `bg` tool's wire contract: one flat schema whose `action`
2
+ * The `tasks` tool's wire contract: one flat schema whose `action`
3
3
  * selects which of the remaining fields apply, plus the model-facing copy.
4
4
  *
5
5
  * The schema stays flat deliberately: a single tool keeps the model's tool list
@@ -8,11 +8,12 @@
8
8
  */
9
9
  import { StringEnum } from "@earendil-works/pi-ai";
10
10
  import { Type } from "typebox";
11
- import { DEFAULT_MAX_BYTES, formatSize } from "../truncate.js";
11
+ import { TASK_RESULT_BYTES } from "../../tasks/output.js";
12
+ import { formatSize } from "../truncate.js";
12
13
  import { TASKS_LOGS_DEFAULT_BYTES, TASKS_LOGS_MIN_BYTES, TASKS_WAIT_DEFAULT_MS, TASKS_WAIT_MAX_MS, TASKS_WAIT_MIN_MS, } from "./constants.js";
13
14
  export const tasksSchema = Type.Object({
14
15
  action: StringEnum(["read", "wait", "kill", "list"], {
15
- description: "Which background-task operation to perform",
16
+ description: "Which task operation to perform",
16
17
  }),
17
18
  // — read / wait / kill —
18
19
  taskId: Type.Optional(Type.String({ description: "Task execution id (read/wait/kill)" })),
@@ -21,14 +22,14 @@ export const tasksSchema = Type.Object({
21
22
  description: "Read from the end (default) or the start of the output (read)",
22
23
  })),
23
24
  bytes: Type.Optional(Type.Number({
24
- description: `Max bytes to return (read, default ${formatSize(TASKS_LOGS_DEFAULT_BYTES)}, max ${formatSize(DEFAULT_MAX_BYTES)})`,
25
+ description: `Max bytes to return (read, default ${formatSize(TASKS_LOGS_DEFAULT_BYTES)}, max ${formatSize(TASK_RESULT_BYTES)})`,
25
26
  })),
26
27
  // — wait —
27
28
  waitMs: Type.Optional(Type.Number({
28
29
  description: `Max time to wait in ms, default ${TASKS_WAIT_DEFAULT_MS}, max ${TASKS_WAIT_MAX_MS} (wait)`,
29
30
  })),
30
31
  sinceBytes: Type.Optional(Type.Number({
31
- description: "Only return output written after this byte offset — take it from a previous read/wait result (wait)",
32
+ description: "Only return output written after this byte offset — use the 'next sinceBytes' value from a previous read or wait (wait)",
32
33
  })),
33
34
  });
34
35
  // ── reading the contract ──────────────────────────────────────────────────
@@ -44,7 +45,7 @@ export function requireTaskId(input) {
44
45
  }
45
46
  export function clampReadBytes(bytes) {
46
47
  const value = bytes !== undefined && Number.isFinite(bytes) ? bytes : TASKS_LOGS_DEFAULT_BYTES;
47
- return Math.min(DEFAULT_MAX_BYTES, Math.max(TASKS_LOGS_MIN_BYTES, Math.floor(value)));
48
+ return Math.min(TASK_RESULT_BYTES, Math.max(TASKS_LOGS_MIN_BYTES, Math.floor(value)));
48
49
  }
49
50
  /** Shared with the pending-call renderer so the window it shows is the one that runs. */
50
51
  export function clampWaitMs(waitMs) {
@@ -60,7 +61,7 @@ export const TASKS_TOOL_DESCRIPTION = "Inspect and control background tasks star
60
61
  "read: bounded output or report slice (head/tail). " +
61
62
  "wait: block up to waitMs for a task to settle; cancelling the wait ends only the wait, never the task. " +
62
63
  "kill: request cancellation of a whole task. " +
63
- "tasks cannot start work; submit background work through its owning tool. Output is capped at 50KB per response.";
64
+ "tasks cannot start work; submit background work through its owning tool. Each read or wait reports its byte range and the next sinceBytes. Output is capped at 50KB per response.";
64
65
  export const TASKS_PROMPT_SNIPPET = "Manage background tasks (list, read, wait, kill)";
65
66
  export const TASKS_PROMPT_GUIDELINES = [
66
67
  "Start background work through its owning tool with background: true; continue independent work while it runs.",
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * background — the `bg` tool's wire contract: one flat schema whose `action`\n * selects which of the remaining fields apply, plus the model-facing copy.\n *\n * The schema stays flat deliberately: a single tool keeps the model's tool list\n * short. Execution creation belongs to the native tools. Narrowing happens\n * inside actions.ts, not here.\n */\n\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { type Static, Type } from \"typebox\";\nimport { DEFAULT_MAX_BYTES, formatSize } from \"../truncate.ts\";\nimport {\n\tTASKS_LOGS_DEFAULT_BYTES,\n\tTASKS_LOGS_MIN_BYTES,\n\tTASKS_WAIT_DEFAULT_MS,\n\tTASKS_WAIT_MAX_MS,\n\tTASKS_WAIT_MIN_MS,\n} from \"./constants.ts\";\n\nexport const tasksSchema = Type.Object({\n\taction: StringEnum([\"read\", \"wait\", \"kill\", \"list\"] as const, {\n\t\tdescription: \"Which background-task operation to perform\",\n\t}),\n\t// — read / wait / kill —\n\ttaskId: Type.Optional(Type.String({ description: \"Task execution id (read/wait/kill)\" })),\n\t// — read —\n\tmode: Type.Optional(\n\t\tStringEnum([\"tail\", \"head\"] as const, {\n\t\t\tdescription: \"Read from the end (default) or the start of the output (read)\",\n\t\t}),\n\t),\n\tbytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max bytes to return (read, default ${formatSize(TASKS_LOGS_DEFAULT_BYTES)}, max ${formatSize(DEFAULT_MAX_BYTES)})`,\n\t\t}),\n\t),\n\t// — wait —\n\twaitMs: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max time to wait in ms, default ${TASKS_WAIT_DEFAULT_MS}, max ${TASKS_WAIT_MAX_MS} (wait)`,\n\t\t}),\n\t),\n\tsinceBytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription:\n\t\t\t\t\"Only return output written after this byte offset — take it from a previous read/wait result (wait)\",\n\t\t}),\n\t),\n});\n\n/** Raw tool arguments. Every per-action field is optional here; actions.ts narrows. */\nexport type TasksInput = Static<typeof tasksSchema>;\n\n// ── reading the contract ──────────────────────────────────────────────────\n// One place per field: required fields throw a message that names the next\n// step, optional ones clamp to their documented range. Callers get plain\n// values, so no action handler needs a cast.\n\nexport function requireTaskId(input: TasksInput): string {\n\tconst taskId = input.taskId;\n\tif (!taskId || taskId.trim().length === 0) {\n\t\tthrow new Error(`action '${input.action}' requires 'taskId' — use action list to find the execution id.`);\n\t}\n\treturn taskId;\n}\n\nexport function clampReadBytes(bytes: number | undefined): number {\n\tconst value = bytes !== undefined && Number.isFinite(bytes) ? bytes : TASKS_LOGS_DEFAULT_BYTES;\n\treturn Math.min(DEFAULT_MAX_BYTES, Math.max(TASKS_LOGS_MIN_BYTES, Math.floor(value)));\n}\n\n/** Shared with the pending-call renderer so the window it shows is the one that runs. */\nexport function clampWaitMs(waitMs: number | undefined): number {\n\tconst value = waitMs !== undefined && Number.isFinite(waitMs) ? waitMs : TASKS_WAIT_DEFAULT_MS;\n\treturn Math.min(TASKS_WAIT_MAX_MS, Math.max(TASKS_WAIT_MIN_MS, Math.floor(value)));\n}\n\nexport function clampSinceBytes(sinceBytes: number | undefined): number | undefined {\n\treturn sinceBytes === undefined || !Number.isFinite(sinceBytes) ? undefined : Math.max(0, Math.floor(sinceBytes));\n}\n\nexport const TASKS_TOOL_DESCRIPTION =\n\t\"Inspect and control background tasks started by native tools or extensions. \" +\n\t\"Completion is delivered to you automatically as a notification — never poll. \" +\n\t\"list: bounded activity/history listing; find task IDs here. \" +\n\t\"read: bounded output or report slice (head/tail). \" +\n\t\"wait: block up to waitMs for a task to settle; cancelling the wait ends only the wait, never the task. \" +\n\t\"kill: request cancellation of a whole task. \" +\n\t\"tasks cannot start work; submit background work through its owning tool. Output is capped at 50KB per response.\";\nexport const TASKS_PROMPT_SNIPPET = \"Manage background tasks (list, read, wait, kill)\";\nexport const TASKS_PROMPT_GUIDELINES = [\n\t\"Start background work through its owning tool with background: true; continue independent work while it runs.\",\n\t\"A finished background task delivers its result automatically as a notification; use tasks wait only when your next step is blocked on it, and never sleep-poll with repeated reads.\",\n];\n"]}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACN,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,gBAAgB,CAAC;AAExB,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,EAAE;QAC7D,WAAW,EAAE,iCAAiC;KAC9C,CAAC;IACF,yBAAyB;IACzB,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC,CAAC;IACzF,WAAW;IACX,IAAI,EAAE,IAAI,CAAC,QAAQ,CAClB,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,CAAU,EAAE;QACrC,WAAW,EAAE,+DAA+D;KAC5E,CAAC,CACF;IACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,sCAAsC,UAAU,CAAC,wBAAwB,CAAC,SAAS,UAAU,CAAC,iBAAiB,CAAC,GAAG;KAChI,CAAC,CACF;IACD,WAAW;IACX,MAAM,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EAAE,mCAAmC,qBAAqB,SAAS,iBAAiB,SAAS;KACxG,CAAC,CACF;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACxB,IAAI,CAAC,MAAM,CAAC;QACX,WAAW,EACV,yHAAyH;KAC1H,CAAC,CACF;CACD,CAAC,CAAC;AAKH,6EAA6E;AAC7E,2EAA2E;AAC3E,yEAAyE;AACzE,6CAA6C;AAE7C,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,CAAC,MAAM,iEAAiE,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAyB;IACvD,MAAM,KAAK,GAAG,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,wBAAwB,CAAC;IAC/F,OAAO,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,WAAW,CAAC,MAA0B;IACrD,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAC/F,OAAO,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAA8B;IAC7D,OAAO,UAAU,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;AACnH,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAClC,8EAA8E;IAC9E,+EAA+E;IAC/E,8DAA8D;IAC9D,oDAAoD;IACpD,yGAAyG;IACzG,8CAA8C;IAC9C,mLAAmL,CAAC;AACrL,MAAM,CAAC,MAAM,oBAAoB,GAAG,kDAAkD,CAAC;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACtC,+GAA+G;IAC/G,qLAAqL;CACrL,CAAC","sourcesContent":["/**\n * The `tasks` tool's wire contract: one flat schema whose `action`\n * selects which of the remaining fields apply, plus the model-facing copy.\n *\n * The schema stays flat deliberately: a single tool keeps the model's tool list\n * short. Execution creation belongs to the native tools. Narrowing happens\n * inside actions.ts, not here.\n */\n\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { type Static, Type } from \"typebox\";\nimport { TASK_RESULT_BYTES } from \"../../tasks/output.ts\";\nimport { formatSize } from \"../truncate.ts\";\nimport {\n\tTASKS_LOGS_DEFAULT_BYTES,\n\tTASKS_LOGS_MIN_BYTES,\n\tTASKS_WAIT_DEFAULT_MS,\n\tTASKS_WAIT_MAX_MS,\n\tTASKS_WAIT_MIN_MS,\n} from \"./constants.ts\";\n\nexport const tasksSchema = Type.Object({\n\taction: StringEnum([\"read\", \"wait\", \"kill\", \"list\"] as const, {\n\t\tdescription: \"Which task operation to perform\",\n\t}),\n\t// — read / wait / kill —\n\ttaskId: Type.Optional(Type.String({ description: \"Task execution id (read/wait/kill)\" })),\n\t// — read —\n\tmode: Type.Optional(\n\t\tStringEnum([\"tail\", \"head\"] as const, {\n\t\t\tdescription: \"Read from the end (default) or the start of the output (read)\",\n\t\t}),\n\t),\n\tbytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max bytes to return (read, default ${formatSize(TASKS_LOGS_DEFAULT_BYTES)}, max ${formatSize(TASK_RESULT_BYTES)})`,\n\t\t}),\n\t),\n\t// — wait —\n\twaitMs: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription: `Max time to wait in ms, default ${TASKS_WAIT_DEFAULT_MS}, max ${TASKS_WAIT_MAX_MS} (wait)`,\n\t\t}),\n\t),\n\tsinceBytes: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription:\n\t\t\t\t\"Only return output written after this byte offset — use the 'next sinceBytes' value from a previous read or wait (wait)\",\n\t\t}),\n\t),\n});\n\n/** Raw tool arguments. Every per-action field is optional here; actions.ts narrows. */\nexport type TasksInput = Static<typeof tasksSchema>;\n\n// ── reading the contract ──────────────────────────────────────────────────\n// One place per field: required fields throw a message that names the next\n// step, optional ones clamp to their documented range. Callers get plain\n// values, so no action handler needs a cast.\n\nexport function requireTaskId(input: TasksInput): string {\n\tconst taskId = input.taskId;\n\tif (!taskId || taskId.trim().length === 0) {\n\t\tthrow new Error(`action '${input.action}' requires 'taskId' — use action list to find the execution id.`);\n\t}\n\treturn taskId;\n}\n\nexport function clampReadBytes(bytes: number | undefined): number {\n\tconst value = bytes !== undefined && Number.isFinite(bytes) ? bytes : TASKS_LOGS_DEFAULT_BYTES;\n\treturn Math.min(TASK_RESULT_BYTES, Math.max(TASKS_LOGS_MIN_BYTES, Math.floor(value)));\n}\n\n/** Shared with the pending-call renderer so the window it shows is the one that runs. */\nexport function clampWaitMs(waitMs: number | undefined): number {\n\tconst value = waitMs !== undefined && Number.isFinite(waitMs) ? waitMs : TASKS_WAIT_DEFAULT_MS;\n\treturn Math.min(TASKS_WAIT_MAX_MS, Math.max(TASKS_WAIT_MIN_MS, Math.floor(value)));\n}\n\nexport function clampSinceBytes(sinceBytes: number | undefined): number | undefined {\n\treturn sinceBytes === undefined || !Number.isFinite(sinceBytes) ? undefined : Math.max(0, Math.floor(sinceBytes));\n}\n\nexport const TASKS_TOOL_DESCRIPTION =\n\t\"Inspect and control background tasks started by native tools or extensions. \" +\n\t\"Completion is delivered to you automatically as a notification — never poll. \" +\n\t\"list: bounded activity/history listing; find task IDs here. \" +\n\t\"read: bounded output or report slice (head/tail). \" +\n\t\"wait: block up to waitMs for a task to settle; cancelling the wait ends only the wait, never the task. \" +\n\t\"kill: request cancellation of a whole task. \" +\n\t\"tasks cannot start work; submit background work through its owning tool. Each read or wait reports its byte range and the next sinceBytes. Output is capped at 50KB per response.\";\nexport const TASKS_PROMPT_SNIPPET = \"Manage background tasks (list, read, wait, kill)\";\nexport const TASKS_PROMPT_GUIDELINES = [\n\t\"Start background work through its owning tool with background: true; continue independent work while it runs.\",\n\t\"A finished background task delivers its result automatically as a notification; use tasks wait only when your next step is blocked on it, and never sleep-poll with repeated reads.\",\n];\n"]}
@@ -1,28 +1,14 @@
1
1
  /**
2
- * background — the structured `details` payloads.
2
+ * The `tasks` tool's structured `details` payloads.
3
3
  *
4
- * PERSISTENCE CONTRACT: every shape here is JSON-serialized verbatim into the
5
- * session file (agent-session.ts -> session-manager.ts) and read back by this
6
- * extension's renderers on `/reload`, `/tree`, and session resume — so a
7
- * renderer always has to cope with details written by an older build. Adding an
8
- * optional field is free; renaming or repurposing an existing one silently
9
- * degrades historical transcripts, because components/custom-message.ts catches
10
- * renderer failures and falls back to an unstyled box with no diagnostic.
4
+ * Every shape here is JSON-serialized verbatim into the session file and read back
5
+ * by the renderers on `/reload`, `/tree`, and session resume. Adding an optional
6
+ * field is free; renaming or repurposing an existing one degrades historical
7
+ * transcripts.
11
8
  *
12
- * Keep `exitCode` three-state for the same reason: historical entries hold
13
- * `null` for signal-reaped tasks. task-view.ts's `exitSuffix` is the one place
14
- * that has to know.
9
+ * `exitCode` is three-state: `null` for signal-reaped tasks.
15
10
  */
16
11
  import type { TaskKind, TaskStatus } from "../../tasks/types.ts";
17
- /** Historical transcripts used killed rather than cancelled. */
18
- export type TasksTaskStatus = TaskStatus | "killed";
19
- export interface TasksCreateDetails {
20
- action: "create";
21
- taskId: string;
22
- outputPath: string;
23
- command: string;
24
- description?: string;
25
- }
26
12
  export interface TasksReadDetails {
27
13
  kind?: TaskKind;
28
14
  status?: TaskStatus;
@@ -39,7 +25,7 @@ export interface TasksWaitDetails {
39
25
  taskId: string;
40
26
  /** True when the wait window expired and the task is still running. */
41
27
  timedOut: boolean;
42
- status: TasksTaskStatus;
28
+ status: TaskStatus;
43
29
  exitCode: number | null | undefined;
44
30
  waitedMs: number;
45
31
  deltaBytes: number;
@@ -63,21 +49,5 @@ export interface TasksListDetails {
63
49
  /** Foreground executions omitted from the listing; they deliver inline in the transcript. */
64
50
  foregroundOmitted?: number;
65
51
  }
66
- export type TasksDetails = TasksCreateDetails | TasksReadDetails | TasksKillDetails | TasksListDetails | TasksWaitDetails;
67
- export interface TasksNotificationDetails {
68
- taskId: string;
69
- command: string;
70
- description?: string;
71
- status: TasksTaskStatus;
72
- /** True for the one-shot "waiting for interactive input" signal; the task keeps running. */
73
- stalled?: true;
74
- exitCode: number | null | undefined;
75
- runtimeMs: number;
76
- outputPath: string;
77
- totalBytes: number;
78
- tailText: string;
79
- tailTruncated: boolean;
80
- error?: string;
81
- tailError?: string;
82
- }
52
+ export type TasksDetails = TasksReadDetails | TasksKillDetails | TasksListDetails | TasksWaitDetails;
83
53
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEjE,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,YAAY,GACrB,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;IACxB,4FAA4F;IAC5F,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC"}
@@ -1,17 +1,12 @@
1
1
  /**
2
- * background — the structured `details` payloads.
2
+ * The `tasks` tool's structured `details` payloads.
3
3
  *
4
- * PERSISTENCE CONTRACT: every shape here is JSON-serialized verbatim into the
5
- * session file (agent-session.ts -> session-manager.ts) and read back by this
6
- * extension's renderers on `/reload`, `/tree`, and session resume — so a
7
- * renderer always has to cope with details written by an older build. Adding an
8
- * optional field is free; renaming or repurposing an existing one silently
9
- * degrades historical transcripts, because components/custom-message.ts catches
10
- * renderer failures and falls back to an unstyled box with no diagnostic.
4
+ * Every shape here is JSON-serialized verbatim into the session file and read back
5
+ * by the renderers on `/reload`, `/tree`, and session resume. Adding an optional
6
+ * field is free; renaming or repurposing an existing one degrades historical
7
+ * transcripts.
11
8
  *
12
- * Keep `exitCode` three-state for the same reason: historical entries hold
13
- * `null` for signal-reaped tasks. task-view.ts's `exitSuffix` is the one place
14
- * that has to know.
9
+ * `exitCode` is three-state: `null` for signal-reaped tasks.
15
10
  */
16
11
  export {};
17
12
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG","sourcesContent":["/**\n * background — the structured `details` payloads.\n *\n * PERSISTENCE CONTRACT: every shape here is JSON-serialized verbatim into the\n * session file (agent-session.ts -> session-manager.ts) and read back by this\n * extension's renderers on `/reload`, `/tree`, and session resume — so a\n * renderer always has to cope with details written by an older build. Adding an\n * optional field is free; renaming or repurposing an existing one silently\n * degrades historical transcripts, because components/custom-message.ts catches\n * renderer failures and falls back to an unstyled box with no diagnostic.\n *\n * Keep `exitCode` three-state for the same reason: historical entries hold\n * `null` for signal-reaped tasks. task-view.ts's `exitSuffix` is the one place\n * that has to know.\n */\n\nimport type { TaskKind, TaskStatus } from \"../../tasks/types.ts\";\n\n/** Historical transcripts used killed rather than cancelled. */\nexport type TasksTaskStatus = TaskStatus | \"killed\";\n\nexport interface TasksCreateDetails {\n\taction: \"create\";\n\ttaskId: string;\n\toutputPath: string;\n\tcommand: string;\n\tdescription?: string;\n}\n\nexport interface TasksReadDetails {\n\tkind?: TaskKind;\n\tstatus?: TaskStatus;\n\taction: \"read\";\n\ttaskId: string;\n\tmode: \"head\" | \"tail\";\n\tsliceBytes: number;\n\ttotalBytes: number;\n\toutputPath: string;\n}\n\nexport interface TasksWaitDetails {\n\tkind?: TaskKind;\n\taction: \"wait\";\n\ttaskId: string;\n\t/** True when the wait window expired and the task is still running. */\n\ttimedOut: boolean;\n\tstatus: TasksTaskStatus;\n\texitCode: number | null | undefined;\n\twaitedMs: number;\n\tdeltaBytes: number;\n\ttotalBytes: number;\n\tdeltaTruncated: boolean;\n\toutputPath: string;\n}\n\nexport interface TasksKillDetails {\n\trequested?: boolean;\n\tstatus?: TaskStatus;\n\taction: \"kill\";\n\ttaskId: string;\n\tcommand: string;\n}\n\nexport interface TasksListDetails {\n\taction: \"list\";\n\trunning: number;\n\tfinished: number;\n\tshown: number;\n\thidden: number;\n\t/** Foreground executions omitted from the listing; they deliver inline in the transcript. */\n\tforegroundOmitted?: number;\n}\n\nexport type TasksDetails =\n\t| TasksCreateDetails\n\t| TasksReadDetails\n\t| TasksKillDetails\n\t| TasksListDetails\n\t| TasksWaitDetails;\n\nexport interface TasksNotificationDetails {\n\ttaskId: string;\n\tcommand: string;\n\tdescription?: string;\n\tstatus: TasksTaskStatus;\n\t/** True for the one-shot \"waiting for interactive input\" signal; the task keeps running. */\n\tstalled?: true;\n\texitCode: number | null | undefined;\n\truntimeMs: number;\n\toutputPath: string;\n\ttotalBytes: number;\n\ttailText: string;\n\ttailTruncated: boolean;\n\terror?: string;\n\ttailError?: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/tools/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG","sourcesContent":["/**\n * The `tasks` tool's structured `details` payloads.\n *\n * Every shape here is JSON-serialized verbatim into the session file and read back\n * by the renderers on `/reload`, `/tree`, and session resume. Adding an optional\n * field is free; renaming or repurposing an existing one degrades historical\n * transcripts.\n *\n * `exitCode` is three-state: `null` for signal-reaped tasks.\n */\n\nimport type { TaskKind, TaskStatus } from \"../../tasks/types.ts\";\n\nexport interface TasksReadDetails {\n\tkind?: TaskKind;\n\tstatus?: TaskStatus;\n\taction: \"read\";\n\ttaskId: string;\n\tmode: \"head\" | \"tail\";\n\tsliceBytes: number;\n\ttotalBytes: number;\n\toutputPath: string;\n}\n\nexport interface TasksWaitDetails {\n\tkind?: TaskKind;\n\taction: \"wait\";\n\ttaskId: string;\n\t/** True when the wait window expired and the task is still running. */\n\ttimedOut: boolean;\n\tstatus: TaskStatus;\n\texitCode: number | null | undefined;\n\twaitedMs: number;\n\tdeltaBytes: number;\n\ttotalBytes: number;\n\tdeltaTruncated: boolean;\n\toutputPath: string;\n}\n\nexport interface TasksKillDetails {\n\trequested?: boolean;\n\tstatus?: TaskStatus;\n\taction: \"kill\";\n\ttaskId: string;\n\tcommand: string;\n}\n\nexport interface TasksListDetails {\n\taction: \"list\";\n\trunning: number;\n\tfinished: number;\n\tshown: number;\n\thidden: number;\n\t/** Foreground executions omitted from the listing; they deliver inline in the transcript. */\n\tforegroundOmitted?: number;\n}\n\nexport type TasksDetails = TasksReadDetails | TasksKillDetails | TasksListDetails | TasksWaitDetails;\n"]}
@@ -97,6 +97,8 @@ export declare function findLatestResponse(messages: readonly AgentMessage[]): A
97
97
  * `model_change`, because responses name the physical models it routed to. Otherwise the latest
98
98
  * physical response wins, as in sessions without virtual models. A virtual model that is no longer
99
99
  * registered does not hold, so the selection falls back to the physical model that answered last.
100
+ *
101
+ * Only the last `model_change` can hold, so this looks up at most one model in the catalog.
100
102
  */
101
103
  export declare function getBranchSelection(branch: readonly SessionEntry[], getModel: (provider: string, modelId: string) => Model<Api> | undefined): {
102
104
  provider: string;
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-models.d.ts","sourceRoot":"","sources":["../../src/core/virtual-models.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"virtual-models.d.ts","sourceRoot":"","sources":["../../src/core/virtual-models.ts"],"names":[],"mappings":"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"}
@@ -23,24 +23,31 @@ export function findLatestResponse(messages) {
23
23
  * `model_change`, because responses name the physical models it routed to. Otherwise the latest
24
24
  * physical response wins, as in sessions without virtual models. A virtual model that is no longer
25
25
  * registered does not hold, so the selection falls back to the physical model that answered last.
26
+ *
27
+ * Only the last `model_change` can hold, so this looks up at most one model in the catalog.
26
28
  */
27
29
  export function getBranchSelection(branch, getModel) {
28
- const isVirtual = (provider, modelId) => {
29
- const model = getModel(provider, modelId);
30
- return model !== undefined && isVirtualModel(model);
31
- };
32
- let selection;
33
- for (const entry of branch) {
30
+ for (let i = branch.length - 1; i >= 0; i--) {
31
+ const entry = branch[i];
34
32
  if (entry.type === "model_change") {
35
- selection = { provider: entry.provider, modelId: entry.modelId };
33
+ return { provider: entry.provider, modelId: entry.modelId };
36
34
  }
37
- else if (entry.type === "message" && entry.message.role === "assistant" && !isVirtualModel(entry.message)) {
38
- if (!selection || !isVirtual(selection.provider, selection.modelId)) {
39
- selection = { provider: entry.message.provider, modelId: entry.message.model };
40
- }
35
+ if (entry.type === "message" && entry.message.role === "assistant" && !isVirtualModel(entry.message)) {
36
+ const response = { provider: entry.message.provider, modelId: entry.message.model };
37
+ const change = findLastModelChange(branch, i);
38
+ const model = change && getModel(change.provider, change.modelId);
39
+ return change && model && isVirtualModel(model) ? change : response;
41
40
  }
42
41
  }
43
- return selection;
42
+ return undefined;
43
+ }
44
+ function findLastModelChange(branch, before) {
45
+ for (let i = before - 1; i >= 0; i--) {
46
+ const entry = branch[i];
47
+ if (entry.type === "model_change")
48
+ return { provider: entry.provider, modelId: entry.modelId };
49
+ }
50
+ return undefined;
44
51
  }
45
52
  /** Latest router state a session branch stores for a virtual model. */
46
53
  export function getVirtualModelState(branch, provider, modelId) {
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-models.js","sourceRoot":"","sources":["../../src/core/virtual-models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Virtual models are catalog entries that route each request to a physical model.\n *\n * The selection (`model_change`, `agent.state.model`, `ctx.model`) may name a virtual model.\n * Everything below the routing step only sees physical models: providers stream them and\n * assistant messages record them. A virtual model never reaches a provider.\n *\n * Virtual models belong to a provider id but are not provider models. `ModelRuntime` keeps them\n * separately and adds them to the provider's catalog with `withVirtualModels()`, so any provider,\n * including one with physical models, can list several virtual models.\n */\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AnyModel,\n\ttype Api,\n\ttype AssistantMessage,\n\ttype AssistantMessageEventStream,\n\tisModelType,\n\tlazyStream,\n\ttype Message,\n\ttype Model,\n\ttype ModelThinkingLevel,\n\ttype Provider,\n\ttype ThinkingLevelMap,\n} from \"@earendil-works/pi-ai\";\nimport type { SessionEntry } from \"./session-manager.ts\";\n\n/** API id of virtual catalog entries. Requests for it fail unless routed first. */\nexport const VIRTUAL_MODEL_API = \"pi-virtual\";\n\n/** Custom entry type that stores router state on the session branch. */\nexport const VIRTUAL_MODEL_STATE_ENTRY = \"pi.virtual-model-state\";\n\n/** Data of a `pi.virtual-model-state` custom entry. */\nexport interface VirtualModelStateData<TState = unknown> {\n\tprovider: string;\n\tmodelId: string;\n\tstate: TState;\n}\n\nconst THINKING_LEVELS: readonly ModelThinkingLevel[] = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n\n/**\n * Why a request is being routed.\n * - `user`: first request after a message the user wrote (prompt, steering, or follow-up)\n * - `continuation`: any other request in the agent loop, e.g. after tool results or extension messages\n * - `retry`: automatic retry after a failed request, including after compaction for a context overflow\n * - `direct`: a request outside the agent loop, e.g. a compaction summary or an extension call\n */\nexport type ModelRouteReason = \"user\" | \"continuation\" | \"retry\" | \"direct\";\n\nexport interface ModelRouteRequest<TState = unknown> {\n\t/** The selected virtual model. */\n\tmodel: Model<Api>;\n\t/** The selected thinking level. Its meaning is up to the router. */\n\tthinkingLevel: ModelThinkingLevel;\n\treason: ModelRouteReason;\n\t/** Physical model and thinking level of the latest successful response in `messages`. */\n\tprevious?: { model: Model<Api>; thinkingLevel?: ModelThinkingLevel };\n\t/**\n\t * For `retry`: the failed request, which `messages` no longer contains. `message` carries its\n\t * `stopReason` and `errorMessage`. Absent when the router itself failed.\n\t */\n\tfailed?: { model: Model<Api>; thinkingLevel?: ModelThinkingLevel; message: AssistantMessage };\n\t/** Router state last returned on this session branch. Undefined before the first state and for `direct` requests. */\n\tstate?: TState;\n\t/** Conversation for this request, including system messages. */\n\tmessages: readonly Message[];\n\tsignal?: AbortSignal;\n}\n\n/** Physical model and thinking level for one request. */\nexport interface ModelRoute<TState = unknown> {\n\tmodel: Model<Api>;\n\tthinkingLevel: ModelThinkingLevel;\n\t/**\n\t * New router state, stored on the session branch unless it is `request.state` itself. Return\n\t * `request.state` or undefined to keep the current state. Must be JSON-serializable. Ignored for\n\t * `direct` requests.\n\t */\n\tstate?: TState;\n}\n\nexport interface VirtualModelDefinition<TState = unknown> {\n\t/** Provider the virtual model is listed under. May be a provider with physical models. */\n\tprovider: string;\n\t/** Model id. Must not be the id of a physical model of `provider`. */\n\tid: string;\n\tname: string;\n\t/** Thinking levels offered for selection. Defaults to `[\"off\"]`. */\n\tthinkingLevels?: readonly ModelThinkingLevel[];\n\t/**\n\t * Limits shown before the first response. Afterwards, Pi uses the limits of the physical model\n\t * that answered. Unset limits are unknown (0).\n\t */\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n\t/** Input types accepted for selection. Defaults to text and images; routed models without image support get placeholders. */\n\tinput?: (\"text\" | \"image\")[];\n\t/** Pick the physical model, which must have credentials, and thinking level for one request. */\n\troute(request: ModelRouteRequest<TState>): ModelRoute<TState> | Promise<ModelRoute<TState>>;\n}\n\n/** Whether a model or message names a virtual model. Failed routing leaves the virtual model on its message. */\nexport function isVirtualModel(model: { api: string }): boolean {\n\treturn model.api === VIRTUAL_MODEL_API;\n}\n\n/** Latest successful response. Its model is physical: failed or aborted requests, including failed routing, are skipped. */\nexport function findLatestResponse(messages: readonly AgentMessage[]): AssistantMessage | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst message = messages[i];\n\t\tif (message.role === \"assistant\" && message.stopReason !== \"error\" && message.stopReason !== \"aborted\") {\n\t\t\treturn message;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * The model selection a session branch records. A virtual `model_change` holds until the next\n * `model_change`, because responses name the physical models it routed to. Otherwise the latest\n * physical response wins, as in sessions without virtual models. A virtual model that is no longer\n * registered does not hold, so the selection falls back to the physical model that answered last.\n */\nexport function getBranchSelection(\n\tbranch: readonly SessionEntry[],\n\tgetModel: (provider: string, modelId: string) => Model<Api> | undefined,\n): { provider: string; modelId: string } | undefined {\n\tconst isVirtual = (provider: string, modelId: string) => {\n\t\tconst model = getModel(provider, modelId);\n\t\treturn model !== undefined && isVirtualModel(model);\n\t};\n\tlet selection: { provider: string; modelId: string } | undefined;\n\tfor (const entry of branch) {\n\t\tif (entry.type === \"model_change\") {\n\t\t\tselection = { provider: entry.provider, modelId: entry.modelId };\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"assistant\" && !isVirtualModel(entry.message)) {\n\t\t\tif (!selection || !isVirtual(selection.provider, selection.modelId)) {\n\t\t\t\tselection = { provider: entry.message.provider, modelId: entry.message.model };\n\t\t\t}\n\t\t}\n\t}\n\treturn selection;\n}\n\n/** Latest router state a session branch stores for a virtual model. */\nexport function getVirtualModelState(branch: readonly SessionEntry[], provider: string, modelId: string): unknown {\n\tfor (let i = branch.length - 1; i >= 0; i--) {\n\t\tconst entry = branch[i];\n\t\tif (entry.type !== \"custom\" || entry.customType !== VIRTUAL_MODEL_STATE_ENTRY) continue;\n\t\tconst data = entry.data as VirtualModelStateData | undefined;\n\t\tif (data?.provider === provider && data.modelId === modelId) return data.state;\n\t}\n\treturn undefined;\n}\n\n/** Build the catalog entry of a virtual model. */\nexport function createVirtualModel(definition: Omit<VirtualModelDefinition, \"route\">): Model<Api> {\n\tconst levels = definition.thinkingLevels ?? [\"off\"];\n\tconst thinkingLevelMap: ThinkingLevelMap = {};\n\tfor (const level of THINKING_LEVELS) thinkingLevelMap[level] = levels.includes(level) ? level : null;\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\tapi: VIRTUAL_MODEL_API,\n\t\tprovider: definition.provider,\n\t\tbaseUrl: \"\",\n\t\treasoning: levels.some((level) => level !== \"off\"),\n\t\tthinkingLevelMap,\n\t\tinput: definition.input ?? [\"text\", \"image\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 0,\n\t\tmaxTokens: definition.maxTokens ?? 0,\n\t};\n}\n\n/** Stream for a virtual model that was not routed, e.g. `stream()` with API-specific options. */\nfunction unroutedStream(model: Model<Api>): AssistantMessageEventStream {\n\treturn lazyStream(model, async () => {\n\t\tthrow new Error(`Virtual model ${model.provider}/${model.id} must be routed before streaming`);\n\t});\n}\n\n/**\n * Add virtual models to a provider's catalog. Without a provider, the result is a keyless provider\n * that only lists the virtual models. A virtual model hides a physical chat model with the same id,\n * which a catalog refresh can add after registration. Availability follows the provider's auth.\n */\nexport function withVirtualModels(\n\tproviderId: string,\n\tprovider: Provider | undefined,\n\tvirtualModels: readonly Model<Api>[],\n): Provider {\n\tif (!provider) {\n\t\treturn {\n\t\t\tid: providerId,\n\t\t\tname: providerId,\n\t\t\tauth: { apiKey: { name: \"Virtual model\", resolve: async () => ({ auth: {}, source: \"virtual\" }) } },\n\t\t\tgetModels: () => virtualModels,\n\t\t\tstream: unroutedStream,\n\t\t\tstreamSimple: unroutedStream,\n\t\t};\n\t}\n\tconst ids = new Set(virtualModels.map((model) => model.id));\n\tconst physical = <TModel extends AnyModel>(models: readonly TModel[]) =>\n\t\tmodels.filter((model) => !isVirtualModel(model) && !(isModelType(model, \"chat\") && ids.has(model.id)));\n\tconst virtual = <TModel extends AnyModel>(models: readonly TModel[]) =>\n\t\tmodels.filter((model) => isVirtualModel(model));\n\tconst { filterModels, filterAllModels } = provider;\n\treturn {\n\t\t...provider,\n\t\tgetModels: () => [...physical(provider.getModels()), ...virtualModels],\n\t\tgetAllModels: () => [...physical(provider.getAllModels?.() ?? provider.getModels()), ...virtualModels],\n\t\tfilterModels: (models, credential) => {\n\t\t\tconst real = physical(models);\n\t\t\treturn [...(filterModels?.(real, credential) ?? real), ...virtual(models)];\n\t\t},\n\t\tfilterAllModels:\n\t\t\tfilterAllModels &&\n\t\t\t((models, credential) => [...filterAllModels(physical(models), credential), ...virtual(models)]),\n\t\tstream: (model, context, options) =>\n\t\t\tisVirtualModel(model) ? unroutedStream(model) : provider.stream(model, context, options),\n\t\tstreamSimple: (model, context, options) =>\n\t\t\tisVirtualModel(model) ? unroutedStream(model) : provider.streamSimple(model, context, options),\n\t};\n}\n"]}
1
+ {"version":3,"file":"virtual-models.js","sourceRoot":"","sources":["../../src/core/virtual-models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Virtual models are catalog entries that route each request to a physical model.\n *\n * The selection (`model_change`, `agent.state.model`, `ctx.model`) may name a virtual model.\n * Everything below the routing step only sees physical models: providers stream them and\n * assistant messages record them. A virtual model never reaches a provider.\n *\n * Virtual models belong to a provider id but are not provider models. `ModelRuntime` keeps them\n * separately and adds them to the provider's catalog with `withVirtualModels()`, so any provider,\n * including one with physical models, can list several virtual models.\n */\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AnyModel,\n\ttype Api,\n\ttype AssistantMessage,\n\ttype AssistantMessageEventStream,\n\tisModelType,\n\tlazyStream,\n\ttype Message,\n\ttype Model,\n\ttype ModelThinkingLevel,\n\ttype Provider,\n\ttype ThinkingLevelMap,\n} from \"@earendil-works/pi-ai\";\nimport type { SessionEntry } from \"./session-manager.ts\";\n\n/** API id of virtual catalog entries. Requests for it fail unless routed first. */\nexport const VIRTUAL_MODEL_API = \"pi-virtual\";\n\n/** Custom entry type that stores router state on the session branch. */\nexport const VIRTUAL_MODEL_STATE_ENTRY = \"pi.virtual-model-state\";\n\n/** Data of a `pi.virtual-model-state` custom entry. */\nexport interface VirtualModelStateData<TState = unknown> {\n\tprovider: string;\n\tmodelId: string;\n\tstate: TState;\n}\n\nconst THINKING_LEVELS: readonly ModelThinkingLevel[] = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n\n/**\n * Why a request is being routed.\n * - `user`: first request after a message the user wrote (prompt, steering, or follow-up)\n * - `continuation`: any other request in the agent loop, e.g. after tool results or extension messages\n * - `retry`: automatic retry after a failed request, including after compaction for a context overflow\n * - `direct`: a request outside the agent loop, e.g. a compaction summary or an extension call\n */\nexport type ModelRouteReason = \"user\" | \"continuation\" | \"retry\" | \"direct\";\n\nexport interface ModelRouteRequest<TState = unknown> {\n\t/** The selected virtual model. */\n\tmodel: Model<Api>;\n\t/** The selected thinking level. Its meaning is up to the router. */\n\tthinkingLevel: ModelThinkingLevel;\n\treason: ModelRouteReason;\n\t/** Physical model and thinking level of the latest successful response in `messages`. */\n\tprevious?: { model: Model<Api>; thinkingLevel?: ModelThinkingLevel };\n\t/**\n\t * For `retry`: the failed request, which `messages` no longer contains. `message` carries its\n\t * `stopReason` and `errorMessage`. Absent when the router itself failed.\n\t */\n\tfailed?: { model: Model<Api>; thinkingLevel?: ModelThinkingLevel; message: AssistantMessage };\n\t/** Router state last returned on this session branch. Undefined before the first state and for `direct` requests. */\n\tstate?: TState;\n\t/** Conversation for this request, including system messages. */\n\tmessages: readonly Message[];\n\tsignal?: AbortSignal;\n}\n\n/** Physical model and thinking level for one request. */\nexport interface ModelRoute<TState = unknown> {\n\tmodel: Model<Api>;\n\tthinkingLevel: ModelThinkingLevel;\n\t/**\n\t * New router state, stored on the session branch unless it is `request.state` itself. Return\n\t * `request.state` or undefined to keep the current state. Must be JSON-serializable. Ignored for\n\t * `direct` requests.\n\t */\n\tstate?: TState;\n}\n\nexport interface VirtualModelDefinition<TState = unknown> {\n\t/** Provider the virtual model is listed under. May be a provider with physical models. */\n\tprovider: string;\n\t/** Model id. Must not be the id of a physical model of `provider`. */\n\tid: string;\n\tname: string;\n\t/** Thinking levels offered for selection. Defaults to `[\"off\"]`. */\n\tthinkingLevels?: readonly ModelThinkingLevel[];\n\t/**\n\t * Limits shown before the first response. Afterwards, Pi uses the limits of the physical model\n\t * that answered. Unset limits are unknown (0).\n\t */\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n\t/** Input types accepted for selection. Defaults to text and images; routed models without image support get placeholders. */\n\tinput?: (\"text\" | \"image\")[];\n\t/** Pick the physical model, which must have credentials, and thinking level for one request. */\n\troute(request: ModelRouteRequest<TState>): ModelRoute<TState> | Promise<ModelRoute<TState>>;\n}\n\n/** Whether a model or message names a virtual model. Failed routing leaves the virtual model on its message. */\nexport function isVirtualModel(model: { api: string }): boolean {\n\treturn model.api === VIRTUAL_MODEL_API;\n}\n\n/** Latest successful response. Its model is physical: failed or aborted requests, including failed routing, are skipped. */\nexport function findLatestResponse(messages: readonly AgentMessage[]): AssistantMessage | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst message = messages[i];\n\t\tif (message.role === \"assistant\" && message.stopReason !== \"error\" && message.stopReason !== \"aborted\") {\n\t\t\treturn message;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * The model selection a session branch records. A virtual `model_change` holds until the next\n * `model_change`, because responses name the physical models it routed to. Otherwise the latest\n * physical response wins, as in sessions without virtual models. A virtual model that is no longer\n * registered does not hold, so the selection falls back to the physical model that answered last.\n *\n * Only the last `model_change` can hold, so this looks up at most one model in the catalog.\n */\nexport function getBranchSelection(\n\tbranch: readonly SessionEntry[],\n\tgetModel: (provider: string, modelId: string) => Model<Api> | undefined,\n): { provider: string; modelId: string } | undefined {\n\tfor (let i = branch.length - 1; i >= 0; i--) {\n\t\tconst entry = branch[i];\n\t\tif (entry.type === \"model_change\") {\n\t\t\treturn { provider: entry.provider, modelId: entry.modelId };\n\t\t}\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\" && !isVirtualModel(entry.message)) {\n\t\t\tconst response = { provider: entry.message.provider, modelId: entry.message.model };\n\t\t\tconst change = findLastModelChange(branch, i);\n\t\t\tconst model = change && getModel(change.provider, change.modelId);\n\t\t\treturn change && model && isVirtualModel(model) ? change : response;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction findLastModelChange(\n\tbranch: readonly SessionEntry[],\n\tbefore: number,\n): { provider: string; modelId: string } | undefined {\n\tfor (let i = before - 1; i >= 0; i--) {\n\t\tconst entry = branch[i];\n\t\tif (entry.type === \"model_change\") return { provider: entry.provider, modelId: entry.modelId };\n\t}\n\treturn undefined;\n}\n\n/** Latest router state a session branch stores for a virtual model. */\nexport function getVirtualModelState(branch: readonly SessionEntry[], provider: string, modelId: string): unknown {\n\tfor (let i = branch.length - 1; i >= 0; i--) {\n\t\tconst entry = branch[i];\n\t\tif (entry.type !== \"custom\" || entry.customType !== VIRTUAL_MODEL_STATE_ENTRY) continue;\n\t\tconst data = entry.data as VirtualModelStateData | undefined;\n\t\tif (data?.provider === provider && data.modelId === modelId) return data.state;\n\t}\n\treturn undefined;\n}\n\n/** Build the catalog entry of a virtual model. */\nexport function createVirtualModel(definition: Omit<VirtualModelDefinition, \"route\">): Model<Api> {\n\tconst levels = definition.thinkingLevels ?? [\"off\"];\n\tconst thinkingLevelMap: ThinkingLevelMap = {};\n\tfor (const level of THINKING_LEVELS) thinkingLevelMap[level] = levels.includes(level) ? level : null;\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name,\n\t\tapi: VIRTUAL_MODEL_API,\n\t\tprovider: definition.provider,\n\t\tbaseUrl: \"\",\n\t\treasoning: levels.some((level) => level !== \"off\"),\n\t\tthinkingLevelMap,\n\t\tinput: definition.input ?? [\"text\", \"image\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 0,\n\t\tmaxTokens: definition.maxTokens ?? 0,\n\t};\n}\n\n/** Stream for a virtual model that was not routed, e.g. `stream()` with API-specific options. */\nfunction unroutedStream(model: Model<Api>): AssistantMessageEventStream {\n\treturn lazyStream(model, async () => {\n\t\tthrow new Error(`Virtual model ${model.provider}/${model.id} must be routed before streaming`);\n\t});\n}\n\n/**\n * Add virtual models to a provider's catalog. Without a provider, the result is a keyless provider\n * that only lists the virtual models. A virtual model hides a physical chat model with the same id,\n * which a catalog refresh can add after registration. Availability follows the provider's auth.\n */\nexport function withVirtualModels(\n\tproviderId: string,\n\tprovider: Provider | undefined,\n\tvirtualModels: readonly Model<Api>[],\n): Provider {\n\tif (!provider) {\n\t\treturn {\n\t\t\tid: providerId,\n\t\t\tname: providerId,\n\t\t\tauth: { apiKey: { name: \"Virtual model\", resolve: async () => ({ auth: {}, source: \"virtual\" }) } },\n\t\t\tgetModels: () => virtualModels,\n\t\t\tstream: unroutedStream,\n\t\t\tstreamSimple: unroutedStream,\n\t\t};\n\t}\n\tconst ids = new Set(virtualModels.map((model) => model.id));\n\tconst physical = <TModel extends AnyModel>(models: readonly TModel[]) =>\n\t\tmodels.filter((model) => !isVirtualModel(model) && !(isModelType(model, \"chat\") && ids.has(model.id)));\n\tconst virtual = <TModel extends AnyModel>(models: readonly TModel[]) =>\n\t\tmodels.filter((model) => isVirtualModel(model));\n\tconst { filterModels, filterAllModels } = provider;\n\treturn {\n\t\t...provider,\n\t\tgetModels: () => [...physical(provider.getModels()), ...virtualModels],\n\t\tgetAllModels: () => [...physical(provider.getAllModels?.() ?? provider.getModels()), ...virtualModels],\n\t\tfilterModels: (models, credential) => {\n\t\t\tconst real = physical(models);\n\t\t\treturn [...(filterModels?.(real, credential) ?? real), ...virtual(models)];\n\t\t},\n\t\tfilterAllModels:\n\t\t\tfilterAllModels &&\n\t\t\t((models, credential) => [...filterAllModels(physical(models), credential), ...virtual(models)]),\n\t\tstream: (model, context, options) =>\n\t\t\tisVirtualModel(model) ? unroutedStream(model) : provider.stream(model, context, options),\n\t\tstreamSimple: (model, context, options) =>\n\t\t\tisVirtualModel(model) ? unroutedStream(model) : provider.streamSimple(model, context, options),\n\t};\n}\n"]}