@asterxsk/kiln 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (491) hide show
  1. package/README.md +155 -170
  2. package/agent/AGENTS.md +67 -67
  3. package/agent/README.md +5 -5
  4. package/agent/extensions/ask-user/index.ts +418 -418
  5. package/agent/extensions/ask-user/install.ps1 +4 -0
  6. package/agent/extensions/ask-user/install.sh +3 -0
  7. package/agent/extensions/ask-user/package-lock.json +769 -769
  8. package/agent/extensions/ask-user/package.json +19 -19
  9. package/agent/extensions/ask-user/prompt.ts +45 -45
  10. package/agent/extensions/ask-user/tsconfig.json +7 -7
  11. package/agent/extensions/background-terminals/docs/implementation-guide.md +942 -942
  12. package/agent/extensions/background-terminals/index.ts +627 -627
  13. package/agent/extensions/background-terminals/install.ps1 +4 -0
  14. package/agent/extensions/background-terminals/install.sh +3 -0
  15. package/agent/extensions/background-terminals/manager.test.ts +735 -735
  16. package/agent/extensions/background-terminals/output.test.ts +109 -109
  17. package/agent/extensions/background-terminals/package-lock.json +769 -769
  18. package/agent/extensions/background-terminals/package.json +17 -17
  19. package/agent/extensions/background-terminals/prompt.test.ts +125 -125
  20. package/agent/extensions/background-terminals/ps.test.ts +82 -82
  21. package/agent/extensions/background-terminals/result-delivery.test.ts +44 -44
  22. package/agent/extensions/background-terminals/src/domain.ts +87 -87
  23. package/agent/extensions/background-terminals/src/manager.ts +907 -907
  24. package/agent/extensions/background-terminals/src/output.ts +84 -84
  25. package/agent/extensions/background-terminals/src/prompt.ts +142 -142
  26. package/agent/extensions/background-terminals/src/result-delivery.ts +27 -27
  27. package/agent/extensions/background-terminals/src/runtime.ts +36 -36
  28. package/agent/extensions/background-terminals/src/ui/output-view.ts +79 -79
  29. package/agent/extensions/background-terminals/src/ui/ps.ts +621 -621
  30. package/agent/extensions/background-terminals/tsconfig.json +7 -7
  31. package/agent/extensions/destructive/install.ps1 +4 -0
  32. package/agent/extensions/destructive/install.sh +3 -0
  33. package/agent/extensions/file-search/index.spec.ts +443 -443
  34. package/agent/extensions/file-search/index.ts +459 -459
  35. package/agent/extensions/file-search/install.ps1 +4 -0
  36. package/agent/extensions/file-search/install.sh +3 -0
  37. package/agent/extensions/file-search/package-lock.json +2253 -2253
  38. package/agent/extensions/file-search/package.json +23 -23
  39. package/agent/extensions/file-search/src/args.ts +122 -122
  40. package/agent/extensions/file-search/src/binaries.ts +422 -422
  41. package/agent/extensions/file-search/src/output.ts +126 -126
  42. package/agent/extensions/file-search/src/process.ts +146 -146
  43. package/agent/extensions/file-search/src/prompt.ts +52 -52
  44. package/agent/extensions/file-search/tsconfig.json +7 -7
  45. package/agent/extensions/goal/install.ps1 +4 -0
  46. package/agent/extensions/goal/install.sh +3 -0
  47. package/agent/extensions/herdr-agent-state.ts +257 -0
  48. package/agent/extensions/kiln-update/README.md +25 -0
  49. package/agent/extensions/kiln-update/index.ts +99 -0
  50. package/agent/extensions/kiln-update/install.ps1 +27 -0
  51. package/agent/extensions/kiln-update/install.sh +24 -0
  52. package/agent/extensions/modelconf/PLAN.md +915 -915
  53. package/agent/extensions/modelconf/index.ts +296 -296
  54. package/agent/extensions/modelconf/install.ps1 +4 -0
  55. package/agent/extensions/modelconf/install.sh +3 -0
  56. package/agent/extensions/modelconf/src/ui/ModelConfView.ts +1101 -1101
  57. package/agent/extensions/pi-web-access/CHANGELOG.md +690 -690
  58. package/agent/extensions/pi-web-access/LICENSE +21 -21
  59. package/agent/extensions/pi-web-access/README.md +470 -470
  60. package/agent/extensions/pi-web-access/SECURITY.md +5 -5
  61. package/agent/extensions/pi-web-access/activity.ts +101 -101
  62. package/agent/extensions/pi-web-access/auth-fetch.ts +148 -148
  63. package/agent/extensions/pi-web-access/brightdata-unlocker.ts +272 -272
  64. package/agent/extensions/pi-web-access/chrome-cookies.ts +669 -669
  65. package/agent/extensions/pi-web-access/content-find.ts +139 -139
  66. package/agent/extensions/pi-web-access/credential-source.ts +191 -191
  67. package/agent/extensions/pi-web-access/data-uri-sanitize.ts +406 -406
  68. package/agent/extensions/pi-web-access/datalab-pdf-extract.ts +568 -568
  69. package/agent/extensions/pi-web-access/declared-web-links.ts +173 -173
  70. package/agent/extensions/pi-web-access/evidence/CONTRACT-EVIDENCE.md +496 -496
  71. package/agent/extensions/pi-web-access/evidence/contract-probe.mjs +140 -140
  72. package/agent/extensions/pi-web-access/exa.ts +526 -526
  73. package/agent/extensions/pi-web-access/extract.ts +1196 -1196
  74. package/agent/extensions/pi-web-access/feature-config.ts +29 -29
  75. package/agent/extensions/pi-web-access/fetch-params.ts +111 -111
  76. package/agent/extensions/pi-web-access/gemini-adc.ts +298 -298
  77. package/agent/extensions/pi-web-access/gemini-api.ts +353 -353
  78. package/agent/extensions/pi-web-access/gemini-pdf-extract.ts +108 -108
  79. package/agent/extensions/pi-web-access/gemini-url-context.ts +128 -128
  80. package/agent/extensions/pi-web-access/gemini-web-config.ts +101 -101
  81. package/agent/extensions/pi-web-access/gemini-web.ts +487 -487
  82. package/agent/extensions/pi-web-access/github-api.ts +197 -197
  83. package/agent/extensions/pi-web-access/github-extract.ts +746 -746
  84. package/agent/extensions/pi-web-access/github-issue-pr.ts +700 -700
  85. package/agent/extensions/pi-web-access/index.ts +1737 -1737
  86. package/agent/extensions/pi-web-access/package-lock.json +5808 -5808
  87. package/agent/extensions/pi-web-access/package.json +64 -64
  88. package/agent/extensions/pi-web-access/page-query.ts +96 -96
  89. package/agent/extensions/pi-web-access/pdf-extract.ts +409 -409
  90. package/agent/extensions/pi-web-access/promise-try.d.ts +7 -7
  91. package/agent/extensions/pi-web-access/query-rewrite.ts +51 -51
  92. package/agent/extensions/pi-web-access/render-search-error.ts +170 -170
  93. package/agent/extensions/pi-web-access/rsc-extract.ts +338 -338
  94. package/agent/extensions/pi-web-access/source-check.ts +282 -282
  95. package/agent/extensions/pi-web-access/ssrf-protection.ts +526 -526
  96. package/agent/extensions/pi-web-access/storage.ts +521 -521
  97. package/agent/extensions/pi-web-access/summary-model-scope.ts +125 -125
  98. package/agent/extensions/pi-web-access/test/auth-fetch.test.mjs +208 -208
  99. package/agent/extensions/pi-web-access/test/brightdata-unlocker.test.mjs +840 -840
  100. package/agent/extensions/pi-web-access/test/chrome-cookie-extraction.test.mjs +441 -441
  101. package/agent/extensions/pi-web-access/test/config-path.test.mjs +283 -283
  102. package/agent/extensions/pi-web-access/test/content-find.test.mjs +25 -25
  103. package/agent/extensions/pi-web-access/test/credential-source.test.mjs +118 -118
  104. package/agent/extensions/pi-web-access/test/data-uri-sanitize.test.mjs +210 -210
  105. package/agent/extensions/pi-web-access/test/datalab-pdf-extract.test.mjs +552 -552
  106. package/agent/extensions/pi-web-access/test/declared-web-links.test.mjs +212 -212
  107. package/agent/extensions/pi-web-access/test/fetch-answer-storage.test.mjs +40 -40
  108. package/agent/extensions/pi-web-access/test/fetch-cache-storage.test.mjs +334 -334
  109. package/agent/extensions/pi-web-access/test/fetch-content-domain-policy.test.mjs +95 -95
  110. package/agent/extensions/pi-web-access/test/fetch-modes.test.mjs +53 -53
  111. package/agent/extensions/pi-web-access/test/fetch-not-found-guidance.test.mjs +92 -92
  112. package/agent/extensions/pi-web-access/test/fetch-params.test.mjs +86 -86
  113. package/agent/extensions/pi-web-access/test/fetch-render-call.test.mjs +34 -34
  114. package/agent/extensions/pi-web-access/test/fetch-routing.test.mjs +173 -173
  115. package/agent/extensions/pi-web-access/test/gemini-adc-auth.test.mjs +257 -257
  116. package/agent/extensions/pi-web-access/test/gemini-api-transport.test.mjs +170 -170
  117. package/agent/extensions/pi-web-access/test/gemini-pdf-extract.test.mjs +133 -133
  118. package/agent/extensions/pi-web-access/test/gemini-web-cookie-opt-in.test.mjs +178 -178
  119. package/agent/extensions/pi-web-access/test/gemini-web-header-overflow.test.mjs +148 -148
  120. package/agent/extensions/pi-web-access/test/get-search-content.test.mjs +223 -223
  121. package/agent/extensions/pi-web-access/test/github-extract.test.mjs +378 -378
  122. package/agent/extensions/pi-web-access/test/github-issue-pr.test.mjs +565 -565
  123. package/agent/extensions/pi-web-access/test/inline-content-config.test.mjs +99 -99
  124. package/agent/extensions/pi-web-access/test/lazy-extract-load.test.mjs +118 -118
  125. package/agent/extensions/pi-web-access/test/local-video-oversize.test.mjs +52 -52
  126. package/agent/extensions/pi-web-access/test/package-typebox-dependency.test.mjs +50 -50
  127. package/agent/extensions/pi-web-access/test/page-query.test.mjs +51 -51
  128. package/agent/extensions/pi-web-access/test/pdf-config.test.mjs +140 -140
  129. package/agent/extensions/pi-web-access/test/pdf-extract.test.mjs +500 -500
  130. package/agent/extensions/pi-web-access/test/proxy-transport.test.mjs +286 -286
  131. package/agent/extensions/pi-web-access/test/query-rewrite.test.mjs +52 -52
  132. package/agent/extensions/pi-web-access/test/rsc-fallback.test.mjs +102 -102
  133. package/agent/extensions/pi-web-access/test/search-error-render.test.mjs +152 -152
  134. package/agent/extensions/pi-web-access/test/search-providers.test.mjs +274 -274
  135. package/agent/extensions/pi-web-access/test/source-check.test.mjs +179 -179
  136. package/agent/extensions/pi-web-access/test/ssrf-allow-ranges-config.test.mjs +205 -205
  137. package/agent/extensions/pi-web-access/test/ssrf-protection.test.mjs +456 -456
  138. package/agent/extensions/pi-web-access/test/tool-registration-config.test.mjs +182 -182
  139. package/agent/extensions/pi-web-access/test/youtube-extract-errors.test.mjs +64 -64
  140. package/agent/extensions/pi-web-access/tsconfig.json +11 -11
  141. package/agent/extensions/pi-web-access/utils.ts +451 -451
  142. package/agent/extensions/pi-web-access/video-extract.ts +392 -392
  143. package/agent/extensions/pi-web-access/youtube-extract.ts +328 -328
  144. package/agent/extensions/shared/activity-status.ts +31 -31
  145. package/agent/extensions/shared/child-session.test.ts +270 -270
  146. package/agent/extensions/shared/child-session.ts +148 -148
  147. package/agent/extensions/shared/context-utilization.test.ts +48 -48
  148. package/agent/extensions/shared/context-utilization.ts +47 -47
  149. package/agent/extensions/shared/dashboard-state.ts +99 -99
  150. package/agent/extensions/shared/install.ps1 +4 -0
  151. package/agent/extensions/shared/install.sh +3 -0
  152. package/agent/extensions/shared/tool-call-timeout.test.ts +117 -117
  153. package/agent/extensions/shared/tool-call-timeout.ts +104 -104
  154. package/agent/extensions/skillsconf/install.ps1 +4 -0
  155. package/agent/extensions/skillsconf/install.sh +3 -0
  156. package/agent/extensions/statusline/index.ts +282 -0
  157. package/agent/extensions/statusline/install.ps1 +27 -0
  158. package/agent/extensions/statusline/install.sh +24 -0
  159. package/agent/extensions/subagents/by-the-way.test.ts +29 -29
  160. package/agent/extensions/subagents/claude.test.ts +119 -119
  161. package/agent/extensions/subagents/codex.test.ts +102 -102
  162. package/agent/extensions/subagents/context-usage.test.ts +107 -107
  163. package/agent/extensions/subagents/docs/design-plan.md +568 -568
  164. package/agent/extensions/subagents/docs/effect-v4-extension-guide.md +354 -354
  165. package/agent/extensions/subagents/docs/effect-v4-notes.md +571 -571
  166. package/agent/extensions/subagents/index.ts +779 -779
  167. package/agent/extensions/subagents/install.ps1 +4 -0
  168. package/agent/extensions/subagents/install.sh +3 -0
  169. package/agent/extensions/subagents/manager.test.ts +276 -276
  170. package/agent/extensions/subagents/package-lock.json +2244 -2244
  171. package/agent/extensions/subagents/package.json +19 -19
  172. package/agent/extensions/subagents/result-delivery.test.ts +27 -27
  173. package/agent/extensions/subagents/src/backend.ts +73 -73
  174. package/agent/extensions/subagents/src/backends/claude.ts +701 -701
  175. package/agent/extensions/subagents/src/backends/codex.ts +1060 -1060
  176. package/agent/extensions/subagents/src/backends/pi.ts +575 -575
  177. package/agent/extensions/subagents/src/backends/stub.ts +300 -300
  178. package/agent/extensions/subagents/src/by-the-way.ts +21 -21
  179. package/agent/extensions/subagents/src/domain.ts +253 -253
  180. package/agent/extensions/subagents/src/format.ts +74 -74
  181. package/agent/extensions/subagents/src/manager.ts +736 -736
  182. package/agent/extensions/subagents/src/prompt.ts +92 -92
  183. package/agent/extensions/subagents/src/result-delivery.ts +20 -20
  184. package/agent/extensions/subagents/src/runtime.ts +53 -53
  185. package/agent/extensions/subagents/src/ui/takeover.ts +583 -583
  186. package/agent/extensions/subagents/src/ui/transcript.ts +201 -201
  187. package/agent/extensions/subagents/takeover.test.ts +29 -29
  188. package/agent/extensions/subagents/tsconfig.json +7 -7
  189. package/agent/extensions/taste/install.ps1 +4 -0
  190. package/agent/extensions/taste/install.sh +3 -0
  191. package/agent/extensions/todo/AGENTS.md +38 -38
  192. package/agent/extensions/todo/LICENSE +21 -21
  193. package/agent/extensions/todo/config.ts +55 -55
  194. package/agent/extensions/todo/index.ts +151 -151
  195. package/agent/extensions/todo/install.ps1 +4 -0
  196. package/agent/extensions/todo/install.sh +3 -0
  197. package/agent/extensions/todo/locales/de.json +17 -17
  198. package/agent/extensions/todo/locales/en.json +15 -15
  199. package/agent/extensions/todo/locales/es.json +17 -17
  200. package/agent/extensions/todo/locales/fr.json +17 -17
  201. package/agent/extensions/todo/locales/pt-BR.json +17 -17
  202. package/agent/extensions/todo/locales/pt.json +17 -17
  203. package/agent/extensions/todo/locales/ru.json +17 -17
  204. package/agent/extensions/todo/locales/uk.json +17 -17
  205. package/agent/extensions/todo/locales/zh.json +17 -17
  206. package/agent/extensions/todo/package-lock.json +3358 -3358
  207. package/agent/extensions/todo/package.json +67 -67
  208. package/agent/extensions/todo/state/i18n-bridge.ts +64 -64
  209. package/agent/extensions/todo/state/invariants.ts +20 -20
  210. package/agent/extensions/todo/state/replay.ts +38 -38
  211. package/agent/extensions/todo/state/selectors.ts +107 -107
  212. package/agent/extensions/todo/state/state-reducer.ts +326 -326
  213. package/agent/extensions/todo/state/state.ts +18 -18
  214. package/agent/extensions/todo/state/store.ts +82 -82
  215. package/agent/extensions/todo/state/task-graph.ts +57 -57
  216. package/agent/extensions/todo/todo-overlay.ts +200 -200
  217. package/agent/extensions/todo/todo.ts +155 -155
  218. package/agent/extensions/todo/tool/response-envelope.ts +109 -109
  219. package/agent/extensions/todo/tool/types.ts +206 -206
  220. package/agent/extensions/todo/view/format.ts +177 -177
  221. package/agent/extensions/trim-context/install.ps1 +4 -0
  222. package/agent/extensions/trim-context/install.sh +3 -0
  223. package/agent/keybindings.json +7 -7
  224. package/agent/version.txt +1 -0
  225. package/agent.bak.20260905-190020/AGENTS.md +67 -0
  226. package/agent.bak.20260905-190020/README.md +5 -0
  227. package/agent.bak.20260905-190020/extensions/ask-user/index.ts +418 -0
  228. package/agent.bak.20260905-190020/extensions/ask-user/package-lock.json +769 -0
  229. package/agent.bak.20260905-190020/extensions/ask-user/package.json +19 -0
  230. package/agent.bak.20260905-190020/extensions/ask-user/prompt.ts +45 -0
  231. package/agent.bak.20260905-190020/extensions/ask-user/tsconfig.json +7 -0
  232. package/agent.bak.20260905-190020/extensions/background-terminals/docs/implementation-guide.md +942 -0
  233. package/agent.bak.20260905-190020/extensions/background-terminals/index.ts +629 -0
  234. package/agent.bak.20260905-190020/extensions/background-terminals/install.ps1 +23 -0
  235. package/agent.bak.20260905-190020/extensions/background-terminals/install.sh +21 -0
  236. package/agent.bak.20260905-190020/extensions/background-terminals/package-lock.json +769 -0
  237. package/agent.bak.20260905-190020/extensions/background-terminals/package.json +17 -0
  238. package/agent.bak.20260905-190020/extensions/background-terminals/src/domain.ts +87 -0
  239. package/agent.bak.20260905-190020/extensions/background-terminals/src/manager.ts +907 -0
  240. package/agent.bak.20260905-190020/extensions/background-terminals/src/output.ts +84 -0
  241. package/agent.bak.20260905-190020/extensions/background-terminals/src/prompt.ts +142 -0
  242. package/agent.bak.20260905-190020/extensions/background-terminals/src/result-delivery.ts +27 -0
  243. package/agent.bak.20260905-190020/extensions/background-terminals/src/runtime.ts +36 -0
  244. package/agent.bak.20260905-190020/extensions/background-terminals/src/ui/output-view.ts +79 -0
  245. package/agent.bak.20260905-190020/extensions/background-terminals/src/ui/ps.ts +621 -0
  246. package/agent.bak.20260905-190020/extensions/background-terminals/src/widget-order.ts +121 -0
  247. package/agent.bak.20260905-190020/extensions/background-terminals/test/manager.test.ts +735 -0
  248. package/agent.bak.20260905-190020/extensions/background-terminals/test/output.test.ts +109 -0
  249. package/agent.bak.20260905-190020/extensions/background-terminals/test/prompt.test.ts +125 -0
  250. package/agent.bak.20260905-190020/extensions/background-terminals/test/ps.test.ts +82 -0
  251. package/agent.bak.20260905-190020/extensions/background-terminals/test/result-delivery.test.ts +44 -0
  252. package/agent.bak.20260905-190020/extensions/background-terminals/tsconfig.json +7 -0
  253. package/agent.bak.20260905-190020/extensions/destructive/README.md +34 -0
  254. package/agent.bak.20260905-190020/extensions/destructive/index.ts +124 -0
  255. package/agent.bak.20260905-190020/extensions/destructive/install.ps1 +23 -0
  256. package/agent.bak.20260905-190020/extensions/destructive/install.sh +21 -0
  257. package/agent.bak.20260905-190020/extensions/file-search/index.ts +459 -0
  258. package/agent.bak.20260905-190020/extensions/file-search/install.ps1 +23 -0
  259. package/agent.bak.20260905-190020/extensions/file-search/install.sh +21 -0
  260. package/agent.bak.20260905-190020/extensions/file-search/package-lock.json +2253 -0
  261. package/agent.bak.20260905-190020/extensions/file-search/package.json +23 -0
  262. package/agent.bak.20260905-190020/extensions/file-search/src/args.ts +122 -0
  263. package/agent.bak.20260905-190020/extensions/file-search/src/binaries.ts +422 -0
  264. package/agent.bak.20260905-190020/extensions/file-search/src/output.ts +126 -0
  265. package/agent.bak.20260905-190020/extensions/file-search/src/process.ts +146 -0
  266. package/agent.bak.20260905-190020/extensions/file-search/src/prompt.ts +52 -0
  267. package/agent.bak.20260905-190020/extensions/file-search/test/index.spec.ts +443 -0
  268. package/agent.bak.20260905-190020/extensions/file-search/tsconfig.json +7 -0
  269. package/agent.bak.20260905-190020/extensions/goal/README.md +50 -0
  270. package/agent.bak.20260905-190020/extensions/goal/index.ts +155 -0
  271. package/agent.bak.20260905-190020/extensions/goal/install.ps1 +23 -0
  272. package/agent.bak.20260905-190020/extensions/goal/install.sh +21 -0
  273. package/agent.bak.20260905-190020/extensions/kiln-update/README.md +25 -0
  274. package/agent.bak.20260905-190020/extensions/kiln-update/index.ts +99 -0
  275. package/agent.bak.20260905-190020/extensions/kiln-update/install.ps1 +23 -0
  276. package/agent.bak.20260905-190020/extensions/kiln-update/install.sh +21 -0
  277. package/agent.bak.20260905-190020/extensions/modelconf/PLAN.md +915 -0
  278. package/agent.bak.20260905-190020/extensions/modelconf/README.md +66 -0
  279. package/agent.bak.20260905-190020/extensions/modelconf/index.ts +296 -0
  280. package/agent.bak.20260905-190020/extensions/modelconf/install.ps1 +23 -0
  281. package/agent.bak.20260905-190020/extensions/modelconf/install.sh +21 -0
  282. package/agent.bak.20260905-190020/extensions/modelconf/package-lock.json +1809 -0
  283. package/agent.bak.20260905-190020/extensions/modelconf/package.json +13 -0
  284. package/agent.bak.20260905-190020/extensions/modelconf/src/fuzzy.ts +26 -0
  285. package/agent.bak.20260905-190020/extensions/modelconf/src/glob.ts +13 -0
  286. package/agent.bak.20260905-190020/extensions/modelconf/src/persistence.test.ts +46 -0
  287. package/agent.bak.20260905-190020/extensions/modelconf/src/persistence.ts +164 -0
  288. package/agent.bak.20260905-190020/extensions/modelconf/src/ui/ModelConfView.test.ts +75 -0
  289. package/agent.bak.20260905-190020/extensions/modelconf/src/ui/ModelConfView.ts +1101 -0
  290. package/agent.bak.20260905-190020/extensions/modelconf/tsconfig.json +15 -0
  291. package/agent.bak.20260905-190020/extensions/pi-web-access/CHANGELOG.md +690 -0
  292. package/agent.bak.20260905-190020/extensions/pi-web-access/LICENSE +21 -0
  293. package/agent.bak.20260905-190020/extensions/pi-web-access/README.md +470 -0
  294. package/agent.bak.20260905-190020/extensions/pi-web-access/SECURITY.md +5 -0
  295. package/agent.bak.20260905-190020/extensions/pi-web-access/activity.ts +101 -0
  296. package/agent.bak.20260905-190020/extensions/pi-web-access/auth-fetch.ts +148 -0
  297. package/agent.bak.20260905-190020/extensions/pi-web-access/banner.png +0 -0
  298. package/agent.bak.20260905-190020/extensions/pi-web-access/brightdata-unlocker.ts +272 -0
  299. package/agent.bak.20260905-190020/extensions/pi-web-access/chrome-cookies.ts +669 -0
  300. package/agent.bak.20260905-190020/extensions/pi-web-access/content-find.ts +139 -0
  301. package/agent.bak.20260905-190020/extensions/pi-web-access/credential-source.ts +191 -0
  302. package/agent.bak.20260905-190020/extensions/pi-web-access/data-uri-sanitize.ts +406 -0
  303. package/agent.bak.20260905-190020/extensions/pi-web-access/datalab-pdf-extract.ts +568 -0
  304. package/agent.bak.20260905-190020/extensions/pi-web-access/declared-web-links.ts +173 -0
  305. package/agent.bak.20260905-190020/extensions/pi-web-access/evidence/CONTRACT-EVIDENCE.md +496 -0
  306. package/agent.bak.20260905-190020/extensions/pi-web-access/evidence/contract-probe.mjs +140 -0
  307. package/agent.bak.20260905-190020/extensions/pi-web-access/exa.ts +526 -0
  308. package/agent.bak.20260905-190020/extensions/pi-web-access/extract.ts +1196 -0
  309. package/agent.bak.20260905-190020/extensions/pi-web-access/feature-config.ts +29 -0
  310. package/agent.bak.20260905-190020/extensions/pi-web-access/fetch-params.ts +111 -0
  311. package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-adc.ts +298 -0
  312. package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-api.ts +353 -0
  313. package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-pdf-extract.ts +108 -0
  314. package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-search.ts +21 -0
  315. package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-url-context.ts +128 -0
  316. package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-web-config.ts +101 -0
  317. package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-web.ts +487 -0
  318. package/agent.bak.20260905-190020/extensions/pi-web-access/github-api.ts +197 -0
  319. package/agent.bak.20260905-190020/extensions/pi-web-access/github-extract.ts +746 -0
  320. package/agent.bak.20260905-190020/extensions/pi-web-access/github-issue-pr.ts +700 -0
  321. package/agent.bak.20260905-190020/extensions/pi-web-access/index.ts +1737 -0
  322. package/agent.bak.20260905-190020/extensions/pi-web-access/package-lock.json +5808 -0
  323. package/agent.bak.20260905-190020/extensions/pi-web-access/package.json +64 -0
  324. package/agent.bak.20260905-190020/extensions/pi-web-access/page-query.ts +96 -0
  325. package/agent.bak.20260905-190020/extensions/pi-web-access/pdf-extract.ts +409 -0
  326. package/agent.bak.20260905-190020/extensions/pi-web-access/pi-web-fetch-demo.mp4 +0 -0
  327. package/agent.bak.20260905-190020/extensions/pi-web-access/promise-try.d.ts +7 -0
  328. package/agent.bak.20260905-190020/extensions/pi-web-access/query-rewrite.ts +51 -0
  329. package/agent.bak.20260905-190020/extensions/pi-web-access/render-search-error.ts +170 -0
  330. package/agent.bak.20260905-190020/extensions/pi-web-access/rsc-extract.ts +338 -0
  331. package/agent.bak.20260905-190020/extensions/pi-web-access/search-types.ts +20 -0
  332. package/agent.bak.20260905-190020/extensions/pi-web-access/source-check.ts +282 -0
  333. package/agent.bak.20260905-190020/extensions/pi-web-access/ssrf-protection.ts +526 -0
  334. package/agent.bak.20260905-190020/extensions/pi-web-access/storage.ts +521 -0
  335. package/agent.bak.20260905-190020/extensions/pi-web-access/summary-model-scope.ts +125 -0
  336. package/agent.bak.20260905-190020/extensions/pi-web-access/test/auth-fetch.test.mjs +208 -0
  337. package/agent.bak.20260905-190020/extensions/pi-web-access/test/brightdata-unlocker.test.mjs +840 -0
  338. package/agent.bak.20260905-190020/extensions/pi-web-access/test/chrome-cookie-extraction.test.mjs +441 -0
  339. package/agent.bak.20260905-190020/extensions/pi-web-access/test/config-path.test.mjs +283 -0
  340. package/agent.bak.20260905-190020/extensions/pi-web-access/test/content-find.test.mjs +25 -0
  341. package/agent.bak.20260905-190020/extensions/pi-web-access/test/credential-source.test.mjs +118 -0
  342. package/agent.bak.20260905-190020/extensions/pi-web-access/test/data-uri-sanitize.test.mjs +210 -0
  343. package/agent.bak.20260905-190020/extensions/pi-web-access/test/datalab-pdf-extract.test.mjs +552 -0
  344. package/agent.bak.20260905-190020/extensions/pi-web-access/test/declared-web-links.test.mjs +212 -0
  345. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-answer-storage.test.mjs +40 -0
  346. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-cache-storage.test.mjs +334 -0
  347. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-content-domain-policy.test.mjs +95 -0
  348. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-modes.test.mjs +53 -0
  349. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-not-found-guidance.test.mjs +92 -0
  350. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-params.test.mjs +86 -0
  351. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-render-call.test.mjs +34 -0
  352. package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-routing.test.mjs +173 -0
  353. package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-adc-auth.test.mjs +257 -0
  354. package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-api-transport.test.mjs +170 -0
  355. package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-pdf-extract.test.mjs +133 -0
  356. package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-web-cookie-opt-in.test.mjs +178 -0
  357. package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-web-header-overflow.test.mjs +148 -0
  358. package/agent.bak.20260905-190020/extensions/pi-web-access/test/get-search-content.test.mjs +223 -0
  359. package/agent.bak.20260905-190020/extensions/pi-web-access/test/github-extract.test.mjs +378 -0
  360. package/agent.bak.20260905-190020/extensions/pi-web-access/test/github-issue-pr.test.mjs +565 -0
  361. package/agent.bak.20260905-190020/extensions/pi-web-access/test/inline-content-config.test.mjs +99 -0
  362. package/agent.bak.20260905-190020/extensions/pi-web-access/test/lazy-extract-load.test.mjs +118 -0
  363. package/agent.bak.20260905-190020/extensions/pi-web-access/test/local-video-oversize.test.mjs +52 -0
  364. package/agent.bak.20260905-190020/extensions/pi-web-access/test/package-typebox-dependency.test.mjs +50 -0
  365. package/agent.bak.20260905-190020/extensions/pi-web-access/test/page-query.test.mjs +51 -0
  366. package/agent.bak.20260905-190020/extensions/pi-web-access/test/pdf-config.test.mjs +140 -0
  367. package/agent.bak.20260905-190020/extensions/pi-web-access/test/pdf-extract.test.mjs +500 -0
  368. package/agent.bak.20260905-190020/extensions/pi-web-access/test/proxy-transport.test.mjs +286 -0
  369. package/agent.bak.20260905-190020/extensions/pi-web-access/test/query-rewrite.test.mjs +52 -0
  370. package/agent.bak.20260905-190020/extensions/pi-web-access/test/rsc-fallback.test.mjs +102 -0
  371. package/agent.bak.20260905-190020/extensions/pi-web-access/test/search-error-render.test.mjs +152 -0
  372. package/agent.bak.20260905-190020/extensions/pi-web-access/test/search-providers.test.mjs +274 -0
  373. package/agent.bak.20260905-190020/extensions/pi-web-access/test/source-check.test.mjs +179 -0
  374. package/agent.bak.20260905-190020/extensions/pi-web-access/test/ssrf-allow-ranges-config.test.mjs +205 -0
  375. package/agent.bak.20260905-190020/extensions/pi-web-access/test/ssrf-protection.test.mjs +456 -0
  376. package/agent.bak.20260905-190020/extensions/pi-web-access/test/summary-model-scope.test.mjs +106 -0
  377. package/agent.bak.20260905-190020/extensions/pi-web-access/test/tool-registration-config.test.mjs +182 -0
  378. package/agent.bak.20260905-190020/extensions/pi-web-access/test/web-search-answer-render.test.mjs +66 -0
  379. package/agent.bak.20260905-190020/extensions/pi-web-access/test/youtube-extract-errors.test.mjs +64 -0
  380. package/agent.bak.20260905-190020/extensions/pi-web-access/tsconfig.json +11 -0
  381. package/agent.bak.20260905-190020/extensions/pi-web-access/utils.ts +451 -0
  382. package/agent.bak.20260905-190020/extensions/pi-web-access/video-extract.ts +392 -0
  383. package/agent.bak.20260905-190020/extensions/pi-web-access/youtube-extract.ts +328 -0
  384. package/agent.bak.20260905-190020/extensions/shared/activity-status.ts +31 -0
  385. package/agent.bak.20260905-190020/extensions/shared/child-session.ts +148 -0
  386. package/agent.bak.20260905-190020/extensions/shared/context-utilization.ts +47 -0
  387. package/agent.bak.20260905-190020/extensions/shared/dashboard-state.ts +99 -0
  388. package/agent.bak.20260905-190020/extensions/shared/install.ps1 +23 -0
  389. package/agent.bak.20260905-190020/extensions/shared/install.sh +21 -0
  390. package/agent.bak.20260905-190020/extensions/shared/test/child-session.test.ts +270 -0
  391. package/agent.bak.20260905-190020/extensions/shared/test/context-utilization.test.ts +48 -0
  392. package/agent.bak.20260905-190020/extensions/shared/test/tool-call-timeout.test.ts +117 -0
  393. package/agent.bak.20260905-190020/extensions/shared/test/widget-order.test.ts +167 -0
  394. package/agent.bak.20260905-190020/extensions/shared/tool-call-timeout.ts +104 -0
  395. package/agent.bak.20260905-190020/extensions/skillsconf/README.md +74 -0
  396. package/agent.bak.20260905-190020/extensions/skillsconf/index.ts +92 -0
  397. package/agent.bak.20260905-190020/extensions/skillsconf/install.ps1 +23 -0
  398. package/agent.bak.20260905-190020/extensions/skillsconf/install.sh +21 -0
  399. package/agent.bak.20260905-190020/extensions/skillsconf/package-lock.json +1809 -0
  400. package/agent.bak.20260905-190020/extensions/skillsconf/package.json +18 -0
  401. package/agent.bak.20260905-190020/extensions/skillsconf/src/delete-skill.test.ts +64 -0
  402. package/agent.bak.20260905-190020/extensions/skillsconf/src/delete-skill.ts +45 -0
  403. package/agent.bak.20260905-190020/extensions/skillsconf/src/filter.test.ts +80 -0
  404. package/agent.bak.20260905-190020/extensions/skillsconf/src/filter.ts +74 -0
  405. package/agent.bak.20260905-190020/extensions/skillsconf/src/fuzzy.ts +26 -0
  406. package/agent.bak.20260905-190020/extensions/skillsconf/src/persistence.test.ts +72 -0
  407. package/agent.bak.20260905-190020/extensions/skillsconf/src/persistence.ts +169 -0
  408. package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/SkillConfView.test.ts +337 -0
  409. package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/SkillConfView.ts +758 -0
  410. package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/text-input.ts +91 -0
  411. package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/tui-helpers.ts +144 -0
  412. package/agent.bak.20260905-190020/extensions/skillsconf/tsconfig.json +15 -0
  413. package/agent.bak.20260905-190020/extensions/statusline/install.ps1 +23 -0
  414. package/agent.bak.20260905-190020/extensions/statusline/install.sh +21 -0
  415. package/agent.bak.20260905-190020/extensions/subagents/docs/design-plan.md +568 -0
  416. package/agent.bak.20260905-190020/extensions/subagents/docs/effect-v4-extension-guide.md +354 -0
  417. package/agent.bak.20260905-190020/extensions/subagents/docs/effect-v4-notes.md +571 -0
  418. package/agent.bak.20260905-190020/extensions/subagents/index.ts +826 -0
  419. package/agent.bak.20260905-190020/extensions/subagents/install.ps1 +23 -0
  420. package/agent.bak.20260905-190020/extensions/subagents/install.sh +21 -0
  421. package/agent.bak.20260905-190020/extensions/subagents/package-lock.json +2244 -0
  422. package/agent.bak.20260905-190020/extensions/subagents/package.json +19 -0
  423. package/agent.bak.20260905-190020/extensions/subagents/src/backend.ts +73 -0
  424. package/agent.bak.20260905-190020/extensions/subagents/src/backends/claude.ts +701 -0
  425. package/agent.bak.20260905-190020/extensions/subagents/src/backends/codex.ts +1060 -0
  426. package/agent.bak.20260905-190020/extensions/subagents/src/backends/pi.ts +575 -0
  427. package/agent.bak.20260905-190020/extensions/subagents/src/backends/stub.ts +300 -0
  428. package/agent.bak.20260905-190020/extensions/subagents/src/by-the-way.ts +21 -0
  429. package/agent.bak.20260905-190020/extensions/subagents/src/domain.ts +253 -0
  430. package/agent.bak.20260905-190020/extensions/subagents/src/format.ts +74 -0
  431. package/agent.bak.20260905-190020/extensions/subagents/src/manager.ts +736 -0
  432. package/agent.bak.20260905-190020/extensions/subagents/src/prompt.ts +92 -0
  433. package/agent.bak.20260905-190020/extensions/subagents/src/result-delivery.ts +20 -0
  434. package/agent.bak.20260905-190020/extensions/subagents/src/runtime.ts +53 -0
  435. package/agent.bak.20260905-190020/extensions/subagents/src/ui/takeover.ts +583 -0
  436. package/agent.bak.20260905-190020/extensions/subagents/src/ui/transcript.ts +201 -0
  437. package/agent.bak.20260905-190020/extensions/subagents/src/widget-order.ts +121 -0
  438. package/agent.bak.20260905-190020/extensions/subagents/test/by-the-way.test.ts +29 -0
  439. package/agent.bak.20260905-190020/extensions/subagents/test/claude.test.ts +119 -0
  440. package/agent.bak.20260905-190020/extensions/subagents/test/codex.test.ts +102 -0
  441. package/agent.bak.20260905-190020/extensions/subagents/test/context-usage.test.ts +107 -0
  442. package/agent.bak.20260905-190020/extensions/subagents/test/manager.test.ts +276 -0
  443. package/agent.bak.20260905-190020/extensions/subagents/test/result-delivery.test.ts +27 -0
  444. package/agent.bak.20260905-190020/extensions/subagents/test/takeover.test.ts +29 -0
  445. package/agent.bak.20260905-190020/extensions/subagents/tsconfig.json +7 -0
  446. package/agent.bak.20260905-190020/extensions/taste/index.ts +443 -0
  447. package/agent.bak.20260905-190020/extensions/taste/install.ps1 +23 -0
  448. package/agent.bak.20260905-190020/extensions/taste/install.sh +21 -0
  449. package/agent.bak.20260905-190020/extensions/todo/AGENTS.md +38 -0
  450. package/agent.bak.20260905-190020/extensions/todo/LICENSE +21 -0
  451. package/agent.bak.20260905-190020/extensions/todo/config.ts +55 -0
  452. package/agent.bak.20260905-190020/extensions/todo/index.ts +151 -0
  453. package/agent.bak.20260905-190020/extensions/todo/install.ps1 +23 -0
  454. package/agent.bak.20260905-190020/extensions/todo/install.sh +21 -0
  455. package/agent.bak.20260905-190020/extensions/todo/locales/de.json +17 -0
  456. package/agent.bak.20260905-190020/extensions/todo/locales/en.json +15 -0
  457. package/agent.bak.20260905-190020/extensions/todo/locales/es.json +17 -0
  458. package/agent.bak.20260905-190020/extensions/todo/locales/fr.json +17 -0
  459. package/agent.bak.20260905-190020/extensions/todo/locales/pt-BR.json +17 -0
  460. package/agent.bak.20260905-190020/extensions/todo/locales/pt.json +17 -0
  461. package/agent.bak.20260905-190020/extensions/todo/locales/ru.json +17 -0
  462. package/agent.bak.20260905-190020/extensions/todo/locales/uk.json +17 -0
  463. package/agent.bak.20260905-190020/extensions/todo/locales/zh.json +17 -0
  464. package/agent.bak.20260905-190020/extensions/todo/package-lock.json +3358 -0
  465. package/agent.bak.20260905-190020/extensions/todo/package.json +67 -0
  466. package/agent.bak.20260905-190020/extensions/todo/state/i18n-bridge.ts +64 -0
  467. package/agent.bak.20260905-190020/extensions/todo/state/invariants.ts +20 -0
  468. package/agent.bak.20260905-190020/extensions/todo/state/replay.ts +38 -0
  469. package/agent.bak.20260905-190020/extensions/todo/state/selectors.ts +107 -0
  470. package/agent.bak.20260905-190020/extensions/todo/state/state-reducer.ts +326 -0
  471. package/agent.bak.20260905-190020/extensions/todo/state/state.ts +18 -0
  472. package/agent.bak.20260905-190020/extensions/todo/state/store.ts +82 -0
  473. package/agent.bak.20260905-190020/extensions/todo/state/task-graph.ts +57 -0
  474. package/agent.bak.20260905-190020/extensions/todo/todo-overlay.ts +204 -0
  475. package/agent.bak.20260905-190020/extensions/todo/todo.ts +155 -0
  476. package/agent.bak.20260905-190020/extensions/todo/tool/response-envelope.ts +109 -0
  477. package/agent.bak.20260905-190020/extensions/todo/tool/types.ts +206 -0
  478. package/agent.bak.20260905-190020/extensions/todo/view/format.ts +177 -0
  479. package/agent.bak.20260905-190020/extensions/todo/widget-order.ts +121 -0
  480. package/agent.bak.20260905-190020/extensions/trim-context/README.md +54 -0
  481. package/agent.bak.20260905-190020/extensions/trim-context/index.ts +487 -0
  482. package/agent.bak.20260905-190020/extensions/trim-context/install.ps1 +23 -0
  483. package/agent.bak.20260905-190020/extensions/trim-context/install.sh +21 -0
  484. package/agent.bak.20260905-190020/keybindings.json +7 -0
  485. package/bin/kiln.js +588 -358
  486. package/package.json +27 -21
  487. package/agent/install.ps1 +0 -527
  488. package/agent/install.sh +0 -511
  489. /package/{agent/extensions/status line → agent.bak.20260905-190020/extensions/ask-user}/install.ps1 +0 -0
  490. /package/{agent/extensions/status line → agent.bak.20260905-190020/extensions/ask-user}/install.sh +0 -0
  491. /package/{agent/extensions/status line → agent.bak.20260905-190020/extensions/statusline}/index.ts +0 -0
@@ -1,443 +1,443 @@
1
- import * as NodeServices from "@effect/platform-node/NodeServices";
2
- import { assert, it } from "@effect/vitest";
3
- import { homedir } from "node:os";
4
- import { dirname, join } from "node:path";
5
- import { Effect, FileSystem } from "effect";
6
- import { HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
7
- import {
8
- buildFdArgs,
9
- buildRgArgs,
10
- FD_DEFAULT_LIMIT,
11
- normalizeSearchPath,
12
- } from "./src/args.ts";
13
- import {
14
- FD_INTEL_DARWIN_VERSION,
15
- InstallError,
16
- readBoundedResponse,
17
- releaseAsset,
18
- resolveBinary,
19
- TOOL_SPECS,
20
- UnsupportedPlatformError,
21
- type BinaryEnv,
22
- type ReleaseAsset,
23
- type ResolvedBinary,
24
- } from "./src/binaries.ts";
25
- import { formatCapturedOutput, formatOutput } from "./src/output.ts";
26
- import { executeSearchProcess } from "./src/process.ts";
27
- import { installNotifications, makeBinaryInitializers } from "./index.ts";
28
-
29
- // --- argument construction -------------------------------------------------
30
-
31
- it("fd args: defaults list everything with the default limit", () => {
32
- assert.deepEqual(buildFdArgs({}), [
33
- "--color=never",
34
- "--max-results",
35
- String(FD_DEFAULT_LIMIT),
36
- "--",
37
- "",
38
- ]);
39
- });
40
-
41
- it("fd args: all options are translated and pattern stays behind --", () => {
42
- const args = buildFdArgs({
43
- pattern: "-rf",
44
- path: "@src",
45
- type: "file",
46
- extension: ".ts",
47
- glob: true,
48
- hidden: true,
49
- max_depth: 3,
50
- limit: 50,
51
- });
52
- assert.deepEqual(args, [
53
- "--color=never",
54
- "--hidden",
55
- "--glob",
56
- "--type",
57
- "f",
58
- "--extension",
59
- "ts",
60
- "--max-depth",
61
- "3",
62
- "--max-results",
63
- "50",
64
- "--",
65
- "-rf",
66
- "src",
67
- ]);
68
- });
69
-
70
- it("fd args: out-of-range values are clamped", () => {
71
- const args = buildFdArgs({ max_depth: 500, limit: 1_000_000 });
72
- assert.deepEqual(args, [
73
- "--color=never",
74
- "--max-depth",
75
- "64",
76
- "--max-results",
77
- "10000",
78
- "--",
79
- "",
80
- ]);
81
- });
82
-
83
- it("rg args: defaults use smart-case and safe separators", () => {
84
- assert.deepEqual(buildRgArgs({ pattern: "--help" }), [
85
- "--line-number",
86
- "--color=never",
87
- "--no-heading",
88
- "--with-filename",
89
- "--smart-case",
90
- "--max-count",
91
- "100",
92
- "--",
93
- "--help",
94
- ]);
95
- });
96
-
97
- it("rg args: all options are translated", () => {
98
- const args = buildRgArgs({
99
- pattern: "TODO",
100
- path: "@lib",
101
- glob: "*.ts",
102
- file_type: "ts",
103
- case_sensitive: true,
104
- fixed_strings: true,
105
- hidden: true,
106
- context: 2,
107
- limit: 10,
108
- });
109
- assert.deepEqual(args, [
110
- "--line-number",
111
- "--color=never",
112
- "--no-heading",
113
- "--with-filename",
114
- "--case-sensitive",
115
- "--fixed-strings",
116
- "--hidden",
117
- "--context",
118
- "2",
119
- "--glob",
120
- "*.ts",
121
- "--type",
122
- "ts",
123
- "--max-count",
124
- "10",
125
- "--",
126
- "TODO",
127
- "lib",
128
- ]);
129
- });
130
-
131
- it("rg args: case_sensitive false forces ignore-case", () => {
132
- const args = buildRgArgs({ pattern: "x", case_sensitive: false });
133
- assert.isTrue(args.includes("--ignore-case"));
134
- assert.isFalse(args.includes("--smart-case"));
135
- });
136
-
137
- it("path normalization strips leading @ and expands ~", () => {
138
- assert.equal(normalizeSearchPath("@src/lib"), "src/lib");
139
- assert.equal(normalizeSearchPath("~"), homedir());
140
- assert.equal(normalizeSearchPath("~/projects"), join(homedir(), "projects"));
141
- assert.equal(normalizeSearchPath(" plain "), "plain");
142
- });
143
-
144
- // --- binary resolution -----------------------------------------------------
145
-
146
- function makeEnv(options: {
147
- available?: string[];
148
- installShouldFail?: boolean;
149
- }): BinaryEnv & { installs: ReleaseAsset[]; probes: string[] } {
150
- const installs: ReleaseAsset[] = [];
151
- const probes: string[] = [];
152
- const installed = new Set<string>();
153
- return {
154
- installs,
155
- probes,
156
- probe: (command) =>
157
- Effect.sync(() => {
158
- probes.push(command);
159
- return (
160
- (options.available ?? []).includes(command) || installed.has(command)
161
- );
162
- }),
163
- install: (asset, destination) => {
164
- if (options.installShouldFail) {
165
- return Effect.fail(new InstallError({ message: "network down" }));
166
- }
167
- return Effect.sync(() => {
168
- installs.push(asset);
169
- installed.add(destination);
170
- });
171
- },
172
- };
173
- }
174
-
175
- const darwinArm = { os: "darwin", arch: "arm64" } as const;
176
-
177
- it.effect("binary resolution: system fd wins and nothing is installed", () =>
178
- Effect.gen(function* () {
179
- const env = makeEnv({ available: ["fd"] });
180
- const resolved = yield* resolveBinary(
181
- TOOL_SPECS.fd,
182
- "/repo/bin",
183
- darwinArm,
184
- env,
185
- );
186
-
187
- assert.deepEqual(resolved, {
188
- tool: "fd",
189
- command: "fd",
190
- source: "system",
191
- });
192
- assert.equal(env.installs.length, 0);
193
- }),
194
- );
195
-
196
- it.effect("binary resolution: fdfind is accepted as a system fd", () =>
197
- Effect.gen(function* () {
198
- const env = makeEnv({ available: ["fdfind"] });
199
- const resolved = yield* resolveBinary(
200
- TOOL_SPECS.fd,
201
- "/repo/bin",
202
- darwinArm,
203
- env,
204
- );
205
-
206
- assert.deepEqual(resolved, {
207
- tool: "fd",
208
- command: "fdfind",
209
- source: "system",
210
- });
211
- assert.equal(env.installs.length, 0);
212
- }),
213
- );
214
-
215
- it.effect("binary resolution: existing bin fallback is used silently", () =>
216
- Effect.gen(function* () {
217
- const env = makeEnv({ available: ["/repo/bin/rg"] });
218
- const resolved = yield* resolveBinary(
219
- TOOL_SPECS.rg,
220
- "/repo/bin",
221
- darwinArm,
222
- env,
223
- );
224
-
225
- assert.deepEqual(resolved, {
226
- tool: "rg",
227
- command: "/repo/bin/rg",
228
- source: "bundled",
229
- });
230
- assert.equal(env.installs.length, 0);
231
- }),
232
- );
233
-
234
- it.effect(
235
- "binary resolution: missing everywhere triggers exactly one install",
236
- () =>
237
- Effect.gen(function* () {
238
- const env = makeEnv({ available: [] });
239
- const resolved = yield* resolveBinary(
240
- TOOL_SPECS.rg,
241
- "/repo/bin",
242
- darwinArm,
243
- env,
244
- );
245
-
246
- assert.equal(resolved.source, "installed");
247
- assert.equal(resolved.command, "/repo/bin/rg");
248
- assert.equal(env.installs.length, 1);
249
- assert.match(
250
- env.installs[0].url,
251
- /^https:\/\/github\.com\/BurntSushi\/ripgrep\//,
252
- );
253
- }),
254
- );
255
-
256
- it.effect("binary resolution: install failure surfaces a typed error", () =>
257
- Effect.gen(function* () {
258
- const env = makeEnv({ available: [], installShouldFail: true });
259
- const error = yield* Effect.flip(
260
- resolveBinary(TOOL_SPECS.fd, "/repo/bin", darwinArm, env),
261
- );
262
-
263
- assert.instanceOf(error, InstallError);
264
- assert.equal(error.message, "network down");
265
- }),
266
- );
267
-
268
- it.effect(
269
- "binary resolution: unsupported platform fails without installing",
270
- () =>
271
- Effect.gen(function* () {
272
- const env = makeEnv({ available: [] });
273
- const error = yield* Effect.flip(
274
- resolveBinary(
275
- TOOL_SPECS.fd,
276
- "/repo/bin",
277
- { os: "linux", arch: "s390x" },
278
- env,
279
- ),
280
- );
281
-
282
- assert.instanceOf(error, UnsupportedPlatformError);
283
- assert.equal(env.installs.length, 0);
284
- }),
285
- );
286
-
287
- it.effect("binary resolution: one failed tool does not disable the other", () =>
288
- Effect.gen(function* () {
289
- const env = makeEnv({
290
- available: ["rg"],
291
- installShouldFail: true,
292
- });
293
- const initializers = makeBinaryInitializers("/repo/bin", darwinArm, env);
294
-
295
- const fdError = yield* Effect.flip(initializers.fd);
296
- const rg = yield* initializers.rg;
297
-
298
- assert.instanceOf(fdError, InstallError);
299
- assert.deepEqual(rg, { tool: "rg", command: "rg", source: "system" });
300
- }),
301
- );
302
-
303
- it("release assets cover macOS and Linux on arm64 and x64 over HTTPS", () => {
304
- for (const os of ["darwin", "linux"] as const) {
305
- for (const arch of ["arm64", "x64"] as const) {
306
- for (const tool of ["fd", "rg"] as const) {
307
- const asset = releaseAsset(tool, { os, arch });
308
- assert.isDefined(asset, `${tool} ${os}/${arch}`);
309
- assert.match(asset.url, /^https:\/\//);
310
- assert.isTrue(asset.url.endsWith(asset.fileName));
311
- assert.match(asset.sha256, /^[a-f0-9]{64}$/);
312
- }
313
- }
314
- }
315
- });
316
-
317
- it("linux assets use statically linked musl builds", () => {
318
- const asset = releaseAsset("fd", { os: "linux", arch: "x64" });
319
- assert.isTrue(asset?.url.includes("unknown-linux-musl"));
320
- });
321
-
322
- it("Intel macOS uses the latest fd release that publishes that target", () => {
323
- const asset = releaseAsset("fd", { os: "darwin", arch: "x64" });
324
- assert.equal(asset?.version, FD_INTEL_DARWIN_VERSION);
325
- });
326
-
327
- it.effect(
328
- "bounded downloads reject oversized declared and streamed bodies",
329
- () =>
330
- Effect.gen(function* () {
331
- const request = HttpClientRequest.get(
332
- "https://example.com/archive.tar.gz",
333
- );
334
- const declared = HttpClientResponse.fromWeb(
335
- request,
336
- new Response("small", {
337
- headers: { "content-length": "100" },
338
- }),
339
- );
340
- const declaredError = yield* Effect.flip(
341
- readBoundedResponse(declared, 10),
342
- );
343
- assert.match(declaredError.message, /size limit/);
344
-
345
- const streamed = HttpClientResponse.fromWeb(
346
- request,
347
- new Response("this body is too large"),
348
- );
349
- const streamedError = yield* Effect.flip(
350
- readBoundedResponse(streamed, 5),
351
- );
352
- assert.match(streamedError.message, /size limit/);
353
- }),
354
- );
355
-
356
- // --- notification policy ----------------------------------------------------
357
-
358
- it("notifications: only fresh installs notify", () => {
359
- const system: ResolvedBinary = {
360
- tool: "fd",
361
- command: "fd",
362
- source: "system",
363
- };
364
- const bundled: ResolvedBinary = {
365
- tool: "rg",
366
- command: "/repo/bin/rg",
367
- source: "bundled",
368
- };
369
- const installed: ResolvedBinary = {
370
- tool: "rg",
371
- command: "/repo/bin/rg",
372
- source: "installed",
373
- version: "15.2.0",
374
- };
375
-
376
- assert.deepEqual(installNotifications([system, bundled]), []);
377
- const messages = installNotifications([system, installed]);
378
- assert.equal(messages.length, 1);
379
- assert.match(messages[0], /downloaded rg 15\.2\.0/);
380
- });
381
-
382
- // --- output truncation -------------------------------------------------------
383
-
384
- it.effect("process output is streamed to a complete spill file", () =>
385
- Effect.gen(function* () {
386
- const result = yield* executeSearchProcess({
387
- command: process.execPath,
388
- args: ["-e", 'process.stdout.write("line\\n".repeat(3000))'],
389
- cwd: process.cwd(),
390
- tempPrefix: "pi-search-test-",
391
- });
392
- const formatted = formatCapturedOutput(result.output);
393
-
394
- assert.equal(result.code, 0);
395
- assert.isTrue(formatted.truncated);
396
- assert.equal(formatted.lineCount, 3000);
397
- assert.match(formatted.text, /2000 of 3000 lines/);
398
- assert.isDefined(formatted.fullOutputPath);
399
-
400
- const fs = yield* FileSystem.FileSystem;
401
- const fullOutput = yield* fs.readFileString(formatted.fullOutputPath);
402
- assert.equal(fullOutput, "line\n".repeat(3000));
403
- yield* fs.remove(dirname(formatted.fullOutputPath), {
404
- recursive: true,
405
- force: true,
406
- });
407
- }).pipe(Effect.provide(NodeServices.layer)),
408
- );
409
-
410
- it("output: small results pass through untouched", async () => {
411
- const formatted = await formatOutput("a.ts\nb.ts\n", {
412
- tempPrefix: "pi-fd-",
413
- persistFullOutput: () => Promise.reject(new Error("should not persist")),
414
- });
415
- assert.equal(formatted.text, "a.ts\nb.ts");
416
- assert.equal(formatted.lineCount, 2);
417
- assert.isFalse(formatted.truncated);
418
- assert.isUndefined(formatted.fullOutputPath);
419
- });
420
-
421
- it("output: oversized results are truncated and persisted", async () => {
422
- const bigOutput = Array.from({ length: 3000 }, (_, i) => `file-${i}.ts`).join(
423
- "\n",
424
- );
425
- let persisted: string | undefined;
426
- const formatted = await formatOutput(bigOutput, {
427
- tempPrefix: "pi-fd-",
428
- persistFullOutput: async (full) => {
429
- persisted = full;
430
- return "/tmp/fake/output.txt";
431
- },
432
- });
433
- assert.isTrue(formatted.truncated);
434
- assert.equal(formatted.fullOutputPath, "/tmp/fake/output.txt");
435
- assert.equal(persisted, bigOutput);
436
- assert.match(formatted.text, /\[Output truncated: 2000 of 3000 lines/);
437
- assert.match(
438
- formatted.text,
439
- /Full output saved to: \/tmp\/fake\/output\.txt\]/,
440
- );
441
- const shownLines = formatted.text.split("\n");
442
- assert.equal(shownLines[0], "file-0.ts");
443
- });
1
+ import * as NodeServices from "@effect/platform-node/NodeServices";
2
+ import { assert, it } from "@effect/vitest";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
5
+ import { Effect, FileSystem } from "effect";
6
+ import { HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
7
+ import {
8
+ buildFdArgs,
9
+ buildRgArgs,
10
+ FD_DEFAULT_LIMIT,
11
+ normalizeSearchPath,
12
+ } from "./src/args.ts";
13
+ import {
14
+ FD_INTEL_DARWIN_VERSION,
15
+ InstallError,
16
+ readBoundedResponse,
17
+ releaseAsset,
18
+ resolveBinary,
19
+ TOOL_SPECS,
20
+ UnsupportedPlatformError,
21
+ type BinaryEnv,
22
+ type ReleaseAsset,
23
+ type ResolvedBinary,
24
+ } from "./src/binaries.ts";
25
+ import { formatCapturedOutput, formatOutput } from "./src/output.ts";
26
+ import { executeSearchProcess } from "./src/process.ts";
27
+ import { installNotifications, makeBinaryInitializers } from "./index.ts";
28
+
29
+ // --- argument construction -------------------------------------------------
30
+
31
+ it("fd args: defaults list everything with the default limit", () => {
32
+ assert.deepEqual(buildFdArgs({}), [
33
+ "--color=never",
34
+ "--max-results",
35
+ String(FD_DEFAULT_LIMIT),
36
+ "--",
37
+ "",
38
+ ]);
39
+ });
40
+
41
+ it("fd args: all options are translated and pattern stays behind --", () => {
42
+ const args = buildFdArgs({
43
+ pattern: "-rf",
44
+ path: "@src",
45
+ type: "file",
46
+ extension: ".ts",
47
+ glob: true,
48
+ hidden: true,
49
+ max_depth: 3,
50
+ limit: 50,
51
+ });
52
+ assert.deepEqual(args, [
53
+ "--color=never",
54
+ "--hidden",
55
+ "--glob",
56
+ "--type",
57
+ "f",
58
+ "--extension",
59
+ "ts",
60
+ "--max-depth",
61
+ "3",
62
+ "--max-results",
63
+ "50",
64
+ "--",
65
+ "-rf",
66
+ "src",
67
+ ]);
68
+ });
69
+
70
+ it("fd args: out-of-range values are clamped", () => {
71
+ const args = buildFdArgs({ max_depth: 500, limit: 1_000_000 });
72
+ assert.deepEqual(args, [
73
+ "--color=never",
74
+ "--max-depth",
75
+ "64",
76
+ "--max-results",
77
+ "10000",
78
+ "--",
79
+ "",
80
+ ]);
81
+ });
82
+
83
+ it("rg args: defaults use smart-case and safe separators", () => {
84
+ assert.deepEqual(buildRgArgs({ pattern: "--help" }), [
85
+ "--line-number",
86
+ "--color=never",
87
+ "--no-heading",
88
+ "--with-filename",
89
+ "--smart-case",
90
+ "--max-count",
91
+ "100",
92
+ "--",
93
+ "--help",
94
+ ]);
95
+ });
96
+
97
+ it("rg args: all options are translated", () => {
98
+ const args = buildRgArgs({
99
+ pattern: "TODO",
100
+ path: "@lib",
101
+ glob: "*.ts",
102
+ file_type: "ts",
103
+ case_sensitive: true,
104
+ fixed_strings: true,
105
+ hidden: true,
106
+ context: 2,
107
+ limit: 10,
108
+ });
109
+ assert.deepEqual(args, [
110
+ "--line-number",
111
+ "--color=never",
112
+ "--no-heading",
113
+ "--with-filename",
114
+ "--case-sensitive",
115
+ "--fixed-strings",
116
+ "--hidden",
117
+ "--context",
118
+ "2",
119
+ "--glob",
120
+ "*.ts",
121
+ "--type",
122
+ "ts",
123
+ "--max-count",
124
+ "10",
125
+ "--",
126
+ "TODO",
127
+ "lib",
128
+ ]);
129
+ });
130
+
131
+ it("rg args: case_sensitive false forces ignore-case", () => {
132
+ const args = buildRgArgs({ pattern: "x", case_sensitive: false });
133
+ assert.isTrue(args.includes("--ignore-case"));
134
+ assert.isFalse(args.includes("--smart-case"));
135
+ });
136
+
137
+ it("path normalization strips leading @ and expands ~", () => {
138
+ assert.equal(normalizeSearchPath("@src/lib"), "src/lib");
139
+ assert.equal(normalizeSearchPath("~"), homedir());
140
+ assert.equal(normalizeSearchPath("~/projects"), join(homedir(), "projects"));
141
+ assert.equal(normalizeSearchPath(" plain "), "plain");
142
+ });
143
+
144
+ // --- binary resolution -----------------------------------------------------
145
+
146
+ function makeEnv(options: {
147
+ available?: string[];
148
+ installShouldFail?: boolean;
149
+ }): BinaryEnv & { installs: ReleaseAsset[]; probes: string[] } {
150
+ const installs: ReleaseAsset[] = [];
151
+ const probes: string[] = [];
152
+ const installed = new Set<string>();
153
+ return {
154
+ installs,
155
+ probes,
156
+ probe: (command) =>
157
+ Effect.sync(() => {
158
+ probes.push(command);
159
+ return (
160
+ (options.available ?? []).includes(command) || installed.has(command)
161
+ );
162
+ }),
163
+ install: (asset, destination) => {
164
+ if (options.installShouldFail) {
165
+ return Effect.fail(new InstallError({ message: "network down" }));
166
+ }
167
+ return Effect.sync(() => {
168
+ installs.push(asset);
169
+ installed.add(destination);
170
+ });
171
+ },
172
+ };
173
+ }
174
+
175
+ const darwinArm = { os: "darwin", arch: "arm64" } as const;
176
+
177
+ it.effect("binary resolution: system fd wins and nothing is installed", () =>
178
+ Effect.gen(function* () {
179
+ const env = makeEnv({ available: ["fd"] });
180
+ const resolved = yield* resolveBinary(
181
+ TOOL_SPECS.fd,
182
+ "/repo/bin",
183
+ darwinArm,
184
+ env,
185
+ );
186
+
187
+ assert.deepEqual(resolved, {
188
+ tool: "fd",
189
+ command: "fd",
190
+ source: "system",
191
+ });
192
+ assert.equal(env.installs.length, 0);
193
+ }),
194
+ );
195
+
196
+ it.effect("binary resolution: fdfind is accepted as a system fd", () =>
197
+ Effect.gen(function* () {
198
+ const env = makeEnv({ available: ["fdfind"] });
199
+ const resolved = yield* resolveBinary(
200
+ TOOL_SPECS.fd,
201
+ "/repo/bin",
202
+ darwinArm,
203
+ env,
204
+ );
205
+
206
+ assert.deepEqual(resolved, {
207
+ tool: "fd",
208
+ command: "fdfind",
209
+ source: "system",
210
+ });
211
+ assert.equal(env.installs.length, 0);
212
+ }),
213
+ );
214
+
215
+ it.effect("binary resolution: existing bin fallback is used silently", () =>
216
+ Effect.gen(function* () {
217
+ const env = makeEnv({ available: ["/repo/bin/rg"] });
218
+ const resolved = yield* resolveBinary(
219
+ TOOL_SPECS.rg,
220
+ "/repo/bin",
221
+ darwinArm,
222
+ env,
223
+ );
224
+
225
+ assert.deepEqual(resolved, {
226
+ tool: "rg",
227
+ command: "/repo/bin/rg",
228
+ source: "bundled",
229
+ });
230
+ assert.equal(env.installs.length, 0);
231
+ }),
232
+ );
233
+
234
+ it.effect(
235
+ "binary resolution: missing everywhere triggers exactly one install",
236
+ () =>
237
+ Effect.gen(function* () {
238
+ const env = makeEnv({ available: [] });
239
+ const resolved = yield* resolveBinary(
240
+ TOOL_SPECS.rg,
241
+ "/repo/bin",
242
+ darwinArm,
243
+ env,
244
+ );
245
+
246
+ assert.equal(resolved.source, "installed");
247
+ assert.equal(resolved.command, "/repo/bin/rg");
248
+ assert.equal(env.installs.length, 1);
249
+ assert.match(
250
+ env.installs[0].url,
251
+ /^https:\/\/github\.com\/BurntSushi\/ripgrep\//,
252
+ );
253
+ }),
254
+ );
255
+
256
+ it.effect("binary resolution: install failure surfaces a typed error", () =>
257
+ Effect.gen(function* () {
258
+ const env = makeEnv({ available: [], installShouldFail: true });
259
+ const error = yield* Effect.flip(
260
+ resolveBinary(TOOL_SPECS.fd, "/repo/bin", darwinArm, env),
261
+ );
262
+
263
+ assert.instanceOf(error, InstallError);
264
+ assert.equal(error.message, "network down");
265
+ }),
266
+ );
267
+
268
+ it.effect(
269
+ "binary resolution: unsupported platform fails without installing",
270
+ () =>
271
+ Effect.gen(function* () {
272
+ const env = makeEnv({ available: [] });
273
+ const error = yield* Effect.flip(
274
+ resolveBinary(
275
+ TOOL_SPECS.fd,
276
+ "/repo/bin",
277
+ { os: "linux", arch: "s390x" },
278
+ env,
279
+ ),
280
+ );
281
+
282
+ assert.instanceOf(error, UnsupportedPlatformError);
283
+ assert.equal(env.installs.length, 0);
284
+ }),
285
+ );
286
+
287
+ it.effect("binary resolution: one failed tool does not disable the other", () =>
288
+ Effect.gen(function* () {
289
+ const env = makeEnv({
290
+ available: ["rg"],
291
+ installShouldFail: true,
292
+ });
293
+ const initializers = makeBinaryInitializers("/repo/bin", darwinArm, env);
294
+
295
+ const fdError = yield* Effect.flip(initializers.fd);
296
+ const rg = yield* initializers.rg;
297
+
298
+ assert.instanceOf(fdError, InstallError);
299
+ assert.deepEqual(rg, { tool: "rg", command: "rg", source: "system" });
300
+ }),
301
+ );
302
+
303
+ it("release assets cover macOS and Linux on arm64 and x64 over HTTPS", () => {
304
+ for (const os of ["darwin", "linux"] as const) {
305
+ for (const arch of ["arm64", "x64"] as const) {
306
+ for (const tool of ["fd", "rg"] as const) {
307
+ const asset = releaseAsset(tool, { os, arch });
308
+ assert.isDefined(asset, `${tool} ${os}/${arch}`);
309
+ assert.match(asset.url, /^https:\/\//);
310
+ assert.isTrue(asset.url.endsWith(asset.fileName));
311
+ assert.match(asset.sha256, /^[a-f0-9]{64}$/);
312
+ }
313
+ }
314
+ }
315
+ });
316
+
317
+ it("linux assets use statically linked musl builds", () => {
318
+ const asset = releaseAsset("fd", { os: "linux", arch: "x64" });
319
+ assert.isTrue(asset?.url.includes("unknown-linux-musl"));
320
+ });
321
+
322
+ it("Intel macOS uses the latest fd release that publishes that target", () => {
323
+ const asset = releaseAsset("fd", { os: "darwin", arch: "x64" });
324
+ assert.equal(asset?.version, FD_INTEL_DARWIN_VERSION);
325
+ });
326
+
327
+ it.effect(
328
+ "bounded downloads reject oversized declared and streamed bodies",
329
+ () =>
330
+ Effect.gen(function* () {
331
+ const request = HttpClientRequest.get(
332
+ "https://example.com/archive.tar.gz",
333
+ );
334
+ const declared = HttpClientResponse.fromWeb(
335
+ request,
336
+ new Response("small", {
337
+ headers: { "content-length": "100" },
338
+ }),
339
+ );
340
+ const declaredError = yield* Effect.flip(
341
+ readBoundedResponse(declared, 10),
342
+ );
343
+ assert.match(declaredError.message, /size limit/);
344
+
345
+ const streamed = HttpClientResponse.fromWeb(
346
+ request,
347
+ new Response("this body is too large"),
348
+ );
349
+ const streamedError = yield* Effect.flip(
350
+ readBoundedResponse(streamed, 5),
351
+ );
352
+ assert.match(streamedError.message, /size limit/);
353
+ }),
354
+ );
355
+
356
+ // --- notification policy ----------------------------------------------------
357
+
358
+ it("notifications: only fresh installs notify", () => {
359
+ const system: ResolvedBinary = {
360
+ tool: "fd",
361
+ command: "fd",
362
+ source: "system",
363
+ };
364
+ const bundled: ResolvedBinary = {
365
+ tool: "rg",
366
+ command: "/repo/bin/rg",
367
+ source: "bundled",
368
+ };
369
+ const installed: ResolvedBinary = {
370
+ tool: "rg",
371
+ command: "/repo/bin/rg",
372
+ source: "installed",
373
+ version: "15.2.0",
374
+ };
375
+
376
+ assert.deepEqual(installNotifications([system, bundled]), []);
377
+ const messages = installNotifications([system, installed]);
378
+ assert.equal(messages.length, 1);
379
+ assert.match(messages[0], /downloaded rg 15\.2\.0/);
380
+ });
381
+
382
+ // --- output truncation -------------------------------------------------------
383
+
384
+ it.effect("process output is streamed to a complete spill file", () =>
385
+ Effect.gen(function* () {
386
+ const result = yield* executeSearchProcess({
387
+ command: process.execPath,
388
+ args: ["-e", 'process.stdout.write("line\\n".repeat(3000))'],
389
+ cwd: process.cwd(),
390
+ tempPrefix: "pi-search-test-",
391
+ });
392
+ const formatted = formatCapturedOutput(result.output);
393
+
394
+ assert.equal(result.code, 0);
395
+ assert.isTrue(formatted.truncated);
396
+ assert.equal(formatted.lineCount, 3000);
397
+ assert.match(formatted.text, /2000 of 3000 lines/);
398
+ assert.isDefined(formatted.fullOutputPath);
399
+
400
+ const fs = yield* FileSystem.FileSystem;
401
+ const fullOutput = yield* fs.readFileString(formatted.fullOutputPath);
402
+ assert.equal(fullOutput, "line\n".repeat(3000));
403
+ yield* fs.remove(dirname(formatted.fullOutputPath), {
404
+ recursive: true,
405
+ force: true,
406
+ });
407
+ }).pipe(Effect.provide(NodeServices.layer)),
408
+ );
409
+
410
+ it("output: small results pass through untouched", async () => {
411
+ const formatted = await formatOutput("a.ts\nb.ts\n", {
412
+ tempPrefix: "pi-fd-",
413
+ persistFullOutput: () => Promise.reject(new Error("should not persist")),
414
+ });
415
+ assert.equal(formatted.text, "a.ts\nb.ts");
416
+ assert.equal(formatted.lineCount, 2);
417
+ assert.isFalse(formatted.truncated);
418
+ assert.isUndefined(formatted.fullOutputPath);
419
+ });
420
+
421
+ it("output: oversized results are truncated and persisted", async () => {
422
+ const bigOutput = Array.from({ length: 3000 }, (_, i) => `file-${i}.ts`).join(
423
+ "\n",
424
+ );
425
+ let persisted: string | undefined;
426
+ const formatted = await formatOutput(bigOutput, {
427
+ tempPrefix: "pi-fd-",
428
+ persistFullOutput: async (full) => {
429
+ persisted = full;
430
+ return "/tmp/fake/output.txt";
431
+ },
432
+ });
433
+ assert.isTrue(formatted.truncated);
434
+ assert.equal(formatted.fullOutputPath, "/tmp/fake/output.txt");
435
+ assert.equal(persisted, bigOutput);
436
+ assert.match(formatted.text, /\[Output truncated: 2000 of 3000 lines/);
437
+ assert.match(
438
+ formatted.text,
439
+ /Full output saved to: \/tmp\/fake\/output\.txt\]/,
440
+ );
441
+ const shownLines = formatted.text.split("\n");
442
+ assert.equal(shownLines[0], "file-0.ts");
443
+ });