pim-agent 0.13.0 → 0.14.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 (253) hide show
  1. package/package.json +3 -3
  2. package/packages/core/src/attachments/AttachmentStore.ts +8 -13
  3. package/packages/core/src/attachments/Attachments.ts +2 -4
  4. package/packages/core/src/extensions/CoreExtensions.ts +1 -1
  5. package/packages/core/src/extensions/apply-patch/coordinator.ts +1 -1
  6. package/packages/core/src/extensions/apply-patch/executor.ts +21 -25
  7. package/packages/core/src/extensions/apply-patch/matcher.ts +1 -1
  8. package/packages/core/src/extensions/apply-patch/model.ts +2 -6
  9. package/packages/core/src/extensions/apply-patch/parser.ts +60 -162
  10. package/packages/core/src/extensions/apply-patch/schema.ts +0 -1
  11. package/packages/core/src/extensions/bash/MemoryCap.ts +5 -4
  12. package/packages/core/src/extensions/bash/capture.ts +16 -23
  13. package/packages/core/src/extensions/bash/format.ts +2 -2
  14. package/packages/core/src/extensions/bash/image.ts +4 -8
  15. package/packages/core/src/extensions/bash/index.ts +1 -1
  16. package/packages/core/src/extensions/bash/render.ts +1 -1
  17. package/packages/core/src/extensions/bash/run.ts +9 -15
  18. package/packages/core/src/extensions/bash/schema.ts +4 -4
  19. package/packages/core/src/extensions/edit/edit.ts +14 -33
  20. package/packages/core/src/extensions/glob/glob.ts +1 -3
  21. package/packages/core/src/extensions/glob/index.ts +7 -9
  22. package/packages/core/src/extensions/glob/render.ts +2 -4
  23. package/packages/core/src/extensions/glob/schema.ts +1 -1
  24. package/packages/core/src/extensions/grep/grep.ts +7 -7
  25. package/packages/core/src/extensions/grep/render.ts +5 -6
  26. package/packages/core/src/extensions/grep/schema.ts +3 -7
  27. package/packages/core/src/extensions/read/ImageMemory.ts +2 -8
  28. package/packages/core/src/extensions/read/image.ts +3 -3
  29. package/packages/core/src/extensions/read/index.ts +2 -14
  30. package/packages/core/src/extensions/read/read.ts +5 -6
  31. package/packages/core/src/extensions/read/render.ts +1 -1
  32. package/packages/core/src/extensions/read/schema.ts +2 -2
  33. package/packages/core/src/extensions/subagent/render.ts +2 -2
  34. package/packages/core/src/extensions/subagent/subagent.ts +10 -21
  35. package/packages/core/src/extensions/system-prompt/index.ts +1 -2
  36. package/packages/core/src/extensions/system-prompt/prompt.ts +2 -4
  37. package/packages/core/src/extensions/todo/render.ts +1 -4
  38. package/packages/core/src/extensions/todo/todo.ts +16 -23
  39. package/packages/core/src/extensions/web-fetch/JinaReaderClient.ts +3 -11
  40. package/packages/core/src/extensions/web-fetch/WebViewFetchClient.ts +1 -3
  41. package/packages/core/src/extensions/web-fetch/fetch.ts +4 -12
  42. package/packages/core/src/extensions/web-fetch/image.ts +3 -4
  43. package/packages/core/src/extensions/web-fetch/index.ts +2 -13
  44. package/packages/core/src/extensions/web-fetch/render.ts +3 -4
  45. package/packages/core/src/extensions/web-fetch/schema.ts +3 -4
  46. package/packages/core/src/extensions/web-search/ExaMcpClient.ts +23 -31
  47. package/packages/core/src/extensions/web-search/SearchBreaker.ts +1 -1
  48. package/packages/core/src/extensions/web-search/SearchChain.ts +6 -5
  49. package/packages/core/src/extensions/web-search/providers/DuckDuckGoProvider.ts +2 -2
  50. package/packages/core/src/extensions/web-search/providers/FirecrawlProvider.ts +1 -2
  51. package/packages/core/src/extensions/web-search/providers/SearchProvider.ts +3 -3
  52. package/packages/core/src/extensions/write/write.ts +1 -1
  53. package/packages/core/src/picker/InProcessFilePickerSuggestionEngine.ts +1 -3
  54. package/packages/core/src/picker/PickerItem.ts +1 -1
  55. package/packages/core/src/picker/PickerService.ts +3 -7
  56. package/packages/core/src/picker/RemoteFilePickerSuggestionEngine.ts +1 -2
  57. package/packages/core/src/picker/catalog.ts +7 -15
  58. package/packages/core/src/picker/filePickerWorker.ts +1 -3
  59. package/packages/core/src/picker/ranker.ts +1 -1
  60. package/packages/core/src/picker/token.ts +3 -4
  61. package/packages/core/src/session/AgentRuntime.ts +5 -8
  62. package/packages/core/src/session/EventLog.ts +6 -12
  63. package/packages/core/src/session/ReadCursors.ts +3 -4
  64. package/packages/core/src/session/SearchIndex.ts +49 -86
  65. package/packages/core/src/session/SearchTokens.ts +4 -7
  66. package/packages/core/src/session/SessionCache.ts +8 -6
  67. package/packages/core/src/session/SessionDigest.ts +10 -19
  68. package/packages/core/src/session/SessionHost.ts +53 -83
  69. package/packages/core/src/session/SessionLease.ts +12 -15
  70. package/packages/core/src/session/SessionMeta.ts +16 -32
  71. package/packages/core/src/session/SessionName.ts +3 -7
  72. package/packages/core/src/session/SessionRegistry.ts +13 -29
  73. package/packages/core/src/session/SessionUi.ts +12 -16
  74. package/packages/core/src/session/WriteMark.ts +7 -16
  75. package/packages/core/src/shared/Cli.ts +1 -1
  76. package/packages/core/src/shared/DaemonUnit.ts +1 -2
  77. package/packages/core/src/shared/DiffLines.ts +16 -34
  78. package/packages/core/src/shared/DiffRenderer.ts +8 -27
  79. package/packages/core/src/shared/Directories.ts +4 -4
  80. package/packages/core/src/shared/EditMatcher.ts +18 -50
  81. package/packages/core/src/shared/ExtensionToggles.ts +3 -6
  82. package/packages/core/src/shared/FileEnumerator.ts +73 -57
  83. package/packages/core/src/shared/FileScanner.ts +5 -13
  84. package/packages/core/src/shared/FileWatch.ts +13 -17
  85. package/packages/core/src/shared/Format.ts +2 -3
  86. package/packages/core/src/shared/FuzzyMatcher.ts +18 -19
  87. package/packages/core/src/shared/Git.ts +22 -47
  88. package/packages/core/src/shared/GitMonitor.ts +12 -23
  89. package/packages/core/src/shared/GlobExclusions.ts +0 -4
  90. package/packages/core/src/shared/Http.ts +1 -1
  91. package/packages/core/src/shared/ImageMime.ts +3 -5
  92. package/packages/core/src/shared/Images.ts +17 -27
  93. package/packages/core/src/shared/Languages.ts +2 -2
  94. package/packages/core/src/shared/Levenshtein.ts +1 -6
  95. package/packages/core/src/shared/Lines.ts +1 -1
  96. package/packages/core/src/shared/McpClient.ts +2 -2
  97. package/packages/core/src/shared/PatchSummary.ts +1 -1
  98. package/packages/core/src/shared/Paths.ts +4 -1
  99. package/packages/core/src/shared/PiExtensions.ts +5 -12
  100. package/packages/core/src/shared/PimSettings.ts +14 -15
  101. package/packages/core/src/shared/Proc.ts +2 -3
  102. package/packages/core/src/shared/RateLimiter.ts +1 -1
  103. package/packages/core/src/shared/Renderer.ts +1 -3
  104. package/packages/core/src/shared/RepoDiff.ts +24 -46
  105. package/packages/core/src/shared/SearchRender.ts +3 -4
  106. package/packages/core/src/shared/SpillCache.ts +2 -3
  107. package/packages/core/src/shared/SubagentLogs.ts +4 -6
  108. package/packages/core/src/shared/Supervisor.ts +19 -32
  109. package/packages/core/src/shared/Surface.ts +1 -1
  110. package/packages/core/src/shared/Sweeper.ts +1 -1
  111. package/packages/core/src/shared/Tools.ts +17 -30
  112. package/packages/core/src/shared/Updater.ts +15 -15
  113. package/packages/core/src/view/BodyRenderer.ts +1 -1
  114. package/packages/core/src/view/DiffBlocks.ts +0 -1
  115. package/packages/core/src/view/DiffExpand.ts +10 -25
  116. package/packages/core/src/view/DiffLayout.ts +2 -2
  117. package/packages/core/src/view/DiffPairs.ts +2 -2
  118. package/packages/core/src/view/MarkdownPainter.ts +2 -19
  119. package/packages/core/src/view/MovePath.ts +4 -17
  120. package/packages/core/src/view/Painting.ts +4 -4
  121. package/packages/core/src/view/ViewBlock.ts +11 -12
  122. package/packages/daemon/src/Daemon.ts +2 -7
  123. package/packages/daemon/src/DaemonInstall.ts +5 -12
  124. package/packages/daemon/src/Surfaces.ts +3 -12
  125. package/packages/daemon/src/TelegramSurface.ts +0 -1
  126. package/packages/daemon/src/index.ts +0 -1
  127. package/packages/protocol/src/Command.ts +33 -41
  128. package/packages/protocol/src/Diff.ts +0 -5
  129. package/packages/protocol/src/ImageRoute.ts +2 -5
  130. package/packages/protocol/src/ServerEvent.ts +68 -105
  131. package/packages/server/src/AttachmentEndpoint.ts +45 -19
  132. package/packages/server/src/ClientConnection.ts +11 -12
  133. package/packages/server/src/ImageEndpoint.ts +3 -4
  134. package/packages/server/src/ProbeClient.ts +26 -59
  135. package/packages/server/src/Reloader.ts +4 -7
  136. package/packages/server/src/SendFileTool.ts +1 -1
  137. package/packages/server/src/SessionCatalogue.ts +35 -47
  138. package/packages/server/src/SessionProjection.ts +7 -12
  139. package/packages/server/src/SessionStream.ts +33 -80
  140. package/packages/server/src/StaticClient.ts +7 -8
  141. package/packages/server/src/WebOptions.ts +2 -6
  142. package/packages/server/src/WsGateway.ts +35 -96
  143. package/packages/server/src/probe.ts +6 -18
  144. package/packages/telegram/src/Bot.ts +2 -2
  145. package/packages/telegram/src/Commands.ts +108 -65
  146. package/packages/telegram/src/Config.ts +1 -6
  147. package/packages/telegram/src/Markdown.ts +4 -13
  148. package/packages/telegram/src/Renderer.ts +1 -1
  149. package/packages/telegram/src/Session.ts +3 -10
  150. package/packages/telegram/src/TaskScheduler.ts +31 -10
  151. package/packages/telegram/src/TaskStore.ts +11 -1
  152. package/packages/telegram/src/TaskTool.ts +1 -1
  153. package/packages/telegram/src/UpdateConfirm.ts +2 -2
  154. package/packages/tui/src/extensions/_init/index.ts +2 -5
  155. package/packages/tui/src/extensions/file-picker/index.ts +2 -6
  156. package/packages/tui/src/extensions/footer/index.ts +0 -1
  157. package/packages/tui/src/extensions/footer/powerline.ts +16 -28
  158. package/packages/tui/src/extensions/pim/index.ts +1 -1
  159. package/packages/tui/src/extensions/session-lease/index.ts +5 -6
  160. package/packages/tui/src/extensions/working-indicator/index.ts +1 -2
  161. package/packages/tui/src/themes/themeCliArgs.ts +1 -1
  162. package/packages/web/dist/client/assets/{abnfDiagram-O67JEVCF-CZ7V84ot.js → abnfDiagram-O67JEVCF-WweOU5DK.js} +1 -1
  163. package/packages/web/dist/client/assets/{arc-DiHGkUvc.js → arc-O2PmZXWt.js} +1 -1
  164. package/packages/web/dist/client/assets/architecture-7GRP2DOG-COBxVilU.js +1 -0
  165. package/packages/web/dist/client/assets/{architectureDiagram-NJMV4G6O-XS5DhfJB.js → architectureDiagram-NJMV4G6O-DwYq1YaM.js} +1 -1
  166. package/packages/web/dist/client/assets/{blockDiagram-BEXU5L5S-BCsgLvy1.js → blockDiagram-BEXU5L5S-CVab041n.js} +1 -1
  167. package/packages/web/dist/client/assets/{c4Diagram-YGBWAQC7-Bj9LcWNm.js → c4Diagram-YGBWAQC7-BmotHez3.js} +1 -1
  168. package/packages/web/dist/client/assets/channel-BKV-IcTA.js +1 -0
  169. package/packages/web/dist/client/assets/{chunk-3FUC2YCW-BmDurFxp.js → chunk-3FUC2YCW-CWNS7-n4.js} +1 -1
  170. package/packages/web/dist/client/assets/{chunk-5DYCD2WN-DAjG-pqn.js → chunk-5DYCD2WN-DflvXohu.js} +1 -1
  171. package/packages/web/dist/client/assets/{chunk-742MDFTN-Bmxs5puY.js → chunk-742MDFTN-B_0t6_RE.js} +1 -1
  172. package/packages/web/dist/client/assets/{chunk-7INBJB4K-Di7kIxrQ.js → chunk-7INBJB4K-wKj0Q3Kv.js} +1 -1
  173. package/packages/web/dist/client/assets/{chunk-7M6MHVWA-CSc8sR0b.js → chunk-7M6MHVWA-BMvUghc8.js} +1 -1
  174. package/packages/web/dist/client/assets/{chunk-7PRAP22T-C8kd5QvY.js → chunk-7PRAP22T-BY41wkcT.js} +1 -1
  175. package/packages/web/dist/client/assets/{chunk-GTNCS2PH-DG2b2LYE.js → chunk-GTNCS2PH-PqY_YoS0.js} +1 -1
  176. package/packages/web/dist/client/assets/{chunk-GWA4HPMP-DdLaLQCu.js → chunk-GWA4HPMP-fozSU5ty.js} +1 -1
  177. package/packages/web/dist/client/assets/{chunk-MBY4JIJT-C1j0yQlk.js → chunk-MBY4JIJT-CrHrC3jw.js} +1 -1
  178. package/packages/web/dist/client/assets/{chunk-NETBCI7D-Bfq9H74p.js → chunk-NETBCI7D-DWdAxieG.js} +1 -1
  179. package/packages/web/dist/client/assets/{chunk-O7XYJQB3-ZHvBmBO-.js → chunk-O7XYJQB3-B6uOn9iS.js} +1 -1
  180. package/packages/web/dist/client/assets/{chunk-UA2S7LBM-ku1JeHSK.js → chunk-UA2S7LBM-BxYSHqyy.js} +1 -1
  181. package/packages/web/dist/client/assets/{chunk-WEXAMYUT-BP1iga_7.js → chunk-WEXAMYUT-CtwIaQDa.js} +1 -1
  182. package/packages/web/dist/client/assets/{chunk-XXDRQBXY-BBeccPcX.js → chunk-XXDRQBXY-fgBFe-PX.js} +1 -1
  183. package/packages/web/dist/client/assets/{chunk-Z7XXMR3K-SMHZugaR.js → chunk-Z7XXMR3K-CPonoV3p.js} +1 -1
  184. package/packages/web/dist/client/assets/{chunk-ZIGJFQKS-CFU_JLG4.js → chunk-ZIGJFQKS-Cdu87cTj.js} +1 -1
  185. package/packages/web/dist/client/assets/{classDiagram-v2-NBCMYWYE-CYviuQzJ.js → classDiagram-v2-NBCMYWYE-DSWsPaa7.js} +1 -1
  186. package/packages/web/dist/client/assets/{core-DyHsgs5k.js → core-CBoS7AST.js} +1 -1
  187. package/packages/web/dist/client/assets/{cose-bilkent-JH36ORCC-9v2ZkJzo.js → cose-bilkent-JH36ORCC-CTwlldtJ.js} +1 -1
  188. package/packages/web/dist/client/assets/{cynefin-OW5HDTMX-Bx5xRadi.js → cynefin-OW5HDTMX-CZQ4EPNJ.js} +1 -1
  189. package/packages/web/dist/client/assets/{cynefinDiagram-VND7K2PF-BRfGDKqa.js → cynefinDiagram-VND7K2PF-C2gp6H_Q.js} +1 -1
  190. package/packages/web/dist/client/assets/{dagre-6A5THRUB-C4l-2L2e.js → dagre-6A5THRUB-CDxTP47t.js} +1 -1
  191. package/packages/web/dist/client/assets/{diagram-22UHCM2B-d_hQ3kyi.js → diagram-22UHCM2B-BIohE1lI.js} +1 -1
  192. package/packages/web/dist/client/assets/{diagram-3UASUU5V-DrEeguPI.js → diagram-3UASUU5V-TwAUir-w.js} +1 -1
  193. package/packages/web/dist/client/assets/{diagram-ATOU4E4O-BmfQ22pD.js → diagram-ATOU4E4O-BM1JQrIu.js} +1 -1
  194. package/packages/web/dist/client/assets/{diagram-CDSNMT55-BjVWjuPF.js → diagram-CDSNMT55-BKIqhxSI.js} +1 -1
  195. package/packages/web/dist/client/assets/{diagram-MLGK6HIB-wDjk-O8i.js → diagram-MLGK6HIB-CVe3QDHr.js} +1 -1
  196. package/packages/web/dist/client/assets/{diagram-MPIPVDR6-DqXQFE1s.js → diagram-MPIPVDR6-Bj-MQIFI.js} +1 -1
  197. package/packages/web/dist/client/assets/{dist-BddGOpie.js → dist-DlZpcyc2.js} +1 -1
  198. package/packages/web/dist/client/assets/{ebnfDiagram-ZINNZB2B-UB8kOITM.js → ebnfDiagram-ZINNZB2B-C06mmvmz.js} +1 -1
  199. package/packages/web/dist/client/assets/{elk-276RUBZZ-D4miYQnD.js → elk-276RUBZZ-CizJSNEj.js} +1 -1
  200. package/packages/web/dist/client/assets/{erDiagram-OPXOYQCR--RXKv7KH.js → erDiagram-OPXOYQCR-M3FQkKI1.js} +1 -1
  201. package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-D_UXLpIu.js +1 -0
  202. package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-BT4eEEVm.js +1 -0
  203. package/packages/web/dist/client/assets/{ganttDiagram-FUAMR5RP-C0CFpE5x.js → ganttDiagram-FUAMR5RP-CojF9Q16.js} +1 -1
  204. package/packages/web/dist/client/assets/{gitGraph-4MIJSDKK-VPL7nv2c.js → gitGraph-4MIJSDKK-YvKqGEPk.js} +1 -1
  205. package/packages/web/dist/client/assets/{gitGraphDiagram-X574FWY7-CgxJA-T8.js → gitGraphDiagram-X574FWY7-XqNqIFo9.js} +1 -1
  206. package/packages/web/dist/client/assets/index--2CDtzvY.css +1 -0
  207. package/packages/web/dist/client/assets/{index-XTlTnQmx.js → index-bT6QPJZs.js} +7 -7
  208. package/packages/web/dist/client/assets/{info-A6RAGUB7-P0-o68pj.js → info-A6RAGUB7-B_1BCzM2.js} +1 -1
  209. package/packages/web/dist/client/assets/{infoDiagram-VRGFBTTK-DFJZNRUP.js → infoDiagram-VRGFBTTK-zFX8B-dP.js} +1 -1
  210. package/packages/web/dist/client/assets/{ishikawaDiagram-OU5B5YK6-ZkyhNd1T.js → ishikawaDiagram-OU5B5YK6-DLzQ_Uyf.js} +1 -1
  211. package/packages/web/dist/client/assets/{journeyDiagram-ZHPQQLJL-DFevH8my.js → journeyDiagram-ZHPQQLJL-S3WRMmoa.js} +1 -1
  212. package/packages/web/dist/client/assets/{kanban-definition-PNTS6WVX-l7e7ZZDC.js → kanban-definition-PNTS6WVX-B5Z8I-kM.js} +1 -1
  213. package/packages/web/dist/client/assets/{line-DO_s6Ujd.js → line-BGMH-i2X.js} +1 -1
  214. package/packages/web/dist/client/assets/{linear-C4xH5PPc.js → linear-KsrestXG.js} +1 -1
  215. package/packages/web/dist/client/assets/{mermaid-parser.core-nQaTP3VY.js → mermaid-parser.core-DNffyJJA.js} +3 -3
  216. package/packages/web/dist/client/assets/{mermaid.core-Cz05yTZh.js → mermaid.core-Cz3vJeQG.js} +4 -4
  217. package/packages/web/dist/client/assets/{mindmap-definition-NLK3R4M7-CHOEuHm2.js → mindmap-definition-NLK3R4M7-CzA61XUf.js} +1 -1
  218. package/packages/web/dist/client/assets/{packet-AYTQ26CC-BH3ehPMo.js → packet-AYTQ26CC-BO55e7cR.js} +1 -1
  219. package/packages/web/dist/client/assets/{pegDiagram-GJSIUBJH-CkWBLtad.js → pegDiagram-GJSIUBJH-DeRiXYNd.js} +1 -1
  220. package/packages/web/dist/client/assets/{pie-WAS4IAKB-nNVEq3dx.js → pie-WAS4IAKB-D9ibrQRe.js} +1 -1
  221. package/packages/web/dist/client/assets/{pieDiagram-5QR66LMP-DimUBAgN.js → pieDiagram-5QR66LMP-BaBpPP33.js} +1 -1
  222. package/packages/web/dist/client/assets/{quadrantDiagram-O4NWA36T-BR0XpRGQ.js → quadrantDiagram-O4NWA36T-DIfn4GjM.js} +1 -1
  223. package/packages/web/dist/client/assets/{radar-RG4KPBEZ-paA-H3mb.js → radar-RG4KPBEZ-Dmn5-nJq.js} +1 -1
  224. package/packages/web/dist/client/assets/{railroad-74A4TZTK-yEiKB3rz.js → railroad-74A4TZTK-ZCWNEd2Z.js} +1 -1
  225. package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-_swqhy0y.js +1 -0
  226. package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-CytbazPx.js +1 -0
  227. package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-Bg8QW17T.js +1 -0
  228. package/packages/web/dist/client/assets/{railroadDiagram-XR7U4H2S--TXe6rdU.js → railroadDiagram-XR7U4H2S-CDPZ39sy.js} +1 -1
  229. package/packages/web/dist/client/assets/{requirementDiagram-PLB6GJNP-DyqH36Za.js → requirementDiagram-PLB6GJNP-CyCI8Yul.js} +1 -1
  230. package/packages/web/dist/client/assets/{sankeyDiagram-IPEJSGJF-Bg6e3BlM.js → sankeyDiagram-IPEJSGJF-p_XAPv72.js} +1 -1
  231. package/packages/web/dist/client/assets/{sequenceDiagram-PO4LG4MO-ClGf85My.js → sequenceDiagram-PO4LG4MO-DmR6IP_o.js} +1 -1
  232. package/packages/web/dist/client/assets/{src-DF7hQfMh.js → src-gnv7pJ1z.js} +1 -1
  233. package/packages/web/dist/client/assets/{stateDiagram-v2-GCMORJYK-BK8TpxNo.js → stateDiagram-v2-GCMORJYK-7ZTHl6ih.js} +1 -1
  234. package/packages/web/dist/client/assets/{swimlanes-2SLR337P-DDnTIT9M.js → swimlanes-2SLR337P-N6bj71pw.js} +1 -1
  235. package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-BJQ2CBsp.js +8 -0
  236. package/packages/web/dist/client/assets/{timeline-definition-EJHVYXUP-mBBbH3bk.js → timeline-definition-EJHVYXUP-GNez0kW8.js} +1 -1
  237. package/packages/web/dist/client/assets/{treeView-Q6P3EWNA-CTK7tRwR.js → treeView-Q6P3EWNA-DyQZkboR.js} +1 -1
  238. package/packages/web/dist/client/assets/{treemap-WGGIJYW6-vOI-Ef_m.js → treemap-WGGIJYW6-_J8Pw2TM.js} +1 -1
  239. package/packages/web/dist/client/assets/{usecaseDiagram-POWQR4AR-COcii8x-.js → usecaseDiagram-POWQR4AR-Bg-CzKjl.js} +1 -1
  240. package/packages/web/dist/client/assets/{vennDiagram-UO4OBE2U-D6kmDGpM.js → vennDiagram-UO4OBE2U-DBQKHXhK.js} +1 -1
  241. package/packages/web/dist/client/assets/{wardley-WFR3VGLG-CtE2KI9r.js → wardley-WFR3VGLG-B5aAsQ3F.js} +1 -1
  242. package/packages/web/dist/client/assets/{wardleyDiagram-VNRHLVJA-ncxNGWnW.js → wardleyDiagram-VNRHLVJA-BKUQ1LK6.js} +1 -1
  243. package/packages/web/dist/client/assets/{xychartDiagram-PMCCYNJV-DUvd2Qze.js → xychartDiagram-PMCCYNJV-BI2sVbks.js} +1 -1
  244. package/packages/web/dist/client/index.html +2 -2
  245. package/packages/web/dist/client/assets/architecture-7GRP2DOG-HIzEIkwQ.js +0 -1
  246. package/packages/web/dist/client/assets/channel-BCA6qe9I.js +0 -1
  247. package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-l6SYFw1s.js +0 -1
  248. package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-CWW9qnqm.js +0 -1
  249. package/packages/web/dist/client/assets/index-D9_XJLSc.css +0 -1
  250. package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-mVQx9aVM.js +0 -1
  251. package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-CllXx1OJ.js +0 -1
  252. package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-BBD2Q5W_.js +0 -1
  253. package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-CM8UnP5t.js +0 -8
@@ -43,27 +43,26 @@ function prepare<T>(candidates: readonly FuzzyCandidate<T>[]): FuzzyIndex<T> {
43
43
  return {
44
44
  find: (query, options = {}) => {
45
45
  const trimmed = query.trim();
46
- const limit = options.limit ?? Infinity;
47
46
  if (trimmed.length === 0) {
48
- if (emptyHits === undefined) {
49
- emptyHits = [...candidates]
50
- .sort((a, b) =>
51
- (a.haystacks[0] ?? "").localeCompare(b.haystacks[0] ?? "")
52
- )
53
- .map((candidate) => ({
54
- item: candidate.item,
55
- score: 0,
56
- positions: new Set<number>(),
57
- }));
58
- }
59
- return limit === Infinity ? emptyHits : emptyHits.slice(0, limit);
47
+ emptyHits ??= [...candidates]
48
+ .sort((a, b) =>
49
+ (a.haystacks[0] ?? "").localeCompare(b.haystacks[0] ?? "")
50
+ )
51
+ .map((candidate) => ({
52
+ item: candidate.item,
53
+ score: 0,
54
+ positions: new Set<number>(),
55
+ }));
56
+ return emptyHits.slice(0, options.limit);
60
57
  }
61
- const hits = fzf.find(trimmed).map((result) => ({
62
- item: result.item.item,
63
- score: result.score,
64
- positions: result.positions,
65
- }));
66
- return limit === Infinity ? hits : hits.slice(0, limit);
58
+ return fzf
59
+ .find(trimmed)
60
+ .slice(0, options.limit)
61
+ .map((result) => ({
62
+ item: result.item.item,
63
+ score: result.score,
64
+ positions: result.positions,
65
+ }));
67
66
  },
68
67
  };
69
68
  }
@@ -6,32 +6,26 @@ import { Proc, type ProcOptions, type ProcResult } from "./Proc";
6
6
 
7
7
  export type GitState = {
8
8
  readonly branch: string | null;
9
- /** Paths `git status` lists as changed; zero is a clean tree. */
10
9
  readonly dirtyCount: number;
11
10
  readonly ahead: number;
12
11
  readonly behind: number;
13
- /**
14
- * Changes whenever the repository's content does: the commit at head, every
15
- * path git calls changed, and what each of those paths now holds. A count
16
- * cannot see an edit to a file already dirty; this can.
17
- */
12
+ /** Hash of HEAD, the changed paths and their stats; also moves when an already-dirty file is edited again. */
18
13
  readonly revision: string;
19
14
  };
20
15
 
21
- /** One local branch, as `listBranches` ranks and labels it. */
22
16
  export type GitBranch = {
23
17
  readonly name: string;
24
18
  readonly current: boolean;
25
- /** The branch `origin/HEAD` points at, or the first of `main`/`master`/`trunk` that exists. */
19
+ /** `origin/HEAD`'s target, else the first of `main`/`master`/`trunk` that exists. */
26
20
  readonly isDefault: boolean;
27
- /** Its last commit, in epoch seconds. */
21
+ /** Last commit time, epoch seconds. */
28
22
  readonly updatedAt: number;
29
23
  readonly ahead: number;
30
24
  readonly behind: number;
31
- /** It tracked a remote branch that has since been deleted, so its work has usually landed. */
25
+ /** Its upstream branch was deleted. */
32
26
  readonly gone: boolean;
33
27
  readonly merged: boolean;
34
- /** Checked out in another worktree, where git will refuse to take it from. */
28
+ /** Checked out in another worktree. */
35
29
  readonly worktree: boolean;
36
30
  };
37
31
 
@@ -41,7 +35,7 @@ export type GitOutcome =
41
35
 
42
36
  export type CommitRequest = {
43
37
  readonly message: string;
44
- /** Exactly what is committed; a rename contributes both of its names. */
38
+ /** Exactly what is committed; a rename lists both names. */
45
39
  readonly paths: readonly string[];
46
40
  };
47
41
 
@@ -81,7 +75,7 @@ const COMMIT_TIMEOUT_MS = 120_000;
81
75
 
82
76
  const ERROR_LIMIT = 400;
83
77
 
84
- /** No surface behind a daemon can answer a credential prompt, so every network call must fail instead of waiting on one. */
78
+ /** Fail instead of waiting on a credential prompt nobody can answer. */
85
79
  const NETWORK_ENV: Readonly<Record<string, string | undefined>> = {
86
80
  GIT_TERMINAL_PROMPT: "0",
87
81
  GIT_ASKPASS: undefined,
@@ -90,7 +84,7 @@ const NETWORK_ENV: Readonly<Record<string, string | undefined>> = {
90
84
  GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND ?? "ssh -o BatchMode=yes",
91
85
  };
92
86
 
93
- /** A commit runs hooks and may sign, neither of which may open an editor on a machine nobody is sitting at. */
87
+ /** Hooks and signing must never open an editor. */
94
88
  const COMMIT_OPTIONS: ProcOptions = {
95
89
  env: { GIT_EDITOR: "true" },
96
90
  timeoutMs: COMMIT_TIMEOUT_MS,
@@ -109,17 +103,13 @@ function git(
109
103
  }
110
104
 
111
105
  function network(cwd: string, args: readonly string[]): Promise<ProcResult> {
112
- return Proc.run(["git", ...args], {
113
- cwd,
114
- env: NETWORK_ENV,
115
- timeoutMs: NETWORK_TIMEOUT_MS,
116
- });
106
+ return git(cwd, args, { env: NETWORK_ENV, timeoutMs: NETWORK_TIMEOUT_MS });
117
107
  }
118
108
 
119
- /** Which field of a porcelain-v2 entry holds the path it is about. */
109
+ /** Index of the path field in each porcelain-v2 entry type. */
120
110
  const PATH_FIELD: Readonly<Record<string, number>> = { "1": 8, "2": 9, u: 10 };
121
111
 
122
- /** Beyond this many changed paths the count alone stands for the worktree. */
112
+ /** Only the first this-many changed paths are stat'd into the revision. */
123
113
  const SAMPLE_LIMIT = 500;
124
114
 
125
115
  function pathOf(line: string): string {
@@ -135,7 +125,6 @@ function pathOf(line: string): string {
135
125
  return line.split(" ").slice(field).join(" ").split("\t")[0] ?? "";
136
126
  }
137
127
 
138
- /** What a changed path holds now, cheaply enough to read on every poll. */
139
128
  function worktreeSample(cwd: string): (path: string) => string {
140
129
  return (path) => {
141
130
  const stats = statSync(join(cwd, path), { throwIfNoEntry: false });
@@ -205,7 +194,6 @@ function parseTrack(text: string): {
205
194
  };
206
195
  }
207
196
 
208
- /** What one `for-each-ref` line says; `rank` adds the two facts that need the whole list. */
209
197
  type Ref = Omit<GitBranch, "isDefault" | "merged">;
210
198
 
211
199
  function parseRefs(text: string): readonly Ref[] {
@@ -228,7 +216,7 @@ function parseRefs(text: string): readonly Ref[] {
228
216
 
229
217
  const MOVING = "checkout: moving from ";
230
218
 
231
- /** When each branch was last checked out, newest first, so a branch worked on without committing still ranks. */
219
+ /** Last checkout time per branch, from the reflog. */
232
220
  function parseVisits(text: string): ReadonlyMap<string, number> {
233
221
  const visits = new Map<string, number>();
234
222
  for (const line of Lines.split(text)) {
@@ -285,7 +273,7 @@ async function remoteOf(cwd: string): Promise<string | undefined> {
285
273
  return remotes.length === 1 ? remotes[0] : undefined;
286
274
  }
287
275
 
288
- /** What the remote calls its trunk; absent when no remote names one. */
276
+ /** The remote's default branch, if it names one. */
289
277
  async function remoteHead(cwd: string): Promise<string | undefined> {
290
278
  const remote = await remoteOf(cwd);
291
279
  if (remote === undefined) {
@@ -315,7 +303,7 @@ async function mergedInto(
315
303
  return new Set(code === 0 ? Lines.split(stdout) : []);
316
304
  }
317
305
 
318
- /** Every local branch, trunk first and the rest by the last time they were committed to or checked out. */
306
+ /** Local branches: default first, then by last commit or checkout. */
319
307
  async function listBranches(cwd: string): Promise<readonly GitBranch[]> {
320
308
  const [refs, log, remote] = await Promise.all([
321
309
  git(cwd, ["for-each-ref", "--format", BRANCH_FORMAT, "refs/heads/"]),
@@ -337,10 +325,7 @@ async function listBranches(cwd: string): Promise<readonly GitBranch[]> {
337
325
  );
338
326
  }
339
327
 
340
- /**
341
- * What a failed `git` said, in one line: its own words where it had any, the
342
- * caller's fallback where it had none, and the timeout where it never answered.
343
- */
328
+ /** git's own error text, else `fallback`, or `timeout` when it timed out. */
344
329
  function failure(
345
330
  result: ProcResult,
346
331
  fallback: string,
@@ -369,16 +354,12 @@ async function checkout(cwd: string, branch: string): Promise<GitOutcome> {
369
354
  );
370
355
  }
371
356
 
372
- /** A path git is allowed to be pointed at: inside the repository, and named relative to it. */
357
+ /** True for an empty, absolute or `..` path. */
373
358
  function escapes(path: string): boolean {
374
359
  return path === "" || isAbsolute(path) || path.split(/[/\\]/).includes("..");
375
360
  }
376
361
 
377
- /**
378
- * Commits exactly `paths` and nothing else: everything else changed stays
379
- * dirty, and an unrelated path someone had staged stays staged. Untracked
380
- * paths are added first, or a path-limited commit of one finds no such file.
381
- */
362
+ /** Commits exactly `paths`; other changes, staged or not, are left alone. */
382
363
  async function commit(
383
364
  cwd: string,
384
365
  request: CommitRequest
@@ -397,13 +378,8 @@ async function commit(
397
378
  error: `${outside === "" ? "an empty path" : outside} is not a path inside this repository`,
398
379
  };
399
380
  }
400
- /**
401
- * `git add` refuses a pathspec that matches nothing on disk, and a staged
402
- * rename's old name matches nothing: it is gone from both the worktree and
403
- * the index. A deletion is the same. `git commit -- <paths>` reads those two
404
- * off HEAD and the index by itself, so only the paths still on disk are
405
- * worth adding, and a pick made entirely of them needs no `add` at all.
406
- */
381
+ // Add only paths on disk: `git add` rejects deleted paths and a rename's old
382
+ // name, and `git commit -- <paths>` handles those itself.
407
383
  const onDisk = await Promise.all(
408
384
  request.paths.map((path) => Bun.file(join(cwd, path)).exists())
409
385
  );
@@ -457,7 +433,7 @@ async function pull(cwd: string): Promise<GitOutcome> {
457
433
  );
458
434
  }
459
435
 
460
- /** The remote branch HEAD tracks, or undefined when the branch is local-only or HEAD is detached. */
436
+ /** Undefined when the branch has no upstream or HEAD is detached. */
461
437
  async function upstreamOf(cwd: string): Promise<string | undefined> {
462
438
  const { code, stdout } = await git(cwd, [
463
439
  "rev-parse",
@@ -469,7 +445,7 @@ async function upstreamOf(cwd: string): Promise<string | undefined> {
469
445
  return code === 0 && name !== "" ? name : undefined;
470
446
  }
471
447
 
472
- /** Publishes the branch, adopting the remote as its upstream the first time it is pushed. */
448
+ /** Sets the upstream on the first push. */
473
449
  async function push(cwd: string): Promise<GitOutcome> {
474
450
  const [head, upstream] = await Promise.all([
475
451
  git(cwd, ["symbolic-ref", "--quiet", "--short", "HEAD"]),
@@ -500,7 +476,7 @@ async function push(cwd: string): Promise<GitOutcome> {
500
476
  async function fetchStatus(cwd: string): Promise<GitState> {
501
477
  try {
502
478
  const { code, stdout } = await git(cwd, [
503
- // Or the chip's own read takes `index.lock` and fails the checkout beside it.
479
+ // Avoids taking `index.lock`, which would fail a concurrent checkout.
504
480
  "--no-optional-locks",
505
481
  "status",
506
482
  "--porcelain=v2",
@@ -512,7 +488,6 @@ async function fetchStatus(cwd: string): Promise<GitState> {
512
488
  }
513
489
  }
514
490
 
515
- /** The cwd's git state, for the TUI footer and the web's branch menu. */
516
491
  export const Git = {
517
492
  EMPTY,
518
493
  parseStatus,
@@ -5,16 +5,13 @@ import { Git, type GitOutcome, type GitState } from "./Git";
5
5
 
6
6
  export type GitListener = (state: GitState) => void;
7
7
 
8
- /**
9
- * What one operation under the lock says, and what it made where it made
10
- * anything: a commit has a sha to hand back, a checkout has only its outcome.
11
- */
8
+ /** `value` carries an operation's result, e.g. a commit's sha. */
12
9
  export type GitRun<T = never> = GitOutcome & { readonly value?: T };
13
10
 
14
11
  export type GitMonitorDeps = {
15
- /** How long a fetch stands before another is worth its round trip. */
12
+ /** Minimum gap between fetches. Defaults to 30s. */
16
13
  readonly fetchTtlMs?: number;
17
- /** How often a watched repository is read for the edits `.git` never hears about. */
14
+ /** Poll for worktree edits, which `.git` never sees. Defaults to 2s. */
18
15
  readonly pollMs?: number;
19
16
  readonly status?: (cwd: string) => Promise<GitState>;
20
17
  readonly fetch?: (cwd: string) => Promise<GitOutcome>;
@@ -29,20 +26,18 @@ type Entry = {
29
26
  pending: boolean;
30
27
  fetchedAt: number;
31
28
  locked: boolean;
32
- /** How long the last read took, and when it ended: what the poll paces itself by. */
29
+ /** Duration and end time of the last read; the poll backs off by these. */
33
30
  readMs: number;
34
31
  readAt: number;
35
32
  };
36
33
 
37
- /** A checkout writes half the repository; one read has to stand for the burst. */
38
34
  const DEBOUNCE_MS = 200;
39
35
 
40
36
  const FETCH_TTL_MS = 30_000;
41
37
 
42
- /** A worktree edit touches nothing under `.git`, so the watch alone would never see it. */
43
38
  const POLL_MS = 2_000;
44
39
 
45
- /** A repository too big to read in a tick is read this many times its own cost apart. */
40
+ /** A slow repository is polled at most once per this many read durations. */
46
41
  const BACKOFF = 4;
47
42
 
48
43
  function same(a: GitState, b: GitState): boolean {
@@ -55,12 +50,7 @@ function same(a: GitState, b: GitState): boolean {
55
50
  );
56
51
  }
57
52
 
58
- /**
59
- * One reader of one repository, however many sessions share it: it watches
60
- * `.git` so a commit anywhere reaches every surface, coalesces the burst a
61
- * checkout makes into a single read, and serialises the operations that write,
62
- * which cannot run two at a time over one index.
63
- */
53
+ /** One shared reader per repository: watches `.git`, debounces reads, and allows one writing operation at a time. */
64
54
  export class GitMonitor {
65
55
  private readonly entries = new Map<string, Entry>();
66
56
  private readonly deps: GitMonitorDeps;
@@ -69,7 +59,7 @@ export class GitMonitor {
69
59
  this.deps = deps;
70
60
  }
71
61
 
72
- /** Follows `cwd` until the returned stop is called; the listener hears only changes, after a read of its own. */
62
+ /** The listener hears only changes. */
73
63
  public watch(cwd: string, listener: GitListener): () => void {
74
64
  const entry = this.entryOf(cwd);
75
65
  entry.listeners.add(listener);
@@ -84,12 +74,12 @@ export class GitMonitor {
84
74
  };
85
75
  }
86
76
 
87
- /** The last state read, without waiting: a caller painting a frame takes what is known now. */
77
+ /** The last state read; never waits. */
88
78
  public stateOf(cwd: string): GitState {
89
79
  return this.entries.get(cwd)?.state ?? Git.EMPTY;
90
80
  }
91
81
 
92
- /** Re-reads now; `fetch` also asks the remote, which is what ahead and behind are counted against. */
82
+ /** `fetch` also fetches the remote first, at most once per TTL. */
93
83
  public async refresh(
94
84
  cwd: string,
95
85
  options: { readonly fetch?: boolean } = {}
@@ -107,7 +97,7 @@ export class GitMonitor {
107
97
  return await this.read(entry);
108
98
  }
109
99
 
110
- /** Runs one writing operation over `cwd`, refusing a second while it lasts and re-reading once it ends. */
100
+ /** Refuses while another operation runs on `cwd`; re-reads after. */
111
101
  public async run<T = never>(
112
102
  cwd: string,
113
103
  operation: () => Promise<GitRun<T>>
@@ -165,8 +155,7 @@ export class GitMonitor {
165
155
  }, DEBOUNCE_MS);
166
156
  timer.unref?.();
167
157
  });
168
- // `false`: a read already running is fresh enough for a tick, and a slow
169
- // status must never queue another behind itself.
158
+ // `false`: a tick must not queue a read behind a slow one.
170
159
  const poll = setInterval(() => {
171
160
  if (Date.now() - entry.readAt < entry.readMs * BACKOFF) {
172
161
  return;
@@ -181,7 +170,7 @@ export class GitMonitor {
181
170
  };
182
171
  }
183
172
 
184
- /** `restart` re-reads behind a read already running: a change cannot be answered by a read that predates it, a new subscriber can. */
173
+ /** `restart` re-reads after an in-flight read, which may predate the change. */
185
174
  private read(entry: Entry, restart = true): Promise<GitState> {
186
175
  if (entry.inFlight) {
187
176
  entry.pending ||= restart;
@@ -3,10 +3,6 @@ function compile(exclude: readonly string[] | undefined): readonly Bun.Glob[] {
3
3
  }
4
4
 
5
5
  function ignores(globs: readonly Bun.Glob[], relativePath: string): boolean {
6
- if (globs.length === 0) {
7
- return false;
8
- }
9
-
10
6
  return globs.some((glob) => glob.match(relativePath));
11
7
  }
12
8
 
@@ -5,7 +5,7 @@ export type HttpFetch = (
5
5
  init?: Parameters<typeof fetch>[1]
6
6
  ) => ReturnType<typeof fetch>;
7
7
 
8
- /** Ky with retries off: its defaults retry GETs twice and honour `Retry-After` uncapped, stalling a tool for hours. */
8
+ /** Retries off: ky's default honours `Retry-After` uncapped and can stall a tool for hours. */
9
9
  export function createKy(custom?: HttpFetch): KyInstance {
10
10
  return ky.create({
11
11
  retry: 0,
@@ -1,4 +1,3 @@
1
- /** The formats every provider we target accepts. */
2
1
  export type ImageMimeType =
3
2
  | "image/png"
4
3
  | "image/jpeg"
@@ -12,13 +11,12 @@ const EXTENSIONS = {
12
11
  "image/webp": "webp",
13
12
  } satisfies Record<ImageMimeType, string>;
14
13
 
15
- /** Both spellings of every format, so `.jpeg` names a picture as surely as `.jpg`. */
14
+ /** Includes both `jpg` and `jpeg`. */
16
15
  const NAME_EXTENSIONS = new Set([
17
16
  ...Object.values(EXTENSIONS),
18
17
  ...Object.keys(EXTENSIONS).map((mimeType) => mimeType.slice("image/".length)),
19
18
  ]);
20
19
 
21
- /** The format as a word, in the one spelling the notes, the UI and the cache filename all use. */
22
20
  function extensionOf(mimeType: ImageMimeType): string {
23
21
  return EXTENSIONS[mimeType];
24
22
  }
@@ -27,10 +25,10 @@ function isSupported(mimeType: string): mimeType is ImageMimeType {
27
25
  return Object.hasOwn(EXTENSIONS, mimeType);
28
26
  }
29
27
 
30
- /** Whether a bare, lowercased extension is one of the spellings a picture goes by. */
28
+ /** Takes a bare, lowercased extension. */
31
29
  function namesExtension(extension: string): boolean {
32
30
  return NAME_EXTENSIONS.has(extension);
33
31
  }
34
32
 
35
- /** The format table alone, free of Node so the browser can name a picture too. */
33
+ /** Browser-safe: no Node imports. */
36
34
  export const ImageMime = { extensionOf, isSupported, namesExtension };
@@ -10,33 +10,31 @@ import { SpillCache } from "./SpillCache";
10
10
 
11
11
  export type { ImageMimeType };
12
12
 
13
- /** What a tool needs off `ctx.model` to know whether a picture can be sent. */
14
13
  export type VisionModel = {
15
14
  readonly id: string;
16
15
  readonly input: readonly string[];
17
16
  };
18
17
 
19
- /** An image the providers will take: within their formats, dimensions and byte budget. */
20
18
  export type NormalisedImage = {
21
19
  readonly base64: string;
22
20
  readonly mimeType: ImageMimeType;
23
21
  readonly width: number;
24
22
  readonly height: number;
25
- /** Encoded size after the resize, which is what the cache holds. */
23
+ /** Encoded size after the resize. */
26
24
  readonly bytes: number;
27
25
  readonly originalWidth: number;
28
26
  readonly originalHeight: number;
29
- /** The container the frames were counted in: a resize is free to re-encode as another. */
27
+ /** May differ from `mimeType`: a resize can re-encode. */
30
28
  readonly originalMimeType: ImageMimeType;
31
29
  readonly resized: boolean;
32
- /** Frames in the source container, 1 for a still: the encoded copy holds only the first. */
30
+ /** Frames in the source; the encoded copy keeps only the first. */
33
31
  readonly frames: number;
34
32
  readonly sha256: string;
35
33
  /** `~/.pim/cache/img-<sha256>.<ext>`, or null when the cache write failed. */
36
34
  readonly cachePath: string | null;
37
35
  };
38
36
 
39
- /** What every tool records about a picture it showed: the picture itself never rides here, `sha256` addresses it in the spill cache. */
37
+ /** No pixel data: `sha256` addresses the picture in the spill cache. */
40
38
  export type ImageDetails = {
41
39
  readonly sha256: string;
42
40
  readonly mimeType: ImageMimeType;
@@ -49,12 +47,12 @@ export type ImageDetails = {
49
47
 
50
48
  type ToolContent = AgentToolResult<unknown>["content"];
51
49
 
52
- /** Never decode past this: a mislabelled video is rejected on its size alone. */
50
+ /** Larger sources are rejected before decoding. */
53
51
  const MAX_SOURCE_BYTES = 25 * 1024 * 1024;
54
52
  const MAX_EDGE = 2000;
55
53
  const MAX_ENCODED_BYTES = 3_932_160;
56
54
 
57
- /** Enough for every magic-byte signature, WebP's `RIFF….WEBP` included. */
55
+ /** Long enough for every signature, including WebP's `RIFF….WEBP`. */
58
56
  const SNIFF_BYTES = 12;
59
57
 
60
58
  const CACHE_PREFIX = "img-";
@@ -81,7 +79,7 @@ function startsWith(
81
79
  return signature.every((byte, index) => bytes[offset + index] === byte);
82
80
  }
83
81
 
84
- /** Magic bytes only: an extension is a claim, not evidence. */
82
+ /** By magic bytes, never by extension. */
85
83
  function sniff(bytes: Uint8Array): ImageMimeType | null {
86
84
  if (startsWith(bytes, PNG)) {
87
85
  return "image/png";
@@ -102,7 +100,7 @@ function view(bytes: Uint8Array): DataView {
102
100
  return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
103
101
  }
104
102
 
105
- /** RIFF chunks are padded to an even length, so an odd body carries one trailing byte. */
103
+ /** RIFF chunks are padded to an even length. */
106
104
  function webpFrames(bytes: Uint8Array): number {
107
105
  const reader = view(bytes);
108
106
  let count = 0;
@@ -117,7 +115,7 @@ function webpFrames(bytes: Uint8Array): number {
117
115
  return count;
118
116
  }
119
117
 
120
- /** `acTL` carries the count outright, and must appear before the first `IDAT`. */
118
+ /** `acTL` holds the count and must come before the first `IDAT`. */
121
119
  function apngFrames(bytes: Uint8Array): number {
122
120
  const reader = view(bytes);
123
121
  let at = 8;
@@ -173,32 +171,30 @@ const FRAME_READERS: Partial<
173
171
  "image/gif": gifFrames,
174
172
  };
175
173
 
176
- /** Headers only: the count has to be read before the resize, which keeps frame 1 alone. */
174
+ /** Read from the source, since the resize keeps only frame 1. */
177
175
  function frames(bytes: Uint8Array, mimeType: ImageMimeType): number {
178
176
  return Math.max(1, FRAME_READERS[mimeType]?.(bytes) ?? 1);
179
177
  }
180
178
 
181
- /** An unknown model is not a blind one: only a model that names its inputs can rule the picture out. */
179
+ /** An unknown model is assumed to see. */
182
180
  function canSee(model: VisionModel | undefined): boolean {
183
181
  return model === undefined || model.input.includes("image");
184
182
  }
185
183
 
186
- /** What a model without eyes is told in place of the picture it cannot be sent. */
187
184
  function noVisionNote(tool: string, subject: string): string {
188
185
  return `[${tool} tool: ${subject}; the current model has no vision input.]`;
189
186
  }
190
187
 
191
- /** A name that claims a picture — a claim the bytes still have to back. */
192
188
  function looksLikeImageName(path: string): boolean {
193
189
  return ImageMime.namesExtension(extname(path).slice(1).toLowerCase());
194
190
  }
195
191
 
196
- /** What the spill cache holds the picture under; the resize picks the extension, never the source path. */
192
+ /** The extension follows the encoded type, not the source path. */
197
193
  function cacheName(sha256: string, mimeType: ImageMimeType): string {
198
194
  return `${CACHE_PREFIX}${sha256}.${ImageMime.extensionOf(mimeType)}`;
199
195
  }
200
196
 
201
- /** Refuse on the stat alone, so a mislabelled video is never pulled into memory. */
197
+ /** Meant for the stat size, so an oversized file is never read. */
202
198
  function assertWithinSourceCap(byteLength: number, path: string): void {
203
199
  if (byteLength > MAX_SOURCE_BYTES) {
204
200
  throw new Error(
@@ -231,7 +227,7 @@ async function normalise(
231
227
  );
232
228
  }
233
229
 
234
- // An unresized encode is the input re-spelled: decoding it back would copy the bytes twice.
230
+ // Unresized output is the input, so skip decoding the base64 back.
235
231
  const data = resized.wasResized ? Buffer.from(resized.data, "base64") : bytes;
236
232
  const mimeType = ImageMime.isSupported(resized.mimeType)
237
233
  ? resized.mimeType
@@ -256,7 +252,6 @@ async function normalise(
256
252
  };
257
253
  }
258
254
 
259
- /** The record of the picture a tool hands its view, off the picture itself. */
260
255
  function detailsOf(image: NormalisedImage): ImageDetails {
261
256
  return {
262
257
  sha256: image.sha256,
@@ -269,7 +264,7 @@ function detailsOf(image: NormalisedImage): ImageDetails {
269
264
  };
270
265
  }
271
266
 
272
- /** Text first, the way pi's own read orders it. */
267
+ /** Text first, matching pi's read tool. */
273
268
  function contentOf(image: NormalisedImage, note?: string): ToolContent {
274
269
  const picture = {
275
270
  type: "image" as const,
@@ -281,7 +276,6 @@ function contentOf(image: NormalisedImage, note?: string): ToolContent {
281
276
  : [{ type: "text", text: note }, picture];
282
277
  }
283
278
 
284
- /** How the model maps coordinates it reads off the picture back onto the file. */
285
279
  function resizeNote(image: NormalisedImage): string | undefined {
286
280
  if (!image.resized) {
287
281
  return undefined;
@@ -290,10 +284,7 @@ function resizeNote(image: NormalisedImage): string | undefined {
290
284
  return `image resized from ${image.originalWidth}x${image.originalHeight} to ${image.width}x${image.height}; multiply coordinates by ${scale} to map to the original.`;
291
285
  }
292
286
 
293
- /**
294
- * What the picture leaves out, which a still under every cap says nothing about:
295
- * providers see one frame, so an unmentioned animation reads as an empty screen.
296
- */
287
+ /** Providers see only one frame, so say the image is animated. */
297
288
  function animationNote(image: NormalisedImage): string | undefined {
298
289
  if (image.frames < 2) {
299
290
  return undefined;
@@ -301,7 +292,6 @@ function animationNote(image: NormalisedImage): string | undefined {
301
292
  return `animated ${ImageMime.extensionOf(image.originalMimeType)}: ${image.frames} frames, ${image.originalWidth}x${image.originalHeight}; frame 1 shown.`;
302
293
  }
303
294
 
304
- /** Everything true of the picture that is not in the picture. */
305
295
  function noteOf(image: NormalisedImage): string | undefined {
306
296
  const notes = [resizeNote(image), animationNote(image)].filter(
307
297
  (note) => note !== undefined
@@ -309,7 +299,7 @@ function noteOf(image: NormalisedImage): string | undefined {
309
299
  return notes.length === 0 ? undefined : notes.join(" ");
310
300
  }
311
301
 
312
- /** What the bytes are instead, in the words a person would use to go find them. */
302
+ /** A human description of non-image bytes. */
313
303
  function describe(bytes: Uint8Array): string {
314
304
  if (bytes.length === 0) {
315
305
  return "an empty file";
@@ -1,4 +1,4 @@
1
- // Values are highlight.js language ids; keep this module import-free, the web bundle needs it.
1
+ // Values are highlight.js language ids. Keep import-free: the web bundle uses it.
2
2
 
3
3
  const ALIASES: Readonly<Record<string, string>> = {
4
4
  ts: "typescript",
@@ -77,7 +77,7 @@ const ALIASES: Readonly<Record<string, string>> = {
77
77
 
78
78
  const CANONICAL: ReadonlySet<string> = new Set(Object.values(ALIASES));
79
79
 
80
- // Never guess a language: auto-detection paints ordinary prose as keywords.
80
+ // Unknown names stay undefined: auto-detection paints prose as code.
81
81
  function resolve(name: string | undefined): string | undefined {
82
82
  if (name === undefined) {
83
83
  return undefined;
@@ -27,12 +27,7 @@ function distance(left: string, right: string): number {
27
27
  return previous[right.length] ?? 0;
28
28
  }
29
29
 
30
- /**
31
- * Damerau–Levenshtein, where a transposition is one edit rather than two, and
32
- * a pair that cannot reach `max` answers `max + 1` without finishing the
33
- * matrix — the shape a vocabulary scan wants, since almost every term it asks
34
- * about is nowhere near.
35
- */
30
+ /** Damerau–Levenshtein (a transposition is one edit). Returns `max + 1` early once over `max`. */
36
31
  function damerau(left: string, right: string, max: number): number {
37
32
  const over = max + 1;
38
33
  if (left === right) {
@@ -1,7 +1,7 @@
1
1
  const utf8Bom = "\uFEFF";
2
2
  const utf8BomBytes = new Uint8Array([0xef, 0xbb, 0xbf]);
3
3
 
4
- /** How far in a NUL is still evidence of a binary file rather than text. */
4
+ /** A NUL within this many leading bytes marks a file as binary. */
5
5
  const binarySniffBytes = 8192;
6
6
 
7
7
  function normalize(content: string): string {
@@ -201,9 +201,9 @@ export class McpClient {
201
201
 
202
202
  private async sendCancellation(
203
203
  sessionId: string | undefined,
204
- requestId: number | undefined
204
+ requestId: number
205
205
  ): Promise<void> {
206
- if (sessionId === undefined || requestId === undefined) {
206
+ if (sessionId === undefined) {
207
207
  return;
208
208
  }
209
209
 
@@ -36,5 +36,5 @@ export function cleanPath(raw: string): string {
36
36
  return path;
37
37
  }
38
38
 
39
- /** Fault-tolerant scan of V4A patch text for renderers; unrecognized lines are ignored. */
39
+ /** Lenient scan of V4A patch text for renderers; unknown lines are ignored. */
40
40
  export const PatchSummary = { firstPath };