@agimon-ai/doompi 0.0.1-alpha.17 → 0.0.1-alpha.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -92,8 +92,8 @@ A major mode is the base config. It names the extension layers for development,
92
92
  or whatever else you do. Define as many as you like; only one is active at a time, and you
93
93
  can switch it without leaving the session.
94
94
 
95
- Minor modes are switches inside that base. They start off, stack freely, and bring their
96
- own tools and instructions when turned on. Doompi ships six:
95
+ Minor modes are battery-included switches inside that base. They start off, stack freely,
96
+ and keep their model tools and skills out of context until turned on. Doompi ships six:
97
97
 
98
98
  - **Help mode** — expose package-owned guidance only while you need it.
99
99
  - **Plan mode** — make the repository read-only while you agree on an approach.
@@ -256,7 +256,15 @@ their controls.
256
256
 
257
257
  `@agimon-ai/doompi-task` keeps a task graph on disk, not a disposable checklist in the
258
258
  transcript. Dependencies and delegation survive compaction, and work can be handed to a
259
- subagent—including a smaller model when the job does not need the expensive one.
259
+ subagent—including a smaller model when the job does not need the expensive one. Seeded
260
+ `minimal` and `copilot` modes select its `task` layer; omit that layer when a major mode
261
+ should not expose the task tool.
262
+
263
+ ### Runner
264
+
265
+ `@agimon-ai/doompi-runner` replaces Pi's blocking bash tool with supervised command execution in the default
266
+ Copilot mode. Short commands still return inline; long-running commands move into the background with durable
267
+ logs and remain inspectable through `SPC r r` or the `doom-runner` CLI.
260
268
 
261
269
  ### Auto-compact
262
270
 
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`./modules/moduleResolution.cjs`),t=require(`../services/extensionAssembler.cjs`),n=require(`./piSettings.cjs`);let r=require(`@agimon-ai/doompi-config/majorModes`),i=require(`@earendil-works/pi-coding-agent`);function a(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function o(e,t,n){let i=new Set;for(let o of t){let t=e.layers[o];if(!t)throw Error(`Unknown layer: ${o}`);for(let e of t.packages??[]){let t=typeof e==`string`?e:e.name;typeof e!=`string`&&e.optional===!0||(0,r.isLocalPackageSpecifier)(t)||a(n,t)===void 0&&i.add(t)}}return[...i]}function s(t){return[...new Set(t.map(t=>`npm:${e.splitPackageSpecifier(t).name}`))]}function c(e,t){let r=n.piAgentDirectory(t);return new i.DefaultPackageManager({cwd:e,agentDir:r,settingsManager:i.SettingsManager.create(e,r,{projectTrusted:!0})})}async function l(e,n={}){let r=e.environment??process.env,i=n.resolvers??t.createLayerResolvers(e.repoRoot),l=o(e.config,e.layers,i);if(l.length===0)return[];let u=s(l),d=n.packageManager??c(e.repoRoot,r);try{await d.resolveExtensionSources(u,{local:!0})}catch(e){throw Error(`Failed to install missing DoomPi layer package(s): ${u.join(`, `)}`,{cause:e})}let f=l.filter(e=>!a(i,e)?.length);if(f.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${f.join(`, `)}`);return u}exports.ensureLayerPackages=l;
2
+ //# sourceMappingURL=layerPackageInstaller.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layerPackageInstaller.cjs","names":["splitPackageSpecifier","piAgentDirectory","DefaultPackageManager","SettingsManager","createLayerResolvers"],"sources":["../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { isLocalPackageSpecifier, type MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DefaultPackageManager, type PackageManager, SettingsManager } from '@earendil-works/pi-coding-agent';\nimport { createLayerResolvers, type ExtensionLayerResolvers } from '../services/extensionAssembler.ts';\nimport { splitPackageSpecifier } from './modules/moduleResolution.ts';\nimport { piAgentDirectory } from './piSettings.ts';\n\nconst NPM_SOURCE_PREFIX = 'npm:';\n\ntype LayerPackageManager = Pick<PackageManager, 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n}\n\nfunction resolvePackageEntries(resolvers: ExtensionLayerResolvers, specifier: string): string[] | undefined {\n const entries = resolvers.optionalPackageEntries?.(specifier);\n if (entries !== undefined) return entries;\n const entry = resolvers.optionalPackageEntry(specifier);\n return entry ? [entry] : undefined;\n}\n\n/** Finds required npm packages selected by the active layers that are not installed anywhere DoomPi resolves. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n const missing = new Set<string>();\n for (const layerName of layers) {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n for (const configured of layer.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured !== 'string' && configured.optional === true;\n if (optional || isLocalPackageSpecifier(specifier)) continue;\n // An empty entry list means the package exists but declares no usable Pi\n // extension. Leave that validation to the assembler rather than masking a\n // broken install with another copy from the registry.\n if (resolvePackageEntries(resolvers, specifier) === undefined) missing.add(specifier);\n }\n }\n return [...missing];\n}\n\nfunction npmSources(specifiers: readonly string[]): string[] {\n return [...new Set(specifiers.map((specifier) => `${NPM_SOURCE_PREFIX}${splitPackageSpecifier(specifier).name}`))];\n}\n\nfunction createPackageManager(repoRoot: string, environment: NodeJS.ProcessEnv): LayerPackageManager {\n const agentDirectory = piAgentDirectory(environment);\n const settingsManager = SettingsManager.create(repoRoot, agentDirectory, { projectTrusted: true });\n return new DefaultPackageManager({ cwd: repoRoot, agentDir: agentDirectory, settingsManager });\n}\n\n/** Installs missing selected layer packages into Pi's project-local `.pi/npm` store and verifies the retry. */\nexport async function ensureLayerPackages(\n options: EnsureLayerPackagesOptions,\n dependencies: LayerPackageInstallerDependencies = {},\n): Promise<string[]> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const missing = missingLayerPackageSpecifiers(options.config, options.layers, resolvers);\n if (missing.length === 0) return [];\n\n const sources = npmSources(missing);\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n try {\n await packageManager.resolveExtensionSources(sources, { local: true });\n } catch (error) {\n throw new Error(`Failed to install missing DoomPi layer package(s): ${sources.join(', ')}`, { cause: error });\n }\n\n const unresolved = missing.filter((specifier) => !resolvePackageEntries(resolvers, specifier)?.length);\n if (unresolved.length > 0) {\n throw new Error(\n `Installed DoomPi layer package(s) did not expose the configured Pi extension: ${unresolved.join(', ')}`,\n );\n }\n return sources;\n}\n"],"mappings":"+QAsBA,SAAS,EAAsB,EAAoC,EAAyC,CAC1G,IAAM,EAAU,EAAU,yBAAyB,EAAU,CAC7D,GAAI,IAAY,IAAA,GAAW,OAAO,EAClC,IAAM,EAAQ,EAAU,qBAAqB,EAAU,CACvD,OAAO,EAAQ,CAAC,EAAM,CAAG,IAAA,GAI3B,SAAgB,EACd,EACA,EACA,EACU,CACV,IAAM,EAAU,IAAI,IACpB,IAAK,IAAM,KAAa,EAAQ,CAC9B,IAAM,EAAQ,EAAO,OAAO,GAC5B,GAAI,CAAC,EAAO,MAAU,MAAM,kBAAkB,IAAY,CAC1D,IAAK,IAAM,KAAc,EAAM,UAAY,EAAE,CAAE,CAC7C,IAAM,EAAY,OAAO,GAAe,SAAW,EAAa,EAAW,KAC1D,OAAO,GAAe,UAAY,EAAW,WAAa,KAAA,EAAA,EAAA,yBACnC,EAAU,EAI9C,EAAsB,EAAW,EAAU,GAAK,IAAA,IAAW,EAAQ,IAAI,EAAU,EAGzF,MAAO,CAAC,GAAG,EAAQ,CAGrB,SAAS,EAAW,EAAyC,CAC3D,MAAO,CAAC,GAAG,IAAI,IAAI,EAAW,IAAK,GAAc,OAAuBA,EAAAA,sBAAsB,EAAU,CAAC,OAAO,CAAC,CAAC,CAGpH,SAAS,EAAqB,EAAkB,EAAqD,CACnG,IAAM,EAAiBC,EAAAA,iBAAiB,EAAY,CAEpD,OAAO,IAAIC,EAAAA,sBAAsB,CAAE,IAAK,EAAU,SAAU,EAAgB,gBADpDC,EAAAA,gBAAgB,OAAO,EAAU,EAAgB,CAAE,eAAgB,GAAM,CACN,CAAE,CAAC,CAIhG,eAAsB,EACpB,EACA,EAAkD,EAAE,CACjC,CACnB,IAAM,EAAc,EAAQ,aAAe,QAAQ,IAC7C,EAAY,EAAa,WAAaC,EAAAA,qBAAqB,EAAQ,SAAS,CAC5E,EAAU,EAA8B,EAAQ,OAAQ,EAAQ,OAAQ,EAAU,CACxF,GAAI,EAAQ,SAAW,EAAG,MAAO,EAAE,CAEnC,IAAM,EAAU,EAAW,EAAQ,CAC7B,EAAiB,EAAa,gBAAkB,EAAqB,EAAQ,SAAU,EAAY,CACzG,GAAI,CACF,MAAM,EAAe,wBAAwB,EAAS,CAAE,MAAO,GAAM,CAAC,OAC/D,EAAO,CACd,MAAU,MAAM,sDAAsD,EAAQ,KAAK,KAAK,GAAI,CAAE,MAAO,EAAO,CAAC,CAG/G,IAAM,EAAa,EAAQ,OAAQ,GAAc,CAAC,EAAsB,EAAW,EAAU,EAAE,OAAO,CACtG,GAAI,EAAW,OAAS,EACtB,MAAU,MACR,iFAAiF,EAAW,KAAK,KAAK,GACvG,CAEH,OAAO"}
@@ -0,0 +1,2 @@
1
+ import{splitPackageSpecifier as e}from"./modules/moduleResolution.mjs";import{createLayerResolvers as t}from"../services/extensionAssembler.mjs";import{piAgentDirectory as n}from"./piSettings.mjs";import{isLocalPackageSpecifier as r}from"@agimon-ai/doompi-config/majorModes";import{DefaultPackageManager as i,SettingsManager as a}from"@earendil-works/pi-coding-agent";function o(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function s(e,t,n){let i=new Set;for(let a of t){let t=e.layers[a];if(!t)throw Error(`Unknown layer: ${a}`);for(let e of t.packages??[]){let t=typeof e==`string`?e:e.name;typeof e!=`string`&&e.optional===!0||r(t)||o(n,t)===void 0&&i.add(t)}}return[...i]}function c(t){return[...new Set(t.map(t=>`npm:${e(t).name}`))]}function l(e,t){let r=n(t);return new i({cwd:e,agentDir:r,settingsManager:a.create(e,r,{projectTrusted:!0})})}async function u(e,n={}){let r=e.environment??process.env,i=n.resolvers??t(e.repoRoot),a=s(e.config,e.layers,i);if(a.length===0)return[];let u=c(a),d=n.packageManager??l(e.repoRoot,r);try{await d.resolveExtensionSources(u,{local:!0})}catch(e){throw Error(`Failed to install missing DoomPi layer package(s): ${u.join(`, `)}`,{cause:e})}let f=a.filter(e=>!o(i,e)?.length);if(f.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${f.join(`, `)}`);return u}export{u as ensureLayerPackages};
2
+ //# sourceMappingURL=layerPackageInstaller.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layerPackageInstaller.mjs","names":[],"sources":["../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { isLocalPackageSpecifier, type MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DefaultPackageManager, type PackageManager, SettingsManager } from '@earendil-works/pi-coding-agent';\nimport { createLayerResolvers, type ExtensionLayerResolvers } from '../services/extensionAssembler.ts';\nimport { splitPackageSpecifier } from './modules/moduleResolution.ts';\nimport { piAgentDirectory } from './piSettings.ts';\n\nconst NPM_SOURCE_PREFIX = 'npm:';\n\ntype LayerPackageManager = Pick<PackageManager, 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n}\n\nfunction resolvePackageEntries(resolvers: ExtensionLayerResolvers, specifier: string): string[] | undefined {\n const entries = resolvers.optionalPackageEntries?.(specifier);\n if (entries !== undefined) return entries;\n const entry = resolvers.optionalPackageEntry(specifier);\n return entry ? [entry] : undefined;\n}\n\n/** Finds required npm packages selected by the active layers that are not installed anywhere DoomPi resolves. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n const missing = new Set<string>();\n for (const layerName of layers) {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n for (const configured of layer.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured !== 'string' && configured.optional === true;\n if (optional || isLocalPackageSpecifier(specifier)) continue;\n // An empty entry list means the package exists but declares no usable Pi\n // extension. Leave that validation to the assembler rather than masking a\n // broken install with another copy from the registry.\n if (resolvePackageEntries(resolvers, specifier) === undefined) missing.add(specifier);\n }\n }\n return [...missing];\n}\n\nfunction npmSources(specifiers: readonly string[]): string[] {\n return [...new Set(specifiers.map((specifier) => `${NPM_SOURCE_PREFIX}${splitPackageSpecifier(specifier).name}`))];\n}\n\nfunction createPackageManager(repoRoot: string, environment: NodeJS.ProcessEnv): LayerPackageManager {\n const agentDirectory = piAgentDirectory(environment);\n const settingsManager = SettingsManager.create(repoRoot, agentDirectory, { projectTrusted: true });\n return new DefaultPackageManager({ cwd: repoRoot, agentDir: agentDirectory, settingsManager });\n}\n\n/** Installs missing selected layer packages into Pi's project-local `.pi/npm` store and verifies the retry. */\nexport async function ensureLayerPackages(\n options: EnsureLayerPackagesOptions,\n dependencies: LayerPackageInstallerDependencies = {},\n): Promise<string[]> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const missing = missingLayerPackageSpecifiers(options.config, options.layers, resolvers);\n if (missing.length === 0) return [];\n\n const sources = npmSources(missing);\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n try {\n await packageManager.resolveExtensionSources(sources, { local: true });\n } catch (error) {\n throw new Error(`Failed to install missing DoomPi layer package(s): ${sources.join(', ')}`, { cause: error });\n }\n\n const unresolved = missing.filter((specifier) => !resolvePackageEntries(resolvers, specifier)?.length);\n if (unresolved.length > 0) {\n throw new Error(\n `Installed DoomPi layer package(s) did not expose the configured Pi extension: ${unresolved.join(', ')}`,\n );\n }\n return sources;\n}\n"],"mappings":"gXAsBA,SAAS,EAAsB,EAAoC,EAAyC,CAC1G,IAAM,EAAU,EAAU,yBAAyB,EAAU,CAC7D,GAAI,IAAY,IAAA,GAAW,OAAO,EAClC,IAAM,EAAQ,EAAU,qBAAqB,EAAU,CACvD,OAAO,EAAQ,CAAC,EAAM,CAAG,IAAA,GAI3B,SAAgB,EACd,EACA,EACA,EACU,CACV,IAAM,EAAU,IAAI,IACpB,IAAK,IAAM,KAAa,EAAQ,CAC9B,IAAM,EAAQ,EAAO,OAAO,GAC5B,GAAI,CAAC,EAAO,MAAU,MAAM,kBAAkB,IAAY,CAC1D,IAAK,IAAM,KAAc,EAAM,UAAY,EAAE,CAAE,CAC7C,IAAM,EAAY,OAAO,GAAe,SAAW,EAAa,EAAW,KAC1D,OAAO,GAAe,UAAY,EAAW,WAAa,IAC3D,EAAwB,EAAU,EAI9C,EAAsB,EAAW,EAAU,GAAK,IAAA,IAAW,EAAQ,IAAI,EAAU,EAGzF,MAAO,CAAC,GAAG,EAAQ,CAGrB,SAAS,EAAW,EAAyC,CAC3D,MAAO,CAAC,GAAG,IAAI,IAAI,EAAW,IAAK,GAAc,OAAuB,EAAsB,EAAU,CAAC,OAAO,CAAC,CAAC,CAGpH,SAAS,EAAqB,EAAkB,EAAqD,CACnG,IAAM,EAAiB,EAAiB,EAAY,CAEpD,OAAO,IAAI,EAAsB,CAAE,IAAK,EAAU,SAAU,EAAgB,gBADpD,EAAgB,OAAO,EAAU,EAAgB,CAAE,eAAgB,GAAM,CACN,CAAE,CAAC,CAIhG,eAAsB,EACpB,EACA,EAAkD,EAAE,CACjC,CACnB,IAAM,EAAc,EAAQ,aAAe,QAAQ,IAC7C,EAAY,EAAa,WAAa,EAAqB,EAAQ,SAAS,CAC5E,EAAU,EAA8B,EAAQ,OAAQ,EAAQ,OAAQ,EAAU,CACxF,GAAI,EAAQ,SAAW,EAAG,MAAO,EAAE,CAEnC,IAAM,EAAU,EAAW,EAAQ,CAC7B,EAAiB,EAAa,gBAAkB,EAAqB,EAAQ,SAAU,EAAY,CACzG,GAAI,CACF,MAAM,EAAe,wBAAwB,EAAS,CAAE,MAAO,GAAM,CAAC,OAC/D,EAAO,CACd,MAAU,MAAM,sDAAsD,EAAQ,KAAK,KAAK,GAAI,CAAE,MAAO,EAAO,CAAC,CAG/G,IAAM,EAAa,EAAQ,OAAQ,GAAc,CAAC,EAAsB,EAAW,EAAU,EAAE,OAAO,CACtG,GAAI,EAAW,OAAS,EACtB,MAAU,MACR,iFAAiF,EAAW,KAAK,KAAK,GACvG,CAEH,OAAO"}
@@ -1,2 +1,2 @@
1
- const e=require(`../../_virtual/_rolldown/runtime.cjs`);let t=require(`node:url`),n=require(`node:path`);n=e.__toESM(n,1);let r=require(`node:fs`);r=e.__toESM(r,1);let i=require(`minimatch`);const a=`package.json`,o=[`!`,`+`,`-`],s=/[*?[\]{}()]/,c=[`index.ts`,`index.js`,`index.mts`,`index.mjs`,`index.cts`,`index.cjs`],l=new Set([`.ts`,`.js`,`.mts`,`.mjs`,`.cts`,`.cjs`]),u=[`import`,`module`,`node`,`default`];function d(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function f(e){try{let t=JSON.parse(r.default.readFileSync(n.default.join(e,a),`utf8`));return d(t)?t:void 0}catch{return}}function p(e){return!!(e&&d(e.pi)&&Object.hasOwn(e.pi,`extensions`))}function m(e){return o.some(t=>e.startsWith(t))}function h(e,t){return n.default.relative(e,t).split(n.default.sep).join(`/`)}function g(e,t,r){let a=t.replaceAll(`\\`,`/`).replace(/^\.\//,``);return(0,i.minimatch)(h(r,e),a)||(0,i.minimatch)(n.default.basename(e),a)||(0,i.minimatch)(e.split(n.default.sep).join(`/`),a)}function _(e,t,r){let i=t.replaceAll(`\\`,`/`).replace(/^\.\//,``);return h(r,e)===i||e.split(n.default.sep).join(`/`)===i}function v(e){for(let t of c){let i=n.default.join(e,t);if(r.default.existsSync(i))return i}}function y(e){let t;try{t=r.default.statSync(e)}catch{return[]}if(t.isFile())return[e];if(!t.isDirectory())return[];let i=[];for(let t of r.default.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let r=n.default.join(e,t.name);if((t.isFile()||t.isSymbolicLink())&&l.has(n.default.extname(t.name))){i.push(r);continue}if(!t.isDirectory()&&!t.isSymbolicLink())continue;let a=v(r);a&&i.push(a)}return i}function b(e,t,i){if(!p(t)||!d(t?.pi))return;let a=t.pi.extensions;if(!Array.isArray(a)||!a.every(e=>typeof e==`string`))throw Error(`${i} package.json pi.extensions must be an array of strings.`);let o=[];for(let t of a.filter(e=>!m(e))){let i=s.test(t)?r.default.globSync(t,{cwd:e}).sort():[t];for(let t of i)for(let r of y(n.default.resolve(e,t)))o.includes(r)||o.push(r)}let c=a.filter(e=>e.startsWith(`!`)).map(e=>e.slice(1)),l=a.filter(e=>e.startsWith(`+`)).map(e=>e.slice(1)),u=a.filter(e=>e.startsWith(`-`)).map(e=>e.slice(1)),f=o.filter(t=>!c.some(n=>g(t,n,e)));for(let t of o)!f.includes(t)&&l.some(n=>_(t,n,e))&&f.push(t);let h=f.filter(t=>!u.some(n=>_(t,n,e)));return h.length>0?h:void 0}function x(e){return(0,t.fileURLToPath)({}.resolve(e))}function S(e){try{return x(e)}catch{return}}function C(e){let t=e.split(`/`),n=e.startsWith(`@`)?2:1,r=t.slice(0,n).join(`/`),i=t.slice(n).join(`/`);return{name:r,subpath:i?`./${i}`:`.`}}function w(e){if(typeof e==`string`)return e;if(Array.isArray(e)){for(let t of e){let e=w(t);if(e)return e}return}if(typeof e!=`object`||!e)return;let t=e;for(let e of u)if(e in t){let n=w(t[e]);if(n)return n}}function T(e,t){let i=n.default.resolve(t);for(;;){let t=n.default.join(i,`node_modules`,e);if(r.default.existsSync(n.default.join(t,a)))return t;let o=n.default.dirname(i);if(o===i)return;i=o}}function E(e){let{name:r,subpath:i}=C(e);if(i!==`.`)return[x(e)];let a=T(r,n.default.dirname((0,t.fileURLToPath)(require(`url`).pathToFileURL(__filename).href))),o=a?f(a):void 0;return(a?b(a,o,r):void 0)||[(a&&p(o)?v(a):void 0)??x(e)]}function D(e){try{return E(e)}catch{return}}function O(e,t){let{name:n,subpath:r}=C(e),i=T(n,t);if(!i)return;if(r===`.`){let e=b(i,f(i),n);if(e!==void 0)return e}let a=k(e,t);return a?[a]:[]}function k(e,t){let{name:i,subpath:o}=C(e),s=T(i,t);if(!s)return;let c=n.default.join(s,a),l=n.default.join(s,o),u;try{u=JSON.parse(r.default.readFileSync(c,`utf8`))}catch{return o===`.`?v(s):r.default.existsSync(l)?l:void 0}let d=u.exports;if(d!=null){let e=w(typeof d==`object`&&!Array.isArray(d)?d[o]:o===`.`?d:void 0);if(e){let t=n.default.join(s,e);if(r.default.existsSync(t))return t}}return o===`.`?v(s):r.default.existsSync(l)?l:void 0}const A=[`module`,`main`];function j(e,t){let i=n.default.resolve(t,e);try{if(!r.default.statSync(i).isDirectory())return;let e=JSON.parse(r.default.readFileSync(n.default.join(i,a),`utf8`));return typeof e.name==`string`&&e.name.trim()?e.name.trim():void 0}catch{return}}function M(e,t){let i=n.default.resolve(t,e),a;try{a=r.default.statSync(i)}catch{return}if(a.isFile())return[i];if(!a.isDirectory())return;let o=b(i,f(i),j(e,t)??i);if(o!==void 0)return o;let s=N(e,t);return s?[s]:y(i)}function N(e,t){let i=n.default.resolve(t,e),o;try{let e=r.default.statSync(i);if(e.isFile())return i;o=e.isDirectory()}catch{return}if(!o)return;let s;try{s=JSON.parse(r.default.readFileSync(n.default.join(i,a),`utf8`))}catch{return}let c=s.exports,l=[w(typeof c==`object`&&c&&!Array.isArray(c)?c[`.`]:c)];for(let e of A)typeof s[e]==`string`&&l.push(s[e]);for(let e of l){if(!e)continue;let t=n.default.join(i,e);if(r.default.existsSync(t))return t}return v(i)}function P(e){let r=require(`url`).pathToFileURL(__filename).href.endsWith(`.ts`)?`ts`:`mjs`,i=n.default.dirname(n.default.dirname(n.default.dirname((0,t.fileURLToPath)(require(`url`).pathToFileURL(__filename).href))));return n.default.join(i,`extensions`,`entries`,`${e}.${r}`)}function F(){return n.default.join(n.default.dirname(x(`@earendil-works/pi-coding-agent`)),`cli.js`)}exports.consumerPackageEntries=O,exports.consumerPackageEntry=k,exports.localEntries=M,exports.localEntry=N,exports.localPackageName=j,exports.optionalPackageEntries=D,exports.optionalPackageEntry=S,exports.ownEntry=P,exports.packageEntries=E,exports.packageEntry=x,exports.piCliPath=F,exports.splitPackageSpecifier=C;
1
+ const e=require(`../../_virtual/_rolldown/runtime.cjs`);let t=require(`node:url`),n=require(`node:path`);n=e.__toESM(n,1);let r=require(`node:fs`);r=e.__toESM(r,1);let i=require(`minimatch`);const a=`package.json`,o=`node_modules`,s=n.default.join(`.pi`,`npm`,o),c=[`!`,`+`,`-`],l=/[*?[\]{}()]/,u=[`index.ts`,`index.js`,`index.mts`,`index.mjs`,`index.cts`,`index.cjs`],d=new Set([`.ts`,`.js`,`.mts`,`.mjs`,`.cts`,`.cjs`]),f=[`import`,`module`,`node`,`default`];function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e){try{let t=JSON.parse(r.default.readFileSync(n.default.join(e,a),`utf8`));return p(t)?t:void 0}catch{return}}function h(e){return!!(e&&p(e.pi)&&Object.hasOwn(e.pi,`extensions`))}function g(e){return c.some(t=>e.startsWith(t))}function _(e,t){return n.default.relative(e,t).split(n.default.sep).join(`/`)}function v(e,t,r){let a=t.replaceAll(`\\`,`/`).replace(/^\.\//,``);return(0,i.minimatch)(_(r,e),a)||(0,i.minimatch)(n.default.basename(e),a)||(0,i.minimatch)(e.split(n.default.sep).join(`/`),a)}function y(e,t,r){let i=t.replaceAll(`\\`,`/`).replace(/^\.\//,``);return _(r,e)===i||e.split(n.default.sep).join(`/`)===i}function b(e){for(let t of u){let i=n.default.join(e,t);if(r.default.existsSync(i))return i}}function x(e){let t;try{t=r.default.statSync(e)}catch{return[]}if(t.isFile())return[e];if(!t.isDirectory())return[];let i=[];for(let t of r.default.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let r=n.default.join(e,t.name);if((t.isFile()||t.isSymbolicLink())&&d.has(n.default.extname(t.name))){i.push(r);continue}if(!t.isDirectory()&&!t.isSymbolicLink())continue;let a=b(r);a&&i.push(a)}return i}function S(e,t,i){if(!h(t)||!p(t?.pi))return;let a=t.pi.extensions;if(!Array.isArray(a)||!a.every(e=>typeof e==`string`))throw Error(`${i} package.json pi.extensions must be an array of strings.`);let o=[];for(let t of a.filter(e=>!g(e))){let i=l.test(t)?r.default.globSync(t,{cwd:e}).sort():[t];for(let t of i)for(let r of x(n.default.resolve(e,t)))o.includes(r)||o.push(r)}let s=a.filter(e=>e.startsWith(`!`)).map(e=>e.slice(1)),c=a.filter(e=>e.startsWith(`+`)).map(e=>e.slice(1)),u=a.filter(e=>e.startsWith(`-`)).map(e=>e.slice(1)),d=o.filter(t=>!s.some(n=>v(t,n,e)));for(let t of o)!d.includes(t)&&c.some(n=>y(t,n,e))&&d.push(t);let f=d.filter(t=>!u.some(n=>y(t,n,e)));return f.length>0?f:void 0}function C(e){return(0,t.fileURLToPath)({}.resolve(e))}function w(e){try{return C(e)}catch{return}}function T(e){let t=e.split(`/`),n=e.startsWith(`@`)?2:1,r=t.slice(0,n).join(`/`),i=t.slice(n).join(`/`);return{name:r,subpath:i?`./${i}`:`.`}}function E(e){if(typeof e==`string`)return e;if(Array.isArray(e)){for(let t of e){let e=E(t);if(e)return e}return}if(typeof e!=`object`||!e)return;let t=e;for(let e of f)if(e in t){let n=E(t[e]);if(n)return n}}function D(e,t){let i=n.default.resolve(t);for(;;){let t=n.default.join(i,o,e);if(r.default.existsSync(n.default.join(t,a)))return t;let s=n.default.dirname(i);if(s===i)return;i=s}}function O(e,t){let i=n.default.join(n.default.resolve(t),s,e);return r.default.existsSync(n.default.join(i,a))?i:void 0}function k(e,t){return D(e,t)??O(e,t)}function A(e){let{name:r,subpath:i}=T(e);if(i!==`.`)return[C(e)];let a=D(r,n.default.dirname((0,t.fileURLToPath)(require(`url`).pathToFileURL(__filename).href))),o=a?m(a):void 0;return(a?S(a,o,r):void 0)||[(a&&h(o)?b(a):void 0)??C(e)]}function j(e){try{return A(e)}catch{return}}function M(e,t){let{name:n,subpath:r}=T(e),i=k(n,t);if(!i)return;if(r===`.`){let e=S(i,m(i),n);if(e!==void 0)return e}let a=N(e,t);return a?[a]:[]}function N(e,t){let{name:i,subpath:o}=T(e),s=k(i,t);if(!s)return;let c=n.default.join(s,a),l=n.default.join(s,o),u;try{u=JSON.parse(r.default.readFileSync(c,`utf8`))}catch{return o===`.`?b(s):r.default.existsSync(l)?l:void 0}let d=u.exports;if(d!=null){let e=E(typeof d==`object`&&!Array.isArray(d)?d[o]:o===`.`?d:void 0);if(e){let t=n.default.join(s,e);if(r.default.existsSync(t))return t}}return o===`.`?b(s):r.default.existsSync(l)?l:void 0}const P=[`module`,`main`];function F(e,t){let i=n.default.resolve(t,e);try{if(!r.default.statSync(i).isDirectory())return;let e=JSON.parse(r.default.readFileSync(n.default.join(i,a),`utf8`));return typeof e.name==`string`&&e.name.trim()?e.name.trim():void 0}catch{return}}function I(e,t){let i=n.default.resolve(t,e),a;try{a=r.default.statSync(i)}catch{return}if(a.isFile())return[i];if(!a.isDirectory())return;let o=S(i,m(i),F(e,t)??i);if(o!==void 0)return o;let s=L(e,t);return s?[s]:x(i)}function L(e,t){let i=n.default.resolve(t,e),o;try{let e=r.default.statSync(i);if(e.isFile())return i;o=e.isDirectory()}catch{return}if(!o)return;let s;try{s=JSON.parse(r.default.readFileSync(n.default.join(i,a),`utf8`))}catch{return}let c=s.exports,l=[E(typeof c==`object`&&c&&!Array.isArray(c)?c[`.`]:c)];for(let e of P)typeof s[e]==`string`&&l.push(s[e]);for(let e of l){if(!e)continue;let t=n.default.join(i,e);if(r.default.existsSync(t))return t}return b(i)}function R(e){let r=require(`url`).pathToFileURL(__filename).href.endsWith(`.ts`)?`ts`:`mjs`,i=n.default.dirname(n.default.dirname(n.default.dirname((0,t.fileURLToPath)(require(`url`).pathToFileURL(__filename).href))));return n.default.join(i,`extensions`,`entries`,`${e}.${r}`)}function z(){return n.default.join(n.default.dirname(C(`@earendil-works/pi-coding-agent`)),`cli.js`)}exports.consumerPackageEntries=M,exports.consumerPackageEntry=N,exports.localEntries=I,exports.localEntry=L,exports.localPackageName=F,exports.optionalPackageEntries=j,exports.optionalPackageEntry=w,exports.ownEntry=R,exports.packageEntries=A,exports.packageEntry=C,exports.piCliPath=z,exports.splitPackageSpecifier=T;
2
2
  //# sourceMappingURL=moduleResolution.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"moduleResolution.cjs","names":["fs","path"],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"moduleResolution.cjs","names":["path","fs"],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm', NODE_MODULES);\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Finds a package provisioned by Pi without mutating the consumer's package manifest. */\nfunction findManagedPackage(name: string, consumerRoot: string): string | undefined {\n const candidate = path.join(path.resolve(consumerRoot), PI_MANAGED_NPM_DIRECTORY, name);\n return fs.existsSync(path.join(candidate, PACKAGE_MANIFEST)) ? candidate : undefined;\n}\n\nfunction findConsumerPackage(name: string, consumerRoot: string): string | undefined {\n return findInstalledPackage(name, consumerRoot) ?? findManagedPackage(name, consumerRoot);\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"moduleResolution.d.cts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;AAwJA;;;;;iBAAgB,YAAA,CAAa,IAAA;;iBAKb,oBAAA,CAAqB,IAAA;;;AAcrC;;;;iBAAgB,qBAAA,CAAsB,SAAA;EAAsB,IAAA;EAAc,OAAA;AAAA;;iBAgD1D,cAAA,CAAe,SAAA;;iBAaf,sBAAA,CAAuB,SAAA;;;AAAvC;;;;;AAgBA;iBAAgB,sBAAA,CAAuB,SAAA,UAAmB,YAAA;;iBAa1C,oBAAA,CAAqB,SAAA,UAAmB,YAAA;;AAAxD;;;;;AA6CA;;iBAAgB,gBAAA,CAAiB,SAAA,UAAmB,aAAA;;;AAsBpD;;;;;AAuBA;;iBAvBgB,YAAA,CAAa,SAAA,UAAmB,aAAA;;iBAuBhC,UAAA,CAAW,SAAA,UAAmB,aAAA;AA4C9C;;;;;AAQA;;AARA,iBAAgB,QAAA,CAAS,IAAA;;iBAQT,SAAA,CAAA"}
1
+ {"version":3,"file":"moduleResolution.d.cts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;AAyJA;;;;;iBAAgB,YAAA,CAAa,IAAA;;iBAKb,oBAAA,CAAqB,IAAA;;;AAcrC;;;;iBAAgB,qBAAA,CAAsB,SAAA;EAAsB,IAAA;EAAc,OAAA;AAAA;;iBA0D1D,cAAA,CAAe,SAAA;;iBAaf,sBAAA,CAAuB,SAAA;;;AAAvC;;;;;AAgBA;iBAAgB,sBAAA,CAAuB,SAAA,UAAmB,YAAA;;iBAa1C,oBAAA,CAAqB,SAAA,UAAmB,YAAA;;AAAxD;;;;;AA6CA;;iBAAgB,gBAAA,CAAiB,SAAA,UAAmB,aAAA;;;AAsBpD;;;;;AAuBA;;iBAvBgB,YAAA,CAAa,SAAA,UAAmB,aAAA;;iBAuBhC,UAAA,CAAW,SAAA,UAAmB,aAAA;AA4C9C;;;;;AAQA;;AARA,iBAAgB,QAAA,CAAS,IAAA;;iBAQT,SAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"moduleResolution.d.mts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;AAwJA;;;;;iBAAgB,YAAA,CAAa,IAAA;;iBAKb,oBAAA,CAAqB,IAAA;;;AAcrC;;;;iBAAgB,qBAAA,CAAsB,SAAA;EAAsB,IAAA;EAAc,OAAA;AAAA;;iBAgD1D,cAAA,CAAe,SAAA;;iBAaf,sBAAA,CAAuB,SAAA;;;AAAvC;;;;;AAgBA;iBAAgB,sBAAA,CAAuB,SAAA,UAAmB,YAAA;;iBAa1C,oBAAA,CAAqB,SAAA,UAAmB,YAAA;;AAAxD;;;;;AA6CA;;iBAAgB,gBAAA,CAAiB,SAAA,UAAmB,aAAA;;;AAsBpD;;;;;AAuBA;;iBAvBgB,YAAA,CAAa,SAAA,UAAmB,aAAA;;iBAuBhC,UAAA,CAAW,SAAA,UAAmB,aAAA;AA4C9C;;;;;AAQA;;AARA,iBAAgB,QAAA,CAAS,IAAA;;iBAQT,SAAA,CAAA"}
1
+ {"version":3,"file":"moduleResolution.d.mts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;AAyJA;;;;;iBAAgB,YAAA,CAAa,IAAA;;iBAKb,oBAAA,CAAqB,IAAA;;;AAcrC;;;;iBAAgB,qBAAA,CAAsB,SAAA;EAAsB,IAAA;EAAc,OAAA;AAAA;;iBA0D1D,cAAA,CAAe,SAAA;;iBAaf,sBAAA,CAAuB,SAAA;;;AAAvC;;;;;AAgBA;iBAAgB,sBAAA,CAAuB,SAAA,UAAmB,YAAA;;iBAa1C,oBAAA,CAAqB,SAAA,UAAmB,YAAA;;AAAxD;;;;;AA6CA;;iBAAgB,gBAAA,CAAiB,SAAA,UAAmB,aAAA;;;AAsBpD;;;;;AAuBA;;iBAvBgB,YAAA,CAAa,SAAA,UAAmB,aAAA;;iBAuBhC,UAAA,CAAW,SAAA,UAAmB,aAAA;AA4C9C;;;;;AAQA;;AARA,iBAAgB,QAAA,CAAS,IAAA;;iBAQT,SAAA,CAAA"}
@@ -1,2 +1,2 @@
1
- import{fileURLToPath as e}from"node:url";import t from"node:path";import n from"node:fs";import{minimatch as r}from"minimatch";const i=`package.json`,a=[`!`,`+`,`-`],o=/[*?[\]{}()]/,s=[`index.ts`,`index.js`,`index.mts`,`index.mjs`,`index.cts`,`index.cjs`],c=new Set([`.ts`,`.js`,`.mts`,`.mjs`,`.cts`,`.cjs`]),l=[`import`,`module`,`node`,`default`];function u(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function d(e){try{let r=JSON.parse(n.readFileSync(t.join(e,i),`utf8`));return u(r)?r:void 0}catch{return}}function f(e){return!!(e&&u(e.pi)&&Object.hasOwn(e.pi,`extensions`))}function p(e){return a.some(t=>e.startsWith(t))}function m(e,n){return t.relative(e,n).split(t.sep).join(`/`)}function h(e,n,i){let a=n.replaceAll(`\\`,`/`).replace(/^\.\//,``);return r(m(i,e),a)||r(t.basename(e),a)||r(e.split(t.sep).join(`/`),a)}function g(e,n,r){let i=n.replaceAll(`\\`,`/`).replace(/^\.\//,``);return m(r,e)===i||e.split(t.sep).join(`/`)===i}function _(e){for(let r of s){let i=t.join(e,r);if(n.existsSync(i))return i}}function v(e){let r;try{r=n.statSync(e)}catch{return[]}if(r.isFile())return[e];if(!r.isDirectory())return[];let i=[];for(let r of n.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let n=t.join(e,r.name);if((r.isFile()||r.isSymbolicLink())&&c.has(t.extname(r.name))){i.push(n);continue}if(!r.isDirectory()&&!r.isSymbolicLink())continue;let a=_(n);a&&i.push(a)}return i}function y(e,r,i){if(!f(r)||!u(r?.pi))return;let a=r.pi.extensions;if(!Array.isArray(a)||!a.every(e=>typeof e==`string`))throw Error(`${i} package.json pi.extensions must be an array of strings.`);let s=[];for(let r of a.filter(e=>!p(e))){let i=o.test(r)?n.globSync(r,{cwd:e}).sort():[r];for(let n of i)for(let r of v(t.resolve(e,n)))s.includes(r)||s.push(r)}let c=a.filter(e=>e.startsWith(`!`)).map(e=>e.slice(1)),l=a.filter(e=>e.startsWith(`+`)).map(e=>e.slice(1)),d=a.filter(e=>e.startsWith(`-`)).map(e=>e.slice(1)),m=s.filter(t=>!c.some(n=>h(t,n,e)));for(let t of s)!m.includes(t)&&l.some(n=>g(t,n,e))&&m.push(t);let _=m.filter(t=>!d.some(n=>g(t,n,e)));return _.length>0?_:void 0}function b(t){return e(import.meta.resolve(t))}function x(e){try{return b(e)}catch{return}}function S(e){let t=e.split(`/`),n=e.startsWith(`@`)?2:1,r=t.slice(0,n).join(`/`),i=t.slice(n).join(`/`);return{name:r,subpath:i?`./${i}`:`.`}}function C(e){if(typeof e==`string`)return e;if(Array.isArray(e)){for(let t of e){let e=C(t);if(e)return e}return}if(typeof e!=`object`||!e)return;let t=e;for(let e of l)if(e in t){let n=C(t[e]);if(n)return n}}function w(e,r){let a=t.resolve(r);for(;;){let r=t.join(a,`node_modules`,e);if(n.existsSync(t.join(r,i)))return r;let o=t.dirname(a);if(o===a)return;a=o}}function T(n){let{name:r,subpath:i}=S(n);if(i!==`.`)return[b(n)];let a=w(r,t.dirname(e(import.meta.url))),o=a?d(a):void 0;return(a?y(a,o,r):void 0)||[(a&&f(o)?_(a):void 0)??b(n)]}function E(e){try{return T(e)}catch{return}}function D(e,t){let{name:n,subpath:r}=S(e),i=w(n,t);if(!i)return;if(r===`.`){let e=y(i,d(i),n);if(e!==void 0)return e}let a=O(e,t);return a?[a]:[]}function O(e,r){let{name:a,subpath:o}=S(e),s=w(a,r);if(!s)return;let c=t.join(s,i),l=t.join(s,o),u;try{u=JSON.parse(n.readFileSync(c,`utf8`))}catch{return o===`.`?_(s):n.existsSync(l)?l:void 0}let d=u.exports;if(d!=null){let e=C(typeof d==`object`&&!Array.isArray(d)?d[o]:o===`.`?d:void 0);if(e){let r=t.join(s,e);if(n.existsSync(r))return r}}return o===`.`?_(s):n.existsSync(l)?l:void 0}const k=[`module`,`main`];function A(e,r){let a=t.resolve(r,e);try{if(!n.statSync(a).isDirectory())return;let e=JSON.parse(n.readFileSync(t.join(a,i),`utf8`));return typeof e.name==`string`&&e.name.trim()?e.name.trim():void 0}catch{return}}function j(e,r){let i=t.resolve(r,e),a;try{a=n.statSync(i)}catch{return}if(a.isFile())return[i];if(!a.isDirectory())return;let o=y(i,d(i),A(e,r)??i);if(o!==void 0)return o;let s=M(e,r);return s?[s]:v(i)}function M(e,r){let a=t.resolve(r,e),o;try{let e=n.statSync(a);if(e.isFile())return a;o=e.isDirectory()}catch{return}if(!o)return;let s;try{s=JSON.parse(n.readFileSync(t.join(a,i),`utf8`))}catch{return}let c=s.exports,l=[C(typeof c==`object`&&c&&!Array.isArray(c)?c[`.`]:c)];for(let e of k)typeof s[e]==`string`&&l.push(s[e]);for(let e of l){if(!e)continue;let r=t.join(a,e);if(n.existsSync(r))return r}return _(a)}function N(n){let r=import.meta.url.endsWith(`.ts`)?`ts`:`mjs`,i=t.dirname(t.dirname(t.dirname(e(import.meta.url))));return t.join(i,`extensions`,`entries`,`${n}.${r}`)}function P(){return t.join(t.dirname(b(`@earendil-works/pi-coding-agent`)),`cli.js`)}export{D as consumerPackageEntries,O as consumerPackageEntry,j as localEntries,M as localEntry,A as localPackageName,E as optionalPackageEntries,x as optionalPackageEntry,N as ownEntry,T as packageEntries,b as packageEntry,P as piCliPath,S as splitPackageSpecifier};
1
+ import{fileURLToPath as e}from"node:url";import t from"node:path";import n from"node:fs";import{minimatch as r}from"minimatch";const i=`package.json`,a=`node_modules`,o=t.join(`.pi`,`npm`,a),s=[`!`,`+`,`-`],c=/[*?[\]{}()]/,l=[`index.ts`,`index.js`,`index.mts`,`index.mjs`,`index.cts`,`index.cjs`],u=new Set([`.ts`,`.js`,`.mts`,`.mjs`,`.cts`,`.cjs`]),d=[`import`,`module`,`node`,`default`];function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function p(e){try{let r=JSON.parse(n.readFileSync(t.join(e,i),`utf8`));return f(r)?r:void 0}catch{return}}function m(e){return!!(e&&f(e.pi)&&Object.hasOwn(e.pi,`extensions`))}function h(e){return s.some(t=>e.startsWith(t))}function g(e,n){return t.relative(e,n).split(t.sep).join(`/`)}function _(e,n,i){let a=n.replaceAll(`\\`,`/`).replace(/^\.\//,``);return r(g(i,e),a)||r(t.basename(e),a)||r(e.split(t.sep).join(`/`),a)}function v(e,n,r){let i=n.replaceAll(`\\`,`/`).replace(/^\.\//,``);return g(r,e)===i||e.split(t.sep).join(`/`)===i}function y(e){for(let r of l){let i=t.join(e,r);if(n.existsSync(i))return i}}function b(e){let r;try{r=n.statSync(e)}catch{return[]}if(r.isFile())return[e];if(!r.isDirectory())return[];let i=[];for(let r of n.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let n=t.join(e,r.name);if((r.isFile()||r.isSymbolicLink())&&u.has(t.extname(r.name))){i.push(n);continue}if(!r.isDirectory()&&!r.isSymbolicLink())continue;let a=y(n);a&&i.push(a)}return i}function x(e,r,i){if(!m(r)||!f(r?.pi))return;let a=r.pi.extensions;if(!Array.isArray(a)||!a.every(e=>typeof e==`string`))throw Error(`${i} package.json pi.extensions must be an array of strings.`);let o=[];for(let r of a.filter(e=>!h(e))){let i=c.test(r)?n.globSync(r,{cwd:e}).sort():[r];for(let n of i)for(let r of b(t.resolve(e,n)))o.includes(r)||o.push(r)}let s=a.filter(e=>e.startsWith(`!`)).map(e=>e.slice(1)),l=a.filter(e=>e.startsWith(`+`)).map(e=>e.slice(1)),u=a.filter(e=>e.startsWith(`-`)).map(e=>e.slice(1)),d=o.filter(t=>!s.some(n=>_(t,n,e)));for(let t of o)!d.includes(t)&&l.some(n=>v(t,n,e))&&d.push(t);let p=d.filter(t=>!u.some(n=>v(t,n,e)));return p.length>0?p:void 0}function S(t){return e(import.meta.resolve(t))}function C(e){try{return S(e)}catch{return}}function w(e){let t=e.split(`/`),n=e.startsWith(`@`)?2:1,r=t.slice(0,n).join(`/`),i=t.slice(n).join(`/`);return{name:r,subpath:i?`./${i}`:`.`}}function T(e){if(typeof e==`string`)return e;if(Array.isArray(e)){for(let t of e){let e=T(t);if(e)return e}return}if(typeof e!=`object`||!e)return;let t=e;for(let e of d)if(e in t){let n=T(t[e]);if(n)return n}}function E(e,r){let o=t.resolve(r);for(;;){let r=t.join(o,a,e);if(n.existsSync(t.join(r,i)))return r;let s=t.dirname(o);if(s===o)return;o=s}}function D(e,r){let a=t.join(t.resolve(r),o,e);return n.existsSync(t.join(a,i))?a:void 0}function O(e,t){return E(e,t)??D(e,t)}function k(n){let{name:r,subpath:i}=w(n);if(i!==`.`)return[S(n)];let a=E(r,t.dirname(e(import.meta.url))),o=a?p(a):void 0;return(a?x(a,o,r):void 0)||[(a&&m(o)?y(a):void 0)??S(n)]}function A(e){try{return k(e)}catch{return}}function j(e,t){let{name:n,subpath:r}=w(e),i=O(n,t);if(!i)return;if(r===`.`){let e=x(i,p(i),n);if(e!==void 0)return e}let a=M(e,t);return a?[a]:[]}function M(e,r){let{name:a,subpath:o}=w(e),s=O(a,r);if(!s)return;let c=t.join(s,i),l=t.join(s,o),u;try{u=JSON.parse(n.readFileSync(c,`utf8`))}catch{return o===`.`?y(s):n.existsSync(l)?l:void 0}let d=u.exports;if(d!=null){let e=T(typeof d==`object`&&!Array.isArray(d)?d[o]:o===`.`?d:void 0);if(e){let r=t.join(s,e);if(n.existsSync(r))return r}}return o===`.`?y(s):n.existsSync(l)?l:void 0}const N=[`module`,`main`];function P(e,r){let a=t.resolve(r,e);try{if(!n.statSync(a).isDirectory())return;let e=JSON.parse(n.readFileSync(t.join(a,i),`utf8`));return typeof e.name==`string`&&e.name.trim()?e.name.trim():void 0}catch{return}}function F(e,r){let i=t.resolve(r,e),a;try{a=n.statSync(i)}catch{return}if(a.isFile())return[i];if(!a.isDirectory())return;let o=x(i,p(i),P(e,r)??i);if(o!==void 0)return o;let s=I(e,r);return s?[s]:b(i)}function I(e,r){let a=t.resolve(r,e),o;try{let e=n.statSync(a);if(e.isFile())return a;o=e.isDirectory()}catch{return}if(!o)return;let s;try{s=JSON.parse(n.readFileSync(t.join(a,i),`utf8`))}catch{return}let c=s.exports,l=[T(typeof c==`object`&&c&&!Array.isArray(c)?c[`.`]:c)];for(let e of N)typeof s[e]==`string`&&l.push(s[e]);for(let e of l){if(!e)continue;let r=t.join(a,e);if(n.existsSync(r))return r}return y(a)}function L(n){let r=import.meta.url.endsWith(`.ts`)?`ts`:`mjs`,i=t.dirname(t.dirname(t.dirname(e(import.meta.url))));return t.join(i,`extensions`,`entries`,`${n}.${r}`)}function R(){return t.join(t.dirname(S(`@earendil-works/pi-coding-agent`)),`cli.js`)}export{j as consumerPackageEntries,M as consumerPackageEntry,F as localEntries,I as localEntry,P as localPackageName,A as optionalPackageEntries,C as optionalPackageEntry,L as ownEntry,k as packageEntries,S as packageEntry,R as piCliPath,w as splitPackageSpecifier};
2
2
  //# sourceMappingURL=moduleResolution.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"moduleResolution.mjs","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"moduleResolution.mjs","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm', NODE_MODULES);\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Finds a package provisioned by Pi without mutating the consumer's package manifest. */\nfunction findManagedPackage(name: string, consumerRoot: string): string | undefined {\n const candidate = path.join(path.resolve(consumerRoot), PI_MANAGED_NPM_DIRECTORY, name);\n return fs.existsSync(path.join(candidate, PACKAGE_MANIFEST)) ? candidate : undefined;\n}\n\nfunction findConsumerPackage(name: string, consumerRoot: string): string | undefined {\n return findInstalledPackage(name, consumerRoot) ?? findManagedPackage(name, consumerRoot);\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../adapters/repository/repository.cjs`),n=require(`./cli/options.cjs`);require(`../services/config/index.cjs`),require(`../utils/index.cjs`);const r=require(`../services/extensionAssembler.cjs`),i=require(`../adapters/harnessContext.cjs`),a=require(`../adapters/syncState.cjs`),o=require(`../adapters/projectPiSettings.cjs`),s=require(`../adapters/runtimeBundle.cjs`),c=require(`./syncCommand.cjs`);let l=require(`node:path`);l=e.__toESM(l,1);let u=require(`@agimon-ai/doompi-config/majorModes`),d=require(`@agimon-ai/doompi-config/domains`);function f(e,t,n){if(!a.syncStateRootMatches(e,t.root)||a.computeInputsHash(e,t.selection)!==t.inputsHash)return!1;let i=a.recordResolvedEntries(n,r.createLayerResolvers(e));return JSON.stringify(i)===JSON.stringify(t.resolved)}function p(e){return[`bundle: ${e.bundle}`,`manifest: ${e.manifest}`,`extensions: ${e.extensionCount} -> 1`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,...e.syncedBootstrap?[`bootstrap: ${e.syncedBootstrap}`,`modes: ${String(e.syncedBundleCount??0)} precompiled`]:[],...e.duplicateRegistration?[`warning: ${o.DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`]:[],``,`Doom Pi is built. The next launch will use the dist mode extension.`,``].join(`
2
- `)}var m=class{name=`build`;telemetry;constructor(e){this.telemetry=e}matches(e){return e[0]===this.name}async execute(e,r=process.env,m=process.cwd(),h=process.stdout){let g=r.DOOMPI_ROOT,_=g?l.default.resolve(g):t.findRepositoryRoot(m),v=await i.buildHarnessContext({...n.parseHarnessArgs(e.slice(1),c.selectionEnvironment(_,r),m,(0,u.loadMajorModesConfig)(_).defaultMajorMode,(0,d.loadDomains)(_).defaultDomains).options,repoRoot:_},this.telemetry);try{let e=await s.buildRuntimeBundle(v),t,n=a.readSyncState(_);if(n&&f(_,n,v.majorModesConfig)){let{buildSyncedRuntime:e}=await Promise.resolve().then(()=>require(`../adapters/syncedRuntimeBuilder.cjs`));t=await e(_,r)}return h.write(p({bundle:e.bundle,manifest:e.manifest,extensionCount:e.extensions.length,skillCount:v.resources.skillCount,agentCount:v.resources.agentCount,syncedBootstrap:t?.bootstrap,syncedBundleCount:t?Object.keys(t.bundles).length:void 0,duplicateRegistration:o.projectRegistersDoom(_)})),0}finally{await v.cleanup()}}};exports.BuildCommand=m;
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../adapters/repository/repository.cjs`),n=require(`./cli/options.cjs`);require(`../services/config/index.cjs`),require(`../utils/index.cjs`);const r=require(`../services/extensionAssembler.cjs`),i=require(`../adapters/harnessContext.cjs`),a=require(`../adapters/syncState.cjs`),o=require(`../adapters/projectPiSettings.cjs`),s=require(`../adapters/runtimeBundle.cjs`),c=require(`./syncCommand.cjs`),l=require(`../adapters/layerPackageInstaller.cjs`);let u=require(`node:path`);u=e.__toESM(u,1);let d=require(`@agimon-ai/doompi-config/majorModes`),f=require(`@agimon-ai/doompi-config/domains`);function p(e,t,n){if(!a.syncStateRootMatches(e,t.root)||a.computeInputsHash(e,t.selection)!==t.inputsHash)return!1;let i=a.recordResolvedEntries(n,r.createLayerResolvers(e));return JSON.stringify(i)===JSON.stringify(t.resolved)}function m(e){return[`bundle: ${e.bundle}`,`manifest: ${e.manifest}`,`extensions: ${e.extensionCount} -> 1`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,...e.syncedBootstrap?[`bootstrap: ${e.syncedBootstrap}`,`modes: ${String(e.syncedBundleCount??0)} precompiled`]:[],...e.duplicateRegistration?[`warning: ${o.DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`]:[],``,`Doom Pi is built. The next launch will use the dist mode extension.`,``].join(`
2
+ `)}var h=class{name=`build`;telemetry;constructor(e){this.telemetry=e}matches(e){return e[0]===this.name}async execute(e,r=process.env,h=process.cwd(),g=process.stdout){let _=r.DOOMPI_ROOT,v=_?u.default.resolve(_):t.findRepositoryRoot(h),y=await i.buildHarnessContext({...n.parseHarnessArgs(e.slice(1),c.selectionEnvironment(v,r),h,(0,d.loadMajorModesConfig)(v).defaultMajorMode,(0,f.loadDomains)(v).defaultDomains).options,repoRoot:v},this.telemetry);try{await l.ensureLayerPackages({repoRoot:v,config:y.majorModesConfig,layers:y.selectedLayers,environment:r});let e=await s.buildRuntimeBundle(y),t,n=a.readSyncState(v);if(n&&p(v,n,y.majorModesConfig)){let{buildSyncedRuntime:e}=await Promise.resolve().then(()=>require(`../adapters/syncedRuntimeBuilder.cjs`));t=await e(v,r)}return g.write(m({bundle:e.bundle,manifest:e.manifest,extensionCount:e.extensions.length,skillCount:y.resources.skillCount,agentCount:y.resources.agentCount,syncedBootstrap:t?.bootstrap,syncedBundleCount:t?Object.keys(t.bundles).length:void 0,duplicateRegistration:o.projectRegistersDoom(v)})),0}finally{await y.cleanup()}}};exports.BuildCommand=h;
3
3
  //# sourceMappingURL=buildCommand.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildCommand.cjs","names":["syncStateRootMatches","computeInputsHash","recordResolvedEntries","createLayerResolvers","DUPLICATE_REGISTRATION_DRIFT","path","findRepositoryRoot","buildHarnessContext","parseHarnessArgs","selectionEnvironment","buildRuntimeBundle","readSyncState","projectRegistersDoom"],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"8lBAqCA,SAAS,EAAmB,EAAkB,EAAkB,EAA6C,CAE3G,GADI,CAACA,EAAAA,qBAAqB,EAAU,EAAM,KAAK,EAC3CC,EAAAA,kBAAkB,EAAU,EAAM,UAAU,GAAK,EAAM,WAAY,MAAO,GAC9E,IAAM,EAAWC,EAAAA,sBAAsB,EAAkBC,EAAAA,qBAAqB,EAAS,CAAC,CACxF,OAAO,KAAK,UAAU,EAAS,GAAK,KAAK,UAAU,EAAM,SAAS,CAGpE,SAAgB,EAAkB,EAA6B,CAC7D,MAAO,CACL,eAAe,EAAO,SACtB,eAAe,EAAO,WACtB,eAAe,EAAO,eAAe,OACrC,eAAe,EAAO,aACtB,eAAe,EAAO,aACtB,GAAI,EAAO,gBACP,CAAC,eAAe,EAAO,kBAAmB,eAAe,OAAO,EAAO,mBAAqB,EAAE,CAAC,cAAc,CAC7G,EAAE,CAEN,GAAI,EAAO,sBAAwB,CAAC,eAAeC,EAAAA,6BAA6B,mBAAmB,CAAG,EAAE,CACxG,GACA,sEACA,GACD,CAAC,KAAK;EAAK,CAId,IAAa,EAAb,KAA0B,CACxB,KAAgB,QAChB,UAEA,YAAY,EAA8B,CACxC,KAAK,UAAY,EAGnB,QAAQ,EAAyB,CAC/B,OAAO,EAAK,KAAO,KAAK,KAG1B,MAAM,QACJ,EACA,EAAiC,QAAQ,IACzC,EAAmB,QAAQ,KAAK,CAChC,EAAsB,QAAQ,OACb,CACjB,IAAM,EAAgB,EAAY,YAC5B,EAAW,EAAgBC,EAAAA,QAAK,QAAQ,EAAc,CAAGC,EAAAA,mBAAmB,EAAiB,CAQ7F,EAAU,MAAMC,EAAAA,oBAAoB,CAAE,GAP7BC,EAAAA,iBACb,EAAK,MAAM,EAAE,CACbC,EAAAA,qBAAqB,EAAU,EAAY,CAC3C,GAAA,EAAA,EAAA,sBACqB,EAAS,CAAC,kBAAA,EAAA,EAAA,aACnB,EAAS,CAAC,eAE6B,CAAC,QAAS,WAAU,CAAE,KAAK,UAAU,CAC1F,GAAI,CACF,IAAM,EAAQ,MAAMC,EAAAA,mBAAmB,EAAQ,CAC3C,EACE,EAAYC,EAAAA,cAAc,EAAS,CACzC,GAAI,GAAa,EAAmB,EAAU,EAAW,EAAQ,iBAAiB,CAAE,CAClF,GAAM,CAAE,sBAAuB,MAAA,QAAA,SAAA,CAAA,SAAA,QAAM,uCAAA,CAAA,CACrC,EAAS,MAAM,EAAmB,EAAU,EAAY,CAc1D,OAZA,EAAO,MACL,EAAkB,CAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,eAAgB,EAAM,WAAW,OACjC,WAAY,EAAQ,UAAU,WAC9B,WAAY,EAAQ,UAAU,WAC9B,gBAAiB,GAAQ,UACzB,kBAAmB,EAAS,OAAO,KAAK,EAAO,QAAQ,CAAC,OAAS,IAAA,GACjE,sBAAuBC,EAAAA,qBAAqB,EAAS,CACtD,CAAC,CACH,CACM,SACC,CACR,MAAM,EAAQ,SAAS"}
1
+ {"version":3,"file":"buildCommand.cjs","names":["syncStateRootMatches","computeInputsHash","recordResolvedEntries","createLayerResolvers","DUPLICATE_REGISTRATION_DRIFT","path","findRepositoryRoot","buildHarnessContext","parseHarnessArgs","selectionEnvironment","ensureLayerPackages","buildRuntimeBundle","readSyncState","projectRegistersDoom"],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages } from '../adapters/layerPackageInstaller.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n await ensureLayerPackages({\n repoRoot,\n config: context.majorModesConfig,\n layers: context.selectedLayers,\n environment,\n });\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"ipBAsCA,SAAS,EAAmB,EAAkB,EAAkB,EAA6C,CAE3G,GADI,CAACA,EAAAA,qBAAqB,EAAU,EAAM,KAAK,EAC3CC,EAAAA,kBAAkB,EAAU,EAAM,UAAU,GAAK,EAAM,WAAY,MAAO,GAC9E,IAAM,EAAWC,EAAAA,sBAAsB,EAAkBC,EAAAA,qBAAqB,EAAS,CAAC,CACxF,OAAO,KAAK,UAAU,EAAS,GAAK,KAAK,UAAU,EAAM,SAAS,CAGpE,SAAgB,EAAkB,EAA6B,CAC7D,MAAO,CACL,eAAe,EAAO,SACtB,eAAe,EAAO,WACtB,eAAe,EAAO,eAAe,OACrC,eAAe,EAAO,aACtB,eAAe,EAAO,aACtB,GAAI,EAAO,gBACP,CAAC,eAAe,EAAO,kBAAmB,eAAe,OAAO,EAAO,mBAAqB,EAAE,CAAC,cAAc,CAC7G,EAAE,CAEN,GAAI,EAAO,sBAAwB,CAAC,eAAeC,EAAAA,6BAA6B,mBAAmB,CAAG,EAAE,CACxG,GACA,sEACA,GACD,CAAC,KAAK;EAAK,CAId,IAAa,EAAb,KAA0B,CACxB,KAAgB,QAChB,UAEA,YAAY,EAA8B,CACxC,KAAK,UAAY,EAGnB,QAAQ,EAAyB,CAC/B,OAAO,EAAK,KAAO,KAAK,KAG1B,MAAM,QACJ,EACA,EAAiC,QAAQ,IACzC,EAAmB,QAAQ,KAAK,CAChC,EAAsB,QAAQ,OACb,CACjB,IAAM,EAAgB,EAAY,YAC5B,EAAW,EAAgBC,EAAAA,QAAK,QAAQ,EAAc,CAAGC,EAAAA,mBAAmB,EAAiB,CAQ7F,EAAU,MAAMC,EAAAA,oBAAoB,CAAE,GAP7BC,EAAAA,iBACb,EAAK,MAAM,EAAE,CACbC,EAAAA,qBAAqB,EAAU,EAAY,CAC3C,GAAA,EAAA,EAAA,sBACqB,EAAS,CAAC,kBAAA,EAAA,EAAA,aACnB,EAAS,CAAC,eAE6B,CAAC,QAAS,WAAU,CAAE,KAAK,UAAU,CAC1F,GAAI,CACF,MAAMC,EAAAA,oBAAoB,CACxB,WACA,OAAQ,EAAQ,iBAChB,OAAQ,EAAQ,eAChB,cACD,CAAC,CACF,IAAM,EAAQ,MAAMC,EAAAA,mBAAmB,EAAQ,CAC3C,EACE,EAAYC,EAAAA,cAAc,EAAS,CACzC,GAAI,GAAa,EAAmB,EAAU,EAAW,EAAQ,iBAAiB,CAAE,CAClF,GAAM,CAAE,sBAAuB,MAAA,QAAA,SAAA,CAAA,SAAA,QAAM,uCAAA,CAAA,CACrC,EAAS,MAAM,EAAmB,EAAU,EAAY,CAc1D,OAZA,EAAO,MACL,EAAkB,CAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,eAAgB,EAAM,WAAW,OACjC,WAAY,EAAQ,UAAU,WAC9B,WAAY,EAAQ,UAAU,WAC9B,gBAAiB,GAAQ,UACzB,kBAAmB,EAAS,OAAO,KAAK,EAAO,QAAQ,CAAC,OAAS,IAAA,GACjE,sBAAuBC,EAAAA,qBAAqB,EAAS,CACtD,CAAC,CACH,CACM,SACC,CACR,MAAM,EAAQ,SAAS"}
@@ -1,3 +1,3 @@
1
- import{findRepositoryRoot as e}from"../adapters/repository/repository.mjs";import{parseHarnessArgs as t}from"./cli/options.mjs";import{loadDomains as n,loadMajorModesConfig as r}from"../services/config/index.mjs";import"../utils/index.mjs";import{createLayerResolvers as i}from"../services/extensionAssembler.mjs";import{buildHarnessContext as a}from"../adapters/harnessContext.mjs";import{computeInputsHash as o,readSyncState as s,recordResolvedEntries as c,syncStateRootMatches as l}from"../adapters/syncState.mjs";import{DUPLICATE_REGISTRATION_DRIFT as u,projectRegistersDoom as d}from"../adapters/projectPiSettings.mjs";import{buildRuntimeBundle as f}from"../adapters/runtimeBundle.mjs";import{selectionEnvironment as p}from"./syncCommand.mjs";import m from"node:path";function h(e,t,n){if(!l(e,t.root)||o(e,t.selection)!==t.inputsHash)return!1;let r=c(n,i(e));return JSON.stringify(r)===JSON.stringify(t.resolved)}function g(e){return[`bundle: ${e.bundle}`,`manifest: ${e.manifest}`,`extensions: ${e.extensionCount} -> 1`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,...e.syncedBootstrap?[`bootstrap: ${e.syncedBootstrap}`,`modes: ${String(e.syncedBundleCount??0)} precompiled`]:[],...e.duplicateRegistration?[`warning: ${u}; run doompi sync`]:[],``,`Doom Pi is built. The next launch will use the dist mode extension.`,``].join(`
2
- `)}var _=class{name=`build`;telemetry;constructor(e){this.telemetry=e}matches(e){return e[0]===this.name}async execute(i,o=process.env,c=process.cwd(),l=process.stdout){let u=o.DOOMPI_ROOT,_=u?m.resolve(u):e(c),v=await a({...t(i.slice(1),p(_,o),c,r(_).defaultMajorMode,n(_).defaultDomains).options,repoRoot:_},this.telemetry);try{let e=await f(v),t,n=s(_);if(n&&h(_,n,v.majorModesConfig)){let{buildSyncedRuntime:e}=await import(`../adapters/syncedRuntimeBuilder.mjs`);t=await e(_,o)}return l.write(g({bundle:e.bundle,manifest:e.manifest,extensionCount:e.extensions.length,skillCount:v.resources.skillCount,agentCount:v.resources.agentCount,syncedBootstrap:t?.bootstrap,syncedBundleCount:t?Object.keys(t.bundles).length:void 0,duplicateRegistration:d(_)})),0}finally{await v.cleanup()}}};export{_ as BuildCommand};
1
+ import{findRepositoryRoot as e}from"../adapters/repository/repository.mjs";import{parseHarnessArgs as t}from"./cli/options.mjs";import{loadDomains as n,loadMajorModesConfig as r}from"../services/config/index.mjs";import"../utils/index.mjs";import{createLayerResolvers as i}from"../services/extensionAssembler.mjs";import{buildHarnessContext as a}from"../adapters/harnessContext.mjs";import{computeInputsHash as o,readSyncState as s,recordResolvedEntries as c,syncStateRootMatches as l}from"../adapters/syncState.mjs";import{DUPLICATE_REGISTRATION_DRIFT as u,projectRegistersDoom as d}from"../adapters/projectPiSettings.mjs";import{buildRuntimeBundle as f}from"../adapters/runtimeBundle.mjs";import{selectionEnvironment as p}from"./syncCommand.mjs";import{ensureLayerPackages as m}from"../adapters/layerPackageInstaller.mjs";import h from"node:path";function g(e,t,n){if(!l(e,t.root)||o(e,t.selection)!==t.inputsHash)return!1;let r=c(n,i(e));return JSON.stringify(r)===JSON.stringify(t.resolved)}function _(e){return[`bundle: ${e.bundle}`,`manifest: ${e.manifest}`,`extensions: ${e.extensionCount} -> 1`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,...e.syncedBootstrap?[`bootstrap: ${e.syncedBootstrap}`,`modes: ${String(e.syncedBundleCount??0)} precompiled`]:[],...e.duplicateRegistration?[`warning: ${u}; run doompi sync`]:[],``,`Doom Pi is built. The next launch will use the dist mode extension.`,``].join(`
2
+ `)}var v=class{name=`build`;telemetry;constructor(e){this.telemetry=e}matches(e){return e[0]===this.name}async execute(i,o=process.env,c=process.cwd(),l=process.stdout){let u=o.DOOMPI_ROOT,v=u?h.resolve(u):e(c),y=await a({...t(i.slice(1),p(v,o),c,r(v).defaultMajorMode,n(v).defaultDomains).options,repoRoot:v},this.telemetry);try{await m({repoRoot:v,config:y.majorModesConfig,layers:y.selectedLayers,environment:o});let e=await f(y),t,n=s(v);if(n&&g(v,n,y.majorModesConfig)){let{buildSyncedRuntime:e}=await import(`../adapters/syncedRuntimeBuilder.mjs`);t=await e(v,o)}return l.write(_({bundle:e.bundle,manifest:e.manifest,extensionCount:e.extensions.length,skillCount:y.resources.skillCount,agentCount:y.resources.agentCount,syncedBootstrap:t?.bootstrap,syncedBundleCount:t?Object.keys(t.bundles).length:void 0,duplicateRegistration:d(v)})),0}finally{await y.cleanup()}}};export{v as BuildCommand};
3
3
  //# sourceMappingURL=buildCommand.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildCommand.mjs","names":[],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"qwBAqCA,SAAS,EAAmB,EAAkB,EAAkB,EAA6C,CAE3G,GADI,CAAC,EAAqB,EAAU,EAAM,KAAK,EAC3C,EAAkB,EAAU,EAAM,UAAU,GAAK,EAAM,WAAY,MAAO,GAC9E,IAAM,EAAW,EAAsB,EAAkB,EAAqB,EAAS,CAAC,CACxF,OAAO,KAAK,UAAU,EAAS,GAAK,KAAK,UAAU,EAAM,SAAS,CAGpE,SAAgB,EAAkB,EAA6B,CAC7D,MAAO,CACL,eAAe,EAAO,SACtB,eAAe,EAAO,WACtB,eAAe,EAAO,eAAe,OACrC,eAAe,EAAO,aACtB,eAAe,EAAO,aACtB,GAAI,EAAO,gBACP,CAAC,eAAe,EAAO,kBAAmB,eAAe,OAAO,EAAO,mBAAqB,EAAE,CAAC,cAAc,CAC7G,EAAE,CAEN,GAAI,EAAO,sBAAwB,CAAC,eAAe,EAA6B,mBAAmB,CAAG,EAAE,CACxG,GACA,sEACA,GACD,CAAC,KAAK;EAAK,CAId,IAAa,EAAb,KAA0B,CACxB,KAAgB,QAChB,UAEA,YAAY,EAA8B,CACxC,KAAK,UAAY,EAGnB,QAAQ,EAAyB,CAC/B,OAAO,EAAK,KAAO,KAAK,KAG1B,MAAM,QACJ,EACA,EAAiC,QAAQ,IACzC,EAAmB,QAAQ,KAAK,CAChC,EAAsB,QAAQ,OACb,CACjB,IAAM,EAAgB,EAAY,YAC5B,EAAW,EAAgB,EAAK,QAAQ,EAAc,CAAG,EAAmB,EAAiB,CAQ7F,EAAU,MAAM,EAAoB,CAAE,GAP7B,EACb,EAAK,MAAM,EAAE,CACb,EAAqB,EAAU,EAAY,CAC3C,EACA,EAAqB,EAAS,CAAC,iBAC/B,EAAY,EAAS,CAAC,eAE6B,CAAC,QAAS,WAAU,CAAE,KAAK,UAAU,CAC1F,GAAI,CACF,IAAM,EAAQ,MAAM,EAAmB,EAAQ,CAC3C,EACE,EAAY,EAAc,EAAS,CACzC,GAAI,GAAa,EAAmB,EAAU,EAAW,EAAQ,iBAAiB,CAAE,CAClF,GAAM,CAAE,sBAAuB,MAAM,OAAO,wCAC5C,EAAS,MAAM,EAAmB,EAAU,EAAY,CAc1D,OAZA,EAAO,MACL,EAAkB,CAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,eAAgB,EAAM,WAAW,OACjC,WAAY,EAAQ,UAAU,WAC9B,WAAY,EAAQ,UAAU,WAC9B,gBAAiB,GAAQ,UACzB,kBAAmB,EAAS,OAAO,KAAK,EAAO,QAAQ,CAAC,OAAS,IAAA,GACjE,sBAAuB,EAAqB,EAAS,CACtD,CAAC,CACH,CACM,SACC,CACR,MAAM,EAAQ,SAAS"}
1
+ {"version":3,"file":"buildCommand.mjs","names":[],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages } from '../adapters/layerPackageInstaller.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n await ensureLayerPackages({\n repoRoot,\n config: context.majorModesConfig,\n layers: context.selectedLayers,\n environment,\n });\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"i1BAsCA,SAAS,EAAmB,EAAkB,EAAkB,EAA6C,CAE3G,GADI,CAAC,EAAqB,EAAU,EAAM,KAAK,EAC3C,EAAkB,EAAU,EAAM,UAAU,GAAK,EAAM,WAAY,MAAO,GAC9E,IAAM,EAAW,EAAsB,EAAkB,EAAqB,EAAS,CAAC,CACxF,OAAO,KAAK,UAAU,EAAS,GAAK,KAAK,UAAU,EAAM,SAAS,CAGpE,SAAgB,EAAkB,EAA6B,CAC7D,MAAO,CACL,eAAe,EAAO,SACtB,eAAe,EAAO,WACtB,eAAe,EAAO,eAAe,OACrC,eAAe,EAAO,aACtB,eAAe,EAAO,aACtB,GAAI,EAAO,gBACP,CAAC,eAAe,EAAO,kBAAmB,eAAe,OAAO,EAAO,mBAAqB,EAAE,CAAC,cAAc,CAC7G,EAAE,CAEN,GAAI,EAAO,sBAAwB,CAAC,eAAe,EAA6B,mBAAmB,CAAG,EAAE,CACxG,GACA,sEACA,GACD,CAAC,KAAK;EAAK,CAId,IAAa,EAAb,KAA0B,CACxB,KAAgB,QAChB,UAEA,YAAY,EAA8B,CACxC,KAAK,UAAY,EAGnB,QAAQ,EAAyB,CAC/B,OAAO,EAAK,KAAO,KAAK,KAG1B,MAAM,QACJ,EACA,EAAiC,QAAQ,IACzC,EAAmB,QAAQ,KAAK,CAChC,EAAsB,QAAQ,OACb,CACjB,IAAM,EAAgB,EAAY,YAC5B,EAAW,EAAgB,EAAK,QAAQ,EAAc,CAAG,EAAmB,EAAiB,CAQ7F,EAAU,MAAM,EAAoB,CAAE,GAP7B,EACb,EAAK,MAAM,EAAE,CACb,EAAqB,EAAU,EAAY,CAC3C,EACA,EAAqB,EAAS,CAAC,iBAC/B,EAAY,EAAS,CAAC,eAE6B,CAAC,QAAS,WAAU,CAAE,KAAK,UAAU,CAC1F,GAAI,CACF,MAAM,EAAoB,CACxB,WACA,OAAQ,EAAQ,iBAChB,OAAQ,EAAQ,eAChB,cACD,CAAC,CACF,IAAM,EAAQ,MAAM,EAAmB,EAAQ,CAC3C,EACE,EAAY,EAAc,EAAS,CACzC,GAAI,GAAa,EAAmB,EAAU,EAAW,EAAQ,iBAAiB,CAAE,CAClF,GAAM,CAAE,sBAAuB,MAAM,OAAO,wCAC5C,EAAS,MAAM,EAAmB,EAAU,EAAY,CAc1D,OAZA,EAAO,MACL,EAAkB,CAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,eAAgB,EAAM,WAAW,OACjC,WAAY,EAAQ,UAAU,WAC9B,WAAY,EAAQ,UAAU,WAC9B,gBAAiB,GAAQ,UACzB,kBAAmB,EAAS,OAAO,KAAK,EAAO,QAAQ,CAAC,OAAS,IAAA,GACjE,sBAAuB,EAAqB,EAAS,CACtD,CAAC,CACH,CACM,SACC,CACR,MAAM,EAAQ,SAAS"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../adapters/modules/moduleResolution.cjs`);require(`../utils/index.cjs`);let t=require(`@agimon-ai/doompi-config/majorModes`);const n=`@agimon-ai/doompi-user-feedback`;function r(e){return e===`@juicesharp/rpiv-ask-user-question`?n:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${n}${e.slice(34)}`:e}const i={ownEntry:e.ownEntry,packageEntry:t=>e.packageEntry(r(t)),optionalPackageEntry:t=>e.optionalPackageEntry(r(t)),packageEntries:t=>e.packageEntries(r(t)),optionalPackageEntries:t=>e.optionalPackageEntries(r(t)),localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName};function a(t){return t?{ownEntry:e.ownEntry,packageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.packageEntry(i)},optionalPackageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.optionalPackageEntry(i)},packageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.packageEntries(i)},optionalPackageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.optionalPackageEntries(i)},localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName}:i}const o=`guardrails`,s=`vibe-lint`,c=`code-intel`,l=`runner`,u=`ask-user`,d=`style-system`,f={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},p={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,task:`@agimon-ai/doompi-task/extensions/pi`,voice:`@agimon-ai/doompi-voice/extensions/doom`,goalDoom:`@agimon-ai/doompi-goal/extensions/doom`},m=new Set([o,s,c]),h={mcp:`@agimon-ai/doompi-mcp/extensions/pi`,workflow:`@agimon-ai/doompi-workflow/extensions/pi`,dispatcherWorkflow:`@agimon-ai/doompi-workflow/extensions/dispatcher`},g=`persona`;function _(e){let t=r(e),n=t.split(`/`);return t.startsWith(`@`)?n.slice(0,2).join(`/`):n[0]??t}function v(e,t,n){return{name:`own:${e}`,path:t,priority:n}}function y(e,t,n,r=0){let i=r===0?``:`:${r}`;return{name:`package:${_(e)}${i}`,path:t,priority:n}}function b(e,t,n=0){let r=n===0?``:`:${n}`;return{name:t?`package:${_(t)}${r}`:`local:${e.replaceAll(`\\`,`/`)}`,path:e,priority:1}}function x(e,t,n){let r=e.localEntries?.(t,n);if(r!==void 0)return r;let i=e.localEntry(t,n);return i?[i]:void 0}function S(e,n,r){let i=e.layers[n];if(!i)throw Error(`Unknown layer: ${n}`);let a=[];for(let e of i.extensions??[]){if(!(0,t.isLocalPackageSpecifier)(e)){a.push(v(e,r.ownEntry(e),1));continue}let o=x(r,e,i.baseDirectory);if(!o?.length)throw Error(`Layer "${n}" extension "${e}" does not resolve under ${i.baseDirectory}. Point it at a Pi extension file or directory.`);a.push(...o.map(e=>b(e)))}for(let e of i.packages??[]){let o=typeof e==`string`?e:e.name,s=typeof e==`string`?!1:e.optional===!0;if((0,t.isLocalPackageSpecifier)(o)){let e=x(r,o,i.baseDirectory);if(e?.length){let t=r.localPackageName?.(o,i.baseDirectory);a.push(...e.map((e,n)=>b(e,t,n)))}else if(!s)throw Error(`Layer "${n}" package "${o}" does not resolve under ${i.baseDirectory}. Point it at an extension file, or a directory whose package.json declares pi.extensions.`);continue}let c;if(s){if(c=r.optionalPackageEntries?.(o),c===void 0){let e=r.optionalPackageEntry(o);c=e?[e]:void 0}}else c=r.packageEntries?.(o)??[r.packageEntry(o)];if(c?.length)a.push(...c.map((e,t)=>y(o,e,1,t)));else if(!s)throw Error(`Layer "${n}" package "${o}" declares no Pi extensions.`)}return a}function C(e){let t=[];for(let n of e){let e=n.path.replaceAll(`\\`,`/`),r=t.findIndex(t=>t.name===n.name||t.path.replaceAll(`\\`,`/`)===e);if(r===-1){t.push(n);continue}let i=t[r];i&&n.priority>i.priority&&(t[r]=n)}return t.map(e=>e.path)}function w(e){let t=e.majorModesConfig,n=e.resolvers??i,r=e=>v(e,n.ownEntry(e),0),a=e=>y(e,n.packageEntry(e),0),m=new Set(e.layers),_=e=>m.has(e)?S(t,e,n):[],b=[];return e.mcpEntry&&b.push(y(h.mcp,e.mcpEntry,2)),b.push(a(p.logSinkTelemetry)),e.personaEntry&&b.push(v(g,e.personaEntry,2)),e.workflowExtension&&b.push(y(h.workflow,e.workflowExtension,2)),b.push(..._(`agiflow`),..._(o),..._(s),..._(c)),e.preset===`ollama`&&b.push(r(f.ollamaProvider)),b.push(r(f.effort)),b.push(..._(`plan-mode`)),b.push(a(p.task)),b.push(a(p.loop)),b.push(a(p.autocompact)),b.push(a(p.fileEdit)),b.push(..._(l)),b.push(..._(u),..._(d)),b.push(a(p.voice)),b.push(r(f.domains)),b.push(r(f.skills)),b.push(r(f.majorMode)),b.push(r(f.profile)),b.push(a(p.goalDoom)),b.push(r(f.cacheOptimizer)),e.mute||b.push(r(f.notifications)),e.agents&&b.push(..._(`team`)),b.push(a(p.doomHelp)),b.push(a(p.doomUi)),b.push(a(p.doomConfig)),b.push(r(f.modeCatalog)),e.autoStop&&b.unshift(r(f.autoStop)),C(b)}function T(e){let t=e.resolvers??i,n=e=>y(e,t.packageEntry(e),0),r=new Set(e.layers),a=n=>r.has(n)?S(e.majorModesConfig,n,t):[],m=[];return e.mcpEntry&&m.push(y(h.mcp,e.mcpEntry,2)),m.push(n(p.logSinkTelemetry)),e.personaEntry&&m.push(v(g,e.personaEntry,2)),e.preset===`ollama`&&m.push(v(f.ollamaProvider,t.ownEntry(f.ollamaProvider),0)),m.push(...a(o),...a(s),...a(c),...a(l),...a(u),...a(d)),m.push(n(p.autocompact)),m.push(n(p.doomConfig)),C(m)}function E(e,t){return t?[...e]:e.filter(e=>!m.has(e))}exports.CONTEXT_PACKAGES=h,exports.LAYER_RESOLVERS=i,exports.LEGACY_ASK_USER_PACKAGE=`@juicesharp/rpiv-ask-user-question`,exports.OLLAMA_PRESET=`ollama`,exports.PERSONA_ENTRY=g,exports.USER_FEEDBACK_PACKAGE=n,exports.assembleChildExtensions=T,exports.assembleExtensions=w,exports.canonicalPackageSpecifier=r,exports.createLayerResolvers=a,exports.filterHookDisabledLayers=E;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../adapters/modules/moduleResolution.cjs`);require(`../utils/index.cjs`);let t=require(`@agimon-ai/doompi-config/majorModes`);const n=`@agimon-ai/doompi-user-feedback`;function r(e){return e===`@juicesharp/rpiv-ask-user-question`?n:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${n}${e.slice(34)}`:e}const i={ownEntry:e.ownEntry,packageEntry:t=>e.packageEntry(r(t)),optionalPackageEntry:t=>e.optionalPackageEntry(r(t)),packageEntries:t=>e.packageEntries(r(t)),optionalPackageEntries:t=>e.optionalPackageEntries(r(t)),localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName};function a(t){return t?{ownEntry:e.ownEntry,packageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.packageEntry(i)},optionalPackageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.optionalPackageEntry(i)},packageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.packageEntries(i)},optionalPackageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.optionalPackageEntries(i)},localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName}:i}const o=`guardrails`,s=`vibe-lint`,c=`code-intel`,l=`runner`,u=`ask-user`,d=`style-system`,f={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},p={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,planDoom:`@agimon-ai/doompi-plan/extensions/doom`,voice:`@agimon-ai/doompi-voice/extensions/doom`,goalDoom:`@agimon-ai/doompi-goal/extensions/doom`},m=new Set([o,s,c]),h={mcp:`@agimon-ai/doompi-mcp/extensions/pi`,workflow:`@agimon-ai/doompi-workflow/extensions/pi`,dispatcherWorkflow:`@agimon-ai/doompi-workflow/extensions/dispatcher`},g=`persona`;function _(e){let t=r(e),n=t.split(`/`);return t.startsWith(`@`)?n.slice(0,2).join(`/`):n[0]??t}function v(e,t,n){return{name:`own:${e}`,path:t,priority:n}}function y(e,t,n,r=0){let i=r===0?``:`:${r}`;return{name:`package:${_(e)}${i}`,path:t,priority:n}}function b(e,t,n=0){let r=n===0?``:`:${n}`;return{name:t?`package:${_(t)}${r}`:`local:${e.replaceAll(`\\`,`/`)}`,path:e,priority:1}}function x(e,t,n){let r=e.localEntries?.(t,n);if(r!==void 0)return r;let i=e.localEntry(t,n);return i?[i]:void 0}function S(e,n,r){let i=e.layers[n];if(!i)throw Error(`Unknown layer: ${n}`);let a=[];for(let e of i.extensions??[]){if(!(0,t.isLocalPackageSpecifier)(e)){a.push(v(e,r.ownEntry(e),1));continue}let o=x(r,e,i.baseDirectory);if(!o?.length)throw Error(`Layer "${n}" extension "${e}" does not resolve under ${i.baseDirectory}. Point it at a Pi extension file or directory.`);a.push(...o.map(e=>b(e)))}for(let e of i.packages??[]){let o=typeof e==`string`?e:e.name,s=typeof e==`string`?!1:e.optional===!0;if((0,t.isLocalPackageSpecifier)(o)){let e=x(r,o,i.baseDirectory);if(e?.length){let t=r.localPackageName?.(o,i.baseDirectory);a.push(...e.map((e,n)=>b(e,t,n)))}else if(!s)throw Error(`Layer "${n}" package "${o}" does not resolve under ${i.baseDirectory}. Point it at an extension file, or a directory whose package.json declares pi.extensions.`);continue}let c;if(s){if(c=r.optionalPackageEntries?.(o),c===void 0){let e=r.optionalPackageEntry(o);c=e?[e]:void 0}}else c=r.packageEntries?.(o)??[r.packageEntry(o)];if(c?.length)a.push(...c.map((e,t)=>y(o,e,1,t)));else if(!s)throw Error(`Layer "${n}" package "${o}" declares no Pi extensions.`)}return a}function C(e){let t=[];for(let n of e){let e=n.path.replaceAll(`\\`,`/`),r=t.findIndex(t=>t.name===n.name||t.path.replaceAll(`\\`,`/`)===e);if(r===-1){t.push(n);continue}let i=t[r];i&&n.priority>i.priority&&(t[r]=n)}return t.map(e=>e.path)}function w(e){let t=e.majorModesConfig,n=e.resolvers??i,r=e=>v(e,n.ownEntry(e),0),a=e=>y(e,n.packageEntry(e),0),m=new Set(e.layers),_=e=>m.has(e)?S(t,e,n):[],b=[];return e.mcpEntry&&b.push(y(h.mcp,e.mcpEntry,2)),b.push(a(p.logSinkTelemetry)),e.personaEntry&&b.push(v(g,e.personaEntry,2)),e.workflowExtension&&b.push(y(h.workflow,e.workflowExtension,2)),b.push(..._(`agiflow`),..._(o),..._(s),..._(c)),e.preset===`ollama`&&b.push(r(f.ollamaProvider)),b.push(r(f.effort)),b.push(a(p.planDoom)),b.push(..._(`task`)),b.push(a(p.loop)),b.push(a(p.autocompact)),b.push(a(p.fileEdit)),b.push(..._(l)),b.push(..._(u),..._(d)),b.push(a(p.voice)),b.push(r(f.domains)),b.push(r(f.skills)),b.push(r(f.majorMode)),b.push(r(f.profile)),b.push(a(p.goalDoom)),b.push(r(f.cacheOptimizer)),e.mute||b.push(r(f.notifications)),e.agents&&b.push(..._(`team`)),b.push(a(p.doomHelp)),b.push(a(p.doomUi)),b.push(a(p.doomConfig)),b.push(r(f.modeCatalog)),e.autoStop&&b.unshift(r(f.autoStop)),C(b)}function T(e){let t=e.resolvers??i,n=e=>y(e,t.packageEntry(e),0),r=new Set(e.layers),a=n=>r.has(n)?S(e.majorModesConfig,n,t):[],m=[];return e.mcpEntry&&m.push(y(h.mcp,e.mcpEntry,2)),m.push(n(p.logSinkTelemetry)),e.personaEntry&&m.push(v(g,e.personaEntry,2)),e.preset===`ollama`&&m.push(v(f.ollamaProvider,t.ownEntry(f.ollamaProvider),0)),m.push(...a(o),...a(s),...a(c),...a(l),...a(u),...a(d)),m.push(n(p.autocompact)),m.push(n(p.doomConfig)),C(m)}function E(e,t){return t?[...e]:e.filter(e=>!m.has(e))}exports.CONTEXT_PACKAGES=h,exports.LAYER_RESOLVERS=i,exports.LEGACY_ASK_USER_PACKAGE=`@juicesharp/rpiv-ask-user-question`,exports.OLLAMA_PRESET=`ollama`,exports.PERSONA_ENTRY=g,exports.USER_FEEDBACK_PACKAGE=n,exports.assembleChildExtensions=T,exports.assembleExtensions=w,exports.canonicalPackageSpecifier=r,exports.createLayerResolvers=a,exports.filterHookDisabledLayers=E;
2
2
  //# sourceMappingURL=extensionAssembler.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensionAssembler.cjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName","consumerPackageEntry","consumerPackageEntries"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_PLAN_MODE = 'plan-mode';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n task: '@agimon-ai/doompi-task/extensions/pi',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n extensions.push(...layer(LAYER_PLAN_MODE));\n extensions.push(pkg(PACKAGE_ENTRIES.task));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"extensionAssembler.cjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName","consumerPackageEntry","consumerPackageEntries"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_TASK = 'task';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n planDoom: '@agimon-ai/doompi-plan/extensions/doom',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n // Plan is a battery-included minor mode. Its tools stay inactive until the\n // user enters Plan, while its Doom adapter keeps Leader and mode metadata ready.\n extensions.push(pkg(PACKAGE_ENTRIES.planDoom));\n // Task is a major-mode capability: selected modes opt into its persistent graph.\n extensions.push(...layer(LAYER_TASK));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"extensionAssembler.d.cts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;iBA+NgB,uBAAA,CAAwB,OAAA,EAAS,gBAAA;;iBAyCjC,wBAAA,CAAyB,MAAA,YAAkB,KAAA"}
1
+ {"version":3,"file":"extensionAssembler.d.cts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;iBAkOgB,uBAAA,CAAwB,OAAA,EAAS,gBAAA;;iBAyCjC,wBAAA,CAAyB,MAAA,YAAkB,KAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"extensionAssembler.d.mts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;iBA+NgB,uBAAA,CAAwB,OAAA,EAAS,gBAAA;;iBAyCjC,wBAAA,CAAyB,MAAA,YAAkB,KAAA"}
1
+ {"version":3,"file":"extensionAssembler.d.mts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;iBAkOgB,uBAAA,CAAwB,OAAA,EAAS,gBAAA;;iBAyCjC,wBAAA,CAAyB,MAAA,YAAkB,KAAA"}
@@ -1,2 +1,2 @@
1
- import{consumerPackageEntries as e,consumerPackageEntry as t,localEntries as n,localEntry as r,localPackageName as i,optionalPackageEntries as a,optionalPackageEntry as o,ownEntry as s,packageEntries as c,packageEntry as l}from"../adapters/modules/moduleResolution.mjs";import"../utils/index.mjs";import{isLocalPackageSpecifier as u}from"@agimon-ai/doompi-config/majorModes";const d=`@juicesharp/rpiv-ask-user-question`,f=`@agimon-ai/doompi-user-feedback`;function p(e){return e===`@juicesharp/rpiv-ask-user-question`?f:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${f}${e.slice(34)}`:e}const m={ownEntry:s,packageEntry:e=>l(p(e)),optionalPackageEntry:e=>o(p(e)),packageEntries:e=>c(p(e)),optionalPackageEntries:e=>a(p(e)),localEntry:r,localEntries:n,localPackageName:i};function h(u){return u?{ownEntry:s,packageEntry:e=>{let n=p(e);return t(n,u)??l(n)},optionalPackageEntry:e=>{let n=p(e);return t(n,u)??o(n)},packageEntries:t=>{let n=p(t);return e(n,u)??c(n)},optionalPackageEntries:t=>{let n=p(t);return e(n,u)??a(n)},localEntry:r,localEntries:n,localPackageName:i}:m}const g=`guardrails`,_=`vibe-lint`,v=`code-intel`,y=`runner`,b=`ask-user`,x=`style-system`,S=`ollama`,C={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},w={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,task:`@agimon-ai/doompi-task/extensions/pi`,voice:`@agimon-ai/doompi-voice/extensions/doom`,goalDoom:`@agimon-ai/doompi-goal/extensions/doom`},T=new Set([g,_,v]),E={mcp:`@agimon-ai/doompi-mcp/extensions/pi`,workflow:`@agimon-ai/doompi-workflow/extensions/pi`,dispatcherWorkflow:`@agimon-ai/doompi-workflow/extensions/dispatcher`},D=`persona`;function O(e){let t=p(e),n=t.split(`/`);return t.startsWith(`@`)?n.slice(0,2).join(`/`):n[0]??t}function k(e,t,n){return{name:`own:${e}`,path:t,priority:n}}function A(e,t,n,r=0){let i=r===0?``:`:${r}`;return{name:`package:${O(e)}${i}`,path:t,priority:n}}function j(e,t,n=0){let r=n===0?``:`:${n}`;return{name:t?`package:${O(t)}${r}`:`local:${e.replaceAll(`\\`,`/`)}`,path:e,priority:1}}function M(e,t,n){let r=e.localEntries?.(t,n);if(r!==void 0)return r;let i=e.localEntry(t,n);return i?[i]:void 0}function N(e,t,n){let r=e.layers[t];if(!r)throw Error(`Unknown layer: ${t}`);let i=[];for(let e of r.extensions??[]){if(!u(e)){i.push(k(e,n.ownEntry(e),1));continue}let a=M(n,e,r.baseDirectory);if(!a?.length)throw Error(`Layer "${t}" extension "${e}" does not resolve under ${r.baseDirectory}. Point it at a Pi extension file or directory.`);i.push(...a.map(e=>j(e)))}for(let e of r.packages??[]){let a=typeof e==`string`?e:e.name,o=typeof e==`string`?!1:e.optional===!0;if(u(a)){let e=M(n,a,r.baseDirectory);if(e?.length){let t=n.localPackageName?.(a,r.baseDirectory);i.push(...e.map((e,n)=>j(e,t,n)))}else if(!o)throw Error(`Layer "${t}" package "${a}" does not resolve under ${r.baseDirectory}. Point it at an extension file, or a directory whose package.json declares pi.extensions.`);continue}let s;if(o){if(s=n.optionalPackageEntries?.(a),s===void 0){let e=n.optionalPackageEntry(a);s=e?[e]:void 0}}else s=n.packageEntries?.(a)??[n.packageEntry(a)];if(s?.length)i.push(...s.map((e,t)=>A(a,e,1,t)));else if(!o)throw Error(`Layer "${t}" package "${a}" declares no Pi extensions.`)}return i}function P(e){let t=[];for(let n of e){let e=n.path.replaceAll(`\\`,`/`),r=t.findIndex(t=>t.name===n.name||t.path.replaceAll(`\\`,`/`)===e);if(r===-1){t.push(n);continue}let i=t[r];i&&n.priority>i.priority&&(t[r]=n)}return t.map(e=>e.path)}function F(e){let t=e.majorModesConfig,n=e.resolvers??m,r=e=>k(e,n.ownEntry(e),0),i=e=>A(e,n.packageEntry(e),0),a=new Set(e.layers),o=e=>a.has(e)?N(t,e,n):[],s=[];return e.mcpEntry&&s.push(A(E.mcp,e.mcpEntry,2)),s.push(i(w.logSinkTelemetry)),e.personaEntry&&s.push(k(D,e.personaEntry,2)),e.workflowExtension&&s.push(A(E.workflow,e.workflowExtension,2)),s.push(...o(`agiflow`),...o(g),...o(_),...o(v)),e.preset===`ollama`&&s.push(r(C.ollamaProvider)),s.push(r(C.effort)),s.push(...o(`plan-mode`)),s.push(i(w.task)),s.push(i(w.loop)),s.push(i(w.autocompact)),s.push(i(w.fileEdit)),s.push(...o(y)),s.push(...o(b),...o(x)),s.push(i(w.voice)),s.push(r(C.domains)),s.push(r(C.skills)),s.push(r(C.majorMode)),s.push(r(C.profile)),s.push(i(w.goalDoom)),s.push(r(C.cacheOptimizer)),e.mute||s.push(r(C.notifications)),e.agents&&s.push(...o(`team`)),s.push(i(w.doomHelp)),s.push(i(w.doomUi)),s.push(i(w.doomConfig)),s.push(r(C.modeCatalog)),e.autoStop&&s.unshift(r(C.autoStop)),P(s)}function I(e){let t=e.resolvers??m,n=e=>A(e,t.packageEntry(e),0),r=new Set(e.layers),i=n=>r.has(n)?N(e.majorModesConfig,n,t):[],a=[];return e.mcpEntry&&a.push(A(E.mcp,e.mcpEntry,2)),a.push(n(w.logSinkTelemetry)),e.personaEntry&&a.push(k(D,e.personaEntry,2)),e.preset===`ollama`&&a.push(k(C.ollamaProvider,t.ownEntry(C.ollamaProvider),0)),a.push(...i(g),...i(_),...i(v),...i(y),...i(b),...i(x)),a.push(n(w.autocompact)),a.push(n(w.doomConfig)),P(a)}function L(e,t){return t?[...e]:e.filter(e=>!T.has(e))}export{E as CONTEXT_PACKAGES,m as LAYER_RESOLVERS,d as LEGACY_ASK_USER_PACKAGE,S as OLLAMA_PRESET,D as PERSONA_ENTRY,f as USER_FEEDBACK_PACKAGE,I as assembleChildExtensions,F as assembleExtensions,p as canonicalPackageSpecifier,h as createLayerResolvers,L as filterHookDisabledLayers};
1
+ import{consumerPackageEntries as e,consumerPackageEntry as t,localEntries as n,localEntry as r,localPackageName as i,optionalPackageEntries as a,optionalPackageEntry as o,ownEntry as s,packageEntries as c,packageEntry as l}from"../adapters/modules/moduleResolution.mjs";import"../utils/index.mjs";import{isLocalPackageSpecifier as u}from"@agimon-ai/doompi-config/majorModes";const d=`@juicesharp/rpiv-ask-user-question`,f=`@agimon-ai/doompi-user-feedback`;function p(e){return e===`@juicesharp/rpiv-ask-user-question`?f:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${f}${e.slice(34)}`:e}const m={ownEntry:s,packageEntry:e=>l(p(e)),optionalPackageEntry:e=>o(p(e)),packageEntries:e=>c(p(e)),optionalPackageEntries:e=>a(p(e)),localEntry:r,localEntries:n,localPackageName:i};function h(u){return u?{ownEntry:s,packageEntry:e=>{let n=p(e);return t(n,u)??l(n)},optionalPackageEntry:e=>{let n=p(e);return t(n,u)??o(n)},packageEntries:t=>{let n=p(t);return e(n,u)??c(n)},optionalPackageEntries:t=>{let n=p(t);return e(n,u)??a(n)},localEntry:r,localEntries:n,localPackageName:i}:m}const g=`guardrails`,_=`vibe-lint`,v=`code-intel`,y=`runner`,b=`ask-user`,x=`style-system`,S=`ollama`,C={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},w={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,planDoom:`@agimon-ai/doompi-plan/extensions/doom`,voice:`@agimon-ai/doompi-voice/extensions/doom`,goalDoom:`@agimon-ai/doompi-goal/extensions/doom`},T=new Set([g,_,v]),E={mcp:`@agimon-ai/doompi-mcp/extensions/pi`,workflow:`@agimon-ai/doompi-workflow/extensions/pi`,dispatcherWorkflow:`@agimon-ai/doompi-workflow/extensions/dispatcher`},D=`persona`;function O(e){let t=p(e),n=t.split(`/`);return t.startsWith(`@`)?n.slice(0,2).join(`/`):n[0]??t}function k(e,t,n){return{name:`own:${e}`,path:t,priority:n}}function A(e,t,n,r=0){let i=r===0?``:`:${r}`;return{name:`package:${O(e)}${i}`,path:t,priority:n}}function j(e,t,n=0){let r=n===0?``:`:${n}`;return{name:t?`package:${O(t)}${r}`:`local:${e.replaceAll(`\\`,`/`)}`,path:e,priority:1}}function M(e,t,n){let r=e.localEntries?.(t,n);if(r!==void 0)return r;let i=e.localEntry(t,n);return i?[i]:void 0}function N(e,t,n){let r=e.layers[t];if(!r)throw Error(`Unknown layer: ${t}`);let i=[];for(let e of r.extensions??[]){if(!u(e)){i.push(k(e,n.ownEntry(e),1));continue}let a=M(n,e,r.baseDirectory);if(!a?.length)throw Error(`Layer "${t}" extension "${e}" does not resolve under ${r.baseDirectory}. Point it at a Pi extension file or directory.`);i.push(...a.map(e=>j(e)))}for(let e of r.packages??[]){let a=typeof e==`string`?e:e.name,o=typeof e==`string`?!1:e.optional===!0;if(u(a)){let e=M(n,a,r.baseDirectory);if(e?.length){let t=n.localPackageName?.(a,r.baseDirectory);i.push(...e.map((e,n)=>j(e,t,n)))}else if(!o)throw Error(`Layer "${t}" package "${a}" does not resolve under ${r.baseDirectory}. Point it at an extension file, or a directory whose package.json declares pi.extensions.`);continue}let s;if(o){if(s=n.optionalPackageEntries?.(a),s===void 0){let e=n.optionalPackageEntry(a);s=e?[e]:void 0}}else s=n.packageEntries?.(a)??[n.packageEntry(a)];if(s?.length)i.push(...s.map((e,t)=>A(a,e,1,t)));else if(!o)throw Error(`Layer "${t}" package "${a}" declares no Pi extensions.`)}return i}function P(e){let t=[];for(let n of e){let e=n.path.replaceAll(`\\`,`/`),r=t.findIndex(t=>t.name===n.name||t.path.replaceAll(`\\`,`/`)===e);if(r===-1){t.push(n);continue}let i=t[r];i&&n.priority>i.priority&&(t[r]=n)}return t.map(e=>e.path)}function F(e){let t=e.majorModesConfig,n=e.resolvers??m,r=e=>k(e,n.ownEntry(e),0),i=e=>A(e,n.packageEntry(e),0),a=new Set(e.layers),o=e=>a.has(e)?N(t,e,n):[],s=[];return e.mcpEntry&&s.push(A(E.mcp,e.mcpEntry,2)),s.push(i(w.logSinkTelemetry)),e.personaEntry&&s.push(k(D,e.personaEntry,2)),e.workflowExtension&&s.push(A(E.workflow,e.workflowExtension,2)),s.push(...o(`agiflow`),...o(g),...o(_),...o(v)),e.preset===`ollama`&&s.push(r(C.ollamaProvider)),s.push(r(C.effort)),s.push(i(w.planDoom)),s.push(...o(`task`)),s.push(i(w.loop)),s.push(i(w.autocompact)),s.push(i(w.fileEdit)),s.push(...o(y)),s.push(...o(b),...o(x)),s.push(i(w.voice)),s.push(r(C.domains)),s.push(r(C.skills)),s.push(r(C.majorMode)),s.push(r(C.profile)),s.push(i(w.goalDoom)),s.push(r(C.cacheOptimizer)),e.mute||s.push(r(C.notifications)),e.agents&&s.push(...o(`team`)),s.push(i(w.doomHelp)),s.push(i(w.doomUi)),s.push(i(w.doomConfig)),s.push(r(C.modeCatalog)),e.autoStop&&s.unshift(r(C.autoStop)),P(s)}function I(e){let t=e.resolvers??m,n=e=>A(e,t.packageEntry(e),0),r=new Set(e.layers),i=n=>r.has(n)?N(e.majorModesConfig,n,t):[],a=[];return e.mcpEntry&&a.push(A(E.mcp,e.mcpEntry,2)),a.push(n(w.logSinkTelemetry)),e.personaEntry&&a.push(k(D,e.personaEntry,2)),e.preset===`ollama`&&a.push(k(C.ollamaProvider,t.ownEntry(C.ollamaProvider),0)),a.push(...i(g),...i(_),...i(v),...i(y),...i(b),...i(x)),a.push(n(w.autocompact)),a.push(n(w.doomConfig)),P(a)}function L(e,t){return t?[...e]:e.filter(e=>!T.has(e))}export{E as CONTEXT_PACKAGES,m as LAYER_RESOLVERS,d as LEGACY_ASK_USER_PACKAGE,S as OLLAMA_PRESET,D as PERSONA_ENTRY,f as USER_FEEDBACK_PACKAGE,I as assembleChildExtensions,F as assembleExtensions,p as canonicalPackageSpecifier,h as createLayerResolvers,L as filterHookDisabledLayers};
2
2
  //# sourceMappingURL=extensionAssembler.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensionAssembler.mjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_PLAN_MODE = 'plan-mode';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n task: '@agimon-ai/doompi-task/extensions/pi',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n extensions.push(...layer(LAYER_PLAN_MODE));\n extensions.push(pkg(PACKAGE_ENTRIES.task));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"extensionAssembler.mjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_TASK = 'task';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n planDoom: '@agimon-ai/doompi-plan/extensions/doom',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n // Plan is a battery-included minor mode. Its tools stay inactive until the\n // user enters Plan, while its Doom adapter keeps Leader and mode metadata ready.\n extensions.push(pkg(PACKAGE_ENTRIES.planDoom));\n // Task is a major-mode capability: selected modes opt into its persistent graph.\n extensions.push(...layer(LAYER_TASK));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\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.17",
3
+ "version": "0.0.1-alpha.18",
4
4
  "description": "Pi-based agent harness for repository automations and developer workflows",
5
5
  "keywords": [
6
6
  "ai",
@@ -345,24 +345,24 @@
345
345
  "rolldown": "1.0.0-rc.17",
346
346
  "typebox": "1.1.38",
347
347
  "yaml": "2.9.0",
348
- "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.17",
349
- "@agimon-ai/doompi-autocompact": "0.0.1-alpha.17",
350
- "@agimon-ai/doompi-config": "0.0.1-alpha.17",
351
- "@agimon-ai/doompi-help": "0.0.1-alpha.0",
352
- "@agimon-ai/doompi-log": "0.0.1-alpha.17",
353
- "@agimon-ai/doompi-loop": "0.0.1-alpha.17",
354
- "@agimon-ai/doompi-file-edit": "0.0.1-alpha.17",
355
- "@agimon-ai/doompi-plan": "0.0.1-alpha.17",
356
- "@agimon-ai/doompi-mcp": "0.0.1-alpha.17",
357
- "@agimon-ai/doompi-runner": "0.0.1-alpha.17",
358
- "@agimon-ai/doompi-task": "0.0.1-alpha.17",
359
- "@agimon-ai/doompi-team": "0.0.1-alpha.17",
360
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.17",
361
- "@agimon-ai/doompi-ui": "0.0.1-alpha.17",
362
- "@agimon-ai/doompi-user-feedback": "0.0.1-alpha.6",
363
- "@agimon-ai/doompi-voice": "0.0.1-alpha.17",
364
- "@agimon-ai/doompi-goal": "0.0.1-alpha.7",
365
- "@agimon-ai/doompi-workflow": "0.0.1-alpha.17"
348
+ "@agimon-ai/doompi-autocompact": "0.0.1-alpha.18",
349
+ "@agimon-ai/doompi-config": "0.0.1-alpha.18",
350
+ "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.18",
351
+ "@agimon-ai/doompi-file-edit": "0.0.1-alpha.18",
352
+ "@agimon-ai/doompi-help": "0.0.1-alpha.1",
353
+ "@agimon-ai/doompi-loop": "0.0.1-alpha.18",
354
+ "@agimon-ai/doompi-mcp": "0.0.1-alpha.18",
355
+ "@agimon-ai/doompi-runner": "0.0.1-alpha.18",
356
+ "@agimon-ai/doompi-plan": "0.0.1-alpha.18",
357
+ "@agimon-ai/doompi-team": "0.0.1-alpha.18",
358
+ "@agimon-ai/doompi-task": "0.0.1-alpha.18",
359
+ "@agimon-ai/doompi-goal": "0.0.1-alpha.8",
360
+ "@agimon-ai/doompi-log": "0.0.1-alpha.18",
361
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.18",
362
+ "@agimon-ai/doompi-workflow": "0.0.1-alpha.18",
363
+ "@agimon-ai/doompi-user-feedback": "0.0.1-alpha.7",
364
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.18",
365
+ "@agimon-ai/doompi-voice": "0.0.1-alpha.18"
366
366
  },
367
367
  "devDependencies": {
368
368
  "@earendil-works/pi-ai": "0.84.2",