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
@@ -1,6 +1,5 @@
1
- /** One indexable word and where it sits in the string it came from. */
2
1
  export type SearchToken = {
3
- /** Lowercased: the corpus itself is never lowered, only its tokens. */
2
+ /** Lowercased. */
4
3
  readonly text: string;
5
4
  readonly start: number;
6
5
  readonly end: number;
@@ -33,10 +32,8 @@ function scan(text: string): readonly SearchToken[] {
33
32
  }
34
33
 
35
34
  /**
36
- * The words a query asks for: its pieces alone, never the identifier they
37
- * spell. `SessionLease` asks for `session` and `lease`, which the index holds
38
- * for `SessionLease` and for `session lease` alike; asking for `sessionlease`
39
- * too would AND away the second.
35
+ * Query pieces only, never the whole identifier: `SessionLease` asks for
36
+ * `session` and `lease`, so it also matches "session lease".
40
37
  */
41
38
  function words(query: string): readonly string[] {
42
39
  const found: string[] = [];
@@ -51,7 +48,7 @@ function words(query: string): readonly string[] {
51
48
  return found;
52
49
  }
53
50
 
54
- /** Half-open slices of one run: `WsGateway` is `ws` and `gateway`, `read_file` is `read` and `file`. */
51
+ /** Half-open slices: `WsGateway` → `ws`, `gateway`; `read_file` → `read`, `file`. */
55
52
  function piecesOf(run: string): readonly (readonly [number, number])[] {
56
53
  const pieces: (readonly [number, number])[] = [];
57
54
  let start = -1;
@@ -1,4 +1,3 @@
1
- /** What a cache entry has to offer: a recency stamp and a way to let go. */
2
1
  export type CachedSession = {
3
2
  lastUsed: number;
4
3
  dispose(): Promise<void>;
@@ -6,7 +5,7 @@ export type CachedSession = {
6
5
 
7
6
  const CAPACITY = 16;
8
7
 
9
- /** Live sessions, keyed however the frontend keys them, capped by least-recently-used. */
8
+ /** LRU cache of live sessions; evicted entries are disposed. */
10
9
  export class SessionCache<T extends CachedSession> {
11
10
  private readonly capacity: number;
12
11
  private readonly entries = new Map<string, T>();
@@ -19,12 +18,11 @@ export class SessionCache<T extends CachedSession> {
19
18
  return this.entries.size;
20
19
  }
21
20
 
22
- /** The live entry, if there is one, without counting as a use. */
21
+ /** Does not count as a use. */
23
22
  public peek(key: string): T | undefined {
24
23
  return this.entries.get(key);
25
24
  }
26
25
 
27
- /** The live entry, marked used now so eviction passes over it. */
28
26
  public touch(key: string): T | undefined {
29
27
  const entry = this.entries.get(key);
30
28
  if (entry) {
@@ -33,7 +31,6 @@ export class SessionCache<T extends CachedSession> {
33
31
  return entry;
34
32
  }
35
33
 
36
- /** Store `value`, disposing the least recently used entry first when full. */
37
34
  public adopt(key: string, value: T): T {
38
35
  this.evictIfNeeded();
39
36
  this.entries.set(key, value);
@@ -63,6 +60,11 @@ export class SessionCache<T extends CachedSession> {
63
60
  }
64
61
  const evicted = this.entries.get(oldestKey)!;
65
62
  this.entries.delete(oldestKey);
66
- void evicted.dispose();
63
+ evicted.dispose().catch((err: unknown) => {
64
+ console.warn(
65
+ `[pim] failed to dispose evicted session ${oldestKey}:`,
66
+ err
67
+ );
68
+ });
67
69
  }
68
70
  }
@@ -3,35 +3,27 @@ import { parseSessionEntries } from "@earendil-works/pi-coding-agent";
3
3
  import { Attachments } from "../attachments/Attachments";
4
4
  import { MessageText } from "./MessageText";
5
5
 
6
- /** What the session catalogue shows for one file without opening a session. */
6
+ /** Catalogue summary of a session file. */
7
7
  export type SessionDigest = {
8
- /** The session's name if it has one, else its first user message; absent when it has neither. */
8
+ /** The session name, else the first user message. */
9
9
  readonly title?: string;
10
- /** True when `title` is a name somebody wrote rather than the opening message. */
10
+ /** Set when `title` is a session name. */
11
11
  readonly named?: true;
12
- /** When the agent last wrote; it moves with an in-flight turn, so read it before starting one. */
12
+ /** When the agent last wrote. Moves during a turn, so read it before starting one. */
13
13
  readonly settledAt?: number;
14
14
  };
15
15
 
16
- /**
17
- * The digest before it is clamped, so a reader that tails an appended region
18
- * can fold that region into what an earlier read of the same file found.
19
- */
16
+ /** The unclamped digest, so a tail read can be merged into an earlier one. */
20
17
  export type DigestParts = {
21
18
  readonly name?: string;
22
- /** The opening ask, unclamped. */
23
19
  readonly opening?: string;
24
20
  readonly settledAt?: number;
25
21
  };
26
22
 
27
- /**
28
- * A session file's durable bytes, undecoded: a whole session is megabytes of
29
- * tool output and the digest wants a handful of lines of it, so the search
30
- * runs over the bytes and only the lines it keeps become strings.
31
- */
23
+ /** A session file's bytes, kept undecoded so only the lines used become strings. */
32
24
  export type Durable = {
33
25
  readonly bytes: Buffer;
34
- /** Past the last newline; a trailing fragment is a write in progress and is not a line. */
26
+ /** Just past the last newline; a trailing partial line is excluded. */
35
27
  readonly end: number;
36
28
  };
37
29
 
@@ -41,7 +33,7 @@ const TAIL_LINES = 10;
41
33
 
42
34
  const TITLE_LIMIT = 120;
43
35
 
44
- /** Cheap reject before decoding a line: pi writes the discriminant verbatim. */
36
+ /** Searched in raw bytes before decoding a line. */
45
37
  const NAMED = Buffer.from('"session_info"');
46
38
 
47
39
  export const NEWLINE = 0x0a;
@@ -60,7 +52,7 @@ function partsOf(body: Durable): DigestParts {
60
52
  };
61
53
  }
62
54
 
63
- /** An append only adds, so the opening ask stands and a later name or agent line wins. */
55
+ /** Keeps the earlier opening; a later name or settle time wins. */
64
56
  function merge(before: DigestParts, appended: DigestParts): DigestParts {
65
57
  return {
66
58
  name: appended.name ?? before.name,
@@ -78,7 +70,7 @@ function of({ name, opening, settledAt }: DigestParts): SessionDigest {
78
70
  };
79
71
  }
80
72
 
81
- /** The last `session_info` line, found by walking the marker's occurrences backwards; a line that merely quotes the marker parses as something else, and the walk carries on past it. */
73
+ /** The last `session_info` entry's name. Skips lines that merely quote the marker. */
82
74
  function nameOf({ bytes, end }: Durable): string | undefined {
83
75
  let at = end - 1;
84
76
  while (at >= 0) {
@@ -140,7 +132,6 @@ function clamp(text: string): string {
140
132
  : text;
141
133
  }
142
134
 
143
- /** Over the head window the caller has already cut, not the whole file. */
144
135
  function firstUserMessage(lines: readonly string[]): string | undefined {
145
136
  for (const line of lines) {
146
137
  const entry = parseSessionEntries(line)[0];
@@ -34,10 +34,8 @@ import { SessionName } from "./SessionName";
34
34
  import { adaptSessionUi, type SessionUi } from "./SessionUi";
35
35
  import { WriteMark } from "./WriteMark";
36
36
 
37
- /** What the agent is doing right now. */
38
37
  export type SessionStatus = "idle" | "thinking" | "streaming" | "tool";
39
38
 
40
- /** Everything the host persists about a session; frontend-specific settings stay with the adapter. */
41
39
  export type HostSettings = {
42
40
  readonly cwd?: string;
43
41
  readonly model?: string;
@@ -63,13 +61,12 @@ export type SessionCompactResult = {
63
61
  readonly activeMessages: number;
64
62
  };
65
63
 
66
- /** What a `cancel` did; `restored` messages are the caller's from here on. */
64
+ /** `restored` are the queued messages taken back from pi. */
67
65
  export type CancelResult = {
68
66
  readonly cancelled: boolean;
69
67
  readonly restored: readonly string[];
70
68
  };
71
69
 
72
- /** Whether this host can mutate its session file right now, and who is stopping it. */
73
70
  export type LeaseState = {
74
71
  readonly writable: boolean;
75
72
  readonly heldBy?: {
@@ -79,7 +76,7 @@ export type LeaseState = {
79
76
  };
80
77
 
81
78
  export type SessionHostDeps = {
82
- /** Prefix for this host's log lines; also the registry key in practice. */
79
+ /** Log prefix. */
83
80
  readonly label: string;
84
81
  readonly settings: HostSettings;
85
82
  readonly defaults: { readonly cwd: string; readonly model?: string };
@@ -88,36 +85,25 @@ export type SessionHostDeps = {
88
85
  readonly modelRegistry: ModelRegistry;
89
86
  readonly settingsManagerFor: (cwd: string) => SettingsManager;
90
87
  readonly persistSettings: (patch: Partial<HostSettings>) => Promise<void>;
91
- /**
92
- * Take the session file's turn lease around every mutation, as this frontend.
93
- * Leave unset where nothing else can open the file.
94
- */
88
+ /** Takes the turn lease around every mutation. Omit when no other process can open the file. */
95
89
  readonly lease?: LeaseFrontend;
96
- /** Omit to let pi place the file in its own cwd-grouped sessions directory. */
90
+ /** Omit to let pi choose the file path. */
97
91
  readonly mainSessionPath?: () => string;
98
92
  readonly isolatedSessionPath?: () => string;
99
93
  readonly systemInstruction?: () => Promise<string | undefined>;
100
- /** Where this host's human is reading; surfaces in the system prompt's environment block. */
101
94
  readonly surface?: Surface;
102
95
  readonly customTools?: (
103
96
  context: CustomToolContext
104
97
  ) => readonly ToolDefinition[];
105
- /** Runs after the agent is disposed, before the session file is forgotten. */
98
+ /** Runs after the agent is disposed, before `sessionPath` is cleared. */
106
99
  readonly onRetire?: (sessionPath: string) => Promise<void>;
107
- /**
108
- * Where this host's extensions say things, resolved per call so an agent
109
- * rebuilt under the host follows its live target. Omit to leave pi's no-op
110
- * UI in place: pi freezes the mode at `bindExtensions`, so this is a dep
111
- * rather than something a caller can turn on once a session exists.
112
- */
100
+ /** Extension UI sink, read per call. Omit for pi's no-op UI; pi fixes the mode at bind time. */
113
101
  readonly ui?: () => SessionUi | undefined;
114
102
  };
115
103
 
116
- /** What a frontend's own tools are built against. */
117
104
  export type CustomToolContext = {
118
- /** Where this session's tools resolve relative paths. */
119
105
  readonly cwd: string;
120
- /** Pi's session uuid, undefined until the agent exists. */
106
+ /** Undefined until the agent exists. */
121
107
  readonly sessionId: () => string | undefined;
122
108
  };
123
109
 
@@ -126,7 +112,7 @@ type ModelResolveResult =
126
112
  | { readonly kind: "ambiguous"; readonly candidates: readonly string[] }
127
113
  | { readonly kind: "none"; readonly candidates: readonly string[] };
128
114
 
129
- /** A mutation of ours parked behind someone else's lease; the holder is unknown when their file is torn. */
115
+ /** `holder` is absent when the lease file is unreadable. */
130
116
  type LeaseWait = { readonly holder?: LeaseRecord };
131
117
 
132
118
  const FOREIGN_POLL_MS = 2_000;
@@ -150,7 +136,7 @@ function isOutput(event: AssistantMessageEvent): boolean {
150
136
  }
151
137
  }
152
138
 
153
- /** Owns one in-process `createAgentSession()`, its settings and a serialized turn queue. */
139
+ /** One in-process pi agent session, its settings and a serialized turn queue. */
154
140
  export class SessionHost {
155
141
  public readonly label: string;
156
142
  public lastUsed = Date.now();
@@ -162,12 +148,12 @@ export class SessionHost {
162
148
  private cachedLog: EventLog | undefined;
163
149
  private queue: Promise<unknown> = Promise.resolve();
164
150
  private seqLog: EventLog | undefined;
165
- /** The `EventLog` head as of this host's own last write to that file. */
151
+ /** File head after this host's last write. */
166
152
  private lastSeen: { readonly path: string; readonly seq: number } | undefined;
167
153
  private blockedBy: LeaseWait | undefined;
168
154
  private readonly leaseListeners = new Set<() => void>();
169
155
  private readonly foreignListeners = new Set<() => void>();
170
- /** Set only while a held turn is watching the file; re-samples on demand. */
156
+ /** Set only while a held turn is watching for foreign writes. */
171
157
  private sampleWrites: (() => Promise<void>) | undefined;
172
158
  private readonly agentListeners = new Set<
173
159
  (event: AgentSessionEvent) => void
@@ -204,12 +190,12 @@ export class SessionHost {
204
190
  return this.cached?.sessionId;
205
191
  }
206
192
 
207
- /** Reader over this session's JSONL, live only once the agent is built. */
193
+ /** Undefined until the agent is built. */
208
194
  public get eventLog(): EventLog | undefined {
209
195
  return this.cachedLog;
210
196
  }
211
197
 
212
- /** False only while one of this host's own mutations waits on another process. */
198
+ /** Not writable only while one of our mutations waits on another process's lease. */
213
199
  public get leaseState(): LeaseState {
214
200
  const blocked = this.blockedBy;
215
201
  if (blocked === undefined) {
@@ -232,7 +218,7 @@ export class SessionHost {
232
218
  };
233
219
  }
234
220
 
235
- /** Fires once per turn in which another process appended to this session's file. */
221
+ /** Fires at most once per turn in which another process appended to the file. */
236
222
  public onForeignWrite(listener: () => void): () => void {
237
223
  this.foreignListeners.add(listener);
238
224
  return () => {
@@ -240,7 +226,7 @@ export class SessionHost {
240
226
  };
241
227
  }
242
228
 
243
- /** Events from whatever agent this host currently holds, across rehydration rebuilds. */
229
+ /** Survives agent rebuilds. */
244
230
  public subscribe(listener: (event: AgentSessionEvent) => void): () => void {
245
231
  this.agentListeners.add(listener);
246
232
  return () => {
@@ -280,17 +266,17 @@ export class SessionHost {
280
266
  }
281
267
 
282
268
  public get currentModelId(): string | undefined {
283
- const model = this.cached?.model ?? this.resolveDefaultModel();
269
+ const model = this.currentModel();
284
270
  return model ? qualifiedModelId(model) : undefined;
285
271
  }
286
272
 
287
- /** The model's display name — "Claude Opus 5.0", not `anthropic/claude-opus-5`. */
273
+ /** Display name, e.g. "Claude Opus 5.0". */
288
274
  public get currentModelLabel(): string | undefined {
289
- return (this.cached?.model ?? this.resolveDefaultModel())?.name;
275
+ return this.currentModel()?.name;
290
276
  }
291
277
 
292
278
  public get supportedThinkingLevels(): readonly ThinkingLevel[] {
293
- const model = this.cached?.model ?? this.resolveDefaultModel();
279
+ const model = this.currentModel();
294
280
  return model ? getSupportedThinkingLevels(model) : [];
295
281
  }
296
282
 
@@ -303,17 +289,16 @@ export class SessionHost {
303
289
  return (sm.getDefaultThinkingLevel() as ThinkingLevel) ?? "medium";
304
290
  }
305
291
 
306
- /** The level this session was told to think at, absent when only its directory has a default. */
292
+ /** Undefined when only the directory's default applies. */
307
293
  public get chosenThinkingLevel(): ThinkingLevel | undefined {
308
294
  return this.currentSettings.thinkingLevel ?? this.cached?.thinkingLevel;
309
295
  }
310
296
 
311
- /** Run `work` as a turn, serialized in submission order; `isolated` uses a throwaway agent and file. */
297
+ /** Runs `work` as a queued turn. `isolated` uses a throwaway agent and file, without the lease. */
312
298
  public run(
313
299
  work: (agent: AgentSession) => Promise<void>,
314
300
  opts?: { readonly isolated?: boolean }
315
301
  ): Promise<void> {
316
- // An isolated run owns a throwaway file nobody else can name, so it takes no lease.
317
302
  if (opts?.isolated) {
318
303
  return this.enqueue(async () => {
319
304
  const { agent, sessionPath } = await this.buildIsolatedAgent();
@@ -335,28 +320,28 @@ export class SessionHost {
335
320
  });
336
321
  }
337
322
 
338
- /** Build or reuse the cached agent inside the turn queue; its id and file exist once this resolves. */
323
+ /** Builds or reuses the agent inside the turn queue. */
339
324
  public ensureAgent(): Promise<AgentSession> {
340
325
  return this.enqueue(() => this.ensureCached());
341
326
  }
342
327
 
343
- /** Run `work` in this session's turn queue without touching the agent. */
328
+ /** Runs `work` in the turn queue without touching the agent. */
344
329
  public serialize<T>(work: () => Promise<T>): Promise<T> {
345
330
  return this.enqueue(work);
346
331
  }
347
332
 
348
- /** Stop the turn in flight; empty the queue before aborting or pi delivers it to the next turn. */
333
+ /** Aborts the running turn and takes back its queued messages. */
349
334
  public async cancel(): Promise<CancelResult> {
350
335
  if (!this.cached || !this.cached.isStreaming) {
351
336
  return { cancelled: false, restored: [] };
352
337
  }
353
- // Take the queue back *before* aborting: anything left in pi is delivered to the next turn.
338
+ // Before aborting, or pi delivers the queue to the next turn.
354
339
  const restored = this.takeBack();
355
340
  await this.cached.abort();
356
341
  return { cancelled: true, restored };
357
342
  }
358
343
 
359
- /** Take back every message queued behind the running turn; not serialized, the turn holds the queue. */
344
+ /** Takes back messages queued behind the running turn. Not queued: the turn holds the queue. */
360
345
  public takeBack(): readonly string[] {
361
346
  if (!this.cached || !this.cached.isStreaming) {
362
347
  return [];
@@ -412,10 +397,7 @@ export class SessionHost {
412
397
  });
413
398
  }
414
399
 
415
- /**
416
- * Rename this session through pi's own session name, so its `/resume` picker
417
- * shows it too; `null` clears it. Answers with the name pi kept.
418
- */
400
+ /** Sets pi's session name; `null` clears it. Returns the stored name. */
419
401
  public setName(name: string | null): Promise<string | undefined> {
420
402
  return this.withLease(async () => {
421
403
  const agent = await this.ensureCached();
@@ -432,7 +414,7 @@ export class SessionHost {
432
414
  });
433
415
  }
434
416
 
435
- /** Drop the cached agent so the next turn rebuilds it from the file; never retires the session. */
417
+ /** Drops the agent so the next turn rebuilds it from the file. */
436
418
  public async invalidate(): Promise<void> {
437
419
  if (!this.cached) {
438
420
  return;
@@ -449,7 +431,7 @@ export class SessionHost {
449
431
 
450
432
  private enqueue<T>(work: () => Promise<T>): Promise<T> {
451
433
  const next = this.queue.then(work);
452
- // Only the stored tail swallows: the chain must never reject, callers still see their own failure.
434
+ // Keep the chain alive; callers still get their own rejection.
453
435
  this.queue = next.catch((err: unknown) => {
454
436
  console.error(`[${this.label}] work failed:`, err);
455
437
  });
@@ -457,7 +439,6 @@ export class SessionHost {
457
439
  return next;
458
440
  }
459
441
 
460
- /** Where this session's turn lease lives, once anything has named the file. */
461
442
  private get leasePath(): string | undefined {
462
443
  return (
463
444
  this.cached?.sessionFile ??
@@ -466,11 +447,7 @@ export class SessionHost {
466
447
  );
467
448
  }
468
449
 
469
- /**
470
- * Serialize `work` behind the session file's turn lease, with a rehydration on
471
- * either side of the acquire: waiting for the lease is exactly the window in
472
- * which the other surface appends.
473
- */
450
+ /** Queues `work` under the turn lease, rehydrating before and after waiting for it. */
474
451
  private withLease<T>(work: () => Promise<T>): Promise<T> {
475
452
  return this.enqueue(async () => {
476
453
  const frontend = this.deps.lease;
@@ -478,7 +455,7 @@ export class SessionHost {
478
455
  return await work();
479
456
  }
480
457
  await this.rehydrateIfStale();
481
- // pi names a brand-new session's file itself, and a file nobody else knows cannot be contended.
458
+ // A new session's path is only known once pi builds the agent.
482
459
  const path = this.leasePath ?? (await this.ensureCached()).sessionFile;
483
460
  if (path === undefined) {
484
461
  return await work();
@@ -494,8 +471,7 @@ export class SessionHost {
494
471
  try {
495
472
  return await work();
496
473
  } finally {
497
- // A line we cannot account for means the file has moved past our
498
- // agent: leave `lastSeen` behind the head so the next turn rebuilds.
474
+ // After a foreign write, leave `lastSeen` stale so the next turn rebuilds.
499
475
  if (!(await settle())) {
500
476
  await this.markSeen(path);
501
477
  }
@@ -513,10 +489,8 @@ export class SessionHost {
513
489
  }
514
490
 
515
491
  /**
516
- * Watch, for one held turn, for lines this host cannot account for: a `pi` that
517
- * took no lease, or a holder killed mid-write. Reports at most once and never
518
- * aborts — the work in flight is worth more than the inconsistency it races.
519
- * Resolves to whether anything foreign landed.
492
+ * Polls for lines another process appended during a held turn. Warns at most
493
+ * once and never aborts. The returned stop function resolves to whether any landed.
520
494
  */
521
495
  private async watchForeignWrites(
522
496
  path: string
@@ -531,8 +505,7 @@ export class SessionHost {
531
505
  return;
532
506
  }
533
507
  const agent = this.cached;
534
- // A rebuilt agent re-opened the file, which repairs a torn tail and rewrites
535
- // on migration, so its own accounting starts from whatever it just read.
508
+ // A rebuilt agent may have rewritten the file, so restart accounting from it.
536
509
  if (agent?.sessionFile !== path) {
537
510
  base = undefined;
538
511
  return;
@@ -579,7 +552,7 @@ export class SessionHost {
579
552
  }
580
553
  }
581
554
 
582
- /** Another writer moved the file past what this host's `messages` were loaded from. */
555
+ /** Drops the agent if the file grew since our last write. */
583
556
  private async rehydrateIfStale(): Promise<void> {
584
557
  const path = this.cached?.sessionFile;
585
558
  const seen = this.lastSeen;
@@ -591,8 +564,6 @@ export class SessionHost {
591
564
  }
592
565
  }
593
566
 
594
- // Reading the head is how our own writes stop looking foreign: pi repairs a torn tail and
595
- // rewrites on migration, so a rebuild moves the head without anyone else touching the file.
596
567
  private async markSeen(path: string): Promise<void> {
597
568
  this.lastSeen = { path, seq: await this.logFor(path).head() };
598
569
  }
@@ -626,8 +597,7 @@ export class SessionHost {
626
597
  if (this.deps.lease !== undefined && agent.sessionFile) {
627
598
  await this.markSeen(agent.sessionFile);
628
599
  }
629
- // Anchor a watching turn on the agent it is about to run, not on the file as
630
- // it was before this rebuild read it.
600
+ // Re-anchor a watching turn on the new agent.
631
601
  await this.sampleWrites?.();
632
602
  await this.patchSettings({ cwd, sessionPath: agent.sessionFile });
633
603
  return agent;
@@ -740,7 +710,7 @@ export class SessionHost {
740
710
  cwd,
741
711
  agentDir: this.deps.agentDir,
742
712
  settingsManager,
743
- // Load core tools in-process: a disk-loaded copy registers views into a second `Tools`.
713
+ // In-process: a disk-loaded copy would register views into a second `Tools`.
744
714
  extensionFactories: CoreExtensions.gated(this.deps.surface),
745
715
  appendSystemPromptOverride: (base) => {
746
716
  return promptRef.wrapped ? [...base, promptRef.wrapped] : base;
@@ -784,8 +754,7 @@ export class SessionHost {
784
754
  `[${this.label}] extension ${err.extensionPath} (${err.event}):`,
785
755
  err.error
786
756
  );
787
- // Pi answers a command handler that threw as if it had succeeded, so
788
- // without this the user's message vanishes and only stderr says why.
757
+ // Pi treats a throwing command as success, so tell the user.
789
758
  this.deps
790
759
  .ui?.()
791
760
  ?.notify(
@@ -794,11 +763,10 @@ export class SessionHost {
794
763
  );
795
764
  };
796
765
  const ui = this.deps.ui;
797
- // Emits session_start; without it extension tools are registered but never usable.
766
+ // Emits session_start; extension tools are unusable without it.
798
767
  await agent.bindExtensions(
799
768
  ui
800
- ? // Any context at all makes pi's `hasUI()` true (`uiContext !== noOpUIContext`,
801
- // runner.js:318); "rpc" is its own name for dialog-capable but not a terminal.
769
+ ? // Any uiContext makes pi's `hasUI()` true; "rpc" means dialogs but no terminal.
802
770
  {
803
771
  uiContext: adaptSessionUi(ui),
804
772
  mode: "rpc",
@@ -834,6 +802,10 @@ export class SessionHost {
834
802
  await this.deps.persistSettings(patch);
835
803
  }
836
804
 
805
+ private currentModel(): Model<ModelApi> | undefined {
806
+ return this.cached?.model ?? this.resolveDefaultModel();
807
+ }
808
+
837
809
  private resolveDefaultModel(): Model<ModelApi> | undefined {
838
810
  this.deps.modelRegistry.refresh();
839
811
  for (const candidate of [
@@ -862,23 +834,21 @@ export class SessionHost {
862
834
  private resolveModel(pattern: string): ModelResolveResult {
863
835
  this.deps.modelRegistry.refresh();
864
836
  const available = this.deps.modelRegistry.getAvailable();
865
- const candidates: FuzzyCandidate<Model<ModelApi>>[] = available.map(
866
- (m) => ({
867
- item: m,
868
- haystacks: [qualifiedModelId(m), m.id, m.name],
869
- })
870
- );
871
-
837
+ const wanted = pattern.trim();
872
838
  const exact = available.find(
873
839
  (m) =>
874
- qualifiedModelId(m) === pattern.trim() ||
875
- m.id === pattern.trim() ||
876
- m.name === pattern.trim()
840
+ qualifiedModelId(m) === wanted || m.id === wanted || m.name === wanted
877
841
  );
878
842
  if (exact) {
879
843
  return { kind: "ok", model: exact };
880
844
  }
881
845
 
846
+ const candidates: FuzzyCandidate<Model<ModelApi>>[] = available.map(
847
+ (m) => ({
848
+ item: m,
849
+ haystacks: [qualifiedModelId(m), m.id, m.name],
850
+ })
851
+ );
882
852
  const hits = FuzzyMatcher.rank(pattern, candidates, { limit: 5 });
883
853
  if (hits.length === 0) {
884
854
  return {