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.
- package/package.json +3 -3
- package/packages/core/src/attachments/AttachmentStore.ts +8 -13
- package/packages/core/src/attachments/Attachments.ts +2 -4
- package/packages/core/src/extensions/CoreExtensions.ts +1 -1
- package/packages/core/src/extensions/apply-patch/coordinator.ts +1 -1
- package/packages/core/src/extensions/apply-patch/executor.ts +21 -25
- package/packages/core/src/extensions/apply-patch/matcher.ts +1 -1
- package/packages/core/src/extensions/apply-patch/model.ts +2 -6
- package/packages/core/src/extensions/apply-patch/parser.ts +60 -162
- package/packages/core/src/extensions/apply-patch/schema.ts +0 -1
- package/packages/core/src/extensions/bash/MemoryCap.ts +5 -4
- package/packages/core/src/extensions/bash/capture.ts +16 -23
- package/packages/core/src/extensions/bash/format.ts +2 -2
- package/packages/core/src/extensions/bash/image.ts +4 -8
- package/packages/core/src/extensions/bash/index.ts +1 -1
- package/packages/core/src/extensions/bash/render.ts +1 -1
- package/packages/core/src/extensions/bash/run.ts +9 -15
- package/packages/core/src/extensions/bash/schema.ts +4 -4
- package/packages/core/src/extensions/edit/edit.ts +14 -33
- package/packages/core/src/extensions/glob/glob.ts +1 -3
- package/packages/core/src/extensions/glob/index.ts +7 -9
- package/packages/core/src/extensions/glob/render.ts +2 -4
- package/packages/core/src/extensions/glob/schema.ts +1 -1
- package/packages/core/src/extensions/grep/grep.ts +7 -7
- package/packages/core/src/extensions/grep/render.ts +5 -6
- package/packages/core/src/extensions/grep/schema.ts +3 -7
- package/packages/core/src/extensions/read/ImageMemory.ts +2 -8
- package/packages/core/src/extensions/read/image.ts +3 -3
- package/packages/core/src/extensions/read/index.ts +2 -14
- package/packages/core/src/extensions/read/read.ts +5 -6
- package/packages/core/src/extensions/read/render.ts +1 -1
- package/packages/core/src/extensions/read/schema.ts +2 -2
- package/packages/core/src/extensions/subagent/render.ts +2 -2
- package/packages/core/src/extensions/subagent/subagent.ts +10 -21
- package/packages/core/src/extensions/system-prompt/index.ts +1 -2
- package/packages/core/src/extensions/system-prompt/prompt.ts +2 -4
- package/packages/core/src/extensions/todo/render.ts +1 -4
- package/packages/core/src/extensions/todo/todo.ts +16 -23
- package/packages/core/src/extensions/web-fetch/JinaReaderClient.ts +3 -11
- package/packages/core/src/extensions/web-fetch/WebViewFetchClient.ts +1 -3
- package/packages/core/src/extensions/web-fetch/fetch.ts +4 -12
- package/packages/core/src/extensions/web-fetch/image.ts +3 -4
- package/packages/core/src/extensions/web-fetch/index.ts +2 -13
- package/packages/core/src/extensions/web-fetch/render.ts +3 -4
- package/packages/core/src/extensions/web-fetch/schema.ts +3 -4
- package/packages/core/src/extensions/web-search/ExaMcpClient.ts +23 -31
- package/packages/core/src/extensions/web-search/SearchBreaker.ts +1 -1
- package/packages/core/src/extensions/web-search/SearchChain.ts +6 -5
- package/packages/core/src/extensions/web-search/providers/DuckDuckGoProvider.ts +2 -2
- package/packages/core/src/extensions/web-search/providers/FirecrawlProvider.ts +1 -2
- package/packages/core/src/extensions/web-search/providers/SearchProvider.ts +3 -3
- package/packages/core/src/extensions/write/write.ts +1 -1
- package/packages/core/src/picker/InProcessFilePickerSuggestionEngine.ts +1 -3
- package/packages/core/src/picker/PickerItem.ts +1 -1
- package/packages/core/src/picker/PickerService.ts +3 -7
- package/packages/core/src/picker/RemoteFilePickerSuggestionEngine.ts +1 -2
- package/packages/core/src/picker/catalog.ts +7 -15
- package/packages/core/src/picker/filePickerWorker.ts +1 -3
- package/packages/core/src/picker/ranker.ts +1 -1
- package/packages/core/src/picker/token.ts +3 -4
- package/packages/core/src/session/AgentRuntime.ts +5 -8
- package/packages/core/src/session/EventLog.ts +6 -12
- package/packages/core/src/session/ReadCursors.ts +3 -4
- package/packages/core/src/session/SearchIndex.ts +49 -86
- package/packages/core/src/session/SearchTokens.ts +4 -7
- package/packages/core/src/session/SessionCache.ts +8 -6
- package/packages/core/src/session/SessionDigest.ts +10 -19
- package/packages/core/src/session/SessionHost.ts +53 -83
- package/packages/core/src/session/SessionLease.ts +12 -15
- package/packages/core/src/session/SessionMeta.ts +16 -32
- package/packages/core/src/session/SessionName.ts +3 -7
- package/packages/core/src/session/SessionRegistry.ts +13 -29
- package/packages/core/src/session/SessionUi.ts +12 -16
- package/packages/core/src/session/WriteMark.ts +7 -16
- package/packages/core/src/shared/Cli.ts +1 -1
- package/packages/core/src/shared/DaemonUnit.ts +1 -2
- package/packages/core/src/shared/DiffLines.ts +16 -34
- package/packages/core/src/shared/DiffRenderer.ts +8 -27
- package/packages/core/src/shared/Directories.ts +4 -4
- package/packages/core/src/shared/EditMatcher.ts +18 -50
- package/packages/core/src/shared/ExtensionToggles.ts +3 -6
- package/packages/core/src/shared/FileEnumerator.ts +73 -57
- package/packages/core/src/shared/FileScanner.ts +5 -13
- package/packages/core/src/shared/FileWatch.ts +13 -17
- package/packages/core/src/shared/Format.ts +2 -3
- package/packages/core/src/shared/FuzzyMatcher.ts +18 -19
- package/packages/core/src/shared/Git.ts +22 -47
- package/packages/core/src/shared/GitMonitor.ts +12 -23
- package/packages/core/src/shared/GlobExclusions.ts +0 -4
- package/packages/core/src/shared/Http.ts +1 -1
- package/packages/core/src/shared/ImageMime.ts +3 -5
- package/packages/core/src/shared/Images.ts +17 -27
- package/packages/core/src/shared/Languages.ts +2 -2
- package/packages/core/src/shared/Levenshtein.ts +1 -6
- package/packages/core/src/shared/Lines.ts +1 -1
- package/packages/core/src/shared/McpClient.ts +2 -2
- package/packages/core/src/shared/PatchSummary.ts +1 -1
- package/packages/core/src/shared/Paths.ts +4 -1
- package/packages/core/src/shared/PiExtensions.ts +5 -12
- package/packages/core/src/shared/PimSettings.ts +14 -15
- package/packages/core/src/shared/Proc.ts +2 -3
- package/packages/core/src/shared/RateLimiter.ts +1 -1
- package/packages/core/src/shared/Renderer.ts +1 -3
- package/packages/core/src/shared/RepoDiff.ts +24 -46
- package/packages/core/src/shared/SearchRender.ts +3 -4
- package/packages/core/src/shared/SpillCache.ts +2 -3
- package/packages/core/src/shared/SubagentLogs.ts +4 -6
- package/packages/core/src/shared/Supervisor.ts +19 -32
- package/packages/core/src/shared/Surface.ts +1 -1
- package/packages/core/src/shared/Sweeper.ts +1 -1
- package/packages/core/src/shared/Tools.ts +17 -30
- package/packages/core/src/shared/Updater.ts +15 -15
- package/packages/core/src/view/BodyRenderer.ts +1 -1
- package/packages/core/src/view/DiffBlocks.ts +0 -1
- package/packages/core/src/view/DiffExpand.ts +10 -25
- package/packages/core/src/view/DiffLayout.ts +2 -2
- package/packages/core/src/view/DiffPairs.ts +2 -2
- package/packages/core/src/view/MarkdownPainter.ts +2 -19
- package/packages/core/src/view/MovePath.ts +4 -17
- package/packages/core/src/view/Painting.ts +4 -4
- package/packages/core/src/view/ViewBlock.ts +11 -12
- package/packages/daemon/src/Daemon.ts +2 -7
- package/packages/daemon/src/DaemonInstall.ts +5 -12
- package/packages/daemon/src/Surfaces.ts +3 -12
- package/packages/daemon/src/TelegramSurface.ts +0 -1
- package/packages/daemon/src/index.ts +0 -1
- package/packages/protocol/src/Command.ts +33 -41
- package/packages/protocol/src/Diff.ts +0 -5
- package/packages/protocol/src/ImageRoute.ts +2 -5
- package/packages/protocol/src/ServerEvent.ts +68 -105
- package/packages/server/src/AttachmentEndpoint.ts +45 -19
- package/packages/server/src/ClientConnection.ts +11 -12
- package/packages/server/src/ImageEndpoint.ts +3 -4
- package/packages/server/src/ProbeClient.ts +26 -59
- package/packages/server/src/Reloader.ts +4 -7
- package/packages/server/src/SendFileTool.ts +1 -1
- package/packages/server/src/SessionCatalogue.ts +35 -47
- package/packages/server/src/SessionProjection.ts +7 -12
- package/packages/server/src/SessionStream.ts +33 -80
- package/packages/server/src/StaticClient.ts +7 -8
- package/packages/server/src/WebOptions.ts +2 -6
- package/packages/server/src/WsGateway.ts +35 -96
- package/packages/server/src/probe.ts +6 -18
- package/packages/telegram/src/Bot.ts +2 -2
- package/packages/telegram/src/Commands.ts +108 -65
- package/packages/telegram/src/Config.ts +1 -6
- package/packages/telegram/src/Markdown.ts +4 -13
- package/packages/telegram/src/Renderer.ts +1 -1
- package/packages/telegram/src/Session.ts +3 -10
- package/packages/telegram/src/TaskScheduler.ts +31 -10
- package/packages/telegram/src/TaskStore.ts +11 -1
- package/packages/telegram/src/TaskTool.ts +1 -1
- package/packages/telegram/src/UpdateConfirm.ts +2 -2
- package/packages/tui/src/extensions/_init/index.ts +2 -5
- package/packages/tui/src/extensions/file-picker/index.ts +2 -6
- package/packages/tui/src/extensions/footer/index.ts +0 -1
- package/packages/tui/src/extensions/footer/powerline.ts +16 -28
- package/packages/tui/src/extensions/pim/index.ts +1 -1
- package/packages/tui/src/extensions/session-lease/index.ts +5 -6
- package/packages/tui/src/extensions/working-indicator/index.ts +1 -2
- package/packages/tui/src/themes/themeCliArgs.ts +1 -1
- package/packages/web/dist/client/assets/{abnfDiagram-O67JEVCF-CZ7V84ot.js → abnfDiagram-O67JEVCF-WweOU5DK.js} +1 -1
- package/packages/web/dist/client/assets/{arc-DiHGkUvc.js → arc-O2PmZXWt.js} +1 -1
- package/packages/web/dist/client/assets/architecture-7GRP2DOG-COBxVilU.js +1 -0
- package/packages/web/dist/client/assets/{architectureDiagram-NJMV4G6O-XS5DhfJB.js → architectureDiagram-NJMV4G6O-DwYq1YaM.js} +1 -1
- package/packages/web/dist/client/assets/{blockDiagram-BEXU5L5S-BCsgLvy1.js → blockDiagram-BEXU5L5S-CVab041n.js} +1 -1
- package/packages/web/dist/client/assets/{c4Diagram-YGBWAQC7-Bj9LcWNm.js → c4Diagram-YGBWAQC7-BmotHez3.js} +1 -1
- package/packages/web/dist/client/assets/channel-BKV-IcTA.js +1 -0
- package/packages/web/dist/client/assets/{chunk-3FUC2YCW-BmDurFxp.js → chunk-3FUC2YCW-CWNS7-n4.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-5DYCD2WN-DAjG-pqn.js → chunk-5DYCD2WN-DflvXohu.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-742MDFTN-Bmxs5puY.js → chunk-742MDFTN-B_0t6_RE.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-7INBJB4K-Di7kIxrQ.js → chunk-7INBJB4K-wKj0Q3Kv.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-7M6MHVWA-CSc8sR0b.js → chunk-7M6MHVWA-BMvUghc8.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-7PRAP22T-C8kd5QvY.js → chunk-7PRAP22T-BY41wkcT.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-GTNCS2PH-DG2b2LYE.js → chunk-GTNCS2PH-PqY_YoS0.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-GWA4HPMP-DdLaLQCu.js → chunk-GWA4HPMP-fozSU5ty.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-MBY4JIJT-C1j0yQlk.js → chunk-MBY4JIJT-CrHrC3jw.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-NETBCI7D-Bfq9H74p.js → chunk-NETBCI7D-DWdAxieG.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-O7XYJQB3-ZHvBmBO-.js → chunk-O7XYJQB3-B6uOn9iS.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-UA2S7LBM-ku1JeHSK.js → chunk-UA2S7LBM-BxYSHqyy.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-WEXAMYUT-BP1iga_7.js → chunk-WEXAMYUT-CtwIaQDa.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-XXDRQBXY-BBeccPcX.js → chunk-XXDRQBXY-fgBFe-PX.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-Z7XXMR3K-SMHZugaR.js → chunk-Z7XXMR3K-CPonoV3p.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-ZIGJFQKS-CFU_JLG4.js → chunk-ZIGJFQKS-Cdu87cTj.js} +1 -1
- package/packages/web/dist/client/assets/{classDiagram-v2-NBCMYWYE-CYviuQzJ.js → classDiagram-v2-NBCMYWYE-DSWsPaa7.js} +1 -1
- package/packages/web/dist/client/assets/{core-DyHsgs5k.js → core-CBoS7AST.js} +1 -1
- package/packages/web/dist/client/assets/{cose-bilkent-JH36ORCC-9v2ZkJzo.js → cose-bilkent-JH36ORCC-CTwlldtJ.js} +1 -1
- package/packages/web/dist/client/assets/{cynefin-OW5HDTMX-Bx5xRadi.js → cynefin-OW5HDTMX-CZQ4EPNJ.js} +1 -1
- package/packages/web/dist/client/assets/{cynefinDiagram-VND7K2PF-BRfGDKqa.js → cynefinDiagram-VND7K2PF-C2gp6H_Q.js} +1 -1
- package/packages/web/dist/client/assets/{dagre-6A5THRUB-C4l-2L2e.js → dagre-6A5THRUB-CDxTP47t.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-22UHCM2B-d_hQ3kyi.js → diagram-22UHCM2B-BIohE1lI.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-3UASUU5V-DrEeguPI.js → diagram-3UASUU5V-TwAUir-w.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-ATOU4E4O-BmfQ22pD.js → diagram-ATOU4E4O-BM1JQrIu.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-CDSNMT55-BjVWjuPF.js → diagram-CDSNMT55-BKIqhxSI.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-MLGK6HIB-wDjk-O8i.js → diagram-MLGK6HIB-CVe3QDHr.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-MPIPVDR6-DqXQFE1s.js → diagram-MPIPVDR6-Bj-MQIFI.js} +1 -1
- package/packages/web/dist/client/assets/{dist-BddGOpie.js → dist-DlZpcyc2.js} +1 -1
- package/packages/web/dist/client/assets/{ebnfDiagram-ZINNZB2B-UB8kOITM.js → ebnfDiagram-ZINNZB2B-C06mmvmz.js} +1 -1
- package/packages/web/dist/client/assets/{elk-276RUBZZ-D4miYQnD.js → elk-276RUBZZ-CizJSNEj.js} +1 -1
- package/packages/web/dist/client/assets/{erDiagram-OPXOYQCR--RXKv7KH.js → erDiagram-OPXOYQCR-M3FQkKI1.js} +1 -1
- package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-D_UXLpIu.js +1 -0
- package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-BT4eEEVm.js +1 -0
- package/packages/web/dist/client/assets/{ganttDiagram-FUAMR5RP-C0CFpE5x.js → ganttDiagram-FUAMR5RP-CojF9Q16.js} +1 -1
- package/packages/web/dist/client/assets/{gitGraph-4MIJSDKK-VPL7nv2c.js → gitGraph-4MIJSDKK-YvKqGEPk.js} +1 -1
- package/packages/web/dist/client/assets/{gitGraphDiagram-X574FWY7-CgxJA-T8.js → gitGraphDiagram-X574FWY7-XqNqIFo9.js} +1 -1
- package/packages/web/dist/client/assets/index--2CDtzvY.css +1 -0
- package/packages/web/dist/client/assets/{index-XTlTnQmx.js → index-bT6QPJZs.js} +7 -7
- package/packages/web/dist/client/assets/{info-A6RAGUB7-P0-o68pj.js → info-A6RAGUB7-B_1BCzM2.js} +1 -1
- package/packages/web/dist/client/assets/{infoDiagram-VRGFBTTK-DFJZNRUP.js → infoDiagram-VRGFBTTK-zFX8B-dP.js} +1 -1
- package/packages/web/dist/client/assets/{ishikawaDiagram-OU5B5YK6-ZkyhNd1T.js → ishikawaDiagram-OU5B5YK6-DLzQ_Uyf.js} +1 -1
- package/packages/web/dist/client/assets/{journeyDiagram-ZHPQQLJL-DFevH8my.js → journeyDiagram-ZHPQQLJL-S3WRMmoa.js} +1 -1
- package/packages/web/dist/client/assets/{kanban-definition-PNTS6WVX-l7e7ZZDC.js → kanban-definition-PNTS6WVX-B5Z8I-kM.js} +1 -1
- package/packages/web/dist/client/assets/{line-DO_s6Ujd.js → line-BGMH-i2X.js} +1 -1
- package/packages/web/dist/client/assets/{linear-C4xH5PPc.js → linear-KsrestXG.js} +1 -1
- package/packages/web/dist/client/assets/{mermaid-parser.core-nQaTP3VY.js → mermaid-parser.core-DNffyJJA.js} +3 -3
- package/packages/web/dist/client/assets/{mermaid.core-Cz05yTZh.js → mermaid.core-Cz3vJeQG.js} +4 -4
- package/packages/web/dist/client/assets/{mindmap-definition-NLK3R4M7-CHOEuHm2.js → mindmap-definition-NLK3R4M7-CzA61XUf.js} +1 -1
- package/packages/web/dist/client/assets/{packet-AYTQ26CC-BH3ehPMo.js → packet-AYTQ26CC-BO55e7cR.js} +1 -1
- package/packages/web/dist/client/assets/{pegDiagram-GJSIUBJH-CkWBLtad.js → pegDiagram-GJSIUBJH-DeRiXYNd.js} +1 -1
- package/packages/web/dist/client/assets/{pie-WAS4IAKB-nNVEq3dx.js → pie-WAS4IAKB-D9ibrQRe.js} +1 -1
- package/packages/web/dist/client/assets/{pieDiagram-5QR66LMP-DimUBAgN.js → pieDiagram-5QR66LMP-BaBpPP33.js} +1 -1
- package/packages/web/dist/client/assets/{quadrantDiagram-O4NWA36T-BR0XpRGQ.js → quadrantDiagram-O4NWA36T-DIfn4GjM.js} +1 -1
- package/packages/web/dist/client/assets/{radar-RG4KPBEZ-paA-H3mb.js → radar-RG4KPBEZ-Dmn5-nJq.js} +1 -1
- package/packages/web/dist/client/assets/{railroad-74A4TZTK-yEiKB3rz.js → railroad-74A4TZTK-ZCWNEd2Z.js} +1 -1
- package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-_swqhy0y.js +1 -0
- package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-CytbazPx.js +1 -0
- package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-Bg8QW17T.js +1 -0
- package/packages/web/dist/client/assets/{railroadDiagram-XR7U4H2S--TXe6rdU.js → railroadDiagram-XR7U4H2S-CDPZ39sy.js} +1 -1
- package/packages/web/dist/client/assets/{requirementDiagram-PLB6GJNP-DyqH36Za.js → requirementDiagram-PLB6GJNP-CyCI8Yul.js} +1 -1
- package/packages/web/dist/client/assets/{sankeyDiagram-IPEJSGJF-Bg6e3BlM.js → sankeyDiagram-IPEJSGJF-p_XAPv72.js} +1 -1
- package/packages/web/dist/client/assets/{sequenceDiagram-PO4LG4MO-ClGf85My.js → sequenceDiagram-PO4LG4MO-DmR6IP_o.js} +1 -1
- package/packages/web/dist/client/assets/{src-DF7hQfMh.js → src-gnv7pJ1z.js} +1 -1
- package/packages/web/dist/client/assets/{stateDiagram-v2-GCMORJYK-BK8TpxNo.js → stateDiagram-v2-GCMORJYK-7ZTHl6ih.js} +1 -1
- package/packages/web/dist/client/assets/{swimlanes-2SLR337P-DDnTIT9M.js → swimlanes-2SLR337P-N6bj71pw.js} +1 -1
- package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-BJQ2CBsp.js +8 -0
- package/packages/web/dist/client/assets/{timeline-definition-EJHVYXUP-mBBbH3bk.js → timeline-definition-EJHVYXUP-GNez0kW8.js} +1 -1
- package/packages/web/dist/client/assets/{treeView-Q6P3EWNA-CTK7tRwR.js → treeView-Q6P3EWNA-DyQZkboR.js} +1 -1
- package/packages/web/dist/client/assets/{treemap-WGGIJYW6-vOI-Ef_m.js → treemap-WGGIJYW6-_J8Pw2TM.js} +1 -1
- package/packages/web/dist/client/assets/{usecaseDiagram-POWQR4AR-COcii8x-.js → usecaseDiagram-POWQR4AR-Bg-CzKjl.js} +1 -1
- package/packages/web/dist/client/assets/{vennDiagram-UO4OBE2U-D6kmDGpM.js → vennDiagram-UO4OBE2U-DBQKHXhK.js} +1 -1
- package/packages/web/dist/client/assets/{wardley-WFR3VGLG-CtE2KI9r.js → wardley-WFR3VGLG-B5aAsQ3F.js} +1 -1
- package/packages/web/dist/client/assets/{wardleyDiagram-VNRHLVJA-ncxNGWnW.js → wardleyDiagram-VNRHLVJA-BKUQ1LK6.js} +1 -1
- package/packages/web/dist/client/assets/{xychartDiagram-PMCCYNJV-DUvd2Qze.js → xychartDiagram-PMCCYNJV-BI2sVbks.js} +1 -1
- package/packages/web/dist/client/index.html +2 -2
- package/packages/web/dist/client/assets/architecture-7GRP2DOG-HIzEIkwQ.js +0 -1
- package/packages/web/dist/client/assets/channel-BCA6qe9I.js +0 -1
- package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-l6SYFw1s.js +0 -1
- package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-CWW9qnqm.js +0 -1
- package/packages/web/dist/client/assets/index-D9_XJLSc.css +0 -1
- package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-mVQx9aVM.js +0 -1
- package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-CllXx1OJ.js +0 -1
- package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-BBD2Q5W_.js +0 -1
- 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
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
-
//
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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,
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
15
|
+
/** Absent means folded. */
|
|
16
16
|
readonly expanded?: boolean;
|
|
17
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
//
|
|
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
|
-
/**
|
|
33
|
+
/** Defaults to a new runtime over `agentDir`. */
|
|
35
34
|
readonly runtime?: AgentRuntime;
|
|
36
|
-
/**
|
|
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
|
-
/**
|
|
48
|
+
/** Copies model, thinking level and (if `cwd` is unset) cwd from this host. */
|
|
51
49
|
readonly like?: SessionHost;
|
|
52
50
|
};
|
|
53
51
|
|
|
54
|
-
/**
|
|
52
|
+
/** Concurrent header reads, to avoid running out of file descriptors. */
|
|
55
53
|
const HEADER_READS = 32;
|
|
56
54
|
|
|
57
|
-
/** Live sessions keyed
|
|
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
|
-
*
|
|
72
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
114
|
-
*
|
|
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
|
-
//
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
|
|
39
|
-
|
|
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
|
|
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
|
-
*
|
|
78
|
-
*
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
24
|
-
*
|
|
25
|
-
*
|
|
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
|
|
38
|
-
*
|
|
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,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
|
-
/**
|
|
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" },
|