@agimon-ai/doompi 0.0.1-alpha.15 → 0.0.1-alpha.17
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 +280 -19
- 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/helpSkills.cjs +2 -0
- package/dist/adapters/helpSkills.cjs.map +1 -0
- package/dist/adapters/helpSkills.mjs +2 -0
- package/dist/adapters/helpSkills.mjs.map +1 -0
- 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/modules/moduleResolution.cjs +1 -1
- package/dist/adapters/modules/moduleResolution.cjs.map +1 -1
- package/dist/adapters/modules/moduleResolution.d.cts +5 -4
- package/dist/adapters/modules/moduleResolution.d.cts.map +1 -1
- package/dist/adapters/modules/moduleResolution.d.mts +5 -4
- package/dist/adapters/modules/moduleResolution.d.mts.map +1 -1
- package/dist/adapters/modules/moduleResolution.mjs +1 -1
- package/dist/adapters/modules/moduleResolution.mjs.map +1 -1
- package/dist/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 +6 -1
- package/dist/adapters/skillCatalog.d.cts.map +1 -1
- package/dist/adapters/skillCatalog.d.mts +6 -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 +5 -2
- package/dist/adapters/syncState.d.cts.map +1 -1
- package/dist/adapters/syncState.d.mts +5 -2
- 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.cjs.map +1 -1
- package/dist/commands/buildCommand.mjs +2 -2
- package/dist/commands/buildCommand.mjs.map +1 -1
- 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/skills.cjs +3 -2
- package/dist/extensions/entries/skills.cjs.map +1 -1
- package/dist/extensions/entries/skills.d.cts.map +1 -1
- package/dist/extensions/entries/skills.d.mts.map +1 -1
- package/dist/extensions/entries/skills.mjs +3 -2
- package/dist/extensions/entries/skills.mjs.map +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/extensionAssembler.cjs +1 -1
- package/dist/services/extensionAssembler.cjs.map +1 -1
- package/dist/services/extensionAssembler.d.cts +2 -2
- package/dist/services/extensionAssembler.d.cts.map +1 -1
- package/dist/services/extensionAssembler.d.mts +2 -2
- package/dist/services/extensionAssembler.d.mts.map +1 -1
- package/dist/services/extensionAssembler.mjs +1 -1
- package/dist/services/extensionAssembler.mjs.map +1 -1
- package/dist/services/index.cjs +1 -1
- package/dist/services/index.mjs +1 -1
- package/dist/services/syncState.cjs +1 -1
- package/dist/services/syncState.d.cts +2 -2
- package/dist/services/syncState.d.mts +2 -2
- package/dist/services/syncState.mjs +1 -1
- package/dist/types/interfaces/harness.d.cts +1 -1
- package/dist/types/interfaces/harness.d.mts +1 -1
- package/package.json +37 -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
|
@@ -13,7 +13,7 @@ MCP servers, and system prompts into config instead of background noise.
|
|
|
13
13
|
Plugin systems scope what an agent knows. Nothing scopes what it can reach. Claude Code's
|
|
14
14
|
`enableAllProjectMcpServers` and static denylist are repository-wide. Doompi draws that
|
|
15
15
|
boundary around the session. Pick a major mode and some domains; add a profile if you want
|
|
16
|
-
one.
|
|
16
|
+
one. Four YAML files decide what loads; `doompi --explain` tells you what got in, why, and
|
|
17
17
|
what it costs before launch.
|
|
18
18
|
|
|
19
19
|
It borrows its shape from [Doom Emacs Core](https://github.com/doomemacs/core): quick to
|
|
@@ -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
|
|
@@ -60,8 +93,9 @@ or whatever else you do. Define as many as you like; only one is active at a tim
|
|
|
60
93
|
can switch it without leaving the session.
|
|
61
94
|
|
|
62
95
|
Minor modes are switches inside that base. They start off, stack freely, and bring their
|
|
63
|
-
own tools and instructions when turned on. Doompi ships
|
|
96
|
+
own tools and instructions when turned on. Doompi ships six:
|
|
64
97
|
|
|
98
|
+
- **Help mode** — expose package-owned guidance only while you need it.
|
|
65
99
|
- **Plan mode** — make the repository read-only while you agree on an approach.
|
|
66
100
|
- **Loop mode** — run a prompt now, then run it again on a schedule.
|
|
67
101
|
- **Goal mode** — keep one objective in view until it is done or dismissed.
|
|
@@ -73,6 +107,31 @@ own tools and instructions when turned on. Doompi ships five:
|
|
|
73
107
|
A domain is a named group of Pi plugins. It carries the skills and MCP servers for one
|
|
74
108
|
kind of work, and `/domains` switches it while the session is running.
|
|
75
109
|
|
|
110
|
+
Plugins are catalogued once and domains refer to their names. A configured root may be a
|
|
111
|
+
Codex-compatible marketplace or a folder whose direct children are plugins, so a repository
|
|
112
|
+
with many plugins does not need one entry per directory:
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
plugins:
|
|
116
|
+
roots: [plugins]
|
|
117
|
+
entries:
|
|
118
|
+
remote-review:
|
|
119
|
+
source: url
|
|
120
|
+
url: https://github.com/acme/review-plugin.git
|
|
121
|
+
ref: v1.2.0
|
|
122
|
+
|
|
123
|
+
domains:
|
|
124
|
+
development:
|
|
125
|
+
description: Implementation and code-review tools.
|
|
126
|
+
plugins: [pi-development, remote-review]
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
DoomPi also checks personal and repository Codex marketplace layouts. Marketplace IDs use
|
|
130
|
+
`plugin@marketplace`. Remote Git and npm sources are downloaded once into the persistent
|
|
131
|
+
`~/.pi/.doom/plugin-cache` directory. Cache entries are reused until their source descriptor
|
|
132
|
+
changes; use a Git SHA or exact npm version for reproducible installs. Home and repository
|
|
133
|
+
catalogs merge, and repository names replace matching home names.
|
|
134
|
+
|
|
76
135
|
A blog is not one task. Research it, draft it, make the assets, then review it. Turn on the
|
|
77
136
|
`visual` domain while making assets; the other three steps have no reason to carry it.
|
|
78
137
|
|
|
@@ -81,6 +140,25 @@ A blog is not one task. Research it, draft it, make the assets, then review it.
|
|
|
81
140
|
An LLM has no house style until you give it one. A profile can supply a narrative, brand
|
|
82
141
|
rules, or a different voice. It is optional; no profile is a perfectly good profile.
|
|
83
142
|
|
|
143
|
+
Profile roots remove the need to list every persona folder. A root may itself contain the
|
|
144
|
+
persona files, or its direct-child folders become profiles named after those folders. DoomPi
|
|
145
|
+
recognizes `profile.md`, `SOUL.md`, and `AGENTS.md` and never searches deeper directories.
|
|
146
|
+
|
|
147
|
+
```yaml
|
|
148
|
+
profiles:
|
|
149
|
+
roots: [agents/acme]
|
|
150
|
+
entries:
|
|
151
|
+
editor:
|
|
152
|
+
persona: agents/special/editor
|
|
153
|
+
env:
|
|
154
|
+
EDITOR_MODE: strict
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Roots from the home and repository files accumulate relative to their declaring config.
|
|
158
|
+
Repository discoveries replace same-named home discoveries. Explicit entries override
|
|
159
|
+
discovery and can add string environment defaults; repository entries replace matching home
|
|
160
|
+
entries. Select one at launch with `--profile editor` or switch with `/profile`.
|
|
161
|
+
|
|
84
162
|
## What this buys you
|
|
85
163
|
|
|
86
164
|
Every tool schema and skill name competes for the same context. Loading less has two
|
|
@@ -100,7 +178,7 @@ choices, then press the next key.
|
|
|
100
178
|
|
|
101
179
|
When the keyboard is the wrong tool, autonomous Voice mode keeps the conversation going.
|
|
102
180
|
You can talk to the agent while doing the chores instead of carrying a laptop around the
|
|
103
|
-
house.
|
|
181
|
+
house, and the primary agent can speak its own opening, milestone, and final updates.
|
|
104
182
|
|
|
105
183
|
### Autopilot
|
|
106
184
|
|
|
@@ -155,10 +233,11 @@ them one at a time.
|
|
|
155
233
|
|
|
156
234
|
### Configuration and composition
|
|
157
235
|
|
|
158
|
-
`@agimon-ai/doompi` is both an extension and the command-line config compiler.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
236
|
+
`@agimon-ai/doompi` is both an extension and the command-line config compiler. `dpi init`
|
|
237
|
+
creates repository config for an isolated experiment, while `doompi init` creates the personal
|
|
238
|
+
config and registers the permanent Pi integration. The sync commands resolve every major mode
|
|
239
|
+
and domain into a distribution Pi can load quickly. A large major mode with 15 extensions adds
|
|
240
|
+
only 400 ms of code startup time.
|
|
162
241
|
|
|
163
242
|
### Leader key
|
|
164
243
|
|
|
@@ -192,6 +271,15 @@ Ordinary compaction waits for one summary to save an overgrown session.
|
|
|
192
271
|
The work runs off-thread. Each checkpoint carries the live plan, task graph, team state,
|
|
193
272
|
and user request with it, so coordination does not have to be guessed back out of prose.
|
|
194
273
|
|
|
274
|
+
### Help mode
|
|
275
|
+
|
|
276
|
+
`@agimon-ai/doompi-help` keeps package guidance out of the default prompt. A fresh parent
|
|
277
|
+
session performs no Help retrieval and exposes no Help skills. Use `SPC h e`, or the existing
|
|
278
|
+
`minor_mode` client in headless sessions, to activate the package indexes; use the same action
|
|
279
|
+
to deactivate them before the next interaction. The initial contributors expose
|
|
280
|
+
`doompi-help`, `workflow-help`, and `doompi-config-help`. Child sessions never assemble the
|
|
281
|
+
Help runtime.
|
|
282
|
+
|
|
195
283
|
### MCP
|
|
196
284
|
|
|
197
285
|
`@agimon-ai/doompi-mcp` is the gate between a session and its servers. It reads `.mcp.json`
|
|
@@ -243,5 +331,178 @@ explicit handoffs rather than one long conversation.
|
|
|
243
331
|
### Voice mode
|
|
244
332
|
|
|
245
333
|
`@agimon-ai/doompi-voice` records and transcribes speech locally; audio stays on the
|
|
246
|
-
machine.
|
|
247
|
-
|
|
334
|
+
machine. `SPC v v` is one-shot manual dictation and never enables Voice tools. `SPC v a`
|
|
335
|
+
toggles autonomous capture; only its exact-active TUI session receives the two Voice
|
|
336
|
+
façades plus the standalone `narrate` tool.
|
|
337
|
+
|
|
338
|
+
While `narrate` is available, the primary agent calls it before every user-facing final
|
|
339
|
+
response. One concise spoken answer is enough for a short conversation or clarification;
|
|
340
|
+
longer work also gets an opening and meaningful milestone calls. Each ready-to-speak
|
|
341
|
+
utterance is limited to 4,096 characters, waits for physical playback, and returns
|
|
342
|
+
`completed`, `interrupted`, `superseded`, or `failed`.
|
|
343
|
+
|
|
344
|
+
If the agent never attempts `narrate` during a run, exact-active Voice speaks one sanitized
|
|
345
|
+
turn-end fallback rather than leaving the final response silent. Finals of at most 320
|
|
346
|
+
characters use deterministic speech; longer finals use the configured
|
|
347
|
+
`voice.autoCapture.model` for one bounded summary, with deterministic degradation on
|
|
348
|
+
failure or timeout. Any `narrate` attempt suppresses this safety net, so it cannot duplicate
|
|
349
|
+
or retry direct speech. Voice does not generate automatic intent, plan, milestone, or tool
|
|
350
|
+
progress narration. External task, workflow, and user-feedback narration remains
|
|
351
|
+
available, and the same model continues to provide bounded command correction.
|
|
352
|
+
|
|
353
|
+
## Configuration
|
|
354
|
+
|
|
355
|
+
Doompi reads four configuration files:
|
|
356
|
+
|
|
357
|
+
- `config.yaml` defines runtime settings such as trust, editor, planning, and voice behavior.
|
|
358
|
+
- `modes.yaml` defines extension layers and major modes.
|
|
359
|
+
- `domains.yaml` catalogs plugins and sets session access.
|
|
360
|
+
- `profiles.yaml` supplies persona files and environment defaults.
|
|
361
|
+
|
|
362
|
+
Each matrix file has two optional layers: personal defaults in `~/.pi/.doom/` and repository
|
|
363
|
+
overrides in `<repository>/.doom/`. Doompi loads both. Unique named entries from either layer
|
|
364
|
+
remain available; a same-named repository entry replaces the complete personal entry. Plugin
|
|
365
|
+
and profile roots from both layers are retained. Relative paths in personal config resolve
|
|
366
|
+
from `~/.pi/.doom/`; relative paths in repository config resolve from the repository root.
|
|
367
|
+
|
|
368
|
+
### `modes.yaml`: choose behavior
|
|
369
|
+
|
|
370
|
+
A layer is an ordered bundle of extension packages and hook groups. A major mode names the
|
|
371
|
+
layers that should run together. Packages may be bare strings, or mappings when the package
|
|
372
|
+
accepts configuration:
|
|
373
|
+
|
|
374
|
+
```yaml
|
|
375
|
+
layers:
|
|
376
|
+
team:
|
|
377
|
+
packages:
|
|
378
|
+
- name: '@agimon-ai/doompi-team'
|
|
379
|
+
config:
|
|
380
|
+
models:
|
|
381
|
+
- model: provider/model-id
|
|
382
|
+
thinking: high
|
|
383
|
+
review:
|
|
384
|
+
packages:
|
|
385
|
+
- '@scope/review-extension'
|
|
386
|
+
|
|
387
|
+
defaultMajorMode: copilot
|
|
388
|
+
majorMode:
|
|
389
|
+
minimal:
|
|
390
|
+
description: Lean sessions with delegation and little else.
|
|
391
|
+
layers: [team]
|
|
392
|
+
copilot:
|
|
393
|
+
description: General coding with delegation and review tools.
|
|
394
|
+
layers: [team, review]
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Order matters: Doompi assembles layers and their packages from left to right. Put settings
|
|
398
|
+
under the package that consumes them; a layer is composition, not a mystery bag of shared
|
|
399
|
+
configuration. Home and repository `layers` and `majorMode` records merge by name, with the
|
|
400
|
+
repository definition winning a collision.
|
|
401
|
+
|
|
402
|
+
Choose a mode with `--major-mode copilot`, switch it with `/mode`, or change
|
|
403
|
+
`defaultMajorMode` when one mode should be the ordinary starting point.
|
|
404
|
+
|
|
405
|
+
### `domains.yaml`: choose content and access
|
|
406
|
+
|
|
407
|
+
Plugins are catalogued once, then domains refer to their names. A root can be a marketplace,
|
|
408
|
+
a single plugin, or a container whose direct-child folders are plugins. Discovery is
|
|
409
|
+
intentionally nonrecursive: a tool buried five directories down should not load by accident.
|
|
410
|
+
|
|
411
|
+
```yaml
|
|
412
|
+
defaultDomains: [development]
|
|
413
|
+
|
|
414
|
+
plugins:
|
|
415
|
+
roots: [plugins]
|
|
416
|
+
entries:
|
|
417
|
+
remote-review:
|
|
418
|
+
source: url
|
|
419
|
+
url: https://github.com/acme/review-plugin.git
|
|
420
|
+
ref: v1.2.0
|
|
421
|
+
published-research:
|
|
422
|
+
source: npm
|
|
423
|
+
package: '@acme/research-plugin'
|
|
424
|
+
version: 1.4.0
|
|
425
|
+
|
|
426
|
+
domains:
|
|
427
|
+
development:
|
|
428
|
+
description: Repository implementation tools.
|
|
429
|
+
plugins: [coding-tools]
|
|
430
|
+
review:
|
|
431
|
+
description: Focused review skills with a narrow MCP boundary.
|
|
432
|
+
plugins:
|
|
433
|
+
- name: remote-review
|
|
434
|
+
skills: [typescript]
|
|
435
|
+
agents: [reviewer]
|
|
436
|
+
hooks: false
|
|
437
|
+
mcp: true
|
|
438
|
+
mcp:
|
|
439
|
+
servers: [filesystem]
|
|
440
|
+
proxy: [github]
|
|
441
|
+
|
|
442
|
+
aliases:
|
|
443
|
+
work: [development, review]
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
Here, `coding-tools` is discovered from `plugins/coding-tools`; its manifest name, or its
|
|
447
|
+
folder name when no manifest name exists, becomes the catalog ID. Local roots and entries
|
|
448
|
+
resolve beside the declaring file. Git and npm entries are cached in
|
|
449
|
+
`~/.pi/.doom/plugin-cache`; pin a Git SHA or exact package version when reproducibility
|
|
450
|
+
matters. Domains may load an entire plugin or select only its skills, agents, hooks, and MCP
|
|
451
|
+
configuration. The optional `mcp` mapping is an allowlist, not a request to start every server
|
|
452
|
+
in the repository.
|
|
453
|
+
|
|
454
|
+
Select one or more domains with `--domains development,review`, use an alias such as
|
|
455
|
+
`--domains work`, or switch them with `/domains`. `--no-domains` is useful when the right
|
|
456
|
+
amount of repository context is none.
|
|
457
|
+
|
|
458
|
+
### `profiles.yaml`: choose a point of view
|
|
459
|
+
|
|
460
|
+
A profile directory becomes discoverable when it directly contains `profile.md`, `SOUL.md`,
|
|
461
|
+
or `AGENTS.md`. A root may be one profile or a container of direct-child profiles. The folder
|
|
462
|
+
name becomes the profile name; Doompi concatenates those three files in that order.
|
|
463
|
+
|
|
464
|
+
```yaml
|
|
465
|
+
profiles:
|
|
466
|
+
roots: [personas]
|
|
467
|
+
entries:
|
|
468
|
+
release-writer:
|
|
469
|
+
persona: personas/release-writer
|
|
470
|
+
env:
|
|
471
|
+
BRAND: acme
|
|
472
|
+
TONE: concise
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
With that config, `personas/release-writer/profile.md` is enough to discover
|
|
476
|
+
`release-writer`. The explicit entry is optional; use one when the profile needs another name,
|
|
477
|
+
an exact persona path, or string environment defaults. Explicit entries override discovered
|
|
478
|
+
folders. Already exported environment values win, so selecting a profile never quietly
|
|
479
|
+
replaces a value supplied by the caller.
|
|
480
|
+
|
|
481
|
+
Discovery never recurses. Persona paths must remain under `agents/` or a root declared in the
|
|
482
|
+
same file, and symlinks may not escape the persona boundary. Legacy profiles written directly
|
|
483
|
+
under `profiles` still load, but new configuration should use `roots` and `entries`.
|
|
484
|
+
|
|
485
|
+
Select a profile with `--profile release-writer` or switch it with `/profile`. Leaving the
|
|
486
|
+
catalog empty is valid; no profile remains a first-class choice.
|
|
487
|
+
|
|
488
|
+
### Check the matrix before launch
|
|
489
|
+
|
|
490
|
+
The fastest configuration debugger is the one that does not start a model:
|
|
491
|
+
|
|
492
|
+
```bash
|
|
493
|
+
doompi --major-mode copilot --domains work --profile release-writer --explain
|
|
494
|
+
dpi sync
|
|
495
|
+
doompi sync --check
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
`--explain` prints the resolved mode, domains, profile, plugins, skills, agents, MCP boundary,
|
|
499
|
+
and estimated prompt cost. `dpi sync` resolves the repository configuration and synchronizes
|
|
500
|
+
DPI without registering it in normal Pi settings. `doompi sync --check` turns drift into a
|
|
501
|
+
non-zero exit code for CI. If the explanation is surprising, fix the YAML before paying a model
|
|
502
|
+
to be surprised with you.
|
|
503
|
+
|
|
504
|
+
## Package release order
|
|
505
|
+
|
|
506
|
+
Publish `@agimon-ai/doompi-extension-contracts` first, then `@agimon-ai/doompi-help`, and only
|
|
507
|
+
then the `@agimon-ai/doompi` runtime that consumes them. Generated changelogs remain owned by
|
|
508
|
+
the release tooling.
|
|
@@ -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
|