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
@@ -10,7 +10,6 @@ import { Json } from "../shared/Json";
10
10
 
11
11
  export type LeaseFrontend = "tui" | "daemon";
12
12
 
13
- /** What one holder wrote into `<sessionPath>.lease`. */
14
13
  export type LeaseRecord = {
15
14
  readonly pid: number;
16
15
  readonly hostname: string;
@@ -24,14 +23,14 @@ export type LeaseHandle = {
24
23
 
25
24
  export type AcquireResult =
26
25
  | { readonly ok: true; readonly handle: LeaseHandle }
27
- /** Absent when the holder's file is torn or vanished mid-read. */
26
+ /** Absent when the lease file is torn or vanished mid-read. */
28
27
  | { readonly ok: false; readonly holder?: LeaseRecord };
29
28
 
30
29
  export type LeaseOptions = {
31
30
  readonly heartbeatMs?: number;
32
31
  readonly pollMs?: number;
33
32
  readonly timeoutMs?: number;
34
- /** Called with the current holder each time an acquire is denied and another poll follows. */
33
+ /** Called on each denied attempt that will be retried. */
35
34
  readonly onBlocked?: (holder: LeaseRecord | undefined) => void;
36
35
  };
37
36
 
@@ -73,7 +72,7 @@ async function recordAt(path: string): Promise<LeaseRecord | undefined> {
73
72
  return toRecord(await Fs.readJsonOr<unknown>(path, undefined));
74
73
  }
75
74
 
76
- /** The current holder, or undefined when the file is absent, torn, or half-written. */
75
+ /** Undefined when the file is absent or unparseable. */
77
76
  async function read(sessionPath: string): Promise<LeaseRecord | undefined> {
78
77
  return await recordAt(pathFor(sessionPath));
79
78
  }
@@ -83,12 +82,12 @@ function isAlive(pid: number): boolean {
83
82
  process.kill(pid, 0);
84
83
  return true;
85
84
  } catch (err) {
86
- // EPERM is someone else's live process.
85
+ // EPERM means the process exists but belongs to another user.
87
86
  return FsErrors.code(err) !== "ESRCH";
88
87
  }
89
88
  }
90
89
 
91
- /** A holder is stale once its pid is gone, or once it stops heartbeating; never across hosts. */
90
+ /** Stale when its pid is gone or it stopped heartbeating. Never stale across hosts. */
92
91
  function isStale(
93
92
  record: LeaseRecord,
94
93
  mtimeMs: number,
@@ -100,7 +99,6 @@ function isStale(
100
99
  return !isAlive(record.pid) || now - mtimeMs > STALE_MS;
101
100
  }
102
101
 
103
- /** Whether this very process wrote that record — the one holder allowed to release it. */
104
102
  function isOurs(record: LeaseRecord | undefined): boolean {
105
103
  return record?.pid === process.pid && record.hostname === HOST;
106
104
  }
@@ -116,7 +114,7 @@ async function stealable(
116
114
  if (mtimeMs === undefined) {
117
115
  return true;
118
116
  }
119
- // A torn file is a holder mid-write until it stops being refreshed.
117
+ // A torn file may be mid-write; only steal it once its heartbeat stops.
120
118
  return record === undefined
121
119
  ? Date.now() - mtimeMs > STALE_MS
122
120
  : isStale(record, mtimeMs);
@@ -136,7 +134,7 @@ async function claim(
136
134
  if (FsErrors.code(err) === "EEXIST") {
137
135
  return undefined;
138
136
  }
139
- // The session's directory is pi's to create, and a lease can precede the file it guards.
137
+ // The lease can be taken before pi creates the session directory.
140
138
  if (FsErrors.code(err) === "ENOENT") {
141
139
  return mkdir(dirname(path), { recursive: true }).then(() =>
142
140
  open(path, "wx")
@@ -174,7 +172,7 @@ function hookExit(): void {
174
172
  function handleFor(path: string, options: LeaseOptions): LeaseHandle {
175
173
  held.add(path);
176
174
  hookExit();
177
- // Bump mtime rather than rewrite: a rename would clobber whoever holds the file next.
175
+ // Touch mtime only; rewriting could clobber the next holder's file.
178
176
  const beat = setInterval(() => {
179
177
  const now = new Date();
180
178
  void utimes(path, now, now).catch(() => undefined);
@@ -197,7 +195,7 @@ function handleFor(path: string, options: LeaseOptions): LeaseHandle {
197
195
  };
198
196
  }
199
197
 
200
- /** Create-exclusive, stealing only a lease whose holder is provably gone. */
198
+ /** Create-exclusive; steals only a stale lease. */
201
199
  async function acquire(
202
200
  sessionPath: string,
203
201
  frontend: LeaseFrontend,
@@ -217,7 +215,7 @@ async function acquire(
217
215
  }
218
216
  }
219
217
 
220
- /** Polls until the lease is free, the deadline passes, or the holder is stealable. */
218
+ /** Polls `acquire` until it succeeds or the timeout passes. */
221
219
  async function waitFor(
222
220
  sessionPath: string,
223
221
  frontend: LeaseFrontend,
@@ -243,7 +241,7 @@ function denial(result: { readonly holder?: LeaseRecord }): string {
243
241
  return `Session is busy: ${who} still holds its turn lease.`;
244
242
  }
245
243
 
246
- /** The only safe way to take a lease: waits for it, and always gives it back. */
244
+ /** Runs `work` under the lease, always releasing it. Throws if it cannot be taken. */
247
245
  async function hold<T>(
248
246
  sessionPath: string,
249
247
  frontend: LeaseFrontend,
@@ -261,12 +259,11 @@ async function hold<T>(
261
259
  }
262
260
  }
263
261
 
264
- /** Fires whenever the lease appears, changes hands, or is released. */
265
262
  function watch(sessionPath: string, onChange: () => void): () => void {
266
263
  return FileWatch.file(pathFor(sessionPath), onChange);
267
264
  }
268
265
 
269
- /** A turn lease over one session file, held as a sibling `<sessionPath>.lease`. */
266
+ /** A turn lease over one session file, stored at `<sessionPath>.lease`. */
270
267
  export const SessionLease = {
271
268
  pathFor,
272
269
  read,
@@ -6,23 +6,22 @@ import { Paths } from "../shared/Paths";
6
6
 
7
7
  export type SessionEntry = {
8
8
  readonly archived?: boolean;
9
- /** Sticky: set by hand, and only a read clears it. */
9
+ /** Set by hand; only a read clears it. */
10
10
  readonly unread?: boolean;
11
11
  };
12
12
 
13
13
  export type ProjectEntry = {
14
14
  readonly pinned?: boolean;
15
- /** The sidebar group stands unfolded; absent is folded, which is where a project starts. */
15
+ /** Absent means folded. */
16
16
  readonly expanded?: boolean;
17
- /** What to call the directory instead of its base name; the directory itself is never touched. */
17
+ /** Display name instead of the directory's base name. */
18
18
  readonly label?: string;
19
19
  };
20
20
 
21
- /** The pin flags and the order they are shown in, from one read of the file. */
22
21
  export type Pinning = {
23
22
  /** Keyed by absolute cwd. */
24
23
  readonly projects: ReadonlyMap<string, ProjectEntry>;
25
- /** The pinned directories, in the order they are shown. */
24
+ /** Pinned cwds in display order. */
26
25
  readonly order: readonly string[];
27
26
  };
28
27
 
@@ -30,13 +29,7 @@ type Stored = {
30
29
  readonly version: 1;
31
30
  readonly sessions: Record<string, SessionEntry>;
32
31
  readonly projects: Record<string, ProjectEntry>;
33
- /**
34
- * Where the pinned directories sort, and only that: `projects` stays the
35
- * truth of whether one is pinned. An entry here that is not pinned is
36
- * ignored and a pin it has never heard of still sorts, so a file written by
37
- * a pim that predates the order — or by one that does not write it — needs
38
- * no migration.
39
- */
32
+ /** Sort order only; `projects` decides what is pinned. */
40
33
  readonly pins: readonly string[];
41
34
  };
42
35
 
@@ -48,7 +41,7 @@ type Loaded = {
48
41
 
49
42
  const NONE: SessionEntry = {};
50
43
 
51
- /** Per-session and per-project overrides, shared by every surface on a machine. */
44
+ /** Per-session and per-project UI state, shared by every surface on the machine. */
52
45
  export class SessionMeta {
53
46
  private readonly file: string;
54
47
  private readonly writes = Fs.serialised();
@@ -62,18 +55,17 @@ export class SessionMeta {
62
55
  return (await this.sessions()).get(sessionId) ?? NONE;
63
56
  }
64
57
 
65
- /** One read for a whole listing; `of` per row is one read per row. */
58
+ /** One file read for the whole listing. */
66
59
  public async sessions(): Promise<ReadonlyMap<string, SessionEntry>> {
67
60
  return (await this.read()).sessions;
68
61
  }
69
62
 
70
- /** The pinned directories in display order; a listing wants both halves, and this is one read for them. */
71
63
  public async pinning(): Promise<Pinning> {
72
64
  const loaded = await this.read();
73
65
  return { projects: loaded.projects, order: ordered(loaded) };
74
66
  }
75
67
 
76
- /** The pinned directories in display order. */
68
+ /** Pinned cwds in display order. */
77
69
  public async pins(): Promise<readonly string[]> {
78
70
  return ordered(await this.read());
79
71
  }
@@ -88,7 +80,7 @@ export class SessionMeta {
88
80
  return this.mutate((loaded) => put(loaded.sessions, sessionId, { unread }));
89
81
  }
90
82
 
91
- /** A new pin goes to the top, where you have just put it; an old one leaves the order with the flag. */
83
+ /** A new pin goes to the top. */
92
84
  public setPinned(cwd: string, pinned: boolean): Promise<void> {
93
85
  return this.mutate((loaded) => {
94
86
  const at = loaded.pins.indexOf(cwd);
@@ -102,22 +94,18 @@ export class SessionMeta {
102
94
  });
103
95
  }
104
96
 
105
- /**
106
- * Folds a project's group, or unfolds it. Kept beside the pin rather than
107
- * in the browser, so the fold a phone made is the fold a desktop opens to.
108
- */
109
97
  public setExpanded(cwd: string, expanded: boolean): Promise<void> {
110
98
  return this.mutate((loaded) => put(loaded.projects, cwd, { expanded }));
111
99
  }
112
100
 
113
- /** Names the project for the sidebar; `null` puts it back to its base name. */
101
+ /** `null` restores the base name. */
114
102
  public setLabel(cwd: string, label: string | null): Promise<void> {
115
103
  return this.mutate((loaded) =>
116
104
  put(loaded.projects, cwd, { label: label ?? "" })
117
105
  );
118
106
  }
119
107
 
120
- /** Takes the whole order rather than a move, so two surfaces settle on the last one written. */
108
+ /** Replaces the whole order; unpinned and duplicate cwds are dropped. */
121
109
  public setPinOrder(order: readonly string[]): Promise<void> {
122
110
  return this.mutate((loaded) => {
123
111
  loaded.pins = [...new Set(order)].filter(
@@ -127,7 +115,7 @@ export class SessionMeta {
127
115
  });
128
116
  }
129
117
 
130
- /** Drops the sessions that are gone; a pin outlives every session of its project. */
118
+ /** Drops entries for sessions not in `alive`. Projects are kept. */
131
119
  public prune(alive: ReadonlySet<string>): Promise<void> {
132
120
  return this.mutate((loaded) => {
133
121
  let dropped = false;
@@ -141,7 +129,7 @@ export class SessionMeta {
141
129
  });
142
130
  }
143
131
 
144
- /** Settles the writes taken so far, for a clean stop. */
132
+ /** Waits for pending writes. */
145
133
  public async flush(): Promise<void> {
146
134
  await this.writes.run(async () => undefined);
147
135
  }
@@ -162,7 +150,7 @@ export class SessionMeta {
162
150
  };
163
151
  }
164
152
 
165
- /** Re-reads under the lock, so a write by another process survives this one. */
153
+ /** Re-reads under the lock so another process's write is not lost. */
166
154
  private async mutate(update: (loaded: Loaded) => boolean): Promise<void> {
167
155
  await this.writes.run(async () => {
168
156
  const loaded = await this.read();
@@ -180,11 +168,7 @@ export class SessionMeta {
180
168
  }
181
169
  }
182
170
 
183
- /**
184
- * The pinned directories in display order: the ones the stored order names,
185
- * then any pin it has not heard of, by path. A duplicate in the order is
186
- * taken once, at the first place it appears.
187
- */
171
+ /** Stored order first, then pins missing from it sorted by path. */
188
172
  function ordered({ projects, pins }: Loaded): readonly string[] {
189
173
  const unplaced = new Set(
190
174
  [...projects]
@@ -209,7 +193,7 @@ function put<T extends object>(
209
193
  return true;
210
194
  }
211
195
 
212
- /** Every field is opt-in, so a false flag or an empty name is the same as an absent one. */
196
+ /** Drops `false` and `""` fields; they mean the same as absent. */
213
197
  function onlySet<T extends object>(entry: T): T {
214
198
  return Object.fromEntries(
215
199
  Object.entries(entry).filter(
@@ -1,18 +1,14 @@
1
- /**
2
- * Twice the width a sidebar row can show, so a name is never silently cut at the
3
- * length it happens to render at, and a pasted essay still cannot become one.
4
- */
1
+ /** In code points. */
5
2
  const LIMIT = 80;
6
3
 
7
- /** What pi should store for this name: whitespace collapsed, controls gone, `""` to clear. */
4
+ /** Collapses whitespace and strips control characters; `""` clears the name. */
8
5
  function normalise(name: string | null | undefined): string {
9
6
  const clean = (name ?? "")
10
7
  .replace(/\p{Cc}/gu, " ")
11
8
  .replace(/\s+/gu, " ")
12
9
  .trim();
13
- // By code point: a cap that splits a surrogate pair stores half a character.
10
+ // Slice by code point so a surrogate pair is never split.
14
11
  return [...clean].slice(0, LIMIT).join("").trim();
15
12
  }
16
13
 
17
- /** The one spelling of a session name pim writes into pi's `session_info`. */
18
14
  export const SessionName = { normalise };
@@ -20,7 +20,6 @@ import { SessionLease } from "./SessionLease";
20
20
  import { SessionName } from "./SessionName";
21
21
  import type { SessionUi } from "./SessionUi";
22
22
 
23
- /** A session as pi stores it: one JSONL file under a cwd-encoded directory. */
24
23
  export type SessionSummary = {
25
24
  readonly sessionId: string;
26
25
  readonly cwd: string;
@@ -31,9 +30,9 @@ export type SessionSummary = {
31
30
 
32
31
  export type SessionRegistryDeps = {
33
32
  readonly defaults: { readonly cwd: string; readonly model?: string };
34
- /** The process-wide pi installation; one is built here when a caller has none to share. */
33
+ /** Defaults to a new runtime over `agentDir`. */
35
34
  readonly runtime?: AgentRuntime;
36
- /** Where auth, models, settings and sessions live; must agree with pi's own `getAgentDir()`. */
35
+ /** Must match pi's `getAgentDir()`. */
37
36
  readonly agentDir?: string;
38
37
  readonly capacity?: number;
39
38
  readonly customTools?: (
@@ -41,20 +40,19 @@ export type SessionRegistryDeps = {
41
40
  ) => readonly ToolDefinition[];
42
41
  /** Appended to every session's system prompt. */
43
42
  readonly systemInstruction?: () => Promise<string | undefined>;
44
- /** Where this frontend's human is reading. */
45
43
  readonly surface?: Surface;
46
44
  };
47
45
 
48
46
  export type SessionCreateOptions = {
49
47
  readonly cwd?: string;
50
- /** Open the new session like this one: model, chosen thinking level, and cwd when none is given. */
48
+ /** Copies model, thinking level and (if `cwd` is unset) cwd from this host. */
51
49
  readonly like?: SessionHost;
52
50
  };
53
51
 
54
- /** A session tree is thousands of files and each header is one open; fanning out over all of them at once is how a listing runs the process out of descriptors. */
52
+ /** Concurrent header reads, to avoid running out of file descriptors. */
55
53
  const HEADER_READS = 32;
56
54
 
57
- /** Live sessions keyed on pi's session UUID; the catalogue is pi's sessions directory, read on demand. */
55
+ /** Live sessions keyed by pi's session id, plus listing of pi's sessions directory. */
58
56
  export class SessionRegistry {
59
57
  private readonly deps: SessionRegistryDeps;
60
58
  private readonly runtime: AgentRuntime;
@@ -68,10 +66,8 @@ export class SessionRegistry {
68
66
  }
69
67
 
70
68
  /**
71
- * Where the extensions of every host built from here speak. It belongs to the
72
- * registry rather than each caller because `create` binds an agent eagerly,
73
- * and pi freezes a session's UI mode at that bind. Resolved per call: a
74
- * host outlives the stream that speaks for it.
69
+ * UI sink for hosts built after this call. Lives here because `create` binds
70
+ * the agent eagerly and pi fixes the UI at bind time.
75
71
  */
76
72
  public setUi(ui: (host: SessionHost) => SessionUi | undefined): void {
77
73
  this.ui = ui;
@@ -89,7 +85,7 @@ export class SessionRegistry {
89
85
  await this.runtime.init();
90
86
  }
91
87
 
92
- /** Sessions on disk, newest first; reads only each file's header line. */
88
+ /** Newest first; reads only each file's header. */
93
89
  public async list(cwd?: string): Promise<readonly SessionSummary[]> {
94
90
  const summaries = (
95
91
  await Pool.mapPooled(
@@ -104,15 +100,13 @@ export class SessionRegistry {
104
100
  return summaries.sort((a, b) => b.modifiedAt - a.modifiedAt);
105
101
  }
106
102
 
107
- /** The live host for `sessionId`, if one is currently loaded. */
108
103
  public peek(sessionId: string): SessionHost | undefined {
109
104
  return this.hosts.peek(sessionId);
110
105
  }
111
106
 
112
107
  /**
113
- * Rename a session through pi's own session name, so its `/resume` picker shows
114
- * it too; `null` clears it. A live session is renamed by its agent, a closed one
115
- * by appending to its file under the turn lease. Answers with the name pi kept.
108
+ * Sets pi's session name; `null` clears it. A closed session's file is
109
+ * appended to under the turn lease. Returns the stored name.
116
110
  */
117
111
  public async setName(
118
112
  sessionId: string,
@@ -127,8 +121,7 @@ export class SessionRegistry {
127
121
  throw new Error(`unknown session: ${sessionId}`);
128
122
  }
129
123
  const next = SessionName.normalise(name);
130
- // Reopening is a plain read today, but a pi that migrates the file rewrites it.
131
- // The lease is only ever held for a whole turn, so a rename refuses rather than queues.
124
+ // Fails fast instead of waiting out a whole turn.
132
125
  return await SessionLease.hold(
133
126
  summary.path,
134
127
  "daemon",
@@ -141,7 +134,6 @@ export class SessionRegistry {
141
134
  );
142
135
  }
143
136
 
144
- /** Every model this machine has credentials for, qualified as `SessionHost.setModel` takes them. */
145
137
  public models(): readonly ModelChoice[] {
146
138
  return this.runtime.models();
147
139
  }
@@ -164,7 +156,7 @@ export class SessionRegistry {
164
156
  );
165
157
  }
166
158
 
167
- /** Start a new session; the agent is built eagerly because pi assigns the UUID and file. */
159
+ /** Builds the agent eagerly: pi assigns the session id. */
168
160
  public async create(
169
161
  options: SessionCreateOptions = {}
170
162
  ): Promise<SessionHost> {
@@ -189,11 +181,7 @@ export class SessionRegistry {
189
181
  await this.hosts.disposeAll();
190
182
  }
191
183
 
192
- /**
193
- * One session by id. Pi names a file for the id it carries, so the usual
194
- * answer is one glob and one header; resolving it by listing would read the
195
- * header of every session on disk to throw all but one away.
196
- */
184
+ /** Tries files named for the id first, then falls back to a full listing. */
197
185
  private async find(sessionId: string): Promise<SessionSummary | undefined> {
198
186
  for (const path of await this.paths(`*/*${sessionId}.jsonl`)) {
199
187
  const summary = await readSummary(path);
@@ -201,7 +189,6 @@ export class SessionRegistry {
201
189
  return summary;
202
190
  }
203
191
  }
204
- // A file named something else entirely: the id is the header's, not the name's.
205
192
  return (await this.list()).find(
206
193
  (summary) => summary.sessionId === sessionId
207
194
  );
@@ -224,8 +211,6 @@ export class SessionRegistry {
224
211
 
225
212
  private buildHost(label: string, settings: HostSettings): SessionHost {
226
213
  const ui = this.ui;
227
- // Named so the sink can reach back for the host it belongs to; the closure
228
- // only ever runs once construction has returned.
229
214
  const host: SessionHost = new SessionHost({
230
215
  label: `session ${label}`,
231
216
  settings,
@@ -235,7 +220,6 @@ export class SessionRegistry {
235
220
  modelRegistry: this.runtime.modelRegistry,
236
221
  settingsManagerFor: (cwd) => this.runtime.settingsManagerFor(cwd),
237
222
  persistSettings: async () => {},
238
- // The terminal can hold the same file open, so every mutation goes through the turn lease.
239
223
  lease: "daemon",
240
224
  customTools: this.deps.customTools,
241
225
  ...(this.deps.systemInstruction === undefined
@@ -5,13 +5,13 @@ import type {
5
5
 
6
6
  import type { NoticeSeverity } from "../view/ViewBlock";
7
7
 
8
- /** The slice of pi's dialog options a surface without a terminal can honour; the rest is countdown chrome. */
8
+ /** The subset of pi's dialog options a non-terminal surface honours. */
9
9
  export type UiAsk = {
10
10
  readonly timeout?: number;
11
11
  readonly signal?: AbortSignal;
12
12
  };
13
13
 
14
- /** Where an extension's own words go. Four of pi's thirty methods: the ones that address a human rather than a terminal. */
14
+ /** The parts of pi's `ExtensionUIContext` a non-terminal surface implements. */
15
15
  export type SessionUi = {
16
16
  readonly notify: (text: string, severity: NoticeSeverity) => void;
17
17
  readonly select: (
@@ -31,15 +31,11 @@ export type SessionUi = {
31
31
  ) => Promise<string | undefined>;
32
32
  };
33
33
 
34
- /** Everything off the terminal paints with; also what pi's border getters hand back. */
35
34
  const IDENTITY = (text: string): string => text;
36
35
 
37
- /**
38
- * pi keeps its own `theme` instance to itself, and nothing off the terminal has
39
- * colours to paint with. `satisfies` covers the whole public surface — `keyof`
40
- * skips the private fields the cast is for — so a method pi adds is a type
41
- * error here rather than a throw inside somebody's event handler.
42
- */
36
+ const DEFAULT_COLOR = { kind: "indexed", index: 7 } as const;
37
+
38
+ /** `satisfies` checks every public member, so a method pi adds is a type error here. */
43
39
  const PLAIN_THEME = {
44
40
  fg: (_color: string, text: string) => text,
45
41
  bg: (_color: string, text: string) => text,
@@ -53,6 +49,9 @@ const PLAIN_THEME = {
53
49
  getColorMode: () => "truecolor",
54
50
  getThinkingBorderColor: () => IDENTITY,
55
51
  getBashModeBorderColor: () => IDENTITY,
52
+ appearance: "dark",
53
+ colors: new Proxy({}, { get: () => DEFAULT_COLOR }) as Theme["colors"],
54
+ style: IDENTITY,
56
55
  } satisfies { [K in keyof Theme]: Theme[K] } as unknown as Theme;
57
56
 
58
57
  function severityOf(
@@ -61,7 +60,7 @@ function severityOf(
61
60
  return kind === "warning" ? "warn" : (kind ?? "info");
62
61
  }
63
62
 
64
- /** A dialog an extension awaits goes unanswered rather than ever throwing at it. */
63
+ /** A failing sink answers `undefined` instead of throwing. */
65
64
  async function settle<T>(
66
65
  ask: () => Promise<T> | undefined
67
66
  ): Promise<T | undefined> {
@@ -74,13 +73,10 @@ async function settle<T>(
74
73
  }
75
74
 
76
75
  /**
77
- * Widens the sink onto pi's `ExtensionUIContext`, no-opping everything a
78
- * terminal owns exactly as pi's own RPC mode does. `sink` is read per call, so
79
- * an agent rebuilt under a host keeps whatever its host was last handed.
76
+ * Adapts a sink to pi's `ExtensionUIContext`; terminal-only methods are no-ops,
77
+ * as in pi's RPC mode. `sink` is read per call.
80
78
  *
81
- * Every method has to be an *own* property: pi re-wraps what it is given with
82
- * `{ ...ui }` (`runner.js:274`), which copies own enumerable keys only. A class
83
- * instance would arrive with `notify` and the rest of the prototype missing.
79
+ * Must be a plain object: pi copies it with `{ ...ui }`, which drops prototype methods.
84
80
  */
85
81
  export function adaptSessionUi(
86
82
  sink: () => SessionUi | undefined
@@ -1,32 +1,26 @@
1
1
  import type { EventLog } from "./EventLog";
2
2
 
3
- /** How much of a session file one process can account for: durable lines, and pi's own entries. */
3
+ /** Lines in a session file (`head`) and entries pi holds in memory (`entries`). */
4
4
  export type WriteMark = {
5
5
  readonly head: number;
6
6
  readonly entries: number;
7
7
  };
8
8
 
9
- /** Pi's in-memory entry list: an `AgentSession`'s `sessionManager`, or one held directly. */
10
9
  type EntrySource = {
11
10
  getEntries(): readonly unknown[];
12
11
  };
13
12
 
14
- /** Nothing accounted for yet, which `foreignSince` reads as "the file is pi's to write". */
15
13
  const UNREAD: WriteMark = { head: 0, entries: 0 };
16
14
 
17
- /** Head first: an append between the two reads must under-count the file, never over. */
15
+ /** Reads head first so a concurrent append under-counts the file, never over-counts. */
18
16
  async function of(log: EventLog, source: EntrySource): Promise<WriteMark> {
19
17
  return { head: await log.head(), entries: source.getEntries().length };
20
18
  }
21
19
 
22
20
  /**
23
- * Whether the file gained lines beyond the ones pi appended from memory. A turn, a
24
- * model change, a compaction, a `/name` and an idle `!bash` all move both counts
25
- * together, so only a writer that is not this process makes the difference positive.
26
- *
27
- * pi names a session file before it writes one, buffering entries until the first
28
- * assistant reply, so a mark taken before the file exists is answered by the whole of
29
- * it: header plus every entry pi was holding.
21
+ * Whether another process appended lines since `mark`. Our own writes move both
22
+ * counts together. A mark taken before pi created the file (`head` 0) counts
23
+ * the header plus every buffered entry as ours.
30
24
  */
31
25
  function foreignSince(mark: WriteMark, next: WriteMark): boolean {
32
26
  const base = mark.head === 0 ? { head: 1, entries: 0 } : mark;
@@ -34,10 +28,8 @@ function foreignSince(mark: WriteMark, next: WriteMark): boolean {
34
28
  }
35
29
 
36
30
  /**
37
- * Whether every line the file gained since `mark` is one no reader has to replay.
38
- * A rename appends `session_info` and moves no history, so a surface that absorbs
39
- * it stays on the session it is already holding. Only ask between turns: a window
40
- * that also holds our own appends is not benign, and a running turn's is.
31
+ * Whether every line added since `mark` is a `session_info` (a rename), so no
32
+ * replay is needed. Only meaningful between turns.
41
33
  */
42
34
  async function benignSince(log: EventLog, mark: WriteMark): Promise<boolean> {
43
35
  const added = await log.read(mark.head);
@@ -47,5 +39,4 @@ async function benignSince(log: EventLog, mark: WriteMark): Promise<boolean> {
47
39
  );
48
40
  }
49
41
 
50
- /** Write accounting over one session file: whose lines are these? */
51
42
  export const WriteMark = { UNREAD, of, foreignSince, benignSince };
@@ -1,4 +1,4 @@
1
- // Never throw on an unknown flag or positional: the same argv reaches every mode.
1
+ // Ignores unknown flags and positionals: the same argv reaches every mode.
2
2
  function scan(
3
3
  args: ReadonlyArray<string>,
4
4
  visit: (key: string, take: () => string | undefined) => void
@@ -1,12 +1,11 @@
1
1
  import type { Unit } from "./Supervisor";
2
2
 
3
- /** The single unit every pim surface runs inside; `--surfaces` picks which of them come up. */
4
3
  export const DaemonUnit = {
5
4
  mode: "daemon",
6
5
  description: "Pim daemon",
7
6
  } satisfies Unit;
8
7
 
9
- /** One unit per surface, which is how pim shipped until the surfaces shared a process. */
8
+ /** Legacy per-surface units, removed on install. */
10
9
  export const SupersededUnits: ReadonlyArray<Unit> = [
11
10
  { mode: "web", description: "Pim web daemon" },
12
11
  { mode: "telegram", description: "Pim Telegram daemon" },