@pellux/goodvibes-tui 2.0.13 → 2.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.goodvibes/GOODVIBES.md +1 -1
- package/.goodvibes/agents/reviewer.md +8 -8
- package/.goodvibes/skills/add-provider/SKILL.md +22 -22
- package/CHANGELOG.md +61 -0
- package/README.md +40 -29
- package/docs/README.md +1 -1
- package/docs/foundation-artifacts/README.md +5 -5
- package/docs/foundation-artifacts/operator-contract.json +123 -123
- package/package.json +12 -10
- package/scripts/postinstall.js +3 -3
- package/src/audio/activation-sound.ts +7 -7
- package/src/audio/capture.ts +7 -7
- package/src/audio/onnxruntime-assets.d.ts +1 -1
- package/src/audio/player.ts +4 -4
- package/src/audio/spoken-turn-wiring.ts +4 -4
- package/src/audio/voice-capture-wiring.ts +5 -5
- package/src/audio/voice-input-session.ts +3 -3
- package/src/audio/wake-inference.ts +13 -8
- package/src/audio/wake-runtime.ts +10 -10
- package/src/cli/completions/generate.ts +2 -2
- package/src/cli/doctor.ts +13 -13
- package/src/cli/ensure-goodvibes-gitignore.ts +3 -3
- package/src/cli/entrypoint.ts +3 -3
- package/src/cli/help.ts +6 -6
- package/src/cli/hooks-command.ts +4 -4
- package/src/cli/hooks-report.ts +4 -4
- package/src/cli/launch-auto-update.ts +17 -17
- package/src/cli/management-commands.ts +8 -8
- package/src/cli/management-utils.ts +3 -3
- package/src/cli/management.ts +1 -1
- package/src/cli/plugin-bundles-command.ts +10 -10
- package/src/cli/plugin-command.ts +9 -9
- package/src/cli/service-posture.ts +1 -1
- package/src/cli/status.ts +10 -10
- package/src/cli/surface-command.ts +4 -4
- package/src/cli/tui-startup.ts +23 -23
- package/src/config/run-daemon-config-migration.ts +3 -3
- package/src/config/secret-config.ts +10 -10
- package/src/config/surface.ts +1 -1
- package/src/config/tui-extension-settings.ts +8 -8
- package/src/core/active-model-identity.ts +7 -7
- package/src/core/approval-alert.ts +5 -5
- package/src/core/bookmark-navigation.ts +3 -3
- package/src/core/budget-breach-notifier.ts +6 -6
- package/src/core/compaction-receipt.ts +8 -8
- package/src/core/composer-state.ts +2 -2
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-event-navigation.ts +2 -2
- package/src/core/conversation-fold.ts +9 -9
- package/src/core/conversation-line-cache.ts +14 -14
- package/src/core/conversation-render-context.ts +6 -6
- package/src/core/conversation-rendering.ts +27 -30
- package/src/core/conversation-search-expansion.ts +6 -6
- package/src/core/conversation-splash-state.ts +3 -3
- package/src/core/conversation-turn-structure.ts +13 -13
- package/src/core/conversation-types.ts +3 -3
- package/src/core/conversation-user-receipts.ts +5 -5
- package/src/core/conversation.ts +17 -17
- package/src/core/format-user-error.ts +5 -5
- package/src/core/long-task-notifier.ts +9 -9
- package/src/core/memory-diagnostics-gateway.ts +8 -8
- package/src/core/memory-provenance.ts +5 -5
- package/src/core/model-routing-chip.ts +3 -3
- package/src/core/pairing-tailscale-gateway.ts +3 -3
- package/src/core/permission-mode.ts +5 -5
- package/src/core/power-chip-source.ts +3 -3
- package/src/core/power-status.ts +8 -8
- package/src/core/rewind-receipt.ts +6 -6
- package/src/core/session-resume-core.ts +8 -8
- package/src/core/stream-event-wiring.ts +36 -36
- package/src/core/stream-stall-watchdog.ts +4 -4
- package/src/core/system-message-noise.ts +7 -7
- package/src/core/system-message-router.ts +10 -10
- package/src/core/terminal-notifier.ts +5 -5
- package/src/core/turn-budget-outcome.ts +5 -5
- package/src/core/turn-cancellation.ts +3 -3
- package/src/core/turn-event-wiring.ts +16 -16
- package/src/core/voice-capture-status.ts +2 -2
- package/src/core/voice-provision-gateway.ts +12 -12
- package/src/core/voice-provision-status.ts +19 -19
- package/src/core/voice-stt-gateway.ts +6 -6
- package/src/core/wake-provision-runner.ts +7 -7
- package/src/core/wake-provision-status.ts +17 -17
- package/src/core/workstream-notification.ts +8 -8
- package/src/export/gist-uploader.ts +7 -7
- package/src/input/autocomplete.ts +3 -3
- package/src/input/bookmark-modal.ts +1 -1
- package/src/input/command-args-hint.ts +2 -2
- package/src/input/command-reference.ts +9 -9
- package/src/input/command-registry.ts +32 -32
- package/src/input/commands/acp-runtime.ts +6 -6
- package/src/input/commands/calendar-runtime.ts +9 -9
- package/src/input/commands/channel-pairing.ts +11 -11
- package/src/input/commands/channel-runtime.ts +1 -1
- package/src/input/commands/checkin-runtime.ts +4 -4
- package/src/input/commands/checkpoint-runtime.ts +4 -4
- package/src/input/commands/ci-runtime.ts +4 -4
- package/src/input/commands/cluster-runtime.ts +3 -3
- package/src/input/commands/codebase-runtime.ts +16 -16
- package/src/input/commands/config.ts +6 -6
- package/src/input/commands/connection-status.ts +12 -12
- package/src/input/commands/context-window.ts +2 -2
- package/src/input/commands/cost-attribution-format.ts +4 -4
- package/src/input/commands/cost-runtime.ts +2 -2
- package/src/input/commands/devices-runtime.ts +7 -7
- package/src/input/commands/diff-runtime.ts +2 -2
- package/src/input/commands/editor-runtime.ts +1 -1
- package/src/input/commands/eval.ts +4 -4
- package/src/input/commands/experience-runtime.ts +1 -1
- package/src/input/commands/git-runtime.ts +3 -3
- package/src/input/commands/graph-runtime.ts +3 -3
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-metrics-format.ts +2 -2
- package/src/input/commands/health-runtime.ts +8 -8
- package/src/input/commands/hosted-runtime.ts +13 -13
- package/src/input/commands/image-runtime.ts +6 -6
- package/src/input/commands/intelligence-runtime.ts +2 -2
- package/src/input/commands/local-auth-runtime.ts +3 -3
- package/src/input/commands/local-provider-runtime.ts +3 -3
- package/src/input/commands/local-runtime.ts +7 -7
- package/src/input/commands/mail-runtime.ts +9 -9
- package/src/input/commands/mcp-runtime.ts +1 -1
- package/src/input/commands/memory.ts +13 -13
- package/src/input/commands/notify-runtime.ts +1 -1
- package/src/input/commands/operator-panel-runtime.ts +8 -8
- package/src/input/commands/operator-rpc.ts +3 -3
- package/src/input/commands/operator-runtime.ts +3 -3
- package/src/input/commands/palette-runtime.ts +1 -1
- package/src/input/commands/payment-card-intake.ts +17 -17
- package/src/input/commands/permissions-provenance.ts +7 -7
- package/src/input/commands/permissions-runtime.ts +1 -1
- package/src/input/commands/planning-runtime.ts +9 -9
- package/src/input/commands/platform-services-runtime.ts +2 -2
- package/src/input/commands/policy-dispatch.ts +6 -6
- package/src/input/commands/power-runtime.ts +6 -6
- package/src/input/commands/principals-runtime.ts +3 -3
- package/src/input/commands/product-runtime.ts +3 -3
- package/src/input/commands/profile-render.ts +13 -13
- package/src/input/commands/profile-runtime.ts +13 -13
- package/src/input/commands/profile-types.ts +13 -13
- package/src/input/commands/provider-accounts-runtime.ts +5 -5
- package/src/input/commands/provider.ts +10 -10
- package/src/input/commands/qrcode-runtime.ts +3 -3
- package/src/input/commands/queue-runtime.ts +6 -6
- package/src/input/commands/recall-files-config.ts +4 -4
- package/src/input/commands/recall-files-git.ts +3 -3
- package/src/input/commands/recall-files.ts +12 -12
- package/src/input/commands/recall-query.ts +3 -3
- package/src/input/commands/recall-review.ts +3 -3
- package/src/input/commands/recall-shared.ts +1 -1
- package/src/input/commands/relay-runtime.ts +5 -5
- package/src/input/commands/remote-runtime.ts +3 -3
- package/src/input/commands/review-runtime.ts +8 -8
- package/src/input/commands/rewind-runtime.ts +21 -21
- package/src/input/commands/runtime-services.ts +1 -2
- package/src/input/commands/schedule-nl.ts +2 -2
- package/src/input/commands/schedule-runtime.ts +2 -2
- package/src/input/commands/secret-runtime.ts +3 -3
- package/src/input/commands/session-content.ts +7 -7
- package/src/input/commands/session-picker-filter.ts +3 -3
- package/src/input/commands/session-workflow.ts +10 -10
- package/src/input/commands/session.ts +15 -15
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/share-runtime.ts +4 -4
- package/src/input/commands/shell-core.ts +11 -11
- package/src/input/commands/tasks-runtime.ts +4 -4
- package/src/input/commands/test-runtime.ts +6 -6
- package/src/input/commands/tts-runtime.ts +4 -4
- package/src/input/commands/update-runtime.ts +27 -27
- package/src/input/commands/websearch-runtime.ts +2 -2
- package/src/input/commands/work-plan-runtime.ts +2 -2
- package/src/input/commands/workstream-attempt-dependents.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +16 -16
- package/src/input/commands/workstream-runtime.ts +36 -36
- package/src/input/commands/worktree-runtime.ts +6 -6
- package/src/input/composer-capture.ts +5 -5
- package/src/input/concealed-input.ts +2 -2
- package/src/input/config-modal-types.ts +16 -16
- package/src/input/config-modal.ts +30 -30
- package/src/input/daemon-owned-settings-descriptions.ts +4 -4
- package/src/input/delete-key-policy.ts +1 -1
- package/src/input/exec-env-scrub-config.ts +7 -7
- package/src/input/feature-unit-layout.ts +5 -5
- package/src/input/feed-context-factory.ts +38 -38
- package/src/input/file-picker.ts +1 -1
- package/src/input/handler-command-route.ts +2 -2
- package/src/input/handler-content-actions.ts +8 -8
- package/src/input/handler-feed-routes.ts +13 -13
- package/src/input/handler-feed.ts +31 -31
- package/src/input/handler-interactions.ts +2 -2
- package/src/input/handler-modal-routes.ts +13 -13
- package/src/input/handler-modal-stack.ts +1 -1
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-onboarding-daemon-adopt.ts +6 -6
- package/src/input/handler-picker-routes.ts +7 -7
- package/src/input/handler-prompt-buffer.ts +1 -1
- package/src/input/handler-shortcuts.ts +12 -12
- package/src/input/handler-types.ts +3 -3
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +9 -9
- package/src/input/input-history.ts +1 -1
- package/src/input/keybindings.ts +13 -13
- package/src/input/kill-ring.ts +7 -11
- package/src/input/model-picker-filter.ts +3 -3
- package/src/input/model-picker-items.ts +5 -5
- package/src/input/model-picker-types.ts +2 -2
- package/src/input/model-picker.ts +18 -18
- package/src/input/onboarding/onboarding-feature-units.ts +9 -13
- package/src/input/onboarding/onboarding-provider-key-fields.ts +3 -3
- package/src/input/onboarding/onboarding-runtime-status.ts +3 -3
- package/src/input/onboarding/onboarding-wizard-apply.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +4 -4
- package/src/input/onboarding/onboarding-wizard-network-adopt.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-steps.ts +2 -2
- package/src/input/panel-integration-actions.ts +3 -3
- package/src/input/panel-mouse-geometry.ts +1 -1
- package/src/input/panel-paste-flood-guard.ts +9 -9
- package/src/input/payments-config.ts +15 -15
- package/src/input/profile-picker-modal.ts +1 -1
- package/src/input/provider-key-intake.ts +9 -9
- package/src/input/relay-settings-descriptions.ts +3 -3
- package/src/input/sandbox-exec-config.ts +9 -9
- package/src/input/search.ts +18 -18
- package/src/input/selection-modal-queue.ts +10 -10
- package/src/input/selection-modal.ts +2 -2
- package/src/input/session-picker-modal.ts +7 -7
- package/src/input/settings-modal-activation.ts +1 -1
- package/src/input/settings-modal-adjustment.ts +2 -2
- package/src/input/settings-modal-commit.ts +6 -6
- package/src/input/settings-modal-connections.ts +2 -2
- package/src/input/settings-modal-data.ts +29 -29
- package/src/input/settings-modal-mutations.ts +7 -7
- package/src/input/settings-modal-reset.ts +3 -3
- package/src/input/settings-modal-search.ts +6 -6
- package/src/input/settings-modal-secrets.ts +3 -3
- package/src/input/settings-modal-types.ts +16 -16
- package/src/input/settings-modal.ts +4 -4
- package/src/input/voice-local-settings.ts +3 -3
- package/src/input/worktree-setup-config.ts +8 -8
- package/src/main.ts +15 -15
- package/src/panels/agent-inspector-shared.ts +5 -5
- package/src/panels/base-panel.ts +3 -3
- package/src/panels/builtin/agent.ts +3 -3
- package/src/panels/builtin/development.ts +4 -4
- package/src/panels/builtin/knowledge.ts +1 -1
- package/src/panels/builtin/operations.ts +12 -12
- package/src/panels/builtin/session.ts +8 -8
- package/src/panels/builtin/shared.ts +6 -6
- package/src/panels/builtin-modals.ts +8 -8
- package/src/panels/confirm-state.ts +5 -5
- package/src/panels/cost-tracker-panel.ts +22 -22
- package/src/panels/diff-panel.ts +20 -20
- package/src/panels/diff-review-model.ts +5 -5
- package/src/panels/diff-review-panel.ts +5 -5
- package/src/panels/eval-registry.ts +2 -2
- package/src/panels/expandable-list-panel.ts +5 -5
- package/src/panels/fleet-acts.ts +20 -20
- package/src/panels/fleet-deep-link.ts +5 -5
- package/src/panels/fleet-gateway.ts +12 -12
- package/src/panels/fleet-observed-render.ts +11 -11
- package/src/panels/fleet-panel-format.ts +14 -14
- package/src/panels/fleet-panel-worktree-detail.ts +8 -8
- package/src/panels/fleet-panel.ts +34 -34
- package/src/panels/fleet-read-model.ts +49 -49
- package/src/panels/fleet-spawn.ts +15 -15
- package/src/panels/fleet-steer.ts +7 -7
- package/src/panels/fleet-stop.ts +5 -5
- package/src/panels/fleet-tabs.ts +14 -14
- package/src/panels/fleet-transcript.ts +26 -26
- package/src/panels/git-panel.ts +8 -8
- package/src/panels/hosted-session-feed.ts +13 -13
- package/src/panels/hosted-session-panel.ts +7 -7
- package/src/panels/index.ts +1 -1
- package/src/panels/local-auth-panel.ts +15 -15
- package/src/panels/memory-consolidation-gateway.ts +8 -8
- package/src/panels/modals/devices-modal.ts +8 -8
- package/src/panels/modals/hooks-modal.ts +1 -1
- package/src/panels/modals/keybindings-modal.ts +5 -5
- package/src/panels/modals/knowledge-modal.ts +2 -2
- package/src/panels/modals/local-auth-modal.ts +4 -4
- package/src/panels/modals/marketplace-modal.ts +3 -3
- package/src/panels/modals/memory-modal.ts +19 -19
- package/src/panels/modals/modal-surface-helpers.ts +1 -1
- package/src/panels/modals/modal-theme.ts +3 -3
- package/src/panels/modals/pairing-modal.ts +19 -19
- package/src/panels/modals/planning-modal.ts +4 -4
- package/src/panels/modals/plugins-modal.ts +1 -1
- package/src/panels/modals/policy-modal.ts +4 -4
- package/src/panels/modals/provider-health-modal.ts +1 -1
- package/src/panels/modals/remote-modal.ts +1 -1
- package/src/panels/modals/sandbox-modal.ts +2 -2
- package/src/panels/modals/security-modal.ts +4 -4
- package/src/panels/modals/services-modal.ts +1 -1
- package/src/panels/modals/work-plan-modal.ts +4 -4
- package/src/panels/notifications-feed.ts +6 -6
- package/src/panels/notifications-panel.ts +6 -6
- package/src/panels/panel-confirm-overlay.ts +4 -4
- package/src/panels/panel-manager.ts +13 -13
- package/src/panels/plugins-panel.ts +6 -6
- package/src/panels/polish-core.ts +2 -2
- package/src/panels/polish-tables.ts +2 -2
- package/src/panels/polish.ts +1 -1
- package/src/panels/project-planning-answer-actions.ts +3 -3
- package/src/panels/scrollable-list-panel.ts +15 -15
- package/src/panels/search-focus.ts +1 -1
- package/src/panels/session-maintenance.ts +1 -1
- package/src/panels/skills-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +11 -11
- package/src/panels/types.ts +14 -14
- package/src/panels/workstream-graph-render.ts +5 -5
- package/src/panels/wrfc-panel-format.ts +1 -1
- package/src/permissions/broker-approval-card.ts +13 -13
- package/src/permissions/hunk-selection.ts +13 -13
- package/src/permissions/prompt.ts +22 -22
- package/src/permissions/sandbox-exec-gate.ts +5 -5
- package/src/providers/provider-classification.ts +1 -1
- package/src/providers/reasoning-effort-surface.ts +12 -12
- package/src/renderer/ansi-sanitize.ts +5 -6
- package/src/renderer/autocomplete-overlay.ts +5 -5
- package/src/renderer/block-actions-overlay.ts +1 -1
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/code-block.ts +2 -2
- package/src/renderer/compaction-history-modal.ts +4 -4
- package/src/renderer/compaction-preview.ts +5 -5
- package/src/renderer/compaction-quality.ts +5 -5
- package/src/renderer/composer-fragments.ts +6 -6
- package/src/renderer/compositor.ts +9 -9
- package/src/renderer/config-modal.ts +3 -3
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/context-status-hint.ts +10 -10
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +2 -2
- package/src/renderer/conversation-surface.ts +6 -6
- package/src/renderer/diff.ts +4 -4
- package/src/renderer/fleet-tab-strip.ts +2 -2
- package/src/renderer/footer-tips.ts +4 -4
- package/src/renderer/fullscreen-primitives.ts +1 -1
- package/src/renderer/git-status.ts +5 -5
- package/src/renderer/header-line.ts +5 -5
- package/src/renderer/help-overlay.ts +5 -5
- package/src/renderer/hint-grammar.ts +2 -2
- package/src/renderer/layout.ts +1 -1
- package/src/renderer/markdown-inline.ts +3 -3
- package/src/renderer/markdown-table.ts +7 -7
- package/src/renderer/modal-factory.ts +3 -3
- package/src/renderer/model-picker-overlay.ts +2 -2
- package/src/renderer/model-workspace.ts +7 -7
- package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
- package/src/renderer/overlay-box.ts +1 -1
- package/src/renderer/panel-composite.ts +5 -5
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +8 -8
- package/src/renderer/profile-picker-modal.ts +3 -3
- package/src/renderer/prompt-content-width.ts +1 -1
- package/src/renderer/search-overlay.ts +3 -3
- package/src/renderer/selection-modal-overlay.ts +6 -6
- package/src/renderer/semantic-diff.ts +6 -7
- package/src/renderer/session-picker-modal.ts +24 -24
- package/src/renderer/settings-modal-connections.ts +3 -3
- package/src/renderer/settings-modal-helpers.ts +16 -16
- package/src/renderer/settings-modal.ts +10 -10
- package/src/renderer/shell-surface.ts +8 -8
- package/src/renderer/status-glyphs.ts +6 -6
- package/src/renderer/syntax-highlighter.ts +2 -3
- package/src/renderer/system-message.ts +3 -3
- package/src/renderer/tab-strip.ts +2 -2
- package/src/renderer/term-caps.ts +12 -12
- package/src/renderer/terminal-bg-probe.ts +10 -10
- package/src/renderer/terminal-escapes.ts +1 -1
- package/src/renderer/theme-mode-config.ts +3 -3
- package/src/renderer/theme.ts +34 -34
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +5 -5
- package/src/renderer/tool-result-expanded-lines.ts +3 -3
- package/src/renderer/tool-result-summary.ts +6 -6
- package/src/renderer/turn-injection.ts +9 -9
- package/src/renderer/ui-factory.ts +33 -33
- package/src/renderer/ui-primitives.ts +4 -4
- package/src/runtime/bootstrap-command-parts.ts +3 -3
- package/src/runtime/bootstrap-core.ts +21 -21
- package/src/runtime/bootstrap-hook-bridge.ts +8 -8
- package/src/runtime/bootstrap-shell.ts +9 -9
- package/src/runtime/bootstrap.ts +16 -16
- package/src/runtime/client/approval-updates.ts +3 -3
- package/src/runtime/client/build-floors.ts +7 -7
- package/src/runtime/client/daemon-attach-handshake.ts +5 -5
- package/src/runtime/client/fleet-union.ts +7 -7
- package/src/runtime/client/host-service-status.ts +2 -2
- package/src/runtime/client/hosted-exit.ts +4 -4
- package/src/runtime/client/hosted-roster.ts +4 -4
- package/src/runtime/client/hosted-session-stream.ts +5 -5
- package/src/runtime/client/hosted-sessions.ts +8 -8
- package/src/runtime/client/operator-endpoint.ts +14 -14
- package/src/runtime/client/spine-adoption.ts +8 -8
- package/src/runtime/context-accounting-source.ts +4 -4
- package/src/runtime/context.ts +2 -2
- package/src/runtime/conversation-rewind-port.ts +6 -6
- package/src/runtime/credential-composition.ts +2 -2
- package/src/runtime/daemon-attach-notices.ts +6 -6
- package/src/runtime/diagnostics/panels/index.ts +1 -1
- package/src/runtime/diagnostics/panels/ops.ts +2 -2
- package/src/runtime/disposal-wiring.ts +6 -6
- package/src/runtime/index.ts +11 -11
- package/src/runtime/install-self-check-startup.ts +4 -4
- package/src/runtime/install-self-check.ts +6 -6
- package/src/runtime/interaction-seams.ts +4 -4
- package/src/runtime/knowledge-services.ts +2 -2
- package/src/runtime/legacy-daemon-migration.ts +37 -37
- package/src/runtime/legacy-daemon-reconcile.ts +30 -30
- package/src/runtime/memory-governance-services.ts +3 -3
- package/src/runtime/memory-spine-transport.ts +3 -3
- package/src/runtime/notification-dispatch.ts +4 -4
- package/src/runtime/onboarding/apply.ts +1 -1
- package/src/runtime/onboarding/derivation.ts +1 -1
- package/src/runtime/onboarding/fast-path.ts +7 -7
- package/src/runtime/onboarding/progress.ts +2 -2
- package/src/runtime/onboarding/provider-key-capture.ts +4 -4
- package/src/runtime/onboarding/snapshot.ts +2 -2
- package/src/runtime/onboarding/state.ts +4 -4
- package/src/runtime/onboarding/types.ts +4 -4
- package/src/runtime/orchestrator-core-services.ts +5 -5
- package/src/runtime/path-shadow-startup.ts +3 -3
- package/src/runtime/perf/panel-contracts.ts +1 -1
- package/src/runtime/power-keepawake-remote.ts +6 -6
- package/src/runtime/process-lifecycle.ts +14 -14
- package/src/runtime/provider-fallback.ts +3 -3
- package/src/runtime/recovery-autosave.ts +3 -3
- package/src/runtime/recovery-decisions.ts +19 -19
- package/src/runtime/recovery-offer-wiring.ts +4 -4
- package/src/runtime/recovery-prompt.ts +20 -20
- package/src/runtime/relay-reachability-bridge.ts +3 -3
- package/src/runtime/release-artifacts.ts +1 -1
- package/src/runtime/resume-notice.ts +20 -20
- package/src/runtime/runtime-services-types.ts +20 -20
- package/src/runtime/services.ts +20 -20
- package/src/runtime/session-continuity-hints.ts +1 -1
- package/src/runtime/session-inbound-inputs.ts +12 -12
- package/src/runtime/session-resume-liveness-confirm.ts +4 -4
- package/src/runtime/session-spine-transport.ts +3 -3
- package/src/runtime/store/domains/panels.ts +2 -2
- package/src/runtime/store/domains/ui-perf.ts +2 -2
- package/src/runtime/store/index.ts +1 -1
- package/src/runtime/store/selectors/index.ts +1 -1
- package/src/runtime/store/state.ts +2 -2
- package/src/runtime/ui-services.ts +3 -3
- package/src/runtime/workspace-checkpointing.ts +3 -3
- package/src/runtime/wrfc-persistence.ts +15 -15
- package/src/scripts/process-messages.ts +1 -1
- package/src/shell/blocking-input.ts +9 -9
- package/src/shell/recovery-input-helpers.ts +2 -2
- package/src/shell/retry-affordance.ts +9 -9
- package/src/shell/ui-openers.ts +14 -14
- package/src/shell/voice-capture-shell.ts +3 -3
- package/src/tools/wrfc-agent-guard.ts +4 -4
- package/src/utils/browser.ts +2 -2
- package/src/utils/format-duration.ts +3 -3
- package/src/utils/format-number.ts +2 -2
- package/src/utils/splash-lines.ts +4 -4
- package/src/utils/terminal-width.ts +6 -6
- package/src/verification/verification-ledger.ts +25 -25
- package/src/version.ts +3 -3
package/src/runtime/bootstrap.ts
CHANGED
|
@@ -94,7 +94,7 @@ export type BootstrapContext = RuntimeContext & {
|
|
|
94
94
|
lastGitInfoRef: { value: GitHeaderInfo | undefined };
|
|
95
95
|
/** Unsubscribe functions owned by bootstrap (cleared on shutdown). */
|
|
96
96
|
bootstrapUnsubs: Array<() => void>;
|
|
97
|
-
/** Ref holding the periodic agent-status interval (use ref
|
|
97
|
+
/** Ref holding the periodic agent-status interval (use ref, not local var, to keep shutdown in sync). */
|
|
98
98
|
agentStatusIntervalRef: { value: ReturnType<typeof setInterval> | null };
|
|
99
99
|
/** Mutable refs for viewport/scroll/render functions; main.ts patches these after constructing UI state. */
|
|
100
100
|
orchestratorRefs: { getViewportHeight: () => number; scrollToEnd: (vHeight: number) => void; requestRender: () => void };
|
|
@@ -198,7 +198,7 @@ export async function bootstrapRuntime(
|
|
|
198
198
|
panelManager,
|
|
199
199
|
pluginManager,
|
|
200
200
|
} = services;
|
|
201
|
-
// A saved custom-provider model must never crash boot
|
|
201
|
+
// A saved custom-provider model must never crash boot, see provider-fallback.ts.
|
|
202
202
|
await ensureBootModelResolvable(providerRegistry, configManager);
|
|
203
203
|
|
|
204
204
|
// ── Phase 6: Orchestrator + AcpManager ───────────────────────────────────
|
|
@@ -241,7 +241,7 @@ export async function bootstrapRuntime(
|
|
|
241
241
|
logger.debug('companion handleUserInput safety catch', { error: String(err) });
|
|
242
242
|
});
|
|
243
243
|
};
|
|
244
|
-
// Shared payload (single source of truth, includes the memoryRegistry
|
|
244
|
+
// Shared payload (single source of truth, includes the memoryRegistry,
|
|
245
245
|
// see orchestrator-core-services.ts) plus this site's cacheHitTracker.
|
|
246
246
|
orchestrator.setCoreServices({
|
|
247
247
|
...buildSharedOrchestratorCoreServices({ services, configManager, providerRegistry }),
|
|
@@ -311,7 +311,7 @@ export async function bootstrapRuntime(
|
|
|
311
311
|
const commandContext = shell.commandContext;
|
|
312
312
|
// Boot resume notice (item 1): after rehydrate() so chain history is ready, before
|
|
313
313
|
// the operator can type anything. Fire-and-forget, same as main.ts's non-blocking
|
|
314
|
-
// `void workspaceCheckpointManager.init().catch(() => {})
|
|
314
|
+
// `void workspaceCheckpointManager.init().catch(() => {})`, local file I/O only,
|
|
315
315
|
// resolves well before a human can react to the first rendered frame.
|
|
316
316
|
void announceResumeState({
|
|
317
317
|
surface: services.surface,
|
|
@@ -321,7 +321,7 @@ export async function bootstrapRuntime(
|
|
|
321
321
|
memoryAvailable: Boolean(commandContext.clients?.knowledgeApi?.memory),
|
|
322
322
|
router: systemMessageRouter,
|
|
323
323
|
}).catch(() => {
|
|
324
|
-
// Best-effort
|
|
324
|
+
// Best-effort, never let the resume notice block or crash boot.
|
|
325
325
|
});
|
|
326
326
|
announceInstallHealth(systemMessageRouter);
|
|
327
327
|
const { gitStatusProvider, inputHistory, lastGitInfoRef } = shell;
|
|
@@ -352,7 +352,7 @@ export async function bootstrapRuntime(
|
|
|
352
352
|
const deferredStartup = createDeferredStartupCoordinator();
|
|
353
353
|
|
|
354
354
|
// Adopting a daemon: session identity, the inbound steer path, the
|
|
355
|
-
// cross-surface union read, and the memory spine
|
|
355
|
+
// cross-surface union read, and the memory spine, see client/spine-adoption.ts.
|
|
356
356
|
const syncSessionSpineToHostStatus = createSpineAdoptionSync({
|
|
357
357
|
sessionSpine,
|
|
358
358
|
memorySpine: services.memorySpine,
|
|
@@ -384,7 +384,7 @@ export async function bootstrapRuntime(
|
|
|
384
384
|
httpListenerPortInUse: hostServiceIsBlocked(httpListenerStatus),
|
|
385
385
|
daemonStatus,
|
|
386
386
|
httpListenerStatus,
|
|
387
|
-
// Honest session-spine posture, independent of daemonRunning
|
|
387
|
+
// Honest session-spine posture, independent of daemonRunning, degrades to 'offline'
|
|
388
388
|
// when adopted-but-unreachable even though daemonRunning might still read a stale
|
|
389
389
|
// handle as true; sessionSpine.status() alone is activity-gated, so it's derived
|
|
390
390
|
// together with the union cache's 5s liveness probe (one signal, no new timer).
|
|
@@ -396,13 +396,13 @@ export async function bootstrapRuntime(
|
|
|
396
396
|
// ADOPT ONLY. This app never constructs a DaemonServer or an HttpListener: the
|
|
397
397
|
// daemon is a separate product with its own binary and its own service unit.
|
|
398
398
|
// The factories carry the shared bearer and the daemon's state directory so an
|
|
399
|
-
// adopted daemon is authenticated the same way it always was
|
|
399
|
+
// adopted daemon is authenticated the same way it always was, no factory that
|
|
400
400
|
// BUILDS anything is passed, and `adoptOnly` makes the SDK refuse to start one
|
|
401
401
|
// even if a future caller did.
|
|
402
402
|
//
|
|
403
403
|
// `daemonRuntimeDir` names the daemon's own STATE directory
|
|
404
404
|
// (`<home>/.goodvibes/daemon`), which is where operator-tokens.json,
|
|
405
|
-
// auth-users.json and daemon-settings.json live
|
|
405
|
+
// auth-users.json and daemon-settings.json live, not the home above it. Every
|
|
406
406
|
// reader in this repository resolves it that way.
|
|
407
407
|
const createExternalServiceFactories = (token: string): ExternalServiceFactories => ({
|
|
408
408
|
sharedDaemonToken: token,
|
|
@@ -458,7 +458,7 @@ export async function bootstrapRuntime(
|
|
|
458
458
|
platformExternalServices.externalServices = {
|
|
459
459
|
// The relay is a DAEMON feature and reading an adopted daemon's relay state
|
|
460
460
|
// is a verb this contract does not carry, so these two report 'unavailable'
|
|
461
|
-
// rather than a state this process is in no position to know
|
|
461
|
+
// rather than a state this process is in no position to know, see
|
|
462
462
|
// relay-reachability-bridge.ts.
|
|
463
463
|
...relayReadAccessors,
|
|
464
464
|
inspect: inspectExternalServices,
|
|
@@ -488,7 +488,7 @@ export async function bootstrapRuntime(
|
|
|
488
488
|
},
|
|
489
489
|
};
|
|
490
490
|
// Attaching to a daemon settles both build floors and its undelivered
|
|
491
|
-
// receipts off one /status read
|
|
491
|
+
// receipts off one /status read, see client/daemon-attach-handshake.ts.
|
|
492
492
|
const daemonHandshake = createDaemonAttachHandshake({
|
|
493
493
|
clientBuildGuard: services.clientBuildGuard,
|
|
494
494
|
readDaemonStatus: () => externalServices.daemonStatus,
|
|
@@ -509,8 +509,8 @@ export async function bootstrapRuntime(
|
|
|
509
509
|
// Plugin loading stays here: a plugin's commands, tools, providers, voice
|
|
510
510
|
// and media providers and embedding providers all reach things a turn
|
|
511
511
|
// needs in THIS process. Three of the eleven registries a plugin can
|
|
512
|
-
// reach are the daemon's now
|
|
513
|
-
// delivery strategies
|
|
512
|
+
// reach are the daemon's now, gateway methods, channel plugins and
|
|
513
|
+
// delivery strategies, and a registration into those reaches nothing
|
|
514
514
|
// from here. No plugin is affected today (none is installed, and this
|
|
515
515
|
// package bundles none); the classification and the open question about
|
|
516
516
|
// where a daemon-side plugin is loaded are recorded in
|
|
@@ -549,7 +549,7 @@ export async function bootstrapRuntime(
|
|
|
549
549
|
const companionTokenRecord = resolveDaemonCompanionToken(daemonHomeDir, GOODVIBES_TUI_SURFACE_ROOT);
|
|
550
550
|
// Fix (TUI 0.19.20): remove stale pre-0.21.28 workspace-scoped operator
|
|
551
551
|
// token files so only the canonical <daemonHomeDir>/operator-tokens.json survives.
|
|
552
|
-
// The prune is best-effort
|
|
552
|
+
// The prune is best-effort, it silently skips missing files, no-ops when tokens
|
|
553
553
|
// already match, and records un-deletable candidates in `failedPaths` for logging.
|
|
554
554
|
// See `pruneStaleOperatorTokens` in the SDK for semantics.
|
|
555
555
|
const prune = pruneStaleOperatorTokens({
|
|
@@ -710,12 +710,12 @@ export async function bootstrapRuntime(
|
|
|
710
710
|
runtimeUnsubs.forEach((fn) => fn());
|
|
711
711
|
runtimeUnsubs.length = 0;
|
|
712
712
|
forensicsCollector.dispose();
|
|
713
|
-
// Honest close on exit
|
|
713
|
+
// Honest close on exit, fire-and-forget (never blocks shutdown);
|
|
714
714
|
// a no-op when the spine was never activated (embedded/local-only topology).
|
|
715
715
|
sessionSpine.close(runtime.sessionId);
|
|
716
716
|
sessionSpine.dispose();
|
|
717
717
|
sessionInboundInputs.dispose(); sessionUnionCache.dispose(); // stop the inbound-steer poll and the wire-refresh interval on exit
|
|
718
|
-
// Quitting has to SAY it is leaving: a hosted session's detach policy applies when the LAST client detaches, so an exit that never detaches leaves a kill-policy session (the shipped default) alive, attached to a process that is gone. Bounded and non-throwing
|
|
718
|
+
// Quitting has to SAY it is leaving: a hosted session's detach policy applies when the LAST client detaches, so an exit that never detaches leaves a kill-policy session (the shipped default) alive, attached to a process that is gone. Bounded and non-throwing, see client/hosted-exit.ts.
|
|
719
719
|
await Promise.all([leaveHostedSessionOnExit({ configManager, homeDirectory: services.homeDirectory }), deferredStartup.drain(100)]);
|
|
720
720
|
if (externalServicesPromise) {
|
|
721
721
|
try {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* approval-updates.ts
|
|
2
|
+
* approval-updates.ts, this terminal's subscription to approval decisions made
|
|
3
3
|
* somewhere else.
|
|
4
4
|
*
|
|
5
5
|
* ── What this replaces ────────────────────────────────────────────────────
|
|
6
6
|
*
|
|
7
7
|
* The SDK's client raiser (approval-raiser.ts) raises an ask on the daemon and
|
|
8
8
|
* prompts locally at the same time, and then has to learn about a decision made
|
|
9
|
-
* on another surface
|
|
9
|
+
* on another surface, a phone, the web UI, a second terminal. Without a push
|
|
10
10
|
* channel wired it learns by RE-READING the record on an interval, which is
|
|
11
11
|
* both slower than it needs to be and the thing the `control.approval_update`
|
|
12
12
|
* event exists to end. Wiring this seam makes a remote decision arrive in the
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* a connection) still has to be able to answer a tool call. `watchApprovalUpdates`
|
|
18
18
|
* reports failure by returning null rather than throwing, and the raiser then
|
|
19
19
|
* behaves exactly as it did before this seam existed. Push is the fast path, not
|
|
20
|
-
* a new dependency
|
|
20
|
+
* a new dependency, and the raiser's own discipline of doing one immediate read
|
|
21
21
|
* after subscribing stays intact, because a decision can land between the raise
|
|
22
22
|
* and the subscription and no push channel can deliver what happened before it
|
|
23
23
|
* opened.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* build-floors.ts
|
|
2
|
+
* build-floors.ts, the two build floors this terminal and the daemon hold
|
|
3
3
|
* against each other.
|
|
4
4
|
*
|
|
5
5
|
* ── Forward: the daemon's floor on this client ────────────────────────────
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* running the build it started with: same rules, same bugs, still registered in
|
|
9
9
|
* the shared session store, still able to execute shared-session work. That is
|
|
10
10
|
* how a behavioral fix can land in the daemon, be verified present in the
|
|
11
|
-
* installed binaries, and still not change what the owner observes
|
|
11
|
+
* installed binaries, and still not change what the owner observes, an older
|
|
12
12
|
* terminal beside the new daemon simply keeps doing the old thing.
|
|
13
13
|
*
|
|
14
14
|
* So the daemon publishes the minimum client build it will let participate, as
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
* to a daemon it did not start, over a base URL that may point at another
|
|
23
23
|
* machine, and every capability it has is something the daemon performs on its
|
|
24
24
|
* behalf. A verb it depends on may simply not exist in the build that answers,
|
|
25
|
-
* and what the owner sees then is a 400 or a 404 on one call
|
|
25
|
+
* and what the owner sees then is a 400 or a 404 on one call, which reads as a
|
|
26
26
|
* broken feature rather than as an old daemon. So this terminal declares the
|
|
27
27
|
* oldest daemon build it can work against and checks it on attach against the
|
|
28
28
|
* `version` `/status` already returns, refusing to adopt a daemon below it.
|
|
29
29
|
*
|
|
30
30
|
* ── Where these rules live ────────────────────────────────────────────────
|
|
31
31
|
*
|
|
32
|
-
* Both comparisons
|
|
33
|
-
|
|
32
|
+
* Both comparisons, the header name, the verdict shapes, the version ordering
|
|
33
|
+
*, are owned by the SDK (platform/control-plane/client-compatibility.ts and
|
|
34
34
|
* daemon-compatibility.ts) and imported below rather than duplicated. What
|
|
35
35
|
* stays here is this process's own state: the forward latch, the reverse
|
|
36
36
|
* announce-once, and the daemon floor this product declares. The agent holds
|
|
@@ -73,7 +73,7 @@ export interface ClientBuildGuardOptions {
|
|
|
73
73
|
* later read that fails to see the header (a restart, a truncated response)
|
|
74
74
|
* must not silently re-enable work.
|
|
75
75
|
*
|
|
76
|
-
* The notice sink is attached after construction
|
|
76
|
+
* The notice sink is attached after construction, this guard is built in the
|
|
77
77
|
* services composition root, and the surface that renders its one line is wired
|
|
78
78
|
* in the bootstrap tail. A verdict reached before the sink attaches is held and
|
|
79
79
|
* delivered on attach, the same buffered-until-attach idiom the daemon receipt
|
|
@@ -134,7 +134,7 @@ export class ClientBuildGuard {
|
|
|
134
134
|
* the problem once instead of on every poll.
|
|
135
135
|
*
|
|
136
136
|
* Unlatched, unlike the forward guard: a daemon CAN become new enough while
|
|
137
|
-
* this terminal runs
|
|
137
|
+
* this terminal runs, that is exactly what a daemon update does, and the
|
|
138
138
|
* attach that sees the newer build must adopt it. What is remembered is only
|
|
139
139
|
* which sentence has already been said.
|
|
140
140
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* daemon-attach-handshake.ts
|
|
2
|
+
* daemon-attach-handshake.ts, attaching to a daemon is a handshake, not a
|
|
3
3
|
* pointer swap.
|
|
4
4
|
*
|
|
5
5
|
* ONE `/status` read carries the three things this terminal has to settle
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* - The DAEMON's own build. Every capability here is something the daemon
|
|
10
10
|
* performs on this terminal's behalf, so a daemon below this build's floor
|
|
11
|
-
* is refused rather than adopted
|
|
11
|
+
* is refused rather than adopted, otherwise a verb it does not serve
|
|
12
12
|
* surfaces as one broken feature instead of as an old daemon, and the
|
|
13
13
|
* terminal keeps running half-working against a peer it has no reason to
|
|
14
14
|
* suspect. Refused means local-only, which is a state this app already
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* and the continuation runner stops taking shared-session work.
|
|
18
18
|
* - Its undelivered receipts (update applied, restarted after a crash,
|
|
19
19
|
* settings migrated), read from `/status?receipts=consume` where delivery is
|
|
20
|
-
* destructive
|
|
20
|
+
* destructive, so the read that consumed them is the read that renders
|
|
21
21
|
* them.
|
|
22
22
|
*
|
|
23
23
|
* Every one of those is decided from the same response, which is why this is
|
|
@@ -37,7 +37,7 @@ import { readExternalDaemonAttach } from '../daemon-attach-notices.ts';
|
|
|
37
37
|
import { ClientBuildGuard, DaemonBuildFloor } from './build-floors.ts';
|
|
38
38
|
|
|
39
39
|
export interface DaemonAttachHandshakeDeps {
|
|
40
|
-
/** The forward floor's latch
|
|
40
|
+
/** The forward floor's latch, fed the floor this daemon announces. */
|
|
41
41
|
readonly clientBuildGuard: ClientBuildGuard;
|
|
42
42
|
/** The daemon this terminal is currently pointed at. Re-read on every attach. */
|
|
43
43
|
readonly readDaemonStatus: () => HostServiceStatus;
|
|
@@ -89,7 +89,7 @@ export function createDaemonAttachHandshake(deps: DaemonAttachHandshakeDeps): Da
|
|
|
89
89
|
authToken: daemonToken,
|
|
90
90
|
consumeReceipts: true,
|
|
91
91
|
});
|
|
92
|
-
// Nothing was read, so nothing is known
|
|
92
|
+
// Nothing was read, so nothing is known, adopt as before and leave a
|
|
93
93
|
// daemon that is not answering to the spine's own reachability handling.
|
|
94
94
|
// Refusing on a failed read would turn one dropped request into a lost
|
|
95
95
|
// mirror.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* fleet-union.ts
|
|
2
|
+
* fleet-union.ts, the Fleet panel shows everything running, not just what this
|
|
3
3
|
* terminal started.
|
|
4
4
|
*
|
|
5
5
|
* ── What moved to the SDK, and what stays here ────────────────────────────
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
* interface (interrupt/resume/kill/steer/archive, subscribe, snapshots) and
|
|
16
16
|
* `buildFleetSnapshot`, the tree-builder + honest cost/token aggregator this
|
|
17
17
|
* repo's Fleet panel renders from. Rebuilding through the SAME builder the
|
|
18
|
-
* local view uses
|
|
18
|
+
* local view uses, rather than summing two halves, is what keeps the
|
|
19
19
|
* rollups, the cost/token totals and the blocked-on-user ordering computed
|
|
20
20
|
* once, over the whole fleet.
|
|
21
21
|
*
|
|
22
22
|
* ── Who wins ──────────────────────────────────────────────────────────────
|
|
23
23
|
*
|
|
24
24
|
* Local rows are AUTHORITATIVE for processes this terminal spawned. They are
|
|
25
|
-
* live
|
|
25
|
+
* live, the registry pushes on every state change, with sub-second latency,
|
|
26
26
|
* and they carry the capabilities that make a row actionable here (interrupt,
|
|
27
27
|
* resume, kill, steer all reach a real child process). The daemon's copy of
|
|
28
28
|
* the same row, arriving over a poll, is necessarily staler; where both
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* ── Acting on a row you do not own ────────────────────────────────────────
|
|
32
32
|
*
|
|
33
33
|
* `interrupt`/`resume`/`kill`/`steer` reach this process's own children. A
|
|
34
|
-
* daemon row has no child here to signal, so those refuse
|
|
34
|
+
* daemon row has no child here to signal, so those refuse, and `steer`,
|
|
35
35
|
* which has a reason channel, says why rather than returning a bare false
|
|
36
36
|
* that reads as "the agent ignored you". The panel's own act surface
|
|
37
37
|
* (fleet-gateway.ts) already drives the daemon's verbs for the acts the
|
|
@@ -56,7 +56,7 @@ export { DEFAULT_FLEET_REFRESH_MS, daemonOnlyFleetActRefusal, mergeFleetNodes, r
|
|
|
56
56
|
export type { DaemonFleetRows, DaemonFleetRowsPoller, DaemonFleetRowsPollerOptions };
|
|
57
57
|
|
|
58
58
|
export interface FleetUnionOptions {
|
|
59
|
-
/** This surface's own live registry view
|
|
59
|
+
/** This surface's own live registry view, authoritative for what it spawned. */
|
|
60
60
|
readonly local: FleetReadModel;
|
|
61
61
|
readonly verbs: DaemonVerbCaller;
|
|
62
62
|
readonly refreshIntervalMs?: number;
|
|
@@ -78,7 +78,7 @@ const SURFACE_LABEL = 'this terminal';
|
|
|
78
78
|
* daemon's rows, over the SDK's poll/merge/refusal policy.
|
|
79
79
|
*
|
|
80
80
|
* Inert until the first poll lands: before then, and whenever the daemon
|
|
81
|
-
* cannot answer, the snapshot is exactly the local one
|
|
81
|
+
* cannot answer, the snapshot is exactly the local one, which is the honest
|
|
82
82
|
* answer, not a degraded one. A daemon that stops answering keeps its LAST
|
|
83
83
|
* known rows rather than dropping them (the poller's own retention), so a
|
|
84
84
|
* momentary blip does not make half the fleet blink out and back.
|
|
@@ -96,7 +96,7 @@ export function createFleetUnionReadModel(options: FleetUnionOptions): FleetUnio
|
|
|
96
96
|
for (const listener of listeners) listener();
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
/** Ids this surface owns right now
|
|
99
|
+
/** Ids this surface owns right now, the set the daemon's copy defers to. */
|
|
100
100
|
const localNodeIds = (snapshot: FleetSnapshot): Set<string> =>
|
|
101
101
|
new Set(snapshot.rows.map((row) => row.node.id));
|
|
102
102
|
const isLocalId = (id: string): boolean => localNodeIds(local.getSnapshot()).has(id);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* host-service-status.ts
|
|
2
|
+
* host-service-status.ts, reading a background service's posture.
|
|
3
3
|
*
|
|
4
4
|
* Three questions the composition root asks about the daemon and the webhook
|
|
5
5
|
* listener, none of which need anything from the composition itself: what URL
|
|
@@ -61,7 +61,7 @@ export function hostServiceIsActive(status: HostServiceStatus): boolean {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* The configured port is held and unusable by this terminal
|
|
64
|
+
* The configured port is held and unusable by this terminal, either by an
|
|
65
65
|
* unverified process ('blocked') or by a GoodVibes daemon this build refused to
|
|
66
66
|
* adopt ('incompatible': a wire-version mismatch, or a daemon below this
|
|
67
67
|
* build's own floor).
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hosted-exit.ts
|
|
2
|
+
* hosted-exit.ts, leaving a hosted session because the terminal is closing.
|
|
3
3
|
*
|
|
4
4
|
* ── Why this exists at all ────────────────────────────────────────────────
|
|
5
5
|
*
|
|
6
6
|
* The detach policy is applied when the LAST attached client detaches. A
|
|
7
7
|
* terminal that simply exits never detaches: the daemon keeps this window in
|
|
8
|
-
* `attachedClients` forever, so a `kill`-policy session
|
|
9
|
-
* and the behavior closing a client has always had
|
|
8
|
+
* `attachedClients` forever, so a `kill`-policy session, the shipped default,
|
|
9
|
+
* and the behavior closing a client has always had, would quietly NOT be
|
|
10
10
|
* killed, and would sit there attached to a process that no longer exists.
|
|
11
11
|
*
|
|
12
12
|
* That is not a cosmetic gap. The owner's ruling is that the capability lands
|
|
@@ -52,7 +52,7 @@ export async function leaveHostedSessionOnExit(
|
|
|
52
52
|
): Promise<'none' | 'detached' | 'failed'> {
|
|
53
53
|
const feed = options.feed ?? getSharedHostedSessionFeed();
|
|
54
54
|
const record = feed.getState().record;
|
|
55
|
-
// Closing the socket is this process's own business and is done either way
|
|
55
|
+
// Closing the socket is this process's own business and is done either way,
|
|
56
56
|
// an already-terminated session has nothing to detach from, but the stream
|
|
57
57
|
// watching it is still open.
|
|
58
58
|
feed.closeStream();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hosted-roster.ts
|
|
2
|
+
* hosted-roster.ts, the last answer the daemon gave about what it is hosting.
|
|
3
3
|
*
|
|
4
4
|
* The session picker is where a person goes to ask "what sessions are there?",
|
|
5
5
|
* and the honest answer includes conversations running inside the
|
|
6
|
-
* daemon
|
|
6
|
+
* daemon, not only this terminal's saved transcripts and the cross-surface
|
|
7
7
|
* union. The picker is a synchronous render over modal state, though, and
|
|
8
8
|
* `sessions.hosted.list` is a round trip. This roster is the seam between them:
|
|
9
9
|
* it holds the last list the daemon answered with, refreshes on demand, and
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* The picker is constructed in the input layer, which has no config manager and
|
|
23
23
|
* no home directory to resolve a daemon from. The composition root
|
|
24
24
|
* (runtime/services.ts) has both and already builds the verb caller, so it binds
|
|
25
|
-
* the client here once
|
|
25
|
+
* the client here once, the same shape the shared notification feed uses for a
|
|
26
26
|
* surface that two unrelated layers read.
|
|
27
27
|
*/
|
|
28
28
|
import type { HostedSessionRecord, HostedSessionsClient } from './hosted-sessions.ts';
|
|
@@ -64,7 +64,7 @@ export class HostedSessionRoster {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
* Ask the daemon again. Never throws and never runs twice at once
|
|
67
|
+
* Ask the daemon again. Never throws and never runs twice at once, a picker
|
|
68
68
|
* opened repeatedly must not stack round trips.
|
|
69
69
|
*/
|
|
70
70
|
async refresh(): Promise<void> {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hosted-session-stream.ts
|
|
2
|
+
* hosted-session-stream.ts, watching a conversation that is running somewhere
|
|
3
3
|
* else.
|
|
4
4
|
*
|
|
5
5
|
* A hosted session's loop is the ORDINARY Orchestrator, composed inside the
|
|
6
|
-
* daemon. So it emits exactly what a local turn emits
|
|
7
|
-
* starts, tool results, turn transitions
|
|
6
|
+
* daemon. So it emits exactly what a local turn emits, STREAM_DELTA, tool
|
|
7
|
+
* starts, tool results, turn transitions, on the `turn` and `tools` runtime
|
|
8
8
|
* domains, and the control-plane forwards those domains to any subscriber with
|
|
9
9
|
* the session id stamped on every envelope. There is no hosted-only token
|
|
10
10
|
* stream to consume and this file does not invent one: it opens the same event
|
|
11
11
|
* stream a client already uses and keeps the frames whose id matches the
|
|
12
12
|
* session it was told to watch.
|
|
13
13
|
*
|
|
14
|
-
* The third domain is `session`, which carries `hosted-session-update
|
|
14
|
+
* The third domain is `session`, which carries `hosted-session-update`, the
|
|
15
15
|
* lifecycle channel: created, attached, detached, turn started, turn ended,
|
|
16
16
|
* terminated, restored. That is how an attached terminal learns its session was
|
|
17
17
|
* killed from another surface, or that a turn started that it did not begin.
|
|
@@ -114,7 +114,7 @@ export function readHostedLifecycleNotice(payload: unknown): HostedSessionUpdate
|
|
|
114
114
|
*
|
|
115
115
|
* Resolves to null when the stream could not be opened; the reason is logged
|
|
116
116
|
* once rather than thrown into a keystroke path, and the caller keeps whatever
|
|
117
|
-
* it had (the verbs still work
|
|
117
|
+
* it had (the verbs still work, the conversation is simply not being watched).
|
|
118
118
|
*/
|
|
119
119
|
export async function watchHostedSession(
|
|
120
120
|
options: WatchHostedSessionOptions,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hosted-sessions.ts
|
|
2
|
+
* hosted-sessions.ts, this terminal's handle on a conversation the DAEMON runs.
|
|
3
3
|
*
|
|
4
4
|
* A local session's loop lives in this process: the orchestrator, the tools and
|
|
5
5
|
* the permission gate are all here, and closing the terminal ends the work. A
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*
|
|
19
19
|
* It is not the stream. The hosted loop is the ordinary Orchestrator, so its
|
|
20
20
|
* tokens, tool calls and turn transitions arrive on the `turn` and `tools`
|
|
21
|
-
* event domains stamped with the hosted session's id
|
|
21
|
+
* event domains stamped with the hosted session's id, see
|
|
22
22
|
* hosted-session-stream.ts, which watches exactly what a local session watches
|
|
23
23
|
* and filters on the id `attach` handed back.
|
|
24
24
|
*
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* Every `sessions.hosted.*` verb is declared `transport: ['ws']` with no REST
|
|
28
28
|
* path of its own, so `sdk.operator.invoke` refuses them before making a
|
|
29
29
|
* request. `createDaemonVerbCaller` (operator-endpoint.ts) already handles that
|
|
30
|
-
* exact class by falling through to the generic gateway route
|
|
30
|
+
* exact class by falling through to the generic gateway route, which IS the
|
|
31
31
|
* binding for a ws-declared verb reached over HTTP.
|
|
32
32
|
*/
|
|
33
33
|
import { hostname } from 'node:os';
|
|
@@ -59,7 +59,7 @@ export interface HostedSessionAttachment {
|
|
|
59
59
|
* terminals on one machine, because the detach policy is applied when the LAST
|
|
60
60
|
* client leaves: two windows sharing one id would make the first `detach` look
|
|
61
61
|
* like the last one. Host + pid is both, and it is readable in
|
|
62
|
-
* `attachedClients
|
|
62
|
+
* `attachedClients`, a person reading the record can tell which terminal that
|
|
63
63
|
* is.
|
|
64
64
|
*/
|
|
65
65
|
let cachedClientId: string | null = null;
|
|
@@ -70,18 +70,18 @@ export function terminalHostedClientId(): string {
|
|
|
70
70
|
|
|
71
71
|
/** The narrow client the command layer and the panel share. */
|
|
72
72
|
export interface HostedSessionsClient {
|
|
73
|
-
/** This terminal's attach identity
|
|
73
|
+
/** This terminal's attach identity, the same string the records carry. */
|
|
74
74
|
readonly clientId: string;
|
|
75
75
|
list(options?: { readonly includeTerminated?: boolean }): Promise<readonly HostedSessionRecord[]>;
|
|
76
76
|
create(input: Omit<CreateHostedSessionInput, 'clientId'>): Promise<HostedSessionRecord>;
|
|
77
77
|
attach(sessionId: string): Promise<HostedSessionAttachment>;
|
|
78
78
|
detach(sessionId: string): Promise<HostedSessionRecord>;
|
|
79
79
|
kill(sessionId: string): Promise<HostedSessionRecord>;
|
|
80
|
-
/** Send a message into a running hosted session
|
|
80
|
+
/** Send a message into a running hosted session, the ordinary steer verb. */
|
|
81
81
|
steer(sessionId: string, body: string): Promise<void>;
|
|
82
|
-
/** Queue a message for after the current turn
|
|
82
|
+
/** Queue a message for after the current turn, the ordinary follow-up verb. */
|
|
83
83
|
followUp(sessionId: string, body: string): Promise<void>;
|
|
84
|
-
/** Cancel one in-flight tool call
|
|
84
|
+
/** Cancel one in-flight tool call, the ordinary live-turn verb. */
|
|
85
85
|
cancelToolCall(sessionId: string, callId: string): Promise<boolean>;
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* operator-endpoint.ts
|
|
2
|
+
* operator-endpoint.ts, the one place this product resolves "the daemon I talk
|
|
3
3
|
* to", for every seam that talks to it.
|
|
4
4
|
*
|
|
5
5
|
* The terminal app is a pure client: it runs its own conversation loop and asks
|
|
6
6
|
* a separately-running daemon for everything else. Every one of those asks is
|
|
7
7
|
* an operator verb over HTTP, and every one of them needs the same three
|
|
8
|
-
* things
|
|
8
|
+
* things, is the daemon enabled, what base URL does it answer on, and what
|
|
9
9
|
* bearer token proves this surface may call it. Resolving that in each seam is
|
|
10
10
|
* how the old composition ended up with a DirectTransport in one place and a
|
|
11
11
|
* real fetch in another.
|
|
12
12
|
*
|
|
13
13
|
* `resolveOperatorRpc` was previously the command layer's private helper
|
|
14
14
|
* (input/commands/operator-rpc.ts). It moved here unchanged in behaviour so the
|
|
15
|
-
* runtime seams
|
|
16
|
-
* devices, checkpoints
|
|
15
|
+
* runtime seams, approvals, config, credentials, sessions, fleet, tasks,
|
|
16
|
+
* devices, checkpoints, reach the daemon through the SAME resolution the
|
|
17
17
|
* commands already used, and the command module now re-exports it.
|
|
18
18
|
*
|
|
19
19
|
* Refusals are values, never throws: a disabled daemon or an underivable base
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* Auth is the loopback file-token bootstrap: the token
|
|
26
26
|
* is read (or minted) from the daemon's own state directory. A daemon on
|
|
27
27
|
* another machine is reached by the network-adopt path, which writes that
|
|
28
|
-
* daemon's bearer into the same file
|
|
28
|
+
* daemon's bearer into the same file, so this resolution covers both.
|
|
29
29
|
*/
|
|
30
30
|
import { join } from 'node:path';
|
|
31
31
|
import { createGoodVibesSdk } from '@pellux/goodvibes-sdk';
|
|
@@ -77,7 +77,7 @@ export function resolveControlPlaneBaseUrl(configManager: ConfigManager): string
|
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
/** The daemon's own state directory
|
|
80
|
+
/** The daemon's own state directory, where the shared bearer token lives. */
|
|
81
81
|
export function resolveDaemonStateDirectory(homeDirectory: string): string {
|
|
82
82
|
return join(homeDirectory, '.goodvibes', 'daemon');
|
|
83
83
|
}
|
|
@@ -85,14 +85,14 @@ export function resolveDaemonStateDirectory(homeDirectory: string): string {
|
|
|
85
85
|
/**
|
|
86
86
|
* Resolve (or honestly refuse to resolve) an operator SDK client wired to this
|
|
87
87
|
* workspace's control-plane daemon, from just the two things the resolution
|
|
88
|
-
* actually needs
|
|
88
|
+
* actually needs, the config manager and the home directory.
|
|
89
89
|
*/
|
|
90
90
|
export function resolveOperatorRpc(deps: {
|
|
91
91
|
readonly configManager: ConfigManager;
|
|
92
92
|
readonly homeDirectory: string | (() => string);
|
|
93
93
|
}): OperatorRpc {
|
|
94
94
|
const { configManager } = deps;
|
|
95
|
-
// A refusal is a VALUE here, never a throw
|
|
95
|
+
// A refusal is a VALUE here, never a throw, that is the whole contract of
|
|
96
96
|
// this function, and callers rely on it to print an honest line rather than
|
|
97
97
|
// crash a keystroke. A context whose config manager cannot answer (a narrow
|
|
98
98
|
// embed, a partially-wired test double) is one more case of "no daemon can be
|
|
@@ -101,13 +101,13 @@ export function resolveOperatorRpc(deps: {
|
|
|
101
101
|
return { available: false, reason: 'no config manager is wired here, so no control-plane daemon can be resolved.' };
|
|
102
102
|
}
|
|
103
103
|
if (!resolveDaemonEnabled(configManager)) {
|
|
104
|
-
return { available: false, reason: 'the daemon is disabled (daemon.enabled=false)
|
|
104
|
+
return { available: false, reason: 'the daemon is disabled (daemon.enabled=false): no operator surface to reach. Enable it in /settings, then retry.' };
|
|
105
105
|
}
|
|
106
106
|
const baseUrl = resolveControlPlaneBaseUrl(configManager);
|
|
107
107
|
if (!baseUrl) {
|
|
108
|
-
return { available: false, reason: 'no control-plane base URL is configured (controlPlane.publicBaseUrl / controlPlane.host+port)
|
|
108
|
+
return { available: false, reason: 'no control-plane base URL is configured (controlPlane.publicBaseUrl / controlPlane.host+port): cannot reach the operator surface.' };
|
|
109
109
|
}
|
|
110
|
-
// Resolve the home directory only AFTER the static refusals
|
|
110
|
+
// Resolve the home directory only AFTER the static refusals, a caller whose
|
|
111
111
|
// shell paths are not wired (a disabled-daemon path) must still get the honest
|
|
112
112
|
// unavailable reason above, never a "shell paths not wired" throw.
|
|
113
113
|
const homeDirectory = typeof deps.homeDirectory === 'function' ? deps.homeDirectory() : deps.homeDirectory;
|
|
@@ -124,7 +124,7 @@ export function resolveOperatorRpc(deps: {
|
|
|
124
124
|
export function describeOperatorRpcError(error: unknown): string {
|
|
125
125
|
if (error instanceof GoodVibesSdkError) {
|
|
126
126
|
if (error.status === 404) {
|
|
127
|
-
return 'the connected daemon returned 404
|
|
127
|
+
return 'the connected daemon returned 404; this operator verb is not wired up on that daemon yet.';
|
|
128
128
|
}
|
|
129
129
|
if (error.status === 401 || error.status === 403) {
|
|
130
130
|
return `the connected daemon rejected the request (${error.status}): ${error.message}`;
|
|
@@ -139,8 +139,8 @@ export function describeOperatorRpcError(error: unknown): string {
|
|
|
139
139
|
* WEBSOCKET binding only.
|
|
140
140
|
*
|
|
141
141
|
* This matters more than it looks. `sdk.operator.invoke` resolves a method's
|
|
142
|
-
* declared `http` route and refuses
|
|
143
|
-
* is made
|
|
142
|
+
* declared `http` route and refuses, with a contract error, before any request
|
|
143
|
+
* is made, when the method has none. A large part of what this client needs is
|
|
144
144
|
* exactly that class: `approvals.raise`, `credentials.set`/`delete`,
|
|
145
145
|
* `checkpoints.*`, `rewind.*` and the `fleet.*` reads are all `transport: ws`
|
|
146
146
|
* in the operator contract, with no REST path of their own.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* spine-adoption.ts
|
|
2
|
+
* spine-adoption.ts, wiring this surface's session and memory spines to the
|
|
3
3
|
* daemon it adopted, over the SDK's adoption policy.
|
|
4
4
|
*
|
|
5
5
|
* ── What moved to the SDK, and what stays here ────────────────────────────
|
|
6
6
|
*
|
|
7
7
|
* The SDK's `@pellux/goodvibes-sdk/platform/runtime/client` now owns WHEN the
|
|
8
8
|
* wire comes up and goes down: idempotent per base URL, torn down on a
|
|
9
|
-
* change, the one-time legacy-store fold. This module owns WHAT the wire is
|
|
9
|
+
* change, the one-time legacy-store fold. This module owns WHAT the wire is,
|
|
10
10
|
* this terminal's own `createHttpTransport` + `createTuiSpineTransport` +
|
|
11
11
|
* `createTuiMemorySpineTransport`, injected as the SDK's `connect(baseUrl,
|
|
12
|
-
* authToken)` callback
|
|
12
|
+
* authToken)` callback, because building the actual HTTP client is the same
|
|
13
13
|
* connection-resolution concern the verb caller already keeps product-side.
|
|
14
14
|
*
|
|
15
15
|
* `activation: 'adopt-on-status'` is passed explicitly: this terminal gates
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
* ── What crosses the wire ──────────────────────────────────────────────────
|
|
21
21
|
*
|
|
22
22
|
* Session IDENTITY, not session execution. The conversation itself runs here;
|
|
23
|
-
* what the daemon holds is the register
|
|
23
|
+
* what the daemon holds is the register,
|
|
24
24
|
* which sessions exist, which surface is live on each, and the inputs queued
|
|
25
25
|
* against them. Concretely, on adoption this wires:
|
|
26
26
|
*
|
|
27
|
-
* - `sessions.register` / `sessions.close
|
|
27
|
+
* - `sessions.register` / `sessions.close`, the identity mirror, deliberately
|
|
28
28
|
* fire-and-forget so a slow daemon never shows up in a keystroke.
|
|
29
|
-
* - `sessions.inputs.list` / `sessions.inputs.deliver
|
|
29
|
+
* - `sessions.inputs.list` / `sessions.inputs.deliver`, the inbound steer
|
|
30
30
|
* path, so a message another surface queued for THIS session lands in the
|
|
31
31
|
* turn machinery here and is acknowledged on the wire.
|
|
32
|
-
* - `sessions.list
|
|
32
|
+
* - `sessions.list`, the cross-surface union the panels read, interval-
|
|
33
33
|
* refreshed and served synchronously.
|
|
34
34
|
* - the memory spine's wire transport, folded into the same handler by the
|
|
35
|
-
* SDK
|
|
35
|
+
* SDK, this module's own `syncMemorySpineToHostStatus` call is retired;
|
|
36
36
|
* supplying `memoryTransport` in the bundle and `memorySpine` in the
|
|
37
37
|
* options is what activates it now.
|
|
38
38
|
*
|