@code-yeongyu/senpi 2026.6.15 → 2026.6.16

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 (299) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/core/compaction/compaction.d.ts.map +1 -1
  3. package/dist/core/compaction/compaction.js +5 -0
  4. package/dist/core/compaction/compaction.js.map +1 -1
  5. package/dist/core/extensions/builtin/bash-timeout/index.d.ts.map +1 -1
  6. package/dist/core/extensions/builtin/bash-timeout/index.js +3 -1
  7. package/dist/core/extensions/builtin/bash-timeout/index.js.map +1 -1
  8. package/dist/core/extensions/builtin/bash-timeout/timeout.js +2 -2
  9. package/dist/core/extensions/builtin/bash-timeout/timeout.js.map +1 -1
  10. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  11. package/dist/core/extensions/builtin/compaction/speculative.js +24 -12
  12. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  13. package/dist/core/extensions/builtin/goal/command.d.ts +14 -0
  14. package/dist/core/extensions/builtin/goal/command.d.ts.map +1 -0
  15. package/dist/core/extensions/builtin/goal/command.js +16 -0
  16. package/dist/core/extensions/builtin/goal/command.js.map +1 -0
  17. package/dist/core/extensions/builtin/goal/continuation.d.ts +4 -0
  18. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -0
  19. package/dist/core/extensions/builtin/goal/continuation.js +7 -0
  20. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -0
  21. package/dist/core/extensions/builtin/goal/errors.d.ts +13 -0
  22. package/dist/core/extensions/builtin/goal/errors.d.ts.map +1 -0
  23. package/dist/core/extensions/builtin/goal/errors.js +25 -0
  24. package/dist/core/extensions/builtin/goal/errors.js.map +1 -0
  25. package/dist/core/extensions/builtin/goal/format.d.ts +8 -0
  26. package/dist/core/extensions/builtin/goal/format.d.ts.map +1 -0
  27. package/dist/core/extensions/builtin/goal/format.js +71 -0
  28. package/dist/core/extensions/builtin/goal/format.js.map +1 -0
  29. package/dist/core/extensions/builtin/goal/index.d.ts +3 -0
  30. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -0
  31. package/dist/core/extensions/builtin/goal/index.js +322 -0
  32. package/dist/core/extensions/builtin/goal/index.js.map +1 -0
  33. package/dist/core/extensions/builtin/goal/prompt.d.ts +3 -0
  34. package/dist/core/extensions/builtin/goal/prompt.d.ts.map +1 -0
  35. package/dist/core/extensions/builtin/goal/prompt.js +34 -0
  36. package/dist/core/extensions/builtin/goal/prompt.js.map +1 -0
  37. package/dist/core/extensions/builtin/goal/store.d.ts +9 -0
  38. package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -0
  39. package/dist/core/extensions/builtin/goal/store.js +173 -0
  40. package/dist/core/extensions/builtin/goal/store.js.map +1 -0
  41. package/dist/core/extensions/builtin/goal/types.d.ts +50 -0
  42. package/dist/core/extensions/builtin/goal/types.d.ts.map +1 -0
  43. package/dist/core/extensions/builtin/goal/types.js +6 -0
  44. package/dist/core/extensions/builtin/goal/types.js.map +1 -0
  45. package/dist/core/extensions/builtin/goal/ui.d.ts +6 -0
  46. package/dist/core/extensions/builtin/goal/ui.d.ts.map +1 -0
  47. package/dist/core/extensions/builtin/goal/ui.js +20 -0
  48. package/dist/core/extensions/builtin/goal/ui.js.map +1 -0
  49. package/dist/core/extensions/builtin/goal/validation.d.ts +3 -0
  50. package/dist/core/extensions/builtin/goal/validation.d.ts.map +1 -0
  51. package/dist/core/extensions/builtin/goal/validation.js +13 -0
  52. package/dist/core/extensions/builtin/goal/validation.js.map +1 -0
  53. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  54. package/dist/core/extensions/builtin/index.js +10 -2
  55. package/dist/core/extensions/builtin/index.js.map +1 -1
  56. package/dist/core/extensions/builtin/nested-agents-md/core/containment.d.ts +10 -0
  57. package/dist/core/extensions/builtin/nested-agents-md/core/containment.d.ts.map +1 -0
  58. package/dist/core/extensions/builtin/nested-agents-md/core/containment.js +23 -0
  59. package/dist/core/extensions/builtin/nested-agents-md/core/containment.js.map +1 -0
  60. package/dist/core/extensions/builtin/nested-agents-md/core/errors.d.ts +5 -0
  61. package/dist/core/extensions/builtin/nested-agents-md/core/errors.d.ts.map +1 -0
  62. package/dist/core/extensions/builtin/nested-agents-md/core/errors.js +9 -0
  63. package/dist/core/extensions/builtin/nested-agents-md/core/errors.js.map +1 -0
  64. package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.d.ts +7 -0
  65. package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.d.ts.map +1 -0
  66. package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.js +44 -0
  67. package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.js.map +1 -0
  68. package/dist/core/extensions/builtin/nested-agents-md/core/format.d.ts +7 -0
  69. package/dist/core/extensions/builtin/nested-agents-md/core/format.d.ts.map +1 -0
  70. package/dist/core/extensions/builtin/nested-agents-md/core/format.js +7 -0
  71. package/dist/core/extensions/builtin/nested-agents-md/core/format.js.map +1 -0
  72. package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.d.ts +11 -0
  73. package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.d.ts.map +1 -0
  74. package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.js +77 -0
  75. package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.js.map +1 -0
  76. package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.d.ts +11 -0
  77. package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.d.ts.map +1 -0
  78. package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.js +33 -0
  79. package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.js.map +1 -0
  80. package/dist/core/extensions/builtin/nested-agents-md/core/session-key.d.ts +8 -0
  81. package/dist/core/extensions/builtin/nested-agents-md/core/session-key.d.ts.map +1 -0
  82. package/dist/core/extensions/builtin/nested-agents-md/core/session-key.js +8 -0
  83. package/dist/core/extensions/builtin/nested-agents-md/core/session-key.js.map +1 -0
  84. package/dist/core/extensions/builtin/nested-agents-md/core/truncate.d.ts +8 -0
  85. package/dist/core/extensions/builtin/nested-agents-md/core/truncate.d.ts.map +1 -0
  86. package/dist/core/extensions/builtin/nested-agents-md/core/truncate.js +26 -0
  87. package/dist/core/extensions/builtin/nested-agents-md/core/truncate.js.map +1 -0
  88. package/dist/core/extensions/builtin/nested-agents-md/core/types.d.ts +25 -0
  89. package/dist/core/extensions/builtin/nested-agents-md/core/types.d.ts.map +1 -0
  90. package/dist/core/extensions/builtin/nested-agents-md/core/types.js +4 -0
  91. package/dist/core/extensions/builtin/nested-agents-md/core/types.js.map +1 -0
  92. package/dist/core/extensions/builtin/nested-agents-md/index.d.ts +3 -0
  93. package/dist/core/extensions/builtin/nested-agents-md/index.d.ts.map +1 -0
  94. package/dist/core/extensions/builtin/nested-agents-md/index.js +102 -0
  95. package/dist/core/extensions/builtin/nested-agents-md/index.js.map +1 -0
  96. package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.d.ts +32 -0
  97. package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.d.ts.map +1 -0
  98. package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.js +66 -0
  99. package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.js.map +1 -0
  100. package/dist/core/extensions/builtin/prompt-preset/presets.js +2 -2
  101. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  102. package/dist/core/extensions/builtin/rules/commands.d.ts +4 -0
  103. package/dist/core/extensions/builtin/rules/commands.d.ts.map +1 -0
  104. package/dist/core/extensions/builtin/rules/commands.js +87 -0
  105. package/dist/core/extensions/builtin/rules/commands.js.map +1 -0
  106. package/dist/core/extensions/builtin/rules/index.d.ts +3 -0
  107. package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -0
  108. package/dist/core/extensions/builtin/rules/index.js +127 -0
  109. package/dist/core/extensions/builtin/rules/index.js.map +1 -0
  110. package/dist/core/extensions/builtin/rules/rules/cache.d.ts +10 -0
  111. package/dist/core/extensions/builtin/rules/rules/cache.d.ts.map +1 -0
  112. package/dist/core/extensions/builtin/rules/rules/cache.js +51 -0
  113. package/dist/core/extensions/builtin/rules/rules/cache.js.map +1 -0
  114. package/dist/core/extensions/builtin/rules/rules/constants.d.ts +57 -0
  115. package/dist/core/extensions/builtin/rules/rules/constants.d.ts.map +1 -0
  116. package/dist/core/extensions/builtin/rules/rules/constants.js +96 -0
  117. package/dist/core/extensions/builtin/rules/rules/constants.js.map +1 -0
  118. package/dist/core/extensions/builtin/rules/rules/engine.d.ts +67 -0
  119. package/dist/core/extensions/builtin/rules/rules/engine.d.ts.map +1 -0
  120. package/dist/core/extensions/builtin/rules/rules/engine.js +443 -0
  121. package/dist/core/extensions/builtin/rules/rules/engine.js.map +1 -0
  122. package/dist/core/extensions/builtin/rules/rules/errors.d.ts +7 -0
  123. package/dist/core/extensions/builtin/rules/rules/errors.d.ts.map +1 -0
  124. package/dist/core/extensions/builtin/rules/rules/errors.js +13 -0
  125. package/dist/core/extensions/builtin/rules/rules/errors.js.map +1 -0
  126. package/dist/core/extensions/builtin/rules/rules/finder.d.ts +27 -0
  127. package/dist/core/extensions/builtin/rules/rules/finder.d.ts.map +1 -0
  128. package/dist/core/extensions/builtin/rules/rules/finder.js +241 -0
  129. package/dist/core/extensions/builtin/rules/rules/finder.js.map +1 -0
  130. package/dist/core/extensions/builtin/rules/rules/formatter.d.ts +8 -0
  131. package/dist/core/extensions/builtin/rules/rules/formatter.d.ts.map +1 -0
  132. package/dist/core/extensions/builtin/rules/rules/formatter.js +44 -0
  133. package/dist/core/extensions/builtin/rules/rules/formatter.js.map +1 -0
  134. package/dist/core/extensions/builtin/rules/rules/matcher.d.ts +25 -0
  135. package/dist/core/extensions/builtin/rules/rules/matcher.d.ts.map +1 -0
  136. package/dist/core/extensions/builtin/rules/rules/matcher.js +107 -0
  137. package/dist/core/extensions/builtin/rules/rules/matcher.js.map +1 -0
  138. package/dist/core/extensions/builtin/rules/rules/ordering.d.ts +4 -0
  139. package/dist/core/extensions/builtin/rules/rules/ordering.d.ts.map +1 -0
  140. package/dist/core/extensions/builtin/rules/rules/ordering.js +28 -0
  141. package/dist/core/extensions/builtin/rules/rules/ordering.js.map +1 -0
  142. package/dist/core/extensions/builtin/rules/rules/parser.d.ts +4 -0
  143. package/dist/core/extensions/builtin/rules/rules/parser.d.ts.map +1 -0
  144. package/dist/core/extensions/builtin/rules/rules/parser.js +290 -0
  145. package/dist/core/extensions/builtin/rules/rules/parser.js.map +1 -0
  146. package/dist/core/extensions/builtin/rules/rules/project-root.d.ts +2 -0
  147. package/dist/core/extensions/builtin/rules/rules/project-root.d.ts.map +1 -0
  148. package/dist/core/extensions/builtin/rules/rules/project-root.js +24 -0
  149. package/dist/core/extensions/builtin/rules/rules/project-root.js.map +1 -0
  150. package/dist/core/extensions/builtin/rules/rules/scanner.d.ts +14 -0
  151. package/dist/core/extensions/builtin/rules/rules/scanner.d.ts.map +1 -0
  152. package/dist/core/extensions/builtin/rules/rules/scanner.js +96 -0
  153. package/dist/core/extensions/builtin/rules/rules/scanner.js.map +1 -0
  154. package/dist/core/extensions/builtin/rules/rules/tool-paths.d.ts +4 -0
  155. package/dist/core/extensions/builtin/rules/rules/tool-paths.d.ts.map +1 -0
  156. package/dist/core/extensions/builtin/rules/rules/tool-paths.js +37 -0
  157. package/dist/core/extensions/builtin/rules/rules/tool-paths.js.map +1 -0
  158. package/dist/core/extensions/builtin/rules/rules/truncator.d.ts +18 -0
  159. package/dist/core/extensions/builtin/rules/rules/truncator.d.ts.map +1 -0
  160. package/dist/core/extensions/builtin/rules/rules/truncator.js +46 -0
  161. package/dist/core/extensions/builtin/rules/rules/truncator.js.map +1 -0
  162. package/dist/core/extensions/builtin/rules/rules/types.d.ts +124 -0
  163. package/dist/core/extensions/builtin/rules/rules/types.d.ts.map +1 -0
  164. package/dist/core/extensions/builtin/rules/rules/types.js +9 -0
  165. package/dist/core/extensions/builtin/rules/rules/types.js.map +1 -0
  166. package/dist/core/extensions/builtin/rules/ui/dynamic-border.d.ts +8 -0
  167. package/dist/core/extensions/builtin/rules/ui/dynamic-border.d.ts.map +1 -0
  168. package/dist/core/extensions/builtin/rules/ui/dynamic-border.js +10 -0
  169. package/dist/core/extensions/builtin/rules/ui/dynamic-border.js.map +1 -0
  170. package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts +22 -0
  171. package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts.map +1 -0
  172. package/dist/core/extensions/builtin/rules/ui/rules-banner.js +51 -0
  173. package/dist/core/extensions/builtin/rules/ui/rules-banner.js.map +1 -0
  174. package/dist/core/extensions/builtin/webfetch/index.d.ts +10 -0
  175. package/dist/core/extensions/builtin/webfetch/index.d.ts.map +1 -0
  176. package/dist/core/extensions/builtin/webfetch/index.js +53 -0
  177. package/dist/core/extensions/builtin/webfetch/index.js.map +1 -0
  178. package/dist/core/extensions/builtin/webfetch/webfetch/content.d.ts +4 -0
  179. package/dist/core/extensions/builtin/webfetch/webfetch/content.d.ts.map +1 -0
  180. package/dist/core/extensions/builtin/webfetch/webfetch/content.js +60 -0
  181. package/dist/core/extensions/builtin/webfetch/webfetch/content.js.map +1 -0
  182. package/dist/core/extensions/builtin/webfetch/webfetch/errors.d.ts +13 -0
  183. package/dist/core/extensions/builtin/webfetch/webfetch/errors.d.ts.map +1 -0
  184. package/dist/core/extensions/builtin/webfetch/webfetch/errors.js +25 -0
  185. package/dist/core/extensions/builtin/webfetch/webfetch/errors.js.map +1 -0
  186. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts +24 -0
  187. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts.map +1 -0
  188. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js +148 -0
  189. package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js.map +1 -0
  190. package/dist/core/extensions/builtin/webfetch/webfetch/renderers.d.ts +15 -0
  191. package/dist/core/extensions/builtin/webfetch/webfetch/renderers.d.ts.map +1 -0
  192. package/dist/core/extensions/builtin/webfetch/webfetch/renderers.js +110 -0
  193. package/dist/core/extensions/builtin/webfetch/webfetch/renderers.js.map +1 -0
  194. package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts +28 -0
  195. package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts.map +1 -0
  196. package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +79 -0
  197. package/dist/core/extensions/builtin/webfetch/webfetch/tool.js.map +1 -0
  198. package/dist/core/extensions/builtin/websearch/index.d.ts +3 -0
  199. package/dist/core/extensions/builtin/websearch/index.d.ts.map +1 -0
  200. package/dist/core/extensions/builtin/websearch/index.js +76 -0
  201. package/dist/core/extensions/builtin/websearch/index.js.map +1 -0
  202. package/dist/core/extensions/builtin/websearch/websearch/config.d.ts +12 -0
  203. package/dist/core/extensions/builtin/websearch/websearch/config.d.ts.map +1 -0
  204. package/dist/core/extensions/builtin/websearch/websearch/config.js +245 -0
  205. package/dist/core/extensions/builtin/websearch/websearch/config.js.map +1 -0
  206. package/dist/core/extensions/builtin/websearch/websearch/native.d.ts +19 -0
  207. package/dist/core/extensions/builtin/websearch/websearch/native.d.ts.map +1 -0
  208. package/dist/core/extensions/builtin/websearch/websearch/native.js +65 -0
  209. package/dist/core/extensions/builtin/websearch/websearch/native.js.map +1 -0
  210. package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.d.ts +5 -0
  211. package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.d.ts.map +1 -0
  212. package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.js +58 -0
  213. package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.js.map +1 -0
  214. package/dist/core/extensions/builtin/websearch/websearch/providers.d.ts +4 -0
  215. package/dist/core/extensions/builtin/websearch/websearch/providers.d.ts.map +1 -0
  216. package/dist/core/extensions/builtin/websearch/websearch/providers.js +464 -0
  217. package/dist/core/extensions/builtin/websearch/websearch/providers.js.map +1 -0
  218. package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts +26 -0
  219. package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts.map +1 -0
  220. package/dist/core/extensions/builtin/websearch/websearch/renderers.js +66 -0
  221. package/dist/core/extensions/builtin/websearch/websearch/renderers.js.map +1 -0
  222. package/dist/core/extensions/builtin/websearch/websearch/search.d.ts +9 -0
  223. package/dist/core/extensions/builtin/websearch/websearch/search.d.ts.map +1 -0
  224. package/dist/core/extensions/builtin/websearch/websearch/search.js +261 -0
  225. package/dist/core/extensions/builtin/websearch/websearch/search.js.map +1 -0
  226. package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts +18 -0
  227. package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts.map +1 -0
  228. package/dist/core/extensions/builtin/websearch/websearch/tool.js +88 -0
  229. package/dist/core/extensions/builtin/websearch/websearch/tool.js.map +1 -0
  230. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +115 -0
  231. package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -0
  232. package/dist/core/extensions/builtin/websearch/websearch/types.js +2 -0
  233. package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -0
  234. package/dist/core/extensions/runner.d.ts.map +1 -1
  235. package/dist/core/extensions/runner.js +8 -1
  236. package/dist/core/extensions/runner.js.map +1 -1
  237. package/dist/core/tools/bash.d.ts.map +1 -1
  238. package/dist/core/tools/bash.js +4 -0
  239. package/dist/core/tools/bash.js.map +1 -1
  240. package/dist/modes/interactive/components/diff.d.ts +14 -0
  241. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  242. package/dist/modes/interactive/components/diff.js +65 -1
  243. package/dist/modes/interactive/components/diff.js.map +1 -1
  244. package/dist/modes/interactive/components/session-selector.d.ts +0 -1
  245. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  246. package/dist/modes/interactive/components/session-selector.js +0 -4
  247. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  248. package/dist/utils/child-process.d.ts +7 -4
  249. package/dist/utils/child-process.d.ts.map +1 -1
  250. package/dist/utils/child-process.js +23 -5
  251. package/dist/utils/child-process.js.map +1 -1
  252. package/docs/containerization.md +36 -36
  253. package/docs/index.md +1 -1
  254. package/docs/security.md +13 -13
  255. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  256. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  257. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  258. package/examples/extensions/gondolin/package-lock.json +2 -2
  259. package/examples/extensions/gondolin/package.json +1 -1
  260. package/examples/extensions/sandbox/package-lock.json +2 -2
  261. package/examples/extensions/sandbox/package.json +1 -1
  262. package/examples/extensions/with-deps/package-lock.json +2 -2
  263. package/examples/extensions/with-deps/package.json +1 -1
  264. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
  265. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +5 -0
  266. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
  267. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  268. package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
  269. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +88 -74
  270. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  271. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +124 -132
  272. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
  273. package/node_modules/@earendil-works/pi-ai/dist/models.js +4 -1
  274. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  275. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  276. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +18 -1
  277. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
  278. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +2 -1
  279. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
  280. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js +2 -1
  281. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js.map +1 -1
  282. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  283. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +20 -2
  284. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
  285. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +2 -0
  286. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  287. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  288. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.d.ts +5 -0
  289. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.d.ts.map +1 -0
  290. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.js +41 -0
  291. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.js.map +1 -0
  292. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  293. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  294. package/npm-shrinkwrap.json +45 -12
  295. package/package.json +8 -4
  296. package/dist/core/extensions/builtin/kimi-web-search/index.d.ts +0 -3
  297. package/dist/core/extensions/builtin/kimi-web-search/index.d.ts.map +0 -1
  298. package/dist/core/extensions/builtin/kimi-web-search/index.js +0 -208
  299. package/dist/core/extensions/builtin/kimi-web-search/index.js.map +0 -1
@@ -0,0 +1,290 @@
1
+ import { RuleFrontmatterParseError } from "./errors.js";
2
+ const FRONTMATTER_OPENING = "---\n";
3
+ const FRONTMATTER_OPENING_CRLF = "---\r\n";
4
+ /** Parse markdown rule content and extract the supported YAML frontmatter subset. */
5
+ export function parseRule(content) {
6
+ const normalizedContent = stripBom(content);
7
+ const openingLength = getOpeningDelimiterLength(normalizedContent);
8
+ if (openingLength === 0) {
9
+ return { frontmatter: {}, body: normalizedContent };
10
+ }
11
+ const closingDelimiter = findClosingDelimiter(normalizedContent, openingLength);
12
+ if (closingDelimiter === null) {
13
+ return {
14
+ frontmatter: {},
15
+ body: normalizedContent,
16
+ diagnostic: "Missing closing frontmatter delimiter",
17
+ };
18
+ }
19
+ const yamlContent = normalizedContent.slice(openingLength, closingDelimiter.start);
20
+ const body = normalizedContent.slice(closingDelimiter.bodyStart);
21
+ try {
22
+ return { frontmatter: parseYamlFrontmatter(yamlContent), body };
23
+ }
24
+ catch (error) {
25
+ const message = error instanceof Error ? error.message : "Invalid YAML frontmatter";
26
+ return {
27
+ frontmatter: {},
28
+ body: normalizedContent,
29
+ diagnostic: `Malformed frontmatter: ${message}`,
30
+ };
31
+ }
32
+ }
33
+ function stripBom(content) {
34
+ return content.startsWith("\uFEFF") ? content.slice(1) : content;
35
+ }
36
+ function getOpeningDelimiterLength(content) {
37
+ if (content.startsWith(FRONTMATTER_OPENING_CRLF))
38
+ return FRONTMATTER_OPENING_CRLF.length;
39
+ if (content.startsWith(FRONTMATTER_OPENING))
40
+ return FRONTMATTER_OPENING.length;
41
+ return 0;
42
+ }
43
+ function findClosingDelimiter(content, openingLength) {
44
+ let lineStart = openingLength;
45
+ while (lineStart <= content.length) {
46
+ const nextNewline = content.indexOf("\n", lineStart);
47
+ const lineEnd = nextNewline === -1 ? content.length : nextNewline;
48
+ const line = content.slice(lineStart, lineEnd).replace(/\r$/, "");
49
+ if (line === "---") {
50
+ return {
51
+ start: lineStart,
52
+ bodyStart: nextNewline === -1 ? content.length : nextNewline + 1,
53
+ };
54
+ }
55
+ if (nextNewline === -1)
56
+ break;
57
+ lineStart = nextNewline + 1;
58
+ }
59
+ return null;
60
+ }
61
+ function parseYamlFrontmatter(yamlContent) {
62
+ const lines = yamlContent.replace(/\r\n/g, "\n").split("\n");
63
+ const frontmatter = {};
64
+ const globValues = [];
65
+ let lineIndex = 0;
66
+ while (lineIndex < lines.length) {
67
+ const rawLine = lines[lineIndex];
68
+ if (rawLine === undefined)
69
+ break;
70
+ const line = stripComment(rawLine).trim();
71
+ if (line.length === 0) {
72
+ lineIndex += 1;
73
+ continue;
74
+ }
75
+ const colonIndex = line.indexOf(":");
76
+ if (colonIndex === -1) {
77
+ throw new RuleFrontmatterParseError(`Expected key-value pair on line ${lineIndex + 1}`);
78
+ }
79
+ const key = line.slice(0, colonIndex).trim();
80
+ const rawValue = line.slice(colonIndex + 1).trim();
81
+ if (key === "description") {
82
+ frontmatter.description = parseStringValue(rawValue);
83
+ lineIndex += 1;
84
+ continue;
85
+ }
86
+ if (key === "alwaysApply") {
87
+ frontmatter.alwaysApply = parseBooleanValue(rawValue, lineIndex + 1);
88
+ lineIndex += 1;
89
+ continue;
90
+ }
91
+ if (key === "globs" || key === "paths" || key === "applyTo") {
92
+ const parsed = parseGlobValue(rawValue, lines, lineIndex);
93
+ for (const glob of parsed.values) {
94
+ if (!globValues.includes(glob))
95
+ globValues.push(glob);
96
+ }
97
+ lineIndex += parsed.consumed;
98
+ continue;
99
+ }
100
+ lineIndex += 1;
101
+ }
102
+ if (globValues.length === 1) {
103
+ const singleGlob = globValues[0];
104
+ if (singleGlob !== undefined)
105
+ frontmatter.globs = singleGlob;
106
+ }
107
+ else if (globValues.length > 1) {
108
+ frontmatter.globs = globValues;
109
+ }
110
+ return frontmatter;
111
+ }
112
+ function parseBooleanValue(value, lineNumber) {
113
+ if (value === "true")
114
+ return true;
115
+ if (value === "false")
116
+ return false;
117
+ throw new RuleFrontmatterParseError(`Expected boolean on line ${lineNumber}`);
118
+ }
119
+ function parseGlobValue(rawValue, lines, lineIndex) {
120
+ if (rawValue.startsWith("[")) {
121
+ return { values: parseInlineArray(rawValue), consumed: 1 };
122
+ }
123
+ if (rawValue.length === 0) {
124
+ return parseMultilineArray(lines, lineIndex);
125
+ }
126
+ const value = parseStringValue(rawValue);
127
+ if (value.includes(",")) {
128
+ return {
129
+ values: value
130
+ .split(",")
131
+ .map((item) => item.trim())
132
+ .filter(Boolean),
133
+ consumed: 1,
134
+ };
135
+ }
136
+ return { values: [value], consumed: 1 };
137
+ }
138
+ function parseMultilineArray(lines, lineIndex) {
139
+ const values = [];
140
+ let consumed = 1;
141
+ for (let index = lineIndex + 1; index < lines.length; index += 1) {
142
+ const rawLine = lines[index];
143
+ if (rawLine === undefined)
144
+ break;
145
+ const lineWithoutComment = stripComment(rawLine);
146
+ if (lineWithoutComment.trim().length === 0) {
147
+ consumed += 1;
148
+ continue;
149
+ }
150
+ const arrayItem = lineWithoutComment.match(/^\s+-\s*(.*)$/);
151
+ if (arrayItem === null)
152
+ break;
153
+ values.push(parseStringValue(arrayItem[1] ?? ""));
154
+ consumed += 1;
155
+ }
156
+ return { values: values.filter(Boolean), consumed };
157
+ }
158
+ function parseInlineArray(value) {
159
+ const closingBracketIndex = findClosingBracket(value);
160
+ if (closingBracketIndex === -1) {
161
+ throw new RuleFrontmatterParseError("Unclosed inline array");
162
+ }
163
+ const trailing = value.slice(closingBracketIndex + 1).trim();
164
+ if (trailing.length > 0) {
165
+ throw new RuleFrontmatterParseError("Unexpected content after inline array");
166
+ }
167
+ const content = value.slice(1, closingBracketIndex).trim();
168
+ if (content.length === 0)
169
+ return [];
170
+ return splitCommaSeparated(content).map(parseStringValue).filter(Boolean);
171
+ }
172
+ function findClosingBracket(value) {
173
+ let quote = null;
174
+ let escaped = false;
175
+ for (let index = 0; index < value.length; index += 1) {
176
+ const character = value[index];
177
+ if (character === undefined)
178
+ continue;
179
+ if (escaped) {
180
+ escaped = false;
181
+ continue;
182
+ }
183
+ if (quote !== null && character === "\\") {
184
+ escaped = true;
185
+ continue;
186
+ }
187
+ if (character === '"' || character === "'") {
188
+ if (quote === null)
189
+ quote = character;
190
+ else if (quote === character)
191
+ quote = null;
192
+ continue;
193
+ }
194
+ if (quote === null && character === "]")
195
+ return index;
196
+ }
197
+ return -1;
198
+ }
199
+ function splitCommaSeparated(value) {
200
+ const values = [];
201
+ let current = "";
202
+ let quote = null;
203
+ let escaped = false;
204
+ for (let index = 0; index < value.length; index += 1) {
205
+ const character = value[index];
206
+ if (character === undefined)
207
+ continue;
208
+ if (escaped) {
209
+ current += character;
210
+ escaped = false;
211
+ continue;
212
+ }
213
+ if (quote !== null && character === "\\") {
214
+ current += character;
215
+ escaped = true;
216
+ continue;
217
+ }
218
+ if (character === '"' || character === "'") {
219
+ if (quote === null)
220
+ quote = character;
221
+ else if (quote === character)
222
+ quote = null;
223
+ current += character;
224
+ continue;
225
+ }
226
+ if (quote === null && character === ",") {
227
+ values.push(current.trim());
228
+ current = "";
229
+ continue;
230
+ }
231
+ current += character;
232
+ }
233
+ if (quote !== null) {
234
+ throw new RuleFrontmatterParseError("Unclosed quoted value");
235
+ }
236
+ values.push(current.trim());
237
+ return values.filter(Boolean);
238
+ }
239
+ function parseStringValue(value) {
240
+ if (value.length === 0)
241
+ return "";
242
+ if (value.startsWith('"'))
243
+ return parseJsonString(value);
244
+ if (value.startsWith("'") && value.endsWith("'"))
245
+ return value.slice(1, -1);
246
+ if (value.startsWith("'"))
247
+ throw new RuleFrontmatterParseError("Unclosed quoted value");
248
+ return value;
249
+ }
250
+ function parseJsonString(value) {
251
+ let parsedValue;
252
+ try {
253
+ parsedValue = JSON.parse(value);
254
+ }
255
+ catch {
256
+ throw new RuleFrontmatterParseError("Invalid JSON-quoted string");
257
+ }
258
+ if (typeof parsedValue !== "string") {
259
+ throw new RuleFrontmatterParseError("Expected JSON-quoted string");
260
+ }
261
+ return parsedValue;
262
+ }
263
+ function stripComment(line) {
264
+ let quote = null;
265
+ let escaped = false;
266
+ for (let index = 0; index < line.length; index += 1) {
267
+ const character = line[index];
268
+ if (character === undefined)
269
+ continue;
270
+ if (escaped) {
271
+ escaped = false;
272
+ continue;
273
+ }
274
+ if (quote !== null && character === "\\") {
275
+ escaped = true;
276
+ continue;
277
+ }
278
+ if (character === '"' || character === "'") {
279
+ if (quote === null)
280
+ quote = character;
281
+ else if (quote === character)
282
+ quote = null;
283
+ continue;
284
+ }
285
+ if (quote === null && character === "#")
286
+ return line.slice(0, index);
287
+ }
288
+ return line;
289
+ }
290
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/parser.ts"],"names":[],"mappings":"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","sourcesContent":["import { RuleFrontmatterParseError } from \"./errors.ts\";\nimport type { ParsedRule, RuleFrontmatter } from \"./types.ts\";\n\nconst FRONTMATTER_OPENING = \"---\\n\";\nconst FRONTMATTER_OPENING_CRLF = \"---\\r\\n\";\n\n/** Parse markdown rule content and extract the supported YAML frontmatter subset. */\nexport function parseRule(content: string): ParsedRule {\n\tconst normalizedContent = stripBom(content);\n\tconst openingLength = getOpeningDelimiterLength(normalizedContent);\n\tif (openingLength === 0) {\n\t\treturn { frontmatter: {}, body: normalizedContent };\n\t}\n\n\tconst closingDelimiter = findClosingDelimiter(normalizedContent, openingLength);\n\tif (closingDelimiter === null) {\n\t\treturn {\n\t\t\tfrontmatter: {},\n\t\t\tbody: normalizedContent,\n\t\t\tdiagnostic: \"Missing closing frontmatter delimiter\",\n\t\t};\n\t}\n\n\tconst yamlContent = normalizedContent.slice(openingLength, closingDelimiter.start);\n\tconst body = normalizedContent.slice(closingDelimiter.bodyStart);\n\n\ttry {\n\t\treturn { frontmatter: parseYamlFrontmatter(yamlContent), body };\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"Invalid YAML frontmatter\";\n\t\treturn {\n\t\t\tfrontmatter: {},\n\t\t\tbody: normalizedContent,\n\t\t\tdiagnostic: `Malformed frontmatter: ${message}`,\n\t\t};\n\t}\n}\n\nfunction stripBom(content: string): string {\n\treturn content.startsWith(\"\\uFEFF\") ? content.slice(1) : content;\n}\n\nfunction getOpeningDelimiterLength(content: string): number {\n\tif (content.startsWith(FRONTMATTER_OPENING_CRLF)) return FRONTMATTER_OPENING_CRLF.length;\n\tif (content.startsWith(FRONTMATTER_OPENING)) return FRONTMATTER_OPENING.length;\n\treturn 0;\n}\n\nfunction findClosingDelimiter(content: string, openingLength: number): { start: number; bodyStart: number } | null {\n\tlet lineStart = openingLength;\n\n\twhile (lineStart <= content.length) {\n\t\tconst nextNewline = content.indexOf(\"\\n\", lineStart);\n\t\tconst lineEnd = nextNewline === -1 ? content.length : nextNewline;\n\t\tconst line = content.slice(lineStart, lineEnd).replace(/\\r$/, \"\");\n\n\t\tif (line === \"---\") {\n\t\t\treturn {\n\t\t\t\tstart: lineStart,\n\t\t\t\tbodyStart: nextNewline === -1 ? content.length : nextNewline + 1,\n\t\t\t};\n\t\t}\n\n\t\tif (nextNewline === -1) break;\n\t\tlineStart = nextNewline + 1;\n\t}\n\n\treturn null;\n}\n\nfunction parseYamlFrontmatter(yamlContent: string): RuleFrontmatter {\n\tconst lines = yamlContent.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\tconst frontmatter: RuleFrontmatter = {};\n\tconst globValues: string[] = [];\n\tlet lineIndex = 0;\n\n\twhile (lineIndex < lines.length) {\n\t\tconst rawLine = lines[lineIndex];\n\t\tif (rawLine === undefined) break;\n\n\t\tconst line = stripComment(rawLine).trim();\n\t\tif (line.length === 0) {\n\t\t\tlineIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst colonIndex = line.indexOf(\":\");\n\t\tif (colonIndex === -1) {\n\t\t\tthrow new RuleFrontmatterParseError(`Expected key-value pair on line ${lineIndex + 1}`);\n\t\t}\n\n\t\tconst key = line.slice(0, colonIndex).trim();\n\t\tconst rawValue = line.slice(colonIndex + 1).trim();\n\n\t\tif (key === \"description\") {\n\t\t\tfrontmatter.description = parseStringValue(rawValue);\n\t\t\tlineIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (key === \"alwaysApply\") {\n\t\t\tfrontmatter.alwaysApply = parseBooleanValue(rawValue, lineIndex + 1);\n\t\t\tlineIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (key === \"globs\" || key === \"paths\" || key === \"applyTo\") {\n\t\t\tconst parsed = parseGlobValue(rawValue, lines, lineIndex);\n\t\t\tfor (const glob of parsed.values) {\n\t\t\t\tif (!globValues.includes(glob)) globValues.push(glob);\n\t\t\t}\n\t\t\tlineIndex += parsed.consumed;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlineIndex += 1;\n\t}\n\n\tif (globValues.length === 1) {\n\t\tconst singleGlob = globValues[0];\n\t\tif (singleGlob !== undefined) frontmatter.globs = singleGlob;\n\t} else if (globValues.length > 1) {\n\t\tfrontmatter.globs = globValues;\n\t}\n\n\treturn frontmatter;\n}\n\nfunction parseBooleanValue(value: string, lineNumber: number): boolean {\n\tif (value === \"true\") return true;\n\tif (value === \"false\") return false;\n\tthrow new RuleFrontmatterParseError(`Expected boolean on line ${lineNumber}`);\n}\n\nfunction parseGlobValue(rawValue: string, lines: string[], lineIndex: number): { values: string[]; consumed: number } {\n\tif (rawValue.startsWith(\"[\")) {\n\t\treturn { values: parseInlineArray(rawValue), consumed: 1 };\n\t}\n\n\tif (rawValue.length === 0) {\n\t\treturn parseMultilineArray(lines, lineIndex);\n\t}\n\n\tconst value = parseStringValue(rawValue);\n\tif (value.includes(\",\")) {\n\t\treturn {\n\t\t\tvalues: value\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((item) => item.trim())\n\t\t\t\t.filter(Boolean),\n\t\t\tconsumed: 1,\n\t\t};\n\t}\n\n\treturn { values: [value], consumed: 1 };\n}\n\nfunction parseMultilineArray(lines: string[], lineIndex: number): { values: string[]; consumed: number } {\n\tconst values: string[] = [];\n\tlet consumed = 1;\n\n\tfor (let index = lineIndex + 1; index < lines.length; index += 1) {\n\t\tconst rawLine = lines[index];\n\t\tif (rawLine === undefined) break;\n\n\t\tconst lineWithoutComment = stripComment(rawLine);\n\t\tif (lineWithoutComment.trim().length === 0) {\n\t\t\tconsumed += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst arrayItem = lineWithoutComment.match(/^\\s+-\\s*(.*)$/);\n\t\tif (arrayItem === null) break;\n\n\t\tvalues.push(parseStringValue(arrayItem[1] ?? \"\"));\n\t\tconsumed += 1;\n\t}\n\n\treturn { values: values.filter(Boolean), consumed };\n}\n\nfunction parseInlineArray(value: string): string[] {\n\tconst closingBracketIndex = findClosingBracket(value);\n\tif (closingBracketIndex === -1) {\n\t\tthrow new RuleFrontmatterParseError(\"Unclosed inline array\");\n\t}\n\n\tconst trailing = value.slice(closingBracketIndex + 1).trim();\n\tif (trailing.length > 0) {\n\t\tthrow new RuleFrontmatterParseError(\"Unexpected content after inline array\");\n\t}\n\n\tconst content = value.slice(1, closingBracketIndex).trim();\n\tif (content.length === 0) return [];\n\n\treturn splitCommaSeparated(content).map(parseStringValue).filter(Boolean);\n}\n\nfunction findClosingBracket(value: string): number {\n\tlet quote: string | null = null;\n\tlet escaped = false;\n\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst character = value[index];\n\t\tif (character === undefined) continue;\n\n\t\tif (escaped) {\n\t\t\tescaped = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote !== null && character === \"\\\\\") {\n\t\t\tescaped = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tif (quote === null) quote = character;\n\t\t\telse if (quote === character) quote = null;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === null && character === \"]\") return index;\n\t}\n\n\treturn -1;\n}\n\nfunction splitCommaSeparated(value: string): string[] {\n\tconst values: string[] = [];\n\tlet current = \"\";\n\tlet quote: string | null = null;\n\tlet escaped = false;\n\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst character = value[index];\n\t\tif (character === undefined) continue;\n\n\t\tif (escaped) {\n\t\t\tcurrent += character;\n\t\t\tescaped = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote !== null && character === \"\\\\\") {\n\t\t\tcurrent += character;\n\t\t\tescaped = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tif (quote === null) quote = character;\n\t\t\telse if (quote === character) quote = null;\n\t\t\tcurrent += character;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === null && character === \",\") {\n\t\t\tvalues.push(current.trim());\n\t\t\tcurrent = \"\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrent += character;\n\t}\n\n\tif (quote !== null) {\n\t\tthrow new RuleFrontmatterParseError(\"Unclosed quoted value\");\n\t}\n\n\tvalues.push(current.trim());\n\treturn values.filter(Boolean);\n}\n\nfunction parseStringValue(value: string): string {\n\tif (value.length === 0) return \"\";\n\tif (value.startsWith('\"')) return parseJsonString(value);\n\tif (value.startsWith(\"'\") && value.endsWith(\"'\")) return value.slice(1, -1);\n\tif (value.startsWith(\"'\")) throw new RuleFrontmatterParseError(\"Unclosed quoted value\");\n\treturn value;\n}\n\nfunction parseJsonString(value: string): string {\n\tlet parsedValue: unknown;\n\ttry {\n\t\tparsedValue = JSON.parse(value);\n\t} catch {\n\t\tthrow new RuleFrontmatterParseError(\"Invalid JSON-quoted string\");\n\t}\n\n\tif (typeof parsedValue !== \"string\") {\n\t\tthrow new RuleFrontmatterParseError(\"Expected JSON-quoted string\");\n\t}\n\n\treturn parsedValue;\n}\n\nfunction stripComment(line: string): string {\n\tlet quote: string | null = null;\n\tlet escaped = false;\n\n\tfor (let index = 0; index < line.length; index += 1) {\n\t\tconst character = line[index];\n\t\tif (character === undefined) continue;\n\n\t\tif (escaped) {\n\t\t\tescaped = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote !== null && character === \"\\\\\") {\n\t\t\tescaped = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tif (quote === null) quote = character;\n\t\t\telse if (quote === character) quote = null;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === null && character === \"#\") return line.slice(0, index);\n\t}\n\n\treturn line;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function findProjectRoot(startPath: string, markers?: ReadonlyArray<string>): string | null;
2
+ //# sourceMappingURL=project-root.d.ts.map
@@ -0,0 +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,CAwBlH"}
@@ -0,0 +1,24 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { PROJECT_MARKERS } from "./constants.js";
4
+ export function findProjectRoot(startPath, markers = PROJECT_MARKERS) {
5
+ const resolvedStartPath = resolve(startPath);
6
+ if (!existsSync(resolvedStartPath)) {
7
+ return null;
8
+ }
9
+ const startStats = statSync(resolvedStartPath);
10
+ let currentDirectory = startStats.isDirectory() ? resolvedStartPath : dirname(resolvedStartPath);
11
+ const filesystemRoot = resolve("/");
12
+ while (true) {
13
+ for (const marker of markers) {
14
+ if (existsSync(join(currentDirectory, marker))) {
15
+ return currentDirectory;
16
+ }
17
+ }
18
+ if (currentDirectory === filesystemRoot) {
19
+ return null;
20
+ }
21
+ currentDirectory = dirname(currentDirectory);
22
+ }
23
+ }
24
+ //# sourceMappingURL=project-root.js.map
@@ -0,0 +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,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9C,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\tcurrentDirectory = dirname(currentDirectory);\n\t}\n}\n"]}
@@ -0,0 +1,14 @@
1
+ export interface ScanOptions {
2
+ rootDir: string;
3
+ excludedDirs?: ReadonlyArray<string>;
4
+ /** Maximum recursion depth. Default: 10 */
5
+ maxDepth?: number;
6
+ }
7
+ export interface ScannedFile {
8
+ /** Absolute path as encountered (may be a symlink). */
9
+ path: string;
10
+ /** Real (resolved) path; same as path if not a symlink. */
11
+ realPath: string;
12
+ }
13
+ export declare function scanRuleFiles(options: ScanOptions): ScannedFile[];
14
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/scanner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC3B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE,CAwBjE"}
@@ -0,0 +1,96 @@
1
+ import { existsSync, lstatSync, readdirSync, realpathSync, statSync } from "node:fs";
2
+ import { isAbsolute, join, resolve } from "node:path";
3
+ import { RULE_FILE_EXTENSIONS, SCANNER_EXCLUDED_DIRS } from "./constants.js";
4
+ export function scanRuleFiles(options) {
5
+ const rootPath = toAbsolutePath(options.rootDir);
6
+ if (!existsSync(rootPath)) {
7
+ return [];
8
+ }
9
+ let rootStats;
10
+ try {
11
+ rootStats = statSync(rootPath);
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ if (!rootStats.isDirectory()) {
17
+ return [];
18
+ }
19
+ const results = [];
20
+ const visitedDirectories = new Set();
21
+ const excludedDirs = new Set(options.excludedDirs ?? SCANNER_EXCLUDED_DIRS);
22
+ const maxDepth = options.maxDepth ?? 10;
23
+ scanDirectory(rootPath, 0, maxDepth, excludedDirs, visitedDirectories, results);
24
+ return results;
25
+ }
26
+ function toAbsolutePath(filePath) {
27
+ return isAbsolute(filePath) ? filePath : resolve(filePath);
28
+ }
29
+ function scanDirectory(directoryPath, depth, maxDepth, excludedDirs, visitedDirectories, results) {
30
+ let realDirectoryPath;
31
+ try {
32
+ realDirectoryPath = realpathSync.native(directoryPath);
33
+ }
34
+ catch {
35
+ return;
36
+ }
37
+ if (visitedDirectories.has(realDirectoryPath)) {
38
+ return;
39
+ }
40
+ visitedDirectories.add(realDirectoryPath);
41
+ let entries;
42
+ try {
43
+ entries = readdirSync(directoryPath, { withFileTypes: true }).sort((leftEntry, rightEntry) => leftEntry.name.localeCompare(rightEntry.name));
44
+ }
45
+ catch {
46
+ return;
47
+ }
48
+ for (const entry of entries) {
49
+ const entryPath = join(directoryPath, entry.name);
50
+ if (entry.isDirectory()) {
51
+ if (!excludedDirs.has(entry.name) && depth < maxDepth) {
52
+ scanDirectory(entryPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);
53
+ }
54
+ continue;
55
+ }
56
+ if (entry.isSymbolicLink()) {
57
+ scanSymbolicLink(entryPath, entry.name, depth, maxDepth, excludedDirs, visitedDirectories, results);
58
+ continue;
59
+ }
60
+ if (entry.isFile() && isRuleFile(entry.name)) {
61
+ results.push({ path: entryPath, realPath: resolveRealPath(entryPath) });
62
+ }
63
+ }
64
+ }
65
+ function scanSymbolicLink(linkPath, linkName, depth, maxDepth, excludedDirs, visitedDirectories, results) {
66
+ let targetStats;
67
+ try {
68
+ targetStats = statSync(linkPath);
69
+ }
70
+ catch {
71
+ return;
72
+ }
73
+ if (targetStats.isDirectory()) {
74
+ if (!excludedDirs.has(linkName) && depth < maxDepth) {
75
+ scanDirectory(linkPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);
76
+ }
77
+ return;
78
+ }
79
+ if (targetStats.isFile() && isRuleFile(linkName)) {
80
+ results.push({ path: linkPath, realPath: resolveRealPath(linkPath) });
81
+ }
82
+ }
83
+ function isRuleFile(fileName) {
84
+ return RULE_FILE_EXTENSIONS.some((extension) => fileName.endsWith(extension));
85
+ }
86
+ function resolveRealPath(filePath) {
87
+ try {
88
+ const realPath = realpathSync.native(filePath);
89
+ const fileStats = lstatSync(filePath);
90
+ return fileStats.isSymbolicLink() ? realPath : filePath;
91
+ }
92
+ catch {
93
+ return filePath;
94
+ }
95
+ }
96
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/scanner.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Dirent, existsSync, lstatSync, readdirSync, realpathSync, type Stats, statSync } from \"node:fs\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nimport { RULE_FILE_EXTENSIONS, SCANNER_EXCLUDED_DIRS } from \"./constants.ts\";\n\nexport interface ScanOptions {\n\trootDir: string;\n\texcludedDirs?: ReadonlyArray<string>;\n\t/** Maximum recursion depth. Default: 10 */\n\tmaxDepth?: number;\n}\n\nexport interface ScannedFile {\n\t/** Absolute path as encountered (may be a symlink). */\n\tpath: string;\n\t/** Real (resolved) path; same as path if not a symlink. */\n\trealPath: string;\n}\n\nexport function scanRuleFiles(options: ScanOptions): ScannedFile[] {\n\tconst rootPath = toAbsolutePath(options.rootDir);\n\tif (!existsSync(rootPath)) {\n\t\treturn [];\n\t}\n\n\tlet rootStats: Stats;\n\ttry {\n\t\trootStats = statSync(rootPath);\n\t} catch {\n\t\treturn [];\n\t}\n\n\tif (!rootStats.isDirectory()) {\n\t\treturn [];\n\t}\n\n\tconst results: ScannedFile[] = [];\n\tconst visitedDirectories = new Set<string>();\n\tconst excludedDirs = new Set(options.excludedDirs ?? SCANNER_EXCLUDED_DIRS);\n\tconst maxDepth = options.maxDepth ?? 10;\n\n\tscanDirectory(rootPath, 0, maxDepth, excludedDirs, visitedDirectories, results);\n\treturn results;\n}\n\nfunction toAbsolutePath(filePath: string): string {\n\treturn isAbsolute(filePath) ? filePath : resolve(filePath);\n}\n\nfunction scanDirectory(\n\tdirectoryPath: string,\n\tdepth: number,\n\tmaxDepth: number,\n\texcludedDirs: ReadonlySet<string>,\n\tvisitedDirectories: Set<string>,\n\tresults: ScannedFile[],\n): void {\n\tlet realDirectoryPath: string;\n\ttry {\n\t\trealDirectoryPath = realpathSync.native(directoryPath);\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (visitedDirectories.has(realDirectoryPath)) {\n\t\treturn;\n\t}\n\tvisitedDirectories.add(realDirectoryPath);\n\n\tlet entries: Dirent[];\n\ttry {\n\t\tentries = readdirSync(directoryPath, { withFileTypes: true }).sort((leftEntry, rightEntry) =>\n\t\t\tleftEntry.name.localeCompare(rightEntry.name),\n\t\t);\n\t} catch {\n\t\treturn;\n\t}\n\n\tfor (const entry of entries) {\n\t\tconst entryPath = join(directoryPath, entry.name);\n\n\t\tif (entry.isDirectory()) {\n\t\t\tif (!excludedDirs.has(entry.name) && depth < maxDepth) {\n\t\t\t\tscanDirectory(entryPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.isSymbolicLink()) {\n\t\t\tscanSymbolicLink(entryPath, entry.name, depth, maxDepth, excludedDirs, visitedDirectories, results);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.isFile() && isRuleFile(entry.name)) {\n\t\t\tresults.push({ path: entryPath, realPath: resolveRealPath(entryPath) });\n\t\t}\n\t}\n}\n\nfunction scanSymbolicLink(\n\tlinkPath: string,\n\tlinkName: string,\n\tdepth: number,\n\tmaxDepth: number,\n\texcludedDirs: ReadonlySet<string>,\n\tvisitedDirectories: Set<string>,\n\tresults: ScannedFile[],\n): void {\n\tlet targetStats: Stats;\n\ttry {\n\t\ttargetStats = statSync(linkPath);\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (targetStats.isDirectory()) {\n\t\tif (!excludedDirs.has(linkName) && depth < maxDepth) {\n\t\t\tscanDirectory(linkPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (targetStats.isFile() && isRuleFile(linkName)) {\n\t\tresults.push({ path: linkPath, realPath: resolveRealPath(linkPath) });\n\t}\n}\n\nfunction isRuleFile(fileName: string): boolean {\n\treturn RULE_FILE_EXTENSIONS.some((extension) => fileName.endsWith(extension));\n}\n\nfunction resolveRealPath(filePath: string): string {\n\ttry {\n\t\tconst realPath = realpathSync.native(filePath);\n\t\tconst fileStats = lstatSync(filePath);\n\t\treturn fileStats.isSymbolicLink() ? realPath : filePath;\n\t} catch {\n\t\treturn filePath;\n\t}\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { ToolResultEvent } from "../../../types.ts";
2
+ export declare function isTrackedTool(toolName: string): boolean;
3
+ export declare function extractToolPaths(event: ToolResultEvent, cwd: string): string[];
4
+ //# sourceMappingURL=tool-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-paths.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/tool-paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB9E"}
@@ -0,0 +1,37 @@
1
+ import { isAbsolute, resolve } from "node:path";
2
+ import { TRACKED_BUILTIN_TOOL_SET } from "./constants.js";
3
+ export function isTrackedTool(toolName) {
4
+ return TRACKED_BUILTIN_TOOL_SET.has(toolName);
5
+ }
6
+ export function extractToolPaths(event, cwd) {
7
+ if (event.isError || !isTrackedTool(event.toolName)) {
8
+ return [];
9
+ }
10
+ const filePaths = new Set();
11
+ if (event.toolName === "read" || event.toolName === "edit") {
12
+ addPath(filePaths, getStringProperty(event.details, "filePath"), cwd);
13
+ addPath(filePaths, getStringProperty(event.input, "path"), cwd);
14
+ }
15
+ if (event.toolName === "write") {
16
+ addPath(filePaths, getStringProperty(event.input, "filePath"), cwd);
17
+ addPath(filePaths, getStringProperty(event.input, "path"), cwd);
18
+ }
19
+ return [...filePaths];
20
+ }
21
+ function addPath(filePaths, filePath, cwd) {
22
+ if (filePath === undefined || filePath.length === 0) {
23
+ return;
24
+ }
25
+ filePaths.add(isAbsolute(filePath) ? filePath : resolve(cwd, filePath));
26
+ }
27
+ function getStringProperty(value, propertyName) {
28
+ if (!isRecord(value)) {
29
+ return undefined;
30
+ }
31
+ const propertyValue = value[propertyName];
32
+ return typeof propertyValue === "string" ? propertyValue : undefined;
33
+ }
34
+ function isRecord(value) {
35
+ return typeof value === "object" && value !== null;
36
+ }
37
+ //# sourceMappingURL=tool-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-paths.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/tool-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIhD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC7C,OAAO,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAsB,EAAE,GAAW;IACnE,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC5D,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;QACtE,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;QACpE,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,OAAO,CAAC,SAAsB,EAAE,QAA4B,EAAE,GAAW;IACjF,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO;IACR,CAAC;IAED,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,YAAoB;IAC9D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;IAC1C,OAAO,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;AACtE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACpD,CAAC","sourcesContent":["import { isAbsolute, resolve } from \"node:path\";\n\nimport type { ToolResultEvent } from \"../../../types.ts\";\n\nimport { TRACKED_BUILTIN_TOOL_SET } from \"./constants.ts\";\n\nexport function isTrackedTool(toolName: string): boolean {\n\treturn TRACKED_BUILTIN_TOOL_SET.has(toolName);\n}\n\nexport function extractToolPaths(event: ToolResultEvent, cwd: string): string[] {\n\tif (event.isError || !isTrackedTool(event.toolName)) {\n\t\treturn [];\n\t}\n\n\tconst filePaths = new Set<string>();\n\n\tif (event.toolName === \"read\" || event.toolName === \"edit\") {\n\t\taddPath(filePaths, getStringProperty(event.details, \"filePath\"), cwd);\n\t\taddPath(filePaths, getStringProperty(event.input, \"path\"), cwd);\n\t}\n\n\tif (event.toolName === \"write\") {\n\t\taddPath(filePaths, getStringProperty(event.input, \"filePath\"), cwd);\n\t\taddPath(filePaths, getStringProperty(event.input, \"path\"), cwd);\n\t}\n\n\treturn [...filePaths];\n}\n\nfunction addPath(filePaths: Set<string>, filePath: string | undefined, cwd: string): void {\n\tif (filePath === undefined || filePath.length === 0) {\n\t\treturn;\n\t}\n\n\tfilePaths.add(isAbsolute(filePath) ? filePath : resolve(cwd, filePath));\n}\n\nfunction getStringProperty(value: unknown, propertyName: string): string | undefined {\n\tif (!isRecord(value)) {\n\t\treturn undefined;\n\t}\n\n\tconst propertyValue = value[propertyName];\n\treturn typeof propertyValue === \"string\" ? propertyValue : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import type { TruncationResult } from "./types.ts";
2
+ type BudgetRule = {
3
+ body: string;
4
+ relativePath: string;
5
+ };
6
+ type BudgetResult = BudgetRule & {
7
+ truncated: boolean;
8
+ };
9
+ export declare function truncateRule(body: string, options: {
10
+ maxChars: number;
11
+ relativePath: string;
12
+ }): TruncationResult;
13
+ export declare function truncateBudget(input: {
14
+ rules: ReadonlyArray<BudgetRule>;
15
+ maxResultChars: number;
16
+ }): BudgetResult[];
17
+ export {};
18
+ //# sourceMappingURL=truncator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"truncator.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/truncator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,KAAK,UAAU,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,YAAY,GAAG,UAAU,GAAG;IAChC,SAAS,EAAE,OAAO,CAAC;CACnB,CAAC;AAmBF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAYhH;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,EAAE,CAuBlH"}
@@ -0,0 +1,46 @@
1
+ import { TRUNCATION_NOTICE } from "./constants.js";
2
+ function truncationNotice(relativePath) {
3
+ return TRUNCATION_NOTICE.replace("{path}", relativePath);
4
+ }
5
+ function safeSliceEnd(body, end) {
6
+ if (end <= 0) {
7
+ return 0;
8
+ }
9
+ const lastCodeUnit = body.charCodeAt(end - 1);
10
+ if (lastCodeUnit >= 0xd800 && lastCodeUnit <= 0xdbff) {
11
+ return end - 1;
12
+ }
13
+ return end;
14
+ }
15
+ export function truncateRule(body, options) {
16
+ if (body.length <= options.maxChars) {
17
+ return { body, truncated: false, originalLength: body.length };
18
+ }
19
+ const notice = truncationNotice(options.relativePath);
20
+ if (options.maxChars < notice.length) {
21
+ return { body: notice, truncated: true, originalLength: body.length };
22
+ }
23
+ const sliceEnd = safeSliceEnd(body, options.maxChars - notice.length);
24
+ return { body: `${body.slice(0, sliceEnd)}${notice}`, truncated: true, originalLength: body.length };
25
+ }
26
+ export function truncateBudget(input) {
27
+ const results = [];
28
+ let remainingBudget = input.maxResultChars;
29
+ for (const rule of input.rules) {
30
+ if (remainingBudget >= rule.body.length) {
31
+ results.push({ body: rule.body, truncated: false, relativePath: rule.relativePath });
32
+ remainingBudget -= rule.body.length;
33
+ continue;
34
+ }
35
+ const notice = truncationNotice(rule.relativePath);
36
+ if (remainingBudget <= notice.length) {
37
+ break;
38
+ }
39
+ const sliceEnd = safeSliceEnd(rule.body, remainingBudget - notice.length);
40
+ const body = `${rule.body.slice(0, sliceEnd)}${notice}`;
41
+ results.push({ body, truncated: true, relativePath: rule.relativePath });
42
+ remainingBudget -= body.length;
43
+ }
44
+ return results;
45
+ }
46
+ //# sourceMappingURL=truncator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"truncator.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/truncator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYnD,SAAS,gBAAgB,CAAC,YAAoB;IAC7C,OAAO,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,GAAW;IAC9C,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACd,OAAO,CAAC,CAAC;IACV,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,YAAY,IAAI,MAAM,IAAI,YAAY,IAAI,MAAM,EAAE,CAAC;QACtD,OAAO,GAAG,GAAG,CAAC,CAAC;IAChB,CAAC;IAED,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAmD;IAC7F,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IAChE,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACvE,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACtE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAmE;IACjG,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC;IAE3C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;YACrF,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YACpC,SAAS;QACV,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACnD,IAAI,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM;QACP,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACzE,eAAe,IAAI,IAAI,CAAC,MAAM,CAAC;IAChC,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC","sourcesContent":["import { TRUNCATION_NOTICE } from \"./constants.ts\";\nimport type { TruncationResult } from \"./types.ts\";\n\ntype BudgetRule = {\n\tbody: string;\n\trelativePath: string;\n};\n\ntype BudgetResult = BudgetRule & {\n\ttruncated: boolean;\n};\n\nfunction truncationNotice(relativePath: string): string {\n\treturn TRUNCATION_NOTICE.replace(\"{path}\", relativePath);\n}\n\nfunction safeSliceEnd(body: string, end: number): number {\n\tif (end <= 0) {\n\t\treturn 0;\n\t}\n\n\tconst lastCodeUnit = body.charCodeAt(end - 1);\n\tif (lastCodeUnit >= 0xd800 && lastCodeUnit <= 0xdbff) {\n\t\treturn end - 1;\n\t}\n\n\treturn end;\n}\n\nexport function truncateRule(body: string, options: { maxChars: number; relativePath: string }): TruncationResult {\n\tif (body.length <= options.maxChars) {\n\t\treturn { body, truncated: false, originalLength: body.length };\n\t}\n\n\tconst notice = truncationNotice(options.relativePath);\n\tif (options.maxChars < notice.length) {\n\t\treturn { body: notice, truncated: true, originalLength: body.length };\n\t}\n\n\tconst sliceEnd = safeSliceEnd(body, options.maxChars - notice.length);\n\treturn { body: `${body.slice(0, sliceEnd)}${notice}`, truncated: true, originalLength: body.length };\n}\n\nexport function truncateBudget(input: { rules: ReadonlyArray<BudgetRule>; maxResultChars: number }): BudgetResult[] {\n\tconst results: BudgetResult[] = [];\n\tlet remainingBudget = input.maxResultChars;\n\n\tfor (const rule of input.rules) {\n\t\tif (remainingBudget >= rule.body.length) {\n\t\t\tresults.push({ body: rule.body, truncated: false, relativePath: rule.relativePath });\n\t\t\tremainingBudget -= rule.body.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst notice = truncationNotice(rule.relativePath);\n\t\tif (remainingBudget <= notice.length) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst sliceEnd = safeSliceEnd(rule.body, remainingBudget - notice.length);\n\t\tconst body = `${rule.body.slice(0, sliceEnd)}${notice}`;\n\t\tresults.push({ body, truncated: true, relativePath: rule.relativePath });\n\t\tremainingBudget -= body.length;\n\t}\n\n\treturn results;\n}\n"]}