@pellux/goodvibes-tui 2.0.14 → 2.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.goodvibes/GOODVIBES.md +1 -1
- package/.goodvibes/agents/reviewer.md +8 -8
- package/.goodvibes/skills/add-provider/SKILL.md +22 -22
- package/CHANGELOG.md +35 -0
- package/README.md +40 -29
- package/docs/README.md +1 -1
- package/docs/foundation-artifacts/README.md +5 -5
- package/docs/foundation-artifacts/operator-contract.json +123 -123
- package/package.json +12 -10
- package/scripts/postinstall.js +3 -3
- package/src/audio/activation-sound.ts +7 -7
- package/src/audio/capture.ts +7 -7
- package/src/audio/onnxruntime-assets.d.ts +1 -1
- package/src/audio/player.ts +4 -4
- package/src/audio/spoken-turn-wiring.ts +4 -4
- package/src/audio/voice-capture-wiring.ts +5 -5
- package/src/audio/voice-input-session.ts +3 -3
- package/src/audio/wake-inference.ts +13 -8
- package/src/audio/wake-runtime.ts +10 -10
- package/src/cli/completions/generate.ts +2 -2
- package/src/cli/doctor.ts +13 -13
- package/src/cli/ensure-goodvibes-gitignore.ts +3 -3
- package/src/cli/entrypoint.ts +3 -3
- package/src/cli/help.ts +6 -6
- package/src/cli/hooks-command.ts +4 -4
- package/src/cli/hooks-report.ts +4 -4
- package/src/cli/launch-auto-update.ts +17 -17
- package/src/cli/management-commands.ts +8 -8
- package/src/cli/management-utils.ts +3 -3
- package/src/cli/management.ts +1 -1
- package/src/cli/plugin-bundles-command.ts +10 -10
- package/src/cli/plugin-command.ts +9 -9
- package/src/cli/service-posture.ts +1 -1
- package/src/cli/status.ts +10 -10
- package/src/cli/surface-command.ts +4 -4
- package/src/cli/tui-startup.ts +23 -23
- package/src/config/run-daemon-config-migration.ts +3 -3
- package/src/config/secret-config.ts +10 -10
- package/src/config/surface.ts +1 -1
- package/src/config/tui-extension-settings.ts +8 -8
- package/src/core/active-model-identity.ts +7 -7
- package/src/core/approval-alert.ts +5 -5
- package/src/core/bookmark-navigation.ts +3 -3
- package/src/core/budget-breach-notifier.ts +6 -6
- package/src/core/compaction-receipt.ts +8 -8
- package/src/core/composer-state.ts +2 -2
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-event-navigation.ts +2 -2
- package/src/core/conversation-fold.ts +9 -9
- package/src/core/conversation-line-cache.ts +14 -14
- package/src/core/conversation-render-context.ts +6 -6
- package/src/core/conversation-rendering.ts +27 -30
- package/src/core/conversation-search-expansion.ts +6 -6
- package/src/core/conversation-splash-state.ts +3 -3
- package/src/core/conversation-turn-structure.ts +13 -13
- package/src/core/conversation-types.ts +3 -3
- package/src/core/conversation-user-receipts.ts +5 -5
- package/src/core/conversation.ts +17 -17
- package/src/core/format-user-error.ts +5 -5
- package/src/core/long-task-notifier.ts +9 -9
- package/src/core/memory-diagnostics-gateway.ts +8 -8
- package/src/core/memory-provenance.ts +5 -5
- package/src/core/model-routing-chip.ts +3 -3
- package/src/core/pairing-tailscale-gateway.ts +3 -3
- package/src/core/permission-mode.ts +5 -5
- package/src/core/power-chip-source.ts +3 -3
- package/src/core/power-status.ts +8 -8
- package/src/core/rewind-receipt.ts +6 -6
- package/src/core/session-resume-core.ts +8 -8
- package/src/core/stream-event-wiring.ts +36 -36
- package/src/core/stream-stall-watchdog.ts +4 -4
- package/src/core/system-message-noise.ts +7 -7
- package/src/core/system-message-router.ts +10 -10
- package/src/core/terminal-notifier.ts +5 -5
- package/src/core/turn-budget-outcome.ts +5 -5
- package/src/core/turn-cancellation.ts +3 -3
- package/src/core/turn-event-wiring.ts +16 -16
- package/src/core/voice-capture-status.ts +2 -2
- package/src/core/voice-provision-gateway.ts +12 -12
- package/src/core/voice-provision-status.ts +19 -19
- package/src/core/voice-stt-gateway.ts +6 -6
- package/src/core/wake-provision-runner.ts +7 -7
- package/src/core/wake-provision-status.ts +17 -17
- package/src/core/workstream-notification.ts +8 -8
- package/src/export/gist-uploader.ts +7 -7
- package/src/input/autocomplete.ts +3 -3
- package/src/input/bookmark-modal.ts +1 -1
- package/src/input/command-args-hint.ts +2 -2
- package/src/input/command-reference.ts +9 -9
- package/src/input/command-registry.ts +32 -32
- package/src/input/commands/acp-runtime.ts +6 -6
- package/src/input/commands/calendar-runtime.ts +9 -9
- package/src/input/commands/channel-pairing.ts +11 -11
- package/src/input/commands/channel-runtime.ts +1 -1
- package/src/input/commands/checkin-runtime.ts +4 -4
- package/src/input/commands/checkpoint-runtime.ts +4 -4
- package/src/input/commands/ci-runtime.ts +4 -4
- package/src/input/commands/cluster-runtime.ts +3 -3
- package/src/input/commands/codebase-runtime.ts +16 -16
- package/src/input/commands/config.ts +6 -6
- package/src/input/commands/connection-status.ts +12 -12
- package/src/input/commands/context-window.ts +2 -2
- package/src/input/commands/cost-attribution-format.ts +4 -4
- package/src/input/commands/cost-runtime.ts +2 -2
- package/src/input/commands/devices-runtime.ts +7 -7
- package/src/input/commands/diff-runtime.ts +2 -2
- package/src/input/commands/editor-runtime.ts +1 -1
- package/src/input/commands/eval.ts +4 -4
- package/src/input/commands/experience-runtime.ts +1 -1
- package/src/input/commands/git-runtime.ts +3 -3
- package/src/input/commands/graph-runtime.ts +3 -3
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-metrics-format.ts +2 -2
- package/src/input/commands/health-runtime.ts +8 -8
- package/src/input/commands/hosted-runtime.ts +13 -13
- package/src/input/commands/image-runtime.ts +6 -6
- package/src/input/commands/intelligence-runtime.ts +2 -2
- package/src/input/commands/local-auth-runtime.ts +3 -3
- package/src/input/commands/local-provider-runtime.ts +3 -3
- package/src/input/commands/local-runtime.ts +7 -7
- package/src/input/commands/mail-runtime.ts +9 -9
- package/src/input/commands/mcp-runtime.ts +1 -1
- package/src/input/commands/memory.ts +13 -13
- package/src/input/commands/notify-runtime.ts +1 -1
- package/src/input/commands/operator-panel-runtime.ts +8 -8
- package/src/input/commands/operator-rpc.ts +3 -3
- package/src/input/commands/operator-runtime.ts +3 -3
- package/src/input/commands/palette-runtime.ts +1 -1
- package/src/input/commands/payment-card-intake.ts +17 -17
- package/src/input/commands/permissions-provenance.ts +7 -7
- package/src/input/commands/permissions-runtime.ts +1 -1
- package/src/input/commands/planning-runtime.ts +9 -9
- package/src/input/commands/platform-services-runtime.ts +2 -2
- package/src/input/commands/policy-dispatch.ts +6 -6
- package/src/input/commands/power-runtime.ts +6 -6
- package/src/input/commands/principals-runtime.ts +3 -3
- package/src/input/commands/product-runtime.ts +3 -3
- package/src/input/commands/profile-render.ts +13 -13
- package/src/input/commands/profile-runtime.ts +13 -13
- package/src/input/commands/profile-types.ts +13 -13
- package/src/input/commands/provider-accounts-runtime.ts +5 -5
- package/src/input/commands/provider.ts +10 -10
- package/src/input/commands/qrcode-runtime.ts +3 -3
- package/src/input/commands/queue-runtime.ts +6 -6
- package/src/input/commands/recall-files-config.ts +4 -4
- package/src/input/commands/recall-files-git.ts +3 -3
- package/src/input/commands/recall-files.ts +12 -12
- package/src/input/commands/recall-query.ts +3 -3
- package/src/input/commands/recall-review.ts +3 -3
- package/src/input/commands/recall-shared.ts +1 -1
- package/src/input/commands/relay-runtime.ts +5 -5
- package/src/input/commands/remote-runtime.ts +3 -3
- package/src/input/commands/review-runtime.ts +8 -8
- package/src/input/commands/rewind-runtime.ts +21 -21
- package/src/input/commands/runtime-services.ts +1 -2
- package/src/input/commands/schedule-nl.ts +2 -2
- package/src/input/commands/schedule-runtime.ts +2 -2
- package/src/input/commands/secret-runtime.ts +3 -3
- package/src/input/commands/session-content.ts +7 -7
- package/src/input/commands/session-picker-filter.ts +3 -3
- package/src/input/commands/session-workflow.ts +10 -10
- package/src/input/commands/session.ts +15 -15
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/share-runtime.ts +4 -4
- package/src/input/commands/shell-core.ts +11 -11
- package/src/input/commands/tasks-runtime.ts +4 -4
- package/src/input/commands/test-runtime.ts +6 -6
- package/src/input/commands/tts-runtime.ts +4 -4
- package/src/input/commands/update-runtime.ts +27 -27
- package/src/input/commands/websearch-runtime.ts +2 -2
- package/src/input/commands/work-plan-runtime.ts +2 -2
- package/src/input/commands/workstream-attempt-dependents.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +16 -16
- package/src/input/commands/workstream-runtime.ts +36 -36
- package/src/input/commands/worktree-runtime.ts +6 -6
- package/src/input/composer-capture.ts +5 -5
- package/src/input/concealed-input.ts +2 -2
- package/src/input/config-modal-types.ts +16 -16
- package/src/input/config-modal.ts +30 -30
- package/src/input/daemon-owned-settings-descriptions.ts +4 -4
- package/src/input/delete-key-policy.ts +1 -1
- package/src/input/exec-env-scrub-config.ts +7 -7
- package/src/input/feature-unit-layout.ts +5 -5
- package/src/input/feed-context-factory.ts +38 -38
- package/src/input/file-picker.ts +1 -1
- package/src/input/handler-command-route.ts +2 -2
- package/src/input/handler-content-actions.ts +8 -8
- package/src/input/handler-feed-routes.ts +13 -13
- package/src/input/handler-feed.ts +31 -31
- package/src/input/handler-interactions.ts +2 -2
- package/src/input/handler-modal-routes.ts +13 -13
- package/src/input/handler-modal-stack.ts +1 -1
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-onboarding-daemon-adopt.ts +6 -6
- package/src/input/handler-picker-routes.ts +7 -7
- package/src/input/handler-prompt-buffer.ts +1 -1
- package/src/input/handler-shortcuts.ts +12 -12
- package/src/input/handler-types.ts +3 -3
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +9 -9
- package/src/input/input-history.ts +1 -1
- package/src/input/keybindings.ts +13 -13
- package/src/input/kill-ring.ts +7 -11
- package/src/input/model-picker-filter.ts +3 -3
- package/src/input/model-picker-items.ts +5 -5
- package/src/input/model-picker-types.ts +2 -2
- package/src/input/model-picker.ts +18 -18
- package/src/input/onboarding/onboarding-feature-units.ts +9 -13
- package/src/input/onboarding/onboarding-provider-key-fields.ts +3 -3
- package/src/input/onboarding/onboarding-runtime-status.ts +3 -3
- package/src/input/onboarding/onboarding-wizard-apply.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +4 -4
- package/src/input/onboarding/onboarding-wizard-network-adopt.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-steps.ts +2 -2
- package/src/input/panel-integration-actions.ts +3 -3
- package/src/input/panel-mouse-geometry.ts +1 -1
- package/src/input/panel-paste-flood-guard.ts +9 -9
- package/src/input/payments-config.ts +15 -15
- package/src/input/profile-picker-modal.ts +1 -1
- package/src/input/provider-key-intake.ts +9 -9
- package/src/input/relay-settings-descriptions.ts +3 -3
- package/src/input/sandbox-exec-config.ts +9 -9
- package/src/input/search.ts +18 -18
- package/src/input/selection-modal-queue.ts +10 -10
- package/src/input/selection-modal.ts +2 -2
- package/src/input/session-picker-modal.ts +7 -7
- package/src/input/settings-modal-activation.ts +1 -1
- package/src/input/settings-modal-adjustment.ts +2 -2
- package/src/input/settings-modal-commit.ts +6 -6
- package/src/input/settings-modal-connections.ts +2 -2
- package/src/input/settings-modal-data.ts +29 -29
- package/src/input/settings-modal-mutations.ts +7 -7
- package/src/input/settings-modal-reset.ts +3 -3
- package/src/input/settings-modal-search.ts +6 -6
- package/src/input/settings-modal-secrets.ts +3 -3
- package/src/input/settings-modal-types.ts +16 -16
- package/src/input/settings-modal.ts +4 -4
- package/src/input/voice-local-settings.ts +3 -3
- package/src/input/worktree-setup-config.ts +8 -8
- package/src/main.ts +15 -15
- package/src/panels/agent-inspector-shared.ts +5 -5
- package/src/panels/base-panel.ts +3 -3
- package/src/panels/builtin/agent.ts +3 -3
- package/src/panels/builtin/development.ts +4 -4
- package/src/panels/builtin/knowledge.ts +1 -1
- package/src/panels/builtin/operations.ts +12 -12
- package/src/panels/builtin/session.ts +8 -8
- package/src/panels/builtin/shared.ts +6 -6
- package/src/panels/builtin-modals.ts +8 -8
- package/src/panels/confirm-state.ts +5 -5
- package/src/panels/cost-tracker-panel.ts +22 -22
- package/src/panels/diff-panel.ts +20 -20
- package/src/panels/diff-review-model.ts +5 -5
- package/src/panels/diff-review-panel.ts +5 -5
- package/src/panels/eval-registry.ts +2 -2
- package/src/panels/expandable-list-panel.ts +5 -5
- package/src/panels/fleet-acts.ts +20 -20
- package/src/panels/fleet-deep-link.ts +5 -5
- package/src/panels/fleet-gateway.ts +12 -12
- package/src/panels/fleet-observed-render.ts +11 -11
- package/src/panels/fleet-panel-format.ts +14 -14
- package/src/panels/fleet-panel-worktree-detail.ts +8 -8
- package/src/panels/fleet-panel.ts +34 -34
- package/src/panels/fleet-read-model.ts +49 -49
- package/src/panels/fleet-spawn.ts +15 -15
- package/src/panels/fleet-steer.ts +7 -7
- package/src/panels/fleet-stop.ts +5 -5
- package/src/panels/fleet-tabs.ts +14 -14
- package/src/panels/fleet-transcript.ts +26 -26
- package/src/panels/git-panel.ts +8 -8
- package/src/panels/hosted-session-feed.ts +13 -13
- package/src/panels/hosted-session-panel.ts +7 -7
- package/src/panels/index.ts +1 -1
- package/src/panels/local-auth-panel.ts +15 -15
- package/src/panels/memory-consolidation-gateway.ts +8 -8
- package/src/panels/modals/devices-modal.ts +8 -8
- package/src/panels/modals/hooks-modal.ts +1 -1
- package/src/panels/modals/keybindings-modal.ts +5 -5
- package/src/panels/modals/knowledge-modal.ts +2 -2
- package/src/panels/modals/local-auth-modal.ts +4 -4
- package/src/panels/modals/marketplace-modal.ts +3 -3
- package/src/panels/modals/memory-modal.ts +19 -19
- package/src/panels/modals/modal-surface-helpers.ts +1 -1
- package/src/panels/modals/modal-theme.ts +3 -3
- package/src/panels/modals/pairing-modal.ts +19 -19
- package/src/panels/modals/planning-modal.ts +4 -4
- package/src/panels/modals/plugins-modal.ts +1 -1
- package/src/panels/modals/policy-modal.ts +4 -4
- package/src/panels/modals/provider-health-modal.ts +1 -1
- package/src/panels/modals/remote-modal.ts +1 -1
- package/src/panels/modals/sandbox-modal.ts +2 -2
- package/src/panels/modals/security-modal.ts +4 -4
- package/src/panels/modals/services-modal.ts +1 -1
- package/src/panels/modals/work-plan-modal.ts +4 -4
- package/src/panels/notifications-feed.ts +6 -6
- package/src/panels/notifications-panel.ts +6 -6
- package/src/panels/panel-confirm-overlay.ts +4 -4
- package/src/panels/panel-manager.ts +13 -13
- package/src/panels/plugins-panel.ts +6 -6
- package/src/panels/polish-core.ts +2 -2
- package/src/panels/polish-tables.ts +2 -2
- package/src/panels/polish.ts +1 -1
- package/src/panels/project-planning-answer-actions.ts +3 -3
- package/src/panels/scrollable-list-panel.ts +15 -15
- package/src/panels/search-focus.ts +1 -1
- package/src/panels/session-maintenance.ts +1 -1
- package/src/panels/skills-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +11 -11
- package/src/panels/types.ts +14 -14
- package/src/panels/workstream-graph-render.ts +5 -5
- package/src/panels/wrfc-panel-format.ts +1 -1
- package/src/permissions/broker-approval-card.ts +13 -13
- package/src/permissions/hunk-selection.ts +13 -13
- package/src/permissions/prompt.ts +22 -22
- package/src/permissions/sandbox-exec-gate.ts +5 -5
- package/src/providers/provider-classification.ts +1 -1
- package/src/providers/reasoning-effort-surface.ts +12 -12
- package/src/renderer/ansi-sanitize.ts +5 -6
- package/src/renderer/autocomplete-overlay.ts +5 -5
- package/src/renderer/block-actions-overlay.ts +1 -1
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/code-block.ts +2 -2
- package/src/renderer/compaction-history-modal.ts +4 -4
- package/src/renderer/compaction-preview.ts +5 -5
- package/src/renderer/compaction-quality.ts +5 -5
- package/src/renderer/composer-fragments.ts +6 -6
- package/src/renderer/compositor.ts +9 -9
- package/src/renderer/config-modal.ts +3 -3
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/context-status-hint.ts +10 -10
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +2 -2
- package/src/renderer/conversation-surface.ts +6 -6
- package/src/renderer/diff.ts +4 -4
- package/src/renderer/fleet-tab-strip.ts +2 -2
- package/src/renderer/footer-tips.ts +4 -4
- package/src/renderer/fullscreen-primitives.ts +1 -1
- package/src/renderer/git-status.ts +5 -5
- package/src/renderer/header-line.ts +5 -5
- package/src/renderer/help-overlay.ts +5 -5
- package/src/renderer/hint-grammar.ts +2 -2
- package/src/renderer/layout.ts +1 -1
- package/src/renderer/markdown-inline.ts +3 -3
- package/src/renderer/markdown-table.ts +7 -7
- package/src/renderer/modal-factory.ts +3 -3
- package/src/renderer/model-picker-overlay.ts +2 -2
- package/src/renderer/model-workspace.ts +7 -7
- package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
- package/src/renderer/overlay-box.ts +1 -1
- package/src/renderer/panel-composite.ts +5 -5
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +8 -8
- package/src/renderer/profile-picker-modal.ts +3 -3
- package/src/renderer/prompt-content-width.ts +1 -1
- package/src/renderer/search-overlay.ts +3 -3
- package/src/renderer/selection-modal-overlay.ts +6 -6
- package/src/renderer/semantic-diff.ts +6 -7
- package/src/renderer/session-picker-modal.ts +24 -24
- package/src/renderer/settings-modal-connections.ts +3 -3
- package/src/renderer/settings-modal-helpers.ts +16 -16
- package/src/renderer/settings-modal.ts +10 -10
- package/src/renderer/shell-surface.ts +8 -8
- package/src/renderer/status-glyphs.ts +6 -6
- package/src/renderer/syntax-highlighter.ts +2 -3
- package/src/renderer/system-message.ts +3 -3
- package/src/renderer/tab-strip.ts +2 -2
- package/src/renderer/term-caps.ts +12 -12
- package/src/renderer/terminal-bg-probe.ts +10 -10
- package/src/renderer/terminal-escapes.ts +1 -1
- package/src/renderer/theme-mode-config.ts +3 -3
- package/src/renderer/theme.ts +34 -34
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +5 -5
- package/src/renderer/tool-result-expanded-lines.ts +3 -3
- package/src/renderer/tool-result-summary.ts +6 -6
- package/src/renderer/turn-injection.ts +9 -9
- package/src/renderer/ui-factory.ts +33 -33
- package/src/renderer/ui-primitives.ts +4 -4
- package/src/runtime/bootstrap-command-parts.ts +3 -3
- package/src/runtime/bootstrap-core.ts +21 -21
- package/src/runtime/bootstrap-hook-bridge.ts +8 -8
- package/src/runtime/bootstrap-shell.ts +9 -9
- package/src/runtime/bootstrap.ts +16 -16
- package/src/runtime/client/approval-updates.ts +3 -3
- package/src/runtime/client/build-floors.ts +7 -7
- package/src/runtime/client/daemon-attach-handshake.ts +5 -5
- package/src/runtime/client/fleet-union.ts +7 -7
- package/src/runtime/client/host-service-status.ts +2 -2
- package/src/runtime/client/hosted-exit.ts +4 -4
- package/src/runtime/client/hosted-roster.ts +4 -4
- package/src/runtime/client/hosted-session-stream.ts +5 -5
- package/src/runtime/client/hosted-sessions.ts +8 -8
- package/src/runtime/client/operator-endpoint.ts +14 -14
- package/src/runtime/client/spine-adoption.ts +8 -8
- package/src/runtime/context-accounting-source.ts +4 -4
- package/src/runtime/context.ts +2 -2
- package/src/runtime/conversation-rewind-port.ts +6 -6
- package/src/runtime/credential-composition.ts +2 -2
- package/src/runtime/daemon-attach-notices.ts +6 -6
- package/src/runtime/diagnostics/panels/index.ts +1 -1
- package/src/runtime/diagnostics/panels/ops.ts +2 -2
- package/src/runtime/disposal-wiring.ts +6 -6
- package/src/runtime/index.ts +11 -11
- package/src/runtime/install-self-check-startup.ts +4 -4
- package/src/runtime/install-self-check.ts +6 -6
- package/src/runtime/interaction-seams.ts +4 -4
- package/src/runtime/knowledge-services.ts +2 -2
- package/src/runtime/legacy-daemon-migration.ts +37 -37
- package/src/runtime/legacy-daemon-reconcile.ts +30 -30
- package/src/runtime/memory-governance-services.ts +3 -3
- package/src/runtime/memory-spine-transport.ts +3 -3
- package/src/runtime/notification-dispatch.ts +4 -4
- package/src/runtime/onboarding/apply.ts +1 -1
- package/src/runtime/onboarding/derivation.ts +1 -1
- package/src/runtime/onboarding/fast-path.ts +7 -7
- package/src/runtime/onboarding/progress.ts +2 -2
- package/src/runtime/onboarding/provider-key-capture.ts +4 -4
- package/src/runtime/onboarding/snapshot.ts +2 -2
- package/src/runtime/onboarding/state.ts +4 -4
- package/src/runtime/onboarding/types.ts +4 -4
- package/src/runtime/orchestrator-core-services.ts +5 -5
- package/src/runtime/path-shadow-startup.ts +3 -3
- package/src/runtime/perf/panel-contracts.ts +1 -1
- package/src/runtime/power-keepawake-remote.ts +6 -6
- package/src/runtime/process-lifecycle.ts +14 -14
- package/src/runtime/provider-fallback.ts +3 -3
- package/src/runtime/recovery-autosave.ts +3 -3
- package/src/runtime/recovery-decisions.ts +19 -19
- package/src/runtime/recovery-offer-wiring.ts +4 -4
- package/src/runtime/recovery-prompt.ts +20 -20
- package/src/runtime/relay-reachability-bridge.ts +3 -3
- package/src/runtime/release-artifacts.ts +1 -1
- package/src/runtime/resume-notice.ts +20 -20
- package/src/runtime/runtime-services-types.ts +20 -20
- package/src/runtime/services.ts +20 -20
- package/src/runtime/session-continuity-hints.ts +1 -1
- package/src/runtime/session-inbound-inputs.ts +12 -12
- package/src/runtime/session-resume-liveness-confirm.ts +4 -4
- package/src/runtime/session-spine-transport.ts +3 -3
- package/src/runtime/store/domains/panels.ts +2 -2
- package/src/runtime/store/domains/ui-perf.ts +2 -2
- package/src/runtime/store/index.ts +1 -1
- package/src/runtime/store/selectors/index.ts +1 -1
- package/src/runtime/store/state.ts +2 -2
- package/src/runtime/ui-services.ts +3 -3
- package/src/runtime/workspace-checkpointing.ts +3 -3
- package/src/runtime/wrfc-persistence.ts +15 -15
- package/src/scripts/process-messages.ts +1 -1
- package/src/shell/blocking-input.ts +9 -9
- package/src/shell/recovery-input-helpers.ts +2 -2
- package/src/shell/retry-affordance.ts +9 -9
- package/src/shell/ui-openers.ts +14 -14
- package/src/shell/voice-capture-shell.ts +3 -3
- package/src/tools/wrfc-agent-guard.ts +4 -4
- package/src/utils/browser.ts +2 -2
- package/src/utils/format-duration.ts +3 -3
- package/src/utils/format-number.ts +2 -2
- package/src/utils/splash-lines.ts +4 -4
- package/src/utils/terminal-width.ts +6 -6
- package/src/verification/verification-ledger.ts +25 -25
- package/src/version.ts +3 -3
|
@@ -24,7 +24,7 @@ const GRADIENT_CYCLE_FRAMES = 50;
|
|
|
24
24
|
* Ms since the last STREAM_DELTA before the whimsical phrase rotation freezes
|
|
25
25
|
* and createThinkingFragment shows an honest "stalled Ns" / "reconnecting"
|
|
26
26
|
* label instead. Deliberately much shorter than the 30s stream-stall-watchdog
|
|
27
|
-
* hint threshold (stream-stall-watchdog.ts)
|
|
27
|
+
* hint threshold (stream-stall-watchdog.ts), that threshold gates a
|
|
28
28
|
* low-priority system message about a likely-dead connection; this one gates
|
|
29
29
|
* a cosmetic label so the UI stops claiming "Vibing..." within a couple of
|
|
30
30
|
* seconds of real silence, well before the stall is confirmed as a problem.
|
|
@@ -35,7 +35,7 @@ const THINKING_STALL_FREEZE_MS = 2_500;
|
|
|
35
35
|
* Stall/reconnect state for the live thinking indicator, computed by the
|
|
36
36
|
* caller every render frame from streamMetrics (see stream-event-wiring.ts).
|
|
37
37
|
* `reconnect` is populated only once the SDK's STREAM_RETRY event fires
|
|
38
|
-
* (structurally consumed
|
|
38
|
+
* (structurally consumed, absent from SDK 0.35.0's TurnEvent union today).
|
|
39
39
|
*/
|
|
40
40
|
export interface ThinkingStallInfo {
|
|
41
41
|
/** Ms since the last STREAM_DELTA (or STREAM_START if none yet this turn). */
|
|
@@ -61,7 +61,7 @@ function fmtCost(usd: number): string {
|
|
|
61
61
|
*/
|
|
62
62
|
export class UIFactory {
|
|
63
63
|
/**
|
|
64
|
-
* The header row. Delegates to renderHeaderLine (header-line.ts)
|
|
64
|
+
* The header row. Delegates to renderHeaderLine (header-line.ts), extracted
|
|
65
65
|
* when the header gained the failover divergence marker and this file was
|
|
66
66
|
* already on the 800-line source gate.
|
|
67
67
|
*
|
|
@@ -85,7 +85,7 @@ export class UIFactory {
|
|
|
85
85
|
strikethrough = false
|
|
86
86
|
): Line[] {
|
|
87
87
|
// A historical user-message pill: it carries its own dark bodyBg, so its fg
|
|
88
|
-
// reads fg.secondary/state.reasoning (light-on-dark)
|
|
88
|
+
// reads fg.secondary/state.reasoning (light-on-dark), this is conversation
|
|
89
89
|
// content, not the transparent-terminal chrome, so it is not part of the
|
|
90
90
|
// light-terminal chrome flip.
|
|
91
91
|
return renderConversationFragment(text, width, {
|
|
@@ -111,12 +111,12 @@ export class UIFactory {
|
|
|
111
111
|
});
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
/** The mid-turn queue as an editable list
|
|
114
|
+
/** The mid-turn queue as an editable list, see composer-fragments.ts. */
|
|
115
115
|
public static createQueuedMessageList(width: number, items: readonly { readonly id: string; readonly text: string }[]): Line[] {
|
|
116
116
|
return renderQueuedMessageList(width, items);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
/** The optional "used N memories" provenance chip
|
|
119
|
+
/** The optional "used N memories" provenance chip, see composer-fragments.ts. */
|
|
120
120
|
public static createMemoryProvenanceChip(width: number, count: number, entries: readonly MemoryProvenanceEntry[], expanded: boolean): Line[] {
|
|
121
121
|
return renderMemoryProvenanceChip(width, count, entries, expanded);
|
|
122
122
|
}
|
|
@@ -150,10 +150,10 @@ export class UIFactory {
|
|
|
150
150
|
// Session permission mode (config value). Rendered as a leading pill in the
|
|
151
151
|
// posture block; undefined suppresses the pill (e.g. bare test callers).
|
|
152
152
|
permissionMode?: string,
|
|
153
|
-
// The web surface's reachable URL, when that surface is enabled
|
|
153
|
+
// The web surface's reachable URL, when that surface is enabled, a
|
|
154
154
|
// persistent low-priority context segment; undefined suppresses it.
|
|
155
155
|
webSurfaceUrl?: string,
|
|
156
|
-
// True while power.keepAwake holds
|
|
156
|
+
// True while power.keepAwake holds, renders the always-visible
|
|
157
157
|
// "sleep disabled" chip in the posture block (the danger-mode idiom: a
|
|
158
158
|
// persistent, colored surface indicator, the safety mechanism itself).
|
|
159
159
|
powerKeepAwake?: boolean,
|
|
@@ -180,7 +180,7 @@ export class UIFactory {
|
|
|
180
180
|
promptLines.forEach((text, i) => {
|
|
181
181
|
const contentW = boxWidth - 4;
|
|
182
182
|
const prefix = i === 0 ? ' › ' : ' ';
|
|
183
|
-
// Render text without cursor insertion
|
|
183
|
+
// Render text without cursor insertion, cursor is overlaid after
|
|
184
184
|
const rawText = `${prefix}${text}`;
|
|
185
185
|
const paddedText = fitDisplay(rawText, contentW);
|
|
186
186
|
const contentLine = createBaseLine();
|
|
@@ -218,7 +218,7 @@ export class UIFactory {
|
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
} else if (promptFocused && i === promptLines.length - 1) {
|
|
221
|
-
// No cursorPos provided
|
|
221
|
+
// No cursorPos provided, show block at end (fallback)
|
|
222
222
|
const endX = boxStartX + 2 + prefix.length + text.length;
|
|
223
223
|
if (endX < boxStartX + boxWidth - 2) {
|
|
224
224
|
contentLine[endX] = { char: GLYPHS.surface.cursor, fg: '252', bg: promptFocused ? BG_COLOR : '#334155', bold: false, dim: false, underline: false, italic: false, strikethrough: false };
|
|
@@ -226,11 +226,11 @@ export class UIFactory {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
// focus visibility (item 1c): when the panel workspace owns focus
|
|
229
|
-
// and the composer is empty, name the state and the way back
|
|
229
|
+
// and the composer is empty, name the state and the way back, the
|
|
230
230
|
// dimmed prompt alone (TEXT_COLOR/BG_COLOR above) told you nothing was
|
|
231
231
|
// wrong, but not why keystrokes weren't landing here.
|
|
232
232
|
if (!promptFocused && text === '' && i === 0) {
|
|
233
|
-
const hintText = 'panel focused
|
|
233
|
+
const hintText = 'panel focused: Esc returns';
|
|
234
234
|
const hintStartX = boxStartX + 2 + prefix.length;
|
|
235
235
|
let hx = hintStartX;
|
|
236
236
|
for (const ch of hintText) {
|
|
@@ -296,7 +296,7 @@ export class UIFactory {
|
|
|
296
296
|
// (light-terminal-aware); state.info reads on both light and dark terminals.
|
|
297
297
|
const t = activeUiTones();
|
|
298
298
|
const composerTokens: Array<{ text: string; fg: string; bold?: boolean; dim?: boolean }> = [];
|
|
299
|
-
// Permission-mode pill
|
|
299
|
+
// Permission-mode pill, always shown so the active session posture (normal
|
|
300
300
|
// / plan / accept-edits / auto) is visible at a glance. Tone: normal reads
|
|
301
301
|
// dim/neutral, plan reads info (read-only, safe), accept-edits and auto read
|
|
302
302
|
// as caution (raised autonomy). Cycled by Shift+Tab, toggled by /plan.
|
|
@@ -305,7 +305,7 @@ export class UIFactory {
|
|
|
305
305
|
const modeFg = modeTone === 'caution' ? t.chrome.warn : modeTone === 'info' ? t.state.info : '244';
|
|
306
306
|
composerTokens.push({ text: ` mode:${permissionModeLabel(permissionMode)} `, fg: modeFg, bold: modeTone !== 'neutral', dim: modeTone === 'neutral' });
|
|
307
307
|
}
|
|
308
|
-
// Context-usage chip
|
|
308
|
+
// Context-usage chip, always-visible compaction-pressure indicator so the
|
|
309
309
|
// user sees compaction approaching before it happens. Colored by proximity
|
|
310
310
|
// to the auto-compact threshold (fraction; falls back to 0.85 when unset).
|
|
311
311
|
if (contextWindow && contextWindow > 0) {
|
|
@@ -325,7 +325,7 @@ export class UIFactory {
|
|
|
325
325
|
: t.chrome.warn;
|
|
326
326
|
composerTokens.push({ text: ` risk:${composerPendingRisk} `, fg: riskColor, bold: true });
|
|
327
327
|
}
|
|
328
|
-
// "sleep disabled" chip
|
|
328
|
+
// "sleep disabled" chip, always visible while keep-awake holds, in the
|
|
329
329
|
// danger-mode idiom (a persistent warn-tone indicator; the chip is the
|
|
330
330
|
// safety mechanism, so there is no timer and no AC-only variant).
|
|
331
331
|
if (powerKeepAwake) composerTokens.push({ text: ` ${SLEEP_DISABLED_CHIP} `, fg: t.chrome.warn, bold: true });
|
|
@@ -353,7 +353,7 @@ export class UIFactory {
|
|
|
353
353
|
}
|
|
354
354
|
lines.push(postureLine);
|
|
355
355
|
} else if (compact && powerKeepAwake) {
|
|
356
|
-
// The keep-awake chip is a safety indicator
|
|
356
|
+
// The keep-awake chip is a safety indicator, it survives compact height
|
|
357
357
|
// even though the rest of the posture row (mode/ctx/risk/state/flags) is
|
|
358
358
|
// dropped at height < 30. Its own compact-surviving slot.
|
|
359
359
|
const chipLine = createBaseLine();
|
|
@@ -377,7 +377,7 @@ export class UIFactory {
|
|
|
377
377
|
const tokenSep = ` ${GLYPHS.navigation.pipeSeparator} `;
|
|
378
378
|
// 'n/a' (not 'unpriced') to stay compact in the single-line footer and
|
|
379
379
|
// match the existing "no priceable data" convention used elsewhere
|
|
380
|
-
// (cockpit-panel formatCost, agent-inspector-shared)
|
|
380
|
+
// (cockpit-panel formatCost, agent-inspector-shared), the footer has no
|
|
381
381
|
// room for a longer marker before truncation kicks in.
|
|
382
382
|
const mainCostStr = model
|
|
383
383
|
? isModelPriced(model)
|
|
@@ -387,7 +387,7 @@ export class UIFactory {
|
|
|
387
387
|
// Honest total = your main session + the delegated fleet. We show a SPLIT
|
|
388
388
|
// ("you ~$X · fleet ~$Y") rather than one summed figure: the two costs are
|
|
389
389
|
// tracked and attributed to different actors, and the split directly answers
|
|
390
|
-
// "where did the money go"
|
|
390
|
+
// "where did the money go", the exact confusion in the eval where the footer
|
|
391
391
|
// showed only the main session (~$0.046) while the fleet cost ~10x more
|
|
392
392
|
// ($0.446). The fleet segment appears only when there is a real fleet cost, so
|
|
393
393
|
// the idle single-session footer is unchanged.
|
|
@@ -405,7 +405,7 @@ export class UIFactory {
|
|
|
405
405
|
const copiedNotice = isRecentlyCopied ? ` [COPIED] ` : '';
|
|
406
406
|
const statsLine = ' ' + tokenLine + ' '.repeat(Math.max(0, width - 4 - getDisplayWidth(tokenLine) - getDisplayWidth(copiedNotice))) + copiedNotice;
|
|
407
407
|
lines.push(this.stringToLine(statsLine, width, { fg: isRecentlyCopied ? '81' : '244', bold: isRecentlyCopied }));
|
|
408
|
-
// Context usage progress bar
|
|
408
|
+
// Context usage progress bar, suppressed in compact mode.
|
|
409
409
|
if (!compact && contextWindow && contextWindow > 0) {
|
|
410
410
|
const ctxTokens = lastInputTokens ?? 0;
|
|
411
411
|
const label = ' Context Usage: ';
|
|
@@ -421,7 +421,7 @@ export class UIFactory {
|
|
|
421
421
|
lines.push(this.createProgressBarLine(label, ctxPct, barWidth, width, suffix, thresholdFraction));
|
|
422
422
|
}
|
|
423
423
|
// Context info line (working dir, model+provider, tools, hitl).
|
|
424
|
-
// Suppressed in compact mode. mode/status/flags are intentionally omitted
|
|
424
|
+
// Suppressed in compact mode. mode/status/flags are intentionally omitted,
|
|
425
425
|
// the posture block above owns them, so they are not duplicated here.
|
|
426
426
|
if (!compact && (workingDir || model)) {
|
|
427
427
|
const home = typeof process !== 'undefined' ? process.env.HOME ?? '' : '';
|
|
@@ -433,25 +433,25 @@ export class UIFactory {
|
|
|
433
433
|
// segment is character-truncated mid-word. cwd/model are the essential
|
|
434
434
|
// orientation segments (priority 0); the spine liveness marker is the
|
|
435
435
|
// daemon-honesty signal and must outlive the two decorative segments
|
|
436
|
-
// (tool count, notify mode)
|
|
436
|
+
// (tool count, notify mode), it is ordered ahead of them too, so a
|
|
437
437
|
// narrow line drops "N tools"/"notify:x" whole before spine is at risk.
|
|
438
438
|
const ctxParts: PrioritizedSegment[] = [];
|
|
439
439
|
if (displayDir) ctxParts.push({ text: displayDir, priority: 0 });
|
|
440
440
|
if (model) {
|
|
441
441
|
ctxParts.push({ text: model + (provider ? ` (${provider})` : ''), priority: 0 });
|
|
442
442
|
}
|
|
443
|
-
// Divergence marker
|
|
443
|
+
// Divergence marker, its own segment so a narrow line drops it WHOLE
|
|
444
444
|
// (joinPrioritizedSegments breaks priority ties toward the later
|
|
445
445
|
// segment) rather than truncating it into a half-word. Priority 0: it
|
|
446
446
|
// outranks every decorative segment, and what survives without it is
|
|
447
447
|
// still the SERVING backend, never a claim about the configured one.
|
|
448
448
|
if (modelNote) ctxParts.push({ text: modelNote, priority: 0 });
|
|
449
|
-
// Cross-surface spine posture
|
|
449
|
+
// Cross-surface spine posture, plain words, no blame. Adopted mode only.
|
|
450
450
|
if (sessionSpineStatus) ctxParts.push({ text: `spine:${sessionSpineStatus}`, priority: 1 });
|
|
451
|
-
// Web surface reachability
|
|
451
|
+
// Web surface reachability, plain, persistent; dropped first under width pressure.
|
|
452
452
|
if (webSurfaceUrl) ctxParts.push({ text: `web:${webSurfaceUrl}`, priority: 2 });
|
|
453
453
|
if (toolCount) ctxParts.push({ text: `${toolCount} tools`, priority: 2 });
|
|
454
|
-
// Labeled "notify" (not "hitl")
|
|
454
|
+
// Labeled "notify" (not "hitl"), /mode (aliased /hitl) governs UX
|
|
455
455
|
// notification verbosity (quiet/balanced/operator), not tool
|
|
456
456
|
// auto-approval, so it must not share vocabulary with the DANGER MODE
|
|
457
457
|
// risk banner rendered a few lines below. Lowest priority: dropped first.
|
|
@@ -494,19 +494,19 @@ export class UIFactory {
|
|
|
494
494
|
// wording (approval/reconnecting/pre-first-token/stalled/thinking) are no
|
|
495
495
|
// longer minted here. They come from the SDK presentation contract's
|
|
496
496
|
// waitingPhrase() (@pellux/goodvibes-sdk/platform/presentation, already
|
|
497
|
-
// adopted by the agent)
|
|
497
|
+
// adopted by the agent), see createThinkingFragment
|
|
498
498
|
// below. This renderer still decides WHICH state applies from its own
|
|
499
499
|
// stall/reconnect/approval signals (computeStallInfo/computeRenderStallInfo
|
|
500
500
|
// stay renderer-local per the extraction decision record); only the exact
|
|
501
501
|
// wording is shared.
|
|
502
502
|
|
|
503
|
-
// Gradient colors for thinking text
|
|
503
|
+
// Gradient colors for thinking text, cyan→purple in dark, teal→purple in
|
|
504
504
|
// light (matches splash/brand). Read live per render inside
|
|
505
505
|
// createThinkingFragment via activeUiTones() rather than baked into a static
|
|
506
506
|
// field, so a mode flip re-resolves without a module reload.
|
|
507
507
|
|
|
508
508
|
/**
|
|
509
|
-
* Per-frame stall info from stream metrics
|
|
509
|
+
* Per-frame stall info from stream metrics, computed from lastDeltaAtMs every render (not
|
|
510
510
|
* from any event) so it degrades gracefully with zero new SDK events. Undefined until the
|
|
511
511
|
* first delta clock exists this turn.
|
|
512
512
|
*/
|
|
@@ -525,11 +525,11 @@ export class UIFactory {
|
|
|
525
525
|
* never advanced during tool execution (the model isn't producing tokens
|
|
526
526
|
* then), so without this gate any tool call longer than
|
|
527
527
|
* THINKING_STALL_FREEZE_MS would make the thinking fragment print
|
|
528
|
-
* "Stalled Ns..." directly above the ticking "executing (Ns)" tool row
|
|
528
|
+
* "Stalled Ns..." directly above the ticking "executing (Ns)" tool row, a
|
|
529
529
|
* false positive during ordinary tool execution (see stream-event-wiring.ts
|
|
530
530
|
* TOOL_EXECUTING/TOOL_SUCCEEDED/TOOL_FAILED/TOOL_CANCELLED handlers).
|
|
531
|
-
* Genuine no-delta silence while waiting on the provider
|
|
532
|
-
* pre-first-token case, where lastDeltaAtMs is seeded at STREAM_START
|
|
531
|
+
* Genuine no-delta silence while waiting on the provider, including the
|
|
532
|
+
* pre-first-token case, where lastDeltaAtMs is seeded at STREAM_START,
|
|
533
533
|
* still stall-detects normally here, since no tool is active then; that is
|
|
534
534
|
* the honest stall case this indicator exists for.
|
|
535
535
|
*/
|
|
@@ -548,7 +548,7 @@ export class UIFactory {
|
|
|
548
548
|
const tones = activeUiTones();
|
|
549
549
|
// Freeze the whimsical phrase rotation once real silence has gone on
|
|
550
550
|
// long enough to be misleading (THINKING_STALL_FREEZE_MS). Decide WHICH
|
|
551
|
-
// honest waiting state applies (renderer-local
|
|
551
|
+
// honest waiting state applies (renderer-local, this signal computation
|
|
552
552
|
// stays here per the extraction decision record), then defer the exact
|
|
553
553
|
// wording to the SDK presentation contract's waitingPhrase() (which
|
|
554
554
|
// mirrors the agent's adoption). Precedence matches the contract:
|
|
@@ -567,7 +567,7 @@ export class UIFactory {
|
|
|
567
567
|
frame,
|
|
568
568
|
});
|
|
569
569
|
// Token-rate and time-to-first-token readouts are meaningless while waiting on the user, and a
|
|
570
|
-
// "tok/s" figure next to an approval prompt reads as if the model were still working
|
|
570
|
+
// "tok/s" figure next to an approval prompt reads as if the model were still working, suppress
|
|
571
571
|
// them; keep the elapsed timer since "how long the approval has waited" is honest.
|
|
572
572
|
const speedSuffix = (!approvalPending && tokenSpeed !== undefined && tokenSpeed > 0) ? ` (${Math.round(tokenSpeed)} tok/s)` : '';
|
|
573
573
|
const elapsedSuffix = elapsedMs !== undefined ? ` (${formatElapsed(elapsedMs)})` : '';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// ui-primitives.ts
|
|
2
|
+
// ui-primitives.ts, glyph registry + tone-token table.
|
|
3
3
|
//
|
|
4
4
|
// These four tables (GLYPHS, UI_TONES, DIFF_TONES, SPINNER_FRAMES) are
|
|
5
5
|
// no longer minted locally. They are the SDK presentation contract
|
|
6
6
|
// (@pellux/goodvibes-sdk/platform/presentation, already
|
|
7
7
|
// adopted by the agent), consumed here so the TUI and the agent
|
|
8
|
-
// share ONE source (Mike's move-to-SDK ruling
|
|
8
|
+
// share ONE source (Mike's move-to-SDK ruling, machinery needed by 2+
|
|
9
9
|
// surfaces => SDK). The TUI was the reference these values were lifted from
|
|
10
10
|
// verbatim, so this swap is byte-identical. See
|
|
11
11
|
// docs/decisions/2026-07-05-presentation-contract-sdk-extraction.md in the SDK.
|
|
@@ -27,9 +27,9 @@ import {
|
|
|
27
27
|
export { GLYPHS, DIFF_TONES, SPINNER_FRAMES };
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* UI_TONES
|
|
30
|
+
* UI_TONES, the single chrome/color-token source for src/renderer and
|
|
31
31
|
* src/panels. Concrete (dark-mode) values; resolveUiTones(mode) in theme.ts
|
|
32
|
-
* is the single mode-resolved read path
|
|
32
|
+
* is the single mode-resolved read path, this object is the 'dark' entry
|
|
33
33
|
* (== resolveTones('dark') from the SDK presentation contract).
|
|
34
34
|
*/
|
|
35
35
|
export const UI_TONES = TONE_TOKENS;
|
|
@@ -215,7 +215,7 @@ export function createBootstrapCommandActions(
|
|
|
215
215
|
const showPanel = (panelId: string, pane?: 'top' | 'bottom', target?: PanelDeepLinkTarget) => {
|
|
216
216
|
// (the purge): a MIGRATE-TO-MODAL id resolves to a modal, not a panel.
|
|
217
217
|
// panelManager.open() fires the injected openModal callback and returns a
|
|
218
|
-
// no-op sentinel
|
|
218
|
+
// no-op sentinel, so skip panelManager.show() (which would reveal an empty
|
|
219
219
|
// panel workspace behind the modal) when this id redirects. Keeps every
|
|
220
220
|
// showPanel-based front-door (openHooksPanel/openSecurityPanel/… and the
|
|
221
221
|
// migrated command runtimes) opening the modal cleanly.
|
|
@@ -272,7 +272,7 @@ export function createBootstrapCommandActions(
|
|
|
272
272
|
// the preference. Every other route into this callback (model-only
|
|
273
273
|
// commit, context-cap commit) carries a level merely carried over
|
|
274
274
|
// from the previous model; storing that is what used to ratchet the
|
|
275
|
-
// preference down for good
|
|
275
|
+
// preference down for good, one hop through a model that caps at
|
|
276
276
|
// 'medium' and 'xhigh' was gone from config, so hopping back could
|
|
277
277
|
// not restore it.
|
|
278
278
|
//
|
|
@@ -344,7 +344,7 @@ export function createBootstrapCommandActions(
|
|
|
344
344
|
showPanel('memory');
|
|
345
345
|
},
|
|
346
346
|
// remote/subscription migrated to config-modal surfaces. open() hits
|
|
347
|
-
// the modal redirect and invokes the openModal callback
|
|
347
|
+
// the modal redirect and invokes the openModal callback, do NOT go through
|
|
348
348
|
// showPanel here, which would additionally reveal + focus an (empty) panel
|
|
349
349
|
// workspace behind the fullscreen modal.
|
|
350
350
|
openRemotePanel: () => {
|
|
@@ -118,14 +118,14 @@ export interface BootstrapCoreState {
|
|
|
118
118
|
readonly requestRender: () => void;
|
|
119
119
|
readonly setRenderRequest: (fn: () => void) => void;
|
|
120
120
|
readonly runtimeSessionIdRef: { value: string };
|
|
121
|
-
/** Cross-surface identity mirror; dormant for local-only, and for the SDK's 'embedded' HostServiceMode, which no product-facing setting can select
|
|
121
|
+
/** Cross-surface identity mirror; dormant for local-only, and for the SDK's 'embedded' HostServiceMode, which no product-facing setting can select, this product only ever adopts an external daemon or runs local-only (see the ADOPT ONLY guard in bootstrap.ts) (docs/decisions/2026-07-06-session-spine-mode-branch-is-permanent.md). Activated by bootstrap.ts only for an adopted 'external' daemon. */
|
|
122
122
|
readonly sessionSpine: SessionSpineClient;
|
|
123
123
|
/** Inbound steer/follow-up delivery; dormant until bootstrap.ts activates it. */
|
|
124
124
|
readonly sessionInboundInputs: SessionInboundInputPoller;
|
|
125
|
-
/** Cache-backed read facade; bootstrap.ts drives its mode (external/local-only in this product
|
|
125
|
+
/** Cache-backed read facade; bootstrap.ts drives its mode (external/local-only in this product, 'embedded' is a HostServiceMode value with no product-facing setting to select it here) from the same HostServiceMode as the spine above. */
|
|
126
126
|
readonly sessionUnionCache: SessionUnionCache;
|
|
127
127
|
/**
|
|
128
|
-
* WRFC chain persistence
|
|
128
|
+
* WRFC chain persistence, call `rehydrate()` once after the SystemMessageRouter
|
|
129
129
|
* is wired so interrupted chains from a previous process are surfaced to the operator.
|
|
130
130
|
*/
|
|
131
131
|
readonly wrfcPersistence: WrfcPersistence;
|
|
@@ -136,7 +136,7 @@ export type CompanionMessagePayload = Extract<SessionEvent, { type: 'COMPANION_M
|
|
|
136
136
|
// --- Operator narration of inbound channel events ---
|
|
137
137
|
|
|
138
138
|
/** Narrate an inbound channel event (GitHub, Slack, ntfy, etc.) that triggered an
|
|
139
|
-
* agent turn, via the SystemMessageRouter
|
|
139
|
+
* agent turn, via the SystemMessageRouter, null for internal/companion sources. */
|
|
140
140
|
export function narrateInboundEvent(event: {
|
|
141
141
|
source: string;
|
|
142
142
|
metadata: Readonly<Record<string, unknown>> | undefined;
|
|
@@ -144,7 +144,7 @@ export function narrateInboundEvent(event: {
|
|
|
144
144
|
const { source, metadata } = event;
|
|
145
145
|
if (!source) return null;
|
|
146
146
|
|
|
147
|
-
// Derive the effective surface
|
|
147
|
+
// Derive the effective surface, prefer metadata.surface, fall back to source.
|
|
148
148
|
const surface = typeof metadata?.surface === 'string' ? metadata.surface : source;
|
|
149
149
|
|
|
150
150
|
// Internal / companion sources do not need operator narration.
|
|
@@ -260,7 +260,7 @@ export async function initializeBootstrapCore(
|
|
|
260
260
|
services.benchmarkStore.initBenchmarks();
|
|
261
261
|
providerRegistry.initCatalog();
|
|
262
262
|
// Wire cost-utils to the live catalog AND the ONE pricing resolver so every
|
|
263
|
-
// cost surface distinguishes real pricing from unpriced and names its source ("your price" vs "catalog price, as of <date>")
|
|
263
|
+
// cost surface distinguishes real pricing from unpriced and names its source ("your price" vs "catalog price, as of <date>"), see cost-utils.
|
|
264
264
|
wireCostPricing(providerRegistry);
|
|
265
265
|
services.keybindingsManager.loadFromDisk();
|
|
266
266
|
domainDispatch.syncControlPlaneState({
|
|
@@ -296,7 +296,7 @@ export async function initializeBootstrapCore(
|
|
|
296
296
|
surfaceRegistry,
|
|
297
297
|
watcherRegistry,
|
|
298
298
|
} = services;
|
|
299
|
-
// Dormant for local-only, and for the SDK's 'embedded' HostServiceMode
|
|
299
|
+
// Dormant for local-only, and for the SDK's 'embedded' HostServiceMode, no product-facing
|
|
300
300
|
// setting can select it (SDK-internal embedder/test machinery); bootstrap.ts activates this spine only for an adopted 'external' daemon.
|
|
301
301
|
const sessionSpine = new SessionSpineClient({ participant: TUI_SPINE_PARTICIPANT, recordKind: 'tui' });
|
|
302
302
|
// Cache-backed read facade over the local broker (passthrough until bootstrap.ts
|
|
@@ -381,7 +381,7 @@ export async function initializeBootstrapCore(
|
|
|
381
381
|
credentialEnvScrub: { allowlist: readExecEnvScrubAllowlist(configManager) },
|
|
382
382
|
// Register context_accounting against OUR holder (the Orchestrator-backed source bound at bootstrap.ts). See runtime/context-accounting-source.ts.
|
|
383
383
|
contextAccountingHolder: services.contextAccountingHolder,
|
|
384
|
-
// First contained (sandboxed) command run announces "commands now run contained" once
|
|
384
|
+
// First contained (sandboxed) command run announces "commands now run contained" once, recorded and surfaced now.
|
|
385
385
|
onSandboxedRun: createSandboxContainmentNotice({ configManager, notify: (text) => conversation.log(`[Sandbox] ${text}`, { fg: '135' }) }),
|
|
386
386
|
}); registerClientPhoneTool(toolRegistry, services.devices); // the `phone` tool follows the LOOP, so it is registered here; the posture runtime it used to call is the daemon's now and this tool reaches it over the devices.* verbs (see the SDK's client/phone-tool.ts)
|
|
387
387
|
// Note: installWrfcAgentToolGuard is called after routeOrBuffer is defined (further below) so the onTrace callback routes guard decisions through the pre-router buffer.
|
|
@@ -426,7 +426,7 @@ export async function initializeBootstrapCore(
|
|
|
426
426
|
await runBootMemoryFold(memoryStore, services.memoryEmbeddingRegistry, workingDir, logger);
|
|
427
427
|
|
|
428
428
|
const renderRequestRef = { value: (): void => {} };
|
|
429
|
-
// Coalescing render scheduler
|
|
429
|
+
// Coalescing render scheduler, collapses N requestRender() calls into 1 and
|
|
430
430
|
// enforces a 16ms minimum interval to cap repaints at ~60fps. renderScheduled stays
|
|
431
431
|
// set for the ENTIRE window (until run() executes), so requestRender() calls arriving
|
|
432
432
|
// on later event-loop ticks within the same 16ms window coalesce into the one
|
|
@@ -435,8 +435,8 @@ export async function initializeBootstrapCore(
|
|
|
435
435
|
let renderScheduled = false;
|
|
436
436
|
let lastRenderTime = 0;
|
|
437
437
|
const RENDER_INTERVAL_MS = 16;
|
|
438
|
-
// run() performs the actual render. It clears renderScheduled FIRST
|
|
439
|
-
// render callback throws
|
|
438
|
+
// run() performs the actual render. It clears renderScheduled FIRST, even if the
|
|
439
|
+
// render callback throws, otherwise a single render exception would wedge the entire
|
|
440
440
|
// TUI (no future requestRender() would schedule anything); we log at error so the
|
|
441
441
|
// next requestRender() can still reschedule.
|
|
442
442
|
const run = (): void => {
|
|
@@ -449,7 +449,7 @@ export async function initializeBootstrapCore(
|
|
|
449
449
|
}
|
|
450
450
|
// Debounced spine heartbeat on turn/render activity (no-op while dormant, i.e. local-only, or
|
|
451
451
|
// the SDK's 'embedded' mode, for which no product-facing setting exists): a cheap synchronous
|
|
452
|
-
// no-op unless its own internal window has elapsed (at most one wire call per heartbeatMinIntervalMs)
|
|
452
|
+
// no-op unless its own internal window has elapsed (at most one wire call per heartbeatMinIntervalMs), safe on the hot path.
|
|
453
453
|
sessionSpine.heartbeat(runtimeSessionIdRef.value);
|
|
454
454
|
};
|
|
455
455
|
const requestRender = (): void => {
|
|
@@ -458,7 +458,7 @@ export async function initializeBootstrapCore(
|
|
|
458
458
|
setImmediate(() => {
|
|
459
459
|
const elapsed = Date.now() - lastRenderTime;
|
|
460
460
|
if (elapsed < RENDER_INTERVAL_MS) {
|
|
461
|
-
// Too soon
|
|
461
|
+
// Too soon, debounce to the tail of the current 16ms window. The flag
|
|
462
462
|
// stays set until run() fires, so window-local requests coalesce here.
|
|
463
463
|
setTimeout(run, RENDER_INTERVAL_MS - elapsed);
|
|
464
464
|
} else {
|
|
@@ -470,7 +470,7 @@ export async function initializeBootstrapCore(
|
|
|
470
470
|
// client approval raiser calls, so the UI layer patching this patches that.
|
|
471
471
|
const permissionPromptRef = services.localPromptRef as { requestPermission: PermissionRequestHandler };
|
|
472
472
|
// Trust-at-consequence-time: raised by trustGatedAsk on the first non-read
|
|
473
|
-
// request in an undecided workspace; overridden once the UI layer exists
|
|
473
|
+
// request in an undecided workspace; overridden once the UI layer exists, same ref-patching pattern as permissionPromptRef above.
|
|
474
474
|
const trustPromptRef = { requestTrustDecision: (async () => 'restricted') as () => Promise<WorkspaceTrustLevel> };
|
|
475
475
|
approvalBroker.start().catch((err) => logger.warn('approval broker start failed at bootstrap', { err }));
|
|
476
476
|
sharedSessionBroker.start().catch((err) => logger.warn('shared session broker start failed at bootstrap', { err }));
|
|
@@ -539,7 +539,7 @@ export async function initializeBootstrapCore(
|
|
|
539
539
|
}
|
|
540
540
|
};
|
|
541
541
|
|
|
542
|
-
// Startup TLS banner
|
|
542
|
+
// Startup TLS banner, emitted via wrfcBuffer.push() because the
|
|
543
543
|
// SystemMessageRouter is not attached yet at this point in bootstrap. The
|
|
544
544
|
// smart-ref setter on systemMessageRouterRef auto-flushes the buffer when
|
|
545
545
|
// the router attaches, so the message will appear in the WRFC panel on startup.
|
|
@@ -616,7 +616,7 @@ export async function initializeBootstrapCore(
|
|
|
616
616
|
getLastUserMessage: () => conversation.getLastUserMessage(),
|
|
617
617
|
onTrace: ({ kind, reason, task }) => {
|
|
618
618
|
const shortTask = task.length > 80 ? `${task.slice(0, 77)}...` : task;
|
|
619
|
-
routeOrBuffer(`[WRFC] Guard: ${reason}
|
|
619
|
+
routeOrBuffer(`[WRFC] Guard: ${reason}; task: "${shortTask}" (${kind})`, 'low');
|
|
620
620
|
},
|
|
621
621
|
});
|
|
622
622
|
|
|
@@ -629,7 +629,7 @@ export async function initializeBootstrapCore(
|
|
|
629
629
|
// which (a) adds the user message to the conversation view and (b) fires a real LLM
|
|
630
630
|
// turn whose STREAM_DELTA / TURN_COMPLETED events flow to both TUI and companion SSE.
|
|
631
631
|
//
|
|
632
|
-
// The fallback (ref not yet set) adds the message to the conversation view only
|
|
632
|
+
// The fallback (ref not yet set) adds the message to the conversation view only,
|
|
633
633
|
// this path is unreachable in practice because the event bus is not connected to
|
|
634
634
|
// any live HTTP traffic until after the orchestrator is wired in bootstrap.ts.
|
|
635
635
|
const orchestratorHandleUserInputRef: {
|
|
@@ -661,7 +661,7 @@ export async function initializeBootstrapCore(
|
|
|
661
661
|
},
|
|
662
662
|
));
|
|
663
663
|
|
|
664
|
-
// Inbound steer delivery
|
|
664
|
+
// Inbound steer delivery, see createBootstrapInboundInputPoller's doc comment.
|
|
665
665
|
const sessionInboundInputs = createBootstrapInboundInputPoller({
|
|
666
666
|
runtimeSessionIdRef, routeOrBuffer, orchestratorHandleUserInputRef, conversation, requestRender,
|
|
667
667
|
});
|
|
@@ -674,7 +674,7 @@ export async function initializeBootstrapCore(
|
|
|
674
674
|
// webhook URL added mid-session reached long-task notifications (which read
|
|
675
675
|
// ctx.services.webhookNotifier directly) but never reached this instance's
|
|
676
676
|
// AGENT_FAILED/WORKFLOW_CHAIN_FAILED/WORKFLOW_CHAIN_PASSED runtime-bus
|
|
677
|
-
// listeners until restart
|
|
677
|
+
// listeners until restart, and if the session started with zero URLs
|
|
678
678
|
// configured, attachToRuntimeBus was never even called, so those listeners
|
|
679
679
|
// never existed at all for the rest of the session. Always attaching
|
|
680
680
|
// (regardless of initial URL count) and seeding the shared instance fixes
|
|
@@ -729,7 +729,7 @@ export async function initializeBootstrapCore(
|
|
|
729
729
|
runtimeSessionIdRef.value = runtime.sessionId;
|
|
730
730
|
services.liveSessionIdRef.value = runtime.sessionId; // the session an ask raised on the daemon belongs to
|
|
731
731
|
// The live conversation, for this process's own /rewind AND for the daemon's
|
|
732
|
-
// questions about it
|
|
732
|
+
// questions about it, only the process holding the messages can count or
|
|
733
733
|
// drop them (conversation-rewind-port.ts, the SDK's client/conversation-rewind-host.ts).
|
|
734
734
|
registerSessionConversation(runtime.sessionId, conversation);
|
|
735
735
|
void sharedSessionBroker.createSession({
|
|
@@ -743,7 +743,7 @@ export async function initializeBootstrapCore(
|
|
|
743
743
|
lastSeenAt: Date.now(),
|
|
744
744
|
},
|
|
745
745
|
}).catch((err) => { logger.debug('session broker create session failed at bootstrap', { err }); });
|
|
746
|
-
// Fire-and-forget spine mirror
|
|
746
|
+
// Fire-and-forget spine mirror, a permanent parallel-write posture alongside (never
|
|
747
747
|
// instead of) the still-authoritative local SharedSessionBroker above. Dormant/queued
|
|
748
748
|
// until bootstrap.ts's deferred task activates it for an adopted 'external' daemon.
|
|
749
749
|
sessionSpine.register({ sessionId: runtime.sessionId, project: services.workingDirectory, title: 'Terminal UI session' });
|
|
@@ -25,14 +25,14 @@ export interface ResumeSessionOptions {
|
|
|
25
25
|
readonly onSessionIdChanged?: (sessionId: string) => void;
|
|
26
26
|
readonly sharedSessionBroker: Pick<SharedSessionBroker, 'reopenSession'>;
|
|
27
27
|
/** Fire-and-forget daemon-spine mirror. Reopen (not register) is the
|
|
28
|
-
* ONLY resume-time verb
|
|
28
|
+
* ONLY resume-time verb, see the SDK session-spine client.ts header doc. */
|
|
29
29
|
readonly sessionSpine: Pick<SessionSpineClient, 'reopen'>;
|
|
30
30
|
readonly project: string;
|
|
31
31
|
readonly writeLastSessionPointer: (sessionId: string) => void;
|
|
32
32
|
readonly hookDispatcher: HookDispatcher;
|
|
33
33
|
readonly sessionManager: SessionManager;
|
|
34
34
|
readonly panelManager: PanelManager;
|
|
35
|
-
/** The app's declare-once session-storage handle
|
|
35
|
+
/** The app's declare-once session-storage handle, the same one /session resume threads. */
|
|
36
36
|
readonly surface: SessionSurface;
|
|
37
37
|
/**
|
|
38
38
|
* Multi-instance guard for this seam. Resolves false when the operator
|
|
@@ -47,7 +47,7 @@ export interface ResumeSessionOptions {
|
|
|
47
47
|
/**
|
|
48
48
|
* Reselects the resumed session's saved model through the live provider
|
|
49
49
|
* registry (matches session-workflow.ts's `/session resume` reselection
|
|
50
|
-
* fallback
|
|
50
|
+
* fallback, see core/session-resume-core.ts). Optional so a caller without
|
|
51
51
|
* a provider API wired still gets the direct-assignment behavior this seam
|
|
52
52
|
* always had.
|
|
53
53
|
*/
|
|
@@ -58,7 +58,7 @@ export interface ResumeSessionOptions {
|
|
|
58
58
|
* Delegates the mechanical resume sequence to resumeSessionCore (the same
|
|
59
59
|
* routine session-workflow.ts's `/session resume` calls) so the two seams
|
|
60
60
|
* cannot diverge on restoreTurnAnchors, resetAll-before-fromJSON, model
|
|
61
|
-
* reselection, or the modal-redirect panel-reopen skip
|
|
61
|
+
* reselection, or the modal-redirect panel-reopen skip, see
|
|
62
62
|
* core/session-resume-core.ts's header doc for the full list of divergences
|
|
63
63
|
* this closes. Everything below the resumeSessionCore call is plumbing only
|
|
64
64
|
* this seam performs (hook fire, session-spine mirror, shared-broker
|
|
@@ -71,12 +71,12 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
|
|
|
71
71
|
// for the text path: never fork a session another terminal is holding
|
|
72
72
|
// open without the operator saying so.
|
|
73
73
|
if (options.confirmLiveResume && !(await options.confirmLiveResume(sessionId))) {
|
|
74
|
-
options.conversation.log('Resume cancelled
|
|
74
|
+
options.conversation.log('Resume cancelled: the session is still open in another terminal.', { fg: '244' });
|
|
75
75
|
options.requestRender();
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
78
|
// Pre-read purely for the emitSessionResumed announcement's turnCount,
|
|
79
|
-
// which reports the raw saved-snapshot size
|
|
79
|
+
// which reports the raw saved-snapshot size, resumeSessionCore performs
|
|
80
80
|
// its own load() right after this (SessionManager.load is a cheap JSONL
|
|
81
81
|
// parse; the tiny duplicate read keeps this announcement's meaning
|
|
82
82
|
// unchanged rather than repurposing it to a post-replay count).
|
|
@@ -104,11 +104,11 @@ export function createResumeSessionHandler(options: ResumeSessionOptions): (sess
|
|
|
104
104
|
options.onSessionIdChanged?.(sessionId);
|
|
105
105
|
options.writeLastSessionPointer(sessionId);
|
|
106
106
|
void options.sharedSessionBroker.reopenSession(sessionId).catch((err) => { logger.debug('session broker reopen session failed', { err }); });
|
|
107
|
-
// Fire-and-forget spine mirror (reopen:true
|
|
107
|
+
// Fire-and-forget spine mirror (reopen:true, the user resume verb).
|
|
108
108
|
options.sessionSpine.reopen({ sessionId, project: options.project, title: options.conversation.title || meta.title });
|
|
109
109
|
options.conversation.log(`Resumed session: ${sessionId}`, { fg: '135' });
|
|
110
110
|
if (panels.movedToModal.length > 0) {
|
|
111
|
-
options.conversation.log(`Resume: ${panels.movedToModal.join(', ')} moved to a modal
|
|
111
|
+
options.conversation.log(`Resume: ${panels.movedToModal.join(', ')} moved to a modal; reopen via its command instead of as a panel.`, { fg: '244' });
|
|
112
112
|
}
|
|
113
113
|
if (panels.notReopened.length > 0) {
|
|
114
114
|
options.conversation.log(`Resume: …and ${panels.notReopened.length} more not reopened (/panels to open)`, { fg: '244' });
|
|
@@ -96,7 +96,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
96
96
|
|
|
97
97
|
// after any resume seam replays historical messages into `conversation`,
|
|
98
98
|
// the freshly-constructed `orchestrator` still has its zeroed default usage
|
|
99
|
-
// (SDK gap
|
|
99
|
+
// (SDK gap, Orchestrator.usage is never persisted/reseeded). Recompute it
|
|
100
100
|
// from the replayed history so the footer doesn't show Input: 0 post-resume.
|
|
101
101
|
const hydrateSessionUsage = (): void => {
|
|
102
102
|
const { usage, lastInputTokens } = sumConversationUsage(conversation.getMessageSnapshot());
|
|
@@ -105,7 +105,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
105
105
|
};
|
|
106
106
|
// Built before resumeSession below so its providerApi.selectModel is
|
|
107
107
|
// available for the resume handler's model-reselection step (matches
|
|
108
|
-
// session-workflow.ts's /session resume
|
|
108
|
+
// session-workflow.ts's /session resume, see core/session-resume-core.ts).
|
|
109
109
|
const foundationClients = createRuntimeFoundationClients({
|
|
110
110
|
runtimeServices: services,
|
|
111
111
|
tasksReadModel: uiServices.readModels.tasks,
|
|
@@ -156,7 +156,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
156
156
|
|
|
157
157
|
// initial cost-budget alert threshold (USD; 0/unset = disabled).
|
|
158
158
|
// Once the session starts, the real control surface is the CostTrackerPanel
|
|
159
|
-
// itself
|
|
159
|
+
// itself, the in-panel 'b' key and /cost budget <usd> both call
|
|
160
160
|
// CostTrackerPanel.setBudgetThreshold() directly on the live panel instance,
|
|
161
161
|
// which now writes through to the behavior.budgetAlertUsd config key
|
|
162
162
|
// so the background budget-breach notifier reads the same value. The env
|
|
@@ -221,7 +221,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
221
221
|
openPanel: (panelId: string) => { services.panelManager.open(panelId); },
|
|
222
222
|
knowledgeApi,
|
|
223
223
|
// Fleet acts (pick / conflict / discard) surface receipts through the command
|
|
224
|
-
// context's print and reuse its one-key jump affordance
|
|
224
|
+
// context's print and reuse its one-key jump affordance, both late-bound
|
|
225
225
|
// (the command context is assigned to commandContextRef after bootstrap, and
|
|
226
226
|
// main.ts patches armFixSessionAttach onto it).
|
|
227
227
|
fleetActsNotify: (message: string) => { commandContextRef?.print?.(message); requestRender(); },
|
|
@@ -239,7 +239,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
239
239
|
},
|
|
240
240
|
{
|
|
241
241
|
// Suppress stale WRFC replay re-notifications for chains that can no
|
|
242
|
-
// longer act
|
|
242
|
+
// longer act, gone (killed/removed → getChain null) or terminal
|
|
243
243
|
// (passed/failed). (item 1c.)
|
|
244
244
|
isChainTerminal: (chainId) => {
|
|
245
245
|
const chain = services.wrfcController.getChain(chainId);
|
|
@@ -286,7 +286,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
286
286
|
workspaceTrustManager: services.workspaceTrustManager,
|
|
287
287
|
// Registration half is stateless (reads the shared registry on demand), so
|
|
288
288
|
// it is constructed here for the command context rather than threaded through
|
|
289
|
-
// RuntimeServices
|
|
289
|
+
// RuntimeServices, no early-load requirement like the trust gate has.
|
|
290
290
|
workspaceRegistrationManager: new WorkspaceRegistrationManager({ shellPaths: services.shellPaths }),
|
|
291
291
|
memoryRegistry: services.memoryRegistry,
|
|
292
292
|
integrationHelpers: services.integrationHelpers,
|
|
@@ -322,7 +322,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
322
322
|
isPassiveCodeInjectionFlagEnabled: () => services.featureFlags.isEnabled('agent-passive-code-injection'),
|
|
323
323
|
featureFlagManager: services.featureFlags,
|
|
324
324
|
// Expose the MAIN session's per-turn passive-injection ring
|
|
325
|
-
// so `/recall injections` (no agent id) renders it
|
|
325
|
+
// so `/recall injections` (no agent id) renders it, see recall-review.ts.
|
|
326
326
|
getMainSessionTurnInjections: () => orchestrator.getTurnInjections(),
|
|
327
327
|
changeTracker: services.sessionChangeTracker,
|
|
328
328
|
planManager: services.planManager,
|
|
@@ -347,7 +347,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
347
347
|
activatePlan: (_planId, task) => {
|
|
348
348
|
setTimeout(() => {
|
|
349
349
|
void (async () => {
|
|
350
|
-
// Refresh the recall snapshot before this plan-driven turn
|
|
350
|
+
// Refresh the recall snapshot before this plan-driven turn, see
|
|
351
351
|
// the matching comment in main.ts's submitInput.
|
|
352
352
|
await refreshMemoryRecallSnapshot(services);
|
|
353
353
|
orchestrator.handleUserInput(task).catch((err) => {
|
|
@@ -370,7 +370,7 @@ export function createBootstrapShell(options: BootstrapShellOptions): BootstrapS
|
|
|
370
370
|
}).catch(() => { /* non-fatal */ });
|
|
371
371
|
// FIX 2: the header's git segment otherwise only refreshes on
|
|
372
372
|
// TURN_COMPLETED/TOOL_SUCCEEDED/TOOL_FAILED (see turn-event-wiring.ts's
|
|
373
|
-
// refreshGit())
|
|
373
|
+
// refreshGit()), if the user runs `git init` externally and never submits
|
|
374
374
|
// another turn, the header stays stuck on the startup-time fallback
|
|
375
375
|
// indefinitely. Poll at the same 5s cadence GitPanel already uses for its
|
|
376
376
|
// own self-poll (git-panel.ts) so the two mechanisms are cadence-consistent.
|