@bubblebrain-ai/bubble 0.0.52 → 0.0.54
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/README.md +4 -12
- package/dist/agent/routing-catalog.js +3 -2
- package/dist/agent/subagent/router.js +5 -0
- package/dist/agent/subagent/runtime.d.ts +1 -0
- package/dist/agent/subagent/runtime.js +13 -1
- package/dist/agent/subagent-control.d.ts +4 -0
- package/dist/agent/subagent-control.js +1 -0
- package/dist/agent/subagent-store.js +2 -0
- package/dist/agent/workflow/control.d.ts +2 -0
- package/dist/agent/workflow/runs.d.ts +1 -0
- package/dist/agent/workflow/runs.js +3 -0
- package/dist/agent.d.ts +11 -1
- package/dist/agent.js +158 -57
- package/dist/bin.js +2 -44
- package/dist/config.d.ts +14 -1
- package/dist/config.js +45 -4
- package/dist/context/budget.d.ts +7 -1
- package/dist/context/budget.js +25 -2
- package/dist/context/compact-llm.d.ts +1 -1
- package/dist/context/compact-llm.js +5 -2
- package/dist/context/overflow.js +2 -0
- package/dist/context/projector.d.ts +8 -0
- package/dist/context/projector.js +55 -6
- package/dist/context/tool-output-truncate.d.ts +17 -1
- package/dist/context/tool-output-truncate.js +171 -49
- package/dist/feishu/agent-host/run-driver.js +3 -0
- package/dist/feishu/serve.js +2 -0
- package/dist/goal/command.d.ts +1 -1
- package/dist/goal/command.js +7 -2
- package/dist/main.d.ts +1 -1
- package/dist/main.js +38 -8
- package/dist/memory/db.js +0 -7
- package/dist/model-catalog.js +25 -6
- package/dist/model-config.js +3 -2
- package/dist/model-pricing.d.ts +24 -5
- package/dist/model-pricing.js +0 -0
- package/dist/model-selection.js +13 -4
- package/dist/network/chatgpt-transport.js +0 -34
- package/dist/network/errors.d.ts +19 -0
- package/dist/network/errors.js +24 -0
- package/dist/network/provider-transport.d.ts +0 -4
- package/dist/network/provider-transport.js +3 -35
- package/dist/network/retry.d.ts +6 -1
- package/dist/network/retry.js +9 -0
- package/dist/provider-model-policy.d.ts +16 -0
- package/dist/provider-model-policy.js +33 -0
- package/dist/provider-registry.d.ts +1 -1
- package/dist/provider-registry.js +73 -10
- package/dist/provider-transform.js +32 -4
- package/dist/provider.d.ts +6 -2
- package/dist/provider.js +95 -6
- package/dist/question/controller.js +5 -4
- package/dist/question/normalize.d.ts +6 -0
- package/dist/question/normalize.js +11 -0
- package/dist/rewind.d.ts +20 -0
- package/dist/rewind.js +29 -0
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +11 -3
- package/dist/session.d.ts +7 -0
- package/dist/session.js +20 -0
- package/dist/skills/discovery.js +18 -0
- package/dist/skills/registry.d.ts +12 -2
- package/dist/skills/registry.js +40 -5
- package/dist/skills/types.d.ts +2 -0
- package/dist/slash-commands/commands.js +120 -81
- package/dist/slash-commands/registry.d.ts +2 -1
- package/dist/slash-commands/registry.js +3 -0
- package/dist/slash-commands/types.d.ts +22 -4
- package/dist/stats/usage.d.ts +3 -1
- package/dist/stats/usage.js +22 -13
- package/dist/tasks/manager.d.ts +4 -2
- package/dist/tasks/manager.js +34 -9
- package/dist/tasks/promotion.d.ts +2 -2
- package/dist/tasks/promotion.js +2 -2
- package/dist/tools/agent-lifecycle.js +4 -0
- package/dist/tools/bash.d.ts +3 -1
- package/dist/tools/bash.js +13 -2
- package/dist/tools/grep.d.ts +5 -1
- package/dist/tools/grep.js +318 -69
- package/dist/tools/index.d.ts +3 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/question.js +5 -4
- package/dist/tools/read.js +40 -21
- package/dist/tui/animation-clock.d.ts +14 -0
- package/dist/tui/animation-clock.js +34 -0
- package/dist/tui/app.d.ts +176 -0
- package/dist/tui/app.js +1647 -0
- package/dist/tui/components/approval-dialog.d.ts +43 -0
- package/dist/tui/components/approval-dialog.js +247 -0
- package/dist/tui/components/bottom-sheet.d.ts +9 -0
- package/dist/tui/components/bottom-sheet.js +32 -0
- package/dist/tui/components/context-info.d.ts +54 -0
- package/dist/tui/components/context-info.js +388 -0
- package/dist/tui/components/feedback-dialog.d.ts +56 -0
- package/dist/tui/components/feedback-dialog.js +262 -0
- package/dist/tui/components/feishu-setup-dialog.d.ts +65 -0
- package/dist/tui/components/feishu-setup-dialog.js +332 -0
- package/dist/tui/components/image-preview.d.ts +32 -0
- package/dist/tui/components/image-preview.js +130 -0
- package/dist/tui/components/plan-dialog.d.ts +34 -0
- package/dist/tui/components/plan-dialog.js +196 -0
- package/dist/tui/components/provider-key-input.d.ts +18 -0
- package/dist/tui/components/provider-key-input.js +49 -0
- package/dist/tui/components/question-dialog.d.ts +25 -0
- package/dist/tui/components/question-dialog.js +263 -0
- package/dist/tui/components/responsive-transcript.d.ts +31 -0
- package/dist/tui/components/responsive-transcript.js +77 -0
- package/dist/tui/components/rewind-picker.d.ts +62 -0
- package/dist/tui/components/rewind-picker.js +317 -0
- package/dist/tui/components/session-picker.d.ts +49 -0
- package/dist/tui/components/session-picker.js +303 -0
- package/dist/tui/components/skills-panel.d.ts +59 -0
- package/dist/tui/components/skills-panel.js +568 -0
- package/dist/tui/components/stats-panel.d.ts +40 -0
- package/dist/tui/components/stats-panel.js +301 -0
- package/dist/tui/components/streaming-message.d.ts +69 -0
- package/dist/tui/components/streaming-message.js +393 -0
- package/dist/tui/components/subagent-inspector.d.ts +28 -0
- package/dist/tui/components/subagent-inspector.js +127 -0
- package/dist/tui/components/task-inspector.d.ts +26 -0
- package/dist/tui/components/task-inspector.js +70 -0
- package/dist/tui/components/tasks-pane.d.ts +88 -0
- package/dist/tui/components/tasks-pane.js +416 -0
- package/dist/tui/components/transcript.d.ts +96 -0
- package/dist/tui/components/transcript.js +771 -0
- package/dist/tui/components/welcome.d.ts +20 -0
- package/dist/tui/components/welcome.js +133 -0
- package/dist/tui/components/workflow-inspector.d.ts +30 -0
- package/dist/tui/components/workflow-inspector.js +136 -0
- package/dist/tui/composer-autocomplete.d.ts +61 -0
- package/dist/tui/composer-autocomplete.js +383 -0
- package/dist/tui/composer-style.d.ts +7 -0
- package/dist/tui/composer-style.js +29 -0
- package/dist/tui/controller/agent-event-reducer.d.ts +75 -0
- package/dist/tui/controller/agent-event-reducer.js +238 -0
- package/dist/tui/controller/composer-controller.d.ts +95 -0
- package/dist/tui/controller/composer-controller.js +502 -0
- package/dist/tui/controller/controller.d.ts +194 -0
- package/dist/tui/controller/controller.js +1035 -0
- package/dist/tui/controller/effects.d.ts +71 -0
- package/dist/tui/controller/effects.js +1 -0
- package/dist/tui/controller/goal-runtime-controller.d.ts +47 -0
- package/dist/tui/controller/goal-runtime-controller.js +202 -0
- package/dist/tui/controller/input-queue-machine.d.ts +71 -0
- package/dist/tui/controller/input-queue-machine.js +121 -0
- package/dist/tui/controller/intents.d.ts +56 -0
- package/dist/tui/controller/intents.js +6 -0
- package/dist/tui/controller/overlay-controller.d.ts +64 -0
- package/dist/tui/controller/overlay-controller.js +129 -0
- package/dist/tui/controller/ports.d.ts +57 -0
- package/dist/tui/controller/ports.js +9 -0
- package/dist/tui/controller/session-transition.d.ts +54 -0
- package/dist/tui/controller/session-transition.js +68 -0
- package/dist/tui/controller/state.d.ts +14 -0
- package/dist/tui/controller/state.js +36 -0
- package/dist/tui/controller/task-runtime-controller.d.ts +66 -0
- package/dist/tui/controller/task-runtime-controller.js +158 -0
- package/dist/tui/footer.d.ts +37 -0
- package/dist/tui/footer.js +80 -0
- package/dist/{tui-ink → tui/formatting}/edit-diff.d.ts +1 -1
- package/dist/{tui-ink → tui/formatting}/edit-diff.js +1 -1
- package/dist/{tui-ink/app-helpers.d.ts → tui/formatting/summary.d.ts} +4 -4
- package/dist/{tui-ink/app-helpers.js → tui/formatting/summary.js} +2 -2
- package/dist/tui/fullscreen.d.ts +48 -0
- package/dist/tui/fullscreen.js +255 -0
- package/dist/tui/image-display.d.ts +4 -0
- package/dist/tui/image-display.js +30 -12
- package/dist/tui/markdown-style.d.ts +5 -0
- package/dist/tui/markdown-style.js +23 -0
- package/dist/{tui-ink → tui/model}/composer-buffer.js +1 -1
- package/dist/tui/model/composer-types.d.ts +17 -0
- package/dist/tui/model/composer-types.js +1 -0
- package/dist/{tui-ink → tui/model}/display-history.d.ts +7 -1
- package/dist/{tui-ink → tui/model}/display-reconstruct.d.ts +1 -1
- package/dist/{tui-ink → tui/model}/display-reconstruct.js +54 -6
- package/dist/{tui-ink → tui/model}/file-mentions.d.ts +2 -0
- package/dist/{tui-ink → tui/model}/file-mentions.js +4 -0
- package/dist/tui/model/image-attachment.d.ts +15 -0
- package/dist/tui/model/image-attachment.js +1 -0
- package/dist/{tui-ink → tui/model}/image-paste.d.ts +7 -1
- package/dist/{tui-ink → tui/model}/image-paste.js +46 -0
- package/dist/tui/model/input-history.d.ts +1 -0
- package/dist/tui/model/input-history.js +1 -0
- package/dist/{tui-ink → tui/model}/input-queue.d.ts +1 -1
- package/dist/{tui-ink → tui/model}/recent-activity.js +1 -1
- package/dist/{tui-ink → tui/model}/subagent-view.d.ts +17 -2
- package/dist/{tui-ink → tui/model}/subagent-view.js +125 -4
- package/dist/{tui-ink → tui/model}/submit-dedupe.d.ts +1 -1
- package/dist/tui/model/theme-style.d.ts +10 -0
- package/dist/tui/model/theme-style.js +79 -0
- package/dist/{tui-ink → tui/model}/theme.d.ts +11 -23
- package/dist/{tui-ink → tui/model}/theme.js +23 -38
- package/dist/{tui-ink → tui/model}/trace-groups.d.ts +2 -0
- package/dist/{tui-ink → tui/model}/trace-groups.js +91 -30
- package/dist/tui/model/trace-interaction.d.ts +63 -0
- package/dist/tui/model/trace-interaction.js +87 -0
- package/dist/tui/model-picker-data.d.ts +1 -2
- package/dist/tui/model-picker-data.js +8 -1
- package/dist/tui/model-switch.js +2 -0
- package/dist/{tui-ink → tui}/run-session-picker.d.ts +2 -3
- package/dist/tui/run-session-picker.js +64 -0
- package/dist/tui/run.d.ts +72 -0
- package/dist/tui/run.js +139 -0
- package/dist/tui/terminal/multiplexer.d.ts +5 -0
- package/dist/tui/terminal/multiplexer.js +14 -0
- package/dist/tui/testing/fake-agent.d.ts +24 -0
- package/dist/tui/testing/fake-agent.js +22 -0
- package/dist/tui/testing/spy-host.d.ts +21 -0
- package/dist/tui/testing/spy-host.js +55 -0
- package/dist/tui/trace-groups.js +27 -6
- package/dist/types.d.ts +7 -0
- package/dist/update/index.d.ts +1 -0
- package/dist/update/index.js +22 -17
- package/node_modules/@bubblebrain-ai/pi-tui/LICENSE +21 -0
- package/node_modules/@bubblebrain-ai/pi-tui/README.md +854 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts +26 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js +121 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/alt-screen-search.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts +86 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js +649 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/autocomplete.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts +13 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js +36 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/alt-screen-flash.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js +99 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/box.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js +36 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/cancellable-loader.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts +330 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js +2344 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/editor.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts +7 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js +43 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/h-stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts +28 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js +82 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/image.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts +48 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js +390 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/input.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts +31 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js +67 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/loader.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts +103 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js +797 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/markdown.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts +56 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js +179 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/scroll-view.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts +53 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js +175 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/select-list.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts +50 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js +174 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/settings-list.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts +12 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/spacer.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts +32 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js +109 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts +19 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js +81 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/text.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts +13 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js +48 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/truncated-text.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts +8 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js +26 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/components/v-stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts +39 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js +2 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/editor-component.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts +16 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js +110 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/fuzzy.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts +31 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js +42 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/index.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts +273 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js +231 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keybindings.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts +184 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js +1174 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/keys.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts +28 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js +46 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/kill-ring.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts +10 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js +1268 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/latex.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts +40 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js +6 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout-node.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts +42 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js +335 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/layout.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts +3 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js +60 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/native-modifiers.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts +56 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js +363 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/stdin-buffer.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts +10 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js +59 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-colors.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts +116 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js +518 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal-image.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts +142 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js +544 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/terminal.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts +11 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js +11 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/testing.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts +140 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js +1334 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-alt-screen.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts +39 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js +536 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui-main-screen.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts +338 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js +1016 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/tui.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts +17 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js +27 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/undo-stack.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts +96 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js +1193 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/utils.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts +25 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js +96 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/src/word-navigation.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts +73 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.d.ts.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js +188 -0
- package/node_modules/@bubblebrain-ai/pi-tui/dist/test/virtual-terminal.js.map +1 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/README.md +20 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/build.sh +62 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/darwin/src/darwin-modifiers.c +70 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/README.md +22 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/build.mjs +229 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
- package/node_modules/@bubblebrain-ai/pi-tui/native/win32/src/win32-console-mode.c +119 -0
- package/node_modules/@bubblebrain-ai/pi-tui/package.json +66 -0
- package/node_modules/get-east-asian-width/index.d.ts +60 -0
- package/node_modules/get-east-asian-width/index.js +30 -0
- package/node_modules/get-east-asian-width/license +9 -0
- package/node_modules/get-east-asian-width/lookup-data.js +21 -0
- package/node_modules/get-east-asian-width/lookup.js +138 -0
- package/node_modules/get-east-asian-width/package.json +71 -0
- package/node_modules/get-east-asian-width/readme.md +65 -0
- package/node_modules/get-east-asian-width/utilities.js +24 -0
- package/node_modules/marked/LICENSE +44 -0
- package/node_modules/marked/README.md +115 -0
- package/node_modules/marked/bin/main.js +284 -0
- package/node_modules/marked/bin/marked.js +16 -0
- package/node_modules/marked/lib/marked.d.ts +760 -0
- package/node_modules/marked/lib/marked.esm.js +77 -0
- package/node_modules/marked/lib/marked.esm.js.map +7 -0
- package/node_modules/marked/lib/marked.umd.js +79 -0
- package/node_modules/marked/lib/marked.umd.js.map +7 -0
- package/node_modules/marked/man/marked.1 +113 -0
- package/node_modules/marked/man/marked.1.md +93 -0
- package/node_modules/marked/package.json +103 -0
- package/package.json +25 -10
- package/dist/tui-ink/app.d.ts +0 -76
- package/dist/tui-ink/app.js +0 -2377
- package/dist/tui-ink/approval/approval-dialog.d.ts +0 -13
- package/dist/tui-ink/approval/approval-dialog.js +0 -184
- package/dist/tui-ink/approval/diff-view.d.ts +0 -7
- package/dist/tui-ink/approval/diff-view.js +0 -44
- package/dist/tui-ink/approval/select.d.ts +0 -35
- package/dist/tui-ink/approval/select.js +0 -98
- package/dist/tui-ink/code-highlight.d.ts +0 -8
- package/dist/tui-ink/code-highlight.js +0 -121
- package/dist/tui-ink/command-palette.d.ts +0 -32
- package/dist/tui-ink/command-palette.js +0 -158
- package/dist/tui-ink/compaction-progress.d.ts +0 -19
- package/dist/tui-ink/compaction-progress.js +0 -74
- package/dist/tui-ink/detect-theme.d.ts +0 -1
- package/dist/tui-ink/detect-theme.js +0 -1
- package/dist/tui-ink/feedback-dialog.d.ts +0 -19
- package/dist/tui-ink/feedback-dialog.js +0 -133
- package/dist/tui-ink/feishu-setup-picker.d.ts +0 -5
- package/dist/tui-ink/feishu-setup-picker.js +0 -271
- package/dist/tui-ink/footer.d.ts +0 -26
- package/dist/tui-ink/footer.js +0 -51
- package/dist/tui-ink/input-box.d.ts +0 -189
- package/dist/tui-ink/input-box.js +0 -1279
- package/dist/tui-ink/input-history.d.ts +0 -1
- package/dist/tui-ink/input-history.js +0 -1
- package/dist/tui-ink/markdown.d.ts +0 -103
- package/dist/tui-ink/markdown.js +0 -747
- package/dist/tui-ink/message-list.d.ts +0 -49
- package/dist/tui-ink/message-list.js +0 -841
- package/dist/tui-ink/model-picker.d.ts +0 -143
- package/dist/tui-ink/model-picker.js +0 -966
- package/dist/tui-ink/plan-confirm.d.ts +0 -7
- package/dist/tui-ink/plan-confirm.js +0 -115
- package/dist/tui-ink/question-dialog.d.ts +0 -8
- package/dist/tui-ink/question-dialog.js +0 -135
- package/dist/tui-ink/rewind-picker.d.ts +0 -8
- package/dist/tui-ink/rewind-picker.js +0 -102
- package/dist/tui-ink/run-session-picker.js +0 -22
- package/dist/tui-ink/run.d.ts +0 -62
- package/dist/tui-ink/run.js +0 -103
- package/dist/tui-ink/session-picker.d.ts +0 -10
- package/dist/tui-ink/session-picker.js +0 -113
- package/dist/tui-ink/stats-panel.d.ts +0 -11
- package/dist/tui-ink/stats-panel.js +0 -65
- package/dist/tui-ink/subagent-inspector.d.ts +0 -21
- package/dist/tui-ink/subagent-inspector.js +0 -205
- package/dist/tui-ink/use-terminal-size.d.ts +0 -4
- package/dist/tui-ink/use-terminal-size.js +0 -48
- package/dist/tui-ink/waiting-indicator.d.ts +0 -12
- package/dist/tui-ink/waiting-indicator.js +0 -129
- package/dist/tui-ink/welcome.d.ts +0 -25
- package/dist/tui-ink/welcome.js +0 -88
- package/dist/tui-ink/wordmark.d.ts +0 -8
- package/dist/tui-ink/wordmark.js +0 -103
- /package/dist/{tui-ink → tui/model}/composer-buffer.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/display-history.js +0 -0
- /package/dist/{tui-ink → tui/model}/input-queue.js +0 -0
- /package/dist/{tui-ink → tui/model}/key-events.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/key-events.js +0 -0
- /package/dist/{tui-ink → tui/model}/paste-operation-tracker.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/paste-operation-tracker.js +0 -0
- /package/dist/{tui-ink → tui/model}/recent-activity.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/submit-dedupe.js +0 -0
- /package/dist/{tui-ink → tui/model}/sync-output.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/sync-output.js +0 -0
- /package/dist/{tui-ink → tui/model}/terminal-env.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/terminal-env.js +0 -0
- /package/dist/{tui-ink → tui/model}/terminal-mouse.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/terminal-mouse.js +0 -0
- /package/dist/{tui-ink → tui/model}/width.d.ts +0 -0
- /package/dist/{tui-ink → tui/model}/width.js +0 -0
package/dist/model-catalog.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OPENROUTER_MODEL_ID } from "./provider-model-policy.js";
|
|
1
2
|
export const BUILTIN_PROVIDERS = [
|
|
2
3
|
{ id: "openrouter", name: "OpenRouter", baseURL: "https://openrouter.ai/api/v1" },
|
|
3
4
|
{ id: "openai", name: "OpenAI", baseURL: "https://api.openai.com/v1", supportsOAuth: true },
|
|
@@ -38,13 +39,16 @@ const GPT51_LEVELS = ["off", "low", "medium", "high"];
|
|
|
38
39
|
const GPT51_CODEX_MAX_LEVELS = ["off", "low", "medium", "high", "xhigh"];
|
|
39
40
|
const GPT51_CODEX_MINI_LEVELS = ["off", "medium", "high"];
|
|
40
41
|
const OPENAI_CHAT_LEVELS = ["off"];
|
|
42
|
+
// Ox Alpha declares mandatory reasoning with exactly low/high/max through
|
|
43
|
+
// OpenRouter's live model metadata. The endpoint rejects disabled reasoning.
|
|
44
|
+
const OPENROUTER_OX_REASONING_LEVELS = ["low", "high", "max"];
|
|
41
45
|
// Internal representation for APIs that expose thinking as enabled/disabled.
|
|
42
46
|
// UI code must render supported toggle models as on/off, not as "medium" effort.
|
|
43
47
|
const TOGGLE_THINKING_LEVELS = ["off", "medium"];
|
|
44
48
|
// GLM-5.2 accepts OpenAI-style `reasoning_effort`. We expose high and max plus
|
|
45
49
|
// "off", which disables thinking outright via `thinking: {type: "disabled"}`.
|
|
46
50
|
const GLM_5_2_LEVELS = ["high", "max", "off"];
|
|
47
|
-
// GLM-5.3
|
|
51
|
+
// The GLM-5.3 family normalizes efforts into exactly three real tiers. Its
|
|
48
52
|
// default is max, and disabling thinking maps to low rather than turning it off.
|
|
49
53
|
const GLM_5_3_LEVELS = ["low", "high", "max"];
|
|
50
54
|
// Kimi K2.7 Code variants only support thinking mode (disabling it errors), so
|
|
@@ -56,7 +60,9 @@ const KIMI_THINKING_ONLY_LEVELS = ["medium"];
|
|
|
56
60
|
// "disabled"); the 256k variant exposes effort only, so it has no "off".
|
|
57
61
|
const KIMI_K3_LEVELS = ["off", "low", "high", "max"];
|
|
58
62
|
const KIMI_K3_EFFORT_ONLY_LEVELS = ["low", "high", "max"];
|
|
59
|
-
|
|
63
|
+
// DeepSeek V4 defaults to thinking/high, but the OpenAI-compatible API also
|
|
64
|
+
// supports disabling thinking and selecting low/high/max effort explicitly.
|
|
65
|
+
const DEEPSEEK_V4_LEVELS = ["off", "low", "high", "max"];
|
|
60
66
|
// Bailian token plan grades, read off the endpoint's own 400 responses
|
|
61
67
|
// ("'reasoning_effort' must be one of: ..."), which differ per model. "none"
|
|
62
68
|
// maps to our "off". qwen3.6-flash / qwen3.7-* stop at xhigh; deepseek-v4-pro
|
|
@@ -84,6 +90,10 @@ const GEMINI_3_FLASH_LEVELS = ["minimal", "low", "medium", "high"];
|
|
|
84
90
|
const GEMINI_25_PRO_LEVELS = ["low", "medium", "high"];
|
|
85
91
|
const GEMINI_25_FLASH_LEVELS = ["off", "low", "medium", "high"];
|
|
86
92
|
export const BUILTIN_MODELS = [
|
|
93
|
+
// OpenRouter exposes a very large catalog, but Bubble intentionally offers
|
|
94
|
+
// only Ox Alpha. Discovery refreshes this entry's public metadata without
|
|
95
|
+
// expanding provider membership.
|
|
96
|
+
{ id: OPENROUTER_MODEL_ID, name: "Ox Alpha", providerId: "openrouter", tier: "strong", reasoningLevels: OPENROUTER_OX_REASONING_LEVELS, defaultReasoningLevel: "max", contextWindow: 1048576 },
|
|
87
97
|
{ id: "gpt-5.6-sol", name: "GPT-5.6-Sol", providerId: "openai-codex", tier: "balanced", reasoningLevels: GPT56_LEVELS, defaultReasoningLevel: "low", contextWindow: 372000, useResponsesLite: true, toolOutputTokenLimit: 10000 },
|
|
88
98
|
{ id: "gpt-5.6-terra", name: "GPT-5.6-Terra", providerId: "openai-codex", tier: "strong", reasoningLevels: GPT56_LEVELS, defaultReasoningLevel: "medium", contextWindow: 372000, useResponsesLite: true, toolOutputTokenLimit: 10000 },
|
|
89
99
|
{ id: "gpt-5.6-luna", name: "GPT-5.6-Luna", providerId: "openai-codex", tier: "strong", reasoningLevels: GPT56_LUNA_LEVELS, defaultReasoningLevel: "medium", contextWindow: 372000, useResponsesLite: true, toolOutputTokenLimit: 10000 },
|
|
@@ -108,8 +118,12 @@ export const BUILTIN_MODELS = [
|
|
|
108
118
|
{ id: "claude-opus-4-8", name: "Claude Opus 4.8", providerId: "anthropic", tier: "strong", reasoningLevels: ANTHROPIC_OPUS_EFFORT_LEVELS, defaultReasoningLevel: "high", contextWindow: 1000000 },
|
|
109
119
|
{ id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6", providerId: "anthropic", tier: "balanced", reasoningLevels: ANTHROPIC_SONNET_EFFORT_LEVELS, defaultReasoningLevel: "high", contextWindow: 1000000 },
|
|
110
120
|
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5", providerId: "anthropic", tier: "fast", reasoningLevels: ANTHROPIC_CHAT_LEVELS, contextWindow: 200000 },
|
|
111
|
-
{ id: "deepseek-v4-flash", name: "deepseek-v4-flash", providerId: "deepseek", tier: "fast", reasoningLevels: DEEPSEEK_V4_LEVELS, contextWindow: 1048576 },
|
|
112
|
-
|
|
121
|
+
{ id: "deepseek-v4-flash", name: "deepseek-v4-flash", providerId: "deepseek", tier: "fast", reasoningLevels: DEEPSEEK_V4_LEVELS, defaultReasoningLevel: "high", contextWindow: 1048576 },
|
|
122
|
+
// Experimental vision model stays explicit-only: it is text-capable, but
|
|
123
|
+
// automatic fast-tier routing must not silently switch ordinary subagents
|
|
124
|
+
// from the stable Flash model to an experimental multimodal endpoint.
|
|
125
|
+
{ id: "deepseek-v4-flash-vision-exp", name: "DeepSeek-V4-Flash-Vision-Exp", providerId: "deepseek", reasoningLevels: DEEPSEEK_V4_LEVELS, defaultReasoningLevel: "high", contextWindow: 1048576 },
|
|
126
|
+
{ id: "deepseek-v4-pro", name: "deepseek-v4-pro", providerId: "deepseek", tier: "strong", reasoningLevels: DEEPSEEK_V4_LEVELS, defaultReasoningLevel: "high", contextWindow: 1048576 },
|
|
113
127
|
// Offline/no-key fallback only: with an API key the registry replaces this
|
|
114
128
|
// list via fetchGeminiModels (GET /v1beta/models, newest five). Gemini 3
|
|
115
129
|
// exposes thinking_level (minimal/low/medium/high); 2.5 Pro cannot disable
|
|
@@ -123,8 +137,13 @@ export const BUILTIN_MODELS = [
|
|
|
123
137
|
{ id: "glm-5.1", name: "GLM-5.1", providerId: "zhipuai", tier: "balanced", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
|
|
124
138
|
{ id: "glm-4.7", name: "GLM-4.7", providerId: "zhipuai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
|
|
125
139
|
{ id: "glm-4.6", name: "GLM-4.6", providerId: "zhipuai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
|
|
126
|
-
//
|
|
127
|
-
//
|
|
140
|
+
// GLM-5.3-Flash is a native multimodal model with the same mandatory
|
|
141
|
+
// low/high/max thinking contract as GLM-5.3. It is fully available on the
|
|
142
|
+
// Coding Plan and GET /models (verified live 2026-08-26). Official docs list
|
|
143
|
+
// a 1M context window and position it as the fast/low-cost plan model.
|
|
144
|
+
{ id: "glm-5.3-flash", name: "GLM-5.3-Flash", providerId: "zhipuai-coding-plan", tier: "fast", reasoningLevels: GLM_5_3_LEVELS, defaultReasoningLevel: "max", contextWindow: 1000000 },
|
|
145
|
+
// Coding Plan exposed GLM-5.3 before GET /models listed it (verified live
|
|
146
|
+
// 2026-08-14). The standard API was still marked "coming soon" at that time.
|
|
128
147
|
{ id: "glm-5.3", name: "GLM-5.3", providerId: "zhipuai-coding-plan", tier: "strong", reasoningLevels: GLM_5_3_LEVELS, defaultReasoningLevel: "max", contextWindow: 1000000 },
|
|
129
148
|
{ id: "glm-5.2", name: "GLM-5.2", providerId: "zhipuai-coding-plan", tier: "strong", reasoningLevels: GLM_5_2_LEVELS, contextWindow: 1000000 },
|
|
130
149
|
{ id: "glm-5.1", name: "GLM-5.1", providerId: "zhipuai-coding-plan", tier: "balanced", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
|
package/dist/model-config.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { existsSync, readFileSync } from "node:fs";
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
|
+
import { filterProviderModels } from "./provider-model-policy.js";
|
|
10
11
|
const MODELS_PATH = join(homedir(), ".bubble", "models.json");
|
|
11
12
|
const MODEL_TIERS = ["fast", "balanced", "strong"];
|
|
12
13
|
function sanitizeTier(value) {
|
|
@@ -53,13 +54,13 @@ export class ModelConfig {
|
|
|
53
54
|
const cfg = this.data?.providers?.[providerId];
|
|
54
55
|
if (!cfg?.models)
|
|
55
56
|
return [];
|
|
56
|
-
return cfg.models.map((m) => ({
|
|
57
|
+
return filterProviderModels(providerId, cfg.models.map((m) => ({
|
|
57
58
|
id: m.id,
|
|
58
59
|
name: m.name || m.id,
|
|
59
60
|
providerId,
|
|
60
61
|
tier: sanitizeTier(m.tier),
|
|
61
62
|
routingPriority: sanitizeRoutingPriority(m.routingPriority),
|
|
62
|
-
}));
|
|
63
|
+
})));
|
|
63
64
|
}
|
|
64
65
|
getApiKey(providerId) {
|
|
65
66
|
return this.data?.providers?.[providerId]?.apiKey;
|
package/dist/model-pricing.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { TokenUsage, UsageCost } from "./types.js";
|
|
2
2
|
export type { UsageCost } from "./types.js";
|
|
3
3
|
export type PricingCurrency = UsageCost["currency"];
|
|
4
|
-
export interface
|
|
5
|
-
providerId: string;
|
|
6
|
-
modelId: string;
|
|
7
|
-
currency: PricingCurrency;
|
|
4
|
+
export interface ModelPricingRate {
|
|
8
5
|
inputCacheHitPerMillion: number;
|
|
9
6
|
inputCacheMissPerMillion: number;
|
|
10
7
|
/**
|
|
@@ -15,6 +12,28 @@ export interface ModelPricing {
|
|
|
15
12
|
*/
|
|
16
13
|
inputCacheWritePerMillion?: number;
|
|
17
14
|
outputPerMillion: number;
|
|
15
|
+
}
|
|
16
|
+
export interface UtcPricingWindow {
|
|
17
|
+
/** Inclusive minute since 00:00 UTC. */
|
|
18
|
+
startMinute: number;
|
|
19
|
+
/** Exclusive minute since 00:00 UTC. */
|
|
20
|
+
endMinute: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ModelPricing extends ModelPricingRate {
|
|
23
|
+
providerId: string;
|
|
24
|
+
modelId: string;
|
|
25
|
+
currency: PricingCurrency;
|
|
26
|
+
/**
|
|
27
|
+
* Optional recurring UTC time-of-use tariff. Top-level rates are the peak
|
|
28
|
+
* tariff; outside these windows, `offPeak` applies. DeepSeek introduced this
|
|
29
|
+
* pricing shape for the V4 family on 2026-08-16.
|
|
30
|
+
*/
|
|
31
|
+
peakWindowsUtc?: UtcPricingWindow[];
|
|
32
|
+
offPeak?: ModelPricingRate;
|
|
33
|
+
/** When the recurring tariff became effective. */
|
|
34
|
+
effectiveFrom?: string;
|
|
35
|
+
/** Rate used before `effectiveFrom` (for historical session statistics). */
|
|
36
|
+
prior?: ModelPricingRate;
|
|
18
37
|
effectiveUntil?: string;
|
|
19
38
|
original?: {
|
|
20
39
|
inputCacheHitPerMillion: number;
|
|
@@ -32,4 +51,4 @@ export interface ModelPricing {
|
|
|
32
51
|
export declare const MODEL_PRICING_OVERRIDES: ModelPricing[];
|
|
33
52
|
export declare const MODEL_PRICING: ModelPricing[];
|
|
34
53
|
export declare function getModelPricing(providerId: string, modelId: string): ModelPricing | undefined;
|
|
35
|
-
export declare function calculateUsageCost(providerId: string, modelId: string, usage: TokenUsage): UsageCost | undefined;
|
|
54
|
+
export declare function calculateUsageCost(providerId: string, modelId: string, usage: TokenUsage, at?: Date): UsageCost | undefined;
|
package/dist/model-pricing.js
CHANGED
|
Binary file
|
package/dist/model-selection.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { encodeModel } from "./provider-registry.js";
|
|
1
|
+
import { decodeModel, encodeModel } from "./provider-registry.js";
|
|
2
|
+
import { assertProviderModelAllowed } from "./provider-model-policy.js";
|
|
2
3
|
export function resolveConfiguredModel(input) {
|
|
3
4
|
const selected = input.cliModel ?? input.sessionModel ?? input.defaultModel;
|
|
4
5
|
if (!selected)
|
|
5
6
|
return "";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const normalized = selected.includes(":")
|
|
8
|
+
? selected
|
|
9
|
+
: input.fallbackProviderId
|
|
10
|
+
? encodeModel(input.fallbackProviderId, selected)
|
|
11
|
+
: "";
|
|
12
|
+
if (!normalized)
|
|
13
|
+
return "";
|
|
14
|
+
const { providerId, modelId } = decodeModel(normalized);
|
|
15
|
+
if (providerId)
|
|
16
|
+
assertProviderModelAllowed(providerId, modelId);
|
|
17
|
+
return normalized;
|
|
9
18
|
}
|
|
@@ -32,8 +32,6 @@ export function createChatGptFetch(options = {}) {
|
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
34
|
export function createChatGptDispatcher(env = process.env, input) {
|
|
35
|
-
if (isBunRuntime())
|
|
36
|
-
return undefined;
|
|
37
35
|
const ca = loadExtraCaCertificates(env);
|
|
38
36
|
const proxy = input ? nodeProxyForUrl(input, env) : defaultNodeProxy(env);
|
|
39
37
|
if (!proxy && ca.length === 0)
|
|
@@ -49,15 +47,6 @@ export function createChatGptDispatcher(env = process.env, input) {
|
|
|
49
47
|
}
|
|
50
48
|
export function withChatGptNetworkOptions(input, init, env = process.env, dispatcher = createChatGptDispatcher(env, input)) {
|
|
51
49
|
const next = { ...(init ?? {}) };
|
|
52
|
-
if (isBunRuntime()) {
|
|
53
|
-
const proxy = bunProxyForUrl(input, env);
|
|
54
|
-
if (proxy)
|
|
55
|
-
next.proxy = proxy;
|
|
56
|
-
const ca = bunExtraCaFiles(env);
|
|
57
|
-
if (ca.length > 0)
|
|
58
|
-
next.tls = { ...(next.tls ?? {}), ca };
|
|
59
|
-
return next;
|
|
60
|
-
}
|
|
61
50
|
if (dispatcher)
|
|
62
51
|
next.dispatcher = dispatcher;
|
|
63
52
|
return next;
|
|
@@ -94,23 +83,6 @@ function hasProxyEnv(env) {
|
|
|
94
83
|
function chatGptProxyOverride(env) {
|
|
95
84
|
return env.BUBBLE_CHATGPT_PROXY ?? env.bubble_chatgpt_proxy;
|
|
96
85
|
}
|
|
97
|
-
function isBunRuntime() {
|
|
98
|
-
return typeof globalThis.Bun !== "undefined";
|
|
99
|
-
}
|
|
100
|
-
function bunProxyForUrl(input, env) {
|
|
101
|
-
const url = urlFromInput(input);
|
|
102
|
-
if (!url || shouldBypassProxy(url, env))
|
|
103
|
-
return undefined;
|
|
104
|
-
const override = chatGptProxyOverride(env);
|
|
105
|
-
if (override)
|
|
106
|
-
return override;
|
|
107
|
-
const allProxy = env.ALL_PROXY ?? env.all_proxy;
|
|
108
|
-
if (url.protocol === "https:")
|
|
109
|
-
return env.HTTPS_PROXY ?? env.https_proxy ?? allProxy ?? getSystemProxyForUrl(url, env);
|
|
110
|
-
if (url.protocol === "http:")
|
|
111
|
-
return env.HTTP_PROXY ?? env.http_proxy ?? allProxy ?? getSystemProxyForUrl(url, env);
|
|
112
|
-
return undefined;
|
|
113
|
-
}
|
|
114
86
|
function nodeProxyForUrl(input, env) {
|
|
115
87
|
const url = urlFromInput(input);
|
|
116
88
|
if (!url || shouldBypassProxy(url, env))
|
|
@@ -129,12 +101,6 @@ function defaultNodeProxy(env) {
|
|
|
129
101
|
?? env.HTTPS_PROXY ?? env.https_proxy ?? env.HTTP_PROXY ?? env.http_proxy ?? env.ALL_PROXY ?? env.all_proxy
|
|
130
102
|
?? getSystemProxyForUrl(new URL("https://system-proxy-default.invalid/"), env);
|
|
131
103
|
}
|
|
132
|
-
function bunExtraCaFiles(env) {
|
|
133
|
-
const bun = globalThis.Bun;
|
|
134
|
-
if (!bun?.file)
|
|
135
|
-
return [];
|
|
136
|
-
return extraCaCertificatePaths(env).map((path) => bun.file(path));
|
|
137
|
-
}
|
|
138
104
|
function urlFromInput(input) {
|
|
139
105
|
if (input instanceof URL)
|
|
140
106
|
return input;
|
package/dist/network/errors.d.ts
CHANGED
|
@@ -17,6 +17,25 @@ export declare class RateLimitError extends Error {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
export declare function isRateLimitError(error: unknown): error is RateLimitError;
|
|
20
|
+
/**
|
|
21
|
+
* A provider accepted the HTTP request but terminated generation with an
|
|
22
|
+
* in-band protocol error (for example OpenRouter's HTTP-200 SSE error chunk).
|
|
23
|
+
* Keeping the wire status/type structured prevents the agent from mistaking
|
|
24
|
+
* the terminal event for a successful empty response.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ProviderResponseError extends Error {
|
|
27
|
+
readonly isProviderResponseError = true;
|
|
28
|
+
readonly status?: number;
|
|
29
|
+
readonly errorType?: string;
|
|
30
|
+
readonly retryAfterMs?: number;
|
|
31
|
+
constructor(message: string, options?: {
|
|
32
|
+
status?: number;
|
|
33
|
+
errorType?: string;
|
|
34
|
+
retryAfterMs?: number;
|
|
35
|
+
cause?: unknown;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export declare function isProviderResponseError(error: unknown): error is ProviderResponseError;
|
|
20
39
|
/**
|
|
21
40
|
* How a provider transport should treat HTTP 429 responses.
|
|
22
41
|
*
|
package/dist/network/errors.js
CHANGED
|
@@ -22,3 +22,27 @@ export function isRateLimitError(error) {
|
|
|
22
22
|
&& typeof error === "object"
|
|
23
23
|
&& error.isRateLimitError === true;
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* A provider accepted the HTTP request but terminated generation with an
|
|
27
|
+
* in-band protocol error (for example OpenRouter's HTTP-200 SSE error chunk).
|
|
28
|
+
* Keeping the wire status/type structured prevents the agent from mistaking
|
|
29
|
+
* the terminal event for a successful empty response.
|
|
30
|
+
*/
|
|
31
|
+
export class ProviderResponseError extends Error {
|
|
32
|
+
isProviderResponseError = true;
|
|
33
|
+
status;
|
|
34
|
+
errorType;
|
|
35
|
+
retryAfterMs;
|
|
36
|
+
constructor(message, options = {}) {
|
|
37
|
+
super(message, options.cause !== undefined ? { cause: options.cause } : undefined);
|
|
38
|
+
this.name = "ProviderResponseError";
|
|
39
|
+
this.status = options.status;
|
|
40
|
+
this.errorType = options.errorType;
|
|
41
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function isProviderResponseError(error) {
|
|
45
|
+
return !!error
|
|
46
|
+
&& typeof error === "object"
|
|
47
|
+
&& error.isProviderResponseError === true;
|
|
48
|
+
}
|
|
@@ -8,10 +8,6 @@ export interface ProviderFetchOptions {
|
|
|
8
8
|
}
|
|
9
9
|
type RequestInitWithProviderOptions = RequestInit & {
|
|
10
10
|
dispatcher?: Dispatcher;
|
|
11
|
-
proxy?: string;
|
|
12
|
-
tls?: {
|
|
13
|
-
ca?: unknown[];
|
|
14
|
-
};
|
|
15
11
|
verbose?: boolean;
|
|
16
12
|
};
|
|
17
13
|
export declare function providerFetch(input: RequestInfo | URL, init: RequestInit | undefined, options: ProviderFetchOptions): Promise<Response>;
|
|
@@ -28,8 +28,6 @@ export function createProviderFetch(options) {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
export function createProviderDispatcher(env = process.env, input, providerName = "provider") {
|
|
31
|
-
if (isBunRuntime())
|
|
32
|
-
return undefined;
|
|
33
31
|
const ca = loadExtraCaCertificates(env, providerName);
|
|
34
32
|
const proxy = input ? nodeProxyForUrl(input, env) : defaultNodeProxy(env);
|
|
35
33
|
if (!proxy && ca.length === 0)
|
|
@@ -47,19 +45,9 @@ export function withProviderNetworkOptions(input, init, options = {}) {
|
|
|
47
45
|
const env = options.env ?? process.env;
|
|
48
46
|
const providerName = options.providerName ?? "provider";
|
|
49
47
|
const next = { ...(init ?? {}) };
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
next.proxy = proxy;
|
|
54
|
-
const ca = bunExtraCaFiles(env);
|
|
55
|
-
if (ca.length > 0)
|
|
56
|
-
next.tls = { ...(next.tls ?? {}), ca };
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const dispatcher = createProviderDispatcher(env, input, providerName);
|
|
60
|
-
if (dispatcher)
|
|
61
|
-
next.dispatcher = dispatcher;
|
|
62
|
-
}
|
|
48
|
+
const dispatcher = createProviderDispatcher(env, input, providerName);
|
|
49
|
+
if (dispatcher)
|
|
50
|
+
next.dispatcher = dispatcher;
|
|
63
51
|
if (shouldEnableFetchVerbose(env, options.verboseEnvVar)) {
|
|
64
52
|
next.verbose = true;
|
|
65
53
|
}
|
|
@@ -129,20 +117,6 @@ function hasProxyEnv(env) {
|
|
|
129
117
|
function hasCustomCaEnv(env) {
|
|
130
118
|
return Boolean(env.NODE_EXTRA_CA_CERTS?.trim() || env.BUBBLE_EXTRA_CA_CERTS?.trim());
|
|
131
119
|
}
|
|
132
|
-
function isBunRuntime() {
|
|
133
|
-
return typeof globalThis.Bun !== "undefined";
|
|
134
|
-
}
|
|
135
|
-
function bunProxyForUrl(input, env) {
|
|
136
|
-
const url = urlFromInput(input);
|
|
137
|
-
if (!url || shouldBypassProxy(url, env))
|
|
138
|
-
return undefined;
|
|
139
|
-
const allProxy = env.ALL_PROXY ?? env.all_proxy;
|
|
140
|
-
if (url.protocol === "https:")
|
|
141
|
-
return env.HTTPS_PROXY ?? env.https_proxy ?? allProxy ?? getSystemProxyForUrl(url, env);
|
|
142
|
-
if (url.protocol === "http:")
|
|
143
|
-
return env.HTTP_PROXY ?? env.http_proxy ?? allProxy ?? getSystemProxyForUrl(url, env);
|
|
144
|
-
return undefined;
|
|
145
|
-
}
|
|
146
120
|
function nodeProxyForUrl(input, env) {
|
|
147
121
|
const url = urlFromInput(input);
|
|
148
122
|
if (!url || shouldBypassProxy(url, env))
|
|
@@ -157,12 +131,6 @@ function defaultNodeProxy(env) {
|
|
|
157
131
|
return env.HTTPS_PROXY ?? env.https_proxy ?? env.HTTP_PROXY ?? env.http_proxy ?? env.ALL_PROXY ?? env.all_proxy
|
|
158
132
|
?? getSystemProxyForUrl(new URL("https://system-proxy-default.invalid/"), env);
|
|
159
133
|
}
|
|
160
|
-
function bunExtraCaFiles(env) {
|
|
161
|
-
const bun = globalThis.Bun;
|
|
162
|
-
if (!bun?.file)
|
|
163
|
-
return [];
|
|
164
|
-
return extraCaCertificatePaths(env).map((path) => bun.file(path));
|
|
165
|
-
}
|
|
166
134
|
function urlFromInput(input) {
|
|
167
135
|
if (input instanceof URL)
|
|
168
136
|
return input;
|
package/dist/network/retry.d.ts
CHANGED
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
export declare const MAX_STREAM_INTERRUPTION_RETRIES = 2;
|
|
11
11
|
export declare class ProviderStreamInterruptedError extends Error {
|
|
12
12
|
readonly isProviderStreamInterruption = true;
|
|
13
|
+
readonly retryAfterMs?: number;
|
|
14
|
+
readonly maxRetries?: number;
|
|
13
15
|
constructor(message: string, options?: {
|
|
14
16
|
cause?: unknown;
|
|
17
|
+
retryAfterMs?: number;
|
|
18
|
+
maxRetries?: number;
|
|
15
19
|
});
|
|
16
20
|
}
|
|
17
|
-
export declare function isProviderStreamInterruption(error: unknown):
|
|
21
|
+
export declare function isProviderStreamInterruption(error: unknown): error is ProviderStreamInterruptedError;
|
|
22
|
+
export declare function providerStreamRetryLimit(error: ProviderStreamInterruptedError): number;
|
|
18
23
|
export declare function getProviderMaxRetries(env?: NodeJS.ProcessEnv): number;
|
|
19
24
|
export declare function isRetryableHttpStatus(status: number): boolean;
|
|
20
25
|
/**
|
package/dist/network/retry.js
CHANGED
|
@@ -16,9 +16,13 @@ export const MAX_STREAM_INTERRUPTION_RETRIES = 2;
|
|
|
16
16
|
const RETRYABLE_HTTP_STATUSES = new Set([408, 429, 500, 502, 503, 504, 529]);
|
|
17
17
|
export class ProviderStreamInterruptedError extends Error {
|
|
18
18
|
isProviderStreamInterruption = true;
|
|
19
|
+
retryAfterMs;
|
|
20
|
+
maxRetries;
|
|
19
21
|
constructor(message, options) {
|
|
20
22
|
super(message, options);
|
|
21
23
|
this.name = "ProviderStreamInterruptedError";
|
|
24
|
+
this.retryAfterMs = options?.retryAfterMs;
|
|
25
|
+
this.maxRetries = options?.maxRetries;
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
28
|
export function isProviderStreamInterruption(error) {
|
|
@@ -26,6 +30,11 @@ export function isProviderStreamInterruption(error) {
|
|
|
26
30
|
&& typeof error === "object"
|
|
27
31
|
&& error.isProviderStreamInterruption === true;
|
|
28
32
|
}
|
|
33
|
+
export function providerStreamRetryLimit(error) {
|
|
34
|
+
if (error.maxRetries === undefined)
|
|
35
|
+
return MAX_STREAM_INTERRUPTION_RETRIES;
|
|
36
|
+
return Math.max(0, Math.min(MAX_CONFIGURABLE_RETRIES, Math.floor(error.maxRetries)));
|
|
37
|
+
}
|
|
29
38
|
export function getProviderMaxRetries(env = process.env) {
|
|
30
39
|
const raw = env.BUBBLE_PROVIDER_MAX_RETRIES?.trim();
|
|
31
40
|
if (!raw)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable provider-level model constraints.
|
|
3
|
+
*
|
|
4
|
+
* Catalog discovery describes what a provider currently lists; it is not a
|
|
5
|
+
* runtime security boundary. A fixed policy is different: Bubble deliberately
|
|
6
|
+
* exposes and permits exactly one model for that provider, across every host
|
|
7
|
+
* and caller (TUI, CLI, SDK, Feishu, parent agents, and subagents).
|
|
8
|
+
*/
|
|
9
|
+
export declare const OPENROUTER_MODEL_ID = "stealth/ox-alpha";
|
|
10
|
+
export declare function getFixedProviderModelId(providerId: string): string | undefined;
|
|
11
|
+
export declare function isProviderModelAllowed(providerId: string, modelId: string): boolean;
|
|
12
|
+
export declare function providerModelPolicyError(providerId: string, modelId: string): string | undefined;
|
|
13
|
+
export declare function assertProviderModelAllowed(providerId: string, modelId: string): void;
|
|
14
|
+
export declare function filterProviderModels<T extends {
|
|
15
|
+
id: string;
|
|
16
|
+
}>(providerId: string, models: readonly T[]): T[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable provider-level model constraints.
|
|
3
|
+
*
|
|
4
|
+
* Catalog discovery describes what a provider currently lists; it is not a
|
|
5
|
+
* runtime security boundary. A fixed policy is different: Bubble deliberately
|
|
6
|
+
* exposes and permits exactly one model for that provider, across every host
|
|
7
|
+
* and caller (TUI, CLI, SDK, Feishu, parent agents, and subagents).
|
|
8
|
+
*/
|
|
9
|
+
export const OPENROUTER_MODEL_ID = "stealth/ox-alpha";
|
|
10
|
+
const FIXED_PROVIDER_MODELS = {
|
|
11
|
+
openrouter: OPENROUTER_MODEL_ID,
|
|
12
|
+
};
|
|
13
|
+
export function getFixedProviderModelId(providerId) {
|
|
14
|
+
return FIXED_PROVIDER_MODELS[providerId.toLowerCase()];
|
|
15
|
+
}
|
|
16
|
+
export function isProviderModelAllowed(providerId, modelId) {
|
|
17
|
+
const fixedModelId = getFixedProviderModelId(providerId);
|
|
18
|
+
return !fixedModelId || modelId === fixedModelId;
|
|
19
|
+
}
|
|
20
|
+
export function providerModelPolicyError(providerId, modelId) {
|
|
21
|
+
const fixedModelId = getFixedProviderModelId(providerId);
|
|
22
|
+
if (!fixedModelId || modelId === fixedModelId)
|
|
23
|
+
return undefined;
|
|
24
|
+
return `Provider "${providerId}" is fixed to model "${fixedModelId}"; received "${modelId}".`;
|
|
25
|
+
}
|
|
26
|
+
export function assertProviderModelAllowed(providerId, modelId) {
|
|
27
|
+
const error = providerModelPolicyError(providerId, modelId);
|
|
28
|
+
if (error)
|
|
29
|
+
throw new Error(error);
|
|
30
|
+
}
|
|
31
|
+
export function filterProviderModels(providerId, models) {
|
|
32
|
+
return models.filter((model) => isProviderModelAllowed(providerId, model.id));
|
|
33
|
+
}
|
|
@@ -10,7 +10,7 @@ import { ModelConfig } from "./model-config.js";
|
|
|
10
10
|
import { AuthStorage } from "./oauth/index.js";
|
|
11
11
|
import { type OpenAICodexAuthAdapter } from "./provider-openai-codex.js";
|
|
12
12
|
import { type GrokAuthAdapter } from "./provider-grok.js";
|
|
13
|
-
import type
|
|
13
|
+
import { type ThinkingLevel } from "./types.js";
|
|
14
14
|
export interface ProviderProfile {
|
|
15
15
|
id: string;
|
|
16
16
|
name: string;
|
|
@@ -16,6 +16,8 @@ import { extractChatGptAccountId, fetchOpenAICodexModelCatalog } from "./provide
|
|
|
16
16
|
import { fetchGrokSubscriptionModels } from "./provider-grok.js";
|
|
17
17
|
import { refreshOpenAICodex } from "./oauth/openai-codex.js";
|
|
18
18
|
import { refreshGrok } from "./oauth/grok.js";
|
|
19
|
+
import { THINKING_LEVELS } from "./types.js";
|
|
20
|
+
import { filterProviderModels, OPENROUTER_MODEL_ID, } from "./provider-model-policy.js";
|
|
19
21
|
/** True for providers speaking the OpenAI chat-completions protocol (the default). */
|
|
20
22
|
export function isOpenAICompatibleProtocol(protocol) {
|
|
21
23
|
return protocol === undefined || protocol === "openai-chat";
|
|
@@ -67,9 +69,56 @@ const MODEL_DISCOVERY_FAILURE_TTL_MS = 10_000;
|
|
|
67
69
|
const MODEL_DISCOVERY_DISK_TTL_MS = 24 * 60 * 60 * 1000;
|
|
68
70
|
/** Discovery must never delay startup or a model picker for long. */
|
|
69
71
|
const MODEL_DISCOVERY_TIMEOUT_MS = 5_000;
|
|
72
|
+
// Included in the cache identity so a pre-single-model OpenRouter disk cache
|
|
73
|
+
// can never repopulate the picker with the old full remote catalog.
|
|
74
|
+
const OPENROUTER_CATALOG_SCOPE = "ox-alpha-only-v2";
|
|
75
|
+
const OPENROUTER_WIRE_EFFORTS = new Map([
|
|
76
|
+
["none", "off"],
|
|
77
|
+
["minimal", "minimal"],
|
|
78
|
+
["low", "low"],
|
|
79
|
+
["medium", "medium"],
|
|
80
|
+
["high", "high"],
|
|
81
|
+
["xhigh", "xhigh"],
|
|
82
|
+
["max", "max"],
|
|
83
|
+
]);
|
|
84
|
+
function openRouterReasoningMetadata(value, fallback) {
|
|
85
|
+
const fallbackMetadata = {
|
|
86
|
+
reasoningLevels: fallback.reasoningLevels,
|
|
87
|
+
defaultReasoningLevel: fallback.defaultReasoningLevel,
|
|
88
|
+
};
|
|
89
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
90
|
+
return fallbackMetadata;
|
|
91
|
+
const raw = value;
|
|
92
|
+
if (!Array.isArray(raw.supported_efforts))
|
|
93
|
+
return fallbackMetadata;
|
|
94
|
+
const declared = new Set();
|
|
95
|
+
for (const effort of raw.supported_efforts) {
|
|
96
|
+
if (typeof effort !== "string")
|
|
97
|
+
continue;
|
|
98
|
+
const mapped = OPENROUTER_WIRE_EFFORTS.get(effort);
|
|
99
|
+
if (mapped)
|
|
100
|
+
declared.add(mapped);
|
|
101
|
+
}
|
|
102
|
+
if (raw.mandatory === true)
|
|
103
|
+
declared.delete("off");
|
|
104
|
+
const reasoningLevels = THINKING_LEVELS.filter((level) => declared.has(level));
|
|
105
|
+
if (reasoningLevels.length === 0)
|
|
106
|
+
return fallbackMetadata;
|
|
107
|
+
const rawDefault = typeof raw.default_effort === "string"
|
|
108
|
+
? OPENROUTER_WIRE_EFFORTS.get(raw.default_effort)
|
|
109
|
+
: undefined;
|
|
110
|
+
const defaultReasoningLevel = rawDefault && reasoningLevels.includes(rawDefault)
|
|
111
|
+
? rawDefault
|
|
112
|
+
: fallback.defaultReasoningLevel && reasoningLevels.includes(fallback.defaultReasoningLevel)
|
|
113
|
+
? fallback.defaultReasoningLevel
|
|
114
|
+
: reasoningLevels.includes("medium")
|
|
115
|
+
? "medium"
|
|
116
|
+
: reasoningLevels[0];
|
|
117
|
+
return { reasoningLevels, defaultReasoningLevel };
|
|
118
|
+
}
|
|
70
119
|
export const BUILTIN_PROVIDERS = CATALOG_PROVIDERS;
|
|
71
120
|
export const USER_VISIBLE_PROVIDER_IDS = BUILTIN_PROVIDERS
|
|
72
|
-
.filter((provider) => !provider.hidden && provider.id !== "
|
|
121
|
+
.filter((provider) => !provider.hidden && provider.id !== "openai-codex")
|
|
73
122
|
.map((provider) => provider.id);
|
|
74
123
|
export function isUserVisibleProvider(providerId) {
|
|
75
124
|
return USER_VISIBLE_PROVIDER_IDS.includes(providerId);
|
|
@@ -289,7 +338,7 @@ export class ProviderRegistry {
|
|
|
289
338
|
};
|
|
290
339
|
}
|
|
291
340
|
getDefaultModel(providerId, authType = "api") {
|
|
292
|
-
const customModels = this.modelConfig.getCustomModels(providerId);
|
|
341
|
+
const customModels = filterProviderModels(providerId, this.modelConfig.getCustomModels(providerId));
|
|
293
342
|
if (customModels.length > 0) {
|
|
294
343
|
return customModels[0].id;
|
|
295
344
|
}
|
|
@@ -533,22 +582,34 @@ export class ProviderRegistry {
|
|
|
533
582
|
return pending;
|
|
534
583
|
}
|
|
535
584
|
async performModelDiscovery(provider) {
|
|
536
|
-
const customModels = this.modelConfig.getCustomModels(provider.id);
|
|
585
|
+
const customModels = filterProviderModels(provider.id, this.modelConfig.getCustomModels(provider.id));
|
|
537
586
|
if (customModels.length > 0) {
|
|
538
587
|
return { models: customModels, source: "static", authoritative: true };
|
|
539
588
|
}
|
|
540
589
|
if (provider.id === "openrouter") {
|
|
541
590
|
try {
|
|
542
|
-
const response = await fetch("https://openrouter.ai/api/v1/models"
|
|
591
|
+
const response = await fetch("https://openrouter.ai/api/v1/models", {
|
|
592
|
+
signal: AbortSignal.timeout(MODEL_DISCOVERY_TIMEOUT_MS),
|
|
593
|
+
});
|
|
543
594
|
if (!response.ok)
|
|
544
595
|
throw new Error(`HTTP ${response.status}`);
|
|
545
596
|
const data = (await response.json());
|
|
597
|
+
const local = this.localModelsForProvider(provider);
|
|
598
|
+
const fallback = local.find((model) => model.id === OPENROUTER_MODEL_ID);
|
|
599
|
+
const remote = (data.data ?? []).find((model) => model?.id === OPENROUTER_MODEL_ID);
|
|
600
|
+
if (!remote || !fallback) {
|
|
601
|
+
return { models: local, source: "static", authoritative: true };
|
|
602
|
+
}
|
|
603
|
+
const reasoning = openRouterReasoningMetadata(remote.reasoning, fallback);
|
|
546
604
|
return {
|
|
547
|
-
models:
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
605
|
+
models: [{
|
|
606
|
+
...fallback,
|
|
607
|
+
name: typeof remote.name === "string" && remote.name.trim() ? remote.name : fallback.name,
|
|
608
|
+
...reasoning,
|
|
609
|
+
contextWindow: typeof remote.context_length === "number" && remote.context_length > 0
|
|
610
|
+
? remote.context_length
|
|
611
|
+
: fallback.contextWindow,
|
|
612
|
+
}],
|
|
552
613
|
source: "remote",
|
|
553
614
|
authoritative: true,
|
|
554
615
|
};
|
|
@@ -719,7 +780,7 @@ export class ProviderRegistry {
|
|
|
719
780
|
};
|
|
720
781
|
}
|
|
721
782
|
localModelsForProvider(provider) {
|
|
722
|
-
const customModels = this.modelConfig.getCustomModels(provider.id);
|
|
783
|
+
const customModels = filterProviderModels(provider.id, this.modelConfig.getCustomModels(provider.id));
|
|
723
784
|
if (customModels.length > 0)
|
|
724
785
|
return customModels;
|
|
725
786
|
const catalogProviderId = provider.id === "openai" && provider.authType === "oauth"
|
|
@@ -732,6 +793,7 @@ export class ProviderRegistry {
|
|
|
732
793
|
reasoningLevels: model.reasoningLevels,
|
|
733
794
|
defaultReasoningLevel: model.defaultReasoningLevel,
|
|
734
795
|
contextWindow: model.contextWindow,
|
|
796
|
+
tier: model.tier,
|
|
735
797
|
useResponsesLite: model.useResponsesLite,
|
|
736
798
|
toolOutputTokenLimit: model.toolOutputTokenLimit,
|
|
737
799
|
}));
|
|
@@ -755,6 +817,7 @@ export class ProviderRegistry {
|
|
|
755
817
|
provider.authType ?? "api",
|
|
756
818
|
provider.protocol ?? "default",
|
|
757
819
|
this.discoveryIdentity(provider),
|
|
820
|
+
provider.id === "openrouter" ? OPENROUTER_CATALOG_SCOPE : undefined,
|
|
758
821
|
]);
|
|
759
822
|
}
|
|
760
823
|
/**
|