@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,80 @@
|
|
|
1
|
+
/** Shared footer line renderer (main + fullscreen modes). */
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { truncateToWidth } from "@bubblebrain-ai/pi-tui";
|
|
4
|
+
import { formatContextUsageLabel, friendlyCwd } from "./formatting/summary.js";
|
|
5
|
+
import { PERMISSION_MODE_INFO } from "../permission/mode.js";
|
|
6
|
+
import { classifyExternalRuntimeBinding } from "../external-runtime/session-policy.js";
|
|
7
|
+
import { darkTheme } from "./model/theme.js";
|
|
8
|
+
import { themeDim, themeForeground } from "./model/theme-style.js";
|
|
9
|
+
/** Width-responsive single-row footer shared by main and fullscreen TUIs. */
|
|
10
|
+
export class ResponsiveFooterComponent {
|
|
11
|
+
getSnapshot;
|
|
12
|
+
constructor(getSnapshot) {
|
|
13
|
+
this.getSnapshot = getSnapshot;
|
|
14
|
+
}
|
|
15
|
+
render(width) {
|
|
16
|
+
const snapshot = this.getSnapshot();
|
|
17
|
+
if (snapshot.hidden)
|
|
18
|
+
return [];
|
|
19
|
+
const rows = [];
|
|
20
|
+
const theme = snapshot.theme ?? darkTheme;
|
|
21
|
+
const muted = snapshot.theme ? (text) => themeDim(theme.dim, text) : chalk.dim;
|
|
22
|
+
if (snapshot.goalLine?.trim()) {
|
|
23
|
+
rows.push(truncateToWidth(muted(snapshot.goalLine.trim()), Math.max(1, Math.floor(width))));
|
|
24
|
+
}
|
|
25
|
+
if (snapshot.runtimeLabel?.trim()) {
|
|
26
|
+
rows.push(truncateToWidth(snapshot.theme ? themeForeground(theme.accent, snapshot.runtimeLabel.trim()) : chalk.cyan(snapshot.runtimeLabel.trim()), Math.max(1, Math.floor(width))));
|
|
27
|
+
}
|
|
28
|
+
rows.push(renderFooterLine(snapshot.agent, width, snapshot));
|
|
29
|
+
return rows;
|
|
30
|
+
}
|
|
31
|
+
invalidate() {
|
|
32
|
+
// No cache: terminal width, model, cwd, usage, and queue badges are live.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function renderFooterLine(agent, columns, options = {}) {
|
|
36
|
+
const theme = options.theme ?? darkTheme;
|
|
37
|
+
const muted = options.theme ? (text) => themeDim(theme.dim, text) : chalk.dim;
|
|
38
|
+
const usage = formatContextUsageLabel(agent.getContextUsageSnapshot());
|
|
39
|
+
const cwd = options.cwd ?? friendlyCwd(process.cwd());
|
|
40
|
+
const mode = renderPermissionModeBadge(options.mode);
|
|
41
|
+
const nativeDetails = !options.runtimeLabel?.trim();
|
|
42
|
+
const parts = [
|
|
43
|
+
...(mode ? [mode] : []),
|
|
44
|
+
...(nativeDetails && agent.model ? [muted(agent.model)] : []),
|
|
45
|
+
muted(cwd),
|
|
46
|
+
...(options.branch?.trim() ? [muted(options.branch.trim())] : []),
|
|
47
|
+
...(nativeDetails && options.sessionTitle?.trim() ? [muted(options.sessionTitle.trim())] : []),
|
|
48
|
+
...(nativeDetails && usage ? [muted(usage)] : []),
|
|
49
|
+
...(options.extra ?? []),
|
|
50
|
+
];
|
|
51
|
+
const line = parts.join(muted(" │ "));
|
|
52
|
+
return truncateToWidth(line, Math.max(1, Math.floor(columns)));
|
|
53
|
+
}
|
|
54
|
+
/** Match the legacy footer contract for persisted external-runtime sessions. */
|
|
55
|
+
export function formatExternalRuntimeFooterLabel(binding) {
|
|
56
|
+
const kind = classifyExternalRuntimeBinding(binding);
|
|
57
|
+
if (kind === "none")
|
|
58
|
+
return undefined;
|
|
59
|
+
if (kind === "unsupported")
|
|
60
|
+
return "Unsupported external runtime · recovery-only";
|
|
61
|
+
const record = binding && typeof binding === "object"
|
|
62
|
+
? binding
|
|
63
|
+
: undefined;
|
|
64
|
+
const model = typeof record?.modelId === "string" && record.modelId.trim()
|
|
65
|
+
? record.modelId.trim()
|
|
66
|
+
: undefined;
|
|
67
|
+
const effort = typeof record?.reasoningEffort === "string"
|
|
68
|
+
&& record.reasoningEffort.trim()
|
|
69
|
+
&& record.reasoningEffort !== "off"
|
|
70
|
+
? record.reasoningEffort.trim()
|
|
71
|
+
: undefined;
|
|
72
|
+
return ["Grok Subscription", model, effort, "workspace"].filter(Boolean).join(" · ");
|
|
73
|
+
}
|
|
74
|
+
export function renderPermissionModeBadge(mode) {
|
|
75
|
+
if (!mode || mode === "default")
|
|
76
|
+
return "";
|
|
77
|
+
const info = PERMISSION_MODE_INFO[mode];
|
|
78
|
+
const label = `${info.symbol ? `${info.symbol} ` : ""}${info.shortTitle} on`;
|
|
79
|
+
return mode === "bypassPermissions" ? chalk.bold.red(label) : chalk.bold.cyan(label);
|
|
80
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Agent } from "
|
|
2
|
-
import { type ProviderRegistry } from "
|
|
3
|
-
import type { BackgroundTaskInfo } from "
|
|
4
|
-
import { type DisplayMessage } from "
|
|
1
|
+
import type { Agent } from "../../agent.js";
|
|
2
|
+
import { type ProviderRegistry } from "../../provider-registry.js";
|
|
3
|
+
import type { BackgroundTaskInfo } from "../../tasks/manager.js";
|
|
4
|
+
import { type DisplayMessage } from "../model/display-history.js";
|
|
5
5
|
export declare const TASK_WAKE_DEBOUNCE_MS = 2000;
|
|
6
6
|
export declare function buildTips(agent: Agent, registry: ProviderRegistry, grokActive?: boolean): string[];
|
|
7
7
|
/**
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* clamp shared by the picker overlays.
|
|
6
6
|
*/
|
|
7
7
|
import os from "node:os";
|
|
8
|
-
import { displayModel } from "
|
|
9
|
-
import { nextDisplayMessageKey } from "
|
|
8
|
+
import { displayModel } from "../../provider-registry.js";
|
|
9
|
+
import { nextDisplayMessageKey } from "../model/display-history.js";
|
|
10
10
|
export const TASK_WAKE_DEBOUNCE_MS = 2000;
|
|
11
11
|
export function buildTips(agent, registry, grokActive = false) {
|
|
12
12
|
const tips = [];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type Terminal } from "@bubblebrain-ai/pi-tui";
|
|
2
|
+
import type { BubbleTuiController } from "./controller/controller.js";
|
|
3
|
+
import type { Agent } from "../agent.js";
|
|
4
|
+
import { TraceInteractionState } from "./model/trace-interaction.js";
|
|
5
|
+
import type { ComposerController } from "./controller/composer-controller.js";
|
|
6
|
+
import { type Theme } from "./model/theme.js";
|
|
7
|
+
export interface FullscreenAppOptions {
|
|
8
|
+
controller: BubbleTuiController;
|
|
9
|
+
agent: Pick<Agent, "model" | "mode" | "setMode" | "getContextUsageSnapshot">;
|
|
10
|
+
onExit(): void;
|
|
11
|
+
/** Route non-mode slash commands through the main app's shared registry. */
|
|
12
|
+
onCommand(command: string): void;
|
|
13
|
+
/** Test/embedded host injection; production uses ProcessTerminal. */
|
|
14
|
+
terminal?: Terminal;
|
|
15
|
+
/** Preserve tool-group folds when switching from the regular renderer. */
|
|
16
|
+
traceInteraction?: TraceInteractionState;
|
|
17
|
+
/** Shared semantic composer state when transitioning from the main renderer. */
|
|
18
|
+
composer?: ComposerController;
|
|
19
|
+
/** Shared live palette when this view is entered from the regular renderer. */
|
|
20
|
+
getTheme?: () => Theme;
|
|
21
|
+
}
|
|
22
|
+
export declare class FullscreenApp {
|
|
23
|
+
private readonly options;
|
|
24
|
+
private readonly tui;
|
|
25
|
+
private readonly transcript;
|
|
26
|
+
private readonly streamingMessage;
|
|
27
|
+
private readonly animationClock;
|
|
28
|
+
private readonly editor;
|
|
29
|
+
private readonly composerPreview?;
|
|
30
|
+
private readonly footer;
|
|
31
|
+
private readonly traceInteraction;
|
|
32
|
+
private readonly markdown;
|
|
33
|
+
private readonly transcriptTheme;
|
|
34
|
+
private readonly markdownRenderer;
|
|
35
|
+
private readonly unsubscribe;
|
|
36
|
+
private showReasoning;
|
|
37
|
+
private verboseTrace;
|
|
38
|
+
private disposed;
|
|
39
|
+
private streamingMounted;
|
|
40
|
+
constructor(options: FullscreenAppOptions);
|
|
41
|
+
private buildLayout;
|
|
42
|
+
private openImageViewer;
|
|
43
|
+
render(): void;
|
|
44
|
+
private transcriptRenderOptions;
|
|
45
|
+
start(): void;
|
|
46
|
+
dispose(): void;
|
|
47
|
+
waitUntilExit(): Promise<void>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fullscreen (alternate-screen) mode on TuiAltScreen (rewrite/pi-tui).
|
|
3
|
+
*
|
|
4
|
+
* Complements the default main-screen chat flow: instead of appending to
|
|
5
|
+
* scrollback, the whole transcript lives in a viewport with follow-end,
|
|
6
|
+
* mouse-wheel scrolling, click-drag selection, and Ctrl+F transcript search
|
|
7
|
+
* (all provided by TuiAltScreen + ScrollView). The composer stays docked at
|
|
8
|
+
* the bottom via a layout root: [transcript scroll view, editor, footer].
|
|
9
|
+
*
|
|
10
|
+
* Toggle with /fullscreen; Escape exits back to the main screen.
|
|
11
|
+
*/
|
|
12
|
+
import process from "node:process";
|
|
13
|
+
import { ProcessTerminal, TuiAltScreen, VStack, ScrollView, Editor, Markdown, matchesKey, isKeyRelease, } from "@bubblebrain-ai/pi-tui";
|
|
14
|
+
import { ResponsiveTranscriptComponent } from "./components/responsive-transcript.js";
|
|
15
|
+
import { StreamingMessageComponent } from "./components/streaming-message.js";
|
|
16
|
+
import { createTranscriptTheme } from "./components/transcript.js";
|
|
17
|
+
import { ResponsiveFooterComponent } from "./footer.js";
|
|
18
|
+
import { getNextPermissionMode } from "../permission/mode.js";
|
|
19
|
+
import { COMPOSER_EDITOR_OPTIONS, createComposerEditorTheme } from "./composer-style.js";
|
|
20
|
+
import { TraceInteractionState } from "./model/trace-interaction.js";
|
|
21
|
+
import { ComposerImagePreviewComponent, ImageViewerComponent } from "./components/image-preview.js";
|
|
22
|
+
import { createAssistantMarkdownTheme } from "./markdown-style.js";
|
|
23
|
+
import { darkTheme } from "./model/theme.js";
|
|
24
|
+
import { TuiAnimationClock } from "./animation-clock.js";
|
|
25
|
+
export class FullscreenApp {
|
|
26
|
+
options;
|
|
27
|
+
tui;
|
|
28
|
+
transcript;
|
|
29
|
+
streamingMessage;
|
|
30
|
+
animationClock;
|
|
31
|
+
editor;
|
|
32
|
+
composerPreview;
|
|
33
|
+
footer;
|
|
34
|
+
traceInteraction;
|
|
35
|
+
markdown;
|
|
36
|
+
transcriptTheme;
|
|
37
|
+
markdownRenderer = (text, width) => {
|
|
38
|
+
this.markdown.setText(text);
|
|
39
|
+
return this.markdown.render(width);
|
|
40
|
+
};
|
|
41
|
+
unsubscribe;
|
|
42
|
+
showReasoning = false;
|
|
43
|
+
verboseTrace = false;
|
|
44
|
+
disposed = false;
|
|
45
|
+
streamingMounted = false;
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.options = options;
|
|
48
|
+
const terminal = options.terminal ?? new ProcessTerminal();
|
|
49
|
+
const getTheme = options.getTheme ?? (() => darkTheme);
|
|
50
|
+
this.transcriptTheme = createTranscriptTheme(getTheme);
|
|
51
|
+
this.markdown = new Markdown("", 0, 0, createAssistantMarkdownTheme(getTheme));
|
|
52
|
+
this.traceInteraction = options.traceInteraction ?? new TraceInteractionState();
|
|
53
|
+
// Trace hover depends on no-button pointer motion, including inside tmux.
|
|
54
|
+
this.tui = new TuiAltScreen(terminal, undefined, undefined, { mouseMotion: "all" });
|
|
55
|
+
this.editor = new Editor(this.tui, createComposerEditorTheme(getTheme), COMPOSER_EDITOR_OPTIONS);
|
|
56
|
+
this.composerPreview = options.composer
|
|
57
|
+
? new ComposerImagePreviewComponent(() => options.composer?.previewAttachment(), getTheme)
|
|
58
|
+
: undefined;
|
|
59
|
+
this.transcript = new ResponsiveTranscriptComponent(() => ({
|
|
60
|
+
messages: this.options.controller.getTranscript(),
|
|
61
|
+
options: this.transcriptRenderOptions(),
|
|
62
|
+
}), {
|
|
63
|
+
onTraceAction: (action) => {
|
|
64
|
+
if (action.kind !== "open-image")
|
|
65
|
+
return;
|
|
66
|
+
const message = this.options.controller.getTranscript().find((candidate) => candidate.key === action.messageKey);
|
|
67
|
+
const image = message?.images?.find((candidate) => candidate.label === action.imageLabel);
|
|
68
|
+
if (image)
|
|
69
|
+
this.openImageViewer(image);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
this.streamingMessage = new StreamingMessageComponent(8, () => this.tui.requestRender(), undefined, getTheme);
|
|
73
|
+
this.animationClock = new TuiAnimationClock((elapsedMs) => {
|
|
74
|
+
if (this.streamingMessage.advanceAnimationFrame(elapsedMs))
|
|
75
|
+
this.tui.requestRender();
|
|
76
|
+
});
|
|
77
|
+
this.footer = new ResponsiveFooterComponent(() => ({
|
|
78
|
+
agent: this.options.agent,
|
|
79
|
+
mode: this.options.agent.mode,
|
|
80
|
+
goalLine: this.options.controller.getGoalIndicator?.(),
|
|
81
|
+
hidden: this.tui.terminal.rows <= 2,
|
|
82
|
+
theme: getTheme(),
|
|
83
|
+
}));
|
|
84
|
+
this.buildLayout();
|
|
85
|
+
this.unsubscribe = this.options.controller.subscribe(() => this.render());
|
|
86
|
+
}
|
|
87
|
+
buildLayout() {
|
|
88
|
+
// The live tail belongs inside the scrolling transcript. Its activity lane
|
|
89
|
+
// stays docked above the composer and keeps one row both running and idle,
|
|
90
|
+
// so clearing the spinner cannot pull settled content downward.
|
|
91
|
+
const transcriptBody = new VStack([this.transcript, this.streamingMessage]);
|
|
92
|
+
const scroll = new ScrollView(transcriptBody, { follow: "end", primary: true });
|
|
93
|
+
const layout = new VStack([
|
|
94
|
+
{ component: scroll, basis: 0, grow: 1, minSize: 0 },
|
|
95
|
+
{ component: this.streamingMessage.activityLane, basis: "auto", shrink: 0 },
|
|
96
|
+
...(this.composerPreview ? [{ component: this.composerPreview, basis: "auto", shrink: 0 }] : []),
|
|
97
|
+
{ component: this.editor, basis: "auto", shrink: 0 },
|
|
98
|
+
{ component: this.footer, basis: "auto", shrink: 0 },
|
|
99
|
+
]);
|
|
100
|
+
this.tui.setLayoutRoot(layout);
|
|
101
|
+
this.tui.setFocus(this.editor);
|
|
102
|
+
if (this.options.composer) {
|
|
103
|
+
this.options.composer.attachEditor(this.editor);
|
|
104
|
+
this.options.composer.setOpenImageHandler((image) => this.openImageViewer(image));
|
|
105
|
+
}
|
|
106
|
+
else
|
|
107
|
+
this.editor.onSubmit = (text) => {
|
|
108
|
+
const trimmed = text.trim();
|
|
109
|
+
if (!trimmed)
|
|
110
|
+
return;
|
|
111
|
+
this.editor.addToHistory(trimmed);
|
|
112
|
+
if (trimmed === "/fullscreen" || trimmed === "/main") {
|
|
113
|
+
this.options.onExit();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (trimmed.startsWith("/")) {
|
|
117
|
+
this.options.onCommand(trimmed);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (this.options.controller.isRunning()) {
|
|
121
|
+
this.options.controller.steer(trimmed);
|
|
122
|
+
}
|
|
123
|
+
else if (this.options.controller.queueAfterCommand?.(trimmed)) {
|
|
124
|
+
this.render();
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
this.options.controller.appendDisplayMessage({ key: `user-${Date.now()}`, role: "user", content: trimmed });
|
|
128
|
+
void this.options.controller.runTurn(trimmed, process.cwd());
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
this.tui.addInputListener((data) => {
|
|
132
|
+
// Kitty reports key releases separately. Global shortcuts must only run
|
|
133
|
+
// on the press or Escape would cancel the run and exit on key-up.
|
|
134
|
+
if (isKeyRelease(data))
|
|
135
|
+
return { consume: true };
|
|
136
|
+
if (matchesKey(data, "shift+tab")) {
|
|
137
|
+
this.options.agent.setMode(getNextPermissionMode(this.options.agent.mode));
|
|
138
|
+
this.render();
|
|
139
|
+
return { consume: true };
|
|
140
|
+
}
|
|
141
|
+
if (matchesKey(data, "escape")) {
|
|
142
|
+
if (this.options.controller.cancelActiveRun()) {
|
|
143
|
+
return { consume: true };
|
|
144
|
+
}
|
|
145
|
+
if (this.options.controller.isBusy?.())
|
|
146
|
+
return { consume: true };
|
|
147
|
+
this.options.onExit();
|
|
148
|
+
return { consume: true };
|
|
149
|
+
}
|
|
150
|
+
if (matchesKey(data, "ctrl+c")) {
|
|
151
|
+
if (this.options.controller.cancelActiveRun()) {
|
|
152
|
+
return { consume: true };
|
|
153
|
+
}
|
|
154
|
+
if (this.options.controller.isBusy?.())
|
|
155
|
+
return { consume: true };
|
|
156
|
+
this.options.onExit();
|
|
157
|
+
return { consume: true };
|
|
158
|
+
}
|
|
159
|
+
if (data === "\x14") {
|
|
160
|
+
this.showReasoning = !this.showReasoning;
|
|
161
|
+
this.render();
|
|
162
|
+
return { consume: true };
|
|
163
|
+
}
|
|
164
|
+
if (data === "\x0f") {
|
|
165
|
+
this.verboseTrace = !this.verboseTrace;
|
|
166
|
+
this.render();
|
|
167
|
+
return { consume: true };
|
|
168
|
+
}
|
|
169
|
+
return undefined;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
openImageViewer(image) {
|
|
173
|
+
let handle;
|
|
174
|
+
const close = () => {
|
|
175
|
+
handle?.hide();
|
|
176
|
+
this.tui.setFocus(this.editor);
|
|
177
|
+
this.render();
|
|
178
|
+
};
|
|
179
|
+
const component = new ImageViewerComponent(image, close, () => this.tui.terminal.rows, this.options.getTheme);
|
|
180
|
+
handle = this.tui.showOverlay(component, {
|
|
181
|
+
anchor: "center",
|
|
182
|
+
width: "70%",
|
|
183
|
+
minWidth: 36,
|
|
184
|
+
maxWidth: 110,
|
|
185
|
+
maxHeight: "85%",
|
|
186
|
+
margin: 1,
|
|
187
|
+
dismissOnOutsideClick: true,
|
|
188
|
+
});
|
|
189
|
+
this.tui.setFocus(component);
|
|
190
|
+
}
|
|
191
|
+
render() {
|
|
192
|
+
if (this.disposed)
|
|
193
|
+
return;
|
|
194
|
+
const columns = this.tui.terminal.columns || process.stdout.columns || 80;
|
|
195
|
+
const tail = this.options.controller.isRunning()
|
|
196
|
+
? this.options.controller.getStreamingTail()
|
|
197
|
+
: null;
|
|
198
|
+
const commandActivity = this.options.controller.getCommandActivity?.() ?? null;
|
|
199
|
+
if (tail) {
|
|
200
|
+
if (!this.streamingMounted) {
|
|
201
|
+
this.streamingMounted = true;
|
|
202
|
+
this.streamingMessage.startSpinner();
|
|
203
|
+
}
|
|
204
|
+
this.streamingMessage.noteWidth(columns);
|
|
205
|
+
this.streamingMessage.update(tail, columns, this.transcriptRenderOptions());
|
|
206
|
+
}
|
|
207
|
+
else if (commandActivity) {
|
|
208
|
+
if (!this.streamingMounted) {
|
|
209
|
+
this.streamingMounted = true;
|
|
210
|
+
this.streamingMessage.startSpinner();
|
|
211
|
+
}
|
|
212
|
+
this.streamingMessage.noteWidth(columns);
|
|
213
|
+
this.streamingMessage.updateCommandActivity(commandActivity.kind === "compact" ? "Compacting" : commandActivity.kind, commandActivity.status === "cancelling", columns);
|
|
214
|
+
}
|
|
215
|
+
else if (this.streamingMounted) {
|
|
216
|
+
this.streamingMounted = false;
|
|
217
|
+
this.streamingMessage.clearToNothing();
|
|
218
|
+
}
|
|
219
|
+
this.animationClock.setActive(this.streamingMessage.isAnimationActive());
|
|
220
|
+
this.tui.requestRender();
|
|
221
|
+
}
|
|
222
|
+
transcriptRenderOptions() {
|
|
223
|
+
return {
|
|
224
|
+
theme: this.transcriptTheme,
|
|
225
|
+
showReasoning: this.showReasoning,
|
|
226
|
+
verboseTrace: this.verboseTrace,
|
|
227
|
+
traceInteraction: this.traceInteraction,
|
|
228
|
+
markdownRenderer: this.markdownRenderer,
|
|
229
|
+
// While running, this separates settled history from the live surface.
|
|
230
|
+
// Once settled, the permanent blank activity lane owns the dock gap.
|
|
231
|
+
trailingSpacer: this.options.controller.isRunning(),
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
start() {
|
|
235
|
+
this.tui.start();
|
|
236
|
+
this.render();
|
|
237
|
+
}
|
|
238
|
+
dispose() {
|
|
239
|
+
if (this.disposed)
|
|
240
|
+
return;
|
|
241
|
+
this.disposed = true;
|
|
242
|
+
this.unsubscribe();
|
|
243
|
+
this.animationClock.dispose();
|
|
244
|
+
this.streamingMessage.dispose();
|
|
245
|
+
// Returning to the host/main renderer must not copy the fullscreen dock
|
|
246
|
+
// (composer + footer) into terminal scrollback.
|
|
247
|
+
this.tui.stop({ preserveScreen: true });
|
|
248
|
+
}
|
|
249
|
+
async waitUntilExit() {
|
|
250
|
+
await new Promise(() => {
|
|
251
|
+
// Exit is driven by onExit (Escape/Ctrl+C//fullscreen); the promise
|
|
252
|
+
// resolves via dispose() from the host.
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -16,4 +16,8 @@ export declare function splitImageDisplayContent(content: string): {
|
|
|
16
16
|
referenceLines: string[];
|
|
17
17
|
};
|
|
18
18
|
export declare function formatImageUserDisplayText(input: string, imageCount: number, labelStart?: number): string;
|
|
19
|
+
export declare function displayImagesFromPayload(payload: SubmitPayload): DisplayImageAttachment[];
|
|
20
|
+
export declare function imageAttachmentFromDataUrl(url: string): ImageAttachment | undefined;
|
|
19
21
|
export declare function nextImageDisplayLabelStart(messages: Iterable<ImageDisplayMessage>): number;
|
|
22
|
+
import type { SubmitPayload } from "./model/composer-types.js";
|
|
23
|
+
import type { DisplayImageAttachment, ImageAttachment } from "./model/image-attachment.js";
|
|
@@ -46,18 +46,36 @@ export function formatImageUserDisplayText(input, imageCount, labelStart = 1) {
|
|
|
46
46
|
if (imageCount <= 0)
|
|
47
47
|
return input;
|
|
48
48
|
const labels = imageDisplayLabels(imageCount, labelStart);
|
|
49
|
-
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
...
|
|
60
|
-
|
|
49
|
+
// The composer text is the canonical presentation: if a chip was inserted
|
|
50
|
+
// inline, keep it at that exact position after submit. Reconstructed legacy
|
|
51
|
+
// messages do not contain labels, so only their missing chips fall back to
|
|
52
|
+
// standalone reference rows.
|
|
53
|
+
const missingLabels = labels.filter((label) => !input.includes(label));
|
|
54
|
+
return [input, ...missingLabels.map(imageDisplayReferenceLine)].filter(Boolean).join("\n");
|
|
55
|
+
}
|
|
56
|
+
export function displayImagesFromPayload(payload) {
|
|
57
|
+
const start = payload.imageDisplayStart ?? 1;
|
|
58
|
+
return payload.images.map((attachment, index) => ({
|
|
59
|
+
...attachment,
|
|
60
|
+
label: imageDisplayLabel(start + index),
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
export function imageAttachmentFromDataUrl(url) {
|
|
64
|
+
const match = /^data:([^;,]+);base64,([A-Za-z0-9+/=\r\n]+)$/.exec(url.trim());
|
|
65
|
+
if (!match)
|
|
66
|
+
return undefined;
|
|
67
|
+
const mediaType = match[1].toLowerCase();
|
|
68
|
+
const base64 = match[2].replace(/[\r\n]/g, "");
|
|
69
|
+
if (!mediaType.startsWith("image/"))
|
|
70
|
+
return undefined;
|
|
71
|
+
let bytes = 0;
|
|
72
|
+
try {
|
|
73
|
+
bytes = Buffer.from(base64, "base64").byteLength;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return { base64, mediaType, bytes, dataUrl: `data:${mediaType};base64,${base64}` };
|
|
61
79
|
}
|
|
62
80
|
export function nextImageDisplayLabelStart(messages) {
|
|
63
81
|
let max = 0;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { MarkdownTheme } from "@bubblebrain-ai/pi-tui";
|
|
2
|
+
import { type Theme } from "./model/theme.js";
|
|
3
|
+
/** Shared assistant Markdown styling for every transcript host. */
|
|
4
|
+
export declare function createAssistantMarkdownTheme(getTheme: () => Theme): MarkdownTheme;
|
|
5
|
+
export declare const ASSISTANT_MARKDOWN_THEME: MarkdownTheme;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { darkTheme } from "./model/theme.js";
|
|
3
|
+
import { themeDim, themeForeground } from "./model/theme-style.js";
|
|
4
|
+
/** Shared assistant Markdown styling for every transcript host. */
|
|
5
|
+
export function createAssistantMarkdownTheme(getTheme) {
|
|
6
|
+
return {
|
|
7
|
+
heading: (text) => chalk.bold(themeForeground(getTheme().accent, text)),
|
|
8
|
+
link: (text) => chalk.underline(themeForeground(getTheme().accent, text)),
|
|
9
|
+
linkUrl: (text) => themeDim(getTheme().dim, text),
|
|
10
|
+
code: (text) => themeForeground(getTheme().inlineCode, text),
|
|
11
|
+
codeBlock: (text) => themeForeground(getTheme().agent, text),
|
|
12
|
+
codeBlockBorder: (text) => themeDim(getTheme().border, text),
|
|
13
|
+
quote: (text) => themeDim(getTheme().dim, text),
|
|
14
|
+
quoteBorder: (text) => themeDim(getTheme().border, text),
|
|
15
|
+
hr: (text) => themeDim(getTheme().border, text),
|
|
16
|
+
listBullet: (text) => themeForeground(getTheme().accent, text),
|
|
17
|
+
bold: (text) => chalk.bold(text),
|
|
18
|
+
italic: (text) => chalk.italic(text),
|
|
19
|
+
strikethrough: (text) => chalk.strikethrough(text),
|
|
20
|
+
underline: (text) => chalk.underline(text),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export const ASSISTANT_MARKDOWN_THEME = createAssistantMarkdownTheme(() => darkTheme);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composer submission payload — the bridge type between the composer UI and
|
|
3
|
+
* the agent input path. Lives in the renderer-neutral model layer so the
|
|
4
|
+
* queue state machine can reference it without importing a renderer.
|
|
5
|
+
*/
|
|
6
|
+
import type { ImageAttachment } from "./image-attachment.js";
|
|
7
|
+
export interface SubmitPayload {
|
|
8
|
+
/** Fully-expanded text sent to the agent. */
|
|
9
|
+
text: string;
|
|
10
|
+
/** Text shown in the composer/transcript when it differs from the real text. */
|
|
11
|
+
displayText?: string;
|
|
12
|
+
images: ImageAttachment[];
|
|
13
|
+
/** First UI-only [Image #N] label reserved for this submitted payload. */
|
|
14
|
+
imageDisplayStart?: number;
|
|
15
|
+
/** Harness-initiated submission; runs hidden (task wake path). */
|
|
16
|
+
internal?: "task_wake";
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { Message, ToolResultMetadata } from "
|
|
1
|
+
import type { Message, ToolResultMetadata } from "../../types.js";
|
|
2
|
+
import type { DisplayImageAttachment } from "./image-attachment.js";
|
|
2
3
|
export type UserInputStatus = "queued" | "pending_steer";
|
|
3
4
|
export interface DisplayMessage {
|
|
4
5
|
/** Stable identity, used as the transcript list key. Generated by the UI layer. */
|
|
5
6
|
key?: string;
|
|
6
7
|
role: "user" | "assistant" | "error";
|
|
7
8
|
content: string;
|
|
9
|
+
/** Rich image state retained for chips, preview and session restore. */
|
|
10
|
+
images?: DisplayImageAttachment[];
|
|
8
11
|
/** Correlates queued/steer placeholder rows with their lifecycle events. */
|
|
9
12
|
clientId?: string;
|
|
10
13
|
/** Badge for user input waiting to enter the run (QUEUED / STEER). */
|
|
@@ -50,6 +53,9 @@ export interface DisplayToolCall {
|
|
|
50
53
|
* a command preview.
|
|
51
54
|
*/
|
|
52
55
|
rawArguments?: string;
|
|
56
|
+
/** Live execution state. Result text may be present during a running
|
|
57
|
+
* subagent/tool update, so pending cannot be inferred from `result` alone. */
|
|
58
|
+
status?: "queued" | "pending" | "running" | "completed" | "failed" | "blocked" | "cancelled";
|
|
53
59
|
result?: string;
|
|
54
60
|
isError?: boolean;
|
|
55
61
|
metadata?: ToolResultMetadata;
|
|
@@ -2,14 +2,59 @@
|
|
|
2
2
|
* Rebuilds UI DisplayMessages from the agent's raw transcript — used on
|
|
3
3
|
* initial mount and after transcript rewrites (rewind, resume).
|
|
4
4
|
*/
|
|
5
|
-
import { INTERRUPTED_ASSISTANT_CONTENT } from "
|
|
6
|
-
import { isHiddenToolMetadata } from "
|
|
7
|
-
import { isInternalBlockOnlyContent } from "
|
|
5
|
+
import { INTERRUPTED_ASSISTANT_CONTENT } from "../../agent.js";
|
|
6
|
+
import { isHiddenToolMetadata } from "../../agent/tool-visibility.js";
|
|
7
|
+
import { isInternalBlockOnlyContent } from "../../agent/internal-reminder-sanitizer.js";
|
|
8
|
+
import { COMPACTION_SUMMARY_PREFIX } from "../../context/compact.js";
|
|
8
9
|
import { nextDisplayMessageKey, stripInterruptedAssistantMarker } from "./display-history.js";
|
|
10
|
+
import { synchronizeSubagentSnapshots } from "./subagent-view.js";
|
|
11
|
+
import { formatImageUserDisplayText, imageAttachmentFromDataUrl, imageDisplayLabel } from "../image-display.js";
|
|
12
|
+
function reconstructUserContent(message, imageDisplayStart) {
|
|
13
|
+
const { content } = message;
|
|
14
|
+
if (typeof content === "string") {
|
|
15
|
+
return { text: content, images: [], nextImageDisplayStart: imageDisplayStart };
|
|
16
|
+
}
|
|
17
|
+
const text = content
|
|
18
|
+
.filter((part) => part.type === "text")
|
|
19
|
+
.map((part) => part.text)
|
|
20
|
+
.join("\n")
|
|
21
|
+
.trim();
|
|
22
|
+
const imageCount = content.filter((part) => part.type === "image_url").length;
|
|
23
|
+
const labelStart = message.ui?.imageDisplayStart ?? imageDisplayStart;
|
|
24
|
+
const images = content
|
|
25
|
+
.filter((part) => part.type === "image_url")
|
|
26
|
+
.map((part, index) => {
|
|
27
|
+
const attachment = imageAttachmentFromDataUrl(part.image_url.url);
|
|
28
|
+
return attachment ? { ...attachment, label: imageDisplayLabel(labelStart + index) } : undefined;
|
|
29
|
+
})
|
|
30
|
+
.filter((item) => item !== undefined);
|
|
31
|
+
return {
|
|
32
|
+
text: formatImageUserDisplayText(message.ui?.displayText ?? text, imageCount, labelStart),
|
|
33
|
+
images,
|
|
34
|
+
nextImageDisplayStart: Math.max(imageDisplayStart, labelStart + imageCount),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
9
37
|
export function reconstructDisplayMessages(agentMessages) {
|
|
10
38
|
const result = [];
|
|
39
|
+
let nextImageDisplayStart = 1;
|
|
11
40
|
for (const m of agentMessages) {
|
|
12
|
-
if (m.role === "system"
|
|
41
|
+
if (m.role === "system") {
|
|
42
|
+
const content = typeof m.content === "string" ? m.content : "";
|
|
43
|
+
if (content.startsWith(COMPACTION_SUMMARY_PREFIX)) {
|
|
44
|
+
const summary = content.slice(COMPACTION_SUMMARY_PREFIX.length).trim();
|
|
45
|
+
if (summary) {
|
|
46
|
+
result.push({
|
|
47
|
+
key: nextDisplayMessageKey("compact"),
|
|
48
|
+
role: "assistant",
|
|
49
|
+
content: "Compaction completed.",
|
|
50
|
+
syntheticKind: "ui_compact_summary",
|
|
51
|
+
compactionSummary: summary,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (m.role === "tool")
|
|
13
58
|
continue;
|
|
14
59
|
if (m.role === "user") {
|
|
15
60
|
if (m.isMeta)
|
|
@@ -20,10 +65,13 @@ export function reconstructDisplayMessages(agentMessages) {
|
|
|
20
65
|
// when the transcript is rebuilt.
|
|
21
66
|
if (isInternalBlockOnlyContent(m.content))
|
|
22
67
|
continue;
|
|
68
|
+
const reconstructed = reconstructUserContent(m, nextImageDisplayStart);
|
|
69
|
+
nextImageDisplayStart = reconstructed.nextImageDisplayStart;
|
|
23
70
|
result.push({
|
|
24
71
|
key: nextDisplayMessageKey("user"),
|
|
25
72
|
role: "user",
|
|
26
|
-
content:
|
|
73
|
+
content: reconstructed.text,
|
|
74
|
+
images: reconstructed.images.length > 0 ? reconstructed.images : undefined,
|
|
27
75
|
});
|
|
28
76
|
}
|
|
29
77
|
else if (m.role === "assistant") {
|
|
@@ -78,5 +126,5 @@ export function reconstructDisplayMessages(agentMessages) {
|
|
|
78
126
|
}
|
|
79
127
|
}
|
|
80
128
|
}
|
|
81
|
-
return result;
|
|
129
|
+
return synchronizeSubagentSnapshots(result);
|
|
82
130
|
}
|