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
|
@@ -27,7 +27,7 @@ export type ReadRange = {
|
|
|
27
27
|
readonly end?: number;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
type ReadTextDetails = {
|
|
31
31
|
readonly kind: "text";
|
|
32
32
|
readonly absolutePath: string;
|
|
33
33
|
readonly totalLines: number;
|
|
@@ -42,7 +42,7 @@ export type ReadTextDetails = {
|
|
|
42
42
|
export type ReadImageDetails = ImageDetails & {
|
|
43
43
|
readonly kind: "image";
|
|
44
44
|
readonly absolutePath: string;
|
|
45
|
-
/**
|
|
45
|
+
/** Only a note was sent; the image went out earlier. */
|
|
46
46
|
readonly deduped?: boolean;
|
|
47
47
|
};
|
|
48
48
|
|
|
@@ -28,7 +28,7 @@ export function formatCallTitle(prompt: string | undefined): string {
|
|
|
28
28
|
return (prompt ?? "...").split(/\r?\n/u)[0]?.trim() || "...";
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
/** The
|
|
31
|
+
/** The summary as plain text, for streaming updates. */
|
|
32
32
|
export function formatTopLine(details: SubagentDetails): string {
|
|
33
33
|
return summarySpans(details, details.stopReason === undefined)
|
|
34
34
|
.map((span) => span.text)
|
|
@@ -57,7 +57,7 @@ function summarySpans(
|
|
|
57
57
|
details: SubagentDetails,
|
|
58
58
|
isPartial: boolean
|
|
59
59
|
): readonly Span[] {
|
|
60
|
-
//
|
|
60
|
+
// pi empties `details` on failure, and old sessions lack usage.
|
|
61
61
|
if (details.usage === undefined) {
|
|
62
62
|
return [];
|
|
63
63
|
}
|
|
@@ -20,9 +20,8 @@ import { MessageText } from "../../session/MessageText";
|
|
|
20
20
|
import { CoreExtensions } from "../CoreExtensions";
|
|
21
21
|
import { formatTopLine } from "./render";
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const PER_TASK_OUTPUT_CAP = 32 * 1024;
|
|
24
|
+
const SUBAGENT_TOOL_NAME = "subagent";
|
|
26
25
|
export const UPDATE_INTERVAL_MS = 100;
|
|
27
26
|
|
|
28
27
|
const inSubagent = new AsyncLocalStorage<true>();
|
|
@@ -38,7 +37,6 @@ export type SubagentUsage = {
|
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
export type SubagentSnapshot = {
|
|
41
|
-
/** The child's session id, for a log reader; a transcript is found from the call id, not this. */
|
|
42
40
|
readonly sessionId: string | undefined;
|
|
43
41
|
readonly usage: SubagentUsage;
|
|
44
42
|
readonly stopReason: string | undefined;
|
|
@@ -47,7 +45,7 @@ export type SubagentSnapshot = {
|
|
|
47
45
|
readonly contextWindow: number | undefined;
|
|
48
46
|
};
|
|
49
47
|
|
|
50
|
-
/** `returnedOutput` is the capped
|
|
48
|
+
/** `returnedOutput` is the capped last message; `fullOutput` is every message. */
|
|
51
49
|
export type SubagentDetails = SubagentSnapshot & {
|
|
52
50
|
readonly returnedOutput: string;
|
|
53
51
|
readonly fullOutput: string;
|
|
@@ -67,9 +65,9 @@ export type SubagentSession = {
|
|
|
67
65
|
|
|
68
66
|
export type SubagentSessionSpec = {
|
|
69
67
|
readonly activeToolNames?: readonly string[];
|
|
70
|
-
/**
|
|
68
|
+
/** Unset falls back to pi's settings, not the parent's level. */
|
|
71
69
|
readonly thinkingLevel?: ThinkingLevel;
|
|
72
|
-
/**
|
|
70
|
+
/** Names the child's log file. */
|
|
73
71
|
readonly callId?: string;
|
|
74
72
|
};
|
|
75
73
|
|
|
@@ -90,7 +88,7 @@ export function childToolNames(
|
|
|
90
88
|
return activeToolNames.filter((name) => name !== SUBAGENT_TOOL_NAME);
|
|
91
89
|
}
|
|
92
90
|
|
|
93
|
-
// The child inherits no registrations
|
|
91
|
+
// The child inherits no registrations; without these its `tools` allowlist drops every pim tool.
|
|
94
92
|
export function childLoaderOptions(cwd: string): {
|
|
95
93
|
readonly cwd: string;
|
|
96
94
|
readonly agentDir: string;
|
|
@@ -103,7 +101,7 @@ export function childLoaderOptions(cwd: string): {
|
|
|
103
101
|
};
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
|
|
104
|
+
async function createSdkSubagentSession(
|
|
107
105
|
parentCtx: ExtensionContext,
|
|
108
106
|
spec: SubagentSessionSpec = {}
|
|
109
107
|
): Promise<SubagentSession> {
|
|
@@ -125,7 +123,7 @@ export async function createSdkSubagentSession(
|
|
|
125
123
|
return session;
|
|
126
124
|
}
|
|
127
125
|
|
|
128
|
-
// `open`, not `create
|
|
126
|
+
// `open`, not `create`, so the log path is derived from the parent session id and call id.
|
|
129
127
|
async function childSessionManager(
|
|
130
128
|
parentCtx: ExtensionContext,
|
|
131
129
|
callId: string | undefined
|
|
@@ -279,7 +277,6 @@ export class SubagentEventCapture {
|
|
|
279
277
|
this.emitUpdate();
|
|
280
278
|
}
|
|
281
279
|
|
|
282
|
-
/** Drops a throttled update still in flight once the run is over. */
|
|
283
280
|
public dispose(): void {
|
|
284
281
|
this.cancelPending();
|
|
285
282
|
}
|
|
@@ -295,7 +292,7 @@ export class SubagentEventCapture {
|
|
|
295
292
|
};
|
|
296
293
|
}
|
|
297
294
|
|
|
298
|
-
/**
|
|
295
|
+
/** All assistant messages so far, including one still streaming. */
|
|
299
296
|
public narration(): string {
|
|
300
297
|
const said =
|
|
301
298
|
this.pendingText === ""
|
|
@@ -358,15 +355,7 @@ export class SubagentEventCapture {
|
|
|
358
355
|
}
|
|
359
356
|
}
|
|
360
357
|
|
|
361
|
-
type MutableUsage = {
|
|
362
|
-
input: number;
|
|
363
|
-
output: number;
|
|
364
|
-
cacheRead: number;
|
|
365
|
-
cacheWrite: number;
|
|
366
|
-
cost: number;
|
|
367
|
-
turns: number;
|
|
368
|
-
contextTokens: number | undefined;
|
|
369
|
-
};
|
|
358
|
+
type MutableUsage = { -readonly [K in keyof SubagentUsage]: SubagentUsage[K] };
|
|
370
359
|
|
|
371
360
|
export type OutputCapResult = {
|
|
372
361
|
readonly text: string;
|
|
@@ -15,8 +15,7 @@ const DATETIME_MESSAGE_TYPE = "pim-datetime";
|
|
|
15
15
|
|
|
16
16
|
export default function (surface?: Surface): ExtensionFactory {
|
|
17
17
|
return (pi: ExtensionAPI): void => {
|
|
18
|
-
//
|
|
19
|
-
// behind the user's message.
|
|
18
|
+
// `before_agent_start` could only append after the user's message.
|
|
20
19
|
pi.on("input", () => {
|
|
21
20
|
pi.sendMessage(
|
|
22
21
|
{
|
|
@@ -78,7 +78,7 @@ export function buildEnvironment(opts: EnvironmentOptions): string {
|
|
|
78
78
|
].join("\n");
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/**
|
|
81
|
+
/** Empty makes pi omit the section. */
|
|
82
82
|
export function buildFormatting(surface: Surface | undefined): string {
|
|
83
83
|
return surface === undefined ? "" : FORMATTING[surface];
|
|
84
84
|
}
|
|
@@ -110,8 +110,6 @@ function computeOs(options: OsDescriptionOptions): string {
|
|
|
110
110
|
return undefined;
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
|
-
const unixName = (): string | undefined => runCommand(["uname", "-sr"]);
|
|
114
|
-
|
|
115
113
|
if (platform === "linux") {
|
|
116
114
|
const osRelease = runCommand(["cat", "/etc/os-release"]);
|
|
117
115
|
if (osRelease) {
|
|
@@ -147,7 +145,7 @@ function computeOs(options: OsDescriptionOptions): string {
|
|
|
147
145
|
return ver?.replace(/\s+/g, " ").trim() || platform;
|
|
148
146
|
}
|
|
149
147
|
|
|
150
|
-
return
|
|
148
|
+
return runCommand(["uname", "-sr"]) ?? platform;
|
|
151
149
|
}
|
|
152
150
|
|
|
153
151
|
type FieldParser = (line: string) => readonly [string, string] | undefined;
|
|
@@ -47,10 +47,7 @@ function inProgressSection(items: readonly TodoItem[]): readonly ViewBlock[] {
|
|
|
47
47
|
];
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
items: readonly TodoItem[],
|
|
52
|
-
theme: Theme
|
|
53
|
-
): string {
|
|
50
|
+
function formatWidgetTitle(items: readonly TodoItem[], theme: Theme): string {
|
|
54
51
|
const total = theme.bold(Format.count(items.length, "todo"));
|
|
55
52
|
const summary = formatStatusSummary(items);
|
|
56
53
|
return summary ? `${total} (${summary})` : total;
|
|
@@ -14,7 +14,6 @@ export type FormatChecklistOptions = {
|
|
|
14
14
|
readonly activeOnly?: boolean;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
/** Identity key for the per-session state slot. */
|
|
18
17
|
export type TodoSessionKey = ExtensionContext["sessionManager"];
|
|
19
18
|
|
|
20
19
|
const itemsBySession = new WeakMap<TodoSessionKey, TodoItem[]>();
|
|
@@ -67,7 +66,7 @@ export function hasActiveItems(items: readonly TodoItem[]): boolean {
|
|
|
67
66
|
return items.some(isActive);
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
|
|
69
|
+
function summarizeItems(items: readonly TodoItem[]): TodoSummary {
|
|
71
70
|
const summary: TodoSummary = {
|
|
72
71
|
pending: 0,
|
|
73
72
|
in_progress: 0,
|
|
@@ -129,32 +128,26 @@ function findLatestTodoItems(branch: readonly unknown[]): TodoItem[] {
|
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
function extractTodoItems(entry: unknown): TodoItem[] | undefined {
|
|
131
|
+
const holder = todoHolder(entry);
|
|
132
|
+
return isRecord(holder) && Array.isArray(holder.todos)
|
|
133
|
+
? normalizeUnknownItems(holder.todos)
|
|
134
|
+
: undefined;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** The todo tool result's details, or a compaction checkpoint's data. */
|
|
138
|
+
function todoHolder(entry: unknown): unknown {
|
|
132
139
|
if (!isRecord(entry)) {
|
|
133
140
|
return undefined;
|
|
134
141
|
}
|
|
135
|
-
if (entry.type === "message") {
|
|
136
|
-
const message = entry.message;
|
|
137
|
-
if (
|
|
138
|
-
!isRecord(message) ||
|
|
139
|
-
message.role !== "toolResult" ||
|
|
140
|
-
message.toolName !== "todo"
|
|
141
|
-
) {
|
|
142
|
-
return undefined;
|
|
143
|
-
}
|
|
144
|
-
const details = message.details;
|
|
145
|
-
if (!isRecord(details) || !Array.isArray(details.todos)) {
|
|
146
|
-
return undefined;
|
|
147
|
-
}
|
|
148
|
-
return normalizeUnknownItems(details.todos);
|
|
149
|
-
}
|
|
150
142
|
if (entry.type === "custom" && entry.customType === TODO_STATE_CUSTOM_TYPE) {
|
|
151
|
-
|
|
152
|
-
if (!isRecord(data) || !Array.isArray(data.todos)) {
|
|
153
|
-
return undefined;
|
|
154
|
-
}
|
|
155
|
-
return normalizeUnknownItems(data.todos);
|
|
143
|
+
return entry.data;
|
|
156
144
|
}
|
|
157
|
-
|
|
145
|
+
const message = entry.type === "message" ? entry.message : undefined;
|
|
146
|
+
return isRecord(message) &&
|
|
147
|
+
message.role === "toolResult" &&
|
|
148
|
+
message.toolName === "todo"
|
|
149
|
+
? message.details
|
|
150
|
+
: undefined;
|
|
158
151
|
}
|
|
159
152
|
|
|
160
153
|
function normalizeUnknownItems(items: readonly unknown[]): TodoItem[] {
|
|
@@ -155,17 +155,9 @@ function requiredString(value: unknown, name: string): string {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
function optionalString(value: unknown, name: string): string | undefined {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (typeof value !== "string") {
|
|
163
|
-
throw new JinaReaderClientError(
|
|
164
|
-
`Response contained invalid payload: expected string ${name}.`
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return value;
|
|
158
|
+
return value === undefined || value === null
|
|
159
|
+
? undefined
|
|
160
|
+
: requiredString(value, name);
|
|
169
161
|
}
|
|
170
162
|
|
|
171
163
|
function stringifyErrorData(data: unknown): string {
|
|
@@ -171,9 +171,7 @@ function readSnapshot(value: unknown): WebViewSnapshot {
|
|
|
171
171
|
function safeClose(view: WebViewLike): void {
|
|
172
172
|
try {
|
|
173
173
|
view.close();
|
|
174
|
-
} catch {
|
|
175
|
-
// close() throws if already closed.
|
|
176
|
-
}
|
|
174
|
+
} catch {}
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
function defaultFactory(): WebViewLike {
|
|
@@ -9,7 +9,7 @@ import type { JinaReaderClient } from "./JinaReaderClient";
|
|
|
9
9
|
import {
|
|
10
10
|
WEB_FETCH_INLINE_BYTES,
|
|
11
11
|
type WebFetchFormat,
|
|
12
|
-
type
|
|
12
|
+
type WebFetchPageDetails,
|
|
13
13
|
} from "./schema";
|
|
14
14
|
import type { WebViewFetchClient } from "./WebViewFetchClient";
|
|
15
15
|
|
|
@@ -19,16 +19,8 @@ export type WebFetchPage = {
|
|
|
19
19
|
readonly content: string;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
export type WebFetchPageOutcome = {
|
|
23
|
-
readonly kind: "page";
|
|
22
|
+
export type WebFetchPageOutcome = WebFetchPageDetails & {
|
|
24
23
|
readonly text: string;
|
|
25
|
-
readonly title: string;
|
|
26
|
-
readonly url: string;
|
|
27
|
-
readonly format: WebFetchResolvedFormat;
|
|
28
|
-
readonly returnedBytes: number;
|
|
29
|
-
readonly totalBytes: number;
|
|
30
|
-
readonly truncated: boolean;
|
|
31
|
-
readonly path: string | null;
|
|
32
24
|
};
|
|
33
25
|
|
|
34
26
|
export type WebFetchOutcome = WebFetchPageOutcome | WebFetchImageOutcome;
|
|
@@ -73,7 +65,7 @@ export function validatePublicUrl(value: string): string {
|
|
|
73
65
|
|
|
74
66
|
export async function formatOutcome(
|
|
75
67
|
page: WebFetchPage,
|
|
76
|
-
format:
|
|
68
|
+
format: WebFetchFormat
|
|
77
69
|
): Promise<WebFetchPageOutcome> {
|
|
78
70
|
const { body, returnedBytes, totalBytes, truncated } =
|
|
79
71
|
OutputBudget.truncateUtf8(page.content, WEB_FETCH_INLINE_BYTES);
|
|
@@ -120,7 +112,7 @@ export type ExecuteFetchInput = {
|
|
|
120
112
|
readonly url: string;
|
|
121
113
|
readonly format: WebFetchFormat;
|
|
122
114
|
readonly signal?: AbortSignal;
|
|
123
|
-
/**
|
|
115
|
+
/** Used only by the image probe. */
|
|
124
116
|
readonly fetch?: HttpFetch;
|
|
125
117
|
};
|
|
126
118
|
|
|
@@ -20,7 +20,7 @@ const TIMEOUT_MS = 20_000;
|
|
|
20
20
|
|
|
21
21
|
const IMAGE_CONTENT_TYPE = /^image\//iu;
|
|
22
22
|
|
|
23
|
-
/**
|
|
23
|
+
/** Null when the URL does not serve an image. */
|
|
24
24
|
export async function fetchImage(
|
|
25
25
|
input: ImageFetchInput
|
|
26
26
|
): Promise<NormalisedImage | null> {
|
|
@@ -49,7 +49,6 @@ export function imageContent(
|
|
|
49
49
|
return [...Images.contentOf(image, Images.noteOf(image)), ...footer];
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/** The fetch succeeded and the intent was ambiguous, so the model is told what it got, not refused. */
|
|
53
52
|
export function noVisionNote(url: string, image: NormalisedImage): string {
|
|
54
53
|
const saved = image.cachePath === null ? "" : `, saved to ${image.cachePath}`;
|
|
55
54
|
return Images.noVisionNote(
|
|
@@ -72,7 +71,7 @@ export function imageDetails(
|
|
|
72
71
|
};
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
/** A response whose
|
|
74
|
+
/** A response whose headers claim an image; the bytes are sniffed later. */
|
|
76
75
|
async function declaredImage(input: ImageFetchInput): Promise<Response | null> {
|
|
77
76
|
let response: Response;
|
|
78
77
|
|
|
@@ -105,7 +104,7 @@ async function declaredImage(input: ImageFetchInput): Promise<Response | null> {
|
|
|
105
104
|
return response;
|
|
106
105
|
}
|
|
107
106
|
|
|
108
|
-
/** Stops
|
|
107
|
+
/** Stops early on oversize or on bytes that don't sniff as an image. */
|
|
109
108
|
async function readCapped(
|
|
110
109
|
response: Response,
|
|
111
110
|
url: string
|
|
@@ -64,19 +64,8 @@ export default function (pi: ExtensionAPI): void {
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
details: {
|
|
70
|
-
kind: "page",
|
|
71
|
-
url: outcome.url,
|
|
72
|
-
title: outcome.title,
|
|
73
|
-
format: outcome.format,
|
|
74
|
-
returnedBytes: outcome.returnedBytes,
|
|
75
|
-
totalBytes: outcome.totalBytes,
|
|
76
|
-
truncated: outcome.truncated,
|
|
77
|
-
path: outcome.path,
|
|
78
|
-
},
|
|
79
|
-
};
|
|
67
|
+
const { text, ...details } = outcome;
|
|
68
|
+
return { content: [{ type: "text", text }], details };
|
|
80
69
|
},
|
|
81
70
|
toViewModel: webFetchView,
|
|
82
71
|
});
|
|
@@ -9,14 +9,13 @@ import type {
|
|
|
9
9
|
WebFetchFormat,
|
|
10
10
|
WebFetchImageDetails,
|
|
11
11
|
WebFetchInput,
|
|
12
|
-
WebFetchResolvedFormat,
|
|
13
12
|
webFetchSchema,
|
|
14
13
|
} from "./schema";
|
|
15
14
|
|
|
16
15
|
type WebFetchViewInput = ToolViewInput<typeof webFetchSchema, WebFetchDetails>;
|
|
17
16
|
|
|
18
17
|
type TitleOutcome = {
|
|
19
|
-
readonly format:
|
|
18
|
+
readonly format: WebFetchFormat;
|
|
20
19
|
readonly totalBytes: number;
|
|
21
20
|
};
|
|
22
21
|
|
|
@@ -41,7 +40,7 @@ export function webFetchView({ args, result }: WebFetchViewInput): ToolView {
|
|
|
41
40
|
};
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
/**
|
|
43
|
+
/** Untagged (legacy) details are pages. */
|
|
45
44
|
function imageDetailsOf(
|
|
46
45
|
details: WebFetchDetails | undefined
|
|
47
46
|
): WebFetchImageDetails | undefined {
|
|
@@ -95,6 +94,6 @@ function formatDetail(
|
|
|
95
94
|
: `${Format.bytesCompact(outcome.totalBytes)} ${label}`;
|
|
96
95
|
}
|
|
97
96
|
|
|
98
|
-
function formatLabel(format:
|
|
97
|
+
function formatLabel(format: WebFetchFormat): string {
|
|
99
98
|
return format === "html" ? "HTML" : "Markdown";
|
|
100
99
|
}
|
|
@@ -6,7 +6,6 @@ export const WEB_FETCH_INLINE_BYTES = 32 * 1024;
|
|
|
6
6
|
|
|
7
7
|
export const FETCH_FORMATS = ["markdown", "html"] as const;
|
|
8
8
|
export type WebFetchFormat = (typeof FETCH_FORMATS)[number];
|
|
9
|
-
export type WebFetchResolvedFormat = WebFetchFormat;
|
|
10
9
|
|
|
11
10
|
export const webFetchSchema = Type.Object({
|
|
12
11
|
url: Type.String({
|
|
@@ -27,7 +26,7 @@ export type WebFetchPageDetails = {
|
|
|
27
26
|
readonly kind: "page";
|
|
28
27
|
readonly url: string;
|
|
29
28
|
readonly title: string;
|
|
30
|
-
readonly format:
|
|
29
|
+
readonly format: WebFetchFormat;
|
|
31
30
|
readonly returnedBytes: number;
|
|
32
31
|
readonly totalBytes: number;
|
|
33
32
|
readonly truncated: boolean;
|
|
@@ -37,9 +36,9 @@ export type WebFetchPageDetails = {
|
|
|
37
36
|
export type WebFetchImageDetails = ImageDetails & {
|
|
38
37
|
readonly kind: "image";
|
|
39
38
|
readonly url: string;
|
|
40
|
-
/**
|
|
39
|
+
/** Null when the cache write failed. */
|
|
41
40
|
readonly path: string | null;
|
|
42
|
-
/**
|
|
41
|
+
/** Not sent because the model has no vision input. */
|
|
43
42
|
readonly withheld: boolean;
|
|
44
43
|
};
|
|
45
44
|
|
|
@@ -19,6 +19,8 @@ type ExaSearchInput = {
|
|
|
19
19
|
readonly signal?: AbortSignal;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
type ResultObject = Readonly<Record<string, unknown>>;
|
|
23
|
+
|
|
22
24
|
class ExaSearchError extends Error {
|
|
23
25
|
public constructor(message: string) {
|
|
24
26
|
super(message);
|
|
@@ -28,7 +30,7 @@ class ExaSearchError extends Error {
|
|
|
28
30
|
|
|
29
31
|
const defaultEndpoint = "https://mcp.exa.ai/mcp";
|
|
30
32
|
const toolName = "web_search_exa";
|
|
31
|
-
// Stay under the keyless
|
|
33
|
+
// Stay under the keyless 2 req/s limit so a 429 means the daily cap.
|
|
32
34
|
const maxRequestsPerWindow = 2;
|
|
33
35
|
const windowMs = 1100;
|
|
34
36
|
|
|
@@ -40,7 +42,7 @@ export class ExaMcpClient {
|
|
|
40
42
|
options.apiKey === undefined || options.apiKey.length === 0
|
|
41
43
|
? undefined
|
|
42
44
|
: options.apiKey;
|
|
43
|
-
//
|
|
45
|
+
// An API key lifts the rate limit.
|
|
44
46
|
const rateLimiter =
|
|
45
47
|
apiKey !== undefined
|
|
46
48
|
? undefined
|
|
@@ -181,37 +183,30 @@ function readPlainTextSnippet(lines: readonly string[]): string {
|
|
|
181
183
|
|
|
182
184
|
function findFirstObjectArray(
|
|
183
185
|
values: readonly unknown[]
|
|
184
|
-
): readonly
|
|
186
|
+
): readonly ResultObject[] | undefined {
|
|
185
187
|
for (const value of values) {
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
value.every((item) => Json.asRecord(item) !== undefined)
|
|
189
|
-
) {
|
|
190
|
-
return value as readonly Readonly<Record<string, unknown>>[];
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const record = Json.asRecord(value);
|
|
194
|
-
|
|
195
|
-
if (record === undefined) {
|
|
196
|
-
continue;
|
|
188
|
+
if (isObjectArray(value)) {
|
|
189
|
+
return value;
|
|
197
190
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
) {
|
|
204
|
-
return nestedValue as readonly Readonly<Record<string, unknown>>[];
|
|
205
|
-
}
|
|
191
|
+
const nested = Object.values(Json.asRecord(value) ?? {}).find(
|
|
192
|
+
isObjectArray
|
|
193
|
+
);
|
|
194
|
+
if (nested !== undefined) {
|
|
195
|
+
return nested;
|
|
206
196
|
}
|
|
207
197
|
}
|
|
208
198
|
|
|
209
199
|
return undefined;
|
|
210
200
|
}
|
|
211
201
|
|
|
212
|
-
function
|
|
213
|
-
|
|
214
|
-
)
|
|
202
|
+
function isObjectArray(value: unknown): value is readonly ResultObject[] {
|
|
203
|
+
return (
|
|
204
|
+
Array.isArray(value) &&
|
|
205
|
+
value.every((item) => Json.asRecord(item) !== undefined)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function projectResult(result: ResultObject): SearchResult {
|
|
215
210
|
return {
|
|
216
211
|
title: readResultString(result, "title"),
|
|
217
212
|
url: readResultString(result, "url"),
|
|
@@ -219,7 +214,7 @@ function projectResult(
|
|
|
219
214
|
};
|
|
220
215
|
}
|
|
221
216
|
|
|
222
|
-
function readSnippet(result:
|
|
217
|
+
function readSnippet(result: ResultObject): string {
|
|
223
218
|
return (
|
|
224
219
|
readOptionalResultString(result, "snippet") ??
|
|
225
220
|
readOptionalResultString(result, "text") ??
|
|
@@ -228,10 +223,7 @@ function readSnippet(result: Readonly<Record<string, unknown>>): string {
|
|
|
228
223
|
);
|
|
229
224
|
}
|
|
230
225
|
|
|
231
|
-
function readResultString(
|
|
232
|
-
result: Readonly<Record<string, unknown>>,
|
|
233
|
-
name: string
|
|
234
|
-
): string {
|
|
226
|
+
function readResultString(result: ResultObject, name: string): string {
|
|
235
227
|
const value = readOptionalResultString(result, name);
|
|
236
228
|
|
|
237
229
|
if (value === undefined) {
|
|
@@ -242,7 +234,7 @@ function readResultString(
|
|
|
242
234
|
}
|
|
243
235
|
|
|
244
236
|
function readOptionalResultString(
|
|
245
|
-
result:
|
|
237
|
+
result: ResultObject,
|
|
246
238
|
name: string
|
|
247
239
|
): string | undefined {
|
|
248
240
|
const value = result[name];
|
|
@@ -27,7 +27,7 @@ const DAY_MS = 86_400_000;
|
|
|
27
27
|
|
|
28
28
|
const defaultProbeIntervalMs = 1_800_000;
|
|
29
29
|
|
|
30
|
-
/**
|
|
30
|
+
/** Persists quota-exhausted providers. Trips expire at UTC midnight unless a retry-after is given. */
|
|
31
31
|
export class SearchBreaker {
|
|
32
32
|
private readonly filePath: string;
|
|
33
33
|
private readonly now: () => number;
|
|
@@ -18,7 +18,7 @@ export type SearchChainOptions = {
|
|
|
18
18
|
readonly breaker: SearchBreaker;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
/** Tries providers in order
|
|
21
|
+
/** Tries providers in order; the first answer wins, even an empty one. */
|
|
22
22
|
export class SearchChain {
|
|
23
23
|
private readonly providers: readonly SearchProvider[];
|
|
24
24
|
private readonly breaker: SearchBreaker;
|
|
@@ -30,7 +30,6 @@ export class SearchChain {
|
|
|
30
30
|
|
|
31
31
|
public async search(input: ProviderSearchInput): Promise<ChainSearchOutcome> {
|
|
32
32
|
const failures: string[] = [];
|
|
33
|
-
let attempted = false;
|
|
34
33
|
|
|
35
34
|
for (const provider of this.providers) {
|
|
36
35
|
if (await this.breaker.isOpen(provider.name)) {
|
|
@@ -46,14 +45,16 @@ export class SearchChain {
|
|
|
46
45
|
const results = await provider.search(input);
|
|
47
46
|
await this.breaker.reset(provider.name);
|
|
48
47
|
|
|
49
|
-
return {
|
|
48
|
+
return {
|
|
49
|
+
provider: provider.name,
|
|
50
|
+
results,
|
|
51
|
+
fellBack: failures.length > 0,
|
|
52
|
+
};
|
|
50
53
|
} catch (error) {
|
|
51
54
|
if (input.signal?.aborted || Errors.isAbort(error)) {
|
|
52
55
|
throw error;
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
attempted = true;
|
|
56
|
-
|
|
57
58
|
if (error instanceof ProviderQuotaError) {
|
|
58
59
|
await this.breaker.trip({
|
|
59
60
|
provider: provider.name,
|
|
@@ -25,7 +25,7 @@ const defaultReaderEndpoint = "https://r.jina.ai";
|
|
|
25
25
|
const defaultSearchEndpoint = "https://lite.duckduckgo.com/lite/";
|
|
26
26
|
const defaultTimeoutMs = 30_000;
|
|
27
27
|
|
|
28
|
-
/** Reads the Lite SERP through Jina
|
|
28
|
+
/** Reads the Lite SERP through Jina; direct requests get a 202 anti-bot challenge. */
|
|
29
29
|
export class DuckDuckGoProvider implements SearchProvider {
|
|
30
30
|
public readonly name = "duckduckgo";
|
|
31
31
|
|
|
@@ -43,7 +43,7 @@ export class DuckDuckGoProvider implements SearchProvider {
|
|
|
43
43
|
this.timeoutMs = options.timeoutMs ?? defaultTimeoutMs;
|
|
44
44
|
this.headers = {
|
|
45
45
|
Accept: "application/json",
|
|
46
|
-
//
|
|
46
|
+
// Otherwise the reader may serve a stale SERP.
|
|
47
47
|
"x-no-cache": "true",
|
|
48
48
|
...(options.apiKey === undefined || options.apiKey.length === 0
|
|
49
49
|
? {}
|
|
@@ -20,7 +20,6 @@ export type FirecrawlProviderOptions = {
|
|
|
20
20
|
const defaultEndpoint = "https://api.firecrawl.dev/v2/search";
|
|
21
21
|
const defaultTimeoutMs = 20_000;
|
|
22
22
|
|
|
23
|
-
/** Firecrawl search; omitting `Authorization` is the keyless tier, whose exhaustion shows only as a 429. */
|
|
24
23
|
export class FirecrawlProvider implements SearchProvider {
|
|
25
24
|
public readonly name = "firecrawl";
|
|
26
25
|
|
|
@@ -73,7 +72,7 @@ export class FirecrawlProvider implements SearchProvider {
|
|
|
73
72
|
quotaStatuses: [429],
|
|
74
73
|
quotaMessage:
|
|
75
74
|
"Firecrawl rejected the request: keyless daily limit reached.",
|
|
76
|
-
// Firecrawl
|
|
75
|
+
// Firecrawl reports the wait in the body, not Retry-After.
|
|
77
76
|
readRetryAfterMs,
|
|
78
77
|
});
|
|
79
78
|
}
|