@agimon-ai/doompi 0.0.1-alpha.50 → 0.0.1-alpha.52

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.
@@ -1,3 +1,3 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("./modules/moduleResolution.cjs"),n=require("../services/extensionAssembler.cjs"),r=require("./piSettings.cjs");let i=require("node:path");i=e.__toESM(i,1);let a=require("node:fs");a=e.__toESM(a,1);let o=require("@agimon-ai/doompi-config/majorModes"),s=require("node:child_process"),c=require("node:util"),l=require("@earendil-works/pi-coding-agent");const u=`npm:`,d=i.default.join(`.pi`,`npm`),f=i.default.join(d,`node_modules`),p=`package.json`,m=[`const { spawn } = require('node:child_process');`,`const [command, ...args] = process.argv.slice(1);`,`if (!command) throw new Error('Missing package-manager command');`,`const child = spawn(command, args, { stdio: ['ignore', 2, 2] });`,`child.once('error', (error) => { console.error(error.message); process.exit(1); });`,`child.once('exit', (code) => process.exit(code ?? 1));`].join(``),h=(0,c.promisify)(s.execFile);function g(e){let t=e.indexOf(`@`,+!!e.startsWith(`@`));return t===-1?e:e.slice(0,t)}const _={"@hono/node-server@2.0.0 - 2.0.9":`^2.0.10`,"@opentelemetry/core@2.0.0 - 2.7.999":`2.8.0`,"brace-expansion@5.0.0 - 5.0.8":`^5.0.9`,"hono@4.0.0 - 4.12.33":`^4.12.34`,"js-yaml@4.0.0 - 4.3.0":`^4.3.1`,"js-yaml@5.0.0 - 5.2.1":`^5.2.2`,"liquidjs@10.0.0 - 10.27.0":`^10.27.1`,"protobufjs@8.0.0 - 8.7.1":`^8.7.2`},v=new Set(Object.keys(_).map(g));function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e){return y(e)?{...e}:{}}function x(e){let t=b(e);for(let[e,n]of Object.entries(t))v.has(g(e))?delete t[e]:y(n)&&(t[e]=x(n));return t}function S(e){return i.default.join(e,d,p)}function C(e,t){let n=new Set,r=[...e.default?[e.default]:[],...t.map(t=>{let n=e.layers[t];if(!n)throw Error(`Unknown layer: ${t}`);return n})];for(let e of r)for(let t of e.packages??[]){let e=typeof t==`string`?t:t.name;(typeof t==`string`||t.optional!==!0)&&!(0,o.isLocalPackageSpecifier)(e)&&n.add(e)}return[...n]}function w(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function T(e,t,n=new Map){let r=S(e),o=a.default.existsSync(r)?a.default.readFileSync(r,`utf8`):void 0,s;if(o===void 0)s={name:`pi-extensions`,private:!0};else{let e=JSON.parse(o);if(!y(e))throw Error(`Pi managed package manifest at ${r} must be a JSON object.`);s=e}let c=b(s.dependencies);for(let e of t){let t=D(e),r=n.get(t);r===void 0?Object.hasOwn(c,t)||(c[t]=`*`):c[t]=r}s.dependencies=c,s.overrides={...x(s.overrides),..._};let l=b(s.pnpm);l.overrides={...x(l.overrides),..._},s.pnpm=l;let u=`${JSON.stringify(s,null,2)}\n`;return u!==o&&(a.default.mkdirSync(i.default.dirname(r),{recursive:!0}),a.default.writeFileSync(r,u,`utf8`),!0)}function E(e,t,n){return C(e,t).filter(e=>w(n,e)===void 0)}function D(e){return e.startsWith(u)?e.slice(4):e}function O(e){return[...new Set(e.map(e=>`${u}${t.splitPackageSpecifier(e).name}`))]}function k(e,t){return`${e} ${t}${e===1?``:`s`}`}function A(e,t){let n=i.default.join(e,f,t,p);if(a.default.existsSync(n))try{let e=JSON.parse(a.default.readFileSync(n,`utf8`));return y(e)&&typeof e.version==`string`?e.version:void 0}catch{return}}function j(e){let t=e?.length?e:[`npm`];return[process.execPath,`--eval`,m,`--`,...t]}function M(e,t){let n=r.piAgentDirectory(t),i=l.SettingsManager.create(e,n,{projectTrusted:!0}),a=new Proxy(i,{get(e,t,n){return t===`getNpmCommand`?()=>j(e.getNpmCommand()):Reflect.get(e,t,n)}});return new l.DefaultPackageManager({cwd:e,agentDir:n,settingsManager:a})}function N(e,t){let[n,...i]=l.SettingsManager.create(e,r.piAgentDirectory(t),{projectTrusted:!0}).getNpmCommand()??[],a=n??`npm`,o=n?i:[];return async t=>{let{stdout:n}=await h(a,[...o,`view`,t,`version`,`--json`],{cwd:e,timeout:2e4,encoding:`utf8`}),r=JSON.parse(n.trim()||`null`);if(typeof r!=`string`)throw Error(`${a} view reported no published version`);return r}}async function P(e,t,n,r){let i=t.map(t=>({name:D(t),from:A(e,D(t))})).filter(e=>e.from!==void 0),a=await Promise.all(i.map(async e=>{try{return{...e,to:await n(e.name)}}catch(t){return{...e,failure:(t instanceof Error?t.message:String(t)).split(`
2
- `)[0]}}})),o=[],s=[];for(let e of a){if(e.to===void 0){s.push(e.name),r?.(`kept ${e.name} ${e.from}: ${e.failure??`no published version`}`);continue}e.to!==e.from&&(o.push({name:e.name,from:e.from,to:e.to}),r?.(`${e.name} ${e.from} -> ${e.to}`))}return{updated:o,unchecked:s}}async function F(e,t={}){let r=e.environment??process.env,o=t.resolvers??n.createLayerResolvers(e.repoRoot),s=C(e.config,e.layers),c=s.filter(e=>w(o,e)===void 0),l=O(c),u=O(s);if(u.length===0)return{installed:[],updated:[],unchecked:[]};let d=i.default.dirname(S(e.repoRoot));if(c.length===0&&!a.default.existsSync(d))return{installed:[],updated:[],unchecked:[]};let{updated:f,unchecked:p}=e.refresh?await P(e.repoRoot,u,t.publishedVersion??N(e.repoRoot,r),e.onProgress):{updated:[],unchecked:[]},m=T(e.repoRoot,u,new Map(f.map(e=>[e.name,e.to])));if(c.length===0&&!m)return{installed:[],updated:[],unchecked:p};let h=t.packageManager??M(e.repoRoot,r);e.onProgress?.(`installing ${f.length>0?k(f.length,`update`):c.length>0?k(c.length,`missing package`):`the package manifest`}`);try{m?await h.install(u[0],{local:!0}):await h.resolveExtensionSources(l,{local:!0})}catch(e){throw Error(`Failed to reconcile DoomPi layer package(s): ${(m?u:l).join(`, `)}`,{cause:e})}let g=c.filter(e=>!w(o,e)?.length);if(g.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${g.join(`, `)}`);return{installed:l,updated:f,unchecked:p}}exports.SAFE_TRANSITIVE_OVERRIDES=_,exports.ensureLayerPackages=F,exports.ensureManagedPackageManifest=T,exports.missingLayerPackageSpecifiers=E,exports.packageManagerCommandWithStderr=j;
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("./modules/moduleResolution.cjs"),n=require("../services/extensionAssembler.cjs"),r=require("./piSettings.cjs");let i=require("node:path");i=e.__toESM(i,1);let a=require("node:fs");a=e.__toESM(a,1);let o=require("@agimon-ai/doompi-config/majorModes"),s=require("node:child_process"),c=require("node:util"),l=require("@earendil-works/pi-coding-agent");const u=`npm:`,d=i.default.join(`.pi`,`npm`),f=i.default.join(d,`node_modules`),p=`package.json`,m=[`const { spawn } = require('node:child_process');`,`const [command, ...args] = process.argv.slice(1);`,`if (!command) throw new Error('Missing package-manager command');`,`const child = spawn(command, args, { stdio: ['ignore', 2, 2] });`,`child.once('error', (error) => { console.error(error.message); process.exit(1); });`,`child.once('exit', (code) => process.exit(code ?? 1));`].join(``),h=(0,c.promisify)(s.execFile);function g(e){let t=e.indexOf(`@`,+!!e.startsWith(`@`));return t===-1?e:e.slice(0,t)}const _={"@hono/node-server@2.0.0 - 2.0.9":`^2.0.10`,"@opentelemetry/core@2.0.0 - 2.7.999":`2.8.0`,"brace-expansion@5.0.0 - 5.0.8":`^5.0.9`,"hono@4.0.0 - 4.12.33":`^4.12.34`,"js-yaml@4.0.0 - 4.3.0":`^4.3.1`,"js-yaml@5.0.0 - 5.2.1":`^5.2.2`,"liquidjs@10.0.0 - 10.27.0":`^10.27.1`,"protobufjs@8.0.0 - 8.7.1":`^8.7.2`},v=new Set(Object.keys(_).map(g));function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e){return y(e)?{...e}:{}}function x(e){let t=b(e);for(let[e,n]of Object.entries(t))v.has(g(e))?delete t[e]:y(n)&&(t[e]=x(n));return t}function S(e){return i.default.join(e,d,p)}function C(e,t){let n=new Set,r=[...e.default?[e.default]:[],...t.map(t=>{let n=e.layers[t];if(!n)throw Error(`Unknown layer: ${t}`);return n})];for(let e of r)for(let t of e.packages??[]){let e=typeof t==`string`?t:t.name;(typeof t==`string`||t.optional!==!0)&&!(0,o.isLocalPackageSpecifier)(e)&&n.add(e)}return[...n]}function w(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function T(e,t,n=new Map){let r=S(e),o=a.default.existsSync(r)?a.default.readFileSync(r,`utf8`):void 0,s;if(o===void 0)s={name:`pi-extensions`,private:!0};else{let e=JSON.parse(o);if(!y(e))throw Error(`Pi managed package manifest at ${r} must be a JSON object.`);s=e}let c=b(s.dependencies);for(let e of t){let t=D(e),r=n.get(t);r===void 0?Object.hasOwn(c,t)||(c[t]=`*`):c[t]=r}s.dependencies=c,s.overrides={...x(s.overrides),..._};let l=b(s.pnpm);l.overrides={...x(l.overrides),..._},s.pnpm=l;let u=`${JSON.stringify(s,null,2)}\n`;return u!==o&&(a.default.mkdirSync(i.default.dirname(r),{recursive:!0}),a.default.writeFileSync(r,u,`utf8`),!0)}function E(e,t,n){return C(e,t).filter(e=>w(n,e)===void 0)}function D(e){let t=e.startsWith(u)?e.slice(4):e;if(t.startsWith(`@`)){let e=t.indexOf(`/`),n=e===-1?-1:t.indexOf(`@`,e);return n===-1?t:t.slice(0,n)}let n=t.indexOf(`@`);return n===-1?t:t.slice(0,n)}function O(e){let t=e.DOOMPI_PACKAGE_CATALOG?.trim();if(!t)return new Map;let n=JSON.parse(a.default.readFileSync(t,`utf8`));if(!y(n)||n.version!==1||!y(n.packages))throw Error(`Unsupported DoomPi package catalog: ${t}`);let r=new Map;for(let[e,o]of Object.entries(n.packages)){if(!y(o)||typeof o.archive!=`string`||!Array.isArray(o.dependencies))throw Error(`Invalid package entry for ${e} in ${t}`);let n=o.dependencies.filter(e=>typeof e==`string`);if(n.length!==o.dependencies.length)throw Error(`Invalid dependencies for ${e} in ${t}`);let s=i.default.resolve(i.default.dirname(t),o.archive);if(!a.default.existsSync(s))throw Error(`DoomPi package catalog archive is missing: ${s}`);r.set(e,{target:`file:${s}`,dependencies:n})}return r}function k(e,n=new Map,r=!1){let i=[...new Set(e.map(e=>t.splitPackageSpecifier(e).name))];if(r)for(let e=0;e<i.length;e+=1)for(let t of n.get(i[e])?.dependencies??[])i.includes(t)||i.push(t);return i.map(e=>{let t=n.get(e)?.target;return`${u}${e}${t?`@${t}`:``}`})}function A(e,t){return`${e} ${t}${e===1?``:`s`}`}function j(e,t){let n=i.default.join(e,f,t,p);if(a.default.existsSync(n))try{let e=JSON.parse(a.default.readFileSync(n,`utf8`));return y(e)&&typeof e.version==`string`?e.version:void 0}catch{return}}function M(e){let t=e?.length?e:[`npm`];return[process.execPath,`--eval`,m,`--`,...t]}function N(e,t){if(e?.length)return e;let n=t.DOOMPI_NPM_CLI?.trim();return n?[process.execPath,n]:void 0}function P(e,t){return N(e.getNpmCommand(),t)}function F(e,t){let n=r.piAgentDirectory(t),i=l.SettingsManager.create(e,n,{projectTrusted:!0}),a=new Proxy(i,{get(e,n,r){return n===`getNpmCommand`?()=>M(P(e,t)):Reflect.get(e,n,r)}});return new l.DefaultPackageManager({cwd:e,agentDir:n,settingsManager:a})}function I(e,t){let[n,...i]=P(l.SettingsManager.create(e,r.piAgentDirectory(t),{projectTrusted:!0}),t)??[],a=n??`npm`;return async t=>{let{stdout:n}=await h(a,[...i,`view`,t,`version`,`--json`],{cwd:e,timeout:2e4,encoding:`utf8`}),r=JSON.parse(n.trim()||`null`);if(typeof r!=`string`)throw Error(`${a} view reported no published version`);return r}}async function L(e,t,n,r){let i=t.map(t=>({name:D(t),from:j(e,D(t))})).filter(e=>e.from!==void 0),a=await Promise.all(i.map(async e=>{try{return{...e,to:await n(e.name)}}catch(t){return{...e,failure:(t instanceof Error?t.message:String(t)).split(`
2
+ `)[0]}}})),o=[],s=[];for(let e of a){if(e.to===void 0){s.push(e.name),r?.(`kept ${e.name} ${e.from}: ${e.failure??`no published version`}`);continue}e.to!==e.from&&(o.push({name:e.name,from:e.from,to:e.to}),r?.(`${e.name} ${e.from} -> ${e.to}`))}return{updated:o,unchecked:s}}async function R(e,t={}){let r=e.environment??process.env,o=t.resolvers??n.createLayerResolvers(e.repoRoot),s=C(e.config,e.layers),c=s.filter(e=>w(o,e)===void 0),l=O(r),u=k(c,l),d=k(s,l,!0);if(d.length===0)return{installed:[],updated:[],unchecked:[]};let f=i.default.dirname(S(e.repoRoot));if(c.length===0&&!a.default.existsSync(f))return{installed:[],updated:[],unchecked:[]};let p=d.filter(e=>!l.has(D(e))),{updated:m,unchecked:h}=e.refresh?await L(e.repoRoot,p,t.publishedVersion??I(e.repoRoot,r),e.onProgress):{updated:[],unchecked:[]},g=new Map;for(let e of d){let t=D(e),n=l.get(t)?.target;n&&g.set(t,n)}for(let e of m)g.set(e.name,e.to);let _=T(e.repoRoot,d,g);if(c.length===0&&!_)return{installed:[],updated:[],unchecked:h};let v=t.packageManager??F(e.repoRoot,r);e.onProgress?.(`installing ${m.length>0?A(m.length,`update`):c.length>0?A(c.length,`missing package`):`the package manifest`}`);try{_?await v.install(d[0],{local:!0}):await v.resolveExtensionSources(u,{local:!0})}catch(e){throw Error(`Failed to reconcile DoomPi layer package(s): ${(_?d:u).join(`, `)}`,{cause:e})}let y=c.filter(e=>!w(o,e)?.length);if(y.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${y.join(`, `)}`);return{installed:u,updated:m,unchecked:h}}exports.SAFE_TRANSITIVE_OVERRIDES=_,exports.effectivePackageManagerCommand=N,exports.ensureLayerPackages=R,exports.ensureManagedPackageManifest=T,exports.missingLayerPackageSpecifiers=E,exports.packageManagerCommandWithStderr=M;
3
3
  //# sourceMappingURL=layerPackageInstaller.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"layerPackageInstaller.cjs","names":["path","promisify","execFile","isLocalPackageSpecifier","fs","splitPackageSpecifier","piAgentDirectory","SettingsManager","DefaultPackageManager","createLayerResolvers"],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport { 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:';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm');\nconst PI_MANAGED_MODULES_DIRECTORY = path.join(PI_MANAGED_NPM_DIRECTORY, 'node_modules');\nconst PI_MANAGED_PACKAGE_NAME = 'pi-extensions';\nconst UNPINNED_PACKAGE_RANGE = '*';\nconst PACKAGE_MANIFEST = 'package.json';\nconst DEFAULT_NPM_COMMAND = 'npm';\nconst REGISTRY_TIMEOUT_MS = 20_000;\nconst PACKAGE_MANAGER_STDERR_SCRIPT = [\n \"const { spawn } = require('node:child_process');\",\n 'const [command, ...args] = process.argv.slice(1);',\n \"if (!command) throw new Error('Missing package-manager command');\",\n \"const child = spawn(command, args, { stdio: ['ignore', 2, 2] });\",\n \"child.once('error', (error) => { console.error(error.message); process.exit(1); });\",\n \"child.once('exit', (code) => process.exit(code ?? 1));\",\n].join('');\n\nconst execFileAsync = promisify(execFile);\n\nfunction overridePackageName(selector: string): string {\n const separatorIndex = selector.indexOf('@', selector.startsWith('@') ? 1 : 0);\n return separatorIndex === -1 ? selector : selector.slice(0, separatorIndex);\n}\n\n/**\n * Same-major patches for transitive versions pinned by the current foundation packages.\n * npm only honors overrides from the install root, so published extensions cannot carry\n * these fixes in their own manifests.\n */\nexport const SAFE_TRANSITIVE_OVERRIDES = {\n '@hono/node-server@2.0.0 - 2.0.9': '^2.0.10',\n '@opentelemetry/core@2.0.0 - 2.7.999': '2.8.0',\n 'brace-expansion@5.0.0 - 5.0.8': '^5.0.9',\n 'hono@4.0.0 - 4.12.33': '^4.12.34',\n 'js-yaml@4.0.0 - 4.3.0': '^4.3.1',\n 'js-yaml@5.0.0 - 5.2.1': '^5.2.2',\n 'liquidjs@10.0.0 - 10.27.0': '^10.27.1',\n 'protobufjs@8.0.0 - 8.7.1': '^8.7.2',\n} as const satisfies Readonly<Record<string, string>>;\n\nconst SAFE_TRANSITIVE_PACKAGE_NAMES = new Set(Object.keys(SAFE_TRANSITIVE_OVERRIDES).map(overridePackageName));\n\ntype LayerPackageManager = Pick<PackageManager, 'install' | 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n /**\n * Move every managed package to its newest published version.\n *\n * Launch installs what a selection needs and nothing more, so a session never\n * pays for a registry round trip. Sync is the explicit maintenance command and\n * is the only caller that asks for this.\n */\n refresh?: boolean;\n /** Receives one human-readable line per package decision. */\n onProgress?: (message: string) => void;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n /** Registry lookup seam; the default reads the newest version with Pi's npm client. */\n publishedVersion?: (name: string) => Promise<string>;\n}\n\n/** One managed package moving from the installed version to the newest published one. */\nexport interface LayerPackageUpdate {\n name: string;\n from: string;\n to: string;\n}\n\nexport interface LayerPackageResult {\n /** Sources installed because a configured extension could not be resolved. */\n installed: string[];\n /** Packages this run moved to a newer published version. */\n updated: LayerPackageUpdate[];\n /** Packages left at the installed version because the registry could not be read. */\n unchecked: string[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction recordValue(value: unknown): Record<string, unknown> {\n return isRecord(value) ? { ...value } : {};\n}\n\nfunction withoutConflictingTransitiveOverrides(value: unknown): Record<string, unknown> {\n const overrides = recordValue(value);\n for (const [selector, replacement] of Object.entries(overrides)) {\n if (SAFE_TRANSITIVE_PACKAGE_NAMES.has(overridePackageName(selector))) {\n delete overrides[selector];\n } else if (isRecord(replacement)) {\n overrides[selector] = withoutConflictingTransitiveOverrides(replacement);\n }\n }\n return overrides;\n}\n\nfunction managedPackageManifestPath(repoRoot: string): string {\n return path.join(repoRoot, PI_MANAGED_NPM_DIRECTORY, PACKAGE_MANIFEST);\n}\n\nfunction configuredPackageSpecifiers(config: MajorModesConfig, layers: readonly string[]): string[] {\n const specifiers = new Set<string>();\n const selectedDefinitions = [\n ...(config.default ? [config.default] : []),\n ...layers.map((layerName) => {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n return layer;\n }),\n ];\n for (const layer of selectedDefinitions) {\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)) specifiers.add(specifier);\n }\n }\n return [...specifiers];\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/** Adds the complete package set and patched transitive policy to Pi's managed install root. */\nexport function ensureManagedPackageManifest(\n repoRoot: string,\n sources: readonly string[],\n targets: ReadonlyMap<string, string> = new Map(),\n): boolean {\n const manifestPath = managedPackageManifestPath(repoRoot);\n const current = fs.existsSync(manifestPath) ? fs.readFileSync(manifestPath, 'utf8') : undefined;\n let manifest: Record<string, unknown>;\n if (current === undefined) {\n manifest = { name: PI_MANAGED_PACKAGE_NAME, private: true };\n } else {\n const parsed: unknown = JSON.parse(current);\n if (!isRecord(parsed)) throw new Error(`Pi managed package manifest at ${manifestPath} must be a JSON object.`);\n manifest = parsed;\n }\n\n const dependencies = recordValue(manifest.dependencies);\n for (const source of sources) {\n const name = packageName(source);\n const target = targets.get(name);\n // An exact target is what makes an update reach the store: npm keeps a\n // locked version whenever the recorded range still admits it, and the range\n // it writes back after an install always admits the version it just wrote.\n if (target !== undefined) dependencies[name] = target;\n else if (!Object.hasOwn(dependencies, name)) dependencies[name] = UNPINNED_PACKAGE_RANGE;\n }\n manifest.dependencies = dependencies;\n // npm gives nested and overlapping consumer rules precedence in cases that can retain\n // vulnerable versions, so DoomPi owns these package-specific selectors recursively.\n manifest.overrides = {\n ...withoutConflictingTransitiveOverrides(manifest.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n const pnpm = recordValue(manifest.pnpm);\n pnpm.overrides = {\n ...withoutConflictingTransitiveOverrides(pnpm.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n manifest.pnpm = pnpm;\n\n const serialized = `${JSON.stringify(manifest, null, 2)}\\n`;\n if (serialized === current) return false;\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(manifestPath, serialized, 'utf8');\n return true;\n}\n\n/** Finds required npm packages selected by defaults and active layers that DoomPi cannot resolve. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n return configuredPackageSpecifiers(config, layers).filter(\n (specifier) => resolvePackageEntries(resolvers, specifier) === undefined,\n );\n}\n\nfunction packageName(source: string): string {\n return source.startsWith(NPM_SOURCE_PREFIX) ? source.slice(NPM_SOURCE_PREFIX.length) : source;\n}\n\nfunction npmSources(specifiers: readonly string[]): string[] {\n return [...new Set(specifiers.map((specifier) => `${NPM_SOURCE_PREFIX}${splitPackageSpecifier(specifier).name}`))];\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`;\n}\n\n/** Version of a package inside Pi's managed store, absent when sync does not own it. */\nfunction managedPackageVersion(repoRoot: string, name: string): string | undefined {\n const manifestPath = path.join(repoRoot, PI_MANAGED_MODULES_DIRECTORY, name, PACKAGE_MANIFEST);\n if (!fs.existsSync(manifestPath)) return undefined;\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n return isRecord(parsed) && typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n // An unreadable manifest carries the same meaning as an absent one: nothing\n // usable is installed, so the caller treats the package as uninstalled.\n return undefined;\n }\n}\n\nexport function packageManagerCommandWithStderr(configured: readonly string[] | undefined): string[] {\n const command = configured?.length ? configured : [DEFAULT_NPM_COMMAND];\n return [process.execPath, '--eval', PACKAGE_MANAGER_STDERR_SCRIPT, '--', ...command];\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 const redirectedSettingsManager = new Proxy(settingsManager, {\n get(target, property, receiver) {\n if (property === 'getNpmCommand') return () => packageManagerCommandWithStderr(target.getNpmCommand());\n return Reflect.get(target, property, receiver) as unknown;\n },\n });\n return new DefaultPackageManager({\n cwd: repoRoot,\n agentDir: agentDirectory,\n settingsManager: redirectedSettingsManager,\n });\n}\n\n/** Reads newest published versions with the same client Pi installs them with. */\nfunction createVersionReader(repoRoot: string, environment: NodeJS.ProcessEnv): (name: string) => Promise<string> {\n const configured = SettingsManager.create(repoRoot, piAgentDirectory(environment), {\n projectTrusted: true,\n }).getNpmCommand();\n const [command, ...args] = configured ?? [];\n const client = command ?? DEFAULT_NPM_COMMAND;\n const clientArguments = command ? args : [];\n return async (name) => {\n const { stdout } = await execFileAsync(client, [...clientArguments, 'view', name, 'version', '--json'], {\n cwd: repoRoot,\n timeout: REGISTRY_TIMEOUT_MS,\n encoding: 'utf8',\n });\n const parsed: unknown = JSON.parse(stdout.trim() || 'null');\n if (typeof parsed !== 'string') throw new Error(`${client} view reported no published version`);\n return parsed;\n };\n}\n\ninterface CheckedPackage {\n name: string;\n from: string;\n to?: string;\n failure?: string;\n}\n\n/**\n * Compares every package sync installed against the registry.\n *\n * Only the managed store is consulted: a package that resolves from the\n * repository's own modules is not sync's to move, and a package that is not\n * installed yet is already covered by the missing-package path.\n */\nasync function resolveUpdates(\n repoRoot: string,\n sources: readonly string[],\n publishedVersion: (name: string) => Promise<string>,\n onProgress: ((message: string) => void) | undefined,\n): Promise<Pick<LayerPackageResult, 'updated' | 'unchecked'>> {\n const managed = sources\n .map((source) => ({ name: packageName(source), from: managedPackageVersion(repoRoot, packageName(source)) }))\n .filter((entry): entry is { name: string; from: string } => entry.from !== undefined);\n const checked: CheckedPackage[] = await Promise.all(\n managed.map(async (entry) => {\n try {\n return { ...entry, to: await publishedVersion(entry.name) };\n } catch (error) {\n return { ...entry, failure: (error instanceof Error ? error.message : String(error)).split('\\n')[0] };\n }\n }),\n );\n\n const updated: LayerPackageUpdate[] = [];\n const unchecked: string[] = [];\n for (const entry of checked) {\n if (entry.to === undefined) {\n unchecked.push(entry.name);\n onProgress?.(`kept ${entry.name} ${entry.from}: ${entry.failure ?? 'no published version'}`);\n continue;\n }\n if (entry.to === entry.from) continue;\n updated.push({ name: entry.name, from: entry.from, to: entry.to });\n onProgress?.(`${entry.name} ${entry.from} -> ${entry.to}`);\n }\n return { updated, unchecked };\n}\n\n/** Installs 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<LayerPackageResult> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const configured = configuredPackageSpecifiers(options.config, options.layers);\n const missing = configured.filter((specifier) => resolvePackageEntries(resolvers, specifier) === undefined);\n const missingSources = npmSources(missing);\n const sources = npmSources(configured);\n if (sources.length === 0) return { installed: [], updated: [], unchecked: [] };\n\n const managedDirectory = path.dirname(managedPackageManifestPath(options.repoRoot));\n if (missing.length === 0 && !fs.existsSync(managedDirectory)) return { installed: [], updated: [], unchecked: [] };\n\n const { updated, unchecked } = options.refresh\n ? await resolveUpdates(\n options.repoRoot,\n sources,\n dependencies.publishedVersion ?? createVersionReader(options.repoRoot, environment),\n options.onProgress,\n )\n : { updated: [], unchecked: [] };\n const manifestChanged = ensureManagedPackageManifest(\n options.repoRoot,\n sources,\n new Map(updated.map((update) => [update.name, update.to])),\n );\n if (missing.length === 0 && !manifestChanged) return { installed: [], updated: [], unchecked };\n\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n options.onProgress?.(\n `installing ${\n updated.length > 0\n ? pluralize(updated.length, 'update')\n : missing.length > 0\n ? pluralize(missing.length, 'missing package')\n : 'the package manifest'\n }`,\n );\n try {\n if (manifestChanged) {\n // Installing one source reconciles the complete dependency set already written\n // to package.json, avoiding one npm install and audit report per DoomPi package.\n await packageManager.install(sources[0]!, { local: true });\n } else {\n await packageManager.resolveExtensionSources(missingSources, { local: true });\n }\n } catch (error) {\n const attempted = manifestChanged ? sources : missingSources;\n throw new Error(`Failed to reconcile DoomPi layer package(s): ${attempted.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 { installed: missingSources, updated, unchecked };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"layerPackageInstaller.cjs","names":["path","promisify","execFile","isLocalPackageSpecifier","fs","splitPackageSpecifier","piAgentDirectory","SettingsManager","DefaultPackageManager","createLayerResolvers"],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport { 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:';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm');\nconst PI_MANAGED_MODULES_DIRECTORY = path.join(PI_MANAGED_NPM_DIRECTORY, 'node_modules');\nconst PI_MANAGED_PACKAGE_NAME = 'pi-extensions';\nconst UNPINNED_PACKAGE_RANGE = '*';\nconst PACKAGE_MANIFEST = 'package.json';\nconst DEFAULT_NPM_COMMAND = 'npm';\nconst NPM_CLI_ENV = 'DOOMPI_NPM_CLI';\nconst PACKAGE_CATALOG_ENV = 'DOOMPI_PACKAGE_CATALOG';\nconst REGISTRY_TIMEOUT_MS = 20_000;\nconst PACKAGE_MANAGER_STDERR_SCRIPT = [\n \"const { spawn } = require('node:child_process');\",\n 'const [command, ...args] = process.argv.slice(1);',\n \"if (!command) throw new Error('Missing package-manager command');\",\n \"const child = spawn(command, args, { stdio: ['ignore', 2, 2] });\",\n \"child.once('error', (error) => { console.error(error.message); process.exit(1); });\",\n \"child.once('exit', (code) => process.exit(code ?? 1));\",\n].join('');\n\nconst execFileAsync = promisify(execFile);\n\nfunction overridePackageName(selector: string): string {\n const separatorIndex = selector.indexOf('@', selector.startsWith('@') ? 1 : 0);\n return separatorIndex === -1 ? selector : selector.slice(0, separatorIndex);\n}\n\n/**\n * Same-major patches for transitive versions pinned by the current foundation packages.\n * npm only honors overrides from the install root, so published extensions cannot carry\n * these fixes in their own manifests.\n */\nexport const SAFE_TRANSITIVE_OVERRIDES = {\n '@hono/node-server@2.0.0 - 2.0.9': '^2.0.10',\n '@opentelemetry/core@2.0.0 - 2.7.999': '2.8.0',\n 'brace-expansion@5.0.0 - 5.0.8': '^5.0.9',\n 'hono@4.0.0 - 4.12.33': '^4.12.34',\n 'js-yaml@4.0.0 - 4.3.0': '^4.3.1',\n 'js-yaml@5.0.0 - 5.2.1': '^5.2.2',\n 'liquidjs@10.0.0 - 10.27.0': '^10.27.1',\n 'protobufjs@8.0.0 - 8.7.1': '^8.7.2',\n} as const satisfies Readonly<Record<string, string>>;\n\nconst SAFE_TRANSITIVE_PACKAGE_NAMES = new Set(Object.keys(SAFE_TRANSITIVE_OVERRIDES).map(overridePackageName));\n\ntype LayerPackageManager = Pick<PackageManager, 'install' | 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n /**\n * Move every managed package to its newest published version.\n *\n * Launch installs what a selection needs and nothing more, so a session never\n * pays for a registry round trip. Sync is the explicit maintenance command and\n * is the only caller that asks for this.\n */\n refresh?: boolean;\n /** Receives one human-readable line per package decision. */\n onProgress?: (message: string) => void;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n /** Registry lookup seam; the default reads the newest version with Pi's npm client. */\n publishedVersion?: (name: string) => Promise<string>;\n}\n\n/** One managed package moving from the installed version to the newest published one. */\nexport interface LayerPackageUpdate {\n name: string;\n from: string;\n to: string;\n}\n\nexport interface LayerPackageResult {\n /** Sources installed because a configured extension could not be resolved. */\n installed: string[];\n /** Packages this run moved to a newer published version. */\n updated: LayerPackageUpdate[];\n /** Packages left at the installed version because the registry could not be read. */\n unchecked: string[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction recordValue(value: unknown): Record<string, unknown> {\n return isRecord(value) ? { ...value } : {};\n}\n\nfunction withoutConflictingTransitiveOverrides(value: unknown): Record<string, unknown> {\n const overrides = recordValue(value);\n for (const [selector, replacement] of Object.entries(overrides)) {\n if (SAFE_TRANSITIVE_PACKAGE_NAMES.has(overridePackageName(selector))) {\n delete overrides[selector];\n } else if (isRecord(replacement)) {\n overrides[selector] = withoutConflictingTransitiveOverrides(replacement);\n }\n }\n return overrides;\n}\n\nfunction managedPackageManifestPath(repoRoot: string): string {\n return path.join(repoRoot, PI_MANAGED_NPM_DIRECTORY, PACKAGE_MANIFEST);\n}\n\nfunction configuredPackageSpecifiers(config: MajorModesConfig, layers: readonly string[]): string[] {\n const specifiers = new Set<string>();\n const selectedDefinitions = [\n ...(config.default ? [config.default] : []),\n ...layers.map((layerName) => {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n return layer;\n }),\n ];\n for (const layer of selectedDefinitions) {\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)) specifiers.add(specifier);\n }\n }\n return [...specifiers];\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/** Adds the complete package set and patched transitive policy to Pi's managed install root. */\nexport function ensureManagedPackageManifest(\n repoRoot: string,\n sources: readonly string[],\n targets: ReadonlyMap<string, string> = new Map(),\n): boolean {\n const manifestPath = managedPackageManifestPath(repoRoot);\n const current = fs.existsSync(manifestPath) ? fs.readFileSync(manifestPath, 'utf8') : undefined;\n let manifest: Record<string, unknown>;\n if (current === undefined) {\n manifest = { name: PI_MANAGED_PACKAGE_NAME, private: true };\n } else {\n const parsed: unknown = JSON.parse(current);\n if (!isRecord(parsed)) throw new Error(`Pi managed package manifest at ${manifestPath} must be a JSON object.`);\n manifest = parsed;\n }\n\n const dependencies = recordValue(manifest.dependencies);\n for (const source of sources) {\n const name = packageName(source);\n const target = targets.get(name);\n // An exact target is what makes an update reach the store: npm keeps a\n // locked version whenever the recorded range still admits it, and the range\n // it writes back after an install always admits the version it just wrote.\n if (target !== undefined) dependencies[name] = target;\n else if (!Object.hasOwn(dependencies, name)) dependencies[name] = UNPINNED_PACKAGE_RANGE;\n }\n manifest.dependencies = dependencies;\n // npm gives nested and overlapping consumer rules precedence in cases that can retain\n // vulnerable versions, so DoomPi owns these package-specific selectors recursively.\n manifest.overrides = {\n ...withoutConflictingTransitiveOverrides(manifest.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n const pnpm = recordValue(manifest.pnpm);\n pnpm.overrides = {\n ...withoutConflictingTransitiveOverrides(pnpm.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n manifest.pnpm = pnpm;\n\n const serialized = `${JSON.stringify(manifest, null, 2)}\\n`;\n if (serialized === current) return false;\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(manifestPath, serialized, 'utf8');\n return true;\n}\n\n/** Finds required npm packages selected by defaults and active layers that DoomPi cannot resolve. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n return configuredPackageSpecifiers(config, layers).filter(\n (specifier) => resolvePackageEntries(resolvers, specifier) === undefined,\n );\n}\n\nfunction packageName(source: string): string {\n const specifier = source.startsWith(NPM_SOURCE_PREFIX) ? source.slice(NPM_SOURCE_PREFIX.length) : source;\n if (specifier.startsWith('@')) {\n const slash = specifier.indexOf('/');\n const version = slash === -1 ? -1 : specifier.indexOf('@', slash);\n return version === -1 ? specifier : specifier.slice(0, version);\n }\n const version = specifier.indexOf('@');\n return version === -1 ? specifier : specifier.slice(0, version);\n}\n\ninterface PackageCatalogEntry {\n target: string;\n dependencies: readonly string[];\n}\n\ntype PackageCatalog = ReadonlyMap<string, PackageCatalogEntry>;\n\nfunction readPackageCatalog(environment: NodeJS.ProcessEnv): PackageCatalog {\n const manifestPath = environment[PACKAGE_CATALOG_ENV]?.trim();\n if (!manifestPath) return new Map();\n const parsed: unknown = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n if (!isRecord(parsed) || parsed.version !== 1 || !isRecord(parsed.packages)) {\n throw new Error(`Unsupported DoomPi package catalog: ${manifestPath}`);\n }\n const catalog = new Map<string, PackageCatalogEntry>();\n for (const [name, value] of Object.entries(parsed.packages)) {\n if (!isRecord(value) || typeof value.archive !== 'string' || !Array.isArray(value.dependencies)) {\n throw new Error(`Invalid package entry for ${name} in ${manifestPath}`);\n }\n const dependencies = value.dependencies.filter(\n (dependency): dependency is string => typeof dependency === 'string',\n );\n if (dependencies.length !== value.dependencies.length)\n throw new Error(`Invalid dependencies for ${name} in ${manifestPath}`);\n const archive = path.resolve(path.dirname(manifestPath), value.archive);\n if (!fs.existsSync(archive)) throw new Error(`DoomPi package catalog archive is missing: ${archive}`);\n catalog.set(name, { target: `file:${archive}`, dependencies });\n }\n return catalog;\n}\n\nfunction npmSources(\n specifiers: readonly string[],\n catalog: PackageCatalog = new Map(),\n includeCatalogDependencies = false,\n): string[] {\n const names = [...new Set(specifiers.map((specifier) => splitPackageSpecifier(specifier).name))];\n if (includeCatalogDependencies) {\n for (let index = 0; index < names.length; index += 1) {\n for (const dependency of catalog.get(names[index]!)?.dependencies ?? []) {\n if (!names.includes(dependency)) names.push(dependency);\n }\n }\n }\n return names.map((name) => {\n const target = catalog.get(name)?.target;\n return `${NPM_SOURCE_PREFIX}${name}${target ? `@${target}` : ''}`;\n });\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`;\n}\n\n/** Version of a package inside Pi's managed store, absent when sync does not own it. */\nfunction managedPackageVersion(repoRoot: string, name: string): string | undefined {\n const manifestPath = path.join(repoRoot, PI_MANAGED_MODULES_DIRECTORY, name, PACKAGE_MANIFEST);\n if (!fs.existsSync(manifestPath)) return undefined;\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n return isRecord(parsed) && typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n // An unreadable manifest carries the same meaning as an absent one: nothing\n // usable is installed, so the caller treats the package as uninstalled.\n return undefined;\n }\n}\n\nexport function packageManagerCommandWithStderr(configured: readonly string[] | undefined): string[] {\n const command = configured?.length ? configured : [DEFAULT_NPM_COMMAND];\n return [process.execPath, '--eval', PACKAGE_MANAGER_STDERR_SCRIPT, '--', ...command];\n}\n\nexport function effectivePackageManagerCommand(\n configured: readonly string[] | undefined,\n environment: NodeJS.ProcessEnv,\n): readonly string[] | undefined {\n if (configured?.length) return configured;\n const bundledCli = environment[NPM_CLI_ENV]?.trim();\n return bundledCli ? [process.execPath, bundledCli] : undefined;\n}\n\nfunction configuredPackageManagerCommand(\n settingsManager: Pick<SettingsManager, 'getNpmCommand'>,\n environment: NodeJS.ProcessEnv,\n): readonly string[] | undefined {\n return effectivePackageManagerCommand(settingsManager.getNpmCommand(), environment);\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 const redirectedSettingsManager = new Proxy(settingsManager, {\n get(target, property, receiver) {\n if (property === 'getNpmCommand') {\n return () => packageManagerCommandWithStderr(configuredPackageManagerCommand(target, environment));\n }\n return Reflect.get(target, property, receiver) as unknown;\n },\n });\n return new DefaultPackageManager({\n cwd: repoRoot,\n agentDir: agentDirectory,\n settingsManager: redirectedSettingsManager,\n });\n}\n\n/** Reads newest published versions with the same client Pi installs them with. */\nfunction createVersionReader(repoRoot: string, environment: NodeJS.ProcessEnv): (name: string) => Promise<string> {\n const settingsManager = SettingsManager.create(repoRoot, piAgentDirectory(environment), { projectTrusted: true });\n const [command, ...args] = configuredPackageManagerCommand(settingsManager, environment) ?? [];\n const client = command ?? DEFAULT_NPM_COMMAND;\n return async (name) => {\n const { stdout } = await execFileAsync(client, [...args, 'view', name, 'version', '--json'], {\n cwd: repoRoot,\n timeout: REGISTRY_TIMEOUT_MS,\n encoding: 'utf8',\n });\n const parsed: unknown = JSON.parse(stdout.trim() || 'null');\n if (typeof parsed !== 'string') throw new Error(`${client} view reported no published version`);\n return parsed;\n };\n}\n\ninterface CheckedPackage {\n name: string;\n from: string;\n to?: string;\n failure?: string;\n}\n\n/**\n * Compares every package sync installed against the registry.\n *\n * Only the managed store is consulted: a package that resolves from the\n * repository's own modules is not sync's to move, and a package that is not\n * installed yet is already covered by the missing-package path.\n */\nasync function resolveUpdates(\n repoRoot: string,\n sources: readonly string[],\n publishedVersion: (name: string) => Promise<string>,\n onProgress: ((message: string) => void) | undefined,\n): Promise<Pick<LayerPackageResult, 'updated' | 'unchecked'>> {\n const managed = sources\n .map((source) => ({ name: packageName(source), from: managedPackageVersion(repoRoot, packageName(source)) }))\n .filter((entry): entry is { name: string; from: string } => entry.from !== undefined);\n const checked: CheckedPackage[] = await Promise.all(\n managed.map(async (entry) => {\n try {\n return { ...entry, to: await publishedVersion(entry.name) };\n } catch (error) {\n return { ...entry, failure: (error instanceof Error ? error.message : String(error)).split('\\n')[0] };\n }\n }),\n );\n\n const updated: LayerPackageUpdate[] = [];\n const unchecked: string[] = [];\n for (const entry of checked) {\n if (entry.to === undefined) {\n unchecked.push(entry.name);\n onProgress?.(`kept ${entry.name} ${entry.from}: ${entry.failure ?? 'no published version'}`);\n continue;\n }\n if (entry.to === entry.from) continue;\n updated.push({ name: entry.name, from: entry.from, to: entry.to });\n onProgress?.(`${entry.name} ${entry.from} -> ${entry.to}`);\n }\n return { updated, unchecked };\n}\n\n/** Installs 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<LayerPackageResult> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const configured = configuredPackageSpecifiers(options.config, options.layers);\n const missing = configured.filter((specifier) => resolvePackageEntries(resolvers, specifier) === undefined);\n const catalog = readPackageCatalog(environment);\n const missingSources = npmSources(missing, catalog);\n const sources = npmSources(configured, catalog, true);\n if (sources.length === 0) return { installed: [], updated: [], unchecked: [] };\n\n const managedDirectory = path.dirname(managedPackageManifestPath(options.repoRoot));\n if (missing.length === 0 && !fs.existsSync(managedDirectory)) return { installed: [], updated: [], unchecked: [] };\n\n const registrySources = sources.filter((source) => !catalog.has(packageName(source)));\n const { updated, unchecked } = options.refresh\n ? await resolveUpdates(\n options.repoRoot,\n registrySources,\n dependencies.publishedVersion ?? createVersionReader(options.repoRoot, environment),\n options.onProgress,\n )\n : { updated: [], unchecked: [] };\n const targets = new Map<string, string>();\n for (const source of sources) {\n const name = packageName(source);\n const target = catalog.get(name)?.target;\n if (target) targets.set(name, target);\n }\n for (const update of updated) targets.set(update.name, update.to);\n const manifestChanged = ensureManagedPackageManifest(options.repoRoot, sources, targets);\n if (missing.length === 0 && !manifestChanged) return { installed: [], updated: [], unchecked };\n\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n options.onProgress?.(\n `installing ${\n updated.length > 0\n ? pluralize(updated.length, 'update')\n : missing.length > 0\n ? pluralize(missing.length, 'missing package')\n : 'the package manifest'\n }`,\n );\n try {\n if (manifestChanged) {\n // Installing one source reconciles the complete dependency set already written\n // to package.json, avoiding one npm install and audit report per DoomPi package.\n await packageManager.install(sources[0]!, { local: true });\n } else {\n await packageManager.resolveExtensionSources(missingSources, { local: true });\n }\n } catch (error) {\n const attempted = manifestChanged ? sources : missingSources;\n throw new Error(`Failed to reconcile DoomPi layer package(s): ${attempted.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 { installed: missingSources, updated, unchecked };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"layerPackageInstaller.d.cts","names":[],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"mappings":";;;;KAoDK,sBAAsB,KAAK;UAEf;EACf;EACA,QAAQ;EACR;EACA,cAAc,OAAO;;;;;;;;EAQrB;;EAEA,cAAc;;UAGC;EACf,iBAAiB;EACjB,YAAY;;EAEZ,oBAAoB,iBAAiB;;;UAItB;EACf;EACA;EACA;;UAGe;;EAEf;;EAEA,SAAS;;EAET;;;iBAqOoB,oBACpB,SAAS,4BACT,eAAc,oCACb,QAAQ"}
1
+ {"version":3,"file":"layerPackageInstaller.d.cts","names":[],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"mappings":";;;;KAsDK,sBAAsB,KAAK;UAEf;EACf;EACA,QAAQ;EACR;EACA,cAAc,OAAO;;;;;;;;EAQrB;;EAEA,cAAc;;UAGC;EACf,iBAAiB;EACjB,YAAY;;EAEZ,oBAAoB,iBAAiB;;;UAItB;EACf;EACA;EACA;;UAGe;;EAEf;;EAEA,SAAS;;EAET;;;iBAySoB,oBACpB,SAAS,4BACT,eAAc,oCACb,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"layerPackageInstaller.d.mts","names":[],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"mappings":";;;;KAoDK,sBAAsB,KAAK;UAEf;EACf;EACA,QAAQ;EACR;EACA,cAAc,OAAO;;;;;;;;EAQrB;;EAEA,cAAc;;UAGC;EACf,iBAAiB;EACjB,YAAY;;EAEZ,oBAAoB,iBAAiB;;;UAItB;EACf;EACA;EACA;;UAGe;;EAEf;;EAEA,SAAS;;EAET;;;iBAqOoB,oBACpB,SAAS,4BACT,eAAc,oCACb,QAAQ"}
1
+ {"version":3,"file":"layerPackageInstaller.d.mts","names":[],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"mappings":";;;;KAsDK,sBAAsB,KAAK;UAEf;EACf;EACA,QAAQ;EACR;EACA,cAAc,OAAO;;;;;;;;EAQrB;;EAEA,cAAc;;UAGC;EACf,iBAAiB;EACjB,YAAY;;EAEZ,oBAAoB,iBAAiB;;;UAItB;EACf;EACA;EACA;;UAGe;;EAEf;;EAEA,SAAS;;EAET;;;iBAySoB,oBACpB,SAAS,4BACT,eAAc,oCACb,QAAQ"}
@@ -1,3 +1,3 @@
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 r from"node:path";import i from"node:fs";import{isLocalPackageSpecifier as a}from"@agimon-ai/doompi-config/majorModes";import{execFile as o}from"node:child_process";import{promisify as s}from"node:util";import{DefaultPackageManager as c,SettingsManager as l}from"@earendil-works/pi-coding-agent";const u=`npm:`,d=r.join(`.pi`,`npm`),f=r.join(d,`node_modules`),p=`package.json`,m=[`const { spawn } = require('node:child_process');`,`const [command, ...args] = process.argv.slice(1);`,`if (!command) throw new Error('Missing package-manager command');`,`const child = spawn(command, args, { stdio: ['ignore', 2, 2] });`,`child.once('error', (error) => { console.error(error.message); process.exit(1); });`,`child.once('exit', (code) => process.exit(code ?? 1));`].join(``),h=s(o);function g(e){let t=e.indexOf(`@`,+!!e.startsWith(`@`));return t===-1?e:e.slice(0,t)}const _={"@hono/node-server@2.0.0 - 2.0.9":`^2.0.10`,"@opentelemetry/core@2.0.0 - 2.7.999":`2.8.0`,"brace-expansion@5.0.0 - 5.0.8":`^5.0.9`,"hono@4.0.0 - 4.12.33":`^4.12.34`,"js-yaml@4.0.0 - 4.3.0":`^4.3.1`,"js-yaml@5.0.0 - 5.2.1":`^5.2.2`,"liquidjs@10.0.0 - 10.27.0":`^10.27.1`,"protobufjs@8.0.0 - 8.7.1":`^8.7.2`},v=new Set(Object.keys(_).map(g));function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e){return y(e)?{...e}:{}}function x(e){let t=b(e);for(let[e,n]of Object.entries(t))v.has(g(e))?delete t[e]:y(n)&&(t[e]=x(n));return t}function S(e){return r.join(e,d,p)}function C(e,t){let n=new Set,r=[...e.default?[e.default]:[],...t.map(t=>{let n=e.layers[t];if(!n)throw Error(`Unknown layer: ${t}`);return n})];for(let e of r)for(let t of e.packages??[]){let e=typeof t==`string`?t:t.name;(typeof t==`string`||t.optional!==!0)&&!a(e)&&n.add(e)}return[...n]}function w(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function T(e,t,n=new Map){let a=S(e),o=i.existsSync(a)?i.readFileSync(a,`utf8`):void 0,s;if(o===void 0)s={name:`pi-extensions`,private:!0};else{let e=JSON.parse(o);if(!y(e))throw Error(`Pi managed package manifest at ${a} must be a JSON object.`);s=e}let c=b(s.dependencies);for(let e of t){let t=D(e),r=n.get(t);r===void 0?Object.hasOwn(c,t)||(c[t]=`*`):c[t]=r}s.dependencies=c,s.overrides={...x(s.overrides),..._};let l=b(s.pnpm);l.overrides={...x(l.overrides),..._},s.pnpm=l;let u=`${JSON.stringify(s,null,2)}\n`;return u!==o&&(i.mkdirSync(r.dirname(a),{recursive:!0}),i.writeFileSync(a,u,`utf8`),!0)}function E(e,t,n){return C(e,t).filter(e=>w(n,e)===void 0)}function D(e){return e.startsWith(u)?e.slice(4):e}function O(t){return[...new Set(t.map(t=>`${u}${e(t).name}`))]}function k(e,t){return`${e} ${t}${e===1?``:`s`}`}function A(e,t){let n=r.join(e,f,t,p);if(i.existsSync(n))try{let e=JSON.parse(i.readFileSync(n,`utf8`));return y(e)&&typeof e.version==`string`?e.version:void 0}catch{return}}function j(e){let t=e?.length?e:[`npm`];return[process.execPath,`--eval`,m,`--`,...t]}function M(e,t){let r=n(t),i=l.create(e,r,{projectTrusted:!0}),a=new Proxy(i,{get(e,t,n){return t===`getNpmCommand`?()=>j(e.getNpmCommand()):Reflect.get(e,t,n)}});return new c({cwd:e,agentDir:r,settingsManager:a})}function N(e,t){let[r,...i]=l.create(e,n(t),{projectTrusted:!0}).getNpmCommand()??[],a=r??`npm`,o=r?i:[];return async t=>{let{stdout:n}=await h(a,[...o,`view`,t,`version`,`--json`],{cwd:e,timeout:2e4,encoding:`utf8`}),r=JSON.parse(n.trim()||`null`);if(typeof r!=`string`)throw Error(`${a} view reported no published version`);return r}}async function P(e,t,n,r){let i=t.map(t=>({name:D(t),from:A(e,D(t))})).filter(e=>e.from!==void 0),a=await Promise.all(i.map(async e=>{try{return{...e,to:await n(e.name)}}catch(t){return{...e,failure:(t instanceof Error?t.message:String(t)).split(`
2
- `)[0]}}})),o=[],s=[];for(let e of a){if(e.to===void 0){s.push(e.name),r?.(`kept ${e.name} ${e.from}: ${e.failure??`no published version`}`);continue}e.to!==e.from&&(o.push({name:e.name,from:e.from,to:e.to}),r?.(`${e.name} ${e.from} -> ${e.to}`))}return{updated:o,unchecked:s}}async function F(e,n={}){let a=e.environment??process.env,o=n.resolvers??t(e.repoRoot),s=C(e.config,e.layers),c=s.filter(e=>w(o,e)===void 0),l=O(c),u=O(s);if(u.length===0)return{installed:[],updated:[],unchecked:[]};let d=r.dirname(S(e.repoRoot));if(c.length===0&&!i.existsSync(d))return{installed:[],updated:[],unchecked:[]};let{updated:f,unchecked:p}=e.refresh?await P(e.repoRoot,u,n.publishedVersion??N(e.repoRoot,a),e.onProgress):{updated:[],unchecked:[]},m=T(e.repoRoot,u,new Map(f.map(e=>[e.name,e.to])));if(c.length===0&&!m)return{installed:[],updated:[],unchecked:p};let h=n.packageManager??M(e.repoRoot,a);e.onProgress?.(`installing ${f.length>0?k(f.length,`update`):c.length>0?k(c.length,`missing package`):`the package manifest`}`);try{m?await h.install(u[0],{local:!0}):await h.resolveExtensionSources(l,{local:!0})}catch(e){throw Error(`Failed to reconcile DoomPi layer package(s): ${(m?u:l).join(`, `)}`,{cause:e})}let g=c.filter(e=>!w(o,e)?.length);if(g.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${g.join(`, `)}`);return{installed:l,updated:f,unchecked:p}}export{_ as SAFE_TRANSITIVE_OVERRIDES,F as ensureLayerPackages,T as ensureManagedPackageManifest,E as missingLayerPackageSpecifiers,j as packageManagerCommandWithStderr};
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 r from"node:path";import i from"node:fs";import{isLocalPackageSpecifier as a}from"@agimon-ai/doompi-config/majorModes";import{execFile as o}from"node:child_process";import{promisify as s}from"node:util";import{DefaultPackageManager as c,SettingsManager as l}from"@earendil-works/pi-coding-agent";const u=`npm:`,d=r.join(`.pi`,`npm`),f=r.join(d,`node_modules`),p=`package.json`,m=[`const { spawn } = require('node:child_process');`,`const [command, ...args] = process.argv.slice(1);`,`if (!command) throw new Error('Missing package-manager command');`,`const child = spawn(command, args, { stdio: ['ignore', 2, 2] });`,`child.once('error', (error) => { console.error(error.message); process.exit(1); });`,`child.once('exit', (code) => process.exit(code ?? 1));`].join(``),h=s(o);function g(e){let t=e.indexOf(`@`,+!!e.startsWith(`@`));return t===-1?e:e.slice(0,t)}const _={"@hono/node-server@2.0.0 - 2.0.9":`^2.0.10`,"@opentelemetry/core@2.0.0 - 2.7.999":`2.8.0`,"brace-expansion@5.0.0 - 5.0.8":`^5.0.9`,"hono@4.0.0 - 4.12.33":`^4.12.34`,"js-yaml@4.0.0 - 4.3.0":`^4.3.1`,"js-yaml@5.0.0 - 5.2.1":`^5.2.2`,"liquidjs@10.0.0 - 10.27.0":`^10.27.1`,"protobufjs@8.0.0 - 8.7.1":`^8.7.2`},v=new Set(Object.keys(_).map(g));function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e){return y(e)?{...e}:{}}function x(e){let t=b(e);for(let[e,n]of Object.entries(t))v.has(g(e))?delete t[e]:y(n)&&(t[e]=x(n));return t}function S(e){return r.join(e,d,p)}function C(e,t){let n=new Set,r=[...e.default?[e.default]:[],...t.map(t=>{let n=e.layers[t];if(!n)throw Error(`Unknown layer: ${t}`);return n})];for(let e of r)for(let t of e.packages??[]){let e=typeof t==`string`?t:t.name;(typeof t==`string`||t.optional!==!0)&&!a(e)&&n.add(e)}return[...n]}function w(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function T(e,t,n=new Map){let a=S(e),o=i.existsSync(a)?i.readFileSync(a,`utf8`):void 0,s;if(o===void 0)s={name:`pi-extensions`,private:!0};else{let e=JSON.parse(o);if(!y(e))throw Error(`Pi managed package manifest at ${a} must be a JSON object.`);s=e}let c=b(s.dependencies);for(let e of t){let t=D(e),r=n.get(t);r===void 0?Object.hasOwn(c,t)||(c[t]=`*`):c[t]=r}s.dependencies=c,s.overrides={...x(s.overrides),..._};let l=b(s.pnpm);l.overrides={...x(l.overrides),..._},s.pnpm=l;let u=`${JSON.stringify(s,null,2)}\n`;return u!==o&&(i.mkdirSync(r.dirname(a),{recursive:!0}),i.writeFileSync(a,u,`utf8`),!0)}function E(e,t,n){return C(e,t).filter(e=>w(n,e)===void 0)}function D(e){let t=e.startsWith(u)?e.slice(4):e;if(t.startsWith(`@`)){let e=t.indexOf(`/`),n=e===-1?-1:t.indexOf(`@`,e);return n===-1?t:t.slice(0,n)}let n=t.indexOf(`@`);return n===-1?t:t.slice(0,n)}function O(e){let t=e.DOOMPI_PACKAGE_CATALOG?.trim();if(!t)return new Map;let n=JSON.parse(i.readFileSync(t,`utf8`));if(!y(n)||n.version!==1||!y(n.packages))throw Error(`Unsupported DoomPi package catalog: ${t}`);let a=new Map;for(let[e,o]of Object.entries(n.packages)){if(!y(o)||typeof o.archive!=`string`||!Array.isArray(o.dependencies))throw Error(`Invalid package entry for ${e} in ${t}`);let n=o.dependencies.filter(e=>typeof e==`string`);if(n.length!==o.dependencies.length)throw Error(`Invalid dependencies for ${e} in ${t}`);let s=r.resolve(r.dirname(t),o.archive);if(!i.existsSync(s))throw Error(`DoomPi package catalog archive is missing: ${s}`);a.set(e,{target:`file:${s}`,dependencies:n})}return a}function k(t,n=new Map,r=!1){let i=[...new Set(t.map(t=>e(t).name))];if(r)for(let e=0;e<i.length;e+=1)for(let t of n.get(i[e])?.dependencies??[])i.includes(t)||i.push(t);return i.map(e=>{let t=n.get(e)?.target;return`${u}${e}${t?`@${t}`:``}`})}function A(e,t){return`${e} ${t}${e===1?``:`s`}`}function j(e,t){let n=r.join(e,f,t,p);if(i.existsSync(n))try{let e=JSON.parse(i.readFileSync(n,`utf8`));return y(e)&&typeof e.version==`string`?e.version:void 0}catch{return}}function M(e){let t=e?.length?e:[`npm`];return[process.execPath,`--eval`,m,`--`,...t]}function N(e,t){if(e?.length)return e;let n=t.DOOMPI_NPM_CLI?.trim();return n?[process.execPath,n]:void 0}function P(e,t){return N(e.getNpmCommand(),t)}function F(e,t){let r=n(t),i=l.create(e,r,{projectTrusted:!0}),a=new Proxy(i,{get(e,n,r){return n===`getNpmCommand`?()=>M(P(e,t)):Reflect.get(e,n,r)}});return new c({cwd:e,agentDir:r,settingsManager:a})}function I(e,t){let[r,...i]=P(l.create(e,n(t),{projectTrusted:!0}),t)??[],a=r??`npm`;return async t=>{let{stdout:n}=await h(a,[...i,`view`,t,`version`,`--json`],{cwd:e,timeout:2e4,encoding:`utf8`}),r=JSON.parse(n.trim()||`null`);if(typeof r!=`string`)throw Error(`${a} view reported no published version`);return r}}async function L(e,t,n,r){let i=t.map(t=>({name:D(t),from:j(e,D(t))})).filter(e=>e.from!==void 0),a=await Promise.all(i.map(async e=>{try{return{...e,to:await n(e.name)}}catch(t){return{...e,failure:(t instanceof Error?t.message:String(t)).split(`
2
+ `)[0]}}})),o=[],s=[];for(let e of a){if(e.to===void 0){s.push(e.name),r?.(`kept ${e.name} ${e.from}: ${e.failure??`no published version`}`);continue}e.to!==e.from&&(o.push({name:e.name,from:e.from,to:e.to}),r?.(`${e.name} ${e.from} -> ${e.to}`))}return{updated:o,unchecked:s}}async function R(e,n={}){let a=e.environment??process.env,o=n.resolvers??t(e.repoRoot),s=C(e.config,e.layers),c=s.filter(e=>w(o,e)===void 0),l=O(a),u=k(c,l),d=k(s,l,!0);if(d.length===0)return{installed:[],updated:[],unchecked:[]};let f=r.dirname(S(e.repoRoot));if(c.length===0&&!i.existsSync(f))return{installed:[],updated:[],unchecked:[]};let p=d.filter(e=>!l.has(D(e))),{updated:m,unchecked:h}=e.refresh?await L(e.repoRoot,p,n.publishedVersion??I(e.repoRoot,a),e.onProgress):{updated:[],unchecked:[]},g=new Map;for(let e of d){let t=D(e),n=l.get(t)?.target;n&&g.set(t,n)}for(let e of m)g.set(e.name,e.to);let _=T(e.repoRoot,d,g);if(c.length===0&&!_)return{installed:[],updated:[],unchecked:h};let v=n.packageManager??F(e.repoRoot,a);e.onProgress?.(`installing ${m.length>0?A(m.length,`update`):c.length>0?A(c.length,`missing package`):`the package manifest`}`);try{_?await v.install(d[0],{local:!0}):await v.resolveExtensionSources(u,{local:!0})}catch(e){throw Error(`Failed to reconcile DoomPi layer package(s): ${(_?d:u).join(`, `)}`,{cause:e})}let y=c.filter(e=>!w(o,e)?.length);if(y.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${y.join(`, `)}`);return{installed:u,updated:m,unchecked:h}}export{_ as SAFE_TRANSITIVE_OVERRIDES,N as effectivePackageManagerCommand,R as ensureLayerPackages,T as ensureManagedPackageManifest,E as missingLayerPackageSpecifiers,M as packageManagerCommandWithStderr};
3
3
  //# sourceMappingURL=layerPackageInstaller.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"layerPackageInstaller.mjs","names":[],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport { 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:';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm');\nconst PI_MANAGED_MODULES_DIRECTORY = path.join(PI_MANAGED_NPM_DIRECTORY, 'node_modules');\nconst PI_MANAGED_PACKAGE_NAME = 'pi-extensions';\nconst UNPINNED_PACKAGE_RANGE = '*';\nconst PACKAGE_MANIFEST = 'package.json';\nconst DEFAULT_NPM_COMMAND = 'npm';\nconst REGISTRY_TIMEOUT_MS = 20_000;\nconst PACKAGE_MANAGER_STDERR_SCRIPT = [\n \"const { spawn } = require('node:child_process');\",\n 'const [command, ...args] = process.argv.slice(1);',\n \"if (!command) throw new Error('Missing package-manager command');\",\n \"const child = spawn(command, args, { stdio: ['ignore', 2, 2] });\",\n \"child.once('error', (error) => { console.error(error.message); process.exit(1); });\",\n \"child.once('exit', (code) => process.exit(code ?? 1));\",\n].join('');\n\nconst execFileAsync = promisify(execFile);\n\nfunction overridePackageName(selector: string): string {\n const separatorIndex = selector.indexOf('@', selector.startsWith('@') ? 1 : 0);\n return separatorIndex === -1 ? selector : selector.slice(0, separatorIndex);\n}\n\n/**\n * Same-major patches for transitive versions pinned by the current foundation packages.\n * npm only honors overrides from the install root, so published extensions cannot carry\n * these fixes in their own manifests.\n */\nexport const SAFE_TRANSITIVE_OVERRIDES = {\n '@hono/node-server@2.0.0 - 2.0.9': '^2.0.10',\n '@opentelemetry/core@2.0.0 - 2.7.999': '2.8.0',\n 'brace-expansion@5.0.0 - 5.0.8': '^5.0.9',\n 'hono@4.0.0 - 4.12.33': '^4.12.34',\n 'js-yaml@4.0.0 - 4.3.0': '^4.3.1',\n 'js-yaml@5.0.0 - 5.2.1': '^5.2.2',\n 'liquidjs@10.0.0 - 10.27.0': '^10.27.1',\n 'protobufjs@8.0.0 - 8.7.1': '^8.7.2',\n} as const satisfies Readonly<Record<string, string>>;\n\nconst SAFE_TRANSITIVE_PACKAGE_NAMES = new Set(Object.keys(SAFE_TRANSITIVE_OVERRIDES).map(overridePackageName));\n\ntype LayerPackageManager = Pick<PackageManager, 'install' | 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n /**\n * Move every managed package to its newest published version.\n *\n * Launch installs what a selection needs and nothing more, so a session never\n * pays for a registry round trip. Sync is the explicit maintenance command and\n * is the only caller that asks for this.\n */\n refresh?: boolean;\n /** Receives one human-readable line per package decision. */\n onProgress?: (message: string) => void;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n /** Registry lookup seam; the default reads the newest version with Pi's npm client. */\n publishedVersion?: (name: string) => Promise<string>;\n}\n\n/** One managed package moving from the installed version to the newest published one. */\nexport interface LayerPackageUpdate {\n name: string;\n from: string;\n to: string;\n}\n\nexport interface LayerPackageResult {\n /** Sources installed because a configured extension could not be resolved. */\n installed: string[];\n /** Packages this run moved to a newer published version. */\n updated: LayerPackageUpdate[];\n /** Packages left at the installed version because the registry could not be read. */\n unchecked: string[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction recordValue(value: unknown): Record<string, unknown> {\n return isRecord(value) ? { ...value } : {};\n}\n\nfunction withoutConflictingTransitiveOverrides(value: unknown): Record<string, unknown> {\n const overrides = recordValue(value);\n for (const [selector, replacement] of Object.entries(overrides)) {\n if (SAFE_TRANSITIVE_PACKAGE_NAMES.has(overridePackageName(selector))) {\n delete overrides[selector];\n } else if (isRecord(replacement)) {\n overrides[selector] = withoutConflictingTransitiveOverrides(replacement);\n }\n }\n return overrides;\n}\n\nfunction managedPackageManifestPath(repoRoot: string): string {\n return path.join(repoRoot, PI_MANAGED_NPM_DIRECTORY, PACKAGE_MANIFEST);\n}\n\nfunction configuredPackageSpecifiers(config: MajorModesConfig, layers: readonly string[]): string[] {\n const specifiers = new Set<string>();\n const selectedDefinitions = [\n ...(config.default ? [config.default] : []),\n ...layers.map((layerName) => {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n return layer;\n }),\n ];\n for (const layer of selectedDefinitions) {\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)) specifiers.add(specifier);\n }\n }\n return [...specifiers];\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/** Adds the complete package set and patched transitive policy to Pi's managed install root. */\nexport function ensureManagedPackageManifest(\n repoRoot: string,\n sources: readonly string[],\n targets: ReadonlyMap<string, string> = new Map(),\n): boolean {\n const manifestPath = managedPackageManifestPath(repoRoot);\n const current = fs.existsSync(manifestPath) ? fs.readFileSync(manifestPath, 'utf8') : undefined;\n let manifest: Record<string, unknown>;\n if (current === undefined) {\n manifest = { name: PI_MANAGED_PACKAGE_NAME, private: true };\n } else {\n const parsed: unknown = JSON.parse(current);\n if (!isRecord(parsed)) throw new Error(`Pi managed package manifest at ${manifestPath} must be a JSON object.`);\n manifest = parsed;\n }\n\n const dependencies = recordValue(manifest.dependencies);\n for (const source of sources) {\n const name = packageName(source);\n const target = targets.get(name);\n // An exact target is what makes an update reach the store: npm keeps a\n // locked version whenever the recorded range still admits it, and the range\n // it writes back after an install always admits the version it just wrote.\n if (target !== undefined) dependencies[name] = target;\n else if (!Object.hasOwn(dependencies, name)) dependencies[name] = UNPINNED_PACKAGE_RANGE;\n }\n manifest.dependencies = dependencies;\n // npm gives nested and overlapping consumer rules precedence in cases that can retain\n // vulnerable versions, so DoomPi owns these package-specific selectors recursively.\n manifest.overrides = {\n ...withoutConflictingTransitiveOverrides(manifest.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n const pnpm = recordValue(manifest.pnpm);\n pnpm.overrides = {\n ...withoutConflictingTransitiveOverrides(pnpm.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n manifest.pnpm = pnpm;\n\n const serialized = `${JSON.stringify(manifest, null, 2)}\\n`;\n if (serialized === current) return false;\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(manifestPath, serialized, 'utf8');\n return true;\n}\n\n/** Finds required npm packages selected by defaults and active layers that DoomPi cannot resolve. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n return configuredPackageSpecifiers(config, layers).filter(\n (specifier) => resolvePackageEntries(resolvers, specifier) === undefined,\n );\n}\n\nfunction packageName(source: string): string {\n return source.startsWith(NPM_SOURCE_PREFIX) ? source.slice(NPM_SOURCE_PREFIX.length) : source;\n}\n\nfunction npmSources(specifiers: readonly string[]): string[] {\n return [...new Set(specifiers.map((specifier) => `${NPM_SOURCE_PREFIX}${splitPackageSpecifier(specifier).name}`))];\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`;\n}\n\n/** Version of a package inside Pi's managed store, absent when sync does not own it. */\nfunction managedPackageVersion(repoRoot: string, name: string): string | undefined {\n const manifestPath = path.join(repoRoot, PI_MANAGED_MODULES_DIRECTORY, name, PACKAGE_MANIFEST);\n if (!fs.existsSync(manifestPath)) return undefined;\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n return isRecord(parsed) && typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n // An unreadable manifest carries the same meaning as an absent one: nothing\n // usable is installed, so the caller treats the package as uninstalled.\n return undefined;\n }\n}\n\nexport function packageManagerCommandWithStderr(configured: readonly string[] | undefined): string[] {\n const command = configured?.length ? configured : [DEFAULT_NPM_COMMAND];\n return [process.execPath, '--eval', PACKAGE_MANAGER_STDERR_SCRIPT, '--', ...command];\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 const redirectedSettingsManager = new Proxy(settingsManager, {\n get(target, property, receiver) {\n if (property === 'getNpmCommand') return () => packageManagerCommandWithStderr(target.getNpmCommand());\n return Reflect.get(target, property, receiver) as unknown;\n },\n });\n return new DefaultPackageManager({\n cwd: repoRoot,\n agentDir: agentDirectory,\n settingsManager: redirectedSettingsManager,\n });\n}\n\n/** Reads newest published versions with the same client Pi installs them with. */\nfunction createVersionReader(repoRoot: string, environment: NodeJS.ProcessEnv): (name: string) => Promise<string> {\n const configured = SettingsManager.create(repoRoot, piAgentDirectory(environment), {\n projectTrusted: true,\n }).getNpmCommand();\n const [command, ...args] = configured ?? [];\n const client = command ?? DEFAULT_NPM_COMMAND;\n const clientArguments = command ? args : [];\n return async (name) => {\n const { stdout } = await execFileAsync(client, [...clientArguments, 'view', name, 'version', '--json'], {\n cwd: repoRoot,\n timeout: REGISTRY_TIMEOUT_MS,\n encoding: 'utf8',\n });\n const parsed: unknown = JSON.parse(stdout.trim() || 'null');\n if (typeof parsed !== 'string') throw new Error(`${client} view reported no published version`);\n return parsed;\n };\n}\n\ninterface CheckedPackage {\n name: string;\n from: string;\n to?: string;\n failure?: string;\n}\n\n/**\n * Compares every package sync installed against the registry.\n *\n * Only the managed store is consulted: a package that resolves from the\n * repository's own modules is not sync's to move, and a package that is not\n * installed yet is already covered by the missing-package path.\n */\nasync function resolveUpdates(\n repoRoot: string,\n sources: readonly string[],\n publishedVersion: (name: string) => Promise<string>,\n onProgress: ((message: string) => void) | undefined,\n): Promise<Pick<LayerPackageResult, 'updated' | 'unchecked'>> {\n const managed = sources\n .map((source) => ({ name: packageName(source), from: managedPackageVersion(repoRoot, packageName(source)) }))\n .filter((entry): entry is { name: string; from: string } => entry.from !== undefined);\n const checked: CheckedPackage[] = await Promise.all(\n managed.map(async (entry) => {\n try {\n return { ...entry, to: await publishedVersion(entry.name) };\n } catch (error) {\n return { ...entry, failure: (error instanceof Error ? error.message : String(error)).split('\\n')[0] };\n }\n }),\n );\n\n const updated: LayerPackageUpdate[] = [];\n const unchecked: string[] = [];\n for (const entry of checked) {\n if (entry.to === undefined) {\n unchecked.push(entry.name);\n onProgress?.(`kept ${entry.name} ${entry.from}: ${entry.failure ?? 'no published version'}`);\n continue;\n }\n if (entry.to === entry.from) continue;\n updated.push({ name: entry.name, from: entry.from, to: entry.to });\n onProgress?.(`${entry.name} ${entry.from} -> ${entry.to}`);\n }\n return { updated, unchecked };\n}\n\n/** Installs 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<LayerPackageResult> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const configured = configuredPackageSpecifiers(options.config, options.layers);\n const missing = configured.filter((specifier) => resolvePackageEntries(resolvers, specifier) === undefined);\n const missingSources = npmSources(missing);\n const sources = npmSources(configured);\n if (sources.length === 0) return { installed: [], updated: [], unchecked: [] };\n\n const managedDirectory = path.dirname(managedPackageManifestPath(options.repoRoot));\n if (missing.length === 0 && !fs.existsSync(managedDirectory)) return { installed: [], updated: [], unchecked: [] };\n\n const { updated, unchecked } = options.refresh\n ? await resolveUpdates(\n options.repoRoot,\n sources,\n dependencies.publishedVersion ?? createVersionReader(options.repoRoot, environment),\n options.onProgress,\n )\n : { updated: [], unchecked: [] };\n const manifestChanged = ensureManagedPackageManifest(\n options.repoRoot,\n sources,\n new Map(updated.map((update) => [update.name, update.to])),\n );\n if (missing.length === 0 && !manifestChanged) return { installed: [], updated: [], unchecked };\n\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n options.onProgress?.(\n `installing ${\n updated.length > 0\n ? pluralize(updated.length, 'update')\n : missing.length > 0\n ? pluralize(missing.length, 'missing package')\n : 'the package manifest'\n }`,\n );\n try {\n if (manifestChanged) {\n // Installing one source reconciles the complete dependency set already written\n // to package.json, avoiding one npm install and audit report per DoomPi package.\n await packageManager.install(sources[0]!, { local: true });\n } else {\n await packageManager.resolveExtensionSources(missingSources, { local: true });\n }\n } catch (error) {\n const attempted = manifestChanged ? sources : missingSources;\n throw new Error(`Failed to reconcile DoomPi layer package(s): ${attempted.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 { installed: missingSources, updated, unchecked };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"layerPackageInstaller.mjs","names":[],"sources":["../../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport { 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:';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm');\nconst PI_MANAGED_MODULES_DIRECTORY = path.join(PI_MANAGED_NPM_DIRECTORY, 'node_modules');\nconst PI_MANAGED_PACKAGE_NAME = 'pi-extensions';\nconst UNPINNED_PACKAGE_RANGE = '*';\nconst PACKAGE_MANIFEST = 'package.json';\nconst DEFAULT_NPM_COMMAND = 'npm';\nconst NPM_CLI_ENV = 'DOOMPI_NPM_CLI';\nconst PACKAGE_CATALOG_ENV = 'DOOMPI_PACKAGE_CATALOG';\nconst REGISTRY_TIMEOUT_MS = 20_000;\nconst PACKAGE_MANAGER_STDERR_SCRIPT = [\n \"const { spawn } = require('node:child_process');\",\n 'const [command, ...args] = process.argv.slice(1);',\n \"if (!command) throw new Error('Missing package-manager command');\",\n \"const child = spawn(command, args, { stdio: ['ignore', 2, 2] });\",\n \"child.once('error', (error) => { console.error(error.message); process.exit(1); });\",\n \"child.once('exit', (code) => process.exit(code ?? 1));\",\n].join('');\n\nconst execFileAsync = promisify(execFile);\n\nfunction overridePackageName(selector: string): string {\n const separatorIndex = selector.indexOf('@', selector.startsWith('@') ? 1 : 0);\n return separatorIndex === -1 ? selector : selector.slice(0, separatorIndex);\n}\n\n/**\n * Same-major patches for transitive versions pinned by the current foundation packages.\n * npm only honors overrides from the install root, so published extensions cannot carry\n * these fixes in their own manifests.\n */\nexport const SAFE_TRANSITIVE_OVERRIDES = {\n '@hono/node-server@2.0.0 - 2.0.9': '^2.0.10',\n '@opentelemetry/core@2.0.0 - 2.7.999': '2.8.0',\n 'brace-expansion@5.0.0 - 5.0.8': '^5.0.9',\n 'hono@4.0.0 - 4.12.33': '^4.12.34',\n 'js-yaml@4.0.0 - 4.3.0': '^4.3.1',\n 'js-yaml@5.0.0 - 5.2.1': '^5.2.2',\n 'liquidjs@10.0.0 - 10.27.0': '^10.27.1',\n 'protobufjs@8.0.0 - 8.7.1': '^8.7.2',\n} as const satisfies Readonly<Record<string, string>>;\n\nconst SAFE_TRANSITIVE_PACKAGE_NAMES = new Set(Object.keys(SAFE_TRANSITIVE_OVERRIDES).map(overridePackageName));\n\ntype LayerPackageManager = Pick<PackageManager, 'install' | 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n /**\n * Move every managed package to its newest published version.\n *\n * Launch installs what a selection needs and nothing more, so a session never\n * pays for a registry round trip. Sync is the explicit maintenance command and\n * is the only caller that asks for this.\n */\n refresh?: boolean;\n /** Receives one human-readable line per package decision. */\n onProgress?: (message: string) => void;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n /** Registry lookup seam; the default reads the newest version with Pi's npm client. */\n publishedVersion?: (name: string) => Promise<string>;\n}\n\n/** One managed package moving from the installed version to the newest published one. */\nexport interface LayerPackageUpdate {\n name: string;\n from: string;\n to: string;\n}\n\nexport interface LayerPackageResult {\n /** Sources installed because a configured extension could not be resolved. */\n installed: string[];\n /** Packages this run moved to a newer published version. */\n updated: LayerPackageUpdate[];\n /** Packages left at the installed version because the registry could not be read. */\n unchecked: string[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction recordValue(value: unknown): Record<string, unknown> {\n return isRecord(value) ? { ...value } : {};\n}\n\nfunction withoutConflictingTransitiveOverrides(value: unknown): Record<string, unknown> {\n const overrides = recordValue(value);\n for (const [selector, replacement] of Object.entries(overrides)) {\n if (SAFE_TRANSITIVE_PACKAGE_NAMES.has(overridePackageName(selector))) {\n delete overrides[selector];\n } else if (isRecord(replacement)) {\n overrides[selector] = withoutConflictingTransitiveOverrides(replacement);\n }\n }\n return overrides;\n}\n\nfunction managedPackageManifestPath(repoRoot: string): string {\n return path.join(repoRoot, PI_MANAGED_NPM_DIRECTORY, PACKAGE_MANIFEST);\n}\n\nfunction configuredPackageSpecifiers(config: MajorModesConfig, layers: readonly string[]): string[] {\n const specifiers = new Set<string>();\n const selectedDefinitions = [\n ...(config.default ? [config.default] : []),\n ...layers.map((layerName) => {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n return layer;\n }),\n ];\n for (const layer of selectedDefinitions) {\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)) specifiers.add(specifier);\n }\n }\n return [...specifiers];\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/** Adds the complete package set and patched transitive policy to Pi's managed install root. */\nexport function ensureManagedPackageManifest(\n repoRoot: string,\n sources: readonly string[],\n targets: ReadonlyMap<string, string> = new Map(),\n): boolean {\n const manifestPath = managedPackageManifestPath(repoRoot);\n const current = fs.existsSync(manifestPath) ? fs.readFileSync(manifestPath, 'utf8') : undefined;\n let manifest: Record<string, unknown>;\n if (current === undefined) {\n manifest = { name: PI_MANAGED_PACKAGE_NAME, private: true };\n } else {\n const parsed: unknown = JSON.parse(current);\n if (!isRecord(parsed)) throw new Error(`Pi managed package manifest at ${manifestPath} must be a JSON object.`);\n manifest = parsed;\n }\n\n const dependencies = recordValue(manifest.dependencies);\n for (const source of sources) {\n const name = packageName(source);\n const target = targets.get(name);\n // An exact target is what makes an update reach the store: npm keeps a\n // locked version whenever the recorded range still admits it, and the range\n // it writes back after an install always admits the version it just wrote.\n if (target !== undefined) dependencies[name] = target;\n else if (!Object.hasOwn(dependencies, name)) dependencies[name] = UNPINNED_PACKAGE_RANGE;\n }\n manifest.dependencies = dependencies;\n // npm gives nested and overlapping consumer rules precedence in cases that can retain\n // vulnerable versions, so DoomPi owns these package-specific selectors recursively.\n manifest.overrides = {\n ...withoutConflictingTransitiveOverrides(manifest.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n const pnpm = recordValue(manifest.pnpm);\n pnpm.overrides = {\n ...withoutConflictingTransitiveOverrides(pnpm.overrides),\n ...SAFE_TRANSITIVE_OVERRIDES,\n };\n manifest.pnpm = pnpm;\n\n const serialized = `${JSON.stringify(manifest, null, 2)}\\n`;\n if (serialized === current) return false;\n fs.mkdirSync(path.dirname(manifestPath), { recursive: true });\n fs.writeFileSync(manifestPath, serialized, 'utf8');\n return true;\n}\n\n/** Finds required npm packages selected by defaults and active layers that DoomPi cannot resolve. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n return configuredPackageSpecifiers(config, layers).filter(\n (specifier) => resolvePackageEntries(resolvers, specifier) === undefined,\n );\n}\n\nfunction packageName(source: string): string {\n const specifier = source.startsWith(NPM_SOURCE_PREFIX) ? source.slice(NPM_SOURCE_PREFIX.length) : source;\n if (specifier.startsWith('@')) {\n const slash = specifier.indexOf('/');\n const version = slash === -1 ? -1 : specifier.indexOf('@', slash);\n return version === -1 ? specifier : specifier.slice(0, version);\n }\n const version = specifier.indexOf('@');\n return version === -1 ? specifier : specifier.slice(0, version);\n}\n\ninterface PackageCatalogEntry {\n target: string;\n dependencies: readonly string[];\n}\n\ntype PackageCatalog = ReadonlyMap<string, PackageCatalogEntry>;\n\nfunction readPackageCatalog(environment: NodeJS.ProcessEnv): PackageCatalog {\n const manifestPath = environment[PACKAGE_CATALOG_ENV]?.trim();\n if (!manifestPath) return new Map();\n const parsed: unknown = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n if (!isRecord(parsed) || parsed.version !== 1 || !isRecord(parsed.packages)) {\n throw new Error(`Unsupported DoomPi package catalog: ${manifestPath}`);\n }\n const catalog = new Map<string, PackageCatalogEntry>();\n for (const [name, value] of Object.entries(parsed.packages)) {\n if (!isRecord(value) || typeof value.archive !== 'string' || !Array.isArray(value.dependencies)) {\n throw new Error(`Invalid package entry for ${name} in ${manifestPath}`);\n }\n const dependencies = value.dependencies.filter(\n (dependency): dependency is string => typeof dependency === 'string',\n );\n if (dependencies.length !== value.dependencies.length)\n throw new Error(`Invalid dependencies for ${name} in ${manifestPath}`);\n const archive = path.resolve(path.dirname(manifestPath), value.archive);\n if (!fs.existsSync(archive)) throw new Error(`DoomPi package catalog archive is missing: ${archive}`);\n catalog.set(name, { target: `file:${archive}`, dependencies });\n }\n return catalog;\n}\n\nfunction npmSources(\n specifiers: readonly string[],\n catalog: PackageCatalog = new Map(),\n includeCatalogDependencies = false,\n): string[] {\n const names = [...new Set(specifiers.map((specifier) => splitPackageSpecifier(specifier).name))];\n if (includeCatalogDependencies) {\n for (let index = 0; index < names.length; index += 1) {\n for (const dependency of catalog.get(names[index]!)?.dependencies ?? []) {\n if (!names.includes(dependency)) names.push(dependency);\n }\n }\n }\n return names.map((name) => {\n const target = catalog.get(name)?.target;\n return `${NPM_SOURCE_PREFIX}${name}${target ? `@${target}` : ''}`;\n });\n}\n\nfunction pluralize(count: number, noun: string): string {\n return `${count} ${noun}${count === 1 ? '' : 's'}`;\n}\n\n/** Version of a package inside Pi's managed store, absent when sync does not own it. */\nfunction managedPackageVersion(repoRoot: string, name: string): string | undefined {\n const manifestPath = path.join(repoRoot, PI_MANAGED_MODULES_DIRECTORY, name, PACKAGE_MANIFEST);\n if (!fs.existsSync(manifestPath)) return undefined;\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));\n return isRecord(parsed) && typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n // An unreadable manifest carries the same meaning as an absent one: nothing\n // usable is installed, so the caller treats the package as uninstalled.\n return undefined;\n }\n}\n\nexport function packageManagerCommandWithStderr(configured: readonly string[] | undefined): string[] {\n const command = configured?.length ? configured : [DEFAULT_NPM_COMMAND];\n return [process.execPath, '--eval', PACKAGE_MANAGER_STDERR_SCRIPT, '--', ...command];\n}\n\nexport function effectivePackageManagerCommand(\n configured: readonly string[] | undefined,\n environment: NodeJS.ProcessEnv,\n): readonly string[] | undefined {\n if (configured?.length) return configured;\n const bundledCli = environment[NPM_CLI_ENV]?.trim();\n return bundledCli ? [process.execPath, bundledCli] : undefined;\n}\n\nfunction configuredPackageManagerCommand(\n settingsManager: Pick<SettingsManager, 'getNpmCommand'>,\n environment: NodeJS.ProcessEnv,\n): readonly string[] | undefined {\n return effectivePackageManagerCommand(settingsManager.getNpmCommand(), environment);\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 const redirectedSettingsManager = new Proxy(settingsManager, {\n get(target, property, receiver) {\n if (property === 'getNpmCommand') {\n return () => packageManagerCommandWithStderr(configuredPackageManagerCommand(target, environment));\n }\n return Reflect.get(target, property, receiver) as unknown;\n },\n });\n return new DefaultPackageManager({\n cwd: repoRoot,\n agentDir: agentDirectory,\n settingsManager: redirectedSettingsManager,\n });\n}\n\n/** Reads newest published versions with the same client Pi installs them with. */\nfunction createVersionReader(repoRoot: string, environment: NodeJS.ProcessEnv): (name: string) => Promise<string> {\n const settingsManager = SettingsManager.create(repoRoot, piAgentDirectory(environment), { projectTrusted: true });\n const [command, ...args] = configuredPackageManagerCommand(settingsManager, environment) ?? [];\n const client = command ?? DEFAULT_NPM_COMMAND;\n return async (name) => {\n const { stdout } = await execFileAsync(client, [...args, 'view', name, 'version', '--json'], {\n cwd: repoRoot,\n timeout: REGISTRY_TIMEOUT_MS,\n encoding: 'utf8',\n });\n const parsed: unknown = JSON.parse(stdout.trim() || 'null');\n if (typeof parsed !== 'string') throw new Error(`${client} view reported no published version`);\n return parsed;\n };\n}\n\ninterface CheckedPackage {\n name: string;\n from: string;\n to?: string;\n failure?: string;\n}\n\n/**\n * Compares every package sync installed against the registry.\n *\n * Only the managed store is consulted: a package that resolves from the\n * repository's own modules is not sync's to move, and a package that is not\n * installed yet is already covered by the missing-package path.\n */\nasync function resolveUpdates(\n repoRoot: string,\n sources: readonly string[],\n publishedVersion: (name: string) => Promise<string>,\n onProgress: ((message: string) => void) | undefined,\n): Promise<Pick<LayerPackageResult, 'updated' | 'unchecked'>> {\n const managed = sources\n .map((source) => ({ name: packageName(source), from: managedPackageVersion(repoRoot, packageName(source)) }))\n .filter((entry): entry is { name: string; from: string } => entry.from !== undefined);\n const checked: CheckedPackage[] = await Promise.all(\n managed.map(async (entry) => {\n try {\n return { ...entry, to: await publishedVersion(entry.name) };\n } catch (error) {\n return { ...entry, failure: (error instanceof Error ? error.message : String(error)).split('\\n')[0] };\n }\n }),\n );\n\n const updated: LayerPackageUpdate[] = [];\n const unchecked: string[] = [];\n for (const entry of checked) {\n if (entry.to === undefined) {\n unchecked.push(entry.name);\n onProgress?.(`kept ${entry.name} ${entry.from}: ${entry.failure ?? 'no published version'}`);\n continue;\n }\n if (entry.to === entry.from) continue;\n updated.push({ name: entry.name, from: entry.from, to: entry.to });\n onProgress?.(`${entry.name} ${entry.from} -> ${entry.to}`);\n }\n return { updated, unchecked };\n}\n\n/** Installs 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<LayerPackageResult> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const configured = configuredPackageSpecifiers(options.config, options.layers);\n const missing = configured.filter((specifier) => resolvePackageEntries(resolvers, specifier) === undefined);\n const catalog = readPackageCatalog(environment);\n const missingSources = npmSources(missing, catalog);\n const sources = npmSources(configured, catalog, true);\n if (sources.length === 0) return { installed: [], updated: [], unchecked: [] };\n\n const managedDirectory = path.dirname(managedPackageManifestPath(options.repoRoot));\n if (missing.length === 0 && !fs.existsSync(managedDirectory)) return { installed: [], updated: [], unchecked: [] };\n\n const registrySources = sources.filter((source) => !catalog.has(packageName(source)));\n const { updated, unchecked } = options.refresh\n ? await resolveUpdates(\n options.repoRoot,\n registrySources,\n dependencies.publishedVersion ?? createVersionReader(options.repoRoot, environment),\n options.onProgress,\n )\n : { updated: [], unchecked: [] };\n const targets = new Map<string, string>();\n for (const source of sources) {\n const name = packageName(source);\n const target = catalog.get(name)?.target;\n if (target) targets.set(name, target);\n }\n for (const update of updated) targets.set(update.name, update.to);\n const manifestChanged = ensureManagedPackageManifest(options.repoRoot, sources, targets);\n if (missing.length === 0 && !manifestChanged) return { installed: [], updated: [], unchecked };\n\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n options.onProgress?.(\n `installing ${\n updated.length > 0\n ? pluralize(updated.length, 'update')\n : missing.length > 0\n ? pluralize(missing.length, 'missing package')\n : 'the package manifest'\n }`,\n );\n try {\n if (manifestChanged) {\n // Installing one source reconciles the complete dependency set already written\n // to package.json, avoiding one npm install and audit report per DoomPi package.\n await packageManager.install(sources[0]!, { local: true });\n } else {\n await packageManager.resolveExtensionSources(missingSources, { local: true });\n }\n } catch (error) {\n const attempted = manifestChanged ? sources : missingSources;\n throw new Error(`Failed to reconcile DoomPi layer package(s): ${attempted.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 { installed: missingSources, updated, unchecked };\n}\n"],"mappings":"ofAUA,MAAM,EAAoB,OACpB,EAA2B,EAAK,KAAK,MAAO,KAAK,EACjD,EAA+B,EAAK,KAAK,EAA0B,cAAc,EAGjF,EAAmB,eAKnB,EAAgC,CACpC,mDACA,oDACA,oEACA,mEACA,sFACA,wDACF,CAAC,CAAC,KAAK,EAAE,EAEH,EAAgB,EAAU,CAAQ,EAExC,SAAS,EAAoB,EAA0B,CACrD,IAAM,EAAiB,EAAS,QAAQ,IAAK,KAAS,WAAW,GAAG,CAAS,EAC7E,OAAO,IAAmB,GAAK,EAAW,EAAS,MAAM,EAAG,CAAc,CAC5E,CAOA,MAAa,EAA4B,CACvC,kCAAmC,UACnC,sCAAuC,QACvC,gCAAiC,SACjC,uBAAwB,WACxB,wBAAyB,SACzB,wBAAyB,SACzB,4BAA6B,WAC7B,2BAA4B,QAC9B,EAEM,EAAgC,IAAI,IAAI,OAAO,KAAK,CAAyB,CAAC,CAAC,IAAI,CAAmB,CAAC,EA4C7G,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAEA,SAAS,EAAY,EAAyC,CAC5D,OAAO,EAAS,CAAK,EAAI,CAAE,GAAG,CAAM,EAAI,CAAC,CAC3C,CAEA,SAAS,EAAsC,EAAyC,CACtF,IAAM,EAAY,EAAY,CAAK,EACnC,IAAK,GAAM,CAAC,EAAU,KAAgB,OAAO,QAAQ,CAAS,EACxD,EAA8B,IAAI,EAAoB,CAAQ,CAAC,EACjE,OAAO,EAAU,GACR,EAAS,CAAW,IAC7B,EAAU,GAAY,EAAsC,CAAW,GAG3E,OAAO,CACT,CAEA,SAAS,EAA2B,EAA0B,CAC5D,OAAO,EAAK,KAAK,EAAU,EAA0B,CAAgB,CACvE,CAEA,SAAS,EAA4B,EAA0B,EAAqC,CAClG,IAAM,EAAa,IAAI,IACjB,EAAsB,CAC1B,GAAI,EAAO,QAAU,CAAC,EAAO,OAAO,EAAI,CAAC,EACzC,GAAG,EAAO,IAAK,GAAc,CAC3B,IAAM,EAAQ,EAAO,OAAO,GAC5B,GAAI,CAAC,EAAO,MAAU,MAAM,kBAAkB,GAAW,EACzD,OAAO,CACT,CAAC,CACH,EACA,IAAK,IAAM,KAAS,EAClB,IAAK,IAAM,KAAc,EAAM,UAAY,CAAC,EAAG,CAC7C,IAAM,EAAY,OAAO,GAAe,SAAW,EAAa,EAAW,MAC1D,OAAO,GAAe,UAAY,EAAW,WAAa,KAC1D,CAAC,EAAwB,CAAS,GAAG,EAAW,IAAI,CAAS,CAChF,CAEF,MAAO,CAAC,GAAG,CAAU,CACvB,CAEA,SAAS,EAAsB,EAAoC,EAAyC,CAC1G,IAAM,EAAU,EAAU,yBAAyB,CAAS,EAC5D,GAAI,IAAY,IAAA,GAAW,OAAO,EAClC,IAAM,EAAQ,EAAU,qBAAqB,CAAS,EACtD,OAAO,EAAQ,CAAC,CAAK,EAAI,IAAA,EAC3B,CAGA,SAAgB,EACd,EACA,EACA,EAAuC,IAAI,IAClC,CACT,IAAM,EAAe,EAA2B,CAAQ,EAClD,EAAU,EAAG,WAAW,CAAY,EAAI,EAAG,aAAa,EAAc,MAAM,EAAI,IAAA,GAClF,EACJ,GAAI,IAAY,IAAA,GACd,EAAW,CAAE,KAAM,gBAAyB,QAAS,EAAK,MACrD,CACL,IAAM,EAAkB,KAAK,MAAM,CAAO,EAC1C,GAAI,CAAC,EAAS,CAAM,EAAG,MAAU,MAAM,kCAAkC,EAAa,wBAAwB,EAC9G,EAAW,CACb,CAEA,IAAM,EAAe,EAAY,EAAS,YAAY,EACtD,IAAK,IAAM,KAAU,EAAS,CAC5B,IAAM,EAAO,EAAY,CAAM,EACzB,EAAS,EAAQ,IAAI,CAAI,EAI3B,IAAW,IAAA,GACL,OAAO,OAAO,EAAc,CAAI,IAAG,EAAa,GAAQ,KADxC,EAAa,GAAQ,CAEjD,CACA,EAAS,aAAe,EAGxB,EAAS,UAAY,CACnB,GAAG,EAAsC,EAAS,SAAS,EAC3D,GAAG,CACL,EACA,IAAM,EAAO,EAAY,EAAS,IAAI,EACtC,EAAK,UAAY,CACf,GAAG,EAAsC,EAAK,SAAS,EACvD,GAAG,CACL,EACA,EAAS,KAAO,EAEhB,IAAM,EAAa,GAAG,KAAK,UAAU,EAAU,KAAM,CAAC,EAAE,IAIxD,OAHI,IAAe,IACnB,EAAG,UAAU,EAAK,QAAQ,CAAY,EAAG,CAAE,UAAW,EAAK,CAAC,EAC5D,EAAG,cAAc,EAAc,EAAY,MAAM,EAC1C,GACT,CAGA,SAAgB,EACd,EACA,EACA,EACU,CACV,OAAO,EAA4B,EAAQ,CAAM,CAAC,CAAC,OAChD,GAAc,EAAsB,EAAW,CAAS,IAAM,IAAA,EACjE,CACF,CAEA,SAAS,EAAY,EAAwB,CAC3C,IAAM,EAAY,EAAO,WAAW,CAAiB,EAAI,EAAO,MAAM,CAAwB,EAAI,EAClG,GAAI,EAAU,WAAW,GAAG,EAAG,CAC7B,IAAM,EAAQ,EAAU,QAAQ,GAAG,EAC7B,EAAU,IAAU,GAAK,GAAK,EAAU,QAAQ,IAAK,CAAK,EAChE,OAAO,IAAY,GAAK,EAAY,EAAU,MAAM,EAAG,CAAO,CAChE,CACA,IAAM,EAAU,EAAU,QAAQ,GAAG,EACrC,OAAO,IAAY,GAAK,EAAY,EAAU,MAAM,EAAG,CAAO,CAChE,CASA,SAAS,EAAmB,EAAgD,CAC1E,IAAM,EAAe,EAAY,wBAAsB,KAAK,EAC5D,GAAI,CAAC,EAAc,OAAO,IAAI,IAC9B,IAAM,EAAkB,KAAK,MAAM,EAAG,aAAa,EAAc,MAAM,CAAC,EACxE,GAAI,CAAC,EAAS,CAAM,GAAK,EAAO,UAAY,GAAK,CAAC,EAAS,EAAO,QAAQ,EACxE,MAAU,MAAM,uCAAuC,GAAc,EAEvE,IAAM,EAAU,IAAI,IACpB,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAO,QAAQ,EAAG,CAC3D,GAAI,CAAC,EAAS,CAAK,GAAK,OAAO,EAAM,SAAY,UAAY,CAAC,MAAM,QAAQ,EAAM,YAAY,EAC5F,MAAU,MAAM,6BAA6B,EAAK,MAAM,GAAc,EAExE,IAAM,EAAe,EAAM,aAAa,OACrC,GAAqC,OAAO,GAAe,QAC9D,EACA,GAAI,EAAa,SAAW,EAAM,aAAa,OAC7C,MAAU,MAAM,4BAA4B,EAAK,MAAM,GAAc,EACvE,IAAM,EAAU,EAAK,QAAQ,EAAK,QAAQ,CAAY,EAAG,EAAM,OAAO,EACtE,GAAI,CAAC,EAAG,WAAW,CAAO,EAAG,MAAU,MAAM,8CAA8C,GAAS,EACpG,EAAQ,IAAI,EAAM,CAAE,OAAQ,QAAQ,IAAW,cAAa,CAAC,CAC/D,CACA,OAAO,CACT,CAEA,SAAS,EACP,EACA,EAA0B,IAAI,IAC9B,EAA6B,GACnB,CACV,IAAM,EAAQ,CAAC,GAAG,IAAI,IAAI,EAAW,IAAK,GAAc,EAAsB,CAAS,CAAC,CAAC,IAAI,CAAC,CAAC,EAC/F,GAAI,EACG,IAAA,IAAI,EAAQ,EAAG,EAAQ,EAAM,OAAQ,GAAS,EACjD,IAAK,IAAM,KAAc,EAAQ,IAAI,EAAM,EAAO,CAAC,EAAE,cAAgB,CAAC,EAC/D,EAAM,SAAS,CAAU,GAAG,EAAM,KAAK,CAAU,EAI5D,OAAO,EAAM,IAAK,GAAS,CACzB,IAAM,EAAS,EAAQ,IAAI,CAAI,CAAC,EAAE,OAClC,MAAO,GAAG,IAAoB,IAAO,EAAS,IAAI,IAAW,IAC/D,CAAC,CACH,CAEA,SAAS,EAAU,EAAe,EAAsB,CACtD,MAAO,GAAG,EAAM,GAAG,IAAO,IAAU,EAAI,GAAK,KAC/C,CAGA,SAAS,EAAsB,EAAkB,EAAkC,CACjF,IAAM,EAAe,EAAK,KAAK,EAAU,EAA8B,EAAM,CAAgB,EACxF,KAAG,WAAW,CAAY,EAC/B,GAAI,CACF,IAAM,EAAkB,KAAK,MAAM,EAAG,aAAa,EAAc,MAAM,CAAC,EACxE,OAAO,EAAS,CAAM,GAAK,OAAO,EAAO,SAAY,SAAW,EAAO,QAAU,IAAA,EACnF,MAAQ,CAGN,MACF,CACF,CAEA,SAAgB,EAAgC,EAAqD,CACnG,IAAM,EAAU,GAAY,OAAS,EAAa,CAAC,KAAmB,EACtE,MAAO,CAAC,QAAQ,SAAU,SAAU,EAA+B,KAAM,GAAG,CAAO,CACrF,CAEA,SAAgB,EACd,EACA,EAC+B,CAC/B,GAAI,GAAY,OAAQ,OAAO,EAC/B,IAAM,EAAa,EAAY,gBAAc,KAAK,EAClD,OAAO,EAAa,CAAC,QAAQ,SAAU,CAAU,EAAI,IAAA,EACvD,CAEA,SAAS,EACP,EACA,EAC+B,CAC/B,OAAO,EAA+B,EAAgB,cAAc,EAAG,CAAW,CACpF,CAEA,SAAS,EAAqB,EAAkB,EAAqD,CACnG,IAAM,EAAiB,EAAiB,CAAW,EAC7C,EAAkB,EAAgB,OAAO,EAAU,EAAgB,CAAE,eAAgB,EAAK,CAAC,EAC3F,EAA4B,IAAI,MAAM,EAAiB,CAC3D,IAAI,EAAQ,EAAU,EAAU,CAI9B,OAHI,IAAa,oBACF,EAAgC,EAAgC,EAAQ,CAAW,CAAC,EAE5F,QAAQ,IAAI,EAAQ,EAAU,CAAQ,CAC/C,CACF,CAAC,EACD,OAAO,IAAI,EAAsB,CAC/B,IAAK,EACL,SAAU,EACV,gBAAiB,CACnB,CAAC,CACH,CAGA,SAAS,EAAoB,EAAkB,EAAmE,CAEhH,GAAM,CAAC,EAAS,GAAG,GAAQ,EADH,EAAgB,OAAO,EAAU,EAAiB,CAAW,EAAG,CAAE,eAAgB,EAAK,CACtC,EAAG,CAAW,GAAK,CAAC,EACvF,EAAS,GAAW,MAC1B,OAAO,KAAO,IAAS,CACrB,GAAM,CAAE,UAAW,MAAM,EAAc,EAAQ,CAAC,GAAG,EAAM,OAAQ,EAAM,UAAW,QAAQ,EAAG,CAC3F,IAAK,EACL,QAAS,IACT,SAAU,MACZ,CAAC,EACK,EAAkB,KAAK,MAAM,EAAO,KAAK,GAAK,MAAM,EAC1D,GAAI,OAAO,GAAW,SAAU,MAAU,MAAM,GAAG,EAAO,oCAAoC,EAC9F,OAAO,CACT,CACF,CAgBA,eAAe,EACb,EACA,EACA,EACA,EAC4D,CAC5D,IAAM,EAAU,EACb,IAAK,IAAY,CAAE,KAAM,EAAY,CAAM,EAAG,KAAM,EAAsB,EAAU,EAAY,CAAM,CAAC,CAAE,EAAE,CAAC,CAC5G,OAAQ,GAAmD,EAAM,OAAS,IAAA,EAAS,EAChF,EAA4B,MAAM,QAAQ,IAC9C,EAAQ,IAAI,KAAO,IAAU,CAC3B,GAAI,CACF,MAAO,CAAE,GAAG,EAAO,GAAI,MAAM,EAAiB,EAAM,IAAI,CAAE,CAC5D,OAAS,EAAO,CACd,MAAO,CAAE,GAAG,EAAO,SAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAA,CAAG,MAAM;CAAI,CAAC,CAAC,EAAG,CACtG,CACF,CAAC,CACH,EAEM,EAAgC,CAAC,EACjC,EAAsB,CAAC,EAC7B,IAAK,IAAM,KAAS,EAAS,CAC3B,GAAI,EAAM,KAAO,IAAA,GAAW,CAC1B,EAAU,KAAK,EAAM,IAAI,EACzB,IAAa,QAAQ,EAAM,KAAK,GAAG,EAAM,KAAK,IAAI,EAAM,SAAW,wBAAwB,EAC3F,QACF,CACI,EAAM,KAAO,EAAM,OACvB,EAAQ,KAAK,CAAE,KAAM,EAAM,KAAM,KAAM,EAAM,KAAM,GAAI,EAAM,EAAG,CAAC,EACjE,IAAa,GAAG,EAAM,KAAK,GAAG,EAAM,KAAK,MAAM,EAAM,IAAI,EAC3D,CACA,MAAO,CAAE,UAAS,WAAU,CAC9B,CAGA,eAAsB,EACpB,EACA,EAAkD,CAAC,EACtB,CAC7B,IAAM,EAAc,EAAQ,aAAe,QAAQ,IAC7C,EAAY,EAAa,WAAa,EAAqB,EAAQ,QAAQ,EAC3E,EAAa,EAA4B,EAAQ,OAAQ,EAAQ,MAAM,EACvE,EAAU,EAAW,OAAQ,GAAc,EAAsB,EAAW,CAAS,IAAM,IAAA,EAAS,EACpG,EAAU,EAAmB,CAAW,EACxC,EAAiB,EAAW,EAAS,CAAO,EAC5C,EAAU,EAAW,EAAY,EAAS,EAAI,EACpD,GAAI,EAAQ,SAAW,EAAG,MAAO,CAAE,UAAW,CAAC,EAAG,QAAS,CAAC,EAAG,UAAW,CAAC,CAAE,EAE7E,IAAM,EAAmB,EAAK,QAAQ,EAA2B,EAAQ,QAAQ,CAAC,EAClF,GAAI,EAAQ,SAAW,GAAK,CAAC,EAAG,WAAW,CAAgB,EAAG,MAAO,CAAE,UAAW,CAAC,EAAG,QAAS,CAAC,EAAG,UAAW,CAAC,CAAE,EAEjH,IAAM,EAAkB,EAAQ,OAAQ,GAAW,CAAC,EAAQ,IAAI,EAAY,CAAM,CAAC,CAAC,EAC9E,CAAE,UAAS,aAAc,EAAQ,QACnC,MAAM,EACJ,EAAQ,SACR,EACA,EAAa,kBAAoB,EAAoB,EAAQ,SAAU,CAAW,EAClF,EAAQ,UACV,EACA,CAAE,QAAS,CAAC,EAAG,UAAW,CAAC,CAAE,EAC3B,EAAU,IAAI,IACpB,IAAK,IAAM,KAAU,EAAS,CAC5B,IAAM,EAAO,EAAY,CAAM,EACzB,EAAS,EAAQ,IAAI,CAAI,CAAC,EAAE,OAC9B,GAAQ,EAAQ,IAAI,EAAM,CAAM,CACtC,CACA,IAAK,IAAM,KAAU,EAAS,EAAQ,IAAI,EAAO,KAAM,EAAO,EAAE,EAChE,IAAM,EAAkB,EAA6B,EAAQ,SAAU,EAAS,CAAO,EACvF,GAAI,EAAQ,SAAW,GAAK,CAAC,EAAiB,MAAO,CAAE,UAAW,CAAC,EAAG,QAAS,CAAC,EAAG,WAAU,EAE7F,IAAM,EAAiB,EAAa,gBAAkB,EAAqB,EAAQ,SAAU,CAAW,EACxG,EAAQ,aACN,cACE,EAAQ,OAAS,EACb,EAAU,EAAQ,OAAQ,QAAQ,EAClC,EAAQ,OAAS,EACf,EAAU,EAAQ,OAAQ,iBAAiB,EAC3C,wBAEV,EACA,GAAI,CACE,EAGF,MAAM,EAAe,QAAQ,EAAQ,GAAK,CAAE,MAAO,EAAK,CAAC,EAEzD,MAAM,EAAe,wBAAwB,EAAgB,CAAE,MAAO,EAAK,CAAC,CAEhF,OAAS,EAAO,CAEd,MAAU,MAAM,iDADE,EAAkB,EAAU,EAAA,CAC4B,KAAK,IAAI,IAAK,CAAE,MAAO,CAAM,CAAC,CAC1G,CAEA,IAAM,EAAa,EAAQ,OAAQ,GAAc,CAAC,EAAsB,EAAW,CAAS,CAAC,EAAE,MAAM,EACrG,GAAI,EAAW,OAAS,EACtB,MAAU,MACR,iFAAiF,EAAW,KAAK,IAAI,GACvG,EAEF,MAAO,CAAE,UAAW,EAAgB,UAAS,WAAU,CACzD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi",
3
- "version": "0.0.1-alpha.50",
3
+ "version": "0.0.1-alpha.52",
4
4
  "description": "Opinionated, composable Pi distribution for scoped agent tools, skills, MCP servers, and developer workflows.",
5
5
  "keywords": [
6
6
  "ai",
@@ -319,17 +319,17 @@
319
319
  "rolldown": "1.2.6",
320
320
  "typebox": "1.3.19",
321
321
  "yaml": "2.9.0",
322
- "@agimon-ai/doompi-autostop": "0.0.1-alpha.27",
323
- "@agimon-ai/doompi-cache": "0.0.1-alpha.16",
324
- "@agimon-ai/doompi-config": "0.0.1-alpha.49",
325
- "@agimon-ai/doompi-domain": "0.0.1-alpha.28",
326
- "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.49",
327
- "@agimon-ai/doompi-major-mode": "0.0.1-alpha.28",
328
- "@agimon-ai/doompi-notification": "0.0.1-alpha.27",
329
- "@agimon-ai/doompi-profile": "0.0.1-alpha.28",
330
- "@agimon-ai/doompi-skill": "0.0.1-alpha.28",
331
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.49",
332
- "@agimon-ai/doompi-ui": "0.0.1-alpha.50"
322
+ "@agimon-ai/doompi-autostop": "0.0.1-alpha.29",
323
+ "@agimon-ai/doompi-cache": "0.0.1-alpha.18",
324
+ "@agimon-ai/doompi-domain": "0.0.1-alpha.30",
325
+ "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.51",
326
+ "@agimon-ai/doompi-major-mode": "0.0.1-alpha.30",
327
+ "@agimon-ai/doompi-notification": "0.0.1-alpha.29",
328
+ "@agimon-ai/doompi-config": "0.0.1-alpha.51",
329
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.51",
330
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.52",
331
+ "@agimon-ai/doompi-profile": "0.0.1-alpha.30",
332
+ "@agimon-ai/doompi-skill": "0.0.1-alpha.30"
333
333
  },
334
334
  "devDependencies": {
335
335
  "@earendil-works/pi-ai": "0.84.4",
@@ -339,7 +339,7 @@
339
339
  "@vitest/coverage-v8": "4.1.11",
340
340
  "typescript": "7.0.2",
341
341
  "vitest": "4.1.11",
342
- "@agimon-ai/doompi-runner": "0.0.1-alpha.50"
342
+ "@agimon-ai/doompi-runner": "0.0.1-alpha.52"
343
343
  },
344
344
  "peerDependencies": {
345
345
  "@earendil-works/pi-tui": "0.84.4"