@agimon-ai/doompi-config 0.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +36 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs +1 -0
- package/dist/_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs +1 -0
- package/dist/_virtual/_rolldown/runtime.cjs +1 -0
- package/dist/atomicJson.cjs +2 -0
- package/dist/atomicJson.cjs.map +1 -0
- package/dist/atomicJson.d.cts +6 -0
- package/dist/atomicJson.d.cts.map +1 -0
- package/dist/atomicJson.d.mts +6 -0
- package/dist/atomicJson.d.mts.map +1 -0
- package/dist/atomicJson.mjs +2 -0
- package/dist/atomicJson.mjs.map +1 -0
- package/dist/config/piConfig.cjs +2 -0
- package/dist/config/piConfig.cjs.map +1 -0
- package/dist/config/piConfig.d.cts +7 -0
- package/dist/config/piConfig.d.cts.map +1 -0
- package/dist/config/piConfig.d.mts +7 -0
- package/dist/config/piConfig.d.mts.map +1 -0
- package/dist/config/piConfig.mjs +2 -0
- package/dist/config/piConfig.mjs.map +1 -0
- package/dist/config/schema.cjs +0 -0
- package/dist/config/schema.d.cts +33 -0
- package/dist/config/schema.d.cts.map +1 -0
- package/dist/config/schema.d.mts +33 -0
- package/dist/config/schema.d.mts.map +1 -0
- package/dist/config/schema.mjs +1 -0
- package/dist/config.cjs +2 -0
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.cts +24 -0
- package/dist/config.d.cts.map +1 -0
- package/dist/config.d.mts +24 -0
- package/dist/config.d.mts.map +1 -0
- package/dist/config.mjs +2 -0
- package/dist/config.mjs.map +1 -0
- package/dist/configWriter.cjs +2 -0
- package/dist/configWriter.cjs.map +1 -0
- package/dist/configWriter.d.cts +52 -0
- package/dist/configWriter.d.cts.map +1 -0
- package/dist/configWriter.d.mts +52 -0
- package/dist/configWriter.d.mts.map +1 -0
- package/dist/configWriter.mjs +2 -0
- package/dist/configWriter.mjs.map +1 -0
- package/dist/container.cjs +2 -0
- package/dist/container.cjs.map +1 -0
- package/dist/container.d.cts +12 -0
- package/dist/container.d.cts.map +1 -0
- package/dist/container.d.mts +12 -0
- package/dist/container.d.mts.map +1 -0
- package/dist/container.mjs +2 -0
- package/dist/container.mjs.map +1 -0
- package/dist/domains.cjs +2 -0
- package/dist/domains.cjs.map +1 -0
- package/dist/domains.d.cts +75 -0
- package/dist/domains.d.cts.map +1 -0
- package/dist/domains.d.mts +75 -0
- package/dist/domains.d.mts.map +1 -0
- package/dist/domains.mjs +2 -0
- package/dist/domains.mjs.map +1 -0
- package/dist/extensions/doom.cjs +2 -0
- package/dist/extensions/doom.cjs.map +1 -0
- package/dist/extensions/doom.d.cts +8 -0
- package/dist/extensions/doom.d.cts.map +1 -0
- package/dist/extensions/doom.d.mts +8 -0
- package/dist/extensions/doom.d.mts.map +1 -0
- package/dist/extensions/doom.mjs +2 -0
- package/dist/extensions/doom.mjs.map +1 -0
- package/dist/extensions/pi.cjs +2 -0
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.cts +8 -0
- package/dist/extensions/pi.d.cts.map +1 -0
- package/dist/extensions/pi.d.mts +8 -0
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +2 -0
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/harnessState.cjs +2 -0
- package/dist/harnessState.cjs.map +1 -0
- package/dist/harnessState.d.cts +50 -0
- package/dist/harnessState.d.cts.map +1 -0
- package/dist/harnessState.d.mts +50 -0
- package/dist/harnessState.d.mts.map +1 -0
- package/dist/harnessState.mjs +2 -0
- package/dist/harnessState.mjs.map +1 -0
- package/dist/harnessStore.cjs +2 -0
- package/dist/harnessStore.cjs.map +1 -0
- package/dist/harnessStore.d.cts +102 -0
- package/dist/harnessStore.d.cts.map +1 -0
- package/dist/harnessStore.d.mts +102 -0
- package/dist/harnessStore.d.mts.map +1 -0
- package/dist/harnessStore.mjs +2 -0
- package/dist/harnessStore.mjs.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.mjs +1 -0
- package/dist/init.cjs +73 -0
- package/dist/init.cjs.map +1 -0
- package/dist/init.d.cts +33 -0
- package/dist/init.d.cts.map +1 -0
- package/dist/init.d.mts +33 -0
- package/dist/init.d.mts.map +1 -0
- package/dist/init.mjs +73 -0
- package/dist/init.mjs.map +1 -0
- package/dist/layeredConfig.cjs +2 -0
- package/dist/layeredConfig.cjs.map +1 -0
- package/dist/layeredConfig.d.cts +49 -0
- package/dist/layeredConfig.d.cts.map +1 -0
- package/dist/layeredConfig.d.mts +49 -0
- package/dist/layeredConfig.d.mts.map +1 -0
- package/dist/layeredConfig.mjs +2 -0
- package/dist/layeredConfig.mjs.map +1 -0
- package/dist/majorModes.cjs +2 -0
- package/dist/majorModes.cjs.map +1 -0
- package/dist/majorModes.d.cts +73 -0
- package/dist/majorModes.d.cts.map +1 -0
- package/dist/majorModes.d.mts +73 -0
- package/dist/majorModes.d.mts.map +1 -0
- package/dist/majorModes.mjs +2 -0
- package/dist/majorModes.mjs.map +1 -0
- package/dist/pi.cjs +1 -0
- package/dist/pi.d.cts +2 -0
- package/dist/pi.d.mts +2 -0
- package/dist/pi.mjs +1 -0
- package/dist/piContext.cjs +2 -0
- package/dist/piContext.cjs.map +1 -0
- package/dist/piContext.d.cts +19 -0
- package/dist/piContext.d.cts.map +1 -0
- package/dist/piContext.d.mts +19 -0
- package/dist/piContext.d.mts.map +1 -0
- package/dist/piContext.mjs +2 -0
- package/dist/piContext.mjs.map +1 -0
- package/dist/profiles.cjs +4 -0
- package/dist/profiles.cjs.map +1 -0
- package/dist/profiles.d.cts +35 -0
- package/dist/profiles.d.cts.map +1 -0
- package/dist/profiles.d.mts +35 -0
- package/dist/profiles.d.mts.map +1 -0
- package/dist/profiles.mjs +4 -0
- package/dist/profiles.mjs.map +1 -0
- package/dist/types.cjs +2 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +132 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +132 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +150 -0
- package/skills/doom-pi-config/SKILL.md +26 -0
- package/skills/doom-pi-config/agents/openai.yaml +4 -0
- package/skills/doom-pi-config/references/config-contract.md +43 -0
package/dist/pi.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("./piContext.cjs");module.exports=e.doomConfigExtension;
|
package/dist/pi.d.cts
ADDED
package/dist/pi.d.mts
ADDED
package/dist/pi.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{doomConfigExtension as e}from"./piContext.mjs";export{e as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piContext.cjs","names":["getHarnessState","loadDoomConfig","createDoomTelemetry"],"sources":["../src/piContext.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext, ExtensionFactory, SessionEntry } from '@earendil-works/pi-coding-agent';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { loadDoomConfig } from './config.ts';\nimport { getHarnessState } from './harnessStore.ts';\nimport type { DeepReadonly, DoomConfigContext, HarnessState } from './types.ts';\n\nexport const DOOM_CONFIG_ENTRY_TYPE = 'doom-pi:config:v1';\n\nexport interface DoomConfigSelection {\n readonly version: 1;\n readonly majorMode: string;\n readonly domains: readonly string[];\n readonly profile?: string;\n}\n\ninterface ConfigBinding {\n readonly context: DoomConfigContext;\n readonly generation: symbol;\n}\n\nconst configBindings = new WeakMap<ExtensionContext['sessionManager'], ConfigBinding>();\n\nfunction isSelection(value: unknown): value is DoomConfigSelection {\n if (typeof value !== 'object' || value === null) return false;\n const selection = value as Partial<DoomConfigSelection>;\n return (\n selection.version === 1 &&\n typeof selection.majorMode === 'string' &&\n Array.isArray(selection.domains) &&\n selection.domains.every((domain) => typeof domain === 'string') &&\n (selection.profile === undefined || typeof selection.profile === 'string')\n );\n}\n\nfunction branchSelection(entries: readonly SessionEntry[]): DoomConfigSelection | undefined {\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index];\n if (entry?.type === 'custom' && entry.customType === DOOM_CONFIG_ENTRY_TYPE && isSelection(entry.data)) {\n return entry.data;\n }\n }\n return undefined;\n}\n\nfunction deepFreeze<TValue>(value: TValue): DeepReadonly<TValue> {\n if (typeof value !== 'object' || value === null || Object.isFrozen(value)) {\n return value as DeepReadonly<TValue>;\n }\n for (const child of Object.values(value)) deepFreeze(child);\n return Object.freeze(value) as DeepReadonly<TValue>;\n}\n\nexport function readDoomConfigSelection(\n ctx: Pick<ExtensionContext, 'sessionManager'>,\n): DoomConfigSelection | undefined {\n return branchSelection(ctx.sessionManager.getBranch());\n}\n\nexport function createDoomConfigContext(ctx: Pick<ExtensionContext, 'cwd' | 'sessionManager'>): DoomConfigContext {\n const bootstrap = getHarnessState();\n const selection = readDoomConfigSelection(ctx);\n const harness: HarnessState = selection\n ? { ...bootstrap, majorMode: selection.majorMode, domains: [...selection.domains], profile: selection.profile }\n : bootstrap;\n const requiresRelaunch = Boolean(\n selection &&\n (selection.majorMode !== bootstrap.majorMode ||\n selection.profile !== bootstrap.profile ||\n selection.domains.join(',') !== bootstrap.domains.join(',')),\n );\n return deepFreeze({ settings: loadDoomConfig(bootstrap.root ?? ctx.cwd), harness, requiresRelaunch });\n}\n\nexport function appendDoomConfigSelection(pi: Pick<ExtensionAPI, 'appendEntry'>, selection: DoomConfigSelection): void {\n pi.appendEntry(DOOM_CONFIG_ENTRY_TYPE, selection);\n}\n\nexport function provideDoomConfigContext(\n ctx: Pick<ExtensionContext, 'sessionManager'>,\n context: DoomConfigContext,\n): () => void {\n const binding = { context, generation: Symbol('doom-config-context') };\n configBindings.set(ctx.sessionManager, binding);\n return () => {\n if (configBindings.get(ctx.sessionManager)?.generation === binding.generation) {\n configBindings.delete(ctx.sessionManager);\n }\n };\n}\n\nexport function requireDoomConfigContext(ctx: Pick<ExtensionContext, 'sessionManager'>): DoomConfigContext {\n const binding = configBindings.get(ctx.sessionManager);\n if (!binding) throw new Error('Doom config context is unavailable. Load @agimon-ai/doompi-config/pi.');\n return binding.context;\n}\n\nexport const doomConfigExtension: ExtensionFactory = (pi) => {\n let dispose: (() => void) | undefined;\n let telemetry: DoomTelemetry | undefined;\n pi.on('session_start', async (_event, ctx) => {\n dispose?.();\n const context = createDoomConfigContext(ctx);\n dispose = provideDoomConfigContext(ctx, context);\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-config',\n packageName: '@agimon-ai/doompi-config',\n cwd: ctx.cwd,\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n await telemetry.recordEvent('doom_config.context_bound', {\n 'config.major_mode': context.harness.majorMode,\n 'config.domain_count': context.harness.domains.length,\n 'config.has_profile': context.harness.profile !== undefined,\n 'config.requires_relaunch': context.requiresRelaunch,\n });\n });\n pi.on('session_shutdown', async () => {\n // Other extensions consume config during shutdown. Keep the WeakMap entry\n // alive for that phase and let it disappear with Pi's sessionManager.\n dispose = undefined;\n await telemetry?.shutdown();\n telemetry = undefined;\n });\n};\n"],"mappings":"gLAMA,MAAa,EAAyB,oBAchC,EAAiB,IAAI,QAE3B,SAAS,EAAY,EAA8C,CACjE,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,IAAM,EAAY,EAClB,OACE,EAAU,UAAY,GACtB,OAAO,EAAU,WAAc,UAC/B,MAAM,QAAQ,EAAU,OAAO,GAC/B,EAAU,QAAQ,MAAO,GAAW,OAAO,GAAW,QAAQ,IAC7D,EAAU,UAAY,IAAA,IAAa,OAAO,EAAU,SAAY,SAErE,CAEA,SAAS,EAAgB,EAAmE,CAC1F,IAAK,IAAI,EAAQ,EAAQ,OAAS,EAAG,GAAS,EAAG,IAAY,CAC3D,IAAM,EAAQ,EAAQ,GACtB,GAAI,GAAO,OAAS,UAAY,EAAM,aAAA,qBAAyC,EAAY,EAAM,IAAI,EACnG,OAAO,EAAM,IAEjB,CAEF,CAEA,SAAS,EAAmB,EAAqC,CAC/D,GAAI,OAAO,GAAU,WAAY,GAAkB,OAAO,SAAS,CAAK,EACtE,OAAO,EAET,IAAK,IAAM,KAAS,OAAO,OAAO,CAAK,EAAG,EAAW,CAAK,EAC1D,OAAO,OAAO,OAAO,CAAK,CAC5B,CAEA,SAAgB,EACd,EACiC,CACjC,OAAO,EAAgB,EAAI,eAAe,UAAU,CAAC,CACvD,CAEA,SAAgB,EAAwB,EAA0E,CAChH,IAAM,EAAYA,EAAAA,gBAAgB,EAC5B,EAAY,EAAwB,CAAG,EACvC,EAAwB,EAC1B,CAAE,GAAG,EAAW,UAAW,EAAU,UAAW,QAAS,CAAC,GAAG,EAAU,OAAO,EAAG,QAAS,EAAU,OAAQ,EAC5G,EACE,EAAmB,GACvB,IACC,EAAU,YAAc,EAAU,WACjC,EAAU,UAAY,EAAU,SAChC,EAAU,QAAQ,KAAK,GAAG,IAAM,EAAU,QAAQ,KAAK,GAAG,IAE9D,OAAO,EAAW,CAAE,SAAUC,EAAAA,eAAe,EAAU,MAAQ,EAAI,GAAG,EAAG,UAAS,kBAAiB,CAAC,CACtG,CAEA,SAAgB,EAA0B,EAAuC,EAAsC,CACrH,EAAG,YAAY,EAAwB,CAAS,CAClD,CAEA,SAAgB,EACd,EACA,EACY,CACZ,IAAM,EAAU,CAAE,UAAS,WAAY,OAAO,qBAAqB,CAAE,EAErE,OADA,EAAe,IAAI,EAAI,eAAgB,CAAO,MACjC,CACP,EAAe,IAAI,EAAI,cAAc,CAAC,EAAE,aAAe,EAAQ,YACjE,EAAe,OAAO,EAAI,cAAc,CAE5C,CACF,CAEA,SAAgB,EAAyB,EAAkE,CACzG,IAAM,EAAU,EAAe,IAAI,EAAI,cAAc,EACrD,GAAI,CAAC,EAAS,MAAU,MAAM,uEAAuE,EACrG,OAAO,EAAQ,OACjB,CAEA,MAAa,EAAyC,GAAO,CAC3D,IAAI,EACA,EACJ,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAAQ,CAC5C,IAAU,EACV,IAAM,EAAU,EAAwB,CAAG,EAC3C,EAAU,EAAyB,EAAK,CAAO,EAC/C,KAAA,EAAcC,EAAAA,oBAAAA,CAAoB,CAChC,YAAa,cACb,YAAa,2BACb,IAAK,EAAI,IACT,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACD,MAAM,EAAU,YAAY,4BAA6B,CACvD,oBAAqB,EAAQ,QAAQ,UACrC,sBAAuB,EAAQ,QAAQ,QAAQ,OAC/C,qBAAsB,EAAQ,QAAQ,UAAY,IAAA,GAClD,2BAA4B,EAAQ,gBACtC,CAAC,CACH,CAAC,EACD,EAAG,GAAG,mBAAoB,SAAY,CAGpC,EAAU,IAAA,GACV,MAAM,GAAW,SAAS,EAC1B,EAAY,IAAA,EACd,CAAC,CACH"}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piContext.d.cts","names":[],"sources":["../src/piContext.ts"],"mappings":";;;cAMa;UAEI;WACN;WACA;WACA;WACA;;iBAwCK,wBACd,KAAK,KAAK,sCACT;iBAIa,wBAAwB,KAAK,KAAK,8CAA8C;iBAehF,0BAA0B,IAAI,KAAK,8BAA8B,WAAW;iBAI5E,yBACd,KAAK,KAAK,qCACV,SAAS;iBAWK,yBAAyB,KAAK,KAAK,sCAAsC;cAM5E,qBAAqB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piContext.d.mts","names":[],"sources":["../src/piContext.ts"],"mappings":";;;cAMa;UAEI;WACN;WACA;WACA;WACA;;iBAwCK,wBACd,KAAK,KAAK,sCACT;iBAIa,wBAAwB,KAAK,KAAK,8CAA8C;iBAehF,0BAA0B,IAAI,KAAK,8BAA8B,WAAW;iBAI5E,yBACd,KAAK,KAAK,qCACV,SAAS;iBAWK,yBAAyB,KAAK,KAAK,sCAAsC;cAM5E,qBAAqB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piContext.mjs","names":[],"sources":["../src/piContext.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext, ExtensionFactory, SessionEntry } from '@earendil-works/pi-coding-agent';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { loadDoomConfig } from './config.ts';\nimport { getHarnessState } from './harnessStore.ts';\nimport type { DeepReadonly, DoomConfigContext, HarnessState } from './types.ts';\n\nexport const DOOM_CONFIG_ENTRY_TYPE = 'doom-pi:config:v1';\n\nexport interface DoomConfigSelection {\n readonly version: 1;\n readonly majorMode: string;\n readonly domains: readonly string[];\n readonly profile?: string;\n}\n\ninterface ConfigBinding {\n readonly context: DoomConfigContext;\n readonly generation: symbol;\n}\n\nconst configBindings = new WeakMap<ExtensionContext['sessionManager'], ConfigBinding>();\n\nfunction isSelection(value: unknown): value is DoomConfigSelection {\n if (typeof value !== 'object' || value === null) return false;\n const selection = value as Partial<DoomConfigSelection>;\n return (\n selection.version === 1 &&\n typeof selection.majorMode === 'string' &&\n Array.isArray(selection.domains) &&\n selection.domains.every((domain) => typeof domain === 'string') &&\n (selection.profile === undefined || typeof selection.profile === 'string')\n );\n}\n\nfunction branchSelection(entries: readonly SessionEntry[]): DoomConfigSelection | undefined {\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index];\n if (entry?.type === 'custom' && entry.customType === DOOM_CONFIG_ENTRY_TYPE && isSelection(entry.data)) {\n return entry.data;\n }\n }\n return undefined;\n}\n\nfunction deepFreeze<TValue>(value: TValue): DeepReadonly<TValue> {\n if (typeof value !== 'object' || value === null || Object.isFrozen(value)) {\n return value as DeepReadonly<TValue>;\n }\n for (const child of Object.values(value)) deepFreeze(child);\n return Object.freeze(value) as DeepReadonly<TValue>;\n}\n\nexport function readDoomConfigSelection(\n ctx: Pick<ExtensionContext, 'sessionManager'>,\n): DoomConfigSelection | undefined {\n return branchSelection(ctx.sessionManager.getBranch());\n}\n\nexport function createDoomConfigContext(ctx: Pick<ExtensionContext, 'cwd' | 'sessionManager'>): DoomConfigContext {\n const bootstrap = getHarnessState();\n const selection = readDoomConfigSelection(ctx);\n const harness: HarnessState = selection\n ? { ...bootstrap, majorMode: selection.majorMode, domains: [...selection.domains], profile: selection.profile }\n : bootstrap;\n const requiresRelaunch = Boolean(\n selection &&\n (selection.majorMode !== bootstrap.majorMode ||\n selection.profile !== bootstrap.profile ||\n selection.domains.join(',') !== bootstrap.domains.join(',')),\n );\n return deepFreeze({ settings: loadDoomConfig(bootstrap.root ?? ctx.cwd), harness, requiresRelaunch });\n}\n\nexport function appendDoomConfigSelection(pi: Pick<ExtensionAPI, 'appendEntry'>, selection: DoomConfigSelection): void {\n pi.appendEntry(DOOM_CONFIG_ENTRY_TYPE, selection);\n}\n\nexport function provideDoomConfigContext(\n ctx: Pick<ExtensionContext, 'sessionManager'>,\n context: DoomConfigContext,\n): () => void {\n const binding = { context, generation: Symbol('doom-config-context') };\n configBindings.set(ctx.sessionManager, binding);\n return () => {\n if (configBindings.get(ctx.sessionManager)?.generation === binding.generation) {\n configBindings.delete(ctx.sessionManager);\n }\n };\n}\n\nexport function requireDoomConfigContext(ctx: Pick<ExtensionContext, 'sessionManager'>): DoomConfigContext {\n const binding = configBindings.get(ctx.sessionManager);\n if (!binding) throw new Error('Doom config context is unavailable. Load @agimon-ai/doompi-config/pi.');\n return binding.context;\n}\n\nexport const doomConfigExtension: ExtensionFactory = (pi) => {\n let dispose: (() => void) | undefined;\n let telemetry: DoomTelemetry | undefined;\n pi.on('session_start', async (_event, ctx) => {\n dispose?.();\n const context = createDoomConfigContext(ctx);\n dispose = provideDoomConfigContext(ctx, context);\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-config',\n packageName: '@agimon-ai/doompi-config',\n cwd: ctx.cwd,\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n await telemetry.recordEvent('doom_config.context_bound', {\n 'config.major_mode': context.harness.majorMode,\n 'config.domain_count': context.harness.domains.length,\n 'config.has_profile': context.harness.profile !== undefined,\n 'config.requires_relaunch': context.requiresRelaunch,\n });\n });\n pi.on('session_shutdown', async () => {\n // Other extensions consume config during shutdown. Keep the WeakMap entry\n // alive for that phase and let it disappear with Pi's sessionManager.\n dispose = undefined;\n await telemetry?.shutdown();\n telemetry = undefined;\n });\n};\n"],"mappings":"qKAMA,MAAa,EAAyB,oBAchC,EAAiB,IAAI,QAE3B,SAAS,EAAY,EAA8C,CACjE,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,IAAM,EAAY,EAClB,OACE,EAAU,UAAY,GACtB,OAAO,EAAU,WAAc,UAC/B,MAAM,QAAQ,EAAU,OAAO,GAC/B,EAAU,QAAQ,MAAO,GAAW,OAAO,GAAW,QAAQ,IAC7D,EAAU,UAAY,IAAA,IAAa,OAAO,EAAU,SAAY,SAErE,CAEA,SAAS,EAAgB,EAAmE,CAC1F,IAAK,IAAI,EAAQ,EAAQ,OAAS,EAAG,GAAS,EAAG,IAAY,CAC3D,IAAM,EAAQ,EAAQ,GACtB,GAAI,GAAO,OAAS,UAAY,EAAM,aAAA,qBAAyC,EAAY,EAAM,IAAI,EACnG,OAAO,EAAM,IAEjB,CAEF,CAEA,SAAS,EAAmB,EAAqC,CAC/D,GAAI,OAAO,GAAU,WAAY,GAAkB,OAAO,SAAS,CAAK,EACtE,OAAO,EAET,IAAK,IAAM,KAAS,OAAO,OAAO,CAAK,EAAG,EAAW,CAAK,EAC1D,OAAO,OAAO,OAAO,CAAK,CAC5B,CAEA,SAAgB,EACd,EACiC,CACjC,OAAO,EAAgB,EAAI,eAAe,UAAU,CAAC,CACvD,CAEA,SAAgB,EAAwB,EAA0E,CAChH,IAAM,EAAY,EAAgB,EAC5B,EAAY,EAAwB,CAAG,EACvC,EAAwB,EAC1B,CAAE,GAAG,EAAW,UAAW,EAAU,UAAW,QAAS,CAAC,GAAG,EAAU,OAAO,EAAG,QAAS,EAAU,OAAQ,EAC5G,EACE,EAAmB,GACvB,IACC,EAAU,YAAc,EAAU,WACjC,EAAU,UAAY,EAAU,SAChC,EAAU,QAAQ,KAAK,GAAG,IAAM,EAAU,QAAQ,KAAK,GAAG,IAE9D,OAAO,EAAW,CAAE,SAAU,EAAe,EAAU,MAAQ,EAAI,GAAG,EAAG,UAAS,kBAAiB,CAAC,CACtG,CAEA,SAAgB,EAA0B,EAAuC,EAAsC,CACrH,EAAG,YAAY,EAAwB,CAAS,CAClD,CAEA,SAAgB,EACd,EACA,EACY,CACZ,IAAM,EAAU,CAAE,UAAS,WAAY,OAAO,qBAAqB,CAAE,EAErE,OADA,EAAe,IAAI,EAAI,eAAgB,CAAO,MACjC,CACP,EAAe,IAAI,EAAI,cAAc,CAAC,EAAE,aAAe,EAAQ,YACjE,EAAe,OAAO,EAAI,cAAc,CAE5C,CACF,CAEA,SAAgB,EAAyB,EAAkE,CACzG,IAAM,EAAU,EAAe,IAAI,EAAI,cAAc,EACrD,GAAI,CAAC,EAAS,MAAU,MAAM,uEAAuE,EACrG,OAAO,EAAQ,OACjB,CAEA,MAAa,EAAyC,GAAO,CAC3D,IAAI,EACA,EACJ,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAAQ,CAC5C,IAAU,EACV,IAAM,EAAU,EAAwB,CAAG,EAC3C,EAAU,EAAyB,EAAK,CAAO,EAC/C,IAAc,EAAoB,CAChC,YAAa,cACb,YAAa,2BACb,IAAK,EAAI,IACT,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACD,MAAM,EAAU,YAAY,4BAA6B,CACvD,oBAAqB,EAAQ,QAAQ,UACrC,sBAAuB,EAAQ,QAAQ,QAAQ,OAC/C,qBAAsB,EAAQ,QAAQ,UAAY,IAAA,GAClD,2BAA4B,EAAQ,gBACtC,CAAC,CACH,CAAC,EACD,EAAG,GAAG,mBAAoB,SAAY,CAGpC,EAAU,IAAA,GACV,MAAM,GAAW,SAAS,EAC1B,EAAY,IAAA,EACd,CAAC,CACH"}
|
|
@@ -0,0 +1,4 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.cjs","names":["path","fs","os","readDoomConfigSources"],"sources":["../src/profiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { readDoomConfigSources } from './layeredConfig.ts';\n\n/** Files that make up one repository persona, concatenated in this order. */\nexport const PERSONA_FILES = ['profile.md', 'SOUL.md', 'AGENTS.md'];\n\nexport interface AgentProfile {\n name: string;\n /** Directory under agents/, relative to personaRoot, which remains the persona source. */\n persona: string;\n /**\n * Root the persona path resolves against: the repository root for a\n * repository profile, the global `.doom` directory for a global one.\n */\n personaRoot: string;\n /** Environment defaults. Values already exported by the caller win. */\n env: Record<string, string>;\n}\n\nconst PROFILE_KEYS = new Set(['persona', 'env']);\nconst PROFILES_FILE = 'profiles.yaml';\nconst PROFILES_ROOT_KEY = 'profiles';\nconst AGENTS_DIRECTORY = 'agents';\nconst PARENT_DIRECTORY = '..';\nconst TEXT_ENCODING = 'utf8';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseEnvironment(name: string, value: unknown): Record<string, string> {\n if (value === undefined) return {};\n if (!isRecord(value)) throw new Error(`Profile \"${name}\" env must be a string mapping`);\n\n const environment: Record<string, string> = {};\n for (const [key, entry] of Object.entries(value)) {\n if (typeof entry !== 'string') throw new Error(`Profile \"${name}\" env.${key} must be a string`);\n environment[key] = entry;\n }\n return environment;\n}\n\nfunction parseProfile(personaRoot: string, name: string, value: unknown): AgentProfile {\n if (!isRecord(value)) throw new Error(`Profile \"${name}\" must be a mapping`);\n\n const unsupported = Object.keys(value).filter((key) => !PROFILE_KEYS.has(key));\n if (unsupported.length > 0) {\n throw new Error(`Profile \"${name}\" may only set persona and env; unsupported: ${unsupported.join(', ')}`);\n }\n if (typeof value.persona !== 'string' || value.persona.trim().length === 0) {\n throw new Error(`Profile \"${name}\" must set a persona`);\n }\n if (path.isAbsolute(value.persona)) {\n throw new Error(`Profile \"${name}\" persona must be relative to the config that declares it`);\n }\n\n const persona = value.persona;\n const personaPath = path.resolve(personaRoot, persona);\n const relativePersonaPath = path.relative(personaRoot, personaPath);\n if (relativePersonaPath !== AGENTS_DIRECTORY && !relativePersonaPath.startsWith(`${AGENTS_DIRECTORY}${path.sep}`)) {\n throw new Error(`Profile \"${name}\" persona must stay inside agents/`);\n }\n if (!fs.existsSync(personaPath) || !fs.statSync(personaPath).isDirectory()) {\n throw new Error(`Profile \"${name}\" references a missing persona: ${persona}`);\n }\n const realAgentsPath = fs.realpathSync(path.join(personaRoot, AGENTS_DIRECTORY));\n const realPersonaPath = fs.realpathSync(personaPath);\n const realRelativePersonaPath = path.relative(realAgentsPath, realPersonaPath);\n if (\n realRelativePersonaPath === PARENT_DIRECTORY ||\n realRelativePersonaPath.startsWith(`${PARENT_DIRECTORY}${path.sep}`)\n ) {\n throw new Error(`Profile \"${name}\" persona must stay inside agents/`);\n }\n if (!buildPersonaPrompt(personaRoot, persona)) {\n throw new Error(`Profile \"${name}\" persona has no readable persona files: ${persona}`);\n }\n\n return { name, persona, personaRoot, env: parseEnvironment(name, value.env) };\n}\n\n/**\n * Loads profiles from the global and repository configs, repository last.\n *\n * A repository profile replaces the global profile of the same name. Each one\n * keeps the root it was declared under, so a global profile's persona is read\n * from `~/.pi/.doom/agents/` however many repositories inherit it.\n */\nexport function loadProfiles(repoRoot: string, homeDirectory: string = os.homedir()): AgentProfile[] {\n const sources = readDoomConfigSources<unknown>(PROFILES_FILE, repoRoot, homeDirectory);\n const byName = new Map<string, AgentProfile>();\n\n for (const source of sources) {\n const parsed = source.document;\n if (!isRecord(parsed) || !isRecord(parsed[PROFILES_ROOT_KEY])) {\n throw new Error(`${source.filePath} must contain a profiles mapping`);\n }\n const unsupported = Object.keys(parsed).filter((key) => key !== PROFILES_ROOT_KEY);\n if (unsupported.length > 0) {\n throw new Error(`${source.filePath} may only contain profiles; unsupported: ${unsupported.join(', ')}`);\n }\n for (const [name, value] of Object.entries(parsed[PROFILES_ROOT_KEY])) {\n byName.set(name, parseProfile(source.baseDirectory, name, value));\n }\n }\n\n return [...byName.values()].sort((left, right) => left.name.localeCompare(right.name));\n}\n\n/** Resolves one selected profile and fails clearly when its name is unknown. */\nexport function resolveProfile(repoRoot: string, name: string, homeDirectory?: string): AgentProfile {\n const profile = loadProfiles(repoRoot, homeDirectory).find((candidate) => candidate.name === name);\n if (!profile) throw new Error(`Unknown profile: ${name}`);\n return profile;\n}\n\nexport function listProfileNames(repoRoot: string, homeDirectory?: string): string[] {\n return loadProfiles(repoRoot, homeDirectory).map((profile) => profile.name);\n}\n\n/** Builds the persona system-prompt block, or undefined when nothing is readable. */\nexport function buildPersonaPrompt(personaRoot: string, personaDirectory: string): string | undefined {\n const sections: string[] = [];\n const personaPath = fs.realpathSync(path.join(personaRoot, personaDirectory));\n for (const file of PERSONA_FILES) {\n const filePath = path.join(personaPath, file);\n if (!fs.existsSync(filePath)) continue;\n const realFilePath = fs.realpathSync(filePath);\n const relativeFilePath = path.relative(personaPath, realFilePath);\n if (relativeFilePath === PARENT_DIRECTORY || relativeFilePath.startsWith(`${PARENT_DIRECTORY}${path.sep}`)) {\n throw new Error(`Persona file must stay inside ${personaDirectory}: ${file}`);\n }\n const content = fs.readFileSync(realFilePath, TEXT_ENCODING).trim();\n if (content) sections.push(content);\n }\n if (sections.length === 0) return undefined;\n return [`[PERSONA] You are operating as the person described below (source: ${personaDirectory}).`, ...sections].join(\n '\\n\\n',\n );\n}\n\n/** Applies profile environment defaults and returns only the values it contributed. */\nexport function applyProfileEnvironment(\n environment: NodeJS.ProcessEnv,\n defaults: Record<string, string>,\n): Record<string, string> {\n const applied: Record<string, string> = {};\n for (const [key, value] of Object.entries(defaults)) {\n if (environment[key] !== undefined) continue;\n environment[key] = value;\n applied[key] = value;\n }\n return applied;\n}\n\n/** Replaces environment defaults previously contributed by another profile. */\nexport function replaceProfileEnvironment(\n environment: NodeJS.ProcessEnv,\n previous: Record<string, string>,\n next: Record<string, string>,\n): Record<string, string> {\n for (const [key, value] of Object.entries(previous)) {\n if (environment[key] === value) delete environment[key];\n }\n return applyProfileEnvironment(environment, next);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.d.cts","names":[],"sources":["../src/profiles.ts"],"mappings":";;cAMa;UAEI;EACf;;EAEA;;;;;EAKA;;EAEA,KAAK;;;;;;;;;iBAwES,aAAa,kBAAkB,yBAAuC;;iBAsBtE,eAAe,kBAAkB,cAAc,yBAAyB;iBAMxE,iBAAiB,kBAAkB;;iBAKnC,mBAAmB,qBAAqB;;iBAqBxC,wBACd,aAAa,OAAO,YACpB,UAAU,yBACT;;iBAWa,0BACd,aAAa,OAAO,YACpB,UAAU,wBACV,MAAM,yBACL"}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.d.mts","names":[],"sources":["../src/profiles.ts"],"mappings":";;cAMa;UAEI;EACf;;EAEA;;;;;EAKA;;EAEA,KAAK;;;;;;;;;iBAwES,aAAa,kBAAkB,yBAAuC;;iBAsBtE,eAAe,kBAAkB,cAAc,yBAAyB;iBAMxE,iBAAiB,kBAAkB;;iBAKnC,mBAAmB,qBAAqB;;iBAqBxC,wBACd,aAAa,OAAO,YACpB,UAAU,yBACT;;iBAWa,0BACd,aAAa,OAAO,YACpB,UAAU,wBACV,MAAM,yBACL"}
|
|
@@ -0,0 +1,4 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.mjs","names":[],"sources":["../src/profiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { readDoomConfigSources } from './layeredConfig.ts';\n\n/** Files that make up one repository persona, concatenated in this order. */\nexport const PERSONA_FILES = ['profile.md', 'SOUL.md', 'AGENTS.md'];\n\nexport interface AgentProfile {\n name: string;\n /** Directory under agents/, relative to personaRoot, which remains the persona source. */\n persona: string;\n /**\n * Root the persona path resolves against: the repository root for a\n * repository profile, the global `.doom` directory for a global one.\n */\n personaRoot: string;\n /** Environment defaults. Values already exported by the caller win. */\n env: Record<string, string>;\n}\n\nconst PROFILE_KEYS = new Set(['persona', 'env']);\nconst PROFILES_FILE = 'profiles.yaml';\nconst PROFILES_ROOT_KEY = 'profiles';\nconst AGENTS_DIRECTORY = 'agents';\nconst PARENT_DIRECTORY = '..';\nconst TEXT_ENCODING = 'utf8';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction parseEnvironment(name: string, value: unknown): Record<string, string> {\n if (value === undefined) return {};\n if (!isRecord(value)) throw new Error(`Profile \"${name}\" env must be a string mapping`);\n\n const environment: Record<string, string> = {};\n for (const [key, entry] of Object.entries(value)) {\n if (typeof entry !== 'string') throw new Error(`Profile \"${name}\" env.${key} must be a string`);\n environment[key] = entry;\n }\n return environment;\n}\n\nfunction parseProfile(personaRoot: string, name: string, value: unknown): AgentProfile {\n if (!isRecord(value)) throw new Error(`Profile \"${name}\" must be a mapping`);\n\n const unsupported = Object.keys(value).filter((key) => !PROFILE_KEYS.has(key));\n if (unsupported.length > 0) {\n throw new Error(`Profile \"${name}\" may only set persona and env; unsupported: ${unsupported.join(', ')}`);\n }\n if (typeof value.persona !== 'string' || value.persona.trim().length === 0) {\n throw new Error(`Profile \"${name}\" must set a persona`);\n }\n if (path.isAbsolute(value.persona)) {\n throw new Error(`Profile \"${name}\" persona must be relative to the config that declares it`);\n }\n\n const persona = value.persona;\n const personaPath = path.resolve(personaRoot, persona);\n const relativePersonaPath = path.relative(personaRoot, personaPath);\n if (relativePersonaPath !== AGENTS_DIRECTORY && !relativePersonaPath.startsWith(`${AGENTS_DIRECTORY}${path.sep}`)) {\n throw new Error(`Profile \"${name}\" persona must stay inside agents/`);\n }\n if (!fs.existsSync(personaPath) || !fs.statSync(personaPath).isDirectory()) {\n throw new Error(`Profile \"${name}\" references a missing persona: ${persona}`);\n }\n const realAgentsPath = fs.realpathSync(path.join(personaRoot, AGENTS_DIRECTORY));\n const realPersonaPath = fs.realpathSync(personaPath);\n const realRelativePersonaPath = path.relative(realAgentsPath, realPersonaPath);\n if (\n realRelativePersonaPath === PARENT_DIRECTORY ||\n realRelativePersonaPath.startsWith(`${PARENT_DIRECTORY}${path.sep}`)\n ) {\n throw new Error(`Profile \"${name}\" persona must stay inside agents/`);\n }\n if (!buildPersonaPrompt(personaRoot, persona)) {\n throw new Error(`Profile \"${name}\" persona has no readable persona files: ${persona}`);\n }\n\n return { name, persona, personaRoot, env: parseEnvironment(name, value.env) };\n}\n\n/**\n * Loads profiles from the global and repository configs, repository last.\n *\n * A repository profile replaces the global profile of the same name. Each one\n * keeps the root it was declared under, so a global profile's persona is read\n * from `~/.pi/.doom/agents/` however many repositories inherit it.\n */\nexport function loadProfiles(repoRoot: string, homeDirectory: string = os.homedir()): AgentProfile[] {\n const sources = readDoomConfigSources<unknown>(PROFILES_FILE, repoRoot, homeDirectory);\n const byName = new Map<string, AgentProfile>();\n\n for (const source of sources) {\n const parsed = source.document;\n if (!isRecord(parsed) || !isRecord(parsed[PROFILES_ROOT_KEY])) {\n throw new Error(`${source.filePath} must contain a profiles mapping`);\n }\n const unsupported = Object.keys(parsed).filter((key) => key !== PROFILES_ROOT_KEY);\n if (unsupported.length > 0) {\n throw new Error(`${source.filePath} may only contain profiles; unsupported: ${unsupported.join(', ')}`);\n }\n for (const [name, value] of Object.entries(parsed[PROFILES_ROOT_KEY])) {\n byName.set(name, parseProfile(source.baseDirectory, name, value));\n }\n }\n\n return [...byName.values()].sort((left, right) => left.name.localeCompare(right.name));\n}\n\n/** Resolves one selected profile and fails clearly when its name is unknown. */\nexport function resolveProfile(repoRoot: string, name: string, homeDirectory?: string): AgentProfile {\n const profile = loadProfiles(repoRoot, homeDirectory).find((candidate) => candidate.name === name);\n if (!profile) throw new Error(`Unknown profile: ${name}`);\n return profile;\n}\n\nexport function listProfileNames(repoRoot: string, homeDirectory?: string): string[] {\n return loadProfiles(repoRoot, homeDirectory).map((profile) => profile.name);\n}\n\n/** Builds the persona system-prompt block, or undefined when nothing is readable. */\nexport function buildPersonaPrompt(personaRoot: string, personaDirectory: string): string | undefined {\n const sections: string[] = [];\n const personaPath = fs.realpathSync(path.join(personaRoot, personaDirectory));\n for (const file of PERSONA_FILES) {\n const filePath = path.join(personaPath, file);\n if (!fs.existsSync(filePath)) continue;\n const realFilePath = fs.realpathSync(filePath);\n const relativeFilePath = path.relative(personaPath, realFilePath);\n if (relativeFilePath === PARENT_DIRECTORY || relativeFilePath.startsWith(`${PARENT_DIRECTORY}${path.sep}`)) {\n throw new Error(`Persona file must stay inside ${personaDirectory}: ${file}`);\n }\n const content = fs.readFileSync(realFilePath, TEXT_ENCODING).trim();\n if (content) sections.push(content);\n }\n if (sections.length === 0) return undefined;\n return [`[PERSONA] You are operating as the person described below (source: ${personaDirectory}).`, ...sections].join(\n '\\n\\n',\n );\n}\n\n/** Applies profile environment defaults and returns only the values it contributed. */\nexport function applyProfileEnvironment(\n environment: NodeJS.ProcessEnv,\n defaults: Record<string, string>,\n): Record<string, string> {\n const applied: Record<string, string> = {};\n for (const [key, value] of Object.entries(defaults)) {\n if (environment[key] !== undefined) continue;\n environment[key] = value;\n applied[key] = value;\n }\n return applied;\n}\n\n/** Replaces environment defaults previously contributed by another profile. */\nexport function replaceProfileEnvironment(\n environment: NodeJS.ProcessEnv,\n previous: Record<string, string>,\n next: Record<string, string>,\n): Record<string, string> {\n for (const [key, value] of Object.entries(previous)) {\n if (environment[key] === value) delete environment[key];\n }\n return applyProfileEnvironment(environment, next);\n}\n"],"mappings":"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"}
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["export const DOOM_CONFIG_TYPES = { ConfigService: Symbol.for('DoomConfig:ConfigService') } as const;\n\nexport type ProjectTrust = 'ask' | 'always' | 'never';\nexport type PlanningThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';\nexport type VoiceEngine = 'auto' | 'whisper-cpp' | 'openai-whisper' | 'mlx-whisper';\nexport type VoiceTtsEngine = 'macos-say';\n\nexport interface PlanningAgentConfig {\n model?: string;\n thinking?: PlanningThinkingLevel;\n}\nexport interface PlanningModeConfig {\n main?: PlanningAgentConfig;\n subagents?: PlanningAgentConfig;\n plansDirectory?: string;\n}\nexport interface EditorConfig {\n command?: string;\n}\nexport interface VoiceModelConfig {\n path?: string;\n id?: string;\n}\nexport interface VoiceAdapterConfig {\n binary?: string;\n model: VoiceModelConfig;\n}\nexport interface VoiceTtsConfig {\n engine: VoiceTtsEngine;\n voice?: string;\n rate?: number;\n}\nexport interface VoiceAutoCaptureConfig {\n model: string;\n startPhrases?: string[];\n stopPhrases?: string[];\n tts: VoiceTtsConfig;\n}\nexport interface ResolvedVoiceAutoCaptureConfig {\n model: string;\n startPhrases: string[];\n stopPhrases: string[];\n tts: VoiceTtsConfig;\n}\nexport interface VoiceConfig {\n engine?: VoiceEngine;\n language?: string;\n recorder?: { binary?: string; device?: string };\n adapters?: {\n 'whisper-cpp'?: VoiceAdapterConfig;\n 'openai-whisper'?: VoiceAdapterConfig;\n 'mlx-whisper'?: VoiceAdapterConfig;\n };\n autoCapture?: VoiceAutoCaptureConfig;\n}\nexport interface ResolvedVoiceConfig {\n engine: VoiceEngine;\n language: string;\n recorder: { binary?: string; device: string };\n adapters: NonNullable<VoiceConfig['adapters']>;\n autoCapture?: ResolvedVoiceAutoCaptureConfig;\n}\n/**\n * The matrix a repository selects by default.\n *\n * Read by `doom-pi sync`, which pins it into the generated Pi config so a plain\n * `pi` session starts on the same matrix the repository declares. The launcher\n * keeps taking its selection from flags and the environment.\n */\nexport interface DoomSelectionConfig {\n majorMode?: string;\n domains?: string[];\n profile?: string;\n}\n\nexport interface DoomConfig {\n modes?: { planning?: PlanningModeConfig };\n projectTrust: ProjectTrust;\n editor?: EditorConfig;\n voice?: VoiceConfig;\n selection?: DoomSelectionConfig;\n}\n\nexport interface PluginHookSource {\n pluginRoot: string;\n configPath: string;\n}\n\nexport interface HarnessState {\n root?: string;\n /** The one named major mode this session runs under. */\n majorMode: string;\n temporaryDirectory?: string;\n domains: string[];\n /** The layer components the major mode resolved to. */\n layers: string[];\n profile?: string;\n profileEnvironment: Record<string, string>;\n hookGroups?: string[];\n skillDirectories: string[];\n agentDirectories: string[];\n additionalDirectories: string[];\n childExtensions: string[];\n pluginDirectories: string[];\n pluginHooks: PluginHookSource[];\n mcpConfigPath?: string;\n personaFile?: string;\n workflowExtension?: string;\n allowProtectedWrites: boolean;\n hooks: boolean;\n agents: boolean;\n mcp: boolean;\n}\n\nexport type DeepReadonly<TValue> = TValue extends (...args: never[]) => unknown\n ? TValue\n : TValue extends readonly (infer TItem)[]\n ? readonly DeepReadonly<TItem>[]\n : TValue extends object\n ? { readonly [TKey in keyof TValue]: DeepReadonly<TValue[TKey]> }\n : TValue;\n\nexport type DoomHarnessContext = DeepReadonly<HarnessState>;\n\nexport interface DoomConfigContext {\n readonly settings: DeepReadonly<DoomConfig>;\n readonly harness: DoomHarnessContext;\n readonly requiresRelaunch: boolean;\n}\n\nexport interface IDoomConfigService {\n load(repoRoot: string, homeDirectory?: string): DoomConfig;\n}\n"],"mappings":"mEAAA,MAAa,EAAoB,CAAE,cAAe,OAAO,IAAI,0BAA0B,CAAE"}
|
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
declare const DOOM_CONFIG_TYPES: {
|
|
3
|
+
readonly ConfigService: symbol;
|
|
4
|
+
};
|
|
5
|
+
type ProjectTrust = 'ask' | 'always' | 'never';
|
|
6
|
+
type PlanningThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
7
|
+
type VoiceEngine = 'auto' | 'whisper-cpp' | 'openai-whisper' | 'mlx-whisper';
|
|
8
|
+
type VoiceTtsEngine = 'macos-say';
|
|
9
|
+
interface PlanningAgentConfig {
|
|
10
|
+
model?: string;
|
|
11
|
+
thinking?: PlanningThinkingLevel;
|
|
12
|
+
}
|
|
13
|
+
interface PlanningModeConfig {
|
|
14
|
+
main?: PlanningAgentConfig;
|
|
15
|
+
subagents?: PlanningAgentConfig;
|
|
16
|
+
plansDirectory?: string;
|
|
17
|
+
}
|
|
18
|
+
interface EditorConfig {
|
|
19
|
+
command?: string;
|
|
20
|
+
}
|
|
21
|
+
interface VoiceModelConfig {
|
|
22
|
+
path?: string;
|
|
23
|
+
id?: string;
|
|
24
|
+
}
|
|
25
|
+
interface VoiceAdapterConfig {
|
|
26
|
+
binary?: string;
|
|
27
|
+
model: VoiceModelConfig;
|
|
28
|
+
}
|
|
29
|
+
interface VoiceTtsConfig {
|
|
30
|
+
engine: VoiceTtsEngine;
|
|
31
|
+
voice?: string;
|
|
32
|
+
rate?: number;
|
|
33
|
+
}
|
|
34
|
+
interface VoiceAutoCaptureConfig {
|
|
35
|
+
model: string;
|
|
36
|
+
startPhrases?: string[];
|
|
37
|
+
stopPhrases?: string[];
|
|
38
|
+
tts: VoiceTtsConfig;
|
|
39
|
+
}
|
|
40
|
+
interface ResolvedVoiceAutoCaptureConfig {
|
|
41
|
+
model: string;
|
|
42
|
+
startPhrases: string[];
|
|
43
|
+
stopPhrases: string[];
|
|
44
|
+
tts: VoiceTtsConfig;
|
|
45
|
+
}
|
|
46
|
+
interface VoiceConfig {
|
|
47
|
+
engine?: VoiceEngine;
|
|
48
|
+
language?: string;
|
|
49
|
+
recorder?: {
|
|
50
|
+
binary?: string;
|
|
51
|
+
device?: string;
|
|
52
|
+
};
|
|
53
|
+
adapters?: {
|
|
54
|
+
'whisper-cpp'?: VoiceAdapterConfig;
|
|
55
|
+
'openai-whisper'?: VoiceAdapterConfig;
|
|
56
|
+
'mlx-whisper'?: VoiceAdapterConfig;
|
|
57
|
+
};
|
|
58
|
+
autoCapture?: VoiceAutoCaptureConfig;
|
|
59
|
+
}
|
|
60
|
+
interface ResolvedVoiceConfig {
|
|
61
|
+
engine: VoiceEngine;
|
|
62
|
+
language: string;
|
|
63
|
+
recorder: {
|
|
64
|
+
binary?: string;
|
|
65
|
+
device: string;
|
|
66
|
+
};
|
|
67
|
+
adapters: NonNullable<VoiceConfig['adapters']>;
|
|
68
|
+
autoCapture?: ResolvedVoiceAutoCaptureConfig;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The matrix a repository selects by default.
|
|
72
|
+
*
|
|
73
|
+
* Read by `doom-pi sync`, which pins it into the generated Pi config so a plain
|
|
74
|
+
* `pi` session starts on the same matrix the repository declares. The launcher
|
|
75
|
+
* keeps taking its selection from flags and the environment.
|
|
76
|
+
*/
|
|
77
|
+
interface DoomSelectionConfig {
|
|
78
|
+
majorMode?: string;
|
|
79
|
+
domains?: string[];
|
|
80
|
+
profile?: string;
|
|
81
|
+
}
|
|
82
|
+
interface DoomConfig {
|
|
83
|
+
modes?: {
|
|
84
|
+
planning?: PlanningModeConfig;
|
|
85
|
+
};
|
|
86
|
+
projectTrust: ProjectTrust;
|
|
87
|
+
editor?: EditorConfig;
|
|
88
|
+
voice?: VoiceConfig;
|
|
89
|
+
selection?: DoomSelectionConfig;
|
|
90
|
+
}
|
|
91
|
+
interface PluginHookSource {
|
|
92
|
+
pluginRoot: string;
|
|
93
|
+
configPath: string;
|
|
94
|
+
}
|
|
95
|
+
interface HarnessState {
|
|
96
|
+
root?: string;
|
|
97
|
+
/** The one named major mode this session runs under. */
|
|
98
|
+
majorMode: string;
|
|
99
|
+
temporaryDirectory?: string;
|
|
100
|
+
domains: string[];
|
|
101
|
+
/** The layer components the major mode resolved to. */
|
|
102
|
+
layers: string[];
|
|
103
|
+
profile?: string;
|
|
104
|
+
profileEnvironment: Record<string, string>;
|
|
105
|
+
hookGroups?: string[];
|
|
106
|
+
skillDirectories: string[];
|
|
107
|
+
agentDirectories: string[];
|
|
108
|
+
additionalDirectories: string[];
|
|
109
|
+
childExtensions: string[];
|
|
110
|
+
pluginDirectories: string[];
|
|
111
|
+
pluginHooks: PluginHookSource[];
|
|
112
|
+
mcpConfigPath?: string;
|
|
113
|
+
personaFile?: string;
|
|
114
|
+
workflowExtension?: string;
|
|
115
|
+
allowProtectedWrites: boolean;
|
|
116
|
+
hooks: boolean;
|
|
117
|
+
agents: boolean;
|
|
118
|
+
mcp: boolean;
|
|
119
|
+
}
|
|
120
|
+
type DeepReadonly<TValue> = TValue extends ((...args: never[]) => unknown) ? TValue : TValue extends readonly (infer TItem)[] ? readonly DeepReadonly<TItem>[] : TValue extends object ? { readonly [TKey in keyof TValue]: DeepReadonly<TValue[TKey]>; } : TValue;
|
|
121
|
+
type DoomHarnessContext = DeepReadonly<HarnessState>;
|
|
122
|
+
interface DoomConfigContext {
|
|
123
|
+
readonly settings: DeepReadonly<DoomConfig>;
|
|
124
|
+
readonly harness: DoomHarnessContext;
|
|
125
|
+
readonly requiresRelaunch: boolean;
|
|
126
|
+
}
|
|
127
|
+
interface IDoomConfigService {
|
|
128
|
+
load(repoRoot: string, homeDirectory?: string): DoomConfig;
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
export { DOOM_CONFIG_TYPES, DeepReadonly, DoomConfig, DoomConfigContext, DoomHarnessContext, DoomSelectionConfig, EditorConfig, HarnessState, IDoomConfigService, PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, PluginHookSource, ProjectTrust, ResolvedVoiceAutoCaptureConfig, ResolvedVoiceConfig, VoiceAdapterConfig, VoiceAutoCaptureConfig, VoiceConfig, VoiceEngine, VoiceModelConfig, VoiceTtsConfig, VoiceTtsEngine };
|
|
132
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";cAAa;WAAA;;KAED;KACA;KACA;KACA;UAEK;EACf;EACA,WAAW;;UAEI;EACf,OAAO;EACP,YAAY;EACZ;;UAEe;EACf;;UAEe;EACf;EACA;;UAEe;EACf;EACA,OAAO;;UAEQ;EACf,QAAQ;EACR;EACA;;UAEe;EACf;EACA;EACA;EACA,KAAK;;UAEU;EACf;EACA;EACA;EACA,KAAK;;UAEU;EACf,SAAS;EACT;EACA;IAAa;IAAiB;;EAC9B;IACE,gBAAgB;IAChB,mBAAmB;IACnB,gBAAgB;;EAElB,cAAc;;UAEC;EACf,QAAQ;EACR;EACA;IAAY;IAAiB;;EAC7B,UAAU,YAAY;EACtB,cAAc;;;;;;;;;UASC;EACf;EACA;EACA;;UAGe;EACf;IAAU,WAAW;;EACrB,cAAc;EACd,SAAS;EACT,QAAQ;EACR,YAAY;;UAGG;EACf;EACA;;UAGe;EACf;;EAEA;EACA;EACA;;EAEA;EACA;EACA,oBAAoB;EACpB;EACA;EACA;EACA;EACA;EACA;EACA,aAAa;EACb;EACA;EACA;EACA;EACA;EACA;EACA;;KAGU,aAAa,UAAU,oBAAmB,6BAClD,SACA,+BAA+B,oBACpB,aAAa,WACtB,oCACc,cAAc,SAAS,aAAa,OAAO,YACvD;KAEI,qBAAqB,aAAa;UAE7B;WACN,UAAU,aAAa;WACvB,SAAS;WACT;;UAGM;EACf,KAAK,kBAAkB,yBAAyB"}
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
declare const DOOM_CONFIG_TYPES: {
|
|
3
|
+
readonly ConfigService: symbol;
|
|
4
|
+
};
|
|
5
|
+
type ProjectTrust = 'ask' | 'always' | 'never';
|
|
6
|
+
type PlanningThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
7
|
+
type VoiceEngine = 'auto' | 'whisper-cpp' | 'openai-whisper' | 'mlx-whisper';
|
|
8
|
+
type VoiceTtsEngine = 'macos-say';
|
|
9
|
+
interface PlanningAgentConfig {
|
|
10
|
+
model?: string;
|
|
11
|
+
thinking?: PlanningThinkingLevel;
|
|
12
|
+
}
|
|
13
|
+
interface PlanningModeConfig {
|
|
14
|
+
main?: PlanningAgentConfig;
|
|
15
|
+
subagents?: PlanningAgentConfig;
|
|
16
|
+
plansDirectory?: string;
|
|
17
|
+
}
|
|
18
|
+
interface EditorConfig {
|
|
19
|
+
command?: string;
|
|
20
|
+
}
|
|
21
|
+
interface VoiceModelConfig {
|
|
22
|
+
path?: string;
|
|
23
|
+
id?: string;
|
|
24
|
+
}
|
|
25
|
+
interface VoiceAdapterConfig {
|
|
26
|
+
binary?: string;
|
|
27
|
+
model: VoiceModelConfig;
|
|
28
|
+
}
|
|
29
|
+
interface VoiceTtsConfig {
|
|
30
|
+
engine: VoiceTtsEngine;
|
|
31
|
+
voice?: string;
|
|
32
|
+
rate?: number;
|
|
33
|
+
}
|
|
34
|
+
interface VoiceAutoCaptureConfig {
|
|
35
|
+
model: string;
|
|
36
|
+
startPhrases?: string[];
|
|
37
|
+
stopPhrases?: string[];
|
|
38
|
+
tts: VoiceTtsConfig;
|
|
39
|
+
}
|
|
40
|
+
interface ResolvedVoiceAutoCaptureConfig {
|
|
41
|
+
model: string;
|
|
42
|
+
startPhrases: string[];
|
|
43
|
+
stopPhrases: string[];
|
|
44
|
+
tts: VoiceTtsConfig;
|
|
45
|
+
}
|
|
46
|
+
interface VoiceConfig {
|
|
47
|
+
engine?: VoiceEngine;
|
|
48
|
+
language?: string;
|
|
49
|
+
recorder?: {
|
|
50
|
+
binary?: string;
|
|
51
|
+
device?: string;
|
|
52
|
+
};
|
|
53
|
+
adapters?: {
|
|
54
|
+
'whisper-cpp'?: VoiceAdapterConfig;
|
|
55
|
+
'openai-whisper'?: VoiceAdapterConfig;
|
|
56
|
+
'mlx-whisper'?: VoiceAdapterConfig;
|
|
57
|
+
};
|
|
58
|
+
autoCapture?: VoiceAutoCaptureConfig;
|
|
59
|
+
}
|
|
60
|
+
interface ResolvedVoiceConfig {
|
|
61
|
+
engine: VoiceEngine;
|
|
62
|
+
language: string;
|
|
63
|
+
recorder: {
|
|
64
|
+
binary?: string;
|
|
65
|
+
device: string;
|
|
66
|
+
};
|
|
67
|
+
adapters: NonNullable<VoiceConfig['adapters']>;
|
|
68
|
+
autoCapture?: ResolvedVoiceAutoCaptureConfig;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The matrix a repository selects by default.
|
|
72
|
+
*
|
|
73
|
+
* Read by `doom-pi sync`, which pins it into the generated Pi config so a plain
|
|
74
|
+
* `pi` session starts on the same matrix the repository declares. The launcher
|
|
75
|
+
* keeps taking its selection from flags and the environment.
|
|
76
|
+
*/
|
|
77
|
+
interface DoomSelectionConfig {
|
|
78
|
+
majorMode?: string;
|
|
79
|
+
domains?: string[];
|
|
80
|
+
profile?: string;
|
|
81
|
+
}
|
|
82
|
+
interface DoomConfig {
|
|
83
|
+
modes?: {
|
|
84
|
+
planning?: PlanningModeConfig;
|
|
85
|
+
};
|
|
86
|
+
projectTrust: ProjectTrust;
|
|
87
|
+
editor?: EditorConfig;
|
|
88
|
+
voice?: VoiceConfig;
|
|
89
|
+
selection?: DoomSelectionConfig;
|
|
90
|
+
}
|
|
91
|
+
interface PluginHookSource {
|
|
92
|
+
pluginRoot: string;
|
|
93
|
+
configPath: string;
|
|
94
|
+
}
|
|
95
|
+
interface HarnessState {
|
|
96
|
+
root?: string;
|
|
97
|
+
/** The one named major mode this session runs under. */
|
|
98
|
+
majorMode: string;
|
|
99
|
+
temporaryDirectory?: string;
|
|
100
|
+
domains: string[];
|
|
101
|
+
/** The layer components the major mode resolved to. */
|
|
102
|
+
layers: string[];
|
|
103
|
+
profile?: string;
|
|
104
|
+
profileEnvironment: Record<string, string>;
|
|
105
|
+
hookGroups?: string[];
|
|
106
|
+
skillDirectories: string[];
|
|
107
|
+
agentDirectories: string[];
|
|
108
|
+
additionalDirectories: string[];
|
|
109
|
+
childExtensions: string[];
|
|
110
|
+
pluginDirectories: string[];
|
|
111
|
+
pluginHooks: PluginHookSource[];
|
|
112
|
+
mcpConfigPath?: string;
|
|
113
|
+
personaFile?: string;
|
|
114
|
+
workflowExtension?: string;
|
|
115
|
+
allowProtectedWrites: boolean;
|
|
116
|
+
hooks: boolean;
|
|
117
|
+
agents: boolean;
|
|
118
|
+
mcp: boolean;
|
|
119
|
+
}
|
|
120
|
+
type DeepReadonly<TValue> = TValue extends ((...args: never[]) => unknown) ? TValue : TValue extends readonly (infer TItem)[] ? readonly DeepReadonly<TItem>[] : TValue extends object ? { readonly [TKey in keyof TValue]: DeepReadonly<TValue[TKey]>; } : TValue;
|
|
121
|
+
type DoomHarnessContext = DeepReadonly<HarnessState>;
|
|
122
|
+
interface DoomConfigContext {
|
|
123
|
+
readonly settings: DeepReadonly<DoomConfig>;
|
|
124
|
+
readonly harness: DoomHarnessContext;
|
|
125
|
+
readonly requiresRelaunch: boolean;
|
|
126
|
+
}
|
|
127
|
+
interface IDoomConfigService {
|
|
128
|
+
load(repoRoot: string, homeDirectory?: string): DoomConfig;
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
export { DOOM_CONFIG_TYPES, DeepReadonly, DoomConfig, DoomConfigContext, DoomHarnessContext, DoomSelectionConfig, EditorConfig, HarnessState, IDoomConfigService, PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, PluginHookSource, ProjectTrust, ResolvedVoiceAutoCaptureConfig, ResolvedVoiceConfig, VoiceAdapterConfig, VoiceAutoCaptureConfig, VoiceConfig, VoiceEngine, VoiceModelConfig, VoiceTtsConfig, VoiceTtsEngine };
|
|
132
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";cAAa;WAAA;;KAED;KACA;KACA;KACA;UAEK;EACf;EACA,WAAW;;UAEI;EACf,OAAO;EACP,YAAY;EACZ;;UAEe;EACf;;UAEe;EACf;EACA;;UAEe;EACf;EACA,OAAO;;UAEQ;EACf,QAAQ;EACR;EACA;;UAEe;EACf;EACA;EACA;EACA,KAAK;;UAEU;EACf;EACA;EACA;EACA,KAAK;;UAEU;EACf,SAAS;EACT;EACA;IAAa;IAAiB;;EAC9B;IACE,gBAAgB;IAChB,mBAAmB;IACnB,gBAAgB;;EAElB,cAAc;;UAEC;EACf,QAAQ;EACR;EACA;IAAY;IAAiB;;EAC7B,UAAU,YAAY;EACtB,cAAc;;;;;;;;;UASC;EACf;EACA;EACA;;UAGe;EACf;IAAU,WAAW;;EACrB,cAAc;EACd,SAAS;EACT,QAAQ;EACR,YAAY;;UAGG;EACf;EACA;;UAGe;EACf;;EAEA;EACA;EACA;;EAEA;EACA;EACA,oBAAoB;EACpB;EACA;EACA;EACA;EACA;EACA;EACA,aAAa;EACb;EACA;EACA;EACA;EACA;EACA;EACA;;KAGU,aAAa,UAAU,oBAAmB,6BAClD,SACA,+BAA+B,oBACpB,aAAa,WACtB,oCACc,cAAc,SAAS,aAAa,OAAO,YACvD;KAEI,qBAAqB,aAAa;UAE7B;WACN,UAAU,aAAa;WACvB,SAAS;WACT;;UAGM;EACf,KAAK,kBAAkB,yBAAyB"}
|
package/dist/types.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["export const DOOM_CONFIG_TYPES = { ConfigService: Symbol.for('DoomConfig:ConfigService') } as const;\n\nexport type ProjectTrust = 'ask' | 'always' | 'never';\nexport type PlanningThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';\nexport type VoiceEngine = 'auto' | 'whisper-cpp' | 'openai-whisper' | 'mlx-whisper';\nexport type VoiceTtsEngine = 'macos-say';\n\nexport interface PlanningAgentConfig {\n model?: string;\n thinking?: PlanningThinkingLevel;\n}\nexport interface PlanningModeConfig {\n main?: PlanningAgentConfig;\n subagents?: PlanningAgentConfig;\n plansDirectory?: string;\n}\nexport interface EditorConfig {\n command?: string;\n}\nexport interface VoiceModelConfig {\n path?: string;\n id?: string;\n}\nexport interface VoiceAdapterConfig {\n binary?: string;\n model: VoiceModelConfig;\n}\nexport interface VoiceTtsConfig {\n engine: VoiceTtsEngine;\n voice?: string;\n rate?: number;\n}\nexport interface VoiceAutoCaptureConfig {\n model: string;\n startPhrases?: string[];\n stopPhrases?: string[];\n tts: VoiceTtsConfig;\n}\nexport interface ResolvedVoiceAutoCaptureConfig {\n model: string;\n startPhrases: string[];\n stopPhrases: string[];\n tts: VoiceTtsConfig;\n}\nexport interface VoiceConfig {\n engine?: VoiceEngine;\n language?: string;\n recorder?: { binary?: string; device?: string };\n adapters?: {\n 'whisper-cpp'?: VoiceAdapterConfig;\n 'openai-whisper'?: VoiceAdapterConfig;\n 'mlx-whisper'?: VoiceAdapterConfig;\n };\n autoCapture?: VoiceAutoCaptureConfig;\n}\nexport interface ResolvedVoiceConfig {\n engine: VoiceEngine;\n language: string;\n recorder: { binary?: string; device: string };\n adapters: NonNullable<VoiceConfig['adapters']>;\n autoCapture?: ResolvedVoiceAutoCaptureConfig;\n}\n/**\n * The matrix a repository selects by default.\n *\n * Read by `doom-pi sync`, which pins it into the generated Pi config so a plain\n * `pi` session starts on the same matrix the repository declares. The launcher\n * keeps taking its selection from flags and the environment.\n */\nexport interface DoomSelectionConfig {\n majorMode?: string;\n domains?: string[];\n profile?: string;\n}\n\nexport interface DoomConfig {\n modes?: { planning?: PlanningModeConfig };\n projectTrust: ProjectTrust;\n editor?: EditorConfig;\n voice?: VoiceConfig;\n selection?: DoomSelectionConfig;\n}\n\nexport interface PluginHookSource {\n pluginRoot: string;\n configPath: string;\n}\n\nexport interface HarnessState {\n root?: string;\n /** The one named major mode this session runs under. */\n majorMode: string;\n temporaryDirectory?: string;\n domains: string[];\n /** The layer components the major mode resolved to. */\n layers: string[];\n profile?: string;\n profileEnvironment: Record<string, string>;\n hookGroups?: string[];\n skillDirectories: string[];\n agentDirectories: string[];\n additionalDirectories: string[];\n childExtensions: string[];\n pluginDirectories: string[];\n pluginHooks: PluginHookSource[];\n mcpConfigPath?: string;\n personaFile?: string;\n workflowExtension?: string;\n allowProtectedWrites: boolean;\n hooks: boolean;\n agents: boolean;\n mcp: boolean;\n}\n\nexport type DeepReadonly<TValue> = TValue extends (...args: never[]) => unknown\n ? TValue\n : TValue extends readonly (infer TItem)[]\n ? readonly DeepReadonly<TItem>[]\n : TValue extends object\n ? { readonly [TKey in keyof TValue]: DeepReadonly<TValue[TKey]> }\n : TValue;\n\nexport type DoomHarnessContext = DeepReadonly<HarnessState>;\n\nexport interface DoomConfigContext {\n readonly settings: DeepReadonly<DoomConfig>;\n readonly harness: DoomHarnessContext;\n readonly requiresRelaunch: boolean;\n}\n\nexport interface IDoomConfigService {\n load(repoRoot: string, homeDirectory?: string): DoomConfig;\n}\n"],"mappings":"AAAA,MAAa,EAAoB,CAAE,cAAe,OAAO,IAAI,0BAA0B,CAAE"}
|