@astralyn/pi 0.99.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (512) hide show
  1. package/CHANGELOG.md +39 -3
  2. package/dist/bundle/chunks/anthropic-messages-CG2BSDQS.js +6 -0
  3. package/dist/bundle/chunks/anthropic.js +2 -2
  4. package/dist/bundle/chunks/{azure-openai-responses-RPBERDXD.js → azure-openai-responses-PBA4QKCM.js} +1 -1
  5. package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
  6. package/dist/bundle/chunks/{chunk-ABVRAYXT.js → chunk-6UFFVA7M.js} +2 -2
  7. package/dist/bundle/chunks/chunk-GIG5IHES.js +2 -0
  8. package/dist/bundle/chunks/{chunk-VW2P3X6P.js → chunk-HESRDUKO.js} +414 -666
  9. package/dist/bundle/chunks/{chunk-A576H74Y.js → chunk-PFZKRUMO.js} +1 -1
  10. package/dist/bundle/chunks/chunk-SGLYRVQL.js +2 -0
  11. package/dist/bundle/chunks/chunk-TRHTWM3C.js +2 -0
  12. package/dist/bundle/chunks/{chunk-DEWXBB6W.js → chunk-V66VGGOM.js} +1 -1
  13. package/dist/bundle/chunks/chunk-Z2RKSI3O.js +2 -0
  14. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-ZYSAFXXL.js → cloudflare-workers-ai-system-one-YB7XPPP4.js} +1 -1
  15. package/dist/bundle/chunks/codemode-worker.js +67 -8
  16. package/dist/bundle/chunks/github-copilot.js +1 -1
  17. package/dist/bundle/chunks/{google-generative-ai-SDNQVVXA.js → google-generative-ai-V5ZM5MCL.js} +1 -1
  18. package/dist/bundle/chunks/{google-vertex-LZXOLBIO.js → google-vertex-22THOFP5.js} +1 -1
  19. package/dist/bundle/chunks/{llama-cpp-classify-7IYGGPND.js → llama-cpp-classify-R7DQLTQN.js} +1 -1
  20. package/dist/bundle/chunks/{mistral-conversations-VYKPSSAM.js → mistral-conversations-WHSCJJWP.js} +1 -1
  21. package/dist/bundle/chunks/openai-chatgpt.js +1 -1
  22. package/dist/bundle/chunks/{openai-codex-responses-HZ4VUDXD.js → openai-codex-responses-N7GDPBPP.js} +1 -1
  23. package/dist/bundle/chunks/openai-codex.js +1 -1
  24. package/dist/bundle/chunks/{openai-completions-SKDGF6OE.js → openai-completions-RGGQK5UW.js} +1 -1
  25. package/dist/bundle/chunks/{openai-responses-FPML4SSG.js → openai-responses-3ZLD5JYI.js} +1 -1
  26. package/dist/bundle/chunks/{openrouter-images-5524IQHX.js → openrouter-images-YP3YVB54.js} +1 -1
  27. package/dist/bundle/chunks/openrouter.js +1 -1
  28. package/dist/bundle/chunks/radius.js +1 -1
  29. package/dist/bundle/chunks/{typesafe-system-one-Z2CDLKEY.js → typesafe-system-one-RREJAKWB.js} +1 -1
  30. package/dist/bundle/chunks/virtual-modules-4RQ2L6W4.js +2 -0
  31. package/dist/bundle/cli.js +1 -1
  32. package/dist/bundle/index.js +1 -1
  33. package/dist/bundle/rpc-entry.js +1 -1
  34. package/dist/cli/args.js +1 -1
  35. package/dist/cli/args.js.map +1 -1
  36. package/dist/config.d.ts +5 -8
  37. package/dist/config.d.ts.map +1 -1
  38. package/dist/config.js +16 -13
  39. package/dist/config.js.map +1 -1
  40. package/dist/core/agent-session.d.ts +21 -1
  41. package/dist/core/agent-session.d.ts.map +1 -1
  42. package/dist/core/agent-session.js +64 -11
  43. package/dist/core/agent-session.js.map +1 -1
  44. package/dist/core/extensions/index.d.ts +1 -1
  45. package/dist/core/extensions/index.d.ts.map +1 -1
  46. package/dist/core/extensions/index.js.map +1 -1
  47. package/dist/core/extensions/loader.d.ts.map +1 -1
  48. package/dist/core/extensions/loader.js +13 -1
  49. package/dist/core/extensions/loader.js.map +1 -1
  50. package/dist/core/extensions/types.d.ts +6 -1
  51. package/dist/core/extensions/types.d.ts.map +1 -1
  52. package/dist/core/extensions/types.js.map +1 -1
  53. package/dist/core/keybindings.d.ts +51 -11
  54. package/dist/core/keybindings.d.ts.map +1 -1
  55. package/dist/core/keybindings.js +11 -3
  56. package/dist/core/keybindings.js.map +1 -1
  57. package/dist/core/mcp-servers.d.ts +34 -7
  58. package/dist/core/mcp-servers.d.ts.map +1 -1
  59. package/dist/core/mcp-servers.js +52 -11
  60. package/dist/core/mcp-servers.js.map +1 -1
  61. package/dist/core/model-registry.d.ts +3 -1
  62. package/dist/core/model-registry.d.ts.map +1 -1
  63. package/dist/core/model-registry.js +4 -0
  64. package/dist/core/model-registry.js.map +1 -1
  65. package/dist/core/model-runtime.d.ts +6 -0
  66. package/dist/core/model-runtime.d.ts.map +1 -1
  67. package/dist/core/model-runtime.js +22 -18
  68. package/dist/core/model-runtime.js.map +1 -1
  69. package/dist/core/radius.d.ts +2 -0
  70. package/dist/core/radius.d.ts.map +1 -1
  71. package/dist/core/radius.js +2 -0
  72. package/dist/core/radius.js.map +1 -1
  73. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  74. package/dist/core/remote-catalog-provider.js +4 -9
  75. package/dist/core/remote-catalog-provider.js.map +1 -1
  76. package/dist/core/sdk.d.ts.map +1 -1
  77. package/dist/core/sdk.js +1 -0
  78. package/dist/core/sdk.js.map +1 -1
  79. package/dist/core/settings-manager.d.ts +7 -5
  80. package/dist/core/settings-manager.d.ts.map +1 -1
  81. package/dist/core/settings-manager.js +2 -1
  82. package/dist/core/settings-manager.js.map +1 -1
  83. package/dist/core/system-prompt.js +1 -1
  84. package/dist/core/system-prompt.js.map +1 -1
  85. package/dist/core/tasks/format.d.ts +7 -0
  86. package/dist/core/tasks/format.d.ts.map +1 -0
  87. package/dist/core/tasks/format.js +14 -0
  88. package/dist/core/tasks/format.js.map +1 -0
  89. package/dist/core/tasks/history.d.ts.map +1 -1
  90. package/dist/core/tasks/history.js +0 -19
  91. package/dist/core/tasks/history.js.map +1 -1
  92. package/dist/core/tasks/output.d.ts +8 -0
  93. package/dist/core/tasks/output.d.ts.map +1 -1
  94. package/dist/core/tasks/output.js +19 -0
  95. package/dist/core/tasks/output.js.map +1 -1
  96. package/dist/core/tasks/presentation.d.ts +1 -3
  97. package/dist/core/tasks/presentation.d.ts.map +1 -1
  98. package/dist/core/tasks/presentation.js +79 -166
  99. package/dist/core/tasks/presentation.js.map +1 -1
  100. package/dist/core/tasks/runtime.d.ts +16 -9
  101. package/dist/core/tasks/runtime.d.ts.map +1 -1
  102. package/dist/core/tasks/runtime.js +89 -106
  103. package/dist/core/tasks/runtime.js.map +1 -1
  104. package/dist/core/tasks/session.d.ts.map +1 -1
  105. package/dist/core/tasks/session.js +13 -4
  106. package/dist/core/tasks/session.js.map +1 -1
  107. package/dist/core/tasks/store.d.ts +20 -6
  108. package/dist/core/tasks/store.d.ts.map +1 -1
  109. package/dist/core/tasks/store.js +45 -18
  110. package/dist/core/tasks/store.js.map +1 -1
  111. package/dist/core/tasks/types.d.ts +14 -54
  112. package/dist/core/tasks/types.d.ts.map +1 -1
  113. package/dist/core/tasks/types.js +1 -5
  114. package/dist/core/tasks/types.js.map +1 -1
  115. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  116. package/dist/core/tools/renderers/bash.js +11 -34
  117. package/dist/core/tools/renderers/bash.js.map +1 -1
  118. package/dist/core/tools/shell-execution.d.ts +0 -1
  119. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  120. package/dist/core/tools/shell-execution.js +3 -10
  121. package/dist/core/tools/shell-execution.js.map +1 -1
  122. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  123. package/dist/core/tools/shell-tool.js +2 -4
  124. package/dist/core/tools/shell-tool.js.map +1 -1
  125. package/dist/core/tools/tasks/actions.d.ts +1 -1
  126. package/dist/core/tools/tasks/actions.d.ts.map +1 -1
  127. package/dist/core/tools/tasks/actions.js +26 -12
  128. package/dist/core/tools/tasks/actions.js.map +1 -1
  129. package/dist/core/tools/tasks/constants.d.ts +2 -6
  130. package/dist/core/tools/tasks/constants.d.ts.map +1 -1
  131. package/dist/core/tools/tasks/constants.js +2 -6
  132. package/dist/core/tools/tasks/constants.js.map +1 -1
  133. package/dist/core/tools/tasks/schema.d.ts +1 -1
  134. package/dist/core/tools/tasks/schema.d.ts.map +1 -1
  135. package/dist/core/tools/tasks/schema.js +8 -7
  136. package/dist/core/tools/tasks/schema.js.map +1 -1
  137. package/dist/core/tools/tasks/types.d.ts +8 -38
  138. package/dist/core/tools/tasks/types.d.ts.map +1 -1
  139. package/dist/core/tools/tasks/types.js +6 -11
  140. package/dist/core/tools/tasks/types.js.map +1 -1
  141. package/dist/core/virtual-models.d.ts +2 -0
  142. package/dist/core/virtual-models.d.ts.map +1 -1
  143. package/dist/core/virtual-models.js +19 -12
  144. package/dist/core/virtual-models.js.map +1 -1
  145. package/dist/extensions/btw/agent.d.ts +17 -8
  146. package/dist/extensions/btw/agent.d.ts.map +1 -1
  147. package/dist/extensions/btw/agent.js +74 -76
  148. package/dist/extensions/btw/agent.js.map +1 -1
  149. package/dist/extensions/btw/controller.d.ts +0 -1
  150. package/dist/extensions/btw/controller.d.ts.map +1 -1
  151. package/dist/extensions/btw/controller.js +26 -33
  152. package/dist/extensions/btw/controller.js.map +1 -1
  153. package/dist/extensions/btw/panel.d.ts +13 -14
  154. package/dist/extensions/btw/panel.d.ts.map +1 -1
  155. package/dist/extensions/btw/panel.js +38 -29
  156. package/dist/extensions/btw/panel.js.map +1 -1
  157. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  158. package/dist/extensions/codemode/execute.js +197 -51
  159. package/dist/extensions/codemode/execute.js.map +1 -1
  160. package/dist/extensions/codemode/renderer.d.ts.map +1 -1
  161. package/dist/extensions/codemode/renderer.js +43 -25
  162. package/dist/extensions/codemode/renderer.js.map +1 -1
  163. package/dist/extensions/codemode/tool.d.ts +12 -11
  164. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  165. package/dist/extensions/codemode/tool.js +73 -129
  166. package/dist/extensions/codemode/tool.js.map +1 -1
  167. package/dist/extensions/codemode/worker.d.ts +1 -1
  168. package/dist/extensions/codemode/worker.js +1 -1
  169. package/dist/extensions/codemode/worker.js.map +1 -1
  170. package/dist/extensions/deepwiki/schema.d.ts +1 -1
  171. package/dist/extensions/index.d.ts.map +1 -1
  172. package/dist/extensions/index.js +0 -2
  173. package/dist/extensions/index.js.map +1 -1
  174. package/dist/extensions/mcp/cli.d.ts.map +1 -1
  175. package/dist/extensions/mcp/cli.js +20 -5
  176. package/dist/extensions/mcp/cli.js.map +1 -1
  177. package/dist/extensions/mcp/config.d.ts +4 -2
  178. package/dist/extensions/mcp/config.d.ts.map +1 -1
  179. package/dist/extensions/mcp/config.js +14 -2
  180. package/dist/extensions/mcp/config.js.map +1 -1
  181. package/dist/extensions/mcp/index.d.ts +32 -8
  182. package/dist/extensions/mcp/index.d.ts.map +1 -1
  183. package/dist/extensions/mcp/index.js +235 -61
  184. package/dist/extensions/mcp/index.js.map +1 -1
  185. package/dist/extensions/mcp/oauth.d.ts +10 -7
  186. package/dist/extensions/mcp/oauth.d.ts.map +1 -1
  187. package/dist/extensions/mcp/oauth.js +56 -31
  188. package/dist/extensions/mcp/oauth.js.map +1 -1
  189. package/dist/extensions/mcp/runtime.d.ts +2 -0
  190. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  191. package/dist/extensions/mcp/runtime.js +16 -9
  192. package/dist/extensions/mcp/runtime.js.map +1 -1
  193. package/dist/extensions/mcp/tools.d.ts +5 -4
  194. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  195. package/dist/extensions/mcp/tools.js +33 -15
  196. package/dist/extensions/mcp/tools.js.map +1 -1
  197. package/dist/extensions/mcp/ui.d.ts.map +1 -1
  198. package/dist/extensions/mcp/ui.js +4 -2
  199. package/dist/extensions/mcp/ui.js.map +1 -1
  200. package/dist/extensions/provider/catalog.d.ts +8 -1
  201. package/dist/extensions/provider/catalog.d.ts.map +1 -1
  202. package/dist/extensions/provider/catalog.js +31 -0
  203. package/dist/extensions/provider/catalog.js.map +1 -1
  204. package/dist/extensions/provider/connection.d.ts +4 -1
  205. package/dist/extensions/provider/connection.d.ts.map +1 -1
  206. package/dist/extensions/provider/connection.js +1 -5
  207. package/dist/extensions/provider/connection.js.map +1 -1
  208. package/dist/extensions/provider/editing.d.ts +36 -0
  209. package/dist/extensions/provider/editing.d.ts.map +1 -0
  210. package/dist/extensions/provider/editing.js +99 -0
  211. package/dist/extensions/provider/editing.js.map +1 -0
  212. package/dist/extensions/provider/json-fields.d.ts +5 -0
  213. package/dist/extensions/provider/json-fields.d.ts.map +1 -0
  214. package/dist/extensions/provider/json-fields.js +31 -0
  215. package/dist/extensions/provider/json-fields.js.map +1 -0
  216. package/dist/extensions/provider/store.d.ts +1 -4
  217. package/dist/extensions/provider/store.d.ts.map +1 -1
  218. package/dist/extensions/provider/store.js +2 -30
  219. package/dist/extensions/provider/store.js.map +1 -1
  220. package/dist/extensions/provider/ui/builtin-data.d.ts +0 -2
  221. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  222. package/dist/extensions/provider/ui/builtin-data.js +14 -79
  223. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  224. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  225. package/dist/extensions/provider/ui/compat.js +6 -9
  226. package/dist/extensions/provider/ui/compat.js.map +1 -1
  227. package/dist/extensions/provider/ui/controls.d.ts +48 -0
  228. package/dist/extensions/provider/ui/controls.d.ts.map +1 -0
  229. package/dist/extensions/provider/ui/controls.js +108 -0
  230. package/dist/extensions/provider/ui/controls.js.map +1 -0
  231. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  232. package/dist/extensions/provider/ui/dictionary.js +6 -9
  233. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  234. package/dist/extensions/provider/ui/editor.d.ts +3 -3
  235. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  236. package/dist/extensions/provider/ui/editor.js +35 -140
  237. package/dist/extensions/provider/ui/editor.js.map +1 -1
  238. package/dist/extensions/provider/ui/fetch-models.d.ts +0 -3
  239. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  240. package/dist/extensions/provider/ui/fetch-models.js +49 -44
  241. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  242. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  243. package/dist/extensions/provider/ui/model-fields.js +11 -14
  244. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  245. package/dist/extensions/provider/ui/model-options.d.ts +4 -34
  246. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  247. package/dist/extensions/provider/ui/model-options.js +90 -271
  248. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  249. package/dist/extensions/provider/ui/pane.d.ts +4 -18
  250. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  251. package/dist/extensions/provider/ui/pane.js.map +1 -1
  252. package/dist/extensions/provider/ui/provider-fields.d.ts +2 -19
  253. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  254. package/dist/extensions/provider/ui/provider-fields.js +58 -171
  255. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  256. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  257. package/dist/extensions/provider/ui/thinking-map.js +6 -9
  258. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  259. package/dist/extensions/question/detail-pane.d.ts +7 -2
  260. package/dist/extensions/question/detail-pane.d.ts.map +1 -1
  261. package/dist/extensions/question/detail-pane.js +16 -5
  262. package/dist/extensions/question/detail-pane.js.map +1 -1
  263. package/dist/extensions/question/dialog-view.d.ts +41 -0
  264. package/dist/extensions/question/dialog-view.d.ts.map +1 -0
  265. package/dist/extensions/question/dialog-view.js +329 -0
  266. package/dist/extensions/question/dialog-view.js.map +1 -0
  267. package/dist/extensions/question/dialog.d.ts +3 -3
  268. package/dist/extensions/question/dialog.d.ts.map +1 -1
  269. package/dist/extensions/question/dialog.js +220 -634
  270. package/dist/extensions/question/dialog.js.map +1 -1
  271. package/dist/extensions/question/index.d.ts.map +1 -1
  272. package/dist/extensions/question/index.js +2 -3
  273. package/dist/extensions/question/index.js.map +1 -1
  274. package/dist/extensions/question/render.d.ts.map +1 -1
  275. package/dist/extensions/question/render.js +22 -32
  276. package/dist/extensions/question/render.js.map +1 -1
  277. package/dist/extensions/question/results.d.ts.map +1 -1
  278. package/dist/extensions/question/results.js +56 -12
  279. package/dist/extensions/question/results.js.map +1 -1
  280. package/dist/extensions/question/schema.d.ts +21 -6
  281. package/dist/extensions/question/schema.d.ts.map +1 -1
  282. package/dist/extensions/question/schema.js.map +1 -1
  283. package/dist/extensions/question/state.d.ts +9 -7
  284. package/dist/extensions/question/state.d.ts.map +1 -1
  285. package/dist/extensions/question/state.js +63 -54
  286. package/dist/extensions/question/state.js.map +1 -1
  287. package/dist/extensions/question/types.d.ts +41 -18
  288. package/dist/extensions/question/types.d.ts.map +1 -1
  289. package/dist/extensions/question/types.js.map +1 -1
  290. package/dist/extensions/statusline/index.d.ts +4 -0
  291. package/dist/extensions/statusline/index.d.ts.map +1 -1
  292. package/dist/extensions/statusline/index.js +18 -355
  293. package/dist/extensions/statusline/index.js.map +1 -1
  294. package/dist/extensions/statusline/render.d.ts +19 -0
  295. package/dist/extensions/statusline/render.d.ts.map +1 -0
  296. package/dist/extensions/statusline/render.js +163 -0
  297. package/dist/extensions/statusline/render.js.map +1 -0
  298. package/dist/extensions/statusline/usage.d.ts +12 -0
  299. package/dist/extensions/statusline/usage.d.ts.map +1 -0
  300. package/dist/extensions/statusline/usage.js +36 -0
  301. package/dist/extensions/statusline/usage.js.map +1 -0
  302. package/dist/extensions/tool-search/tool.d.ts +5 -4
  303. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  304. package/dist/extensions/tool-search/tool.js +7 -28
  305. package/dist/extensions/tool-search/tool.js.map +1 -1
  306. package/dist/extensions/web-search/execute.d.ts +1 -5
  307. package/dist/extensions/web-search/execute.d.ts.map +1 -1
  308. package/dist/extensions/web-search/execute.js +4 -9
  309. package/dist/extensions/web-search/execute.js.map +1 -1
  310. package/dist/extensions/web-search/format.d.ts +12 -3
  311. package/dist/extensions/web-search/format.d.ts.map +1 -1
  312. package/dist/extensions/web-search/format.js +33 -25
  313. package/dist/extensions/web-search/format.js.map +1 -1
  314. package/dist/extensions/web-search/index.d.ts.map +1 -1
  315. package/dist/extensions/web-search/index.js +6 -29
  316. package/dist/extensions/web-search/index.js.map +1 -1
  317. package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -1
  318. package/dist/extensions/web-search/providers/deepseek.js +0 -1
  319. package/dist/extensions/web-search/providers/deepseek.js.map +1 -1
  320. package/dist/extensions/web-search/providers/http.d.ts +1 -1
  321. package/dist/extensions/web-search/providers/http.d.ts.map +1 -1
  322. package/dist/extensions/web-search/providers/http.js.map +1 -1
  323. package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -1
  324. package/dist/extensions/web-search/providers/minimax.js +0 -1
  325. package/dist/extensions/web-search/providers/minimax.js.map +1 -1
  326. package/dist/extensions/web-search/render.d.ts +7 -2
  327. package/dist/extensions/web-search/render.d.ts.map +1 -1
  328. package/dist/extensions/web-search/render.js +32 -4
  329. package/dist/extensions/web-search/render.js.map +1 -1
  330. package/dist/extensions/web-search/results.d.ts.map +1 -1
  331. package/dist/extensions/web-search/results.js +3 -8
  332. package/dist/extensions/web-search/results.js.map +1 -1
  333. package/dist/extensions/web-search/types.d.ts +4 -2
  334. package/dist/extensions/web-search/types.d.ts.map +1 -1
  335. package/dist/extensions/web-search/types.js.map +1 -1
  336. package/dist/index.d.ts +2 -4
  337. package/dist/index.d.ts.map +1 -1
  338. package/dist/index.js +0 -1
  339. package/dist/index.js.map +1 -1
  340. package/dist/main.d.ts.map +1 -1
  341. package/dist/main.js +6 -0
  342. package/dist/main.js.map +1 -1
  343. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  344. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  345. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  346. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  347. package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
  348. package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
  349. package/dist/modes/interactive/components/pi-logo-animation.js +1076 -0
  350. package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
  351. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
  352. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
  353. package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
  354. package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
  355. package/dist/modes/interactive/components/pi-logo.d.ts +7 -0
  356. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
  357. package/dist/modes/interactive/components/pi-logo.js +13 -1
  358. package/dist/modes/interactive/components/pi-logo.js.map +1 -1
  359. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  360. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  361. package/dist/modes/interactive/components/radius-login-selector.js +83 -0
  362. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  363. package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
  364. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  365. package/dist/modes/interactive/components/settings-selector.js +5 -5
  366. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  367. package/dist/modes/interactive/components/status-marker.d.ts +0 -2
  368. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  369. package/dist/modes/interactive/components/status-marker.js +0 -4
  370. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  371. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  372. package/dist/modes/interactive/components/user-message.js +5 -4
  373. package/dist/modes/interactive/components/user-message.js.map +1 -1
  374. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  375. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  376. package/dist/modes/interactive/components/visual-truncate.js +36 -6
  377. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  378. package/dist/modes/interactive/interactive-mode.d.ts +10 -0
  379. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  380. package/dist/modes/interactive/interactive-mode.js +167 -40
  381. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  382. package/dist/modes/interactive/tasks/completion-render.d.ts +1 -1
  383. package/dist/modes/interactive/tasks/completion-render.d.ts.map +1 -1
  384. package/dist/modes/interactive/tasks/completion-render.js +28 -82
  385. package/dist/modes/interactive/tasks/completion-render.js.map +1 -1
  386. package/dist/modes/interactive/tasks/index.d.ts.map +1 -1
  387. package/dist/modes/interactive/tasks/index.js +18 -13
  388. package/dist/modes/interactive/tasks/index.js.map +1 -1
  389. package/dist/modes/interactive/tasks/inspector.d.ts +35 -0
  390. package/dist/modes/interactive/tasks/inspector.d.ts.map +1 -0
  391. package/dist/modes/interactive/tasks/inspector.js +93 -0
  392. package/dist/modes/interactive/tasks/inspector.js.map +1 -0
  393. package/dist/modes/interactive/tasks/layout.d.ts +40 -0
  394. package/dist/modes/interactive/tasks/layout.d.ts.map +1 -0
  395. package/dist/modes/interactive/tasks/layout.js +212 -0
  396. package/dist/modes/interactive/tasks/layout.js.map +1 -0
  397. package/dist/modes/interactive/tasks/list.d.ts +21 -0
  398. package/dist/modes/interactive/tasks/list.d.ts.map +1 -0
  399. package/dist/modes/interactive/tasks/list.js +96 -0
  400. package/dist/modes/interactive/tasks/list.js.map +1 -0
  401. package/dist/modes/interactive/tasks/manager.d.ts +29 -36
  402. package/dist/modes/interactive/tasks/manager.d.ts.map +1 -1
  403. package/dist/modes/interactive/tasks/manager.js +315 -315
  404. package/dist/modes/interactive/tasks/manager.js.map +1 -1
  405. package/dist/modes/interactive/tasks/model.d.ts +21 -0
  406. package/dist/modes/interactive/tasks/model.d.ts.map +1 -0
  407. package/dist/modes/interactive/tasks/model.js +41 -0
  408. package/dist/modes/interactive/tasks/model.js.map +1 -0
  409. package/dist/modes/interactive/tasks/render.d.ts +5 -19
  410. package/dist/modes/interactive/tasks/render.d.ts.map +1 -1
  411. package/dist/modes/interactive/tasks/render.js +18 -102
  412. package/dist/modes/interactive/tasks/render.js.map +1 -1
  413. package/dist/modes/interactive/tasks/task-view.d.ts +8 -48
  414. package/dist/modes/interactive/tasks/task-view.d.ts.map +1 -1
  415. package/dist/modes/interactive/tasks/task-view.js +11 -51
  416. package/dist/modes/interactive/tasks/task-view.js.map +1 -1
  417. package/dist/modes/interactive/tasks/text.d.ts +1 -7
  418. package/dist/modes/interactive/tasks/text.d.ts.map +1 -1
  419. package/dist/modes/interactive/tasks/text.js +6 -29
  420. package/dist/modes/interactive/tasks/text.js.map +1 -1
  421. package/dist/modes/interactive/tasks/viewport.d.ts +2 -0
  422. package/dist/modes/interactive/tasks/viewport.d.ts.map +1 -1
  423. package/dist/modes/interactive/tasks/viewport.js +17 -7
  424. package/dist/modes/interactive/tasks/viewport.js.map +1 -1
  425. package/dist/modes/interactive/tasks/views.d.ts +9 -0
  426. package/dist/modes/interactive/tasks/views.d.ts.map +1 -0
  427. package/dist/modes/interactive/tasks/views.js +42 -0
  428. package/dist/modes/interactive/tasks/views.js.map +1 -0
  429. package/dist/modes/interactive/theme/system-theme.d.ts +2 -1
  430. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
  431. package/dist/modes/interactive/theme/system-theme.js +16 -5
  432. package/dist/modes/interactive/theme/system-theme.js.map +1 -1
  433. package/docs/bundled/README.md +0 -1
  434. package/docs/bundled/extensions/question.md +2 -2
  435. package/docs/bundled/extensions/statusline.md +24 -15
  436. package/docs/bundled/tasks.md +34 -48
  437. package/docs/codemode.md +207 -0
  438. package/docs/docs.json +4 -4
  439. package/docs/environment-variables.md +1 -1
  440. package/docs/extensions.md +7 -9
  441. package/docs/keybindings.md +13 -6
  442. package/docs/mcp.md +142 -82
  443. package/docs/models.md +21 -0
  444. package/docs/providers.md +8 -0
  445. package/docs/sdk.md +2 -2
  446. package/docs/session-format.md +12 -22
  447. package/docs/settings.md +4 -2
  448. package/docs/tui.md +1 -1
  449. package/docs/usage.md +6 -16
  450. package/examples/README.md +1 -1
  451. package/examples/extensions/README.md +1 -2
  452. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  453. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  454. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  455. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  456. package/examples/extensions/gondolin/package-lock.json +2 -2
  457. package/examples/extensions/gondolin/package.json +1 -1
  458. package/examples/extensions/minimal-mode.ts +24 -96
  459. package/examples/extensions/sandbox/package-lock.json +2 -2
  460. package/examples/extensions/sandbox/package.json +1 -1
  461. package/examples/extensions/with-deps/package-lock.json +2 -2
  462. package/examples/extensions/with-deps/package.json +1 -1
  463. package/examples/sdk/14-codemode-mcp.ts +2 -2
  464. package/npm-shrinkwrap.json +69 -58
  465. package/package.json +11 -10
  466. package/dist/bundle/chunks/anthropic-messages-KIXY7EDT.js +0 -6
  467. package/dist/bundle/chunks/chunk-CLLDCO64.js +0 -2
  468. package/dist/bundle/chunks/chunk-UUSTLCVC.js +0 -2
  469. package/dist/bundle/chunks/chunk-VWCWZD6E.js +0 -2
  470. package/dist/bundle/chunks/virtual-modules-TQRORWJQ.js +0 -2
  471. package/dist/core/tasks/view-data.d.ts +0 -8
  472. package/dist/core/tasks/view-data.d.ts.map +0 -1
  473. package/dist/core/tasks/view-data.js +0 -61
  474. package/dist/core/tasks/view-data.js.map +0 -1
  475. package/dist/core/tasks/view.d.ts +0 -30
  476. package/dist/core/tasks/view.d.ts.map +0 -1
  477. package/dist/core/tasks/view.js +0 -50
  478. package/dist/core/tasks/view.js.map +0 -1
  479. package/dist/core/tools/renderers/shell-task.d.ts +0 -4
  480. package/dist/core/tools/renderers/shell-task.d.ts.map +0 -1
  481. package/dist/core/tools/renderers/shell-task.js +0 -35
  482. package/dist/core/tools/renderers/shell-task.js.map +0 -1
  483. package/dist/extensions/todo/constants.d.ts +0 -16
  484. package/dist/extensions/todo/constants.d.ts.map +0 -1
  485. package/dist/extensions/todo/constants.js +0 -30
  486. package/dist/extensions/todo/constants.js.map +0 -1
  487. package/dist/extensions/todo/index.d.ts +0 -3
  488. package/dist/extensions/todo/index.d.ts.map +0 -1
  489. package/dist/extensions/todo/index.js +0 -98
  490. package/dist/extensions/todo/index.js.map +0 -1
  491. package/dist/extensions/todo/schema.d.ts +0 -60
  492. package/dist/extensions/todo/schema.d.ts.map +0 -1
  493. package/dist/extensions/todo/schema.js +0 -56
  494. package/dist/extensions/todo/schema.js.map +0 -1
  495. package/dist/extensions/todo/state.d.ts +0 -34
  496. package/dist/extensions/todo/state.d.ts.map +0 -1
  497. package/dist/extensions/todo/state.js +0 -425
  498. package/dist/extensions/todo/state.js.map +0 -1
  499. package/dist/extensions/todo/view.d.ts +0 -36
  500. package/dist/extensions/todo/view.d.ts.map +0 -1
  501. package/dist/extensions/todo/view.js +0 -580
  502. package/dist/extensions/todo/view.js.map +0 -1
  503. package/dist/extensions/todo/widget.d.ts +0 -15
  504. package/dist/extensions/todo/widget.d.ts.map +0 -1
  505. package/dist/extensions/todo/widget.js +0 -50
  506. package/dist/extensions/todo/widget.js.map +0 -1
  507. package/dist/modes/interactive/tasks/fallback-view.d.ts +0 -4
  508. package/dist/modes/interactive/tasks/fallback-view.d.ts.map +0 -1
  509. package/dist/modes/interactive/tasks/fallback-view.js +0 -27
  510. package/dist/modes/interactive/tasks/fallback-view.js.map +0 -1
  511. package/docs/bundled/extensions/todo.md +0 -104
  512. package/examples/extensions/todo.ts +0 -297
@@ -0,0 +1,163 @@
1
+ import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
2
+ const CONTEXT_WARNING_PERCENT = 40;
3
+ const CONTEXT_ERROR_PERCENT = 80;
4
+ const MIN_GAP = 1;
5
+ /** Shorten a path to `~` relative to the user's home directory. */
6
+ function formatWorkingDirectory(cwd, home) {
7
+ const homeDirectory = home.replace(/[\\/]+$/, "");
8
+ if (!homeDirectory)
9
+ return cwd;
10
+ const normalizePath = (filePath) => filePath.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
11
+ const normalizedHomeDirectory = normalizePath(homeDirectory);
12
+ const normalizedCwd = normalizePath(cwd);
13
+ if (normalizedCwd === normalizedHomeDirectory)
14
+ return "~";
15
+ if (normalizedCwd.startsWith(`${normalizedHomeDirectory}/`)) {
16
+ return `~${cwd.slice(homeDirectory.length).replace(/\\/g, "/")}`;
17
+ }
18
+ return cwd;
19
+ }
20
+ /** Collapse a display path to `~/basename` or bare basename when tight. */
21
+ function pathBasename(displayPath) {
22
+ const normalized = displayPath.replace(/\\/g, "/").replace(/\/+$/, "");
23
+ if (!normalized || normalized === "~")
24
+ return normalized || displayPath;
25
+ const slash = normalized.lastIndexOf("/");
26
+ if (slash < 0)
27
+ return normalized;
28
+ const base = normalized.slice(slash + 1);
29
+ return normalized.startsWith("~/") ? `~/${base}` : base;
30
+ }
31
+ function formatTokenCount(count) {
32
+ if (count < 1000)
33
+ return `${count}`;
34
+ if (count < 10_000)
35
+ return `${(count / 1000).toFixed(1)}k`;
36
+ if (count < 1_000_000)
37
+ return `${Math.round(count / 1000)}k`;
38
+ if (count < 10_000_000)
39
+ return `${(count / 1_000_000).toFixed(1)}M`;
40
+ return `${Math.round(count / 1_000_000)}M`;
41
+ }
42
+ function joinSegments(segments, separator) {
43
+ return segments.filter(Boolean).join(separator);
44
+ }
45
+ function formatContextUsage(data, theme) {
46
+ const contextWindow = data.contextUsage?.contextWindow ?? data.model?.contextWindow;
47
+ const suffix = contextWindow ? `/${formatTokenCount(contextWindow)}` : "";
48
+ const percent = data.contextUsage?.percent;
49
+ const label = `CTX ${percent == null ? "?" : percent.toFixed(1)}%${suffix}`;
50
+ if (percent != null && percent > CONTEXT_ERROR_PERCENT)
51
+ return theme.fg("error", label);
52
+ if (percent != null && percent > CONTEXT_WARNING_PERCENT)
53
+ return theme.fg("warning", label);
54
+ return theme.fg("accent", label);
55
+ }
56
+ /** Format fields once, then offer full usage, without W, and without W/R. */
57
+ function formatUsageCandidates(summary, subscription, theme) {
58
+ const tokens = [
59
+ summary.input > 0 ? `↑${formatTokenCount(summary.input)}` : "",
60
+ summary.output > 0 ? `↓${formatTokenCount(summary.output)}` : "",
61
+ ];
62
+ const read = summary.cacheRead > 0 ? `R${formatTokenCount(summary.cacheRead)}` : "";
63
+ const write = summary.cacheWrite > 0 ? `W${formatTokenCount(summary.cacheWrite)}` : "";
64
+ const suffix = [
65
+ summary.latestCacheHitPercent === undefined ? "" : `CH${summary.latestCacheHitPercent.toFixed(1)}%`,
66
+ summary.cost > 0 ? `$${summary.cost.toFixed(3)}${subscription ? " (sub)" : ""}` : "",
67
+ ];
68
+ const candidates = [[read, write], [read], []].map((cache) => joinSegments([...tokens, ...cache, ...suffix], " "));
69
+ return [...new Set(candidates.filter(Boolean))].map((text) => theme.fg("dim", text));
70
+ }
71
+ function formatExtensionStatuses(statuses, theme) {
72
+ return ([...statuses.entries()]
73
+ .sort(([first], [second]) => first.localeCompare(second))
74
+ .map(([, text]) => text
75
+ .replace(/[\r\n\t]/g, " ")
76
+ .replace(/ +/g, " ")
77
+ .trim())
78
+ .filter(Boolean)
79
+ // Preserve colors supplied by other extensions.
80
+ .map((text) => (text.includes("\x1b[") ? text : theme.fg("muted", text)))
81
+ .join(" "));
82
+ }
83
+ function fitsLeftRight(left, right, width) {
84
+ return visibleWidth(left) + visibleWidth(right) + (left && right ? MIN_GAP : 0) <= width;
85
+ }
86
+ /** Right-align the second cluster; when both compete, cap it at about 45%. */
87
+ function layoutLeftRight(left, right, width, ellipsis) {
88
+ if (width <= 0)
89
+ return "";
90
+ if (!right)
91
+ return truncateToWidth(left, width, ellipsis);
92
+ let rightWidth = visibleWidth(right);
93
+ if (!left)
94
+ return `${" ".repeat(Math.max(0, width - rightWidth))}${truncateToWidth(right, width, ellipsis)}`;
95
+ let leftWidth = visibleWidth(left);
96
+ if (leftWidth + rightWidth + MIN_GAP > width) {
97
+ const maxRightWidth = Math.min(rightWidth, Math.max(8, Math.floor(width * 0.45)));
98
+ right = truncateToWidth(right, maxRightWidth, ellipsis);
99
+ rightWidth = visibleWidth(right);
100
+ const maxLeftWidth = width - rightWidth - MIN_GAP;
101
+ if (maxLeftWidth < 1)
102
+ return truncateToWidth(right, width, ellipsis);
103
+ left = truncateToWidth(left, maxLeftWidth, ellipsis);
104
+ leftWidth = visibleWidth(left);
105
+ }
106
+ return `${left}${" ".repeat(Math.max(MIN_GAP, width - leftWidth - rightWidth))}${right}`;
107
+ }
108
+ /** Center status absolutely when possible; otherwise balance the remaining gap. */
109
+ function layoutSecondaryLine(left, status, right, width, ellipsis) {
110
+ const leftWidth = visibleWidth(left);
111
+ const statusWidth = visibleWidth(status);
112
+ const rightWidth = visibleWidth(right);
113
+ const free = width - leftWidth - statusWidth - rightWidth;
114
+ if (!status || free < MIN_GAP * 2)
115
+ return layoutLeftRight(left, right, width, ellipsis);
116
+ let leftPad = Math.floor((width - statusWidth) / 2) - leftWidth;
117
+ if (leftPad < MIN_GAP || free - leftPad < MIN_GAP)
118
+ leftPad = Math.floor(free / 2);
119
+ return `${left}${" ".repeat(leftPad)}${status}${" ".repeat(free - leftPad)}${right}`;
120
+ }
121
+ function renderPrimaryLine(data, theme, width, ellipsis) {
122
+ const { model, thinkingLevel } = data;
123
+ const name = theme.fg("toolTitle", theme.bold(model?.name ?? model?.id ?? "no-model"));
124
+ const provider = model?.provider ? theme.fg("muted", `(${model.provider})`) : "";
125
+ const effort = model?.reasoning && thinkingLevel !== "off" ? theme.getThinkingBorderColor(thinkingLevel)(thinkingLevel) : "";
126
+ const separator = theme.fg("dim", " · ");
127
+ const rich = joinSegments([joinSegments([name, provider], " "), effort], separator);
128
+ const plain = joinSegments([name, effort], separator);
129
+ const cwd = formatWorkingDirectory(data.cwd, data.home);
130
+ const full = theme.fg("success", cwd);
131
+ const short = theme.fg("success", pathBasename(cwd));
132
+ const branch = data.gitBranch ? theme.fg("accent", data.gitBranch) : "";
133
+ // Shortening the path or removing the provider can make room for the branch again.
134
+ const candidates = [
135
+ { left: rich, right: joinSegments([full, branch], separator) },
136
+ { left: rich, right: full },
137
+ { left: rich, right: joinSegments([short, branch], separator) },
138
+ { left: rich, right: short },
139
+ { left: plain, right: joinSegments([short, branch], separator) },
140
+ { left: plain, right: short },
141
+ { left: plain, right: "" },
142
+ ];
143
+ const chosen = candidates.find(({ left, right }) => fitsLeftRight(left, right, width)) ?? {
144
+ left: plain,
145
+ right: short,
146
+ };
147
+ return layoutLeftRight(chosen.left, chosen.right, width, ellipsis);
148
+ }
149
+ /** Fixed two-line presentation, independent of session access and footer lifecycle. */
150
+ export function renderStatusline(data, theme, width) {
151
+ const ellipsis = theme.fg("dim", "...");
152
+ const primary = renderPrimaryLine(data, theme, width, ellipsis);
153
+ const context = formatContextUsage(data, theme);
154
+ const status = formatExtensionStatuses(data.statuses, theme);
155
+ const candidates = formatUsageCandidates(data.usage, data.usesSubscription, theme);
156
+ const usage = candidates.find((candidate) => fitsLeftRight(context, candidate, width));
157
+ // If no usage variant fits, retain the original full-usage truncation policy.
158
+ const secondary = candidates.length > 0 && usage === undefined
159
+ ? layoutLeftRight(context, candidates[0], width, ellipsis)
160
+ : layoutSecondaryLine(context, status, usage ?? "", width, ellipsis);
161
+ return [primary, secondary];
162
+ }
163
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/extensions/statusline/render.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Model } from \"@earendil-works/pi-ai\";\nimport { truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport type { ContextUsage } from \"../../core/extensions/types.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { UsageSummary } from \"./usage.ts\";\n\nexport interface StatuslineData {\n\tmodel: Pick<Model<string>, \"id\" | \"name\" | \"provider\" | \"reasoning\" | \"contextWindow\"> | undefined;\n\tthinkingLevel: ThinkingLevel;\n\tcwd: string;\n\thome: string;\n\tgitBranch: string | null;\n\tcontextUsage: ContextUsage | undefined;\n\tusage: UsageSummary;\n\tusesSubscription: boolean;\n\tstatuses: ReadonlyMap<string, string>;\n}\n\nconst CONTEXT_WARNING_PERCENT = 40;\nconst CONTEXT_ERROR_PERCENT = 80;\nconst MIN_GAP = 1;\n\n/** Shorten a path to `~` relative to the user's home directory. */\nfunction formatWorkingDirectory(cwd: string, home: string): string {\n\tconst homeDirectory = home.replace(/[\\\\/]+$/, \"\");\n\tif (!homeDirectory) return cwd;\n\tconst normalizePath = (filePath: string) => filePath.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\").toLowerCase();\n\tconst normalizedHomeDirectory = normalizePath(homeDirectory);\n\tconst normalizedCwd = normalizePath(cwd);\n\tif (normalizedCwd === normalizedHomeDirectory) return \"~\";\n\tif (normalizedCwd.startsWith(`${normalizedHomeDirectory}/`)) {\n\t\treturn `~${cwd.slice(homeDirectory.length).replace(/\\\\/g, \"/\")}`;\n\t}\n\treturn cwd;\n}\n\n/** Collapse a display path to `~/basename` or bare basename when tight. */\nfunction pathBasename(displayPath: string): string {\n\tconst normalized = displayPath.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n\tif (!normalized || normalized === \"~\") return normalized || displayPath;\n\tconst slash = normalized.lastIndexOf(\"/\");\n\tif (slash < 0) return normalized;\n\tconst base = normalized.slice(slash + 1);\n\treturn normalized.startsWith(\"~/\") ? `~/${base}` : base;\n}\n\nfunction formatTokenCount(count: number): string {\n\tif (count < 1000) return `${count}`;\n\tif (count < 10_000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1_000_000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10_000_000) return `${(count / 1_000_000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1_000_000)}M`;\n}\n\nfunction joinSegments(segments: string[], separator: string): string {\n\treturn segments.filter(Boolean).join(separator);\n}\n\nfunction formatContextUsage(data: StatuslineData, theme: Theme): string {\n\tconst contextWindow = data.contextUsage?.contextWindow ?? data.model?.contextWindow;\n\tconst suffix = contextWindow ? `/${formatTokenCount(contextWindow)}` : \"\";\n\tconst percent = data.contextUsage?.percent;\n\tconst label = `CTX ${percent == null ? \"?\" : percent.toFixed(1)}%${suffix}`;\n\tif (percent != null && percent > CONTEXT_ERROR_PERCENT) return theme.fg(\"error\", label);\n\tif (percent != null && percent > CONTEXT_WARNING_PERCENT) return theme.fg(\"warning\", label);\n\treturn theme.fg(\"accent\", label);\n}\n\n/** Format fields once, then offer full usage, without W, and without W/R. */\nfunction formatUsageCandidates(summary: UsageSummary, subscription: boolean, theme: Theme): string[] {\n\tconst tokens = [\n\t\tsummary.input > 0 ? `↑${formatTokenCount(summary.input)}` : \"\",\n\t\tsummary.output > 0 ? `↓${formatTokenCount(summary.output)}` : \"\",\n\t];\n\tconst read = summary.cacheRead > 0 ? `R${formatTokenCount(summary.cacheRead)}` : \"\";\n\tconst write = summary.cacheWrite > 0 ? `W${formatTokenCount(summary.cacheWrite)}` : \"\";\n\tconst suffix = [\n\t\tsummary.latestCacheHitPercent === undefined ? \"\" : `CH${summary.latestCacheHitPercent.toFixed(1)}%`,\n\t\tsummary.cost > 0 ? `$${summary.cost.toFixed(3)}${subscription ? \" (sub)\" : \"\"}` : \"\",\n\t];\n\tconst candidates = [[read, write], [read], []].map((cache) => joinSegments([...tokens, ...cache, ...suffix], \" \"));\n\treturn [...new Set(candidates.filter(Boolean))].map((text) => theme.fg(\"dim\", text));\n}\n\nfunction formatExtensionStatuses(statuses: ReadonlyMap<string, string>, theme: Theme): string {\n\treturn (\n\t\t[...statuses.entries()]\n\t\t\t.sort(([first], [second]) => first.localeCompare(second))\n\t\t\t.map(([, text]) =>\n\t\t\t\ttext\n\t\t\t\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t\t\t\t.replace(/ +/g, \" \")\n\t\t\t\t\t.trim(),\n\t\t\t)\n\t\t\t.filter(Boolean)\n\t\t\t// Preserve colors supplied by other extensions.\n\t\t\t.map((text) => (text.includes(\"\\x1b[\") ? text : theme.fg(\"muted\", text)))\n\t\t\t.join(\" \")\n\t);\n}\n\nfunction fitsLeftRight(left: string, right: string, width: number): boolean {\n\treturn visibleWidth(left) + visibleWidth(right) + (left && right ? MIN_GAP : 0) <= width;\n}\n\n/** Right-align the second cluster; when both compete, cap it at about 45%. */\nfunction layoutLeftRight(left: string, right: string, width: number, ellipsis: string): string {\n\tif (width <= 0) return \"\";\n\tif (!right) return truncateToWidth(left, width, ellipsis);\n\tlet rightWidth = visibleWidth(right);\n\tif (!left) return `${\" \".repeat(Math.max(0, width - rightWidth))}${truncateToWidth(right, width, ellipsis)}`;\n\tlet leftWidth = visibleWidth(left);\n\tif (leftWidth + rightWidth + MIN_GAP > width) {\n\t\tconst maxRightWidth = Math.min(rightWidth, Math.max(8, Math.floor(width * 0.45)));\n\t\tright = truncateToWidth(right, maxRightWidth, ellipsis);\n\t\trightWidth = visibleWidth(right);\n\t\tconst maxLeftWidth = width - rightWidth - MIN_GAP;\n\t\tif (maxLeftWidth < 1) return truncateToWidth(right, width, ellipsis);\n\t\tleft = truncateToWidth(left, maxLeftWidth, ellipsis);\n\t\tleftWidth = visibleWidth(left);\n\t}\n\treturn `${left}${\" \".repeat(Math.max(MIN_GAP, width - leftWidth - rightWidth))}${right}`;\n}\n\n/** Center status absolutely when possible; otherwise balance the remaining gap. */\nfunction layoutSecondaryLine(left: string, status: string, right: string, width: number, ellipsis: string): string {\n\tconst leftWidth = visibleWidth(left);\n\tconst statusWidth = visibleWidth(status);\n\tconst rightWidth = visibleWidth(right);\n\tconst free = width - leftWidth - statusWidth - rightWidth;\n\tif (!status || free < MIN_GAP * 2) return layoutLeftRight(left, right, width, ellipsis);\n\tlet leftPad = Math.floor((width - statusWidth) / 2) - leftWidth;\n\tif (leftPad < MIN_GAP || free - leftPad < MIN_GAP) leftPad = Math.floor(free / 2);\n\treturn `${left}${\" \".repeat(leftPad)}${status}${\" \".repeat(free - leftPad)}${right}`;\n}\n\nfunction renderPrimaryLine(data: StatuslineData, theme: Theme, width: number, ellipsis: string): string {\n\tconst { model, thinkingLevel } = data;\n\tconst name = theme.fg(\"toolTitle\", theme.bold(model?.name ?? model?.id ?? \"no-model\"));\n\tconst provider = model?.provider ? theme.fg(\"muted\", `(${model.provider})`) : \"\";\n\tconst effort =\n\t\tmodel?.reasoning && thinkingLevel !== \"off\" ? theme.getThinkingBorderColor(thinkingLevel)(thinkingLevel) : \"\";\n\tconst separator = theme.fg(\"dim\", \" · \");\n\tconst rich = joinSegments([joinSegments([name, provider], \" \"), effort], separator);\n\tconst plain = joinSegments([name, effort], separator);\n\tconst cwd = formatWorkingDirectory(data.cwd, data.home);\n\tconst full = theme.fg(\"success\", cwd);\n\tconst short = theme.fg(\"success\", pathBasename(cwd));\n\tconst branch = data.gitBranch ? theme.fg(\"accent\", data.gitBranch) : \"\";\n\t// Shortening the path or removing the provider can make room for the branch again.\n\tconst candidates = [\n\t\t{ left: rich, right: joinSegments([full, branch], separator) },\n\t\t{ left: rich, right: full },\n\t\t{ left: rich, right: joinSegments([short, branch], separator) },\n\t\t{ left: rich, right: short },\n\t\t{ left: plain, right: joinSegments([short, branch], separator) },\n\t\t{ left: plain, right: short },\n\t\t{ left: plain, right: \"\" },\n\t];\n\tconst chosen = candidates.find(({ left, right }) => fitsLeftRight(left, right, width)) ?? {\n\t\tleft: plain,\n\t\tright: short,\n\t};\n\treturn layoutLeftRight(chosen.left, chosen.right, width, ellipsis);\n}\n\n/** Fixed two-line presentation, independent of session access and footer lifecycle. */\nexport function renderStatusline(data: StatuslineData, theme: Theme, width: number): string[] {\n\tconst ellipsis = theme.fg(\"dim\", \"...\");\n\tconst primary = renderPrimaryLine(data, theme, width, ellipsis);\n\tconst context = formatContextUsage(data, theme);\n\tconst status = formatExtensionStatuses(data.statuses, theme);\n\tconst candidates = formatUsageCandidates(data.usage, data.usesSubscription, theme);\n\tconst usage = candidates.find((candidate) => fitsLeftRight(context, candidate, width));\n\t// If no usage variant fits, retain the original full-usage truncation policy.\n\tconst secondary =\n\t\tcandidates.length > 0 && usage === undefined\n\t\t\t? layoutLeftRight(context, candidates[0], width, ellipsis)\n\t\t\t: layoutSecondaryLine(context, status, usage ?? \"\", width, ellipsis);\n\treturn [primary, secondary];\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import type { ReadonlySessionManager } from "../../core/session-manager.ts";
2
+ import { type UsageTotals } from "../../core/usage-totals.ts";
3
+ export interface UsageSummary extends UsageTotals {
4
+ latestCacheHitPercent: number | undefined;
5
+ }
6
+ /** Per-footer accounting cache. Persisted entries are append-only; every append moves the leaf. */
7
+ export declare class BranchUsage {
8
+ private cached?;
9
+ invalidate(): void;
10
+ read(manager: ReadonlySessionManager): UsageSummary;
11
+ }
12
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/extensions/statusline/usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAA2D,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEvH,MAAM,WAAW,YAAa,SAAQ,WAAW;IAChD,qBAAqB,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,mGAAmG;AACnG,qBAAa,WAAW;IACvB,OAAO,CAAC,MAAM,CAAC,CAKb;IAEF,UAAU,IAAI,IAAI;IAIlB,IAAI,CAAC,OAAO,EAAE,sBAAsB,GAAG,YAAY;CA6BnD"}
@@ -0,0 +1,36 @@
1
+ import { addUsageToTotals, createUsageTotals, getAccountedUsages } from "../../core/usage-totals.js";
2
+ /** Per-footer accounting cache. Persisted entries are append-only; every append moves the leaf. */
3
+ export class BranchUsage {
4
+ invalidate() {
5
+ this.cached = undefined;
6
+ }
7
+ read(manager) {
8
+ const sessionId = manager.getSessionId();
9
+ const leafId = manager.getLeafId();
10
+ if (this.cached?.manager === manager && this.cached.sessionId === sessionId && this.cached.leafId === leafId) {
11
+ return this.cached.usage;
12
+ }
13
+ const entries = manager.getBranch();
14
+ const totals = createUsageTotals();
15
+ for (const usage of getAccountedUsages(entries))
16
+ addUsageToTotals(totals, usage);
17
+ // CH belongs to the latest assistant request, including failures. Other
18
+ // usage contributes to totals without replacing that request's cache rate.
19
+ let latestCacheHitPercent;
20
+ for (let index = entries.length - 1; index >= 0; index--) {
21
+ const entry = entries[index];
22
+ if (entry.type !== "message" || entry.message.role !== "assistant")
23
+ continue;
24
+ const { input, cacheRead, cacheWrite } = entry.message.usage;
25
+ const promptTokens = input + cacheRead + cacheWrite;
26
+ if ((cacheRead > 0 || cacheWrite > 0) && promptTokens > 0) {
27
+ latestCacheHitPercent = (cacheRead / promptTokens) * 100;
28
+ }
29
+ break;
30
+ }
31
+ const usage = { ...totals, latestCacheHitPercent };
32
+ this.cached = { manager, sessionId, leafId, usage };
33
+ return usage;
34
+ }
35
+ }
36
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/extensions/statusline/usage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAoB,MAAM,4BAA4B,CAAC;AAMvH,mGAAmG;AACnG,MAAM,OAAO,WAAW;IAQvB,UAAU;QACT,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IACzB,CAAC;IAED,IAAI,CAAC,OAA+B;QACnC,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9G,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAC1B,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,kBAAkB,CAAC,OAAO,CAAC;YAAE,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAEjF,wEAAwE;QACxE,2EAA2E;QAC3E,IAAI,qBAAyC,CAAC;QAC9C,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;gBAAE,SAAS;YAC7E,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAC7D,MAAM,YAAY,GAAG,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC;YACpD,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;gBAC3D,qBAAqB,GAAG,CAAC,SAAS,GAAG,YAAY,CAAC,GAAG,GAAG,CAAC;YAC1D,CAAC;YACD,MAAM;QACP,CAAC;QAED,MAAM,KAAK,GAAG,EAAE,GAAG,MAAM,EAAE,qBAAqB,EAAE,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACd,CAAC;CACD","sourcesContent":["import type { ReadonlySessionManager } from \"../../core/session-manager.ts\";\nimport { addUsageToTotals, createUsageTotals, getAccountedUsages, type UsageTotals } from \"../../core/usage-totals.ts\";\n\nexport interface UsageSummary extends UsageTotals {\n\tlatestCacheHitPercent: number | undefined;\n}\n\n/** Per-footer accounting cache. Persisted entries are append-only; every append moves the leaf. */\nexport class BranchUsage {\n\tprivate cached?: {\n\t\tmanager: ReadonlySessionManager;\n\t\tsessionId: string;\n\t\tleafId: string | null;\n\t\tusage: UsageSummary;\n\t};\n\n\tinvalidate(): void {\n\t\tthis.cached = undefined;\n\t}\n\n\tread(manager: ReadonlySessionManager): UsageSummary {\n\t\tconst sessionId = manager.getSessionId();\n\t\tconst leafId = manager.getLeafId();\n\t\tif (this.cached?.manager === manager && this.cached.sessionId === sessionId && this.cached.leafId === leafId) {\n\t\t\treturn this.cached.usage;\n\t\t}\n\n\t\tconst entries = manager.getBranch();\n\t\tconst totals = createUsageTotals();\n\t\tfor (const usage of getAccountedUsages(entries)) addUsageToTotals(totals, usage);\n\n\t\t// CH belongs to the latest assistant request, including failures. Other\n\t\t// usage contributes to totals without replacing that request's cache rate.\n\t\tlet latestCacheHitPercent: number | undefined;\n\t\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\t\tconst entry = entries[index];\n\t\t\tif (entry.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n\t\t\tconst { input, cacheRead, cacheWrite } = entry.message.usage;\n\t\t\tconst promptTokens = input + cacheRead + cacheWrite;\n\t\t\tif ((cacheRead > 0 || cacheWrite > 0) && promptTokens > 0) {\n\t\t\t\tlatestCacheHitPercent = (cacheRead / promptTokens) * 100;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tconst usage = { ...totals, latestCacheHitPercent };\n\t\tthis.cached = { manager, sessionId, leafId, usage };\n\t\treturn usage;\n\t}\n}\n"]}
@@ -28,7 +28,8 @@ export interface ToolRanker {
28
28
  export declare function tokenize(text: string): string[];
29
29
  /**
30
30
  * Search text of a tool: the name, the name with `_`
31
- * as spaces, the description, schema descriptions and property names, and the namespace.
31
+ * as spaces, the description, schema descriptions and property names, and the namespace with its
32
+ * description and instructions.
32
33
  */
33
34
  export declare function createToolSearchDocument(tool: Pick<ToolInfo, "name" | "description" | "parameters">, namespace?: ToolNamespace): ToolSearchDocument;
34
35
  /** Okapi BM25 with the usual parameters. Ties keep document order. */
@@ -64,9 +65,9 @@ export interface ToolSearchToolOptions {
64
65
  tools?: Pick<ExtensionAPI, "getAllTools" | "getActiveTools" | "setActiveTools">;
65
66
  }
66
67
  /**
67
- * The `tool_search` description. `sources` lists the namespaces whose tools can be found, with
68
- * their descriptions.
68
+ * The `tool_search` description. It does not list the searchable tools or their namespaces, so it
69
+ * stays the same while tools are registered, for example when MCP servers connect.
69
70
  */
70
- export declare function createToolSearchDescription(sources?: readonly ToolNamespace[]): string;
71
+ export declare const TOOL_SEARCH_DESCRIPTION = "# Tool discovery\n\nSearches over deferred tool metadata with BM25 and exposes matching tools for the next model call.\n\nSome of the tools, such as tools of MCP servers, may not have been provided to you upfront, and you should use this tool (`tool_search`) to search for the required tools. For MCP tool discovery, always use `tool_search`.";
71
72
  export declare function createToolSearchToolDefinition(options?: ToolSearchToolOptions): ToolDefinition<typeof toolSearchSchema, ToolSearchToolDetails>;
72
73
  //# sourceMappingURL=tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../src/extensions/tool-search/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EACX,YAAY,EACZ,cAAc,EAEd,QAAQ,EACR,aAAa,EACb,MAAM,gCAAgC,CAAC;AAExC,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AACnD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,qGAAqG;AACrG,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACd;AAED,2FAA2F;AAC3F,MAAM,WAAW,UAAU;IAC1B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAAC;CAChG;AAkCD,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ/C;AAuBD;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,YAAY,CAAC,EAC3D,SAAS,CAAC,EAAE,aAAa,GACvB,kBAAkB,CAKpB;AAED,sEAAsE;AACtE,qBAAa,UAAW,YAAW,UAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;gBAEf,OAAO,GAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAO;IAKrD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE;CA6B/F;AAED,eAAO,MAAM,gBAAgB;;;EAK3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE9D,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC,GAAG,OAAO,CAErF;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACrC,iCAAiC;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,KAAK,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,gBAAgB,GAAG,gBAAgB,CAAC,CAAC;CAChF;AA2BD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,SAAS,aAAa,EAAO,GAAG,MAAM,CAW1F;AAED,wBAAgB,8BAA8B,CAC7C,OAAO,GAAE,qBAA0B,GACjC,cAAc,CAAC,OAAO,gBAAgB,EAAE,qBAAqB,CAAC,CAmChE"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../src/extensions/tool-search/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EACX,YAAY,EACZ,cAAc,EAEd,QAAQ,EACR,aAAa,EACb,MAAM,gCAAgC,CAAC;AAExC,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AACnD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,qGAAqG;AACrG,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACd;AAED,2FAA2F;AAC3F,MAAM,WAAW,UAAU;IAC1B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CAAC;CAChG;AAkCD,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ/C;AAuBD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACvC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,YAAY,CAAC,EAC3D,SAAS,CAAC,EAAE,aAAa,GACvB,kBAAkB,CAKpB;AAED,sEAAsE;AACtE,qBAAa,UAAW,YAAW,UAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAS;gBAEf,OAAO,GAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAO;IAKrD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE;CA6B/F;AAED,eAAO,MAAM,gBAAgB;;;EAK3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE9D,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC,GAAG,OAAO,CAErF;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACrC,iCAAiC;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,KAAK,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,gBAAgB,GAAG,gBAAgB,CAAC,CAAC;CAChF;AA2BD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,2VAAyX,CAAC;AAE9Z,wBAAgB,8BAA8B,CAC7C,OAAO,GAAE,qBAA0B,GACjC,cAAc,CAAC,OAAO,gBAAgB,EAAE,qBAAqB,CAAC,CAuBhE"}
@@ -78,13 +78,14 @@ function schemaText(schema, parts) {
78
78
  }
79
79
  /**
80
80
  * Search text of a tool: the name, the name with `_`
81
- * as spaces, the description, schema descriptions and property names, and the namespace.
81
+ * as spaces, the description, schema descriptions and property names, and the namespace with its
82
+ * description and instructions.
82
83
  */
83
84
  export function createToolSearchDocument(tool, namespace) {
84
85
  const parts = [tool.name, tool.name.replaceAll("_", " "), tool.description];
85
86
  schemaText(tool.parameters, parts);
86
87
  if (namespace)
87
- parts.push(namespace.name, namespace.description ?? "");
88
+ parts.push(namespace.name, namespace.description ?? "", namespace.instructions ?? "");
88
89
  return { name: tool.name, text: parts.filter((part) => part.trim()).join(" ") };
89
90
  }
90
91
  /** Okapi BM25 with the usual parameters. Ties keep document order. */
@@ -154,41 +155,19 @@ function searchAndLoad(tools, query, limit) {
154
155
  }));
155
156
  }
156
157
  /**
157
- * The `tool_search` description. `sources` lists the namespaces whose tools can be found, with
158
- * their descriptions.
158
+ * The `tool_search` description. It does not list the searchable tools or their namespaces, so it
159
+ * stays the same while tools are registered, for example when MCP servers connect.
159
160
  */
160
- export function createToolSearchDescription(sources = []) {
161
- const listed = sources.length === 0
162
- ? "None currently enabled."
163
- : sources
164
- .map((source) => {
165
- const description = source.description?.trim().split(/\r?\n/)[0];
166
- return description ? `- ${source.name}: ${description}` : `- ${source.name}`;
167
- })
168
- .join("\n");
169
- return `# Tool discovery\n\nSearches over deferred tool metadata with BM25 and exposes matching tools for the next model call.\n\nYou have access to tools from the following sources:\n${listed}\n\nSome of the tools may not have been provided to you upfront, and you should use this tool (\`${TOOL_SEARCH_TOOL_NAME}\`) to search for the required tools. For MCP tool discovery, always use \`${TOOL_SEARCH_TOOL_NAME}\`.`;
170
- }
161
+ export const TOOL_SEARCH_DESCRIPTION = `# Tool discovery\n\nSearches over deferred tool metadata with BM25 and exposes matching tools for the next model call.\n\nSome of the tools, such as tools of MCP servers, may not have been provided to you upfront, and you should use this tool (\`${TOOL_SEARCH_TOOL_NAME}\`) to search for the required tools. For MCP tool discovery, always use \`${TOOL_SEARCH_TOOL_NAME}\`.`;
171
162
  export function createToolSearchToolDefinition(options = {}) {
172
163
  return {
173
164
  name: TOOL_SEARCH_TOOL_NAME,
174
165
  label: TOOL_SEARCH_TOOL_NAME,
175
- // Replaced with the searchable sources when the tool is activated.
176
- description: createToolSearchDescription(),
166
+ description: TOOL_SEARCH_DESCRIPTION,
177
167
  promptSnippet: "Search for tools that are not loaded yet and load the matches",
178
168
  parameters: toolSearchSchema,
179
169
  // Searching is not something scripts need; it changes what the model sees.
180
170
  exposure: "model-only",
181
- // List the namespaces of the searchable tools.
182
- prepareLoadout: (loadout) => {
183
- const sources = new Map();
184
- for (const tool of loadout.registered) {
185
- const namespace = loadout.getNamespace(tool.name);
186
- if (isSearchable(loadout.getExposure(tool.name)) && namespace && !sources.has(namespace.name)) {
187
- sources.set(namespace.name, namespace);
188
- }
189
- }
190
- return { descriptions: { [TOOL_SEARCH_TOOL_NAME]: createToolSearchDescription([...sources.values()]) } };
191
- },
192
171
  async execute(_toolCallId, { query, limit }) {
193
172
  if (query.trim() === "")
194
173
  throw new Error("query must not be empty");
@@ -1 +1 @@
1
- {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/extensions/tool-search/tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool discovery: a BM25 ranker over tool metadata, shared by `searchTools()` in codemode scripts and\n * the optional `tool_search` tool.\n *\n * `tool_search` searches tools that are not declared to\n * the model (`codemode` and `deferred` exposure) and loads the matches, so they are declared for the\n * next model call. Loading goes through the active tool set, so it is recorded in the transcript\n * like any other tool change and survives `/tree`, resume, and fork on that branch.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport type {\n\tExtensionAPI,\n\tToolDefinition,\n\tToolExposure,\n\tToolInfo,\n\tToolNamespace,\n} from \"../../core/extensions/types.ts\";\n\nexport const TOOL_SEARCH_TOOL_NAME = \"tool_search\";\nexport const DEFAULT_TOOL_SEARCH_LIMIT = 8;\n\n/** A tool as the ranker sees it: its name and the text built by {@link createToolSearchDocument}. */\nexport interface ToolSearchDocument {\n\tname: string;\n\ttext: string;\n}\n\nexport interface ToolSearchMatch {\n\tname: string;\n\tscore: number;\n}\n\n/** Ranks tools for a query. BM25 today; a hybrid ranker with embeddings can replace it. */\nexport interface ToolRanker {\n\trank(query: string, documents: readonly ToolSearchDocument[], limit: number): ToolSearchMatch[];\n}\n\nconst STOP_WORDS: ReadonlySet<string> = new Set([\n\t\"a\",\n\t\"an\",\n\t\"and\",\n\t\"are\",\n\t\"as\",\n\t\"at\",\n\t\"be\",\n\t\"by\",\n\t\"for\",\n\t\"from\",\n\t\"in\",\n\t\"is\",\n\t\"it\",\n\t\"of\",\n\t\"on\",\n\t\"or\",\n\t\"that\",\n\t\"the\",\n\t\"this\",\n\t\"to\",\n\t\"with\",\n]);\n\n/** Naive singular form, so `issues` matches `issue` and `searches` matches `search`. */\nfunction stem(term: string): string {\n\tif (term.length > 4 && term.endsWith(\"ies\")) return `${term.slice(0, -3)}y`;\n\tif (term.length > 4 && /(ches|shes|sses|xes|zes)$/.test(term)) return term.slice(0, -2);\n\tif (term.length > 3 && term.endsWith(\"s\") && !term.endsWith(\"ss\")) return term.slice(0, -1);\n\treturn term;\n}\n\n/** Lowercase terms, split at camelCase boundaries and non-alphanumerics, without stop words. */\nexport function tokenize(text: string): string[] {\n\treturn text\n\t\t.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n\t\t.replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter((term) => term.length > 0 && !STOP_WORDS.has(term))\n\t\t.map(stem);\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Schema descriptions and property names, recursively. */\nfunction schemaText(schema: unknown, parts: string[]): void {\n\tif (!isObject(schema)) return;\n\tif (typeof schema.description === \"string\") parts.push(schema.description);\n\tif (isObject(schema.properties)) {\n\t\tfor (const [name, property] of Object.entries(schema.properties)) {\n\t\t\tparts.push(name);\n\t\t\tschemaText(property, parts);\n\t\t}\n\t}\n\tschemaText(schema.items, parts);\n\tfor (const key of [\"anyOf\", \"oneOf\", \"allOf\"]) {\n\t\tconst variants = schema[key];\n\t\tif (Array.isArray(variants)) for (const variant of variants) schemaText(variant, parts);\n\t}\n}\n\n/**\n * Search text of a tool: the name, the name with `_`\n * as spaces, the description, schema descriptions and property names, and the namespace.\n */\nexport function createToolSearchDocument(\n\ttool: Pick<ToolInfo, \"name\" | \"description\" | \"parameters\">,\n\tnamespace?: ToolNamespace,\n): ToolSearchDocument {\n\tconst parts = [tool.name, tool.name.replaceAll(\"_\", \" \"), tool.description];\n\tschemaText(tool.parameters, parts);\n\tif (namespace) parts.push(namespace.name, namespace.description ?? \"\");\n\treturn { name: tool.name, text: parts.filter((part) => part.trim()).join(\" \") };\n}\n\n/** Okapi BM25 with the usual parameters. Ties keep document order. */\nexport class Bm25Ranker implements ToolRanker {\n\tprivate readonly k1: number;\n\tprivate readonly b: number;\n\n\tconstructor(options: { k1?: number; b?: number } = {}) {\n\t\tthis.k1 = options.k1 ?? 1.2;\n\t\tthis.b = options.b ?? 0.75;\n\t}\n\n\trank(query: string, documents: readonly ToolSearchDocument[], limit: number): ToolSearchMatch[] {\n\t\tconst queryTerms = [...new Set(tokenize(query))];\n\t\tif (queryTerms.length === 0 || documents.length === 0 || limit <= 0) return [];\n\t\tconst termCounts = documents.map((document) => {\n\t\t\tconst counts = new Map<string, number>();\n\t\t\tfor (const term of tokenize(document.text)) counts.set(term, (counts.get(term) ?? 0) + 1);\n\t\t\treturn counts;\n\t\t});\n\t\tconst lengths = termCounts.map((counts) => [...counts.values()].reduce((sum, count) => sum + count, 0));\n\t\tconst averageLength = lengths.reduce((sum, length) => sum + length, 0) / documents.length || 1;\n\t\tconst idf = new Map(\n\t\t\tqueryTerms.map((term) => {\n\t\t\t\tconst frequency = termCounts.filter((counts) => counts.has(term)).length;\n\t\t\t\treturn [term, Math.log(1 + (documents.length - frequency + 0.5) / (frequency + 0.5))] as const;\n\t\t\t}),\n\t\t);\n\t\tconst matches: ToolSearchMatch[] = [];\n\t\tdocuments.forEach((document, index) => {\n\t\t\tlet score = 0;\n\t\t\tfor (const term of queryTerms) {\n\t\t\t\tconst count = termCounts[index].get(term);\n\t\t\t\tif (!count) continue;\n\t\t\t\tconst norm = this.k1 * (1 - this.b + (this.b * lengths[index]) / averageLength);\n\t\t\t\tscore += (idf.get(term) ?? 0) * ((count * (this.k1 + 1)) / (count + norm));\n\t\t\t}\n\t\t\tif (score > 0) matches.push({ name: document.name, score });\n\t\t});\n\t\treturn matches.sort((a, b) => b.score - a.score).slice(0, limit);\n\t}\n}\n\nexport const toolSearchSchema = Type.Object({\n\tquery: Type.String({ description: \"Search query for deferred tools.\" }),\n\tlimit: Type.Optional(\n\t\tType.Number({ description: `Maximum number of tools to return. Defaults to ${DEFAULT_TOOL_SEARCH_LIMIT}.` }),\n\t),\n});\n\nexport type ToolSearchInput = Static<typeof toolSearchSchema>;\n\n/** Whether the tool is this `tool_search`, not another extension's tool of the same name. */\nexport function isToolSearchTool(tool: Pick<ToolInfo, \"name\" | \"parameters\">): boolean {\n\treturn tool.name === TOOL_SEARCH_TOOL_NAME && tool.parameters === toolSearchSchema;\n}\n\nexport interface ToolSearchResultTool {\n\tname: string;\n\tdescription: string;\n}\n\nexport interface ToolSearchToolDetails {\n\t/** Tools loaded by this call. */\n\tloaded: string[];\n}\n\nexport interface ToolSearchToolOptions {\n\t/**\n\t * The session's tools. `tool_search` searches the tools that are not declared to the model and\n\t * activates the matches. Without it, the tool finds nothing. An `ExtensionAPI` fits.\n\t */\n\ttools?: Pick<ExtensionAPI, \"getAllTools\" | \"getActiveTools\" | \"setActiveTools\">;\n}\n\n/** Whether `tool_search` can load a tool with this exposure. */\nfunction isSearchable(exposure: ToolExposure): boolean {\n\treturn exposure === \"codemode\" || exposure === \"deferred\";\n}\n\n/**\n * Rank the searchable tools that are not active yet and activate the matches, so the next model\n * call declares them. Activation is recorded in the transcript like any tool change.\n */\nfunction searchAndLoad(\n\ttools: NonNullable<ToolSearchToolOptions[\"tools\"]>,\n\tquery: string,\n\tlimit: number,\n): ToolSearchResultTool[] {\n\tconst active = tools.getActiveTools();\n\tconst candidates = tools.getAllTools().filter((tool) => isSearchable(tool.exposure) && !active.includes(tool.name));\n\tconst documents = candidates.map((tool) => createToolSearchDocument(tool, tool.namespace));\n\tconst matches = new Bm25Ranker().rank(query, documents, limit);\n\tif (matches.length > 0) tools.setActiveTools([...active, ...matches.map((match) => match.name)]);\n\treturn matches.map((match) => ({\n\t\tname: match.name,\n\t\tdescription: candidates.find((tool) => tool.name === match.name)?.description ?? \"\",\n\t}));\n}\n\n/**\n * The `tool_search` description. `sources` lists the namespaces whose tools can be found, with\n * their descriptions.\n */\nexport function createToolSearchDescription(sources: readonly ToolNamespace[] = []): string {\n\tconst listed =\n\t\tsources.length === 0\n\t\t\t? \"None currently enabled.\"\n\t\t\t: sources\n\t\t\t\t\t.map((source) => {\n\t\t\t\t\t\tconst description = source.description?.trim().split(/\\r?\\n/)[0];\n\t\t\t\t\t\treturn description ? `- ${source.name}: ${description}` : `- ${source.name}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\");\n\treturn `# Tool discovery\\n\\nSearches over deferred tool metadata with BM25 and exposes matching tools for the next model call.\\n\\nYou have access to tools from the following sources:\\n${listed}\\n\\nSome of the tools may not have been provided to you upfront, and you should use this tool (\\`${TOOL_SEARCH_TOOL_NAME}\\`) to search for the required tools. For MCP tool discovery, always use \\`${TOOL_SEARCH_TOOL_NAME}\\`.`;\n}\n\nexport function createToolSearchToolDefinition(\n\toptions: ToolSearchToolOptions = {},\n): ToolDefinition<typeof toolSearchSchema, ToolSearchToolDetails> {\n\treturn {\n\t\tname: TOOL_SEARCH_TOOL_NAME,\n\t\tlabel: TOOL_SEARCH_TOOL_NAME,\n\t\t// Replaced with the searchable sources when the tool is activated.\n\t\tdescription: createToolSearchDescription(),\n\t\tpromptSnippet: \"Search for tools that are not loaded yet and load the matches\",\n\t\tparameters: toolSearchSchema,\n\t\t// Searching is not something scripts need; it changes what the model sees.\n\t\texposure: \"model-only\",\n\t\t// List the namespaces of the searchable tools.\n\t\tprepareLoadout: (loadout) => {\n\t\t\tconst sources = new Map<string, ToolNamespace>();\n\t\t\tfor (const tool of loadout.registered) {\n\t\t\t\tconst namespace = loadout.getNamespace(tool.name);\n\t\t\t\tif (isSearchable(loadout.getExposure(tool.name)) && namespace && !sources.has(namespace.name)) {\n\t\t\t\t\tsources.set(namespace.name, namespace);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { descriptions: { [TOOL_SEARCH_TOOL_NAME]: createToolSearchDescription([...sources.values()]) } };\n\t\t},\n\t\tasync execute(_toolCallId, { query, limit }) {\n\t\t\tif (query.trim() === \"\") throw new Error(\"query must not be empty\");\n\t\t\tconst max = limit ?? DEFAULT_TOOL_SEARCH_LIMIT;\n\t\t\tif (!Number.isInteger(max) || max <= 0) throw new Error(\"limit must be a positive integer\");\n\t\t\tconst tools = options.tools ? searchAndLoad(options.tools, query, max) : [];\n\t\t\tconst text =\n\t\t\t\ttools.length === 0\n\t\t\t\t\t? \"No matching tools found.\"\n\t\t\t\t\t: `Loaded ${tools.length} tool${tools.length === 1 ? \"\" : \"s\"}. They are available from your next call:\\n${tools\n\t\t\t\t\t\t\t.map((tool) => `- ${tool.name}: ${tool.description.trim().split(/\\r?\\n/)[0]}`)\n\t\t\t\t\t\t\t.join(\"\\n\")}`;\n\t\t\treturn { content: [{ type: \"text\", text }], details: { loaded: tools.map((tool) => tool.name) } };\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/extensions/tool-search/tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool discovery: a BM25 ranker over tool metadata, shared by `searchTools()` in codemode scripts and\n * the optional `tool_search` tool.\n *\n * `tool_search` searches tools that are not declared to\n * the model (`codemode` and `deferred` exposure) and loads the matches, so they are declared for the\n * next model call. Loading goes through the active tool set, so it is recorded in the transcript\n * like any other tool change and survives `/tree`, resume, and fork on that branch.\n */\n\nimport { type Static, Type } from \"typebox\";\nimport type {\n\tExtensionAPI,\n\tToolDefinition,\n\tToolExposure,\n\tToolInfo,\n\tToolNamespace,\n} from \"../../core/extensions/types.ts\";\n\nexport const TOOL_SEARCH_TOOL_NAME = \"tool_search\";\nexport const DEFAULT_TOOL_SEARCH_LIMIT = 8;\n\n/** A tool as the ranker sees it: its name and the text built by {@link createToolSearchDocument}. */\nexport interface ToolSearchDocument {\n\tname: string;\n\ttext: string;\n}\n\nexport interface ToolSearchMatch {\n\tname: string;\n\tscore: number;\n}\n\n/** Ranks tools for a query. BM25 today; a hybrid ranker with embeddings can replace it. */\nexport interface ToolRanker {\n\trank(query: string, documents: readonly ToolSearchDocument[], limit: number): ToolSearchMatch[];\n}\n\nconst STOP_WORDS: ReadonlySet<string> = new Set([\n\t\"a\",\n\t\"an\",\n\t\"and\",\n\t\"are\",\n\t\"as\",\n\t\"at\",\n\t\"be\",\n\t\"by\",\n\t\"for\",\n\t\"from\",\n\t\"in\",\n\t\"is\",\n\t\"it\",\n\t\"of\",\n\t\"on\",\n\t\"or\",\n\t\"that\",\n\t\"the\",\n\t\"this\",\n\t\"to\",\n\t\"with\",\n]);\n\n/** Naive singular form, so `issues` matches `issue` and `searches` matches `search`. */\nfunction stem(term: string): string {\n\tif (term.length > 4 && term.endsWith(\"ies\")) return `${term.slice(0, -3)}y`;\n\tif (term.length > 4 && /(ches|shes|sses|xes|zes)$/.test(term)) return term.slice(0, -2);\n\tif (term.length > 3 && term.endsWith(\"s\") && !term.endsWith(\"ss\")) return term.slice(0, -1);\n\treturn term;\n}\n\n/** Lowercase terms, split at camelCase boundaries and non-alphanumerics, without stop words. */\nexport function tokenize(text: string): string[] {\n\treturn text\n\t\t.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n\t\t.replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter((term) => term.length > 0 && !STOP_WORDS.has(term))\n\t\t.map(stem);\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Schema descriptions and property names, recursively. */\nfunction schemaText(schema: unknown, parts: string[]): void {\n\tif (!isObject(schema)) return;\n\tif (typeof schema.description === \"string\") parts.push(schema.description);\n\tif (isObject(schema.properties)) {\n\t\tfor (const [name, property] of Object.entries(schema.properties)) {\n\t\t\tparts.push(name);\n\t\t\tschemaText(property, parts);\n\t\t}\n\t}\n\tschemaText(schema.items, parts);\n\tfor (const key of [\"anyOf\", \"oneOf\", \"allOf\"]) {\n\t\tconst variants = schema[key];\n\t\tif (Array.isArray(variants)) for (const variant of variants) schemaText(variant, parts);\n\t}\n}\n\n/**\n * Search text of a tool: the name, the name with `_`\n * as spaces, the description, schema descriptions and property names, and the namespace with its\n * description and instructions.\n */\nexport function createToolSearchDocument(\n\ttool: Pick<ToolInfo, \"name\" | \"description\" | \"parameters\">,\n\tnamespace?: ToolNamespace,\n): ToolSearchDocument {\n\tconst parts = [tool.name, tool.name.replaceAll(\"_\", \" \"), tool.description];\n\tschemaText(tool.parameters, parts);\n\tif (namespace) parts.push(namespace.name, namespace.description ?? \"\", namespace.instructions ?? \"\");\n\treturn { name: tool.name, text: parts.filter((part) => part.trim()).join(\" \") };\n}\n\n/** Okapi BM25 with the usual parameters. Ties keep document order. */\nexport class Bm25Ranker implements ToolRanker {\n\tprivate readonly k1: number;\n\tprivate readonly b: number;\n\n\tconstructor(options: { k1?: number; b?: number } = {}) {\n\t\tthis.k1 = options.k1 ?? 1.2;\n\t\tthis.b = options.b ?? 0.75;\n\t}\n\n\trank(query: string, documents: readonly ToolSearchDocument[], limit: number): ToolSearchMatch[] {\n\t\tconst queryTerms = [...new Set(tokenize(query))];\n\t\tif (queryTerms.length === 0 || documents.length === 0 || limit <= 0) return [];\n\t\tconst termCounts = documents.map((document) => {\n\t\t\tconst counts = new Map<string, number>();\n\t\t\tfor (const term of tokenize(document.text)) counts.set(term, (counts.get(term) ?? 0) + 1);\n\t\t\treturn counts;\n\t\t});\n\t\tconst lengths = termCounts.map((counts) => [...counts.values()].reduce((sum, count) => sum + count, 0));\n\t\tconst averageLength = lengths.reduce((sum, length) => sum + length, 0) / documents.length || 1;\n\t\tconst idf = new Map(\n\t\t\tqueryTerms.map((term) => {\n\t\t\t\tconst frequency = termCounts.filter((counts) => counts.has(term)).length;\n\t\t\t\treturn [term, Math.log(1 + (documents.length - frequency + 0.5) / (frequency + 0.5))] as const;\n\t\t\t}),\n\t\t);\n\t\tconst matches: ToolSearchMatch[] = [];\n\t\tdocuments.forEach((document, index) => {\n\t\t\tlet score = 0;\n\t\t\tfor (const term of queryTerms) {\n\t\t\t\tconst count = termCounts[index].get(term);\n\t\t\t\tif (!count) continue;\n\t\t\t\tconst norm = this.k1 * (1 - this.b + (this.b * lengths[index]) / averageLength);\n\t\t\t\tscore += (idf.get(term) ?? 0) * ((count * (this.k1 + 1)) / (count + norm));\n\t\t\t}\n\t\t\tif (score > 0) matches.push({ name: document.name, score });\n\t\t});\n\t\treturn matches.sort((a, b) => b.score - a.score).slice(0, limit);\n\t}\n}\n\nexport const toolSearchSchema = Type.Object({\n\tquery: Type.String({ description: \"Search query for deferred tools.\" }),\n\tlimit: Type.Optional(\n\t\tType.Number({ description: `Maximum number of tools to return. Defaults to ${DEFAULT_TOOL_SEARCH_LIMIT}.` }),\n\t),\n});\n\nexport type ToolSearchInput = Static<typeof toolSearchSchema>;\n\n/** Whether the tool is this `tool_search`, not another extension's tool of the same name. */\nexport function isToolSearchTool(tool: Pick<ToolInfo, \"name\" | \"parameters\">): boolean {\n\treturn tool.name === TOOL_SEARCH_TOOL_NAME && tool.parameters === toolSearchSchema;\n}\n\nexport interface ToolSearchResultTool {\n\tname: string;\n\tdescription: string;\n}\n\nexport interface ToolSearchToolDetails {\n\t/** Tools loaded by this call. */\n\tloaded: string[];\n}\n\nexport interface ToolSearchToolOptions {\n\t/**\n\t * The session's tools. `tool_search` searches the tools that are not declared to the model and\n\t * activates the matches. Without it, the tool finds nothing. An `ExtensionAPI` fits.\n\t */\n\ttools?: Pick<ExtensionAPI, \"getAllTools\" | \"getActiveTools\" | \"setActiveTools\">;\n}\n\n/** Whether `tool_search` can load a tool with this exposure. */\nfunction isSearchable(exposure: ToolExposure): boolean {\n\treturn exposure === \"codemode\" || exposure === \"deferred\";\n}\n\n/**\n * Rank the searchable tools that are not active yet and activate the matches, so the next model\n * call declares them. Activation is recorded in the transcript like any tool change.\n */\nfunction searchAndLoad(\n\ttools: NonNullable<ToolSearchToolOptions[\"tools\"]>,\n\tquery: string,\n\tlimit: number,\n): ToolSearchResultTool[] {\n\tconst active = tools.getActiveTools();\n\tconst candidates = tools.getAllTools().filter((tool) => isSearchable(tool.exposure) && !active.includes(tool.name));\n\tconst documents = candidates.map((tool) => createToolSearchDocument(tool, tool.namespace));\n\tconst matches = new Bm25Ranker().rank(query, documents, limit);\n\tif (matches.length > 0) tools.setActiveTools([...active, ...matches.map((match) => match.name)]);\n\treturn matches.map((match) => ({\n\t\tname: match.name,\n\t\tdescription: candidates.find((tool) => tool.name === match.name)?.description ?? \"\",\n\t}));\n}\n\n/**\n * The `tool_search` description. It does not list the searchable tools or their namespaces, so it\n * stays the same while tools are registered, for example when MCP servers connect.\n */\nexport const TOOL_SEARCH_DESCRIPTION = `# Tool discovery\\n\\nSearches over deferred tool metadata with BM25 and exposes matching tools for the next model call.\\n\\nSome of the tools, such as tools of MCP servers, may not have been provided to you upfront, and you should use this tool (\\`${TOOL_SEARCH_TOOL_NAME}\\`) to search for the required tools. For MCP tool discovery, always use \\`${TOOL_SEARCH_TOOL_NAME}\\`.`;\n\nexport function createToolSearchToolDefinition(\n\toptions: ToolSearchToolOptions = {},\n): ToolDefinition<typeof toolSearchSchema, ToolSearchToolDetails> {\n\treturn {\n\t\tname: TOOL_SEARCH_TOOL_NAME,\n\t\tlabel: TOOL_SEARCH_TOOL_NAME,\n\t\tdescription: TOOL_SEARCH_DESCRIPTION,\n\t\tpromptSnippet: \"Search for tools that are not loaded yet and load the matches\",\n\t\tparameters: toolSearchSchema,\n\t\t// Searching is not something scripts need; it changes what the model sees.\n\t\texposure: \"model-only\",\n\t\tasync execute(_toolCallId, { query, limit }) {\n\t\t\tif (query.trim() === \"\") throw new Error(\"query must not be empty\");\n\t\t\tconst max = limit ?? DEFAULT_TOOL_SEARCH_LIMIT;\n\t\t\tif (!Number.isInteger(max) || max <= 0) throw new Error(\"limit must be a positive integer\");\n\t\t\tconst tools = options.tools ? searchAndLoad(options.tools, query, max) : [];\n\t\t\tconst text =\n\t\t\t\ttools.length === 0\n\t\t\t\t\t? \"No matching tools found.\"\n\t\t\t\t\t: `Loaded ${tools.length} tool${tools.length === 1 ? \"\" : \"s\"}. They are available from your next call:\\n${tools\n\t\t\t\t\t\t\t.map((tool) => `- ${tool.name}: ${tool.description.trim().split(/\\r?\\n/)[0]}`)\n\t\t\t\t\t\t\t.join(\"\\n\")}`;\n\t\t\treturn { content: [{ type: \"text\", text }], details: { loaded: tools.map((tool) => tool.name) } };\n\t\t},\n\t};\n}\n"]}
@@ -4,10 +4,6 @@
4
4
  import type { AgentToolUpdateCallback } from "../../core/extensions/types.ts";
5
5
  import type { WebSearchParams } from "./schema.ts";
6
6
  import type { ResolvedSearchCredentials, WebSearchDetails } from "./types.ts";
7
- export interface WebSearchExecution {
8
- formattedOutput: string;
9
- details: WebSearchDetails;
10
- }
11
7
  /** Execute all configured search providers and combine their successful results. */
12
- export declare function executeWebSearch(params: WebSearchParams, credentials: ResolvedSearchCredentials, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback<WebSearchDetails>): Promise<WebSearchExecution>;
8
+ export declare function executeWebSearch(params: WebSearchParams, credentials: ResolvedSearchCredentials, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback<WebSearchDetails>): Promise<WebSearchDetails>;
13
9
  //# sourceMappingURL=execute.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/extensions/web-search/execute.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAO9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAwB,yBAAyB,EAAoB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEtH,MAAM,WAAW,kBAAkB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,gBAAgB,CAAC;CAC1B;AAED,oFAAoF;AACpF,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,yBAAyB,EACtC,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,GAClD,OAAO,CAAC,kBAAkB,CAAC,CAmG7B"}
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/extensions/web-search/execute.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAM9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAwB,yBAAyB,EAAoB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEtH,oFAAoF;AACpF,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,yBAAyB,EACtC,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,GAClD,OAAO,CAAC,gBAAgB,CAAC,CA8F3B"}
@@ -3,7 +3,6 @@
3
3
  */
4
4
  import { configuredEngine } from "./auth.js";
5
5
  import { getEngineLabel, WEB_SEARCH_DISABLED_MESSAGE } from "./constants.js";
6
- import { formatSearchOutput } from "./format.js";
7
6
  import { searchDeepSeek } from "./providers/deepseek.js";
8
7
  import { searchMiniMax } from "./providers/minimax.js";
9
8
  import { boundSingleLineText, fuseSearchHits, MAX_ERROR_MESSAGE_LENGTH, MAX_QUERY_LENGTH } from "./results.js";
@@ -13,7 +12,7 @@ export async function executeWebSearch(params, credentials, signal, onUpdate) {
13
12
  const query = boundSingleLineText(params.query, MAX_QUERY_LENGTH) ?? "";
14
13
  const engine = configuredEngine(credentials);
15
14
  if (!query) {
16
- const details = {
15
+ return {
17
16
  query: "",
18
17
  durationMs: 0,
19
18
  status: "error",
@@ -22,10 +21,9 @@ export async function executeWebSearch(params, credentials, signal, onUpdate) {
22
21
  hits: [],
23
22
  errorMessage: "Search query must not be empty.",
24
23
  };
25
- return { formattedOutput: formatSearchOutput(query, details), details };
26
24
  }
27
25
  if (engine === "none") {
28
- const details = {
26
+ return {
29
27
  query,
30
28
  durationMs: 0,
31
29
  status: "disabled",
@@ -34,7 +32,6 @@ export async function executeWebSearch(params, credentials, signal, onUpdate) {
34
32
  hits: [],
35
33
  errorMessage: WEB_SEARCH_DISABLED_MESSAGE,
36
34
  };
37
- return { formattedOutput: formatSearchOutput(query, details), details };
38
35
  }
39
36
  signal?.throwIfAborted();
40
37
  onUpdate?.({
@@ -72,7 +69,7 @@ export async function executeWebSearch(params, credentials, signal, onUpdate) {
72
69
  errors.push(result.reason instanceof Error ? result.reason.message : String(result.reason));
73
70
  }
74
71
  if (successfulResults.length === 0) {
75
- const details = {
72
+ return {
76
73
  query,
77
74
  durationMs,
78
75
  status: "error",
@@ -81,12 +78,11 @@ export async function executeWebSearch(params, credentials, signal, onUpdate) {
81
78
  hits: [],
82
79
  errorMessage: boundSingleLineText(errors.join(" | "), MAX_ERROR_MESSAGE_LENGTH) ?? "All search engines failed",
83
80
  };
84
- return { formattedOutput: formatSearchOutput(query, details), details };
85
81
  }
86
82
  const { hits, relatedSearches, deepseekSynthesis } = fuseSearchHits(successfulResults);
87
83
  const respondedSources = new Set(successfulResults.map((result) => result.source));
88
84
  const contributingEngine = respondedSources.size > 1 ? "dual" : respondedSources.has("MiniMax") ? "minimax" : "deepseek";
89
- const details = {
85
+ return {
90
86
  query,
91
87
  durationMs,
92
88
  status: "success",
@@ -96,6 +92,5 @@ export async function executeWebSearch(params, credentials, signal, onUpdate) {
96
92
  relatedSearches,
97
93
  deepseekSynthesis,
98
94
  };
99
- return { formattedOutput: formatSearchOutput(query, details), details };
100
95
  }
101
96
  //# sourceMappingURL=execute.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/extensions/web-search/execute.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider orchestration and execution-state construction for web_search.\n */\n\nimport type { AgentToolUpdateCallback } from \"../../core/extensions/types.ts\";\nimport { configuredEngine } from \"./auth.ts\";\nimport { getEngineLabel, WEB_SEARCH_DISABLED_MESSAGE } from \"./constants.ts\";\nimport { formatSearchOutput } from \"./format.ts\";\nimport { searchDeepSeek } from \"./providers/deepseek.ts\";\nimport { searchMiniMax } from \"./providers/minimax.ts\";\nimport { boundSingleLineText, fuseSearchHits, MAX_ERROR_MESSAGE_LENGTH, MAX_QUERY_LENGTH } from \"./results.ts\";\nimport type { WebSearchParams } from \"./schema.ts\";\nimport type { ProviderSearchResult, ResolvedSearchCredentials, SearchEngineType, WebSearchDetails } from \"./types.ts\";\n\nexport interface WebSearchExecution {\n\tformattedOutput: string;\n\tdetails: WebSearchDetails;\n}\n\n/** Execute all configured search providers and combine their successful results. */\nexport async function executeWebSearch(\n\tparams: WebSearchParams,\n\tcredentials: ResolvedSearchCredentials,\n\tsignal?: AbortSignal,\n\tonUpdate?: AgentToolUpdateCallback<WebSearchDetails>,\n): Promise<WebSearchExecution> {\n\tconst startTime = Date.now();\n\tconst query = boundSingleLineText(params.query, MAX_QUERY_LENGTH) ?? \"\";\n\tconst engine = configuredEngine(credentials);\n\n\tif (!query) {\n\t\tconst details: WebSearchDetails = {\n\t\t\tquery: \"\",\n\t\t\tdurationMs: 0,\n\t\t\tstatus: \"error\",\n\t\t\tengine,\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t\terrorMessage: \"Search query must not be empty.\",\n\t\t};\n\t\treturn { formattedOutput: formatSearchOutput(query, details), details };\n\t}\n\n\tif (engine === \"none\") {\n\t\tconst details: WebSearchDetails = {\n\t\t\tquery,\n\t\t\tdurationMs: 0,\n\t\t\tstatus: \"disabled\",\n\t\t\tengine: \"none\",\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t\terrorMessage: WEB_SEARCH_DISABLED_MESSAGE,\n\t\t};\n\t\treturn { formattedOutput: formatSearchOutput(query, details), details };\n\t}\n\n\tsignal?.throwIfAborted();\n\tonUpdate?.({\n\t\tcontent: [{ type: \"text\", text: `Searching for \"${query}\" via ${getEngineLabel(engine)}...` }],\n\t\tdetails: {\n\t\t\tquery,\n\t\t\tdurationMs: 0,\n\t\t\tstatus: \"success\",\n\t\t\tengine,\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t},\n\t});\n\n\tconst searches: Promise<ProviderSearchResult>[] = [];\n\tif (credentials.minimax) {\n\t\tsearches.push(\n\t\t\tsearchMiniMax({\n\t\t\t\tquery,\n\t\t\t\tapiKey: credentials.minimax.key,\n\t\t\t\tapiHost: credentials.minimax.host,\n\t\t\t\tsignal,\n\t\t\t}),\n\t\t);\n\t}\n\tif (credentials.deepseek) {\n\t\tsearches.push(searchDeepSeek({ query, apiKey: credentials.deepseek.key, signal }));\n\t}\n\n\tconst settledResults = await Promise.allSettled(searches);\n\tsignal?.throwIfAborted();\n\tconst durationMs = Date.now() - startTime;\n\tconst successfulResults: ProviderSearchResult[] = [];\n\tconst errors: string[] = [];\n\n\tfor (const result of settledResults) {\n\t\tif (result.status === \"fulfilled\") successfulResults.push(result.value);\n\t\telse errors.push(result.reason instanceof Error ? result.reason.message : String(result.reason));\n\t}\n\n\tif (successfulResults.length === 0) {\n\t\tconst details: WebSearchDetails = {\n\t\t\tquery,\n\t\t\tdurationMs,\n\t\t\tstatus: \"error\",\n\t\t\tengine,\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t\terrorMessage: boundSingleLineText(errors.join(\" | \"), MAX_ERROR_MESSAGE_LENGTH) ?? \"All search engines failed\",\n\t\t};\n\t\treturn { formattedOutput: formatSearchOutput(query, details), details };\n\t}\n\n\tconst { hits, relatedSearches, deepseekSynthesis } = fuseSearchHits(successfulResults);\n\tconst respondedSources = new Set(successfulResults.map((result) => result.source));\n\tconst contributingEngine: SearchEngineType =\n\t\trespondedSources.size > 1 ? \"dual\" : respondedSources.has(\"MiniMax\") ? \"minimax\" : \"deepseek\";\n\tconst details: WebSearchDetails = {\n\t\tquery,\n\t\tdurationMs,\n\t\tstatus: \"success\",\n\t\tengine: contributingEngine,\n\t\ttotalHits: hits.length,\n\t\thits,\n\t\trelatedSearches,\n\t\tdeepseekSynthesis,\n\t};\n\n\treturn { formattedOutput: formatSearchOutput(query, details), details };\n}\n"]}
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../src/extensions/web-search/execute.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provider orchestration and execution-state construction for web_search.\n */\n\nimport type { AgentToolUpdateCallback } from \"../../core/extensions/types.ts\";\nimport { configuredEngine } from \"./auth.ts\";\nimport { getEngineLabel, WEB_SEARCH_DISABLED_MESSAGE } from \"./constants.ts\";\nimport { searchDeepSeek } from \"./providers/deepseek.ts\";\nimport { searchMiniMax } from \"./providers/minimax.ts\";\nimport { boundSingleLineText, fuseSearchHits, MAX_ERROR_MESSAGE_LENGTH, MAX_QUERY_LENGTH } from \"./results.ts\";\nimport type { WebSearchParams } from \"./schema.ts\";\nimport type { ProviderSearchResult, ResolvedSearchCredentials, SearchEngineType, WebSearchDetails } from \"./types.ts\";\n\n/** Execute all configured search providers and combine their successful results. */\nexport async function executeWebSearch(\n\tparams: WebSearchParams,\n\tcredentials: ResolvedSearchCredentials,\n\tsignal?: AbortSignal,\n\tonUpdate?: AgentToolUpdateCallback<WebSearchDetails>,\n): Promise<WebSearchDetails> {\n\tconst startTime = Date.now();\n\tconst query = boundSingleLineText(params.query, MAX_QUERY_LENGTH) ?? \"\";\n\tconst engine = configuredEngine(credentials);\n\n\tif (!query) {\n\t\treturn {\n\t\t\tquery: \"\",\n\t\t\tdurationMs: 0,\n\t\t\tstatus: \"error\",\n\t\t\tengine,\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t\terrorMessage: \"Search query must not be empty.\",\n\t\t};\n\t}\n\n\tif (engine === \"none\") {\n\t\treturn {\n\t\t\tquery,\n\t\t\tdurationMs: 0,\n\t\t\tstatus: \"disabled\",\n\t\t\tengine: \"none\",\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t\terrorMessage: WEB_SEARCH_DISABLED_MESSAGE,\n\t\t};\n\t}\n\n\tsignal?.throwIfAborted();\n\tonUpdate?.({\n\t\tcontent: [{ type: \"text\", text: `Searching for \"${query}\" via ${getEngineLabel(engine)}...` }],\n\t\tdetails: {\n\t\t\tquery,\n\t\t\tdurationMs: 0,\n\t\t\tstatus: \"success\",\n\t\t\tengine,\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t},\n\t});\n\n\tconst searches: Promise<ProviderSearchResult>[] = [];\n\tif (credentials.minimax) {\n\t\tsearches.push(\n\t\t\tsearchMiniMax({\n\t\t\t\tquery,\n\t\t\t\tapiKey: credentials.minimax.key,\n\t\t\t\tapiHost: credentials.minimax.host,\n\t\t\t\tsignal,\n\t\t\t}),\n\t\t);\n\t}\n\tif (credentials.deepseek) {\n\t\tsearches.push(searchDeepSeek({ query, apiKey: credentials.deepseek.key, signal }));\n\t}\n\n\tconst settledResults = await Promise.allSettled(searches);\n\tsignal?.throwIfAborted();\n\tconst durationMs = Date.now() - startTime;\n\tconst successfulResults: ProviderSearchResult[] = [];\n\tconst errors: string[] = [];\n\n\tfor (const result of settledResults) {\n\t\tif (result.status === \"fulfilled\") successfulResults.push(result.value);\n\t\telse errors.push(result.reason instanceof Error ? result.reason.message : String(result.reason));\n\t}\n\n\tif (successfulResults.length === 0) {\n\t\treturn {\n\t\t\tquery,\n\t\t\tdurationMs,\n\t\t\tstatus: \"error\",\n\t\t\tengine,\n\t\t\ttotalHits: 0,\n\t\t\thits: [],\n\t\t\terrorMessage: boundSingleLineText(errors.join(\" | \"), MAX_ERROR_MESSAGE_LENGTH) ?? \"All search engines failed\",\n\t\t};\n\t}\n\n\tconst { hits, relatedSearches, deepseekSynthesis } = fuseSearchHits(successfulResults);\n\tconst respondedSources = new Set(successfulResults.map((result) => result.source));\n\tconst contributingEngine: SearchEngineType =\n\t\trespondedSources.size > 1 ? \"dual\" : respondedSources.has(\"MiniMax\") ? \"minimax\" : \"deepseek\";\n\treturn {\n\t\tquery,\n\t\tdurationMs,\n\t\tstatus: \"success\",\n\t\tengine: contributingEngine,\n\t\ttotalHits: hits.length,\n\t\thits,\n\t\trelatedSearches,\n\t\tdeepseekSynthesis,\n\t};\n}\n"]}
@@ -1,12 +1,21 @@
1
1
  /**
2
2
  * Model-facing and expanded-TUI Markdown formatting for web_search results.
3
3
  */
4
- import type { WebSearchDetails } from "./types.ts";
4
+ import type { WebSearchDetails, WebSearchHit } from "./types.ts";
5
+ interface PreparedResults {
6
+ engine: WebSearchDetails["engine"];
7
+ hits: WebSearchHit[];
8
+ synthesis?: string;
9
+ relatedSearches: string[];
10
+ }
11
+ /** Historical details enter here; Markdown rendering only consumes bounded content. */
12
+ export declare function prepareResults(details: WebSearchDetails): PreparedResults;
5
13
  /**
6
14
  * Sources, synthesis, and related-search sections shared by model output and
7
15
  * the expanded TUI. This function adds no model instructions.
8
16
  */
9
- export declare function formatResultsMarkdown(details: WebSearchDetails): string;
17
+ export declare function formatResultsMarkdown({ engine, hits, synthesis, relatedSearches }: PreparedResults): string;
10
18
  /** Format a structured result payload for the main agent. */
11
- export declare function formatSearchOutput(query: string, details: WebSearchDetails): string;
19
+ export declare function formatSearchOutput(details: WebSearchDetails): string;
20
+ export {};
12
21
  //# sourceMappingURL=format.d.ts.map