pim-agent 0.13.0 → 0.14.1
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-w0u0UKcC.js} +1 -1
- package/packages/web/dist/client/assets/{arc-DiHGkUvc.js → arc-C8AeY-3C.js} +1 -1
- package/packages/web/dist/client/assets/architecture-7GRP2DOG-D-GDy9ga.js +1 -0
- package/packages/web/dist/client/assets/{architectureDiagram-NJMV4G6O-XS5DhfJB.js → architectureDiagram-NJMV4G6O-CLdCZfsP.js} +1 -1
- package/packages/web/dist/client/assets/{blockDiagram-BEXU5L5S-BCsgLvy1.js → blockDiagram-BEXU5L5S-BgAbOzdH.js} +1 -1
- package/packages/web/dist/client/assets/{c4Diagram-YGBWAQC7-Bj9LcWNm.js → c4Diagram-YGBWAQC7-DGRXXzDl.js} +1 -1
- package/packages/web/dist/client/assets/channel-BJtpIKaC.js +1 -0
- package/packages/web/dist/client/assets/{chunk-3FUC2YCW-BmDurFxp.js → chunk-3FUC2YCW-Dmz4_CY0.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-5DYCD2WN-DAjG-pqn.js → chunk-5DYCD2WN-D6q0r_NW.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-742MDFTN-Bmxs5puY.js → chunk-742MDFTN-biXvhzMn.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-7INBJB4K-Di7kIxrQ.js → chunk-7INBJB4K-CtfPEr8P.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-7M6MHVWA-CSc8sR0b.js → chunk-7M6MHVWA-CTixWKLk.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-7PRAP22T-C8kd5QvY.js → chunk-7PRAP22T-DijOiKl2.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-GTNCS2PH-DG2b2LYE.js → chunk-GTNCS2PH-DLId7dTl.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-GWA4HPMP-DdLaLQCu.js → chunk-GWA4HPMP-YUQxYmiu.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-MBY4JIJT-C1j0yQlk.js → chunk-MBY4JIJT-VWR3HSRr.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-NETBCI7D-Bfq9H74p.js → chunk-NETBCI7D-B8SeJoMY.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-O7XYJQB3-ZHvBmBO-.js → chunk-O7XYJQB3-CeLpEz0Q.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-UA2S7LBM-ku1JeHSK.js → chunk-UA2S7LBM-cBGKkXV_.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-WEXAMYUT-BP1iga_7.js → chunk-WEXAMYUT-BesXAOy9.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-XXDRQBXY-BBeccPcX.js → chunk-XXDRQBXY-DiuGUc8m.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-Z7XXMR3K-SMHZugaR.js → chunk-Z7XXMR3K-Dr2W5_t1.js} +1 -1
- package/packages/web/dist/client/assets/{chunk-ZIGJFQKS-CFU_JLG4.js → chunk-ZIGJFQKS-CwoMYXLJ.js} +1 -1
- package/packages/web/dist/client/assets/{classDiagram-v2-NBCMYWYE-CYviuQzJ.js → classDiagram-v2-NBCMYWYE-Gc3jAsDf.js} +1 -1
- package/packages/web/dist/client/assets/{core-DyHsgs5k.js → core-C27Q2ZSN.js} +1 -1
- package/packages/web/dist/client/assets/{cose-bilkent-JH36ORCC-9v2ZkJzo.js → cose-bilkent-JH36ORCC-ox5QohTH.js} +1 -1
- package/packages/web/dist/client/assets/{cynefin-OW5HDTMX-Bx5xRadi.js → cynefin-OW5HDTMX-CjQ-AjuJ.js} +1 -1
- package/packages/web/dist/client/assets/{cynefinDiagram-VND7K2PF-BRfGDKqa.js → cynefinDiagram-VND7K2PF-BVajmbbO.js} +1 -1
- package/packages/web/dist/client/assets/{dagre-6A5THRUB-C4l-2L2e.js → dagre-6A5THRUB-BtXhDxGN.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-22UHCM2B-d_hQ3kyi.js → diagram-22UHCM2B-DwjrV0H_.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-3UASUU5V-DrEeguPI.js → diagram-3UASUU5V-DQ1E_6hO.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-ATOU4E4O-BmfQ22pD.js → diagram-ATOU4E4O-wVYWlHRV.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-CDSNMT55-BjVWjuPF.js → diagram-CDSNMT55-CMlxHWMz.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-MLGK6HIB-wDjk-O8i.js → diagram-MLGK6HIB-Cbiwo7t9.js} +1 -1
- package/packages/web/dist/client/assets/{diagram-MPIPVDR6-DqXQFE1s.js → diagram-MPIPVDR6-Cv4zIyW1.js} +1 -1
- package/packages/web/dist/client/assets/{dist-BddGOpie.js → dist-Dl4GbwtH.js} +1 -1
- package/packages/web/dist/client/assets/{ebnfDiagram-ZINNZB2B-UB8kOITM.js → ebnfDiagram-ZINNZB2B-Bd8xl8W2.js} +1 -1
- package/packages/web/dist/client/assets/{elk-276RUBZZ-D4miYQnD.js → elk-276RUBZZ-DPRtUxgw.js} +1 -1
- package/packages/web/dist/client/assets/{erDiagram-OPXOYQCR--RXKv7KH.js → erDiagram-OPXOYQCR-BNoG4SxS.js} +1 -1
- package/packages/web/dist/client/assets/eventmodeling-NTZA5JFV-Dh9l6A3t.js +1 -0
- package/packages/web/dist/client/assets/flowDiagram-KWPJA3E3-DoJ97uSW.js +1 -0
- package/packages/web/dist/client/assets/{ganttDiagram-FUAMR5RP-C0CFpE5x.js → ganttDiagram-FUAMR5RP-BtFYI7uw.js} +1 -1
- package/packages/web/dist/client/assets/{gitGraph-4MIJSDKK-VPL7nv2c.js → gitGraph-4MIJSDKK-Di6RG5Kg.js} +1 -1
- package/packages/web/dist/client/assets/{gitGraphDiagram-X574FWY7-CgxJA-T8.js → gitGraphDiagram-X574FWY7-J4_JKGBH.js} +1 -1
- package/packages/web/dist/client/assets/index-BD7ptjuS.css +1 -0
- package/packages/web/dist/client/assets/{index-XTlTnQmx.js → index-Cn66jcLF.js} +7 -7
- package/packages/web/dist/client/assets/{info-A6RAGUB7-P0-o68pj.js → info-A6RAGUB7-wk6vNDP4.js} +1 -1
- package/packages/web/dist/client/assets/{infoDiagram-VRGFBTTK-DFJZNRUP.js → infoDiagram-VRGFBTTK-Zl7Uhlcj.js} +1 -1
- package/packages/web/dist/client/assets/{ishikawaDiagram-OU5B5YK6-ZkyhNd1T.js → ishikawaDiagram-OU5B5YK6-I0VVed8w.js} +1 -1
- package/packages/web/dist/client/assets/{journeyDiagram-ZHPQQLJL-DFevH8my.js → journeyDiagram-ZHPQQLJL-CLGZAy0Q.js} +1 -1
- package/packages/web/dist/client/assets/{kanban-definition-PNTS6WVX-l7e7ZZDC.js → kanban-definition-PNTS6WVX-D3Zv63YL.js} +1 -1
- package/packages/web/dist/client/assets/{line-DO_s6Ujd.js → line-C4_qzTJY.js} +1 -1
- package/packages/web/dist/client/assets/{linear-C4xH5PPc.js → linear-Dbp9FWGm.js} +1 -1
- package/packages/web/dist/client/assets/{mermaid-parser.core-nQaTP3VY.js → mermaid-parser.core-Cbd2Flfk.js} +3 -3
- package/packages/web/dist/client/assets/{mermaid.core-Cz05yTZh.js → mermaid.core-CPXk02t0.js} +4 -4
- package/packages/web/dist/client/assets/{mindmap-definition-NLK3R4M7-CHOEuHm2.js → mindmap-definition-NLK3R4M7-hcjd2vg0.js} +1 -1
- package/packages/web/dist/client/assets/{packet-AYTQ26CC-BH3ehPMo.js → packet-AYTQ26CC-CLiY7MdL.js} +1 -1
- package/packages/web/dist/client/assets/{pegDiagram-GJSIUBJH-CkWBLtad.js → pegDiagram-GJSIUBJH-Or6L-npJ.js} +1 -1
- package/packages/web/dist/client/assets/{pie-WAS4IAKB-nNVEq3dx.js → pie-WAS4IAKB-DTF5qxhB.js} +1 -1
- package/packages/web/dist/client/assets/{pieDiagram-5QR66LMP-DimUBAgN.js → pieDiagram-5QR66LMP-wDNyDsTs.js} +1 -1
- package/packages/web/dist/client/assets/{quadrantDiagram-O4NWA36T-BR0XpRGQ.js → quadrantDiagram-O4NWA36T-BL_0xWWi.js} +1 -1
- package/packages/web/dist/client/assets/{radar-RG4KPBEZ-paA-H3mb.js → radar-RG4KPBEZ-hK8uEd3E.js} +1 -1
- package/packages/web/dist/client/assets/{railroad-74A4TZTK-yEiKB3rz.js → railroad-74A4TZTK-Cj1mtGfH.js} +1 -1
- package/packages/web/dist/client/assets/railroad-abnf-HS5TGJTU-t8ibqa0P.js +1 -0
- package/packages/web/dist/client/assets/railroad-ebnf-LZEXJU2U-B4RYlcUM.js +1 -0
- package/packages/web/dist/client/assets/railroad-peg-WCYAUIDC-DFqfvrfB.js +1 -0
- package/packages/web/dist/client/assets/{railroadDiagram-XR7U4H2S--TXe6rdU.js → railroadDiagram-XR7U4H2S-BUXe7pvJ.js} +1 -1
- package/packages/web/dist/client/assets/{requirementDiagram-PLB6GJNP-DyqH36Za.js → requirementDiagram-PLB6GJNP-DBnKurFY.js} +1 -1
- package/packages/web/dist/client/assets/{sankeyDiagram-IPEJSGJF-Bg6e3BlM.js → sankeyDiagram-IPEJSGJF-BDlSxPY7.js} +1 -1
- package/packages/web/dist/client/assets/{sequenceDiagram-PO4LG4MO-ClGf85My.js → sequenceDiagram-PO4LG4MO-BcKSq_cS.js} +1 -1
- package/packages/web/dist/client/assets/{src-DF7hQfMh.js → src-kcIgRrGC.js} +1 -1
- package/packages/web/dist/client/assets/{stateDiagram-v2-GCMORJYK-BK8TpxNo.js → stateDiagram-v2-GCMORJYK-D-1tpyK1.js} +1 -1
- package/packages/web/dist/client/assets/{swimlanes-2SLR337P-DDnTIT9M.js → swimlanes-2SLR337P-edQaMeEJ.js} +1 -1
- package/packages/web/dist/client/assets/swimlanesDiagram-TC7HE7FX-vI6XtOyR.js +8 -0
- package/packages/web/dist/client/assets/{timeline-definition-EJHVYXUP-mBBbH3bk.js → timeline-definition-EJHVYXUP-BHspcgaG.js} +1 -1
- package/packages/web/dist/client/assets/{treeView-Q6P3EWNA-CTK7tRwR.js → treeView-Q6P3EWNA-Bvc71ryx.js} +1 -1
- package/packages/web/dist/client/assets/{treemap-WGGIJYW6-vOI-Ef_m.js → treemap-WGGIJYW6-CoZvoF_t.js} +1 -1
- package/packages/web/dist/client/assets/{usecaseDiagram-POWQR4AR-COcii8x-.js → usecaseDiagram-POWQR4AR-B203AiCD.js} +1 -1
- package/packages/web/dist/client/assets/{vennDiagram-UO4OBE2U-D6kmDGpM.js → vennDiagram-UO4OBE2U-Cia3spa9.js} +1 -1
- package/packages/web/dist/client/assets/{wardley-WFR3VGLG-CtE2KI9r.js → wardley-WFR3VGLG-C7qHTXAu.js} +1 -1
- package/packages/web/dist/client/assets/{wardleyDiagram-VNRHLVJA-ncxNGWnW.js → wardleyDiagram-VNRHLVJA-CK2R_SgC.js} +1 -1
- package/packages/web/dist/client/assets/{xychartDiagram-PMCCYNJV-DUvd2Qze.js → xychartDiagram-PMCCYNJV-BBLqtYJ_.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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pim-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "A batteries-included distro of Pi, accessible in your terminal, browser and Telegram.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"vite": "^8.2.2"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
80
|
-
"@earendil-works/pi-server": "0.
|
|
79
|
+
"@earendil-works/pi-coding-agent": "1.0.4",
|
|
80
|
+
"@earendil-works/pi-server": "1.0.4",
|
|
81
81
|
"diff": "^9.0.0",
|
|
82
82
|
"fzf": "^0.5.2",
|
|
83
83
|
"grammy": "^1.46.0",
|
|
@@ -3,36 +3,32 @@ import { basename, extname } from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import { SafePath } from "../shared/SafePath";
|
|
5
5
|
|
|
6
|
-
/** A file the store has taken a copy of, under a name it chose. */
|
|
7
6
|
export type StoredFile = {
|
|
8
|
-
/**
|
|
7
|
+
/** Unique within its scope. */
|
|
9
8
|
readonly id: string;
|
|
10
|
-
/** Absolute path on the server.
|
|
9
|
+
/** Absolute path on the server. */
|
|
11
10
|
readonly path: string;
|
|
12
11
|
readonly mimeType: string;
|
|
13
12
|
};
|
|
14
13
|
|
|
15
|
-
/** A file that now lives on the machine the agent runs on. */
|
|
16
14
|
export type StoredAttachment = StoredFile & {
|
|
17
|
-
/**
|
|
15
|
+
/** Set only for images up to IMAGE_BYTES_LIMIT. */
|
|
18
16
|
readonly imageBase64: string | undefined;
|
|
19
17
|
};
|
|
20
18
|
|
|
21
19
|
export type AttachmentInput = {
|
|
22
20
|
readonly bytes: ArrayBuffer;
|
|
23
21
|
readonly mimeType: string;
|
|
24
|
-
/** Client-supplied filename
|
|
22
|
+
/** Client-supplied filename; only its extension is used. */
|
|
25
23
|
readonly name?: string;
|
|
26
|
-
/**
|
|
24
|
+
/** Defaults to a random UUID. */
|
|
27
25
|
readonly stem?: string;
|
|
28
|
-
/**
|
|
26
|
+
/** Used when `name` has no extension. */
|
|
29
27
|
readonly ext?: string;
|
|
30
28
|
};
|
|
31
29
|
|
|
32
|
-
/** Above this, an image is referenced by path instead of inlined. */
|
|
33
30
|
const IMAGE_BYTES_LIMIT = 4 * 1024 * 1024;
|
|
34
31
|
|
|
35
|
-
/** Materialises client bytes onto the server's filesystem; the agent is only ever told a server path. */
|
|
36
32
|
export class AttachmentStore {
|
|
37
33
|
public constructor(private readonly root: string) {}
|
|
38
34
|
|
|
@@ -59,12 +55,11 @@ export class AttachmentStore {
|
|
|
59
55
|
};
|
|
60
56
|
}
|
|
61
57
|
|
|
62
|
-
/** Copies a file already on the agent's disk into the store so it can be served. */
|
|
63
58
|
public async storeFile(scope: string, source: string): Promise<StoredFile> {
|
|
64
59
|
const file = Bun.file(source);
|
|
65
60
|
const name = basename(source);
|
|
66
61
|
const ext = extname(name);
|
|
67
|
-
//
|
|
62
|
+
// `basename(name, ext)` keeps dotfiles like `.bashrc` named.
|
|
68
63
|
const { id, path } = await this.place(scope, basename(name, ext), ext);
|
|
69
64
|
await Bun.write(path, file);
|
|
70
65
|
return { id, path, mimeType: file.type || "application/octet-stream" };
|
|
@@ -87,7 +82,7 @@ export class AttachmentStore {
|
|
|
87
82
|
return SafePath.contain(this.root, SafePath.safeName(scope));
|
|
88
83
|
}
|
|
89
84
|
|
|
90
|
-
/**
|
|
85
|
+
/** The id is re-sanitised, so it cannot escape its scope. */
|
|
91
86
|
public locate(scope: string, id: string): string {
|
|
92
87
|
return SafePath.contain(this.scopeDir(scope), SafePath.safeName(id));
|
|
93
88
|
}
|
|
@@ -4,24 +4,22 @@ import { basename, extname } from "node:path";
|
|
|
4
4
|
import type { StoredAttachment } from "./AttachmentStore";
|
|
5
5
|
|
|
6
6
|
export type AttachmentPrompt = {
|
|
7
|
-
/** One line per file, appended to the prompt text. */
|
|
8
7
|
readonly lines: readonly string[];
|
|
9
8
|
readonly images: NonNullable<PromptOptions["images"]>;
|
|
10
9
|
};
|
|
11
10
|
|
|
12
|
-
/** One file a prompt carried, read back out of the text that carried it. */
|
|
13
11
|
export type PromptAttachment = {
|
|
14
12
|
readonly path: string;
|
|
15
13
|
readonly isImage: boolean;
|
|
16
14
|
};
|
|
17
15
|
|
|
18
16
|
export type ParsedPrompt = {
|
|
19
|
-
/** The prompt with the marker lines removed
|
|
17
|
+
/** The prompt with the marker lines removed. */
|
|
20
18
|
readonly text: string;
|
|
21
19
|
readonly files: readonly PromptAttachment[];
|
|
22
20
|
};
|
|
23
21
|
|
|
24
|
-
//
|
|
22
|
+
// Old session files carry older spellings; keep matching them.
|
|
25
23
|
const MARKER = /^\[(image )?attachment:\s*(.+)]$/i;
|
|
26
24
|
|
|
27
25
|
const STAMP = /-\d{10,}$/;
|
|
@@ -26,7 +26,7 @@ export type PimInlineExtension = {
|
|
|
26
26
|
readonly factory: ExtensionFactory;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
//
|
|
29
|
+
// Listed explicitly so the published package needs no directory scan.
|
|
30
30
|
function list(surface?: Surface): readonly PimInlineExtension[] {
|
|
31
31
|
return [
|
|
32
32
|
{ name: "apply-patch", factory: applyPatch },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const EDIT_TOOL = "edit";
|
|
2
2
|
const APPLY_PATCH_TOOL = "apply_patch";
|
|
3
3
|
|
|
4
|
-
/**
|
|
4
|
+
/** Keeps at most one of `edit`/`apply_patch` active. Returns `active` itself when nothing changes. */
|
|
5
5
|
export function computeActiveTools(
|
|
6
6
|
available: readonly string[],
|
|
7
7
|
active: readonly string[],
|
|
@@ -164,11 +164,7 @@ async function planUpdate(
|
|
|
164
164
|
): Promise<PlannedAction> {
|
|
165
165
|
const absoluteSource = Paths.resolve(hunk.path, cwd);
|
|
166
166
|
const metadata = await statPatchTarget(absoluteSource, hunk.path, "update");
|
|
167
|
-
const canonicalSource = await
|
|
168
|
-
absoluteSource,
|
|
169
|
-
hunk.path,
|
|
170
|
-
"update"
|
|
171
|
-
);
|
|
167
|
+
const canonicalSource = await realpathUpdateTarget(absoluteSource, hunk.path);
|
|
172
168
|
if (metadata.size > MAX_UPDATE_BYTES) {
|
|
173
169
|
throw new Error(
|
|
174
170
|
`Cannot update ${hunk.path}: file is too large (${metadata.size} bytes, max ${MAX_UPDATE_BYTES}). Use bash or another purpose-built tool for large-file edits.`
|
|
@@ -257,15 +253,14 @@ async function statPatchTarget(
|
|
|
257
253
|
return metadata;
|
|
258
254
|
}
|
|
259
255
|
|
|
260
|
-
async function
|
|
256
|
+
async function realpathUpdateTarget(
|
|
261
257
|
absolutePath: string,
|
|
262
|
-
displayPath: string
|
|
263
|
-
operation: "delete" | "update"
|
|
258
|
+
displayPath: string
|
|
264
259
|
): Promise<string> {
|
|
265
260
|
try {
|
|
266
261
|
return await realpath(absolutePath);
|
|
267
262
|
} catch (error) {
|
|
268
|
-
throw new Error(formatStatFailure(displayPath,
|
|
263
|
+
throw new Error(formatStatFailure(displayPath, "update", error));
|
|
269
264
|
}
|
|
270
265
|
}
|
|
271
266
|
|
|
@@ -275,23 +270,21 @@ function formatStatFailure(
|
|
|
275
270
|
error: unknown
|
|
276
271
|
): string {
|
|
277
272
|
const code = FsErrors.code(error);
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (code === "EACCES" || code === "EPERM") {
|
|
283
|
-
return `Failed to delete file ${displayPath}: permission denied.`;
|
|
284
|
-
}
|
|
285
|
-
return `Failed to delete file ${displayPath}: ${errorDetail(error)}.`;
|
|
286
|
-
}
|
|
287
|
-
|
|
273
|
+
const prefix =
|
|
274
|
+
operation === "delete"
|
|
275
|
+
? `Failed to delete file ${displayPath}`
|
|
276
|
+
: `Failed to read file to update ${displayPath}`;
|
|
288
277
|
if (code === "ENOENT") {
|
|
289
|
-
|
|
278
|
+
const hint =
|
|
279
|
+
operation === "delete"
|
|
280
|
+
? "Use glob to locate the file, or omit this delete hunk."
|
|
281
|
+
: "Use *** Add File to create a new file, or use glob to locate the existing file.";
|
|
282
|
+
return `${prefix}: file does not exist. ${hint}`;
|
|
290
283
|
}
|
|
291
284
|
if (code === "EACCES" || code === "EPERM") {
|
|
292
|
-
return
|
|
285
|
+
return `${prefix}: permission denied.`;
|
|
293
286
|
}
|
|
294
|
-
return
|
|
287
|
+
return `${prefix}: ${errorDetail(error)}.`;
|
|
295
288
|
}
|
|
296
289
|
|
|
297
290
|
function errorDetail(error: unknown): string {
|
|
@@ -352,6 +345,7 @@ function applyChunks(
|
|
|
352
345
|
readonly start: number;
|
|
353
346
|
readonly oldLen: number;
|
|
354
347
|
readonly newLines: readonly string[];
|
|
348
|
+
readonly order: number;
|
|
355
349
|
}> = [];
|
|
356
350
|
let lineIndex = 0;
|
|
357
351
|
|
|
@@ -373,11 +367,12 @@ function applyChunks(
|
|
|
373
367
|
}
|
|
374
368
|
|
|
375
369
|
if (chunk.oldLines.length === 0) {
|
|
376
|
-
const insertionIdx = originalLines.length;
|
|
377
370
|
replacements.push({
|
|
378
|
-
start:
|
|
371
|
+
start:
|
|
372
|
+
chunk.changeContext === undefined ? originalLines.length : lineIndex,
|
|
379
373
|
oldLen: 0,
|
|
380
374
|
newLines: chunk.newLines,
|
|
375
|
+
order: replacements.length,
|
|
381
376
|
});
|
|
382
377
|
continue;
|
|
383
378
|
}
|
|
@@ -416,11 +411,12 @@ function applyChunks(
|
|
|
416
411
|
start: found[0]!,
|
|
417
412
|
oldLen: pattern.length,
|
|
418
413
|
newLines: newSlice,
|
|
414
|
+
order: replacements.length,
|
|
419
415
|
});
|
|
420
416
|
lineIndex = found[0]! + pattern.length;
|
|
421
417
|
}
|
|
422
418
|
|
|
423
|
-
replacements.sort((a, b) => a.start - b.start);
|
|
419
|
+
replacements.sort((a, b) => a.start - b.start || a.order - b.order);
|
|
424
420
|
|
|
425
421
|
const lines = [...originalLines];
|
|
426
422
|
for (const { start, oldLen, newLines } of replacements.reverse()) {
|
|
@@ -4,7 +4,7 @@ const MATCHERS: ReadonlyArray<(a: string, b: string) => boolean> = [
|
|
|
4
4
|
(a, b) => a.trim() === b.trim(),
|
|
5
5
|
];
|
|
6
6
|
|
|
7
|
-
/**
|
|
7
|
+
/** Match starts of `pattern` at or after `start`, relaxing whitespace each pass. `eof` only tries the last possible position. */
|
|
8
8
|
export function seekSequenceMatches(
|
|
9
9
|
lines: readonly string[],
|
|
10
10
|
pattern: readonly string[],
|
|
@@ -4,8 +4,8 @@ type ModelLike = {
|
|
|
4
4
|
readonly id?: string;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
//
|
|
8
|
-
function
|
|
7
|
+
// Must not match GPT-named non-OpenAI models such as `eleutherai/gpt-neo`.
|
|
8
|
+
export function prefersApplyPatch(model: ModelLike | undefined): boolean {
|
|
9
9
|
const provider = (model?.provider ?? "").toLowerCase();
|
|
10
10
|
const api = (model?.api ?? "").toLowerCase();
|
|
11
11
|
const id = (model?.id ?? "").toLowerCase();
|
|
@@ -22,7 +22,3 @@ function isGptModel(model: ModelLike | undefined): boolean {
|
|
|
22
22
|
id.includes("gpt"))
|
|
23
23
|
);
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
export function prefersApplyPatch(model: ModelLike | undefined): boolean {
|
|
27
|
-
return isGptModel(model);
|
|
28
|
-
}
|
|
@@ -12,25 +12,18 @@ const END_PATCH_MARKER = "*** End Patch";
|
|
|
12
12
|
const EOF_MARKER = "*** End of File";
|
|
13
13
|
const CHANGE_CONTEXT_MARKER = "@@ ";
|
|
14
14
|
const EMPTY_CHANGE_CONTEXT_MARKER = "@@";
|
|
15
|
+
const EMPTY_CHUNK =
|
|
16
|
+
"Update hunk does not contain any context, added, or removed lines. Include at least one line starting with ' ', '+', or '-'.";
|
|
15
17
|
const MOVE_DESTINATION_REQUIRED =
|
|
16
18
|
"Invalid *** Move to directive: destination path is required.";
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
readonly message: string;
|
|
23
|
-
readonly lineNumber: number;
|
|
24
|
-
};
|
|
20
|
+
// Matches Codex's ParseError text byte for byte; GPT models recover from it.
|
|
21
|
+
function patchError(message: string): Error {
|
|
22
|
+
return new Error(`invalid patch: ${message}`);
|
|
23
|
+
}
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
switch (error.type) {
|
|
29
|
-
case "patch":
|
|
30
|
-
return `invalid patch: ${error.message}`;
|
|
31
|
-
case "hunk":
|
|
32
|
-
return `invalid hunk at line ${error.lineNumber}, ${error.message}`;
|
|
33
|
-
}
|
|
25
|
+
function hunkError(lineNumber: number, message: string): Error {
|
|
26
|
+
return new Error(`invalid hunk at line ${lineNumber}, ${message}`);
|
|
34
27
|
}
|
|
35
28
|
|
|
36
29
|
export function parsePatch(text: string): Patch {
|
|
@@ -53,26 +46,15 @@ export function parsePatch(text: string): Patch {
|
|
|
53
46
|
}
|
|
54
47
|
|
|
55
48
|
function checkBoundaries(lines: readonly string[]): void {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (first === undefined || !lines[0]!.trim().startsWith(BEGIN_PATCH_MARKER)) {
|
|
60
|
-
throw new Error(
|
|
61
|
-
formatParseError({
|
|
62
|
-
type: "patch",
|
|
63
|
-
message:
|
|
64
|
-
"The first line of the patch must be '*** Begin Patch'. Do not include Markdown fences, prose, or shell heredoc text before it.",
|
|
65
|
-
})
|
|
49
|
+
if (!lines[0]!.trim().startsWith(BEGIN_PATCH_MARKER)) {
|
|
50
|
+
throw patchError(
|
|
51
|
+
"The first line of the patch must be '*** Begin Patch'. Do not include Markdown fences, prose, or shell heredoc text before it."
|
|
66
52
|
);
|
|
67
53
|
}
|
|
68
54
|
|
|
69
|
-
if (
|
|
70
|
-
throw
|
|
71
|
-
|
|
72
|
-
type: "patch",
|
|
73
|
-
message:
|
|
74
|
-
"The last line of the patch must be '*** End Patch'. Do not include Markdown fences or trailing prose after it.",
|
|
75
|
-
})
|
|
55
|
+
if (lines.at(-1)!.trim() !== END_PATCH_MARKER) {
|
|
56
|
+
throw patchError(
|
|
57
|
+
"The last line of the patch must be '*** End Patch'. Do not include Markdown fences or trailing prose after it."
|
|
76
58
|
);
|
|
77
59
|
}
|
|
78
60
|
}
|
|
@@ -98,15 +80,11 @@ function parseOneHunk(
|
|
|
98
80
|
return parseUpdateHunk(lines, lineNumber, updatePath);
|
|
99
81
|
}
|
|
100
82
|
|
|
101
|
-
throw
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
`'${firstLine}' is not a valid hunk header. ` +
|
|
107
|
-
"Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'. " +
|
|
108
|
-
"Do not use unified-diff file headers like '---' or '+++' as hunk headers.",
|
|
109
|
-
})
|
|
83
|
+
throw hunkError(
|
|
84
|
+
lineNumber,
|
|
85
|
+
`'${firstLine}' is not a valid hunk header. ` +
|
|
86
|
+
"Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'. " +
|
|
87
|
+
"Do not use unified-diff file headers like '---' or '+++' as hunk headers."
|
|
110
88
|
);
|
|
111
89
|
}
|
|
112
90
|
|
|
@@ -126,17 +104,10 @@ function parseAddHunk(
|
|
|
126
104
|
}
|
|
127
105
|
}
|
|
128
106
|
const nextLine = lines[consumed];
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
formatParseError({
|
|
136
|
-
type: "hunk",
|
|
137
|
-
lineNumber: lineNumber + consumed,
|
|
138
|
-
message: `Invalid Add File body: '${nextLine}' must start with '+'. Added file content lines must start with '+'.`,
|
|
139
|
-
})
|
|
107
|
+
if (nextLine !== undefined && !nextLine.trim().startsWith("*")) {
|
|
108
|
+
throw hunkError(
|
|
109
|
+
lineNumber + consumed,
|
|
110
|
+
`Invalid Add File body: '${nextLine}' must start with '+'. Added file content lines must start with '+'.`
|
|
140
111
|
);
|
|
141
112
|
}
|
|
142
113
|
return {
|
|
@@ -151,17 +122,10 @@ function parseDeleteHunk(
|
|
|
151
122
|
deletePath: string
|
|
152
123
|
): { readonly hunk: Hunk; readonly consumed: number } {
|
|
153
124
|
const nextLine = lines[1];
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
) {
|
|
159
|
-
throw new Error(
|
|
160
|
-
formatParseError({
|
|
161
|
-
type: "hunk",
|
|
162
|
-
lineNumber: lineNumber + 1,
|
|
163
|
-
message: `Delete File hunks must not contain content lines, got: '${nextLine}'.`,
|
|
164
|
-
})
|
|
125
|
+
if (nextLine !== undefined && !nextLine.trim().startsWith("*")) {
|
|
126
|
+
throw hunkError(
|
|
127
|
+
lineNumber + 1,
|
|
128
|
+
`Delete File hunks must not contain content lines, got: '${nextLine}'.`
|
|
165
129
|
);
|
|
166
130
|
}
|
|
167
131
|
return {
|
|
@@ -182,46 +146,23 @@ function parseUpdateHunk(
|
|
|
182
146
|
const moveLine = remaining[0]?.trim();
|
|
183
147
|
if (moveLine?.startsWith(MOVE_TO_MARKER)) {
|
|
184
148
|
const rawMovePath = moveLine.slice(MOVE_TO_MARKER.length);
|
|
185
|
-
if (rawMovePath.length
|
|
186
|
-
throw
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
lineNumber: lineNumber + consumed,
|
|
190
|
-
message: MOVE_DESTINATION_REQUIRED,
|
|
191
|
-
})
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
if (!rawMovePath.startsWith(" ")) {
|
|
195
|
-
throw new Error(
|
|
196
|
-
formatParseError({
|
|
197
|
-
type: "hunk",
|
|
198
|
-
lineNumber: lineNumber + consumed,
|
|
199
|
-
message: `Invalid *** Move to directive: use '*** Move to: {path}'.`,
|
|
200
|
-
})
|
|
149
|
+
if (rawMovePath.length > 0 && !rawMovePath.startsWith(" ")) {
|
|
150
|
+
throw hunkError(
|
|
151
|
+
lineNumber + consumed,
|
|
152
|
+
"Invalid *** Move to directive: use '*** Move to: {path}'."
|
|
201
153
|
);
|
|
202
154
|
}
|
|
203
155
|
if (cleanPath(rawMovePath).length === 0) {
|
|
204
|
-
throw
|
|
205
|
-
formatParseError({
|
|
206
|
-
type: "hunk",
|
|
207
|
-
lineNumber: lineNumber + consumed,
|
|
208
|
-
message: MOVE_DESTINATION_REQUIRED,
|
|
209
|
-
})
|
|
210
|
-
);
|
|
156
|
+
throw hunkError(lineNumber + consumed, MOVE_DESTINATION_REQUIRED);
|
|
211
157
|
}
|
|
212
|
-
movePath = rawMovePath;
|
|
213
|
-
} else if (moveLine?.startsWith("*** Move")) {
|
|
214
|
-
throw new Error(
|
|
215
|
-
formatParseError({
|
|
216
|
-
type: "hunk",
|
|
217
|
-
lineNumber: lineNumber + consumed,
|
|
218
|
-
message: `Invalid move directive '${moveLine}'. Use '*** Move to: {path}'.`,
|
|
219
|
-
})
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
if (movePath !== undefined) {
|
|
158
|
+
movePath = cleanPath(rawMovePath);
|
|
223
159
|
remaining = remaining.slice(1);
|
|
224
160
|
consumed += 1;
|
|
161
|
+
} else if (moveLine?.startsWith("*** Move")) {
|
|
162
|
+
throw hunkError(
|
|
163
|
+
lineNumber + consumed,
|
|
164
|
+
`Invalid move directive '${moveLine}'. Use '*** Move to: {path}'.`
|
|
165
|
+
);
|
|
225
166
|
}
|
|
226
167
|
|
|
227
168
|
const chunks: UpdateChunk[] = [];
|
|
@@ -246,12 +187,9 @@ function parseUpdateHunk(
|
|
|
246
187
|
}
|
|
247
188
|
|
|
248
189
|
if (chunks.length === 0 && movePath === undefined) {
|
|
249
|
-
throw
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
lineNumber,
|
|
253
|
-
message: `Update file hunk for path '${cleanPath(updatePath)}' is empty. Include @@ plus at least one context, added, or removed line, or add *** Move to for a pure rename.`,
|
|
254
|
-
})
|
|
190
|
+
throw hunkError(
|
|
191
|
+
lineNumber,
|
|
192
|
+
`Update file hunk for path '${cleanPath(updatePath)}' is empty. Include @@ plus at least one context, added, or removed line, or add *** Move to for a pure rename.`
|
|
255
193
|
);
|
|
256
194
|
}
|
|
257
195
|
|
|
@@ -259,7 +197,7 @@ function parseUpdateHunk(
|
|
|
259
197
|
hunk: {
|
|
260
198
|
kind: "update",
|
|
261
199
|
path: cleanPath(updatePath),
|
|
262
|
-
movePath
|
|
200
|
+
movePath,
|
|
263
201
|
chunks,
|
|
264
202
|
},
|
|
265
203
|
consumed,
|
|
@@ -271,41 +209,21 @@ function parseUpdateChunk(
|
|
|
271
209
|
lineNumber: number,
|
|
272
210
|
allowMissingContext: boolean
|
|
273
211
|
): { readonly chunk: UpdateChunk; readonly consumed: number } {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
changeContext = ctx;
|
|
284
|
-
startIndex = 1;
|
|
285
|
-
} else {
|
|
286
|
-
if (!allowMissingContext) {
|
|
287
|
-
throw new Error(
|
|
288
|
-
formatParseError({
|
|
289
|
-
type: "hunk",
|
|
290
|
-
lineNumber,
|
|
291
|
-
message: `Expected update hunk to start with a @@ context marker, got: '${lines[0]}'. Start each additional edit chunk with @@ or @@ followed by nearby context.`,
|
|
292
|
-
})
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
changeContext = undefined;
|
|
296
|
-
startIndex = 0;
|
|
297
|
-
}
|
|
212
|
+
const first = lines[0]!;
|
|
213
|
+
const hasMarker =
|
|
214
|
+
first === EMPTY_CHANGE_CONTEXT_MARKER ||
|
|
215
|
+
first.startsWith(CHANGE_CONTEXT_MARKER);
|
|
216
|
+
if (!hasMarker && !allowMissingContext) {
|
|
217
|
+
throw hunkError(
|
|
218
|
+
lineNumber,
|
|
219
|
+
`Expected update hunk to start with a @@ context marker, got: '${first}'. Start each additional edit chunk with @@ or @@ followed by nearby context.`
|
|
220
|
+
);
|
|
298
221
|
}
|
|
222
|
+
const changeContext = stripPrefix(first, CHANGE_CONTEXT_MARKER);
|
|
223
|
+
const startIndex = hasMarker ? 1 : 0;
|
|
299
224
|
|
|
300
225
|
if (startIndex >= lines.length) {
|
|
301
|
-
throw
|
|
302
|
-
formatParseError({
|
|
303
|
-
type: "hunk",
|
|
304
|
-
lineNumber,
|
|
305
|
-
message:
|
|
306
|
-
"Update hunk does not contain any context, added, or removed lines. Include at least one line starting with ' ', '+', or '-'.",
|
|
307
|
-
})
|
|
308
|
-
);
|
|
226
|
+
throw hunkError(lineNumber, EMPTY_CHUNK);
|
|
309
227
|
}
|
|
310
228
|
|
|
311
229
|
const oldLines: string[] = [];
|
|
@@ -316,14 +234,7 @@ function parseUpdateChunk(
|
|
|
316
234
|
for (const line of lines.slice(startIndex)) {
|
|
317
235
|
if (line === EOF_MARKER) {
|
|
318
236
|
if (parsed === 0) {
|
|
319
|
-
throw
|
|
320
|
-
formatParseError({
|
|
321
|
-
type: "hunk",
|
|
322
|
-
lineNumber,
|
|
323
|
-
message:
|
|
324
|
-
"Update hunk does not contain any context, added, or removed lines. Include at least one line starting with ' ', '+', or '-'.",
|
|
325
|
-
})
|
|
326
|
-
);
|
|
237
|
+
throw hunkError(lineNumber, EMPTY_CHUNK);
|
|
327
238
|
}
|
|
328
239
|
isEndOfFile = true;
|
|
329
240
|
parsed += 1;
|
|
@@ -343,15 +254,11 @@ function parseUpdateChunk(
|
|
|
343
254
|
oldLines.push(line.slice(1));
|
|
344
255
|
} else {
|
|
345
256
|
if (parsed === 0) {
|
|
346
|
-
throw
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
`Unexpected line found in update hunk: '${line}'. ` +
|
|
352
|
-
"Every line should start with ' ' (context line), '+' (added line), or '-' (removed line). " +
|
|
353
|
-
"Unchanged context lines must be prefixed with a single space.",
|
|
354
|
-
})
|
|
257
|
+
throw hunkError(
|
|
258
|
+
lineNumber,
|
|
259
|
+
`Unexpected line found in update hunk: '${line}'. ` +
|
|
260
|
+
"Every line should start with ' ' (context line), '+' (added line), or '-' (removed line). " +
|
|
261
|
+
"Unchanged context lines must be prefixed with a single space."
|
|
355
262
|
);
|
|
356
263
|
}
|
|
357
264
|
break;
|
|
@@ -368,12 +275,3 @@ function parseUpdateChunk(
|
|
|
368
275
|
function stripPrefix(value: string, prefix: string): string | undefined {
|
|
369
276
|
return value.startsWith(prefix) ? value.slice(prefix.length) : undefined;
|
|
370
277
|
}
|
|
371
|
-
|
|
372
|
-
function isHunkHeader(line: string): boolean {
|
|
373
|
-
const trimmed = line.trim();
|
|
374
|
-
return (
|
|
375
|
-
trimmed.startsWith(ADD_FILE_MARKER) ||
|
|
376
|
-
trimmed.startsWith(DELETE_FILE_MARKER) ||
|
|
377
|
-
trimmed.startsWith(UPDATE_FILE_MARKER)
|
|
378
|
-
);
|
|
379
|
-
}
|
|
@@ -10,7 +10,6 @@ export type ApplyPatchInput = Static<typeof applyPatchSchema>;
|
|
|
10
10
|
|
|
11
11
|
const ALIAS_KEYS = ["patch", "patchText", "patch_text"] as const;
|
|
12
12
|
|
|
13
|
-
/** Normalize a bare string or a `patch`/`patchText`/`patch_text` key to `{input}`, dropping the alias. */
|
|
14
13
|
export function prepareApplyPatchArguments(rawArgs: unknown): ApplyPatchInput {
|
|
15
14
|
if (typeof rawArgs === "string") {
|
|
16
15
|
return { input: rawArgs };
|
|
@@ -33,7 +33,7 @@ function limitBytes(): number | null {
|
|
|
33
33
|
return Math.floor(Number(match[1]) * UNITS[unit]);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
/** Whether
|
|
36
|
+
/** Whether MemoryMax is enforced; without memory controller delegation systemd silently ignores it. */
|
|
37
37
|
async function probe(): Promise<boolean> {
|
|
38
38
|
if (process.platform !== "linux") {
|
|
39
39
|
return false;
|
|
@@ -65,7 +65,7 @@ async function probe(): Promise<boolean> {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
/** The user
|
|
68
|
+
/** The user service pim runs in, so command scopes stop with it. */
|
|
69
69
|
async function findOwner(): Promise<string | null> {
|
|
70
70
|
try {
|
|
71
71
|
const cgroup = await readFile("/proc/self/cgroup", "utf8");
|
|
@@ -82,7 +82,7 @@ async function findOwner(): Promise<string | null> {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
/**
|
|
85
|
+
/** systemd-run argv prefix for a memory-capped scope; null when capping is off or unsupported. */
|
|
86
86
|
async function scope(): Promise<MemoryScope | null> {
|
|
87
87
|
const limit = limitBytes();
|
|
88
88
|
if (limit === null || !(await (supported ??= probe()))) {
|
|
@@ -104,6 +104,8 @@ async function scope(): Promise<MemoryScope | null> {
|
|
|
104
104
|
`--property=MemoryMax=${limit}`,
|
|
105
105
|
"--property=MemorySwapMax=0",
|
|
106
106
|
"--property=OOMPolicy=kill",
|
|
107
|
+
// The kernel's group kill races systemd's OOM stop; both must SIGKILL so run.ts can tell.
|
|
108
|
+
"--property=KillSignal=SIGKILL",
|
|
107
109
|
...(bindTo
|
|
108
110
|
? [`--property=BindsTo=${bindTo}`, `--property=After=${bindTo}`]
|
|
109
111
|
: []),
|
|
@@ -120,7 +122,6 @@ async function systemctl(args: readonly string[]): Promise<void> {
|
|
|
120
122
|
}).exited;
|
|
121
123
|
}
|
|
122
124
|
|
|
123
|
-
/** Ends whatever of a killed command is still in its scope, including a scope systemd never saw empty. */
|
|
124
125
|
async function stop(unit: string): Promise<void> {
|
|
125
126
|
await systemctl(["--no-block", "stop", unit]);
|
|
126
127
|
}
|