@code-yeongyu/senpi 2026.7.17-5 → 2026.7.20-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (605) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +5 -2
  3. package/dist/cli/neo/build-argv.d.ts.map +1 -1
  4. package/dist/cli/neo/build-argv.js +2 -0
  5. package/dist/cli/neo/build-argv.js.map +1 -1
  6. package/dist/core/agent-session-services.d.ts.map +1 -1
  7. package/dist/core/agent-session-services.js +11 -4
  8. package/dist/core/agent-session-services.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +37 -0
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +395 -73
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/compaction/compaction.d.ts +2 -2
  14. package/dist/core/compaction/compaction.d.ts.map +1 -1
  15. package/dist/core/compaction/compaction.js +59 -15
  16. package/dist/core/compaction/compaction.js.map +1 -1
  17. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  18. package/dist/core/extensions/builtin/compaction/index.js +68 -10
  19. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  20. package/dist/core/extensions/builtin/compaction/speculative.d.ts +7 -1
  21. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  22. package/dist/core/extensions/builtin/compaction/speculative.js +29 -11
  23. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  24. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +9 -7
  25. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
  26. package/dist/core/extensions/builtin/compaction/todo-bridge.js +34 -9
  27. package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
  28. package/dist/core/extensions/builtin/goal/command-registration.d.ts +2 -2
  29. package/dist/core/extensions/builtin/goal/command-registration.d.ts.map +1 -1
  30. package/dist/core/extensions/builtin/goal/command-registration.js +3 -4
  31. package/dist/core/extensions/builtin/goal/command-registration.js.map +1 -1
  32. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/goal/index.js +11 -27
  34. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  35. package/dist/core/extensions/builtin/goal/tool-registration.d.ts +2 -2
  36. package/dist/core/extensions/builtin/goal/tool-registration.d.ts.map +1 -1
  37. package/dist/core/extensions/builtin/goal/tool-registration.js +2 -3
  38. package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
  39. package/dist/core/extensions/builtin/goal/turn-usage.d.ts +20 -0
  40. package/dist/core/extensions/builtin/goal/turn-usage.d.ts.map +1 -0
  41. package/dist/core/extensions/builtin/goal/turn-usage.js +61 -0
  42. package/dist/core/extensions/builtin/goal/turn-usage.js.map +1 -0
  43. package/dist/core/extensions/builtin/gpt-apply-patch/constants.d.ts +1 -0
  44. package/dist/core/extensions/builtin/gpt-apply-patch/constants.d.ts.map +1 -1
  45. package/dist/core/extensions/builtin/gpt-apply-patch/constants.js +5 -1
  46. package/dist/core/extensions/builtin/gpt-apply-patch/constants.js.map +1 -1
  47. package/dist/core/extensions/builtin/gpt-apply-patch/extension.d.ts +2 -1
  48. package/dist/core/extensions/builtin/gpt-apply-patch/extension.d.ts.map +1 -1
  49. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js +48 -29
  50. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js.map +1 -1
  51. package/dist/core/extensions/builtin/gpt-apply-patch/index.d.ts +2 -2
  52. package/dist/core/extensions/builtin/gpt-apply-patch/index.d.ts.map +1 -1
  53. package/dist/core/extensions/builtin/gpt-apply-patch/index.js +2 -2
  54. package/dist/core/extensions/builtin/gpt-apply-patch/index.js.map +1 -1
  55. package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts +1 -1
  56. package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js +5 -3
  58. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js.map +1 -1
  59. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts +7 -6
  60. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/gpt-apply-patch/types.js.map +1 -1
  62. package/dist/core/extensions/builtin/hooks/matcher.d.ts.map +1 -1
  63. package/dist/core/extensions/builtin/hooks/matcher.js +1 -0
  64. package/dist/core/extensions/builtin/hooks/matcher.js.map +1 -1
  65. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  66. package/dist/core/extensions/builtin/index.js +4 -0
  67. package/dist/core/extensions/builtin/index.js.map +1 -1
  68. package/dist/core/extensions/builtin/model-fallback/index.d.ts +4 -0
  69. package/dist/core/extensions/builtin/model-fallback/index.d.ts.map +1 -0
  70. package/dist/core/extensions/builtin/model-fallback/index.js +55 -0
  71. package/dist/core/extensions/builtin/model-fallback/index.js.map +1 -0
  72. package/dist/core/extensions/builtin/model-fallback/settings.d.ts +6 -0
  73. package/dist/core/extensions/builtin/model-fallback/settings.d.ts.map +1 -0
  74. package/dist/core/extensions/builtin/model-fallback/settings.js +11 -0
  75. package/dist/core/extensions/builtin/model-fallback/settings.js.map +1 -0
  76. package/dist/core/extensions/builtin/model-fallback/ui.d.ts +12 -0
  77. package/dist/core/extensions/builtin/model-fallback/ui.d.ts.map +1 -0
  78. package/dist/core/extensions/builtin/model-fallback/ui.js +72 -0
  79. package/dist/core/extensions/builtin/model-fallback/ui.js.map +1 -0
  80. package/dist/core/extensions/builtin/nested-agents-md/index.d.ts.map +1 -1
  81. package/dist/core/extensions/builtin/nested-agents-md/index.js +4 -1
  82. package/dist/core/extensions/builtin/nested-agents-md/index.js.map +1 -1
  83. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js +1 -1
  84. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js.map +1 -1
  85. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +2 -2
  86. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
  87. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +2 -2
  88. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  89. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts +3 -0
  90. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts.map +1 -0
  91. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +80 -0
  92. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js.map +1 -0
  93. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  94. package/dist/core/extensions/builtin/prompt-preset/presets.js +14 -0
  95. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  96. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  97. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  98. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  99. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  100. package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
  101. package/dist/core/extensions/builtin/rules/index.js +4 -1
  102. package/dist/core/extensions/builtin/rules/index.js.map +1 -1
  103. package/dist/core/extensions/builtin/terminal/shared.d.ts +7 -0
  104. package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
  105. package/dist/core/extensions/builtin/terminal/shared.js +7 -0
  106. package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
  107. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts.map +1 -1
  108. package/dist/core/extensions/builtin/terminal/tools/bash.js +68 -6
  109. package/dist/core/extensions/builtin/terminal/tools/bash.js.map +1 -1
  110. package/dist/core/extensions/builtin/todotools/commands.d.ts +18 -0
  111. package/dist/core/extensions/builtin/todotools/commands.d.ts.map +1 -0
  112. package/dist/core/extensions/builtin/todotools/commands.js +395 -0
  113. package/dist/core/extensions/builtin/todotools/commands.js.map +1 -0
  114. package/dist/core/extensions/builtin/todotools/index.d.ts +4 -1
  115. package/dist/core/extensions/builtin/todotools/index.d.ts.map +1 -1
  116. package/dist/core/extensions/builtin/todotools/index.js +17 -14
  117. package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
  118. package/dist/core/extensions/builtin/todotools/markdown.d.ts +13 -0
  119. package/dist/core/extensions/builtin/todotools/markdown.d.ts.map +1 -0
  120. package/dist/core/extensions/builtin/todotools/markdown.js +82 -0
  121. package/dist/core/extensions/builtin/todotools/markdown.js.map +1 -0
  122. package/dist/core/extensions/builtin/todotools/prompt.d.ts +2 -1
  123. package/dist/core/extensions/builtin/todotools/prompt.d.ts.map +1 -1
  124. package/dist/core/extensions/builtin/todotools/prompt.js +50 -153
  125. package/dist/core/extensions/builtin/todotools/prompt.js.map +1 -1
  126. package/dist/core/extensions/builtin/todotools/state.d.ts +67 -14
  127. package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/todotools/state.js +400 -35
  129. package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
  130. package/dist/core/extensions/builtin/todotools/tools/todo.d.ts +22 -0
  131. package/dist/core/extensions/builtin/todotools/tools/todo.d.ts.map +1 -0
  132. package/dist/core/extensions/builtin/todotools/tools/todo.js +229 -0
  133. package/dist/core/extensions/builtin/todotools/tools/todo.js.map +1 -0
  134. package/dist/core/extensions/builtin/video-in/index.d.ts +3 -0
  135. package/dist/core/extensions/builtin/video-in/index.d.ts.map +1 -0
  136. package/dist/core/extensions/builtin/video-in/index.js +111 -0
  137. package/dist/core/extensions/builtin/video-in/index.js.map +1 -0
  138. package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts.map +1 -1
  139. package/dist/core/extensions/builtin/websearch/websearch/renderers.js +13 -4
  140. package/dist/core/extensions/builtin/websearch/websearch/renderers.js.map +1 -1
  141. package/dist/core/extensions/builtin/websearch/websearch/search.d.ts +3 -2
  142. package/dist/core/extensions/builtin/websearch/websearch/search.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/websearch/websearch/search.js +2 -1
  144. package/dist/core/extensions/builtin/websearch/websearch/search.js.map +1 -1
  145. package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/websearch/websearch/tool.js +17 -1
  147. package/dist/core/extensions/builtin/websearch/websearch/tool.js.map +1 -1
  148. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +2 -0
  149. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -1
  150. package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -1
  151. package/dist/core/extensions/loader.d.ts +10 -1
  152. package/dist/core/extensions/loader.d.ts.map +1 -1
  153. package/dist/core/extensions/loader.js +44 -3
  154. package/dist/core/extensions/loader.js.map +1 -1
  155. package/dist/core/extensions/runner.d.ts +3 -1
  156. package/dist/core/extensions/runner.d.ts.map +1 -1
  157. package/dist/core/extensions/runner.js +60 -8
  158. package/dist/core/extensions/runner.js.map +1 -1
  159. package/dist/core/extensions/types.d.ts +103 -18
  160. package/dist/core/extensions/types.d.ts.map +1 -1
  161. package/dist/core/extensions/types.js.map +1 -1
  162. package/dist/core/model-registry.d.ts +5 -1
  163. package/dist/core/model-registry.d.ts.map +1 -1
  164. package/dist/core/model-registry.js +17 -2
  165. package/dist/core/model-registry.js.map +1 -1
  166. package/dist/core/model-runtime.d.ts +12 -1
  167. package/dist/core/model-runtime.d.ts.map +1 -1
  168. package/dist/core/model-runtime.js +51 -9
  169. package/dist/core/model-runtime.js.map +1 -1
  170. package/dist/core/prompt-templates.d.ts +1 -0
  171. package/dist/core/prompt-templates.d.ts.map +1 -1
  172. package/dist/core/prompt-templates.js +4 -4
  173. package/dist/core/prompt-templates.js.map +1 -1
  174. package/dist/core/provider-composer.d.ts +1 -1
  175. package/dist/core/provider-composer.d.ts.map +1 -1
  176. package/dist/core/provider-composer.js.map +1 -1
  177. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  178. package/dist/core/remote-catalog-provider.js +16 -3
  179. package/dist/core/remote-catalog-provider.js.map +1 -1
  180. package/dist/core/resource-loader.d.ts +6 -0
  181. package/dist/core/resource-loader.d.ts.map +1 -1
  182. package/dist/core/resource-loader.js +27 -2
  183. package/dist/core/resource-loader.js.map +1 -1
  184. package/dist/core/retry-fallback/chains.d.ts +29 -0
  185. package/dist/core/retry-fallback/chains.d.ts.map +1 -0
  186. package/dist/core/retry-fallback/chains.js +109 -0
  187. package/dist/core/retry-fallback/chains.js.map +1 -0
  188. package/dist/core/retry-fallback/controller.d.ts +77 -0
  189. package/dist/core/retry-fallback/controller.d.ts.map +1 -0
  190. package/dist/core/retry-fallback/controller.js +157 -0
  191. package/dist/core/retry-fallback/controller.js.map +1 -0
  192. package/dist/core/retry-fallback/cooldown.d.ts +21 -0
  193. package/dist/core/retry-fallback/cooldown.d.ts.map +1 -0
  194. package/dist/core/retry-fallback/cooldown.js +49 -0
  195. package/dist/core/retry-fallback/cooldown.js.map +1 -0
  196. package/dist/core/retry-fallback/log.d.ts +10 -0
  197. package/dist/core/retry-fallback/log.d.ts.map +1 -0
  198. package/dist/core/retry-fallback/log.js +128 -0
  199. package/dist/core/retry-fallback/log.js.map +1 -0
  200. package/dist/core/retry-fallback/validate.d.ts +8 -0
  201. package/dist/core/retry-fallback/validate.d.ts.map +1 -0
  202. package/dist/core/retry-fallback/validate.js +63 -0
  203. package/dist/core/retry-fallback/validate.js.map +1 -0
  204. package/dist/core/sdk.d.ts.map +1 -1
  205. package/dist/core/sdk.js +1 -0
  206. package/dist/core/sdk.js.map +1 -1
  207. package/dist/core/session-manager.d.ts +6 -1
  208. package/dist/core/session-manager.d.ts.map +1 -1
  209. package/dist/core/session-manager.js +19 -3
  210. package/dist/core/session-manager.js.map +1 -1
  211. package/dist/core/settings-manager.d.ts +21 -0
  212. package/dist/core/settings-manager.d.ts.map +1 -1
  213. package/dist/core/settings-manager.js +100 -1
  214. package/dist/core/settings-manager.js.map +1 -1
  215. package/dist/core/tools/bash.d.ts.map +1 -1
  216. package/dist/core/tools/bash.js +20 -5
  217. package/dist/core/tools/bash.js.map +1 -1
  218. package/dist/core/tools/read.js +1 -1
  219. package/dist/core/tools/read.js.map +1 -1
  220. package/dist/extensions/index.d.ts +3 -0
  221. package/dist/extensions/index.d.ts.map +1 -0
  222. package/dist/extensions/index.js +3 -0
  223. package/dist/extensions/index.js.map +1 -0
  224. package/dist/extensions/llama/client.d.ts +61 -0
  225. package/dist/extensions/llama/client.d.ts.map +1 -0
  226. package/dist/extensions/llama/client.js +298 -0
  227. package/dist/extensions/llama/client.js.map +1 -0
  228. package/dist/extensions/llama/huggingface.d.ts +23 -0
  229. package/dist/extensions/llama/huggingface.d.ts.map +1 -0
  230. package/dist/extensions/llama/huggingface.js +139 -0
  231. package/dist/extensions/llama/huggingface.js.map +1 -0
  232. package/dist/extensions/llama/index.d.ts +3 -0
  233. package/dist/extensions/llama/index.d.ts.map +1 -0
  234. package/dist/extensions/llama/index.js +208 -0
  235. package/dist/extensions/llama/index.js.map +1 -0
  236. package/dist/extensions/llama/provider.d.ts +10 -0
  237. package/dist/extensions/llama/provider.d.ts.map +1 -0
  238. package/dist/extensions/llama/provider.js +106 -0
  239. package/dist/extensions/llama/provider.js.map +1 -0
  240. package/dist/extensions/llama/ui.d.ts +42 -0
  241. package/dist/extensions/llama/ui.d.ts.map +1 -0
  242. package/dist/extensions/llama/ui.js +400 -0
  243. package/dist/extensions/llama/ui.js.map +1 -0
  244. package/dist/index.d.ts +1 -1
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js.map +1 -1
  247. package/dist/main.d.ts.map +1 -1
  248. package/dist/main.js +6 -4
  249. package/dist/main.js.map +1 -1
  250. package/dist/modes/interactive/components/assistant-message.d.ts +6 -7
  251. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/assistant-message.js +154 -114
  253. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  254. package/dist/modes/interactive/components/footer.d.ts +2 -1
  255. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  256. package/dist/modes/interactive/components/footer.js +25 -4
  257. package/dist/modes/interactive/components/footer.js.map +1 -1
  258. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  259. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  260. package/dist/modes/interactive/components/settings-selector.js +20 -0
  261. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  262. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  263. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  264. package/dist/modes/interactive/interactive-mode.js +165 -13
  265. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  266. package/dist/modes/interactive/streaming-reveal.d.ts +35 -0
  267. package/dist/modes/interactive/streaming-reveal.d.ts.map +1 -0
  268. package/dist/modes/interactive/streaming-reveal.js +268 -0
  269. package/dist/modes/interactive/streaming-reveal.js.map +1 -0
  270. package/dist/modes/interactive/tool-args-reveal.d.ts +20 -0
  271. package/dist/modes/interactive/tool-args-reveal.d.ts.map +1 -0
  272. package/dist/modes/interactive/tool-args-reveal.js +153 -0
  273. package/dist/modes/interactive/tool-args-reveal.js.map +1 -0
  274. package/dist/utils/child-process.d.ts +17 -1
  275. package/dist/utils/child-process.d.ts.map +1 -1
  276. package/dist/utils/child-process.js +41 -1
  277. package/dist/utils/child-process.js.map +1 -1
  278. package/docs/custom-provider.md +28 -0
  279. package/docs/extensions.md +65 -5
  280. package/docs/index.md +1 -0
  281. package/docs/llama-cpp.md +99 -0
  282. package/docs/neo.md +2 -1
  283. package/docs/prompt-templates.md +1 -0
  284. package/docs/providers.md +7 -0
  285. package/docs/settings.md +35 -0
  286. package/docs/tui.md +41 -26
  287. package/docs/usage.md +1 -0
  288. package/examples/extensions/README.md +1 -1
  289. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +26 -0
  290. package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
  291. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +0 -1
  292. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  293. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +76 -8
  294. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  295. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  296. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +26 -1
  297. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  298. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  299. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +24 -2
  300. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  301. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +5 -0
  302. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
  303. package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
  304. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  305. package/node_modules/@earendil-works/pi-ai/README.md +1 -1
  306. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  307. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +92 -29
  308. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  309. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts.map +1 -1
  310. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +105 -61
  311. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
  312. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +15 -0
  313. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  314. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +15 -0
  315. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  316. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
  317. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  318. package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
  319. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  320. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +4263 -22324
  321. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  322. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts +436 -1988
  323. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
  324. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js +2 -1892
  325. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js.map +1 -1
  326. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.d.ts +10 -80
  327. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.d.ts.map +1 -1
  328. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.js +2 -57
  329. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.js.map +1 -1
  330. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts +43 -267
  331. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts.map +1 -1
  332. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js +2 -252
  333. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js.map +1 -1
  334. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.d.ts +184 -883
  335. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.d.ts.map +1 -1
  336. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.js +2 -811
  337. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.js.map +1 -1
  338. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts +10 -60
  339. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts.map +1 -1
  340. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js +2 -56
  341. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js.map +1 -1
  342. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts +168 -884
  343. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
  344. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js +2 -755
  345. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
  346. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.d.ts +40 -286
  347. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -1
  348. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.js +2 -236
  349. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.js.map +1 -1
  350. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -0
  351. package/node_modules/@earendil-works/pi-ai/dist/providers/data/ant-ling.json +1 -0
  352. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -0
  353. package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -0
  354. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cerebras.json +1 -0
  355. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -0
  356. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -0
  357. package/node_modules/@earendil-works/pi-ai/dist/providers/data/deepseek.json +1 -0
  358. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -0
  359. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -0
  360. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google-vertex.json +1 -0
  361. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -0
  362. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -0
  363. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -0
  364. package/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -0
  365. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax-cn.json +1 -0
  366. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax.json +1 -0
  367. package/node_modules/@earendil-works/pi-ai/dist/providers/data/mistral.json +1 -0
  368. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai-cn.json +1 -0
  369. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai.json +1 -0
  370. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -0
  371. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -0
  372. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -0
  373. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -0
  374. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -0
  375. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -0
  376. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -0
  377. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -0
  378. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xai.json +1 -0
  379. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-ams.json +1 -0
  380. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-cn.json +1 -0
  381. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-sgp.json +1 -0
  382. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi.json +1 -0
  383. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -0
  384. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -0
  385. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.d.ts +7 -58
  386. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.d.ts.map +1 -1
  387. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.js +2 -40
  388. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.js.map +1 -1
  389. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts +1 -0
  390. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts.map +1 -1
  391. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js +1 -0
  392. package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js.map +1 -1
  393. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts +49 -362
  394. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts.map +1 -1
  395. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js +2 -292
  396. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js.map +1 -1
  397. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts +85 -760
  398. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts.map +1 -1
  399. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js +2 -538
  400. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js.map +1 -1
  401. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts +31 -189
  402. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts.map +1 -1
  403. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.js +2 -179
  404. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.js.map +1 -1
  405. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts +49 -309
  406. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts.map +1 -1
  407. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.js +2 -285
  408. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.js.map +1 -1
  409. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.d.ts +22 -118
  410. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.d.ts.map +1 -1
  411. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js +2 -122
  412. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js.map +1 -1
  413. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts +196 -979
  414. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts.map +1 -1
  415. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.js +2 -884
  416. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.js.map +1 -1
  417. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts +13 -122
  418. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts.map +1 -1
  419. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js +2 -98
  420. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js.map +1 -1
  421. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.d.ts +10 -48
  422. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.d.ts.map +1 -1
  423. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.js +2 -53
  424. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.js.map +1 -1
  425. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.d.ts +10 -48
  426. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.d.ts.map +1 -1
  427. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.js +2 -53
  428. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.js.map +1 -1
  429. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts +91 -480
  430. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts.map +1 -1
  431. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js +2 -512
  432. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js.map +1 -1
  433. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts +31 -257
  434. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
  435. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js +2 -185
  436. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js.map +1 -1
  437. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts +31 -257
  438. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts.map +1 -1
  439. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js +2 -185
  440. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js.map +1 -1
  441. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts +58 -541
  442. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts.map +1 -1
  443. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js +2 -382
  444. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js.map +1 -1
  445. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.d.ts +22 -196
  446. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.d.ts.map +1 -1
  447. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.js +2 -139
  448. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.js.map +1 -1
  449. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.d.ts +184 -954
  450. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.d.ts.map +1 -1
  451. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.js +2 -825
  452. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.js.map +1 -1
  453. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.d.ts +1 -1
  454. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.d.ts.map +1 -1
  455. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js +2 -0
  456. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js.map +1 -1
  457. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts +46 -335
  458. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts.map +1 -1
  459. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js +2 -273
  460. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js.map +1 -1
  461. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts +163 -1185
  462. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts.map +1 -1
  463. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js +2 -996
  464. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js.map +1 -1
  465. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +1076 -5729
  466. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
  467. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +2 -4892
  468. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
  469. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.d.ts +49 -610
  470. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.d.ts.map +1 -1
  471. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js +2 -396
  472. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js.map +1 -1
  473. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +752 -3336
  474. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
  475. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +2 -3263
  476. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  477. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts +10 -65
  478. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts.map +1 -1
  479. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js +2 -57
  480. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js.map +1 -1
  481. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.d.ts +10 -63
  482. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
  483. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js +2 -56
  484. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
  485. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.d.ts +10 -63
  486. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
  487. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js +2 -56
  488. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
  489. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.d.ts +10 -63
  490. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
  491. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js +2 -56
  492. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
  493. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.d.ts +19 -126
  494. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.d.ts.map +1 -1
  495. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js +2 -110
  496. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js.map +1 -1
  497. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.d.ts +19 -144
  498. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.d.ts.map +1 -1
  499. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.js +2 -111
  500. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.js.map +1 -1
  501. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.d.ts +19 -144
  502. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.d.ts.map +1 -1
  503. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.js +2 -111
  504. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.js.map +1 -1
  505. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.d.ts.map +1 -1
  506. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js +9 -0
  507. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js.map +1 -1
  508. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
  509. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +2 -1
  510. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
  511. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts +1 -0
  512. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts.map +1 -1
  513. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js +1 -1
  514. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js.map +1 -1
  515. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts +1 -0
  516. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts.map +1 -1
  517. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js +1 -1
  518. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js.map +1 -1
  519. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts +19 -0
  520. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts.map +1 -0
  521. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js +8 -0
  522. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js.map +1 -0
  523. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts +2 -0
  524. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts.map +1 -1
  525. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js +7 -4
  526. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js.map +1 -1
  527. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts +2 -0
  528. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts.map +1 -1
  529. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js +22 -18
  530. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js.map +1 -1
  531. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts +15 -0
  532. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts.map +1 -0
  533. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.js +198 -0
  534. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.js.map +1 -0
  535. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.d.ts +3 -0
  536. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.d.ts.map +1 -0
  537. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.js +8 -0
  538. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.js.map +1 -0
  539. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.d.ts +6 -0
  540. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.d.ts.map +1 -0
  541. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.js +33 -0
  542. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.js.map +1 -0
  543. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts +6 -0
  544. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts.map +1 -0
  545. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js +6 -0
  546. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js.map +1 -0
  547. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.d.ts +4 -0
  548. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.d.ts.map +1 -0
  549. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.js +6 -0
  550. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.js.map +1 -0
  551. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.d.ts +12 -0
  552. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.d.ts.map +1 -0
  553. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.js +46 -0
  554. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.js.map +1 -0
  555. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.d.ts +4 -0
  556. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.d.ts.map +1 -0
  557. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.js +6 -0
  558. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.js.map +1 -0
  559. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts +2 -1
  560. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts.map +1 -1
  561. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.js.map +1 -1
  562. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +19 -2
  563. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  564. package/node_modules/@earendil-works/pi-ai/dist/types.js +4 -1
  565. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  566. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  567. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +6 -1
  568. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  569. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts +4 -0
  570. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts.map +1 -0
  571. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js +6 -0
  572. package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js.map +1 -0
  573. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  574. package/node_modules/@earendil-works/pi-pty/dist/registry-session.d.ts +1 -1
  575. package/node_modules/@earendil-works/pi-pty/dist/registry-session.d.ts.map +1 -1
  576. package/node_modules/@earendil-works/pi-pty/dist/registry-session.js +25 -6
  577. package/node_modules/@earendil-works/pi-pty/dist/registry-session.js.map +1 -1
  578. package/node_modules/@earendil-works/pi-pty/dist/registry-types.d.ts +6 -0
  579. package/node_modules/@earendil-works/pi-pty/dist/registry-types.d.ts.map +1 -1
  580. package/node_modules/@earendil-works/pi-pty/dist/registry-types.js.map +1 -1
  581. package/node_modules/@earendil-works/pi-pty/dist/registry.d.ts +1 -0
  582. package/node_modules/@earendil-works/pi-pty/dist/registry.d.ts.map +1 -1
  583. package/node_modules/@earendil-works/pi-pty/dist/registry.js +9 -1
  584. package/node_modules/@earendil-works/pi-pty/dist/registry.js.map +1 -1
  585. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  586. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
  587. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  588. package/node_modules/@earendil-works/pi-tui/dist/index.js +1 -1
  589. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  590. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +6 -1
  591. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
  592. package/node_modules/@earendil-works/pi-tui/dist/tui.js +14 -2
  593. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  594. package/node_modules/@earendil-works/pi-tui/dist/utils.js +1 -1
  595. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
  596. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  597. package/package.json +6 -6
  598. package/dist/core/extensions/builtin/todotools/tools/todoread.d.ts +0 -4
  599. package/dist/core/extensions/builtin/todotools/tools/todoread.d.ts.map +0 -1
  600. package/dist/core/extensions/builtin/todotools/tools/todoread.js +0 -37
  601. package/dist/core/extensions/builtin/todotools/tools/todoread.js.map +0 -1
  602. package/dist/core/extensions/builtin/todotools/tools/todowrite.d.ts +0 -10
  603. package/dist/core/extensions/builtin/todotools/tools/todowrite.d.ts.map +0 -1
  604. package/dist/core/extensions/builtin/todotools/tools/todowrite.js +0 -95
  605. package/dist/core/extensions/builtin/todotools/tools/todowrite.js.map +0 -1
@@ -0,0 +1,229 @@
1
+ // Ported and adapted from oh-my-pi's todo tool (MIT License).
2
+ // Copyright (c) 2025 Mario Zechner
3
+ // Copyright (c) 2025-2026 Can Bölük
4
+ // https://github.com/can1357/oh-my-pi
5
+ import { Text } from "@earendil-works/pi-tui";
6
+ import { Type } from "typebox";
7
+ import { TODO_TOOL_DESCRIPTION } from "../prompt.js";
8
+ import { applyParams, clonePhases, findTaskByContent, formatSummary, getCompletionTransitions, getTodoMarker, nextActionableTask, sanitizeTodoText, TODO_STATE_ENTRY_TYPE, } from "../state.js";
9
+ const TodoOperationSchema = Type.Union([
10
+ Type.Literal("init"),
11
+ Type.Literal("start"),
12
+ Type.Literal("done"),
13
+ Type.Literal("rm"),
14
+ Type.Literal("drop"),
15
+ Type.Literal("append"),
16
+ Type.Literal("view"),
17
+ ]);
18
+ const TodoPhaseInputSchema = Type.Object({
19
+ phase: Type.String({ description: "Phase name" }),
20
+ items: Type.Array(Type.String({ description: "Task content" }), {
21
+ description: "Tasks for this phase",
22
+ minItems: 1,
23
+ }),
24
+ });
25
+ export const TODO_PARAMS_SCHEMA = Type.Object({
26
+ op: TodoOperationSchema,
27
+ list: Type.Optional(Type.Array(TodoPhaseInputSchema, { description: "Phased task list for init" })),
28
+ task: Type.Optional(Type.String({ description: "Task content" })),
29
+ phase: Type.Optional(Type.String({ description: "Phase name" })),
30
+ // Keep this unconstrained at the schema boundary. init and append return
31
+ // operation-specific errors, while unrelated operations may ignore it.
32
+ items: Type.Optional(Type.Array(Type.String({ description: "Task content" }), { description: "Tasks to append" })),
33
+ });
34
+ function countInitItems(params) {
35
+ if (params.list) {
36
+ return {
37
+ phases: params.list.length,
38
+ tasks: params.list.reduce((total, phase) => total + phase.items.length, 0),
39
+ };
40
+ }
41
+ if (params.items)
42
+ return { phases: params.items.length > 0 ? 1 : 0, tasks: params.items.length };
43
+ return { phases: 0, tasks: 0 };
44
+ }
45
+ function countLabel(count, singular) {
46
+ return `${count} ${singular}${count === 1 ? "" : "s"}`;
47
+ }
48
+ function renderCallLabel(params) {
49
+ switch (params.op) {
50
+ case "init": {
51
+ const counts = countInitItems(params);
52
+ return `todo init (${countLabel(counts.phases, "phase")}, ${countLabel(counts.tasks, "task")})`;
53
+ }
54
+ case "append":
55
+ return `todo append: ${sanitizeTodoText(params.phase ?? "") || "(missing phase)"} (${countLabel(params.items?.length ?? 0, "item")})`;
56
+ case "start":
57
+ case "done":
58
+ case "drop":
59
+ return `todo ${params.op}: ${sanitizeTodoText(params.task ?? params.phase ?? "") || "(missing target)"}`;
60
+ case "rm":
61
+ return `todo rm: ${sanitizeTodoText(params.task ?? params.phase ?? "all") || "all"}`;
62
+ case "view":
63
+ return "todo view";
64
+ }
65
+ }
66
+ export function phaseRomanNumeral(oneBasedIndex) {
67
+ if (oneBasedIndex <= 0)
68
+ return "";
69
+ const pairs = [
70
+ [1000, "M"],
71
+ [900, "CM"],
72
+ [500, "D"],
73
+ [400, "CD"],
74
+ [100, "C"],
75
+ [90, "XC"],
76
+ [50, "L"],
77
+ [40, "XL"],
78
+ [10, "X"],
79
+ [9, "IX"],
80
+ [5, "V"],
81
+ [4, "IV"],
82
+ [1, "I"],
83
+ ];
84
+ let remaining = oneBasedIndex;
85
+ let output = "";
86
+ for (const [value, symbol] of pairs) {
87
+ while (remaining >= value) {
88
+ output += symbol;
89
+ remaining -= value;
90
+ }
91
+ }
92
+ return output;
93
+ }
94
+ function formatPhaseHeader(name, index, theme) {
95
+ return theme.fg("accent", theme.bold(`${phaseRomanNumeral(index)}. ${sanitizeTodoText(name)}`));
96
+ }
97
+ function formatPhaseSummary(phase, index, theme) {
98
+ const closed = phase.tasks.filter((task) => task.status === "completed" || task.status === "abandoned").length;
99
+ return theme.fg("dim", `${phaseRomanNumeral(index)}. ${sanitizeTodoText(phase.name)} — ${closed}/${phase.tasks.length} done`);
100
+ }
101
+ function formatTaskLine(task, theme) {
102
+ const content = sanitizeTodoText(task.content);
103
+ const line = `${getTodoMarker(task.status)} ${content}`;
104
+ switch (task.status) {
105
+ case "completed":
106
+ return theme.fg("dim", theme.strikethrough(line));
107
+ case "in_progress":
108
+ return theme.fg("accent", theme.bold(line));
109
+ case "abandoned":
110
+ return theme.fg("dim", line);
111
+ case "pending":
112
+ return line;
113
+ }
114
+ }
115
+ function computeTouchedPhases(args, phases, completedTasks) {
116
+ const touched = new Set();
117
+ const activeTask = nextActionableTask(phases);
118
+ if (activeTask) {
119
+ const activePhase = phases.find((phase) => phase.tasks.includes(activeTask));
120
+ if (activePhase)
121
+ touched.add(activePhase.name);
122
+ }
123
+ for (const transition of completedTasks)
124
+ touched.add(transition.phase);
125
+ if (args.op === "init") {
126
+ for (const phase of phases)
127
+ touched.add(phase.name);
128
+ }
129
+ else {
130
+ if (args.phase) {
131
+ const phase = phases.find((candidate) => candidate.name === args.phase);
132
+ if (phase)
133
+ touched.add(phase.name);
134
+ }
135
+ if (args.task) {
136
+ const hit = findTaskByContent([...phases], args.task);
137
+ if (hit)
138
+ touched.add(hit.phase.name);
139
+ }
140
+ }
141
+ return touched.size > 0 ? touched : null;
142
+ }
143
+ function renderTodoPhases(phases, completedTasks, options, args, theme) {
144
+ const visiblePhases = phases.filter((phase) => phase.tasks.length > 0);
145
+ if (visiblePhases.length === 0)
146
+ return "";
147
+ const touched = options.expanded || visiblePhases.length === 1 ? null : computeTouchedPhases(args, visiblePhases, completedTasks);
148
+ const lines = [];
149
+ for (let index = 0; index < visiblePhases.length; index += 1) {
150
+ const phase = visiblePhases[index];
151
+ const oneBasedIndex = index + 1;
152
+ if (touched && !touched.has(phase.name)) {
153
+ lines.push(formatPhaseSummary(phase, oneBasedIndex, theme));
154
+ continue;
155
+ }
156
+ lines.push(formatPhaseHeader(phase.name, oneBasedIndex, theme));
157
+ for (const task of phase.tasks)
158
+ lines.push(` ${formatTaskLine(task, theme)}`);
159
+ }
160
+ return lines.join("\n");
161
+ }
162
+ function getTextContent(result) {
163
+ return result.content
164
+ .filter((content) => content.type === "text" && typeof content.text === "string")
165
+ .map((content) => content.text)
166
+ .join("\n");
167
+ }
168
+ export function registerTodoTool(pi, accessors) {
169
+ const tool = {
170
+ name: "todo",
171
+ label: "Todo",
172
+ description: TODO_TOOL_DESCRIPTION,
173
+ promptSnippet: "Track phased tasks with one op-based todo tool; reference tasks by their exact content.",
174
+ promptGuidelines: [
175
+ "Use one todo operation at a time; batch it with the real work rather than making a solo todo turn.",
176
+ "Reference tasks and phases by their exact content/name; use view when the text is uncertain.",
177
+ "Mark work done immediately and use drop for tasks that are no longer needed.",
178
+ ],
179
+ parameters: TODO_PARAMS_SCHEMA,
180
+ executionMode: "sequential",
181
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
182
+ const previousPhases = clonePhases(accessors.getCurrentPhases());
183
+ const readOnly = params.op === "view";
184
+ const applied = readOnly
185
+ ? { phases: previousPhases, errors: [] }
186
+ : applyParams(clonePhases(previousPhases), params);
187
+ const failed = applied.errors.length > 0;
188
+ const effective = failed ? previousPhases : applied.phases;
189
+ const completedTasks = readOnly || failed ? [] : getCompletionTransitions(previousPhases, applied.phases);
190
+ if (!readOnly && !failed) {
191
+ pi.appendEntry(TODO_STATE_ENTRY_TYPE, {
192
+ schema: "v2",
193
+ phases: clonePhases(applied.phases),
194
+ });
195
+ accessors.setCurrentPhases(clonePhases(applied.phases));
196
+ accessors.syncWidget(ctx);
197
+ }
198
+ const details = {
199
+ op: params.op,
200
+ phases: clonePhases(effective),
201
+ storage: ctx.sessionManager.getSessionFile() ? "session" : "memory",
202
+ };
203
+ if (completedTasks.length > 0)
204
+ details.completedTasks = completedTasks;
205
+ return {
206
+ content: [{ type: "text", text: formatSummary(effective, applied.errors, readOnly) }],
207
+ details,
208
+ isError: failed ? true : undefined,
209
+ };
210
+ },
211
+ renderCall(args, theme) {
212
+ return new Text(theme.fg("toolTitle", theme.bold(renderCallLabel(args))), 0, 0);
213
+ },
214
+ renderResult(result, options, theme, context) {
215
+ if (isTodoToolError(result) || context.isError) {
216
+ return new Text(theme.fg("toolOutput", getTextContent(result)), 0, 0);
217
+ }
218
+ const phases = result.details?.phases ?? [];
219
+ const rendered = renderTodoPhases(phases, result.details?.completedTasks ?? [], options, context.args, theme);
220
+ const text = rendered || getTextContent(result) || "Todo list is empty.";
221
+ return new Text(text, 0, 0);
222
+ },
223
+ };
224
+ pi.registerTool(tool);
225
+ }
226
+ function isTodoToolError(result) {
227
+ return "isError" in result && result.isError === true;
228
+ }
229
+ //# sourceMappingURL=todo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todo.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/todotools/tools/todo.ts"],"names":[],"mappings":"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","sourcesContent":["// Ported and adapted from oh-my-pi's todo tool (MIT License).\n// Copyright (c) 2025 Mario Zechner\n// Copyright (c) 2025-2026 Can Bölük\n// https://github.com/can1357/oh-my-pi\n\nimport { Text } from \"@earendil-works/pi-tui\";\nimport { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../../../../modes/interactive/theme/theme.ts\";\nimport type {\n\tAgentToolResult,\n\tExtensionAPI,\n\tExtensionContext,\n\tToolDefinition,\n\tToolRenderContext,\n\tToolRenderResultOptions,\n} from \"../../../types.ts\";\nimport { TODO_TOOL_DESCRIPTION } from \"../prompt.ts\";\nimport {\n\tapplyParams,\n\tclonePhases,\n\tfindTaskByContent,\n\tformatSummary,\n\tgetCompletionTransitions,\n\tgetTodoMarker,\n\tnextActionableTask,\n\tsanitizeTodoText,\n\tTODO_STATE_ENTRY_TYPE,\n\ttype TodoCompletionTransition,\n\ttype TodoPhase,\n\ttype TodoStateEntry,\n\ttype TodoToolDetails,\n} from \"../state.ts\";\n\nconst TodoOperationSchema = Type.Union([\n\tType.Literal(\"init\"),\n\tType.Literal(\"start\"),\n\tType.Literal(\"done\"),\n\tType.Literal(\"rm\"),\n\tType.Literal(\"drop\"),\n\tType.Literal(\"append\"),\n\tType.Literal(\"view\"),\n]);\n\nconst TodoPhaseInputSchema = Type.Object({\n\tphase: Type.String({ description: \"Phase name\" }),\n\titems: Type.Array(Type.String({ description: \"Task content\" }), {\n\t\tdescription: \"Tasks for this phase\",\n\t\tminItems: 1,\n\t}),\n});\n\nexport const TODO_PARAMS_SCHEMA = Type.Object({\n\top: TodoOperationSchema,\n\tlist: Type.Optional(Type.Array(TodoPhaseInputSchema, { description: \"Phased task list for init\" })),\n\ttask: Type.Optional(Type.String({ description: \"Task content\" })),\n\tphase: Type.Optional(Type.String({ description: \"Phase name\" })),\n\t// Keep this unconstrained at the schema boundary. init and append return\n\t// operation-specific errors, while unrelated operations may ignore it.\n\titems: Type.Optional(Type.Array(Type.String({ description: \"Task content\" }), { description: \"Tasks to append\" })),\n});\n\ntype TodoParams = Static<typeof TODO_PARAMS_SCHEMA>;\n\ntype TodoAccessors = {\n\tgetCurrentPhases: () => TodoPhase[];\n\tsetCurrentPhases: (phases: TodoPhase[]) => void;\n\tsyncWidget: (ctx: ExtensionContext) => void;\n};\n\ntype TodoToolResult = AgentToolResult<TodoToolDetails> & {\n\tisError?: boolean;\n};\n\nfunction countInitItems(params: TodoParams): { phases: number; tasks: number } {\n\tif (params.list) {\n\t\treturn {\n\t\t\tphases: params.list.length,\n\t\t\ttasks: params.list.reduce((total, phase) => total + phase.items.length, 0),\n\t\t};\n\t}\n\tif (params.items) return { phases: params.items.length > 0 ? 1 : 0, tasks: params.items.length };\n\treturn { phases: 0, tasks: 0 };\n}\n\nfunction countLabel(count: number, singular: string): string {\n\treturn `${count} ${singular}${count === 1 ? \"\" : \"s\"}`;\n}\n\nfunction renderCallLabel(params: TodoParams): string {\n\tswitch (params.op) {\n\t\tcase \"init\": {\n\t\t\tconst counts = countInitItems(params);\n\t\t\treturn `todo init (${countLabel(counts.phases, \"phase\")}, ${countLabel(counts.tasks, \"task\")})`;\n\t\t}\n\t\tcase \"append\":\n\t\t\treturn `todo append: ${sanitizeTodoText(params.phase ?? \"\") || \"(missing phase)\"} (${countLabel(\n\t\t\t\tparams.items?.length ?? 0,\n\t\t\t\t\"item\",\n\t\t\t)})`;\n\t\tcase \"start\":\n\t\tcase \"done\":\n\t\tcase \"drop\":\n\t\t\treturn `todo ${params.op}: ${sanitizeTodoText(params.task ?? params.phase ?? \"\") || \"(missing target)\"}`;\n\t\tcase \"rm\":\n\t\t\treturn `todo rm: ${sanitizeTodoText(params.task ?? params.phase ?? \"all\") || \"all\"}`;\n\t\tcase \"view\":\n\t\t\treturn \"todo view\";\n\t}\n}\n\nexport function phaseRomanNumeral(oneBasedIndex: number): string {\n\tif (oneBasedIndex <= 0) return \"\";\n\tconst pairs: ReadonlyArray<readonly [number, string]> = [\n\t\t[1000, \"M\"],\n\t\t[900, \"CM\"],\n\t\t[500, \"D\"],\n\t\t[400, \"CD\"],\n\t\t[100, \"C\"],\n\t\t[90, \"XC\"],\n\t\t[50, \"L\"],\n\t\t[40, \"XL\"],\n\t\t[10, \"X\"],\n\t\t[9, \"IX\"],\n\t\t[5, \"V\"],\n\t\t[4, \"IV\"],\n\t\t[1, \"I\"],\n\t];\n\tlet remaining = oneBasedIndex;\n\tlet output = \"\";\n\tfor (const [value, symbol] of pairs) {\n\t\twhile (remaining >= value) {\n\t\t\toutput += symbol;\n\t\t\tremaining -= value;\n\t\t}\n\t}\n\treturn output;\n}\n\nfunction formatPhaseHeader(name: string, index: number, theme: Theme): string {\n\treturn theme.fg(\"accent\", theme.bold(`${phaseRomanNumeral(index)}. ${sanitizeTodoText(name)}`));\n}\n\nfunction formatPhaseSummary(phase: TodoPhase, index: number, theme: Theme): string {\n\tconst closed = phase.tasks.filter((task) => task.status === \"completed\" || task.status === \"abandoned\").length;\n\treturn theme.fg(\n\t\t\"dim\",\n\t\t`${phaseRomanNumeral(index)}. ${sanitizeTodoText(phase.name)} — ${closed}/${phase.tasks.length} done`,\n\t);\n}\n\nfunction formatTaskLine(task: TodoPhase[\"tasks\"][number], theme: Theme): string {\n\tconst content = sanitizeTodoText(task.content);\n\tconst line = `${getTodoMarker(task.status)} ${content}`;\n\tswitch (task.status) {\n\t\tcase \"completed\":\n\t\t\treturn theme.fg(\"dim\", theme.strikethrough(line));\n\t\tcase \"in_progress\":\n\t\t\treturn theme.fg(\"accent\", theme.bold(line));\n\t\tcase \"abandoned\":\n\t\t\treturn theme.fg(\"dim\", line);\n\t\tcase \"pending\":\n\t\t\treturn line;\n\t}\n}\n\nfunction computeTouchedPhases(\n\targs: TodoParams,\n\tphases: readonly TodoPhase[],\n\tcompletedTasks: readonly TodoCompletionTransition[],\n): Set<string> | null {\n\tconst touched = new Set<string>();\n\tconst activeTask = nextActionableTask(phases);\n\tif (activeTask) {\n\t\tconst activePhase = phases.find((phase) => phase.tasks.includes(activeTask));\n\t\tif (activePhase) touched.add(activePhase.name);\n\t}\n\tfor (const transition of completedTasks) touched.add(transition.phase);\n\tif (args.op === \"init\") {\n\t\tfor (const phase of phases) touched.add(phase.name);\n\t} else {\n\t\tif (args.phase) {\n\t\t\tconst phase = phases.find((candidate) => candidate.name === args.phase);\n\t\t\tif (phase) touched.add(phase.name);\n\t\t}\n\t\tif (args.task) {\n\t\t\tconst hit = findTaskByContent([...phases], args.task);\n\t\t\tif (hit) touched.add(hit.phase.name);\n\t\t}\n\t}\n\treturn touched.size > 0 ? touched : null;\n}\n\nfunction renderTodoPhases(\n\tphases: readonly TodoPhase[],\n\tcompletedTasks: readonly TodoCompletionTransition[],\n\toptions: ToolRenderResultOptions,\n\targs: TodoParams,\n\ttheme: Theme,\n): string {\n\tconst visiblePhases = phases.filter((phase) => phase.tasks.length > 0);\n\tif (visiblePhases.length === 0) return \"\";\n\n\tconst touched =\n\t\toptions.expanded || visiblePhases.length === 1 ? null : computeTouchedPhases(args, visiblePhases, completedTasks);\n\tconst lines: string[] = [];\n\tfor (let index = 0; index < visiblePhases.length; index += 1) {\n\t\tconst phase = visiblePhases[index];\n\t\tconst oneBasedIndex = index + 1;\n\t\tif (touched && !touched.has(phase.name)) {\n\t\t\tlines.push(formatPhaseSummary(phase, oneBasedIndex, theme));\n\t\t\tcontinue;\n\t\t}\n\t\tlines.push(formatPhaseHeader(phase.name, oneBasedIndex, theme));\n\t\tfor (const task of phase.tasks) lines.push(` ${formatTaskLine(task, theme)}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction getTextContent(result: AgentToolResult<TodoToolDetails>): string {\n\treturn result.content\n\t\t.filter(\n\t\t\t(content): content is { type: \"text\"; text: string } =>\n\t\t\t\tcontent.type === \"text\" && typeof content.text === \"string\",\n\t\t)\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\");\n}\n\nexport function registerTodoTool(pi: ExtensionAPI, accessors: TodoAccessors): void {\n\tconst tool: ToolDefinition<typeof TODO_PARAMS_SCHEMA, TodoToolDetails, unknown> = {\n\t\tname: \"todo\",\n\t\tlabel: \"Todo\",\n\t\tdescription: TODO_TOOL_DESCRIPTION,\n\t\tpromptSnippet: \"Track phased tasks with one op-based todo tool; reference tasks by their exact content.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use one todo operation at a time; batch it with the real work rather than making a solo todo turn.\",\n\t\t\t\"Reference tasks and phases by their exact content/name; use view when the text is uncertain.\",\n\t\t\t\"Mark work done immediately and use drop for tasks that are no longer needed.\",\n\t\t],\n\t\tparameters: TODO_PARAMS_SCHEMA,\n\t\texecutionMode: \"sequential\",\n\t\tasync execute(_toolCallId, params, _signal, _onUpdate, ctx): Promise<TodoToolResult> {\n\t\t\tconst previousPhases = clonePhases(accessors.getCurrentPhases());\n\t\t\tconst readOnly = params.op === \"view\";\n\t\t\tconst applied = readOnly\n\t\t\t\t? { phases: previousPhases, errors: [] as string[] }\n\t\t\t\t: applyParams(clonePhases(previousPhases), params);\n\t\t\tconst failed = applied.errors.length > 0;\n\t\t\tconst effective = failed ? previousPhases : applied.phases;\n\t\t\tconst completedTasks = readOnly || failed ? [] : getCompletionTransitions(previousPhases, applied.phases);\n\t\t\tif (!readOnly && !failed) {\n\t\t\t\tpi.appendEntry(TODO_STATE_ENTRY_TYPE, {\n\t\t\t\t\tschema: \"v2\",\n\t\t\t\t\tphases: clonePhases(applied.phases),\n\t\t\t\t} satisfies TodoStateEntry);\n\t\t\t\taccessors.setCurrentPhases(clonePhases(applied.phases));\n\t\t\t\taccessors.syncWidget(ctx);\n\t\t\t}\n\n\t\t\tconst details: TodoToolDetails = {\n\t\t\t\top: params.op,\n\t\t\t\tphases: clonePhases(effective),\n\t\t\t\tstorage: ctx.sessionManager.getSessionFile() ? \"session\" : \"memory\",\n\t\t\t};\n\t\t\tif (completedTasks.length > 0) details.completedTasks = completedTasks;\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: formatSummary(effective, applied.errors, readOnly) }],\n\t\t\t\tdetails,\n\t\t\t\tisError: failed ? true : undefined,\n\t\t\t};\n\t\t},\n\t\trenderCall(args, theme) {\n\t\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(renderCallLabel(args))), 0, 0);\n\t\t},\n\t\trenderResult(result, options, theme, context: ToolRenderContext<unknown, TodoParams>) {\n\t\t\tif (isTodoToolError(result) || context.isError) {\n\t\t\t\treturn new Text(theme.fg(\"toolOutput\", getTextContent(result)), 0, 0);\n\t\t\t}\n\t\t\tconst phases = result.details?.phases ?? [];\n\t\t\tconst rendered = renderTodoPhases(phases, result.details?.completedTasks ?? [], options, context.args, theme);\n\t\t\tconst text = rendered || getTextContent(result) || \"Todo list is empty.\";\n\t\t\treturn new Text(text, 0, 0);\n\t\t},\n\t};\n\n\tpi.registerTool(tool);\n}\n\nfunction isTodoToolError(result: AgentToolResult<TodoToolDetails>): result is TodoToolResult {\n\treturn \"isError\" in result && result.isError === true;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { ExtensionAPI } from "../../types.ts";
2
+ export default function videoInExtension(pi: ExtensionAPI): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/video-in/index.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAkCnD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAsE/D"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * video-in — model-gated video file input (kimi-code `ReadMediaFile` parity).
3
+ *
4
+ * Registers a `read_video` tool that reads a local video file and attaches it
5
+ * to the conversation as a base64 video payload. The tool is only active when
6
+ * the current model declares the "video" input modality (currently only
7
+ * kimi-coding `k3`); on `session_start` and `model_select` it is added to or
8
+ * removed from the active tool set accordingly.
9
+ *
10
+ * Wire behavior: the payload rides an ImageContent block with a `video/*`
11
+ * mimeType. The anthropic-messages API serializes such blocks as
12
+ * `{type:"video", source:{type:"base64", media_type, data}}`, which the Kimi
13
+ * Anthropic-compatible endpoint accepts (verified against MoonshotAI/kimi-code
14
+ * kosong anthropic provider). transform-messages downgrades the block to a
15
+ * placeholder for models without the "video" modality, so switching models
16
+ * mid-session cannot wedge the request.
17
+ */
18
+ import { readFile as fsReadFile, stat as fsStat } from "node:fs/promises";
19
+ import { basename, extname, isAbsolute, resolve as resolvePath } from "node:path";
20
+ import { Type } from "typebox";
21
+ const TOOL_NAME = "read_video";
22
+ /** Same cap as kimi-code's ReadMediaFile (base64 inflates ~4/3 on the wire). */
23
+ const MAX_VIDEO_MEGABYTES = 100;
24
+ const MAX_VIDEO_BYTES = MAX_VIDEO_MEGABYTES * 1024 * 1024;
25
+ /** Extension -> mime map mirrored from kimi-code's supported video set. */
26
+ const EXT_TO_MIME = {
27
+ mp4: "video/mp4",
28
+ mpeg: "video/mpeg",
29
+ mpg: "video/mpeg",
30
+ mov: "video/quicktime",
31
+ webm: "video/webm",
32
+ mkv: "video/x-matroska",
33
+ avi: "video/x-msvideo",
34
+ flv: "video/x-flv",
35
+ "3gp": "video/3gpp",
36
+ };
37
+ function detectVideoMimeType(path) {
38
+ const ext = extname(path).slice(1).toLowerCase();
39
+ return EXT_TO_MIME[ext];
40
+ }
41
+ function modelSupportsVideo(model) {
42
+ return model?.input?.includes("video") === true;
43
+ }
44
+ const readVideoSchema = Type.Object({
45
+ path: Type.String({ description: "Path to a video file (relative or absolute). Max 100MB." }),
46
+ });
47
+ export default function videoInExtension(pi) {
48
+ pi.registerTool({
49
+ name: TOOL_NAME,
50
+ label: "Read Video",
51
+ description: `Read a video file (${Object.keys(EXT_TO_MIME).join(", ")}) and attach it to the conversation so you can watch it. ` +
52
+ `Maximum file size ${MAX_VIDEO_MEGABYTES}MB. ` +
53
+ "Use this to understand screen recordings, demo clips, or any behavior that is hard to describe in text. " +
54
+ "If you generate or edit a video via commands or scripts, read the result back before continuing.",
55
+ promptSnippet: "Attach a video file so the model can watch it (video-capable models only)",
56
+ parameters: readVideoSchema,
57
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
58
+ if (signal?.aborted)
59
+ throw new Error("Operation aborted");
60
+ if (!modelSupportsVideo(ctx.model)) {
61
+ throw new Error("The current model does not support video input. Tell the user to switch to a model with video input capability (e.g. kimi-coding/k3).");
62
+ }
63
+ const absolutePath = isAbsolute(params.path) ? params.path : resolvePath(ctx.cwd, params.path);
64
+ const mimeType = detectVideoMimeType(absolutePath);
65
+ if (!mimeType) {
66
+ throw new Error(`"${params.path}" is not a supported video file. Supported extensions: ${Object.keys(EXT_TO_MIME).join(", ")}.`);
67
+ }
68
+ const stats = await fsStat(absolutePath);
69
+ if (!stats.isFile()) {
70
+ throw new Error(`"${params.path}" is not a regular file.`);
71
+ }
72
+ if (stats.size === 0) {
73
+ throw new Error(`"${params.path}" is empty.`);
74
+ }
75
+ if (stats.size > MAX_VIDEO_BYTES) {
76
+ throw new Error(`"${params.path}" is ${stats.size} bytes, which exceeds the maximum ${MAX_VIDEO_MEGABYTES}MB for video files. Create a smaller clip (e.g. with ffmpeg) and read that instead.`);
77
+ }
78
+ const data = await fsReadFile(absolutePath);
79
+ if (signal?.aborted)
80
+ throw new Error("Operation aborted");
81
+ return {
82
+ content: [
83
+ {
84
+ type: "text",
85
+ text: `Read video file "${basename(absolutePath)}" [${mimeType}, ${stats.size} bytes]. The video is attached below.`,
86
+ },
87
+ { type: "image", data: data.toString("base64"), mimeType },
88
+ ],
89
+ details: undefined,
90
+ };
91
+ },
92
+ });
93
+ function syncToolActivation(model) {
94
+ const active = pi.getActiveTools();
95
+ const isActive = active.includes(TOOL_NAME);
96
+ const shouldBeActive = modelSupportsVideo(model);
97
+ if (shouldBeActive && !isActive) {
98
+ pi.setActiveTools([...active, TOOL_NAME]);
99
+ }
100
+ else if (!shouldBeActive && isActive) {
101
+ pi.setActiveTools(active.filter((name) => name !== TOOL_NAME));
102
+ }
103
+ }
104
+ pi.on("session_start", async (_event, ctx) => {
105
+ syncToolActivation(ctx.model);
106
+ });
107
+ pi.on("model_select", async (event) => {
108
+ syncToolActivation(event.model);
109
+ });
110
+ }
111
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/video-in/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * video-in — model-gated video file input (kimi-code `ReadMediaFile` parity).\n *\n * Registers a `read_video` tool that reads a local video file and attaches it\n * to the conversation as a base64 video payload. The tool is only active when\n * the current model declares the \"video\" input modality (currently only\n * kimi-coding `k3`); on `session_start` and `model_select` it is added to or\n * removed from the active tool set accordingly.\n *\n * Wire behavior: the payload rides an ImageContent block with a `video/*`\n * mimeType. The anthropic-messages API serializes such blocks as\n * `{type:\"video\", source:{type:\"base64\", media_type, data}}`, which the Kimi\n * Anthropic-compatible endpoint accepts (verified against MoonshotAI/kimi-code\n * kosong anthropic provider). transform-messages downgrades the block to a\n * placeholder for models without the \"video\" modality, so switching models\n * mid-session cannot wedge the request.\n */\nimport { readFile as fsReadFile, stat as fsStat } from \"node:fs/promises\";\nimport { basename, extname, isAbsolute, resolve as resolvePath } from \"node:path\";\nimport type { Model } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport type { ExtensionAPI } from \"../../types.ts\";\n\nconst TOOL_NAME = \"read_video\";\n\n/** Same cap as kimi-code's ReadMediaFile (base64 inflates ~4/3 on the wire). */\nconst MAX_VIDEO_MEGABYTES = 100;\nconst MAX_VIDEO_BYTES = MAX_VIDEO_MEGABYTES * 1024 * 1024;\n\n/** Extension -> mime map mirrored from kimi-code's supported video set. */\nconst EXT_TO_MIME: Record<string, string> = {\n\tmp4: \"video/mp4\",\n\tmpeg: \"video/mpeg\",\n\tmpg: \"video/mpeg\",\n\tmov: \"video/quicktime\",\n\twebm: \"video/webm\",\n\tmkv: \"video/x-matroska\",\n\tavi: \"video/x-msvideo\",\n\tflv: \"video/x-flv\",\n\t\"3gp\": \"video/3gpp\",\n};\n\nfunction detectVideoMimeType(path: string): string | undefined {\n\tconst ext = extname(path).slice(1).toLowerCase();\n\treturn EXT_TO_MIME[ext];\n}\n\nfunction modelSupportsVideo(model: Model<any> | undefined): boolean {\n\treturn model?.input?.includes(\"video\") === true;\n}\n\nconst readVideoSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to a video file (relative or absolute). Max 100MB.\" }),\n});\n\nexport default function videoInExtension(pi: ExtensionAPI): void {\n\tpi.registerTool({\n\t\tname: TOOL_NAME,\n\t\tlabel: \"Read Video\",\n\t\tdescription:\n\t\t\t`Read a video file (${Object.keys(EXT_TO_MIME).join(\", \")}) and attach it to the conversation so you can watch it. ` +\n\t\t\t`Maximum file size ${MAX_VIDEO_MEGABYTES}MB. ` +\n\t\t\t\"Use this to understand screen recordings, demo clips, or any behavior that is hard to describe in text. \" +\n\t\t\t\"If you generate or edit a video via commands or scripts, read the result back before continuing.\",\n\t\tpromptSnippet: \"Attach a video file so the model can watch it (video-capable models only)\",\n\t\tparameters: readVideoSchema,\n\t\tasync execute(_toolCallId, params, signal, _onUpdate, ctx) {\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\tif (!modelSupportsVideo(ctx.model)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"The current model does not support video input. Tell the user to switch to a model with video input capability (e.g. kimi-coding/k3).\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst absolutePath = isAbsolute(params.path) ? params.path : resolvePath(ctx.cwd, params.path);\n\t\t\tconst mimeType = detectVideoMimeType(absolutePath);\n\t\t\tif (!mimeType) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`\"${params.path}\" is not a supported video file. Supported extensions: ${Object.keys(EXT_TO_MIME).join(\", \")}.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst stats = await fsStat(absolutePath);\n\t\t\tif (!stats.isFile()) {\n\t\t\t\tthrow new Error(`\"${params.path}\" is not a regular file.`);\n\t\t\t}\n\t\t\tif (stats.size === 0) {\n\t\t\t\tthrow new Error(`\"${params.path}\" is empty.`);\n\t\t\t}\n\t\t\tif (stats.size > MAX_VIDEO_BYTES) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`\"${params.path}\" is ${stats.size} bytes, which exceeds the maximum ${MAX_VIDEO_MEGABYTES}MB for video files. Create a smaller clip (e.g. with ffmpeg) and read that instead.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst data = await fsReadFile(absolutePath);\n\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Read video file \"${basename(absolutePath)}\" [${mimeType}, ${stats.size} bytes]. The video is attached below.`,\n\t\t\t\t\t},\n\t\t\t\t\t{ type: \"image\", data: data.toString(\"base64\"), mimeType },\n\t\t\t\t],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t},\n\t});\n\n\tfunction syncToolActivation(model: Model<any> | undefined): void {\n\t\tconst active = pi.getActiveTools();\n\t\tconst isActive = active.includes(TOOL_NAME);\n\t\tconst shouldBeActive = modelSupportsVideo(model);\n\t\tif (shouldBeActive && !isActive) {\n\t\t\tpi.setActiveTools([...active, TOOL_NAME]);\n\t\t} else if (!shouldBeActive && isActive) {\n\t\t\tpi.setActiveTools(active.filter((name) => name !== TOOL_NAME));\n\t\t}\n\t}\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tsyncToolActivation(ctx.model);\n\t});\n\n\tpi.on(\"model_select\", async (event) => {\n\t\tsyncToolActivation(event.model);\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"renderers.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,OAAO,KAAK,EAA4D,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEhH,UAAU,SAAS;IAClB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACvC;AAED,UAAU,UAAU;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,UAAU,UAAU,CAAC,QAAQ;IAC5B,OAAO,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,OAAO,CAAC,EAAE,QAAQ,CAAC;CACnB;AAED,UAAU,mBAAmB;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AA6BD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAMzE;AAED,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,UAAU,CAAC,mBAAmB,CAAC,EACvC,OAAO,EAAE,mBAAmB,EAC5B,KAAK,EAAE,SAAS,GACd,IAAI,CA2CN"}
1
+ {"version":3,"file":"renderers.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,OAAO,KAAK,EAA4D,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEhH,UAAU,SAAS;IAClB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACvC;AAED,UAAU,UAAU;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,UAAU,UAAU,CAAC,QAAQ;IAC5B,OAAO,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,OAAO,CAAC,EAAE,QAAQ,CAAC;CACnB;AAED,UAAU,mBAAmB;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AA6BD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAMzE;AAED,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,UAAU,CAAC,mBAAmB,CAAC,EACvC,OAAO,EAAE,mBAAmB,EAC5B,KAAK,EAAE,SAAS,GACd,IAAI,CAuDN"}
@@ -5,9 +5,9 @@ function shorten(value, max) {
5
5
  function durationText(durationMs) {
6
6
  return durationMs >= 1000 ? `${Math.round(durationMs / 1000)}s` : `${durationMs}ms`;
7
7
  }
8
- function attemptLabel(details) {
9
- return details.attempts
10
- ? details.attempts
8
+ function attemptLabel(attempts) {
9
+ return attempts
10
+ ? attempts
11
11
  .map((attempt) => `${attempt.entryId ? `${attempt.provider}/${attempt.entryId}` : attempt.provider}:${attempt.error ? "failed" : attempt.resultsCount}`)
12
12
  .join(" -> ")
13
13
  : "";
@@ -29,6 +29,15 @@ export function renderSearchResult(result, options, theme) {
29
29
  if (options.isPartial) {
30
30
  const details = result.details;
31
31
  if (isSearchProgressDetails(details)) {
32
+ if (details.currentProvider) {
33
+ const total = details.providerLabels.length;
34
+ const position = Math.min((details.attempts?.length ?? 0) + 1, Math.max(total, 1));
35
+ const step = total > 1 ? ` [${position}/${total}]` : "";
36
+ const line = theme.fg("warning", `Searching "${shorten(details.query, 80)}" via ${details.currentProvider}${step} (max ${details.maxResults})`);
37
+ const attempts = attemptLabel(details.attempts);
38
+ const rows = options.expanded && attempts ? [line, theme.fg("muted", `route ${attempts}`)] : [line];
39
+ return new Text(rows.join("\n"), 0, 0);
40
+ }
32
41
  const route = details.providerLabels.length > 0 ? details.providerLabels.join(" -> ") : "configured providers";
33
42
  return new Text(theme.fg("warning", `Searching "${shorten(details.query, 80)}" via ${route} (max ${details.maxResults})`), 0, 0);
34
43
  }
@@ -50,7 +59,7 @@ export function renderSearchResult(result, options, theme) {
50
59
  (details.truncated ? theme.fg("warning", " (truncated)") : "");
51
60
  if (count === 0)
52
61
  return new Text(summary, 0, 0);
53
- const attempts = attemptLabel(details);
62
+ const attempts = attemptLabel(details.attempts);
54
63
  const rows = options.expanded && attempts ? [summary, theme.fg("muted", `route ${attempts}`)] : [summary];
55
64
  const visibleLimit = options.expanded ? 8 : 3;
56
65
  for (const item of details.results.slice(0, visibleLimit)) {
@@ -1 +1 @@
1
- {"version":3,"file":"renderers.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\n\nimport type { SearchDetails, SearchErrorDetails, SearchProgressDetails, SearchRenderDetails } from \"./types.ts\";\n\ninterface ThemeLike {\n\tbold(value: string): string;\n\tfg(key: string, value: string): string;\n}\n\ninterface SearchArgs {\n\tquery: string;\n\tallowed_domains?: string[];\n\tblocked_domains?: string[];\n}\n\ninterface ResultLike<TDetails> {\n\tcontent: ReadonlyArray<{ type: string; text?: string }>;\n\tdetails?: TDetails;\n}\n\ninterface RenderResultOptions {\n\texpanded?: boolean;\n\tisPartial?: boolean;\n}\n\nfunction shorten(value: string, max: number): string {\n\treturn value.length <= max ? value : `${value.slice(0, max - 1)}…`;\n}\n\nfunction durationText(durationMs: number): string {\n\treturn durationMs >= 1000 ? `${Math.round(durationMs / 1000)}s` : `${durationMs}ms`;\n}\n\nfunction attemptLabel(details: SearchDetails): string {\n\treturn details.attempts\n\t\t? details.attempts\n\t\t\t\t.map(\n\t\t\t\t\t(attempt) =>\n\t\t\t\t\t\t`${attempt.entryId ? `${attempt.provider}/${attempt.entryId}` : attempt.provider}:${attempt.error ? \"failed\" : attempt.resultsCount}`,\n\t\t\t\t)\n\t\t\t\t.join(\" -> \")\n\t\t: \"\";\n}\n\nfunction isSearchProgressDetails(details: SearchRenderDetails | undefined): details is SearchProgressDetails {\n\treturn details !== undefined && \"phase\" in details && details.phase === \"searching\";\n}\n\nfunction isSearchErrorDetails(details: SearchRenderDetails): details is SearchErrorDetails {\n\treturn \"phase\" in details && details.phase === \"error\";\n}\n\nexport function renderSearchCall(args: SearchArgs, theme: ThemeLike): Text {\n\tconst head = theme.fg(\"toolTitle\", theme.bold(\"web_search \"));\n\tconst query = theme.fg(\"accent\", `\"${shorten(args.query, 90)}\"`);\n\tconst domains = args.allowed_domains ?? args.blocked_domains;\n\tconst filter = domains?.length ? theme.fg(\"muted\", ` domains:${domains.length}`) : \"\";\n\treturn new Text(head + query + filter, 0, 0);\n}\n\nexport function renderSearchResult(\n\tresult: ResultLike<SearchRenderDetails>,\n\toptions: RenderResultOptions,\n\ttheme: ThemeLike,\n): Text {\n\tif (options.isPartial) {\n\t\tconst details = result.details;\n\t\tif (isSearchProgressDetails(details)) {\n\t\t\tconst route = details.providerLabels.length > 0 ? details.providerLabels.join(\" -> \") : \"configured providers\";\n\t\t\treturn new Text(\n\t\t\t\ttheme.fg(\"warning\", `Searching \"${shorten(details.query, 80)}\" via ${route} (max ${details.maxResults})`),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t\treturn new Text(theme.fg(\"warning\", result.content[0]?.text ?? \"Searching the web...\"), 0, 0);\n\t}\n\n\tconst details = result.details;\n\tif (!details) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchProgressDetails(details)) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchErrorDetails(details)) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\tif (details.error) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\n\tconst count = details.results.length;\n\tconst provider = details.entryId ? `${details.provider}/${details.entryId}` : details.provider;\n\tconst summary =\n\t\ttheme.fg(\"success\", `${count} result${count === 1 ? \"\" : \"s\"}`) +\n\t\ttheme.fg(\n\t\t\t\"muted\",\n\t\t\t` via ${provider}${details.strategy ? ` (${details.strategy})` : \"\"} in ${durationText(details.durationMs)}`,\n\t\t) +\n\t\t(details.truncated ? theme.fg(\"warning\", \" (truncated)\") : \"\");\n\n\tif (count === 0) return new Text(summary, 0, 0);\n\n\tconst attempts = attemptLabel(details);\n\tconst rows = options.expanded && attempts ? [summary, theme.fg(\"muted\", `route ${attempts}`)] : [summary];\n\tconst visibleLimit = options.expanded ? 8 : 3;\n\tfor (const item of details.results.slice(0, visibleLimit)) {\n\t\trows.push(`${theme.fg(\"accent\", shorten(item.title, 80))} ${theme.fg(\"dim\", shorten(item.url, 100))}`);\n\t\tif (item.snippet) rows.push(theme.fg(\"muted\", ` ${shorten(item.snippet, 140)}`));\n\t}\n\tif (details.results.length > visibleLimit) {\n\t\trows.push(theme.fg(\"dim\", `… ${details.results.length - visibleLimit} more sources`));\n\t}\n\treturn new Text(rows.join(\"\\n\"), 0, 0);\n}\n"]}
1
+ {"version":3,"file":"renderers.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/renderers.ts"],"names":[],"mappings":"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","sourcesContent":["import { Text } from \"@earendil-works/pi-tui\";\n\nimport type { SearchDetails, SearchErrorDetails, SearchProgressDetails, SearchRenderDetails } from \"./types.ts\";\n\ninterface ThemeLike {\n\tbold(value: string): string;\n\tfg(key: string, value: string): string;\n}\n\ninterface SearchArgs {\n\tquery: string;\n\tallowed_domains?: string[];\n\tblocked_domains?: string[];\n}\n\ninterface ResultLike<TDetails> {\n\tcontent: ReadonlyArray<{ type: string; text?: string }>;\n\tdetails?: TDetails;\n}\n\ninterface RenderResultOptions {\n\texpanded?: boolean;\n\tisPartial?: boolean;\n}\n\nfunction shorten(value: string, max: number): string {\n\treturn value.length <= max ? value : `${value.slice(0, max - 1)}…`;\n}\n\nfunction durationText(durationMs: number): string {\n\treturn durationMs >= 1000 ? `${Math.round(durationMs / 1000)}s` : `${durationMs}ms`;\n}\n\nfunction attemptLabel(attempts: SearchDetails[\"attempts\"]): string {\n\treturn attempts\n\t\t? attempts\n\t\t\t\t.map(\n\t\t\t\t\t(attempt) =>\n\t\t\t\t\t\t`${attempt.entryId ? `${attempt.provider}/${attempt.entryId}` : attempt.provider}:${attempt.error ? \"failed\" : attempt.resultsCount}`,\n\t\t\t\t)\n\t\t\t\t.join(\" -> \")\n\t\t: \"\";\n}\n\nfunction isSearchProgressDetails(details: SearchRenderDetails | undefined): details is SearchProgressDetails {\n\treturn details !== undefined && \"phase\" in details && details.phase === \"searching\";\n}\n\nfunction isSearchErrorDetails(details: SearchRenderDetails): details is SearchErrorDetails {\n\treturn \"phase\" in details && details.phase === \"error\";\n}\n\nexport function renderSearchCall(args: SearchArgs, theme: ThemeLike): Text {\n\tconst head = theme.fg(\"toolTitle\", theme.bold(\"web_search \"));\n\tconst query = theme.fg(\"accent\", `\"${shorten(args.query, 90)}\"`);\n\tconst domains = args.allowed_domains ?? args.blocked_domains;\n\tconst filter = domains?.length ? theme.fg(\"muted\", ` domains:${domains.length}`) : \"\";\n\treturn new Text(head + query + filter, 0, 0);\n}\n\nexport function renderSearchResult(\n\tresult: ResultLike<SearchRenderDetails>,\n\toptions: RenderResultOptions,\n\ttheme: ThemeLike,\n): Text {\n\tif (options.isPartial) {\n\t\tconst details = result.details;\n\t\tif (isSearchProgressDetails(details)) {\n\t\t\tif (details.currentProvider) {\n\t\t\t\tconst total = details.providerLabels.length;\n\t\t\t\tconst position = Math.min((details.attempts?.length ?? 0) + 1, Math.max(total, 1));\n\t\t\t\tconst step = total > 1 ? ` [${position}/${total}]` : \"\";\n\t\t\t\tconst line = theme.fg(\n\t\t\t\t\t\"warning\",\n\t\t\t\t\t`Searching \"${shorten(details.query, 80)}\" via ${details.currentProvider}${step} (max ${details.maxResults})`,\n\t\t\t\t);\n\t\t\t\tconst attempts = attemptLabel(details.attempts);\n\t\t\t\tconst rows = options.expanded && attempts ? [line, theme.fg(\"muted\", `route ${attempts}`)] : [line];\n\t\t\t\treturn new Text(rows.join(\"\\n\"), 0, 0);\n\t\t\t}\n\t\t\tconst route = details.providerLabels.length > 0 ? details.providerLabels.join(\" -> \") : \"configured providers\";\n\t\t\treturn new Text(\n\t\t\t\ttheme.fg(\"warning\", `Searching \"${shorten(details.query, 80)}\" via ${route} (max ${details.maxResults})`),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t\treturn new Text(theme.fg(\"warning\", result.content[0]?.text ?? \"Searching the web...\"), 0, 0);\n\t}\n\n\tconst details = result.details;\n\tif (!details) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchProgressDetails(details)) return new Text(theme.fg(\"muted\", result.content[0]?.text ?? \"\"), 0, 0);\n\tif (isSearchErrorDetails(details)) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\tif (details.error) return new Text(theme.fg(\"error\", details.error), 0, 0);\n\n\tconst count = details.results.length;\n\tconst provider = details.entryId ? `${details.provider}/${details.entryId}` : details.provider;\n\tconst summary =\n\t\ttheme.fg(\"success\", `${count} result${count === 1 ? \"\" : \"s\"}`) +\n\t\ttheme.fg(\n\t\t\t\"muted\",\n\t\t\t` via ${provider}${details.strategy ? ` (${details.strategy})` : \"\"} in ${durationText(details.durationMs)}`,\n\t\t) +\n\t\t(details.truncated ? theme.fg(\"warning\", \" (truncated)\") : \"\");\n\n\tif (count === 0) return new Text(summary, 0, 0);\n\n\tconst attempts = attemptLabel(details.attempts);\n\tconst rows = options.expanded && attempts ? [summary, theme.fg(\"muted\", `route ${attempts}`)] : [summary];\n\tconst visibleLimit = options.expanded ? 8 : 3;\n\tfor (const item of details.results.slice(0, visibleLimit)) {\n\t\trows.push(`${theme.fg(\"accent\", shorten(item.title, 80))} ${theme.fg(\"dim\", shorten(item.url, 100))}`);\n\t\tif (item.snippet) rows.push(theme.fg(\"muted\", ` ${shorten(item.snippet, 140)}`));\n\t}\n\tif (details.results.length > visibleLimit) {\n\t\trows.push(theme.fg(\"dim\", `… ${details.results.length - visibleLimit} more sources`));\n\t}\n\treturn new Text(rows.join(\"\\n\"), 0, 0);\n}\n"]}
@@ -1,9 +1,10 @@
1
- import type { SearchDetails, SearchRequest, WebsearchConfig } from "./types.ts";
1
+ import type { SearchAttempt, SearchDetails, SearchRequest, WebsearchConfig } from "./types.ts";
2
2
  export interface SearchRoutingState {
3
3
  roundRobinCursor: number;
4
4
  successCounts: number[];
5
5
  }
6
6
  export declare function createSearchRoutingState(providerCount: number): SearchRoutingState;
7
- export declare function performSearch(config: WebsearchConfig, request: SearchRequest, signal?: AbortSignal, routingState?: SearchRoutingState): Promise<SearchDetails>;
7
+ export type SearchAttemptListener = (providerLabel: string, attempts: readonly SearchAttempt[]) => void;
8
+ export declare function performSearch(config: WebsearchConfig, request: SearchRequest, signal?: AbortSignal, routingState?: SearchRoutingState, onAttempt?: SearchAttemptListener): Promise<SearchDetails>;
8
9
  export declare function formatSearchText(details: SearchDetails): string;
9
10
  //# sourceMappingURL=search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIX,aAAa,EAEb,aAAa,EACb,eAAe,EACf,MAAM,YAAY,CAAC;AAyEpB,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAElF;AA6JD,wBAAsB,aAAa,CAClC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,aAAa,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,YAAY,CAAC,EAAE,kBAAkB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAgExB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA0B/D"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGX,aAAa,EACb,aAAa,EAEb,aAAa,EACb,eAAe,EACf,MAAM,YAAY,CAAC;AAyEpB,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAElF;AA6JD,MAAM,MAAM,qBAAqB,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,aAAa,EAAE,KAAK,IAAI,CAAC;AAExG,wBAAsB,aAAa,CAClC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,aAAa,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,YAAY,CAAC,EAAE,kBAAkB,EACjC,SAAS,CAAC,EAAE,qBAAqB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAiExB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA0B/D"}
@@ -225,7 +225,7 @@ function attemptFromDetails(details) {
225
225
  attempt.error = details.error;
226
226
  return attempt;
227
227
  }
228
- export async function performSearch(config, request, signal, routingState) {
228
+ export async function performSearch(config, request, signal, routingState, onAttempt) {
229
229
  const startedAt = Date.now();
230
230
  const state = routingState ?? createSearchRoutingState(config.providers.length);
231
231
  const order = selectOrder(config.strategy, config.providers, state);
@@ -236,6 +236,7 @@ export async function performSearch(config, request, signal, routingState) {
236
236
  const provider = config.providers[index];
237
237
  if (!provider)
238
238
  continue;
239
+ onAttempt?.(entryLabel(provider), attempts);
239
240
  const details = await performProviderSearch(provider, request, signal);
240
241
  attempts.push(attemptFromDetails(details));
241
242
  if (details.error) {