@agimon-ai/doompi 0.0.1-alpha.17 → 0.0.1-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -21
- package/assets/doompi-tui.png +0 -0
- package/dist/adapters/layerPackageInstaller.cjs +2 -0
- package/dist/adapters/layerPackageInstaller.cjs.map +1 -0
- package/dist/adapters/layerPackageInstaller.mjs +2 -0
- package/dist/adapters/layerPackageInstaller.mjs.map +1 -0
- package/dist/adapters/modules/moduleResolution.cjs +1 -1
- package/dist/adapters/modules/moduleResolution.cjs.map +1 -1
- package/dist/adapters/modules/moduleResolution.d.cts.map +1 -1
- package/dist/adapters/modules/moduleResolution.d.mts.map +1 -1
- package/dist/adapters/modules/moduleResolution.mjs +1 -1
- package/dist/adapters/modules/moduleResolution.mjs.map +1 -1
- package/dist/commands/buildCommand.cjs +2 -2
- package/dist/commands/buildCommand.cjs.map +1 -1
- package/dist/commands/buildCommand.mjs +2 -2
- package/dist/commands/buildCommand.mjs.map +1 -1
- package/dist/services/extensionAssembler.cjs +1 -1
- package/dist/services/extensionAssembler.cjs.map +1 -1
- package/dist/services/extensionAssembler.d.cts.map +1 -1
- package/dist/services/extensionAssembler.d.mts.map +1 -1
- package/dist/services/extensionAssembler.mjs +1 -1
- package/dist/services/extensionAssembler.mjs.map +1 -1
- package/package.json +20 -19
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ Doompi is a configuration framework for [Pi](https://github.com/earendil-works/p
|
|
|
10
10
|
tailored for people whose agent has one MCP server too many. It turns extensions, skills,
|
|
11
11
|
MCP servers, and system prompts into config instead of background noise.
|
|
12
12
|
|
|
13
|
+

|
|
14
|
+
|
|
13
15
|
Plugin systems scope what an agent knows. Nothing scopes what it can reach. Claude Code's
|
|
14
16
|
`enableAllProjectMcpServers` and static denylist are repository-wide. Doompi draws that
|
|
15
17
|
boundary around the session. Pick a major mode and some domains; add a profile if you want
|
|
@@ -92,8 +94,8 @@ A major mode is the base config. It names the extension layers for development,
|
|
|
92
94
|
or whatever else you do. Define as many as you like; only one is active at a time, and you
|
|
93
95
|
can switch it without leaving the session.
|
|
94
96
|
|
|
95
|
-
Minor modes are switches inside that base. They start off, stack freely,
|
|
96
|
-
|
|
97
|
+
Minor modes are battery-included switches inside that base. They start off, stack freely,
|
|
98
|
+
and keep their model tools and skills out of context until turned on. Doompi ships six:
|
|
97
99
|
|
|
98
100
|
- **Help mode** — expose package-owned guidance only while you need it.
|
|
99
101
|
- **Plan mode** — make the repository read-only while you agree on an approach.
|
|
@@ -233,7 +235,7 @@ them one at a time.
|
|
|
233
235
|
|
|
234
236
|
### Configuration and composition
|
|
235
237
|
|
|
236
|
-
`@agimon-ai/doompi` is both an extension and the command-line config compiler. `dpi init`
|
|
238
|
+
[`@agimon-ai/doompi`][pkg-doompi] is both an extension and the command-line config compiler. `dpi init`
|
|
237
239
|
creates repository config for an isolated experiment, while `doompi init` creates the personal
|
|
238
240
|
config and registers the permanent Pi integration. The sync commands resolve every major mode
|
|
239
241
|
and domain into a distribution Pi can load quickly. A large major mode with 15 extensions adds
|
|
@@ -241,27 +243,40 @@ only 400 ms of code startup time.
|
|
|
241
243
|
|
|
242
244
|
### Leader key
|
|
243
245
|
|
|
244
|
-
`@agimon-ai/doompi-ui` turns `SPC` into a map of the available commands. It stays out of
|
|
246
|
+
[`@agimon-ai/doompi-ui`][pkg-doompi-ui] turns `SPC` into a map of the available commands. It stays out of
|
|
245
247
|
the way when a draft is not empty, and other packages contribute bindings through one
|
|
246
248
|
leader API instead of hardcoding their own menus.
|
|
247
249
|
|
|
248
250
|
### Agent team
|
|
249
251
|
|
|
250
|
-
`@agimon-ai/doompi-team` runs named subagents asynchronously against a shared task board.
|
|
252
|
+
[`@agimon-ai/doompi-team`][pkg-doompi-team] runs named subagents asynchronously against a shared task board.
|
|
251
253
|
They can work in parallel, message one another, and use the model policy attached to the
|
|
252
254
|
selected Team package entry. `SPC a l` lists available agents; `SPC a r` opens current-session runs and
|
|
253
255
|
their controls.
|
|
254
256
|
|
|
255
257
|
### Tasks
|
|
256
258
|
|
|
257
|
-
`@agimon-ai/doompi-task` keeps a task graph on disk, not a disposable checklist in the
|
|
259
|
+
[`@agimon-ai/doompi-task`][pkg-doompi-task] keeps a task graph on disk, not a disposable checklist in the
|
|
258
260
|
transcript. Dependencies and delegation survive compaction, and work can be handed to a
|
|
259
|
-
subagent—including a smaller model when the job does not need the expensive one.
|
|
261
|
+
subagent—including a smaller model when the job does not need the expensive one. Seeded
|
|
262
|
+
`minimal` and `copilot` modes select its `task` layer; omit that layer when a major mode
|
|
263
|
+
should not expose the task tool.
|
|
264
|
+
|
|
265
|
+
### Runner
|
|
266
|
+
|
|
267
|
+
[`@agimon-ai/doompi-runner`][pkg-doompi-runner] replaces Pi's blocking `bash` tool with
|
|
268
|
+
supervised command execution in the generated default Copilot mode. Short commands still return
|
|
269
|
+
inline; commands that pass the configurable threshold—60 seconds by default—move into the
|
|
270
|
+
background with durable logs. Use `background: true` for an immediate detached run or
|
|
271
|
+
`interactive: true` when the command needs terminal input. Runner IDs, controls, and logs survive
|
|
272
|
+
compaction and context rewrites and remain available through Runner Space at `SPC r r` or the
|
|
273
|
+
`doom-runner` CLI. Platform-specific RMUX binaries are selected automatically, with a fallback
|
|
274
|
+
when RMUX is unavailable. Custom modes must include the `runner` layer to replace `bash`.
|
|
260
275
|
|
|
261
276
|
### Auto-compact
|
|
262
277
|
|
|
263
278
|
Ordinary compaction waits for one summary to save an overgrown session.
|
|
264
|
-
`@agimon-ai/doompi-autocompact` leaves checkpoints instead:
|
|
279
|
+
[`@agimon-ai/doompi-autocompact`][pkg-doompi-autocompact] leaves checkpoints instead:
|
|
265
280
|
|
|
266
281
|
1. At 50%, it writes the first compact summary.
|
|
267
282
|
2. Later, it combines that summary with the messages since; the model decides whether the
|
|
@@ -273,7 +288,7 @@ and user request with it, so coordination does not have to be guessed back out o
|
|
|
273
288
|
|
|
274
289
|
### Help mode
|
|
275
290
|
|
|
276
|
-
`@agimon-ai/doompi-help` keeps package guidance out of the default prompt. A fresh parent
|
|
291
|
+
[`@agimon-ai/doompi-help`][pkg-doompi-help] keeps package guidance out of the default prompt. A fresh parent
|
|
277
292
|
session performs no Help retrieval and exposes no Help skills. Use `SPC h e`, or the existing
|
|
278
293
|
`minor_mode` client in headless sessions, to activate the package indexes; use the same action
|
|
279
294
|
to deactivate them before the next interaction. The initial contributors expose
|
|
@@ -282,25 +297,26 @@ Help runtime.
|
|
|
282
297
|
|
|
283
298
|
### MCP
|
|
284
299
|
|
|
285
|
-
`@agimon-ai/doompi-mcp` is the gate between a session and its servers. It reads `.mcp.json`
|
|
300
|
+
[`@agimon-ai/doompi-mcp`][pkg-doompi-mcp] is the gate between a session and its servers. It reads `.mcp.json`
|
|
286
301
|
and other common formats, then exposes only the servers and proxy upstreams allowed by the
|
|
287
302
|
selected domains. Switch domains and that boundary reloads with them.
|
|
288
303
|
|
|
289
304
|
### Ask user question
|
|
290
305
|
|
|
291
|
-
`@agimon-ai/doompi-user-feedback` gives the agent a structured question that actually
|
|
306
|
+
[`@agimon-ai/doompi-user-feedback`][pkg-doompi-user-feedback] gives the agent a structured question that actually
|
|
292
307
|
waits for an answer. In autonomous Voice mode it skips the modal, narrates the choices,
|
|
293
308
|
and accepts the next spoken response as an ordinary user message.
|
|
294
309
|
|
|
295
310
|
### Logging and telemetry
|
|
296
311
|
|
|
297
312
|
Doompi telemetry records counters and spans, never prompt text or file content, in a local
|
|
298
|
-
SQLite database by default. `SPC h l` opens the metrics, and
|
|
299
|
-
gives the agent CLI tools for inspecting its own
|
|
313
|
+
SQLite database by default. `SPC h l` opens the metrics, and
|
|
314
|
+
[`@agimon-ai/log-sink-mcp`][pkg-log-sink-mcp] gives the agent CLI tools for inspecting its own
|
|
315
|
+
runs.
|
|
300
316
|
|
|
301
317
|
### Plan mode
|
|
302
318
|
|
|
303
|
-
A promise to "only plan" is not a permission boundary. `@agimon-ai/doompi-plan` makes the
|
|
319
|
+
A promise to "only plan" is not a permission boundary. [`@agimon-ai/doompi-plan`][pkg-doompi-plan] makes the
|
|
304
320
|
repository read-only while the agent explores, persists the plan, and hands it back for
|
|
305
321
|
approval. Use `SPC p p` for normal planning, `SPC p d` for debug planning, `SPC p f` for
|
|
306
322
|
the Fable flow, and `SPC p e` to exit. Turn it on when the approach should be settled
|
|
@@ -308,21 +324,21 @@ before the files move.
|
|
|
308
324
|
|
|
309
325
|
### Loop mode
|
|
310
326
|
|
|
311
|
-
`@agimon-ai/doompi-loop` is an in-session scheduler. It runs a prompt immediately and then
|
|
327
|
+
[`@agimon-ai/doompi-loop`][pkg-doompi-loop] is an in-session scheduler. It runs a prompt immediately and then
|
|
312
328
|
repeats it on an interval; several loops can coexist. Use `SPC l s` to start one and
|
|
313
329
|
`SPC l l` to list or stop them. It is for recurring checks and prompts that belong to the
|
|
314
330
|
current session.
|
|
315
331
|
|
|
316
332
|
### Goal mode
|
|
317
333
|
|
|
318
|
-
`@agimon-ai/doompi-goal` pins one objective to the session until it completes or you end
|
|
334
|
+
[`@agimon-ai/doompi-goal`][pkg-doompi-goal] pins one objective to the session until it completes or you end
|
|
319
335
|
it. Use `SPC g g` for status, `SPC g s` to start, `SPC g e` to end, and `SPC g p` for
|
|
320
336
|
history. Finished goals leave the prompt and tools behind but remain in history when you
|
|
321
337
|
want to restart one.
|
|
322
338
|
|
|
323
339
|
### Workflow mode
|
|
324
340
|
|
|
325
|
-
`@agimon-ai/doompi-workflow` runs GitHub Actions-style job graphs with dependencies,
|
|
341
|
+
[`@agimon-ai/doompi-workflow`][pkg-doompi-workflow] runs GitHub Actions-style job graphs with dependencies,
|
|
326
342
|
timeouts, artifacts, and a separate Doompi session for each step. Use `SPC w w` to launch,
|
|
327
343
|
`SPC w l` to manage, `SPC w r` to recover a failed run, and `SPC w e` to give the agent
|
|
328
344
|
workflow tools or take them back. It is for work that needs hard job boundaries and
|
|
@@ -330,7 +346,7 @@ explicit handoffs rather than one long conversation.
|
|
|
330
346
|
|
|
331
347
|
### Voice mode
|
|
332
348
|
|
|
333
|
-
`@agimon-ai/doompi-voice` records and transcribes speech locally; audio stays on the
|
|
349
|
+
[`@agimon-ai/doompi-voice`][pkg-doompi-voice] records and transcribes speech locally; audio stays on the
|
|
334
350
|
machine. `SPC v v` is one-shot manual dictation and never enables Voice tools. `SPC v a`
|
|
335
351
|
toggles autonomous capture; only its exact-active TUI session receives the two Voice
|
|
336
352
|
façades plus the standalone `narrate` tool.
|
|
@@ -503,6 +519,24 @@ to be surprised with you.
|
|
|
503
519
|
|
|
504
520
|
## Package release order
|
|
505
521
|
|
|
506
|
-
Publish `@agimon-ai/doompi-extension-contracts` first, then
|
|
507
|
-
|
|
508
|
-
|
|
522
|
+
Publish [`@agimon-ai/doompi-extension-contracts`][pkg-doompi-extension-contracts] first, then
|
|
523
|
+
[`@agimon-ai/doompi-help`][pkg-doompi-help], and only then the
|
|
524
|
+
[`@agimon-ai/doompi`][pkg-doompi] runtime that consumes them. Generated changelogs remain owned
|
|
525
|
+
by the release tooling.
|
|
526
|
+
|
|
527
|
+
[pkg-doompi]: https://www.npmjs.com/package/@agimon-ai/doompi
|
|
528
|
+
[pkg-doompi-ui]: https://www.npmjs.com/package/@agimon-ai/doompi-ui
|
|
529
|
+
[pkg-doompi-team]: https://www.npmjs.com/package/@agimon-ai/doompi-team
|
|
530
|
+
[pkg-doompi-task]: https://www.npmjs.com/package/@agimon-ai/doompi-task
|
|
531
|
+
[pkg-doompi-runner]: https://www.npmjs.com/package/@agimon-ai/doompi-runner
|
|
532
|
+
[pkg-doompi-autocompact]: https://www.npmjs.com/package/@agimon-ai/doompi-autocompact
|
|
533
|
+
[pkg-doompi-help]: https://www.npmjs.com/package/@agimon-ai/doompi-help
|
|
534
|
+
[pkg-doompi-mcp]: https://www.npmjs.com/package/@agimon-ai/doompi-mcp
|
|
535
|
+
[pkg-doompi-user-feedback]: https://www.npmjs.com/package/@agimon-ai/doompi-user-feedback
|
|
536
|
+
[pkg-log-sink-mcp]: https://www.npmjs.com/package/@agimon-ai/log-sink-mcp
|
|
537
|
+
[pkg-doompi-plan]: https://www.npmjs.com/package/@agimon-ai/doompi-plan
|
|
538
|
+
[pkg-doompi-loop]: https://www.npmjs.com/package/@agimon-ai/doompi-loop
|
|
539
|
+
[pkg-doompi-goal]: https://www.npmjs.com/package/@agimon-ai/doompi-goal
|
|
540
|
+
[pkg-doompi-workflow]: https://www.npmjs.com/package/@agimon-ai/doompi-workflow
|
|
541
|
+
[pkg-doompi-voice]: https://www.npmjs.com/package/@agimon-ai/doompi-voice
|
|
542
|
+
[pkg-doompi-extension-contracts]: https://www.npmjs.com/package/@agimon-ai/doompi-extension-contracts
|
|
Binary file
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`./modules/moduleResolution.cjs`),t=require(`../services/extensionAssembler.cjs`),n=require(`./piSettings.cjs`);let r=require(`@agimon-ai/doompi-config/majorModes`),i=require(`@earendil-works/pi-coding-agent`);function a(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function o(e,t,n){let i=new Set;for(let o of t){let t=e.layers[o];if(!t)throw Error(`Unknown layer: ${o}`);for(let e of t.packages??[]){let t=typeof e==`string`?e:e.name;typeof e!=`string`&&e.optional===!0||(0,r.isLocalPackageSpecifier)(t)||a(n,t)===void 0&&i.add(t)}}return[...i]}function s(t){return[...new Set(t.map(t=>`npm:${e.splitPackageSpecifier(t).name}`))]}function c(e,t){let r=n.piAgentDirectory(t);return new i.DefaultPackageManager({cwd:e,agentDir:r,settingsManager:i.SettingsManager.create(e,r,{projectTrusted:!0})})}async function l(e,n={}){let r=e.environment??process.env,i=n.resolvers??t.createLayerResolvers(e.repoRoot),l=o(e.config,e.layers,i);if(l.length===0)return[];let u=s(l),d=n.packageManager??c(e.repoRoot,r);try{await d.resolveExtensionSources(u,{local:!0})}catch(e){throw Error(`Failed to install missing DoomPi layer package(s): ${u.join(`, `)}`,{cause:e})}let f=l.filter(e=>!a(i,e)?.length);if(f.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${f.join(`, `)}`);return u}exports.ensureLayerPackages=l;
|
|
2
|
+
//# sourceMappingURL=layerPackageInstaller.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layerPackageInstaller.cjs","names":["splitPackageSpecifier","piAgentDirectory","DefaultPackageManager","SettingsManager","createLayerResolvers"],"sources":["../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { isLocalPackageSpecifier, type MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DefaultPackageManager, type PackageManager, SettingsManager } from '@earendil-works/pi-coding-agent';\nimport { createLayerResolvers, type ExtensionLayerResolvers } from '../services/extensionAssembler.ts';\nimport { splitPackageSpecifier } from './modules/moduleResolution.ts';\nimport { piAgentDirectory } from './piSettings.ts';\n\nconst NPM_SOURCE_PREFIX = 'npm:';\n\ntype LayerPackageManager = Pick<PackageManager, 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n}\n\nfunction resolvePackageEntries(resolvers: ExtensionLayerResolvers, specifier: string): string[] | undefined {\n const entries = resolvers.optionalPackageEntries?.(specifier);\n if (entries !== undefined) return entries;\n const entry = resolvers.optionalPackageEntry(specifier);\n return entry ? [entry] : undefined;\n}\n\n/** Finds required npm packages selected by the active layers that are not installed anywhere DoomPi resolves. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n const missing = new Set<string>();\n for (const layerName of layers) {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n for (const configured of layer.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured !== 'string' && configured.optional === true;\n if (optional || isLocalPackageSpecifier(specifier)) continue;\n // An empty entry list means the package exists but declares no usable Pi\n // extension. Leave that validation to the assembler rather than masking a\n // broken install with another copy from the registry.\n if (resolvePackageEntries(resolvers, specifier) === undefined) missing.add(specifier);\n }\n }\n return [...missing];\n}\n\nfunction npmSources(specifiers: readonly string[]): string[] {\n return [...new Set(specifiers.map((specifier) => `${NPM_SOURCE_PREFIX}${splitPackageSpecifier(specifier).name}`))];\n}\n\nfunction createPackageManager(repoRoot: string, environment: NodeJS.ProcessEnv): LayerPackageManager {\n const agentDirectory = piAgentDirectory(environment);\n const settingsManager = SettingsManager.create(repoRoot, agentDirectory, { projectTrusted: true });\n return new DefaultPackageManager({ cwd: repoRoot, agentDir: agentDirectory, settingsManager });\n}\n\n/** Installs missing selected layer packages into Pi's project-local `.pi/npm` store and verifies the retry. */\nexport async function ensureLayerPackages(\n options: EnsureLayerPackagesOptions,\n dependencies: LayerPackageInstallerDependencies = {},\n): Promise<string[]> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const missing = missingLayerPackageSpecifiers(options.config, options.layers, resolvers);\n if (missing.length === 0) return [];\n\n const sources = npmSources(missing);\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n try {\n await packageManager.resolveExtensionSources(sources, { local: true });\n } catch (error) {\n throw new Error(`Failed to install missing DoomPi layer package(s): ${sources.join(', ')}`, { cause: error });\n }\n\n const unresolved = missing.filter((specifier) => !resolvePackageEntries(resolvers, specifier)?.length);\n if (unresolved.length > 0) {\n throw new Error(\n `Installed DoomPi layer package(s) did not expose the configured Pi extension: ${unresolved.join(', ')}`,\n );\n }\n return sources;\n}\n"],"mappings":"+QAsBA,SAAS,EAAsB,EAAoC,EAAyC,CAC1G,IAAM,EAAU,EAAU,yBAAyB,EAAU,CAC7D,GAAI,IAAY,IAAA,GAAW,OAAO,EAClC,IAAM,EAAQ,EAAU,qBAAqB,EAAU,CACvD,OAAO,EAAQ,CAAC,EAAM,CAAG,IAAA,GAI3B,SAAgB,EACd,EACA,EACA,EACU,CACV,IAAM,EAAU,IAAI,IACpB,IAAK,IAAM,KAAa,EAAQ,CAC9B,IAAM,EAAQ,EAAO,OAAO,GAC5B,GAAI,CAAC,EAAO,MAAU,MAAM,kBAAkB,IAAY,CAC1D,IAAK,IAAM,KAAc,EAAM,UAAY,EAAE,CAAE,CAC7C,IAAM,EAAY,OAAO,GAAe,SAAW,EAAa,EAAW,KAC1D,OAAO,GAAe,UAAY,EAAW,WAAa,KAAA,EAAA,EAAA,yBACnC,EAAU,EAI9C,EAAsB,EAAW,EAAU,GAAK,IAAA,IAAW,EAAQ,IAAI,EAAU,EAGzF,MAAO,CAAC,GAAG,EAAQ,CAGrB,SAAS,EAAW,EAAyC,CAC3D,MAAO,CAAC,GAAG,IAAI,IAAI,EAAW,IAAK,GAAc,OAAuBA,EAAAA,sBAAsB,EAAU,CAAC,OAAO,CAAC,CAAC,CAGpH,SAAS,EAAqB,EAAkB,EAAqD,CACnG,IAAM,EAAiBC,EAAAA,iBAAiB,EAAY,CAEpD,OAAO,IAAIC,EAAAA,sBAAsB,CAAE,IAAK,EAAU,SAAU,EAAgB,gBADpDC,EAAAA,gBAAgB,OAAO,EAAU,EAAgB,CAAE,eAAgB,GAAM,CACN,CAAE,CAAC,CAIhG,eAAsB,EACpB,EACA,EAAkD,EAAE,CACjC,CACnB,IAAM,EAAc,EAAQ,aAAe,QAAQ,IAC7C,EAAY,EAAa,WAAaC,EAAAA,qBAAqB,EAAQ,SAAS,CAC5E,EAAU,EAA8B,EAAQ,OAAQ,EAAQ,OAAQ,EAAU,CACxF,GAAI,EAAQ,SAAW,EAAG,MAAO,EAAE,CAEnC,IAAM,EAAU,EAAW,EAAQ,CAC7B,EAAiB,EAAa,gBAAkB,EAAqB,EAAQ,SAAU,EAAY,CACzG,GAAI,CACF,MAAM,EAAe,wBAAwB,EAAS,CAAE,MAAO,GAAM,CAAC,OAC/D,EAAO,CACd,MAAU,MAAM,sDAAsD,EAAQ,KAAK,KAAK,GAAI,CAAE,MAAO,EAAO,CAAC,CAG/G,IAAM,EAAa,EAAQ,OAAQ,GAAc,CAAC,EAAsB,EAAW,EAAU,EAAE,OAAO,CACtG,GAAI,EAAW,OAAS,EACtB,MAAU,MACR,iFAAiF,EAAW,KAAK,KAAK,GACvG,CAEH,OAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{splitPackageSpecifier as e}from"./modules/moduleResolution.mjs";import{createLayerResolvers as t}from"../services/extensionAssembler.mjs";import{piAgentDirectory as n}from"./piSettings.mjs";import{isLocalPackageSpecifier as r}from"@agimon-ai/doompi-config/majorModes";import{DefaultPackageManager as i,SettingsManager as a}from"@earendil-works/pi-coding-agent";function o(e,t){let n=e.optionalPackageEntries?.(t);if(n!==void 0)return n;let r=e.optionalPackageEntry(t);return r?[r]:void 0}function s(e,t,n){let i=new Set;for(let a of t){let t=e.layers[a];if(!t)throw Error(`Unknown layer: ${a}`);for(let e of t.packages??[]){let t=typeof e==`string`?e:e.name;typeof e!=`string`&&e.optional===!0||r(t)||o(n,t)===void 0&&i.add(t)}}return[...i]}function c(t){return[...new Set(t.map(t=>`npm:${e(t).name}`))]}function l(e,t){let r=n(t);return new i({cwd:e,agentDir:r,settingsManager:a.create(e,r,{projectTrusted:!0})})}async function u(e,n={}){let r=e.environment??process.env,i=n.resolvers??t(e.repoRoot),a=s(e.config,e.layers,i);if(a.length===0)return[];let u=c(a),d=n.packageManager??l(e.repoRoot,r);try{await d.resolveExtensionSources(u,{local:!0})}catch(e){throw Error(`Failed to install missing DoomPi layer package(s): ${u.join(`, `)}`,{cause:e})}let f=a.filter(e=>!o(i,e)?.length);if(f.length>0)throw Error(`Installed DoomPi layer package(s) did not expose the configured Pi extension: ${f.join(`, `)}`);return u}export{u as ensureLayerPackages};
|
|
2
|
+
//# sourceMappingURL=layerPackageInstaller.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layerPackageInstaller.mjs","names":[],"sources":["../../src/adapters/layerPackageInstaller.ts"],"sourcesContent":["import { isLocalPackageSpecifier, type MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { DefaultPackageManager, type PackageManager, SettingsManager } from '@earendil-works/pi-coding-agent';\nimport { createLayerResolvers, type ExtensionLayerResolvers } from '../services/extensionAssembler.ts';\nimport { splitPackageSpecifier } from './modules/moduleResolution.ts';\nimport { piAgentDirectory } from './piSettings.ts';\n\nconst NPM_SOURCE_PREFIX = 'npm:';\n\ntype LayerPackageManager = Pick<PackageManager, 'resolveExtensionSources'>;\n\nexport interface EnsureLayerPackagesOptions {\n repoRoot: string;\n config: MajorModesConfig;\n layers: readonly string[];\n environment?: NodeJS.ProcessEnv;\n}\n\nexport interface LayerPackageInstallerDependencies {\n packageManager?: LayerPackageManager;\n resolvers?: ExtensionLayerResolvers;\n}\n\nfunction resolvePackageEntries(resolvers: ExtensionLayerResolvers, specifier: string): string[] | undefined {\n const entries = resolvers.optionalPackageEntries?.(specifier);\n if (entries !== undefined) return entries;\n const entry = resolvers.optionalPackageEntry(specifier);\n return entry ? [entry] : undefined;\n}\n\n/** Finds required npm packages selected by the active layers that are not installed anywhere DoomPi resolves. */\nexport function missingLayerPackageSpecifiers(\n config: MajorModesConfig,\n layers: readonly string[],\n resolvers: ExtensionLayerResolvers,\n): string[] {\n const missing = new Set<string>();\n for (const layerName of layers) {\n const layer = config.layers[layerName];\n if (!layer) throw new Error(`Unknown layer: ${layerName}`);\n for (const configured of layer.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured !== 'string' && configured.optional === true;\n if (optional || isLocalPackageSpecifier(specifier)) continue;\n // An empty entry list means the package exists but declares no usable Pi\n // extension. Leave that validation to the assembler rather than masking a\n // broken install with another copy from the registry.\n if (resolvePackageEntries(resolvers, specifier) === undefined) missing.add(specifier);\n }\n }\n return [...missing];\n}\n\nfunction npmSources(specifiers: readonly string[]): string[] {\n return [...new Set(specifiers.map((specifier) => `${NPM_SOURCE_PREFIX}${splitPackageSpecifier(specifier).name}`))];\n}\n\nfunction createPackageManager(repoRoot: string, environment: NodeJS.ProcessEnv): LayerPackageManager {\n const agentDirectory = piAgentDirectory(environment);\n const settingsManager = SettingsManager.create(repoRoot, agentDirectory, { projectTrusted: true });\n return new DefaultPackageManager({ cwd: repoRoot, agentDir: agentDirectory, settingsManager });\n}\n\n/** Installs missing selected layer packages into Pi's project-local `.pi/npm` store and verifies the retry. */\nexport async function ensureLayerPackages(\n options: EnsureLayerPackagesOptions,\n dependencies: LayerPackageInstallerDependencies = {},\n): Promise<string[]> {\n const environment = options.environment ?? process.env;\n const resolvers = dependencies.resolvers ?? createLayerResolvers(options.repoRoot);\n const missing = missingLayerPackageSpecifiers(options.config, options.layers, resolvers);\n if (missing.length === 0) return [];\n\n const sources = npmSources(missing);\n const packageManager = dependencies.packageManager ?? createPackageManager(options.repoRoot, environment);\n try {\n await packageManager.resolveExtensionSources(sources, { local: true });\n } catch (error) {\n throw new Error(`Failed to install missing DoomPi layer package(s): ${sources.join(', ')}`, { cause: error });\n }\n\n const unresolved = missing.filter((specifier) => !resolvePackageEntries(resolvers, specifier)?.length);\n if (unresolved.length > 0) {\n throw new Error(\n `Installed DoomPi layer package(s) did not expose the configured Pi extension: ${unresolved.join(', ')}`,\n );\n }\n return sources;\n}\n"],"mappings":"gXAsBA,SAAS,EAAsB,EAAoC,EAAyC,CAC1G,IAAM,EAAU,EAAU,yBAAyB,EAAU,CAC7D,GAAI,IAAY,IAAA,GAAW,OAAO,EAClC,IAAM,EAAQ,EAAU,qBAAqB,EAAU,CACvD,OAAO,EAAQ,CAAC,EAAM,CAAG,IAAA,GAI3B,SAAgB,EACd,EACA,EACA,EACU,CACV,IAAM,EAAU,IAAI,IACpB,IAAK,IAAM,KAAa,EAAQ,CAC9B,IAAM,EAAQ,EAAO,OAAO,GAC5B,GAAI,CAAC,EAAO,MAAU,MAAM,kBAAkB,IAAY,CAC1D,IAAK,IAAM,KAAc,EAAM,UAAY,EAAE,CAAE,CAC7C,IAAM,EAAY,OAAO,GAAe,SAAW,EAAa,EAAW,KAC1D,OAAO,GAAe,UAAY,EAAW,WAAa,IAC3D,EAAwB,EAAU,EAI9C,EAAsB,EAAW,EAAU,GAAK,IAAA,IAAW,EAAQ,IAAI,EAAU,EAGzF,MAAO,CAAC,GAAG,EAAQ,CAGrB,SAAS,EAAW,EAAyC,CAC3D,MAAO,CAAC,GAAG,IAAI,IAAI,EAAW,IAAK,GAAc,OAAuB,EAAsB,EAAU,CAAC,OAAO,CAAC,CAAC,CAGpH,SAAS,EAAqB,EAAkB,EAAqD,CACnG,IAAM,EAAiB,EAAiB,EAAY,CAEpD,OAAO,IAAI,EAAsB,CAAE,IAAK,EAAU,SAAU,EAAgB,gBADpD,EAAgB,OAAO,EAAU,EAAgB,CAAE,eAAgB,GAAM,CACN,CAAE,CAAC,CAIhG,eAAsB,EACpB,EACA,EAAkD,EAAE,CACjC,CACnB,IAAM,EAAc,EAAQ,aAAe,QAAQ,IAC7C,EAAY,EAAa,WAAa,EAAqB,EAAQ,SAAS,CAC5E,EAAU,EAA8B,EAAQ,OAAQ,EAAQ,OAAQ,EAAU,CACxF,GAAI,EAAQ,SAAW,EAAG,MAAO,EAAE,CAEnC,IAAM,EAAU,EAAW,EAAQ,CAC7B,EAAiB,EAAa,gBAAkB,EAAqB,EAAQ,SAAU,EAAY,CACzG,GAAI,CACF,MAAM,EAAe,wBAAwB,EAAS,CAAE,MAAO,GAAM,CAAC,OAC/D,EAAO,CACd,MAAU,MAAM,sDAAsD,EAAQ,KAAK,KAAK,GAAI,CAAE,MAAO,EAAO,CAAC,CAG/G,IAAM,EAAa,EAAQ,OAAQ,GAAc,CAAC,EAAsB,EAAW,EAAU,EAAE,OAAO,CACtG,GAAI,EAAW,OAAS,EACtB,MAAU,MACR,iFAAiF,EAAW,KAAK,KAAK,GACvG,CAEH,OAAO"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`../../_virtual/_rolldown/runtime.cjs`);let t=require(`node:url`),n=require(`node:path`);n=e.__toESM(n,1);let r=require(`node:fs`);r=e.__toESM(r,1);let i=require(`minimatch`);const a=`package.json`,o=[`!`,`+`,`-`],
|
|
1
|
+
const e=require(`../../_virtual/_rolldown/runtime.cjs`);let t=require(`node:url`),n=require(`node:path`);n=e.__toESM(n,1);let r=require(`node:fs`);r=e.__toESM(r,1);let i=require(`minimatch`);const a=`package.json`,o=`node_modules`,s=n.default.join(`.pi`,`npm`,o),c=[`!`,`+`,`-`],l=/[*?[\]{}()]/,u=[`index.ts`,`index.js`,`index.mts`,`index.mjs`,`index.cts`,`index.cjs`],d=new Set([`.ts`,`.js`,`.mts`,`.mjs`,`.cts`,`.cjs`]),f=[`import`,`module`,`node`,`default`];function p(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function m(e){try{let t=JSON.parse(r.default.readFileSync(n.default.join(e,a),`utf8`));return p(t)?t:void 0}catch{return}}function h(e){return!!(e&&p(e.pi)&&Object.hasOwn(e.pi,`extensions`))}function g(e){return c.some(t=>e.startsWith(t))}function _(e,t){return n.default.relative(e,t).split(n.default.sep).join(`/`)}function v(e,t,r){let a=t.replaceAll(`\\`,`/`).replace(/^\.\//,``);return(0,i.minimatch)(_(r,e),a)||(0,i.minimatch)(n.default.basename(e),a)||(0,i.minimatch)(e.split(n.default.sep).join(`/`),a)}function y(e,t,r){let i=t.replaceAll(`\\`,`/`).replace(/^\.\//,``);return _(r,e)===i||e.split(n.default.sep).join(`/`)===i}function b(e){for(let t of u){let i=n.default.join(e,t);if(r.default.existsSync(i))return i}}function x(e){let t;try{t=r.default.statSync(e)}catch{return[]}if(t.isFile())return[e];if(!t.isDirectory())return[];let i=[];for(let t of r.default.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let r=n.default.join(e,t.name);if((t.isFile()||t.isSymbolicLink())&&d.has(n.default.extname(t.name))){i.push(r);continue}if(!t.isDirectory()&&!t.isSymbolicLink())continue;let a=b(r);a&&i.push(a)}return i}function S(e,t,i){if(!h(t)||!p(t?.pi))return;let a=t.pi.extensions;if(!Array.isArray(a)||!a.every(e=>typeof e==`string`))throw Error(`${i} package.json pi.extensions must be an array of strings.`);let o=[];for(let t of a.filter(e=>!g(e))){let i=l.test(t)?r.default.globSync(t,{cwd:e}).sort():[t];for(let t of i)for(let r of x(n.default.resolve(e,t)))o.includes(r)||o.push(r)}let s=a.filter(e=>e.startsWith(`!`)).map(e=>e.slice(1)),c=a.filter(e=>e.startsWith(`+`)).map(e=>e.slice(1)),u=a.filter(e=>e.startsWith(`-`)).map(e=>e.slice(1)),d=o.filter(t=>!s.some(n=>v(t,n,e)));for(let t of o)!d.includes(t)&&c.some(n=>y(t,n,e))&&d.push(t);let f=d.filter(t=>!u.some(n=>y(t,n,e)));return f.length>0?f:void 0}function C(e){return(0,t.fileURLToPath)({}.resolve(e))}function w(e){try{return C(e)}catch{return}}function T(e){let t=e.split(`/`),n=e.startsWith(`@`)?2:1,r=t.slice(0,n).join(`/`),i=t.slice(n).join(`/`);return{name:r,subpath:i?`./${i}`:`.`}}function E(e){if(typeof e==`string`)return e;if(Array.isArray(e)){for(let t of e){let e=E(t);if(e)return e}return}if(typeof e!=`object`||!e)return;let t=e;for(let e of f)if(e in t){let n=E(t[e]);if(n)return n}}function D(e,t){let i=n.default.resolve(t);for(;;){let t=n.default.join(i,o,e);if(r.default.existsSync(n.default.join(t,a)))return t;let s=n.default.dirname(i);if(s===i)return;i=s}}function O(e,t){let i=n.default.join(n.default.resolve(t),s,e);return r.default.existsSync(n.default.join(i,a))?i:void 0}function k(e,t){return D(e,t)??O(e,t)}function A(e){let{name:r,subpath:i}=T(e);if(i!==`.`)return[C(e)];let a=D(r,n.default.dirname((0,t.fileURLToPath)(require(`url`).pathToFileURL(__filename).href))),o=a?m(a):void 0;return(a?S(a,o,r):void 0)||[(a&&h(o)?b(a):void 0)??C(e)]}function j(e){try{return A(e)}catch{return}}function M(e,t){let{name:n,subpath:r}=T(e),i=k(n,t);if(!i)return;if(r===`.`){let e=S(i,m(i),n);if(e!==void 0)return e}let a=N(e,t);return a?[a]:[]}function N(e,t){let{name:i,subpath:o}=T(e),s=k(i,t);if(!s)return;let c=n.default.join(s,a),l=n.default.join(s,o),u;try{u=JSON.parse(r.default.readFileSync(c,`utf8`))}catch{return o===`.`?b(s):r.default.existsSync(l)?l:void 0}let d=u.exports;if(d!=null){let e=E(typeof d==`object`&&!Array.isArray(d)?d[o]:o===`.`?d:void 0);if(e){let t=n.default.join(s,e);if(r.default.existsSync(t))return t}}return o===`.`?b(s):r.default.existsSync(l)?l:void 0}const P=[`module`,`main`];function F(e,t){let i=n.default.resolve(t,e);try{if(!r.default.statSync(i).isDirectory())return;let e=JSON.parse(r.default.readFileSync(n.default.join(i,a),`utf8`));return typeof e.name==`string`&&e.name.trim()?e.name.trim():void 0}catch{return}}function I(e,t){let i=n.default.resolve(t,e),a;try{a=r.default.statSync(i)}catch{return}if(a.isFile())return[i];if(!a.isDirectory())return;let o=S(i,m(i),F(e,t)??i);if(o!==void 0)return o;let s=L(e,t);return s?[s]:x(i)}function L(e,t){let i=n.default.resolve(t,e),o;try{let e=r.default.statSync(i);if(e.isFile())return i;o=e.isDirectory()}catch{return}if(!o)return;let s;try{s=JSON.parse(r.default.readFileSync(n.default.join(i,a),`utf8`))}catch{return}let c=s.exports,l=[E(typeof c==`object`&&c&&!Array.isArray(c)?c[`.`]:c)];for(let e of P)typeof s[e]==`string`&&l.push(s[e]);for(let e of l){if(!e)continue;let t=n.default.join(i,e);if(r.default.existsSync(t))return t}return b(i)}function R(e){let r=require(`url`).pathToFileURL(__filename).href.endsWith(`.ts`)?`ts`:`mjs`,i=n.default.dirname(n.default.dirname(n.default.dirname((0,t.fileURLToPath)(require(`url`).pathToFileURL(__filename).href))));return n.default.join(i,`extensions`,`entries`,`${e}.${r}`)}function z(){return n.default.join(n.default.dirname(C(`@earendil-works/pi-coding-agent`)),`cli.js`)}exports.consumerPackageEntries=M,exports.consumerPackageEntry=N,exports.localEntries=I,exports.localEntry=L,exports.localPackageName=F,exports.optionalPackageEntries=j,exports.optionalPackageEntry=w,exports.ownEntry=R,exports.packageEntries=A,exports.packageEntry=C,exports.piCliPath=z,exports.splitPackageSpecifier=T;
|
|
2
2
|
//# sourceMappingURL=moduleResolution.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moduleResolution.cjs","names":["fs","path"],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"moduleResolution.cjs","names":["path","fs"],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm', NODE_MODULES);\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Finds a package provisioned by Pi without mutating the consumer's package manifest. */\nfunction findManagedPackage(name: string, consumerRoot: string): string | undefined {\n const candidate = path.join(path.resolve(consumerRoot), PI_MANAGED_NPM_DIRECTORY, name);\n return fs.existsSync(path.join(candidate, PACKAGE_MANIFEST)) ? candidate : undefined;\n}\n\nfunction findConsumerPackage(name: string, consumerRoot: string): string | undefined {\n return findInstalledPackage(name, consumerRoot) ?? findManagedPackage(name, consumerRoot);\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moduleResolution.d.cts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"moduleResolution.d.cts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;AAyJA;;;;;iBAAgB,YAAA,CAAa,IAAA;;iBAKb,oBAAA,CAAqB,IAAA;;;AAcrC;;;;iBAAgB,qBAAA,CAAsB,SAAA;EAAsB,IAAA;EAAc,OAAA;AAAA;;iBA0D1D,cAAA,CAAe,SAAA;;iBAaf,sBAAA,CAAuB,SAAA;;;AAAvC;;;;;AAgBA;iBAAgB,sBAAA,CAAuB,SAAA,UAAmB,YAAA;;iBAa1C,oBAAA,CAAqB,SAAA,UAAmB,YAAA;;AAAxD;;;;;AA6CA;;iBAAgB,gBAAA,CAAiB,SAAA,UAAmB,aAAA;;;AAsBpD;;;;;AAuBA;;iBAvBgB,YAAA,CAAa,SAAA,UAAmB,aAAA;;iBAuBhC,UAAA,CAAW,SAAA,UAAmB,aAAA;AA4C9C;;;;;AAQA;;AARA,iBAAgB,QAAA,CAAS,IAAA;;iBAQT,SAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moduleResolution.d.mts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"moduleResolution.d.mts","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"mappings":";;AAyJA;;;;;iBAAgB,YAAA,CAAa,IAAA;;iBAKb,oBAAA,CAAqB,IAAA;;;AAcrC;;;;iBAAgB,qBAAA,CAAsB,SAAA;EAAsB,IAAA;EAAc,OAAA;AAAA;;iBA0D1D,cAAA,CAAe,SAAA;;iBAaf,sBAAA,CAAuB,SAAA;;;AAAvC;;;;;AAgBA;iBAAgB,sBAAA,CAAuB,SAAA,UAAmB,YAAA;;iBAa1C,oBAAA,CAAqB,SAAA,UAAmB,YAAA;;AAAxD;;;;;AA6CA;;iBAAgB,gBAAA,CAAiB,SAAA,UAAmB,aAAA;;;AAsBpD;;;;;AAuBA;;iBAvBgB,YAAA,CAAa,SAAA,UAAmB,aAAA;;iBAuBhC,UAAA,CAAW,SAAA,UAAmB,aAAA;AA4C9C;;;;;AAQA;;AARA,iBAAgB,QAAA,CAAS,IAAA;;iBAQT,SAAA,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{fileURLToPath as e}from"node:url";import t from"node:path";import n from"node:fs";import{minimatch as r}from"minimatch";const i=`package.json`,a=[`!`,`+`,`-`],
|
|
1
|
+
import{fileURLToPath as e}from"node:url";import t from"node:path";import n from"node:fs";import{minimatch as r}from"minimatch";const i=`package.json`,a=`node_modules`,o=t.join(`.pi`,`npm`,a),s=[`!`,`+`,`-`],c=/[*?[\]{}()]/,l=[`index.ts`,`index.js`,`index.mts`,`index.mjs`,`index.cts`,`index.cjs`],u=new Set([`.ts`,`.js`,`.mts`,`.mjs`,`.cts`,`.cjs`]),d=[`import`,`module`,`node`,`default`];function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function p(e){try{let r=JSON.parse(n.readFileSync(t.join(e,i),`utf8`));return f(r)?r:void 0}catch{return}}function m(e){return!!(e&&f(e.pi)&&Object.hasOwn(e.pi,`extensions`))}function h(e){return s.some(t=>e.startsWith(t))}function g(e,n){return t.relative(e,n).split(t.sep).join(`/`)}function _(e,n,i){let a=n.replaceAll(`\\`,`/`).replace(/^\.\//,``);return r(g(i,e),a)||r(t.basename(e),a)||r(e.split(t.sep).join(`/`),a)}function v(e,n,r){let i=n.replaceAll(`\\`,`/`).replace(/^\.\//,``);return g(r,e)===i||e.split(t.sep).join(`/`)===i}function y(e){for(let r of l){let i=t.join(e,r);if(n.existsSync(i))return i}}function b(e){let r;try{r=n.statSync(e)}catch{return[]}if(r.isFile())return[e];if(!r.isDirectory())return[];let i=[];for(let r of n.readdirSync(e,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let n=t.join(e,r.name);if((r.isFile()||r.isSymbolicLink())&&u.has(t.extname(r.name))){i.push(n);continue}if(!r.isDirectory()&&!r.isSymbolicLink())continue;let a=y(n);a&&i.push(a)}return i}function x(e,r,i){if(!m(r)||!f(r?.pi))return;let a=r.pi.extensions;if(!Array.isArray(a)||!a.every(e=>typeof e==`string`))throw Error(`${i} package.json pi.extensions must be an array of strings.`);let o=[];for(let r of a.filter(e=>!h(e))){let i=c.test(r)?n.globSync(r,{cwd:e}).sort():[r];for(let n of i)for(let r of b(t.resolve(e,n)))o.includes(r)||o.push(r)}let s=a.filter(e=>e.startsWith(`!`)).map(e=>e.slice(1)),l=a.filter(e=>e.startsWith(`+`)).map(e=>e.slice(1)),u=a.filter(e=>e.startsWith(`-`)).map(e=>e.slice(1)),d=o.filter(t=>!s.some(n=>_(t,n,e)));for(let t of o)!d.includes(t)&&l.some(n=>v(t,n,e))&&d.push(t);let p=d.filter(t=>!u.some(n=>v(t,n,e)));return p.length>0?p:void 0}function S(t){return e(import.meta.resolve(t))}function C(e){try{return S(e)}catch{return}}function w(e){let t=e.split(`/`),n=e.startsWith(`@`)?2:1,r=t.slice(0,n).join(`/`),i=t.slice(n).join(`/`);return{name:r,subpath:i?`./${i}`:`.`}}function T(e){if(typeof e==`string`)return e;if(Array.isArray(e)){for(let t of e){let e=T(t);if(e)return e}return}if(typeof e!=`object`||!e)return;let t=e;for(let e of d)if(e in t){let n=T(t[e]);if(n)return n}}function E(e,r){let o=t.resolve(r);for(;;){let r=t.join(o,a,e);if(n.existsSync(t.join(r,i)))return r;let s=t.dirname(o);if(s===o)return;o=s}}function D(e,r){let a=t.join(t.resolve(r),o,e);return n.existsSync(t.join(a,i))?a:void 0}function O(e,t){return E(e,t)??D(e,t)}function k(n){let{name:r,subpath:i}=w(n);if(i!==`.`)return[S(n)];let a=E(r,t.dirname(e(import.meta.url))),o=a?p(a):void 0;return(a?x(a,o,r):void 0)||[(a&&m(o)?y(a):void 0)??S(n)]}function A(e){try{return k(e)}catch{return}}function j(e,t){let{name:n,subpath:r}=w(e),i=O(n,t);if(!i)return;if(r===`.`){let e=x(i,p(i),n);if(e!==void 0)return e}let a=M(e,t);return a?[a]:[]}function M(e,r){let{name:a,subpath:o}=w(e),s=O(a,r);if(!s)return;let c=t.join(s,i),l=t.join(s,o),u;try{u=JSON.parse(n.readFileSync(c,`utf8`))}catch{return o===`.`?y(s):n.existsSync(l)?l:void 0}let d=u.exports;if(d!=null){let e=T(typeof d==`object`&&!Array.isArray(d)?d[o]:o===`.`?d:void 0);if(e){let r=t.join(s,e);if(n.existsSync(r))return r}}return o===`.`?y(s):n.existsSync(l)?l:void 0}const N=[`module`,`main`];function P(e,r){let a=t.resolve(r,e);try{if(!n.statSync(a).isDirectory())return;let e=JSON.parse(n.readFileSync(t.join(a,i),`utf8`));return typeof e.name==`string`&&e.name.trim()?e.name.trim():void 0}catch{return}}function F(e,r){let i=t.resolve(r,e),a;try{a=n.statSync(i)}catch{return}if(a.isFile())return[i];if(!a.isDirectory())return;let o=x(i,p(i),P(e,r)??i);if(o!==void 0)return o;let s=I(e,r);return s?[s]:b(i)}function I(e,r){let a=t.resolve(r,e),o;try{let e=n.statSync(a);if(e.isFile())return a;o=e.isDirectory()}catch{return}if(!o)return;let s;try{s=JSON.parse(n.readFileSync(t.join(a,i),`utf8`))}catch{return}let c=s.exports,l=[T(typeof c==`object`&&c&&!Array.isArray(c)?c[`.`]:c)];for(let e of N)typeof s[e]==`string`&&l.push(s[e]);for(let e of l){if(!e)continue;let r=t.join(a,e);if(n.existsSync(r))return r}return y(a)}function L(n){let r=import.meta.url.endsWith(`.ts`)?`ts`:`mjs`,i=t.dirname(t.dirname(t.dirname(e(import.meta.url))));return t.join(i,`extensions`,`entries`,`${n}.${r}`)}function R(){return t.join(t.dirname(S(`@earendil-works/pi-coding-agent`)),`cli.js`)}export{j as consumerPackageEntries,M as consumerPackageEntry,F as localEntries,I as localEntry,P as localPackageName,A as optionalPackageEntries,C as optionalPackageEntry,L as ownEntry,k as packageEntries,S as packageEntry,R as piCliPath,w as splitPackageSpecifier};
|
|
2
2
|
//# sourceMappingURL=moduleResolution.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moduleResolution.mjs","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findInstalledPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"moduleResolution.mjs","names":[],"sources":["../../../src/adapters/modules/moduleResolution.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { minimatch } from 'minimatch';\n\nconst PACKAGE_MANIFEST = 'package.json';\nconst NODE_MODULES = 'node_modules';\nconst PI_MANAGED_NPM_DIRECTORY = path.join('.pi', 'npm', NODE_MODULES);\nconst CURRENT_DIRECTORY_PREFIX = './';\nconst MANIFEST_PATTERN_PREFIXES = ['!', '+', '-'] as const;\nconst GLOB_CHARACTERS = /[*?[\\]{}()]/;\nconst EXTENSION_INDEX_NAMES = ['index.ts', 'index.js', 'index.mts', 'index.mjs', 'index.cts', 'index.cjs'] as const;\nconst EXTENSION_FILE_SUFFIXES = new Set(['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']);\n/** Import-side conditions, in the order Node prefers them for an ESM consumer. */\nconst IMPORT_CONDITIONS = ['import', 'module', 'node', 'default'] as const;\n\ninterface PackageManifest {\n name?: unknown;\n exports?: unknown;\n module?: unknown;\n main?: unknown;\n pi?: unknown;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction readPackageManifest(packageRoot: string): PackageManifest | undefined {\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(path.join(packageRoot, PACKAGE_MANIFEST), 'utf8'));\n return isRecord(parsed) ? parsed : undefined;\n } catch {\n // An unreadable manifest is equivalent to an absent package declaration;\n // the normal export resolver remains available as the compatibility path.\n return undefined;\n }\n}\n\nfunction manifestDeclaresExtensions(manifest: PackageManifest | undefined): boolean {\n return Boolean(manifest && isRecord(manifest.pi) && Object.hasOwn(manifest.pi, 'extensions'));\n}\n\nfunction isManifestPattern(entry: string): boolean {\n return MANIFEST_PATTERN_PREFIXES.some((prefix) => entry.startsWith(prefix));\n}\n\nfunction normalizedRelativePath(packageRoot: string, target: string): string {\n return path.relative(packageRoot, target).split(path.sep).join('/');\n}\n\nfunction matchesManifestPattern(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n const relative = normalizedRelativePath(packageRoot, target);\n return (\n minimatch(relative, normalizedPattern) ||\n minimatch(path.basename(target), normalizedPattern) ||\n minimatch(target.split(path.sep).join('/'), normalizedPattern)\n );\n}\n\nfunction matchesExactManifestPath(target: string, pattern: string, packageRoot: string): boolean {\n const normalizedPattern = pattern.replaceAll('\\\\', '/').replace(/^\\.\\//, '');\n return (\n normalizedRelativePath(packageRoot, target) === normalizedPattern ||\n target.split(path.sep).join('/') === normalizedPattern\n );\n}\n\nfunction extensionIndexEntry(directory: string): string | undefined {\n for (const indexName of EXTENSION_INDEX_NAMES) {\n const candidate = path.join(directory, indexName);\n if (fs.existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction extensionFilesAt(target: string): string[] {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return [];\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return [];\n\n const files: string[] = [];\n for (const entry of fs\n .readdirSync(target, { withFileTypes: true })\n .sort((left, right) => left.name.localeCompare(right.name))) {\n const entryPath = path.join(target, entry.name);\n if ((entry.isFile() || entry.isSymbolicLink()) && EXTENSION_FILE_SUFFIXES.has(path.extname(entry.name))) {\n files.push(entryPath);\n continue;\n }\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;\n const indexEntry = extensionIndexEntry(entryPath);\n if (indexEntry) files.push(indexEntry);\n }\n return files;\n}\n\n/** Resolves the standard package.json pi.extensions declaration exactly as a layer contribution. */\nfunction manifestExtensionEntries(\n packageRoot: string,\n manifest: PackageManifest | undefined,\n packageName: string,\n): string[] | undefined {\n if (!manifestDeclaresExtensions(manifest) || !isRecord(manifest?.pi)) return undefined;\n const configured = manifest.pi.extensions;\n if (!Array.isArray(configured) || !configured.every((entry) => typeof entry === 'string')) {\n throw new Error(`${packageName} package.json pi.extensions must be an array of strings.`);\n }\n\n const allPaths: string[] = [];\n for (const configuredEntry of configured.filter((entry) => !isManifestPattern(entry))) {\n const candidates = GLOB_CHARACTERS.test(configuredEntry)\n ? fs.globSync(configuredEntry, { cwd: packageRoot }).sort()\n : [configuredEntry];\n for (const candidate of candidates) {\n for (const target of extensionFilesAt(path.resolve(packageRoot, candidate))) {\n if (!allPaths.includes(target)) allPaths.push(target);\n }\n }\n }\n\n const excluded = configured.filter((entry) => entry.startsWith('!')).map((entry) => entry.slice(1));\n const forceIncluded = configured.filter((entry) => entry.startsWith('+')).map((entry) => entry.slice(1));\n const forceExcluded = configured.filter((entry) => entry.startsWith('-')).map((entry) => entry.slice(1));\n const selected = allPaths.filter(\n (target) => !excluded.some((pattern) => matchesManifestPattern(target, pattern, packageRoot)),\n );\n for (const target of allPaths) {\n if (\n !selected.includes(target) &&\n forceIncluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot))\n ) {\n selected.push(target);\n }\n }\n const filtered = selected.filter(\n (target) => !forceExcluded.some((pattern) => matchesExactManifestPath(target, pattern, packageRoot)),\n );\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Resolves the on-disk entry point of an installed package.\n *\n * Pi loads extensions by absolute path, so anything contributed as an\n * extension has to be resolved to a file before it can be passed along.\n */\nexport function packageEntry(name: string): string {\n return fileURLToPath(import.meta.resolve(name));\n}\n\n/** Same as packageEntry, but returns undefined when the package is absent. */\nexport function optionalPackageEntry(name: string): string | undefined {\n try {\n return packageEntry(name);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Splits `@scope/name/sub/path` into the package name and its export subpath.\n *\n * A scoped name owns two segments, an unscoped name one. Everything after that\n * is the subpath the package's own `exports` map has to answer for.\n */\nexport function splitPackageSpecifier(specifier: string): { name: string; subpath: string } {\n const segments = specifier.split('/');\n const nameSegments = specifier.startsWith('@') ? 2 : 1;\n const name = segments.slice(0, nameSegments).join('/');\n const rest = segments.slice(nameSegments).join('/');\n return { name, subpath: rest ? `${CURRENT_DIRECTORY_PREFIX}${rest}` : '.' };\n}\n\n/** Picks the import-side target out of one `exports` entry. */\nfunction selectImportTarget(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n for (const candidate of value) {\n const target = selectImportTarget(candidate);\n if (target) return target;\n }\n return undefined;\n }\n if (typeof value !== 'object' || value === null) return undefined;\n const conditions = value as Record<string, unknown>;\n for (const condition of IMPORT_CONDITIONS) {\n if (condition in conditions) {\n const target = selectImportTarget(conditions[condition]);\n if (target) return target;\n }\n }\n return undefined;\n}\n\n/**\n * Finds an installed package directory by walking the consumer's module chain.\n *\n * Node's own lookup order, so a workspace link in the repository root is found\n * exactly where the repository installed it, and nothing outside that chain can\n * answer for a specifier the repository declared.\n */\nfunction findInstalledPackage(name: string, consumerRoot: string): string | undefined {\n let directory = path.resolve(consumerRoot);\n while (true) {\n const candidate = path.join(directory, NODE_MODULES, name);\n if (fs.existsSync(path.join(candidate, PACKAGE_MANIFEST))) return candidate;\n const parent = path.dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n}\n\n/** Finds a package provisioned by Pi without mutating the consumer's package manifest. */\nfunction findManagedPackage(name: string, consumerRoot: string): string | undefined {\n const candidate = path.join(path.resolve(consumerRoot), PI_MANAGED_NPM_DIRECTORY, name);\n return fs.existsSync(path.join(candidate, PACKAGE_MANIFEST)) ? candidate : undefined;\n}\n\nfunction findConsumerPackage(name: string, consumerRoot: string): string | undefined {\n return findInstalledPackage(name, consumerRoot) ?? findManagedPackage(name, consumerRoot);\n}\n\n/** Resolves every extension declared by a bare package's standard Pi manifest. */\nexport function packageEntries(specifier: string): string[] {\n const { name, subpath } = splitPackageSpecifier(specifier);\n if (subpath !== '.') return [packageEntry(specifier)];\n\n const packageRoot = findInstalledPackage(name, path.dirname(fileURLToPath(import.meta.url)));\n const manifest = packageRoot ? readPackageManifest(packageRoot) : undefined;\n const manifestEntries = packageRoot ? manifestExtensionEntries(packageRoot, manifest, name) : undefined;\n if (manifestEntries) return manifestEntries;\n const indexEntry = packageRoot && manifestDeclaresExtensions(manifest) ? extensionIndexEntry(packageRoot) : undefined;\n return [indexEntry ?? packageEntry(specifier)];\n}\n\n/** Same as packageEntries, but returns undefined when the package is absent. */\nexport function optionalPackageEntries(specifier: string): string[] | undefined {\n try {\n return packageEntries(specifier);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves manifest entries from the consumer repository's dependency tree.\n *\n * The meta-package cannot resolve what the repository declares: under an\n * isolated node_modules layout Doom Pi only sees its own dependencies. Walking\n * the consumer's module chain lets its package manifest answer first without\n * accidentally falling through to DoomPi's dependency tree.\n */\nexport function consumerPackageEntries(specifier: string, consumerRoot: string): string[] | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n if (subpath === '.') {\n const manifestEntries = manifestExtensionEntries(packageRoot, readPackageManifest(packageRoot), name);\n if (manifestEntries !== undefined) return manifestEntries;\n }\n const entry = consumerPackageEntry(specifier, consumerRoot);\n return entry ? [entry] : [];\n}\n\n/** Resolves one explicit package export or direct package-relative path from the consumer. */\nexport function consumerPackageEntry(specifier: string, consumerRoot: string): string | undefined {\n const { name, subpath } = splitPackageSpecifier(specifier);\n const packageRoot = findConsumerPackage(name, consumerRoot);\n if (!packageRoot) return undefined;\n\n const manifestPath = path.join(packageRoot, PACKAGE_MANIFEST);\n // A relative subpath that the package does not export is still loadable by\n // path, which is how layers point at a file inside a package (`.../index.ts`).\n const directTarget = path.join(packageRoot, subpath);\n let manifest: { exports?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as { exports?: unknown };\n } catch {\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n }\n\n const exports = manifest.exports;\n if (exports !== undefined && exports !== null) {\n const entry =\n typeof exports === 'object' && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)[subpath]\n : subpath === '.'\n ? exports\n : undefined;\n const target = selectImportTarget(entry);\n if (target) {\n const resolved = path.join(packageRoot, target);\n if (fs.existsSync(resolved)) return resolved;\n }\n }\n\n return subpath === '.' ? extensionIndexEntry(packageRoot) : fs.existsSync(directTarget) ? directTarget : undefined;\n}\n\n/** Manifest fields consulted when a local package declares no `exports`. */\nconst MAIN_FIELDS = ['module', 'main'] as const;\n\n/**\n * Returns the canonical name of a path-style package directory.\n *\n * A direct file is intentionally anonymous: treating the repository manifest\n * above it as the file's identity would collapse every local extension in that\n * repository. Only a directory with its own named manifest represents a package\n * that can replace another installed version by logical identity.\n */\nexport function localPackageName(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n try {\n if (!fs.statSync(target).isDirectory()) return undefined;\n const manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as {\n name?: unknown;\n };\n return typeof manifest.name === 'string' && manifest.name.trim() ? manifest.name.trim() : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolves Pi extension entries from a local file, extension directory, or package.\n *\n * A file is taken as the extension entry as written. A package directory uses\n * its native `pi.extensions` declaration or legacy root entry. A plain directory\n * follows Pi's extension discovery convention for scripts and child `index`\n * modules. This lets unpublished extensions live in the repository, or beside\n * the global config in `~/.pi/.doom`, and still load in deterministic order.\n */\nexport function localEntries(specifier: string, baseDirectory: string): string[] | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let stats: fs.Stats;\n try {\n stats = fs.statSync(target);\n } catch {\n return undefined;\n }\n if (stats.isFile()) return [target];\n if (!stats.isDirectory()) return undefined;\n\n const manifest = readPackageManifest(target);\n const manifestEntries = manifestExtensionEntries(\n target,\n manifest,\n localPackageName(specifier, baseDirectory) ?? target,\n );\n if (manifestEntries !== undefined) return manifestEntries;\n const entry = localEntry(specifier, baseDirectory);\n return entry ? [entry] : extensionFilesAt(target);\n}\n\n/** Resolves the legacy single entry from a local package's exports, module, or main field. */\nexport function localEntry(specifier: string, baseDirectory: string): string | undefined {\n const target = path.resolve(baseDirectory, specifier);\n let isDirectory: boolean;\n try {\n const stats = fs.statSync(target);\n if (stats.isFile()) return target;\n isDirectory = stats.isDirectory();\n } catch {\n return undefined;\n }\n if (!isDirectory) return undefined;\n\n let manifest: { exports?: unknown; module?: unknown; main?: unknown };\n try {\n manifest = JSON.parse(fs.readFileSync(path.join(target, PACKAGE_MANIFEST), 'utf8')) as typeof manifest;\n } catch {\n return undefined;\n }\n\n const exports = manifest.exports;\n const rootExport =\n typeof exports === 'object' && exports !== null && !Array.isArray(exports)\n ? (exports as Record<string, unknown>)['.']\n : exports;\n const candidates = [selectImportTarget(rootExport)];\n for (const field of MAIN_FIELDS) {\n if (typeof manifest[field] === 'string') candidates.push(manifest[field]);\n }\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const resolved = path.join(target, candidate);\n if (fs.existsSync(resolved)) return resolved;\n }\n return extensionIndexEntry(target);\n}\n\n/**\n * Resolves one of this package's own extensions in src/extensions/entries.\n *\n * The file extension differs between running from source (.ts, how the shell\n * launchers invoke this) and running the build output (.mjs), so it is derived\n * from this module's own URL rather than assumed.\n */\nexport function ownEntry(name: string): string {\n const extension = import.meta.url.endsWith('.ts') ? 'ts' : 'mjs';\n // This file sits in src/adapters/modules, so the source root is two directories up.\n const sourceRoot = path.dirname(path.dirname(path.dirname(fileURLToPath(import.meta.url))));\n return path.join(sourceRoot, 'extensions', 'entries', `${name}.${extension}`);\n}\n\n/** Path to Pi's own CLI, which the launch command spawns. */\nexport function piCliPath(): string {\n return path.join(path.dirname(packageEntry('@earendil-works/pi-coding-agent')), 'cli.js');\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../adapters/repository/repository.cjs`),n=require(`./cli/options.cjs`);require(`../services/config/index.cjs`),require(`../utils/index.cjs`);const r=require(`../services/extensionAssembler.cjs`),i=require(`../adapters/harnessContext.cjs`),a=require(`../adapters/syncState.cjs`),o=require(`../adapters/projectPiSettings.cjs`),s=require(`../adapters/runtimeBundle.cjs`),c=require(`./syncCommand.cjs`);let
|
|
2
|
-
`)}var
|
|
1
|
+
const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../adapters/repository/repository.cjs`),n=require(`./cli/options.cjs`);require(`../services/config/index.cjs`),require(`../utils/index.cjs`);const r=require(`../services/extensionAssembler.cjs`),i=require(`../adapters/harnessContext.cjs`),a=require(`../adapters/syncState.cjs`),o=require(`../adapters/projectPiSettings.cjs`),s=require(`../adapters/runtimeBundle.cjs`),c=require(`./syncCommand.cjs`),l=require(`../adapters/layerPackageInstaller.cjs`);let u=require(`node:path`);u=e.__toESM(u,1);let d=require(`@agimon-ai/doompi-config/majorModes`),f=require(`@agimon-ai/doompi-config/domains`);function p(e,t,n){if(!a.syncStateRootMatches(e,t.root)||a.computeInputsHash(e,t.selection)!==t.inputsHash)return!1;let i=a.recordResolvedEntries(n,r.createLayerResolvers(e));return JSON.stringify(i)===JSON.stringify(t.resolved)}function m(e){return[`bundle: ${e.bundle}`,`manifest: ${e.manifest}`,`extensions: ${e.extensionCount} -> 1`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,...e.syncedBootstrap?[`bootstrap: ${e.syncedBootstrap}`,`modes: ${String(e.syncedBundleCount??0)} precompiled`]:[],...e.duplicateRegistration?[`warning: ${o.DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`]:[],``,`Doom Pi is built. The next launch will use the dist mode extension.`,``].join(`
|
|
2
|
+
`)}var h=class{name=`build`;telemetry;constructor(e){this.telemetry=e}matches(e){return e[0]===this.name}async execute(e,r=process.env,h=process.cwd(),g=process.stdout){let _=r.DOOMPI_ROOT,v=_?u.default.resolve(_):t.findRepositoryRoot(h),y=await i.buildHarnessContext({...n.parseHarnessArgs(e.slice(1),c.selectionEnvironment(v,r),h,(0,d.loadMajorModesConfig)(v).defaultMajorMode,(0,f.loadDomains)(v).defaultDomains).options,repoRoot:v},this.telemetry);try{await l.ensureLayerPackages({repoRoot:v,config:y.majorModesConfig,layers:y.selectedLayers,environment:r});let e=await s.buildRuntimeBundle(y),t,n=a.readSyncState(v);if(n&&p(v,n,y.majorModesConfig)){let{buildSyncedRuntime:e}=await Promise.resolve().then(()=>require(`../adapters/syncedRuntimeBuilder.cjs`));t=await e(v,r)}return g.write(m({bundle:e.bundle,manifest:e.manifest,extensionCount:e.extensions.length,skillCount:y.resources.skillCount,agentCount:y.resources.agentCount,syncedBootstrap:t?.bootstrap,syncedBundleCount:t?Object.keys(t.bundles).length:void 0,duplicateRegistration:o.projectRegistersDoom(v)})),0}finally{await y.cleanup()}}};exports.BuildCommand=h;
|
|
3
3
|
//# sourceMappingURL=buildCommand.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildCommand.cjs","names":["syncStateRootMatches","computeInputsHash","recordResolvedEntries","createLayerResolvers","DUPLICATE_REGISTRATION_DRIFT","path","findRepositoryRoot","buildHarnessContext","parseHarnessArgs","selectionEnvironment","buildRuntimeBundle","readSyncState","projectRegistersDoom"],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"buildCommand.cjs","names":["syncStateRootMatches","computeInputsHash","recordResolvedEntries","createLayerResolvers","DUPLICATE_REGISTRATION_DRIFT","path","findRepositoryRoot","buildHarnessContext","parseHarnessArgs","selectionEnvironment","ensureLayerPackages","buildRuntimeBundle","readSyncState","projectRegistersDoom"],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages } from '../adapters/layerPackageInstaller.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n await ensureLayerPackages({\n repoRoot,\n config: context.majorModesConfig,\n layers: context.selectedLayers,\n environment,\n });\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"ipBAsCA,SAAS,EAAmB,EAAkB,EAAkB,EAA6C,CAE3G,GADI,CAACA,EAAAA,qBAAqB,EAAU,EAAM,KAAK,EAC3CC,EAAAA,kBAAkB,EAAU,EAAM,UAAU,GAAK,EAAM,WAAY,MAAO,GAC9E,IAAM,EAAWC,EAAAA,sBAAsB,EAAkBC,EAAAA,qBAAqB,EAAS,CAAC,CACxF,OAAO,KAAK,UAAU,EAAS,GAAK,KAAK,UAAU,EAAM,SAAS,CAGpE,SAAgB,EAAkB,EAA6B,CAC7D,MAAO,CACL,eAAe,EAAO,SACtB,eAAe,EAAO,WACtB,eAAe,EAAO,eAAe,OACrC,eAAe,EAAO,aACtB,eAAe,EAAO,aACtB,GAAI,EAAO,gBACP,CAAC,eAAe,EAAO,kBAAmB,eAAe,OAAO,EAAO,mBAAqB,EAAE,CAAC,cAAc,CAC7G,EAAE,CAEN,GAAI,EAAO,sBAAwB,CAAC,eAAeC,EAAAA,6BAA6B,mBAAmB,CAAG,EAAE,CACxG,GACA,sEACA,GACD,CAAC,KAAK;EAAK,CAId,IAAa,EAAb,KAA0B,CACxB,KAAgB,QAChB,UAEA,YAAY,EAA8B,CACxC,KAAK,UAAY,EAGnB,QAAQ,EAAyB,CAC/B,OAAO,EAAK,KAAO,KAAK,KAG1B,MAAM,QACJ,EACA,EAAiC,QAAQ,IACzC,EAAmB,QAAQ,KAAK,CAChC,EAAsB,QAAQ,OACb,CACjB,IAAM,EAAgB,EAAY,YAC5B,EAAW,EAAgBC,EAAAA,QAAK,QAAQ,EAAc,CAAGC,EAAAA,mBAAmB,EAAiB,CAQ7F,EAAU,MAAMC,EAAAA,oBAAoB,CAAE,GAP7BC,EAAAA,iBACb,EAAK,MAAM,EAAE,CACbC,EAAAA,qBAAqB,EAAU,EAAY,CAC3C,GAAA,EAAA,EAAA,sBACqB,EAAS,CAAC,kBAAA,EAAA,EAAA,aACnB,EAAS,CAAC,eAE6B,CAAC,QAAS,WAAU,CAAE,KAAK,UAAU,CAC1F,GAAI,CACF,MAAMC,EAAAA,oBAAoB,CACxB,WACA,OAAQ,EAAQ,iBAChB,OAAQ,EAAQ,eAChB,cACD,CAAC,CACF,IAAM,EAAQ,MAAMC,EAAAA,mBAAmB,EAAQ,CAC3C,EACE,EAAYC,EAAAA,cAAc,EAAS,CACzC,GAAI,GAAa,EAAmB,EAAU,EAAW,EAAQ,iBAAiB,CAAE,CAClF,GAAM,CAAE,sBAAuB,MAAA,QAAA,SAAA,CAAA,SAAA,QAAM,uCAAA,CAAA,CACrC,EAAS,MAAM,EAAmB,EAAU,EAAY,CAc1D,OAZA,EAAO,MACL,EAAkB,CAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,eAAgB,EAAM,WAAW,OACjC,WAAY,EAAQ,UAAU,WAC9B,WAAY,EAAQ,UAAU,WAC9B,gBAAiB,GAAQ,UACzB,kBAAmB,EAAS,OAAO,KAAK,EAAO,QAAQ,CAAC,OAAS,IAAA,GACjE,sBAAuBC,EAAAA,qBAAqB,EAAS,CACtD,CAAC,CACH,CACM,SACC,CACR,MAAM,EAAQ,SAAS"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{findRepositoryRoot as e}from"../adapters/repository/repository.mjs";import{parseHarnessArgs as t}from"./cli/options.mjs";import{loadDomains as n,loadMajorModesConfig as r}from"../services/config/index.mjs";import"../utils/index.mjs";import{createLayerResolvers as i}from"../services/extensionAssembler.mjs";import{buildHarnessContext as a}from"../adapters/harnessContext.mjs";import{computeInputsHash as o,readSyncState as s,recordResolvedEntries as c,syncStateRootMatches as l}from"../adapters/syncState.mjs";import{DUPLICATE_REGISTRATION_DRIFT as u,projectRegistersDoom as d}from"../adapters/projectPiSettings.mjs";import{buildRuntimeBundle as f}from"../adapters/runtimeBundle.mjs";import{selectionEnvironment as p}from"./syncCommand.mjs";import m from"node:path";function
|
|
2
|
-
`)}var
|
|
1
|
+
import{findRepositoryRoot as e}from"../adapters/repository/repository.mjs";import{parseHarnessArgs as t}from"./cli/options.mjs";import{loadDomains as n,loadMajorModesConfig as r}from"../services/config/index.mjs";import"../utils/index.mjs";import{createLayerResolvers as i}from"../services/extensionAssembler.mjs";import{buildHarnessContext as a}from"../adapters/harnessContext.mjs";import{computeInputsHash as o,readSyncState as s,recordResolvedEntries as c,syncStateRootMatches as l}from"../adapters/syncState.mjs";import{DUPLICATE_REGISTRATION_DRIFT as u,projectRegistersDoom as d}from"../adapters/projectPiSettings.mjs";import{buildRuntimeBundle as f}from"../adapters/runtimeBundle.mjs";import{selectionEnvironment as p}from"./syncCommand.mjs";import{ensureLayerPackages as m}from"../adapters/layerPackageInstaller.mjs";import h from"node:path";function g(e,t,n){if(!l(e,t.root)||o(e,t.selection)!==t.inputsHash)return!1;let r=c(n,i(e));return JSON.stringify(r)===JSON.stringify(t.resolved)}function _(e){return[`bundle: ${e.bundle}`,`manifest: ${e.manifest}`,`extensions: ${e.extensionCount} -> 1`,`skills: ${e.skillCount}`,`agents: ${e.agentCount}`,...e.syncedBootstrap?[`bootstrap: ${e.syncedBootstrap}`,`modes: ${String(e.syncedBundleCount??0)} precompiled`]:[],...e.duplicateRegistration?[`warning: ${u}; run doompi sync`]:[],``,`Doom Pi is built. The next launch will use the dist mode extension.`,``].join(`
|
|
2
|
+
`)}var v=class{name=`build`;telemetry;constructor(e){this.telemetry=e}matches(e){return e[0]===this.name}async execute(i,o=process.env,c=process.cwd(),l=process.stdout){let u=o.DOOMPI_ROOT,v=u?h.resolve(u):e(c),y=await a({...t(i.slice(1),p(v,o),c,r(v).defaultMajorMode,n(v).defaultDomains).options,repoRoot:v},this.telemetry);try{await m({repoRoot:v,config:y.majorModesConfig,layers:y.selectedLayers,environment:o});let e=await f(y),t,n=s(v);if(n&&g(v,n,y.majorModesConfig)){let{buildSyncedRuntime:e}=await import(`../adapters/syncedRuntimeBuilder.mjs`);t=await e(v,o)}return l.write(_({bundle:e.bundle,manifest:e.manifest,extensionCount:e.extensions.length,skillCount:y.resources.skillCount,agentCount:y.resources.agentCount,syncedBootstrap:t?.bootstrap,syncedBundleCount:t?Object.keys(t.bundles).length:void 0,duplicateRegistration:d(v)})),0}finally{await y.cleanup()}}};export{v as BuildCommand};
|
|
3
3
|
//# sourceMappingURL=buildCommand.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildCommand.mjs","names":[],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"buildCommand.mjs","names":[],"sources":["../../src/commands/buildCommand.ts"],"sourcesContent":["import path from 'node:path';\nimport type { MajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport { buildHarnessContext } from '../adapters/harnessContext.ts';\nimport { ensureLayerPackages } from '../adapters/layerPackageInstaller.ts';\nimport { DUPLICATE_REGISTRATION_DRIFT, projectRegistersDoom } from '../adapters/projectPiSettings.ts';\nimport { buildRuntimeBundle } from '../adapters/runtimeBundle.ts';\nimport type { SyncedRuntimeBuild } from '../adapters/syncedRuntimeBuilder.ts';\nimport {\n computeInputsHash,\n readSyncState,\n recordResolvedEntries,\n syncStateRootMatches,\n type SyncState,\n} from '../adapters/syncState.ts';\nimport type { HarnessTelemetry } from '../adapters/telemetry/logSinkTelemetry.ts';\nimport { loadDomains, loadMajorModesConfig } from '../services/config/index.ts';\nimport { createLayerResolvers } from '../services/extensionAssembler.ts';\nimport { findRepositoryRoot } from '../utils/index.ts';\nimport { parseHarnessArgs } from './cli/options.ts';\nimport { selectionEnvironment } from './syncCommand.ts';\n\nconst BUILD_COMMAND = 'build';\nconst HARNESS_ROOT_ENV = 'DOOMPI_ROOT';\n\ntype BuildOutput = Pick<NodeJS.WritableStream, 'write'>;\n\nexport interface BuildResult {\n bundle: string;\n manifest: string;\n extensionCount: number;\n skillCount: number;\n agentCount: number;\n syncedBootstrap?: string;\n syncedBundleCount?: number;\n /** Set when the repository registers DoomPi the user scope already provides. */\n duplicateRegistration?: boolean;\n}\n\nfunction syncStateIsCurrent(repoRoot: string, state: SyncState, majorModesConfig: MajorModesConfig): boolean {\n if (!syncStateRootMatches(repoRoot, state.root)) return false;\n if (computeInputsHash(repoRoot, state.selection) !== state.inputsHash) return false;\n const resolved = recordResolvedEntries(majorModesConfig, createLayerResolvers(repoRoot));\n return JSON.stringify(resolved) === JSON.stringify(state.resolved);\n}\n\nexport function formatBuildResult(result: BuildResult): string {\n return [\n `bundle: ${result.bundle}`,\n `manifest: ${result.manifest}`,\n `extensions: ${result.extensionCount} -> 1`,\n `skills: ${result.skillCount}`,\n `agents: ${result.agentCount}`,\n ...(result.syncedBootstrap\n ? [`bootstrap: ${result.syncedBootstrap}`, `modes: ${String(result.syncedBundleCount ?? 0)} precompiled`]\n : []),\n // Build never writes settings, so it reports what only sync can repair.\n ...(result.duplicateRegistration ? [`warning: ${DUPLICATE_REGISTRATION_DRIFT}; run doompi sync`] : []),\n '',\n 'Doom Pi is built. The next launch will use the dist mode extension.',\n '',\n ].join('\\n');\n}\n\n/** Builds the selected mode extension without launching Pi or changing settings. */\nexport class BuildCommand {\n readonly name = BUILD_COMMAND;\n private readonly telemetry: HarnessTelemetry | undefined;\n\n constructor(telemetry?: HarnessTelemetry) {\n this.telemetry = telemetry;\n }\n\n matches(args: string[]): boolean {\n return args[0] === this.name;\n }\n\n async execute(\n args: string[],\n environment: NodeJS.ProcessEnv = process.env,\n currentDirectory = process.cwd(),\n output: BuildOutput = process.stdout,\n ): Promise<number> {\n const inheritedRoot = environment[HARNESS_ROOT_ENV];\n const repoRoot = inheritedRoot ? path.resolve(inheritedRoot) : findRepositoryRoot(currentDirectory);\n const parsed = parseHarnessArgs(\n args.slice(1),\n selectionEnvironment(repoRoot, environment),\n currentDirectory,\n loadMajorModesConfig(repoRoot).defaultMajorMode,\n loadDomains(repoRoot).defaultDomains,\n );\n const context = await buildHarnessContext({ ...parsed.options, repoRoot }, this.telemetry);\n try {\n await ensureLayerPackages({\n repoRoot,\n config: context.majorModesConfig,\n layers: context.selectedLayers,\n environment,\n });\n const built = await buildRuntimeBundle(context);\n let synced: SyncedRuntimeBuild | undefined;\n const syncState = readSyncState(repoRoot);\n if (syncState && syncStateIsCurrent(repoRoot, syncState, context.majorModesConfig)) {\n const { buildSyncedRuntime } = await import('../adapters/syncedRuntimeBuilder.ts');\n synced = await buildSyncedRuntime(repoRoot, environment);\n }\n output.write(\n formatBuildResult({\n bundle: built.bundle,\n manifest: built.manifest,\n extensionCount: built.extensions.length,\n skillCount: context.resources.skillCount,\n agentCount: context.resources.agentCount,\n syncedBootstrap: synced?.bootstrap,\n syncedBundleCount: synced ? Object.keys(synced.bundles).length : undefined,\n duplicateRegistration: projectRegistersDoom(repoRoot),\n }),\n );\n return 0;\n } finally {\n await context.cleanup();\n }\n }\n}\n"],"mappings":"i1BAsCA,SAAS,EAAmB,EAAkB,EAAkB,EAA6C,CAE3G,GADI,CAAC,EAAqB,EAAU,EAAM,KAAK,EAC3C,EAAkB,EAAU,EAAM,UAAU,GAAK,EAAM,WAAY,MAAO,GAC9E,IAAM,EAAW,EAAsB,EAAkB,EAAqB,EAAS,CAAC,CACxF,OAAO,KAAK,UAAU,EAAS,GAAK,KAAK,UAAU,EAAM,SAAS,CAGpE,SAAgB,EAAkB,EAA6B,CAC7D,MAAO,CACL,eAAe,EAAO,SACtB,eAAe,EAAO,WACtB,eAAe,EAAO,eAAe,OACrC,eAAe,EAAO,aACtB,eAAe,EAAO,aACtB,GAAI,EAAO,gBACP,CAAC,eAAe,EAAO,kBAAmB,eAAe,OAAO,EAAO,mBAAqB,EAAE,CAAC,cAAc,CAC7G,EAAE,CAEN,GAAI,EAAO,sBAAwB,CAAC,eAAe,EAA6B,mBAAmB,CAAG,EAAE,CACxG,GACA,sEACA,GACD,CAAC,KAAK;EAAK,CAId,IAAa,EAAb,KAA0B,CACxB,KAAgB,QAChB,UAEA,YAAY,EAA8B,CACxC,KAAK,UAAY,EAGnB,QAAQ,EAAyB,CAC/B,OAAO,EAAK,KAAO,KAAK,KAG1B,MAAM,QACJ,EACA,EAAiC,QAAQ,IACzC,EAAmB,QAAQ,KAAK,CAChC,EAAsB,QAAQ,OACb,CACjB,IAAM,EAAgB,EAAY,YAC5B,EAAW,EAAgB,EAAK,QAAQ,EAAc,CAAG,EAAmB,EAAiB,CAQ7F,EAAU,MAAM,EAAoB,CAAE,GAP7B,EACb,EAAK,MAAM,EAAE,CACb,EAAqB,EAAU,EAAY,CAC3C,EACA,EAAqB,EAAS,CAAC,iBAC/B,EAAY,EAAS,CAAC,eAE6B,CAAC,QAAS,WAAU,CAAE,KAAK,UAAU,CAC1F,GAAI,CACF,MAAM,EAAoB,CACxB,WACA,OAAQ,EAAQ,iBAChB,OAAQ,EAAQ,eAChB,cACD,CAAC,CACF,IAAM,EAAQ,MAAM,EAAmB,EAAQ,CAC3C,EACE,EAAY,EAAc,EAAS,CACzC,GAAI,GAAa,EAAmB,EAAU,EAAW,EAAQ,iBAAiB,CAAE,CAClF,GAAM,CAAE,sBAAuB,MAAM,OAAO,wCAC5C,EAAS,MAAM,EAAmB,EAAU,EAAY,CAc1D,OAZA,EAAO,MACL,EAAkB,CAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,eAAgB,EAAM,WAAW,OACjC,WAAY,EAAQ,UAAU,WAC9B,WAAY,EAAQ,UAAU,WAC9B,gBAAiB,GAAQ,UACzB,kBAAmB,EAAS,OAAO,KAAK,EAAO,QAAQ,CAAC,OAAS,IAAA,GACjE,sBAAuB,EAAqB,EAAS,CACtD,CAAC,CACH,CACM,SACC,CACR,MAAM,EAAQ,SAAS"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../adapters/modules/moduleResolution.cjs`);require(`../utils/index.cjs`);let t=require(`@agimon-ai/doompi-config/majorModes`);const n=`@agimon-ai/doompi-user-feedback`;function r(e){return e===`@juicesharp/rpiv-ask-user-question`?n:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${n}${e.slice(34)}`:e}const i={ownEntry:e.ownEntry,packageEntry:t=>e.packageEntry(r(t)),optionalPackageEntry:t=>e.optionalPackageEntry(r(t)),packageEntries:t=>e.packageEntries(r(t)),optionalPackageEntries:t=>e.optionalPackageEntries(r(t)),localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName};function a(t){return t?{ownEntry:e.ownEntry,packageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.packageEntry(i)},optionalPackageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.optionalPackageEntry(i)},packageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.packageEntries(i)},optionalPackageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.optionalPackageEntries(i)},localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName}:i}const o=`guardrails`,s=`vibe-lint`,c=`code-intel`,l=`runner`,u=`ask-user`,d=`style-system`,f={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},p={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../adapters/modules/moduleResolution.cjs`);require(`../utils/index.cjs`);let t=require(`@agimon-ai/doompi-config/majorModes`);const n=`@agimon-ai/doompi-user-feedback`;function r(e){return e===`@juicesharp/rpiv-ask-user-question`?n:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${n}${e.slice(34)}`:e}const i={ownEntry:e.ownEntry,packageEntry:t=>e.packageEntry(r(t)),optionalPackageEntry:t=>e.optionalPackageEntry(r(t)),packageEntries:t=>e.packageEntries(r(t)),optionalPackageEntries:t=>e.optionalPackageEntries(r(t)),localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName};function a(t){return t?{ownEntry:e.ownEntry,packageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.packageEntry(i)},optionalPackageEntry:n=>{let i=r(n);return e.consumerPackageEntry(i,t)??e.optionalPackageEntry(i)},packageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.packageEntries(i)},optionalPackageEntries:n=>{let i=r(n);return e.consumerPackageEntries(i,t)??e.optionalPackageEntries(i)},localEntry:e.localEntry,localEntries:e.localEntries,localPackageName:e.localPackageName}:i}const o=`guardrails`,s=`vibe-lint`,c=`code-intel`,l=`runner`,u=`ask-user`,d=`style-system`,f={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},p={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,planDoom:`@agimon-ai/doompi-plan/extensions/doom`,voice:`@agimon-ai/doompi-voice/extensions/doom`,goalDoom:`@agimon-ai/doompi-goal/extensions/doom`},m=new Set([o,s,c]),h={mcp:`@agimon-ai/doompi-mcp/extensions/pi`,workflow:`@agimon-ai/doompi-workflow/extensions/pi`,dispatcherWorkflow:`@agimon-ai/doompi-workflow/extensions/dispatcher`},g=`persona`;function _(e){let t=r(e),n=t.split(`/`);return t.startsWith(`@`)?n.slice(0,2).join(`/`):n[0]??t}function v(e,t,n){return{name:`own:${e}`,path:t,priority:n}}function y(e,t,n,r=0){let i=r===0?``:`:${r}`;return{name:`package:${_(e)}${i}`,path:t,priority:n}}function b(e,t,n=0){let r=n===0?``:`:${n}`;return{name:t?`package:${_(t)}${r}`:`local:${e.replaceAll(`\\`,`/`)}`,path:e,priority:1}}function x(e,t,n){let r=e.localEntries?.(t,n);if(r!==void 0)return r;let i=e.localEntry(t,n);return i?[i]:void 0}function S(e,n,r){let i=e.layers[n];if(!i)throw Error(`Unknown layer: ${n}`);let a=[];for(let e of i.extensions??[]){if(!(0,t.isLocalPackageSpecifier)(e)){a.push(v(e,r.ownEntry(e),1));continue}let o=x(r,e,i.baseDirectory);if(!o?.length)throw Error(`Layer "${n}" extension "${e}" does not resolve under ${i.baseDirectory}. Point it at a Pi extension file or directory.`);a.push(...o.map(e=>b(e)))}for(let e of i.packages??[]){let o=typeof e==`string`?e:e.name,s=typeof e==`string`?!1:e.optional===!0;if((0,t.isLocalPackageSpecifier)(o)){let e=x(r,o,i.baseDirectory);if(e?.length){let t=r.localPackageName?.(o,i.baseDirectory);a.push(...e.map((e,n)=>b(e,t,n)))}else if(!s)throw Error(`Layer "${n}" package "${o}" does not resolve under ${i.baseDirectory}. Point it at an extension file, or a directory whose package.json declares pi.extensions.`);continue}let c;if(s){if(c=r.optionalPackageEntries?.(o),c===void 0){let e=r.optionalPackageEntry(o);c=e?[e]:void 0}}else c=r.packageEntries?.(o)??[r.packageEntry(o)];if(c?.length)a.push(...c.map((e,t)=>y(o,e,1,t)));else if(!s)throw Error(`Layer "${n}" package "${o}" declares no Pi extensions.`)}return a}function C(e){let t=[];for(let n of e){let e=n.path.replaceAll(`\\`,`/`),r=t.findIndex(t=>t.name===n.name||t.path.replaceAll(`\\`,`/`)===e);if(r===-1){t.push(n);continue}let i=t[r];i&&n.priority>i.priority&&(t[r]=n)}return t.map(e=>e.path)}function w(e){let t=e.majorModesConfig,n=e.resolvers??i,r=e=>v(e,n.ownEntry(e),0),a=e=>y(e,n.packageEntry(e),0),m=new Set(e.layers),_=e=>m.has(e)?S(t,e,n):[],b=[];return e.mcpEntry&&b.push(y(h.mcp,e.mcpEntry,2)),b.push(a(p.logSinkTelemetry)),e.personaEntry&&b.push(v(g,e.personaEntry,2)),e.workflowExtension&&b.push(y(h.workflow,e.workflowExtension,2)),b.push(..._(`agiflow`),..._(o),..._(s),..._(c)),e.preset===`ollama`&&b.push(r(f.ollamaProvider)),b.push(r(f.effort)),b.push(a(p.planDoom)),b.push(..._(`task`)),b.push(a(p.loop)),b.push(a(p.autocompact)),b.push(a(p.fileEdit)),b.push(..._(l)),b.push(..._(u),..._(d)),b.push(a(p.voice)),b.push(r(f.domains)),b.push(r(f.skills)),b.push(r(f.majorMode)),b.push(r(f.profile)),b.push(a(p.goalDoom)),b.push(r(f.cacheOptimizer)),e.mute||b.push(r(f.notifications)),e.agents&&b.push(..._(`team`)),b.push(a(p.doomHelp)),b.push(a(p.doomUi)),b.push(a(p.doomConfig)),b.push(r(f.modeCatalog)),e.autoStop&&b.unshift(r(f.autoStop)),C(b)}function T(e){let t=e.resolvers??i,n=e=>y(e,t.packageEntry(e),0),r=new Set(e.layers),a=n=>r.has(n)?S(e.majorModesConfig,n,t):[],m=[];return e.mcpEntry&&m.push(y(h.mcp,e.mcpEntry,2)),m.push(n(p.logSinkTelemetry)),e.personaEntry&&m.push(v(g,e.personaEntry,2)),e.preset===`ollama`&&m.push(v(f.ollamaProvider,t.ownEntry(f.ollamaProvider),0)),m.push(...a(o),...a(s),...a(c),...a(l),...a(u),...a(d)),m.push(n(p.autocompact)),m.push(n(p.doomConfig)),C(m)}function E(e,t){return t?[...e]:e.filter(e=>!m.has(e))}exports.CONTEXT_PACKAGES=h,exports.LAYER_RESOLVERS=i,exports.LEGACY_ASK_USER_PACKAGE=`@juicesharp/rpiv-ask-user-question`,exports.OLLAMA_PRESET=`ollama`,exports.PERSONA_ENTRY=g,exports.USER_FEEDBACK_PACKAGE=n,exports.assembleChildExtensions=T,exports.assembleExtensions=w,exports.canonicalPackageSpecifier=r,exports.createLayerResolvers=a,exports.filterHookDisabledLayers=E;
|
|
2
2
|
//# sourceMappingURL=extensionAssembler.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensionAssembler.cjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName","consumerPackageEntry","consumerPackageEntries"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_PLAN_MODE = 'plan-mode';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n task: '@agimon-ai/doompi-task/extensions/pi',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n extensions.push(...layer(LAYER_PLAN_MODE));\n extensions.push(pkg(PACKAGE_ENTRIES.task));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extensionAssembler.cjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName","consumerPackageEntry","consumerPackageEntries"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_TASK = 'task';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n planDoom: '@agimon-ai/doompi-plan/extensions/doom',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n // Plan is a battery-included minor mode. Its tools stay inactive until the\n // user enters Plan, while its Doom adapter keeps Leader and mode metadata ready.\n extensions.push(pkg(PACKAGE_ENTRIES.planDoom));\n // Task is a major-mode capability: selected modes opt into its persistent graph.\n extensions.push(...layer(LAYER_TASK));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensionAssembler.d.cts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;
|
|
1
|
+
{"version":3,"file":"extensionAssembler.d.cts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;iBAkOgB,uBAAA,CAAwB,OAAA,EAAS,gBAAA;;iBAyCjC,wBAAA,CAAyB,MAAA,YAAkB,KAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensionAssembler.d.mts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;
|
|
1
|
+
{"version":3,"file":"extensionAssembler.d.mts","names":[],"sources":["../../src/services/extensionAssembler.ts"],"mappings":";;;UAkBiB,uBAAA,SAAgC,cAAA;;EAE/C,gBAAA,IAAoB,SAAA,UAAmB,aAAA;AAAA;AAAA,UAGxB,gBAAA;EACf,MAAA;EACA,QAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,YAAA;EACA,iBAAA;EAPe;EASf,MAAA;EACA,gBAAA,EAAkB,gBAAA;EAQiB;;;;;;;EAAnC,SAAA,GAAY,uBAAA;AAAA;AAAA,cAGD,uBAAA;AAAA,cACA,qBAAA;AAAA,iBAEG,yBAAA,CAA0B,SAAA;AAAA,cAQ7B,eAAA,EAAiB,uBAAA;;;AAX9B;;;;;AACA;;;;iBAgCgB,oBAAA,CAAqB,YAAA,YAAwB,uBAAA;AAAA,cAmChD,aAAA;;;;;AAzDb;;cA4Fa,gBAAA;EAAA;;;;;cAOA,aAAA;;AA1Cb;;;;;AAmCA;;;;iBA6JgB,kBAAA,CAAmB,OAAA,EAAS,gBAAA;;;;;AAtJ5C;iBAkOgB,uBAAA,CAAwB,OAAA,EAAS,gBAAA;;iBAyCjC,wBAAA,CAAyB,MAAA,YAAkB,KAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{consumerPackageEntries as e,consumerPackageEntry as t,localEntries as n,localEntry as r,localPackageName as i,optionalPackageEntries as a,optionalPackageEntry as o,ownEntry as s,packageEntries as c,packageEntry as l}from"../adapters/modules/moduleResolution.mjs";import"../utils/index.mjs";import{isLocalPackageSpecifier as u}from"@agimon-ai/doompi-config/majorModes";const d=`@juicesharp/rpiv-ask-user-question`,f=`@agimon-ai/doompi-user-feedback`;function p(e){return e===`@juicesharp/rpiv-ask-user-question`?f:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${f}${e.slice(34)}`:e}const m={ownEntry:s,packageEntry:e=>l(p(e)),optionalPackageEntry:e=>o(p(e)),packageEntries:e=>c(p(e)),optionalPackageEntries:e=>a(p(e)),localEntry:r,localEntries:n,localPackageName:i};function h(u){return u?{ownEntry:s,packageEntry:e=>{let n=p(e);return t(n,u)??l(n)},optionalPackageEntry:e=>{let n=p(e);return t(n,u)??o(n)},packageEntries:t=>{let n=p(t);return e(n,u)??c(n)},optionalPackageEntries:t=>{let n=p(t);return e(n,u)??a(n)},localEntry:r,localEntries:n,localPackageName:i}:m}const g=`guardrails`,_=`vibe-lint`,v=`code-intel`,y=`runner`,b=`ask-user`,x=`style-system`,S=`ollama`,C={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},w={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,
|
|
1
|
+
import{consumerPackageEntries as e,consumerPackageEntry as t,localEntries as n,localEntry as r,localPackageName as i,optionalPackageEntries as a,optionalPackageEntry as o,ownEntry as s,packageEntries as c,packageEntry as l}from"../adapters/modules/moduleResolution.mjs";import"../utils/index.mjs";import{isLocalPackageSpecifier as u}from"@agimon-ai/doompi-config/majorModes";const d=`@juicesharp/rpiv-ask-user-question`,f=`@agimon-ai/doompi-user-feedback`;function p(e){return e===`@juicesharp/rpiv-ask-user-question`?f:e.startsWith(`@juicesharp/rpiv-ask-user-question/`)?`${f}${e.slice(34)}`:e}const m={ownEntry:s,packageEntry:e=>l(p(e)),optionalPackageEntry:e=>o(p(e)),packageEntries:e=>c(p(e)),optionalPackageEntries:e=>a(p(e)),localEntry:r,localEntries:n,localPackageName:i};function h(u){return u?{ownEntry:s,packageEntry:e=>{let n=p(e);return t(n,u)??l(n)},optionalPackageEntry:e=>{let n=p(e);return t(n,u)??o(n)},packageEntries:t=>{let n=p(t);return e(n,u)??c(n)},optionalPackageEntries:t=>{let n=p(t);return e(n,u)??a(n)},localEntry:r,localEntries:n,localPackageName:i}:m}const g=`guardrails`,_=`vibe-lint`,v=`code-intel`,y=`runner`,b=`ask-user`,x=`style-system`,S=`ollama`,C={autoStop:`autoStop`,cacheOptimizer:`cacheOptimizer`,domains:`domains`,effort:`effort`,majorMode:`majorMode`,modeCatalog:`modeCatalog`,notifications:`notifications`,ollamaProvider:`ollamaProvider`,profile:`profile`,skills:`skills`},w={autocompact:`@agimon-ai/doompi-autocompact/extensions/pi`,doomConfig:`@agimon-ai/doompi-config/pi`,doomHelp:`@agimon-ai/doompi-help/extensions/doom`,doomUi:`@agimon-ai/doompi-ui/extensions/pi`,fileEdit:`@agimon-ai/doompi-file-edit/extensions/doom`,logSinkTelemetry:`@agimon-ai/doompi-log/extensions/pi`,loop:`@agimon-ai/doompi-loop/extensions/pi`,planDoom:`@agimon-ai/doompi-plan/extensions/doom`,voice:`@agimon-ai/doompi-voice/extensions/doom`,goalDoom:`@agimon-ai/doompi-goal/extensions/doom`},T=new Set([g,_,v]),E={mcp:`@agimon-ai/doompi-mcp/extensions/pi`,workflow:`@agimon-ai/doompi-workflow/extensions/pi`,dispatcherWorkflow:`@agimon-ai/doompi-workflow/extensions/dispatcher`},D=`persona`;function O(e){let t=p(e),n=t.split(`/`);return t.startsWith(`@`)?n.slice(0,2).join(`/`):n[0]??t}function k(e,t,n){return{name:`own:${e}`,path:t,priority:n}}function A(e,t,n,r=0){let i=r===0?``:`:${r}`;return{name:`package:${O(e)}${i}`,path:t,priority:n}}function j(e,t,n=0){let r=n===0?``:`:${n}`;return{name:t?`package:${O(t)}${r}`:`local:${e.replaceAll(`\\`,`/`)}`,path:e,priority:1}}function M(e,t,n){let r=e.localEntries?.(t,n);if(r!==void 0)return r;let i=e.localEntry(t,n);return i?[i]:void 0}function N(e,t,n){let r=e.layers[t];if(!r)throw Error(`Unknown layer: ${t}`);let i=[];for(let e of r.extensions??[]){if(!u(e)){i.push(k(e,n.ownEntry(e),1));continue}let a=M(n,e,r.baseDirectory);if(!a?.length)throw Error(`Layer "${t}" extension "${e}" does not resolve under ${r.baseDirectory}. Point it at a Pi extension file or directory.`);i.push(...a.map(e=>j(e)))}for(let e of r.packages??[]){let a=typeof e==`string`?e:e.name,o=typeof e==`string`?!1:e.optional===!0;if(u(a)){let e=M(n,a,r.baseDirectory);if(e?.length){let t=n.localPackageName?.(a,r.baseDirectory);i.push(...e.map((e,n)=>j(e,t,n)))}else if(!o)throw Error(`Layer "${t}" package "${a}" does not resolve under ${r.baseDirectory}. Point it at an extension file, or a directory whose package.json declares pi.extensions.`);continue}let s;if(o){if(s=n.optionalPackageEntries?.(a),s===void 0){let e=n.optionalPackageEntry(a);s=e?[e]:void 0}}else s=n.packageEntries?.(a)??[n.packageEntry(a)];if(s?.length)i.push(...s.map((e,t)=>A(a,e,1,t)));else if(!o)throw Error(`Layer "${t}" package "${a}" declares no Pi extensions.`)}return i}function P(e){let t=[];for(let n of e){let e=n.path.replaceAll(`\\`,`/`),r=t.findIndex(t=>t.name===n.name||t.path.replaceAll(`\\`,`/`)===e);if(r===-1){t.push(n);continue}let i=t[r];i&&n.priority>i.priority&&(t[r]=n)}return t.map(e=>e.path)}function F(e){let t=e.majorModesConfig,n=e.resolvers??m,r=e=>k(e,n.ownEntry(e),0),i=e=>A(e,n.packageEntry(e),0),a=new Set(e.layers),o=e=>a.has(e)?N(t,e,n):[],s=[];return e.mcpEntry&&s.push(A(E.mcp,e.mcpEntry,2)),s.push(i(w.logSinkTelemetry)),e.personaEntry&&s.push(k(D,e.personaEntry,2)),e.workflowExtension&&s.push(A(E.workflow,e.workflowExtension,2)),s.push(...o(`agiflow`),...o(g),...o(_),...o(v)),e.preset===`ollama`&&s.push(r(C.ollamaProvider)),s.push(r(C.effort)),s.push(i(w.planDoom)),s.push(...o(`task`)),s.push(i(w.loop)),s.push(i(w.autocompact)),s.push(i(w.fileEdit)),s.push(...o(y)),s.push(...o(b),...o(x)),s.push(i(w.voice)),s.push(r(C.domains)),s.push(r(C.skills)),s.push(r(C.majorMode)),s.push(r(C.profile)),s.push(i(w.goalDoom)),s.push(r(C.cacheOptimizer)),e.mute||s.push(r(C.notifications)),e.agents&&s.push(...o(`team`)),s.push(i(w.doomHelp)),s.push(i(w.doomUi)),s.push(i(w.doomConfig)),s.push(r(C.modeCatalog)),e.autoStop&&s.unshift(r(C.autoStop)),P(s)}function I(e){let t=e.resolvers??m,n=e=>A(e,t.packageEntry(e),0),r=new Set(e.layers),i=n=>r.has(n)?N(e.majorModesConfig,n,t):[],a=[];return e.mcpEntry&&a.push(A(E.mcp,e.mcpEntry,2)),a.push(n(w.logSinkTelemetry)),e.personaEntry&&a.push(k(D,e.personaEntry,2)),e.preset===`ollama`&&a.push(k(C.ollamaProvider,t.ownEntry(C.ollamaProvider),0)),a.push(...i(g),...i(_),...i(v),...i(y),...i(b),...i(x)),a.push(n(w.autocompact)),a.push(n(w.doomConfig)),P(a)}function L(e,t){return t?[...e]:e.filter(e=>!T.has(e))}export{E as CONTEXT_PACKAGES,m as LAYER_RESOLVERS,d as LEGACY_ASK_USER_PACKAGE,S as OLLAMA_PRESET,D as PERSONA_ENTRY,f as USER_FEEDBACK_PACKAGE,I as assembleChildExtensions,F as assembleExtensions,p as canonicalPackageSpecifier,h as createLayerResolvers,L as filterHookDisabledLayers};
|
|
2
2
|
//# sourceMappingURL=extensionAssembler.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensionAssembler.mjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_PLAN_MODE = 'plan-mode';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n task: '@agimon-ai/doompi-task/extensions/pi',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n extensions.push(...layer(LAYER_PLAN_MODE));\n extensions.push(pkg(PACKAGE_ENTRIES.task));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extensionAssembler.mjs","names":["resolvePackageEntry","resolveOptionalPackageEntry","resolvePackageEntries","resolveOptionalPackageEntries","resolveLocalPackageName"],"sources":["../../src/services/extensionAssembler.ts"],"sourcesContent":["import {\n isLocalPackageSpecifier,\n type LayerResolvers,\n type MajorModesConfig,\n} from '@agimon-ai/doompi-config/majorModes';\nimport {\n consumerPackageEntries,\n consumerPackageEntry,\n localEntries,\n localEntry,\n ownEntry,\n localPackageName as resolveLocalPackageName,\n optionalPackageEntries as resolveOptionalPackageEntries,\n optionalPackageEntry as resolveOptionalPackageEntry,\n packageEntries as resolvePackageEntries,\n packageEntry as resolvePackageEntry,\n} from '../utils/index.ts';\n\nexport interface ExtensionLayerResolvers extends LayerResolvers {\n /** Canonical manifest name for a path that represents a package directory. */\n localPackageName?: (specifier: string, baseDirectory: string) => string | undefined;\n}\n\nexport interface ExtensionContext {\n agents: boolean;\n autoStop: boolean;\n mute?: boolean;\n preset?: string;\n mcpEntry?: string;\n personaEntry?: string;\n workflowExtension?: string;\n /** Resolved layer names from the selected major mode. */\n layers: string[];\n majorModesConfig: MajorModesConfig;\n /**\n * How entry names become absolute paths. Defaults to resolving them here.\n *\n * The synced Pi path composes inside a Pi session, where module resolution\n * cannot be relied on, so it substitutes resolvers backed by the map\n * `doom-pi sync` recorded. Both paths therefore run this same function.\n */\n resolvers?: ExtensionLayerResolvers;\n}\n\nexport const LEGACY_ASK_USER_PACKAGE = '@juicesharp/rpiv-ask-user-question';\nexport const USER_FEEDBACK_PACKAGE = '@agimon-ai/doompi-user-feedback';\n\nexport function canonicalPackageSpecifier(specifier: string): string {\n if (specifier === LEGACY_ASK_USER_PACKAGE) return USER_FEEDBACK_PACKAGE;\n if (specifier.startsWith(`${LEGACY_ASK_USER_PACKAGE}/`)) {\n return `${USER_FEEDBACK_PACKAGE}${specifier.slice(LEGACY_ASK_USER_PACKAGE.length)}`;\n }\n return specifier;\n}\n\nexport const LAYER_RESOLVERS: ExtensionLayerResolvers = {\n ownEntry,\n packageEntry: (name) => resolvePackageEntry(canonicalPackageSpecifier(name)),\n optionalPackageEntry: (name) => resolveOptionalPackageEntry(canonicalPackageSpecifier(name)),\n packageEntries: (name) => resolvePackageEntries(canonicalPackageSpecifier(name)),\n optionalPackageEntries: (name) => resolveOptionalPackageEntries(canonicalPackageSpecifier(name)),\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n};\n\n/**\n * Resolvers that answer for the consumer repository before the meta-package.\n *\n * A repository declares its own layer packages in `.doom/modes.yaml`, and it is\n * the repository that installs them. Doom Pi owns only the Doom closure, so a\n * consumer specifier has to resolve from the consumer root and everything else\n * falls back to what ships with the installed meta-package.\n *\n * Path-style extensions and packages skip all of that: they are already\n * anchored to the config that declared them, so there is no chain to search.\n */\nexport function createLayerResolvers(consumerRoot?: string): ExtensionLayerResolvers {\n if (!consumerRoot) return LAYER_RESOLVERS;\n return {\n ownEntry,\n packageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolvePackageEntry(target);\n },\n optionalPackageEntry: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntry(target, consumerRoot) ?? resolveOptionalPackageEntry(target);\n },\n packageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolvePackageEntries(target);\n },\n optionalPackageEntries: (name) => {\n const target = canonicalPackageSpecifier(name);\n return consumerPackageEntries(target, consumerRoot) ?? resolveOptionalPackageEntries(target);\n },\n localEntry,\n localEntries,\n localPackageName: resolveLocalPackageName,\n };\n}\n\nconst LAYER_AGIFLOW = 'agiflow';\nconst LAYER_GUARDRAILS = 'guardrails';\nconst LAYER_VIBE_LINT = 'vibe-lint';\nconst LAYER_CODE_INTEL = 'code-intel';\nconst LAYER_TEAM = 'team';\nconst LAYER_TASK = 'task';\nconst LAYER_RUNNER = 'runner';\nconst LAYER_ASK_USER = 'ask-user';\nconst LAYER_STYLE_SYSTEM = 'style-system';\nexport const OLLAMA_PRESET = 'ollama';\nconst OWN_ENTRIES = {\n autoStop: 'autoStop',\n cacheOptimizer: 'cacheOptimizer',\n domains: 'domains',\n effort: 'effort',\n majorMode: 'majorMode',\n modeCatalog: 'modeCatalog',\n notifications: 'notifications',\n ollamaProvider: 'ollamaProvider',\n profile: 'profile',\n skills: 'skills',\n} as const;\nconst PACKAGE_ENTRIES = {\n autocompact: '@agimon-ai/doompi-autocompact/extensions/pi',\n doomConfig: '@agimon-ai/doompi-config/pi',\n doomHelp: '@agimon-ai/doompi-help/extensions/doom',\n doomUi: '@agimon-ai/doompi-ui/extensions/pi',\n // Doom entries, not the bare Pi ones: they wrap the same extension and add the\n // leader (and, for voice, config) contributions that only exist under Doom.\n fileEdit: '@agimon-ai/doompi-file-edit/extensions/doom',\n logSinkTelemetry: '@agimon-ai/doompi-log/extensions/pi',\n loop: '@agimon-ai/doompi-loop/extensions/pi',\n planDoom: '@agimon-ai/doompi-plan/extensions/doom',\n voice: '@agimon-ai/doompi-voice/extensions/doom',\n goalDoom: '@agimon-ai/doompi-goal/extensions/doom',\n} as const;\nconst HOOK_DISABLED_LAYERS = new Set([LAYER_GUARDRAILS, LAYER_VIBE_LINT, LAYER_CODE_INTEL]);\n\n/**\n * Optional packages passed in as context rather than resolved from a layer.\n *\n * Named here so the launcher and the synced Pi path ask for the same three\n * specifiers; the synced path also needs them in its recorded resolution map.\n */\nexport const CONTEXT_PACKAGES = {\n mcp: '@agimon-ai/doompi-mcp/extensions/pi',\n workflow: '@agimon-ai/doompi-workflow/extensions/pi',\n dispatcherWorkflow: '@agimon-ai/doompi-workflow/extensions/dispatcher',\n} as const;\n\n/** Own entry that is always loaded so /profile can pick a persona later. */\nexport const PERSONA_ENTRY = 'persona';\n\nconst DEFAULT_EXTENSION_PRIORITY = 0;\nconst LAYER_EXTENSION_PRIORITY = 1;\nconst CONTEXT_EXTENSION_PRIORITY = 2;\n\ntype ExtensionPriority =\n | typeof DEFAULT_EXTENSION_PRIORITY\n | typeof LAYER_EXTENSION_PRIORITY\n | typeof CONTEXT_EXTENSION_PRIORITY;\n\ninterface NamedExtension {\n name: string;\n path: string;\n priority: ExtensionPriority;\n}\n\nfunction packageName(specifier: string): string {\n const canonical = canonicalPackageSpecifier(specifier);\n const segments = canonical.split('/');\n return canonical.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? canonical);\n}\n\nfunction ownExtension(name: string, path: string, priority: ExtensionPriority): NamedExtension {\n return { name: `own:${name}`, path, priority };\n}\n\nfunction packageExtension(\n specifier: string,\n path: string,\n priority: ExtensionPriority,\n manifestIndex = 0,\n): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n return { name: `package:${packageName(specifier)}${suffix}`, path, priority };\n}\n\nfunction localExtension(path: string, manifestName?: string, manifestIndex = 0): NamedExtension {\n const suffix = manifestIndex === 0 ? '' : `:${manifestIndex}`;\n const name = manifestName ? `package:${packageName(manifestName)}${suffix}` : `local:${path.replaceAll('\\\\', '/')}`;\n return { name, path, priority: LAYER_EXTENSION_PRIORITY };\n}\n\nfunction resolveLocalEntries(\n resolvers: ExtensionLayerResolvers,\n specifier: string,\n baseDirectory: string,\n): string[] | undefined {\n const resolved = resolvers.localEntries?.(specifier, baseDirectory);\n if (resolved !== undefined) return resolved;\n const single = resolvers.localEntry(specifier, baseDirectory);\n return single ? [single] : undefined;\n}\n\nfunction resolveLayerExtensions(\n config: MajorModesConfig,\n name: string,\n resolvers: ExtensionLayerResolvers,\n): NamedExtension[] {\n const definition = config.layers[name];\n if (!definition) throw new Error(`Unknown layer: ${name}`);\n\n const extensions: NamedExtension[] = [];\n for (const entry of definition.extensions ?? []) {\n if (!isLocalPackageSpecifier(entry)) {\n extensions.push(ownExtension(entry, resolvers.ownEntry(entry), LAYER_EXTENSION_PRIORITY));\n continue;\n }\n const resolved = resolveLocalEntries(resolvers, entry, definition.baseDirectory);\n if (!resolved?.length) {\n throw new Error(\n `Layer \"${name}\" extension \"${entry}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at a Pi extension file or directory.',\n );\n }\n extensions.push(...resolved.map((resolvedEntry) => localExtension(resolvedEntry)));\n }\n for (const configured of definition.packages ?? []) {\n const specifier = typeof configured === 'string' ? configured : configured.name;\n const optional = typeof configured === 'string' ? false : configured.optional === true;\n if (isLocalPackageSpecifier(specifier)) {\n const resolved = resolveLocalEntries(resolvers, specifier, definition.baseDirectory);\n if (resolved?.length) {\n const manifestName = resolvers.localPackageName?.(specifier, definition.baseDirectory);\n extensions.push(...resolved.map((entry, index) => localExtension(entry, manifestName, index)));\n } else if (!optional) {\n throw new Error(\n `Layer \"${name}\" package \"${specifier}\" does not resolve under ${definition.baseDirectory}. ` +\n 'Point it at an extension file, or a directory whose package.json declares pi.extensions.',\n );\n }\n continue;\n }\n\n let resolved: string[] | undefined;\n if (optional) {\n resolved = resolvers.optionalPackageEntries?.(specifier);\n if (resolved === undefined) {\n const single = resolvers.optionalPackageEntry(specifier);\n resolved = single ? [single] : undefined;\n }\n } else {\n resolved = resolvers.packageEntries?.(specifier) ?? [resolvers.packageEntry(specifier)];\n }\n if (resolved?.length) {\n extensions.push(\n ...resolved.map((entry, index) => packageExtension(specifier, entry, LAYER_EXTENSION_PRIORITY, index)),\n );\n } else if (!optional) {\n throw new Error(`Layer \"${name}\" package \"${specifier}\" declares no Pi extensions.`);\n }\n }\n return extensions;\n}\n\n/**\n * Keeps one extension per logical name without moving its dependency slot.\n *\n * The first occurrence establishes load order. A selected major-mode layer can\n * replace a default in that slot, and an explicit context entry has final\n * precedence. This gives repository configuration priority without loading\n * both implementations.\n */\nfunction deduplicateExtensions(extensions: NamedExtension[]): string[] {\n const selected: NamedExtension[] = [];\n for (const extension of extensions) {\n const normalizedPath = extension.path.replaceAll('\\\\', '/');\n const index = selected.findIndex(\n (current) => current.name === extension.name || current.path.replaceAll('\\\\', '/') === normalizedPath,\n );\n if (index === -1) {\n selected.push(extension);\n continue;\n }\n const current = selected[index];\n if (current && extension.priority > current.priority) selected[index] = extension;\n }\n return selected.map((extension) => extension.path);\n}\n\n/**\n * Assembles the ordered Pi --extension list.\n *\n * Order is load-bearing: the workflow extension must register its launch tool\n * before the Agiflow dispatcher can steer toward it, and auto-stop must end up\n * first because Pi applies extension arguments in reverse. That is why this\n * function, not modes.yaml, owns the sequence. Layers declare WHAT they\n * contribute; each one is spliced in at its slot below. Kept pure so a snapshot\n * test can pin the result.\n */\nexport function assembleExtensions(context: ExtensionContext): string[] {\n const config = context.majorModesConfig;\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const own = (name: string): NamedExtension => ownExtension(name, resolve.ownEntry(name), DEFAULT_EXTENSION_PRIORITY);\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(config, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n // Loaded when a profile supplies a persona, and kept available for /profile.\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.workflowExtension) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.workflow, context.workflowExtension, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(\n ...layer(LAYER_AGIFLOW),\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n );\n if (context.preset === OLLAMA_PRESET) extensions.push(own(OWN_ENTRIES.ollamaProvider));\n extensions.push(own(OWN_ENTRIES.effort));\n // Plan is a battery-included minor mode. Its tools stay inactive until the\n // user enters Plan, while its Doom adapter keeps Leader and mode metadata ready.\n extensions.push(pkg(PACKAGE_ENTRIES.planDoom));\n // Task is a major-mode capability: selected modes opt into its persistent graph.\n extensions.push(...layer(LAYER_TASK));\n extensions.push(pkg(PACKAGE_ENTRIES.loop));\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n extensions.push(pkg(PACKAGE_ENTRIES.fileEdit));\n // Next to task: both own long-lived work, and the runner's bash replacement\n // has to be registered before any layer that renders tool results.\n extensions.push(...layer(LAYER_RUNNER));\n extensions.push(...layer(LAYER_ASK_USER), ...layer(LAYER_STYLE_SYSTEM));\n extensions.push(pkg(PACKAGE_ENTRIES.voice));\n extensions.push(own(OWN_ENTRIES.domains));\n // Next to domains, which owns the same selection. This entry starts deferred\n // skill loading after the TUI is live and hosts the attribution registry\n // before contributors register into it (Pi applies these in reverse).\n extensions.push(own(OWN_ENTRIES.skills));\n extensions.push(own(OWN_ENTRIES.majorMode));\n extensions.push(own(OWN_ENTRIES.profile));\n // Goal is a globally available minor mode, not a configurable major-mode layer.\n extensions.push(pkg(PACKAGE_ENTRIES.goalDoom));\n // The upstream package publishes TypeScript only. This package's build\n // inlines it behind an own JavaScript entry so plain Pi never type-strips a\n // file below node_modules.\n extensions.push(own(OWN_ENTRIES.cacheOptimizer));\n if (!context.mute) extensions.push(own(OWN_ENTRIES.notifications));\n if (context.agents) extensions.push(...layer(LAYER_TEAM));\n // Pi loads explicit extension arguments in reverse. Help sits immediately\n // before Leader so the UI host exists before Help registers SPC h e, while\n // Help itself is available before the core skills consumer initializes.\n extensions.push(pkg(PACKAGE_ENTRIES.doomHelp));\n extensions.push(pkg(PACKAGE_ENTRIES.doomUi));\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n // Pi loads in reverse: the catalog must bind before owners and consumers.\n extensions.push(own(OWN_ENTRIES.modeCatalog));\n if (context.autoStop) extensions.unshift(own(OWN_ENTRIES.autoStop));\n\n return deduplicateExtensions(extensions);\n}\n\n/**\n * Builds the explicit extension set inherited by detached Doom Team children.\n * UI, launch, notification, and orchestration extensions remain parent-only.\n * Domain skills and profile environment values travel through harness state.\n */\nexport function assembleChildExtensions(context: ExtensionContext): string[] {\n const resolve = context.resolvers ?? LAYER_RESOLVERS;\n const pkg = (specifier: string): NamedExtension =>\n packageExtension(specifier, resolve.packageEntry(specifier), DEFAULT_EXTENSION_PRIORITY);\n const selected = new Set(context.layers);\n const layer = (name: string): NamedExtension[] =>\n selected.has(name) ? resolveLayerExtensions(context.majorModesConfig, name, resolve) : [];\n const extensions: NamedExtension[] = [];\n\n if (context.mcpEntry) {\n extensions.push(packageExtension(CONTEXT_PACKAGES.mcp, context.mcpEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n extensions.push(pkg(PACKAGE_ENTRIES.logSinkTelemetry));\n if (context.personaEntry) {\n extensions.push(ownExtension(PERSONA_ENTRY, context.personaEntry, CONTEXT_EXTENSION_PRIORITY));\n }\n if (context.preset === OLLAMA_PRESET) {\n extensions.push(\n ownExtension(\n OWN_ENTRIES.ollamaProvider,\n resolve.ownEntry(OWN_ENTRIES.ollamaProvider),\n DEFAULT_EXTENSION_PRIORITY,\n ),\n );\n }\n extensions.push(\n ...layer(LAYER_GUARDRAILS),\n ...layer(LAYER_VIBE_LINT),\n ...layer(LAYER_CODE_INTEL),\n ...layer(LAYER_RUNNER),\n ...layer(LAYER_ASK_USER),\n ...layer(LAYER_STYLE_SYSTEM),\n );\n extensions.push(pkg(PACKAGE_ENTRIES.autocompact));\n // Pi reverses explicit extension arguments, so the child-safe provider stays last.\n extensions.push(pkg(PACKAGE_ENTRIES.doomConfig));\n\n return deduplicateExtensions(extensions);\n}\n\n/** Preserves the historical --no-hooks behavior by filtering the resolved base. */\nexport function filterHookDisabledLayers(layers: string[], hooks: boolean): string[] {\n return hooks ? [...layers] : layers.filter((name) => !HOOK_DISABLED_LAYERS.has(name));\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.19",
|
|
4
4
|
"description": "Pi-based agent harness for repository automations and developer workflows",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"dpi": "./dist/bin/dpi.mjs"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
|
+
"assets",
|
|
21
22
|
"dist"
|
|
22
23
|
],
|
|
23
24
|
"type": "module",
|
|
@@ -345,24 +346,24 @@
|
|
|
345
346
|
"rolldown": "1.0.0-rc.17",
|
|
346
347
|
"typebox": "1.1.38",
|
|
347
348
|
"yaml": "2.9.0",
|
|
348
|
-
"@agimon-ai/doompi-
|
|
349
|
-
"@agimon-ai/doompi-
|
|
350
|
-
"@agimon-ai/doompi-
|
|
351
|
-
"@agimon-ai/doompi-
|
|
352
|
-
"@agimon-ai/doompi-
|
|
353
|
-
"@agimon-ai/doompi-
|
|
354
|
-
"@agimon-ai/doompi-
|
|
355
|
-
"@agimon-ai/doompi-
|
|
356
|
-
"@agimon-ai/doompi-
|
|
357
|
-
"@agimon-ai/doompi-
|
|
358
|
-
"@agimon-ai/doompi-
|
|
359
|
-
"@agimon-ai/doompi-
|
|
360
|
-
"@agimon-ai/doompi-
|
|
361
|
-
"@agimon-ai/doompi-ui": "0.0.1-alpha.
|
|
362
|
-
"@agimon-ai/doompi-
|
|
363
|
-
"@agimon-ai/doompi-
|
|
364
|
-
"@agimon-ai/doompi-
|
|
365
|
-
"@agimon-ai/doompi-
|
|
349
|
+
"@agimon-ai/doompi-file-edit": "0.0.1-alpha.19",
|
|
350
|
+
"@agimon-ai/doompi-config": "0.0.1-alpha.19",
|
|
351
|
+
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.19",
|
|
352
|
+
"@agimon-ai/doompi-log": "0.0.1-alpha.19",
|
|
353
|
+
"@agimon-ai/doompi-loop": "0.0.1-alpha.19",
|
|
354
|
+
"@agimon-ai/doompi-mcp": "0.0.1-alpha.19",
|
|
355
|
+
"@agimon-ai/doompi-runner": "0.0.1-alpha.19",
|
|
356
|
+
"@agimon-ai/doompi-goal": "0.0.1-alpha.9",
|
|
357
|
+
"@agimon-ai/doompi-plan": "0.0.1-alpha.19",
|
|
358
|
+
"@agimon-ai/doompi-autocompact": "0.0.1-alpha.19",
|
|
359
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.19",
|
|
360
|
+
"@agimon-ai/doompi-task": "0.0.1-alpha.19",
|
|
361
|
+
"@agimon-ai/doompi-user-feedback": "0.0.1-alpha.8",
|
|
362
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.19",
|
|
363
|
+
"@agimon-ai/doompi-team": "0.0.1-alpha.19",
|
|
364
|
+
"@agimon-ai/doompi-help": "0.0.1-alpha.2",
|
|
365
|
+
"@agimon-ai/doompi-workflow": "0.0.1-alpha.19",
|
|
366
|
+
"@agimon-ai/doompi-voice": "0.0.1-alpha.19"
|
|
366
367
|
},
|
|
367
368
|
"devDependencies": {
|
|
368
369
|
"@earendil-works/pi-ai": "0.84.2",
|