@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.
Files changed (559) hide show
  1. package/dist/contracts/artifacts/operator-contract.json +4468 -916
  2. package/dist/daemon.d.ts +2 -0
  3. package/dist/daemon.d.ts.map +1 -1
  4. package/dist/daemon.js +4 -0
  5. package/dist/events/communication.d.ts +1 -1
  6. package/dist/events/surfaces.d.ts +25 -3
  7. package/dist/events/surfaces.d.ts.map +1 -1
  8. package/dist/events/surfaces.js +22 -1
  9. package/dist/events/workflows.d.ts +7 -6
  10. package/dist/events/workflows.d.ts.map +1 -1
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/platform/agents/archetypes.d.ts.map +1 -1
  14. package/dist/platform/agents/archetypes.js +7 -0
  15. package/dist/platform/agents/index.d.ts +1 -0
  16. package/dist/platform/agents/index.d.ts.map +1 -1
  17. package/dist/platform/agents/index.js +1 -0
  18. package/dist/platform/agents/orchestrator-runner.d.ts +16 -3
  19. package/dist/platform/agents/orchestrator-runner.d.ts.map +1 -1
  20. package/dist/platform/agents/orchestrator-runner.js +20 -6
  21. package/dist/platform/agents/orchestrator.d.ts +42 -10
  22. package/dist/platform/agents/orchestrator.d.ts.map +1 -1
  23. package/dist/platform/agents/orchestrator.js +68 -20
  24. package/dist/platform/agents/planner-decomposition-runner.d.ts +38 -0
  25. package/dist/platform/agents/planner-decomposition-runner.d.ts.map +1 -0
  26. package/dist/platform/agents/planner-decomposition-runner.js +113 -0
  27. package/dist/platform/agents/turn-knowledge-injection.d.ts +88 -3
  28. package/dist/platform/agents/turn-knowledge-injection.d.ts.map +1 -1
  29. package/dist/platform/agents/turn-knowledge-injection.js +147 -30
  30. package/dist/platform/agents/worktree.d.ts +126 -8
  31. package/dist/platform/agents/worktree.d.ts.map +1 -1
  32. package/dist/platform/agents/worktree.js +240 -19
  33. package/dist/platform/agents/wrfc-controller.d.ts +24 -1
  34. package/dist/platform/agents/wrfc-controller.d.ts.map +1 -1
  35. package/dist/platform/agents/wrfc-controller.js +161 -35
  36. package/dist/platform/agents/wrfc-gate-runtime.d.ts +9 -0
  37. package/dist/platform/agents/wrfc-gate-runtime.d.ts.map +1 -1
  38. package/dist/platform/agents/wrfc-gate-runtime.js +7 -3
  39. package/dist/platform/agents/wrfc-gates.d.ts +1 -1
  40. package/dist/platform/agents/wrfc-gates.d.ts.map +1 -1
  41. package/dist/platform/agents/wrfc-gates.js +7 -1
  42. package/dist/platform/agents/wrfc-types.d.ts +23 -3
  43. package/dist/platform/agents/wrfc-types.d.ts.map +1 -1
  44. package/dist/platform/automation/types.d.ts +9 -1
  45. package/dist/platform/automation/types.d.ts.map +1 -1
  46. package/dist/platform/calendar/calendar-api-shared.d.ts +25 -0
  47. package/dist/platform/calendar/calendar-api-shared.d.ts.map +1 -0
  48. package/dist/platform/calendar/calendar-api-shared.js +100 -0
  49. package/dist/platform/calendar/calendar-connector.d.ts +79 -0
  50. package/dist/platform/calendar/calendar-connector.d.ts.map +1 -0
  51. package/dist/platform/calendar/calendar-connector.js +155 -0
  52. package/dist/platform/calendar/google-calendar-api.d.ts +25 -0
  53. package/dist/platform/calendar/google-calendar-api.d.ts.map +1 -0
  54. package/dist/platform/calendar/google-calendar-api.js +89 -0
  55. package/dist/platform/calendar/http-fetch-adapter.d.ts +25 -0
  56. package/dist/platform/calendar/http-fetch-adapter.d.ts.map +1 -0
  57. package/dist/platform/calendar/http-fetch-adapter.js +25 -0
  58. package/dist/platform/calendar/ics-parser.d.ts +35 -0
  59. package/dist/platform/calendar/ics-parser.d.ts.map +1 -0
  60. package/dist/platform/calendar/ics-parser.js +236 -0
  61. package/dist/platform/calendar/index.d.ts +41 -0
  62. package/dist/platform/calendar/index.d.ts.map +1 -0
  63. package/dist/platform/calendar/index.js +49 -0
  64. package/dist/platform/calendar/merged-calendar-model.d.ts +67 -0
  65. package/dist/platform/calendar/merged-calendar-model.d.ts.map +1 -0
  66. package/dist/platform/calendar/merged-calendar-model.js +181 -0
  67. package/dist/platform/calendar/microsoft-graph-api.d.ts +25 -0
  68. package/dist/platform/calendar/microsoft-graph-api.d.ts.map +1 -0
  69. package/dist/platform/calendar/microsoft-graph-api.js +95 -0
  70. package/dist/platform/calendar/oauth-flow.d.ts +62 -0
  71. package/dist/platform/calendar/oauth-flow.d.ts.map +1 -0
  72. package/dist/platform/calendar/oauth-flow.js +305 -0
  73. package/dist/platform/calendar/oauth-providers.d.ts +43 -0
  74. package/dist/platform/calendar/oauth-providers.d.ts.map +1 -0
  75. package/dist/platform/calendar/oauth-providers.js +120 -0
  76. package/dist/platform/calendar/oauth-token-store.d.ts +72 -0
  77. package/dist/platform/calendar/oauth-token-store.d.ts.map +1 -0
  78. package/dist/platform/calendar/oauth-token-store.js +189 -0
  79. package/dist/platform/calendar/oauth-types.d.ts +274 -0
  80. package/dist/platform/calendar/oauth-types.d.ts.map +1 -0
  81. package/dist/platform/calendar/oauth-types.js +22 -0
  82. package/dist/platform/calendar/rrule.d.ts +39 -0
  83. package/dist/platform/calendar/rrule.d.ts.map +1 -0
  84. package/dist/platform/calendar/rrule.js +261 -0
  85. package/dist/platform/calendar/subscription-store.d.ts +118 -0
  86. package/dist/platform/calendar/subscription-store.d.ts.map +1 -0
  87. package/dist/platform/calendar/subscription-store.js +293 -0
  88. package/dist/platform/calendar/types.d.ts +170 -0
  89. package/dist/platform/calendar/types.d.ts.map +1 -0
  90. package/dist/platform/calendar/types.js +21 -0
  91. package/dist/platform/companion/companion-chat-attachments.d.ts +29 -0
  92. package/dist/platform/companion/companion-chat-attachments.d.ts.map +1 -0
  93. package/dist/platform/companion/companion-chat-attachments.js +121 -0
  94. package/dist/platform/companion/companion-chat-branching.d.ts +66 -0
  95. package/dist/platform/companion/companion-chat-branching.d.ts.map +1 -0
  96. package/dist/platform/companion/companion-chat-branching.js +142 -0
  97. package/dist/platform/companion/companion-chat-broker-bridge.d.ts +40 -0
  98. package/dist/platform/companion/companion-chat-broker-bridge.d.ts.map +1 -0
  99. package/dist/platform/companion/companion-chat-broker-bridge.js +14 -0
  100. package/dist/platform/companion/companion-chat-broker-sync.d.ts +38 -0
  101. package/dist/platform/companion/companion-chat-broker-sync.d.ts.map +1 -0
  102. package/dist/platform/companion/companion-chat-broker-sync.js +80 -0
  103. package/dist/platform/companion/companion-chat-gc.d.ts +63 -0
  104. package/dist/platform/companion/companion-chat-gc.d.ts.map +1 -0
  105. package/dist/platform/companion/companion-chat-gc.js +38 -0
  106. package/dist/platform/companion/companion-chat-manager.d.ts +91 -23
  107. package/dist/platform/companion/companion-chat-manager.d.ts.map +1 -1
  108. package/dist/platform/companion/companion-chat-manager.js +195 -223
  109. package/dist/platform/companion/companion-chat-persistence.d.ts +9 -1
  110. package/dist/platform/companion/companion-chat-persistence.d.ts.map +1 -1
  111. package/dist/platform/companion/companion-chat-persistence.js +10 -2
  112. package/dist/platform/companion/companion-chat-routes.d.ts +2 -1
  113. package/dist/platform/companion/companion-chat-routes.d.ts.map +1 -1
  114. package/dist/platform/companion/companion-chat-routes.js +113 -4
  115. package/dist/platform/companion/companion-chat-turn-execution.d.ts +61 -0
  116. package/dist/platform/companion/companion-chat-turn-execution.d.ts.map +1 -0
  117. package/dist/platform/companion/companion-chat-turn-execution.js +107 -0
  118. package/dist/platform/companion/companion-chat-types.d.ts +67 -0
  119. package/dist/platform/companion/companion-chat-types.d.ts.map +1 -1
  120. package/dist/platform/config/credential-status.d.ts +28 -0
  121. package/dist/platform/config/credential-status.d.ts.map +1 -0
  122. package/dist/platform/config/credential-status.js +75 -0
  123. package/dist/platform/config/index.d.ts +25 -0
  124. package/dist/platform/config/index.d.ts.map +1 -1
  125. package/dist/platform/config/index.js +18 -0
  126. package/dist/platform/config/manager.d.ts +9 -0
  127. package/dist/platform/config/manager.d.ts.map +1 -1
  128. package/dist/platform/config/manager.js +21 -2
  129. package/dist/platform/config/migrations.d.ts +48 -0
  130. package/dist/platform/config/migrations.d.ts.map +1 -0
  131. package/dist/platform/config/migrations.js +54 -0
  132. package/dist/platform/config/schema-domain-core.d.ts +10 -1
  133. package/dist/platform/config/schema-domain-core.d.ts.map +1 -1
  134. package/dist/platform/config/schema-domain-core.js +46 -3
  135. package/dist/platform/config/schema-domain-runtime.d.ts +8 -0
  136. package/dist/platform/config/schema-domain-runtime.d.ts.map +1 -1
  137. package/dist/platform/config/schema-domain-runtime.js +32 -0
  138. package/dist/platform/config/schema-types.d.ts +21 -7
  139. package/dist/platform/config/schema-types.d.ts.map +1 -1
  140. package/dist/platform/config/schema.d.ts.map +1 -1
  141. package/dist/platform/config/schema.js +2 -0
  142. package/dist/platform/control-plane/approval-broker.d.ts +11 -0
  143. package/dist/platform/control-plane/approval-broker.d.ts.map +1 -1
  144. package/dist/platform/control-plane/approval-broker.js +17 -1
  145. package/dist/platform/control-plane/approval-hunk-apply.d.ts +77 -0
  146. package/dist/platform/control-plane/approval-hunk-apply.d.ts.map +1 -0
  147. package/dist/platform/control-plane/approval-hunk-apply.js +80 -0
  148. package/dist/platform/control-plane/gateway-disabled-response.d.ts +20 -0
  149. package/dist/platform/control-plane/gateway-disabled-response.d.ts.map +1 -0
  150. package/dist/platform/control-plane/gateway-disabled-response.js +24 -0
  151. package/dist/platform/control-plane/gateway-scope-enforcement.d.ts +68 -0
  152. package/dist/platform/control-plane/gateway-scope-enforcement.d.ts.map +1 -0
  153. package/dist/platform/control-plane/gateway-scope-enforcement.js +91 -0
  154. package/dist/platform/control-plane/gateway-utils.d.ts +17 -0
  155. package/dist/platform/control-plane/gateway-utils.d.ts.map +1 -1
  156. package/dist/platform/control-plane/gateway-utils.js +30 -0
  157. package/dist/platform/control-plane/gateway.d.ts +12 -2
  158. package/dist/platform/control-plane/gateway.d.ts.map +1 -1
  159. package/dist/platform/control-plane/gateway.js +27 -31
  160. package/dist/platform/control-plane/index.d.ts +8 -1
  161. package/dist/platform/control-plane/index.d.ts.map +1 -1
  162. package/dist/platform/control-plane/index.js +8 -0
  163. package/dist/platform/control-plane/invoke-input-validation.d.ts +56 -0
  164. package/dist/platform/control-plane/invoke-input-validation.d.ts.map +1 -0
  165. package/dist/platform/control-plane/invoke-input-validation.js +163 -0
  166. package/dist/platform/control-plane/method-catalog-admin.d.ts.map +1 -1
  167. package/dist/platform/control-plane/method-catalog-admin.js +12 -1
  168. package/dist/platform/control-plane/method-catalog-calendar.d.ts +16 -0
  169. package/dist/platform/control-plane/method-catalog-calendar.d.ts.map +1 -1
  170. package/dist/platform/control-plane/method-catalog-calendar.js +21 -0
  171. package/dist/platform/control-plane/method-catalog-channels.d.ts.map +1 -1
  172. package/dist/platform/control-plane/method-catalog-channels.js +32 -3
  173. package/dist/platform/control-plane/method-catalog-control-automation.d.ts.map +1 -1
  174. package/dist/platform/control-plane/method-catalog-control-automation.js +19 -34
  175. package/dist/platform/control-plane/method-catalog-control-companion.d.ts +15 -0
  176. package/dist/platform/control-plane/method-catalog-control-companion.d.ts.map +1 -0
  177. package/dist/platform/control-plane/method-catalog-control-companion.js +176 -0
  178. package/dist/platform/control-plane/method-catalog-control-core.d.ts.map +1 -1
  179. package/dist/platform/control-plane/method-catalog-control-core.js +104 -122
  180. package/dist/platform/control-plane/method-catalog-control.d.ts.map +1 -1
  181. package/dist/platform/control-plane/method-catalog-control.js +4 -0
  182. package/dist/platform/control-plane/method-catalog-email.d.ts +17 -0
  183. package/dist/platform/control-plane/method-catalog-email.d.ts.map +1 -1
  184. package/dist/platform/control-plane/method-catalog-email.js +21 -0
  185. package/dist/platform/control-plane/method-catalog-events.d.ts +28 -0
  186. package/dist/platform/control-plane/method-catalog-events.d.ts.map +1 -1
  187. package/dist/platform/control-plane/method-catalog-events.js +74 -1
  188. package/dist/platform/control-plane/method-catalog-fleet.d.ts +24 -0
  189. package/dist/platform/control-plane/method-catalog-fleet.d.ts.map +1 -0
  190. package/dist/platform/control-plane/method-catalog-fleet.js +65 -0
  191. package/dist/platform/control-plane/method-catalog-push.d.ts +30 -0
  192. package/dist/platform/control-plane/method-catalog-push.d.ts.map +1 -0
  193. package/dist/platform/control-plane/method-catalog-push.js +80 -0
  194. package/dist/platform/control-plane/method-catalog-route-reconcile.d.ts +84 -0
  195. package/dist/platform/control-plane/method-catalog-route-reconcile.d.ts.map +1 -0
  196. package/dist/platform/control-plane/method-catalog-route-reconcile.js +103 -0
  197. package/dist/platform/control-plane/method-catalog-runtime.d.ts.map +1 -1
  198. package/dist/platform/control-plane/method-catalog-runtime.js +83 -1
  199. package/dist/platform/control-plane/method-catalog-shared.d.ts +29 -0
  200. package/dist/platform/control-plane/method-catalog-shared.d.ts.map +1 -1
  201. package/dist/platform/control-plane/method-catalog.d.ts +9 -0
  202. package/dist/platform/control-plane/method-catalog.d.ts.map +1 -1
  203. package/dist/platform/control-plane/method-catalog.js +34 -3
  204. package/dist/platform/control-plane/operator-contract-schemas-admin.d.ts +8 -0
  205. package/dist/platform/control-plane/operator-contract-schemas-admin.d.ts.map +1 -1
  206. package/dist/platform/control-plane/operator-contract-schemas-admin.js +22 -1
  207. package/dist/platform/control-plane/operator-contract-schemas-fleet.d.ts +18 -0
  208. package/dist/platform/control-plane/operator-contract-schemas-fleet.d.ts.map +1 -0
  209. package/dist/platform/control-plane/operator-contract-schemas-fleet.js +182 -0
  210. package/dist/platform/control-plane/operator-contract-schemas-permissions.d.ts.map +1 -1
  211. package/dist/platform/control-plane/operator-contract-schemas-permissions.js +5 -0
  212. package/dist/platform/control-plane/operator-contract-schemas-runtime.d.ts +37 -0
  213. package/dist/platform/control-plane/operator-contract-schemas-runtime.d.ts.map +1 -1
  214. package/dist/platform/control-plane/operator-contract-schemas-runtime.js +100 -3
  215. package/dist/platform/control-plane/operator-contract-schemas.d.ts +1 -0
  216. package/dist/platform/control-plane/operator-contract-schemas.d.ts.map +1 -1
  217. package/dist/platform/control-plane/operator-contract-schemas.js +1 -0
  218. package/dist/platform/control-plane/operator-contract.d.ts.map +1 -1
  219. package/dist/platform/control-plane/operator-contract.js +8 -0
  220. package/dist/platform/control-plane/routes/checkpoints.d.ts +39 -0
  221. package/dist/platform/control-plane/routes/checkpoints.d.ts.map +1 -0
  222. package/dist/platform/control-plane/routes/checkpoints.js +166 -0
  223. package/dist/platform/control-plane/routes/fleet.d.ts +53 -0
  224. package/dist/platform/control-plane/routes/fleet.d.ts.map +1 -0
  225. package/dist/platform/control-plane/routes/fleet.js +153 -0
  226. package/dist/platform/control-plane/routes/gateway-verb-error.d.ts +30 -0
  227. package/dist/platform/control-plane/routes/gateway-verb-error.d.ts.map +1 -0
  228. package/dist/platform/control-plane/routes/gateway-verb-error.js +36 -0
  229. package/dist/platform/control-plane/routes/index.d.ts +0 -6
  230. package/dist/platform/control-plane/routes/index.d.ts.map +1 -1
  231. package/dist/platform/control-plane/routes/index.js +5 -5
  232. package/dist/platform/control-plane/routes/invocation-params.d.ts +23 -0
  233. package/dist/platform/control-plane/routes/invocation-params.d.ts.map +1 -0
  234. package/dist/platform/control-plane/routes/invocation-params.js +9 -0
  235. package/dist/platform/control-plane/routes/push.d.ts +26 -0
  236. package/dist/platform/control-plane/routes/push.d.ts.map +1 -0
  237. package/dist/platform/control-plane/routes/push.js +104 -0
  238. package/dist/platform/control-plane/routes/register-gateway-verb-groups.d.ts +31 -0
  239. package/dist/platform/control-plane/routes/register-gateway-verb-groups.d.ts.map +1 -0
  240. package/dist/platform/control-plane/routes/register-gateway-verb-groups.js +16 -0
  241. package/dist/platform/control-plane/routes/register-w3-s2.d.ts +26 -0
  242. package/dist/platform/control-plane/routes/register-w3-s2.d.ts.map +1 -0
  243. package/dist/platform/control-plane/routes/register-w3-s2.js +8 -0
  244. package/dist/platform/control-plane/routes/session-search.d.ts +37 -0
  245. package/dist/platform/control-plane/routes/session-search.d.ts.map +1 -0
  246. package/dist/platform/control-plane/routes/session-search.js +113 -0
  247. package/dist/platform/control-plane/session-broker-gc.d.ts +16 -0
  248. package/dist/platform/control-plane/session-broker-gc.d.ts.map +1 -1
  249. package/dist/platform/control-plane/session-broker-gc.js +23 -6
  250. package/dist/platform/control-plane/session-broker-helpers.d.ts +3 -3
  251. package/dist/platform/control-plane/session-broker-helpers.d.ts.map +1 -1
  252. package/dist/platform/control-plane/session-broker-inputs.d.ts +18 -0
  253. package/dist/platform/control-plane/session-broker-inputs.d.ts.map +1 -1
  254. package/dist/platform/control-plane/session-broker-inputs.js +34 -0
  255. package/dist/platform/control-plane/session-broker-sessions.d.ts +102 -3
  256. package/dist/platform/control-plane/session-broker-sessions.d.ts.map +1 -1
  257. package/dist/platform/control-plane/session-broker-sessions.js +179 -5
  258. package/dist/platform/control-plane/session-broker-state.d.ts +20 -1
  259. package/dist/platform/control-plane/session-broker-state.d.ts.map +1 -1
  260. package/dist/platform/control-plane/session-broker-state.js +67 -5
  261. package/dist/platform/control-plane/session-broker.d.ts +51 -38
  262. package/dist/platform/control-plane/session-broker.d.ts.map +1 -1
  263. package/dist/platform/control-plane/session-broker.js +183 -75
  264. package/dist/platform/control-plane/session-store-importer.d.ts +57 -0
  265. package/dist/platform/control-plane/session-store-importer.d.ts.map +1 -0
  266. package/dist/platform/control-plane/session-store-importer.js +227 -0
  267. package/dist/platform/control-plane/session-types.d.ts +142 -7
  268. package/dist/platform/control-plane/session-types.d.ts.map +1 -1
  269. package/dist/platform/core/execution-plan.d.ts +43 -1
  270. package/dist/platform/core/execution-plan.d.ts.map +1 -1
  271. package/dist/platform/core/execution-plan.js +46 -10
  272. package/dist/platform/core/index.d.ts +1 -0
  273. package/dist/platform/core/index.d.ts.map +1 -1
  274. package/dist/platform/core/index.js +1 -0
  275. package/dist/platform/core/orchestrator-runtime.d.ts +23 -3
  276. package/dist/platform/core/orchestrator-runtime.d.ts.map +1 -1
  277. package/dist/platform/core/orchestrator-tool-runtime.d.ts +7 -0
  278. package/dist/platform/core/orchestrator-tool-runtime.d.ts.map +1 -1
  279. package/dist/platform/core/orchestrator-tool-runtime.js +10 -0
  280. package/dist/platform/core/orchestrator-turn-loop.d.ts +13 -6
  281. package/dist/platform/core/orchestrator-turn-loop.d.ts.map +1 -1
  282. package/dist/platform/core/orchestrator-turn-loop.js +29 -22
  283. package/dist/platform/core/orchestrator.d.ts +16 -10
  284. package/dist/platform/core/orchestrator.d.ts.map +1 -1
  285. package/dist/platform/core/orchestrator.js +23 -8
  286. package/dist/platform/core/plan-decomposition.d.ts +196 -0
  287. package/dist/platform/core/plan-decomposition.d.ts.map +1 -0
  288. package/dist/platform/core/plan-decomposition.js +417 -0
  289. package/dist/platform/core/plan-proposal.d.ts +39 -0
  290. package/dist/platform/core/plan-proposal.d.ts.map +1 -1
  291. package/dist/platform/core/wrfc-routing.d.ts +1 -0
  292. package/dist/platform/core/wrfc-routing.d.ts.map +1 -1
  293. package/dist/platform/core/wrfc-routing.js +51 -1
  294. package/dist/platform/daemon/boot.d.ts +69 -0
  295. package/dist/platform/daemon/boot.d.ts.map +1 -0
  296. package/dist/platform/daemon/boot.js +61 -0
  297. package/dist/platform/daemon/cli.js +2 -1
  298. package/dist/platform/daemon/control-plane.d.ts.map +1 -1
  299. package/dist/platform/daemon/control-plane.js +50 -1
  300. package/dist/platform/daemon/facade-composition.d.ts.map +1 -1
  301. package/dist/platform/daemon/facade-composition.js +6 -0
  302. package/dist/platform/daemon/facade.d.ts +15 -6
  303. package/dist/platform/daemon/facade.d.ts.map +1 -1
  304. package/dist/platform/daemon/facade.js +48 -43
  305. package/dist/platform/daemon/http/router-route-contexts.d.ts +1 -0
  306. package/dist/platform/daemon/http/router-route-contexts.d.ts.map +1 -1
  307. package/dist/platform/daemon/http/router-route-contexts.js +1 -0
  308. package/dist/platform/daemon/http/router-session-broker-adapter.d.ts +13 -0
  309. package/dist/platform/daemon/http/router-session-broker-adapter.d.ts.map +1 -0
  310. package/dist/platform/daemon/http/router-session-broker-adapter.js +27 -0
  311. package/dist/platform/daemon/http/router.d.ts +2 -1
  312. package/dist/platform/daemon/http/router.d.ts.map +1 -1
  313. package/dist/platform/daemon/http/router.js +42 -40
  314. package/dist/platform/daemon/http/runtime-route-types.d.ts +42 -4
  315. package/dist/platform/daemon/http/runtime-route-types.d.ts.map +1 -1
  316. package/dist/platform/daemon/http/webui-serving.d.ts +68 -0
  317. package/dist/platform/daemon/http/webui-serving.d.ts.map +1 -0
  318. package/dist/platform/daemon/http/webui-serving.js +230 -0
  319. package/dist/platform/daemon/index.d.ts +2 -0
  320. package/dist/platform/daemon/index.d.ts.map +1 -1
  321. package/dist/platform/daemon/index.js +1 -0
  322. package/dist/platform/daemon/service-manager.d.ts +16 -0
  323. package/dist/platform/daemon/service-manager.d.ts.map +1 -1
  324. package/dist/platform/daemon/service-manager.js +79 -15
  325. package/dist/platform/intelligence/tree-sitter/service.d.ts.map +1 -1
  326. package/dist/platform/intelligence/tree-sitter/service.js +16 -2
  327. package/dist/platform/knowledge/browser-history/readers.d.ts.map +1 -1
  328. package/dist/platform/knowledge/browser-history/readers.js +15 -5
  329. package/dist/platform/knowledge/knowledge-api.d.ts +1 -1
  330. package/dist/platform/knowledge/project-planning/service.d.ts +14 -1
  331. package/dist/platform/knowledge/project-planning/service.d.ts.map +1 -1
  332. package/dist/platform/knowledge/project-planning/service.js +77 -0
  333. package/dist/platform/knowledge/project-planning/types.d.ts +32 -0
  334. package/dist/platform/knowledge/project-planning/types.d.ts.map +1 -1
  335. package/dist/platform/orchestration/bookkeeping.d.ts +12 -0
  336. package/dist/platform/orchestration/bookkeeping.d.ts.map +1 -0
  337. package/dist/platform/orchestration/bookkeeping.js +91 -0
  338. package/dist/platform/orchestration/budget.d.ts +2 -2
  339. package/dist/platform/orchestration/cancellation.d.ts +2 -2
  340. package/dist/platform/orchestration/controller-compat.d.ts +16 -3
  341. package/dist/platform/orchestration/controller-compat.d.ts.map +1 -1
  342. package/dist/platform/orchestration/controller-compat.js +18 -4
  343. package/dist/platform/orchestration/dirty-guard.js +1 -1
  344. package/dist/platform/orchestration/engine.d.ts +26 -1
  345. package/dist/platform/orchestration/engine.d.ts.map +1 -1
  346. package/dist/platform/orchestration/engine.js +229 -25
  347. package/dist/platform/orchestration/index.d.ts +6 -4
  348. package/dist/platform/orchestration/index.d.ts.map +1 -1
  349. package/dist/platform/orchestration/index.js +3 -2
  350. package/dist/platform/orchestration/persistence.d.ts.map +1 -1
  351. package/dist/platform/orchestration/persistence.js +6 -3
  352. package/dist/platform/orchestration/phase-runner.d.ts +33 -6
  353. package/dist/platform/orchestration/phase-runner.d.ts.map +1 -1
  354. package/dist/platform/orchestration/phase-runner.js +98 -25
  355. package/dist/platform/orchestration/proposal-workstream.d.ts +56 -0
  356. package/dist/platform/orchestration/proposal-workstream.d.ts.map +1 -0
  357. package/dist/platform/orchestration/proposal-workstream.js +76 -0
  358. package/dist/platform/orchestration/scheduler.d.ts +20 -1
  359. package/dist/platform/orchestration/scheduler.d.ts.map +1 -1
  360. package/dist/platform/orchestration/scheduler.js +16 -0
  361. package/dist/platform/orchestration/types.d.ts +289 -4
  362. package/dist/platform/orchestration/types.d.ts.map +1 -1
  363. package/dist/platform/orchestration/types.js +32 -0
  364. package/dist/platform/orchestration/worktree-isolation.d.ts +33 -0
  365. package/dist/platform/orchestration/worktree-isolation.d.ts.map +1 -0
  366. package/dist/platform/orchestration/worktree-isolation.js +248 -0
  367. package/dist/platform/presentation/glyphs.d.ts +91 -0
  368. package/dist/platform/presentation/glyphs.d.ts.map +1 -0
  369. package/dist/platform/presentation/glyphs.js +93 -0
  370. package/dist/platform/presentation/index.d.ts +28 -0
  371. package/dist/platform/presentation/index.d.ts.map +1 -0
  372. package/dist/platform/presentation/index.js +27 -0
  373. package/dist/platform/presentation/thinking-phrases.d.ts +12 -0
  374. package/dist/platform/presentation/thinking-phrases.d.ts.map +1 -0
  375. package/dist/platform/presentation/thinking-phrases.js +32 -0
  376. package/dist/platform/presentation/tones.d.ts +121 -0
  377. package/dist/platform/presentation/tones.d.ts.map +1 -0
  378. package/dist/platform/presentation/tones.js +145 -0
  379. package/dist/platform/presentation/waiting-wording.d.ts +54 -0
  380. package/dist/platform/presentation/waiting-wording.d.ts.map +1 -0
  381. package/dist/platform/presentation/waiting-wording.js +51 -0
  382. package/dist/platform/providers/runtime-snapshot.d.ts.map +1 -1
  383. package/dist/platform/providers/runtime-snapshot.js +12 -2
  384. package/dist/platform/push/delivery.d.ts +48 -0
  385. package/dist/platform/push/delivery.d.ts.map +1 -0
  386. package/dist/platform/push/delivery.js +117 -0
  387. package/dist/platform/push/encryption.d.ts +41 -0
  388. package/dist/platform/push/encryption.d.ts.map +1 -0
  389. package/dist/platform/push/encryption.js +82 -0
  390. package/dist/platform/push/index.d.ts +17 -0
  391. package/dist/platform/push/index.d.ts.map +1 -0
  392. package/dist/platform/push/index.js +10 -0
  393. package/dist/platform/push/service.d.ts +75 -0
  394. package/dist/platform/push/service.d.ts.map +1 -0
  395. package/dist/platform/push/service.js +95 -0
  396. package/dist/platform/push/subscription-store.d.ts +50 -0
  397. package/dist/platform/push/subscription-store.d.ts.map +1 -0
  398. package/dist/platform/push/subscription-store.js +123 -0
  399. package/dist/platform/push/types.d.ts +68 -0
  400. package/dist/platform/push/types.d.ts.map +1 -0
  401. package/dist/platform/push/types.js +13 -0
  402. package/dist/platform/push/vapid.d.ts +54 -0
  403. package/dist/platform/push/vapid.d.ts.map +1 -0
  404. package/dist/platform/push/vapid.js +113 -0
  405. package/dist/platform/runtime/bootstrap-services.d.ts +62 -2
  406. package/dist/platform/runtime/bootstrap-services.d.ts.map +1 -1
  407. package/dist/platform/runtime/bootstrap-services.js +217 -50
  408. package/dist/platform/runtime/daemon-version-compat.d.ts +39 -0
  409. package/dist/platform/runtime/daemon-version-compat.d.ts.map +1 -0
  410. package/dist/platform/runtime/daemon-version-compat.js +75 -0
  411. package/dist/platform/runtime/detached-daemon-runtime.d.ts +26 -0
  412. package/dist/platform/runtime/detached-daemon-runtime.d.ts.map +1 -0
  413. package/dist/platform/runtime/detached-daemon-runtime.js +49 -0
  414. package/dist/platform/runtime/emitters/workflows.d.ts +1 -1
  415. package/dist/platform/runtime/emitters/workflows.d.ts.map +1 -1
  416. package/dist/platform/runtime/events/index.d.ts +13 -0
  417. package/dist/platform/runtime/events/index.d.ts.map +1 -1
  418. package/dist/platform/runtime/events/index.js +13 -0
  419. package/dist/platform/runtime/feature-flags/flags.d.ts.map +1 -1
  420. package/dist/platform/runtime/feature-flags/flags.js +39 -1
  421. package/dist/platform/runtime/fleet/adapters/agent.d.ts +2 -2
  422. package/dist/platform/runtime/fleet/adapters/agent.d.ts.map +1 -1
  423. package/dist/platform/runtime/fleet/adapters/agent.js +4 -4
  424. package/dist/platform/runtime/fleet/adapters/automation.d.ts +1 -1
  425. package/dist/platform/runtime/fleet/adapters/automation.js +1 -1
  426. package/dist/platform/runtime/fleet/adapters/code-index.d.ts +1 -1
  427. package/dist/platform/runtime/fleet/adapters/code-index.js +1 -1
  428. package/dist/platform/runtime/fleet/adapters/orchestration.d.ts +40 -18
  429. package/dist/platform/runtime/fleet/adapters/orchestration.d.ts.map +1 -1
  430. package/dist/platform/runtime/fleet/adapters/orchestration.js +138 -34
  431. package/dist/platform/runtime/fleet/adapters/schedule.d.ts +4 -4
  432. package/dist/platform/runtime/fleet/adapters/schedule.js +4 -4
  433. package/dist/platform/runtime/fleet/adapters/trigger.d.ts +3 -4
  434. package/dist/platform/runtime/fleet/adapters/trigger.d.ts.map +1 -1
  435. package/dist/platform/runtime/fleet/adapters/trigger.js +3 -4
  436. package/dist/platform/runtime/fleet/adapters/wrfc.d.ts +13 -0
  437. package/dist/platform/runtime/fleet/adapters/wrfc.d.ts.map +1 -1
  438. package/dist/platform/runtime/fleet/adapters/wrfc.js +49 -2
  439. package/dist/platform/runtime/fleet/registry.d.ts +7 -7
  440. package/dist/platform/runtime/fleet/registry.d.ts.map +1 -1
  441. package/dist/platform/runtime/fleet/registry.js +41 -7
  442. package/dist/platform/runtime/fleet/types.d.ts +9 -9
  443. package/dist/platform/runtime/fleet/types.d.ts.map +1 -1
  444. package/dist/platform/runtime/memory-spine/client.d.ts +127 -0
  445. package/dist/platform/runtime/memory-spine/client.d.ts.map +1 -0
  446. package/dist/platform/runtime/memory-spine/client.js +113 -0
  447. package/dist/platform/runtime/memory-spine/index.d.ts +11 -0
  448. package/dist/platform/runtime/memory-spine/index.d.ts.map +1 -0
  449. package/dist/platform/runtime/memory-spine/index.js +10 -0
  450. package/dist/platform/runtime/operator-client.d.ts +20 -2
  451. package/dist/platform/runtime/operator-client.d.ts.map +1 -1
  452. package/dist/platform/runtime/operator-client.js +11 -1
  453. package/dist/platform/runtime/provider-accounts/registry.d.ts.map +1 -1
  454. package/dist/platform/runtime/provider-accounts/registry.js +11 -1
  455. package/dist/platform/runtime/services.d.ts +11 -9
  456. package/dist/platform/runtime/services.d.ts.map +1 -1
  457. package/dist/platform/runtime/services.js +24 -9
  458. package/dist/platform/runtime/session-spine/client.d.ts +234 -0
  459. package/dist/platform/runtime/session-spine/client.d.ts.map +1 -0
  460. package/dist/platform/runtime/session-spine/client.js +449 -0
  461. package/dist/platform/runtime/session-spine/index.d.ts +12 -0
  462. package/dist/platform/runtime/session-spine/index.d.ts.map +1 -0
  463. package/dist/platform/runtime/session-spine/index.js +11 -0
  464. package/dist/platform/runtime/session-spine/union-cache.d.ts +225 -0
  465. package/dist/platform/runtime/session-spine/union-cache.d.ts.map +1 -0
  466. package/dist/platform/runtime/session-spine/union-cache.js +333 -0
  467. package/dist/platform/runtime/shell-command-ops.d.ts +3 -1
  468. package/dist/platform/runtime/shell-command-ops.d.ts.map +1 -1
  469. package/dist/platform/runtime/transports/daemon-http-client-validators.d.ts.map +1 -1
  470. package/dist/platform/runtime/transports/daemon-http-client-validators.js +22 -0
  471. package/dist/platform/runtime/transports/daemon-http-client.d.ts.map +1 -1
  472. package/dist/platform/runtime/transports/daemon-http-client.js +25 -2
  473. package/dist/platform/runtime/transports/http-types.d.ts +9 -2
  474. package/dist/platform/runtime/transports/http-types.d.ts.map +1 -1
  475. package/dist/platform/state/canonical-memory.d.ts +95 -0
  476. package/dist/platform/state/canonical-memory.d.ts.map +1 -0
  477. package/dist/platform/state/canonical-memory.js +155 -0
  478. package/dist/platform/state/code-index-chunking.js +1 -1
  479. package/dist/platform/state/code-index-db.d.ts +1 -1
  480. package/dist/platform/state/code-index-reindex.d.ts +73 -0
  481. package/dist/platform/state/code-index-reindex.d.ts.map +1 -0
  482. package/dist/platform/state/code-index-reindex.js +156 -0
  483. package/dist/platform/state/code-index-store.d.ts.map +1 -1
  484. package/dist/platform/state/code-index-store.js +11 -3
  485. package/dist/platform/state/index.d.ts +8 -0
  486. package/dist/platform/state/index.d.ts.map +1 -1
  487. package/dist/platform/state/index.js +4 -0
  488. package/dist/platform/state/memory-recall-contract.d.ts +118 -0
  489. package/dist/platform/state/memory-recall-contract.d.ts.map +1 -0
  490. package/dist/platform/state/memory-recall-contract.js +170 -0
  491. package/dist/platform/state/memory-registry.d.ts +8 -0
  492. package/dist/platform/state/memory-registry.d.ts.map +1 -1
  493. package/dist/platform/state/memory-registry.js +10 -0
  494. package/dist/platform/state/memory-store.d.ts +2 -0
  495. package/dist/platform/state/memory-store.d.ts.map +1 -1
  496. package/dist/platform/state/memory-store.js +4 -0
  497. package/dist/platform/state/memory-vector-store.d.ts.map +1 -1
  498. package/dist/platform/state/memory-vector-store.js +14 -3
  499. package/dist/platform/state/sqlite-store.d.ts +2 -0
  500. package/dist/platform/state/sqlite-store.d.ts.map +1 -1
  501. package/dist/platform/state/sqlite-store.js +4 -0
  502. package/dist/platform/state/sqlite-vec-loader.d.ts +1 -1
  503. package/dist/platform/state/sqlite-vec-loader.js +1 -1
  504. package/dist/platform/state/vibe-projection.d.ts +67 -0
  505. package/dist/platform/state/vibe-projection.d.ts.map +1 -0
  506. package/dist/platform/state/vibe-projection.js +115 -0
  507. package/dist/platform/tools/agent/index.d.ts.map +1 -1
  508. package/dist/platform/tools/agent/index.js +8 -0
  509. package/dist/platform/tools/agent/manager.d.ts +22 -10
  510. package/dist/platform/tools/agent/manager.d.ts.map +1 -1
  511. package/dist/platform/tools/agent/manager.js +13 -7
  512. package/dist/platform/tools/agent/schema.d.ts +26 -0
  513. package/dist/platform/tools/agent/schema.d.ts.map +1 -1
  514. package/dist/platform/tools/agent/schema.js +2 -2
  515. package/dist/platform/tools/agent/wrfc-batch-policy.d.ts +13 -0
  516. package/dist/platform/tools/agent/wrfc-batch-policy.d.ts.map +1 -1
  517. package/dist/platform/tools/agent/wrfc-batch-policy.js +60 -0
  518. package/dist/platform/tools/exec/runtime.d.ts +10 -0
  519. package/dist/platform/tools/exec/runtime.d.ts.map +1 -1
  520. package/dist/platform/tools/exec/runtime.js +27 -10
  521. package/dist/platform/tools/exec/schema.d.ts +2 -2
  522. package/dist/platform/tools/exec/schema.d.ts.map +1 -1
  523. package/dist/platform/tools/exec/schema.js +2 -1
  524. package/dist/platform/tools/fetch/runtime.d.ts +1 -1
  525. package/dist/platform/tools/index.d.ts +2 -0
  526. package/dist/platform/tools/index.d.ts.map +1 -1
  527. package/dist/platform/tools/index.js +2 -0
  528. package/dist/platform/tools/registry.d.ts +1 -1
  529. package/dist/platform/tools/registry.js +1 -1
  530. package/dist/platform/tools/state/index.d.ts +9 -0
  531. package/dist/platform/tools/state/index.d.ts.map +1 -1
  532. package/dist/platform/tools/state/index.js +60 -3
  533. package/dist/platform/types/foundation-contract.d.ts +1 -1
  534. package/dist/platform/types/foundation-contract.d.ts.map +1 -1
  535. package/dist/platform/types/index.d.ts +1 -1
  536. package/dist/platform/types/index.d.ts.map +1 -1
  537. package/dist/platform/types/tools.d.ts +1 -1
  538. package/dist/platform/utils/request-body.d.ts.map +1 -1
  539. package/dist/platform/utils/request-body.js +50 -5
  540. package/dist/platform/version.js +1 -1
  541. package/package.json +25 -9
  542. package/dist/platform/control-plane/routes/automation.d.ts +0 -3
  543. package/dist/platform/control-plane/routes/automation.d.ts.map +0 -1
  544. package/dist/platform/control-plane/routes/automation.js +0 -63
  545. package/dist/platform/control-plane/routes/context.d.ts +0 -2
  546. package/dist/platform/control-plane/routes/context.d.ts.map +0 -1
  547. package/dist/platform/control-plane/routes/context.js +0 -1
  548. package/dist/platform/control-plane/routes/operator.d.ts +0 -8
  549. package/dist/platform/control-plane/routes/operator.d.ts.map +0 -1
  550. package/dist/platform/control-plane/routes/operator.js +0 -415
  551. package/dist/platform/control-plane/routes/remote.d.ts +0 -3
  552. package/dist/platform/control-plane/routes/remote.d.ts.map +0 -1
  553. package/dist/platform/control-plane/routes/remote.js +0 -35
  554. package/dist/platform/control-plane/routes/sessions.d.ts +0 -3
  555. package/dist/platform/control-plane/routes/sessions.d.ts.map +0 -1
  556. package/dist/platform/control-plane/routes/sessions.js +0 -43
  557. package/dist/platform/control-plane/routes/tasks.d.ts +0 -3
  558. package/dist/platform/control-plane/routes/tasks.d.ts.map +0 -1
  559. 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: 'danger.daemon' | 'danger.httpListener' | 'controlPlane.host' | 'controlPlane.port' | 'httpListener.host' | 'httpListener.port'): boolean | string | number;
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":"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"}
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 daemonStatus = createServiceStatus('disabled', daemonHost, daemonPort, { reason: 'danger.daemon is disabled' });
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 (readBooleanSetting(config, 'danger.daemon')) {
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 = createServiceStatus('external', daemonHost, daemonPort, {
215
- authenticated: true,
216
- status: identity.status,
217
- version: identity.version,
218
- reason: 'Existing GoodVibes daemon verified on configured host/port',
219
- });
220
- logger.info('Existing GoodVibes daemon detected; continuing without embedded daemon in this host instance', {
221
- host: daemonHost,
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
- const pendingDaemonServer = factories.createDaemonServer
240
- ? factories.createDaemonServer(runtimeBus, sharedUserAuth, runtimeServices)
241
- : await createDefaultDaemonServer(runtimeBus, sharedUserAuth, runtimeServices);
242
- const service = pendingDaemonServer;
243
- service.enable({ daemon: true }, factories.sharedDaemonToken);
244
- const started = await startGuardedService({
245
- label: 'Daemon server',
246
- service,
247
- timeoutMs: startupTimeoutMs,
248
- timedOutStatus: () => createServiceStatus('unavailable', daemonHost, daemonPort, {
249
- reason: 'Daemon server startup timed out',
250
- }),
251
- startedStatus: () => createServiceStatus('embedded', daemonHost, daemonPort, {
252
- reason: 'Embedded daemon started in this host instance',
253
- }),
254
- bindConflictStatus: async (message) => {
255
- const identity = await probeDaemonIdentity(daemonHost, daemonPort, factories.sharedDaemonToken);
256
- if (identity.kind === 'goodvibes') {
257
- logger.info('Existing GoodVibes daemon detected after bind conflict; continuing without embedded daemon in this host instance', {
258
- host: daemonHost,
259
- port: daemonPort,
260
- version: identity.version,
261
- });
262
- return createServiceStatus('external', daemonHost, daemonPort, {
263
- authenticated: true,
264
- status: identity.status,
265
- version: identity.version,
266
- reason: 'Existing GoodVibes daemon verified after bind conflict',
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
- logger.warn('Daemon server port already in use; continuing without local daemon in this host instance', { error: message });
270
- return createServiceStatus('blocked', daemonHost, daemonPort, {
271
- authenticated: identity.kind !== 'unauthorized' ? undefined : false,
272
- reason: identity.reason ?? message,
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
- embeddedDaemonServer = started.service;
277
- daemonStatus = started.status;
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"}