@agimon-ai/po-config 0.0.0-alpha.2 → 0.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/LICENSE +149 -21
  2. package/README.md +11 -11
  3. package/dist/agentPluginMcp.cjs +313 -134
  4. package/dist/agentPluginMcp.cjs.map +1 -1
  5. package/dist/agentPluginMcp.d.mts +22 -4
  6. package/dist/agentPluginMcp.d.mts.map +1 -1
  7. package/dist/agentPluginMcp.mjs +312 -134
  8. package/dist/agentPluginMcp.mjs.map +1 -1
  9. package/dist/apiContracts.cjs.map +1 -1
  10. package/dist/apiContracts.mjs.map +1 -1
  11. package/dist/atomicJson-D3MHqnLW.cjs +59 -0
  12. package/dist/atomicJson-D3MHqnLW.cjs.map +1 -0
  13. package/dist/atomicJson-Dj3rlZbD.mjs +40 -0
  14. package/dist/atomicJson-Dj3rlZbD.mjs.map +1 -0
  15. package/dist/atomicJson.cjs +4 -2
  16. package/dist/atomicJson.d.mts +2 -2
  17. package/dist/atomicJson.mjs +3 -2
  18. package/dist/{index-BT29GZx5.d.mts → completion-Ba0TiBHa.d.mts} +58 -27
  19. package/dist/completion-Ba0TiBHa.d.mts.map +1 -0
  20. package/dist/config-BBvn_ZLP.mjs +1 -0
  21. package/dist/config-Cdybp9rT.cjs +155 -0
  22. package/dist/config-Cdybp9rT.cjs.map +1 -0
  23. package/dist/config-Cxc2xw54.mjs +112 -0
  24. package/dist/config-Cxc2xw54.mjs.map +1 -0
  25. package/dist/{config-D2HbBLzo.d.mts → config-pxC7FyUJ.d.mts} +33 -33
  26. package/dist/config-pxC7FyUJ.d.mts.map +1 -0
  27. package/dist/config.cjs +21 -17
  28. package/dist/config.d.mts +3 -3
  29. package/dist/config.mjs +4 -3
  30. package/dist/{configPolicy-Ce1QKDxa.cjs → configPolicy-CowlLhK1.cjs} +99 -99
  31. package/dist/configPolicy-CowlLhK1.cjs.map +1 -0
  32. package/dist/{configPolicy-DCQgF5-f.mjs → configPolicy-DueX0k6i.mjs} +84 -84
  33. package/dist/configPolicy-DueX0k6i.mjs.map +1 -0
  34. package/dist/configSchema.d.mts +2 -2
  35. package/dist/configWriter-DCASRzr-.mjs +180 -0
  36. package/dist/configWriter-DCASRzr-.mjs.map +1 -0
  37. package/dist/configWriter-DGO0gmXo.cjs +218 -0
  38. package/dist/configWriter-DGO0gmXo.cjs.map +1 -0
  39. package/dist/configWriter.cjs +7 -4
  40. package/dist/configWriter.d.mts +2 -2
  41. package/dist/configWriter.mjs +1 -2
  42. package/dist/core-B0Qg0Qq2.cjs +224 -0
  43. package/dist/core-B0Qg0Qq2.cjs.map +1 -0
  44. package/dist/core-DKWW9gkh.mjs +139 -0
  45. package/dist/core-DKWW9gkh.mjs.map +1 -0
  46. package/dist/{domains-DGCb7uMC.cjs → domains-CiDUsRiX.cjs} +473 -171
  47. package/dist/domains-CiDUsRiX.cjs.map +1 -0
  48. package/dist/{domains-BroCVHrS.mjs → domains-IlieGHaY.mjs} +437 -170
  49. package/dist/domains-IlieGHaY.mjs.map +1 -0
  50. package/dist/domains.cjs +9 -3
  51. package/dist/domains.d.mts +3 -3
  52. package/dist/domains.mjs +3 -3
  53. package/dist/extensions/mcp-ui.mjs +1 -1
  54. package/dist/extensions/mcp-ui.mjs.map +1 -1
  55. package/dist/extensions/mcp.cjs +3 -3
  56. package/dist/extensions/mcp.cjs.map +1 -1
  57. package/dist/extensions/mcp.d.mts +1 -1
  58. package/dist/extensions/mcp.mjs +2 -2
  59. package/dist/extensions/mcp.mjs.map +1 -1
  60. package/dist/extensions/server.cjs +55 -47
  61. package/dist/extensions/server.cjs.map +1 -1
  62. package/dist/extensions/server.d.mts +2 -2
  63. package/dist/extensions/server.d.mts.map +1 -1
  64. package/dist/extensions/server.mjs +56 -48
  65. package/dist/extensions/server.mjs.map +1 -1
  66. package/dist/{harnessState-Dn_S7fB9.mjs → harnessState-8lZda_8r.mjs} +2 -2
  67. package/dist/{harnessState-Dn_S7fB9.mjs.map → harnessState-8lZda_8r.mjs.map} +1 -1
  68. package/dist/{harnessState-CCyBeutB.cjs → harnessState-BrmH0lG5.cjs} +2 -2
  69. package/dist/{harnessState-CCyBeutB.cjs.map → harnessState-BrmH0lG5.cjs.map} +1 -1
  70. package/dist/harnessState.cjs +1 -1
  71. package/dist/harnessState.d.mts +1 -1
  72. package/dist/harnessState.mjs +1 -2
  73. package/dist/{harnessStore-CJSxdSkV.cjs → harnessStore-BinxGITh.cjs} +189 -81
  74. package/dist/harnessStore-BinxGITh.cjs.map +1 -0
  75. package/dist/{harnessStore-CltwLB7M.mjs → harnessStore-w8zHmJ_H.mjs} +160 -82
  76. package/dist/harnessStore-w8zHmJ_H.mjs.map +1 -0
  77. package/dist/harnessStore.cjs +6 -1
  78. package/dist/harnessStore.d.mts +2 -2
  79. package/dist/harnessStore.mjs +1 -2
  80. package/dist/index-7RuIAWX1.d.mts +63 -0
  81. package/dist/index-7RuIAWX1.d.mts.map +1 -0
  82. package/dist/{index-CkDDvVQt.d.mts → index-BNcG0voG.d.mts} +61 -16
  83. package/dist/index-BNcG0voG.d.mts.map +1 -0
  84. package/dist/{index-Dy_-m7gx.d.mts → index-BTOU4XiI.d.mts} +3 -3
  85. package/dist/{index-Dy_-m7gx.d.mts.map → index-BTOU4XiI.d.mts.map} +1 -1
  86. package/dist/index-COokUToB.d.mts +83 -0
  87. package/dist/index-COokUToB.d.mts.map +1 -0
  88. package/dist/index-D3vGEYup.d.mts +135 -0
  89. package/dist/index-D3vGEYup.d.mts.map +1 -0
  90. package/dist/{index-Ch7ptOkW.d.mts → index-DNEK9W6n.d.mts} +26 -16
  91. package/dist/index-DNEK9W6n.d.mts.map +1 -0
  92. package/dist/index-D_OtYtsl.d.mts +37 -0
  93. package/dist/index-D_OtYtsl.d.mts.map +1 -0
  94. package/dist/{index-DNk4q0Qm.d.mts → index-Nbj2iQWw.d.mts} +19 -25
  95. package/dist/index-Nbj2iQWw.d.mts.map +1 -0
  96. package/dist/{index-CEUc7m16.d.mts → index-dYgF03lE.d.mts} +82 -32
  97. package/dist/index-dYgF03lE.d.mts.map +1 -0
  98. package/dist/index-fTuf8tVH.d.mts +34 -0
  99. package/dist/index-fTuf8tVH.d.mts.map +1 -0
  100. package/dist/index-nVcEC1jO.d.mts +62 -0
  101. package/dist/index-nVcEC1jO.d.mts.map +1 -0
  102. package/dist/index.cjs +81 -59
  103. package/dist/index.d.mts +16 -15
  104. package/dist/index.mjs +17 -15
  105. package/dist/{init-Cd3Ki6Ub.cjs → init-BdZ-gqqk.cjs} +209 -59
  106. package/dist/init-BdZ-gqqk.cjs.map +1 -0
  107. package/dist/{init-DVzhiCUE.mjs → init-DG7MxGxC.mjs} +187 -48
  108. package/dist/init-DG7MxGxC.mjs.map +1 -0
  109. package/dist/init.cjs +8 -6
  110. package/dist/init.d.mts +2 -2
  111. package/dist/init.mjs +1 -2
  112. package/dist/layeredConfig-BbkoIEfM.mjs +95 -0
  113. package/dist/layeredConfig-BbkoIEfM.mjs.map +1 -0
  114. package/dist/layeredConfig-Bs18dXQG.cjs +127 -0
  115. package/dist/layeredConfig-Bs18dXQG.cjs.map +1 -0
  116. package/dist/layeredConfig.cjs +5 -4
  117. package/dist/layeredConfig.d.mts +7 -2
  118. package/dist/layeredConfig.d.mts.map +1 -0
  119. package/dist/layeredConfig.mjs +1 -2
  120. package/dist/{majorModes-D1Itd8SN.mjs → majorModes-B8Km83e1.mjs} +130 -23
  121. package/dist/majorModes-B8Km83e1.mjs.map +1 -0
  122. package/dist/{majorModes-DnNSH9ZK.cjs → majorModes-CLccNMZt.cjs} +147 -22
  123. package/dist/majorModes-CLccNMZt.cjs.map +1 -0
  124. package/dist/majorModes.cjs +4 -1
  125. package/dist/majorModes.d.mts +2 -2
  126. package/dist/majorModes.mjs +1 -2
  127. package/dist/{piConfig-qGyCbcVj.mjs → piConfig-Bq36PQFF.mjs} +104 -69
  128. package/dist/piConfig-Bq36PQFF.mjs.map +1 -0
  129. package/dist/{piConfig-Bx26HMb_.d.mts → piConfig-C9rGUqPe.d.mts} +3 -3
  130. package/dist/{piConfig-Bx26HMb_.d.mts.map → piConfig-C9rGUqPe.d.mts.map} +1 -1
  131. package/dist/{piConfig-CCBdZXQr.cjs → piConfig-cluCie5i.cjs} +122 -70
  132. package/dist/piConfig-cluCie5i.cjs.map +1 -0
  133. package/dist/piConfig.cjs +4 -1
  134. package/dist/piConfig.d.mts +2 -2
  135. package/dist/piConfig.mjs +1 -2
  136. package/dist/piContext.cjs +27 -16
  137. package/dist/piContext.d.mts +3 -3
  138. package/dist/piContext.mjs +1 -2
  139. package/dist/{profiles-DBcYg5nA.mjs → profiles-CHict0x-.mjs} +322 -101
  140. package/dist/profiles-CHict0x-.mjs.map +1 -0
  141. package/dist/{profiles-tpplXY4r.cjs → profiles-t2EUj0aB.cjs} +359 -102
  142. package/dist/profiles-t2EUj0aB.cjs.map +1 -0
  143. package/dist/profiles.cjs +7 -1
  144. package/dist/profiles.d.mts +27 -3
  145. package/dist/profiles.d.mts.map +1 -1
  146. package/dist/profiles.mjs +1 -2
  147. package/dist/selectionSwitch.cjs +88 -22
  148. package/dist/selectionSwitch.cjs.map +1 -1
  149. package/dist/selectionSwitch.d.mts +40 -18
  150. package/dist/selectionSwitch.d.mts.map +1 -1
  151. package/dist/selectionSwitch.mjs +85 -22
  152. package/dist/selectionSwitch.mjs.map +1 -1
  153. package/dist/{sessionConfig-DV5xTRRw.mjs → sessionConfig-DFQF618G.mjs} +48 -47
  154. package/dist/sessionConfig-DFQF618G.mjs.map +1 -0
  155. package/dist/{sessionConfig-Bf6xHWLd.cjs → sessionConfig-DeP6pplT.cjs} +74 -85
  156. package/dist/sessionConfig-DeP6pplT.cjs.map +1 -0
  157. package/dist/sync-BJ8gCP9s.mjs +29 -0
  158. package/dist/sync-BJ8gCP9s.mjs.map +1 -0
  159. package/dist/sync-CC_15kkB.d.mts +46 -0
  160. package/dist/sync-CC_15kkB.d.mts.map +1 -0
  161. package/dist/sync-Dlxz2msM.cjs +37 -0
  162. package/dist/sync-Dlxz2msM.cjs.map +1 -0
  163. package/dist/types.cjs +2 -2
  164. package/dist/types.d.mts +2 -2
  165. package/dist/types.mjs +1 -2
  166. package/llms.txt +1 -1
  167. package/package.json +16 -16
  168. package/src/prompts/po-author-config/SKILL.md +4 -4
  169. package/src/prompts/po-author-config/agents/openai.yaml +1 -1
  170. package/src/prompts/po-author-config/references/config-contract.md +5 -5
  171. package/dist/atomicJson-1W0WhuFF.mjs +0 -44
  172. package/dist/atomicJson-1W0WhuFF.mjs.map +0 -1
  173. package/dist/atomicJson-Dt2z_DXl.cjs +0 -52
  174. package/dist/atomicJson-Dt2z_DXl.cjs.map +0 -1
  175. package/dist/config-CfTb0_9G.cjs +0 -219
  176. package/dist/config-CfTb0_9G.cjs.map +0 -1
  177. package/dist/config-D2HbBLzo.d.mts.map +0 -1
  178. package/dist/config-DoQWSt1V.mjs +0 -162
  179. package/dist/config-DoQWSt1V.mjs.map +0 -1
  180. package/dist/config-NSHRd6na.mjs +0 -2
  181. package/dist/configPolicy-Ce1QKDxa.cjs.map +0 -1
  182. package/dist/configPolicy-DCQgF5-f.mjs.map +0 -1
  183. package/dist/configWriter-B7uO8MuN.cjs +0 -150
  184. package/dist/configWriter-B7uO8MuN.cjs.map +0 -1
  185. package/dist/configWriter-DUtLgOlD.mjs +0 -130
  186. package/dist/configWriter-DUtLgOlD.mjs.map +0 -1
  187. package/dist/domains-BroCVHrS.mjs.map +0 -1
  188. package/dist/domains-DGCb7uMC.cjs.map +0 -1
  189. package/dist/harnessStore-CJSxdSkV.cjs.map +0 -1
  190. package/dist/harnessStore-CltwLB7M.mjs.map +0 -1
  191. package/dist/index-78zvoS9s.d.mts +0 -35
  192. package/dist/index-78zvoS9s.d.mts.map +0 -1
  193. package/dist/index-BT29GZx5.d.mts.map +0 -1
  194. package/dist/index-C6GaYjq-.d.mts +0 -6
  195. package/dist/index-C6GaYjq-.d.mts.map +0 -1
  196. package/dist/index-CEUc7m16.d.mts.map +0 -1
  197. package/dist/index-CRcoVYXz.d.mts +0 -39
  198. package/dist/index-CRcoVYXz.d.mts.map +0 -1
  199. package/dist/index-CVlciCJF.d.mts +0 -40
  200. package/dist/index-CVlciCJF.d.mts.map +0 -1
  201. package/dist/index-Ch7ptOkW.d.mts.map +0 -1
  202. package/dist/index-CkDDvVQt.d.mts.map +0 -1
  203. package/dist/index-Cvdt-Y-i.d.mts +0 -66
  204. package/dist/index-Cvdt-Y-i.d.mts.map +0 -1
  205. package/dist/index-DNk4q0Qm.d.mts.map +0 -1
  206. package/dist/index-DdH0w56b.d.mts +0 -116
  207. package/dist/index-DdH0w56b.d.mts.map +0 -1
  208. package/dist/init-Cd3Ki6Ub.cjs.map +0 -1
  209. package/dist/init-DVzhiCUE.mjs.map +0 -1
  210. package/dist/layeredConfig-fukqN2EA.mjs +0 -67
  211. package/dist/layeredConfig-fukqN2EA.mjs.map +0 -1
  212. package/dist/layeredConfig-ol0274TN.cjs +0 -94
  213. package/dist/layeredConfig-ol0274TN.cjs.map +0 -1
  214. package/dist/majorModes-D1Itd8SN.mjs.map +0 -1
  215. package/dist/majorModes-DnNSH9ZK.cjs.map +0 -1
  216. package/dist/piConfig-CCBdZXQr.cjs.map +0 -1
  217. package/dist/piConfig-qGyCbcVj.mjs.map +0 -1
  218. package/dist/profiles-DBcYg5nA.mjs.map +0 -1
  219. package/dist/profiles-tpplXY4r.cjs.map +0 -1
  220. package/dist/sessionConfig-Bf6xHWLd.cjs.map +0 -1
  221. package/dist/sessionConfig-DV5xTRRw.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: po-author-config
3
- description: Configure Po runtime settings, source precedence, and typed session configuration. Use for config.yaml, the doom/config Cordis service, immutable context snapshots, or shared selection transition state. Do not use for defining modes.yaml, domains.yaml, or profiles.yaml.
3
+ description: Configure Po runtime settings, source precedence, and typed session configuration. Use for config.yaml, the po/config Cordis service, immutable context snapshots, or shared selection transition state. Do not use for defining modes.yaml, domains.yaml, or profiles.yaml.
4
4
  ---
5
5
 
6
6
  # Author Po runtime configuration
@@ -10,16 +10,16 @@ Configure runtime policy in `config.yaml` and consume one immutable session snap
10
10
  ## Workflow
11
11
 
12
12
  1. Read both `~/.po/config.yaml` and the repository's `.po/config.yaml` before changing effective settings.
13
- 2. Check the `DoomConfig` types and parser before adding or editing a field. Unknown keys and invalid values fail early
13
+ 2. Check the `PoConfig` types and parser before adding or editing a field. Unknown keys and invalid values fail early
14
14
  everywhere a session reads config. `po sync` is the one exception: it reports an unknown key and carries on, so a
15
15
  config written for another version cannot break a build. Invalid values for known keys still fail there too. Run
16
16
  `po doctor` for the strict check.
17
17
  3. Preserve field-specific source policy. Repository settings do not uniformly replace every personal setting.
18
- 4. Consume live state only inside an owning `cordis.inject([DOOM_CONFIG_SERVICE], ...)` callback, using `requireDoomConfigContext(cordis)`.
18
+ 4. Consume live state only inside an owning `cordis.inject([PO_CONFIG_SERVICE], ...)` callback, using `requirePoConfigContext(cordis)`.
19
19
  5. Treat `settings`, `harness`, `pendingSelection`, and nested values as immutable. Do not mutate or cache a snapshot across session replacement.
20
20
  6. Route live major-mode, domain, and profile changes through the transition coordinator. Keep append-only selection and transition entries consistent with the active harness.
21
21
  7. Keep `process.env` as launcher transport and the controlled live-switch boundary, not as an alternative configuration registry.
22
- 8. Verify parsing and merge behavior with Doom Config tests, then exercise `po --explain` and a real session when transition behavior changes.
22
+ 8. Verify parsing and merge behavior with Po Config tests, then exercise `po --explain` and a real session when transition behavior changes.
23
23
 
24
24
  Use the package-owned Major Mode, Domain, or Profile Help skill when the task is to define an axis in `modes.yaml`, `domains.yaml`, or `profiles.yaml`.
25
25
 
@@ -1,4 +1,4 @@
1
1
  interface:
2
- display_name: "Doom Pi Runtime Config"
2
+ display_name: "Po Pi Runtime Config"
3
3
  short_description: "Configure runtime settings and session context"
4
4
  default_prompt: "Use $po-author-config to update Po runtime configuration safely."
@@ -91,7 +91,7 @@ Autonomous capture is personal-only and belongs in `~/.po/config.yaml`:
91
91
  voice:
92
92
  autoCapture:
93
93
  model: openai/gpt-4.1-mini
94
- startPhrases: [hey doom]
94
+ startPhrases: [hey po]
95
95
  stopPhrases: [stop speaking]
96
96
  utteranceIdleMs: 3000
97
97
  transcriptionTimeoutMs: 120000
@@ -135,17 +135,17 @@ Merge behavior is field-specific:
135
135
  mapping supplies the defaults. When the repository declares `selection`, its parsed mapping
136
136
  replaces personal values for omitted axes as well as axes it sets.
137
137
 
138
- Do not assume one generic deep-merge rule or copy this policy into consumers. Call `loadDoomConfig`
138
+ Do not assume one generic deep-merge rule or copy this policy into consumers. Call `loadPoConfig`
139
139
  or use the live service snapshot.
140
140
 
141
141
  ## Immutable Cordis context
142
142
 
143
- `@agimon-ai/po-config/extensions/pi` provides `DOOM_CONFIG_SERVICE` on the runner's shared Cordis
143
+ `@agimon-ai/po-config/extensions/pi` provides `PO_CONFIG_SERVICE` on the runner's shared Cordis
144
144
  session branch. Consume it inside an owning injection:
145
145
 
146
146
  ```ts
147
- cordis.inject([DOOM_CONFIG_SERVICE], (configContext) => {
148
- const snapshot = requireDoomConfigContext(configContext);
147
+ cordis.inject([PO_CONFIG_SERVICE], (configContext) => {
148
+ const snapshot = requirePoConfigContext(configContext);
149
149
  const settings = snapshot.settings;
150
150
  const active = snapshot.harness;
151
151
  const pending = snapshot.pendingSelection;
@@ -1,44 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- //#region src/services/atomicJson/index.ts
5
- /**
6
- * Private atomic JSON writes.
7
- *
8
- * Write to a uniquely named temporary file in the destination directory, then
9
- * rename onto the target. Rename is atomic within a filesystem, so a reader
10
- * sees either the previous file or the complete new one and never a partial
11
- * write. The temporary name carries the pid and a random suffix, so two
12
- * processes writing the same target cannot collide on it.
13
- *
14
- * This prevents torn reads. It does NOT prevent lost updates: two writers doing
15
- * read-modify-write still clobber each other, because the rename only publishes
16
- * what the caller already computed. Harness state avoids that by giving every
17
- * process a file it owns rather than by locking.
18
- *
19
- * AVOID:
20
- * - Treating this as a lock
21
- * - Leaving the temporary file behind when the write fails
22
- */
23
- const PRIVATE_FILE_MODE = 384;
24
- const PRIVATE_DIRECTORY_MODE = 448;
25
- const TEMPORARY_SUFFIX = ".tmp";
26
- /** Writes JSON readable by its owner only, replacing the target atomically. */
27
- function writePrivateAtomicJson(filePath, value) {
28
- fs.mkdirSync(path.dirname(filePath), {
29
- mode: PRIVATE_DIRECTORY_MODE,
30
- recursive: true
31
- });
32
- const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}${TEMPORARY_SUFFIX}`;
33
- try {
34
- fs.writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\n`, { mode: PRIVATE_FILE_MODE });
35
- fs.renameSync(temporaryPath, filePath);
36
- } catch (error) {
37
- fs.rmSync(temporaryPath, { force: true });
38
- throw error;
39
- }
40
- }
41
- //#endregion
42
- export { writePrivateAtomicJson as t };
43
-
44
- //# sourceMappingURL=atomicJson-1W0WhuFF.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"atomicJson-1W0WhuFF.mjs","names":[],"sources":["../src/services/atomicJson/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Private atomic JSON writes.\n *\n * Write to a uniquely named temporary file in the destination directory, then\n * rename onto the target. Rename is atomic within a filesystem, so a reader\n * sees either the previous file or the complete new one and never a partial\n * write. The temporary name carries the pid and a random suffix, so two\n * processes writing the same target cannot collide on it.\n *\n * This prevents torn reads. It does NOT prevent lost updates: two writers doing\n * read-modify-write still clobber each other, because the rename only publishes\n * what the caller already computed. Harness state avoids that by giving every\n * process a file it owns rather than by locking.\n *\n * AVOID:\n * - Treating this as a lock\n * - Leaving the temporary file behind when the write fails\n */\n\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst TEMPORARY_SUFFIX = '.tmp';\n\n/** Writes JSON readable by its owner only, replacing the target atomically. */\nexport function writePrivateAtomicJson(filePath: string, value: unknown): void {\n fs.mkdirSync(path.dirname(filePath), { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}${TEMPORARY_SUFFIX}`;\n try {\n fs.writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\\n`, { mode: PRIVATE_FILE_MODE });\n fs.renameSync(temporaryPath, filePath);\n } catch (error) {\n fs.rmSync(temporaryPath, { force: true });\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAM,oBAAoB;AAC1B,MAAM,yBAAyB;AAC/B,MAAM,mBAAmB;;AAGzB,SAAgB,uBAAuB,UAAkB,OAAsB;CAC7E,GAAG,UAAU,KAAK,QAAQ,QAAQ,GAAG;EAAE,MAAM;EAAwB,WAAW;CAAK,CAAC;CACtF,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,IAAI,GAAG,WAAW,IAAI;CACnE,IAAI;EACF,GAAG,cAAc,eAAe,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;EAClG,GAAG,WAAW,eAAe,QAAQ;CACvC,SAAS,OAAO;EACd,GAAG,OAAO,eAAe,EAAE,OAAO,KAAK,CAAC;EACxC,MAAM;CACR;AACF"}
@@ -1,52 +0,0 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
2
- let node_crypto = require("node:crypto");
3
- let node_fs = require("node:fs");
4
- node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
5
- let node_path = require("node:path");
6
- node_path = require_rolldown_runtime.__toESM(node_path, 1);
7
- //#region src/services/atomicJson/index.ts
8
- /**
9
- * Private atomic JSON writes.
10
- *
11
- * Write to a uniquely named temporary file in the destination directory, then
12
- * rename onto the target. Rename is atomic within a filesystem, so a reader
13
- * sees either the previous file or the complete new one and never a partial
14
- * write. The temporary name carries the pid and a random suffix, so two
15
- * processes writing the same target cannot collide on it.
16
- *
17
- * This prevents torn reads. It does NOT prevent lost updates: two writers doing
18
- * read-modify-write still clobber each other, because the rename only publishes
19
- * what the caller already computed. Harness state avoids that by giving every
20
- * process a file it owns rather than by locking.
21
- *
22
- * AVOID:
23
- * - Treating this as a lock
24
- * - Leaving the temporary file behind when the write fails
25
- */
26
- const PRIVATE_FILE_MODE = 384;
27
- const PRIVATE_DIRECTORY_MODE = 448;
28
- const TEMPORARY_SUFFIX = ".tmp";
29
- /** Writes JSON readable by its owner only, replacing the target atomically. */
30
- function writePrivateAtomicJson(filePath, value) {
31
- node_fs.default.mkdirSync(node_path.default.dirname(filePath), {
32
- mode: PRIVATE_DIRECTORY_MODE,
33
- recursive: true
34
- });
35
- const temporaryPath = `${filePath}.${process.pid}.${(0, node_crypto.randomUUID)()}${TEMPORARY_SUFFIX}`;
36
- try {
37
- node_fs.default.writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\n`, { mode: PRIVATE_FILE_MODE });
38
- node_fs.default.renameSync(temporaryPath, filePath);
39
- } catch (error) {
40
- node_fs.default.rmSync(temporaryPath, { force: true });
41
- throw error;
42
- }
43
- }
44
- //#endregion
45
- Object.defineProperty(exports, "writePrivateAtomicJson", {
46
- enumerable: true,
47
- get: function() {
48
- return writePrivateAtomicJson;
49
- }
50
- });
51
-
52
- //# sourceMappingURL=atomicJson-Dt2z_DXl.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"atomicJson-Dt2z_DXl.cjs","names":["path","randomUUID"],"sources":["../src/services/atomicJson/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Private atomic JSON writes.\n *\n * Write to a uniquely named temporary file in the destination directory, then\n * rename onto the target. Rename is atomic within a filesystem, so a reader\n * sees either the previous file or the complete new one and never a partial\n * write. The temporary name carries the pid and a random suffix, so two\n * processes writing the same target cannot collide on it.\n *\n * This prevents torn reads. It does NOT prevent lost updates: two writers doing\n * read-modify-write still clobber each other, because the rename only publishes\n * what the caller already computed. Harness state avoids that by giving every\n * process a file it owns rather than by locking.\n *\n * AVOID:\n * - Treating this as a lock\n * - Leaving the temporary file behind when the write fails\n */\n\nconst PRIVATE_FILE_MODE = 0o600;\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst TEMPORARY_SUFFIX = '.tmp';\n\n/** Writes JSON readable by its owner only, replacing the target atomically. */\nexport function writePrivateAtomicJson(filePath: string, value: unknown): void {\n fs.mkdirSync(path.dirname(filePath), { mode: PRIVATE_DIRECTORY_MODE, recursive: true });\n const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}${TEMPORARY_SUFFIX}`;\n try {\n fs.writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\\n`, { mode: PRIVATE_FILE_MODE });\n fs.renameSync(temporaryPath, filePath);\n } catch (error) {\n fs.rmSync(temporaryPath, { force: true });\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAM,oBAAoB;AAC1B,MAAM,yBAAyB;AAC/B,MAAM,mBAAmB;;AAGzB,SAAgB,uBAAuB,UAAkB,OAAsB;CAC7E,QAAA,QAAG,UAAUA,UAAAA,QAAK,QAAQ,QAAQ,GAAG;EAAE,MAAM;EAAwB,WAAW;CAAK,CAAC;CACtF,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,IAAI,IAAA,GAAGC,YAAAA,WAAAA,CAAW,IAAI;CACnE,IAAI;EACF,QAAA,QAAG,cAAc,eAAe,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;EAClG,QAAA,QAAG,WAAW,eAAe,QAAQ;CACvC,SAAS,OAAO;EACd,QAAA,QAAG,OAAO,eAAe,EAAE,OAAO,KAAK,CAAC;EACxC,MAAM;CACR;AACF"}
@@ -1,219 +0,0 @@
1
- const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
2
- const require_configPolicy = require("./configPolicy-Ce1QKDxa.cjs");
3
- let node_crypto = require("node:crypto");
4
- let node_fs = require("node:fs");
5
- node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
6
- let node_path = require("node:path");
7
- node_path = require_rolldown_runtime.__toESM(node_path, 1);
8
- let node_os = require("node:os");
9
- node_os = require_rolldown_runtime.__toESM(node_os, 1);
10
- let _agimon_ai_po_core_piSettings = require("@agimon-ai/po-core/piSettings");
11
- let yaml = require("yaml");
12
- //#region src/services/config/index.ts
13
- const DOOM_DIR = ".po";
14
- const CONFIG_FILE = "config.yaml";
15
- const PLANS_DIR = "plans";
16
- function readConfig(filePath) {
17
- return node_fs.default.existsSync(filePath) ? require_configPolicy.parseDoomConfig(node_fs.default.readFileSync(filePath, "utf8"), filePath) : { projectTrust: "ask" };
18
- }
19
- async function readConfigAsync(filePath) {
20
- try {
21
- return require_configPolicy.parseDoomConfig(await node_fs.default.promises.readFile(filePath, "utf8"), filePath);
22
- } catch (error) {
23
- if (error.code === "ENOENT") return { projectTrust: "ask" };
24
- throw error;
25
- }
26
- }
27
- function globalDoomConfigDirectory(homeDirectory = node_os.default.homedir()) {
28
- return (0, _agimon_ai_po_core_piSettings.poHomeDirectory)(homeDirectory);
29
- }
30
- function globalDoomConfigPath(homeDirectory = node_os.default.homedir()) {
31
- return node_path.default.join(globalDoomConfigDirectory(homeDirectory), CONFIG_FILE);
32
- }
33
- function resolvePlanningPlansDirectory(configured, repoRoot, homeDirectory = node_os.default.homedir()) {
34
- if (!configured) return node_path.default.join(globalDoomConfigDirectory(homeDirectory), PLANS_DIR);
35
- if (configured === "~") return homeDirectory;
36
- if (configured.startsWith("~/")) return node_path.default.resolve(homeDirectory, configured.slice(2));
37
- if (configured.startsWith("~")) throw new Error("Doom planning plansDirectory supports only '~' or '~/' home aliases");
38
- return node_path.default.isAbsolute(configured) ? node_path.default.normalize(configured) : node_path.default.resolve(repoRoot, configured);
39
- }
40
- function repositoryDoomConfigPath(repoRoot) {
41
- return node_path.default.join(repoRoot, DOOM_DIR, CONFIG_FILE);
42
- }
43
- /**
44
- * True when a repository's `.po` folder is Po's home itself, as it is for a
45
- * session rooted at home. That folder is already the global layer; reading it
46
- * again as the repository layer would apply global-only keys at repository scope.
47
- */
48
- function isGlobalDoomConfigRoot(repoRoot, homeDirectory = node_os.default.homedir()) {
49
- return node_path.default.resolve(repoRoot, DOOM_DIR) === node_path.default.resolve(globalDoomConfigDirectory(homeDirectory));
50
- }
51
- function repositoryConfigFor(repoRoot, homeDirectory) {
52
- return isGlobalDoomConfigRoot(repoRoot, homeDirectory) ? void 0 : repositoryDoomConfigPath(repoRoot);
53
- }
54
- /** Process-local distribution defaults never grant native authority or modify user files. */
55
- function distributionDefaults(config, environment) {
56
- if (environment.PO_DISTRIBUTION !== "desktop") return config;
57
- return {
58
- ...config,
59
- computerUse: {
60
- ...config.computerUse,
61
- enabled: config.computerUse?.enabled ?? true
62
- }
63
- };
64
- }
65
- function loadDoomConfig(repoRoot, homeDirectory = node_os.default.homedir(), environment = process.env) {
66
- const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);
67
- return distributionDefaults(require_configPolicy.mergeDoomConfigs(readConfig(globalDoomConfigPath(homeDirectory)), repositoryPath === void 0 ? { projectTrust: "ask" } : readConfig(repositoryPath)), environment);
68
- }
69
- /**
70
- * Loads the merged config, tolerating unknown keys in either file.
71
- *
72
- * Only `po sync` uses this. Everything that runs during a session keeps
73
- * `loadDoomConfig`, because a key a running extension cannot understand is
74
- * better reported than silently ignored; a build that refuses to start over
75
- * the same key is not.
76
- */
77
- function loadDoomConfigLenient(repoRoot, homeDirectory = node_os.default.homedir(), environment = process.env) {
78
- const read = (filePath) => filePath !== void 0 && node_fs.default.existsSync(filePath) ? require_configPolicy.parseDoomConfig(node_fs.default.readFileSync(filePath, "utf8"), filePath, { lenient: true }) : {
79
- config: { projectTrust: "ask" },
80
- diagnostics: []
81
- };
82
- const globalConfig = read(globalDoomConfigPath(homeDirectory));
83
- const repositoryConfig = read(repositoryConfigFor(repoRoot, homeDirectory));
84
- const diagnostics = [...globalConfig.diagnostics, ...repositoryConfig.diagnostics];
85
- return {
86
- config: distributionDefaults(require_configPolicy.mergeDoomConfigs(globalConfig.config, repositoryConfig.config), environment),
87
- diagnostics
88
- };
89
- }
90
- async function loadDoomConfigAsync(repoRoot, homeDirectory = node_os.default.homedir(), environment = process.env) {
91
- const globalConfig = await readConfigAsync(globalDoomConfigPath(homeDirectory));
92
- const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);
93
- const repositoryConfig = repositoryPath === void 0 ? { projectTrust: "ask" } : await readConfigAsync(repositoryPath);
94
- return distributionDefaults(require_configPolicy.mergeDoomConfigs(globalConfig, repositoryConfig), environment);
95
- }
96
- /**
97
- * Reads one config file as a layer: what it is, what it sets, and the bytes it
98
- * held. A file that does not exist is a layer that sets nothing, which is a
99
- * normal state rather than an error.
100
- */
101
- function readLayer(filePath) {
102
- let text;
103
- try {
104
- text = node_fs.default.readFileSync(filePath, "utf8");
105
- } catch (error) {
106
- if (error.code === "ENOENT") return {
107
- filePath,
108
- exists: false,
109
- hash: "",
110
- keys: []
111
- };
112
- throw error;
113
- }
114
- const document = (0, yaml.parse)(text) ?? {};
115
- return {
116
- filePath,
117
- exists: true,
118
- hash: (0, node_crypto.createHash)("sha256").update(text, "utf8").digest("hex"),
119
- keys: require_configPolicy.configLeafKeys(document)
120
- };
121
- }
122
- /**
123
- * The two config files kept apart, with the merge alongside them.
124
- *
125
- * `repoRoot` is optional because the global file is complete on its own: a
126
- * settings surface with no repository in view still has settings to show, and
127
- * demanding one would leave it with nothing to render rather than with the
128
- * global half.
129
- *
130
- * The origin answer respects the merge's own per-field rules rather than simply
131
- * preferring the repository: `editor` is read from the global side whatever the
132
- * repository says, and `projectTrust` from the repository side whatever the
133
- * global one says. Reporting a file as the source of a value the merge discards
134
- * is the exact confusion this exists to remove.
135
- */
136
- function loadDoomConfigLayers(repoRoot, homeDirectory = node_os.default.homedir(), environment = process.env) {
137
- const globalLayer = readLayer(globalDoomConfigPath(homeDirectory));
138
- const repositoryPath = repoRoot === void 0 ? void 0 : repositoryConfigFor(repoRoot, homeDirectory);
139
- const repositoryLayer = repositoryPath === void 0 ? {
140
- filePath: "",
141
- exists: false,
142
- hash: "",
143
- keys: []
144
- } : readLayer(repositoryPath);
145
- const effective = repoRoot === void 0 ? distributionDefaults(require_configPolicy.mergeDoomConfigs(readConfig(globalDoomConfigPath(homeDirectory)), { projectTrust: "ask" }), environment) : loadDoomConfig(repoRoot, homeDirectory, environment);
146
- const sets = (layer, keyPath) => {
147
- const dotted = keyPath.join(".");
148
- return layer.keys.some((key) => key === dotted || key.startsWith(`${dotted}.`));
149
- };
150
- return {
151
- globalFile: globalLayer,
152
- repositoryFile: repositoryLayer,
153
- effective,
154
- originOf(keyPath) {
155
- const scope = require_configPolicy.configScopeOf(keyPath);
156
- if (scope !== "global" && sets(repositoryLayer, keyPath)) return "repository";
157
- if (scope !== "repository" && sets(globalLayer, keyPath)) return "global";
158
- return "default";
159
- },
160
- valueAt: (keyPath) => require_configPolicy.valueAtKeyPath(effective, keyPath)
161
- };
162
- }
163
- //#endregion
164
- Object.defineProperty(exports, "globalDoomConfigDirectory", {
165
- enumerable: true,
166
- get: function() {
167
- return globalDoomConfigDirectory;
168
- }
169
- });
170
- Object.defineProperty(exports, "globalDoomConfigPath", {
171
- enumerable: true,
172
- get: function() {
173
- return globalDoomConfigPath;
174
- }
175
- });
176
- Object.defineProperty(exports, "isGlobalDoomConfigRoot", {
177
- enumerable: true,
178
- get: function() {
179
- return isGlobalDoomConfigRoot;
180
- }
181
- });
182
- Object.defineProperty(exports, "loadDoomConfig", {
183
- enumerable: true,
184
- get: function() {
185
- return loadDoomConfig;
186
- }
187
- });
188
- Object.defineProperty(exports, "loadDoomConfigAsync", {
189
- enumerable: true,
190
- get: function() {
191
- return loadDoomConfigAsync;
192
- }
193
- });
194
- Object.defineProperty(exports, "loadDoomConfigLayers", {
195
- enumerable: true,
196
- get: function() {
197
- return loadDoomConfigLayers;
198
- }
199
- });
200
- Object.defineProperty(exports, "loadDoomConfigLenient", {
201
- enumerable: true,
202
- get: function() {
203
- return loadDoomConfigLenient;
204
- }
205
- });
206
- Object.defineProperty(exports, "repositoryDoomConfigPath", {
207
- enumerable: true,
208
- get: function() {
209
- return repositoryDoomConfigPath;
210
- }
211
- });
212
- Object.defineProperty(exports, "resolvePlanningPlansDirectory", {
213
- enumerable: true,
214
- get: function() {
215
- return resolvePlanningPlansDirectory;
216
- }
217
- });
218
-
219
- //# sourceMappingURL=config-CfTb0_9G.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-CfTb0_9G.cjs","names":["fs","parseDoomConfig","os","poHomeDirectory","path","mergeDoomConfigs","parseYaml","createHash","configLeafKeys","configScopeOf","valueAtKeyPath"],"sources":["../src/services/config/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\nimport { parse as parseYaml } from 'yaml';\n\nimport type {\n ConfigDiagnostic,\n ConfigValueOrigin,\n DoomConfig,\n DoomConfigLayer,\n DoomConfigLayers,\n LenientParseResult,\n} from '../../types/config';\nimport { configLeafKeys, configScopeOf, mergeDoomConfigs, parseDoomConfig, valueAtKeyPath } from '../configPolicy';\n\nconst DOOM_DIR = '.po';\nconst CONFIG_FILE = 'config.yaml';\nconst PLANS_DIR = 'plans';\n\nfunction readConfig(filePath: string): DoomConfig {\n return fs.existsSync(filePath)\n ? parseDoomConfig(fs.readFileSync(filePath, 'utf8'), filePath)\n : { projectTrust: 'ask' };\n}\n\nasync function readConfigAsync(filePath: string): Promise<DoomConfig> {\n try {\n return parseDoomConfig(await fs.promises.readFile(filePath, 'utf8'), filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { projectTrust: 'ask' };\n throw error;\n }\n}\n\nexport function globalDoomConfigDirectory(homeDirectory = os.homedir()): string {\n return poHomeDirectory(homeDirectory);\n}\n\nexport function globalDoomConfigPath(homeDirectory = os.homedir()): string {\n return path.join(globalDoomConfigDirectory(homeDirectory), CONFIG_FILE);\n}\n\nexport function resolvePlanningPlansDirectory(\n configured: string | undefined,\n repoRoot: string,\n homeDirectory = os.homedir(),\n): string {\n // Under Po's home, so Po writes nothing into ~/.pi.\n if (!configured) return path.join(globalDoomConfigDirectory(homeDirectory), PLANS_DIR);\n if (configured === '~') return homeDirectory;\n if (configured.startsWith('~/')) return path.resolve(homeDirectory, configured.slice(2));\n if (configured.startsWith('~')) {\n throw new Error(\"Doom planning plansDirectory supports only '~' or '~/' home aliases\");\n }\n return path.isAbsolute(configured) ? path.normalize(configured) : path.resolve(repoRoot, configured);\n}\n\nexport function repositoryDoomConfigPath(repoRoot: string): string {\n return path.join(repoRoot, DOOM_DIR, CONFIG_FILE);\n}\n\n/**\n * True when a repository's `.po` folder is Po's home itself, as it is for a\n * session rooted at home. That folder is already the global layer; reading it\n * again as the repository layer would apply global-only keys at repository scope.\n */\nexport function isGlobalDoomConfigRoot(repoRoot: string, homeDirectory = os.homedir()): boolean {\n return path.resolve(repoRoot, DOOM_DIR) === path.resolve(globalDoomConfigDirectory(homeDirectory));\n}\n\nfunction repositoryConfigFor(repoRoot: string, homeDirectory: string): string | undefined {\n return isGlobalDoomConfigRoot(repoRoot, homeDirectory) ? undefined : repositoryDoomConfigPath(repoRoot);\n}\n\n/** Process-local distribution defaults never grant native authority or modify user files. */\nfunction distributionDefaults(config: DoomConfig, environment: NodeJS.ProcessEnv): DoomConfig {\n if (environment.PO_DISTRIBUTION !== 'desktop') return config;\n return { ...config, computerUse: { ...config.computerUse, enabled: config.computerUse?.enabled ?? true } };\n}\n\nexport function loadDoomConfig(\n repoRoot: string,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): DoomConfig {\n const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);\n return distributionDefaults(\n mergeDoomConfigs(\n readConfig(globalDoomConfigPath(homeDirectory)),\n repositoryPath === undefined ? { projectTrust: 'ask' } : readConfig(repositoryPath),\n ),\n environment,\n );\n}\n\n/**\n * Loads the merged config, tolerating unknown keys in either file.\n *\n * Only `po sync` uses this. Everything that runs during a session keeps\n * `loadDoomConfig`, because a key a running extension cannot understand is\n * better reported than silently ignored; a build that refuses to start over\n * the same key is not.\n */\nexport function loadDoomConfigLenient(\n repoRoot: string,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): LenientParseResult {\n const read = (filePath: string | undefined): LenientParseResult =>\n filePath !== undefined && fs.existsSync(filePath)\n ? parseDoomConfig(fs.readFileSync(filePath, 'utf8'), filePath, { lenient: true })\n : { config: { projectTrust: 'ask' }, diagnostics: [] };\n const globalConfig = read(globalDoomConfigPath(homeDirectory));\n const repositoryConfig = read(repositoryConfigFor(repoRoot, homeDirectory));\n const diagnostics: ConfigDiagnostic[] = [...globalConfig.diagnostics, ...repositoryConfig.diagnostics];\n // mergeDoomConfigs stays strict on purpose: its errors are cross-file scope\n // violations on known keys, which is a different fault from an unknown key.\n return {\n config: distributionDefaults(mergeDoomConfigs(globalConfig.config, repositoryConfig.config), environment),\n diagnostics,\n };\n}\n\nexport async function loadDoomConfigAsync(\n repoRoot: string,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<DoomConfig> {\n const globalConfig = await readConfigAsync(globalDoomConfigPath(homeDirectory));\n const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);\n const repositoryConfig: DoomConfig =\n repositoryPath === undefined ? { projectTrust: 'ask' } : await readConfigAsync(repositoryPath);\n return distributionDefaults(mergeDoomConfigs(globalConfig, repositoryConfig), environment);\n}\n\n/**\n * Reads one config file as a layer: what it is, what it sets, and the bytes it\n * held. A file that does not exist is a layer that sets nothing, which is a\n * normal state rather than an error.\n */\nfunction readLayer(filePath: string): DoomConfigLayer {\n let text: string;\n try {\n text = fs.readFileSync(filePath, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return { filePath, exists: false, hash: '', keys: [] };\n }\n throw error;\n }\n // The raw document, not the parsed config: this is the one read that has to\n // distinguish a key the file set from a key the parser defaulted.\n const document = (parseYaml(text) ?? {}) as unknown;\n return {\n filePath,\n exists: true,\n hash: createHash('sha256').update(text, 'utf8').digest('hex'),\n keys: configLeafKeys(document),\n };\n}\n\n/**\n * The two config files kept apart, with the merge alongside them.\n *\n * `repoRoot` is optional because the global file is complete on its own: a\n * settings surface with no repository in view still has settings to show, and\n * demanding one would leave it with nothing to render rather than with the\n * global half.\n *\n * The origin answer respects the merge's own per-field rules rather than simply\n * preferring the repository: `editor` is read from the global side whatever the\n * repository says, and `projectTrust` from the repository side whatever the\n * global one says. Reporting a file as the source of a value the merge discards\n * is the exact confusion this exists to remove.\n */\nexport function loadDoomConfigLayers(\n repoRoot: string | undefined,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): DoomConfigLayers {\n const globalLayer = readLayer(globalDoomConfigPath(homeDirectory));\n const repositoryPath = repoRoot === undefined ? undefined : repositoryConfigFor(repoRoot, homeDirectory);\n const repositoryLayer =\n repositoryPath === undefined ? { filePath: '', exists: false, hash: '', keys: [] } : readLayer(repositoryPath);\n // With no repository there is nothing to merge, so the global file stands as\n // the effective config on its own.\n const effective =\n repoRoot === undefined\n ? distributionDefaults(\n mergeDoomConfigs(readConfig(globalDoomConfigPath(homeDirectory)), { projectTrust: 'ask' }),\n environment,\n )\n : loadDoomConfig(repoRoot, homeDirectory, environment);\n const sets = (layer: DoomConfigLayer, keyPath: readonly string[]): boolean => {\n const dotted = keyPath.join('.');\n return layer.keys.some((key) => key === dotted || key.startsWith(`${dotted}.`));\n };\n return {\n globalFile: globalLayer,\n repositoryFile: repositoryLayer,\n effective,\n originOf(keyPath: readonly string[]): ConfigValueOrigin {\n const scope = configScopeOf(keyPath);\n if (scope !== 'global' && sets(repositoryLayer, keyPath)) return 'repository';\n if (scope !== 'repository' && sets(globalLayer, keyPath)) return 'global';\n return 'default';\n },\n valueAt: (keyPath: readonly string[]) => valueAtKeyPath(effective, keyPath),\n };\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-D2HbBLzo.d.mts","names":["IDoomConfigService","DoomConfigServiceContract"],"sources":["../src/types/config.ts"],"mappings":";;;;;KAOY;KACA;KACA;KACA;KACA;UAEK;EACf;EACA,WAAW;;UAEI;EACf,OAAO;EACP,YAAY;EACZ;;;;;;;;;UASe;EACf;EACA;EACA;;;;;;;;;UASe;EACf;EACA;EACA;;;;;;;;;UASe;EACf;EACA,QAAQ;;UAEO;EACf;EACA;EACA,WAAW;EACX,aAAa;EACb,YAAY;;UAEG;EACf;;UAGe;EACf;;;UAGe;;EAEf;;EAEA;;UAEe;EACf;EACA;;UAEe;EACf;EACA,OAAO;;UAEQ;EACf,QAAQ;EACR;EACA;;UAEe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,KAAK;;UAEU;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,KAAK;;UAEU;EACf,OAAO;EACP,SAAS;EACT;EACA;IAAa;IAAiB;;EAC9B;IACE,gBAAgB;IAChB,mBAAmB;IACnB,gBAAgB;;EAElB,cAAc;;EAEd;IAAS;IAAgB;;;UAEV;EACf,MAAM;EACN,QAAQ;EACR;EACA;IAAY;IAAiB;;EAC7B,UAAU,YAAY;EACtB,cAAc;;;;;;;;;UASC;EACf;EACA;EACA;;;UAIe;WACN;WACA;WACA;WACA;;WAEA;;KAGC;KACA;UAEK;WACN;WACA;WACA,QAAQ;WACR,QAAQ;WACR,UAAU;WACV,OAAO;;;KAIN,6BAA6B;WAAwC;;UAEhE;EACf;IAAU,WAAW;IAAoB,cAAc;;EACvD,cAAc;EACd,cAAc;EACd,SAAS;EACT,SAAS;EACT,QAAQ;EACR,YAAY;;EAEZ;IAAQ;;;EAER;IAAW;;;UAGI;EACf;EACA;;UAMe;EACf;;EAEA;EACA;EACA;;EAEA;;;;;;;;;;;EAWA,qBAAqB,eAAe;;EAEpC;EACA;EACA,oBAAoB;EACpB;EACA;EACA;EACA;EACA;EACA;EACA,aAAa;;EAEb,gBAAgB;;EAEhB;IAAgB;;EAChB;EACA;;;;;;EAMA,kBAAkB;;EAElB,eAAe;EACf;EACA;EACA;EACA;;KAGU,aAAa,UAAU,oBAAmB,6BAClD,SACA,+BAA+B,oBACpB,aAAa,WACtB,oCACc,cAAc,SAAS,aAAa,OAAO,YACvD;KAEI,qBAAqB,aAAa;UAE7B;WACN,UAAU,aAAa;WACvB,SAAS;;WAET,mBAAmB,aAAa;;WAEhC;;;UAIM;EACf,KAAK,kBAAkB,yBAAyB;;;UAIjCA,6BAA2BC,mBAA0B,mBAAmB;;YAG7E;IACR,eAAeD;;;;KAQP;;UAGK;EACf;EACA;;;;;;EAMA;;EAEA;;;;;;;;;;UAWe;;EAEf,YAAY;EACZ,gBAAgB;EAChB,WAAW;;EAEX,SAAS,6BAA6B;;EAEtC,QAAQ;;;;;;;;;UAUO;EACf;;EAEA;EACA;;;UAIe;EACf;;;UAIe;EACf,QAAQ;EACR,aAAa"}
@@ -1,162 +0,0 @@
1
- import { c as configScopeOf, d as parseDoomConfig, l as mergeDoomConfigs, m as valueAtKeyPath, o as configLeafKeys } from "./configPolicy-DCQgF5-f.mjs";
2
- import { createHash } from "node:crypto";
3
- import fs from "node:fs";
4
- import path from "node:path";
5
- import os from "node:os";
6
- import { poHomeDirectory } from "@agimon-ai/po-core/piSettings";
7
- import { parse } from "yaml";
8
- //#region src/services/config/index.ts
9
- const DOOM_DIR = ".po";
10
- const CONFIG_FILE = "config.yaml";
11
- const PLANS_DIR = "plans";
12
- function readConfig(filePath) {
13
- return fs.existsSync(filePath) ? parseDoomConfig(fs.readFileSync(filePath, "utf8"), filePath) : { projectTrust: "ask" };
14
- }
15
- async function readConfigAsync(filePath) {
16
- try {
17
- return parseDoomConfig(await fs.promises.readFile(filePath, "utf8"), filePath);
18
- } catch (error) {
19
- if (error.code === "ENOENT") return { projectTrust: "ask" };
20
- throw error;
21
- }
22
- }
23
- function globalDoomConfigDirectory(homeDirectory = os.homedir()) {
24
- return poHomeDirectory(homeDirectory);
25
- }
26
- function globalDoomConfigPath(homeDirectory = os.homedir()) {
27
- return path.join(globalDoomConfigDirectory(homeDirectory), CONFIG_FILE);
28
- }
29
- function resolvePlanningPlansDirectory(configured, repoRoot, homeDirectory = os.homedir()) {
30
- if (!configured) return path.join(globalDoomConfigDirectory(homeDirectory), PLANS_DIR);
31
- if (configured === "~") return homeDirectory;
32
- if (configured.startsWith("~/")) return path.resolve(homeDirectory, configured.slice(2));
33
- if (configured.startsWith("~")) throw new Error("Doom planning plansDirectory supports only '~' or '~/' home aliases");
34
- return path.isAbsolute(configured) ? path.normalize(configured) : path.resolve(repoRoot, configured);
35
- }
36
- function repositoryDoomConfigPath(repoRoot) {
37
- return path.join(repoRoot, DOOM_DIR, CONFIG_FILE);
38
- }
39
- /**
40
- * True when a repository's `.po` folder is Po's home itself, as it is for a
41
- * session rooted at home. That folder is already the global layer; reading it
42
- * again as the repository layer would apply global-only keys at repository scope.
43
- */
44
- function isGlobalDoomConfigRoot(repoRoot, homeDirectory = os.homedir()) {
45
- return path.resolve(repoRoot, DOOM_DIR) === path.resolve(globalDoomConfigDirectory(homeDirectory));
46
- }
47
- function repositoryConfigFor(repoRoot, homeDirectory) {
48
- return isGlobalDoomConfigRoot(repoRoot, homeDirectory) ? void 0 : repositoryDoomConfigPath(repoRoot);
49
- }
50
- /** Process-local distribution defaults never grant native authority or modify user files. */
51
- function distributionDefaults(config, environment) {
52
- if (environment.PO_DISTRIBUTION !== "desktop") return config;
53
- return {
54
- ...config,
55
- computerUse: {
56
- ...config.computerUse,
57
- enabled: config.computerUse?.enabled ?? true
58
- }
59
- };
60
- }
61
- function loadDoomConfig(repoRoot, homeDirectory = os.homedir(), environment = process.env) {
62
- const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);
63
- return distributionDefaults(mergeDoomConfigs(readConfig(globalDoomConfigPath(homeDirectory)), repositoryPath === void 0 ? { projectTrust: "ask" } : readConfig(repositoryPath)), environment);
64
- }
65
- /**
66
- * Loads the merged config, tolerating unknown keys in either file.
67
- *
68
- * Only `po sync` uses this. Everything that runs during a session keeps
69
- * `loadDoomConfig`, because a key a running extension cannot understand is
70
- * better reported than silently ignored; a build that refuses to start over
71
- * the same key is not.
72
- */
73
- function loadDoomConfigLenient(repoRoot, homeDirectory = os.homedir(), environment = process.env) {
74
- const read = (filePath) => filePath !== void 0 && fs.existsSync(filePath) ? parseDoomConfig(fs.readFileSync(filePath, "utf8"), filePath, { lenient: true }) : {
75
- config: { projectTrust: "ask" },
76
- diagnostics: []
77
- };
78
- const globalConfig = read(globalDoomConfigPath(homeDirectory));
79
- const repositoryConfig = read(repositoryConfigFor(repoRoot, homeDirectory));
80
- const diagnostics = [...globalConfig.diagnostics, ...repositoryConfig.diagnostics];
81
- return {
82
- config: distributionDefaults(mergeDoomConfigs(globalConfig.config, repositoryConfig.config), environment),
83
- diagnostics
84
- };
85
- }
86
- async function loadDoomConfigAsync(repoRoot, homeDirectory = os.homedir(), environment = process.env) {
87
- const globalConfig = await readConfigAsync(globalDoomConfigPath(homeDirectory));
88
- const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);
89
- const repositoryConfig = repositoryPath === void 0 ? { projectTrust: "ask" } : await readConfigAsync(repositoryPath);
90
- return distributionDefaults(mergeDoomConfigs(globalConfig, repositoryConfig), environment);
91
- }
92
- /**
93
- * Reads one config file as a layer: what it is, what it sets, and the bytes it
94
- * held. A file that does not exist is a layer that sets nothing, which is a
95
- * normal state rather than an error.
96
- */
97
- function readLayer(filePath) {
98
- let text;
99
- try {
100
- text = fs.readFileSync(filePath, "utf8");
101
- } catch (error) {
102
- if (error.code === "ENOENT") return {
103
- filePath,
104
- exists: false,
105
- hash: "",
106
- keys: []
107
- };
108
- throw error;
109
- }
110
- const document = parse(text) ?? {};
111
- return {
112
- filePath,
113
- exists: true,
114
- hash: createHash("sha256").update(text, "utf8").digest("hex"),
115
- keys: configLeafKeys(document)
116
- };
117
- }
118
- /**
119
- * The two config files kept apart, with the merge alongside them.
120
- *
121
- * `repoRoot` is optional because the global file is complete on its own: a
122
- * settings surface with no repository in view still has settings to show, and
123
- * demanding one would leave it with nothing to render rather than with the
124
- * global half.
125
- *
126
- * The origin answer respects the merge's own per-field rules rather than simply
127
- * preferring the repository: `editor` is read from the global side whatever the
128
- * repository says, and `projectTrust` from the repository side whatever the
129
- * global one says. Reporting a file as the source of a value the merge discards
130
- * is the exact confusion this exists to remove.
131
- */
132
- function loadDoomConfigLayers(repoRoot, homeDirectory = os.homedir(), environment = process.env) {
133
- const globalLayer = readLayer(globalDoomConfigPath(homeDirectory));
134
- const repositoryPath = repoRoot === void 0 ? void 0 : repositoryConfigFor(repoRoot, homeDirectory);
135
- const repositoryLayer = repositoryPath === void 0 ? {
136
- filePath: "",
137
- exists: false,
138
- hash: "",
139
- keys: []
140
- } : readLayer(repositoryPath);
141
- const effective = repoRoot === void 0 ? distributionDefaults(mergeDoomConfigs(readConfig(globalDoomConfigPath(homeDirectory)), { projectTrust: "ask" }), environment) : loadDoomConfig(repoRoot, homeDirectory, environment);
142
- const sets = (layer, keyPath) => {
143
- const dotted = keyPath.join(".");
144
- return layer.keys.some((key) => key === dotted || key.startsWith(`${dotted}.`));
145
- };
146
- return {
147
- globalFile: globalLayer,
148
- repositoryFile: repositoryLayer,
149
- effective,
150
- originOf(keyPath) {
151
- const scope = configScopeOf(keyPath);
152
- if (scope !== "global" && sets(repositoryLayer, keyPath)) return "repository";
153
- if (scope !== "repository" && sets(globalLayer, keyPath)) return "global";
154
- return "default";
155
- },
156
- valueAt: (keyPath) => valueAtKeyPath(effective, keyPath)
157
- };
158
- }
159
- //#endregion
160
- export { loadDoomConfigAsync as a, repositoryDoomConfigPath as c, loadDoomConfig as i, resolvePlanningPlansDirectory as l, globalDoomConfigPath as n, loadDoomConfigLayers as o, isGlobalDoomConfigRoot as r, loadDoomConfigLenient as s, globalDoomConfigDirectory as t };
161
-
162
- //# sourceMappingURL=config-DoQWSt1V.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DoQWSt1V.mjs","names":["parseYaml"],"sources":["../src/services/config/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\nimport { parse as parseYaml } from 'yaml';\n\nimport type {\n ConfigDiagnostic,\n ConfigValueOrigin,\n DoomConfig,\n DoomConfigLayer,\n DoomConfigLayers,\n LenientParseResult,\n} from '../../types/config';\nimport { configLeafKeys, configScopeOf, mergeDoomConfigs, parseDoomConfig, valueAtKeyPath } from '../configPolicy';\n\nconst DOOM_DIR = '.po';\nconst CONFIG_FILE = 'config.yaml';\nconst PLANS_DIR = 'plans';\n\nfunction readConfig(filePath: string): DoomConfig {\n return fs.existsSync(filePath)\n ? parseDoomConfig(fs.readFileSync(filePath, 'utf8'), filePath)\n : { projectTrust: 'ask' };\n}\n\nasync function readConfigAsync(filePath: string): Promise<DoomConfig> {\n try {\n return parseDoomConfig(await fs.promises.readFile(filePath, 'utf8'), filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { projectTrust: 'ask' };\n throw error;\n }\n}\n\nexport function globalDoomConfigDirectory(homeDirectory = os.homedir()): string {\n return poHomeDirectory(homeDirectory);\n}\n\nexport function globalDoomConfigPath(homeDirectory = os.homedir()): string {\n return path.join(globalDoomConfigDirectory(homeDirectory), CONFIG_FILE);\n}\n\nexport function resolvePlanningPlansDirectory(\n configured: string | undefined,\n repoRoot: string,\n homeDirectory = os.homedir(),\n): string {\n // Under Po's home, so Po writes nothing into ~/.pi.\n if (!configured) return path.join(globalDoomConfigDirectory(homeDirectory), PLANS_DIR);\n if (configured === '~') return homeDirectory;\n if (configured.startsWith('~/')) return path.resolve(homeDirectory, configured.slice(2));\n if (configured.startsWith('~')) {\n throw new Error(\"Doom planning plansDirectory supports only '~' or '~/' home aliases\");\n }\n return path.isAbsolute(configured) ? path.normalize(configured) : path.resolve(repoRoot, configured);\n}\n\nexport function repositoryDoomConfigPath(repoRoot: string): string {\n return path.join(repoRoot, DOOM_DIR, CONFIG_FILE);\n}\n\n/**\n * True when a repository's `.po` folder is Po's home itself, as it is for a\n * session rooted at home. That folder is already the global layer; reading it\n * again as the repository layer would apply global-only keys at repository scope.\n */\nexport function isGlobalDoomConfigRoot(repoRoot: string, homeDirectory = os.homedir()): boolean {\n return path.resolve(repoRoot, DOOM_DIR) === path.resolve(globalDoomConfigDirectory(homeDirectory));\n}\n\nfunction repositoryConfigFor(repoRoot: string, homeDirectory: string): string | undefined {\n return isGlobalDoomConfigRoot(repoRoot, homeDirectory) ? undefined : repositoryDoomConfigPath(repoRoot);\n}\n\n/** Process-local distribution defaults never grant native authority or modify user files. */\nfunction distributionDefaults(config: DoomConfig, environment: NodeJS.ProcessEnv): DoomConfig {\n if (environment.PO_DISTRIBUTION !== 'desktop') return config;\n return { ...config, computerUse: { ...config.computerUse, enabled: config.computerUse?.enabled ?? true } };\n}\n\nexport function loadDoomConfig(\n repoRoot: string,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): DoomConfig {\n const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);\n return distributionDefaults(\n mergeDoomConfigs(\n readConfig(globalDoomConfigPath(homeDirectory)),\n repositoryPath === undefined ? { projectTrust: 'ask' } : readConfig(repositoryPath),\n ),\n environment,\n );\n}\n\n/**\n * Loads the merged config, tolerating unknown keys in either file.\n *\n * Only `po sync` uses this. Everything that runs during a session keeps\n * `loadDoomConfig`, because a key a running extension cannot understand is\n * better reported than silently ignored; a build that refuses to start over\n * the same key is not.\n */\nexport function loadDoomConfigLenient(\n repoRoot: string,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): LenientParseResult {\n const read = (filePath: string | undefined): LenientParseResult =>\n filePath !== undefined && fs.existsSync(filePath)\n ? parseDoomConfig(fs.readFileSync(filePath, 'utf8'), filePath, { lenient: true })\n : { config: { projectTrust: 'ask' }, diagnostics: [] };\n const globalConfig = read(globalDoomConfigPath(homeDirectory));\n const repositoryConfig = read(repositoryConfigFor(repoRoot, homeDirectory));\n const diagnostics: ConfigDiagnostic[] = [...globalConfig.diagnostics, ...repositoryConfig.diagnostics];\n // mergeDoomConfigs stays strict on purpose: its errors are cross-file scope\n // violations on known keys, which is a different fault from an unknown key.\n return {\n config: distributionDefaults(mergeDoomConfigs(globalConfig.config, repositoryConfig.config), environment),\n diagnostics,\n };\n}\n\nexport async function loadDoomConfigAsync(\n repoRoot: string,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<DoomConfig> {\n const globalConfig = await readConfigAsync(globalDoomConfigPath(homeDirectory));\n const repositoryPath = repositoryConfigFor(repoRoot, homeDirectory);\n const repositoryConfig: DoomConfig =\n repositoryPath === undefined ? { projectTrust: 'ask' } : await readConfigAsync(repositoryPath);\n return distributionDefaults(mergeDoomConfigs(globalConfig, repositoryConfig), environment);\n}\n\n/**\n * Reads one config file as a layer: what it is, what it sets, and the bytes it\n * held. A file that does not exist is a layer that sets nothing, which is a\n * normal state rather than an error.\n */\nfunction readLayer(filePath: string): DoomConfigLayer {\n let text: string;\n try {\n text = fs.readFileSync(filePath, 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return { filePath, exists: false, hash: '', keys: [] };\n }\n throw error;\n }\n // The raw document, not the parsed config: this is the one read that has to\n // distinguish a key the file set from a key the parser defaulted.\n const document = (parseYaml(text) ?? {}) as unknown;\n return {\n filePath,\n exists: true,\n hash: createHash('sha256').update(text, 'utf8').digest('hex'),\n keys: configLeafKeys(document),\n };\n}\n\n/**\n * The two config files kept apart, with the merge alongside them.\n *\n * `repoRoot` is optional because the global file is complete on its own: a\n * settings surface with no repository in view still has settings to show, and\n * demanding one would leave it with nothing to render rather than with the\n * global half.\n *\n * The origin answer respects the merge's own per-field rules rather than simply\n * preferring the repository: `editor` is read from the global side whatever the\n * repository says, and `projectTrust` from the repository side whatever the\n * global one says. Reporting a file as the source of a value the merge discards\n * is the exact confusion this exists to remove.\n */\nexport function loadDoomConfigLayers(\n repoRoot: string | undefined,\n homeDirectory = os.homedir(),\n environment: NodeJS.ProcessEnv = process.env,\n): DoomConfigLayers {\n const globalLayer = readLayer(globalDoomConfigPath(homeDirectory));\n const repositoryPath = repoRoot === undefined ? undefined : repositoryConfigFor(repoRoot, homeDirectory);\n const repositoryLayer =\n repositoryPath === undefined ? { filePath: '', exists: false, hash: '', keys: [] } : readLayer(repositoryPath);\n // With no repository there is nothing to merge, so the global file stands as\n // the effective config on its own.\n const effective =\n repoRoot === undefined\n ? distributionDefaults(\n mergeDoomConfigs(readConfig(globalDoomConfigPath(homeDirectory)), { projectTrust: 'ask' }),\n environment,\n )\n : loadDoomConfig(repoRoot, homeDirectory, environment);\n const sets = (layer: DoomConfigLayer, keyPath: readonly string[]): boolean => {\n const dotted = keyPath.join('.');\n return layer.keys.some((key) => key === dotted || key.startsWith(`${dotted}.`));\n };\n return {\n globalFile: globalLayer,\n repositoryFile: repositoryLayer,\n effective,\n originOf(keyPath: readonly string[]): ConfigValueOrigin {\n const scope = configScopeOf(keyPath);\n if (scope !== 'global' && sets(repositoryLayer, keyPath)) return 'repository';\n if (scope !== 'repository' && sets(globalLayer, keyPath)) return 'global';\n return 'default';\n },\n valueAt: (keyPath: readonly string[]) => valueAtKeyPath(effective, keyPath),\n };\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import { DOOM_CONFIG_SERVICE } from "@agimon-ai/po-core/config";
2
- export { DOOM_CONFIG_SERVICE as t };