@agimon-ai/doompi 0.0.1-alpha.15 → 0.0.1-alpha.16

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.
Files changed (159) hide show
  1. package/README.md +242 -14
  2. package/dist/adapters/compatibility/process.cjs +1 -1
  3. package/dist/adapters/compatibility/process.mjs +1 -1
  4. package/dist/adapters/compatibilityContext.cjs +1 -1
  5. package/dist/adapters/compatibilityContext.cjs.map +1 -1
  6. package/dist/adapters/compatibilityContext.d.cts.map +1 -1
  7. package/dist/adapters/compatibilityContext.d.mts.map +1 -1
  8. package/dist/adapters/compatibilityContext.mjs +1 -1
  9. package/dist/adapters/compatibilityContext.mjs.map +1 -1
  10. package/dist/adapters/composer.cjs +1 -1
  11. package/dist/adapters/composer.mjs +1 -1
  12. package/dist/adapters/dpiRunner.cjs +3 -0
  13. package/dist/adapters/dpiRunner.cjs.map +1 -0
  14. package/dist/adapters/dpiRunner.mjs +3 -0
  15. package/dist/adapters/dpiRunner.mjs.map +1 -0
  16. package/dist/adapters/dpiSettings.cjs +2 -0
  17. package/dist/adapters/dpiSettings.cjs.map +1 -0
  18. package/dist/adapters/dpiSettings.mjs +2 -0
  19. package/dist/adapters/dpiSettings.mjs.map +1 -0
  20. package/dist/adapters/harnessContext.cjs +1 -1
  21. package/dist/adapters/harnessContext.cjs.map +1 -1
  22. package/dist/adapters/harnessContext.d.cts.map +1 -1
  23. package/dist/adapters/harnessContext.d.mts.map +1 -1
  24. package/dist/adapters/harnessContext.mjs +1 -1
  25. package/dist/adapters/harnessContext.mjs.map +1 -1
  26. package/dist/adapters/matrixSwitcher.cjs +1 -1
  27. package/dist/adapters/matrixSwitcher.cjs.map +1 -1
  28. package/dist/adapters/matrixSwitcher.d.cts.map +1 -1
  29. package/dist/adapters/matrixSwitcher.d.mts.map +1 -1
  30. package/dist/adapters/matrixSwitcher.mjs +1 -1
  31. package/dist/adapters/matrixSwitcher.mjs.map +1 -1
  32. package/dist/adapters/pluginMaterializer.cjs +2 -0
  33. package/dist/adapters/pluginMaterializer.cjs.map +1 -0
  34. package/dist/adapters/pluginMaterializer.mjs +2 -0
  35. package/dist/adapters/pluginMaterializer.mjs.map +1 -0
  36. package/dist/adapters/resourceCollector.cjs +2 -2
  37. package/dist/adapters/resourceCollector.cjs.map +1 -1
  38. package/dist/adapters/resourceCollector.d.cts +3 -3
  39. package/dist/adapters/resourceCollector.d.cts.map +1 -1
  40. package/dist/adapters/resourceCollector.d.mts +3 -3
  41. package/dist/adapters/resourceCollector.d.mts.map +1 -1
  42. package/dist/adapters/resourceCollector.mjs +2 -2
  43. package/dist/adapters/resourceCollector.mjs.map +1 -1
  44. package/dist/adapters/skillCatalog.cjs +1 -1
  45. package/dist/adapters/skillCatalog.cjs.map +1 -1
  46. package/dist/adapters/skillCatalog.d.cts.map +1 -1
  47. package/dist/adapters/skillCatalog.d.mts.map +1 -1
  48. package/dist/adapters/skillCatalog.mjs +1 -1
  49. package/dist/adapters/skillCatalog.mjs.map +1 -1
  50. package/dist/adapters/startupPrecompiler.cjs.map +1 -1
  51. package/dist/adapters/startupPrecompiler.d.cts +1 -1
  52. package/dist/adapters/startupPrecompiler.d.mts +1 -1
  53. package/dist/adapters/startupPrecompiler.mjs.map +1 -1
  54. package/dist/adapters/syncState.cjs +1 -1
  55. package/dist/adapters/syncState.cjs.map +1 -1
  56. package/dist/adapters/syncState.d.cts +2 -1
  57. package/dist/adapters/syncState.d.cts.map +1 -1
  58. package/dist/adapters/syncState.d.mts +2 -1
  59. package/dist/adapters/syncState.d.mts.map +1 -1
  60. package/dist/adapters/syncState.mjs +1 -1
  61. package/dist/adapters/syncState.mjs.map +1 -1
  62. package/dist/adapters/syncedRuntimeBuilder.cjs +1 -1
  63. package/dist/adapters/syncedRuntimeBuilder.cjs.map +1 -1
  64. package/dist/adapters/syncedRuntimeBuilder.d.cts +1 -1
  65. package/dist/adapters/syncedRuntimeBuilder.d.mts +1 -1
  66. package/dist/adapters/syncedRuntimeBuilder.mjs +1 -1
  67. package/dist/adapters/syncedRuntimeBuilder.mjs.map +1 -1
  68. package/dist/bin/cli.cjs +1 -1
  69. package/dist/bin/cli.cjs.map +1 -1
  70. package/dist/bin/cli.mjs +1 -1
  71. package/dist/bin/cli.mjs.map +1 -1
  72. package/dist/bin/dpi.cjs +3 -0
  73. package/dist/bin/dpi.cjs.map +1 -0
  74. package/dist/bin/dpi.d.cts +1 -0
  75. package/dist/bin/dpi.d.mts +1 -0
  76. package/dist/bin/dpi.mjs +3 -0
  77. package/dist/bin/dpi.mjs.map +1 -0
  78. package/dist/commands/buildCommand.cjs +2 -2
  79. package/dist/commands/buildCommand.mjs +2 -2
  80. package/dist/commands/cli/cliApp.cjs +1 -1
  81. package/dist/commands/cli/cliApp.cjs.map +1 -1
  82. package/dist/commands/cli/cliApp.d.cts.map +1 -1
  83. package/dist/commands/cli/cliApp.d.mts.map +1 -1
  84. package/dist/commands/cli/cliApp.mjs +1 -1
  85. package/dist/commands/cli/cliApp.mjs.map +1 -1
  86. package/dist/commands/cli/help.cjs +1 -3
  87. package/dist/commands/cli/help.cjs.map +1 -1
  88. package/dist/commands/cli/help.mjs +1 -3
  89. package/dist/commands/cli/help.mjs.map +1 -1
  90. package/dist/commands/compatibilityCommand.cjs +1 -1
  91. package/dist/commands/compatibilityCommand.mjs +1 -1
  92. package/dist/commands/index.cjs +1 -1
  93. package/dist/commands/index.d.cts +2 -3
  94. package/dist/commands/index.d.mts +2 -3
  95. package/dist/commands/index.mjs +1 -1
  96. package/dist/commands/initCommand.cjs +1 -1
  97. package/dist/commands/initCommand.mjs +1 -1
  98. package/dist/commands/initPresenter.cjs +1 -1
  99. package/dist/commands/initPresenter.cjs.map +1 -1
  100. package/dist/commands/initPresenter.mjs +1 -1
  101. package/dist/commands/initPresenter.mjs.map +1 -1
  102. package/dist/commands/launchCommand.cjs +1 -1
  103. package/dist/commands/launchCommand.mjs +1 -1
  104. package/dist/commands/syncCommand.cjs +4 -4
  105. package/dist/commands/syncCommand.cjs.map +1 -1
  106. package/dist/commands/syncCommand.d.cts +11 -4
  107. package/dist/commands/syncCommand.d.cts.map +1 -1
  108. package/dist/commands/syncCommand.d.mts +11 -4
  109. package/dist/commands/syncCommand.d.mts.map +1 -1
  110. package/dist/commands/syncCommand.mjs +4 -4
  111. package/dist/commands/syncCommand.mjs.map +1 -1
  112. package/dist/commands/syncPipeline.cjs +2 -0
  113. package/dist/commands/syncPipeline.cjs.map +1 -0
  114. package/dist/commands/syncPipeline.mjs +2 -0
  115. package/dist/commands/syncPipeline.mjs.map +1 -0
  116. package/dist/entries/majorMode.cjs +1 -1
  117. package/dist/entries/majorMode.d.cts +2 -2
  118. package/dist/entries/majorMode.d.mts +2 -2
  119. package/dist/entries/majorMode.mjs +1 -1
  120. package/dist/extensions/entries/domains.cjs +1 -1
  121. package/dist/extensions/entries/domains.cjs.map +1 -1
  122. package/dist/extensions/entries/domains.d.cts +1 -1
  123. package/dist/extensions/entries/domains.d.cts.map +1 -1
  124. package/dist/extensions/entries/domains.d.mts +1 -1
  125. package/dist/extensions/entries/domains.d.mts.map +1 -1
  126. package/dist/extensions/entries/domains.mjs +1 -1
  127. package/dist/extensions/entries/domains.mjs.map +1 -1
  128. package/dist/extensions/entries/majorMode.cjs +4 -4
  129. package/dist/extensions/entries/majorMode.cjs.map +1 -1
  130. package/dist/extensions/entries/majorMode.d.cts +1 -3
  131. package/dist/extensions/entries/majorMode.d.cts.map +1 -1
  132. package/dist/extensions/entries/majorMode.d.mts +1 -3
  133. package/dist/extensions/entries/majorMode.d.mts.map +1 -1
  134. package/dist/extensions/entries/majorMode.mjs +4 -4
  135. package/dist/extensions/entries/majorMode.mjs.map +1 -1
  136. package/dist/extensions/entries/repositoryHooks.cjs +1 -1
  137. package/dist/extensions/entries/repositoryHooks.mjs +1 -1
  138. package/dist/extensions/entries/styleSystem.cjs +2 -2
  139. package/dist/extensions/entries/styleSystem.cjs.map +1 -1
  140. package/dist/extensions/entries/styleSystem.mjs +2 -2
  141. package/dist/index.cjs +1 -1
  142. package/dist/index.d.cts +2 -3
  143. package/dist/index.d.mts +2 -3
  144. package/dist/index.mjs +1 -1
  145. package/dist/pi-cache-optimizer-D9beVnnH.mjs.map +1 -1
  146. package/dist/schemas/majorModeVoiceTools.cjs +2 -0
  147. package/dist/schemas/majorModeVoiceTools.cjs.map +1 -0
  148. package/dist/schemas/majorModeVoiceTools.mjs +2 -0
  149. package/dist/schemas/majorModeVoiceTools.mjs.map +1 -0
  150. package/dist/services/config/index.d.mts +2 -2
  151. package/dist/services/index.cjs +1 -1
  152. package/dist/services/index.mjs +1 -1
  153. package/dist/types/interfaces/harness.d.cts +1 -1
  154. package/dist/types/interfaces/harness.d.mts +1 -1
  155. package/package.json +36 -32
  156. package/dist/commands/buildCommand.d.cts +0 -27
  157. package/dist/commands/buildCommand.d.cts.map +0 -1
  158. package/dist/commands/buildCommand.d.mts +0 -27
  159. package/dist/commands/buildCommand.d.mts.map +0 -1
package/README.md CHANGED
@@ -23,23 +23,56 @@ not. Use it as-is, build your own config on top, or raid it for parts.
23
23
  ## Install
24
24
 
25
25
  ```bash
26
- npm install -g @agimon-ai/doompi @earendil-works/pi-coding-agent
26
+ npm install -g @agimon-ai/doompi
27
27
  ```
28
28
 
29
- ## Quickstart
29
+ The package pins and installs the upstream Pi version used by `dpi`.
30
+
31
+ ## Try DoomPi without replacing your Pi setup
32
+
33
+ `dpi` is the comparison runner. Use it to try DoomPi beside your current `pi` customization
34
+ before registering anything in Pi's settings:
30
35
 
31
36
  ```bash
32
- doompi init # seed ~/.pi/.doom, once per machine
33
- mkdir .doom && cp ~/.pi/.doom/*.yaml .doom/ # the repository config Doompi reads
34
- doompi --explain # what would load, and why
35
- doompi # start a session
37
+ dpi init # create this repository's .doom configuration
38
+ dpi sync # resolve and synchronize the DoomPi experiment
39
+ dpi # run the DoomPi experiment
40
+ pi # run your existing Pi setup for comparison
41
+ ```
42
+
43
+ `dpi init` creates `.doom/config.yaml`, `.doom/modes.yaml`, `.doom/domains.yaml`, and
44
+ `.doom/profiles.yaml` in the current repository. It preserves existing files unless you pass
45
+ `--force` and does not create or change `.pi/settings.json`.
46
+
47
+ `dpi sync` writes DoomPi's generated state, package alias, and theme resource, but it does
48
+ not register DoomPi in either normal Pi settings file.
49
+
50
+ For a fair comparison, `dpi` lets Pi merge the same ordinary settings from
51
+ `~/.pi/agent/settings.json` and `<repo>/.pi/settings.json`. It then overlays only these
52
+ DoomPi-owned values in memory:
53
+
54
+ ```json
55
+ {
56
+ "extensions": ["@agimon-ai/doompi", "!extensions/**"],
57
+ "themes": ["themes/doom-pi-dark.json"],
58
+ "theme": "doom-pi-dark",
59
+ "quietStartup": true
60
+ }
36
61
  ```
37
62
 
38
- `doompi init` is the one machine-wide step. It seeds `~/.pi/.doom`; copy those files into
39
- a repository when the repository needs its own agent. Commit `.doom/`. Now the config
40
- follows the code instead of living in someone's shell history.
63
+ Those four values are never written by `dpi`, including when Pi saves an unrelated option.
64
+ Every other value keeps Pi's normal global/project precedence and trust handling.
41
65
 
42
- Flags override the defaults for one session:
66
+ When you are comfortable with DoomPi and no longer need the side-by-side experiment, register
67
+ it for normal Pi:
68
+
69
+ ```bash
70
+ doompi init # seed ~/.pi/.doom and Pi integration resources
71
+ doompi sync # register DoomPi in normal Pi settings
72
+ pi # DoomPi now starts through the regular Pi command
73
+ ```
74
+
75
+ `doompi` remains available as an explicit harness when you want one-run matrix flags:
43
76
 
44
77
  ```bash
45
78
  doompi --major-mode dev --domains development
@@ -73,6 +106,31 @@ own tools and instructions when turned on. Doompi ships five:
73
106
  A domain is a named group of Pi plugins. It carries the skills and MCP servers for one
74
107
  kind of work, and `/domains` switches it while the session is running.
75
108
 
109
+ Plugins are catalogued once and domains refer to their names. A configured root may be a
110
+ Codex-compatible marketplace or a folder whose direct children are plugins, so a repository
111
+ with many plugins does not need one entry per directory:
112
+
113
+ ```yaml
114
+ plugins:
115
+ roots: [plugins]
116
+ entries:
117
+ remote-review:
118
+ source: url
119
+ url: https://github.com/acme/review-plugin.git
120
+ ref: v1.2.0
121
+
122
+ domains:
123
+ development:
124
+ description: Implementation and code-review tools.
125
+ plugins: [pi-development, remote-review]
126
+ ```
127
+
128
+ DoomPi also checks personal and repository Codex marketplace layouts. Marketplace IDs use
129
+ `plugin@marketplace`. Remote Git and npm sources are downloaded once into the persistent
130
+ `~/.pi/.doom/plugin-cache` directory. Cache entries are reused until their source descriptor
131
+ changes; use a Git SHA or exact npm version for reproducible installs. Home and repository
132
+ catalogs merge, and repository names replace matching home names.
133
+
76
134
  A blog is not one task. Research it, draft it, make the assets, then review it. Turn on the
77
135
  `visual` domain while making assets; the other three steps have no reason to carry it.
78
136
 
@@ -81,6 +139,25 @@ A blog is not one task. Research it, draft it, make the assets, then review it.
81
139
  An LLM has no house style until you give it one. A profile can supply a narrative, brand
82
140
  rules, or a different voice. It is optional; no profile is a perfectly good profile.
83
141
 
142
+ Profile roots remove the need to list every persona folder. A root may itself contain the
143
+ persona files, or its direct-child folders become profiles named after those folders. DoomPi
144
+ recognizes `profile.md`, `SOUL.md`, and `AGENTS.md` and never searches deeper directories.
145
+
146
+ ```yaml
147
+ profiles:
148
+ roots: [agents/acme]
149
+ entries:
150
+ editor:
151
+ persona: agents/special/editor
152
+ env:
153
+ EDITOR_MODE: strict
154
+ ```
155
+
156
+ Roots from the home and repository files accumulate relative to their declaring config.
157
+ Repository discoveries replace same-named home discoveries. Explicit entries override
158
+ discovery and can add string environment defaults; repository entries replace matching home
159
+ entries. Select one at launch with `--profile editor` or switch with `/profile`.
160
+
84
161
  ## What this buys you
85
162
 
86
163
  Every tool schema and skill name competes for the same context. Loading less has two
@@ -155,10 +232,11 @@ them one at a time.
155
232
 
156
233
  ### Configuration and composition
157
234
 
158
- `@agimon-ai/doompi` is both an extension and the command-line config compiler. The
159
- `doompi init` command writes the config; `doompi sync` resolves every major mode and
160
- domain into a distribution Pi can load quickly. A large major mode with 15 extensions
161
- adds only 400 ms of code startup time.
235
+ `@agimon-ai/doompi` is both an extension and the command-line config compiler. `dpi init`
236
+ creates repository config for an isolated experiment, while `doompi init` creates the personal
237
+ config and registers the permanent Pi integration. The sync commands resolve every major mode
238
+ and domain into a distribution Pi can load quickly. A large major mode with 15 extensions adds
239
+ only 400 ms of code startup time.
162
240
 
163
241
  ### Leader key
164
242
 
@@ -245,3 +323,153 @@ explicit handoffs rather than one long conversation.
245
323
  `@agimon-ai/doompi-voice` records and transcribes speech locally; audio stays on the
246
324
  machine. Use `SPC v v` for one recording or `SPC v a` to toggle autonomous capture. It
247
325
  replaces the keyboard without replacing the work already in progress.
326
+
327
+ ## Configuration
328
+
329
+ Doompi keeps the session matrix in three files:
330
+
331
+ - `modes.yaml` defines extension layers and major modes.
332
+ - `domains.yaml` catalogs plugins and sets session access.
333
+ - `profiles.yaml` supplies persona files and environment defaults.
334
+
335
+ Each matrix file has two optional layers: personal defaults in `~/.pi/.doom/` and repository
336
+ overrides in `<repository>/.doom/`. Doompi loads both. Unique named entries from either layer
337
+ remain available; a same-named repository entry replaces the complete personal entry. Plugin
338
+ and profile roots from both layers are retained. Relative paths in personal config resolve
339
+ from `~/.pi/.doom/`; relative paths in repository config resolve from the repository root.
340
+
341
+ ### `modes.yaml`: choose behavior
342
+
343
+ A layer is an ordered bundle of extension packages and hook groups. A major mode names the
344
+ layers that should run together. Packages may be bare strings, or mappings when the package
345
+ accepts configuration:
346
+
347
+ ```yaml
348
+ layers:
349
+ team:
350
+ packages:
351
+ - name: '@agimon-ai/doompi-team'
352
+ config:
353
+ models:
354
+ - model: provider/model-id
355
+ thinking: high
356
+ review:
357
+ packages:
358
+ - '@scope/review-extension'
359
+
360
+ defaultMajorMode: copilot
361
+ majorMode:
362
+ minimal:
363
+ description: Lean sessions with delegation and little else.
364
+ layers: [team]
365
+ copilot:
366
+ description: General coding with delegation and review tools.
367
+ layers: [team, review]
368
+ ```
369
+
370
+ Order matters: Doompi assembles layers and their packages from left to right. Put settings
371
+ under the package that consumes them; a layer is composition, not a mystery bag of shared
372
+ configuration. Home and repository `layers` and `majorMode` records merge by name, with the
373
+ repository definition winning a collision.
374
+
375
+ Choose a mode with `--major-mode copilot`, switch it with `/mode`, or change
376
+ `defaultMajorMode` when one mode should be the ordinary starting point.
377
+
378
+ ### `domains.yaml`: choose content and access
379
+
380
+ Plugins are catalogued once, then domains refer to their names. A root can be a marketplace,
381
+ a single plugin, or a container whose direct-child folders are plugins. Discovery is
382
+ intentionally nonrecursive: a tool buried five directories down should not load by accident.
383
+
384
+ ```yaml
385
+ defaultDomains: [development]
386
+
387
+ plugins:
388
+ roots: [plugins]
389
+ entries:
390
+ remote-review:
391
+ source: url
392
+ url: https://github.com/acme/review-plugin.git
393
+ ref: v1.2.0
394
+ published-research:
395
+ source: npm
396
+ package: '@acme/research-plugin'
397
+ version: 1.4.0
398
+
399
+ domains:
400
+ development:
401
+ description: Repository implementation tools.
402
+ plugins: [coding-tools]
403
+ review:
404
+ description: Focused review skills with a narrow MCP boundary.
405
+ plugins:
406
+ - name: remote-review
407
+ skills: [typescript]
408
+ agents: [reviewer]
409
+ hooks: false
410
+ mcp: true
411
+ mcp:
412
+ servers: [filesystem]
413
+ proxy: [github]
414
+
415
+ aliases:
416
+ work: [development, review]
417
+ ```
418
+
419
+ Here, `coding-tools` is discovered from `plugins/coding-tools`; its manifest name, or its
420
+ folder name when no manifest name exists, becomes the catalog ID. Local roots and entries
421
+ resolve beside the declaring file. Git and npm entries are cached in
422
+ `~/.pi/.doom/plugin-cache`; pin a Git SHA or exact package version when reproducibility
423
+ matters. Domains may load an entire plugin or select only its skills, agents, hooks, and MCP
424
+ configuration. The optional `mcp` mapping is an allowlist, not a request to start every server
425
+ in the repository.
426
+
427
+ Select one or more domains with `--domains development,review`, use an alias such as
428
+ `--domains work`, or switch them with `/domains`. `--no-domains` is useful when the right
429
+ amount of repository context is none.
430
+
431
+ ### `profiles.yaml`: choose a point of view
432
+
433
+ A profile directory becomes discoverable when it directly contains `profile.md`, `SOUL.md`,
434
+ or `AGENTS.md`. A root may be one profile or a container of direct-child profiles. The folder
435
+ name becomes the profile name; Doompi concatenates those three files in that order.
436
+
437
+ ```yaml
438
+ profiles:
439
+ roots: [personas]
440
+ entries:
441
+ release-writer:
442
+ persona: personas/release-writer
443
+ env:
444
+ BRAND: acme
445
+ TONE: concise
446
+ ```
447
+
448
+ With that config, `personas/release-writer/profile.md` is enough to discover
449
+ `release-writer`. The explicit entry is optional; use one when the profile needs another name,
450
+ an exact persona path, or string environment defaults. Explicit entries override discovered
451
+ folders. Already exported environment values win, so selecting a profile never quietly
452
+ replaces a value supplied by the caller.
453
+
454
+ Discovery never recurses. Persona paths must remain under `agents/` or a root declared in the
455
+ same file, and symlinks may not escape the persona boundary. Legacy profiles written directly
456
+ under `profiles` still load, but new configuration should use `roots` and `entries`.
457
+
458
+ Select a profile with `--profile release-writer` or switch it with `/profile`. Leaving the
459
+ catalog empty is valid; no profile remains a first-class choice.
460
+
461
+ ### Check the matrix before launch
462
+
463
+ The fastest configuration debugger is the one that does not start a model:
464
+
465
+ ```bash
466
+ doompi --major-mode copilot --domains work --profile release-writer --explain
467
+ dpi sync
468
+ doompi sync --check
469
+ ```
470
+
471
+ `--explain` prints the resolved mode, domains, profile, plugins, skills, agents, MCP boundary,
472
+ and estimated prompt cost. `dpi sync` resolves the repository configuration and synchronizes
473
+ DPI without registering it in normal Pi settings. `doompi sync --check` turns drift into a
474
+ non-zero exit code for CI. If the explanation is surprising, fix the YAML before paying a model
475
+ to be surprised with you.
@@ -1,2 +1,2 @@
1
- const e=require(`../../_virtual/_rolldown/runtime.cjs`),t=require(`../serialization/json.cjs`);require(`../../utils/index.cjs`);let n=require(`node:path`);n=e.__toESM(n,1);let r=require(`node:fs`);r=e.__toESM(r,1);let i=require(`node:os`),a=require(`node:child_process`),o=require(`node:timers/promises`),s=require(`cross-spawn`);s=e.__toESM(s,1);const c=[`SIGINT`,`SIGTERM`,`SIGHUP`,`SIGQUIT`],l=`owner.json`;function u(e,t,n,r){let i=(0,a.spawnSync)(e,t,{cwd:n,encoding:`utf8`,env:r});if(i.error)throw i.error;if(i.stderr&&process.stderr.write(i.stderr),i.status!==0)throw Error(`${e} exited with status ${i.status??1}`);return i.stdout.trim()}function d(e,t,n,r){let i=(0,a.spawnSync)(e,t,{cwd:n,env:r,stdio:`inherit`});if(i.error)throw i.error;if(i.status!==0)throw Error(`${e} exited with status ${i.status??1}`)}function f(e){if(!e)return 1;let t=i.constants.signals[e];return t?128+t:1}function p(e){let t=t=>{e.exitCode===null&&e.signalCode===null&&e.kill(t)};for(let e of c)process.on(e,t);return()=>{for(let e of c)process.removeListener(e,t)}}function m(e){return new Promise((t,n)=>{e.once(`error`,n),e.once(`exit`,(e,n)=>t(e??f(n)))})}async function h(e,t,n,r){let i=(0,s.default)(e,t,{cwd:n,env:r,stdio:`inherit`}),a=p(i);try{return await m(i)}finally{a()}}function g(e){return e instanceof Error&&typeof e.code==`string`}function _(e){let r=t.readJson(n.default.join(e,l));if(typeof r.pid!=`number`||!Number.isSafeInteger(r.pid)||r.pid<=0)return!1;try{return process.kill(r.pid,0),!0}catch(e){return!g(e)||e.code!==`ESRCH`}}async function v(e){r.default.mkdirSync(n.default.dirname(e),{recursive:!0});let i=Date.now();for(;;)try{await r.default.promises.mkdir(e);try{t.writeJson(n.default.join(e,l),{pid:process.pid})}catch(t){throw await r.default.promises.rm(e,{recursive:!0,force:!0}),t}return()=>r.default.promises.rm(e,{recursive:!0,force:!0})}catch(t){if(!g(t)||t.code!==`EEXIST`)throw t;try{let t=await r.default.promises.stat(e);if(Date.now()-t.mtimeMs>=1e4&&!_(e)){await r.default.promises.rm(e,{recursive:!0,force:!0});continue}}catch(e){if(g(e)&&e.code===`ENOENT`)continue;throw e}if(Date.now()-i>=3e4)throw Error(`Timed out waiting for Antigravity state lock: ${e}`);await(0,o.setTimeout)(25)}}function y(e,t){let r=n.default.relative(e,t);return r===``||!r.startsWith(`..${n.default.sep}`)&&r!==`..`&&!n.default.isAbsolute(r)}exports.acquireDirectoryLock=v,exports.forwardSignals=p,exports.isFileSystemError=g,exports.lockOwnerIsRunning=_,exports.pathInside=y,exports.runCaptured=u,exports.runChecked=d,exports.runInteractive=h,exports.signalExitCode=f,exports.waitForExit=m;
1
+ const e=require(`../../_virtual/_rolldown/runtime.cjs`),t=require(`../serialization/json.cjs`);require(`../../utils/index.cjs`);let n=require(`node:path`);n=e.__toESM(n,1);let r=require(`node:fs`);r=e.__toESM(r,1);let i=require(`node:child_process`),a=require(`node:os`),o=require(`node:timers/promises`),s=require(`cross-spawn`);s=e.__toESM(s,1);const c=[`SIGINT`,`SIGTERM`,`SIGHUP`,`SIGQUIT`],l=`owner.json`;function u(e,t,n,r){let a=(0,i.spawnSync)(e,t,{cwd:n,encoding:`utf8`,env:r});if(a.error)throw a.error;if(a.stderr&&process.stderr.write(a.stderr),a.status!==0)throw Error(`${e} exited with status ${a.status??1}`);return a.stdout.trim()}function d(e,t,n,r){let a=(0,i.spawnSync)(e,t,{cwd:n,env:r,stdio:`inherit`});if(a.error)throw a.error;if(a.status!==0)throw Error(`${e} exited with status ${a.status??1}`)}function f(e){if(!e)return 1;let t=a.constants.signals[e];return t?128+t:1}function p(e){let t=t=>{e.exitCode===null&&e.signalCode===null&&e.kill(t)};for(let e of c)process.on(e,t);return()=>{for(let e of c)process.removeListener(e,t)}}function m(e){return new Promise((t,n)=>{e.once(`error`,n),e.once(`exit`,(e,n)=>t(e??f(n)))})}async function h(e,t,n,r){let i=(0,s.default)(e,t,{cwd:n,env:r,stdio:`inherit`}),a=p(i);try{return await m(i)}finally{a()}}function g(e){return e instanceof Error&&typeof e.code==`string`}function _(e){let r=t.readJson(n.default.join(e,l));if(typeof r.pid!=`number`||!Number.isSafeInteger(r.pid)||r.pid<=0)return!1;try{return process.kill(r.pid,0),!0}catch(e){return!g(e)||e.code!==`ESRCH`}}async function v(e){r.default.mkdirSync(n.default.dirname(e),{recursive:!0});let i=Date.now();for(;;)try{await r.default.promises.mkdir(e);try{t.writeJson(n.default.join(e,l),{pid:process.pid})}catch(t){throw await r.default.promises.rm(e,{recursive:!0,force:!0}),t}return()=>r.default.promises.rm(e,{recursive:!0,force:!0})}catch(t){if(!g(t)||t.code!==`EEXIST`)throw t;try{let t=await r.default.promises.stat(e);if(Date.now()-t.mtimeMs>=1e4&&!_(e)){await r.default.promises.rm(e,{recursive:!0,force:!0});continue}}catch(e){if(g(e)&&e.code===`ENOENT`)continue;throw e}if(Date.now()-i>=3e4)throw Error(`Timed out waiting for Antigravity state lock: ${e}`);await(0,o.setTimeout)(25)}}function y(e,t){let r=n.default.relative(e,t);return r===``||!r.startsWith(`..${n.default.sep}`)&&r!==`..`&&!n.default.isAbsolute(r)}exports.acquireDirectoryLock=v,exports.forwardSignals=p,exports.isFileSystemError=g,exports.lockOwnerIsRunning=_,exports.pathInside=y,exports.runCaptured=u,exports.runChecked=d,exports.runInteractive=h,exports.signalExitCode=f,exports.waitForExit=m;
2
2
  //# sourceMappingURL=process.cjs.map
@@ -1,2 +1,2 @@
1
- import{readJson as e,writeJson as t}from"../serialization/json.mjs";import"../../utils/index.mjs";import n from"node:path";import r from"node:fs";import{constants as i}from"node:os";import{spawnSync as a}from"node:child_process";import{setTimeout as o}from"node:timers/promises";import s from"cross-spawn";const c=[`SIGINT`,`SIGTERM`,`SIGHUP`,`SIGQUIT`],l=`owner.json`;function u(e,t,n,r){let i=a(e,t,{cwd:n,encoding:`utf8`,env:r});if(i.error)throw i.error;if(i.stderr&&process.stderr.write(i.stderr),i.status!==0)throw Error(`${e} exited with status ${i.status??1}`);return i.stdout.trim()}function d(e,t,n,r){let i=a(e,t,{cwd:n,env:r,stdio:`inherit`});if(i.error)throw i.error;if(i.status!==0)throw Error(`${e} exited with status ${i.status??1}`)}function f(e){if(!e)return 1;let t=i.signals[e];return t?128+t:1}function p(e){let t=t=>{e.exitCode===null&&e.signalCode===null&&e.kill(t)};for(let e of c)process.on(e,t);return()=>{for(let e of c)process.removeListener(e,t)}}function m(e){return new Promise((t,n)=>{e.once(`error`,n),e.once(`exit`,(e,n)=>t(e??f(n)))})}async function h(e,t,n,r){let i=s(e,t,{cwd:n,env:r,stdio:`inherit`}),a=p(i);try{return await m(i)}finally{a()}}function g(e){return e instanceof Error&&typeof e.code==`string`}function _(t){let r=e(n.join(t,l));if(typeof r.pid!=`number`||!Number.isSafeInteger(r.pid)||r.pid<=0)return!1;try{return process.kill(r.pid,0),!0}catch(e){return!g(e)||e.code!==`ESRCH`}}async function v(e){r.mkdirSync(n.dirname(e),{recursive:!0});let i=Date.now();for(;;)try{await r.promises.mkdir(e);try{t(n.join(e,l),{pid:process.pid})}catch(t){throw await r.promises.rm(e,{recursive:!0,force:!0}),t}return()=>r.promises.rm(e,{recursive:!0,force:!0})}catch(t){if(!g(t)||t.code!==`EEXIST`)throw t;try{let t=await r.promises.stat(e);if(Date.now()-t.mtimeMs>=1e4&&!_(e)){await r.promises.rm(e,{recursive:!0,force:!0});continue}}catch(e){if(g(e)&&e.code===`ENOENT`)continue;throw e}if(Date.now()-i>=3e4)throw Error(`Timed out waiting for Antigravity state lock: ${e}`);await o(25)}}function y(e,t){let r=n.relative(e,t);return r===``||!r.startsWith(`..${n.sep}`)&&r!==`..`&&!n.isAbsolute(r)}export{v as acquireDirectoryLock,p as forwardSignals,g as isFileSystemError,_ as lockOwnerIsRunning,y as pathInside,u as runCaptured,d as runChecked,h as runInteractive,f as signalExitCode,m as waitForExit};
1
+ import{readJson as e,writeJson as t}from"../serialization/json.mjs";import"../../utils/index.mjs";import n from"node:path";import r from"node:fs";import{spawnSync as i}from"node:child_process";import{constants as a}from"node:os";import{setTimeout as o}from"node:timers/promises";import s from"cross-spawn";const c=[`SIGINT`,`SIGTERM`,`SIGHUP`,`SIGQUIT`],l=`owner.json`;function u(e,t,n,r){let a=i(e,t,{cwd:n,encoding:`utf8`,env:r});if(a.error)throw a.error;if(a.stderr&&process.stderr.write(a.stderr),a.status!==0)throw Error(`${e} exited with status ${a.status??1}`);return a.stdout.trim()}function d(e,t,n,r){let a=i(e,t,{cwd:n,env:r,stdio:`inherit`});if(a.error)throw a.error;if(a.status!==0)throw Error(`${e} exited with status ${a.status??1}`)}function f(e){if(!e)return 1;let t=a.signals[e];return t?128+t:1}function p(e){let t=t=>{e.exitCode===null&&e.signalCode===null&&e.kill(t)};for(let e of c)process.on(e,t);return()=>{for(let e of c)process.removeListener(e,t)}}function m(e){return new Promise((t,n)=>{e.once(`error`,n),e.once(`exit`,(e,n)=>t(e??f(n)))})}async function h(e,t,n,r){let i=s(e,t,{cwd:n,env:r,stdio:`inherit`}),a=p(i);try{return await m(i)}finally{a()}}function g(e){return e instanceof Error&&typeof e.code==`string`}function _(t){let r=e(n.join(t,l));if(typeof r.pid!=`number`||!Number.isSafeInteger(r.pid)||r.pid<=0)return!1;try{return process.kill(r.pid,0),!0}catch(e){return!g(e)||e.code!==`ESRCH`}}async function v(e){r.mkdirSync(n.dirname(e),{recursive:!0});let i=Date.now();for(;;)try{await r.promises.mkdir(e);try{t(n.join(e,l),{pid:process.pid})}catch(t){throw await r.promises.rm(e,{recursive:!0,force:!0}),t}return()=>r.promises.rm(e,{recursive:!0,force:!0})}catch(t){if(!g(t)||t.code!==`EEXIST`)throw t;try{let t=await r.promises.stat(e);if(Date.now()-t.mtimeMs>=1e4&&!_(e)){await r.promises.rm(e,{recursive:!0,force:!0});continue}}catch(e){if(g(e)&&e.code===`ENOENT`)continue;throw e}if(Date.now()-i>=3e4)throw Error(`Timed out waiting for Antigravity state lock: ${e}`);await o(25)}}function y(e,t){let r=n.relative(e,t);return r===``||!r.startsWith(`..${n.sep}`)&&r!==`..`&&!n.isAbsolute(r)}export{v as acquireDirectoryLock,p as forwardSignals,g as isFileSystemError,_ as lockOwnerIsRunning,y as pathInside,u as runCaptured,d as runChecked,h as runInteractive,f as signalExitCode,m as waitForExit};
2
2
  //# sourceMappingURL=process.mjs.map
@@ -1,2 +1,2 @@
1
- const e=require(`../_virtual/_rolldown/runtime.cjs`);require(`../services/config/index.cjs`);const t=require(`./mcpFilter.cjs`),n=require(`./resourceCollector.cjs`);let r=require(`node:path`);r=e.__toESM(r,1);let i=require(`node:fs`);i=e.__toESM(i,1);let a=require(`node:os`);a=e.__toESM(a,1);let o=require(`@agimon-ai/doompi-config/majorModes`),s=require(`@agimon-ai/doompi-config/profiles`),c=require(`@agimon-ai/doompi-config/domains`),l=require(`@agimon-ai/doompi-config/harnessState`);const u=`.mcp.json`;function d(e,t){let n=[r.default.join(e,u)];for(let e of t){if(e.mcp===!1)continue;let t=r.default.join(e.directory,u);i.default.existsSync(t)&&n.push(t)}return n}function f(e,n){let i=(e.mcpServers??{})[t.PROXY_SERVER_NAME],a=Array.isArray(i?.args)?i.args.map(String):[],o=a.indexOf(`--config`),s=o===-1?void 0:a[o+1];return s?r.default.resolve(n,s):r.default.join(n,`mcp-config.yaml`)}async function p(e,a,o,s){let c=await t.applyMcpAllowlist(n.mergeMcpConfigs(d(e,a)),o,e,s),l=r.default.join(s,`mcp.json`);return await i.default.promises.writeFile(l,`${JSON.stringify(c,null,2)}\n`,{mode:384}),{mcpConfigPath:l,proxyConfigPath:f(c,e)}}async function m(e){let n=(0,o.loadMajorModesConfig)(e.repoRoot),u=(0,o.resolveLayers)(n,e.majorMode),d=(0,o.layerHookGroups)(n,u),f=await i.default.promises.mkdtemp(r.default.join(a.default.tmpdir(),`doom-pi-compat-`));await i.default.promises.chmod(f,448);try{let n=e.profile?(0,s.resolveProfile)(e.repoRoot,e.profile):void 0,a=(0,c.resolvePluginEntries)(e.repoRoot,e.domains,[]),o=t.resolveMcpAllowlist(e.repoRoot,e.domains),m=await p(e.repoRoot,a,o,f),h={...process.env};h.NX_DAEMON??=`false`;let g=(0,s.applyProfileEnvironment)(h,n?.env??{}),_=n?.persona?(0,s.buildPersonaPrompt)(n.personaRoot,n.persona):void 0,v;return _&&(v=r.default.join(f,`persona.md`),await i.default.promises.writeFile(v,`${_}\n`,{mode:384})),(0,l.projectHarnessEnvironment)({root:e.repoRoot,majorMode:e.majorMode,temporaryDirectory:f,domains:e.domains,layers:u,profile:n?.name,profileEnvironment:g,hookGroups:d,mcpConfigPath:m.mcpConfigPath,personaFile:v,additionalDirectories:e.additionalDirectories,hooks:!0},h),h.DOOMPI_ADDITIONAL_DIRS=e.additionalDirectories.join(r.default.delimiter),h.CLAUDE_PROJECT_DIR=e.repoRoot,h.CODEX_REPO_ROOT=e.repoRoot,h.AGY_REPO_ROOT=e.repoRoot,h.ORIGINAL_REPO_PATH||=e.repoRoot,{options:e,environment:h,plugins:a,profile:n,personaFile:v,mcpAllowlist:o,mcpConfigPath:m.mcpConfigPath,proxyConfigPath:m.proxyConfigPath,selectedLayers:u,hookGroups:d,sharedSkills:(0,c.resolveSharedSkills)(e.repoRoot,e.domains),cleanup:()=>i.default.promises.rm(f,{recursive:!0,force:!0})}}catch(e){throw await i.default.promises.rm(f,{recursive:!0,force:!0}),e}}exports.buildCompatibilityContext=m;
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`);require(`../services/config/index.cjs`);const t=require(`./mcpFilter.cjs`),n=require(`./pluginMaterializer.cjs`),r=require(`./resourceCollector.cjs`);let i=require(`node:path`);i=e.__toESM(i,1);let a=require(`node:fs`);a=e.__toESM(a,1);let o=require(`node:os`);o=e.__toESM(o,1);let s=require(`@agimon-ai/doompi-config/majorModes`),c=require(`@agimon-ai/doompi-config/profiles`),l=require(`@agimon-ai/doompi-config/domains`),u=require(`@agimon-ai/doompi-config/harnessState`);const d=`.mcp.json`;function f(e,t){let n=[i.default.join(e,d)];for(let e of t){if(e.mcp===!1)continue;let t=i.default.join(e.directory,d);a.default.existsSync(t)&&n.push(t)}return n}function p(e,n){let r=(e.mcpServers??{})[t.PROXY_SERVER_NAME],a=Array.isArray(r?.args)?r.args.map(String):[],o=a.indexOf(`--config`),s=o===-1?void 0:a[o+1];return s?i.default.resolve(n,s):i.default.join(n,`mcp-config.yaml`)}async function m(e,n,o,s){let c=await t.applyMcpAllowlist(r.mergeMcpConfigs(f(e,n)),o,e,s),l=i.default.join(s,`mcp.json`);return await a.default.promises.writeFile(l,`${JSON.stringify(c,null,2)}\n`,{mode:384}),{mcpConfigPath:l,proxyConfigPath:p(c,e)}}async function h(e){let r=(0,s.loadMajorModesConfig)(e.repoRoot),d=(0,s.resolveLayers)(r,e.majorMode),f=(0,s.layerHookGroups)(r,d),p=await a.default.promises.mkdtemp(i.default.join(o.default.tmpdir(),`doom-pi-compat-`));await a.default.promises.chmod(p,448);try{let r=e.profile?(0,c.resolveProfile)(e.repoRoot,e.profile):void 0,o=await n.materializePluginEntries((0,l.resolvePluginEntries)(e.repoRoot,e.domains,[])),s=t.resolveMcpAllowlist(e.repoRoot,e.domains),h=await m(e.repoRoot,o,s,p),g={...process.env};g.NX_DAEMON??=`false`;let _=(0,c.applyProfileEnvironment)(g,r?.env??{}),v=r?.persona?(0,c.buildPersonaPrompt)(r.personaRoot,r.persona):void 0,y;return v&&(y=i.default.join(p,`persona.md`),await a.default.promises.writeFile(y,`${v}\n`,{mode:384})),(0,u.projectHarnessEnvironment)({root:e.repoRoot,majorMode:e.majorMode,temporaryDirectory:p,domains:e.domains,layers:d,profile:r?.name,profileEnvironment:_,hookGroups:f,mcpConfigPath:h.mcpConfigPath,personaFile:y,additionalDirectories:e.additionalDirectories,hooks:!0},g),g.DOOMPI_ADDITIONAL_DIRS=e.additionalDirectories.join(i.default.delimiter),g.CLAUDE_PROJECT_DIR=e.repoRoot,g.CODEX_REPO_ROOT=e.repoRoot,g.AGY_REPO_ROOT=e.repoRoot,g.ORIGINAL_REPO_PATH||=e.repoRoot,{options:e,environment:g,plugins:o,profile:r,personaFile:y,mcpAllowlist:s,mcpConfigPath:h.mcpConfigPath,proxyConfigPath:h.proxyConfigPath,selectedLayers:d,hookGroups:f,sharedSkills:(0,l.resolveSharedSkills)(e.repoRoot,e.domains),cleanup:()=>a.default.promises.rm(p,{recursive:!0,force:!0})}}catch(e){throw await a.default.promises.rm(p,{recursive:!0,force:!0}),e}}exports.buildCompatibilityContext=h;
2
2
  //# sourceMappingURL=compatibilityContext.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"compatibilityContext.cjs","names":["path","fs","PROXY_SERVER_NAME","applyMcpAllowlist","mergeMcpConfigs","os","resolveMcpAllowlist"],"sources":["../../src/adapters/compatibilityContext.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { CompatibilityOptions } from '../types/interfaces/index.ts';\nimport {\n type AgentProfile,\n applyProfileEnvironment,\n buildPersonaPrompt,\n type DomainMcpAllowlist,\n layerHookGroups,\n loadMajorModesConfig,\n type PluginEntry,\n projectHarnessEnvironment,\n resolveLayers,\n resolvePluginEntries,\n resolveProfile,\n resolveSharedSkills,\n} from '../services/config/index.ts';\nimport { applyMcpAllowlist, PROXY_SERVER_NAME, resolveMcpAllowlist } from './mcpFilter.ts';\nimport { mergeMcpConfigs } from './resourceCollector.ts';\n\ntype JsonObject = Record<string, unknown>;\n\nconst MCP_CONFIG_FILENAME = '.mcp.json';\nconst GENERATED_MCP_CONFIG_FILENAME = 'mcp.json';\nconst PROXY_CONFIG_FILENAME = 'mcp-config.yaml';\nconst PERSONA_FILENAME = 'persona.md';\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst CONFIG_OPTION = '--config';\nconst TEMPORARY_DIRECTORY_PREFIX = 'doom-pi-compat-';\nconst ADDITIONAL_DIRS_ENV = 'DOOMPI_ADDITIONAL_DIRS';\nconst CLAUDE_PROJECT_DIR_ENV = 'CLAUDE_PROJECT_DIR';\nconst CODEX_REPO_ROOT_ENV = 'CODEX_REPO_ROOT';\nconst AGY_REPO_ROOT_ENV = 'AGY_REPO_ROOT';\nconst ORIGINAL_REPO_PATH_ENV = 'ORIGINAL_REPO_PATH';\n\nexport interface CompatibilityContext {\n options: CompatibilityOptions;\n environment: NodeJS.ProcessEnv;\n plugins: PluginEntry[];\n profile?: AgentProfile;\n personaFile?: string;\n mcpAllowlist?: DomainMcpAllowlist;\n mcpConfigPath: string;\n proxyConfigPath: string;\n selectedLayers: string[];\n hookGroups: string[];\n sharedSkills: boolean;\n cleanup(): Promise<void>;\n}\n\nfunction pluginMcpPaths(repoRoot: string, plugins: PluginEntry[]): string[] {\n const paths = [path.join(repoRoot, MCP_CONFIG_FILENAME)];\n for (const plugin of plugins) {\n if (plugin.mcp === false) continue;\n const configPath = path.join(plugin.directory, MCP_CONFIG_FILENAME);\n if (fs.existsSync(configPath)) paths.push(configPath);\n }\n return paths;\n}\n\nfunction resolveProxyConfigPath(config: JsonObject, repoRoot: string): string {\n const servers = (config.mcpServers ?? {}) as Record<string, JsonObject>;\n const proxy = servers[PROXY_SERVER_NAME];\n const args = Array.isArray(proxy?.args) ? proxy.args.map(String) : [];\n const configIndex = args.indexOf(CONFIG_OPTION);\n const selected = configIndex === -1 ? undefined : args[configIndex + 1];\n return selected ? path.resolve(repoRoot, selected) : path.join(repoRoot, PROXY_CONFIG_FILENAME);\n}\n\nasync function writeCompatibilityMcpConfig(\n repoRoot: string,\n plugins: PluginEntry[],\n allowlist: DomainMcpAllowlist | undefined,\n temporaryDirectory: string,\n): Promise<{ mcpConfigPath: string; proxyConfigPath: string }> {\n const config = await applyMcpAllowlist(\n mergeMcpConfigs(pluginMcpPaths(repoRoot, plugins)),\n allowlist,\n repoRoot,\n temporaryDirectory,\n );\n const mcpConfigPath = path.join(temporaryDirectory, GENERATED_MCP_CONFIG_FILENAME);\n await fs.promises.writeFile(mcpConfigPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: PRIVATE_FILE_MODE });\n return { mcpConfigPath, proxyConfigPath: resolveProxyConfigPath(config, repoRoot) };\n}\n\n/** Resolves only the resources shared by Pi and compatibility frontends. */\nexport async function buildCompatibilityContext(options: CompatibilityOptions): Promise<CompatibilityContext> {\n const majorModesConfig = loadMajorModesConfig(options.repoRoot);\n const selectedLayers = resolveLayers(majorModesConfig, options.majorMode);\n const hookGroups = layerHookGroups(majorModesConfig, selectedLayers);\n const temporaryDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), TEMPORARY_DIRECTORY_PREFIX));\n await fs.promises.chmod(temporaryDirectory, PRIVATE_DIRECTORY_MODE);\n\n try {\n const profile = options.profile ? resolveProfile(options.repoRoot, options.profile) : undefined;\n const plugins = resolvePluginEntries(options.repoRoot, options.domains, []);\n const mcpAllowlist = resolveMcpAllowlist(options.repoRoot, options.domains);\n const mcp = await writeCompatibilityMcpConfig(options.repoRoot, plugins, mcpAllowlist, temporaryDirectory);\n const environment = { ...process.env };\n environment.NX_DAEMON ??= 'false';\n const profileEnvironment = applyProfileEnvironment(environment, profile?.env ?? {});\n const personaPrompt = profile?.persona ? buildPersonaPrompt(profile.personaRoot, profile.persona) : undefined;\n let personaFile: string | undefined;\n\n if (personaPrompt) {\n personaFile = path.join(temporaryDirectory, PERSONA_FILENAME);\n await fs.promises.writeFile(personaFile, `${personaPrompt}\\n`, { mode: PRIVATE_FILE_MODE });\n }\n\n // Projection only, with no state file: Claude, Codex and Antigravity read\n // an environment and never the store.\n projectHarnessEnvironment(\n {\n root: options.repoRoot,\n majorMode: options.majorMode,\n temporaryDirectory,\n domains: options.domains,\n layers: selectedLayers,\n profile: profile?.name,\n profileEnvironment,\n hookGroups,\n mcpConfigPath: mcp.mcpConfigPath,\n personaFile,\n additionalDirectories: options.additionalDirectories,\n hooks: true,\n },\n environment,\n );\n environment[ADDITIONAL_DIRS_ENV] = options.additionalDirectories.join(path.delimiter);\n environment[CLAUDE_PROJECT_DIR_ENV] = options.repoRoot;\n environment[CODEX_REPO_ROOT_ENV] = options.repoRoot;\n environment[AGY_REPO_ROOT_ENV] = options.repoRoot;\n environment[ORIGINAL_REPO_PATH_ENV] ||= options.repoRoot;\n\n return {\n options,\n environment,\n plugins,\n profile,\n personaFile,\n mcpAllowlist,\n mcpConfigPath: mcp.mcpConfigPath,\n proxyConfigPath: mcp.proxyConfigPath,\n selectedLayers,\n hookGroups,\n sharedSkills: resolveSharedSkills(options.repoRoot, options.domains),\n cleanup: () => fs.promises.rm(temporaryDirectory, { recursive: true, force: true }),\n };\n } catch (error) {\n await fs.promises.rm(temporaryDirectory, { recursive: true, force: true });\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"compatibilityContext.cjs","names":["path","fs","PROXY_SERVER_NAME","applyMcpAllowlist","mergeMcpConfigs","os","materializePluginEntries","resolveMcpAllowlist"],"sources":["../../src/adapters/compatibilityContext.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport {\n type AgentProfile,\n applyProfileEnvironment,\n buildPersonaPrompt,\n type DomainMcpAllowlist,\n layerHookGroups,\n loadMajorModesConfig,\n type PluginEntry,\n projectHarnessEnvironment,\n resolveLayers,\n resolvePluginEntries,\n resolveProfile,\n resolveSharedSkills,\n} from '../services/config/index.ts';\nimport type { CompatibilityOptions } from '../types/interfaces/index.ts';\nimport { applyMcpAllowlist, PROXY_SERVER_NAME, resolveMcpAllowlist } from './mcpFilter.ts';\nimport { materializePluginEntries } from './pluginMaterializer.ts';\nimport { mergeMcpConfigs } from './resourceCollector.ts';\n\ntype JsonObject = Record<string, unknown>;\n\nconst MCP_CONFIG_FILENAME = '.mcp.json';\nconst GENERATED_MCP_CONFIG_FILENAME = 'mcp.json';\nconst PROXY_CONFIG_FILENAME = 'mcp-config.yaml';\nconst PERSONA_FILENAME = 'persona.md';\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst CONFIG_OPTION = '--config';\nconst TEMPORARY_DIRECTORY_PREFIX = 'doom-pi-compat-';\nconst ADDITIONAL_DIRS_ENV = 'DOOMPI_ADDITIONAL_DIRS';\nconst CLAUDE_PROJECT_DIR_ENV = 'CLAUDE_PROJECT_DIR';\nconst CODEX_REPO_ROOT_ENV = 'CODEX_REPO_ROOT';\nconst AGY_REPO_ROOT_ENV = 'AGY_REPO_ROOT';\nconst ORIGINAL_REPO_PATH_ENV = 'ORIGINAL_REPO_PATH';\n\nexport interface CompatibilityContext {\n options: CompatibilityOptions;\n environment: NodeJS.ProcessEnv;\n plugins: PluginEntry[];\n profile?: AgentProfile;\n personaFile?: string;\n mcpAllowlist?: DomainMcpAllowlist;\n mcpConfigPath: string;\n proxyConfigPath: string;\n selectedLayers: string[];\n hookGroups: string[];\n sharedSkills: boolean;\n cleanup(): Promise<void>;\n}\n\nfunction pluginMcpPaths(repoRoot: string, plugins: PluginEntry[]): string[] {\n const paths = [path.join(repoRoot, MCP_CONFIG_FILENAME)];\n for (const plugin of plugins) {\n if (plugin.mcp === false) continue;\n const configPath = path.join(plugin.directory, MCP_CONFIG_FILENAME);\n if (fs.existsSync(configPath)) paths.push(configPath);\n }\n return paths;\n}\n\nfunction resolveProxyConfigPath(config: JsonObject, repoRoot: string): string {\n const servers = (config.mcpServers ?? {}) as Record<string, JsonObject>;\n const proxy = servers[PROXY_SERVER_NAME];\n const args = Array.isArray(proxy?.args) ? proxy.args.map(String) : [];\n const configIndex = args.indexOf(CONFIG_OPTION);\n const selected = configIndex === -1 ? undefined : args[configIndex + 1];\n return selected ? path.resolve(repoRoot, selected) : path.join(repoRoot, PROXY_CONFIG_FILENAME);\n}\n\nasync function writeCompatibilityMcpConfig(\n repoRoot: string,\n plugins: PluginEntry[],\n allowlist: DomainMcpAllowlist | undefined,\n temporaryDirectory: string,\n): Promise<{ mcpConfigPath: string; proxyConfigPath: string }> {\n const config = await applyMcpAllowlist(\n mergeMcpConfigs(pluginMcpPaths(repoRoot, plugins)),\n allowlist,\n repoRoot,\n temporaryDirectory,\n );\n const mcpConfigPath = path.join(temporaryDirectory, GENERATED_MCP_CONFIG_FILENAME);\n await fs.promises.writeFile(mcpConfigPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: PRIVATE_FILE_MODE });\n return { mcpConfigPath, proxyConfigPath: resolveProxyConfigPath(config, repoRoot) };\n}\n\n/** Resolves only the resources shared by Pi and compatibility frontends. */\nexport async function buildCompatibilityContext(options: CompatibilityOptions): Promise<CompatibilityContext> {\n const majorModesConfig = loadMajorModesConfig(options.repoRoot);\n const selectedLayers = resolveLayers(majorModesConfig, options.majorMode);\n const hookGroups = layerHookGroups(majorModesConfig, selectedLayers);\n const temporaryDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), TEMPORARY_DIRECTORY_PREFIX));\n await fs.promises.chmod(temporaryDirectory, PRIVATE_DIRECTORY_MODE);\n\n try {\n const profile = options.profile ? resolveProfile(options.repoRoot, options.profile) : undefined;\n const plugins = await materializePluginEntries(resolvePluginEntries(options.repoRoot, options.domains, []));\n const mcpAllowlist = resolveMcpAllowlist(options.repoRoot, options.domains);\n const mcp = await writeCompatibilityMcpConfig(options.repoRoot, plugins, mcpAllowlist, temporaryDirectory);\n const environment = { ...process.env };\n environment.NX_DAEMON ??= 'false';\n const profileEnvironment = applyProfileEnvironment(environment, profile?.env ?? {});\n const personaPrompt = profile?.persona ? buildPersonaPrompt(profile.personaRoot, profile.persona) : undefined;\n let personaFile: string | undefined;\n\n if (personaPrompt) {\n personaFile = path.join(temporaryDirectory, PERSONA_FILENAME);\n await fs.promises.writeFile(personaFile, `${personaPrompt}\\n`, { mode: PRIVATE_FILE_MODE });\n }\n\n // Projection only, with no state file: Claude, Codex and Antigravity read\n // an environment and never the store.\n projectHarnessEnvironment(\n {\n root: options.repoRoot,\n majorMode: options.majorMode,\n temporaryDirectory,\n domains: options.domains,\n layers: selectedLayers,\n profile: profile?.name,\n profileEnvironment,\n hookGroups,\n mcpConfigPath: mcp.mcpConfigPath,\n personaFile,\n additionalDirectories: options.additionalDirectories,\n hooks: true,\n },\n environment,\n );\n environment[ADDITIONAL_DIRS_ENV] = options.additionalDirectories.join(path.delimiter);\n environment[CLAUDE_PROJECT_DIR_ENV] = options.repoRoot;\n environment[CODEX_REPO_ROOT_ENV] = options.repoRoot;\n environment[AGY_REPO_ROOT_ENV] = options.repoRoot;\n environment[ORIGINAL_REPO_PATH_ENV] ||= options.repoRoot;\n\n return {\n options,\n environment,\n plugins,\n profile,\n personaFile,\n mcpAllowlist,\n mcpConfigPath: mcp.mcpConfigPath,\n proxyConfigPath: mcp.proxyConfigPath,\n selectedLayers,\n hookGroups,\n sharedSkills: resolveSharedSkills(options.repoRoot, options.domains),\n cleanup: () => fs.promises.rm(temporaryDirectory, { recursive: true, force: true }),\n };\n } catch (error) {\n await fs.promises.rm(temporaryDirectory, { recursive: true, force: true });\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compatibilityContext.d.cts","names":[],"sources":["../../src/adapters/compatibilityContext.ts"],"mappings":";;;;UAqCiB,oBAAA;EACf,OAAA,EAAS,oBAAA;EACT,WAAA,EAAa,MAAA,CAAO,UAAA;EACpB,OAAA,EAAS,WAAA;EACT,OAAA,GAAU,YAAA;EACV,WAAA;EACA,YAAA,GAAe,kBAAA;EACf,aAAA;EACA,eAAA;EACA,cAAA;EACA,UAAA;EACA,YAAA;EACA,OAAA,IAAW,OAAA;AAAA;;iBAwCS,yBAAA,CAA0B,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,oBAAA"}
1
+ {"version":3,"file":"compatibilityContext.d.cts","names":[],"sources":["../../src/adapters/compatibilityContext.ts"],"mappings":";;;;UAsCiB,oBAAA;EACf,OAAA,EAAS,oBAAA;EACT,WAAA,EAAa,MAAA,CAAO,UAAA;EACpB,OAAA,EAAS,WAAA;EACT,OAAA,GAAU,YAAA;EACV,WAAA;EACA,YAAA,GAAe,kBAAA;EACf,aAAA;EACA,eAAA;EACA,cAAA;EACA,UAAA;EACA,YAAA;EACA,OAAA,IAAW,OAAA;AAAA;;iBAwCS,yBAAA,CAA0B,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,oBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"compatibilityContext.d.mts","names":[],"sources":["../../src/adapters/compatibilityContext.ts"],"mappings":";;;;UAqCiB,oBAAA;EACf,OAAA,EAAS,oBAAA;EACT,WAAA,EAAa,MAAA,CAAO,UAAA;EACpB,OAAA,EAAS,WAAA;EACT,OAAA,GAAU,YAAA;EACV,WAAA;EACA,YAAA,GAAe,kBAAA;EACf,aAAA;EACA,eAAA;EACA,cAAA;EACA,UAAA;EACA,YAAA;EACA,OAAA,IAAW,OAAA;AAAA;;iBAwCS,yBAAA,CAA0B,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,oBAAA"}
1
+ {"version":3,"file":"compatibilityContext.d.mts","names":[],"sources":["../../src/adapters/compatibilityContext.ts"],"mappings":";;;;UAsCiB,oBAAA;EACf,OAAA,EAAS,oBAAA;EACT,WAAA,EAAa,MAAA,CAAO,UAAA;EACpB,OAAA,EAAS,WAAA;EACT,OAAA,GAAU,YAAA;EACV,WAAA;EACA,YAAA,GAAe,kBAAA;EACf,aAAA;EACA,eAAA;EACA,cAAA;EACA,UAAA;EACA,YAAA;EACA,OAAA,IAAW,OAAA;AAAA;;iBAwCS,yBAAA,CAA0B,OAAA,EAAS,oBAAA,GAAuB,OAAA,CAAQ,oBAAA"}
@@ -1,2 +1,2 @@
1
- import{projectHarnessEnvironment as e}from"./config/harnessState.mjs";import{applyProfileEnvironment as t,buildPersonaPrompt as n,layerHookGroups as r,loadMajorModesConfig as i,resolveLayers as a,resolvePluginEntries as o,resolveProfile as s,resolveSharedSkills as c}from"../services/config/index.mjs";import{PROXY_SERVER_NAME as l,applyMcpAllowlist as u,resolveMcpAllowlist as d}from"./mcpFilter.mjs";import{mergeMcpConfigs as f}from"./resourceCollector.mjs";import p from"node:path";import m from"node:fs";import h from"node:os";const g=`.mcp.json`;function _(e,t){let n=[p.join(e,g)];for(let e of t){if(e.mcp===!1)continue;let t=p.join(e.directory,g);m.existsSync(t)&&n.push(t)}return n}function v(e,t){let n=(e.mcpServers??{})[l],r=Array.isArray(n?.args)?n.args.map(String):[],i=r.indexOf(`--config`),a=i===-1?void 0:r[i+1];return a?p.resolve(t,a):p.join(t,`mcp-config.yaml`)}async function y(e,t,n,r){let i=await u(f(_(e,t)),n,e,r),a=p.join(r,`mcp.json`);return await m.promises.writeFile(a,`${JSON.stringify(i,null,2)}\n`,{mode:384}),{mcpConfigPath:a,proxyConfigPath:v(i,e)}}async function b(l){let u=i(l.repoRoot),f=a(u,l.majorMode),g=r(u,f),_=await m.promises.mkdtemp(p.join(h.tmpdir(),`doom-pi-compat-`));await m.promises.chmod(_,448);try{let r=l.profile?s(l.repoRoot,l.profile):void 0,i=o(l.repoRoot,l.domains,[]),a=d(l.repoRoot,l.domains),u=await y(l.repoRoot,i,a,_),h={...process.env};h.NX_DAEMON??=`false`;let v=t(h,r?.env??{}),b=r?.persona?n(r.personaRoot,r.persona):void 0,x;return b&&(x=p.join(_,`persona.md`),await m.promises.writeFile(x,`${b}\n`,{mode:384})),e({root:l.repoRoot,majorMode:l.majorMode,temporaryDirectory:_,domains:l.domains,layers:f,profile:r?.name,profileEnvironment:v,hookGroups:g,mcpConfigPath:u.mcpConfigPath,personaFile:x,additionalDirectories:l.additionalDirectories,hooks:!0},h),h.DOOMPI_ADDITIONAL_DIRS=l.additionalDirectories.join(p.delimiter),h.CLAUDE_PROJECT_DIR=l.repoRoot,h.CODEX_REPO_ROOT=l.repoRoot,h.AGY_REPO_ROOT=l.repoRoot,h.ORIGINAL_REPO_PATH||=l.repoRoot,{options:l,environment:h,plugins:i,profile:r,personaFile:x,mcpAllowlist:a,mcpConfigPath:u.mcpConfigPath,proxyConfigPath:u.proxyConfigPath,selectedLayers:f,hookGroups:g,sharedSkills:c(l.repoRoot,l.domains),cleanup:()=>m.promises.rm(_,{recursive:!0,force:!0})}}catch(e){throw await m.promises.rm(_,{recursive:!0,force:!0}),e}}export{b as buildCompatibilityContext};
1
+ import{projectHarnessEnvironment as e}from"./config/harnessState.mjs";import{applyProfileEnvironment as t,buildPersonaPrompt as n,layerHookGroups as r,loadMajorModesConfig as i,resolveLayers as a,resolvePluginEntries as o,resolveProfile as s,resolveSharedSkills as c}from"../services/config/index.mjs";import{PROXY_SERVER_NAME as l,applyMcpAllowlist as u,resolveMcpAllowlist as d}from"./mcpFilter.mjs";import{materializePluginEntries as f}from"./pluginMaterializer.mjs";import{mergeMcpConfigs as p}from"./resourceCollector.mjs";import m from"node:path";import h from"node:fs";import g from"node:os";const _=`.mcp.json`;function v(e,t){let n=[m.join(e,_)];for(let e of t){if(e.mcp===!1)continue;let t=m.join(e.directory,_);h.existsSync(t)&&n.push(t)}return n}function y(e,t){let n=(e.mcpServers??{})[l],r=Array.isArray(n?.args)?n.args.map(String):[],i=r.indexOf(`--config`),a=i===-1?void 0:r[i+1];return a?m.resolve(t,a):m.join(t,`mcp-config.yaml`)}async function b(e,t,n,r){let i=await u(p(v(e,t)),n,e,r),a=m.join(r,`mcp.json`);return await h.promises.writeFile(a,`${JSON.stringify(i,null,2)}\n`,{mode:384}),{mcpConfigPath:a,proxyConfigPath:y(i,e)}}async function x(l){let u=i(l.repoRoot),p=a(u,l.majorMode),_=r(u,p),v=await h.promises.mkdtemp(m.join(g.tmpdir(),`doom-pi-compat-`));await h.promises.chmod(v,448);try{let r=l.profile?s(l.repoRoot,l.profile):void 0,i=await f(o(l.repoRoot,l.domains,[])),a=d(l.repoRoot,l.domains),u=await b(l.repoRoot,i,a,v),g={...process.env};g.NX_DAEMON??=`false`;let y=t(g,r?.env??{}),x=r?.persona?n(r.personaRoot,r.persona):void 0,S;return x&&(S=m.join(v,`persona.md`),await h.promises.writeFile(S,`${x}\n`,{mode:384})),e({root:l.repoRoot,majorMode:l.majorMode,temporaryDirectory:v,domains:l.domains,layers:p,profile:r?.name,profileEnvironment:y,hookGroups:_,mcpConfigPath:u.mcpConfigPath,personaFile:S,additionalDirectories:l.additionalDirectories,hooks:!0},g),g.DOOMPI_ADDITIONAL_DIRS=l.additionalDirectories.join(m.delimiter),g.CLAUDE_PROJECT_DIR=l.repoRoot,g.CODEX_REPO_ROOT=l.repoRoot,g.AGY_REPO_ROOT=l.repoRoot,g.ORIGINAL_REPO_PATH||=l.repoRoot,{options:l,environment:g,plugins:i,profile:r,personaFile:S,mcpAllowlist:a,mcpConfigPath:u.mcpConfigPath,proxyConfigPath:u.proxyConfigPath,selectedLayers:p,hookGroups:_,sharedSkills:c(l.repoRoot,l.domains),cleanup:()=>h.promises.rm(v,{recursive:!0,force:!0})}}catch(e){throw await h.promises.rm(v,{recursive:!0,force:!0}),e}}export{x as buildCompatibilityContext};
2
2
  //# sourceMappingURL=compatibilityContext.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"compatibilityContext.mjs","names":[],"sources":["../../src/adapters/compatibilityContext.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { CompatibilityOptions } from '../types/interfaces/index.ts';\nimport {\n type AgentProfile,\n applyProfileEnvironment,\n buildPersonaPrompt,\n type DomainMcpAllowlist,\n layerHookGroups,\n loadMajorModesConfig,\n type PluginEntry,\n projectHarnessEnvironment,\n resolveLayers,\n resolvePluginEntries,\n resolveProfile,\n resolveSharedSkills,\n} from '../services/config/index.ts';\nimport { applyMcpAllowlist, PROXY_SERVER_NAME, resolveMcpAllowlist } from './mcpFilter.ts';\nimport { mergeMcpConfigs } from './resourceCollector.ts';\n\ntype JsonObject = Record<string, unknown>;\n\nconst MCP_CONFIG_FILENAME = '.mcp.json';\nconst GENERATED_MCP_CONFIG_FILENAME = 'mcp.json';\nconst PROXY_CONFIG_FILENAME = 'mcp-config.yaml';\nconst PERSONA_FILENAME = 'persona.md';\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst CONFIG_OPTION = '--config';\nconst TEMPORARY_DIRECTORY_PREFIX = 'doom-pi-compat-';\nconst ADDITIONAL_DIRS_ENV = 'DOOMPI_ADDITIONAL_DIRS';\nconst CLAUDE_PROJECT_DIR_ENV = 'CLAUDE_PROJECT_DIR';\nconst CODEX_REPO_ROOT_ENV = 'CODEX_REPO_ROOT';\nconst AGY_REPO_ROOT_ENV = 'AGY_REPO_ROOT';\nconst ORIGINAL_REPO_PATH_ENV = 'ORIGINAL_REPO_PATH';\n\nexport interface CompatibilityContext {\n options: CompatibilityOptions;\n environment: NodeJS.ProcessEnv;\n plugins: PluginEntry[];\n profile?: AgentProfile;\n personaFile?: string;\n mcpAllowlist?: DomainMcpAllowlist;\n mcpConfigPath: string;\n proxyConfigPath: string;\n selectedLayers: string[];\n hookGroups: string[];\n sharedSkills: boolean;\n cleanup(): Promise<void>;\n}\n\nfunction pluginMcpPaths(repoRoot: string, plugins: PluginEntry[]): string[] {\n const paths = [path.join(repoRoot, MCP_CONFIG_FILENAME)];\n for (const plugin of plugins) {\n if (plugin.mcp === false) continue;\n const configPath = path.join(plugin.directory, MCP_CONFIG_FILENAME);\n if (fs.existsSync(configPath)) paths.push(configPath);\n }\n return paths;\n}\n\nfunction resolveProxyConfigPath(config: JsonObject, repoRoot: string): string {\n const servers = (config.mcpServers ?? {}) as Record<string, JsonObject>;\n const proxy = servers[PROXY_SERVER_NAME];\n const args = Array.isArray(proxy?.args) ? proxy.args.map(String) : [];\n const configIndex = args.indexOf(CONFIG_OPTION);\n const selected = configIndex === -1 ? undefined : args[configIndex + 1];\n return selected ? path.resolve(repoRoot, selected) : path.join(repoRoot, PROXY_CONFIG_FILENAME);\n}\n\nasync function writeCompatibilityMcpConfig(\n repoRoot: string,\n plugins: PluginEntry[],\n allowlist: DomainMcpAllowlist | undefined,\n temporaryDirectory: string,\n): Promise<{ mcpConfigPath: string; proxyConfigPath: string }> {\n const config = await applyMcpAllowlist(\n mergeMcpConfigs(pluginMcpPaths(repoRoot, plugins)),\n allowlist,\n repoRoot,\n temporaryDirectory,\n );\n const mcpConfigPath = path.join(temporaryDirectory, GENERATED_MCP_CONFIG_FILENAME);\n await fs.promises.writeFile(mcpConfigPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: PRIVATE_FILE_MODE });\n return { mcpConfigPath, proxyConfigPath: resolveProxyConfigPath(config, repoRoot) };\n}\n\n/** Resolves only the resources shared by Pi and compatibility frontends. */\nexport async function buildCompatibilityContext(options: CompatibilityOptions): Promise<CompatibilityContext> {\n const majorModesConfig = loadMajorModesConfig(options.repoRoot);\n const selectedLayers = resolveLayers(majorModesConfig, options.majorMode);\n const hookGroups = layerHookGroups(majorModesConfig, selectedLayers);\n const temporaryDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), TEMPORARY_DIRECTORY_PREFIX));\n await fs.promises.chmod(temporaryDirectory, PRIVATE_DIRECTORY_MODE);\n\n try {\n const profile = options.profile ? resolveProfile(options.repoRoot, options.profile) : undefined;\n const plugins = resolvePluginEntries(options.repoRoot, options.domains, []);\n const mcpAllowlist = resolveMcpAllowlist(options.repoRoot, options.domains);\n const mcp = await writeCompatibilityMcpConfig(options.repoRoot, plugins, mcpAllowlist, temporaryDirectory);\n const environment = { ...process.env };\n environment.NX_DAEMON ??= 'false';\n const profileEnvironment = applyProfileEnvironment(environment, profile?.env ?? {});\n const personaPrompt = profile?.persona ? buildPersonaPrompt(profile.personaRoot, profile.persona) : undefined;\n let personaFile: string | undefined;\n\n if (personaPrompt) {\n personaFile = path.join(temporaryDirectory, PERSONA_FILENAME);\n await fs.promises.writeFile(personaFile, `${personaPrompt}\\n`, { mode: PRIVATE_FILE_MODE });\n }\n\n // Projection only, with no state file: Claude, Codex and Antigravity read\n // an environment and never the store.\n projectHarnessEnvironment(\n {\n root: options.repoRoot,\n majorMode: options.majorMode,\n temporaryDirectory,\n domains: options.domains,\n layers: selectedLayers,\n profile: profile?.name,\n profileEnvironment,\n hookGroups,\n mcpConfigPath: mcp.mcpConfigPath,\n personaFile,\n additionalDirectories: options.additionalDirectories,\n hooks: true,\n },\n environment,\n );\n environment[ADDITIONAL_DIRS_ENV] = options.additionalDirectories.join(path.delimiter);\n environment[CLAUDE_PROJECT_DIR_ENV] = options.repoRoot;\n environment[CODEX_REPO_ROOT_ENV] = options.repoRoot;\n environment[AGY_REPO_ROOT_ENV] = options.repoRoot;\n environment[ORIGINAL_REPO_PATH_ENV] ||= options.repoRoot;\n\n return {\n options,\n environment,\n plugins,\n profile,\n personaFile,\n mcpAllowlist,\n mcpConfigPath: mcp.mcpConfigPath,\n proxyConfigPath: mcp.proxyConfigPath,\n selectedLayers,\n hookGroups,\n sharedSkills: resolveSharedSkills(options.repoRoot, options.domains),\n cleanup: () => fs.promises.rm(temporaryDirectory, { recursive: true, force: true }),\n };\n } catch (error) {\n await fs.promises.rm(temporaryDirectory, { recursive: true, force: true });\n throw error;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"compatibilityContext.mjs","names":[],"sources":["../../src/adapters/compatibilityContext.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport {\n type AgentProfile,\n applyProfileEnvironment,\n buildPersonaPrompt,\n type DomainMcpAllowlist,\n layerHookGroups,\n loadMajorModesConfig,\n type PluginEntry,\n projectHarnessEnvironment,\n resolveLayers,\n resolvePluginEntries,\n resolveProfile,\n resolveSharedSkills,\n} from '../services/config/index.ts';\nimport type { CompatibilityOptions } from '../types/interfaces/index.ts';\nimport { applyMcpAllowlist, PROXY_SERVER_NAME, resolveMcpAllowlist } from './mcpFilter.ts';\nimport { materializePluginEntries } from './pluginMaterializer.ts';\nimport { mergeMcpConfigs } from './resourceCollector.ts';\n\ntype JsonObject = Record<string, unknown>;\n\nconst MCP_CONFIG_FILENAME = '.mcp.json';\nconst GENERATED_MCP_CONFIG_FILENAME = 'mcp.json';\nconst PROXY_CONFIG_FILENAME = 'mcp-config.yaml';\nconst PERSONA_FILENAME = 'persona.md';\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst CONFIG_OPTION = '--config';\nconst TEMPORARY_DIRECTORY_PREFIX = 'doom-pi-compat-';\nconst ADDITIONAL_DIRS_ENV = 'DOOMPI_ADDITIONAL_DIRS';\nconst CLAUDE_PROJECT_DIR_ENV = 'CLAUDE_PROJECT_DIR';\nconst CODEX_REPO_ROOT_ENV = 'CODEX_REPO_ROOT';\nconst AGY_REPO_ROOT_ENV = 'AGY_REPO_ROOT';\nconst ORIGINAL_REPO_PATH_ENV = 'ORIGINAL_REPO_PATH';\n\nexport interface CompatibilityContext {\n options: CompatibilityOptions;\n environment: NodeJS.ProcessEnv;\n plugins: PluginEntry[];\n profile?: AgentProfile;\n personaFile?: string;\n mcpAllowlist?: DomainMcpAllowlist;\n mcpConfigPath: string;\n proxyConfigPath: string;\n selectedLayers: string[];\n hookGroups: string[];\n sharedSkills: boolean;\n cleanup(): Promise<void>;\n}\n\nfunction pluginMcpPaths(repoRoot: string, plugins: PluginEntry[]): string[] {\n const paths = [path.join(repoRoot, MCP_CONFIG_FILENAME)];\n for (const plugin of plugins) {\n if (plugin.mcp === false) continue;\n const configPath = path.join(plugin.directory, MCP_CONFIG_FILENAME);\n if (fs.existsSync(configPath)) paths.push(configPath);\n }\n return paths;\n}\n\nfunction resolveProxyConfigPath(config: JsonObject, repoRoot: string): string {\n const servers = (config.mcpServers ?? {}) as Record<string, JsonObject>;\n const proxy = servers[PROXY_SERVER_NAME];\n const args = Array.isArray(proxy?.args) ? proxy.args.map(String) : [];\n const configIndex = args.indexOf(CONFIG_OPTION);\n const selected = configIndex === -1 ? undefined : args[configIndex + 1];\n return selected ? path.resolve(repoRoot, selected) : path.join(repoRoot, PROXY_CONFIG_FILENAME);\n}\n\nasync function writeCompatibilityMcpConfig(\n repoRoot: string,\n plugins: PluginEntry[],\n allowlist: DomainMcpAllowlist | undefined,\n temporaryDirectory: string,\n): Promise<{ mcpConfigPath: string; proxyConfigPath: string }> {\n const config = await applyMcpAllowlist(\n mergeMcpConfigs(pluginMcpPaths(repoRoot, plugins)),\n allowlist,\n repoRoot,\n temporaryDirectory,\n );\n const mcpConfigPath = path.join(temporaryDirectory, GENERATED_MCP_CONFIG_FILENAME);\n await fs.promises.writeFile(mcpConfigPath, `${JSON.stringify(config, null, 2)}\\n`, { mode: PRIVATE_FILE_MODE });\n return { mcpConfigPath, proxyConfigPath: resolveProxyConfigPath(config, repoRoot) };\n}\n\n/** Resolves only the resources shared by Pi and compatibility frontends. */\nexport async function buildCompatibilityContext(options: CompatibilityOptions): Promise<CompatibilityContext> {\n const majorModesConfig = loadMajorModesConfig(options.repoRoot);\n const selectedLayers = resolveLayers(majorModesConfig, options.majorMode);\n const hookGroups = layerHookGroups(majorModesConfig, selectedLayers);\n const temporaryDirectory = await fs.promises.mkdtemp(path.join(os.tmpdir(), TEMPORARY_DIRECTORY_PREFIX));\n await fs.promises.chmod(temporaryDirectory, PRIVATE_DIRECTORY_MODE);\n\n try {\n const profile = options.profile ? resolveProfile(options.repoRoot, options.profile) : undefined;\n const plugins = await materializePluginEntries(resolvePluginEntries(options.repoRoot, options.domains, []));\n const mcpAllowlist = resolveMcpAllowlist(options.repoRoot, options.domains);\n const mcp = await writeCompatibilityMcpConfig(options.repoRoot, plugins, mcpAllowlist, temporaryDirectory);\n const environment = { ...process.env };\n environment.NX_DAEMON ??= 'false';\n const profileEnvironment = applyProfileEnvironment(environment, profile?.env ?? {});\n const personaPrompt = profile?.persona ? buildPersonaPrompt(profile.personaRoot, profile.persona) : undefined;\n let personaFile: string | undefined;\n\n if (personaPrompt) {\n personaFile = path.join(temporaryDirectory, PERSONA_FILENAME);\n await fs.promises.writeFile(personaFile, `${personaPrompt}\\n`, { mode: PRIVATE_FILE_MODE });\n }\n\n // Projection only, with no state file: Claude, Codex and Antigravity read\n // an environment and never the store.\n projectHarnessEnvironment(\n {\n root: options.repoRoot,\n majorMode: options.majorMode,\n temporaryDirectory,\n domains: options.domains,\n layers: selectedLayers,\n profile: profile?.name,\n profileEnvironment,\n hookGroups,\n mcpConfigPath: mcp.mcpConfigPath,\n personaFile,\n additionalDirectories: options.additionalDirectories,\n hooks: true,\n },\n environment,\n );\n environment[ADDITIONAL_DIRS_ENV] = options.additionalDirectories.join(path.delimiter);\n environment[CLAUDE_PROJECT_DIR_ENV] = options.repoRoot;\n environment[CODEX_REPO_ROOT_ENV] = options.repoRoot;\n environment[AGY_REPO_ROOT_ENV] = options.repoRoot;\n environment[ORIGINAL_REPO_PATH_ENV] ||= options.repoRoot;\n\n return {\n options,\n environment,\n plugins,\n profile,\n personaFile,\n mcpAllowlist,\n mcpConfigPath: mcp.mcpConfigPath,\n proxyConfigPath: mcp.proxyConfigPath,\n selectedLayers,\n hookGroups,\n sharedSkills: resolveSharedSkills(options.repoRoot, options.domains),\n cleanup: () => fs.promises.rm(temporaryDirectory, { recursive: true, force: true }),\n };\n } catch (error) {\n await fs.promises.rm(temporaryDirectory, { recursive: true, force: true });\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`./bootstrapLocator.cjs`),n=require(`./config/harnessState.cjs`),r=require(`../services/extensionAssembler.cjs`),i=require(`./resourceCollector.cjs`),a=require(`./harnessContext.cjs`),o=require(`./extensionCompiler.cjs`),s=require(`./syncState.cjs`),c=require(`./compositionState.cjs`);let l=require(`node:url`),u=require(`node:path`);u=e.__toESM(u,1);let d=require(`node:fs`);d=e.__toESM(d,1);let f=require(`@agimon-ai/doompi-config/majorModes`),p=require(`@agimon-ai/doompi-ui/extensionName`),m=require(`@earendil-works/pi-coding-agent`),h=require(`@agimon-ai/doompi-config/harnessStore`);const g=`doompi is configured for Pi but this repository was never synced. Run doompi sync.`,_=process.env.DOOMPI_TIMING===`1`||process.env.PI_TIMING===`1`,v={majorMode:`major-mode`,domains:`domains`,profile:`profile`,mute:`mute`},y=`layer`;function b(e){return e instanceof Error?e.message:String(e)}function x(e){try{return d.default.realpathSync(e)}catch{return u.default.resolve(e)}}function S(e,t){let{extensions:n}=(0,m.parseArgs)(e);if(!n||n.length===0)return!1;let r=new Set(Object.values(t).map(x));return n.some(e=>r.has(x(e)))}async function C(e,t,r=process.env){let i=await D(t),a={...n.readHarnessState({...e.env,...r}),...e.fileState,temporaryDirectory:i};(0,h.createHarnessSession)(a,{directory:i,environment:r});for(let[e,t]of Object.entries(a.profileEnvironment))r[e]===void 0&&(r[e]=t);return a}function w(e){let{unknownFlags:t}=(0,m.parseArgs)(e),n=e=>{let n=t.get(e);return typeof n==`string`&&n.trim()?n.trim():void 0},r=n(v.domains);return{majorMode:n(v.majorMode),domains:r?.split(`,`).map(e=>e.trim()).filter(Boolean),profile:n(v.profile),mute:t.get(v.mute)!==void 0,removedLayer:t.get(y)!==void 0}}function T(e){e.registerFlag(v.majorMode,{type:`string`,description:`Named major mode from .doom/modes.yaml`}),e.registerFlag(v.domains,{type:`string`,description:`Comma-separated content domains`}),e.registerFlag(v.profile,{type:`string`,description:`Persona and env from .doom/profiles.yaml`}),e.registerFlag(v.mute,{type:`boolean`,description:`Disable the notification extension`})}async function E(e,t,r,i){if(e.removedLayer&&i.push(`--${y} was replaced by --${v.majorMode}`),e.majorMode)try{let{applyMajorMode:r}=await Promise.resolve().then(()=>require(`./matrixSwitcher.cjs`));r(t,e.majorMode,n.getHarnessState())}catch(t){i.push(`--${v.majorMode} ${e.majorMode}: ${b(t)}`)}if(e.domains&&e.domains.length>0)try{let{applyDomains:t}=await Promise.resolve().then(()=>require(`./matrixSwitcher.cjs`));await t(e.domains,n.getHarnessState())}catch(t){i.push(`--domains ${e.domains.join(`,`)}: ${b(t)}`)}if(e.profile)try{let[{applyProfile:t},{resolveProfile:i}]=await Promise.all([Promise.resolve().then(()=>require(`./matrixSwitcher.cjs`)),import(`@agimon-ai/doompi-config/profiles`)]);await t(i(r,e.profile),n.getHarnessState())}catch(t){i.push(`--profile ${e.profile}: ${b(t)}`)}}async function D(e,t=process.env){let r=s.runDirectory(e);return await d.default.promises.mkdir(r,{mode:448,recursive:!0}),n.updateHarnessState({temporaryDirectory:r},t),r}async function O(e){await d.default.promises.rm(s.runDirectory(e),{recursive:!0,force:!0})}async function k(e,t=n.getHarnessState(),a=process.env){let l=t.root??e.root,d=s.createMapResolvers(e.resolved,e.compiled),p=t.mcp?d.optionalPackageEntry(r.CONTEXT_PACKAGES.mcp):void 0,m={agents:t.agents,autoStop:!1,preset:e.selection.preset,mcpEntry:p,personaEntry:d.ownEntry(r.PERSONA_ENTRY),workflowExtension:i.selectWorkflowExtensionForProcess(d.optionalPackageEntry(r.CONTEXT_PACKAGES.workflow),d.optionalPackageEntry(r.CONTEXT_PACKAGES.dispatcherWorkflow),a),layers:[...t.layers],majorModesConfig:(0,f.loadMajorModesConfig)(l),resolvers:d};n.updateHarnessState({childExtensions:r.assembleChildExtensions({...m,agents:!1,mute:!0})},a),t.agents&&(a.PI_SUBAGENT_EXTRA_AGENT_DIRS=t.agentDirectories.join(u.default.delimiter),a.PI_SUBAGENT_EXTRA_SKILL_DIRS=t.skillDirectories.join(u.default.delimiter));let h=[...r.assembleExtensions({...m,mute:a[c.MUTE_ENV]===`1`})].reverse(),g=e.bundles?.[o.extensionSetKey(h)];return g?[g]:h}async function A(e,t,n){let r=[];for(let i of t){let t=performance.now(),a;try{a=await import((0,l.pathToFileURL)(i).href),_&&process.stderr.write(`[doompi:timing] import ${(performance.now()-t).toFixed(1)}ms ${i}\n`)}catch(e){n.push(`${i}: ${b(e)}`);continue}if(typeof a.default!=`function`){n.push(`${i}: does not export an extension factory`);continue}let o=performance.now();try{await a.default((0,p.withExtensionSource)(e,i)),_&&process.stderr.write(`[doompi:timing] factory ${(performance.now()-o).toFixed(1)}ms ${i}\n`),r.push(i)}catch(e){n.push(`${i}: ${b(e)}`)}}return r}async function j(e,n={}){let r=n.environment??process.env,i=[],o=t.findSyncedRoot(n.cwd??process.cwd());if(!o)return{problems:[g],stale:!1,loaded:[]};let l;try{l=s.readSyncState(o)}catch(e){return{problems:[b(e)],stale:!1,loaded:[]}}if(!l)return{problems:[g],stale:!1,loaded:[]};let u=n.argv??process.argv.slice(2);if(r[c.EXTERNAL_EXTENSIONS_ENV]===`1`||S(u,{...l.resolved,...l.bundles}))return{problems:[],stale:!1,loaded:[]};if(a.configurePreset({preset:l.selection.preset,piArgs:[]},r),!c.alreadyComposed(r)){r[c.COMPOSED_ENV]=`1`,await C(l,o,r);let e=w(u);e.mute&&(r[c.MUTE_ENV]=`1`),await E(e,(0,f.loadMajorModesConfig)(o),o,i)}let d;try{d=await k(l,(0,h.loadHarnessState)(r).state,r)}catch(e){return{problems:[...i,b(e)],stale:!1,loaded:[]}}let p=await A(e,d,i);return{problems:i,stale:s.computeInputsHash(o,l.selection)!==l.inputsHash,loaded:p}}exports.DOOM_FLAGS=v,exports.REMOVED_LAYER_FLAG=y,exports.applyStartupFlags=E,exports.cleanupRunDirectory=O,exports.composeDoomSession=j,exports.composeLoadOrder=k,exports.extensionsProvidedExternally=S,exports.loadComposedExtensions=A,exports.prepareRunDirectory=D,exports.readStartupFlags=w,exports.registerDoomFlags=T,exports.startSyncedSession=C;
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`./bootstrapLocator.cjs`),n=require(`./config/harnessState.cjs`),r=require(`./resourceCollector.cjs`),i=require(`../services/extensionAssembler.cjs`),a=require(`./extensionCompiler.cjs`),o=require(`./compositionState.cjs`),s=require(`./harnessContext.cjs`),c=require(`./syncState.cjs`);let l=require(`node:url`),u=require(`node:path`);u=e.__toESM(u,1);let d=require(`node:fs`);d=e.__toESM(d,1);let f=require(`@agimon-ai/doompi-config/majorModes`),p=require(`@agimon-ai/doompi-ui/extensionName`),m=require(`@earendil-works/pi-coding-agent`),h=require(`@agimon-ai/doompi-config/harnessStore`);const g=`doompi is configured for Pi but this repository was never synced. Run doompi sync.`,_=process.env.DOOMPI_TIMING===`1`||process.env.PI_TIMING===`1`,v={majorMode:`major-mode`,domains:`domains`,profile:`profile`,mute:`mute`},y=`layer`;function b(e){return e instanceof Error?e.message:String(e)}function x(e){try{return d.default.realpathSync(e)}catch{return u.default.resolve(e)}}function S(e,t){let{extensions:n}=(0,m.parseArgs)(e);if(!n||n.length===0)return!1;let r=new Set(Object.values(t).map(x));return n.some(e=>r.has(x(e)))}async function C(e,t,r=process.env){let i=await D(t),a={...n.readHarnessState({...e.env,...r}),...e.fileState,temporaryDirectory:i};(0,h.createHarnessSession)(a,{directory:i,environment:r});for(let[e,t]of Object.entries(a.profileEnvironment))r[e]===void 0&&(r[e]=t);return a}function w(e){let{unknownFlags:t}=(0,m.parseArgs)(e),n=e=>{let n=t.get(e);return typeof n==`string`&&n.trim()?n.trim():void 0},r=n(v.domains);return{majorMode:n(v.majorMode),domains:r?.split(`,`).map(e=>e.trim()).filter(Boolean),profile:n(v.profile),mute:t.get(v.mute)!==void 0,removedLayer:t.get(y)!==void 0}}function T(e){e.registerFlag(v.majorMode,{type:`string`,description:`Named major mode from .doom/modes.yaml`}),e.registerFlag(v.domains,{type:`string`,description:`Comma-separated content domains`}),e.registerFlag(v.profile,{type:`string`,description:`Persona and env from .doom/profiles.yaml`}),e.registerFlag(v.mute,{type:`boolean`,description:`Disable the notification extension`})}async function E(e,t,r,i){if(e.removedLayer&&i.push(`--${y} was replaced by --${v.majorMode}`),e.majorMode)try{let{applyMajorMode:r}=await Promise.resolve().then(()=>require(`./matrixSwitcher.cjs`));r(t,e.majorMode,n.getHarnessState())}catch(t){i.push(`--${v.majorMode} ${e.majorMode}: ${b(t)}`)}if(e.domains&&e.domains.length>0)try{let{applyDomains:t}=await Promise.resolve().then(()=>require(`./matrixSwitcher.cjs`));await t(e.domains,n.getHarnessState())}catch(t){i.push(`--domains ${e.domains.join(`,`)}: ${b(t)}`)}if(e.profile)try{let[{applyProfile:t},{resolveProfile:i}]=await Promise.all([Promise.resolve().then(()=>require(`./matrixSwitcher.cjs`)),import(`@agimon-ai/doompi-config/profiles`)]);await t(i(r,e.profile),n.getHarnessState())}catch(t){i.push(`--profile ${e.profile}: ${b(t)}`)}}async function D(e,t=process.env){let r=c.runDirectory(e);return await d.default.promises.mkdir(r,{mode:448,recursive:!0}),n.updateHarnessState({temporaryDirectory:r},t),r}async function O(e){await d.default.promises.rm(c.runDirectory(e),{recursive:!0,force:!0})}async function k(e,t=n.getHarnessState(),s=process.env){let l=t.root??e.root,d=c.createMapResolvers(e.resolved,e.compiled),p=t.mcp?d.optionalPackageEntry(i.CONTEXT_PACKAGES.mcp):void 0,m={agents:t.agents,autoStop:!1,preset:e.selection.preset,mcpEntry:p,personaEntry:d.ownEntry(i.PERSONA_ENTRY),workflowExtension:r.selectWorkflowExtensionForProcess(d.optionalPackageEntry(i.CONTEXT_PACKAGES.workflow),d.optionalPackageEntry(i.CONTEXT_PACKAGES.dispatcherWorkflow),s),layers:[...t.layers],majorModesConfig:(0,f.loadMajorModesConfig)(l),resolvers:d};n.updateHarnessState({childExtensions:i.assembleChildExtensions({...m,agents:!1,mute:!0})},s),t.agents&&(s.PI_SUBAGENT_EXTRA_AGENT_DIRS=t.agentDirectories.join(u.default.delimiter),s.PI_SUBAGENT_EXTRA_SKILL_DIRS=t.skillDirectories.join(u.default.delimiter));let h=[...i.assembleExtensions({...m,mute:s[o.MUTE_ENV]===`1`})].reverse(),g=e.bundles?.[a.extensionSetKey(h)];return g?[g]:h}async function A(e,t,n){let r=[];for(let i of t){let t=performance.now(),a;try{a=await import((0,l.pathToFileURL)(i).href),_&&process.stderr.write(`[doompi:timing] import ${(performance.now()-t).toFixed(1)}ms ${i}\n`)}catch(e){n.push(`${i}: ${b(e)}`);continue}if(typeof a.default!=`function`){n.push(`${i}: does not export an extension factory`);continue}let o=performance.now();try{await a.default((0,p.withExtensionSource)(e,i)),_&&process.stderr.write(`[doompi:timing] factory ${(performance.now()-o).toFixed(1)}ms ${i}\n`),r.push(i)}catch(e){n.push(`${i}: ${b(e)}`)}}return r}async function j(e,n={}){let r=n.environment??process.env,i=[],a=t.findSyncedRoot(n.cwd??process.cwd());if(!a)return{problems:[g],stale:!1,loaded:[]};let l;try{l=c.readSyncState(a)}catch(e){return{problems:[b(e)],stale:!1,loaded:[]}}if(!l)return{problems:[g],stale:!1,loaded:[]};let u=n.argv??process.argv.slice(2);if(r[o.EXTERNAL_EXTENSIONS_ENV]===`1`||S(u,{...l.resolved,...l.bundles}))return{problems:[],stale:!1,loaded:[]};if(s.configurePreset({preset:l.selection.preset,piArgs:[]},r),!o.alreadyComposed(r)){r[o.COMPOSED_ENV]=`1`,await C(l,a,r);let e=w(u);e.mute&&(r[o.MUTE_ENV]=`1`),await E(e,(0,f.loadMajorModesConfig)(a),a,i)}let d;try{d=await k(l,(0,h.loadHarnessState)(r).state,r)}catch(e){return{problems:[...i,b(e)],stale:!1,loaded:[]}}let p=await A(e,d,i);return{problems:i,stale:c.computeInputsHash(a,l.selection)!==l.inputsHash,loaded:p}}exports.DOOM_FLAGS=v,exports.REMOVED_LAYER_FLAG=y,exports.applyStartupFlags=E,exports.cleanupRunDirectory=O,exports.composeDoomSession=j,exports.composeLoadOrder=k,exports.extensionsProvidedExternally=S,exports.loadComposedExtensions=A,exports.prepareRunDirectory=D,exports.readStartupFlags=w,exports.registerDoomFlags=T,exports.startSyncedSession=C;
2
2
  //# sourceMappingURL=composer.cjs.map
@@ -1,2 +1,2 @@
1
- import{findSyncedRoot as e}from"./bootstrapLocator.mjs";import{createHarnessSession as t,getHarnessState as n,loadHarnessState as r,readHarnessState as i,updateHarnessState as a}from"./config/harnessState.mjs";import{CONTEXT_PACKAGES as o,PERSONA_ENTRY as s,assembleChildExtensions as c,assembleExtensions as l}from"../services/extensionAssembler.mjs";import{selectWorkflowExtensionForProcess as u}from"./resourceCollector.mjs";import{configurePreset as d}from"./harnessContext.mjs";import{extensionSetKey as f}from"./extensionCompiler.mjs";import{computeInputsHash as p,createMapResolvers as m,readSyncState as h,runDirectory as g}from"./syncState.mjs";import{COMPOSED_ENV as _,EXTERNAL_EXTENSIONS_ENV as v,MUTE_ENV as y,alreadyComposed as b}from"./compositionState.mjs";import{pathToFileURL as x}from"node:url";import S from"node:path";import C from"node:fs";import{loadMajorModesConfig as w}from"@agimon-ai/doompi-config/majorModes";import{withExtensionSource as T}from"@agimon-ai/doompi-ui/extensionName";import{parseArgs as E}from"@earendil-works/pi-coding-agent";const D=`doompi is configured for Pi but this repository was never synced. Run doompi sync.`,O=process.env.DOOMPI_TIMING===`1`||process.env.PI_TIMING===`1`,k={majorMode:`major-mode`,domains:`domains`,profile:`profile`,mute:`mute`},A=`layer`;function j(e){return e instanceof Error?e.message:String(e)}function M(e){try{return C.realpathSync(e)}catch{return S.resolve(e)}}function N(e,t){let{extensions:n}=E(e);if(!n||n.length===0)return!1;let r=new Set(Object.values(t).map(M));return n.some(e=>r.has(M(e)))}async function P(e,n,r=process.env){let a=await R(n),o={...i({...e.env,...r}),...e.fileState,temporaryDirectory:a};t(o,{directory:a,environment:r});for(let[e,t]of Object.entries(o.profileEnvironment))r[e]===void 0&&(r[e]=t);return o}function F(e){let{unknownFlags:t}=E(e),n=e=>{let n=t.get(e);return typeof n==`string`&&n.trim()?n.trim():void 0},r=n(k.domains);return{majorMode:n(k.majorMode),domains:r?.split(`,`).map(e=>e.trim()).filter(Boolean),profile:n(k.profile),mute:t.get(k.mute)!==void 0,removedLayer:t.get(A)!==void 0}}function I(e){e.registerFlag(k.majorMode,{type:`string`,description:`Named major mode from .doom/modes.yaml`}),e.registerFlag(k.domains,{type:`string`,description:`Comma-separated content domains`}),e.registerFlag(k.profile,{type:`string`,description:`Persona and env from .doom/profiles.yaml`}),e.registerFlag(k.mute,{type:`boolean`,description:`Disable the notification extension`})}async function L(e,t,r,i){if(e.removedLayer&&i.push(`--${A} was replaced by --${k.majorMode}`),e.majorMode)try{let{applyMajorMode:r}=await import(`./matrixSwitcher.mjs`);r(t,e.majorMode,n())}catch(t){i.push(`--${k.majorMode} ${e.majorMode}: ${j(t)}`)}if(e.domains&&e.domains.length>0)try{let{applyDomains:t}=await import(`./matrixSwitcher.mjs`);await t(e.domains,n())}catch(t){i.push(`--domains ${e.domains.join(`,`)}: ${j(t)}`)}if(e.profile)try{let[{applyProfile:t},{resolveProfile:i}]=await Promise.all([import(`./matrixSwitcher.mjs`),import(`@agimon-ai/doompi-config/profiles`)]);await t(i(r,e.profile),n())}catch(t){i.push(`--profile ${e.profile}: ${j(t)}`)}}async function R(e,t=process.env){let n=g(e);return await C.promises.mkdir(n,{mode:448,recursive:!0}),a({temporaryDirectory:n},t),n}async function z(e){await C.promises.rm(g(e),{recursive:!0,force:!0})}async function B(e,t=n(),r=process.env){let i=t.root??e.root,d=m(e.resolved,e.compiled),p=t.mcp?d.optionalPackageEntry(o.mcp):void 0,h={agents:t.agents,autoStop:!1,preset:e.selection.preset,mcpEntry:p,personaEntry:d.ownEntry(s),workflowExtension:u(d.optionalPackageEntry(o.workflow),d.optionalPackageEntry(o.dispatcherWorkflow),r),layers:[...t.layers],majorModesConfig:w(i),resolvers:d};a({childExtensions:c({...h,agents:!1,mute:!0})},r),t.agents&&(r.PI_SUBAGENT_EXTRA_AGENT_DIRS=t.agentDirectories.join(S.delimiter),r.PI_SUBAGENT_EXTRA_SKILL_DIRS=t.skillDirectories.join(S.delimiter));let g=[...l({...h,mute:r[y]===`1`})].reverse(),_=e.bundles?.[f(g)];return _?[_]:g}async function V(e,t,n){let r=[];for(let i of t){let t=performance.now(),a;try{a=await import(x(i).href),O&&process.stderr.write(`[doompi:timing] import ${(performance.now()-t).toFixed(1)}ms ${i}\n`)}catch(e){n.push(`${i}: ${j(e)}`);continue}if(typeof a.default!=`function`){n.push(`${i}: does not export an extension factory`);continue}let o=performance.now();try{await a.default(T(e,i)),O&&process.stderr.write(`[doompi:timing] factory ${(performance.now()-o).toFixed(1)}ms ${i}\n`),r.push(i)}catch(e){n.push(`${i}: ${j(e)}`)}}return r}async function H(t,n={}){let i=n.environment??process.env,a=[],o=e(n.cwd??process.cwd());if(!o)return{problems:[D],stale:!1,loaded:[]};let s;try{s=h(o)}catch(e){return{problems:[j(e)],stale:!1,loaded:[]}}if(!s)return{problems:[D],stale:!1,loaded:[]};let c=n.argv??process.argv.slice(2);if(i[v]===`1`||N(c,{...s.resolved,...s.bundles}))return{problems:[],stale:!1,loaded:[]};if(d({preset:s.selection.preset,piArgs:[]},i),!b(i)){i[_]=`1`,await P(s,o,i);let e=F(c);e.mute&&(i[y]=`1`),await L(e,w(o),o,a)}let l;try{l=await B(s,r(i).state,i)}catch(e){return{problems:[...a,j(e)],stale:!1,loaded:[]}}let u=await V(t,l,a);return{problems:a,stale:p(o,s.selection)!==s.inputsHash,loaded:u}}export{k as DOOM_FLAGS,A as REMOVED_LAYER_FLAG,L as applyStartupFlags,z as cleanupRunDirectory,H as composeDoomSession,B as composeLoadOrder,N as extensionsProvidedExternally,V as loadComposedExtensions,R as prepareRunDirectory,F as readStartupFlags,I as registerDoomFlags,P as startSyncedSession};
1
+ import{findSyncedRoot as e}from"./bootstrapLocator.mjs";import{createHarnessSession as t,getHarnessState as n,loadHarnessState as r,readHarnessState as i,updateHarnessState as a}from"./config/harnessState.mjs";import{selectWorkflowExtensionForProcess as o}from"./resourceCollector.mjs";import{CONTEXT_PACKAGES as s,PERSONA_ENTRY as c,assembleChildExtensions as l,assembleExtensions as u}from"../services/extensionAssembler.mjs";import{extensionSetKey as d}from"./extensionCompiler.mjs";import{COMPOSED_ENV as f,EXTERNAL_EXTENSIONS_ENV as p,MUTE_ENV as m,alreadyComposed as h}from"./compositionState.mjs";import{configurePreset as g}from"./harnessContext.mjs";import{computeInputsHash as _,createMapResolvers as v,readSyncState as y,runDirectory as b}from"./syncState.mjs";import{pathToFileURL as x}from"node:url";import S from"node:path";import C from"node:fs";import{loadMajorModesConfig as w}from"@agimon-ai/doompi-config/majorModes";import{withExtensionSource as T}from"@agimon-ai/doompi-ui/extensionName";import{parseArgs as E}from"@earendil-works/pi-coding-agent";const D=`doompi is configured for Pi but this repository was never synced. Run doompi sync.`,O=process.env.DOOMPI_TIMING===`1`||process.env.PI_TIMING===`1`,k={majorMode:`major-mode`,domains:`domains`,profile:`profile`,mute:`mute`},A=`layer`;function j(e){return e instanceof Error?e.message:String(e)}function M(e){try{return C.realpathSync(e)}catch{return S.resolve(e)}}function N(e,t){let{extensions:n}=E(e);if(!n||n.length===0)return!1;let r=new Set(Object.values(t).map(M));return n.some(e=>r.has(M(e)))}async function P(e,n,r=process.env){let a=await R(n),o={...i({...e.env,...r}),...e.fileState,temporaryDirectory:a};t(o,{directory:a,environment:r});for(let[e,t]of Object.entries(o.profileEnvironment))r[e]===void 0&&(r[e]=t);return o}function F(e){let{unknownFlags:t}=E(e),n=e=>{let n=t.get(e);return typeof n==`string`&&n.trim()?n.trim():void 0},r=n(k.domains);return{majorMode:n(k.majorMode),domains:r?.split(`,`).map(e=>e.trim()).filter(Boolean),profile:n(k.profile),mute:t.get(k.mute)!==void 0,removedLayer:t.get(A)!==void 0}}function I(e){e.registerFlag(k.majorMode,{type:`string`,description:`Named major mode from .doom/modes.yaml`}),e.registerFlag(k.domains,{type:`string`,description:`Comma-separated content domains`}),e.registerFlag(k.profile,{type:`string`,description:`Persona and env from .doom/profiles.yaml`}),e.registerFlag(k.mute,{type:`boolean`,description:`Disable the notification extension`})}async function L(e,t,r,i){if(e.removedLayer&&i.push(`--${A} was replaced by --${k.majorMode}`),e.majorMode)try{let{applyMajorMode:r}=await import(`./matrixSwitcher.mjs`);r(t,e.majorMode,n())}catch(t){i.push(`--${k.majorMode} ${e.majorMode}: ${j(t)}`)}if(e.domains&&e.domains.length>0)try{let{applyDomains:t}=await import(`./matrixSwitcher.mjs`);await t(e.domains,n())}catch(t){i.push(`--domains ${e.domains.join(`,`)}: ${j(t)}`)}if(e.profile)try{let[{applyProfile:t},{resolveProfile:i}]=await Promise.all([import(`./matrixSwitcher.mjs`),import(`@agimon-ai/doompi-config/profiles`)]);await t(i(r,e.profile),n())}catch(t){i.push(`--profile ${e.profile}: ${j(t)}`)}}async function R(e,t=process.env){let n=b(e);return await C.promises.mkdir(n,{mode:448,recursive:!0}),a({temporaryDirectory:n},t),n}async function z(e){await C.promises.rm(b(e),{recursive:!0,force:!0})}async function B(e,t=n(),r=process.env){let i=t.root??e.root,f=v(e.resolved,e.compiled),p=t.mcp?f.optionalPackageEntry(s.mcp):void 0,h={agents:t.agents,autoStop:!1,preset:e.selection.preset,mcpEntry:p,personaEntry:f.ownEntry(c),workflowExtension:o(f.optionalPackageEntry(s.workflow),f.optionalPackageEntry(s.dispatcherWorkflow),r),layers:[...t.layers],majorModesConfig:w(i),resolvers:f};a({childExtensions:l({...h,agents:!1,mute:!0})},r),t.agents&&(r.PI_SUBAGENT_EXTRA_AGENT_DIRS=t.agentDirectories.join(S.delimiter),r.PI_SUBAGENT_EXTRA_SKILL_DIRS=t.skillDirectories.join(S.delimiter));let g=[...u({...h,mute:r[m]===`1`})].reverse(),_=e.bundles?.[d(g)];return _?[_]:g}async function V(e,t,n){let r=[];for(let i of t){let t=performance.now(),a;try{a=await import(x(i).href),O&&process.stderr.write(`[doompi:timing] import ${(performance.now()-t).toFixed(1)}ms ${i}\n`)}catch(e){n.push(`${i}: ${j(e)}`);continue}if(typeof a.default!=`function`){n.push(`${i}: does not export an extension factory`);continue}let o=performance.now();try{await a.default(T(e,i)),O&&process.stderr.write(`[doompi:timing] factory ${(performance.now()-o).toFixed(1)}ms ${i}\n`),r.push(i)}catch(e){n.push(`${i}: ${j(e)}`)}}return r}async function H(t,n={}){let i=n.environment??process.env,a=[],o=e(n.cwd??process.cwd());if(!o)return{problems:[D],stale:!1,loaded:[]};let s;try{s=y(o)}catch(e){return{problems:[j(e)],stale:!1,loaded:[]}}if(!s)return{problems:[D],stale:!1,loaded:[]};let c=n.argv??process.argv.slice(2);if(i[p]===`1`||N(c,{...s.resolved,...s.bundles}))return{problems:[],stale:!1,loaded:[]};if(g({preset:s.selection.preset,piArgs:[]},i),!h(i)){i[f]=`1`,await P(s,o,i);let e=F(c);e.mute&&(i[m]=`1`),await L(e,w(o),o,a)}let l;try{l=await B(s,r(i).state,i)}catch(e){return{problems:[...a,j(e)],stale:!1,loaded:[]}}let u=await V(t,l,a);return{problems:a,stale:_(o,s.selection)!==s.inputsHash,loaded:u}}export{k as DOOM_FLAGS,A as REMOVED_LAYER_FLAG,L as applyStartupFlags,z as cleanupRunDirectory,H as composeDoomSession,B as composeLoadOrder,N as extensionsProvidedExternally,V as loadComposedExtensions,R as prepareRunDirectory,F as readStartupFlags,I as registerDoomFlags,P as startSyncedSession};
2
2
  //# sourceMappingURL=composer.mjs.map
@@ -0,0 +1,3 @@
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`./dpiSettings.cjs`);let n=require(`node:path`);n=e.__toESM(n,1);let r=require(`@agimon-ai/doompi-config`);const i=`--force`,a=`PI_SUBAGENT_PI_BINARY`,o=/^dpi(?:\.[cm]?js|\.ts)?$/u;async function s(e){let t=await import(`@earendil-works/pi-coding-agent`);if(t.SettingsManager!==e.SettingsManager)throw Error(`DPI resolved more than one Pi settings runtime`);return t}function c(e=process.env,t=process.argv[1]){e.PI_CODING_AGENT=`true`,e.AI_AGENT=`pi`,!e[a]?.trim()&&t&&o.test(n.default.basename(t))&&(e[a]=n.default.resolve(t))}async function l(e){let n=await t.loadPiSettingsRuntime(),r=await s(n),i=t.installDpiSettingsOverlay(n);process.title=`dpi`,c(),process.emitWarning=(()=>void 0);try{await r.main(e);let t=process.exitCode;return typeof t==`number`?t:Number.parseInt(t??`0`,10)}finally{i()}}function u(e){return[`DoomPi repository configuration: ${e.directory}`,...e.created.length>0?[`created: ${e.created.join(`, `)}`]:[],...e.preserved.length>0?[`kept: ${e.preserved.join(`, `)}`]:[],...e.replaced.length>0?[`replaced: ${e.replaced.join(`, `)}`]:[],``,"Run `dpi sync` next.",``].join(`
2
+ `)}function d(e,t=process.cwd(),n=process.stdout){let a=e.slice(1),o=a.find(e=>e!==i);if(o!==void 0)throw Error(`dpi init does not accept ${o}`);let s=(0,r.initializeRepositoryDoomConfig)(t,{force:a.includes(i)});return n.write(u(s)),0}async function f(e){let{SyncPipeline:t}=await Promise.resolve().then(()=>require(`../commands/syncPipeline.cjs`));return new t({settingsMode:`embedded`}).execute(e)}const p={init:d,launchPi:l,sync:f};async function m(e,t=p){return e[0]===`init`?t.init(e):e[0]===`sync`?t.sync(e):t.launchPi(e)}exports.runDpi=m;
3
+ //# sourceMappingURL=dpiRunner.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpiRunner.cjs","names":["path","loadPiSettingsRuntime","installDpiSettingsOverlay"],"sources":["../../src/adapters/dpiRunner.ts"],"sourcesContent":["import path from 'node:path';\nimport { initializeRepositoryDoomConfig, type RepositoryDoomInitResult } from '@agimon-ai/doompi-config';\nimport { installDpiSettingsOverlay, loadPiSettingsRuntime, type PiSettingsRuntime } from './dpiSettings.ts';\n\nconst INIT_COMMAND = 'init';\nconst SYNC_COMMAND = 'sync';\nconst FORCE_FLAG = '--force';\nconst PI_SUBAGENT_BINARY_ENV = 'PI_SUBAGENT_PI_BINARY';\nconst DPI_ENTRY_PATTERN = /^dpi(?:\\.[cm]?js|\\.ts)?$/u;\n\ntype PiModule = typeof import('@earendil-works/pi-coding-agent');\n\nexport interface DpiRunnerDependencies {\n init(args: string[]): number | Promise<number>;\n launchPi(args: string[]): Promise<number>;\n sync(args: string[]): Promise<number>;\n}\n\nasync function loadPiModule(settingsRuntime: PiSettingsRuntime): Promise<PiModule> {\n const loaded = await import('@earendil-works/pi-coding-agent');\n if (loaded.SettingsManager !== settingsRuntime.SettingsManager) {\n throw new Error('DPI resolved more than one Pi settings runtime');\n }\n return loaded;\n}\n\n/** Marks the process as Pi and keeps any CLI-based nested fallback on DPI. */\nexport function configureDpiEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n entryPoint: string | undefined = process.argv[1],\n): void {\n environment.PI_CODING_AGENT = 'true';\n environment.AI_AGENT = 'pi';\n if (!environment[PI_SUBAGENT_BINARY_ENV]?.trim() && entryPoint && DPI_ENTRY_PATTERN.test(path.basename(entryPoint))) {\n environment[PI_SUBAGENT_BINARY_ENV] = path.resolve(entryPoint);\n }\n}\n\n/** Runs the pinned upstream Pi entry point after installing DPI's settings view. */\nexport async function launchDpiPi(args: string[]): Promise<number> {\n const settingsRuntime = await loadPiSettingsRuntime();\n const pi = await loadPiModule(settingsRuntime);\n const restoreSettings = installDpiSettingsOverlay(settingsRuntime);\n process.title = 'dpi';\n configureDpiEnvironment();\n process.emitWarning = (() => undefined) as typeof process.emitWarning;\n\n try {\n await pi.main(args);\n const exitCode = process.exitCode;\n return typeof exitCode === 'number' ? exitCode : Number.parseInt(exitCode ?? '0', 10);\n } finally {\n restoreSettings();\n }\n}\n\nfunction formatDpiInitResult(result: RepositoryDoomInitResult): string {\n return [\n `DoomPi repository configuration: ${result.directory}`,\n ...(result.created.length > 0 ? [`created: ${result.created.join(', ')}`] : []),\n ...(result.preserved.length > 0 ? [`kept: ${result.preserved.join(', ')}`] : []),\n ...(result.replaced.length > 0 ? [`replaced: ${result.replaced.join(', ')}`] : []),\n '',\n 'Run `dpi sync` next.',\n '',\n ].join('\\n');\n}\n\n/** Seeds repository-local DoomPi configuration without registering anything with Pi. */\nexport function runDpiInit(\n args: string[],\n currentDirectory = process.cwd(),\n output: Pick<NodeJS.WritableStream, 'write'> = process.stdout,\n): number {\n const flags = args.slice(1);\n const unknown = flags.find((flag) => flag !== FORCE_FLAG);\n if (unknown !== undefined) throw new Error(`dpi init does not accept ${unknown}`);\n\n const result = initializeRepositoryDoomConfig(currentDirectory, { force: flags.includes(FORCE_FLAG) });\n output.write(formatDpiInitResult(result));\n return 0;\n}\n\n/** Runs DPI's private build → sync pipeline without persisting the settings overlay. */\nexport async function runDpiSync(args: string[]): Promise<number> {\n const { SyncPipeline } = await import('../commands/syncPipeline.ts');\n return new SyncPipeline({ settingsMode: 'embedded' }).execute(args);\n}\n\nconst DEFAULT_DEPENDENCIES: DpiRunnerDependencies = {\n init: runDpiInit,\n launchPi: launchDpiPi,\n sync: runDpiSync,\n};\n\n/** Dispatches DPI-owned setup commands and forwards every other argument to Pi. */\nexport async function runDpi(\n args: string[],\n dependencies: DpiRunnerDependencies = DEFAULT_DEPENDENCIES,\n): Promise<number> {\n if (args[0] === INIT_COMMAND) return dependencies.init(args);\n if (args[0] === SYNC_COMMAND) return dependencies.sync(args);\n return dependencies.launchPi(args);\n}\n"],"mappings":"0KAIA,MAEM,EAAa,UACb,EAAyB,wBACzB,EAAoB,4BAU1B,eAAe,EAAa,EAAuD,CACjF,IAAM,EAAS,MAAM,OAAO,mCAC5B,GAAI,EAAO,kBAAoB,EAAgB,gBAC7C,MAAU,MAAM,iDAAiD,CAEnE,OAAO,EAIT,SAAgB,EACd,EAAiC,QAAQ,IACzC,EAAiC,QAAQ,KAAK,GACxC,CACN,EAAY,gBAAkB,OAC9B,EAAY,SAAW,KACnB,CAAC,EAAY,IAAyB,MAAM,EAAI,GAAc,EAAkB,KAAKA,EAAAA,QAAK,SAAS,EAAW,CAAC,GACjH,EAAY,GAA0BA,EAAAA,QAAK,QAAQ,EAAW,EAKlE,eAAsB,EAAY,EAAiC,CACjE,IAAM,EAAkB,MAAMC,EAAAA,uBAAuB,CAC/C,EAAK,MAAM,EAAa,EAAgB,CACxC,EAAkBC,EAAAA,0BAA0B,EAAgB,CAClE,QAAQ,MAAQ,MAChB,GAAyB,CACzB,QAAQ,iBAAqB,IAAA,IAE7B,GAAI,CACF,MAAM,EAAG,KAAK,EAAK,CACnB,IAAM,EAAW,QAAQ,SACzB,OAAO,OAAO,GAAa,SAAW,EAAW,OAAO,SAAS,GAAY,IAAK,GAAG,QAC7E,CACR,GAAiB,EAIrB,SAAS,EAAoB,EAA0C,CACrE,MAAO,CACL,oCAAoC,EAAO,YAC3C,GAAI,EAAO,QAAQ,OAAS,EAAI,CAAC,aAAa,EAAO,QAAQ,KAAK,KAAK,GAAG,CAAG,EAAE,CAC/E,GAAI,EAAO,UAAU,OAAS,EAAI,CAAC,aAAa,EAAO,UAAU,KAAK,KAAK,GAAG,CAAG,EAAE,CACnF,GAAI,EAAO,SAAS,OAAS,EAAI,CAAC,aAAa,EAAO,SAAS,KAAK,KAAK,GAAG,CAAG,EAAE,CACjF,GACA,uBACA,GACD,CAAC,KAAK;EAAK,CAId,SAAgB,EACd,EACA,EAAmB,QAAQ,KAAK,CAChC,EAA+C,QAAQ,OAC/C,CACR,IAAM,EAAQ,EAAK,MAAM,EAAE,CACrB,EAAU,EAAM,KAAM,GAAS,IAAS,EAAW,CACzD,GAAI,IAAY,IAAA,GAAW,MAAU,MAAM,4BAA4B,IAAU,CAEjF,IAAM,GAAA,EAAA,EAAA,gCAAwC,EAAkB,CAAE,MAAO,EAAM,SAAS,EAAW,CAAE,CAAC,CAEtG,OADA,EAAO,MAAM,EAAoB,EAAO,CAAC,CAClC,EAIT,eAAsB,EAAW,EAAiC,CAChE,GAAM,CAAE,gBAAiB,MAAA,QAAA,SAAA,CAAA,SAAA,QAAM,+BAAA,CAAA,CAC/B,OAAO,IAAI,EAAa,CAAE,aAAc,WAAY,CAAC,CAAC,QAAQ,EAAK,CAGrE,MAAM,EAA8C,CAClD,KAAM,EACN,SAAU,EACV,KAAM,EACP,CAGD,eAAsB,EACpB,EACA,EAAsC,EACrB,CAGjB,OAFI,EAAK,KAAO,OAAqB,EAAa,KAAK,EAAK,CACxD,EAAK,KAAO,OAAqB,EAAa,KAAK,EAAK,CACrD,EAAa,SAAS,EAAK"}
@@ -0,0 +1,3 @@
1
+ import{installDpiSettingsOverlay as e,loadPiSettingsRuntime as t}from"./dpiSettings.mjs";import n from"node:path";import{initializeRepositoryDoomConfig as r}from"@agimon-ai/doompi-config";const i=`--force`,a=`PI_SUBAGENT_PI_BINARY`,o=/^dpi(?:\.[cm]?js|\.ts)?$/u;async function s(e){let t=await import(`@earendil-works/pi-coding-agent`);if(t.SettingsManager!==e.SettingsManager)throw Error(`DPI resolved more than one Pi settings runtime`);return t}function c(e=process.env,t=process.argv[1]){e.PI_CODING_AGENT=`true`,e.AI_AGENT=`pi`,!e[a]?.trim()&&t&&o.test(n.basename(t))&&(e[a]=n.resolve(t))}async function l(n){let r=await t(),i=await s(r),a=e(r);process.title=`dpi`,c(),process.emitWarning=(()=>void 0);try{await i.main(n);let e=process.exitCode;return typeof e==`number`?e:Number.parseInt(e??`0`,10)}finally{a()}}function u(e){return[`DoomPi repository configuration: ${e.directory}`,...e.created.length>0?[`created: ${e.created.join(`, `)}`]:[],...e.preserved.length>0?[`kept: ${e.preserved.join(`, `)}`]:[],...e.replaced.length>0?[`replaced: ${e.replaced.join(`, `)}`]:[],``,"Run `dpi sync` next.",``].join(`
2
+ `)}function d(e,t=process.cwd(),n=process.stdout){let a=e.slice(1),o=a.find(e=>e!==i);if(o!==void 0)throw Error(`dpi init does not accept ${o}`);let s=r(t,{force:a.includes(i)});return n.write(u(s)),0}async function f(e){let{SyncPipeline:t}=await import(`../commands/syncPipeline.mjs`);return new t({settingsMode:`embedded`}).execute(e)}const p={init:d,launchPi:l,sync:f};async function m(e,t=p){return e[0]===`init`?t.init(e):e[0]===`sync`?t.sync(e):t.launchPi(e)}export{m as runDpi};
3
+ //# sourceMappingURL=dpiRunner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpiRunner.mjs","names":[],"sources":["../../src/adapters/dpiRunner.ts"],"sourcesContent":["import path from 'node:path';\nimport { initializeRepositoryDoomConfig, type RepositoryDoomInitResult } from '@agimon-ai/doompi-config';\nimport { installDpiSettingsOverlay, loadPiSettingsRuntime, type PiSettingsRuntime } from './dpiSettings.ts';\n\nconst INIT_COMMAND = 'init';\nconst SYNC_COMMAND = 'sync';\nconst FORCE_FLAG = '--force';\nconst PI_SUBAGENT_BINARY_ENV = 'PI_SUBAGENT_PI_BINARY';\nconst DPI_ENTRY_PATTERN = /^dpi(?:\\.[cm]?js|\\.ts)?$/u;\n\ntype PiModule = typeof import('@earendil-works/pi-coding-agent');\n\nexport interface DpiRunnerDependencies {\n init(args: string[]): number | Promise<number>;\n launchPi(args: string[]): Promise<number>;\n sync(args: string[]): Promise<number>;\n}\n\nasync function loadPiModule(settingsRuntime: PiSettingsRuntime): Promise<PiModule> {\n const loaded = await import('@earendil-works/pi-coding-agent');\n if (loaded.SettingsManager !== settingsRuntime.SettingsManager) {\n throw new Error('DPI resolved more than one Pi settings runtime');\n }\n return loaded;\n}\n\n/** Marks the process as Pi and keeps any CLI-based nested fallback on DPI. */\nexport function configureDpiEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n entryPoint: string | undefined = process.argv[1],\n): void {\n environment.PI_CODING_AGENT = 'true';\n environment.AI_AGENT = 'pi';\n if (!environment[PI_SUBAGENT_BINARY_ENV]?.trim() && entryPoint && DPI_ENTRY_PATTERN.test(path.basename(entryPoint))) {\n environment[PI_SUBAGENT_BINARY_ENV] = path.resolve(entryPoint);\n }\n}\n\n/** Runs the pinned upstream Pi entry point after installing DPI's settings view. */\nexport async function launchDpiPi(args: string[]): Promise<number> {\n const settingsRuntime = await loadPiSettingsRuntime();\n const pi = await loadPiModule(settingsRuntime);\n const restoreSettings = installDpiSettingsOverlay(settingsRuntime);\n process.title = 'dpi';\n configureDpiEnvironment();\n process.emitWarning = (() => undefined) as typeof process.emitWarning;\n\n try {\n await pi.main(args);\n const exitCode = process.exitCode;\n return typeof exitCode === 'number' ? exitCode : Number.parseInt(exitCode ?? '0', 10);\n } finally {\n restoreSettings();\n }\n}\n\nfunction formatDpiInitResult(result: RepositoryDoomInitResult): string {\n return [\n `DoomPi repository configuration: ${result.directory}`,\n ...(result.created.length > 0 ? [`created: ${result.created.join(', ')}`] : []),\n ...(result.preserved.length > 0 ? [`kept: ${result.preserved.join(', ')}`] : []),\n ...(result.replaced.length > 0 ? [`replaced: ${result.replaced.join(', ')}`] : []),\n '',\n 'Run `dpi sync` next.',\n '',\n ].join('\\n');\n}\n\n/** Seeds repository-local DoomPi configuration without registering anything with Pi. */\nexport function runDpiInit(\n args: string[],\n currentDirectory = process.cwd(),\n output: Pick<NodeJS.WritableStream, 'write'> = process.stdout,\n): number {\n const flags = args.slice(1);\n const unknown = flags.find((flag) => flag !== FORCE_FLAG);\n if (unknown !== undefined) throw new Error(`dpi init does not accept ${unknown}`);\n\n const result = initializeRepositoryDoomConfig(currentDirectory, { force: flags.includes(FORCE_FLAG) });\n output.write(formatDpiInitResult(result));\n return 0;\n}\n\n/** Runs DPI's private build → sync pipeline without persisting the settings overlay. */\nexport async function runDpiSync(args: string[]): Promise<number> {\n const { SyncPipeline } = await import('../commands/syncPipeline.ts');\n return new SyncPipeline({ settingsMode: 'embedded' }).execute(args);\n}\n\nconst DEFAULT_DEPENDENCIES: DpiRunnerDependencies = {\n init: runDpiInit,\n launchPi: launchDpiPi,\n sync: runDpiSync,\n};\n\n/** Dispatches DPI-owned setup commands and forwards every other argument to Pi. */\nexport async function runDpi(\n args: string[],\n dependencies: DpiRunnerDependencies = DEFAULT_DEPENDENCIES,\n): Promise<number> {\n if (args[0] === INIT_COMMAND) return dependencies.init(args);\n if (args[0] === SYNC_COMMAND) return dependencies.sync(args);\n return dependencies.launchPi(args);\n}\n"],"mappings":"4LAIA,MAEM,EAAa,UACb,EAAyB,wBACzB,EAAoB,4BAU1B,eAAe,EAAa,EAAuD,CACjF,IAAM,EAAS,MAAM,OAAO,mCAC5B,GAAI,EAAO,kBAAoB,EAAgB,gBAC7C,MAAU,MAAM,iDAAiD,CAEnE,OAAO,EAIT,SAAgB,EACd,EAAiC,QAAQ,IACzC,EAAiC,QAAQ,KAAK,GACxC,CACN,EAAY,gBAAkB,OAC9B,EAAY,SAAW,KACnB,CAAC,EAAY,IAAyB,MAAM,EAAI,GAAc,EAAkB,KAAK,EAAK,SAAS,EAAW,CAAC,GACjH,EAAY,GAA0B,EAAK,QAAQ,EAAW,EAKlE,eAAsB,EAAY,EAAiC,CACjE,IAAM,EAAkB,MAAM,GAAuB,CAC/C,EAAK,MAAM,EAAa,EAAgB,CACxC,EAAkB,EAA0B,EAAgB,CAClE,QAAQ,MAAQ,MAChB,GAAyB,CACzB,QAAQ,iBAAqB,IAAA,IAE7B,GAAI,CACF,MAAM,EAAG,KAAK,EAAK,CACnB,IAAM,EAAW,QAAQ,SACzB,OAAO,OAAO,GAAa,SAAW,EAAW,OAAO,SAAS,GAAY,IAAK,GAAG,QAC7E,CACR,GAAiB,EAIrB,SAAS,EAAoB,EAA0C,CACrE,MAAO,CACL,oCAAoC,EAAO,YAC3C,GAAI,EAAO,QAAQ,OAAS,EAAI,CAAC,aAAa,EAAO,QAAQ,KAAK,KAAK,GAAG,CAAG,EAAE,CAC/E,GAAI,EAAO,UAAU,OAAS,EAAI,CAAC,aAAa,EAAO,UAAU,KAAK,KAAK,GAAG,CAAG,EAAE,CACnF,GAAI,EAAO,SAAS,OAAS,EAAI,CAAC,aAAa,EAAO,SAAS,KAAK,KAAK,GAAG,CAAG,EAAE,CACjF,GACA,uBACA,GACD,CAAC,KAAK;EAAK,CAId,SAAgB,EACd,EACA,EAAmB,QAAQ,KAAK,CAChC,EAA+C,QAAQ,OAC/C,CACR,IAAM,EAAQ,EAAK,MAAM,EAAE,CACrB,EAAU,EAAM,KAAM,GAAS,IAAS,EAAW,CACzD,GAAI,IAAY,IAAA,GAAW,MAAU,MAAM,4BAA4B,IAAU,CAEjF,IAAM,EAAS,EAA+B,EAAkB,CAAE,MAAO,EAAM,SAAS,EAAW,CAAE,CAAC,CAEtG,OADA,EAAO,MAAM,EAAoB,EAAO,CAAC,CAClC,EAIT,eAAsB,EAAW,EAAiC,CAChE,GAAM,CAAE,gBAAiB,MAAM,OAAO,gCACtC,OAAO,IAAI,EAAa,CAAE,aAAc,WAAY,CAAC,CAAC,QAAQ,EAAK,CAGrE,MAAM,EAA8C,CAClD,KAAM,EACN,SAAU,EACV,KAAM,EACP,CAGD,eAAsB,EACpB,EACA,EAAsC,EACrB,CAGjB,OAFI,EAAK,KAAO,OAAqB,EAAa,KAAK,EAAK,CACxD,EAAK,KAAO,OAAqB,EAAa,KAAK,EAAK,CACrD,EAAa,SAAS,EAAK"}
@@ -0,0 +1,2 @@
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`./modules/moduleResolution.cjs`),n=require(`./piSettings.cjs`);let r=require(`node:url`),i=require(`node:path`);i=e.__toESM(i,1);const a=[`extensions`,`themes`,`theme`,`quietStartup`],o={extensions:[`@agimon-ai/doompi`,`!extensions/**`],themes:[`themes/doom-pi-dark.json`],theme:`doom-pi-dark`,quietStartup:!0};function s(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function c(e){if(e===void 0)return{};let t=JSON.parse(e);if(!s(t))throw SyntaxError(`Pi settings must contain a JSON object`);return t}function l(e,t){if(e===`project`&&t===void 0)return;let n=c(t);if(e===`global`)Object.assign(n,o);else for(let e of a)delete n[e];return JSON.stringify(n,null,2)}function u(e,t){let n=c(e),r=c(t);for(let e of a)Object.hasOwn(n,e)?r[e]=n[e]:delete r[e];return JSON.stringify(r,null,2)}var d=class{backend;constructor(e){this.backend=e}withLock(e,t){this.backend.withLock(e,n=>{let r=t(l(e,n));return r===void 0?void 0:u(n,r)})}};function f(e){if(!s(e)||typeof e.FileSettingsStorage!=`function`)return!1;let t=e.SettingsManager;return typeof t==`function`?typeof Reflect.get(t,`create`)==`function`&&typeof Reflect.get(t,`fromStorage`)==`function`:!1}async function p(){let e=i.default.join(i.default.dirname(t.piCliPath()),`core`,`settings-manager.js`),n=await import((0,r.pathToFileURL)(e).href);if(!f(n))throw Error(`Unsupported Pi settings runtime: ${e}`);return n}function m(e,t=process.env){let r=e.SettingsManager.create;return e.SettingsManager.create=(r,i,a)=>{let o=i??n.piAgentDirectory(t),s=new e.FileSettingsStorage(r,o);return e.SettingsManager.fromStorage(new d(s),a)},()=>{e.SettingsManager.create=r}}exports.installDpiSettingsOverlay=m,exports.loadPiSettingsRuntime=p;
2
+ //# sourceMappingURL=dpiSettings.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpiSettings.cjs","names":["path","piCliPath","piAgentDirectory"],"sources":["../../src/adapters/dpiSettings.ts"],"sourcesContent":["import path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { SettingsManager, SettingsManagerCreateOptions } from '@earendil-works/pi-coding-agent';\nimport { piCliPath } from './modules/moduleResolution.ts';\nimport { piAgentDirectory } from './piSettings.ts';\n\nconst GLOBAL_SCOPE = 'global';\nconst PROJECT_SCOPE = 'project';\nconst MANAGED_KEYS = ['extensions', 'themes', 'theme', 'quietStartup'] as const;\n\nexport const DPI_MANAGED_SETTINGS = {\n extensions: ['@agimon-ai/doompi', '!extensions/**'],\n themes: ['themes/doom-pi-dark.json'],\n theme: 'doom-pi-dark',\n quietStartup: true,\n};\n\nexport type DpiSettingsScope = typeof GLOBAL_SCOPE | typeof PROJECT_SCOPE;\n\nexport interface DpiSettingsStorageBackend {\n withLock(scope: DpiSettingsScope, callback: (current: string | undefined) => string | undefined): void;\n}\n\ninterface SettingsManagerClass {\n create(this: void, cwd: string, agentDir?: string, options?: SettingsManagerCreateOptions): SettingsManager;\n fromStorage(this: void, storage: DpiSettingsStorageBackend, options?: SettingsManagerCreateOptions): SettingsManager;\n}\n\ninterface FileSettingsStorageConstructor {\n new (cwd: string, agentDir: string): DpiSettingsStorageBackend;\n}\n\nexport interface PiSettingsRuntime {\n FileSettingsStorage: FileSettingsStorageConstructor;\n SettingsManager: SettingsManagerClass;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseSettings(content: string | undefined): Record<string, unknown> {\n if (content === undefined) return {};\n const parsed: unknown = JSON.parse(content);\n if (!isRecord(parsed)) throw new SyntaxError('Pi settings must contain a JSON object');\n return parsed;\n}\n\nfunction managedView(scope: DpiSettingsScope, current: string | undefined): string | undefined {\n if (scope === PROJECT_SCOPE && current === undefined) return undefined;\n const settings = parseSettings(current);\n if (scope === GLOBAL_SCOPE) Object.assign(settings, DPI_MANAGED_SETTINGS);\n else for (const key of MANAGED_KEYS) delete settings[key];\n return JSON.stringify(settings, null, 2);\n}\n\nfunction restorePersistedSettings(current: string | undefined, next: string): string {\n const persisted = parseSettings(current);\n const updated = parseSettings(next);\n for (const key of MANAGED_KEYS) {\n if (Object.hasOwn(persisted, key)) updated[key] = persisted[key];\n else delete updated[key];\n }\n return JSON.stringify(updated, null, 2);\n}\n\n/**\n * Presents DoomPi-owned settings to Pi without allowing that overlay to leak\n * into either the global or project settings file when Pi saves another key.\n */\nexport class DpiSettingsStorage implements DpiSettingsStorageBackend {\n private readonly backend: DpiSettingsStorageBackend;\n\n constructor(backend: DpiSettingsStorageBackend) {\n this.backend = backend;\n }\n\n withLock(scope: DpiSettingsScope, callback: (current: string | undefined) => string | undefined): void {\n this.backend.withLock(scope, (current) => {\n const next = callback(managedView(scope, current));\n return next === undefined ? undefined : restorePersistedSettings(current, next);\n });\n }\n}\n\nfunction isPiSettingsRuntime(value: unknown): value is PiSettingsRuntime {\n if (!isRecord(value) || typeof value.FileSettingsStorage !== 'function') return false;\n const settingsManager = value.SettingsManager;\n if (typeof settingsManager !== 'function') return false;\n return (\n typeof Reflect.get(settingsManager, 'create') === 'function' &&\n typeof Reflect.get(settingsManager, 'fromStorage') === 'function'\n );\n}\n\n/** Loads Pi's concrete file storage from the same pinned installation as its CLI. */\nexport async function loadPiSettingsRuntime(): Promise<PiSettingsRuntime> {\n const modulePath = path.join(path.dirname(piCliPath()), 'core', 'settings-manager.js');\n const loaded: unknown = await import(pathToFileURL(modulePath).href);\n if (!isPiSettingsRuntime(loaded)) throw new Error(`Unsupported Pi settings runtime: ${modulePath}`);\n return loaded;\n}\n\n/** Installs the process-local create() hook used by upstream Pi startup and reloads. */\nexport function installDpiSettingsOverlay(\n runtime: PiSettingsRuntime,\n environment: NodeJS.ProcessEnv = process.env,\n): () => void {\n const originalCreate = runtime.SettingsManager.create;\n runtime.SettingsManager.create = (cwd, agentDir, options) => {\n const resolvedAgentDirectory = agentDir ?? piAgentDirectory(environment);\n const storage = new runtime.FileSettingsStorage(cwd, resolvedAgentDirectory);\n return runtime.SettingsManager.fromStorage(new DpiSettingsStorage(storage), options);\n };\n\n return () => {\n runtime.SettingsManager.create = originalCreate;\n };\n}\n"],"mappings":"iMAMA,MAEM,EAAe,CAAC,aAAc,SAAU,QAAS,eAAe,CAEzD,EAAuB,CAClC,WAAY,CAAC,oBAAqB,iBAAiB,CACnD,OAAQ,CAAC,2BAA2B,CACpC,MAAO,eACP,aAAc,GACf,CAsBD,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,EAAM,CAG7E,SAAS,EAAc,EAAsD,CAC3E,GAAI,IAAY,IAAA,GAAW,MAAO,EAAE,CACpC,IAAM,EAAkB,KAAK,MAAM,EAAQ,CAC3C,GAAI,CAAC,EAAS,EAAO,CAAE,MAAU,YAAY,yCAAyC,CACtF,OAAO,EAGT,SAAS,EAAY,EAAyB,EAAiD,CAC7F,GAAI,IAAU,WAAiB,IAAY,IAAA,GAAW,OACtD,IAAM,EAAW,EAAc,EAAQ,CACvC,GAAI,IAAU,SAAc,OAAO,OAAO,EAAU,EAAqB,MACpE,IAAK,IAAM,KAAO,EAAc,OAAO,EAAS,GACrD,OAAO,KAAK,UAAU,EAAU,KAAM,EAAE,CAG1C,SAAS,EAAyB,EAA6B,EAAsB,CACnF,IAAM,EAAY,EAAc,EAAQ,CAClC,EAAU,EAAc,EAAK,CACnC,IAAK,IAAM,KAAO,EACZ,OAAO,OAAO,EAAW,EAAI,CAAE,EAAQ,GAAO,EAAU,GACvD,OAAO,EAAQ,GAEtB,OAAO,KAAK,UAAU,EAAS,KAAM,EAAE,CAOzC,IAAa,EAAb,KAAqE,CACnE,QAEA,YAAY,EAAoC,CAC9C,KAAK,QAAU,EAGjB,SAAS,EAAyB,EAAqE,CACrG,KAAK,QAAQ,SAAS,EAAQ,GAAY,CACxC,IAAM,EAAO,EAAS,EAAY,EAAO,EAAQ,CAAC,CAClD,OAAO,IAAS,IAAA,GAAY,IAAA,GAAY,EAAyB,EAAS,EAAK,EAC/E,GAIN,SAAS,EAAoB,EAA4C,CACvE,GAAI,CAAC,EAAS,EAAM,EAAI,OAAO,EAAM,qBAAwB,WAAY,MAAO,GAChF,IAAM,EAAkB,EAAM,gBAE9B,OADI,OAAO,GAAoB,WAE7B,OAAO,QAAQ,IAAI,EAAiB,SAAS,EAAK,YAClD,OAAO,QAAQ,IAAI,EAAiB,cAAc,EAAK,WAHP,GAQpD,eAAsB,GAAoD,CACxE,IAAM,EAAaA,EAAAA,QAAK,KAAKA,EAAAA,QAAK,QAAQC,EAAAA,WAAW,CAAC,CAAE,OAAQ,sBAAsB,CAChF,EAAkB,MAAM,QAAA,EAAA,EAAA,eAAqB,EAAW,CAAC,MAC/D,GAAI,CAAC,EAAoB,EAAO,CAAE,MAAU,MAAM,oCAAoC,IAAa,CACnG,OAAO,EAIT,SAAgB,EACd,EACA,EAAiC,QAAQ,IAC7B,CACZ,IAAM,EAAiB,EAAQ,gBAAgB,OAO/C,MANA,GAAQ,gBAAgB,QAAU,EAAK,EAAU,IAAY,CAC3D,IAAM,EAAyB,GAAYC,EAAAA,iBAAiB,EAAY,CAClE,EAAU,IAAI,EAAQ,oBAAoB,EAAK,EAAuB,CAC5E,OAAO,EAAQ,gBAAgB,YAAY,IAAI,EAAmB,EAAQ,CAAE,EAAQ,MAGzE,CACX,EAAQ,gBAAgB,OAAS"}