@agimon-ai/doompi 0.0.1-alpha.81 → 0.0.1-alpha.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/doomRunner.cjs +2 -1
- package/dist/bin/doomRunner.cjs.map +1 -1
- package/dist/bin/doomRunner.d.cts.map +1 -1
- package/dist/bin/doomRunner.d.mts.map +1 -1
- package/dist/bin/doomRunner.mjs +3 -2
- package/dist/bin/doomRunner.mjs.map +1 -1
- package/dist/builders/server/runtime.cjs +117 -48
- package/dist/builders/server/runtime.cjs.map +1 -1
- package/dist/builders/server/runtime.mjs +117 -48
- package/dist/builders/server/runtime.mjs.map +1 -1
- package/package.json +17 -17
package/dist/bin/doomRunner.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const require_index = require("../composition/repository/index.cjs");
|
|
4
|
+
let node_fs = require("node:fs");
|
|
4
5
|
let node_url = require("node:url");
|
|
5
6
|
let _agimon_ai_doompi_core_module_resolution = require("@agimon-ai/doompi-core/module-resolution");
|
|
6
7
|
//#region src/bin/doomRunner.ts
|
|
@@ -26,7 +27,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
26
27
|
if (typeof loaded.main !== "function") throw new Error(`${RUNNER_CLI_EXPORT} does not export a callable main function.`);
|
|
27
28
|
return loaded.main(argv);
|
|
28
29
|
}
|
|
29
|
-
if (process.argv[1] && require("url").pathToFileURL(__filename).href === (0,
|
|
30
|
+
if (process.argv[1] && (0, node_fs.existsSync)(process.argv[1]) && (0, node_fs.realpathSync)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href)) === (0, node_fs.realpathSync)(process.argv[1])) main().then((exitCode) => {
|
|
30
31
|
process.exitCode = exitCode;
|
|
31
32
|
}, (error) => {
|
|
32
33
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doomRunner.cjs","names":["findRepositoryRoot","consumerPackageEntry","pathToFileURL"],"sources":["../../src/bin/doomRunner.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI Entry Point for doom-runner\n *\n * The Runner package is selectable, so this compatibility executable resolves\n * it from the active repository instead of retaining it in DoomPi's dependency\n * closure. The Runner package's own entry only self-invokes when it is argv[1],\n * which it is not once this shim imports it by absolute path.\n */\n\nimport { pathToFileURL } from 'node:url';\n\nimport { consumerPackageEntry } from '@agimon-ai/doompi-core/module-resolution';\n\nimport { findRepositoryRoot } from '../composition/repository';\n\nconst RUNNER_CLI_EXPORT = '@agimon-ai/doompi-runner/bin/cli';\n\ninterface RunnerCliModule {\n readonly main?: unknown;\n}\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n let repoRoot: string;\n try {\n repoRoot = findRepositoryRoot(process.cwd());\n } catch (error) {\n throw new Error('doom-runner must be invoked inside a configured repository.', { cause: error });\n }\n const entry = consumerPackageEntry(RUNNER_CLI_EXPORT, repoRoot);\n if (!entry) {\n throw new Error(\n 'Doom Runner is not installed for this repository. Add @agimon-ai/doompi-runner to .doom/modes.yaml and run doompi sync.',\n );\n }\n const loaded = (await import(pathToFileURL(entry).href)) as RunnerCliModule;\n if (typeof loaded.main !== 'function') {\n throw new Error(`${RUNNER_CLI_EXPORT} does not export a callable main function.`);\n }\n return (loaded.main as (args: readonly string[]) => Promise<number>)(argv);\n}\n\nif (process.argv[1]
|
|
1
|
+
{"version":3,"file":"doomRunner.cjs","names":["findRepositoryRoot","consumerPackageEntry","pathToFileURL","existsSync","realpathSync","fileURLToPath"],"sources":["../../src/bin/doomRunner.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI Entry Point for doom-runner\n *\n * The Runner package is selectable, so this compatibility executable resolves\n * it from the active repository instead of retaining it in DoomPi's dependency\n * closure. The Runner package's own entry only self-invokes when it is argv[1],\n * which it is not once this shim imports it by absolute path.\n */\n\nimport { existsSync, realpathSync } from 'node:fs';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\n\nimport { consumerPackageEntry } from '@agimon-ai/doompi-core/module-resolution';\n\nimport { findRepositoryRoot } from '../composition/repository';\n\nconst RUNNER_CLI_EXPORT = '@agimon-ai/doompi-runner/bin/cli';\n\ninterface RunnerCliModule {\n readonly main?: unknown;\n}\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n let repoRoot: string;\n try {\n repoRoot = findRepositoryRoot(process.cwd());\n } catch (error) {\n throw new Error('doom-runner must be invoked inside a configured repository.', { cause: error });\n }\n const entry = consumerPackageEntry(RUNNER_CLI_EXPORT, repoRoot);\n if (!entry) {\n throw new Error(\n 'Doom Runner is not installed for this repository. Add @agimon-ai/doompi-runner to .doom/modes.yaml and run doompi sync.',\n );\n }\n const loaded = (await import(pathToFileURL(entry).href)) as RunnerCliModule;\n if (typeof loaded.main !== 'function') {\n throw new Error(`${RUNNER_CLI_EXPORT} does not export a callable main function.`);\n }\n return (loaded.main as (args: readonly string[]) => Promise<number>)(argv);\n}\n\nif (\n process.argv[1] &&\n existsSync(process.argv[1]) &&\n realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])\n) {\n main().then(\n (exitCode) => {\n process.exitCode = exitCode;\n },\n (error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[doom-runner] ${message}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,oBAAoB;AAM1B,eAAsB,KAAK,OAA0B,QAAQ,KAAK,MAAM,CAAC,GAAoB;CAC3F,IAAI;CACJ,IAAI;EACF,WAAWA,cAAAA,mBAAmB,QAAQ,IAAI,CAAC;CAC7C,SAAS,OAAO;EACd,MAAM,IAAI,MAAM,+DAA+D,EAAE,OAAO,MAAM,CAAC;CACjG;CACA,MAAM,SAAA,GAAQC,yCAAAA,qBAAAA,CAAqB,mBAAmB,QAAQ;CAC9D,IAAI,CAAC,OACH,MAAM,IAAI,MACR,yHACF;CAEF,MAAM,SAAU,MAAM,QAAA,GAAOC,SAAAA,cAAAA,CAAc,KAAK,CAAC,CAAC;CAClD,IAAI,OAAO,OAAO,SAAS,YACzB,MAAM,IAAI,MAAM,GAAG,kBAAkB,2CAA2C;CAElF,OAAQ,OAAO,KAAsD,IAAI;AAC3E;AAEA,IACE,QAAQ,KAAK,OAAA,GACbC,QAAAA,WAAAA,CAAW,QAAQ,KAAK,EAAE,MAAA,GAC1BC,QAAAA,aAAAA,EAAAA,GAAaC,SAAAA,cAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,IAA6B,CAAC,OAAA,GAAMD,QAAAA,aAAAA,CAAa,QAAQ,KAAK,EAAE,GAE7E,KAAK,CAAC,CAAC,MACJ,aAAa;CACZ,QAAQ,WAAW;AACrB,IACC,UAAmB;CAClB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACrE,QAAQ,OAAO,MAAM,iBAAiB,QAAQ,GAAG;CACjD,QAAQ,WAAW;AACrB,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doomRunner.d.cts","names":[],"sources":["../../src/bin/doomRunner.ts"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"doomRunner.d.cts","names":[],"sources":["../../src/bin/doomRunner.ts"],"mappings":";;;;;;;;;wBAwBsB,KAAK,2BAAkD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doomRunner.d.mts","names":[],"sources":["../../src/bin/doomRunner.ts"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"doomRunner.d.mts","names":[],"sources":["../../src/bin/doomRunner.ts"],"mappings":";;;;;;;;;wBAwBsB,KAAK,2BAAkD"}
|
package/dist/bin/doomRunner.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { findRepositoryRoot } from "../composition/repository/index.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
5
|
import { consumerPackageEntry } from "@agimon-ai/doompi-core/module-resolution";
|
|
5
6
|
//#region src/bin/doomRunner.ts
|
|
6
7
|
/**
|
|
@@ -25,7 +26,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
25
26
|
if (typeof loaded.main !== "function") throw new Error(`${RUNNER_CLI_EXPORT} does not export a callable main function.`);
|
|
26
27
|
return loaded.main(argv);
|
|
27
28
|
}
|
|
28
|
-
if (process.argv[1] && import.meta.url ===
|
|
29
|
+
if (process.argv[1] && existsSync(process.argv[1]) && realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])) main().then((exitCode) => {
|
|
29
30
|
process.exitCode = exitCode;
|
|
30
31
|
}, (error) => {
|
|
31
32
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doomRunner.mjs","names":[],"sources":["../../src/bin/doomRunner.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI Entry Point for doom-runner\n *\n * The Runner package is selectable, so this compatibility executable resolves\n * it from the active repository instead of retaining it in DoomPi's dependency\n * closure. The Runner package's own entry only self-invokes when it is argv[1],\n * which it is not once this shim imports it by absolute path.\n */\n\nimport { pathToFileURL } from 'node:url';\n\nimport { consumerPackageEntry } from '@agimon-ai/doompi-core/module-resolution';\n\nimport { findRepositoryRoot } from '../composition/repository';\n\nconst RUNNER_CLI_EXPORT = '@agimon-ai/doompi-runner/bin/cli';\n\ninterface RunnerCliModule {\n readonly main?: unknown;\n}\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n let repoRoot: string;\n try {\n repoRoot = findRepositoryRoot(process.cwd());\n } catch (error) {\n throw new Error('doom-runner must be invoked inside a configured repository.', { cause: error });\n }\n const entry = consumerPackageEntry(RUNNER_CLI_EXPORT, repoRoot);\n if (!entry) {\n throw new Error(\n 'Doom Runner is not installed for this repository. Add @agimon-ai/doompi-runner to .doom/modes.yaml and run doompi sync.',\n );\n }\n const loaded = (await import(pathToFileURL(entry).href)) as RunnerCliModule;\n if (typeof loaded.main !== 'function') {\n throw new Error(`${RUNNER_CLI_EXPORT} does not export a callable main function.`);\n }\n return (loaded.main as (args: readonly string[]) => Promise<number>)(argv);\n}\n\nif (process.argv[1]
|
|
1
|
+
{"version":3,"file":"doomRunner.mjs","names":[],"sources":["../../src/bin/doomRunner.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI Entry Point for doom-runner\n *\n * The Runner package is selectable, so this compatibility executable resolves\n * it from the active repository instead of retaining it in DoomPi's dependency\n * closure. The Runner package's own entry only self-invokes when it is argv[1],\n * which it is not once this shim imports it by absolute path.\n */\n\nimport { existsSync, realpathSync } from 'node:fs';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\n\nimport { consumerPackageEntry } from '@agimon-ai/doompi-core/module-resolution';\n\nimport { findRepositoryRoot } from '../composition/repository';\n\nconst RUNNER_CLI_EXPORT = '@agimon-ai/doompi-runner/bin/cli';\n\ninterface RunnerCliModule {\n readonly main?: unknown;\n}\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n let repoRoot: string;\n try {\n repoRoot = findRepositoryRoot(process.cwd());\n } catch (error) {\n throw new Error('doom-runner must be invoked inside a configured repository.', { cause: error });\n }\n const entry = consumerPackageEntry(RUNNER_CLI_EXPORT, repoRoot);\n if (!entry) {\n throw new Error(\n 'Doom Runner is not installed for this repository. Add @agimon-ai/doompi-runner to .doom/modes.yaml and run doompi sync.',\n );\n }\n const loaded = (await import(pathToFileURL(entry).href)) as RunnerCliModule;\n if (typeof loaded.main !== 'function') {\n throw new Error(`${RUNNER_CLI_EXPORT} does not export a callable main function.`);\n }\n return (loaded.main as (args: readonly string[]) => Promise<number>)(argv);\n}\n\nif (\n process.argv[1] &&\n existsSync(process.argv[1]) &&\n realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1])\n) {\n main().then(\n (exitCode) => {\n process.exitCode = exitCode;\n },\n (error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[doom-runner] ${message}\\n`);\n process.exitCode = 1;\n },\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAkBA,MAAM,oBAAoB;AAM1B,eAAsB,KAAK,OAA0B,QAAQ,KAAK,MAAM,CAAC,GAAoB;CAC3F,IAAI;CACJ,IAAI;EACF,WAAW,mBAAmB,QAAQ,IAAI,CAAC;CAC7C,SAAS,OAAO;EACd,MAAM,IAAI,MAAM,+DAA+D,EAAE,OAAO,MAAM,CAAC;CACjG;CACA,MAAM,QAAQ,qBAAqB,mBAAmB,QAAQ;CAC9D,IAAI,CAAC,OACH,MAAM,IAAI,MACR,yHACF;CAEF,MAAM,SAAU,MAAM,OAAO,cAAc,KAAK,CAAC,CAAC;CAClD,IAAI,OAAO,OAAO,SAAS,YACzB,MAAM,IAAI,MAAM,GAAG,kBAAkB,2CAA2C;CAElF,OAAQ,OAAO,KAAsD,IAAI;AAC3E;AAEA,IACE,QAAQ,KAAK,MACb,WAAW,QAAQ,KAAK,EAAE,KAC1B,aAAa,cAAc,YAAY,GAAG,CAAC,MAAM,aAAa,QAAQ,KAAK,EAAE,GAE7E,KAAK,CAAC,CAAC,MACJ,aAAa;CACZ,QAAQ,WAAW;AACrB,IACC,UAAmB;CAClB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACrE,QAAQ,OAAO,MAAM,iBAAiB,QAAQ,GAAG;CACjD,QAAQ,WAAW;AACrB,CACF"}
|
|
@@ -176,6 +176,20 @@ async function runServerRuntime(options, runtime) {
|
|
|
176
176
|
});
|
|
177
177
|
},
|
|
178
178
|
createSession: (request) => openSession(request),
|
|
179
|
+
sessionReservations: {
|
|
180
|
+
read(id, parentSessionId) {
|
|
181
|
+
if (!cockpit) throw new Error("Session setup is not ready.");
|
|
182
|
+
return cockpit.sessionReservations.read(id, parentSessionId);
|
|
183
|
+
},
|
|
184
|
+
async prepare(id, parentSessionId, cwd) {
|
|
185
|
+
if (!cockpit) throw new Error("Session setup is not ready.");
|
|
186
|
+
return cockpit.sessionReservations.prepare(id, parentSessionId, cwd);
|
|
187
|
+
},
|
|
188
|
+
async complete(id, parentSessionId) {
|
|
189
|
+
if (!cockpit) throw new Error("Session setup is not ready.");
|
|
190
|
+
return cockpit.sessionReservations.complete(id, parentSessionId);
|
|
191
|
+
}
|
|
192
|
+
},
|
|
179
193
|
onNotice: notice,
|
|
180
194
|
hubToken: () => attachToken,
|
|
181
195
|
requestSessionApi: (scope, request) => requestSessionApi(scope, request)
|
|
@@ -381,7 +395,7 @@ async function runServerRuntime(options, runtime) {
|
|
|
381
395
|
notice(`Workspace '${workspace.root}' could not be restored: ${error instanceof Error ? error.message : String(error)}`);
|
|
382
396
|
}
|
|
383
397
|
}
|
|
384
|
-
const sessionHostOptions = (context, bundle, mcpBundle, identity) => {
|
|
398
|
+
const sessionHostOptions = (context, bundle, mcpBundle, identity, workspaceId) => {
|
|
385
399
|
const policyOptions = context.options;
|
|
386
400
|
const sessionSelection = {
|
|
387
401
|
root: policyOptions.repoRoot,
|
|
@@ -395,7 +409,7 @@ async function runServerRuntime(options, runtime) {
|
|
|
395
409
|
cwd: policyOptions.cwd,
|
|
396
410
|
repoRoot: policyOptions.repoRoot,
|
|
397
411
|
sessionId: identity.sessionId,
|
|
398
|
-
workspaceId: (0, _agimon_ai_doompi_core_sync_location.resolveSyncLocation)(policyOptions.repoRoot, homeDirectory).identity.worktreeId,
|
|
412
|
+
workspaceId: workspaceId ?? (0, _agimon_ai_doompi_core_sync_location.resolveSyncLocation)(policyOptions.repoRoot, homeDirectory).identity.worktreeId,
|
|
399
413
|
sessionName: identity.sessionName,
|
|
400
414
|
webComposition: webCompositions?.publish({
|
|
401
415
|
scope: "session",
|
|
@@ -513,59 +527,110 @@ async function runServerRuntime(options, runtime) {
|
|
|
513
527
|
}
|
|
514
528
|
await bounded(harnessTelemetry.flush(), "initial composition telemetry flush", notice);
|
|
515
529
|
}
|
|
530
|
+
const reservedOpens = /* @__PURE__ */ new Map();
|
|
516
531
|
openSession = async (request, sessionId) => {
|
|
532
|
+
request.signal?.throwIfAborted();
|
|
533
|
+
if (request.reservationId !== void 0) {
|
|
534
|
+
if (!request.parentSessionId || !cockpit) throw new Error("A reserved session requires its owning parent.");
|
|
535
|
+
const prepared = await cockpit.sessionReservations.prepare(request.reservationId, request.parentSessionId, request.cwd);
|
|
536
|
+
if (sessionId !== void 0 && sessionId !== prepared.sessionId) throw new Error("Reserved session identity cannot change.");
|
|
537
|
+
sessionId = prepared.sessionId;
|
|
538
|
+
const existing = hub.session(sessionId);
|
|
539
|
+
if (existing) {
|
|
540
|
+
if (existing.cwd !== prepared.cwd || existing.parentSessionId !== request.parentSessionId) throw new Error("Reserved session target does not match.");
|
|
541
|
+
return {
|
|
542
|
+
sessionId,
|
|
543
|
+
cwd: existing.cwd,
|
|
544
|
+
workspaceId: existing.workspaceId
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
if (openSessions.list().some((record) => record.sessionId === sessionId)) throw new Error("Resume the recorded session instead of recreating it.");
|
|
548
|
+
const pending = reservedOpens.get(sessionId);
|
|
549
|
+
if (pending) return pending;
|
|
550
|
+
request = {
|
|
551
|
+
...request,
|
|
552
|
+
cwd: prepared.cwd
|
|
553
|
+
};
|
|
554
|
+
}
|
|
517
555
|
const identity = {
|
|
518
556
|
sessionId: sessionId ?? node_crypto.default.randomUUID(),
|
|
519
557
|
sessionName: request.name,
|
|
520
558
|
parentSessionId: request.parentSessionId,
|
|
521
559
|
sessionProvenance: request.sessionProvenance
|
|
522
560
|
};
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
561
|
+
const inheritedWorkspaceId = request.sessionProvenance === "worktree" && request.parentSessionId ? hub.session(request.parentSessionId)?.workspaceId ?? openSessions.list().find((record) => record.sessionId === request.parentSessionId)?.workspaceId : void 0;
|
|
562
|
+
if (request.sessionProvenance === "worktree" && inheritedWorkspaceId === void 0) throw new Error("Worktree session requires its parent workspace.");
|
|
563
|
+
const start = (async () => {
|
|
564
|
+
const childIdentity = require_sessionArguments.resolveSessionIdentity([], identity);
|
|
565
|
+
const childEnvironment = { ...baseEnvironment };
|
|
566
|
+
for (const key of [_agimon_ai_doompi_config_harnessStore.HARNESS_STATE_POINTER, ...Object.values(_agimon_ai_doompi_config_harnessState.HARNESS_STATE_KEYS)]) delete childEnvironment[key];
|
|
567
|
+
const childContext = await require_harnessContext.buildHarnessContext(resolveHarnessOptions({
|
|
568
|
+
args: [
|
|
569
|
+
"--cwd",
|
|
570
|
+
request.cwd,
|
|
571
|
+
...childIdentity.agentArgs
|
|
572
|
+
],
|
|
573
|
+
cwd: request.cwd,
|
|
574
|
+
environment: childEnvironment
|
|
575
|
+
}), harnessTelemetry);
|
|
576
|
+
try {
|
|
577
|
+
if (inheritedWorkspaceId === void 0) await admitWorkspace(childContext.options.repoRoot);
|
|
578
|
+
else {
|
|
579
|
+
if (hub.workspaces().find((workspace) => workspace.id === inheritedWorkspaceId && workspace.available !== false) === void 0) throw new Error("Worktree parent workspace is unavailable.");
|
|
580
|
+
const syncEnvironment = {
|
|
581
|
+
...baseEnvironment,
|
|
582
|
+
DOOMPI_ROOT: childContext.options.repoRoot
|
|
583
|
+
};
|
|
584
|
+
for (const key of [_agimon_ai_doompi_config_harnessStore.HARNESS_STATE_POINTER, ...Object.values(_agimon_ai_doompi_config_harnessState.HARNESS_STATE_KEYS)]) delete syncEnvironment[key];
|
|
585
|
+
await syncWorkspace(childContext.options.repoRoot, syncEnvironment);
|
|
586
|
+
}
|
|
587
|
+
const bundle = await loadComposition(childContext.options.repoRoot, "session", {
|
|
588
|
+
root: childContext.options.repoRoot,
|
|
589
|
+
majorMode: childContext.options.majorMode,
|
|
590
|
+
activeLayers: childContext.selectedLayers
|
|
591
|
+
});
|
|
592
|
+
const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {
|
|
593
|
+
majorMode: childContext.options.majorMode,
|
|
594
|
+
activeLayers: childContext.selectedLayers
|
|
595
|
+
});
|
|
596
|
+
request.signal?.throwIfAborted();
|
|
597
|
+
pendingSessions.set(identity.sessionId, {
|
|
598
|
+
cleanup: () => childContext.cleanup(),
|
|
599
|
+
bundle,
|
|
600
|
+
mcpBundle
|
|
601
|
+
});
|
|
602
|
+
const created = await hub.create(sessionHostOptions(childContext, bundle, mcpBundle, identity, inheritedWorkspaceId));
|
|
603
|
+
request.signal?.throwIfAborted();
|
|
604
|
+
if (created.workspaceId !== void 0) {
|
|
605
|
+
if (openSessions.add({
|
|
606
|
+
sessionId: created.id,
|
|
607
|
+
workspaceId: created.workspaceId,
|
|
608
|
+
cwd: created.cwd,
|
|
609
|
+
name: created.name,
|
|
610
|
+
createdAt: created.createdAt,
|
|
611
|
+
...created.parentSessionId === void 0 ? {} : { parentSessionId: created.parentSessionId },
|
|
612
|
+
...created.sessionProvenance === void 0 ? {} : { sessionProvenance: created.sessionProvenance }
|
|
613
|
+
}) === false) throw new Error("The new session could not be durably recorded.");
|
|
614
|
+
}
|
|
615
|
+
return {
|
|
616
|
+
sessionId: identity.sessionId,
|
|
617
|
+
cwd: childContext.options.cwd,
|
|
618
|
+
workspaceId: created.workspaceId
|
|
619
|
+
};
|
|
620
|
+
} catch (error) {
|
|
621
|
+
if (hub.session(identity.sessionId)) await hub.closeSession(identity.sessionId);
|
|
622
|
+
else {
|
|
623
|
+
pendingSessions.delete(identity.sessionId);
|
|
624
|
+
await childContext.cleanup().catch((cleanupError) => notice(String(cleanupError)));
|
|
625
|
+
}
|
|
626
|
+
throw error;
|
|
627
|
+
}
|
|
628
|
+
})();
|
|
629
|
+
if (request.reservationId !== void 0) reservedOpens.set(identity.sessionId, start);
|
|
535
630
|
try {
|
|
536
|
-
await
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
majorMode: childContext.options.majorMode,
|
|
540
|
-
activeLayers: childContext.selectedLayers
|
|
541
|
-
});
|
|
542
|
-
const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {
|
|
543
|
-
majorMode: childContext.options.majorMode,
|
|
544
|
-
activeLayers: childContext.selectedLayers
|
|
545
|
-
});
|
|
546
|
-
pendingSessions.set(identity.sessionId, {
|
|
547
|
-
cleanup: () => childContext.cleanup(),
|
|
548
|
-
bundle,
|
|
549
|
-
mcpBundle
|
|
550
|
-
});
|
|
551
|
-
const created = await hub.create(sessionHostOptions(childContext, bundle, mcpBundle, identity));
|
|
552
|
-
if (created.workspaceId !== void 0) openSessions.add({
|
|
553
|
-
sessionId: created.id,
|
|
554
|
-
workspaceId: created.workspaceId,
|
|
555
|
-
cwd: created.cwd,
|
|
556
|
-
name: created.name,
|
|
557
|
-
createdAt: created.createdAt,
|
|
558
|
-
...created.parentSessionId === void 0 ? {} : { parentSessionId: created.parentSessionId },
|
|
559
|
-
...created.sessionProvenance === void 0 ? {} : { sessionProvenance: created.sessionProvenance }
|
|
560
|
-
});
|
|
561
|
-
return {
|
|
562
|
-
sessionId: identity.sessionId,
|
|
563
|
-
cwd: childContext.options.cwd
|
|
564
|
-
};
|
|
565
|
-
} catch (error) {
|
|
566
|
-
pendingSessions.delete(identity.sessionId);
|
|
567
|
-
await childContext.cleanup().catch((cleanupError) => notice(String(cleanupError)));
|
|
568
|
-
throw error;
|
|
631
|
+
return await start;
|
|
632
|
+
} finally {
|
|
633
|
+
if (reservedOpens.get(identity.sessionId) === start) reservedOpens.delete(identity.sessionId);
|
|
569
634
|
}
|
|
570
635
|
};
|
|
571
636
|
});
|
|
@@ -575,7 +640,9 @@ async function runServerRuntime(options, runtime) {
|
|
|
575
640
|
headlessHub: hub,
|
|
576
641
|
token: attachToken,
|
|
577
642
|
sessionMcpPublicOrigin: () => remoteRuntime?.remote.publicOrigin(),
|
|
643
|
+
sessionMcpStateDir: serverDirectory,
|
|
578
644
|
sessionMcpPublicOriginRevision: () => remoteRuntime?.remote.publicOriginRevision() ?? 0,
|
|
645
|
+
isSessionPersisted: (sessionId, cwd) => openSessions.list().some((record) => record.sessionId === sessionId && record.cwd === cwd),
|
|
579
646
|
workspaceHistory: (workspaceId) => {
|
|
580
647
|
const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;
|
|
581
648
|
if (!workspaceRoot) throw new Error("Workspace not found.");
|
|
@@ -633,7 +700,9 @@ async function runServerRuntime(options, runtime) {
|
|
|
633
700
|
await hub.closeSession(session.id);
|
|
634
701
|
await openSession({
|
|
635
702
|
cwd: session.cwd,
|
|
636
|
-
name: session.name
|
|
703
|
+
name: session.name,
|
|
704
|
+
...session.parentSessionId === void 0 ? {} : { parentSessionId: session.parentSessionId },
|
|
705
|
+
...session.sessionProvenance === void 0 ? {} : { sessionProvenance: session.sessionProvenance }
|
|
637
706
|
}, session.id);
|
|
638
707
|
},
|
|
639
708
|
resumeSession: async (session, targetSessionId) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.cjs","names":["createServerTelemetry","path","piAgentDirectory","createWorkspaceRegistry","createOpenSessionRegistry","createHarnessTelemetry","createHeadlessSessionManager","publishHeadlessSelectionStatus","readMinorModeCatalog","createHeadlessHub","fs","resolveSessionIdentity","crypto","os","globalDoomConfigDirectory","createWebCompositions","readSyncRegistration","resolveServerBundleSource","loadMajorModesConfig","resolveLayers","loadServerBundle","loadMcpBundle","readSyncDrift","readSyncState","createRemoteRuntime","WebSocket","findRepositoryRoot","resolveSyncLocation","HARNESS_STATE_POINTER","HARNESS_STATE_KEYS","filterHookDisabledLayers","serveSessionApis","buildHarnessContext","serveHeadlessServer","listSavedSessions","readSqliteTranscript"],"sources":["../../../src/builders/server/runtime.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { globalDoomConfigDirectory } from '@agimon-ai/doompi-config/config';\nimport { filterHookDisabledLayers, loadMajorModesConfig, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { createHeadlessHub, type HeadlessHub } from '@agimon-ai/doompi-core/headless-hub';\nimport { serveHeadlessServer } from '@agimon-ai/doompi-core/headless-server';\nimport type { HeadlessSessionHost, HeadlessSessionHostOptions } from '@agimon-ai/doompi-core/headless-session-host';\nimport { createHeadlessSessionManager } from '@agimon-ai/doompi-core/headless-session-manager';\nimport {\n createOpenSessionRegistry,\n createWorkspaceRegistry,\n listSavedSessions,\n readSqliteTranscript,\n} from '@agimon-ai/doompi-core/history';\nimport type { OpenSessionRecord } from '@agimon-ai/doompi-core/history';\nimport type {\n DoomHubSessionApiRequest,\n DoomHubSessionCreateRequest,\n DoomHubSessionScope,\n} from '@agimon-ai/doompi-core/hub-channel';\nimport { loadMcpBundle, type LoadedMcpBundle } from '@agimon-ai/doompi-core/mcp-facet';\nimport { serveSessionApis, type PackageApiServer } from '@agimon-ai/doompi-core/package-api-server';\nimport { piAgentDirectory } from '@agimon-ai/doompi-core/pi-settings';\nimport { createRemoteRuntime, type RemoteRuntime } from '@agimon-ai/doompi-core/remote-runtime';\nimport type { HeadlessSessionManager } from '@agimon-ai/doompi-core/runtime-headless-session-manager';\nimport { createHarnessTelemetry } from '@agimon-ai/doompi-core/runtime-log-sink-telemetry';\nimport { loadServerBundle, resolveServerBundleSource } from '@agimon-ai/doompi-core/server-facet';\nimport { createServerTelemetry } from '@agimon-ai/doompi-core/server-telemetry';\nimport { resolveSyncLocation } from '@agimon-ai/doompi-core/sync-location';\nimport { readSyncRegistration } from '@agimon-ai/doompi-core/sync-registration';\nimport { createWebCompositions } from '@agimon-ai/doompi-core/web-compositions';\nimport { readMinorModeCatalog } from '@agimon-ai/doompi-minor-mode';\nimport WebSocket from 'ws';\n\nimport { HARNESS_STATE_KEYS, HARNESS_STATE_POINTER } from '../../composition/harnessState';\nimport { findRepositoryRoot } from '../../composition/repository';\nimport { readSyncDrift } from '../../composition/syncDrift';\nimport { readSyncState } from '../../composition/syncState';\nimport { buildHarnessContext } from '../cli/harnessContext';\nimport { publishHeadlessSelectionStatus } from './selectionStatus';\nimport { resolveSessionIdentity } from './sessionArguments';\nimport type { ServeOptions, ServerRuntimeEnvironment } from './types';\nconst TELEMETRY_SHUTDOWN_TIMEOUT_MS = 2_000;\n\nasync function bounded(operation: Promise<unknown>, label: string, notice: (message: string) => void): Promise<void> {\n let timeout: NodeJS.Timeout | undefined;\n try {\n await Promise.race([\n operation,\n new Promise<void>((resolve) => {\n timeout = setTimeout(resolve, TELEMETRY_SHUTDOWN_TIMEOUT_MS);\n }),\n ]);\n } catch (error) {\n notice(`${label} failed: ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function runServerRuntime(options: ServeOptions, runtime: ServerRuntimeEnvironment): Promise<number> {\n const { cwd: baseCwd, environment: baseEnvironment, notice, resolveHarnessOptions, signal, syncWorkspace } = runtime;\n const telemetry = createServerTelemetry({ cwd: baseCwd, env: baseEnvironment, warn: notice });\n const serverDirectory = path.join(piAgentDirectory(baseEnvironment), 'server');\n const workspaces = createWorkspaceRegistry({ directory: serverDirectory, onNotice: notice });\n // Beside the journals it names, because a record pointing at a sessions\n // directory it is not stored next to is a record that can outlive its target.\n const openSessions = createOpenSessionRegistry({\n directory: serverDirectory,\n onNotice: notice,\n });\n let nextEventLoopTick = performance.now() + 1_000;\n const eventLoopMonitor = setInterval(() => {\n const now = performance.now();\n const delay = Math.max(0, now - nextEventLoopTick);\n nextEventLoopTick = now + 1_000;\n if (delay >= 100)\n void telemetry\n .recordEvent('doompi_server.event_loop_delay', { duration_ms: Math.round(delay) })\n .catch((error: unknown) => notice(`event loop telemetry failed: ${String(error)}`));\n }, 1_000);\n eventLoopMonitor.unref();\n const harnessTelemetry = createHarnessTelemetry({\n cwd: baseCwd,\n env: baseEnvironment,\n warn: notice,\n deferSpans: true,\n });\n const baseSessionManager = createHeadlessSessionManager({\n publishSelectionStatus: publishHeadlessSelectionStatus,\n contextGroups: (context) =>\n (readMinorModeCatalog(context)?.list() ?? [])\n .filter(({ state }) => state.activation === 'active')\n .map(({ descriptor }) => ({ id: descriptor.id, label: descriptor.label, kind: 'minor' })),\n });\n type SessionSetup = {\n cleanup: () => Promise<void>;\n bundle: Awaited<ReturnType<typeof loadServerBundle>>;\n mcpBundle: LoadedMcpBundle;\n };\n type SessionArtifacts = SessionSetup & { apis: PackageApiServer };\n const pendingSessions = new Map<string, SessionSetup>();\n const sessionArtifacts = new Map<string, SessionArtifacts>();\n let mountSessionApis:\n | ((options: HeadlessSessionHostOptions, host: HeadlessSessionHost) => Promise<PackageApiServer>)\n | undefined;\n /**\n * Shutdown runs every session through the same close path a user-initiated\n * close uses, so without this the registry would be emptied by the very event\n * it exists to survive.\n */\n let shuttingDown = false;\n\n const closeManagedSession = async (sessionId: string): Promise<void> => {\n if (!shuttingDown) openSessions.remove(sessionId);\n const artifacts = sessionArtifacts.get(sessionId);\n sessionArtifacts.delete(sessionId);\n webCompositions?.remove({ scope: 'session', sessionId });\n const failures: unknown[] = [];\n try {\n await artifacts?.apis.close();\n } catch (error) {\n failures.push(error);\n }\n try {\n await artifacts?.cleanup();\n } catch (error) {\n failures.push(error);\n }\n try {\n await baseSessionManager.closeSession(sessionId);\n } catch (error) {\n failures.push(error);\n }\n if (failures.length > 0) throw new AggregateError(failures, `Session '${sessionId}' shutdown failed`);\n };\n\n const sessionManager: HeadlessSessionManager = {\n async create(sessionOptions) {\n const setup = pendingSessions.get(sessionOptions.sessionId);\n let host: HeadlessSessionHost;\n try {\n host = await baseSessionManager.create(sessionOptions);\n } catch (error) {\n if (setup !== undefined && pendingSessions.delete(sessionOptions.sessionId))\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n if (setup === undefined || mountSessionApis === undefined) return host;\n try {\n const apis = await mountSessionApis(sessionOptions, host);\n pendingSessions.delete(sessionOptions.sessionId);\n sessionArtifacts.set(sessionOptions.sessionId, { ...setup, apis });\n return host;\n } catch (error) {\n pendingSessions.delete(sessionOptions.sessionId);\n await baseSessionManager\n .closeSession(sessionOptions.sessionId)\n .catch((closeError: unknown) => notice(String(closeError)));\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n },\n get: (sessionId) => baseSessionManager.get(sessionId),\n sessions: () => baseSessionManager.sessions(),\n closeSession: closeManagedSession,\n async close() {\n const ids = baseSessionManager.sessions().map((session) => session.runtime.sessionId);\n const outcomes = await Promise.allSettled(ids.map((id) => closeManagedSession(id)));\n const failures = outcomes\n .filter((outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected')\n .map((outcome) => outcome.reason);\n if (failures.length > 0) throw new AggregateError(failures, 'Headless session shutdown failed');\n },\n };\n\n let requestSessionApi: (\n scope: DoomHubSessionScope,\n request: DoomHubSessionApiRequest,\n ) => Promise<Response> = async () => Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n let openSession: (\n request: DoomHubSessionCreateRequest,\n sessionId?: string,\n ) => Promise<DoomHubSessionScope> = async () => {\n throw new Error('The cockpit session service is not ready.');\n };\n let admitWorkspace: (root: string) => Promise<{ id: string; root: string; available: boolean }> = async () => {\n throw new Error('Workspace admission is not ready.');\n };\n let hub!: HeadlessHub;\n hub = createHeadlessHub({\n manager: sessionManager,\n admitWorkspace: (root) => admitWorkspace(root),\n onWorkspaceRemoved: (workspaceId) => {\n workspaces.remove(workspaceId);\n webCompositions?.remove({ scope: 'workspace', workspaceId });\n },\n createSession: (request) => openSession(request),\n onNotice: notice,\n hubToken: () => attachToken,\n requestSessionApi: (scope, request) => requestSessionApi(scope, request),\n });\n let harnessContext: Awaited<ReturnType<typeof buildHarnessContext>> | undefined;\n let cockpit: Awaited<ReturnType<typeof serveHeadlessServer>> | undefined;\n let remoteRuntime: RemoteRuntime | undefined;\n let attachToken: string | undefined;\n let webCompositions: ReturnType<typeof createWebCompositions> | undefined;\n\n try {\n await telemetry.runInSpan('doompi_server.startup', {}, async () => {\n const token = fs.readFileSync(options.tokenFile, 'utf8').trim();\n if (!token) throw new Error('The attach token file is empty.');\n attachToken = token;\n\n const resolved = resolveSessionIdentity(options.agentArgs, {\n sessionId: options.sessionId ?? crypto.randomUUID(),\n sessionName: options.sessionName,\n });\n\n const homeDirectory = baseEnvironment.HOME ?? os.homedir();\n const globalRoot = globalDoomConfigDirectory(homeDirectory);\n webCompositions = createWebCompositions(path.join(globalRoot, 'server'), notice);\n const loadComposition = async (\n root: string,\n scope: 'global' | 'workspace' | 'session',\n selection?: { root: string; majorMode: string; activeLayers: string[] },\n ) => {\n const registration = readSyncRegistration(root, homeDirectory);\n const source = resolveServerBundleSource({ registration });\n if (source.kind !== 'descriptor')\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening it.`);\n const selected =\n selection ??\n (() => {\n const config = loadMajorModesConfig(root, homeDirectory);\n const majorMode = config.defaultMajorMode;\n return { root, majorMode, activeLayers: resolveLayers(config, majorMode) };\n })();\n return loadServerBundle(scope, {\n ...source,\n ...selected,\n retainCandidates: scope === 'session',\n onNotice: notice,\n });\n };\n const loadSessionMcp = async (\n root: string,\n selection: { majorMode: string; activeLayers: readonly string[] },\n ): Promise<LoadedMcpBundle> => {\n const registration = readSyncRegistration(root, homeDirectory);\n if (registration?.mcpBundle === undefined)\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening its MCP runtime.`);\n return loadMcpBundle({\n directory: path.dirname(registration.mcpBundle.path),\n generation: registration.generation,\n fingerprint: registration.mcpBundle.fingerprint,\n descriptorSha256: registration.mcpBundle.sha256,\n majorMode: selection.majorMode,\n activeLayers: selection.activeLayers,\n retainCandidates: true,\n onNotice: notice,\n });\n };\n const sharedApiContext = {\n homeDirectory,\n environment: baseEnvironment,\n hubToken: token,\n sessionService: hub.sessionService,\n directEvents: hub.directEvents,\n repositories: () =>\n hub.workspaces().map((workspace) => ({\n id: workspace.id,\n path: workspace.root,\n name: workspace.root.split('/').at(-1) ?? workspace.id,\n active: hub.snapshot().some((session) => session.workspaceId === workspace.id),\n })),\n resolveRepository: (id: string) => hub.workspaces().find((workspace) => workspace.id === id)?.root,\n readRepositorySync: (id: string) => {\n const root = hub.workspaces().find((workspace) => workspace.id === id)?.root;\n if (!root) return undefined;\n const drift = readSyncDrift({ repoRoot: root, homeDirectory, requireWebBundle: true });\n const state = readSyncState(root, homeDirectory);\n return { ...drift, mcpProjection: state?.fileState.mcpProjection };\n },\n onNotice: notice,\n };\n const globalBundle = await loadComposition(globalRoot, 'global');\n webCompositions.publishShell(readSyncRegistration(globalRoot, homeDirectory)!);\n remoteRuntime = createRemoteRuntime({\n homeDirectory,\n registrationToken: token,\n bundleTrust: () => webCompositions?.shellTrust(),\n onNotice: notice,\n forward: async (request) => {\n if (!cockpit || !attachToken)\n return Response.json({ error: 'The headless server is not ready.' }, { status: 503 });\n const from = new URL(request.url);\n const headers = new Headers(request.headers);\n headers.set('x-doompi-token', attachToken);\n return fetch(\n new URL(`${from.pathname}${from.search}`, cockpit.url),\n new Request(request, { headers, redirect: 'manual' }),\n );\n },\n connectProtocol: (pathname) => {\n if (!cockpit || !attachToken) throw new Error('The headless protocol listener is not ready.');\n const url = new URL(pathname, cockpit.url);\n url.protocol = 'ws:';\n return new WebSocket(url, { headers: { 'x-doompi-token': attachToken } });\n },\n });\n await hub.mountFacets(globalBundle.facets, {\n ...sharedApiContext,\n scope: 'global',\n remoteControl: { fetch: (request: Request) => remoteRuntime!.fetchLocal(request) },\n });\n webCompositions.publish(\n { scope: 'global' },\n readSyncRegistration(globalRoot, homeDirectory)!,\n hub.channelTypes(),\n );\n const admissions = new Map<string, Promise<{ id: string; root: string; available: boolean }>>();\n admitWorkspace = async (from) => {\n const root = fs.realpathSync(findRepositoryRoot(from));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n const existing = hub.workspaces().find((workspace) => workspace.id === id);\n if (existing !== undefined && existing.available !== false) return { ...existing, available: true };\n const pending = admissions.get(id);\n if (pending) return pending;\n const wasRemembered = workspaces.list().some((workspace) => workspace.id === id);\n if (!wasRemembered) workspaces.add({ id, root });\n hub.registerWorkspace({ id, root, available: false });\n const admission = (async () => {\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: root };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n await syncWorkspace(root, syncEnvironment);\n const bundle = await loadComposition(root, 'workspace');\n await hub.mountFacets(bundle.facets, {\n ...sharedApiContext,\n scope: 'workspace',\n workspaceId: id,\n workspaceRoot: root,\n cwd: root,\n resolveRepository: (requestedId) => (requestedId === id ? root : undefined),\n });\n webCompositions?.publish(\n { scope: 'workspace', workspaceId: id },\n readSyncRegistration(root, homeDirectory)!,\n hub.channelTypes(),\n );\n return { id, root, available: true };\n })();\n admissions.set(id, admission);\n try {\n return await admission;\n } catch (error) {\n if (!wasRemembered) {\n await hub.removeWorkspace(id);\n workspaces.remove(id);\n }\n throw error;\n } finally {\n admissions.delete(id);\n }\n };\n for (const record of openSessions.list()) {\n if (workspaces.list().some((workspace) => workspace.id === record.workspaceId)) continue;\n try {\n const root = fs.realpathSync(findRepositoryRoot(record.cwd));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (id === record.workspaceId) workspaces.add({ id, root });\n else\n notice(\n `Session '${record.sessionId}' no longer resolves to its recorded workspace; skipping registration.`,\n );\n } catch (error) {\n notice(\n `Session '${record.sessionId}' workspace could not be registered: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n for (const workspace of workspaces.list()) {\n hub.registerWorkspace({ ...workspace, available: false });\n try {\n const root = fs.realpathSync(findRepositoryRoot(workspace.root));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (root !== workspace.root || id !== workspace.id) {\n notice(\n `Workspace '${workspace.root}' no longer resolves to its recorded identity; leaving it unavailable.`,\n );\n continue;\n }\n await admitWorkspace(workspace.root);\n } catch (error) {\n notice(\n `Workspace '${workspace.root}' could not be restored: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n const sessionHostOptions = (\n context: Awaited<ReturnType<typeof buildHarnessContext>>,\n bundle: Awaited<ReturnType<typeof loadServerBundle>>,\n mcpBundle: LoadedMcpBundle,\n identity: {\n sessionId: string;\n sessionName: string;\n parentSessionId?: string;\n sessionProvenance?: string;\n },\n ): HeadlessSessionHostOptions => {\n const policyOptions = context.options;\n const sessionSelection = {\n root: policyOptions.repoRoot,\n majorMode: policyOptions.majorMode,\n activeLayers: context.selectedLayers,\n domains: policyOptions.domains,\n profile: context.profile,\n state: { 'minor-mode': [] },\n };\n return {\n cwd: policyOptions.cwd,\n repoRoot: policyOptions.repoRoot,\n sessionId: identity.sessionId,\n workspaceId: resolveSyncLocation(policyOptions.repoRoot, homeDirectory).identity.worktreeId,\n sessionName: identity.sessionName,\n webComposition: webCompositions?.publish(\n { scope: 'session', sessionId: identity.sessionId },\n readSyncRegistration(policyOptions.repoRoot, homeDirectory)!,\n hub.channelTypes(),\n ),\n ...(identity.parentSessionId === undefined ? {} : { parentSessionId: identity.parentSessionId }),\n ...(identity.sessionProvenance === undefined ? {} : { sessionProvenance: identity.sessionProvenance }),\n agentArgs: policyOptions.piArgs,\n environment: Object.freeze({ ...context.environment }),\n selection: sessionSelection,\n selectionOverrides: (['majorMode', 'domains', 'profile'] as const).filter((axis) => {\n const flag = axis === 'majorMode' ? '--major-mode' : `--${axis}`;\n return (\n identity.sessionId === resolved.identity.sessionId &&\n resolved.agentArgs.some((arg) => arg === flag || arg.startsWith(`${flag}=`))\n );\n }),\n inheritedSelection: () => {\n const environment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete environment[key];\n const defaults = resolveHarnessOptions({\n args: ['--cwd', policyOptions.cwd],\n cwd: policyOptions.cwd,\n environment,\n });\n return { majorMode: defaults.majorMode, domains: defaults.domains, profile: defaults.profile };\n },\n candidates: bundle.descriptor.entries,\n mcpPlugins: mcpBundle.plugins,\n resolveSelection: (requested) => {\n const config = loadMajorModesConfig(policyOptions.repoRoot, policyOptions.homeDirectory);\n return {\n ...requested,\n activeLayers: filterHookDisabledLayers(\n config,\n resolveLayers(config, requested.majorMode),\n policyOptions.hooks,\n ),\n };\n },\n onNotice: notice,\n };\n };\n\n mountSessionApis = (sessionOptions, host) =>\n serveSessionApis({\n sessionId: sessionOptions.sessionId,\n cwd: sessionOptions.cwd,\n environment: sessionOptions.environment,\n directEvents: hub.directEvents,\n hubToken: token,\n sessionService: hub.sessionService,\n pluginRegistry: hub.pluginRegistry,\n apis: [],\n facets: pendingSessions.get(sessionOptions.sessionId)?.bundle.facets ?? [],\n workspaceId: sessionOptions.workspaceId,\n workspaceRoot: sessionOptions.repoRoot,\n homeDirectory,\n mountChannel: (channel) => {\n const dispose = hub.registerChannel(channel, { scope: 'session', sessionId: sessionOptions.sessionId });\n return { mounted: true, dispose };\n },\n prepareFacets: host.prepareFacets,\n activateFacets: host.activateFacets,\n canDispatch: host.canDispatch,\n telemetry,\n onNotice: notice,\n });\n\n requestSessionApi = async (scope, request) => {\n const session = hub.session(scope.sessionId);\n const artifacts = sessionArtifacts.get(scope.sessionId);\n if (session === undefined || session.cwd !== scope.cwd || artifacts === undefined)\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(request.basePath))\n return Response.json({ error: 'Invalid session API base path.' }, { status: 400 });\n if (!request.path.startsWith('/') || request.path.startsWith('//') || request.path.includes('#'))\n return Response.json({ error: 'Invalid session API path.' }, { status: 400 });\n const body = request.body === null || request.body === undefined ? undefined : request.body;\n return artifacts.apis.request(\n new Request(`http://doompi.local/api/plugins/${request.basePath}${request.path}`, {\n method: request.method,\n headers: request.headers,\n ...(body === undefined ? {} : { body }),\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n }),\n );\n };\n\n if (!options.noSession) {\n harnessContext = await buildHarnessContext(\n resolveHarnessOptions({ args: resolved.agentArgs, cwd: baseCwd, environment: baseEnvironment }),\n harnessTelemetry,\n );\n const activeHarnessContext = harnessContext;\n try {\n await admitWorkspace(harnessContext.options.repoRoot);\n const initialBundle = await loadComposition(harnessContext.options.repoRoot, 'session', {\n root: harnessContext.options.repoRoot,\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n const initialMcpBundle = await loadSessionMcp(harnessContext.options.repoRoot, {\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n pendingSessions.set(resolved.identity.sessionId, {\n cleanup: () => activeHarnessContext.cleanup(),\n bundle: initialBundle,\n mcpBundle: initialMcpBundle,\n });\n await hub.create(sessionHostOptions(harnessContext, initialBundle, initialMcpBundle, resolved.identity));\n } catch (error) {\n pendingSessions.delete(resolved.identity.sessionId);\n await activeHarnessContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n await bounded(harnessTelemetry.flush(), 'initial composition telemetry flush', notice);\n }\n\n openSession = async (request, sessionId) => {\n const identity = {\n sessionId: sessionId ?? crypto.randomUUID(),\n sessionName: request.name,\n parentSessionId: request.parentSessionId,\n sessionProvenance: request.sessionProvenance,\n };\n const childIdentity = resolveSessionIdentity([], identity);\n const childEnvironment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete childEnvironment[key];\n const childContext = await buildHarnessContext(\n resolveHarnessOptions({\n args: ['--cwd', request.cwd, ...childIdentity.agentArgs],\n cwd: request.cwd,\n environment: childEnvironment,\n }),\n harnessTelemetry,\n );\n try {\n await admitWorkspace(childContext.options.repoRoot);\n const bundle = await loadComposition(childContext.options.repoRoot, 'session', {\n root: childContext.options.repoRoot,\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n pendingSessions.set(identity.sessionId, { cleanup: () => childContext.cleanup(), bundle, mcpBundle });\n const created = await hub.create(sessionHostOptions(childContext, bundle, mcpBundle, identity));\n // Recorded only once the session is live, and only with a workspace,\n // because a record the revive route cannot address is a rail card that\n // never wakes.\n if (created.workspaceId !== undefined) {\n openSessions.add({\n sessionId: created.id,\n workspaceId: created.workspaceId,\n cwd: created.cwd,\n name: created.name,\n createdAt: created.createdAt,\n ...(created.parentSessionId === undefined ? {} : { parentSessionId: created.parentSessionId }),\n ...(created.sessionProvenance === undefined ? {} : { sessionProvenance: created.sessionProvenance }),\n });\n }\n return { sessionId: identity.sessionId, cwd: childContext.options.cwd };\n } catch (error) {\n pendingSessions.delete(identity.sessionId);\n await childContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n };\n });\n\n const workspaceResumes = new Map<string, Promise<string>>();\n cockpit = await serveHeadlessServer({\n port: options.webPort,\n headlessHub: hub,\n token: attachToken,\n sessionMcpPublicOrigin: () => remoteRuntime?.remote.publicOrigin(),\n sessionMcpPublicOriginRevision: () => remoteRuntime?.remote.publicOriginRevision() ?? 0,\n workspaceHistory: (workspaceId) => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n return listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n resumeWorkspaceSession: async (workspaceId, targetSessionId) => {\n const key = `${workspaceId}\\0${targetSessionId}`;\n const pending = workspaceResumes.get(key);\n if (pending) return pending;\n const resume = (async () => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n const saved = await listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await openSession({ cwd: workspaceRoot, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n })();\n workspaceResumes.set(key, resume);\n try {\n return await resume;\n } finally {\n workspaceResumes.delete(key);\n }\n },\n sessionHistory: (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n return listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n readDormantTranscript: (record, request, context) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === record.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Saved transcript unavailable.');\n return readSqliteTranscript(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions', `${record.sessionId}.sqlite`),\n request,\n context,\n { sessionId: record.sessionId, workspaceRoot },\n );\n },\n restartSession: async (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: workspaceRoot };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n try {\n await syncWorkspace(workspaceRoot, syncEnvironment);\n } catch (error) {\n notice(`Workspace sync failed before restart: ${error instanceof Error ? error.message : String(error)}`);\n throw new Error('Workspace sync failed; the session is still running.', { cause: error });\n }\n await hub.closeSession(session.id);\n await openSession({ cwd: session.cwd, name: session.name }, session.id);\n },\n resumeSession: async (session, targetSessionId) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const saved = await listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await hub.closeSession(session.id);\n await openSession({ cwd: session.cwd, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n },\n dormantSessions: () => openSessions.list(),\n removeDormantSession: (record: OpenSessionRecord) => openSessions.remove(record.sessionId),\n reviveSession: async (record: OpenSessionRecord) => {\n // A failed wake may be transient, for example while another server still\n // owns the journal. Keep the record so the user can retry after resolving\n // the conflict instead of losing the session from the cockpit.\n await openSession(\n {\n cwd: record.cwd,\n name: record.name,\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n },\n record.sessionId,\n );\n },\n requestAsset: (request) => webCompositions?.request(request) ?? Promise.resolve(undefined),\n compositions: () => ({\n global: webCompositions?.get({ scope: 'global' }),\n publicKey: webCompositions?.publicKey(),\n shell: webCompositions?.shellTrust(),\n workspaces: hub.workspaces().map((workspace) => ({\n ...workspace,\n webComposition: webCompositions?.get({ scope: 'workspace', workspaceId: workspace.id }),\n })),\n }),\n telemetry,\n onNotice: notice,\n });\n notice(`protocol on ${cockpit.url}/api/ws`);\n let resolveShutdown!: (exitCode: number) => void;\n const shutdown = new Promise<number>((resolve) => {\n resolveShutdown = resolve;\n });\n const stop = (): void => resolveShutdown(0);\n signal.addEventListener('abort', stop, { once: true });\n if (signal.aborted) stop();\n try {\n return await shutdown;\n } finally {\n signal.removeEventListener('abort', stop);\n }\n } finally {\n shuttingDown = true;\n clearInterval(eventLoopMonitor);\n await bounded(telemetry.recordEvent('doompi_server.shutdown'), 'shutdown telemetry', notice);\n await Promise.allSettled([cockpit?.close()]);\n await bounded(remoteRuntime?.close() ?? Promise.resolve(), 'remote control shutdown', notice);\n try {\n await hub.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n try {\n await sessionManager.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n webCompositions?.close();\n const pendingCleanups = [...pendingSessions.values()].map((setup) => setup.cleanup());\n pendingSessions.clear();\n await Promise.allSettled(pendingCleanups);\n await bounded(harnessTelemetry.flush(), 'harness telemetry flush', notice);\n await bounded(harnessTelemetry.shutdown(), 'harness telemetry shutdown', notice);\n await bounded(telemetry.flush(), 'server telemetry flush', notice);\n await bounded(telemetry.shutdown(), 'server telemetry shutdown', notice);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.cjs","names":["createServerTelemetry","path","piAgentDirectory","createWorkspaceRegistry","createOpenSessionRegistry","createHarnessTelemetry","createHeadlessSessionManager","publishHeadlessSelectionStatus","readMinorModeCatalog","createHeadlessHub","fs","resolveSessionIdentity","crypto","os","globalDoomConfigDirectory","createWebCompositions","readSyncRegistration","resolveServerBundleSource","loadMajorModesConfig","resolveLayers","loadServerBundle","loadMcpBundle","readSyncDrift","readSyncState","createRemoteRuntime","WebSocket","findRepositoryRoot","resolveSyncLocation","HARNESS_STATE_POINTER","HARNESS_STATE_KEYS","filterHookDisabledLayers","serveSessionApis","buildHarnessContext","serveHeadlessServer","listSavedSessions","readSqliteTranscript"],"sources":["../../../src/builders/server/runtime.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { globalDoomConfigDirectory } from '@agimon-ai/doompi-config/config';\nimport { filterHookDisabledLayers, loadMajorModesConfig, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { createHeadlessHub, type HeadlessHub } from '@agimon-ai/doompi-core/headless-hub';\nimport { serveHeadlessServer } from '@agimon-ai/doompi-core/headless-server';\nimport type { HeadlessSessionHost, HeadlessSessionHostOptions } from '@agimon-ai/doompi-core/headless-session-host';\nimport { createHeadlessSessionManager } from '@agimon-ai/doompi-core/headless-session-manager';\nimport {\n createOpenSessionRegistry,\n createWorkspaceRegistry,\n listSavedSessions,\n readSqliteTranscript,\n} from '@agimon-ai/doompi-core/history';\nimport type { OpenSessionRecord } from '@agimon-ai/doompi-core/history';\nimport type {\n DoomHubSessionApiRequest,\n DoomHubSessionCreateRequest,\n DoomHubSessionScope,\n} from '@agimon-ai/doompi-core/hub-channel';\nimport { loadMcpBundle, type LoadedMcpBundle } from '@agimon-ai/doompi-core/mcp-facet';\nimport { serveSessionApis, type PackageApiServer } from '@agimon-ai/doompi-core/package-api-server';\nimport { piAgentDirectory } from '@agimon-ai/doompi-core/pi-settings';\nimport { createRemoteRuntime, type RemoteRuntime } from '@agimon-ai/doompi-core/remote-runtime';\nimport type { HeadlessSessionManager } from '@agimon-ai/doompi-core/runtime-headless-session-manager';\nimport { createHarnessTelemetry } from '@agimon-ai/doompi-core/runtime-log-sink-telemetry';\nimport { loadServerBundle, resolveServerBundleSource } from '@agimon-ai/doompi-core/server-facet';\nimport { createServerTelemetry } from '@agimon-ai/doompi-core/server-telemetry';\nimport { resolveSyncLocation } from '@agimon-ai/doompi-core/sync-location';\nimport { readSyncRegistration } from '@agimon-ai/doompi-core/sync-registration';\nimport { createWebCompositions } from '@agimon-ai/doompi-core/web-compositions';\nimport { readMinorModeCatalog } from '@agimon-ai/doompi-minor-mode';\nimport WebSocket from 'ws';\n\nimport { HARNESS_STATE_KEYS, HARNESS_STATE_POINTER } from '../../composition/harnessState';\nimport { findRepositoryRoot } from '../../composition/repository';\nimport { readSyncDrift } from '../../composition/syncDrift';\nimport { readSyncState } from '../../composition/syncState';\nimport { buildHarnessContext } from '../cli/harnessContext';\nimport { publishHeadlessSelectionStatus } from './selectionStatus';\nimport { resolveSessionIdentity } from './sessionArguments';\nimport type { ServeOptions, ServerRuntimeEnvironment } from './types';\nconst TELEMETRY_SHUTDOWN_TIMEOUT_MS = 2_000;\n\nasync function bounded(operation: Promise<unknown>, label: string, notice: (message: string) => void): Promise<void> {\n let timeout: NodeJS.Timeout | undefined;\n try {\n await Promise.race([\n operation,\n new Promise<void>((resolve) => {\n timeout = setTimeout(resolve, TELEMETRY_SHUTDOWN_TIMEOUT_MS);\n }),\n ]);\n } catch (error) {\n notice(`${label} failed: ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function runServerRuntime(options: ServeOptions, runtime: ServerRuntimeEnvironment): Promise<number> {\n const { cwd: baseCwd, environment: baseEnvironment, notice, resolveHarnessOptions, signal, syncWorkspace } = runtime;\n const telemetry = createServerTelemetry({ cwd: baseCwd, env: baseEnvironment, warn: notice });\n const serverDirectory = path.join(piAgentDirectory(baseEnvironment), 'server');\n const workspaces = createWorkspaceRegistry({ directory: serverDirectory, onNotice: notice });\n // Beside the journals it names, because a record pointing at a sessions\n // directory it is not stored next to is a record that can outlive its target.\n const openSessions = createOpenSessionRegistry({\n directory: serverDirectory,\n onNotice: notice,\n });\n let nextEventLoopTick = performance.now() + 1_000;\n const eventLoopMonitor = setInterval(() => {\n const now = performance.now();\n const delay = Math.max(0, now - nextEventLoopTick);\n nextEventLoopTick = now + 1_000;\n if (delay >= 100)\n void telemetry\n .recordEvent('doompi_server.event_loop_delay', { duration_ms: Math.round(delay) })\n .catch((error: unknown) => notice(`event loop telemetry failed: ${String(error)}`));\n }, 1_000);\n eventLoopMonitor.unref();\n const harnessTelemetry = createHarnessTelemetry({\n cwd: baseCwd,\n env: baseEnvironment,\n warn: notice,\n deferSpans: true,\n });\n const baseSessionManager = createHeadlessSessionManager({\n publishSelectionStatus: publishHeadlessSelectionStatus,\n contextGroups: (context) =>\n (readMinorModeCatalog(context)?.list() ?? [])\n .filter(({ state }) => state.activation === 'active')\n .map(({ descriptor }) => ({ id: descriptor.id, label: descriptor.label, kind: 'minor' })),\n });\n type SessionSetup = {\n cleanup: () => Promise<void>;\n bundle: Awaited<ReturnType<typeof loadServerBundle>>;\n mcpBundle: LoadedMcpBundle;\n };\n type SessionArtifacts = SessionSetup & { apis: PackageApiServer };\n const pendingSessions = new Map<string, SessionSetup>();\n const sessionArtifacts = new Map<string, SessionArtifacts>();\n let mountSessionApis:\n | ((options: HeadlessSessionHostOptions, host: HeadlessSessionHost) => Promise<PackageApiServer>)\n | undefined;\n /**\n * Shutdown runs every session through the same close path a user-initiated\n * close uses, so without this the registry would be emptied by the very event\n * it exists to survive.\n */\n let shuttingDown = false;\n\n const closeManagedSession = async (sessionId: string): Promise<void> => {\n if (!shuttingDown) openSessions.remove(sessionId);\n const artifacts = sessionArtifacts.get(sessionId);\n sessionArtifacts.delete(sessionId);\n webCompositions?.remove({ scope: 'session', sessionId });\n const failures: unknown[] = [];\n try {\n await artifacts?.apis.close();\n } catch (error) {\n failures.push(error);\n }\n try {\n await artifacts?.cleanup();\n } catch (error) {\n failures.push(error);\n }\n try {\n await baseSessionManager.closeSession(sessionId);\n } catch (error) {\n failures.push(error);\n }\n if (failures.length > 0) throw new AggregateError(failures, `Session '${sessionId}' shutdown failed`);\n };\n\n const sessionManager: HeadlessSessionManager = {\n async create(sessionOptions) {\n const setup = pendingSessions.get(sessionOptions.sessionId);\n let host: HeadlessSessionHost;\n try {\n host = await baseSessionManager.create(sessionOptions);\n } catch (error) {\n if (setup !== undefined && pendingSessions.delete(sessionOptions.sessionId))\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n if (setup === undefined || mountSessionApis === undefined) return host;\n try {\n const apis = await mountSessionApis(sessionOptions, host);\n pendingSessions.delete(sessionOptions.sessionId);\n sessionArtifacts.set(sessionOptions.sessionId, { ...setup, apis });\n return host;\n } catch (error) {\n pendingSessions.delete(sessionOptions.sessionId);\n await baseSessionManager\n .closeSession(sessionOptions.sessionId)\n .catch((closeError: unknown) => notice(String(closeError)));\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n },\n get: (sessionId) => baseSessionManager.get(sessionId),\n sessions: () => baseSessionManager.sessions(),\n closeSession: closeManagedSession,\n async close() {\n const ids = baseSessionManager.sessions().map((session) => session.runtime.sessionId);\n const outcomes = await Promise.allSettled(ids.map((id) => closeManagedSession(id)));\n const failures = outcomes\n .filter((outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected')\n .map((outcome) => outcome.reason);\n if (failures.length > 0) throw new AggregateError(failures, 'Headless session shutdown failed');\n },\n };\n\n let requestSessionApi: (\n scope: DoomHubSessionScope,\n request: DoomHubSessionApiRequest,\n ) => Promise<Response> = async () => Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n let openSession: (\n request: DoomHubSessionCreateRequest,\n sessionId?: string,\n ) => Promise<DoomHubSessionScope> = async () => {\n throw new Error('The cockpit session service is not ready.');\n };\n let admitWorkspace: (root: string) => Promise<{ id: string; root: string; available: boolean }> = async () => {\n throw new Error('Workspace admission is not ready.');\n };\n let hub!: HeadlessHub;\n hub = createHeadlessHub({\n manager: sessionManager,\n admitWorkspace: (root) => admitWorkspace(root),\n onWorkspaceRemoved: (workspaceId) => {\n workspaces.remove(workspaceId);\n webCompositions?.remove({ scope: 'workspace', workspaceId });\n },\n createSession: (request) => openSession(request),\n sessionReservations: {\n read(id, parentSessionId) {\n if (!cockpit) throw new Error('Session setup is not ready.');\n return cockpit.sessionReservations.read(id, parentSessionId);\n },\n async prepare(id, parentSessionId, cwd) {\n if (!cockpit) throw new Error('Session setup is not ready.');\n return cockpit.sessionReservations.prepare(id, parentSessionId, cwd);\n },\n async complete(id, parentSessionId) {\n if (!cockpit) throw new Error('Session setup is not ready.');\n return cockpit.sessionReservations.complete(id, parentSessionId);\n },\n },\n onNotice: notice,\n hubToken: () => attachToken,\n requestSessionApi: (scope, request) => requestSessionApi(scope, request),\n });\n let harnessContext: Awaited<ReturnType<typeof buildHarnessContext>> | undefined;\n let cockpit: Awaited<ReturnType<typeof serveHeadlessServer>> | undefined;\n let remoteRuntime: RemoteRuntime | undefined;\n let attachToken: string | undefined;\n let webCompositions: ReturnType<typeof createWebCompositions> | undefined;\n\n try {\n await telemetry.runInSpan('doompi_server.startup', {}, async () => {\n const token = fs.readFileSync(options.tokenFile, 'utf8').trim();\n if (!token) throw new Error('The attach token file is empty.');\n attachToken = token;\n\n const resolved = resolveSessionIdentity(options.agentArgs, {\n sessionId: options.sessionId ?? crypto.randomUUID(),\n sessionName: options.sessionName,\n });\n\n const homeDirectory = baseEnvironment.HOME ?? os.homedir();\n const globalRoot = globalDoomConfigDirectory(homeDirectory);\n webCompositions = createWebCompositions(path.join(globalRoot, 'server'), notice);\n const loadComposition = async (\n root: string,\n scope: 'global' | 'workspace' | 'session',\n selection?: { root: string; majorMode: string; activeLayers: string[] },\n ) => {\n const registration = readSyncRegistration(root, homeDirectory);\n const source = resolveServerBundleSource({ registration });\n if (source.kind !== 'descriptor')\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening it.`);\n const selected =\n selection ??\n (() => {\n const config = loadMajorModesConfig(root, homeDirectory);\n const majorMode = config.defaultMajorMode;\n return { root, majorMode, activeLayers: resolveLayers(config, majorMode) };\n })();\n return loadServerBundle(scope, {\n ...source,\n ...selected,\n retainCandidates: scope === 'session',\n onNotice: notice,\n });\n };\n const loadSessionMcp = async (\n root: string,\n selection: { majorMode: string; activeLayers: readonly string[] },\n ): Promise<LoadedMcpBundle> => {\n const registration = readSyncRegistration(root, homeDirectory);\n if (registration?.mcpBundle === undefined)\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening its MCP runtime.`);\n return loadMcpBundle({\n directory: path.dirname(registration.mcpBundle.path),\n generation: registration.generation,\n fingerprint: registration.mcpBundle.fingerprint,\n descriptorSha256: registration.mcpBundle.sha256,\n majorMode: selection.majorMode,\n activeLayers: selection.activeLayers,\n retainCandidates: true,\n onNotice: notice,\n });\n };\n const sharedApiContext = {\n homeDirectory,\n environment: baseEnvironment,\n hubToken: token,\n sessionService: hub.sessionService,\n directEvents: hub.directEvents,\n repositories: () =>\n hub.workspaces().map((workspace) => ({\n id: workspace.id,\n path: workspace.root,\n name: workspace.root.split('/').at(-1) ?? workspace.id,\n active: hub.snapshot().some((session) => session.workspaceId === workspace.id),\n })),\n resolveRepository: (id: string) => hub.workspaces().find((workspace) => workspace.id === id)?.root,\n readRepositorySync: (id: string) => {\n const root = hub.workspaces().find((workspace) => workspace.id === id)?.root;\n if (!root) return undefined;\n const drift = readSyncDrift({ repoRoot: root, homeDirectory, requireWebBundle: true });\n const state = readSyncState(root, homeDirectory);\n return { ...drift, mcpProjection: state?.fileState.mcpProjection };\n },\n onNotice: notice,\n };\n const globalBundle = await loadComposition(globalRoot, 'global');\n webCompositions.publishShell(readSyncRegistration(globalRoot, homeDirectory)!);\n remoteRuntime = createRemoteRuntime({\n homeDirectory,\n registrationToken: token,\n bundleTrust: () => webCompositions?.shellTrust(),\n onNotice: notice,\n forward: async (request) => {\n if (!cockpit || !attachToken)\n return Response.json({ error: 'The headless server is not ready.' }, { status: 503 });\n const from = new URL(request.url);\n const headers = new Headers(request.headers);\n headers.set('x-doompi-token', attachToken);\n return fetch(\n new URL(`${from.pathname}${from.search}`, cockpit.url),\n new Request(request, { headers, redirect: 'manual' }),\n );\n },\n connectProtocol: (pathname) => {\n if (!cockpit || !attachToken) throw new Error('The headless protocol listener is not ready.');\n const url = new URL(pathname, cockpit.url);\n url.protocol = 'ws:';\n return new WebSocket(url, { headers: { 'x-doompi-token': attachToken } });\n },\n });\n await hub.mountFacets(globalBundle.facets, {\n ...sharedApiContext,\n scope: 'global',\n remoteControl: { fetch: (request: Request) => remoteRuntime!.fetchLocal(request) },\n });\n webCompositions.publish(\n { scope: 'global' },\n readSyncRegistration(globalRoot, homeDirectory)!,\n hub.channelTypes(),\n );\n const admissions = new Map<string, Promise<{ id: string; root: string; available: boolean }>>();\n admitWorkspace = async (from) => {\n const root = fs.realpathSync(findRepositoryRoot(from));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n const existing = hub.workspaces().find((workspace) => workspace.id === id);\n if (existing !== undefined && existing.available !== false) return { ...existing, available: true };\n const pending = admissions.get(id);\n if (pending) return pending;\n const wasRemembered = workspaces.list().some((workspace) => workspace.id === id);\n if (!wasRemembered) workspaces.add({ id, root });\n hub.registerWorkspace({ id, root, available: false });\n const admission = (async () => {\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: root };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n await syncWorkspace(root, syncEnvironment);\n const bundle = await loadComposition(root, 'workspace');\n await hub.mountFacets(bundle.facets, {\n ...sharedApiContext,\n scope: 'workspace',\n workspaceId: id,\n workspaceRoot: root,\n cwd: root,\n resolveRepository: (requestedId) => (requestedId === id ? root : undefined),\n });\n webCompositions?.publish(\n { scope: 'workspace', workspaceId: id },\n readSyncRegistration(root, homeDirectory)!,\n hub.channelTypes(),\n );\n return { id, root, available: true };\n })();\n admissions.set(id, admission);\n try {\n return await admission;\n } catch (error) {\n if (!wasRemembered) {\n await hub.removeWorkspace(id);\n workspaces.remove(id);\n }\n throw error;\n } finally {\n admissions.delete(id);\n }\n };\n for (const record of openSessions.list()) {\n if (workspaces.list().some((workspace) => workspace.id === record.workspaceId)) continue;\n try {\n const root = fs.realpathSync(findRepositoryRoot(record.cwd));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (id === record.workspaceId) workspaces.add({ id, root });\n else\n notice(\n `Session '${record.sessionId}' no longer resolves to its recorded workspace; skipping registration.`,\n );\n } catch (error) {\n notice(\n `Session '${record.sessionId}' workspace could not be registered: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n for (const workspace of workspaces.list()) {\n hub.registerWorkspace({ ...workspace, available: false });\n try {\n const root = fs.realpathSync(findRepositoryRoot(workspace.root));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (root !== workspace.root || id !== workspace.id) {\n notice(\n `Workspace '${workspace.root}' no longer resolves to its recorded identity; leaving it unavailable.`,\n );\n continue;\n }\n await admitWorkspace(workspace.root);\n } catch (error) {\n notice(\n `Workspace '${workspace.root}' could not be restored: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n const sessionHostOptions = (\n context: Awaited<ReturnType<typeof buildHarnessContext>>,\n bundle: Awaited<ReturnType<typeof loadServerBundle>>,\n mcpBundle: LoadedMcpBundle,\n identity: {\n sessionId: string;\n sessionName: string;\n parentSessionId?: string;\n sessionProvenance?: string;\n },\n workspaceId?: string,\n ): HeadlessSessionHostOptions => {\n const policyOptions = context.options;\n const sessionSelection = {\n root: policyOptions.repoRoot,\n majorMode: policyOptions.majorMode,\n activeLayers: context.selectedLayers,\n domains: policyOptions.domains,\n profile: context.profile,\n state: { 'minor-mode': [] },\n };\n return {\n cwd: policyOptions.cwd,\n repoRoot: policyOptions.repoRoot,\n sessionId: identity.sessionId,\n workspaceId: workspaceId ?? resolveSyncLocation(policyOptions.repoRoot, homeDirectory).identity.worktreeId,\n sessionName: identity.sessionName,\n webComposition: webCompositions?.publish(\n { scope: 'session', sessionId: identity.sessionId },\n readSyncRegistration(policyOptions.repoRoot, homeDirectory)!,\n hub.channelTypes(),\n ),\n ...(identity.parentSessionId === undefined ? {} : { parentSessionId: identity.parentSessionId }),\n ...(identity.sessionProvenance === undefined ? {} : { sessionProvenance: identity.sessionProvenance }),\n agentArgs: policyOptions.piArgs,\n environment: Object.freeze({ ...context.environment }),\n selection: sessionSelection,\n selectionOverrides: (['majorMode', 'domains', 'profile'] as const).filter((axis) => {\n const flag = axis === 'majorMode' ? '--major-mode' : `--${axis}`;\n return (\n identity.sessionId === resolved.identity.sessionId &&\n resolved.agentArgs.some((arg) => arg === flag || arg.startsWith(`${flag}=`))\n );\n }),\n inheritedSelection: () => {\n const environment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete environment[key];\n const defaults = resolveHarnessOptions({\n args: ['--cwd', policyOptions.cwd],\n cwd: policyOptions.cwd,\n environment,\n });\n return { majorMode: defaults.majorMode, domains: defaults.domains, profile: defaults.profile };\n },\n candidates: bundle.descriptor.entries,\n mcpPlugins: mcpBundle.plugins,\n resolveSelection: (requested) => {\n const config = loadMajorModesConfig(policyOptions.repoRoot, policyOptions.homeDirectory);\n return {\n ...requested,\n activeLayers: filterHookDisabledLayers(\n config,\n resolveLayers(config, requested.majorMode),\n policyOptions.hooks,\n ),\n };\n },\n onNotice: notice,\n };\n };\n\n mountSessionApis = (sessionOptions, host) =>\n serveSessionApis({\n sessionId: sessionOptions.sessionId,\n cwd: sessionOptions.cwd,\n environment: sessionOptions.environment,\n directEvents: hub.directEvents,\n hubToken: token,\n sessionService: hub.sessionService,\n pluginRegistry: hub.pluginRegistry,\n apis: [],\n facets: pendingSessions.get(sessionOptions.sessionId)?.bundle.facets ?? [],\n workspaceId: sessionOptions.workspaceId,\n workspaceRoot: sessionOptions.repoRoot,\n homeDirectory,\n mountChannel: (channel) => {\n const dispose = hub.registerChannel(channel, { scope: 'session', sessionId: sessionOptions.sessionId });\n return { mounted: true, dispose };\n },\n prepareFacets: host.prepareFacets,\n activateFacets: host.activateFacets,\n canDispatch: host.canDispatch,\n telemetry,\n onNotice: notice,\n });\n\n requestSessionApi = async (scope, request) => {\n const session = hub.session(scope.sessionId);\n const artifacts = sessionArtifacts.get(scope.sessionId);\n if (session === undefined || session.cwd !== scope.cwd || artifacts === undefined)\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(request.basePath))\n return Response.json({ error: 'Invalid session API base path.' }, { status: 400 });\n if (!request.path.startsWith('/') || request.path.startsWith('//') || request.path.includes('#'))\n return Response.json({ error: 'Invalid session API path.' }, { status: 400 });\n const body = request.body === null || request.body === undefined ? undefined : request.body;\n return artifacts.apis.request(\n new Request(`http://doompi.local/api/plugins/${request.basePath}${request.path}`, {\n method: request.method,\n headers: request.headers,\n ...(body === undefined ? {} : { body }),\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n }),\n );\n };\n\n if (!options.noSession) {\n harnessContext = await buildHarnessContext(\n resolveHarnessOptions({ args: resolved.agentArgs, cwd: baseCwd, environment: baseEnvironment }),\n harnessTelemetry,\n );\n const activeHarnessContext = harnessContext;\n try {\n await admitWorkspace(harnessContext.options.repoRoot);\n const initialBundle = await loadComposition(harnessContext.options.repoRoot, 'session', {\n root: harnessContext.options.repoRoot,\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n const initialMcpBundle = await loadSessionMcp(harnessContext.options.repoRoot, {\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n pendingSessions.set(resolved.identity.sessionId, {\n cleanup: () => activeHarnessContext.cleanup(),\n bundle: initialBundle,\n mcpBundle: initialMcpBundle,\n });\n await hub.create(sessionHostOptions(harnessContext, initialBundle, initialMcpBundle, resolved.identity));\n } catch (error) {\n pendingSessions.delete(resolved.identity.sessionId);\n await activeHarnessContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n await bounded(harnessTelemetry.flush(), 'initial composition telemetry flush', notice);\n }\n\n const reservedOpens = new Map<string, Promise<DoomHubSessionScope>>();\n openSession = async (request, sessionId) => {\n request.signal?.throwIfAborted();\n if (request.reservationId !== undefined) {\n if (!request.parentSessionId || !cockpit) throw new Error('A reserved session requires its owning parent.');\n const prepared = await cockpit.sessionReservations.prepare(\n request.reservationId,\n request.parentSessionId,\n request.cwd,\n );\n if (sessionId !== undefined && sessionId !== prepared.sessionId)\n throw new Error('Reserved session identity cannot change.');\n sessionId = prepared.sessionId;\n const existing = hub.session(sessionId);\n if (existing) {\n if (existing.cwd !== prepared.cwd || existing.parentSessionId !== request.parentSessionId)\n throw new Error('Reserved session target does not match.');\n return { sessionId, cwd: existing.cwd, workspaceId: existing.workspaceId };\n }\n if (openSessions.list().some((record) => record.sessionId === sessionId))\n throw new Error('Resume the recorded session instead of recreating it.');\n const pending = reservedOpens.get(sessionId);\n if (pending) return pending;\n request = { ...request, cwd: prepared.cwd };\n }\n const identity = {\n sessionId: sessionId ?? crypto.randomUUID(),\n sessionName: request.name,\n parentSessionId: request.parentSessionId,\n sessionProvenance: request.sessionProvenance,\n };\n const inheritedWorkspaceId =\n request.sessionProvenance === 'worktree' && request.parentSessionId\n ? (hub.session(request.parentSessionId)?.workspaceId ??\n openSessions.list().find((record) => record.sessionId === request.parentSessionId)?.workspaceId)\n : undefined;\n if (request.sessionProvenance === 'worktree' && inheritedWorkspaceId === undefined)\n throw new Error('Worktree session requires its parent workspace.');\n const start = (async (): Promise<DoomHubSessionScope> => {\n const childIdentity = resolveSessionIdentity([], identity);\n const childEnvironment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete childEnvironment[key];\n const childContext = await buildHarnessContext(\n resolveHarnessOptions({\n args: ['--cwd', request.cwd, ...childIdentity.agentArgs],\n cwd: request.cwd,\n environment: childEnvironment,\n }),\n harnessTelemetry,\n );\n try {\n if (inheritedWorkspaceId === undefined) {\n await admitWorkspace(childContext.options.repoRoot);\n } else {\n const inheritedWorkspace = hub\n .workspaces()\n .find((workspace) => workspace.id === inheritedWorkspaceId && workspace.available !== false);\n if (inheritedWorkspace === undefined) throw new Error('Worktree parent workspace is unavailable.');\n const syncEnvironment: NodeJS.ProcessEnv = {\n ...baseEnvironment,\n DOOMPI_ROOT: childContext.options.repoRoot,\n };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)])\n delete syncEnvironment[key];\n await syncWorkspace(childContext.options.repoRoot, syncEnvironment);\n }\n const bundle = await loadComposition(childContext.options.repoRoot, 'session', {\n root: childContext.options.repoRoot,\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n request.signal?.throwIfAborted();\n pendingSessions.set(identity.sessionId, { cleanup: () => childContext.cleanup(), bundle, mcpBundle });\n const created = await hub.create(\n sessionHostOptions(childContext, bundle, mcpBundle, identity, inheritedWorkspaceId),\n );\n request.signal?.throwIfAborted();\n if (created.workspaceId !== undefined) {\n const saved = openSessions.add({\n sessionId: created.id,\n workspaceId: created.workspaceId,\n cwd: created.cwd,\n name: created.name,\n createdAt: created.createdAt,\n ...(created.parentSessionId === undefined ? {} : { parentSessionId: created.parentSessionId }),\n ...(created.sessionProvenance === undefined ? {} : { sessionProvenance: created.sessionProvenance }),\n });\n if (saved === false) throw new Error('The new session could not be durably recorded.');\n }\n return { sessionId: identity.sessionId, cwd: childContext.options.cwd, workspaceId: created.workspaceId };\n } catch (error) {\n if (hub.session(identity.sessionId)) await hub.closeSession(identity.sessionId);\n else {\n pendingSessions.delete(identity.sessionId);\n await childContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n }\n throw error;\n }\n })();\n if (request.reservationId !== undefined) reservedOpens.set(identity.sessionId, start);\n try {\n return await start;\n } finally {\n if (reservedOpens.get(identity.sessionId) === start) reservedOpens.delete(identity.sessionId);\n }\n };\n });\n\n const workspaceResumes = new Map<string, Promise<string>>();\n cockpit = await serveHeadlessServer({\n port: options.webPort,\n headlessHub: hub,\n token: attachToken,\n sessionMcpPublicOrigin: () => remoteRuntime?.remote.publicOrigin(),\n sessionMcpStateDir: serverDirectory,\n sessionMcpPublicOriginRevision: () => remoteRuntime?.remote.publicOriginRevision() ?? 0,\n isSessionPersisted: (sessionId, cwd) =>\n openSessions.list().some((record) => record.sessionId === sessionId && record.cwd === cwd),\n workspaceHistory: (workspaceId) => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n return listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n resumeWorkspaceSession: async (workspaceId, targetSessionId) => {\n const key = `${workspaceId}\\0${targetSessionId}`;\n const pending = workspaceResumes.get(key);\n if (pending) return pending;\n const resume = (async () => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n const saved = await listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await openSession({ cwd: workspaceRoot, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n })();\n workspaceResumes.set(key, resume);\n try {\n return await resume;\n } finally {\n workspaceResumes.delete(key);\n }\n },\n sessionHistory: (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n return listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n readDormantTranscript: (record, request, context) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === record.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Saved transcript unavailable.');\n return readSqliteTranscript(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions', `${record.sessionId}.sqlite`),\n request,\n context,\n { sessionId: record.sessionId, workspaceRoot },\n );\n },\n restartSession: async (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: workspaceRoot };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n try {\n await syncWorkspace(workspaceRoot, syncEnvironment);\n } catch (error) {\n notice(`Workspace sync failed before restart: ${error instanceof Error ? error.message : String(error)}`);\n throw new Error('Workspace sync failed; the session is still running.', { cause: error });\n }\n await hub.closeSession(session.id);\n await openSession(\n {\n cwd: session.cwd,\n name: session.name,\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n },\n session.id,\n );\n },\n resumeSession: async (session, targetSessionId) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const saved = await listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await hub.closeSession(session.id);\n await openSession({ cwd: session.cwd, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n },\n dormantSessions: () => openSessions.list(),\n removeDormantSession: (record: OpenSessionRecord) => openSessions.remove(record.sessionId),\n reviveSession: async (record: OpenSessionRecord) => {\n // A failed wake may be transient, for example while another server still\n // owns the journal. Keep the record so the user can retry after resolving\n // the conflict instead of losing the session from the cockpit.\n await openSession(\n {\n cwd: record.cwd,\n name: record.name,\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n },\n record.sessionId,\n );\n },\n requestAsset: (request) => webCompositions?.request(request) ?? Promise.resolve(undefined),\n compositions: () => ({\n global: webCompositions?.get({ scope: 'global' }),\n publicKey: webCompositions?.publicKey(),\n shell: webCompositions?.shellTrust(),\n workspaces: hub.workspaces().map((workspace) => ({\n ...workspace,\n webComposition: webCompositions?.get({ scope: 'workspace', workspaceId: workspace.id }),\n })),\n }),\n telemetry,\n onNotice: notice,\n });\n notice(`protocol on ${cockpit.url}/api/ws`);\n let resolveShutdown!: (exitCode: number) => void;\n const shutdown = new Promise<number>((resolve) => {\n resolveShutdown = resolve;\n });\n const stop = (): void => resolveShutdown(0);\n signal.addEventListener('abort', stop, { once: true });\n if (signal.aborted) stop();\n try {\n return await shutdown;\n } finally {\n signal.removeEventListener('abort', stop);\n }\n } finally {\n shuttingDown = true;\n clearInterval(eventLoopMonitor);\n await bounded(telemetry.recordEvent('doompi_server.shutdown'), 'shutdown telemetry', notice);\n await Promise.allSettled([cockpit?.close()]);\n await bounded(remoteRuntime?.close() ?? Promise.resolve(), 'remote control shutdown', notice);\n try {\n await hub.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n try {\n await sessionManager.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n webCompositions?.close();\n const pendingCleanups = [...pendingSessions.values()].map((setup) => setup.cleanup());\n pendingSessions.clear();\n await Promise.allSettled(pendingCleanups);\n await bounded(harnessTelemetry.flush(), 'harness telemetry flush', notice);\n await bounded(harnessTelemetry.shutdown(), 'harness telemetry shutdown', notice);\n await bounded(telemetry.flush(), 'server telemetry flush', notice);\n await bounded(telemetry.shutdown(), 'server telemetry shutdown', notice);\n }\n}\n"],"mappings":"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"}
|
|
@@ -168,6 +168,20 @@ async function runServerRuntime(options, runtime) {
|
|
|
168
168
|
});
|
|
169
169
|
},
|
|
170
170
|
createSession: (request) => openSession(request),
|
|
171
|
+
sessionReservations: {
|
|
172
|
+
read(id, parentSessionId) {
|
|
173
|
+
if (!cockpit) throw new Error("Session setup is not ready.");
|
|
174
|
+
return cockpit.sessionReservations.read(id, parentSessionId);
|
|
175
|
+
},
|
|
176
|
+
async prepare(id, parentSessionId, cwd) {
|
|
177
|
+
if (!cockpit) throw new Error("Session setup is not ready.");
|
|
178
|
+
return cockpit.sessionReservations.prepare(id, parentSessionId, cwd);
|
|
179
|
+
},
|
|
180
|
+
async complete(id, parentSessionId) {
|
|
181
|
+
if (!cockpit) throw new Error("Session setup is not ready.");
|
|
182
|
+
return cockpit.sessionReservations.complete(id, parentSessionId);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
171
185
|
onNotice: notice,
|
|
172
186
|
hubToken: () => attachToken,
|
|
173
187
|
requestSessionApi: (scope, request) => requestSessionApi(scope, request)
|
|
@@ -373,7 +387,7 @@ async function runServerRuntime(options, runtime) {
|
|
|
373
387
|
notice(`Workspace '${workspace.root}' could not be restored: ${error instanceof Error ? error.message : String(error)}`);
|
|
374
388
|
}
|
|
375
389
|
}
|
|
376
|
-
const sessionHostOptions = (context, bundle, mcpBundle, identity) => {
|
|
390
|
+
const sessionHostOptions = (context, bundle, mcpBundle, identity, workspaceId) => {
|
|
377
391
|
const policyOptions = context.options;
|
|
378
392
|
const sessionSelection = {
|
|
379
393
|
root: policyOptions.repoRoot,
|
|
@@ -387,7 +401,7 @@ async function runServerRuntime(options, runtime) {
|
|
|
387
401
|
cwd: policyOptions.cwd,
|
|
388
402
|
repoRoot: policyOptions.repoRoot,
|
|
389
403
|
sessionId: identity.sessionId,
|
|
390
|
-
workspaceId: resolveSyncLocation(policyOptions.repoRoot, homeDirectory).identity.worktreeId,
|
|
404
|
+
workspaceId: workspaceId ?? resolveSyncLocation(policyOptions.repoRoot, homeDirectory).identity.worktreeId,
|
|
391
405
|
sessionName: identity.sessionName,
|
|
392
406
|
webComposition: webCompositions?.publish({
|
|
393
407
|
scope: "session",
|
|
@@ -505,59 +519,110 @@ async function runServerRuntime(options, runtime) {
|
|
|
505
519
|
}
|
|
506
520
|
await bounded(harnessTelemetry.flush(), "initial composition telemetry flush", notice);
|
|
507
521
|
}
|
|
522
|
+
const reservedOpens = /* @__PURE__ */ new Map();
|
|
508
523
|
openSession = async (request, sessionId) => {
|
|
524
|
+
request.signal?.throwIfAborted();
|
|
525
|
+
if (request.reservationId !== void 0) {
|
|
526
|
+
if (!request.parentSessionId || !cockpit) throw new Error("A reserved session requires its owning parent.");
|
|
527
|
+
const prepared = await cockpit.sessionReservations.prepare(request.reservationId, request.parentSessionId, request.cwd);
|
|
528
|
+
if (sessionId !== void 0 && sessionId !== prepared.sessionId) throw new Error("Reserved session identity cannot change.");
|
|
529
|
+
sessionId = prepared.sessionId;
|
|
530
|
+
const existing = hub.session(sessionId);
|
|
531
|
+
if (existing) {
|
|
532
|
+
if (existing.cwd !== prepared.cwd || existing.parentSessionId !== request.parentSessionId) throw new Error("Reserved session target does not match.");
|
|
533
|
+
return {
|
|
534
|
+
sessionId,
|
|
535
|
+
cwd: existing.cwd,
|
|
536
|
+
workspaceId: existing.workspaceId
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
if (openSessions.list().some((record) => record.sessionId === sessionId)) throw new Error("Resume the recorded session instead of recreating it.");
|
|
540
|
+
const pending = reservedOpens.get(sessionId);
|
|
541
|
+
if (pending) return pending;
|
|
542
|
+
request = {
|
|
543
|
+
...request,
|
|
544
|
+
cwd: prepared.cwd
|
|
545
|
+
};
|
|
546
|
+
}
|
|
509
547
|
const identity = {
|
|
510
548
|
sessionId: sessionId ?? crypto.randomUUID(),
|
|
511
549
|
sessionName: request.name,
|
|
512
550
|
parentSessionId: request.parentSessionId,
|
|
513
551
|
sessionProvenance: request.sessionProvenance
|
|
514
552
|
};
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
553
|
+
const inheritedWorkspaceId = request.sessionProvenance === "worktree" && request.parentSessionId ? hub.session(request.parentSessionId)?.workspaceId ?? openSessions.list().find((record) => record.sessionId === request.parentSessionId)?.workspaceId : void 0;
|
|
554
|
+
if (request.sessionProvenance === "worktree" && inheritedWorkspaceId === void 0) throw new Error("Worktree session requires its parent workspace.");
|
|
555
|
+
const start = (async () => {
|
|
556
|
+
const childIdentity = resolveSessionIdentity([], identity);
|
|
557
|
+
const childEnvironment = { ...baseEnvironment };
|
|
558
|
+
for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete childEnvironment[key];
|
|
559
|
+
const childContext = await buildHarnessContext(resolveHarnessOptions({
|
|
560
|
+
args: [
|
|
561
|
+
"--cwd",
|
|
562
|
+
request.cwd,
|
|
563
|
+
...childIdentity.agentArgs
|
|
564
|
+
],
|
|
565
|
+
cwd: request.cwd,
|
|
566
|
+
environment: childEnvironment
|
|
567
|
+
}), harnessTelemetry);
|
|
568
|
+
try {
|
|
569
|
+
if (inheritedWorkspaceId === void 0) await admitWorkspace(childContext.options.repoRoot);
|
|
570
|
+
else {
|
|
571
|
+
if (hub.workspaces().find((workspace) => workspace.id === inheritedWorkspaceId && workspace.available !== false) === void 0) throw new Error("Worktree parent workspace is unavailable.");
|
|
572
|
+
const syncEnvironment = {
|
|
573
|
+
...baseEnvironment,
|
|
574
|
+
DOOMPI_ROOT: childContext.options.repoRoot
|
|
575
|
+
};
|
|
576
|
+
for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];
|
|
577
|
+
await syncWorkspace(childContext.options.repoRoot, syncEnvironment);
|
|
578
|
+
}
|
|
579
|
+
const bundle = await loadComposition(childContext.options.repoRoot, "session", {
|
|
580
|
+
root: childContext.options.repoRoot,
|
|
581
|
+
majorMode: childContext.options.majorMode,
|
|
582
|
+
activeLayers: childContext.selectedLayers
|
|
583
|
+
});
|
|
584
|
+
const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {
|
|
585
|
+
majorMode: childContext.options.majorMode,
|
|
586
|
+
activeLayers: childContext.selectedLayers
|
|
587
|
+
});
|
|
588
|
+
request.signal?.throwIfAborted();
|
|
589
|
+
pendingSessions.set(identity.sessionId, {
|
|
590
|
+
cleanup: () => childContext.cleanup(),
|
|
591
|
+
bundle,
|
|
592
|
+
mcpBundle
|
|
593
|
+
});
|
|
594
|
+
const created = await hub.create(sessionHostOptions(childContext, bundle, mcpBundle, identity, inheritedWorkspaceId));
|
|
595
|
+
request.signal?.throwIfAborted();
|
|
596
|
+
if (created.workspaceId !== void 0) {
|
|
597
|
+
if (openSessions.add({
|
|
598
|
+
sessionId: created.id,
|
|
599
|
+
workspaceId: created.workspaceId,
|
|
600
|
+
cwd: created.cwd,
|
|
601
|
+
name: created.name,
|
|
602
|
+
createdAt: created.createdAt,
|
|
603
|
+
...created.parentSessionId === void 0 ? {} : { parentSessionId: created.parentSessionId },
|
|
604
|
+
...created.sessionProvenance === void 0 ? {} : { sessionProvenance: created.sessionProvenance }
|
|
605
|
+
}) === false) throw new Error("The new session could not be durably recorded.");
|
|
606
|
+
}
|
|
607
|
+
return {
|
|
608
|
+
sessionId: identity.sessionId,
|
|
609
|
+
cwd: childContext.options.cwd,
|
|
610
|
+
workspaceId: created.workspaceId
|
|
611
|
+
};
|
|
612
|
+
} catch (error) {
|
|
613
|
+
if (hub.session(identity.sessionId)) await hub.closeSession(identity.sessionId);
|
|
614
|
+
else {
|
|
615
|
+
pendingSessions.delete(identity.sessionId);
|
|
616
|
+
await childContext.cleanup().catch((cleanupError) => notice(String(cleanupError)));
|
|
617
|
+
}
|
|
618
|
+
throw error;
|
|
619
|
+
}
|
|
620
|
+
})();
|
|
621
|
+
if (request.reservationId !== void 0) reservedOpens.set(identity.sessionId, start);
|
|
527
622
|
try {
|
|
528
|
-
await
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
majorMode: childContext.options.majorMode,
|
|
532
|
-
activeLayers: childContext.selectedLayers
|
|
533
|
-
});
|
|
534
|
-
const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {
|
|
535
|
-
majorMode: childContext.options.majorMode,
|
|
536
|
-
activeLayers: childContext.selectedLayers
|
|
537
|
-
});
|
|
538
|
-
pendingSessions.set(identity.sessionId, {
|
|
539
|
-
cleanup: () => childContext.cleanup(),
|
|
540
|
-
bundle,
|
|
541
|
-
mcpBundle
|
|
542
|
-
});
|
|
543
|
-
const created = await hub.create(sessionHostOptions(childContext, bundle, mcpBundle, identity));
|
|
544
|
-
if (created.workspaceId !== void 0) openSessions.add({
|
|
545
|
-
sessionId: created.id,
|
|
546
|
-
workspaceId: created.workspaceId,
|
|
547
|
-
cwd: created.cwd,
|
|
548
|
-
name: created.name,
|
|
549
|
-
createdAt: created.createdAt,
|
|
550
|
-
...created.parentSessionId === void 0 ? {} : { parentSessionId: created.parentSessionId },
|
|
551
|
-
...created.sessionProvenance === void 0 ? {} : { sessionProvenance: created.sessionProvenance }
|
|
552
|
-
});
|
|
553
|
-
return {
|
|
554
|
-
sessionId: identity.sessionId,
|
|
555
|
-
cwd: childContext.options.cwd
|
|
556
|
-
};
|
|
557
|
-
} catch (error) {
|
|
558
|
-
pendingSessions.delete(identity.sessionId);
|
|
559
|
-
await childContext.cleanup().catch((cleanupError) => notice(String(cleanupError)));
|
|
560
|
-
throw error;
|
|
623
|
+
return await start;
|
|
624
|
+
} finally {
|
|
625
|
+
if (reservedOpens.get(identity.sessionId) === start) reservedOpens.delete(identity.sessionId);
|
|
561
626
|
}
|
|
562
627
|
};
|
|
563
628
|
});
|
|
@@ -567,7 +632,9 @@ async function runServerRuntime(options, runtime) {
|
|
|
567
632
|
headlessHub: hub,
|
|
568
633
|
token: attachToken,
|
|
569
634
|
sessionMcpPublicOrigin: () => remoteRuntime?.remote.publicOrigin(),
|
|
635
|
+
sessionMcpStateDir: serverDirectory,
|
|
570
636
|
sessionMcpPublicOriginRevision: () => remoteRuntime?.remote.publicOriginRevision() ?? 0,
|
|
637
|
+
isSessionPersisted: (sessionId, cwd) => openSessions.list().some((record) => record.sessionId === sessionId && record.cwd === cwd),
|
|
571
638
|
workspaceHistory: (workspaceId) => {
|
|
572
639
|
const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;
|
|
573
640
|
if (!workspaceRoot) throw new Error("Workspace not found.");
|
|
@@ -625,7 +692,9 @@ async function runServerRuntime(options, runtime) {
|
|
|
625
692
|
await hub.closeSession(session.id);
|
|
626
693
|
await openSession({
|
|
627
694
|
cwd: session.cwd,
|
|
628
|
-
name: session.name
|
|
695
|
+
name: session.name,
|
|
696
|
+
...session.parentSessionId === void 0 ? {} : { parentSessionId: session.parentSessionId },
|
|
697
|
+
...session.sessionProvenance === void 0 ? {} : { sessionProvenance: session.sessionProvenance }
|
|
629
698
|
}, session.id);
|
|
630
699
|
},
|
|
631
700
|
resumeSession: async (session, targetSessionId) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.mjs","names":[],"sources":["../../../src/builders/server/runtime.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { globalDoomConfigDirectory } from '@agimon-ai/doompi-config/config';\nimport { filterHookDisabledLayers, loadMajorModesConfig, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { createHeadlessHub, type HeadlessHub } from '@agimon-ai/doompi-core/headless-hub';\nimport { serveHeadlessServer } from '@agimon-ai/doompi-core/headless-server';\nimport type { HeadlessSessionHost, HeadlessSessionHostOptions } from '@agimon-ai/doompi-core/headless-session-host';\nimport { createHeadlessSessionManager } from '@agimon-ai/doompi-core/headless-session-manager';\nimport {\n createOpenSessionRegistry,\n createWorkspaceRegistry,\n listSavedSessions,\n readSqliteTranscript,\n} from '@agimon-ai/doompi-core/history';\nimport type { OpenSessionRecord } from '@agimon-ai/doompi-core/history';\nimport type {\n DoomHubSessionApiRequest,\n DoomHubSessionCreateRequest,\n DoomHubSessionScope,\n} from '@agimon-ai/doompi-core/hub-channel';\nimport { loadMcpBundle, type LoadedMcpBundle } from '@agimon-ai/doompi-core/mcp-facet';\nimport { serveSessionApis, type PackageApiServer } from '@agimon-ai/doompi-core/package-api-server';\nimport { piAgentDirectory } from '@agimon-ai/doompi-core/pi-settings';\nimport { createRemoteRuntime, type RemoteRuntime } from '@agimon-ai/doompi-core/remote-runtime';\nimport type { HeadlessSessionManager } from '@agimon-ai/doompi-core/runtime-headless-session-manager';\nimport { createHarnessTelemetry } from '@agimon-ai/doompi-core/runtime-log-sink-telemetry';\nimport { loadServerBundle, resolveServerBundleSource } from '@agimon-ai/doompi-core/server-facet';\nimport { createServerTelemetry } from '@agimon-ai/doompi-core/server-telemetry';\nimport { resolveSyncLocation } from '@agimon-ai/doompi-core/sync-location';\nimport { readSyncRegistration } from '@agimon-ai/doompi-core/sync-registration';\nimport { createWebCompositions } from '@agimon-ai/doompi-core/web-compositions';\nimport { readMinorModeCatalog } from '@agimon-ai/doompi-minor-mode';\nimport WebSocket from 'ws';\n\nimport { HARNESS_STATE_KEYS, HARNESS_STATE_POINTER } from '../../composition/harnessState';\nimport { findRepositoryRoot } from '../../composition/repository';\nimport { readSyncDrift } from '../../composition/syncDrift';\nimport { readSyncState } from '../../composition/syncState';\nimport { buildHarnessContext } from '../cli/harnessContext';\nimport { publishHeadlessSelectionStatus } from './selectionStatus';\nimport { resolveSessionIdentity } from './sessionArguments';\nimport type { ServeOptions, ServerRuntimeEnvironment } from './types';\nconst TELEMETRY_SHUTDOWN_TIMEOUT_MS = 2_000;\n\nasync function bounded(operation: Promise<unknown>, label: string, notice: (message: string) => void): Promise<void> {\n let timeout: NodeJS.Timeout | undefined;\n try {\n await Promise.race([\n operation,\n new Promise<void>((resolve) => {\n timeout = setTimeout(resolve, TELEMETRY_SHUTDOWN_TIMEOUT_MS);\n }),\n ]);\n } catch (error) {\n notice(`${label} failed: ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function runServerRuntime(options: ServeOptions, runtime: ServerRuntimeEnvironment): Promise<number> {\n const { cwd: baseCwd, environment: baseEnvironment, notice, resolveHarnessOptions, signal, syncWorkspace } = runtime;\n const telemetry = createServerTelemetry({ cwd: baseCwd, env: baseEnvironment, warn: notice });\n const serverDirectory = path.join(piAgentDirectory(baseEnvironment), 'server');\n const workspaces = createWorkspaceRegistry({ directory: serverDirectory, onNotice: notice });\n // Beside the journals it names, because a record pointing at a sessions\n // directory it is not stored next to is a record that can outlive its target.\n const openSessions = createOpenSessionRegistry({\n directory: serverDirectory,\n onNotice: notice,\n });\n let nextEventLoopTick = performance.now() + 1_000;\n const eventLoopMonitor = setInterval(() => {\n const now = performance.now();\n const delay = Math.max(0, now - nextEventLoopTick);\n nextEventLoopTick = now + 1_000;\n if (delay >= 100)\n void telemetry\n .recordEvent('doompi_server.event_loop_delay', { duration_ms: Math.round(delay) })\n .catch((error: unknown) => notice(`event loop telemetry failed: ${String(error)}`));\n }, 1_000);\n eventLoopMonitor.unref();\n const harnessTelemetry = createHarnessTelemetry({\n cwd: baseCwd,\n env: baseEnvironment,\n warn: notice,\n deferSpans: true,\n });\n const baseSessionManager = createHeadlessSessionManager({\n publishSelectionStatus: publishHeadlessSelectionStatus,\n contextGroups: (context) =>\n (readMinorModeCatalog(context)?.list() ?? [])\n .filter(({ state }) => state.activation === 'active')\n .map(({ descriptor }) => ({ id: descriptor.id, label: descriptor.label, kind: 'minor' })),\n });\n type SessionSetup = {\n cleanup: () => Promise<void>;\n bundle: Awaited<ReturnType<typeof loadServerBundle>>;\n mcpBundle: LoadedMcpBundle;\n };\n type SessionArtifacts = SessionSetup & { apis: PackageApiServer };\n const pendingSessions = new Map<string, SessionSetup>();\n const sessionArtifacts = new Map<string, SessionArtifacts>();\n let mountSessionApis:\n | ((options: HeadlessSessionHostOptions, host: HeadlessSessionHost) => Promise<PackageApiServer>)\n | undefined;\n /**\n * Shutdown runs every session through the same close path a user-initiated\n * close uses, so without this the registry would be emptied by the very event\n * it exists to survive.\n */\n let shuttingDown = false;\n\n const closeManagedSession = async (sessionId: string): Promise<void> => {\n if (!shuttingDown) openSessions.remove(sessionId);\n const artifacts = sessionArtifacts.get(sessionId);\n sessionArtifacts.delete(sessionId);\n webCompositions?.remove({ scope: 'session', sessionId });\n const failures: unknown[] = [];\n try {\n await artifacts?.apis.close();\n } catch (error) {\n failures.push(error);\n }\n try {\n await artifacts?.cleanup();\n } catch (error) {\n failures.push(error);\n }\n try {\n await baseSessionManager.closeSession(sessionId);\n } catch (error) {\n failures.push(error);\n }\n if (failures.length > 0) throw new AggregateError(failures, `Session '${sessionId}' shutdown failed`);\n };\n\n const sessionManager: HeadlessSessionManager = {\n async create(sessionOptions) {\n const setup = pendingSessions.get(sessionOptions.sessionId);\n let host: HeadlessSessionHost;\n try {\n host = await baseSessionManager.create(sessionOptions);\n } catch (error) {\n if (setup !== undefined && pendingSessions.delete(sessionOptions.sessionId))\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n if (setup === undefined || mountSessionApis === undefined) return host;\n try {\n const apis = await mountSessionApis(sessionOptions, host);\n pendingSessions.delete(sessionOptions.sessionId);\n sessionArtifacts.set(sessionOptions.sessionId, { ...setup, apis });\n return host;\n } catch (error) {\n pendingSessions.delete(sessionOptions.sessionId);\n await baseSessionManager\n .closeSession(sessionOptions.sessionId)\n .catch((closeError: unknown) => notice(String(closeError)));\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n },\n get: (sessionId) => baseSessionManager.get(sessionId),\n sessions: () => baseSessionManager.sessions(),\n closeSession: closeManagedSession,\n async close() {\n const ids = baseSessionManager.sessions().map((session) => session.runtime.sessionId);\n const outcomes = await Promise.allSettled(ids.map((id) => closeManagedSession(id)));\n const failures = outcomes\n .filter((outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected')\n .map((outcome) => outcome.reason);\n if (failures.length > 0) throw new AggregateError(failures, 'Headless session shutdown failed');\n },\n };\n\n let requestSessionApi: (\n scope: DoomHubSessionScope,\n request: DoomHubSessionApiRequest,\n ) => Promise<Response> = async () => Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n let openSession: (\n request: DoomHubSessionCreateRequest,\n sessionId?: string,\n ) => Promise<DoomHubSessionScope> = async () => {\n throw new Error('The cockpit session service is not ready.');\n };\n let admitWorkspace: (root: string) => Promise<{ id: string; root: string; available: boolean }> = async () => {\n throw new Error('Workspace admission is not ready.');\n };\n let hub!: HeadlessHub;\n hub = createHeadlessHub({\n manager: sessionManager,\n admitWorkspace: (root) => admitWorkspace(root),\n onWorkspaceRemoved: (workspaceId) => {\n workspaces.remove(workspaceId);\n webCompositions?.remove({ scope: 'workspace', workspaceId });\n },\n createSession: (request) => openSession(request),\n onNotice: notice,\n hubToken: () => attachToken,\n requestSessionApi: (scope, request) => requestSessionApi(scope, request),\n });\n let harnessContext: Awaited<ReturnType<typeof buildHarnessContext>> | undefined;\n let cockpit: Awaited<ReturnType<typeof serveHeadlessServer>> | undefined;\n let remoteRuntime: RemoteRuntime | undefined;\n let attachToken: string | undefined;\n let webCompositions: ReturnType<typeof createWebCompositions> | undefined;\n\n try {\n await telemetry.runInSpan('doompi_server.startup', {}, async () => {\n const token = fs.readFileSync(options.tokenFile, 'utf8').trim();\n if (!token) throw new Error('The attach token file is empty.');\n attachToken = token;\n\n const resolved = resolveSessionIdentity(options.agentArgs, {\n sessionId: options.sessionId ?? crypto.randomUUID(),\n sessionName: options.sessionName,\n });\n\n const homeDirectory = baseEnvironment.HOME ?? os.homedir();\n const globalRoot = globalDoomConfigDirectory(homeDirectory);\n webCompositions = createWebCompositions(path.join(globalRoot, 'server'), notice);\n const loadComposition = async (\n root: string,\n scope: 'global' | 'workspace' | 'session',\n selection?: { root: string; majorMode: string; activeLayers: string[] },\n ) => {\n const registration = readSyncRegistration(root, homeDirectory);\n const source = resolveServerBundleSource({ registration });\n if (source.kind !== 'descriptor')\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening it.`);\n const selected =\n selection ??\n (() => {\n const config = loadMajorModesConfig(root, homeDirectory);\n const majorMode = config.defaultMajorMode;\n return { root, majorMode, activeLayers: resolveLayers(config, majorMode) };\n })();\n return loadServerBundle(scope, {\n ...source,\n ...selected,\n retainCandidates: scope === 'session',\n onNotice: notice,\n });\n };\n const loadSessionMcp = async (\n root: string,\n selection: { majorMode: string; activeLayers: readonly string[] },\n ): Promise<LoadedMcpBundle> => {\n const registration = readSyncRegistration(root, homeDirectory);\n if (registration?.mcpBundle === undefined)\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening its MCP runtime.`);\n return loadMcpBundle({\n directory: path.dirname(registration.mcpBundle.path),\n generation: registration.generation,\n fingerprint: registration.mcpBundle.fingerprint,\n descriptorSha256: registration.mcpBundle.sha256,\n majorMode: selection.majorMode,\n activeLayers: selection.activeLayers,\n retainCandidates: true,\n onNotice: notice,\n });\n };\n const sharedApiContext = {\n homeDirectory,\n environment: baseEnvironment,\n hubToken: token,\n sessionService: hub.sessionService,\n directEvents: hub.directEvents,\n repositories: () =>\n hub.workspaces().map((workspace) => ({\n id: workspace.id,\n path: workspace.root,\n name: workspace.root.split('/').at(-1) ?? workspace.id,\n active: hub.snapshot().some((session) => session.workspaceId === workspace.id),\n })),\n resolveRepository: (id: string) => hub.workspaces().find((workspace) => workspace.id === id)?.root,\n readRepositorySync: (id: string) => {\n const root = hub.workspaces().find((workspace) => workspace.id === id)?.root;\n if (!root) return undefined;\n const drift = readSyncDrift({ repoRoot: root, homeDirectory, requireWebBundle: true });\n const state = readSyncState(root, homeDirectory);\n return { ...drift, mcpProjection: state?.fileState.mcpProjection };\n },\n onNotice: notice,\n };\n const globalBundle = await loadComposition(globalRoot, 'global');\n webCompositions.publishShell(readSyncRegistration(globalRoot, homeDirectory)!);\n remoteRuntime = createRemoteRuntime({\n homeDirectory,\n registrationToken: token,\n bundleTrust: () => webCompositions?.shellTrust(),\n onNotice: notice,\n forward: async (request) => {\n if (!cockpit || !attachToken)\n return Response.json({ error: 'The headless server is not ready.' }, { status: 503 });\n const from = new URL(request.url);\n const headers = new Headers(request.headers);\n headers.set('x-doompi-token', attachToken);\n return fetch(\n new URL(`${from.pathname}${from.search}`, cockpit.url),\n new Request(request, { headers, redirect: 'manual' }),\n );\n },\n connectProtocol: (pathname) => {\n if (!cockpit || !attachToken) throw new Error('The headless protocol listener is not ready.');\n const url = new URL(pathname, cockpit.url);\n url.protocol = 'ws:';\n return new WebSocket(url, { headers: { 'x-doompi-token': attachToken } });\n },\n });\n await hub.mountFacets(globalBundle.facets, {\n ...sharedApiContext,\n scope: 'global',\n remoteControl: { fetch: (request: Request) => remoteRuntime!.fetchLocal(request) },\n });\n webCompositions.publish(\n { scope: 'global' },\n readSyncRegistration(globalRoot, homeDirectory)!,\n hub.channelTypes(),\n );\n const admissions = new Map<string, Promise<{ id: string; root: string; available: boolean }>>();\n admitWorkspace = async (from) => {\n const root = fs.realpathSync(findRepositoryRoot(from));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n const existing = hub.workspaces().find((workspace) => workspace.id === id);\n if (existing !== undefined && existing.available !== false) return { ...existing, available: true };\n const pending = admissions.get(id);\n if (pending) return pending;\n const wasRemembered = workspaces.list().some((workspace) => workspace.id === id);\n if (!wasRemembered) workspaces.add({ id, root });\n hub.registerWorkspace({ id, root, available: false });\n const admission = (async () => {\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: root };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n await syncWorkspace(root, syncEnvironment);\n const bundle = await loadComposition(root, 'workspace');\n await hub.mountFacets(bundle.facets, {\n ...sharedApiContext,\n scope: 'workspace',\n workspaceId: id,\n workspaceRoot: root,\n cwd: root,\n resolveRepository: (requestedId) => (requestedId === id ? root : undefined),\n });\n webCompositions?.publish(\n { scope: 'workspace', workspaceId: id },\n readSyncRegistration(root, homeDirectory)!,\n hub.channelTypes(),\n );\n return { id, root, available: true };\n })();\n admissions.set(id, admission);\n try {\n return await admission;\n } catch (error) {\n if (!wasRemembered) {\n await hub.removeWorkspace(id);\n workspaces.remove(id);\n }\n throw error;\n } finally {\n admissions.delete(id);\n }\n };\n for (const record of openSessions.list()) {\n if (workspaces.list().some((workspace) => workspace.id === record.workspaceId)) continue;\n try {\n const root = fs.realpathSync(findRepositoryRoot(record.cwd));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (id === record.workspaceId) workspaces.add({ id, root });\n else\n notice(\n `Session '${record.sessionId}' no longer resolves to its recorded workspace; skipping registration.`,\n );\n } catch (error) {\n notice(\n `Session '${record.sessionId}' workspace could not be registered: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n for (const workspace of workspaces.list()) {\n hub.registerWorkspace({ ...workspace, available: false });\n try {\n const root = fs.realpathSync(findRepositoryRoot(workspace.root));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (root !== workspace.root || id !== workspace.id) {\n notice(\n `Workspace '${workspace.root}' no longer resolves to its recorded identity; leaving it unavailable.`,\n );\n continue;\n }\n await admitWorkspace(workspace.root);\n } catch (error) {\n notice(\n `Workspace '${workspace.root}' could not be restored: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n const sessionHostOptions = (\n context: Awaited<ReturnType<typeof buildHarnessContext>>,\n bundle: Awaited<ReturnType<typeof loadServerBundle>>,\n mcpBundle: LoadedMcpBundle,\n identity: {\n sessionId: string;\n sessionName: string;\n parentSessionId?: string;\n sessionProvenance?: string;\n },\n ): HeadlessSessionHostOptions => {\n const policyOptions = context.options;\n const sessionSelection = {\n root: policyOptions.repoRoot,\n majorMode: policyOptions.majorMode,\n activeLayers: context.selectedLayers,\n domains: policyOptions.domains,\n profile: context.profile,\n state: { 'minor-mode': [] },\n };\n return {\n cwd: policyOptions.cwd,\n repoRoot: policyOptions.repoRoot,\n sessionId: identity.sessionId,\n workspaceId: resolveSyncLocation(policyOptions.repoRoot, homeDirectory).identity.worktreeId,\n sessionName: identity.sessionName,\n webComposition: webCompositions?.publish(\n { scope: 'session', sessionId: identity.sessionId },\n readSyncRegistration(policyOptions.repoRoot, homeDirectory)!,\n hub.channelTypes(),\n ),\n ...(identity.parentSessionId === undefined ? {} : { parentSessionId: identity.parentSessionId }),\n ...(identity.sessionProvenance === undefined ? {} : { sessionProvenance: identity.sessionProvenance }),\n agentArgs: policyOptions.piArgs,\n environment: Object.freeze({ ...context.environment }),\n selection: sessionSelection,\n selectionOverrides: (['majorMode', 'domains', 'profile'] as const).filter((axis) => {\n const flag = axis === 'majorMode' ? '--major-mode' : `--${axis}`;\n return (\n identity.sessionId === resolved.identity.sessionId &&\n resolved.agentArgs.some((arg) => arg === flag || arg.startsWith(`${flag}=`))\n );\n }),\n inheritedSelection: () => {\n const environment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete environment[key];\n const defaults = resolveHarnessOptions({\n args: ['--cwd', policyOptions.cwd],\n cwd: policyOptions.cwd,\n environment,\n });\n return { majorMode: defaults.majorMode, domains: defaults.domains, profile: defaults.profile };\n },\n candidates: bundle.descriptor.entries,\n mcpPlugins: mcpBundle.plugins,\n resolveSelection: (requested) => {\n const config = loadMajorModesConfig(policyOptions.repoRoot, policyOptions.homeDirectory);\n return {\n ...requested,\n activeLayers: filterHookDisabledLayers(\n config,\n resolveLayers(config, requested.majorMode),\n policyOptions.hooks,\n ),\n };\n },\n onNotice: notice,\n };\n };\n\n mountSessionApis = (sessionOptions, host) =>\n serveSessionApis({\n sessionId: sessionOptions.sessionId,\n cwd: sessionOptions.cwd,\n environment: sessionOptions.environment,\n directEvents: hub.directEvents,\n hubToken: token,\n sessionService: hub.sessionService,\n pluginRegistry: hub.pluginRegistry,\n apis: [],\n facets: pendingSessions.get(sessionOptions.sessionId)?.bundle.facets ?? [],\n workspaceId: sessionOptions.workspaceId,\n workspaceRoot: sessionOptions.repoRoot,\n homeDirectory,\n mountChannel: (channel) => {\n const dispose = hub.registerChannel(channel, { scope: 'session', sessionId: sessionOptions.sessionId });\n return { mounted: true, dispose };\n },\n prepareFacets: host.prepareFacets,\n activateFacets: host.activateFacets,\n canDispatch: host.canDispatch,\n telemetry,\n onNotice: notice,\n });\n\n requestSessionApi = async (scope, request) => {\n const session = hub.session(scope.sessionId);\n const artifacts = sessionArtifacts.get(scope.sessionId);\n if (session === undefined || session.cwd !== scope.cwd || artifacts === undefined)\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(request.basePath))\n return Response.json({ error: 'Invalid session API base path.' }, { status: 400 });\n if (!request.path.startsWith('/') || request.path.startsWith('//') || request.path.includes('#'))\n return Response.json({ error: 'Invalid session API path.' }, { status: 400 });\n const body = request.body === null || request.body === undefined ? undefined : request.body;\n return artifacts.apis.request(\n new Request(`http://doompi.local/api/plugins/${request.basePath}${request.path}`, {\n method: request.method,\n headers: request.headers,\n ...(body === undefined ? {} : { body }),\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n }),\n );\n };\n\n if (!options.noSession) {\n harnessContext = await buildHarnessContext(\n resolveHarnessOptions({ args: resolved.agentArgs, cwd: baseCwd, environment: baseEnvironment }),\n harnessTelemetry,\n );\n const activeHarnessContext = harnessContext;\n try {\n await admitWorkspace(harnessContext.options.repoRoot);\n const initialBundle = await loadComposition(harnessContext.options.repoRoot, 'session', {\n root: harnessContext.options.repoRoot,\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n const initialMcpBundle = await loadSessionMcp(harnessContext.options.repoRoot, {\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n pendingSessions.set(resolved.identity.sessionId, {\n cleanup: () => activeHarnessContext.cleanup(),\n bundle: initialBundle,\n mcpBundle: initialMcpBundle,\n });\n await hub.create(sessionHostOptions(harnessContext, initialBundle, initialMcpBundle, resolved.identity));\n } catch (error) {\n pendingSessions.delete(resolved.identity.sessionId);\n await activeHarnessContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n await bounded(harnessTelemetry.flush(), 'initial composition telemetry flush', notice);\n }\n\n openSession = async (request, sessionId) => {\n const identity = {\n sessionId: sessionId ?? crypto.randomUUID(),\n sessionName: request.name,\n parentSessionId: request.parentSessionId,\n sessionProvenance: request.sessionProvenance,\n };\n const childIdentity = resolveSessionIdentity([], identity);\n const childEnvironment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete childEnvironment[key];\n const childContext = await buildHarnessContext(\n resolveHarnessOptions({\n args: ['--cwd', request.cwd, ...childIdentity.agentArgs],\n cwd: request.cwd,\n environment: childEnvironment,\n }),\n harnessTelemetry,\n );\n try {\n await admitWorkspace(childContext.options.repoRoot);\n const bundle = await loadComposition(childContext.options.repoRoot, 'session', {\n root: childContext.options.repoRoot,\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n pendingSessions.set(identity.sessionId, { cleanup: () => childContext.cleanup(), bundle, mcpBundle });\n const created = await hub.create(sessionHostOptions(childContext, bundle, mcpBundle, identity));\n // Recorded only once the session is live, and only with a workspace,\n // because a record the revive route cannot address is a rail card that\n // never wakes.\n if (created.workspaceId !== undefined) {\n openSessions.add({\n sessionId: created.id,\n workspaceId: created.workspaceId,\n cwd: created.cwd,\n name: created.name,\n createdAt: created.createdAt,\n ...(created.parentSessionId === undefined ? {} : { parentSessionId: created.parentSessionId }),\n ...(created.sessionProvenance === undefined ? {} : { sessionProvenance: created.sessionProvenance }),\n });\n }\n return { sessionId: identity.sessionId, cwd: childContext.options.cwd };\n } catch (error) {\n pendingSessions.delete(identity.sessionId);\n await childContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n };\n });\n\n const workspaceResumes = new Map<string, Promise<string>>();\n cockpit = await serveHeadlessServer({\n port: options.webPort,\n headlessHub: hub,\n token: attachToken,\n sessionMcpPublicOrigin: () => remoteRuntime?.remote.publicOrigin(),\n sessionMcpPublicOriginRevision: () => remoteRuntime?.remote.publicOriginRevision() ?? 0,\n workspaceHistory: (workspaceId) => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n return listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n resumeWorkspaceSession: async (workspaceId, targetSessionId) => {\n const key = `${workspaceId}\\0${targetSessionId}`;\n const pending = workspaceResumes.get(key);\n if (pending) return pending;\n const resume = (async () => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n const saved = await listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await openSession({ cwd: workspaceRoot, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n })();\n workspaceResumes.set(key, resume);\n try {\n return await resume;\n } finally {\n workspaceResumes.delete(key);\n }\n },\n sessionHistory: (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n return listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n readDormantTranscript: (record, request, context) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === record.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Saved transcript unavailable.');\n return readSqliteTranscript(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions', `${record.sessionId}.sqlite`),\n request,\n context,\n { sessionId: record.sessionId, workspaceRoot },\n );\n },\n restartSession: async (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: workspaceRoot };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n try {\n await syncWorkspace(workspaceRoot, syncEnvironment);\n } catch (error) {\n notice(`Workspace sync failed before restart: ${error instanceof Error ? error.message : String(error)}`);\n throw new Error('Workspace sync failed; the session is still running.', { cause: error });\n }\n await hub.closeSession(session.id);\n await openSession({ cwd: session.cwd, name: session.name }, session.id);\n },\n resumeSession: async (session, targetSessionId) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const saved = await listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await hub.closeSession(session.id);\n await openSession({ cwd: session.cwd, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n },\n dormantSessions: () => openSessions.list(),\n removeDormantSession: (record: OpenSessionRecord) => openSessions.remove(record.sessionId),\n reviveSession: async (record: OpenSessionRecord) => {\n // A failed wake may be transient, for example while another server still\n // owns the journal. Keep the record so the user can retry after resolving\n // the conflict instead of losing the session from the cockpit.\n await openSession(\n {\n cwd: record.cwd,\n name: record.name,\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n },\n record.sessionId,\n );\n },\n requestAsset: (request) => webCompositions?.request(request) ?? Promise.resolve(undefined),\n compositions: () => ({\n global: webCompositions?.get({ scope: 'global' }),\n publicKey: webCompositions?.publicKey(),\n shell: webCompositions?.shellTrust(),\n workspaces: hub.workspaces().map((workspace) => ({\n ...workspace,\n webComposition: webCompositions?.get({ scope: 'workspace', workspaceId: workspace.id }),\n })),\n }),\n telemetry,\n onNotice: notice,\n });\n notice(`protocol on ${cockpit.url}/api/ws`);\n let resolveShutdown!: (exitCode: number) => void;\n const shutdown = new Promise<number>((resolve) => {\n resolveShutdown = resolve;\n });\n const stop = (): void => resolveShutdown(0);\n signal.addEventListener('abort', stop, { once: true });\n if (signal.aborted) stop();\n try {\n return await shutdown;\n } finally {\n signal.removeEventListener('abort', stop);\n }\n } finally {\n shuttingDown = true;\n clearInterval(eventLoopMonitor);\n await bounded(telemetry.recordEvent('doompi_server.shutdown'), 'shutdown telemetry', notice);\n await Promise.allSettled([cockpit?.close()]);\n await bounded(remoteRuntime?.close() ?? Promise.resolve(), 'remote control shutdown', notice);\n try {\n await hub.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n try {\n await sessionManager.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n webCompositions?.close();\n const pendingCleanups = [...pendingSessions.values()].map((setup) => setup.cleanup());\n pendingSessions.clear();\n await Promise.allSettled(pendingCleanups);\n await bounded(harnessTelemetry.flush(), 'harness telemetry flush', notice);\n await bounded(harnessTelemetry.shutdown(), 'harness telemetry shutdown', notice);\n await bounded(telemetry.flush(), 'server telemetry flush', notice);\n await bounded(telemetry.shutdown(), 'server telemetry shutdown', notice);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.mjs","names":[],"sources":["../../../src/builders/server/runtime.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { globalDoomConfigDirectory } from '@agimon-ai/doompi-config/config';\nimport { filterHookDisabledLayers, loadMajorModesConfig, resolveLayers } from '@agimon-ai/doompi-config/majorModes';\nimport { createHeadlessHub, type HeadlessHub } from '@agimon-ai/doompi-core/headless-hub';\nimport { serveHeadlessServer } from '@agimon-ai/doompi-core/headless-server';\nimport type { HeadlessSessionHost, HeadlessSessionHostOptions } from '@agimon-ai/doompi-core/headless-session-host';\nimport { createHeadlessSessionManager } from '@agimon-ai/doompi-core/headless-session-manager';\nimport {\n createOpenSessionRegistry,\n createWorkspaceRegistry,\n listSavedSessions,\n readSqliteTranscript,\n} from '@agimon-ai/doompi-core/history';\nimport type { OpenSessionRecord } from '@agimon-ai/doompi-core/history';\nimport type {\n DoomHubSessionApiRequest,\n DoomHubSessionCreateRequest,\n DoomHubSessionScope,\n} from '@agimon-ai/doompi-core/hub-channel';\nimport { loadMcpBundle, type LoadedMcpBundle } from '@agimon-ai/doompi-core/mcp-facet';\nimport { serveSessionApis, type PackageApiServer } from '@agimon-ai/doompi-core/package-api-server';\nimport { piAgentDirectory } from '@agimon-ai/doompi-core/pi-settings';\nimport { createRemoteRuntime, type RemoteRuntime } from '@agimon-ai/doompi-core/remote-runtime';\nimport type { HeadlessSessionManager } from '@agimon-ai/doompi-core/runtime-headless-session-manager';\nimport { createHarnessTelemetry } from '@agimon-ai/doompi-core/runtime-log-sink-telemetry';\nimport { loadServerBundle, resolveServerBundleSource } from '@agimon-ai/doompi-core/server-facet';\nimport { createServerTelemetry } from '@agimon-ai/doompi-core/server-telemetry';\nimport { resolveSyncLocation } from '@agimon-ai/doompi-core/sync-location';\nimport { readSyncRegistration } from '@agimon-ai/doompi-core/sync-registration';\nimport { createWebCompositions } from '@agimon-ai/doompi-core/web-compositions';\nimport { readMinorModeCatalog } from '@agimon-ai/doompi-minor-mode';\nimport WebSocket from 'ws';\n\nimport { HARNESS_STATE_KEYS, HARNESS_STATE_POINTER } from '../../composition/harnessState';\nimport { findRepositoryRoot } from '../../composition/repository';\nimport { readSyncDrift } from '../../composition/syncDrift';\nimport { readSyncState } from '../../composition/syncState';\nimport { buildHarnessContext } from '../cli/harnessContext';\nimport { publishHeadlessSelectionStatus } from './selectionStatus';\nimport { resolveSessionIdentity } from './sessionArguments';\nimport type { ServeOptions, ServerRuntimeEnvironment } from './types';\nconst TELEMETRY_SHUTDOWN_TIMEOUT_MS = 2_000;\n\nasync function bounded(operation: Promise<unknown>, label: string, notice: (message: string) => void): Promise<void> {\n let timeout: NodeJS.Timeout | undefined;\n try {\n await Promise.race([\n operation,\n new Promise<void>((resolve) => {\n timeout = setTimeout(resolve, TELEMETRY_SHUTDOWN_TIMEOUT_MS);\n }),\n ]);\n } catch (error) {\n notice(`${label} failed: ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function runServerRuntime(options: ServeOptions, runtime: ServerRuntimeEnvironment): Promise<number> {\n const { cwd: baseCwd, environment: baseEnvironment, notice, resolveHarnessOptions, signal, syncWorkspace } = runtime;\n const telemetry = createServerTelemetry({ cwd: baseCwd, env: baseEnvironment, warn: notice });\n const serverDirectory = path.join(piAgentDirectory(baseEnvironment), 'server');\n const workspaces = createWorkspaceRegistry({ directory: serverDirectory, onNotice: notice });\n // Beside the journals it names, because a record pointing at a sessions\n // directory it is not stored next to is a record that can outlive its target.\n const openSessions = createOpenSessionRegistry({\n directory: serverDirectory,\n onNotice: notice,\n });\n let nextEventLoopTick = performance.now() + 1_000;\n const eventLoopMonitor = setInterval(() => {\n const now = performance.now();\n const delay = Math.max(0, now - nextEventLoopTick);\n nextEventLoopTick = now + 1_000;\n if (delay >= 100)\n void telemetry\n .recordEvent('doompi_server.event_loop_delay', { duration_ms: Math.round(delay) })\n .catch((error: unknown) => notice(`event loop telemetry failed: ${String(error)}`));\n }, 1_000);\n eventLoopMonitor.unref();\n const harnessTelemetry = createHarnessTelemetry({\n cwd: baseCwd,\n env: baseEnvironment,\n warn: notice,\n deferSpans: true,\n });\n const baseSessionManager = createHeadlessSessionManager({\n publishSelectionStatus: publishHeadlessSelectionStatus,\n contextGroups: (context) =>\n (readMinorModeCatalog(context)?.list() ?? [])\n .filter(({ state }) => state.activation === 'active')\n .map(({ descriptor }) => ({ id: descriptor.id, label: descriptor.label, kind: 'minor' })),\n });\n type SessionSetup = {\n cleanup: () => Promise<void>;\n bundle: Awaited<ReturnType<typeof loadServerBundle>>;\n mcpBundle: LoadedMcpBundle;\n };\n type SessionArtifacts = SessionSetup & { apis: PackageApiServer };\n const pendingSessions = new Map<string, SessionSetup>();\n const sessionArtifacts = new Map<string, SessionArtifacts>();\n let mountSessionApis:\n | ((options: HeadlessSessionHostOptions, host: HeadlessSessionHost) => Promise<PackageApiServer>)\n | undefined;\n /**\n * Shutdown runs every session through the same close path a user-initiated\n * close uses, so without this the registry would be emptied by the very event\n * it exists to survive.\n */\n let shuttingDown = false;\n\n const closeManagedSession = async (sessionId: string): Promise<void> => {\n if (!shuttingDown) openSessions.remove(sessionId);\n const artifacts = sessionArtifacts.get(sessionId);\n sessionArtifacts.delete(sessionId);\n webCompositions?.remove({ scope: 'session', sessionId });\n const failures: unknown[] = [];\n try {\n await artifacts?.apis.close();\n } catch (error) {\n failures.push(error);\n }\n try {\n await artifacts?.cleanup();\n } catch (error) {\n failures.push(error);\n }\n try {\n await baseSessionManager.closeSession(sessionId);\n } catch (error) {\n failures.push(error);\n }\n if (failures.length > 0) throw new AggregateError(failures, `Session '${sessionId}' shutdown failed`);\n };\n\n const sessionManager: HeadlessSessionManager = {\n async create(sessionOptions) {\n const setup = pendingSessions.get(sessionOptions.sessionId);\n let host: HeadlessSessionHost;\n try {\n host = await baseSessionManager.create(sessionOptions);\n } catch (error) {\n if (setup !== undefined && pendingSessions.delete(sessionOptions.sessionId))\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n if (setup === undefined || mountSessionApis === undefined) return host;\n try {\n const apis = await mountSessionApis(sessionOptions, host);\n pendingSessions.delete(sessionOptions.sessionId);\n sessionArtifacts.set(sessionOptions.sessionId, { ...setup, apis });\n return host;\n } catch (error) {\n pendingSessions.delete(sessionOptions.sessionId);\n await baseSessionManager\n .closeSession(sessionOptions.sessionId)\n .catch((closeError: unknown) => notice(String(closeError)));\n await setup.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n },\n get: (sessionId) => baseSessionManager.get(sessionId),\n sessions: () => baseSessionManager.sessions(),\n closeSession: closeManagedSession,\n async close() {\n const ids = baseSessionManager.sessions().map((session) => session.runtime.sessionId);\n const outcomes = await Promise.allSettled(ids.map((id) => closeManagedSession(id)));\n const failures = outcomes\n .filter((outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected')\n .map((outcome) => outcome.reason);\n if (failures.length > 0) throw new AggregateError(failures, 'Headless session shutdown failed');\n },\n };\n\n let requestSessionApi: (\n scope: DoomHubSessionScope,\n request: DoomHubSessionApiRequest,\n ) => Promise<Response> = async () => Response.json({ error: 'Session API unavailable.' }, { status: 404 });\n let openSession: (\n request: DoomHubSessionCreateRequest,\n sessionId?: string,\n ) => Promise<DoomHubSessionScope> = async () => {\n throw new Error('The cockpit session service is not ready.');\n };\n let admitWorkspace: (root: string) => Promise<{ id: string; root: string; available: boolean }> = async () => {\n throw new Error('Workspace admission is not ready.');\n };\n let hub!: HeadlessHub;\n hub = createHeadlessHub({\n manager: sessionManager,\n admitWorkspace: (root) => admitWorkspace(root),\n onWorkspaceRemoved: (workspaceId) => {\n workspaces.remove(workspaceId);\n webCompositions?.remove({ scope: 'workspace', workspaceId });\n },\n createSession: (request) => openSession(request),\n sessionReservations: {\n read(id, parentSessionId) {\n if (!cockpit) throw new Error('Session setup is not ready.');\n return cockpit.sessionReservations.read(id, parentSessionId);\n },\n async prepare(id, parentSessionId, cwd) {\n if (!cockpit) throw new Error('Session setup is not ready.');\n return cockpit.sessionReservations.prepare(id, parentSessionId, cwd);\n },\n async complete(id, parentSessionId) {\n if (!cockpit) throw new Error('Session setup is not ready.');\n return cockpit.sessionReservations.complete(id, parentSessionId);\n },\n },\n onNotice: notice,\n hubToken: () => attachToken,\n requestSessionApi: (scope, request) => requestSessionApi(scope, request),\n });\n let harnessContext: Awaited<ReturnType<typeof buildHarnessContext>> | undefined;\n let cockpit: Awaited<ReturnType<typeof serveHeadlessServer>> | undefined;\n let remoteRuntime: RemoteRuntime | undefined;\n let attachToken: string | undefined;\n let webCompositions: ReturnType<typeof createWebCompositions> | undefined;\n\n try {\n await telemetry.runInSpan('doompi_server.startup', {}, async () => {\n const token = fs.readFileSync(options.tokenFile, 'utf8').trim();\n if (!token) throw new Error('The attach token file is empty.');\n attachToken = token;\n\n const resolved = resolveSessionIdentity(options.agentArgs, {\n sessionId: options.sessionId ?? crypto.randomUUID(),\n sessionName: options.sessionName,\n });\n\n const homeDirectory = baseEnvironment.HOME ?? os.homedir();\n const globalRoot = globalDoomConfigDirectory(homeDirectory);\n webCompositions = createWebCompositions(path.join(globalRoot, 'server'), notice);\n const loadComposition = async (\n root: string,\n scope: 'global' | 'workspace' | 'session',\n selection?: { root: string; majorMode: string; activeLayers: string[] },\n ) => {\n const registration = readSyncRegistration(root, homeDirectory);\n const source = resolveServerBundleSource({ registration });\n if (source.kind !== 'descriptor')\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening it.`);\n const selected =\n selection ??\n (() => {\n const config = loadMajorModesConfig(root, homeDirectory);\n const majorMode = config.defaultMajorMode;\n return { root, majorMode, activeLayers: resolveLayers(config, majorMode) };\n })();\n return loadServerBundle(scope, {\n ...source,\n ...selected,\n retainCandidates: scope === 'session',\n onNotice: notice,\n });\n };\n const loadSessionMcp = async (\n root: string,\n selection: { majorMode: string; activeLayers: readonly string[] },\n ): Promise<LoadedMcpBundle> => {\n const registration = readSyncRegistration(root, homeDirectory);\n if (registration?.mcpBundle === undefined)\n throw new Error(`Run the scoped DoomPi sync for '${root}' before opening its MCP runtime.`);\n return loadMcpBundle({\n directory: path.dirname(registration.mcpBundle.path),\n generation: registration.generation,\n fingerprint: registration.mcpBundle.fingerprint,\n descriptorSha256: registration.mcpBundle.sha256,\n majorMode: selection.majorMode,\n activeLayers: selection.activeLayers,\n retainCandidates: true,\n onNotice: notice,\n });\n };\n const sharedApiContext = {\n homeDirectory,\n environment: baseEnvironment,\n hubToken: token,\n sessionService: hub.sessionService,\n directEvents: hub.directEvents,\n repositories: () =>\n hub.workspaces().map((workspace) => ({\n id: workspace.id,\n path: workspace.root,\n name: workspace.root.split('/').at(-1) ?? workspace.id,\n active: hub.snapshot().some((session) => session.workspaceId === workspace.id),\n })),\n resolveRepository: (id: string) => hub.workspaces().find((workspace) => workspace.id === id)?.root,\n readRepositorySync: (id: string) => {\n const root = hub.workspaces().find((workspace) => workspace.id === id)?.root;\n if (!root) return undefined;\n const drift = readSyncDrift({ repoRoot: root, homeDirectory, requireWebBundle: true });\n const state = readSyncState(root, homeDirectory);\n return { ...drift, mcpProjection: state?.fileState.mcpProjection };\n },\n onNotice: notice,\n };\n const globalBundle = await loadComposition(globalRoot, 'global');\n webCompositions.publishShell(readSyncRegistration(globalRoot, homeDirectory)!);\n remoteRuntime = createRemoteRuntime({\n homeDirectory,\n registrationToken: token,\n bundleTrust: () => webCompositions?.shellTrust(),\n onNotice: notice,\n forward: async (request) => {\n if (!cockpit || !attachToken)\n return Response.json({ error: 'The headless server is not ready.' }, { status: 503 });\n const from = new URL(request.url);\n const headers = new Headers(request.headers);\n headers.set('x-doompi-token', attachToken);\n return fetch(\n new URL(`${from.pathname}${from.search}`, cockpit.url),\n new Request(request, { headers, redirect: 'manual' }),\n );\n },\n connectProtocol: (pathname) => {\n if (!cockpit || !attachToken) throw new Error('The headless protocol listener is not ready.');\n const url = new URL(pathname, cockpit.url);\n url.protocol = 'ws:';\n return new WebSocket(url, { headers: { 'x-doompi-token': attachToken } });\n },\n });\n await hub.mountFacets(globalBundle.facets, {\n ...sharedApiContext,\n scope: 'global',\n remoteControl: { fetch: (request: Request) => remoteRuntime!.fetchLocal(request) },\n });\n webCompositions.publish(\n { scope: 'global' },\n readSyncRegistration(globalRoot, homeDirectory)!,\n hub.channelTypes(),\n );\n const admissions = new Map<string, Promise<{ id: string; root: string; available: boolean }>>();\n admitWorkspace = async (from) => {\n const root = fs.realpathSync(findRepositoryRoot(from));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n const existing = hub.workspaces().find((workspace) => workspace.id === id);\n if (existing !== undefined && existing.available !== false) return { ...existing, available: true };\n const pending = admissions.get(id);\n if (pending) return pending;\n const wasRemembered = workspaces.list().some((workspace) => workspace.id === id);\n if (!wasRemembered) workspaces.add({ id, root });\n hub.registerWorkspace({ id, root, available: false });\n const admission = (async () => {\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: root };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n await syncWorkspace(root, syncEnvironment);\n const bundle = await loadComposition(root, 'workspace');\n await hub.mountFacets(bundle.facets, {\n ...sharedApiContext,\n scope: 'workspace',\n workspaceId: id,\n workspaceRoot: root,\n cwd: root,\n resolveRepository: (requestedId) => (requestedId === id ? root : undefined),\n });\n webCompositions?.publish(\n { scope: 'workspace', workspaceId: id },\n readSyncRegistration(root, homeDirectory)!,\n hub.channelTypes(),\n );\n return { id, root, available: true };\n })();\n admissions.set(id, admission);\n try {\n return await admission;\n } catch (error) {\n if (!wasRemembered) {\n await hub.removeWorkspace(id);\n workspaces.remove(id);\n }\n throw error;\n } finally {\n admissions.delete(id);\n }\n };\n for (const record of openSessions.list()) {\n if (workspaces.list().some((workspace) => workspace.id === record.workspaceId)) continue;\n try {\n const root = fs.realpathSync(findRepositoryRoot(record.cwd));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (id === record.workspaceId) workspaces.add({ id, root });\n else\n notice(\n `Session '${record.sessionId}' no longer resolves to its recorded workspace; skipping registration.`,\n );\n } catch (error) {\n notice(\n `Session '${record.sessionId}' workspace could not be registered: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n for (const workspace of workspaces.list()) {\n hub.registerWorkspace({ ...workspace, available: false });\n try {\n const root = fs.realpathSync(findRepositoryRoot(workspace.root));\n const id = resolveSyncLocation(root, homeDirectory).identity.worktreeId;\n if (root !== workspace.root || id !== workspace.id) {\n notice(\n `Workspace '${workspace.root}' no longer resolves to its recorded identity; leaving it unavailable.`,\n );\n continue;\n }\n await admitWorkspace(workspace.root);\n } catch (error) {\n notice(\n `Workspace '${workspace.root}' could not be restored: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n const sessionHostOptions = (\n context: Awaited<ReturnType<typeof buildHarnessContext>>,\n bundle: Awaited<ReturnType<typeof loadServerBundle>>,\n mcpBundle: LoadedMcpBundle,\n identity: {\n sessionId: string;\n sessionName: string;\n parentSessionId?: string;\n sessionProvenance?: string;\n },\n workspaceId?: string,\n ): HeadlessSessionHostOptions => {\n const policyOptions = context.options;\n const sessionSelection = {\n root: policyOptions.repoRoot,\n majorMode: policyOptions.majorMode,\n activeLayers: context.selectedLayers,\n domains: policyOptions.domains,\n profile: context.profile,\n state: { 'minor-mode': [] },\n };\n return {\n cwd: policyOptions.cwd,\n repoRoot: policyOptions.repoRoot,\n sessionId: identity.sessionId,\n workspaceId: workspaceId ?? resolveSyncLocation(policyOptions.repoRoot, homeDirectory).identity.worktreeId,\n sessionName: identity.sessionName,\n webComposition: webCompositions?.publish(\n { scope: 'session', sessionId: identity.sessionId },\n readSyncRegistration(policyOptions.repoRoot, homeDirectory)!,\n hub.channelTypes(),\n ),\n ...(identity.parentSessionId === undefined ? {} : { parentSessionId: identity.parentSessionId }),\n ...(identity.sessionProvenance === undefined ? {} : { sessionProvenance: identity.sessionProvenance }),\n agentArgs: policyOptions.piArgs,\n environment: Object.freeze({ ...context.environment }),\n selection: sessionSelection,\n selectionOverrides: (['majorMode', 'domains', 'profile'] as const).filter((axis) => {\n const flag = axis === 'majorMode' ? '--major-mode' : `--${axis}`;\n return (\n identity.sessionId === resolved.identity.sessionId &&\n resolved.agentArgs.some((arg) => arg === flag || arg.startsWith(`${flag}=`))\n );\n }),\n inheritedSelection: () => {\n const environment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete environment[key];\n const defaults = resolveHarnessOptions({\n args: ['--cwd', policyOptions.cwd],\n cwd: policyOptions.cwd,\n environment,\n });\n return { majorMode: defaults.majorMode, domains: defaults.domains, profile: defaults.profile };\n },\n candidates: bundle.descriptor.entries,\n mcpPlugins: mcpBundle.plugins,\n resolveSelection: (requested) => {\n const config = loadMajorModesConfig(policyOptions.repoRoot, policyOptions.homeDirectory);\n return {\n ...requested,\n activeLayers: filterHookDisabledLayers(\n config,\n resolveLayers(config, requested.majorMode),\n policyOptions.hooks,\n ),\n };\n },\n onNotice: notice,\n };\n };\n\n mountSessionApis = (sessionOptions, host) =>\n serveSessionApis({\n sessionId: sessionOptions.sessionId,\n cwd: sessionOptions.cwd,\n environment: sessionOptions.environment,\n directEvents: hub.directEvents,\n hubToken: token,\n sessionService: hub.sessionService,\n pluginRegistry: hub.pluginRegistry,\n apis: [],\n facets: pendingSessions.get(sessionOptions.sessionId)?.bundle.facets ?? [],\n workspaceId: sessionOptions.workspaceId,\n workspaceRoot: sessionOptions.repoRoot,\n homeDirectory,\n mountChannel: (channel) => {\n const dispose = hub.registerChannel(channel, { scope: 'session', sessionId: sessionOptions.sessionId });\n return { mounted: true, dispose };\n },\n prepareFacets: host.prepareFacets,\n activateFacets: host.activateFacets,\n canDispatch: host.canDispatch,\n telemetry,\n onNotice: notice,\n });\n\n requestSessionApi = async (scope, request) => {\n const session = hub.session(scope.sessionId);\n const artifacts = sessionArtifacts.get(scope.sessionId);\n if (session === undefined || session.cwd !== scope.cwd || artifacts === undefined)\n return Response.json({ error: 'Session not found.' }, { status: 404 });\n if (!/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u.test(request.basePath))\n return Response.json({ error: 'Invalid session API base path.' }, { status: 400 });\n if (!request.path.startsWith('/') || request.path.startsWith('//') || request.path.includes('#'))\n return Response.json({ error: 'Invalid session API path.' }, { status: 400 });\n const body = request.body === null || request.body === undefined ? undefined : request.body;\n return artifacts.apis.request(\n new Request(`http://doompi.local/api/plugins/${request.basePath}${request.path}`, {\n method: request.method,\n headers: request.headers,\n ...(body === undefined ? {} : { body }),\n ...(request.signal === undefined ? {} : { signal: request.signal }),\n }),\n );\n };\n\n if (!options.noSession) {\n harnessContext = await buildHarnessContext(\n resolveHarnessOptions({ args: resolved.agentArgs, cwd: baseCwd, environment: baseEnvironment }),\n harnessTelemetry,\n );\n const activeHarnessContext = harnessContext;\n try {\n await admitWorkspace(harnessContext.options.repoRoot);\n const initialBundle = await loadComposition(harnessContext.options.repoRoot, 'session', {\n root: harnessContext.options.repoRoot,\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n const initialMcpBundle = await loadSessionMcp(harnessContext.options.repoRoot, {\n majorMode: harnessContext.options.majorMode,\n activeLayers: harnessContext.selectedLayers,\n });\n pendingSessions.set(resolved.identity.sessionId, {\n cleanup: () => activeHarnessContext.cleanup(),\n bundle: initialBundle,\n mcpBundle: initialMcpBundle,\n });\n await hub.create(sessionHostOptions(harnessContext, initialBundle, initialMcpBundle, resolved.identity));\n } catch (error) {\n pendingSessions.delete(resolved.identity.sessionId);\n await activeHarnessContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n throw error;\n }\n await bounded(harnessTelemetry.flush(), 'initial composition telemetry flush', notice);\n }\n\n const reservedOpens = new Map<string, Promise<DoomHubSessionScope>>();\n openSession = async (request, sessionId) => {\n request.signal?.throwIfAborted();\n if (request.reservationId !== undefined) {\n if (!request.parentSessionId || !cockpit) throw new Error('A reserved session requires its owning parent.');\n const prepared = await cockpit.sessionReservations.prepare(\n request.reservationId,\n request.parentSessionId,\n request.cwd,\n );\n if (sessionId !== undefined && sessionId !== prepared.sessionId)\n throw new Error('Reserved session identity cannot change.');\n sessionId = prepared.sessionId;\n const existing = hub.session(sessionId);\n if (existing) {\n if (existing.cwd !== prepared.cwd || existing.parentSessionId !== request.parentSessionId)\n throw new Error('Reserved session target does not match.');\n return { sessionId, cwd: existing.cwd, workspaceId: existing.workspaceId };\n }\n if (openSessions.list().some((record) => record.sessionId === sessionId))\n throw new Error('Resume the recorded session instead of recreating it.');\n const pending = reservedOpens.get(sessionId);\n if (pending) return pending;\n request = { ...request, cwd: prepared.cwd };\n }\n const identity = {\n sessionId: sessionId ?? crypto.randomUUID(),\n sessionName: request.name,\n parentSessionId: request.parentSessionId,\n sessionProvenance: request.sessionProvenance,\n };\n const inheritedWorkspaceId =\n request.sessionProvenance === 'worktree' && request.parentSessionId\n ? (hub.session(request.parentSessionId)?.workspaceId ??\n openSessions.list().find((record) => record.sessionId === request.parentSessionId)?.workspaceId)\n : undefined;\n if (request.sessionProvenance === 'worktree' && inheritedWorkspaceId === undefined)\n throw new Error('Worktree session requires its parent workspace.');\n const start = (async (): Promise<DoomHubSessionScope> => {\n const childIdentity = resolveSessionIdentity([], identity);\n const childEnvironment = { ...baseEnvironment };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete childEnvironment[key];\n const childContext = await buildHarnessContext(\n resolveHarnessOptions({\n args: ['--cwd', request.cwd, ...childIdentity.agentArgs],\n cwd: request.cwd,\n environment: childEnvironment,\n }),\n harnessTelemetry,\n );\n try {\n if (inheritedWorkspaceId === undefined) {\n await admitWorkspace(childContext.options.repoRoot);\n } else {\n const inheritedWorkspace = hub\n .workspaces()\n .find((workspace) => workspace.id === inheritedWorkspaceId && workspace.available !== false);\n if (inheritedWorkspace === undefined) throw new Error('Worktree parent workspace is unavailable.');\n const syncEnvironment: NodeJS.ProcessEnv = {\n ...baseEnvironment,\n DOOMPI_ROOT: childContext.options.repoRoot,\n };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)])\n delete syncEnvironment[key];\n await syncWorkspace(childContext.options.repoRoot, syncEnvironment);\n }\n const bundle = await loadComposition(childContext.options.repoRoot, 'session', {\n root: childContext.options.repoRoot,\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n const mcpBundle = await loadSessionMcp(childContext.options.repoRoot, {\n majorMode: childContext.options.majorMode,\n activeLayers: childContext.selectedLayers,\n });\n request.signal?.throwIfAborted();\n pendingSessions.set(identity.sessionId, { cleanup: () => childContext.cleanup(), bundle, mcpBundle });\n const created = await hub.create(\n sessionHostOptions(childContext, bundle, mcpBundle, identity, inheritedWorkspaceId),\n );\n request.signal?.throwIfAborted();\n if (created.workspaceId !== undefined) {\n const saved = openSessions.add({\n sessionId: created.id,\n workspaceId: created.workspaceId,\n cwd: created.cwd,\n name: created.name,\n createdAt: created.createdAt,\n ...(created.parentSessionId === undefined ? {} : { parentSessionId: created.parentSessionId }),\n ...(created.sessionProvenance === undefined ? {} : { sessionProvenance: created.sessionProvenance }),\n });\n if (saved === false) throw new Error('The new session could not be durably recorded.');\n }\n return { sessionId: identity.sessionId, cwd: childContext.options.cwd, workspaceId: created.workspaceId };\n } catch (error) {\n if (hub.session(identity.sessionId)) await hub.closeSession(identity.sessionId);\n else {\n pendingSessions.delete(identity.sessionId);\n await childContext.cleanup().catch((cleanupError: unknown) => notice(String(cleanupError)));\n }\n throw error;\n }\n })();\n if (request.reservationId !== undefined) reservedOpens.set(identity.sessionId, start);\n try {\n return await start;\n } finally {\n if (reservedOpens.get(identity.sessionId) === start) reservedOpens.delete(identity.sessionId);\n }\n };\n });\n\n const workspaceResumes = new Map<string, Promise<string>>();\n cockpit = await serveHeadlessServer({\n port: options.webPort,\n headlessHub: hub,\n token: attachToken,\n sessionMcpPublicOrigin: () => remoteRuntime?.remote.publicOrigin(),\n sessionMcpStateDir: serverDirectory,\n sessionMcpPublicOriginRevision: () => remoteRuntime?.remote.publicOriginRevision() ?? 0,\n isSessionPersisted: (sessionId, cwd) =>\n openSessions.list().some((record) => record.sessionId === sessionId && record.cwd === cwd),\n workspaceHistory: (workspaceId) => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n return listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n resumeWorkspaceSession: async (workspaceId, targetSessionId) => {\n const key = `${workspaceId}\\0${targetSessionId}`;\n const pending = workspaceResumes.get(key);\n if (pending) return pending;\n const resume = (async () => {\n const workspaceRoot = hub\n .workspaces()\n .find((workspace) => workspace.id === workspaceId && workspace.available !== false)?.root;\n if (!workspaceRoot) throw new Error('Workspace not found.');\n const saved = await listSavedSessions(\n path.join(serverDirectory, 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await openSession({ cwd: workspaceRoot, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n })();\n workspaceResumes.set(key, resume);\n try {\n return await resume;\n } finally {\n workspaceResumes.delete(key);\n }\n },\n sessionHistory: (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n return listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n },\n readDormantTranscript: (record, request, context) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === record.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Saved transcript unavailable.');\n return readSqliteTranscript(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions', `${record.sessionId}.sqlite`),\n request,\n context,\n { sessionId: record.sessionId, workspaceRoot },\n );\n },\n restartSession: async (session) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const syncEnvironment: NodeJS.ProcessEnv = { ...baseEnvironment, DOOMPI_ROOT: workspaceRoot };\n for (const key of [HARNESS_STATE_POINTER, ...Object.values(HARNESS_STATE_KEYS)]) delete syncEnvironment[key];\n try {\n await syncWorkspace(workspaceRoot, syncEnvironment);\n } catch (error) {\n notice(`Workspace sync failed before restart: ${error instanceof Error ? error.message : String(error)}`);\n throw new Error('Workspace sync failed; the session is still running.', { cause: error });\n }\n await hub.closeSession(session.id);\n await openSession(\n {\n cwd: session.cwd,\n name: session.name,\n ...(session.parentSessionId === undefined ? {} : { parentSessionId: session.parentSessionId }),\n ...(session.sessionProvenance === undefined ? {} : { sessionProvenance: session.sessionProvenance }),\n },\n session.id,\n );\n },\n resumeSession: async (session, targetSessionId) => {\n const workspaceRoot = hub.workspaces().find((workspace) => workspace.id === session.workspaceId)?.root;\n if (!workspaceRoot) throw new Error('Session workspace not found.');\n const saved = await listSavedSessions(\n path.join(piAgentDirectory(baseEnvironment), 'server', 'sessions'),\n workspaceRoot,\n new Set(hub.snapshot().map((active) => active.id)),\n );\n const target = saved.find((item) => item.id === targetSessionId);\n if (!target) throw new Error('Saved Pi thread not found in this workspace.');\n await hub.closeSession(session.id);\n await openSession({ cwd: session.cwd, name: target.name ?? 'untitled' }, target.id);\n return target.id;\n },\n dormantSessions: () => openSessions.list(),\n removeDormantSession: (record: OpenSessionRecord) => openSessions.remove(record.sessionId),\n reviveSession: async (record: OpenSessionRecord) => {\n // A failed wake may be transient, for example while another server still\n // owns the journal. Keep the record so the user can retry after resolving\n // the conflict instead of losing the session from the cockpit.\n await openSession(\n {\n cwd: record.cwd,\n name: record.name,\n ...(record.parentSessionId === undefined ? {} : { parentSessionId: record.parentSessionId }),\n ...(record.sessionProvenance === undefined ? {} : { sessionProvenance: record.sessionProvenance }),\n },\n record.sessionId,\n );\n },\n requestAsset: (request) => webCompositions?.request(request) ?? Promise.resolve(undefined),\n compositions: () => ({\n global: webCompositions?.get({ scope: 'global' }),\n publicKey: webCompositions?.publicKey(),\n shell: webCompositions?.shellTrust(),\n workspaces: hub.workspaces().map((workspace) => ({\n ...workspace,\n webComposition: webCompositions?.get({ scope: 'workspace', workspaceId: workspace.id }),\n })),\n }),\n telemetry,\n onNotice: notice,\n });\n notice(`protocol on ${cockpit.url}/api/ws`);\n let resolveShutdown!: (exitCode: number) => void;\n const shutdown = new Promise<number>((resolve) => {\n resolveShutdown = resolve;\n });\n const stop = (): void => resolveShutdown(0);\n signal.addEventListener('abort', stop, { once: true });\n if (signal.aborted) stop();\n try {\n return await shutdown;\n } finally {\n signal.removeEventListener('abort', stop);\n }\n } finally {\n shuttingDown = true;\n clearInterval(eventLoopMonitor);\n await bounded(telemetry.recordEvent('doompi_server.shutdown'), 'shutdown telemetry', notice);\n await Promise.allSettled([cockpit?.close()]);\n await bounded(remoteRuntime?.close() ?? Promise.resolve(), 'remote control shutdown', notice);\n try {\n await hub.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n try {\n await sessionManager.close();\n } catch (error) {\n notice(error instanceof Error ? error.message : String(error));\n }\n webCompositions?.close();\n const pendingCleanups = [...pendingSessions.values()].map((setup) => setup.cleanup());\n pendingSessions.clear();\n await Promise.allSettled(pendingCleanups);\n await bounded(harnessTelemetry.flush(), 'harness telemetry flush', notice);\n await bounded(harnessTelemetry.shutdown(), 'harness telemetry shutdown', notice);\n await bounded(telemetry.flush(), 'server telemetry flush', notice);\n await bounded(telemetry.shutdown(), 'server telemetry shutdown', notice);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.82",
|
|
4
4
|
"description": "Opinionated, composable Pi distribution for scoped agent tools, skills, MCP servers, and developer workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -277,20 +277,20 @@
|
|
|
277
277
|
"registry": "https://registry.npmjs.org/"
|
|
278
278
|
},
|
|
279
279
|
"dependencies": {
|
|
280
|
-
"@agimon-ai/doompi-autostop": "0.0.1-alpha.
|
|
281
|
-
"@agimon-ai/doompi-cache": "0.0.1-alpha.
|
|
282
|
-
"@agimon-ai/doompi-config": "0.0.1-alpha.
|
|
283
|
-
"@agimon-ai/doompi-core": "0.0.1-alpha.
|
|
284
|
-
"@agimon-ai/doompi-domain": "0.0.1-alpha.
|
|
285
|
-
"@agimon-ai/doompi-major-mode": "0.0.1-alpha.
|
|
286
|
-
"@agimon-ai/doompi-minor-mode": "0.0.1-alpha.
|
|
287
|
-
"@agimon-ai/doompi-notification": "0.0.1-alpha.
|
|
288
|
-
"@agimon-ai/doompi-profile": "0.0.1-alpha.
|
|
289
|
-
"@agimon-ai/doompi-session": "0.0.1-alpha.
|
|
290
|
-
"@agimon-ai/doompi-skill": "0.0.1-alpha.
|
|
291
|
-
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.
|
|
292
|
-
"@agimon-ai/doompi-ui": "0.0.1-alpha.
|
|
293
|
-
"@agimon-ai/doompi-web-security": "0.0.1-alpha.
|
|
280
|
+
"@agimon-ai/doompi-autostop": "0.0.1-alpha.56",
|
|
281
|
+
"@agimon-ai/doompi-cache": "0.0.1-alpha.45",
|
|
282
|
+
"@agimon-ai/doompi-config": "0.0.1-alpha.78",
|
|
283
|
+
"@agimon-ai/doompi-core": "0.0.1-alpha.79",
|
|
284
|
+
"@agimon-ai/doompi-domain": "0.0.1-alpha.57",
|
|
285
|
+
"@agimon-ai/doompi-major-mode": "0.0.1-alpha.57",
|
|
286
|
+
"@agimon-ai/doompi-minor-mode": "0.0.1-alpha.79",
|
|
287
|
+
"@agimon-ai/doompi-notification": "0.0.1-alpha.56",
|
|
288
|
+
"@agimon-ai/doompi-profile": "0.0.1-alpha.57",
|
|
289
|
+
"@agimon-ai/doompi-session": "0.0.1-alpha.3",
|
|
290
|
+
"@agimon-ai/doompi-skill": "0.0.1-alpha.57",
|
|
291
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.76",
|
|
292
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.79",
|
|
293
|
+
"@agimon-ai/doompi-web-security": "0.0.1-alpha.39",
|
|
294
294
|
"@deepseek-ai/cordis": "4.0.2",
|
|
295
295
|
"@earendil-works/chord": "0.86.0",
|
|
296
296
|
"@earendil-works/pi-agent-core": "0.86.0",
|
|
@@ -315,8 +315,8 @@
|
|
|
315
315
|
"yaml": "2.9.0"
|
|
316
316
|
},
|
|
317
317
|
"devDependencies": {
|
|
318
|
-
"@agimon-ai/doompi-runner": "0.0.1-alpha.
|
|
319
|
-
"@agimon-ai/vibe-lint-plugin-doom-cli": "0.0.1-alpha.
|
|
318
|
+
"@agimon-ai/doompi-runner": "0.0.1-alpha.79",
|
|
319
|
+
"@agimon-ai/vibe-lint-plugin-doom-cli": "0.0.1-alpha.11",
|
|
320
320
|
"@earendil-works/pi-ai": "0.86.0",
|
|
321
321
|
"@earendil-works/pi-client": "0.86.0",
|
|
322
322
|
"@earendil-works/pi-tui": "0.86.0",
|