@opengsd/gsd-pi 1.9.0-dev.e10b60d4 → 1.10.0-dev.a5e42e99

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 (251) hide show
  1. package/README.md +10 -9
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/gsd/auto/loop.js +24 -4
  4. package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
  5. package/dist/resources/extensions/gsd/auto-model-selection.js +1 -0
  6. package/dist/resources/extensions/gsd/auto-start.js +30 -10
  7. package/dist/resources/extensions/gsd/auto-verification.js +25 -12
  8. package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
  9. package/dist/resources/extensions/gsd/auto.js +12 -1
  10. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +4 -3
  11. package/dist/resources/extensions/gsd/docs/preferences-reference.md +12 -3
  12. package/dist/resources/extensions/gsd/doctor-engine-checks.js +37 -6
  13. package/dist/resources/extensions/gsd/flat-phase-migration.js +12 -0
  14. package/dist/resources/extensions/gsd/gsd-db.js +75 -31
  15. package/dist/resources/extensions/gsd/model-cost-table.js +6 -3
  16. package/dist/resources/extensions/gsd/model-router.js +10 -5
  17. package/dist/resources/extensions/gsd/planning-subagent-registry.js +12 -4
  18. package/dist/resources/extensions/gsd/preferences-models.js +50 -10
  19. package/dist/resources/extensions/gsd/preferences-types.js +1 -0
  20. package/dist/resources/extensions/gsd/preferences-validation.js +41 -6
  21. package/dist/resources/extensions/gsd/preferences.js +7 -0
  22. package/dist/resources/extensions/gsd/templates/PREFERENCES.md +3 -0
  23. package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -1
  24. package/dist/resources/extensions/gsd/verification-evidence.js +5 -3
  25. package/dist/resources/extensions/gsd/worktree-state-projection.js +20 -18
  26. package/dist/resources/extensions/ollama/ollama-chat-provider.js +2 -2
  27. package/dist/resources/extensions/subagent/index.js +1 -1
  28. package/dist/startup-model-validation.d.ts +1 -1
  29. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  30. package/dist/web/standalone/.next/BUILD_ID +1 -1
  31. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  32. package/dist/web/standalone/.next/build-manifest.json +2 -2
  33. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  34. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  35. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  36. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  37. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  38. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  39. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  40. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  41. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  42. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  43. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  44. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  45. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  46. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  47. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  48. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  49. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  50. package/dist/web/standalone/.next/server/app/index.html +1 -1
  51. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  52. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  53. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  54. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  55. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  56. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  57. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  58. package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
  59. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  60. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  61. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  62. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  63. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  64. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  65. package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
  66. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  67. package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
  68. package/integrations/hermes/pyproject.toml +1 -1
  69. package/package.json +7 -6
  70. package/packages/cloud-mcp-gateway/package.json +2 -2
  71. package/packages/contracts/dist/rpc.d.ts +1 -1
  72. package/packages/contracts/dist/rpc.d.ts.map +1 -1
  73. package/packages/contracts/dist/rpc.js +1 -1
  74. package/packages/contracts/dist/rpc.js.map +1 -1
  75. package/packages/contracts/dist/rpc.test.js +1 -1
  76. package/packages/contracts/dist/rpc.test.js.map +1 -1
  77. package/packages/contracts/package.json +1 -1
  78. package/packages/daemon/package.json +4 -4
  79. package/packages/gsd-agent-core/package.json +5 -5
  80. package/packages/gsd-agent-modes/dist/cli/args.js +2 -2
  81. package/packages/gsd-agent-modes/dist/cli/args.js.map +1 -1
  82. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  83. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +1 -0
  84. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  85. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  86. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js +1 -0
  87. package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  88. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  89. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js +1 -0
  90. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  91. package/packages/gsd-agent-modes/package.json +7 -7
  92. package/packages/gsd-cloud/README.md +21 -5
  93. package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
  94. package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
  95. package/packages/gsd-cloud/dist/background-cli.test.js +325 -0
  96. package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
  97. package/packages/gsd-cloud/dist/cli.d.ts.map +1 -1
  98. package/packages/gsd-cloud/dist/cli.js +146 -16
  99. package/packages/gsd-cloud/dist/cli.js.map +1 -1
  100. package/packages/gsd-cloud/dist/cloud-config.d.ts +1 -1
  101. package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -1
  102. package/packages/gsd-cloud/dist/cloud-config.js +7 -1
  103. package/packages/gsd-cloud/dist/cloud-config.js.map +1 -1
  104. package/packages/gsd-cloud/dist/cloud-runtime.d.ts +7 -4
  105. package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -1
  106. package/packages/gsd-cloud/dist/cloud-runtime.js +115 -31
  107. package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -1
  108. package/packages/gsd-cloud/dist/cloud-runtime.test.js +224 -59
  109. package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -1
  110. package/packages/gsd-cloud/dist/runtime-artifacts.d.ts +3 -0
  111. package/packages/gsd-cloud/dist/runtime-artifacts.d.ts.map +1 -0
  112. package/packages/gsd-cloud/dist/runtime-artifacts.js +36 -0
  113. package/packages/gsd-cloud/dist/runtime-artifacts.js.map +1 -0
  114. package/packages/gsd-cloud/dist/runtime-process.d.ts +32 -0
  115. package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
  116. package/packages/gsd-cloud/dist/runtime-process.js +640 -0
  117. package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
  118. package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
  119. package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
  120. package/packages/gsd-cloud/dist/runtime-process.test.js +543 -0
  121. package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
  122. package/packages/gsd-cloud/dist/runtime-telemetry.d.ts +117 -0
  123. package/packages/gsd-cloud/dist/runtime-telemetry.d.ts.map +1 -0
  124. package/packages/gsd-cloud/dist/runtime-telemetry.js +291 -0
  125. package/packages/gsd-cloud/dist/runtime-telemetry.js.map +1 -0
  126. package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts +2 -0
  127. package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts.map +1 -0
  128. package/packages/gsd-cloud/dist/runtime-telemetry.test.js +434 -0
  129. package/packages/gsd-cloud/dist/runtime-telemetry.test.js.map +1 -0
  130. package/packages/gsd-cloud/package.json +2 -2
  131. package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
  132. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
  133. package/packages/mcp-server/dist/cli-runner.js +119 -33
  134. package/packages/mcp-server/dist/cli-runner.js.map +1 -1
  135. package/packages/mcp-server/package.json +4 -4
  136. package/packages/native/package.json +1 -1
  137. package/packages/pi-agent-core/dist/types.d.ts +2 -2
  138. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  139. package/packages/pi-agent-core/dist/types.js.map +1 -1
  140. package/packages/pi-agent-core/package.json +1 -1
  141. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  142. package/packages/pi-ai/dist/models.generated.d.ts +130 -2
  143. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  144. package/packages/pi-ai/dist/models.generated.js +101 -9
  145. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  146. package/packages/pi-ai/dist/models.js +18 -6
  147. package/packages/pi-ai/dist/models.js.map +1 -1
  148. package/packages/pi-ai/dist/providers/amazon-bedrock.js +3 -2
  149. package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  150. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
  151. package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  152. package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  153. package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
  154. package/packages/pi-ai/dist/providers/google.js.map +1 -1
  155. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +1 -1
  156. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  157. package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
  158. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  159. package/packages/pi-ai/dist/providers/openai-completions.d.ts +1 -1
  160. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  161. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  162. package/packages/pi-ai/dist/providers/openai-responses.d.ts +1 -1
  163. package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  164. package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
  165. package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
  166. package/packages/pi-ai/dist/providers/simple-options.d.ts +1 -1
  167. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  168. package/packages/pi-ai/dist/providers/simple-options.js +1 -1
  169. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  170. package/packages/pi-ai/dist/types.d.ts +9 -1
  171. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  172. package/packages/pi-ai/dist/types.js.map +1 -1
  173. package/packages/pi-ai/package.json +1 -1
  174. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  175. package/packages/pi-coding-agent/dist/core/model-registry.js +1 -0
  176. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
  178. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -3
  180. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  182. package/packages/pi-coding-agent/dist/core/skills.d.ts +5 -0
  183. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  184. package/packages/pi-coding-agent/dist/core/skills.js +54 -0
  185. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  186. package/packages/pi-coding-agent/dist/theme/theme.d.ts +1 -1
  187. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  188. package/packages/pi-coding-agent/dist/theme/theme.js +1 -0
  189. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  190. package/packages/pi-coding-agent/package.json +7 -7
  191. package/packages/pi-tui/package.json +2 -2
  192. package/packages/rpc-client/package.json +2 -2
  193. package/pkg/dist/theme/theme.d.ts +1 -1
  194. package/pkg/dist/theme/theme.d.ts.map +1 -1
  195. package/pkg/dist/theme/theme.js +1 -0
  196. package/pkg/dist/theme/theme.js.map +1 -1
  197. package/pkg/package.json +1 -1
  198. package/src/resources/extensions/gsd/auto/loop.ts +48 -4
  199. package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
  200. package/src/resources/extensions/gsd/auto-model-selection.ts +1 -0
  201. package/src/resources/extensions/gsd/auto-start.ts +32 -9
  202. package/src/resources/extensions/gsd/auto-verification.ts +46 -12
  203. package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
  204. package/src/resources/extensions/gsd/auto.ts +13 -1
  205. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +4 -3
  206. package/src/resources/extensions/gsd/docs/preferences-reference.md +12 -3
  207. package/src/resources/extensions/gsd/doctor-engine-checks.ts +42 -6
  208. package/src/resources/extensions/gsd/flat-phase-migration.ts +14 -0
  209. package/src/resources/extensions/gsd/gsd-db.ts +85 -33
  210. package/src/resources/extensions/gsd/model-cost-table.ts +14 -3
  211. package/src/resources/extensions/gsd/model-router.ts +10 -5
  212. package/src/resources/extensions/gsd/planning-subagent-registry.ts +18 -4
  213. package/src/resources/extensions/gsd/preferences-models.ts +54 -10
  214. package/src/resources/extensions/gsd/preferences-types.ts +10 -2
  215. package/src/resources/extensions/gsd/preferences-validation.ts +49 -6
  216. package/src/resources/extensions/gsd/preferences.ts +13 -0
  217. package/src/resources/extensions/gsd/templates/PREFERENCES.md +3 -0
  218. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +156 -0
  219. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
  220. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
  221. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +147 -0
  222. package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +8 -9
  223. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +32 -0
  224. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -0
  225. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +22 -7
  226. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +55 -0
  227. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  228. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +24 -0
  229. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +38 -1
  230. package/src/resources/extensions/gsd/tests/preferences.test.ts +71 -4
  231. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +3 -0
  232. package/src/resources/extensions/gsd/tests/service-tier.test.ts +2 -2
  233. package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +1 -1
  234. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +12 -0
  235. package/src/resources/extensions/gsd/tests/workflow-authority-faults.test.ts +238 -0
  236. package/src/resources/extensions/gsd/tests/workflow-authority-fixture.test.ts +48 -0
  237. package/src/resources/extensions/gsd/tests/workflow-authority-fixture.ts +141 -0
  238. package/src/resources/extensions/gsd/tests/workflow-authority-projection-conflict.test.ts +177 -0
  239. package/src/resources/extensions/gsd/tests/workflow-fault-harness.test.ts +39 -0
  240. package/src/resources/extensions/gsd/tests/workflow-fault-harness.ts +72 -0
  241. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +2 -2
  242. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
  243. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +40 -0
  244. package/src/resources/extensions/gsd/tools/plan-slice.ts +5 -1
  245. package/src/resources/extensions/gsd/verification-evidence.ts +5 -2
  246. package/src/resources/extensions/gsd/worktree-state-projection.ts +21 -24
  247. package/src/resources/extensions/ollama/ollama-chat-provider.ts +2 -2
  248. package/src/resources/extensions/ollama/tests/ollama-chat-provider-think.test.ts +4 -0
  249. package/src/resources/extensions/subagent/index.ts +1 -1
  250. /package/dist/web/standalone/.next/static/{V9MAVyYVPboQUB9KTTAMi → xwUaOqui04jIIFVsIBLiL}/_buildManifest.js +0 -0
  251. /package/dist/web/standalone/.next/static/{V9MAVyYVPboQUB9KTTAMi → xwUaOqui04jIIFVsIBLiL}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-runtime.js","sourceRoot":"","sources":["../src/cloud-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import WebSocket from \"ws\";\nimport type { Logger } from \"./logger.js\";\nimport type { DaemonConfig } from \"./types.js\";\nimport type { Executor } from \"./executors/executor.js\";\nimport { createGatewayLookup, parseCloudGatewayUrl, validateGatewayNetworkTarget } from \"./cloud-config.js\";\n\ninterface GatewayMessage {\n type: string;\n requestId?: string;\n toolName?: string;\n args?: Record<string, unknown>;\n projectAlias?: string;\n}\n\nexport class CloudRuntime {\n private static readonly MAX_OUTBOX = 200;\n private static readonly RECONNECT_DELAY_MS = 5_000;\n // How many times to retry the initial connect before rejecting start(). A\n // transient handshake failure (gateway briefly unreachable, DNS hiccup) should\n // retry like the daemon's reconnect loop rather than kill the runtime; a\n // persistent failure (gateway down, session rejected) must eventually reject so\n // the CLI reports an error instead of hanging or exiting silently.\n private static readonly MAX_INITIAL_CONNECT_ATTEMPTS = 5;\n private static readonly INITIAL_CONNECT_HANDSHAKE_TIMEOUT_MS = 30_000;\n private socket: WebSocket | undefined;\n private heartbeat: ReturnType<typeof setInterval> | undefined;\n private reconnect: ReturnType<typeof setTimeout> | undefined;\n private readonly inFlight = new Map<string, GatewayMessage>();\n private outbox: string[] = [];\n private stopped = false;\n private firstConnectDeferred: PromiseWithResolvers<void> | undefined;\n private initialConnectAttempts = 0;\n\n constructor(\n private readonly cloud: NonNullable<DaemonConfig[\"cloud\"]>,\n private readonly executor: Executor,\n private readonly logger: Logger,\n ) {}\n\n start(): Promise<void> {\n this.stopped = false;\n this.initialConnectAttempts = 0;\n this.firstConnectDeferred = Promise.withResolvers<void>();\n this.connect();\n return this.firstConnectDeferred.promise;\n }\n\n stop(): void {\n this.stopped = true;\n this.rejectFirstConnect(new Error(\"cloud runtime stopped\"));\n if (this.reconnect) clearTimeout(this.reconnect);\n this.reconnect = undefined;\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = undefined;\n this.inFlight.clear();\n this.outbox = [];\n const socket = this.socket;\n this.socket = undefined;\n socket?.close();\n }\n\n private connect(): void {\n if (this.reconnect) clearTimeout(this.reconnect);\n this.reconnect = undefined;\n if (!this.cloud.device_token || !this.cloud.runtime_id) {\n this.logger.warn(\"cloud runtime skipped — missing device token or runtime id\");\n this.rejectFirstConnect(new Error(\"cloud runtime missing device token or runtime id\"));\n return;\n }\n const gatewayUrl = parseCloudGatewayUrl(this.cloud.gateway_url);\n try {\n validateGatewayNetworkTarget(gatewayUrl);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logger.warn(\"cloud runtime skipped unsafe gateway URL\", { error: message });\n this.rejectFirstConnect(new Error(`cloud runtime unsafe gateway URL: ${message}`));\n return;\n }\n const url = new URL(\"/runtime/connect\", gatewayUrl);\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n const socket = new WebSocket(url, {\n headers: { Authorization: `Bearer ${this.cloud.device_token}` },\n lookup: createGatewayLookup(gatewayUrl),\n handshakeTimeout: CloudRuntime.INITIAL_CONNECT_HANDSHAKE_TIMEOUT_MS,\n });\n const previousSocket = this.socket;\n this.socket = socket;\n if (previousSocket) {\n // Detach the old socket's handlers before closing so its listeners don't\n // linger on a socket we've already replaced (handlers also guard on\n // identity, but this releases them eagerly for GC).\n previousSocket.removeAllListeners();\n if (previousSocket.readyState !== WebSocket.CLOSING && previousSocket.readyState !== WebSocket.CLOSED) {\n previousSocket.close();\n }\n }\n\n socket.on(\"open\", () => {\n this.handleSocketOpen(socket);\n });\n socket.on(\"message\", (data) => {\n void this.handleSocketMessage(socket, data.toString(\"utf8\"));\n });\n socket.on(\"close\", () => {\n this.handleSocketClose(socket);\n });\n socket.on(\"error\", (err) => {\n this.handleSocketError(socket, err);\n });\n }\n\n private handleSocketOpen(socket: WebSocket): void {\n if (socket !== this.socket) return;\n this.resolveFirstConnect();\n this.logger.info(\"cloud runtime connected\", { gateway_url: this.cloud.gateway_url, runtime_id: this.cloud.runtime_id });\n // Re-advertise projects (async: the hello is sent on a later microtask), then\n // drain any messages buffered while disconnected. tool_results route by\n // requestId on the authenticated connection, so drain order vs the hello is\n // not significant.\n void this.advertiseProjects();\n const pending = this.outbox;\n this.outbox = [];\n for (const text of pending) {\n if (this.socket?.readyState === WebSocket.OPEN) this.socket.send(text);\n else this.outbox.push(text);\n }\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = setInterval(() => this.send({ type: \"heartbeat\", at: Date.now() }), 30_000);\n }\n\n private async handleSocketMessage(socket: WebSocket, text: string): Promise<void> {\n if (socket !== this.socket) return;\n await this.handleMessage(text);\n }\n\n private handleSocketClose(socket: WebSocket): void {\n if (socket !== this.socket) return;\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = undefined;\n this.socket = undefined;\n if (this.stopped) return;\n if (this.firstConnectDeferred) {\n // Still trying to establish the first connection: retry transient\n // handshake failures (like the daemon's reconnect loop) and only reject\n // start() once the bounded attempts are exhausted, so a brief blip does\n // not kill the runtime while a persistent outage still surfaces an error.\n this.initialConnectAttempts += 1;\n if (this.initialConnectAttempts >= CloudRuntime.MAX_INITIAL_CONNECT_ATTEMPTS) {\n this.rejectFirstConnect(\n new Error(\n `cloud runtime connection failed after ${this.initialConnectAttempts} attempt(s)`,\n ),\n );\n return;\n }\n this.logger.warn(\"cloud runtime initial connect failed; retrying\", {\n attempt: this.initialConnectAttempts,\n max: CloudRuntime.MAX_INITIAL_CONNECT_ATTEMPTS,\n });\n } else {\n this.logger.warn(\"cloud runtime disconnected; reconnecting\");\n }\n if (this.reconnect) clearTimeout(this.reconnect);\n this.reconnect = setTimeout(() => this.connect(), CloudRuntime.RECONNECT_DELAY_MS);\n }\n\n private handleSocketError(socket: WebSocket, err: Error): void {\n if (socket !== this.socket) return;\n this.logger.warn(\"cloud runtime socket error\", { error: err.message });\n }\n\n private async advertiseProjects(): Promise<void> {\n const projects = await this.executor.advertisedProjects();\n this.send({\n type: \"hello\",\n runtimeId: this.cloud.runtime_id,\n runtimeName: this.cloud.runtime_name,\n projects,\n });\n }\n\n private async handleMessage(text: string): Promise<void> {\n let message: GatewayMessage;\n try {\n message = JSON.parse(text) as GatewayMessage;\n } catch {\n return;\n }\n if (message.type === \"cancel\" && message.requestId) {\n void this.cancelInFlight(message.requestId);\n return;\n }\n if (message.type !== \"tool_call\" || !message.requestId || !message.toolName) return;\n this.inFlight.set(message.requestId, message);\n try {\n const result = await this.executor.execute(message.toolName, message.args ?? {}, message.projectAlias);\n if (!this.inFlight.has(message.requestId)) return;\n this.send({ type: \"tool_result\", requestId: message.requestId, result });\n } catch (err) {\n if (!this.inFlight.has(message.requestId)) return;\n this.send({\n type: \"tool_result\",\n requestId: message.requestId,\n error: err instanceof Error ? err.message : String(err),\n });\n } finally {\n this.inFlight.delete(message.requestId);\n }\n }\n\n private async cancelInFlight(requestId: string): Promise<void> {\n const pending = this.inFlight.get(requestId);\n if (!pending) return;\n this.inFlight.delete(requestId);\n try {\n if (typeof pending.args?.sessionId === \"string\") {\n await this.executor.execute(\"gsd_cancel\", { sessionId: pending.args.sessionId }, pending.projectAlias);\n return;\n }\n const projectDir = typeof pending.args?.projectDir === \"string\" ? pending.args.projectDir : pending.projectAlias;\n if (projectDir) {\n await this.executor.execute(\"gsd_cancel\", { projectDir });\n }\n } catch (err) {\n this.logger.warn(\"cloud runtime cancel failed\", {\n requestId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n private resolveFirstConnect(): void {\n const deferred = this.firstConnectDeferred;\n if (!deferred) return;\n this.firstConnectDeferred = undefined;\n deferred.resolve();\n }\n\n private rejectFirstConnect(err: Error): void {\n const deferred = this.firstConnectDeferred;\n if (!deferred) return;\n this.firstConnectDeferred = undefined;\n deferred.reject(err);\n }\n\n private send(message: unknown): void {\n const text = JSON.stringify(message);\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(text);\n return;\n }\n // Buffer while disconnected; flushed on reconnect in handleSocketOpen. Bounded\n // so a long outage cannot grow memory without limit — a stale heartbeat is\n // worth less than a fresh tool_result, so drop oldest first.\n this.outbox.push(text);\n if (this.outbox.length > CloudRuntime.MAX_OUTBOX) {\n this.outbox.shift();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"cloud-runtime.js","sourceRoot":"","sources":["../src/cloud-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import WebSocket from \"ws\";\nimport type { Logger } from \"./logger.js\";\nimport type { DaemonConfig } from \"./types.js\";\nimport type { AdvertisedProject, Executor } from \"./executors/executor.js\";\nimport { createGatewayLookup, parseCloudGatewayUrl, validateGatewayNetworkTarget } from \"./cloud-config.js\";\nimport {\n noopRuntimeTelemetry,\n type RuntimeTelemetryReporter,\n} from \"./runtime-telemetry.js\";\n\nconst INITIAL_CONNECT_ATTEMPTS = 5;\nconst INITIAL_CONNECT_HANDSHAKE_TIMEOUT_MS = 30_000;\nconst RECONNECT_DELAY_MS = 5_000;\n\nexport const CLOUD_RUNTIME_INITIAL_CONNECT_WINDOW_MS =\n INITIAL_CONNECT_ATTEMPTS * INITIAL_CONNECT_HANDSHAKE_TIMEOUT_MS\n + (INITIAL_CONNECT_ATTEMPTS - 1) * RECONNECT_DELAY_MS;\n\ninterface GatewayMessage {\n type: string;\n requestId?: string;\n toolName?: string;\n args?: Record<string, unknown>;\n projectAlias?: string;\n}\n\ninterface QueuedFrame {\n text: string;\n projectPath?: string;\n}\n\ninterface InFlightRequest {\n message: GatewayMessage;\n routingKey?: string;\n}\n\nexport class CloudRuntime {\n private static readonly MAX_OUTBOX = 200;\n // How many times to retry the initial connect before rejecting start(). A\n // transient handshake failure (gateway briefly unreachable, DNS hiccup) should\n // retry like the daemon's reconnect loop rather than kill the runtime; a\n // persistent failure (gateway down, session rejected) must eventually reject so\n // the CLI reports an error instead of hanging or exiting silently.\n private socket: WebSocket | undefined;\n private heartbeat: ReturnType<typeof setInterval> | undefined;\n private reconnect: ReturnType<typeof setTimeout> | undefined;\n private readonly inFlight = new Map<string, InFlightRequest>();\n private outbox: QueuedFrame[] = [];\n private advertisedProjects: AdvertisedProject[] = [];\n private stopped = false;\n private firstConnectDeferred: PromiseWithResolvers<void> | undefined;\n private initialConnectAttempts = 0;\n\n constructor(\n private readonly cloud: NonNullable<DaemonConfig[\"cloud\"]>,\n private readonly executor: Executor,\n private readonly logger: Logger,\n private readonly telemetry: RuntimeTelemetryReporter = noopRuntimeTelemetry,\n ) {}\n\n start(): Promise<void> {\n this.stopped = false;\n this.initialConnectAttempts = 0;\n const firstConnect = Promise.withResolvers<void>();\n this.firstConnectDeferred = firstConnect;\n const result = firstConnect.promise.catch(async (error: unknown) => {\n this.telemetry.failed?.();\n await this.telemetry.flush?.();\n throw error;\n });\n try {\n this.connect();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.telemetry.socketError(message);\n this.rejectFirstConnect(error instanceof Error ? error : new Error(message));\n }\n return result;\n }\n\n stop(): void {\n this.stopped = true;\n this.telemetry.stopped();\n this.rejectFirstConnect(new Error(\"cloud runtime stopped\"));\n if (this.reconnect) clearTimeout(this.reconnect);\n this.reconnect = undefined;\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = undefined;\n this.inFlight.clear();\n this.outbox = [];\n const socket = this.socket;\n this.socket = undefined;\n socket?.close();\n }\n\n private connect(): void {\n if (this.reconnect) clearTimeout(this.reconnect);\n this.reconnect = undefined;\n this.telemetry.connecting();\n if (!this.cloud.device_token || !this.cloud.runtime_id) {\n const message = \"cloud runtime missing device token or runtime id\";\n this.logger.warn(\"cloud runtime skipped — missing device token or runtime id\");\n this.telemetry.socketError(message);\n this.rejectFirstConnect(new Error(message));\n return;\n }\n const gatewayUrl = parseCloudGatewayUrl(this.cloud.gateway_url);\n try {\n validateGatewayNetworkTarget(gatewayUrl);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logger.warn(\"cloud runtime skipped unsafe gateway URL\", { error: message });\n this.telemetry.socketError(message);\n this.rejectFirstConnect(new Error(`cloud runtime unsafe gateway URL: ${message}`));\n return;\n }\n const url = new URL(\"/runtime/connect\", gatewayUrl);\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n const socket = new WebSocket(url, {\n headers: { Authorization: `Bearer ${this.cloud.device_token}` },\n lookup: createGatewayLookup(gatewayUrl),\n handshakeTimeout: INITIAL_CONNECT_HANDSHAKE_TIMEOUT_MS,\n });\n const previousSocket = this.socket;\n this.socket = socket;\n if (previousSocket) {\n // Detach the old socket's handlers before closing so its listeners don't\n // linger on a socket we've already replaced (handlers also guard on\n // identity, but this releases them eagerly for GC).\n previousSocket.removeAllListeners();\n if (previousSocket.readyState !== WebSocket.CLOSING && previousSocket.readyState !== WebSocket.CLOSED) {\n previousSocket.close();\n }\n }\n\n socket.on(\"open\", () => {\n this.handleSocketOpen(socket);\n });\n socket.on(\"message\", (data) => {\n void this.handleSocketMessage(socket, data.toString(\"utf8\"));\n });\n socket.on(\"close\", () => {\n this.handleSocketClose(socket);\n });\n socket.on(\"error\", (err) => {\n this.handleSocketError(socket, err);\n });\n }\n\n private handleSocketOpen(socket: WebSocket): void {\n if (socket !== this.socket) return;\n this.telemetry.connected();\n this.resolveFirstConnect();\n this.logger.info(\"cloud runtime connected\", { gateway_url: this.cloud.gateway_url, runtime_id: this.cloud.runtime_id });\n // Re-advertise projects (async: the hello is sent on a later microtask), then\n // drain any messages buffered while disconnected. tool_results route by\n // requestId on the authenticated connection, so drain order vs the hello is\n // not significant.\n void this.advertiseProjects();\n const pending = this.outbox;\n this.outbox = [];\n for (const frame of pending) {\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(frame.text);\n this.telemetry.sent(frame.text, frame.projectPath);\n }\n else this.outbox.push(frame);\n }\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = setInterval(() => this.send({ type: \"heartbeat\", at: Date.now() }), 30_000);\n }\n\n private async handleSocketMessage(socket: WebSocket, text: string): Promise<void> {\n if (socket !== this.socket) return;\n this.telemetry.received(text);\n await this.handleMessage(text);\n }\n\n private handleSocketClose(socket: WebSocket): void {\n if (socket !== this.socket) return;\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = undefined;\n this.socket = undefined;\n if (this.stopped) return;\n this.telemetry.disconnected();\n if (this.firstConnectDeferred) {\n // Still trying to establish the first connection: retry transient\n // handshake failures (like the daemon's reconnect loop) and only reject\n // start() once the bounded attempts are exhausted, so a brief blip does\n // not kill the runtime while a persistent outage still surfaces an error.\n this.initialConnectAttempts += 1;\n if (this.initialConnectAttempts >= INITIAL_CONNECT_ATTEMPTS) {\n const error = new Error(\n `cloud runtime connection failed after ${this.initialConnectAttempts} attempt(s)`,\n );\n this.telemetry.socketError(error.message);\n this.rejectFirstConnect(error);\n return;\n }\n this.logger.warn(\"cloud runtime initial connect failed; retrying\", {\n attempt: this.initialConnectAttempts,\n max: INITIAL_CONNECT_ATTEMPTS,\n });\n } else {\n this.logger.warn(\"cloud runtime disconnected; reconnecting\");\n }\n if (this.reconnect) clearTimeout(this.reconnect);\n this.reconnect = setTimeout(() => this.connect(), RECONNECT_DELAY_MS);\n }\n\n private handleSocketError(socket: WebSocket, err: Error): void {\n if (socket !== this.socket) return;\n this.logger.warn(\"cloud runtime socket error\", { error: err.message });\n this.telemetry.socketError(err.message);\n }\n\n private async advertiseProjects(): Promise<void> {\n const projects = await this.executor.advertisedProjects();\n this.advertisedProjects = projects;\n this.telemetry.projectsAdvertised(projects);\n this.send({\n type: \"hello\",\n runtimeId: this.cloud.runtime_id,\n runtimeName: this.cloud.runtime_name,\n projects,\n });\n }\n\n private async handleMessage(text: string): Promise<void> {\n let message: GatewayMessage;\n try {\n message = JSON.parse(text) as GatewayMessage;\n } catch {\n return;\n }\n if (message.type === \"cancel\" && message.requestId) {\n void this.cancelInFlight(message.requestId);\n return;\n }\n if (message.type !== \"tool_call\" || !message.requestId || !message.toolName) return;\n const routingKey = this.resolveRoutingKey(message);\n const project = this.resolveProject(routingKey);\n const projectAlias = project?.alias;\n const projectPath = project?.path;\n const startedAt = Date.now();\n const receivedBytes = Buffer.byteLength(text);\n this.inFlight.set(message.requestId, {\n message,\n ...(routingKey !== undefined ? { routingKey } : {}),\n });\n this.telemetry.requestStarted({\n requestId: message.requestId,\n ...(projectAlias ? { projectAlias } : {}),\n ...(projectPath ? { projectPath } : {}),\n toolName: message.toolName,\n receivedBytes,\n });\n let outcome: \"success\" | \"error\" | \"cancelled\" = \"success\";\n let errorMessage: string | undefined;\n try {\n const result = await this.executor.execute(message.toolName, message.args ?? {}, routingKey);\n if (!this.inFlight.has(message.requestId)) {\n outcome = \"cancelled\";\n return;\n }\n this.send({ type: \"tool_result\", requestId: message.requestId, result }, projectPath);\n } catch (err) {\n if (!this.inFlight.has(message.requestId)) {\n outcome = \"cancelled\";\n return;\n }\n outcome = \"error\";\n errorMessage = err instanceof Error ? err.message : String(err);\n this.send({\n type: \"tool_result\",\n requestId: message.requestId,\n error: errorMessage,\n }, projectPath);\n } finally {\n this.inFlight.delete(message.requestId);\n this.telemetry.requestFinished({\n requestId: message.requestId,\n ...(projectAlias ? { projectAlias } : {}),\n ...(projectPath ? { projectPath } : {}),\n toolName: message.toolName,\n durationMs: Date.now() - startedAt,\n outcome,\n ...(errorMessage ? { error: errorMessage } : {}),\n });\n }\n }\n\n private resolveRoutingKey(message: GatewayMessage): string | undefined {\n return message.projectAlias\n ?? (typeof message.args?.projectDir === \"string\" ? message.args.projectDir : undefined)\n ?? (typeof message.args?.projectAlias === \"string\" ? message.args.projectAlias : undefined);\n }\n\n private resolveProject(routingKey?: string): AdvertisedProject | undefined {\n if (routingKey !== undefined) {\n const exact = this.advertisedProjects.find((project) => project.path === routingKey);\n if (exact) return exact;\n const matches = this.advertisedProjects.filter((project) => project.alias === routingKey);\n return matches.length === 1 ? matches[0] : undefined;\n }\n if (this.advertisedProjects.length === 1) return this.advertisedProjects[0];\n return undefined;\n }\n\n private async cancelInFlight(requestId: string): Promise<void> {\n const pending = this.inFlight.get(requestId);\n if (!pending) return;\n this.inFlight.delete(requestId);\n try {\n if (typeof pending.message.args?.sessionId === \"string\") {\n await this.executor.execute(\n \"gsd_cancel\",\n { sessionId: pending.message.args.sessionId },\n pending.routingKey,\n );\n return;\n }\n if (pending.routingKey !== undefined) {\n await this.executor.execute(\n \"gsd_cancel\",\n { projectDir: pending.routingKey },\n pending.routingKey,\n );\n }\n } catch (err) {\n this.logger.warn(\"cloud runtime cancel failed\", {\n requestId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n private resolveFirstConnect(): void {\n const deferred = this.firstConnectDeferred;\n if (!deferred) return;\n this.firstConnectDeferred = undefined;\n deferred.resolve();\n }\n\n private rejectFirstConnect(err: Error): void {\n const deferred = this.firstConnectDeferred;\n if (!deferred) return;\n this.firstConnectDeferred = undefined;\n deferred.reject(err);\n }\n\n private send(message: unknown, projectPath?: string): void {\n const text = JSON.stringify(message);\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(text);\n this.telemetry.sent(text, projectPath);\n return;\n }\n // Buffer while disconnected; flushed on reconnect in handleSocketOpen. Bounded\n // so a long outage cannot grow memory without limit — a stale heartbeat is\n // worth less than a fresh tool_result, so drop oldest first.\n this.outbox.push({ text, ...(projectPath ? { projectPath } : {}) });\n if (this.outbox.length > CloudRuntime.MAX_OUTBOX) {\n this.outbox.shift();\n }\n }\n}\n"]}
@@ -4,8 +4,12 @@
4
4
  // failure, so the CLI never reports "connected" for a socket that never opened.
5
5
  import { test } from "node:test";
6
6
  import assert from "node:assert/strict";
7
+ import { mkdtempSync, readFileSync, rmSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
7
10
  import WebSocket from "ws";
8
11
  import { CloudRuntime } from "./cloud-runtime.js";
12
+ import { RuntimeTelemetryStore } from "./runtime-telemetry.js";
9
13
  const noopLogger = { info: () => undefined, warn: () => undefined, error: () => undefined, debug: () => undefined };
10
14
  const noopExecutor = { execute: async () => ({}), advertisedProjects: async () => [] };
11
15
  function makeRuntime(cloud = {}) {
@@ -15,74 +19,235 @@ function fakeSocket(readyState = WebSocket.OPEN) {
15
19
  const sent = [];
16
20
  return { readyState, sent, send: (t) => sent.push(t), close: () => undefined };
17
21
  }
18
- test("start()'s first-connect promise resolves only when the relay socket opens", async () => {
19
- const runtime = makeRuntime();
22
+ test("one routing selector drives execution, cancellation, and telemetry", async (t) => {
23
+ const selectors = [];
24
+ const started = [];
25
+ const execution = Promise.withResolvers();
26
+ const telemetry = {
27
+ ...Object.fromEntries([
28
+ "connecting", "connected", "disconnected", "socketError", "received", "sent",
29
+ "projectsAdvertised", "requestFinished", "stopped",
30
+ ].map((name) => [name, () => undefined])),
31
+ requestStarted: (request) => started.push(request),
32
+ };
33
+ const runtime = new CloudRuntime({ gateway_url: "wss://cloud.example.net", device_token: "fixture", runtime_id: "runtime" }, {
34
+ execute: async (toolName, _args, selector) => {
35
+ selectors.push(selector);
36
+ if (toolName === "gsd_cancel")
37
+ return {};
38
+ return execution.promise;
39
+ },
40
+ advertisedProjects: async () => [],
41
+ }, noopLogger, telemetry);
42
+ const internals = runtime;
43
+ t.after(() => runtime.stop());
44
+ internals.advertisedProjects = [
45
+ { alias: "one", path: "/work/one", repoIdentity: "one", markers: [".gsd"] },
46
+ { alias: "two", path: "/work/two", repoIdentity: "two", markers: [".gsd"] },
47
+ ];
48
+ const socket = fakeSocket();
49
+ internals.socket = socket;
50
+ const request = internals.handleSocketMessage(socket, JSON.stringify({
51
+ type: "tool_call",
52
+ requestId: "request-routing",
53
+ toolName: "gsd_status",
54
+ projectAlias: "one",
55
+ args: { projectDir: "/work/two" },
56
+ }));
57
+ await Promise.resolve();
58
+ await internals.handleSocketMessage(socket, JSON.stringify({
59
+ type: "cancel",
60
+ requestId: "request-routing",
61
+ }));
62
+ execution.resolve({});
63
+ await request;
64
+ assert.deepEqual(selectors, ["one", "one"]);
65
+ assert.equal(started[0]?.projectAlias, "one");
66
+ assert.equal(started[0]?.projectPath, "/work/one");
67
+ internals.advertisedProjects = [
68
+ { alias: "app", path: "/work/one/app", repoIdentity: "one", markers: [".gsd"] },
69
+ { alias: "app", path: "/work/two/app", repoIdentity: "two", markers: [".gsd"] },
70
+ ];
71
+ await internals.handleSocketMessage(socket, JSON.stringify({
72
+ type: "tool_call",
73
+ requestId: "request-ambiguous",
74
+ toolName: "gsd_status",
75
+ projectAlias: "app",
76
+ }));
77
+ assert.equal(started[1]?.projectAlias, undefined);
78
+ assert.equal(started[1]?.projectPath, undefined);
79
+ });
80
+ test("queued project bytes are reported only after transmission", async (t) => {
81
+ const sentProjects = [];
82
+ const telemetry = {
83
+ ...Object.fromEntries([
84
+ "connecting", "connected", "disconnected", "socketError", "received",
85
+ "projectsAdvertised", "requestStarted", "requestFinished", "stopped",
86
+ ].map((name) => [name, () => undefined])),
87
+ sent: (_text, projectPath) => sentProjects.push(projectPath),
88
+ };
89
+ const runtime = new CloudRuntime({ gateway_url: "wss://cloud.example.net", device_token: "fixture", runtime_id: "runtime" }, {
90
+ execute: async () => ({ ok: true }),
91
+ advertisedProjects: async () => [
92
+ { alias: "app", path: "/work/one/app", repoIdentity: "one", markers: [".gsd"] },
93
+ { alias: "app", path: "/work/two/app", repoIdentity: "two", markers: [".gsd"] },
94
+ ],
95
+ }, noopLogger, telemetry);
20
96
  const internals = runtime;
21
- try {
22
- const deferred = Promise.withResolvers();
23
- internals.firstConnectDeferred = deferred;
24
- const socket = fakeSocket();
25
- internals.socket = socket;
26
- let settled = false;
27
- void deferred.promise.then(() => (settled = true));
28
- await Promise.resolve(); // let any premature settle flush
29
- assert.equal(settled, false, "promise must not resolve before the socket opens");
30
- internals.handleSocketOpen(socket);
31
- await deferred.promise; // resolves — otherwise this hangs/throws
32
- }
33
- finally {
34
- runtime.stop();
35
- }
97
+ t.after(() => runtime.stop());
98
+ internals.advertisedProjects = [
99
+ { alias: "app", path: "/work/one/app", repoIdentity: "one", markers: [".gsd"] },
100
+ { alias: "app", path: "/work/two/app", repoIdentity: "two", markers: [".gsd"] },
101
+ ];
102
+ internals.socket = fakeSocket(WebSocket.CLOSED);
103
+ await internals.handleSocketMessage(internals.socket, JSON.stringify({
104
+ type: "tool_call",
105
+ requestId: "request-queued",
106
+ toolName: "gsd_status",
107
+ args: { projectDir: "/work/two/app" },
108
+ }));
109
+ assert.deepEqual(sentProjects, []);
110
+ const openSocket = fakeSocket();
111
+ internals.socket = openSocket;
112
+ internals.handleSocketOpen(openSocket);
113
+ assert.deepEqual(sentProjects, ["/work/two/app"]);
36
114
  });
37
- test("an early socket close retries instead of rejecting while attempts remain", async () => {
115
+ test("start()'s first-connect promise resolves only when the relay socket opens", async (t) => {
38
116
  const runtime = makeRuntime();
39
117
  const internals = runtime;
40
- try {
41
- const deferred = Promise.withResolvers();
42
- internals.firstConnectDeferred = deferred;
43
- const socket = fakeSocket();
44
- internals.socket = socket;
45
- let settled = false;
46
- void deferred.promise.then(() => (settled = true), () => (settled = true));
47
- internals.handleSocketClose(socket); // first transient failure
48
- await Promise.resolve();
49
- assert.equal(settled, false, "a single early close must not settle start()");
50
- assert.equal(internals.initialConnectAttempts, 1);
51
- assert.notEqual(internals.reconnect, undefined, "a reconnect must be scheduled");
52
- }
53
- finally {
54
- runtime.stop();
55
- }
118
+ t.after(() => runtime.stop());
119
+ const deferred = Promise.withResolvers();
120
+ internals.firstConnectDeferred = deferred;
121
+ const socket = fakeSocket();
122
+ internals.socket = socket;
123
+ let settled = false;
124
+ void deferred.promise.then(() => (settled = true));
125
+ await Promise.resolve(); // let any premature settle flush
126
+ assert.equal(settled, false, "promise must not resolve before the socket opens");
127
+ internals.handleSocketOpen(socket);
128
+ await deferred.promise; // resolves — otherwise this hangs/throws
56
129
  });
57
- test("start()'s first-connect promise rejects once the initial connect attempts are exhausted", async () => {
130
+ test("an early socket close retries instead of rejecting while attempts remain", async (t) => {
58
131
  const runtime = makeRuntime();
59
132
  const internals = runtime;
60
- try {
61
- const deferred = Promise.withResolvers();
62
- internals.firstConnectDeferred = deferred;
63
- // Simulate having already burned every retry but the last so the next close
64
- // is the one that must give up and reject.
65
- internals.initialConnectAttempts = 4;
66
- const socket = fakeSocket();
67
- internals.socket = socket;
68
- internals.handleSocketClose(socket);
69
- await assert.rejects(deferred.promise, /connection failed/);
70
- }
71
- finally {
72
- runtime.stop();
73
- }
133
+ t.after(() => runtime.stop());
134
+ const deferred = Promise.withResolvers();
135
+ internals.firstConnectDeferred = deferred;
136
+ const socket = fakeSocket();
137
+ internals.socket = socket;
138
+ let settled = false;
139
+ void deferred.promise.then(() => (settled = true), () => (settled = true));
140
+ internals.handleSocketClose(socket); // first transient failure
141
+ await Promise.resolve();
142
+ assert.equal(settled, false, "a single early close must not settle start()");
143
+ assert.equal(internals.initialConnectAttempts, 1);
144
+ assert.notEqual(internals.reconnect, undefined, "a reconnect must be scheduled");
145
+ });
146
+ test("start()'s first-connect promise rejects once the initial connect attempts are exhausted", async (t) => {
147
+ const errors = [];
148
+ const telemetry = {
149
+ ...Object.fromEntries([
150
+ "connecting", "connected", "disconnected", "received", "sent", "projectsAdvertised",
151
+ "requestStarted", "requestFinished", "stopped",
152
+ ].map((name) => [name, () => undefined])),
153
+ socketError: (message) => errors.push(message),
154
+ };
155
+ const runtime = new CloudRuntime({ gateway_url: "wss://cloud.example.net", device_token: "fixture", runtime_id: "runtime" }, noopExecutor, noopLogger, telemetry);
156
+ const internals = runtime;
157
+ t.after(() => runtime.stop());
158
+ const deferred = Promise.withResolvers();
159
+ internals.firstConnectDeferred = deferred;
160
+ // Simulate having already burned every retry but the last so the next close
161
+ // is the one that must give up and reject.
162
+ internals.initialConnectAttempts = 4;
163
+ const socket = fakeSocket();
164
+ internals.socket = socket;
165
+ internals.handleSocketClose(socket);
166
+ await assert.rejects(deferred.promise, /connection failed/);
167
+ assert.deepEqual(errors, ["cloud runtime connection failed after 5 attempt(s)"]);
74
168
  });
75
- test("connect() rejects the first-connect promise when the device token is missing", async () => {
169
+ test("connect() rejects the first-connect promise when the device token is missing", async (t) => {
76
170
  const runtime = makeRuntime({ device_token: "" });
77
171
  const internals = runtime;
78
- try {
79
- const deferred = Promise.withResolvers();
80
- internals.firstConnectDeferred = deferred;
81
- internals.connect();
82
- await assert.rejects(deferred.promise, /missing device token/);
83
- }
84
- finally {
85
- runtime.stop();
86
- }
172
+ t.after(() => runtime.stop());
173
+ const deferred = Promise.withResolvers();
174
+ internals.firstConnectDeferred = deferred;
175
+ internals.connect();
176
+ await assert.rejects(deferred.promise, /missing device token/);
177
+ });
178
+ test("socket activity is reported to runtime telemetry", async (t) => {
179
+ const events = [];
180
+ const telemetry = {
181
+ connecting: () => events.push({ name: "connecting" }),
182
+ connected: () => events.push({ name: "connected" }),
183
+ disconnected: () => events.push({ name: "disconnected" }),
184
+ socketError: () => events.push({ name: "error" }),
185
+ received: () => events.push({ name: "received" }),
186
+ sent: () => events.push({ name: "sent" }),
187
+ projectsAdvertised: (details) => events.push({ name: "projects", details }),
188
+ requestStarted: (details) => events.push({ name: "request-started", details }),
189
+ requestFinished: (details) => events.push({ name: "request-finished", details }),
190
+ stopped: () => events.push({ name: "stopped" }),
191
+ };
192
+ const runtime = new CloudRuntime({ gateway_url: "wss://cloud.example.net", device_token: "fixture", runtime_id: "runtime" }, {
193
+ execute: async () => ({ ok: true }),
194
+ advertisedProjects: async () => [{
195
+ alias: "project-one",
196
+ path: "/work/project-one",
197
+ repoIdentity: "repo-one",
198
+ markers: [".gsd"],
199
+ }],
200
+ }, noopLogger, telemetry);
201
+ const internals = runtime;
202
+ t.after(() => runtime.stop());
203
+ const socket = fakeSocket();
204
+ internals.socket = socket;
205
+ internals.handleSocketOpen(socket);
206
+ await new Promise((resolve) => setImmediate(resolve));
207
+ await internals.handleSocketMessage(socket, JSON.stringify({
208
+ type: "tool_call",
209
+ requestId: "request-1",
210
+ toolName: "gsd_status",
211
+ projectAlias: "project-one",
212
+ }));
213
+ assert.ok(events.some((event) => event.name === "connected"));
214
+ assert.ok(events.some((event) => event.name === "received"));
215
+ const advertised = events.find((event) => event.name === "projects");
216
+ assert.equal((advertised?.details)[0]?.alias, "project-one");
217
+ const started = events.find((event) => event.name === "request-started");
218
+ assert.equal((started?.details).projectAlias, "project-one");
219
+ assert.equal((started?.details).toolName, "gsd_status");
220
+ assert.ok(((started?.details).receivedBytes ?? 0) > 0);
221
+ const finished = events.find((event) => event.name === "request-finished");
222
+ assert.equal((finished?.details).projectAlias, "project-one");
223
+ assert.equal((finished?.details).outcome, "success");
224
+ assert.equal((finished?.details).sentBytes, undefined);
225
+ assert.ok(events.some((event) => event.name === "sent"));
226
+ });
227
+ test("startup failures flush runtime telemetry before rejecting", async (t) => {
228
+ const root = mkdtempSync(join(tmpdir(), "gsd-cloud-startup-error-"));
229
+ t.after(() => rmSync(root, { recursive: true, force: true }));
230
+ const telemetry = new RuntimeTelemetryStore(join(root, "daemon.yaml"), {
231
+ gatewayUrl: "wss://cloud.example.net",
232
+ });
233
+ const runtime = new CloudRuntime({ gateway_url: "wss://cloud.example.net", device_token: "", runtime_id: "runtime" }, noopExecutor, noopLogger, telemetry);
234
+ t.after(() => runtime.stop());
235
+ await assert.rejects(runtime.start(), /missing device token/);
236
+ const status = JSON.parse(readFileSync(join(root, "cloud-runtime-status.json"), "utf8"));
237
+ assert.equal(status.state, "error");
238
+ assert.equal(status.last_error, "cloud runtime missing device token or runtime id");
239
+ });
240
+ test("malformed gateway failures flush runtime telemetry before rejecting", async (t) => {
241
+ const root = mkdtempSync(join(tmpdir(), "gsd-cloud-startup-url-error-"));
242
+ t.after(() => rmSync(root, { recursive: true, force: true }));
243
+ const telemetry = new RuntimeTelemetryStore(join(root, "daemon.yaml"), {
244
+ gatewayUrl: "not-a-url",
245
+ });
246
+ const runtime = new CloudRuntime({ gateway_url: "not-a-url", device_token: "fixture", runtime_id: "runtime" }, noopExecutor, noopLogger, telemetry);
247
+ t.after(() => runtime.stop());
248
+ await assert.rejects(runtime.start(), /absolute HTTP\(S\) URL/);
249
+ const status = JSON.parse(readFileSync(join(root, "cloud-runtime-status.json"), "utf8"));
250
+ assert.equal(status.state, "error");
251
+ assert.match(status.last_error ?? "", /absolute HTTP\(S\) URL/);
87
252
  });
88
253
  //# sourceMappingURL=cloud-runtime.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-runtime.test.js","sourceRoot":"","sources":["../src/cloud-runtime.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Regression tests for CloudRuntime.start()'s first-connect promise\n// — it must resolve only once the relay is actually up and reject on connect\n// failure, so the CLI never reports \"connected\" for a socket that never opened.\nimport { test } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport WebSocket from \"ws\";\nimport { CloudRuntime } from \"./cloud-runtime.js\";\n\nconst noopLogger = { info: () => undefined, warn: () => undefined, error: () => undefined, debug: () => undefined };\nconst noopExecutor = { execute: async () => ({}), advertisedProjects: async () => [] };\n\nfunction makeRuntime(cloud: Record<string, unknown> = {}): CloudRuntime {\n return new CloudRuntime(\n { gateway_url: \"wss://cloud.example.net\", device_token: \"fixture\", runtime_id: \"runtime\", ...cloud } as never,\n noopExecutor as never,\n noopLogger as never,\n );\n}\n\ntype FakeSocket = { readyState: number; sent: string[]; send: (t: string) => void; close: () => void };\nfunction fakeSocket(readyState = WebSocket.OPEN): FakeSocket {\n const sent: string[] = [];\n return { readyState, sent, send: (t: string) => sent.push(t), close: () => undefined };\n}\ntype RuntimeInternals = {\n socket: FakeSocket | undefined;\n firstConnectDeferred: PromiseWithResolvers<void> | undefined;\n initialConnectAttempts: number;\n reconnect: ReturnType<typeof setTimeout> | undefined;\n handleSocketOpen: (socket: unknown) => void;\n handleSocketClose: (socket: unknown) => void;\n connect: () => void;\n};\n\ntest(\"start()'s first-connect promise resolves only when the relay socket opens\", async () => {\n const runtime = makeRuntime();\n const internals = runtime as unknown as RuntimeInternals;\n try {\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n const socket = fakeSocket();\n internals.socket = socket;\n\n let settled = false;\n void deferred.promise.then(() => (settled = true));\n await Promise.resolve(); // let any premature settle flush\n assert.equal(settled, false, \"promise must not resolve before the socket opens\");\n\n internals.handleSocketOpen(socket);\n await deferred.promise; // resolves — otherwise this hangs/throws\n } finally {\n runtime.stop();\n }\n});\n\ntest(\"an early socket close retries instead of rejecting while attempts remain\", async () => {\n const runtime = makeRuntime();\n const internals = runtime as unknown as RuntimeInternals;\n try {\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n const socket = fakeSocket();\n internals.socket = socket;\n\n let settled = false;\n void deferred.promise.then(() => (settled = true), () => (settled = true));\n\n internals.handleSocketClose(socket); // first transient failure\n await Promise.resolve();\n assert.equal(settled, false, \"a single early close must not settle start()\");\n assert.equal(internals.initialConnectAttempts, 1);\n assert.notEqual(internals.reconnect, undefined, \"a reconnect must be scheduled\");\n } finally {\n runtime.stop();\n }\n});\n\ntest(\"start()'s first-connect promise rejects once the initial connect attempts are exhausted\", async () => {\n const runtime = makeRuntime();\n const internals = runtime as unknown as RuntimeInternals;\n try {\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n // Simulate having already burned every retry but the last so the next close\n // is the one that must give up and reject.\n internals.initialConnectAttempts = 4;\n const socket = fakeSocket();\n internals.socket = socket;\n\n internals.handleSocketClose(socket);\n await assert.rejects(deferred.promise, /connection failed/);\n } finally {\n runtime.stop();\n }\n});\n\ntest(\"connect() rejects the first-connect promise when the device token is missing\", async () => {\n const runtime = makeRuntime({ device_token: \"\" });\n const internals = runtime as unknown as RuntimeInternals;\n try {\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n internals.connect();\n await assert.rejects(deferred.promise, /missing device token/);\n } finally {\n runtime.stop();\n }\n});\n"]}
1
+ {"version":3,"file":"cloud-runtime.test.js","sourceRoot":"","sources":["../src/cloud-runtime.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Regression tests for CloudRuntime.start()'s first-connect promise\n// — it must resolve only once the relay is actually up and reject on connect\n// failure, so the CLI never reports \"connected\" for a socket that never opened.\nimport { test } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport WebSocket from \"ws\";\nimport { CloudRuntime } from \"./cloud-runtime.js\";\nimport { RuntimeTelemetryStore } from \"./runtime-telemetry.js\";\n\nconst noopLogger = { info: () => undefined, warn: () => undefined, error: () => undefined, debug: () => undefined };\nconst noopExecutor = { execute: async () => ({}), advertisedProjects: async () => [] };\n\nfunction makeRuntime(cloud: Record<string, unknown> = {}): CloudRuntime {\n return new CloudRuntime(\n { gateway_url: \"wss://cloud.example.net\", device_token: \"fixture\", runtime_id: \"runtime\", ...cloud } as never,\n noopExecutor as never,\n noopLogger as never,\n );\n}\n\ntype FakeSocket = { readyState: number; sent: string[]; send: (t: string) => void; close: () => void };\nfunction fakeSocket(readyState: number = WebSocket.OPEN): FakeSocket {\n const sent: string[] = [];\n return { readyState, sent, send: (t: string) => sent.push(t), close: () => undefined };\n}\ntype RuntimeInternals = {\n socket: FakeSocket | undefined;\n advertisedProjects: Array<{ alias: string; path: string; repoIdentity: string; markers: string[] }>;\n firstConnectDeferred: PromiseWithResolvers<void> | undefined;\n initialConnectAttempts: number;\n reconnect: ReturnType<typeof setTimeout> | undefined;\n handleSocketOpen: (socket: unknown) => void;\n handleSocketClose: (socket: unknown) => void;\n handleSocketMessage: (socket: unknown, text: string) => Promise<void>;\n connect: () => void;\n};\n\ntest(\"one routing selector drives execution, cancellation, and telemetry\", async (t) => {\n const selectors: Array<string | undefined> = [];\n const started: Array<{ projectAlias?: string; projectPath?: string }> = [];\n const execution = Promise.withResolvers<unknown>();\n const telemetry = {\n ...Object.fromEntries([\n \"connecting\", \"connected\", \"disconnected\", \"socketError\", \"received\", \"sent\",\n \"projectsAdvertised\", \"requestFinished\", \"stopped\",\n ].map((name) => [name, () => undefined])),\n requestStarted: (request: { projectAlias?: string; projectPath?: string }) => started.push(request),\n } as never;\n const runtime = new CloudRuntime(\n { gateway_url: \"wss://cloud.example.net\", device_token: \"fixture\", runtime_id: \"runtime\" },\n {\n execute: async (toolName: string, _args: unknown, selector?: string) => {\n selectors.push(selector);\n if (toolName === \"gsd_cancel\") return {};\n return execution.promise;\n },\n advertisedProjects: async () => [],\n } as never,\n noopLogger as never,\n telemetry,\n );\n const internals = runtime as unknown as RuntimeInternals;\n t.after(() => runtime.stop());\n internals.advertisedProjects = [\n { alias: \"one\", path: \"/work/one\", repoIdentity: \"one\", markers: [\".gsd\"] },\n { alias: \"two\", path: \"/work/two\", repoIdentity: \"two\", markers: [\".gsd\"] },\n ];\n const socket = fakeSocket();\n internals.socket = socket;\n\n const request = internals.handleSocketMessage(socket, JSON.stringify({\n type: \"tool_call\",\n requestId: \"request-routing\",\n toolName: \"gsd_status\",\n projectAlias: \"one\",\n args: { projectDir: \"/work/two\" },\n }));\n await Promise.resolve();\n await internals.handleSocketMessage(socket, JSON.stringify({\n type: \"cancel\",\n requestId: \"request-routing\",\n }));\n execution.resolve({});\n await request;\n\n assert.deepEqual(selectors, [\"one\", \"one\"]);\n assert.equal(started[0]?.projectAlias, \"one\");\n assert.equal(started[0]?.projectPath, \"/work/one\");\n\n internals.advertisedProjects = [\n { alias: \"app\", path: \"/work/one/app\", repoIdentity: \"one\", markers: [\".gsd\"] },\n { alias: \"app\", path: \"/work/two/app\", repoIdentity: \"two\", markers: [\".gsd\"] },\n ];\n await internals.handleSocketMessage(socket, JSON.stringify({\n type: \"tool_call\",\n requestId: \"request-ambiguous\",\n toolName: \"gsd_status\",\n projectAlias: \"app\",\n }));\n assert.equal(started[1]?.projectAlias, undefined);\n assert.equal(started[1]?.projectPath, undefined);\n\n});\n\ntest(\"queued project bytes are reported only after transmission\", async (t) => {\n const sentProjects: Array<string | undefined> = [];\n const telemetry = {\n ...Object.fromEntries([\n \"connecting\", \"connected\", \"disconnected\", \"socketError\", \"received\",\n \"projectsAdvertised\", \"requestStarted\", \"requestFinished\", \"stopped\",\n ].map((name) => [name, () => undefined])),\n sent: (_text: string, projectPath?: string) => sentProjects.push(projectPath),\n } as never;\n const runtime = new CloudRuntime(\n { gateway_url: \"wss://cloud.example.net\", device_token: \"fixture\", runtime_id: \"runtime\" },\n {\n execute: async () => ({ ok: true }),\n advertisedProjects: async () => [\n { alias: \"app\", path: \"/work/one/app\", repoIdentity: \"one\", markers: [\".gsd\"] },\n { alias: \"app\", path: \"/work/two/app\", repoIdentity: \"two\", markers: [\".gsd\"] },\n ],\n } as never,\n noopLogger as never,\n telemetry,\n );\n const internals = runtime as unknown as RuntimeInternals;\n t.after(() => runtime.stop());\n internals.advertisedProjects = [\n { alias: \"app\", path: \"/work/one/app\", repoIdentity: \"one\", markers: [\".gsd\"] },\n { alias: \"app\", path: \"/work/two/app\", repoIdentity: \"two\", markers: [\".gsd\"] },\n ];\n internals.socket = fakeSocket(WebSocket.CLOSED);\n\n await internals.handleSocketMessage(internals.socket, JSON.stringify({\n type: \"tool_call\",\n requestId: \"request-queued\",\n toolName: \"gsd_status\",\n args: { projectDir: \"/work/two/app\" },\n }));\n assert.deepEqual(sentProjects, []);\n\n const openSocket = fakeSocket();\n internals.socket = openSocket;\n internals.handleSocketOpen(openSocket);\n assert.deepEqual(sentProjects, [\"/work/two/app\"]);\n\n});\n\ntest(\"start()'s first-connect promise resolves only when the relay socket opens\", async (t) => {\n const runtime = makeRuntime();\n const internals = runtime as unknown as RuntimeInternals;\n t.after(() => runtime.stop());\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n const socket = fakeSocket();\n internals.socket = socket;\n\n let settled = false;\n void deferred.promise.then(() => (settled = true));\n await Promise.resolve(); // let any premature settle flush\n assert.equal(settled, false, \"promise must not resolve before the socket opens\");\n\n internals.handleSocketOpen(socket);\n await deferred.promise; // resolves — otherwise this hangs/throws\n\n});\n\ntest(\"an early socket close retries instead of rejecting while attempts remain\", async (t) => {\n const runtime = makeRuntime();\n const internals = runtime as unknown as RuntimeInternals;\n t.after(() => runtime.stop());\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n const socket = fakeSocket();\n internals.socket = socket;\n\n let settled = false;\n void deferred.promise.then(() => (settled = true), () => (settled = true));\n\n internals.handleSocketClose(socket); // first transient failure\n await Promise.resolve();\n assert.equal(settled, false, \"a single early close must not settle start()\");\n assert.equal(internals.initialConnectAttempts, 1);\n assert.notEqual(internals.reconnect, undefined, \"a reconnect must be scheduled\");\n\n});\n\ntest(\"start()'s first-connect promise rejects once the initial connect attempts are exhausted\", async (t) => {\n const errors: string[] = [];\n const telemetry = {\n ...Object.fromEntries([\n \"connecting\", \"connected\", \"disconnected\", \"received\", \"sent\", \"projectsAdvertised\",\n \"requestStarted\", \"requestFinished\", \"stopped\",\n ].map((name) => [name, () => undefined])),\n socketError: (message: string) => errors.push(message),\n } as never;\n const runtime = new CloudRuntime(\n { gateway_url: \"wss://cloud.example.net\", device_token: \"fixture\", runtime_id: \"runtime\" },\n noopExecutor as never,\n noopLogger as never,\n telemetry,\n );\n const internals = runtime as unknown as RuntimeInternals;\n t.after(() => runtime.stop());\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n // Simulate having already burned every retry but the last so the next close\n // is the one that must give up and reject.\n internals.initialConnectAttempts = 4;\n const socket = fakeSocket();\n internals.socket = socket;\n\n internals.handleSocketClose(socket);\n await assert.rejects(deferred.promise, /connection failed/);\n assert.deepEqual(errors, [\"cloud runtime connection failed after 5 attempt(s)\"]);\n\n});\n\ntest(\"connect() rejects the first-connect promise when the device token is missing\", async (t) => {\n const runtime = makeRuntime({ device_token: \"\" });\n const internals = runtime as unknown as RuntimeInternals;\n t.after(() => runtime.stop());\n const deferred = Promise.withResolvers<void>();\n internals.firstConnectDeferred = deferred;\n internals.connect();\n await assert.rejects(deferred.promise, /missing device token/);\n\n});\n\ntest(\"socket activity is reported to runtime telemetry\", async (t) => {\n const events: Array<{ name: string; details?: unknown }> = [];\n const telemetry = {\n connecting: () => events.push({ name: \"connecting\" }),\n connected: () => events.push({ name: \"connected\" }),\n disconnected: () => events.push({ name: \"disconnected\" }),\n socketError: () => events.push({ name: \"error\" }),\n received: () => events.push({ name: \"received\" }),\n sent: () => events.push({ name: \"sent\" }),\n projectsAdvertised: (details: unknown) => events.push({ name: \"projects\", details }),\n requestStarted: (details: unknown) => events.push({ name: \"request-started\", details }),\n requestFinished: (details: unknown) => events.push({ name: \"request-finished\", details }),\n stopped: () => events.push({ name: \"stopped\" }),\n };\n const runtime = new CloudRuntime(\n { gateway_url: \"wss://cloud.example.net\", device_token: \"fixture\", runtime_id: \"runtime\" },\n {\n execute: async () => ({ ok: true }),\n advertisedProjects: async () => [{\n alias: \"project-one\",\n path: \"/work/project-one\",\n repoIdentity: \"repo-one\",\n markers: [\".gsd\"],\n }],\n } as never,\n noopLogger as never,\n telemetry,\n );\n const internals = runtime as unknown as RuntimeInternals;\n t.after(() => runtime.stop());\n const socket = fakeSocket();\n internals.socket = socket;\n\n internals.handleSocketOpen(socket);\n await new Promise((resolve) => setImmediate(resolve));\n await internals.handleSocketMessage(socket, JSON.stringify({\n type: \"tool_call\",\n requestId: \"request-1\",\n toolName: \"gsd_status\",\n projectAlias: \"project-one\",\n }));\n\n assert.ok(events.some((event) => event.name === \"connected\"));\n assert.ok(events.some((event) => event.name === \"received\"));\n const advertised = events.find((event) => event.name === \"projects\");\n assert.equal((advertised?.details as Array<{ alias?: string }>)[0]?.alias, \"project-one\");\n const started = events.find((event) => event.name === \"request-started\");\n assert.equal((started?.details as { projectAlias?: string }).projectAlias, \"project-one\");\n assert.equal((started?.details as { toolName?: string }).toolName, \"gsd_status\");\n assert.ok(((started?.details as { receivedBytes?: number }).receivedBytes ?? 0) > 0);\n const finished = events.find((event) => event.name === \"request-finished\");\n assert.equal((finished?.details as { projectAlias?: string }).projectAlias, \"project-one\");\n assert.equal((finished?.details as { outcome?: string }).outcome, \"success\");\n assert.equal((finished?.details as { sentBytes?: number }).sentBytes, undefined);\n assert.ok(events.some((event) => event.name === \"sent\"));\n\n});\n\ntest(\"startup failures flush runtime telemetry before rejecting\", async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-startup-error-\"));\n t.after(() => rmSync(root, { recursive: true, force: true }));\n const telemetry = new RuntimeTelemetryStore(join(root, \"daemon.yaml\"), {\n gatewayUrl: \"wss://cloud.example.net\",\n });\n const runtime = new CloudRuntime(\n { gateway_url: \"wss://cloud.example.net\", device_token: \"\", runtime_id: \"runtime\" },\n noopExecutor as never,\n noopLogger as never,\n telemetry,\n );\n t.after(() => runtime.stop());\n\n await assert.rejects(runtime.start(), /missing device token/);\n const status = JSON.parse(readFileSync(join(root, \"cloud-runtime-status.json\"), \"utf8\")) as {\n state?: string;\n last_error?: string;\n };\n assert.equal(status.state, \"error\");\n assert.equal(status.last_error, \"cloud runtime missing device token or runtime id\");\n\n});\n\ntest(\"malformed gateway failures flush runtime telemetry before rejecting\", async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-startup-url-error-\"));\n t.after(() => rmSync(root, { recursive: true, force: true }));\n const telemetry = new RuntimeTelemetryStore(join(root, \"daemon.yaml\"), {\n gatewayUrl: \"not-a-url\",\n });\n const runtime = new CloudRuntime(\n { gateway_url: \"not-a-url\", device_token: \"fixture\", runtime_id: \"runtime\" },\n noopExecutor as never,\n noopLogger as never,\n telemetry,\n );\n t.after(() => runtime.stop());\n\n await assert.rejects(runtime.start(), /absolute HTTP\\(S\\) URL/);\n const status = JSON.parse(readFileSync(join(root, \"cloud-runtime-status.json\"), \"utf8\")) as {\n state?: string;\n last_error?: string;\n };\n assert.equal(status.state, \"error\");\n assert.match(status.last_error ?? \"\", /absolute HTTP\\(S\\) URL/);\n\n});\n"]}
@@ -0,0 +1,3 @@
1
+ export declare function canonicalConfigPath(configPath: string): string;
2
+ export declare function runtimeArtifactPath(configPath: string, artifact: "status" | "state" | "log" | "start.lock"): string;
3
+ //# sourceMappingURL=runtime-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-artifacts.d.ts","sourceRoot":"","sources":["../src/runtime-artifacts.ts"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,YAAY,GAClD,MAAM,CAcR"}
@@ -0,0 +1,36 @@
1
+ import { createHash } from "node:crypto";
2
+ import { realpathSync } from "node:fs";
3
+ import { basename, dirname, join, resolve } from "node:path";
4
+ export function canonicalConfigPath(configPath) {
5
+ const absolutePath = resolve(configPath);
6
+ try {
7
+ return realpathSync(absolutePath);
8
+ }
9
+ catch {
10
+ return absolutePath;
11
+ }
12
+ }
13
+ export function runtimeArtifactPath(configPath, artifact) {
14
+ const canonicalPath = canonicalConfigPath(configPath);
15
+ const legacy = basename(canonicalPath) === "daemon.yaml";
16
+ const namespace = legacy
17
+ ? ""
18
+ : `-${createHash("sha256").update(canonicalPath).digest("hex").slice(0, 16)}`;
19
+ let suffix;
20
+ switch (artifact) {
21
+ case "status":
22
+ suffix = "-status.json";
23
+ break;
24
+ case "state":
25
+ suffix = ".json";
26
+ break;
27
+ case "log":
28
+ suffix = ".log";
29
+ break;
30
+ case "start.lock":
31
+ suffix = ".start.lock";
32
+ break;
33
+ }
34
+ return join(dirname(canonicalPath), `cloud-runtime${namespace}${suffix}`);
35
+ }
36
+ //# sourceMappingURL=runtime-artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-artifacts.js","sourceRoot":"","sources":["../src/runtime-artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7D,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,YAAY,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,YAAY,CAAC;IACtB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,QAAmD;IAEnD,MAAM,aAAa,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,aAAa,CAAC;IACzD,MAAM,SAAS,GAAG,MAAM;QACtB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAChF,IAAI,MAAc,CAAC;IACnB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YAAE,MAAM,GAAG,cAAc,CAAC;YAAC,MAAM;QAC9C,KAAK,OAAO;YAAE,MAAM,GAAG,OAAO,CAAC;YAAC,MAAM;QACtC,KAAK,KAAK;YAAE,MAAM,GAAG,MAAM,CAAC;YAAC,MAAM;QACnC,KAAK,YAAY;YAAE,MAAM,GAAG,aAAa,CAAC;YAAC,MAAM;IACnD,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,gBAAgB,SAAS,GAAG,MAAM,EAAE,CAAC,CAAC;AAC5E,CAAC","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { realpathSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\n\nexport function canonicalConfigPath(configPath: string): string {\n const absolutePath = resolve(configPath);\n try {\n return realpathSync(absolutePath);\n } catch {\n return absolutePath;\n }\n}\n\nexport function runtimeArtifactPath(\n configPath: string,\n artifact: \"status\" | \"state\" | \"log\" | \"start.lock\",\n): string {\n const canonicalPath = canonicalConfigPath(configPath);\n const legacy = basename(canonicalPath) === \"daemon.yaml\";\n const namespace = legacy\n ? \"\"\n : `-${createHash(\"sha256\").update(canonicalPath).digest(\"hex\").slice(0, 16)}`;\n let suffix: string;\n switch (artifact) {\n case \"status\": suffix = \"-status.json\"; break;\n case \"state\": suffix = \".json\"; break;\n case \"log\": suffix = \".log\"; break;\n case \"start.lock\": suffix = \".start.lock\"; break;\n }\n return join(dirname(canonicalPath), `cloud-runtime${namespace}${suffix}`);\n}\n"]}
@@ -0,0 +1,32 @@
1
+ export interface RuntimeProcessStatus {
2
+ running: boolean;
3
+ pid: number | null;
4
+ projects: string[];
5
+ log_file: string;
6
+ }
7
+ interface StartRuntimeOptions {
8
+ binaryPath: string;
9
+ configPath: string;
10
+ projectDirs: string[];
11
+ readyTimeoutMs?: number;
12
+ verbose?: boolean;
13
+ processIdentityReader?: (pid: number) => string | null;
14
+ }
15
+ export declare const BACKGROUND_RUNTIME_READY_TIMEOUT_MS: number;
16
+ export declare function startBackgroundRuntime(opts: StartRuntimeOptions): Promise<RuntimeProcessStatus>;
17
+ /**
18
+ * Record a running runtime so a later launch can find and stop it. Used both by
19
+ * the detached launcher (child PID) and by a `--foreground` session (its own
20
+ * PID), so the two modes share one source of truth and never coexist on the
21
+ * same device token.
22
+ */
23
+ export declare function writeRuntimeState(configPath: string, pid: number, projects: string[]): void;
24
+ export declare function clearRuntimeState(configPath: string): void;
25
+ export declare function stopBackgroundRuntime(configPath: string): Promise<boolean>;
26
+ export declare function backgroundRuntimeStatus(configPath: string): RuntimeProcessStatus;
27
+ export declare function runtimeStatePath(configPath: string): string;
28
+ export declare function runtimeLogPath(configPath: string): string;
29
+ export declare function acquireRuntimeStartLock(configPath: string, onRecoveryClaimed?: () => void): Promise<() => void>;
30
+ export declare function commandLineMatchesRuntimeConfig(command: string, configPath: string, platform: NodeJS.Platform): boolean;
31
+ export {};
32
+ //# sourceMappingURL=runtime-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-process.d.ts","sourceRoot":"","sources":["../src/runtime-process.ts"],"names":[],"mappings":"AAmCA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,mBAAmB;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qBAAqB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACxD;AAQD,eAAO,MAAM,mCAAmC,QACoB,CAAC;AAKrE,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAwErG;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAM3F;AAiBD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWhF;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,CAoBhF;AAmCD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEzD;AAMD,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,iBAAiB,CAAC,EAAE,MAAM,IAAI,GAC7B,OAAO,CAAC,MAAM,IAAI,CAAC,CAoCrB;AAgOD,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,CAAC,QAAQ,GACxB,OAAO,CAKT"}