@agimon-ai/doompi 0.0.1-alpha.73 → 0.0.1-alpha.74
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/builders/cli/projectSettings.cjs +1 -1
- package/dist/builders/cli/projectSettings.cjs.map +1 -1
- package/dist/builders/cli/projectSettings.mjs +1 -1
- package/dist/builders/cli/projectSettings.mjs.map +1 -1
- package/dist/builders/server/runtime.cjs +7 -11
- package/dist/builders/server/runtime.cjs.map +1 -1
- package/dist/builders/server/runtime.mjs +7 -11
- package/dist/builders/server/runtime.mjs.map +1 -1
- package/dist/builders/web/bundle.cjs +1 -0
- package/dist/builders/web/bundle.cjs.map +1 -1
- package/dist/builders/web/bundle.mjs +1 -0
- package/dist/builders/web/bundle.mjs.map +1 -1
- package/dist/builders/web/webPluginGenerate.cjs +12 -5
- package/dist/builders/web/webPluginGenerate.cjs.map +1 -1
- package/dist/builders/web/webPluginGenerate.d.cts.map +1 -1
- package/dist/builders/web/webPluginGenerate.d.mts.map +1 -1
- package/dist/builders/web/webPluginGenerate.mjs +12 -5
- package/dist/builders/web/webPluginGenerate.mjs.map +1 -1
- package/dist/builders/web/webPluginVite.cjs +9 -0
- package/dist/builders/web/webPluginVite.cjs.map +1 -1
- package/dist/builders/web/webPluginVite.d.cts +9 -0
- package/dist/builders/web/webPluginVite.d.cts.map +1 -1
- package/dist/builders/web/webPluginVite.d.mts +9 -0
- package/dist/builders/web/webPluginVite.d.mts.map +1 -1
- package/dist/builders/web/webPluginVite.mjs +9 -0
- package/dist/builders/web/webPluginVite.mjs.map +1 -1
- package/dist/cli/server/run.cjs +2 -0
- package/dist/cli/server/run.cjs.map +1 -1
- package/dist/cli/server/run.mjs +2 -0
- package/dist/cli/server/run.mjs.map +1 -1
- package/docs/server/api-export.md +2 -2
- package/docs/server/getting-started.md +1 -1
- package/package.json +17 -17
- package/src/prompts/doompi-author-extension/SKILL.md +4 -3
- package/src/prompts/doompi-author-extension/references/extension-contract.md +26 -26
|
@@ -57,7 +57,7 @@ function resolveSettingsPath(value, baseDirectory, homeDirectory) {
|
|
|
57
57
|
*
|
|
58
58
|
* The bare package name is matched textually because that is the spelling sync
|
|
59
59
|
* writes into the user scope, and a resolved path is matched by walking to the
|
|
60
|
-
* package it belongs to, which is what catches `../packages/
|
|
60
|
+
* package it belongs to, which is what catches `../packages/cli/doompi` and a
|
|
61
61
|
* direct reference to a file inside it. Pattern entries select among already
|
|
62
62
|
* resolved paths rather than naming one, so they are left for the user to own.
|
|
63
63
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectSettings.cjs","names":["path","DOOM_PACKAGE_NAME","isDoomPackagePath","isRecord","os","fs","readJson","piExtensionAliasPath"],"sources":["../../../src/builders/cli/projectSettings.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { DOOM_PACKAGE_NAME, isDoomPackagePath } from '@agimon-ai/doompi-core/doom-package';\nimport { isRecord, readJson, writeFileAtomic } from '@agimon-ai/doompi-core/runtime-json';\nimport type { JsonObject } from '@agimon-ai/doompi-core/runtime-json';\n\nimport { piExtensionAliasPath } from './piExtensionAlias';\n\n/**\n * Pi's project settings, as `doompi sync` reconciles them.\n *\n * Pi documents project settings as overriding user settings, but resource\n * resolution unions the two scopes and dedupes only by the resolved file's real\n * path. A repository that registers DoomPi alongside the stable user entry\n * therefore loads two installs of the same package against one home-scoped\n * worktree state. Sync removes the redundant project registration and leaves every\n * other key alone: the repository still overrides the user scope, through its own\n * `.doom` configuration and the runtime staged under `~/.pi/.doom/sync`.\n */\n\nconst PI_DIRECTORY = '.pi';\nconst SETTINGS_FILE = 'settings.json';\nconst EXTENSIONS_KEY = 'extensions';\nconst PACKAGES_KEY = 'packages';\nconst PACKAGE_SOURCE_KEY = 'source';\nconst HOME_ALIAS = '~';\nconst HOME_ALIAS_PREFIX = '~/';\n/** Pattern-form entries Pi filters with rather than resolves. */\nconst PATTERN_PREFIXES = ['!', '+', '-'] as const;\n\n/**\n * Reported by `sync --check` and `build`, and repaired by `sync`.\n *\n * Lives here rather than with either command because both report the same\n * finding about the same file, and the detector below is what decides it.\n */\nexport const DUPLICATE_REGISTRATION_DRIFT = 'duplicate DoomPi registration in .pi/settings.json';\n\n/** Pi's project configuration directory, the base its relative paths resolve against. */\nexport function projectPiDirectory(repoRoot: string): string {\n return path.join(repoRoot, PI_DIRECTORY);\n}\n\nexport function projectPiSettingsPath(repoRoot: string): string {\n return path.join(projectPiDirectory(repoRoot), SETTINGS_FILE);\n}\n\nfunction resolveSettingsPath(value: string, baseDirectory: string, homeDirectory: string): string {\n if (value === HOME_ALIAS) return homeDirectory;\n if (value.startsWith(HOME_ALIAS_PREFIX)) return path.join(homeDirectory, value.slice(HOME_ALIAS_PREFIX.length));\n return path.resolve(baseDirectory, value);\n}\n\n/**\n * Whether one settings entry names this package.\n *\n * The bare package name is matched textually because that is the spelling sync\n * writes into the user scope, and a resolved path is matched by walking to the\n * package it belongs to, which is what catches `../packages/
|
|
1
|
+
{"version":3,"file":"projectSettings.cjs","names":["path","DOOM_PACKAGE_NAME","isDoomPackagePath","isRecord","os","fs","readJson","piExtensionAliasPath"],"sources":["../../../src/builders/cli/projectSettings.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { DOOM_PACKAGE_NAME, isDoomPackagePath } from '@agimon-ai/doompi-core/doom-package';\nimport { isRecord, readJson, writeFileAtomic } from '@agimon-ai/doompi-core/runtime-json';\nimport type { JsonObject } from '@agimon-ai/doompi-core/runtime-json';\n\nimport { piExtensionAliasPath } from './piExtensionAlias';\n\n/**\n * Pi's project settings, as `doompi sync` reconciles them.\n *\n * Pi documents project settings as overriding user settings, but resource\n * resolution unions the two scopes and dedupes only by the resolved file's real\n * path. A repository that registers DoomPi alongside the stable user entry\n * therefore loads two installs of the same package against one home-scoped\n * worktree state. Sync removes the redundant project registration and leaves every\n * other key alone: the repository still overrides the user scope, through its own\n * `.doom` configuration and the runtime staged under `~/.pi/.doom/sync`.\n */\n\nconst PI_DIRECTORY = '.pi';\nconst SETTINGS_FILE = 'settings.json';\nconst EXTENSIONS_KEY = 'extensions';\nconst PACKAGES_KEY = 'packages';\nconst PACKAGE_SOURCE_KEY = 'source';\nconst HOME_ALIAS = '~';\nconst HOME_ALIAS_PREFIX = '~/';\n/** Pattern-form entries Pi filters with rather than resolves. */\nconst PATTERN_PREFIXES = ['!', '+', '-'] as const;\n\n/**\n * Reported by `sync --check` and `build`, and repaired by `sync`.\n *\n * Lives here rather than with either command because both report the same\n * finding about the same file, and the detector below is what decides it.\n */\nexport const DUPLICATE_REGISTRATION_DRIFT = 'duplicate DoomPi registration in .pi/settings.json';\n\n/** Pi's project configuration directory, the base its relative paths resolve against. */\nexport function projectPiDirectory(repoRoot: string): string {\n return path.join(repoRoot, PI_DIRECTORY);\n}\n\nexport function projectPiSettingsPath(repoRoot: string): string {\n return path.join(projectPiDirectory(repoRoot), SETTINGS_FILE);\n}\n\nfunction resolveSettingsPath(value: string, baseDirectory: string, homeDirectory: string): string {\n if (value === HOME_ALIAS) return homeDirectory;\n if (value.startsWith(HOME_ALIAS_PREFIX)) return path.join(homeDirectory, value.slice(HOME_ALIAS_PREFIX.length));\n return path.resolve(baseDirectory, value);\n}\n\n/**\n * Whether one settings entry names this package.\n *\n * The bare package name is matched textually because that is the spelling sync\n * writes into the user scope, and a resolved path is matched by walking to the\n * package it belongs to, which is what catches `../packages/cli/doompi` and a\n * direct reference to a file inside it. Pattern entries select among already\n * resolved paths rather than naming one, so they are left for the user to own.\n */\nfunction isDoomEntry(value: string, baseDirectory: string, homeDirectory: string): boolean {\n const normalized = value.replaceAll('\\\\', '/').trim();\n if (normalized === DOOM_PACKAGE_NAME) return true;\n if (PATTERN_PREFIXES.some((prefix) => normalized.startsWith(prefix))) return false;\n return isDoomPackagePath(resolveSettingsPath(normalized, baseDirectory, homeDirectory));\n}\n\nfunction packageSource(entry: unknown): string | undefined {\n if (typeof entry === 'string') return entry;\n if (isRecord(entry) && typeof entry[PACKAGE_SOURCE_KEY] === 'string') return entry[PACKAGE_SOURCE_KEY];\n return undefined;\n}\n\n/**\n * Drops DoomPi from one resource list, or reports that the key should go.\n *\n * A list that empties out is removed rather than left behind: an empty array is\n * indistinguishable from an absent one to Pi, and keeping it would leave the\n * repository looking like it still configures something.\n */\nfunction withoutDoomEntries(value: unknown, baseDirectory: string, homeDirectory: string): unknown {\n if (!Array.isArray(value)) return value;\n const kept = value.filter((entry) => {\n const source = packageSource(entry);\n return source === undefined || !isDoomEntry(source, baseDirectory, homeDirectory);\n });\n if (kept.length === value.length) return value;\n return kept.length > 0 ? kept : undefined;\n}\n\n/** Produces the project settings content for a reconciliation, without writing it. */\nexport function mergeProjectPiSettings(\n current: JsonObject,\n repoRoot: string,\n homeDirectory: string = os.homedir(),\n): JsonObject {\n const baseDirectory = projectPiDirectory(repoRoot);\n const merged: JsonObject = { ...current };\n for (const key of [EXTENSIONS_KEY, PACKAGES_KEY]) {\n if (!(key in merged)) continue;\n const next = withoutDoomEntries(merged[key], baseDirectory, homeDirectory);\n if (next === undefined) delete merged[key];\n else merged[key] = next;\n }\n return merged;\n}\n\n/** Reads Pi's project settings, or nothing when the repository declares none. */\nexport function readProjectPiSettings(repoRoot: string): JsonObject | undefined {\n const settingsPath = projectPiSettingsPath(repoRoot);\n if (!fs.existsSync(settingsPath)) return undefined;\n const settings = readJson(settingsPath);\n return isRecord(settings) ? settings : {};\n}\n\nexport function serializeProjectPiSettings(settings: JsonObject): string {\n return `${JSON.stringify(settings, null, 2)}\\n`;\n}\n\n/** True when the repository still registers DoomPi alongside the user scope. */\nexport function projectRegistersDoom(repoRoot: string, homeDirectory: string = os.homedir()): boolean {\n const settings = readProjectPiSettings(repoRoot);\n if (!settings) return false;\n return (\n serializeProjectPiSettings(mergeProjectPiSettings(settings, repoRoot, homeDirectory)) !==\n serializeProjectPiSettings(settings)\n );\n}\n\n/**\n * Removes the alias a repository-scoped registration needed.\n *\n * Only a symbolic link is removed, for the same reason sync refuses to replace\n * one: anything else at that path was not created here.\n */\nfunction removeProjectExtensionAlias(repoRoot: string): void {\n const aliasPath = piExtensionAliasPath(projectPiDirectory(repoRoot));\n if (fs.lstatSync(aliasPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n fs.rmSync(aliasPath, { force: true });\n }\n}\n\n/**\n * Reconciles the repository's Pi settings with the user-scope registration.\n *\n * The file is never created and never deleted, only rewritten: an absent one\n * means the repository registers nothing, and an existing one is a repository\n * root marker that other DoomPi code walks up to find.\n */\nexport function writeProjectPiSettings(repoRoot: string, homeDirectory: string = os.homedir()): string | undefined {\n const settings = readProjectPiSettings(repoRoot);\n removeProjectExtensionAlias(repoRoot);\n if (!settings) return undefined;\n\n const merged = mergeProjectPiSettings(settings, repoRoot, homeDirectory);\n const serialized = serializeProjectPiSettings(merged);\n if (serialized === serializeProjectPiSettings(settings)) return undefined;\n\n const settingsPath = projectPiSettingsPath(repoRoot);\n writeFileAtomic(settingsPath, serialized);\n return settingsPath;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,MAAM,eAAe;AACrB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,eAAe;AACrB,MAAM,qBAAqB;AAC3B,MAAM,aAAa;AACnB,MAAM,oBAAoB;;AAE1B,MAAM,mBAAmB;CAAC;CAAK;CAAK;AAAG;;;;;;;AAQvC,MAAa,+BAA+B;;AAG5C,SAAgB,mBAAmB,UAA0B;CAC3D,OAAOA,UAAAA,QAAK,KAAK,UAAU,YAAY;AACzC;AAEA,SAAgB,sBAAsB,UAA0B;CAC9D,OAAOA,UAAAA,QAAK,KAAK,mBAAmB,QAAQ,GAAG,aAAa;AAC9D;AAEA,SAAS,oBAAoB,OAAe,eAAuB,eAA+B;CAChG,IAAI,UAAU,YAAY,OAAO;CACjC,IAAI,MAAM,WAAW,iBAAiB,GAAG,OAAOA,UAAAA,QAAK,KAAK,eAAe,MAAM,MAAM,CAAwB,CAAC;CAC9G,OAAOA,UAAAA,QAAK,QAAQ,eAAe,KAAK;AAC1C;;;;;;;;;;AAWA,SAAS,YAAY,OAAe,eAAuB,eAAgC;CACzF,MAAM,aAAa,MAAM,WAAW,MAAM,GAAG,CAAC,CAAC,KAAK;CACpD,IAAI,eAAeC,oCAAAA,mBAAmB,OAAO;CAC7C,IAAI,iBAAiB,MAAM,WAAW,WAAW,WAAW,MAAM,CAAC,GAAG,OAAO;CAC7E,QAAA,GAAOC,oCAAAA,kBAAAA,CAAkB,oBAAoB,YAAY,eAAe,aAAa,CAAC;AACxF;AAEA,SAAS,cAAc,OAAoC;CACzD,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,KAAA,GAAIC,oCAAAA,SAAAA,CAAS,KAAK,KAAK,OAAO,MAAM,wBAAwB,UAAU,OAAO,MAAM;AAErF;;;;;;;;AASA,SAAS,mBAAmB,OAAgB,eAAuB,eAAgC;CACjG,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,OAAO;CAClC,MAAM,OAAO,MAAM,QAAQ,UAAU;EACnC,MAAM,SAAS,cAAc,KAAK;EAClC,OAAO,WAAW,KAAA,KAAa,CAAC,YAAY,QAAQ,eAAe,aAAa;CAClF,CAAC;CACD,IAAI,KAAK,WAAW,MAAM,QAAQ,OAAO;CACzC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAA;AAClC;;AAGA,SAAgB,uBACd,SACA,UACA,gBAAwBC,QAAAA,QAAG,QAAQ,GACvB;CACZ,MAAM,gBAAgB,mBAAmB,QAAQ;CACjD,MAAM,SAAqB,EAAE,GAAG,QAAQ;CACxC,KAAK,MAAM,OAAO,CAAC,gBAAgB,YAAY,GAAG;EAChD,IAAI,EAAE,OAAO,SAAS;EACtB,MAAM,OAAO,mBAAmB,OAAO,MAAM,eAAe,aAAa;EACzE,IAAI,SAAS,KAAA,GAAW,OAAO,OAAO;OACjC,OAAO,OAAO;CACrB;CACA,OAAO;AACT;;AAGA,SAAgB,sBAAsB,UAA0C;CAC9E,MAAM,eAAe,sBAAsB,QAAQ;CACnD,IAAI,CAACC,QAAAA,QAAG,WAAW,YAAY,GAAG,OAAO,KAAA;CACzC,MAAM,YAAA,GAAWC,oCAAAA,SAAAA,CAAS,YAAY;CACtC,QAAA,GAAOH,oCAAAA,SAAAA,CAAS,QAAQ,IAAI,WAAW,CAAC;AAC1C;AAEA,SAAgB,2BAA2B,UAA8B;CACvE,OAAO,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE;AAC9C;;AAGA,SAAgB,qBAAqB,UAAkB,gBAAwBC,QAAAA,QAAG,QAAQ,GAAY;CACpG,MAAM,WAAW,sBAAsB,QAAQ;CAC/C,IAAI,CAAC,UAAU,OAAO;CACtB,OACE,2BAA2B,uBAAuB,UAAU,UAAU,aAAa,CAAC,MACpF,2BAA2B,QAAQ;AAEvC;;;;;;;AAQA,SAAS,4BAA4B,UAAwB;CAC3D,MAAM,YAAYG,cAAAA,qBAAqB,mBAAmB,QAAQ,CAAC;CACnE,IAAIF,QAAAA,QAAG,UAAU,WAAW,EAAE,gBAAgB,MAAM,CAAC,CAAC,EAAE,eAAe,GACrE,QAAA,QAAG,OAAO,WAAW,EAAE,OAAO,KAAK,CAAC;AAExC;;;;;;;;AASA,SAAgB,uBAAuB,UAAkB,gBAAwBD,QAAAA,QAAG,QAAQ,GAAuB;CACjH,MAAM,WAAW,sBAAsB,QAAQ;CAC/C,4BAA4B,QAAQ;CACpC,IAAI,CAAC,UAAU,OAAO,KAAA;CAGtB,MAAM,aAAa,2BADJ,uBAAuB,UAAU,UAAU,aACP,CAAC;CACpD,IAAI,eAAe,2BAA2B,QAAQ,GAAG,OAAO,KAAA;CAEhE,MAAM,eAAe,sBAAsB,QAAQ;CACnD,CAAA,GAAA,oCAAA,gBAAA,CAAgB,cAAc,UAAU;CACxC,OAAO;AACT"}
|
|
@@ -53,7 +53,7 @@ function resolveSettingsPath(value, baseDirectory, homeDirectory) {
|
|
|
53
53
|
*
|
|
54
54
|
* The bare package name is matched textually because that is the spelling sync
|
|
55
55
|
* writes into the user scope, and a resolved path is matched by walking to the
|
|
56
|
-
* package it belongs to, which is what catches `../packages/
|
|
56
|
+
* package it belongs to, which is what catches `../packages/cli/doompi` and a
|
|
57
57
|
* direct reference to a file inside it. Pattern entries select among already
|
|
58
58
|
* resolved paths rather than naming one, so they are left for the user to own.
|
|
59
59
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectSettings.mjs","names":[],"sources":["../../../src/builders/cli/projectSettings.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { DOOM_PACKAGE_NAME, isDoomPackagePath } from '@agimon-ai/doompi-core/doom-package';\nimport { isRecord, readJson, writeFileAtomic } from '@agimon-ai/doompi-core/runtime-json';\nimport type { JsonObject } from '@agimon-ai/doompi-core/runtime-json';\n\nimport { piExtensionAliasPath } from './piExtensionAlias';\n\n/**\n * Pi's project settings, as `doompi sync` reconciles them.\n *\n * Pi documents project settings as overriding user settings, but resource\n * resolution unions the two scopes and dedupes only by the resolved file's real\n * path. A repository that registers DoomPi alongside the stable user entry\n * therefore loads two installs of the same package against one home-scoped\n * worktree state. Sync removes the redundant project registration and leaves every\n * other key alone: the repository still overrides the user scope, through its own\n * `.doom` configuration and the runtime staged under `~/.pi/.doom/sync`.\n */\n\nconst PI_DIRECTORY = '.pi';\nconst SETTINGS_FILE = 'settings.json';\nconst EXTENSIONS_KEY = 'extensions';\nconst PACKAGES_KEY = 'packages';\nconst PACKAGE_SOURCE_KEY = 'source';\nconst HOME_ALIAS = '~';\nconst HOME_ALIAS_PREFIX = '~/';\n/** Pattern-form entries Pi filters with rather than resolves. */\nconst PATTERN_PREFIXES = ['!', '+', '-'] as const;\n\n/**\n * Reported by `sync --check` and `build`, and repaired by `sync`.\n *\n * Lives here rather than with either command because both report the same\n * finding about the same file, and the detector below is what decides it.\n */\nexport const DUPLICATE_REGISTRATION_DRIFT = 'duplicate DoomPi registration in .pi/settings.json';\n\n/** Pi's project configuration directory, the base its relative paths resolve against. */\nexport function projectPiDirectory(repoRoot: string): string {\n return path.join(repoRoot, PI_DIRECTORY);\n}\n\nexport function projectPiSettingsPath(repoRoot: string): string {\n return path.join(projectPiDirectory(repoRoot), SETTINGS_FILE);\n}\n\nfunction resolveSettingsPath(value: string, baseDirectory: string, homeDirectory: string): string {\n if (value === HOME_ALIAS) return homeDirectory;\n if (value.startsWith(HOME_ALIAS_PREFIX)) return path.join(homeDirectory, value.slice(HOME_ALIAS_PREFIX.length));\n return path.resolve(baseDirectory, value);\n}\n\n/**\n * Whether one settings entry names this package.\n *\n * The bare package name is matched textually because that is the spelling sync\n * writes into the user scope, and a resolved path is matched by walking to the\n * package it belongs to, which is what catches `../packages/
|
|
1
|
+
{"version":3,"file":"projectSettings.mjs","names":[],"sources":["../../../src/builders/cli/projectSettings.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { DOOM_PACKAGE_NAME, isDoomPackagePath } from '@agimon-ai/doompi-core/doom-package';\nimport { isRecord, readJson, writeFileAtomic } from '@agimon-ai/doompi-core/runtime-json';\nimport type { JsonObject } from '@agimon-ai/doompi-core/runtime-json';\n\nimport { piExtensionAliasPath } from './piExtensionAlias';\n\n/**\n * Pi's project settings, as `doompi sync` reconciles them.\n *\n * Pi documents project settings as overriding user settings, but resource\n * resolution unions the two scopes and dedupes only by the resolved file's real\n * path. A repository that registers DoomPi alongside the stable user entry\n * therefore loads two installs of the same package against one home-scoped\n * worktree state. Sync removes the redundant project registration and leaves every\n * other key alone: the repository still overrides the user scope, through its own\n * `.doom` configuration and the runtime staged under `~/.pi/.doom/sync`.\n */\n\nconst PI_DIRECTORY = '.pi';\nconst SETTINGS_FILE = 'settings.json';\nconst EXTENSIONS_KEY = 'extensions';\nconst PACKAGES_KEY = 'packages';\nconst PACKAGE_SOURCE_KEY = 'source';\nconst HOME_ALIAS = '~';\nconst HOME_ALIAS_PREFIX = '~/';\n/** Pattern-form entries Pi filters with rather than resolves. */\nconst PATTERN_PREFIXES = ['!', '+', '-'] as const;\n\n/**\n * Reported by `sync --check` and `build`, and repaired by `sync`.\n *\n * Lives here rather than with either command because both report the same\n * finding about the same file, and the detector below is what decides it.\n */\nexport const DUPLICATE_REGISTRATION_DRIFT = 'duplicate DoomPi registration in .pi/settings.json';\n\n/** Pi's project configuration directory, the base its relative paths resolve against. */\nexport function projectPiDirectory(repoRoot: string): string {\n return path.join(repoRoot, PI_DIRECTORY);\n}\n\nexport function projectPiSettingsPath(repoRoot: string): string {\n return path.join(projectPiDirectory(repoRoot), SETTINGS_FILE);\n}\n\nfunction resolveSettingsPath(value: string, baseDirectory: string, homeDirectory: string): string {\n if (value === HOME_ALIAS) return homeDirectory;\n if (value.startsWith(HOME_ALIAS_PREFIX)) return path.join(homeDirectory, value.slice(HOME_ALIAS_PREFIX.length));\n return path.resolve(baseDirectory, value);\n}\n\n/**\n * Whether one settings entry names this package.\n *\n * The bare package name is matched textually because that is the spelling sync\n * writes into the user scope, and a resolved path is matched by walking to the\n * package it belongs to, which is what catches `../packages/cli/doompi` and a\n * direct reference to a file inside it. Pattern entries select among already\n * resolved paths rather than naming one, so they are left for the user to own.\n */\nfunction isDoomEntry(value: string, baseDirectory: string, homeDirectory: string): boolean {\n const normalized = value.replaceAll('\\\\', '/').trim();\n if (normalized === DOOM_PACKAGE_NAME) return true;\n if (PATTERN_PREFIXES.some((prefix) => normalized.startsWith(prefix))) return false;\n return isDoomPackagePath(resolveSettingsPath(normalized, baseDirectory, homeDirectory));\n}\n\nfunction packageSource(entry: unknown): string | undefined {\n if (typeof entry === 'string') return entry;\n if (isRecord(entry) && typeof entry[PACKAGE_SOURCE_KEY] === 'string') return entry[PACKAGE_SOURCE_KEY];\n return undefined;\n}\n\n/**\n * Drops DoomPi from one resource list, or reports that the key should go.\n *\n * A list that empties out is removed rather than left behind: an empty array is\n * indistinguishable from an absent one to Pi, and keeping it would leave the\n * repository looking like it still configures something.\n */\nfunction withoutDoomEntries(value: unknown, baseDirectory: string, homeDirectory: string): unknown {\n if (!Array.isArray(value)) return value;\n const kept = value.filter((entry) => {\n const source = packageSource(entry);\n return source === undefined || !isDoomEntry(source, baseDirectory, homeDirectory);\n });\n if (kept.length === value.length) return value;\n return kept.length > 0 ? kept : undefined;\n}\n\n/** Produces the project settings content for a reconciliation, without writing it. */\nexport function mergeProjectPiSettings(\n current: JsonObject,\n repoRoot: string,\n homeDirectory: string = os.homedir(),\n): JsonObject {\n const baseDirectory = projectPiDirectory(repoRoot);\n const merged: JsonObject = { ...current };\n for (const key of [EXTENSIONS_KEY, PACKAGES_KEY]) {\n if (!(key in merged)) continue;\n const next = withoutDoomEntries(merged[key], baseDirectory, homeDirectory);\n if (next === undefined) delete merged[key];\n else merged[key] = next;\n }\n return merged;\n}\n\n/** Reads Pi's project settings, or nothing when the repository declares none. */\nexport function readProjectPiSettings(repoRoot: string): JsonObject | undefined {\n const settingsPath = projectPiSettingsPath(repoRoot);\n if (!fs.existsSync(settingsPath)) return undefined;\n const settings = readJson(settingsPath);\n return isRecord(settings) ? settings : {};\n}\n\nexport function serializeProjectPiSettings(settings: JsonObject): string {\n return `${JSON.stringify(settings, null, 2)}\\n`;\n}\n\n/** True when the repository still registers DoomPi alongside the user scope. */\nexport function projectRegistersDoom(repoRoot: string, homeDirectory: string = os.homedir()): boolean {\n const settings = readProjectPiSettings(repoRoot);\n if (!settings) return false;\n return (\n serializeProjectPiSettings(mergeProjectPiSettings(settings, repoRoot, homeDirectory)) !==\n serializeProjectPiSettings(settings)\n );\n}\n\n/**\n * Removes the alias a repository-scoped registration needed.\n *\n * Only a symbolic link is removed, for the same reason sync refuses to replace\n * one: anything else at that path was not created here.\n */\nfunction removeProjectExtensionAlias(repoRoot: string): void {\n const aliasPath = piExtensionAliasPath(projectPiDirectory(repoRoot));\n if (fs.lstatSync(aliasPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n fs.rmSync(aliasPath, { force: true });\n }\n}\n\n/**\n * Reconciles the repository's Pi settings with the user-scope registration.\n *\n * The file is never created and never deleted, only rewritten: an absent one\n * means the repository registers nothing, and an existing one is a repository\n * root marker that other DoomPi code walks up to find.\n */\nexport function writeProjectPiSettings(repoRoot: string, homeDirectory: string = os.homedir()): string | undefined {\n const settings = readProjectPiSettings(repoRoot);\n removeProjectExtensionAlias(repoRoot);\n if (!settings) return undefined;\n\n const merged = mergeProjectPiSettings(settings, repoRoot, homeDirectory);\n const serialized = serializeProjectPiSettings(merged);\n if (serialized === serializeProjectPiSettings(settings)) return undefined;\n\n const settingsPath = projectPiSettingsPath(repoRoot);\n writeFileAtomic(settingsPath, serialized);\n return settingsPath;\n}\n"],"mappings":"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"}
|
|
@@ -523,18 +523,14 @@ async function runServerRuntime(options, runtime) {
|
|
|
523
523
|
return target.id;
|
|
524
524
|
},
|
|
525
525
|
dormantSessions: () => openSessions.list(),
|
|
526
|
+
removeDormantSession: (record) => openSessions.remove(record.sessionId),
|
|
526
527
|
reviveSession: async (record) => {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
}, record.sessionId);
|
|
534
|
-
} catch (error) {
|
|
535
|
-
openSessions.remove(record.sessionId);
|
|
536
|
-
throw error;
|
|
537
|
-
}
|
|
528
|
+
await openSession({
|
|
529
|
+
cwd: record.cwd,
|
|
530
|
+
name: record.name,
|
|
531
|
+
...record.parentSessionId === void 0 ? {} : { parentSessionId: record.parentSessionId },
|
|
532
|
+
...record.sessionProvenance === void 0 ? {} : { sessionProvenance: record.sessionProvenance }
|
|
533
|
+
}, record.sessionId);
|
|
538
534
|
},
|
|
539
535
|
requestAsset: (request) => webCompositions?.request(request) ?? Promise.resolve(void 0),
|
|
540
536
|
compositions: () => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.cjs","names":["createServerTelemetry","createOpenSessionRegistry","path","piAgentDirectory","createHarnessTelemetry","createHeadlessSessionManager","publishHeadlessSelectionStatus","readMinorModeCatalog","createHeadlessHub","fs","resolveSessionIdentity","crypto","os","globalDoomConfigDirectory","createWebCompositions","readSyncRegistration","resolveServerBundleSource","loadMajorModesConfig","resolveLayers","loadServerBundle","readSyncDrift","readSyncState","createRemoteRuntime","WebSocket","findRepositoryRoot","resolveSyncLocation","HARNESS_STATE_POINTER","HARNESS_STATE_KEYS","filterHookDisabledLayers","serveSessionApis","buildHarnessContext","serveHeadlessServer","listSavedSessions"],"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 { createOpenSessionRegistry, listSavedSessions } 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 { 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 // 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: path.join(piAgentDirectory(baseEnvironment), 'server'),\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 = { cleanup: () => Promise<void>; bundle: Awaited<ReturnType<typeof loadServerBundle>> };\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 }> = 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) => webCompositions?.remove({ scope: 'workspace', workspaceId }),\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 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(new URL(`${from.pathname}${from.search}`, cockpit.url), new Request(request, { headers }));\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 }>>();\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) return existing;\n const pending = admissions.get(id);\n if (pending) return pending;\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 };\n })();\n admissions.set(id, admission);\n try {\n return await admission;\n } finally {\n admissions.delete(id);\n }\n };\n\n const sessionHostOptions = (\n context: Awaited<ReturnType<typeof buildHarnessContext>>,\n bundle: Awaited<ReturnType<typeof loadServerBundle>>,\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 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 pendingSessions.set(resolved.identity.sessionId, {\n cleanup: () => activeHarnessContext.cleanup(),\n bundle: initialBundle,\n });\n await hub.create(sessionHostOptions(harnessContext, initialBundle, 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 pendingSessions.set(identity.sessionId, { cleanup: () => childContext.cleanup(), bundle });\n const created = await hub.create(sessionHostOptions(childContext, bundle, 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 cockpit = await serveHeadlessServer({\n port: options.webPort,\n headlessHub: hub,\n token: attachToken,\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 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 reviveSession: async (record: OpenSessionRecord) => {\n try {\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 } catch (error) {\n // A record whose journal or worktree is gone will fail the same way on\n // every attempt, so it is dropped rather than left offering a card\n // that cannot wake.\n openSessions.remove(record.sessionId);\n throw error;\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","createOpenSessionRegistry","path","piAgentDirectory","createHarnessTelemetry","createHeadlessSessionManager","publishHeadlessSelectionStatus","readMinorModeCatalog","createHeadlessHub","fs","resolveSessionIdentity","crypto","os","globalDoomConfigDirectory","createWebCompositions","readSyncRegistration","resolveServerBundleSource","loadMajorModesConfig","resolveLayers","loadServerBundle","readSyncDrift","readSyncState","createRemoteRuntime","WebSocket","findRepositoryRoot","resolveSyncLocation","HARNESS_STATE_POINTER","HARNESS_STATE_KEYS","filterHookDisabledLayers","serveSessionApis","buildHarnessContext","serveHeadlessServer","listSavedSessions"],"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 { createOpenSessionRegistry, listSavedSessions } 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 { 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 // 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: path.join(piAgentDirectory(baseEnvironment), 'server'),\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 = { cleanup: () => Promise<void>; bundle: Awaited<ReturnType<typeof loadServerBundle>> };\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 }> = 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) => webCompositions?.remove({ scope: 'workspace', workspaceId }),\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 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(new URL(`${from.pathname}${from.search}`, cockpit.url), new Request(request, { headers }));\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 }>>();\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) return existing;\n const pending = admissions.get(id);\n if (pending) return pending;\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 };\n })();\n admissions.set(id, admission);\n try {\n return await admission;\n } finally {\n admissions.delete(id);\n }\n };\n\n const sessionHostOptions = (\n context: Awaited<ReturnType<typeof buildHarnessContext>>,\n bundle: Awaited<ReturnType<typeof loadServerBundle>>,\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 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 pendingSessions.set(resolved.identity.sessionId, {\n cleanup: () => activeHarnessContext.cleanup(),\n bundle: initialBundle,\n });\n await hub.create(sessionHostOptions(harnessContext, initialBundle, 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 pendingSessions.set(identity.sessionId, { cleanup: () => childContext.cleanup(), bundle });\n const created = await hub.create(sessionHostOptions(childContext, bundle, 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 cockpit = await serveHeadlessServer({\n port: options.webPort,\n headlessHub: hub,\n token: attachToken,\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 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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"}
|
|
@@ -515,18 +515,14 @@ async function runServerRuntime(options, runtime) {
|
|
|
515
515
|
return target.id;
|
|
516
516
|
},
|
|
517
517
|
dormantSessions: () => openSessions.list(),
|
|
518
|
+
removeDormantSession: (record) => openSessions.remove(record.sessionId),
|
|
518
519
|
reviveSession: async (record) => {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}, record.sessionId);
|
|
526
|
-
} catch (error) {
|
|
527
|
-
openSessions.remove(record.sessionId);
|
|
528
|
-
throw error;
|
|
529
|
-
}
|
|
520
|
+
await openSession({
|
|
521
|
+
cwd: record.cwd,
|
|
522
|
+
name: record.name,
|
|
523
|
+
...record.parentSessionId === void 0 ? {} : { parentSessionId: record.parentSessionId },
|
|
524
|
+
...record.sessionProvenance === void 0 ? {} : { sessionProvenance: record.sessionProvenance }
|
|
525
|
+
}, record.sessionId);
|
|
530
526
|
},
|
|
531
527
|
requestAsset: (request) => webCompositions?.request(request) ?? Promise.resolve(void 0),
|
|
532
528
|
compositions: () => ({
|