@pellux/goodvibes-tui 2.0.13 → 2.0.15
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/.goodvibes/GOODVIBES.md +1 -1
- package/.goodvibes/agents/reviewer.md +8 -8
- package/.goodvibes/skills/add-provider/SKILL.md +22 -22
- package/CHANGELOG.md +61 -0
- package/README.md +40 -29
- package/docs/README.md +1 -1
- package/docs/foundation-artifacts/README.md +5 -5
- package/docs/foundation-artifacts/operator-contract.json +123 -123
- package/package.json +12 -10
- package/scripts/postinstall.js +3 -3
- package/src/audio/activation-sound.ts +7 -7
- package/src/audio/capture.ts +7 -7
- package/src/audio/onnxruntime-assets.d.ts +1 -1
- package/src/audio/player.ts +4 -4
- package/src/audio/spoken-turn-wiring.ts +4 -4
- package/src/audio/voice-capture-wiring.ts +5 -5
- package/src/audio/voice-input-session.ts +3 -3
- package/src/audio/wake-inference.ts +13 -8
- package/src/audio/wake-runtime.ts +10 -10
- package/src/cli/completions/generate.ts +2 -2
- package/src/cli/doctor.ts +13 -13
- package/src/cli/ensure-goodvibes-gitignore.ts +3 -3
- package/src/cli/entrypoint.ts +3 -3
- package/src/cli/help.ts +6 -6
- package/src/cli/hooks-command.ts +4 -4
- package/src/cli/hooks-report.ts +4 -4
- package/src/cli/launch-auto-update.ts +17 -17
- package/src/cli/management-commands.ts +8 -8
- package/src/cli/management-utils.ts +3 -3
- package/src/cli/management.ts +1 -1
- package/src/cli/plugin-bundles-command.ts +10 -10
- package/src/cli/plugin-command.ts +9 -9
- package/src/cli/service-posture.ts +1 -1
- package/src/cli/status.ts +10 -10
- package/src/cli/surface-command.ts +4 -4
- package/src/cli/tui-startup.ts +23 -23
- package/src/config/run-daemon-config-migration.ts +3 -3
- package/src/config/secret-config.ts +10 -10
- package/src/config/surface.ts +1 -1
- package/src/config/tui-extension-settings.ts +8 -8
- package/src/core/active-model-identity.ts +7 -7
- package/src/core/approval-alert.ts +5 -5
- package/src/core/bookmark-navigation.ts +3 -3
- package/src/core/budget-breach-notifier.ts +6 -6
- package/src/core/compaction-receipt.ts +8 -8
- package/src/core/composer-state.ts +2 -2
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-event-navigation.ts +2 -2
- package/src/core/conversation-fold.ts +9 -9
- package/src/core/conversation-line-cache.ts +14 -14
- package/src/core/conversation-render-context.ts +6 -6
- package/src/core/conversation-rendering.ts +27 -30
- package/src/core/conversation-search-expansion.ts +6 -6
- package/src/core/conversation-splash-state.ts +3 -3
- package/src/core/conversation-turn-structure.ts +13 -13
- package/src/core/conversation-types.ts +3 -3
- package/src/core/conversation-user-receipts.ts +5 -5
- package/src/core/conversation.ts +17 -17
- package/src/core/format-user-error.ts +5 -5
- package/src/core/long-task-notifier.ts +9 -9
- package/src/core/memory-diagnostics-gateway.ts +8 -8
- package/src/core/memory-provenance.ts +5 -5
- package/src/core/model-routing-chip.ts +3 -3
- package/src/core/pairing-tailscale-gateway.ts +3 -3
- package/src/core/permission-mode.ts +5 -5
- package/src/core/power-chip-source.ts +3 -3
- package/src/core/power-status.ts +8 -8
- package/src/core/rewind-receipt.ts +6 -6
- package/src/core/session-resume-core.ts +8 -8
- package/src/core/stream-event-wiring.ts +36 -36
- package/src/core/stream-stall-watchdog.ts +4 -4
- package/src/core/system-message-noise.ts +7 -7
- package/src/core/system-message-router.ts +10 -10
- package/src/core/terminal-notifier.ts +5 -5
- package/src/core/turn-budget-outcome.ts +5 -5
- package/src/core/turn-cancellation.ts +3 -3
- package/src/core/turn-event-wiring.ts +16 -16
- package/src/core/voice-capture-status.ts +2 -2
- package/src/core/voice-provision-gateway.ts +12 -12
- package/src/core/voice-provision-status.ts +19 -19
- package/src/core/voice-stt-gateway.ts +6 -6
- package/src/core/wake-provision-runner.ts +7 -7
- package/src/core/wake-provision-status.ts +17 -17
- package/src/core/workstream-notification.ts +8 -8
- package/src/export/gist-uploader.ts +7 -7
- package/src/input/autocomplete.ts +3 -3
- package/src/input/bookmark-modal.ts +1 -1
- package/src/input/command-args-hint.ts +2 -2
- package/src/input/command-reference.ts +9 -9
- package/src/input/command-registry.ts +32 -32
- package/src/input/commands/acp-runtime.ts +6 -6
- package/src/input/commands/calendar-runtime.ts +9 -9
- package/src/input/commands/channel-pairing.ts +11 -11
- package/src/input/commands/channel-runtime.ts +1 -1
- package/src/input/commands/checkin-runtime.ts +4 -4
- package/src/input/commands/checkpoint-runtime.ts +4 -4
- package/src/input/commands/ci-runtime.ts +4 -4
- package/src/input/commands/cluster-runtime.ts +3 -3
- package/src/input/commands/codebase-runtime.ts +16 -16
- package/src/input/commands/config.ts +6 -6
- package/src/input/commands/connection-status.ts +12 -12
- package/src/input/commands/context-window.ts +2 -2
- package/src/input/commands/cost-attribution-format.ts +4 -4
- package/src/input/commands/cost-runtime.ts +2 -2
- package/src/input/commands/devices-runtime.ts +7 -7
- package/src/input/commands/diff-runtime.ts +2 -2
- package/src/input/commands/editor-runtime.ts +1 -1
- package/src/input/commands/eval.ts +4 -4
- package/src/input/commands/experience-runtime.ts +1 -1
- package/src/input/commands/git-runtime.ts +3 -3
- package/src/input/commands/graph-runtime.ts +3 -3
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-metrics-format.ts +2 -2
- package/src/input/commands/health-runtime.ts +8 -8
- package/src/input/commands/hosted-runtime.ts +13 -13
- package/src/input/commands/image-runtime.ts +6 -6
- package/src/input/commands/intelligence-runtime.ts +2 -2
- package/src/input/commands/local-auth-runtime.ts +3 -3
- package/src/input/commands/local-provider-runtime.ts +3 -3
- package/src/input/commands/local-runtime.ts +7 -7
- package/src/input/commands/mail-runtime.ts +9 -9
- package/src/input/commands/mcp-runtime.ts +1 -1
- package/src/input/commands/memory.ts +13 -13
- package/src/input/commands/notify-runtime.ts +1 -1
- package/src/input/commands/operator-panel-runtime.ts +8 -8
- package/src/input/commands/operator-rpc.ts +3 -3
- package/src/input/commands/operator-runtime.ts +3 -3
- package/src/input/commands/palette-runtime.ts +1 -1
- package/src/input/commands/payment-card-intake.ts +17 -17
- package/src/input/commands/permissions-provenance.ts +7 -7
- package/src/input/commands/permissions-runtime.ts +1 -1
- package/src/input/commands/planning-runtime.ts +9 -9
- package/src/input/commands/platform-services-runtime.ts +2 -2
- package/src/input/commands/policy-dispatch.ts +6 -6
- package/src/input/commands/power-runtime.ts +6 -6
- package/src/input/commands/principals-runtime.ts +3 -3
- package/src/input/commands/product-runtime.ts +3 -3
- package/src/input/commands/profile-render.ts +13 -13
- package/src/input/commands/profile-runtime.ts +13 -13
- package/src/input/commands/profile-types.ts +13 -13
- package/src/input/commands/provider-accounts-runtime.ts +5 -5
- package/src/input/commands/provider.ts +10 -10
- package/src/input/commands/qrcode-runtime.ts +3 -3
- package/src/input/commands/queue-runtime.ts +6 -6
- package/src/input/commands/recall-files-config.ts +4 -4
- package/src/input/commands/recall-files-git.ts +3 -3
- package/src/input/commands/recall-files.ts +12 -12
- package/src/input/commands/recall-query.ts +3 -3
- package/src/input/commands/recall-review.ts +3 -3
- package/src/input/commands/recall-shared.ts +1 -1
- package/src/input/commands/relay-runtime.ts +5 -5
- package/src/input/commands/remote-runtime.ts +3 -3
- package/src/input/commands/review-runtime.ts +8 -8
- package/src/input/commands/rewind-runtime.ts +21 -21
- package/src/input/commands/runtime-services.ts +1 -2
- package/src/input/commands/schedule-nl.ts +2 -2
- package/src/input/commands/schedule-runtime.ts +2 -2
- package/src/input/commands/secret-runtime.ts +3 -3
- package/src/input/commands/session-content.ts +7 -7
- package/src/input/commands/session-picker-filter.ts +3 -3
- package/src/input/commands/session-workflow.ts +10 -10
- package/src/input/commands/session.ts +15 -15
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/share-runtime.ts +4 -4
- package/src/input/commands/shell-core.ts +11 -11
- package/src/input/commands/tasks-runtime.ts +4 -4
- package/src/input/commands/test-runtime.ts +6 -6
- package/src/input/commands/tts-runtime.ts +4 -4
- package/src/input/commands/update-runtime.ts +27 -27
- package/src/input/commands/websearch-runtime.ts +2 -2
- package/src/input/commands/work-plan-runtime.ts +2 -2
- package/src/input/commands/workstream-attempt-dependents.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +16 -16
- package/src/input/commands/workstream-runtime.ts +36 -36
- package/src/input/commands/worktree-runtime.ts +6 -6
- package/src/input/composer-capture.ts +5 -5
- package/src/input/concealed-input.ts +2 -2
- package/src/input/config-modal-types.ts +16 -16
- package/src/input/config-modal.ts +30 -30
- package/src/input/daemon-owned-settings-descriptions.ts +4 -4
- package/src/input/delete-key-policy.ts +1 -1
- package/src/input/exec-env-scrub-config.ts +7 -7
- package/src/input/feature-unit-layout.ts +5 -5
- package/src/input/feed-context-factory.ts +38 -38
- package/src/input/file-picker.ts +1 -1
- package/src/input/handler-command-route.ts +2 -2
- package/src/input/handler-content-actions.ts +8 -8
- package/src/input/handler-feed-routes.ts +13 -13
- package/src/input/handler-feed.ts +31 -31
- package/src/input/handler-interactions.ts +2 -2
- package/src/input/handler-modal-routes.ts +13 -13
- package/src/input/handler-modal-stack.ts +1 -1
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-onboarding-daemon-adopt.ts +6 -6
- package/src/input/handler-picker-routes.ts +7 -7
- package/src/input/handler-prompt-buffer.ts +1 -1
- package/src/input/handler-shortcuts.ts +12 -12
- package/src/input/handler-types.ts +3 -3
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +9 -9
- package/src/input/input-history.ts +1 -1
- package/src/input/keybindings.ts +13 -13
- package/src/input/kill-ring.ts +7 -11
- package/src/input/model-picker-filter.ts +3 -3
- package/src/input/model-picker-items.ts +5 -5
- package/src/input/model-picker-types.ts +2 -2
- package/src/input/model-picker.ts +18 -18
- package/src/input/onboarding/onboarding-feature-units.ts +9 -13
- package/src/input/onboarding/onboarding-provider-key-fields.ts +3 -3
- package/src/input/onboarding/onboarding-runtime-status.ts +3 -3
- package/src/input/onboarding/onboarding-wizard-apply.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +4 -4
- package/src/input/onboarding/onboarding-wizard-network-adopt.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-steps.ts +2 -2
- package/src/input/panel-integration-actions.ts +3 -3
- package/src/input/panel-mouse-geometry.ts +1 -1
- package/src/input/panel-paste-flood-guard.ts +9 -9
- package/src/input/payments-config.ts +15 -15
- package/src/input/profile-picker-modal.ts +1 -1
- package/src/input/provider-key-intake.ts +9 -9
- package/src/input/relay-settings-descriptions.ts +3 -3
- package/src/input/sandbox-exec-config.ts +9 -9
- package/src/input/search.ts +18 -18
- package/src/input/selection-modal-queue.ts +10 -10
- package/src/input/selection-modal.ts +2 -2
- package/src/input/session-picker-modal.ts +7 -7
- package/src/input/settings-modal-activation.ts +1 -1
- package/src/input/settings-modal-adjustment.ts +2 -2
- package/src/input/settings-modal-commit.ts +6 -6
- package/src/input/settings-modal-connections.ts +2 -2
- package/src/input/settings-modal-data.ts +29 -29
- package/src/input/settings-modal-mutations.ts +7 -7
- package/src/input/settings-modal-reset.ts +3 -3
- package/src/input/settings-modal-search.ts +6 -6
- package/src/input/settings-modal-secrets.ts +3 -3
- package/src/input/settings-modal-types.ts +16 -16
- package/src/input/settings-modal.ts +4 -4
- package/src/input/voice-local-settings.ts +3 -3
- package/src/input/worktree-setup-config.ts +8 -8
- package/src/main.ts +15 -15
- package/src/panels/agent-inspector-shared.ts +5 -5
- package/src/panels/base-panel.ts +3 -3
- package/src/panels/builtin/agent.ts +3 -3
- package/src/panels/builtin/development.ts +4 -4
- package/src/panels/builtin/knowledge.ts +1 -1
- package/src/panels/builtin/operations.ts +12 -12
- package/src/panels/builtin/session.ts +8 -8
- package/src/panels/builtin/shared.ts +6 -6
- package/src/panels/builtin-modals.ts +8 -8
- package/src/panels/confirm-state.ts +5 -5
- package/src/panels/cost-tracker-panel.ts +22 -22
- package/src/panels/diff-panel.ts +20 -20
- package/src/panels/diff-review-model.ts +5 -5
- package/src/panels/diff-review-panel.ts +5 -5
- package/src/panels/eval-registry.ts +2 -2
- package/src/panels/expandable-list-panel.ts +5 -5
- package/src/panels/fleet-acts.ts +20 -20
- package/src/panels/fleet-deep-link.ts +5 -5
- package/src/panels/fleet-gateway.ts +12 -12
- package/src/panels/fleet-observed-render.ts +11 -11
- package/src/panels/fleet-panel-format.ts +14 -14
- package/src/panels/fleet-panel-worktree-detail.ts +8 -8
- package/src/panels/fleet-panel.ts +34 -34
- package/src/panels/fleet-read-model.ts +49 -49
- package/src/panels/fleet-spawn.ts +15 -15
- package/src/panels/fleet-steer.ts +7 -7
- package/src/panels/fleet-stop.ts +5 -5
- package/src/panels/fleet-tabs.ts +14 -14
- package/src/panels/fleet-transcript.ts +26 -26
- package/src/panels/git-panel.ts +8 -8
- package/src/panels/hosted-session-feed.ts +13 -13
- package/src/panels/hosted-session-panel.ts +7 -7
- package/src/panels/index.ts +1 -1
- package/src/panels/local-auth-panel.ts +15 -15
- package/src/panels/memory-consolidation-gateway.ts +8 -8
- package/src/panels/modals/devices-modal.ts +8 -8
- package/src/panels/modals/hooks-modal.ts +1 -1
- package/src/panels/modals/keybindings-modal.ts +5 -5
- package/src/panels/modals/knowledge-modal.ts +2 -2
- package/src/panels/modals/local-auth-modal.ts +4 -4
- package/src/panels/modals/marketplace-modal.ts +3 -3
- package/src/panels/modals/memory-modal.ts +19 -19
- package/src/panels/modals/modal-surface-helpers.ts +1 -1
- package/src/panels/modals/modal-theme.ts +3 -3
- package/src/panels/modals/pairing-modal.ts +19 -19
- package/src/panels/modals/planning-modal.ts +4 -4
- package/src/panels/modals/plugins-modal.ts +1 -1
- package/src/panels/modals/policy-modal.ts +4 -4
- package/src/panels/modals/provider-health-modal.ts +1 -1
- package/src/panels/modals/remote-modal.ts +1 -1
- package/src/panels/modals/sandbox-modal.ts +2 -2
- package/src/panels/modals/security-modal.ts +4 -4
- package/src/panels/modals/services-modal.ts +1 -1
- package/src/panels/modals/work-plan-modal.ts +4 -4
- package/src/panels/notifications-feed.ts +6 -6
- package/src/panels/notifications-panel.ts +6 -6
- package/src/panels/panel-confirm-overlay.ts +4 -4
- package/src/panels/panel-manager.ts +13 -13
- package/src/panels/plugins-panel.ts +6 -6
- package/src/panels/polish-core.ts +2 -2
- package/src/panels/polish-tables.ts +2 -2
- package/src/panels/polish.ts +1 -1
- package/src/panels/project-planning-answer-actions.ts +3 -3
- package/src/panels/scrollable-list-panel.ts +15 -15
- package/src/panels/search-focus.ts +1 -1
- package/src/panels/session-maintenance.ts +1 -1
- package/src/panels/skills-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +11 -11
- package/src/panels/types.ts +14 -14
- package/src/panels/workstream-graph-render.ts +5 -5
- package/src/panels/wrfc-panel-format.ts +1 -1
- package/src/permissions/broker-approval-card.ts +13 -13
- package/src/permissions/hunk-selection.ts +13 -13
- package/src/permissions/prompt.ts +22 -22
- package/src/permissions/sandbox-exec-gate.ts +5 -5
- package/src/providers/provider-classification.ts +1 -1
- package/src/providers/reasoning-effort-surface.ts +12 -12
- package/src/renderer/ansi-sanitize.ts +5 -6
- package/src/renderer/autocomplete-overlay.ts +5 -5
- package/src/renderer/block-actions-overlay.ts +1 -1
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/code-block.ts +2 -2
- package/src/renderer/compaction-history-modal.ts +4 -4
- package/src/renderer/compaction-preview.ts +5 -5
- package/src/renderer/compaction-quality.ts +5 -5
- package/src/renderer/composer-fragments.ts +6 -6
- package/src/renderer/compositor.ts +9 -9
- package/src/renderer/config-modal.ts +3 -3
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/context-status-hint.ts +10 -10
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +2 -2
- package/src/renderer/conversation-surface.ts +6 -6
- package/src/renderer/diff.ts +4 -4
- package/src/renderer/fleet-tab-strip.ts +2 -2
- package/src/renderer/footer-tips.ts +4 -4
- package/src/renderer/fullscreen-primitives.ts +1 -1
- package/src/renderer/git-status.ts +5 -5
- package/src/renderer/header-line.ts +5 -5
- package/src/renderer/help-overlay.ts +5 -5
- package/src/renderer/hint-grammar.ts +2 -2
- package/src/renderer/layout.ts +1 -1
- package/src/renderer/markdown-inline.ts +3 -3
- package/src/renderer/markdown-table.ts +7 -7
- package/src/renderer/modal-factory.ts +3 -3
- package/src/renderer/model-picker-overlay.ts +2 -2
- package/src/renderer/model-workspace.ts +7 -7
- package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
- package/src/renderer/overlay-box.ts +1 -1
- package/src/renderer/panel-composite.ts +5 -5
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +8 -8
- package/src/renderer/profile-picker-modal.ts +3 -3
- package/src/renderer/prompt-content-width.ts +1 -1
- package/src/renderer/search-overlay.ts +3 -3
- package/src/renderer/selection-modal-overlay.ts +6 -6
- package/src/renderer/semantic-diff.ts +6 -7
- package/src/renderer/session-picker-modal.ts +24 -24
- package/src/renderer/settings-modal-connections.ts +3 -3
- package/src/renderer/settings-modal-helpers.ts +16 -16
- package/src/renderer/settings-modal.ts +10 -10
- package/src/renderer/shell-surface.ts +8 -8
- package/src/renderer/status-glyphs.ts +6 -6
- package/src/renderer/syntax-highlighter.ts +2 -3
- package/src/renderer/system-message.ts +3 -3
- package/src/renderer/tab-strip.ts +2 -2
- package/src/renderer/term-caps.ts +12 -12
- package/src/renderer/terminal-bg-probe.ts +10 -10
- package/src/renderer/terminal-escapes.ts +1 -1
- package/src/renderer/theme-mode-config.ts +3 -3
- package/src/renderer/theme.ts +34 -34
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +5 -5
- package/src/renderer/tool-result-expanded-lines.ts +3 -3
- package/src/renderer/tool-result-summary.ts +6 -6
- package/src/renderer/turn-injection.ts +9 -9
- package/src/renderer/ui-factory.ts +33 -33
- package/src/renderer/ui-primitives.ts +4 -4
- package/src/runtime/bootstrap-command-parts.ts +3 -3
- package/src/runtime/bootstrap-core.ts +21 -21
- package/src/runtime/bootstrap-hook-bridge.ts +8 -8
- package/src/runtime/bootstrap-shell.ts +9 -9
- package/src/runtime/bootstrap.ts +16 -16
- package/src/runtime/client/approval-updates.ts +3 -3
- package/src/runtime/client/build-floors.ts +7 -7
- package/src/runtime/client/daemon-attach-handshake.ts +5 -5
- package/src/runtime/client/fleet-union.ts +7 -7
- package/src/runtime/client/host-service-status.ts +2 -2
- package/src/runtime/client/hosted-exit.ts +4 -4
- package/src/runtime/client/hosted-roster.ts +4 -4
- package/src/runtime/client/hosted-session-stream.ts +5 -5
- package/src/runtime/client/hosted-sessions.ts +8 -8
- package/src/runtime/client/operator-endpoint.ts +14 -14
- package/src/runtime/client/spine-adoption.ts +8 -8
- package/src/runtime/context-accounting-source.ts +4 -4
- package/src/runtime/context.ts +2 -2
- package/src/runtime/conversation-rewind-port.ts +6 -6
- package/src/runtime/credential-composition.ts +2 -2
- package/src/runtime/daemon-attach-notices.ts +6 -6
- package/src/runtime/diagnostics/panels/index.ts +1 -1
- package/src/runtime/diagnostics/panels/ops.ts +2 -2
- package/src/runtime/disposal-wiring.ts +6 -6
- package/src/runtime/index.ts +11 -11
- package/src/runtime/install-self-check-startup.ts +4 -4
- package/src/runtime/install-self-check.ts +6 -6
- package/src/runtime/interaction-seams.ts +4 -4
- package/src/runtime/knowledge-services.ts +2 -2
- package/src/runtime/legacy-daemon-migration.ts +37 -37
- package/src/runtime/legacy-daemon-reconcile.ts +30 -30
- package/src/runtime/memory-governance-services.ts +3 -3
- package/src/runtime/memory-spine-transport.ts +3 -3
- package/src/runtime/notification-dispatch.ts +4 -4
- package/src/runtime/onboarding/apply.ts +1 -1
- package/src/runtime/onboarding/derivation.ts +1 -1
- package/src/runtime/onboarding/fast-path.ts +7 -7
- package/src/runtime/onboarding/progress.ts +2 -2
- package/src/runtime/onboarding/provider-key-capture.ts +4 -4
- package/src/runtime/onboarding/snapshot.ts +2 -2
- package/src/runtime/onboarding/state.ts +4 -4
- package/src/runtime/onboarding/types.ts +4 -4
- package/src/runtime/orchestrator-core-services.ts +5 -5
- package/src/runtime/path-shadow-startup.ts +3 -3
- package/src/runtime/perf/panel-contracts.ts +1 -1
- package/src/runtime/power-keepawake-remote.ts +6 -6
- package/src/runtime/process-lifecycle.ts +14 -14
- package/src/runtime/provider-fallback.ts +3 -3
- package/src/runtime/recovery-autosave.ts +3 -3
- package/src/runtime/recovery-decisions.ts +19 -19
- package/src/runtime/recovery-offer-wiring.ts +4 -4
- package/src/runtime/recovery-prompt.ts +20 -20
- package/src/runtime/relay-reachability-bridge.ts +3 -3
- package/src/runtime/release-artifacts.ts +1 -1
- package/src/runtime/resume-notice.ts +20 -20
- package/src/runtime/runtime-services-types.ts +20 -20
- package/src/runtime/services.ts +20 -20
- package/src/runtime/session-continuity-hints.ts +1 -1
- package/src/runtime/session-inbound-inputs.ts +12 -12
- package/src/runtime/session-resume-liveness-confirm.ts +4 -4
- package/src/runtime/session-spine-transport.ts +3 -3
- package/src/runtime/store/domains/panels.ts +2 -2
- package/src/runtime/store/domains/ui-perf.ts +2 -2
- package/src/runtime/store/index.ts +1 -1
- package/src/runtime/store/selectors/index.ts +1 -1
- package/src/runtime/store/state.ts +2 -2
- package/src/runtime/ui-services.ts +3 -3
- package/src/runtime/workspace-checkpointing.ts +3 -3
- package/src/runtime/wrfc-persistence.ts +15 -15
- package/src/scripts/process-messages.ts +1 -1
- package/src/shell/blocking-input.ts +9 -9
- package/src/shell/recovery-input-helpers.ts +2 -2
- package/src/shell/retry-affordance.ts +9 -9
- package/src/shell/ui-openers.ts +14 -14
- package/src/shell/voice-capture-shell.ts +3 -3
- package/src/tools/wrfc-agent-guard.ts +4 -4
- package/src/utils/browser.ts +2 -2
- package/src/utils/format-duration.ts +3 -3
- package/src/utils/format-number.ts +2 -2
- package/src/utils/splash-lines.ts +4 -4
- package/src/utils/terminal-width.ts +6 -6
- package/src/verification/verification-ledger.ts +25 -25
- package/src/version.ts +3 -3
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-fold.ts
|
|
2
|
+
* conversation-fold.ts, which transcript rows render FOLDED, and what spacing
|
|
3
3
|
* that earns them.
|
|
4
4
|
*
|
|
5
5
|
* A folded tool result is exactly ONE row: its header, with the preview riding
|
|
6
|
-
* on the same line after the `▸ N lines` badge. It used to be four rows
|
|
6
|
+
* on the same line after the `▸ N lines` badge. It used to be four rows, a
|
|
7
7
|
* `▄▄▄` cap, an interior preview line carrying a second `[▸ N hidden]` count, a
|
|
8
|
-
* `▀▀▀` cap, and a blank after all of it
|
|
8
|
+
* `▀▀▀` cap, and a blank after all of it, for one line of text the header had
|
|
9
9
|
* already sized.
|
|
10
10
|
*
|
|
11
11
|
* These predicates live in their own leaf module because TWO callers must agree
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* (conversation-rendering.ts) decides how to draw the row, and the line cache
|
|
14
14
|
* (conversation-line-cache.ts) decides the blank separator that follows it. If
|
|
15
15
|
* those two ever disagreed about which rows are folded, a warm cache and a cold
|
|
16
|
-
* rebuild would space the transcript differently
|
|
16
|
+
* rebuild would space the transcript differently, the exact class of bug the
|
|
17
17
|
* cache's byte-identical contract exists to rule out.
|
|
18
18
|
*
|
|
19
19
|
* Everything here is PURE: collapse state is read, never written, so a row can
|
|
@@ -30,8 +30,8 @@ import type { ConversationMessageSnapshot } from '@pellux/goodvibes-sdk/platform
|
|
|
30
30
|
type FoldContext = Pick<ConversationRenderContext, 'assistantTurns' | 'collapseState'>;
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Does a tool-result row render FOLDED
|
|
34
|
-
* on it
|
|
33
|
+
* Does a tool-result row render FOLDED, one compact header row with its preview
|
|
34
|
+
* on it, rather than header-plus-expanded-body?
|
|
35
35
|
*
|
|
36
36
|
* An unset collapse key answers the same as the default the row itself will
|
|
37
37
|
* store (collapsed), so asking before and asking after the row renders give the
|
|
@@ -42,7 +42,7 @@ export function isToolResultFolded(
|
|
|
42
42
|
collapseState: ReadonlyMap<string, boolean>,
|
|
43
43
|
collapseKey: string,
|
|
44
44
|
): boolean {
|
|
45
|
-
// Threading only
|
|
45
|
+
// Threading only, the decision, the short-content threshold and the
|
|
46
46
|
// unset-key default all belong to foldedToolResult(). summarizeToolResult is
|
|
47
47
|
// this product's own renderer concern, so resolving it stays here: a
|
|
48
48
|
// summarizable result stays folded even when short, because the one-line
|
|
@@ -77,7 +77,7 @@ function rendersFoldedToolRow(node: RenderNode, context: FoldContext): boolean {
|
|
|
77
77
|
* The blank separator that follows a planned row.
|
|
78
78
|
*
|
|
79
79
|
* Branch rows sit tight under their parent, so the blank lands only after the
|
|
80
|
-
* last row of a top-level unit
|
|
80
|
+
* last row of a top-level unit, that is what keeps a turn's whole subtree
|
|
81
81
|
* reading as one block. On top of that, a folded row followed by more tool
|
|
82
82
|
* machinery gets NO blank at all: N consecutive folded results stack as N
|
|
83
83
|
* adjacent single rows. A folded row followed by anything that is not tool
|
|
@@ -89,7 +89,7 @@ export function trailingBlankAfter(
|
|
|
89
89
|
next: RenderNode | undefined,
|
|
90
90
|
context: FoldContext,
|
|
91
91
|
): boolean {
|
|
92
|
-
// Adaptation only
|
|
92
|
+
// Adaptation only, RenderNode is this product's shape, so reading depth and
|
|
93
93
|
// node kind off it stays here; the rule those facts feed belongs to
|
|
94
94
|
// trailingBlankAfterRow(). No `next` at all means end of transcript: neither
|
|
95
95
|
// a branch row nor tool machinery follows, which is the plain-blank case.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-line-cache.ts
|
|
2
|
+
* conversation-line-cache.ts, per-message Line[] production cache.
|
|
3
3
|
*
|
|
4
4
|
* The measured defect (perf baseline 2026-07-03, transcript.build_1k): appending
|
|
5
5
|
* ONE message to an N-message conversation re-rendered all N messages
|
|
6
6
|
* (45.5 ms p50 / 71.4 MB / 695 k objects per rebuild), because
|
|
7
7
|
* ConversationManager.rebuildHistory() clears the buffer and calls
|
|
8
|
-
* appendConversationMessages() over the entire snapshot on every dirty flag
|
|
8
|
+
* appendConversationMessages() over the entire snapshot on every dirty flag,
|
|
9
9
|
* and markDirty() fires on every mutation. The marginal work for one appended
|
|
10
10
|
* message is ~1/1000th of that.
|
|
11
11
|
*
|
|
@@ -13,33 +13,33 @@
|
|
|
13
13
|
* a PURE function of its complete inputs:
|
|
14
14
|
* - message identity + content (via a content signature; snapshots are fresh
|
|
15
15
|
* structuredClone copies each call, so string content compares by value and
|
|
16
|
-
* array-valued fields
|
|
16
|
+
* array-valued fields, user ContentPart[] and assistant toolCalls, are
|
|
17
17
|
* serialised; a streaming assistant message mutates its content string in
|
|
18
18
|
* place, which changes the signature and invalidates the entry)
|
|
19
19
|
* - render width
|
|
20
20
|
* - the four display-config values the render reads (line-number mode,
|
|
21
21
|
* collapse threshold, showThinking, showReasoningSummary)
|
|
22
22
|
* - the block-registry base at message start (the code-block collapseKey embeds
|
|
23
|
-
* the GLOBAL block index
|
|
23
|
+
* the GLOBAL block index, `code_${msgIdx}_${blockIdx}`, so a shift in an
|
|
24
24
|
* earlier message's block count changes this message's keys)
|
|
25
25
|
* - the absolute message index (embedded in every collapseKey and used for the
|
|
26
26
|
* system-message kind lookup)
|
|
27
27
|
* - the system-message kind (drives the error-navigation registry side effect)
|
|
28
28
|
* - this message's tool-group membership (see conversation-tool-groups.ts):
|
|
29
29
|
* whether it's folded under a group header, which member owns that header,
|
|
30
|
-
* and the group's honest tool/line counts
|
|
30
|
+
* and the group's honest tool/line counts, a group growing as new tool
|
|
31
31
|
* results stream in changes these for every existing member
|
|
32
32
|
* - the live values of every collapseState key the render READS (recorded via a
|
|
33
33
|
* proxy during a miss; a collapse toggle flips a recorded value and
|
|
34
34
|
* invalidates exactly the owning message)
|
|
35
35
|
*
|
|
36
|
-
* Invalidation is by comparison of those complete inputs
|
|
36
|
+
* Invalidation is by comparison of those complete inputs, the file-preview
|
|
37
37
|
* contentVersion precedent generalised: instead of a single version counter we
|
|
38
38
|
* compare the full input tuple, which is provably complete (a from-scratch
|
|
39
39
|
* rebuild reads nothing else).
|
|
40
40
|
*
|
|
41
41
|
* Correctness contract: a cache-served rebuild is BYTE-IDENTICAL to a cold
|
|
42
|
-
* appendConversationMessages() rebuild. This is guaranteed by construction
|
|
42
|
+
* appendConversationMessages() rebuild. This is guaranteed by construction, a
|
|
43
43
|
* miss renders through the exact same per-message render functions into an
|
|
44
44
|
* isolated scratch context, and the captured lines / block metas / error lines
|
|
45
45
|
* are replayed at the same buffer offsets a cold render would have produced.
|
|
@@ -111,7 +111,7 @@ interface KeyMeta {
|
|
|
111
111
|
readonly kind: SystemMessageKind | undefined;
|
|
112
112
|
/**
|
|
113
113
|
* Per-call completion signature for an assistant message's tool calls (see
|
|
114
|
-
* pendingToolKeyOf)
|
|
114
|
+
* pendingToolKeyOf), undefined when the message has none. Each call's id
|
|
115
115
|
* is paired with whether it has a matching result yet, in call order, so a
|
|
116
116
|
* SINGLE call finishing invalidates and re-renders that call's glyph from
|
|
117
117
|
* ◌ to ✓ immediately. A prior aggregate boolean only flipped once EVERY
|
|
@@ -134,7 +134,7 @@ interface KeyMeta {
|
|
|
134
134
|
readonly turnToolCount: number;
|
|
135
135
|
readonly turnSharedLabel: string | undefined;
|
|
136
136
|
readonly turnHasReasoning: boolean;
|
|
137
|
-
/** Row depth and connector
|
|
137
|
+
/** Row depth and connector, both change when structure around a row changes. */
|
|
138
138
|
readonly depth: number;
|
|
139
139
|
readonly connector: string | undefined;
|
|
140
140
|
/** Ancestor gutter pattern, flattened; a change repaints the row's gutters. */
|
|
@@ -145,7 +145,7 @@ interface KeyMeta {
|
|
|
145
145
|
|
|
146
146
|
/**
|
|
147
147
|
* Per-call completion signature for an assistant message's tool calls, in
|
|
148
|
-
* call order
|
|
148
|
+
* call order, `id:0` or `id:1` per call, joined. Undefined for a message
|
|
149
149
|
* with no tool calls at all (nothing to key). Comparing this instead of an
|
|
150
150
|
* aggregate boolean lets exactly the calls whose completion status changed
|
|
151
151
|
* invalidate the entry, rather than waiting for every call in the message to
|
|
@@ -172,7 +172,7 @@ interface CacheEntry {
|
|
|
172
172
|
/** [collapseKey, value] pairs the render read; a change invalidates the entry. */
|
|
173
173
|
readonly collapseDeps: Array<[string, boolean | undefined]>;
|
|
174
174
|
/** Memoised rebase of blocks/errors at appliedBase (avoids realloc when the
|
|
175
|
-
* message's buffer offset is unchanged across rebuilds
|
|
175
|
+
* message's buffer offset is unchanged across rebuilds, the common case). */
|
|
176
176
|
appliedBase: number;
|
|
177
177
|
appliedBlocks: BlockMeta[] | null;
|
|
178
178
|
appliedErrors: number[] | null;
|
|
@@ -237,7 +237,7 @@ function contentUnchanged(sig: ContentSig, m: Message): boolean {
|
|
|
237
237
|
|
|
238
238
|
/**
|
|
239
239
|
* Wrap the real collapseState so reads (.get/.has) are recorded while writes
|
|
240
|
-
* (.set
|
|
240
|
+
* (.set, the auto-collapse default) pass straight through to the real map, so
|
|
241
241
|
* the persistent collapse defaults are established exactly as a cold render
|
|
242
242
|
* would establish them.
|
|
243
243
|
*/
|
|
@@ -290,7 +290,7 @@ function renderOne(
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
/**
|
|
293
|
-
* MessageLineCache
|
|
293
|
+
* MessageLineCache, per-message Line[] memoisation for ConversationManager.
|
|
294
294
|
*
|
|
295
295
|
* Keyed by absolute message index; each entry validates its COMPLETE input tuple
|
|
296
296
|
* before serving. A rebuild that reuses entries is byte-identical to a cold
|
|
@@ -538,7 +538,7 @@ export class MessageLineCache {
|
|
|
538
538
|
|
|
539
539
|
/**
|
|
540
540
|
* Replay an entry into the live context at buffer offset `base`. Line objects
|
|
541
|
-
* are shared (never mutated post-production
|
|
541
|
+
* are shared (never mutated post-production, the compositor reads them into a
|
|
542
542
|
* separate back-buffer). Block/error rebasing is memoised per base so an
|
|
543
543
|
* unchanged message pays zero allocation across rebuilds.
|
|
544
544
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-render-context.ts
|
|
2
|
+
* conversation-render-context.ts, the inputs a transcript row render reads,
|
|
3
3
|
* and the small pure derivations over them.
|
|
4
4
|
*
|
|
5
5
|
* Kept apart from conversation-rendering.ts (which draws) so that both the
|
|
@@ -25,8 +25,8 @@ type Message = ConversationMessageSnapshot;
|
|
|
25
25
|
*
|
|
26
26
|
* The transcript stores a failure as content leading with `Error: ` (see the
|
|
27
27
|
* SDK's ConversationManager.addToolResults), and a per-call user cancellation
|
|
28
|
-
* as the more specific `Error: cancelled by user`. Reading the outcome
|
|
29
|
-
* rather than only "did a result arrive"
|
|
28
|
+
* as the more specific `Error: cancelled by user`. Reading the outcome,
|
|
29
|
+
* rather than only "did a result arrive", is what lets the CALL row show
|
|
30
30
|
* ✓ / ✕ / ⊘ honestly instead of a ✓ that means nothing more than "it finished".
|
|
31
31
|
*/
|
|
32
32
|
export type ToolCallOutcome = 'ok' | 'error' | 'cancelled';
|
|
@@ -38,7 +38,7 @@ function outcomeOfToolContent(content: string): ToolCallOutcome {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* Collect, per tool-call id, how that call settled
|
|
41
|
+
* Collect, per tool-call id, how that call settled, for the calls that have a
|
|
42
42
|
* matching tool-result message in the given slice. A call absent from the map
|
|
43
43
|
* has not run yet (e.g. it is still awaiting an approval decision) and renders
|
|
44
44
|
* with the pending glyph. (item 2c.)
|
|
@@ -54,7 +54,7 @@ export function collectToolCallOutcomes(messages: readonly Message[]): Map<strin
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
|
-
* Ids of tool calls that have a matching tool-result message
|
|
57
|
+
* Ids of tool calls that have a matching tool-result message, i.e. the tools
|
|
58
58
|
* that actually ran, regardless of how they settled. Derived from
|
|
59
59
|
* collectToolCallOutcomes so the two can never disagree about what "ran" means.
|
|
60
60
|
*/
|
|
@@ -80,7 +80,7 @@ export interface ConversationRenderContext {
|
|
|
80
80
|
* actually ran). An assistant tool call whose id is NOT in this set is still
|
|
81
81
|
* awaiting a decision (e.g. an approval prompt) and renders with a pending
|
|
82
82
|
* glyph instead of the completed ✓. When undefined (single-message callers
|
|
83
|
-
* without sibling context), every tool call renders as done
|
|
83
|
+
* without sibling context), every tool call renders as done, the prior
|
|
84
84
|
* behaviour. (item 2c.)
|
|
85
85
|
*/
|
|
86
86
|
readonly completedToolCallIds?: ReadonlySet<string>;
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
type ConversationRenderContext,
|
|
22
22
|
} from './conversation-render-context.ts';
|
|
23
23
|
import { renderCompactionContinuationMessage } from './conversation-compaction-render.ts';
|
|
24
|
-
// Which rows fold, and the blank separator that earns
|
|
24
|
+
// Which rows fold, and the blank separator that earns, shared verbatim with
|
|
25
25
|
// conversation-line-cache.ts so a warm cache and a cold rebuild space alike.
|
|
26
26
|
import { isToolResultFolded, trailingBlankAfter } from './conversation-fold.ts';
|
|
27
27
|
import { drawTreeRails, treeIndentCols, treeTextCol } from '@pellux/goodvibes-terminal-shell';
|
|
@@ -48,10 +48,10 @@ import type { SystemMessageKind } from '@/runtime/index.ts';
|
|
|
48
48
|
* Navigable system message kinds for error-navigation (nextErrorLine/prevErrorLine).
|
|
49
49
|
*
|
|
50
50
|
* Kind → navigable mapping:
|
|
51
|
-
* - 'system' YES
|
|
51
|
+
* - 'system' YES, generic/catch-all messages (provider failures, session
|
|
52
52
|
* events, user-visible errors). Default for un-prefixed messages.
|
|
53
|
-
* - 'wrfc' YES
|
|
54
|
-
* - 'operational' NO
|
|
53
|
+
* - 'wrfc' YES, WRFC chain events are important and worth navigating to.
|
|
54
|
+
* - 'operational' NO , tool/scan/plugin/MCP status noise; not useful to jump to.
|
|
55
55
|
*
|
|
56
56
|
* When a message has no recorded kind (added via bare addSystemMessage), it
|
|
57
57
|
* defaults to 'system' and is therefore navigable.
|
|
@@ -90,7 +90,7 @@ export function renderConversationUserMessage(
|
|
|
90
90
|
}
|
|
91
91
|
// Compaction-continuation handoff: a user-ROLE message the compactor
|
|
92
92
|
// authored, not something the user typed. Rendered in full it repeats the
|
|
93
|
-
// entire re-injected instruction block after every automatic compaction
|
|
93
|
+
// entire re-injected instruction block after every automatic compaction,
|
|
94
94
|
// a multi-kilobyte wall in the transcript. Fold it like a tool result; the
|
|
95
95
|
// full payload stays reachable through the normal expand toggle.
|
|
96
96
|
if (msgIdx !== undefined && displayText.startsWith(COMPACTION_HANDOFF_HEADER)) {
|
|
@@ -120,19 +120,19 @@ export function renderConversationAssistantMessage(
|
|
|
120
120
|
if (message.model) {
|
|
121
121
|
assistantHeaderDetails.push({ text: ` ${message.model}${message.provider ? ` (${message.provider})` : ''} `, fg: T.modelNameDim, dim: true });
|
|
122
122
|
}
|
|
123
|
-
// The count spans the whole run, not just this message
|
|
123
|
+
// The count spans the whole run, not just this message, that is the point
|
|
124
124
|
// of merging. `tools:1` repeated over five headers becomes one `5 tools`.
|
|
125
125
|
const toolCount = turn?.toolCallCount ?? message.toolCalls?.length ?? 0;
|
|
126
126
|
if (toolCount > 0) {
|
|
127
127
|
assistantHeaderDetails.push({ text: ` ${GLYPHS.status.pending} ${toolCount} tool${toolCount === 1 ? '' : 's'} `, fg: T.toolAccent });
|
|
128
128
|
}
|
|
129
129
|
// A label every call in the run shares belongs here, once, instead of on
|
|
130
|
-
// every branch
|
|
130
|
+
// every branch, the branches then lead with what distinguishes them.
|
|
131
131
|
//
|
|
132
132
|
// Hoisted ONLY when it fits whole. A label chopped mid-word ("Calling the
|
|
133
133
|
// assistant serv") is worse than no label: it costs a third of the header
|
|
134
134
|
// and tells you less than the rows below it already do, since each row
|
|
135
|
-
// leads with its own distinguishing token. So it either fits or it goes
|
|
135
|
+
// leads with its own distinguishing token. So it either fits or it goes,
|
|
136
136
|
// never a truncated stub. Dropping it loses nothing reachable: the rows
|
|
137
137
|
// still name every call, and omitToolName is unaffected either way.
|
|
138
138
|
if (turn?.sharedToolLabel) {
|
|
@@ -153,7 +153,7 @@ export function renderConversationAssistantMessage(
|
|
|
153
153
|
if (turnCollapsed && toolCount > 0) {
|
|
154
154
|
assistantHeaderDetails.push({ text: ` ${GLYPHS.navigation.collapsed} hidden `, fg: '244', dim: true });
|
|
155
155
|
}
|
|
156
|
-
// An empty run
|
|
156
|
+
// An empty run, no model, no tools, no reasoning, emits no header rather
|
|
157
157
|
// than a bare `● assistant` with nothing under it.
|
|
158
158
|
if (assistantHeaderDetails.length > 0) {
|
|
159
159
|
const headerStartLine = context.history.getLineCount();
|
|
@@ -166,7 +166,7 @@ export function renderConversationAssistantMessage(
|
|
|
166
166
|
detailFg: '244',
|
|
167
167
|
}, assistantHeaderDetails));
|
|
168
168
|
|
|
169
|
-
// Turns are collapsible as a unit and default to EXPANDED
|
|
169
|
+
// Turns are collapsible as a unit and default to EXPANDED, a turn
|
|
170
170
|
// collapsed by default would hide the activity the transcript exists to
|
|
171
171
|
// show. Registered only when there is machinery to hide.
|
|
172
172
|
if (turn && toolCount > 0) {
|
|
@@ -179,7 +179,7 @@ export function renderConversationAssistantMessage(
|
|
|
179
179
|
type: 'assistant_turn',
|
|
180
180
|
startLine: headerStartLine,
|
|
181
181
|
lineCount: 1,
|
|
182
|
-
rawContent: `assistant turn
|
|
182
|
+
rawContent: `assistant turn: ${toolCount} tool call${toolCount === 1 ? '' : 's'}${turn.sharedToolLabel ? ` (${turn.sharedToolLabel})` : ''}`,
|
|
183
183
|
groupMemberIndexes: turn.resultIndexes,
|
|
184
184
|
toolName: turn.sharedToolLabel,
|
|
185
185
|
});
|
|
@@ -201,7 +201,7 @@ export function renderConversationAssistantMessage(
|
|
|
201
201
|
const thinkingStartLine = context.history.getLineCount();
|
|
202
202
|
const thinkingBlockIdx = context.blockRegistry.length;
|
|
203
203
|
const thinkingCollapseKey = `msg_${msgIdx}_thinking`;
|
|
204
|
-
// Collapsed by default, like every other collapsible block
|
|
204
|
+
// Collapsed by default, like every other collapsible block, Tab (or the
|
|
205
205
|
// block-actions menu) expands it via the same collapseKey the BlockMeta
|
|
206
206
|
// below registers. Previously this key was registered but never
|
|
207
207
|
// consulted: the toggle existed but did nothing.
|
|
@@ -215,7 +215,7 @@ export function renderConversationAssistantMessage(
|
|
|
215
215
|
// One row: label plus size badge, no frame and no interior line.
|
|
216
216
|
//
|
|
217
217
|
// Deliberately NO preview, unlike a folded tool result. Reasoning text
|
|
218
|
-
// stays behind the toggle until it is asked for
|
|
218
|
+
// stays behind the toggle until it is asked for, the fold is the quiet
|
|
219
219
|
// state of an already-opt-in display, and previewing the first reasoning
|
|
220
220
|
// line here would disclose content the collapsed form has never shown.
|
|
221
221
|
const thinkingLineCount = message.reasoningContent.split('\n').length;
|
|
@@ -255,7 +255,7 @@ export function renderConversationAssistantMessage(
|
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
/**
|
|
258
|
-
* Assistant prose
|
|
258
|
+
* Assistant prose, the model's actual answer, at full prominence and full
|
|
259
259
|
* width.
|
|
260
260
|
*
|
|
261
261
|
* Prose is never drawn as a tree branch. It is what closes a group (see
|
|
@@ -274,9 +274,6 @@ function renderAssistantProse(
|
|
|
274
274
|
{
|
|
275
275
|
const showAllLineNumbers = lineNumberMode === 'all';
|
|
276
276
|
const showCodeBlockLineNumbers = lineNumberMode === 'all' ? false : lineNumberMode === 'code';
|
|
277
|
-
// First pass: measure totalLines for gutter sizing (only when line-numbers='all').
|
|
278
|
-
// When line numbers are off, skip the measurement pass entirely.
|
|
279
|
-
//
|
|
280
277
|
// NOTE: The 'all' mode intentionally calls renderMarkdownTracked twice:
|
|
281
278
|
// 1. Measure pass: render at full `width` to get the total line count, which
|
|
282
279
|
// determines `numWidth` (digit count) and thus `gutterW` (gutter column width).
|
|
@@ -365,7 +362,7 @@ export function renderConversationSystemMessage(
|
|
|
365
362
|
*
|
|
366
363
|
* The call row is its own plan node rather than part of the assistant
|
|
367
364
|
* message's render, which is what lets a result be interleaved BETWEEN two
|
|
368
|
-
* calls of the same message
|
|
365
|
+
* calls of the same message, the ordering guarantee that makes a
|
|
369
366
|
* late-finishing call's result land inside its own subtree instead of after a
|
|
370
367
|
* call issued later.
|
|
371
368
|
*/
|
|
@@ -409,7 +406,7 @@ export function renderConversationToolCallNode(
|
|
|
409
406
|
{ indentCols: indent, omitToolName: turn?.sharedToolLabel !== undefined },
|
|
410
407
|
);
|
|
411
408
|
|
|
412
|
-
// Recursion stopped here
|
|
409
|
+
// Recursion stopped here, say so rather than silently showing a subtree as
|
|
413
410
|
// if it were a leaf.
|
|
414
411
|
if (node.truncated) {
|
|
415
412
|
const noteIndent = treeIndentCols(node.depth + 1, width);
|
|
@@ -477,15 +474,15 @@ export function renderConversationToolMessage(
|
|
|
477
474
|
const inTree = depth > 0 && indent > 0;
|
|
478
475
|
// The EXPANDED render, computed unconditionally (even while collapsed) so
|
|
479
476
|
// the header's "N lines" badge always names what Tab would actually reveal
|
|
480
|
-
|
|
477
|
+
//, a raw JSON blob that pretty-prints to 50 lines must say 50, not 1, even
|
|
481
478
|
// while it's still folded. Reused below as the actual body when expanded,
|
|
482
479
|
// so this is never rendered twice.
|
|
483
480
|
//
|
|
484
481
|
// In the tree it is rendered at the width it will actually OCCUPY (the row's
|
|
485
482
|
// width less its indent) and then shifted into place, so the badge still
|
|
486
483
|
// counts exactly the lines expansion produces. Rendering it full-width and
|
|
487
|
-
// displaying it indented would desynchronise the two
|
|
488
|
-
// markdown-table-drops-columns bug class
|
|
484
|
+
// displaying it indented would desynchronise the two, the
|
|
485
|
+
// markdown-table-drops-columns bug class, and rendering it full-width and
|
|
489
486
|
// displaying it flush punches the row's rails out for the whole body.
|
|
490
487
|
// The body is a continuation of its row, so it starts at the row's own text
|
|
491
488
|
// column; the shift is that column expressed relative to the flush left
|
|
@@ -516,15 +513,15 @@ export function renderConversationToolMessage(
|
|
|
516
513
|
// A per-call user cancellation settles as a tool result whose content leads
|
|
517
514
|
// with "Error: cancelled by user" (the SDK's structured cancelled shape; any
|
|
518
515
|
// partial output the tool produced before it stopped follows on later lines).
|
|
519
|
-
// Render it structurally as a distinct "cancelled" block in the warn tone
|
|
520
|
-
// not a generic tool result, and not a hard error
|
|
516
|
+
// Render it structurally as a distinct "cancelled" block in the warn tone,
|
|
517
|
+
// not a generic tool result, and not a hard error, so the transcript reads
|
|
521
518
|
// the user's decision honestly while the partial output stays visible below.
|
|
522
519
|
const isCancelled = blockType === 'tool' && /^Error: cancelled by user\b/.test(contentLines[0] ?? '');
|
|
523
520
|
const warnTone = activeUiTones().chrome.warn;
|
|
524
521
|
|
|
525
522
|
// In the tree a result hangs under the call that produced it, so repeating
|
|
526
|
-
// the generic label ("tool result") and the tool's own name
|
|
527
|
-
// parent call row already shows
|
|
523
|
+
// the generic label ("tool result") and the tool's own name, which the
|
|
524
|
+
// parent call row already shows, is exactly the boilerplate this layout
|
|
528
525
|
// removes. The row leads with its size badge instead. `diff` and `cancelled`
|
|
529
526
|
// keep their labels: those carry information the parent row does not.
|
|
530
527
|
const label = isCancelled ? 'cancelled' : (blockType === 'diff' ? 'diff' : (inTree ? '' : 'tool result'));
|
|
@@ -536,7 +533,7 @@ export function renderConversationToolMessage(
|
|
|
536
533
|
|
|
537
534
|
// A FOLDED result is exactly one row: this header, with its preview riding on
|
|
538
535
|
// the same line right after the `▸ N lines` badge (see
|
|
539
|
-
// renderConversationFoldedRow). The badge is the count
|
|
536
|
+
// renderConversationFoldedRow). The badge is the count, the old fold also
|
|
540
537
|
// carried a separate `[▸ N hidden]` marker, which restated it.
|
|
541
538
|
const headerTone = {
|
|
542
539
|
marker: isCancelled ? GLYPHS.status.blocked : (blockType === 'diff' ? GLYPHS.status.dualPane : GLYPHS.status.active),
|
|
@@ -560,14 +557,14 @@ export function renderConversationToolMessage(
|
|
|
560
557
|
const rows: Line[] = [headerLine];
|
|
561
558
|
|
|
562
559
|
if (!isCollapsed) {
|
|
563
|
-
// Diff or plain result
|
|
560
|
+
// Diff or plain result, either way this is exactly `expandedLines`,
|
|
564
561
|
// already computed above (and already what the header's line count is
|
|
565
562
|
// honest about), so there is nothing left to render here.
|
|
566
563
|
//
|
|
567
564
|
// Deliberately NOT indented. renderExpandedToolResultLines is the single
|
|
568
565
|
// source of truth for the "N lines" badge above; re-wrapping it at a
|
|
569
566
|
// reduced width would desynchronise that count from what expansion
|
|
570
|
-
// actually reveals
|
|
567
|
+
// actually reveals, the markdown-table-drops-columns bug class. The body
|
|
571
568
|
// is already visually bound to its row by the header directly above it.
|
|
572
569
|
// In the tree it was rendered at `bodyWidth` above and is shifted into the
|
|
573
570
|
// row's indent here, which is what leaves the rail columns to its left free
|
|
@@ -671,7 +668,7 @@ export function appendConversationMessages(
|
|
|
671
668
|
// Branch rows sit tight under their parent; the blank separator lands only
|
|
672
669
|
// after the last row of a top-level unit, which is what keeps a turn's
|
|
673
670
|
// whole subtree reading as one block instead of a run of spaced-out rows.
|
|
674
|
-
// A folded result followed by more tool machinery gets no blank at all
|
|
671
|
+
// A folded result followed by more tool machinery gets no blank at all,
|
|
675
672
|
// consecutive folded results stack as adjacent single rows.
|
|
676
673
|
if (trailingBlankAfter(node, plan[i + 1], turnContext)) {
|
|
677
674
|
turnContext.history.addLine(createEmptyLine(width));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-search-expansion.ts
|
|
2
|
+
* conversation-search-expansion.ts, tracks which collapse keys transcript
|
|
3
3
|
* search auto-expanded so they can be restored on search close, unless the
|
|
4
4
|
* user explicitly acted on the block while it was open.
|
|
5
5
|
*
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
*
|
|
12
12
|
* The contract (see SearchManager.revealCurrentMatch and .close in
|
|
13
13
|
* search.ts): a single keystroke in the search field must never expand
|
|
14
|
-
* collapsed content
|
|
14
|
+
* collapsed content, only navigating TO a match hidden inside it does, and
|
|
15
15
|
* that expansion is undone when search closes UNLESS the user separately
|
|
16
16
|
* touched the block (toggled, copied, bookmarked, saved, or bulk-expanded
|
|
17
17
|
* via /expand) while it sat auto-expanded. An explicit user action always
|
|
18
18
|
* wins over search's own bookkeeping, regardless of which happened first.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
/** Structural shape restoreOnto() needs
|
|
21
|
+
/** Structural shape restoreOnto() needs, matches ConversationManager's own
|
|
22
22
|
* public setCollapsed() without importing the class (avoids a cycle). */
|
|
23
23
|
export interface CollapseSettable {
|
|
24
24
|
setCollapsed(collapseKey: string, collapsed: boolean): void;
|
|
@@ -28,13 +28,13 @@ export class SearchExpansionTracker {
|
|
|
28
28
|
/**
|
|
29
29
|
* Collapse keys currently expanded because the user navigated to a search
|
|
30
30
|
* match hidden inside them. Never contains a key the user has touched
|
|
31
|
-
* explicitly
|
|
31
|
+
* explicitly, noteUserTouch() removes it on the way in.
|
|
32
32
|
*/
|
|
33
33
|
private searchExpandedKeys = new Set<string>();
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Collapse keys the user has explicitly acted on at least once. Growth is
|
|
37
|
-
* unbounded for the life of the conversation
|
|
37
|
+
* unbounded for the life of the conversation, membership only ever gates
|
|
38
38
|
* one decision (whether restoreSearchExpansions() may re-collapse a key),
|
|
39
39
|
* so a stale positive is harmless and pruning would add complexity for no
|
|
40
40
|
* behavioral gain.
|
|
@@ -57,7 +57,7 @@ export class SearchExpansionTracker {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/** Re-collapse every key search auto-expanded and not since user-touched,
|
|
60
|
-
* through `conversationManager`'s public setCollapsed()
|
|
60
|
+
* through `conversationManager`'s public setCollapsed(), called from
|
|
61
61
|
* SearchManager.close() to restore pre-search collapse state. */
|
|
62
62
|
restoreOnto(conversationManager: CollapseSettable): void {
|
|
63
63
|
const keys = [...this.searchExpandedKeys];
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-splash-state.ts
|
|
2
|
+
* conversation-splash-state.ts, when the splash owns the conversation area,
|
|
3
3
|
* and what has to happen the moment it stops.
|
|
4
4
|
*
|
|
5
5
|
* Two pieces of state, kept out of ConversationManager (core/conversation.ts,
|
|
6
6
|
* already at its line-count gate) and out of `suppressSplash`, which is a
|
|
7
7
|
* per-frame posture the panel workspace sets both ways on every render:
|
|
8
8
|
*
|
|
9
|
-
* - `dismissed
|
|
9
|
+
* - `dismissed`, sticky for the run. Owner rule: the splash yields to ANY
|
|
10
10
|
* submission, a chat message or a slash command alike. A slash command
|
|
11
11
|
* whose whole output is a modal (or nothing) still means the session has
|
|
12
12
|
* started, so the splash must not reappear underneath it, and must not
|
|
13
13
|
* come back in the gap before the first reply arrives.
|
|
14
14
|
*
|
|
15
|
-
* - the splash→transcript EDGE
|
|
15
|
+
* - the splash→transcript EDGE, latched when a rebuild that would have
|
|
16
16
|
* drawn the splash draws transcript content instead. The shell consumes
|
|
17
17
|
* it to repaint the whole viewport for that one frame. Without that, the
|
|
18
18
|
* differential renderer only rewrites rows it knows changed, so every row
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-turn-structure.ts
|
|
2
|
+
* conversation-turn-structure.ts, turns the flat message array into the
|
|
3
3
|
* structural render plan the transcript tree draws from.
|
|
4
4
|
*
|
|
5
5
|
* Three jobs, deliberately not conflated:
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* header (see computeAssistantTurns).
|
|
9
9
|
*
|
|
10
10
|
* 2. **Structural placement.** Where each row goes. A tool result is a child
|
|
11
|
-
* of the CALL that produced it, identified by callId
|
|
11
|
+
* of the CALL that produced it, identified by callId, not a row appended
|
|
12
12
|
* wherever it happens to land in the message array. Two calls issued
|
|
13
13
|
* together run concurrently and settle in whatever order they finish; the
|
|
14
14
|
* later-finishing call's result must still render inside its own call's
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* ## Node identity
|
|
22
22
|
*
|
|
23
|
-
* Every planned row carries a stable string id
|
|
23
|
+
* Every planned row carries a stable string id, `m:<absIdx>` for a message,
|
|
24
24
|
* `c:<absIdx>:<callIndex>` for one tool call, each prefixed by its scope (see
|
|
25
25
|
* nesting below). Ids derive from append-only indices that are never
|
|
26
26
|
* renumbered, so a row inserted in the middle does not change any other row's
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* `AgentManager.getConversationSnapshot(agentId)` already exposes it live (the
|
|
35
35
|
* same read `fleet-panel.ts` uses to draw an attached agent's transcript). So
|
|
36
36
|
* when a tool call spawned an agent, the plan SPLICES that agent's own plan in
|
|
37
|
-
* beneath the call, recursively
|
|
37
|
+
* beneath the call, recursively, the identical operation to lifting a result
|
|
38
38
|
* into its call's subtree, applied to a nested snapshot. The parent
|
|
39
39
|
* transcript, the persisted format, and the message schema are untouched; only
|
|
40
40
|
* the render plan nests.
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
*
|
|
53
53
|
* Proper box drawing: `├` for a branch with siblings below it, `└` for the
|
|
54
54
|
* last sibling, `│` carried down the gutter for every ancestor whose subtree
|
|
55
|
-
* is still open. Connectors are a PURE FUNCTION of current structure
|
|
56
|
-
* recomputed from scratch on every plan build, never cached
|
|
55
|
+
* is still open. Connectors are a PURE FUNCTION of current structure,
|
|
56
|
+
* recomputed from scratch on every plan build, never cached, so a row that
|
|
57
57
|
* stops being last flips `└`→`├` on the next rebuild.
|
|
58
58
|
*
|
|
59
59
|
* That flip is one cell. Indentation width, content column, and row text are
|
|
60
60
|
* all independent of sibling status by construction: `indentCols` depends only
|
|
61
61
|
* on depth and width, and the connector occupies a column that exists whether
|
|
62
62
|
* it holds `├` or `└`. So a sibling arriving repaints a connector cell and
|
|
63
|
-
* moves no text. (The rejected alternative
|
|
63
|
+
* moves no text. (The rejected alternative, a uniform glyph, cannot express
|
|
64
64
|
* "this subtree continues past here", which is what makes a deep tree
|
|
65
65
|
* scannable.)
|
|
66
66
|
*/
|
|
@@ -80,12 +80,12 @@ export const MAX_NEST_DEPTH = 8;
|
|
|
80
80
|
export type TreeConnector = '├' | '└';
|
|
81
81
|
|
|
82
82
|
export interface RenderNode {
|
|
83
|
-
/** Stable identity
|
|
83
|
+
/** Stable identity, survives insertions above it. Scope-prefixed. */
|
|
84
84
|
readonly id: string;
|
|
85
85
|
readonly kind: 'message' | 'toolcall';
|
|
86
86
|
/** Index of the message within ITS OWN snapshot array. */
|
|
87
87
|
readonly absIdx: number;
|
|
88
|
-
/** Position within the owning assistant message's toolCalls
|
|
88
|
+
/** Position within the owning assistant message's toolCalls, 'toolcall' only. */
|
|
89
89
|
readonly callIndex?: number;
|
|
90
90
|
/** 0 = flush; >=1 = branch depth. */
|
|
91
91
|
readonly depth: number;
|
|
@@ -106,7 +106,7 @@ export interface RenderNode {
|
|
|
106
106
|
* renderer draws `│` in those gutters. Excludes this row's own depth.
|
|
107
107
|
*/
|
|
108
108
|
readonly openAncestorDepths: readonly number[];
|
|
109
|
-
/** Set when recursion stopped here (depth ceiling or cycle)
|
|
109
|
+
/** Set when recursion stopped here (depth ceiling or cycle), surfaced honestly. */
|
|
110
110
|
readonly truncated?: 'depth' | 'cycle';
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -233,7 +233,7 @@ export interface RenderPlanOptions {
|
|
|
233
233
|
* The agent id a tool call spawned, when it spawned one.
|
|
234
234
|
*
|
|
235
235
|
* Read from the call's own result payload first (the spawn tool reports the id
|
|
236
|
-
* it allocated
|
|
236
|
+
* it allocated, see AgentInput.agentId in the SDK's agent schema), falling
|
|
237
237
|
* back to an explicit `agentId` argument on the call. Returns undefined for
|
|
238
238
|
* every ordinary tool call, which is the overwhelmingly common case, so this
|
|
239
239
|
* stays a cheap check.
|
|
@@ -253,7 +253,7 @@ function spawnedAgentIdOf(
|
|
|
253
253
|
if (typeof id === 'string' && id.length > 0) return id;
|
|
254
254
|
}
|
|
255
255
|
} catch {
|
|
256
|
-
// Non-JSON result
|
|
256
|
+
// Non-JSON result, fall through to the argument check.
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
const argId = call.arguments.agentId;
|
|
@@ -301,7 +301,7 @@ function buildScopeNodes(
|
|
|
301
301
|
const placed = new Set<number>();
|
|
302
302
|
const messageAt = (absIdx: number): Message => messages[absIdx - indexOffset]!;
|
|
303
303
|
// Calls issued by later messages of the SAME run attach to the run's head
|
|
304
|
-
// node, because the head owns the only visible header
|
|
304
|
+
// node, because the head owns the only visible header, that is what makes
|
|
305
305
|
// them siblings of each other rather than only children of their own
|
|
306
306
|
// (headerless) message, and therefore what makes ├/└ resolve correctly
|
|
307
307
|
// across a merged turn.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-types.ts
|
|
2
|
+
* conversation-types.ts, shared TUI extension types for ConversationManager.
|
|
3
3
|
*
|
|
4
4
|
* Extracted from conversation.ts so that conversation-rendering.ts can import
|
|
5
5
|
* BlockMeta without creating a circular dependency:
|
|
@@ -17,7 +17,7 @@ import type { BlockMeta as SdkBlockMeta } from '@pellux/goodvibes-sdk/platform/c
|
|
|
17
17
|
* a run of >=2 consecutive tool-result messages under one collapsible header
|
|
18
18
|
* (see conversation-tool-groups.ts). Defined as an intersection rather than
|
|
19
19
|
* `interface X extends SdkBlockMeta` because TypeScript requires an extending
|
|
20
|
-
* interface's members to be subtypes of the base interface's
|
|
20
|
+
* interface's members to be subtypes of the base interface's, widening the
|
|
21
21
|
* `type` union that way is a compile error. Omit + intersection adds the new
|
|
22
22
|
* variant without touching the SDK's published type.
|
|
23
23
|
*/
|
|
@@ -42,7 +42,7 @@ export type BlockMeta = Omit<SdkBlockMeta, 'type'> & {
|
|
|
42
42
|
/**
|
|
43
43
|
* The tool call's name, when this block renders a 'tool' result (or is an
|
|
44
44
|
* 'assistant_turn' header whose calls all share one label). Used to name the block honestly in action
|
|
45
|
-
* receipts (e.g. "tool result: exec")
|
|
45
|
+
* receipts (e.g. "tool result: exec"), see describeBlockForReceipt in
|
|
46
46
|
* handler-content-actions.ts. Undefined for non-tool block types and for
|
|
47
47
|
* standalone tool results with no recorded name.
|
|
48
48
|
*/
|