@code-yeongyu/senpi 2026.9.23-5 → 2026.9.24-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 (315) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/bundle/chunks/{anthropic-messages-77YBORJ5.js → anthropic-messages-UPLQFNTT.js} +2 -2
  3. package/dist/bundle/chunks/{app-server-command-BGT65PGC.js → app-server-command-UHPJ2C4D.js} +1 -1
  4. package/dist/bundle/chunks/{azure-openai-responses-PSESFNHN.js → azure-openai-responses-XAR2E66I.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-WXIRFRXY.js → chunk-2PLPSKHD.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-7PANH3NB.js → chunk-3WBSBDBX.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-BBOQ5H4W.js → chunk-6WBYI25N.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-RG3UEFSF.js → chunk-7DY7UYLL.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-VKBY4F76.js → chunk-BSOJHK4W.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-3XHWW7SQ.js → chunk-CLZVNQW3.js} +1 -1
  11. package/dist/bundle/chunks/{chunk-ORCF262V.js → chunk-EJKCBRYK.js} +3 -3
  12. package/dist/bundle/chunks/chunk-J7IUURQ6.js +8 -0
  13. package/dist/bundle/chunks/{chunk-PSMTQDII.js → chunk-JRQSHZPP.js} +15 -9
  14. package/dist/bundle/chunks/{chunk-DUV3UFKX.js → chunk-MKAM7IRH.js} +1 -1
  15. package/dist/bundle/chunks/chunk-MO2U7YRX.js +11 -0
  16. package/dist/bundle/chunks/{chunk-ZEFQYQOU.js → chunk-NGHOUIPR.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-XDSQYM4F.js → chunk-NKVUDCGZ.js} +2 -2
  18. package/dist/bundle/chunks/{chunk-J3QXPP4T.js → chunk-ONR57UMO.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-TQDWU3ZQ.js → chunk-SYQVC7UM.js} +1 -1
  20. package/dist/bundle/chunks/chunk-TTHMOL5G.js +2 -0
  21. package/dist/bundle/chunks/{chunk-NNHFMZD5.js → chunk-UBPMXBOJ.js} +1 -1
  22. package/dist/bundle/chunks/chunk-WASCMT6Y.js +2 -0
  23. package/dist/bundle/chunks/{chunk-EN6KDFY2.js → chunk-WISJJQ4K.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-IVYZMSFY.js → chunk-WL5EQYNL.js} +1 -1
  25. package/dist/bundle/chunks/{chunk-LC6SZTVE.js → chunk-WTSAB6AE.js} +1 -1
  26. package/dist/bundle/chunks/{chunk-HKE42SWX.js → chunk-Y54V65MS.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-3RN6BFG2.js → chunk-YBC274GY.js} +4 -4
  28. package/dist/bundle/chunks/{chunk-RRSND33J.js → chunk-YKU45B65.js} +54 -54
  29. package/dist/bundle/chunks/{chunk-WUYBEF7C.js → chunk-YWO3OBYK.js} +1 -1
  30. package/dist/bundle/chunks/cli-main-O5Y3TBID.js +3 -0
  31. package/dist/bundle/chunks/{google-generative-ai-YJHSZAY5.js → google-generative-ai-B5QMFONL.js} +1 -1
  32. package/dist/bundle/chunks/{google-vertex-JTFWEDNJ.js → google-vertex-O2TGMVWF.js} +1 -1
  33. package/dist/bundle/chunks/{help-fast-path-QXVCHTP3.js → help-fast-path-Y33OIZBU.js} +1 -1
  34. package/dist/bundle/chunks/{host-command-3PUZYQOK.js → host-command-WJOL27Q7.js} +1 -1
  35. package/dist/bundle/chunks/{host-lifecycle-OHPSU5VU.js → host-lifecycle-YBFXYFZP.js} +1 -1
  36. package/dist/bundle/chunks/{interactive-host-runtime-57LEAJPU.js → interactive-host-runtime-XVTF3NUD.js} +1 -1
  37. package/dist/bundle/chunks/interactive-mode-OO3NGM4G.js +2 -0
  38. package/dist/bundle/chunks/{list-tips-Z62FXPOJ.js → list-tips-EBRNBPBM.js} +1 -1
  39. package/dist/bundle/chunks/{mistral-conversations-VJPMPQ5T.js → mistral-conversations-AS3SAWPA.js} +1 -1
  40. package/dist/bundle/chunks/{multi-session-host-GFSDQQUJ.js → multi-session-host-6MKBBOKF.js} +1 -1
  41. package/dist/bundle/chunks/{openai-codex-responses-IQ35QACK.js → openai-codex-responses-CK7T4WNM.js} +1 -1
  42. package/dist/bundle/chunks/{openai-completions-74OLE55U.js → openai-completions-OPQKN7FH.js} +3 -3
  43. package/dist/bundle/chunks/openai-responses-QHWM3KPO.js +2 -0
  44. package/dist/bundle/chunks/{openrouter-images-T4GY3JYM.js → openrouter-images-MW5TXV7L.js} +1 -1
  45. package/dist/bundle/chunks/{package-manager-cli-J7244EJE.js → package-manager-cli-BMEWLAI2.js} +1 -1
  46. package/dist/bundle/chunks/{rotation-stream-CZT4TRPD.js → rotation-stream-ZFA6ELXJ.js} +1 -1
  47. package/dist/bundle/chunks/{rpc-mode-75CRTY24.js → rpc-mode-5653CV65.js} +1 -1
  48. package/dist/bundle/chunks/{session-picker-ZIBANFBQ.js → session-picker-PPYK56TA.js} +1 -1
  49. package/dist/bundle/chunks/session-worker.js +265 -259
  50. package/dist/bundle/cli.js +1 -1
  51. package/dist/bundle/index.js +1 -1
  52. package/dist/bundle/rpc-entry.js +1 -1
  53. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  54. package/dist/core/agent-session-runtime.js +13 -0
  55. package/dist/core/agent-session-runtime.js.map +1 -1
  56. package/dist/core/agent-session.d.ts +28 -0
  57. package/dist/core/agent-session.d.ts.map +1 -1
  58. package/dist/core/agent-session.js +75 -12
  59. package/dist/core/agent-session.js.map +1 -1
  60. package/dist/core/dynamic-prompt/build.d.ts +6 -1
  61. package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
  62. package/dist/core/dynamic-prompt/build.js +0 -7
  63. package/dist/core/dynamic-prompt/build.js.map +1 -1
  64. package/dist/core/environment-context.d.ts +32 -0
  65. package/dist/core/environment-context.d.ts.map +1 -0
  66. package/dist/core/environment-context.js +63 -0
  67. package/dist/core/environment-context.js.map +1 -0
  68. package/dist/core/extensions/builtin/anthropic-subscription/session-sync.d.ts.map +1 -1
  69. package/dist/core/extensions/builtin/anthropic-subscription/session-sync.js +1 -15
  70. package/dist/core/extensions/builtin/anthropic-subscription/session-sync.js.map +1 -1
  71. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js +3 -0
  72. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js.map +1 -1
  73. package/dist/core/extensions/builtin/goal/cache-warm.d.ts +19 -2
  74. package/dist/core/extensions/builtin/goal/cache-warm.d.ts.map +1 -1
  75. package/dist/core/extensions/builtin/goal/cache-warm.js +28 -2
  76. package/dist/core/extensions/builtin/goal/cache-warm.js.map +1 -1
  77. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  78. package/dist/core/extensions/builtin/goal/monitor-continuation.js +4 -2
  79. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  80. package/dist/core/extensions/builtin/goal/parked-wait.js +2 -0
  81. package/dist/core/extensions/builtin/goal/parked-wait.js.map +1 -1
  82. package/dist/core/extensions/builtin/goal/prompt.js +1 -1
  83. package/dist/core/extensions/builtin/goal/prompt.js.map +1 -1
  84. package/dist/core/extensions/builtin/herdr/herdr-state.d.ts +5 -0
  85. package/dist/core/extensions/builtin/herdr/herdr-state.d.ts.map +1 -1
  86. package/dist/core/extensions/builtin/herdr/herdr-state.js +28 -3
  87. package/dist/core/extensions/builtin/herdr/herdr-state.js.map +1 -1
  88. package/dist/core/extensions/builtin/herdr/index.d.ts.map +1 -1
  89. package/dist/core/extensions/builtin/herdr/index.js +7 -1
  90. package/dist/core/extensions/builtin/herdr/index.js.map +1 -1
  91. package/dist/core/extensions/builtin/hooks/index.d.ts.map +1 -1
  92. package/dist/core/extensions/builtin/hooks/index.js +3 -15
  93. package/dist/core/extensions/builtin/hooks/index.js.map +1 -1
  94. package/dist/core/extensions/builtin/hooks/stop-lifecycle.d.ts +26 -0
  95. package/dist/core/extensions/builtin/hooks/stop-lifecycle.d.ts.map +1 -0
  96. package/dist/core/extensions/builtin/hooks/stop-lifecycle.js +88 -0
  97. package/dist/core/extensions/builtin/hooks/stop-lifecycle.js.map +1 -0
  98. package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
  99. package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
  100. package/dist/core/extensions/builtin/recommended-models/index.js +28 -10
  101. package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
  102. package/dist/core/extensions/builtin/rules/commands.d.ts.map +1 -1
  103. package/dist/core/extensions/builtin/rules/commands.js +5 -1
  104. package/dist/core/extensions/builtin/rules/commands.js.map +1 -1
  105. package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
  106. package/dist/core/extensions/builtin/rules/index.js +25 -3
  107. package/dist/core/extensions/builtin/rules/index.js.map +1 -1
  108. package/dist/core/extensions/builtin/rules/rules/constants.d.ts.map +1 -1
  109. package/dist/core/extensions/builtin/rules/rules/constants.js +22 -14
  110. package/dist/core/extensions/builtin/rules/rules/constants.js.map +1 -1
  111. package/dist/core/extensions/builtin/rules/rules/engine.d.ts.map +1 -1
  112. package/dist/core/extensions/builtin/rules/rules/engine.js +39 -9
  113. package/dist/core/extensions/builtin/rules/rules/engine.js.map +1 -1
  114. package/dist/core/extensions/builtin/rules/rules/finder.js +3 -0
  115. package/dist/core/extensions/builtin/rules/rules/finder.js.map +1 -1
  116. package/dist/core/extensions/builtin/rules/rules/project-root.d.ts +17 -0
  117. package/dist/core/extensions/builtin/rules/rules/project-root.d.ts.map +1 -1
  118. package/dist/core/extensions/builtin/rules/rules/project-root.js +67 -5
  119. package/dist/core/extensions/builtin/rules/rules/project-root.js.map +1 -1
  120. package/dist/core/extensions/builtin/rules/rules/types.d.ts +2 -2
  121. package/dist/core/extensions/builtin/rules/rules/types.d.ts.map +1 -1
  122. package/dist/core/extensions/builtin/rules/rules/types.js.map +1 -1
  123. package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts +3 -1
  124. package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts.map +1 -1
  125. package/dist/core/extensions/builtin/rules/ui/rules-banner.js +1 -1
  126. package/dist/core/extensions/builtin/rules/ui/rules-banner.js.map +1 -1
  127. package/dist/core/extensions/builtin/todotools/todo-storage.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/todotools/todo-storage.js +10 -2
  129. package/dist/core/extensions/builtin/todotools/todo-storage.js.map +1 -1
  130. package/dist/core/extensions/builtin/todotools/tools/todo.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/todotools/tools/todo.js +2 -1
  132. package/dist/core/extensions/builtin/todotools/tools/todo.js.map +1 -1
  133. package/dist/core/extensions/builtin/websearch/websearch/config.d.ts.map +1 -1
  134. package/dist/core/extensions/builtin/websearch/websearch/config.js +2 -0
  135. package/dist/core/extensions/builtin/websearch/websearch/config.js.map +1 -1
  136. package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.d.ts.map +1 -1
  137. package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.js +2 -0
  138. package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.js.map +1 -1
  139. package/dist/core/extensions/builtin/websearch/websearch/providers/kagi.d.ts +3 -0
  140. package/dist/core/extensions/builtin/websearch/websearch/providers/kagi.d.ts.map +1 -0
  141. package/dist/core/extensions/builtin/websearch/websearch/providers/kagi.js +34 -0
  142. package/dist/core/extensions/builtin/websearch/websearch/providers/kagi.js.map +1 -0
  143. package/dist/core/extensions/builtin/websearch/websearch/providers/serpdive.d.ts +3 -0
  144. package/dist/core/extensions/builtin/websearch/websearch/providers/serpdive.d.ts.map +1 -0
  145. package/dist/core/extensions/builtin/websearch/websearch/providers/serpdive.js +22 -0
  146. package/dist/core/extensions/builtin/websearch/websearch/providers/serpdive.js.map +1 -0
  147. package/dist/core/extensions/builtin/websearch/websearch/providers.d.ts.map +1 -1
  148. package/dist/core/extensions/builtin/websearch/websearch/providers.js +4 -0
  149. package/dist/core/extensions/builtin/websearch/websearch/providers.js.map +1 -1
  150. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +1 -1
  151. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -1
  152. package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -1
  153. package/dist/core/session-discovery.d.ts +9 -3
  154. package/dist/core/session-discovery.d.ts.map +1 -1
  155. package/dist/core/session-discovery.js +19 -8
  156. package/dist/core/session-discovery.js.map +1 -1
  157. package/dist/core/session-manager.d.ts.map +1 -1
  158. package/dist/core/session-manager.js +8 -4
  159. package/dist/core/session-manager.js.map +1 -1
  160. package/dist/core/session-summary-cache.d.ts +16 -3
  161. package/dist/core/session-summary-cache.d.ts.map +1 -1
  162. package/dist/core/session-summary-cache.js +19 -3
  163. package/dist/core/session-summary-cache.js.map +1 -1
  164. package/dist/core/session-summary-index-file.d.ts +38 -0
  165. package/dist/core/session-summary-index-file.d.ts.map +1 -0
  166. package/dist/core/session-summary-index-file.js +119 -0
  167. package/dist/core/session-summary-index-file.js.map +1 -0
  168. package/dist/core/session-summary-index.d.ts +52 -0
  169. package/dist/core/session-summary-index.d.ts.map +1 -0
  170. package/dist/core/session-summary-index.js +157 -0
  171. package/dist/core/session-summary-index.js.map +1 -0
  172. package/dist/core/session-summary.d.ts +21 -2
  173. package/dist/core/session-summary.d.ts.map +1 -1
  174. package/dist/core/session-summary.js +53 -14
  175. package/dist/core/session-summary.js.map +1 -1
  176. package/dist/core/timings.d.ts +1 -1
  177. package/dist/core/timings.d.ts.map +1 -1
  178. package/dist/core/timings.js.map +1 -1
  179. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  180. package/dist/core/tools/renderers/read.js +7 -2
  181. package/dist/core/tools/renderers/read.js.map +1 -1
  182. package/dist/core/tools/renderers/skill-read-path.d.ts +9 -0
  183. package/dist/core/tools/renderers/skill-read-path.d.ts.map +1 -0
  184. package/dist/core/tools/renderers/skill-read-path.js +49 -0
  185. package/dist/core/tools/renderers/skill-read-path.js.map +1 -0
  186. package/dist/main.d.ts.map +1 -1
  187. package/dist/main.js +7 -0
  188. package/dist/main.js.map +1 -1
  189. package/dist/modes/interactive/components/exploration-call.d.ts +1 -1
  190. package/dist/modes/interactive/components/exploration-call.d.ts.map +1 -1
  191. package/dist/modes/interactive/components/exploration-call.js +3 -1
  192. package/dist/modes/interactive/components/exploration-call.js.map +1 -1
  193. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  194. package/dist/modes/interactive/components/session-selector-search.js +32 -16
  195. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  196. package/dist/modes/interactive/components/session-selector-tree.d.ts +32 -0
  197. package/dist/modes/interactive/components/session-selector-tree.d.ts.map +1 -0
  198. package/dist/modes/interactive/components/session-selector-tree.js +82 -0
  199. package/dist/modes/interactive/components/session-selector-tree.js.map +1 -0
  200. package/dist/modes/interactive/components/session-selector.d.ts +1 -0
  201. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  202. package/dist/modes/interactive/components/session-selector.js +6 -71
  203. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  204. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  205. package/dist/modes/interactive/interactive-mode.js +4 -1
  206. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  207. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +32 -0
  208. package/node_modules/@code-yeongyu/senpi-codemode/README.md +8 -4
  209. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  210. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/AGENTS.md +1 -0
  211. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/code-preview.ts +31 -0
  212. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-code.ts +34 -131
  213. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-js-ast.ts +65 -0
  214. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-js-layout.ts +90 -0
  215. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-js-mask.ts +178 -0
  216. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-js.ts +100 -0
  217. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-python-script.ts +127 -0
  218. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/display-python.ts +150 -0
  219. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-request.ts +18 -4
  220. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +1 -1
  221. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +9 -25
  222. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +16 -9
  223. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts +1 -1
  224. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  225. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +22 -2
  226. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  227. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  228. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +3 -1
  229. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  230. package/node_modules/@earendil-works/pi-agent-core/dist/tool-name-alias.d.ts +6 -0
  231. package/node_modules/@earendil-works/pi-agent-core/dist/tool-name-alias.d.ts.map +1 -1
  232. package/node_modules/@earendil-works/pi-agent-core/dist/tool-name-alias.js +6 -19
  233. package/node_modules/@earendil-works/pi-agent-core/dist/tool-name-alias.js.map +1 -1
  234. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +8 -0
  235. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
  236. package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
  237. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  238. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.d.ts.map +1 -1
  239. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.js +8 -35
  240. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-tool-references.js.map +1 -1
  241. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  242. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +10 -6
  243. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  244. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
  245. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +4 -3
  246. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
  247. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  248. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +53 -1
  249. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  250. package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.js +1 -1
  251. package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.js.map +1 -1
  252. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +30 -0
  253. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  254. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +30 -0
  255. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  256. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +2 -1
  257. package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
  258. package/node_modules/@earendil-works/pi-ai/dist/index.js +2 -1
  259. package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
  260. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +6 -0
  261. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  262. package/node_modules/@earendil-works/pi-ai/dist/models.js +15 -0
  263. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  264. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts +17 -0
  265. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.d.ts.map +1 -1
  266. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.js +4 -1
  267. package/node_modules/@earendil-works/pi-ai/dist/openai-responses-compat.js.map +1 -1
  268. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  269. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  270. package/node_modules/@earendil-works/pi-ai/dist/providers/data/chatgpt-subscription.json +1 -1
  271. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  272. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  273. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  274. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax-cn.json +1 -1
  275. package/node_modules/@earendil-works/pi-ai/dist/providers/data/minimax.json +1 -1
  276. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai-cn.json +1 -1
  277. package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai.json +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  279. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  280. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  281. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  282. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  283. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  284. package/node_modules/@earendil-works/pi-ai/dist/providers/data/venice.json +1 -1
  285. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  286. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +6 -0
  287. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  288. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  289. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.d.ts +30 -0
  290. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.d.ts.map +1 -1
  291. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.js +71 -14
  292. package/node_modules/@earendil-works/pi-ai/dist/utils/prompt-cache-ttl.js.map +1 -1
  293. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-name-match.d.ts +30 -0
  294. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-name-match.d.ts.map +1 -0
  295. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-name-match.js +71 -0
  296. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-name-match.js.map +1 -0
  297. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  298. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  299. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  300. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts +5 -0
  301. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts.map +1 -1
  302. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js +7 -2
  303. package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js.map +1 -1
  304. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
  305. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  306. package/node_modules/@earendil-works/pi-tui/dist/index.js +1 -1
  307. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  308. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  309. package/package.json +7 -7
  310. package/dist/bundle/chunks/chunk-KLDLZHHS.js +0 -11
  311. package/dist/bundle/chunks/chunk-LTIMMSDM.js +0 -8
  312. package/dist/bundle/chunks/chunk-XYM54ZWK.js +0 -2
  313. package/dist/bundle/chunks/cli-main-W55CWPEI.js +0 -3
  314. package/dist/bundle/chunks/interactive-mode-EDJZ4CSY.js +0 -2
  315. package/dist/bundle/chunks/openai-responses-7IGZSW33.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"finder.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/finder.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, posix, relative, resolve } from \"node:path\";\n\nimport {\n\tGLOBAL_DISTANCE,\n\tPROJECT_RULE_SUBDIRS,\n\tPROJECT_SINGLE_FILES,\n\tUSER_HOME_RULE_SUBDIRS,\n\tUSER_HOME_SINGLE_FILES,\n} from \"./constants.ts\";\nimport { UnsupportedRuleSourceError } from \"./errors.ts\";\nimport { scanRuleFiles } from \"./scanner.ts\";\nimport type { RuleCandidate, RuleSource } from \"./types.ts\";\n\ninterface SingleFileInfo {\n\tpath: string;\n\trealPath: string;\n}\n\nexport interface RuleDiscoveryCache {\n\tscannedRuleFiles: Map<string, ReturnType<typeof scanRuleFiles>>;\n\tsingleFileInfo: Map<string, SingleFileInfo | null>;\n}\n\nexport interface FinderOptions {\n\t/** Project root absolute path (use findProjectRoot to get this). */\n\tprojectRoot: string | null;\n\t/** Target file path (used for distance calculation in dynamic injection mode). null for static mode. */\n\ttargetFile: string | null;\n\t/** User home directory (default: os.homedir()). Injectable for tests. */\n\thomeDir?: string;\n\t/** Set of disabled sources to omit from discovery. Empty by default. */\n\tdisabledSources?: ReadonlySet<string>;\n\t/** Whether to skip user-home rules. Default: false. */\n\tskipUserHome?: boolean;\n\tcache?: RuleDiscoveryCache;\n}\n\ninterface WalkDirectory {\n\tdirectory: string;\n\tdistance: number;\n}\n\nexport function createRuleDiscoveryCache(): RuleDiscoveryCache {\n\treturn { scannedRuleFiles: new Map(), singleFileInfo: new Map() };\n}\n\nexport function findRuleCandidates(options: FinderOptions): RuleCandidate[] {\n\tconst skipUserHome = options.skipUserHome ?? false;\n\tif (options.projectRoot === null && skipUserHome) {\n\t\treturn [];\n\t}\n\n\tconst disabledSources = options.disabledSources ?? new Set<string>();\n\tconst candidates: RuleCandidate[] = [];\n\tconst homeDirectory = resolve(options.homeDir ?? homedir());\n\n\tif (options.projectRoot !== null) {\n\t\tcandidates.push(\n\t\t\t...findProjectCandidates(options.projectRoot, options.targetFile, disabledSources, options.cache),\n\t\t);\n\t}\n\n\tif (!skipUserHome) {\n\t\tcandidates.push(...findUserHomeCandidates(homeDirectory, disabledSources, options.cache));\n\t}\n\n\treturn candidates;\n}\n\nfunction findProjectCandidates(\n\tprojectRoot: string,\n\ttargetFile: string | null,\n\tdisabledSources: ReadonlySet<string>,\n\tcache: RuleDiscoveryCache | undefined,\n): RuleCandidate[] {\n\tconst rootDirectory = resolve(projectRoot);\n\tconst walkDirectories = getWalkDirectories(rootDirectory, targetFile);\n\tconst candidates: RuleCandidate[] = [];\n\n\tfor (const walkDirectory of walkDirectories) {\n\t\tfor (const [parentDirectory, subDirectory] of PROJECT_RULE_SUBDIRS) {\n\t\t\tconst source = toProjectRuleSource(parentDirectory, subDirectory);\n\t\t\tif (disabledSources.has(source)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst ruleDirectory = join(walkDirectory.directory, parentDirectory, subDirectory);\n\t\t\tfor (const scannedFile of scanRuleFilesCached(ruleDirectory, cache)) {\n\t\t\t\tcandidates.push({\n\t\t\t\t\tpath: scannedFile.path,\n\t\t\t\t\trealPath: resolveRealPath(scannedFile.path),\n\t\t\t\t\tsource,\n\t\t\t\t\tdistance: targetFile === null ? 0 : walkDirectory.distance,\n\t\t\t\t\tisGlobal: false,\n\t\t\t\t\tisSingleFile: false,\n\t\t\t\t\trelativePath: toRelativePath(rootDirectory, scannedFile.path),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const walkDirectory of walkDirectories) {\n\t\tfor (const ruleFile of PROJECT_SINGLE_FILES) {\n\t\t\tconst source = toProjectSingleFileSource(ruleFile);\n\t\t\tif (disabledSources.has(source)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst filePath = join(walkDirectory.directory, ruleFile);\n\t\t\tconst fileInfo = singleFileInfoCached(filePath, cache);\n\t\t\tif (fileInfo === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcandidates.push({\n\t\t\t\tpath: fileInfo.path,\n\t\t\t\trealPath: fileInfo.realPath,\n\t\t\t\tsource,\n\t\t\t\tdistance: targetFile === null ? 0 : walkDirectory.distance,\n\t\t\t\tisGlobal: false,\n\t\t\t\tisSingleFile: true,\n\t\t\t\trelativePath: toRelativePath(rootDirectory, filePath),\n\t\t\t});\n\t\t}\n\t}\n\n\treturn candidates;\n}\n\nfunction findUserHomeCandidates(\n\thomeDirectory: string,\n\tdisabledSources: ReadonlySet<string>,\n\tcache: RuleDiscoveryCache | undefined,\n): RuleCandidate[] {\n\tconst candidates: RuleCandidate[] = [];\n\n\tfor (const ruleSubdir of USER_HOME_RULE_SUBDIRS) {\n\t\tconst source = toUserHomeRuleSource(ruleSubdir);\n\t\tif (disabledSources.has(source)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ruleDirectory = join(homeDirectory, ruleSubdir);\n\t\tfor (const scannedFile of scanRuleFilesCached(ruleDirectory, cache)) {\n\t\t\tcandidates.push({\n\t\t\t\tpath: scannedFile.path,\n\t\t\t\trealPath: resolveRealPath(scannedFile.path),\n\t\t\t\tsource,\n\t\t\t\tdistance: GLOBAL_DISTANCE,\n\t\t\t\tisGlobal: true,\n\t\t\t\tisSingleFile: false,\n\t\t\t\trelativePath: toRelativePath(homeDirectory, scannedFile.path),\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const ruleFile of USER_HOME_SINGLE_FILES) {\n\t\tconst source = toUserHomeSingleFileSource(ruleFile);\n\t\tif (disabledSources.has(source)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst filePath = join(homeDirectory, ruleFile);\n\t\tconst fileInfo = singleFileInfoCached(filePath, cache);\n\t\tif (fileInfo === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tcandidates.push({\n\t\t\tpath: fileInfo.path,\n\t\t\trealPath: fileInfo.realPath,\n\t\t\tsource,\n\t\t\tdistance: GLOBAL_DISTANCE,\n\t\t\tisGlobal: true,\n\t\t\tisSingleFile: true,\n\t\t\trelativePath: toRelativePath(homeDirectory, filePath),\n\t\t});\n\t}\n\n\treturn candidates;\n}\n\nfunction scanRuleFilesCached(rootDir: string, cache: RuleDiscoveryCache | undefined): ReturnType<typeof scanRuleFiles> {\n\tif (cache === undefined) {\n\t\treturn scanRuleFiles({ rootDir });\n\t}\n\n\tconst cached = cache.scannedRuleFiles.get(rootDir);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\tconst scannedFiles = scanRuleFiles({ rootDir });\n\tcache.scannedRuleFiles.set(rootDir, scannedFiles);\n\treturn scannedFiles;\n}\n\nfunction singleFileInfoCached(filePath: string, cache: RuleDiscoveryCache | undefined): SingleFileInfo | null {\n\tif (cache === undefined) {\n\t\treturn readSingleFileInfo(filePath);\n\t}\n\n\tconst cached = cache.singleFileInfo.get(filePath);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\tconst fileInfo = readSingleFileInfo(filePath);\n\tcache.singleFileInfo.set(filePath, fileInfo);\n\treturn fileInfo;\n}\n\nfunction getWalkDirectories(projectRoot: string, targetFile: string | null): WalkDirectory[] {\n\tif (targetFile === null) {\n\t\treturn [{ directory: projectRoot, distance: 0 }];\n\t}\n\n\tconst startDirectory = dirname(resolve(targetFile));\n\tif (!isSameOrChildPath(startDirectory, projectRoot)) {\n\t\treturn [{ directory: projectRoot, distance: 0 }];\n\t}\n\n\tconst walkDirectories: WalkDirectory[] = [];\n\tlet currentDirectory = startDirectory;\n\tlet distance = 0;\n\n\twhile (true) {\n\t\twalkDirectories.push({ directory: currentDirectory, distance });\n\t\tif (currentDirectory === projectRoot) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst parentDirectory = dirname(currentDirectory);\n\t\tif (parentDirectory === currentDirectory) {\n\t\t\tbreak;\n\t\t}\n\n\t\tcurrentDirectory = parentDirectory;\n\t\tdistance += 1;\n\t}\n\n\treturn walkDirectories;\n}\n\nfunction isSameOrChildPath(childPath: string, parentPath: string): boolean {\n\tconst childRelativePath = relative(parentPath, childPath);\n\treturn childRelativePath === \"\" || (!childRelativePath.startsWith(\"..\") && !childRelativePath.startsWith(\"/\"));\n}\n\nfunction readSingleFileInfo(filePath: string): SingleFileInfo | null {\n\tif (!existsSync(filePath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tif (!statSync(filePath).isFile()) {\n\t\t\treturn null;\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tpath: filePath,\n\t\trealPath: resolveRealPath(filePath),\n\t};\n}\n\nfunction resolveRealPath(filePath: string): string {\n\ttry {\n\t\treturn realpathSync.native(filePath);\n\t} catch {\n\t\treturn filePath;\n\t}\n}\n\nfunction toRelativePath(rootDirectory: string, filePath: string): string {\n\treturn posix.normalize(relative(rootDirectory, filePath).replace(/\\\\/g, \"/\"));\n}\n\nfunction toProjectRuleSource(parentDirectory: string, subDirectory: string): RuleSource {\n\tconst source = `${parentDirectory}/${subDirectory}`;\n\tswitch (source) {\n\t\tcase \".omo/rules\":\n\t\tcase \".claude/rules\":\n\t\tcase \".cursor/rules\":\n\t\tcase \".github/instructions\":\n\t\t\treturn source;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported project rule source: ${source}`);\n\t}\n}\n\nfunction toProjectSingleFileSource(ruleFile: string): RuleSource {\n\tswitch (ruleFile) {\n\t\tcase \".github/copilot-instructions.md\":\n\t\tcase \"AGENTS.md\":\n\t\tcase \"CLAUDE.md\":\n\t\tcase \"CONTEXT.md\":\n\t\t\treturn ruleFile;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported project single-file source: ${ruleFile}`);\n\t}\n}\n\nfunction toUserHomeRuleSource(ruleSubdir: string): RuleSource {\n\tconst source = `~/${ruleSubdir}`;\n\tswitch (source) {\n\t\tcase \"~/.omo/rules\":\n\t\tcase \"~/.opencode/rules\":\n\t\tcase \"~/.claude/rules\":\n\t\t\treturn source;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported user-home rule source: ${source}`);\n\t}\n}\n\nfunction toUserHomeSingleFileSource(ruleFile: string): RuleSource {\n\tconst source = `~/${ruleFile}`;\n\tswitch (source) {\n\t\tcase \"~/.config/opencode/AGENTS.md\":\n\t\tcase \"~/.claude/CLAUDE.md\":\n\t\t\treturn source;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported user-home single-file source: ${source}`);\n\t}\n}\n"]}
1
+ {"version":3,"file":"finder.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/finder.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, posix, relative, resolve } from \"node:path\";\n\nimport {\n\tGLOBAL_DISTANCE,\n\tPROJECT_RULE_SUBDIRS,\n\tPROJECT_SINGLE_FILES,\n\tUSER_HOME_RULE_SUBDIRS,\n\tUSER_HOME_SINGLE_FILES,\n} from \"./constants.ts\";\nimport { UnsupportedRuleSourceError } from \"./errors.ts\";\nimport { scanRuleFiles } from \"./scanner.ts\";\nimport type { RuleCandidate, RuleSource } from \"./types.ts\";\n\ninterface SingleFileInfo {\n\tpath: string;\n\trealPath: string;\n}\n\nexport interface RuleDiscoveryCache {\n\tscannedRuleFiles: Map<string, ReturnType<typeof scanRuleFiles>>;\n\tsingleFileInfo: Map<string, SingleFileInfo | null>;\n}\n\nexport interface FinderOptions {\n\t/** Project root absolute path (use findProjectRoot to get this). */\n\tprojectRoot: string | null;\n\t/** Target file path (used for distance calculation in dynamic injection mode). null for static mode. */\n\ttargetFile: string | null;\n\t/** User home directory (default: os.homedir()). Injectable for tests. */\n\thomeDir?: string;\n\t/** Set of disabled sources to omit from discovery. Empty by default. */\n\tdisabledSources?: ReadonlySet<string>;\n\t/** Whether to skip user-home rules. Default: false. */\n\tskipUserHome?: boolean;\n\tcache?: RuleDiscoveryCache;\n}\n\ninterface WalkDirectory {\n\tdirectory: string;\n\tdistance: number;\n}\n\nexport function createRuleDiscoveryCache(): RuleDiscoveryCache {\n\treturn { scannedRuleFiles: new Map(), singleFileInfo: new Map() };\n}\n\nexport function findRuleCandidates(options: FinderOptions): RuleCandidate[] {\n\tconst skipUserHome = options.skipUserHome ?? false;\n\tif (options.projectRoot === null && skipUserHome) {\n\t\treturn [];\n\t}\n\n\tconst disabledSources = options.disabledSources ?? new Set<string>();\n\tconst candidates: RuleCandidate[] = [];\n\tconst homeDirectory = resolve(options.homeDir ?? homedir());\n\n\tif (options.projectRoot !== null) {\n\t\tcandidates.push(\n\t\t\t...findProjectCandidates(options.projectRoot, options.targetFile, disabledSources, options.cache),\n\t\t);\n\t}\n\n\tif (!skipUserHome) {\n\t\tcandidates.push(...findUserHomeCandidates(homeDirectory, disabledSources, options.cache));\n\t}\n\n\treturn candidates;\n}\n\nfunction findProjectCandidates(\n\tprojectRoot: string,\n\ttargetFile: string | null,\n\tdisabledSources: ReadonlySet<string>,\n\tcache: RuleDiscoveryCache | undefined,\n): RuleCandidate[] {\n\tconst rootDirectory = resolve(projectRoot);\n\tconst walkDirectories = getWalkDirectories(rootDirectory, targetFile);\n\tconst candidates: RuleCandidate[] = [];\n\n\tfor (const walkDirectory of walkDirectories) {\n\t\tfor (const [parentDirectory, subDirectory] of PROJECT_RULE_SUBDIRS) {\n\t\t\tconst source = toProjectRuleSource(parentDirectory, subDirectory);\n\t\t\tif (disabledSources.has(source)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst ruleDirectory = join(walkDirectory.directory, parentDirectory, subDirectory);\n\t\t\tfor (const scannedFile of scanRuleFilesCached(ruleDirectory, cache)) {\n\t\t\t\tcandidates.push({\n\t\t\t\t\tpath: scannedFile.path,\n\t\t\t\t\trealPath: resolveRealPath(scannedFile.path),\n\t\t\t\t\tsource,\n\t\t\t\t\tdistance: targetFile === null ? 0 : walkDirectory.distance,\n\t\t\t\t\tisGlobal: false,\n\t\t\t\t\tisSingleFile: false,\n\t\t\t\t\trelativePath: toRelativePath(rootDirectory, scannedFile.path),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const walkDirectory of walkDirectories) {\n\t\tfor (const ruleFile of PROJECT_SINGLE_FILES) {\n\t\t\tconst source = toProjectSingleFileSource(ruleFile);\n\t\t\tif (disabledSources.has(source)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst filePath = join(walkDirectory.directory, ruleFile);\n\t\t\tconst fileInfo = singleFileInfoCached(filePath, cache);\n\t\t\tif (fileInfo === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcandidates.push({\n\t\t\t\tpath: fileInfo.path,\n\t\t\t\trealPath: fileInfo.realPath,\n\t\t\t\tsource,\n\t\t\t\tdistance: targetFile === null ? 0 : walkDirectory.distance,\n\t\t\t\tisGlobal: false,\n\t\t\t\tisSingleFile: true,\n\t\t\t\trelativePath: toRelativePath(rootDirectory, filePath),\n\t\t\t});\n\t\t}\n\t}\n\n\treturn candidates;\n}\n\nfunction findUserHomeCandidates(\n\thomeDirectory: string,\n\tdisabledSources: ReadonlySet<string>,\n\tcache: RuleDiscoveryCache | undefined,\n): RuleCandidate[] {\n\tconst candidates: RuleCandidate[] = [];\n\n\tfor (const ruleSubdir of USER_HOME_RULE_SUBDIRS) {\n\t\tconst source = toUserHomeRuleSource(ruleSubdir);\n\t\tif (disabledSources.has(source)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst ruleDirectory = join(homeDirectory, ruleSubdir);\n\t\tfor (const scannedFile of scanRuleFilesCached(ruleDirectory, cache)) {\n\t\t\tcandidates.push({\n\t\t\t\tpath: scannedFile.path,\n\t\t\t\trealPath: resolveRealPath(scannedFile.path),\n\t\t\t\tsource,\n\t\t\t\tdistance: GLOBAL_DISTANCE,\n\t\t\t\tisGlobal: true,\n\t\t\t\tisSingleFile: false,\n\t\t\t\trelativePath: toRelativePath(homeDirectory, scannedFile.path),\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const ruleFile of USER_HOME_SINGLE_FILES) {\n\t\tconst source = toUserHomeSingleFileSource(ruleFile);\n\t\tif (disabledSources.has(source)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst filePath = join(homeDirectory, ruleFile);\n\t\tconst fileInfo = singleFileInfoCached(filePath, cache);\n\t\tif (fileInfo === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tcandidates.push({\n\t\t\tpath: fileInfo.path,\n\t\t\trealPath: fileInfo.realPath,\n\t\t\tsource,\n\t\t\tdistance: GLOBAL_DISTANCE,\n\t\t\tisGlobal: true,\n\t\t\tisSingleFile: true,\n\t\t\trelativePath: toRelativePath(homeDirectory, filePath),\n\t\t});\n\t\tbreak;\n\t}\n\n\treturn candidates;\n}\n\nfunction scanRuleFilesCached(rootDir: string, cache: RuleDiscoveryCache | undefined): ReturnType<typeof scanRuleFiles> {\n\tif (cache === undefined) {\n\t\treturn scanRuleFiles({ rootDir });\n\t}\n\n\tconst cached = cache.scannedRuleFiles.get(rootDir);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\tconst scannedFiles = scanRuleFiles({ rootDir });\n\tcache.scannedRuleFiles.set(rootDir, scannedFiles);\n\treturn scannedFiles;\n}\n\nfunction singleFileInfoCached(filePath: string, cache: RuleDiscoveryCache | undefined): SingleFileInfo | null {\n\tif (cache === undefined) {\n\t\treturn readSingleFileInfo(filePath);\n\t}\n\n\tconst cached = cache.singleFileInfo.get(filePath);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\tconst fileInfo = readSingleFileInfo(filePath);\n\tcache.singleFileInfo.set(filePath, fileInfo);\n\treturn fileInfo;\n}\n\nfunction getWalkDirectories(projectRoot: string, targetFile: string | null): WalkDirectory[] {\n\tif (targetFile === null) {\n\t\treturn [{ directory: projectRoot, distance: 0 }];\n\t}\n\n\tconst startDirectory = dirname(resolve(targetFile));\n\tif (!isSameOrChildPath(startDirectory, projectRoot)) {\n\t\treturn [{ directory: projectRoot, distance: 0 }];\n\t}\n\n\tconst walkDirectories: WalkDirectory[] = [];\n\tlet currentDirectory = startDirectory;\n\tlet distance = 0;\n\n\twhile (true) {\n\t\twalkDirectories.push({ directory: currentDirectory, distance });\n\t\tif (currentDirectory === projectRoot) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst parentDirectory = dirname(currentDirectory);\n\t\tif (parentDirectory === currentDirectory) {\n\t\t\tbreak;\n\t\t}\n\n\t\tcurrentDirectory = parentDirectory;\n\t\tdistance += 1;\n\t}\n\n\treturn walkDirectories;\n}\n\nfunction isSameOrChildPath(childPath: string, parentPath: string): boolean {\n\tconst childRelativePath = relative(parentPath, childPath);\n\treturn childRelativePath === \"\" || (!childRelativePath.startsWith(\"..\") && !childRelativePath.startsWith(\"/\"));\n}\n\nfunction readSingleFileInfo(filePath: string): SingleFileInfo | null {\n\tif (!existsSync(filePath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tif (!statSync(filePath).isFile()) {\n\t\t\treturn null;\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tpath: filePath,\n\t\trealPath: resolveRealPath(filePath),\n\t};\n}\n\nfunction resolveRealPath(filePath: string): string {\n\ttry {\n\t\treturn realpathSync.native(filePath);\n\t} catch {\n\t\treturn filePath;\n\t}\n}\n\nfunction toRelativePath(rootDirectory: string, filePath: string): string {\n\treturn posix.normalize(relative(rootDirectory, filePath).replace(/\\\\/g, \"/\"));\n}\n\nfunction toProjectRuleSource(parentDirectory: string, subDirectory: string): RuleSource {\n\tconst source = `${parentDirectory}/${subDirectory}`;\n\tswitch (source) {\n\t\tcase \".pi/rules\":\n\t\tcase \".omo/rules\":\n\t\tcase \".claude/rules\":\n\t\tcase \".cursor/rules\":\n\t\tcase \".github/instructions\":\n\t\t\treturn source;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported project rule source: ${source}`);\n\t}\n}\n\nfunction toProjectSingleFileSource(ruleFile: string): RuleSource {\n\tswitch (ruleFile) {\n\t\tcase \".github/copilot-instructions.md\":\n\t\tcase \"AGENTS.md\":\n\t\tcase \"CLAUDE.md\":\n\t\tcase \"CONTEXT.md\":\n\t\t\treturn ruleFile;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported project single-file source: ${ruleFile}`);\n\t}\n}\n\nfunction toUserHomeRuleSource(ruleSubdir: string): RuleSource {\n\tconst source = `~/${ruleSubdir}`;\n\tswitch (source) {\n\t\tcase \"~/.pi/rules\":\n\t\tcase \"~/.omo/rules\":\n\t\tcase \"~/.opencode/rules\":\n\t\tcase \"~/.claude/rules\":\n\t\t\treturn source;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported user-home rule source: ${source}`);\n\t}\n}\n\nfunction toUserHomeSingleFileSource(ruleFile: string): RuleSource {\n\tconst source = `~/${ruleFile}`;\n\tswitch (source) {\n\t\tcase \"~/.config/opencode/AGENTS.md\":\n\t\tcase \"~/.claude/CLAUDE.md\":\n\t\t\treturn source;\n\t\tdefault:\n\t\t\tthrow new UnsupportedRuleSourceError(`Unsupported user-home single-file source: ${source}`);\n\t}\n}\n"]}
@@ -1,2 +1,19 @@
1
1
  export declare function findProjectRoot(startPath: string, markers?: ReadonlyArray<string>): string | null;
2
+ /**
3
+ * Widen a marker-based project root to the enclosing git repository root.
4
+ *
5
+ * Monorepos (e.g. Cargo workspaces, pnpm workspaces) nest project markers: a
6
+ * file inside `crates/<member>/src/` resolves its project root to the member
7
+ * crate (`crates/<member>/Cargo.toml`), which stops the rule walk before it
8
+ * reaches workspace-level `.github/instructions/` directories. Walking up to
9
+ * the innermost `.git` instead lets rules placed at repository, workspace or
10
+ * member level all participate — the scopeRelative path base keeps each rule's
11
+ * glob semantics keyed to the directory that owns the rule file.
12
+ *
13
+ * A `.git` in the user's home directory (dotfiles repositories) is ignored: it
14
+ * is not a meaningful rule boundary and would otherwise leak rules from `~`
15
+ * into every marker-less project below it. When no `.git` exists above, the
16
+ * project root is returned unchanged (plain upstream behaviour).
17
+ */
18
+ export declare function widenToRepositoryRoot(projectRoot: string | null): string | null;
2
19
  //# sourceMappingURL=project-root.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/project-root.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,aAAa,CAAC,MAAM,CAAmB,GAAG,MAAM,GAAG,IAAI,CA+BlH"}
1
+ {"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/project-root.ts"],"names":[],"mappings":"AAMA,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,aAAa,CAAC,MAAM,CAAmB,GAAG,MAAM,GAAG,IAAI,CA2ClH;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CA6B/E"}
@@ -1,13 +1,27 @@
1
- import { existsSync, statSync } from "node:fs";
1
+ import { existsSync, realpathSync, statSync } from "node:fs";
2
+ import { homedir } from "node:os";
2
3
  import { dirname, join, resolve } from "node:path";
3
4
  import { PROJECT_MARKERS } from "./constants.js";
4
5
  export function findProjectRoot(startPath, markers = PROJECT_MARKERS) {
5
- const resolvedStartPath = resolve(startPath);
6
- if (!existsSync(resolvedStartPath)) {
6
+ const normalizedStartPath = resolve(startPath);
7
+ if (!existsSync(normalizedStartPath)) {
8
+ return null;
9
+ }
10
+ let resolvedStartPath;
11
+ try {
12
+ resolvedStartPath = realpathSync.native(normalizedStartPath);
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ let currentDirectory;
18
+ try {
19
+ const startStats = statSync(resolvedStartPath);
20
+ currentDirectory = startStats.isDirectory() ? resolvedStartPath : dirname(resolvedStartPath);
21
+ }
22
+ catch {
7
23
  return null;
8
24
  }
9
- const startStats = statSync(resolvedStartPath);
10
- let currentDirectory = startStats.isDirectory() ? resolvedStartPath : dirname(resolvedStartPath);
11
25
  const filesystemRoot = resolve("/");
12
26
  while (true) {
13
27
  for (const marker of markers) {
@@ -28,4 +42,52 @@ export function findProjectRoot(startPath, markers = PROJECT_MARKERS) {
28
42
  currentDirectory = parentDirectory;
29
43
  }
30
44
  }
45
+ /**
46
+ * Widen a marker-based project root to the enclosing git repository root.
47
+ *
48
+ * Monorepos (e.g. Cargo workspaces, pnpm workspaces) nest project markers: a
49
+ * file inside `crates/<member>/src/` resolves its project root to the member
50
+ * crate (`crates/<member>/Cargo.toml`), which stops the rule walk before it
51
+ * reaches workspace-level `.github/instructions/` directories. Walking up to
52
+ * the innermost `.git` instead lets rules placed at repository, workspace or
53
+ * member level all participate — the scopeRelative path base keeps each rule's
54
+ * glob semantics keyed to the directory that owns the rule file.
55
+ *
56
+ * A `.git` in the user's home directory (dotfiles repositories) is ignored: it
57
+ * is not a meaningful rule boundary and would otherwise leak rules from `~`
58
+ * into every marker-less project below it. When no `.git` exists above, the
59
+ * project root is returned unchanged (plain upstream behaviour).
60
+ */
61
+ export function widenToRepositoryRoot(projectRoot) {
62
+ if (projectRoot === null) {
63
+ return null;
64
+ }
65
+ const repositoryFilesystemRoot = resolve("/");
66
+ const homeDirectory = resolveExistingPath(homedir());
67
+ let currentDirectory = resolveExistingPath(projectRoot);
68
+ while (true) {
69
+ if (currentDirectory === homeDirectory) {
70
+ return projectRoot;
71
+ }
72
+ if (existsSync(join(currentDirectory, ".git"))) {
73
+ return currentDirectory;
74
+ }
75
+ if (currentDirectory === repositoryFilesystemRoot) {
76
+ return projectRoot;
77
+ }
78
+ const parentDirectory = dirname(currentDirectory);
79
+ if (parentDirectory === currentDirectory) {
80
+ return projectRoot;
81
+ }
82
+ currentDirectory = parentDirectory;
83
+ }
84
+ }
85
+ function resolveExistingPath(path) {
86
+ try {
87
+ return realpathSync.native(resolve(path));
88
+ }
89
+ catch {
90
+ return resolve(path);
91
+ }
92
+ }
31
93
  //# sourceMappingURL=project-root.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-root.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/project-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,UAAU,eAAe,CAAC,SAAiB,EAAE,OAAO,GAA0B,eAAe;IAClG,MAAM,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAE7C,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAC/C,IAAI,gBAAgB,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACjG,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpC,OAAO,IAAI,EAAE,CAAC;QACb,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAChD,OAAO,gBAAgB,CAAC;YACzB,CAAC;QACF,CAAC;QAED,IAAI,gBAAgB,KAAK,cAAc,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAClD,6EAA6E;QAC7E,6EAA6E;QAC7E,8CAA8C;QAC9C,IAAI,eAAe,KAAK,gBAAgB,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACb,CAAC;QACD,gBAAgB,GAAG,eAAe,CAAC;IACpC,CAAC;AACF,CAAC","sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport { PROJECT_MARKERS } from \"./constants.ts\";\n\nexport function findProjectRoot(startPath: string, markers: ReadonlyArray<string> = PROJECT_MARKERS): string | null {\n\tconst resolvedStartPath = resolve(startPath);\n\n\tif (!existsSync(resolvedStartPath)) {\n\t\treturn null;\n\t}\n\n\tconst startStats = statSync(resolvedStartPath);\n\tlet currentDirectory = startStats.isDirectory() ? resolvedStartPath : dirname(resolvedStartPath);\n\tconst filesystemRoot = resolve(\"/\");\n\n\twhile (true) {\n\t\tfor (const marker of markers) {\n\t\t\tif (existsSync(join(currentDirectory, marker))) {\n\t\t\t\treturn currentDirectory;\n\t\t\t}\n\t\t}\n\n\t\tif (currentDirectory === filesystemRoot) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst parentDirectory = dirname(currentDirectory);\n\t\t// Cross-drive / UNC walk: dirname() of a drive root returns the root itself,\n\t\t// and a root on a different drive than cwd never equals resolve(\"/\"), so the\n\t\t// walk would spin forever without this guard.\n\t\tif (parentDirectory === currentDirectory) {\n\t\t\treturn null;\n\t\t}\n\t\tcurrentDirectory = parentDirectory;\n\t}\n}\n"]}
1
+ {"version":3,"file":"project-root.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/project-root.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport { PROJECT_MARKERS } from \"./constants.ts\";\n\nexport function findProjectRoot(startPath: string, markers: ReadonlyArray<string> = PROJECT_MARKERS): string | null {\n\tconst normalizedStartPath = resolve(startPath);\n\n\tif (!existsSync(normalizedStartPath)) {\n\t\treturn null;\n\t}\n\n\tlet resolvedStartPath: string;\n\ttry {\n\t\tresolvedStartPath = realpathSync.native(normalizedStartPath);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tlet currentDirectory: string;\n\ttry {\n\t\tconst startStats = statSync(resolvedStartPath);\n\t\tcurrentDirectory = startStats.isDirectory() ? resolvedStartPath : dirname(resolvedStartPath);\n\t} catch {\n\t\treturn null;\n\t}\n\tconst filesystemRoot = resolve(\"/\");\n\n\twhile (true) {\n\t\tfor (const marker of markers) {\n\t\t\tif (existsSync(join(currentDirectory, marker))) {\n\t\t\t\treturn currentDirectory;\n\t\t\t}\n\t\t}\n\n\t\tif (currentDirectory === filesystemRoot) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst parentDirectory = dirname(currentDirectory);\n\t\t// Cross-drive / UNC walk: dirname() of a drive root returns the root itself,\n\t\t// and a root on a different drive than cwd never equals resolve(\"/\"), so the\n\t\t// walk would spin forever without this guard.\n\t\tif (parentDirectory === currentDirectory) {\n\t\t\treturn null;\n\t\t}\n\t\tcurrentDirectory = parentDirectory;\n\t}\n}\n\n/**\n * Widen a marker-based project root to the enclosing git repository root.\n *\n * Monorepos (e.g. Cargo workspaces, pnpm workspaces) nest project markers: a\n * file inside `crates/<member>/src/` resolves its project root to the member\n * crate (`crates/<member>/Cargo.toml`), which stops the rule walk before it\n * reaches workspace-level `.github/instructions/` directories. Walking up to\n * the innermost `.git` instead lets rules placed at repository, workspace or\n * member level all participate — the scopeRelative path base keeps each rule's\n * glob semantics keyed to the directory that owns the rule file.\n *\n * A `.git` in the user's home directory (dotfiles repositories) is ignored: it\n * is not a meaningful rule boundary and would otherwise leak rules from `~`\n * into every marker-less project below it. When no `.git` exists above, the\n * project root is returned unchanged (plain upstream behaviour).\n */\nexport function widenToRepositoryRoot(projectRoot: string | null): string | null {\n\tif (projectRoot === null) {\n\t\treturn null;\n\t}\n\n\tconst repositoryFilesystemRoot = resolve(\"/\");\n\tconst homeDirectory = resolveExistingPath(homedir());\n\tlet currentDirectory = resolveExistingPath(projectRoot);\n\n\twhile (true) {\n\t\tif (currentDirectory === homeDirectory) {\n\t\t\treturn projectRoot;\n\t\t}\n\n\t\tif (existsSync(join(currentDirectory, \".git\"))) {\n\t\t\treturn currentDirectory;\n\t\t}\n\n\t\tif (currentDirectory === repositoryFilesystemRoot) {\n\t\t\treturn projectRoot;\n\t\t}\n\n\t\tconst parentDirectory = dirname(currentDirectory);\n\t\tif (parentDirectory === currentDirectory) {\n\t\t\treturn projectRoot;\n\t\t}\n\n\t\tcurrentDirectory = parentDirectory;\n\t}\n}\n\nfunction resolveExistingPath(path: string): string {\n\ttry {\n\t\treturn realpathSync.native(resolve(path));\n\t} catch {\n\t\treturn resolve(path);\n\t}\n}\n"]}
@@ -70,7 +70,7 @@ export interface LoadedRule extends RuleCandidate {
70
70
  /**
71
71
  * Source identifier for rule files. Used for deterministic ordering and display.
72
72
  */
73
- export type RuleSource = ".omo/rules" | ".claude/rules" | ".cursor/rules" | ".github/instructions" | ".github/copilot-instructions.md" | "AGENTS.md" | "CLAUDE.md" | "CONTEXT.md" | "~/.omo/rules" | "~/.opencode/rules" | "~/.claude/rules" | "~/.config/opencode/AGENTS.md" | "~/.claude/CLAUDE.md";
73
+ export type RuleSource = ".pi/rules" | ".omo/rules" | ".claude/rules" | ".cursor/rules" | ".github/instructions" | ".github/copilot-instructions.md" | "AGENTS.md" | "CLAUDE.md" | "CONTEXT.md" | "~/.pi/rules" | "~/.omo/rules" | "~/.opencode/rules" | "~/.claude/rules" | "~/.config/opencode/AGENTS.md" | "~/.claude/CLAUDE.md";
74
74
  /**
75
75
  * Why a candidate matched the target file. Surfaced in the injection block so
76
76
  * the model can attribute its behavior to a specific rule.
@@ -90,7 +90,7 @@ export interface TruncationResult {
90
90
  originalLength: number;
91
91
  }
92
92
  /**
93
- * Configuration knobs resolved from environment variables.
93
+ * Configuration knobs resolved from defaults, environment variables, and CLI flags.
94
94
  */
95
95
  export interface PiRulesConfig {
96
96
  disabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IAC1B,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,aAAa;IAChD,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GACnB,YAAY,GACZ,eAAe,GACf,eAAe,GACf,sBAAsB,GACtB,iCAAiC,GACjC,WAAW,GACX,WAAW,GACX,YAAY,GACZ,cAAc,GACd,mBAAmB,GACnB,iBAAiB,GACjB,8BAA8B,GAC9B,qBAAqB,CAAC;AAEzB;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEnH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,yBAAyB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IAC1B,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,aAAa;IAChD,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GACnB,WAAW,GACX,YAAY,GACZ,eAAe,GACf,eAAe,GACf,sBAAsB,GACtB,iCAAiC,GACjC,WAAW,GACX,WAAW,GACX,YAAY,GACZ,aAAa,GACb,cAAc,GACd,mBAAmB,GACnB,iBAAiB,GACjB,8BAA8B,GAC9B,qBAAqB,CAAC;AAEzB;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEnH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,yBAAyB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Public types for pi-rules.\n *\n * These types are stable contracts between modules. The frontmatter type\n * mirrors omo's `RuleMetadata` plus Claude (`paths`) and Copilot (`applyTo`)\n * aliases that are normalized into `globs` internally.\n */\n\n/**\n * YAML frontmatter parsed from a rule markdown file.\n * `paths` (Claude alias) and `applyTo` (Copilot alias) are normalized into\n * `globs` by the parser before any matcher sees this struct.\n */\nexport interface RuleFrontmatter {\n\tdescription?: string;\n\tglobs?: string | string[];\n\tpaths?: string | string[];\n\tapplyTo?: string | string[];\n\talwaysApply?: boolean;\n}\n\n/**\n * Result of parsing a rule markdown file.\n * `body` excludes the frontmatter delimiters and the YAML payload.\n */\nexport interface ParsedRule {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\t/**\n\t * Diagnostic message if frontmatter parsing failed but the body was salvaged.\n\t * Empty when parsing succeeded.\n\t */\n\tdiagnostic?: string;\n}\n\n/**\n * A discovered rule file candidate before parsing/matching.\n *\n * `path` is the absolute path as discovered (possibly via symlink).\n * `realPath` is the canonical resolved path used for dedup.\n * `source` identifies which discovery source produced this candidate.\n */\nexport interface RuleCandidate {\n\tpath: string;\n\trealPath: string;\n\tsource: RuleSource;\n\t/**\n\t * Distance from the target file directory to the directory containing this rule.\n\t * 0 = same directory, 9999 = global/user-home rule.\n\t */\n\tdistance: number;\n\tisGlobal: boolean;\n\t/**\n\t * True when this candidate is a SINGLE-FILE rule like AGENTS.md or\n\t * `.github/copilot-instructions.md` (frontmatter optional, applies always).\n\t */\n\tisSingleFile: boolean;\n\t/**\n\t * Path relative to project root, POSIX-normalized. Used for matcher and display.\n\t * Empty string for user-home global rules.\n\t */\n\trelativePath: string;\n}\n\n/**\n * A fully-loaded rule ready for injection.\n */\nexport interface LoadedRule extends RuleCandidate {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\tcontentHash: string;\n\tmatchReason: MatchReason;\n}\n\n/**\n * Source identifier for rule files. Used for deterministic ordering and display.\n */\nexport type RuleSource =\n\t| \".omo/rules\"\n\t| \".claude/rules\"\n\t| \".cursor/rules\"\n\t| \".github/instructions\"\n\t| \".github/copilot-instructions.md\"\n\t| \"AGENTS.md\"\n\t| \"CLAUDE.md\"\n\t| \"CONTEXT.md\"\n\t| \"~/.omo/rules\"\n\t| \"~/.opencode/rules\"\n\t| \"~/.claude/rules\"\n\t| \"~/.config/opencode/AGENTS.md\"\n\t| \"~/.claude/CLAUDE.md\";\n\n/**\n * Why a candidate matched the target file. Surfaced in the injection block so\n * the model can attribute its behavior to a specific rule.\n */\nexport type MatchReason = \"alwaysApply\" | \"single-file\" | { kind: \"glob\"; pattern: string } | { kind: \"no-match\" };\n\n/**\n * Truncation result.\n */\nexport interface TruncationResult {\n\tbody: string;\n\ttruncated: boolean;\n\toriginalLength: number;\n}\n\n/**\n * Configuration knobs resolved from environment variables.\n */\nexport interface PiRulesConfig {\n\tdisabled: boolean;\n\tmode: \"static\" | \"dynamic\" | \"both\" | \"off\";\n\tmaxRuleChars: number;\n\tmaxResultChars: number;\n\tenabledSources: RuleSource[] | \"auto\";\n}\n\n/**\n * Per-session in-memory dedup state.\n *\n * `staticDedup` keys are `{cwd}::{rulePath}::{contentHash}` strings.\n * `dynamicDedup` stores `{targetPath}::{rulePath}::{contentHash}` strings grouped by target file.\n * `dynamicTargetFingerprints` maps a target file cache key to a digest of its\n * discovered rule candidates + file stats; loadDynamicRules short-circuits\n * targets whose fingerprint has not changed since the previous load.\n */\nexport interface SessionState {\n\tcwd: string | undefined;\n\tstaticDedup: Set<string>;\n\tdynamicDedup: Map<string, Set<string>>;\n\tdynamicTargetFingerprints: Map<string, string>;\n\tloadedRules: LoadedRule[];\n\tdiagnostics: RuleDiagnostic[];\n}\n\nexport interface RuleDiagnostic {\n\tseverity: \"warning\" | \"error\";\n\tsource: string;\n\tmessage: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Public types for pi-rules.\n *\n * These types are stable contracts between modules. The frontmatter type\n * mirrors omo's `RuleMetadata` plus Claude (`paths`) and Copilot (`applyTo`)\n * aliases that are normalized into `globs` internally.\n */\n\n/**\n * YAML frontmatter parsed from a rule markdown file.\n * `paths` (Claude alias) and `applyTo` (Copilot alias) are normalized into\n * `globs` by the parser before any matcher sees this struct.\n */\nexport interface RuleFrontmatter {\n\tdescription?: string;\n\tglobs?: string | string[];\n\tpaths?: string | string[];\n\tapplyTo?: string | string[];\n\talwaysApply?: boolean;\n}\n\n/**\n * Result of parsing a rule markdown file.\n * `body` excludes the frontmatter delimiters and the YAML payload.\n */\nexport interface ParsedRule {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\t/**\n\t * Diagnostic message if frontmatter parsing failed but the body was salvaged.\n\t * Empty when parsing succeeded.\n\t */\n\tdiagnostic?: string;\n}\n\n/**\n * A discovered rule file candidate before parsing/matching.\n *\n * `path` is the absolute path as discovered (possibly via symlink).\n * `realPath` is the canonical resolved path used for dedup.\n * `source` identifies which discovery source produced this candidate.\n */\nexport interface RuleCandidate {\n\tpath: string;\n\trealPath: string;\n\tsource: RuleSource;\n\t/**\n\t * Distance from the target file directory to the directory containing this rule.\n\t * 0 = same directory, 9999 = global/user-home rule.\n\t */\n\tdistance: number;\n\tisGlobal: boolean;\n\t/**\n\t * True when this candidate is a SINGLE-FILE rule like AGENTS.md or\n\t * `.github/copilot-instructions.md` (frontmatter optional, applies always).\n\t */\n\tisSingleFile: boolean;\n\t/**\n\t * Path relative to project root, POSIX-normalized. Used for matcher and display.\n\t * Empty string for user-home global rules.\n\t */\n\trelativePath: string;\n}\n\n/**\n * A fully-loaded rule ready for injection.\n */\nexport interface LoadedRule extends RuleCandidate {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\tcontentHash: string;\n\tmatchReason: MatchReason;\n}\n\n/**\n * Source identifier for rule files. Used for deterministic ordering and display.\n */\nexport type RuleSource =\n\t| \".pi/rules\"\n\t| \".omo/rules\"\n\t| \".claude/rules\"\n\t| \".cursor/rules\"\n\t| \".github/instructions\"\n\t| \".github/copilot-instructions.md\"\n\t| \"AGENTS.md\"\n\t| \"CLAUDE.md\"\n\t| \"CONTEXT.md\"\n\t| \"~/.pi/rules\"\n\t| \"~/.omo/rules\"\n\t| \"~/.opencode/rules\"\n\t| \"~/.claude/rules\"\n\t| \"~/.config/opencode/AGENTS.md\"\n\t| \"~/.claude/CLAUDE.md\";\n\n/**\n * Why a candidate matched the target file. Surfaced in the injection block so\n * the model can attribute its behavior to a specific rule.\n */\nexport type MatchReason = \"alwaysApply\" | \"single-file\" | { kind: \"glob\"; pattern: string } | { kind: \"no-match\" };\n\n/**\n * Truncation result.\n */\nexport interface TruncationResult {\n\tbody: string;\n\ttruncated: boolean;\n\toriginalLength: number;\n}\n\n/**\n * Configuration knobs resolved from defaults, environment variables, and CLI flags.\n */\nexport interface PiRulesConfig {\n\tdisabled: boolean;\n\tmode: \"static\" | \"dynamic\" | \"both\" | \"off\";\n\tmaxRuleChars: number;\n\tmaxResultChars: number;\n\tenabledSources: RuleSource[] | \"auto\";\n}\n\n/**\n * Per-session in-memory dedup state.\n *\n * `staticDedup` keys are `{cwd}::{rulePath}::{contentHash}` strings.\n * `dynamicDedup` stores `{targetPath}::{rulePath}::{contentHash}` strings grouped by target file.\n * `dynamicTargetFingerprints` maps a target file cache key to a digest of its\n * discovered rule candidates + file stats; loadDynamicRules short-circuits\n * targets whose fingerprint has not changed since the previous load.\n */\nexport interface SessionState {\n\tcwd: string | undefined;\n\tstaticDedup: Set<string>;\n\tdynamicDedup: Map<string, Set<string>>;\n\tdynamicTargetFingerprints: Map<string, string>;\n\tloadedRules: LoadedRule[];\n\tdiagnostics: RuleDiagnostic[];\n}\n\nexport interface RuleDiagnostic {\n\tseverity: \"warning\" | \"error\";\n\tsource: string;\n\tmessage: string;\n}\n"]}
@@ -4,7 +4,9 @@ import type { LoadedRule, RuleDiagnostic } from "../rules/types.ts";
4
4
  export interface RulesBannerProps {
5
5
  ruleCount: number;
6
6
  diagnostics: ReadonlyArray<RuleDiagnostic>;
7
- topRules?: ReadonlyArray<Pick<LoadedRule, "relativePath" | "matchReason">>;
7
+ topRules?: ReadonlyArray<Pick<LoadedRule, "relativePath" | "matchReason"> & {
8
+ path?: string;
9
+ }>;
8
10
  }
9
11
  export declare class RulesBanner extends Container {
10
12
  private readonly props;
@@ -1 +1 @@
1
- {"version":3,"file":"rules-banner.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/ui/rules-banner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iDAAiD,CAAC;AAE7E,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,GAAG,aAAa,CAAC,CAAC,CAAC;CAC3E;AAED,qBAAa,WAAY,SAAQ,SAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B,YAAY,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAIhD;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvC;IAEQ,UAAU,IAAI,IAAI,CAAG;CAC9B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAoChG;AAED,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAM3E"}
1
+ {"version":3,"file":"rules-banner.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/ui/rules-banner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iDAAiD,CAAC;AAE7E,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,GAAG,aAAa,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/F;AAED,qBAAa,WAAY,SAAQ,SAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B,YAAY,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAIhD;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvC;IAEQ,UAAU,IAAI,IAAI,CAAG;CAC9B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAsChG;AAED,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAM3E"}
@@ -20,7 +20,7 @@ export function renderBannerLines(props, theme, width) {
20
20
  }, { expanded: false }, theme).render(width);
21
21
  }
22
22
  const extra = (props.topRules ?? []).map((rule) => {
23
- const hasDiagnostic = props.diagnostics.some((diagnostic) => diagnostic.source === rule.relativePath);
23
+ const hasDiagnostic = props.diagnostics.some((diagnostic) => diagnostic.source === rule.path || diagnostic.source === rule.relativePath);
24
24
  const annotation = typeof rule.matchReason === "object" && rule.matchReason.kind === "glob" ? ` ${rule.matchReason.pattern}` : "";
25
25
  return {
26
26
  text: ` ${hasDiagnostic ? "⚠" : "●"} ${rule.relativePath}${annotation}`,
@@ -1 +1 @@
1
- {"version":3,"file":"rules-banner.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/ui/rules-banner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAmB,MAAM,0BAA0B,CAAC;AAS3E,MAAM,OAAO,WAAY,SAAQ,SAAS;IAIzC,YAAY,KAAuB,EAAE,KAAY;QAChD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAEQ,MAAM,CAAC,KAAa;QAC5B,OAAO,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC;IAEQ,UAAU,KAAU,CAAC;CAC9B;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAuB,EAAE,KAAY,EAAE,KAAa;IACrF,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,cAAc,CACpB;YACC,KAAK,EAAE,gCAAgC;YACvC,IAAI,EAAE,QAAQ;YACd,GAAG,EAAE,2BAA2B;SAChC,EACD,EAAE,QAAQ,EAAE,KAAK,EAAE,EACnB,KAAK,CACL,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,KAAK,GAAiB,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/D,MAAM,aAAa,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,KAAK,IAAI,CAAC,YAAY,CAAC,CAAC;QACtG,MAAM,UAAU,GACf,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChH,OAAO;YACN,IAAI,EAAE,KAAK,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,YAAY,GAAG,UAAU,EAAE;YACxE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAE,OAAiB,CAAC,CAAC,CAAE,SAAmB;SAC/D,CAAC;IACH,CAAC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,KAAK,CAAC,WAAW,CAAC,MAAM,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,OAAO,cAAc,CACpB;QACC,KAAK,EAAE,cAAc,KAAK,CAAC,SAAS,eAAe;QACnD,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,gCAAgC;QACvD,KAAK;KACL,EACD,EAAE,QAAQ,EAAE,KAAK,EAAE,EACnB,KAAK,CACL,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAOD,MAAM,UAAU,cAAc,CAAC,KAAsB,EAAE,KAAY;IAClE,MAAM,IAAI,GAAG,cAAc,KAAK,CAAC,SAAS,SAAS,CAAC;IACpD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC","sourcesContent":["import { Container } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../../../../modes/interactive/theme/theme.ts\";\nimport { buildNoticeBox, type NoticeLine } from \"../../../notice/index.ts\";\nimport type { LoadedRule, RuleDiagnostic } from \"../rules/types.ts\";\n\nexport interface RulesBannerProps {\n\truleCount: number;\n\tdiagnostics: ReadonlyArray<RuleDiagnostic>;\n\ttopRules?: ReadonlyArray<Pick<LoadedRule, \"relativePath\" | \"matchReason\">>;\n}\n\nexport class RulesBanner extends Container {\n\tprivate readonly props: RulesBannerProps;\n\tprivate readonly theme: Theme;\n\n\tconstructor(props: RulesBannerProps, theme: Theme) {\n\t\tsuper();\n\t\tthis.props = props;\n\t\tthis.theme = theme;\n\t}\n\n\toverride render(width: number): string[] {\n\t\treturn renderBannerLines(this.props, this.theme, width);\n\t}\n\n\toverride invalidate(): void {}\n}\n\nexport function renderBannerLines(props: RulesBannerProps, theme: Theme, width: number): string[] {\n\tif (props.ruleCount === 0) {\n\t\treturn buildNoticeBox(\n\t\t\t{\n\t\t\t\ttitle: \"[pi-rules] No rules discovered\",\n\t\t\t\ttone: \"accent\",\n\t\t\t\twhy: \"No rules were discovered.\",\n\t\t\t},\n\t\t\t{ expanded: false },\n\t\t\ttheme,\n\t\t).render(width);\n\t}\n\n\tconst extra: NoticeLine[] = (props.topRules ?? []).map((rule) => {\n\t\tconst hasDiagnostic = props.diagnostics.some((diagnostic) => diagnostic.source === rule.relativePath);\n\t\tconst annotation =\n\t\t\ttypeof rule.matchReason === \"object\" && rule.matchReason.kind === \"glob\" ? ` ${rule.matchReason.pattern}` : \"\";\n\t\treturn {\n\t\t\ttext: ` ${hasDiagnostic ? \"⚠\" : \"●\"} ${rule.relativePath}${annotation}`,\n\t\t\ttone: hasDiagnostic ? (\"error\" as const) : (\"success\" as const),\n\t\t};\n\t});\n\tif (props.diagnostics.length > 0) {\n\t\textra.push({ text: ` ⚠ ${props.diagnostics.length} warning(s)`, tone: \"warning\" });\n\t}\n\n\treturn buildNoticeBox(\n\t\t{\n\t\t\ttitle: `[pi-rules] ${props.ruleCount} active rules`,\n\t\t\ttone: \"accent\",\n\t\t\twhy: `${props.ruleCount} active rules were discovered.`,\n\t\t\textra,\n\t\t},\n\t\t{ expanded: false },\n\t\ttheme,\n\t).render(width);\n}\n\nexport interface StatusLineInput {\n\truleCount: number;\n\thasErrors: boolean;\n}\n\nexport function statusLineText(input: StatusLineInput, theme: Theme): string {\n\tconst base = `[pi-rules] ${input.ruleCount} active`;\n\tif (input.hasErrors) {\n\t\treturn theme.fg(\"muted\", `${base} · `) + theme.fg(\"error\", \"⚠ errors\");\n\t}\n\treturn theme.fg(\"muted\", base);\n}\n"]}
1
+ {"version":3,"file":"rules-banner.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/ui/rules-banner.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../../../../modes/interactive/theme/theme.ts\";\nimport { buildNoticeBox, type NoticeLine } from \"../../../notice/index.ts\";\nimport type { LoadedRule, RuleDiagnostic } from \"../rules/types.ts\";\n\nexport interface RulesBannerProps {\n\truleCount: number;\n\tdiagnostics: ReadonlyArray<RuleDiagnostic>;\n\ttopRules?: ReadonlyArray<Pick<LoadedRule, \"relativePath\" | \"matchReason\"> & { path?: string }>;\n}\n\nexport class RulesBanner extends Container {\n\tprivate readonly props: RulesBannerProps;\n\tprivate readonly theme: Theme;\n\n\tconstructor(props: RulesBannerProps, theme: Theme) {\n\t\tsuper();\n\t\tthis.props = props;\n\t\tthis.theme = theme;\n\t}\n\n\toverride render(width: number): string[] {\n\t\treturn renderBannerLines(this.props, this.theme, width);\n\t}\n\n\toverride invalidate(): void {}\n}\n\nexport function renderBannerLines(props: RulesBannerProps, theme: Theme, width: number): string[] {\n\tif (props.ruleCount === 0) {\n\t\treturn buildNoticeBox(\n\t\t\t{\n\t\t\t\ttitle: \"[pi-rules] No rules discovered\",\n\t\t\t\ttone: \"accent\",\n\t\t\t\twhy: \"No rules were discovered.\",\n\t\t\t},\n\t\t\t{ expanded: false },\n\t\t\ttheme,\n\t\t).render(width);\n\t}\n\n\tconst extra: NoticeLine[] = (props.topRules ?? []).map((rule) => {\n\t\tconst hasDiagnostic = props.diagnostics.some(\n\t\t\t(diagnostic) => diagnostic.source === rule.path || diagnostic.source === rule.relativePath,\n\t\t);\n\t\tconst annotation =\n\t\t\ttypeof rule.matchReason === \"object\" && rule.matchReason.kind === \"glob\" ? ` ${rule.matchReason.pattern}` : \"\";\n\t\treturn {\n\t\t\ttext: ` ${hasDiagnostic ? \"⚠\" : \"●\"} ${rule.relativePath}${annotation}`,\n\t\t\ttone: hasDiagnostic ? (\"error\" as const) : (\"success\" as const),\n\t\t};\n\t});\n\tif (props.diagnostics.length > 0) {\n\t\textra.push({ text: ` ⚠ ${props.diagnostics.length} warning(s)`, tone: \"warning\" });\n\t}\n\n\treturn buildNoticeBox(\n\t\t{\n\t\t\ttitle: `[pi-rules] ${props.ruleCount} active rules`,\n\t\t\ttone: \"accent\",\n\t\t\twhy: `${props.ruleCount} active rules were discovered.`,\n\t\t\textra,\n\t\t},\n\t\t{ expanded: false },\n\t\ttheme,\n\t).render(width);\n}\n\nexport interface StatusLineInput {\n\truleCount: number;\n\thasErrors: boolean;\n}\n\nexport function statusLineText(input: StatusLineInput, theme: Theme): string {\n\tconst base = `[pi-rules] ${input.ruleCount} active`;\n\tif (input.hasErrors) {\n\t\treturn theme.fg(\"muted\", `${base} · `) + theme.fg(\"error\", \"⚠ errors\");\n\t}\n\treturn theme.fg(\"muted\", base);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"todo-storage.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/todo-storage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAGN,KAAK,QAAQ,EACb,KAAK,SAAS,EAEd,MAAM,iBAAiB,CAAC;AAEzB,KAAK,WAAW,GAAG,YAAY,CAAC;AAiEhC,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAElD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,EAAE,CAErE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,EAAE,CAEnE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAE9D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,EAAE,CAErE;AAED,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE,CAmBpF;AAED,6EAA6E;AAC7E,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,CAElF"}
1
+ {"version":3,"file":"todo-storage.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/todo-storage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAGN,KAAK,QAAQ,EACb,KAAK,SAAS,EAEd,MAAM,iBAAiB,CAAC;AAEzB,KAAK,WAAW,GAAG,YAAY,CAAC;AAiEhC,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAElD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,EAAE,CAErE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAO5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,EAAE,CAEnE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAG9D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,EAAE,CAErE;AAED,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE,CAmBpF;AAED,6EAA6E;AAC7E,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,CAElF"}
@@ -77,13 +77,21 @@ export function clonePhases(phases) {
77
77
  return phases.map((phase) => ({ name: phase.name, tasks: phase.tasks.map(cloneTask) }));
78
78
  }
79
79
  export function isTodoItem(value) {
80
- return parseTodoItem(value) !== undefined;
80
+ // Strict guard: only the canonical TodoStatus values are accepted. Legacy
81
+ // statuses like "cancelled" are migrated to "abandoned" by the parse path
82
+ // (parseTodoItem/readTodoPayload), not by this guard, so a narrowed value's
83
+ // status is always a sound TodoStatus rather than the unchanged input.
84
+ if (!isRecord(value) || typeof value.content !== "string")
85
+ return false;
86
+ return isTodoStatus(value.status);
81
87
  }
82
88
  export function isTodoItemArray(value) {
83
89
  return Array.isArray(value) && value.every(isTodoItem);
84
90
  }
85
91
  export function isTodoPhase(value) {
86
- return parseTodoPhase(value) !== undefined;
92
+ if (!isRecord(value) || typeof value.name !== "string" || !Array.isArray(value.tasks))
93
+ return false;
94
+ return value.tasks.every(isTodoItem);
87
95
  }
88
96
  export function isTodoPhaseArray(value) {
89
97
  return Array.isArray(value) && value.every(isTodoPhase);
@@ -1 +1 @@
1
- {"version":3,"file":"todo-storage.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/todo-storage.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 type { SessionEntry } from \"../../../session-manager.ts\";\nimport {\n\tDEFAULT_INIT_PHASE,\n\tTODO_STATE_ENTRY_TYPE,\n\ttype TodoItem,\n\ttype TodoPhase,\n\ttype TodoStatus,\n} from \"./todo-types.ts\";\n\ntype BranchEntry = SessionEntry;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isTodoStatus(value: unknown): value is TodoStatus {\n\treturn value === \"pending\" || value === \"in_progress\" || value === \"completed\" || value === \"abandoned\";\n}\n\nfunction parseTodoStatus(value: unknown): TodoStatus | undefined {\n\tif (value === \"cancelled\") return \"abandoned\";\n\treturn isTodoStatus(value) ? value : undefined;\n}\n\nfunction parseTodoItem(value: unknown, options?: { lenient?: boolean }): TodoItem | undefined {\n\tif (!isRecord(value) || typeof value.content !== \"string\") return undefined;\n\tconst status = parseTodoStatus(value.status) ?? (options?.lenient ? \"pending\" : undefined);\n\treturn status ? { content: value.content, status } : undefined;\n}\n\nfunction parseTodoPhase(value: unknown): TodoPhase | undefined {\n\tif (!isRecord(value) || typeof value.name !== \"string\" || !Array.isArray(value.tasks)) return undefined;\n\tconst tasks: TodoItem[] = [];\n\tfor (const task of value.tasks) {\n\t\tconst parsed = parseTodoItem(task);\n\t\tif (!parsed) return undefined;\n\t\ttasks.push(parsed);\n\t}\n\treturn { name: value.name, tasks };\n}\n\nfunction parsePhases(value: unknown): TodoPhase[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst phases: TodoPhase[] = [];\n\tfor (const phase of value) {\n\t\tconst parsed = parseTodoPhase(phase);\n\t\tif (!parsed) return undefined;\n\t\tphases.push(parsed);\n\t}\n\treturn phases;\n}\n\nfunction parseLegacyTodos(value: unknown): TodoPhase[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst tasks: TodoItem[] = [];\n\tfor (const todo of value) {\n\t\t// Legacy todowrite persisted arbitrary status strings (e.g. \"blocked\").\n\t\t// Preserve those entries instead of dropping the whole list: unknown\n\t\t// statuses become \"pending\" so the task survives migration as open work.\n\t\tconst parsed = parseTodoItem(todo, { lenient: true });\n\t\tif (!parsed) return undefined;\n\t\ttasks.push(parsed);\n\t}\n\treturn [{ name: DEFAULT_INIT_PHASE, tasks }];\n}\n\nfunction readTodoPayload(value: unknown): TodoPhase[] | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (value.schema === \"v2\") return parsePhases(value.phases);\n\tif (Array.isArray(value.phases)) return parsePhases(value.phases);\n\tif (Array.isArray(value.todos)) return parseLegacyTodos(value.todos);\n\treturn undefined;\n}\n\nexport function cloneTask(task: TodoItem): TodoItem {\n\treturn { content: task.content, status: task.status };\n}\n\nexport function clonePhases(phases: readonly TodoPhase[]): TodoPhase[] {\n\treturn phases.map((phase) => ({ name: phase.name, tasks: phase.tasks.map(cloneTask) }));\n}\n\nexport function isTodoItem(value: unknown): value is TodoItem {\n\treturn parseTodoItem(value) !== undefined;\n}\n\nexport function isTodoItemArray(value: unknown): value is TodoItem[] {\n\treturn Array.isArray(value) && value.every(isTodoItem);\n}\n\nexport function isTodoPhase(value: unknown): value is TodoPhase {\n\treturn parseTodoPhase(value) !== undefined;\n}\n\nexport function isTodoPhaseArray(value: unknown): value is TodoPhase[] {\n\treturn Array.isArray(value) && value.every(isTodoPhase);\n}\n\nexport function getLatestPhasesFromBranchEntries(entries: BranchEntry[]): TodoPhase[] {\n\tlet phases: TodoPhase[] = [];\n\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"custom\" && entry.customType === TODO_STATE_ENTRY_TYPE) {\n\t\t\tconst parsed = readTodoPayload(entry.data);\n\t\t\tif (parsed) phases = clonePhases(parsed);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.type !== \"message\" || !isRecord(entry.message)) continue;\n\t\tif (entry.message.role !== \"toolResult\") continue;\n\t\tif (entry.message.toolName !== \"todo\" && entry.message.toolName !== \"todowrite\") continue;\n\n\t\tconst parsed = readTodoPayload(entry.message.details);\n\t\tif (parsed) phases = clonePhases(parsed);\n\t}\n\n\treturn phases;\n}\n\n/** Compatibility reader for callers that still expect the old flat array. */\nexport function getLatestTodosFromBranchEntries(entries: BranchEntry[]): TodoItem[] {\n\treturn getLatestPhasesFromBranchEntries(entries).flatMap((phase) => phase.tasks.map(cloneTask));\n}\n"]}
1
+ {"version":3,"file":"todo-storage.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/todotools/todo-storage.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 type { SessionEntry } from \"../../../session-manager.ts\";\nimport {\n\tDEFAULT_INIT_PHASE,\n\tTODO_STATE_ENTRY_TYPE,\n\ttype TodoItem,\n\ttype TodoPhase,\n\ttype TodoStatus,\n} from \"./todo-types.ts\";\n\ntype BranchEntry = SessionEntry;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isTodoStatus(value: unknown): value is TodoStatus {\n\treturn value === \"pending\" || value === \"in_progress\" || value === \"completed\" || value === \"abandoned\";\n}\n\nfunction parseTodoStatus(value: unknown): TodoStatus | undefined {\n\tif (value === \"cancelled\") return \"abandoned\";\n\treturn isTodoStatus(value) ? value : undefined;\n}\n\nfunction parseTodoItem(value: unknown, options?: { lenient?: boolean }): TodoItem | undefined {\n\tif (!isRecord(value) || typeof value.content !== \"string\") return undefined;\n\tconst status = parseTodoStatus(value.status) ?? (options?.lenient ? \"pending\" : undefined);\n\treturn status ? { content: value.content, status } : undefined;\n}\n\nfunction parseTodoPhase(value: unknown): TodoPhase | undefined {\n\tif (!isRecord(value) || typeof value.name !== \"string\" || !Array.isArray(value.tasks)) return undefined;\n\tconst tasks: TodoItem[] = [];\n\tfor (const task of value.tasks) {\n\t\tconst parsed = parseTodoItem(task);\n\t\tif (!parsed) return undefined;\n\t\ttasks.push(parsed);\n\t}\n\treturn { name: value.name, tasks };\n}\n\nfunction parsePhases(value: unknown): TodoPhase[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst phases: TodoPhase[] = [];\n\tfor (const phase of value) {\n\t\tconst parsed = parseTodoPhase(phase);\n\t\tif (!parsed) return undefined;\n\t\tphases.push(parsed);\n\t}\n\treturn phases;\n}\n\nfunction parseLegacyTodos(value: unknown): TodoPhase[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst tasks: TodoItem[] = [];\n\tfor (const todo of value) {\n\t\t// Legacy todowrite persisted arbitrary status strings (e.g. \"blocked\").\n\t\t// Preserve those entries instead of dropping the whole list: unknown\n\t\t// statuses become \"pending\" so the task survives migration as open work.\n\t\tconst parsed = parseTodoItem(todo, { lenient: true });\n\t\tif (!parsed) return undefined;\n\t\ttasks.push(parsed);\n\t}\n\treturn [{ name: DEFAULT_INIT_PHASE, tasks }];\n}\n\nfunction readTodoPayload(value: unknown): TodoPhase[] | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (value.schema === \"v2\") return parsePhases(value.phases);\n\tif (Array.isArray(value.phases)) return parsePhases(value.phases);\n\tif (Array.isArray(value.todos)) return parseLegacyTodos(value.todos);\n\treturn undefined;\n}\n\nexport function cloneTask(task: TodoItem): TodoItem {\n\treturn { content: task.content, status: task.status };\n}\n\nexport function clonePhases(phases: readonly TodoPhase[]): TodoPhase[] {\n\treturn phases.map((phase) => ({ name: phase.name, tasks: phase.tasks.map(cloneTask) }));\n}\n\nexport function isTodoItem(value: unknown): value is TodoItem {\n\t// Strict guard: only the canonical TodoStatus values are accepted. Legacy\n\t// statuses like \"cancelled\" are migrated to \"abandoned\" by the parse path\n\t// (parseTodoItem/readTodoPayload), not by this guard, so a narrowed value's\n\t// status is always a sound TodoStatus rather than the unchanged input.\n\tif (!isRecord(value) || typeof value.content !== \"string\") return false;\n\treturn isTodoStatus(value.status);\n}\n\nexport function isTodoItemArray(value: unknown): value is TodoItem[] {\n\treturn Array.isArray(value) && value.every(isTodoItem);\n}\n\nexport function isTodoPhase(value: unknown): value is TodoPhase {\n\tif (!isRecord(value) || typeof value.name !== \"string\" || !Array.isArray(value.tasks)) return false;\n\treturn value.tasks.every(isTodoItem);\n}\n\nexport function isTodoPhaseArray(value: unknown): value is TodoPhase[] {\n\treturn Array.isArray(value) && value.every(isTodoPhase);\n}\n\nexport function getLatestPhasesFromBranchEntries(entries: BranchEntry[]): TodoPhase[] {\n\tlet phases: TodoPhase[] = [];\n\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"custom\" && entry.customType === TODO_STATE_ENTRY_TYPE) {\n\t\t\tconst parsed = readTodoPayload(entry.data);\n\t\t\tif (parsed) phases = clonePhases(parsed);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.type !== \"message\" || !isRecord(entry.message)) continue;\n\t\tif (entry.message.role !== \"toolResult\") continue;\n\t\tif (entry.message.toolName !== \"todo\" && entry.message.toolName !== \"todowrite\") continue;\n\n\t\tconst parsed = readTodoPayload(entry.message.details);\n\t\tif (parsed) phases = clonePhases(parsed);\n\t}\n\n\treturn phases;\n}\n\n/** Compatibility reader for callers that still expect the old flat array. */\nexport function getLatestTodosFromBranchEntries(entries: BranchEntry[]): TodoItem[] {\n\treturn getLatestPhasesFromBranchEntries(entries).flatMap((phase) => phase.tasks.map(cloneTask));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"todo.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/todotools/tools/todo.ts"],"names":[],"mappings":"AAMA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAEX,YAAY,EACZ,gBAAgB,EAIhB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAUN,KAAK,wBAAwB,EAE7B,KAAK,SAAS,EAGd,MAAM,aAAa,CAAC;AAuBrB,eAAO,MAAM,kBAAkB;;;;;;;;;EAU7B,CAAC;AAIH,KAAK,aAAa,GAAG;IACpB,gBAAgB,EAAE,MAAM,SAAS,EAAE,CAAC;IACpC,gBAAgB,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,CAAC,GAAG,EAAE,gBAAgB,EAAE,cAAc,CAAC,EAAE,SAAS,wBAAwB,EAAE,KAAK,IAAI,CAAC;CAClG,CAAC;AA4CF,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CA0B/D;AAyID,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,GAAG,IAAI,CAyEjF"}
1
+ {"version":3,"file":"todo.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/todotools/tools/todo.ts"],"names":[],"mappings":"AAMA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAEX,YAAY,EACZ,gBAAgB,EAIhB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAUN,KAAK,wBAAwB,EAE7B,KAAK,SAAS,EAGd,MAAM,aAAa,CAAC;AAuBrB,eAAO,MAAM,kBAAkB;;;;;;;;;EAU7B,CAAC;AAIH,KAAK,aAAa,GAAG;IACpB,gBAAgB,EAAE,MAAM,SAAS,EAAE,CAAC;IACpC,gBAAgB,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,CAAC,GAAG,EAAE,gBAAgB,EAAE,cAAc,CAAC,EAAE,SAAS,wBAAwB,EAAE,KAAK,IAAI,CAAC;CAClG,CAAC;AA4CF,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CA0B/D;AAyID,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,GAAG,IAAI,CA0EjF"}
@@ -227,8 +227,9 @@ export function registerTodoTool(pi, accessors) {
227
227
  const entry = normalized.entry;
228
228
  const corrections = normalized.corrections;
229
229
  const readOnly = entry.op === "view";
230
+ const errors = [];
230
231
  const applied = readOnly
231
- ? { phases: previousPhases, errors: [] }
232
+ ? { phases: previousPhases, errors }
232
233
  : applyParams(clonePhases(previousPhases), entry, corrections);
233
234
  if (applied.errors.length > 0)
234
235
  throw new Error(formatSummary(previousPhases, applied.errors, readOnly));
@@ -1 +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 { partialStrikethrough, strikeRevealCount } from \"../../../../../modes/interactive/components/todo-strike.ts\";\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 { normalizeTodoParams } from \"../normalize.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 TodoOperation,\n\ttype TodoPhase,\n\ttype TodoStateEntry,\n\ttype TodoToolDetails,\n} from \"../state.ts\";\n\nconst TodoOperationSchema = Type.Union(\n\t[\n\t\tType.Literal(\"init\"),\n\t\tType.Literal(\"start\"),\n\t\tType.Literal(\"done\"),\n\t\tType.Literal(\"rm\"),\n\t\tType.Literal(\"drop\"),\n\t\tType.Literal(\"append\"),\n\t\tType.Literal(\"view\"),\n\t],\n\t{ description: \"Operation to perform. Required — always pass it explicitly.\" },\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: Type.Optional(TodoOperationSchema),\n\tlist: Type.Optional(Type.Array(TodoPhaseInputSchema, { description: \"Phased task list for init\" })),\n\ttask: Type.Optional(Type.String({ description: \"Exact task text copied from the previous todo result\" })),\n\tphase: Type.Optional(Type.String({ description: \"Exact phase name copied from the previous todo result\" })),\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(\n\t\tType.Array(Type.String({ description: \"Task content\" }), { description: \"Task texts to append\" }),\n\t),\n});\n\ntype TodoParams = Static<typeof TODO_PARAMS_SCHEMA>;\n\ntype TodoAccessors = {\n\tgetCurrentPhases: () => TodoPhase[];\n\tsetCurrentPhases: (phases: TodoPhase[]) => void;\n\tsyncWidget: (ctx: ExtensionContext, completedTasks?: readonly TodoCompletionTransition[]) => void;\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\t// Normalization can rescue a call that omitted `op`; label it generically until\n\t\t// execute resolves the effective operation. Listing `undefined` explicitly (instead\n\t\t// of `default`) keeps this switch exhaustive, so a new TodoOperation fails typecheck.\n\t\tcase undefined:\n\t\t\treturn \"todo\";\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(\n\ttask: TodoPhase[\"tasks\"][number],\n\ttheme: Theme,\n\tcompletionKeys: ReadonlySet<string>,\n\tframe: number | undefined,\n): 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\tconst reveal = completionKeys.has(task.content) ? strikeRevealCount(line, frame) : undefined;\n\t\t\treturn reveal === undefined\n\t\t\t\t? theme.fg(\"dim\", theme.strikethrough(line))\n\t\t\t\t: theme.fg(\n\t\t\t\t\t\t\"dim\",\n\t\t\t\t\t\tpartialStrikethrough(line, reveal, (text) => theme.strikethrough(text)),\n\t\t\t\t\t);\n\t\t}\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\toperation: TodoOperation | undefined,\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\t// Exhaustive over TodoOperation | undefined so adding an operation is a typecheck\n\t// failure here rather than a silent fall-through into target-scoped highlighting.\n\tswitch (operation) {\n\t\tcase \"init\":\n\t\t\tfor (const phase of phases) touched.add(phase.name);\n\t\t\tbreak;\n\t\tcase \"start\":\n\t\tcase \"done\":\n\t\tcase \"drop\":\n\t\tcase \"rm\":\n\t\tcase \"append\":\n\t\tcase \"view\":\n\t\tcase undefined: {\n\t\t\tif (args.phase) {\n\t\t\t\tconst phase = phases.find((candidate) => candidate.name === args.phase);\n\t\t\t\tif (phase) touched.add(phase.name);\n\t\t\t}\n\t\t\tif (args.task) {\n\t\t\t\tconst hit = findTaskByContent([...phases], args.task);\n\t\t\t\tif (hit) touched.add(hit.phase.name);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = operation;\n\t\t\treturn touched.size > 0 ? touched : null;\n\t\t}\n\t}\n\treturn touched.size > 0 ? touched : null;\n}\n\nconst EMPTY_SET: ReadonlySet<string> = new Set();\n\nfunction renderTodoPhases(\n\tphases: readonly TodoPhase[],\n\tcompletedTasks: readonly TodoCompletionTransition[],\n\toptions: ToolRenderResultOptions,\n\targs: TodoParams,\n\toperation: TodoOperation | undefined,\n\ttheme: Theme,\n\tframe: number | undefined,\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\n\t\t\t? null\n\t\t\t: computeTouchedPhases(args, operation, visiblePhases, completedTasks);\n\tconst completionKeysByPhase = new Map<string, Set<string>>();\n\tfor (const transition of completedTasks) {\n\t\tlet completionKeys = completionKeysByPhase.get(transition.phase);\n\t\tif (!completionKeys) {\n\t\t\tcompletionKeys = new Set();\n\t\t\tcompletionKeysByPhase.set(transition.phase, completionKeys);\n\t\t}\n\t\tcompletionKeys.add(transition.content);\n\t}\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\tconst completionKeys = completionKeysByPhase.get(phase.name) ?? EMPTY_SET;\n\t\tfor (const task of phase.tasks) lines.push(` ${formatTaskLine(task, theme, completionKeys, frame)}`);\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<AgentToolResult<TodoToolDetails>> {\n\t\t\tconst previousPhases = clonePhases(accessors.getCurrentPhases());\n\t\t\tconst normalized = normalizeTodoParams(params as Record<string, unknown>, previousPhases);\n\t\t\tif (normalized.error || !normalized.entry) {\n\t\t\t\tconst error =\n\t\t\t\t\tnormalized.error ?? 'Missing \"op\". Example: {\"op\":\"init\",\"list\":[{\"phase\":\"Setup\",\"items\":[\"...\"]}]}';\n\t\t\t\tthrow new Error(`${error}\\n\\n${formatSummary(previousPhases, [], true)}`);\n\t\t\t}\n\t\t\tconst entry = normalized.entry;\n\t\t\tconst corrections = normalized.corrections;\n\t\t\tconst readOnly = entry.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), entry, corrections);\n\t\t\tif (applied.errors.length > 0) throw new Error(formatSummary(previousPhases, applied.errors, readOnly));\n\t\t\tconst completedTasks = readOnly ? [] : getCompletionTransitions(previousPhases, applied.phases);\n\t\t\tif (!readOnly) {\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, completedTasks);\n\t\t\t}\n\n\t\t\tconst details: TodoToolDetails = {\n\t\t\t\top: entry.op,\n\t\t\t\tphases: clonePhases(applied.phases),\n\t\t\t\tstorage: ctx.sessionManager.getSessionFile() ? \"session\" : \"memory\",\n\t\t\t};\n\t\t\tif (corrections.length > 0) details.corrections = corrections;\n\t\t\tif (completedTasks.length > 0) details.completedTasks = completedTasks;\n\t\t\tconst summary = formatSummary(applied.phases, [], readOnly);\n\t\t\tconst text = corrections.length > 0 ? `${corrections.join(\"\\n\")}\\n\\n${summary}` : summary;\n\n\t\t\treturn { content: [{ type: \"text\", text }], details };\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 (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(\n\t\t\t\tphases,\n\t\t\t\tresult.details?.completedTasks ?? [],\n\t\t\t\toptions,\n\t\t\t\tcontext.args,\n\t\t\t\tresult.details?.op,\n\t\t\t\ttheme,\n\t\t\t\tcontext.spinnerFrame,\n\t\t\t);\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"]}
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 { partialStrikethrough, strikeRevealCount } from \"../../../../../modes/interactive/components/todo-strike.ts\";\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 { normalizeTodoParams } from \"../normalize.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 TodoOperation,\n\ttype TodoPhase,\n\ttype TodoStateEntry,\n\ttype TodoToolDetails,\n} from \"../state.ts\";\n\nconst TodoOperationSchema = Type.Union(\n\t[\n\t\tType.Literal(\"init\"),\n\t\tType.Literal(\"start\"),\n\t\tType.Literal(\"done\"),\n\t\tType.Literal(\"rm\"),\n\t\tType.Literal(\"drop\"),\n\t\tType.Literal(\"append\"),\n\t\tType.Literal(\"view\"),\n\t],\n\t{ description: \"Operation to perform. Required — always pass it explicitly.\" },\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: Type.Optional(TodoOperationSchema),\n\tlist: Type.Optional(Type.Array(TodoPhaseInputSchema, { description: \"Phased task list for init\" })),\n\ttask: Type.Optional(Type.String({ description: \"Exact task text copied from the previous todo result\" })),\n\tphase: Type.Optional(Type.String({ description: \"Exact phase name copied from the previous todo result\" })),\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(\n\t\tType.Array(Type.String({ description: \"Task content\" }), { description: \"Task texts to append\" }),\n\t),\n});\n\ntype TodoParams = Static<typeof TODO_PARAMS_SCHEMA>;\n\ntype TodoAccessors = {\n\tgetCurrentPhases: () => TodoPhase[];\n\tsetCurrentPhases: (phases: TodoPhase[]) => void;\n\tsyncWidget: (ctx: ExtensionContext, completedTasks?: readonly TodoCompletionTransition[]) => void;\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\t// Normalization can rescue a call that omitted `op`; label it generically until\n\t\t// execute resolves the effective operation. Listing `undefined` explicitly (instead\n\t\t// of `default`) keeps this switch exhaustive, so a new TodoOperation fails typecheck.\n\t\tcase undefined:\n\t\t\treturn \"todo\";\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(\n\ttask: TodoPhase[\"tasks\"][number],\n\ttheme: Theme,\n\tcompletionKeys: ReadonlySet<string>,\n\tframe: number | undefined,\n): 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\tconst reveal = completionKeys.has(task.content) ? strikeRevealCount(line, frame) : undefined;\n\t\t\treturn reveal === undefined\n\t\t\t\t? theme.fg(\"dim\", theme.strikethrough(line))\n\t\t\t\t: theme.fg(\n\t\t\t\t\t\t\"dim\",\n\t\t\t\t\t\tpartialStrikethrough(line, reveal, (text) => theme.strikethrough(text)),\n\t\t\t\t\t);\n\t\t}\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\toperation: TodoOperation | undefined,\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\t// Exhaustive over TodoOperation | undefined so adding an operation is a typecheck\n\t// failure here rather than a silent fall-through into target-scoped highlighting.\n\tswitch (operation) {\n\t\tcase \"init\":\n\t\t\tfor (const phase of phases) touched.add(phase.name);\n\t\t\tbreak;\n\t\tcase \"start\":\n\t\tcase \"done\":\n\t\tcase \"drop\":\n\t\tcase \"rm\":\n\t\tcase \"append\":\n\t\tcase \"view\":\n\t\tcase undefined: {\n\t\t\tif (args.phase) {\n\t\t\t\tconst phase = phases.find((candidate) => candidate.name === args.phase);\n\t\t\t\tif (phase) touched.add(phase.name);\n\t\t\t}\n\t\t\tif (args.task) {\n\t\t\t\tconst hit = findTaskByContent([...phases], args.task);\n\t\t\t\tif (hit) touched.add(hit.phase.name);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = operation;\n\t\t\treturn touched.size > 0 ? touched : null;\n\t\t}\n\t}\n\treturn touched.size > 0 ? touched : null;\n}\n\nconst EMPTY_SET: ReadonlySet<string> = new Set();\n\nfunction renderTodoPhases(\n\tphases: readonly TodoPhase[],\n\tcompletedTasks: readonly TodoCompletionTransition[],\n\toptions: ToolRenderResultOptions,\n\targs: TodoParams,\n\toperation: TodoOperation | undefined,\n\ttheme: Theme,\n\tframe: number | undefined,\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\n\t\t\t? null\n\t\t\t: computeTouchedPhases(args, operation, visiblePhases, completedTasks);\n\tconst completionKeysByPhase = new Map<string, Set<string>>();\n\tfor (const transition of completedTasks) {\n\t\tlet completionKeys = completionKeysByPhase.get(transition.phase);\n\t\tif (!completionKeys) {\n\t\t\tcompletionKeys = new Set();\n\t\t\tcompletionKeysByPhase.set(transition.phase, completionKeys);\n\t\t}\n\t\tcompletionKeys.add(transition.content);\n\t}\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\tconst completionKeys = completionKeysByPhase.get(phase.name) ?? EMPTY_SET;\n\t\tfor (const task of phase.tasks) lines.push(` ${formatTaskLine(task, theme, completionKeys, frame)}`);\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<AgentToolResult<TodoToolDetails>> {\n\t\t\tconst previousPhases = clonePhases(accessors.getCurrentPhases());\n\t\t\tconst normalized = normalizeTodoParams(params as Record<string, unknown>, previousPhases);\n\t\t\tif (normalized.error || !normalized.entry) {\n\t\t\t\tconst error =\n\t\t\t\t\tnormalized.error ?? 'Missing \"op\". Example: {\"op\":\"init\",\"list\":[{\"phase\":\"Setup\",\"items\":[\"...\"]}]}';\n\t\t\t\tthrow new Error(`${error}\\n\\n${formatSummary(previousPhases, [], true)}`);\n\t\t\t}\n\t\t\tconst entry = normalized.entry;\n\t\t\tconst corrections = normalized.corrections;\n\t\t\tconst readOnly = entry.op === \"view\";\n\t\t\tconst errors: string[] = [];\n\t\t\tconst applied = readOnly\n\t\t\t\t? { phases: previousPhases, errors }\n\t\t\t\t: applyParams(clonePhases(previousPhases), entry, corrections);\n\t\t\tif (applied.errors.length > 0) throw new Error(formatSummary(previousPhases, applied.errors, readOnly));\n\t\t\tconst completedTasks = readOnly ? [] : getCompletionTransitions(previousPhases, applied.phases);\n\t\t\tif (!readOnly) {\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, completedTasks);\n\t\t\t}\n\n\t\t\tconst details: TodoToolDetails = {\n\t\t\t\top: entry.op,\n\t\t\t\tphases: clonePhases(applied.phases),\n\t\t\t\tstorage: ctx.sessionManager.getSessionFile() ? \"session\" : \"memory\",\n\t\t\t};\n\t\t\tif (corrections.length > 0) details.corrections = corrections;\n\t\t\tif (completedTasks.length > 0) details.completedTasks = completedTasks;\n\t\t\tconst summary = formatSummary(applied.phases, [], readOnly);\n\t\t\tconst text = corrections.length > 0 ? `${corrections.join(\"\\n\")}\\n\\n${summary}` : summary;\n\n\t\t\treturn { content: [{ type: \"text\", text }], details };\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 (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(\n\t\t\t\tphases,\n\t\t\t\tresult.details?.completedTasks ?? [],\n\t\t\t\toptions,\n\t\t\t\tcontext.args,\n\t\t\t\tresult.details?.op,\n\t\t\t\ttheme,\n\t\t\t\tcontext.spinnerFrame,\n\t\t\t);\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEX,gBAAgB,EAGhB,wBAAwB,EAKxB,mBAAmB,EAEnB,eAAe,EACf,MAAM,YAAY,CAAC;AA4BpB,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAgID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,wBAAwB,CAmD5F;AAED,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,eAAe,GACrB,wBAAwB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAiBlE;AAWD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0B/F"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/websearch/websearch/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEX,gBAAgB,EAGhB,wBAAwB,EAKxB,mBAAmB,EAEnB,eAAe,EACf,MAAM,YAAY,CAAC;AA8BpB,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAgID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,wBAAwB,CAmD5F;AAED,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,eAAe,GACrB,wBAAwB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAiBlE;AAWD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0B/F"}
@@ -6,6 +6,7 @@ import { isAllowedProviderBaseUrl } from "./provider-endpoints.js";
6
6
  const PROVIDERS = [
7
7
  "exa",
8
8
  "tavily",
9
+ "serpdive",
9
10
  "brave",
10
11
  "duckduckgo-html",
11
12
  "deepseek",
@@ -18,6 +19,7 @@ const PROVIDERS = [
18
19
  "perplexity",
19
20
  "xai",
20
21
  "kimi",
22
+ "kagi",
21
23
  ];
22
24
  const CONTEXT_SIZES = ["low", "medium", "high"];
23
25
  const CODEX_MODES = ["cached", "live"];