@bubblebrain-ai/bubble 0.0.51 → 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 +80 -11
- package/dist/provider-transform.js +32 -4
- package/dist/provider.d.ts +6 -2
- package/dist/provider.js +100 -11
- 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
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
export class OwnedRequest {
|
|
2
|
+
id;
|
|
3
|
+
kind;
|
|
4
|
+
onSettle;
|
|
5
|
+
state = "pending";
|
|
6
|
+
resolvers = [];
|
|
7
|
+
result;
|
|
8
|
+
constructor(id, kind, onSettle) {
|
|
9
|
+
this.id = id;
|
|
10
|
+
this.kind = kind;
|
|
11
|
+
this.onSettle = onSettle;
|
|
12
|
+
this.result = new Promise((resolve) => {
|
|
13
|
+
this.resolvers.push(resolve);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
settle(decision, via) {
|
|
17
|
+
if (this.state !== "pending")
|
|
18
|
+
return false;
|
|
19
|
+
this.state = decision === undefined
|
|
20
|
+
? (via === "user" ? "cancelled" : via === "replaced" ? "disposed" : "cancelled")
|
|
21
|
+
: "accepted";
|
|
22
|
+
const resolve = this.resolvers[0];
|
|
23
|
+
this.resolvers = [];
|
|
24
|
+
resolve?.(decision);
|
|
25
|
+
this.onSettle?.(this, via);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
let nextRequestId = 0;
|
|
30
|
+
export class OverlayRequestController {
|
|
31
|
+
deps;
|
|
32
|
+
requests = new Map();
|
|
33
|
+
questionUnsubscribe;
|
|
34
|
+
notifyChange = () => { };
|
|
35
|
+
constructor(deps = {}) {
|
|
36
|
+
this.deps = deps;
|
|
37
|
+
}
|
|
38
|
+
/** Host wires change notification (snapshot rebuild). */
|
|
39
|
+
onChange(listener) {
|
|
40
|
+
this.notifyChange = listener;
|
|
41
|
+
}
|
|
42
|
+
installPlanHandler(ref) {
|
|
43
|
+
ref.current = (plan) => {
|
|
44
|
+
void plan;
|
|
45
|
+
const request = new OwnedRequest(`plan-${++nextRequestId}`, "plan", (r) => {
|
|
46
|
+
if (r.state === "pending")
|
|
47
|
+
return;
|
|
48
|
+
void r;
|
|
49
|
+
this.notifyChange();
|
|
50
|
+
});
|
|
51
|
+
this.requests.set(request.id, request);
|
|
52
|
+
this.notifyChange();
|
|
53
|
+
return request.result.then((decision) => {
|
|
54
|
+
this.requests.delete(request.id);
|
|
55
|
+
return decision;
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
installApprovalHandler(ref) {
|
|
60
|
+
ref.current = (request) => {
|
|
61
|
+
void request;
|
|
62
|
+
const owned = new OwnedRequest(`approval-${++nextRequestId}`, "approval", () => {
|
|
63
|
+
this.notifyChange();
|
|
64
|
+
});
|
|
65
|
+
this.requests.set(owned.id, owned);
|
|
66
|
+
this.notifyChange();
|
|
67
|
+
return owned.result.then((decision) => {
|
|
68
|
+
this.requests.delete(owned.id);
|
|
69
|
+
return decision;
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
adoptQuestionStream() {
|
|
74
|
+
const controller = this.deps.questionController;
|
|
75
|
+
if (!controller || this.questionUnsubscribe)
|
|
76
|
+
return;
|
|
77
|
+
this.questionUnsubscribe = controller.subscribe((event) => {
|
|
78
|
+
if (event.type === "asked") {
|
|
79
|
+
const owned = new OwnedRequest(event.request.id, "question", () => {
|
|
80
|
+
this.notifyChange();
|
|
81
|
+
});
|
|
82
|
+
this.requests.set(owned.id, owned);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.requests.delete(event.request.id);
|
|
86
|
+
}
|
|
87
|
+
this.notifyChange();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
openFeedback(initialDescription) {
|
|
91
|
+
const owned = new OwnedRequest(`feedback-${++nextRequestId}`, "feedback", () => {
|
|
92
|
+
this.notifyChange();
|
|
93
|
+
});
|
|
94
|
+
this.requests.set(owned.id, owned);
|
|
95
|
+
void initialDescription;
|
|
96
|
+
this.notifyChange();
|
|
97
|
+
return owned;
|
|
98
|
+
}
|
|
99
|
+
/** Settle every pending request (session switch, shutdown, replacement). */
|
|
100
|
+
settleAll(via) {
|
|
101
|
+
let settled = 0;
|
|
102
|
+
for (const request of [...this.requests.values()]) {
|
|
103
|
+
if (request.state === "pending") {
|
|
104
|
+
// Resolve the promise (undefined decision) and mark the terminal state.
|
|
105
|
+
request.settle(undefined, via);
|
|
106
|
+
request.state = via === "shutdown" ? "cancelled" : "disposed";
|
|
107
|
+
settled += 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.requests.clear();
|
|
111
|
+
if (settled > 0)
|
|
112
|
+
this.notifyChange();
|
|
113
|
+
return settled;
|
|
114
|
+
}
|
|
115
|
+
/** Drain the question subscription (controller shutdown). */
|
|
116
|
+
dispose() {
|
|
117
|
+
this.questionUnsubscribe?.();
|
|
118
|
+
this.questionUnsubscribe = undefined;
|
|
119
|
+
this.settleAll("shutdown");
|
|
120
|
+
}
|
|
121
|
+
pendingCount() {
|
|
122
|
+
let count = 0;
|
|
123
|
+
for (const request of this.requests.values()) {
|
|
124
|
+
if (request.state === "pending")
|
|
125
|
+
count += 1;
|
|
126
|
+
}
|
|
127
|
+
return count;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment ports for the Bubble TUI controller.
|
|
3
|
+
*
|
|
4
|
+
* Every side effect the controller can trigger is expressed here as an
|
|
5
|
+
* interface so tests can substitute deterministic fakes (spy host) and the
|
|
6
|
+
* production host (Ink adapter today, pi-tui application later) can wire
|
|
7
|
+
* real implementations. The controller layer never imports ink/react/pi-tui.
|
|
8
|
+
*/
|
|
9
|
+
/** Debounced streaming flush (40ms) shared semantics with the legacy TUI. */
|
|
10
|
+
export interface FlushScheduler {
|
|
11
|
+
/** Schedule `flush` after `intervalMs`, merging with any pending flush. */
|
|
12
|
+
scheduleFlush(intervalMs: number, flush: () => void): void;
|
|
13
|
+
/** Drop any pending flush (must run before clearing stream state). */
|
|
14
|
+
cancelFlush(): void;
|
|
15
|
+
}
|
|
16
|
+
export interface Clock {
|
|
17
|
+
now(): number;
|
|
18
|
+
}
|
|
19
|
+
export interface Scheduler {
|
|
20
|
+
setTimeout(callback: () => void, ms: number): Disposable;
|
|
21
|
+
setInterval(callback: () => void, ms: number): Disposable;
|
|
22
|
+
}
|
|
23
|
+
/** Terminal multiplexer detection (tmux/screen need full reprints). */
|
|
24
|
+
export interface TerminalProbe {
|
|
25
|
+
isMultiplexed(): boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Session storage boundary. The host (main.ts switchSession closure today)
|
|
29
|
+
* owns the disk IO and failure semantics; the controller only commits UI
|
|
30
|
+
* state after a successful prepare.
|
|
31
|
+
*/
|
|
32
|
+
export interface SessionHostPort {
|
|
33
|
+
switchSession(file: string): {
|
|
34
|
+
manager: import("../../session.js").SessionManager;
|
|
35
|
+
} | {
|
|
36
|
+
error: string;
|
|
37
|
+
};
|
|
38
|
+
createFresh(cwd: string): {
|
|
39
|
+
manager: import("../../session.js").SessionManager;
|
|
40
|
+
} | {
|
|
41
|
+
error: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export interface GitBranchProbe {
|
|
45
|
+
/** Current git branch for the footer, or undefined outside a repo. */
|
|
46
|
+
currentBranch(cwd: string): string | undefined;
|
|
47
|
+
}
|
|
48
|
+
export interface BubbleTuiPorts {
|
|
49
|
+
clock: Clock;
|
|
50
|
+
scheduler: Scheduler;
|
|
51
|
+
flush: FlushScheduler;
|
|
52
|
+
terminal: TerminalProbe;
|
|
53
|
+
sessionHost: SessionHostPort;
|
|
54
|
+
git: GitBranchProbe;
|
|
55
|
+
/** Best-effort process exit; host decides signal semantics. */
|
|
56
|
+
exitProcess(code: number): void;
|
|
57
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment ports for the Bubble TUI controller.
|
|
3
|
+
*
|
|
4
|
+
* Every side effect the controller can trigger is expressed here as an
|
|
5
|
+
* interface so tests can substitute deterministic fakes (spy host) and the
|
|
6
|
+
* production host (Ink adapter today, pi-tui application later) can wire
|
|
7
|
+
* real implementations. The controller layer never imports ink/react/pi-tui.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session switch as a two-phase transaction (controller extraction §4).
|
|
3
|
+
*
|
|
4
|
+
* prepare (host-owned, may fail): the switchSession/createFresh closures in
|
|
5
|
+
* main.ts:711-759 — disk IO, history reload, agent rebinding.
|
|
6
|
+
* commit (controller-owned, atomic): the applySessionSwitch cleanup list
|
|
7
|
+
* (app.tsx:986-1018), executed inside one transaction so subscribers see
|
|
8
|
+
* exactly two snapshots (before, after) — never a mixed-session state.
|
|
9
|
+
*/
|
|
10
|
+
import type { SessionManager } from "../../session.js";
|
|
11
|
+
import type { InputQueueState } from "./input-queue-machine.js";
|
|
12
|
+
import type { OverlayRequestController } from "./overlay-controller.js";
|
|
13
|
+
import type { ControllerState } from "./state.js";
|
|
14
|
+
import type { SessionHostPort } from "./ports.js";
|
|
15
|
+
import { type DisplayMessage } from "../model/display-history.js";
|
|
16
|
+
export interface SessionTransitionPlan {
|
|
17
|
+
targetFile: string;
|
|
18
|
+
notice?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface SwitchOutcome {
|
|
21
|
+
ok: boolean;
|
|
22
|
+
manager?: SessionManager;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SessionTransitionDeps {
|
|
26
|
+
host: SessionHostPort;
|
|
27
|
+
state: ControllerState;
|
|
28
|
+
overlays: OverlayRequestController;
|
|
29
|
+
queue: InputQueueState;
|
|
30
|
+
agent: {
|
|
31
|
+
getMessages(): readonly import("../../types.js").Message[];
|
|
32
|
+
setSessionID(file: string): void;
|
|
33
|
+
};
|
|
34
|
+
/** Bump to invalidate stale external-runtime events. */
|
|
35
|
+
bumpExternalGeneration(): void;
|
|
36
|
+
clearLiveSubagentTools(): void;
|
|
37
|
+
/** Apply every controller-owned mirror inside the atomic commit. */
|
|
38
|
+
commit(manager: SessionManager, transcript: DisplayMessage[]): void;
|
|
39
|
+
}
|
|
40
|
+
export declare class SessionTransitionController {
|
|
41
|
+
private readonly deps;
|
|
42
|
+
constructor(deps: SessionTransitionDeps);
|
|
43
|
+
/**
|
|
44
|
+
* Full switch: host prepare, then atomic commit. On prepare failure the
|
|
45
|
+
* previous session is untouched and no notification fires.
|
|
46
|
+
*/
|
|
47
|
+
switchTo(plan: SessionTransitionPlan): SwitchOutcome;
|
|
48
|
+
/** Create and enter a new empty session through the same transaction. */
|
|
49
|
+
createFresh(cwd: string, notice?: string): SwitchOutcome;
|
|
50
|
+
/** Atomic commit — the twelve-item cleanup list from the design doc §4.2. */
|
|
51
|
+
private commitSwitch;
|
|
52
|
+
/** Rebuild the transcript rows for a freshly committed session. */
|
|
53
|
+
buildTranscript(notice?: string, queuedDisplayKeys?: Set<string>): DisplayMessage[];
|
|
54
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { queuedAndPendingDisplayKeys } from "../model/input-queue.js";
|
|
2
|
+
import { reconstructDisplayMessages } from "../model/display-reconstruct.js";
|
|
3
|
+
import { nextDisplayMessageKey } from "../model/display-history.js";
|
|
4
|
+
export class SessionTransitionController {
|
|
5
|
+
deps;
|
|
6
|
+
constructor(deps) {
|
|
7
|
+
this.deps = deps;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Full switch: host prepare, then atomic commit. On prepare failure the
|
|
11
|
+
* previous session is untouched and no notification fires.
|
|
12
|
+
*/
|
|
13
|
+
switchTo(plan) {
|
|
14
|
+
const result = this.deps.host.switchSession(plan.targetFile);
|
|
15
|
+
if ("error" in result) {
|
|
16
|
+
return { ok: false, error: result.error };
|
|
17
|
+
}
|
|
18
|
+
this.commitSwitch(result.manager, plan.notice);
|
|
19
|
+
return { ok: true, manager: result.manager };
|
|
20
|
+
}
|
|
21
|
+
/** Create and enter a new empty session through the same transaction. */
|
|
22
|
+
createFresh(cwd, notice) {
|
|
23
|
+
const result = this.deps.host.createFresh(cwd);
|
|
24
|
+
if ("error" in result) {
|
|
25
|
+
return { ok: false, error: result.error };
|
|
26
|
+
}
|
|
27
|
+
this.commitSwitch(result.manager, notice);
|
|
28
|
+
return { ok: true, manager: result.manager };
|
|
29
|
+
}
|
|
30
|
+
/** Atomic commit — the twelve-item cleanup list from the design doc §4.2. */
|
|
31
|
+
commitSwitch(manager, notice) {
|
|
32
|
+
// Snapshot the keys to filter BEFORE purging (the queue is part of state).
|
|
33
|
+
const queuedDisplayKeys = queuedAndPendingDisplayKeys(this.deps.queue.queued, this.deps.queue.pendingSteers.values());
|
|
34
|
+
const transcript = this.buildTranscript(notice, queuedDisplayKeys);
|
|
35
|
+
this.deps.state.withTransaction(() => {
|
|
36
|
+
// 1. Invalidate late external-runtime events.
|
|
37
|
+
this.deps.bumpExternalGeneration();
|
|
38
|
+
// 3. Purge queue/steer state.
|
|
39
|
+
this.deps.queue.queued.length = 0;
|
|
40
|
+
this.deps.queue.pendingSteers.clear();
|
|
41
|
+
// 6. Rebind the session and the agent's session id.
|
|
42
|
+
this.deps.agent.setSessionID(manager.getSessionFile());
|
|
43
|
+
// 7. External binding refresh comes from the new manager's metadata.
|
|
44
|
+
void manager.getMetadata().externalRuntime;
|
|
45
|
+
// 8. Drop live subagent accumulators (ghost-group defense).
|
|
46
|
+
this.deps.clearLiveSubagentTools();
|
|
47
|
+
// 11. Settle every blocking request (behavior delta vs legacy).
|
|
48
|
+
this.deps.overlays.settleAll("session-switch");
|
|
49
|
+
// 9. Replace the entire renderer-facing history. The host has already
|
|
50
|
+
// rebound Agent.messages, so this projects the NEW session rather than
|
|
51
|
+
// appending a notice to the previous session's transcript.
|
|
52
|
+
this.deps.commit(manager, transcript);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/** Rebuild the transcript rows for a freshly committed session. */
|
|
56
|
+
buildTranscript(notice, queuedDisplayKeys) {
|
|
57
|
+
const rows = reconstructDisplayMessages([...this.deps.agent.getMessages()])
|
|
58
|
+
.filter((message) => !queuedDisplayKeys?.has(message.key ?? ""));
|
|
59
|
+
return notice
|
|
60
|
+
? [...rows, {
|
|
61
|
+
key: nextDisplayMessageKey("notice"),
|
|
62
|
+
role: "assistant",
|
|
63
|
+
content: notice,
|
|
64
|
+
syntheticKind: "ui_notice",
|
|
65
|
+
}]
|
|
66
|
+
: rows;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mutable container for all controller-owned state. Single-writer: only the
|
|
3
|
+
* controller mutates; readers get immutable snapshots (snapshot.ts).
|
|
4
|
+
* `withTransaction` batches mutations into one snapshot + one notification.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ControllerState {
|
|
7
|
+
private transactionDepth;
|
|
8
|
+
private dirty;
|
|
9
|
+
/** Bump on every committed change; consumers use it for cache invalidation. */
|
|
10
|
+
version: number;
|
|
11
|
+
withTransaction<T>(fn: () => T): T;
|
|
12
|
+
/** Mark mutated; version advances when the outermost transaction exits. */
|
|
13
|
+
touch(): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mutable container for all controller-owned state. Single-writer: only the
|
|
3
|
+
* controller mutates; readers get immutable snapshots (snapshot.ts).
|
|
4
|
+
* `withTransaction` batches mutations into one snapshot + one notification.
|
|
5
|
+
*/
|
|
6
|
+
export class ControllerState {
|
|
7
|
+
transactionDepth = 0;
|
|
8
|
+
dirty = false;
|
|
9
|
+
/** Bump on every committed change; consumers use it for cache invalidation. */
|
|
10
|
+
version = 0;
|
|
11
|
+
withTransaction(fn) {
|
|
12
|
+
this.transactionDepth += 1;
|
|
13
|
+
try {
|
|
14
|
+
const result = fn();
|
|
15
|
+
this.transactionDepth -= 1;
|
|
16
|
+
if (this.transactionDepth === 0 && this.dirty) {
|
|
17
|
+
this.dirty = false;
|
|
18
|
+
this.version += 1;
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
this.transactionDepth -= 1;
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Mark mutated; version advances when the outermost transaction exits. */
|
|
28
|
+
touch() {
|
|
29
|
+
if (this.transactionDepth > 0) {
|
|
30
|
+
this.dirty = true;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
this.version += 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task/goal/loop runtime orchestration (controller extraction §5,
|
|
3
|
+
* task-runtime-controller row).
|
|
4
|
+
*
|
|
5
|
+
* Owns the process-manager wiring from app.tsx:2220-2350:
|
|
6
|
+
* - owner-session capture so task_started/finished markers land in the
|
|
7
|
+
* spawning session regardless of the currently bound one
|
|
8
|
+
* - completion announcements for the current session
|
|
9
|
+
* - wake coalescing with fire-time gates (running turn / queued input /
|
|
10
|
+
* exit suppress the wake; the state-change reminder carries it instead)
|
|
11
|
+
* - held completions for non-current sessions replayed on switch-back
|
|
12
|
+
* - loop scheduling (defer-not-stack) and goal continuation stay
|
|
13
|
+
* host-injected run launchers — this class only owns timing and gates.
|
|
14
|
+
*/
|
|
15
|
+
import type { BackgroundTaskInfo } from "../../tasks/manager.js";
|
|
16
|
+
export interface TaskRuntimeDeps {
|
|
17
|
+
readonly processManager: {
|
|
18
|
+
listTasks(sessionFile?: string): BackgroundTaskInfo[];
|
|
19
|
+
getTask?(id: string): BackgroundTaskInfo | undefined;
|
|
20
|
+
onChange(listener: (task: BackgroundTaskInfo) => void): () => void;
|
|
21
|
+
onTaskFinished(listener: (task: BackgroundTaskInfo) => void): () => void;
|
|
22
|
+
taskOutputTail(id: string, maxBytes: number): string | undefined;
|
|
23
|
+
markTaskDelivered(id: string): void;
|
|
24
|
+
};
|
|
25
|
+
getSessionFile(): string | undefined;
|
|
26
|
+
appendMarker(file: string, marker: string, payload: string): void;
|
|
27
|
+
announceCompletion(task: BackgroundTaskInfo): void;
|
|
28
|
+
/** Hidden task-wake submission (host wires to the run launcher). */
|
|
29
|
+
submitTaskWake(summary: string): void;
|
|
30
|
+
readonly tasksAutoResume: boolean;
|
|
31
|
+
/** Live gates evaluated at wake-fire time. */
|
|
32
|
+
gates(): {
|
|
33
|
+
turnRunning: boolean;
|
|
34
|
+
queuedInputs: number;
|
|
35
|
+
exiting: boolean;
|
|
36
|
+
goalActive?: boolean;
|
|
37
|
+
};
|
|
38
|
+
readonly wakeDebounceMs?: number;
|
|
39
|
+
}
|
|
40
|
+
export declare class TaskRuntimeController {
|
|
41
|
+
private readonly deps;
|
|
42
|
+
private readonly ownerSessions;
|
|
43
|
+
private readonly pendingCompletions;
|
|
44
|
+
private readonly deferredWake;
|
|
45
|
+
private readonly wakeCoalescer;
|
|
46
|
+
private readonly unsubscribers;
|
|
47
|
+
private disposed;
|
|
48
|
+
constructor(deps: TaskRuntimeDeps);
|
|
49
|
+
start(): void;
|
|
50
|
+
dispose(): void;
|
|
51
|
+
snapshot(): BackgroundTaskInfo[];
|
|
52
|
+
/** Switch-back sweep: replay completions held for the now-current session. */
|
|
53
|
+
releaseHeldCompletions(sessionFile: string): BackgroundTaskInfo[];
|
|
54
|
+
/** Re-evaluate completions that landed while a turn, queue, or Goal owned the loop. */
|
|
55
|
+
onIdle(): void;
|
|
56
|
+
/** Snapshot results that the next beforeTurn hook is expected to inject. */
|
|
57
|
+
captureCurrentUndeliveredIds(): string[];
|
|
58
|
+
/** A provider turn_start confirms its beforeTurn hook accepted the snapshot. */
|
|
59
|
+
markResultsDelivered(ids: readonly string[]): void;
|
|
60
|
+
/** Persist tasks reaped after the UI controller has already stopped. */
|
|
61
|
+
persistTerminalSnapshot(): void;
|
|
62
|
+
private onTaskChange;
|
|
63
|
+
private onTaskFinished;
|
|
64
|
+
private persistTerminalMarker;
|
|
65
|
+
private fireWake;
|
|
66
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { TaskWakeCoalescer, shouldFireTaskWake, taskEligibleForWake, formatTaskWakeSummary } from "../../tasks/wake.js";
|
|
2
|
+
export class TaskRuntimeController {
|
|
3
|
+
deps;
|
|
4
|
+
ownerSessions = new Map();
|
|
5
|
+
pendingCompletions = new Map();
|
|
6
|
+
deferredWake = new Map();
|
|
7
|
+
wakeCoalescer;
|
|
8
|
+
unsubscribers = [];
|
|
9
|
+
disposed = false;
|
|
10
|
+
constructor(deps) {
|
|
11
|
+
this.deps = deps;
|
|
12
|
+
this.wakeCoalescer = new TaskWakeCoalescer(deps.wakeDebounceMs ?? 500, (tasks) => this.fireWake(tasks));
|
|
13
|
+
}
|
|
14
|
+
start() {
|
|
15
|
+
this.unsubscribers.push(this.deps.processManager.onChange((task) => this.onTaskChange(task)), this.deps.processManager.onTaskFinished((task) => this.onTaskFinished(task)));
|
|
16
|
+
// A manager can already own a task when the renderer/controller is
|
|
17
|
+
// recreated. Capture it exactly as a newly emitted running change.
|
|
18
|
+
for (const task of this.deps.processManager.listTasks(this.deps.getSessionFile())) {
|
|
19
|
+
this.onTaskChange(task);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
dispose() {
|
|
23
|
+
this.disposed = true;
|
|
24
|
+
for (const unsubscribe of this.unsubscribers)
|
|
25
|
+
unsubscribe();
|
|
26
|
+
this.unsubscribers.length = 0;
|
|
27
|
+
this.wakeCoalescer.cancel();
|
|
28
|
+
this.deferredWake.clear();
|
|
29
|
+
}
|
|
30
|
+
snapshot() {
|
|
31
|
+
return this.deps.processManager.listTasks(this.deps.getSessionFile());
|
|
32
|
+
}
|
|
33
|
+
/** Switch-back sweep: replay completions held for the now-current session. */
|
|
34
|
+
releaseHeldCompletions(sessionFile) {
|
|
35
|
+
const held = this.pendingCompletions.get(sessionFile);
|
|
36
|
+
if (!held?.length)
|
|
37
|
+
return [];
|
|
38
|
+
this.pendingCompletions.delete(sessionFile);
|
|
39
|
+
for (const task of held) {
|
|
40
|
+
this.deps.announceCompletion(task);
|
|
41
|
+
if (taskEligibleForWake(task))
|
|
42
|
+
this.wakeCoalescer.add(task);
|
|
43
|
+
}
|
|
44
|
+
return held;
|
|
45
|
+
}
|
|
46
|
+
/** Re-evaluate completions that landed while a turn, queue, or Goal owned the loop. */
|
|
47
|
+
onIdle() {
|
|
48
|
+
if (this.deferredWake.size === 0)
|
|
49
|
+
return;
|
|
50
|
+
const tasks = [...this.deferredWake.values()];
|
|
51
|
+
this.deferredWake.clear();
|
|
52
|
+
this.fireWake(tasks);
|
|
53
|
+
}
|
|
54
|
+
/** Snapshot results that the next beforeTurn hook is expected to inject. */
|
|
55
|
+
captureCurrentUndeliveredIds() {
|
|
56
|
+
const current = this.deps.getSessionFile();
|
|
57
|
+
return this.deps.processManager.listTasks(current)
|
|
58
|
+
.filter((task) => taskEligibleForWake(task) && task.deliveredAt === undefined)
|
|
59
|
+
.map((task) => task.id);
|
|
60
|
+
}
|
|
61
|
+
/** A provider turn_start confirms its beforeTurn hook accepted the snapshot. */
|
|
62
|
+
markResultsDelivered(ids) {
|
|
63
|
+
for (const id of ids) {
|
|
64
|
+
const task = this.deps.processManager.getTask?.(id);
|
|
65
|
+
if (task && taskEligibleForWake(task) && task.deliveredAt === undefined) {
|
|
66
|
+
this.deps.processManager.markTaskDelivered(id);
|
|
67
|
+
}
|
|
68
|
+
this.deferredWake.delete(id);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Persist tasks reaped after the UI controller has already stopped. */
|
|
72
|
+
persistTerminalSnapshot() {
|
|
73
|
+
for (const task of this.deps.processManager.listTasks()) {
|
|
74
|
+
if (task.status !== "running")
|
|
75
|
+
this.persistTerminalMarker(task);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
onTaskChange(task) {
|
|
79
|
+
if (task.status !== "running" || this.ownerSessions.has(task.id))
|
|
80
|
+
return;
|
|
81
|
+
const current = this.deps.getSessionFile();
|
|
82
|
+
if (!current || task.ownerSessionId !== current)
|
|
83
|
+
return;
|
|
84
|
+
this.ownerSessions.set(task.id, current);
|
|
85
|
+
this.deps.appendMarker(current, "task_started", JSON.stringify({
|
|
86
|
+
id: task.id,
|
|
87
|
+
pid: task.pid,
|
|
88
|
+
startedAt: task.startedAt,
|
|
89
|
+
command: task.command,
|
|
90
|
+
description: task.description,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
onTaskFinished(task) {
|
|
94
|
+
this.persistTerminalMarker(task);
|
|
95
|
+
const currentFile = this.deps.getSessionFile();
|
|
96
|
+
if (task.ownerSessionId !== currentFile) {
|
|
97
|
+
if (task.ownerSessionId) {
|
|
98
|
+
const held = this.pendingCompletions.get(task.ownerSessionId) ?? [];
|
|
99
|
+
if (!held.some((candidate) => candidate.id === task.id))
|
|
100
|
+
held.push(task);
|
|
101
|
+
this.pendingCompletions.set(task.ownerSessionId, held);
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.deps.announceCompletion(task);
|
|
106
|
+
if (taskEligibleForWake(task))
|
|
107
|
+
this.wakeCoalescer.add(task);
|
|
108
|
+
}
|
|
109
|
+
persistTerminalMarker(task) {
|
|
110
|
+
const ownerFile = this.ownerSessions.get(task.id);
|
|
111
|
+
if (ownerFile) {
|
|
112
|
+
this.deps.appendMarker(ownerFile, task.status === "killed" ? "task_killed" : "task_finished", JSON.stringify({
|
|
113
|
+
id: task.id,
|
|
114
|
+
status: task.status,
|
|
115
|
+
exitCode: task.exitCode ?? null,
|
|
116
|
+
command: task.command,
|
|
117
|
+
description: task.description,
|
|
118
|
+
startedAt: task.startedAt,
|
|
119
|
+
endedAt: task.endedAt,
|
|
120
|
+
outputLines: task.outputLines,
|
|
121
|
+
output: this.deps.processManager.taskOutputTail(task.id, 12_000),
|
|
122
|
+
}));
|
|
123
|
+
this.ownerSessions.delete(task.id);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
fireWake(tasks) {
|
|
127
|
+
if (this.disposed)
|
|
128
|
+
return;
|
|
129
|
+
if (this.deps.tasksAutoResume === false)
|
|
130
|
+
return;
|
|
131
|
+
const currentFile = this.deps.getSessionFile();
|
|
132
|
+
const eligible = tasks
|
|
133
|
+
.map((task) => this.deps.processManager.getTask?.(task.id) ?? task)
|
|
134
|
+
.filter((task) => task.ownerSessionId === currentFile)
|
|
135
|
+
.filter((task) => taskEligibleForWake(task) && task.deliveredAt === undefined);
|
|
136
|
+
if (eligible.length === 0)
|
|
137
|
+
return;
|
|
138
|
+
const gates = this.deps.gates();
|
|
139
|
+
if (!shouldFireTaskWake({
|
|
140
|
+
autoResume: true,
|
|
141
|
+
turnRunning: gates.turnRunning,
|
|
142
|
+
queuedInputs: gates.queuedInputs,
|
|
143
|
+
exiting: gates.exiting,
|
|
144
|
+
}) || gates.goalActive) {
|
|
145
|
+
if (!gates.exiting) {
|
|
146
|
+
for (const task of eligible)
|
|
147
|
+
this.deferredWake.set(task.id, task);
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const summary = formatTaskWakeSummary(eligible, (id) => this.deps.processManager.taskOutputTail(id, 2000));
|
|
152
|
+
for (const task of eligible) {
|
|
153
|
+
this.deps.processManager.markTaskDelivered(task.id);
|
|
154
|
+
this.deferredWake.delete(task.id);
|
|
155
|
+
}
|
|
156
|
+
this.deps.submitTaskWake(summary);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type Component } from "@bubblebrain-ai/pi-tui";
|
|
2
|
+
import type { PermissionMode } from "../types.js";
|
|
3
|
+
import { type Theme } from "./model/theme.js";
|
|
4
|
+
export interface FooterAgentInfo {
|
|
5
|
+
model: string;
|
|
6
|
+
getContextUsageSnapshot(): {
|
|
7
|
+
usedTokens: number;
|
|
8
|
+
contextWindow?: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export interface FooterRenderOptions {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
branch?: string;
|
|
14
|
+
sessionTitle?: string;
|
|
15
|
+
/** External runtimes own model/context state and replace native details. */
|
|
16
|
+
runtimeLabel?: string;
|
|
17
|
+
extra?: readonly string[];
|
|
18
|
+
mode?: PermissionMode;
|
|
19
|
+
/** Persistent autonomous Goal status, rendered on its own muted row. */
|
|
20
|
+
goalLine?: string;
|
|
21
|
+
theme?: Theme;
|
|
22
|
+
}
|
|
23
|
+
export interface ResponsiveFooterSnapshot extends FooterRenderOptions {
|
|
24
|
+
agent: FooterAgentInfo;
|
|
25
|
+
hidden?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Width-responsive single-row footer shared by main and fullscreen TUIs. */
|
|
28
|
+
export declare class ResponsiveFooterComponent implements Component {
|
|
29
|
+
private readonly getSnapshot;
|
|
30
|
+
constructor(getSnapshot: () => ResponsiveFooterSnapshot);
|
|
31
|
+
render(width: number): string[];
|
|
32
|
+
invalidate(): void;
|
|
33
|
+
}
|
|
34
|
+
export declare function renderFooterLine(agent: FooterAgentInfo, columns: number, options?: FooterRenderOptions): string;
|
|
35
|
+
/** Match the legacy footer contract for persisted external-runtime sessions. */
|
|
36
|
+
export declare function formatExternalRuntimeFooterLabel(binding: unknown): string | undefined;
|
|
37
|
+
export declare function renderPermissionModeBadge(mode?: PermissionMode): string;
|