@pellux/goodvibes-tui 1.27.0 → 2.0.1
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/CHANGELOG.md +125 -2
- package/README.md +7 -9
- package/bin/goodvibes +2 -2
- package/bin/launcher-support.js +8 -4
- package/docs/README.md +11 -2
- package/docs/foundation-artifacts/operator-contract.json +6403 -2347
- package/package.json +14 -25
- package/scripts/postinstall.js +35 -35
- package/src/audio/spoken-turn-model-routing.ts +1 -1
- package/src/cli/bundle-command.ts +5 -5
- package/src/cli/completions/generate.ts +1 -1
- package/src/cli/doctor.ts +3 -3
- package/src/cli/entrypoint.ts +12 -7
- package/src/cli/help.ts +4 -5
- package/src/cli/hooks-command.ts +1 -1
- package/src/cli/index.ts +1 -4
- package/src/cli/launch-auto-update.ts +59 -7
- package/src/cli/management-commands.ts +6 -6
- package/src/cli/management-utils.ts +5 -5
- package/src/cli/management.ts +7 -7
- package/src/cli/network-posture.ts +1 -1
- package/src/cli/package-verification.ts +7 -6
- package/src/cli/plugin-bundles-command.ts +1 -1
- package/src/cli/plugin-command.ts +2 -2
- package/src/cli/service-command.ts +2 -2
- package/src/cli/service-posture.ts +4 -4
- package/src/cli/status.ts +9 -8
- package/src/cli/surface-command.ts +4 -4
- package/src/cli/tui-startup.ts +12 -3
- package/src/cli-flags.ts +3 -3
- package/src/config/goodvibes-home-audit.ts +0 -2
- package/src/config/secret-config.ts +37 -5
- package/src/config/tui-extension-settings.ts +1 -1
- package/src/core/approval-alert.ts +2 -2
- package/src/core/budget-breach-notifier.ts +3 -3
- package/src/core/conversation-compaction-render.ts +1 -1
- package/src/core/conversation-line-cache.ts +1 -1
- package/src/core/conversation-render-context.ts +1 -1
- package/src/core/conversation-rendering.ts +2 -2
- package/src/core/conversation.ts +10 -10
- package/src/core/long-task-notifier.ts +2 -2
- package/src/core/memory-diagnostics-gateway.ts +1 -1
- package/src/core/scriptable-statusline.ts +1 -1
- package/src/core/session-auto-titler.ts +1 -1
- package/src/core/session-resume-core.ts +2 -2
- package/src/core/stream-event-wiring.ts +24 -44
- package/src/core/terminal-notifier.ts +3 -3
- package/src/core/turn-cancellation.ts +1 -1
- package/src/core/turn-event-wiring.ts +5 -5
- package/src/input/command-registry.ts +6 -6
- package/src/input/commands/channel-pairing.ts +1 -1
- package/src/input/commands/cluster-runtime.ts +1 -1
- package/src/input/commands/codebase-runtime.ts +1 -1
- package/src/input/commands/devices-runtime.ts +1 -1
- package/src/input/commands/hosted-runtime.ts +330 -0
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/local-setup-transfer.ts +2 -2
- package/src/input/commands/local-setup.ts +3 -3
- package/src/input/commands/managed-runtime.ts +2 -2
- package/src/input/commands/operator-rpc.ts +24 -110
- package/src/input/commands/payment-card-intake.ts +1 -1
- package/src/input/commands/permissions-provenance.ts +2 -2
- package/src/input/commands/plugin-runtime.ts +1 -1
- package/src/input/commands/provider.ts +1 -1
- package/src/input/commands/relay-runtime.ts +18 -9
- package/src/input/commands/rewind-runtime.ts +1 -1
- package/src/input/commands/runtime-services.ts +1 -1
- package/src/input/commands/services-runtime.ts +1 -1
- package/src/input/commands/session-workflow.ts +1 -1
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/share-runtime.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +145 -55
- package/src/input/commands/update-runtime.ts +31 -28
- package/src/input/commands/work-plan-runtime.ts +2 -2
- package/src/input/commands/workstream-attempts.ts +1 -1
- package/src/input/commands/workstream-runtime.ts +2 -2
- package/src/input/commands.ts +2 -0
- package/src/input/feature-unit-layout.ts +1 -1
- package/src/input/feed-context-factory.ts +3 -3
- package/src/input/handler-content-actions.ts +2 -2
- package/src/input/handler-feed-routes.ts +1 -1
- package/src/input/handler-feed.ts +3 -3
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-onboarding-daemon-adopt.ts +3 -2
- package/src/input/handler-onboarding.ts +1 -1
- package/src/input/handler-types.ts +2 -2
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +4 -4
- package/src/input/input-history.ts +1 -1
- package/src/input/onboarding/onboarding-feature-units.ts +2 -2
- package/src/input/onboarding/onboarding-runtime-status.ts +15 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +17 -8
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +5 -3
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-types.ts +1 -1
- package/src/input/payments-config.ts +6 -6
- package/src/input/search.ts +1 -1
- package/src/input/session-picker-modal.ts +46 -0
- package/src/input/settings-modal-activation.ts +1 -1
- package/src/input/settings-modal-behavior.ts +4 -4
- package/src/input/settings-modal-commit.ts +11 -0
- package/src/input/settings-modal-data.ts +13 -80
- package/src/input/settings-modal-mutations.ts +33 -0
- package/src/input/settings-modal-secrets.ts +34 -0
- package/src/input/settings-modal-subscriptions.ts +1 -1
- package/src/input/settings-modal-types.ts +15 -1
- package/src/input/settings-modal.ts +28 -3
- package/src/input/worktree-setup-config.ts +1 -1
- package/src/main.ts +11 -9
- package/src/panels/agent-inspector-shared.ts +2 -2
- package/src/panels/base-panel.ts +2 -2
- package/src/panels/builtin/operations.ts +6 -8
- package/src/panels/builtin/session.ts +17 -0
- package/src/panels/builtin/shared.ts +5 -5
- package/src/panels/builtin-modals.ts +3 -3
- package/src/panels/confirm-state.ts +1 -1
- package/src/panels/cost-tracker-panel.ts +4 -4
- package/src/panels/diff-panel.ts +2 -2
- package/src/panels/diff-review-panel.ts +2 -2
- package/src/panels/expandable-list-panel.ts +2 -2
- package/src/panels/fleet-acts.ts +1 -1
- package/src/panels/fleet-observed-render.ts +1 -1
- package/src/panels/fleet-panel-format.ts +1 -1
- package/src/panels/fleet-panel.ts +1 -1
- package/src/panels/fleet-spawn.ts +1 -1
- package/src/panels/fleet-steer.ts +1 -1
- package/src/panels/fleet-transcript.ts +1 -1
- package/src/panels/git-panel.ts +1 -1
- package/src/panels/hosted-session-feed.ts +352 -0
- package/src/panels/hosted-session-panel.ts +221 -0
- package/src/panels/local-auth-panel.ts +3 -3
- package/src/panels/modals/devices-modal.ts +1 -1
- package/src/panels/modals/local-auth-modal.ts +1 -1
- package/src/panels/modals/pairing-modal.ts +1 -1
- package/src/panels/modals/services-modal.ts +1 -1
- package/src/panels/modals/settings-sync-modal.ts +1 -1
- package/src/panels/modals/subscription-modal.ts +1 -1
- package/src/panels/modals/work-plan-modal.ts +1 -1
- package/src/panels/notifications-panel.ts +1 -1
- package/src/panels/panel-confirm-overlay.ts +1 -1
- package/src/panels/plugins-panel.ts +2 -2
- package/src/panels/polish-core.ts +2 -2
- package/src/panels/polish-tables.ts +1 -1
- package/src/panels/polish.ts +2 -2
- package/src/panels/scrollable-list-panel.ts +3 -3
- package/src/panels/skills-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +5 -5
- package/src/panels/types.ts +1 -2
- package/src/permissions/prompt.ts +1 -1
- package/src/renderer/autocomplete-overlay.ts +1 -1
- package/src/renderer/block-actions-overlay.ts +1 -1
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/buffer.ts +1 -1
- package/src/renderer/code-block.ts +1 -1
- package/src/renderer/composer-fragments.ts +1 -1
- package/src/renderer/compositor.ts +2 -2
- package/src/renderer/config-modal.ts +1 -1
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +1 -1
- package/src/renderer/conversation-surface.ts +2 -2
- package/src/renderer/diff-view.ts +1 -1
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +1 -1
- package/src/renderer/fleet-tab-strip.ts +1 -1
- package/src/renderer/fullscreen-primitives.ts +2 -2
- package/src/renderer/fullscreen-workspace.ts +1 -1
- package/src/renderer/header-line.ts +1 -1
- package/src/renderer/help-overlay.ts +1 -1
- package/src/renderer/history-search-overlay.ts +2 -2
- package/src/renderer/layout.ts +5 -8
- package/src/renderer/markdown-inline.ts +1 -1
- package/src/renderer/markdown-table.ts +1 -1
- package/src/renderer/markdown.ts +1 -1
- package/src/renderer/mcp-workspace.ts +1 -1
- package/src/renderer/modal-factory.ts +2 -2
- package/src/renderer/model-workspace.ts +2 -2
- package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
- package/src/renderer/overlay-box.ts +1 -1
- package/src/renderer/panel-composite.ts +1 -1
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +1 -1
- package/src/renderer/profile-picker-modal.ts +1 -1
- package/src/renderer/search-overlay.ts +2 -2
- package/src/renderer/selection-modal-overlay.ts +1 -1
- package/src/renderer/session-picker-modal.ts +124 -3
- package/src/renderer/settings-modal-helpers.ts +2 -0
- package/src/renderer/settings-modal.ts +2 -2
- package/src/renderer/shell-surface.ts +2 -2
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tab-strip.ts +1 -1
- package/src/renderer/theme-mode-config.ts +1 -1
- package/src/renderer/theme.ts +11 -12
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +2 -2
- package/src/renderer/tool-result-expanded-lines.ts +1 -1
- package/src/renderer/turn-injection.ts +7 -8
- package/src/renderer/ui-factory.ts +3 -3
- package/src/runtime/bootstrap-command-context.ts +4 -4
- package/src/runtime/bootstrap-command-parts.ts +5 -5
- package/src/runtime/bootstrap-core.ts +30 -30
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +128 -157
- package/src/runtime/client/approval-updates.ts +82 -0
- package/src/runtime/client/build-floors.ts +167 -0
- package/src/runtime/client/daemon-attach-handshake.ts +115 -0
- package/src/runtime/client/fleet-union.ts +147 -0
- package/src/runtime/client/host-service-status.ts +71 -0
- package/src/runtime/client/hosted-exit.ts +86 -0
- package/src/runtime/client/hosted-roster.ts +110 -0
- package/src/runtime/client/hosted-session-stream.ts +178 -0
- package/src/runtime/client/hosted-sessions.ts +187 -0
- package/src/runtime/client/operator-endpoint.ts +213 -0
- package/src/runtime/client/spine-adoption.ts +99 -0
- package/src/runtime/cloudflare-control-plane.ts +1 -1
- package/src/runtime/context-accounting-source.ts +1 -1
- package/src/runtime/context.ts +2 -2
- package/src/runtime/conversation-rewind-port.ts +42 -14
- package/src/runtime/daemon-attach-notices.ts +55 -19
- package/src/runtime/diagnostics/panels/ops.ts +1 -1
- package/src/runtime/disposal-wiring.ts +4 -24
- package/src/runtime/index.ts +119 -105
- package/src/runtime/install-self-check-startup.ts +2 -2
- package/src/runtime/interaction-seams.ts +1 -1
- package/src/runtime/knowledge-services.ts +8 -2
- package/src/runtime/legacy-daemon-migration.ts +15 -3
- package/src/runtime/legacy-daemon-reconcile.ts +3 -2
- package/src/runtime/memory-spine-transport.ts +37 -267
- package/src/runtime/notification-dispatch.ts +2 -2
- package/src/runtime/onboarding/apply.ts +2 -2
- package/src/runtime/onboarding/derivation.ts +2 -2
- package/src/runtime/onboarding/markers.ts +2 -2
- package/src/runtime/onboarding/progress.ts +2 -2
- package/src/runtime/onboarding/snapshot.ts +1 -1
- package/src/runtime/onboarding/state.ts +2 -2
- package/src/runtime/onboarding/types.ts +2 -2
- package/src/runtime/orchestrator-core-services.ts +1 -1
- package/src/runtime/path-shadow-startup.ts +28 -221
- package/src/runtime/power-keepawake-remote.ts +3 -2
- package/src/runtime/process-lifecycle.ts +2 -2
- package/src/runtime/provider-fallback.ts +10 -66
- package/src/runtime/recovery-autosave.ts +1 -1
- package/src/runtime/recovery-offer-wiring.ts +39 -23
- package/src/runtime/recovery-prompt.ts +31 -17
- package/src/runtime/relay-reachability-bridge.ts +53 -42
- package/src/runtime/release-artifacts.ts +2 -1
- package/src/runtime/runtime-services-types.ts +82 -35
- package/src/runtime/services.ts +305 -300
- package/src/runtime/session-resume-liveness-confirm.ts +1 -1
- package/src/runtime/ui-services.ts +7 -6
- package/src/runtime/update-check.ts +23 -43
- package/src/runtime/workspace-checkpointing.ts +1 -1
- package/src/runtime/wrfc-persistence.ts +2 -2
- package/src/shell/ui-openers.ts +30 -7
- package/src/utils/clipboard.ts +1 -1
- package/src/verification/verification-ledger.ts +10 -8
- package/src/version.ts +1 -1
- package/bin/goodvibes-daemon +0 -90
- package/src/cli/config-overrides.ts +0 -267
- package/src/cli/endpoints.ts +0 -109
- package/src/cli/parser.ts +0 -395
- package/src/cli/redaction.ts +0 -170
- package/src/cli/types.ts +0 -84
- package/src/cluster/commands.ts +0 -382
- package/src/cluster/remote-daemon-target.ts +0 -225
- package/src/cluster/render.ts +0 -268
- package/src/config/atomic-write.ts +0 -70
- package/src/config/credential-availability.ts +0 -122
- package/src/config/goodvibes-home.ts +0 -149
- package/src/config/index.ts +0 -88
- package/src/config/provider-model.ts +0 -23
- package/src/config/read-versioned.ts +0 -228
- package/src/core/alert-gating.ts +0 -67
- package/src/core/consolidation-receipt.ts +0 -41
- package/src/core/focus-tracker.ts +0 -41
- package/src/core/history.ts +0 -45
- package/src/core/memory-status.ts +0 -118
- package/src/core/orchestrator.ts +0 -7
- package/src/core/pairing-devices.ts +0 -49
- package/src/core/pairing-handoff.ts +0 -101
- package/src/core/pairing-offers.ts +0 -83
- package/src/core/pairing-origin.ts +0 -78
- package/src/core/rewind-turn-anchors.ts +0 -311
- package/src/core/session-recovery.ts +0 -210
- package/src/core/stable-host.ts +0 -171
- package/src/core/transcript-journal.ts +0 -503
- package/src/daemon/cli.ts +0 -641
- package/src/daemon/handlers/context.ts +0 -29
- package/src/daemon/handlers/contracts.ts +0 -77
- package/src/daemon/handlers/credentials.ts +0 -139
- package/src/daemon/handlers/drafts/draft-store.ts +0 -427
- package/src/daemon/handlers/drafts/index.ts +0 -17
- package/src/daemon/handlers/drafts/register.ts +0 -331
- package/src/daemon/handlers/errors.ts +0 -18
- package/src/daemon/handlers/inbox/cursor-store.ts +0 -457
- package/src/daemon/handlers/inbox/index.ts +0 -284
- package/src/daemon/handlers/inbox/mapping.ts +0 -192
- package/src/daemon/handlers/inbox/poller.ts +0 -212
- package/src/daemon/handlers/inbox/provider-adapter.ts +0 -156
- package/src/daemon/handlers/inbox/providers/discord.ts +0 -252
- package/src/daemon/handlers/inbox/providers/email.ts +0 -152
- package/src/daemon/handlers/inbox/providers/imap-client.ts +0 -300
- package/src/daemon/handlers/inbox/providers/route-util.ts +0 -24
- package/src/daemon/handlers/inbox/providers/slack.ts +0 -263
- package/src/daemon/handlers/index.ts +0 -117
- package/src/daemon/handlers/register.ts +0 -168
- package/src/daemon/handlers/remote/backends/cloud-terminal.ts +0 -142
- package/src/daemon/handlers/remote/backends/docker.ts +0 -79
- package/src/daemon/handlers/remote/backends/index.ts +0 -40
- package/src/daemon/handlers/remote/backends/local-process.ts +0 -113
- package/src/daemon/handlers/remote/backends/process-runner.ts +0 -127
- package/src/daemon/handlers/remote/backends/ssh.ts +0 -125
- package/src/daemon/handlers/remote/backends/types.ts +0 -97
- package/src/daemon/handlers/remote/dispatcher.ts +0 -181
- package/src/daemon/handlers/remote/index.ts +0 -119
- package/src/daemon/handlers/remote/peer-registry.ts +0 -357
- package/src/daemon/handlers/remote/service.ts +0 -191
- package/src/daemon/handlers/routing/inbox-bridge.ts +0 -71
- package/src/daemon/handlers/routing/index.ts +0 -261
- package/src/daemon/handlers/routing/route-store.ts +0 -319
- package/src/daemon/handlers/routing/routing-resolver.ts +0 -75
- package/src/daemon/handlers/sqlite-store.ts +0 -278
- package/src/daemon/handlers/triage/index.ts +0 -57
- package/src/daemon/handlers/triage/integration.ts +0 -213
- package/src/daemon/handlers/triage/pipeline.ts +0 -274
- package/src/daemon/handlers/triage/scorer.ts +0 -287
- package/src/daemon/handlers/triage/tagger/discord.ts +0 -187
- package/src/daemon/handlers/triage/tagger/imap.ts +0 -384
- package/src/daemon/handlers/triage/tagger/index.ts +0 -184
- package/src/daemon/handlers/triage/tagger/shared.ts +0 -70
- package/src/daemon/handlers/triage/tagger/slack.ts +0 -69
- package/src/daemon/handlers/triage/types.ts +0 -50
- package/src/daemon/lifecycle.ts +0 -41
- package/src/daemon/provision-wake-model.ts +0 -81
- package/src/daemon/safe-serve.ts +0 -61
- package/src/daemon/send/channels.ts +0 -200
- package/src/daemon/send/command.ts +0 -332
- package/src/daemon/send/composition.ts +0 -99
- package/src/daemon/send/failure-text.ts +0 -93
- package/src/daemon/send/inert-text.ts +0 -225
- package/src/daemon/send/stdin.ts +0 -24
- package/src/daemon/service-commands.ts +0 -329
- package/src/export/cost-utils.ts +0 -319
- package/src/input/selection.ts +0 -135
- package/src/plugins/loader.ts +0 -15
- package/src/renderer/bottom-bar.ts +0 -58
- package/src/renderer/conversation-tree.ts +0 -228
- package/src/runtime/agent-graph-composition.ts +0 -78
- package/src/runtime/channel-composition.ts +0 -46
- package/src/runtime/cluster-composition.ts +0 -124
- package/src/runtime/cluster-group-composition.ts +0 -284
- package/src/runtime/code-index-services.ts +0 -167
- package/src/runtime/daemon-handler-composition.ts +0 -76
- package/src/runtime/device-posture-composition.ts +0 -110
- package/src/runtime/durability-housekeeping.ts +0 -183
- package/src/runtime/durability-services.ts +0 -155
- package/src/runtime/embedded-service-factories.ts +0 -58
- package/src/runtime/feature-settings.ts +0 -154
- package/src/runtime/fleet-needs-input-push.ts +0 -70
- package/src/runtime/fleet-services.ts +0 -41
- package/src/runtime/idle-power-services.ts +0 -85
- package/src/runtime/mail-composition.ts +0 -65
- package/src/runtime/memory-fold.ts +0 -55
- package/src/runtime/operator-token-cleanup.ts +0 -109
- package/src/runtime/path-shadow.ts +0 -418
- package/src/runtime/perf/panel-health-monitor.ts +0 -18
- package/src/runtime/provider-optimizer-wiring.ts +0 -55
- package/src/runtime/reachability-notice.ts +0 -100
- package/src/runtime/remote-execution-composition.ts +0 -62
- package/src/runtime/session-liveness-marker.ts +0 -257
- package/src/runtime/session-pointer-surface.ts +0 -22
- package/src/runtime/session-storage-services.ts +0 -41
- package/src/runtime/surface-feature-flags.ts +0 -96
- package/src/runtime/terminal-output-guard.ts +0 -235
- package/src/runtime/trust/workspace-registration.ts +0 -192
- package/src/runtime/trust/workspace-trust.ts +0 -229
- package/src/runtime/ui/index.ts +0 -39
- package/src/runtime/ui/model-picker/data-provider.ts +0 -182
- package/src/runtime/ui/model-picker/health-enrichment.ts +0 -231
- package/src/runtime/ui/model-picker/index.ts +0 -59
- package/src/runtime/ui/model-picker/types.ts +0 -153
- package/src/runtime/ui/provider-health/data-provider.ts +0 -244
- package/src/runtime/ui/provider-health/fallback-visualizer.ts +0 -71
- package/src/runtime/ui/provider-health/index.ts +0 -46
- package/src/runtime/ui/provider-health/types.ts +0 -146
- package/src/runtime/ui-events.ts +0 -1
- package/src/runtime/ui-read-model-helpers.ts +0 -1
- package/src/runtime/ui-read-models-observability-maintenance.ts +0 -1
- package/src/runtime/ui-read-models-observability-options.ts +0 -1
- package/src/runtime/ui-read-models-observability-remote.ts +0 -1
- package/src/runtime/ui-read-models-observability-security.ts +0 -1
- package/src/runtime/ui-read-models-observability-system.ts +0 -1
- package/src/runtime/ui-read-models-observability.ts +0 -1
- package/src/runtime/ui-service-queries.ts +0 -1
- package/src/runtime/voice-setup-services.ts +0 -98
- package/src/runtime/workstream-attempts-validation.ts +0 -77
- package/src/runtime/workstream-draft-edits.ts +0 -95
- package/src/runtime/workstream-draft-store.ts +0 -274
- package/src/runtime/workstream-draft-types.ts +0 -42
- package/src/runtime/workstream-services.ts +0 -373
- package/src/tools/index.ts +0 -1
- package/src/types/grid.ts +0 -48
- package/src/types/sql-js.d.ts +0 -15
- package/src/work-plans/work-plan-store.ts +0 -702
package/src/runtime/services.ts
CHANGED
|
@@ -1,80 +1,117 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* services.ts — the terminal app's composition root, as a CLIENT.
|
|
3
|
+
*
|
|
4
|
+
* Every gateway-serving piece — the `GatewayMethodCatalog`, the
|
|
5
|
+
* inbox/triage/drafts/routing handlers, the cluster group and its election,
|
|
6
|
+
* the device-posture runtime and its housekeeping, the mail service deps —
|
|
7
|
+
* lives in the daemon product. This composition serves no verbs, elects
|
|
8
|
+
* nothing, polls no mailbox, and supervises no remote runner. It builds what
|
|
9
|
+
* a TURN needs in this process and reaches the daemon for the rest.
|
|
10
|
+
*
|
|
11
|
+
* ── The floor comes from the SDK ───────────────────────────────────────────
|
|
12
|
+
*
|
|
13
|
+
* The loop essentials — the agent graph, the model stack, config/secrets/
|
|
14
|
+
* services, hooks, plugins, MCP, the file-tool caches, permissions as a client,
|
|
15
|
+
* the spine clients — are composed by `createClientRuntimeServices`, the SDK's
|
|
16
|
+
* one implementation of that shape. Not a fork of it and not a copy of it: the
|
|
17
|
+
* agent product composes the same function, so a wiring step added there
|
|
18
|
+
* cannot silently miss this product.
|
|
19
|
+
*
|
|
20
|
+
* The SDK's own note on that shape applies here literally: it is a FLOOR, not a
|
|
21
|
+
* ceiling. Everything below the `createClientRuntimeServices` call is what THIS
|
|
22
|
+
* surface adds on top — panels, keybindings, the WRFC controller wired over the
|
|
23
|
+
* client's own `agentManager`, the workstream engine, the fleet read model, the
|
|
24
|
+
* voice stack with its local playback sink, the knowledge stack the recall
|
|
25
|
+
* surfaces read. None of those need daemon furniture; they are simply not
|
|
26
|
+
* required for a turn to run, which is why they are here and not in the SDK's
|
|
27
|
+
* client floor.
|
|
28
|
+
*
|
|
29
|
+
* ── The two things that look like daemon furniture and are not ─────────────
|
|
30
|
+
*
|
|
31
|
+
* `sessionBroker` and `approvalBroker` are still constructed. They are this
|
|
32
|
+
* surface's own record of the sessions it is running and the asks it raised —
|
|
33
|
+
* what the transcript, the session panel and the approval card read. They are
|
|
34
|
+
* NOT authoritative: session identity is mirrored to the daemon's spine
|
|
35
|
+
* (register/heartbeat/inputs) and an ask is raised on the daemon
|
|
36
|
+
* (`approvals.raise`) so every other surface can see and answer it. Where the
|
|
37
|
+
* two disagree the daemon's record is the truth, and the client seams in
|
|
38
|
+
* runtime/client/ are what keep them in step.
|
|
39
|
+
*/
|
|
40
|
+
import { FocusTracker } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
4
41
|
import { AutomationDeliveryManager, AutomationManager } from '@pellux/goodvibes-sdk/platform/automation';
|
|
5
|
-
import {
|
|
42
|
+
import { ChannelPolicyManager } from '@pellux/goodvibes-sdk/platform/channels';
|
|
6
43
|
import { ApprovalBroker, GatewayMethodCatalog, SharedSessionBroker } from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { attachWsOnlyGatewayVerbHandlers } from '@pellux/goodvibes-terminal-shell';
|
|
10
|
-
import { composeMailDeps } from './mail-composition.ts';
|
|
11
|
-
import { composeCredentialServices } from './credential-composition.ts';
|
|
44
|
+
import { createClientRuntimeServices } from '@pellux/goodvibes-sdk/platform/runtime/client-services';
|
|
45
|
+
import { wireIdlePowerAndLiveTurn } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
12
46
|
import { createDisposalScope, registerSurfaceRuntimePollers } from './disposal-wiring.ts';
|
|
47
|
+
import { composeCredentialServices } from './credential-composition.ts';
|
|
13
48
|
import { WatcherRegistry } from '@pellux/goodvibes-sdk/platform/watchers';
|
|
14
|
-
import { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
15
49
|
import { createWebKnowledgeGapRepairer } from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
16
50
|
import { createKnowledgeServices } from './knowledge-services.ts';
|
|
51
|
+
import { cancelAllAgentRuns } from '@pellux/goodvibes-sdk/platform/tools';
|
|
17
52
|
import { MediaProviderRegistry, ensureBuiltinMediaProviders } from '@pellux/goodvibes-sdk/platform/media';
|
|
18
53
|
import { MultimodalService } from '@pellux/goodvibes-sdk/platform/multimodal';
|
|
19
|
-
import {
|
|
20
|
-
import { FileStateCache, FileUndoManager, MemoryEmbeddingProviderRegistry, MemoryRegistry, MemoryStore, ModeManager, ProjectIndex, resolveCanonicalMemoryDbPath } from '@pellux/goodvibes-sdk/platform/state';
|
|
54
|
+
import { MemoryEmbeddingProviderRegistry, MemoryRegistry, MemoryStore, resolveCanonicalMemoryDbPath } from '@pellux/goodvibes-sdk/platform/state';
|
|
21
55
|
import { buildExecPromptAnswerHandler } from '@pellux/goodvibes-sdk/platform/runtime/permissions/exec-prompt-wiring';
|
|
22
56
|
import { buildLocalhostFetchApproval } from '@pellux/goodvibes-sdk/platform/runtime/permissions/localhost-fetch-approval';
|
|
23
57
|
import { createNotificationDispatcher, wireRuntimeNotificationBridge, wireMemoryPressureNotice } from './notification-dispatch.ts';
|
|
24
|
-
import { createDurabilityServices } from '
|
|
58
|
+
import { createDurabilityServices } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
25
59
|
import { MemorySpineClient, createLocalMemoryAccess } from '@pellux/goodvibes-sdk/platform/runtime/memory-spine';
|
|
26
60
|
import { createWorkspaceCheckpointing } from './workspace-checkpointing.ts';
|
|
27
|
-
import { createSessionConversationRewindPort } from './conversation-rewind-port.ts';
|
|
28
61
|
import { createDomainDispatch } from './store/index.ts';
|
|
29
|
-
import { DistributedRuntimeManager, IntegrationHelperService, IdempotencyStore, ComponentHealthMonitor, WorktreeRegistry,
|
|
30
|
-
import { createSessionStorageServices } from '
|
|
62
|
+
import { DistributedRuntimeManager, IntegrationHelperService, IdempotencyStore, ComponentHealthMonitor, WorktreeRegistry, createFeatureFlagManager, createShellPathService } from '@/runtime/index.ts';
|
|
63
|
+
import { createSessionStorageServices } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
31
64
|
import { VoiceProviderRegistry, VoiceService, ensureBuiltinVoiceProviders } from '@pellux/goodvibes-sdk/platform/voice';
|
|
32
65
|
import { CacheRegistry, PauseController } from '@pellux/goodvibes-sdk/platform/runtime/memory';
|
|
33
66
|
import { wireMemoryGovernance } from './memory-governance-services.ts';
|
|
34
|
-
import { wireVoiceSetup } from '
|
|
35
|
-
import { WebSearchProviderRegistry, WebSearchService } from '@pellux/goodvibes-sdk/platform/web-search';
|
|
67
|
+
import { wireVoiceSetup } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
36
68
|
import { PanelManager } from '../panels/panel-manager.ts';
|
|
37
|
-
import { HookActivityTracker } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
38
|
-
import { HookDispatcher, createHookWorkbench } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
39
|
-
import { PluginManager } from '@pellux/goodvibes-sdk/platform/plugins';
|
|
40
69
|
import { BookmarkManager } from '@pellux/goodvibes-sdk/platform/bookmarks';
|
|
41
70
|
import { ProfileManager } from '@pellux/goodvibes-sdk/platform/profiles';
|
|
42
|
-
import {
|
|
71
|
+
import { SessionChangeTracker } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
43
72
|
import { ApiTokenAuditor, UserAuthManager } from '@pellux/goodvibes-sdk/platform/security';
|
|
44
73
|
import { WebhookNotifier } from '@pellux/goodvibes-sdk/platform/integrations';
|
|
45
|
-
import { createRemoteExecutionServices } from '
|
|
46
|
-
import {
|
|
47
|
-
import { BenchmarkStore, CacheHitTracker, FavoritesStore, ModelLimitsService, ProviderCapabilityRegistry, ProviderOptimizer, ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
74
|
+
import { createRemoteExecutionServices } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
75
|
+
import { WrfcController } from '@pellux/goodvibes-sdk/platform/agents';
|
|
48
76
|
import { KeybindingsManager } from '../input/keybindings.ts';
|
|
49
77
|
import { AdaptivePlanner, DeterministicReplayEngine, ExecutionPlanManager, SessionLineageTracker, SessionMemoryStore } from '@pellux/goodvibes-sdk/platform/core';
|
|
50
78
|
import { deriveFeatureStates, bindFeatureSettingsBridge } from '@pellux/goodvibes-sdk/platform/runtime/state';
|
|
51
|
-
import { createChannelComposition } from '
|
|
52
|
-
import { applyProviderOptimizerConfigMode, bindProviderOptimizerFeatureFlag } from '
|
|
53
|
-
import { createFleetServices } from '
|
|
54
|
-
import { createWorkstreamServices } from '
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
58
|
-
import {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
|
|
79
|
+
import { createChannelComposition } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
80
|
+
import { applyProviderOptimizerConfigMode, bindProviderOptimizerFeatureFlag } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
81
|
+
import { createFleetServices } from '@pellux/goodvibes-terminal-shell';
|
|
82
|
+
import { createWorkstreamServices } from '@pellux/goodvibes-sdk/platform/orchestration';
|
|
83
|
+
import { codeIndexDbPath, createCodeIndexServices, createStoreRerooter, isCodeInjectionSettingEnabled } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
84
|
+
import { WorkspaceTrustManager } from '@pellux/goodvibes-sdk/platform/runtime/operations';
|
|
85
|
+
import { ensureConfiguredModelIsRoutable } from '@pellux/goodvibes-sdk/platform/providers';
|
|
86
|
+
import { GOODVIBES_TUI_SURFACE_ROOT } from '../config/surface.ts';
|
|
87
|
+
import { createDaemonVerbCaller } from './client/operator-endpoint.ts';
|
|
88
|
+
import { createTerminalApprovalUpdateSubscriber } from './client/approval-updates.ts';
|
|
89
|
+
import { createHostedSessionsClient } from './client/hosted-sessions.ts';
|
|
90
|
+
import { getSharedHostedSessionRoster } from './client/hosted-roster.ts';
|
|
91
|
+
import {
|
|
92
|
+
createClientApprovalRaiser,
|
|
93
|
+
createConversationRewindHost,
|
|
94
|
+
createDaemonConfigClient,
|
|
95
|
+
createDaemonCredentialsClient,
|
|
96
|
+
createDevicesClient,
|
|
97
|
+
createWireSessionDispatch,
|
|
98
|
+
readSurfaceAgentOutcome,
|
|
99
|
+
} from '@pellux/goodvibes-sdk/platform/runtime/client';
|
|
100
|
+
import { ClientBuildGuard } from './client/build-floors.ts';
|
|
101
|
+
import { createFleetUnionReadModel } from './client/fleet-union.ts';
|
|
102
|
+
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
103
|
+
import { VERSION } from '../version.ts';
|
|
104
|
+
import { createSessionConversationRewindPort, hasSessionConversation } from './conversation-rewind-port.ts';
|
|
105
|
+
import { createFleetReadModel } from '../panels/fleet-read-model.ts';
|
|
106
|
+
import type { PermissionPromptDecision, PermissionPromptRequest } from '@pellux/goodvibes-sdk/platform/permissions';
|
|
65
107
|
import type { RuntimeServicesOptions, RuntimeServices } from './runtime-services-types.ts';
|
|
66
108
|
export type { RuntimeServicesOptions, RuntimeServices } from './runtime-services-types.ts';
|
|
67
109
|
|
|
68
110
|
export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeServices {
|
|
69
111
|
const disposalScope = createDisposalScope('RuntimeServices'); const workingDirectory = options.workingDir; // disposal seam: see ./disposal-wiring.ts
|
|
70
112
|
const homeDirectory = options.homeDirectory;
|
|
71
|
-
const shellPaths = createShellPathService({
|
|
72
|
-
workingDirectory,
|
|
73
|
-
homeDirectory,
|
|
74
|
-
});
|
|
75
113
|
// Built before anything that touches session state — see session-storage-services.ts.
|
|
76
|
-
const { surface, sessionManager } = createSessionStorageServices({ workingDirectory, homeDirectory });
|
|
77
|
-
const workspaceTrustManager = new WorkspaceTrustManager({ shellPaths });
|
|
114
|
+
const { surface, sessionManager } = createSessionStorageServices({ workingDirectory, homeDirectory, surfaceRoot: GOODVIBES_TUI_SURFACE_ROOT });
|
|
78
115
|
const configManager = options.configManager;
|
|
79
116
|
const featureFlags = options.featureFlags ?? createFeatureFlagManager();
|
|
80
117
|
if (options.featureFlags === undefined) {
|
|
@@ -83,13 +120,97 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
83
120
|
featureFlags.loadFromConfig({ flags: deriveFeatureStates(configManager) });
|
|
84
121
|
bindFeatureSettingsBridge(configManager, featureFlags);
|
|
85
122
|
}
|
|
123
|
+
|
|
124
|
+
// ── The client seams: one resolution of "which daemon", shared by all of them.
|
|
125
|
+
const verbs = createDaemonVerbCaller({ configManager, homeDirectory });
|
|
126
|
+
const daemonConfig = createDaemonConfigClient(verbs);
|
|
127
|
+
const devices = createDevicesClient(verbs);
|
|
128
|
+
// Daemon-hosted sessions: the session picker (built in the input layer, which
|
|
129
|
+
// has no config manager to resolve a daemon from) reads the roster; this is
|
|
130
|
+
// the one place that can give it a client. See client/hosted-roster.ts.
|
|
131
|
+
getSharedHostedSessionRoster().bindClient(createHostedSessionsClient(verbs));
|
|
132
|
+
|
|
133
|
+
// Built here rather than read off the client composition below because the
|
|
134
|
+
// approval seam it feeds is an INPUT to that composition: the path service is
|
|
135
|
+
// pure (it derives paths, it opens nothing), so building it twice costs
|
|
136
|
+
// nothing and keeps the ordering honest.
|
|
137
|
+
const shellPaths = createShellPathService({ workingDirectory, homeDirectory });
|
|
138
|
+
// The surface's own record of the asks it raised — what the approval card and
|
|
139
|
+
// the panel read. The AUTHORITATIVE record is the daemon's; the raiser below
|
|
140
|
+
// keeps the two in step (see the SDK's client/approval-raiser.ts).
|
|
141
|
+
const approvalBroker = new ApprovalBroker({
|
|
142
|
+
storePath: shellPaths.resolveProjectPath('tui', 'control-plane', 'approvals.json'),
|
|
143
|
+
});
|
|
144
|
+
// The late-bound terminal prompt: the UI layer patches the real implementation
|
|
145
|
+
// in after boot, exactly as it always did.
|
|
146
|
+
const localPromptRef: { requestPermission: (request: PermissionPromptRequest) => Promise<PermissionPromptDecision> } = {
|
|
147
|
+
requestPermission: async () => ({ approved: false, remember: false }),
|
|
148
|
+
};
|
|
149
|
+
const liveSessionIdRef: { value: string | null } = { value: null };
|
|
150
|
+
const requestApproval = createClientApprovalRaiser({
|
|
151
|
+
verbs,
|
|
152
|
+
// The SDK's raiser cannot honestly default this: it names how THIS surface
|
|
153
|
+
// reports its own decision back to the daemon (`actorSurface`), so every
|
|
154
|
+
// other surface can see where the answer came from. Reproduces the
|
|
155
|
+
// previous hard-coded `actor: 'tui', actorSurface: 'tui'` write-back exactly.
|
|
156
|
+
actor: 'tui',
|
|
157
|
+
sessionId: () => liveSessionIdRef.value,
|
|
158
|
+
// The "local prompt" is this surface's own broker plus the terminal ask:
|
|
159
|
+
// that is what puts the ask on the approval card and in the panel while the
|
|
160
|
+
// daemon holds the record every other surface reads.
|
|
161
|
+
localPrompt: () => (request) => approvalBroker.requestApproval({
|
|
162
|
+
request,
|
|
163
|
+
...(liveSessionIdRef.value ? { sessionId: liveSessionIdRef.value } : {}),
|
|
164
|
+
localPrompt: (prompt) => localPromptRef.requestPermission(prompt),
|
|
165
|
+
}),
|
|
166
|
+
// The push channel for a decision made on another surface. Without it the
|
|
167
|
+
// raiser learns by re-reading the record on an interval; with it a phone's
|
|
168
|
+
// answer reaches this terminal in the time one SSE frame takes. The interval
|
|
169
|
+
// stays as the fallback — see client/approval-updates.ts.
|
|
170
|
+
subscribeApprovalUpdates: createTerminalApprovalUpdateSubscriber({ configManager, homeDirectory }),
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// ── The SDK's client floor: everything a turn needs in this process.
|
|
174
|
+
const client = createClientRuntimeServices({
|
|
175
|
+
runtimeBus: options.runtimeBus,
|
|
176
|
+
runtimeStore: options.runtimeStore,
|
|
177
|
+
configManager,
|
|
178
|
+
surfaceRoot: GOODVIBES_TUI_SURFACE_ROOT,
|
|
179
|
+
workingDir: workingDirectory,
|
|
180
|
+
homeDirectory,
|
|
181
|
+
featureFlags,
|
|
182
|
+
requestApproval,
|
|
183
|
+
...(options.daemonHomeDirectory === undefined ? {} : { daemonHome: options.daemonHomeDirectory }),
|
|
184
|
+
});
|
|
86
185
|
const runtimeDispatch = createDomainDispatch(options.runtimeStore);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
186
|
+
const workspaceTrustManager = new WorkspaceTrustManager({ shellPaths, surfaceRoot: GOODVIBES_TUI_SURFACE_ROOT });
|
|
187
|
+
const {
|
|
188
|
+
agentManager, agentMessageBus, agentOrchestrator, archetypeLoader,
|
|
189
|
+
contextAccountingHolder, providerRegistry, providerCapabilityRegistry, cacheHitTracker,
|
|
190
|
+
favoritesStore, benchmarkStore, modelLimitsService, toolLLM,
|
|
191
|
+
secretsManager, serviceRegistry, subscriptionManager, hookDispatcher, hookActivityTracker,
|
|
192
|
+
hookWorkbench, pluginManager, workflow, artifactStore, webSearchProviders, webSearchService,
|
|
193
|
+
mcpRegistry: clientMcpRegistry, sandboxSessionRegistry: clientSandboxRegistry,
|
|
194
|
+
processManager, modeManager, fileUndoManager, overflowHandler, policyRuntimeState,
|
|
195
|
+
fileCache, projectIndex, sessionOrchestration,
|
|
196
|
+
} = client;
|
|
197
|
+
void clientMcpRegistry; void clientSandboxRegistry;
|
|
198
|
+
disposalScope.registry.add('client runtime services', () => client.dispose());
|
|
199
|
+
|
|
200
|
+
ensureConfiguredModelIsRoutable(providerRegistry, configManager);
|
|
201
|
+
providerRegistry.initCustomProviders();
|
|
202
|
+
// Background, TTL-respecting live model discovery so provider model lists
|
|
203
|
+
// refresh from their own listing APIs.
|
|
204
|
+
providerRegistry.initProviderModelDiscovery();
|
|
205
|
+
|
|
206
|
+
// A daemon-scoped credential goes to the daemon over `credentials.set`, which
|
|
207
|
+
// writes the value AND points the config key at it in one verified sequence.
|
|
208
|
+
// Everything else stays in this surface's own store.
|
|
209
|
+
const daemonCredentials = createDaemonCredentialsClient(verbs);
|
|
210
|
+
|
|
211
|
+
// Memory governance seams built EARLY so the scheduler gates and the knowledge
|
|
212
|
+
// background jobs can consult the pause controller before the MemoryGovernor
|
|
213
|
+
// (constructed at the composition tail) drives it.
|
|
93
214
|
const cacheRegistry = new CacheRegistry();
|
|
94
215
|
const pauseController = new PauseController();
|
|
95
216
|
const MEMORY_BACKGROUND_JOB_IDS = ['knowledge-self-improvement', 'memory-consolidation', 'code-index-reindex'];
|
|
@@ -97,11 +218,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
97
218
|
const admitExpensiveWork = (label: string): { allowed: boolean; reason?: string | undefined } =>
|
|
98
219
|
admitExpensiveWorkRef.current?.(label) ?? { allowed: true };
|
|
99
220
|
const isKnowledgeBackgroundPaused = (): boolean => pauseController.isPaused('knowledge-self-improvement');
|
|
100
|
-
const gatewayMethods = new GatewayMethodCatalog();
|
|
101
221
|
const panelManager = new PanelManager();
|
|
102
|
-
// (the purge): MIGRATE-TO-MODAL surface + redirect registration moved to
|
|
103
|
-
// registerBuiltinPanels (builtin-panels.ts), where the panels' resolved deps
|
|
104
|
-
// are available for the surfaces to close over.
|
|
105
222
|
const keybindingsManager = new KeybindingsManager({
|
|
106
223
|
configPath: shellPaths.resolveUserPath('tui', 'keybindings.json'),
|
|
107
224
|
});
|
|
@@ -112,72 +229,27 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
112
229
|
runtimeBus: options.runtimeBus,
|
|
113
230
|
featureFlags,
|
|
114
231
|
});
|
|
115
|
-
//
|
|
116
|
-
|
|
232
|
+
// An EMPTY catalog. This product answers no verbs; the field exists only
|
|
233
|
+
// because the SDK's startExternalServices takes a daemon-grade graph even in
|
|
234
|
+
// the adopt-only mode this surface runs in, and because plugin loading is
|
|
235
|
+
// handed one. With adoptOnly no DaemonServer is constructed, so nothing is
|
|
236
|
+
// ever served off it.
|
|
237
|
+
const gatewayMethods = new GatewayMethodCatalog();
|
|
238
|
+
// The credential/identity seam (credential-composition.ts) — this
|
|
239
|
+
// installation's own pairing tokens and step-up service.
|
|
240
|
+
const { stepUpService, pairingTokens } = composeCredentialServices({
|
|
117
241
|
workingDirectory, homeDirectory, configManager,
|
|
118
|
-
daemonHomeDirectory: options.daemonHomeDirectory,
|
|
242
|
+
...(options.daemonHomeDirectory === undefined ? {} : { daemonHomeDirectory: options.daemonHomeDirectory }),
|
|
119
243
|
pairingTokenPath: shellPaths.resolveUserPath('control-plane', 'pairing-tokens.json'),
|
|
120
244
|
});
|
|
121
|
-
const subscriptionManager = new SubscriptionManager(shellPaths.resolveUserPath('tui', 'subscriptions.json'));
|
|
122
|
-
const serviceRegistry = new ServiceRegistry(shellPaths.resolveProjectPath('tui', 'services.json'), {
|
|
123
|
-
secretsManager,
|
|
124
|
-
subscriptionManager,
|
|
125
|
-
});
|
|
126
|
-
const providerCapabilityRegistry = new ProviderCapabilityRegistry();
|
|
127
|
-
const cacheHitTracker = new CacheHitTracker();
|
|
128
|
-
const favoritesStore = new FavoritesStore({ dir: shellPaths.resolveUserPath('tui') });
|
|
129
|
-
const benchmarkStore = new BenchmarkStore({ dir: shellPaths.resolveUserPath('tui') });
|
|
130
|
-
const modelLimitsService = new ModelLimitsService({
|
|
131
|
-
cachePath: shellPaths.resolveUserPath('tui', 'model-limits.json'),
|
|
132
|
-
});
|
|
133
|
-
const providerRegistry = new ProviderRegistry({
|
|
134
|
-
configManager,
|
|
135
|
-
subscriptionManager,
|
|
136
|
-
secretsManager,
|
|
137
|
-
serviceRegistry,
|
|
138
|
-
capabilityRegistry: providerCapabilityRegistry,
|
|
139
|
-
cacheHitTracker,
|
|
140
|
-
favoritesStore,
|
|
141
|
-
benchmarkStore,
|
|
142
|
-
modelLimitsService,
|
|
143
|
-
featureFlags,
|
|
144
|
-
runtimeBus: options.runtimeBus,
|
|
145
|
-
});
|
|
146
|
-
ensureConfiguredModelIsRoutable(providerRegistry, configManager);
|
|
147
|
-
providerRegistry.initCustomProviders();
|
|
148
|
-
// Kick off the background, TTL-respecting live model discovery sweep so
|
|
149
|
-
// provider model lists refresh from their own listing APIs — matching the
|
|
150
|
-
// SDK and agent compositions (this call was the one omitted here).
|
|
151
|
-
providerRegistry.initProviderModelDiscovery();
|
|
152
|
-
const toolLLM = new ToolLLM({
|
|
153
|
-
configManager,
|
|
154
|
-
providerRegistry,
|
|
155
|
-
});
|
|
156
245
|
const localUserAuthManager = options.localUserAuthManager ?? new UserAuthManager({
|
|
157
246
|
bootstrapFilePath: shellPaths.resolveUserPath('tui', 'auth-users.json'),
|
|
158
247
|
bootstrapCredentialPath: shellPaths.resolveUserPath('tui', 'auth-bootstrap.txt'),
|
|
159
248
|
});
|
|
160
249
|
const profileManager = new ProfileManager(shellPaths.resolveUserPath('tui', 'profiles'));
|
|
161
250
|
const bookmarkManager = new BookmarkManager(shellPaths.resolveUserPath('tui', 'bookmarks'));
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
);
|
|
165
|
-
const hookActivityTracker = new HookActivityTracker();
|
|
166
|
-
// featureFlags is REQUIRED here in practice, even though the SDK types it
|
|
167
|
-
// optional. isFeatureGateEnabled(null, ...) is permissive by design — a
|
|
168
|
-
// narrow embed with no manager wired gets the capability rather than a
|
|
169
|
-
// silent off — so omitting it did not disable the watcher framework when
|
|
170
|
-
// watchers.enabled is turned off; it made the setting configure nothing.
|
|
171
|
-
// Threading it preserves current effective behaviour rather than changing
|
|
172
|
-
// it: watchers.enabled defaults true, the watcher-framework flag's own
|
|
173
|
-
// defaultState is 'enabled', and the flag declares no notOperable record —
|
|
174
|
-
// so with nothing configured the gate reads exactly as before, and the
|
|
175
|
-
// difference is only that turning it OFF now turns it off. This composes
|
|
176
|
-
// with bootstrap-core.ts's own `if (configManager.get('watchers.enabled'))`
|
|
177
|
-
// check around the built-in polling watcher registration: that check reads
|
|
178
|
-
// the same key, so the two never disagree, and this fix only reaches the
|
|
179
|
-
// watcher registry's OTHER entry points (registerWatcher/startWatcher/etc.)
|
|
180
|
-
// that bootstrap-core.ts's narrower check does not cover.
|
|
251
|
+
// The watcher framework is the daemon's to RUN; this registry is the surface's
|
|
252
|
+
// read/edit handle on the same store, so `/watch` still lists and edits.
|
|
181
253
|
const watcherRegistry = new WatcherRegistry({
|
|
182
254
|
storePath: shellPaths.resolveProjectPath('tui', 'watchers.json'),
|
|
183
255
|
featureFlags,
|
|
@@ -186,31 +258,60 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
186
258
|
runtimeStore: options.runtimeStore,
|
|
187
259
|
runtimeBus: options.runtimeBus,
|
|
188
260
|
});
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
agentManager,
|
|
194
|
-
} = createAgentGraph({
|
|
195
|
-
runtimeBus: options.runtimeBus, workingDirectory, configManager, providerRegistry,
|
|
196
|
-
});
|
|
197
|
-
const hookDispatcher = new HookDispatcher({ agentManager, toolLLM, projectRoot: workingDirectory }, hookActivityTracker);
|
|
198
|
-
configManager.attachHookDispatcher(hookDispatcher);
|
|
199
|
-
const hookWorkbench = createHookWorkbench({
|
|
200
|
-
hookDispatcher,
|
|
261
|
+
// WRFC over the client's own agent graph — the "floor, not ceiling" case,
|
|
262
|
+
// verbatim: the review/fix workstream controller needs the agent manager and
|
|
263
|
+
// the message bus, and nothing daemon-side at all.
|
|
264
|
+
const wrfcController = new WrfcController(options.runtimeBus, agentMessageBus, {
|
|
265
|
+
agentManager,
|
|
201
266
|
configManager,
|
|
267
|
+
projectRoot: workingDirectory,
|
|
202
268
|
});
|
|
203
|
-
|
|
204
|
-
storePath: shellPaths.resolveProjectPath('tui', 'control-plane', 'approvals.json'),
|
|
205
|
-
});
|
|
269
|
+
agentManager.setWrfcController(wrfcController);
|
|
206
270
|
const sessionBroker = new SharedSessionBroker({
|
|
207
271
|
storePath: shellPaths.resolveProjectPath('tui', 'control-plane', 'sessions.json'),
|
|
208
272
|
routeBindings,
|
|
209
273
|
agentStatusProvider: agentManager,
|
|
210
274
|
messageSender: agentMessageBus,
|
|
211
|
-
conversationGateConfig: configManager, // without this the gate runs on DEFAULTS
|
|
212
|
-
});
|
|
213
|
-
|
|
275
|
+
conversationGateConfig: configManager, // without this the gate runs on DEFAULTS
|
|
276
|
+
});
|
|
277
|
+
// Work that arrives for a session THIS surface hosts reaches the loop through
|
|
278
|
+
// the same runner whether it came from the local broker or from the daemon's
|
|
279
|
+
// queue. The wire half is inert until bootstrap.ts adopts a daemon (see
|
|
280
|
+
// the SDK's client/session-dispatch.ts); binding one runner to both is what stops a
|
|
281
|
+
// continuation delivered over the wire from taking a different path — and a
|
|
282
|
+
// different set of routing options — than one raised locally.
|
|
283
|
+
const wireSessionDispatch = createWireSessionDispatch({
|
|
284
|
+
hostedSessionIds: () => (liveSessionIdRef.value ? [liveSessionIdRef.value] : []),
|
|
285
|
+
// The reply half. A continuation dispatched here runs in THIS process, so
|
|
286
|
+
// the daemon's own completion poll can never see it finish; this is how the
|
|
287
|
+
// answer gets reported back, and how a message that arrived over a channel
|
|
288
|
+
// is answered into that channel instead of into nothing.
|
|
289
|
+
readAgentOutcome: (agentId) => readSurfaceAgentOutcome(agentManager.getStatus(agentId)),
|
|
290
|
+
});
|
|
291
|
+
disposalScope.registry.add('wire session dispatch', () => wireSessionDispatch.stop());
|
|
292
|
+
// A daemon update swaps the daemon binary and leaves this terminal running
|
|
293
|
+
// the build it started with. The daemon announces the minimum client build it
|
|
294
|
+
// accepts on the /status read the attach handshake already makes; when this
|
|
295
|
+
// build is below it the guard latches, the owner is told on the same surface
|
|
296
|
+
// daemon notices already render, and the runner below stops taking
|
|
297
|
+
// shared-session work rather than executing it under superseded rules. See
|
|
298
|
+
// client/build-floors.ts; bootstrap.ts feeds the reads and attaches the
|
|
299
|
+
// notice sink.
|
|
300
|
+
const clientBuildGuard = new ClientBuildGuard({ clientVersion: VERSION });
|
|
301
|
+
// The parameter type comes from the broker's own runner rather than being
|
|
302
|
+
// re-declared: a hand-written copy would drift from the routing options the
|
|
303
|
+
// spawn actually forwards, and the drift would be silent.
|
|
304
|
+
type ContinuationRequest = Parameters<NonNullable<Parameters<typeof sessionBroker.setContinuationRunner>[0]>>[0];
|
|
305
|
+
const continuationRunner = async ({ task, input }: ContinuationRequest): Promise<{ agentId: string } | null> => {
|
|
306
|
+
// Too old for the live daemon: refuse the work instead of doing it the old
|
|
307
|
+
// way. The owner has already been told to restart this terminal.
|
|
308
|
+
if (!clientBuildGuard.maySharedSessionWork()) {
|
|
309
|
+
logger.warn('declined a shared-session continuation: this build is below the daemon floor', {
|
|
310
|
+
sessionId: input.sessionId,
|
|
311
|
+
floor: clientBuildGuard.current().floor,
|
|
312
|
+
});
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
214
315
|
const record = agentManager.spawn({
|
|
215
316
|
mode: 'spawn',
|
|
216
317
|
task,
|
|
@@ -230,10 +331,11 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
230
331
|
context: `shared-session:${input.sessionId}`,
|
|
231
332
|
});
|
|
232
333
|
return { agentId: record.id };
|
|
233
|
-
}
|
|
234
|
-
|
|
334
|
+
};
|
|
335
|
+
sessionBroker.setContinuationRunner(continuationRunner);
|
|
336
|
+
wireSessionDispatch.setContinuationRunner(continuationRunner);
|
|
235
337
|
const memoryEmbeddingRegistry = new MemoryEmbeddingProviderRegistry({ configManager });
|
|
236
|
-
// Open the ONE home-scoped canonical store; legacy per-project TUI memory folds in at boot (
|
|
338
|
+
// Open the ONE home-scoped canonical store; legacy per-project TUI memory folds in at boot (foldLegacyProjectMemory).
|
|
237
339
|
const memoryDbPath = resolveCanonicalMemoryDbPath(homeDirectory);
|
|
238
340
|
const memoryStore = new MemoryStore(memoryDbPath, {
|
|
239
341
|
embeddingRegistry: memoryEmbeddingRegistry,
|
|
@@ -243,22 +345,8 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
243
345
|
// modal): bootstrap.ts activates the wire transport when a compatible
|
|
244
346
|
// external daemon is adopted, same signal as the session spine.
|
|
245
347
|
const memorySpine = new MemorySpineClient({ local: createLocalMemoryAccess(memoryRegistry) });
|
|
246
|
-
// featureFlags is REQUIRED here in practice, even though the SDK types it
|
|
247
|
-
// optional. isFeatureGateEnabled(null, ...) is permissive by design, so
|
|
248
|
-
// omitting it did not disable delivery tracking when
|
|
249
|
-
// integrations.deliveryTracking is turned off — it made the setting
|
|
250
|
-
// configure nothing: deliverText/deliverJobRun kept running either way.
|
|
251
|
-
// Threading it preserves current effective behaviour rather than changing
|
|
252
|
-
// it: the config default is true, the delivery-engine flag's own
|
|
253
|
-
// defaultState is 'enabled', and the flag declares no notOperable record —
|
|
254
|
-
// so with nothing configured the gate reads exactly as before.
|
|
255
348
|
const deliveryManager = new AutomationDeliveryManager({
|
|
256
349
|
configManager,
|
|
257
|
-
// This manager builds the delivery router the daemon actually replies
|
|
258
|
-
// through (bootstrap.ts hands it to the daemon facade). Without the
|
|
259
|
-
// secrets manager it cannot resolve a goodvibes://secrets/... credential,
|
|
260
|
-
// so Telegram accepted every inbound message and dropped every reply with
|
|
261
|
-
// "Missing Telegram bot token" while ntfy — which needs no secret — worked.
|
|
262
350
|
secretsManager,
|
|
263
351
|
serviceRegistry,
|
|
264
352
|
runtimeBus: options.runtimeBus,
|
|
@@ -267,18 +355,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
267
355
|
artifactStore,
|
|
268
356
|
featureFlags,
|
|
269
357
|
});
|
|
270
|
-
// Same shape as deliveryManager above: automation.enabled defaults true,
|
|
271
|
-
// the automation-domain flag's own defaultState is 'enabled', so threading
|
|
272
|
-
// featureFlags here does not change what a default install does — it only
|
|
273
|
-
// makes turning automation.enabled off actually turn AutomationManager's own
|
|
274
|
-
// create/update/run/list surface off. This composes with bootstrap.ts's own
|
|
275
|
-
// `if (configManager.get('automation.enabled'))` gate around scheduling
|
|
276
|
-
// automationManager.start(): that check reads the same key, and
|
|
277
|
-
// AutomationManager.start() re-checks the same gate internally (it no-ops
|
|
278
|
-
// and stops rather than starting when disabled), so the two can never
|
|
279
|
-
// disagree — this fix only reaches the manager's OTHER entry points
|
|
280
|
-
// (createJob/updateJob/runNow/etc.) that the bootstrap.ts gate does not
|
|
281
|
-
// cover, the same way watchers.enabled and the watcher registry above do.
|
|
282
358
|
const automationManager = new AutomationManager({
|
|
283
359
|
configManager,
|
|
284
360
|
defaultSurfaceKind: 'tui',
|
|
@@ -287,8 +363,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
287
363
|
runtimeStore: options.runtimeStore,
|
|
288
364
|
runtimeBus: options.runtimeBus,
|
|
289
365
|
deliveryManager,
|
|
290
|
-
// Same live registry: a bare model id on an automation job resolves through
|
|
291
|
-
// the shared resolver instead of a format-only rejection.
|
|
292
366
|
providerRegistry,
|
|
293
367
|
featureFlags,
|
|
294
368
|
spawnTask: (input) => {
|
|
@@ -315,32 +389,18 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
315
389
|
knowledgeService, agentKnowledgeService, homeGraphService,
|
|
316
390
|
projectPlanningService, projectPlanningProjectId, workPlanStore,
|
|
317
391
|
} = createKnowledgeServices({ configManager, providerRegistry, artifactStore, memoryRegistry, runtimeBus: options.runtimeBus, workingDirectory, homeDirectory, isBackgroundPaused: isKnowledgeBackgroundPaused, admitExpensiveWork });
|
|
392
|
+
// Voice: the PROVIDERS are local (a spoken turn plays out of this terminal's
|
|
393
|
+
// own speaker) — synthesis reaches `voice.tts.stream` when a daemon serves it
|
|
394
|
+
// and falls back to a local provider otherwise; see audio/spoken-turn-wiring.ts.
|
|
318
395
|
const voiceProviders = new VoiceProviderRegistry();
|
|
319
396
|
ensureBuiltinVoiceProviders(voiceProviders, { readConfig: (key) => configManager.get(key as Parameters<typeof configManager.get>[0]) });
|
|
320
397
|
const voiceService = new VoiceService(voiceProviders);
|
|
321
|
-
const webSearchProviders = new WebSearchProviderRegistry({
|
|
322
|
-
env: process.env,
|
|
323
|
-
serviceRegistry,
|
|
324
|
-
});
|
|
325
|
-
const webSearchService = new WebSearchService(webSearchProviders, {
|
|
326
|
-
serviceRegistry,
|
|
327
|
-
featureFlags,
|
|
328
|
-
});
|
|
329
398
|
for (const [semantic, ingest] of [[knowledgeSemanticService, knowledgeService], [agentKnowledgeSemanticService, agentKnowledgeService], [homeGraphSemanticService, homeGraphService]] as const) {
|
|
330
399
|
semantic.setGapRepairer(createWebKnowledgeGapRepairer({ searchService: webSearchService, ingestService: ingest }));
|
|
331
400
|
}
|
|
332
401
|
const mediaProviders = new MediaProviderRegistry();
|
|
333
402
|
ensureBuiltinMediaProviders(mediaProviders, artifactStore, providerRegistry);
|
|
334
403
|
const multimodalService = new MultimodalService(artifactStore, mediaProviders, voiceService, knowledgeService);
|
|
335
|
-
const pluginManager = new PluginManager({
|
|
336
|
-
pathOptions: {
|
|
337
|
-
cwd: shellPaths.workingDirectory,
|
|
338
|
-
homeDir: shellPaths.homeDirectory,
|
|
339
|
-
},
|
|
340
|
-
stateFilePath: shellPaths.resolveUserPath('tui', 'plugins.json'),
|
|
341
|
-
});
|
|
342
|
-
const workflow = createWorkflowServices();
|
|
343
|
-
hookDispatcher.setTriggerManager(workflow.triggerManager);
|
|
344
404
|
const channelPolicy = new ChannelPolicyManager({
|
|
345
405
|
storePath: shellPaths.resolveProjectPath('tui', 'channels', 'policies.json'),
|
|
346
406
|
});
|
|
@@ -352,34 +412,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
352
412
|
approvalBridge: approvalBroker,
|
|
353
413
|
automationBridge: automationManager,
|
|
354
414
|
});
|
|
355
|
-
// The paired-phone feature for this host, on the SAME runtime phones pair onto
|
|
356
|
-
// and the SAME approval broker every other confirmation rides. Every `device.*`
|
|
357
|
-
// setting is read live through this; see device-posture-composition.ts.
|
|
358
|
-
const { devicePosture } = createDevicePostureServices({
|
|
359
|
-
configManager,
|
|
360
|
-
distributedRuntime,
|
|
361
|
-
approvals: approvalBroker,
|
|
362
|
-
stateDirectory: shellPaths.resolveProjectPath('tui', 'devices'),
|
|
363
|
-
gatewayMethods,
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
// Which machines on this network are "us", and which of them reads the
|
|
367
|
-
// shared inbox. Both inert until startCluster() — no socket, no key material
|
|
368
|
-
// read; see cluster-group-composition.ts for why they are built together.
|
|
369
|
-
const { clusterGroup, clusterCoordinator } = createClusterServices({
|
|
370
|
-
configManager, shellPaths, secretsManager,
|
|
371
|
-
});
|
|
372
|
-
// Daemon handler surfaces (see daemon-handler-composition.ts); the inbox
|
|
373
|
-
// poller registers itself with the coordinator rather than starting eagerly.
|
|
374
|
-
const daemonHandlers = createDaemonHandlerComposition({
|
|
375
|
-
gatewayMethods,
|
|
376
|
-
secretsManager,
|
|
377
|
-
configManager,
|
|
378
|
-
workingDirectory,
|
|
379
|
-
homeDirectory,
|
|
380
|
-
distributedRuntime,
|
|
381
|
-
clusterCoordinator,
|
|
382
|
-
});
|
|
383
415
|
|
|
384
416
|
// Remote runners and the sandboxes tool calls are confined to; see
|
|
385
417
|
// remote-execution-composition.ts for why the four are built as one.
|
|
@@ -387,24 +419,13 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
387
419
|
= createRemoteExecutionServices({
|
|
388
420
|
agentManager, workingDirectory, hookDispatcher, configManager, runtimeBus: options.runtimeBus,
|
|
389
421
|
});
|
|
390
|
-
// featureFlags is REQUIRED here in practice, even though the SDK types it
|
|
391
|
-
// optional. isFeatureGateEnabled(null, ...) is permissive by design, so
|
|
392
|
-
// omitting it did not disable managed blocking when
|
|
393
|
-
// security.tokenAudit.enabled is turned off. Threading it preserves current
|
|
394
|
-
// effective behaviour rather than changing it: managed is hardcoded false
|
|
395
|
-
// here (advisory reporting only; excess-scope/overdue tokens are reported,
|
|
396
|
-
// never blocked, regardless of this flag — see isBlocked()'s
|
|
397
|
-
// `this._config.managed && this._managedBlockingEnabled()` guard), the
|
|
398
|
-
// config default for security.tokenAudit.enabled is true, and the
|
|
399
|
-
// token-scope-rotation-audit flag's own defaultState is 'enabled' — so with
|
|
400
|
-
// nothing configured the gate reads exactly as before either way.
|
|
401
422
|
const tokenAuditor = new ApiTokenAuditor({ managed: false, featureFlags });
|
|
402
423
|
const componentHealthMonitor = new ComponentHealthMonitor();
|
|
403
424
|
const worktreeRegistry = new WorktreeRegistry(workingDirectory);
|
|
404
425
|
const webhookNotifier = new WebhookNotifier();
|
|
405
426
|
const focusTracker = new FocusTracker();
|
|
406
427
|
const replayEngine = new DeterministicReplayEngine(workingDirectory);
|
|
407
|
-
const providerOptimizer =
|
|
428
|
+
const providerOptimizer = client.providerOptimizer;
|
|
408
429
|
bindProviderOptimizerFeatureFlag(featureFlags, providerOptimizer);
|
|
409
430
|
applyProviderOptimizerConfigMode(configManager, providerOptimizer);
|
|
410
431
|
const sessionMemoryStore = new SessionMemoryStore();
|
|
@@ -412,63 +433,60 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
412
433
|
const planManager = new ExecutionPlanManager(workingDirectory);
|
|
413
434
|
const adaptivePlanner = new AdaptivePlanner();
|
|
414
435
|
const idempotencyStore = new IdempotencyStore();
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
});
|
|
425
|
-
const processManager = new ProcessManager();
|
|
426
|
-
// The phase/work-item orchestration engine, constructed
|
|
427
|
-
// before the process registry so its fleet nodes (workstream/phase/
|
|
428
|
-
// work-item) can be folded in below via the registry's optional
|
|
429
|
-
// orchestrationEngine dep.
|
|
436
|
+
// ONE router, not two. This surface used to build a second ChannelDeliveryRouter
|
|
437
|
+
// from the same four arguments AutomationDeliveryManager builds its own from,
|
|
438
|
+
// and expose that second one — so the router on the service surface and the
|
|
439
|
+
// router replies actually leave through were different objects, and a delivery
|
|
440
|
+
// strategy registered on the exposed one reached nothing. The SDK's
|
|
441
|
+
// RuntimeServices contract requires the field; it now names the real router.
|
|
442
|
+
const channelDeliveryRouter = deliveryManager.getDeliveryRouter();
|
|
443
|
+
// The phase/work-item orchestration engine, constructed before the process
|
|
444
|
+
// registry so its fleet nodes can be folded in below.
|
|
430
445
|
const { orchestrationEngine, workstreamCommands } = createWorkstreamServices({
|
|
431
446
|
agentManager, configManager, adaptivePlanner, runtimeBus: options.runtimeBus, projectRoot: workingDirectory,
|
|
432
447
|
});
|
|
433
|
-
// Repo source-tree code index, sharing memoryEmbeddingRegistry
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
// Store snapshots, the periodic append-only sweep, durable remembered-approval rules + the live credential chain — see durability-services.ts.
|
|
448
|
+
// Repo source-tree code index, sharing memoryEmbeddingRegistry with MemoryStore.
|
|
449
|
+
const { codeIndexStore, codeIndexReindexScheduler } = createCodeIndexServices({ workingDirectory, surfaceRoot: GOODVIBES_TUI_SURFACE_ROOT, configManager, memoryEmbeddingRegistry, isReindexPaused: () => pauseController.isPaused('code-index-reindex'), admitExpensiveWork });
|
|
450
|
+
const codeInjectionOrchestratorDeps = { codeIndex: codeIndexStore, isCodeInjectionSettingEnabled: () => isCodeInjectionSettingEnabled(configManager), codeIndexReindexScheduler };
|
|
451
|
+
// Store snapshots, the periodic append-only sweep, durable remembered-approval rules + the live credential chain.
|
|
438
452
|
const { storeSnapshotScheduler, appendOnlyRetentionScheduler, userPermissionRuleStore, stopDurabilityHousekeeping, stopConfigWatch } = createDurabilityServices({
|
|
439
|
-
configManager, secretsManager, providerRegistry, memoryDbPath, codeIndexDbPath: codeIndexDbPath(workingDirectory), surface, shellPaths,
|
|
440
|
-
...(options.currentSessionId ? { currentSessionId: options.currentSessionId } : {}),
|
|
453
|
+
configManager, secretsManager, providerRegistry, memoryDbPath, codeIndexDbPath: codeIndexDbPath(workingDirectory, GOODVIBES_TUI_SURFACE_ROOT), surface, shellPaths,
|
|
454
|
+
...(options.currentSessionId ? { currentSessionId: options.currentSessionId } : {}),
|
|
441
455
|
});
|
|
442
|
-
const
|
|
443
|
-
const { processRegistry } = createFleetServices({ // Shared archive-aware fleet registry (+ daemon observed rows) — see fleet-services.ts
|
|
456
|
+
const { processRegistry } = createFleetServices({ // Shared archive-aware fleet registry — see fleet-services.ts
|
|
444
457
|
agentManager, wrfcController,
|
|
445
|
-
orchestrationEngine,
|
|
446
|
-
codeIndexService: codeIndexStore,
|
|
458
|
+
orchestrationEngine,
|
|
459
|
+
codeIndexService: codeIndexStore,
|
|
447
460
|
processManager, watcherRegistry, workflow, approvalBroker, sessionBroker,
|
|
448
|
-
messageBus: agentMessageBus,
|
|
449
|
-
automationManager,
|
|
461
|
+
messageBus: agentMessageBus,
|
|
462
|
+
automationManager,
|
|
450
463
|
runtimeBus: options.runtimeBus,
|
|
451
|
-
|
|
464
|
+
providerRegistry,
|
|
452
465
|
});
|
|
453
|
-
//
|
|
454
|
-
//
|
|
455
|
-
//
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
466
|
+
// What the Fleet panel reads: this surface's own live registry UNION the
|
|
467
|
+
// adopted daemon's rows. The daemon runs work no registry here knows about
|
|
468
|
+
// (scheduled jobs, channel-driven runs, sessions other surfaces started, the
|
|
469
|
+
// external agents it observes), and a panel showing only half the fleet is
|
|
470
|
+
// worse than one showing none — the half it shows looks complete.
|
|
471
|
+
const fleetReadModel = createFleetUnionReadModel({
|
|
472
|
+
local: createFleetReadModel(processRegistry, options.runtimeBus),
|
|
473
|
+
verbs,
|
|
474
|
+
});
|
|
475
|
+
disposalScope.registry.add('fleet union refresh', () => fleetReadModel.stop());
|
|
476
|
+
// Conversation-scope rewind, from ANY surface. The daemon holds the
|
|
477
|
+
// checkpoint store and answers the files half; the messages live in this
|
|
478
|
+
// process, so this offers them and answers the daemon's questions about them.
|
|
479
|
+
// Started on adoption (bootstrap.ts), released on disposal.
|
|
480
|
+
const conversationRewindHost = createConversationRewindHost({
|
|
481
|
+
verbs,
|
|
482
|
+
port: createSessionConversationRewindPort(),
|
|
483
|
+
hosts: hasSessionConversation,
|
|
484
|
+
label: 'the terminal app',
|
|
485
|
+
});
|
|
486
|
+
disposalScope.registry.add('conversation rewind host', () => { void conversationRewindHost.stop(); });
|
|
462
487
|
const workspaceCheckpointManager = createWorkspaceCheckpointing({ workspaceRoot: workingDirectory, surface, runtimeBus: options.runtimeBus, configManager });
|
|
463
|
-
// memory-consolidation honors governor backpressure: it ticks only when idle
|
|
464
|
-
// AND the 'memory-consolidation' job is not paused AND expensive work is
|
|
465
|
-
// admitted (mirrors the SDK's own createRuntimeServices idle gate).
|
|
466
488
|
const { memoryConsolidationScheduler, powerManager, sessionLiveTurnControls } = wireIdlePowerAndLiveTurn({ configManager, memoryRegistry, runtimeBus: options.runtimeBus, isIdle: () => sessionBroker.countBusySessions() === 0 && !pauseController.isPaused('memory-consolidation') && admitExpensiveWork('memory consolidation').allowed, snapshotTick: () => storeSnapshotScheduler.tick(), heartbeat: async () => { await automationManager.triggerHeartbeat({ source: 'wake-catchup' }); }, powerSeam: options.powerSeam });
|
|
467
489
|
|
|
468
|
-
// Construct + start the MemoryGovernor (default ON — a safety feature) with
|
|
469
|
-
// the standard KNOWN cache adapters (knowledge stores + shared session
|
|
470
|
-
// broker), then late-bind the admission gate the expensive entry points
|
|
471
|
-
// captured earlier. Mirrors the SDK's own createRuntimeServices composition tail.
|
|
472
490
|
const { memoryGovernor } = wireMemoryGovernance({
|
|
473
491
|
configManager,
|
|
474
492
|
runtimeBus: options.runtimeBus,
|
|
@@ -478,8 +496,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
478
496
|
receiptPath: shellPaths.resolveProjectPath('tui', 'memory', 'tripwire-receipt.json'),
|
|
479
497
|
knowledgeStores: [knowledgeStore, agentKnowledgeStore, homeGraphKnowledgeStore],
|
|
480
498
|
sessionBroker,
|
|
481
|
-
// Graceful tripwire shutdown flushes in-flight state via ASYNC store
|
|
482
|
-
// snapshots so the governor's 10s shutdown ceiling stays enforceable.
|
|
483
499
|
onTripwireShutdown: async () => { await storeSnapshotScheduler.snapshotAllAsync('tripwire'); },
|
|
484
500
|
});
|
|
485
501
|
admitExpensiveWorkRef.current = (label) => memoryGovernor.admitExpensiveWork(label);
|
|
@@ -487,17 +503,9 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
487
503
|
// Managed local-voice provisioning (voice.local.status/install) — single-flight
|
|
488
504
|
// one-act install + no-network status; see voice-setup-services.ts.
|
|
489
505
|
const { voiceSetup, stopWakeHousekeeping } = wireVoiceSetup({ configManager, shellPaths, voiceProviders, admitExpensiveWork,
|
|
490
|
-
// Boot provisioning of the wake-word model + its recovery sweep, opted into
|
|
491
|
-
// by the real entrypoints only (same treatment as powerSeam) so a one-shot
|
|
492
|
-
// CLI command and a test composing this graph fetch nothing and start no timer.
|
|
493
506
|
provisionWakeModelsAtBoot: options.provisionWakeModelsAtBoot === true });
|
|
507
|
+
void voiceSetup;
|
|
494
508
|
|
|
495
|
-
// Terminal-shell wrapper over the SDK registerGatewayVerbGroups (gateway-verbs.ts); checkin.*/fleet-needs-input/pairing.* register only when their deps are present. memoryGovernor lights up ops.memory.get; voiceSetup lights up voice.local.status/install.
|
|
496
|
-
// calendar.*/email.* are platform-served; these two let it register (mail-composition.ts).
|
|
497
|
-
const { emailServiceDeps, describeEmailConfigProblem } = composeMailDeps({ configManager, secretsManager });
|
|
498
|
-
attachWsOnlyGatewayVerbHandlers(gatewayMethods, { homeDirectory, emailServiceDeps, describeEmailConfigProblem, processRegistry, workspaceCheckpointManager, conversationRewindPort: createSessionConversationRewindPort(), sessionBroker, secretsManager, stepUpService, approvalBroker, requestApproval: (input) => approvalBroker.requestApproval(input), watcherRegistry, userPermissionRuleStore, shellPaths, configManager, runtimeStore: options.runtimeStore, channelDeliveryRouter, providerRegistry, automationManager, sessionLister: sessionBroker, sessionIntake: sessionBroker, workingDirectory, memoryRegistry, pairingTokens, sessionLiveTurnControls, powerManager, memoryGovernor, voiceSetup, relayAvailable: () => configManager.get('relay.enabled') === true, pairingWebOrigin: () => resolvePairingWebOrigin(configManager).origin, disposal: disposalScope.registry, ...wireFleetNeedsInputPush({ registry: processRegistry, runtimeBus: options.runtimeBus, sessionBroker }) });
|
|
499
|
-
// surface-scoped: continuity's recovery-file check must read the SAME paths
|
|
500
|
-
// the app writes with, not the unscoped legacy pair.
|
|
501
509
|
const integrationHelpers = new IntegrationHelperService({
|
|
502
510
|
surface, configManager, automationManager, approvalBroker, sessionBroker, distributedRuntime,
|
|
503
511
|
remoteRunnerRegistry, remoteSupervisor, panelManager, localUserAuthManager, providerRegistry,
|
|
@@ -505,12 +513,13 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
505
513
|
runtimeStore: options.runtimeStore, runtimeBus: options.runtimeBus,
|
|
506
514
|
getConversationTitle: options.getConversationTitle,
|
|
507
515
|
});
|
|
508
|
-
// A loopback fetch that isn't allow-listed asks once through the
|
|
509
|
-
//
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
//
|
|
513
|
-
|
|
516
|
+
// A loopback fetch that isn't allow-listed asks once through the CLIENT raiser;
|
|
517
|
+
// "allow for this project" persists and later fetches never ask.
|
|
518
|
+
const localhostFetchApproval = buildLocalhostFetchApproval({ requestApproval: (input) => requestApproval(input), configManager });
|
|
519
|
+
// Exec stuck on a terminal prompt rides the same raiser; the typed answer feeds
|
|
520
|
+
// the continuing run. Built once and shared with every setDependencies site —
|
|
521
|
+
// a wholesale replace that forgets it hangs interactive prompts.
|
|
522
|
+
const execPromptAnswerHandler = buildExecPromptAnswerHandler({ requestApproval: (input) => requestApproval(input) });
|
|
514
523
|
agentOrchestrator.setDependencies({
|
|
515
524
|
surfaceRoot: surface.surfaceRoot,
|
|
516
525
|
execPromptAnswerHandler,
|
|
@@ -542,13 +551,9 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
542
551
|
contextAccountingHolder,
|
|
543
552
|
});
|
|
544
553
|
|
|
545
|
-
// Give the panel_only notification target a live producer
|
|
546
|
-
// runtime-domain events route through the notification router into the shared
|
|
547
|
-
// panel feed (panel_only and burst-collapsed decisions land there).
|
|
554
|
+
// Give the panel_only notification target a live producer.
|
|
548
555
|
const notificationDispatcher = createNotificationDispatcher(configManager);
|
|
549
556
|
wireRuntimeNotificationBridge(options.runtimeBus, notificationDispatcher);
|
|
550
|
-
// OPS_MEMORY_PRESSURE is lifted into the notice feed on its own targeted
|
|
551
|
-
// bridge (the high-churn 'ops' domain stays out of the wholesale allowlist).
|
|
552
557
|
wireMemoryPressureNotice(options.runtimeBus, notificationDispatcher);
|
|
553
558
|
|
|
554
559
|
const services: RuntimeServices = {
|
|
@@ -570,6 +575,19 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
570
575
|
channelDeliveryRouter,
|
|
571
576
|
watcherRegistry,
|
|
572
577
|
approvalBroker,
|
|
578
|
+
requestApproval,
|
|
579
|
+
daemonVerbs: verbs,
|
|
580
|
+
wireSessionDispatch,
|
|
581
|
+
clientBuildGuard,
|
|
582
|
+
conversationRewindHost,
|
|
583
|
+
gatewayMethods,
|
|
584
|
+
stepUpService,
|
|
585
|
+
pairingTokens,
|
|
586
|
+
devices,
|
|
587
|
+
daemonConfig,
|
|
588
|
+
daemonCredentials,
|
|
589
|
+
localPromptRef,
|
|
590
|
+
liveSessionIdRef,
|
|
573
591
|
localhostFetchApproval,
|
|
574
592
|
execPromptAnswerHandler,
|
|
575
593
|
notificationDispatcher,
|
|
@@ -577,7 +595,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
577
595
|
sessionBroker,
|
|
578
596
|
deliveryManager,
|
|
579
597
|
automationManager,
|
|
580
|
-
gatewayMethods,
|
|
581
598
|
artifactStore,
|
|
582
599
|
knowledgeService,
|
|
583
600
|
agentKnowledgeService,
|
|
@@ -590,8 +607,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
590
607
|
memorySpine,
|
|
591
608
|
serviceRegistry,
|
|
592
609
|
secretsManager,
|
|
593
|
-
stepUpService,
|
|
594
|
-
pairingTokens,
|
|
595
610
|
subscriptionManager,
|
|
596
611
|
localUserAuthManager,
|
|
597
612
|
profileManager,
|
|
@@ -628,11 +643,6 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
628
643
|
providerRegistry,
|
|
629
644
|
toolLLM,
|
|
630
645
|
distributedRuntime,
|
|
631
|
-
devicePosture,
|
|
632
|
-
daemonHandlers,
|
|
633
|
-
clusterCoordinator,
|
|
634
|
-
clusterGroup,
|
|
635
|
-
startCluster: () => startClusterServices({ clusterGroup, clusterCoordinator }),
|
|
636
646
|
remoteRunnerRegistry,
|
|
637
647
|
remoteSupervisor,
|
|
638
648
|
sessionMemoryStore,
|
|
@@ -662,17 +672,12 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
662
672
|
pauseController,
|
|
663
673
|
sessionLiveTurnControls,
|
|
664
674
|
processRegistry,
|
|
675
|
+
fleetReadModel,
|
|
665
676
|
modeManager,
|
|
666
677
|
fileUndoManager,
|
|
667
678
|
workspaceCheckpointManager,
|
|
668
679
|
integrationHelpers,
|
|
669
|
-
rerootStores: createStoreRerooter({ codeIndexStore, projectIndex }),
|
|
670
|
-
// Cancels the agent runs this graph was hosting. By dispose() time the
|
|
671
|
-
// fleet registry, orchestration engine, process registry and bus these runs
|
|
672
|
-
// report through are already down, so a run still described as "running" is
|
|
673
|
-
// orphaned rather than preserved — and this is the only shutdown-reachable
|
|
674
|
-
// way to abort its in-flight provider call instead of letting it sleep out
|
|
675
|
-
// a retry backoff nobody is waiting on.
|
|
680
|
+
rerootStores: createStoreRerooter({ codeIndexStore, projectIndex, surfaceRoot: GOODVIBES_TUI_SURFACE_ROOT }),
|
|
676
681
|
cancelHostedAgentRuns: () => cancelAllAgentRuns(agentManager),
|
|
677
682
|
dispose: (): void => disposalScope.dispose(),
|
|
678
683
|
};
|