@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
|
@@ -36,7 +36,7 @@ export type PanelFocusRouteState = {
|
|
|
36
36
|
* True when THIS token is a paste: a single 'text' token whose value holds
|
|
37
37
|
* more than one character. The SDK tokenizer emits a bracketed paste
|
|
38
38
|
* (\x1b[?2004h, enabled in main.ts init) as exactly one such token; discrete
|
|
39
|
-
* keystrokes
|
|
39
|
+
* keystrokes, even several batched into one feed() by render-tick latency,
|
|
40
40
|
* arrive as separate 1-char tokens. See the text-token branch below.
|
|
41
41
|
*/
|
|
42
42
|
isPasteToken: boolean;
|
|
@@ -88,12 +88,12 @@ export function handlePanelFocusToken(state: PanelFocusRouteState, token: InputT
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
if (token.type === 'key') {
|
|
91
|
-
// I6: two-stage Escape
|
|
91
|
+
// I6: two-stage Escape, give the panel a chance to consume escape first
|
|
92
92
|
// (e.g. dismiss a confirm dialog or clear search). Only unfocus if the
|
|
93
93
|
// panel returns false (unconsumed) or there is no active panel.
|
|
94
94
|
if (token.logicalName === 'escape') {
|
|
95
95
|
// While streaming, a focused panel must not swallow the
|
|
96
|
-
// only way to cancel
|
|
96
|
+
// only way to cancel, Escape's first job is always cancel-turn; the
|
|
97
97
|
// panel's own two-stage consume-or-unfocus contract only runs once no
|
|
98
98
|
// turn is active, so a *second* Escape falls through to it normally
|
|
99
99
|
// (panelFocused stays unchanged here). Calls cancelGeneration()
|
|
@@ -117,7 +117,7 @@ export function handlePanelFocusToken(state: PanelFocusRouteState, token: InputT
|
|
|
117
117
|
}
|
|
118
118
|
const kb = state.keybindingsManager;
|
|
119
119
|
// NOTE: panel-tab-next/prev, panel-close, and panel-close-all are handled
|
|
120
|
-
// globally in handleGlobalShortcutToken (runs earlier in the feed loop)
|
|
120
|
+
// globally in handleGlobalShortcutToken (runs earlier in the feed loop),
|
|
121
121
|
// their old, drifted copies here were unreachable and are gone. Only
|
|
122
122
|
// panel-focus-toggle stays, since it's meaningful only once the panel
|
|
123
123
|
// workspace already owns focus (it swaps between the two panes).
|
|
@@ -156,7 +156,7 @@ export function handlePanelFocusToken(state: PanelFocusRouteState, token: InputT
|
|
|
156
156
|
// Invariant A/B: a paste (isPasteToken, one multi-char token) into
|
|
157
157
|
// a capturing panel forwards verbatim below; elsewhere it is DROPPED with
|
|
158
158
|
// a one-shot hint (never exploded into hotkeys, never a silent focus
|
|
159
|
-
// flip
|
|
159
|
+
// flip, focus moves only on an explicit verb). Discrete keystrokes fall
|
|
160
160
|
// through to the per-char dispatch below.
|
|
161
161
|
if (state.isPasteToken && !activePanel?.isCapturingTextBurst?.()) {
|
|
162
162
|
state.onPasteDropped?.(activePanel?.name ?? 'the panel');
|
|
@@ -164,7 +164,7 @@ export function handlePanelFocusToken(state: PanelFocusRouteState, token: InputT
|
|
|
164
164
|
return { handled: true, panelFocused };
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
// item 5
|
|
167
|
+
// item 5, paste flood guard (rate-based; see panel-paste-flood-guard.ts).
|
|
168
168
|
if (!state.isPasteToken && !activePanel?.isCapturingTextBurst?.()) {
|
|
169
169
|
const guard = trackPanelPasteFloodGuard(state.burstGuard, state.now);
|
|
170
170
|
if (!guard.dispatch) {
|
|
@@ -293,7 +293,7 @@ export function handlePromptTextToken(state: TextRouteState, token: InputToken):
|
|
|
293
293
|
|
|
294
294
|
if (prompt === '/') {
|
|
295
295
|
// Arm commandMode as soon as the prompt becomes a bare '/', regardless of
|
|
296
|
-
// whether commandRegistry has been (re)attached yet
|
|
296
|
+
// whether commandRegistry has been (re)attached yet, this is a one-shot
|
|
297
297
|
// transition (the only place commandMode ever becomes true), and gating
|
|
298
298
|
// it on commandRegistry meant a transient null during a modal/overlay
|
|
299
299
|
// handoff would permanently miss the window: every following keystroke
|
|
@@ -329,7 +329,7 @@ export type KeyRouteState = {
|
|
|
329
329
|
commandContext: CommandContext | undefined;
|
|
330
330
|
/**
|
|
331
331
|
* Deliver a concealed submission. When it returns true, concealed mode was
|
|
332
|
-
* active and consumed the value
|
|
332
|
+
* active and consumed the value, the plaintext went straight to the
|
|
333
333
|
* requester, bypassing input history and the transcript. Optional so bare
|
|
334
334
|
* test callers omit it.
|
|
335
335
|
*/
|
|
@@ -337,14 +337,14 @@ export type KeyRouteState = {
|
|
|
337
337
|
/**
|
|
338
338
|
* Optional: only used by the enter-key desync safety net below (a stray
|
|
339
339
|
* slash-prefixed submission with commandMode somehow still false). When
|
|
340
|
-
* absent, that fallback simply doesn't trigger
|
|
340
|
+
* absent, that fallback simply doesn't trigger, the primary fix (arming
|
|
341
341
|
* commandMode on the '/' keystroke regardless of registry attachment, in
|
|
342
342
|
* handlePromptTextToken above) is what actually prevents the desync.
|
|
343
343
|
*/
|
|
344
344
|
commandRegistry?: CommandRegistry | null;
|
|
345
345
|
autocomplete: AutocompleteEngine | null;
|
|
346
346
|
blockActionsMenu: { open: (block: BlockMeta) => void };
|
|
347
|
-
/** The absolute history line of the bottom-most visible block
|
|
347
|
+
/** The absolute history line of the bottom-most visible block, the block
|
|
348
348
|
* the user is actually looking at (see getViewportBottomLine's doc).
|
|
349
349
|
* Anchors Enter-on-empty-composer's block-actions menu to that block
|
|
350
350
|
* instead of an arbitrary fixed line. */
|
|
@@ -455,7 +455,7 @@ export function handlePromptKeyToken(state: KeyRouteState, token: InputToken): {
|
|
|
455
455
|
}
|
|
456
456
|
if (text) {
|
|
457
457
|
// Safety net for a desynced commandMode: text is command-shaped (starts
|
|
458
|
-
// with '/') but commandMode never armed
|
|
458
|
+
// with '/') but commandMode never armed, e.g. the '/' keystroke landed
|
|
459
459
|
// during a modal/overlay handoff window. handleCommandModeToken (the
|
|
460
460
|
// normal dispatch path for '/name ...') never runs in this state since
|
|
461
461
|
// it early-returns when commandMode is false, so without this the text
|
|
@@ -611,12 +611,12 @@ export function handlePromptKeyToken(state: KeyRouteState, token: InputToken): {
|
|
|
611
611
|
}
|
|
612
612
|
|
|
613
613
|
if (token.logicalName === 'down') {
|
|
614
|
-
// Announce the focus move honestly
|
|
614
|
+
// Announce the focus move honestly, this handoff is otherwise silent
|
|
615
615
|
// and easy to miss (the next keystrokes look like they're doing nothing,
|
|
616
616
|
// because they're now landing on the indicator, not the composer).
|
|
617
617
|
const announceIndicatorFocus = () => {
|
|
618
618
|
indicatorFocused = true;
|
|
619
|
-
state.commandContext?.print('[Down] Focus moved to the process indicator
|
|
619
|
+
state.commandContext?.print('[Down] Focus moved to the process indicator; Up or Esc returns to the composer.');
|
|
620
620
|
};
|
|
621
621
|
const move = computeCursorVerticalMove(prompt, cursorPos, inputScrollTop, state.contentWidth, state.maxInputRows, 1);
|
|
622
622
|
if (move.moved) {
|
|
@@ -48,39 +48,39 @@ import type { KillRing } from './kill-ring.ts';
|
|
|
48
48
|
import type { FocusTracker } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* InputFeedContext
|
|
51
|
+
* InputFeedContext, The single long-lived context object passed to feedInputTokens
|
|
52
52
|
* on every keystroke. Allocated once at InputHandler construction; mutated in place
|
|
53
53
|
* per-feed to avoid per-keystroke GC pressure from ~80-field object allocation.
|
|
54
54
|
*
|
|
55
55
|
* **Mutable per-feed** (synced from handler at the top of every feed() call, and
|
|
56
56
|
* updated inside action closures via syncFeedContextMutableFields):
|
|
57
|
-
* - `prompt`, `cursorPos
|
|
58
|
-
* - `commandMode`, `panelFocused`, `indicatorFocused
|
|
59
|
-
* - `helpOverlayActive`, `helpScrollOffset
|
|
60
|
-
* - `shortcutsOverlayActive`, `shortcutsScrollOffset
|
|
61
|
-
* - `nextPasteId`, `nextImageId
|
|
62
|
-
* - `mouseDownRow`, `mouseDownCol
|
|
63
|
-
* - `contentWidth
|
|
64
|
-
* - `selectionCallback
|
|
65
|
-
* - `requestRender
|
|
57
|
+
* - `prompt`, `cursorPos`, current text buffer state
|
|
58
|
+
* - `commandMode`, `panelFocused`, `indicatorFocused`, focus-mode flags
|
|
59
|
+
* - `helpOverlayActive`, `helpScrollOffset`, help overlay visibility and scroll
|
|
60
|
+
* - `shortcutsOverlayActive`, `shortcutsScrollOffset`, shortcuts overlay state
|
|
61
|
+
* - `nextPasteId`, `nextImageId`, monotonically increasing ID counters
|
|
62
|
+
* - `mouseDownRow`, `mouseDownCol`, drag-tracking coordinates
|
|
63
|
+
* - `contentWidth`, reflow width (semi-stable; synced at feed() entry only)
|
|
64
|
+
* - `selectionCallback`, current in-flight selection modal callback (nullable)
|
|
65
|
+
* - `requestRender`, swapped per-feed to a buffered version, restored after
|
|
66
66
|
*
|
|
67
67
|
* **Stable service handles** (set once at construction, never reallocated):
|
|
68
|
-
* - `commandRegistry`, `commandContext
|
|
68
|
+
* - `commandRegistry`, `commandContext`, wired via setCommandRegistry() after
|
|
69
69
|
* construction; synced at feed() entry (not per-action) since no action changes them
|
|
70
|
-
* - `autocomplete
|
|
71
|
-
* - `inputHistory`, `conversationManager
|
|
70
|
+
* - `autocomplete`, wired after construction; synced at feed() entry
|
|
71
|
+
* - `inputHistory`, `conversationManager`, late-wired service handles; synced at
|
|
72
72
|
* feed() entry only since no in-feed action rewires them
|
|
73
|
-
* - `pasteRegistry`, `imageRegistry
|
|
73
|
+
* - `pasteRegistry`, `imageRegistry`, owned Maps, never replaced
|
|
74
74
|
* - `selectionModal`, `bookmarkModal`, `settingsModal`, `sessionPickerModal`,
|
|
75
|
-
* `profilePickerModal
|
|
75
|
+
* `profilePickerModal`, modal objects constructed once in InputHandler constructor
|
|
76
76
|
* - `filePicker`, `modelPicker`, `onboardingWizard`,
|
|
77
|
-
* `contextInspectorModal`, `blockActionsMenu`, `searchManager`, `historySearch
|
|
77
|
+
* `contextInspectorModal`, `blockActionsMenu`, `searchManager`, `historySearch`,
|
|
78
78
|
* service objects constructed once
|
|
79
|
-
* - `panelManager`, `keybindingsManager
|
|
80
|
-
* - `modalStack
|
|
81
|
-
* - `getHistory`, `getViewportHeight`, `getScrollTop`, `scroll`, `exitApp
|
|
79
|
+
* - `panelManager`, `keybindingsManager`, from uiServices, stable for app lifetime
|
|
80
|
+
* - `modalStack`, reference to the handler's shared array (mutated in place)
|
|
81
|
+
* - `getHistory`, `getViewportHeight`, `getScrollTop`, `scroll`, `exitApp`, stable
|
|
82
82
|
* callbacks bound in the InputHandler constructor
|
|
83
|
-
* - All method closures (`modalOpened`, `handleEscape`, etc.)
|
|
83
|
+
* - All method closures (`modalOpened`, `handleEscape`, etc.), bound once at init
|
|
84
84
|
*
|
|
85
85
|
* **Rationale:** per-feed mutation avoids per-keystroke allocation cost; stable
|
|
86
86
|
* references are service handles whose identity never changes after construction.
|
|
@@ -130,9 +130,9 @@ export interface InputFeedContext {
|
|
|
130
130
|
inputHistory: InputHistory | null;
|
|
131
131
|
conversationManager: ConversationManager | null;
|
|
132
132
|
readonly killRing: KillRing;
|
|
133
|
-
/** Terminal focus tracker
|
|
133
|
+
/** Terminal focus tracker, updated here from 'focus' tokens, read by the unfocused-alert notifiers in core/. */
|
|
134
134
|
readonly focusTracker: FocusTracker;
|
|
135
|
-
/** item 5
|
|
135
|
+
/** item 5, the paste-flood guard's persistent state, mutated in place across tokens by handlePanelFocusToken (see panel-paste-flood-guard.ts). Never reallocated. */
|
|
136
136
|
readonly panelBurstGuard: PanelBurstGuardState;
|
|
137
137
|
readonly getHistory: () => InfiniteBuffer;
|
|
138
138
|
readonly getViewportHeight: () => number;
|
|
@@ -186,7 +186,7 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
186
186
|
const keybindings = context.keybindingsManager;
|
|
187
187
|
|
|
188
188
|
// Shared opener for the Fleet panel: makes it visible AND transfers keyboard
|
|
189
|
-
// focus to it. panelManager.open() only makes the panel active
|
|
189
|
+
// focus to it. panelManager.open() only makes the panel active, focus is a
|
|
190
190
|
// separate axis (see PanelManager.focusPanels()/getFocusTarget()); without the
|
|
191
191
|
// focusPanels() call, j/k/i/K land silently in the composer until Tab. Used by
|
|
192
192
|
// the footer indicator's [Enter] and by F2 (F2 and the footer
|
|
@@ -199,20 +199,20 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
199
199
|
};
|
|
200
200
|
|
|
201
201
|
// Paste-ness is a per-TOKEN property, computed at the handlePanelFocusToken
|
|
202
|
-
// call below
|
|
202
|
+
// call below, never a per-feed character sum. The SDK tokenizer emits a
|
|
203
203
|
// bracketed paste (\x1b[?2004h, enabled in main.ts terminal init) as ONE
|
|
204
|
-
// 'text' token holding the whole payload, while discrete keystrokes
|
|
205
|
-
// several batched into one feed() by render-tick latency
|
|
204
|
+
// 'text' token holding the whole payload, while discrete keystrokes, even
|
|
205
|
+
// several batched into one feed() by render-tick latency, arrive as
|
|
206
206
|
// separate 1-char 'text' tokens. The old per-feed sum misread two quick nav
|
|
207
207
|
// keystrokes (e.g. j then k in one drain) as a "burst" and yanked focus.
|
|
208
208
|
// item 5's flood guard reuses that same per-token model but adds
|
|
209
|
-
// real timing: one `now` per feed() call (not per token) is intentional
|
|
209
|
+
// real timing: one `now` per feed() call (not per token) is intentional,
|
|
210
210
|
// a genuine flood delivers many tokens in one drain, and they should all
|
|
211
211
|
// measure as arriving "at once", not spread across meaningless sub-ms noise.
|
|
212
212
|
const now = Date.now();
|
|
213
213
|
for (const token of tokens) {
|
|
214
214
|
// Focus-reporting tokens (CSI ?1004h) never reach the composer or any
|
|
215
|
-
// modal route
|
|
215
|
+
// modal route, consumed here, first, unconditionally. No render needed.
|
|
216
216
|
if (token.type === 'focus') {
|
|
217
217
|
context.focusTracker.setFocused(token.action === 'in');
|
|
218
218
|
continue;
|
|
@@ -289,7 +289,7 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
289
289
|
if (token.type === 'key') {
|
|
290
290
|
// Focus can never disagree with workspace visibility: PanelManager owns
|
|
291
291
|
// focusTarget and self-heals it, and context.panelFocused was seeded from
|
|
292
|
-
// it at feed entry
|
|
292
|
+
// it at feed entry, so no manual "unfocus if panels vanished" patch is
|
|
293
293
|
// needed here anymore.
|
|
294
294
|
// Snapshot these four BEFORE dispatch so the write-back below can tell
|
|
295
295
|
// a pipeline-driven change (see comment there) from a stale copy.
|
|
@@ -332,7 +332,7 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
332
332
|
if (handleGlobalShortcutToken(shortcutState, token, viewportHeight)) {
|
|
333
333
|
// Some branches (handleEscape, handleCtrlC, handleUndo, handleRedo,
|
|
334
334
|
// handlePaste) mutate handler state directly and immediately sync it
|
|
335
|
-
// into this same `context` via syncFeedContextMutableFields
|
|
335
|
+
// into this same `context` via syncFeedContextMutableFields, e.g.
|
|
336
336
|
// Escape closing the slash-command palette clears context.prompt and
|
|
337
337
|
// context.commandMode on the live handler mid-call. `shortcutState`
|
|
338
338
|
// above is a snapshot taken BEFORE that call, so applying it
|
|
@@ -383,7 +383,7 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
383
383
|
// focused panel (Invariant A: focus never silently flips to the composer).
|
|
384
384
|
onPasteDropped: (panelName: string) =>
|
|
385
385
|
context.commandContext?.print(
|
|
386
|
-
`paste ignored
|
|
386
|
+
`paste ignored: focus is on ${panelName}; Tab returns to composer`,
|
|
387
387
|
),
|
|
388
388
|
isTurnActive: () => context.commandContext?.isGenerating?.() ?? false,
|
|
389
389
|
cancelGeneration: () => context.commandContext?.cancelGeneration?.(),
|
|
@@ -68,7 +68,7 @@ export async function hydrateOnboardingWizardFromRuntimeForHandler(handler: Inpu
|
|
|
68
68
|
* The prompt is edited on the HANDLER here, not on the shortcut route state
|
|
69
69
|
* that dispatched the key. feedInputTokens snapshots the prompt before
|
|
70
70
|
* dispatching and would write that snapshot back over this edit, erasing the
|
|
71
|
-
* paste
|
|
71
|
+
* paste, it does not, because it only restores a field the action left
|
|
72
72
|
* untouched (see the promptBefore guard in handler-feed.ts). That guard is the
|
|
73
73
|
* only reason Ctrl+V works, so it is pinned by test.
|
|
74
74
|
*/
|
|
@@ -150,7 +150,7 @@ export function handleCopyForHandler(handler: InputHandler): void {
|
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* handleBlockCopy - Ctrl+Y: Copy the content of the block the user is
|
|
153
|
-
* looking at (the viewport's bottom-most visible block
|
|
153
|
+
* looking at (the viewport's bottom-most visible block, see
|
|
154
154
|
* InputHandler.getBlockAnchorLine).
|
|
155
155
|
*/
|
|
156
156
|
export function handleBlockCopyForHandler(handler: InputHandler): void {
|
|
@@ -99,7 +99,7 @@ export function handleSelectionModalToken(state: SelectionRouteState, token: Inp
|
|
|
99
99
|
// instant filter: an unclaimed keystroke arms search AND starts
|
|
100
100
|
// the query immediately, instead of silently doing nothing until the
|
|
101
101
|
// user discovers '/' first (the "help search needs '/' arming while
|
|
102
|
-
// the palette filters instantly" evaluator finding
|
|
102
|
+
// the palette filters instantly" evaluator finding, /help has no
|
|
103
103
|
// customActions, so every letter used to be swallowed here). '/'
|
|
104
104
|
// above still works too; this is additive, not a replacement, and
|
|
105
105
|
// never fires for a claimed hotkey letter (checked first, above).
|
|
@@ -110,10 +110,10 @@ export function handleSelectionModalToken(state: SelectionRouteState, token: Inp
|
|
|
110
110
|
} else if (token.type === 'key') {
|
|
111
111
|
if (token.logicalName === 'escape') {
|
|
112
112
|
// ONE Escape always closes the modal, regardless of search state.
|
|
113
|
-
// Clearing an in-progress query is Backspace's job, not Esc's
|
|
113
|
+
// Clearing an in-progress query is Backspace's job, not Esc's, the old
|
|
114
114
|
// two-stage contract (1st Esc clears query, 2nd blurs search, 3rd
|
|
115
115
|
// finally closes) was the "help modal took 3 Escapes after searching"
|
|
116
|
-
// evaluator finding (searchFocused is not modal-specific
|
|
116
|
+
// evaluator finding (searchFocused is not modal-specific, every
|
|
117
117
|
// SelectionModal-based picker had the same multi-Esc pattern).
|
|
118
118
|
state.handleEscape();
|
|
119
119
|
return true;
|
|
@@ -372,7 +372,7 @@ export function handleSettingsModalToken(state: SettingsRouteState, token: Input
|
|
|
372
372
|
if (token.type === 'key') {
|
|
373
373
|
const focusPane = state.settingsModal.focusPane ?? 'settings';
|
|
374
374
|
if (token.logicalName === 'escape') {
|
|
375
|
-
// Cancel inline edit first
|
|
375
|
+
// Cancel inline edit first, mirrors the global contract in handler-modal-stack.ts.
|
|
376
376
|
// Must check editingMode before searchFocused: the reachable path
|
|
377
377
|
// search→Enter(string/number)→Esc must cancel the edit, NOT just clear search.
|
|
378
378
|
if (state.settingsModal.editingMode) {
|
|
@@ -400,7 +400,7 @@ export function handleSettingsModalToken(state: SettingsRouteState, token: Input
|
|
|
400
400
|
else {
|
|
401
401
|
// Feature-unit toggle headers are boolean settings rows now, so
|
|
402
402
|
// activateSelected toggles them (via the flag-toggle chokepoint) the same
|
|
403
|
-
// way it edits/toggles any other setting
|
|
403
|
+
// way it edits/toggles any other setting, no flags-category special case.
|
|
404
404
|
state.settingsModal.activateSelected();
|
|
405
405
|
consumeSettingsPickerRequest(state);
|
|
406
406
|
}
|
|
@@ -456,7 +456,7 @@ export function handleSettingsModalToken(state: SettingsRouteState, token: Input
|
|
|
456
456
|
}
|
|
457
457
|
} else if (token.type === 'text') {
|
|
458
458
|
if (state.settingsModal.editingMode) {
|
|
459
|
-
// editingMode takes priority over search
|
|
459
|
+
// editingMode takes priority over search, Enter on a string/number search
|
|
460
460
|
// result enters inline edit; subsequent chars must go to editChar, not the query.
|
|
461
461
|
state.settingsModal.editChar(token.value);
|
|
462
462
|
} else if (state.settingsModal.searchFocused) {
|
|
@@ -577,16 +577,16 @@ type ConfigModalRouteState = {
|
|
|
577
577
|
/**
|
|
578
578
|
* Route a key to the generic config-modal host (MIGRATE-TO-MODAL
|
|
579
579
|
* surfaces). The host owns the reserved navigation keys (Esc, up/down/j/k tab
|
|
580
|
-
* left/right, and now '/'
|
|
580
|
+
* left/right, and now '/', item 1's type-to-filter, armed the same
|
|
581
581
|
* way as scrollable-list-panel.ts's opt-in filter and SettingsModal's own
|
|
582
582
|
* '/'-armed search); every other key is offered to the active surface's
|
|
583
583
|
* declarative action table (fireAction handles the two-press confirm for
|
|
584
584
|
* destructive actions). Any unrecognised key is absorbed so the modal stays
|
|
585
|
-
* modal
|
|
585
|
+
* modal, this is the same "active modal captures all keys" shape as the
|
|
586
586
|
* other modal routers.
|
|
587
587
|
*
|
|
588
588
|
* While the filter is armed (`configModal.isFilterActive()`), printable text
|
|
589
|
-
* tokens go to the query instead of nav/action dispatch
|
|
589
|
+
* tokens go to the query instead of nav/action dispatch, this is WHY 'j'/'k'
|
|
590
590
|
* lose their vim-nav meaning mid-filter (you're typing, not navigating) but
|
|
591
591
|
* Escape, Backspace, and the arrow/tab nav keys keep their ordinary meaning
|
|
592
592
|
* (arrows navigate the FILTERED list; Enter still acts on the selected row).
|
|
@@ -594,7 +594,7 @@ type ConfigModalRouteState = {
|
|
|
594
594
|
export function handleConfigModalToken(state: ConfigModalRouteState, token: InputToken): boolean {
|
|
595
595
|
if (!state.configModal.active) return false;
|
|
596
596
|
|
|
597
|
-
// Every token that reaches the modal is a user interaction
|
|
597
|
+
// Every token that reaches the modal is a user interaction, after the
|
|
598
598
|
// first one, structure freezes to interaction boundaries (liveness rule).
|
|
599
599
|
// Before it, renders may sync structure so async onOpen loads appear
|
|
600
600
|
// without a keypress (batch refutation finding 3).
|
|
@@ -646,7 +646,7 @@ export function handleConfigModalToken(state: ConfigModalRouteState, token: Inpu
|
|
|
646
646
|
return true;
|
|
647
647
|
}
|
|
648
648
|
// Any other 'key' token (e.g. 'enter') falls through to the action table
|
|
649
|
-
// below even while filtering
|
|
649
|
+
// below even while filtering, only printable TEXT tokens are captured
|
|
650
650
|
// by the filter (below), so Enter still fires on the current selection.
|
|
651
651
|
} else if (token.type === 'text') {
|
|
652
652
|
if (!filtering && token.value === '/') {
|
|
@@ -655,8 +655,8 @@ export function handleConfigModalToken(state: ConfigModalRouteState, token: Inpu
|
|
|
655
655
|
return true;
|
|
656
656
|
}
|
|
657
657
|
if (filtering) {
|
|
658
|
-
// The WHOLE token value lands in the filter in one call
|
|
659
|
-
// multi-char paste token
|
|
658
|
+
// The WHOLE token value lands in the filter in one call, including a
|
|
659
|
+
// multi-char paste token, never split into per-char nav/action
|
|
660
660
|
// dispatch (the text-capture invariant this item's brief calls out).
|
|
661
661
|
state.configModal.appendFilterText(token.value);
|
|
662
662
|
state.requestRender();
|
|
@@ -150,7 +150,7 @@ export function handleEscape(state: EscapeState): {
|
|
|
150
150
|
state.autocompleteReset();
|
|
151
151
|
// Esc's palette-dismiss convention: a bare '/' with nothing typed
|
|
152
152
|
// after it IS the palette, so Esc clears it along with the slash
|
|
153
|
-
// (first Esc, one step, done
|
|
153
|
+
// (first Esc, one step, done, no lingering '/' to backspace out).
|
|
154
154
|
// Once the user has typed a command name (or anything else) past
|
|
155
155
|
// the slash, Esc's job is only to dismiss the ghost-suggestion
|
|
156
156
|
// overlay; the typed text is real composer content and stays put,
|
|
@@ -78,7 +78,7 @@ export type ModalTokenRouteState = {
|
|
|
78
78
|
searchManager: SearchManager;
|
|
79
79
|
scroll: (delta: number) => void;
|
|
80
80
|
getScrollTop: () => number;
|
|
81
|
-
/** Callback to open the model picker with a specific target (helper or tool). Optional
|
|
81
|
+
/** Callback to open the model picker with a specific target (helper or tool). Optional, only wired when available. */
|
|
82
82
|
openModelPickerWithTarget?: (
|
|
83
83
|
target: import('./model-picker.ts').ModelPickerTarget,
|
|
84
84
|
source?: 'settings' | 'onboarding',
|
|
@@ -27,11 +27,11 @@ import { GOODVIBES_TUI_SURFACE_ROOT } from '../config/surface.ts';
|
|
|
27
27
|
/**
|
|
28
28
|
* Immediately (not deferred to the final wizard Apply):
|
|
29
29
|
* 1. Installs the pasted token into <homeDirectory>/.goodvibes/daemon/operator-tokens.json
|
|
30
|
-
* via `resolveDaemonCompanionToken
|
|
30
|
+
* via `resolveDaemonCompanionToken`, the same durable-persistence logic
|
|
31
31
|
* the `GOODVIBES_DAEMON_TOKEN` non-interactive override uses.
|
|
32
32
|
* 2. Points `controlPlane.host`/`controlPlane.port` at the pasted host/port.
|
|
33
33
|
* 3. Restarts the external-services controller and reports back, honestly,
|
|
34
|
-
* whether the daemon at that host/port was actually adopted
|
|
34
|
+
* whether the daemon at that host/port was actually adopted, reusing
|
|
35
35
|
* the same `onboarding-runtime-status.ts` helpers the normal
|
|
36
36
|
* start-a-new-daemon path uses to report success/failure after Apply.
|
|
37
37
|
*
|
|
@@ -64,7 +64,7 @@ export async function handleConnectExistingDaemonForHandler(handler: InputHandle
|
|
|
64
64
|
resolveDaemonCompanionToken(daemonHomeDir, GOODVIBES_TUI_SURFACE_ROOT, token);
|
|
65
65
|
// hostMode has to move with the host. The control-plane URL is DERIVED from
|
|
66
66
|
// hostMode/host/port, and 'local' pins the dial target to 127.0.0.1 no
|
|
67
|
-
// matter what host is stored
|
|
67
|
+
// matter what host is stored, so adopting a daemon on another machine
|
|
68
68
|
// while leaving hostMode alone would derive a loopback URL for a remote
|
|
69
69
|
// daemon. Adopting a loopback address stays 'local'.
|
|
70
70
|
handler.uiServices.platform.configManager.setDynamic(
|
|
@@ -103,7 +103,7 @@ export async function handleConnectExistingDaemonForHandler(handler: InputHandle
|
|
|
103
103
|
* `goodvibes-daemon.service` unit (an earlier release shipped detect+disclose only; this
|
|
104
104
|
* closes that inheritance). This is a thin wrapper over
|
|
105
105
|
* `detectLegacyUnit` + `runLegacyDaemonMigration`
|
|
106
|
-
* (`../runtime/legacy-daemon-migration.ts`)
|
|
106
|
+
* (`../runtime/legacy-daemon-migration.ts`), the actual migration mechanics
|
|
107
107
|
* (never auto-migrate, new-up-then-old-down with a health check before the
|
|
108
108
|
* legacy unit is touched, adopt-or-warn for an unrecognized process on the
|
|
109
109
|
* port) live there and are exercised against fakes in
|
|
@@ -117,7 +117,7 @@ export async function handleConnectExistingDaemonForHandler(handler: InputHandle
|
|
|
117
117
|
* This lives in `src/input/` rather than importing
|
|
118
118
|
* `../daemon/service-commands.ts` directly because the architecture gate's
|
|
119
119
|
* `input-no-entrypoints` rule forbids `src/input/**` from depending on
|
|
120
|
-
* `src/daemon/**` (input must stay a pure event-handling layer)
|
|
120
|
+
* `src/daemon/**` (input must stay a pure event-handling layer), the shared
|
|
121
121
|
* engine lives in the entrypoint-agnostic `src/runtime/` layer instead.
|
|
122
122
|
*
|
|
123
123
|
* `confirm` is caller-supplied rather than read from a fixed field name here
|
|
@@ -125,7 +125,7 @@ export async function handleConnectExistingDaemonForHandler(handler: InputHandle
|
|
|
125
125
|
* step (`onboarding-wizard-network-adopt.ts`'s `pushLegacyDaemonMigrationFields`,
|
|
126
126
|
* dispatched from `handler-onboarding.ts`'s `migrate-legacy-daemon-service`
|
|
127
127
|
* action) reads its own `network.migrate-legacy-daemon-confirm` checklist
|
|
128
|
-
* toggle and passes it through as this parameter
|
|
128
|
+
* toggle and passes it through as this parameter, unchecked previews the
|
|
129
129
|
* dry-run plan (`confirm: false`), checked executes the real migration
|
|
130
130
|
* (`confirm: true`).
|
|
131
131
|
*/
|
|
@@ -21,7 +21,7 @@ type ModelPickerRouteState = {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* The user's REQUESTED reasoning level for this session, or undefined when the
|
|
24
|
-
* command context is not attached. Read from config through the shared helper
|
|
24
|
+
* command context is not attached. Read from config through the shared helper,
|
|
25
25
|
* never from `session.runtime.reasoningEffort`, which holds the EFFECTIVE level
|
|
26
26
|
* for whichever model is serving and would re-seed a resolution with an already
|
|
27
27
|
* snapped-down value.
|
|
@@ -36,7 +36,7 @@ function readRequestedEffort(state: ModelPickerRouteState): string | undefined {
|
|
|
36
36
|
* The level the effort step should open on for a model about to be selected:
|
|
37
37
|
* the requested level SNAPPED to that model. Opening on the raw requested level
|
|
38
38
|
* would miss the list entirely whenever the target model caps lower, and
|
|
39
|
-
* showEffortPicker falls back to index 0
|
|
39
|
+
* showEffortPicker falls back to index 0, landing the cursor on the LOWEST
|
|
40
40
|
* level rather than on what pressing Enter would actually give you.
|
|
41
41
|
*/
|
|
42
42
|
function effortStepPreselect(state: ModelPickerRouteState, model: { id: string; provider?: string; displayName?: string }): string {
|
|
@@ -52,7 +52,7 @@ export function handleModelPickerToken(state: ModelPickerRouteState, token: Inpu
|
|
|
52
52
|
// Search now starts focused by default (see
|
|
53
53
|
// ModelPickerModal.openAllModels() doc comment). Escape with an empty
|
|
54
54
|
// query used to only blurSearch() here, leaving the picker open and
|
|
55
|
-
// requiring a SECOND Escape to actually close it
|
|
55
|
+
// requiring a SECOND Escape to actually close it, confusing on a
|
|
56
56
|
// freshly-opened, untouched picker where there is nothing to "clear".
|
|
57
57
|
// Clearing a non-empty query is still a distinct first Escape (whether
|
|
58
58
|
// or not search is focused); an empty query falls through to the same
|
|
@@ -92,9 +92,9 @@ export function handleModelPickerToken(state: ModelPickerRouteState, token: Inpu
|
|
|
92
92
|
// even while a model that caps lower is serving.
|
|
93
93
|
const currentEffort = readRequestedEffort(state) ?? 'medium';
|
|
94
94
|
// Whether an effort step appears at all is now this model's own
|
|
95
|
-
// resolved spec: a model with no configurable reasoning level
|
|
95
|
+
// resolved spec: a model with no configurable reasoning level, or
|
|
96
96
|
// one whose levels are only a labelled best guess the adapters will
|
|
97
|
-
// discard
|
|
97
|
+
// discard, skips straight to commit instead of showing a list it
|
|
98
98
|
// does not honour.
|
|
99
99
|
if (state.modelPicker.target === 'main' && offersConfigurableEffort(toEffortModel(selected))) {
|
|
100
100
|
state.modelPicker.showEffortPicker(selected, effortStepPreselect(state, selected));
|
|
@@ -152,7 +152,7 @@ export function handleModelPickerToken(state: ModelPickerRouteState, token: Inpu
|
|
|
152
152
|
const rawInput = state.modelPicker.contextCapQuery.trim();
|
|
153
153
|
const parsedCap = rawInput.length > 0 ? parseInt(rawInput, 10) : null;
|
|
154
154
|
if (parsedCap !== null && (parsedCap <= 0 || parsedCap > 10_000_000)) {
|
|
155
|
-
// Non-empty but out of valid range
|
|
155
|
+
// Non-empty but out of valid range, surface notice; keep picker open for correction.
|
|
156
156
|
state.modelPicker.contextCapError = 'Context cap must be 1–10,000,000';
|
|
157
157
|
} else {
|
|
158
158
|
state.modelPicker.contextCapError = null;
|
|
@@ -231,7 +231,7 @@ export function handleModelPickerToken(state: ModelPickerRouteState, token: Inpu
|
|
|
231
231
|
if (state.modelPicker.mode === 'contextCap') {
|
|
232
232
|
if (token.value.length === 1) state.modelPicker.appendContextCapChar(token.value);
|
|
233
233
|
} else if ((state.modelPicker.mode === 'model' || state.modelPicker.mode === 'provider') && state.modelPicker.searchFocused) {
|
|
234
|
-
// When search is focused every printable char
|
|
234
|
+
// When search is focused every printable char, including space, goes to the query.
|
|
235
235
|
// The space=context-cap shortcut remains active only in the non-search branch below.
|
|
236
236
|
const ch = token.value;
|
|
237
237
|
if (ch.length === 1 && ch >= ' ') state.modelPicker.appendChar(ch);
|
|
@@ -23,7 +23,7 @@ export const UNDO_COALESCE_MS = 500;
|
|
|
23
23
|
export type EditKind = 'text' | 'kill' | 'yank' | 'other';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* shouldCoalesceUndo
|
|
26
|
+
* shouldCoalesceUndo, returns true when the new edit should be merged into
|
|
27
27
|
* the most recent undo group rather than creating a new snapshot.
|
|
28
28
|
*
|
|
29
29
|
* Coalesces only when:
|
|
@@ -77,13 +77,13 @@ export function handleGlobalShortcutToken(
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// Bare F2 is also not in the keybinding table (hardcoded, like pageup/
|
|
80
|
-
// pagedown/escape above)
|
|
80
|
+
// pagedown/escape above), it must be handled here, GLOBALLY, rather than
|
|
81
81
|
// in handlePromptKeyToken (handler-feed-routes.ts) where it used to live.
|
|
82
82
|
// That location only ever runs when the panel workspace does NOT already
|
|
83
83
|
// own focus (handlePanelFocusToken, which runs before it, swallows every
|
|
84
84
|
// unclaimed key once panelFocused is true and reports it handled). The
|
|
85
85
|
// practical effect was that F2 could OPEN+focus the Fleet panel exactly
|
|
86
|
-
// once; every subsequent press while already focused vanished silently
|
|
86
|
+
// once; every subsequent press while already focused vanished silently,
|
|
87
87
|
// "F2 pressed 4x never closed the panel" (evaluator finding). Routing
|
|
88
88
|
// it here, before handlePanelFocusToken ever sees the token, gives F2 the
|
|
89
89
|
// same toggle semantics as Ctrl+O below, matching how Ctrl+P/panel-picker
|
|
@@ -94,8 +94,8 @@ export function handleGlobalShortcutToken(
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
// Shift+Tab cycles the session permission mode (normal → accept-edits → plan
|
|
97
|
-
// → auto → normal), the settled convention. Handled here
|
|
98
|
-
// escape/f2
|
|
97
|
+
// → auto → normal), the settled convention. Handled here, hardcoded, like
|
|
98
|
+
// escape/f2, because it is not in the keybinding table and bare Tab is
|
|
99
99
|
// already heavily overloaded. Arrives as the legacy xterm backtab literal
|
|
100
100
|
// ('\x1b[Z') OR, under a kitty/CSI-u terminal, as tab-with-shift. Only when
|
|
101
101
|
// the composer owns focus (a focused panel keeps its own Shift+Tab, e.g. the
|
|
@@ -121,7 +121,7 @@ export function handleGlobalShortcutToken(
|
|
|
121
121
|
|
|
122
122
|
case 'cancel-tool-call':
|
|
123
123
|
// Cancel JUST the currently-running tool call (the live transcript row).
|
|
124
|
-
// No-op (still consumed) when nothing is running
|
|
124
|
+
// No-op (still consumed) when nothing is running, the composer keeps the
|
|
125
125
|
// keystroke rather than letting it fall through as text.
|
|
126
126
|
state.commandContext?.cancelToolCall?.();
|
|
127
127
|
return true;
|
|
@@ -134,7 +134,7 @@ export function handleGlobalShortcutToken(
|
|
|
134
134
|
|
|
135
135
|
case 'voice-input':
|
|
136
136
|
// Start recording, or stop the recording already running. Routed globally so
|
|
137
|
-
// the key works whether focus is on the composer or the panel workspace
|
|
137
|
+
// the key works whether focus is on the composer or the panel workspace,
|
|
138
138
|
// dictation is not a composer-only act. Still consumed when voice input is
|
|
139
139
|
// not wired, so a stray Alt+V never lands in the prompt as text.
|
|
140
140
|
state.commandContext?.toggleVoiceInput?.();
|
|
@@ -168,11 +168,11 @@ export function handleGlobalShortcutToken(
|
|
|
168
168
|
const active = pm.getActivePanel();
|
|
169
169
|
// Give the active panel a chance to consume Ctrl+X for an
|
|
170
170
|
// in-panel action (FleetPanel session-tab detach) before it closes the
|
|
171
|
-
// panel outright
|
|
171
|
+
// panel outright, see Panel.interceptPanelClose's doc comment.
|
|
172
172
|
if (active?.interceptPanelClose?.()) {
|
|
173
173
|
// fix: a consumed Ctrl+X (the Fleet panel's session-tab detach)
|
|
174
174
|
// used to leave panelFocused untouched, so focus stayed on the panel
|
|
175
|
-
|
|
175
|
+
//, the evaluator's "Ctrl+X detach landed focus in the panel and a
|
|
176
176
|
// typed question became nav keys". Detach is a leave-taking action:
|
|
177
177
|
// like the ordinary close below, it hands control back to the
|
|
178
178
|
// composer rather than leaving the user stranded on the fleet tree.
|
|
@@ -203,7 +203,7 @@ export function handleGlobalShortcutToken(
|
|
|
203
203
|
// Global entry point for the focus-toggle key (Ctrl+G): from the prompt
|
|
204
204
|
// it grabs focus for the panel workspace. Once the workspace already has
|
|
205
205
|
// focus we let it fall through (return false) so handlePanelFocusToken
|
|
206
|
-
// can do the top/bottom pane swap
|
|
206
|
+
// can do the top/bottom pane swap, keeping that behavior in one place.
|
|
207
207
|
if (state.panelFocused) return false;
|
|
208
208
|
const pm = state.panelManager;
|
|
209
209
|
if (pm.isVisible() && pm.getAllOpen().length > 0) {
|
|
@@ -234,7 +234,7 @@ export function handleGlobalShortcutToken(
|
|
|
234
234
|
// Alt+1..9: jump directly to the Nth workspace tab. Routed globally (like
|
|
235
235
|
// panel-tab-next/prev) so the jump works whether focus is on the prompt or
|
|
236
236
|
// the workspace; gated on visibility, matching cyclePanelTab semantics.
|
|
237
|
-
// a chord jump is "I'm going panel-driving" (focus rule 1a)
|
|
237
|
+
// a chord jump is "I'm going panel-driving" (focus rule 1a), the
|
|
238
238
|
// jump now also grabs keyboard focus, matching F2/Ctrl+O/Ctrl+P, so j/k
|
|
239
239
|
// land in the newly-active tab immediately instead of the composer.
|
|
240
240
|
const pm = state.panelManager;
|
|
@@ -434,7 +434,7 @@ export function handleGlobalShortcutToken(
|
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
/**
|
|
437
|
-
* toggleFleetPanel
|
|
437
|
+
* toggleFleetPanel, the shared F2 / Ctrl+O TOGGLE (item 2): if the
|
|
438
438
|
* Fleet panel is open AND the panel workspace currently owns keyboard focus
|
|
439
439
|
* with Fleet as the active tab, the chord CLOSES it and returns focus to the
|
|
440
440
|
* composer; if Fleet is open but not the focused/active tab, the chord brings
|
|
@@ -446,7 +446,7 @@ export function handleGlobalShortcutToken(
|
|
|
446
446
|
*/
|
|
447
447
|
/**
|
|
448
448
|
* Cycle the session permission mode (Shift+Tab). The change goes through the
|
|
449
|
-
* SDK config surface
|
|
449
|
+
* SDK config surface, configManager.set('permissions.mode', ...), which is
|
|
450
450
|
* what the SDK PermissionManager reads and what the orchestrator consults for
|
|
451
451
|
* its standing plan-mode instruction, so every attached surface converges on
|
|
452
452
|
* the same mode. The footer pill re-renders off the config-key subscription
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* handler-types.ts
|
|
2
|
+
* handler-types.ts, Leaf interface for InputHandler.
|
|
3
3
|
*
|
|
4
4
|
* Extracted from handler.ts to break circular import chains between handler.ts
|
|
5
5
|
* and handler-interactions.ts / handler-onboarding.ts / handler-onboarding-cloudflare.ts.
|
|
@@ -137,8 +137,8 @@ export interface InputHandlerLike {
|
|
|
137
137
|
handleBookmark(): void;
|
|
138
138
|
handleBlockToggle(): void;
|
|
139
139
|
handleDiffApply(): boolean;
|
|
140
|
-
/** The absolute history line of the bottom-most visible block
|
|
141
|
-
* the user is actually looking at
|
|
140
|
+
/** The absolute history line of the bottom-most visible block, the block
|
|
141
|
+
* the user is actually looking at, used to anchor every one of the
|
|
142
142
|
* actions above instead of the (possibly off-screen-above) raw scrollTop. */
|
|
143
143
|
getBlockAnchorLine(): number;
|
|
144
144
|
|
|
@@ -203,7 +203,7 @@ type SearchRouteState = {
|
|
|
203
203
|
scroll: (delta: number) => void;
|
|
204
204
|
getScrollTop: () => number;
|
|
205
205
|
getViewportHeight: () => number;
|
|
206
|
-
/** Optional
|
|
206
|
+
/** Optional, when present, search() also expands collapsed blocks whose
|
|
207
207
|
* raw content matches (see SearchManager.search's doc). */
|
|
208
208
|
conversationManager?: ConversationManager | null;
|
|
209
209
|
};
|