@pellux/goodvibes-sdk 0.38.0 → 1.1.0
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/dist/contracts/artifacts/operator-contract.json +4468 -916
- package/dist/daemon.d.ts +2 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +4 -0
- package/dist/events/communication.d.ts +1 -1
- package/dist/events/surfaces.d.ts +25 -3
- package/dist/events/surfaces.d.ts.map +1 -1
- package/dist/events/surfaces.js +22 -1
- package/dist/events/workflows.d.ts +7 -6
- package/dist/events/workflows.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/platform/agents/archetypes.d.ts.map +1 -1
- package/dist/platform/agents/archetypes.js +7 -0
- package/dist/platform/agents/index.d.ts +1 -0
- package/dist/platform/agents/index.d.ts.map +1 -1
- package/dist/platform/agents/index.js +1 -0
- package/dist/platform/agents/orchestrator-runner.d.ts +16 -3
- package/dist/platform/agents/orchestrator-runner.d.ts.map +1 -1
- package/dist/platform/agents/orchestrator-runner.js +20 -6
- package/dist/platform/agents/orchestrator.d.ts +42 -10
- package/dist/platform/agents/orchestrator.d.ts.map +1 -1
- package/dist/platform/agents/orchestrator.js +68 -20
- package/dist/platform/agents/planner-decomposition-runner.d.ts +38 -0
- package/dist/platform/agents/planner-decomposition-runner.d.ts.map +1 -0
- package/dist/platform/agents/planner-decomposition-runner.js +113 -0
- package/dist/platform/agents/turn-knowledge-injection.d.ts +88 -3
- package/dist/platform/agents/turn-knowledge-injection.d.ts.map +1 -1
- package/dist/platform/agents/turn-knowledge-injection.js +147 -30
- package/dist/platform/agents/worktree.d.ts +126 -8
- package/dist/platform/agents/worktree.d.ts.map +1 -1
- package/dist/platform/agents/worktree.js +240 -19
- package/dist/platform/agents/wrfc-controller.d.ts +24 -1
- package/dist/platform/agents/wrfc-controller.d.ts.map +1 -1
- package/dist/platform/agents/wrfc-controller.js +161 -35
- package/dist/platform/agents/wrfc-gate-runtime.d.ts +9 -0
- package/dist/platform/agents/wrfc-gate-runtime.d.ts.map +1 -1
- package/dist/platform/agents/wrfc-gate-runtime.js +7 -3
- package/dist/platform/agents/wrfc-gates.d.ts +1 -1
- package/dist/platform/agents/wrfc-gates.d.ts.map +1 -1
- package/dist/platform/agents/wrfc-gates.js +7 -1
- package/dist/platform/agents/wrfc-types.d.ts +23 -3
- package/dist/platform/agents/wrfc-types.d.ts.map +1 -1
- package/dist/platform/automation/types.d.ts +9 -1
- package/dist/platform/automation/types.d.ts.map +1 -1
- package/dist/platform/calendar/calendar-api-shared.d.ts +25 -0
- package/dist/platform/calendar/calendar-api-shared.d.ts.map +1 -0
- package/dist/platform/calendar/calendar-api-shared.js +100 -0
- package/dist/platform/calendar/calendar-connector.d.ts +79 -0
- package/dist/platform/calendar/calendar-connector.d.ts.map +1 -0
- package/dist/platform/calendar/calendar-connector.js +155 -0
- package/dist/platform/calendar/google-calendar-api.d.ts +25 -0
- package/dist/platform/calendar/google-calendar-api.d.ts.map +1 -0
- package/dist/platform/calendar/google-calendar-api.js +89 -0
- package/dist/platform/calendar/http-fetch-adapter.d.ts +25 -0
- package/dist/platform/calendar/http-fetch-adapter.d.ts.map +1 -0
- package/dist/platform/calendar/http-fetch-adapter.js +25 -0
- package/dist/platform/calendar/ics-parser.d.ts +35 -0
- package/dist/platform/calendar/ics-parser.d.ts.map +1 -0
- package/dist/platform/calendar/ics-parser.js +236 -0
- package/dist/platform/calendar/index.d.ts +41 -0
- package/dist/platform/calendar/index.d.ts.map +1 -0
- package/dist/platform/calendar/index.js +49 -0
- package/dist/platform/calendar/merged-calendar-model.d.ts +67 -0
- package/dist/platform/calendar/merged-calendar-model.d.ts.map +1 -0
- package/dist/platform/calendar/merged-calendar-model.js +181 -0
- package/dist/platform/calendar/microsoft-graph-api.d.ts +25 -0
- package/dist/platform/calendar/microsoft-graph-api.d.ts.map +1 -0
- package/dist/platform/calendar/microsoft-graph-api.js +95 -0
- package/dist/platform/calendar/oauth-flow.d.ts +62 -0
- package/dist/platform/calendar/oauth-flow.d.ts.map +1 -0
- package/dist/platform/calendar/oauth-flow.js +305 -0
- package/dist/platform/calendar/oauth-providers.d.ts +43 -0
- package/dist/platform/calendar/oauth-providers.d.ts.map +1 -0
- package/dist/platform/calendar/oauth-providers.js +120 -0
- package/dist/platform/calendar/oauth-token-store.d.ts +72 -0
- package/dist/platform/calendar/oauth-token-store.d.ts.map +1 -0
- package/dist/platform/calendar/oauth-token-store.js +189 -0
- package/dist/platform/calendar/oauth-types.d.ts +274 -0
- package/dist/platform/calendar/oauth-types.d.ts.map +1 -0
- package/dist/platform/calendar/oauth-types.js +22 -0
- package/dist/platform/calendar/rrule.d.ts +39 -0
- package/dist/platform/calendar/rrule.d.ts.map +1 -0
- package/dist/platform/calendar/rrule.js +261 -0
- package/dist/platform/calendar/subscription-store.d.ts +118 -0
- package/dist/platform/calendar/subscription-store.d.ts.map +1 -0
- package/dist/platform/calendar/subscription-store.js +293 -0
- package/dist/platform/calendar/types.d.ts +170 -0
- package/dist/platform/calendar/types.d.ts.map +1 -0
- package/dist/platform/calendar/types.js +21 -0
- package/dist/platform/companion/companion-chat-attachments.d.ts +29 -0
- package/dist/platform/companion/companion-chat-attachments.d.ts.map +1 -0
- package/dist/platform/companion/companion-chat-attachments.js +121 -0
- package/dist/platform/companion/companion-chat-branching.d.ts +66 -0
- package/dist/platform/companion/companion-chat-branching.d.ts.map +1 -0
- package/dist/platform/companion/companion-chat-branching.js +142 -0
- package/dist/platform/companion/companion-chat-broker-bridge.d.ts +40 -0
- package/dist/platform/companion/companion-chat-broker-bridge.d.ts.map +1 -0
- package/dist/platform/companion/companion-chat-broker-bridge.js +14 -0
- package/dist/platform/companion/companion-chat-broker-sync.d.ts +38 -0
- package/dist/platform/companion/companion-chat-broker-sync.d.ts.map +1 -0
- package/dist/platform/companion/companion-chat-broker-sync.js +80 -0
- package/dist/platform/companion/companion-chat-gc.d.ts +63 -0
- package/dist/platform/companion/companion-chat-gc.d.ts.map +1 -0
- package/dist/platform/companion/companion-chat-gc.js +38 -0
- package/dist/platform/companion/companion-chat-manager.d.ts +91 -23
- package/dist/platform/companion/companion-chat-manager.d.ts.map +1 -1
- package/dist/platform/companion/companion-chat-manager.js +195 -223
- package/dist/platform/companion/companion-chat-persistence.d.ts +9 -1
- package/dist/platform/companion/companion-chat-persistence.d.ts.map +1 -1
- package/dist/platform/companion/companion-chat-persistence.js +10 -2
- package/dist/platform/companion/companion-chat-routes.d.ts +2 -1
- package/dist/platform/companion/companion-chat-routes.d.ts.map +1 -1
- package/dist/platform/companion/companion-chat-routes.js +113 -4
- package/dist/platform/companion/companion-chat-turn-execution.d.ts +61 -0
- package/dist/platform/companion/companion-chat-turn-execution.d.ts.map +1 -0
- package/dist/platform/companion/companion-chat-turn-execution.js +107 -0
- package/dist/platform/companion/companion-chat-types.d.ts +67 -0
- package/dist/platform/companion/companion-chat-types.d.ts.map +1 -1
- package/dist/platform/config/credential-status.d.ts +28 -0
- package/dist/platform/config/credential-status.d.ts.map +1 -0
- package/dist/platform/config/credential-status.js +75 -0
- package/dist/platform/config/index.d.ts +25 -0
- package/dist/platform/config/index.d.ts.map +1 -1
- package/dist/platform/config/index.js +18 -0
- package/dist/platform/config/manager.d.ts +9 -0
- package/dist/platform/config/manager.d.ts.map +1 -1
- package/dist/platform/config/manager.js +21 -2
- package/dist/platform/config/migrations.d.ts +48 -0
- package/dist/platform/config/migrations.d.ts.map +1 -0
- package/dist/platform/config/migrations.js +54 -0
- package/dist/platform/config/schema-domain-core.d.ts +10 -1
- package/dist/platform/config/schema-domain-core.d.ts.map +1 -1
- package/dist/platform/config/schema-domain-core.js +46 -3
- package/dist/platform/config/schema-domain-runtime.d.ts +8 -0
- package/dist/platform/config/schema-domain-runtime.d.ts.map +1 -1
- package/dist/platform/config/schema-domain-runtime.js +32 -0
- package/dist/platform/config/schema-types.d.ts +21 -7
- package/dist/platform/config/schema-types.d.ts.map +1 -1
- package/dist/platform/config/schema.d.ts.map +1 -1
- package/dist/platform/config/schema.js +2 -0
- package/dist/platform/control-plane/approval-broker.d.ts +11 -0
- package/dist/platform/control-plane/approval-broker.d.ts.map +1 -1
- package/dist/platform/control-plane/approval-broker.js +17 -1
- package/dist/platform/control-plane/approval-hunk-apply.d.ts +77 -0
- package/dist/platform/control-plane/approval-hunk-apply.d.ts.map +1 -0
- package/dist/platform/control-plane/approval-hunk-apply.js +80 -0
- package/dist/platform/control-plane/gateway-disabled-response.d.ts +20 -0
- package/dist/platform/control-plane/gateway-disabled-response.d.ts.map +1 -0
- package/dist/platform/control-plane/gateway-disabled-response.js +24 -0
- package/dist/platform/control-plane/gateway-scope-enforcement.d.ts +68 -0
- package/dist/platform/control-plane/gateway-scope-enforcement.d.ts.map +1 -0
- package/dist/platform/control-plane/gateway-scope-enforcement.js +91 -0
- package/dist/platform/control-plane/gateway-utils.d.ts +17 -0
- package/dist/platform/control-plane/gateway-utils.d.ts.map +1 -1
- package/dist/platform/control-plane/gateway-utils.js +30 -0
- package/dist/platform/control-plane/gateway.d.ts +12 -2
- package/dist/platform/control-plane/gateway.d.ts.map +1 -1
- package/dist/platform/control-plane/gateway.js +27 -31
- package/dist/platform/control-plane/index.d.ts +8 -1
- package/dist/platform/control-plane/index.d.ts.map +1 -1
- package/dist/platform/control-plane/index.js +8 -0
- package/dist/platform/control-plane/invoke-input-validation.d.ts +56 -0
- package/dist/platform/control-plane/invoke-input-validation.d.ts.map +1 -0
- package/dist/platform/control-plane/invoke-input-validation.js +163 -0
- package/dist/platform/control-plane/method-catalog-admin.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-admin.js +12 -1
- package/dist/platform/control-plane/method-catalog-calendar.d.ts +16 -0
- package/dist/platform/control-plane/method-catalog-calendar.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-calendar.js +21 -0
- package/dist/platform/control-plane/method-catalog-channels.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-channels.js +32 -3
- package/dist/platform/control-plane/method-catalog-control-automation.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-control-automation.js +19 -34
- package/dist/platform/control-plane/method-catalog-control-companion.d.ts +15 -0
- package/dist/platform/control-plane/method-catalog-control-companion.d.ts.map +1 -0
- package/dist/platform/control-plane/method-catalog-control-companion.js +176 -0
- package/dist/platform/control-plane/method-catalog-control-core.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-control-core.js +104 -122
- package/dist/platform/control-plane/method-catalog-control.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-control.js +4 -0
- package/dist/platform/control-plane/method-catalog-email.d.ts +17 -0
- package/dist/platform/control-plane/method-catalog-email.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-email.js +21 -0
- package/dist/platform/control-plane/method-catalog-events.d.ts +28 -0
- package/dist/platform/control-plane/method-catalog-events.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-events.js +74 -1
- package/dist/platform/control-plane/method-catalog-fleet.d.ts +24 -0
- package/dist/platform/control-plane/method-catalog-fleet.d.ts.map +1 -0
- package/dist/platform/control-plane/method-catalog-fleet.js +65 -0
- package/dist/platform/control-plane/method-catalog-push.d.ts +30 -0
- package/dist/platform/control-plane/method-catalog-push.d.ts.map +1 -0
- package/dist/platform/control-plane/method-catalog-push.js +80 -0
- package/dist/platform/control-plane/method-catalog-route-reconcile.d.ts +84 -0
- package/dist/platform/control-plane/method-catalog-route-reconcile.d.ts.map +1 -0
- package/dist/platform/control-plane/method-catalog-route-reconcile.js +103 -0
- package/dist/platform/control-plane/method-catalog-runtime.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog-runtime.js +83 -1
- package/dist/platform/control-plane/method-catalog-shared.d.ts +29 -0
- package/dist/platform/control-plane/method-catalog-shared.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog.d.ts +9 -0
- package/dist/platform/control-plane/method-catalog.d.ts.map +1 -1
- package/dist/platform/control-plane/method-catalog.js +34 -3
- package/dist/platform/control-plane/operator-contract-schemas-admin.d.ts +8 -0
- package/dist/platform/control-plane/operator-contract-schemas-admin.d.ts.map +1 -1
- package/dist/platform/control-plane/operator-contract-schemas-admin.js +22 -1
- package/dist/platform/control-plane/operator-contract-schemas-fleet.d.ts +18 -0
- package/dist/platform/control-plane/operator-contract-schemas-fleet.d.ts.map +1 -0
- package/dist/platform/control-plane/operator-contract-schemas-fleet.js +182 -0
- package/dist/platform/control-plane/operator-contract-schemas-permissions.d.ts.map +1 -1
- package/dist/platform/control-plane/operator-contract-schemas-permissions.js +5 -0
- package/dist/platform/control-plane/operator-contract-schemas-runtime.d.ts +37 -0
- package/dist/platform/control-plane/operator-contract-schemas-runtime.d.ts.map +1 -1
- package/dist/platform/control-plane/operator-contract-schemas-runtime.js +100 -3
- package/dist/platform/control-plane/operator-contract-schemas.d.ts +1 -0
- package/dist/platform/control-plane/operator-contract-schemas.d.ts.map +1 -1
- package/dist/platform/control-plane/operator-contract-schemas.js +1 -0
- package/dist/platform/control-plane/operator-contract.d.ts.map +1 -1
- package/dist/platform/control-plane/operator-contract.js +8 -0
- package/dist/platform/control-plane/routes/checkpoints.d.ts +39 -0
- package/dist/platform/control-plane/routes/checkpoints.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/checkpoints.js +166 -0
- package/dist/platform/control-plane/routes/fleet.d.ts +53 -0
- package/dist/platform/control-plane/routes/fleet.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/fleet.js +153 -0
- package/dist/platform/control-plane/routes/gateway-verb-error.d.ts +30 -0
- package/dist/platform/control-plane/routes/gateway-verb-error.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/gateway-verb-error.js +36 -0
- package/dist/platform/control-plane/routes/index.d.ts +0 -6
- package/dist/platform/control-plane/routes/index.d.ts.map +1 -1
- package/dist/platform/control-plane/routes/index.js +5 -5
- package/dist/platform/control-plane/routes/invocation-params.d.ts +23 -0
- package/dist/platform/control-plane/routes/invocation-params.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/invocation-params.js +9 -0
- package/dist/platform/control-plane/routes/push.d.ts +26 -0
- package/dist/platform/control-plane/routes/push.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/push.js +104 -0
- package/dist/platform/control-plane/routes/register-gateway-verb-groups.d.ts +31 -0
- package/dist/platform/control-plane/routes/register-gateway-verb-groups.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/register-gateway-verb-groups.js +16 -0
- package/dist/platform/control-plane/routes/register-w3-s2.d.ts +26 -0
- package/dist/platform/control-plane/routes/register-w3-s2.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/register-w3-s2.js +8 -0
- package/dist/platform/control-plane/routes/session-search.d.ts +37 -0
- package/dist/platform/control-plane/routes/session-search.d.ts.map +1 -0
- package/dist/platform/control-plane/routes/session-search.js +113 -0
- package/dist/platform/control-plane/session-broker-gc.d.ts +16 -0
- package/dist/platform/control-plane/session-broker-gc.d.ts.map +1 -1
- package/dist/platform/control-plane/session-broker-gc.js +23 -6
- package/dist/platform/control-plane/session-broker-helpers.d.ts +3 -3
- package/dist/platform/control-plane/session-broker-helpers.d.ts.map +1 -1
- package/dist/platform/control-plane/session-broker-inputs.d.ts +18 -0
- package/dist/platform/control-plane/session-broker-inputs.d.ts.map +1 -1
- package/dist/platform/control-plane/session-broker-inputs.js +34 -0
- package/dist/platform/control-plane/session-broker-sessions.d.ts +102 -3
- package/dist/platform/control-plane/session-broker-sessions.d.ts.map +1 -1
- package/dist/platform/control-plane/session-broker-sessions.js +179 -5
- package/dist/platform/control-plane/session-broker-state.d.ts +20 -1
- package/dist/platform/control-plane/session-broker-state.d.ts.map +1 -1
- package/dist/platform/control-plane/session-broker-state.js +67 -5
- package/dist/platform/control-plane/session-broker.d.ts +51 -38
- package/dist/platform/control-plane/session-broker.d.ts.map +1 -1
- package/dist/platform/control-plane/session-broker.js +183 -75
- package/dist/platform/control-plane/session-store-importer.d.ts +57 -0
- package/dist/platform/control-plane/session-store-importer.d.ts.map +1 -0
- package/dist/platform/control-plane/session-store-importer.js +227 -0
- package/dist/platform/control-plane/session-types.d.ts +142 -7
- package/dist/platform/control-plane/session-types.d.ts.map +1 -1
- package/dist/platform/core/execution-plan.d.ts +43 -1
- package/dist/platform/core/execution-plan.d.ts.map +1 -1
- package/dist/platform/core/execution-plan.js +46 -10
- package/dist/platform/core/index.d.ts +1 -0
- package/dist/platform/core/index.d.ts.map +1 -1
- package/dist/platform/core/index.js +1 -0
- package/dist/platform/core/orchestrator-runtime.d.ts +23 -3
- package/dist/platform/core/orchestrator-runtime.d.ts.map +1 -1
- package/dist/platform/core/orchestrator-tool-runtime.d.ts +7 -0
- package/dist/platform/core/orchestrator-tool-runtime.d.ts.map +1 -1
- package/dist/platform/core/orchestrator-tool-runtime.js +10 -0
- package/dist/platform/core/orchestrator-turn-loop.d.ts +13 -6
- package/dist/platform/core/orchestrator-turn-loop.d.ts.map +1 -1
- package/dist/platform/core/orchestrator-turn-loop.js +29 -22
- package/dist/platform/core/orchestrator.d.ts +16 -10
- package/dist/platform/core/orchestrator.d.ts.map +1 -1
- package/dist/platform/core/orchestrator.js +23 -8
- package/dist/platform/core/plan-decomposition.d.ts +196 -0
- package/dist/platform/core/plan-decomposition.d.ts.map +1 -0
- package/dist/platform/core/plan-decomposition.js +417 -0
- package/dist/platform/core/plan-proposal.d.ts +39 -0
- package/dist/platform/core/plan-proposal.d.ts.map +1 -1
- package/dist/platform/core/wrfc-routing.d.ts +1 -0
- package/dist/platform/core/wrfc-routing.d.ts.map +1 -1
- package/dist/platform/core/wrfc-routing.js +51 -1
- package/dist/platform/daemon/boot.d.ts +69 -0
- package/dist/platform/daemon/boot.d.ts.map +1 -0
- package/dist/platform/daemon/boot.js +61 -0
- package/dist/platform/daemon/cli.js +2 -1
- package/dist/platform/daemon/control-plane.d.ts.map +1 -1
- package/dist/platform/daemon/control-plane.js +50 -1
- package/dist/platform/daemon/facade-composition.d.ts.map +1 -1
- package/dist/platform/daemon/facade-composition.js +6 -0
- package/dist/platform/daemon/facade.d.ts +15 -6
- package/dist/platform/daemon/facade.d.ts.map +1 -1
- package/dist/platform/daemon/facade.js +48 -43
- package/dist/platform/daemon/http/router-route-contexts.d.ts +1 -0
- package/dist/platform/daemon/http/router-route-contexts.d.ts.map +1 -1
- package/dist/platform/daemon/http/router-route-contexts.js +1 -0
- package/dist/platform/daemon/http/router-session-broker-adapter.d.ts +13 -0
- package/dist/platform/daemon/http/router-session-broker-adapter.d.ts.map +1 -0
- package/dist/platform/daemon/http/router-session-broker-adapter.js +27 -0
- package/dist/platform/daemon/http/router.d.ts +2 -1
- package/dist/platform/daemon/http/router.d.ts.map +1 -1
- package/dist/platform/daemon/http/router.js +42 -40
- package/dist/platform/daemon/http/runtime-route-types.d.ts +42 -4
- package/dist/platform/daemon/http/runtime-route-types.d.ts.map +1 -1
- package/dist/platform/daemon/http/webui-serving.d.ts +68 -0
- package/dist/platform/daemon/http/webui-serving.d.ts.map +1 -0
- package/dist/platform/daemon/http/webui-serving.js +230 -0
- package/dist/platform/daemon/index.d.ts +2 -0
- package/dist/platform/daemon/index.d.ts.map +1 -1
- package/dist/platform/daemon/index.js +1 -0
- package/dist/platform/daemon/service-manager.d.ts +16 -0
- package/dist/platform/daemon/service-manager.d.ts.map +1 -1
- package/dist/platform/daemon/service-manager.js +79 -15
- package/dist/platform/intelligence/tree-sitter/service.d.ts.map +1 -1
- package/dist/platform/intelligence/tree-sitter/service.js +16 -2
- package/dist/platform/knowledge/browser-history/readers.d.ts.map +1 -1
- package/dist/platform/knowledge/browser-history/readers.js +15 -5
- package/dist/platform/knowledge/knowledge-api.d.ts +1 -1
- package/dist/platform/knowledge/project-planning/service.d.ts +14 -1
- package/dist/platform/knowledge/project-planning/service.d.ts.map +1 -1
- package/dist/platform/knowledge/project-planning/service.js +77 -0
- package/dist/platform/knowledge/project-planning/types.d.ts +32 -0
- package/dist/platform/knowledge/project-planning/types.d.ts.map +1 -1
- package/dist/platform/orchestration/bookkeeping.d.ts +12 -0
- package/dist/platform/orchestration/bookkeeping.d.ts.map +1 -0
- package/dist/platform/orchestration/bookkeeping.js +91 -0
- package/dist/platform/orchestration/budget.d.ts +2 -2
- package/dist/platform/orchestration/cancellation.d.ts +2 -2
- package/dist/platform/orchestration/controller-compat.d.ts +16 -3
- package/dist/platform/orchestration/controller-compat.d.ts.map +1 -1
- package/dist/platform/orchestration/controller-compat.js +18 -4
- package/dist/platform/orchestration/dirty-guard.js +1 -1
- package/dist/platform/orchestration/engine.d.ts +26 -1
- package/dist/platform/orchestration/engine.d.ts.map +1 -1
- package/dist/platform/orchestration/engine.js +229 -25
- package/dist/platform/orchestration/index.d.ts +6 -4
- package/dist/platform/orchestration/index.d.ts.map +1 -1
- package/dist/platform/orchestration/index.js +3 -2
- package/dist/platform/orchestration/persistence.d.ts.map +1 -1
- package/dist/platform/orchestration/persistence.js +6 -3
- package/dist/platform/orchestration/phase-runner.d.ts +33 -6
- package/dist/platform/orchestration/phase-runner.d.ts.map +1 -1
- package/dist/platform/orchestration/phase-runner.js +98 -25
- package/dist/platform/orchestration/proposal-workstream.d.ts +56 -0
- package/dist/platform/orchestration/proposal-workstream.d.ts.map +1 -0
- package/dist/platform/orchestration/proposal-workstream.js +76 -0
- package/dist/platform/orchestration/scheduler.d.ts +20 -1
- package/dist/platform/orchestration/scheduler.d.ts.map +1 -1
- package/dist/platform/orchestration/scheduler.js +16 -0
- package/dist/platform/orchestration/types.d.ts +289 -4
- package/dist/platform/orchestration/types.d.ts.map +1 -1
- package/dist/platform/orchestration/types.js +32 -0
- package/dist/platform/orchestration/worktree-isolation.d.ts +33 -0
- package/dist/platform/orchestration/worktree-isolation.d.ts.map +1 -0
- package/dist/platform/orchestration/worktree-isolation.js +248 -0
- package/dist/platform/presentation/glyphs.d.ts +91 -0
- package/dist/platform/presentation/glyphs.d.ts.map +1 -0
- package/dist/platform/presentation/glyphs.js +93 -0
- package/dist/platform/presentation/index.d.ts +28 -0
- package/dist/platform/presentation/index.d.ts.map +1 -0
- package/dist/platform/presentation/index.js +27 -0
- package/dist/platform/presentation/thinking-phrases.d.ts +12 -0
- package/dist/platform/presentation/thinking-phrases.d.ts.map +1 -0
- package/dist/platform/presentation/thinking-phrases.js +32 -0
- package/dist/platform/presentation/tones.d.ts +121 -0
- package/dist/platform/presentation/tones.d.ts.map +1 -0
- package/dist/platform/presentation/tones.js +145 -0
- package/dist/platform/presentation/waiting-wording.d.ts +54 -0
- package/dist/platform/presentation/waiting-wording.d.ts.map +1 -0
- package/dist/platform/presentation/waiting-wording.js +51 -0
- package/dist/platform/providers/runtime-snapshot.d.ts.map +1 -1
- package/dist/platform/providers/runtime-snapshot.js +12 -2
- package/dist/platform/push/delivery.d.ts +48 -0
- package/dist/platform/push/delivery.d.ts.map +1 -0
- package/dist/platform/push/delivery.js +117 -0
- package/dist/platform/push/encryption.d.ts +41 -0
- package/dist/platform/push/encryption.d.ts.map +1 -0
- package/dist/platform/push/encryption.js +82 -0
- package/dist/platform/push/index.d.ts +17 -0
- package/dist/platform/push/index.d.ts.map +1 -0
- package/dist/platform/push/index.js +10 -0
- package/dist/platform/push/service.d.ts +75 -0
- package/dist/platform/push/service.d.ts.map +1 -0
- package/dist/platform/push/service.js +95 -0
- package/dist/platform/push/subscription-store.d.ts +50 -0
- package/dist/platform/push/subscription-store.d.ts.map +1 -0
- package/dist/platform/push/subscription-store.js +123 -0
- package/dist/platform/push/types.d.ts +68 -0
- package/dist/platform/push/types.d.ts.map +1 -0
- package/dist/platform/push/types.js +13 -0
- package/dist/platform/push/vapid.d.ts +54 -0
- package/dist/platform/push/vapid.d.ts.map +1 -0
- package/dist/platform/push/vapid.js +113 -0
- package/dist/platform/runtime/bootstrap-services.d.ts +62 -2
- package/dist/platform/runtime/bootstrap-services.d.ts.map +1 -1
- package/dist/platform/runtime/bootstrap-services.js +217 -50
- package/dist/platform/runtime/daemon-version-compat.d.ts +39 -0
- package/dist/platform/runtime/daemon-version-compat.d.ts.map +1 -0
- package/dist/platform/runtime/daemon-version-compat.js +75 -0
- package/dist/platform/runtime/detached-daemon-runtime.d.ts +26 -0
- package/dist/platform/runtime/detached-daemon-runtime.d.ts.map +1 -0
- package/dist/platform/runtime/detached-daemon-runtime.js +49 -0
- package/dist/platform/runtime/emitters/workflows.d.ts +1 -1
- package/dist/platform/runtime/emitters/workflows.d.ts.map +1 -1
- package/dist/platform/runtime/events/index.d.ts +13 -0
- package/dist/platform/runtime/events/index.d.ts.map +1 -1
- package/dist/platform/runtime/events/index.js +13 -0
- package/dist/platform/runtime/feature-flags/flags.d.ts.map +1 -1
- package/dist/platform/runtime/feature-flags/flags.js +39 -1
- package/dist/platform/runtime/fleet/adapters/agent.d.ts +2 -2
- package/dist/platform/runtime/fleet/adapters/agent.d.ts.map +1 -1
- package/dist/platform/runtime/fleet/adapters/agent.js +4 -4
- package/dist/platform/runtime/fleet/adapters/automation.d.ts +1 -1
- package/dist/platform/runtime/fleet/adapters/automation.js +1 -1
- package/dist/platform/runtime/fleet/adapters/code-index.d.ts +1 -1
- package/dist/platform/runtime/fleet/adapters/code-index.js +1 -1
- package/dist/platform/runtime/fleet/adapters/orchestration.d.ts +40 -18
- package/dist/platform/runtime/fleet/adapters/orchestration.d.ts.map +1 -1
- package/dist/platform/runtime/fleet/adapters/orchestration.js +138 -34
- package/dist/platform/runtime/fleet/adapters/schedule.d.ts +4 -4
- package/dist/platform/runtime/fleet/adapters/schedule.js +4 -4
- package/dist/platform/runtime/fleet/adapters/trigger.d.ts +3 -4
- package/dist/platform/runtime/fleet/adapters/trigger.d.ts.map +1 -1
- package/dist/platform/runtime/fleet/adapters/trigger.js +3 -4
- package/dist/platform/runtime/fleet/adapters/wrfc.d.ts +13 -0
- package/dist/platform/runtime/fleet/adapters/wrfc.d.ts.map +1 -1
- package/dist/platform/runtime/fleet/adapters/wrfc.js +49 -2
- package/dist/platform/runtime/fleet/registry.d.ts +7 -7
- package/dist/platform/runtime/fleet/registry.d.ts.map +1 -1
- package/dist/platform/runtime/fleet/registry.js +41 -7
- package/dist/platform/runtime/fleet/types.d.ts +9 -9
- package/dist/platform/runtime/fleet/types.d.ts.map +1 -1
- package/dist/platform/runtime/memory-spine/client.d.ts +127 -0
- package/dist/platform/runtime/memory-spine/client.d.ts.map +1 -0
- package/dist/platform/runtime/memory-spine/client.js +113 -0
- package/dist/platform/runtime/memory-spine/index.d.ts +11 -0
- package/dist/platform/runtime/memory-spine/index.d.ts.map +1 -0
- package/dist/platform/runtime/memory-spine/index.js +10 -0
- package/dist/platform/runtime/operator-client.d.ts +20 -2
- package/dist/platform/runtime/operator-client.d.ts.map +1 -1
- package/dist/platform/runtime/operator-client.js +11 -1
- package/dist/platform/runtime/provider-accounts/registry.d.ts.map +1 -1
- package/dist/platform/runtime/provider-accounts/registry.js +11 -1
- package/dist/platform/runtime/services.d.ts +11 -9
- package/dist/platform/runtime/services.d.ts.map +1 -1
- package/dist/platform/runtime/services.js +24 -9
- package/dist/platform/runtime/session-spine/client.d.ts +234 -0
- package/dist/platform/runtime/session-spine/client.d.ts.map +1 -0
- package/dist/platform/runtime/session-spine/client.js +449 -0
- package/dist/platform/runtime/session-spine/index.d.ts +12 -0
- package/dist/platform/runtime/session-spine/index.d.ts.map +1 -0
- package/dist/platform/runtime/session-spine/index.js +11 -0
- package/dist/platform/runtime/session-spine/union-cache.d.ts +225 -0
- package/dist/platform/runtime/session-spine/union-cache.d.ts.map +1 -0
- package/dist/platform/runtime/session-spine/union-cache.js +333 -0
- package/dist/platform/runtime/shell-command-ops.d.ts +3 -1
- package/dist/platform/runtime/shell-command-ops.d.ts.map +1 -1
- package/dist/platform/runtime/transports/daemon-http-client-validators.d.ts.map +1 -1
- package/dist/platform/runtime/transports/daemon-http-client-validators.js +22 -0
- package/dist/platform/runtime/transports/daemon-http-client.d.ts.map +1 -1
- package/dist/platform/runtime/transports/daemon-http-client.js +25 -2
- package/dist/platform/runtime/transports/http-types.d.ts +9 -2
- package/dist/platform/runtime/transports/http-types.d.ts.map +1 -1
- package/dist/platform/state/canonical-memory.d.ts +95 -0
- package/dist/platform/state/canonical-memory.d.ts.map +1 -0
- package/dist/platform/state/canonical-memory.js +155 -0
- package/dist/platform/state/code-index-chunking.js +1 -1
- package/dist/platform/state/code-index-db.d.ts +1 -1
- package/dist/platform/state/code-index-reindex.d.ts +73 -0
- package/dist/platform/state/code-index-reindex.d.ts.map +1 -0
- package/dist/platform/state/code-index-reindex.js +156 -0
- package/dist/platform/state/code-index-store.d.ts.map +1 -1
- package/dist/platform/state/code-index-store.js +11 -3
- package/dist/platform/state/index.d.ts +8 -0
- package/dist/platform/state/index.d.ts.map +1 -1
- package/dist/platform/state/index.js +4 -0
- package/dist/platform/state/memory-recall-contract.d.ts +118 -0
- package/dist/platform/state/memory-recall-contract.d.ts.map +1 -0
- package/dist/platform/state/memory-recall-contract.js +170 -0
- package/dist/platform/state/memory-registry.d.ts +8 -0
- package/dist/platform/state/memory-registry.d.ts.map +1 -1
- package/dist/platform/state/memory-registry.js +10 -0
- package/dist/platform/state/memory-store.d.ts +2 -0
- package/dist/platform/state/memory-store.d.ts.map +1 -1
- package/dist/platform/state/memory-store.js +4 -0
- package/dist/platform/state/memory-vector-store.d.ts.map +1 -1
- package/dist/platform/state/memory-vector-store.js +14 -3
- package/dist/platform/state/sqlite-store.d.ts +2 -0
- package/dist/platform/state/sqlite-store.d.ts.map +1 -1
- package/dist/platform/state/sqlite-store.js +4 -0
- package/dist/platform/state/sqlite-vec-loader.d.ts +1 -1
- package/dist/platform/state/sqlite-vec-loader.js +1 -1
- package/dist/platform/state/vibe-projection.d.ts +67 -0
- package/dist/platform/state/vibe-projection.d.ts.map +1 -0
- package/dist/platform/state/vibe-projection.js +115 -0
- package/dist/platform/tools/agent/index.d.ts.map +1 -1
- package/dist/platform/tools/agent/index.js +8 -0
- package/dist/platform/tools/agent/manager.d.ts +22 -10
- package/dist/platform/tools/agent/manager.d.ts.map +1 -1
- package/dist/platform/tools/agent/manager.js +13 -7
- package/dist/platform/tools/agent/schema.d.ts +26 -0
- package/dist/platform/tools/agent/schema.d.ts.map +1 -1
- package/dist/platform/tools/agent/schema.js +2 -2
- package/dist/platform/tools/agent/wrfc-batch-policy.d.ts +13 -0
- package/dist/platform/tools/agent/wrfc-batch-policy.d.ts.map +1 -1
- package/dist/platform/tools/agent/wrfc-batch-policy.js +60 -0
- package/dist/platform/tools/exec/runtime.d.ts +10 -0
- package/dist/platform/tools/exec/runtime.d.ts.map +1 -1
- package/dist/platform/tools/exec/runtime.js +27 -10
- package/dist/platform/tools/exec/schema.d.ts +2 -2
- package/dist/platform/tools/exec/schema.d.ts.map +1 -1
- package/dist/platform/tools/exec/schema.js +2 -1
- package/dist/platform/tools/fetch/runtime.d.ts +1 -1
- package/dist/platform/tools/index.d.ts +2 -0
- package/dist/platform/tools/index.d.ts.map +1 -1
- package/dist/platform/tools/index.js +2 -0
- package/dist/platform/tools/registry.d.ts +1 -1
- package/dist/platform/tools/registry.js +1 -1
- package/dist/platform/tools/state/index.d.ts +9 -0
- package/dist/platform/tools/state/index.d.ts.map +1 -1
- package/dist/platform/tools/state/index.js +60 -3
- package/dist/platform/types/foundation-contract.d.ts +1 -1
- package/dist/platform/types/foundation-contract.d.ts.map +1 -1
- package/dist/platform/types/index.d.ts +1 -1
- package/dist/platform/types/index.d.ts.map +1 -1
- package/dist/platform/types/tools.d.ts +1 -1
- package/dist/platform/utils/request-body.d.ts.map +1 -1
- package/dist/platform/utils/request-body.js +50 -5
- package/dist/platform/version.js +1 -1
- package/package.json +25 -9
- package/dist/platform/control-plane/routes/automation.d.ts +0 -3
- package/dist/platform/control-plane/routes/automation.d.ts.map +0 -1
- package/dist/platform/control-plane/routes/automation.js +0 -63
- package/dist/platform/control-plane/routes/context.d.ts +0 -2
- package/dist/platform/control-plane/routes/context.d.ts.map +0 -1
- package/dist/platform/control-plane/routes/context.js +0 -1
- package/dist/platform/control-plane/routes/operator.d.ts +0 -8
- package/dist/platform/control-plane/routes/operator.d.ts.map +0 -1
- package/dist/platform/control-plane/routes/operator.js +0 -415
- package/dist/platform/control-plane/routes/remote.d.ts +0 -3
- package/dist/platform/control-plane/routes/remote.d.ts.map +0 -1
- package/dist/platform/control-plane/routes/remote.js +0 -35
- package/dist/platform/control-plane/routes/sessions.d.ts +0 -3
- package/dist/platform/control-plane/routes/sessions.d.ts.map +0 -1
- package/dist/platform/control-plane/routes/sessions.js +0 -43
- package/dist/platform/control-plane/routes/tasks.d.ts +0 -3
- package/dist/platform/control-plane/routes/tasks.d.ts.map +0 -1
- package/dist/platform/control-plane/routes/tasks.js +0 -22
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* push/vapid.ts
|
|
3
|
+
*
|
|
4
|
+
* VAPID (RFC 8292) key custody and request signing for browser push.
|
|
5
|
+
*
|
|
6
|
+
* KEY CUSTODY — the load-bearing rule of this file:
|
|
7
|
+
* - The daemon generates one P-256 keypair on first need.
|
|
8
|
+
* - The WHOLE keypair (including the private component) is persisted only
|
|
9
|
+
* through the SecretsManager, exactly like any other credential — into the
|
|
10
|
+
* secure store, or the plaintext secrets file, per the active secret policy.
|
|
11
|
+
* It is NEVER written into the config, so it can never ride out in the
|
|
12
|
+
* secret-free config snapshot.
|
|
13
|
+
* - The private key is used only here, to sign the short-lived VAPID JWT that
|
|
14
|
+
* authorizes one delivery. It is never logged and never returned by any read
|
|
15
|
+
* verb.
|
|
16
|
+
* - Only the PUBLIC key leaves the daemon: `getPublicKey()` feeds the
|
|
17
|
+
* `push.vapid.get` verb and the `k=` parameter of the Authorization header.
|
|
18
|
+
*/
|
|
19
|
+
import { createPrivateKey, generateKeyPairSync, sign as cryptoSign } from 'node:crypto';
|
|
20
|
+
/** The secret key under which the keypair is stored (a secrets-store key, not a config key). */
|
|
21
|
+
export const VAPID_SECRET_KEY = 'push.vapid.keypair';
|
|
22
|
+
const DEFAULT_SUBJECT = 'mailto:goodvibes-push@localhost';
|
|
23
|
+
/** VAPID JWTs are short-lived; RFC 8292 caps `exp` at 24h. Use 12h. */
|
|
24
|
+
const JWT_LIFETIME_SECONDS = 12 * 60 * 60;
|
|
25
|
+
function base64UrlFromBuffer(buffer) {
|
|
26
|
+
return buffer.toString('base64url');
|
|
27
|
+
}
|
|
28
|
+
function base64UrlJson(value) {
|
|
29
|
+
return Buffer.from(JSON.stringify(value), 'utf8').toString('base64url');
|
|
30
|
+
}
|
|
31
|
+
/** Derive the 65-byte uncompressed public point (base64url) from a P-256 JWK. */
|
|
32
|
+
function publicKeyFromJwk(jwk) {
|
|
33
|
+
if (!jwk.x || !jwk.y)
|
|
34
|
+
throw new Error('VAPID JWK is missing its public coordinates');
|
|
35
|
+
const point = Buffer.concat([
|
|
36
|
+
Buffer.from([0x04]),
|
|
37
|
+
Buffer.from(jwk.x, 'base64url'),
|
|
38
|
+
Buffer.from(jwk.y, 'base64url'),
|
|
39
|
+
]);
|
|
40
|
+
return base64UrlFromBuffer(point);
|
|
41
|
+
}
|
|
42
|
+
export class VapidManager {
|
|
43
|
+
store;
|
|
44
|
+
subject;
|
|
45
|
+
inflight = null;
|
|
46
|
+
constructor(store, options = {}) {
|
|
47
|
+
this.store = store;
|
|
48
|
+
this.subject = options.subject && options.subject.length > 0 ? options.subject : DEFAULT_SUBJECT;
|
|
49
|
+
}
|
|
50
|
+
/** The public application-server key clients subscribe with. Generates on first call. */
|
|
51
|
+
async getPublicKey() {
|
|
52
|
+
const keypair = await this.ensureKeypair();
|
|
53
|
+
return keypair.publicKey;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the `Authorization: vapid ...` header value for one delivery to
|
|
57
|
+
* `endpoint`. The JWT's audience is the endpoint's origin (RFC 8292).
|
|
58
|
+
*/
|
|
59
|
+
async buildAuthorizationHeader(endpoint) {
|
|
60
|
+
const keypair = await this.ensureKeypair();
|
|
61
|
+
const audience = new URL(endpoint).origin;
|
|
62
|
+
const jwt = this.signJwt(audience, keypair.privateJwk);
|
|
63
|
+
return `vapid t=${jwt}, k=${keypair.publicKey}`;
|
|
64
|
+
}
|
|
65
|
+
signJwt(audience, privateJwk) {
|
|
66
|
+
const header = base64UrlJson({ typ: 'JWT', alg: 'ES256' });
|
|
67
|
+
const payload = base64UrlJson({
|
|
68
|
+
aud: audience,
|
|
69
|
+
exp: Math.floor(Date.now() / 1000) + JWT_LIFETIME_SECONDS,
|
|
70
|
+
sub: this.subject,
|
|
71
|
+
});
|
|
72
|
+
const signingInput = `${header}.${payload}`;
|
|
73
|
+
const key = createPrivateKey({ key: privateJwk, format: 'jwk' });
|
|
74
|
+
// ieee-p1363 gives the raw r||s (64-byte) JOSE signature ES256 requires,
|
|
75
|
+
// not Node's default DER encoding.
|
|
76
|
+
const signature = cryptoSign('sha256', Buffer.from(signingInput, 'utf8'), {
|
|
77
|
+
key,
|
|
78
|
+
dsaEncoding: 'ieee-p1363',
|
|
79
|
+
});
|
|
80
|
+
return `${signingInput}.${base64UrlFromBuffer(signature)}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Load the keypair from the secrets store, or generate and persist one on
|
|
84
|
+
* first use. Concurrent callers share a single in-flight generation so two
|
|
85
|
+
* simultaneous first-time deliveries cannot mint two keypairs.
|
|
86
|
+
*/
|
|
87
|
+
ensureKeypair() {
|
|
88
|
+
if (this.inflight)
|
|
89
|
+
return this.inflight;
|
|
90
|
+
this.inflight = this.loadOrGenerate().catch((error) => {
|
|
91
|
+
// A failed attempt must not poison every later call.
|
|
92
|
+
this.inflight = null;
|
|
93
|
+
throw error;
|
|
94
|
+
});
|
|
95
|
+
return this.inflight;
|
|
96
|
+
}
|
|
97
|
+
async loadOrGenerate() {
|
|
98
|
+
const existing = await this.store.get(VAPID_SECRET_KEY);
|
|
99
|
+
if (existing) {
|
|
100
|
+
const parsed = JSON.parse(existing);
|
|
101
|
+
if (parsed.publicKey && parsed.privateJwk)
|
|
102
|
+
return parsed;
|
|
103
|
+
}
|
|
104
|
+
const { publicKey, privateKey } = generateKeyPairSync('ec', { namedCurve: 'prime256v1' });
|
|
105
|
+
const privateJwk = privateKey.export({ format: 'jwk' });
|
|
106
|
+
const keypair = {
|
|
107
|
+
publicKey: publicKeyFromJwk(publicKey.export({ format: 'jwk' })),
|
|
108
|
+
privateJwk,
|
|
109
|
+
};
|
|
110
|
+
await this.store.set(VAPID_SECRET_KEY, JSON.stringify(keypair));
|
|
111
|
+
return keypair;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -16,8 +16,49 @@ interface HttpListenerService {
|
|
|
16
16
|
start(): Promise<void>;
|
|
17
17
|
stop(): Promise<void>;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Options passed to the injectable detached-daemon spawn seam. Mirrors the subset
|
|
21
|
+
* of `child_process.SpawnOptions` the detached spawn relies on. `detached: true`
|
|
22
|
+
* and the caller's subsequent `unref()` are what let the daemon outlive this
|
|
23
|
+
* surface — tests assert both are present.
|
|
24
|
+
*/
|
|
25
|
+
export interface DetachedDaemonSpawnOptions {
|
|
26
|
+
readonly detached: boolean;
|
|
27
|
+
readonly stdio: 'ignore' | ReadonlyArray<'ignore' | number>;
|
|
28
|
+
readonly cwd?: string | undefined;
|
|
29
|
+
readonly env?: NodeJS.ProcessEnv | undefined;
|
|
30
|
+
}
|
|
31
|
+
/** Minimal child-process shape the detached spawn seam must return. */
|
|
32
|
+
export interface DetachedDaemonChild {
|
|
33
|
+
readonly pid?: number | undefined;
|
|
34
|
+
unref(): void;
|
|
35
|
+
once?(event: 'error' | 'exit', listener: (arg: unknown) => void): void;
|
|
36
|
+
}
|
|
37
|
+
/** One-time hint surfaced ONCE by the TUI after a successful detached spawn. */
|
|
38
|
+
export declare const DETACHED_DAEMON_INSTALL_HINT = "daemon started for this session \u2014 install it as a service so it survives reboots: POST /api/service/install on the daemon HTTP API (admin token required)";
|
|
19
39
|
interface ServiceFactories {
|
|
20
40
|
createDaemonServer?: (runtimeBus: RuntimeEventBus, userAuth: RuntimeServices['localUserAuthManager'], runtimeServices: RuntimeServices) => DaemonService;
|
|
41
|
+
/**
|
|
42
|
+
* Injectable spawn seam for the detached standalone daemon (Layer 2 default).
|
|
43
|
+
* Defaults to `child_process.spawn`. Tests stub this to assert that detached
|
|
44
|
+
* spawn — not in-process embedding — is chosen by default, and that the options
|
|
45
|
+
* carry `detached: true` (the caller then `unref()`s the returned child).
|
|
46
|
+
*/
|
|
47
|
+
spawnDetachedDaemon?: (command: string, args: readonly string[], options: DetachedDaemonSpawnOptions) => DetachedDaemonChild;
|
|
48
|
+
/** Command used to launch the detached daemon. Default: `GOODVIBES_DAEMON_BINARY` env or `goodvibes-daemon`. */
|
|
49
|
+
daemonLaunchCommand?: string | undefined;
|
|
50
|
+
/** Extra CLI args appended after the resolved `--daemon-home/--hostname/--port` flags. */
|
|
51
|
+
daemonLaunchArgs?: readonly string[] | undefined;
|
|
52
|
+
/** Daemon home directory passed via `--daemon-home`. Default: `os.homedir()`. */
|
|
53
|
+
daemonHomeDir?: string | undefined;
|
|
54
|
+
/** Directory where the detached daemon records pid/port + log. Default `<daemonHomeDir>/.goodvibes/daemon`. */
|
|
55
|
+
daemonRuntimeDir?: string | undefined;
|
|
56
|
+
/** Bounded time to wait for the detached daemon to bind + pass the identity probe. */
|
|
57
|
+
detachedSpawnProbeTimeoutMs?: number | undefined;
|
|
58
|
+
/** Poll interval while waiting for the detached daemon to become reachable. */
|
|
59
|
+
detachedSpawnProbeIntervalMs?: number | undefined;
|
|
60
|
+
/** Sleep function (injectable so tests drive the probe loop deterministically). */
|
|
61
|
+
sleep?: ((ms: number) => Promise<void>) | undefined;
|
|
21
62
|
createHttpListener?: (hookDispatcher: HookDispatcher, userAuth: RuntimeServices['localUserAuthManager'], configManager: RuntimeServices['configManager']) => HttpListenerService;
|
|
22
63
|
startupTimeoutMs?: number | undefined;
|
|
23
64
|
probeDaemonPortInUse?: ((host: string, port: number) => Promise<boolean>) | undefined;
|
|
@@ -37,8 +78,20 @@ interface ServiceFactories {
|
|
|
37
78
|
* different tokens, or both may share the same bearer.
|
|
38
79
|
*/
|
|
39
80
|
sharedHttpListenerToken?: string | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* This surface's own SDK version, used to band-check a daemon found on the
|
|
83
|
+
* configured port before adopting it. Defaults to the SDK `VERSION`. Injected
|
|
84
|
+
* mainly so tests can drive the compatibility gate deterministically.
|
|
85
|
+
*/
|
|
86
|
+
localDaemonVersion?: string | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Override for the version-compatibility predicate. Defaults to the shared
|
|
89
|
+
* `isDaemonVersionCompatible` band policy. Tests inject a stub to exercise the
|
|
90
|
+
* incompatible-adoption refusal without constructing skewed daemons.
|
|
91
|
+
*/
|
|
92
|
+
isDaemonVersionCompatible?: ((localVersion: string, remoteVersion: string | undefined) => boolean) | undefined;
|
|
40
93
|
}
|
|
41
|
-
export type HostServiceMode = 'disabled' | 'embedded' | 'external' | 'blocked' | 'unavailable';
|
|
94
|
+
export type HostServiceMode = 'disabled' | 'embedded' | 'external' | 'blocked' | 'incompatible' | 'unavailable';
|
|
42
95
|
export interface HostServiceStatus {
|
|
43
96
|
readonly mode: HostServiceMode;
|
|
44
97
|
readonly host: string;
|
|
@@ -60,11 +113,18 @@ export interface HostServicesHandle {
|
|
|
60
113
|
readonly httpListener: HttpListenerService | null;
|
|
61
114
|
readonly daemonStatus: HostServiceStatus;
|
|
62
115
|
readonly httpListenerStatus: HostServiceStatus;
|
|
116
|
+
/**
|
|
117
|
+
* One-time, honest hint the surface can display ONCE after this host instance
|
|
118
|
+
* spawned a detached daemon for the session. Present only when a detached
|
|
119
|
+
* daemon was just started (Layer 2); undefined when a daemon was adopted,
|
|
120
|
+
* embedded, disabled, or unavailable. See {@link DETACHED_DAEMON_INSTALL_HINT}.
|
|
121
|
+
*/
|
|
122
|
+
readonly daemonStartHint?: string | undefined;
|
|
63
123
|
listRecentControlPlaneEvents(limit: number): readonly import('../control-plane/gateway.js').ControlPlaneRecentEvent[];
|
|
64
124
|
stop(): Promise<void>;
|
|
65
125
|
}
|
|
66
126
|
export interface HostServicesConfig {
|
|
67
|
-
get(key: '
|
|
127
|
+
get(key: 'daemon.enabled' | 'daemon.embedInProcess' | 'danger.httpListener' | 'controlPlane.host' | 'controlPlane.port' | 'httpListener.host' | 'httpListener.port'): boolean | string | number | undefined;
|
|
68
128
|
}
|
|
69
129
|
export declare function startHostServices(config: HostServicesConfig, runtimeBus: RuntimeEventBus, hookDispatcher: HookDispatcher, runtimeServices: RuntimeServices, factories?: ServiceFactories): Promise<HostServicesHandle>;
|
|
70
130
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap-services.d.ts","sourceRoot":"","sources":["../../../src/platform/runtime/bootstrap-services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"bootstrap-services.d.ts","sourceRoot":"","sources":["../../../src/platform/runtime/bootstrap-services.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { ConfigurationError } from '@pellux/goodvibes-errors';
|
|
2
2
|
import { logger } from '../utils/logger.js';
|
|
3
3
|
import net from 'node:net';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { closeSync, mkdirSync, openSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { spawn } from 'node:child_process';
|
|
4
8
|
import { summarizeError } from '../utils/error-display.js';
|
|
5
9
|
import { createTimeoutController } from '../utils/fetch-with-timeout.js';
|
|
10
|
+
import { VERSION } from '../version.js';
|
|
11
|
+
import { isDaemonVersionCompatible, describeVersionIncompatibility } from './daemon-version-compat.js';
|
|
12
|
+
import { resolveDaemonEnabled } from '../config/index.js';
|
|
13
|
+
import { recordDetachedDaemonRuntime } from './detached-daemon-runtime.js';
|
|
14
|
+
/** One-time hint surfaced ONCE by the TUI after a successful detached spawn. */
|
|
15
|
+
export const DETACHED_DAEMON_INSTALL_HINT = 'daemon started for this session — install it as a service so it survives reboots: POST /api/service/install on the daemon HTTP API (admin token required)';
|
|
6
16
|
const DEFAULT_SERVICE_START_TIMEOUT_MS = 1500;
|
|
7
17
|
const TCP_PORT_PROBE_TIMEOUT_MS = 250;
|
|
8
18
|
const DAEMON_IDENTITY_PROBE_TIMEOUT_MS = 750;
|
|
@@ -13,6 +23,14 @@ function readBooleanSetting(config, key) {
|
|
|
13
23
|
}
|
|
14
24
|
return value;
|
|
15
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Whether the daemon should be hosted IN THIS PROCESS (Layer 3 opt-in). Default
|
|
28
|
+
* false: the surface spawns a detached daemon instead. Reads leniently so an
|
|
29
|
+
* unset value (undefined) means false rather than throwing.
|
|
30
|
+
*/
|
|
31
|
+
function readDaemonEmbedInProcess(config) {
|
|
32
|
+
return config.get('daemon.embedInProcess') === true;
|
|
33
|
+
}
|
|
16
34
|
function readHostSetting(config, key, fallback) {
|
|
17
35
|
const value = config.get(key);
|
|
18
36
|
if (value === undefined || value === null)
|
|
@@ -201,27 +219,152 @@ export async function startHostServices(config, runtimeBus, hookDispatcher, runt
|
|
|
201
219
|
const probeDaemonPortInUse = factories.probeDaemonPortInUse ?? ((host, port) => isTcpPortInUse(host, port));
|
|
202
220
|
const probeDaemonIdentity = factories.probeDaemonIdentity ?? probeGoodVibesDaemonIdentity;
|
|
203
221
|
const probeHttpListenerPortInUse = factories.probeHttpListenerPortInUse ?? ((host, port) => isTcpPortInUse(host, port));
|
|
222
|
+
const localDaemonVersion = factories.localDaemonVersion ?? VERSION;
|
|
223
|
+
const versionCompatible = factories.isDaemonVersionCompatible ?? isDaemonVersionCompatible;
|
|
224
|
+
// A daemon whose identity probe says `goodvibes` has only proven it IS a
|
|
225
|
+
// GoodVibes daemon — not that it speaks a wire version this surface can adopt.
|
|
226
|
+
// Band-check the reported version and produce an honest `incompatible` status
|
|
227
|
+
// (never a second competing daemon) when it does not match this surface's band.
|
|
228
|
+
const resolveVerifiedDaemonStatus = (identity, reasonAdopted) => {
|
|
229
|
+
if (versionCompatible(localDaemonVersion, identity.version)) {
|
|
230
|
+
return createServiceStatus('external', daemonHost, daemonPort, {
|
|
231
|
+
authenticated: true,
|
|
232
|
+
status: identity.status,
|
|
233
|
+
version: identity.version,
|
|
234
|
+
reason: reasonAdopted,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
const reason = describeVersionIncompatibility(daemonHost, daemonPort, localDaemonVersion, identity.version);
|
|
238
|
+
logger.warn('Daemon on configured port reports an incompatible version; refusing to adopt or start a competing daemon', {
|
|
239
|
+
host: daemonHost,
|
|
240
|
+
port: daemonPort,
|
|
241
|
+
foundVersion: identity.version,
|
|
242
|
+
localVersion: localDaemonVersion,
|
|
243
|
+
});
|
|
244
|
+
return createServiceStatus('incompatible', daemonHost, daemonPort, {
|
|
245
|
+
authenticated: true,
|
|
246
|
+
status: identity.status,
|
|
247
|
+
version: identity.version,
|
|
248
|
+
reason,
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
// Layer 2: spawn the daemon as a DETACHED standalone process (default), then
|
|
252
|
+
// poll (bounded) for it to bind and pass the identity probe. On success adopt
|
|
253
|
+
// it as 'external' with a one-time install-service hint. Returns an honest
|
|
254
|
+
// failure reason otherwise so the caller can fall back.
|
|
255
|
+
const attemptDetachedDaemonSpawn = async () => {
|
|
256
|
+
const spawnDetached = factories.spawnDetachedDaemon
|
|
257
|
+
?? ((command, args, options) => spawn(command, [...args], {
|
|
258
|
+
detached: options.detached,
|
|
259
|
+
stdio: options.stdio,
|
|
260
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
261
|
+
...(options.env !== undefined ? { env: options.env } : {}),
|
|
262
|
+
}));
|
|
263
|
+
const command = (factories.daemonLaunchCommand ?? process.env.GOODVIBES_DAEMON_BINARY ?? 'goodvibes-daemon').trim()
|
|
264
|
+
|| 'goodvibes-daemon';
|
|
265
|
+
const daemonHomeDir = factories.daemonHomeDir ?? os.homedir();
|
|
266
|
+
const runtimeDir = factories.daemonRuntimeDir ?? join(daemonHomeDir, '.goodvibes', 'daemon');
|
|
267
|
+
const logFilePath = join(runtimeDir, 'detached-daemon.log');
|
|
268
|
+
const args = [
|
|
269
|
+
'--daemon-home', daemonHomeDir,
|
|
270
|
+
'--hostname', daemonHost,
|
|
271
|
+
'--port', String(daemonPort),
|
|
272
|
+
...(factories.daemonLaunchArgs ?? []),
|
|
273
|
+
];
|
|
274
|
+
let stdio = 'ignore';
|
|
275
|
+
let closeStdio = null;
|
|
276
|
+
try {
|
|
277
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
278
|
+
const out = openSync(logFilePath, 'a');
|
|
279
|
+
const err = openSync(logFilePath, 'a');
|
|
280
|
+
stdio = ['ignore', out, err];
|
|
281
|
+
closeStdio = () => {
|
|
282
|
+
try {
|
|
283
|
+
closeSync(out);
|
|
284
|
+
}
|
|
285
|
+
catch { /* already closed */ }
|
|
286
|
+
try {
|
|
287
|
+
closeSync(err);
|
|
288
|
+
}
|
|
289
|
+
catch { /* already closed */ }
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
stdio = 'ignore';
|
|
294
|
+
}
|
|
295
|
+
let child;
|
|
296
|
+
try {
|
|
297
|
+
child = spawnDetached(command, args, {
|
|
298
|
+
detached: true,
|
|
299
|
+
stdio,
|
|
300
|
+
cwd: daemonHomeDir,
|
|
301
|
+
env: { ...process.env, GOODVIBES_DAEMON_HOME: daemonHomeDir },
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
return { reason: `Detached daemon spawn failed to launch: ${summarizeError(error)}` };
|
|
306
|
+
}
|
|
307
|
+
finally {
|
|
308
|
+
// The child has inherited the fds; the parent's copies can be closed now.
|
|
309
|
+
closeStdio?.();
|
|
310
|
+
}
|
|
311
|
+
child.unref();
|
|
312
|
+
let processError = null;
|
|
313
|
+
child.once?.('error', (err) => { processError = summarizeError(err); });
|
|
314
|
+
recordDetachedDaemonRuntime(runtimeDir, {
|
|
315
|
+
pid: child.pid,
|
|
316
|
+
host: daemonHost,
|
|
317
|
+
port: daemonPort,
|
|
318
|
+
command,
|
|
319
|
+
startedAt: new Date().toISOString(),
|
|
320
|
+
logFilePath,
|
|
321
|
+
});
|
|
322
|
+
const timeoutMs = factories.detachedSpawnProbeTimeoutMs ?? 5000;
|
|
323
|
+
const intervalMs = factories.detachedSpawnProbeIntervalMs ?? 150;
|
|
324
|
+
const sleep = factories.sleep ?? ((ms) => new Promise((resolve) => {
|
|
325
|
+
const timer = setTimeout(resolve, ms);
|
|
326
|
+
timer.unref?.();
|
|
327
|
+
}));
|
|
328
|
+
const deadline = Date.now() + timeoutMs;
|
|
329
|
+
let lastReason = 'Detached daemon did not become reachable before timeout';
|
|
330
|
+
// Probe at least once, then poll until the deadline.
|
|
331
|
+
for (;;) {
|
|
332
|
+
if (processError)
|
|
333
|
+
return { reason: `Detached daemon process error: ${processError}` };
|
|
334
|
+
const identity = await probeDaemonIdentity(daemonHost, daemonPort, factories.sharedDaemonToken);
|
|
335
|
+
if (identity.kind === 'goodvibes') {
|
|
336
|
+
const verified = resolveVerifiedDaemonStatus(identity, 'Spawned detached daemon for this session');
|
|
337
|
+
if (verified.mode === 'external') {
|
|
338
|
+
return { status: verified, hint: DETACHED_DAEMON_INSTALL_HINT };
|
|
339
|
+
}
|
|
340
|
+
// Incompatible: do not keep a competing daemon around; report honestly.
|
|
341
|
+
return { reason: verified.reason ?? 'Spawned daemon reported an incompatible version' };
|
|
342
|
+
}
|
|
343
|
+
lastReason = identity.reason ?? lastReason;
|
|
344
|
+
if (Date.now() >= deadline)
|
|
345
|
+
return { reason: lastReason };
|
|
346
|
+
await sleep(intervalMs);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
204
349
|
let embeddedDaemonServer = null;
|
|
205
350
|
let embeddedHttpListener = null;
|
|
206
|
-
let
|
|
351
|
+
let daemonStartHint;
|
|
352
|
+
let daemonStatus = createServiceStatus('disabled', daemonHost, daemonPort, { reason: 'daemon.enabled is false' });
|
|
207
353
|
let httpListenerStatus = createServiceStatus('disabled', httpListenerHost, httpListenerPort, {
|
|
208
354
|
reason: 'danger.httpListener is disabled',
|
|
209
355
|
});
|
|
210
|
-
if (
|
|
356
|
+
if (resolveDaemonEnabled(config)) {
|
|
211
357
|
if (await probeDaemonPortInUse(daemonHost, daemonPort)) {
|
|
212
358
|
const identity = await probeDaemonIdentity(daemonHost, daemonPort, factories.sharedDaemonToken);
|
|
213
359
|
if (identity.kind === 'goodvibes') {
|
|
214
|
-
daemonStatus =
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
port: daemonPort,
|
|
223
|
-
version: identity.version,
|
|
224
|
-
});
|
|
360
|
+
daemonStatus = resolveVerifiedDaemonStatus(identity, 'Existing GoodVibes daemon verified on configured host/port');
|
|
361
|
+
if (daemonStatus.mode === 'external') {
|
|
362
|
+
logger.info('Existing GoodVibes daemon detected; continuing without embedded daemon in this host instance', {
|
|
363
|
+
host: daemonHost,
|
|
364
|
+
port: daemonPort,
|
|
365
|
+
version: identity.version,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
225
368
|
}
|
|
226
369
|
else {
|
|
227
370
|
daemonStatus = createServiceStatus('blocked', daemonHost, daemonPort, {
|
|
@@ -236,45 +379,68 @@ export async function startHostServices(config, runtimeBus, hookDispatcher, runt
|
|
|
236
379
|
}
|
|
237
380
|
}
|
|
238
381
|
else {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
382
|
+
// Port is free. Owner ruling (D7a): the daemon is a SYSTEM SERVICE, so
|
|
383
|
+
// starting a surface must NOT couple the daemon's lifetime to this process.
|
|
384
|
+
// DEFAULT (Layer 2): spawn the daemon as a detached standalone process and
|
|
385
|
+
// adopt it as 'external'. In-process embedding is an explicit opt-in
|
|
386
|
+
// (Layer 3: daemon.embedInProcess).
|
|
387
|
+
const startEmbeddedDaemon = async () => {
|
|
388
|
+
const pendingDaemonServer = factories.createDaemonServer
|
|
389
|
+
? factories.createDaemonServer(runtimeBus, sharedUserAuth, runtimeServices)
|
|
390
|
+
: await createDefaultDaemonServer(runtimeBus, sharedUserAuth, runtimeServices);
|
|
391
|
+
const service = pendingDaemonServer;
|
|
392
|
+
service.enable({ daemon: true }, factories.sharedDaemonToken);
|
|
393
|
+
return startGuardedService({
|
|
394
|
+
label: 'Daemon server',
|
|
395
|
+
service,
|
|
396
|
+
timeoutMs: startupTimeoutMs,
|
|
397
|
+
timedOutStatus: () => createServiceStatus('unavailable', daemonHost, daemonPort, {
|
|
398
|
+
reason: 'Daemon server startup timed out',
|
|
399
|
+
}),
|
|
400
|
+
startedStatus: () => createServiceStatus('embedded', daemonHost, daemonPort, {
|
|
401
|
+
reason: 'Embedded daemon started in this host instance (daemon.embedInProcess opt-in)',
|
|
402
|
+
}),
|
|
403
|
+
bindConflictStatus: async (message) => {
|
|
404
|
+
const identity = await probeDaemonIdentity(daemonHost, daemonPort, factories.sharedDaemonToken);
|
|
405
|
+
if (identity.kind === 'goodvibes') {
|
|
406
|
+
const verified = resolveVerifiedDaemonStatus(identity, 'Existing GoodVibes daemon verified after bind conflict');
|
|
407
|
+
if (verified.mode === 'external') {
|
|
408
|
+
logger.info('Existing GoodVibes daemon detected after bind conflict; continuing without embedded daemon in this host instance', { host: daemonHost, port: daemonPort, version: identity.version });
|
|
409
|
+
}
|
|
410
|
+
return verified;
|
|
411
|
+
}
|
|
412
|
+
logger.warn('Daemon server port already in use; continuing without local daemon in this host instance', { error: message });
|
|
413
|
+
return createServiceStatus('blocked', daemonHost, daemonPort, {
|
|
414
|
+
authenticated: identity.kind !== 'unauthorized' ? undefined : false,
|
|
415
|
+
reason: identity.reason ?? message,
|
|
267
416
|
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
};
|
|
420
|
+
if (readDaemonEmbedInProcess(config)) {
|
|
421
|
+
logger.warn('daemon.embedInProcess is enabled: hosting the daemon in-process couples its lifetime to this surface (single point of failure)');
|
|
422
|
+
const started = await startEmbeddedDaemon();
|
|
423
|
+
embeddedDaemonServer = started.service;
|
|
424
|
+
daemonStatus = started.status;
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
const detached = await attemptDetachedDaemonSpawn();
|
|
428
|
+
if ('status' in detached) {
|
|
429
|
+
daemonStatus = detached.status;
|
|
430
|
+
daemonStartHint = detached.hint;
|
|
431
|
+
logger.info('Spawned detached GoodVibes daemon for this session', {
|
|
432
|
+
host: daemonHost,
|
|
433
|
+
port: daemonPort,
|
|
434
|
+
version: detached.status.version,
|
|
273
435
|
});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
logger.warn('Detached daemon spawn did not become reachable; falling back to in-process embedded daemon for this session', { reason: detached.reason });
|
|
439
|
+
const started = await startEmbeddedDaemon();
|
|
440
|
+
embeddedDaemonServer = started.service;
|
|
441
|
+
daemonStatus = started.status;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
278
444
|
}
|
|
279
445
|
}
|
|
280
446
|
if (readBooleanSetting(config, 'danger.httpListener')) {
|
|
@@ -317,6 +483,7 @@ export async function startHostServices(config, runtimeBus, hookDispatcher, runt
|
|
|
317
483
|
httpListener: embeddedHttpListener,
|
|
318
484
|
daemonStatus,
|
|
319
485
|
httpListenerStatus,
|
|
486
|
+
...(daemonStartHint !== undefined ? { daemonStartHint } : {}),
|
|
320
487
|
listRecentControlPlaneEvents(limit) {
|
|
321
488
|
return embeddedDaemonServer?.listRecentControlPlaneEvents(limit) ?? [];
|
|
322
489
|
},
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon-version-compat.ts
|
|
3
|
+
*
|
|
4
|
+
* The adopt-or-start path (bootstrap-services.ts) verifies that a daemon found
|
|
5
|
+
* on the configured port is a GoodVibes daemon via its `/status` identity probe,
|
|
6
|
+
* which reports the daemon's SDK `version`. Verifying identity is NOT the same as
|
|
7
|
+
* verifying that the daemon speaks the SAME wire shape this surface expects:
|
|
8
|
+
* adopting a daemon built from an incompatible SDK band produces silent
|
|
9
|
+
* wire-shape failures (a session method the surface calls that the daemon does
|
|
10
|
+
* not serve, a payload field that moved). This module answers the one question
|
|
11
|
+
* the probe leaves open — "may this surface safely adopt a daemon reporting
|
|
12
|
+
* version X?" — so the adopt path can refuse an incompatible occupant honestly
|
|
13
|
+
* instead of adopting it and failing later, and without ever starting a second
|
|
14
|
+
* competing daemon on an occupied port.
|
|
15
|
+
*
|
|
16
|
+
* Compatibility band policy (semver, https://semver.org/#spec-item-4):
|
|
17
|
+
* - `0.y.z` releases treat the MINOR position as the breaking axis, so two
|
|
18
|
+
* `0.y` versions are compatible only when `y` matches (0.38.x adopts 0.38.*
|
|
19
|
+
* but not 0.37.*).
|
|
20
|
+
* - `>=1.0.0` releases treat MAJOR as the breaking axis, so major must match
|
|
21
|
+
* (1.4.x adopts any 1.*.* but not 2.*.*).
|
|
22
|
+
* - A version string that cannot be parsed is treated as INCOMPATIBLE — the
|
|
23
|
+
* conservative, honest default. An empty/absent remote version is likewise
|
|
24
|
+
* incompatible: the surface must not adopt something it cannot band-check.
|
|
25
|
+
* Prerelease and build metadata (`-rc.1`, `+sha`) are ignored for banding.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* True when a surface reporting `localVersion` may safely adopt a daemon
|
|
29
|
+
* reporting `remoteVersion` — see the band policy in the file header.
|
|
30
|
+
* Unparseable or absent versions are never compatible.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isDaemonVersionCompatible(localVersion: string | undefined | null, remoteVersion: string | undefined | null): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Human-readable reason string for an incompatible adoption refusal, naming
|
|
35
|
+
* both the occupied endpoint's version and this surface's version so the
|
|
36
|
+
* operator can see the skew without guessing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function describeVersionIncompatibility(host: string, port: number, localVersion: string | undefined | null, remoteVersion: string | undefined | null): string;
|
|
39
|
+
//# sourceMappingURL=daemon-version-compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-version-compat.d.ts","sourceRoot":"","sources":["../../../src/platform/runtime/daemon-version-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AA0BH;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACvC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GACvC,OAAO,CAQT;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACvC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GACvC,MAAM,CAIR"}
|