@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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-tui",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Terminal-native GoodVibes client for coding, operations, knowledge and channel workflows
|
|
3
|
+
"version": "2.0.15",
|
|
4
|
+
"description": "Terminal-native GoodVibes client for coding, operations, knowledge and channel workflows; a pure client of the GoodVibes daemon.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/main.ts",
|
|
7
7
|
"bin": {
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"dev:watch": "bun --watch src/main.ts",
|
|
28
28
|
"prebuild": "bun run scripts/prebuild.ts",
|
|
29
29
|
"build": "bun build src/main.ts --compile --outfile dist/goodvibes",
|
|
30
|
-
"build:linux-x64": "
|
|
31
|
-
"build:linux-arm64": "
|
|
32
|
-
"build:macos-x64": "
|
|
33
|
-
"build:macos-arm64": "
|
|
30
|
+
"build:linux-x64": "goodvibes-build-binaries --target linux-x64",
|
|
31
|
+
"build:linux-arm64": "goodvibes-build-binaries --target linux-arm64",
|
|
32
|
+
"build:macos-x64": "goodvibes-build-binaries --target darwin-x64",
|
|
33
|
+
"build:macos-arm64": "goodvibes-build-binaries --target darwin-arm64",
|
|
34
34
|
"smoke:tui": "goodvibes-post-build-smoke",
|
|
35
|
-
"build:windows": "
|
|
35
|
+
"build:windows": "goodvibes-build-binaries --target windows-x64",
|
|
36
36
|
"build:all-shell": "bun run build:linux-x64 && bun run build:linux-arm64 && bun run build:macos-x64 && bun run build:macos-arm64 && bun run build:windows",
|
|
37
37
|
"typecheck": "bunx tsc --noEmit",
|
|
38
38
|
"typecheck:test": "bunx tsc --noEmit -p tsconfig.test.json",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"platform:publish:dry-run": "bun run scripts/publish-platform-packages.ts --dry-run",
|
|
53
53
|
"publish:dry-run:github": "GOODVIBES_PUBLIC_PACKAGE_NAME=@mgd34msu/goodvibes-tui GOODVIBES_PUBLISH_REGISTRY=https://npm.pkg.github.com bun run scripts/publish-package.ts --dry-run",
|
|
54
54
|
"publish:check": "bun run scripts/publish-check.ts",
|
|
55
|
+
"verify:tag-version": "bun run scripts/verify-release-tag-version.ts",
|
|
55
56
|
"package:install-check": "bun run scripts/package-install-check.ts",
|
|
56
57
|
"build:prod": "goodvibes-build-binaries",
|
|
57
58
|
"build:all": "goodvibes-build-binaries --all",
|
|
@@ -95,11 +96,11 @@
|
|
|
95
96
|
"@anthropic-ai/bedrock-sdk": "^0.29.1",
|
|
96
97
|
"@anthropic-ai/sdk": "^0.92.0",
|
|
97
98
|
"@ast-grep/napi": "^0.42.0",
|
|
98
|
-
"@pellux/goodvibes-sdk": "2.0.
|
|
99
|
-
"@pellux/goodvibes-terminal-shell": "2.0.
|
|
99
|
+
"@pellux/goodvibes-sdk": "2.0.19",
|
|
100
|
+
"@pellux/goodvibes-terminal-shell": "2.0.19",
|
|
100
101
|
"bash-language-server": "^5.6.0",
|
|
101
102
|
"fuse.js": "^7.1.0",
|
|
102
|
-
"@pellux/goodvibes-daemon": "1.28.
|
|
103
|
+
"@pellux/goodvibes-daemon": "1.28.21",
|
|
103
104
|
"graphql": "^16.13.2",
|
|
104
105
|
"jszip": "^3.10.1",
|
|
105
106
|
"node-edge-tts": "^1.2.10",
|
|
@@ -120,6 +121,7 @@
|
|
|
120
121
|
"zustand": "^5.0.12"
|
|
121
122
|
},
|
|
122
123
|
"devDependencies": {
|
|
124
|
+
"@pellux/goodvibes-toolchain": "2.0.19",
|
|
123
125
|
"@types/bun": "^1.3.10",
|
|
124
126
|
"typescript": "^5.9.3"
|
|
125
127
|
},
|
package/scripts/postinstall.js
CHANGED
|
@@ -66,7 +66,7 @@ async function downloadText(url) {
|
|
|
66
66
|
*
|
|
67
67
|
* The daemon binary is NOT here any more. The daemon is its own product with
|
|
68
68
|
* its own npm package (`goodvibes-daemon`), which this package declares as a
|
|
69
|
-
* dependency
|
|
69
|
+
* dependency, so an npm install still brings the whole suite, and the daemon's
|
|
70
70
|
* own postinstall places the daemon's own binary. Two packages each placing
|
|
71
71
|
* a copy of `goodvibes-daemon` is exactly how a machine ends up with two.
|
|
72
72
|
*/
|
|
@@ -234,7 +234,7 @@ function deployBundledFiles() {
|
|
|
234
234
|
* Put the wake-word model on the machine as part of installing.
|
|
235
235
|
*
|
|
236
236
|
* Everything needed to detect "hey goodvibes" already shipped, and provisioning
|
|
237
|
-
* was reachable only by typing `/voice wake setup
|
|
237
|
+
* was reachable only by typing `/voice wake setup`, so the ordinary outcome of
|
|
238
238
|
* installing was a wake word that could not start. The pins (URLs, byte counts,
|
|
239
239
|
* checksums) live in the SDK's wake-word manifest and stay there; this calls the
|
|
240
240
|
* SDK's install policy, which:
|
|
@@ -252,7 +252,7 @@ function deployBundledFiles() {
|
|
|
252
252
|
* It honours the same skip switches as the binary install (`--no-download`,
|
|
253
253
|
* GOODVIBES_SKIP_BINARY_DOWNLOAD) plus its own
|
|
254
254
|
* GOODVIBES_SKIP_WAKE_MODEL_DOWNLOAD, and it stays out of a source checkout for
|
|
255
|
-
* the same reason the binary install does
|
|
255
|
+
* the same reason the binary install does, a repo clone is a development tree,
|
|
256
256
|
* not an installation.
|
|
257
257
|
*/
|
|
258
258
|
async function installWakeWordModel() {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* activation-sound.ts
|
|
2
|
+
* activation-sound.ts, the sound a confirmed wake makes.
|
|
3
3
|
*
|
|
4
4
|
* A wake takes the microphone from "scoring frames nobody hears" to "recording
|
|
5
|
-
* what you say next", and the user needs to know the moment that happened
|
|
5
|
+
* what you say next", and the user needs to know the moment that happened,
|
|
6
6
|
* otherwise the only feedback is a transcript arriving seconds later, and a
|
|
7
7
|
* false accept is indistinguishable from nothing having happened at all. So the
|
|
8
8
|
* sound is played AT the wake, before transcription, per
|
|
9
9
|
* `voice.wake.activationSound`:
|
|
10
10
|
*
|
|
11
|
-
* - `chime`
|
|
11
|
+
* - `chime` , a short two-tone WAV synthesised here. No asset file to ship,
|
|
12
12
|
* install, provision or lose, and nothing to fetch at runtime.
|
|
13
|
-
* - `custom
|
|
14
|
-
* - `none`
|
|
13
|
+
* - `custom`, the file named by `voice.wake.activationSoundPath`.
|
|
14
|
+
* - `none` , silent.
|
|
15
15
|
*
|
|
16
16
|
* Playback reuses the streaming player the spoken-turn path already owns
|
|
17
17
|
* (player.ts), so a host with mpv or ffplay needs nothing extra and a host with
|
|
@@ -32,7 +32,7 @@ const CHIME_SAMPLE_RATE = 16000;
|
|
|
32
32
|
const CHIME_TONES_HZ = [880, 1320] as const;
|
|
33
33
|
/** Milliseconds per tone. Short enough not to overlap the start of an utterance. */
|
|
34
34
|
const CHIME_TONE_MS = 70;
|
|
35
|
-
/** Peak amplitude on the int16 magnitude scale
|
|
35
|
+
/** Peak amplitude on the int16 magnitude scale, audible without being startling. */
|
|
36
36
|
const CHIME_PEAK = 6000;
|
|
37
37
|
/**
|
|
38
38
|
* Fade applied to each end of each tone, in samples. Without it the abrupt start
|
|
@@ -83,7 +83,7 @@ export interface ActivationSoundPlayerDeps {
|
|
|
83
83
|
* sound that fails to play must not delay or cancel that.
|
|
84
84
|
*
|
|
85
85
|
* `settings.activationSound` arrives already resolved against surface capability
|
|
86
|
-
|
|
86
|
+
*, the SDK downgrades `custom` to `chime` on a surface that cannot read a local
|
|
87
87
|
* file, and this surface can, so `custom` here means a real path.
|
|
88
88
|
*/
|
|
89
89
|
export function playActivationSound(sound: WakeActivationSound, deps: ActivationSoundPlayerDeps): void {
|
package/src/audio/capture.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* capture.ts
|
|
2
|
+
* capture.ts, the ONE place this terminal opens a microphone.
|
|
3
3
|
*
|
|
4
4
|
* Two consumers sit on it and they share this single device path: push-to-talk
|
|
5
5
|
* voice input (src/audio/voice-input-session.ts) and wake-word detection
|
|
6
6
|
* (src/audio/wake-runtime.ts). A wake does not END a capture session, it starts
|
|
7
|
-
* one
|
|
8
|
-
* the utterance that follows
|
|
7
|
+
* one, the SDK listener keeps the same stream open and switches it to recording
|
|
8
|
+
* the utterance that follows, so a second opener would drop the beginning of a
|
|
9
9
|
* sentence and race the operating system for a device that is already held.
|
|
10
10
|
*
|
|
11
11
|
* The framing arithmetic, the recorder argv and the utterance policy all live in
|
|
12
12
|
* the SDK (`@pellux/goodvibes-sdk/platform/voice/capture`), because getting any
|
|
13
13
|
* of them subtly wrong is SILENT: a container header out of byte alignment, or a
|
|
14
14
|
* short frame, still "works" and simply never detects. What is local is the one
|
|
15
|
-
* thing that cannot be shared
|
|
15
|
+
* thing that cannot be shared, actually starting a process. That mirrors
|
|
16
16
|
* playback exactly (see player.ts): resolve a command off PATH, spawn it, and
|
|
17
17
|
* treat "no tool installed" as a reported state rather than an exception.
|
|
18
18
|
*/
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
/**
|
|
32
32
|
* Whether a command is runnable from PATH. Same scan `player.ts` uses for
|
|
33
33
|
* mpv/ffplay (`resolveStreamingAudioPlayerCommand` -> `findExecutable`): every
|
|
34
|
-
* PATH entry, X_OK access, Windows extensions included
|
|
34
|
+
* PATH entry, X_OK access, Windows extensions included, kept identical so a
|
|
35
35
|
* host where playback finds its tool and capture does not is a real difference
|
|
36
36
|
* in what is installed, never a difference in how the two looked.
|
|
37
37
|
*/
|
|
@@ -70,7 +70,7 @@ export const spawnRecorderProcess: CaptureSpawn = (command, args): CaptureChildP
|
|
|
70
70
|
// Adapted rather than returned directly: the SDK's port declares the signal as
|
|
71
71
|
// a plain `string` (it is shared with a browser bundle that has no
|
|
72
72
|
// NodeJS.Signals) and node's narrower union is not assignable to it. The two
|
|
73
|
-
// event listeners are branched explicitly for the same reason
|
|
73
|
+
// event listeners are branched explicitly for the same reason, node's `on` is
|
|
74
74
|
// overloaded per event name and takes no union.
|
|
75
75
|
return {
|
|
76
76
|
stdout: child.stdout,
|
|
@@ -103,7 +103,7 @@ export function createTuiCaptureOpener(options: TuiCaptureOpenerOptions = {}): A
|
|
|
103
103
|
platform: options.platform ?? process.platform,
|
|
104
104
|
// FALSE here, and correct: a recorder subprocess captures raw PCM and filters
|
|
105
105
|
// nothing. The suppression stage is applied by the SDK's own wrapper inside
|
|
106
|
-
// WakeListener and PushToTalkSession, which ask this opener for raw frames
|
|
106
|
+
// WakeListener and PushToTalkSession, which ask this opener for raw frames,
|
|
107
107
|
// so `speex` arriving at the RECORDER directly, unwrapped by either, is still
|
|
108
108
|
// refused rather than passed through unfiltered.
|
|
109
109
|
speexAvailable: false,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The two onnxruntime-web assets the wake engine needs on disk.
|
|
3
3
|
*
|
|
4
4
|
* Both are imported with `with { type: 'file' }`, which resolves to a PATH
|
|
5
|
-
* string rather than module contents
|
|
5
|
+
* string rather than module contents, a real filesystem path when the shell
|
|
6
6
|
* runs from source, and a `/$bunfs/root/...` path inside a compiled binary,
|
|
7
7
|
* where the bytes are embedded. Declared here because these are asset
|
|
8
8
|
* specifiers, not typed modules: onnxruntime-web publishes them for exactly
|
package/src/audio/player.ts
CHANGED
|
@@ -43,7 +43,7 @@ export interface LocalStreamingAudioPlayerOptions {
|
|
|
43
43
|
readonly env?: NodeJS.ProcessEnv;
|
|
44
44
|
readonly spawnProcess?: SpawnProcessFactory;
|
|
45
45
|
/**
|
|
46
|
-
* Injected player command
|
|
46
|
+
* Injected player command, the test seam companion to `spawnProcess`.
|
|
47
47
|
* When set, the constructor uses it verbatim instead of scanning PATH, so
|
|
48
48
|
* deterministic fake-sink tests never depend on mpv/ffplay being installed
|
|
49
49
|
* on the machine running them. Pass null to model "no player found".
|
|
@@ -101,7 +101,7 @@ export class LocalStreamingAudioPlayer implements StreamingAudioPlayer {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
// An intentional interrupt (turn cancel / quit chord / /tts stop) has
|
|
104
|
-
// already torn the process down via `abort` and must cut immediately
|
|
104
|
+
// already torn the process down via `abort` and must cut immediately,
|
|
105
105
|
// do not wait on a graceful drain. A natural end-of-speech, by contrast,
|
|
106
106
|
// closes stdin and waits for the sink to play out every buffered sample
|
|
107
107
|
// so the tail of the response is never truncated.
|
|
@@ -163,7 +163,7 @@ export function resolveStreamingAudioPlayerCommand(env: NodeJS.ProcessEnv = proc
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
// ffplay -autoexit quits as soon as its input ends, before the audio output
|
|
166
|
-
// buffer has drained
|
|
166
|
+
// buffer has drained, that clips the tail of the response. `apad` appends a
|
|
167
167
|
// short run of silence so the real audio is fully played out and only the
|
|
168
168
|
// trailing silence gets trimmed.
|
|
169
169
|
const FFPLAY_APAD = ['-af', 'apad=pad_dur=0.3'] as const;
|
|
@@ -177,7 +177,7 @@ function buildPlayerArgs(command: StreamingAudioPlayerCommand, format?: string):
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
/**
|
|
180
|
-
* awaitReady
|
|
180
|
+
* awaitReady, resolves once the spawned player has actually started (its
|
|
181
181
|
* 'spawn' event), rejects if it fails to start ('error'), and resolves early
|
|
182
182
|
* if the caller aborts during startup so an intentional interrupt is never
|
|
183
183
|
* blocked. This is the readiness gate that keeps the first audio byte from
|
|
@@ -20,18 +20,18 @@ export interface WireSpokenTurnRuntimeOptions {
|
|
|
20
20
|
readonly events: UiRuntimeEvents;
|
|
21
21
|
readonly notify: (message: string) => void;
|
|
22
22
|
/**
|
|
23
|
-
* Optional player factory
|
|
23
|
+
* Optional player factory, injected in tests to avoid spawning real
|
|
24
24
|
* subprocesses. Defaults to LocalStreamingAudioPlayer.
|
|
25
25
|
*/
|
|
26
26
|
readonly playerFactory?: () => StreamingAudioPlayer;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* wireSpokenTurnRuntime
|
|
30
|
+
* wireSpokenTurnRuntime, wires the spoken-turn pipeline against the runtime
|
|
31
31
|
* event bus.
|
|
32
32
|
*
|
|
33
33
|
* Always-speak mode: when `ui.voiceEnabled` is true in config, every
|
|
34
|
-
* TURN_SUBMITTED event arms the turn for spoken output automatically
|
|
34
|
+
* TURN_SUBMITTED event arms the turn for spoken output automatically, the
|
|
35
35
|
* user does not need to prefix the prompt with /tts. The availability check
|
|
36
36
|
* inside SpokenTurnController still gates gracefully when no player is found.
|
|
37
37
|
*/
|
|
@@ -39,7 +39,7 @@ export function wireSpokenTurnRuntime(options: WireSpokenTurnRuntimeOptions): Sp
|
|
|
39
39
|
const player = options.playerFactory ? options.playerFactory() : new LocalStreamingAudioPlayer();
|
|
40
40
|
// The TUI's subprocess-based player already satisfies the SDK's AudioSink
|
|
41
41
|
// interface unchanged (see docs/decisions/2026-07-06-spoken-turn-tts-policy-sdk-hoist.md
|
|
42
|
-
// in the SDK repo)
|
|
42
|
+
// in the SDK repo), only the option name (`sink` not `player`) and the
|
|
43
43
|
// attribution `source` are new.
|
|
44
44
|
const controller = new SpokenTurnController({
|
|
45
45
|
voiceService: options.voiceService,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* voice-capture-wiring.ts
|
|
2
|
+
* voice-capture-wiring.ts, composes the terminal's two voice consumers over ONE
|
|
3
3
|
* capture path.
|
|
4
4
|
*
|
|
5
5
|
* Push-to-talk and wake detection are not two audio stacks. They share the
|
|
6
6
|
* opener built here (capture.ts), the transcription gateway (core/voice-stt-gateway.ts)
|
|
7
|
-
* and the same `voice.wake.*` capture rows
|
|
8
|
-
* suppression, ceiling
|
|
7
|
+
* and the same `voice.wake.*` capture rows, device, recorder, noise
|
|
8
|
+
* suppression, ceiling, so a device that works for one works for the other and
|
|
9
9
|
* a change in /settings applies to both.
|
|
10
10
|
*
|
|
11
11
|
* This is the composition root the shell calls once. It owns nothing the shell
|
|
@@ -30,7 +30,7 @@ import { wakeProvisionStatus } from '@pellux/goodvibes-sdk/platform/voice';
|
|
|
30
30
|
|
|
31
31
|
export interface VoiceCaptureWiringDeps {
|
|
32
32
|
readonly configManager: ConfigManager;
|
|
33
|
-
/** `<root>/voice
|
|
33
|
+
/** `<root>/voice`, the managed root the wake tree hangs off (same root /voice setup uses). */
|
|
34
34
|
readonly managedVoiceRoot: string;
|
|
35
35
|
/** A directory this surface owns for the extracted onnxruntime assets. */
|
|
36
36
|
readonly assetDirectory: string;
|
|
@@ -56,7 +56,7 @@ export interface VoiceCaptureWiring {
|
|
|
56
56
|
* standing condition they already know about.
|
|
57
57
|
*/
|
|
58
58
|
readonly status: () => VoiceCaptureIndicatorState | null;
|
|
59
|
-
/** Teardown, for the shell's `unsubs` registry
|
|
59
|
+
/** Teardown, for the shell's `unsubs` registry, releases any open device. */
|
|
60
60
|
readonly unsubs: readonly (() => void)[];
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* voice-input-session.ts
|
|
2
|
+
* voice-input-session.ts, push-to-talk voice input for the terminal.
|
|
3
3
|
*
|
|
4
|
-
* PRESS TO START, PRESS AGAIN TO STOP
|
|
4
|
+
* PRESS TO START, PRESS AGAIN TO STOP, not press-and-hold. A terminal receives
|
|
5
5
|
* discrete key EVENTS, not held-key state: there is no key-release event to
|
|
6
6
|
* observe, so a genuine hold would have to be faked with a timer that guesses
|
|
7
7
|
* when the user let go. The binding's description says "press to start, press
|
|
@@ -63,7 +63,7 @@ const PHASE_INDICATOR: Partial<Record<PushToTalkPhase, VoiceCaptureIndicatorStat
|
|
|
63
63
|
/**
|
|
64
64
|
* Wire push-to-talk. One session object is reused across presses (the SDK session
|
|
65
65
|
* is restartable after both a stop and a failure), so a device is opened per
|
|
66
|
-
* press and released on every path out of it
|
|
66
|
+
* press and released on every path out of it, including the failing ones.
|
|
67
67
|
*/
|
|
68
68
|
export function wireVoiceInputRuntime(deps: VoiceInputRuntimeDeps): VoiceInputRuntime {
|
|
69
69
|
let session: PushToTalkSession | null = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* wake-inference.ts
|
|
2
|
+
* wake-inference.ts, the terminal's inference runtime for the wake engine.
|
|
3
3
|
*
|
|
4
4
|
* The SDK engine never imports an inference runtime; it declares the shape of a
|
|
5
5
|
* session ({@link WakeInferenceSession}) and takes one from the host. This is
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* `/$bunfs/root/ort-wasm-simd-threaded.mjs`, which is not something bun embeds
|
|
14
14
|
* for a dynamic path import, and session creation fails at runtime with
|
|
15
15
|
* "Cannot find module". So both assets are imported with `with { type: 'file' }`
|
|
16
|
-
|
|
16
|
+
*, embedded in the binary, handed to us as a path, written into a directory
|
|
17
17
|
* this surface owns, and `ort.env.wasm.wasmPaths` is pointed at that directory.
|
|
18
18
|
* The same code path runs from source, where the imports resolve to the real
|
|
19
19
|
* files in node_modules and the copy is a no-op after the first launch.
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* rather than trusting a stale extraction from a previous version.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import { mkdirSync, readFileSync
|
|
27
|
+
import { mkdirSync, readFileSync } from 'node:fs';
|
|
28
28
|
import { join } from 'node:path';
|
|
29
29
|
import * as ort from 'onnxruntime-web/wasm';
|
|
30
30
|
import glueAssetPath from 'onnxruntime-web/ort-wasm-simd-threaded.mjs' with { type: 'file' };
|
|
@@ -36,10 +36,11 @@ import type {
|
|
|
36
36
|
WakeTensor,
|
|
37
37
|
} from '@pellux/goodvibes-sdk/platform/voice';
|
|
38
38
|
import { WakeWordEngine } from '@pellux/goodvibes-sdk/platform/voice';
|
|
39
|
+
import { atomicWriteFileSync } from '@pellux/goodvibes-sdk/platform/config';
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* The runtime asks for its glue and its wasm by these exact names, relative to
|
|
42
|
-
* `ort.env.wasm.wasmPaths
|
|
43
|
+
* `ort.env.wasm.wasmPaths`, so the extracted copies must keep them.
|
|
43
44
|
*/
|
|
44
45
|
const ORT_ASSETS = [
|
|
45
46
|
{ source: glueAssetPath, name: 'ort-wasm-simd-threaded.mjs' },
|
|
@@ -51,7 +52,7 @@ let configuredAssetDirectory: string | null = null;
|
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
54
|
* Copy the onnxruntime-web assets into `directory` and return the value
|
|
54
|
-
* `ort.env.wasm.wasmPaths` wants
|
|
55
|
+
* `ort.env.wasm.wasmPaths` wants, a directory prefix WITH its trailing slash,
|
|
55
56
|
* which the runtime concatenates a file name onto. Without the slash it looks
|
|
56
57
|
* for a sibling of the directory and reports a missing module.
|
|
57
58
|
*/
|
|
@@ -67,7 +68,11 @@ export function extractOnnxRuntimeAssets(directory: string): string {
|
|
|
67
68
|
// Absent, or unreadable: either way it gets written below.
|
|
68
69
|
}
|
|
69
70
|
if (existing !== null && existing.equals(bytes)) continue;
|
|
70
|
-
|
|
71
|
+
// The directory is shared by every TUI process for this user; a plain
|
|
72
|
+
// write can leave a torn file for a concurrent process's WASM loader.
|
|
73
|
+
// The SDK's atomicWriteFileSync now accepts raw bytes directly (sdk
|
|
74
|
+
// 2.0.18), so it does the temp-then-rename instead of this file inlining it.
|
|
75
|
+
atomicWriteFileSync(target, bytes, { mkdirp: true });
|
|
71
76
|
}
|
|
72
77
|
return `${directory}/`;
|
|
73
78
|
}
|
|
@@ -138,7 +143,7 @@ export interface WakeEngineFactoryOptions {
|
|
|
138
143
|
/**
|
|
139
144
|
* The provisioned speech gate, present only when `voice.wake.vadThreshold` asks
|
|
140
145
|
* for one. Absent means the engine scores every frame, which is what the
|
|
141
|
-
* shipped default of 0 asks for
|
|
146
|
+
* shipped default of 0 asks for, not a gate that failed to load, because that
|
|
142
147
|
* case is a startup blocker upstream of here.
|
|
143
148
|
*/
|
|
144
149
|
readonly vadPath?: string;
|
|
@@ -152,7 +157,7 @@ export interface WakeEngineFactoryOptions {
|
|
|
152
157
|
* Build the `createEngine` callback the SDK listener drives.
|
|
153
158
|
*
|
|
154
159
|
* The listener calls it on EVERY start including a restart, because a restart
|
|
155
|
-
* exists to recover from a runtime that died
|
|
160
|
+
* exists to recover from a runtime that died, so the sessions are created here
|
|
156
161
|
* per call rather than captured once.
|
|
157
162
|
*/
|
|
158
163
|
export function createWakeEngineFactory(options: WakeEngineFactoryOptions): () => Promise<WakeWordEngine> {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* wake-runtime.ts
|
|
2
|
+
* wake-runtime.ts, wake-word detection on the terminal.
|
|
3
3
|
*
|
|
4
4
|
* The SDK owns the policy that would otherwise be rewritten per surface: the
|
|
5
5
|
* front end, the patience/cooldown rules, keeping ONE stream open across a wake
|
|
6
6
|
* so the utterance that follows is not clipped, resetting the engine afterwards
|
|
7
7
|
* so the command just spoken is not scored again, and the supervisor's restart
|
|
8
|
-
* and latch decisions. What is local is everything that touches this machine
|
|
8
|
+
* and latch decisions. What is local is everything that touches this machine,
|
|
9
9
|
* the recorder subprocess (capture.ts), the inference runtime (wake-inference.ts),
|
|
10
10
|
* transcription over the daemon (core/voice-stt-gateway.ts), the activation sound, and
|
|
11
11
|
* the shell's indicator row.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* - **ENABLING NEVER DOWNLOADS.** The model ships with the installation, so on a
|
|
16
16
|
* normal machine `start()` below finds the artifacts already there and needs
|
|
17
|
-
* nothing else
|
|
17
|
+
* nothing else, that is the whole point of provisioning at install time. What
|
|
18
18
|
* it must never do is FETCH: the check here is read-only and content-verified,
|
|
19
19
|
* and a host whose artifacts are missing or torn gets told which and gets the
|
|
20
20
|
* recovery command named, instead of a switch that silently pulls 6 MB. A
|
|
@@ -65,7 +65,7 @@ export interface WakeRuntimeDeps {
|
|
|
65
65
|
/** Runtime toggling: `voice.wake.enabled` and `voice.wake.surfaces.tui`. */
|
|
66
66
|
readonly subscribeConfig: (key: string, listener: () => void) => () => void;
|
|
67
67
|
readonly openCapture: AudioCaptureOpener;
|
|
68
|
-
/** Managed root the wake tree hangs off
|
|
68
|
+
/** Managed root the wake tree hangs off, `<managed>/wake` (SDK resolveManagedWakePaths). */
|
|
69
69
|
readonly managedRoot: string;
|
|
70
70
|
/** Directory this surface owns for the extracted onnxruntime assets. */
|
|
71
71
|
readonly assetDirectory: string;
|
|
@@ -95,7 +95,7 @@ export interface WakeRuntimeDeps {
|
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
97
|
* What this runtime reads out of provisioning: whether the wake models are usable
|
|
98
|
-
* at all, and whether the SPEECH GATE's own artifact is there
|
|
98
|
+
* at all, and whether the SPEECH GATE's own artifact is there, they are separate
|
|
99
99
|
* answers, because `voice.wake.vadThreshold` defaults to 0 and a detector runs
|
|
100
100
|
* perfectly well with no gate provisioned.
|
|
101
101
|
*/
|
|
@@ -200,7 +200,7 @@ export function wireWakeRuntime(deps: WakeRuntimeDeps): WakeRuntime {
|
|
|
200
200
|
if (settings.autoSubmit) deps.submitTurn(text);
|
|
201
201
|
else {
|
|
202
202
|
deps.writeDraft(text);
|
|
203
|
-
deps.notify('[Wake] Transcript placed in the composer (voice.wake.autoSubmit is off
|
|
203
|
+
deps.notify('[Wake] Transcript placed in the composer (voice.wake.autoSubmit is off: press Enter to send it).');
|
|
204
204
|
deps.render();
|
|
205
205
|
}
|
|
206
206
|
} catch (error) {
|
|
@@ -215,14 +215,14 @@ export function wireWakeRuntime(deps: WakeRuntimeDeps): WakeRuntime {
|
|
|
215
215
|
deps.notify(
|
|
216
216
|
`[Wake] voice.wake.enabled is on, but the wake models are not provisioned (${provision.reason ?? 'not-provisioned'}), `
|
|
217
217
|
+ 'so nothing is listening. Installing goodvibes provisions them and a running daemon retries at boot, so this '
|
|
218
|
-
+ 'means the download has not succeeded yet
|
|
218
|
+
+ 'means the download has not succeeded yet; run /voice wake setup to fetch and verify them now.',
|
|
219
219
|
);
|
|
220
220
|
deps.render();
|
|
221
221
|
return;
|
|
222
222
|
}
|
|
223
223
|
const paths = resolveManagedWakePaths(deps.managedRoot);
|
|
224
224
|
// The SDK resolves `voice.wake.models` to files: the pinned id inside the
|
|
225
|
-
// managed tree, any other id against voice.wake.customModelDir
|
|
225
|
+
// managed tree, any other id against voice.wake.customModelDir, and when that
|
|
226
226
|
// row is empty, against the managed `custom` directory, which is the fallback
|
|
227
227
|
// the row's description promises and the one a host would otherwise get wrong
|
|
228
228
|
// by looking in the process's working directory.
|
|
@@ -249,7 +249,7 @@ export function wireWakeRuntime(deps: WakeRuntimeDeps): WakeRuntime {
|
|
|
249
249
|
models: modelFiles.map((model) => ({ id: model.id, path: model.path })),
|
|
250
250
|
settings,
|
|
251
251
|
// The speech gate, when the row asks for one. `voice.wake.vadThreshold`
|
|
252
|
-
// above 0 with the artifact missing never reaches here
|
|
252
|
+
// above 0 with the artifact missing never reaches here, it is a blocker
|
|
253
253
|
// from resolveWakeRuntimeSettings, so the detector does not start at all
|
|
254
254
|
// rather than starting with the gate quietly absent.
|
|
255
255
|
...(settings.vadThreshold > 0 ? { vadPath: paths.vadPath } : {}),
|
|
@@ -273,7 +273,7 @@ export function wireWakeRuntime(deps: WakeRuntimeDeps): WakeRuntime {
|
|
|
273
273
|
// Reported to the user, not only logged: a detector that stopped
|
|
274
274
|
// listening is exactly the thing a silent log entry hides.
|
|
275
275
|
deps.notify(restarting
|
|
276
|
-
? `[Wake] The capture stream ended (${error.message})
|
|
276
|
+
? `[Wake] The capture stream ended (${error.message}): ${failureDetail}.`
|
|
277
277
|
: `[Wake] The wake-word detector stopped: ${failureDetail}. It stays off until voice.wake.enabled is turned off and on again.`);
|
|
278
278
|
deps.render();
|
|
279
279
|
},
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* command are derived from the usage strings documented in help.ts's
|
|
11
11
|
* COMMAND_HELP table (read-only reference; no mutation of existing files).
|
|
12
12
|
*
|
|
13
|
-
* Deferred wiring (one-line changes to existing files
|
|
13
|
+
* Deferred wiring (one-line changes to existing files, NOT done here):
|
|
14
14
|
* src/cli/completion.ts: replace renderCompletion() body with
|
|
15
15
|
* ```
|
|
16
16
|
* import { generateCompletion } from './completions/generate.ts';
|
|
@@ -629,7 +629,7 @@ export function generateFish(surface: CompletionSurface): string {
|
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
// ---------------------------------------------------------------------------
|
|
632
|
-
// Dispatcher
|
|
632
|
+
// Dispatcher, mirrors the existing renderCompletion(shell) API
|
|
633
633
|
// ---------------------------------------------------------------------------
|
|
634
634
|
|
|
635
635
|
/**
|
package/src/cli/doctor.ts
CHANGED
|
@@ -9,14 +9,14 @@ import type { GoodVibesCliOutputFormat } from '@pellux/goodvibes-terminal-shell'
|
|
|
9
9
|
import { buildHooksValidation } from './hooks-report.ts';
|
|
10
10
|
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
12
|
-
// `goodvibes doctor <explain|routing|hooks
|
|
12
|
+
// `goodvibes doctor <explain|routing|hooks>`, the diagnostician subcommands.
|
|
13
13
|
// Each one explains a decision the platform already makes, reading the LIVE
|
|
14
14
|
// config and reusing the platform's OWN decision machinery. None of them
|
|
15
15
|
// changes config or fires a real action:
|
|
16
|
-
// explain
|
|
16
|
+
// explain , walks the real PermissionManager to say why a tool/command
|
|
17
17
|
// would be allowed / asked / denied under the current mode.
|
|
18
|
-
// routing
|
|
19
|
-
// hooks
|
|
18
|
+
// routing , prints which model/provider serves which role, from live config.
|
|
19
|
+
// hooks , lists registered hooks, from where, and their validation status
|
|
20
20
|
// (reuses the hooks-validate core in hooks-report.ts).
|
|
21
21
|
// ---------------------------------------------------------------------------
|
|
22
22
|
|
|
@@ -124,7 +124,7 @@ function reasonExplanation(result: PermissionCheckResult, mode: string, toolKey:
|
|
|
124
124
|
case 'mode_allow_all':
|
|
125
125
|
if (mode === 'plan') return 'Plan mode allows read-class tools.';
|
|
126
126
|
if (mode === 'accept-edits') return 'Accept-edits mode allows read-class tools.';
|
|
127
|
-
return 'Permission mode is "allow-all"
|
|
127
|
+
return 'Permission mode is "allow-all": every tool call is auto-approved.';
|
|
128
128
|
case 'mode_denied': return 'The active permission mode denies this tool class.';
|
|
129
129
|
case 'plan_mode': return 'Plan mode refuses mutating / execute / delegate tools and steers the model to present a plan instead.';
|
|
130
130
|
case 'mode_accept_edits': return 'Accept-edits mode auto-approves file write/edit tools.';
|
|
@@ -134,7 +134,7 @@ function reasonExplanation(result: PermissionCheckResult, mode: string, toolKey:
|
|
|
134
134
|
case 'session_cached_allow': return 'A remembered session decision ([A] allow-always) approves this call.';
|
|
135
135
|
case 'session_cached_deny': return 'A remembered session decision denies this call.';
|
|
136
136
|
case 'user_approved':
|
|
137
|
-
case 'user_denied': return 'This reaches a Human-in-the-Loop approval prompt
|
|
137
|
+
case 'user_denied': return 'This reaches a Human-in-the-Loop approval prompt; the outcome depends on your response at the prompt.';
|
|
138
138
|
default: return 'Decided by the platform permission machinery.';
|
|
139
139
|
}
|
|
140
140
|
}
|
|
@@ -205,7 +205,7 @@ async function explain(options: DoctorSubcommandOptions): Promise<CliCommandOutp
|
|
|
205
205
|
|
|
206
206
|
const a = result.analysis;
|
|
207
207
|
const lines: string[] = [
|
|
208
|
-
'GoodVibes doctor
|
|
208
|
+
'GoodVibes doctor: explain permission decision',
|
|
209
209
|
` subject : ${args.join(' ')}`,
|
|
210
210
|
` resolved as : ${target.interpretation}`,
|
|
211
211
|
` tool : ${target.tool} (category: ${category})`,
|
|
@@ -222,7 +222,7 @@ async function explain(options: DoctorSubcommandOptions): Promise<CliCommandOutp
|
|
|
222
222
|
` summary : ${a.summary}`,
|
|
223
223
|
...a.reasons.slice(0, 3).map((r) => ` reason : ${r}`),
|
|
224
224
|
'',
|
|
225
|
-
'Layers walked (priority order
|
|
225
|
+
'Layers walked (priority order: the platform PermissionManager decides; this shows the order it walks):',
|
|
226
226
|
...LAYER_NAMES.map((name, i) => ` ${i === decidedIdx ? '▶' : ' '} ${i + 1}. ${name}${i === decidedIdx ? ' ← DECIDED HERE' : ''}`),
|
|
227
227
|
'',
|
|
228
228
|
`Decision: ${verdict}`,
|
|
@@ -284,7 +284,7 @@ function buildRoutingRoles(config: ConfigManager): RoutingRole[] {
|
|
|
284
284
|
provider: emptyProvider(toolProvider),
|
|
285
285
|
model: toolModel || '(unset)',
|
|
286
286
|
keys: ['tools.llmEnabled', 'tools.llmProvider', 'tools.llmModel'],
|
|
287
|
-
...(config.get('tools.llmEnabled') === true ? {} : { note: 'disabled
|
|
287
|
+
...(config.get('tools.llmEnabled') === true ? {} : { note: 'disabled: no tool-LLM route active' }),
|
|
288
288
|
},
|
|
289
289
|
{
|
|
290
290
|
role: 'Helper (cache/compaction/commit-message/etc.)',
|
|
@@ -292,7 +292,7 @@ function buildRoutingRoles(config: ConfigManager): RoutingRole[] {
|
|
|
292
292
|
provider: emptyProvider(helperProvider),
|
|
293
293
|
model: helperModel || '(unset)',
|
|
294
294
|
keys: ['helper.enabled', 'helper.globalProvider', 'helper.globalModel'],
|
|
295
|
-
...(config.get('helper.enabled') === true ? {} : { note: 'disabled
|
|
295
|
+
...(config.get('helper.enabled') === true ? {} : { note: 'disabled: helper tasks stay on the main model' }),
|
|
296
296
|
},
|
|
297
297
|
{
|
|
298
298
|
role: 'Narration LLM (TTS phrasing)',
|
|
@@ -312,7 +312,7 @@ function routing(options: DoctorSubcommandOptions): CliCommandOutput {
|
|
|
312
312
|
return { output: JSON.stringify({ roles }, null, 2), exitCode: 0 };
|
|
313
313
|
}
|
|
314
314
|
const lines: string[] = [
|
|
315
|
-
'GoodVibes doctor
|
|
315
|
+
'GoodVibes doctor: model / provider routing (live config)',
|
|
316
316
|
'',
|
|
317
317
|
];
|
|
318
318
|
for (const role of roles) {
|
|
@@ -345,11 +345,11 @@ function hooks(options: DoctorSubcommandOptions): CliCommandOutput {
|
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
const lines: string[] = [
|
|
348
|
-
'GoodVibes doctor
|
|
348
|
+
'GoodVibes doctor: registered hooks',
|
|
349
349
|
` source file : ${report.path}`,
|
|
350
350
|
];
|
|
351
351
|
if (!report.present) {
|
|
352
|
-
lines.push(' no hooks file present
|
|
352
|
+
lines.push(' no hooks file present: nothing registered.');
|
|
353
353
|
return { output: lines.join('\n'), exitCode: 0 };
|
|
354
354
|
}
|
|
355
355
|
if (report.reason && report.checks.length === 0 && report.topLevelIssues.length === 0) {
|
|
@@ -3,7 +3,7 @@ import { join } from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The TUI's own `.goodvibes/` directory (logs, overflow buffers, exec output,
|
|
6
|
-
* cache, session state, etc.) is transient scratch space, not project source
|
|
6
|
+
* cache, session state, etc.) is transient scratch space, not project source,
|
|
7
7
|
* but nothing else in the codebase excludes it from the *project's* git
|
|
8
8
|
* history. Any `git add -A` (write-quit's auto-commit, a WRFC chain's own
|
|
9
9
|
* commit, etc.) sweeps the whole tree in unless the project's .gitignore
|
|
@@ -17,7 +17,7 @@ const GOODVIBES_IGNORE_PATTERN = /(^|\n)[ \t]*\/?\.goodvibes\/?\*?[ \t]*(\n|$)/;
|
|
|
17
17
|
* Ensures the project's .gitignore excludes .goodvibes/, appending the rule
|
|
18
18
|
* exactly once if it is verifiably absent.
|
|
19
19
|
*
|
|
20
|
-
* @returns true only the FIRST time the rule is actually written this call
|
|
20
|
+
* @returns true only the FIRST time the rule is actually written this call,
|
|
21
21
|
* i.e. this specific invocation just appended/created it. Every subsequent
|
|
22
22
|
* launch (rule already present) and every no-op case (not a git repo, or the
|
|
23
23
|
* write failed) return false. The caller uses this to print a one-time
|
|
@@ -38,7 +38,7 @@ export function ensureGoodvibesGitignore(projectRoot: string): boolean {
|
|
|
38
38
|
appendFileSync(gitignorePath, separator + rule);
|
|
39
39
|
return true;
|
|
40
40
|
} catch {
|
|
41
|
-
// Best-effort only
|
|
41
|
+
// Best-effort only, never block startup on a gitignore write failure.
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
44
|
}
|
package/src/cli/entrypoint.ts
CHANGED
|
@@ -112,9 +112,9 @@ export async function prepareShellCliRuntime(
|
|
|
112
112
|
} = resolveShellEntrypointOwnership(roots, cli.flags.workingDir ?? (cli.command === 'tui' ? cli.commandArgs[0] : undefined));
|
|
113
113
|
configureActivityLogger(join(bootstrapWorkingDir, '.goodvibes', 'logs'));
|
|
114
114
|
// Only prints the first time the rule is actually appended (not on every
|
|
115
|
-
// launch)
|
|
115
|
+
// launch), see ensureGoodvibesGitignore's return-value doc.
|
|
116
116
|
if (ensureGoodvibesGitignore(bootstrapWorkingDir)) {
|
|
117
|
-
console.log("[goodvibes] added '.goodvibes/' to .gitignore
|
|
117
|
+
console.log("[goodvibes] added '.goodvibes/' to .gitignore: this directory holds transient TUI state (logs, session cache, exec output), not project source.");
|
|
118
118
|
}
|
|
119
119
|
const daemonConfigMigration = runDaemonConfigMigration(bootstrapHomeDirectory);
|
|
120
120
|
if (daemonConfigMigration?.migrated && (daemonConfigMigration.marker.moved.length + daemonConfigMigration.marker.discarded.length) > 0) {
|
|
@@ -250,7 +250,7 @@ export async function prepareShellCliRuntime(
|
|
|
250
250
|
? renderOnboardingCliStatus(statusOptions)
|
|
251
251
|
: renderCliStatus(statusOptions));
|
|
252
252
|
// Advisory findings are notes on an otherwise-usable install and must
|
|
253
|
-
// never make a healthy install report failure
|
|
253
|
+
// never make a healthy install report failure, only a must-fix finding
|
|
254
254
|
// exits non-zero; --strict (for CI) flips advisories to failures too.
|
|
255
255
|
process.exit(cli.command === 'doctor' ? resolveDoctorExitCode(snapshot.findings, cli.flags.strict) : 0);
|
|
256
256
|
}
|