@agimon-ai/doompi-config 0.0.1-alpha.2 → 0.0.1-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 (309) hide show
  1. package/README.md +139 -14
  2. package/dist/adapters/atomicJson.cjs +2 -0
  3. package/dist/adapters/atomicJson.cjs.map +1 -0
  4. package/dist/adapters/atomicJson.d.cts +6 -0
  5. package/dist/adapters/atomicJson.d.cts.map +1 -0
  6. package/dist/adapters/atomicJson.d.mts +6 -0
  7. package/dist/adapters/atomicJson.d.mts.map +1 -0
  8. package/dist/adapters/atomicJson.mjs +2 -0
  9. package/dist/adapters/atomicJson.mjs.map +1 -0
  10. package/dist/adapters/config.cjs +2 -0
  11. package/dist/adapters/config.cjs.map +1 -0
  12. package/dist/adapters/config.d.cts +11 -0
  13. package/dist/adapters/config.d.cts.map +1 -0
  14. package/dist/adapters/config.d.mts +11 -0
  15. package/dist/adapters/config.d.mts.map +1 -0
  16. package/dist/adapters/config.mjs +2 -0
  17. package/dist/adapters/config.mjs.map +1 -0
  18. package/dist/adapters/configWriter.cjs +2 -0
  19. package/dist/adapters/configWriter.cjs.map +1 -0
  20. package/dist/adapters/configWriter.d.cts +52 -0
  21. package/dist/adapters/configWriter.d.cts.map +1 -0
  22. package/dist/adapters/configWriter.d.mts +52 -0
  23. package/dist/adapters/configWriter.d.mts.map +1 -0
  24. package/dist/adapters/configWriter.mjs +2 -0
  25. package/dist/adapters/configWriter.mjs.map +1 -0
  26. package/dist/adapters/domains.cjs +2 -0
  27. package/dist/adapters/domains.cjs.map +1 -0
  28. package/dist/adapters/domains.d.cts +25 -0
  29. package/dist/adapters/domains.d.cts.map +1 -0
  30. package/dist/adapters/domains.d.mts +25 -0
  31. package/dist/adapters/domains.d.mts.map +1 -0
  32. package/dist/adapters/domains.mjs +2 -0
  33. package/dist/adapters/domains.mjs.map +1 -0
  34. package/dist/adapters/harnessState.cjs +2 -0
  35. package/dist/adapters/harnessState.cjs.map +1 -0
  36. package/dist/adapters/harnessState.d.cts +50 -0
  37. package/dist/adapters/harnessState.d.cts.map +1 -0
  38. package/dist/adapters/harnessState.d.mts +50 -0
  39. package/dist/adapters/harnessState.d.mts.map +1 -0
  40. package/dist/adapters/harnessState.mjs +2 -0
  41. package/dist/adapters/harnessState.mjs.map +1 -0
  42. package/dist/adapters/harnessStore.cjs +2 -0
  43. package/dist/adapters/harnessStore.cjs.map +1 -0
  44. package/dist/adapters/harnessStore.d.cts +102 -0
  45. package/dist/adapters/harnessStore.d.cts.map +1 -0
  46. package/dist/adapters/harnessStore.d.mts +102 -0
  47. package/dist/adapters/harnessStore.d.mts.map +1 -0
  48. package/dist/adapters/harnessStore.mjs +2 -0
  49. package/dist/adapters/harnessStore.mjs.map +1 -0
  50. package/dist/adapters/init.cjs +178 -0
  51. package/dist/adapters/init.cjs.map +1 -0
  52. package/dist/adapters/init.d.cts +39 -0
  53. package/dist/adapters/init.d.cts.map +1 -0
  54. package/dist/adapters/init.d.mts +39 -0
  55. package/dist/adapters/init.d.mts.map +1 -0
  56. package/dist/adapters/init.mjs +178 -0
  57. package/dist/adapters/init.mjs.map +1 -0
  58. package/dist/adapters/layeredConfig.cjs +2 -0
  59. package/dist/adapters/layeredConfig.cjs.map +1 -0
  60. package/dist/adapters/layeredConfig.d.cts +49 -0
  61. package/dist/adapters/layeredConfig.d.cts.map +1 -0
  62. package/dist/adapters/layeredConfig.d.mts +49 -0
  63. package/dist/adapters/layeredConfig.d.mts.map +1 -0
  64. package/dist/adapters/layeredConfig.mjs +2 -0
  65. package/dist/adapters/layeredConfig.mjs.map +1 -0
  66. package/dist/adapters/majorModes.cjs +2 -0
  67. package/dist/adapters/majorModes.cjs.map +1 -0
  68. package/dist/adapters/majorModes.d.cts +88 -0
  69. package/dist/adapters/majorModes.d.cts.map +1 -0
  70. package/dist/adapters/majorModes.d.mts +88 -0
  71. package/dist/adapters/majorModes.d.mts.map +1 -0
  72. package/dist/adapters/majorModes.mjs +2 -0
  73. package/dist/adapters/majorModes.mjs.map +1 -0
  74. package/dist/adapters/pi/configExtension.cjs +2 -0
  75. package/dist/adapters/pi/configExtension.cjs.map +1 -0
  76. package/dist/adapters/pi/configExtension.d.cts +8 -0
  77. package/dist/adapters/pi/configExtension.d.cts.map +1 -0
  78. package/dist/adapters/pi/configExtension.d.mts +8 -0
  79. package/dist/adapters/pi/configExtension.d.mts.map +1 -0
  80. package/dist/adapters/pi/configExtension.mjs +2 -0
  81. package/dist/adapters/pi/configExtension.mjs.map +1 -0
  82. package/dist/adapters/pi/doomConfigExtension.cjs +2 -0
  83. package/dist/adapters/pi/doomConfigExtension.cjs.map +1 -0
  84. package/dist/adapters/pi/doomConfigExtension.d.cts +8 -0
  85. package/dist/adapters/pi/doomConfigExtension.d.cts.map +1 -0
  86. package/dist/adapters/pi/doomConfigExtension.d.mts +8 -0
  87. package/dist/adapters/pi/doomConfigExtension.d.mts.map +1 -0
  88. package/dist/adapters/pi/doomConfigExtension.mjs +2 -0
  89. package/dist/adapters/pi/doomConfigExtension.mjs.map +1 -0
  90. package/dist/adapters/pi/helpContribution.cjs +2 -0
  91. package/dist/adapters/pi/helpContribution.cjs.map +1 -0
  92. package/dist/adapters/pi/helpContribution.mjs +2 -0
  93. package/dist/adapters/pi/helpContribution.mjs.map +1 -0
  94. package/dist/adapters/pi/piContext.cjs +2 -0
  95. package/dist/adapters/pi/piContext.cjs.map +1 -0
  96. package/dist/adapters/pi/piContext.d.cts +20 -0
  97. package/dist/adapters/pi/piContext.d.cts.map +1 -0
  98. package/dist/adapters/pi/piContext.d.mts +20 -0
  99. package/dist/adapters/pi/piContext.d.mts.map +1 -0
  100. package/dist/adapters/pi/piContext.mjs +2 -0
  101. package/dist/adapters/pi/piContext.mjs.map +1 -0
  102. package/dist/adapters/piConfig.cjs +2 -0
  103. package/dist/adapters/piConfig.cjs.map +1 -0
  104. package/dist/adapters/piConfig.d.cts +8 -0
  105. package/dist/adapters/piConfig.d.cts.map +1 -0
  106. package/dist/adapters/piConfig.d.mts +8 -0
  107. package/dist/adapters/piConfig.d.mts.map +1 -0
  108. package/dist/adapters/piConfig.mjs +2 -0
  109. package/dist/adapters/piConfig.mjs.map +1 -0
  110. package/dist/adapters/pluginCatalog.cjs +2 -0
  111. package/dist/adapters/pluginCatalog.cjs.map +1 -0
  112. package/dist/adapters/pluginCatalog.d.cts +12 -0
  113. package/dist/adapters/pluginCatalog.d.cts.map +1 -0
  114. package/dist/adapters/pluginCatalog.d.mts +12 -0
  115. package/dist/adapters/pluginCatalog.d.mts.map +1 -0
  116. package/dist/adapters/pluginCatalog.mjs +2 -0
  117. package/dist/adapters/pluginCatalog.mjs.map +1 -0
  118. package/dist/adapters/profiles.cjs +4 -0
  119. package/dist/adapters/profiles.cjs.map +1 -0
  120. package/dist/adapters/profiles.d.cts +36 -0
  121. package/dist/adapters/profiles.d.cts.map +1 -0
  122. package/dist/adapters/profiles.d.mts +36 -0
  123. package/dist/adapters/profiles.d.mts.map +1 -0
  124. package/dist/adapters/profiles.mjs +4 -0
  125. package/dist/adapters/profiles.mjs.map +1 -0
  126. package/dist/atomicJson.cjs +1 -2
  127. package/dist/atomicJson.d.cts +2 -6
  128. package/dist/atomicJson.d.mts +2 -6
  129. package/dist/atomicJson.mjs +1 -2
  130. package/dist/config/piConfig.cjs +1 -2
  131. package/dist/config/piConfig.d.cts +2 -7
  132. package/dist/config/piConfig.d.mts +2 -7
  133. package/dist/config/piConfig.mjs +1 -2
  134. package/dist/config/schema.d.cts +2 -33
  135. package/dist/config/schema.d.mts +2 -33
  136. package/dist/config.cjs +1 -2
  137. package/dist/config.d.cts +3 -24
  138. package/dist/config.d.mts +3 -24
  139. package/dist/config.mjs +1 -2
  140. package/dist/configWriter.cjs +1 -2
  141. package/dist/configWriter.d.cts +2 -52
  142. package/dist/configWriter.d.mts +2 -52
  143. package/dist/configWriter.mjs +1 -2
  144. package/dist/container/doomConfigContainer.cjs +2 -0
  145. package/dist/container/doomConfigContainer.cjs.map +1 -0
  146. package/dist/container/doomConfigContainer.d.cts +12 -0
  147. package/dist/container/doomConfigContainer.d.cts.map +1 -0
  148. package/dist/container/doomConfigContainer.d.mts +12 -0
  149. package/dist/container/doomConfigContainer.d.mts.map +1 -0
  150. package/dist/container/doomConfigContainer.mjs +2 -0
  151. package/dist/container/doomConfigContainer.mjs.map +1 -0
  152. package/dist/container.cjs +1 -2
  153. package/dist/container.d.cts +2 -12
  154. package/dist/container.d.mts +2 -12
  155. package/dist/container.mjs +1 -2
  156. package/dist/domains.cjs +1 -2
  157. package/dist/domains.d.cts +6 -77
  158. package/dist/domains.d.mts +6 -77
  159. package/dist/domains.mjs +1 -2
  160. package/dist/extensions/doom.cjs +1 -2
  161. package/dist/extensions/doom.d.cts +2 -8
  162. package/dist/extensions/doom.d.mts +2 -8
  163. package/dist/extensions/doom.mjs +1 -2
  164. package/dist/extensions/pi.cjs +1 -2
  165. package/dist/extensions/pi.d.cts +2 -8
  166. package/dist/extensions/pi.d.mts +2 -8
  167. package/dist/extensions/pi.mjs +1 -2
  168. package/dist/harnessState.cjs +1 -2
  169. package/dist/harnessState.d.cts +2 -50
  170. package/dist/harnessState.d.mts +2 -50
  171. package/dist/harnessState.mjs +1 -2
  172. package/dist/harnessStore.cjs +1 -2
  173. package/dist/harnessStore.d.cts +2 -102
  174. package/dist/harnessStore.d.mts +2 -102
  175. package/dist/harnessStore.mjs +1 -2
  176. package/dist/index.cjs +1 -1
  177. package/dist/index.d.cts +20 -16
  178. package/dist/index.d.mts +20 -16
  179. package/dist/index.mjs +1 -1
  180. package/dist/init.cjs +1 -76
  181. package/dist/init.d.cts +2 -33
  182. package/dist/init.d.mts +2 -33
  183. package/dist/init.mjs +1 -76
  184. package/dist/layeredConfig.cjs +1 -2
  185. package/dist/layeredConfig.d.cts +2 -49
  186. package/dist/layeredConfig.d.mts +2 -49
  187. package/dist/layeredConfig.mjs +1 -2
  188. package/dist/majorModes.cjs +1 -2
  189. package/dist/majorModes.d.cts +2 -75
  190. package/dist/majorModes.d.mts +2 -75
  191. package/dist/majorModes.mjs +1 -2
  192. package/dist/pi.cjs +1 -1
  193. package/dist/pi.d.cts +1 -1
  194. package/dist/pi.d.mts +1 -1
  195. package/dist/pi.mjs +1 -1
  196. package/dist/piContext.cjs +1 -2
  197. package/dist/piContext.d.cts +2 -19
  198. package/dist/piContext.d.mts +2 -19
  199. package/dist/piContext.mjs +1 -2
  200. package/dist/profiles.cjs +1 -4
  201. package/dist/profiles.d.cts +2 -35
  202. package/dist/profiles.d.mts +2 -35
  203. package/dist/profiles.mjs +1 -4
  204. package/dist/schemas/config/schema.d.cts +33 -0
  205. package/dist/schemas/config/schema.d.cts.map +1 -0
  206. package/dist/schemas/config/schema.d.mts +33 -0
  207. package/dist/schemas/config/schema.d.mts.map +1 -0
  208. package/dist/services/configPolicy.cjs +2 -0
  209. package/dist/services/configPolicy.cjs.map +1 -0
  210. package/dist/services/configPolicy.d.cts +19 -0
  211. package/dist/services/configPolicy.d.cts.map +1 -0
  212. package/dist/services/configPolicy.d.mts +19 -0
  213. package/dist/services/configPolicy.d.mts.map +1 -0
  214. package/dist/services/configPolicy.mjs +2 -0
  215. package/dist/services/configPolicy.mjs.map +1 -0
  216. package/dist/services/domains.cjs +2 -0
  217. package/dist/services/domains.cjs.map +1 -0
  218. package/dist/services/domains.d.cts +12 -0
  219. package/dist/services/domains.d.cts.map +1 -0
  220. package/dist/services/domains.d.mts +12 -0
  221. package/dist/services/domains.d.mts.map +1 -0
  222. package/dist/services/domains.mjs +2 -0
  223. package/dist/services/domains.mjs.map +1 -0
  224. package/dist/types/config.cjs +2 -0
  225. package/dist/types/config.cjs.map +1 -0
  226. package/dist/types/config.d.cts +136 -0
  227. package/dist/types/config.d.cts.map +1 -0
  228. package/dist/types/config.d.mts +136 -0
  229. package/dist/types/config.d.mts.map +1 -0
  230. package/dist/types/config.mjs +2 -0
  231. package/dist/types/config.mjs.map +1 -0
  232. package/dist/types/domains.d.cts +89 -0
  233. package/dist/types/domains.d.cts.map +1 -0
  234. package/dist/types/domains.d.mts +89 -0
  235. package/dist/types/domains.d.mts.map +1 -0
  236. package/dist/types.cjs +1 -2
  237. package/dist/types.d.cts +2 -132
  238. package/dist/types.d.mts +2 -132
  239. package/dist/types.mjs +1 -2
  240. package/llms.txt +9 -0
  241. package/package.json +18 -6
  242. package/skills/doom-pi-config/SKILL.md +6 -3
  243. package/skills/doom-pi-config/references/config-contract.md +123 -8
  244. package/dist/atomicJson.cjs.map +0 -1
  245. package/dist/atomicJson.d.cts.map +0 -1
  246. package/dist/atomicJson.d.mts.map +0 -1
  247. package/dist/atomicJson.mjs.map +0 -1
  248. package/dist/config/piConfig.cjs.map +0 -1
  249. package/dist/config/piConfig.d.cts.map +0 -1
  250. package/dist/config/piConfig.d.mts.map +0 -1
  251. package/dist/config/piConfig.mjs.map +0 -1
  252. package/dist/config/schema.d.cts.map +0 -1
  253. package/dist/config/schema.d.mts.map +0 -1
  254. package/dist/config.cjs.map +0 -1
  255. package/dist/config.d.cts.map +0 -1
  256. package/dist/config.d.mts.map +0 -1
  257. package/dist/config.mjs.map +0 -1
  258. package/dist/configWriter.cjs.map +0 -1
  259. package/dist/configWriter.d.cts.map +0 -1
  260. package/dist/configWriter.d.mts.map +0 -1
  261. package/dist/configWriter.mjs.map +0 -1
  262. package/dist/container.cjs.map +0 -1
  263. package/dist/container.d.cts.map +0 -1
  264. package/dist/container.d.mts.map +0 -1
  265. package/dist/container.mjs.map +0 -1
  266. package/dist/domains.cjs.map +0 -1
  267. package/dist/domains.d.cts.map +0 -1
  268. package/dist/domains.d.mts.map +0 -1
  269. package/dist/domains.mjs.map +0 -1
  270. package/dist/extensions/doom.cjs.map +0 -1
  271. package/dist/extensions/doom.d.cts.map +0 -1
  272. package/dist/extensions/doom.d.mts.map +0 -1
  273. package/dist/extensions/doom.mjs.map +0 -1
  274. package/dist/extensions/pi.cjs.map +0 -1
  275. package/dist/extensions/pi.d.cts.map +0 -1
  276. package/dist/extensions/pi.d.mts.map +0 -1
  277. package/dist/extensions/pi.mjs.map +0 -1
  278. package/dist/harnessState.cjs.map +0 -1
  279. package/dist/harnessState.d.cts.map +0 -1
  280. package/dist/harnessState.d.mts.map +0 -1
  281. package/dist/harnessState.mjs.map +0 -1
  282. package/dist/harnessStore.cjs.map +0 -1
  283. package/dist/harnessStore.d.cts.map +0 -1
  284. package/dist/harnessStore.d.mts.map +0 -1
  285. package/dist/harnessStore.mjs.map +0 -1
  286. package/dist/init.cjs.map +0 -1
  287. package/dist/init.d.cts.map +0 -1
  288. package/dist/init.d.mts.map +0 -1
  289. package/dist/init.mjs.map +0 -1
  290. package/dist/layeredConfig.cjs.map +0 -1
  291. package/dist/layeredConfig.d.cts.map +0 -1
  292. package/dist/layeredConfig.d.mts.map +0 -1
  293. package/dist/layeredConfig.mjs.map +0 -1
  294. package/dist/majorModes.cjs.map +0 -1
  295. package/dist/majorModes.d.cts.map +0 -1
  296. package/dist/majorModes.d.mts.map +0 -1
  297. package/dist/majorModes.mjs.map +0 -1
  298. package/dist/piContext.cjs.map +0 -1
  299. package/dist/piContext.d.cts.map +0 -1
  300. package/dist/piContext.d.mts.map +0 -1
  301. package/dist/piContext.mjs.map +0 -1
  302. package/dist/profiles.cjs.map +0 -1
  303. package/dist/profiles.d.cts.map +0 -1
  304. package/dist/profiles.d.mts.map +0 -1
  305. package/dist/profiles.mjs.map +0 -1
  306. package/dist/types.cjs.map +0 -1
  307. package/dist/types.d.cts.map +0 -1
  308. package/dist/types.d.mts.map +0 -1
  309. package/dist/types.mjs.map +0 -1
@@ -1,75 +1,2 @@
1
- import { PlanningThinkingLevel } from "./types.mjs";
2
- //#region src/majorModes.d.ts
3
- interface LayerPackage {
4
- name: string;
5
- optional?: boolean;
6
- }
7
- interface SubagentLayerModelConfig {
8
- model: string;
9
- thinking?: PlanningThinkingLevel;
10
- }
11
- interface SubagentLayerConfig {
12
- models?: SubagentLayerModelConfig[];
13
- excludeTools?: string[];
14
- }
15
- interface LayerCustomizationConfig {
16
- subagents?: SubagentLayerConfig;
17
- }
18
- interface LayerDefinition {
19
- extensions?: string[];
20
- /**
21
- * npm specifiers, or paths relative to the config that declares the layer.
22
- * A path (`./`, `../`, or absolute) is resolved against the repository root
23
- * for `.doom/modes.yaml` and against the global `.doom` directory for
24
- * `~/.pi/.doom/modes.yaml`, which is how an extension that was never
25
- * published to npm gets loaded.
26
- */
27
- packages?: Array<string | LayerPackage>;
28
- hookGroups?: string[];
29
- config?: LayerCustomizationConfig;
30
- }
31
- /** A layer plus the root its relative package paths resolve against. */
32
- interface ResolvedLayerDefinition extends LayerDefinition {
33
- baseDirectory: string;
34
- }
35
- interface MajorModesConfig {
36
- layers: Record<string, ResolvedLayerDefinition>;
37
- /** The mode selected when neither a flag nor the environment names one. */
38
- defaultMajorMode: string;
39
- /** Named major modes, each one a set of layer names. */
40
- majorMode: Record<string, string[]>;
41
- }
42
- interface LayerResolvers {
43
- ownEntry: (name: string) => string;
44
- packageEntry: (name: string) => string;
45
- optionalPackageEntry: (name: string) => string | undefined;
46
- /** Resolves a path-style layer package against the config that declared it. */
47
- localEntry: (specifier: string, baseDirectory: string) => string | undefined;
48
- }
49
- /**
50
- * Whether a layer package names a path rather than an installed package.
51
- *
52
- * The same rule Node applies to import specifiers, so a bare name is always an
53
- * npm package and a path always looks like one.
54
- */
55
- declare function isLocalPackageSpecifier(specifier: string): boolean;
56
- /**
57
- * Reads layers and major modes from the global and repository configs.
58
- *
59
- * The repository is read last, so it replaces a global layer or major mode of
60
- * the same name. Layers keep the root they were declared under so that a
61
- * global layer naming `./extensions/x` still points beside the global config
62
- * once it is loaded from inside some other repository.
63
- */
64
- declare function loadMajorModesConfig(repoRoot: string, homeDirectory?: string): MajorModesConfig;
65
- /** Merges selected layer customization in order, with later models winning and exclusions unioned. */
66
- declare function resolveLayerCustomization(config: MajorModesConfig, names: string[]): LayerCustomizationConfig;
67
- /** Resolves one named major mode into its configured layer components. */
68
- declare function resolveLayers(config: MajorModesConfig, majorMode: string): string[];
69
- /** Resolves one layer's extension and package entries to absolute paths. */
70
- declare function layerEntries(config: MajorModesConfig, name: string, resolvers: LayerResolvers): string[];
71
- /** Hook group ids contributed by the selected layers, deduped. */
72
- declare function layerHookGroups(config: MajorModesConfig, names: string[]): string[];
73
- //#endregion
74
- export { LayerCustomizationConfig, LayerDefinition, LayerPackage, LayerResolvers, MajorModesConfig, ResolvedLayerDefinition, SubagentLayerConfig, SubagentLayerModelConfig, isLocalPackageSpecifier, layerEntries, layerHookGroups, loadMajorModesConfig, resolveLayerCustomization, resolveLayers };
75
- //# sourceMappingURL=majorModes.d.mts.map
1
+ import { LayerDefinition, LayerPackage, LayerPackageConfig, LayerResolvers, MajorModeDefinition, MajorModesConfig, ResolvedLayerDefinition, ResolvedPackageConfiguration, isLocalPackageSpecifier, layerEntries, layerHookGroups, loadMajorModesConfig, resolveLayers, resolvePackageConfigurations } from "./adapters/majorModes.mjs";
2
+ export { type LayerDefinition, type LayerPackage, type LayerPackageConfig, type LayerResolvers, type MajorModeDefinition, type MajorModesConfig, type ResolvedLayerDefinition, type ResolvedPackageConfiguration, isLocalPackageSpecifier, layerEntries, layerHookGroups, loadMajorModesConfig, resolveLayers, resolvePackageConfigurations };
@@ -1,2 +1 @@
1
- import{DOOM_DIR as e,readDoomConfigSources as t}from"./layeredConfig.mjs";import n from"node:os";import r from"node:path";const i=`modes.yaml`,a=r.join(e,i),o=[`./`,`../`];function s(e){return r.isAbsolute(e)||o.some(t=>e.startsWith(t))}const c=[`subagents`],l=[`models`,`excludeTools`],u=[`model`,`thinking`],d=new Set([`off`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`]);function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function p(e,t,n){let r=Object.keys(e).filter(e=>!t.includes(e));if(r.length>0)throw Error(`${n} has unsupported field(s): ${r.join(`, `)}`)}function m(e,t){if(t===void 0)return;let n=`Layer "${e}" config in ${a}`;if(!f(t))throw Error(`${n} must be a mapping`);if(p(t,c,n),t.subagents===void 0)return{};if(!f(t.subagents))throw Error(`${n}.subagents must be a mapping`);p(t.subagents,l,`${n}.subagents`);let r=Object.hasOwn(t.subagents,`models`),i=Object.hasOwn(t.subagents,`excludeTools`);if(!r&&!i)throw Error(`${n}.subagents must define models or excludeTools`);let o;if(r){if(!Array.isArray(t.subagents.models)||t.subagents.models.length===0)throw Error(`${n}.subagents.models must be a non-empty array`);o=t.subagents.models.map((e,t)=>{let r=`${n}.subagents.models[${t}]`;if(!f(e))throw Error(`${r} must be a mapping`);if(p(e,u,r),typeof e.model!=`string`||!e.model.trim())throw Error(`${r}.model must be a non-empty string`);if(e.thinking!==void 0&&(typeof e.thinking!=`string`||!d.has(e.thinking)))throw Error(`${r}.thinking must be one of: ${[...d].join(`, `)}`);return{model:e.model.trim(),...e.thinking?{thinking:e.thinking}:{}}})}let s;if(i){let e=t.subagents.excludeTools;if(!Array.isArray(e)||e.length===0)throw Error(`${n}.subagents.excludeTools must be a non-empty array`);s=[...new Set(e.map((e,t)=>{let r=`${n}.subagents.excludeTools[${t}]`;if(typeof e!=`string`||!e.trim())throw Error(`${r} must be a non-empty string`);return e.trim()}))]}return{subagents:{...o?{models:o}:{},...s?{excludeTools:s}:{}}}}function h(e){if(typeof e!=`string`||!e.trim())throw Error(`defaultMajorMode in ${a} must be a non-empty string`);return e.trim()}function g(e,t){if(!f(t))throw Error(`Layer "${e}" in ${a} must be a mapping`);if(`targets`in t)throw Error(`Layer "${e}" in ${a} uses removed field "targets"; select availability through major modes`);let n=m(e,t.config);return n===void 0?t:{...t,config:n}}function _(e,r=n.homedir()){let o=t(i,e,r),s={},c={},l=`copilot`,u=!1;for(let e of o){for(let[t,n]of Object.entries(e.document.layers??{}))s[t]={...g(t,n),baseDirectory:e.baseDirectory};Object.hasOwn(e.document,`defaultMajorMode`)&&(l=h(e.document.defaultMajorMode),u=!0),Object.assign(c,e.document.majorMode??{})}for(let[e,t]of Object.entries(c))for(let n of t)if(!s[n])throw Error(`Unknown layer "${n}" in majorMode.${e} of ${a}`);if(u&&!Object.hasOwn(c,l))throw Error(`Unknown default major mode "${l}" in ${a}`);return{layers:s,defaultMajorMode:l,majorMode:c}}function v(e,t){let n,r=new Set,i=!1;for(let a of t){let t=e.layers[a];if(!t)throw Error(`Unknown layer: ${a}`);let o=t.config?.subagents;if(o){if(o.excludeTools!==void 0){i=!0;for(let e of o.excludeTools)r.add(e)}n={...n,...o.models?{models:o.models.map(e=>({...e}))}:{},...i?{excludeTools:[...r]}:{}}}}return n?{subagents:n}:{}}function y(e,t){if(!Object.hasOwn(e.majorMode,t))throw Error(`Unknown major mode: ${t}. Known major modes: ${Object.keys(e.majorMode).sort().join(`, `)}`);return[...e.majorMode[t]]}function b(e,t,n){let r=e.layers[t];if(!r)throw Error(`Unknown layer: ${t}`);let i=[];for(let e of r.extensions??[])i.push(n.ownEntry(e));for(let e of r.packages??[]){let a=typeof e==`string`?e:e.name,o=typeof e!=`string`&&e.optional===!0;if(s(a)){let e=n.localEntry(a,r.baseDirectory);if(e)i.push(e);else if(!o)throw Error(`Layer "${t}" package "${a}" does not resolve under ${r.baseDirectory}. Point it at an extension file, or a directory whose package.json names one.`);continue}if(o){let e=n.optionalPackageEntry(a);e&&i.push(e);continue}i.push(n.packageEntry(a))}return i}function x(e,t){let n=new Set;for(let r of t)for(let t of e.layers[r]?.hookGroups??[])n.add(t);return[...n]}export{s as isLocalPackageSpecifier,b as layerEntries,x as layerHookGroups,_ as loadMajorModesConfig,v as resolveLayerCustomization,y as resolveLayers};
2
- //# sourceMappingURL=majorModes.mjs.map
1
+ import{isLocalPackageSpecifier as e,layerEntries as t,layerHookGroups as n,loadMajorModesConfig as r,resolveLayers as i,resolvePackageConfigurations as a}from"./adapters/majorModes.mjs";export{e as isLocalPackageSpecifier,t as layerEntries,n as layerHookGroups,r as loadMajorModesConfig,i as resolveLayers,a as resolvePackageConfigurations};
package/dist/pi.cjs CHANGED
@@ -1 +1 @@
1
- const e=require("./piContext.cjs");module.exports=e.doomConfigExtension;
1
+ const e=require("./adapters/pi/piContext.cjs");module.exports=e.doomConfigExtension;
package/dist/pi.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { doomConfigExtension } from "./piContext.cjs";
1
+ import { doomConfigExtension } from "./adapters/pi/piContext.cjs";
2
2
  export = doomConfigExtension;
package/dist/pi.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { doomConfigExtension } from "./piContext.mjs";
1
+ import { doomConfigExtension } from "./adapters/pi/piContext.mjs";
2
2
  export { doomConfigExtension as default };
package/dist/pi.mjs CHANGED
@@ -1 +1 @@
1
- import{doomConfigExtension as e}from"./piContext.mjs";export{e as default};
1
+ import{doomConfigExtension as e}from"./adapters/pi/piContext.mjs";export{e as default};
@@ -1,2 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./config.cjs"),t=require("./harnessStore.cjs");let n=require("@agimon-ai/doompi-telemetry");const r=`doom-pi:config:v1`,i=new WeakMap;function a(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version===1&&typeof t.majorMode==`string`&&Array.isArray(t.domains)&&t.domains.every(e=>typeof e==`string`)&&(t.profile===void 0||typeof t.profile==`string`)}function o(e){for(let t=e.length-1;t>=0;--t){let n=e[t];if(n?.type===`custom`&&n.customType===`doom-pi:config:v1`&&a(n.data))return n.data}}function s(e){if(typeof e!=`object`||!e||Object.isFrozen(e))return e;for(let t of Object.values(e))s(t);return Object.freeze(e)}function c(e){return o(e.sessionManager.getBranch())}function l(n){let r=t.getHarnessState(),i=c(n),a=i?{...r,majorMode:i.majorMode,domains:[...i.domains],profile:i.profile}:r,o=!!(i&&(i.majorMode!==r.majorMode||i.profile!==r.profile||i.domains.join(`,`)!==r.domains.join(`,`)));return s({settings:e.loadDoomConfig(r.root??n.cwd),harness:a,requiresRelaunch:o})}function u(e,t){e.appendEntry(r,t)}function d(e,t){let n={context:t,generation:Symbol(`doom-config-context`)};return i.set(e.sessionManager,n),()=>{i.get(e.sessionManager)?.generation===n.generation&&i.delete(e.sessionManager)}}function f(e){let t=i.get(e.sessionManager);if(!t)throw Error(`Doom config context is unavailable. Load @agimon-ai/doompi-config/pi.`);return t.context}const p=e=>{let t,r;e.on(`session_start`,async(e,i)=>{t?.();let a=l(i);t=d(i,a),r??=(0,n.createDoomTelemetry)({serviceName:`doom-config`,packageName:`@agimon-ai/doompi-config`,cwd:i.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),await r.recordEvent(`doom_config.context_bound`,{"config.major_mode":a.harness.majorMode,"config.domain_count":a.harness.domains.length,"config.has_profile":a.harness.profile!==void 0,"config.requires_relaunch":a.requiresRelaunch})}),e.on(`session_shutdown`,async()=>{t=void 0,await r?.shutdown(),r=void 0})};exports.DOOM_CONFIG_ENTRY_TYPE=r,exports.appendDoomConfigSelection=u,exports.createDoomConfigContext=l,exports.doomConfigExtension=p,exports.provideDoomConfigContext=d,exports.readDoomConfigSelection=c,exports.requireDoomConfigContext=f;
2
- //# sourceMappingURL=piContext.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/pi/piContext.cjs");exports.DOOM_CONFIG_ENTRY_TYPE=e.DOOM_CONFIG_ENTRY_TYPE,exports.appendDoomConfigSelection=e.appendDoomConfigSelection,exports.createDoomConfigContext=e.createDoomConfigContext,exports.createDoomConfigContextAsync=e.createDoomConfigContextAsync,exports.doomConfigExtension=e.doomConfigExtension,exports.provideDoomConfigContext=e.provideDoomConfigContext,exports.readDoomConfigSelection=e.readDoomConfigSelection,exports.requireDoomConfigContext=e.requireDoomConfigContext;
@@ -1,19 +1,2 @@
1
- import { DoomConfigContext } from "./types.cjs";
2
- import { ExtensionAPI, ExtensionContext, ExtensionFactory } from "@earendil-works/pi-coding-agent";
3
- //#region src/piContext.d.ts
4
- declare const DOOM_CONFIG_ENTRY_TYPE = "doom-pi:config:v1";
5
- interface DoomConfigSelection {
6
- readonly version: 1;
7
- readonly majorMode: string;
8
- readonly domains: readonly string[];
9
- readonly profile?: string;
10
- }
11
- declare function readDoomConfigSelection(ctx: Pick<ExtensionContext, 'sessionManager'>): DoomConfigSelection | undefined;
12
- declare function createDoomConfigContext(ctx: Pick<ExtensionContext, 'cwd' | 'sessionManager'>): DoomConfigContext;
13
- declare function appendDoomConfigSelection(pi: Pick<ExtensionAPI, 'appendEntry'>, selection: DoomConfigSelection): void;
14
- declare function provideDoomConfigContext(ctx: Pick<ExtensionContext, 'sessionManager'>, context: DoomConfigContext): () => void;
15
- declare function requireDoomConfigContext(ctx: Pick<ExtensionContext, 'sessionManager'>): DoomConfigContext;
16
- declare const doomConfigExtension: ExtensionFactory;
17
- //#endregion
18
- export { DOOM_CONFIG_ENTRY_TYPE, DoomConfigSelection, appendDoomConfigSelection, createDoomConfigContext, doomConfigExtension, provideDoomConfigContext, readDoomConfigSelection, requireDoomConfigContext };
19
- //# sourceMappingURL=piContext.d.cts.map
1
+ import { DOOM_CONFIG_ENTRY_TYPE, DoomConfigSelection, appendDoomConfigSelection, createDoomConfigContext, createDoomConfigContextAsync, doomConfigExtension, provideDoomConfigContext, readDoomConfigSelection, requireDoomConfigContext } from "./adapters/pi/piContext.cjs";
2
+ export { DOOM_CONFIG_ENTRY_TYPE, type DoomConfigSelection, appendDoomConfigSelection, createDoomConfigContext, createDoomConfigContextAsync, doomConfigExtension, provideDoomConfigContext, readDoomConfigSelection, requireDoomConfigContext };
@@ -1,19 +1,2 @@
1
- import { DoomConfigContext } from "./types.mjs";
2
- import { ExtensionAPI, ExtensionContext, ExtensionFactory } from "@earendil-works/pi-coding-agent";
3
- //#region src/piContext.d.ts
4
- declare const DOOM_CONFIG_ENTRY_TYPE = "doom-pi:config:v1";
5
- interface DoomConfigSelection {
6
- readonly version: 1;
7
- readonly majorMode: string;
8
- readonly domains: readonly string[];
9
- readonly profile?: string;
10
- }
11
- declare function readDoomConfigSelection(ctx: Pick<ExtensionContext, 'sessionManager'>): DoomConfigSelection | undefined;
12
- declare function createDoomConfigContext(ctx: Pick<ExtensionContext, 'cwd' | 'sessionManager'>): DoomConfigContext;
13
- declare function appendDoomConfigSelection(pi: Pick<ExtensionAPI, 'appendEntry'>, selection: DoomConfigSelection): void;
14
- declare function provideDoomConfigContext(ctx: Pick<ExtensionContext, 'sessionManager'>, context: DoomConfigContext): () => void;
15
- declare function requireDoomConfigContext(ctx: Pick<ExtensionContext, 'sessionManager'>): DoomConfigContext;
16
- declare const doomConfigExtension: ExtensionFactory;
17
- //#endregion
18
- export { DOOM_CONFIG_ENTRY_TYPE, DoomConfigSelection, appendDoomConfigSelection, createDoomConfigContext, doomConfigExtension, provideDoomConfigContext, readDoomConfigSelection, requireDoomConfigContext };
19
- //# sourceMappingURL=piContext.d.mts.map
1
+ import { DOOM_CONFIG_ENTRY_TYPE, DoomConfigSelection, appendDoomConfigSelection, createDoomConfigContext, createDoomConfigContextAsync, doomConfigExtension, provideDoomConfigContext, readDoomConfigSelection, requireDoomConfigContext } from "./adapters/pi/piContext.mjs";
2
+ export { DOOM_CONFIG_ENTRY_TYPE, type DoomConfigSelection, appendDoomConfigSelection, createDoomConfigContext, createDoomConfigContextAsync, doomConfigExtension, provideDoomConfigContext, readDoomConfigSelection, requireDoomConfigContext };
@@ -1,2 +1 @@
1
- import{loadDoomConfig as e}from"./config.mjs";import{getHarnessState as t}from"./harnessStore.mjs";import{createDoomTelemetry as n}from"@agimon-ai/doompi-telemetry";const r=`doom-pi:config:v1`,i=new WeakMap;function a(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.version===1&&typeof t.majorMode==`string`&&Array.isArray(t.domains)&&t.domains.every(e=>typeof e==`string`)&&(t.profile===void 0||typeof t.profile==`string`)}function o(e){for(let t=e.length-1;t>=0;--t){let n=e[t];if(n?.type===`custom`&&n.customType===`doom-pi:config:v1`&&a(n.data))return n.data}}function s(e){if(typeof e!=`object`||!e||Object.isFrozen(e))return e;for(let t of Object.values(e))s(t);return Object.freeze(e)}function c(e){return o(e.sessionManager.getBranch())}function l(n){let r=t(),i=c(n),a=i?{...r,majorMode:i.majorMode,domains:[...i.domains],profile:i.profile}:r,o=!!(i&&(i.majorMode!==r.majorMode||i.profile!==r.profile||i.domains.join(`,`)!==r.domains.join(`,`)));return s({settings:e(r.root??n.cwd),harness:a,requiresRelaunch:o})}function u(e,t){e.appendEntry(r,t)}function d(e,t){let n={context:t,generation:Symbol(`doom-config-context`)};return i.set(e.sessionManager,n),()=>{i.get(e.sessionManager)?.generation===n.generation&&i.delete(e.sessionManager)}}function f(e){let t=i.get(e.sessionManager);if(!t)throw Error(`Doom config context is unavailable. Load @agimon-ai/doompi-config/pi.`);return t.context}const p=e=>{let t,r;e.on(`session_start`,async(e,i)=>{t?.();let a=l(i);t=d(i,a),r??=n({serviceName:`doom-config`,packageName:`@agimon-ai/doompi-config`,cwd:i.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),await r.recordEvent(`doom_config.context_bound`,{"config.major_mode":a.harness.majorMode,"config.domain_count":a.harness.domains.length,"config.has_profile":a.harness.profile!==void 0,"config.requires_relaunch":a.requiresRelaunch})}),e.on(`session_shutdown`,async()=>{t=void 0,await r?.shutdown(),r=void 0})};export{r as DOOM_CONFIG_ENTRY_TYPE,u as appendDoomConfigSelection,l as createDoomConfigContext,p as doomConfigExtension,d as provideDoomConfigContext,c as readDoomConfigSelection,f as requireDoomConfigContext};
2
- //# sourceMappingURL=piContext.mjs.map
1
+ import{DOOM_CONFIG_ENTRY_TYPE as e,appendDoomConfigSelection as t,createDoomConfigContext as n,createDoomConfigContextAsync as r,doomConfigExtension as i,provideDoomConfigContext as a,readDoomConfigSelection as o,requireDoomConfigContext as s}from"./adapters/pi/piContext.mjs";export{e as DOOM_CONFIG_ENTRY_TYPE,t as appendDoomConfigSelection,n as createDoomConfigContext,r as createDoomConfigContextAsync,i as doomConfigExtension,a as provideDoomConfigContext,o as readDoomConfigSelection,s as requireDoomConfigContext};
package/dist/profiles.cjs CHANGED
@@ -1,4 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./_virtual/_rolldown/runtime.cjs"),t=require("./layeredConfig.cjs");let n=require("node:fs");n=e.__toESM(n,1);let r=require("node:os");r=e.__toESM(r,1);let i=require("node:path");i=e.__toESM(i,1);const a=[`profile.md`,`SOUL.md`,`AGENTS.md`],o=new Set([`persona`,`env`]),s=`profiles`,c=`agents`;function l(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function u(e,t){if(t===void 0)return{};if(!l(t))throw Error(`Profile "${e}" env must be a string mapping`);let n={};for(let[r,i]of Object.entries(t)){if(typeof i!=`string`)throw Error(`Profile "${e}" env.${r} must be a string`);n[r]=i}return n}function d(e,t,r){if(!l(r))throw Error(`Profile "${t}" must be a mapping`);let a=Object.keys(r).filter(e=>!o.has(e));if(a.length>0)throw Error(`Profile "${t}" may only set persona and env; unsupported: ${a.join(`, `)}`);if(typeof r.persona!=`string`||r.persona.trim().length===0)throw Error(`Profile "${t}" must set a persona`);if(i.default.isAbsolute(r.persona))throw Error(`Profile "${t}" persona must be relative to the config that declares it`);let s=r.persona,d=i.default.resolve(e,s),f=i.default.relative(e,d);if(f!==c&&!f.startsWith(`${c}${i.default.sep}`))throw Error(`Profile "${t}" persona must stay inside agents/`);if(!n.default.existsSync(d)||!n.default.statSync(d).isDirectory())throw Error(`Profile "${t}" references a missing persona: ${s}`);let p=n.default.realpathSync(i.default.join(e,c)),m=n.default.realpathSync(d),g=i.default.relative(p,m);if(g===`..`||g.startsWith(`..${i.default.sep}`))throw Error(`Profile "${t}" persona must stay inside agents/`);if(!h(e,s))throw Error(`Profile "${t}" persona has no readable persona files: ${s}`);return{name:t,persona:s,personaRoot:e,env:u(t,r.env)}}function f(e,n=r.default.homedir()){let i=t.readDoomConfigSources(`profiles.yaml`,e,n),a=new Map;for(let e of i){let t=e.document;if(!l(t)||!l(t[s]))throw Error(`${e.filePath} must contain a profiles mapping`);let n=Object.keys(t).filter(e=>e!==s);if(n.length>0)throw Error(`${e.filePath} may only contain profiles; unsupported: ${n.join(`, `)}`);for(let[n,r]of Object.entries(t[s]))a.set(n,d(e.baseDirectory,n,r))}return[...a.values()].sort((e,t)=>e.name.localeCompare(t.name))}function p(e,t,n){let r=f(e,n).find(e=>e.name===t);if(!r)throw Error(`Unknown profile: ${t}`);return r}function m(e,t){return f(e,t).map(e=>e.name)}function h(e,t){let r=[],o=n.default.realpathSync(i.default.join(e,t));for(let e of a){let a=i.default.join(o,e);if(!n.default.existsSync(a))continue;let s=n.default.realpathSync(a),c=i.default.relative(o,s);if(c===`..`||c.startsWith(`..${i.default.sep}`))throw Error(`Persona file must stay inside ${t}: ${e}`);let l=n.default.readFileSync(s,`utf8`).trim();l&&r.push(l)}if(r.length!==0)return[`[PERSONA] You are operating as the person described below (source: ${t}).`,...r].join(`
2
-
3
- `)}function g(e,t){let n={};for(let[r,i]of Object.entries(t))e[r]===void 0&&(e[r]=i,n[r]=i);return n}function _(e,t,n){for(let[n,r]of Object.entries(t))e[n]===r&&delete e[n];return g(e,n)}exports.PERSONA_FILES=a,exports.applyProfileEnvironment=g,exports.buildPersonaPrompt=h,exports.listProfileNames=m,exports.loadProfiles=f,exports.replaceProfileEnvironment=_,exports.resolveProfile=p;
4
- //# sourceMappingURL=profiles.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/profiles.cjs");exports.PERSONA_FILES=e.PERSONA_FILES,exports.applyProfileEnvironment=e.applyProfileEnvironment,exports.buildPersonaPrompt=e.buildPersonaPrompt,exports.listProfileNames=e.listProfileNames,exports.loadProfiles=e.loadProfiles,exports.replaceProfileEnvironment=e.replaceProfileEnvironment,exports.resolveProfile=e.resolveProfile;
@@ -1,35 +1,2 @@
1
- //#region src/profiles.d.ts
2
- /** Files that make up one repository persona, concatenated in this order. */
3
- declare const PERSONA_FILES: string[];
4
- interface AgentProfile {
5
- name: string;
6
- /** Directory under agents/, relative to personaRoot, which remains the persona source. */
7
- persona: string;
8
- /**
9
- * Root the persona path resolves against: the repository root for a
10
- * repository profile, the global `.doom` directory for a global one.
11
- */
12
- personaRoot: string;
13
- /** Environment defaults. Values already exported by the caller win. */
14
- env: Record<string, string>;
15
- }
16
- /**
17
- * Loads profiles from the global and repository configs, repository last.
18
- *
19
- * A repository profile replaces the global profile of the same name. Each one
20
- * keeps the root it was declared under, so a global profile's persona is read
21
- * from `~/.pi/.doom/agents/` however many repositories inherit it.
22
- */
23
- declare function loadProfiles(repoRoot: string, homeDirectory?: string): AgentProfile[];
24
- /** Resolves one selected profile and fails clearly when its name is unknown. */
25
- declare function resolveProfile(repoRoot: string, name: string, homeDirectory?: string): AgentProfile;
26
- declare function listProfileNames(repoRoot: string, homeDirectory?: string): string[];
27
- /** Builds the persona system-prompt block, or undefined when nothing is readable. */
28
- declare function buildPersonaPrompt(personaRoot: string, personaDirectory: string): string | undefined;
29
- /** Applies profile environment defaults and returns only the values it contributed. */
30
- declare function applyProfileEnvironment(environment: NodeJS.ProcessEnv, defaults: Record<string, string>): Record<string, string>;
31
- /** Replaces environment defaults previously contributed by another profile. */
32
- declare function replaceProfileEnvironment(environment: NodeJS.ProcessEnv, previous: Record<string, string>, next: Record<string, string>): Record<string, string>;
33
- //#endregion
34
- export { AgentProfile, PERSONA_FILES, applyProfileEnvironment, buildPersonaPrompt, listProfileNames, loadProfiles, replaceProfileEnvironment, resolveProfile };
35
- //# sourceMappingURL=profiles.d.cts.map
1
+ import { AgentProfile, PERSONA_FILES, applyProfileEnvironment, buildPersonaPrompt, listProfileNames, loadProfiles, replaceProfileEnvironment, resolveProfile } from "./adapters/profiles.cjs";
2
+ export { type AgentProfile, PERSONA_FILES, applyProfileEnvironment, buildPersonaPrompt, listProfileNames, loadProfiles, replaceProfileEnvironment, resolveProfile };
@@ -1,35 +1,2 @@
1
- //#region src/profiles.d.ts
2
- /** Files that make up one repository persona, concatenated in this order. */
3
- declare const PERSONA_FILES: string[];
4
- interface AgentProfile {
5
- name: string;
6
- /** Directory under agents/, relative to personaRoot, which remains the persona source. */
7
- persona: string;
8
- /**
9
- * Root the persona path resolves against: the repository root for a
10
- * repository profile, the global `.doom` directory for a global one.
11
- */
12
- personaRoot: string;
13
- /** Environment defaults. Values already exported by the caller win. */
14
- env: Record<string, string>;
15
- }
16
- /**
17
- * Loads profiles from the global and repository configs, repository last.
18
- *
19
- * A repository profile replaces the global profile of the same name. Each one
20
- * keeps the root it was declared under, so a global profile's persona is read
21
- * from `~/.pi/.doom/agents/` however many repositories inherit it.
22
- */
23
- declare function loadProfiles(repoRoot: string, homeDirectory?: string): AgentProfile[];
24
- /** Resolves one selected profile and fails clearly when its name is unknown. */
25
- declare function resolveProfile(repoRoot: string, name: string, homeDirectory?: string): AgentProfile;
26
- declare function listProfileNames(repoRoot: string, homeDirectory?: string): string[];
27
- /** Builds the persona system-prompt block, or undefined when nothing is readable. */
28
- declare function buildPersonaPrompt(personaRoot: string, personaDirectory: string): string | undefined;
29
- /** Applies profile environment defaults and returns only the values it contributed. */
30
- declare function applyProfileEnvironment(environment: NodeJS.ProcessEnv, defaults: Record<string, string>): Record<string, string>;
31
- /** Replaces environment defaults previously contributed by another profile. */
32
- declare function replaceProfileEnvironment(environment: NodeJS.ProcessEnv, previous: Record<string, string>, next: Record<string, string>): Record<string, string>;
33
- //#endregion
34
- export { AgentProfile, PERSONA_FILES, applyProfileEnvironment, buildPersonaPrompt, listProfileNames, loadProfiles, replaceProfileEnvironment, resolveProfile };
35
- //# sourceMappingURL=profiles.d.mts.map
1
+ import { AgentProfile, PERSONA_FILES, applyProfileEnvironment, buildPersonaPrompt, listProfileNames, loadProfiles, replaceProfileEnvironment, resolveProfile } from "./adapters/profiles.mjs";
2
+ export { type AgentProfile, PERSONA_FILES, applyProfileEnvironment, buildPersonaPrompt, listProfileNames, loadProfiles, replaceProfileEnvironment, resolveProfile };
package/dist/profiles.mjs CHANGED
@@ -1,4 +1 @@
1
- import{readDoomConfigSources as e}from"./layeredConfig.mjs";import t from"node:fs";import n from"node:os";import r from"node:path";const i=[`profile.md`,`SOUL.md`,`AGENTS.md`],a=new Set([`persona`,`env`]),o=`profiles`,s=`agents`;function c(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function l(e,t){if(t===void 0)return{};if(!c(t))throw Error(`Profile "${e}" env must be a string mapping`);let n={};for(let[r,i]of Object.entries(t)){if(typeof i!=`string`)throw Error(`Profile "${e}" env.${r} must be a string`);n[r]=i}return n}function u(e,n,i){if(!c(i))throw Error(`Profile "${n}" must be a mapping`);let o=Object.keys(i).filter(e=>!a.has(e));if(o.length>0)throw Error(`Profile "${n}" may only set persona and env; unsupported: ${o.join(`, `)}`);if(typeof i.persona!=`string`||i.persona.trim().length===0)throw Error(`Profile "${n}" must set a persona`);if(r.isAbsolute(i.persona))throw Error(`Profile "${n}" persona must be relative to the config that declares it`);let u=i.persona,d=r.resolve(e,u),f=r.relative(e,d);if(f!==s&&!f.startsWith(`${s}${r.sep}`))throw Error(`Profile "${n}" persona must stay inside agents/`);if(!t.existsSync(d)||!t.statSync(d).isDirectory())throw Error(`Profile "${n}" references a missing persona: ${u}`);let p=t.realpathSync(r.join(e,s)),h=t.realpathSync(d),g=r.relative(p,h);if(g===`..`||g.startsWith(`..${r.sep}`))throw Error(`Profile "${n}" persona must stay inside agents/`);if(!m(e,u))throw Error(`Profile "${n}" persona has no readable persona files: ${u}`);return{name:n,persona:u,personaRoot:e,env:l(n,i.env)}}function d(t,r=n.homedir()){let i=e(`profiles.yaml`,t,r),a=new Map;for(let e of i){let t=e.document;if(!c(t)||!c(t[o]))throw Error(`${e.filePath} must contain a profiles mapping`);let n=Object.keys(t).filter(e=>e!==o);if(n.length>0)throw Error(`${e.filePath} may only contain profiles; unsupported: ${n.join(`, `)}`);for(let[n,r]of Object.entries(t[o]))a.set(n,u(e.baseDirectory,n,r))}return[...a.values()].sort((e,t)=>e.name.localeCompare(t.name))}function f(e,t,n){let r=d(e,n).find(e=>e.name===t);if(!r)throw Error(`Unknown profile: ${t}`);return r}function p(e,t){return d(e,t).map(e=>e.name)}function m(e,n){let a=[],o=t.realpathSync(r.join(e,n));for(let e of i){let i=r.join(o,e);if(!t.existsSync(i))continue;let s=t.realpathSync(i),c=r.relative(o,s);if(c===`..`||c.startsWith(`..${r.sep}`))throw Error(`Persona file must stay inside ${n}: ${e}`);let l=t.readFileSync(s,`utf8`).trim();l&&a.push(l)}if(a.length!==0)return[`[PERSONA] You are operating as the person described below (source: ${n}).`,...a].join(`
2
-
3
- `)}function h(e,t){let n={};for(let[r,i]of Object.entries(t))e[r]===void 0&&(e[r]=i,n[r]=i);return n}function g(e,t,n){for(let[n,r]of Object.entries(t))e[n]===r&&delete e[n];return h(e,n)}export{i as PERSONA_FILES,h as applyProfileEnvironment,m as buildPersonaPrompt,p as listProfileNames,d as loadProfiles,g as replaceProfileEnvironment,f as resolveProfile};
4
- //# sourceMappingURL=profiles.mjs.map
1
+ import{PERSONA_FILES as e,applyProfileEnvironment as t,buildPersonaPrompt as n,listProfileNames as r,loadProfiles as i,replaceProfileEnvironment as a,resolveProfile as o}from"./adapters/profiles.mjs";export{e as PERSONA_FILES,t as applyProfileEnvironment,n as buildPersonaPrompt,r as listProfileNames,i as loadProfiles,a as replaceProfileEnvironment,o as resolveProfile};
@@ -0,0 +1,33 @@
1
+ //#region src/schemas/config/schema.d.ts
2
+ type PiConfig = Record<string, unknown>;
3
+ interface DoomAdapterSettings {
4
+ projectTrust?: 'ask' | 'always' | 'never';
5
+ }
6
+ interface PiConfigPaths {
7
+ canonicalUser: string;
8
+ canonicalProject: string;
9
+ legacyUser: readonly string[];
10
+ legacyProject: readonly string[];
11
+ }
12
+ interface PiConfigLoadOptions {
13
+ repoRoot: string;
14
+ homeDirectory?: string;
15
+ defaults?: PiConfig;
16
+ overlay?: PiConfig;
17
+ userConfigPaths?: readonly string[];
18
+ projectConfigPaths?: readonly string[];
19
+ programmatic?: PiConfig;
20
+ environment?: PiConfig;
21
+ cli?: PiConfig;
22
+ isProjectTrusted: boolean | (() => boolean);
23
+ }
24
+ interface ConfigAdapterRegistrationOptions {
25
+ defaults?: PiConfig;
26
+ programmatic?: PiConfig;
27
+ environment?: PiConfig;
28
+ cli?: PiConfig;
29
+ homeDirectory?: string;
30
+ }
31
+ //#endregion
32
+ export { ConfigAdapterRegistrationOptions, DoomAdapterSettings, PiConfig, PiConfigLoadOptions, PiConfigPaths };
33
+ //# sourceMappingURL=schema.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.cts","names":[],"sources":["../../../src/schemas/config/schema.ts"],"mappings":";KAAY,WAAW;UAEN;EACf;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,WAAW;EACX,UAAU;EACV;EACA;EACA,eAAe;EACf,cAAc;EACd,MAAM;EACN;;UAGe;EACf,WAAW;EACX,eAAe;EACf,cAAc;EACd,MAAM;EACN"}
@@ -0,0 +1,33 @@
1
+ //#region src/schemas/config/schema.d.ts
2
+ type PiConfig = Record<string, unknown>;
3
+ interface DoomAdapterSettings {
4
+ projectTrust?: 'ask' | 'always' | 'never';
5
+ }
6
+ interface PiConfigPaths {
7
+ canonicalUser: string;
8
+ canonicalProject: string;
9
+ legacyUser: readonly string[];
10
+ legacyProject: readonly string[];
11
+ }
12
+ interface PiConfigLoadOptions {
13
+ repoRoot: string;
14
+ homeDirectory?: string;
15
+ defaults?: PiConfig;
16
+ overlay?: PiConfig;
17
+ userConfigPaths?: readonly string[];
18
+ projectConfigPaths?: readonly string[];
19
+ programmatic?: PiConfig;
20
+ environment?: PiConfig;
21
+ cli?: PiConfig;
22
+ isProjectTrusted: boolean | (() => boolean);
23
+ }
24
+ interface ConfigAdapterRegistrationOptions {
25
+ defaults?: PiConfig;
26
+ programmatic?: PiConfig;
27
+ environment?: PiConfig;
28
+ cli?: PiConfig;
29
+ homeDirectory?: string;
30
+ }
31
+ //#endregion
32
+ export { ConfigAdapterRegistrationOptions, DoomAdapterSettings, PiConfig, PiConfigLoadOptions, PiConfigPaths };
33
+ //# sourceMappingURL=schema.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.mts","names":[],"sources":["../../../src/schemas/config/schema.ts"],"mappings":";KAAY,WAAW;UAEN;EACf;;UAGe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA,WAAW;EACX,UAAU;EACV;EACA;EACA,eAAe;EACf,cAAc;EACd,MAAM;EACN;;UAGe;EACf,WAAW;EACX,eAAe;EACf,cAAc;EACd,MAAM;EACN"}
@@ -0,0 +1,2 @@
1
+ let e=require("yaml");const t=`auto`,n=[`modes`,`projectTrust`,`editor`,`voice`,`selection`],r=[`majorMode`,`domains`,`profile`],i=[`planning`],a=[`main`,`subagents`,`plansDirectory`],o=[`model`,`thinking`],s=[`command`],c=[`engine`,`language`,`recorder`,`adapters`,`autoCapture`],l=[`binary`,`device`],u=`whisper-cpp`,d=`openai-whisper`,f=`mlx-whisper`,p=[u,d,f],m=[`binary`,`model`],h=[`path`,`id`],g=[`model`,`startPhrases`,`stopPhrases`,`utteranceIdleMs`,`transcriptionTimeoutMs`,`tts`],_=[`engine`,`voice`,`rate`],v=1500,y=1e4,b=1e3,x=12e4,S=/^[^/\s]+\/[^/\s]+(?:\/[^/\s]+)*$/u,C=/[\p{P}\p{S}]+/gu,w=[`off`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`],T=[t,u,d,f],E=[`macos-say`],D=new Set(w),O=new Set([`ask`,`always`,`never`]),k=new Set(T),A=new Set(E);function j(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function M(e,t,n,r){let i=Object.keys(e).filter(e=>!t.includes(e));if(i.length>0)throw Error(`Doom config at ${r} has unsupported ${n} field(s): ${i.join(`, `)}`)}function N(e,t,n){if(e!==void 0){if(typeof e!=`string`||e.trim().length===0)throw Error(`Doom config at ${n} requires ${t} to be a non-empty string`);return e.trim()}}function P(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&(e<=31||e===127))return!0}return!1}function F(e,t,n,r){let i=N(e,t,n);if(i){if(i.length>r)throw Error(`Doom config at ${n} requires ${t} to be at most ${r} characters`);if(P(i))throw Error(`Doom config at ${n} does not allow control characters in ${t}`);return i}}function I(e,t){let n=`voice.autoCapture.model`,r=N(e,n,t);if(!r||!S.test(r))throw Error(`Doom config at ${t} requires ${n} in provider/model-id form`);return r}function L(e){return e.normalize(`NFKC`).toLocaleLowerCase(`en-US`).replace(C,` `).replace(/\s+/gu,` `).trim()}function R(e,t,n){if(e===void 0)return;if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw Error(`Doom config at ${n} requires ${t} to be an array of strings`);if(e.length>16)throw Error(`Doom config at ${n} requires ${t} to contain at most 16 phrases`);let r=e.map(e=>e.trim()),i=new Set;for(let e of r){if(e.length===0)throw Error(`Doom config at ${n} requires ${t} to contain non-empty strings`);if(e.length>64)throw Error(`Doom config at ${n} requires ${t} phrases to be at most 64 characters`);if(P(e))throw Error(`Doom config at ${n} does not allow control characters in ${t}`);let r=L(e);if(!r)throw Error(`Doom config at ${n} requires ${t} to contain words`);if(i.has(r))throw Error(`Doom config at ${n} does not allow normalized duplicates in ${t}`);i.add(r)}return r}function z(e,t){let n=`voice.autoCapture.tts`;if(!j(e))throw Error(`Doom config at ${t} requires ${n} to be an object`);if(M(e,_,n,t),typeof e.engine!=`string`||!A.has(e.engine))throw Error(`Doom config at ${t} requires ${n}.engine to be one of: ${[...A].join(`, `)}`);let r=F(e.voice,`${n}.voice`,t,64),i=e.rate;if(i!==void 0&&(typeof i!=`number`||!Number.isInteger(i)||i<80||i>500))throw Error(`Doom config at ${t} requires ${n}.rate to be an integer from 80 to 500`);return{engine:e.engine,...r?{voice:r}:{},...i===void 0?{}:{rate:i}}}function B(e,t){if(e===void 0)return;let n=`voice.autoCapture`;if(!j(e))throw Error(`Doom config at ${t} requires ${n} to be an object`);M(e,g,n,t);let r=R(e.startPhrases,`${n}.startPhrases`,t),i=R(e.stopPhrases,`${n}.stopPhrases`,t),a=e.utteranceIdleMs;if(a!==void 0&&(typeof a!=`number`||!Number.isInteger(a)||a<v||a>y))throw Error(`Doom config at ${t} requires ${n}.utteranceIdleMs to be an integer from ${v} to ${y}`);let o=e.transcriptionTimeoutMs;if(o!==void 0&&(typeof o!=`number`||!Number.isInteger(o)||o<b||o>x))throw Error(`Doom config at ${t} requires ${n}.transcriptionTimeoutMs to be an integer from ${b} to ${x}`);let s=new Set((r??[]).map(L));if((i??[]).some(e=>s.has(L(e))))throw Error(`Doom config at ${t} does not allow a phrase in both startPhrases and stopPhrases`);return{model:I(e.model,t),...r?{startPhrases:r}:{},...i?{stopPhrases:i}:{},...a===void 0?{}:{utteranceIdleMs:a},...o===void 0?{}:{transcriptionTimeoutMs:o},tts:z(e.tts,t)}}function V(e,t,n){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${n} requires ${t} to be an object`);M(e,o,t,n);let r=e.thinking;if(r!==void 0&&(typeof r!=`string`||!D.has(r)))throw Error(`Doom config at ${n} requires ${t}.thinking to be one of: ${[...D].join(`, `)}`);let i=N(e.model,`${t}.model`,n);return{...i?{model:i}:{},...r?{thinking:r}:{}}}function H(e,t,n=`modes.planning`){if(!j(e))throw Error(`Doom config at ${t} requires ${n} to be an object`);return M(e,a,n,t),{main:V(e.main,`${n}.main`,t),subagents:V(e.subagents,`${n}.subagents`,t),plansDirectory:N(e.plansDirectory,`${n}.plansDirectory`,t)}}function U(e,t,n,r){if(!j(e))throw Error(`Doom config at ${n} requires ${t} to be an object`);M(e,h,t,n);let i=N(e.path,`${t}.path`,n),a=N(e.id,`${t}.id`,n);if(!!i==!!a)throw Error(`Doom config at ${n} requires exactly one of ${t}.path or ${t}.id`);if(a&&!r)throw Error(`Doom config at ${n} does not support ${t}.id for whisper-cpp`);return{...i?{path:i}:{},...a?{id:a}:{}}}function W(e,t,n,r){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${n} requires ${t} to be an object`);M(e,m,t,n);let i=N(e.binary,`${t}.binary`,n);return{...i?{binary:i}:{},model:U(e.model,`${t}.model`,n,r)}}function G(e,t){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${t} requires voice to be an object`);M(e,c,`voice`,t);let n={};if(e.engine!==void 0){if(typeof e.engine!=`string`||!k.has(e.engine))throw Error(`Doom config at ${t} requires voice.engine to be one of: ${[...k].join(`, `)}`);n.engine=e.engine}let r=N(e.language,`voice.language`,t);if(r&&(n.language=r),e.recorder!==void 0){if(!j(e.recorder))throw Error(`Doom config at ${t} requires voice.recorder to be an object`);M(e.recorder,l,`voice.recorder`,t),n.recorder={};let r=N(e.recorder.binary,`voice.recorder.binary`,t),i=N(e.recorder.device,`voice.recorder.device`,t);r&&(n.recorder.binary=r),i&&(n.recorder.device=i)}if(e.adapters!==void 0){if(!j(e.adapters))throw Error(`Doom config at ${t} requires voice.adapters to be an object`);M(e.adapters,p,`voice.adapters`,t),n.adapters={[u]:W(e.adapters[u],`voice.adapters.${u}`,t,!1),[d]:W(e.adapters[d],`voice.adapters.${d}`,t,!0),[f]:W(e.adapters[f],`voice.adapters.${f}`,t,!0)}}let i=B(e.autoCapture,t);return i&&(n.autoCapture=i),n}function K(e,t){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${t} requires selection to be an object`);M(e,r,`selection`,t);let n=e.domains;if(n!==void 0&&(!Array.isArray(n)||n.some(e=>typeof e!=`string`)))throw Error(`Doom config at ${t} requires selection.domains to be an array of strings`);return{majorMode:N(e.majorMode,`selection.majorMode`,t),domains:n,profile:N(e.profile,`selection.profile`,t)}}function q(e,t){if(e!==void 0){if(!j(e))throw Error(`Doom config at ${t} requires editor to be an object`);return M(e,s,`editor`,t),{command:N(e.command,`editor.command`,t)}}}function J(t,r){let a;try{a=(0,e.parse)(t)??{}}catch(e){throw Error(`Could not parse Doom config at ${r}`,{cause:e})}if(!j(a))throw Error(`Doom config at ${r} must be a YAML object`);M(a,n,`root`,r);let o;if(a.modes!==void 0){if(!j(a.modes))throw Error(`Doom config at ${r} requires modes to be an object`);M(a.modes,i,`modes`,r),o=a.modes.planning===void 0?{}:{planning:H(a.modes.planning,r)}}let s=a.projectTrust===void 0?`ask`:a.projectTrust;if(typeof s!=`string`||!O.has(s))throw Error(`Doom config at ${r} projectTrust must be ask, always, or never`);return{modes:o,projectTrust:s,editor:q(a.editor,r),voice:G(a.voice,r),selection:K(a.selection,r)}}function Y(e,t){return e||t?{...e,...t}:void 0}function X(e,t){if(t.voice?.autoCapture)throw Error(`Repository Doom config voice.autoCapture is global-only; configure it in ~/.pi/.doom/config.yaml`);let n=e.modes?.planning,r=t.modes?.planning,i=n||r?{main:Y(n?.main,r?.main),subagents:Y(n?.subagents,r?.subagents),plansDirectory:r?.plansDirectory??n?.plansDirectory}:void 0,a=Q(e.voice,t.voice);return{modes:i?{planning:i}:void 0,projectTrust:t.projectTrust,editor:e.editor,voice:a,selection:e.selection||t.selection?{...e.selection,...t.selection}:void 0}}function Z(e,t){if(!(!e&&!t))return{...e,...t,model:t?.model??e.model}}function Q(e,t){if(!(!e&&!t))return{...e,...t,recorder:e?.recorder||t?.recorder?{...e?.recorder,...t?.recorder}:void 0,adapters:e?.adapters||t?.adapters?{[u]:Z(e?.adapters?.[u],t?.adapters?.[u]),[d]:Z(e?.adapters?.[d],t?.adapters?.[d]),[f]:Z(e?.adapters?.[f],t?.adapters?.[f])}:void 0,...e?.autoCapture?{autoCapture:e.autoCapture}:{}}}function $(e){return{engine:e.engine??t,language:e.language??`auto`,recorder:{...e.recorder,device:e.recorder?.device??`none:default`},adapters:e.adapters??{},...e.autoCapture?{autoCapture:{...e.autoCapture,startPhrases:[...e.autoCapture.startPhrases??[]],stopPhrases:[...e.autoCapture.stopPhrases??[]],utteranceIdleMs:e.autoCapture.utteranceIdleMs??3e3,transcriptionTimeoutMs:e.autoCapture.transcriptionTimeoutMs??15e3,tts:{...e.autoCapture.tts}}}:{}}}exports.DOOM_PLANNING_THINKING_LEVELS=w,exports.DOOM_VOICE_ENGINES=T,exports.DOOM_VOICE_TTS_ENGINES=E,exports.mergeDoomConfigs=X,exports.parseDoomConfig=J,exports.parsePlanningModeConfig=H,exports.resolveVoiceConfig=$;
2
+ //# sourceMappingURL=configPolicy.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configPolicy.cjs","names":["parseYaml"],"sources":["../../src/services/configPolicy.ts"],"sourcesContent":["import { parse as parseYaml } from 'yaml';\nimport type {\n DoomConfig,\n DoomSelectionConfig,\n EditorConfig,\n PlanningAgentConfig,\n PlanningModeConfig,\n PlanningThinkingLevel,\n ProjectTrust,\n ResolvedVoiceConfig,\n VoiceAdapterConfig,\n VoiceAutoCaptureConfig,\n VoiceConfig,\n VoiceEngine,\n VoiceModelConfig,\n VoiceTtsConfig,\n VoiceTtsEngine,\n} from '../types/config.ts';\n\nconst DEFAULT_PROJECT_TRUST: ProjectTrust = 'ask';\nconst DEFAULT_VOICE_ENGINE: VoiceEngine = 'auto';\nconst DEFAULT_VOICE_LANGUAGE = 'auto';\nconst DEFAULT_RECORDER_DEVICE = 'none:default';\nconst ROOT_KEYS = ['modes', 'projectTrust', 'editor', 'voice', 'selection'] as const;\nconst SELECTION_KEYS = ['majorMode', 'domains', 'profile'] as const;\nconst MODE_KEYS = ['planning'] as const;\nconst PLANNING_KEYS = ['main', 'subagents', 'plansDirectory'] as const;\nconst AGENT_KEYS = ['model', 'thinking'] as const;\nconst EDITOR_KEYS = ['command'] as const;\nconst VOICE_KEYS = ['engine', 'language', 'recorder', 'adapters', 'autoCapture'] as const;\nconst RECORDER_KEYS = ['binary', 'device'] as const;\nconst WHISPER_CPP_ENGINE = 'whisper-cpp' as const;\nconst OPENAI_WHISPER_ENGINE = 'openai-whisper' as const;\nconst MLX_WHISPER_ENGINE = 'mlx-whisper' as const;\nconst MACOS_SAY_TTS_ENGINE = 'macos-say' as const;\nconst ADAPTERS_KEYS = [WHISPER_CPP_ENGINE, OPENAI_WHISPER_ENGINE, MLX_WHISPER_ENGINE] as const;\nconst ADAPTER_KEYS = ['binary', 'model'] as const;\nconst MODEL_KEYS = ['path', 'id'] as const;\nconst AUTO_CAPTURE_KEYS = [\n 'model',\n 'startPhrases',\n 'stopPhrases',\n 'utteranceIdleMs',\n 'transcriptionTimeoutMs',\n 'tts',\n] as const;\nconst TTS_KEYS = ['engine', 'voice', 'rate'] as const;\nconst DEFAULT_UTTERANCE_IDLE_MS = 3_000;\nconst MIN_UTTERANCE_IDLE_MS = 1_500;\nconst MAX_UTTERANCE_IDLE_MS = 10_000;\nconst DEFAULT_TRANSCRIPTION_TIMEOUT_MS = 15_000;\nconst MIN_TRANSCRIPTION_TIMEOUT_MS = 1_000;\nconst MAX_TRANSCRIPTION_TIMEOUT_MS = 120_000;\nconst MAX_CONTROL_PHRASES = 16;\nconst MAX_CONTROL_PHRASE_LENGTH = 64;\nconst MAX_TTS_VOICE_LENGTH = 64;\nconst MIN_TTS_RATE = 80;\nconst MAX_TTS_RATE = 500;\nconst MODEL_REFERENCE_PATTERN = /^[^/\\s]+\\/[^/\\s]+(?:\\/[^/\\s]+)*$/u;\nconst PHRASE_PUNCTUATION_PATTERN = /[\\p{P}\\p{S}]+/gu;\n/**\n * The accepted values, in the order a picker should offer them.\n *\n * Exported because the config UI has to offer exactly what the parser accepts,\n * and a second hand-written list in the contributing package would drift. The\n * validating Sets below are built from these for the same reason.\n */\nexport const DOOM_PLANNING_THINKING_LEVELS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const;\nexport const DOOM_VOICE_ENGINES = [\n DEFAULT_VOICE_ENGINE,\n WHISPER_CPP_ENGINE,\n OPENAI_WHISPER_ENGINE,\n MLX_WHISPER_ENGINE,\n] as const;\nexport const DOOM_VOICE_TTS_ENGINES = [MACOS_SAY_TTS_ENGINE] as const;\n\nconst THINKING_VALUES = new Set<PlanningThinkingLevel>(DOOM_PLANNING_THINKING_LEVELS);\nconst TRUST_VALUES = new Set<ProjectTrust>(['ask', 'always', 'never']);\nconst ENGINE_VALUES = new Set<VoiceEngine>(DOOM_VOICE_ENGINES);\nconst TTS_ENGINE_VALUES = new Set<VoiceTtsEngine>(DOOM_VOICE_TTS_ENGINES);\ntype ConfigObject = Record<string, unknown>;\n\nfunction isObject(value: unknown): value is ConfigObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\nfunction assertKeys(value: ConfigObject, allowed: readonly string[], location: string, filePath: string): void {\n const unknown = Object.keys(value).filter((key) => !allowed.includes(key));\n if (unknown.length > 0)\n throw new Error(`Doom config at ${filePath} has unsupported ${location} field(s): ${unknown.join(', ')}`);\n}\nfunction optionalString(value: unknown, location: string, filePath: string): string | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== 'string' || value.trim().length === 0)\n throw new Error(`Doom config at ${filePath} requires ${location} to be a non-empty string`);\n return value.trim();\n}\nfunction hasControlCharacters(value: string): boolean {\n for (const character of value) {\n const codePoint = character.codePointAt(0);\n if (codePoint !== undefined && (codePoint <= 0x1f || codePoint === 0x7f)) return true;\n }\n return false;\n}\nfunction boundedOptionalString(\n value: unknown,\n location: string,\n filePath: string,\n maximumLength: number,\n): string | undefined {\n const text = optionalString(value, location, filePath);\n if (!text) return undefined;\n if (text.length > maximumLength)\n throw new Error(`Doom config at ${filePath} requires ${location} to be at most ${maximumLength} characters`);\n if (hasControlCharacters(text))\n throw new Error(`Doom config at ${filePath} does not allow control characters in ${location}`);\n return text;\n}\nfunction parseModelReference(value: unknown, filePath: string): string {\n const location = 'voice.autoCapture.model';\n const model = optionalString(value, location, filePath);\n if (!model || !MODEL_REFERENCE_PATTERN.test(model))\n throw new Error(`Doom config at ${filePath} requires ${location} in provider/model-id form`);\n return model;\n}\nfunction normalizeControlPhrase(value: string): string {\n return value\n .normalize('NFKC')\n .toLocaleLowerCase('en-US')\n .replace(PHRASE_PUNCTUATION_PATTERN, ' ')\n .replace(/\\s+/gu, ' ')\n .trim();\n}\nfunction parseControlPhrases(value: unknown, location: string, filePath: string): string[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || value.some((phrase) => typeof phrase !== 'string'))\n throw new Error(`Doom config at ${filePath} requires ${location} to be an array of strings`);\n if (value.length > MAX_CONTROL_PHRASES)\n throw new Error(\n `Doom config at ${filePath} requires ${location} to contain at most ${MAX_CONTROL_PHRASES} phrases`,\n );\n const phrases = value.map((phrase) => phrase.trim());\n const normalized = new Set<string>();\n for (const phrase of phrases) {\n if (phrase.length === 0)\n throw new Error(`Doom config at ${filePath} requires ${location} to contain non-empty strings`);\n if (phrase.length > MAX_CONTROL_PHRASE_LENGTH)\n throw new Error(\n `Doom config at ${filePath} requires ${location} phrases to be at most ${MAX_CONTROL_PHRASE_LENGTH} characters`,\n );\n if (hasControlCharacters(phrase))\n throw new Error(`Doom config at ${filePath} does not allow control characters in ${location}`);\n const key = normalizeControlPhrase(phrase);\n if (!key) throw new Error(`Doom config at ${filePath} requires ${location} to contain words`);\n if (normalized.has(key))\n throw new Error(`Doom config at ${filePath} does not allow normalized duplicates in ${location}`);\n normalized.add(key);\n }\n return phrases;\n}\nfunction parseTtsConfig(value: unknown, filePath: string): VoiceTtsConfig {\n const location = 'voice.autoCapture.tts';\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires ${location} to be an object`);\n assertKeys(value, TTS_KEYS, location, filePath);\n if (typeof value.engine !== 'string' || !TTS_ENGINE_VALUES.has(value.engine as VoiceTtsEngine))\n throw new Error(\n `Doom config at ${filePath} requires ${location}.engine to be one of: ${[...TTS_ENGINE_VALUES].join(', ')}`,\n );\n const voice = boundedOptionalString(value.voice, `${location}.voice`, filePath, MAX_TTS_VOICE_LENGTH);\n const rate = value.rate;\n if (\n rate !== undefined &&\n (typeof rate !== 'number' || !Number.isInteger(rate) || rate < MIN_TTS_RATE || rate > MAX_TTS_RATE)\n ) {\n throw new Error(\n `Doom config at ${filePath} requires ${location}.rate to be an integer from ${MIN_TTS_RATE} to ${MAX_TTS_RATE}`,\n );\n }\n return {\n engine: value.engine as VoiceTtsEngine,\n ...(voice ? { voice } : {}),\n ...(rate === undefined ? {} : { rate }),\n };\n}\nfunction parseAutoCapture(value: unknown, filePath: string): VoiceAutoCaptureConfig | undefined {\n if (value === undefined) return undefined;\n const location = 'voice.autoCapture';\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires ${location} to be an object`);\n assertKeys(value, AUTO_CAPTURE_KEYS, location, filePath);\n const startPhrases = parseControlPhrases(value.startPhrases, `${location}.startPhrases`, filePath);\n const stopPhrases = parseControlPhrases(value.stopPhrases, `${location}.stopPhrases`, filePath);\n const utteranceIdleMs = value.utteranceIdleMs;\n if (\n utteranceIdleMs !== undefined &&\n (typeof utteranceIdleMs !== 'number' ||\n !Number.isInteger(utteranceIdleMs) ||\n utteranceIdleMs < MIN_UTTERANCE_IDLE_MS ||\n utteranceIdleMs > MAX_UTTERANCE_IDLE_MS)\n ) {\n throw new Error(\n `Doom config at ${filePath} requires ${location}.utteranceIdleMs to be an integer from ${MIN_UTTERANCE_IDLE_MS} to ${MAX_UTTERANCE_IDLE_MS}`,\n );\n }\n const transcriptionTimeoutMs = value.transcriptionTimeoutMs;\n if (\n transcriptionTimeoutMs !== undefined &&\n (typeof transcriptionTimeoutMs !== 'number' ||\n !Number.isInteger(transcriptionTimeoutMs) ||\n transcriptionTimeoutMs < MIN_TRANSCRIPTION_TIMEOUT_MS ||\n transcriptionTimeoutMs > MAX_TRANSCRIPTION_TIMEOUT_MS)\n ) {\n throw new Error(\n `Doom config at ${filePath} requires ${location}.transcriptionTimeoutMs to be an integer from ${MIN_TRANSCRIPTION_TIMEOUT_MS} to ${MAX_TRANSCRIPTION_TIMEOUT_MS}`,\n );\n }\n const startKeys = new Set((startPhrases ?? []).map(normalizeControlPhrase));\n if ((stopPhrases ?? []).some((phrase) => startKeys.has(normalizeControlPhrase(phrase))))\n throw new Error(`Doom config at ${filePath} does not allow a phrase in both startPhrases and stopPhrases`);\n return {\n model: parseModelReference(value.model, filePath),\n ...(startPhrases ? { startPhrases } : {}),\n ...(stopPhrases ? { stopPhrases } : {}),\n ...(utteranceIdleMs === undefined ? {} : { utteranceIdleMs }),\n ...(transcriptionTimeoutMs === undefined ? {} : { transcriptionTimeoutMs }),\n tts: parseTtsConfig(value.tts, filePath),\n };\n}\nfunction parseAgent(value: unknown, location: string, filePath: string): PlanningAgentConfig | undefined {\n if (value === undefined) return undefined;\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires ${location} to be an object`);\n assertKeys(value, AGENT_KEYS, location, filePath);\n const thinking = value.thinking;\n if (\n thinking !== undefined &&\n (typeof thinking !== 'string' || !THINKING_VALUES.has(thinking as PlanningThinkingLevel))\n ) {\n throw new Error(\n `Doom config at ${filePath} requires ${location}.thinking to be one of: ${[...THINKING_VALUES].join(', ')}`,\n );\n }\n const model = optionalString(value.model, `${location}.model`, filePath);\n return { ...(model ? { model } : {}), ...(thinking ? { thinking: thinking as PlanningThinkingLevel } : {}) };\n}\nexport function parsePlanningModeConfig(\n value: unknown,\n filePath: string,\n location = 'modes.planning',\n): PlanningModeConfig {\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires ${location} to be an object`);\n assertKeys(value, PLANNING_KEYS, location, filePath);\n return {\n main: parseAgent(value.main, `${location}.main`, filePath),\n subagents: parseAgent(value.subagents, `${location}.subagents`, filePath),\n plansDirectory: optionalString(value.plansDirectory, `${location}.plansDirectory`, filePath),\n };\n}\nfunction parseModel(value: unknown, location: string, filePath: string, allowId: boolean): VoiceModelConfig {\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires ${location} to be an object`);\n assertKeys(value, MODEL_KEYS, location, filePath);\n const modelPath = optionalString(value.path, `${location}.path`, filePath);\n const id = optionalString(value.id, `${location}.id`, filePath);\n if (Boolean(modelPath) === Boolean(id))\n throw new Error(`Doom config at ${filePath} requires exactly one of ${location}.path or ${location}.id`);\n if (id && !allowId) throw new Error(`Doom config at ${filePath} does not support ${location}.id for whisper-cpp`);\n return { ...(modelPath ? { path: modelPath } : {}), ...(id ? { id } : {}) };\n}\nfunction parseAdapter(\n value: unknown,\n location: string,\n filePath: string,\n allowId: boolean,\n): VoiceAdapterConfig | undefined {\n if (value === undefined) return undefined;\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires ${location} to be an object`);\n assertKeys(value, ADAPTER_KEYS, location, filePath);\n const binary = optionalString(value.binary, `${location}.binary`, filePath);\n return { ...(binary ? { binary } : {}), model: parseModel(value.model, `${location}.model`, filePath, allowId) };\n}\nfunction parseVoice(value: unknown, filePath: string): VoiceConfig | undefined {\n if (value === undefined) return undefined;\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires voice to be an object`);\n assertKeys(value, VOICE_KEYS, 'voice', filePath);\n const result: VoiceConfig = {};\n if (value.engine !== undefined) {\n if (typeof value.engine !== 'string' || !ENGINE_VALUES.has(value.engine as VoiceEngine))\n throw new Error(\n `Doom config at ${filePath} requires voice.engine to be one of: ${[...ENGINE_VALUES].join(', ')}`,\n );\n result.engine = value.engine as VoiceEngine;\n }\n const language = optionalString(value.language, 'voice.language', filePath);\n if (language) result.language = language;\n if (value.recorder !== undefined) {\n if (!isObject(value.recorder))\n throw new Error(`Doom config at ${filePath} requires voice.recorder to be an object`);\n assertKeys(value.recorder, RECORDER_KEYS, 'voice.recorder', filePath);\n result.recorder = {};\n const binary = optionalString(value.recorder.binary, 'voice.recorder.binary', filePath);\n const device = optionalString(value.recorder.device, 'voice.recorder.device', filePath);\n if (binary) result.recorder.binary = binary;\n if (device) result.recorder.device = device;\n }\n if (value.adapters !== undefined) {\n if (!isObject(value.adapters))\n throw new Error(`Doom config at ${filePath} requires voice.adapters to be an object`);\n assertKeys(value.adapters, ADAPTERS_KEYS, 'voice.adapters', filePath);\n result.adapters = {\n [WHISPER_CPP_ENGINE]: parseAdapter(\n value.adapters[WHISPER_CPP_ENGINE],\n `voice.adapters.${WHISPER_CPP_ENGINE}`,\n filePath,\n false,\n ),\n [OPENAI_WHISPER_ENGINE]: parseAdapter(\n value.adapters[OPENAI_WHISPER_ENGINE],\n `voice.adapters.${OPENAI_WHISPER_ENGINE}`,\n filePath,\n true,\n ),\n [MLX_WHISPER_ENGINE]: parseAdapter(\n value.adapters[MLX_WHISPER_ENGINE],\n `voice.adapters.${MLX_WHISPER_ENGINE}`,\n filePath,\n true,\n ),\n };\n }\n const autoCapture = parseAutoCapture(value.autoCapture, filePath);\n if (autoCapture) result.autoCapture = autoCapture;\n return result;\n}\nfunction parseSelection(value: unknown, filePath: string): DoomSelectionConfig | undefined {\n if (value === undefined) return undefined;\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires selection to be an object`);\n assertKeys(value, SELECTION_KEYS, 'selection', filePath);\n const domains = value.domains;\n if (domains !== undefined && (!Array.isArray(domains) || domains.some((name) => typeof name !== 'string'))) {\n throw new Error(`Doom config at ${filePath} requires selection.domains to be an array of strings`);\n }\n return {\n majorMode: optionalString(value.majorMode, 'selection.majorMode', filePath),\n // An empty list is meaningful: it selects no content domains at all.\n domains: domains as string[] | undefined,\n profile: optionalString(value.profile, 'selection.profile', filePath),\n };\n}\nfunction parseEditor(value: unknown, filePath: string): EditorConfig | undefined {\n if (value === undefined) return undefined;\n if (!isObject(value)) throw new Error(`Doom config at ${filePath} requires editor to be an object`);\n assertKeys(value, EDITOR_KEYS, 'editor', filePath);\n return { command: optionalString(value.command, 'editor.command', filePath) };\n}\nexport function parseDoomConfig(content: string, filePath: string): DoomConfig {\n let parsed: unknown;\n try {\n parsed = parseYaml(content) ?? {};\n } catch (error) {\n throw new Error(`Could not parse Doom config at ${filePath}`, { cause: error });\n }\n if (!isObject(parsed)) throw new Error(`Doom config at ${filePath} must be a YAML object`);\n assertKeys(parsed, ROOT_KEYS, 'root', filePath);\n let modes: DoomConfig['modes'];\n if (parsed.modes !== undefined) {\n if (!isObject(parsed.modes)) throw new Error(`Doom config at ${filePath} requires modes to be an object`);\n assertKeys(parsed.modes, MODE_KEYS, 'modes', filePath);\n modes =\n parsed.modes.planning === undefined ? {} : { planning: parsePlanningModeConfig(parsed.modes.planning, filePath) };\n }\n const trust = parsed.projectTrust === undefined ? DEFAULT_PROJECT_TRUST : parsed.projectTrust;\n if (typeof trust !== 'string' || !TRUST_VALUES.has(trust as ProjectTrust))\n throw new Error(`Doom config at ${filePath} projectTrust must be ask, always, or never`);\n return {\n modes,\n projectTrust: trust as ProjectTrust,\n editor: parseEditor(parsed.editor, filePath),\n voice: parseVoice(parsed.voice, filePath),\n selection: parseSelection(parsed.selection, filePath),\n };\n}\nfunction mergeAgent(\n globalValue?: PlanningAgentConfig,\n repositoryValue?: PlanningAgentConfig,\n): PlanningAgentConfig | undefined {\n return globalValue || repositoryValue ? { ...globalValue, ...repositoryValue } : undefined;\n}\nexport function mergeDoomConfigs(globalConfig: DoomConfig, repositoryConfig: DoomConfig): DoomConfig {\n if (repositoryConfig.voice?.autoCapture)\n throw new Error('Repository Doom config voice.autoCapture is global-only; configure it in ~/.pi/.doom/config.yaml');\n const globalPlanning = globalConfig.modes?.planning;\n const repositoryPlanning = repositoryConfig.modes?.planning;\n const planning =\n globalPlanning || repositoryPlanning\n ? {\n main: mergeAgent(globalPlanning?.main, repositoryPlanning?.main),\n subagents: mergeAgent(globalPlanning?.subagents, repositoryPlanning?.subagents),\n plansDirectory: repositoryPlanning?.plansDirectory ?? globalPlanning?.plansDirectory,\n }\n : undefined;\n const voice = mergeVoice(globalConfig.voice, repositoryConfig.voice);\n return {\n modes: planning ? { planning } : undefined,\n projectTrust: repositoryConfig.projectTrust,\n editor: globalConfig.editor,\n voice,\n // Per key, so a repository can pin one axis and inherit the rest.\n selection:\n globalConfig.selection || repositoryConfig.selection\n ? { ...globalConfig.selection, ...repositoryConfig.selection }\n : undefined,\n };\n}\nfunction mergeAdapter(\n globalValue?: VoiceAdapterConfig,\n repositoryValue?: VoiceAdapterConfig,\n): VoiceAdapterConfig | undefined {\n if (!globalValue && !repositoryValue) return undefined;\n return { ...globalValue, ...repositoryValue, model: repositoryValue?.model ?? globalValue!.model };\n}\nfunction mergeVoice(globalValue?: VoiceConfig, repositoryValue?: VoiceConfig): VoiceConfig | undefined {\n if (!globalValue && !repositoryValue) return undefined;\n return {\n ...globalValue,\n ...repositoryValue,\n recorder:\n globalValue?.recorder || repositoryValue?.recorder\n ? { ...globalValue?.recorder, ...repositoryValue?.recorder }\n : undefined,\n adapters:\n globalValue?.adapters || repositoryValue?.adapters\n ? {\n [WHISPER_CPP_ENGINE]: mergeAdapter(\n globalValue?.adapters?.[WHISPER_CPP_ENGINE],\n repositoryValue?.adapters?.[WHISPER_CPP_ENGINE],\n ),\n [OPENAI_WHISPER_ENGINE]: mergeAdapter(\n globalValue?.adapters?.[OPENAI_WHISPER_ENGINE],\n repositoryValue?.adapters?.[OPENAI_WHISPER_ENGINE],\n ),\n [MLX_WHISPER_ENGINE]: mergeAdapter(\n globalValue?.adapters?.[MLX_WHISPER_ENGINE],\n repositoryValue?.adapters?.[MLX_WHISPER_ENGINE],\n ),\n }\n : undefined,\n ...(globalValue?.autoCapture ? { autoCapture: globalValue.autoCapture } : {}),\n };\n}\nexport function resolveVoiceConfig(config: VoiceConfig): ResolvedVoiceConfig {\n return {\n engine: config.engine ?? DEFAULT_VOICE_ENGINE,\n language: config.language ?? DEFAULT_VOICE_LANGUAGE,\n recorder: { ...config.recorder, device: config.recorder?.device ?? DEFAULT_RECORDER_DEVICE },\n adapters: config.adapters ?? {},\n ...(config.autoCapture\n ? {\n autoCapture: {\n ...config.autoCapture,\n startPhrases: [...(config.autoCapture.startPhrases ?? [])],\n stopPhrases: [...(config.autoCapture.stopPhrases ?? [])],\n utteranceIdleMs: config.autoCapture.utteranceIdleMs ?? DEFAULT_UTTERANCE_IDLE_MS,\n transcriptionTimeoutMs: config.autoCapture.transcriptionTimeoutMs ?? DEFAULT_TRANSCRIPTION_TIMEOUT_MS,\n tts: { ...config.autoCapture.tts },\n },\n }\n : {}),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { DoomConfig, PlanningModeConfig, ResolvedVoiceConfig, VoiceConfig } from "../types/config.cjs";
2
+ //#region src/services/configPolicy.d.ts
3
+ /**
4
+ * The accepted values, in the order a picker should offer them.
5
+ *
6
+ * Exported because the config UI has to offer exactly what the parser accepts,
7
+ * and a second hand-written list in the contributing package would drift. The
8
+ * validating Sets below are built from these for the same reason.
9
+ */
10
+ declare const DOOM_PLANNING_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
11
+ declare const DOOM_VOICE_ENGINES: readonly ["auto", "whisper-cpp", "openai-whisper", "mlx-whisper"];
12
+ declare const DOOM_VOICE_TTS_ENGINES: readonly ["macos-say"];
13
+ declare function parsePlanningModeConfig(value: unknown, filePath: string, location?: string): PlanningModeConfig;
14
+ declare function parseDoomConfig(content: string, filePath: string): DoomConfig;
15
+ declare function mergeDoomConfigs(globalConfig: DoomConfig, repositoryConfig: DoomConfig): DoomConfig;
16
+ declare function resolveVoiceConfig(config: VoiceConfig): ResolvedVoiceConfig;
17
+ //#endregion
18
+ export { DOOM_PLANNING_THINKING_LEVELS, DOOM_VOICE_ENGINES, DOOM_VOICE_TTS_ENGINES, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, resolveVoiceConfig };
19
+ //# sourceMappingURL=configPolicy.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configPolicy.d.cts","names":[],"sources":["../../src/services/configPolicy.ts"],"mappings":";;;;;;;;;cAmEa;cACA;cAMA;iBAwKG,wBACd,gBACA,kBACA,oBACC;iBAyGa,gBAAgB,iBAAiB,mBAAmB;iBAiCpD,iBAAiB,cAAc,YAAY,kBAAkB,aAAa;iBA8D1E,mBAAmB,QAAQ,cAAc"}
@@ -0,0 +1,19 @@
1
+ import { DoomConfig, PlanningModeConfig, ResolvedVoiceConfig, VoiceConfig } from "../types/config.mjs";
2
+ //#region src/services/configPolicy.d.ts
3
+ /**
4
+ * The accepted values, in the order a picker should offer them.
5
+ *
6
+ * Exported because the config UI has to offer exactly what the parser accepts,
7
+ * and a second hand-written list in the contributing package would drift. The
8
+ * validating Sets below are built from these for the same reason.
9
+ */
10
+ declare const DOOM_PLANNING_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
11
+ declare const DOOM_VOICE_ENGINES: readonly ["auto", "whisper-cpp", "openai-whisper", "mlx-whisper"];
12
+ declare const DOOM_VOICE_TTS_ENGINES: readonly ["macos-say"];
13
+ declare function parsePlanningModeConfig(value: unknown, filePath: string, location?: string): PlanningModeConfig;
14
+ declare function parseDoomConfig(content: string, filePath: string): DoomConfig;
15
+ declare function mergeDoomConfigs(globalConfig: DoomConfig, repositoryConfig: DoomConfig): DoomConfig;
16
+ declare function resolveVoiceConfig(config: VoiceConfig): ResolvedVoiceConfig;
17
+ //#endregion
18
+ export { DOOM_PLANNING_THINKING_LEVELS, DOOM_VOICE_ENGINES, DOOM_VOICE_TTS_ENGINES, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, resolveVoiceConfig };
19
+ //# sourceMappingURL=configPolicy.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configPolicy.d.mts","names":[],"sources":["../../src/services/configPolicy.ts"],"mappings":";;;;;;;;;cAmEa;cACA;cAMA;iBAwKG,wBACd,gBACA,kBACA,oBACC;iBAyGa,gBAAgB,iBAAiB,mBAAmB;iBAiCpD,iBAAiB,cAAc,YAAY,kBAAkB,aAAa;iBA8D1E,mBAAmB,QAAQ,cAAc"}
@@ -0,0 +1,2 @@
1
+ import{parse as e}from"yaml";const t=`auto`,n=[`modes`,`projectTrust`,`editor`,`voice`,`selection`],r=[`majorMode`,`domains`,`profile`],i=[`planning`],a=[`main`,`subagents`,`plansDirectory`],o=[`model`,`thinking`],s=[`command`],c=[`engine`,`language`,`recorder`,`adapters`,`autoCapture`],l=[`binary`,`device`],u=`whisper-cpp`,d=`openai-whisper`,f=`mlx-whisper`,p=[u,d,f],m=[`binary`,`model`],h=[`path`,`id`],g=[`model`,`startPhrases`,`stopPhrases`,`utteranceIdleMs`,`transcriptionTimeoutMs`,`tts`],_=[`engine`,`voice`,`rate`],v=1500,y=1e4,b=1e3,x=12e4,S=/^[^/\s]+\/[^/\s]+(?:\/[^/\s]+)*$/u,C=/[\p{P}\p{S}]+/gu,w=[`off`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`],T=[t,u,d,f],E=[`macos-say`],D=new Set(w),O=new Set([`ask`,`always`,`never`]),k=new Set(T),A=new Set(E);function j(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function M(e,t,n,r){let i=Object.keys(e).filter(e=>!t.includes(e));if(i.length>0)throw Error(`Doom config at ${r} has unsupported ${n} field(s): ${i.join(`, `)}`)}function N(e,t,n){if(e!==void 0){if(typeof e!=`string`||e.trim().length===0)throw Error(`Doom config at ${n} requires ${t} to be a non-empty string`);return e.trim()}}function P(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&(e<=31||e===127))return!0}return!1}function F(e,t,n,r){let i=N(e,t,n);if(i){if(i.length>r)throw Error(`Doom config at ${n} requires ${t} to be at most ${r} characters`);if(P(i))throw Error(`Doom config at ${n} does not allow control characters in ${t}`);return i}}function I(e,t){let n=`voice.autoCapture.model`,r=N(e,n,t);if(!r||!S.test(r))throw Error(`Doom config at ${t} requires ${n} in provider/model-id form`);return r}function L(e){return e.normalize(`NFKC`).toLocaleLowerCase(`en-US`).replace(C,` `).replace(/\s+/gu,` `).trim()}function R(e,t,n){if(e===void 0)return;if(!Array.isArray(e)||e.some(e=>typeof e!=`string`))throw Error(`Doom config at ${n} requires ${t} to be an array of strings`);if(e.length>16)throw Error(`Doom config at ${n} requires ${t} to contain at most 16 phrases`);let r=e.map(e=>e.trim()),i=new Set;for(let e of r){if(e.length===0)throw Error(`Doom config at ${n} requires ${t} to contain non-empty strings`);if(e.length>64)throw Error(`Doom config at ${n} requires ${t} phrases to be at most 64 characters`);if(P(e))throw Error(`Doom config at ${n} does not allow control characters in ${t}`);let r=L(e);if(!r)throw Error(`Doom config at ${n} requires ${t} to contain words`);if(i.has(r))throw Error(`Doom config at ${n} does not allow normalized duplicates in ${t}`);i.add(r)}return r}function z(e,t){let n=`voice.autoCapture.tts`;if(!j(e))throw Error(`Doom config at ${t} requires ${n} to be an object`);if(M(e,_,n,t),typeof e.engine!=`string`||!A.has(e.engine))throw Error(`Doom config at ${t} requires ${n}.engine to be one of: ${[...A].join(`, `)}`);let r=F(e.voice,`${n}.voice`,t,64),i=e.rate;if(i!==void 0&&(typeof i!=`number`||!Number.isInteger(i)||i<80||i>500))throw Error(`Doom config at ${t} requires ${n}.rate to be an integer from 80 to 500`);return{engine:e.engine,...r?{voice:r}:{},...i===void 0?{}:{rate:i}}}function B(e,t){if(e===void 0)return;let n=`voice.autoCapture`;if(!j(e))throw Error(`Doom config at ${t} requires ${n} to be an object`);M(e,g,n,t);let r=R(e.startPhrases,`${n}.startPhrases`,t),i=R(e.stopPhrases,`${n}.stopPhrases`,t),a=e.utteranceIdleMs;if(a!==void 0&&(typeof a!=`number`||!Number.isInteger(a)||a<v||a>y))throw Error(`Doom config at ${t} requires ${n}.utteranceIdleMs to be an integer from ${v} to ${y}`);let o=e.transcriptionTimeoutMs;if(o!==void 0&&(typeof o!=`number`||!Number.isInteger(o)||o<b||o>x))throw Error(`Doom config at ${t} requires ${n}.transcriptionTimeoutMs to be an integer from ${b} to ${x}`);let s=new Set((r??[]).map(L));if((i??[]).some(e=>s.has(L(e))))throw Error(`Doom config at ${t} does not allow a phrase in both startPhrases and stopPhrases`);return{model:I(e.model,t),...r?{startPhrases:r}:{},...i?{stopPhrases:i}:{},...a===void 0?{}:{utteranceIdleMs:a},...o===void 0?{}:{transcriptionTimeoutMs:o},tts:z(e.tts,t)}}function V(e,t,n){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${n} requires ${t} to be an object`);M(e,o,t,n);let r=e.thinking;if(r!==void 0&&(typeof r!=`string`||!D.has(r)))throw Error(`Doom config at ${n} requires ${t}.thinking to be one of: ${[...D].join(`, `)}`);let i=N(e.model,`${t}.model`,n);return{...i?{model:i}:{},...r?{thinking:r}:{}}}function H(e,t,n=`modes.planning`){if(!j(e))throw Error(`Doom config at ${t} requires ${n} to be an object`);return M(e,a,n,t),{main:V(e.main,`${n}.main`,t),subagents:V(e.subagents,`${n}.subagents`,t),plansDirectory:N(e.plansDirectory,`${n}.plansDirectory`,t)}}function U(e,t,n,r){if(!j(e))throw Error(`Doom config at ${n} requires ${t} to be an object`);M(e,h,t,n);let i=N(e.path,`${t}.path`,n),a=N(e.id,`${t}.id`,n);if(!!i==!!a)throw Error(`Doom config at ${n} requires exactly one of ${t}.path or ${t}.id`);if(a&&!r)throw Error(`Doom config at ${n} does not support ${t}.id for whisper-cpp`);return{...i?{path:i}:{},...a?{id:a}:{}}}function W(e,t,n,r){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${n} requires ${t} to be an object`);M(e,m,t,n);let i=N(e.binary,`${t}.binary`,n);return{...i?{binary:i}:{},model:U(e.model,`${t}.model`,n,r)}}function G(e,t){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${t} requires voice to be an object`);M(e,c,`voice`,t);let n={};if(e.engine!==void 0){if(typeof e.engine!=`string`||!k.has(e.engine))throw Error(`Doom config at ${t} requires voice.engine to be one of: ${[...k].join(`, `)}`);n.engine=e.engine}let r=N(e.language,`voice.language`,t);if(r&&(n.language=r),e.recorder!==void 0){if(!j(e.recorder))throw Error(`Doom config at ${t} requires voice.recorder to be an object`);M(e.recorder,l,`voice.recorder`,t),n.recorder={};let r=N(e.recorder.binary,`voice.recorder.binary`,t),i=N(e.recorder.device,`voice.recorder.device`,t);r&&(n.recorder.binary=r),i&&(n.recorder.device=i)}if(e.adapters!==void 0){if(!j(e.adapters))throw Error(`Doom config at ${t} requires voice.adapters to be an object`);M(e.adapters,p,`voice.adapters`,t),n.adapters={[u]:W(e.adapters[u],`voice.adapters.${u}`,t,!1),[d]:W(e.adapters[d],`voice.adapters.${d}`,t,!0),[f]:W(e.adapters[f],`voice.adapters.${f}`,t,!0)}}let i=B(e.autoCapture,t);return i&&(n.autoCapture=i),n}function K(e,t){if(e===void 0)return;if(!j(e))throw Error(`Doom config at ${t} requires selection to be an object`);M(e,r,`selection`,t);let n=e.domains;if(n!==void 0&&(!Array.isArray(n)||n.some(e=>typeof e!=`string`)))throw Error(`Doom config at ${t} requires selection.domains to be an array of strings`);return{majorMode:N(e.majorMode,`selection.majorMode`,t),domains:n,profile:N(e.profile,`selection.profile`,t)}}function q(e,t){if(e!==void 0){if(!j(e))throw Error(`Doom config at ${t} requires editor to be an object`);return M(e,s,`editor`,t),{command:N(e.command,`editor.command`,t)}}}function J(t,r){let a;try{a=e(t)??{}}catch(e){throw Error(`Could not parse Doom config at ${r}`,{cause:e})}if(!j(a))throw Error(`Doom config at ${r} must be a YAML object`);M(a,n,`root`,r);let o;if(a.modes!==void 0){if(!j(a.modes))throw Error(`Doom config at ${r} requires modes to be an object`);M(a.modes,i,`modes`,r),o=a.modes.planning===void 0?{}:{planning:H(a.modes.planning,r)}}let s=a.projectTrust===void 0?`ask`:a.projectTrust;if(typeof s!=`string`||!O.has(s))throw Error(`Doom config at ${r} projectTrust must be ask, always, or never`);return{modes:o,projectTrust:s,editor:q(a.editor,r),voice:G(a.voice,r),selection:K(a.selection,r)}}function Y(e,t){return e||t?{...e,...t}:void 0}function X(e,t){if(t.voice?.autoCapture)throw Error(`Repository Doom config voice.autoCapture is global-only; configure it in ~/.pi/.doom/config.yaml`);let n=e.modes?.planning,r=t.modes?.planning,i=n||r?{main:Y(n?.main,r?.main),subagents:Y(n?.subagents,r?.subagents),plansDirectory:r?.plansDirectory??n?.plansDirectory}:void 0,a=Q(e.voice,t.voice);return{modes:i?{planning:i}:void 0,projectTrust:t.projectTrust,editor:e.editor,voice:a,selection:e.selection||t.selection?{...e.selection,...t.selection}:void 0}}function Z(e,t){if(!(!e&&!t))return{...e,...t,model:t?.model??e.model}}function Q(e,t){if(!(!e&&!t))return{...e,...t,recorder:e?.recorder||t?.recorder?{...e?.recorder,...t?.recorder}:void 0,adapters:e?.adapters||t?.adapters?{[u]:Z(e?.adapters?.[u],t?.adapters?.[u]),[d]:Z(e?.adapters?.[d],t?.adapters?.[d]),[f]:Z(e?.adapters?.[f],t?.adapters?.[f])}:void 0,...e?.autoCapture?{autoCapture:e.autoCapture}:{}}}function $(e){return{engine:e.engine??t,language:e.language??`auto`,recorder:{...e.recorder,device:e.recorder?.device??`none:default`},adapters:e.adapters??{},...e.autoCapture?{autoCapture:{...e.autoCapture,startPhrases:[...e.autoCapture.startPhrases??[]],stopPhrases:[...e.autoCapture.stopPhrases??[]],utteranceIdleMs:e.autoCapture.utteranceIdleMs??3e3,transcriptionTimeoutMs:e.autoCapture.transcriptionTimeoutMs??15e3,tts:{...e.autoCapture.tts}}}:{}}}export{w as DOOM_PLANNING_THINKING_LEVELS,T as DOOM_VOICE_ENGINES,E as DOOM_VOICE_TTS_ENGINES,X as mergeDoomConfigs,J as parseDoomConfig,H as parsePlanningModeConfig,$ as resolveVoiceConfig};
2
+ //# sourceMappingURL=configPolicy.mjs.map