@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.
- package/README.md +10 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/loop.js +24 -4
- package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +1 -0
- package/dist/resources/extensions/gsd/auto-start.js +30 -10
- package/dist/resources/extensions/gsd/auto-verification.js +25 -12
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
- package/dist/resources/extensions/gsd/auto.js +12 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +4 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +12 -3
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +37 -6
- package/dist/resources/extensions/gsd/flat-phase-migration.js +12 -0
- package/dist/resources/extensions/gsd/gsd-db.js +75 -31
- 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/gsd/worktree-state-projection.js +20 -18
- 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 +6 -6
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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 +6 -6
- package/dist/web/standalone/.next/server/chunks/1991.js +2 -2
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- 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/.next/server/server-reference-manifest.json +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 +21 -5
- package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/background-cli.test.js +325 -0
- package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cli.js +146 -16
- package/packages/gsd-cloud/dist/cli.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-config.d.ts +1 -1
- package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cloud-config.js +7 -1
- package/packages/gsd-cloud/dist/cloud-config.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +7 -4
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.js +115 -31
- 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 +32 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.js +640 -0
- package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js +543 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
- 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/dist/cli-runner.d.ts +3 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
- package/packages/mcp-server/dist/cli-runner.js +119 -33
- package/packages/mcp-server/dist/cli-runner.js.map +1 -1
- 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 +130 -2
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +101 -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/core/skills.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +54 -0
- package/packages/pi-coding-agent/dist/core/skills.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/loop.ts +48 -4
- package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +1 -0
- package/src/resources/extensions/gsd/auto-start.ts +32 -9
- package/src/resources/extensions/gsd/auto-verification.ts +46 -12
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
- package/src/resources/extensions/gsd/auto.ts +13 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +4 -3
- package/src/resources/extensions/gsd/docs/preferences-reference.md +12 -3
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +42 -6
- package/src/resources/extensions/gsd/flat-phase-migration.ts +14 -0
- package/src/resources/extensions/gsd/gsd-db.ts +85 -33
- 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/auto-loop.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +8 -9
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -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/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/worktree-state-projection.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -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/gsd/worktree-state-projection.ts +21 -24
- 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/{V9MAVyYVPboQUB9KTTAMi → xwUaOqui04jIIFVsIBLiL}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{V9MAVyYVPboQUB9KTTAMi → xwUaOqui04jIIFVsIBLiL}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-process.test.js","sourceRoot":"","sources":["../src/runtime-process.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Regression coverage for detached cloud runtime process timing and shutdown.\nimport { spawn } from \"node:child_process\";\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, utimesSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { test } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { CLOUD_RUNTIME_INITIAL_CONNECT_WINDOW_MS } from \"./cloud-runtime.js\";\nimport {\n BACKGROUND_RUNTIME_READY_TIMEOUT_MS,\n acquireRuntimeStartLock,\n backgroundRuntimeStatus,\n commandLineMatchesRuntimeConfig,\n runtimeLogPath,\n runtimeStatePath,\n startBackgroundRuntime,\n stopBackgroundRuntime,\n writeRuntimeState,\n} from \"./runtime-process.js\";\nimport { runtimeArtifactPath } from \"./runtime-artifacts.js\";\nimport { runtimeTelemetryPath } from \"./runtime-telemetry.js\";\n\ntest(\"background startup allows the cloud runtime's full initial reconnect window\", () => {\n assert.ok(BACKGROUND_RUNTIME_READY_TIMEOUT_MS > CLOUD_RUNTIME_INITIAL_CONNECT_WINDOW_MS);\n});\n\ntest(\"runtime artifacts are namespaced by config path while daemon.yaml stays legacy-compatible\", (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-artifacts-\"));\n t.after(() => rmSync(root, { recursive: true, force: true }));\n const defaultConfig = join(root, \"daemon.yaml\");\n const firstConfig = join(root, \"first.yaml\");\n const secondConfig = join(root, \"second.yaml\");\n\n assert.equal(runtimeStatePath(defaultConfig), join(root, \"cloud-runtime.json\"));\n assert.equal(runtimeLogPath(defaultConfig), join(root, \"cloud-runtime.log\"));\n assert.equal(runtimeTelemetryPath(defaultConfig), join(root, \"cloud-runtime-status.json\"));\n assert.notEqual(runtimeStatePath(firstConfig), runtimeStatePath(secondConfig));\n assert.notEqual(runtimeLogPath(firstConfig), runtimeLogPath(secondConfig));\n assert.notEqual(runtimeTelemetryPath(firstConfig), runtimeTelemetryPath(secondConfig));\n});\n\ntest(\"runtime artifact namespace is stable across monitor implementations\", () => {\n assert.equal(\n runtimeStatePath(\"/work/state/first.yaml\"),\n \"/work/state/cloud-runtime-58cb3ff924131c6e.json\",\n );\n});\n\ntest(\"stop refuses to signal a process whose identity does not match state\", async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-reused-pid-\"));\n const configPath = join(root, \"daemon.yaml\");\n const statePath = join(root, \"cloud-runtime.json\");\n const child = spawn(process.execPath, [\"-e\", \"setInterval(()=>{},1000)\"]);\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(child.pid);\n writeFileSync(statePath, `${JSON.stringify({\n pid: child.pid,\n projects: [root],\n process_start_identity: \"not-this-process\",\n })}\\n`);\n\n assert.equal(await stopBackgroundRuntime(configPath), false);\n assert.equal(processIsRunning(child.pid), true);\n assert.equal(existsSync(statePath), true);\n});\n\ntest(\"custom configs migrate matching live legacy runtime state\", (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-legacy-state-\"));\n const configPath = join(root, \"custom.yaml\");\n const legacyStatePath = join(root, \"cloud-runtime.json\");\n const child = spawn(process.execPath, [\n writeLegacyRuntime(root, \"gsd-cloud.js\"),\n \"_run\",\n \"--config\",\n configPath,\n ]);\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(child.pid);\n writeFileSync(legacyStatePath, `${JSON.stringify({ pid: child.pid, projects: [root] })}\\n`);\n\n const status = backgroundRuntimeStatus(configPath);\n\n assert.equal(status.running, true);\n assert.equal(status.pid, child.pid);\n assert.equal(existsSync(runtimeStatePath(configPath)), true);\n assert.equal(existsSync(legacyStatePath), false);\n});\n\nfor (const runtimeArgs of [\n [\"connect\"],\n [\"login\", \"--foreground\"],\n]) {\n test(`custom configs migrate legacy ${runtimeArgs.join(\" \")} runtime state`, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-foreground-legacy-\"));\n const configPath = join(root, \"custom runtime.yaml\");\n const legacyStatePath = join(root, \"cloud-runtime.json\");\n const binaryPath = writeLegacyRuntime(root, \"gsd-cloud.js\");\n const child = spawn(process.execPath, [\n binaryPath,\n ...runtimeArgs,\n \"--config\",\n configPath,\n ]);\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(child.pid);\n await waitForCondition(() => processIsRunning(child.pid!));\n writeFileSync(legacyStatePath, `${JSON.stringify({ pid: child.pid, projects: [root] })}\\n`);\n\n const status = backgroundRuntimeStatus(configPath);\n\n assert.equal(status.running, true);\n assert.equal(status.pid, child.pid);\n assert.equal(existsSync(runtimeStatePath(configPath)), true);\n assert.equal(existsSync(legacyStatePath), false);\n });\n}\n\ntest(\"legacy runtime state for another config is not migrated or signalled\", async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-foreign-legacy-state-\"));\n const requestedConfig = join(root, \"requested.yaml\");\n const actualConfig = join(root, \"actual.yaml\");\n const legacyStatePath = join(root, \"cloud-runtime.json\");\n const child = spawn(process.execPath, [\n \"-e\",\n \"setInterval(()=>{},1000)\",\n \"_run\",\n \"--config\",\n actualConfig,\n ]);\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(child.pid);\n writeFileSync(legacyStatePath, `${JSON.stringify({ pid: child.pid, projects: [root] })}\\n`);\n\n assert.equal(await stopBackgroundRuntime(requestedConfig), false);\n assert.equal(processIsRunning(child.pid), true);\n assert.equal(existsSync(legacyStatePath), true);\n});\n\ntest(\"default config preserves shared legacy state owned by a custom config\", async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-shared-legacy-state-\"));\n const requestedConfig = join(root, \"daemon.yaml\");\n const actualConfig = join(root, \"custom.yaml\");\n const legacyStatePath = join(root, \"cloud-runtime.json\");\n const binaryPath = writeLegacyRuntime(root, \"gsd-cloud.js\");\n const child = spawn(process.execPath, [binaryPath, \"connect\", \"--config\", actualConfig]);\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(child.pid);\n writeFileSync(legacyStatePath, `${JSON.stringify({ pid: child.pid, projects: [root] })}\\n`);\n\n assert.equal(await stopBackgroundRuntime(requestedConfig), false);\n assert.equal(processIsRunning(child.pid), true);\n assert.equal(existsSync(legacyStatePath), true);\n});\n\ntest(\"legacy migration rejects unrelated executables\", async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-unrelated-legacy-state-\"));\n const configPath = join(root, \"daemon.yaml\");\n const legacyStatePath = join(root, \"cloud-runtime.json\");\n const binaryPath = writeLegacyRuntime(root, \"other-tool.js\");\n const child = spawn(process.execPath, [binaryPath, \"connect\", \"--config\", configPath]);\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(child.pid);\n writeFileSync(legacyStatePath, `${JSON.stringify({ pid: child.pid, projects: [root] })}\\n`);\n\n assert.equal(await stopBackgroundRuntime(configPath), false);\n assert.equal(processIsRunning(child.pid), true);\n assert.equal(existsSync(legacyStatePath), true);\n});\n\ntest(\"legacy migration preserves config paths with spaces before short options\", async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-argv-legacy-\"));\n const configPath = join(root, \"custom runtime.yaml\");\n const legacyStatePath = join(root, \"cloud-runtime.json\");\n const binaryPath = writeLegacyRuntime(root, \"gsd-cloud.js\");\n const child = spawn(process.execPath, [\n binaryPath,\n \"connect\",\n \"--config\",\n configPath,\n \"-v\",\n \"--foreground\",\n ]);\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(child.pid);\n await waitForCondition(() => processIsRunning(child.pid!));\n writeFileSync(legacyStatePath, `${JSON.stringify({ pid: child.pid, projects: [root] })}\\n`);\n\n const status = backgroundRuntimeStatus(configPath);\n\n assert.equal(status.running, true);\n assert.equal(status.pid, child.pid);\n assert.equal(existsSync(runtimeStatePath(configPath)), true);\n assert.equal(existsSync(legacyStatePath), false);\n});\n\ntest(\"Windows command matching accepts quoted gsd-cloud.js paths\", () => {\n const configPath = \"/work/runtime/daemon.yaml\";\n const command = [\n '\"C:\\\\Program Files\\\\nodejs\\\\node.exe\"',\n '\"C:\\\\Program Files\\\\gsd-cloud\\\\gsd-cloud.js\"',\n \"connect\",\n \"--config\",\n `\"${configPath}\"`,\n ].join(\" \");\n\n assert.equal(commandLineMatchesRuntimeConfig(command, configPath, \"win32\"), true);\n});\n\ntest(\"command matching rejects gsd-cloud decoys before another launcher\", () => {\n const configPath = \"/work/runtime/daemon.yaml\";\n\n assert.equal(commandLineMatchesRuntimeConfig(\n `other-tool /tmp/gsd-cloud.js connect --config ${configPath}`,\n configPath,\n \"linux\",\n ), false);\n assert.equal(commandLineMatchesRuntimeConfig(\n `\"C:\\\\Tools\\\\other-tool.exe\" \"C:\\\\tmp\\\\gsd-cloud.js\" connect --config \"${configPath}\"`,\n configPath,\n \"win32\",\n ), false);\n assert.equal(commandLineMatchesRuntimeConfig(\n `/usr/bin/node /tmp/gsd-cloud.js --config ${configPath} connect --config /other.yaml`,\n configPath,\n \"linux\",\n ), false);\n assert.equal(commandLineMatchesRuntimeConfig(\n `/usr/bin/other /tmp/gsd-cloud.js connect --config ${configPath}`,\n configPath,\n \"darwin\",\n ), false);\n assert.equal(commandLineMatchesRuntimeConfig(\n `/usr/bin/node /usr/bin/other /tmp/gsd-cloud.js connect --config ${configPath}`,\n configPath,\n \"darwin\",\n ), false);\n});\n\ntest(\"command matching accepts a directly launched bare gsd-cloud executable\", () => {\n const configPath = \"/work/runtime/daemon.yaml\";\n\n assert.equal(commandLineMatchesRuntimeConfig(\n `gsd-cloud connect --config ${configPath}`,\n configPath,\n \"darwin\",\n ), true);\n assert.equal(commandLineMatchesRuntimeConfig(\n `\"/Applications/GSD Cloud/gsd-cloud\" connect --config ${configPath}`,\n configPath,\n \"darwin\",\n ), true);\n});\n\ntest(\"start lock atomically records PID and process identity\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-lock-owner-\"));\n const configPath = join(root, \"daemon.yaml\");\n const binaryPath = writeReadyRuntime(root, 500);\n const lockPath = runtimeArtifactPath(configPath, \"start.lock\");\n t.after(async () => {\n await stopBackgroundRuntime(configPath).catch(() => undefined);\n rmSync(root, { recursive: true, force: true });\n });\n\n const starting = startBackgroundRuntime({ binaryPath, configPath, projectDirs: [root] });\n await waitForCondition(() => existsSync(lockPath));\n\n const owner = JSON.parse(readFileSync(lockPath, \"utf8\")) as {\n pid?: number;\n process_start_identity?: string;\n };\n assert.equal(owner.pid, process.pid);\n assert.equal(typeof owner.process_start_identity, \"string\");\n assert.ok(owner.process_start_identity);\n\n await starting;\n});\n\ntest(\"start lock recovers immediately when its PID identity is stale\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-stale-lock-\"));\n const configPath = join(root, \"daemon.yaml\");\n const binaryPath = writeReadyRuntime(root);\n const lockPath = runtimeArtifactPath(configPath, \"start.lock\");\n writeFileSync(lockPath, `${JSON.stringify({\n pid: process.pid,\n process_start_identity: \"reused-process\",\n })}\\n`);\n t.after(async () => {\n await stopBackgroundRuntime(configPath).catch(() => undefined);\n rmSync(root, { recursive: true, force: true });\n });\n\n const starting = startBackgroundRuntime({ binaryPath, configPath, projectDirs: [root] });\n await new Promise<void>((resolveImmediate) => setImmediate(resolveImmediate));\n const owner = JSON.parse(readFileSync(lockPath, \"utf8\")) as {\n process_start_identity?: string;\n };\n\n assert.notEqual(owner.process_start_identity, \"reused-process\");\n await starting;\n});\n\ntest(\"start lock recovery never removes a replacement owner\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-replaced-lock-\"));\n const ownerConfigPath = join(root, \"owner.yaml\");\n const configPath = join(root, \"daemon.yaml\");\n const ownerLockPath = runtimeArtifactPath(ownerConfigPath, \"start.lock\");\n const lockPath = runtimeArtifactPath(configPath, \"start.lock\");\n const releaseOwner = await acquireRuntimeStartLock(ownerConfigPath);\n const replacementOwner = readFileSync(ownerLockPath, \"utf8\");\n releaseOwner();\n writeFileSync(lockPath, \"stale\");\n const old = new Date(0);\n utimesSync(lockPath, old, old);\n let release: (() => void) | undefined;\n t.after(async () => {\n rmSync(lockPath, { force: true });\n release ??= await acquiring.catch(() => undefined);\n release?.();\n rmSync(root, { recursive: true, force: true });\n });\n\n let replacementInstalled!: () => void;\n let replacementInode: bigint | undefined;\n const installed = new Promise<void>((resolve) => {\n replacementInstalled = resolve;\n });\n const acquiring = acquireRuntimeStartLock(configPath, () => {\n rmSync(lockPath);\n writeFileSync(lockPath, replacementOwner);\n replacementInode = statSync(lockPath, { bigint: true }).ino;\n replacementInstalled();\n });\n\n await installed;\n assert.equal(readFileSync(lockPath, \"utf8\"), replacementOwner);\n assert.equal(statSync(lockPath, { bigint: true }).ino, replacementInode);\n rmSync(lockPath);\n release = await acquiring;\n release();\n});\n\ntest(\"start lock recovery ignores an abandoned recovery claim\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-abandoned-recovery-\"));\n const configPath = join(root, \"daemon.yaml\");\n const lockPath = runtimeArtifactPath(configPath, \"start.lock\");\n const recoveryPath = `${lockPath}.recovery`;\n writeFileSync(lockPath, \"stale\");\n writeFileSync(recoveryPath, \"abandoned\");\n const old = new Date(0);\n utimesSync(lockPath, old, old);\n utimesSync(recoveryPath, old, old);\n let release: (() => void) | undefined;\n const acquiring = acquireRuntimeStartLock(configPath);\n t.after(async () => {\n rmSync(lockPath, { force: true });\n rmSync(recoveryPath, { force: true });\n release ??= await acquiring.catch(() => undefined);\n release?.();\n rmSync(root, { recursive: true, force: true });\n });\n\n release = await Promise.race([\n acquiring,\n new Promise<never>((_resolve, reject) => {\n setTimeout(() => reject(new Error(\"abandoned recovery claim blocked start\")), 500);\n }),\n ]);\n release();\n\n assert.equal(existsSync(lockPath), false);\n assert.equal(readFileSync(recoveryPath, \"utf8\"), \"abandoned\");\n});\n\ntest(\"start lock does not reclaim a live legacy owner by age\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-live-legacy-lock-\"));\n const configPath = join(root, \"daemon.yaml\");\n const binaryPath = writeReadyRuntime(root);\n const lockPath = runtimeArtifactPath(configPath, \"start.lock\");\n writeFileSync(lockPath, `${process.pid}\\n`);\n t.after(async () => {\n await stopBackgroundRuntime(configPath).catch(() => undefined);\n rmSync(root, { recursive: true, force: true });\n });\n\n const starting = startBackgroundRuntime({ binaryPath, configPath, projectDirs: [root] });\n await new Promise((resolveDelay) => setTimeout(resolveDelay, 1_200));\n\n assert.equal(readFileSync(lockPath, \"utf8\"), `${process.pid}\\n`);\n rmSync(lockPath);\n await starting;\n});\n\ntest(\"start lock preserves an aged legacy owner running the same config\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-live-runtime-lock-\"));\n const configPath = join(root, \"daemon.yaml\");\n const binaryPath = writeReadyRuntime(root);\n const legacyBinaryPath = writeLegacyRuntime(root, \"gsd-cloud\");\n const lockPath = runtimeArtifactPath(configPath, \"start.lock\");\n const owner = spawn(process.execPath, [legacyBinaryPath, \"connect\", \"--config\", configPath]);\n t.after(async () => {\n owner.kill(\"SIGKILL\");\n await stopBackgroundRuntime(configPath).catch(() => undefined);\n rmSync(root, { recursive: true, force: true });\n });\n\n assert.ok(owner.pid);\n await waitForCondition(() => processIsRunning(owner.pid!));\n writeFileSync(lockPath, `${owner.pid}\\n`);\n const old = new Date(0);\n utimesSync(lockPath, old, old);\n\n const starting = startBackgroundRuntime({ binaryPath, configPath, projectDirs: [root] });\n await new Promise((resolveDelay) => setTimeout(resolveDelay, 200));\n\n assert.equal(readFileSync(lockPath, \"utf8\"), `${owner.pid}\\n`);\n rmSync(lockPath);\n await starting;\n});\n\nfor (const staleOwner of [\"\", \"not-json\", `${process.pid}\\n`]) {\n test(`start lock recovers stale legacy owner ${JSON.stringify(staleOwner)}`, { timeout: 2_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-stale-legacy-lock-\"));\n const configPath = join(root, \"daemon.yaml\");\n const lockPath = runtimeArtifactPath(configPath, \"start.lock\");\n writeFileSync(lockPath, staleOwner);\n const old = new Date(0);\n utimesSync(lockPath, old, old);\n let release: (() => void) | undefined;\n const acquiring = acquireRuntimeStartLock(configPath);\n t.after(async () => {\n if (!release) {\n rmSync(lockPath, { force: true });\n release = await acquiring.catch(() => undefined);\n }\n release?.();\n rmSync(root, { recursive: true, force: true });\n });\n\n release = await Promise.race([\n acquiring,\n new Promise<never>((_resolve, reject) => {\n setTimeout(() => reject(new Error(\"stale start lock was not recovered promptly\")), 500);\n }),\n ]);\n release();\n\n assert.equal(existsSync(lockPath), false);\n });\n}\n\ntest(\"stop waits for the detached runtime to exit before removing its state\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-stop-\"));\n const configPath = join(root, \"daemon.yaml\");\n const statePath = join(root, \"cloud-runtime.json\");\n const binaryPath = join(root, \"gsd-cloud.js\");\n writeFileSync(binaryPath, [\n \"process.on('SIGTERM',()=>setTimeout(()=>process.exit(0),200));\",\n \"process.send?.('ready');\",\n \"setInterval(()=>{},1000);\",\n ].join(\"\\n\"));\n const child = spawn(process.execPath, [\n binaryPath,\n \"_run\",\n \"--config\",\n configPath,\n ], { stdio: [\"ignore\", \"ignore\", \"ignore\", \"ipc\"] });\n t.after(() => {\n child.kill(\"SIGKILL\");\n rmSync(root, { recursive: true, force: true });\n });\n\n await new Promise<void>((resolve, reject) => {\n child.once(\"error\", reject);\n child.once(\"message\", () => resolve());\n });\n assert.ok(child.pid);\n writeRuntimeState(configPath, child.pid, [root]);\n\n const startedAt = Date.now();\n assert.equal(await stopBackgroundRuntime(configPath), true);\n\n assert.ok(Date.now() - startedAt >= 150);\n assert.equal(existsSync(statePath), false);\n});\n\ntest(\"background startup terminates its child when state registration fails\", { timeout: 5_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-registration-failure-\"));\n const configPath = join(root, \"daemon.yaml\");\n const pidPath = join(root, \"runtime-pid.txt\");\n const binaryPath = join(root, \"runtime.mjs\");\n writeFileSync(binaryPath, [\n 'import { writeFileSync } from \"node:fs\";',\n `writeFileSync(${JSON.stringify(pidPath)}, String(process.pid));`,\n 'process.on(\"SIGTERM\", () => process.exit(0));',\n 'setInterval(() => undefined, 1_000);',\n ].join(\"\\n\"));\n mkdirSync(runtimeStatePath(configPath));\n t.after(() => {\n if (existsSync(pidPath)) {\n const pid = Number.parseInt(readFileSync(pidPath, \"utf8\"), 10);\n if (processIsRunning(pid)) process.kill(pid, \"SIGKILL\");\n }\n rmSync(root, { recursive: true, force: true });\n });\n\n await assert.rejects(\n startBackgroundRuntime({ binaryPath, configPath, projectDirs: [root] }),\n );\n await new Promise((resolve) => setTimeout(resolve, 250));\n if (existsSync(pidPath)) {\n const pid = Number.parseInt(readFileSync(pidPath, \"utf8\"), 10);\n await waitForCondition(() => !processIsRunning(pid));\n assert.equal(processIsRunning(pid), false);\n }\n});\n\ntest(\"background startup force-stops its child when identity registration fails\", { timeout: 8_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-registration-force-stop-\"));\n const configPath = join(root, \"daemon.yaml\");\n const pidPath = join(root, \"runtime-pid.txt\");\n const binaryPath = join(root, \"runtime.mjs\");\n writeFileSync(binaryPath, [\n 'import { writeFileSync } from \"node:fs\";',\n 'process.on(\"SIGTERM\", () => undefined);',\n `writeFileSync(${JSON.stringify(pidPath)}, String(process.pid));`,\n 'setInterval(() => undefined, 1_000);',\n ].join(\"\\n\"));\n mkdirSync(runtimeStatePath(configPath));\n t.after(() => {\n if (existsSync(pidPath)) {\n const pid = Number.parseInt(readFileSync(pidPath, \"utf8\"), 10);\n if (processIsRunning(pid)) process.kill(pid, \"SIGKILL\");\n }\n rmSync(root, { recursive: true, force: true });\n });\n\n await assert.rejects(\n startBackgroundRuntime({\n binaryPath,\n configPath,\n projectDirs: [root],\n processIdentityReader: () => {\n const deadline = Date.now() + 1_000;\n while (!existsSync(pidPath) && Date.now() < deadline) {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 10);\n }\n return null;\n },\n }),\n );\n if (existsSync(pidPath)) {\n const pid = Number.parseInt(readFileSync(pidPath, \"utf8\"), 10);\n await waitForCondition(() => !processIsRunning(pid), 7_000);\n assert.equal(processIsRunning(pid), false);\n }\n});\n\ntest(\"concurrent starts serialize and leave only the newest runtime running\", { timeout: 15_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-concurrent-start-\"));\n const configPath = join(root, \"daemon.yaml\");\n const binaryPath = writeReadyRuntime(root);\n t.after(async () => {\n await stopBackgroundRuntime(configPath).catch(() => undefined);\n rmSync(root, { recursive: true, force: true });\n });\n\n const [first, second] = await Promise.all([\n startBackgroundRuntime({ binaryPath, configPath, projectDirs: [root] }),\n startBackgroundRuntime({ binaryPath, configPath, projectDirs: [root] }),\n ]);\n\n assert.notEqual(first.pid, second.pid);\n assert.ok(first.pid);\n assert.equal(processIsRunning(first.pid), false);\n assert.equal(backgroundRuntimeStatus(configPath).pid, second.pid);\n});\n\ntest(\"verbose background starts forward the flag to the runtime child\", { timeout: 10_000 }, async (t) => {\n const root = mkdtempSync(join(tmpdir(), \"gsd-cloud-verbose-start-\"));\n const configPath = join(root, \"daemon.yaml\");\n const binaryPath = writeReadyRuntime(root);\n t.after(async () => {\n await stopBackgroundRuntime(configPath).catch(() => undefined);\n rmSync(root, { recursive: true, force: true });\n });\n\n await startBackgroundRuntime({\n binaryPath,\n configPath,\n projectDirs: [root],\n verbose: true,\n });\n\n const args = JSON.parse(readFileSync(join(root, \"runtime-args.json\"), \"utf8\")) as string[];\n assert.ok(args.includes(\"--verbose\"));\n});\n\nfunction writeReadyRuntime(root: string, readyDelayMs = 0): string {\n const binaryPath = join(root, \"gsd-cloud.js\");\n writeFileSync(binaryPath, [\n 'import { writeFileSync } from \"node:fs\";',\n `writeFileSync(${JSON.stringify(join(root, \"runtime-args.json\"))}, JSON.stringify(process.argv.slice(2)));`,\n 'process.on(\"SIGTERM\", () => process.exit(0));',\n `setTimeout(() => process.send?.({ type: \"ready\" }), ${readyDelayMs});`,\n 'setInterval(() => undefined, 1_000);',\n ].join(\"\\n\"));\n return binaryPath;\n}\n\nfunction writeLegacyRuntime(root: string, name: string): string {\n const binaryPath = join(root, name);\n writeFileSync(binaryPath, [\n \"process.on('SIGTERM', () => process.exit(0));\",\n \"setInterval(() => undefined, 1_000);\",\n ].join(\"\\n\"));\n return binaryPath;\n}\n\nfunction processIsRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function waitForCondition(condition: () => boolean, timeoutMs = 2_000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n while (!condition()) {\n if (Date.now() >= deadline) throw new Error(\"timed out waiting for test condition\");\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n}\n"]}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { AdvertisedProject } from "./executors/executor.js";
|
|
2
|
+
export type RuntimeConnectionState = "connecting" | "connected" | "reconnecting" | "error" | "stopped";
|
|
3
|
+
export type RuntimeProjectState = "idle" | "active" | "error";
|
|
4
|
+
export type RuntimeRequestOutcome = "success" | "error" | "cancelled";
|
|
5
|
+
export interface RuntimeProjectTelemetry {
|
|
6
|
+
alias: string;
|
|
7
|
+
path: string;
|
|
8
|
+
repo_identity: string;
|
|
9
|
+
remote_label?: string;
|
|
10
|
+
state: RuntimeProjectState;
|
|
11
|
+
active_requests: number;
|
|
12
|
+
active_tools: string[];
|
|
13
|
+
request_count: number;
|
|
14
|
+
error_count: number;
|
|
15
|
+
received_bytes: number;
|
|
16
|
+
sent_bytes: number;
|
|
17
|
+
last_tool: string | null;
|
|
18
|
+
last_activity_at: string | null;
|
|
19
|
+
}
|
|
20
|
+
export interface RuntimeActivityTelemetry {
|
|
21
|
+
request_id: string;
|
|
22
|
+
project_alias?: string;
|
|
23
|
+
project_path?: string;
|
|
24
|
+
tool_name: string;
|
|
25
|
+
outcome: RuntimeRequestOutcome;
|
|
26
|
+
duration_ms: number;
|
|
27
|
+
at: string;
|
|
28
|
+
error?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface RuntimeTelemetryStatus {
|
|
31
|
+
version: 1;
|
|
32
|
+
pid: number;
|
|
33
|
+
state: RuntimeConnectionState;
|
|
34
|
+
gateway_url: string;
|
|
35
|
+
runtime_id?: string;
|
|
36
|
+
runtime_name?: string;
|
|
37
|
+
started_at: string;
|
|
38
|
+
connected_at: string | null;
|
|
39
|
+
updated_at: string;
|
|
40
|
+
last_error: string | null;
|
|
41
|
+
connection_attempts: number;
|
|
42
|
+
reconnects: number;
|
|
43
|
+
received_messages: number;
|
|
44
|
+
sent_messages: number;
|
|
45
|
+
received_bytes: number;
|
|
46
|
+
sent_bytes: number;
|
|
47
|
+
active_requests: number;
|
|
48
|
+
projects: RuntimeProjectTelemetry[];
|
|
49
|
+
recent_activity: RuntimeActivityTelemetry[];
|
|
50
|
+
}
|
|
51
|
+
export interface RuntimeRequestStarted {
|
|
52
|
+
requestId: string;
|
|
53
|
+
projectAlias?: string;
|
|
54
|
+
projectPath?: string;
|
|
55
|
+
toolName: string;
|
|
56
|
+
receivedBytes: number;
|
|
57
|
+
}
|
|
58
|
+
export interface RuntimeRequestFinished {
|
|
59
|
+
requestId: string;
|
|
60
|
+
projectAlias?: string;
|
|
61
|
+
projectPath?: string;
|
|
62
|
+
toolName: string;
|
|
63
|
+
durationMs: number;
|
|
64
|
+
outcome: RuntimeRequestOutcome;
|
|
65
|
+
error?: string;
|
|
66
|
+
}
|
|
67
|
+
export interface RuntimeTelemetryReporter {
|
|
68
|
+
connecting(): void;
|
|
69
|
+
connected(): void;
|
|
70
|
+
disconnected(error?: string): void;
|
|
71
|
+
socketError(error: string): void;
|
|
72
|
+
received(text: string): void;
|
|
73
|
+
sent(text: string, projectPath?: string): void;
|
|
74
|
+
projectsAdvertised(projects: AdvertisedProject[]): void;
|
|
75
|
+
requestStarted(request: RuntimeRequestStarted): void;
|
|
76
|
+
requestFinished(request: RuntimeRequestFinished): void;
|
|
77
|
+
stopped(): void;
|
|
78
|
+
failed?(): void;
|
|
79
|
+
flush?(): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
interface RuntimeTelemetryMetadata {
|
|
82
|
+
gatewayUrl: string;
|
|
83
|
+
runtimeId?: string;
|
|
84
|
+
runtimeName?: string;
|
|
85
|
+
}
|
|
86
|
+
export declare const noopRuntimeTelemetry: RuntimeTelemetryReporter;
|
|
87
|
+
export declare class RuntimeTelemetryStore implements RuntimeTelemetryReporter {
|
|
88
|
+
private readonly path;
|
|
89
|
+
private readonly activeRequests;
|
|
90
|
+
private status;
|
|
91
|
+
private livenessTimer;
|
|
92
|
+
private persistTimer;
|
|
93
|
+
private persistPromise;
|
|
94
|
+
constructor(configPath: string, metadata: RuntimeTelemetryMetadata);
|
|
95
|
+
connecting(): void;
|
|
96
|
+
connected(): void;
|
|
97
|
+
disconnected(error?: string): void;
|
|
98
|
+
socketError(error: string): void;
|
|
99
|
+
received(text: string): void;
|
|
100
|
+
sent(text: string, projectPath?: string): void;
|
|
101
|
+
projectsAdvertised(projects: AdvertisedProject[]): void;
|
|
102
|
+
requestStarted(request: RuntimeRequestStarted): void;
|
|
103
|
+
requestFinished(request: RuntimeRequestFinished): void;
|
|
104
|
+
stopped(): void;
|
|
105
|
+
failed(): void;
|
|
106
|
+
flush(): Promise<void>;
|
|
107
|
+
private findProject;
|
|
108
|
+
private activeToolsForProject;
|
|
109
|
+
private persist;
|
|
110
|
+
private enqueuePersist;
|
|
111
|
+
private writeSnapshot;
|
|
112
|
+
}
|
|
113
|
+
export declare function readRuntimeTelemetry(configPath: string): RuntimeTelemetryStatus | null;
|
|
114
|
+
export declare function runtimeTelemetryPath(configPath: string): string;
|
|
115
|
+
export declare function clearRuntimeTelemetry(configPath: string): void;
|
|
116
|
+
export {};
|
|
117
|
+
//# sourceMappingURL=runtime-telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-telemetry.d.ts","sourceRoot":"","sources":["../src/runtime-telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// Project/App: Open GSD
|
|
2
|
+
// File Purpose: Persist token-free cloud runtime status and traffic counters for local monitors.
|
|
3
|
+
import { readFileSync, unlinkSync } from "node:fs";
|
|
4
|
+
import { chmod, mkdir, rename, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import { dirname } from "node:path";
|
|
6
|
+
import { runtimeArtifactPath } from "./runtime-artifacts.js";
|
|
7
|
+
export const noopRuntimeTelemetry = {
|
|
8
|
+
connecting() { },
|
|
9
|
+
connected() { },
|
|
10
|
+
disconnected() { },
|
|
11
|
+
socketError() { },
|
|
12
|
+
received() { },
|
|
13
|
+
sent() { },
|
|
14
|
+
projectsAdvertised() { },
|
|
15
|
+
requestStarted() { },
|
|
16
|
+
requestFinished() { },
|
|
17
|
+
stopped() { },
|
|
18
|
+
failed() { },
|
|
19
|
+
};
|
|
20
|
+
export class RuntimeTelemetryStore {
|
|
21
|
+
path;
|
|
22
|
+
activeRequests = new Map();
|
|
23
|
+
status;
|
|
24
|
+
livenessTimer;
|
|
25
|
+
persistTimer;
|
|
26
|
+
persistPromise = Promise.resolve();
|
|
27
|
+
constructor(configPath, metadata) {
|
|
28
|
+
const now = new Date().toISOString();
|
|
29
|
+
this.path = runtimeTelemetryPath(configPath);
|
|
30
|
+
this.status = {
|
|
31
|
+
version: 1,
|
|
32
|
+
pid: process.pid,
|
|
33
|
+
state: "connecting",
|
|
34
|
+
gateway_url: credentialFreeGatewayLabel(metadata.gatewayUrl),
|
|
35
|
+
...(metadata.runtimeId ? { runtime_id: metadata.runtimeId } : {}),
|
|
36
|
+
...(metadata.runtimeName ? { runtime_name: metadata.runtimeName } : {}),
|
|
37
|
+
started_at: now,
|
|
38
|
+
connected_at: null,
|
|
39
|
+
updated_at: now,
|
|
40
|
+
last_error: null,
|
|
41
|
+
connection_attempts: 0,
|
|
42
|
+
reconnects: 0,
|
|
43
|
+
received_messages: 0,
|
|
44
|
+
sent_messages: 0,
|
|
45
|
+
received_bytes: 0,
|
|
46
|
+
sent_bytes: 0,
|
|
47
|
+
active_requests: 0,
|
|
48
|
+
projects: [],
|
|
49
|
+
recent_activity: [],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
connecting() {
|
|
53
|
+
if (!this.livenessTimer) {
|
|
54
|
+
this.livenessTimer = setInterval(() => this.persist(), 1_000);
|
|
55
|
+
this.livenessTimer.unref();
|
|
56
|
+
}
|
|
57
|
+
this.status.state = this.status.connection_attempts === 0 ? "connecting" : "reconnecting";
|
|
58
|
+
this.status.connection_attempts += 1;
|
|
59
|
+
this.persist();
|
|
60
|
+
}
|
|
61
|
+
connected() {
|
|
62
|
+
this.status.state = "connected";
|
|
63
|
+
this.status.connected_at = new Date().toISOString();
|
|
64
|
+
this.status.last_error = null;
|
|
65
|
+
this.persist();
|
|
66
|
+
}
|
|
67
|
+
disconnected(error) {
|
|
68
|
+
if (this.status.connected_at && this.status.state !== "reconnecting") {
|
|
69
|
+
this.status.reconnects += 1;
|
|
70
|
+
}
|
|
71
|
+
this.status.state = "reconnecting";
|
|
72
|
+
this.status.last_error = error ?? this.status.last_error ?? "connection closed";
|
|
73
|
+
this.persist();
|
|
74
|
+
}
|
|
75
|
+
socketError(error) {
|
|
76
|
+
this.status.state = "error";
|
|
77
|
+
this.status.last_error = error;
|
|
78
|
+
this.persist();
|
|
79
|
+
}
|
|
80
|
+
received(text) {
|
|
81
|
+
this.status.received_messages += 1;
|
|
82
|
+
this.status.received_bytes += Buffer.byteLength(text);
|
|
83
|
+
this.persist();
|
|
84
|
+
}
|
|
85
|
+
sent(text, projectPath) {
|
|
86
|
+
this.status.sent_messages += 1;
|
|
87
|
+
const bytes = Buffer.byteLength(text);
|
|
88
|
+
this.status.sent_bytes += bytes;
|
|
89
|
+
const project = projectPath ? this.findProject(projectPath) : undefined;
|
|
90
|
+
if (project)
|
|
91
|
+
project.sent_bytes += bytes;
|
|
92
|
+
this.persist();
|
|
93
|
+
}
|
|
94
|
+
projectsAdvertised(projects) {
|
|
95
|
+
const existingProjects = new Map(this.status.projects.map((project) => [project.path, project]));
|
|
96
|
+
this.status.projects = projects.map((project) => {
|
|
97
|
+
const existing = existingProjects.get(project.path);
|
|
98
|
+
const remoteLabel = project.remoteLabel
|
|
99
|
+
? credentialFreeRemoteLabel(project.remoteLabel)
|
|
100
|
+
: undefined;
|
|
101
|
+
return {
|
|
102
|
+
alias: project.alias,
|
|
103
|
+
path: project.path,
|
|
104
|
+
repo_identity: project.repoIdentity,
|
|
105
|
+
...(remoteLabel ? { remote_label: remoteLabel } : {}),
|
|
106
|
+
state: existing?.state ?? "idle",
|
|
107
|
+
active_requests: existing?.active_requests ?? 0,
|
|
108
|
+
active_tools: existing?.active_tools ?? [],
|
|
109
|
+
request_count: existing?.request_count ?? 0,
|
|
110
|
+
error_count: existing?.error_count ?? 0,
|
|
111
|
+
received_bytes: existing?.received_bytes ?? 0,
|
|
112
|
+
sent_bytes: existing?.sent_bytes ?? 0,
|
|
113
|
+
last_tool: existing?.last_tool ?? null,
|
|
114
|
+
last_activity_at: existing?.last_activity_at ?? null,
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
this.persist();
|
|
118
|
+
}
|
|
119
|
+
requestStarted(request) {
|
|
120
|
+
this.status.active_requests += 1;
|
|
121
|
+
const project = this.findProject(request.projectPath, request.projectAlias);
|
|
122
|
+
if (project) {
|
|
123
|
+
this.activeRequests.set(request.requestId, {
|
|
124
|
+
projectPath: project.path,
|
|
125
|
+
toolName: request.toolName,
|
|
126
|
+
});
|
|
127
|
+
project.state = "active";
|
|
128
|
+
project.active_requests += 1;
|
|
129
|
+
project.active_tools = this.activeToolsForProject(project.path);
|
|
130
|
+
project.received_bytes += request.receivedBytes;
|
|
131
|
+
project.last_tool = request.toolName;
|
|
132
|
+
project.last_activity_at = new Date().toISOString();
|
|
133
|
+
}
|
|
134
|
+
this.persist();
|
|
135
|
+
}
|
|
136
|
+
requestFinished(request) {
|
|
137
|
+
this.status.active_requests = Math.max(0, this.status.active_requests - 1);
|
|
138
|
+
const now = new Date().toISOString();
|
|
139
|
+
const project = this.findProject(request.projectPath, request.projectAlias);
|
|
140
|
+
this.activeRequests.delete(request.requestId);
|
|
141
|
+
if (project) {
|
|
142
|
+
project.active_requests = Math.max(0, project.active_requests - 1);
|
|
143
|
+
project.active_tools = this.activeToolsForProject(project.path);
|
|
144
|
+
project.request_count += 1;
|
|
145
|
+
project.last_tool = request.toolName;
|
|
146
|
+
project.last_activity_at = now;
|
|
147
|
+
if (request.outcome === "error")
|
|
148
|
+
project.error_count += 1;
|
|
149
|
+
if (request.outcome === "error") {
|
|
150
|
+
project.state = "error";
|
|
151
|
+
}
|
|
152
|
+
else if (project.active_requests > 0) {
|
|
153
|
+
project.state = "active";
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
project.state = "idle";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
this.status.recent_activity.push({
|
|
160
|
+
request_id: request.requestId,
|
|
161
|
+
...(request.projectAlias ? { project_alias: request.projectAlias } : {}),
|
|
162
|
+
...(request.projectPath ? { project_path: request.projectPath } : {}),
|
|
163
|
+
tool_name: request.toolName,
|
|
164
|
+
outcome: request.outcome,
|
|
165
|
+
duration_ms: request.durationMs,
|
|
166
|
+
at: now,
|
|
167
|
+
...(request.error ? { error: request.error } : {}),
|
|
168
|
+
});
|
|
169
|
+
if (this.status.recent_activity.length > 50) {
|
|
170
|
+
this.status.recent_activity.splice(0, this.status.recent_activity.length - 50);
|
|
171
|
+
}
|
|
172
|
+
this.persist();
|
|
173
|
+
}
|
|
174
|
+
stopped() {
|
|
175
|
+
if (this.livenessTimer)
|
|
176
|
+
clearInterval(this.livenessTimer);
|
|
177
|
+
this.livenessTimer = undefined;
|
|
178
|
+
this.status.state = "stopped";
|
|
179
|
+
this.status.active_requests = 0;
|
|
180
|
+
this.activeRequests.clear();
|
|
181
|
+
for (const project of this.status.projects) {
|
|
182
|
+
project.active_requests = 0;
|
|
183
|
+
project.active_tools = [];
|
|
184
|
+
project.state = "idle";
|
|
185
|
+
}
|
|
186
|
+
void this.flush();
|
|
187
|
+
}
|
|
188
|
+
failed() {
|
|
189
|
+
if (this.livenessTimer)
|
|
190
|
+
clearInterval(this.livenessTimer);
|
|
191
|
+
this.livenessTimer = undefined;
|
|
192
|
+
}
|
|
193
|
+
async flush() {
|
|
194
|
+
if (this.persistTimer) {
|
|
195
|
+
clearTimeout(this.persistTimer);
|
|
196
|
+
this.persistTimer = undefined;
|
|
197
|
+
}
|
|
198
|
+
this.enqueuePersist();
|
|
199
|
+
await this.persistPromise;
|
|
200
|
+
}
|
|
201
|
+
findProject(path, alias) {
|
|
202
|
+
if (path)
|
|
203
|
+
return this.status.projects.find((project) => project.path === path);
|
|
204
|
+
if (alias)
|
|
205
|
+
return this.status.projects.find((project) => project.alias === alias);
|
|
206
|
+
if (this.status.projects.length === 1)
|
|
207
|
+
return this.status.projects[0];
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
activeToolsForProject(projectPath) {
|
|
211
|
+
return [...this.activeRequests.values()]
|
|
212
|
+
.filter((request) => request.projectPath === projectPath)
|
|
213
|
+
.map((request) => request.toolName);
|
|
214
|
+
}
|
|
215
|
+
persist() {
|
|
216
|
+
this.status.updated_at = new Date().toISOString();
|
|
217
|
+
if (this.persistTimer)
|
|
218
|
+
return;
|
|
219
|
+
this.persistTimer = setTimeout(() => {
|
|
220
|
+
this.persistTimer = undefined;
|
|
221
|
+
this.enqueuePersist();
|
|
222
|
+
}, 25);
|
|
223
|
+
this.persistTimer.unref();
|
|
224
|
+
}
|
|
225
|
+
enqueuePersist() {
|
|
226
|
+
this.status.updated_at = new Date().toISOString();
|
|
227
|
+
const snapshot = `${JSON.stringify(this.status, null, 2)}\n`;
|
|
228
|
+
this.persistPromise = this.persistPromise.then(() => this.writeSnapshot(snapshot));
|
|
229
|
+
}
|
|
230
|
+
async writeSnapshot(snapshot) {
|
|
231
|
+
const temporaryPath = `${this.path}.${process.pid}.tmp`;
|
|
232
|
+
try {
|
|
233
|
+
await mkdir(dirname(this.path), { recursive: true });
|
|
234
|
+
await writeFile(temporaryPath, snapshot, { encoding: "utf8", mode: 0o600 });
|
|
235
|
+
await chmod(temporaryPath, 0o600);
|
|
236
|
+
await rename(temporaryPath, this.path);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
await rm(temporaryPath, { force: true }).catch(() => undefined);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
export function readRuntimeTelemetry(configPath) {
|
|
244
|
+
try {
|
|
245
|
+
const value = JSON.parse(readFileSync(runtimeTelemetryPath(configPath), "utf8"));
|
|
246
|
+
return value.version === 1 ? value : null;
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
export function runtimeTelemetryPath(configPath) {
|
|
253
|
+
return runtimeArtifactPath(configPath, "status");
|
|
254
|
+
}
|
|
255
|
+
export function clearRuntimeTelemetry(configPath) {
|
|
256
|
+
try {
|
|
257
|
+
unlinkSync(runtimeTelemetryPath(configPath));
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
if (error.code !== "ENOENT")
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function credentialFreeRemoteLabel(remoteLabel) {
|
|
265
|
+
try {
|
|
266
|
+
const url = new URL(remoteLabel);
|
|
267
|
+
url.username = "";
|
|
268
|
+
url.password = "";
|
|
269
|
+
url.search = "";
|
|
270
|
+
url.hash = "";
|
|
271
|
+
return url.toString();
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
return remoteLabel
|
|
275
|
+
.replace(/^[^/@]+@([^:]+):/, "$1:")
|
|
276
|
+
.replace(/[?#].*$/, "");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
function credentialFreeGatewayLabel(gatewayUrl) {
|
|
280
|
+
try {
|
|
281
|
+
const url = new URL(gatewayUrl);
|
|
282
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
283
|
+
return "invalid gateway";
|
|
284
|
+
const path = url.pathname === "/" ? "" : url.pathname;
|
|
285
|
+
return `${url.protocol}//${url.host}${path}`;
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
return "invalid gateway";
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=runtime-telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-telemetry.js","sourceRoot":"","sources":["../src/runtime-telemetry.ts"],"names":[],"mappings":"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","sourcesContent":["// Project/App: Open GSD\n// File Purpose: Persist token-free cloud runtime status and traffic counters for local monitors.\nimport { readFileSync, unlinkSync } from \"node:fs\";\nimport { chmod, mkdir, rename, rm, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { AdvertisedProject } from \"./executors/executor.js\";\nimport { runtimeArtifactPath } from \"./runtime-artifacts.js\";\n\nexport type RuntimeConnectionState = \"connecting\" | \"connected\" | \"reconnecting\" | \"error\" | \"stopped\";\nexport type RuntimeProjectState = \"idle\" | \"active\" | \"error\";\nexport type RuntimeRequestOutcome = \"success\" | \"error\" | \"cancelled\";\n\nexport interface RuntimeProjectTelemetry {\n alias: string;\n path: string;\n repo_identity: string;\n remote_label?: string;\n state: RuntimeProjectState;\n active_requests: number;\n active_tools: string[];\n request_count: number;\n error_count: number;\n received_bytes: number;\n sent_bytes: number;\n last_tool: string | null;\n last_activity_at: string | null;\n}\n\nexport interface RuntimeActivityTelemetry {\n request_id: string;\n project_alias?: string;\n project_path?: string;\n tool_name: string;\n outcome: RuntimeRequestOutcome;\n duration_ms: number;\n at: string;\n error?: string;\n}\n\nexport interface RuntimeTelemetryStatus {\n version: 1;\n pid: number;\n state: RuntimeConnectionState;\n gateway_url: string;\n runtime_id?: string;\n runtime_name?: string;\n started_at: string;\n connected_at: string | null;\n updated_at: string;\n last_error: string | null;\n connection_attempts: number;\n reconnects: number;\n received_messages: number;\n sent_messages: number;\n received_bytes: number;\n sent_bytes: number;\n active_requests: number;\n projects: RuntimeProjectTelemetry[];\n recent_activity: RuntimeActivityTelemetry[];\n}\n\nexport interface RuntimeRequestStarted {\n requestId: string;\n projectAlias?: string;\n projectPath?: string;\n toolName: string;\n receivedBytes: number;\n}\n\nexport interface RuntimeRequestFinished {\n requestId: string;\n projectAlias?: string;\n projectPath?: string;\n toolName: string;\n durationMs: number;\n outcome: RuntimeRequestOutcome;\n error?: string;\n}\n\nexport interface RuntimeTelemetryReporter {\n connecting(): void;\n connected(): void;\n disconnected(error?: string): void;\n socketError(error: string): void;\n received(text: string): void;\n sent(text: string, projectPath?: string): void;\n projectsAdvertised(projects: AdvertisedProject[]): void;\n requestStarted(request: RuntimeRequestStarted): void;\n requestFinished(request: RuntimeRequestFinished): void;\n stopped(): void;\n failed?(): void;\n flush?(): Promise<void>;\n}\n\ninterface RuntimeTelemetryMetadata {\n gatewayUrl: string;\n runtimeId?: string;\n runtimeName?: string;\n}\n\nexport const noopRuntimeTelemetry: RuntimeTelemetryReporter = {\n connecting(): void {},\n connected(): void {},\n disconnected(): void {},\n socketError(): void {},\n received(): void {},\n sent(): void {},\n projectsAdvertised(): void {},\n requestStarted(): void {},\n requestFinished(): void {},\n stopped(): void {},\n failed(): void {},\n};\n\nexport class RuntimeTelemetryStore implements RuntimeTelemetryReporter {\n private readonly path: string;\n private readonly activeRequests = new Map<string, { projectPath: string; toolName: string }>();\n private status: RuntimeTelemetryStatus;\n private livenessTimer: ReturnType<typeof setInterval> | undefined;\n private persistTimer: ReturnType<typeof setTimeout> | undefined;\n private persistPromise = Promise.resolve();\n\n constructor(configPath: string, metadata: RuntimeTelemetryMetadata) {\n const now = new Date().toISOString();\n this.path = runtimeTelemetryPath(configPath);\n this.status = {\n version: 1,\n pid: process.pid,\n state: \"connecting\",\n gateway_url: credentialFreeGatewayLabel(metadata.gatewayUrl),\n ...(metadata.runtimeId ? { runtime_id: metadata.runtimeId } : {}),\n ...(metadata.runtimeName ? { runtime_name: metadata.runtimeName } : {}),\n started_at: now,\n connected_at: null,\n updated_at: now,\n last_error: null,\n connection_attempts: 0,\n reconnects: 0,\n received_messages: 0,\n sent_messages: 0,\n received_bytes: 0,\n sent_bytes: 0,\n active_requests: 0,\n projects: [],\n recent_activity: [],\n };\n }\n\n connecting(): void {\n if (!this.livenessTimer) {\n this.livenessTimer = setInterval(() => this.persist(), 1_000);\n this.livenessTimer.unref();\n }\n this.status.state = this.status.connection_attempts === 0 ? \"connecting\" : \"reconnecting\";\n this.status.connection_attempts += 1;\n this.persist();\n }\n\n connected(): void {\n this.status.state = \"connected\";\n this.status.connected_at = new Date().toISOString();\n this.status.last_error = null;\n this.persist();\n }\n\n disconnected(error?: string): void {\n if (this.status.connected_at && this.status.state !== \"reconnecting\") {\n this.status.reconnects += 1;\n }\n this.status.state = \"reconnecting\";\n this.status.last_error = error ?? this.status.last_error ?? \"connection closed\";\n this.persist();\n }\n\n socketError(error: string): void {\n this.status.state = \"error\";\n this.status.last_error = error;\n this.persist();\n }\n\n received(text: string): void {\n this.status.received_messages += 1;\n this.status.received_bytes += Buffer.byteLength(text);\n this.persist();\n }\n\n sent(text: string, projectPath?: string): void {\n this.status.sent_messages += 1;\n const bytes = Buffer.byteLength(text);\n this.status.sent_bytes += bytes;\n const project = projectPath ? this.findProject(projectPath) : undefined;\n if (project) project.sent_bytes += bytes;\n this.persist();\n }\n\n projectsAdvertised(projects: AdvertisedProject[]): void {\n const existingProjects = new Map(\n this.status.projects.map((project) => [project.path, project]),\n );\n this.status.projects = projects.map((project) => {\n const existing = existingProjects.get(project.path);\n const remoteLabel = project.remoteLabel\n ? credentialFreeRemoteLabel(project.remoteLabel)\n : undefined;\n return {\n alias: project.alias,\n path: project.path,\n repo_identity: project.repoIdentity,\n ...(remoteLabel ? { remote_label: remoteLabel } : {}),\n state: existing?.state ?? \"idle\",\n active_requests: existing?.active_requests ?? 0,\n active_tools: existing?.active_tools ?? [],\n request_count: existing?.request_count ?? 0,\n error_count: existing?.error_count ?? 0,\n received_bytes: existing?.received_bytes ?? 0,\n sent_bytes: existing?.sent_bytes ?? 0,\n last_tool: existing?.last_tool ?? null,\n last_activity_at: existing?.last_activity_at ?? null,\n };\n });\n this.persist();\n }\n\n requestStarted(request: RuntimeRequestStarted): void {\n this.status.active_requests += 1;\n const project = this.findProject(request.projectPath, request.projectAlias);\n if (project) {\n this.activeRequests.set(request.requestId, {\n projectPath: project.path,\n toolName: request.toolName,\n });\n project.state = \"active\";\n project.active_requests += 1;\n project.active_tools = this.activeToolsForProject(project.path);\n project.received_bytes += request.receivedBytes;\n project.last_tool = request.toolName;\n project.last_activity_at = new Date().toISOString();\n }\n this.persist();\n }\n\n requestFinished(request: RuntimeRequestFinished): void {\n this.status.active_requests = Math.max(0, this.status.active_requests - 1);\n const now = new Date().toISOString();\n const project = this.findProject(request.projectPath, request.projectAlias);\n this.activeRequests.delete(request.requestId);\n if (project) {\n project.active_requests = Math.max(0, project.active_requests - 1);\n project.active_tools = this.activeToolsForProject(project.path);\n project.request_count += 1;\n project.last_tool = request.toolName;\n project.last_activity_at = now;\n if (request.outcome === \"error\") project.error_count += 1;\n if (request.outcome === \"error\") {\n project.state = \"error\";\n } else if (project.active_requests > 0) {\n project.state = \"active\";\n } else {\n project.state = \"idle\";\n }\n }\n this.status.recent_activity.push({\n request_id: request.requestId,\n ...(request.projectAlias ? { project_alias: request.projectAlias } : {}),\n ...(request.projectPath ? { project_path: request.projectPath } : {}),\n tool_name: request.toolName,\n outcome: request.outcome,\n duration_ms: request.durationMs,\n at: now,\n ...(request.error ? { error: request.error } : {}),\n });\n if (this.status.recent_activity.length > 50) {\n this.status.recent_activity.splice(0, this.status.recent_activity.length - 50);\n }\n this.persist();\n }\n\n stopped(): void {\n if (this.livenessTimer) clearInterval(this.livenessTimer);\n this.livenessTimer = undefined;\n this.status.state = \"stopped\";\n this.status.active_requests = 0;\n this.activeRequests.clear();\n for (const project of this.status.projects) {\n project.active_requests = 0;\n project.active_tools = [];\n project.state = \"idle\";\n }\n void this.flush();\n }\n\n failed(): void {\n if (this.livenessTimer) clearInterval(this.livenessTimer);\n this.livenessTimer = undefined;\n }\n\n async flush(): Promise<void> {\n if (this.persistTimer) {\n clearTimeout(this.persistTimer);\n this.persistTimer = undefined;\n }\n this.enqueuePersist();\n await this.persistPromise;\n }\n\n private findProject(path?: string, alias?: string): RuntimeProjectTelemetry | undefined {\n if (path) return this.status.projects.find((project) => project.path === path);\n if (alias) return this.status.projects.find((project) => project.alias === alias);\n if (this.status.projects.length === 1) return this.status.projects[0];\n return undefined;\n }\n\n private activeToolsForProject(projectPath: string): string[] {\n return [...this.activeRequests.values()]\n .filter((request) => request.projectPath === projectPath)\n .map((request) => request.toolName);\n }\n\n private persist(): void {\n this.status.updated_at = new Date().toISOString();\n if (this.persistTimer) return;\n this.persistTimer = setTimeout(() => {\n this.persistTimer = undefined;\n this.enqueuePersist();\n }, 25);\n this.persistTimer.unref();\n }\n\n private enqueuePersist(): void {\n this.status.updated_at = new Date().toISOString();\n const snapshot = `${JSON.stringify(this.status, null, 2)}\\n`;\n this.persistPromise = this.persistPromise.then(() => this.writeSnapshot(snapshot));\n }\n\n private async writeSnapshot(snapshot: string): Promise<void> {\n const temporaryPath = `${this.path}.${process.pid}.tmp`;\n try {\n await mkdir(dirname(this.path), { recursive: true });\n await writeFile(temporaryPath, snapshot, { encoding: \"utf8\", mode: 0o600 });\n await chmod(temporaryPath, 0o600);\n await rename(temporaryPath, this.path);\n } catch {\n await rm(temporaryPath, { force: true }).catch(() => undefined);\n }\n }\n}\n\nexport function readRuntimeTelemetry(configPath: string): RuntimeTelemetryStatus | null {\n try {\n const value = JSON.parse(readFileSync(runtimeTelemetryPath(configPath), \"utf8\")) as RuntimeTelemetryStatus;\n return value.version === 1 ? value : null;\n } catch {\n return null;\n }\n}\n\nexport function runtimeTelemetryPath(configPath: string): string {\n return runtimeArtifactPath(configPath, \"status\");\n}\n\nexport function clearRuntimeTelemetry(configPath: string): void {\n try {\n unlinkSync(runtimeTelemetryPath(configPath));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n}\n\nfunction credentialFreeRemoteLabel(remoteLabel: string): string {\n try {\n const url = new URL(remoteLabel);\n url.username = \"\";\n url.password = \"\";\n url.search = \"\";\n url.hash = \"\";\n return url.toString();\n } catch {\n return remoteLabel\n .replace(/^[^/@]+@([^:]+):/, \"$1:\")\n .replace(/[?#].*$/, \"\");\n }\n}\n\nfunction credentialFreeGatewayLabel(gatewayUrl: string): string {\n try {\n const url = new URL(gatewayUrl);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return \"invalid gateway\";\n const path = url.pathname === \"/\" ? \"\" : url.pathname;\n return `${url.protocol}//${url.host}${path}`;\n } catch {\n return \"invalid gateway\";\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-telemetry.test.d.ts","sourceRoot":"","sources":["../src/runtime-telemetry.test.ts"],"names":[],"mappings":""}
|