@agimon-ai/doompi-profile 0.0.1-alpha.2 → 0.0.1-alpha.3

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.
@@ -1,2 +1,2 @@
1
- const e=require("../telemetry/logSinkTelemetry.cjs"),t=require("../../commands/profileCommand.cjs");let n=require("@deepseek-ai/cordis");async function r(r,i=e.createProfileTelemetry()){let a=new n.Context,o,s=()=>(o??=a.fiber.dispose(),o);try{a.effect(function*(){t.registerProfileCommand(r,i),yield()=>void 0},`@agimon-ai/doompi-profile`)}catch(e){throw await s(),e}r.on(`session_shutdown`,s)}exports.default=r,exports.profileExtension=r;
1
+ const e=require("../telemetry/logSinkTelemetry.cjs"),t=require("../../commands/profileCommand.cjs");let n=require("@agimon-ai/doompi-extension-contracts/config"),r=require("@agimon-ai/doompi-extension-contracts/cordis-host"),i=require("@agimon-ai/doompi-extension-contracts/transition");const a=`@agimon-ai/doompi-profile`;async function o(t,n=e.createProfileTelemetry()){let i=await(0,r.connectDoomCordisHost)(t,a),o=i.root.plugin(s,{pi:t,telemetry:n});try{await o}catch(e){try{await o.dispose()}finally{await i.dispose()}throw e}let c;t.on(`session_shutdown`,()=>c??=(async()=>{try{await o.dispose()}finally{await i.dispose()}})())}function s(e,r){let o;e.inject([n.DOOM_CONFIG_SERVICE,i.DOOM_TRANSITION_SERVICE],e=>(o=e,()=>{o===e&&(o=void 0)}));let s=()=>{if(!o)throw Error(`Doom profile runtime is waiting for the session config service.`);return o};e.effect(function*(){t.registerProfileCommand(r.pi,r.telemetry,s),yield()=>void 0},a)}exports.default=o,exports.profileExtension=o;
2
2
  //# sourceMappingURL=extension.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.cjs","names":["createProfileTelemetry","Context"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerProfileCommand } from '../../commands/profileCommand.ts';\nimport type { ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-profile';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\n\n/**\n * The package's single standard Pi factory, and the owner of the cordis Context.\n *\n * Pi can reload an extension in-process, so every registration is yielded to the\n * fiber and one dispose on session shutdown unwinds them in reverse.\n */\nexport async function profileExtension(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry = createProfileTelemetry(),\n): Promise<void> {\n const cordis = new Context();\n let disposal: Promise<void> | undefined;\n const dispose = (): Promise<void> => {\n disposal ??= cordis.fiber.dispose();\n return disposal;\n };\n\n try {\n cordis.effect(function* () {\n registerProfileCommand(pi, telemetry);\n // Pi owns command deregistration across a reload, so the fiber only has to\n // drop this package's own reference to the session.\n yield () => undefined;\n }, PACKAGE_SOURCE);\n } catch (error) {\n await dispose();\n throw error;\n }\n\n pi.on(SESSION_SHUTDOWN_EVENT, dispose);\n}\n\nexport default profileExtension;\n"],"mappings":"yIAeA,eAAsB,EACpB,EACA,EAA8BA,EAAAA,uBAAuB,EACtC,CACf,IAAM,EAAS,IAAIC,EAAAA,QACf,EACE,OACJ,IAAa,EAAO,MAAM,QAAQ,EAC3B,GAGT,GAAI,CACF,EAAO,OAAO,WAAa,CACzB,EAAA,uBAAuB,EAAI,CAAS,EAGpC,SAAY,IAAA,EACd,EAAG,2BAAc,CACnB,OAAS,EAAO,CAEd,MADA,MAAM,EAAQ,EACR,CACR,CAEA,EAAG,GAAG,mBAAwB,CAAO,CACvC"}
1
+ {"version":3,"file":"extension.cjs","names":["createProfileTelemetry","connectDoomCordisHost","DOOM_CONFIG_SERVICE","DOOM_TRANSITION_SERVICE"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { DOOM_CONFIG_SERVICE } from '@agimon-ai/doompi-extension-contracts/config';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_TRANSITION_SERVICE } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerProfileCommand } from '../../commands/profileCommand.ts';\nimport type { ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-profile';\n\n/**\n * The package's single standard Pi factory.\n */\nexport async function profileExtension(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry = createProfileTelemetry(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin(profilePlugin, { pi, telemetry });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface ProfilePluginConfig {\n readonly pi: ExtensionAPI;\n readonly telemetry: ProfileTelemetry;\n}\n\nfunction profilePlugin(cordis: Context, config: ProfilePluginConfig): void {\n let activeContext: Context | undefined;\n cordis.inject([DOOM_CONFIG_SERVICE, DOOM_TRANSITION_SERVICE], (context) => {\n activeContext = context;\n return () => {\n if (activeContext === context) activeContext = undefined;\n };\n });\n const requireRuntimeContext = (): Context => {\n if (!activeContext) throw new Error('Doom profile runtime is waiting for the session config service.');\n return activeContext;\n };\n cordis.effect(function* () {\n registerProfileCommand(config.pi, config.telemetry, requireRuntimeContext);\n yield () => undefined;\n }, PACKAGE_SOURCE);\n}\n\nexport default profileExtension;\n"],"mappings":"+RASA,MAAM,EAAiB,4BAKvB,eAAsB,EACpB,EACA,EAA8BA,EAAAA,uBAAuB,EACtC,CACf,IAAM,EAAa,MAAA,EAAMC,EAAAA,sBAAAA,CAAsB,EAAI,CAAc,EAC3D,EAAQ,EAAW,KAAK,OAAO,EAAe,CAAE,KAAI,WAAU,CAAC,EACrE,GAAI,CACF,MAAM,CACR,OAAS,EAAO,CACd,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACA,MAAM,CACR,CACA,IAAI,EACJ,EAAG,GACD,uBAEG,KAAc,SAAY,CACzB,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACF,EAAA,CAAG,CACP,CACF,CAOA,SAAS,EAAc,EAAiB,EAAmC,CACzE,IAAI,EACJ,EAAO,OAAO,CAACC,EAAAA,oBAAqBC,EAAAA,uBAAuB,EAAI,IAC7D,EAAgB,MACH,CACP,IAAkB,IAAS,EAAgB,IAAA,GACjD,EACD,EACD,IAAM,MAAuC,CAC3C,GAAI,CAAC,EAAe,MAAU,MAAM,iEAAiE,EACrG,OAAO,CACT,EACA,EAAO,OAAO,WAAa,CACzB,EAAA,uBAAuB,EAAO,GAAI,EAAO,UAAW,CAAqB,EACzE,SAAY,IAAA,EACd,EAAG,CAAc,CACnB"}
@@ -2,10 +2,7 @@ import { ProfileTelemetry } from "../../types/telemetry.cjs";
2
2
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  //#region src/adapters/pi/extension.d.ts
4
4
  /**
5
- * The package's single standard Pi factory, and the owner of the cordis Context.
6
- *
7
- * Pi can reload an extension in-process, so every registration is yielded to the
8
- * fiber and one dispose on session shutdown unwinds them in reverse.
5
+ * The package's single standard Pi factory.
9
6
  */
10
7
  declare function profileExtension(pi: ExtensionAPI, telemetry?: ProfileTelemetry): Promise<void>;
11
8
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;;;;iBAesB,iBACpB,IAAI,cACJ,YAAW,mBACV"}
1
+ {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;iBAcsB,iBACpB,IAAI,cACJ,YAAW,mBACV"}
@@ -2,10 +2,7 @@ import { ProfileTelemetry } from "../../types/telemetry.mjs";
2
2
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  //#region src/adapters/pi/extension.d.ts
4
4
  /**
5
- * The package's single standard Pi factory, and the owner of the cordis Context.
6
- *
7
- * Pi can reload an extension in-process, so every registration is yielded to the
8
- * fiber and one dispose on session shutdown unwinds them in reverse.
5
+ * The package's single standard Pi factory.
9
6
  */
10
7
  declare function profileExtension(pi: ExtensionAPI, telemetry?: ProfileTelemetry): Promise<void>;
11
8
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;;;;iBAesB,iBACpB,IAAI,cACJ,YAAW,mBACV"}
1
+ {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;iBAcsB,iBACpB,IAAI,cACJ,YAAW,mBACV"}
@@ -1,2 +1,2 @@
1
- import{createProfileTelemetry as e}from"../telemetry/logSinkTelemetry.mjs";import{registerProfileCommand as t}from"../../commands/profileCommand.mjs";import{Context as n}from"@deepseek-ai/cordis";async function r(r,i=e()){let a=new n,o,s=()=>(o??=a.fiber.dispose(),o);try{a.effect(function*(){t(r,i),yield()=>void 0},`@agimon-ai/doompi-profile`)}catch(e){throw await s(),e}r.on(`session_shutdown`,s)}export{r as default,r as profileExtension};
1
+ import{createProfileTelemetry as e}from"../telemetry/logSinkTelemetry.mjs";import{registerProfileCommand as t}from"../../commands/profileCommand.mjs";import{DOOM_CONFIG_SERVICE as n}from"@agimon-ai/doompi-extension-contracts/config";import{connectDoomCordisHost as r}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_TRANSITION_SERVICE as i}from"@agimon-ai/doompi-extension-contracts/transition";const a=`@agimon-ai/doompi-profile`;async function o(t,n=e()){let i=await r(t,a),o=i.root.plugin(s,{pi:t,telemetry:n});try{await o}catch(e){try{await o.dispose()}finally{await i.dispose()}throw e}let c;t.on(`session_shutdown`,()=>c??=(async()=>{try{await o.dispose()}finally{await i.dispose()}})())}function s(e,r){let o;e.inject([n,i],e=>(o=e,()=>{o===e&&(o=void 0)}));let s=()=>{if(!o)throw Error(`Doom profile runtime is waiting for the session config service.`);return o};e.effect(function*(){t(r.pi,r.telemetry,s),yield()=>void 0},a)}export{o as default,o as profileExtension};
2
2
  //# sourceMappingURL=extension.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerProfileCommand } from '../../commands/profileCommand.ts';\nimport type { ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-profile';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\n\n/**\n * The package's single standard Pi factory, and the owner of the cordis Context.\n *\n * Pi can reload an extension in-process, so every registration is yielded to the\n * fiber and one dispose on session shutdown unwinds them in reverse.\n */\nexport async function profileExtension(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry = createProfileTelemetry(),\n): Promise<void> {\n const cordis = new Context();\n let disposal: Promise<void> | undefined;\n const dispose = (): Promise<void> => {\n disposal ??= cordis.fiber.dispose();\n return disposal;\n };\n\n try {\n cordis.effect(function* () {\n registerProfileCommand(pi, telemetry);\n // Pi owns command deregistration across a reload, so the fiber only has to\n // drop this package's own reference to the session.\n yield () => undefined;\n }, PACKAGE_SOURCE);\n } catch (error) {\n await dispose();\n throw error;\n }\n\n pi.on(SESSION_SHUTDOWN_EVENT, dispose);\n}\n\nexport default profileExtension;\n"],"mappings":"oMAeA,eAAsB,EACpB,EACA,EAA8B,EAAuB,EACtC,CACf,IAAM,EAAS,IAAI,EACf,EACE,OACJ,IAAa,EAAO,MAAM,QAAQ,EAC3B,GAGT,GAAI,CACF,EAAO,OAAO,WAAa,CACzB,EAAuB,EAAI,CAAS,EAGpC,SAAY,IAAA,EACd,EAAG,2BAAc,CACnB,OAAS,EAAO,CAEd,MADA,MAAM,EAAQ,EACR,CACR,CAEA,EAAG,GAAG,mBAAwB,CAAO,CACvC"}
1
+ {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { DOOM_CONFIG_SERVICE } from '@agimon-ai/doompi-extension-contracts/config';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_TRANSITION_SERVICE } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { registerProfileCommand } from '../../commands/profileCommand.ts';\nimport type { ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-profile';\n\n/**\n * The package's single standard Pi factory.\n */\nexport async function profileExtension(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry = createProfileTelemetry(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin(profilePlugin, { pi, telemetry });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface ProfilePluginConfig {\n readonly pi: ExtensionAPI;\n readonly telemetry: ProfileTelemetry;\n}\n\nfunction profilePlugin(cordis: Context, config: ProfilePluginConfig): void {\n let activeContext: Context | undefined;\n cordis.inject([DOOM_CONFIG_SERVICE, DOOM_TRANSITION_SERVICE], (context) => {\n activeContext = context;\n return () => {\n if (activeContext === context) activeContext = undefined;\n };\n });\n const requireRuntimeContext = (): Context => {\n if (!activeContext) throw new Error('Doom profile runtime is waiting for the session config service.');\n return activeContext;\n };\n cordis.effect(function* () {\n registerProfileCommand(config.pi, config.telemetry, requireRuntimeContext);\n yield () => undefined;\n }, PACKAGE_SOURCE);\n}\n\nexport default profileExtension;\n"],"mappings":"8ZASA,MAAM,EAAiB,4BAKvB,eAAsB,EACpB,EACA,EAA8B,EAAuB,EACtC,CACf,IAAM,EAAa,MAAM,EAAsB,EAAI,CAAc,EAC3D,EAAQ,EAAW,KAAK,OAAO,EAAe,CAAE,KAAI,WAAU,CAAC,EACrE,GAAI,CACF,MAAM,CACR,OAAS,EAAO,CACd,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACA,MAAM,CACR,CACA,IAAI,EACJ,EAAG,GACD,uBAEG,KAAc,SAAY,CACzB,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACF,EAAA,CAAG,CACP,CACF,CAOA,SAAS,EAAc,EAAiB,EAAmC,CACzE,IAAI,EACJ,EAAO,OAAO,CAAC,EAAqB,CAAuB,EAAI,IAC7D,EAAgB,MACH,CACP,IAAkB,IAAS,EAAgB,IAAA,GACjD,EACD,EACD,IAAM,MAAuC,CAC3C,GAAI,CAAC,EAAe,MAAU,MAAM,iEAAiE,EACrG,OAAO,CACT,EACA,EAAO,OAAO,WAAa,CACzB,EAAuB,EAAO,GAAI,EAAO,UAAW,CAAqB,EACzE,SAAY,IAAA,EACd,EAAG,CAAc,CACnB"}
@@ -1,2 +1,2 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../telemetry/logSinkTelemetry.cjs"),n=require("../../types/telemetry.cjs");let r=require("node:fs");r=e.__toESM(r,1);let i=require("@agimon-ai/doompi-config/piContext");function a(e,a=t.createProfileTelemetry()){e.on(`before_agent_start`,async(e,t)=>{let{personaFile:o}=(0,i.requireDoomConfigContext)(t).harness;if(o)try{let t=(await r.default.promises.readFile(o,`utf8`)).trim();return t?{systemPrompt:`${e.systemPrompt}\n\n${t}`}:void 0}catch(e){let t=e instanceof Error?e.message:String(e);a.recordError(n.PROFILE_EVENT.personaReadFailed,e),process.stderr.write(`[pi-persona] could not read ${o}: ${t}\n`);return}})}exports.default=a,exports.personaExtension=a;
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../telemetry/logSinkTelemetry.cjs"),n=require("../../types/telemetry.cjs");let r=require("node:fs");r=e.__toESM(r,1);let i=require("@agimon-ai/doompi-config"),a=require("@agimon-ai/doompi-extension-contracts/config"),o=require("@agimon-ai/doompi-extension-contracts/cordis-host");function s(e,{pi:t,telemetry:n}){let r;e.inject([a.DOOM_CONFIG_SERVICE],e=>(r=e,()=>{r===e&&(r=void 0)})),c(t,n,()=>{if(!r)throw Error(`Doom persona runtime is waiting for the session config service.`);return r})}function c(e,t,a){e.on(`before_agent_start`,async(e,o)=>{let{personaFile:s}=(0,i.requireDoomConfigContext)(a()).harness;if(s)try{let t=(await r.default.promises.readFile(s,`utf8`)).trim();return t?{systemPrompt:`${e.systemPrompt}\n\n${t}`}:void 0}catch(e){let r=e instanceof Error?e.message:String(e);t.recordError(n.PROFILE_EVENT.personaReadFailed,e),process.stderr.write(`[pi-persona] could not read ${s}: ${r}\n`);return}})}async function l(e,n=t.createProfileTelemetry()){let r=await(0,o.connectDoomCordisHost)(e,`@agimon-ai/doompi-profile/persona`),i=r.root.plugin(s,{pi:e,telemetry:n});try{await i}catch(e){throw await i.dispose(),await r.dispose(),e}let a;e.on(`session_shutdown`,()=>a??=(async()=>{try{await i.dispose()}finally{await r.dispose()}})())}exports.default=l,exports.personaExtension=l,exports.registerPersonaHandlers=c;
2
2
  //# sourceMappingURL=persona.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"persona.cjs","names":["createProfileTelemetry","requireDoomConfigContext","fs","PROFILE_EVENT"],"sources":["../../../src/adapters/pi/persona.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\n/**\n * Appends the selected profile's persona to the system prompt.\n *\n * The harness writes the assembled persona to a file in the run directory and\n * records the path in the harness state, so agents/ stays the single source of\n * persona material and is never copied into config.\n *\n * This is a separate Pi entry from the /profile command because detached\n * children need the persona without the command: they have no transition\n * coordinator to run a switch through.\n */\nexport function personaExtension(pi: ExtensionAPI, telemetry: ProfileTelemetry = createProfileTelemetry()): void {\n pi.on('before_agent_start', async (event, ctx) => {\n const { personaFile } = requireDoomConfigContext(ctx).harness;\n if (!personaFile) return undefined;\n\n try {\n const content = (await fs.promises.readFile(personaFile, 'utf8')).trim();\n return content ? { systemPrompt: `${event.systemPrompt}\\n\\n${content}` } : undefined;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.personaReadFailed, error);\n process.stderr.write(`[pi-persona] could not read ${personaFile}: ${reason}\\n`);\n return undefined;\n }\n });\n}\n\nexport default personaExtension;\n"],"mappings":"4OAiBA,SAAgB,EAAiB,EAAkB,EAA8BA,EAAAA,uBAAuB,EAAS,CAC/G,EAAG,GAAG,qBAAsB,MAAO,EAAO,IAAQ,CAChD,GAAM,CAAE,gBAAA,EAAgBC,EAAAA,yBAAAA,CAAyB,CAAG,CAAC,CAAC,QACjD,KAEL,GAAI,CACF,IAAM,GAAW,MAAMC,EAAAA,QAAG,SAAS,SAAS,EAAa,MAAM,EAAA,CAAG,KAAK,EACvE,OAAO,EAAU,CAAE,aAAc,GAAG,EAAM,aAAa,MAAM,GAAU,EAAI,IAAA,EAC7E,OAAS,EAAO,CACd,IAAM,EAAS,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACpE,EAAe,YAAYC,EAAAA,cAAc,kBAAmB,CAAK,EACjE,QAAQ,OAAO,MAAM,+BAA+B,EAAY,IAAI,EAAO,GAAG,EAC9E,MACF,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"persona.cjs","names":["DOOM_CONFIG_SERVICE","requireDoomConfigContext","fs","PROFILE_EVENT","createProfileTelemetry","connectDoomCordisHost"],"sources":["../../../src/adapters/pi/persona.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config';\nimport { DOOM_CONFIG_SERVICE } from '@agimon-ai/doompi-extension-contracts/config';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\n/**\n * Appends the selected profile's persona to the system prompt.\n *\n * The harness writes the assembled persona to a file in the run directory and\n * records the path in the harness state, so agents/ stays the single source of\n * persona material and is never copied into config.\n *\n * This is a separate Pi entry from the /profile command because detached\n * children need the persona without the command: they have no transition\n * coordinator to run a switch through.\n */\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-profile/persona';\n\ninterface PersonaPluginConfig {\n readonly pi: ExtensionAPI;\n readonly telemetry: ProfileTelemetry;\n}\n\nfunction personaPlugin(cordis: Context, { pi, telemetry }: PersonaPluginConfig): void {\n let activeContext: Context | undefined;\n cordis.inject([DOOM_CONFIG_SERVICE], (context) => {\n activeContext = context;\n return () => {\n if (activeContext === context) activeContext = undefined;\n };\n });\n registerPersonaHandlers(pi, telemetry, () => {\n if (!activeContext) throw new Error('Doom persona runtime is waiting for the session config service.');\n return activeContext;\n });\n}\n\nexport function registerPersonaHandlers(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry,\n cordisContext: () => Context,\n): void {\n pi.on('before_agent_start', async (event, _ctx) => {\n const { personaFile } = requireDoomConfigContext(cordisContext()).harness;\n if (!personaFile) return undefined;\n\n try {\n const content = (await fs.promises.readFile(personaFile, 'utf8')).trim();\n return content ? { systemPrompt: `${event.systemPrompt}\\n\\n${content}` } : undefined;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.personaReadFailed, error);\n process.stderr.write(`[pi-persona] could not read ${personaFile}: ${reason}\\n`);\n return undefined;\n }\n });\n}\n\nexport async function personaExtension(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry = createProfileTelemetry(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin(personaPlugin, { pi, telemetry });\n try {\n await fiber;\n } catch (error) {\n await fiber.dispose();\n await connection.dispose();\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nexport default personaExtension;\n"],"mappings":"2VA2BA,SAAS,EAAc,EAAiB,CAAE,KAAI,aAAwC,CACpF,IAAI,EACJ,EAAO,OAAO,CAACA,EAAAA,mBAAmB,EAAI,IACpC,EAAgB,MACH,CACP,IAAkB,IAAS,EAAgB,IAAA,GACjD,EACD,EACD,EAAwB,EAAI,MAAiB,CAC3C,GAAI,CAAC,EAAe,MAAU,MAAM,iEAAiE,EACrG,OAAO,CACT,CAAC,CACH,CAEA,SAAgB,EACd,EACA,EACA,EACM,CACN,EAAG,GAAG,qBAAsB,MAAO,EAAO,IAAS,CACjD,GAAM,CAAE,gBAAA,EAAgBC,EAAAA,yBAAAA,CAAyB,EAAc,CAAC,CAAC,CAAC,QAC7D,KAEL,GAAI,CACF,IAAM,GAAW,MAAMC,EAAAA,QAAG,SAAS,SAAS,EAAa,MAAM,EAAA,CAAG,KAAK,EACvE,OAAO,EAAU,CAAE,aAAc,GAAG,EAAM,aAAa,MAAM,GAAU,EAAI,IAAA,EAC7E,OAAS,EAAO,CACd,IAAM,EAAS,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACpE,EAAe,YAAYC,EAAAA,cAAc,kBAAmB,CAAK,EACjE,QAAQ,OAAO,MAAM,+BAA+B,EAAY,IAAI,EAAO,GAAG,EAC9E,MACF,CACF,CAAC,CACH,CAEA,eAAsB,EACpB,EACA,EAA8BC,EAAAA,uBAAuB,EACtC,CACf,IAAM,EAAa,MAAA,EAAMC,EAAAA,sBAAAA,CAAsB,EAAI,mCAAc,EAC3D,EAAQ,EAAW,KAAK,OAAO,EAAe,CAAE,KAAI,WAAU,CAAC,EACrE,GAAI,CACF,MAAM,CACR,OAAS,EAAO,CAGd,MAFA,MAAM,EAAM,QAAQ,EACpB,MAAM,EAAW,QAAQ,EACnB,CACR,CACA,IAAI,EACJ,EAAG,GACD,uBAEG,KAAc,SAAY,CACzB,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACF,EAAA,CAAG,CACP,CACF"}
@@ -1,18 +1,8 @@
1
1
  import { ProfileTelemetry } from "../../types/telemetry.cjs";
2
+ import "@deepseek-ai/cordis";
2
3
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
4
  //#region src/adapters/pi/persona.d.ts
4
- /**
5
- * Appends the selected profile's persona to the system prompt.
6
- *
7
- * The harness writes the assembled persona to a file in the run directory and
8
- * records the path in the harness state, so agents/ stays the single source of
9
- * persona material and is never copied into config.
10
- *
11
- * This is a separate Pi entry from the /profile command because detached
12
- * children need the persona without the command: they have no transition
13
- * coordinator to run a switch through.
14
- */
15
- declare function personaExtension(pi: ExtensionAPI, telemetry?: ProfileTelemetry): void;
5
+ declare function personaExtension(pi: ExtensionAPI, telemetry?: ProfileTelemetry): Promise<void>;
16
6
  //#endregion
17
7
  export { personaExtension as default, personaExtension };
18
8
  //# sourceMappingURL=persona.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persona.d.cts","names":[],"sources":["../../../src/adapters/pi/persona.ts"],"mappings":";;;;;;;;;;;;;;iBAiBgB,iBAAiB,IAAI,cAAc,YAAW"}
1
+ {"version":3,"file":"persona.d.cts","names":[],"sources":["../../../src/adapters/pi/persona.ts"],"mappings":";;;;iBA8DsB,iBACpB,IAAI,cACJ,YAAW,mBACV"}
@@ -1,18 +1,8 @@
1
1
  import { ProfileTelemetry } from "../../types/telemetry.mjs";
2
+ import "@deepseek-ai/cordis";
2
3
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
4
  //#region src/adapters/pi/persona.d.ts
4
- /**
5
- * Appends the selected profile's persona to the system prompt.
6
- *
7
- * The harness writes the assembled persona to a file in the run directory and
8
- * records the path in the harness state, so agents/ stays the single source of
9
- * persona material and is never copied into config.
10
- *
11
- * This is a separate Pi entry from the /profile command because detached
12
- * children need the persona without the command: they have no transition
13
- * coordinator to run a switch through.
14
- */
15
- declare function personaExtension(pi: ExtensionAPI, telemetry?: ProfileTelemetry): void;
5
+ declare function personaExtension(pi: ExtensionAPI, telemetry?: ProfileTelemetry): Promise<void>;
16
6
  //#endregion
17
7
  export { personaExtension as default, personaExtension };
18
8
  //# sourceMappingURL=persona.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persona.d.mts","names":[],"sources":["../../../src/adapters/pi/persona.ts"],"mappings":";;;;;;;;;;;;;;iBAiBgB,iBAAiB,IAAI,cAAc,YAAW"}
1
+ {"version":3,"file":"persona.d.mts","names":[],"sources":["../../../src/adapters/pi/persona.ts"],"mappings":";;;;iBA8DsB,iBACpB,IAAI,cACJ,YAAW,mBACV"}
@@ -1,2 +1,2 @@
1
- import{createProfileTelemetry as e}from"../telemetry/logSinkTelemetry.mjs";import{PROFILE_EVENT as t}from"../../types/telemetry.mjs";import n from"node:fs";import{requireDoomConfigContext as r}from"@agimon-ai/doompi-config/piContext";function i(i,a=e()){i.on(`before_agent_start`,async(e,i)=>{let{personaFile:o}=r(i).harness;if(o)try{let t=(await n.promises.readFile(o,`utf8`)).trim();return t?{systemPrompt:`${e.systemPrompt}\n\n${t}`}:void 0}catch(e){let n=e instanceof Error?e.message:String(e);a.recordError(t.personaReadFailed,e),process.stderr.write(`[pi-persona] could not read ${o}: ${n}\n`);return}})}export{i as default,i as personaExtension};
1
+ import{createProfileTelemetry as e}from"../telemetry/logSinkTelemetry.mjs";import{PROFILE_EVENT as t}from"../../types/telemetry.mjs";import n from"node:fs";import{requireDoomConfigContext as r}from"@agimon-ai/doompi-config";import{DOOM_CONFIG_SERVICE as i}from"@agimon-ai/doompi-extension-contracts/config";import{connectDoomCordisHost as a}from"@agimon-ai/doompi-extension-contracts/cordis-host";function o(e,{pi:t,telemetry:n}){let r;e.inject([i],e=>(r=e,()=>{r===e&&(r=void 0)})),s(t,n,()=>{if(!r)throw Error(`Doom persona runtime is waiting for the session config service.`);return r})}function s(e,i,a){e.on(`before_agent_start`,async(e,o)=>{let{personaFile:s}=r(a()).harness;if(s)try{let t=(await n.promises.readFile(s,`utf8`)).trim();return t?{systemPrompt:`${e.systemPrompt}\n\n${t}`}:void 0}catch(e){let n=e instanceof Error?e.message:String(e);i.recordError(t.personaReadFailed,e),process.stderr.write(`[pi-persona] could not read ${s}: ${n}\n`);return}})}async function c(t,n=e()){let r=await a(t,`@agimon-ai/doompi-profile/persona`),i=r.root.plugin(o,{pi:t,telemetry:n});try{await i}catch(e){throw await i.dispose(),await r.dispose(),e}let s;t.on(`session_shutdown`,()=>s??=(async()=>{try{await i.dispose()}finally{await r.dispose()}})())}export{c as default,c as personaExtension,s as registerPersonaHandlers};
2
2
  //# sourceMappingURL=persona.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"persona.mjs","names":[],"sources":["../../../src/adapters/pi/persona.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\n/**\n * Appends the selected profile's persona to the system prompt.\n *\n * The harness writes the assembled persona to a file in the run directory and\n * records the path in the harness state, so agents/ stays the single source of\n * persona material and is never copied into config.\n *\n * This is a separate Pi entry from the /profile command because detached\n * children need the persona without the command: they have no transition\n * coordinator to run a switch through.\n */\nexport function personaExtension(pi: ExtensionAPI, telemetry: ProfileTelemetry = createProfileTelemetry()): void {\n pi.on('before_agent_start', async (event, ctx) => {\n const { personaFile } = requireDoomConfigContext(ctx).harness;\n if (!personaFile) return undefined;\n\n try {\n const content = (await fs.promises.readFile(personaFile, 'utf8')).trim();\n return content ? { systemPrompt: `${event.systemPrompt}\\n\\n${content}` } : undefined;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.personaReadFailed, error);\n process.stderr.write(`[pi-persona] could not read ${personaFile}: ${reason}\\n`);\n return undefined;\n }\n });\n}\n\nexport default personaExtension;\n"],"mappings":"0OAiBA,SAAgB,EAAiB,EAAkB,EAA8B,EAAuB,EAAS,CAC/G,EAAG,GAAG,qBAAsB,MAAO,EAAO,IAAQ,CAChD,GAAM,CAAE,eAAgB,EAAyB,CAAG,CAAC,CAAC,QACjD,KAEL,GAAI,CACF,IAAM,GAAW,MAAM,EAAG,SAAS,SAAS,EAAa,MAAM,EAAA,CAAG,KAAK,EACvE,OAAO,EAAU,CAAE,aAAc,GAAG,EAAM,aAAa,MAAM,GAAU,EAAI,IAAA,EAC7E,OAAS,EAAO,CACd,IAAM,EAAS,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACpE,EAAe,YAAY,EAAc,kBAAmB,CAAK,EACjE,QAAQ,OAAO,MAAM,+BAA+B,EAAY,IAAI,EAAO,GAAG,EAC9E,MACF,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"persona.mjs","names":[],"sources":["../../../src/adapters/pi/persona.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config';\nimport { DOOM_CONFIG_SERVICE } from '@agimon-ai/doompi-extension-contracts/config';\nimport { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../../types/telemetry.ts';\nimport { createProfileTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\n/**\n * Appends the selected profile's persona to the system prompt.\n *\n * The harness writes the assembled persona to a file in the run directory and\n * records the path in the harness state, so agents/ stays the single source of\n * persona material and is never copied into config.\n *\n * This is a separate Pi entry from the /profile command because detached\n * children need the persona without the command: they have no transition\n * coordinator to run a switch through.\n */\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-profile/persona';\n\ninterface PersonaPluginConfig {\n readonly pi: ExtensionAPI;\n readonly telemetry: ProfileTelemetry;\n}\n\nfunction personaPlugin(cordis: Context, { pi, telemetry }: PersonaPluginConfig): void {\n let activeContext: Context | undefined;\n cordis.inject([DOOM_CONFIG_SERVICE], (context) => {\n activeContext = context;\n return () => {\n if (activeContext === context) activeContext = undefined;\n };\n });\n registerPersonaHandlers(pi, telemetry, () => {\n if (!activeContext) throw new Error('Doom persona runtime is waiting for the session config service.');\n return activeContext;\n });\n}\n\nexport function registerPersonaHandlers(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry,\n cordisContext: () => Context,\n): void {\n pi.on('before_agent_start', async (event, _ctx) => {\n const { personaFile } = requireDoomConfigContext(cordisContext()).harness;\n if (!personaFile) return undefined;\n\n try {\n const content = (await fs.promises.readFile(personaFile, 'utf8')).trim();\n return content ? { systemPrompt: `${event.systemPrompt}\\n\\n${content}` } : undefined;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.personaReadFailed, error);\n process.stderr.write(`[pi-persona] could not read ${personaFile}: ${reason}\\n`);\n return undefined;\n }\n });\n}\n\nexport async function personaExtension(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry = createProfileTelemetry(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin(personaPlugin, { pi, telemetry });\n try {\n await fiber;\n } catch (error) {\n await fiber.dispose();\n await connection.dispose();\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\nexport default personaExtension;\n"],"mappings":"6YA2BA,SAAS,EAAc,EAAiB,CAAE,KAAI,aAAwC,CACpF,IAAI,EACJ,EAAO,OAAO,CAAC,CAAmB,EAAI,IACpC,EAAgB,MACH,CACP,IAAkB,IAAS,EAAgB,IAAA,GACjD,EACD,EACD,EAAwB,EAAI,MAAiB,CAC3C,GAAI,CAAC,EAAe,MAAU,MAAM,iEAAiE,EACrG,OAAO,CACT,CAAC,CACH,CAEA,SAAgB,EACd,EACA,EACA,EACM,CACN,EAAG,GAAG,qBAAsB,MAAO,EAAO,IAAS,CACjD,GAAM,CAAE,eAAgB,EAAyB,EAAc,CAAC,CAAC,CAAC,QAC7D,KAEL,GAAI,CACF,IAAM,GAAW,MAAM,EAAG,SAAS,SAAS,EAAa,MAAM,EAAA,CAAG,KAAK,EACvE,OAAO,EAAU,CAAE,aAAc,GAAG,EAAM,aAAa,MAAM,GAAU,EAAI,IAAA,EAC7E,OAAS,EAAO,CACd,IAAM,EAAS,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACpE,EAAe,YAAY,EAAc,kBAAmB,CAAK,EACjE,QAAQ,OAAO,MAAM,+BAA+B,EAAY,IAAI,EAAO,GAAG,EAC9E,MACF,CACF,CAAC,CACH,CAEA,eAAsB,EACpB,EACA,EAA8B,EAAuB,EACtC,CACf,IAAM,EAAa,MAAM,EAAsB,EAAI,mCAAc,EAC3D,EAAQ,EAAW,KAAK,OAAO,EAAe,CAAE,KAAI,WAAU,CAAC,EACrE,GAAI,CACF,MAAM,CACR,OAAS,EAAO,CAGd,MAFA,MAAM,EAAM,QAAQ,EACpB,MAAM,EAAW,QAAQ,EACnB,CACR,CACA,IAAI,EACJ,EAAG,GACD,uBAEG,KAAc,SAAY,CACzB,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACF,EAAA,CAAG,CACP,CACF"}
@@ -1,2 +1,2 @@
1
- const e=require("../types/telemetry.cjs"),t=require("../services/profileText.cjs");let n=require("@agimon-ai/doompi-config/piContext"),r=require("@agimon-ai/doompi-extension-contracts/transition");const i=`warning`,a=`info`,o=`.doom/profiles.yaml`;function s(){let e,t,n,r,i;return{harnessStore:()=>e??=import(`@agimon-ai/doompi-config/harnessStore`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),profiles:()=>r??=import(`@agimon-ai/doompi-config/profiles`),selection:()=>i??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}async function c(e,n,r,i){let a=t.profileTitle(r);if(e.mode!==`tui`)return e.ui.select(a,n.map(e=>e.name));let{MatrixPickerComponent:o}=await i();return(await e.ui.custom((e,i,s,c)=>new o({title:a,items:t.profileItems(n),selected:r?[r]:[],multi:!1},i,s,c)))?.[0]}function l(l,u){let d=s();l.registerCommand(`profile`,{description:`Show profiles and load a different persona and environment`,handler:async(s,f)=>{let p=(0,n.requireDoomConfigContext)(f).harness,[{requireHarnessRoot:m},{loadProfiles:h}]=await Promise.all([d.harnessStore(),d.profiles()]),g=m(p),_=p.profile,v;try{v=h(g)}catch(t){let n=t instanceof Error?t.message:String(t);u.recordError(e.PROFILE_EVENT.profileLoadFailed,t),f.ui.notify(`Could not load ${o}: ${n}`,i);return}if(v.length===0){f.ui.notify(`No profiles found in ${o}.`,i);return}let y=await c(f,v,_,d.picker),b=v.find(e=>e.name===y);if(!b)return;if(b.name===_){f.ui.notify(t.profileSummary(b),a);return}let x=(0,r.requireDoomTransitionCoordinator)(f),S,C=await x.execute({sessionId:f.sessionManager.getSessionId(),hostGeneration:x.hostGeneration,operationId:crypto.randomUUID(),source:f.mode===`tui`?`ui`:`command`,target:{axis:`profile`,profile:b.name}},async(t,n)=>{S=(0,r.prepareMinorModeReloadHandoff)(f,x.hostGeneration,n.operationId,n.previous.minorModes);try{let{applyProfile:t}=await d.selection();f.ui.notify(await t(b,p),a);let{persistHarnessSelection:r}=await d.journal();return r(l,{...p,profile:b.name}),u.recordEvent(e.PROFILE_EVENT.profileApplied,{"harness.profile":b.name,..._?{"harness.profile.previous":_}:{},"harness.transition.disposition":n.disposition,"harness.transition.operation_id":n.operationId}),`applied`}catch(e){throw S?.discard(),S=void 0,e}});if(C.outcome===`rejected`||C.outcome===`stale`){S?.discard(),f.ui.notify(`Profile transition was ${C.outcome}: ${C.diagnostics.join(`, `)}`,i);return}if(C.outcome!==`applied`){S?.discard();return}try{await f.waitForIdle(),await f.reload()}catch(e){throw S?.discard(),e}}})}exports.registerProfileCommand=l;
1
+ const e=require("../types/telemetry.cjs"),t=require("../services/profileText.cjs");let n=require("@agimon-ai/doompi-extension-contracts/transition"),r=require("@agimon-ai/doompi-config/piContext");const i=`warning`,a=`info`,o=`.doom/profiles.yaml`;function s(){let e,t,n,r,i;return{harnessStore:()=>e??=import(`@agimon-ai/doompi-config/harnessStore`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),profiles:()=>r??=import(`@agimon-ai/doompi-config/profiles`),selection:()=>i??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}async function c(e,n,r,i){let a=t.profileTitle(r);if(e.mode!==`tui`)return e.ui.select(a,n.map(e=>e.name));let{MatrixPickerComponent:o}=await i();return(await e.ui.custom((e,i,s,c)=>new o({title:a,items:t.profileItems(n),selected:r?[r]:[],multi:!1},i,s,c)))?.[0]}function l(l,u,d){let f=s();l.registerCommand(`profile`,{description:`Show profiles and load a different persona and environment`,handler:async(s,p)=>{let m=d(),h=(0,r.requireDoomConfigContext)(m).harness,[{requireHarnessRoot:g},{loadProfiles:_}]=await Promise.all([f.harnessStore(),f.profiles()]),v=g(h),y=h.profile,b;try{b=_(v)}catch(t){let n=t instanceof Error?t.message:String(t);u.recordError(e.PROFILE_EVENT.profileLoadFailed,t),p.ui.notify(`Could not load ${o}: ${n}`,i);return}if(b.length===0){p.ui.notify(`No profiles found in ${o}.`,i);return}let x=await c(p,b,y,f.picker),S=b.find(e=>e.name===x);if(!S)return;if(S.name===y){p.ui.notify(t.profileSummary(S),a);return}let C=(0,n.requireDoomTransitionCoordinator)(m),w,T=await C.execute({sessionId:p.sessionManager.getSessionId(),hostGeneration:C.hostGeneration,operationId:crypto.randomUUID(),source:p.mode===`tui`?`ui`:`command`,target:{axis:`profile`,profile:S.name}},async(t,r)=>{w=(0,n.prepareMinorModeReloadHandoff)(m,p.sessionManager.getSessionId(),C.hostGeneration,r.operationId,r.previous.minorModes);try{let{applyProfile:t}=await f.selection();p.ui.notify(await t(S,h),a);let{persistHarnessSelection:n}=await f.journal();return n(l,{...h,profile:S.name}),u.recordEvent(e.PROFILE_EVENT.profileApplied,{"harness.profile":S.name,...y?{"harness.profile.previous":y}:{},"harness.transition.disposition":r.disposition,"harness.transition.operation_id":r.operationId}),`applied`}catch(e){throw w?.discard(),w=void 0,e}});if(T.outcome===`rejected`||T.outcome===`stale`){w?.discard(),p.ui.notify(`Profile transition was ${T.outcome}: ${T.diagnostics.join(`, `)}`,i);return}if(T.outcome!==`applied`){w?.discard();return}try{await p.waitForIdle(),await p.reload()}catch(e){throw w?.discard(),e}}})}exports.registerProfileCommand=l;
2
2
  //# sourceMappingURL=profileCommand.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"profileCommand.cjs","names":["profileTitle","profileItems","requireDoomConfigContext","PROFILE_EVENT","profileSummary","requireDoomTransitionCoordinator","prepareMinorModeReloadHandoff"],"sources":["../../src/commands/profileCommand.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport type { AgentProfile } from '@agimon-ai/doompi-config/profiles';\nimport {\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { profileItems, profileSummary, profileTitle } from '../services/profileText.ts';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../types/telemetry.ts';\n\nconst WARNING = 'warning';\nconst INFO = 'info';\nconst PROFILE_CONFIG_PATH = '.doom/profiles.yaml';\n\n/**\n * The picker and everything behind it load on first use.\n *\n * Every session registers this command, but almost none of them run it, so the\n * profile catalogue, the TUI component and the switch stay off the startup path.\n */\nfunction lazyModules() {\n let harnessStore: Promise<typeof import('@agimon-ai/doompi-config/harnessStore')> | undefined;\n let journal: Promise<typeof import('@agimon-ai/doompi-config/piContext')> | undefined;\n let picker: Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')> | undefined;\n let profiles: Promise<typeof import('@agimon-ai/doompi-config/profiles')> | undefined;\n let selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n harnessStore: () => (harnessStore ??= import('@agimon-ai/doompi-config/harnessStore')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n profiles: () => (profiles ??= import('@agimon-ai/doompi-config/profiles')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\n\nasync function pickProfile(\n ctx: ExtensionContext,\n profiles: AgentProfile[],\n current: string | undefined,\n loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>,\n): Promise<string | undefined> {\n const title = profileTitle(current);\n if (ctx.mode !== 'tui') {\n return ctx.ui.select(\n title,\n profiles.map((profile) => profile.name),\n );\n }\n const { MatrixPickerComponent } = await loadPicker();\n const chosen = await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: profileItems(profiles), selected: current ? [current] : [], multi: false },\n theme,\n keybindings,\n done,\n ),\n );\n return chosen?.[0];\n}\n\nexport function registerProfileCommand(pi: ExtensionAPI, telemetry: ProfileTelemetry): void {\n const load = lazyModules();\n\n pi.registerCommand('profile', {\n description: 'Show profiles and load a different persona and environment',\n handler: async (_args, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n const [{ requireHarnessRoot }, { loadProfiles }] = await Promise.all([load.harnessStore(), load.profiles()]);\n const root = requireHarnessRoot(state);\n const current = state.profile;\n let profiles: AgentProfile[];\n try {\n profiles = loadProfiles(root);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.profileLoadFailed, error);\n ctx.ui.notify(`Could not load ${PROFILE_CONFIG_PATH}: ${reason}`, WARNING);\n return;\n }\n\n if (profiles.length === 0) {\n ctx.ui.notify(`No profiles found in ${PROFILE_CONFIG_PATH}.`, WARNING);\n return;\n }\n\n const picked = await pickProfile(ctx, profiles, current, load.picker);\n const profile = profiles.find((candidate) => candidate.name === picked);\n if (!profile) return;\n if (profile.name === current) {\n ctx.ui.notify(profileSummary(profile), INFO);\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(ctx);\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: crypto.randomUUID(),\n source: ctx.mode === 'tui' ? 'ui' : 'command',\n target: { axis: 'profile', profile: profile.name },\n },\n async (_request, plan) => {\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n ctx,\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n const { applyProfile } = await load.selection();\n ctx.ui.notify(await applyProfile(profile, state), INFO);\n const { persistHarnessSelection } = await load.journal();\n persistHarnessSelection(pi, { ...state, profile: profile.name });\n void telemetry.recordEvent(PROFILE_EVENT.profileApplied, {\n 'harness.profile': profile.name,\n ...(current ? { 'harness.profile.previous': current } : {}),\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n return 'applied';\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n throw error;\n }\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') {\n minorModeReloadHandoff?.discard();\n ctx.ui.notify(`Profile transition was ${result.outcome}: ${result.diagnostics.join(', ')}`, WARNING);\n return;\n }\n if (result.outcome !== 'applied') {\n minorModeReloadHandoff?.discard();\n return;\n }\n\n try {\n await ctx.waitForIdle();\n // Reload replaces the session and invalidates this command context.\n // Keep it as the handler's final action.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n },\n });\n}\n"],"mappings":"qMAWA,MAAM,EAAU,UACV,EAAO,OACP,EAAsB,sBAQ5B,SAAS,GAAc,CACrB,IAAI,EACA,EACA,EACA,EACA,EACJ,MAAO,CACL,iBAAqB,IAAiB,OAAO,yCAC7C,YAAgB,IAAY,OAAO,sCACnC,WAAe,IAAW,OAAO,gDACjC,aAAiB,IAAa,OAAO,qCACrC,cAAkB,IAAc,OAAO,2CACzC,CACF,CAEA,eAAe,EACb,EACA,EACA,EACA,EAC6B,CAC7B,IAAM,EAAQA,EAAAA,aAAa,CAAO,EAClC,GAAI,EAAI,OAAS,MACf,OAAO,EAAI,GAAG,OACZ,EACA,EAAS,IAAK,GAAY,EAAQ,IAAI,CACxC,EAEF,GAAM,CAAE,yBAA0B,MAAM,EAAW,EAUnD,OAAO,MATc,EAAI,GAAG,QACzB,EAAM,EAAO,EAAa,IACzB,IAAI,EACF,CAAE,QAAO,MAAOC,EAAAA,aAAa,CAAQ,EAAG,SAAU,EAAU,CAAC,CAAO,EAAI,CAAC,EAAG,MAAO,EAAM,EACzF,EACA,EACA,CACF,CACJ,EAAA,GACgB,EAClB,CAEA,SAAgB,EAAuB,EAAkB,EAAmC,CAC1F,IAAM,EAAO,EAAY,EAEzB,EAAG,gBAAgB,UAAW,CAC5B,YAAa,6DACb,QAAS,MAAO,EAAO,IAAQ,CAC7B,IAAM,GAAA,EAAQC,EAAAA,yBAAAA,CAAyB,CAAG,CAAC,CAAC,QACtC,CAAC,CAAE,sBAAsB,CAAE,iBAAkB,MAAM,QAAQ,IAAI,CAAC,EAAK,aAAa,EAAG,EAAK,SAAS,CAAC,CAAC,EACrG,EAAO,EAAmB,CAAK,EAC/B,EAAU,EAAM,QAClB,EACJ,GAAI,CACF,EAAW,EAAa,CAAI,CAC9B,OAAS,EAAO,CACd,IAAM,EAAS,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACpE,EAAe,YAAYC,EAAAA,cAAc,kBAAmB,CAAK,EACjE,EAAI,GAAG,OAAO,kBAAkB,EAAoB,IAAI,IAAU,CAAO,EACzE,MACF,CAEA,GAAI,EAAS,SAAW,EAAG,CACzB,EAAI,GAAG,OAAO,wBAAwB,EAAoB,GAAI,CAAO,EACrE,MACF,CAEA,IAAM,EAAS,MAAM,EAAY,EAAK,EAAU,EAAS,EAAK,MAAM,EAC9D,EAAU,EAAS,KAAM,GAAc,EAAU,OAAS,CAAM,EACtE,GAAI,CAAC,EAAS,OACd,GAAI,EAAQ,OAAS,EAAS,CAC5B,EAAI,GAAG,OAAOC,EAAAA,eAAe,CAAO,EAAG,CAAI,EAC3C,MACF,CAEA,IAAM,GAAA,EAAcC,EAAAA,iCAAAA,CAAiC,CAAG,EACpD,EACE,EAAS,MAAM,EAAY,QAC/B,CACE,UAAW,EAAI,eAAe,aAAa,EAC3C,eAAgB,EAAY,eAC5B,YAAa,OAAO,WAAW,EAC/B,OAAQ,EAAI,OAAS,MAAQ,KAAO,UACpC,OAAQ,CAAE,KAAM,UAAW,QAAS,EAAQ,IAAK,CACnD,EACA,MAAO,EAAU,IAAS,CACxB,GAAA,EAAyBC,EAAAA,8BAAAA,CACvB,EACA,EAAY,eACZ,EAAK,YACL,EAAK,SAAS,UAChB,EACA,GAAI,CACF,GAAM,CAAE,gBAAiB,MAAM,EAAK,UAAU,EAC9C,EAAI,GAAG,OAAO,MAAM,EAAa,EAAS,CAAK,EAAG,CAAI,EACtD,GAAM,CAAE,2BAA4B,MAAM,EAAK,QAAQ,EAQvD,OAPA,EAAwB,EAAI,CAAE,GAAG,EAAO,QAAS,EAAQ,IAAK,CAAC,EAC/D,EAAe,YAAYH,EAAAA,cAAc,eAAgB,CACvD,kBAAmB,EAAQ,KAC3B,GAAI,EAAU,CAAE,2BAA4B,CAAQ,EAAI,CAAC,EACzD,iCAAkC,EAAK,YACvC,kCAAmC,EAAK,WAC1C,CAAC,EACM,SACT,OAAS,EAAO,CAGd,MAFA,GAAwB,QAAQ,EAChC,EAAyB,IAAA,GACnB,CACR,CACF,CACF,EACA,GAAI,EAAO,UAAY,YAAc,EAAO,UAAY,QAAS,CAC/D,GAAwB,QAAQ,EAChC,EAAI,GAAG,OAAO,0BAA0B,EAAO,QAAQ,IAAI,EAAO,YAAY,KAAK,IAAI,IAAK,CAAO,EACnG,MACF,CACA,GAAI,EAAO,UAAY,UAAW,CAChC,GAAwB,QAAQ,EAChC,MACF,CAEA,GAAI,CACF,MAAM,EAAI,YAAY,EAGtB,MAAM,EAAI,OAAO,CACnB,OAAS,EAAO,CAEd,MADA,GAAwB,QAAQ,EAC1B,CACR,CACF,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"profileCommand.cjs","names":["profileTitle","profileItems","requireDoomConfigContext","PROFILE_EVENT","profileSummary","requireDoomTransitionCoordinator","prepareMinorModeReloadHandoff"],"sources":["../../src/commands/profileCommand.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport type { AgentProfile } from '@agimon-ai/doompi-config/profiles';\nimport {\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { Context } from '@deepseek-ai/cordis';\nimport { profileItems, profileSummary, profileTitle } from '../services/profileText.ts';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../types/telemetry.ts';\n\nconst WARNING = 'warning';\nconst INFO = 'info';\nconst PROFILE_CONFIG_PATH = '.doom/profiles.yaml';\n\n/**\n * The picker and everything behind it load on first use.\n *\n * Every session registers this command, but almost none of them run it, so the\n * profile catalogue, the TUI component and the switch stay off the startup path.\n */\nfunction lazyModules() {\n let harnessStore: Promise<typeof import('@agimon-ai/doompi-config/harnessStore')> | undefined;\n let journal: Promise<typeof import('@agimon-ai/doompi-config/piContext')> | undefined;\n let picker: Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')> | undefined;\n let profiles: Promise<typeof import('@agimon-ai/doompi-config/profiles')> | undefined;\n let selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n harnessStore: () => (harnessStore ??= import('@agimon-ai/doompi-config/harnessStore')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n profiles: () => (profiles ??= import('@agimon-ai/doompi-config/profiles')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\n\nasync function pickProfile(\n ctx: ExtensionContext,\n profiles: AgentProfile[],\n current: string | undefined,\n loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>,\n): Promise<string | undefined> {\n const title = profileTitle(current);\n if (ctx.mode !== 'tui') {\n return ctx.ui.select(\n title,\n profiles.map((profile) => profile.name),\n );\n }\n const { MatrixPickerComponent } = await loadPicker();\n const chosen = await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: profileItems(profiles), selected: current ? [current] : [], multi: false },\n theme,\n keybindings,\n done,\n ),\n );\n return chosen?.[0];\n}\n\nexport function registerProfileCommand(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry,\n cordisContext: () => Context,\n): void {\n const load = lazyModules();\n\n pi.registerCommand('profile', {\n description: 'Show profiles and load a different persona and environment',\n handler: async (_args, ctx) => {\n const cordis = cordisContext();\n const state = requireDoomConfigContext(cordis).harness;\n const [{ requireHarnessRoot }, { loadProfiles }] = await Promise.all([load.harnessStore(), load.profiles()]);\n const root = requireHarnessRoot(state);\n const current = state.profile;\n let profiles: AgentProfile[];\n try {\n profiles = loadProfiles(root);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.profileLoadFailed, error);\n ctx.ui.notify(`Could not load ${PROFILE_CONFIG_PATH}: ${reason}`, WARNING);\n return;\n }\n\n if (profiles.length === 0) {\n ctx.ui.notify(`No profiles found in ${PROFILE_CONFIG_PATH}.`, WARNING);\n return;\n }\n\n const picked = await pickProfile(ctx, profiles, current, load.picker);\n const profile = profiles.find((candidate) => candidate.name === picked);\n if (!profile) return;\n if (profile.name === current) {\n ctx.ui.notify(profileSummary(profile), INFO);\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(cordis);\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: crypto.randomUUID(),\n source: ctx.mode === 'tui' ? 'ui' : 'command',\n target: { axis: 'profile', profile: profile.name },\n },\n async (_request, plan) => {\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n cordis,\n ctx.sessionManager.getSessionId(),\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n const { applyProfile } = await load.selection();\n ctx.ui.notify(await applyProfile(profile, state), INFO);\n const { persistHarnessSelection } = await load.journal();\n persistHarnessSelection(pi, { ...state, profile: profile.name });\n void telemetry.recordEvent(PROFILE_EVENT.profileApplied, {\n 'harness.profile': profile.name,\n ...(current ? { 'harness.profile.previous': current } : {}),\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n return 'applied';\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n throw error;\n }\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') {\n minorModeReloadHandoff?.discard();\n ctx.ui.notify(`Profile transition was ${result.outcome}: ${result.diagnostics.join(', ')}`, WARNING);\n return;\n }\n if (result.outcome !== 'applied') {\n minorModeReloadHandoff?.discard();\n return;\n }\n\n try {\n await ctx.waitForIdle();\n // Reload replaces the session and invalidates this command context.\n // Keep it as the handler's final action.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n },\n });\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{PROFILE_EVENT as e}from"../types/telemetry.mjs";import{profileItems as t,profileSummary as n,profileTitle as r}from"../services/profileText.mjs";import{requireDoomConfigContext as i}from"@agimon-ai/doompi-config/piContext";import{prepareMinorModeReloadHandoff as a,requireDoomTransitionCoordinator as o}from"@agimon-ai/doompi-extension-contracts/transition";const s=`warning`,c=`info`,l=`.doom/profiles.yaml`;function u(){let e,t,n,r,i;return{harnessStore:()=>e??=import(`@agimon-ai/doompi-config/harnessStore`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),profiles:()=>r??=import(`@agimon-ai/doompi-config/profiles`),selection:()=>i??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}async function d(e,n,i,a){let o=r(i);if(e.mode!==`tui`)return e.ui.select(o,n.map(e=>e.name));let{MatrixPickerComponent:s}=await a();return(await e.ui.custom((e,r,a,c)=>new s({title:o,items:t(n),selected:i?[i]:[],multi:!1},r,a,c)))?.[0]}function f(t,r){let f=u();t.registerCommand(`profile`,{description:`Show profiles and load a different persona and environment`,handler:async(u,p)=>{let m=i(p).harness,[{requireHarnessRoot:h},{loadProfiles:g}]=await Promise.all([f.harnessStore(),f.profiles()]),_=h(m),v=m.profile,y;try{y=g(_)}catch(t){let n=t instanceof Error?t.message:String(t);r.recordError(e.profileLoadFailed,t),p.ui.notify(`Could not load ${l}: ${n}`,s);return}if(y.length===0){p.ui.notify(`No profiles found in ${l}.`,s);return}let b=await d(p,y,v,f.picker),x=y.find(e=>e.name===b);if(!x)return;if(x.name===v){p.ui.notify(n(x),c);return}let S=o(p),C,w=await S.execute({sessionId:p.sessionManager.getSessionId(),hostGeneration:S.hostGeneration,operationId:crypto.randomUUID(),source:p.mode===`tui`?`ui`:`command`,target:{axis:`profile`,profile:x.name}},async(n,i)=>{C=a(p,S.hostGeneration,i.operationId,i.previous.minorModes);try{let{applyProfile:n}=await f.selection();p.ui.notify(await n(x,m),c);let{persistHarnessSelection:a}=await f.journal();return a(t,{...m,profile:x.name}),r.recordEvent(e.profileApplied,{"harness.profile":x.name,...v?{"harness.profile.previous":v}:{},"harness.transition.disposition":i.disposition,"harness.transition.operation_id":i.operationId}),`applied`}catch(e){throw C?.discard(),C=void 0,e}});if(w.outcome===`rejected`||w.outcome===`stale`){C?.discard(),p.ui.notify(`Profile transition was ${w.outcome}: ${w.diagnostics.join(`, `)}`,s);return}if(w.outcome!==`applied`){C?.discard();return}try{await p.waitForIdle(),await p.reload()}catch(e){throw C?.discard(),e}}})}export{f as registerProfileCommand};
1
+ import{PROFILE_EVENT as e}from"../types/telemetry.mjs";import{profileItems as t,profileSummary as n,profileTitle as r}from"../services/profileText.mjs";import{prepareMinorModeReloadHandoff as i,requireDoomTransitionCoordinator as a}from"@agimon-ai/doompi-extension-contracts/transition";import{requireDoomConfigContext as o}from"@agimon-ai/doompi-config/piContext";const s=`warning`,c=`info`,l=`.doom/profiles.yaml`;function u(){let e,t,n,r,i;return{harnessStore:()=>e??=import(`@agimon-ai/doompi-config/harnessStore`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),profiles:()=>r??=import(`@agimon-ai/doompi-config/profiles`),selection:()=>i??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}async function d(e,n,i,a){let o=r(i);if(e.mode!==`tui`)return e.ui.select(o,n.map(e=>e.name));let{MatrixPickerComponent:s}=await a();return(await e.ui.custom((e,r,a,c)=>new s({title:o,items:t(n),selected:i?[i]:[],multi:!1},r,a,c)))?.[0]}function f(t,r,f){let p=u();t.registerCommand(`profile`,{description:`Show profiles and load a different persona and environment`,handler:async(u,m)=>{let h=f(),g=o(h).harness,[{requireHarnessRoot:_},{loadProfiles:v}]=await Promise.all([p.harnessStore(),p.profiles()]),y=_(g),b=g.profile,x;try{x=v(y)}catch(t){let n=t instanceof Error?t.message:String(t);r.recordError(e.profileLoadFailed,t),m.ui.notify(`Could not load ${l}: ${n}`,s);return}if(x.length===0){m.ui.notify(`No profiles found in ${l}.`,s);return}let S=await d(m,x,b,p.picker),C=x.find(e=>e.name===S);if(!C)return;if(C.name===b){m.ui.notify(n(C),c);return}let w=a(h),T,E=await w.execute({sessionId:m.sessionManager.getSessionId(),hostGeneration:w.hostGeneration,operationId:crypto.randomUUID(),source:m.mode===`tui`?`ui`:`command`,target:{axis:`profile`,profile:C.name}},async(n,a)=>{T=i(h,m.sessionManager.getSessionId(),w.hostGeneration,a.operationId,a.previous.minorModes);try{let{applyProfile:n}=await p.selection();m.ui.notify(await n(C,g),c);let{persistHarnessSelection:i}=await p.journal();return i(t,{...g,profile:C.name}),r.recordEvent(e.profileApplied,{"harness.profile":C.name,...b?{"harness.profile.previous":b}:{},"harness.transition.disposition":a.disposition,"harness.transition.operation_id":a.operationId}),`applied`}catch(e){throw T?.discard(),T=void 0,e}});if(E.outcome===`rejected`||E.outcome===`stale`){T?.discard(),m.ui.notify(`Profile transition was ${E.outcome}: ${E.diagnostics.join(`, `)}`,s);return}if(E.outcome!==`applied`){T?.discard();return}try{await m.waitForIdle(),await m.reload()}catch(e){throw T?.discard(),e}}})}export{f as registerProfileCommand};
2
2
  //# sourceMappingURL=profileCommand.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"profileCommand.mjs","names":[],"sources":["../../src/commands/profileCommand.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport type { AgentProfile } from '@agimon-ai/doompi-config/profiles';\nimport {\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { profileItems, profileSummary, profileTitle } from '../services/profileText.ts';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../types/telemetry.ts';\n\nconst WARNING = 'warning';\nconst INFO = 'info';\nconst PROFILE_CONFIG_PATH = '.doom/profiles.yaml';\n\n/**\n * The picker and everything behind it load on first use.\n *\n * Every session registers this command, but almost none of them run it, so the\n * profile catalogue, the TUI component and the switch stay off the startup path.\n */\nfunction lazyModules() {\n let harnessStore: Promise<typeof import('@agimon-ai/doompi-config/harnessStore')> | undefined;\n let journal: Promise<typeof import('@agimon-ai/doompi-config/piContext')> | undefined;\n let picker: Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')> | undefined;\n let profiles: Promise<typeof import('@agimon-ai/doompi-config/profiles')> | undefined;\n let selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n harnessStore: () => (harnessStore ??= import('@agimon-ai/doompi-config/harnessStore')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n profiles: () => (profiles ??= import('@agimon-ai/doompi-config/profiles')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\n\nasync function pickProfile(\n ctx: ExtensionContext,\n profiles: AgentProfile[],\n current: string | undefined,\n loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>,\n): Promise<string | undefined> {\n const title = profileTitle(current);\n if (ctx.mode !== 'tui') {\n return ctx.ui.select(\n title,\n profiles.map((profile) => profile.name),\n );\n }\n const { MatrixPickerComponent } = await loadPicker();\n const chosen = await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: profileItems(profiles), selected: current ? [current] : [], multi: false },\n theme,\n keybindings,\n done,\n ),\n );\n return chosen?.[0];\n}\n\nexport function registerProfileCommand(pi: ExtensionAPI, telemetry: ProfileTelemetry): void {\n const load = lazyModules();\n\n pi.registerCommand('profile', {\n description: 'Show profiles and load a different persona and environment',\n handler: async (_args, ctx) => {\n const state = requireDoomConfigContext(ctx).harness;\n const [{ requireHarnessRoot }, { loadProfiles }] = await Promise.all([load.harnessStore(), load.profiles()]);\n const root = requireHarnessRoot(state);\n const current = state.profile;\n let profiles: AgentProfile[];\n try {\n profiles = loadProfiles(root);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.profileLoadFailed, error);\n ctx.ui.notify(`Could not load ${PROFILE_CONFIG_PATH}: ${reason}`, WARNING);\n return;\n }\n\n if (profiles.length === 0) {\n ctx.ui.notify(`No profiles found in ${PROFILE_CONFIG_PATH}.`, WARNING);\n return;\n }\n\n const picked = await pickProfile(ctx, profiles, current, load.picker);\n const profile = profiles.find((candidate) => candidate.name === picked);\n if (!profile) return;\n if (profile.name === current) {\n ctx.ui.notify(profileSummary(profile), INFO);\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(ctx);\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: crypto.randomUUID(),\n source: ctx.mode === 'tui' ? 'ui' : 'command',\n target: { axis: 'profile', profile: profile.name },\n },\n async (_request, plan) => {\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n ctx,\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n const { applyProfile } = await load.selection();\n ctx.ui.notify(await applyProfile(profile, state), INFO);\n const { persistHarnessSelection } = await load.journal();\n persistHarnessSelection(pi, { ...state, profile: profile.name });\n void telemetry.recordEvent(PROFILE_EVENT.profileApplied, {\n 'harness.profile': profile.name,\n ...(current ? { 'harness.profile.previous': current } : {}),\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n return 'applied';\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n throw error;\n }\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') {\n minorModeReloadHandoff?.discard();\n ctx.ui.notify(`Profile transition was ${result.outcome}: ${result.diagnostics.join(', ')}`, WARNING);\n return;\n }\n if (result.outcome !== 'applied') {\n minorModeReloadHandoff?.discard();\n return;\n }\n\n try {\n await ctx.waitForIdle();\n // Reload replaces the session and invalidates this command context.\n // Keep it as the handler's final action.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n },\n });\n}\n"],"mappings":"6WAWA,MAAM,EAAU,UACV,EAAO,OACP,EAAsB,sBAQ5B,SAAS,GAAc,CACrB,IAAI,EACA,EACA,EACA,EACA,EACJ,MAAO,CACL,iBAAqB,IAAiB,OAAO,yCAC7C,YAAgB,IAAY,OAAO,sCACnC,WAAe,IAAW,OAAO,gDACjC,aAAiB,IAAa,OAAO,qCACrC,cAAkB,IAAc,OAAO,2CACzC,CACF,CAEA,eAAe,EACb,EACA,EACA,EACA,EAC6B,CAC7B,IAAM,EAAQ,EAAa,CAAO,EAClC,GAAI,EAAI,OAAS,MACf,OAAO,EAAI,GAAG,OACZ,EACA,EAAS,IAAK,GAAY,EAAQ,IAAI,CACxC,EAEF,GAAM,CAAE,yBAA0B,MAAM,EAAW,EAUnD,OAAO,MATc,EAAI,GAAG,QACzB,EAAM,EAAO,EAAa,IACzB,IAAI,EACF,CAAE,QAAO,MAAO,EAAa,CAAQ,EAAG,SAAU,EAAU,CAAC,CAAO,EAAI,CAAC,EAAG,MAAO,EAAM,EACzF,EACA,EACA,CACF,CACJ,EAAA,GACgB,EAClB,CAEA,SAAgB,EAAuB,EAAkB,EAAmC,CAC1F,IAAM,EAAO,EAAY,EAEzB,EAAG,gBAAgB,UAAW,CAC5B,YAAa,6DACb,QAAS,MAAO,EAAO,IAAQ,CAC7B,IAAM,EAAQ,EAAyB,CAAG,CAAC,CAAC,QACtC,CAAC,CAAE,sBAAsB,CAAE,iBAAkB,MAAM,QAAQ,IAAI,CAAC,EAAK,aAAa,EAAG,EAAK,SAAS,CAAC,CAAC,EACrG,EAAO,EAAmB,CAAK,EAC/B,EAAU,EAAM,QAClB,EACJ,GAAI,CACF,EAAW,EAAa,CAAI,CAC9B,OAAS,EAAO,CACd,IAAM,EAAS,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACpE,EAAe,YAAY,EAAc,kBAAmB,CAAK,EACjE,EAAI,GAAG,OAAO,kBAAkB,EAAoB,IAAI,IAAU,CAAO,EACzE,MACF,CAEA,GAAI,EAAS,SAAW,EAAG,CACzB,EAAI,GAAG,OAAO,wBAAwB,EAAoB,GAAI,CAAO,EACrE,MACF,CAEA,IAAM,EAAS,MAAM,EAAY,EAAK,EAAU,EAAS,EAAK,MAAM,EAC9D,EAAU,EAAS,KAAM,GAAc,EAAU,OAAS,CAAM,EACtE,GAAI,CAAC,EAAS,OACd,GAAI,EAAQ,OAAS,EAAS,CAC5B,EAAI,GAAG,OAAO,EAAe,CAAO,EAAG,CAAI,EAC3C,MACF,CAEA,IAAM,EAAc,EAAiC,CAAG,EACpD,EACE,EAAS,MAAM,EAAY,QAC/B,CACE,UAAW,EAAI,eAAe,aAAa,EAC3C,eAAgB,EAAY,eAC5B,YAAa,OAAO,WAAW,EAC/B,OAAQ,EAAI,OAAS,MAAQ,KAAO,UACpC,OAAQ,CAAE,KAAM,UAAW,QAAS,EAAQ,IAAK,CACnD,EACA,MAAO,EAAU,IAAS,CACxB,EAAyB,EACvB,EACA,EAAY,eACZ,EAAK,YACL,EAAK,SAAS,UAChB,EACA,GAAI,CACF,GAAM,CAAE,gBAAiB,MAAM,EAAK,UAAU,EAC9C,EAAI,GAAG,OAAO,MAAM,EAAa,EAAS,CAAK,EAAG,CAAI,EACtD,GAAM,CAAE,2BAA4B,MAAM,EAAK,QAAQ,EAQvD,OAPA,EAAwB,EAAI,CAAE,GAAG,EAAO,QAAS,EAAQ,IAAK,CAAC,EAC/D,EAAe,YAAY,EAAc,eAAgB,CACvD,kBAAmB,EAAQ,KAC3B,GAAI,EAAU,CAAE,2BAA4B,CAAQ,EAAI,CAAC,EACzD,iCAAkC,EAAK,YACvC,kCAAmC,EAAK,WAC1C,CAAC,EACM,SACT,OAAS,EAAO,CAGd,MAFA,GAAwB,QAAQ,EAChC,EAAyB,IAAA,GACnB,CACR,CACF,CACF,EACA,GAAI,EAAO,UAAY,YAAc,EAAO,UAAY,QAAS,CAC/D,GAAwB,QAAQ,EAChC,EAAI,GAAG,OAAO,0BAA0B,EAAO,QAAQ,IAAI,EAAO,YAAY,KAAK,IAAI,IAAK,CAAO,EACnG,MACF,CACA,GAAI,EAAO,UAAY,UAAW,CAChC,GAAwB,QAAQ,EAChC,MACF,CAEA,GAAI,CACF,MAAM,EAAI,YAAY,EAGtB,MAAM,EAAI,OAAO,CACnB,OAAS,EAAO,CAEd,MADA,GAAwB,QAAQ,EAC1B,CACR,CACF,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"profileCommand.mjs","names":[],"sources":["../../src/commands/profileCommand.ts"],"sourcesContent":["import { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport type { AgentProfile } from '@agimon-ai/doompi-config/profiles';\nimport {\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { Context } from '@deepseek-ai/cordis';\nimport { profileItems, profileSummary, profileTitle } from '../services/profileText.ts';\nimport { PROFILE_EVENT, type ProfileTelemetry } from '../types/telemetry.ts';\n\nconst WARNING = 'warning';\nconst INFO = 'info';\nconst PROFILE_CONFIG_PATH = '.doom/profiles.yaml';\n\n/**\n * The picker and everything behind it load on first use.\n *\n * Every session registers this command, but almost none of them run it, so the\n * profile catalogue, the TUI component and the switch stay off the startup path.\n */\nfunction lazyModules() {\n let harnessStore: Promise<typeof import('@agimon-ai/doompi-config/harnessStore')> | undefined;\n let journal: Promise<typeof import('@agimon-ai/doompi-config/piContext')> | undefined;\n let picker: Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')> | undefined;\n let profiles: Promise<typeof import('@agimon-ai/doompi-config/profiles')> | undefined;\n let selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n harnessStore: () => (harnessStore ??= import('@agimon-ai/doompi-config/harnessStore')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n profiles: () => (profiles ??= import('@agimon-ai/doompi-config/profiles')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\n\nasync function pickProfile(\n ctx: ExtensionContext,\n profiles: AgentProfile[],\n current: string | undefined,\n loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>,\n): Promise<string | undefined> {\n const title = profileTitle(current);\n if (ctx.mode !== 'tui') {\n return ctx.ui.select(\n title,\n profiles.map((profile) => profile.name),\n );\n }\n const { MatrixPickerComponent } = await loadPicker();\n const chosen = await ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: profileItems(profiles), selected: current ? [current] : [], multi: false },\n theme,\n keybindings,\n done,\n ),\n );\n return chosen?.[0];\n}\n\nexport function registerProfileCommand(\n pi: ExtensionAPI,\n telemetry: ProfileTelemetry,\n cordisContext: () => Context,\n): void {\n const load = lazyModules();\n\n pi.registerCommand('profile', {\n description: 'Show profiles and load a different persona and environment',\n handler: async (_args, ctx) => {\n const cordis = cordisContext();\n const state = requireDoomConfigContext(cordis).harness;\n const [{ requireHarnessRoot }, { loadProfiles }] = await Promise.all([load.harnessStore(), load.profiles()]);\n const root = requireHarnessRoot(state);\n const current = state.profile;\n let profiles: AgentProfile[];\n try {\n profiles = loadProfiles(root);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n void telemetry.recordError(PROFILE_EVENT.profileLoadFailed, error);\n ctx.ui.notify(`Could not load ${PROFILE_CONFIG_PATH}: ${reason}`, WARNING);\n return;\n }\n\n if (profiles.length === 0) {\n ctx.ui.notify(`No profiles found in ${PROFILE_CONFIG_PATH}.`, WARNING);\n return;\n }\n\n const picked = await pickProfile(ctx, profiles, current, load.picker);\n const profile = profiles.find((candidate) => candidate.name === picked);\n if (!profile) return;\n if (profile.name === current) {\n ctx.ui.notify(profileSummary(profile), INFO);\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(cordis);\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: crypto.randomUUID(),\n source: ctx.mode === 'tui' ? 'ui' : 'command',\n target: { axis: 'profile', profile: profile.name },\n },\n async (_request, plan) => {\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n cordis,\n ctx.sessionManager.getSessionId(),\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n const { applyProfile } = await load.selection();\n ctx.ui.notify(await applyProfile(profile, state), INFO);\n const { persistHarnessSelection } = await load.journal();\n persistHarnessSelection(pi, { ...state, profile: profile.name });\n void telemetry.recordEvent(PROFILE_EVENT.profileApplied, {\n 'harness.profile': profile.name,\n ...(current ? { 'harness.profile.previous': current } : {}),\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n return 'applied';\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n throw error;\n }\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') {\n minorModeReloadHandoff?.discard();\n ctx.ui.notify(`Profile transition was ${result.outcome}: ${result.diagnostics.join(', ')}`, WARNING);\n return;\n }\n if (result.outcome !== 'applied') {\n minorModeReloadHandoff?.discard();\n return;\n }\n\n try {\n await ctx.waitForIdle();\n // Reload replaces the session and invalidates this command context.\n // Keep it as the handler's final action.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n },\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-profile",
3
- "version": "0.0.1-alpha.2",
3
+ "version": "0.0.1-alpha.3",
4
4
  "description": "Persona and environment profile switching for DoomPi sessions.",
5
5
  "keywords": [
6
6
  "agent-persona",
@@ -51,10 +51,10 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@deepseek-ai/cordis": "4.0.1",
54
- "@agimon-ai/doompi-config": "0.0.1-alpha.24",
55
- "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.24",
56
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.24",
57
- "@agimon-ai/doompi-ui": "0.0.1-alpha.24"
54
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.25",
55
+ "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.25",
56
+ "@agimon-ai/doompi-config": "0.0.1-alpha.25",
57
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.25"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@deepseek-ai/cordis": "4.0.1",
@@ -65,7 +65,7 @@
65
65
  "tsdown": "0.22.14",
66
66
  "typescript": "6.0.3",
67
67
  "vitest": "4.1.10",
68
- "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.24"
68
+ "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.25"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@earendil-works/pi-coding-agent": "0.84.2",