@pellux/goodvibes-tui 2.0.14 → 2.0.16
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 +49 -0
- package/README.md +64 -44
- package/docs/README.md +6 -6
- 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 +19 -19
- 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 +11 -11
- 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
|
@@ -8,17 +8,17 @@
|
|
|
8
8
|
* Charter: when the owning surface is LIVE (heartbeating within the daemon's
|
|
9
9
|
* SURFACE_ROUTE_FRESHNESS window), a steer is DELIVERED to that surface rather
|
|
10
10
|
* than spawning a daemon-side executor (which would fail on the daemon's empty
|
|
11
|
-
* model registry). The daemon already does its half
|
|
11
|
+
* model registry). The daemon already does its half, `sessions.steer` /
|
|
12
12
|
* `sessions.followUp` to a surface-managed session with a fresh participant
|
|
13
13
|
* QUEUES the input for the surface (mode 'queued-for-surface') instead of
|
|
14
14
|
* spawning. This poller is the surface completing that contract:
|
|
15
15
|
*
|
|
16
16
|
* 1. poll `sessions.inputs.list` for QUEUED inputs on ITS OWN sessionId
|
|
17
17
|
* (the query is scoped by sessionId, so a steer for another session can
|
|
18
|
-
* never land here
|
|
18
|
+
* never land here, the per-session isolation the concurrent-sessions
|
|
19
19
|
* charter requires);
|
|
20
20
|
* 2. hand each steer/follow-up to `onSteer` (the surface-side injection into
|
|
21
|
-
* the TUI's turn machinery
|
|
21
|
+
* the TUI's turn machinery, narrate "steer received from <surface>" and
|
|
22
22
|
* fire the next-turn boundary), skipping the TUI's own submissions;
|
|
23
23
|
* 3. acknowledge on the wire via `sessions.inputs.deliver` (queued → delivered)
|
|
24
24
|
* so every surface sees delivery truth live and the input is not re-picked.
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* Discipline (mirrors SessionSpineClient): every wire call is best-effort and
|
|
27
27
|
* never throws into the render/keystroke path; a failed poll leaves the cursor
|
|
28
28
|
* where it was so the input is retried on the next tick (deliver is the only
|
|
29
|
-
* de-dup
|
|
29
|
+
* de-dup, an input already advanced past 'queued' is not returned again).
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
32
|
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
@@ -35,7 +35,7 @@ import type {
|
|
|
35
35
|
SharedSessionInputRecord,
|
|
36
36
|
} from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
37
37
|
|
|
38
|
-
/** The TUI's own participant surfaceId
|
|
38
|
+
/** The TUI's own participant surfaceId, inputs it authored are never re-injected. */
|
|
39
39
|
export const TUI_SURFACE_ID = 'surface:tui';
|
|
40
40
|
|
|
41
41
|
/** The narrow inbound wire surface this poller needs. Structurally satisfied by
|
|
@@ -75,7 +75,7 @@ export interface SessionInboundInputPollerOptions {
|
|
|
75
75
|
readonly intervalMs?: number;
|
|
76
76
|
readonly now?: () => number;
|
|
77
77
|
readonly log?: InboundLogger;
|
|
78
|
-
/** The poller's own surfaceId
|
|
78
|
+
/** The poller's own surfaceId, inputs it authored are skipped (default TUI). */
|
|
79
79
|
readonly ownSurfaceId?: string;
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -92,7 +92,7 @@ export class SessionInboundInputPoller {
|
|
|
92
92
|
private client: SpineInboundInputsClient | null = null;
|
|
93
93
|
private timer: ReturnType<typeof setInterval> | null = null;
|
|
94
94
|
private polling = false;
|
|
95
|
-
/** Exclusive createdAt cursor, per session
|
|
95
|
+
/** Exclusive createdAt cursor, per session, a session swap resets it. */
|
|
96
96
|
private cursor = 0;
|
|
97
97
|
private cursorSessionId: string | null = null;
|
|
98
98
|
|
|
@@ -120,7 +120,7 @@ export class SessionInboundInputPoller {
|
|
|
120
120
|
this.timer = setInterval(() => { void this.pollOnce(); }, this.intervalMs);
|
|
121
121
|
this.timer.unref?.();
|
|
122
122
|
}
|
|
123
|
-
this.log.info('session inbound-input poller activated
|
|
123
|
+
this.log.info('session inbound-input poller activated: collecting queued steers for this surface', {});
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/** Detach the backend and stop polling (daemon mode resolved to non-external, or lost). */
|
|
@@ -185,9 +185,9 @@ export class SessionInboundInputPoller {
|
|
|
185
185
|
try {
|
|
186
186
|
this.onSteer(steer);
|
|
187
187
|
} catch (error) {
|
|
188
|
-
// A failing injection must not wedge the poll loop or drop the ack
|
|
188
|
+
// A failing injection must not wedge the poll loop or drop the ack,
|
|
189
189
|
// narrate-and-continue; the input is still acked so it is not re-picked.
|
|
190
|
-
this.log.debug('session inbound steer injection threw
|
|
190
|
+
this.log.debug('session inbound steer injection threw; continuing', {
|
|
191
191
|
error: error instanceof Error ? error.message : String(error),
|
|
192
192
|
});
|
|
193
193
|
}
|
|
@@ -196,14 +196,14 @@ export class SessionInboundInputPoller {
|
|
|
196
196
|
await client.deliverInput(sessionId, input.id, { consumed: false });
|
|
197
197
|
delivered += 1;
|
|
198
198
|
} catch (error) {
|
|
199
|
-
this.log.debug('session inbound deliver ack failed
|
|
199
|
+
this.log.debug('session inbound deliver ack failed; will retry', {
|
|
200
200
|
error: error instanceof Error ? error.message : String(error),
|
|
201
201
|
});
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
} catch (error) {
|
|
205
205
|
// Poll failed entirely (daemon gone, transient): keep the cursor, retry next tick.
|
|
206
|
-
this.log.debug('session inbound-input poll failed
|
|
206
|
+
this.log.debug('session inbound-input poll failed: retry next tick', {
|
|
207
207
|
error: error instanceof Error ? error.message : String(error),
|
|
208
208
|
});
|
|
209
209
|
} finally {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* session-resume-liveness-confirm.ts
|
|
2
|
+
* session-resume-liveness-confirm.ts, the "this session is open somewhere
|
|
3
3
|
* else" check for the session-browser / panel resume seam.
|
|
4
4
|
*
|
|
5
5
|
* `/session resume <id>` already refuses to resume a session whose liveness
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Semantics are unchanged from the text-command check and stay best-effort: a
|
|
13
13
|
* missing, stale, or unreadable marker means "we can't tell", and the resume
|
|
14
14
|
* proceeds exactly as it always did. The marker belonging to THIS process is
|
|
15
|
-
* ignored too
|
|
15
|
+
* ignored too, re-resuming the session already open here is not a fork.
|
|
16
16
|
*/
|
|
17
17
|
import { checkSessionLiveness } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
18
18
|
import type { SessionSurface } from '@/runtime/index.ts';
|
|
@@ -28,8 +28,8 @@ export type LiveResumeSelectionOpener = (
|
|
|
28
28
|
/**
|
|
29
29
|
* The confirm modal's title. Short by necessity: the selection overlay
|
|
30
30
|
* truncates its title to the box width (selection-modal-overlay.ts), so
|
|
31
|
-
* anything the operator must actually read
|
|
32
|
-
* do
|
|
31
|
+
* anything the operator must actually read, the pid, and what resuming would
|
|
32
|
+
* do, belongs in a row's `detail`, which that overlay wraps instead.
|
|
33
33
|
*/
|
|
34
34
|
export const LIVE_RESUME_CONFIRM_TITLE = 'Session open elsewhere';
|
|
35
35
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* satisfied by `HttpTransport.operator.sessions`), and `createTuiSpineTransport`
|
|
12
12
|
* folds it into the SDK's `SpineTransport` the SAME way the SDK's own
|
|
13
13
|
* consumability proof (`session-spine-daemon-integration.test.ts`) does:
|
|
14
|
-
* resolve -> `'ok'`, throw -> `'offline'`. The TUI never emits `'rejected'
|
|
14
|
+
* resolve -> `'ok'`, throw -> `'offline'`. The TUI never emits `'rejected'`, it
|
|
15
15
|
* has no durable-refusal vocabulary to fold (that distinction is the agent's
|
|
16
16
|
* REST mirror's job, per the SDK's divergence ruling #6/#7).
|
|
17
17
|
*/
|
|
@@ -25,7 +25,7 @@ import type { SpineResult, SpineTransport } from '@pellux/goodvibes-sdk/platform
|
|
|
25
25
|
/**
|
|
26
26
|
* The minimal wire surface this adapter needs. Structurally satisfied by BOTH
|
|
27
27
|
* the SDK's in-process `OperatorClient['sessions']` (DirectTransport) and the
|
|
28
|
-
* wire `HttpTransportOperatorClient['sessions']` (HttpTransport)
|
|
28
|
+
* wire `HttpTransportOperatorClient['sessions']` (HttpTransport), bootstrap.ts
|
|
29
29
|
* only ever constructs an Http-backed instance in practice, but this is
|
|
30
30
|
* deliberately typed against the narrow shape rather than either concrete
|
|
31
31
|
* transport type so it has no compile-time dependency on which transport
|
|
@@ -39,7 +39,7 @@ export interface SpineSessionsClient {
|
|
|
39
39
|
/**
|
|
40
40
|
* Adapt the TUI's typed `SpineSessionsClient` into the SDK `SessionSpineClient`'s
|
|
41
41
|
* injected `SpineTransport`. A rejecting wire call is treated as a transient
|
|
42
|
-
* connectivity fault (`'offline'`) rather than a durable refusal
|
|
42
|
+
* connectivity fault (`'offline'`) rather than a durable refusal, the same
|
|
43
43
|
* binary reachability model the pre-extraction TUI-local client used.
|
|
44
44
|
*/
|
|
45
45
|
export function createTuiSpineTransport(sessionsClient: SpineSessionsClient): SpineTransport {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Panels domain state
|
|
2
|
+
* Panels domain state, tracks the panel-first operator UX surfaces:
|
|
3
3
|
* which panels are open, their layout, and focus state.
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -43,7 +43,7 @@ export interface PanelState {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
* PanelDomainState
|
|
46
|
+
* PanelDomainState, panel layout and focus management.
|
|
47
47
|
*/
|
|
48
48
|
export interface PanelDomainState {
|
|
49
49
|
// ── Domain metadata ────────────────────────────────────────────────────────
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* UI performance domain state
|
|
2
|
+
* UI performance domain state, tracks TUI render performance,
|
|
3
3
|
* frame rates, and input responsiveness metrics.
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -31,7 +31,7 @@ export interface InputLatencySample {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* UiPerfDomainState
|
|
34
|
+
* UiPerfDomainState, TUI render and input performance metrics.
|
|
35
35
|
*/
|
|
36
36
|
export interface UiPerfDomainState {
|
|
37
37
|
// ── Domain metadata ────────────────────────────────────────────────────────
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Runtime store
|
|
2
|
+
* Runtime store, Zustand vanilla store for goodvibes-tui.
|
|
3
3
|
*
|
|
4
4
|
* Uses `createStore` from `zustand/vanilla` (NOT the React `create` hook)
|
|
5
5
|
* because goodvibes-tui is a terminal app with no React renderer.
|
|
@@ -135,7 +135,7 @@ export const selectSurfacePerf = selectUiPerf;
|
|
|
135
135
|
// Derived selectors
|
|
136
136
|
// ---------------------------------------------------------------------------
|
|
137
137
|
|
|
138
|
-
/** Active model summary
|
|
138
|
+
/** Active model summary, the three most-used fields for display and routing. */
|
|
139
139
|
export interface ActiveModelSummary {
|
|
140
140
|
providerId: string;
|
|
141
141
|
modelId: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* RuntimeState
|
|
2
|
+
* RuntimeState, the canonical top-level state shape for the goodvibes-tui
|
|
3
3
|
* runtime store. All domain slices are defined here.
|
|
4
4
|
*
|
|
5
5
|
* Each domain includes revision, lastUpdatedAt, and source metadata fields.
|
|
@@ -66,7 +66,7 @@ import { createInitialIntelligenceState } from '@/runtime/index.ts';
|
|
|
66
66
|
import { createInitialUiPerfState } from './domains/ui-perf.ts';
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
|
-
* RuntimeState
|
|
69
|
+
* RuntimeState, the complete state shape managed by the runtime store.
|
|
70
70
|
*
|
|
71
71
|
* Domain slices, each with revision/lastUpdatedAt/source metadata.
|
|
72
72
|
* All mutations must go through typed domain dispatch APIs.
|
|
@@ -42,7 +42,7 @@ export interface UiSessionServices {
|
|
|
42
42
|
readonly sessionManager: RuntimeServices['sessionManager'];
|
|
43
43
|
/**
|
|
44
44
|
* The panel-facing session READ source is the cross-surface union
|
|
45
|
-
* facade, not the raw local broker
|
|
45
|
+
* facade, not the raw local broker, in adopted-daemon ('external') mode the
|
|
46
46
|
* local broker misses sessions hosted for other surfaces. Sync signature
|
|
47
47
|
* preserved; the facade's cache makes that honest (see session-union-cache.ts).
|
|
48
48
|
*/
|
|
@@ -59,7 +59,7 @@ export interface UiPlatformServices {
|
|
|
59
59
|
readonly surfaceRegistry: RuntimeServices['surfaceRegistry'];
|
|
60
60
|
readonly subscriptionManager: RuntimeServices['subscriptionManager'];
|
|
61
61
|
readonly secretsManager: SecretsManager;
|
|
62
|
-
/** Per-device pairing tokens
|
|
62
|
+
/** Per-device pairing tokens, backs the pairing modal QR and the settings device surface. */
|
|
63
63
|
readonly pairingTokens: RuntimeServices['pairingTokens'];
|
|
64
64
|
readonly tokenAuditor: RuntimeServices['tokenAuditor'];
|
|
65
65
|
readonly replayEngine: RuntimeServices['replayEngine'];
|
|
@@ -119,7 +119,7 @@ export interface UiRuntimeSharedServices {
|
|
|
119
119
|
readonly processRegistry: RuntimeServices['processRegistry'];
|
|
120
120
|
/** The Fleet panel's read model: local rows union the adopted daemon's. */
|
|
121
121
|
readonly fleetReadModel: RuntimeServices['fleetReadModel'];
|
|
122
|
-
/** The shared runtime event bus
|
|
122
|
+
/** The shared runtime event bus, the Fleet panel subscribes to its 'communication' domain for the honest steer-consumed signal. */
|
|
123
123
|
readonly runtimeBus: RuntimeServices['runtimeBus'];
|
|
124
124
|
};
|
|
125
125
|
}
|
|
@@ -4,7 +4,7 @@ import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
|
4
4
|
import type { RuntimeEventBus, SessionSurface } from '@/runtime/index.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* createWorkspaceCheckpointing
|
|
7
|
+
* createWorkspaceCheckpointing, build the per-workspace checkpoint manager and
|
|
8
8
|
* kick off its initialization. Extracted from services.ts so the (load-bearing)
|
|
9
9
|
* failure-mode notes below live with the code they describe.
|
|
10
10
|
*/
|
|
@@ -22,14 +22,14 @@ export function createWorkspaceCheckpointing(opts: {
|
|
|
22
22
|
configManager: ConfigManager;
|
|
23
23
|
}): WorkspaceCheckpointManager {
|
|
24
24
|
// Checkpoint root-guard from the user's `checkpoints.*` config (docs/configuration.md;
|
|
25
|
-
// inert until the platform SDK's checkpoint manager exposes the keys
|
|
25
|
+
// inert until the platform SDK's checkpoint manager exposes the keys, see the reader's note).
|
|
26
26
|
const manager = new WorkspaceCheckpointManager(
|
|
27
27
|
withCheckpointGuardSettings({ workspaceRoot: opts.workspaceRoot, surface: opts.surface, runtimeBus: opts.runtimeBus }, opts.configManager),
|
|
28
28
|
);
|
|
29
29
|
// Fire-and-forget: subscriptions go live immediately if init() succeeds.
|
|
30
30
|
// If it rejects, WorkspaceCheckpointManager caches that rejection on
|
|
31
31
|
// `initPromise` and never clears it, so every later call (create/list/
|
|
32
|
-
// diff/restore
|
|
32
|
+
// diff/restore, each awaits init() first) re-throws the same error
|
|
33
33
|
// forever: checkpointing becomes entirely unavailable for the rest of the
|
|
34
34
|
// session, not "degraded to manual-only". The `.catch(() => {})` here only
|
|
35
35
|
// exists to prevent an unhandled rejection at startup; the checkpoint
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* WRFC chain persistence
|
|
2
|
+
* WRFC chain persistence, snapshot active chains to disk on every lifecycle
|
|
3
3
|
* event so that a crash/restart can surface interrupted chains to the operator,
|
|
4
4
|
* and so that terminal chains (passed/failed/cancelled) remain visible as
|
|
5
5
|
* bounded history rather than vanishing the moment they finish.
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
*
|
|
21
21
|
* A chain that looked interrupted (non-terminal) in the old snapshot can be
|
|
22
22
|
* reaped to terminal IN PLACE by `WrfcController.importChain` (the zombie-reap pass:
|
|
23
|
-
* no member agent survived the restart
|
|
23
|
+
* no member agent survived the restart, see wrfc-controller.ts). This
|
|
24
24
|
* module always re-checks `chain.state` AFTER the import call, never the
|
|
25
25
|
* pre-import classification, so a reaped chain is treated as history, not
|
|
26
26
|
* re-surfaced as interrupted and never re-imported again on a later restart.
|
|
27
27
|
*
|
|
28
28
|
* 3. Terminal-history retention (bounded, most-recently-completed first):
|
|
29
29
|
* Previously, every terminal chain was pruned from the snapshot the moment
|
|
30
|
-
* it was written or rehydrated
|
|
30
|
+
* it was written or rehydrated, a killed/finished chain vanished from
|
|
31
31
|
* wrfc-chains.json entirely, including across a restart, so nothing could
|
|
32
32
|
* ever honestly report "last chain: <state>". Terminal chains are now
|
|
33
33
|
* RETAINED, capped at MAX_TERMINAL_HISTORY (20) most-recently-completed,
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* - across a restart, via rehydrate() seeding that cache from whatever
|
|
39
39
|
* was already terminal in the prior snapshot instead of discarding it.
|
|
40
40
|
* A corrupt or version-mismatched snapshot is quarantined by renaming it
|
|
41
|
-
* to `<path>.unrecognized
|
|
41
|
+
* to `<path>.unrecognized`, never a hard crash.
|
|
42
42
|
*
|
|
43
43
|
* Snapshot path: `.goodvibes/tui/wrfc-chains.json`
|
|
44
44
|
* Snapshot schema: `{ version: 1, writtenAt: number, chains: WrfcChain[] }`
|
|
@@ -58,7 +58,7 @@ const DEBOUNCE_MS = 250;
|
|
|
58
58
|
/** Bounded terminal-history retention: keep the most recent K chains, prune beyond. */
|
|
59
59
|
const MAX_TERMINAL_HISTORY = 20;
|
|
60
60
|
|
|
61
|
-
/** Terminal states
|
|
61
|
+
/** Terminal states, chains in these states will not be surfaced as interrupted. */
|
|
62
62
|
const TERMINAL_STATES = new Set<WrfcState>(['passed', 'failed']);
|
|
63
63
|
|
|
64
64
|
/** Non-terminal (interruptible) states. */
|
|
@@ -90,7 +90,7 @@ export interface WrfcControllerReader {
|
|
|
90
90
|
* Re-import a chain recovered from a previous process so it reappears in the
|
|
91
91
|
* controller's in-memory map and becomes selectable/resumable from the panel.
|
|
92
92
|
* Optional so read-only test doubles can omit it; the real WrfcController
|
|
93
|
-
* provides it. `force` is left at its default
|
|
93
|
+
* provides it. `force` is left at its default, on a fresh start the map is
|
|
94
94
|
* empty so importing never clobbers a live chain.
|
|
95
95
|
*/
|
|
96
96
|
importChain?(chain: WrfcChain, force?: boolean): boolean;
|
|
@@ -99,9 +99,9 @@ export interface WrfcControllerReader {
|
|
|
99
99
|
export interface WrfcPersistenceOptions {
|
|
100
100
|
/** Absolute path to the snapshot file, e.g. `.goodvibes/tui/wrfc-chains.json`. */
|
|
101
101
|
readonly snapshotPath: string;
|
|
102
|
-
/** Factory for the current SystemMessageRouter
|
|
102
|
+
/** Factory for the current SystemMessageRouter, may return null before it is wired. */
|
|
103
103
|
readonly getSystemMessageRouter: () => SystemMessageRouter | null;
|
|
104
|
-
/** WrfcController access
|
|
104
|
+
/** WrfcController access, listChains() (read) plus optional importChain() (re-import on rehydrate). */
|
|
105
105
|
readonly controller: WrfcControllerReader;
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -152,7 +152,7 @@ class WrfcPersistenceImpl implements WrfcPersistence {
|
|
|
152
152
|
/**
|
|
153
153
|
* Bounded terminal-history cache (most-recently-completed first once
|
|
154
154
|
* trimmed). Survives past WrfcController's own in-memory cleanup of
|
|
155
|
-
* terminated chains (60s after termination
|
|
155
|
+
* terminated chains (60s after termination, see wrfc-controller.ts
|
|
156
156
|
* scheduleChainCleanup) so a chain that ages out of listChains() is not
|
|
157
157
|
* silently dropped from the persisted snapshot.
|
|
158
158
|
*/
|
|
@@ -209,7 +209,7 @@ class WrfcPersistenceImpl implements WrfcPersistence {
|
|
|
209
209
|
// chain. The accessor is optional for read-only test doubles.
|
|
210
210
|
//
|
|
211
211
|
// NOTE: importChain may reap this chain to a terminal state IN PLACE
|
|
212
|
-
// (zombie reap: no member agent survived the restart)
|
|
212
|
+
// (zombie reap: no member agent survived the restart),
|
|
213
213
|
// always read chain.state AFTER this call below, never the pre-import
|
|
214
214
|
// classification captured by candidateInterrupted.
|
|
215
215
|
this.controller.importChain?.(chain);
|
|
@@ -218,7 +218,7 @@ class WrfcPersistenceImpl implements WrfcPersistence {
|
|
|
218
218
|
// Re-partition after the reap check: a chain that looked interrupted
|
|
219
219
|
// before import may now be terminal. Only genuinely still-live chains are
|
|
220
220
|
// surfaced to the operator as interrupted; anything reaped just now joins
|
|
221
|
-
// history instead
|
|
221
|
+
// history instead, it is done, not a resurrection candidate, and must
|
|
222
222
|
// never be handed to importChain again on a future restart (a chain only
|
|
223
223
|
// ever lands in candidateInterrupted while its persisted state is
|
|
224
224
|
// non-terminal; once it's history its state is terminal for good).
|
|
@@ -230,7 +230,7 @@ class WrfcPersistenceImpl implements WrfcPersistence {
|
|
|
230
230
|
for (const chain of this._interruptedChains) {
|
|
231
231
|
const msg =
|
|
232
232
|
`[WRFC] Chain ${chain.id.slice(0, 12)} (${chain.task.slice(0, 60).trim()}) ` +
|
|
233
|
-
`was interrupted by a restart
|
|
233
|
+
`was interrupted by a restart; state was '${chain.state}' ` +
|
|
234
234
|
`after ${chain.reviewCycles} review cycle${chain.reviewCycles !== 1 ? 's' : ''}`;
|
|
235
235
|
router?.wrfc(msg, 'high');
|
|
236
236
|
}
|
|
@@ -238,7 +238,7 @@ class WrfcPersistenceImpl implements WrfcPersistence {
|
|
|
238
238
|
// Rewrite the snapshot only when something actually changed: a chain was
|
|
239
239
|
// reaped just now, or the history cap pruned an entry that was on disk.
|
|
240
240
|
// Terminal chains are RETAINED (bounded to MAX_TERMINAL_HISTORY, most
|
|
241
|
-
// recently completed first) instead of erased
|
|
241
|
+
// recently completed first) instead of erased, post-restart surfaces
|
|
242
242
|
// (fleet, the resume notice, /wrfc history) need this to honestly report
|
|
243
243
|
// e.g. "last chain: cancelled".
|
|
244
244
|
if (reapedJustNow.length > 0 || alreadyTerminal.length !== this._terminalHistory.length) {
|
|
@@ -299,7 +299,7 @@ class WrfcPersistenceImpl implements WrfcPersistence {
|
|
|
299
299
|
/**
|
|
300
300
|
* Combine the live chains the controller is currently tracking with any
|
|
301
301
|
* historical terminal chains the live map has already forgotten (e.g. after
|
|
302
|
-
* WrfcController's own 60s in-memory cleanup)
|
|
302
|
+
* WrfcController's own 60s in-memory cleanup), so the persisted file never
|
|
303
303
|
* loses a terminal chain just because the live map stopped carrying it.
|
|
304
304
|
* Live entries win on id collision since they are always the freshest copy.
|
|
305
305
|
*/
|
|
@@ -313,7 +313,7 @@ class WrfcPersistenceImpl implements WrfcPersistence {
|
|
|
313
313
|
try {
|
|
314
314
|
atomicWriteFileSync(this.snapshotPath, JSON.stringify(snapshot), { mkdirp: true });
|
|
315
315
|
} catch {
|
|
316
|
-
// Best-effort
|
|
316
|
+
// Best-effort, never crash the TUI over a persistence failure.
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CLI utility script
|
|
1
|
+
// CLI utility script, not imported by the app. console usage is intentional.
|
|
2
2
|
import { readFileSync } from 'fs';
|
|
3
3
|
import { AgentMessageBus } from '@pellux/goodvibes-sdk/platform/agents';
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ export type PendingPermissionState = PermissionRequest & {
|
|
|
9
9
|
detailsExpanded?: boolean;
|
|
10
10
|
/**
|
|
11
11
|
* Active typed-reply mode: 'deny-reason' (started by typing while the card
|
|
12
|
-
* is up
|
|
12
|
+
* is up, Enter denies with the typed reason as feedback) or 'exec-answer'
|
|
13
13
|
* (an exec-prompt ask; Enter approves with the typed answer feeding the
|
|
14
14
|
* running command's stdin). Undefined = plain card keys.
|
|
15
15
|
*/
|
|
@@ -19,8 +19,8 @@ export type PendingPermissionState = PermissionRequest & {
|
|
|
19
19
|
/**
|
|
20
20
|
* Epoch ms when the prompt first appeared. Keystrokes that arrive within
|
|
21
21
|
* APPROVAL_INPUT_DEBOUNCE_MS of this are swallowed (not interpreted as an
|
|
22
|
-
* approve/deny response) so text typed ahead
|
|
23
|
-
* prompt
|
|
22
|
+
* approve/deny response) so text typed ahead, before the user saw the
|
|
23
|
+
* prompt, cannot accidentally answer it.
|
|
24
24
|
*/
|
|
25
25
|
openedAt?: number;
|
|
26
26
|
/** Requester attribution ("session abc12345" / a named agent) shown on the prompt; absent when unknown. */
|
|
@@ -99,7 +99,7 @@ export function handleBlockingShellInput(
|
|
|
99
99
|
|
|
100
100
|
// Typed-reply mode: deny-with-reason (started by typing on any card) or
|
|
101
101
|
// exec-answer (an exec-prompt ask opens in this mode). Every printable
|
|
102
|
-
// key is text here
|
|
102
|
+
// key is text here, nothing is a card command.
|
|
103
103
|
if (req.replyMode) {
|
|
104
104
|
const buffer = req.replyBuffer ?? '';
|
|
105
105
|
if (data === '\r' || data === '\n') {
|
|
@@ -109,7 +109,7 @@ export function handleBlockingShellInput(
|
|
|
109
109
|
req.resolve(true, false, { answer: buffer });
|
|
110
110
|
} else {
|
|
111
111
|
// Deny is feedback: the reason rides the structured "user declined"
|
|
112
|
-
// tool result so the model can adapt
|
|
112
|
+
// tool result so the model can adapt, the turn is NOT aborted.
|
|
113
113
|
req.resolve(false, false, undefined, { reason: buffer });
|
|
114
114
|
}
|
|
115
115
|
render();
|
|
@@ -143,8 +143,8 @@ export function handleBlockingShellInput(
|
|
|
143
143
|
return { handled: true, pendingPermission };
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
// Scroll, mouse, PageUp/Down, arrow, and panel-navigation keys
|
|
147
|
-
// bare Esc
|
|
146
|
+
// Scroll, mouse, PageUp/Down, arrow, and panel-navigation keys, plus a
|
|
147
|
+
// bare Esc, are not card answers. Pass them through to the normal input
|
|
148
148
|
// handler so the transcript stays scrollable and Esc only drops focus. The
|
|
149
149
|
// request stays pending (answer it with y/n or a remember tier when ready);
|
|
150
150
|
// Ctrl+C above is still the hard abort, and 'n' still denies.
|
|
@@ -161,7 +161,7 @@ export function handleBlockingShellInput(
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
if (key === 'a') {
|
|
164
|
-
// Legacy always-this-session choice
|
|
164
|
+
// Legacy always-this-session choice, the 'session' remember tier.
|
|
165
165
|
req.resolve(true, true, undefined, { rememberTier: 'session' });
|
|
166
166
|
render();
|
|
167
167
|
return { handled: true, pendingPermission: null };
|
|
@@ -182,7 +182,7 @@ export function handleBlockingShellInput(
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
if (key === 'n') {
|
|
185
|
-
// Plain deny
|
|
185
|
+
// Plain deny, feedback to the model (the SDK renders an honest "user
|
|
186
186
|
// declined" result), never a turn abort. Ctrl+C above is the hard stop;
|
|
187
187
|
// Esc drops focus (handled above) rather than denying.
|
|
188
188
|
req.resolve(false, false);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* happen ONLY when the user explicitly asks (a CLI flag, a slash command, or
|
|
10
10
|
* a prompt), never automatically at bare launch (owner ruling). A live
|
|
11
11
|
* recovery snapshot is now surfaced, never applied, by the boot resume
|
|
12
|
-
* notice
|
|
12
|
+
* notice, see announceResumeState in runtime/resume-notice.ts.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
export interface ErrorAffordanceDeps {
|
|
@@ -24,7 +24,7 @@ export interface ErrorAffordanceDeps {
|
|
|
24
24
|
/**
|
|
25
25
|
* Handle one keypress while the error-retry affordance is active.
|
|
26
26
|
* 'r' retries on the current provider when armed; 'm' opens the model
|
|
27
|
-
* picker
|
|
27
|
+
* picker, also gated on armed, since switching models here only makes
|
|
28
28
|
* sense in service of the same retry this affordance is offering, not as a
|
|
29
29
|
* general-purpose model-picker shortcut. Returns true when the key was
|
|
30
30
|
* consumed; any other key (or 'm'/'r' while unarmed) returns false so the
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* retry-affordance.ts
|
|
2
|
+
* retry-affordance.ts, the one-key retry/switch-model affordance shown
|
|
3
3
|
* right after a user-visible TURN_ERROR: 'r' re-submits on the current
|
|
4
4
|
* provider, 'm' opens the model picker, any other key disarms it silently.
|
|
5
5
|
*
|
|
6
6
|
* Rendered as a transient FOOTER status line (see retryAffordanceHint,
|
|
7
7
|
* wired into ShellFooterBuildOptions.retryHint in shell-surface.ts) rather
|
|
8
|
-
* than a permanent transcript message
|
|
8
|
+
* than a permanent transcript message, it disappears the moment it's
|
|
9
9
|
* disarmed, instead of sitting in the scrollback claiming an affordance
|
|
10
10
|
* that no longer does anything. Extracted from main.ts to keep the
|
|
11
11
|
* entrypoint under the architecture line cap.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* The affordance is also time-bounded: arming starts a disarm timer so a
|
|
14
14
|
* stray 'r' hours later can never fire a real, paid retry against the
|
|
15
15
|
* provider. The timer's window is exactly what the footer hint's visibility
|
|
16
|
-
* implies
|
|
16
|
+
* implies, when it fires, the state disarms AND retryAffordanceHint(state)
|
|
17
17
|
* goes back to null in the same tick, so the key dies at the same moment
|
|
18
18
|
* the hint disappears.
|
|
19
19
|
*/
|
|
@@ -37,7 +37,7 @@ export interface RetryAffordanceState {
|
|
|
37
37
|
exhausted: boolean;
|
|
38
38
|
/** Internal: the pending disarm timer's handle, or null while unarmed. */
|
|
39
39
|
timer: ReturnType<typeof setTimeout> | null;
|
|
40
|
-
/** Internal: injected timer primitives
|
|
40
|
+
/** Internal: injected timer primitives, real setTimeout/clearTimeout in production. */
|
|
41
41
|
readonly schedule: RetryAffordanceSchedule;
|
|
42
42
|
/** Internal: the disarm window in ms. */
|
|
43
43
|
readonly windowMs: number;
|
|
@@ -50,7 +50,7 @@ export interface CreateRetryAffordanceStateOptions {
|
|
|
50
50
|
readonly windowMs?: number;
|
|
51
51
|
/** Overridable for tests so the disarm timer doesn't require a real 60s wait. */
|
|
52
52
|
readonly schedule?: RetryAffordanceSchedule;
|
|
53
|
-
/** Called once the window elapses with no keypress and the state has been disarmed
|
|
53
|
+
/** Called once the window elapses with no keypress and the state has been disarmed, main.ts hooks this to its render loop so the footer hint clears the instant the key goes dead. */
|
|
54
54
|
readonly onExpire?: () => void;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -72,7 +72,7 @@ function clearPendingTimer(state: RetryAffordanceState): void {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
/** Arm the affordance
|
|
75
|
+
/** Arm the affordance, call only when a retry is actually possible (a live retryCtx).
|
|
76
76
|
* Starts (or restarts, if already armed) the disarm timer. */
|
|
77
77
|
export function armRetryAffordance(state: RetryAffordanceState, exhausted: boolean): void {
|
|
78
78
|
clearPendingTimer(state);
|
|
@@ -83,13 +83,13 @@ export function armRetryAffordance(state: RetryAffordanceState, exhausted: boole
|
|
|
83
83
|
state.armed = false;
|
|
84
84
|
state.onExpire?.();
|
|
85
85
|
}, state.windowMs);
|
|
86
|
-
// Never let this timer hold the process open
|
|
86
|
+
// Never let this timer hold the process open, a background retry-window
|
|
87
87
|
// countdown is not a reason to keep the event loop alive.
|
|
88
88
|
(timer as unknown as { unref?: () => void }).unref?.();
|
|
89
89
|
state.timer = timer;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
/** Disarm the affordance
|
|
92
|
+
/** Disarm the affordance, any key other than the ones it recognizes disarms it,
|
|
93
93
|
* and cancels the pending disarm timer so it never fires on a state that's
|
|
94
94
|
* already been reset (or re-armed by a subsequent error). */
|
|
95
95
|
export function disarmRetryAffordance(state: RetryAffordanceState): void {
|
|
@@ -106,7 +106,7 @@ export function retryAffordanceHint(state: RetryAffordanceState): string | null
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/** Arm the affordance whenever a user-visible error surfaces AND a retry is
|
|
109
|
-
* actually possible
|
|
109
|
+
* actually possible, wired here (not inline in main.ts) to keep the
|
|
110
110
|
* entrypoint under the architecture line cap. */
|
|
111
111
|
export function wireRetryAffordanceOnError(
|
|
112
112
|
onErrorSurfaced: (cb: (exhausted: boolean) => void) => void,
|