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
@@ -36,7 +36,10 @@ function expandHome(value: string): string {
36
36
 
37
37
  function abbreviateHome(path: string): string {
38
38
  const home = homedir();
39
- return home && path.startsWith(home) ? `~${path.slice(home.length)}` : path;
39
+ if (!home || !(path === home || path.startsWith(home + sep))) {
40
+ return path;
41
+ }
42
+ return `~${path.slice(home.length)}`;
40
43
  }
41
44
 
42
45
  function displayRelative(path: string, cwd: string): string {
@@ -10,11 +10,7 @@ import { ExtensionToggles } from "./ExtensionToggles";
10
10
  import { Fs } from "./Fs";
11
11
  import { Paths } from "./Paths";
12
12
 
13
- /**
14
- * Every origin an entry comes from, in the order a reader meets them: the
15
- * roster is sorted by it, and a pane groups what it is handed without
16
- * restating it.
17
- */
13
+ /** Also the sort order of `list`. */
18
14
  const EXTENSION_GROUPS = ["pim", "package", "user", "project"] as const;
19
15
 
20
16
  export type ExtensionGroup = (typeof EXTENSION_GROUPS)[number];
@@ -24,7 +20,7 @@ export type ExtensionEntry = {
24
20
  readonly label: string;
25
21
  readonly group: ExtensionGroup;
26
22
  readonly enabled: boolean;
27
- /** Whether this process will write the toggle; a project-scoped entry is listed but not switched. */
23
+ /** False for project-scoped entries: listed, but not switchable. */
28
24
  readonly writable: boolean;
29
25
  };
30
26
 
@@ -76,8 +72,7 @@ async function setEnabled(
76
72
  await writes.run(() => writePiToggle(id.slice("pi:".length), enabled, scope));
77
73
  }
78
74
 
79
- // A fresh SettingsManager per write: `setExtensionPaths` persists its in-memory
80
- // copy, which another process may have superseded since we last read it.
75
+ // Fresh SettingsManager per write: another process may have changed the file since.
81
76
  async function writePiToggle(
82
77
  path: string,
83
78
  enabled: boolean,
@@ -171,8 +166,7 @@ async function resolve(scope: ExtensionScope): Promise<Resolution> {
171
166
  agentDir,
172
167
  settingsManager,
173
168
  });
174
- // Without an answer, pi npm-installs every missing or drifted package, so a
175
- // bare listing request would fire off an install.
169
+ // "skip" stops pi from npm-installing missing packages during a listing.
176
170
  const resolved = await manager.resolve(async () => "skip");
177
171
  return { extensions: resolved.extensions, settingsManager };
178
172
  }
@@ -205,8 +199,7 @@ function piEntry(resource: ResolvedResource): ExtensionEntry {
205
199
  : fileLabel(path),
206
200
  group,
207
201
  enabled: resource.enabled,
208
- // Scope, not group: a package a project configures is written to the repo's
209
- // settings, which a browser toggle never touches.
202
+ // By scope, not group: project-configured packages live in the repo's settings.
210
203
  writable: metadata.scope === "user",
211
204
  };
212
205
  }
@@ -62,25 +62,24 @@ function load(): Promise<Settings> {
62
62
  return loaded;
63
63
  }
64
64
 
65
- async function getExaApiKey(): Promise<string | undefined> {
66
- return (
67
- normalize(process.env["EXA_API_KEY"]) ??
68
- normalize((await get("exa")).apiKey)
69
- );
65
+ function getExaApiKey(): Promise<string | undefined> {
66
+ return apiKey("EXA_API_KEY", "exa");
70
67
  }
71
68
 
72
- async function getJinaApiKey(): Promise<string | undefined> {
73
- return (
74
- normalize(process.env["JINA_API_KEY"]) ??
75
- normalize((await get("jina")).apiKey)
76
- );
69
+ function getJinaApiKey(): Promise<string | undefined> {
70
+ return apiKey("JINA_API_KEY", "jina");
77
71
  }
78
72
 
79
- async function getFirecrawlApiKey(): Promise<string | undefined> {
80
- return (
81
- normalize(process.env["FIRECRAWL_API_KEY"]) ??
82
- normalize((await get("firecrawl")).apiKey)
83
- );
73
+ function getFirecrawlApiKey(): Promise<string | undefined> {
74
+ return apiKey("FIRECRAWL_API_KEY", "firecrawl");
75
+ }
76
+
77
+ /** The env var wins over the settings file. */
78
+ async function apiKey(
79
+ envName: string,
80
+ key: "exa" | "jina" | "firecrawl"
81
+ ): Promise<string | undefined> {
82
+ return normalize(process.env[envName]) ?? normalize((await get(key)).apiKey);
84
83
  }
85
84
 
86
85
  function normalize(value: string | undefined): string | undefined {
@@ -1,9 +1,9 @@
1
1
  export type ProcOptions = {
2
2
  readonly cwd?: string | undefined;
3
3
  readonly stdout?: "pipe" | "inherit";
4
- /** Merged over the process environment; a key set to `undefined` is removed from it. */
4
+ /** Merged over `process.env`; an `undefined` value removes the key. */
5
5
  readonly env?: Readonly<Record<string, string | undefined>>;
6
- /** Kills the child once it elapses, answering `timedOut`. */
6
+ /** Kills the child and sets `timedOut` once elapsed. */
7
7
  readonly timeoutMs?: number;
8
8
  };
9
9
 
@@ -22,7 +22,6 @@ async function run(
22
22
  cwd: options.cwd,
23
23
  stdout: options.stdout ?? "pipe",
24
24
  stderr: "pipe",
25
- // `undefined` is Bun's own "inherit this process's environment".
26
25
  env:
27
26
  options.env === undefined
28
27
  ? undefined
@@ -1,4 +1,4 @@
1
- export type RateLimiterOptions = {
1
+ type RateLimiterOptions = {
2
2
  readonly maxRequests: number;
3
3
  readonly windowMs: number;
4
4
  readonly now?: () => number;
@@ -19,7 +19,7 @@ export type RenderContext = {
19
19
  readonly isError: boolean;
20
20
  };
21
21
 
22
- export type MarkerStatus = "warning" | "error" | "success";
22
+ type MarkerStatus = "warning" | "error" | "success";
23
23
 
24
24
  export type PrefixSpec = {
25
25
  readonly prefix: string;
@@ -358,14 +358,12 @@ function renderErrorResult(args: {
358
358
  export const Renderer = {
359
359
  GAPPED_PREFIX,
360
360
  TIGHT_PREFIX,
361
- markerColorFor,
362
361
  firstText,
363
362
  extractErrorText,
364
363
  toolTitleText,
365
364
  makeTitleBlock,
366
365
  renderToolCallTitle,
367
366
  makePrefixedBlock,
368
- markdownLines,
369
367
  makeMarkdownBlock,
370
368
  renderErrorResult,
371
369
  };
@@ -30,10 +30,10 @@ export type ChangeSummary = {
30
30
  readonly added: number;
31
31
  readonly removed: number;
32
32
  readonly binary?: boolean;
33
- /** Blob SHAs the diff was computed against; anchors an outdated review comment. */
33
+ /** Blob SHAs of each side; used to anchor outdated review comments. */
34
34
  readonly baseSha?: string;
35
35
  readonly headSha?: string;
36
- /** Changes whenever the file's content does, so a `seen` mark keyed to it clears itself. */
36
+ /** Changes whenever the file's content does. */
37
37
  readonly fingerprint: string;
38
38
  };
39
39
 
@@ -51,14 +51,14 @@ export type FileDiff = {
51
51
  readonly hunks: readonly ToolDiffHunk[];
52
52
  readonly truncated?: boolean;
53
53
  readonly binary?: boolean;
54
- /** Byte size of each side of a binary file, when git or the working tree can say. */
54
+ /** Byte sizes of each side of a binary file, when known. */
55
55
  readonly oldBytes?: number;
56
56
  readonly newBytes?: number;
57
- /** Lines in the side context is read from; absent on a clipped diff, whose end is not the file's. */
57
+ /** Line count of the side `readLines` reads. Absent when the diff was clipped. */
58
58
  readonly total?: number;
59
59
  };
60
60
 
61
- /** A stretch of one file, 1-based and inclusive, numbered on the side `readLines` reads. */
61
+ /** 1-based, inclusive, numbered on the side `readLines` reads. */
62
62
  export type LineSpan = {
63
63
  readonly start: number;
64
64
  readonly end: number;
@@ -78,24 +78,24 @@ const DEFAULT_CONTEXT = 3;
78
78
 
79
79
  const FILE_LIMIT = 2000;
80
80
 
81
- /** How much of one file a reader is handed at once; past either limit the rest is dropped. */
81
+ /** Per-file caps on a diff; the rest is dropped. */
82
82
  const CHANGED_LINE_LIMIT = 2000;
83
83
  const PATCH_TEXT_LIMIT = 1_000_000;
84
84
 
85
- /** Past this an untracked file is reported as binary rather than read. */
85
+ /** Larger untracked files are reported as binary. */
86
86
  const UNTRACKED_BYTE_LIMIT = 1_000_000;
87
87
 
88
- /** Past this a file is diffed but never read whole, so no gap of it can be opened. */
88
+ /** Larger files are diffed but never read whole, so gaps can't be expanded. */
89
89
  const CONTEXT_BYTE_LIMIT = 1_000_000;
90
90
 
91
- /** Most lines one `readLines` hands back, however many spans asked. */
91
+ /** Max lines per `readLines` call, across all spans. */
92
92
  const CONTEXT_LINE_LIMIT = 2000;
93
93
 
94
94
  const EMPTY_SHA = /^0+$/;
95
95
 
96
96
  const BINARY_PATCH = /^(?:Binary files |GIT binary patch)/m;
97
97
 
98
- /** One `git` read; `--no-optional-locks` or it takes `index.lock` and fails an agent's write beside it. */
98
+ /** `--no-optional-locks` keeps reads from taking `index.lock` and failing concurrent writes. */
99
99
  function git(cwd: string, args: readonly string[]): Promise<ProcResult> {
100
100
  return Proc.run(["git", "--no-optional-locks", ...args], { cwd });
101
101
  }
@@ -112,21 +112,13 @@ async function read(
112
112
  return result.stdout;
113
113
  }
114
114
 
115
- /**
116
- * Whether the branch checked out has a commit on it. A repository whose first
117
- * commit is still unwritten has an unborn `HEAD`: it names nothing, and every
118
- * `git diff HEAD` of it fails outright instead of calling the tree new.
119
- */
115
+ /** False for an unborn `HEAD` (no commits yet), where `git diff HEAD` fails. */
120
116
  async function born(cwd: string): Promise<boolean> {
121
117
  const head = await git(cwd, ["rev-parse", "--quiet", "--verify", "HEAD"]);
122
118
  return head.code === 0;
123
119
  }
124
120
 
125
- /**
126
- * The base an unborn `HEAD` is diffed against, so that every file reads as
127
- * added. `hash-object` names git's empty tree without writing it, and names it
128
- * right in a sha256 repository too, where the familiar `4b825dc…` is not it.
129
- */
121
+ /** Base for an unborn `HEAD`. `hash-object` also gets it right in sha256 repos. */
130
122
  async function emptyTree(cwd: string): Promise<string> {
131
123
  const sha = await read(
132
124
  cwd,
@@ -136,7 +128,7 @@ async function emptyTree(cwd: string): Promise<string> {
136
128
  return sha.trim();
137
129
  }
138
130
 
139
- /** What every `git diff` of this base is asked about; `branch` resolves to the merge base first. */
131
+ /** `git diff` args for a base; `branch` diffs against the merge base. */
140
132
  async function baseArgs(
141
133
  cwd: string,
142
134
  base: DiffBase
@@ -151,7 +143,6 @@ async function baseArgs(
151
143
  case "commit":
152
144
  return [base.ref];
153
145
  case "branch": {
154
- // Nothing is shared with a branch when this one has no commits at all.
155
146
  if (!(await born(cwd))) {
156
147
  return [await emptyTree(cwd)];
157
148
  }
@@ -199,7 +190,7 @@ function shaOf(value: string | undefined): string | undefined {
199
190
  : value;
200
191
  }
201
192
 
202
- /** `:<oldmode> <newmode> <oldsha> <newsha> <status>\0<path>\0`, a second path when the status is a rename or copy. */
193
+ /** `:<oldmode> <newmode> <oldsha> <newsha> <status>\0<path>\0`, plus a second path for a rename or copy. */
203
194
  function parseRaw(text: string): readonly Entry[] {
204
195
  const fields = text.split("\0");
205
196
  const entries: Entry[] = [];
@@ -240,7 +231,7 @@ function parseRaw(text: string): readonly Entry[] {
240
231
  return entries;
241
232
  }
242
233
 
243
- /** `<added>\t<removed>\t<path>\0`; a rename leaves the path empty and follows with the old and new ones. */
234
+ /** `<added>\t<removed>\t<path>\0`; a rename has an empty path followed by old and new paths. */
244
235
  function parseNumstat(text: string): ReadonlyMap<string, Counts> {
245
236
  const fields = text.split("\0");
246
237
  const counts = new Map<string, Counts>();
@@ -278,7 +269,7 @@ function parseNumstat(text: string): ReadonlyMap<string, Counts> {
278
269
  return counts;
279
270
  }
280
271
 
281
- /** Only the `?` entries of porcelain v2; a rename entry carries a second field that is a path, not a record. */
272
+ /** The `?` entries of porcelain v2. A rename (`2`) entry is followed by an extra path field. */
282
273
  function parseUntracked(text: string): readonly string[] {
283
274
  const fields = text.split("\0");
284
275
  const paths: string[] = [];
@@ -332,10 +323,7 @@ async function readUntracked(cwd: string, path: string): Promise<Untracked> {
332
323
  return opaque;
333
324
  }
334
325
  const bytes = await file.bytes().catch(() => undefined);
335
- if (bytes === undefined) {
336
- return opaque;
337
- }
338
- if (Lines.isBinaryBytes(bytes)) {
326
+ if (bytes === undefined || Lines.isBinaryBytes(bytes)) {
339
327
  return opaque;
340
328
  }
341
329
  const text = new TextDecoder().decode(bytes);
@@ -446,7 +434,7 @@ type Clip = {
446
434
  readonly truncated: boolean;
447
435
  };
448
436
 
449
- /** The longest prefix of a patch that is still whole hunks, once it is too much text to parse. */
437
+ /** Cuts an oversized patch back to its last whole hunk. */
450
438
  function clipPatch(patch: string): {
451
439
  readonly text: string;
452
440
  readonly cut: boolean;
@@ -462,7 +450,7 @@ function changedOf(lines: readonly ToolDiffLine[]): number {
462
450
  return lines.filter((line) => line.kind !== "context").length;
463
451
  }
464
452
 
465
- /** A hunk cut short still has to describe itself: its spans count the lines left in it. */
453
+ /** Recounts a cut hunk's line spans. */
466
454
  function reflow(
467
455
  hunk: ToolDiffHunk,
468
456
  lines: readonly ToolDiffLine[]
@@ -493,7 +481,7 @@ function headOf(
493
481
  return kept;
494
482
  }
495
483
 
496
- /** Hunks while the changed-line budget lasts, the one that overruns it cut short. */
484
+ /** Keeps hunks within the changed-line budget, cutting the one that overruns it. */
497
485
  function clipHunks(hunks: readonly ToolDiffHunk[]): Clip {
498
486
  let budget = CHANGED_LINE_LIMIT;
499
487
  const kept: ToolDiffHunk[] = [];
@@ -531,11 +519,7 @@ function clipped(
531
519
  };
532
520
  }
533
521
 
534
- /**
535
- * The text of the side a gap is read from: the new one, which is the index
536
- * blob where the base has staged it and the working tree everywhere else. A
537
- * file too big to hold, or gone from the side asked for, has no text at all.
538
- */
522
+ /** The new side: the index blob when staged, else the working tree. Undefined if missing or too big. */
539
523
  async function sideText(
540
524
  cwd: string,
541
525
  path: string,
@@ -578,7 +562,6 @@ async function worktreeSize(
578
562
  return (await file.exists()) ? file.size : undefined;
579
563
  }
580
564
 
581
- /** A binary file is a row, not a diff: all a reader is told is how big each side is. */
582
565
  async function binaryDiff(
583
566
  cwd: string,
584
567
  path: string,
@@ -599,7 +582,7 @@ async function binaryDiff(
599
582
  };
600
583
  }
601
584
 
602
- /** Every changed file of one base, in git's own order and without a hunk of any of them. */
585
+ /** Changed files in git's order, without hunks. */
603
586
  async function listChanges(
604
587
  cwd: string,
605
588
  base: DiffBase,
@@ -629,7 +612,7 @@ async function listChanges(
629
612
  });
630
613
  }
631
614
 
632
- /** One file's hunks; a renamed file is diffed against the path it came from, an untracked one against nothing. */
615
+ /** A rename is diffed against its old path; an untracked file against nothing. */
633
616
  async function fileDiff(
634
617
  cwd: string,
635
618
  base: DiffBase,
@@ -679,7 +662,6 @@ async function fileDiff(
679
662
  });
680
663
  }
681
664
 
682
- /** The lines a reader asked to see of a file they are already reading a diff of, as they are. */
683
665
  async function readLines(
684
666
  cwd: string,
685
667
  base: DiffBase,
@@ -718,11 +700,7 @@ async function readLines(
718
700
  });
719
701
  }
720
702
 
721
- /**
722
- * Reading is serialised against the checkouts and pulls that move the tree
723
- * under it; a read that arrives while one runs is refused rather than answered
724
- * from half a working tree.
725
- */
703
+ /** Refuses to read while a checkout or pull is moving the tree. */
726
704
  async function serialise<T>(
727
705
  monitor: GitMonitor,
728
706
  cwd: string,
@@ -3,9 +3,9 @@ import { Paths } from "./Paths";
3
3
 
4
4
  export const NO_MATCHES = "No matches.";
5
5
 
6
- export type SearchPathFormat = "relative" | "absolute";
6
+ type SearchPathFormat = "relative" | "absolute";
7
7
 
8
- export type SearchPathOptions = {
8
+ type SearchPathOptions = {
9
9
  readonly cwd: string;
10
10
  readonly pathFormat: SearchPathFormat;
11
11
  };
@@ -17,7 +17,7 @@ export type SearchList = {
17
17
  readonly truncated: boolean;
18
18
  };
19
19
 
20
- export type SubjectTitleOptions = {
20
+ type SubjectTitleOptions = {
21
21
  readonly subject: string;
22
22
  readonly path: string | undefined;
23
23
  readonly suffix?: string | undefined;
@@ -75,7 +75,6 @@ function capList(lines: readonly string[], headLimit: number): SearchList {
75
75
  }
76
76
 
77
77
  export const SearchRender = {
78
- NO_MATCHES,
79
78
  formatPath,
80
79
  subjectTitle,
81
80
  capList,
@@ -5,7 +5,7 @@ import { FsErrors } from "./FsErrors";
5
5
  import { Paths } from "./Paths";
6
6
  import { Sweeper } from "./Sweeper";
7
7
 
8
- // UUIDv7-named spills and content-addressed ones, which share the TTL.
8
+ // Matches UUIDv7-named and SHA-256-named spills.
9
9
  const SPILL_FILE_RE =
10
10
  /^[a-z0-9]+-(?:[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|[0-9a-f]{64})\.[a-z0-9]+$/;
11
11
 
@@ -16,7 +16,7 @@ function dir(): string {
16
16
  return join(Paths.pimHomeDir(), "cache");
17
17
  }
18
18
 
19
- /** Writes under a caller-chosen name; an existing file of that name is kept, so content-addressed names re-write for free. */
19
+ /** Keeps an existing file of the same name; returns its path either way. Null on failure. */
20
20
  async function writeNamed(
21
21
  name: string,
22
22
  data: string | Uint8Array
@@ -69,7 +69,6 @@ function installSweeper(): void {
69
69
 
70
70
  export const SpillCache = {
71
71
  TTL_MS,
72
- SWEEP_INTERVAL_MS,
73
72
  dir,
74
73
  write,
75
74
  writeNamed,
@@ -4,15 +4,14 @@ import { dirname, join } from "node:path";
4
4
  import { Paths } from "./Paths";
5
5
  import { Sweeper } from "./Sweeper";
6
6
 
7
- // The parent id names a directory; a call id is opaque provider data, hashed rather than trusted as a segment.
7
+ // Parent ids become directory names; call ids are untrusted, so they are hashed.
8
8
  const ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
9
- // A call id arrives off the wire: bound what gets hashed.
10
9
  const MAX_CALL_ID_LENGTH = 4096;
11
10
 
12
11
  const TTL_MS = 30 * 24 * 60 * 60 * 1000;
13
12
  const SWEEP_INTERVAL_MS = 60 * 60 * 1000;
14
13
 
15
- // Must stay outside pi's sessions root, which `SessionRegistry` globs as the session catalogue.
14
+ // Must stay outside pi's sessions root, which `SessionRegistry` globs.
16
15
  function dir(): string {
17
16
  return join(Paths.pimHomeDir(), "subagents");
18
17
  }
@@ -32,7 +31,7 @@ function pathFor(parentSessionId: string, callId: string): string | null {
32
31
  );
33
32
  }
34
33
 
35
- // Create the log empty with explicit modes: a file pi creates takes the process umask.
34
+ // Created up front with private modes; pi would use the umask.
36
35
  async function create(
37
36
  parentSessionId: string,
38
37
  callId: string
@@ -50,7 +49,7 @@ async function create(
50
49
  }
51
50
  }
52
51
 
53
- // Expire a parent's children together by newest mtime, or a long run loses its earlier subagents.
52
+ // Expires a parent's logs together, by their newest mtime.
54
53
  function cleanup(root = dir(), now = Date.now()): void {
55
54
  let names: string[];
56
55
  try {
@@ -93,7 +92,6 @@ function installSweeper(): void {
93
92
 
94
93
  export const SubagentLogs = {
95
94
  TTL_MS,
96
- SWEEP_INTERVAL_MS,
97
95
  dir,
98
96
  pathFor,
99
97
  create,
@@ -5,29 +5,28 @@ import { basename, dirname, join } from "node:path";
5
5
  import { Fs } from "./Fs";
6
6
  import { Proc } from "./Proc";
7
7
 
8
- // Set by the units this file writes and by nothing else: it tells a daemon an exit is a restart.
8
+ // Set only by the units written here: tells a daemon that exiting means restarting.
9
9
  const SUPERVISED_ENV = "PIM_SUPERVISED";
10
10
 
11
- /** One daemon the supervisor manages, named by the `--mode` it is started with. */
11
+ /** A supervised daemon, named by its `--mode`. */
12
12
  export type Unit = {
13
13
  readonly mode: string;
14
14
  readonly description: string;
15
15
  readonly args?: ReadonlyArray<string>;
16
16
  };
17
17
 
18
- /** One reversible act of an install: everything a unit's removal is made of. */
19
- export type UnitStep =
18
+ type UnitStep =
20
19
  | { readonly kind: "run"; readonly cmd: ReadonlyArray<string> }
21
20
  | { readonly kind: "remove"; readonly path: string };
22
21
 
23
- /** Which init system, and whose home — named so a test can ask about the other platform. */
24
- export type UnitPlace = {
22
+ /** Overridable so tests can target the other platform. */
23
+ type UnitPlace = {
25
24
  readonly platform: NodeJS.Platform;
26
25
  readonly home: string;
27
26
  };
28
27
 
29
- export type InstallOptions = {
30
- /** Units this one replaces: stopped and removed before it is written. */
28
+ type InstallOptions = {
29
+ /** Stopped and removed before the new unit is written. */
31
30
  readonly replaces?: ReadonlyArray<Unit>;
32
31
  };
33
32
 
@@ -44,7 +43,7 @@ async function install(
44
43
  ): Promise<void> {
45
44
  const at = await detectInstall();
46
45
  console.log(`[install] ${at.kind} mode, root=${at.packageRoot}`);
47
- // Strictly before the new unit exists: two daemons must never share a token or a port.
46
+ // First, so two daemons never share a token or port.
48
47
  await supersede(options.replaces ?? []);
49
48
  if (process.platform === "linux") {
50
49
  const path = systemdUnitPath(unit);
@@ -79,7 +78,7 @@ async function install(
79
78
  `gui/${uid}/${launchdLabel(unit)}`,
80
79
  ]);
81
80
  } catch {
82
- // bootout fails when the service isn't loaded; ignore before bootstrap.
81
+ // Fails when not loaded.
83
82
  }
84
83
  await runOrThrow(["launchctl", "bootstrap", `gui/${uid}`, path]);
85
84
  console.log(`[install] bootstrapped ${launchdLabel(unit)}`);
@@ -95,10 +94,7 @@ async function uninstall(unit: Unit): Promise<void> {
95
94
  await runSteps(uninstallSteps(unit), "uninstall");
96
95
  }
97
96
 
98
- /**
99
- * Stop and remove every one of `units` that is installed, saying so. Idempotent:
100
- * a unit that was never installed, or is already stopped, costs a stat and a line.
101
- */
97
+ /** Stops and removes whichever of `units` are installed. Idempotent. */
102
98
  async function supersede(
103
99
  units: ReadonlyArray<Unit>,
104
100
  where: Partial<UnitPlace> = {}
@@ -111,7 +107,7 @@ async function supersede(
111
107
  }
112
108
  }
113
109
 
114
- /** Which of `units` this machine currently has a unit file for. */
110
+ /** The `units` that have a unit file on this machine. */
115
111
  async function installedAmong(
116
112
  units: ReadonlyArray<Unit>,
117
113
  where: Partial<UnitPlace> = {}
@@ -122,10 +118,7 @@ async function installedAmong(
122
118
  return units.filter((_, index) => present[index]);
123
119
  }
124
120
 
125
- /**
126
- * The argv the installed unit starts the daemon with, empty when it is not
127
- * installed: what a re-install has to preserve rather than quietly drop.
128
- */
121
+ /** The installed unit's argv from `--mode` on; empty when not installed. */
129
122
  async function installedArgs(
130
123
  unit: Unit,
131
124
  where: Partial<UnitPlace> = {}
@@ -135,7 +128,6 @@ async function installedArgs(
135
128
  .text()
136
129
  .catch(() => "");
137
130
  const words = unitWords(text, at.platform);
138
- // Everything before `--mode` is the interpreter and the entry point.
139
131
  const mode = words.indexOf("--mode");
140
132
  return mode < 0 ? [] : words.slice(mode);
141
133
  }
@@ -155,7 +147,7 @@ function unitWords(
155
147
  .filter((word) => word.length > 0);
156
148
  }
157
149
 
158
- /** Everything removing `unit` is made of, in the order it has to happen. */
150
+ /** Ordered steps to remove `unit`. */
159
151
  function uninstallSteps(
160
152
  unit: Unit,
161
153
  where: Partial<UnitPlace> = {}
@@ -179,8 +171,7 @@ function uninstallSteps(
179
171
  ];
180
172
  }
181
173
 
182
- // A step that fails is reported, never fatal: an already-stopped unit still has
183
- // to lose its file, and a file already gone still has to trigger a reload.
174
+ // Failed commands only warn, so later steps still run.
184
175
  async function runSteps(
185
176
  steps: ReadonlyArray<UnitStep>,
186
177
  label: string
@@ -208,7 +199,7 @@ async function runSteps(
208
199
  }
209
200
  }
210
201
 
211
- /** Only a supervisor turns an exit into a restart; unsupervised it is a stop. */
202
+ /** Unsupervised, an exit is a stop rather than a restart. */
212
203
  function isSupervised(): boolean {
213
204
  const flag = Bun.env[SUPERVISED_ENV];
214
205
  return flag !== undefined && flag !== "" && flag !== "0";
@@ -218,7 +209,7 @@ function restart(): never {
218
209
  process.exit(0);
219
210
  }
220
211
 
221
- // A global install replaces every daemon's tree: restart the siblings or they run old code.
212
+ // After a global update, other daemons must restart or they keep running old code.
222
213
  async function restartSiblings(self: Unit): Promise<void> {
223
214
  if (process.platform === "linux") {
224
215
  for (const name of await installedUnits(
@@ -277,7 +268,7 @@ async function restartOrWarn(
277
268
 
278
269
  async function detectInstall(): Promise<Install> {
279
270
  const here = await realpath(Bun.fileURLToPath(import.meta.url));
280
- // Start above the workspace packages so the walk lands on the published root.
271
+ // Start above `packages/` so the walk finds the published root.
281
272
  const packageRoot = await findPackageRoot(
282
273
  join(dirname(here), "..", "..", "..", "..")
283
274
  );
@@ -349,7 +340,6 @@ function launchdPlistPath(unit: Unit, at: UnitPlace = place()): string {
349
340
  return join(launchAgentsDir(at), `${launchdLabel(unit)}.plist`);
350
341
  }
351
342
 
352
- /** Where this platform keeps `unit`'s definition, installed or not. */
353
343
  function unitFile(unit: Unit, where: Partial<UnitPlace> = {}): string {
354
344
  const at = place(where);
355
345
  return at.platform === "darwin"
@@ -432,11 +422,8 @@ async function lingerEnabled(): Promise<boolean> {
432
422
  return code === 0 && stdout.includes("Linger=yes");
433
423
  }
434
424
 
435
- async function runOrThrow(
436
- cmd: ReadonlyArray<string>,
437
- cwd?: string
438
- ): Promise<void> {
439
- const { code, stderr } = await Proc.run(cmd, { cwd, stdout: "inherit" });
425
+ async function runOrThrow(cmd: ReadonlyArray<string>): Promise<void> {
426
+ const { code, stderr } = await Proc.run(cmd, { stdout: "inherit" });
440
427
  if (code !== 0) {
441
428
  throw new Error(
442
429
  `${cmd.join(" ")} exit ${code}: ${stderr.trim() || "(no stderr)"}`
@@ -1,2 +1,2 @@
1
- /** Where the human on the other end is reading; absent for a subagent, which has no human. */
1
+ /** Where the user is reading. Absent for a subagent. */
2
2
  export type Surface = "terminal" | "web browser" | "Telegram";
@@ -18,7 +18,7 @@ function install(options: {
18
18
  cleanup();
19
19
  });
20
20
 
21
- // Signals skip the "exit" handler; re-raise after the once-handler, or the default exit is suppressed.
21
+ // Signals skip "exit": clean up, then re-raise so the process still dies.
22
22
  for (const sig of ["SIGTERM", "SIGINT", "SIGHUP"] as const) {
23
23
  process.once(sig, () => {
24
24
  try {