@bubblebrain-ai/bubble 0.0.52 → 0.0.53
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/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/package.json +23 -10
- package/packages/pi-tui/node_modules/marked/LICENSE +44 -0
- package/packages/pi-tui/node_modules/marked/README.md +115 -0
- package/packages/pi-tui/node_modules/marked/bin/main.js +284 -0
- package/packages/pi-tui/node_modules/marked/bin/marked.js +16 -0
- package/packages/pi-tui/node_modules/marked/lib/marked.d.ts +760 -0
- package/packages/pi-tui/node_modules/marked/lib/marked.esm.js +77 -0
- package/packages/pi-tui/node_modules/marked/lib/marked.esm.js.map +7 -0
- package/packages/pi-tui/node_modules/marked/lib/marked.umd.js +79 -0
- package/packages/pi-tui/node_modules/marked/lib/marked.umd.js.map +7 -0
- package/packages/pi-tui/node_modules/marked/man/marked.1 +113 -0
- package/packages/pi-tui/node_modules/marked/man/marked.1.md +93 -0
- package/packages/pi-tui/node_modules/marked/package.json +103 -0
- 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/agent.js
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
import { compactCurrentTurnToolGroups, compactMessages } from "./context/compact.js";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import { compactMessagesWithLLM } from "./context/compact-llm.js";
|
|
8
|
-
import { getContextBudget } from "./context/budget.js";
|
|
8
|
+
import { estimateToolDefinitionsTokens, getContextBudget, getMaxInputTokens, } from "./context/budget.js";
|
|
9
9
|
import { buildContextUsageSnapshot } from "./context/usage.js";
|
|
10
10
|
import { isContextOverflowError } from "./context/overflow.js";
|
|
11
|
-
import { computeRetryDelayMs, isProviderStreamInterruption,
|
|
11
|
+
import { computeRetryDelayMs, isProviderStreamInterruption, providerStreamRetryLimit, sleepBeforeRetry, } from "./network/retry.js";
|
|
12
12
|
import { projectMessages } from "./context/projector.js";
|
|
13
13
|
import { aggressivePruneMessages, markStableCurrentToolResultsForCache, markToolResultCacheStable } from "./context/prune.js";
|
|
14
|
-
import { truncateToolOutputForModel } from "./context/tool-output-truncate.js";
|
|
14
|
+
import { normalizeToolResultForModel, truncateToolOutputForModel } from "./context/tool-output-truncate.js";
|
|
15
15
|
import { buildDeferredToolsReminder, buildToolFreezeReminder, isPermissionModeReminder, reminderForMode } from "./prompt/reminders.js";
|
|
16
16
|
import { HookBus } from "./orchestrator/hooks.js";
|
|
17
17
|
import { normalizeHookInput, truncateHookText, } from "./hooks/index.js";
|
|
@@ -33,11 +33,17 @@ import { debugReasoningStream, summarizeDebugText } from "./reasoning-debug.js";
|
|
|
33
33
|
import { buildToolPromptOptions } from "./tools/prompt-metadata.js";
|
|
34
34
|
import { stopAutoServersForSession } from "./tools/server-manager.js";
|
|
35
35
|
import { summarizeAgentEventForTrace, summarizeTraceError, summarizeTraceMessage, summarizeTraceToolResult, summarizeTraceValue, traceEvent, } from "./debug-trace.js";
|
|
36
|
-
const MAX_CONSECUTIVE_OVERFLOW_RECOVERIES =
|
|
36
|
+
const MAX_CONSECUTIVE_OVERFLOW_RECOVERIES = 2;
|
|
37
37
|
const MAX_EMPTY_ASSISTANT_RECOVERIES = 1;
|
|
38
38
|
const EMPTY_ASSISTANT_RECOVERY_REMINDER = "The previous model response contained no user-visible assistant content and no tool calls. " +
|
|
39
39
|
"Respond now with a concise, user-visible answer, or call an available tool if more work is required. " +
|
|
40
40
|
"Do not put the final answer only in hidden reasoning.";
|
|
41
|
+
class LocalContextPreflightError extends Error {
|
|
42
|
+
constructor(estimatedTokens, maxInputTokens) {
|
|
43
|
+
super(`Local request preflight: estimated prompt length ${estimatedTokens} tokens exceeds maximum prompt length ${maxInputTokens}.`);
|
|
44
|
+
this.name = "LocalContextPreflightError";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
41
47
|
export { AgentAbortError, SubagentAbortError } from "./agent/abort-errors.js";
|
|
42
48
|
// Model-facing interruption boundary. Persisted into the transcript so the
|
|
43
49
|
// next turn sees an explicit stop instead of a dangling request — but it must
|
|
@@ -364,6 +370,11 @@ export class Agent {
|
|
|
364
370
|
memoryPrompt: this.memoryPrompt,
|
|
365
371
|
};
|
|
366
372
|
}
|
|
373
|
+
/** Refresh the live Skill catalog after /skills reloads or changes enablement. */
|
|
374
|
+
setSkillSummaries(skills) {
|
|
375
|
+
this.skillSummaries = skills.slice();
|
|
376
|
+
this.notifyContextChanged();
|
|
377
|
+
}
|
|
367
378
|
/** Current routing menu (design §4); undefined when no accessor is wired. */
|
|
368
379
|
buildModelRoutingPromptSection() {
|
|
369
380
|
return this.router.promptSection();
|
|
@@ -690,7 +701,11 @@ export class Agent {
|
|
|
690
701
|
return;
|
|
691
702
|
}
|
|
692
703
|
this.injectHookModelContext(promptHook.result);
|
|
693
|
-
this.appendMessage({
|
|
704
|
+
this.appendMessage({
|
|
705
|
+
role: "user",
|
|
706
|
+
content: userInput,
|
|
707
|
+
...(options.userMessageUi ? { ui: { ...options.userMessageUi } } : {}),
|
|
708
|
+
});
|
|
694
709
|
}
|
|
695
710
|
await hookBus.runBeforeTurn({
|
|
696
711
|
agent: this,
|
|
@@ -804,22 +819,32 @@ export class Agent {
|
|
|
804
819
|
description: t.description,
|
|
805
820
|
parameters: t.parameters,
|
|
806
821
|
}));
|
|
822
|
+
const toolDefinitionTokens = estimateToolDefinitionsTokens(toolDefinitions, this.providerId);
|
|
807
823
|
// LLM-driven compaction runs ahead of projector's algorithmic passes. If
|
|
808
824
|
// it succeeds, this.messages is replaced with [preserved system+meta] +
|
|
809
825
|
// [LLM summary] + [last user msg], and the projector becomes a no-op for
|
|
810
826
|
// budget. If it fails (network error, etc.), the projector's existing
|
|
811
827
|
// algorithmic fallback still kicks in.
|
|
812
|
-
await this.maybeCompactWithLLM();
|
|
828
|
+
await this.maybeCompactWithLLM(toolDefinitionTokens);
|
|
813
829
|
const bufferedStreamingToolCallIds = new Set();
|
|
830
|
+
let currentRequestEstimate;
|
|
814
831
|
try {
|
|
815
832
|
markStableCurrentToolResultsForCache(this.messages);
|
|
816
833
|
const projectedMessages = projectMessages(this.messages, {
|
|
817
834
|
mode: "budgeted",
|
|
818
835
|
providerId: this.providerId,
|
|
819
836
|
modelId: this.apiModel,
|
|
820
|
-
|
|
821
|
-
|
|
837
|
+
// Projection changes message identity/count (meta rendering, pruning,
|
|
838
|
+
// chain repair), so a resident-array anchor index is not safe here.
|
|
839
|
+
// A fresh estimate also lets us account for current tool schemas.
|
|
840
|
+
additionalInputTokens: toolDefinitionTokens,
|
|
822
841
|
});
|
|
842
|
+
const requestBudget = getContextBudget(this.providerId, this.apiModel, projectedMessages, { additionalInputTokens: toolDefinitionTokens });
|
|
843
|
+
currentRequestEstimate = requestBudget.estimatedTokens;
|
|
844
|
+
const maxInputTokens = getMaxInputTokens(requestBudget.contextWindow);
|
|
845
|
+
if (maxInputTokens !== undefined && currentRequestEstimate > maxInputTokens) {
|
|
846
|
+
throw new LocalContextPreflightError(currentRequestEstimate, maxInputTokens);
|
|
847
|
+
}
|
|
823
848
|
const providerStartedAt = Date.now();
|
|
824
849
|
let streamTextChars = 0;
|
|
825
850
|
let streamReasoningChars = 0;
|
|
@@ -1014,9 +1039,13 @@ export class Agent {
|
|
|
1014
1039
|
if (assistantAppended) {
|
|
1015
1040
|
throw error;
|
|
1016
1041
|
}
|
|
1017
|
-
|
|
1042
|
+
const streamInterruption = isProviderStreamInterruption(error) ? error : undefined;
|
|
1043
|
+
const streamRetryLimit = streamInterruption
|
|
1044
|
+
? providerStreamRetryLimit(streamInterruption)
|
|
1045
|
+
: 0;
|
|
1046
|
+
if (streamInterruption
|
|
1018
1047
|
&& !isAbortLikeError(error, abortSignal)
|
|
1019
|
-
&& consecutiveStreamInterruptionRetries <
|
|
1048
|
+
&& consecutiveStreamInterruptionRetries < streamRetryLimit) {
|
|
1020
1049
|
// The provider stream died after partial content. The half-built
|
|
1021
1050
|
// assistantMsg was never appended to this.messages, and the next
|
|
1022
1051
|
// turn_start resets the streaming display, so re-issuing the whole
|
|
@@ -1025,10 +1054,12 @@ export class Agent {
|
|
|
1025
1054
|
yield emit({
|
|
1026
1055
|
type: "provider_retry",
|
|
1027
1056
|
attempt: consecutiveStreamInterruptionRetries,
|
|
1028
|
-
maxAttempts:
|
|
1029
|
-
reason:
|
|
1057
|
+
maxAttempts: streamRetryLimit,
|
|
1058
|
+
reason: streamInterruption.message,
|
|
1030
1059
|
});
|
|
1031
|
-
await sleepBeforeRetry(computeRetryDelayMs(consecutiveStreamInterruptionRetries
|
|
1060
|
+
await sleepBeforeRetry(computeRetryDelayMs(consecutiveStreamInterruptionRetries, {
|
|
1061
|
+
retryAfterMs: streamInterruption.retryAfterMs,
|
|
1062
|
+
}), abortSignal).catch(() => undefined);
|
|
1032
1063
|
continue;
|
|
1033
1064
|
}
|
|
1034
1065
|
if (!isContextOverflowError(error)) {
|
|
@@ -1045,12 +1076,44 @@ export class Agent {
|
|
|
1045
1076
|
if (consecutiveOverflowRecoveries >= MAX_CONSECUTIVE_OVERFLOW_RECOVERIES) {
|
|
1046
1077
|
throw error;
|
|
1047
1078
|
}
|
|
1048
|
-
const
|
|
1079
|
+
const messagesBeforeRecovery = this.messages;
|
|
1080
|
+
const inputTokensBeforeRecovery = this.lastInputTokens;
|
|
1081
|
+
const anchorBeforeRecovery = this.lastAnchorMessageCount;
|
|
1082
|
+
const failedRequestEstimate = currentRequestEstimate ?? getContextBudget(this.providerId, this.apiModel, projectMessages(this.messages, {
|
|
1083
|
+
mode: "budgeted",
|
|
1084
|
+
providerId: this.providerId,
|
|
1085
|
+
modelId: this.apiModel,
|
|
1086
|
+
additionalInputTokens: toolDefinitionTokens,
|
|
1087
|
+
}), { additionalInputTokens: toolDefinitionTokens }).estimatedTokens;
|
|
1088
|
+
const droppedMessages = await this.recoverFromOverflow(consecutiveOverflowRecoveries, error instanceof LocalContextPreflightError ? 0.999_999 : 0.9);
|
|
1089
|
+
const recoveredRequestEstimate = getContextBudget(this.providerId, this.apiModel, projectMessages(this.messages, {
|
|
1090
|
+
mode: "budgeted",
|
|
1091
|
+
providerId: this.providerId,
|
|
1092
|
+
modelId: this.apiModel,
|
|
1093
|
+
additionalInputTokens: toolDefinitionTokens,
|
|
1094
|
+
}), { additionalInputTokens: toolDefinitionTokens }).estimatedTokens;
|
|
1095
|
+
// Never issue a retry that is the same size or larger. Apart from
|
|
1096
|
+
// avoiding a useless retry loop, this proves that already-completed
|
|
1097
|
+
// tool calls stay historical data rather than being executed again.
|
|
1098
|
+
const madeProgress = recoveredRequestEstimate < failedRequestEstimate;
|
|
1099
|
+
const meaningfulProviderProgress = error instanceof LocalContextPreflightError
|
|
1100
|
+
|| recoveredRequestEstimate <= Math.floor(failedRequestEstimate * 0.9);
|
|
1101
|
+
if (!madeProgress || !meaningfulProviderProgress) {
|
|
1102
|
+
this.messages = messagesBeforeRecovery;
|
|
1103
|
+
this.lastInputTokens = inputTokensBeforeRecovery;
|
|
1104
|
+
this.lastAnchorMessageCount = anchorBeforeRecovery;
|
|
1105
|
+
throw error;
|
|
1106
|
+
}
|
|
1049
1107
|
consecutiveOverflowRecoveries += 1;
|
|
1050
1108
|
this.compactionStats.overflow += 1;
|
|
1051
1109
|
this.compactionStats.fired += 1;
|
|
1052
1110
|
this.compactionStats.droppedMessages += droppedMessages;
|
|
1053
|
-
traceEvent("compaction_fired", {
|
|
1111
|
+
traceEvent("compaction_fired", {
|
|
1112
|
+
path: "overflow",
|
|
1113
|
+
droppedMessages,
|
|
1114
|
+
beforeEstimatedTokens: failedRequestEstimate,
|
|
1115
|
+
afterEstimatedTokens: recoveredRequestEstimate,
|
|
1116
|
+
});
|
|
1054
1117
|
yield emit({ type: "context_recovered", droppedMessages, reason: "overflow" });
|
|
1055
1118
|
continue;
|
|
1056
1119
|
}
|
|
@@ -1175,7 +1238,7 @@ export class Agent {
|
|
|
1175
1238
|
yield emit({ type: "tool_call_end", id: tc.id, name: tc.name, arguments: tc.arguments });
|
|
1176
1239
|
}
|
|
1177
1240
|
if (isHiddenToolResult(blockedResult)) {
|
|
1178
|
-
let result = blockedResult;
|
|
1241
|
+
let result = normalizeToolResultForModel(blockedResult, this.providerId, this.apiModel);
|
|
1179
1242
|
await hookBus.runAfterToolCall({
|
|
1180
1243
|
agent: this,
|
|
1181
1244
|
cwd,
|
|
@@ -1189,6 +1252,7 @@ export class Agent {
|
|
|
1189
1252
|
result = next;
|
|
1190
1253
|
},
|
|
1191
1254
|
});
|
|
1255
|
+
result = normalizeToolResultForModel(result, this.providerId, this.apiModel);
|
|
1192
1256
|
const postToolHook = await this.runExternalHook({
|
|
1193
1257
|
eventName: result.isError ? "PostToolUseFailure" : "PostToolUse",
|
|
1194
1258
|
cwd,
|
|
@@ -1292,6 +1356,9 @@ export class Agent {
|
|
|
1292
1356
|
result = resolved ?? { content: `Error: Tool "${tc.name}" returned no result`, isError: true };
|
|
1293
1357
|
}
|
|
1294
1358
|
}
|
|
1359
|
+
// Hooks receive a bounded canonical result. This prevents a tool
|
|
1360
|
+
// from handing an unbounded multi-megabyte value to PostToolUse.
|
|
1361
|
+
result = normalizeToolResultForModel(result, this.providerId, this.apiModel);
|
|
1295
1362
|
await hookBus.runAfterToolCall({
|
|
1296
1363
|
agent: this,
|
|
1297
1364
|
cwd,
|
|
@@ -1305,6 +1372,9 @@ export class Agent {
|
|
|
1305
1372
|
result = next;
|
|
1306
1373
|
},
|
|
1307
1374
|
});
|
|
1375
|
+
// A hook is allowed to replace the result, so enforce the invariant
|
|
1376
|
+
// again before persistence, callbacks, UI events and provider reuse.
|
|
1377
|
+
result = normalizeToolResultForModel(result, this.providerId, this.apiModel);
|
|
1308
1378
|
const postToolHook = await this.runExternalHook({
|
|
1309
1379
|
eventName: result.isError ? "PostToolUseFailure" : "PostToolUse",
|
|
1310
1380
|
cwd,
|
|
@@ -1339,7 +1409,10 @@ export class Agent {
|
|
|
1339
1409
|
truncated: truncatedOutput.truncated,
|
|
1340
1410
|
originalTokens: truncatedOutput.originalTokens,
|
|
1341
1411
|
finalTokens: truncatedOutput.finalTokens,
|
|
1412
|
+
originalBytes: truncatedOutput.originalBytes,
|
|
1413
|
+
finalBytes: truncatedOutput.finalBytes,
|
|
1342
1414
|
limit: truncatedOutput.limit,
|
|
1415
|
+
hardByteLimit: truncatedOutput.hardByteLimit,
|
|
1343
1416
|
},
|
|
1344
1417
|
}, traceContext);
|
|
1345
1418
|
const toolMessage = {
|
|
@@ -1458,71 +1531,89 @@ export class Agent {
|
|
|
1458
1531
|
}, traceContext);
|
|
1459
1532
|
}
|
|
1460
1533
|
}
|
|
1461
|
-
async recoverFromOverflow(attempt) {
|
|
1534
|
+
async recoverFromOverflow(attempt, maximumSizeRatio = 0.999_999) {
|
|
1462
1535
|
const before = this.messages.length;
|
|
1463
|
-
const
|
|
1536
|
+
const originalMessages = this.messages;
|
|
1537
|
+
const beforeBytes = serializedMessageBytes(originalMessages);
|
|
1538
|
+
const commitIfSmaller = (candidate, summary) => {
|
|
1539
|
+
if (!candidate
|
|
1540
|
+
|| serializedMessageBytes(candidate) > Math.floor(beforeBytes * maximumSizeRatio))
|
|
1541
|
+
return false;
|
|
1542
|
+
this.messages = candidate;
|
|
1543
|
+
this.lastInputTokens = null;
|
|
1544
|
+
this.lastAnchorMessageCount = null;
|
|
1545
|
+
this.fileStateTracker?.invalidateReadHistory();
|
|
1546
|
+
this.persistCompactionSummary(summary);
|
|
1547
|
+
return true;
|
|
1548
|
+
};
|
|
1464
1549
|
if (attempt === 0) {
|
|
1465
|
-
|
|
1466
|
-
const afterTokens = this.messages.reduce((sum, m) => sum + JSON.stringify(m).length, 0);
|
|
1467
|
-
if (afterTokens < beforeTokens) {
|
|
1468
|
-
this.lastInputTokens = null;
|
|
1469
|
-
this.lastAnchorMessageCount = null;
|
|
1470
|
-
this.fileStateTracker?.invalidateReadHistory();
|
|
1550
|
+
if (commitIfSmaller(aggressivePruneMessages(originalMessages))) {
|
|
1471
1551
|
return before - this.messages.length;
|
|
1472
1552
|
}
|
|
1473
1553
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1554
|
+
// Unlike ordinary pruning, overflow recovery is allowed to thin the most
|
|
1555
|
+
// recent completed tool batch. Keeping it protected is exactly what made
|
|
1556
|
+
// a one-turn 6MB grep result impossible to recover from.
|
|
1557
|
+
const emergencyToolLimit = attempt === 0 ? 16 * 1024 : 4 * 1024;
|
|
1558
|
+
const thinnedLatestTools = originalMessages.map((message) => {
|
|
1559
|
+
if (message.role !== "tool")
|
|
1560
|
+
return message;
|
|
1561
|
+
const bounded = truncateToolOutputForModel(message.content, this.providerId, this.apiModel, { hardByteLimit: emergencyToolLimit });
|
|
1562
|
+
return bounded.truncated ? { ...message, content: bounded.content } : message;
|
|
1563
|
+
});
|
|
1564
|
+
if (commitIfSmaller(thinnedLatestTools)) {
|
|
1565
|
+
return before - this.messages.length;
|
|
1566
|
+
}
|
|
1567
|
+
const keepRecentTurns = attempt >= 1 ? 1 : 2;
|
|
1568
|
+
const llmResult = await compactMessagesWithLLM(originalMessages, {
|
|
1476
1569
|
provider: this.provider,
|
|
1477
1570
|
model: this.apiModel,
|
|
1478
1571
|
thinkingLevel: this.thinkingLevel,
|
|
1479
1572
|
keepRecentTurns,
|
|
1480
1573
|
});
|
|
1481
|
-
if (llmResult.compacted && llmResult.messages) {
|
|
1482
|
-
this.messages = llmResult.messages;
|
|
1483
|
-
this.lastInputTokens = null;
|
|
1484
|
-
this.lastAnchorMessageCount = null;
|
|
1485
|
-
this.fileStateTracker?.invalidateReadHistory();
|
|
1486
|
-
this.persistCompactionSummary(llmResult.summary);
|
|
1574
|
+
if (llmResult.compacted && commitIfSmaller(llmResult.messages, llmResult.summary)) {
|
|
1487
1575
|
return before - this.messages.length;
|
|
1488
1576
|
}
|
|
1489
1577
|
// Single-turn capable LLM compactor. compactMessagesWithLLM above no-ops
|
|
1490
1578
|
// when there's only one user turn (the "single huge prompt with many tool
|
|
1491
1579
|
// calls" case), so try the turn-internal compactor before giving up.
|
|
1492
1580
|
const { compactWithLLM } = await import("./context/llm-compactor.js");
|
|
1493
|
-
const singleTurnResult = await compactWithLLM(
|
|
1581
|
+
const singleTurnResult = await compactWithLLM(originalMessages, {
|
|
1494
1582
|
provider: this.provider,
|
|
1495
1583
|
modelId: this.apiModel,
|
|
1496
1584
|
});
|
|
1497
|
-
if (singleTurnResult.compacted && singleTurnResult.messages) {
|
|
1498
|
-
this.messages = singleTurnResult.messages;
|
|
1499
|
-
this.lastInputTokens = null;
|
|
1500
|
-
this.lastAnchorMessageCount = null;
|
|
1501
|
-
this.fileStateTracker?.invalidateReadHistory();
|
|
1502
|
-
this.persistCompactionSummary(singleTurnResult.summary);
|
|
1585
|
+
if (singleTurnResult.compacted && commitIfSmaller(singleTurnResult.messages, singleTurnResult.summary)) {
|
|
1503
1586
|
return before - this.messages.length;
|
|
1504
1587
|
}
|
|
1505
|
-
const fallback = compactMessages(
|
|
1506
|
-
if (fallback.compacted && fallback.messages) {
|
|
1507
|
-
this.messages
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1588
|
+
const fallback = compactMessages(originalMessages, { keepRecentTurns });
|
|
1589
|
+
if (fallback.compacted && commitIfSmaller(fallback.messages, fallback.summary)) {
|
|
1590
|
+
return before - this.messages.length;
|
|
1591
|
+
}
|
|
1592
|
+
const subturn = compactCurrentTurnToolGroups(originalMessages, {
|
|
1593
|
+
keepRecentGroups: attempt === 0 ? 1 : 0,
|
|
1594
|
+
});
|
|
1595
|
+
if (subturn.compacted && commitIfSmaller(subturn.messages, subturn.summary)) {
|
|
1512
1596
|
return before - this.messages.length;
|
|
1513
1597
|
}
|
|
1514
1598
|
// Codex-style last-resort: drop the single oldest non-protected message
|
|
1515
1599
|
// and let the retry loop try again. Cheap, but eventually narrows even an
|
|
1516
1600
|
// intractable single-turn overflow.
|
|
1517
|
-
const
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1601
|
+
const realUserIndexes = originalMessages
|
|
1602
|
+
.map((message, index) => message.role === "user" ? index : -1)
|
|
1603
|
+
.filter((index) => index >= 0);
|
|
1604
|
+
const oldestIdx = realUserIndexes.length > 1
|
|
1605
|
+
? realUserIndexes[0]
|
|
1606
|
+
: -1;
|
|
1607
|
+
const removeUntil = realUserIndexes.length > 1
|
|
1608
|
+
? realUserIndexes[1]
|
|
1609
|
+
: -1;
|
|
1610
|
+
if (oldestIdx >= 0 && removeUntil > oldestIdx && removeUntil < originalMessages.length) {
|
|
1611
|
+
const candidate = [
|
|
1612
|
+
...originalMessages.slice(0, oldestIdx),
|
|
1613
|
+
...originalMessages.slice(removeUntil),
|
|
1522
1614
|
];
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
this.fileStateTracker?.invalidateReadHistory();
|
|
1615
|
+
if (!commitIfSmaller(candidate))
|
|
1616
|
+
return 0;
|
|
1526
1617
|
return before - this.messages.length;
|
|
1527
1618
|
}
|
|
1528
1619
|
return 0;
|
|
@@ -1530,7 +1621,7 @@ export class Agent {
|
|
|
1530
1621
|
compactResidentHistory() {
|
|
1531
1622
|
this.maybeCompactResidentHistory();
|
|
1532
1623
|
}
|
|
1533
|
-
async maybeCompactWithLLM() {
|
|
1624
|
+
async maybeCompactWithLLM(additionalInputTokens = 0) {
|
|
1534
1625
|
if (!this.providerId || !this.apiModel)
|
|
1535
1626
|
return;
|
|
1536
1627
|
if (this.messages.length === 0)
|
|
@@ -1541,6 +1632,7 @@ export class Agent {
|
|
|
1541
1632
|
const budget = getContextBudget(this.providerId, this.apiModel, this.messages, {
|
|
1542
1633
|
usageAnchorTokens: this.lastInputTokens ?? undefined,
|
|
1543
1634
|
tailMessages: tail,
|
|
1635
|
+
additionalInputTokens,
|
|
1544
1636
|
});
|
|
1545
1637
|
if (!budget.shouldCompact)
|
|
1546
1638
|
return;
|
|
@@ -1576,7 +1668,7 @@ export class Agent {
|
|
|
1576
1668
|
* (the caller falls back to heuristic compaction in that case). Throws only
|
|
1577
1669
|
* if the provider stream itself errors.
|
|
1578
1670
|
*/
|
|
1579
|
-
async summarizeForCompaction(oldMessages, onDelta, abortSignal) {
|
|
1671
|
+
async summarizeForCompaction(oldMessages, onDelta, abortSignal, userContext) {
|
|
1580
1672
|
if (oldMessages.length === 0)
|
|
1581
1673
|
return "";
|
|
1582
1674
|
const { buildCompactionPromptMessages } = await import("./context/compact-llm.js");
|
|
@@ -1589,7 +1681,7 @@ export class Agent {
|
|
|
1589
1681
|
const promptInput = oldMessages.map((message) => isCompactionSummaryMessage(message) && typeof message.content === "string"
|
|
1590
1682
|
? { ...message, content: stripFileBlocks(messageText(message)) }
|
|
1591
1683
|
: message);
|
|
1592
|
-
const promptMessages = buildCompactionPromptMessages(promptInput);
|
|
1684
|
+
const promptMessages = buildCompactionPromptMessages(promptInput, userContext);
|
|
1593
1685
|
const stream = this.provider.streamChat(promptMessages, {
|
|
1594
1686
|
model: this.apiModel,
|
|
1595
1687
|
temperature: 0.2,
|
|
@@ -1641,6 +1733,12 @@ export class Agent {
|
|
|
1641
1733
|
listSubAgents() {
|
|
1642
1734
|
return this.subagents.listSubAgents();
|
|
1643
1735
|
}
|
|
1736
|
+
/** Read-only child transcript for the TUI inspector. */
|
|
1737
|
+
getSubAgentMessages(agentId) {
|
|
1738
|
+
const record = this.subagentStore.get(agentId);
|
|
1739
|
+
const messages = record?.agent?.messages ?? record?.messages ?? [];
|
|
1740
|
+
return messages.map((message) => ({ ...message }));
|
|
1741
|
+
}
|
|
1644
1742
|
/** Marks a child's full summary as delivered to parent context (design §3.3). */
|
|
1645
1743
|
markSubagentDelivered(agentId) {
|
|
1646
1744
|
this.subagents.markSubagentDelivered(agentId);
|
|
@@ -1982,3 +2080,6 @@ export class Agent {
|
|
|
1982
2080
|
}
|
|
1983
2081
|
}
|
|
1984
2082
|
}
|
|
2083
|
+
function serializedMessageBytes(messages) {
|
|
2084
|
+
return Buffer.byteLength(JSON.stringify(messages), "utf8");
|
|
2085
|
+
}
|
package/dist/bin.js
CHANGED
|
@@ -1,45 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
const mainPath = fileURLToPath(new URL("./main.js", import.meta.url));
|
|
5
|
-
if (process.versions.bun) {
|
|
6
|
-
await import("./main.js");
|
|
7
|
-
}
|
|
8
|
-
else {
|
|
9
|
-
const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore" });
|
|
10
|
-
if (bunCheck.error) {
|
|
11
|
-
console.error([
|
|
12
|
-
"Bubble requires Bun to run.",
|
|
13
|
-
"",
|
|
14
|
-
"Install Bun, then run bubble again:",
|
|
15
|
-
" curl -fsSL https://bun.sh/install | bash",
|
|
16
|
-
"",
|
|
17
|
-
"After installation, restart your terminal if the bun command is not found.",
|
|
18
|
-
].join("\n"));
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
const child = spawn("bun", [mainPath, ...process.argv.slice(2)], {
|
|
22
|
-
stdio: "inherit",
|
|
23
|
-
env: process.env,
|
|
24
|
-
});
|
|
25
|
-
child.on("error", (error) => {
|
|
26
|
-
console.error(`Failed to start Bubble with Bun: ${error.message}`);
|
|
27
|
-
process.exit(1);
|
|
28
|
-
});
|
|
29
|
-
for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
30
|
-
process.on(signal, () => {
|
|
31
|
-
if (!child.killed) {
|
|
32
|
-
child.kill(signal);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
const result = await new Promise((resolve) => {
|
|
37
|
-
child.on("exit", (code, signal) => resolve({ code, signal }));
|
|
38
|
-
});
|
|
39
|
-
if (result.signal) {
|
|
40
|
-
process.kill(process.pid, result.signal);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
process.exit(result.code ?? 1);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
2
|
+
await import("./main.js");
|
|
3
|
+
export {};
|
package/dist/config.d.ts
CHANGED
|
@@ -17,6 +17,10 @@ export interface UserConfigData {
|
|
|
17
17
|
defaultModel?: string;
|
|
18
18
|
defaultThinkingLevel?: ThinkingLevel;
|
|
19
19
|
skillPaths?: string[];
|
|
20
|
+
/** Skill names disabled from invocation/search until re-enabled in /skills. */
|
|
21
|
+
skills?: {
|
|
22
|
+
disabled?: string[];
|
|
23
|
+
};
|
|
20
24
|
/**
|
|
21
25
|
* Three shapes are accepted on disk so we can evolve without breaking
|
|
22
26
|
* existing configs:
|
|
@@ -35,9 +39,14 @@ export interface UserConfigData {
|
|
|
35
39
|
/** Subagent model-routing knobs: autoTier (default true), allowCrossProvider (default true). */
|
|
36
40
|
agentRouting?: Partial<AgentRoutingConfig>;
|
|
37
41
|
subagents?: SubagentsUserConfig;
|
|
38
|
-
/** Background tasks
|
|
42
|
+
/** Background tasks: completion wakes and Grok-style foreground demotion. */
|
|
39
43
|
tasks?: {
|
|
44
|
+
/** Auto-resume the Agent when an owned task finishes. Defaults ON. */
|
|
40
45
|
autoResume?: boolean;
|
|
46
|
+
/** Move long foreground Execute calls into Tasks automatically. Defaults ON. */
|
|
47
|
+
autoBackground?: boolean;
|
|
48
|
+
/** Foreground wait budget before automatic demotion. Defaults to 15 seconds. */
|
|
49
|
+
foregroundWaitMs?: number;
|
|
41
50
|
};
|
|
42
51
|
}
|
|
43
52
|
export interface SubagentsUserConfig {
|
|
@@ -56,6 +65,8 @@ export declare class UserConfig {
|
|
|
56
65
|
getRecentModels(): string[];
|
|
57
66
|
/** Auto-resume on background-task completion (design §2.3b). Default ON. */
|
|
58
67
|
getTasksAutoResume(): boolean;
|
|
68
|
+
/** Grok-style foreground wait budget. `false` disables automatic demotion. */
|
|
69
|
+
getTasksAutoBackgroundAfterMs(): number | false;
|
|
59
70
|
pushRecentModel(model: string): void;
|
|
60
71
|
getApiKey(): string | undefined;
|
|
61
72
|
setApiKey(key: string): void;
|
|
@@ -65,6 +76,8 @@ export declare class UserConfig {
|
|
|
65
76
|
setDefaultProvider(id: string): void;
|
|
66
77
|
getSkillPaths(): string[];
|
|
67
78
|
setSkillPaths(paths: string[]): void;
|
|
79
|
+
getDisabledSkills(): string[];
|
|
80
|
+
setDisabledSkills(names: string[]): void;
|
|
68
81
|
getTheme(): ThemeConfig;
|
|
69
82
|
getThemeMode(): ThemeMode;
|
|
70
83
|
getThemeOverrides(): Record<string, string>;
|
package/dist/config.js
CHANGED
|
@@ -8,7 +8,10 @@ import { dirname, join } from "node:path";
|
|
|
8
8
|
import { getBubbleHome } from "./bubble-home.js";
|
|
9
9
|
import { sanitizeAgentCategories } from "./agent/categories.js";
|
|
10
10
|
import { sanitizeAgentRouting } from "./agent/routing-catalog.js";
|
|
11
|
-
|
|
11
|
+
import { isProviderModelAllowed } from "./provider-model-policy.js";
|
|
12
|
+
// openai-codex is an internal transport profile surfaced through the visible
|
|
13
|
+
// OpenAI OAuth provider. OpenRouter is a regular user-configurable provider.
|
|
14
|
+
const HIDDEN_PROVIDER_IDS = new Set(["openai-codex"]);
|
|
12
15
|
function getConfigPath() {
|
|
13
16
|
return join(getBubbleHome(), "config.json");
|
|
14
17
|
}
|
|
@@ -20,10 +23,16 @@ function modelProviderId(model) {
|
|
|
20
23
|
return undefined;
|
|
21
24
|
return model.split(":", 1)[0];
|
|
22
25
|
}
|
|
26
|
+
function isAllowedConfiguredModel(model) {
|
|
27
|
+
if (!model.includes(":"))
|
|
28
|
+
return true;
|
|
29
|
+
const [providerId, ...modelParts] = model.split(":");
|
|
30
|
+
return isProviderModelAllowed(providerId, modelParts.join(":"));
|
|
31
|
+
}
|
|
23
32
|
function sanitizeRecentModels(models) {
|
|
24
33
|
if (!models)
|
|
25
34
|
return undefined;
|
|
26
|
-
return models.filter((model) => !isHiddenProviderId(modelProviderId(model)));
|
|
35
|
+
return models.filter((model) => !isHiddenProviderId(modelProviderId(model)) && isAllowedConfiguredModel(model));
|
|
27
36
|
}
|
|
28
37
|
function sanitizeProviders(providers) {
|
|
29
38
|
if (!providers)
|
|
@@ -33,7 +42,9 @@ function sanitizeProviders(providers) {
|
|
|
33
42
|
function sanitizeDefaultModel(model) {
|
|
34
43
|
if (!model)
|
|
35
44
|
return undefined;
|
|
36
|
-
return isHiddenProviderId(modelProviderId(model))
|
|
45
|
+
return isHiddenProviderId(modelProviderId(model)) || !isAllowedConfiguredModel(model)
|
|
46
|
+
? undefined
|
|
47
|
+
: model;
|
|
37
48
|
}
|
|
38
49
|
function sanitizeDefaultProvider(providerId) {
|
|
39
50
|
return isHiddenProviderId(providerId) ? undefined : providerId;
|
|
@@ -143,8 +154,17 @@ export class UserConfig {
|
|
|
143
154
|
getTasksAutoResume() {
|
|
144
155
|
return this.data.tasks?.autoResume !== false;
|
|
145
156
|
}
|
|
157
|
+
/** Grok-style foreground wait budget. `false` disables automatic demotion. */
|
|
158
|
+
getTasksAutoBackgroundAfterMs() {
|
|
159
|
+
if (this.data.tasks?.autoBackground === false)
|
|
160
|
+
return false;
|
|
161
|
+
const configured = this.data.tasks?.foregroundWaitMs;
|
|
162
|
+
if (typeof configured !== "number" || !Number.isFinite(configured))
|
|
163
|
+
return 15_000;
|
|
164
|
+
return Math.max(1_000, Math.min(300_000, Math.floor(configured)));
|
|
165
|
+
}
|
|
146
166
|
pushRecentModel(model) {
|
|
147
|
-
if (isHiddenProviderId(modelProviderId(model))) {
|
|
167
|
+
if (isHiddenProviderId(modelProviderId(model)) || !isAllowedConfiguredModel(model)) {
|
|
148
168
|
return;
|
|
149
169
|
}
|
|
150
170
|
const recent = this.data.recentModels ?? [];
|
|
@@ -182,6 +202,27 @@ export class UserConfig {
|
|
|
182
202
|
this.data.skillPaths = paths.slice();
|
|
183
203
|
this.save();
|
|
184
204
|
}
|
|
205
|
+
getDisabledSkills() {
|
|
206
|
+
const disabled = this.data.skills?.disabled;
|
|
207
|
+
if (!Array.isArray(disabled))
|
|
208
|
+
return [];
|
|
209
|
+
return [...new Set(disabled.filter((name) => (typeof name === "string" && /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(name))))].sort((a, b) => a.localeCompare(b));
|
|
210
|
+
}
|
|
211
|
+
setDisabledSkills(names) {
|
|
212
|
+
const disabled = [...new Set(names.filter((name) => (/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(name))))].sort((a, b) => a.localeCompare(b));
|
|
213
|
+
if (disabled.length === 0) {
|
|
214
|
+
const next = { ...(this.data.skills ?? {}) };
|
|
215
|
+
delete next.disabled;
|
|
216
|
+
if (Object.keys(next).length === 0)
|
|
217
|
+
delete this.data.skills;
|
|
218
|
+
else
|
|
219
|
+
this.data.skills = next;
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
this.data.skills = { ...(this.data.skills ?? {}), disabled };
|
|
223
|
+
}
|
|
224
|
+
this.save();
|
|
225
|
+
}
|
|
185
226
|
getTheme() {
|
|
186
227
|
const theme = sanitizeTheme(this.data.theme);
|
|
187
228
|
return theme ?? { mode: "auto" };
|
package/dist/context/budget.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Message } from "../types.js";
|
|
1
|
+
import type { Message, ToolDefinition } from "../types.js";
|
|
2
2
|
export declare const OUTPUT_RESERVE_TOKENS = 20000;
|
|
3
3
|
export declare const AUTOCOMPACT_BUFFER_TOKENS = 13000;
|
|
4
4
|
export declare const PRUNE_BUFFER_TOKENS = 50000;
|
|
@@ -15,8 +15,14 @@ export interface ContextBudgetOptions {
|
|
|
15
15
|
usageAnchorTokens?: number;
|
|
16
16
|
/** Messages appended after the anchor (their tokens are estimated and added). */
|
|
17
17
|
tailMessages?: Message[];
|
|
18
|
+
/** Tokens outside the message list, primarily serialized tool definitions. */
|
|
19
|
+
additionalInputTokens?: number;
|
|
18
20
|
}
|
|
19
21
|
export declare function estimateMessageTokens(message: Message, providerId?: string): number;
|
|
20
22
|
export declare function estimateContextTokens(messages: Message[], providerId?: string): number;
|
|
21
23
|
export declare function getContextBudget(providerId: string, modelId: string, messages: Message[], options?: ContextBudgetOptions): ContextBudget;
|
|
24
|
+
/** Estimate the request-space occupied by tool schemas sent on every turn. */
|
|
25
|
+
export declare function estimateToolDefinitionsTokens(tools: ToolDefinition[], providerId?: string): number;
|
|
26
|
+
/** Maximum estimated input size that still leaves useful room for an answer. */
|
|
27
|
+
export declare function getMaxInputTokens(contextWindow: number | undefined): number | undefined;
|
|
22
28
|
export declare function estimateTextTokens(text: string, providerId?: string): number;
|
package/dist/context/budget.js
CHANGED
|
@@ -65,16 +65,39 @@ export function getContextBudget(providerId, modelId, messages, options = {}) {
|
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
function computeEstimatedTokens(providerId, messages, options) {
|
|
68
|
+
const additionalInputTokens = Math.max(0, options.additionalInputTokens ?? 0);
|
|
68
69
|
if (options.usageAnchorTokens !== undefined && options.tailMessages) {
|
|
69
70
|
// Anchor is authoritative (server-reported input tokens from the last
|
|
70
71
|
// response). Tail goes through our estimator and may undercount on dense /
|
|
71
72
|
// tool-output content, so we inflate it by a small margin before adding.
|
|
72
73
|
const tailEstimate = estimateContextTokens(options.tailMessages, providerId);
|
|
73
|
-
return options.usageAnchorTokens
|
|
74
|
+
return options.usageAnchorTokens
|
|
75
|
+
+ Math.ceil(tailEstimate * TAIL_SAFETY_MARGIN)
|
|
76
|
+
+ additionalInputTokens;
|
|
74
77
|
}
|
|
75
78
|
// First turn (or anchor lost): there's no server-reported baseline at all,
|
|
76
79
|
// so apply a larger safety margin to the pure estimate.
|
|
77
|
-
return Math.ceil(estimateContextTokens(messages, providerId)
|
|
80
|
+
return Math.ceil((estimateContextTokens(messages, providerId) + additionalInputTokens)
|
|
81
|
+
* FIRST_TURN_SAFETY_MARGIN);
|
|
82
|
+
}
|
|
83
|
+
/** Estimate the request-space occupied by tool schemas sent on every turn. */
|
|
84
|
+
export function estimateToolDefinitionsTokens(tools, providerId) {
|
|
85
|
+
if (tools.length === 0)
|
|
86
|
+
return 0;
|
|
87
|
+
// Providers wrap this array in their own function/tool envelope. The fixed
|
|
88
|
+
// per-entry allowance covers names, discriminator keys and separators not
|
|
89
|
+
// represented by the plain JSON payload.
|
|
90
|
+
return estimateTextTokens(JSON.stringify(tools), providerId) + tools.length * 16 + 16;
|
|
91
|
+
}
|
|
92
|
+
/** Maximum estimated input size that still leaves useful room for an answer. */
|
|
93
|
+
export function getMaxInputTokens(contextWindow) {
|
|
94
|
+
if (!contextWindow)
|
|
95
|
+
return undefined;
|
|
96
|
+
return contextWindow >= MIN_WINDOW_FOR_RESERVE
|
|
97
|
+
? Math.max(1, contextWindow
|
|
98
|
+
- OUTPUT_RESERVE_TOKENS
|
|
99
|
+
- Math.max(AUTOCOMPACT_BUFFER_TOKENS, Math.floor(contextWindow * 0.05)))
|
|
100
|
+
: Math.max(1, Math.floor(contextWindow * 0.75));
|
|
78
101
|
}
|
|
79
102
|
function shouldTriggerPrune(estimatedTokens, contextWindow) {
|
|
80
103
|
if (!contextWindow) {
|
|
@@ -21,5 +21,5 @@ export declare function compactMessagesWithLLM(messages: Message[], options: LLM
|
|
|
21
21
|
* `oldMessages`. Shared by the non-streaming overflow path (`generateSummary`)
|
|
22
22
|
* and the streaming manual `/compact` path (`Agent.summarizeForCompaction`).
|
|
23
23
|
*/
|
|
24
|
-
export declare function buildCompactionPromptMessages(oldMessages: Message[]): ProviderMessage[];
|
|
24
|
+
export declare function buildCompactionPromptMessages(oldMessages: Message[], userContext?: string): ProviderMessage[];
|
|
25
25
|
export declare function serializeTranscript(messages: Message[]): string;
|