@opengsd/gsd-pi 1.10.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +1 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-verification.js +25 -12
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +4 -3
- package/dist/resources/extensions/gsd/db/engine.js +8 -2
- package/dist/resources/extensions/gsd/db-canonical-foundation-schema.js +120 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +4 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +12 -3
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +16 -4
- package/dist/resources/extensions/gsd/model-cost-table.js +6 -3
- package/dist/resources/extensions/gsd/model-router.js +10 -5
- package/dist/resources/extensions/gsd/planning-subagent-registry.js +12 -4
- package/dist/resources/extensions/gsd/preferences-models.js +50 -10
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +41 -6
- package/dist/resources/extensions/gsd/preferences.js +7 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +3 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -1
- package/dist/resources/extensions/gsd/verification-evidence.js +5 -3
- package/dist/resources/extensions/ollama/ollama-chat-provider.js +2 -2
- package/dist/resources/extensions/subagent/index.js +1 -1
- package/dist/startup-model-validation.d.ts +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +7 -6
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -1
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/rpc.test.js +1 -1
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/cli/args.js +2 -2
- package/packages/gsd-agent-modes/dist/cli/args.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/gsd-cloud/README.md +12 -2
- package/packages/gsd-cloud/dist/background-cli.test.js +157 -80
- package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -1
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cli.js +36 -12
- package/packages/gsd-cloud/dist/cli.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +6 -1
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.js +106 -24
- package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.test.js +224 -59
- package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -1
- package/packages/gsd-cloud/dist/runtime-artifacts.d.ts +3 -0
- package/packages/gsd-cloud/dist/runtime-artifacts.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-artifacts.js +36 -0
- package/packages/gsd-cloud/dist/runtime-artifacts.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts +5 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/runtime-process.js +429 -61
- package/packages/gsd-cloud/dist/runtime-process.js.map +1 -1
- package/packages/gsd-cloud/dist/runtime-process.test.js +493 -47
- package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -1
- package/packages/gsd-cloud/dist/runtime-telemetry.d.ts +117 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.js +291 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.js +434 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.js.map +1 -0
- package/packages/gsd-cloud/package.json +2 -2
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +2 -2
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +113 -2
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +84 -9
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.js +18 -6
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +3 -2
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/packages/pi-ai/dist/providers/google.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +9 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -3
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +1 -0
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme.d.ts +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +1 -0
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +1 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-verification.ts +46 -12
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +4 -3
- package/src/resources/extensions/gsd/db/engine.ts +9 -1
- package/src/resources/extensions/gsd/db-canonical-foundation-schema.ts +129 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +5 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +12 -3
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +15 -4
- package/src/resources/extensions/gsd/model-cost-table.ts +14 -3
- package/src/resources/extensions/gsd/model-router.ts +10 -5
- package/src/resources/extensions/gsd/planning-subagent-registry.ts +18 -4
- package/src/resources/extensions/gsd/preferences-models.ts +54 -10
- package/src/resources/extensions/gsd/preferences-types.ts +10 -2
- package/src/resources/extensions/gsd/preferences-validation.ts +49 -6
- package/src/resources/extensions/gsd/preferences.ts +13 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +3 -0
- package/src/resources/extensions/gsd/tests/db-canonical-foundation.test.ts +459 -0
- package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +22 -7
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/preferences.test.ts +71 -4
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-faults.test.ts +238 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-fixture.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-fixture.ts +141 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-projection-conflict.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/workflow-fault-harness.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/workflow-fault-harness.ts +72 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +40 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +5 -1
- package/src/resources/extensions/gsd/verification-evidence.ts +5 -2
- package/src/resources/extensions/ollama/ollama-chat-provider.ts +2 -2
- package/src/resources/extensions/ollama/tests/ollama-chat-provider-think.test.ts +4 -0
- package/src/resources/extensions/subagent/index.ts +1 -1
- /package/dist/web/standalone/.next/static/{EAhnhYMt5UVOiG9-iPDjc → 8ub6oiEp2YnlOHQU20LJr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{EAhnhYMt5UVOiG9-iPDjc → 8ub6oiEp2YnlOHQU20LJr}/_ssgManifest.js +0 -0
|
@@ -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("
|
|
19
|
-
const
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
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("
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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("
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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":"AAAA,wBAAwB;AACxB,kFAAkF;AAClF,6EAA6E;AAC7E,gFAAgF;AAChF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;AACpH,MAAM,YAAY,GAAG,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;AAEvF,SAAS,WAAW,CAAC,QAAiC,EAAE;IACtD,OAAO,IAAI,YAAY,CACrB,EAAE,WAAW,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,EAAW,EAC7G,YAAqB,EACrB,UAAmB,CACpB,CAAC;AACJ,CAAC;AAGD,SAAS,UAAU,CAAC,aAAqB,SAAS,CAAC,IAAI;IACrD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;AACzF,CAAC;AAaD,IAAI,CAAC,oEAAoE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACrF,MAAM,SAAS,GAA8B,EAAE,CAAC;IAChD,MAAM,OAAO,GAA2D,EAAE,CAAC;IAC3E,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,EAAW,CAAC;IACnD,MAAM,SAAS,GAAG;QAChB,GAAG,MAAM,CAAC,WAAW,CAAC;YACpB,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM;YAC5E,oBAAoB,EAAE,iBAAiB,EAAE,SAAS;SACnD,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QACzC,cAAc,EAAE,CAAC,OAAwD,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;KAC3F,CAAC;IACX,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,EAAE,WAAW,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAC1F;QACE,OAAO,EAAE,KAAK,EAAE,QAAgB,EAAE,KAAc,EAAE,QAAiB,EAAE,EAAE;YACrE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,IAAI,QAAQ,KAAK,YAAY;gBAAE,OAAO,EAAE,CAAC;YACzC,OAAO,SAAS,CAAC,OAAO,CAAC;QAC3B,CAAC;QACD,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;KAC1B,EACV,UAAmB,EACnB,SAAS,CACV,CAAC;IACF,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,SAAS,CAAC,kBAAkB,GAAG;QAC7B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;QAC3E,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;KAC5E,CAAC;IACF,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAExB,MAAM,OAAO,GAAG,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;QACnE,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,iBAAiB;QAC5B,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,KAAK;QACnB,IAAI,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE;KAClC,CAAC,CAAC,CAAC;IACJ,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IACxB,MAAM,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;QACzD,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,iBAAiB;KAC7B,CAAC,CAAC,CAAC;IACJ,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACtB,MAAM,OAAO,CAAC;IAEd,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAEnD,SAAS,CAAC,kBAAkB,GAAG;QAC7B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;QAC/E,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;KAChF,CAAC;IACF,MAAM,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;QACzD,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,mBAAmB;QAC9B,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,KAAK;KACpB,CAAC,CAAC,CAAC;IACJ,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;AAErD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2DAA2D,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC5E,MAAM,YAAY,GAA8B,EAAE,CAAC;IACnD,MAAM,SAAS,GAAG;QAChB,GAAG,MAAM,CAAC,WAAW,CAAC;YACpB,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU;YACpE,oBAAoB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,SAAS;SACrE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QACzC,IAAI,EAAE,CAAC,KAAa,EAAE,WAAoB,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC;KACrE,CAAC;IACX,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,EAAE,WAAW,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAC1F;QACE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACnC,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC;YAC9B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;YAC/E,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;SAChF;KACO,EACV,UAAmB,EACnB,SAAS,CACV,CAAC;IACF,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,SAAS,CAAC,kBAAkB,GAAG;QAC7B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;QAC/E,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;KAChF,CAAC;IACF,SAAS,CAAC,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE9C,MAAM,SAAS,CAAC,mBAAmB,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;QACnE,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,gBAAgB;QAC3B,QAAQ,EAAE,YAAY;QACtB,IAAI,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE;KACtC,CAAC,CAAC,CAAC;IACJ,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAEnC,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC;IAChC,SAAS,CAAC,MAAM,GAAG,UAAU,CAAC;IAC9B,SAAS,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;AAEtD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2EAA2E,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC5F,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAC/C,SAAS,CAAC,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAE1B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,iCAAiC;IAC1D,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,kDAAkD,CAAC,CAAC;IAEjF,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,yCAAyC;AAErE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0EAA0E,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC3F,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAC/C,SAAS,CAAC,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAE1B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC;IAE3E,SAAS,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,0BAA0B;IAC/D,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,8CAA8C,CAAC,CAAC;IAC7E,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;IAClD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,+BAA+B,CAAC,CAAC;AAErF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yFAAyF,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC1G,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG;QAChB,GAAG,MAAM,CAAC,WAAW,CAAC;YACpB,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,oBAAoB;YACnF,gBAAgB,EAAE,iBAAiB,EAAE,SAAS;SAC/C,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QACzC,WAAW,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;KAC9C,CAAC;IACX,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,EAAE,WAAW,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAC1F,YAAqB,EACrB,UAAmB,EACnB,SAAS,CACV,CAAC;IACF,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAC/C,SAAS,CAAC,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,4EAA4E;IAC5E,2CAA2C;IAC3C,SAAS,CAAC,sBAAsB,GAAG,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAE1B,SAAS,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAC5D,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,oDAAoD,CAAC,CAAC,CAAC;AAErF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8EAA8E,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC/F,MAAM,OAAO,GAAG,WAAW,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAC/C,SAAS,CAAC,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,SAAS,CAAC,OAAO,EAAE,CAAC;IACpB,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;AAEnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kDAAkD,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACnE,MAAM,MAAM,GAA+C,EAAE,CAAC;IAC9D,MAAM,SAAS,GAAG;QAChB,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QACrD,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QACnD,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;QACzD,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACjD,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QACjD,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACzC,kBAAkB,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QACpF,cAAc,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC;QACvF,eAAe,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC;QACzF,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;KAChD,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,EAAE,WAAW,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAC1F;QACE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACnC,kBAAkB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;gBAC/B,KAAK,EAAE,aAAa;gBACpB,IAAI,EAAE,mBAAmB;gBACzB,YAAY,EAAE,UAAU;gBACxB,OAAO,EAAE,CAAC,MAAM,CAAC;aAClB,CAAC;KACM,EACV,UAAmB,EACnB,SAAS,CACV,CAAC;IACF,MAAM,SAAS,GAAG,OAAsC,CAAC;IACzD,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAExB,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,MAAM,SAAS,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;QACzD,IAAI,EAAE,WAAW;QACjB,SAAS,EAAE,WAAW;QACtB,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,aAAa;KAC5B,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC;IAC9D,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IACrE,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,OAAqC,CAAA,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC;IACzE,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,OAAqC,CAAA,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAC1F,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,OAAiC,CAAA,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACjF,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,OAAsC,CAAA,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACrF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAqC,CAAA,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;IAC3F,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAgC,CAAA,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC7E,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAkC,CAAA,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACjF,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;AAE7D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2DAA2D,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC5E,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE;QACrE,UAAU,EAAE,yBAAyB;KACtC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,EAAE,WAAW,EAAE,yBAAyB,EAAE,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,EACnF,YAAqB,EACrB,UAAmB,EACnB,SAAS,CACV,CAAC;IACF,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAE5B,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,2BAA2B,CAAC,EAAE,MAAM,CAAC,CAGtF,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,kDAAkD,CAAC,CAAC;AAExF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qEAAqE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACtF,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,8BAA8B,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE;QACrE,UAAU,EAAE,WAAW;KACxB,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,YAAY,CAC9B,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,EAC5E,YAAqB,EACrB,UAAmB,EACnB,SAAS,CACV,CAAC;IACF,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAE5B,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,wBAAwB,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,2BAA2B,CAAC,EAAE,MAAM,CAAC,CAGtF,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,EAAE,wBAAwB,CAAC,CAAC;AAEpE,CAAC,CAAC,CAAC","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 @@
|
|
|
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"]}
|
|
@@ -10,6 +10,7 @@ interface StartRuntimeOptions {
|
|
|
10
10
|
projectDirs: string[];
|
|
11
11
|
readyTimeoutMs?: number;
|
|
12
12
|
verbose?: boolean;
|
|
13
|
+
processIdentityReader?: (pid: number) => string | null;
|
|
13
14
|
}
|
|
14
15
|
export declare const BACKGROUND_RUNTIME_READY_TIMEOUT_MS: number;
|
|
15
16
|
export declare function startBackgroundRuntime(opts: StartRuntimeOptions): Promise<RuntimeProcessStatus>;
|
|
@@ -23,5 +24,9 @@ export declare function writeRuntimeState(configPath: string, pid: number, proje
|
|
|
23
24
|
export declare function clearRuntimeState(configPath: string): void;
|
|
24
25
|
export declare function stopBackgroundRuntime(configPath: string): Promise<boolean>;
|
|
25
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;
|
|
26
31
|
export {};
|
|
27
32
|
//# sourceMappingURL=runtime-process.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-process.d.ts","sourceRoot":"","sources":["../src/runtime-process.ts"],"names":[],"mappings":"
|
|
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"}
|