@code-yeongyu/senpi 2026.7.17 → 2026.7.20

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 (641) hide show
  1. package/CHANGELOG.md +82 -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 +5 -0
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +27 -5
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/compaction/compaction.d.ts.map +1 -1
  14. package/dist/core/compaction/compaction.js +20 -4
  15. package/dist/core/compaction/compaction.js.map +1 -1
  16. package/dist/core/dynamic-prompt/build.d.ts +7 -0
  17. package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
  18. package/dist/core/dynamic-prompt/build.js +5 -0
  19. package/dist/core/dynamic-prompt/build.js.map +1 -1
  20. package/dist/core/dynamic-prompt/workstation.d.ts +35 -0
  21. package/dist/core/dynamic-prompt/workstation.d.ts.map +1 -0
  22. package/dist/core/dynamic-prompt/workstation.js +81 -0
  23. package/dist/core/dynamic-prompt/workstation.js.map +1 -0
  24. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  25. package/dist/core/extensions/builtin/compaction/index.js +46 -4
  26. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  27. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts +1 -0
  28. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts.map +1 -1
  29. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js +20 -2
  30. package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js.map +1 -1
  31. package/dist/core/extensions/builtin/compaction/speculative.d.ts +7 -1
  32. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/compaction/speculative.js +29 -11
  34. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  35. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +9 -7
  36. package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
  37. package/dist/core/extensions/builtin/compaction/todo-bridge.js +34 -9
  38. package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
  39. package/dist/core/extensions/builtin/gpt-apply-patch/constants.d.ts +1 -0
  40. package/dist/core/extensions/builtin/gpt-apply-patch/constants.d.ts.map +1 -1
  41. package/dist/core/extensions/builtin/gpt-apply-patch/constants.js +5 -1
  42. package/dist/core/extensions/builtin/gpt-apply-patch/constants.js.map +1 -1
  43. package/dist/core/extensions/builtin/gpt-apply-patch/extension.d.ts +2 -1
  44. package/dist/core/extensions/builtin/gpt-apply-patch/extension.d.ts.map +1 -1
  45. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js +48 -29
  46. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js.map +1 -1
  47. package/dist/core/extensions/builtin/gpt-apply-patch/index.d.ts +2 -2
  48. package/dist/core/extensions/builtin/gpt-apply-patch/index.d.ts.map +1 -1
  49. package/dist/core/extensions/builtin/gpt-apply-patch/index.js +2 -2
  50. package/dist/core/extensions/builtin/gpt-apply-patch/index.js.map +1 -1
  51. package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts +1 -1
  52. package/dist/core/extensions/builtin/gpt-apply-patch/tool.d.ts.map +1 -1
  53. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js +5 -3
  54. package/dist/core/extensions/builtin/gpt-apply-patch/tool.js.map +1 -1
  55. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts +7 -6
  56. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/gpt-apply-patch/types.js.map +1 -1
  58. package/dist/core/extensions/builtin/hooks/matcher.d.ts.map +1 -1
  59. package/dist/core/extensions/builtin/hooks/matcher.js +1 -0
  60. package/dist/core/extensions/builtin/hooks/matcher.js.map +1 -1
  61. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  62. package/dist/core/extensions/builtin/index.js +2 -0
  63. package/dist/core/extensions/builtin/index.js.map +1 -1
  64. package/dist/core/extensions/builtin/mcp/config-schema.d.ts +8 -1
  65. package/dist/core/extensions/builtin/mcp/config-schema.d.ts.map +1 -1
  66. package/dist/core/extensions/builtin/mcp/config-schema.js +23 -0
  67. package/dist/core/extensions/builtin/mcp/config-schema.js.map +1 -1
  68. package/dist/core/extensions/builtin/mcp/config.d.ts +13 -0
  69. package/dist/core/extensions/builtin/mcp/config.d.ts.map +1 -1
  70. package/dist/core/extensions/builtin/mcp/config.js +36 -0
  71. package/dist/core/extensions/builtin/mcp/config.js.map +1 -1
  72. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts +1 -1
  73. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts.map +1 -1
  74. package/dist/core/extensions/builtin/mcp/expose/native-search.js +1 -1
  75. package/dist/core/extensions/builtin/mcp/expose/native-search.js.map +1 -1
  76. package/dist/core/extensions/builtin/mcp/expose/policy.js +1 -1
  77. package/dist/core/extensions/builtin/mcp/expose/policy.js.map +1 -1
  78. package/dist/core/extensions/builtin/mcp/expose/status.js +1 -1
  79. package/dist/core/extensions/builtin/mcp/expose/status.js.map +1 -1
  80. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts +3 -3
  81. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts.map +1 -1
  82. package/dist/core/extensions/builtin/mcp/expose/tier-b.js +10 -10
  83. package/dist/core/extensions/builtin/mcp/expose/tier-b.js.map +1 -1
  84. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts +3 -3
  85. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts.map +1 -1
  86. package/dist/core/extensions/builtin/mcp/expose/tool-search.js +14 -14
  87. package/dist/core/extensions/builtin/mcp/expose/tool-search.js.map +1 -1
  88. package/dist/core/extensions/builtin/mcp/index.js +5 -5
  89. package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
  90. package/dist/core/extensions/builtin/mcp/service-snapshot.d.ts.map +1 -1
  91. package/dist/core/extensions/builtin/mcp/service-snapshot.js +1 -0
  92. package/dist/core/extensions/builtin/mcp/service-snapshot.js.map +1 -1
  93. package/dist/core/extensions/builtin/mcp/service-types.d.ts +12 -0
  94. package/dist/core/extensions/builtin/mcp/service-types.d.ts.map +1 -1
  95. package/dist/core/extensions/builtin/mcp/service-types.js.map +1 -1
  96. package/dist/core/extensions/builtin/mcp/service.d.ts +2 -2
  97. package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
  98. package/dist/core/extensions/builtin/mcp/service.js +4 -3
  99. package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
  100. package/dist/core/extensions/builtin/mcp/status.js +1 -0
  101. package/dist/core/extensions/builtin/mcp/status.js.map +1 -1
  102. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
  103. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +5 -1
  104. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  105. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.d.ts.map +1 -1
  106. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js +5 -1
  107. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js.map +1 -1
  108. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.d.ts.map +1 -1
  109. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js +5 -1
  110. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js.map +1 -1
  111. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.d.ts.map +1 -1
  112. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js +5 -1
  113. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js.map +1 -1
  114. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.d.ts.map +1 -1
  115. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js +5 -1
  116. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js.map +1 -1
  117. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js +2 -2
  118. package/dist/core/extensions/builtin/prompt-preset/glm-5-2.js.map +1 -1
  119. package/dist/core/extensions/builtin/prompt-preset/gpt-5.2.js +1 -1
  120. package/dist/core/extensions/builtin/prompt-preset/gpt-5.2.js.map +1 -1
  121. package/dist/core/extensions/builtin/prompt-preset/gpt-5.3-codex.js +1 -1
  122. package/dist/core/extensions/builtin/prompt-preset/gpt-5.3-codex.js.map +1 -1
  123. package/dist/core/extensions/builtin/prompt-preset/gpt-5.4.js +1 -1
  124. package/dist/core/extensions/builtin/prompt-preset/gpt-5.4.js.map +1 -1
  125. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +3 -3
  126. package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
  127. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +3 -3
  128. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  129. package/dist/core/extensions/builtin/prompt-preset/gpt-5.js +1 -1
  130. package/dist/core/extensions/builtin/prompt-preset/gpt-5.js.map +1 -1
  131. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts +3 -0
  132. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.d.ts.map +1 -0
  133. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +80 -0
  134. package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js.map +1 -0
  135. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js +1 -1
  136. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js.map +1 -1
  137. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js +1 -1
  138. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js.map +1 -1
  139. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
  140. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +5 -7
  141. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  142. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/prompt-preset/presets.js +14 -0
  144. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  145. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  146. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  147. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  148. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  149. package/dist/core/extensions/builtin/terminal/shared.d.ts +7 -0
  150. package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
  151. package/dist/core/extensions/builtin/terminal/shared.js +7 -0
  152. package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
  153. package/dist/core/extensions/builtin/terminal/tools/bash.d.ts.map +1 -1
  154. package/dist/core/extensions/builtin/terminal/tools/bash.js +68 -6
  155. package/dist/core/extensions/builtin/terminal/tools/bash.js.map +1 -1
  156. package/dist/core/extensions/builtin/todotools/commands.d.ts +18 -0
  157. package/dist/core/extensions/builtin/todotools/commands.d.ts.map +1 -0
  158. package/dist/core/extensions/builtin/todotools/commands.js +395 -0
  159. package/dist/core/extensions/builtin/todotools/commands.js.map +1 -0
  160. package/dist/core/extensions/builtin/todotools/index.d.ts +4 -1
  161. package/dist/core/extensions/builtin/todotools/index.d.ts.map +1 -1
  162. package/dist/core/extensions/builtin/todotools/index.js +17 -14
  163. package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
  164. package/dist/core/extensions/builtin/todotools/markdown.d.ts +13 -0
  165. package/dist/core/extensions/builtin/todotools/markdown.d.ts.map +1 -0
  166. package/dist/core/extensions/builtin/todotools/markdown.js +82 -0
  167. package/dist/core/extensions/builtin/todotools/markdown.js.map +1 -0
  168. package/dist/core/extensions/builtin/todotools/prompt.d.ts +2 -1
  169. package/dist/core/extensions/builtin/todotools/prompt.d.ts.map +1 -1
  170. package/dist/core/extensions/builtin/todotools/prompt.js +50 -153
  171. package/dist/core/extensions/builtin/todotools/prompt.js.map +1 -1
  172. package/dist/core/extensions/builtin/todotools/state.d.ts +67 -14
  173. package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
  174. package/dist/core/extensions/builtin/todotools/state.js +400 -35
  175. package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
  176. package/dist/core/extensions/builtin/todotools/tools/todo.d.ts +22 -0
  177. package/dist/core/extensions/builtin/todotools/tools/todo.d.ts.map +1 -0
  178. package/dist/core/extensions/builtin/todotools/tools/todo.js +229 -0
  179. package/dist/core/extensions/builtin/todotools/tools/todo.js.map +1 -0
  180. package/dist/core/extensions/builtin/video-in/index.d.ts +3 -0
  181. package/dist/core/extensions/builtin/video-in/index.d.ts.map +1 -0
  182. package/dist/core/extensions/builtin/video-in/index.js +111 -0
  183. package/dist/core/extensions/builtin/video-in/index.js.map +1 -0
  184. package/dist/core/extensions/builtin/websearch/index.d.ts.map +1 -1
  185. package/dist/core/extensions/builtin/websearch/index.js +20 -3
  186. package/dist/core/extensions/builtin/websearch/index.js.map +1 -1
  187. package/dist/core/extensions/index.d.ts +1 -0
  188. package/dist/core/extensions/index.d.ts.map +1 -1
  189. package/dist/core/extensions/index.js.map +1 -1
  190. package/dist/core/extensions/loader.d.ts +10 -1
  191. package/dist/core/extensions/loader.d.ts.map +1 -1
  192. package/dist/core/extensions/loader.js +64 -7
  193. package/dist/core/extensions/loader.js.map +1 -1
  194. package/dist/core/extensions/runner.d.ts +5 -2
  195. package/dist/core/extensions/runner.d.ts.map +1 -1
  196. package/dist/core/extensions/runner.js +49 -8
  197. package/dist/core/extensions/runner.js.map +1 -1
  198. package/dist/core/extensions/types.d.ts +49 -8
  199. package/dist/core/extensions/types.d.ts.map +1 -1
  200. package/dist/core/extensions/types.js.map +1 -1
  201. package/dist/core/model-registry.d.ts +5 -1
  202. package/dist/core/model-registry.d.ts.map +1 -1
  203. package/dist/core/model-registry.js +17 -2
  204. package/dist/core/model-registry.js.map +1 -1
  205. package/dist/core/model-runtime.d.ts +12 -1
  206. package/dist/core/model-runtime.d.ts.map +1 -1
  207. package/dist/core/model-runtime.js +51 -9
  208. package/dist/core/model-runtime.js.map +1 -1
  209. package/dist/core/prompt-templates.d.ts +1 -0
  210. package/dist/core/prompt-templates.d.ts.map +1 -1
  211. package/dist/core/prompt-templates.js +4 -4
  212. package/dist/core/prompt-templates.js.map +1 -1
  213. package/dist/core/provider-composer.d.ts +1 -1
  214. package/dist/core/provider-composer.d.ts.map +1 -1
  215. package/dist/core/provider-composer.js +8 -1
  216. package/dist/core/provider-composer.js.map +1 -1
  217. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  218. package/dist/core/remote-catalog-provider.js +16 -3
  219. package/dist/core/remote-catalog-provider.js.map +1 -1
  220. package/dist/core/resource-loader.d.ts +6 -0
  221. package/dist/core/resource-loader.d.ts.map +1 -1
  222. package/dist/core/resource-loader.js +27 -2
  223. package/dist/core/resource-loader.js.map +1 -1
  224. package/dist/core/settings-manager.d.ts +6 -0
  225. package/dist/core/settings-manager.d.ts.map +1 -1
  226. package/dist/core/settings-manager.js +20 -0
  227. package/dist/core/settings-manager.js.map +1 -1
  228. package/dist/core/tools/bash.d.ts.map +1 -1
  229. package/dist/core/tools/bash.js +20 -5
  230. package/dist/core/tools/bash.js.map +1 -1
  231. package/dist/core/tools/read.js +1 -1
  232. package/dist/core/tools/read.js.map +1 -1
  233. package/dist/extensions/index.d.ts +3 -0
  234. package/dist/extensions/index.d.ts.map +1 -0
  235. package/dist/extensions/index.js +3 -0
  236. package/dist/extensions/index.js.map +1 -0
  237. package/dist/extensions/llama/client.d.ts +61 -0
  238. package/dist/extensions/llama/client.d.ts.map +1 -0
  239. package/dist/extensions/llama/client.js +298 -0
  240. package/dist/extensions/llama/client.js.map +1 -0
  241. package/dist/extensions/llama/huggingface.d.ts +23 -0
  242. package/dist/extensions/llama/huggingface.d.ts.map +1 -0
  243. package/dist/extensions/llama/huggingface.js +139 -0
  244. package/dist/extensions/llama/huggingface.js.map +1 -0
  245. package/dist/extensions/llama/index.d.ts +3 -0
  246. package/dist/extensions/llama/index.d.ts.map +1 -0
  247. package/dist/extensions/llama/index.js +208 -0
  248. package/dist/extensions/llama/index.js.map +1 -0
  249. package/dist/extensions/llama/provider.d.ts +10 -0
  250. package/dist/extensions/llama/provider.d.ts.map +1 -0
  251. package/dist/extensions/llama/provider.js +106 -0
  252. package/dist/extensions/llama/provider.js.map +1 -0
  253. package/dist/extensions/llama/ui.d.ts +42 -0
  254. package/dist/extensions/llama/ui.d.ts.map +1 -0
  255. package/dist/extensions/llama/ui.js +400 -0
  256. package/dist/extensions/llama/ui.js.map +1 -0
  257. package/dist/index.d.ts +2 -2
  258. package/dist/index.d.ts.map +1 -1
  259. package/dist/index.js.map +1 -1
  260. package/dist/main.d.ts.map +1 -1
  261. package/dist/main.js +6 -4
  262. package/dist/main.js.map +1 -1
  263. package/dist/modes/interactive/components/assistant-message.d.ts +6 -7
  264. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  265. package/dist/modes/interactive/components/assistant-message.js +154 -114
  266. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  267. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  268. package/dist/modes/interactive/components/footer.js +4 -2
  269. package/dist/modes/interactive/components/footer.js.map +1 -1
  270. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  271. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/settings-selector.js +20 -0
  273. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  274. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  275. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  276. package/dist/modes/interactive/interactive-mode.js +87 -10
  277. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  278. package/dist/modes/interactive/streaming-reveal.d.ts +35 -0
  279. package/dist/modes/interactive/streaming-reveal.d.ts.map +1 -0
  280. package/dist/modes/interactive/streaming-reveal.js +268 -0
  281. package/dist/modes/interactive/streaming-reveal.js.map +1 -0
  282. package/dist/modes/interactive/tool-args-reveal.d.ts +20 -0
  283. package/dist/modes/interactive/tool-args-reveal.d.ts.map +1 -0
  284. package/dist/modes/interactive/tool-args-reveal.js +153 -0
  285. package/dist/modes/interactive/tool-args-reveal.js.map +1 -0
  286. package/dist/utils/child-process.d.ts +17 -1
  287. package/dist/utils/child-process.d.ts.map +1 -1
  288. package/dist/utils/child-process.js +41 -1
  289. package/dist/utils/child-process.js.map +1 -1
  290. package/docs/AGENTS.md +70 -0
  291. package/docs/custom-provider.md +28 -0
  292. package/docs/extensions.md +83 -5
  293. package/docs/index.md +1 -0
  294. package/docs/llama-cpp.md +99 -0
  295. package/docs/mcp.md +21 -5
  296. package/docs/neo.md +2 -1
  297. package/docs/prompt-templates.md +1 -0
  298. package/docs/providers.md +7 -0
  299. package/docs/tui.md +41 -26
  300. package/docs/usage.md +1 -0
  301. package/examples/AGENTS.md +3 -0
  302. package/examples/extensions/README.md +1 -1
  303. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +62 -0
  304. package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
  305. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +59 -19
  306. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +0 -1
  307. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +69 -2
  308. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +6 -0
  309. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  310. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +19 -4
  311. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  312. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.d.ts +3 -1
  313. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.d.ts.map +1 -1
  314. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.js +4 -2
  315. package/node_modules/@earendil-works/pi-agent-core/dist/proxy.js.map +1 -1
  316. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  317. package/node_modules/@earendil-works/pi-ai/README.md +1 -1
  318. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  319. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +24 -4
  320. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  321. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts +2 -1
  322. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  323. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +25 -1
  324. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  325. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts.map +1 -1
  326. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +43 -9
  327. package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
  328. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts +1 -0
  329. package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
  330. package/node_modules/@earendil-works/pi-ai/dist/compat.js +1 -0
  331. package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
  332. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +15 -0
  333. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  334. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +15 -0
  335. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  336. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +4267 -22314
  337. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  338. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts +436 -1988
  339. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
  340. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js +2 -1892
  341. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js.map +1 -1
  342. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.d.ts +10 -80
  343. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.d.ts.map +1 -1
  344. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.js +2 -57
  345. package/node_modules/@earendil-works/pi-ai/dist/providers/ant-ling.models.js.map +1 -1
  346. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts +43 -267
  347. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts.map +1 -1
  348. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js +2 -252
  349. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js.map +1 -1
  350. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.d.ts +184 -883
  351. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.d.ts.map +1 -1
  352. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.js +2 -811
  353. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.models.js.map +1 -1
  354. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts +10 -60
  355. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts.map +1 -1
  356. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js +2 -56
  357. package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js.map +1 -1
  358. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts +168 -884
  359. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
  360. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js +2 -755
  361. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
  362. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.d.ts +40 -286
  363. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -1
  364. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.js +2 -236
  365. package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-workers-ai.models.js.map +1 -1
  366. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -0
  367. package/node_modules/@earendil-works/pi-ai/dist/providers/data/ant-ling.json +1 -0
  368. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -0
  369. package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -0
  370. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cerebras.json +1 -0
  371. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -0
  372. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -0
  373. package/node_modules/@earendil-works/pi-ai/dist/providers/data/deepseek.json +1 -0
  374. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -0
  375. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -0
  376. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google-vertex.json +1 -0
  377. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -0
  378. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -0
  379. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -0
  380. package/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -0
  381. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax-cn.json +1 -0
  382. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax.json +1 -0
  383. package/node_modules/@earendil-works/pi-ai/dist/providers/data/mistral.json +1 -0
  384. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai-cn.json +1 -0
  385. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai.json +1 -0
  386. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -0
  387. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -0
  388. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -0
  389. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -0
  390. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -0
  391. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -0
  392. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -0
  393. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -0
  394. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xai.json +1 -0
  395. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-ams.json +1 -0
  396. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-cn.json +1 -0
  397. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi-token-plan-sgp.json +1 -0
  398. package/node_modules/@earendil-works/pi-ai/dist/providers/data/xiaomi.json +1 -0
  399. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -0
  400. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.json +1 -0
  401. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.d.ts +7 -58
  402. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.d.ts.map +1 -1
  403. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.js +2 -40
  404. package/node_modules/@earendil-works/pi-ai/dist/providers/deepseek.models.js.map +1 -1
  405. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts +49 -362
  406. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts.map +1 -1
  407. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js +2 -292
  408. package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js.map +1 -1
  409. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts +85 -760
  410. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts.map +1 -1
  411. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js +2 -538
  412. package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js.map +1 -1
  413. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts +31 -189
  414. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.d.ts.map +1 -1
  415. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.js +2 -179
  416. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.models.js.map +1 -1
  417. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts +49 -309
  418. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts.map +1 -1
  419. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.js +2 -285
  420. package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.js.map +1 -1
  421. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.d.ts +22 -118
  422. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.d.ts.map +1 -1
  423. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js +2 -122
  424. package/node_modules/@earendil-works/pi-ai/dist/providers/groq.models.js.map +1 -1
  425. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts +196 -979
  426. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.d.ts.map +1 -1
  427. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.js +2 -884
  428. package/node_modules/@earendil-works/pi-ai/dist/providers/huggingface.models.js.map +1 -1
  429. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts +16 -121
  430. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts.map +1 -1
  431. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js +2 -98
  432. package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js.map +1 -1
  433. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.d.ts +10 -48
  434. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.d.ts.map +1 -1
  435. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.js +2 -53
  436. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax-cn.models.js.map +1 -1
  437. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.d.ts +10 -48
  438. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.d.ts.map +1 -1
  439. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.js +2 -53
  440. package/node_modules/@earendil-works/pi-ai/dist/providers/minimax.models.js.map +1 -1
  441. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts +91 -480
  442. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.d.ts.map +1 -1
  443. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js +2 -512
  444. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.models.js.map +1 -1
  445. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts +31 -257
  446. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
  447. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js +2 -185
  448. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai-cn.models.js.map +1 -1
  449. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts +31 -257
  450. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.d.ts.map +1 -1
  451. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js +2 -185
  452. package/node_modules/@earendil-works/pi-ai/dist/providers/moonshotai.models.js.map +1 -1
  453. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts +58 -541
  454. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts.map +1 -1
  455. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js +2 -382
  456. package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js.map +1 -1
  457. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.d.ts +22 -196
  458. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.d.ts.map +1 -1
  459. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.js +2 -139
  460. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex.models.js.map +1 -1
  461. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.d.ts +184 -954
  462. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.d.ts.map +1 -1
  463. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.js +2 -825
  464. package/node_modules/@earendil-works/pi-ai/dist/providers/openai.models.js.map +1 -1
  465. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.d.ts +1 -1
  466. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.d.ts.map +1 -1
  467. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js +2 -0
  468. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js.map +1 -1
  469. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts +46 -335
  470. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.d.ts.map +1 -1
  471. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js +2 -273
  472. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js.map +1 -1
  473. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts +163 -1185
  474. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts.map +1 -1
  475. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js +2 -996
  476. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js.map +1 -1
  477. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +1076 -5750
  478. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
  479. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +2 -4910
  480. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
  481. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.d.ts +49 -579
  482. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.d.ts.map +1 -1
  483. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js +2 -377
  484. package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js.map +1 -1
  485. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +752 -3336
  486. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
  487. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +2 -3263
  488. package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  489. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts +10 -65
  490. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.d.ts.map +1 -1
  491. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js +2 -57
  492. package/node_modules/@earendil-works/pi-ai/dist/providers/xai.models.js.map +1 -1
  493. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.d.ts +10 -63
  494. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
  495. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js +2 -56
  496. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
  497. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.d.ts +10 -63
  498. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
  499. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js +2 -56
  500. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
  501. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.d.ts +10 -63
  502. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
  503. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js +2 -56
  504. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
  505. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.d.ts +19 -126
  506. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.d.ts.map +1 -1
  507. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js +2 -110
  508. package/node_modules/@earendil-works/pi-ai/dist/providers/xiaomi.models.js.map +1 -1
  509. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.d.ts +19 -144
  510. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.d.ts.map +1 -1
  511. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.js +2 -111
  512. package/node_modules/@earendil-works/pi-ai/dist/providers/zai-coding-cn.models.js.map +1 -1
  513. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.d.ts +19 -144
  514. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.d.ts.map +1 -1
  515. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.js +2 -111
  516. package/node_modules/@earendil-works/pi-ai/dist/providers/zai.models.js.map +1 -1
  517. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.d.ts.map +1 -1
  518. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js +12 -0
  519. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/context-transformer.js.map +1 -1
  520. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts +1 -1
  521. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
  522. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +4 -2
  523. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
  524. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts +1 -0
  525. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts.map +1 -1
  526. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js +1 -1
  527. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js.map +1 -1
  528. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts +1 -0
  529. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts.map +1 -1
  530. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js +1 -1
  531. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/format.js.map +1 -1
  532. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts +19 -0
  533. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts.map +1 -0
  534. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js +8 -0
  535. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js.map +1 -0
  536. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts +11 -0
  537. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts.map +1 -1
  538. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js +40 -1
  539. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js.map +1 -1
  540. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts +2 -0
  541. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts.map +1 -1
  542. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js +7 -4
  543. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/parse.js.map +1 -1
  544. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts +2 -0
  545. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts.map +1 -1
  546. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js +104 -15
  547. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js.map +1 -1
  548. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts +15 -0
  549. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts.map +1 -0
  550. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.js +198 -0
  551. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/coerce-parameters.js.map +1 -0
  552. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.d.ts +3 -0
  553. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.d.ts.map +1 -0
  554. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.js +8 -0
  555. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/config.js.map +1 -0
  556. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.d.ts +6 -0
  557. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.d.ts.map +1 -0
  558. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.js +33 -0
  559. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/format.js.map +1 -0
  560. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts +6 -0
  561. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts.map +1 -0
  562. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js +6 -0
  563. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js.map +1 -0
  564. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.d.ts +4 -0
  565. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.d.ts.map +1 -0
  566. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.js +6 -0
  567. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/parse.js.map +1 -0
  568. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.d.ts +12 -0
  569. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.d.ts.map +1 -0
  570. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.js +46 -0
  571. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/repair.js.map +1 -0
  572. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.d.ts +4 -0
  573. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.d.ts.map +1 -0
  574. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.js +6 -0
  575. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/stream.js.map +1 -0
  576. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.d.ts +8 -1
  577. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.d.ts.map +1 -1
  578. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.js +129 -27
  579. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/gemma4.js.map +1 -1
  580. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/json-mix.d.ts.map +1 -1
  581. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/json-mix.js +140 -6
  582. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/json-mix.js.map +1 -1
  583. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/morph-xml.d.ts.map +1 -1
  584. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/morph-xml.js +28 -6
  585. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/morph-xml.js.map +1 -1
  586. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/yaml-xml.d.ts.map +1 -1
  587. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/yaml-xml.js +51 -18
  588. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/yaml-xml.js.map +1 -1
  589. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.d.ts.map +1 -1
  590. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.js +70 -9
  591. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.js.map +1 -1
  592. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts +6 -2
  593. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.d.ts.map +1 -1
  594. package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/types.js.map +1 -1
  595. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +16 -3
  596. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  597. package/node_modules/@earendil-works/pi-ai/dist/types.js +4 -1
  598. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  599. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  600. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +1 -0
  601. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  602. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-pair-repair.d.ts.map +1 -1
  603. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-pair-repair.js +19 -2
  604. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-pair-repair.js.map +1 -1
  605. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.d.ts +19 -0
  606. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.d.ts.map +1 -0
  607. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.js +215 -0
  608. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.js.map +1 -0
  609. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  610. package/node_modules/@earendil-works/pi-pty/dist/registry-session.d.ts +1 -1
  611. package/node_modules/@earendil-works/pi-pty/dist/registry-session.d.ts.map +1 -1
  612. package/node_modules/@earendil-works/pi-pty/dist/registry-session.js +25 -6
  613. package/node_modules/@earendil-works/pi-pty/dist/registry-session.js.map +1 -1
  614. package/node_modules/@earendil-works/pi-pty/dist/registry-types.d.ts +6 -0
  615. package/node_modules/@earendil-works/pi-pty/dist/registry-types.d.ts.map +1 -1
  616. package/node_modules/@earendil-works/pi-pty/dist/registry-types.js.map +1 -1
  617. package/node_modules/@earendil-works/pi-pty/dist/registry.d.ts +1 -0
  618. package/node_modules/@earendil-works/pi-pty/dist/registry.d.ts.map +1 -1
  619. package/node_modules/@earendil-works/pi-pty/dist/registry.js +9 -1
  620. package/node_modules/@earendil-works/pi-pty/dist/registry.js.map +1 -1
  621. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  622. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
  623. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  624. package/node_modules/@earendil-works/pi-tui/dist/index.js +1 -1
  625. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  626. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +6 -1
  627. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
  628. package/node_modules/@earendil-works/pi-tui/dist/tui.js +14 -2
  629. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  630. package/node_modules/@earendil-works/pi-tui/dist/utils.js +1 -1
  631. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
  632. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  633. package/package.json +6 -6
  634. package/dist/core/extensions/builtin/todotools/tools/todoread.d.ts +0 -4
  635. package/dist/core/extensions/builtin/todotools/tools/todoread.d.ts.map +0 -1
  636. package/dist/core/extensions/builtin/todotools/tools/todoread.js +0 -37
  637. package/dist/core/extensions/builtin/todotools/tools/todoread.js.map +0 -1
  638. package/dist/core/extensions/builtin/todotools/tools/todowrite.d.ts +0 -10
  639. package/dist/core/extensions/builtin/todotools/tools/todowrite.d.ts.map +0 -1
  640. package/dist/core/extensions/builtin/todotools/tools/todowrite.js +0 -95
  641. package/dist/core/extensions/builtin/todotools/tools/todowrite.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { Type } from "typebox";
2
- import { BACKGROUND_START_GRACE_MS, DEFAULT_COLS, DEFAULT_ROWS, TERMINAL_BASH_TOOL } from "../shared.js";
2
+ import { BACKGROUND_START_GRACE_MS, DEFAULT_COLS, DEFAULT_ROWS, KILLED_SESSION_EXIT_GRACE_MS, TERMINAL_BASH_TOOL, } from "../shared.js";
3
3
  import { errorResult, textResult } from "./context.js";
4
4
  import { describeExit, spawnCommandSession } from "./spawn.js";
5
5
  export const ptyBashSchema = Type.Object({
@@ -22,28 +22,90 @@ function resolveDimension(value, fallback) {
22
22
  function delay(ms) {
23
23
  return new Promise((resolve) => setTimeout(resolve, ms));
24
24
  }
25
+ const MAX_TIMEOUT_MS = 2_147_483_647;
26
+ /**
27
+ * Wait for the session's exit to settle, but stop waiting a bounded grace after
28
+ * the session has been killed. The native wait joins the PTY reader thread,
29
+ * which blocks while any surviving descendant holds the PTY open — without the
30
+ * grace, an aborted or timed-out command can pin the agent forever.
31
+ */
32
+ function raceExitWithKillGrace(runtime, signal, timeoutMs) {
33
+ return new Promise((resolve, reject) => {
34
+ let settled = false;
35
+ let abortGraceTimer;
36
+ let timeoutGraceTimer;
37
+ let armAbortGrace;
38
+ const settle = (finish) => {
39
+ if (settled)
40
+ return;
41
+ settled = true;
42
+ if (abortGraceTimer)
43
+ clearTimeout(abortGraceTimer);
44
+ if (timeoutGraceTimer)
45
+ clearTimeout(timeoutGraceTimer);
46
+ if (signal && armAbortGrace)
47
+ signal.removeEventListener("abort", armAbortGrace);
48
+ finish();
49
+ };
50
+ runtime.session.waitExit().then(() => settle(() => resolve("exited")), (error) => settle(() => reject(error instanceof Error ? error : new Error(String(error)))));
51
+ if (timeoutMs !== undefined) {
52
+ const timeoutGraceDeadlineMs = timeoutMs + KILLED_SESSION_EXIT_GRACE_MS;
53
+ // Beyond the 32-bit setTimeout range the deadline cannot be represented;
54
+ // keep the unbounded wait rather than firing a false early timeout.
55
+ if (timeoutGraceDeadlineMs <= MAX_TIMEOUT_MS) {
56
+ timeoutGraceTimer = setTimeout(() => settle(() => resolve("timeout_grace")), timeoutGraceDeadlineMs);
57
+ }
58
+ }
59
+ if (signal) {
60
+ armAbortGrace = () => {
61
+ abortGraceTimer ??= setTimeout(() => settle(() => resolve("abort_grace")), KILLED_SESSION_EXIT_GRACE_MS);
62
+ };
63
+ if (signal.aborted)
64
+ armAbortGrace();
65
+ else
66
+ signal.addEventListener("abort", armAbortGrace, { once: true });
67
+ }
68
+ });
69
+ }
25
70
  async function runForeground(ctx, input, cols, rows, signal, cwd) {
71
+ if (signal?.aborted)
72
+ return errorResult("Command aborted");
26
73
  const timeoutMs = input.timeout !== undefined ? Math.trunc(input.timeout * 1000) : undefined;
27
- const { runtime } = await spawnCommandSession(ctx, { command: input.command, cols, rows, timeoutMs, cwd });
28
- const onAbort = () => runtime.session.kill();
74
+ const { id, runtime } = await spawnCommandSession(ctx, { command: input.command, cols, rows, timeoutMs, cwd });
75
+ // Interrupt means "stop now": SIGKILL the whole process group in one shot.
76
+ // kill() is one-shot idempotent, so a gentle SIGTERM first would block any
77
+ // escalation, and a SIGTERM-ignoring command would pin the agent forever.
78
+ const onAbort = () => runtime.session.kill("SIGKILL");
29
79
  if (signal) {
30
80
  if (signal.aborted)
31
81
  onAbort();
32
82
  else
33
83
  signal.addEventListener("abort", onAbort, { once: true });
34
84
  }
85
+ let outcome;
35
86
  try {
36
- await runtime.session.waitExit();
87
+ outcome = await raceExitWithKillGrace(runtime, signal, timeoutMs);
37
88
  }
38
89
  finally {
39
90
  signal?.removeEventListener("abort", onAbort);
40
91
  }
92
+ if (outcome !== "exited") {
93
+ // Sweep the never-settling session: the bounded registry stop marks it
94
+ // `stopping`, so later /exit teardown cannot hang on its exit wait.
95
+ void ctx.manager.stop(id).catch(() => { });
96
+ }
41
97
  const output = runtime.fullOutput().trimEnd();
42
- const status = describeExit(runtime);
98
+ // Aborted runs report "Command aborted" (core bash parity) whether the exit
99
+ // settled normally or the kill grace released the wait. `outcome` matters
100
+ // beyond that only for the timeout grace, where exitResult is still null.
101
+ if (signal?.aborted) {
102
+ return errorResult(`${output ? `${output}\n\n` : ""}Command aborted`);
103
+ }
43
104
  const exit = runtime.exitResult;
44
- if (exit?.timedOut) {
105
+ if (outcome === "timeout_grace" || exit?.timedOut) {
45
106
  return errorResult(`${output ? `${output}\n\n` : ""}Command timed out after ${input.timeout} seconds`);
46
107
  }
108
+ const status = describeExit(runtime);
47
109
  if (exit && exit.exitCode !== 0 && exit.exitCode !== null) {
48
110
  return errorResult(`${output ? `${output}\n\n` : ""}Command exited with code ${exit.exitCode}`);
49
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/terminal/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport { BACKGROUND_START_GRACE_MS, DEFAULT_COLS, DEFAULT_ROWS, TERMINAL_BASH_TOOL } from \"../shared.ts\";\nimport { errorResult, type TerminalToolContext, type TerminalToolResult, textResult } from \"./context.ts\";\nimport { describeExit, spawnCommandSession } from \"./spawn.ts\";\n\nexport const ptyBashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Shell command to execute in a PTY-backed session.\" }),\n\ttimeout: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription:\n\t\t\t\t\"Foreground kill deadline in seconds. Ignored for run_in_background sessions (they live until exit or kill_bash).\",\n\t\t}),\n\t),\n\tdescription: Type.Optional(Type.String({ description: \"Short human-readable label for this command.\" })),\n\trun_in_background: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Run as a persistent background session. Returns a bash_id immediately; query it with bash_output, steer with bash_input, tear down with kill_bash.\",\n\t\t}),\n\t),\n\tcols: Type.Optional(Type.Number({ description: \"PTY width in columns (default 120).\" })),\n\trows: Type.Optional(Type.Number({ description: \"PTY height in rows (default 40).\" })),\n});\n\nexport type PtyBashInput = Static<typeof ptyBashSchema>;\n\nfunction resolveDimension(value: number | undefined, fallback: number): number {\n\tif (value === undefined || !Number.isFinite(value) || value < 1) return fallback;\n\treturn Math.trunc(value);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function runForeground(\n\tctx: TerminalToolContext,\n\tinput: PtyBashInput,\n\tcols: number,\n\trows: number,\n\tsignal: AbortSignal | undefined,\n\tcwd: string | undefined,\n): Promise<TerminalToolResult> {\n\tconst timeoutMs = input.timeout !== undefined ? Math.trunc(input.timeout * 1000) : undefined;\n\tconst { runtime } = await spawnCommandSession(ctx, { command: input.command, cols, rows, timeoutMs, cwd });\n\tconst onAbort = () => runtime.session.kill();\n\tif (signal) {\n\t\tif (signal.aborted) onAbort();\n\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t}\n\ttry {\n\t\tawait runtime.session.waitExit();\n\t} finally {\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t}\n\n\tconst output = runtime.fullOutput().trimEnd();\n\tconst status = describeExit(runtime);\n\tconst exit = runtime.exitResult;\n\tif (exit?.timedOut) {\n\t\treturn errorResult(`${output ? `${output}\\n\\n` : \"\"}Command timed out after ${input.timeout} seconds`);\n\t}\n\tif (exit && exit.exitCode !== 0 && exit.exitCode !== null) {\n\t\treturn errorResult(`${output ? `${output}\\n\\n` : \"\"}Command exited with code ${exit.exitCode}`);\n\t}\n\treturn textResult(output || \"(no output)\", { details: { status } });\n}\n\nasync function runBackground(\n\tctx: TerminalToolContext,\n\tinput: PtyBashInput,\n\tcols: number,\n\trows: number,\n\tcwd: string | undefined,\n): Promise<TerminalToolResult> {\n\t// Background sessions are NEVER killed by `timeout` (bash-timeout injects a default into\n\t// every bash call); they live until exit or kill_bash, so no timeoutMs is passed.\n\tconst { id, runtime } = await spawnCommandSession(ctx, { command: input.command, cols, rows, cwd });\n\tif (ctx.onBackgroundExit) runtime.session.onExit(() => ctx.onBackgroundExit?.(id, runtime));\n\n\t// Capture any output the command emits within a short grace window (or its exit).\n\tawait Promise.race([delay(BACKGROUND_START_GRACE_MS), runtime.session.waitExit()]);\n\tconst early = runtime.readDelta().text.trimEnd();\n\tconst header = `Command running in background with ID: ${id}`;\n\tconst backendNote =\n\t\truntime.backend === \"pipe-fallback\"\n\t\t\t? \"\\n(native PTY unavailable — running via pipe fallback; bash_input/bash_resize are limited.)\"\n\t\t\t: \"\";\n\tconst earlyBlock = early ? `\\n\\n${early}` : \"\";\n\treturn textResult(`${header}${backendNote}${earlyBlock}`, { details: { bash_id: id, background: true } });\n}\n\n/** Build the PTY-backed `bash` tool definition. */\nexport function createPtyBashTool(ctx: TerminalToolContext) {\n\treturn {\n\t\tname: TERMINAL_BASH_TOOL,\n\t\tlabel: \"bash\",\n\t\tdescription:\n\t\t\t\"Execute a shell command in a persistent PTY-backed session. Set run_in_background:true for long-lived or interactive sessions; steer them with bash_input, snapshot with bash_output, tear down with kill_bash. Foreground timeout is a kill deadline in seconds.\",\n\t\tpromptSnippet: \"Run shell commands; run_in_background:true for long-lived/interactive PTY sessions\",\n\t\tparameters: ptyBashSchema,\n\t\tasync execute(\n\t\t\t_toolCallId: string,\n\t\t\tinput: PtyBashInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?: unknown,\n\t\t\texecCtx?: { cwd?: string },\n\t\t): Promise<TerminalToolResult> {\n\t\t\tconst cols = resolveDimension(input.cols, ctx.defaultCols || DEFAULT_COLS);\n\t\t\tconst rows = resolveDimension(input.rows, ctx.defaultRows || DEFAULT_ROWS);\n\t\t\tconst cwd = execCtx?.cwd;\n\t\t\tif (input.run_in_background) return runBackground(ctx, input, cols, rows, cwd);\n\t\t\treturn runForeground(ctx, input, cols, rows, signal, cwd);\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/terminal/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { TerminalRuntimeSession } from \"../runtime-session.ts\";\nimport {\n\tBACKGROUND_START_GRACE_MS,\n\tDEFAULT_COLS,\n\tDEFAULT_ROWS,\n\tKILLED_SESSION_EXIT_GRACE_MS,\n\tTERMINAL_BASH_TOOL,\n} from \"../shared.ts\";\nimport { errorResult, type TerminalToolContext, type TerminalToolResult, textResult } from \"./context.ts\";\nimport { describeExit, spawnCommandSession } from \"./spawn.ts\";\n\nexport const ptyBashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Shell command to execute in a PTY-backed session.\" }),\n\ttimeout: Type.Optional(\n\t\tType.Number({\n\t\t\tdescription:\n\t\t\t\t\"Foreground kill deadline in seconds. Ignored for run_in_background sessions (they live until exit or kill_bash).\",\n\t\t}),\n\t),\n\tdescription: Type.Optional(Type.String({ description: \"Short human-readable label for this command.\" })),\n\trun_in_background: Type.Optional(\n\t\tType.Boolean({\n\t\t\tdescription:\n\t\t\t\t\"Run as a persistent background session. Returns a bash_id immediately; query it with bash_output, steer with bash_input, tear down with kill_bash.\",\n\t\t}),\n\t),\n\tcols: Type.Optional(Type.Number({ description: \"PTY width in columns (default 120).\" })),\n\trows: Type.Optional(Type.Number({ description: \"PTY height in rows (default 40).\" })),\n});\n\nexport type PtyBashInput = Static<typeof ptyBashSchema>;\n\nfunction resolveDimension(value: number | undefined, fallback: number): number {\n\tif (value === undefined || !Number.isFinite(value) || value < 1) return fallback;\n\treturn Math.trunc(value);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst MAX_TIMEOUT_MS = 2_147_483_647;\n\ntype ForegroundWaitOutcome = \"exited\" | \"abort_grace\" | \"timeout_grace\";\n\n/**\n * Wait for the session's exit to settle, but stop waiting a bounded grace after\n * the session has been killed. The native wait joins the PTY reader thread,\n * which blocks while any surviving descendant holds the PTY open — without the\n * grace, an aborted or timed-out command can pin the agent forever.\n */\nfunction raceExitWithKillGrace(\n\truntime: TerminalRuntimeSession,\n\tsignal: AbortSignal | undefined,\n\ttimeoutMs: number | undefined,\n): Promise<ForegroundWaitOutcome> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tlet abortGraceTimer: ReturnType<typeof setTimeout> | undefined;\n\t\tlet timeoutGraceTimer: ReturnType<typeof setTimeout> | undefined;\n\t\tlet armAbortGrace: (() => void) | undefined;\n\t\tconst settle = (finish: () => void) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tif (abortGraceTimer) clearTimeout(abortGraceTimer);\n\t\t\tif (timeoutGraceTimer) clearTimeout(timeoutGraceTimer);\n\t\t\tif (signal && armAbortGrace) signal.removeEventListener(\"abort\", armAbortGrace);\n\t\t\tfinish();\n\t\t};\n\t\truntime.session.waitExit().then(\n\t\t\t() => settle(() => resolve(\"exited\")),\n\t\t\t(error: unknown) => settle(() => reject(error instanceof Error ? error : new Error(String(error)))),\n\t\t);\n\t\tif (timeoutMs !== undefined) {\n\t\t\tconst timeoutGraceDeadlineMs = timeoutMs + KILLED_SESSION_EXIT_GRACE_MS;\n\t\t\t// Beyond the 32-bit setTimeout range the deadline cannot be represented;\n\t\t\t// keep the unbounded wait rather than firing a false early timeout.\n\t\t\tif (timeoutGraceDeadlineMs <= MAX_TIMEOUT_MS) {\n\t\t\t\ttimeoutGraceTimer = setTimeout(() => settle(() => resolve(\"timeout_grace\")), timeoutGraceDeadlineMs);\n\t\t\t}\n\t\t}\n\t\tif (signal) {\n\t\t\tarmAbortGrace = () => {\n\t\t\t\tabortGraceTimer ??= setTimeout(() => settle(() => resolve(\"abort_grace\")), KILLED_SESSION_EXIT_GRACE_MS);\n\t\t\t};\n\t\t\tif (signal.aborted) armAbortGrace();\n\t\t\telse signal.addEventListener(\"abort\", armAbortGrace, { once: true });\n\t\t}\n\t});\n}\n\nasync function runForeground(\n\tctx: TerminalToolContext,\n\tinput: PtyBashInput,\n\tcols: number,\n\trows: number,\n\tsignal: AbortSignal | undefined,\n\tcwd: string | undefined,\n): Promise<TerminalToolResult> {\n\tif (signal?.aborted) return errorResult(\"Command aborted\");\n\tconst timeoutMs = input.timeout !== undefined ? Math.trunc(input.timeout * 1000) : undefined;\n\tconst { id, runtime } = await spawnCommandSession(ctx, { command: input.command, cols, rows, timeoutMs, cwd });\n\t// Interrupt means \"stop now\": SIGKILL the whole process group in one shot.\n\t// kill() is one-shot idempotent, so a gentle SIGTERM first would block any\n\t// escalation, and a SIGTERM-ignoring command would pin the agent forever.\n\tconst onAbort = () => runtime.session.kill(\"SIGKILL\");\n\tif (signal) {\n\t\tif (signal.aborted) onAbort();\n\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t}\n\tlet outcome: ForegroundWaitOutcome;\n\ttry {\n\t\toutcome = await raceExitWithKillGrace(runtime, signal, timeoutMs);\n\t} finally {\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t}\n\n\tif (outcome !== \"exited\") {\n\t\t// Sweep the never-settling session: the bounded registry stop marks it\n\t\t// `stopping`, so later /exit teardown cannot hang on its exit wait.\n\t\tvoid ctx.manager.stop(id).catch(() => {});\n\t}\n\tconst output = runtime.fullOutput().trimEnd();\n\t// Aborted runs report \"Command aborted\" (core bash parity) whether the exit\n\t// settled normally or the kill grace released the wait. `outcome` matters\n\t// beyond that only for the timeout grace, where exitResult is still null.\n\tif (signal?.aborted) {\n\t\treturn errorResult(`${output ? `${output}\\n\\n` : \"\"}Command aborted`);\n\t}\n\tconst exit = runtime.exitResult;\n\tif (outcome === \"timeout_grace\" || exit?.timedOut) {\n\t\treturn errorResult(`${output ? `${output}\\n\\n` : \"\"}Command timed out after ${input.timeout} seconds`);\n\t}\n\tconst status = describeExit(runtime);\n\tif (exit && exit.exitCode !== 0 && exit.exitCode !== null) {\n\t\treturn errorResult(`${output ? `${output}\\n\\n` : \"\"}Command exited with code ${exit.exitCode}`);\n\t}\n\treturn textResult(output || \"(no output)\", { details: { status } });\n}\n\nasync function runBackground(\n\tctx: TerminalToolContext,\n\tinput: PtyBashInput,\n\tcols: number,\n\trows: number,\n\tcwd: string | undefined,\n): Promise<TerminalToolResult> {\n\t// Background sessions are NEVER killed by `timeout` (bash-timeout injects a default into\n\t// every bash call); they live until exit or kill_bash, so no timeoutMs is passed.\n\tconst { id, runtime } = await spawnCommandSession(ctx, { command: input.command, cols, rows, cwd });\n\tif (ctx.onBackgroundExit) runtime.session.onExit(() => ctx.onBackgroundExit?.(id, runtime));\n\n\t// Capture any output the command emits within a short grace window (or its exit).\n\tawait Promise.race([delay(BACKGROUND_START_GRACE_MS), runtime.session.waitExit()]);\n\tconst early = runtime.readDelta().text.trimEnd();\n\tconst header = `Command running in background with ID: ${id}`;\n\tconst backendNote =\n\t\truntime.backend === \"pipe-fallback\"\n\t\t\t? \"\\n(native PTY unavailable — running via pipe fallback; bash_input/bash_resize are limited.)\"\n\t\t\t: \"\";\n\tconst earlyBlock = early ? `\\n\\n${early}` : \"\";\n\treturn textResult(`${header}${backendNote}${earlyBlock}`, { details: { bash_id: id, background: true } });\n}\n\n/** Build the PTY-backed `bash` tool definition. */\nexport function createPtyBashTool(ctx: TerminalToolContext) {\n\treturn {\n\t\tname: TERMINAL_BASH_TOOL,\n\t\tlabel: \"bash\",\n\t\tdescription:\n\t\t\t\"Execute a shell command in a persistent PTY-backed session. Set run_in_background:true for long-lived or interactive sessions; steer them with bash_input, snapshot with bash_output, tear down with kill_bash. Foreground timeout is a kill deadline in seconds.\",\n\t\tpromptSnippet: \"Run shell commands; run_in_background:true for long-lived/interactive PTY sessions\",\n\t\tparameters: ptyBashSchema,\n\t\tasync execute(\n\t\t\t_toolCallId: string,\n\t\t\tinput: PtyBashInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?: unknown,\n\t\t\texecCtx?: { cwd?: string },\n\t\t): Promise<TerminalToolResult> {\n\t\t\tconst cols = resolveDimension(input.cols, ctx.defaultCols || DEFAULT_COLS);\n\t\t\tconst rows = resolveDimension(input.rows, ctx.defaultRows || DEFAULT_ROWS);\n\t\t\tconst cwd = execCtx?.cwd;\n\t\t\tif (input.run_in_background) return runBackground(ctx, input, cols, rows, cwd);\n\t\t\treturn runForeground(ctx, input, cols, rows, signal, cwd);\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import type { ExtensionAPI, ExtensionContext } from "../../types.ts";
2
+ import { type TodoItem, type TodoPhase } from "./state.ts";
3
+ export type TodoCommandAccessors = {
4
+ getCurrentPhases: () => TodoPhase[];
5
+ setCurrentPhases: (phases: TodoPhase[]) => void;
6
+ syncWidget: (ctx: ExtensionContext) => void;
7
+ };
8
+ /** Tokenizer honoring double-quoted strings and backslash escapes. */
9
+ export declare function tokenizeTodoArgs(input: string): string[];
10
+ /** Exact name first, then unique prefix, then unique substring (case-insensitive). */
11
+ export declare function findPhaseFuzzy(phases: TodoPhase[], query: string): TodoPhase | undefined;
12
+ /** Exact content first, then unique substring; ambiguity resolved toward open work. */
13
+ export declare function findTaskFuzzy(phases: TodoPhase[], query: string): {
14
+ task: TodoItem;
15
+ phase: TodoPhase;
16
+ } | undefined;
17
+ export declare function registerTodoCommand(pi: ExtensionAPI, accessors: TodoCommandAccessors): void;
18
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/commands.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAA2B,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE9F,OAAO,EAKN,KAAK,QAAQ,EACb,KAAK,SAAS,EAEd,MAAM,YAAY,CAAC;AAkBpB,MAAM,MAAM,oBAAoB,GAAG;IAClC,gBAAgB,EAAE,MAAM,SAAS,EAAE,CAAC;IACpC,gBAAgB,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC5C,CAAC;AAEF,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BxD;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAUxF;AAED,uFAAuF;AACvF,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAAG,SAAS,CAkBlH;AA8BD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAmS3F"}
@@ -0,0 +1,395 @@
1
+ // /todo slash command: user-facing todo management.
2
+ //
3
+ // Ported and adapted from oh-my-pi's
4
+ // `packages/coding-agent/src/modes/controllers/todo-command-controller.ts`
5
+ // (MIT — see NOTICE.md). senpi adaptations: the command registers through the
6
+ // extension API, edits happen in the built-in `ctx.ui.editor` overlay instead
7
+ // of a suspended external $EDITOR, and user edits persist as `senpi.todo-state`
8
+ // entries with `source: "user"` so the branch scanner and compaction bridge
9
+ // pick them up unchanged.
10
+ import { readFile, writeFile } from "node:fs/promises";
11
+ import { copyToClipboard } from "../../../../utils/clipboard.js";
12
+ import { markdownToPhases, phasesToMarkdown, resolveTodoMarkdownPath } from "./markdown.js";
13
+ import { applyOpsToPhases, clonePhases, DEFAULT_INIT_PHASE, TODO_STATE_ENTRY_TYPE, } from "./state.js";
14
+ const USAGE = [
15
+ "Usage: /todo <verb> [args]",
16
+ " /todo Show current todos",
17
+ " /todo edit Edit todos as Markdown in an overlay",
18
+ " /todo copy Copy todos as Markdown to clipboard",
19
+ " /todo export [<path>] Write todos to file (default: TODO.md)",
20
+ " /todo import [<path>] Replace todos from file (default: TODO.md)",
21
+ " /todo append [<phase>] <task...> Append a task; phase fuzzy-matched or created",
22
+ " /todo start <task> Mark task in_progress (fuzzy match)",
23
+ " /todo done [<task|phase>] Mark task/phase/all completed",
24
+ " /todo drop [<task|phase>] Mark task/phase/all abandoned",
25
+ " /todo rm [<task|phase>] Remove task/phase/all",
26
+ ].join("\n");
27
+ const VERBS = ["edit", "copy", "export", "import", "append", "start", "done", "drop", "rm", "help"];
28
+ /** Tokenizer honoring double-quoted strings and backslash escapes. */
29
+ export function tokenizeTodoArgs(input) {
30
+ const tokens = [];
31
+ let current = "";
32
+ let inQuote = false;
33
+ for (let index = 0; index < input.length; index += 1) {
34
+ const char = input[index];
35
+ if (char === "\\" && index + 1 < input.length) {
36
+ current += input[index + 1];
37
+ index += 1;
38
+ continue;
39
+ }
40
+ if (char === '"') {
41
+ inQuote = !inQuote;
42
+ continue;
43
+ }
44
+ if (!inQuote && /\s/.test(char)) {
45
+ if (current) {
46
+ tokens.push(current);
47
+ current = "";
48
+ }
49
+ continue;
50
+ }
51
+ current += char;
52
+ }
53
+ if (current)
54
+ tokens.push(current);
55
+ return tokens;
56
+ }
57
+ /** Exact name first, then unique prefix, then unique substring (case-insensitive). */
58
+ export function findPhaseFuzzy(phases, query) {
59
+ const q = query.trim().toLowerCase();
60
+ if (!q)
61
+ return undefined;
62
+ const byName = phases.find((phase) => phase.name.toLowerCase() === q);
63
+ if (byName)
64
+ return byName;
65
+ const prefixMatches = phases.filter((phase) => phase.name.toLowerCase().startsWith(q));
66
+ if (prefixMatches.length === 1)
67
+ return prefixMatches[0];
68
+ const substringMatches = phases.filter((phase) => phase.name.toLowerCase().includes(q));
69
+ if (substringMatches.length === 1)
70
+ return substringMatches[0];
71
+ return undefined;
72
+ }
73
+ /** Exact content first, then unique substring; ambiguity resolved toward open work. */
74
+ export function findTaskFuzzy(phases, query) {
75
+ const q = query.trim().toLowerCase();
76
+ if (!q)
77
+ return undefined;
78
+ for (const phase of phases) {
79
+ for (const task of phase.tasks) {
80
+ if (task.content.toLowerCase() === q)
81
+ return { task, phase };
82
+ }
83
+ }
84
+ const matches = [];
85
+ for (const phase of phases) {
86
+ for (const task of phase.tasks) {
87
+ if (task.content.toLowerCase().includes(q))
88
+ matches.push({ task, phase });
89
+ }
90
+ }
91
+ if (matches.length === 1)
92
+ return matches[0];
93
+ const open = matches.filter((hit) => hit.task.status === "in_progress" || hit.task.status === "pending");
94
+ if (open.length === 1)
95
+ return open[0];
96
+ return undefined;
97
+ }
98
+ function titleCaseWords(text) {
99
+ return text
100
+ .split(/\s+/)
101
+ .filter(Boolean)
102
+ .map((word) => word[0].toUpperCase() + word.slice(1))
103
+ .join(" ");
104
+ }
105
+ function titleCaseSentence(text) {
106
+ const trimmed = text.trim();
107
+ if (!trimmed)
108
+ return trimmed;
109
+ return trimmed[0].toUpperCase() + trimmed.slice(1);
110
+ }
111
+ function buildUserEditReminder(action, phases, removed) {
112
+ const markdown = phases.length === 0 ? "(empty)" : phasesToMarkdown(phases).trimEnd();
113
+ const lines = ["<system-reminder>", `The user manually modified the todo list (${action}).`];
114
+ if (removed) {
115
+ lines.push(phases.length === 0
116
+ ? "The user intentionally cleared the todo list. Do NOT recreate or re-populate it unless the user explicitly asks; continue the current request without a todo list."
117
+ : "The user intentionally removed the entries no longer shown below. Do NOT re-add them unless the user explicitly asks.");
118
+ }
119
+ lines.push("Current todo list:", "", markdown, "</system-reminder>");
120
+ return lines.join("\n");
121
+ }
122
+ export function registerTodoCommand(pi, accessors) {
123
+ function commit(ctx, nextPhases, action, options) {
124
+ accessors.setCurrentPhases(clonePhases(nextPhases));
125
+ pi.appendEntry(TODO_STATE_ENTRY_TYPE, {
126
+ schema: "v2",
127
+ phases: clonePhases(nextPhases),
128
+ source: "user",
129
+ action,
130
+ });
131
+ accessors.syncWidget(ctx);
132
+ pi.sendMessage({
133
+ customType: "todotools.user-edit",
134
+ content: buildUserEditReminder(action, nextPhases, options?.removed ?? false),
135
+ display: false,
136
+ }, { triggerTurn: false, deliverAs: "nextTurn" });
137
+ }
138
+ function showCurrent(ctx) {
139
+ const phases = accessors.getCurrentPhases();
140
+ if (phases.length === 0) {
141
+ ctx.ui.notify("No todos. Use /todo append <task> to start one.", "info");
142
+ return;
143
+ }
144
+ ctx.ui.notify(phasesToMarkdown(phases).trimEnd(), "info");
145
+ }
146
+ async function editInOverlay(ctx) {
147
+ const current = accessors.getCurrentPhases();
148
+ const initialMarkdown = current.length > 0
149
+ ? phasesToMarkdown(current)
150
+ : `# ${DEFAULT_INIT_PHASE}\n- [ ] (replace this with your tasks)\n`;
151
+ const edited = await ctx.ui.editor("Edit todos (Markdown checklist)", initialMarkdown);
152
+ if (edited === undefined || edited === initialMarkdown) {
153
+ ctx.ui.notify("Todos unchanged.", "info");
154
+ return;
155
+ }
156
+ const { phases, errors } = markdownToPhases(edited);
157
+ if (errors.length > 0) {
158
+ ctx.ui.notify(`Could not parse Markdown:\n ${errors.join("\n ")}`, "error");
159
+ return;
160
+ }
161
+ commit(ctx, phases, "/todo edit");
162
+ const taskCount = phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
163
+ ctx.ui.notify(`Todos updated: ${phases.length} phase(s), ${taskCount} task(s).`, "info");
164
+ }
165
+ async function copyMarkdown(ctx) {
166
+ const phases = accessors.getCurrentPhases();
167
+ if (phases.length === 0) {
168
+ ctx.ui.notify("No todos to copy.", "warning");
169
+ return;
170
+ }
171
+ try {
172
+ await copyToClipboard(phasesToMarkdown(phases));
173
+ ctx.ui.notify("Copied todos as Markdown to clipboard.", "info");
174
+ }
175
+ catch (error) {
176
+ ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
177
+ }
178
+ }
179
+ async function exportToFile(ctx, rest) {
180
+ const phases = accessors.getCurrentPhases();
181
+ if (phases.length === 0) {
182
+ ctx.ui.notify("No todos to export.", "warning");
183
+ return;
184
+ }
185
+ try {
186
+ const target = resolveTodoMarkdownPath(rest, ctx.cwd);
187
+ await writeFile(target, phasesToMarkdown(phases), "utf8");
188
+ ctx.ui.notify(`Wrote todos to ${target}`, "info");
189
+ }
190
+ catch (error) {
191
+ ctx.ui.notify(`Failed to write todos: ${error instanceof Error ? error.message : String(error)}`, "error");
192
+ }
193
+ }
194
+ async function importFromFile(ctx, rest) {
195
+ let source = "";
196
+ let content;
197
+ try {
198
+ source = resolveTodoMarkdownPath(rest, ctx.cwd);
199
+ content = await readFile(source, "utf8");
200
+ }
201
+ catch (error) {
202
+ ctx.ui.notify(`Failed to read todos: ${error instanceof Error ? error.message : String(error)}`, "error");
203
+ return;
204
+ }
205
+ const { phases, errors } = markdownToPhases(content);
206
+ if (errors.length > 0) {
207
+ ctx.ui.notify(`Could not parse ${source}:\n ${errors.join("\n ")}`, "error");
208
+ return;
209
+ }
210
+ commit(ctx, phases, `/todo import ${source}`);
211
+ const taskCount = phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
212
+ ctx.ui.notify(`Imported ${phases.length} phase(s), ${taskCount} task(s) from ${source}.`, "info");
213
+ }
214
+ function append(ctx, rest) {
215
+ const tokens = tokenizeTodoArgs(rest);
216
+ if (tokens.length === 0) {
217
+ ctx.ui.notify("Usage: /todo append [<phase>] <task...>", "error");
218
+ return;
219
+ }
220
+ const next = clonePhases(accessors.getCurrentPhases());
221
+ let phaseName;
222
+ let content;
223
+ if (tokens.length === 1) {
224
+ content = tokens[0];
225
+ }
226
+ else {
227
+ phaseName = tokens[0];
228
+ content = tokens.slice(1).join(" ");
229
+ }
230
+ let targetPhase;
231
+ if (phaseName) {
232
+ targetPhase = findPhaseFuzzy(next, phaseName);
233
+ if (!targetPhase) {
234
+ targetPhase = { name: titleCaseWords(phaseName), tasks: [] };
235
+ next.push(targetPhase);
236
+ }
237
+ }
238
+ else if (next.length > 0) {
239
+ targetPhase = next[next.length - 1];
240
+ }
241
+ else {
242
+ targetPhase = { name: DEFAULT_INIT_PHASE, tasks: [] };
243
+ next.push(targetPhase);
244
+ }
245
+ const finalContent = titleCaseSentence(content);
246
+ targetPhase.tasks.push({ content: finalContent, status: "pending" });
247
+ commit(ctx, next, `/todo append → ${targetPhase.name}`);
248
+ ctx.ui.notify(`Appended to ${targetPhase.name}: ${finalContent}`, "info");
249
+ }
250
+ function start(ctx, rest) {
251
+ if (!rest) {
252
+ ctx.ui.notify("Usage: /todo start <task>", "error");
253
+ return;
254
+ }
255
+ const current = accessors.getCurrentPhases();
256
+ const hit = findTaskFuzzy(current, rest);
257
+ if (!hit) {
258
+ ctx.ui.notify(`No task matched "${rest}". Use /todo to list current tasks.`, "error");
259
+ return;
260
+ }
261
+ const { phases, errors } = applyOpsToPhases(current, [{ op: "start", task: hit.task.content }]);
262
+ if (errors.length > 0) {
263
+ ctx.ui.notify(errors.join("; "), "error");
264
+ return;
265
+ }
266
+ commit(ctx, phases, `/todo start ${hit.task.content}`);
267
+ ctx.ui.notify(`Started: ${hit.task.content}`, "info");
268
+ }
269
+ function mutateStatus(ctx, rest, target) {
270
+ const op = target === "completed" ? "done" : "drop";
271
+ const current = accessors.getCurrentPhases();
272
+ const trimmed = rest.trim();
273
+ if (!trimmed) {
274
+ const { phases, errors } = applyOpsToPhases(current, [{ op }]);
275
+ if (errors.length > 0) {
276
+ ctx.ui.notify(errors.join("; "), "error");
277
+ return;
278
+ }
279
+ commit(ctx, phases, `/todo ${op} (all)`);
280
+ ctx.ui.notify(`Marked all tasks ${target}.`, "info");
281
+ return;
282
+ }
283
+ const taskHit = findTaskFuzzy(current, trimmed);
284
+ if (taskHit) {
285
+ const { phases, errors } = applyOpsToPhases(current, [{ op, task: taskHit.task.content }]);
286
+ if (errors.length > 0) {
287
+ ctx.ui.notify(errors.join("; "), "error");
288
+ return;
289
+ }
290
+ commit(ctx, phases, `/todo ${op} ${taskHit.task.content}`);
291
+ ctx.ui.notify(`Marked ${target}: ${taskHit.task.content}`, "info");
292
+ return;
293
+ }
294
+ const phaseHit = findPhaseFuzzy(current, trimmed);
295
+ if (phaseHit) {
296
+ const { phases, errors } = applyOpsToPhases(current, [{ op, phase: phaseHit.name }]);
297
+ if (errors.length > 0) {
298
+ ctx.ui.notify(errors.join("; "), "error");
299
+ return;
300
+ }
301
+ commit(ctx, phases, `/todo ${op} ${phaseHit.name}`);
302
+ ctx.ui.notify(`Marked phase ${phaseHit.name} ${target}.`, "info");
303
+ return;
304
+ }
305
+ ctx.ui.notify(`No task or phase matched "${trimmed}".`, "error");
306
+ }
307
+ function remove(ctx, rest) {
308
+ const current = accessors.getCurrentPhases();
309
+ const trimmed = rest.trim();
310
+ if (!trimmed) {
311
+ commit(ctx, [], "/todo rm (all)", { removed: true });
312
+ ctx.ui.notify("Cleared all todos.", "info");
313
+ return;
314
+ }
315
+ const taskHit = findTaskFuzzy(current, trimmed);
316
+ if (taskHit) {
317
+ const { phases, errors } = applyOpsToPhases(current, [{ op: "rm", task: taskHit.task.content }]);
318
+ if (errors.length > 0) {
319
+ ctx.ui.notify(errors.join("; "), "error");
320
+ return;
321
+ }
322
+ commit(ctx, phases, `/todo rm ${taskHit.task.content}`, { removed: true });
323
+ ctx.ui.notify(`Removed: ${taskHit.task.content}`, "info");
324
+ return;
325
+ }
326
+ const phaseHit = findPhaseFuzzy(current, trimmed);
327
+ if (phaseHit) {
328
+ const { phases, errors } = applyOpsToPhases(current, [{ op: "rm", phase: phaseHit.name }]);
329
+ if (errors.length > 0) {
330
+ ctx.ui.notify(errors.join("; "), "error");
331
+ return;
332
+ }
333
+ commit(ctx, phases, `/todo rm ${phaseHit.name}`, { removed: true });
334
+ ctx.ui.notify(`Removed phase: ${phaseHit.name}`, "info");
335
+ return;
336
+ }
337
+ ctx.ui.notify(`No task or phase matched "${trimmed}".`, "error");
338
+ }
339
+ pi.registerCommand("todo", {
340
+ description: "Show or edit the todo list (edit/copy/export/import/append/start/done/drop/rm)",
341
+ getArgumentCompletions: (argumentPrefix) => {
342
+ const prefix = argumentPrefix.trim().toLowerCase();
343
+ const matches = VERBS.filter((verb) => verb.startsWith(prefix));
344
+ if (matches.length === 0)
345
+ return null;
346
+ return matches.map((verb) => ({ value: verb, label: verb }));
347
+ },
348
+ handler: async (args, ctx) => {
349
+ const trimmed = args.trim();
350
+ if (!trimmed) {
351
+ showCurrent(ctx);
352
+ return;
353
+ }
354
+ const spaceIndex = trimmed.search(/\s/);
355
+ const verb = (spaceIndex === -1 ? trimmed : trimmed.slice(0, spaceIndex)).toLowerCase();
356
+ const rest = spaceIndex === -1 ? "" : trimmed.slice(spaceIndex + 1).trim();
357
+ switch (verb) {
358
+ case "edit":
359
+ await editInOverlay(ctx);
360
+ return;
361
+ case "copy":
362
+ await copyMarkdown(ctx);
363
+ return;
364
+ case "export":
365
+ await exportToFile(ctx, rest);
366
+ return;
367
+ case "import":
368
+ await importFromFile(ctx, rest);
369
+ return;
370
+ case "help":
371
+ case "?":
372
+ ctx.ui.notify(USAGE, "info");
373
+ return;
374
+ case "append":
375
+ append(ctx, rest);
376
+ return;
377
+ case "start":
378
+ start(ctx, rest);
379
+ return;
380
+ case "done":
381
+ mutateStatus(ctx, rest, "completed");
382
+ return;
383
+ case "drop":
384
+ mutateStatus(ctx, rest, "abandoned");
385
+ return;
386
+ case "rm":
387
+ remove(ctx, rest);
388
+ return;
389
+ default:
390
+ ctx.ui.notify(`Unknown /todo verb "${verb}".\n${USAGE}`, "error");
391
+ }
392
+ },
393
+ });
394
+ }
395
+ //# sourceMappingURL=commands.js.map