@ashx-j/lunr 0.2.21 → 0.2.22
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/CHANGELOG.md +1 -1
- package/README.md +20 -4
- package/dist/builtin-extensions/index.d.ts.map +1 -1
- package/dist/builtin-extensions/index.js +1 -0
- package/dist/builtin-extensions/index.js.map +1 -1
- package/dist/builtin-extensions/lunr-browser.d.ts +3 -0
- package/dist/builtin-extensions/lunr-browser.d.ts.map +1 -0
- package/dist/builtin-extensions/lunr-browser.js +56 -0
- package/dist/builtin-extensions/lunr-browser.js.map +1 -0
- package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-todos.js +15 -0
- package/dist/builtin-extensions/lunr-todos.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.js +3 -0
- package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js +5 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +18 -5
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +3 -0
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts +17 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js +45 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js +4 -11
- package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +4 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +160 -51
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +5 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +2 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +3 -2
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js +2 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +2 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +3 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js +3 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts +18 -0
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +47 -0
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.js +11 -7
- package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +2 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/install-cli.d.ts.map +1 -1
- package/dist/cli/install-cli.js +15 -45
- package/dist/cli/install-cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +9 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +126 -29
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +3 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +20 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/browser/network.d.ts +9 -0
- package/dist/core/browser/network.d.ts.map +1 -0
- package/dist/core/browser/network.js +146 -0
- package/dist/core/browser/network.js.map +1 -0
- package/dist/core/browser/runtime.d.ts +24 -0
- package/dist/core/browser/runtime.d.ts.map +1 -0
- package/dist/core/browser/runtime.js +289 -0
- package/dist/core/browser/runtime.js.map +1 -0
- package/dist/core/browser/schema.d.ts +16 -0
- package/dist/core/browser/schema.d.ts.map +1 -0
- package/dist/core/browser/schema.js +36 -0
- package/dist/core/browser/schema.js.map +1 -0
- package/dist/core/browser/settings.d.ts +8 -0
- package/dist/core/browser/settings.d.ts.map +1 -0
- package/dist/core/browser/settings.js +30 -0
- package/dist/core/browser/settings.js.map +1 -0
- package/dist/core/browser/setup.d.ts +2 -0
- package/dist/core/browser/setup.d.ts.map +1 -0
- package/dist/core/browser/setup.js +16 -0
- package/dist/core/browser/setup.js.map +1 -0
- package/dist/core/customize.d.ts.map +1 -1
- package/dist/core/customize.js +15 -14
- package/dist/core/customize.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +1 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/install-features.d.ts.map +1 -1
- package/dist/core/install-features.js +10 -8
- package/dist/core/install-features.js.map +1 -1
- package/dist/core/memory-cap.d.ts.map +1 -1
- package/dist/core/memory-cap.js +5 -3
- package/dist/core/memory-cap.js.map +1 -1
- package/dist/core/model-tiers.d.ts.map +1 -1
- package/dist/core/model-tiers.js +9 -6
- package/dist/core/model-tiers.js.map +1 -1
- package/dist/core/permissions.d.ts.map +1 -1
- package/dist/core/permissions.js +9 -0
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plan-mode.d.ts.map +1 -1
- package/dist/core/plan-mode.js +3 -0
- package/dist/core/plan-mode.js.map +1 -1
- package/dist/core/process-registry.d.ts.map +1 -1
- package/dist/core/process-registry.js +6 -4
- package/dist/core/process-registry.js.map +1 -1
- package/dist/core/runtime-scope.d.ts +11 -0
- package/dist/core/runtime-scope.d.ts.map +1 -0
- package/dist/core/runtime-scope.js +3 -0
- package/dist/core/runtime-scope.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +13 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-handoff.d.ts +35 -0
- package/dist/core/session-handoff.d.ts.map +1 -0
- package/dist/core/session-handoff.js +214 -0
- package/dist/core/session-handoff.js.map +1 -0
- package/dist/core/session-manager.d.ts +20 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +184 -22
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-ownership.d.ts +28 -0
- package/dist/core/session-ownership.d.ts.map +1 -0
- package/dist/core/session-ownership.js +138 -0
- package/dist/core/session-ownership.js.map +1 -0
- package/dist/core/session-retention.d.ts.map +1 -1
- package/dist/core/session-retention.js +11 -2
- package/dist/core/session-retention.js.map +1 -1
- package/dist/core/settings-manager.d.ts +7 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +18 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +5 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/todo-settings.d.ts +5 -0
- package/dist/core/todo-settings.d.ts.map +1 -0
- package/dist/core/todo-settings.js +7 -0
- package/dist/core/todo-settings.js.map +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +4 -4
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +5 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +4 -4
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +4 -4
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +4 -4
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +4 -4
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +11 -2
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +31 -4
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +4 -4
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/usage-service.d.ts.map +1 -1
- package/dist/core/usage-service.js +5 -3
- package/dist/core/usage-service.js.map +1 -1
- package/dist/gateway/adapters/discord.d.ts +12 -1
- package/dist/gateway/adapters/discord.d.ts.map +1 -1
- package/dist/gateway/adapters/discord.js +112 -17
- package/dist/gateway/adapters/discord.js.map +1 -1
- package/dist/gateway/adapters/telegram.d.ts +4 -2
- package/dist/gateway/adapters/telegram.d.ts.map +1 -1
- package/dist/gateway/adapters/telegram.js +34 -11
- package/dist/gateway/adapters/telegram.js.map +1 -1
- package/dist/gateway/agent-bridge.d.ts +14 -3
- package/dist/gateway/agent-bridge.d.ts.map +1 -1
- package/dist/gateway/agent-bridge.js +252 -60
- package/dist/gateway/agent-bridge.js.map +1 -1
- package/dist/gateway/approval.d.ts +1 -0
- package/dist/gateway/approval.d.ts.map +1 -1
- package/dist/gateway/approval.js +60 -18
- package/dist/gateway/approval.js.map +1 -1
- package/dist/gateway/authz.d.ts +2 -0
- package/dist/gateway/authz.d.ts.map +1 -1
- package/dist/gateway/authz.js +13 -0
- package/dist/gateway/authz.js.map +1 -1
- package/dist/gateway/buttons.d.ts +3 -1
- package/dist/gateway/buttons.d.ts.map +1 -1
- package/dist/gateway/buttons.js +18 -3
- package/dist/gateway/buttons.js.map +1 -1
- package/dist/gateway/command.d.ts.map +1 -1
- package/dist/gateway/command.js +49 -4
- package/dist/gateway/command.js.map +1 -1
- package/dist/gateway/commands.d.ts.map +1 -1
- package/dist/gateway/commands.js +18 -3
- package/dist/gateway/commands.js.map +1 -1
- package/dist/gateway/config.d.ts +5 -0
- package/dist/gateway/config.d.ts.map +1 -1
- package/dist/gateway/config.js +5 -0
- package/dist/gateway/config.js.map +1 -1
- package/dist/gateway/conversations.d.ts +14 -0
- package/dist/gateway/conversations.d.ts.map +1 -0
- package/dist/gateway/conversations.js +30 -0
- package/dist/gateway/conversations.js.map +1 -0
- package/dist/gateway/download.d.ts +2 -0
- package/dist/gateway/download.d.ts.map +1 -0
- package/dist/gateway/download.js +36 -0
- package/dist/gateway/download.js.map +1 -0
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +85 -26
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/mobile-commands.d.ts +24 -0
- package/dist/gateway/mobile-commands.d.ts.map +1 -0
- package/dist/gateway/mobile-commands.js +422 -0
- package/dist/gateway/mobile-commands.js.map +1 -0
- package/dist/gateway/presenter.d.ts +16 -0
- package/dist/gateway/presenter.d.ts.map +1 -0
- package/dist/gateway/presenter.js +210 -0
- package/dist/gateway/presenter.js.map +1 -0
- package/dist/gateway/router.d.ts +1 -0
- package/dist/gateway/router.d.ts.map +1 -1
- package/dist/gateway/router.js +32 -3
- package/dist/gateway/router.js.map +1 -1
- package/dist/gateway/service.d.ts +46 -0
- package/dist/gateway/service.d.ts.map +1 -0
- package/dist/gateway/service.js +395 -0
- package/dist/gateway/service.js.map +1 -0
- package/dist/gateway/setup.d.ts +4 -0
- package/dist/gateway/setup.d.ts.map +1 -0
- package/dist/gateway/setup.js +146 -0
- package/dist/gateway/setup.js.map +1 -0
- package/dist/gateway/types.d.ts +4 -2
- package/dist/gateway/types.d.ts.map +1 -1
- package/dist/gateway/types.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +11 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +53 -16
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/copyable-text.d.ts +31 -0
- package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -0
- package/dist/modes/interactive/components/copyable-text.js +165 -0
- package/dist/modes/interactive/components/copyable-text.js.map +1 -0
- package/dist/modes/interactive/components/custom-entry.d.ts +1 -0
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +8 -0
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +8 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +16 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +5 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +38 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +151 -7
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/node-runtime/agent-session-services-NQ6GKOIK.js +49 -0
- package/dist/node-runtime/{builtin-extensions-JCOPAAB5.js → builtin-extensions-GVC6IFDU.js} +6 -5
- package/dist/node-runtime/{chunk-LTYWTR3V.js → chunk-2MI5OPMN.js} +17 -2
- package/dist/node-runtime/{chunk-W3CVH5RX.js → chunk-2TKODGBZ.js} +11 -6
- package/dist/node-runtime/chunk-4EULYYR4.js +62 -0
- package/dist/node-runtime/chunk-5BNJ4JUH.js +672 -0
- package/dist/node-runtime/{chunk-6N22HULO.js → chunk-5D7LC2ZQ.js} +7 -2
- package/dist/node-runtime/{chunk-KBKMCJDU.js → chunk-5ZQXRPMC.js} +19 -4
- package/dist/node-runtime/{chunk-6KDIOJL3.js → chunk-6427XAWG.js} +3 -3
- package/dist/node-runtime/{chunk-BOHIDQT4.js → chunk-6B2POMK7.js} +1 -1
- package/dist/node-runtime/{chunk-RNBHABBA.js → chunk-7QWNYZDI.js} +7 -0
- package/dist/node-runtime/chunk-AZJHNQKQ.js +205 -0
- package/dist/node-runtime/{chunk-A3KMVBZV.js → chunk-BBUVIEZB.js} +1 -10
- package/dist/node-runtime/chunk-BFNXONG3.js +521 -0
- package/dist/node-runtime/{chunk-IRPJXI6U.js → chunk-BX2RB477.js} +1 -1
- package/dist/node-runtime/chunk-CCCN2UCX.js +14 -0
- package/dist/node-runtime/{chunk-25I2BHAA.js → chunk-CSUZVNYE.js} +1 -1
- package/dist/node-runtime/{chunk-QZMODZQ2.js → chunk-E24EO34J.js} +2 -1
- package/dist/node-runtime/{chunk-2BUAYZ7K.js → chunk-EQ63ANHL.js} +422 -123
- package/dist/node-runtime/{chunk-GB2MGFLI.js → chunk-GJSAD4AB.js} +216 -201
- package/dist/node-runtime/{chunk-W3SILANP.js → chunk-GMHJCCEN.js} +8 -8
- package/dist/node-runtime/{chunk-DDWHZ633.js → chunk-GNN7H3B7.js} +1 -1
- package/dist/node-runtime/chunk-GS66LV4M.js +2830 -0
- package/dist/node-runtime/{chunk-6BEIBLQ3.js → chunk-H3XF4UVQ.js} +1 -1
- package/dist/node-runtime/chunk-H4K3JDRB.js +47 -0
- package/dist/node-runtime/{chunk-YMEAYRBE.js → chunk-HTFRRDSF.js} +2 -7
- package/dist/node-runtime/chunk-IMLCWLPI.js +9 -0
- package/dist/node-runtime/{chunk-Y5KOEMBH.js → chunk-IQIEU7SB.js} +9 -674
- package/dist/node-runtime/{chunk-OPEK5RRY.js → chunk-IVXYUAJE.js} +1 -1
- package/dist/node-runtime/{chunk-PDNXVXMD.js → chunk-IWOWXRWU.js} +58 -48
- package/dist/node-runtime/chunk-KKUTQQV7.js +144 -0
- package/dist/node-runtime/{chunk-AWVD5IEY.js → chunk-LMBNLFXQ.js} +23 -12
- package/dist/node-runtime/{chunk-7NBZ5P7I.js → chunk-NAY6UUQZ.js} +1 -1
- package/dist/node-runtime/chunk-OAR4TYZE.js +146 -0
- package/dist/node-runtime/{chunk-STERBGUB.js → chunk-OFKSVRV7.js} +2 -2
- package/dist/node-runtime/{chunk-JZQ7F36T.js → chunk-ORH324EP.js} +19 -3
- package/dist/node-runtime/{chunk-2SJB2AWP.js → chunk-PC2Z5TKZ.js} +3 -3
- package/dist/node-runtime/{chunk-SY2TFMLO.js → chunk-QDGKKKUM.js} +46 -151
- package/dist/node-runtime/chunk-R3K2F5GI.js +122 -0
- package/dist/node-runtime/chunk-RMQZU2YU.js +117 -0
- package/dist/node-runtime/{chunk-XI77KVKA.js → chunk-TDL7UWJ7.js} +283 -2999
- package/dist/node-runtime/{chunk-G6LRAP36.js → chunk-TQGPP4SC.js} +1 -1
- package/dist/node-runtime/chunk-UAEOTO52.js +119 -0
- package/dist/node-runtime/{chunk-VZR3NCM7.js → chunk-UAFLNHSH.js} +18 -14
- package/dist/node-runtime/{chunk-AY6CAJSL.js → chunk-UJOCPOMX.js} +6 -3
- package/dist/node-runtime/chunk-UP2XBVH5.js +40 -0
- package/dist/node-runtime/{chunk-WJVFOIB5.js → chunk-UQUCFAJ3.js} +1 -1
- package/dist/node-runtime/chunk-URD2SLIT.js +1019 -0
- package/dist/node-runtime/chunk-US544NN6.js +13 -0
- package/dist/node-runtime/chunk-UWPJL22I.js +341 -0
- package/dist/node-runtime/chunk-V2A7CEXK.js +355 -0
- package/dist/node-runtime/chunk-VJPTNWAP.js +708 -0
- package/dist/node-runtime/{chunk-WKDK4C5P.js → chunk-VSSXXL36.js} +38 -164
- package/dist/node-runtime/{chunk-4I23VTC4.js → chunk-VWCE2HSZ.js} +21 -124
- package/dist/node-runtime/{chunk-WLLDXJRT.js → chunk-WADV2VDS.js} +22 -1014
- package/dist/node-runtime/{chunk-GKLEQ3I4.js → chunk-XLTL257W.js} +126 -27
- package/dist/node-runtime/chunk-YPHAIRZT.js +10 -0
- package/dist/node-runtime/cli-runtime.js +2 -2
- package/dist/node-runtime/command-3JHHXOPX.js +45 -0
- package/dist/node-runtime/commands-2JVNFGMQ.js +36 -0
- package/dist/node-runtime/{commands-MV5KOZ64.js → commands-KAMO2T6P.js} +10 -10
- package/dist/node-runtime/config-RORQUQFG.js +20 -0
- package/dist/node-runtime/{customize-LF5VST47.js → customize-VFJV3U6A.js} +2 -1
- package/dist/node-runtime/{direct-tool-executor-BK7CLEBX.js → direct-tool-executor-YAVOLDFY.js} +8 -8
- package/dist/node-runtime/{export-html-TEXVV5RP.js → export-html-KBFVV63J.js} +4 -3
- package/dist/node-runtime/{extension-input-O4HSAEM4.js → extension-input-K24TVKVW.js} +4 -4
- package/dist/node-runtime/{extension-selector-X5FCX43D.js → extension-selector-SPNF7EDR.js} +4 -4
- package/dist/node-runtime/{extract-XLQSJN4V.js → extract-EQJE7FZZ.js} +2 -2
- package/dist/node-runtime/{gateway-BM6NLOH4.js → gateway-VFO6SFKK.js} +275 -994
- package/dist/node-runtime/{gemini-search-U7SUMPQA.js → gemini-search-35OCRFLN.js} +1 -1
- package/dist/node-runtime/{gemini-url-context-PXWCBQHK.js → gemini-url-context-UQY3PHHW.js} +2 -2
- package/dist/node-runtime/index.js +104 -65
- package/dist/node-runtime/{init-3C7Z24OI.js → init-X2LIUB2H.js} +3 -3
- package/dist/node-runtime/{install-cli-EXMJQESX.js → install-cli-C3CF7O7N.js} +21 -82
- package/dist/node-runtime/interactive-mode-LOM6AIF6.js +72 -0
- package/dist/node-runtime/{interactive-view-ILS6TAN5.js → interactive-view-IDSCPPK7.js} +8 -8
- package/dist/node-runtime/lunr-browser-YNW7FTYX.js +87 -0
- package/dist/node-runtime/{lunr-cron-4VHP4E4B.js → lunr-cron-BKHGNBKT.js} +19 -5
- package/dist/node-runtime/main.js +44 -31
- package/dist/node-runtime/{memory-cap-3S4XRLNP.js → memory-cap-EL3KL4JJ.js} +2 -1
- package/dist/node-runtime/mobile-commands-HMP25WBC.js +32 -0
- package/dist/node-runtime/model-runtime-PLQKAG4B.js +16 -0
- package/dist/node-runtime/{model-tiers-NJLHUEGK.js → model-tiers-OU3U5CZG.js} +2 -1
- package/dist/node-runtime/{package-manager-cli-N37546V5.js → package-manager-cli-VCK4E2RC.js} +22 -15
- package/dist/node-runtime/{pi-intercom-NV2LW6X7.js → pi-intercom-HBPK5HSJ.js} +4 -1
- package/dist/node-runtime/{pi-mcp-adapter-GUFZWW54.js → pi-mcp-adapter-E6WULBKF.js} +4 -4
- package/dist/node-runtime/{pi-subagents-6MUIFNDM.js → pi-subagents-FEUDLJOE.js} +201 -78
- package/dist/node-runtime/{pi-web-access-2CQGFLT2.js → pi-web-access-WTGMNZ32.js} +15 -15
- package/dist/node-runtime/process-registry-4FAKZQOL.js +31 -0
- package/dist/node-runtime/{proxy-modes-V6YVFH3C.js → proxy-modes-OSQCWRBI.js} +9 -9
- package/dist/node-runtime/rpc-entry.js +44 -31
- package/dist/node-runtime/{rpc-mode-W5ZTLTMZ.js → rpc-mode-P5ODXPEG.js} +2 -2
- package/dist/node-runtime/runtime-4VA6JKNF.js +373 -0
- package/dist/node-runtime/{runtime-bridges-2VQTLPOZ.js → runtime-bridges-3XUQ46XW.js} +6 -5
- package/dist/node-runtime/service-ISSP6VHE.js +36 -0
- package/dist/node-runtime/session-handoff-HC7R5E24.js +33 -0
- package/dist/node-runtime/{session-manager-E7AREDTV.js → session-manager-CFN4UFM2.js} +2 -1
- package/dist/node-runtime/{session-selector-FJ7M2AIX.js → session-selector-LHRMJOKT.js} +5 -4
- package/dist/node-runtime/{settings-manager-CUGAZWAB.js → settings-manager-UUZ6NUXI.js} +7 -2
- package/dist/node-runtime/setup-JBKOLJ6F.js +18 -0
- package/dist/node-runtime/setup-NRXVZBLJ.js +155 -0
- package/dist/node-runtime/{subagent-executor-MH4A7CCF.js → subagent-executor-MLUMBWCP.js} +22 -18
- package/dist/node-runtime/theme-U7IGOA7O.js +68 -0
- package/dist/node-runtime/trust-manager-MMISNCYO.js +17 -0
- package/dist/node-runtime/{update-cli-XTZMZGOL.js → update-cli-4TP25CNW.js} +7 -2
- package/dist/node-runtime/usage-service-LFB2SWYV.js +37 -0
- package/dist/node-runtime/{video-extract-OYT5WKS5.js → video-extract-OOZHR7SU.js} +2 -2
- package/dist/node-runtime/{youtube-extract-TQYKGFGS.js → youtube-extract-FNPAUNHU.js} +6 -6
- package/docs/browser.md +86 -0
- package/docs/extensions.md +2 -0
- package/docs/features.md +94 -16
- package/docs/interactive-startup.md +2 -1
- package/docs/sessions.md +10 -0
- package/docs/settings.md +1 -0
- package/docs/tui.md +2 -0
- package/docs/usage.md +16 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +7 -4
- package/scripts/install-browser.mjs +20 -0
- package/dist/node-runtime/agent-session-services-C743TYQE.js +0 -37
- package/dist/node-runtime/chunk-VGYZ3APQ.js +0 -59
- package/dist/node-runtime/command-P4NYCJ2M.js +0 -13
- package/dist/node-runtime/interactive-mode-EVVBA64D.js +0 -59
- package/dist/node-runtime/{chunk-UWQYRSYQ.js → chunk-YJMMG7C6.js} +25 -25
- package/dist/node-runtime/{mcp-panel-IIGMXQGP.js → mcp-panel-KTTFXJZ4.js} +3 -3
- package/dist/node-runtime/{src-BPQFJR76.js → src-IVPNZ2BX.js} +9 -9
|
@@ -1,2913 +1,126 @@
|
|
|
1
1
|
import { createRequire as __lunrRequire } from "node:module"; const require = __lunrRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
} from "./chunk-
|
|
61
|
-
import {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
} from "./chunk-
|
|
76
|
-
import {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} from "./chunk-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
import { dirname, join } from "path";
|
|
103
|
-
|
|
104
|
-
// packages/coding-agent/dist/core/resolve-config-value.js
|
|
105
|
-
import { execSync, spawnSync } from "child_process";
|
|
106
|
-
var commandResultCache = /* @__PURE__ */ new Map(), ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/, ENV_VAR_NAME_PREFIX_RE = /^[A-Za-z_][A-Za-z0-9_]*/;
|
|
107
|
-
function appendLiteral(parts, value) {
|
|
108
|
-
if (!value)
|
|
109
|
-
return;
|
|
110
|
-
let previousPart = parts[parts.length - 1];
|
|
111
|
-
if (previousPart?.type === "literal") {
|
|
112
|
-
previousPart.value += value;
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
parts.push({ type: "literal", value });
|
|
116
|
-
}
|
|
117
|
-
function parseConfigValueTemplate(config) {
|
|
118
|
-
let parts = [], index = 0;
|
|
119
|
-
for (; index < config.length; ) {
|
|
120
|
-
let dollarIndex = config.indexOf("$", index);
|
|
121
|
-
if (dollarIndex < 0) {
|
|
122
|
-
appendLiteral(parts, config.slice(index));
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
appendLiteral(parts, config.slice(index, dollarIndex));
|
|
126
|
-
let nextChar = config[dollarIndex + 1];
|
|
127
|
-
if (nextChar === "$" || nextChar === "!") {
|
|
128
|
-
appendLiteral(parts, nextChar), index = dollarIndex + 2;
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
if (nextChar === "{") {
|
|
132
|
-
let endIndex = config.indexOf("}", dollarIndex + 2);
|
|
133
|
-
if (endIndex < 0) {
|
|
134
|
-
appendLiteral(parts, "$"), index = dollarIndex + 1;
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
let name = config.slice(dollarIndex + 2, endIndex);
|
|
138
|
-
ENV_VAR_NAME_RE.test(name) ? parts.push({ type: "env", name }) : appendLiteral(parts, config.slice(dollarIndex, endIndex + 1)), index = endIndex + 1;
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
let match = config.slice(dollarIndex + 1).match(ENV_VAR_NAME_PREFIX_RE);
|
|
142
|
-
if (match) {
|
|
143
|
-
parts.push({ type: "env", name: match[0] }), index = dollarIndex + 1 + match[0].length;
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
appendLiteral(parts, "$"), index = dollarIndex + 1;
|
|
147
|
-
}
|
|
148
|
-
return parts;
|
|
149
|
-
}
|
|
150
|
-
function parseConfigValueReference(config) {
|
|
151
|
-
return config.startsWith("!") ? { type: "command", config } : { type: "template", parts: parseConfigValueTemplate(config) };
|
|
152
|
-
}
|
|
153
|
-
function resolveEnvConfigValue(name, env) {
|
|
154
|
-
return env?.[name] || process.env[name] || void 0;
|
|
155
|
-
}
|
|
156
|
-
function getTemplateEnvVarNames(parts) {
|
|
157
|
-
let names = [];
|
|
158
|
-
for (let part of parts)
|
|
159
|
-
part.type !== "env" || names.includes(part.name) || names.push(part.name);
|
|
160
|
-
return names;
|
|
161
|
-
}
|
|
162
|
-
function resolveTemplate(parts, env) {
|
|
163
|
-
let resolved = "";
|
|
164
|
-
for (let part of parts) {
|
|
165
|
-
if (part.type === "literal") {
|
|
166
|
-
resolved += part.value;
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
let envValue = resolveEnvConfigValue(part.name, env);
|
|
170
|
-
if (envValue === void 0)
|
|
171
|
-
return;
|
|
172
|
-
resolved += envValue;
|
|
173
|
-
}
|
|
174
|
-
return resolved;
|
|
175
|
-
}
|
|
176
|
-
function getConfigValueEnvVarNames(config) {
|
|
177
|
-
let reference = parseConfigValueReference(config);
|
|
178
|
-
return reference.type === "template" ? getTemplateEnvVarNames(reference.parts) : [];
|
|
179
|
-
}
|
|
180
|
-
function getMissingConfigValueEnvVarNames(config, env) {
|
|
181
|
-
return getConfigValueEnvVarNames(config).filter((name) => resolveEnvConfigValue(name, env) === void 0);
|
|
182
|
-
}
|
|
183
|
-
function isCommandConfigValue(config) {
|
|
184
|
-
return parseConfigValueReference(config).type === "command";
|
|
185
|
-
}
|
|
186
|
-
function isConfigValueConfigured(config, env) {
|
|
187
|
-
return getMissingConfigValueEnvVarNames(config, env).length === 0;
|
|
188
|
-
}
|
|
189
|
-
function resolveConfigValue(config, env) {
|
|
190
|
-
let reference = parseConfigValueReference(config);
|
|
191
|
-
return reference.type === "command" ? executeCommand(reference.config) : resolveTemplate(reference.parts, env);
|
|
192
|
-
}
|
|
193
|
-
function executeWithConfiguredShell(command) {
|
|
194
|
-
try {
|
|
195
|
-
let { shell, args, commandTransport } = getShellConfig(), commandFromStdin = commandTransport === "stdin", result = spawnSync(shell, commandFromStdin ? args : [...args, command], {
|
|
196
|
-
encoding: "utf-8",
|
|
197
|
-
input: commandFromStdin ? command : void 0,
|
|
198
|
-
timeout: 1e4,
|
|
199
|
-
stdio: [commandFromStdin ? "pipe" : "ignore", "pipe", "ignore"],
|
|
200
|
-
shell: !1,
|
|
201
|
-
windowsHide: !0
|
|
202
|
-
});
|
|
203
|
-
return result.error ? result.error.code === "ENOENT" ? { executed: !1, value: void 0 } : { executed: !0, value: void 0 } : result.status !== 0 ? { executed: !0, value: void 0 } : { executed: !0, value: (result.stdout ?? "").trim() || void 0 };
|
|
204
|
-
} catch {
|
|
205
|
-
return { executed: !1, value: void 0 };
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
function executeWithDefaultShell(command) {
|
|
209
|
-
try {
|
|
210
|
-
return execSync(command, {
|
|
211
|
-
encoding: "utf-8",
|
|
212
|
-
timeout: 1e4,
|
|
213
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
214
|
-
}).trim() || void 0;
|
|
215
|
-
} catch {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
function executeCommandUncached(commandConfig) {
|
|
220
|
-
let command = commandConfig.slice(1);
|
|
221
|
-
return process.platform === "win32" ? (() => {
|
|
222
|
-
let configuredResult = executeWithConfiguredShell(command);
|
|
223
|
-
return configuredResult.executed ? configuredResult.value : executeWithDefaultShell(command);
|
|
224
|
-
})() : executeWithDefaultShell(command);
|
|
225
|
-
}
|
|
226
|
-
function executeCommand(commandConfig) {
|
|
227
|
-
if (commandResultCache.has(commandConfig))
|
|
228
|
-
return commandResultCache.get(commandConfig);
|
|
229
|
-
let result = executeCommandUncached(commandConfig);
|
|
230
|
-
return commandResultCache.set(commandConfig, result), result;
|
|
231
|
-
}
|
|
232
|
-
function resolveConfigValueUncached(config, env) {
|
|
233
|
-
let reference = parseConfigValueReference(config);
|
|
234
|
-
return reference.type === "command" ? executeCommandUncached(reference.config) : resolveTemplate(reference.parts, env);
|
|
235
|
-
}
|
|
236
|
-
function resolveConfigValueOrThrow(config, description, env) {
|
|
237
|
-
let resolvedValue = resolveConfigValueUncached(config, env);
|
|
238
|
-
if (resolvedValue !== void 0)
|
|
239
|
-
return resolvedValue;
|
|
240
|
-
let reference = parseConfigValueReference(config);
|
|
241
|
-
if (reference.type === "command")
|
|
242
|
-
throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);
|
|
243
|
-
if (reference.type === "template") {
|
|
244
|
-
let missingEnvVars = getMissingConfigValueEnvVarNames(config, env);
|
|
245
|
-
if (missingEnvVars.length === 1)
|
|
246
|
-
throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);
|
|
247
|
-
if (missingEnvVars.length > 1)
|
|
248
|
-
throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`);
|
|
249
|
-
}
|
|
250
|
-
throw new Error(`Failed to resolve ${description}`);
|
|
251
|
-
}
|
|
252
|
-
function resolveHeadersOrThrow(headers, description, env) {
|
|
253
|
-
if (!headers)
|
|
254
|
-
return;
|
|
255
|
-
let resolved = {};
|
|
256
|
-
for (let [key, value] of Object.entries(headers))
|
|
257
|
-
resolved[key] = resolveConfigValueOrThrow(value, `${description} header "${key}"`, env);
|
|
258
|
-
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// packages/coding-agent/dist/core/auth-storage.js
|
|
262
|
-
var AUTH_FILE_WRITE_OPTIONS = { encoding: "utf-8", mode: 384 }, AUTH_LOCK_STALE_MS = 12e4;
|
|
263
|
-
function writeAuthFileAtomic(authPath, contents) {
|
|
264
|
-
let tmp = `${authPath}.${process.pid}.${Date.now()}.tmp`;
|
|
265
|
-
writeFileSync(tmp, contents, AUTH_FILE_WRITE_OPTIONS);
|
|
266
|
-
try {
|
|
267
|
-
chmodSync(tmp, 384);
|
|
268
|
-
} catch {
|
|
269
|
-
}
|
|
270
|
-
try {
|
|
271
|
-
if (process.platform === "win32" && existsSync(authPath)) {
|
|
272
|
-
writeFileSync(authPath, contents, AUTH_FILE_WRITE_OPTIONS), chmodSync(authPath, 384);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
renameSync(tmp, authPath);
|
|
276
|
-
try {
|
|
277
|
-
chmodSync(authPath, 384);
|
|
278
|
-
} catch {
|
|
279
|
-
}
|
|
280
|
-
} finally {
|
|
281
|
-
try {
|
|
282
|
-
unlinkSync(tmp);
|
|
283
|
-
} catch {
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
var FileAuthStorageBackend = class {
|
|
288
|
-
authPath;
|
|
289
|
-
constructor(authPath = join(getAgentDir(), "auth.json")) {
|
|
290
|
-
this.authPath = normalizePath(authPath);
|
|
291
|
-
}
|
|
292
|
-
ensureParentDir() {
|
|
293
|
-
let dir = dirname(this.authPath);
|
|
294
|
-
existsSync(dir) || mkdirSync(dir, { recursive: !0, mode: 448 });
|
|
295
|
-
}
|
|
296
|
-
ensureFileExists() {
|
|
297
|
-
existsSync(this.authPath) || (writeFileSync(this.authPath, "{}", AUTH_FILE_WRITE_OPTIONS), chmodSync(this.authPath, 384));
|
|
298
|
-
}
|
|
299
|
-
acquireLockSyncWithRetry(path) {
|
|
300
|
-
let lastError;
|
|
301
|
-
for (let attempt = 1; attempt <= 10; attempt++)
|
|
302
|
-
try {
|
|
303
|
-
return import_proper_lockfile.default.lockSync(path, { realpath: !1, stale: AUTH_LOCK_STALE_MS });
|
|
304
|
-
} catch (error) {
|
|
305
|
-
if ((typeof error == "object" && error !== null && "code" in error ? String(error.code) : void 0) !== "ELOCKED" || attempt === 10)
|
|
306
|
-
throw error;
|
|
307
|
-
lastError = error;
|
|
308
|
-
let start = Date.now();
|
|
309
|
-
for (; Date.now() - start < 20; )
|
|
310
|
-
;
|
|
311
|
-
}
|
|
312
|
-
throw lastError ?? new Error("Failed to acquire auth storage lock");
|
|
313
|
-
}
|
|
314
|
-
withLock(fn) {
|
|
315
|
-
this.ensureParentDir(), this.ensureFileExists();
|
|
316
|
-
let release;
|
|
317
|
-
try {
|
|
318
|
-
release = this.acquireLockSyncWithRetry(this.authPath);
|
|
319
|
-
let current = existsSync(this.authPath) ? readFileSync(this.authPath, "utf-8") : void 0, { result, next } = fn(current);
|
|
320
|
-
return next !== void 0 && writeAuthFileAtomic(this.authPath, next), result;
|
|
321
|
-
} finally {
|
|
322
|
-
release && release();
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
async withLockAsync(fn) {
|
|
326
|
-
this.ensureParentDir(), this.ensureFileExists();
|
|
327
|
-
let release, lockCompromised = !1, lockCompromisedError, throwIfCompromised = () => {
|
|
328
|
-
if (lockCompromised)
|
|
329
|
-
throw lockCompromisedError ?? new Error("Auth storage lock was compromised");
|
|
330
|
-
};
|
|
331
|
-
try {
|
|
332
|
-
release = await import_proper_lockfile.default.lock(this.authPath, {
|
|
333
|
-
retries: {
|
|
334
|
-
retries: 10,
|
|
335
|
-
factor: 2,
|
|
336
|
-
minTimeout: 100,
|
|
337
|
-
maxTimeout: 1e4,
|
|
338
|
-
randomize: !0
|
|
339
|
-
},
|
|
340
|
-
stale: AUTH_LOCK_STALE_MS,
|
|
341
|
-
onCompromised: (err) => {
|
|
342
|
-
lockCompromised = !0, lockCompromisedError = err;
|
|
343
|
-
}
|
|
344
|
-
}), throwIfCompromised();
|
|
345
|
-
let current = existsSync(this.authPath) ? readFileSync(this.authPath, "utf-8") : void 0, { result, next } = await fn(current);
|
|
346
|
-
return throwIfCompromised(), next !== void 0 && writeAuthFileAtomic(this.authPath, next), throwIfCompromised(), result;
|
|
347
|
-
} finally {
|
|
348
|
-
if (release)
|
|
349
|
-
try {
|
|
350
|
-
await release();
|
|
351
|
-
} catch {
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}, InMemoryAuthStorageBackend = class {
|
|
356
|
-
value;
|
|
357
|
-
withLock(fn) {
|
|
358
|
-
let { result, next } = fn(this.value);
|
|
359
|
-
return next !== void 0 && (this.value = next), result;
|
|
360
|
-
}
|
|
361
|
-
async withLockAsync(fn) {
|
|
362
|
-
let { result, next } = await fn(this.value);
|
|
363
|
-
return next !== void 0 && (this.value = next), result;
|
|
364
|
-
}
|
|
365
|
-
}, AuthStorage = class _AuthStorage {
|
|
366
|
-
data = {};
|
|
367
|
-
storage;
|
|
368
|
-
constructor(storage) {
|
|
369
|
-
this.storage = storage, this.reload();
|
|
370
|
-
}
|
|
371
|
-
static create(authPath) {
|
|
372
|
-
return new _AuthStorage(new FileAuthStorageBackend(authPath ?? join(getAgentDir(), "auth.json")));
|
|
373
|
-
}
|
|
374
|
-
static fromStorage(storage) {
|
|
375
|
-
return new _AuthStorage(storage);
|
|
376
|
-
}
|
|
377
|
-
static inMemory(data = {}) {
|
|
378
|
-
let storage = new InMemoryAuthStorageBackend();
|
|
379
|
-
return storage.withLock(() => ({ result: void 0, next: JSON.stringify(data, null, 2) })), _AuthStorage.fromStorage(storage);
|
|
380
|
-
}
|
|
381
|
-
parseStorageData(content) {
|
|
382
|
-
return content ? JSON.parse(content) : {};
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* Reload credentials from storage.
|
|
386
|
-
*/
|
|
387
|
-
reload() {
|
|
388
|
-
let content;
|
|
389
|
-
try {
|
|
390
|
-
this.storage.withLock((current) => (content = current, { result: void 0 })), this.data = this.parseStorageData(content);
|
|
391
|
-
} catch {
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
async read(provider) {
|
|
395
|
-
let credential = this.data[provider];
|
|
396
|
-
return credential?.type !== "api_key" || credential.key === void 0 ? credential : { ...credential, key: resolveConfigValue(credential.key, credential.env) };
|
|
397
|
-
}
|
|
398
|
-
async modify(provider, fn) {
|
|
399
|
-
return this.storage.withLockAsync(async (content) => {
|
|
400
|
-
let currentData = this.parseStorageData(content), next = await fn(currentData[provider]);
|
|
401
|
-
if (next === void 0)
|
|
402
|
-
return this.data = currentData, { result: currentData[provider] };
|
|
403
|
-
let merged = { ...currentData, [provider]: next };
|
|
404
|
-
return this.data = merged, { result: next, next: JSON.stringify(merged, null, 2) };
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
async delete(provider) {
|
|
408
|
-
await this.storage.withLockAsync(async (content) => {
|
|
409
|
-
let currentData = this.parseStorageData(content);
|
|
410
|
-
return delete currentData[provider], this.data = currentData, { result: void 0, next: JSON.stringify(currentData, null, 2) };
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
/** List credential metadata without resolving configured key values. */
|
|
414
|
-
async list() {
|
|
415
|
-
return Object.entries(this.data).map(([providerId, credential]) => ({ providerId, type: credential.type }));
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
function readStoredCredential(providerId, authPath = join(getAgentDir(), "auth.json")) {
|
|
419
|
-
try {
|
|
420
|
-
return JSON.parse(readFileSync(normalizePath(authPath), "utf-8"))[providerId];
|
|
421
|
-
} catch {
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// packages/coding-agent/dist/core/catalog-cache-scope.js
|
|
427
|
-
import { createHash } from "node:crypto";
|
|
428
|
-
function catalogCacheScope(provider, baseUrl, credential) {
|
|
429
|
-
let identity = credential?.type === "oauth" ? typeof credential.accountId == "string" ? credential.accountId : credential.refresh || credential.access : credential?.key;
|
|
430
|
-
return createHash("sha256").update(JSON.stringify([provider, baseUrl.replace(/\/+$/, ""), identity ?? null])).digest("hex");
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// packages/coding-agent/dist/core/catalog-merge.js
|
|
434
|
-
import { withOpenAiEffortMetadata, withXaiEffortMetadata } from "@ashx-j/lunr-ai";
|
|
435
|
-
|
|
436
|
-
// packages/coding-agent/dist/core/official-catalog.js
|
|
437
|
-
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
438
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
439
|
-
import { dirname as dirname2, join as join2 } from "node:path";
|
|
440
|
-
import { fileURLToPath } from "node:url";
|
|
441
|
-
|
|
442
|
-
// packages/coding-agent/dist/utils/pi-user-agent.js
|
|
443
|
-
function getPiUserAgent(version) {
|
|
444
|
-
let runtime = process.versions.bun ? `bun/${process.versions.bun}` : `node/${process.version}`;
|
|
445
|
-
return `pi/${version} (${process.platform}; ${runtime}; ${process.arch})`;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// packages/coding-agent/dist/core/official-catalog.js
|
|
449
|
-
var OFFICIAL_CATALOG_DEFAULT_URL = "https://raw.githubusercontent.com/ashx-j/lunR/master/catalog", VERSIONED_CATALOG_URL = "https://raw.githubusercontent.com/ashx-j/lunR/model-catalog/catalog", OFFICIAL_CATALOG_TIMEOUT_MS = 4e3, OFFICIAL_CATALOG_CACHE_FILENAME = "official-catalog-cache.json", THINKING_LEVEL_KEYS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"], META_KEYS = /* @__PURE__ */ new Set(["version", "updatedAt", "generatedAt", "sourceCommit", "providerCount", "modelCount"]), BUNDLED_OFFICIAL_CATALOG = {
|
|
450
|
-
version: 1,
|
|
451
|
-
updatedAt: "2026-08-15T00:00:00Z",
|
|
452
|
-
models: [
|
|
453
|
-
{
|
|
454
|
-
id: "grok-4.6",
|
|
455
|
-
name: "Grok 4.6",
|
|
456
|
-
api: "openai-completions",
|
|
457
|
-
provider: "xai",
|
|
458
|
-
baseUrl: "https://api.x.ai/v1",
|
|
459
|
-
reasoning: !0,
|
|
460
|
-
input: ["text", "image"],
|
|
461
|
-
cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },
|
|
462
|
-
contextWindow: 5e5,
|
|
463
|
-
maxTokens: 5e5
|
|
464
|
-
}
|
|
465
|
-
]
|
|
466
|
-
};
|
|
467
|
-
function officialCatalogCachePath(agentDir = getAgentDir()) {
|
|
468
|
-
return join2(agentDir, OFFICIAL_CATALOG_CACHE_FILENAME);
|
|
469
|
-
}
|
|
470
|
-
function officialCatalogBaseUrl(override) {
|
|
471
|
-
return ((override ?? process.env.LUNR_OFFICIAL_CATALOG_URL)?.trim() || OFFICIAL_CATALOG_DEFAULT_URL).replace(/\/+$/, "");
|
|
472
|
-
}
|
|
473
|
-
function officialCatalogUrlFor(path, base) {
|
|
474
|
-
let normalized = path.replace(/^\/+/, "");
|
|
475
|
-
return `${officialCatalogBaseUrl(base)}/${normalized}`;
|
|
476
|
-
}
|
|
477
|
-
function modelKey(provider, id) {
|
|
478
|
-
return `${provider}/${id}`;
|
|
479
|
-
}
|
|
480
|
-
function isRecord(value) {
|
|
481
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
482
|
-
}
|
|
483
|
-
function asFiniteNumber(value) {
|
|
484
|
-
if (typeof value == "number" && Number.isFinite(value))
|
|
485
|
-
return value;
|
|
486
|
-
if (typeof value == "string" && value.trim()) {
|
|
487
|
-
let parsed = Number(value);
|
|
488
|
-
if (Number.isFinite(parsed))
|
|
489
|
-
return parsed;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
function parseCost(value) {
|
|
493
|
-
if (!isRecord(value))
|
|
494
|
-
return;
|
|
495
|
-
let input = asFiniteNumber(value.input), output = asFiniteNumber(value.output);
|
|
496
|
-
if (!(input === void 0 || output === void 0))
|
|
497
|
-
return {
|
|
498
|
-
input,
|
|
499
|
-
output,
|
|
500
|
-
cacheRead: asFiniteNumber(value.cacheRead) ?? 0,
|
|
501
|
-
cacheWrite: asFiniteNumber(value.cacheWrite) ?? 0,
|
|
502
|
-
...Array.isArray(value.tiers) ? {
|
|
503
|
-
tiers: value.tiers.flatMap((tier) => {
|
|
504
|
-
if (!isRecord(tier) || !(typeof tier.inputTokensAbove == "number" && tier.inputTokensAbove >= 0))
|
|
505
|
-
return [];
|
|
506
|
-
let rates = parseCost({
|
|
507
|
-
input: tier.input,
|
|
508
|
-
output: tier.output,
|
|
509
|
-
cacheRead: tier.cacheRead,
|
|
510
|
-
cacheWrite: tier.cacheWrite
|
|
511
|
-
});
|
|
512
|
-
return rates ? [{ ...rates, inputTokensAbove: tier.inputTokensAbove }] : [];
|
|
513
|
-
})
|
|
514
|
-
} : {}
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
function parseInput(value) {
|
|
518
|
-
if (!Array.isArray(value))
|
|
519
|
-
return;
|
|
520
|
-
let input = [];
|
|
521
|
-
for (let entry of value)
|
|
522
|
-
(entry === "text" || entry === "image") && input.push(entry);
|
|
523
|
-
return input.length > 0 ? input : void 0;
|
|
524
|
-
}
|
|
525
|
-
function parseThinkingLevelMap(value) {
|
|
526
|
-
if (!isRecord(value))
|
|
527
|
-
return;
|
|
528
|
-
let map = {}, any = !1;
|
|
529
|
-
for (let level of THINKING_LEVEL_KEYS) {
|
|
530
|
-
let mapped = value[level];
|
|
531
|
-
(mapped === null || typeof mapped == "string") && (map[level] = mapped, any = !0);
|
|
532
|
-
}
|
|
533
|
-
return any ? map : void 0;
|
|
534
|
-
}
|
|
535
|
-
function parseHeaders(value) {
|
|
536
|
-
if (!isRecord(value))
|
|
537
|
-
return;
|
|
538
|
-
let headers = {};
|
|
539
|
-
for (let [name, headerValue] of Object.entries(value))
|
|
540
|
-
typeof headerValue == "string" && (headers[name] = headerValue);
|
|
541
|
-
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
542
|
-
}
|
|
543
|
-
function parseOfficialEntry(value) {
|
|
544
|
-
if (!isRecord(value))
|
|
545
|
-
return;
|
|
546
|
-
let id = typeof value.id == "string" ? value.id.trim() : "", provider = typeof value.provider == "string" ? value.provider.trim() : "";
|
|
547
|
-
if (!id || !provider)
|
|
548
|
-
return;
|
|
549
|
-
let api = typeof value.api == "string" && value.api.trim() ? value.api.trim() : "openai-completions", name = typeof value.name == "string" && value.name.trim() ? value.name.trim() : id, baseUrl = typeof value.baseUrl == "string" ? value.baseUrl.trim() : "", cost = parseCost(value.cost) ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, input = parseInput(value.input) ?? ["text"], compat = isRecord(value.compat) ? value.compat : void 0, thinkingLevelMap = parseThinkingLevelMap(value.thinkingLevelMap), headers = parseHeaders(value.headers);
|
|
550
|
-
return {
|
|
551
|
-
id,
|
|
552
|
-
...isRecord(value.catalog) && value.catalog.source === "provider" && Array.isArray(value.catalog.supplied) ? { catalog: value.catalog } : {},
|
|
553
|
-
name,
|
|
554
|
-
api,
|
|
555
|
-
provider,
|
|
556
|
-
baseUrl,
|
|
557
|
-
reasoning: value.reasoning === !0,
|
|
558
|
-
input,
|
|
559
|
-
cost,
|
|
560
|
-
contextWindow: asFiniteNumber(value.contextWindow) ?? 128e3,
|
|
561
|
-
maxTokens: asFiniteNumber(value.maxTokens) ?? 8192,
|
|
562
|
-
...compat ? { compat } : {},
|
|
563
|
-
...thinkingLevelMap ? { thinkingLevelMap } : {},
|
|
564
|
-
...headers ? { headers } : {}
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
function catalogFile(models, value) {
|
|
568
|
-
let version = value ? asFiniteNumber(value.version) ?? 1 : 1, updatedAt = value && typeof value.updatedAt == "string" && value.updatedAt.trim() ? value.updatedAt : "";
|
|
569
|
-
return { version, updatedAt, models };
|
|
570
|
-
}
|
|
571
|
-
function parseKeyedCatalog(value) {
|
|
572
|
-
let models = [];
|
|
573
|
-
for (let [key, entry] of Object.entries(value))
|
|
574
|
-
if (!(META_KEYS.has(key) || !isRecord(entry))) {
|
|
575
|
-
if (typeof entry.id == "string") {
|
|
576
|
-
let parsed = parseOfficialEntry(entry);
|
|
577
|
-
parsed && models.push(parsed);
|
|
578
|
-
continue;
|
|
579
|
-
}
|
|
580
|
-
for (let [modelId, model] of Object.entries(entry)) {
|
|
581
|
-
if (!isRecord(model))
|
|
582
|
-
continue;
|
|
583
|
-
let parsed = parseOfficialEntry({
|
|
584
|
-
...model,
|
|
585
|
-
id: typeof model.id == "string" && model.id.trim() ? model.id : modelId,
|
|
586
|
-
provider: typeof model.provider == "string" && model.provider.trim() ? model.provider : key
|
|
587
|
-
});
|
|
588
|
-
parsed && models.push(parsed);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
return models.length > 0 ? catalogFile(models, value) : void 0;
|
|
592
|
-
}
|
|
593
|
-
function parseOfficialCatalog(value) {
|
|
594
|
-
if (isRecord(value)) {
|
|
595
|
-
if (Array.isArray(value.models)) {
|
|
596
|
-
let models = [];
|
|
597
|
-
for (let entry of value.models) {
|
|
598
|
-
let parsed = parseOfficialEntry(entry);
|
|
599
|
-
parsed && models.push(parsed);
|
|
600
|
-
}
|
|
601
|
-
return catalogFile(models, value);
|
|
602
|
-
}
|
|
603
|
-
if (!("models" in value))
|
|
604
|
-
return parseKeyedCatalog(value);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
function parseProviderIndex(value) {
|
|
608
|
-
if (!(!Array.isArray(value) || !value.every((entry) => typeof entry == "string")))
|
|
609
|
-
return value;
|
|
610
|
-
}
|
|
611
|
-
function readCatalogFile(path) {
|
|
612
|
-
try {
|
|
613
|
-
return existsSync2(path) ? parseOfficialCatalog(JSON.parse(readFileSync2(path, "utf-8"))) : void 0;
|
|
614
|
-
} catch {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
function bundledCatalogCandidates() {
|
|
619
|
-
let here = dirname2(fileURLToPath(new URL("../core/official-catalog.js", import.meta.url).href)), packageDir = getPackageDir();
|
|
620
|
-
return [
|
|
621
|
-
join2(packageDir, "dist", "catalog", "models.json"),
|
|
622
|
-
join2(packageDir, "..", "..", "catalog", "models.json"),
|
|
623
|
-
join2(here, "../../../../catalog/models.json"),
|
|
624
|
-
join2(packageDir, "catalog", "models.json"),
|
|
625
|
-
join2(here, "../catalog/models.json"),
|
|
626
|
-
join2(here, "models.json"),
|
|
627
|
-
join2(packageDir, "dist", "catalog", "official-models.json"),
|
|
628
|
-
join2(packageDir, "..", "..", "catalog", "official-models.json"),
|
|
629
|
-
join2(here, "../../../../catalog/official-models.json"),
|
|
630
|
-
join2(here, "official-models.json"),
|
|
631
|
-
join2(here, "../catalog/official-models.json")
|
|
632
|
-
];
|
|
633
|
-
}
|
|
634
|
-
function loadBundledOfficialCatalog() {
|
|
635
|
-
for (let path of bundledCatalogCandidates()) {
|
|
636
|
-
let parsed = readCatalogFile(path);
|
|
637
|
-
if (parsed)
|
|
638
|
-
return parsed;
|
|
639
|
-
}
|
|
640
|
-
return BUNDLED_OFFICIAL_CATALOG;
|
|
641
|
-
}
|
|
642
|
-
function loadCachedOfficialCatalog(cachePath) {
|
|
643
|
-
if (cachePath)
|
|
644
|
-
return readCatalogFile(cachePath);
|
|
645
|
-
}
|
|
646
|
-
function writeOfficialCatalogCache(catalog, cachePath) {
|
|
647
|
-
let temporary = `${cachePath}.${randomUUID()}.tmp`;
|
|
648
|
-
try {
|
|
649
|
-
mkdirSync2(dirname2(cachePath), { recursive: !0, mode: 448 }), writeFileSync2(temporary, `${JSON.stringify(catalog, null, 2)}
|
|
650
|
-
`, { encoding: "utf-8", mode: 384 }), renameSync2(temporary, cachePath);
|
|
651
|
-
} catch {
|
|
652
|
-
} finally {
|
|
653
|
-
try {
|
|
654
|
-
unlinkSync2(temporary);
|
|
655
|
-
} catch {
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
function officialModelsByProvider(catalog) {
|
|
660
|
-
let byProvider = /* @__PURE__ */ new Map();
|
|
661
|
-
for (let model of catalog.models) {
|
|
662
|
-
let list = byProvider.get(model.provider) ?? [];
|
|
663
|
-
list.push(model), byProvider.set(model.provider, list);
|
|
664
|
-
}
|
|
665
|
-
return byProvider;
|
|
666
|
-
}
|
|
667
|
-
function mergeOfficialCatalogByProvider(base, replacements, updatedAt) {
|
|
668
|
-
let byProvider = officialModelsByProvider(base);
|
|
669
|
-
for (let [providerId, models] of replacements)
|
|
670
|
-
byProvider.set(providerId, models);
|
|
671
|
-
return {
|
|
672
|
-
version: base.version || 1,
|
|
673
|
-
updatedAt: updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
674
|
-
models: [...byProvider.values()].flat()
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
function officialCatalogBase(bundled, cachePath) {
|
|
678
|
-
let cached = loadCachedOfficialCatalog(cachePath);
|
|
679
|
-
return cached ? mergeOfficialCatalogByProvider(bundled, officialModelsByProvider(cached), cached.updatedAt) : bundled;
|
|
680
|
-
}
|
|
681
|
-
function preferOfficialCatalog(previous, next) {
|
|
682
|
-
return next.source === "github" ? next : previous?.source === "github" ? { ...previous, errors: next.errors } : next;
|
|
683
|
-
}
|
|
684
|
-
function officialModelKeys(catalog) {
|
|
685
|
-
return new Set(catalog.models.map((model) => modelKey(model.provider, model.id)));
|
|
686
|
-
}
|
|
687
|
-
var ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
688
|
-
function officialEntryToModel(entry, template) {
|
|
689
|
-
return {
|
|
690
|
-
catalog: entry.catalog,
|
|
691
|
-
id: entry.id,
|
|
692
|
-
name: entry.name,
|
|
693
|
-
api: entry.api || template?.api || "openai-completions",
|
|
694
|
-
provider: entry.provider,
|
|
695
|
-
baseUrl: entry.baseUrl || template?.baseUrl || "",
|
|
696
|
-
reasoning: entry.reasoning,
|
|
697
|
-
input: entry.input.length > 0 ? entry.input : template?.input ?? ["text"],
|
|
698
|
-
cost: entry.cost ?? template?.cost ?? ZERO_COST,
|
|
699
|
-
contextWindow: entry.contextWindow,
|
|
700
|
-
maxTokens: entry.maxTokens,
|
|
701
|
-
compat: entry.compat ?? template?.compat,
|
|
702
|
-
thinkingLevelMap: entry.thinkingLevelMap ?? template?.thinkingLevelMap,
|
|
703
|
-
headers: entry.headers ?? template?.headers
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
function resolveBundledCatalog(bundled) {
|
|
707
|
-
return bundled || loadBundledOfficialCatalog();
|
|
708
|
-
}
|
|
709
|
-
function fallbackCatalog(bundled, cachePath) {
|
|
710
|
-
let cached = loadCachedOfficialCatalog(cachePath);
|
|
711
|
-
if (cached)
|
|
712
|
-
return { catalog: cached, source: "cache" };
|
|
713
|
-
let resolved = resolveBundledCatalog(bundled);
|
|
714
|
-
return resolved.models.length > 0 ? { catalog: resolved, source: "bundled" } : { catalog: BUNDLED_OFFICIAL_CATALOG, source: "bundled" };
|
|
715
|
-
}
|
|
716
|
-
async function fetchJson(url, options) {
|
|
717
|
-
let controller = new AbortController(), timer = setTimeout(() => controller.abort(), options.timeoutMs), onParentAbort = () => controller.abort();
|
|
718
|
-
options.signal?.addEventListener("abort", onParentAbort, { once: !0 }), options.signal?.aborted && controller.abort();
|
|
719
|
-
try {
|
|
720
|
-
let abortError = () => {
|
|
721
|
-
let error = new Error("The operation was aborted");
|
|
722
|
-
return error.name = "AbortError", error;
|
|
723
|
-
};
|
|
724
|
-
return await Promise.race([
|
|
725
|
-
(async () => {
|
|
726
|
-
let response = await options.fetchImpl(url, {
|
|
727
|
-
headers: options.headers,
|
|
728
|
-
signal: controller.signal
|
|
729
|
-
});
|
|
730
|
-
return response.ok ? { ok: !0, value: await response.json() } : { ok: !1, status: response.status };
|
|
731
|
-
})(),
|
|
732
|
-
new Promise((_, reject) => {
|
|
733
|
-
controller.signal.addEventListener("abort", () => reject(abortError()), { once: !0 }), controller.signal.aborted && reject(abortError());
|
|
734
|
-
})
|
|
735
|
-
]);
|
|
736
|
-
} catch {
|
|
737
|
-
return { ok: !1 };
|
|
738
|
-
} finally {
|
|
739
|
-
clearTimeout(timer), options.signal?.removeEventListener("abort", onParentAbort);
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
async function loadOfficialCatalog(options = {}) {
|
|
743
|
-
let cachePath = options.cachePath;
|
|
744
|
-
if (!options.allowNetwork)
|
|
745
|
-
return fallbackCatalog(options.bundled, cachePath);
|
|
746
|
-
let bundled = resolveBundledCatalog(options.bundled), timeoutMs = options.timeoutMs ?? OFFICIAL_CATALOG_TIMEOUT_MS, fetchImpl = options.fetchImpl ?? fetch, headers = {
|
|
747
|
-
accept: "application/json",
|
|
748
|
-
"User-Agent": getPiUserAgent(VERSION)
|
|
749
|
-
}, fetchOptions = { timeoutMs, signal: options.signal, fetchImpl, headers }, unavailable = () => ({
|
|
750
|
-
...fallbackCatalog(bundled, cachePath),
|
|
751
|
-
errors: Object.fromEntries((options.providerIds ?? []).map((id) => [id, "Published catalog unavailable; using cached metadata"]))
|
|
752
|
-
}), base = options.url ?? officialCatalogBaseUrl(), manifest;
|
|
753
|
-
if (!options.url && !process.env.LUNR_OFFICIAL_CATALOG_URL) {
|
|
754
|
-
let result = await fetchJson(`${VERSIONED_CATALOG_URL}/publication.json`, fetchOptions);
|
|
755
|
-
result.ok && isRecord(result.value) && result.value.version === 2 && typeof result.value.revision == "string" && /^sha256-[a-f0-9]{64}$/.test(result.value.revision) && isRecord(result.value.shards) && parseProviderIndex(result.value.providers) && (manifest = result.value, base = `${VERSIONED_CATALOG_URL}/snapshots/${result.value.revision}`);
|
|
756
|
-
}
|
|
757
|
-
try {
|
|
758
|
-
let indexResult = manifest ? { ok: !0, value: manifest.providers } : await fetchJson(officialCatalogUrlFor("providers.json", base), fetchOptions);
|
|
759
|
-
if (!indexResult.ok)
|
|
760
|
-
return unavailable();
|
|
761
|
-
let index = parseProviderIndex(indexResult.value);
|
|
762
|
-
if (!index)
|
|
763
|
-
return unavailable();
|
|
764
|
-
let wanted = new Set(index), shardIds = (options.providerIds ?? []).filter((providerId) => wanted.has(providerId));
|
|
765
|
-
if (shardIds.length === 0)
|
|
766
|
-
return fallbackCatalog(bundled, cachePath);
|
|
767
|
-
let replacements = /* @__PURE__ */ new Map(), errors = {};
|
|
768
|
-
if (await Promise.all(shardIds.map(async (providerId) => {
|
|
769
|
-
let result = await fetchJson(officialCatalogUrlFor(`providers/${encodeURIComponent(providerId)}.json`, base), fetchOptions);
|
|
770
|
-
if (!result.ok) {
|
|
771
|
-
errors[providerId] = "Catalog shard unavailable; using cached metadata";
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
if (manifest && manifest.shards[providerId] !== createHash2("sha256").update(JSON.stringify(result.value)).digest("hex")) {
|
|
775
|
-
errors[providerId] = "Catalog shard checksum mismatch; using cached metadata";
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
let parsed = parseOfficialCatalog(result.value);
|
|
779
|
-
if (!parsed || parsed.models.length === 0 || parsed.models.some((model) => model.provider !== providerId)) {
|
|
780
|
-
errors[providerId] = "Invalid catalog shard; using cached metadata";
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
replacements.set(providerId, parsed.models);
|
|
784
|
-
})), replacements.size === 0)
|
|
785
|
-
return { ...fallbackCatalog(bundled, cachePath), errors };
|
|
786
|
-
let catalog = mergeOfficialCatalogByProvider(officialCatalogBase(bundled, cachePath), replacements, typeof manifest?.generatedAt == "string" ? manifest.generatedAt : void 0);
|
|
787
|
-
return cachePath && writeOfficialCatalogCache(catalog, cachePath), { catalog, source: "github", ...Object.keys(errors).length ? { errors } : {} };
|
|
788
|
-
} catch {
|
|
789
|
-
return unavailable();
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
// packages/coding-agent/dist/core/catalog-merge.js
|
|
794
|
-
function mergeCatalogLayers(args) {
|
|
795
|
-
let byId = /* @__PURE__ */ new Map();
|
|
796
|
-
for (let model of args.bakedIn)
|
|
797
|
-
byId.set(model.id, model);
|
|
798
|
-
for (let model of args.live ?? [])
|
|
799
|
-
byId.set(model.id, model);
|
|
800
|
-
for (let model of args.user ?? [])
|
|
801
|
-
byId.set(model.id, model);
|
|
802
|
-
for (let model of args.official ?? [])
|
|
803
|
-
byId.set(model.id, model);
|
|
804
|
-
let seen = /* @__PURE__ */ new Set(), result = [];
|
|
805
|
-
for (let baked of args.bakedIn) {
|
|
806
|
-
let merged = byId.get(baked.id);
|
|
807
|
-
merged && (result.push(merged), seen.add(baked.id));
|
|
808
|
-
}
|
|
809
|
-
for (let model of [...args.live ?? [], ...args.user ?? [], ...args.official ?? []]) {
|
|
810
|
-
if (seen.has(model.id))
|
|
811
|
-
continue;
|
|
812
|
-
let winner = byId.get(model.id);
|
|
813
|
-
winner && (result.push(winner), seen.add(model.id));
|
|
814
|
-
}
|
|
815
|
-
let liveById = new Map((args.live ?? []).map((model) => [model.id, model])), pricedIds = new Set([...args.bakedIn, ...args.official ?? [], ...args.user ?? []].filter((model) => model.catalog?.pricing !== "unknown").map((model) => model.id));
|
|
816
|
-
return result.map((model) => {
|
|
817
|
-
let resolved = withXaiEffortMetadata(model);
|
|
818
|
-
model.catalog?.supplied.includes("thinkingLevelMap") || (resolved = withOpenAiEffortMetadata(resolved));
|
|
819
|
-
let live = liveById.get(model.id);
|
|
820
|
-
if (!live?.catalog)
|
|
821
|
-
return resolved;
|
|
822
|
-
resolved = { ...resolved, catalog: { ...live.catalog } };
|
|
823
|
-
for (let field of live.catalog.supplied)
|
|
824
|
-
Object.assign(resolved, { [field]: live[field] });
|
|
825
|
-
return (pricedIds.has(model.id) || live.catalog.supplied.includes("cost")) && delete resolved.catalog.pricing, resolved;
|
|
826
|
-
});
|
|
827
|
-
}
|
|
828
|
-
var CatalogOverlaySource = class {
|
|
829
|
-
official = /* @__PURE__ */ new Map();
|
|
830
|
-
user = /* @__PURE__ */ new Map();
|
|
831
|
-
live = /* @__PURE__ */ new Map();
|
|
832
|
-
setOfficial(models) {
|
|
833
|
-
this.official = groupByProvider(models);
|
|
834
|
-
}
|
|
835
|
-
setUser(models) {
|
|
836
|
-
this.user = groupByProvider(models);
|
|
837
|
-
}
|
|
838
|
-
setLive(providerId, models) {
|
|
839
|
-
this.live.set(providerId, [...models]);
|
|
840
|
-
}
|
|
841
|
-
officialFor(providerId) {
|
|
842
|
-
return this.official.get(providerId) ?? [];
|
|
843
|
-
}
|
|
844
|
-
userFor(providerId) {
|
|
845
|
-
return this.user.get(providerId) ?? [];
|
|
846
|
-
}
|
|
847
|
-
liveFor(providerId) {
|
|
848
|
-
return this.live.get(providerId) ?? [];
|
|
849
|
-
}
|
|
850
|
-
/** Codex's complete account catalog is authoritative for picker availability only. */
|
|
851
|
-
isAvailable(model) {
|
|
852
|
-
if (model.catalog?.hidden)
|
|
853
|
-
return !1;
|
|
854
|
-
let live = this.liveFor(model.provider);
|
|
855
|
-
return model.provider !== "openai-codex" || !live.length || live.some((row) => row.id === model.id && !row.catalog?.hidden);
|
|
856
|
-
}
|
|
857
|
-
};
|
|
858
|
-
function groupByProvider(models) {
|
|
859
|
-
let byProvider = /* @__PURE__ */ new Map();
|
|
860
|
-
for (let model of models) {
|
|
861
|
-
let list = byProvider.get(model.provider) ?? [];
|
|
862
|
-
list.push(model), byProvider.set(model.provider, list);
|
|
863
|
-
}
|
|
864
|
-
return byProvider;
|
|
865
|
-
}
|
|
866
|
-
function withCatalogOverlay(provider, overlay) {
|
|
867
|
-
let bakedIn = () => provider.getModels();
|
|
868
|
-
return {
|
|
869
|
-
...provider,
|
|
870
|
-
getModels: () => mergeCatalogLayers({
|
|
871
|
-
bakedIn: bakedIn(),
|
|
872
|
-
live: overlay.liveFor(provider.id),
|
|
873
|
-
user: overlay.userFor(provider.id),
|
|
874
|
-
official: overlay.officialFor(provider.id)
|
|
875
|
-
})
|
|
876
|
-
};
|
|
877
|
-
}
|
|
878
|
-
function formatCatalogRefreshSummary(input) {
|
|
879
|
-
let parts = [];
|
|
880
|
-
if (input.official?.source === "github") {
|
|
881
|
-
let evicted = input.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : "", plural = input.official.evictedUserRows === 1 ? "" : input.official.evictedUserRows > 0 ? "s" : "";
|
|
882
|
-
parts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);
|
|
883
|
-
}
|
|
884
|
-
let refreshed = [], failed = [];
|
|
885
|
-
for (let provider of input.providers)
|
|
886
|
-
if (provider.status === "ok") {
|
|
887
|
-
let added = provider.added ?? 0, total = provider.total ?? 0;
|
|
888
|
-
refreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);
|
|
889
|
-
} else provider.status === "timeout" ? failed.push(`${provider.id} timed out (cached)`) : provider.status === "error" && failed.push(formatLiveProviderError(provider));
|
|
890
|
-
return refreshed.length > 0 ? parts.push(`Refreshed ${refreshed.join(", ")}.`) : input.providers.some((provider) => provider.status === "ok") && parts.push("Refreshed model catalogs."), failed.length > 0 && parts.push(`${failed.join("; ")}.`), input.asked && input.asked.length > 0 && parts.push(`Asked for missing metadata on ${input.asked.join(", ")}.`), input.extraDefaults && input.extraDefaults > 0 && parts.push(`+${input.extraDefaults} more using defaults.`), input.ollama && parts.push(input.ollama), parts.length === 0 ? "Model catalogs refreshed." : parts.join(" ");
|
|
891
|
-
}
|
|
892
|
-
function formatLiveProviderError(provider) {
|
|
893
|
-
return provider.id === "xai" && provider.error && /invalid_grant|refresh token revoked/i.test(provider.error) && !/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error) ? "xai login expired (run /login xai)" : provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;
|
|
894
|
-
}
|
|
895
|
-
function knownModelKeys(bakedIn, official, user) {
|
|
896
|
-
let keys = new Set(official);
|
|
897
|
-
for (let key of user)
|
|
898
|
-
keys.add(key);
|
|
899
|
-
for (let model of bakedIn)
|
|
900
|
-
keys.add(modelKey(model.provider, model.id));
|
|
901
|
-
return keys;
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
// packages/coding-agent/dist/core/grok-cli-auth.js
|
|
905
|
-
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
906
|
-
import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
907
|
-
import { homedir } from "node:os";
|
|
908
|
-
import { dirname as dirname3, join as join3 } from "node:path";
|
|
909
|
-
var XAI_PROVIDER_ID = "xai", XAI_GROK_CLI_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828", REFRESH_SKEW_MS = 300 * 1e3, AUTH_FILE_WRITE_OPTIONS2 = { encoding: "utf-8", mode: 384 };
|
|
910
|
-
function grokHomeDir(grokHome) {
|
|
911
|
-
if (grokHome)
|
|
912
|
-
return grokHome;
|
|
913
|
-
let fromEnv = process.env.GROK_HOME?.trim();
|
|
914
|
-
return fromEnv || join3(homedir(), ".grok");
|
|
915
|
-
}
|
|
916
|
-
function grokAuthPath(grokHome) {
|
|
917
|
-
return join3(grokHomeDir(grokHome), "auth.json");
|
|
918
|
-
}
|
|
919
|
-
function grokOidcEntryKey(clientId = XAI_GROK_CLI_CLIENT_ID) {
|
|
920
|
-
return `https://auth.x.ai::${clientId}`;
|
|
921
|
-
}
|
|
922
|
-
function parseGrokExpiresAt(value) {
|
|
923
|
-
if (typeof value == "number" && Number.isFinite(value) && value > 0)
|
|
924
|
-
return value < 1e12 ? Math.round(value * 1e3) : Math.round(value);
|
|
925
|
-
if (typeof value == "string" && value.trim()) {
|
|
926
|
-
let numeric = Number(value);
|
|
927
|
-
if (Number.isFinite(numeric) && numeric > 0)
|
|
928
|
-
return numeric < 1e12 ? Math.round(numeric * 1e3) : Math.round(numeric);
|
|
929
|
-
let parsed = Date.parse(value);
|
|
930
|
-
if (Number.isFinite(parsed))
|
|
931
|
-
return parsed;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
function formatGrokExpiresAt(expires) {
|
|
935
|
-
return new Date(expires).toISOString();
|
|
936
|
-
}
|
|
937
|
-
function grokEntryToOAuth(entry) {
|
|
938
|
-
if (!entry || typeof entry != "object" || Array.isArray(entry))
|
|
939
|
-
return;
|
|
940
|
-
let record = entry, access = typeof record.key == "string" ? record.key : void 0, refresh = typeof record.refresh_token == "string" ? record.refresh_token : void 0, expires = parseGrokExpiresAt(record.expires_at);
|
|
941
|
-
if (!(!access || !refresh || expires === void 0))
|
|
942
|
-
return { type: "oauth", access, refresh, expires };
|
|
943
|
-
}
|
|
944
|
-
function readGrokCliXaiOAuth(options = {}) {
|
|
945
|
-
try {
|
|
946
|
-
let raw = readFileSync3(grokAuthPath(options.grokHome), "utf-8"), parsed = JSON.parse(raw);
|
|
947
|
-
return !parsed || typeof parsed != "object" || Array.isArray(parsed) ? void 0 : grokEntryToOAuth(parsed[grokOidcEntryKey()]);
|
|
948
|
-
} catch {
|
|
949
|
-
return;
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
function hasGrokCliXaiAuth(options = {}) {
|
|
953
|
-
return readGrokCliXaiOAuth(options) !== void 0;
|
|
954
|
-
}
|
|
955
|
-
function chooseXaiOAuth(lunr, grok) {
|
|
956
|
-
if (lunr?.type === "api_key")
|
|
957
|
-
return lunr;
|
|
958
|
-
let lunrOAuth = lunr?.type === "oauth" ? lunr : void 0;
|
|
959
|
-
if (lunrOAuth && grok) {
|
|
960
|
-
if (lunrOAuth.refresh === grok.refresh)
|
|
961
|
-
return grok.expires >= lunrOAuth.expires ? grok : lunrOAuth;
|
|
962
|
-
let now = Date.now(), lunrLive = now < lunrOAuth.expires, grokLive = now < grok.expires;
|
|
963
|
-
return grokLive && !lunrLive ? grok : lunrLive && !grokLive ? lunrOAuth : !lunrLive && !grokLive && grok.expires >= lunrOAuth.expires ? grok : lunrOAuth;
|
|
964
|
-
}
|
|
965
|
-
return grok ?? lunrOAuth ?? lunr;
|
|
966
|
-
}
|
|
967
|
-
function oauthRefreshFailed(error) {
|
|
968
|
-
let parts = [], current = error, seen = /* @__PURE__ */ new Set();
|
|
969
|
-
for (; current && typeof current == "object" && !seen.has(current); ) {
|
|
970
|
-
if (seen.add(current), current instanceof Error) {
|
|
971
|
-
parts.push(current.message), current = current.cause;
|
|
972
|
-
continue;
|
|
973
|
-
}
|
|
974
|
-
break;
|
|
975
|
-
}
|
|
976
|
-
let chain = parts.join(" ");
|
|
977
|
-
return /timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(chain) ? !1 : /invalid_grant|refresh token revoked/i.test(chain);
|
|
978
|
-
}
|
|
979
|
-
function shouldAdopt(lunr, chosen) {
|
|
980
|
-
return !chosen || chosen.type !== "oauth" ? !1 : !lunr || lunr.type !== "oauth" ? !0 : lunr.access !== chosen.access || lunr.refresh !== chosen.refresh;
|
|
981
|
-
}
|
|
982
|
-
function writeAuthFileAtomic2(authPath, contents) {
|
|
983
|
-
let tmp = `${authPath}.${process.pid}.${Date.now()}.tmp`;
|
|
984
|
-
writeFileSync3(tmp, contents, AUTH_FILE_WRITE_OPTIONS2);
|
|
985
|
-
try {
|
|
986
|
-
chmodSync2(tmp, 384);
|
|
987
|
-
} catch {
|
|
988
|
-
}
|
|
989
|
-
try {
|
|
990
|
-
if (process.platform === "win32" && existsSync3(authPath)) {
|
|
991
|
-
writeFileSync3(authPath, contents, AUTH_FILE_WRITE_OPTIONS2), chmodSync2(authPath, 384);
|
|
992
|
-
return;
|
|
993
|
-
}
|
|
994
|
-
renameSync3(tmp, authPath);
|
|
995
|
-
try {
|
|
996
|
-
chmodSync2(authPath, 384);
|
|
997
|
-
} catch {
|
|
998
|
-
}
|
|
999
|
-
} finally {
|
|
1000
|
-
try {
|
|
1001
|
-
unlinkSync3(tmp);
|
|
1002
|
-
} catch {
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
function acquireGrokLock(authPath) {
|
|
1007
|
-
let lastError;
|
|
1008
|
-
for (let attempt = 1; attempt <= 10; attempt++)
|
|
1009
|
-
try {
|
|
1010
|
-
return import_proper_lockfile2.default.lockSync(authPath, { realpath: !1, stale: 12e4 });
|
|
1011
|
-
} catch (error) {
|
|
1012
|
-
if ((typeof error == "object" && error !== null && "code" in error ? String(error.code) : void 0) !== "ELOCKED" || attempt === 10)
|
|
1013
|
-
throw error;
|
|
1014
|
-
lastError = error;
|
|
1015
|
-
let start = Date.now();
|
|
1016
|
-
for (; Date.now() - start < 20; )
|
|
1017
|
-
;
|
|
1018
|
-
}
|
|
1019
|
-
throw lastError ?? new Error("Failed to acquire Grok CLI auth lock");
|
|
1020
|
-
}
|
|
1021
|
-
function writeGrokCliXaiOAuth(credential, options = {}) {
|
|
1022
|
-
let authPath = grokAuthPath(options.grokHome);
|
|
1023
|
-
if (options.onlyIfFileExists !== !1 && !existsSync3(authPath))
|
|
1024
|
-
return !1;
|
|
1025
|
-
let dir = dirname3(authPath);
|
|
1026
|
-
existsSync3(dir) || mkdirSync3(dir, { recursive: !0, mode: 448 }), existsSync3(authPath) || writeAuthFileAtomic2(authPath, `{}
|
|
1027
|
-
`);
|
|
1028
|
-
let release;
|
|
1029
|
-
try {
|
|
1030
|
-
release = acquireGrokLock(authPath);
|
|
1031
|
-
let data = {};
|
|
1032
|
-
try {
|
|
1033
|
-
let parsed = JSON.parse(readFileSync3(authPath, "utf-8"));
|
|
1034
|
-
if (parsed && typeof parsed == "object" && !Array.isArray(parsed))
|
|
1035
|
-
data = parsed;
|
|
1036
|
-
else
|
|
1037
|
-
return !1;
|
|
1038
|
-
} catch {
|
|
1039
|
-
return !1;
|
|
1040
|
-
}
|
|
1041
|
-
let key = grokOidcEntryKey(), previous = data[key] && typeof data[key] == "object" && !Array.isArray(data[key]) ? data[key] : {}, existing = grokEntryToOAuth(previous);
|
|
1042
|
-
return existing && existing.refresh !== credential.refresh && existing.expires > credential.expires + REFRESH_SKEW_MS ? !1 : (data[key] = {
|
|
1043
|
-
...previous,
|
|
1044
|
-
key: credential.access,
|
|
1045
|
-
refresh_token: credential.refresh,
|
|
1046
|
-
expires_at: formatGrokExpiresAt(credential.expires)
|
|
1047
|
-
}, writeAuthFileAtomic2(authPath, `${JSON.stringify(data, null, 2)}
|
|
1048
|
-
`), !0);
|
|
1049
|
-
} finally {
|
|
1050
|
-
if (release)
|
|
1051
|
-
try {
|
|
1052
|
-
release();
|
|
1053
|
-
} catch {
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
function wrapXaiGrokCliCredentials(store, options = {}) {
|
|
1058
|
-
let grokHome = options.grokHome;
|
|
1059
|
-
return {
|
|
1060
|
-
async read(providerId) {
|
|
1061
|
-
let stored = await store.read(providerId);
|
|
1062
|
-
if (providerId !== XAI_PROVIDER_ID || stored?.type === "api_key")
|
|
1063
|
-
return stored;
|
|
1064
|
-
let grok = readGrokCliXaiOAuth({ grokHome }), chosen = chooseXaiOAuth(stored, grok);
|
|
1065
|
-
if (shouldAdopt(stored, chosen) && chosen?.type === "oauth")
|
|
1066
|
-
try {
|
|
1067
|
-
await store.modify(providerId, async (current) => {
|
|
1068
|
-
if (current?.type === "api_key")
|
|
1069
|
-
return;
|
|
1070
|
-
let latestGrok = readGrokCliXaiOAuth({ grokHome }), latestChosen = chooseXaiOAuth(current, latestGrok);
|
|
1071
|
-
if (shouldAdopt(current, latestChosen) && latestChosen?.type === "oauth")
|
|
1072
|
-
return latestChosen;
|
|
1073
|
-
});
|
|
1074
|
-
} catch {
|
|
1075
|
-
}
|
|
1076
|
-
return chosen;
|
|
1077
|
-
},
|
|
1078
|
-
async list() {
|
|
1079
|
-
let entries = new Map((await store.list()).map((entry) => [entry.providerId, entry]));
|
|
1080
|
-
return !entries.has(XAI_PROVIDER_ID) && hasGrokCliXaiAuth({ grokHome }) && entries.set(XAI_PROVIDER_ID, { providerId: XAI_PROVIDER_ID, type: "oauth" }), [...entries.values()];
|
|
1081
|
-
},
|
|
1082
|
-
modify(providerId, fn) {
|
|
1083
|
-
return providerId !== XAI_PROVIDER_ID ? store.modify(providerId, fn) : store.modify(providerId, async (lunrCurrent) => {
|
|
1084
|
-
if (lunrCurrent?.type === "api_key")
|
|
1085
|
-
return fn(lunrCurrent);
|
|
1086
|
-
let grok = readGrokCliXaiOAuth({ grokHome }), chosen = chooseXaiOAuth(lunrCurrent, grok), next;
|
|
1087
|
-
try {
|
|
1088
|
-
next = await fn(chosen);
|
|
1089
|
-
} catch (error) {
|
|
1090
|
-
let retryGrok = readGrokCliXaiOAuth({ grokHome });
|
|
1091
|
-
if (!(oauthRefreshFailed(error) && retryGrok && !(chosen?.type === "oauth" && retryGrok.refresh === chosen.refresh)))
|
|
1092
|
-
throw error;
|
|
1093
|
-
try {
|
|
1094
|
-
next = await fn(retryGrok);
|
|
1095
|
-
} catch {
|
|
1096
|
-
throw error;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
if (next?.type === "oauth")
|
|
1100
|
-
try {
|
|
1101
|
-
writeGrokCliXaiOAuth(next, { grokHome, onlyIfFileExists: !0 });
|
|
1102
|
-
} catch {
|
|
1103
|
-
}
|
|
1104
|
-
return next;
|
|
1105
|
-
});
|
|
1106
|
-
},
|
|
1107
|
-
delete(providerId) {
|
|
1108
|
-
return store.delete(providerId);
|
|
1109
|
-
}
|
|
1110
|
-
};
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
// packages/coding-agent/dist/core/live-catalog.js
|
|
1114
|
-
import { isOpenAiChatModel, parseOpenAiGptVersion } from "@ashx-j/lunr-ai";
|
|
1115
|
-
import { codexModelsUrl, resolveCodexCatalogVersion } from "@ashx-j/lunr-ai/catalog/codex";
|
|
1116
|
-
import { normalizeCatalogPricing } from "@ashx-j/lunr-ai/catalog/metadata";
|
|
1117
|
-
|
|
1118
|
-
// packages/coding-agent/dist/core/codex-catalog.js
|
|
1119
|
-
import { parseCodexCatalog } from "@ashx-j/lunr-ai/catalog/codex";
|
|
1120
|
-
function discoverCodexModels(payload, baseUrl) {
|
|
1121
|
-
return parseCodexCatalog(payload, baseUrl).map((model) => ({
|
|
1122
|
-
model,
|
|
1123
|
-
supplied: {
|
|
1124
|
-
name: model.catalog.supplied.includes("name"),
|
|
1125
|
-
contextWindow: model.catalog.supplied.includes("contextWindow"),
|
|
1126
|
-
maxTokens: model.catalog.supplied.includes("maxTokens"),
|
|
1127
|
-
input: model.catalog.supplied.includes("input"),
|
|
1128
|
-
cost: !1,
|
|
1129
|
-
reasoning: model.catalog.supplied.includes("reasoning")
|
|
1130
|
-
}
|
|
1131
|
-
}));
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
// packages/coding-agent/dist/core/live-catalog.js
|
|
1135
|
-
var LIVE_CATALOG_TIMEOUT_MS = 4e3;
|
|
1136
|
-
var DEFAULT_CONTEXT_WINDOW = 128e3, DEFAULT_MAX_TOKENS = 8192, LIVE_LIST_PROVIDER_IDS = [
|
|
1137
|
-
"openai-codex",
|
|
1138
|
-
"xai",
|
|
1139
|
-
"openrouter",
|
|
1140
|
-
"qwen-cloud",
|
|
1141
|
-
"qwen-cloud-cn",
|
|
1142
|
-
"groq",
|
|
1143
|
-
"openai",
|
|
1144
|
-
"deepseek"
|
|
1145
|
-
], LIVE_LIST_PROVIDER_SET = new Set(LIVE_LIST_PROVIDER_IDS);
|
|
1146
|
-
var ZERO_COST2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, NONE_SUPPLIED = {
|
|
1147
|
-
contextWindow: !1,
|
|
1148
|
-
maxTokens: !1,
|
|
1149
|
-
input: !1,
|
|
1150
|
-
name: !1,
|
|
1151
|
-
cost: !1,
|
|
1152
|
-
reasoning: !1
|
|
1153
|
-
};
|
|
1154
|
-
function isRecord2(value) {
|
|
1155
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
1156
|
-
}
|
|
1157
|
-
function asFiniteNumber2(value) {
|
|
1158
|
-
if (typeof value == "number" && Number.isFinite(value))
|
|
1159
|
-
return value;
|
|
1160
|
-
if (typeof value == "string" && value.trim()) {
|
|
1161
|
-
let parsed = Number(value);
|
|
1162
|
-
if (Number.isFinite(parsed))
|
|
1163
|
-
return parsed;
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
function roundCost(value) {
|
|
1167
|
-
return Number(value.toFixed(6));
|
|
1168
|
-
}
|
|
1169
|
-
function modelsListUrl(baseUrl) {
|
|
1170
|
-
return `${baseUrl.replace(/\/+$/u, "")}/models`;
|
|
1171
|
-
}
|
|
1172
|
-
function credentialAuthHeaders(credential) {
|
|
1173
|
-
return credential ? credential.type === "api_key" && credential.key ? { Authorization: `Bearer ${credential.key}` } : credential.type === "oauth" && typeof credential.access == "string" && credential.access ? { Authorization: `Bearer ${credential.access}` } : {} : {};
|
|
1174
|
-
}
|
|
1175
|
-
function parseOpenAIModelsList(value) {
|
|
1176
|
-
let entries = isRecord2(value) && Array.isArray(value.data) ? value.data : Array.isArray(value) ? value : [], rows = [];
|
|
1177
|
-
for (let entry of entries) {
|
|
1178
|
-
if (typeof entry == "string" && entry.trim()) {
|
|
1179
|
-
rows.push({ id: entry.trim() });
|
|
1180
|
-
continue;
|
|
1181
|
-
}
|
|
1182
|
-
isRecord2(entry) && typeof entry.id == "string" && entry.id.trim() && rows.push(entry);
|
|
1183
|
-
}
|
|
1184
|
-
return rows;
|
|
1185
|
-
}
|
|
1186
|
-
function firstBakedInModel(models) {
|
|
1187
|
-
return models[0];
|
|
1188
|
-
}
|
|
1189
|
-
function selectLiveTemplate(providerId, id, bakedIn) {
|
|
1190
|
-
let exact = bakedIn.find((model) => model.id === id);
|
|
1191
|
-
if (exact)
|
|
1192
|
-
return exact;
|
|
1193
|
-
let version = parseOpenAiGptVersion(id);
|
|
1194
|
-
if (providerId !== "openai" || !version || version.major < 5 || isOpenAiChatModel(id))
|
|
1195
|
-
return firstBakedInModel(bakedIn);
|
|
1196
|
-
let reasoning;
|
|
1197
|
-
for (let model of bakedIn)
|
|
1198
|
-
model.reasoning && parseOpenAiGptVersion(model.id) && (reasoning = model);
|
|
1199
|
-
return reasoning ?? firstBakedInModel(bakedIn);
|
|
1200
|
-
}
|
|
1201
|
-
function uniqueApis(models) {
|
|
1202
|
-
let seen = /* @__PURE__ */ new Set(), apis = [];
|
|
1203
|
-
for (let model of models)
|
|
1204
|
-
seen.has(model.api) || (seen.add(model.api), apis.push(model.api));
|
|
1205
|
-
return apis;
|
|
1206
|
-
}
|
|
1207
|
-
function synthesizeLiveModel(id, template, raw = {}) {
|
|
1208
|
-
let name = typeof raw.name == "string" && raw.name.trim() ? raw.name.trim() : id, exact = id === template.id, discovery = {
|
|
1209
|
-
model: {
|
|
1210
|
-
id,
|
|
1211
|
-
name,
|
|
1212
|
-
api: template.api,
|
|
1213
|
-
provider: template.provider,
|
|
1214
|
-
baseUrl: template.baseUrl,
|
|
1215
|
-
reasoning: template.reasoning,
|
|
1216
|
-
input: exact ? template.input : ["text"],
|
|
1217
|
-
cost: ZERO_COST2,
|
|
1218
|
-
contextWindow: DEFAULT_CONTEXT_WINDOW,
|
|
1219
|
-
maxTokens: DEFAULT_MAX_TOKENS,
|
|
1220
|
-
compat: template.compat,
|
|
1221
|
-
thinkingLevelMap: exact ? template.thinkingLevelMap : void 0,
|
|
1222
|
-
catalog: { source: "provider", supplied: typeof raw.name == "string" ? ["name"] : [], pricing: "unknown" }
|
|
1223
|
-
},
|
|
1224
|
-
supplied: {
|
|
1225
|
-
...NONE_SUPPLIED,
|
|
1226
|
-
name: typeof raw.name == "string" && raw.name.trim().length > 0
|
|
1227
|
-
}
|
|
1228
|
-
}, context = asFiniteNumber2(raw.context_window ?? raw.context_length ?? raw.max_context_length), output = asFiniteNumber2(raw.max_output_tokens ?? raw.max_completion_tokens);
|
|
1229
|
-
if (context && context > 0 && (discovery.model.contextWindow = context, discovery.supplied.contextWindow = !0), output && output > 0 && (discovery.model.maxTokens = output, discovery.supplied.maxTokens = !0), typeof raw.reasoning == "boolean" && (discovery.model.reasoning = raw.reasoning, discovery.supplied.reasoning = !0), Array.isArray(raw.input_modalities)) {
|
|
1230
|
-
let input = raw.input_modalities.filter((value) => value === "text" || value === "image");
|
|
1231
|
-
input.length && (discovery.model.input = input, discovery.supplied.input = !0);
|
|
1232
|
-
}
|
|
1233
|
-
return discovery.model.catalog.supplied = Object.entries(discovery.supplied).filter(([, value]) => value).map(([field]) => field), discovery;
|
|
1234
|
-
}
|
|
1235
|
-
function mapOpenRouterModel(raw, template) {
|
|
1236
|
-
let id = typeof raw.id == "string" ? raw.id.trim() : "";
|
|
1237
|
-
if (!id)
|
|
1238
|
-
return;
|
|
1239
|
-
let supported = Array.isArray(raw.supported_parameters) ? raw.supported_parameters : [];
|
|
1240
|
-
if (!supported.includes("tools"))
|
|
1241
|
-
return;
|
|
1242
|
-
let architecture = isRecord2(raw.architecture) ? raw.architecture : void 0, modality = typeof architecture?.modality == "string" ? architecture.modality : "", input = ["text"];
|
|
1243
|
-
modality.includes("image") && input.push("image");
|
|
1244
|
-
let pricing = isRecord2(raw.pricing) ? raw.pricing : void 0, inputCost = roundCost((asFiniteNumber2(pricing?.prompt) ?? 0) * 1e6), outputCost = roundCost((asFiniteNumber2(pricing?.completion) ?? 0) * 1e6), cacheReadCost = roundCost((asFiniteNumber2(pricing?.input_cache_read) ?? 0) * 1e6), cacheWriteCost = roundCost((asFiniteNumber2(pricing?.input_cache_write) ?? 0) * 1e6), topProvider = isRecord2(raw.top_provider) ? raw.top_provider : void 0, contextWindow = asFiniteNumber2(topProvider?.context_length) ?? asFiniteNumber2(raw.context_length), maxTokens = asFiniteNumber2(topProvider?.max_completion_tokens) ?? asFiniteNumber2(raw.max_completion_tokens), name = typeof raw.name == "string" && raw.name.trim() ? raw.name.trim() : id;
|
|
1245
|
-
return {
|
|
1246
|
-
model: {
|
|
1247
|
-
id,
|
|
1248
|
-
name,
|
|
1249
|
-
api: template.api,
|
|
1250
|
-
provider: template.provider,
|
|
1251
|
-
baseUrl: template.baseUrl,
|
|
1252
|
-
reasoning: supported.includes("reasoning") || template.reasoning,
|
|
1253
|
-
input,
|
|
1254
|
-
cost: {
|
|
1255
|
-
input: inputCost,
|
|
1256
|
-
output: outputCost,
|
|
1257
|
-
cacheRead: cacheReadCost,
|
|
1258
|
-
cacheWrite: cacheWriteCost
|
|
1259
|
-
},
|
|
1260
|
-
contextWindow: contextWindow ?? DEFAULT_CONTEXT_WINDOW,
|
|
1261
|
-
maxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
1262
|
-
compat: template.compat,
|
|
1263
|
-
thinkingLevelMap: template.thinkingLevelMap
|
|
1264
|
-
},
|
|
1265
|
-
supplied: {
|
|
1266
|
-
contextWindow: contextWindow !== void 0,
|
|
1267
|
-
maxTokens: maxTokens !== void 0,
|
|
1268
|
-
input: !0,
|
|
1269
|
-
name: typeof raw.name == "string" && raw.name.trim().length > 0,
|
|
1270
|
-
cost: asFiniteNumber2(pricing?.prompt) !== void 0 && asFiniteNumber2(pricing?.completion) !== void 0,
|
|
1271
|
-
reasoning: supported.includes("reasoning")
|
|
1272
|
-
}
|
|
1273
|
-
};
|
|
1274
|
-
}
|
|
1275
|
-
function discoverLiveModels(providerId, payload, bakedIn) {
|
|
1276
|
-
if (providerId === "openai-codex")
|
|
1277
|
-
return discoverCodexModels(payload, bakedIn[0]?.baseUrl ?? "https://chatgpt.com/backend-api");
|
|
1278
|
-
let fallback = firstBakedInModel(bakedIn);
|
|
1279
|
-
if (!fallback)
|
|
1280
|
-
return [];
|
|
1281
|
-
let rows = parseOpenAIModelsList(payload), discoveries = [];
|
|
1282
|
-
for (let raw of rows) {
|
|
1283
|
-
let id = typeof raw.id == "string" ? raw.id.trim() : "";
|
|
1284
|
-
if (!id || raw.tool_call === !1 || raw.type === "embedding" || providerId === "openai" && /^(?:text-embedding-|tts-|whisper-|dall-e-|gpt-image-|gpt-audio|gpt-realtime|sora-|.*moderation)/i.test(id))
|
|
1285
|
-
continue;
|
|
1286
|
-
let template = { ...selectLiveTemplate(providerId, id, bakedIn) ?? fallback, provider: providerId };
|
|
1287
|
-
if (providerId === "openrouter") {
|
|
1288
|
-
let mapped = mapOpenRouterModel(raw, template);
|
|
1289
|
-
mapped && (mapped.model.catalog = {
|
|
1290
|
-
source: "provider",
|
|
1291
|
-
...mapped.supplied.cost ? {} : { pricing: "unknown" },
|
|
1292
|
-
supplied: Object.entries(mapped.supplied).filter(([, supplied]) => supplied).map(([key]) => key)
|
|
1293
|
-
}, mapped.model = normalizeCatalogPricing(mapped.model), mapped.model.catalog?.pricing === "unknown" && (mapped.supplied.cost = !1), discoveries.push(mapped));
|
|
1294
|
-
continue;
|
|
1295
|
-
}
|
|
1296
|
-
discoveries.push(synthesizeLiveModel(id, template, raw));
|
|
1297
|
-
}
|
|
1298
|
-
return discoveries;
|
|
1299
|
-
}
|
|
1300
|
-
function missingLiveFields(supplied) {
|
|
1301
|
-
let missing = [];
|
|
1302
|
-
return supplied.contextWindow || missing.push("contextWindow"), supplied.maxTokens || missing.push("maxTokens"), supplied.input || missing.push("input"), missing;
|
|
1303
|
-
}
|
|
1304
|
-
function isLiveModelIncomplete(discovery, knownKeys) {
|
|
1305
|
-
return knownKeys.has(modelKey(discovery.model.provider, discovery.model.id)) ? !1 : missingLiveFields(discovery.supplied).length > 0;
|
|
1306
|
-
}
|
|
1307
|
-
function collectIncompleteLiveModels(discoveries, bakedIn, knownKeys) {
|
|
1308
|
-
let apis = uniqueApis(bakedIn), incomplete = [];
|
|
1309
|
-
for (let discovery of discoveries)
|
|
1310
|
-
isLiveModelIncomplete(discovery, knownKeys) && incomplete.push({
|
|
1311
|
-
provider: discovery.model.provider,
|
|
1312
|
-
id: discovery.model.id,
|
|
1313
|
-
name: discovery.model.name,
|
|
1314
|
-
missing: missingLiveFields(discovery.supplied),
|
|
1315
|
-
draft: discovery.model,
|
|
1316
|
-
availableApis: apis
|
|
1317
|
-
});
|
|
1318
|
-
return incomplete;
|
|
1319
|
-
}
|
|
1320
|
-
function buildLiveOverlay(bakedIn, discoveries) {
|
|
1321
|
-
let bakedById = new Map(bakedIn.map((model) => [model.id, model])), overlay = [];
|
|
1322
|
-
for (let discovery of discoveries) {
|
|
1323
|
-
let baked = bakedById.get(discovery.model.id);
|
|
1324
|
-
if (!baked) {
|
|
1325
|
-
overlay.push(discovery.model);
|
|
1326
|
-
continue;
|
|
1327
|
-
}
|
|
1328
|
-
overlay.push({
|
|
1329
|
-
...baked,
|
|
1330
|
-
catalog: discovery.model.catalog,
|
|
1331
|
-
thinkingLevelMap: discovery.model.catalog?.supplied.includes("thinkingLevelMap") ? discovery.model.thinkingLevelMap : baked.thinkingLevelMap,
|
|
1332
|
-
name: discovery.supplied.name ? discovery.model.name : baked.name,
|
|
1333
|
-
contextWindow: discovery.supplied.contextWindow ? discovery.model.contextWindow : baked.contextWindow,
|
|
1334
|
-
maxTokens: discovery.supplied.maxTokens ? discovery.model.maxTokens : baked.maxTokens,
|
|
1335
|
-
input: discovery.supplied.input ? discovery.model.input : baked.input,
|
|
1336
|
-
cost: discovery.supplied.cost ? discovery.model.cost : baked.cost,
|
|
1337
|
-
reasoning: discovery.supplied.reasoning ? discovery.model.reasoning : baked.reasoning
|
|
1338
|
-
});
|
|
1339
|
-
}
|
|
1340
|
-
return overlay;
|
|
1341
|
-
}
|
|
1342
|
-
async function fetchLiveProviderModels(options) {
|
|
1343
|
-
let empty = {
|
|
1344
|
-
providerId: options.providerId,
|
|
1345
|
-
status: "skipped",
|
|
1346
|
-
discoveries: [],
|
|
1347
|
-
added: 0,
|
|
1348
|
-
total: 0,
|
|
1349
|
-
incomplete: []
|
|
1350
|
-
};
|
|
1351
|
-
if (!firstBakedInModel(options.bakedIn) && options.providerId !== "openai-codex" || !options.baseUrl)
|
|
1352
|
-
return empty;
|
|
1353
|
-
let timeoutMs = options.timeoutMs ?? LIVE_CATALOG_TIMEOUT_MS, controller = new AbortController(), timedOut = !1, timer = setTimeout(() => {
|
|
1354
|
-
timedOut = !0, controller.abort();
|
|
1355
|
-
}, timeoutMs), onParentAbort = () => controller.abort();
|
|
1356
|
-
options.signal?.addEventListener("abort", onParentAbort, { once: !0 }), options.signal?.aborted && controller.abort();
|
|
1357
|
-
try {
|
|
1358
|
-
let fetchImpl = options.fetchImpl ?? fetch, codex = options.providerId === "openai-codex", accountId = options.credential?.type === "oauth" && typeof options.credential.accountId == "string" ? options.credential.accountId : void 0, discoveryClientVersion = options.discoveryClientVersion, payload = await Promise.race([
|
|
1359
|
-
(async () => {
|
|
1360
|
-
codex && (discoveryClientVersion = await resolveCodexCatalogVersion(fetchImpl, controller.signal, discoveryClientVersion));
|
|
1361
|
-
let response = await fetchImpl(codex ? codexModelsUrl(options.baseUrl, discoveryClientVersion) : modelsListUrl(options.baseUrl), {
|
|
1362
|
-
headers: {
|
|
1363
|
-
accept: "application/json",
|
|
1364
|
-
"User-Agent": getPiUserAgent(VERSION),
|
|
1365
|
-
...credentialAuthHeaders(options.credential),
|
|
1366
|
-
...accountId ? { "ChatGPT-Account-ID": accountId } : {}
|
|
1367
|
-
},
|
|
1368
|
-
signal: controller.signal
|
|
1369
|
-
});
|
|
1370
|
-
if (!response.ok)
|
|
1371
|
-
throw new Error(`HTTP ${response.status}`);
|
|
1372
|
-
return response.json();
|
|
1373
|
-
})(),
|
|
1374
|
-
new Promise((_, reject) => {
|
|
1375
|
-
let abortError = new Error("The operation was aborted");
|
|
1376
|
-
abortError.name = "AbortError", controller.signal.addEventListener("abort", () => reject(abortError), { once: !0 }), controller.signal.aborted && reject(abortError);
|
|
1377
|
-
})
|
|
1378
|
-
]), discoveries = codex ? discoverCodexModels(payload, options.baseUrl) : discoverLiveModels(options.providerId, payload, options.bakedIn);
|
|
1379
|
-
if (!discoveries.length)
|
|
1380
|
-
throw new Error("No usable models returned; retaining cached models");
|
|
1381
|
-
let bakedIds = new Set(options.bakedIn.map((model) => model.id)), added = discoveries.filter((discovery) => !bakedIds.has(discovery.model.id)).length;
|
|
1382
|
-
return {
|
|
1383
|
-
providerId: options.providerId,
|
|
1384
|
-
discoveryClientVersion,
|
|
1385
|
-
status: "ok",
|
|
1386
|
-
discoveries,
|
|
1387
|
-
added,
|
|
1388
|
-
total: discoveries.length,
|
|
1389
|
-
incomplete: collectIncompleteLiveModels(discoveries, options.bakedIn, options.knownKeys)
|
|
1390
|
-
};
|
|
1391
|
-
} catch (error) {
|
|
1392
|
-
return options.signal?.aborted && !timedOut ? { ...empty, status: "skipped", error: "aborted" } : timedOut || error instanceof Error && error.name === "AbortError" ? { ...empty, status: "timeout", error: "timed out" } : {
|
|
1393
|
-
...empty,
|
|
1394
|
-
status: "error",
|
|
1395
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1396
|
-
};
|
|
1397
|
-
} finally {
|
|
1398
|
-
clearTimeout(timer), options.signal?.removeEventListener("abort", onParentAbort);
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
// packages/coding-agent/dist/core/model-config.js
|
|
1403
|
-
import { readFile } from "node:fs/promises";
|
|
1404
|
-
import { Type } from "typebox";
|
|
1405
|
-
import { Compile } from "typebox/compile";
|
|
1406
|
-
|
|
1407
|
-
// packages/coding-agent/dist/utils/json.js
|
|
1408
|
-
function stripJsonComments(input) {
|
|
1409
|
-
return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (m) => m[0] === '"' ? m : "").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (m, tail) => tail ?? (m[0] === '"' ? m : ""));
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
// packages/coding-agent/dist/core/model-config.js
|
|
1413
|
-
var PercentileCutoffsSchema = Type.Object({
|
|
1414
|
-
p50: Type.Optional(Type.Number()),
|
|
1415
|
-
p75: Type.Optional(Type.Number()),
|
|
1416
|
-
p90: Type.Optional(Type.Number()),
|
|
1417
|
-
p99: Type.Optional(Type.Number())
|
|
1418
|
-
}), OpenRouterRoutingSchema = Type.Object({
|
|
1419
|
-
allow_fallbacks: Type.Optional(Type.Boolean()),
|
|
1420
|
-
require_parameters: Type.Optional(Type.Boolean()),
|
|
1421
|
-
data_collection: Type.Optional(Type.Union([Type.Literal("deny"), Type.Literal("allow")])),
|
|
1422
|
-
zdr: Type.Optional(Type.Boolean()),
|
|
1423
|
-
enforce_distillable_text: Type.Optional(Type.Boolean()),
|
|
1424
|
-
order: Type.Optional(Type.Array(Type.String())),
|
|
1425
|
-
only: Type.Optional(Type.Array(Type.String())),
|
|
1426
|
-
ignore: Type.Optional(Type.Array(Type.String())),
|
|
1427
|
-
quantizations: Type.Optional(Type.Array(Type.String())),
|
|
1428
|
-
sort: Type.Optional(Type.Union([
|
|
1429
|
-
Type.String(),
|
|
1430
|
-
Type.Object({
|
|
1431
|
-
by: Type.Optional(Type.String()),
|
|
1432
|
-
partition: Type.Optional(Type.Union([Type.String(), Type.Null()]))
|
|
1433
|
-
})
|
|
1434
|
-
])),
|
|
1435
|
-
max_price: Type.Optional(Type.Object({
|
|
1436
|
-
prompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1437
|
-
completion: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1438
|
-
image: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1439
|
-
audio: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1440
|
-
request: Type.Optional(Type.Union([Type.Number(), Type.String()]))
|
|
1441
|
-
})),
|
|
1442
|
-
preferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),
|
|
1443
|
-
preferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema]))
|
|
1444
|
-
}), VercelGatewayRoutingSchema = Type.Object({
|
|
1445
|
-
only: Type.Optional(Type.Array(Type.String())),
|
|
1446
|
-
order: Type.Optional(Type.Array(Type.String()))
|
|
1447
|
-
}), ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]), ThinkingLevelMapSchema = Type.Object({
|
|
1448
|
-
off: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1449
|
-
minimal: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1450
|
-
low: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1451
|
-
medium: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1452
|
-
high: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1453
|
-
xhigh: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1454
|
-
max: Type.Optional(ThinkingLevelMapValueSchema)
|
|
1455
|
-
}), ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]), ChatTemplateKwargVariableSchema = Type.Object({
|
|
1456
|
-
$var: Type.Union([Type.Literal("thinking.enabled"), Type.Literal("thinking.effort")]),
|
|
1457
|
-
omitWhenOff: Type.Optional(Type.Boolean())
|
|
1458
|
-
}), ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]), OpenAICompletionsCompatSchema = Type.Object({
|
|
1459
|
-
supportsStore: Type.Optional(Type.Boolean()),
|
|
1460
|
-
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
1461
|
-
supportsReasoningEffort: Type.Optional(Type.Boolean()),
|
|
1462
|
-
supportsUsageInStreaming: Type.Optional(Type.Boolean()),
|
|
1463
|
-
maxTokensField: Type.Optional(Type.Union([Type.Literal("max_completion_tokens"), Type.Literal("max_tokens")])),
|
|
1464
|
-
requiresToolResultName: Type.Optional(Type.Boolean()),
|
|
1465
|
-
requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
|
|
1466
|
-
requiresThinkingAsText: Type.Optional(Type.Boolean()),
|
|
1467
|
-
requiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),
|
|
1468
|
-
thinkingFormat: Type.Optional(Type.Union([
|
|
1469
|
-
Type.Literal("openai"),
|
|
1470
|
-
Type.Literal("openrouter"),
|
|
1471
|
-
Type.Literal("together"),
|
|
1472
|
-
Type.Literal("deepseek"),
|
|
1473
|
-
Type.Literal("zai"),
|
|
1474
|
-
Type.Literal("qwen"),
|
|
1475
|
-
Type.Literal("chat-template"),
|
|
1476
|
-
Type.Literal("qwen-chat-template"),
|
|
1477
|
-
Type.Literal("string-thinking"),
|
|
1478
|
-
Type.Literal("ant-ling")
|
|
1479
|
-
])),
|
|
1480
|
-
chatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),
|
|
1481
|
-
cacheControlFormat: Type.Optional(Type.Literal("anthropic")),
|
|
1482
|
-
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
|
|
1483
|
-
vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
|
|
1484
|
-
supportsStrictMode: Type.Optional(Type.Boolean()),
|
|
1485
|
-
sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
|
|
1486
|
-
deferredToolsMode: Type.Optional(Type.Literal("kimi")),
|
|
1487
|
-
sessionAffinityFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")])),
|
|
1488
|
-
supportsLongCacheRetention: Type.Optional(Type.Boolean())
|
|
1489
|
-
}), OpenAIResponsesCompatSchema = Type.Object({
|
|
1490
|
-
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
1491
|
-
sessionAffinityFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")])),
|
|
1492
|
-
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
1493
|
-
supportsToolSearch: Type.Optional(Type.Boolean())
|
|
1494
|
-
}), AnthropicMessagesCompatSchema = Type.Object({
|
|
1495
|
-
supportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),
|
|
1496
|
-
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
1497
|
-
sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
|
|
1498
|
-
supportsCacheControlOnTools: Type.Optional(Type.Boolean()),
|
|
1499
|
-
forceAdaptiveThinking: Type.Optional(Type.Boolean()),
|
|
1500
|
-
supportsToolReferences: Type.Optional(Type.Boolean())
|
|
1501
|
-
}), ProviderCompatSchema = Type.Union([
|
|
1502
|
-
OpenAICompletionsCompatSchema,
|
|
1503
|
-
OpenAIResponsesCompatSchema,
|
|
1504
|
-
AnthropicMessagesCompatSchema
|
|
1505
|
-
]), ModelCostRatesSchema = {
|
|
1506
|
-
input: Type.Number(),
|
|
1507
|
-
output: Type.Number(),
|
|
1508
|
-
cacheRead: Type.Number(),
|
|
1509
|
-
cacheWrite: Type.Number()
|
|
1510
|
-
}, ModelCostTierSchema = Type.Object({
|
|
1511
|
-
inputTokensAbove: Type.Number(),
|
|
1512
|
-
...ModelCostRatesSchema
|
|
1513
|
-
}), ModelCostSchema = Type.Object({
|
|
1514
|
-
...ModelCostRatesSchema,
|
|
1515
|
-
tiers: Type.Optional(Type.Array(ModelCostTierSchema))
|
|
1516
|
-
}), ModelDefinitionSchema = Type.Object({
|
|
1517
|
-
id: Type.String({ minLength: 1 }),
|
|
1518
|
-
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
1519
|
-
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
1520
|
-
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
1521
|
-
reasoning: Type.Optional(Type.Boolean()),
|
|
1522
|
-
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
1523
|
-
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
|
|
1524
|
-
cost: Type.Optional(ModelCostSchema),
|
|
1525
|
-
contextWindow: Type.Optional(Type.Number()),
|
|
1526
|
-
maxTokens: Type.Optional(Type.Number()),
|
|
1527
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
1528
|
-
compat: Type.Optional(ProviderCompatSchema)
|
|
1529
|
-
}), ModelOverrideSchema = Type.Object({
|
|
1530
|
-
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
1531
|
-
reasoning: Type.Optional(Type.Boolean()),
|
|
1532
|
-
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
1533
|
-
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
|
|
1534
|
-
cost: Type.Optional(Type.Object({
|
|
1535
|
-
input: Type.Optional(Type.Number()),
|
|
1536
|
-
output: Type.Optional(Type.Number()),
|
|
1537
|
-
cacheRead: Type.Optional(Type.Number()),
|
|
1538
|
-
cacheWrite: Type.Optional(Type.Number()),
|
|
1539
|
-
tiers: Type.Optional(Type.Array(ModelCostTierSchema))
|
|
1540
|
-
})),
|
|
1541
|
-
contextWindow: Type.Optional(Type.Number()),
|
|
1542
|
-
maxTokens: Type.Optional(Type.Number()),
|
|
1543
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
1544
|
-
compat: Type.Optional(ProviderCompatSchema)
|
|
1545
|
-
}), ProviderConfigSchema = Type.Object({
|
|
1546
|
-
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
1547
|
-
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
1548
|
-
apiKey: Type.Optional(Type.String({ minLength: 1 })),
|
|
1549
|
-
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
1550
|
-
oauth: Type.Optional(Type.Literal("radius")),
|
|
1551
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
1552
|
-
compat: Type.Optional(ProviderCompatSchema),
|
|
1553
|
-
authHeader: Type.Optional(Type.Boolean()),
|
|
1554
|
-
models: Type.Optional(Type.Array(ModelDefinitionSchema)),
|
|
1555
|
-
modelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema))
|
|
1556
|
-
}), ModelsConfigSchema = Type.Object({
|
|
1557
|
-
providers: Type.Record(Type.String(), ProviderConfigSchema)
|
|
1558
|
-
}), validateModelsConfig = Compile(ModelsConfigSchema);
|
|
1559
|
-
function formatValidationPath(error) {
|
|
1560
|
-
if (error.keyword === "required") {
|
|
1561
|
-
let requiredProperty = error.params.requiredProperties?.[0];
|
|
1562
|
-
if (requiredProperty) {
|
|
1563
|
-
let basePath = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
1564
|
-
return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
return error.instancePath.replace(/^\//, "").replace(/\//g, ".") || "root";
|
|
1568
|
-
}
|
|
1569
|
-
function deepFreeze(value) {
|
|
1570
|
-
if (typeof value != "object" || value === null || Object.isFrozen(value))
|
|
1571
|
-
return value;
|
|
1572
|
-
for (let child of Object.values(value))
|
|
1573
|
-
deepFreeze(child);
|
|
1574
|
-
return Object.freeze(value);
|
|
1575
|
-
}
|
|
1576
|
-
var ModelConfig = class _ModelConfig {
|
|
1577
|
-
providers;
|
|
1578
|
-
error;
|
|
1579
|
-
constructor(providers, error) {
|
|
1580
|
-
this.providers = providers, this.error = error;
|
|
1581
|
-
}
|
|
1582
|
-
static async load(modelsJsonPath) {
|
|
1583
|
-
if (!modelsJsonPath)
|
|
1584
|
-
return new _ModelConfig(/* @__PURE__ */ new Map());
|
|
1585
|
-
let path = normalizePath(modelsJsonPath), content;
|
|
1586
|
-
try {
|
|
1587
|
-
content = await readFile(path, "utf-8");
|
|
1588
|
-
} catch (error) {
|
|
1589
|
-
return error.code === "ENOENT" ? new _ModelConfig(/* @__PURE__ */ new Map()) : new _ModelConfig(/* @__PURE__ */ new Map(), `Failed to load models.json: ${error instanceof Error ? error.message : error}
|
|
1590
|
-
|
|
1591
|
-
File: ${path}`);
|
|
1592
|
-
}
|
|
1593
|
-
let parsed;
|
|
1594
|
-
try {
|
|
1595
|
-
parsed = JSON.parse(stripJsonComments(content));
|
|
1596
|
-
} catch (error) {
|
|
1597
|
-
return new _ModelConfig(/* @__PURE__ */ new Map(), `Failed to parse models.json: ${error instanceof Error ? error.message : error}
|
|
1598
|
-
|
|
1599
|
-
File: ${path}`);
|
|
1600
|
-
}
|
|
1601
|
-
if (!validateModelsConfig.Check(parsed)) {
|
|
1602
|
-
let errors = validateModelsConfig.Errors(parsed).map((error) => ` - ${formatValidationPath(error)}: ${error.message}`).join(`
|
|
1603
|
-
`) || "Unknown schema error";
|
|
1604
|
-
return new _ModelConfig(/* @__PURE__ */ new Map(), `Invalid models.json schema:
|
|
1605
|
-
${errors}
|
|
1606
|
-
|
|
1607
|
-
File: ${path}`);
|
|
1608
|
-
}
|
|
1609
|
-
let config = parsed, providers = /* @__PURE__ */ new Map();
|
|
1610
|
-
for (let [providerId, provider] of Object.entries(config.providers))
|
|
1611
|
-
providers.set(providerId, deepFreeze(structuredClone(provider)));
|
|
1612
|
-
return new _ModelConfig(providers);
|
|
1613
|
-
}
|
|
1614
|
-
getProvider(providerId) {
|
|
1615
|
-
return this.providers.get(providerId);
|
|
1616
|
-
}
|
|
1617
|
-
getProviderIds() {
|
|
1618
|
-
return [...this.providers.keys()];
|
|
1619
|
-
}
|
|
1620
|
-
getError() {
|
|
1621
|
-
return this.error;
|
|
1622
|
-
}
|
|
1623
|
-
};
|
|
1624
|
-
|
|
1625
|
-
// packages/coding-agent/dist/core/models-store.js
|
|
1626
|
-
import { join as join4 } from "node:path";
|
|
1627
|
-
var InMemoryCodingAgentModelsStore = class {
|
|
1628
|
-
entries = /* @__PURE__ */ new Map();
|
|
1629
|
-
async read(providerId) {
|
|
1630
|
-
return this.entries.get(providerId);
|
|
1631
|
-
}
|
|
1632
|
-
async write(providerId, entry) {
|
|
1633
|
-
this.entries.set(providerId, entry);
|
|
1634
|
-
}
|
|
1635
|
-
async delete(providerId) {
|
|
1636
|
-
this.entries.delete(providerId);
|
|
1637
|
-
}
|
|
1638
|
-
}, FileModelsStore = class {
|
|
1639
|
-
storage;
|
|
1640
|
-
constructor(path = join4(getAgentDir(), "models-store.json")) {
|
|
1641
|
-
this.storage = new FileAuthStorageBackend(path);
|
|
1642
|
-
}
|
|
1643
|
-
parse(content) {
|
|
1644
|
-
let trimmed = content?.replace(/^\uFEFF/, "").trim();
|
|
1645
|
-
if (!trimmed)
|
|
1646
|
-
return {};
|
|
1647
|
-
try {
|
|
1648
|
-
let parsed = JSON.parse(trimmed);
|
|
1649
|
-
return !parsed || typeof parsed != "object" || Array.isArray(parsed) ? {} : parsed;
|
|
1650
|
-
} catch {
|
|
1651
|
-
return {};
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
async read(providerId) {
|
|
1655
|
-
return this.storage.withLock((content) => ({
|
|
1656
|
-
result: structuredClone(this.parse(content)[providerId])
|
|
1657
|
-
}));
|
|
1658
|
-
}
|
|
1659
|
-
async write(providerId, entry) {
|
|
1660
|
-
await this.storage.withLockAsync(async (content) => {
|
|
1661
|
-
let current = this.parse(content);
|
|
1662
|
-
return current[providerId] = structuredClone(entry), { result: void 0, next: JSON.stringify(current, null, 2) };
|
|
1663
|
-
});
|
|
1664
|
-
}
|
|
1665
|
-
async delete(providerId) {
|
|
1666
|
-
await this.storage.withLockAsync(async (content) => {
|
|
1667
|
-
let current = this.parse(content);
|
|
1668
|
-
return delete current[providerId], { result: void 0, next: JSON.stringify(current, null, 2) };
|
|
1669
|
-
});
|
|
1670
|
-
}
|
|
1671
|
-
};
|
|
1672
|
-
|
|
1673
|
-
// packages/coding-agent/dist/core/provider-composer.js
|
|
1674
|
-
import { lazyStream } from "@ashx-j/lunr-ai";
|
|
1675
|
-
import { getApiProvider } from "@ashx-j/lunr-ai/compat";
|
|
1676
|
-
function mergeCompat(base, override) {
|
|
1677
|
-
if (!override)
|
|
1678
|
-
return base;
|
|
1679
|
-
let merged = { ...base, ...override }, baseNested = base, overrideNested = override, mergedNested = merged;
|
|
1680
|
-
for (let key of ["openRouterRouting", "vercelGatewayRouting", "chatTemplateKwargs"]) {
|
|
1681
|
-
let baseValue = baseNested?.[key], overrideValue = overrideNested[key];
|
|
1682
|
-
(typeof baseValue == "object" && baseValue !== null || typeof overrideValue == "object" && overrideValue !== null) && (mergedNested[key] = { ...baseValue, ...overrideValue });
|
|
1683
|
-
}
|
|
1684
|
-
return merged;
|
|
1685
|
-
}
|
|
1686
|
-
function applyModelOverride(model, override) {
|
|
1687
|
-
return {
|
|
1688
|
-
...model,
|
|
1689
|
-
name: override.name ?? model.name,
|
|
1690
|
-
reasoning: override.reasoning ?? model.reasoning,
|
|
1691
|
-
thinkingLevelMap: override.thinkingLevelMap ? { ...model.thinkingLevelMap, ...override.thinkingLevelMap } : model.thinkingLevelMap,
|
|
1692
|
-
input: override.input ?? model.input,
|
|
1693
|
-
cost: override.cost ? {
|
|
1694
|
-
input: override.cost.input ?? model.cost.input,
|
|
1695
|
-
output: override.cost.output ?? model.cost.output,
|
|
1696
|
-
cacheRead: override.cost.cacheRead ?? model.cost.cacheRead,
|
|
1697
|
-
cacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,
|
|
1698
|
-
tiers: override.cost.tiers ?? model.cost.tiers
|
|
1699
|
-
} : model.cost,
|
|
1700
|
-
contextWindow: override.contextWindow ?? model.contextWindow,
|
|
1701
|
-
maxTokens: override.maxTokens ?? model.maxTokens,
|
|
1702
|
-
compat: mergeCompat(model.compat, override.compat)
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
function modelFromJson(providerId, definition, providerConfig, defaults) {
|
|
1706
|
-
let api = definition.api ?? providerConfig.api ?? defaults?.api;
|
|
1707
|
-
if (!api)
|
|
1708
|
-
throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);
|
|
1709
|
-
let baseUrl = definition.baseUrl ?? providerConfig.baseUrl ?? defaults?.baseUrl;
|
|
1710
|
-
if (!baseUrl)
|
|
1711
|
-
throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);
|
|
1712
|
-
if (definition.contextWindow !== void 0 && definition.contextWindow <= 0)
|
|
1713
|
-
throw new Error(`Provider ${providerId}, model ${definition.id}: invalid contextWindow`);
|
|
1714
|
-
if (definition.maxTokens !== void 0 && definition.maxTokens <= 0)
|
|
1715
|
-
throw new Error(`Provider ${providerId}, model ${definition.id}: invalid maxTokens`);
|
|
1716
|
-
return {
|
|
1717
|
-
id: definition.id,
|
|
1718
|
-
name: definition.name ?? definition.id,
|
|
1719
|
-
api,
|
|
1720
|
-
provider: providerId,
|
|
1721
|
-
baseUrl,
|
|
1722
|
-
reasoning: definition.reasoning ?? !1,
|
|
1723
|
-
thinkingLevelMap: definition.thinkingLevelMap,
|
|
1724
|
-
input: definition.input ?? ["text"],
|
|
1725
|
-
cost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1726
|
-
contextWindow: definition.contextWindow ?? 128e3,
|
|
1727
|
-
maxTokens: definition.maxTokens ?? 16384,
|
|
1728
|
-
headers: void 0,
|
|
1729
|
-
compat: mergeCompat(providerConfig.compat, definition.compat)
|
|
1730
|
-
};
|
|
1731
|
-
}
|
|
1732
|
-
function applyModelsJson(providerId, baseModels, config) {
|
|
1733
|
-
if (!config)
|
|
1734
|
-
return [...baseModels];
|
|
1735
|
-
if (config.oauth && !config.baseUrl)
|
|
1736
|
-
throw new Error(`Provider ${providerId}: "baseUrl" is required when "oauth" is set.`);
|
|
1737
|
-
let hasOverrides = config.modelOverrides && Object.keys(config.modelOverrides).length > 0;
|
|
1738
|
-
if (!config.models?.length && !config.baseUrl && !config.headers && !config.compat && !hasOverrides && !config.apiKey && !config.oauth && config.authHeader === void 0)
|
|
1739
|
-
throw new Error(`Provider ${providerId}: must specify "baseUrl", "headers", "compat", "modelOverrides", or "models".`);
|
|
1740
|
-
let models = baseModels.map((model) => ({
|
|
1741
|
-
...model,
|
|
1742
|
-
baseUrl: config.oauth === "radius" ? model.baseUrl : config.baseUrl ?? model.baseUrl,
|
|
1743
|
-
compat: mergeCompat(model.compat, config.compat)
|
|
1744
|
-
}));
|
|
1745
|
-
for (let definition of config.models ?? []) {
|
|
1746
|
-
let existingIndex = models.findIndex((model2) => model2.id === definition.id), defaults = existingIndex >= 0 ? models[existingIndex] : models[0], model = modelFromJson(providerId, definition, config, defaults);
|
|
1747
|
-
existingIndex >= 0 ? models[existingIndex] = model : models.push(model);
|
|
1748
|
-
}
|
|
1749
|
-
return models;
|
|
1750
|
-
}
|
|
1751
|
-
function applyExtension(providerId, models, config) {
|
|
1752
|
-
return config ? config.models ? config.models.map((definition) => {
|
|
1753
|
-
let defaults = models.find((model) => model.id === definition.id) ?? models[0], api = definition.api ?? config.api ?? defaults?.api;
|
|
1754
|
-
if (!api)
|
|
1755
|
-
throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);
|
|
1756
|
-
let baseUrl = definition.baseUrl ?? config.baseUrl ?? defaults?.baseUrl;
|
|
1757
|
-
if (!baseUrl)
|
|
1758
|
-
throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);
|
|
1759
|
-
return {
|
|
1760
|
-
...definition,
|
|
1761
|
-
api,
|
|
1762
|
-
provider: providerId,
|
|
1763
|
-
baseUrl,
|
|
1764
|
-
headers: void 0
|
|
1765
|
-
};
|
|
1766
|
-
}) : config.baseUrl ? models.map((model) => ({ ...model, baseUrl: config.baseUrl })) : [...models] : [...models];
|
|
1767
|
-
}
|
|
1768
|
-
function adaptOAuth(config) {
|
|
1769
|
-
return {
|
|
1770
|
-
name: config.name,
|
|
1771
|
-
login: async (callbacks) => ({ ...await config.login({
|
|
1772
|
-
onAuth: (info) => callbacks.notify({ type: "auth_url", ...info }),
|
|
1773
|
-
onDeviceCode: (info) => callbacks.notify({ type: "device_code", ...info }),
|
|
1774
|
-
onPrompt: (prompt) => callbacks.prompt({ type: "text", ...prompt }),
|
|
1775
|
-
onProgress: (message) => callbacks.notify({ type: "progress", message }),
|
|
1776
|
-
onManualCodeInput: () => callbacks.prompt({ type: "manual_code", message: "Paste the authorization code" }),
|
|
1777
|
-
onSelect: (prompt) => callbacks.prompt({ type: "select", ...prompt }),
|
|
1778
|
-
signal: callbacks.signal
|
|
1779
|
-
}), type: "oauth" }),
|
|
1780
|
-
refresh: async (credential) => ({ ...await config.refreshToken(credential), type: "oauth" }),
|
|
1781
|
-
toAuth: async (credential) => ({ apiKey: config.getApiKey(credential) })
|
|
1782
|
-
};
|
|
1783
|
-
}
|
|
1784
|
-
function withConfiguredAuth(auth, headers, authHeader) {
|
|
1785
|
-
let mergedHeaders = auth.headers || headers ? { ...auth.headers, ...headers } : void 0;
|
|
1786
|
-
if (authHeader) {
|
|
1787
|
-
if (!auth.apiKey)
|
|
1788
|
-
throw new Error("authHeader requires a resolved API key");
|
|
1789
|
-
mergedHeaders = { ...mergedHeaders, Authorization: `Bearer ${auth.apiKey}` };
|
|
1790
|
-
}
|
|
1791
|
-
return { ...auth, headers: mergedHeaders };
|
|
1792
|
-
}
|
|
1793
|
-
function configuredApiKey(config, extension) {
|
|
1794
|
-
return extension?.apiKey ?? config?.apiKey;
|
|
1795
|
-
}
|
|
1796
|
-
function configuredHeaders(config, extension) {
|
|
1797
|
-
if (!(!config?.headers && !extension?.headers))
|
|
1798
|
-
return { ...config?.headers, ...extension?.headers };
|
|
1799
|
-
}
|
|
1800
|
-
async function configContextEnv(values, ctx, explicit) {
|
|
1801
|
-
let env = { ...explicit };
|
|
1802
|
-
for (let name of new Set(values.flatMap(getConfigValueEnvVarNames))) {
|
|
1803
|
-
if (env[name] !== void 0)
|
|
1804
|
-
continue;
|
|
1805
|
-
let value = await ctx.env(name);
|
|
1806
|
-
value !== void 0 && (env[name] = value);
|
|
1807
|
-
}
|
|
1808
|
-
return Object.keys(env).length > 0 ? env : void 0;
|
|
1809
|
-
}
|
|
1810
|
-
function composeApiKeyAuth(providerId, base, config, extension) {
|
|
1811
|
-
let inherited = base?.auth.apiKey, rawKey = configuredApiKey(config, extension), oauth = extension?.oauth ?? base?.auth.oauth;
|
|
1812
|
-
if (!inherited && rawKey === void 0 && oauth)
|
|
1813
|
-
return;
|
|
1814
|
-
let rawHeaders = configuredHeaders(config, extension), authHeader = extension?.authHeader ?? config?.authHeader ?? !1;
|
|
1815
|
-
return {
|
|
1816
|
-
name: inherited?.name ?? "API key",
|
|
1817
|
-
login: inherited?.login ?? (async (interaction) => ({
|
|
1818
|
-
type: "api_key",
|
|
1819
|
-
key: await interaction.prompt({ type: "secret", message: "Enter API key" })
|
|
1820
|
-
})),
|
|
1821
|
-
check: async (input) => {
|
|
1822
|
-
if (input.credential) {
|
|
1823
|
-
if (inherited?.check)
|
|
1824
|
-
return inherited.check(input);
|
|
1825
|
-
if (input.credential.key)
|
|
1826
|
-
return { type: "api_key", source: "stored credential" };
|
|
1827
|
-
let resolved2 = await inherited?.resolve(input);
|
|
1828
|
-
return resolved2 ? { type: "api_key", source: resolved2.source } : void 0;
|
|
1829
|
-
}
|
|
1830
|
-
if (rawKey !== void 0) {
|
|
1831
|
-
if (isCommandConfigValue(rawKey))
|
|
1832
|
-
return { type: "api_key", source: "configured API key" };
|
|
1833
|
-
let envNames = getConfigValueEnvVarNames(rawKey);
|
|
1834
|
-
for (let name of envNames)
|
|
1835
|
-
if (await input.ctx.env(name) === void 0)
|
|
1836
|
-
return;
|
|
1837
|
-
return { type: "api_key", source: "configured API key" };
|
|
1838
|
-
}
|
|
1839
|
-
if (inherited?.check)
|
|
1840
|
-
return inherited.check(input);
|
|
1841
|
-
let resolved = await inherited?.resolve(input);
|
|
1842
|
-
return resolved ? { type: "api_key", source: resolved.source } : void 0;
|
|
1843
|
-
},
|
|
1844
|
-
resolve: async (input) => {
|
|
1845
|
-
let result;
|
|
1846
|
-
if (input.credential)
|
|
1847
|
-
result = inherited ? await inherited.resolve(input) : input.credential.key ? { auth: { apiKey: input.credential.key }, env: input.credential.env, source: "stored credential" } : void 0;
|
|
1848
|
-
else if (rawKey !== void 0) {
|
|
1849
|
-
let env = await configContextEnv([rawKey], input.ctx), key = resolveConfigValueOrThrow(rawKey, `API key for provider "${providerId}"`, env);
|
|
1850
|
-
result = inherited ? await inherited.resolve({ ...input, credential: { type: "api_key", key } }) : { auth: { apiKey: key }, source: "configured API key" };
|
|
1851
|
-
} else
|
|
1852
|
-
result = await inherited?.resolve(input);
|
|
1853
|
-
if (!result)
|
|
1854
|
-
return;
|
|
1855
|
-
let explicitEnv = { ...input.credential?.env ?? {}, ...result.env ?? {} }, headerEnv = await configContextEnv(Object.values(rawHeaders ?? {}), input.ctx, explicitEnv), headers = resolveHeadersOrThrow(rawHeaders, `provider "${providerId}"`, headerEnv);
|
|
1856
|
-
return { ...result, auth: withConfiguredAuth(result.auth, headers, authHeader) };
|
|
1857
|
-
}
|
|
1858
|
-
};
|
|
1859
|
-
}
|
|
1860
|
-
function composeOAuthAuth(providerId, base, config, extension) {
|
|
1861
|
-
let oauth = extension?.oauth ? adaptOAuth(extension.oauth) : base?.auth.oauth;
|
|
1862
|
-
if (!oauth)
|
|
1863
|
-
return;
|
|
1864
|
-
let rawHeaders = configuredHeaders(config, extension), authHeader = extension?.authHeader ?? config?.authHeader ?? !1;
|
|
1865
|
-
return {
|
|
1866
|
-
...oauth,
|
|
1867
|
-
toAuth: async (credential) => {
|
|
1868
|
-
let auth = await oauth.toAuth(credential), env = credential.env, headers = resolveHeadersOrThrow(rawHeaders, `provider "${providerId}"`, typeof env == "object" && env !== null ? env : void 0);
|
|
1869
|
-
return withConfiguredAuth(auth, headers, authHeader);
|
|
1870
|
-
}
|
|
1871
|
-
};
|
|
1872
|
-
}
|
|
1873
|
-
function rawModelHeaders(model, config, extension) {
|
|
1874
|
-
let definition = config?.models?.find((entry) => entry.id === model.id), extensionModel = extension?.models?.find((entry) => entry.id === model.id), headers = {
|
|
1875
|
-
...config?.modelOverrides?.[model.id]?.headers,
|
|
1876
|
-
...definition?.headers,
|
|
1877
|
-
...extensionModel?.headers
|
|
1878
|
-
};
|
|
1879
|
-
return Object.keys(headers).length > 0 ? headers : void 0;
|
|
1880
|
-
}
|
|
1881
|
-
function validateExtensionProvider(providerId, base, modelsConfig, extension) {
|
|
1882
|
-
if (extension.streamSimple && !extension.api)
|
|
1883
|
-
throw new Error(`Provider ${providerId}: "api" is required when registering streamSimple.`);
|
|
1884
|
-
applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], modelsConfig), extension);
|
|
1885
|
-
}
|
|
1886
|
-
function composeModelProvider(providerId, base, modelConfig, extension) {
|
|
1887
|
-
let config = modelConfig.getProvider(providerId), extensionOAuthCredential, refreshedExtensionModels, currentExtension = () => extension && refreshedExtensionModels ? { ...extension, models: refreshedExtensionModels } : extension, getModels = () => {
|
|
1888
|
-
let models = applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config), currentExtension());
|
|
1889
|
-
return extensionOAuthCredential && extension?.oauth?.modifyModels && (models = extension.oauth.modifyModels(models, extensionOAuthCredential)), models.map((model) => {
|
|
1890
|
-
let override = config?.modelOverrides?.[model.id];
|
|
1891
|
-
return override ? applyModelOverride(model, override) : model;
|
|
1892
|
-
});
|
|
1893
|
-
};
|
|
1894
|
-
getModels();
|
|
1895
|
-
let apiKey = composeApiKeyAuth(providerId, base, config, extension), oauth = composeOAuthAuth(providerId, base, config, extension);
|
|
1896
|
-
if (!apiKey && !oauth)
|
|
1897
|
-
throw new Error(`Provider ${providerId}: no authentication method configured.`);
|
|
1898
|
-
let supportsBaseApi = (model) => base?.getModels().some((entry) => entry.api === model.api) ?? !1, streamWith = (model, context, options, simple) => lazyStream(model, async () => {
|
|
1899
|
-
if (extension?.streamSimple && model.api === extension.api)
|
|
1900
|
-
return extension.streamSimple(model, context, options);
|
|
1901
|
-
if (base && supportsBaseApi(model))
|
|
1902
|
-
return simple ? base.streamSimple(model, context, options) : base.stream(model, context, options);
|
|
1903
|
-
let api = getApiProvider(model.api);
|
|
1904
|
-
if (!api)
|
|
1905
|
-
throw new Error(`No API provider registered for api: ${model.api}`);
|
|
1906
|
-
return simple ? api.streamSimple(model, context, options) : api.stream(model, context, options);
|
|
1907
|
-
});
|
|
1908
|
-
return {
|
|
1909
|
-
id: providerId,
|
|
1910
|
-
name: extension?.name ?? config?.name ?? base?.name ?? extension?.oauth?.name ?? providerId,
|
|
1911
|
-
baseUrl: extension?.baseUrl ?? config?.baseUrl ?? base?.baseUrl,
|
|
1912
|
-
headers: base?.headers,
|
|
1913
|
-
auth: { ...apiKey ? { apiKey } : {}, ...oauth ? { oauth } : {} },
|
|
1914
|
-
getModels,
|
|
1915
|
-
refreshModels: base?.refreshModels || extension?.refreshModels || extension?.oauth?.modifyModels ? async (context) => {
|
|
1916
|
-
if (await base?.refreshModels?.(context), extension?.refreshModels) {
|
|
1917
|
-
let refreshed = await extension.refreshModels(context);
|
|
1918
|
-
context.signal?.aborted || (applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config), {
|
|
1919
|
-
...extension,
|
|
1920
|
-
models: refreshed
|
|
1921
|
-
}), refreshedExtensionModels = refreshed);
|
|
1922
|
-
}
|
|
1923
|
-
extensionOAuthCredential = context.credential?.type === "oauth" ? context.credential : void 0;
|
|
1924
|
-
} : void 0,
|
|
1925
|
-
filterModels: base?.filterModels ? (models, credential) => base.filterModels(models, credential) : void 0,
|
|
1926
|
-
stream: (model, context, options) => streamWith(model, context, options, !1),
|
|
1927
|
-
streamSimple: (model, context, options) => streamWith(model, context, options, !0)
|
|
1928
|
-
};
|
|
1929
|
-
}
|
|
1930
|
-
function resolveConfiguredModelHeaders(model, config, extension, env) {
|
|
1931
|
-
return resolveHeadersOrThrow(rawModelHeaders(model, config, extension), `model "${model.provider}/${model.id}"`, env);
|
|
1932
|
-
}
|
|
1933
|
-
function resolveCompatibilityRequestConfig(model, config, extension) {
|
|
1934
|
-
let configured = resolveHeadersOrThrow({ ...configuredHeaders(config, extension), ...rawModelHeaders(model, config, extension) }, `model "${model.provider}/${model.id}"`);
|
|
1935
|
-
return {
|
|
1936
|
-
headers: model.headers || configured ? { ...model.headers, ...configured } : void 0,
|
|
1937
|
-
authHeader: extension?.authHeader ?? config?.authHeader ?? !1
|
|
1938
|
-
};
|
|
1939
|
-
}
|
|
1940
|
-
function configuredRequestAuthStatus(config, extension) {
|
|
1941
|
-
let value = configuredApiKey(config, extension);
|
|
1942
|
-
if (value === void 0)
|
|
1943
|
-
return;
|
|
1944
|
-
if (isCommandConfigValue(value))
|
|
1945
|
-
return { configured: !0, source: "models_json_command" };
|
|
1946
|
-
let names = getConfigValueEnvVarNames(value);
|
|
1947
|
-
return names.length > 0 ? isConfigValueConfigured(value) ? { configured: !0, source: "environment", label: names.join(", ") } : { configured: !1 } : { configured: !0, source: extension?.apiKey !== void 0 ? "fallback" : "models_json_key" };
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
|
-
// packages/coding-agent/dist/core/runtime-credentials.js
|
|
1951
|
-
var RuntimeCredentials = class {
|
|
1952
|
-
store;
|
|
1953
|
-
overrides = /* @__PURE__ */ new Map();
|
|
1954
|
-
constructor(store) {
|
|
1955
|
-
this.store = store;
|
|
1956
|
-
}
|
|
1957
|
-
setRuntimeApiKey(providerId, apiKey) {
|
|
1958
|
-
this.overrides.set(providerId, apiKey);
|
|
1959
|
-
}
|
|
1960
|
-
removeRuntimeApiKey(providerId) {
|
|
1961
|
-
this.overrides.delete(providerId);
|
|
1962
|
-
}
|
|
1963
|
-
hasRuntimeApiKey(providerId) {
|
|
1964
|
-
return this.overrides.has(providerId);
|
|
1965
|
-
}
|
|
1966
|
-
async read(providerId) {
|
|
1967
|
-
let override = this.overrides.get(providerId);
|
|
1968
|
-
return override ? { type: "api_key", key: override } : this.store.read(providerId);
|
|
1969
|
-
}
|
|
1970
|
-
async list() {
|
|
1971
|
-
let entries = new Map((await this.store.list()).map((entry) => [entry.providerId, entry]));
|
|
1972
|
-
for (let providerId of this.overrides.keys())
|
|
1973
|
-
entries.set(providerId, { providerId, type: "api_key" });
|
|
1974
|
-
return [...entries.values()];
|
|
1975
|
-
}
|
|
1976
|
-
modify(providerId, fn) {
|
|
1977
|
-
return this.store.modify(providerId, fn);
|
|
1978
|
-
}
|
|
1979
|
-
async delete(providerId) {
|
|
1980
|
-
this.overrides.delete(providerId), await this.store.delete(providerId);
|
|
1981
|
-
}
|
|
1982
|
-
};
|
|
1983
|
-
|
|
1984
|
-
// packages/coding-agent/dist/core/subscriptions.js
|
|
1985
|
-
import { join as join5 } from "path";
|
|
1986
|
-
|
|
1987
|
-
// packages/coding-agent/dist/core/usage-limit.js
|
|
1988
|
-
var USAGE_LIMIT_ERROR_PATTERNS = [
|
|
1989
|
-
// Provider-declared subscription/free-tier limit error types and wording
|
|
1990
|
-
// (pi-ai NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN spirit).
|
|
1991
|
-
"GoUsageLimitError",
|
|
1992
|
-
"FreeUsageLimitError",
|
|
1993
|
-
"Monthly usage limit reached",
|
|
1994
|
-
"available balance",
|
|
1995
|
-
"insufficient_quota",
|
|
1996
|
-
"out of budget",
|
|
1997
|
-
"quota exceeded",
|
|
1998
|
-
"billing"
|
|
1999
|
-
], USAGE_LIMIT_ERROR_REGEXES = [
|
|
2000
|
-
// Goal runtime USAGE_LIMIT_GOAL_ERROR_PATTERNS: usage caps, quota exhaustion,
|
|
2001
|
-
// credit/balance exhaustion, payment required.
|
|
2002
|
-
/usage[_\s-]*(?:limit|cap)|chatgpt.{0,32}usage/i,
|
|
2003
|
-
/quota.{0,32}(?:reached|exceeded|exhausted|depleted)|(?:reached|exceeded|exhausted|depleted).{0,32}quota/i,
|
|
2004
|
-
/insufficient[_\s-]*(?:quota|credits?)|out of credits|out of budget|available balance|payment required/i,
|
|
2005
|
-
/(?:credit|balance).{0,32}(?:low|exhausted|depleted)|billing/i
|
|
2006
|
-
], AUTH_INVALID_ERROR_PATTERN = /\b401\b|unauthori[sz]ed|unauthenticated|invalid.{0,16}(?:api.?key|token|credentials?)|authentication.{0,16}failed/i;
|
|
2007
|
-
function isUsageLimitError(errorMessage) {
|
|
2008
|
-
return errorMessage ? USAGE_LIMIT_ERROR_PATTERNS.some((pattern) => errorMessage.toLowerCase().includes(pattern.toLowerCase())) ? !0 : USAGE_LIMIT_ERROR_REGEXES.some((pattern) => pattern.test(errorMessage)) : !1;
|
|
2009
|
-
}
|
|
2010
|
-
function isAuthInvalidError(errorMessage) {
|
|
2011
|
-
return errorMessage ? AUTH_INVALID_ERROR_PATTERN.test(errorMessage) : !1;
|
|
2012
|
-
}
|
|
2013
|
-
var RESET_TIME_PATTERNS = [
|
|
2014
|
-
/reset(?:s|ting)?\s*(?:in|after|at)?\s*(\d+)\s*s(ec)?/i,
|
|
2015
|
-
/reset(?:s|ting)?\s*(?:in|after|at)?\s*(\d+)\s*m(in)?/i,
|
|
2016
|
-
/reset(?:s|ting)?\s*(?:in|after|at)?\s*(\d+)\s*h(our|r)?/i,
|
|
2017
|
-
/(?:retry|try(?:\s+again)?|available)\s+(?:in|after|at)\s*(\d+)\s*s(ec)?/i,
|
|
2018
|
-
/(?:retry|try(?:\s+again)?|available)\s+(?:in|after|at)\s*(\d+)\s*m(in)?/i,
|
|
2019
|
-
/(?:retry|try(?:\s+again)?|available)\s+(?:in|after|at)\s*(\d+)\s*h(our|r)?/i
|
|
2020
|
-
];
|
|
2021
|
-
function parseResetTimeMs(errorMessage) {
|
|
2022
|
-
if (!errorMessage)
|
|
2023
|
-
return;
|
|
2024
|
-
let now = Date.now();
|
|
2025
|
-
for (let pattern of RESET_TIME_PATTERNS) {
|
|
2026
|
-
let match = errorMessage.match(pattern);
|
|
2027
|
-
if (!match)
|
|
2028
|
-
continue;
|
|
2029
|
-
let value = Number.parseInt(match[1] ?? "", 10);
|
|
2030
|
-
if (!Number.isFinite(value) || value <= 0)
|
|
2031
|
-
continue;
|
|
2032
|
-
let unit = pattern.source.includes("\\s*h") ? 36e5 : pattern.source.includes("\\s*m") ? 6e4 : 1e3;
|
|
2033
|
-
return now + value * unit;
|
|
2034
|
-
}
|
|
2035
|
-
let isoMatch = errorMessage.match(/(?:reset|available).{0,12}(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)/i);
|
|
2036
|
-
if (isoMatch?.[1]) {
|
|
2037
|
-
let parsed = Date.parse(isoMatch[1]);
|
|
2038
|
-
if (Number.isFinite(parsed) && parsed > now)
|
|
2039
|
-
return parsed;
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
// packages/coding-agent/dist/core/subscriptions.js
|
|
2044
|
-
var SubscriptionManager = class _SubscriptionManager {
|
|
2045
|
-
data = {};
|
|
2046
|
-
loaded = !1;
|
|
2047
|
-
storage;
|
|
2048
|
-
authStorage;
|
|
2049
|
-
// In-process write queue so mutations serialize even before the file lock.
|
|
2050
|
-
queue = Promise.resolve();
|
|
2051
|
-
// Per-provider ids of keys exhausted without a parseable reset time.
|
|
2052
|
-
// Process-local on purpose: infinite exhaustion is never persisted.
|
|
2053
|
-
memoryExhausted = /* @__PURE__ */ new Map();
|
|
2054
|
-
constructor(authStorage, storage) {
|
|
2055
|
-
this.authStorage = authStorage, this.storage = storage;
|
|
2056
|
-
}
|
|
2057
|
-
static create(authStorage, path) {
|
|
2058
|
-
return new _SubscriptionManager(authStorage, new FileAuthStorageBackend(path ?? join5(getAgentDir(), "subscriptions.json")));
|
|
2059
|
-
}
|
|
2060
|
-
static fromStorage(authStorage, storage) {
|
|
2061
|
-
return new _SubscriptionManager(authStorage, storage);
|
|
2062
|
-
}
|
|
2063
|
-
static inMemory(authStorage, data = {}) {
|
|
2064
|
-
let storage = new InMemoryAuthStorageBackend();
|
|
2065
|
-
return storage.withLock(() => ({ result: void 0, next: JSON.stringify(data, null, 2) })), _SubscriptionManager.fromStorage(authStorage, storage);
|
|
2066
|
-
}
|
|
2067
|
-
parseStorageData(content) {
|
|
2068
|
-
return content ? JSON.parse(content) : {};
|
|
2069
|
-
}
|
|
2070
|
-
ensureLoaded() {
|
|
2071
|
-
if (this.loaded)
|
|
2072
|
-
return;
|
|
2073
|
-
this.loaded = !0;
|
|
2074
|
-
let content;
|
|
2075
|
-
try {
|
|
2076
|
-
this.storage.withLock((current) => (content = current, { result: void 0 })), this.data = this.parseStorageData(content);
|
|
2077
|
-
} catch {
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
enqueue(fn) {
|
|
2081
|
-
let next = this.queue.then(fn);
|
|
2082
|
-
return this.queue = next.catch(() => {
|
|
2083
|
-
}), next;
|
|
2084
|
-
}
|
|
2085
|
-
persist() {
|
|
2086
|
-
return this.storage.withLockAsync(async () => ({
|
|
2087
|
-
result: void 0,
|
|
2088
|
-
next: JSON.stringify(this.data, null, 2)
|
|
2089
|
-
}));
|
|
2090
|
-
}
|
|
2091
|
-
/** Raw stored credential read via the modify path (returning undefined leaves it unchanged). */
|
|
2092
|
-
async readRawCredential(providerId) {
|
|
2093
|
-
let current;
|
|
2094
|
-
return await this.authStorage.modify(providerId, async (credential) => {
|
|
2095
|
-
current = credential;
|
|
2096
|
-
}), current;
|
|
2097
|
-
}
|
|
2098
|
-
/**
|
|
2099
|
-
* Pool for a provider, lazy-importing an existing stored api_key credential
|
|
2100
|
-
* as "Sub 1" on first access. OAuth credentials are not imported.
|
|
2101
|
-
*/
|
|
2102
|
-
async ensurePool(providerId) {
|
|
2103
|
-
this.ensureLoaded();
|
|
2104
|
-
let existing = this.data[providerId];
|
|
2105
|
-
if (existing)
|
|
2106
|
-
return existing;
|
|
2107
|
-
let credential = await this.readRawCredential(providerId);
|
|
2108
|
-
if (credential?.type !== "api_key" || credential.key === void 0)
|
|
2109
|
-
return;
|
|
2110
|
-
let pool = {
|
|
2111
|
-
active: "1",
|
|
2112
|
-
keys: [{ id: "1", name: "Sub 1", key: credential.key, addedAt: Date.now() }]
|
|
2113
|
-
};
|
|
2114
|
-
return this.data = { ...this.data, [providerId]: pool }, await this.persist(), pool;
|
|
2115
|
-
}
|
|
2116
|
-
nextId(pool) {
|
|
2117
|
-
let max = 0;
|
|
2118
|
-
for (let entry of pool.keys) {
|
|
2119
|
-
let numeric = Number.parseInt(entry.id, 10);
|
|
2120
|
-
Number.isFinite(numeric) && numeric > max && (max = numeric);
|
|
2121
|
-
}
|
|
2122
|
-
return String(max + 1);
|
|
2123
|
-
}
|
|
2124
|
-
async mirrorActive(providerId, key) {
|
|
2125
|
-
await this.authStorage.modify(providerId, async () => ({ type: "api_key", key }));
|
|
2126
|
-
}
|
|
2127
|
-
async list(providerId) {
|
|
2128
|
-
return this.enqueue(async () => {
|
|
2129
|
-
let pool = await this.ensurePool(providerId);
|
|
2130
|
-
return pool ? [...pool.keys] : [];
|
|
2131
|
-
});
|
|
2132
|
-
}
|
|
2133
|
-
async getActive(providerId) {
|
|
2134
|
-
return this.enqueue(async () => {
|
|
2135
|
-
let pool = await this.ensurePool(providerId);
|
|
2136
|
-
return pool?.keys.find((entry) => entry.id === pool.active);
|
|
2137
|
-
});
|
|
2138
|
-
}
|
|
2139
|
-
async addKey(providerId, key, name) {
|
|
2140
|
-
return this.enqueue(async () => {
|
|
2141
|
-
this.ensureLoaded();
|
|
2142
|
-
let pool = await this.ensurePool(providerId), id = pool ? this.nextId(pool) : "1", entry = { id, name: name ?? `Sub ${id}`, key, addedAt: Date.now() }, keys = [...pool?.keys ?? [], entry];
|
|
2143
|
-
return this.data = { ...this.data, [providerId]: { active: id, keys } }, await this.persist(), await this.mirrorActive(providerId, key), entry;
|
|
2144
|
-
});
|
|
2145
|
-
}
|
|
2146
|
-
async removeKey(providerId, id) {
|
|
2147
|
-
return this.enqueue(async () => {
|
|
2148
|
-
let pool = await this.ensurePool(providerId);
|
|
2149
|
-
if (!pool || !pool.keys.some((entry) => entry.id === id))
|
|
2150
|
-
return;
|
|
2151
|
-
let keys = pool.keys.filter((entry) => entry.id !== id);
|
|
2152
|
-
if (this.memoryExhausted.get(providerId)?.delete(id), keys.length === 0) {
|
|
2153
|
-
let data = { ...this.data };
|
|
2154
|
-
delete data[providerId], this.data = data, await this.persist(), await this.authStorage.delete(providerId);
|
|
2155
|
-
return;
|
|
2156
|
-
}
|
|
2157
|
-
let active = pool.active;
|
|
2158
|
-
if (active === id) {
|
|
2159
|
-
active = keys[0]?.id ?? active, this.data = { ...this.data, [providerId]: { active, keys } }, await this.persist();
|
|
2160
|
-
let promoted = keys.find((entry) => entry.id === active);
|
|
2161
|
-
promoted && await this.mirrorActive(providerId, promoted.key);
|
|
2162
|
-
return;
|
|
2163
|
-
}
|
|
2164
|
-
this.data = { ...this.data, [providerId]: { active, keys } }, await this.persist();
|
|
2165
|
-
});
|
|
2166
|
-
}
|
|
2167
|
-
async renameKey(providerId, id, name) {
|
|
2168
|
-
return this.enqueue(async () => {
|
|
2169
|
-
let pool = await this.ensurePool(providerId);
|
|
2170
|
-
if (!pool)
|
|
2171
|
-
return;
|
|
2172
|
-
let keys = pool.keys.map((entry) => entry.id === id ? { ...entry, name } : entry);
|
|
2173
|
-
this.data = { ...this.data, [providerId]: { ...pool, keys } }, await this.persist();
|
|
2174
|
-
});
|
|
2175
|
-
}
|
|
2176
|
-
async setActive(providerId, id) {
|
|
2177
|
-
return this.enqueue(async () => {
|
|
2178
|
-
let pool = await this.ensurePool(providerId), entry = pool?.keys.find((candidate) => candidate.id === id);
|
|
2179
|
-
!pool || !entry || (this.data = { ...this.data, [providerId]: { ...pool, active: id } }, await this.persist(), await this.mirrorActive(providerId, entry.key));
|
|
2180
|
-
});
|
|
2181
|
-
}
|
|
2182
|
-
/**
|
|
2183
|
-
* Mark the active key exhausted and rotate to the next non-exhausted key in
|
|
2184
|
-
* round-robin order. A parseable reset time is persisted as exhaustedUntil;
|
|
2185
|
-
* otherwise the exhaustion is process-local only. Returns the new active key,
|
|
2186
|
-
* or null when no non-exhausted alternative exists (current key stays active).
|
|
2187
|
-
*/
|
|
2188
|
-
async rotateOnFailure(providerId, errorMessage, now = Date.now()) {
|
|
2189
|
-
return this.enqueue(async () => {
|
|
2190
|
-
let pool = await this.ensurePool(providerId);
|
|
2191
|
-
if (!pool)
|
|
2192
|
-
return null;
|
|
2193
|
-
let currentIndex = pool.keys.findIndex((entry) => entry.id === pool.active);
|
|
2194
|
-
if (currentIndex === -1)
|
|
2195
|
-
return null;
|
|
2196
|
-
let current = pool.keys[currentIndex];
|
|
2197
|
-
if (!current)
|
|
2198
|
-
return null;
|
|
2199
|
-
let resetAt = parseResetTimeMs(errorMessage), keys = pool.keys;
|
|
2200
|
-
if (resetAt !== void 0 && resetAt > now)
|
|
2201
|
-
keys = pool.keys.map((entry) => entry.id === current.id ? { ...entry, exhaustedUntil: resetAt, lastError: errorMessage } : entry);
|
|
2202
|
-
else {
|
|
2203
|
-
let set = this.memoryExhausted.get(providerId) ?? /* @__PURE__ */ new Set();
|
|
2204
|
-
set.add(current.id), this.memoryExhausted.set(providerId, set);
|
|
2205
|
-
}
|
|
2206
|
-
let isExhausted = (entry) => this.memoryExhausted.get(providerId)?.has(entry.id) === !0 || entry.exhaustedUntil !== void 0 && entry.exhaustedUntil > now;
|
|
2207
|
-
for (let offset = 1; offset < keys.length; offset++) {
|
|
2208
|
-
let candidate = keys[(currentIndex + offset) % keys.length];
|
|
2209
|
-
if (!(!candidate || isExhausted(candidate)))
|
|
2210
|
-
return this.data = { ...this.data, [providerId]: { active: candidate.id, keys } }, await this.persist(), await this.mirrorActive(providerId, candidate.key), candidate;
|
|
2211
|
-
}
|
|
2212
|
-
return keys !== pool.keys && (this.data = { ...this.data, [providerId]: { ...pool, keys } }, await this.persist()), null;
|
|
2213
|
-
});
|
|
2214
|
-
}
|
|
2215
|
-
/** Manual reactivate: clears persisted and process-local exhaustion for a key. */
|
|
2216
|
-
async clearExhaustion(providerId, id) {
|
|
2217
|
-
return this.enqueue(async () => {
|
|
2218
|
-
this.memoryExhausted.get(providerId)?.delete(id);
|
|
2219
|
-
let pool = await this.ensurePool(providerId);
|
|
2220
|
-
if (!pool)
|
|
2221
|
-
return;
|
|
2222
|
-
let target = pool.keys.find((entry) => entry.id === id);
|
|
2223
|
-
if (!target || target.exhaustedUntil === void 0 && target.lastError === void 0)
|
|
2224
|
-
return;
|
|
2225
|
-
let keys = pool.keys.map((entry) => {
|
|
2226
|
-
if (entry.id !== id)
|
|
2227
|
-
return entry;
|
|
2228
|
-
let { exhaustedUntil: _exhaustedUntil, lastError: _lastError, ...rest } = entry;
|
|
2229
|
-
return rest;
|
|
2230
|
-
});
|
|
2231
|
-
this.data = { ...this.data, [providerId]: { ...pool, keys } }, await this.persist();
|
|
2232
|
-
});
|
|
2233
|
-
}
|
|
2234
|
-
};
|
|
2235
|
-
|
|
2236
|
-
// packages/coding-agent/dist/core/user-models.js
|
|
2237
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2238
|
-
import { dirname as dirname4, join as join6 } from "node:path";
|
|
2239
|
-
var USER_MODELS_FILENAME = "user-models.json";
|
|
2240
|
-
function userModelsPath(agentDir = getAgentDir()) {
|
|
2241
|
-
return join6(agentDir, USER_MODELS_FILENAME);
|
|
2242
|
-
}
|
|
2243
|
-
function isRecord3(value) {
|
|
2244
|
-
return typeof value == "object" && value !== null && !Array.isArray(value);
|
|
2245
|
-
}
|
|
2246
|
-
function asFiniteNumber3(value) {
|
|
2247
|
-
if (typeof value == "number" && Number.isFinite(value))
|
|
2248
|
-
return value;
|
|
2249
|
-
}
|
|
2250
|
-
function parseUserEntry(value) {
|
|
2251
|
-
if (!isRecord3(value))
|
|
2252
|
-
return;
|
|
2253
|
-
let id = typeof value.id == "string" ? value.id.trim() : "", provider = typeof value.provider == "string" ? value.provider.trim() : "";
|
|
2254
|
-
if (!id || !provider)
|
|
2255
|
-
return;
|
|
2256
|
-
let parsedInput = Array.isArray(value.input) ? value.input.filter((entry) => entry === "text" || entry === "image") : ["text"], input = parsedInput.length > 0 ? parsedInput : ["text"], cost = isRecord3(value.cost) ? {
|
|
2257
|
-
input: asFiniteNumber3(value.cost.input) ?? 0,
|
|
2258
|
-
output: asFiniteNumber3(value.cost.output) ?? 0,
|
|
2259
|
-
cacheRead: asFiniteNumber3(value.cost.cacheRead) ?? 0,
|
|
2260
|
-
cacheWrite: asFiniteNumber3(value.cost.cacheWrite) ?? 0
|
|
2261
|
-
} : { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
2262
|
-
return {
|
|
2263
|
-
id,
|
|
2264
|
-
name: typeof value.name == "string" && value.name.trim() ? value.name : id,
|
|
2265
|
-
api: typeof value.api == "string" && value.api.trim() ? value.api : "openai-completions",
|
|
2266
|
-
provider,
|
|
2267
|
-
baseUrl: typeof value.baseUrl == "string" ? value.baseUrl : "",
|
|
2268
|
-
reasoning: value.reasoning === !0,
|
|
2269
|
-
input,
|
|
2270
|
-
cost,
|
|
2271
|
-
contextWindow: asFiniteNumber3(value.contextWindow) ?? 128e3,
|
|
2272
|
-
maxTokens: asFiniteNumber3(value.maxTokens) ?? 8192,
|
|
2273
|
-
compat: isRecord3(value.compat) ? value.compat : void 0,
|
|
2274
|
-
thinkingLevelMap: isRecord3(value.thinkingLevelMap) ? value.thinkingLevelMap : void 0,
|
|
2275
|
-
source: "user"
|
|
2276
|
-
};
|
|
2277
|
-
}
|
|
2278
|
-
function emptyUserModels() {
|
|
2279
|
-
return { version: 1, models: [] };
|
|
2280
|
-
}
|
|
2281
|
-
function readUserModels(path) {
|
|
2282
|
-
try {
|
|
2283
|
-
if (!existsSync4(path))
|
|
2284
|
-
return emptyUserModels();
|
|
2285
|
-
let parsed = JSON.parse(readFileSync4(path, "utf-8"));
|
|
2286
|
-
if (!isRecord3(parsed) || !Array.isArray(parsed.models))
|
|
2287
|
-
return emptyUserModels();
|
|
2288
|
-
let models = [];
|
|
2289
|
-
for (let entry of parsed.models) {
|
|
2290
|
-
let model = parseUserEntry(entry);
|
|
2291
|
-
model && models.push(model);
|
|
2292
|
-
}
|
|
2293
|
-
return { version: asFiniteNumber3(parsed.version) ?? 1, models };
|
|
2294
|
-
} catch {
|
|
2295
|
-
return emptyUserModels();
|
|
2296
|
-
}
|
|
2297
|
-
}
|
|
2298
|
-
function writeUserModels(file, path) {
|
|
2299
|
-
mkdirSync4(dirname4(path), { recursive: !0, mode: 448 }), writeFileSync4(path, `${JSON.stringify({ version: file.version ?? 1, models: file.models }, null, 2)}
|
|
2300
|
-
`, "utf-8");
|
|
2301
|
-
}
|
|
2302
|
-
function evictUserModelsOnOfficial(user, officialKeys) {
|
|
2303
|
-
let hits = new Set(officialKeys), kept = [], evicted = [];
|
|
2304
|
-
for (let model of user.models)
|
|
2305
|
-
hits.has(modelKey(model.provider, model.id)) ? evicted.push(model) : kept.push(model);
|
|
2306
|
-
return { next: { version: user.version, models: kept }, evicted };
|
|
2307
|
-
}
|
|
2308
|
-
function evictUserModelsByProvider(user, providerId) {
|
|
2309
|
-
let kept = [], evicted = [];
|
|
2310
|
-
for (let model of user.models)
|
|
2311
|
-
model.provider === providerId ? evicted.push(model) : kept.push(model);
|
|
2312
|
-
return { next: { version: user.version, models: kept }, evicted };
|
|
2313
|
-
}
|
|
2314
|
-
function upsertUserModels(existing, rows) {
|
|
2315
|
-
let byKey = new Map(existing.models.map((model) => [modelKey(model.provider, model.id), model]));
|
|
2316
|
-
for (let row of rows)
|
|
2317
|
-
byKey.set(modelKey(row.provider, row.id), { ...row, source: "user" });
|
|
2318
|
-
return { version: existing.version ?? 1, models: [...byKey.values()] };
|
|
2319
|
-
}
|
|
2320
|
-
function userEntryToModel(entry) {
|
|
2321
|
-
return {
|
|
2322
|
-
id: entry.id,
|
|
2323
|
-
name: entry.name,
|
|
2324
|
-
api: entry.api,
|
|
2325
|
-
provider: entry.provider,
|
|
2326
|
-
baseUrl: entry.baseUrl,
|
|
2327
|
-
reasoning: entry.reasoning,
|
|
2328
|
-
input: entry.input,
|
|
2329
|
-
cost: entry.cost,
|
|
2330
|
-
contextWindow: entry.contextWindow,
|
|
2331
|
-
maxTokens: entry.maxTokens,
|
|
2332
|
-
compat: entry.compat,
|
|
2333
|
-
thinkingLevelMap: entry.thinkingLevelMap
|
|
2334
|
-
};
|
|
2335
|
-
}
|
|
2336
|
-
var UserModelsStore = class {
|
|
2337
|
-
path;
|
|
2338
|
-
file;
|
|
2339
|
-
constructor(path) {
|
|
2340
|
-
this.path = path, this.file = path ? readUserModels(path) : emptyUserModels();
|
|
2341
|
-
}
|
|
2342
|
-
list() {
|
|
2343
|
-
return this.file.models;
|
|
2344
|
-
}
|
|
2345
|
-
keys() {
|
|
2346
|
-
return new Set(this.file.models.map((model) => modelKey(model.provider, model.id)));
|
|
2347
|
-
}
|
|
2348
|
-
modelsFor(providerId) {
|
|
2349
|
-
return this.file.models.filter((model) => model.provider === providerId).map(userEntryToModel);
|
|
2350
|
-
}
|
|
2351
|
-
evictOfficial(officialKeys) {
|
|
2352
|
-
let { next, evicted } = evictUserModelsOnOfficial(this.file, officialKeys);
|
|
2353
|
-
return evicted.length > 0 && (this.file = next, this.persist()), evicted;
|
|
2354
|
-
}
|
|
2355
|
-
evictProvider(providerId) {
|
|
2356
|
-
let { next, evicted } = evictUserModelsByProvider(this.file, providerId);
|
|
2357
|
-
return evicted.length > 0 && (this.file = next, this.persist()), evicted;
|
|
2358
|
-
}
|
|
2359
|
-
upsert(rows) {
|
|
2360
|
-
rows.length !== 0 && (this.file = upsertUserModels(this.file, rows), this.persist());
|
|
2361
|
-
}
|
|
2362
|
-
persist() {
|
|
2363
|
-
if (this.path)
|
|
2364
|
-
try {
|
|
2365
|
-
writeUserModels(this.file, this.path);
|
|
2366
|
-
} catch {
|
|
2367
|
-
}
|
|
2368
|
-
}
|
|
2369
|
-
};
|
|
2370
|
-
|
|
2371
|
-
// packages/coding-agent/dist/core/model-runtime.js
|
|
2372
|
-
function mergeHeaders(base, override) {
|
|
2373
|
-
if (!base && !override)
|
|
2374
|
-
return;
|
|
2375
|
-
let merged = { ...base };
|
|
2376
|
-
for (let [name, value] of Object.entries(override ?? {})) {
|
|
2377
|
-
let lowerName = name.toLowerCase();
|
|
2378
|
-
for (let existingName of Object.keys(merged))
|
|
2379
|
-
existingName.toLowerCase() === lowerName && delete merged[existingName];
|
|
2380
|
-
merged[name] = value;
|
|
2381
|
-
}
|
|
2382
|
-
return merged;
|
|
2383
|
-
}
|
|
2384
|
-
var ModelRuntime = class _ModelRuntime {
|
|
2385
|
-
models;
|
|
2386
|
-
credentials;
|
|
2387
|
-
/** lunr: per-provider subscription-key pools; rotation mirrors the active key into the credential store. */
|
|
2388
|
-
subscriptionManager;
|
|
2389
|
-
defaultBuiltins;
|
|
2390
|
-
builtins = /* @__PURE__ */ new Map();
|
|
2391
|
-
extensionProviders = /* @__PURE__ */ new Map();
|
|
2392
|
-
compositionErrors = /* @__PURE__ */ new Map();
|
|
2393
|
-
modelsPath;
|
|
2394
|
-
allowModelNetwork;
|
|
2395
|
-
config;
|
|
2396
|
-
snapshot = {
|
|
2397
|
-
all: [],
|
|
2398
|
-
available: [],
|
|
2399
|
-
configuredProviders: /* @__PURE__ */ new Set(),
|
|
2400
|
-
storedProviders: /* @__PURE__ */ new Set(),
|
|
2401
|
-
auth: /* @__PURE__ */ new Map()
|
|
2402
|
-
};
|
|
2403
|
-
availabilityRefresh;
|
|
2404
|
-
availabilityError;
|
|
2405
|
-
modelsStore;
|
|
2406
|
-
overlay = new CatalogOverlaySource();
|
|
2407
|
-
userModels;
|
|
2408
|
-
officialCachePath;
|
|
2409
|
-
lastCatalogRefresh = { aborted: !1, errors: /* @__PURE__ */ new Map(), live: [], incomplete: [] };
|
|
2410
|
-
lastOfficial;
|
|
2411
|
-
catalogRefresh;
|
|
2412
|
-
catalogRefreshAllowsNetwork = !1;
|
|
2413
|
-
nextAutomaticRefresh = 0;
|
|
2414
|
-
automaticRefreshIdentity = "";
|
|
2415
|
-
grokHome;
|
|
2416
|
-
constructor(credentials, config, modelsPath, modelsStore, providers, allowModelNetwork, subscriptionManager, catalogDir, grokHome) {
|
|
2417
|
-
this.credentials = credentials, this.config = config, this.modelsPath = modelsPath, this.modelsStore = modelsStore, this.allowModelNetwork = allowModelNetwork, this.subscriptionManager = subscriptionManager, this.userModels = new UserModelsStore(catalogDir ? userModelsPath(catalogDir) : void 0), this.officialCachePath = catalogDir ? officialCatalogCachePath(catalogDir) : void 0, this.grokHome = grokHome, this.defaultBuiltins = new Map(providers.map((provider) => [provider.id, provider]));
|
|
2418
|
-
for (let [providerId, provider] of this.defaultBuiltins)
|
|
2419
|
-
this.builtins.set(providerId, provider);
|
|
2420
|
-
this.models = createModels({ credentials, modelsStore }), this.rebuildProviders();
|
|
2421
|
-
}
|
|
2422
|
-
static async create(options = {}) {
|
|
2423
|
-
let rawStore = options.credentials ?? AuthStorage.create(options.authPath), grokHomeDisabled = options.grokHome === null || options.grokHome === void 0 && options.credentials !== void 0, grokHome = grokHomeDisabled ? void 0 : options.grokHome ?? void 0, baseStore = grokHomeDisabled ? rawStore : wrapXaiGrokCliCredentials(rawStore, { grokHome }), credentials = new RuntimeCredentials(baseStore), subscriptionManager = options.subscriptions ?? (options.credentials && !options.authPath ? SubscriptionManager.inMemory(baseStore) : SubscriptionManager.create(baseStore, options.authPath ? join7(dirname5(options.authPath), "subscriptions.json") : void 0)), modelsPath = options.modelsPath === null ? void 0 : options.modelsPath ?? join7(getAgentDir(), "models.json"), config = await ModelConfig.load(modelsPath), modelsStore = options.modelsStore ?? (modelsPath ? new FileModelsStore(options.modelsStorePath ?? join7(dirname5(modelsPath), "models-store.json")) : new InMemoryCodingAgentModelsStore()), providers = builtinProviderCatalog.builtinProviders(), catalogDir = modelsPath ? dirname5(modelsPath) : options.authPath ? dirname5(options.authPath) : void 0, runtime = new _ModelRuntime(credentials, config, modelsPath, modelsStore, providers, options.allowModelNetwork ?? process.env.PI_OFFLINE === void 0, subscriptionManager, catalogDir, grokHome);
|
|
2424
|
-
return runtime.configureRadiusProviders(), runtime.rebuildProviders(), await runtime.refresh({ allowNetwork: !1 }), runtime;
|
|
2425
|
-
}
|
|
2426
|
-
configureRadiusProviders() {
|
|
2427
|
-
this.builtins.clear();
|
|
2428
|
-
for (let [providerId, provider] of this.defaultBuiltins)
|
|
2429
|
-
this.builtins.set(providerId, provider);
|
|
2430
|
-
for (let providerId of this.config.getProviderIds()) {
|
|
2431
|
-
let config = this.config.getProvider(providerId);
|
|
2432
|
-
config?.oauth !== "radius" || !config.baseUrl || this.builtins.set(providerId, builtinProviderCatalog.radiusProvider({
|
|
2433
|
-
id: providerId,
|
|
2434
|
-
name: config.name ?? providerId,
|
|
2435
|
-
gateway: config.baseUrl.replace(/\/v1\/?$/u, "")
|
|
2436
|
-
}));
|
|
2437
|
-
}
|
|
2438
|
-
}
|
|
2439
|
-
providerIds() {
|
|
2440
|
-
return /* @__PURE__ */ new Set([...this.builtins.keys(), ...this.config.getProviderIds(), ...this.extensionProviders.keys()]);
|
|
2441
|
-
}
|
|
2442
|
-
recomposeProvider(providerId) {
|
|
2443
|
-
let base = this.builtins.get(providerId), extension = this.extensionProviders.get(providerId);
|
|
2444
|
-
if (!base && !this.config.getProvider(providerId) && !extension) {
|
|
2445
|
-
this.models.deleteProvider(providerId), this.compositionErrors.delete(providerId);
|
|
2446
|
-
return;
|
|
2447
|
-
}
|
|
2448
|
-
if (base && !this.config.getProvider(providerId) && !extension) {
|
|
2449
|
-
this.models.setProvider(this.withLocalCatalog(base)), this.compositionErrors.delete(providerId);
|
|
2450
|
-
return;
|
|
2451
|
-
}
|
|
2452
|
-
try {
|
|
2453
|
-
this.models.setProvider(composeModelProvider(providerId, base ? this.withLocalCatalog(base) : void 0, this.config, extension)), this.compositionErrors.delete(providerId);
|
|
2454
|
-
} catch (error) {
|
|
2455
|
-
this.compositionErrors.set(providerId, error instanceof Error ? error.message : String(error)), base ? this.models.setProvider(this.withLocalCatalog(base)) : this.models.deleteProvider(providerId);
|
|
2456
|
-
}
|
|
2457
|
-
}
|
|
2458
|
-
withLocalCatalog(provider) {
|
|
2459
|
-
return withCatalogOverlay(provider, this.overlay);
|
|
2460
|
-
}
|
|
2461
|
-
bakedInModels(providerId) {
|
|
2462
|
-
return [...this.defaultBuiltins.get(providerId)?.getModels() ?? []];
|
|
2463
|
-
}
|
|
2464
|
-
rebuildProviders() {
|
|
2465
|
-
this.models.clearProviders(), this.compositionErrors.clear();
|
|
2466
|
-
for (let providerId of this.providerIds())
|
|
2467
|
-
this.recomposeProvider(providerId);
|
|
2468
|
-
this.updateModelSnapshot();
|
|
2469
|
-
}
|
|
2470
|
-
updateModelSnapshot() {
|
|
2471
|
-
let all = [...this.models.getModels()];
|
|
2472
|
-
this.snapshot = {
|
|
2473
|
-
...this.snapshot,
|
|
2474
|
-
all,
|
|
2475
|
-
available: all.filter((model) => this.snapshot.configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model))
|
|
2476
|
-
};
|
|
2477
|
-
}
|
|
2478
|
-
isCatalogModelAvailable(model) {
|
|
2479
|
-
return !!this.config.getProvider(model.provider)?.models?.some((row) => row.id === model.id) || !!this.extensionProviders.get(model.provider)?.models?.some((row) => row.id === model.id) || this.overlay.isAvailable(model);
|
|
2480
|
-
}
|
|
2481
|
-
async listStoredProviderIds() {
|
|
2482
|
-
let credentials = await this.credentials.list();
|
|
2483
|
-
return new Set(credentials.map((entry) => entry.providerId));
|
|
2484
|
-
}
|
|
2485
|
-
/** `/model` lists stored creds + models.json/extension keys, never ambient envApiKeyAuth. */
|
|
2486
|
-
configuredProviderIds(storedProviders) {
|
|
2487
|
-
let configured = new Set(storedProviders);
|
|
2488
|
-
for (let provider of this.models.getProviders())
|
|
2489
|
-
configuredRequestAuthStatus(this.config.getProvider(provider.id), this.extensionProviders.get(provider.id))?.configured && configured.add(provider.id);
|
|
2490
|
-
return configured;
|
|
2491
|
-
}
|
|
2492
|
-
userModelsForStoredProviders(storedProviders) {
|
|
2493
|
-
return this.userModels.list().filter((row) => storedProviders.has(row.provider)).map(userEntryToModel);
|
|
2494
|
-
}
|
|
2495
|
-
async runAvailabilityRefresh() {
|
|
2496
|
-
let providers = this.models.getProviders(), [available, checks, storedProviders] = await Promise.all([
|
|
2497
|
-
this.models.getAvailable(),
|
|
2498
|
-
Promise.all(providers.map(async (provider) => [
|
|
2499
|
-
provider.id,
|
|
2500
|
-
await this.models.checkAuth(provider.id)
|
|
2501
|
-
])),
|
|
2502
|
-
this.listStoredProviderIds()
|
|
2503
|
-
]), auth = new Map(checks), configuredProviders = this.configuredProviderIds(storedProviders);
|
|
2504
|
-
this.snapshot = {
|
|
2505
|
-
all: [...this.models.getModels()],
|
|
2506
|
-
available: available.filter((model) => configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model)),
|
|
2507
|
-
configuredProviders,
|
|
2508
|
-
storedProviders,
|
|
2509
|
-
auth
|
|
2510
|
-
}, this.availabilityError = void 0;
|
|
2511
|
-
}
|
|
2512
|
-
queueAvailabilityRefresh(after) {
|
|
2513
|
-
let tracked = (after ?? Promise.resolve()).catch(() => {
|
|
2514
|
-
}).then(() => this.runAvailabilityRefresh()).catch((error) => {
|
|
2515
|
-
throw this.availabilityError = error instanceof Error ? error.message : String(error), error;
|
|
2516
|
-
}).finally(() => {
|
|
2517
|
-
this.availabilityRefresh === tracked && (this.availabilityRefresh = void 0);
|
|
2518
|
-
});
|
|
2519
|
-
return this.availabilityRefresh = tracked, tracked;
|
|
2520
|
-
}
|
|
2521
|
-
/** Coalesce concurrent readers onto the pending refresh. */
|
|
2522
|
-
refreshAvailability() {
|
|
2523
|
-
return this.availabilityRefresh ?? this.queueAvailabilityRefresh(void 0);
|
|
2524
|
-
}
|
|
2525
|
-
/** Mutations must not observe an in-flight refresh started before them. */
|
|
2526
|
-
forceRefreshAvailability() {
|
|
2527
|
-
return this.queueAvailabilityRefresh(this.availabilityRefresh);
|
|
2528
|
-
}
|
|
2529
|
-
getProviders() {
|
|
2530
|
-
return this.models.getProviders();
|
|
2531
|
-
}
|
|
2532
|
-
getProvider(providerId) {
|
|
2533
|
-
return this.models.getProvider(providerId);
|
|
2534
|
-
}
|
|
2535
|
-
getModels(providerId) {
|
|
2536
|
-
return this.models.getModels(providerId);
|
|
2537
|
-
}
|
|
2538
|
-
getModel(providerId, modelId) {
|
|
2539
|
-
return this.models.getModel(providerId, modelId);
|
|
2540
|
-
}
|
|
2541
|
-
async checkAuth(providerId) {
|
|
2542
|
-
return this.models.checkAuth(providerId);
|
|
2543
|
-
}
|
|
2544
|
-
async getAvailable(providerId) {
|
|
2545
|
-
if (providerId) {
|
|
2546
|
-
if (this.availabilityRefresh)
|
|
2547
|
-
return await this.availabilityRefresh, this.snapshot.available.filter((model) => model.provider === providerId);
|
|
2548
|
-
try {
|
|
2549
|
-
return (await this.models.getAvailable(providerId)).filter((model) => this.isCatalogModelAvailable(model));
|
|
2550
|
-
} catch (error) {
|
|
2551
|
-
throw this.availabilityError = error instanceof Error ? error.message : String(error), error;
|
|
2552
|
-
}
|
|
2553
|
-
}
|
|
2554
|
-
return await this.refreshAvailability(), this.snapshot.available;
|
|
2555
|
-
}
|
|
2556
|
-
getAvailableSnapshot() {
|
|
2557
|
-
return this.snapshot.available;
|
|
2558
|
-
}
|
|
2559
|
-
getError() {
|
|
2560
|
-
let errors = [], configError = this.config.getError();
|
|
2561
|
-
configError && errors.push(configError);
|
|
2562
|
-
for (let [providerId, error] of this.compositionErrors)
|
|
2563
|
-
errors.push(`Provider "${providerId}": ${error}`);
|
|
2564
|
-
return this.availabilityError && errors.push(`Availability refresh: ${this.availabilityError}`), errors.length > 0 ? errors.join(`
|
|
3
|
+
TODO_TOOL_NAMES
|
|
4
|
+
} from "./chunk-CCCN2UCX.js";
|
|
5
|
+
import {
|
|
6
|
+
DefaultResourceLoader,
|
|
7
|
+
createSyntheticSourceInfo,
|
|
8
|
+
expandPromptTemplate,
|
|
9
|
+
formatSkillsForPrompt
|
|
10
|
+
} from "./chunk-IQIEU7SB.js";
|
|
11
|
+
import {
|
|
12
|
+
stripFrontmatter
|
|
13
|
+
} from "./chunk-QFWG2RVL.js";
|
|
14
|
+
import {
|
|
15
|
+
createAllToolDefinitions,
|
|
16
|
+
createLocalBashOperations,
|
|
17
|
+
createToolDefinitionFromAgentTool,
|
|
18
|
+
wrapToolDefinition
|
|
19
|
+
} from "./chunk-VSSXXL36.js";
|
|
20
|
+
import {
|
|
21
|
+
DEFAULT_MAX_BYTES,
|
|
22
|
+
truncateTail
|
|
23
|
+
} from "./chunk-53YJI7JU.js";
|
|
24
|
+
import {
|
|
25
|
+
stripAnsi
|
|
26
|
+
} from "./chunk-5ZQXRPMC.js";
|
|
27
|
+
import {
|
|
28
|
+
ModelRuntime,
|
|
29
|
+
isAuthInvalidError,
|
|
30
|
+
isUsageLimitError
|
|
31
|
+
} from "./chunk-GS66LV4M.js";
|
|
32
|
+
import {
|
|
33
|
+
SettingsManager
|
|
34
|
+
} from "./chunk-WADV2VDS.js";
|
|
35
|
+
import {
|
|
36
|
+
DEFAULT_THINKING_LEVEL,
|
|
37
|
+
calculateContextTokens,
|
|
38
|
+
collectEntriesForBranchSummary,
|
|
39
|
+
compact,
|
|
40
|
+
estimateContextTokens,
|
|
41
|
+
estimateTokens,
|
|
42
|
+
findInitialModel,
|
|
43
|
+
generateBranchSummary,
|
|
44
|
+
prepareCompaction,
|
|
45
|
+
shouldCompact
|
|
46
|
+
} from "./chunk-OFKSVRV7.js";
|
|
47
|
+
import {
|
|
48
|
+
ExtensionRunner,
|
|
49
|
+
emitSessionShutdownEvent
|
|
50
|
+
} from "./chunk-5BNJ4JUH.js";
|
|
51
|
+
import {
|
|
52
|
+
getSubagentCancellation
|
|
53
|
+
} from "./chunk-BBUVIEZB.js";
|
|
54
|
+
import {
|
|
55
|
+
gateToolCall
|
|
56
|
+
} from "./chunk-5D7LC2ZQ.js";
|
|
57
|
+
import {
|
|
58
|
+
isUserInstructionsPath,
|
|
59
|
+
loadSelectedUserInstructions
|
|
60
|
+
} from "./chunk-M3LZLQW2.js";
|
|
61
|
+
import {
|
|
62
|
+
list
|
|
63
|
+
} from "./chunk-KKUTQQV7.js";
|
|
64
|
+
import {
|
|
65
|
+
sanitizeBinaryOutput
|
|
66
|
+
} from "./chunk-CSFI6YXL.js";
|
|
67
|
+
import {
|
|
68
|
+
SessionTransferError
|
|
69
|
+
} from "./chunk-AZJHNQKQ.js";
|
|
70
|
+
import {
|
|
71
|
+
CURRENT_SESSION_VERSION,
|
|
72
|
+
SessionManager,
|
|
73
|
+
getDefaultSessionDir,
|
|
74
|
+
getLatestCompactionEntry
|
|
75
|
+
} from "./chunk-XLTL257W.js";
|
|
76
|
+
import {
|
|
77
|
+
convertToLlm
|
|
78
|
+
} from "./chunk-FVDOXRUD.js";
|
|
79
|
+
import {
|
|
80
|
+
MEMORY_TOOL_NAMES
|
|
81
|
+
} from "./chunk-UJOCPOMX.js";
|
|
82
|
+
import {
|
|
83
|
+
SessionOwnership,
|
|
84
|
+
canonicalSessionPath
|
|
85
|
+
} from "./chunk-UAEOTO52.js";
|
|
86
|
+
import {
|
|
87
|
+
measureStartup,
|
|
88
|
+
time
|
|
89
|
+
} from "./chunk-PVCDKGR6.js";
|
|
90
|
+
import {
|
|
91
|
+
getThemeByName,
|
|
92
|
+
theme
|
|
93
|
+
} from "./chunk-7QWNYZDI.js";
|
|
94
|
+
import {
|
|
95
|
+
CONFIG_DIR_NAME,
|
|
96
|
+
getAgentDir,
|
|
97
|
+
getDocsPath,
|
|
98
|
+
getExamplesPath,
|
|
99
|
+
getReadmePath,
|
|
100
|
+
resolvePath
|
|
101
|
+
} from "./chunk-FQMM2EZ2.js";
|
|
2565
102
|
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
getRegisteredProviderConfig(providerId) {
|
|
2569
|
-
return this.extensionProviders.get(providerId);
|
|
2570
|
-
}
|
|
2571
|
-
getRegisteredProviderIds() {
|
|
2572
|
-
return [...this.extensionProviders.keys()];
|
|
2573
|
-
}
|
|
2574
|
-
/** @internal Compatibility fallback for ModelRegistry when provider auth is unconfigured. */
|
|
2575
|
-
getCompatibilityRequestConfig(model) {
|
|
2576
|
-
return resolveCompatibilityRequestConfig(model, this.config.getProvider(model.provider), this.extensionProviders.get(model.provider));
|
|
2577
|
-
}
|
|
2578
|
-
isUsingOAuth(providerId) {
|
|
2579
|
-
return this.snapshot.auth.get(providerId)?.type === "oauth";
|
|
2580
|
-
}
|
|
2581
|
-
hasConfiguredAuth(providerId) {
|
|
2582
|
-
return this.snapshot.configuredProviders.has(providerId);
|
|
2583
|
-
}
|
|
2584
|
-
async getAuth(providerOrModel, overrides = {}) {
|
|
2585
|
-
if (typeof providerOrModel == "string")
|
|
2586
|
-
return this.models.getAuth(providerOrModel, overrides);
|
|
2587
|
-
let resolution = await this.models.getAuth(providerOrModel, overrides);
|
|
2588
|
-
if (!resolution)
|
|
2589
|
-
return;
|
|
2590
|
-
let configuredHeaders2 = resolveConfiguredModelHeaders(providerOrModel, this.config.getProvider(providerOrModel.provider), this.extensionProviders.get(providerOrModel.provider), { ...resolution.env ?? {}, ...overrides.env ?? {} });
|
|
2591
|
-
return {
|
|
2592
|
-
...resolution,
|
|
2593
|
-
auth: {
|
|
2594
|
-
...resolution.auth,
|
|
2595
|
-
headers: mergeHeaders(resolution.auth.headers, configuredHeaders2)
|
|
2596
|
-
}
|
|
2597
|
-
};
|
|
2598
|
-
}
|
|
2599
|
-
/** lunr: whether a runtime --api-key override is active for the provider (it shadows auth.json). */
|
|
2600
|
-
hasRuntimeApiKey(providerId) {
|
|
2601
|
-
return this.credentials.hasRuntimeApiKey(providerId);
|
|
2602
|
-
}
|
|
2603
|
-
async setRuntimeApiKey(providerId, apiKey, options) {
|
|
2604
|
-
this.credentials.setRuntimeApiKey(providerId, apiKey);
|
|
2605
|
-
let auth = new Map(this.snapshot.auth).set(providerId, { type: "api_key", source: "runtime API key" }), configuredProviders = new Set(this.snapshot.configuredProviders).add(providerId), storedProviders = new Set(this.snapshot.storedProviders).add(providerId);
|
|
2606
|
-
this.snapshot = {
|
|
2607
|
-
...this.snapshot,
|
|
2608
|
-
auth,
|
|
2609
|
-
configuredProviders,
|
|
2610
|
-
storedProviders,
|
|
2611
|
-
available: this.snapshot.all.filter((model) => configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model))
|
|
2612
|
-
}, await this.refresh({ allowNetwork: options?.allowNetwork ?? this.allowModelNetwork });
|
|
2613
|
-
}
|
|
2614
|
-
async removeRuntimeApiKey(providerId) {
|
|
2615
|
-
this.credentials.removeRuntimeApiKey(providerId), await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
2616
|
-
}
|
|
2617
|
-
/** lunr: whether network model-catalog fetches are allowed (offline mode disables them). */
|
|
2618
|
-
isNetworkAllowed() {
|
|
2619
|
-
return this.allowModelNetwork;
|
|
2620
|
-
}
|
|
2621
|
-
listCredentials() {
|
|
2622
|
-
return this.credentials.list();
|
|
2623
|
-
}
|
|
2624
|
-
getProviderAuthStatus(providerId) {
|
|
2625
|
-
if (this.credentials.hasRuntimeApiKey(providerId))
|
|
2626
|
-
return { configured: !0, source: "runtime" };
|
|
2627
|
-
if (this.snapshot.storedProviders.has(providerId))
|
|
2628
|
-
return { configured: !0, source: "stored" };
|
|
2629
|
-
let configured = configuredRequestAuthStatus(this.config.getProvider(providerId), this.extensionProviders.get(providerId));
|
|
2630
|
-
if (configured)
|
|
2631
|
-
return configured;
|
|
2632
|
-
let check = this.snapshot.auth.get(providerId);
|
|
2633
|
-
return check ? { configured: !0, source: "environment", label: check.source } : { configured: !1 };
|
|
2634
|
-
}
|
|
2635
|
-
async prepareRequest(model, options) {
|
|
2636
|
-
let provider = this.models.getProvider(model.provider);
|
|
2637
|
-
if (!provider)
|
|
2638
|
-
throw new ModelsError("provider", `Unknown provider: ${model.provider}`);
|
|
2639
|
-
let resolution = await this.getAuth(model, { apiKey: options?.apiKey, env: options?.env });
|
|
2640
|
-
if (!resolution)
|
|
2641
|
-
throw new ModelsError("auth", `Provider is not configured: ${model.provider}`);
|
|
2642
|
-
let { transformHeaders, ...providerOptions } = options ?? {}, headers = mergeHeaders(resolution.auth.headers, providerOptions.headers);
|
|
2643
|
-
transformHeaders && (headers = await transformHeaders(headers ?? {}));
|
|
2644
|
-
let env = resolution.env || providerOptions.env ? { ...resolution.env ?? {}, ...providerOptions.env ?? {} } : void 0;
|
|
2645
|
-
return {
|
|
2646
|
-
provider,
|
|
2647
|
-
model: resolution.auth.baseUrl ? { ...model, baseUrl: resolution.auth.baseUrl } : model,
|
|
2648
|
-
options: {
|
|
2649
|
-
...providerOptions,
|
|
2650
|
-
apiKey: providerOptions.apiKey ?? resolution.auth.apiKey,
|
|
2651
|
-
headers,
|
|
2652
|
-
env
|
|
2653
|
-
}
|
|
2654
|
-
};
|
|
2655
|
-
}
|
|
2656
|
-
stream(model, context, options) {
|
|
2657
|
-
return lazyStream2(model, async () => {
|
|
2658
|
-
let prepared = await this.prepareRequest(model, options);
|
|
2659
|
-
return prepared.provider.stream(prepared.model, context, prepared.options);
|
|
2660
|
-
});
|
|
2661
|
-
}
|
|
2662
|
-
complete(model, context, options) {
|
|
2663
|
-
return this.stream(model, context, options).result();
|
|
2664
|
-
}
|
|
2665
|
-
streamSimple(model, context, options) {
|
|
2666
|
-
return lazyStream2(model, async () => {
|
|
2667
|
-
let prepared = await this.prepareRequest(model, options);
|
|
2668
|
-
return prepared.provider.streamSimple(prepared.model, context, prepared.options);
|
|
2669
|
-
});
|
|
2670
|
-
}
|
|
2671
|
-
completeSimple(model, context, options) {
|
|
2672
|
-
return this.streamSimple(model, context, options).result();
|
|
2673
|
-
}
|
|
2674
|
-
async login(providerId, type, interaction) {
|
|
2675
|
-
let credential = await this.models.login(providerId, type, interaction);
|
|
2676
|
-
return clearPlanUsageCache(), await this.refresh({ allowNetwork: this.allowModelNetwork }), credential;
|
|
2677
|
-
}
|
|
2678
|
-
async logout(providerId) {
|
|
2679
|
-
await this.models.logout(providerId), await this.modelsStore.delete(providerId), this.userModels.evictProvider(providerId), this.overlay.setLive(providerId, []), this.recomposeProvider(providerId), clearPlanUsageCache(), await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
2680
|
-
}
|
|
2681
|
-
/** Copy a live Grok CLI SuperGrok session into lunR `auth.json`. */
|
|
2682
|
-
async importGrokCliXaiAuth() {
|
|
2683
|
-
let grok = readGrokCliXaiOAuth({ grokHome: this.grokHome });
|
|
2684
|
-
if (!grok)
|
|
2685
|
-
return;
|
|
2686
|
-
let stored = await this.credentials.modify("xai", async () => grok);
|
|
2687
|
-
return clearPlanUsageCache(), await this.refresh({ allowNetwork: this.allowModelNetwork }), stored;
|
|
2688
|
-
}
|
|
2689
|
-
async reloadConfig() {
|
|
2690
|
-
this.config = await ModelConfig.load(this.modelsPath), this.configureRadiusProviders(), this.rebuildProviders(), await this.refresh({ allowNetwork: this.allowModelNetwork });
|
|
2691
|
-
}
|
|
2692
|
-
async refresh(options = {}) {
|
|
2693
|
-
let allowNetwork = options.allowNetwork ?? this.allowModelNetwork;
|
|
2694
|
-
if (this.catalogRefresh)
|
|
2695
|
-
return this.catalogRefreshAllowsNetwork || !allowNetwork ? this.catalogRefresh : (await this.catalogRefresh.catch(() => {
|
|
2696
|
-
}), this.refresh({ ...options, allowNetwork }));
|
|
2697
|
-
let run = this.executeCatalogRefresh({ ...options, allowNetwork }).finally(() => {
|
|
2698
|
-
this.catalogRefresh === run && (this.catalogRefresh = void 0, this.catalogRefreshAllowsNetwork = !1);
|
|
2699
|
-
});
|
|
2700
|
-
return this.catalogRefresh = run, this.catalogRefreshAllowsNetwork = allowNetwork, run;
|
|
2701
|
-
}
|
|
2702
|
-
async executeCatalogRefresh(refreshOptions) {
|
|
2703
|
-
let official = await this.refreshOfficialCatalog(refreshOptions.allowNetwork, refreshOptions.signal), live = refreshOptions.allowNetwork ? await this.refreshLiveCatalogs(official ? officialModelKeys(official.catalog) : /* @__PURE__ */ new Set(), refreshOptions.signal) : await this.restoreLiveCatalogs(), result = await this.models.refresh(refreshOptions) ?? {
|
|
2704
|
-
aborted: refreshOptions.signal?.aborted ?? !1,
|
|
2705
|
-
errors: /* @__PURE__ */ new Map()
|
|
2706
|
-
}, errors = new Map(result.errors);
|
|
2707
|
-
for (let [id, error] of Object.entries(official?.errors ?? {}))
|
|
2708
|
-
errors.set(id, new Error(error));
|
|
2709
|
-
for (let entry of live)
|
|
2710
|
-
(entry.status === "error" || entry.status === "timeout") && errors.set(entry.providerId, new Error(entry.error ?? entry.status));
|
|
2711
|
-
this.updateModelSnapshot();
|
|
2712
|
-
try {
|
|
2713
|
-
await this.forceRefreshAvailability();
|
|
2714
|
-
} catch {
|
|
2715
|
-
}
|
|
2716
|
-
let catalogResult = {
|
|
2717
|
-
aborted: result.aborted,
|
|
2718
|
-
errors,
|
|
2719
|
-
official,
|
|
2720
|
-
live,
|
|
2721
|
-
incomplete: live.flatMap((entry) => entry.incomplete)
|
|
2722
|
-
};
|
|
2723
|
-
return this.lastCatalogRefresh = catalogResult, catalogResult;
|
|
2724
|
-
}
|
|
2725
|
-
getLastCatalogRefresh() {
|
|
2726
|
-
return this.lastCatalogRefresh;
|
|
2727
|
-
}
|
|
2728
|
-
/** Called after first paint and by the picker; explicit /refresh always bypasses this gate. */
|
|
2729
|
-
async refreshIfStale(options = {}) {
|
|
2730
|
-
if (!this.allowModelNetwork || options.signal?.aborted)
|
|
2731
|
-
return this.lastCatalogRefresh;
|
|
2732
|
-
if (this.catalogRefresh)
|
|
2733
|
-
return this.refresh({ allowNetwork: !0, signal: options.signal });
|
|
2734
|
-
let providers = [...await this.listStoredProviderIds()].sort(), identity = (await Promise.all(providers.map(async (id) => this.scopeFor(id)))).join(":");
|
|
2735
|
-
if (identity === this.automaticRefreshIdentity && Date.now() < this.nextAutomaticRefresh)
|
|
2736
|
-
return this.lastCatalogRefresh;
|
|
2737
|
-
this.automaticRefreshIdentity = identity, this.nextAutomaticRefresh = Date.now() + 6e4;
|
|
2738
|
-
let result = await this.refresh({ allowNetwork: !0, signal: options.signal });
|
|
2739
|
-
return !result.aborted && !result.errors.size && (this.nextAutomaticRefresh = Date.now() + 36e5), result;
|
|
2740
|
-
}
|
|
2741
|
-
async scopeFor(providerId) {
|
|
2742
|
-
let provider = this.models.getProvider(providerId) ?? this.defaultBuiltins.get(providerId);
|
|
2743
|
-
return catalogCacheScope(providerId, provider?.baseUrl ?? "", await this.credentials.read(providerId));
|
|
2744
|
-
}
|
|
2745
|
-
persistUserModels(rows) {
|
|
2746
|
-
this.userModels.upsert(rows), this.overlay.setUser(this.userModelsForStoredProviders(this.snapshot.storedProviders)), this.updateModelSnapshot();
|
|
2747
|
-
}
|
|
2748
|
-
async refreshOfficialCatalog(allowNetwork, signal) {
|
|
2749
|
-
let storedProviders = await this.listStoredProviderIds(), loaded = preferOfficialCatalog(this.lastOfficial, await loadOfficialCatalog({
|
|
2750
|
-
allowNetwork,
|
|
2751
|
-
cachePath: this.officialCachePath,
|
|
2752
|
-
signal,
|
|
2753
|
-
providerIds: [...storedProviders]
|
|
2754
|
-
}));
|
|
2755
|
-
this.lastOfficial = loaded;
|
|
2756
|
-
let evicted = this.userModels.evictOfficial(officialModelKeys(loaded.catalog)), templateByProvider = /* @__PURE__ */ new Map(), officialModels = loaded.catalog.models.filter((entry) => storedProviders.has(entry.provider)).map((entry) => (templateByProvider.has(entry.provider) || templateByProvider.set(entry.provider, this.bakedInModels(entry.provider)[0]), officialEntryToModel(entry, templateByProvider.get(entry.provider))));
|
|
2757
|
-
return this.overlay.setOfficial(officialModels), this.overlay.setUser(this.userModelsForStoredProviders(storedProviders)), { ...loaded, evictedUserRows: evicted.length };
|
|
2758
|
-
}
|
|
2759
|
-
async restoreLiveCatalogs() {
|
|
2760
|
-
let storedProviders = await this.listStoredProviderIds(), results = [];
|
|
2761
|
-
for (let providerId of LIVE_LIST_PROVIDER_IDS) {
|
|
2762
|
-
let stored = storedProviders.has(providerId) ? await this.modelsStore.read(providerId) : void 0;
|
|
2763
|
-
(!stored?.scope && providerId !== "openai-codex" || stored?.scope === await this.scopeFor(providerId)) && stored?.models ? this.overlay.setLive(providerId, stored.models) : this.overlay.setLive(providerId, []), results.push({
|
|
2764
|
-
providerId,
|
|
2765
|
-
status: "skipped",
|
|
2766
|
-
discoveries: [],
|
|
2767
|
-
added: 0,
|
|
2768
|
-
total: stored?.models.length ?? 0,
|
|
2769
|
-
incomplete: []
|
|
2770
|
-
});
|
|
2771
|
-
}
|
|
2772
|
-
return results;
|
|
2773
|
-
}
|
|
2774
|
-
async refreshLiveCatalogs(officialKeys, signal) {
|
|
2775
|
-
let storedProviders = await this.listStoredProviderIds(), known = knownModelKeys(LIVE_LIST_PROVIDER_IDS.flatMap((id) => this.bakedInModels(id)), officialKeys, this.userModels.keys());
|
|
2776
|
-
return await Promise.all(LIVE_LIST_PROVIDER_IDS.map(async (providerId) => {
|
|
2777
|
-
if (!storedProviders.has(providerId))
|
|
2778
|
-
return this.overlay.setLive(providerId, []), {
|
|
2779
|
-
providerId,
|
|
2780
|
-
status: "skipped",
|
|
2781
|
-
discoveries: [],
|
|
2782
|
-
added: 0,
|
|
2783
|
-
total: 0,
|
|
2784
|
-
incomplete: []
|
|
2785
|
-
};
|
|
2786
|
-
let stored = await this.modelsStore.read(providerId), initialScope = await this.scopeFor(providerId);
|
|
2787
|
-
if (stored?.models && (stored.scope === initialScope || !stored.scope && providerId !== "openai-codex") ? this.overlay.setLive(providerId, stored.models) : this.overlay.setLive(providerId, []), signal?.aborted)
|
|
2788
|
-
return {
|
|
2789
|
-
providerId,
|
|
2790
|
-
status: "skipped",
|
|
2791
|
-
discoveries: [],
|
|
2792
|
-
added: 0,
|
|
2793
|
-
total: stored?.models.length ?? 0,
|
|
2794
|
-
incomplete: [],
|
|
2795
|
-
error: "aborted"
|
|
2796
|
-
};
|
|
2797
|
-
let bakedIn = this.bakedInModels(providerId), baseUrl = (this.models.getProvider(providerId) ?? this.defaultBuiltins.get(providerId))?.baseUrl ?? bakedIn[0]?.baseUrl;
|
|
2798
|
-
if (!baseUrl)
|
|
2799
|
-
return {
|
|
2800
|
-
providerId,
|
|
2801
|
-
status: "skipped",
|
|
2802
|
-
discoveries: [],
|
|
2803
|
-
added: 0,
|
|
2804
|
-
total: 0,
|
|
2805
|
-
incomplete: []
|
|
2806
|
-
};
|
|
2807
|
-
let credential;
|
|
2808
|
-
try {
|
|
2809
|
-
credential = await this.refreshCredentialFor(providerId);
|
|
2810
|
-
} catch (error) {
|
|
2811
|
-
return {
|
|
2812
|
-
providerId,
|
|
2813
|
-
status: "error",
|
|
2814
|
-
discoveries: [],
|
|
2815
|
-
added: 0,
|
|
2816
|
-
total: stored?.models.length ?? 0,
|
|
2817
|
-
incomplete: [],
|
|
2818
|
-
error: error instanceof Error ? error.message : String(error)
|
|
2819
|
-
};
|
|
2820
|
-
}
|
|
2821
|
-
if (!credential)
|
|
2822
|
-
return {
|
|
2823
|
-
providerId,
|
|
2824
|
-
status: "skipped",
|
|
2825
|
-
discoveries: [],
|
|
2826
|
-
added: 0,
|
|
2827
|
-
total: stored?.models.length ?? 0,
|
|
2828
|
-
incomplete: []
|
|
2829
|
-
};
|
|
2830
|
-
let requestScope = catalogCacheScope(providerId, baseUrl, credential), result = await fetchLiveProviderModels({
|
|
2831
|
-
discoveryClientVersion: stored?.scope === requestScope ? stored.discoveryClientVersion : void 0,
|
|
2832
|
-
providerId,
|
|
2833
|
-
baseUrl,
|
|
2834
|
-
bakedIn,
|
|
2835
|
-
credential,
|
|
2836
|
-
knownKeys: known,
|
|
2837
|
-
signal
|
|
2838
|
-
}), accountChanged = await this.scopeFor(providerId) !== requestScope;
|
|
2839
|
-
if (accountChanged && this.overlay.setLive(providerId, []), signal?.aborted || accountChanged)
|
|
2840
|
-
return { ...result, status: "skipped", discoveries: [], incomplete: [] };
|
|
2841
|
-
if (result.status === "ok") {
|
|
2842
|
-
let overlayModels = buildLiveOverlay(bakedIn, result.discoveries);
|
|
2843
|
-
this.overlay.setLive(providerId, overlayModels);
|
|
2844
|
-
try {
|
|
2845
|
-
await this.modelsStore.write(providerId, {
|
|
2846
|
-
models: overlayModels,
|
|
2847
|
-
checkedAt: Date.now(),
|
|
2848
|
-
scope: requestScope,
|
|
2849
|
-
discoveryClientVersion: result.discoveryClientVersion
|
|
2850
|
-
});
|
|
2851
|
-
} catch {
|
|
2852
|
-
}
|
|
2853
|
-
}
|
|
2854
|
-
return result;
|
|
2855
|
-
}));
|
|
2856
|
-
}
|
|
2857
|
-
async refreshCredentialFor(providerId) {
|
|
2858
|
-
let resolved = await this.getAuth(providerId), stored = await this.credentials.read(providerId);
|
|
2859
|
-
if (stored?.type === "oauth")
|
|
2860
|
-
return { ...stored, access: resolved?.auth.apiKey ?? stored.access };
|
|
2861
|
-
if (resolved?.auth.apiKey)
|
|
2862
|
-
return { type: "api_key", key: resolved.auth.apiKey, env: resolved.env };
|
|
2863
|
-
if (stored?.type === "api_key" && stored.key)
|
|
2864
|
-
return stored;
|
|
2865
|
-
}
|
|
2866
|
-
registerProvider(providerId, config) {
|
|
2867
|
-
validateExtensionProvider(providerId, this.builtins.get(providerId), this.config.getProvider(providerId), config);
|
|
2868
|
-
let effective = { ...this.extensionProviders.get(providerId) };
|
|
2869
|
-
for (let [key, value] of Object.entries(config))
|
|
2870
|
-
value !== void 0 && (effective[key] = value);
|
|
2871
|
-
if (this.extensionProviders.set(providerId, effective), this.recomposeProvider(providerId), this.updateModelSnapshot(), this.snapshot.storedProviders.has(providerId) || configuredRequestAuthStatus(this.config.getProvider(providerId), effective)?.configured) {
|
|
2872
|
-
let configuredProviders = new Set(this.snapshot.configuredProviders).add(providerId), auth = new Map(this.snapshot.auth);
|
|
2873
|
-
auth.get(providerId) || auth.set(providerId, {
|
|
2874
|
-
type: effective.oauth && !effective.apiKey ? "oauth" : "api_key",
|
|
2875
|
-
source: "configured provider"
|
|
2876
|
-
}), this.snapshot = {
|
|
2877
|
-
...this.snapshot,
|
|
2878
|
-
auth,
|
|
2879
|
-
configuredProviders,
|
|
2880
|
-
available: this.snapshot.all.filter((model) => configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model))
|
|
2881
|
-
};
|
|
2882
|
-
}
|
|
2883
|
-
this.refresh({ allowNetwork: !1 });
|
|
2884
|
-
}
|
|
2885
|
-
unregisterProvider(providerId) {
|
|
2886
|
-
this.extensionProviders.delete(providerId), this.recomposeProvider(providerId), this.updateModelSnapshot(), this.refresh({ allowNetwork: !1 });
|
|
2887
|
-
}
|
|
2888
|
-
};
|
|
2889
|
-
async function refreshModelCandidatesForInit(runtime) {
|
|
2890
|
-
return await runtime.refresh({ allowNetwork: !1 }), runtime.getAvailableSnapshot();
|
|
2891
|
-
}
|
|
103
|
+
// packages/coding-agent/dist/core/agent-session-services.js
|
|
104
|
+
import { join as join7 } from "node:path";
|
|
2892
105
|
|
|
2893
106
|
// packages/coding-agent/dist/core/sdk.js
|
|
2894
|
-
import { join as
|
|
107
|
+
import { join as join6 } from "node:path";
|
|
2895
108
|
import { Agent } from "@ashx-j/lunr-agent";
|
|
2896
109
|
import { clampThinkingLevel as clampThinkingLevel2 } from "@ashx-j/lunr-ai";
|
|
2897
110
|
|
|
2898
111
|
// packages/coding-agent/dist/core/agent-session.js
|
|
2899
|
-
import { existsSync as
|
|
2900
|
-
import { basename, dirname as
|
|
112
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
113
|
+
import { basename, dirname as dirname2, join as join4, resolve as resolve2 } from "node:path";
|
|
2901
114
|
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple } from "@ashx-j/lunr-ai/compat";
|
|
2902
115
|
|
|
2903
116
|
// packages/coding-agent/dist/utils/sleep.js
|
|
2904
117
|
function sleep(ms, signal) {
|
|
2905
|
-
return new Promise((
|
|
118
|
+
return new Promise((resolve3, reject) => {
|
|
2906
119
|
if (signal?.aborted) {
|
|
2907
120
|
reject(new Error("Aborted"));
|
|
2908
121
|
return;
|
|
2909
122
|
}
|
|
2910
|
-
let timeout = setTimeout(
|
|
123
|
+
let timeout = setTimeout(resolve3, ms);
|
|
2911
124
|
signal?.addEventListener("abort", () => {
|
|
2912
125
|
clearTimeout(timeout), reject(new Error("Aborted"));
|
|
2913
126
|
});
|
|
@@ -2915,13 +128,13 @@ function sleep(ms, signal) {
|
|
|
2915
128
|
}
|
|
2916
129
|
|
|
2917
130
|
// packages/coding-agent/dist/core/auth-guidance.js
|
|
2918
|
-
import { join
|
|
131
|
+
import { join } from "node:path";
|
|
2919
132
|
var UNKNOWN_PROVIDER = "unknown";
|
|
2920
133
|
function getProviderLoginHelp() {
|
|
2921
134
|
return [
|
|
2922
135
|
"Use /login to log into a provider via OAuth or API key. See:",
|
|
2923
|
-
` ${
|
|
2924
|
-
` ${
|
|
136
|
+
` ${join(getDocsPath(), "providers.md")}`,
|
|
137
|
+
` ${join(getDocsPath(), "models.md")}`
|
|
2925
138
|
].join(`
|
|
2926
139
|
`);
|
|
2927
140
|
}
|
|
@@ -2945,13 +158,13 @@ ${getProviderLoginHelp()}`;
|
|
|
2945
158
|
import { randomBytes } from "node:crypto";
|
|
2946
159
|
import { createWriteStream } from "node:fs";
|
|
2947
160
|
import { tmpdir } from "node:os";
|
|
2948
|
-
import { join as
|
|
161
|
+
import { join as join2 } from "node:path";
|
|
2949
162
|
async function executeBashWithOperations(command, cwd, operations, options) {
|
|
2950
163
|
let outputChunks = [], outputBytes = 0, maxOutputBytes = 51200 * 2, tempFilePath, tempFileStream, totalBytes = 0, ensureTempFile = () => {
|
|
2951
164
|
if (tempFilePath)
|
|
2952
165
|
return;
|
|
2953
166
|
let id = randomBytes(8).toString("hex");
|
|
2954
|
-
tempFilePath =
|
|
167
|
+
tempFilePath = join2(tmpdir(), `lunr-bash-${id}.log`), tempFileStream = createWriteStream(tempFilePath);
|
|
2955
168
|
for (let chunk of outputChunks)
|
|
2956
169
|
tempFileStream.write(chunk);
|
|
2957
170
|
}, decoder = new TextDecoder(), onData = (data) => {
|
|
@@ -3086,12 +299,12 @@ var ModelRegistry = class {
|
|
|
3086
299
|
};
|
|
3087
300
|
|
|
3088
301
|
// packages/coding-agent/dist/core/rollback.js
|
|
3089
|
-
import { spawnSync
|
|
3090
|
-
import { createHash
|
|
3091
|
-
import { cpSync, existsSync
|
|
3092
|
-
import { homedir
|
|
3093
|
-
import { dirname
|
|
3094
|
-
var ROLLBACK_BASE =
|
|
302
|
+
import { spawnSync } from "node:child_process";
|
|
303
|
+
import { createHash } from "node:crypto";
|
|
304
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
305
|
+
import { homedir } from "node:os";
|
|
306
|
+
import { dirname, join as join3, normalize, resolve } from "node:path";
|
|
307
|
+
var ROLLBACK_BASE = join3(homedir(), ".lunr", "rollback"), contexts = /* @__PURE__ */ new Map(), lastSessionId, globalSettingsManager, warningHandler;
|
|
3095
308
|
function setRollbackWarningHandler(handler) {
|
|
3096
309
|
warningHandler = handler;
|
|
3097
310
|
}
|
|
@@ -3151,8 +364,8 @@ function rollbackSnapshotBeforeWrite(absPath, sessionId) {
|
|
|
3151
364
|
let turn = ctx.turns[ctx.turns.length - 1];
|
|
3152
365
|
if (turn && !turn.files.has(absPath))
|
|
3153
366
|
try {
|
|
3154
|
-
let existed =
|
|
3155
|
-
existed && (content =
|
|
367
|
+
let existed = existsSync(absPath), content;
|
|
368
|
+
existed && (content = readFileSync(absPath)), turn.files.set(absPath, {
|
|
3156
369
|
existed,
|
|
3157
370
|
content,
|
|
3158
371
|
createdByTool: !0
|
|
@@ -3169,13 +382,13 @@ function captureTreeBaseline(ctx, cwd) {
|
|
|
3169
382
|
for (let { path } of entries) {
|
|
3170
383
|
if (!path)
|
|
3171
384
|
continue;
|
|
3172
|
-
let abs =
|
|
385
|
+
let abs = join3(cwd, path);
|
|
3173
386
|
if (!turn.files.has(abs))
|
|
3174
387
|
try {
|
|
3175
|
-
let existed =
|
|
388
|
+
let existed = existsSync(abs);
|
|
3176
389
|
turn.files.set(abs, {
|
|
3177
390
|
existed,
|
|
3178
|
-
content: existed ?
|
|
391
|
+
content: existed ? readFileSync(abs) : void 0,
|
|
3179
392
|
createdByTool: !1
|
|
3180
393
|
}), persistSnapshot(ctx, turn, abs);
|
|
3181
394
|
} catch {
|
|
@@ -3194,14 +407,14 @@ function captureTreeChanges(cwd, sessionId) {
|
|
|
3194
407
|
for (let { status, path, source } of entries) {
|
|
3195
408
|
if (!path)
|
|
3196
409
|
continue;
|
|
3197
|
-
let abs =
|
|
410
|
+
let abs = join3(cwd, path);
|
|
3198
411
|
if (!turn.files.has(abs))
|
|
3199
412
|
try {
|
|
3200
413
|
if (status === "??" || status.includes("R")) {
|
|
3201
414
|
if (turn.files.set(abs, { existed: !1, createdByTool: !1 }), persistSnapshot(ctx, turn, abs), status.includes("R") && source) {
|
|
3202
|
-
let sourceAbs =
|
|
415
|
+
let sourceAbs = join3(cwd, source);
|
|
3203
416
|
if (!turn.files.has(sourceAbs)) {
|
|
3204
|
-
let headSrc =
|
|
417
|
+
let headSrc = spawnSync("git", ["show", `HEAD:${source}`], {
|
|
3205
418
|
cwd,
|
|
3206
419
|
timeout: 5e3,
|
|
3207
420
|
maxBuffer: 33554432
|
|
@@ -3214,7 +427,7 @@ function captureTreeChanges(cwd, sessionId) {
|
|
|
3214
427
|
}
|
|
3215
428
|
}
|
|
3216
429
|
} else {
|
|
3217
|
-
let head =
|
|
430
|
+
let head = spawnSync("git", ["show", `HEAD:${path}`], {
|
|
3218
431
|
cwd,
|
|
3219
432
|
timeout: 5e3,
|
|
3220
433
|
maxBuffer: 33554432
|
|
@@ -3233,7 +446,7 @@ function captureTreeChanges(cwd, sessionId) {
|
|
|
3233
446
|
}
|
|
3234
447
|
function gitPorcelain(ctx, cwd) {
|
|
3235
448
|
try {
|
|
3236
|
-
let result =
|
|
449
|
+
let result = spawnSync("git", ["status", "--porcelain", "-z"], { cwd, encoding: "utf8", timeout: 5e3 });
|
|
3237
450
|
if (result.error || result.status !== 0) {
|
|
3238
451
|
warnOnce(ctx, "Rollback tree scope: not a git repository (or git failed) \u2014 bash side-effects won't be captured.");
|
|
3239
452
|
return;
|
|
@@ -3264,21 +477,21 @@ function persistSnapshot(ctx, turn, absPath) {
|
|
|
3264
477
|
if (!snap)
|
|
3265
478
|
return;
|
|
3266
479
|
let turnDir = getTurnDir(ctx, turn.turnIndex);
|
|
3267
|
-
|
|
3268
|
-
let manifestPath =
|
|
480
|
+
mkdirSync(turnDir, { recursive: !0 });
|
|
481
|
+
let manifestPath = join3(turnDir, "manifest.json"), manifest = readManifest(manifestPath), entry = { existed: snap.existed, createdByTool: snap.createdByTool };
|
|
3269
482
|
if (snap.content) {
|
|
3270
483
|
let snapFile = snapFileName(absPath);
|
|
3271
|
-
|
|
484
|
+
writeFileSync(join3(turnDir, snapFile), snap.content), entry.snapFile = snapFile;
|
|
3272
485
|
}
|
|
3273
|
-
manifest.files[absPath] = entry, turn.cwd && (manifest.cwd = turn.cwd),
|
|
486
|
+
manifest.files[absPath] = entry, turn.cwd && (manifest.cwd = turn.cwd), writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
3274
487
|
} catch {
|
|
3275
488
|
}
|
|
3276
489
|
}
|
|
3277
490
|
function readManifest(path) {
|
|
3278
|
-
if (!
|
|
491
|
+
if (!existsSync(path))
|
|
3279
492
|
return { files: {} };
|
|
3280
493
|
try {
|
|
3281
|
-
let parsed = JSON.parse(
|
|
494
|
+
let parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
3282
495
|
if (parsed && typeof parsed == "object" && !Array.isArray(parsed)) {
|
|
3283
496
|
let files = parsed.files;
|
|
3284
497
|
return {
|
|
@@ -3293,20 +506,20 @@ function readManifest(path) {
|
|
|
3293
506
|
}
|
|
3294
507
|
function loadPersistedTurns(ctx) {
|
|
3295
508
|
try {
|
|
3296
|
-
let sessionDir =
|
|
3297
|
-
if (!
|
|
509
|
+
let sessionDir = join3(ROLLBACK_BASE, ctx.sessionId);
|
|
510
|
+
if (!existsSync(sessionDir))
|
|
3298
511
|
return;
|
|
3299
512
|
let loaded = [];
|
|
3300
513
|
for (let dirName of readdirSync(sessionDir)) {
|
|
3301
514
|
let match = /^turn-(\d+)$/.exec(dirName);
|
|
3302
515
|
if (!match)
|
|
3303
516
|
continue;
|
|
3304
|
-
let turnIndex = Number(match[1]), turnDir =
|
|
517
|
+
let turnIndex = Number(match[1]), turnDir = join3(sessionDir, dirName), manifest = readManifest(join3(turnDir, "manifest.json")), files = /* @__PURE__ */ new Map();
|
|
3305
518
|
for (let [absPath, meta] of Object.entries(manifest.files)) {
|
|
3306
519
|
let content;
|
|
3307
520
|
if (meta.snapFile)
|
|
3308
521
|
try {
|
|
3309
|
-
content =
|
|
522
|
+
content = readFileSync(join3(turnDir, meta.snapFile));
|
|
3310
523
|
} catch {
|
|
3311
524
|
content = void 0;
|
|
3312
525
|
}
|
|
@@ -3319,12 +532,12 @@ function loadPersistedTurns(ctx) {
|
|
|
3319
532
|
}
|
|
3320
533
|
}
|
|
3321
534
|
function getTurnDir(ctx, turnIndex) {
|
|
3322
|
-
return
|
|
535
|
+
return join3(ROLLBACK_BASE, ctx.sessionId, `turn-${turnIndex}`);
|
|
3323
536
|
}
|
|
3324
537
|
function cleanupTurnFiles(ctx, turn) {
|
|
3325
538
|
try {
|
|
3326
539
|
let dir = getTurnDir(ctx, turn.turnIndex);
|
|
3327
|
-
|
|
540
|
+
existsSync(dir) && rmSync(dir, { recursive: !0, force: !0 });
|
|
3328
541
|
} catch {
|
|
3329
542
|
}
|
|
3330
543
|
}
|
|
@@ -3335,10 +548,10 @@ function isPathUnderRoot(absPath, root) {
|
|
|
3335
548
|
function isWithinAllowedRoots(absPath, turn) {
|
|
3336
549
|
return turn.cwd ? [
|
|
3337
550
|
ROLLBACK_BASE,
|
|
3338
|
-
|
|
551
|
+
join3(homedir(), CONFIG_DIR_NAME),
|
|
3339
552
|
// lunr: agent settings / cron jobs.json live under the config dir
|
|
3340
553
|
// lunr: simple-memory lives next to the lunr agent dir (~/.lunr/simple-memory)
|
|
3341
|
-
|
|
554
|
+
join3(dirname(getAgentDir()), "simple-memory"),
|
|
3342
555
|
resolve(turn.cwd)
|
|
3343
556
|
].some((root) => isPathUnderRoot(absPath, root)) : !0;
|
|
3344
557
|
}
|
|
@@ -3380,10 +593,10 @@ function rollbackLastTurn(sessionId) {
|
|
|
3380
593
|
continue;
|
|
3381
594
|
}
|
|
3382
595
|
if (snap.existed && snap.content) {
|
|
3383
|
-
if (!snap.createdByTool &&
|
|
596
|
+
if (!snap.createdByTool && existsSync(absPath) && readFileSync(absPath).equals(snap.content))
|
|
3384
597
|
continue;
|
|
3385
|
-
|
|
3386
|
-
} else snap.existed || (snap.createdByTool || capture === "hybrid" || capture === "shadow-git") &&
|
|
598
|
+
mkdirSync(dirname(absPath), { recursive: !0 }), writeFileSync(absPath, snap.content), restored.push(absPath);
|
|
599
|
+
} else snap.existed || (snap.createdByTool || capture === "hybrid" || capture === "shadow-git") && existsSync(absPath) && (unlinkSync(absPath), deleted.push(absPath));
|
|
3387
600
|
} catch {
|
|
3388
601
|
}
|
|
3389
602
|
return cleanupTurnFiles(ctx, turn), ctx.turns.pop(), { restored, deleted, turnsConsumed };
|
|
@@ -3394,11 +607,11 @@ function migrateRollbackSession(oldSessionId, newSessionId) {
|
|
|
3394
607
|
let ctx = contexts.get(oldSessionId);
|
|
3395
608
|
ctx && (contexts.delete(oldSessionId), ctx.sessionId = newSessionId, contexts.set(newSessionId, ctx));
|
|
3396
609
|
try {
|
|
3397
|
-
let oldDir =
|
|
3398
|
-
if (
|
|
3399
|
-
|
|
610
|
+
let oldDir = join3(ROLLBACK_BASE, oldSessionId), newDir = join3(ROLLBACK_BASE, newSessionId);
|
|
611
|
+
if (existsSync(oldDir)) {
|
|
612
|
+
existsSync(newDir) && rmSync(newDir, { recursive: !0, force: !0 });
|
|
3400
613
|
try {
|
|
3401
|
-
|
|
614
|
+
renameSync(oldDir, newDir);
|
|
3402
615
|
} catch {
|
|
3403
616
|
cpSync(oldDir, newDir, { recursive: !0 }), rmSync(oldDir, { recursive: !0, force: !0 });
|
|
3404
617
|
}
|
|
@@ -3412,8 +625,8 @@ function clearRollback(sessionId) {
|
|
|
3412
625
|
for (let turn of ctx2.turns)
|
|
3413
626
|
cleanupTurnFiles(ctx2, turn);
|
|
3414
627
|
try {
|
|
3415
|
-
let sessionDir =
|
|
3416
|
-
|
|
628
|
+
let sessionDir = join3(ROLLBACK_BASE, ctx2.sessionId);
|
|
629
|
+
existsSync(sessionDir) && rmSync(sessionDir, { recursive: !0, force: !0 });
|
|
3417
630
|
} catch {
|
|
3418
631
|
}
|
|
3419
632
|
}
|
|
@@ -3425,15 +638,15 @@ function clearRollback(sessionId) {
|
|
|
3425
638
|
for (let turn of ctx.turns)
|
|
3426
639
|
cleanupTurnFiles(ctx, turn);
|
|
3427
640
|
try {
|
|
3428
|
-
let sessionDir =
|
|
3429
|
-
|
|
641
|
+
let sessionDir = join3(ROLLBACK_BASE, sessionId);
|
|
642
|
+
existsSync(sessionDir) && rmSync(sessionDir, { recursive: !0, force: !0 });
|
|
3430
643
|
} catch {
|
|
3431
644
|
}
|
|
3432
645
|
contexts.delete(sessionId);
|
|
3433
646
|
}
|
|
3434
647
|
}
|
|
3435
648
|
function snapFileName(absPath) {
|
|
3436
|
-
return `${
|
|
649
|
+
return `${createHash("sha1").update(absPath).digest("hex")}.snap`;
|
|
3437
650
|
}
|
|
3438
651
|
|
|
3439
652
|
// packages/coding-agent/dist/core/system-prompt.js
|
|
@@ -3463,7 +676,8 @@ ${content}
|
|
|
3463
676
|
return (!selectedTools || selectedTools.includes("read")) && skills.length > 0 && (prompt2 += formatSkillsForPrompt(skills)), prompt2 += `
|
|
3464
677
|
Current working directory: ${promptCwd}`, prompt2;
|
|
3465
678
|
}
|
|
3466
|
-
let readmePath = getReadmePath(), docsPath = getDocsPath(), examplesPath = getExamplesPath(), currentModel = modelSlug?.trim() || "no model selected", hasRead = !selectedTools || selectedTools.includes("read"),
|
|
679
|
+
let readmePath = getReadmePath(), docsPath = getDocsPath(), examplesPath = getExamplesPath(), currentModel = modelSlug?.trim() || "no model selected", hasRead = !selectedTools || selectedTools.includes("read"), todoGuideline = !selectedTools || selectedTools.includes("todo") ? `- Use todo for meaningful multi-step work. Every update must send the complete list, with exactly one item in progress at a time.
|
|
680
|
+
` : "", prompt = `You are an expert coding assistant currently running ''${currentModel}'', operating inside lunR, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
|
|
3467
681
|
Current working directory: ''${promptCwd}''
|
|
3468
682
|
|
|
3469
683
|
Behavior guidelines:
|
|
@@ -3474,6 +688,7 @@ Behavior guidelines:
|
|
|
3474
688
|
- When several agents work in parallel, state file ownership up front so they do not collide.
|
|
3475
689
|
- Tests are good! Endless smoke tests, regressions tests for feature deletions, etc, much less good. Tests should be focused, not slop.
|
|
3476
690
|
- Prefer editing existing files to creating new ones.
|
|
691
|
+
- When a reusable excerpt, prompt, or code fragment should have its own Copy button, wrap only that payload in a fenced Markdown block with the info string \`lunr-copy\`. Keep explanation outside the block. Use a longer backtick or tilde fence when the payload contains fenced code.
|
|
3477
692
|
- Only use emojis if the user explicitly requests it.
|
|
3478
693
|
- Never exfil private data on public platforms like github or any other services under any circumstances.
|
|
3479
694
|
|
|
@@ -3486,8 +701,7 @@ Guidelines:
|
|
|
3486
701
|
- Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.
|
|
3487
702
|
- Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.
|
|
3488
703
|
- Use write only for new files or complete rewrites.
|
|
3489
|
-
- Use
|
|
3490
|
-
- Use subagents for independent parallel work, specialist analysis, or substantial research. Subagents start with fresh sessions. Use intercom instead to coordinate with an existing lunR session.
|
|
704
|
+
${todoGuideline}- Use subagents for independent parallel work, specialist analysis, or substantial research. Subagents start with fresh sessions. Use intercom instead to coordinate with an existing lunR session.
|
|
3491
705
|
- Use ast_search for structural code matches.
|
|
3492
706
|
- Use cron only when the user asks to schedule or manage unattended prompts.
|
|
3493
707
|
- Memory stores established, durable facts and stable preferences. Do not store behavior instructions, transient task details, transcripts, guesses, or secrets. Change memory only with the memory tools.
|
|
@@ -3670,10 +884,10 @@ var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"
|
|
|
3670
884
|
if (toolName === "edit" || toolName === "write")
|
|
3671
885
|
argPath && pathsToSnapshot.push(argPath);
|
|
3672
886
|
else if (toolName === "memory_add" || toolName === "memory_remove")
|
|
3673
|
-
pathsToSnapshot.push(
|
|
887
|
+
pathsToSnapshot.push(join4(dirname2(getAgentDir()), "simple-memory", "memory.md"));
|
|
3674
888
|
else if (toolName === "cron" && args && typeof args == "object") {
|
|
3675
889
|
let action = String(args.action ?? "");
|
|
3676
|
-
(action === "create" || action === "update" || action === "remove") && pathsToSnapshot.push(
|
|
890
|
+
(action === "create" || action === "update" || action === "remove") && pathsToSnapshot.push(join4(getAgentDir(), "cron", "jobs.json"));
|
|
3677
891
|
}
|
|
3678
892
|
for (let p of pathsToSnapshot)
|
|
3679
893
|
rollbackSnapshotBeforeWrite(p, this.sessionId);
|
|
@@ -3755,15 +969,15 @@ var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"
|
|
|
3755
969
|
});
|
|
3756
970
|
}
|
|
3757
971
|
_getIdleWaitPromise() {
|
|
3758
|
-
return this._idleWaitPromise || (this._idleWaitPromise = new Promise((
|
|
3759
|
-
this._resolveIdleWait =
|
|
972
|
+
return this._idleWaitPromise || (this._idleWaitPromise = new Promise((resolve3) => {
|
|
973
|
+
this._resolveIdleWait = resolve3;
|
|
3760
974
|
})), this._idleWaitPromise;
|
|
3761
975
|
}
|
|
3762
976
|
_resolveIdleWaitIfIdle() {
|
|
3763
977
|
if (this._isAgentRunActive || !this._resolveIdleWait)
|
|
3764
978
|
return;
|
|
3765
|
-
let
|
|
3766
|
-
this._idleWaitPromise = void 0, this._resolveIdleWait = void 0,
|
|
979
|
+
let resolve3 = this._resolveIdleWait;
|
|
980
|
+
this._idleWaitPromise = void 0, this._resolveIdleWait = void 0, resolve3();
|
|
3767
981
|
}
|
|
3768
982
|
async _emitAgentSettled() {
|
|
3769
983
|
this._isAgentRunActive = !1;
|
|
@@ -3936,12 +1150,20 @@ var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"
|
|
|
3936
1150
|
* Remove all listeners and disconnect from agent.
|
|
3937
1151
|
* Call this when completely done with the session.
|
|
3938
1152
|
*/
|
|
1153
|
+
transferring = !1;
|
|
1154
|
+
setTransferring(value) {
|
|
1155
|
+
this.transferring = value;
|
|
1156
|
+
}
|
|
1157
|
+
assertCanStartWork() {
|
|
1158
|
+
if (this.sessionManager.assertWritable(), this.transferring)
|
|
1159
|
+
throw new Error("Session transfer is in progress. Wait or reclaim the session.");
|
|
1160
|
+
}
|
|
3939
1161
|
dispose() {
|
|
3940
1162
|
try {
|
|
3941
1163
|
this.abortRetry(), this.abortCompaction(), this.abortBranchSummary(), this.abortBash(), this.agent.abort();
|
|
3942
1164
|
} catch {
|
|
3943
1165
|
}
|
|
3944
|
-
this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."), this._disconnectFromAgent(), this._eventListeners = [], cleanupSessionResources(this.sessionId);
|
|
1166
|
+
this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."), this._disconnectFromAgent(), this._eventListeners = [], cleanupSessionResources(this.sessionId), this.sessionManager.dispose();
|
|
3945
1167
|
}
|
|
3946
1168
|
// =========================================================================
|
|
3947
1169
|
// Read-only State Access
|
|
@@ -4158,6 +1380,7 @@ ${this._systemPromptAppend}` : prompt;
|
|
|
4158
1380
|
* @throws Error if no model selected or no API key available (when not streaming)
|
|
4159
1381
|
*/
|
|
4160
1382
|
async prompt(text, options) {
|
|
1383
|
+
this.assertCanStartWork();
|
|
4161
1384
|
let expandPromptTemplates = options?.expandPromptTemplates ?? !0, preflightResult = options?.preflightResult, messages;
|
|
4162
1385
|
try {
|
|
4163
1386
|
if (expandPromptTemplates && text.startsWith("/") && await this._tryExecuteExtensionCommand(text)) {
|
|
@@ -4243,7 +1466,7 @@ ${this._systemPromptAppend}` : prompt;
|
|
|
4243
1466
|
if (!skill)
|
|
4244
1467
|
return text;
|
|
4245
1468
|
try {
|
|
4246
|
-
let content =
|
|
1469
|
+
let content = readFileSync2(skill.filePath, "utf-8"), body = stripFrontmatter(content).trim(), skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
|
|
4247
1470
|
References are relative to ${skill.baseDir}.
|
|
4248
1471
|
|
|
4249
1472
|
${body}
|
|
@@ -4268,7 +1491,7 @@ ${args}` : skillBlock;
|
|
|
4268
1491
|
* @throws Error if text is an extension command
|
|
4269
1492
|
*/
|
|
4270
1493
|
async steer(text, images) {
|
|
4271
|
-
text.startsWith("/") && this._throwIfExtensionCommand(text);
|
|
1494
|
+
this.assertCanStartWork(), text.startsWith("/") && this._throwIfExtensionCommand(text);
|
|
4272
1495
|
let expandedText = this._expandSkillCommand(text);
|
|
4273
1496
|
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]), await this._queueSteer(expandedText, images);
|
|
4274
1497
|
}
|
|
@@ -4280,7 +1503,7 @@ ${args}` : skillBlock;
|
|
|
4280
1503
|
* @throws Error if text is an extension command
|
|
4281
1504
|
*/
|
|
4282
1505
|
async followUp(text, images) {
|
|
4283
|
-
text.startsWith("/") && this._throwIfExtensionCommand(text);
|
|
1506
|
+
this.assertCanStartWork(), text.startsWith("/") && this._throwIfExtensionCommand(text);
|
|
4284
1507
|
let expandedText = this._expandSkillCommand(text);
|
|
4285
1508
|
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]), await this._queueFollowUp(expandedText, images);
|
|
4286
1509
|
}
|
|
@@ -4329,6 +1552,7 @@ ${args}` : skillBlock;
|
|
|
4329
1552
|
* @param options.deliverAs Delivery mode: "steer", "followUp", or "nextTurn"
|
|
4330
1553
|
*/
|
|
4331
1554
|
async sendCustomMessage(message, options) {
|
|
1555
|
+
this.assertCanStartWork();
|
|
4332
1556
|
let appMessage = {
|
|
4333
1557
|
role: "custom",
|
|
4334
1558
|
customType: message.customType,
|
|
@@ -4877,7 +2101,7 @@ ${args}` : skillBlock;
|
|
|
4877
2101
|
}
|
|
4878
2102
|
buildExtensionResourcePaths(entries) {
|
|
4879
2103
|
return entries.map((entry) => {
|
|
4880
|
-
let source = this.getExtensionSourceLabel(entry.extensionPath), baseDir = entry.extensionPath.startsWith("<") ? void 0 :
|
|
2104
|
+
let source = this.getExtensionSourceLabel(entry.extensionPath), baseDir = entry.extensionPath.startsWith("<") ? void 0 : dirname2(entry.extensionPath);
|
|
4881
2105
|
return {
|
|
4882
2106
|
path: entry.path,
|
|
4883
2107
|
metadata: {
|
|
@@ -4972,7 +2196,7 @@ ${args}` : skillBlock;
|
|
|
4972
2196
|
}
|
|
4973
2197
|
this.abort();
|
|
4974
2198
|
},
|
|
4975
|
-
hasPendingMessages: () => this.pendingMessageCount > 0,
|
|
2199
|
+
hasPendingMessages: () => this.pendingMessageCount > 0 || this.agent.hasQueuedMessages(),
|
|
4976
2200
|
shutdown: () => {
|
|
4977
2201
|
this._extensionShutdownHandler?.();
|
|
4978
2202
|
},
|
|
@@ -5000,7 +2224,7 @@ ${args}` : skillBlock;
|
|
|
5000
2224
|
});
|
|
5001
2225
|
}
|
|
5002
2226
|
_refreshToolRegistry(options) {
|
|
5003
|
-
let previousRegistryNames = new Set(this._toolRegistry.keys()), previousActiveToolNames = this.getActiveToolNames(), allowedToolNames = this._allowedToolNames, excludedToolNames = this._excludedToolNames, isAllowedTool = (name) => (!allowedToolNames || allowedToolNames.has(name)) && !excludedToolNames?.has(name) && (this.settingsManager.getMemoryEnabled() || !MEMORY_TOOL_NAMES.has(name)), allCustomTools = [
|
|
2227
|
+
let previousRegistryNames = new Set(this._toolRegistry.keys()), previousActiveToolNames = this.getActiveToolNames(), allowedToolNames = this._allowedToolNames, excludedToolNames = this._excludedToolNames, isAllowedTool = (name) => (!allowedToolNames || allowedToolNames.has(name)) && !excludedToolNames?.has(name) && (this.settingsManager.getMemoryEnabled() || !MEMORY_TOOL_NAMES.has(name)) && (this.settingsManager.getTodosEnabled() || !TODO_TOOL_NAMES.has(name)) && (name !== "browser" || this.settingsManager.getBrowserEnabled()), allCustomTools = [
|
|
5004
2228
|
...this._extensionRunner.getAllRegisteredTools(),
|
|
5005
2229
|
...this._customTools.map((definition) => ({
|
|
5006
2230
|
definition,
|
|
@@ -5182,7 +2406,7 @@ ${args}` : skillBlock;
|
|
|
5182
2406
|
* @param options.operations Custom BashOperations for remote execution
|
|
5183
2407
|
*/
|
|
5184
2408
|
async executeBash(command, onChunk, options) {
|
|
5185
|
-
this._bashAbortController = new AbortController();
|
|
2409
|
+
this.assertCanStartWork(), this._bashAbortController = new AbortController();
|
|
5186
2410
|
let prefix = this.settingsManager.getShellCommandPrefix(), shellPath = this.settingsManager.getShellPath(), resolvedCommand = prefix ? `${prefix}
|
|
5187
2411
|
${command}` : command;
|
|
5188
2412
|
try {
|
|
@@ -5439,7 +2663,7 @@ ${command}` : command;
|
|
|
5439
2663
|
*/
|
|
5440
2664
|
async exportToHtml(outputPath) {
|
|
5441
2665
|
let [{ exportSessionToHtml }, { createToolHtmlRenderer }] = await Promise.all([
|
|
5442
|
-
import("./export-html-
|
|
2666
|
+
import("./export-html-KBFVV63J.js"),
|
|
5443
2667
|
import("./tool-renderer-MV5O452K.js")
|
|
5444
2668
|
]), configuredThemeName = this.settingsManager.getTheme(), themeName = configuredThemeName && getThemeByName(configuredThemeName) ? configuredThemeName : void 0, toolRenderer = createToolHtmlRenderer({
|
|
5445
2669
|
getToolDefinition: (name) => this.getToolDefinition(name),
|
|
@@ -5459,8 +2683,8 @@ ${command}` : command;
|
|
|
5459
2683
|
* @returns The resolved output file path.
|
|
5460
2684
|
*/
|
|
5461
2685
|
exportToJsonl(outputPath) {
|
|
5462
|
-
let filePath = resolvePath(outputPath ?? `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.jsonl`, process.cwd()), dir =
|
|
5463
|
-
|
|
2686
|
+
let filePath = resolvePath(outputPath ?? `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.jsonl`, process.cwd()), dir = dirname2(filePath);
|
|
2687
|
+
existsSync2(dir) || mkdirSync2(dir, { recursive: !0 });
|
|
5464
2688
|
let header = {
|
|
5465
2689
|
type: "session",
|
|
5466
2690
|
version: CURRENT_SESSION_VERSION,
|
|
@@ -5472,7 +2696,7 @@ ${command}` : command;
|
|
|
5472
2696
|
let linear = { ...entry, parentId: prevId };
|
|
5473
2697
|
lines.push(JSON.stringify(linear)), prevId = entry.id;
|
|
5474
2698
|
}
|
|
5475
|
-
return
|
|
2699
|
+
return writeFileSync2(filePath, `${lines.join(`
|
|
5476
2700
|
`)}
|
|
5477
2701
|
`), filePath;
|
|
5478
2702
|
}
|
|
@@ -5542,17 +2766,17 @@ function mergeProviderAttributionHeaders(model, _settingsManager, sessionId, ...
|
|
|
5542
2766
|
}
|
|
5543
2767
|
|
|
5544
2768
|
// packages/coding-agent/dist/core/agent-session-runtime.js
|
|
5545
|
-
import { copyFileSync, existsSync as
|
|
5546
|
-
import { basename as basename2, join as
|
|
2769
|
+
import { copyFileSync, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "node:fs";
|
|
2770
|
+
import { basename as basename2, join as join5 } from "node:path";
|
|
5547
2771
|
|
|
5548
2772
|
// packages/coding-agent/dist/core/session-cwd.js
|
|
5549
|
-
import { existsSync as
|
|
2773
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
5550
2774
|
function getMissingSessionCwdIssue(sessionManager, fallbackCwd) {
|
|
5551
2775
|
let sessionFile = sessionManager.getSessionFile();
|
|
5552
2776
|
if (!sessionFile)
|
|
5553
2777
|
return;
|
|
5554
2778
|
let sessionCwd = sessionManager.getCwd();
|
|
5555
|
-
if (!(!sessionCwd ||
|
|
2779
|
+
if (!(!sessionCwd || existsSync3(sessionCwd)))
|
|
5556
2780
|
return {
|
|
5557
2781
|
sessionFile,
|
|
5558
2782
|
sessionCwd,
|
|
@@ -5603,9 +2827,40 @@ var AgentSessionRuntime = class {
|
|
|
5603
2827
|
onRuntimeApplied;
|
|
5604
2828
|
_diagnostics;
|
|
5605
2829
|
_modelFallbackMessage;
|
|
2830
|
+
detached = !1;
|
|
2831
|
+
transferring = !1;
|
|
2832
|
+
get isDetached() {
|
|
2833
|
+
return this.detached;
|
|
2834
|
+
}
|
|
2835
|
+
async releaseForTransfer(options = {}) {
|
|
2836
|
+
if (options.signal?.throwIfAborted(), this.detached)
|
|
2837
|
+
return;
|
|
2838
|
+
if (this.transferring)
|
|
2839
|
+
throw new SessionTransferError("Session transfer is already in progress.", "busy");
|
|
2840
|
+
this.transferring = !0, this.session.setTransferring(!0);
|
|
2841
|
+
let hasAttachedWork = () => getSubagentCancellation(this.session.sessionId)?.hasActiveRuns() || getSubagentCancellation(this.session.sessionFile ?? "")?.hasActiveRuns() || list().some((entry) => entry.status !== "exited" && (!entry.sessionId || entry.sessionId === this.session.sessionId)), busy = () => this.session.isStreaming || this.session.isCompacting || this.session.isBashRunning || this.session.isRetrying || this.session.pendingMessageCount > 0;
|
|
2842
|
+
try {
|
|
2843
|
+
if (hasAttachedWork())
|
|
2844
|
+
throw new SessionTransferError("Live children or processes cannot move between runtimes. Wait for them to finish or stop them and retry.", "busy");
|
|
2845
|
+
if (busy() && !options.stop)
|
|
2846
|
+
throw new SessionTransferError("Session is busy. Wait and retry, explicitly request stop, or cancel.", "busy");
|
|
2847
|
+
if (busy() && (this.session.abortCompaction(), this.session.abortBranchSummary(), this.session.abortBash(), this.session.clearQueue(), await this.session.abort()), busy() || hasAttachedWork())
|
|
2848
|
+
throw new SessionTransferError("Work has not stopped yet. Wait and retry.", "busy");
|
|
2849
|
+
options.signal?.throwIfAborted(), this.session.sessionManager.flush(), await this.teardownCurrent("resume");
|
|
2850
|
+
} finally {
|
|
2851
|
+
this.transferring = !1, this.detached || this.session.setTransferring(!1);
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
5606
2854
|
constructor(_session, _services, createRuntime, _diagnostics = [], _modelFallbackMessage, onRuntimeApplied) {
|
|
5607
2855
|
this._session = _session, this._services = _services, this.createRuntime = createRuntime, this._diagnostics = _diagnostics, this._modelFallbackMessage = _modelFallbackMessage, this.onRuntimeApplied = onRuntimeApplied;
|
|
5608
2856
|
}
|
|
2857
|
+
async createOwnedRuntime(options) {
|
|
2858
|
+
try {
|
|
2859
|
+
return await this.createRuntime(options);
|
|
2860
|
+
} catch (error) {
|
|
2861
|
+
throw options.sessionManager.dispose(), error;
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
5609
2864
|
get services() {
|
|
5610
2865
|
return this._services;
|
|
5611
2866
|
}
|
|
@@ -5652,24 +2907,38 @@ var AgentSessionRuntime = class {
|
|
|
5652
2907
|
}))?.cancel === !0 } : { cancelled: !1 };
|
|
5653
2908
|
}
|
|
5654
2909
|
async teardownCurrent(reason, targetSessionFile) {
|
|
5655
|
-
await emitSessionShutdownEvent(this.session.extensionRunner, {
|
|
2910
|
+
this.detached || (await emitSessionShutdownEvent(this.session.extensionRunner, {
|
|
5656
2911
|
type: "session_shutdown",
|
|
5657
2912
|
reason,
|
|
5658
2913
|
targetSessionFile
|
|
5659
|
-
}), this.beforeSessionInvalidate?.(reason), this.session.dispose();
|
|
2914
|
+
}), this.beforeSessionInvalidate?.(reason), this.session.dispose(), this.detached = !0);
|
|
2915
|
+
}
|
|
2916
|
+
async teardownForReplacement(reason, sessionManager) {
|
|
2917
|
+
try {
|
|
2918
|
+
await this.teardownCurrent(reason, sessionManager.getSessionFile());
|
|
2919
|
+
} catch (error) {
|
|
2920
|
+
throw sessionManager.dispose(), error;
|
|
2921
|
+
}
|
|
5660
2922
|
}
|
|
5661
2923
|
apply(result) {
|
|
5662
|
-
this._session = result.session, this._services = result.services, this._diagnostics = result.diagnostics, this._modelFallbackMessage = result.modelFallbackMessage, this.onRuntimeApplied?.(result);
|
|
2924
|
+
this.detached = !1, this._session = result.session, this._services = result.services, this._diagnostics = result.diagnostics, this._modelFallbackMessage = result.modelFallbackMessage, this.onRuntimeApplied?.(result);
|
|
5663
2925
|
}
|
|
5664
2926
|
async finishSessionReplacement(withSession) {
|
|
5665
2927
|
this.rebindSession && await this.rebindSession(this.session), withSession && await withSession(this.session.createReplacedSessionContext());
|
|
5666
2928
|
}
|
|
5667
2929
|
async switchSession(sessionPath, options) {
|
|
5668
|
-
|
|
2930
|
+
if (!this.detached && this.session.sessionFile && canonicalSessionPath(sessionPath) === canonicalSessionPath(this.session.sessionFile))
|
|
2931
|
+
return { cancelled: !1 };
|
|
2932
|
+
let beforeResult = this.detached ? { cancelled: !1 } : await this.emitBeforeSwitch("resume", sessionPath);
|
|
5669
2933
|
if (beforeResult.cancelled)
|
|
5670
2934
|
return beforeResult;
|
|
5671
2935
|
let previousSessionFile = this.session.sessionFile, sessionManager = SessionManager.open(sessionPath, void 0, options?.cwdOverride);
|
|
5672
|
-
|
|
2936
|
+
try {
|
|
2937
|
+
assertSessionCwdExists(sessionManager, this.cwd);
|
|
2938
|
+
} catch (error) {
|
|
2939
|
+
throw sessionManager.dispose(), error;
|
|
2940
|
+
}
|
|
2941
|
+
return await this.teardownForReplacement("resume", sessionManager), this.apply(await this.createOwnedRuntime({
|
|
5673
2942
|
cwd: sessionManager.getCwd(),
|
|
5674
2943
|
agentDir: this.services.agentDir,
|
|
5675
2944
|
sessionManager,
|
|
@@ -5682,7 +2951,7 @@ var AgentSessionRuntime = class {
|
|
|
5682
2951
|
if (beforeResult.cancelled)
|
|
5683
2952
|
return beforeResult;
|
|
5684
2953
|
let previousSessionFile = this.session.sessionFile, sessionDir = this.session.sessionManager.getSessionDir(), sessionManager = this.session.sessionManager.isPersisted() ? SessionManager.create(this.cwd, sessionDir) : SessionManager.inMemory(this.cwd);
|
|
5685
|
-
return options?.parentSession && sessionManager.newSession({ parentSession: options.parentSession }), await this.
|
|
2954
|
+
return options?.parentSession && sessionManager.newSession({ parentSession: options.parentSession }), await this.teardownForReplacement("new", sessionManager), this.apply(await this.createOwnedRuntime({
|
|
5686
2955
|
cwd: this.cwd,
|
|
5687
2956
|
agentDir: this.services.agentDir,
|
|
5688
2957
|
sessionManager,
|
|
@@ -5711,27 +2980,27 @@ var AgentSessionRuntime = class {
|
|
|
5711
2980
|
let sessionDir = this.session.sessionManager.getSessionDir();
|
|
5712
2981
|
if (!targetLeafId) {
|
|
5713
2982
|
let sessionManager3 = SessionManager.create(this.cwd, sessionDir);
|
|
5714
|
-
return sessionManager3.newSession({ parentSession: currentSessionFile }), await this.
|
|
2983
|
+
return sessionManager3.newSession({ parentSession: currentSessionFile }), await this.teardownForReplacement("fork", sessionManager3), this.apply(await this.createOwnedRuntime({
|
|
5715
2984
|
cwd: this.cwd,
|
|
5716
2985
|
agentDir: this.services.agentDir,
|
|
5717
2986
|
sessionManager: sessionManager3,
|
|
5718
2987
|
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile }
|
|
5719
2988
|
})), await this.finishSessionReplacement(options?.withSession), { cancelled: !1, selectedText };
|
|
5720
2989
|
}
|
|
5721
|
-
if (!
|
|
2990
|
+
if (!existsSync4(currentSessionFile))
|
|
5722
2991
|
throw new Error("This session has not been saved yet. Wait for the first assistant response before cloning or forking it.");
|
|
5723
|
-
let sessionManager2 = SessionManager.
|
|
5724
|
-
if (!sessionManager2.
|
|
2992
|
+
let sessionManager2 = SessionManager.forkBranch(currentSessionFile, targetLeafId, sessionDir);
|
|
2993
|
+
if (!sessionManager2.getSessionFile())
|
|
5725
2994
|
throw new Error("Failed to create forked session");
|
|
5726
|
-
return await this.
|
|
2995
|
+
return await this.teardownForReplacement("fork", sessionManager2), this.apply(await this.createOwnedRuntime({
|
|
5727
2996
|
cwd: sessionManager2.getCwd(),
|
|
5728
2997
|
agentDir: this.services.agentDir,
|
|
5729
2998
|
sessionManager: sessionManager2,
|
|
5730
2999
|
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile }
|
|
5731
3000
|
})), await this.finishSessionReplacement(options?.withSession), { cancelled: !1, selectedText };
|
|
5732
3001
|
}
|
|
5733
|
-
let sessionManager = this.session.sessionManager;
|
|
5734
|
-
return targetLeafId ? sessionManager.createBranchedSession(targetLeafId) : sessionManager.newSession({ parentSession: this.session.sessionFile }), await this.
|
|
3002
|
+
let sessionManager = this.session.sessionManager.copyInMemory();
|
|
3003
|
+
return targetLeafId ? sessionManager.createBranchedSession(targetLeafId) : sessionManager.newSession({ parentSession: this.session.sessionFile }), await this.teardownForReplacement("fork", sessionManager), this.apply(await this.createOwnedRuntime({
|
|
5735
3004
|
cwd: this.cwd,
|
|
5736
3005
|
agentDir: this.services.agentDir,
|
|
5737
3006
|
sessionManager,
|
|
@@ -5747,17 +3016,29 @@ var AgentSessionRuntime = class {
|
|
|
5747
3016
|
*/
|
|
5748
3017
|
async importFromJsonl(inputPath, cwdOverride) {
|
|
5749
3018
|
let resolvedPath = resolvePath(inputPath);
|
|
5750
|
-
if (!
|
|
3019
|
+
if (!existsSync4(resolvedPath))
|
|
5751
3020
|
throw new SessionImportFileNotFoundError(resolvedPath);
|
|
5752
3021
|
let sessionDir = this.session.sessionManager.getSessionDir();
|
|
5753
|
-
|
|
5754
|
-
let destinationPath =
|
|
3022
|
+
existsSync4(sessionDir) || mkdirSync3(sessionDir, { recursive: !0 });
|
|
3023
|
+
let destinationPath = join5(sessionDir, basename2(resolvedPath)), beforeResult = await this.emitBeforeSwitch("resume", destinationPath);
|
|
5755
3024
|
if (beforeResult.cancelled)
|
|
5756
3025
|
return beforeResult;
|
|
5757
3026
|
let previousSessionFile = this.session.sessionFile;
|
|
5758
|
-
|
|
3027
|
+
if (canonicalSessionPath(destinationPath) !== canonicalSessionPath(resolvedPath)) {
|
|
3028
|
+
let ownership = new SessionOwnership(destinationPath);
|
|
3029
|
+
try {
|
|
3030
|
+
copyFileSync(resolvedPath, destinationPath);
|
|
3031
|
+
} finally {
|
|
3032
|
+
ownership.release();
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
5759
3035
|
let sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);
|
|
5760
|
-
|
|
3036
|
+
try {
|
|
3037
|
+
assertSessionCwdExists(sessionManager, this.cwd);
|
|
3038
|
+
} catch (error) {
|
|
3039
|
+
throw sessionManager.dispose(), error;
|
|
3040
|
+
}
|
|
3041
|
+
return await this.teardownForReplacement("resume", sessionManager), this.apply(await this.createOwnedRuntime({
|
|
5761
3042
|
cwd: sessionManager.getCwd(),
|
|
5762
3043
|
agentDir: this.services.agentDir,
|
|
5763
3044
|
sessionManager,
|
|
@@ -5765,15 +3046,17 @@ var AgentSessionRuntime = class {
|
|
|
5765
3046
|
})), await this.finishSessionReplacement(), { cancelled: !1 };
|
|
5766
3047
|
}
|
|
5767
3048
|
async dispose() {
|
|
5768
|
-
await
|
|
5769
|
-
type: "session_shutdown",
|
|
5770
|
-
reason: "quit"
|
|
5771
|
-
}), this.beforeSessionInvalidate?.("quit"), this.session.dispose();
|
|
3049
|
+
await this.teardownCurrent("quit");
|
|
5772
3050
|
}
|
|
5773
3051
|
};
|
|
5774
3052
|
async function createAgentSessionRuntime(createRuntime, options) {
|
|
5775
|
-
|
|
5776
|
-
|
|
3053
|
+
let result;
|
|
3054
|
+
try {
|
|
3055
|
+
assertSessionCwdExists(options.sessionManager, options.cwd), result = await createRuntime(options);
|
|
3056
|
+
} catch (error) {
|
|
3057
|
+
throw options.sessionManager.dispose(), error;
|
|
3058
|
+
}
|
|
3059
|
+
let runtime = new AgentSessionRuntime(result.session, result.services, createRuntime, result.diagnostics, result.modelFallbackMessage, options.onRuntimeApplied);
|
|
5777
3060
|
return options.onRuntimeApplied?.(result), runtime;
|
|
5778
3061
|
}
|
|
5779
3062
|
|
|
@@ -5782,7 +3065,15 @@ function getDefaultAgentDir() {
|
|
|
5782
3065
|
return getAgentDir();
|
|
5783
3066
|
}
|
|
5784
3067
|
async function createAgentSession(options = {}) {
|
|
5785
|
-
let cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd()), agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir(),
|
|
3068
|
+
let cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd()), agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir(), sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));
|
|
3069
|
+
try {
|
|
3070
|
+
return sessionManager.assertWritable(), await createOwnedAgentSession({ ...options, sessionManager });
|
|
3071
|
+
} catch (error) {
|
|
3072
|
+
throw sessionManager.dispose(), error;
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
async function createOwnedAgentSession(options) {
|
|
3076
|
+
let cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd()), agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir(), resourceLoader = options.resourceLoader, authPath = options.agentDir ? join6(agentDir, "auth.json") : void 0, modelsPath = options.agentDir ? join6(agentDir, "models.json") : void 0, modelRuntime = options.modelRuntime ?? await ModelRuntime.create({ authPath, modelsPath }), settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir), sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));
|
|
5786
3077
|
resourceLoader || (resourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager }), await resourceLoader.reload(), time("resourceLoader.reload"));
|
|
5787
3078
|
let existingSession = sessionManager.buildSessionContext(), hasExistingSession = existingSession.messages.length > 0, hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === "thinking_level_change"), model = options.model, modelFallbackMessage;
|
|
5788
3079
|
if (!model && hasExistingSession && existingSession.model) {
|
|
@@ -5921,8 +3212,8 @@ function applyExtensionFlagValues(resourceLoader, extensionFlagValues) {
|
|
|
5921
3212
|
}
|
|
5922
3213
|
async function createAgentSessionServices(options) {
|
|
5923
3214
|
let cwd = resolvePath(options.cwd), agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir(), modelRuntime = options.modelRuntime ?? await ModelRuntime.create({
|
|
5924
|
-
authPath:
|
|
5925
|
-
modelsPath:
|
|
3215
|
+
authPath: join7(agentDir, "auth.json"),
|
|
3216
|
+
modelsPath: join7(agentDir, "models.json")
|
|
5926
3217
|
});
|
|
5927
3218
|
time("ModelRuntime.create");
|
|
5928
3219
|
let settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir), resourceLoader = new DefaultResourceLoader({
|
|
@@ -5972,13 +3263,6 @@ async function createAgentSessionFromServices(options) {
|
|
|
5972
3263
|
}
|
|
5973
3264
|
|
|
5974
3265
|
export {
|
|
5975
|
-
AuthStorage,
|
|
5976
|
-
readStoredCredential,
|
|
5977
|
-
formatCatalogRefreshSummary,
|
|
5978
|
-
hasGrokCliXaiAuth,
|
|
5979
|
-
stripJsonComments,
|
|
5980
|
-
ModelRuntime,
|
|
5981
|
-
refreshModelCandidatesForInit,
|
|
5982
3266
|
formatNoModelsAvailableMessage,
|
|
5983
3267
|
wrapRegisteredTool,
|
|
5984
3268
|
wrapRegisteredTools,
|