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