@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.
- package/README.md +242 -14
- package/dist/adapters/compatibility/process.cjs +1 -1
- package/dist/adapters/compatibility/process.mjs +1 -1
- package/dist/adapters/compatibilityContext.cjs +1 -1
- package/dist/adapters/compatibilityContext.cjs.map +1 -1
- package/dist/adapters/compatibilityContext.d.cts.map +1 -1
- package/dist/adapters/compatibilityContext.d.mts.map +1 -1
- package/dist/adapters/compatibilityContext.mjs +1 -1
- package/dist/adapters/compatibilityContext.mjs.map +1 -1
- package/dist/adapters/composer.cjs +1 -1
- package/dist/adapters/composer.mjs +1 -1
- package/dist/adapters/dpiRunner.cjs +3 -0
- package/dist/adapters/dpiRunner.cjs.map +1 -0
- package/dist/adapters/dpiRunner.mjs +3 -0
- package/dist/adapters/dpiRunner.mjs.map +1 -0
- package/dist/adapters/dpiSettings.cjs +2 -0
- package/dist/adapters/dpiSettings.cjs.map +1 -0
- package/dist/adapters/dpiSettings.mjs +2 -0
- package/dist/adapters/dpiSettings.mjs.map +1 -0
- package/dist/adapters/harnessContext.cjs +1 -1
- package/dist/adapters/harnessContext.cjs.map +1 -1
- package/dist/adapters/harnessContext.d.cts.map +1 -1
- package/dist/adapters/harnessContext.d.mts.map +1 -1
- package/dist/adapters/harnessContext.mjs +1 -1
- package/dist/adapters/harnessContext.mjs.map +1 -1
- package/dist/adapters/matrixSwitcher.cjs +1 -1
- package/dist/adapters/matrixSwitcher.cjs.map +1 -1
- package/dist/adapters/matrixSwitcher.d.cts.map +1 -1
- package/dist/adapters/matrixSwitcher.d.mts.map +1 -1
- package/dist/adapters/matrixSwitcher.mjs +1 -1
- package/dist/adapters/matrixSwitcher.mjs.map +1 -1
- package/dist/adapters/pluginMaterializer.cjs +2 -0
- package/dist/adapters/pluginMaterializer.cjs.map +1 -0
- package/dist/adapters/pluginMaterializer.mjs +2 -0
- package/dist/adapters/pluginMaterializer.mjs.map +1 -0
- package/dist/adapters/resourceCollector.cjs +2 -2
- package/dist/adapters/resourceCollector.cjs.map +1 -1
- package/dist/adapters/resourceCollector.d.cts +3 -3
- package/dist/adapters/resourceCollector.d.cts.map +1 -1
- package/dist/adapters/resourceCollector.d.mts +3 -3
- package/dist/adapters/resourceCollector.d.mts.map +1 -1
- package/dist/adapters/resourceCollector.mjs +2 -2
- package/dist/adapters/resourceCollector.mjs.map +1 -1
- package/dist/adapters/skillCatalog.cjs +1 -1
- package/dist/adapters/skillCatalog.cjs.map +1 -1
- package/dist/adapters/skillCatalog.d.cts.map +1 -1
- package/dist/adapters/skillCatalog.d.mts.map +1 -1
- package/dist/adapters/skillCatalog.mjs +1 -1
- package/dist/adapters/skillCatalog.mjs.map +1 -1
- package/dist/adapters/startupPrecompiler.cjs.map +1 -1
- package/dist/adapters/startupPrecompiler.d.cts +1 -1
- package/dist/adapters/startupPrecompiler.d.mts +1 -1
- package/dist/adapters/startupPrecompiler.mjs.map +1 -1
- package/dist/adapters/syncState.cjs +1 -1
- package/dist/adapters/syncState.cjs.map +1 -1
- package/dist/adapters/syncState.d.cts +2 -1
- package/dist/adapters/syncState.d.cts.map +1 -1
- package/dist/adapters/syncState.d.mts +2 -1
- package/dist/adapters/syncState.d.mts.map +1 -1
- package/dist/adapters/syncState.mjs +1 -1
- package/dist/adapters/syncState.mjs.map +1 -1
- package/dist/adapters/syncedRuntimeBuilder.cjs +1 -1
- package/dist/adapters/syncedRuntimeBuilder.cjs.map +1 -1
- package/dist/adapters/syncedRuntimeBuilder.d.cts +1 -1
- package/dist/adapters/syncedRuntimeBuilder.d.mts +1 -1
- package/dist/adapters/syncedRuntimeBuilder.mjs +1 -1
- package/dist/adapters/syncedRuntimeBuilder.mjs.map +1 -1
- package/dist/bin/cli.cjs +1 -1
- package/dist/bin/cli.cjs.map +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/bin/cli.mjs.map +1 -1
- package/dist/bin/dpi.cjs +3 -0
- package/dist/bin/dpi.cjs.map +1 -0
- package/dist/bin/dpi.d.cts +1 -0
- package/dist/bin/dpi.d.mts +1 -0
- package/dist/bin/dpi.mjs +3 -0
- package/dist/bin/dpi.mjs.map +1 -0
- package/dist/commands/buildCommand.cjs +2 -2
- package/dist/commands/buildCommand.mjs +2 -2
- package/dist/commands/cli/cliApp.cjs +1 -1
- package/dist/commands/cli/cliApp.cjs.map +1 -1
- package/dist/commands/cli/cliApp.d.cts.map +1 -1
- package/dist/commands/cli/cliApp.d.mts.map +1 -1
- package/dist/commands/cli/cliApp.mjs +1 -1
- package/dist/commands/cli/cliApp.mjs.map +1 -1
- package/dist/commands/cli/help.cjs +1 -3
- package/dist/commands/cli/help.cjs.map +1 -1
- package/dist/commands/cli/help.mjs +1 -3
- package/dist/commands/cli/help.mjs.map +1 -1
- package/dist/commands/compatibilityCommand.cjs +1 -1
- package/dist/commands/compatibilityCommand.mjs +1 -1
- package/dist/commands/index.cjs +1 -1
- package/dist/commands/index.d.cts +2 -3
- package/dist/commands/index.d.mts +2 -3
- package/dist/commands/index.mjs +1 -1
- package/dist/commands/initCommand.cjs +1 -1
- package/dist/commands/initCommand.mjs +1 -1
- package/dist/commands/initPresenter.cjs +1 -1
- package/dist/commands/initPresenter.cjs.map +1 -1
- package/dist/commands/initPresenter.mjs +1 -1
- package/dist/commands/initPresenter.mjs.map +1 -1
- package/dist/commands/launchCommand.cjs +1 -1
- package/dist/commands/launchCommand.mjs +1 -1
- package/dist/commands/syncCommand.cjs +4 -4
- package/dist/commands/syncCommand.cjs.map +1 -1
- package/dist/commands/syncCommand.d.cts +11 -4
- package/dist/commands/syncCommand.d.cts.map +1 -1
- package/dist/commands/syncCommand.d.mts +11 -4
- package/dist/commands/syncCommand.d.mts.map +1 -1
- package/dist/commands/syncCommand.mjs +4 -4
- package/dist/commands/syncCommand.mjs.map +1 -1
- package/dist/commands/syncPipeline.cjs +2 -0
- package/dist/commands/syncPipeline.cjs.map +1 -0
- package/dist/commands/syncPipeline.mjs +2 -0
- package/dist/commands/syncPipeline.mjs.map +1 -0
- package/dist/entries/majorMode.cjs +1 -1
- package/dist/entries/majorMode.d.cts +2 -2
- package/dist/entries/majorMode.d.mts +2 -2
- package/dist/entries/majorMode.mjs +1 -1
- package/dist/extensions/entries/domains.cjs +1 -1
- package/dist/extensions/entries/domains.cjs.map +1 -1
- package/dist/extensions/entries/domains.d.cts +1 -1
- package/dist/extensions/entries/domains.d.cts.map +1 -1
- package/dist/extensions/entries/domains.d.mts +1 -1
- package/dist/extensions/entries/domains.d.mts.map +1 -1
- package/dist/extensions/entries/domains.mjs +1 -1
- package/dist/extensions/entries/domains.mjs.map +1 -1
- package/dist/extensions/entries/majorMode.cjs +4 -4
- package/dist/extensions/entries/majorMode.cjs.map +1 -1
- package/dist/extensions/entries/majorMode.d.cts +1 -3
- package/dist/extensions/entries/majorMode.d.cts.map +1 -1
- package/dist/extensions/entries/majorMode.d.mts +1 -3
- package/dist/extensions/entries/majorMode.d.mts.map +1 -1
- package/dist/extensions/entries/majorMode.mjs +4 -4
- package/dist/extensions/entries/majorMode.mjs.map +1 -1
- package/dist/extensions/entries/repositoryHooks.cjs +1 -1
- package/dist/extensions/entries/repositoryHooks.mjs +1 -1
- package/dist/extensions/entries/styleSystem.cjs +2 -2
- package/dist/extensions/entries/styleSystem.cjs.map +1 -1
- package/dist/extensions/entries/styleSystem.mjs +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -3
- package/dist/index.d.mts +2 -3
- package/dist/index.mjs +1 -1
- package/dist/pi-cache-optimizer-D9beVnnH.mjs.map +1 -1
- package/dist/schemas/majorModeVoiceTools.cjs +2 -0
- package/dist/schemas/majorModeVoiceTools.cjs.map +1 -0
- package/dist/schemas/majorModeVoiceTools.mjs +2 -0
- package/dist/schemas/majorModeVoiceTools.mjs.map +1 -0
- package/dist/services/config/index.d.mts +2 -2
- package/dist/services/index.cjs +1 -1
- package/dist/services/index.mjs +1 -1
- package/dist/types/interfaces/harness.d.cts +1 -1
- package/dist/types/interfaces/harness.d.mts +1 -1
- package/package.json +36 -32
- package/dist/commands/buildCommand.d.cts +0 -27
- package/dist/commands/buildCommand.d.cts.map +0 -1
- package/dist/commands/buildCommand.d.mts +0 -27
- 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
|
|
26
|
+
npm install -g @agimon-ai/doompi
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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
|
-
|
|
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.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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:
|
|
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{
|
|
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
|
|
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
|
|
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":";;;;
|
|
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":";;;;
|
|
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{
|
|
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
|
|
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(
|
|
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
|
|
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"}
|