@pellux/goodvibes-tui 2.0.14 → 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 +35 -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
package/src/cli/tui-startup.ts
CHANGED
|
@@ -22,10 +22,10 @@ export type FirstOpenTrustLevel = 'trusted' | 'restricted';
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* What `resumeNamedSessionWithRecoveryCheck` needs to actually APPLY an
|
|
25
|
-
* accepted crash-recovery snapshot
|
|
25
|
+
* accepted crash-recovery snapshot, the same shape `buildRecoveryOfferWiring`
|
|
26
26
|
* (runtime/recovery-offer-wiring.ts) takes, minus `surface` and
|
|
27
27
|
* `commandContext` which this module already has in scope. Optional: a caller
|
|
28
|
-
* that omits it (or a snapshot-free boot) gets exactly today's behavior
|
|
28
|
+
* that omits it (or a snapshot-free boot) gets exactly today's behavior,
|
|
29
29
|
* straight resume from the durable store, no modal.
|
|
30
30
|
*/
|
|
31
31
|
export interface TuiStartupRecoveryDeps {
|
|
@@ -37,7 +37,7 @@ export interface TuiStartupRecoveryDeps {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* resumeNamedSessionWithRecoveryCheck
|
|
40
|
+
* resumeNamedSessionWithRecoveryCheck, the pre-resume guard for `--continue`
|
|
41
41
|
* and the bare `--resume` (pointer) path.
|
|
42
42
|
*
|
|
43
43
|
* Resuming a named session straight from its durable store is exactly the
|
|
@@ -47,13 +47,13 @@ export interface TuiStartupRecoveryDeps {
|
|
|
47
47
|
* read-only probe for that; when it finds one, this routes through the same
|
|
48
48
|
* ask-then-retire modal flow the general boot offer uses
|
|
49
49
|
* (runtime/recovery-prompt.ts), scoped to this one session via
|
|
50
|
-
* `targetSessionId
|
|
50
|
+
* `targetSessionId`, never auto-applied.
|
|
51
51
|
*
|
|
52
52
|
* - No live snapshot (or `recovery` deps not wired): straight resume, same
|
|
53
53
|
* as before this check existed.
|
|
54
54
|
* - Resume chosen: the snapshot is applied (via `buildRecoveryOfferWiring`'s
|
|
55
55
|
* `applySnapshot`, which rebinds the runtime session id and replays any
|
|
56
|
-
* journal tail) and the plain store resume is skipped
|
|
56
|
+
* journal tail) and the plain store resume is skipped, the snapshot IS
|
|
57
57
|
* the more complete copy.
|
|
58
58
|
* - "Not now" (or a dismissal, or a failed load): falls through to the
|
|
59
59
|
* plain store resume, after the follow-up Keep/Remove question the
|
|
@@ -63,7 +63,7 @@ export interface TuiStartupRecoveryDeps {
|
|
|
63
63
|
* `scheduleRecoveryOffer`'s own reasoning: `applyInitialTuiCliState` runs
|
|
64
64
|
* before the shell's first render, so asking a question here synchronously
|
|
65
65
|
* would draw it at a blank terminal. The synchronous `checkRecoveryForSession`
|
|
66
|
-
* probe above needs no such deferral
|
|
66
|
+
* probe above needs no such deferral, only opening the modal does.
|
|
67
67
|
*/
|
|
68
68
|
async function resumeNamedSessionWithRecoveryCheck(options: {
|
|
69
69
|
readonly sessionId: string;
|
|
@@ -124,7 +124,7 @@ async function resumeNamedSessionWithRecoveryCheck(options: {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/**
|
|
127
|
-
* decodeFirstOpenChoice
|
|
127
|
+
* decodeFirstOpenChoice, pure mapping from a chosen selection-item id (or
|
|
128
128
|
* null on Escape/enter-through) to the trust decision. Kept pure so the
|
|
129
129
|
* consequence-time trust prompt's semantics (raised by trustGatedAsk, wired
|
|
130
130
|
* in main.ts's trustPromptRef.requestTrustDecision) are unit-testable
|
|
@@ -137,16 +137,16 @@ export function decodeFirstOpenChoice(id: string | null): FirstOpenTrustLevel {
|
|
|
137
137
|
|
|
138
138
|
/**
|
|
139
139
|
* Build the selection rows for the trust prompt. This used to also offer a
|
|
140
|
-
* "register this directory?" half (a combined 2x2 when both were needed)
|
|
140
|
+
* "register this directory?" half (a combined 2x2 when both were needed),
|
|
141
141
|
* that half is gone: registration self-records (see
|
|
142
142
|
* selfRecordWorkspaceRegistration below) rather than ever asking a question
|
|
143
143
|
* about a registry the user hasn't met yet.
|
|
144
144
|
*/
|
|
145
145
|
export function buildFirstOpenItems(): { readonly title: string; readonly items: SelectionItem[] } {
|
|
146
146
|
return {
|
|
147
|
-
title: 'New workspace
|
|
147
|
+
title: 'New workspace: choose a trust level',
|
|
148
148
|
items: [
|
|
149
|
-
{ id: 'trusted', label: 'Trust this workspace', detail: 'Full capability
|
|
149
|
+
{ id: 'trusted', label: 'Trust this workspace', detail: 'Full capability: all tools may run', primaryAction: 'select' },
|
|
150
150
|
{ id: 'restricted', label: 'Keep restricted (read-only)', detail: 'Explore safely; writes and commands are denied until trusted', primaryAction: 'select' },
|
|
151
151
|
],
|
|
152
152
|
};
|
|
@@ -155,8 +155,8 @@ export function buildFirstOpenItems(): { readonly title: string; readonly items:
|
|
|
155
155
|
/**
|
|
156
156
|
* Registration self-records: a workspace the user actually works in becomes
|
|
157
157
|
* its own registry entry with no question ever asked (the former "Register
|
|
158
|
-
* this directory as a workspace?" prompt
|
|
159
|
-
* trust was undecided too
|
|
158
|
+
* this directory as a workspace?" prompt, sometimes a four-option 2x2 when
|
|
159
|
+
* trust was undecided too, is gone entirely).
|
|
160
160
|
*
|
|
161
161
|
* "Actually works in" is anchored to TRUST, not mere directory-open: this is
|
|
162
162
|
* only ever called for a workspace that is (or has just become) trusted,
|
|
@@ -167,7 +167,7 @@ export function buildFirstOpenItems(): { readonly title: string; readonly items:
|
|
|
167
167
|
* checkpoint-owning consumer's boundary. That boundary now reads the SAME
|
|
168
168
|
* shared registration store this writes to, gated by each record's
|
|
169
169
|
* `checkpointEligible` flag (absent means false). So the separation is no
|
|
170
|
-
* longer "a separate list the agent owns"
|
|
170
|
+
* longer "a separate list the agent owns", it is one store, and this self
|
|
171
171
|
* record stays out of scope by stamping its `origin` ('tui') for honest
|
|
172
172
|
* provenance while NEVER setting `checkpointEligible`. Only the consumer that
|
|
173
173
|
* owns checkpointing re-stamps its own roots eligible on boot.
|
|
@@ -188,7 +188,7 @@ export function applyInitialTuiCliState(options: {
|
|
|
188
188
|
readonly commandContext: CommandContext;
|
|
189
189
|
readonly shellPaths: TuiStartupShellPaths;
|
|
190
190
|
/**
|
|
191
|
-
* The app's declare-once session-storage handle
|
|
191
|
+
* The app's declare-once session-storage handle, the SAME one the runtime
|
|
192
192
|
* writes the last-session pointer through. `--continue` and bare `--resume`
|
|
193
193
|
* read that pointer below; deriving its path independently here is exactly
|
|
194
194
|
* how this read used to land on a file nothing ever wrote.
|
|
@@ -199,7 +199,7 @@ export function applyInitialTuiCliState(options: {
|
|
|
199
199
|
* Enables the crash-recovery check ahead of `--continue` / bare `--resume`
|
|
200
200
|
* (see `resumeNamedSessionWithRecoveryCheck` above). Omitted, the two flags
|
|
201
201
|
* resume straight from the durable store exactly as before this check
|
|
202
|
-
* existed
|
|
202
|
+
* existed, main.ts always wires this; only tests that don't care about
|
|
203
203
|
* recovery snapshots leave it out.
|
|
204
204
|
*/
|
|
205
205
|
readonly continueRecovery?: TuiStartupRecoveryDeps;
|
|
@@ -208,7 +208,7 @@ export function applyInitialTuiCliState(options: {
|
|
|
208
208
|
const globalOnboardingMarker = readOnboardingCheckMarker(shellPaths, 'user');
|
|
209
209
|
|
|
210
210
|
// Registration self-records on every launch of an already-trusted
|
|
211
|
-
// workspace (fire-and-forget
|
|
211
|
+
// workspace (fire-and-forget, never blocks or gates startup, never a
|
|
212
212
|
// modal). A workspace that is undecided or restricted is never
|
|
213
213
|
// self-registered here; for one that becomes trusted just now (via the
|
|
214
214
|
// consequence-time trust prompt), main.ts's trustPromptRef wiring calls
|
|
@@ -233,7 +233,7 @@ export function applyInitialTuiCliState(options: {
|
|
|
233
233
|
}
|
|
234
234
|
} else if (cli.flags.continueLast) {
|
|
235
235
|
// --continue: resume the last session tracked by the pointer file. Checked
|
|
236
|
-
// for a live crash-recovery snapshot first
|
|
236
|
+
// for a live crash-recovery snapshot first, see
|
|
237
237
|
// resumeNamedSessionWithRecoveryCheck's doc comment.
|
|
238
238
|
const lastId = readLastSessionPointer({ surface });
|
|
239
239
|
if (lastId) {
|
|
@@ -263,7 +263,7 @@ export function applyInitialTuiCliState(options: {
|
|
|
263
263
|
} else if (!globalOnboardingMarker.exists) {
|
|
264
264
|
// Fast path: get a brand-new user to a working session in the fewest steps.
|
|
265
265
|
// Falls back to the full wizard when the surface can't detect providers.
|
|
266
|
-
// Trust stays undecided here on purpose
|
|
266
|
+
// Trust stays undecided here on purpose, the first non-read tool
|
|
267
267
|
// request is what raises the trust question now (see main.ts's
|
|
268
268
|
// trustPromptRef), not this startup branch.
|
|
269
269
|
startOnboardingFastPath({ input, commandContext, shellPaths, render });
|
|
@@ -288,17 +288,17 @@ export function applyInitialTuiCliState(options: {
|
|
|
288
288
|
}
|
|
289
289
|
// Returning user, no wizard to resume, nothing else to do at startup:
|
|
290
290
|
// trust (if still undecided) is asked at the first non-read tool
|
|
291
|
-
// request, not here
|
|
291
|
+
// request, not here, see main.ts's trustPromptRef wiring.
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
/**
|
|
296
|
-
* reportFatalStartupError
|
|
296
|
+
* reportFatalStartupError, the main() catch handler. A bare Error
|
|
297
297
|
* JSON-serializes to {} in structured logs, and background timers keep the
|
|
298
|
-
* process alive after a boot failure
|
|
298
|
+
* process alive after a boot failure, the historical result was a blank
|
|
299
299
|
* screen and a useless `Fatal error {"error": {}}` log line. Log real
|
|
300
300
|
* fields, tell the user what broke, and exit. Both writes are individually
|
|
301
|
-
* best-effort
|
|
301
|
+
* best-effort, a failing logger or torn-down stderr must never hide the
|
|
302
302
|
* original launch failure.
|
|
303
303
|
*/
|
|
304
304
|
export function reportFatalStartupError(err: unknown): void {
|
|
@@ -314,7 +314,7 @@ export function reportFatalStartupError(err: unknown): void {
|
|
|
314
314
|
// process.stderr to keep the rendered screen clean
|
|
315
315
|
// (runtime/terminal-output-guard.ts), so a replaced writer that records
|
|
316
316
|
// instead of printing would swallow the one line explaining why the screen
|
|
317
|
-
// is blank
|
|
317
|
+
// is blank, and a stream write issued immediately before the exit below
|
|
318
318
|
// can still be in flight when the process stops existing. The descriptor
|
|
319
319
|
// write is neither interceptable nor droppable. See
|
|
320
320
|
// daemon/fatal-boot-report.ts.
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* run-daemon-config-migration.ts
|
|
2
|
+
* run-daemon-config-migration.ts, the one call every TUI composition root
|
|
3
3
|
* makes before constructing its `ConfigManager`.
|
|
4
4
|
*
|
|
5
5
|
* Daemon-owned configuration now has exactly one home:
|
|
6
6
|
* `~/.goodvibes/daemon/settings.json`. Before this migration, every product
|
|
7
7
|
* wrote every key (including daemon-only ones like `surfaces.telegram.*`)
|
|
8
8
|
* into its own per-surface silo, and the daemon only ever read
|
|
9
|
-
* `~/.goodvibes/tui/settings.json
|
|
9
|
+
* `~/.goodvibes/tui/settings.json`, so a value written by, say, the agent
|
|
10
10
|
* surface reported a successful save and configured nothing the daemon could
|
|
11
11
|
* see.
|
|
12
12
|
*
|
|
13
13
|
* `migrateDaemonOwnedConfig` (SDK, `platform/config`) is idempotent and cheap
|
|
14
14
|
* on the fast path (one file read + JSON parse), so it is safe and correct to
|
|
15
15
|
* call this at every composition root that is about to construct a
|
|
16
|
-
* `ConfigManager
|
|
16
|
+
* `ConfigManager`, not just the first one to run in a given process. It
|
|
17
17
|
* must never abort startup: any failure is caught, logged with the marker
|
|
18
18
|
* path so the failure is diagnosable, and startup continues on whatever
|
|
19
19
|
* config state already exists.
|
|
@@ -4,21 +4,21 @@ import type { SecretScope, SecretStorageMedium } from './secrets.ts';
|
|
|
4
4
|
|
|
5
5
|
export const SECRET_CONFIG_KEYS = new Set<ConfigKey>([
|
|
6
6
|
// Mailbox and CalDAV credentials. Their own CONFIG_SCHEMA descriptions read
|
|
7
|
-
// "Stored in the daemon secret tier, never in config"
|
|
7
|
+
// "Stored in the daemon secret tier, never in config", and until they were
|
|
8
8
|
// listed here that sentence was aspirational: the settings modal wrote them
|
|
9
9
|
// as plain strings into a config JSON file, because membership in this set is
|
|
10
10
|
// the thing that routes an edit through the secret manager instead.
|
|
11
11
|
//
|
|
12
12
|
// The daemon reads each of these back with
|
|
13
13
|
// resolveConfigSecret('<key>') → GOODVIBES_<KEY>, which is exactly the store
|
|
14
|
-
// key buildGoodVibesSecretKey() writes
|
|
14
|
+
// key buildGoodVibesSecretKey() writes, see
|
|
15
15
|
// daemon/handlers/inbox/providers/email.ts.
|
|
16
16
|
'surfaces.email.password',
|
|
17
17
|
'surfaces.email.imapPassword',
|
|
18
18
|
'surfaces.email.imap.password',
|
|
19
19
|
'surfaces.email.smtp.password',
|
|
20
20
|
'surfaces.calendar.caldavPassword',
|
|
21
|
-
// Telephony delivery credentials
|
|
21
|
+
// Telephony delivery credentials, same shape, same file, same gap.
|
|
22
22
|
'surfaces.telephony.authToken',
|
|
23
23
|
'surfaces.telephony.token',
|
|
24
24
|
'surfaces.telephony.webhookSecret',
|
|
@@ -43,7 +43,7 @@ export const SECRET_CONFIG_KEYS = new Set<ConfigKey>([
|
|
|
43
43
|
'surfaces.mattermost.botToken',
|
|
44
44
|
'surfaces.matrix.accessToken',
|
|
45
45
|
// TUI-local synthetic sub-keys, one level under the SDK's real `payments`
|
|
46
|
-
// section (not a scalar CONFIG_SCHEMA entry
|
|
46
|
+
// section (not a scalar CONFIG_SCHEMA entry, same situation as
|
|
47
47
|
// behavior.notifyAfterSeconds and the other synthetics in
|
|
48
48
|
// settings-modal-data.ts), hence the cast. See input/payments-config.ts for why these are named flat
|
|
49
49
|
// (payments.cardNumber, not payments.card.number): a flat one-level leaf is
|
|
@@ -131,14 +131,14 @@ export function buildSecretBackedConfigUpdate(configKey: ConfigKey, rawValue: st
|
|
|
131
131
|
* A daemon-owned config key (`surfaces.*`, `payments.*`, `controlPlane.*`, ...)
|
|
132
132
|
* names a credential the DAEMON executes with, not this interactive client, so
|
|
133
133
|
* its secret material belongs in the daemon-scoped tier the daemon actually
|
|
134
|
-
* reads
|
|
134
|
+
* reads, the same rule the SDK's config-ownership.ts already applies to the
|
|
135
135
|
* `goodvibes://` reference that points at it.
|
|
136
136
|
*
|
|
137
137
|
* Defaulting these to 'user' (the historical behavior here) split the pair: the
|
|
138
138
|
* reference landed in the daemon's own settings file, because ConfigManager
|
|
139
139
|
* routes daemon-owned keys there, while the value it pointed at sat in a tier
|
|
140
140
|
* the daemon never resolves. The surface reported success and the daemon found
|
|
141
|
-
* nothing. For the mailbox password that is the whole feature failing silently
|
|
141
|
+
* nothing. For the mailbox password that is the whole feature failing silently,
|
|
142
142
|
* the daemon is the process that polls IMAP and answers over Telegram, and it
|
|
143
143
|
* does so with every surface closed. A payment card entered through
|
|
144
144
|
* /payments card is the same shape of failure at purchase time.
|
|
@@ -153,7 +153,7 @@ export function defaultSecretBackedScope(configKey: ConfigKey): SecretScope {
|
|
|
153
153
|
* One call, not two: `credentials.set` derives the store key, writes the value,
|
|
154
154
|
* reads it back to verify, and only then points the config key at it. Doing
|
|
155
155
|
* those halves separately from here would leave a window where the config
|
|
156
|
-
* names a reference that resolves to nothing
|
|
156
|
+
* names a reference that resolves to nothing, which every reader treats as a
|
|
157
157
|
* configured-but-broken credential.
|
|
158
158
|
*/
|
|
159
159
|
export interface DaemonCredentialWriter {
|
|
@@ -173,7 +173,7 @@ export async function persistSecretBackedConfigValue(
|
|
|
173
173
|
|
|
174
174
|
// A daemon-scoped credential is the daemon's to store, and the daemon does
|
|
175
175
|
// the whole reference-and-value sequence atomically. This surface neither
|
|
176
|
-
// writes the config key nor the secret in that case
|
|
176
|
+
// writes the config key nor the secret in that case, it would be writing
|
|
177
177
|
// both into a tree the daemon never reads.
|
|
178
178
|
if (scope === 'daemon' && options.daemonWriter) {
|
|
179
179
|
const trimmed = rawValue.trim();
|
|
@@ -182,7 +182,7 @@ export async function persistSecretBackedConfigValue(
|
|
|
182
182
|
return '';
|
|
183
183
|
}
|
|
184
184
|
// Already a reference: the caller pasted one rather than a secret, so there
|
|
185
|
-
// is nothing to store
|
|
185
|
+
// is nothing to store, the config value is the whole write.
|
|
186
186
|
if (isSecretReferenceValue(trimmed)) return trimmed;
|
|
187
187
|
await options.daemonWriter.set(configKey, rawValue);
|
|
188
188
|
return update.configValue;
|
|
@@ -198,7 +198,7 @@ export async function persistSecretBackedConfigValue(
|
|
|
198
198
|
await secretsManager.set(update.secretKey, update.secretValue, { scope, medium });
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
// 3. Clear old secret
|
|
201
|
+
// 3. Clear old secret, pass the same medium so plaintext-medium secrets are found for deletion.
|
|
202
202
|
if (update.clearSecretKey && secretsManager?.delete) {
|
|
203
203
|
await secretsManager.delete(update.clearSecretKey, { scope, medium });
|
|
204
204
|
}
|
package/src/config/surface.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* surface.ts
|
|
2
|
+
* surface.ts, the TUI's single surface-root identifier.
|
|
3
3
|
*
|
|
4
4
|
* Every piece of the TUI's own on-disk state (sessions, the last-session
|
|
5
5
|
* pointer, recovery snapshots, checkpoints, the transcript journal, the
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TUI-extension settings
|
|
2
|
+
* TUI-extension settings, config namespaces the TUI reads that are NOT part
|
|
3
3
|
* of the SDK's ConfigManager schema.
|
|
4
4
|
*
|
|
5
5
|
* The SDK owns settings.json's typed schema (its `ConfigKey` union), but its
|
|
6
6
|
* loader deep-merges user JSON over the defaults and only strips unknown
|
|
7
|
-
* `permissions.tools` keys
|
|
7
|
+
* `permissions.tools` keys, every other unknown top-level key survives load
|
|
8
8
|
* and round-trips through `save()`. That lets the TUI keep its own namespaces
|
|
9
9
|
* (e.g. `checkpoints.*`) in the same settings.json file and read them back
|
|
10
10
|
* here via `getRaw()`.
|
|
@@ -45,7 +45,7 @@ function readNonEmptyString(src: RawRecord, key: string): string | undefined {
|
|
|
45
45
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
// ─── statusline
|
|
48
|
+
// ─── statusline.*, scriptable status line ───────────────────────────────────
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* User-settable scriptable status line. When `command` is present it is run as
|
|
@@ -63,7 +63,7 @@ export const STATUSLINE_DEFAULT_TIMEOUT_MS = 2000;
|
|
|
63
63
|
const STATUSLINE_MIN_TIMEOUT_MS = 100;
|
|
64
64
|
const STATUSLINE_MAX_TIMEOUT_MS = 15_000;
|
|
65
65
|
|
|
66
|
-
// ─── session
|
|
66
|
+
// ─── session.*, session behavior ────────────────────────────────────────────
|
|
67
67
|
|
|
68
68
|
/** User-settable session behavior. */
|
|
69
69
|
export interface SessionSettings {
|
|
@@ -99,7 +99,7 @@ export function readStatuslineSettings(configManager: Pick<ConfigManager, 'getRa
|
|
|
99
99
|
return out;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
// ─── update
|
|
102
|
+
// ─── update.*, launch-time self-update behavior ─────────────────────────────
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
105
|
* User-settable launch-time self-update behavior. The feature itself (check at
|
|
@@ -140,7 +140,7 @@ export function readUpdateSettings(configManager: Pick<ConfigManager, 'getRaw'>)
|
|
|
140
140
|
return out;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
// ─── checkpoints
|
|
143
|
+
// ─── checkpoints.*, workspace checkpoint root-guard options ─────────────────
|
|
144
144
|
|
|
145
145
|
/**
|
|
146
146
|
* User-settable root-guard options for the SDK's WorkspaceCheckpointManager.
|
|
@@ -165,12 +165,12 @@ export interface CheckpointGuardSettings {
|
|
|
165
165
|
* WorkspaceCheckpointManager options object.
|
|
166
166
|
*
|
|
167
167
|
* NOTE: the pinned platform SDK's WorkspaceCheckpointManager may predate these
|
|
168
|
-
* root-guard options
|
|
168
|
+
* root-guard options, an older constructor reads only
|
|
169
169
|
* workspaceRoot/checkpointDir/runtimeBus/retention/now and silently ignores the
|
|
170
170
|
* rest, making the guard keys INERT. They become effective the moment the SDK
|
|
171
171
|
* is upgraded to a build whose options type declares them (preferGitRoot,
|
|
172
172
|
* allowBroadRoot, allowLargeFirstSnapshot, maxFirstSnapshotFiles,
|
|
173
|
-
* autoRetention)
|
|
173
|
+
* autoRetention), no code change needed here. The return type intersects the
|
|
174
174
|
* base with CheckpointGuardSettings so the extra keys flow through structurally
|
|
175
175
|
* without an unsafe cast.
|
|
176
176
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* active-model-identity.ts
|
|
2
|
+
* active-model-identity.ts, the single answer to "which backend is serving
|
|
3
3
|
* this session right now, and is that what the user chose?"
|
|
4
4
|
*
|
|
5
5
|
* Two shell surfaces used to answer that question independently and could
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Both surfaces now resolve through resolveActiveModelDisplay() so they are
|
|
15
15
|
* computed from one comparison of serving-vs-configured. Divergence is
|
|
16
|
-
* detected structurally
|
|
17
|
-
* configured selection
|
|
16
|
+
* detected structurally, by comparing the live registry key against the
|
|
17
|
+
* configured selection, not by trusting a flag, so ANY path that moves the
|
|
18
18
|
* registry off the user's choice is surfaced, not just the failover path that
|
|
19
19
|
* sets the record below.
|
|
20
20
|
*
|
|
@@ -46,11 +46,11 @@ export interface FailoverTurnState {
|
|
|
46
46
|
current(): FailoverTurnRecord | null;
|
|
47
47
|
/**
|
|
48
48
|
* Record a failover switch. On a second switch within the same turn the
|
|
49
|
-
* originally-configured key is preserved
|
|
49
|
+
* originally-configured key is preserved, divergence is always reported
|
|
50
50
|
* against the user's own selection.
|
|
51
51
|
*/
|
|
52
52
|
begin(record: FailoverTurnRecord): void;
|
|
53
|
-
/** Drop the record
|
|
53
|
+
/** Drop the record, called only after serving is actually back on the configured selection. */
|
|
54
54
|
clear(): void;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -76,7 +76,7 @@ export interface ServingModelIdentity {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export interface ActiveModelInputs {
|
|
79
|
-
/** Live registry answer
|
|
79
|
+
/** Live registry answer, who is actually serving right now. */
|
|
80
80
|
readonly serving: ServingModelIdentity;
|
|
81
81
|
/** The user's configured selection as a registry key (config `provider.model`). */
|
|
82
82
|
readonly configuredRegistryKey: string | undefined;
|
|
@@ -100,7 +100,7 @@ export interface ActiveModelDisplay {
|
|
|
100
100
|
/**
|
|
101
101
|
* Divergence marker naming the configured selection, e.g.
|
|
102
102
|
* `failover from abacusai:route-llm`. Empty string when serving is the
|
|
103
|
-
* configured selection
|
|
103
|
+
* configured selection, in that case both surfaces render exactly as they
|
|
104
104
|
* did before this resolver existed.
|
|
105
105
|
*/
|
|
106
106
|
readonly divergenceNote: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* approval-alert
|
|
2
|
+
* approval-alert, fires an unfocused-user alert the moment a tool call
|
|
3
3
|
* becomes a real, user-blocking permission prompt.
|
|
4
4
|
*
|
|
5
5
|
* Anchor: `PERMISSION_REQUESTED` (SDK events/permissions.ts) is the wrong
|
|
6
|
-
* signal
|
|
6
|
+
* signal, it fires for every policy-evaluation step, including ones
|
|
7
7
|
* auto-resolved by allow-lists/yolo-mode in milliseconds. The only place a
|
|
8
8
|
* request becomes an actual user-facing prompt is where main.ts assigns
|
|
9
9
|
* `permissionPromptRef.requestPermission`. There is no `permissions` feed on
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* wrapped promise settles) so it reflects "a prompt just appeared", not
|
|
15
15
|
* "a prompt was just resolved".
|
|
16
16
|
*
|
|
17
|
-
* PRIVACY: message content is tool name + permission category only
|
|
17
|
+
* PRIVACY: message content is tool name + permission category only, no
|
|
18
18
|
* args, no file contents, no command strings (mirrors long-task-notifier's
|
|
19
19
|
* privacy guarantee).
|
|
20
20
|
*/
|
|
@@ -43,7 +43,7 @@ export interface ApprovalAlertDeps {
|
|
|
43
43
|
* Wrap a PermissionRequestHandler so every call also fires an unfocused-user
|
|
44
44
|
* alert (subject to the behavior.notifyOnApprovalPending / notifyOnlyWhenUnfocused
|
|
45
45
|
* gates). The wrapped handler's behavior (what it resolves to) is completely
|
|
46
|
-
* unchanged
|
|
46
|
+
* unchanged, this only adds a side effect at call time.
|
|
47
47
|
*/
|
|
48
48
|
export function wrapRequestPermissionWithAlert(
|
|
49
49
|
original: PermissionRequestHandler,
|
|
@@ -65,7 +65,7 @@ function fireApprovalAlert(request: PermissionPromptRequest, deps: ApprovalAlert
|
|
|
65
65
|
|
|
66
66
|
if (!shouldFireAlert(deps.focusTracker, deps.configGet, 'behavior.notifyOnApprovalPending')) return;
|
|
67
67
|
|
|
68
|
-
const title = 'GoodVibes
|
|
68
|
+
const title = 'GoodVibes: approval needed';
|
|
69
69
|
|
|
70
70
|
try {
|
|
71
71
|
notifyCompletion(title, message, FORCE_NOTIFY_DURATION_MS);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* bookmark-navigation.ts
|
|
2
|
+
* bookmark-navigation.ts, fallback resolution for a bookmark whose direct
|
|
3
3
|
* BlockMeta lookup misses.
|
|
4
4
|
*
|
|
5
5
|
* A bookmark stores a block's collapseKey at the time it was set (see
|
|
6
6
|
* handler-content-actions.ts's handleBookmark). A tool-result message that is
|
|
7
7
|
* a non-owning member of a folded tool-result group (see
|
|
8
8
|
* conversation-tool-groups.ts) pushes no BlockMeta of its own while the group
|
|
9
|
-
* stays collapsed
|
|
9
|
+
* stays collapsed, its own collapseKey (`msg_<absoluteIdx>`) never appears
|
|
10
10
|
* in getBlockRegistry() until the group is expanded. A direct
|
|
11
11
|
* find(entry => entry.collapseKey === key) then reports "not found", even
|
|
12
12
|
* though the message is still present in the transcript, just folded under
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* for a folded group member, already resolves to the group's own header line
|
|
19
19
|
* rather than the position of whatever renders next (see getMessageLine's
|
|
20
20
|
* doc and conversation-rendering.ts / conversation-line-cache.ts, which
|
|
21
|
-
* anchor a folded member's registered line at its group's header)
|
|
21
|
+
* anchor a folded member's registered line at its group's header), landing
|
|
22
22
|
* on the header is an honest, reachable result rather than a false
|
|
23
23
|
* "not found".
|
|
24
24
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* budget-breach-notifier
|
|
2
|
+
* budget-breach-notifier, fires an unfocused-user alert the moment session
|
|
3
3
|
* cost crosses the configured budget threshold (behavior.budgetAlertUsd).
|
|
4
4
|
*
|
|
5
5
|
* One-shot semantics: fires exactly once on the false→true edge (crossing
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
* Delivery mirrors long-task-notifier.ts: desktop notification
|
|
13
13
|
* (notifyCompletion) + outbound webhook (WebhookNotifier), both gated by
|
|
14
14
|
* the shared focus/config gating in alert-gating.ts. Skips evaluation
|
|
15
|
-
* entirely when the session model is unpriced
|
|
15
|
+
* entirely when the session model is unpriced, a $0 placeholder cost must
|
|
16
16
|
* never be reported as a real breach (mirrors CostTrackerPanel's "unpriced"
|
|
17
17
|
* display convention).
|
|
18
18
|
*
|
|
19
19
|
* PRIVACY: message text is built from cost/threshold numbers and the
|
|
20
|
-
* session id prefix only
|
|
20
|
+
* session id prefix only, no conversation content.
|
|
21
21
|
*/
|
|
22
22
|
import { notifyCompletion } from '@pellux/goodvibes-sdk/platform/utils';
|
|
23
23
|
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
@@ -40,7 +40,7 @@ export interface BudgetBreachNotifierDeps {
|
|
|
40
40
|
readonly sessionId: string;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
/** Stateful edge-trigger checker
|
|
43
|
+
/** Stateful edge-trigger checker, construct once per session, call on every TURN_COMPLETED. */
|
|
44
44
|
export interface BudgetBreachNotifier {
|
|
45
45
|
/**
|
|
46
46
|
* Evaluate current usage against the configured threshold and fire an
|
|
@@ -57,7 +57,7 @@ export function createBudgetBreachNotifier(deps: BudgetBreachNotifierDeps): Budg
|
|
|
57
57
|
return {
|
|
58
58
|
check(usage, sessionModel, budgetThresholdUsd) {
|
|
59
59
|
if (budgetThresholdUsd !== lastThreshold) {
|
|
60
|
-
// Threshold raised, lowered, or cleared since the last check
|
|
60
|
+
// Threshold raised, lowered, or cleared since the last check, re-arm
|
|
61
61
|
// the latch so a breach against the new threshold can fire again.
|
|
62
62
|
lastThreshold = budgetThresholdUsd;
|
|
63
63
|
notified = false;
|
|
@@ -85,7 +85,7 @@ export function createBudgetBreachNotifier(deps: BudgetBreachNotifierDeps): Budg
|
|
|
85
85
|
function fireBudgetBreachAlert(deps: BudgetBreachNotifierDeps, sessionCost: number, budgetThresholdUsd: number): void {
|
|
86
86
|
if (!shouldFireAlert(deps.focusTracker, deps.configGet, 'behavior.notifyOnBudgetBreach')) return;
|
|
87
87
|
|
|
88
|
-
const title = 'GoodVibes
|
|
88
|
+
const title = 'GoodVibes: budget breach';
|
|
89
89
|
const message = `session cost $${sessionCost.toFixed(2)} exceeded budget $${budgetThresholdUsd.toFixed(2)} · session ${deps.sessionId.slice(0, 8)}`;
|
|
90
90
|
|
|
91
91
|
try {
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* The SDK emits a mandatory COMPACTION_RECEIPT event after every automatic (and
|
|
5
5
|
* the manual) compaction path, so a compaction is never silent. This module
|
|
6
6
|
* turns that receipt into a distinct, multi-line `[Compaction]` block for the
|
|
7
|
-
* transcript. It is a pure formatter
|
|
7
|
+
* transcript. It is a pure formatter, no state, no I/O, so it is unit-testable
|
|
8
8
|
* and the wiring layer only has to route the returned string.
|
|
9
9
|
*
|
|
10
10
|
* Why a visible receipt: automatic behavior (the orchestrator's post-turn
|
|
11
11
|
* auto-compaction) previously ran without any transcript trace. The receipt
|
|
12
12
|
* makes the audit trail visible: what was compacted, the quality the guard
|
|
13
13
|
* computed, whether the standing-instruction chain was re-injected, and the
|
|
14
|
-
* outcome
|
|
14
|
+
* outcome, applied, kept-original (quality guard rejected it), or failed.
|
|
15
15
|
*
|
|
16
16
|
* The `[Compaction]` prefix is one of the FORCE_CONVERSATION_PREFIXES the
|
|
17
17
|
* system-message router always surfaces inline (see system-message-router.ts),
|
|
@@ -41,7 +41,7 @@ export interface CompactionReceiptInput {
|
|
|
41
41
|
readonly detail?: string | undefined;
|
|
42
42
|
/**
|
|
43
43
|
* The strategy the caller REQUESTED (from `behavior.compactionStrategy`),
|
|
44
|
-
* present only when it differs from `strategy
|
|
44
|
+
* present only when it differs from `strategy`, i.e. a distiller→structured
|
|
45
45
|
* fallback happened. `strategy` always names what actually ran.
|
|
46
46
|
*/
|
|
47
47
|
readonly requestedStrategy?: string | undefined;
|
|
@@ -57,11 +57,11 @@ function fmtN(n: number): string {
|
|
|
57
57
|
function describeOutcome(outcome: CompactionReceiptInput['outcome']): string {
|
|
58
58
|
switch (outcome) {
|
|
59
59
|
case 'applied':
|
|
60
|
-
return 'applied
|
|
60
|
+
return 'applied: compacted context committed';
|
|
61
61
|
case 'kept-original':
|
|
62
|
-
return 'kept original
|
|
62
|
+
return 'kept original: quality guard rejected the summary, conversation retained';
|
|
63
63
|
case 'failed':
|
|
64
|
-
return 'failed
|
|
64
|
+
return 'failed: compaction did not produce a usable result';
|
|
65
65
|
default:
|
|
66
66
|
return outcome;
|
|
67
67
|
}
|
|
@@ -80,7 +80,7 @@ export function buildCompactionReceiptBlock(receipt: CompactionReceiptInput): st
|
|
|
80
80
|
: 0;
|
|
81
81
|
|
|
82
82
|
const lines: string[] = [];
|
|
83
|
-
lines.push(`[Compaction] Receipt
|
|
83
|
+
lines.push(`[Compaction] Receipt: ${triggerWord.toLowerCase()} compaction, outcome: ${describeOutcome(receipt.outcome)}`);
|
|
84
84
|
|
|
85
85
|
// Only report the size delta when the summary was actually applied; on
|
|
86
86
|
// kept-original / failed the "after" counts describe the retained original,
|
|
@@ -99,7 +99,7 @@ export function buildCompactionReceiptBlock(receipt: CompactionReceiptInput): st
|
|
|
99
99
|
const qualitySuffix = receipt.lowQuality ? ' (below the quality bar)' : '';
|
|
100
100
|
lines.push(` Quality: ${gradeStr}${Math.round(receipt.qualityScore)}/100${qualitySuffix} · strategy: ${receipt.strategy || 'unknown'}.`);
|
|
101
101
|
|
|
102
|
-
// Only present on a distiller→structured fallback
|
|
102
|
+
// Only present on a distiller→structured fallback, say plainly what was
|
|
103
103
|
// requested, what actually ran, and why, so the fallback is never silent.
|
|
104
104
|
if (receipt.requestedStrategy && receipt.requestedStrategy !== receipt.strategy) {
|
|
105
105
|
const reasonSuffix = receipt.strategyFallbackReason ? `: ${receipt.strategyFallbackReason}` : '';
|
|
@@ -22,7 +22,7 @@ export function deriveComposerState(input: ComposerStateInput): ComposerState {
|
|
|
22
22
|
|
|
23
23
|
// An approval wait is the dominant composer state and owns the single honest
|
|
24
24
|
// status tag: `risk:approval-wait`. It is therefore NOT also duplicated as a
|
|
25
|
-
// `approval` flag, and (below) it suppresses the competing `state:` turn tag
|
|
25
|
+
// `approval` flag, and (below) it suppresses the competing `state:` turn tag,
|
|
26
26
|
// the turn is blocked on the user, not really streaming. Precedence:
|
|
27
27
|
// approval-wait > live turn state. (item 4.)
|
|
28
28
|
const approvalWait = input.pendingApproval === true;
|
|
@@ -53,7 +53,7 @@ export function deriveComposerState(input: ComposerStateInput): ComposerState {
|
|
|
53
53
|
}
|
|
54
54
|
})();
|
|
55
55
|
// 'idle' is suppressed by the footer renderer, so an approval wait shows only
|
|
56
|
-
// `risk:approval-wait
|
|
56
|
+
// `risk:approval-wait`, one honest tag, not three spellings of the wait.
|
|
57
57
|
const statusLabel = approvalWait ? 'idle' : turnStatus;
|
|
58
58
|
|
|
59
59
|
return {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* hand-rolled copies.
|
|
7
7
|
*
|
|
8
8
|
* IMPORTANT: compaction-preview.ts intentionally displays usage > 100%
|
|
9
|
-
* ("exceeds window")
|
|
9
|
+
* ("exceeds window"), callers that need the unclamped value must use
|
|
10
10
|
* rawRatio, not clampedRatio / pct.
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-compaction-render.ts
|
|
2
|
+
* conversation-compaction-render.ts, folds a compaction-continuation user
|
|
3
3
|
* message (the instruction block the compactor re-injects after an automatic
|
|
4
4
|
* compaction) to one header + preview line.
|
|
5
5
|
*
|
|
@@ -16,7 +16,7 @@ import type { BlockMeta } from './conversation-types.ts';
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* The slice of the render context this module needs, declared structurally
|
|
19
|
-
* rather than imported from conversation-rendering.ts
|
|
19
|
+
* rather than imported from conversation-rendering.ts, that import would form
|
|
20
20
|
* a 2-file cycle the architecture check rejects, and this module only ever
|
|
21
21
|
* touches these three fields.
|
|
22
22
|
*/
|
|
@@ -62,7 +62,7 @@ export function renderCompactionContinuationMessage(
|
|
|
62
62
|
|
|
63
63
|
if (isCollapsed) {
|
|
64
64
|
// One row. This used to be the header PLUS a framed fragment holding a
|
|
65
|
-
// single static sentence
|
|
65
|
+
// single static sentence, three rows of chrome to say what the label and
|
|
66
66
|
// the badge already said. The distinguishing half of that sentence folds
|
|
67
67
|
// onto the header instead.
|
|
68
68
|
context.history.addLine(renderConversationFoldedRow(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* conversation-event-navigation.ts
|
|
2
|
+
* conversation-event-navigation.ts, resolving "jump to the next/previous
|
|
3
3
|
* transcript event" into a history-buffer line number.
|
|
4
4
|
*
|
|
5
5
|
* Extracted from ConversationManager (core/conversation.ts), which is at its
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* The rule both directions share: take the events of the requested kind, map
|
|
10
10
|
* each to the line its message was rendered at, drop the ones that were never
|
|
11
|
-
* rendered (a message with no registry entry), sort ascending, then wrap
|
|
11
|
+
* rendered (a message with no registry entry), sort ascending, then wrap,
|
|
12
12
|
* searching forward past `currentLine` falls back to the first line, searching
|
|
13
13
|
* backward falls back to the last. -1 means there is nowhere to go.
|
|
14
14
|
*/
|