@agimon-ai/doompi-major-mode 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.
Files changed (34) hide show
  1. package/dist/adapters/pi/extension.cjs +1 -1
  2. package/dist/adapters/pi/extension.cjs.map +1 -1
  3. package/dist/adapters/pi/extension.d.cts +1 -6
  4. package/dist/adapters/pi/extension.d.cts.map +1 -1
  5. package/dist/adapters/pi/extension.d.mts +1 -6
  6. package/dist/adapters/pi/extension.d.mts.map +1 -1
  7. package/dist/adapters/pi/extension.mjs +1 -1
  8. package/dist/adapters/pi/extension.mjs.map +1 -1
  9. package/dist/adapters/pi/voiceTool.cjs +1 -1
  10. package/dist/adapters/pi/voiceTool.cjs.map +1 -1
  11. package/dist/adapters/pi/voiceTool.d.cts +4 -1
  12. package/dist/adapters/pi/voiceTool.d.cts.map +1 -1
  13. package/dist/adapters/pi/voiceTool.d.mts +4 -1
  14. package/dist/adapters/pi/voiceTool.d.mts.map +1 -1
  15. package/dist/adapters/pi/voiceTool.mjs +1 -1
  16. package/dist/adapters/pi/voiceTool.mjs.map +1 -1
  17. package/dist/commands/majorModeCommand.cjs +1 -1
  18. package/dist/commands/majorModeCommand.cjs.map +1 -1
  19. package/dist/commands/majorModeCommand.d.cts +4 -0
  20. package/dist/commands/majorModeCommand.d.cts.map +1 -1
  21. package/dist/commands/majorModeCommand.d.mts +4 -0
  22. package/dist/commands/majorModeCommand.d.mts.map +1 -1
  23. package/dist/commands/majorModeCommand.mjs +1 -1
  24. package/dist/commands/majorModeCommand.mjs.map +1 -1
  25. package/dist/services/majorModeText.d.mts +1 -1
  26. package/dist/services/pendingSelection.cjs +1 -1
  27. package/dist/services/pendingSelection.cjs.map +1 -1
  28. package/dist/services/pendingSelection.d.cts +3 -2
  29. package/dist/services/pendingSelection.d.cts.map +1 -1
  30. package/dist/services/pendingSelection.d.mts +3 -2
  31. package/dist/services/pendingSelection.d.mts.map +1 -1
  32. package/dist/services/pendingSelection.mjs +1 -1
  33. package/dist/services/pendingSelection.mjs.map +1 -1
  34. package/package.json +6 -6
@@ -1,2 +1,2 @@
1
- const e=require("../../services/statusLine.cjs"),t=require("../../types/telemetry.cjs"),n=require("../../types/majorMode.cjs"),r=require("../../commands/majorModeCommand.cjs"),i=require("../telemetry/logSinkTelemetry.cjs"),a=require("./voiceTool.cjs");let o=require("@agimon-ai/doompi-config/harnessStore"),s=require("@agimon-ai/doompi-config/piContext"),c=require("@deepseek-ai/cordis");function l(){let e,t,n,r;return{config:()=>e??=import(`@agimon-ai/doompi-config/majorModes`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),selection:()=>r??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}async function u(u,d=i.createMajorModeTelemetry()){let f=new c.Context,p=l(),m,h=()=>(m??=f.fiber.dispose(),m),g=async e=>{let t=(0,s.requireDoomConfigContext)(e).harness,{loadMajorModesConfig:n}=await p.config();return{config:n((0,o.requireHarnessRoot)(t)),majorMode:t.majorMode,domains:t.domains,profile:t.profile}};try{f.effect(function*(){a.registerMajorModeVoiceCapability(u,g),r.registerMajorModeCommand(u,d,{currentView:g,loadPicker:p.picker,loadSelectionSwitch:p.selection,loadConfigJournal:p.journal,resolveLayers:(e,t)=>[...e.majorMode[t]?.layers??[]]}),u.on(`session_start`,(n,r)=>{try{let{majorMode:t,domains:n,profile:i}=(0,s.requireDoomConfigContext)(r).harness;r.ui.setStatus(e.STATUS_KEY,e.colorStatus(r.ui.theme,t,n,i,!1))}catch(n){d.recordError(t.MAJOR_MODE_EVENT.majorModeUnavailable,n),r.ui.setStatus(e.STATUS_KEY,`major mode unavailable (${n instanceof Error?n.message:String(n)})`)}}),yield()=>void 0},n.MAJOR_MODE_SOURCE)}catch(e){throw await h(),e}u.on(`session_shutdown`,h)}exports.default=u,exports.majorModeExtension=u;
1
+ const e=require("../../services/statusLine.cjs"),t=require("../../types/telemetry.cjs"),n=require("../../types/majorMode.cjs"),r=require("../../commands/majorModeCommand.cjs"),i=require("../telemetry/logSinkTelemetry.cjs"),a=require("./voiceTool.cjs");let o=require("@agimon-ai/doompi-config/harnessStore"),s=require("@agimon-ai/doompi-config/piContext"),c=require("@agimon-ai/doompi-extension-contracts/config"),l=require("@agimon-ai/doompi-extension-contracts/cordis-host"),u=require("@agimon-ai/doompi-extension-contracts/transition"),d=require("@agimon-ai/doompi-extension-contracts/voice-tools"),f=require("@agimon-ai/doompi-extension-contracts/voice-reload-handoff");function p(){let e,t,n,r;return{config:()=>e??=import(`@agimon-ai/doompi-config/majorModes`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),selection:()=>r??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}function m(i,{pi:l,telemetry:m}){let h=p(),g,_=i.inject([c.DOOM_CONFIG_SERVICE,u.DOOM_TRANSITION_SERVICE],e=>(g=e,()=>{g===e&&(g=void 0)})),v=()=>{if(!g)throw Error(`Doom major-mode runtime is waiting for the session config service.`);return g},y=async e=>{let t=(0,s.requireDoomConfigContext)(v()).harness,{loadMajorModesConfig:n}=await h.config();return{config:n((0,o.requireHarnessRoot)(t)),majorMode:t.majorMode,domains:t.domains,profile:t.profile}},b=(0,f.createVoiceReloadHandoffStore)({now:()=>Date.now(),createToken:()=>crypto.randomUUID()});i.inject([c.DOOM_CONFIG_SERVICE,u.DOOM_TRANSITION_SERVICE,d.DOOM_VOICE_TOOLS_SERVICE],e=>a.registerMajorModeVoiceCapability((0,d.requireDoomVoiceToolsService)(e),l,y,b,()=>e)),i.effect(function*(){r.registerMajorModeCommand(l,m,{cordisContext:v,currentView:y,reloadHandoffs:b,loadPicker:h.picker,loadSelectionSwitch:h.selection,loadConfigJournal:h.journal,resolveLayers:(e,t)=>[...e.majorMode[t]?.layers??[]]}),l.on(`session_start`,async(n,r)=>{await _.await();try{let{majorMode:t,domains:n,profile:i}=(0,s.requireDoomConfigContext)(v()).harness;r.ui.setStatus(e.STATUS_KEY,e.colorStatus(r.ui.theme,t,n,i,!1))}catch(n){m.recordError(t.MAJOR_MODE_EVENT.majorModeUnavailable,n),r.ui.setStatus(e.STATUS_KEY,`major mode unavailable (${n instanceof Error?n.message:String(n)})`)}}),yield()=>void 0},n.MAJOR_MODE_SOURCE)}async function h(e,t=i.createMajorModeTelemetry()){let r=await(0,l.connectDoomCordisHost)(e,n.MAJOR_MODE_SOURCE),a=r.root.plugin(m,{pi:e,telemetry:t});try{await a}catch(e){try{await a.dispose()}finally{await r.dispose()}throw e}let o;e.on(`session_shutdown`,()=>o??=(async()=>{try{await a.dispose()}finally{await r.dispose()}})())}exports.default=h,exports.majorModeExtension=h;
2
2
  //# sourceMappingURL=extension.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.cjs","names":["createMajorModeTelemetry","Context","requireDoomConfigContext","requireHarnessRoot","STATUS_KEY","colorStatus","MAJOR_MODE_EVENT","MAJOR_MODE_SOURCE"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { requireHarnessRoot } from '@agimon-ai/doompi-config/harnessStore';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { registerMajorModeCommand } from '../../commands/majorModeCommand.ts';\nimport { colorStatus, STATUS_KEY } from '../../services/statusLine.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../../types/telemetry.ts';\nimport { createMajorModeTelemetry } from '../telemetry/logSinkTelemetry.ts';\nimport { registerMajorModeVoiceCapability } from './voiceTool.ts';\n\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\n\n/**\n * Everything the axis needs beyond the session, loaded on first use.\n *\n * Every session registers /mode, but most never run it, so the picker, the\n * switch and the journal stay off the startup path.\n */\nfunction lazyModules() {\n let config: Promise<typeof import('@agimon-ai/doompi-config/majorModes')> | 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 selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n config: () => (config ??= import('@agimon-ai/doompi-config/majorModes')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\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 majorModeExtension(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry = createMajorModeTelemetry(),\n): Promise<void> {\n const cordis = new Context();\n const load = lazyModules();\n let disposal: Promise<void> | undefined;\n const dispose = (): Promise<void> => {\n disposal ??= cordis.fiber.dispose();\n return disposal;\n };\n\n const currentView = async (ctx: ExtensionContext): Promise<MajorModeView> => {\n const state = requireDoomConfigContext(ctx).harness;\n const { loadMajorModesConfig } = await load.config();\n return {\n config: loadMajorModesConfig(requireHarnessRoot(state)),\n majorMode: state.majorMode,\n domains: state.domains,\n profile: state.profile,\n };\n };\n\n try {\n cordis.effect(function* () {\n registerMajorModeVoiceCapability(pi, currentView);\n registerMajorModeCommand(pi, telemetry, {\n currentView,\n loadPicker: load.picker,\n loadSelectionSwitch: load.selection,\n loadConfigJournal: load.journal,\n resolveLayers: (config, majorMode) => [...(config.majorMode[majorMode]?.layers ?? [])],\n });\n pi.on('session_start', (_event, ctx) => {\n try {\n const { majorMode, domains, profile } = requireDoomConfigContext(ctx).harness;\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, majorMode, domains, profile, false));\n } catch (error) {\n // The status line degrades to a message nobody reads, while the run\n // keeps going with whatever layers the environment happened to carry.\n void telemetry.recordError(MAJOR_MODE_EVENT.majorModeUnavailable, error);\n ctx.ui.setStatus(\n STATUS_KEY,\n `major mode unavailable (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n });\n // Pi owns command and hook deregistration across a reload, so the fiber\n // only has to drop this package's own reference to the session.\n yield () => undefined;\n }, MAJOR_MODE_SOURCE);\n } catch (error) {\n await dispose();\n throw error;\n }\n\n pi.on(SESSION_SHUTDOWN_EVENT, dispose);\n}\n\nexport default majorModeExtension;\n"],"mappings":"oYAmBA,SAAS,GAAc,CACrB,IAAI,EACA,EACA,EACA,EACJ,MAAO,CACL,WAAe,IAAW,OAAO,uCACjC,YAAgB,IAAY,OAAO,sCACnC,WAAe,IAAW,OAAO,gDACjC,cAAkB,IAAc,OAAO,2CACzC,CACF,CAQA,eAAsB,EACpB,EACA,EAAgCA,EAAAA,yBAAyB,EAC1C,CACf,IAAM,EAAS,IAAIC,EAAAA,QACb,EAAO,EAAY,EACrB,EACE,OACJ,IAAa,EAAO,MAAM,QAAQ,EAC3B,GAGH,EAAc,KAAO,IAAkD,CAC3E,IAAM,GAAA,EAAQC,EAAAA,yBAAAA,CAAyB,CAAG,CAAC,CAAC,QACtC,CAAE,wBAAyB,MAAM,EAAK,OAAO,EACnD,MAAO,CACL,OAAQ,GAAA,EAAqBC,EAAAA,mBAAAA,CAAmB,CAAK,CAAC,EACtD,UAAW,EAAM,UACjB,QAAS,EAAM,QACf,QAAS,EAAM,OACjB,CACF,EAEA,GAAI,CACF,EAAO,OAAO,WAAa,CACzB,EAAA,iCAAiC,EAAI,CAAW,EAChD,EAAA,yBAAyB,EAAI,EAAW,CACtC,cACA,WAAY,EAAK,OACjB,oBAAqB,EAAK,UAC1B,kBAAmB,EAAK,QACxB,eAAgB,EAAQ,IAAc,CAAC,GAAI,EAAO,UAAU,EAAU,EAAE,QAAU,CAAC,CAAE,CACvF,CAAC,EACD,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,GAAI,CACF,GAAM,CAAE,YAAW,UAAS,YAAA,EAAYD,EAAAA,yBAAAA,CAAyB,CAAG,CAAC,CAAC,QACtE,EAAI,GAAG,UAAUE,EAAAA,WAAYC,EAAAA,YAAY,EAAI,GAAG,MAAO,EAAW,EAAS,EAAS,EAAK,CAAC,CAC5F,OAAS,EAAO,CAGd,EAAe,YAAYC,EAAAA,iBAAiB,qBAAsB,CAAK,EACvE,EAAI,GAAG,UACLF,EAAAA,WACA,2BAA2B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,EACpF,CACF,CACF,CAAC,EAGD,SAAY,IAAA,EACd,EAAGG,EAAAA,iBAAiB,CACtB,OAAS,EAAO,CAEd,MADA,MAAM,EAAQ,EACR,CACR,CAEA,EAAG,GAAG,mBAAwB,CAAO,CACvC"}
1
+ {"version":3,"file":"extension.cjs","names":["DOOM_CONFIG_SERVICE","DOOM_TRANSITION_SERVICE","requireDoomConfigContext","requireHarnessRoot","createVoiceReloadHandoffStore","DOOM_VOICE_TOOLS_SERVICE","registerMajorModeVoiceCapability","requireDoomVoiceToolsService","STATUS_KEY","colorStatus","MAJOR_MODE_EVENT","MAJOR_MODE_SOURCE","createMajorModeTelemetry","connectDoomCordisHost"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { requireHarnessRoot } from '@agimon-ai/doompi-config/harnessStore';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport { 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 {\n DOOM_VOICE_TOOLS_SERVICE,\n requireDoomVoiceToolsService,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport { createVoiceReloadHandoffStore } from '@agimon-ai/doompi-extension-contracts/voice-reload-handoff';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { registerMajorModeCommand } from '../../commands/majorModeCommand.ts';\nimport { colorStatus, STATUS_KEY } from '../../services/statusLine.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../../types/telemetry.ts';\nimport { createMajorModeTelemetry } from '../telemetry/logSinkTelemetry.ts';\nimport { registerMajorModeVoiceCapability } from './voiceTool.ts';\n\n/**\n * Everything the axis needs beyond the session, loaded on first use.\n *\n * Every session registers /mode, but most never run it, so the picker, the\n * switch and the journal stay off the startup path.\n */\nfunction lazyModules() {\n let config: Promise<typeof import('@agimon-ai/doompi-config/majorModes')> | 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 selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n config: () => (config ??= import('@agimon-ai/doompi-config/majorModes')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\n\ninterface MajorModePluginConfig {\n readonly pi: ExtensionAPI;\n readonly telemetry: MajorModeTelemetry;\n}\n\nfunction majorModePlugin(cordis: Context, { pi, telemetry }: MajorModePluginConfig): void {\n const load = lazyModules();\n let activeContext: Context | undefined;\n const runtimeInjection = 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 major-mode runtime is waiting for the session config service.');\n return activeContext;\n };\n const currentView = async (_ctx: ExtensionContext): Promise<MajorModeView> => {\n const state = requireDoomConfigContext(requireRuntimeContext()).harness;\n const { loadMajorModesConfig } = await load.config();\n return {\n config: loadMajorModesConfig(requireHarnessRoot(state)),\n majorMode: state.majorMode,\n domains: state.domains,\n profile: state.profile,\n };\n };\n const reloadHandoffs = createVoiceReloadHandoffStore({\n now: () => Date.now(),\n createToken: () => crypto.randomUUID(),\n });\n cordis.inject([DOOM_CONFIG_SERVICE, DOOM_TRANSITION_SERVICE, DOOM_VOICE_TOOLS_SERVICE], (voiceContext) =>\n registerMajorModeVoiceCapability(\n requireDoomVoiceToolsService(voiceContext),\n pi,\n currentView,\n reloadHandoffs,\n () => voiceContext,\n ),\n );\n\n cordis.effect(function* () {\n registerMajorModeCommand(pi, telemetry, {\n cordisContext: requireRuntimeContext,\n currentView,\n reloadHandoffs,\n loadPicker: load.picker,\n loadSelectionSwitch: load.selection,\n loadConfigJournal: load.journal,\n resolveLayers: (config, majorMode) => [...(config.majorMode[majorMode]?.layers ?? [])],\n });\n pi.on('session_start', async (_event, ctx) => {\n await runtimeInjection.await();\n try {\n const { majorMode, domains, profile } = requireDoomConfigContext(requireRuntimeContext()).harness;\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, majorMode, domains, profile, false));\n } catch (error) {\n void telemetry.recordError(MAJOR_MODE_EVENT.majorModeUnavailable, error);\n ctx.ui.setStatus(\n STATUS_KEY,\n `major mode unavailable (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n });\n yield () => undefined;\n }, MAJOR_MODE_SOURCE);\n}\n\n/** The package's single standard Pi factory. */\nexport async function majorModeExtension(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry = createMajorModeTelemetry(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, MAJOR_MODE_SOURCE);\n const fiber = connection.root.plugin(majorModePlugin, { 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\nexport default majorModeExtension;\n"],"mappings":"iqBAyBA,SAAS,GAAc,CACrB,IAAI,EACA,EACA,EACA,EACJ,MAAO,CACL,WAAe,IAAW,OAAO,uCACjC,YAAgB,IAAY,OAAO,sCACnC,WAAe,IAAW,OAAO,gDACjC,cAAkB,IAAc,OAAO,2CACzC,CACF,CAOA,SAAS,EAAgB,EAAiB,CAAE,KAAI,aAA0C,CACxF,IAAM,EAAO,EAAY,EACrB,EACE,EAAmB,EAAO,OAAO,CAACA,EAAAA,oBAAqBC,EAAAA,uBAAuB,EAAI,IACtF,EAAgB,MACH,CACP,IAAkB,IAAS,EAAgB,IAAA,GACjD,EACD,EACK,MAAuC,CAC3C,GAAI,CAAC,EAAe,MAAU,MAAM,oEAAoE,EACxG,OAAO,CACT,EACM,EAAc,KAAO,IAAmD,CAC5E,IAAM,GAAA,EAAQC,EAAAA,yBAAAA,CAAyB,EAAsB,CAAC,CAAC,CAAC,QAC1D,CAAE,wBAAyB,MAAM,EAAK,OAAO,EACnD,MAAO,CACL,OAAQ,GAAA,EAAqBC,EAAAA,mBAAAA,CAAmB,CAAK,CAAC,EACtD,UAAW,EAAM,UACjB,QAAS,EAAM,QACf,QAAS,EAAM,OACjB,CACF,EACM,GAAA,EAAiBC,EAAAA,8BAAAA,CAA8B,CACnD,QAAW,KAAK,IAAI,EACpB,gBAAmB,OAAO,WAAW,CACvC,CAAC,EACD,EAAO,OAAO,CAACJ,EAAAA,oBAAqBC,EAAAA,wBAAyBI,EAAAA,wBAAwB,EAAI,GACvFC,EAAAA,kCAAAA,EACEC,EAAAA,6BAAAA,CAA6B,CAAY,EACzC,EACA,EACA,MACM,CACR,CACF,EAEA,EAAO,OAAO,WAAa,CACzB,EAAA,yBAAyB,EAAI,EAAW,CACtC,cAAe,EACf,cACA,iBACA,WAAY,EAAK,OACjB,oBAAqB,EAAK,UAC1B,kBAAmB,EAAK,QACxB,eAAgB,EAAQ,IAAc,CAAC,GAAI,EAAO,UAAU,EAAU,EAAE,QAAU,CAAC,CAAE,CACvF,CAAC,EACD,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAAQ,CAC5C,MAAM,EAAiB,MAAM,EAC7B,GAAI,CACF,GAAM,CAAE,YAAW,UAAS,YAAA,EAAYL,EAAAA,yBAAAA,CAAyB,EAAsB,CAAC,CAAC,CAAC,QAC1F,EAAI,GAAG,UAAUM,EAAAA,WAAYC,EAAAA,YAAY,EAAI,GAAG,MAAO,EAAW,EAAS,EAAS,EAAK,CAAC,CAC5F,OAAS,EAAO,CACd,EAAe,YAAYC,EAAAA,iBAAiB,qBAAsB,CAAK,EACvE,EAAI,GAAG,UACLF,EAAAA,WACA,2BAA2B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,EACpF,CACF,CACF,CAAC,EACD,SAAY,IAAA,EACd,EAAGG,EAAAA,iBAAiB,CACtB,CAGA,eAAsB,EACpB,EACA,EAAgCC,EAAAA,yBAAyB,EAC1C,CACf,IAAM,EAAa,MAAA,EAAMC,EAAAA,sBAAAA,CAAsB,EAAIF,EAAAA,iBAAiB,EAC9D,EAAQ,EAAW,KAAK,OAAO,EAAiB,CAAE,KAAI,WAAU,CAAC,EACvE,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"}
@@ -1,12 +1,7 @@
1
1
  import { MajorModeTelemetry } from "../../types/telemetry.cjs";
2
2
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  //#region src/adapters/pi/extension.d.ts
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.
9
- */
4
+ /** The package's single standard Pi factory. */
10
5
  declare function majorModeExtension(pi: ExtensionAPI, telemetry?: MajorModeTelemetry): Promise<void>;
11
6
  //#endregion
12
7
  export { majorModeExtension as default, majorModeExtension };
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;;;;iBAsCsB,mBACpB,IAAI,cACJ,YAAW,qBACV"}
1
+ {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;iBA4GsB,mBACpB,IAAI,cACJ,YAAW,qBACV"}
@@ -1,12 +1,7 @@
1
1
  import { MajorModeTelemetry } from "../../types/telemetry.mjs";
2
2
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  //#region src/adapters/pi/extension.d.ts
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.
9
- */
4
+ /** The package's single standard Pi factory. */
10
5
  declare function majorModeExtension(pi: ExtensionAPI, telemetry?: MajorModeTelemetry): Promise<void>;
11
6
  //#endregion
12
7
  export { majorModeExtension as default, majorModeExtension };
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;;;;;;iBAsCsB,mBACpB,IAAI,cACJ,YAAW,qBACV"}
1
+ {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;iBA4GsB,mBACpB,IAAI,cACJ,YAAW,qBACV"}
@@ -1,2 +1,2 @@
1
- import{STATUS_KEY as e,colorStatus as t}from"../../services/statusLine.mjs";import{MAJOR_MODE_EVENT as n}from"../../types/telemetry.mjs";import{MAJOR_MODE_SOURCE as r}from"../../types/majorMode.mjs";import{registerMajorModeCommand as i}from"../../commands/majorModeCommand.mjs";import{createMajorModeTelemetry as a}from"../telemetry/logSinkTelemetry.mjs";import{registerMajorModeVoiceCapability as o}from"./voiceTool.mjs";import{requireHarnessRoot as s}from"@agimon-ai/doompi-config/harnessStore";import{requireDoomConfigContext as c}from"@agimon-ai/doompi-config/piContext";import{Context as l}from"@deepseek-ai/cordis";function u(){let e,t,n,r;return{config:()=>e??=import(`@agimon-ai/doompi-config/majorModes`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),selection:()=>r??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}async function d(d,f=a()){let p=new l,m=u(),h,g=()=>(h??=p.fiber.dispose(),h),_=async e=>{let t=c(e).harness,{loadMajorModesConfig:n}=await m.config();return{config:n(s(t)),majorMode:t.majorMode,domains:t.domains,profile:t.profile}};try{p.effect(function*(){o(d,_),i(d,f,{currentView:_,loadPicker:m.picker,loadSelectionSwitch:m.selection,loadConfigJournal:m.journal,resolveLayers:(e,t)=>[...e.majorMode[t]?.layers??[]]}),d.on(`session_start`,(r,i)=>{try{let{majorMode:n,domains:r,profile:a}=c(i).harness;i.ui.setStatus(e,t(i.ui.theme,n,r,a,!1))}catch(t){f.recordError(n.majorModeUnavailable,t),i.ui.setStatus(e,`major mode unavailable (${t instanceof Error?t.message:String(t)})`)}}),yield()=>void 0},r)}catch(e){throw await g(),e}d.on(`session_shutdown`,g)}export{d as default,d as majorModeExtension};
1
+ import{STATUS_KEY as e,colorStatus as t}from"../../services/statusLine.mjs";import{MAJOR_MODE_EVENT as n}from"../../types/telemetry.mjs";import{MAJOR_MODE_SOURCE as r}from"../../types/majorMode.mjs";import{registerMajorModeCommand as i}from"../../commands/majorModeCommand.mjs";import{createMajorModeTelemetry as a}from"../telemetry/logSinkTelemetry.mjs";import{registerMajorModeVoiceCapability as o}from"./voiceTool.mjs";import{requireHarnessRoot as s}from"@agimon-ai/doompi-config/harnessStore";import{requireDoomConfigContext as c}from"@agimon-ai/doompi-config/piContext";import{DOOM_CONFIG_SERVICE as l}from"@agimon-ai/doompi-extension-contracts/config";import{connectDoomCordisHost as u}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_TRANSITION_SERVICE as d}from"@agimon-ai/doompi-extension-contracts/transition";import{DOOM_VOICE_TOOLS_SERVICE as f,requireDoomVoiceToolsService as p}from"@agimon-ai/doompi-extension-contracts/voice-tools";import{createVoiceReloadHandoffStore as m}from"@agimon-ai/doompi-extension-contracts/voice-reload-handoff";function h(){let e,t,n,r;return{config:()=>e??=import(`@agimon-ai/doompi-config/majorModes`),journal:()=>t??=import(`@agimon-ai/doompi-config/piContext`),picker:()=>n??=import(`@agimon-ai/doompi-ui/components/matrixPicker`),selection:()=>r??=import(`@agimon-ai/doompi-config/selectionSwitch`)}}function g(a,{pi:u,telemetry:g}){let _=h(),v,y=a.inject([l,d],e=>(v=e,()=>{v===e&&(v=void 0)})),b=()=>{if(!v)throw Error(`Doom major-mode runtime is waiting for the session config service.`);return v},x=async e=>{let t=c(b()).harness,{loadMajorModesConfig:n}=await _.config();return{config:n(s(t)),majorMode:t.majorMode,domains:t.domains,profile:t.profile}},S=m({now:()=>Date.now(),createToken:()=>crypto.randomUUID()});a.inject([l,d,f],e=>o(p(e),u,x,S,()=>e)),a.effect(function*(){i(u,g,{cordisContext:b,currentView:x,reloadHandoffs:S,loadPicker:_.picker,loadSelectionSwitch:_.selection,loadConfigJournal:_.journal,resolveLayers:(e,t)=>[...e.majorMode[t]?.layers??[]]}),u.on(`session_start`,async(r,i)=>{await y.await();try{let{majorMode:n,domains:r,profile:a}=c(b()).harness;i.ui.setStatus(e,t(i.ui.theme,n,r,a,!1))}catch(t){g.recordError(n.majorModeUnavailable,t),i.ui.setStatus(e,`major mode unavailable (${t instanceof Error?t.message:String(t)})`)}}),yield()=>void 0},r)}async function _(e,t=a()){let n=await u(e,r),i=n.root.plugin(g,{pi:e,telemetry:t});try{await i}catch(e){try{await i.dispose()}finally{await n.dispose()}throw e}let o;e.on(`session_shutdown`,()=>o??=(async()=>{try{await i.dispose()}finally{await n.dispose()}})())}export{_ as default,_ as majorModeExtension};
2
2
  //# sourceMappingURL=extension.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { requireHarnessRoot } from '@agimon-ai/doompi-config/harnessStore';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { registerMajorModeCommand } from '../../commands/majorModeCommand.ts';\nimport { colorStatus, STATUS_KEY } from '../../services/statusLine.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../../types/telemetry.ts';\nimport { createMajorModeTelemetry } from '../telemetry/logSinkTelemetry.ts';\nimport { registerMajorModeVoiceCapability } from './voiceTool.ts';\n\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\n\n/**\n * Everything the axis needs beyond the session, loaded on first use.\n *\n * Every session registers /mode, but most never run it, so the picker, the\n * switch and the journal stay off the startup path.\n */\nfunction lazyModules() {\n let config: Promise<typeof import('@agimon-ai/doompi-config/majorModes')> | 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 selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n config: () => (config ??= import('@agimon-ai/doompi-config/majorModes')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\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 majorModeExtension(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry = createMajorModeTelemetry(),\n): Promise<void> {\n const cordis = new Context();\n const load = lazyModules();\n let disposal: Promise<void> | undefined;\n const dispose = (): Promise<void> => {\n disposal ??= cordis.fiber.dispose();\n return disposal;\n };\n\n const currentView = async (ctx: ExtensionContext): Promise<MajorModeView> => {\n const state = requireDoomConfigContext(ctx).harness;\n const { loadMajorModesConfig } = await load.config();\n return {\n config: loadMajorModesConfig(requireHarnessRoot(state)),\n majorMode: state.majorMode,\n domains: state.domains,\n profile: state.profile,\n };\n };\n\n try {\n cordis.effect(function* () {\n registerMajorModeVoiceCapability(pi, currentView);\n registerMajorModeCommand(pi, telemetry, {\n currentView,\n loadPicker: load.picker,\n loadSelectionSwitch: load.selection,\n loadConfigJournal: load.journal,\n resolveLayers: (config, majorMode) => [...(config.majorMode[majorMode]?.layers ?? [])],\n });\n pi.on('session_start', (_event, ctx) => {\n try {\n const { majorMode, domains, profile } = requireDoomConfigContext(ctx).harness;\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, majorMode, domains, profile, false));\n } catch (error) {\n // The status line degrades to a message nobody reads, while the run\n // keeps going with whatever layers the environment happened to carry.\n void telemetry.recordError(MAJOR_MODE_EVENT.majorModeUnavailable, error);\n ctx.ui.setStatus(\n STATUS_KEY,\n `major mode unavailable (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n });\n // Pi owns command and hook deregistration across a reload, so the fiber\n // only has to drop this package's own reference to the session.\n yield () => undefined;\n }, MAJOR_MODE_SOURCE);\n } catch (error) {\n await dispose();\n throw error;\n }\n\n pi.on(SESSION_SHUTDOWN_EVENT, dispose);\n}\n\nexport default majorModeExtension;\n"],"mappings":"6mBAmBA,SAAS,GAAc,CACrB,IAAI,EACA,EACA,EACA,EACJ,MAAO,CACL,WAAe,IAAW,OAAO,uCACjC,YAAgB,IAAY,OAAO,sCACnC,WAAe,IAAW,OAAO,gDACjC,cAAkB,IAAc,OAAO,2CACzC,CACF,CAQA,eAAsB,EACpB,EACA,EAAgC,EAAyB,EAC1C,CACf,IAAM,EAAS,IAAI,EACb,EAAO,EAAY,EACrB,EACE,OACJ,IAAa,EAAO,MAAM,QAAQ,EAC3B,GAGH,EAAc,KAAO,IAAkD,CAC3E,IAAM,EAAQ,EAAyB,CAAG,CAAC,CAAC,QACtC,CAAE,wBAAyB,MAAM,EAAK,OAAO,EACnD,MAAO,CACL,OAAQ,EAAqB,EAAmB,CAAK,CAAC,EACtD,UAAW,EAAM,UACjB,QAAS,EAAM,QACf,QAAS,EAAM,OACjB,CACF,EAEA,GAAI,CACF,EAAO,OAAO,WAAa,CACzB,EAAiC,EAAI,CAAW,EAChD,EAAyB,EAAI,EAAW,CACtC,cACA,WAAY,EAAK,OACjB,oBAAqB,EAAK,UAC1B,kBAAmB,EAAK,QACxB,eAAgB,EAAQ,IAAc,CAAC,GAAI,EAAO,UAAU,EAAU,EAAE,QAAU,CAAC,CAAE,CACvF,CAAC,EACD,EAAG,GAAG,iBAAkB,EAAQ,IAAQ,CACtC,GAAI,CACF,GAAM,CAAE,YAAW,UAAS,WAAY,EAAyB,CAAG,CAAC,CAAC,QACtE,EAAI,GAAG,UAAU,EAAY,EAAY,EAAI,GAAG,MAAO,EAAW,EAAS,EAAS,EAAK,CAAC,CAC5F,OAAS,EAAO,CAGd,EAAe,YAAY,EAAiB,qBAAsB,CAAK,EACvE,EAAI,GAAG,UACL,EACA,2BAA2B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,EACpF,CACF,CACF,CAAC,EAGD,SAAY,IAAA,EACd,EAAG,CAAiB,CACtB,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 { requireHarnessRoot } from '@agimon-ai/doompi-config/harnessStore';\nimport { requireDoomConfigContext } from '@agimon-ai/doompi-config/piContext';\nimport { 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 {\n DOOM_VOICE_TOOLS_SERVICE,\n requireDoomVoiceToolsService,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport { createVoiceReloadHandoffStore } from '@agimon-ai/doompi-extension-contracts/voice-reload-handoff';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport { registerMajorModeCommand } from '../../commands/majorModeCommand.ts';\nimport { colorStatus, STATUS_KEY } from '../../services/statusLine.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../../types/telemetry.ts';\nimport { createMajorModeTelemetry } from '../telemetry/logSinkTelemetry.ts';\nimport { registerMajorModeVoiceCapability } from './voiceTool.ts';\n\n/**\n * Everything the axis needs beyond the session, loaded on first use.\n *\n * Every session registers /mode, but most never run it, so the picker, the\n * switch and the journal stay off the startup path.\n */\nfunction lazyModules() {\n let config: Promise<typeof import('@agimon-ai/doompi-config/majorModes')> | 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 selection: Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')> | undefined;\n return {\n config: () => (config ??= import('@agimon-ai/doompi-config/majorModes')),\n journal: () => (journal ??= import('@agimon-ai/doompi-config/piContext')),\n picker: () => (picker ??= import('@agimon-ai/doompi-ui/components/matrixPicker')),\n selection: () => (selection ??= import('@agimon-ai/doompi-config/selectionSwitch')),\n };\n}\n\ninterface MajorModePluginConfig {\n readonly pi: ExtensionAPI;\n readonly telemetry: MajorModeTelemetry;\n}\n\nfunction majorModePlugin(cordis: Context, { pi, telemetry }: MajorModePluginConfig): void {\n const load = lazyModules();\n let activeContext: Context | undefined;\n const runtimeInjection = 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 major-mode runtime is waiting for the session config service.');\n return activeContext;\n };\n const currentView = async (_ctx: ExtensionContext): Promise<MajorModeView> => {\n const state = requireDoomConfigContext(requireRuntimeContext()).harness;\n const { loadMajorModesConfig } = await load.config();\n return {\n config: loadMajorModesConfig(requireHarnessRoot(state)),\n majorMode: state.majorMode,\n domains: state.domains,\n profile: state.profile,\n };\n };\n const reloadHandoffs = createVoiceReloadHandoffStore({\n now: () => Date.now(),\n createToken: () => crypto.randomUUID(),\n });\n cordis.inject([DOOM_CONFIG_SERVICE, DOOM_TRANSITION_SERVICE, DOOM_VOICE_TOOLS_SERVICE], (voiceContext) =>\n registerMajorModeVoiceCapability(\n requireDoomVoiceToolsService(voiceContext),\n pi,\n currentView,\n reloadHandoffs,\n () => voiceContext,\n ),\n );\n\n cordis.effect(function* () {\n registerMajorModeCommand(pi, telemetry, {\n cordisContext: requireRuntimeContext,\n currentView,\n reloadHandoffs,\n loadPicker: load.picker,\n loadSelectionSwitch: load.selection,\n loadConfigJournal: load.journal,\n resolveLayers: (config, majorMode) => [...(config.majorMode[majorMode]?.layers ?? [])],\n });\n pi.on('session_start', async (_event, ctx) => {\n await runtimeInjection.await();\n try {\n const { majorMode, domains, profile } = requireDoomConfigContext(requireRuntimeContext()).harness;\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, majorMode, domains, profile, false));\n } catch (error) {\n void telemetry.recordError(MAJOR_MODE_EVENT.majorModeUnavailable, error);\n ctx.ui.setStatus(\n STATUS_KEY,\n `major mode unavailable (${error instanceof Error ? error.message : String(error)})`,\n );\n }\n });\n yield () => undefined;\n }, MAJOR_MODE_SOURCE);\n}\n\n/** The package's single standard Pi factory. */\nexport async function majorModeExtension(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry = createMajorModeTelemetry(),\n): Promise<void> {\n const connection = await connectDoomCordisHost(pi, MAJOR_MODE_SOURCE);\n const fiber = connection.root.plugin(majorModePlugin, { 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\nexport default majorModeExtension;\n"],"mappings":"ijCAyBA,SAAS,GAAc,CACrB,IAAI,EACA,EACA,EACA,EACJ,MAAO,CACL,WAAe,IAAW,OAAO,uCACjC,YAAgB,IAAY,OAAO,sCACnC,WAAe,IAAW,OAAO,gDACjC,cAAkB,IAAc,OAAO,2CACzC,CACF,CAOA,SAAS,EAAgB,EAAiB,CAAE,KAAI,aAA0C,CACxF,IAAM,EAAO,EAAY,EACrB,EACE,EAAmB,EAAO,OAAO,CAAC,EAAqB,CAAuB,EAAI,IACtF,EAAgB,MACH,CACP,IAAkB,IAAS,EAAgB,IAAA,GACjD,EACD,EACK,MAAuC,CAC3C,GAAI,CAAC,EAAe,MAAU,MAAM,oEAAoE,EACxG,OAAO,CACT,EACM,EAAc,KAAO,IAAmD,CAC5E,IAAM,EAAQ,EAAyB,EAAsB,CAAC,CAAC,CAAC,QAC1D,CAAE,wBAAyB,MAAM,EAAK,OAAO,EACnD,MAAO,CACL,OAAQ,EAAqB,EAAmB,CAAK,CAAC,EACtD,UAAW,EAAM,UACjB,QAAS,EAAM,QACf,QAAS,EAAM,OACjB,CACF,EACM,EAAiB,EAA8B,CACnD,QAAW,KAAK,IAAI,EACpB,gBAAmB,OAAO,WAAW,CACvC,CAAC,EACD,EAAO,OAAO,CAAC,EAAqB,EAAyB,CAAwB,EAAI,GACvF,EACE,EAA6B,CAAY,EACzC,EACA,EACA,MACM,CACR,CACF,EAEA,EAAO,OAAO,WAAa,CACzB,EAAyB,EAAI,EAAW,CACtC,cAAe,EACf,cACA,iBACA,WAAY,EAAK,OACjB,oBAAqB,EAAK,UAC1B,kBAAmB,EAAK,QACxB,eAAgB,EAAQ,IAAc,CAAC,GAAI,EAAO,UAAU,EAAU,EAAE,QAAU,CAAC,CAAE,CACvF,CAAC,EACD,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAAQ,CAC5C,MAAM,EAAiB,MAAM,EAC7B,GAAI,CACF,GAAM,CAAE,YAAW,UAAS,WAAY,EAAyB,EAAsB,CAAC,CAAC,CAAC,QAC1F,EAAI,GAAG,UAAU,EAAY,EAAY,EAAI,GAAG,MAAO,EAAW,EAAS,EAAS,EAAK,CAAC,CAC5F,OAAS,EAAO,CACd,EAAe,YAAY,EAAiB,qBAAsB,CAAK,EACvE,EAAI,GAAG,UACL,EACA,2BAA2B,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,EACpF,CACF,CACF,CAAC,EACD,SAAY,IAAA,EACd,EAAG,CAAiB,CACtB,CAGA,eAAsB,EACpB,EACA,EAAgC,EAAyB,EAC1C,CACf,IAAM,EAAa,MAAM,EAAsB,EAAI,CAAiB,EAC9D,EAAQ,EAAW,KAAK,OAAO,EAAiB,CAAE,KAAI,WAAU,CAAC,EACvE,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"}
@@ -1,2 +1,2 @@
1
- const e=require("../../services/majorModeText.cjs"),t=require("../../services/pendingSelection.cjs"),n=require("../../types/majorMode.cjs"),r=require("../../schemas/majorModeVoiceTools.cjs");let i=require("@agimon-ai/doompi-extension-contracts/transition"),a=require("@agimon-ai/doompi-extension-contracts/voice-tools");function o(e){return{status:`listed`,current:e.majorMode,modes:Object.entries(e.config.majorMode).map(([e,t])=>({name:e,description:t.description,layers:[...t.layers]}))}}function s(s,c){(0,a.registerVoiceToolContribution)(s,{descriptor:{source:n.MAJOR_MODE_SOURCE,id:r.MAJOR_MODE_VOICE_TOOL_NAME,name:r.MAJOR_MODE_VOICE_TOOL_NAME,label:`Major Mode`,description:`List configured Doom major modes with their purpose and layers, or queue a validated mode switch.`,order:10,inputSchema:r.MAJOR_MODE_VOICE_INPUT_SCHEMA,resultSchema:r.MAJOR_MODE_VOICE_RESULT_SCHEMA},async execute(r,l){let u=r,d=await c(l.context);if(u.action===`list`)return o(d);let f=u.majorMode.trim();if(!Object.hasOwn(d.config.majorMode,f))throw Error(`Unknown major mode: ${f}. Known major modes: ${Object.keys(d.config.majorMode).sort().join(`, `)}`);if(f===d.majorMode)return t.clearPendingSelection(s,l.context),{status:`unchanged`,majorMode:f};let p=(0,i.requireDoomTransitionCoordinator)(l.context),m=p.plan({sessionId:l.sessionId,hostGeneration:p.hostGeneration,operationId:l.operationId,source:`voice`,target:{axis:`major-mode`,majorMode:f},signal:l.signal});if(m.disposition===`sync-required`)throw Error(`Major-mode transition requires doompi sync: ${m.diagnostics.join(`, `)}`);let h=(0,a.prepareVoiceReloadHandoff)({sessionId:l.sessionId,hostGeneration:l.hostGeneration,operationId:l.operationId,kind:n.MAJOR_MODE_SWITCH_HANDOFF_KIND,majorMode:f});try{s.sendUserMessage.bind(s)(`/${e.MAJOR_MODE_COMMAND} ${e.VOICE_SWITCH_TOKEN_PREFIX}${h.token}`,{deliverAs:`followUp`,expandPromptTemplates:!0})}catch(e){throw h.discard(),e}return{status:`queued`,majorMode:f,stopBatch:`session-reload`}}})}exports.registerMajorModeVoiceCapability=s;
1
+ const e=require("../../services/majorModeText.cjs"),t=require("../../services/pendingSelection.cjs"),n=require("../../types/majorMode.cjs"),r=require("../../schemas/majorModeVoiceTools.cjs");let i=require("@agimon-ai/doompi-extension-contracts/transition");function a(e){return{status:`listed`,current:e.majorMode,modes:Object.entries(e.config.majorMode).map(([e,t])=>({name:e,description:t.description,layers:[...t.layers]}))}}function o(o,s,c,l,u){let d=o.register({descriptor:{source:n.MAJOR_MODE_SOURCE,id:r.MAJOR_MODE_VOICE_TOOL_NAME,name:r.MAJOR_MODE_VOICE_TOOL_NAME,label:`Major Mode`,description:`List configured Doom major modes with their purpose and layers, or queue a validated mode switch.`,order:10,inputSchema:r.MAJOR_MODE_VOICE_INPUT_SCHEMA,resultSchema:r.MAJOR_MODE_VOICE_RESULT_SCHEMA},async execute(r,o){let d=r,f=await c(o.context);if(d.action===`list`)return a(f);let p=d.majorMode.trim();if(!Object.hasOwn(f.config.majorMode,p))throw Error(`Unknown major mode: ${p}. Known major modes: ${Object.keys(f.config.majorMode).sort().join(`, `)}`);if(p===f.majorMode)return t.clearPendingSelection(s,u()),{status:`unchanged`,majorMode:p};let m=(0,i.requireDoomTransitionCoordinator)(u()),h=m.plan({sessionId:o.sessionId,hostGeneration:m.hostGeneration,operationId:o.operationId,source:`voice`,target:{axis:`major-mode`,majorMode:p},signal:o.signal});if(h.disposition===`sync-required`)throw Error(`Major-mode transition requires doompi sync: ${h.diagnostics.join(`, `)}`);let g=l.prepare({active:!o.signal.aborted,sessionId:o.sessionId,hostGeneration:o.hostGeneration},{operationId:o.operationId,kind:n.MAJOR_MODE_SWITCH_HANDOFF_KIND,majorMode:p});try{s.sendUserMessage.bind(s)(`/${e.MAJOR_MODE_COMMAND} ${e.VOICE_SWITCH_TOKEN_PREFIX}${g.token}`,{deliverAs:`followUp`,expandPromptTemplates:!0})}catch(e){throw g.discard(),e}return{status:`queued`,majorMode:p,stopBatch:`session-reload`}}});return()=>d.dispose()}exports.registerMajorModeVoiceCapability=o;
2
2
  //# sourceMappingURL=voiceTool.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"voiceTool.cjs","names":["host","MAJOR_MODE_SOURCE","MAJOR_MODE_VOICE_TOOL_NAME","MAJOR_MODE_VOICE_INPUT_SCHEMA","MAJOR_MODE_VOICE_RESULT_SCHEMA","requireDoomTransitionCoordinator","prepareVoiceReloadHandoff","MAJOR_MODE_SWITCH_HANDOFF_KIND","MAJOR_MODE_COMMAND","VOICE_SWITCH_TOKEN_PREFIX"],"sources":["../../../src/adapters/pi/voiceTool.ts"],"sourcesContent":["import type { DoomExtensionHost } from '@agimon-ai/doompi-extension-contracts/config';\nimport { requireDoomTransitionCoordinator } from '@agimon-ai/doompi-extension-contracts/transition';\nimport {\n prepareVoiceReloadHandoff,\n registerVoiceToolContribution,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n MAJOR_MODE_VOICE_INPUT_SCHEMA,\n MAJOR_MODE_VOICE_RESULT_SCHEMA,\n MAJOR_MODE_VOICE_TOOL_NAME,\n type MajorModeVoiceInput,\n type MajorModeVoiceResult,\n} from '../../schemas/majorModeVoiceTools.ts';\nimport { MAJOR_MODE_COMMAND, VOICE_SWITCH_TOKEN_PREFIX } from '../../services/majorModeText.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND } from '../../types/majorMode.ts';\nimport { clearPendingSelection } from '../../services/pendingSelection.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\n\ntype VoiceMessageSender = (\n content: string,\n options: { readonly deliverAs: 'followUp'; readonly expandPromptTemplates: true },\n) => void;\n\nfunction majorModeListing(view: MajorModeView): MajorModeVoiceResult {\n return {\n status: 'listed',\n current: view.majorMode,\n modes: Object.entries(view.config.majorMode).map(([name, definition]) => ({\n name,\n description: definition.description,\n layers: [...definition.layers],\n })),\n };\n}\n\n/**\n * The model-facing half of the axis.\n *\n * A switch is never applied here. It plans the transition, mints an opaque\n * handoff token and sends `/mode --voice-switch-token=…` back as a follow-up, so\n * the reload happens inside a command handler where it can be the terminal\n * action.\n */\nexport function registerMajorModeVoiceCapability(\n pi: ExtensionAPI,\n currentView: (ctx: ExtensionContext) => Promise<MajorModeView>,\n): void {\n const host = pi as unknown as DoomExtensionHost<ExtensionContext>;\n registerVoiceToolContribution(host, {\n descriptor: {\n source: MAJOR_MODE_SOURCE,\n id: MAJOR_MODE_VOICE_TOOL_NAME,\n name: MAJOR_MODE_VOICE_TOOL_NAME,\n label: 'Major Mode',\n description: 'List configured Doom major modes with their purpose and layers, or queue a validated mode switch.',\n order: 10,\n inputSchema: MAJOR_MODE_VOICE_INPUT_SCHEMA,\n resultSchema: MAJOR_MODE_VOICE_RESULT_SCHEMA,\n },\n async execute(input, execution) {\n const params = input as MajorModeVoiceInput;\n const view = await currentView(execution.context);\n if (params.action === 'list') return majorModeListing(view);\n\n const majorMode = params.majorMode.trim();\n if (!Object.hasOwn(view.config.majorMode, majorMode)) {\n throw new Error(\n `Unknown major mode: ${majorMode}. Known major modes: ${Object.keys(view.config.majorMode).sort().join(', ')}`,\n );\n }\n if (majorMode === view.majorMode) {\n clearPendingSelection(pi, execution.context);\n return { status: 'unchanged', majorMode };\n }\n\n const coordinator = requireDoomTransitionCoordinator(execution.context);\n const transitionPlan = coordinator.plan({\n sessionId: execution.sessionId,\n hostGeneration: coordinator.hostGeneration,\n operationId: execution.operationId,\n source: 'voice',\n target: { axis: 'major-mode', majorMode },\n signal: execution.signal,\n });\n if (transitionPlan.disposition === 'sync-required') {\n throw new Error(`Major-mode transition requires doompi sync: ${transitionPlan.diagnostics.join(', ')}`);\n }\n\n const reloadHandoff = prepareVoiceReloadHandoff({\n sessionId: execution.sessionId,\n hostGeneration: execution.hostGeneration,\n operationId: execution.operationId,\n kind: MAJOR_MODE_SWITCH_HANDOFF_KIND,\n majorMode,\n });\n try {\n const sendUserMessage = pi.sendUserMessage.bind(pi) as unknown as VoiceMessageSender;\n sendUserMessage(`/${MAJOR_MODE_COMMAND} ${VOICE_SWITCH_TOKEN_PREFIX}${reloadHandoff.token}`, {\n deliverAs: 'followUp',\n expandPromptTemplates: true,\n });\n } catch (error) {\n reloadHandoff.discard();\n throw error;\n }\n return { status: 'queued', majorMode, stopBatch: 'session-reload' };\n },\n });\n}\n"],"mappings":"gUAwBA,SAAS,EAAiB,EAA2C,CACnE,MAAO,CACL,OAAQ,SACR,QAAS,EAAK,UACd,MAAO,OAAO,QAAQ,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,EAAM,MAAiB,CACxE,OACA,YAAa,EAAW,YACxB,OAAQ,CAAC,GAAG,EAAW,MAAM,CAC/B,EAAE,CACJ,CACF,CAUA,SAAgB,EACd,EACA,EACM,EAEN,EAAA,EAAA,8BAAA,CAA8BA,EAAM,CAClC,WAAY,CACV,OAAQC,EAAAA,kBACR,GAAIC,EAAAA,2BACJ,KAAMA,EAAAA,2BACN,MAAO,aACP,YAAa,oGACb,MAAO,GACP,YAAaC,EAAAA,8BACb,aAAcC,EAAAA,8BAChB,EACA,MAAM,QAAQ,EAAO,EAAW,CAC9B,IAAM,EAAS,EACT,EAAO,MAAM,EAAY,EAAU,OAAO,EAChD,GAAI,EAAO,SAAW,OAAQ,OAAO,EAAiB,CAAI,EAE1D,IAAM,EAAY,EAAO,UAAU,KAAK,EACxC,GAAI,CAAC,OAAO,OAAO,EAAK,OAAO,UAAW,CAAS,EACjD,MAAU,MACR,uBAAuB,EAAU,uBAAuB,OAAO,KAAK,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,GAC7G,EAEF,GAAI,IAAc,EAAK,UAErB,OADA,EAAA,sBAAsB,EAAI,EAAU,OAAO,EACpC,CAAE,OAAQ,YAAa,WAAU,EAG1C,IAAM,GAAA,EAAcC,EAAAA,iCAAAA,CAAiC,EAAU,OAAO,EAChE,EAAiB,EAAY,KAAK,CACtC,UAAW,EAAU,UACrB,eAAgB,EAAY,eAC5B,YAAa,EAAU,YACvB,OAAQ,QACR,OAAQ,CAAE,KAAM,aAAc,WAAU,EACxC,OAAQ,EAAU,MACpB,CAAC,EACD,GAAI,EAAe,cAAgB,gBACjC,MAAU,MAAM,+CAA+C,EAAe,YAAY,KAAK,IAAI,GAAG,EAGxG,IAAM,GAAA,EAAgBC,EAAAA,0BAAAA,CAA0B,CAC9C,UAAW,EAAU,UACrB,eAAgB,EAAU,eAC1B,YAAa,EAAU,YACvB,KAAMC,EAAAA,+BACN,WACF,CAAC,EACD,GAAI,CAEF,EAD2B,gBAAgB,KAAK,CAClC,CAAC,CAAC,IAAIC,EAAAA,mBAAmB,GAAGC,EAAAA,4BAA4B,EAAc,QAAS,CAC3F,UAAW,WACX,sBAAuB,EACzB,CAAC,CACH,OAAS,EAAO,CAEd,MADA,EAAc,QAAQ,EAChB,CACR,CACA,MAAO,CAAE,OAAQ,SAAU,YAAW,UAAW,gBAAiB,CACpE,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"voiceTool.cjs","names":["MAJOR_MODE_SOURCE","MAJOR_MODE_VOICE_TOOL_NAME","MAJOR_MODE_VOICE_INPUT_SCHEMA","MAJOR_MODE_VOICE_RESULT_SCHEMA","requireDoomTransitionCoordinator","MAJOR_MODE_SWITCH_HANDOFF_KIND","MAJOR_MODE_COMMAND","VOICE_SWITCH_TOKEN_PREFIX"],"sources":["../../../src/adapters/pi/voiceTool.ts"],"sourcesContent":["import { requireDoomTransitionCoordinator } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { DoomVoiceToolsService } from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { VoiceReloadHandoffStore } from '@agimon-ai/doompi-extension-contracts/voice-reload-handoff';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { Context } from '@deepseek-ai/cordis';\nimport {\n MAJOR_MODE_VOICE_INPUT_SCHEMA,\n MAJOR_MODE_VOICE_RESULT_SCHEMA,\n MAJOR_MODE_VOICE_TOOL_NAME,\n type MajorModeVoiceInput,\n type MajorModeVoiceResult,\n} from '../../schemas/majorModeVoiceTools.ts';\nimport { MAJOR_MODE_COMMAND, VOICE_SWITCH_TOKEN_PREFIX } from '../../services/majorModeText.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND } from '../../types/majorMode.ts';\nimport { clearPendingSelection } from '../../services/pendingSelection.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\n\ntype VoiceMessageSender = (\n content: string,\n options: { readonly deliverAs: 'followUp'; readonly expandPromptTemplates: true },\n) => void;\n\nfunction majorModeListing(view: MajorModeView): MajorModeVoiceResult {\n return {\n status: 'listed',\n current: view.majorMode,\n modes: Object.entries(view.config.majorMode).map(([name, definition]) => ({\n name,\n description: definition.description,\n layers: [...definition.layers],\n })),\n };\n}\n\n/**\n * The model-facing half of the axis.\n *\n * A switch is never applied here. It plans the transition, mints an opaque\n * handoff token and sends `/mode --voice-switch-token=…` back as a follow-up, so\n * the reload happens inside a command handler where it can be the terminal\n * action.\n */\nexport function registerMajorModeVoiceCapability(\n voiceTools: DoomVoiceToolsService<ExtensionContext>,\n pi: ExtensionAPI,\n currentView: (ctx: ExtensionContext) => Promise<MajorModeView>,\n reloadHandoffs: VoiceReloadHandoffStore,\n cordisContext: () => Context,\n): () => void {\n const registration = voiceTools.register({\n descriptor: {\n source: MAJOR_MODE_SOURCE,\n id: MAJOR_MODE_VOICE_TOOL_NAME,\n name: MAJOR_MODE_VOICE_TOOL_NAME,\n label: 'Major Mode',\n description: 'List configured Doom major modes with their purpose and layers, or queue a validated mode switch.',\n order: 10,\n inputSchema: MAJOR_MODE_VOICE_INPUT_SCHEMA,\n resultSchema: MAJOR_MODE_VOICE_RESULT_SCHEMA,\n },\n async execute(input, execution) {\n const params = input as MajorModeVoiceInput;\n const view = await currentView(execution.context);\n if (params.action === 'list') return majorModeListing(view);\n\n const majorMode = params.majorMode.trim();\n if (!Object.hasOwn(view.config.majorMode, majorMode)) {\n throw new Error(\n `Unknown major mode: ${majorMode}. Known major modes: ${Object.keys(view.config.majorMode).sort().join(', ')}`,\n );\n }\n if (majorMode === view.majorMode) {\n clearPendingSelection(pi, cordisContext());\n return { status: 'unchanged', majorMode };\n }\n\n const coordinator = requireDoomTransitionCoordinator(cordisContext());\n const transitionPlan = coordinator.plan({\n sessionId: execution.sessionId,\n hostGeneration: coordinator.hostGeneration,\n operationId: execution.operationId,\n source: 'voice',\n target: { axis: 'major-mode', majorMode },\n signal: execution.signal,\n });\n if (transitionPlan.disposition === 'sync-required') {\n throw new Error(`Major-mode transition requires doompi sync: ${transitionPlan.diagnostics.join(', ')}`);\n }\n\n const reloadHandoff = reloadHandoffs.prepare(\n {\n active: !execution.signal.aborted,\n sessionId: execution.sessionId,\n hostGeneration: execution.hostGeneration,\n },\n {\n operationId: execution.operationId,\n kind: MAJOR_MODE_SWITCH_HANDOFF_KIND,\n majorMode,\n },\n );\n try {\n const sendUserMessage = pi.sendUserMessage.bind(pi) as unknown as VoiceMessageSender;\n sendUserMessage(`/${MAJOR_MODE_COMMAND} ${VOICE_SWITCH_TOKEN_PREFIX}${reloadHandoff.token}`, {\n deliverAs: 'followUp',\n expandPromptTemplates: true,\n });\n } catch (error) {\n reloadHandoff.discard();\n throw error;\n }\n return { status: 'queued', majorMode, stopBatch: 'session-reload' };\n },\n });\n return () => registration.dispose();\n}\n"],"mappings":"iQAsBA,SAAS,EAAiB,EAA2C,CACnE,MAAO,CACL,OAAQ,SACR,QAAS,EAAK,UACd,MAAO,OAAO,QAAQ,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,EAAM,MAAiB,CACxE,OACA,YAAa,EAAW,YACxB,OAAQ,CAAC,GAAG,EAAW,MAAM,CAC/B,EAAE,CACJ,CACF,CAUA,SAAgB,EACd,EACA,EACA,EACA,EACA,EACY,CACZ,IAAM,EAAe,EAAW,SAAS,CACvC,WAAY,CACV,OAAQA,EAAAA,kBACR,GAAIC,EAAAA,2BACJ,KAAMA,EAAAA,2BACN,MAAO,aACP,YAAa,oGACb,MAAO,GACP,YAAaC,EAAAA,8BACb,aAAcC,EAAAA,8BAChB,EACA,MAAM,QAAQ,EAAO,EAAW,CAC9B,IAAM,EAAS,EACT,EAAO,MAAM,EAAY,EAAU,OAAO,EAChD,GAAI,EAAO,SAAW,OAAQ,OAAO,EAAiB,CAAI,EAE1D,IAAM,EAAY,EAAO,UAAU,KAAK,EACxC,GAAI,CAAC,OAAO,OAAO,EAAK,OAAO,UAAW,CAAS,EACjD,MAAU,MACR,uBAAuB,EAAU,uBAAuB,OAAO,KAAK,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,GAC7G,EAEF,GAAI,IAAc,EAAK,UAErB,OADA,EAAA,sBAAsB,EAAI,EAAc,CAAC,EAClC,CAAE,OAAQ,YAAa,WAAU,EAG1C,IAAM,GAAA,EAAcC,EAAAA,iCAAAA,CAAiC,EAAc,CAAC,EAC9D,EAAiB,EAAY,KAAK,CACtC,UAAW,EAAU,UACrB,eAAgB,EAAY,eAC5B,YAAa,EAAU,YACvB,OAAQ,QACR,OAAQ,CAAE,KAAM,aAAc,WAAU,EACxC,OAAQ,EAAU,MACpB,CAAC,EACD,GAAI,EAAe,cAAgB,gBACjC,MAAU,MAAM,+CAA+C,EAAe,YAAY,KAAK,IAAI,GAAG,EAGxG,IAAM,EAAgB,EAAe,QACnC,CACE,OAAQ,CAAC,EAAU,OAAO,QAC1B,UAAW,EAAU,UACrB,eAAgB,EAAU,cAC5B,EACA,CACE,YAAa,EAAU,YACvB,KAAMC,EAAAA,+BACN,WACF,CACF,EACA,GAAI,CAEF,EAD2B,gBAAgB,KAAK,CAClC,CAAC,CAAC,IAAIC,EAAAA,mBAAmB,GAAGC,EAAAA,4BAA4B,EAAc,QAAS,CAC3F,UAAW,WACX,sBAAuB,EACzB,CAAC,CACH,OAAS,EAAO,CAEd,MADA,EAAc,QAAQ,EAChB,CACR,CACA,MAAO,CAAE,OAAQ,SAAU,YAAW,UAAW,gBAAiB,CACpE,CACF,CAAC,EACD,UAAa,EAAa,QAAQ,CACpC"}
@@ -1,5 +1,8 @@
1
1
  import { MajorModeView } from "../../types/majorMode.cjs";
2
2
  import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
3
+ import { DoomVoiceToolsService } from "@agimon-ai/doompi-extension-contracts/voice-tools";
4
+ import { VoiceReloadHandoffStore } from "@agimon-ai/doompi-extension-contracts/voice-reload-handoff";
5
+ import { Context } from "@deepseek-ai/cordis";
3
6
  //#region src/adapters/pi/voiceTool.d.ts
4
7
  /**
5
8
  * The model-facing half of the axis.
@@ -9,7 +12,7 @@ import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"
9
12
  * the reload happens inside a command handler where it can be the terminal
10
13
  * action.
11
14
  */
12
- declare function registerMajorModeVoiceCapability(pi: ExtensionAPI, currentView: (ctx: ExtensionContext) => Promise<MajorModeView>): void;
15
+ declare function registerMajorModeVoiceCapability(voiceTools: DoomVoiceToolsService<ExtensionContext>, pi: ExtensionAPI, currentView: (ctx: ExtensionContext) => Promise<MajorModeView>, reloadHandoffs: VoiceReloadHandoffStore, cordisContext: () => Context): () => void;
13
16
  //#endregion
14
17
  export { registerMajorModeVoiceCapability };
15
18
  //# sourceMappingURL=voiceTool.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"voiceTool.d.cts","names":[],"sources":["../../../src/adapters/pi/voiceTool.ts"],"mappings":";;;;;;;;;;;iBA4CgB,iCACd,IAAI,cACJ,cAAc,KAAK,qBAAqB,QAAQ"}
1
+ {"version":3,"file":"voiceTool.d.cts","names":[],"sources":["../../../src/adapters/pi/voiceTool.ts"],"mappings":";;;;;;;;;;;;;;iBA0CgB,iCACd,YAAY,sBAAsB,mBAClC,IAAI,cACJ,cAAc,KAAK,qBAAqB,QAAQ,gBAChD,gBAAgB,yBAChB,qBAAqB"}
@@ -1,5 +1,8 @@
1
1
  import { MajorModeView } from "../../types/majorMode.mjs";
2
+ import { DoomVoiceToolsService } from "@agimon-ai/doompi-extension-contracts/voice-tools";
3
+ import { VoiceReloadHandoffStore } from "@agimon-ai/doompi-extension-contracts/voice-reload-handoff";
2
4
  import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
5
+ import { Context } from "@deepseek-ai/cordis";
3
6
  //#region src/adapters/pi/voiceTool.d.ts
4
7
  /**
5
8
  * The model-facing half of the axis.
@@ -9,7 +12,7 @@ import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"
9
12
  * the reload happens inside a command handler where it can be the terminal
10
13
  * action.
11
14
  */
12
- declare function registerMajorModeVoiceCapability(pi: ExtensionAPI, currentView: (ctx: ExtensionContext) => Promise<MajorModeView>): void;
15
+ declare function registerMajorModeVoiceCapability(voiceTools: DoomVoiceToolsService<ExtensionContext>, pi: ExtensionAPI, currentView: (ctx: ExtensionContext) => Promise<MajorModeView>, reloadHandoffs: VoiceReloadHandoffStore, cordisContext: () => Context): () => void;
13
16
  //#endregion
14
17
  export { registerMajorModeVoiceCapability };
15
18
  //# sourceMappingURL=voiceTool.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"voiceTool.d.mts","names":[],"sources":["../../../src/adapters/pi/voiceTool.ts"],"mappings":";;;;;;;;;;;iBA4CgB,iCACd,IAAI,cACJ,cAAc,KAAK,qBAAqB,QAAQ"}
1
+ {"version":3,"file":"voiceTool.d.mts","names":[],"sources":["../../../src/adapters/pi/voiceTool.ts"],"mappings":";;;;;;;;;;;;;;iBA0CgB,iCACd,YAAY,sBAAsB,mBAClC,IAAI,cACJ,cAAc,KAAK,qBAAqB,QAAQ,gBAChD,gBAAgB,yBAChB,qBAAqB"}
@@ -1,2 +1,2 @@
1
- import{MAJOR_MODE_COMMAND as e,VOICE_SWITCH_TOKEN_PREFIX as t}from"../../services/majorModeText.mjs";import{clearPendingSelection as n}from"../../services/pendingSelection.mjs";import{MAJOR_MODE_SOURCE as r,MAJOR_MODE_SWITCH_HANDOFF_KIND as i}from"../../types/majorMode.mjs";import{MAJOR_MODE_VOICE_INPUT_SCHEMA as a,MAJOR_MODE_VOICE_RESULT_SCHEMA as o,MAJOR_MODE_VOICE_TOOL_NAME as s}from"../../schemas/majorModeVoiceTools.mjs";import{requireDoomTransitionCoordinator as c}from"@agimon-ai/doompi-extension-contracts/transition";import{prepareVoiceReloadHandoff as l,registerVoiceToolContribution as u}from"@agimon-ai/doompi-extension-contracts/voice-tools";function d(e){return{status:`listed`,current:e.majorMode,modes:Object.entries(e.config.majorMode).map(([e,t])=>({name:e,description:t.description,layers:[...t.layers]}))}}function f(f,p){u(f,{descriptor:{source:r,id:s,name:s,label:`Major Mode`,description:`List configured Doom major modes with their purpose and layers, or queue a validated mode switch.`,order:10,inputSchema:a,resultSchema:o},async execute(r,a){let o=r,s=await p(a.context);if(o.action===`list`)return d(s);let u=o.majorMode.trim();if(!Object.hasOwn(s.config.majorMode,u))throw Error(`Unknown major mode: ${u}. Known major modes: ${Object.keys(s.config.majorMode).sort().join(`, `)}`);if(u===s.majorMode)return n(f,a.context),{status:`unchanged`,majorMode:u};let m=c(a.context),h=m.plan({sessionId:a.sessionId,hostGeneration:m.hostGeneration,operationId:a.operationId,source:`voice`,target:{axis:`major-mode`,majorMode:u},signal:a.signal});if(h.disposition===`sync-required`)throw Error(`Major-mode transition requires doompi sync: ${h.diagnostics.join(`, `)}`);let g=l({sessionId:a.sessionId,hostGeneration:a.hostGeneration,operationId:a.operationId,kind:i,majorMode:u});try{f.sendUserMessage.bind(f)(`/${e} ${t}${g.token}`,{deliverAs:`followUp`,expandPromptTemplates:!0})}catch(e){throw g.discard(),e}return{status:`queued`,majorMode:u,stopBatch:`session-reload`}}})}export{f as registerMajorModeVoiceCapability};
1
+ import{MAJOR_MODE_COMMAND as e,VOICE_SWITCH_TOKEN_PREFIX as t}from"../../services/majorModeText.mjs";import{clearPendingSelection as n}from"../../services/pendingSelection.mjs";import{MAJOR_MODE_SOURCE as r,MAJOR_MODE_SWITCH_HANDOFF_KIND as i}from"../../types/majorMode.mjs";import{MAJOR_MODE_VOICE_INPUT_SCHEMA as a,MAJOR_MODE_VOICE_RESULT_SCHEMA as o,MAJOR_MODE_VOICE_TOOL_NAME as s}from"../../schemas/majorModeVoiceTools.mjs";import{requireDoomTransitionCoordinator as c}from"@agimon-ai/doompi-extension-contracts/transition";function l(e){return{status:`listed`,current:e.majorMode,modes:Object.entries(e.config.majorMode).map(([e,t])=>({name:e,description:t.description,layers:[...t.layers]}))}}function u(u,d,f,p,m){let h=u.register({descriptor:{source:r,id:s,name:s,label:`Major Mode`,description:`List configured Doom major modes with their purpose and layers, or queue a validated mode switch.`,order:10,inputSchema:a,resultSchema:o},async execute(r,a){let o=r,s=await f(a.context);if(o.action===`list`)return l(s);let u=o.majorMode.trim();if(!Object.hasOwn(s.config.majorMode,u))throw Error(`Unknown major mode: ${u}. Known major modes: ${Object.keys(s.config.majorMode).sort().join(`, `)}`);if(u===s.majorMode)return n(d,m()),{status:`unchanged`,majorMode:u};let h=c(m()),g=h.plan({sessionId:a.sessionId,hostGeneration:h.hostGeneration,operationId:a.operationId,source:`voice`,target:{axis:`major-mode`,majorMode:u},signal:a.signal});if(g.disposition===`sync-required`)throw Error(`Major-mode transition requires doompi sync: ${g.diagnostics.join(`, `)}`);let _=p.prepare({active:!a.signal.aborted,sessionId:a.sessionId,hostGeneration:a.hostGeneration},{operationId:a.operationId,kind:i,majorMode:u});try{d.sendUserMessage.bind(d)(`/${e} ${t}${_.token}`,{deliverAs:`followUp`,expandPromptTemplates:!0})}catch(e){throw _.discard(),e}return{status:`queued`,majorMode:u,stopBatch:`session-reload`}}});return()=>h.dispose()}export{u as registerMajorModeVoiceCapability};
2
2
  //# sourceMappingURL=voiceTool.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"voiceTool.mjs","names":["host"],"sources":["../../../src/adapters/pi/voiceTool.ts"],"sourcesContent":["import type { DoomExtensionHost } from '@agimon-ai/doompi-extension-contracts/config';\nimport { requireDoomTransitionCoordinator } from '@agimon-ai/doompi-extension-contracts/transition';\nimport {\n prepareVoiceReloadHandoff,\n registerVoiceToolContribution,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n MAJOR_MODE_VOICE_INPUT_SCHEMA,\n MAJOR_MODE_VOICE_RESULT_SCHEMA,\n MAJOR_MODE_VOICE_TOOL_NAME,\n type MajorModeVoiceInput,\n type MajorModeVoiceResult,\n} from '../../schemas/majorModeVoiceTools.ts';\nimport { MAJOR_MODE_COMMAND, VOICE_SWITCH_TOKEN_PREFIX } from '../../services/majorModeText.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND } from '../../types/majorMode.ts';\nimport { clearPendingSelection } from '../../services/pendingSelection.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\n\ntype VoiceMessageSender = (\n content: string,\n options: { readonly deliverAs: 'followUp'; readonly expandPromptTemplates: true },\n) => void;\n\nfunction majorModeListing(view: MajorModeView): MajorModeVoiceResult {\n return {\n status: 'listed',\n current: view.majorMode,\n modes: Object.entries(view.config.majorMode).map(([name, definition]) => ({\n name,\n description: definition.description,\n layers: [...definition.layers],\n })),\n };\n}\n\n/**\n * The model-facing half of the axis.\n *\n * A switch is never applied here. It plans the transition, mints an opaque\n * handoff token and sends `/mode --voice-switch-token=…` back as a follow-up, so\n * the reload happens inside a command handler where it can be the terminal\n * action.\n */\nexport function registerMajorModeVoiceCapability(\n pi: ExtensionAPI,\n currentView: (ctx: ExtensionContext) => Promise<MajorModeView>,\n): void {\n const host = pi as unknown as DoomExtensionHost<ExtensionContext>;\n registerVoiceToolContribution(host, {\n descriptor: {\n source: MAJOR_MODE_SOURCE,\n id: MAJOR_MODE_VOICE_TOOL_NAME,\n name: MAJOR_MODE_VOICE_TOOL_NAME,\n label: 'Major Mode',\n description: 'List configured Doom major modes with their purpose and layers, or queue a validated mode switch.',\n order: 10,\n inputSchema: MAJOR_MODE_VOICE_INPUT_SCHEMA,\n resultSchema: MAJOR_MODE_VOICE_RESULT_SCHEMA,\n },\n async execute(input, execution) {\n const params = input as MajorModeVoiceInput;\n const view = await currentView(execution.context);\n if (params.action === 'list') return majorModeListing(view);\n\n const majorMode = params.majorMode.trim();\n if (!Object.hasOwn(view.config.majorMode, majorMode)) {\n throw new Error(\n `Unknown major mode: ${majorMode}. Known major modes: ${Object.keys(view.config.majorMode).sort().join(', ')}`,\n );\n }\n if (majorMode === view.majorMode) {\n clearPendingSelection(pi, execution.context);\n return { status: 'unchanged', majorMode };\n }\n\n const coordinator = requireDoomTransitionCoordinator(execution.context);\n const transitionPlan = coordinator.plan({\n sessionId: execution.sessionId,\n hostGeneration: coordinator.hostGeneration,\n operationId: execution.operationId,\n source: 'voice',\n target: { axis: 'major-mode', majorMode },\n signal: execution.signal,\n });\n if (transitionPlan.disposition === 'sync-required') {\n throw new Error(`Major-mode transition requires doompi sync: ${transitionPlan.diagnostics.join(', ')}`);\n }\n\n const reloadHandoff = prepareVoiceReloadHandoff({\n sessionId: execution.sessionId,\n hostGeneration: execution.hostGeneration,\n operationId: execution.operationId,\n kind: MAJOR_MODE_SWITCH_HANDOFF_KIND,\n majorMode,\n });\n try {\n const sendUserMessage = pi.sendUserMessage.bind(pi) as unknown as VoiceMessageSender;\n sendUserMessage(`/${MAJOR_MODE_COMMAND} ${VOICE_SWITCH_TOKEN_PREFIX}${reloadHandoff.token}`, {\n deliverAs: 'followUp',\n expandPromptTemplates: true,\n });\n } catch (error) {\n reloadHandoff.discard();\n throw error;\n }\n return { status: 'queued', majorMode, stopBatch: 'session-reload' };\n },\n });\n}\n"],"mappings":"kpBAwBA,SAAS,EAAiB,EAA2C,CACnE,MAAO,CACL,OAAQ,SACR,QAAS,EAAK,UACd,MAAO,OAAO,QAAQ,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,EAAM,MAAiB,CACxE,OACA,YAAa,EAAW,YACxB,OAAQ,CAAC,GAAG,EAAW,MAAM,CAC/B,EAAE,CACJ,CACF,CAUA,SAAgB,EACd,EACA,EACM,CAEN,EAA8BA,EAAM,CAClC,WAAY,CACV,OAAQ,EACR,GAAI,EACJ,KAAM,EACN,MAAO,aACP,YAAa,oGACb,MAAO,GACP,YAAa,EACb,aAAc,CAChB,EACA,MAAM,QAAQ,EAAO,EAAW,CAC9B,IAAM,EAAS,EACT,EAAO,MAAM,EAAY,EAAU,OAAO,EAChD,GAAI,EAAO,SAAW,OAAQ,OAAO,EAAiB,CAAI,EAE1D,IAAM,EAAY,EAAO,UAAU,KAAK,EACxC,GAAI,CAAC,OAAO,OAAO,EAAK,OAAO,UAAW,CAAS,EACjD,MAAU,MACR,uBAAuB,EAAU,uBAAuB,OAAO,KAAK,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,GAC7G,EAEF,GAAI,IAAc,EAAK,UAErB,OADA,EAAsB,EAAI,EAAU,OAAO,EACpC,CAAE,OAAQ,YAAa,WAAU,EAG1C,IAAM,EAAc,EAAiC,EAAU,OAAO,EAChE,EAAiB,EAAY,KAAK,CACtC,UAAW,EAAU,UACrB,eAAgB,EAAY,eAC5B,YAAa,EAAU,YACvB,OAAQ,QACR,OAAQ,CAAE,KAAM,aAAc,WAAU,EACxC,OAAQ,EAAU,MACpB,CAAC,EACD,GAAI,EAAe,cAAgB,gBACjC,MAAU,MAAM,+CAA+C,EAAe,YAAY,KAAK,IAAI,GAAG,EAGxG,IAAM,EAAgB,EAA0B,CAC9C,UAAW,EAAU,UACrB,eAAgB,EAAU,eAC1B,YAAa,EAAU,YACvB,KAAM,EACN,WACF,CAAC,EACD,GAAI,CAEF,EAD2B,gBAAgB,KAAK,CAClC,CAAC,CAAC,IAAI,EAAmB,GAAG,IAA4B,EAAc,QAAS,CAC3F,UAAW,WACX,sBAAuB,EACzB,CAAC,CACH,OAAS,EAAO,CAEd,MADA,EAAc,QAAQ,EAChB,CACR,CACA,MAAO,CAAE,OAAQ,SAAU,YAAW,UAAW,gBAAiB,CACpE,CACF,CAAC,CACH"}
1
+ {"version":3,"file":"voiceTool.mjs","names":[],"sources":["../../../src/adapters/pi/voiceTool.ts"],"sourcesContent":["import { requireDoomTransitionCoordinator } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { DoomVoiceToolsService } from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { VoiceReloadHandoffStore } from '@agimon-ai/doompi-extension-contracts/voice-reload-handoff';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { Context } from '@deepseek-ai/cordis';\nimport {\n MAJOR_MODE_VOICE_INPUT_SCHEMA,\n MAJOR_MODE_VOICE_RESULT_SCHEMA,\n MAJOR_MODE_VOICE_TOOL_NAME,\n type MajorModeVoiceInput,\n type MajorModeVoiceResult,\n} from '../../schemas/majorModeVoiceTools.ts';\nimport { MAJOR_MODE_COMMAND, VOICE_SWITCH_TOKEN_PREFIX } from '../../services/majorModeText.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND } from '../../types/majorMode.ts';\nimport { clearPendingSelection } from '../../services/pendingSelection.ts';\nimport { MAJOR_MODE_SOURCE, type MajorModeView } from '../../types/majorMode.ts';\n\ntype VoiceMessageSender = (\n content: string,\n options: { readonly deliverAs: 'followUp'; readonly expandPromptTemplates: true },\n) => void;\n\nfunction majorModeListing(view: MajorModeView): MajorModeVoiceResult {\n return {\n status: 'listed',\n current: view.majorMode,\n modes: Object.entries(view.config.majorMode).map(([name, definition]) => ({\n name,\n description: definition.description,\n layers: [...definition.layers],\n })),\n };\n}\n\n/**\n * The model-facing half of the axis.\n *\n * A switch is never applied here. It plans the transition, mints an opaque\n * handoff token and sends `/mode --voice-switch-token=…` back as a follow-up, so\n * the reload happens inside a command handler where it can be the terminal\n * action.\n */\nexport function registerMajorModeVoiceCapability(\n voiceTools: DoomVoiceToolsService<ExtensionContext>,\n pi: ExtensionAPI,\n currentView: (ctx: ExtensionContext) => Promise<MajorModeView>,\n reloadHandoffs: VoiceReloadHandoffStore,\n cordisContext: () => Context,\n): () => void {\n const registration = voiceTools.register({\n descriptor: {\n source: MAJOR_MODE_SOURCE,\n id: MAJOR_MODE_VOICE_TOOL_NAME,\n name: MAJOR_MODE_VOICE_TOOL_NAME,\n label: 'Major Mode',\n description: 'List configured Doom major modes with their purpose and layers, or queue a validated mode switch.',\n order: 10,\n inputSchema: MAJOR_MODE_VOICE_INPUT_SCHEMA,\n resultSchema: MAJOR_MODE_VOICE_RESULT_SCHEMA,\n },\n async execute(input, execution) {\n const params = input as MajorModeVoiceInput;\n const view = await currentView(execution.context);\n if (params.action === 'list') return majorModeListing(view);\n\n const majorMode = params.majorMode.trim();\n if (!Object.hasOwn(view.config.majorMode, majorMode)) {\n throw new Error(\n `Unknown major mode: ${majorMode}. Known major modes: ${Object.keys(view.config.majorMode).sort().join(', ')}`,\n );\n }\n if (majorMode === view.majorMode) {\n clearPendingSelection(pi, cordisContext());\n return { status: 'unchanged', majorMode };\n }\n\n const coordinator = requireDoomTransitionCoordinator(cordisContext());\n const transitionPlan = coordinator.plan({\n sessionId: execution.sessionId,\n hostGeneration: coordinator.hostGeneration,\n operationId: execution.operationId,\n source: 'voice',\n target: { axis: 'major-mode', majorMode },\n signal: execution.signal,\n });\n if (transitionPlan.disposition === 'sync-required') {\n throw new Error(`Major-mode transition requires doompi sync: ${transitionPlan.diagnostics.join(', ')}`);\n }\n\n const reloadHandoff = reloadHandoffs.prepare(\n {\n active: !execution.signal.aborted,\n sessionId: execution.sessionId,\n hostGeneration: execution.hostGeneration,\n },\n {\n operationId: execution.operationId,\n kind: MAJOR_MODE_SWITCH_HANDOFF_KIND,\n majorMode,\n },\n );\n try {\n const sendUserMessage = pi.sendUserMessage.bind(pi) as unknown as VoiceMessageSender;\n sendUserMessage(`/${MAJOR_MODE_COMMAND} ${VOICE_SWITCH_TOKEN_PREFIX}${reloadHandoff.token}`, {\n deliverAs: 'followUp',\n expandPromptTemplates: true,\n });\n } catch (error) {\n reloadHandoff.discard();\n throw error;\n }\n return { status: 'queued', majorMode, stopBatch: 'session-reload' };\n },\n });\n return () => registration.dispose();\n}\n"],"mappings":"ihBAsBA,SAAS,EAAiB,EAA2C,CACnE,MAAO,CACL,OAAQ,SACR,QAAS,EAAK,UACd,MAAO,OAAO,QAAQ,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,EAAM,MAAiB,CACxE,OACA,YAAa,EAAW,YACxB,OAAQ,CAAC,GAAG,EAAW,MAAM,CAC/B,EAAE,CACJ,CACF,CAUA,SAAgB,EACd,EACA,EACA,EACA,EACA,EACY,CACZ,IAAM,EAAe,EAAW,SAAS,CACvC,WAAY,CACV,OAAQ,EACR,GAAI,EACJ,KAAM,EACN,MAAO,aACP,YAAa,oGACb,MAAO,GACP,YAAa,EACb,aAAc,CAChB,EACA,MAAM,QAAQ,EAAO,EAAW,CAC9B,IAAM,EAAS,EACT,EAAO,MAAM,EAAY,EAAU,OAAO,EAChD,GAAI,EAAO,SAAW,OAAQ,OAAO,EAAiB,CAAI,EAE1D,IAAM,EAAY,EAAO,UAAU,KAAK,EACxC,GAAI,CAAC,OAAO,OAAO,EAAK,OAAO,UAAW,CAAS,EACjD,MAAU,MACR,uBAAuB,EAAU,uBAAuB,OAAO,KAAK,EAAK,OAAO,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,GAC7G,EAEF,GAAI,IAAc,EAAK,UAErB,OADA,EAAsB,EAAI,EAAc,CAAC,EAClC,CAAE,OAAQ,YAAa,WAAU,EAG1C,IAAM,EAAc,EAAiC,EAAc,CAAC,EAC9D,EAAiB,EAAY,KAAK,CACtC,UAAW,EAAU,UACrB,eAAgB,EAAY,eAC5B,YAAa,EAAU,YACvB,OAAQ,QACR,OAAQ,CAAE,KAAM,aAAc,WAAU,EACxC,OAAQ,EAAU,MACpB,CAAC,EACD,GAAI,EAAe,cAAgB,gBACjC,MAAU,MAAM,+CAA+C,EAAe,YAAY,KAAK,IAAI,GAAG,EAGxG,IAAM,EAAgB,EAAe,QACnC,CACE,OAAQ,CAAC,EAAU,OAAO,QAC1B,UAAW,EAAU,UACrB,eAAgB,EAAU,cAC5B,EACA,CACE,YAAa,EAAU,YACvB,KAAM,EACN,WACF,CACF,EACA,GAAI,CAEF,EAD2B,gBAAgB,KAAK,CAClC,CAAC,CAAC,IAAI,EAAmB,GAAG,IAA4B,EAAc,QAAS,CAC3F,UAAW,WACX,sBAAuB,EACzB,CAAC,CACH,OAAS,EAAO,CAEd,MADA,EAAc,QAAQ,EAChB,CACR,CACA,MAAO,CAAE,OAAQ,SAAU,YAAW,UAAW,gBAAiB,CACpE,CACF,CAAC,EACD,UAAa,EAAa,QAAQ,CACpC"}
@@ -1,2 +1,2 @@
1
- const e=require("../services/majorModeText.cjs"),t=require("../services/statusLine.cjs"),n=require("../types/telemetry.cjs"),r=require("../services/pendingSelection.cjs");require("../types/majorMode.cjs");let i=require("@agimon-ai/doompi-config/harnessStore"),a=require("@agimon-ai/doompi-config/piContext"),o=require("@agimon-ai/doompi-config/majorModes"),s=require("@agimon-ai/doompi-extension-contracts/child-process"),c=require("@agimon-ai/doompi-extension-contracts/transition"),l=require("@agimon-ai/doompi-extension-contracts/voice-tools");function u(e){return Error(`Major-mode transition was ${e.outcome}: ${e.diagnostics.join(`, `)}`)}function d(d,f,p){d.registerCommand(e.MAJOR_MODE_COMMAND,{description:`Pick a named major mode`,handler:async(m,h)=>{let g;try{g=e.voiceSwitchToken(m)}catch(t){h.ui.notify(e.errorMessage(t),`error`);return}if(m.trim()&&!g){h.ui.notify(`Usage: /${e.MAJOR_MODE_COMMAND}`,`warning`);return}let _={sessionId:h.sessionManager.getSessionId()},v,y,b=!1;try{let{config:m,majorMode:x,domains:S,profile:C}=await p.currentView(h),w=Object.keys(m.majorMode),T;if(g){if(v=(0,l.acceptVoiceReloadHandoff)(g,_),v?.kind!==`major-mode-switch`||!v.majorMode)throw Error(`The voice major-mode switch token is stale or belongs to another session.`);T=v.majorMode}else{let t=`Major mode (current: ${x})`;T=(h.mode===`tui`?await p.loadPicker().then(({MatrixPickerComponent:n})=>h.ui.custom((r,i,a,o)=>new n({title:t,items:e.majorModeItems(m,w),selected:[x],multi:!1},i,a,o))):[e.optionName(await h.ui.select(t,w.map(t=>e.majorModeOptionLabel(t,m.majorMode[t]?.layers??[],x)))??``)])?.[0]}if(!T)return;let E=(0,s.alreadyComposed)();if(T===x){g&&(0,l.discardVoiceReloadHandoff)(g,_),r.clearPendingSelection(d,h),h.ui.notify(e.majorModeSummary(T,p.resolveLayers(m,T),x,E),`info`);return}let D=(0,c.requireDoomTransitionCoordinator)(h),O=await D.execute({sessionId:h.sessionManager.getSessionId(),hostGeneration:D.hostGeneration,operationId:v?.operationId??crypto.randomUUID(),source:v?`voice`:`command`,target:{axis:`major-mode`,majorMode:T}},async(s,l)=>{let u=[...l.candidate.layers],m=l.externalRelaunchRequired,g=(0,a.requireDoomConfigContext)(h),_=g.harness;if(l.strategy===`process-relaunch`){let i={version:1,operationId:l.operationId,active:r.selectionFromSnapshot(l.previous),target:r.selectionFromSnapshot(l.candidate),strategy:l.strategy,phase:`pending`},o=(0,a.requireDoomConfigContext)(h).pendingSelection;return o&&(0,a.supersedeDoomConfigTransition)(d,o),(0,a.appendDoomConfigTransition)(d,i),(0,a.provideDoomConfigContext)(h,r.bindPendingSelection((0,a.requireDoomConfigContext)(h),i)),f.recordEvent(n.MAJOR_MODE_EVENT.majorModeSwitched,{"harness.major_mode.previous":_.majorMode,"harness.major_mode":T,"harness.layers":u.join(`,`),"harness.major_mode.stale":!0,"harness.transition.disposition":l.disposition,"harness.transition.operation_id":l.operationId}),h.ui.setStatus(t.STATUS_KEY,t.colorStatus(h.ui.theme,_.majorMode,_.domains,_.profile,!0)),h.ui.notify(e.applySummary(T,u,!0,E,l.strategy),`info`),`queued`}let[{applyMajorMode:v},{persistHarnessSelection:w}]=await Promise.all([p.loadSelectionSwitch(),p.loadConfigJournal()]),O={version:1,operationId:l.operationId,active:r.selectionFromSnapshot(l.previous),target:r.selectionFromSnapshot(l.candidate),strategy:l.strategy??`pi-reload`,phase:`pending`},k=(0,o.loadMajorModesConfig)(_.root??h.cwd),A=(0,i.snapshotHarnessState)(),j=g.pendingSelection;y=(0,c.prepareMinorModeReloadHandoff)(h,D.hostGeneration,l.operationId,l.previous.minorModes);try{j&&(0,a.supersedeDoomConfigTransition)(d,j),(0,a.appendDoomConfigTransition)(d,O),w(d,v(k,T,_,l.candidate.compositionFingerprint,l.candidate.childActivation))}catch(e){y?.discard(),y=void 0;try{(0,i.restoreHarnessStateSnapshot)(A)}catch(t){let n=t instanceof Error?t.message:String(t);throw Error(`Transition failed and compensation failed: ${n}`,{cause:e})}throw(0,a.appendDoomConfigTransition)(d,{...O,phase:`aborted`}),j&&(0,a.appendDoomConfigTransition)(d,j),e}return f.recordEvent(n.MAJOR_MODE_EVENT.majorModeSwitched,{"harness.major_mode.previous":x,"harness.major_mode":T,"harness.layers":u.join(`,`),"harness.major_mode.stale":m,"harness.transition.disposition":l.disposition,"harness.transition.operation_id":l.operationId}),h.ui.setStatus(t.STATUS_KEY,t.colorStatus(h.ui.theme,T,S,C,!1)),h.ui.notify(e.applySummary(T,u,!1,E,l.strategy),`info`),b=!0,`applied`});if(O.outcome===`rejected`||O.outcome===`stale`)throw u(O)}catch(t){if(b=!1,y?.discard(),y=void 0,!g)throw t;(0,l.discardVoiceReloadHandoff)(g,_),h.ui.notify(e.errorMessage(t),`error`)}if(b)try{await h.waitForIdle(),await h.reload()}catch(e){throw y?.discard(),e}}})}exports.registerMajorModeCommand=d;
1
+ const e=require("../services/majorModeText.cjs"),t=require("../services/statusLine.cjs"),n=require("../types/telemetry.cjs"),r=require("../services/pendingSelection.cjs");require("../types/majorMode.cjs");let i=require("@agimon-ai/doompi-config/harnessStore"),a=require("@agimon-ai/doompi-config/piContext"),o=require("@agimon-ai/doompi-extension-contracts/transition"),s=require("@agimon-ai/doompi-extension-contracts/voice-tools"),c=require("@agimon-ai/doompi-config/majorModes"),l=require("@agimon-ai/doompi-extension-contracts/child-process");function u(e){return Error(`Major-mode transition was ${e.outcome}: ${e.diagnostics.join(`, `)}`)}function d(d,f,p){d.registerCommand(e.MAJOR_MODE_COMMAND,{description:`Pick a named major mode`,handler:async(m,h)=>{let g;try{g=e.voiceSwitchToken(m)}catch(t){h.ui.notify(e.errorMessage(t),`error`);return}if(m.trim()&&!g){h.ui.notify(`Usage: /${e.MAJOR_MODE_COMMAND}`,`warning`);return}let _=h.sessionManager.getSessionId(),v=p.cordisContext(),y,b,x,S=!1;try{let{config:m,majorMode:C,domains:w,profile:T}=await p.currentView(h),E=Object.keys(m.majorMode),D;if(g){let e=(0,s.readDoomVoiceToolsService)(v)?.readSession(_);if(e&&(y={sessionId:_,hostGeneration:e.hostGeneration}),b=y?p.reloadHandoffs.accept(g,y):void 0,b?.kind!==`major-mode-switch`||!b.majorMode)throw Error(`The voice major-mode switch token is stale or belongs to another session.`);D=b.majorMode}else{let t=`Major mode (current: ${C})`;D=(h.mode===`tui`?await p.loadPicker().then(({MatrixPickerComponent:n})=>h.ui.custom((r,i,a,o)=>new n({title:t,items:e.majorModeItems(m,E),selected:[C],multi:!1},i,a,o))):[e.optionName(await h.ui.select(t,E.map(t=>e.majorModeOptionLabel(t,m.majorMode[t]?.layers??[],C)))??``)])?.[0]}if(!D)return;let O=(0,l.alreadyComposed)();if(D===C){g&&y&&p.reloadHandoffs.discard(g,y),r.clearPendingSelection(d,p.cordisContext()),h.ui.notify(e.majorModeSummary(D,p.resolveLayers(m,D),C,O),`info`);return}let k=(0,o.requireDoomTransitionCoordinator)(v),A=await k.execute({sessionId:h.sessionManager.getSessionId(),hostGeneration:k.hostGeneration,operationId:b?.operationId??crypto.randomUUID(),source:b?`voice`:`command`,target:{axis:`major-mode`,majorMode:D}},async(s,l)=>{let u=[...l.candidate.layers],m=l.externalRelaunchRequired,g=(0,a.requireDoomConfigContext)(v),_=g.harness;if(l.strategy===`process-relaunch`){let i={version:1,operationId:l.operationId,active:r.selectionFromSnapshot(l.previous),target:r.selectionFromSnapshot(l.candidate),strategy:l.strategy,phase:`pending`},o=(0,a.requireDoomConfigContext)(v).pendingSelection;return o&&(0,a.supersedeDoomConfigTransition)(d,o),(0,a.appendDoomConfigTransition)(d,i),(0,a.replaceDoomConfigContext)(v,r.bindPendingSelection((0,a.requireDoomConfigContext)(v),i)),f.recordEvent(n.MAJOR_MODE_EVENT.majorModeSwitched,{"harness.major_mode.previous":_.majorMode,"harness.major_mode":D,"harness.layers":u.join(`,`),"harness.major_mode.stale":!0,"harness.transition.disposition":l.disposition,"harness.transition.operation_id":l.operationId}),h.ui.setStatus(t.STATUS_KEY,t.colorStatus(h.ui.theme,_.majorMode,_.domains,_.profile,!0)),h.ui.notify(e.applySummary(D,u,!0,O,l.strategy),`info`),`queued`}let[{applyMajorMode:y},{persistHarnessSelection:b}]=await Promise.all([p.loadSelectionSwitch(),p.loadConfigJournal()]),E={version:1,operationId:l.operationId,active:r.selectionFromSnapshot(l.previous),target:r.selectionFromSnapshot(l.candidate),strategy:l.strategy??`pi-reload`,phase:`pending`},A=(0,c.loadMajorModesConfig)(_.root??h.cwd),j=(0,i.snapshotHarnessState)(),M=g.pendingSelection;x=(0,o.prepareMinorModeReloadHandoff)(v,h.sessionManager.getSessionId(),k.hostGeneration,l.operationId,l.previous.minorModes);try{M&&(0,a.supersedeDoomConfigTransition)(d,M),(0,a.appendDoomConfigTransition)(d,E),b(d,y(A,D,_,l.candidate.compositionFingerprint,l.candidate.childActivation))}catch(e){x?.discard(),x=void 0;try{(0,i.restoreHarnessStateSnapshot)(j)}catch(t){let n=t instanceof Error?t.message:String(t);throw Error(`Transition failed and compensation failed: ${n}`,{cause:e})}throw(0,a.appendDoomConfigTransition)(d,{...E,phase:`aborted`}),M&&(0,a.appendDoomConfigTransition)(d,M),e}return f.recordEvent(n.MAJOR_MODE_EVENT.majorModeSwitched,{"harness.major_mode.previous":C,"harness.major_mode":D,"harness.layers":u.join(`,`),"harness.major_mode.stale":m,"harness.transition.disposition":l.disposition,"harness.transition.operation_id":l.operationId}),h.ui.setStatus(t.STATUS_KEY,t.colorStatus(h.ui.theme,D,w,T,!1)),h.ui.notify(e.applySummary(D,u,!1,O,l.strategy),`info`),S=!0,`applied`});if(A.outcome===`rejected`||A.outcome===`stale`)throw u(A)}catch(t){if(S=!1,x?.discard(),x=void 0,!g)throw t;y&&p.reloadHandoffs.discard(g,y),h.ui.notify(e.errorMessage(t),`error`)}if(S)try{await h.waitForIdle(),await h.reload()}catch(e){throw x?.discard(),e}}})}exports.registerMajorModeCommand=d;
2
2
  //# sourceMappingURL=majorModeCommand.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"majorModeCommand.cjs","names":["MAJOR_MODE_COMMAND","voiceSwitchToken","errorMessage","acceptVoiceReloadHandoff","majorModeItems","optionName","majorModeOptionLabel","alreadyComposed","majorModeSummary","requireDoomTransitionCoordinator","requireDoomConfigContext","selectionFromSnapshot","provideDoomConfigContext","bindPendingSelection","MAJOR_MODE_EVENT","STATUS_KEY","colorStatus","applySummary","loadMajorModesConfig","snapshotHarnessState","prepareMinorModeReloadHandoff"],"sources":["../../src/commands/majorModeCommand.ts"],"sourcesContent":["import { restoreHarnessStateSnapshot, snapshotHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport {\n appendDoomConfigTransition,\n provideDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport { alreadyComposed } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport {\n type DoomTransitionResult,\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport {\n acceptVoiceReloadHandoff,\n discardVoiceReloadHandoff,\n type VoiceReloadHandoff,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n applySummary,\n errorMessage,\n MAJOR_MODE_COMMAND,\n majorModeItems,\n majorModeOptionLabel,\n majorModeSummary,\n optionName,\n voiceSwitchToken,\n} from '../services/majorModeText.ts';\nimport { colorStatus, STATUS_KEY } from '../services/statusLine.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../types/telemetry.ts';\nimport { bindPendingSelection, clearPendingSelection, selectionFromSnapshot } from '../services/pendingSelection.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND, type MajorModeView } from '../types/majorMode.ts';\n\nfunction transitionError(result: DoomTransitionResult): Error {\n return new Error(`Major-mode transition was ${result.outcome}: ${result.diagnostics.join(', ')}`);\n}\n\nexport interface MajorModeCommandDependencies {\n readonly currentView: (ctx: ExtensionContext) => Promise<MajorModeView>;\n readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;\n readonly loadSelectionSwitch: () => Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')>;\n readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;\n readonly resolveLayers: (config: MajorModeView['config'], majorMode: string) => string[];\n}\n\nexport function registerMajorModeCommand(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry,\n dependencies: MajorModeCommandDependencies,\n): void {\n pi.registerCommand(MAJOR_MODE_COMMAND, {\n description: 'Pick a named major mode',\n handler: async (args, ctx) => {\n let token: string | undefined;\n try {\n token = voiceSwitchToken(args);\n } catch (error) {\n ctx.ui.notify(errorMessage(error), 'error');\n return;\n }\n if (args.trim() && !token) {\n ctx.ui.notify(`Usage: /${MAJOR_MODE_COMMAND}`, 'warning');\n return;\n }\n\n const sessionIdentity = { sessionId: ctx.sessionManager.getSessionId() };\n let handoff: VoiceReloadHandoff | undefined;\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n let reloadRequested = false;\n try {\n const { config, majorMode, domains, profile } = await dependencies.currentView(ctx);\n const names = Object.keys(config.majorMode);\n let picked: string | undefined;\n\n if (token) {\n handoff = acceptVoiceReloadHandoff(token, sessionIdentity);\n if (handoff?.kind !== MAJOR_MODE_SWITCH_HANDOFF_KIND || !handoff.majorMode) {\n throw new Error('The voice major-mode switch token is stale or belongs to another session.');\n }\n picked = handoff.majorMode;\n } else {\n const title = `Major mode (current: ${majorMode})`;\n const chosen =\n ctx.mode === 'tui'\n ? await dependencies\n .loadPicker()\n .then(({ MatrixPickerComponent }) =>\n ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: majorModeItems(config, names), selected: [majorMode], multi: false },\n theme,\n keybindings,\n done,\n ),\n ),\n )\n : [\n optionName(\n (await ctx.ui.select(\n title,\n names.map((name) => majorModeOptionLabel(name, config.majorMode[name]?.layers ?? [], majorMode)),\n )) ?? '',\n ),\n ];\n picked = chosen?.[0];\n }\n if (!picked) return;\n\n const composed = alreadyComposed();\n if (picked === majorMode) {\n if (token) discardVoiceReloadHandoff(token, sessionIdentity);\n clearPendingSelection(pi, ctx);\n ctx.ui.notify(\n majorModeSummary(picked, dependencies.resolveLayers(config, picked), majorMode, composed),\n 'info',\n );\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(ctx);\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: handoff?.operationId ?? crypto.randomUUID(),\n source: handoff ? 'voice' : 'command',\n target: { axis: 'major-mode', majorMode: picked },\n },\n async (_request, plan) => {\n const selected = [...plan.candidate.layers];\n const stale = plan.externalRelaunchRequired;\n const currentContextAtExecution = requireDoomConfigContext(ctx);\n const harness = currentContextAtExecution.harness;\n if (plan.strategy === 'process-relaunch') {\n const pendingSelection: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy,\n phase: 'pending',\n };\n const existingPending = requireDoomConfigContext(ctx).pendingSelection;\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, pendingSelection);\n void provideDoomConfigContext(ctx, bindPendingSelection(requireDoomConfigContext(ctx), pendingSelection));\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': harness.majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': true,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(\n STATUS_KEY,\n colorStatus(ctx.ui.theme, harness.majorMode, harness.domains, harness.profile, true),\n );\n ctx.ui.notify(applySummary(picked, selected, true, composed, plan.strategy), 'info');\n return 'queued';\n }\n const [{ applyMajorMode }, { persistHarnessSelection }] = await Promise.all([\n dependencies.loadSelectionSwitch(),\n dependencies.loadConfigJournal(),\n ]);\n const transition: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy ?? 'pi-reload',\n phase: 'pending',\n };\n const activeConfig = loadMajorModesConfig(harness.root ?? ctx.cwd);\n const snapshot = snapshotHarnessState();\n const existingPending = currentContextAtExecution.pendingSelection;\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n ctx,\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, transition);\n const updated = applyMajorMode(\n activeConfig,\n picked,\n harness,\n plan.candidate.compositionFingerprint,\n plan.candidate.childActivation,\n );\n persistHarnessSelection(pi, updated);\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n try {\n restoreHarnessStateSnapshot(snapshot);\n } catch (compensationError) {\n const detail =\n compensationError instanceof Error ? compensationError.message : String(compensationError);\n throw new Error(`Transition failed and compensation failed: ${detail}`, { cause: error });\n }\n appendDoomConfigTransition(pi, { ...transition, phase: 'aborted' });\n if (existingPending) appendDoomConfigTransition(pi, existingPending);\n throw error;\n }\n\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': stale,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, picked, domains, profile, false));\n ctx.ui.notify(applySummary(picked, selected, false, composed, plan.strategy), 'info');\n // Reload must be the command handler's terminal action. Pi invalidates\n // this command context as soon as the replacement session is active.\n reloadRequested = true;\n return 'applied';\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') throw transitionError(result);\n } catch (error) {\n reloadRequested = false;\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n if (!token) throw error;\n discardVoiceReloadHandoff(token, sessionIdentity);\n ctx.ui.notify(errorMessage(error), 'error');\n }\n\n if (reloadRequested) {\n try {\n await ctx.waitForIdle();\n // The replacement session acknowledges the pending journal after its\n // bootstrap harness is active. Do not touch ctx after this await.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n }\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"majorModeCommand.cjs","names":["MAJOR_MODE_COMMAND","voiceSwitchToken","errorMessage","readDoomVoiceToolsService","majorModeItems","optionName","majorModeOptionLabel","alreadyComposed","majorModeSummary","requireDoomTransitionCoordinator","requireDoomConfigContext","selectionFromSnapshot","bindPendingSelection","MAJOR_MODE_EVENT","STATUS_KEY","colorStatus","applySummary","loadMajorModesConfig","snapshotHarnessState","prepareMinorModeReloadHandoff"],"sources":["../../src/commands/majorModeCommand.ts"],"sourcesContent":["import { restoreHarnessStateSnapshot, snapshotHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport {\n appendDoomConfigTransition,\n replaceDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport { alreadyComposed } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport {\n type DoomTransitionResult,\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport { readDoomVoiceToolsService } from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type {\n VoiceReloadHandoff,\n VoiceReloadHandoffIdentity,\n VoiceReloadHandoffStore,\n} from '@agimon-ai/doompi-extension-contracts/voice-reload-handoff';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { Context } from '@deepseek-ai/cordis';\nimport {\n applySummary,\n errorMessage,\n MAJOR_MODE_COMMAND,\n majorModeItems,\n majorModeOptionLabel,\n majorModeSummary,\n optionName,\n voiceSwitchToken,\n} from '../services/majorModeText.ts';\nimport { colorStatus, STATUS_KEY } from '../services/statusLine.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../types/telemetry.ts';\nimport { bindPendingSelection, clearPendingSelection, selectionFromSnapshot } from '../services/pendingSelection.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND, type MajorModeView } from '../types/majorMode.ts';\n\nfunction transitionError(result: DoomTransitionResult): Error {\n return new Error(`Major-mode transition was ${result.outcome}: ${result.diagnostics.join(', ')}`);\n}\n\nexport interface MajorModeCommandDependencies {\n readonly cordisContext: () => Context;\n readonly currentView: (ctx: ExtensionContext) => Promise<MajorModeView>;\n readonly reloadHandoffs: VoiceReloadHandoffStore;\n readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;\n readonly loadSelectionSwitch: () => Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')>;\n readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;\n readonly resolveLayers: (config: MajorModeView['config'], majorMode: string) => string[];\n}\n\nexport function registerMajorModeCommand(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry,\n dependencies: MajorModeCommandDependencies,\n): void {\n pi.registerCommand(MAJOR_MODE_COMMAND, {\n description: 'Pick a named major mode',\n handler: async (args, ctx) => {\n let token: string | undefined;\n try {\n token = voiceSwitchToken(args);\n } catch (error) {\n ctx.ui.notify(errorMessage(error), 'error');\n return;\n }\n if (args.trim() && !token) {\n ctx.ui.notify(`Usage: /${MAJOR_MODE_COMMAND}`, 'warning');\n return;\n }\n\n const sessionId = ctx.sessionManager.getSessionId();\n const cordis = dependencies.cordisContext();\n let sessionIdentity: VoiceReloadHandoffIdentity | undefined;\n let handoff: VoiceReloadHandoff | undefined;\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n let reloadRequested = false;\n try {\n const { config, majorMode, domains, profile } = await dependencies.currentView(ctx);\n const names = Object.keys(config.majorMode);\n let picked: string | undefined;\n\n if (token) {\n const voiceSession = readDoomVoiceToolsService(cordis)?.readSession(sessionId);\n if (voiceSession) sessionIdentity = { sessionId, hostGeneration: voiceSession.hostGeneration };\n handoff = sessionIdentity ? dependencies.reloadHandoffs.accept(token, sessionIdentity) : undefined;\n if (handoff?.kind !== MAJOR_MODE_SWITCH_HANDOFF_KIND || !handoff.majorMode) {\n throw new Error('The voice major-mode switch token is stale or belongs to another session.');\n }\n picked = handoff.majorMode;\n } else {\n const title = `Major mode (current: ${majorMode})`;\n const chosen =\n ctx.mode === 'tui'\n ? await dependencies\n .loadPicker()\n .then(({ MatrixPickerComponent }) =>\n ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: majorModeItems(config, names), selected: [majorMode], multi: false },\n theme,\n keybindings,\n done,\n ),\n ),\n )\n : [\n optionName(\n (await ctx.ui.select(\n title,\n names.map((name) => majorModeOptionLabel(name, config.majorMode[name]?.layers ?? [], majorMode)),\n )) ?? '',\n ),\n ];\n picked = chosen?.[0];\n }\n if (!picked) return;\n\n const composed = alreadyComposed();\n if (picked === majorMode) {\n if (token && sessionIdentity) dependencies.reloadHandoffs.discard(token, sessionIdentity);\n clearPendingSelection(pi, dependencies.cordisContext());\n ctx.ui.notify(\n majorModeSummary(picked, dependencies.resolveLayers(config, picked), majorMode, composed),\n 'info',\n );\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(cordis);\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: handoff?.operationId ?? crypto.randomUUID(),\n source: handoff ? 'voice' : 'command',\n target: { axis: 'major-mode', majorMode: picked },\n },\n async (_request, plan) => {\n const selected = [...plan.candidate.layers];\n const stale = plan.externalRelaunchRequired;\n const currentContextAtExecution = requireDoomConfigContext(cordis);\n const harness = currentContextAtExecution.harness;\n if (plan.strategy === 'process-relaunch') {\n const pendingSelection: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy,\n phase: 'pending',\n };\n const existingPending = requireDoomConfigContext(cordis).pendingSelection;\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, pendingSelection);\n replaceDoomConfigContext(\n cordis,\n bindPendingSelection(requireDoomConfigContext(cordis), pendingSelection),\n );\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': harness.majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': true,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(\n STATUS_KEY,\n colorStatus(ctx.ui.theme, harness.majorMode, harness.domains, harness.profile, true),\n );\n ctx.ui.notify(applySummary(picked, selected, true, composed, plan.strategy), 'info');\n return 'queued';\n }\n const [{ applyMajorMode }, { persistHarnessSelection }] = await Promise.all([\n dependencies.loadSelectionSwitch(),\n dependencies.loadConfigJournal(),\n ]);\n const transition: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy ?? 'pi-reload',\n phase: 'pending',\n };\n const activeConfig = loadMajorModesConfig(harness.root ?? ctx.cwd);\n const snapshot = snapshotHarnessState();\n const existingPending = currentContextAtExecution.pendingSelection;\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n cordis,\n ctx.sessionManager.getSessionId(),\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, transition);\n const updated = applyMajorMode(\n activeConfig,\n picked,\n harness,\n plan.candidate.compositionFingerprint,\n plan.candidate.childActivation,\n );\n persistHarnessSelection(pi, updated);\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n try {\n restoreHarnessStateSnapshot(snapshot);\n } catch (compensationError) {\n const detail =\n compensationError instanceof Error ? compensationError.message : String(compensationError);\n throw new Error(`Transition failed and compensation failed: ${detail}`, { cause: error });\n }\n appendDoomConfigTransition(pi, { ...transition, phase: 'aborted' });\n if (existingPending) appendDoomConfigTransition(pi, existingPending);\n throw error;\n }\n\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': stale,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, picked, domains, profile, false));\n ctx.ui.notify(applySummary(picked, selected, false, composed, plan.strategy), 'info');\n // Reload must be the command handler's terminal action. Pi invalidates\n // this command context as soon as the replacement session is active.\n reloadRequested = true;\n return 'applied';\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') throw transitionError(result);\n } catch (error) {\n reloadRequested = false;\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n if (!token) throw error;\n if (sessionIdentity) dependencies.reloadHandoffs.discard(token, sessionIdentity);\n ctx.ui.notify(errorMessage(error), 'error');\n }\n\n if (reloadRequested) {\n try {\n await ctx.waitForIdle();\n // The replacement session acknowledges the pending journal after its\n // bootstrap harness is active. Do not touch ctx after this await.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n }\n },\n });\n}\n"],"mappings":"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"}
@@ -1,9 +1,13 @@
1
1
  import { MajorModeTelemetry } from "../types/telemetry.cjs";
2
2
  import { MajorModeView } from "../types/majorMode.cjs";
3
3
  import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
4
+ import { VoiceReloadHandoffStore } from "@agimon-ai/doompi-extension-contracts/voice-reload-handoff";
5
+ import { Context } from "@deepseek-ai/cordis";
4
6
  //#region src/commands/majorModeCommand.d.ts
5
7
  interface MajorModeCommandDependencies {
8
+ readonly cordisContext: () => Context;
6
9
  readonly currentView: (ctx: ExtensionContext) => Promise<MajorModeView>;
10
+ readonly reloadHandoffs: VoiceReloadHandoffStore;
7
11
  readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;
8
12
  readonly loadSelectionSwitch: () => Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')>;
9
13
  readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;
@@ -1 +1 @@
1
- {"version":3,"file":"majorModeCommand.d.cts","names":[],"sources":["../../src/commands/majorModeCommand.ts"],"mappings":";;;;UAyCiB;WACN,cAAc,KAAK,qBAAqB,QAAQ;WAChD,kBAAkB;WAClB,2BAA2B;WAC3B,yBAAyB;WACzB,gBAAgB,QAAQ,yBAAyB;;iBAG5C,yBACd,IAAI,cACJ,WAAW,oBACX,cAAc"}
1
+ {"version":3,"file":"majorModeCommand.d.cts","names":[],"sources":["../../src/commands/majorModeCommand.ts"],"mappings":";;;;;;UA2CiB;WACN,qBAAqB;WACrB,cAAc,KAAK,qBAAqB,QAAQ;WAChD,gBAAgB;WAChB,kBAAkB;WAClB,2BAA2B;WAC3B,yBAAyB;WACzB,gBAAgB,QAAQ,yBAAyB;;iBAG5C,yBACd,IAAI,cACJ,WAAW,oBACX,cAAc"}
@@ -1,9 +1,13 @@
1
1
  import { MajorModeTelemetry } from "../types/telemetry.mjs";
2
2
  import { MajorModeView } from "../types/majorMode.mjs";
3
+ import { VoiceReloadHandoffStore } from "@agimon-ai/doompi-extension-contracts/voice-reload-handoff";
3
4
  import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
5
+ import { Context } from "@deepseek-ai/cordis";
4
6
  //#region src/commands/majorModeCommand.d.ts
5
7
  interface MajorModeCommandDependencies {
8
+ readonly cordisContext: () => Context;
6
9
  readonly currentView: (ctx: ExtensionContext) => Promise<MajorModeView>;
10
+ readonly reloadHandoffs: VoiceReloadHandoffStore;
7
11
  readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;
8
12
  readonly loadSelectionSwitch: () => Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')>;
9
13
  readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;
@@ -1 +1 @@
1
- {"version":3,"file":"majorModeCommand.d.mts","names":[],"sources":["../../src/commands/majorModeCommand.ts"],"mappings":";;;;UAyCiB;WACN,cAAc,KAAK,qBAAqB,QAAQ;WAChD,kBAAkB;WAClB,2BAA2B;WAC3B,yBAAyB;WACzB,gBAAgB,QAAQ,yBAAyB;;iBAG5C,yBACd,IAAI,cACJ,WAAW,oBACX,cAAc"}
1
+ {"version":3,"file":"majorModeCommand.d.mts","names":[],"sources":["../../src/commands/majorModeCommand.ts"],"mappings":";;;;;;UA2CiB;WACN,qBAAqB;WACrB,cAAc,KAAK,qBAAqB,QAAQ;WAChD,gBAAgB;WAChB,kBAAkB;WAClB,2BAA2B;WAC3B,yBAAyB;WACzB,gBAAgB,QAAQ,yBAAyB;;iBAG5C,yBACd,IAAI,cACJ,WAAW,oBACX,cAAc"}
@@ -1,2 +1,2 @@
1
- import{MAJOR_MODE_COMMAND as e,applySummary as t,errorMessage as n,majorModeItems as r,majorModeOptionLabel as i,majorModeSummary as a,optionName as o,voiceSwitchToken as s}from"../services/majorModeText.mjs";import{STATUS_KEY as c,colorStatus as l}from"../services/statusLine.mjs";import{MAJOR_MODE_EVENT as u}from"../types/telemetry.mjs";import{bindPendingSelection as d,clearPendingSelection as f,selectionFromSnapshot as p}from"../services/pendingSelection.mjs";import"../types/majorMode.mjs";import{restoreHarnessStateSnapshot as m,snapshotHarnessState as h}from"@agimon-ai/doompi-config/harnessStore";import{appendDoomConfigTransition as g,provideDoomConfigContext as _,requireDoomConfigContext as v,supersedeDoomConfigTransition as y}from"@agimon-ai/doompi-config/piContext";import{loadMajorModesConfig as b}from"@agimon-ai/doompi-config/majorModes";import{alreadyComposed as x}from"@agimon-ai/doompi-extension-contracts/child-process";import{prepareMinorModeReloadHandoff as S,requireDoomTransitionCoordinator as C}from"@agimon-ai/doompi-extension-contracts/transition";import{acceptVoiceReloadHandoff as w,discardVoiceReloadHandoff as T}from"@agimon-ai/doompi-extension-contracts/voice-tools";function E(e){return Error(`Major-mode transition was ${e.outcome}: ${e.diagnostics.join(`, `)}`)}function D(D,O,k){D.registerCommand(e,{description:`Pick a named major mode`,handler:async(A,j)=>{let M;try{M=s(A)}catch(e){j.ui.notify(n(e),`error`);return}if(A.trim()&&!M){j.ui.notify(`Usage: /${e}`,`warning`);return}let N={sessionId:j.sessionManager.getSessionId()},P,F,I=!1;try{let{config:e,majorMode:n,domains:s,profile:A}=await k.currentView(j),L=Object.keys(e.majorMode),R;if(M){if(P=w(M,N),P?.kind!==`major-mode-switch`||!P.majorMode)throw Error(`The voice major-mode switch token is stale or belongs to another session.`);R=P.majorMode}else{let t=`Major mode (current: ${n})`;R=(j.mode===`tui`?await k.loadPicker().then(({MatrixPickerComponent:i})=>j.ui.custom((a,o,s,c)=>new i({title:t,items:r(e,L),selected:[n],multi:!1},o,s,c))):[o(await j.ui.select(t,L.map(t=>i(t,e.majorMode[t]?.layers??[],n)))??``)])?.[0]}if(!R)return;let z=x();if(R===n){M&&T(M,N),f(D,j),j.ui.notify(a(R,k.resolveLayers(e,R),n,z),`info`);return}let B=C(j),V=await B.execute({sessionId:j.sessionManager.getSessionId(),hostGeneration:B.hostGeneration,operationId:P?.operationId??crypto.randomUUID(),source:P?`voice`:`command`,target:{axis:`major-mode`,majorMode:R}},async(e,r)=>{let i=[...r.candidate.layers],a=r.externalRelaunchRequired,o=v(j),f=o.harness;if(r.strategy===`process-relaunch`){let e={version:1,operationId:r.operationId,active:p(r.previous),target:p(r.candidate),strategy:r.strategy,phase:`pending`},n=v(j).pendingSelection;return n&&y(D,n),g(D,e),_(j,d(v(j),e)),O.recordEvent(u.majorModeSwitched,{"harness.major_mode.previous":f.majorMode,"harness.major_mode":R,"harness.layers":i.join(`,`),"harness.major_mode.stale":!0,"harness.transition.disposition":r.disposition,"harness.transition.operation_id":r.operationId}),j.ui.setStatus(c,l(j.ui.theme,f.majorMode,f.domains,f.profile,!0)),j.ui.notify(t(R,i,!0,z,r.strategy),`info`),`queued`}let[{applyMajorMode:x},{persistHarnessSelection:C}]=await Promise.all([k.loadSelectionSwitch(),k.loadConfigJournal()]),w={version:1,operationId:r.operationId,active:p(r.previous),target:p(r.candidate),strategy:r.strategy??`pi-reload`,phase:`pending`},T=b(f.root??j.cwd),E=h(),M=o.pendingSelection;F=S(j,B.hostGeneration,r.operationId,r.previous.minorModes);try{M&&y(D,M),g(D,w),C(D,x(T,R,f,r.candidate.compositionFingerprint,r.candidate.childActivation))}catch(e){F?.discard(),F=void 0;try{m(E)}catch(t){let n=t instanceof Error?t.message:String(t);throw Error(`Transition failed and compensation failed: ${n}`,{cause:e})}throw g(D,{...w,phase:`aborted`}),M&&g(D,M),e}return O.recordEvent(u.majorModeSwitched,{"harness.major_mode.previous":n,"harness.major_mode":R,"harness.layers":i.join(`,`),"harness.major_mode.stale":a,"harness.transition.disposition":r.disposition,"harness.transition.operation_id":r.operationId}),j.ui.setStatus(c,l(j.ui.theme,R,s,A,!1)),j.ui.notify(t(R,i,!1,z,r.strategy),`info`),I=!0,`applied`});if(V.outcome===`rejected`||V.outcome===`stale`)throw E(V)}catch(e){if(I=!1,F?.discard(),F=void 0,!M)throw e;T(M,N),j.ui.notify(n(e),`error`)}if(I)try{await j.waitForIdle(),await j.reload()}catch(e){throw F?.discard(),e}}})}export{D as registerMajorModeCommand};
1
+ import{MAJOR_MODE_COMMAND as e,applySummary as t,errorMessage as n,majorModeItems as r,majorModeOptionLabel as i,majorModeSummary as a,optionName as o,voiceSwitchToken as s}from"../services/majorModeText.mjs";import{STATUS_KEY as c,colorStatus as l}from"../services/statusLine.mjs";import{MAJOR_MODE_EVENT as u}from"../types/telemetry.mjs";import{bindPendingSelection as d,clearPendingSelection as f,selectionFromSnapshot as p}from"../services/pendingSelection.mjs";import"../types/majorMode.mjs";import{restoreHarnessStateSnapshot as m,snapshotHarnessState as h}from"@agimon-ai/doompi-config/harnessStore";import{appendDoomConfigTransition as g,replaceDoomConfigContext as _,requireDoomConfigContext as v,supersedeDoomConfigTransition as y}from"@agimon-ai/doompi-config/piContext";import{prepareMinorModeReloadHandoff as b,requireDoomTransitionCoordinator as x}from"@agimon-ai/doompi-extension-contracts/transition";import{readDoomVoiceToolsService as S}from"@agimon-ai/doompi-extension-contracts/voice-tools";import{loadMajorModesConfig as C}from"@agimon-ai/doompi-config/majorModes";import{alreadyComposed as w}from"@agimon-ai/doompi-extension-contracts/child-process";function T(e){return Error(`Major-mode transition was ${e.outcome}: ${e.diagnostics.join(`, `)}`)}function E(E,D,O){E.registerCommand(e,{description:`Pick a named major mode`,handler:async(k,A)=>{let j;try{j=s(k)}catch(e){A.ui.notify(n(e),`error`);return}if(k.trim()&&!j){A.ui.notify(`Usage: /${e}`,`warning`);return}let M=A.sessionManager.getSessionId(),N=O.cordisContext(),P,F,I,L=!1;try{let{config:e,majorMode:n,domains:s,profile:k}=await O.currentView(A),R=Object.keys(e.majorMode),z;if(j){let e=S(N)?.readSession(M);if(e&&(P={sessionId:M,hostGeneration:e.hostGeneration}),F=P?O.reloadHandoffs.accept(j,P):void 0,F?.kind!==`major-mode-switch`||!F.majorMode)throw Error(`The voice major-mode switch token is stale or belongs to another session.`);z=F.majorMode}else{let t=`Major mode (current: ${n})`;z=(A.mode===`tui`?await O.loadPicker().then(({MatrixPickerComponent:i})=>A.ui.custom((a,o,s,c)=>new i({title:t,items:r(e,R),selected:[n],multi:!1},o,s,c))):[o(await A.ui.select(t,R.map(t=>i(t,e.majorMode[t]?.layers??[],n)))??``)])?.[0]}if(!z)return;let B=w();if(z===n){j&&P&&O.reloadHandoffs.discard(j,P),f(E,O.cordisContext()),A.ui.notify(a(z,O.resolveLayers(e,z),n,B),`info`);return}let V=x(N),H=await V.execute({sessionId:A.sessionManager.getSessionId(),hostGeneration:V.hostGeneration,operationId:F?.operationId??crypto.randomUUID(),source:F?`voice`:`command`,target:{axis:`major-mode`,majorMode:z}},async(e,r)=>{let i=[...r.candidate.layers],a=r.externalRelaunchRequired,o=v(N),f=o.harness;if(r.strategy===`process-relaunch`){let e={version:1,operationId:r.operationId,active:p(r.previous),target:p(r.candidate),strategy:r.strategy,phase:`pending`},n=v(N).pendingSelection;return n&&y(E,n),g(E,e),_(N,d(v(N),e)),D.recordEvent(u.majorModeSwitched,{"harness.major_mode.previous":f.majorMode,"harness.major_mode":z,"harness.layers":i.join(`,`),"harness.major_mode.stale":!0,"harness.transition.disposition":r.disposition,"harness.transition.operation_id":r.operationId}),A.ui.setStatus(c,l(A.ui.theme,f.majorMode,f.domains,f.profile,!0)),A.ui.notify(t(z,i,!0,B,r.strategy),`info`),`queued`}let[{applyMajorMode:x},{persistHarnessSelection:S}]=await Promise.all([O.loadSelectionSwitch(),O.loadConfigJournal()]),w={version:1,operationId:r.operationId,active:p(r.previous),target:p(r.candidate),strategy:r.strategy??`pi-reload`,phase:`pending`},T=C(f.root??A.cwd),j=h(),M=o.pendingSelection;I=b(N,A.sessionManager.getSessionId(),V.hostGeneration,r.operationId,r.previous.minorModes);try{M&&y(E,M),g(E,w),S(E,x(T,z,f,r.candidate.compositionFingerprint,r.candidate.childActivation))}catch(e){I?.discard(),I=void 0;try{m(j)}catch(t){let n=t instanceof Error?t.message:String(t);throw Error(`Transition failed and compensation failed: ${n}`,{cause:e})}throw g(E,{...w,phase:`aborted`}),M&&g(E,M),e}return D.recordEvent(u.majorModeSwitched,{"harness.major_mode.previous":n,"harness.major_mode":z,"harness.layers":i.join(`,`),"harness.major_mode.stale":a,"harness.transition.disposition":r.disposition,"harness.transition.operation_id":r.operationId}),A.ui.setStatus(c,l(A.ui.theme,z,s,k,!1)),A.ui.notify(t(z,i,!1,B,r.strategy),`info`),L=!0,`applied`});if(H.outcome===`rejected`||H.outcome===`stale`)throw T(H)}catch(e){if(L=!1,I?.discard(),I=void 0,!j)throw e;P&&O.reloadHandoffs.discard(j,P),A.ui.notify(n(e),`error`)}if(L)try{await A.waitForIdle(),await A.reload()}catch(e){throw I?.discard(),e}}})}export{E as registerMajorModeCommand};
2
2
  //# sourceMappingURL=majorModeCommand.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"majorModeCommand.mjs","names":[],"sources":["../../src/commands/majorModeCommand.ts"],"sourcesContent":["import { restoreHarnessStateSnapshot, snapshotHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport {\n appendDoomConfigTransition,\n provideDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport { alreadyComposed } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport {\n type DoomTransitionResult,\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport {\n acceptVoiceReloadHandoff,\n discardVoiceReloadHandoff,\n type VoiceReloadHandoff,\n} from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n applySummary,\n errorMessage,\n MAJOR_MODE_COMMAND,\n majorModeItems,\n majorModeOptionLabel,\n majorModeSummary,\n optionName,\n voiceSwitchToken,\n} from '../services/majorModeText.ts';\nimport { colorStatus, STATUS_KEY } from '../services/statusLine.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../types/telemetry.ts';\nimport { bindPendingSelection, clearPendingSelection, selectionFromSnapshot } from '../services/pendingSelection.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND, type MajorModeView } from '../types/majorMode.ts';\n\nfunction transitionError(result: DoomTransitionResult): Error {\n return new Error(`Major-mode transition was ${result.outcome}: ${result.diagnostics.join(', ')}`);\n}\n\nexport interface MajorModeCommandDependencies {\n readonly currentView: (ctx: ExtensionContext) => Promise<MajorModeView>;\n readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;\n readonly loadSelectionSwitch: () => Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')>;\n readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;\n readonly resolveLayers: (config: MajorModeView['config'], majorMode: string) => string[];\n}\n\nexport function registerMajorModeCommand(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry,\n dependencies: MajorModeCommandDependencies,\n): void {\n pi.registerCommand(MAJOR_MODE_COMMAND, {\n description: 'Pick a named major mode',\n handler: async (args, ctx) => {\n let token: string | undefined;\n try {\n token = voiceSwitchToken(args);\n } catch (error) {\n ctx.ui.notify(errorMessage(error), 'error');\n return;\n }\n if (args.trim() && !token) {\n ctx.ui.notify(`Usage: /${MAJOR_MODE_COMMAND}`, 'warning');\n return;\n }\n\n const sessionIdentity = { sessionId: ctx.sessionManager.getSessionId() };\n let handoff: VoiceReloadHandoff | undefined;\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n let reloadRequested = false;\n try {\n const { config, majorMode, domains, profile } = await dependencies.currentView(ctx);\n const names = Object.keys(config.majorMode);\n let picked: string | undefined;\n\n if (token) {\n handoff = acceptVoiceReloadHandoff(token, sessionIdentity);\n if (handoff?.kind !== MAJOR_MODE_SWITCH_HANDOFF_KIND || !handoff.majorMode) {\n throw new Error('The voice major-mode switch token is stale or belongs to another session.');\n }\n picked = handoff.majorMode;\n } else {\n const title = `Major mode (current: ${majorMode})`;\n const chosen =\n ctx.mode === 'tui'\n ? await dependencies\n .loadPicker()\n .then(({ MatrixPickerComponent }) =>\n ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: majorModeItems(config, names), selected: [majorMode], multi: false },\n theme,\n keybindings,\n done,\n ),\n ),\n )\n : [\n optionName(\n (await ctx.ui.select(\n title,\n names.map((name) => majorModeOptionLabel(name, config.majorMode[name]?.layers ?? [], majorMode)),\n )) ?? '',\n ),\n ];\n picked = chosen?.[0];\n }\n if (!picked) return;\n\n const composed = alreadyComposed();\n if (picked === majorMode) {\n if (token) discardVoiceReloadHandoff(token, sessionIdentity);\n clearPendingSelection(pi, ctx);\n ctx.ui.notify(\n majorModeSummary(picked, dependencies.resolveLayers(config, picked), majorMode, composed),\n 'info',\n );\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(ctx);\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: handoff?.operationId ?? crypto.randomUUID(),\n source: handoff ? 'voice' : 'command',\n target: { axis: 'major-mode', majorMode: picked },\n },\n async (_request, plan) => {\n const selected = [...plan.candidate.layers];\n const stale = plan.externalRelaunchRequired;\n const currentContextAtExecution = requireDoomConfigContext(ctx);\n const harness = currentContextAtExecution.harness;\n if (plan.strategy === 'process-relaunch') {\n const pendingSelection: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy,\n phase: 'pending',\n };\n const existingPending = requireDoomConfigContext(ctx).pendingSelection;\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, pendingSelection);\n void provideDoomConfigContext(ctx, bindPendingSelection(requireDoomConfigContext(ctx), pendingSelection));\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': harness.majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': true,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(\n STATUS_KEY,\n colorStatus(ctx.ui.theme, harness.majorMode, harness.domains, harness.profile, true),\n );\n ctx.ui.notify(applySummary(picked, selected, true, composed, plan.strategy), 'info');\n return 'queued';\n }\n const [{ applyMajorMode }, { persistHarnessSelection }] = await Promise.all([\n dependencies.loadSelectionSwitch(),\n dependencies.loadConfigJournal(),\n ]);\n const transition: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy ?? 'pi-reload',\n phase: 'pending',\n };\n const activeConfig = loadMajorModesConfig(harness.root ?? ctx.cwd);\n const snapshot = snapshotHarnessState();\n const existingPending = currentContextAtExecution.pendingSelection;\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n ctx,\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, transition);\n const updated = applyMajorMode(\n activeConfig,\n picked,\n harness,\n plan.candidate.compositionFingerprint,\n plan.candidate.childActivation,\n );\n persistHarnessSelection(pi, updated);\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n try {\n restoreHarnessStateSnapshot(snapshot);\n } catch (compensationError) {\n const detail =\n compensationError instanceof Error ? compensationError.message : String(compensationError);\n throw new Error(`Transition failed and compensation failed: ${detail}`, { cause: error });\n }\n appendDoomConfigTransition(pi, { ...transition, phase: 'aborted' });\n if (existingPending) appendDoomConfigTransition(pi, existingPending);\n throw error;\n }\n\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': stale,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, picked, domains, profile, false));\n ctx.ui.notify(applySummary(picked, selected, false, composed, plan.strategy), 'info');\n // Reload must be the command handler's terminal action. Pi invalidates\n // this command context as soon as the replacement session is active.\n reloadRequested = true;\n return 'applied';\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') throw transitionError(result);\n } catch (error) {\n reloadRequested = false;\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n if (!token) throw error;\n discardVoiceReloadHandoff(token, sessionIdentity);\n ctx.ui.notify(errorMessage(error), 'error');\n }\n\n if (reloadRequested) {\n try {\n await ctx.waitForIdle();\n // The replacement session acknowledges the pending journal after its\n // bootstrap harness is active. Do not touch ctx after this await.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n }\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"majorModeCommand.mjs","names":[],"sources":["../../src/commands/majorModeCommand.ts"],"sourcesContent":["import { restoreHarnessStateSnapshot, snapshotHarnessState } from '@agimon-ai/doompi-config/harnessStore';\nimport { loadMajorModesConfig } from '@agimon-ai/doompi-config/majorModes';\nimport {\n appendDoomConfigTransition,\n replaceDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport { alreadyComposed } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport {\n type DoomTransitionResult,\n type MinorModeReloadHandoffHandle,\n prepareMinorModeReloadHandoff,\n requireDoomTransitionCoordinator,\n} from '@agimon-ai/doompi-extension-contracts/transition';\nimport { readDoomVoiceToolsService } from '@agimon-ai/doompi-extension-contracts/voice-tools';\nimport type {\n VoiceReloadHandoff,\n VoiceReloadHandoffIdentity,\n VoiceReloadHandoffStore,\n} from '@agimon-ai/doompi-extension-contracts/voice-reload-handoff';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport type { Context } from '@deepseek-ai/cordis';\nimport {\n applySummary,\n errorMessage,\n MAJOR_MODE_COMMAND,\n majorModeItems,\n majorModeOptionLabel,\n majorModeSummary,\n optionName,\n voiceSwitchToken,\n} from '../services/majorModeText.ts';\nimport { colorStatus, STATUS_KEY } from '../services/statusLine.ts';\nimport { MAJOR_MODE_EVENT, type MajorModeTelemetry } from '../types/telemetry.ts';\nimport { bindPendingSelection, clearPendingSelection, selectionFromSnapshot } from '../services/pendingSelection.ts';\nimport { MAJOR_MODE_SWITCH_HANDOFF_KIND, type MajorModeView } from '../types/majorMode.ts';\n\nfunction transitionError(result: DoomTransitionResult): Error {\n return new Error(`Major-mode transition was ${result.outcome}: ${result.diagnostics.join(', ')}`);\n}\n\nexport interface MajorModeCommandDependencies {\n readonly cordisContext: () => Context;\n readonly currentView: (ctx: ExtensionContext) => Promise<MajorModeView>;\n readonly reloadHandoffs: VoiceReloadHandoffStore;\n readonly loadPicker: () => Promise<typeof import('@agimon-ai/doompi-ui/components/matrixPicker')>;\n readonly loadSelectionSwitch: () => Promise<typeof import('@agimon-ai/doompi-config/selectionSwitch')>;\n readonly loadConfigJournal: () => Promise<typeof import('@agimon-ai/doompi-config/piContext')>;\n readonly resolveLayers: (config: MajorModeView['config'], majorMode: string) => string[];\n}\n\nexport function registerMajorModeCommand(\n pi: ExtensionAPI,\n telemetry: MajorModeTelemetry,\n dependencies: MajorModeCommandDependencies,\n): void {\n pi.registerCommand(MAJOR_MODE_COMMAND, {\n description: 'Pick a named major mode',\n handler: async (args, ctx) => {\n let token: string | undefined;\n try {\n token = voiceSwitchToken(args);\n } catch (error) {\n ctx.ui.notify(errorMessage(error), 'error');\n return;\n }\n if (args.trim() && !token) {\n ctx.ui.notify(`Usage: /${MAJOR_MODE_COMMAND}`, 'warning');\n return;\n }\n\n const sessionId = ctx.sessionManager.getSessionId();\n const cordis = dependencies.cordisContext();\n let sessionIdentity: VoiceReloadHandoffIdentity | undefined;\n let handoff: VoiceReloadHandoff | undefined;\n let minorModeReloadHandoff: MinorModeReloadHandoffHandle | undefined;\n let reloadRequested = false;\n try {\n const { config, majorMode, domains, profile } = await dependencies.currentView(ctx);\n const names = Object.keys(config.majorMode);\n let picked: string | undefined;\n\n if (token) {\n const voiceSession = readDoomVoiceToolsService(cordis)?.readSession(sessionId);\n if (voiceSession) sessionIdentity = { sessionId, hostGeneration: voiceSession.hostGeneration };\n handoff = sessionIdentity ? dependencies.reloadHandoffs.accept(token, sessionIdentity) : undefined;\n if (handoff?.kind !== MAJOR_MODE_SWITCH_HANDOFF_KIND || !handoff.majorMode) {\n throw new Error('The voice major-mode switch token is stale or belongs to another session.');\n }\n picked = handoff.majorMode;\n } else {\n const title = `Major mode (current: ${majorMode})`;\n const chosen =\n ctx.mode === 'tui'\n ? await dependencies\n .loadPicker()\n .then(({ MatrixPickerComponent }) =>\n ctx.ui.custom<string[] | undefined>(\n (_tui, theme, keybindings, done) =>\n new MatrixPickerComponent(\n { title, items: majorModeItems(config, names), selected: [majorMode], multi: false },\n theme,\n keybindings,\n done,\n ),\n ),\n )\n : [\n optionName(\n (await ctx.ui.select(\n title,\n names.map((name) => majorModeOptionLabel(name, config.majorMode[name]?.layers ?? [], majorMode)),\n )) ?? '',\n ),\n ];\n picked = chosen?.[0];\n }\n if (!picked) return;\n\n const composed = alreadyComposed();\n if (picked === majorMode) {\n if (token && sessionIdentity) dependencies.reloadHandoffs.discard(token, sessionIdentity);\n clearPendingSelection(pi, dependencies.cordisContext());\n ctx.ui.notify(\n majorModeSummary(picked, dependencies.resolveLayers(config, picked), majorMode, composed),\n 'info',\n );\n return;\n }\n\n const coordinator = requireDoomTransitionCoordinator(cordis);\n const result = await coordinator.execute(\n {\n sessionId: ctx.sessionManager.getSessionId(),\n hostGeneration: coordinator.hostGeneration,\n operationId: handoff?.operationId ?? crypto.randomUUID(),\n source: handoff ? 'voice' : 'command',\n target: { axis: 'major-mode', majorMode: picked },\n },\n async (_request, plan) => {\n const selected = [...plan.candidate.layers];\n const stale = plan.externalRelaunchRequired;\n const currentContextAtExecution = requireDoomConfigContext(cordis);\n const harness = currentContextAtExecution.harness;\n if (plan.strategy === 'process-relaunch') {\n const pendingSelection: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy,\n phase: 'pending',\n };\n const existingPending = requireDoomConfigContext(cordis).pendingSelection;\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, pendingSelection);\n replaceDoomConfigContext(\n cordis,\n bindPendingSelection(requireDoomConfigContext(cordis), pendingSelection),\n );\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': harness.majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': true,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(\n STATUS_KEY,\n colorStatus(ctx.ui.theme, harness.majorMode, harness.domains, harness.profile, true),\n );\n ctx.ui.notify(applySummary(picked, selected, true, composed, plan.strategy), 'info');\n return 'queued';\n }\n const [{ applyMajorMode }, { persistHarnessSelection }] = await Promise.all([\n dependencies.loadSelectionSwitch(),\n dependencies.loadConfigJournal(),\n ]);\n const transition: DoomConfigPendingSelection = {\n version: 1,\n operationId: plan.operationId,\n active: selectionFromSnapshot(plan.previous),\n target: selectionFromSnapshot(plan.candidate),\n strategy: plan.strategy ?? 'pi-reload',\n phase: 'pending',\n };\n const activeConfig = loadMajorModesConfig(harness.root ?? ctx.cwd);\n const snapshot = snapshotHarnessState();\n const existingPending = currentContextAtExecution.pendingSelection;\n minorModeReloadHandoff = prepareMinorModeReloadHandoff(\n cordis,\n ctx.sessionManager.getSessionId(),\n coordinator.hostGeneration,\n plan.operationId,\n plan.previous.minorModes,\n );\n try {\n if (existingPending) supersedeDoomConfigTransition(pi, existingPending);\n appendDoomConfigTransition(pi, transition);\n const updated = applyMajorMode(\n activeConfig,\n picked,\n harness,\n plan.candidate.compositionFingerprint,\n plan.candidate.childActivation,\n );\n persistHarnessSelection(pi, updated);\n } catch (error) {\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n try {\n restoreHarnessStateSnapshot(snapshot);\n } catch (compensationError) {\n const detail =\n compensationError instanceof Error ? compensationError.message : String(compensationError);\n throw new Error(`Transition failed and compensation failed: ${detail}`, { cause: error });\n }\n appendDoomConfigTransition(pi, { ...transition, phase: 'aborted' });\n if (existingPending) appendDoomConfigTransition(pi, existingPending);\n throw error;\n }\n\n void telemetry.recordEvent(MAJOR_MODE_EVENT.majorModeSwitched, {\n 'harness.major_mode.previous': majorMode,\n 'harness.major_mode': picked,\n 'harness.layers': selected.join(','),\n 'harness.major_mode.stale': stale,\n 'harness.transition.disposition': plan.disposition,\n 'harness.transition.operation_id': plan.operationId,\n });\n ctx.ui.setStatus(STATUS_KEY, colorStatus(ctx.ui.theme, picked, domains, profile, false));\n ctx.ui.notify(applySummary(picked, selected, false, composed, plan.strategy), 'info');\n // Reload must be the command handler's terminal action. Pi invalidates\n // this command context as soon as the replacement session is active.\n reloadRequested = true;\n return 'applied';\n },\n );\n if (result.outcome === 'rejected' || result.outcome === 'stale') throw transitionError(result);\n } catch (error) {\n reloadRequested = false;\n minorModeReloadHandoff?.discard();\n minorModeReloadHandoff = undefined;\n if (!token) throw error;\n if (sessionIdentity) dependencies.reloadHandoffs.discard(token, sessionIdentity);\n ctx.ui.notify(errorMessage(error), 'error');\n }\n\n if (reloadRequested) {\n try {\n await ctx.waitForIdle();\n // The replacement session acknowledges the pending journal after its\n // bootstrap harness is active. Do not touch ctx after this await.\n await ctx.reload();\n } catch (error) {\n minorModeReloadHandoff?.discard();\n throw error;\n }\n }\n },\n });\n}\n"],"mappings":"opCAuCA,SAAS,EAAgB,EAAqC,CAC5D,OAAW,MAAM,6BAA6B,EAAO,QAAQ,IAAI,EAAO,YAAY,KAAK,IAAI,GAAG,CAClG,CAYA,SAAgB,EACd,EACA,EACA,EACM,CACN,EAAG,gBAAgB,EAAoB,CACrC,YAAa,0BACb,QAAS,MAAO,EAAM,IAAQ,CAC5B,IAAI,EACJ,GAAI,CACF,EAAQ,EAAiB,CAAI,CAC/B,OAAS,EAAO,CACd,EAAI,GAAG,OAAO,EAAa,CAAK,EAAG,OAAO,EAC1C,MACF,CACA,GAAI,EAAK,KAAK,GAAK,CAAC,EAAO,CACzB,EAAI,GAAG,OAAO,WAAW,IAAsB,SAAS,EACxD,MACF,CAEA,IAAM,EAAY,EAAI,eAAe,aAAa,EAC5C,EAAS,EAAa,cAAc,EACtC,EACA,EACA,EACA,EAAkB,GACtB,GAAI,CACF,GAAM,CAAE,SAAQ,YAAW,UAAS,WAAY,MAAM,EAAa,YAAY,CAAG,EAC5E,EAAQ,OAAO,KAAK,EAAO,SAAS,EACtC,EAEJ,GAAI,EAAO,CACT,IAAM,EAAe,EAA0B,CAAM,CAAC,EAAE,YAAY,CAAS,EAG7E,GAFI,IAAc,EAAkB,CAAE,YAAW,eAAgB,EAAa,cAAe,GAC7F,EAAU,EAAkB,EAAa,eAAe,OAAO,EAAO,CAAe,EAAI,IAAA,GACrF,GAAS,OAAA,qBAA2C,CAAC,EAAQ,UAC/D,MAAU,MAAM,2EAA2E,EAE7F,EAAS,EAAQ,SACnB,KAAO,CACL,IAAM,EAAQ,wBAAwB,EAAU,GAwBhD,GAtBE,EAAI,OAAS,MACT,MAAM,EACH,WAAW,CAAC,CACZ,MAAM,CAAE,2BACP,EAAI,GAAG,QACJ,EAAM,EAAO,EAAa,IACzB,IAAI,EACF,CAAE,QAAO,MAAO,EAAe,EAAQ,CAAK,EAAG,SAAU,CAAC,CAAS,EAAG,MAAO,EAAM,EACnF,EACA,EACA,CACF,CACJ,CACF,EACF,CACE,EACG,MAAM,EAAI,GAAG,OACZ,EACA,EAAM,IAAK,GAAS,EAAqB,EAAM,EAAO,UAAU,EAAK,EAAE,QAAU,CAAC,EAAG,CAAS,CAAC,CACjG,GAAM,EACR,CACF,EAAA,GACY,EACpB,CACA,GAAI,CAAC,EAAQ,OAEb,IAAM,EAAW,EAAgB,EACjC,GAAI,IAAW,EAAW,CACpB,GAAS,GAAiB,EAAa,eAAe,QAAQ,EAAO,CAAe,EACxF,EAAsB,EAAI,EAAa,cAAc,CAAC,EACtD,EAAI,GAAG,OACL,EAAiB,EAAQ,EAAa,cAAc,EAAQ,CAAM,EAAG,EAAW,CAAQ,EACxF,MACF,EACA,MACF,CAEA,IAAM,EAAc,EAAiC,CAAM,EACrD,EAAS,MAAM,EAAY,QAC/B,CACE,UAAW,EAAI,eAAe,aAAa,EAC3C,eAAgB,EAAY,eAC5B,YAAa,GAAS,aAAe,OAAO,WAAW,EACvD,OAAQ,EAAU,QAAU,UAC5B,OAAQ,CAAE,KAAM,aAAc,UAAW,CAAO,CAClD,EACA,MAAO,EAAU,IAAS,CACxB,IAAM,EAAW,CAAC,GAAG,EAAK,UAAU,MAAM,EACpC,EAAQ,EAAK,yBACb,EAA4B,EAAyB,CAAM,EAC3D,EAAU,EAA0B,QAC1C,GAAI,EAAK,WAAa,mBAAoB,CACxC,IAAM,EAA+C,CACnD,QAAS,EACT,YAAa,EAAK,YAClB,OAAQ,EAAsB,EAAK,QAAQ,EAC3C,OAAQ,EAAsB,EAAK,SAAS,EAC5C,SAAU,EAAK,SACf,MAAO,SACT,EACM,EAAkB,EAAyB,CAAM,CAAC,CAAC,iBAoBzD,OAnBI,GAAiB,EAA8B,EAAI,CAAe,EACtE,EAA2B,EAAI,CAAgB,EAC/C,EACE,EACA,EAAqB,EAAyB,CAAM,EAAG,CAAgB,CACzE,EACA,EAAe,YAAY,EAAiB,kBAAmB,CAC7D,8BAA+B,EAAQ,UACvC,qBAAsB,EACtB,iBAAkB,EAAS,KAAK,GAAG,EACnC,2BAA4B,GAC5B,iCAAkC,EAAK,YACvC,kCAAmC,EAAK,WAC1C,CAAC,EACD,EAAI,GAAG,UACL,EACA,EAAY,EAAI,GAAG,MAAO,EAAQ,UAAW,EAAQ,QAAS,EAAQ,QAAS,EAAI,CACrF,EACA,EAAI,GAAG,OAAO,EAAa,EAAQ,EAAU,GAAM,EAAU,EAAK,QAAQ,EAAG,MAAM,EAC5E,QACT,CACA,GAAM,CAAC,CAAE,kBAAkB,CAAE,4BAA6B,MAAM,QAAQ,IAAI,CAC1E,EAAa,oBAAoB,EACjC,EAAa,kBAAkB,CACjC,CAAC,EACK,EAAyC,CAC7C,QAAS,EACT,YAAa,EAAK,YAClB,OAAQ,EAAsB,EAAK,QAAQ,EAC3C,OAAQ,EAAsB,EAAK,SAAS,EAC5C,SAAU,EAAK,UAAY,YAC3B,MAAO,SACT,EACM,EAAe,EAAqB,EAAQ,MAAQ,EAAI,GAAG,EAC3D,EAAW,EAAqB,EAChC,EAAkB,EAA0B,iBAClD,EAAyB,EACvB,EACA,EAAI,eAAe,aAAa,EAChC,EAAY,eACZ,EAAK,YACL,EAAK,SAAS,UAChB,EACA,GAAI,CACE,GAAiB,EAA8B,EAAI,CAAe,EACtE,EAA2B,EAAI,CAAU,EAQzC,EAAwB,EAPR,EACd,EACA,EACA,EACA,EAAK,UAAU,uBACf,EAAK,UAAU,eAEiB,CAAC,CACrC,OAAS,EAAO,CACd,GAAwB,QAAQ,EAChC,EAAyB,IAAA,GACzB,GAAI,CACF,EAA4B,CAAQ,CACtC,OAAS,EAAmB,CAC1B,IAAM,EACJ,aAA6B,MAAQ,EAAkB,QAAU,OAAO,CAAiB,EAC3F,MAAU,MAAM,8CAA8C,IAAU,CAAE,MAAO,CAAM,CAAC,CAC1F,CAGA,MAFA,EAA2B,EAAI,CAAE,GAAG,EAAY,MAAO,SAAU,CAAC,EAC9D,GAAiB,EAA2B,EAAI,CAAe,EAC7D,CACR,CAeA,OAbA,EAAe,YAAY,EAAiB,kBAAmB,CAC7D,8BAA+B,EAC/B,qBAAsB,EACtB,iBAAkB,EAAS,KAAK,GAAG,EACnC,2BAA4B,EAC5B,iCAAkC,EAAK,YACvC,kCAAmC,EAAK,WAC1C,CAAC,EACD,EAAI,GAAG,UAAU,EAAY,EAAY,EAAI,GAAG,MAAO,EAAQ,EAAS,EAAS,EAAK,CAAC,EACvF,EAAI,GAAG,OAAO,EAAa,EAAQ,EAAU,GAAO,EAAU,EAAK,QAAQ,EAAG,MAAM,EAGpF,EAAkB,GACX,SACT,CACF,EACA,GAAI,EAAO,UAAY,YAAc,EAAO,UAAY,QAAS,MAAM,EAAgB,CAAM,CAC/F,OAAS,EAAO,CAId,GAHA,EAAkB,GAClB,GAAwB,QAAQ,EAChC,EAAyB,IAAA,GACrB,CAAC,EAAO,MAAM,EACd,GAAiB,EAAa,eAAe,QAAQ,EAAO,CAAe,EAC/E,EAAI,GAAG,OAAO,EAAa,CAAK,EAAG,OAAO,CAC5C,CAEA,GAAI,EACF,GAAI,CACF,MAAM,EAAI,YAAY,EAGtB,MAAM,EAAI,OAAO,CACnB,OAAS,EAAO,CAEd,MADA,GAAwB,QAAQ,EAC1B,CACR,CAEJ,CACF,CAAC,CACH"}
@@ -1,5 +1,5 @@
1
- import { MajorModesConfig } from "@agimon-ai/doompi-config/majorModes";
2
1
  import { TransitionExecutionStrategy } from "@agimon-ai/doompi-extension-contracts/transition";
2
+ import { MajorModesConfig } from "@agimon-ai/doompi-config/majorModes";
3
3
  import { SelectItem } from "@earendil-works/pi-tui";
4
4
  //#region src/services/majorModeText.d.ts
5
5
  declare const MAJOR_MODE_COMMAND = "mode";
@@ -1,2 +1,2 @@
1
- let e=require("@agimon-ai/doompi-config/piContext");function t(e){return{version:1,majorMode:e.majorMode,domains:[...e.domains],profile:e.profile,compositionFingerprint:e.compositionFingerprint}}function n(t,n){let r=(0,e.requireDoomConfigContext)(n),i=r.pendingSelection;i&&((0,e.supersedeDoomConfigTransition)(t,i),(0,e.provideDoomConfigContext)(n,Object.freeze({...r,pendingSelection:void 0})))}function r(e,t){let n=e=>Object.freeze({...e,domains:Object.freeze([...e.domains])});return Object.freeze({...e,pendingSelection:Object.freeze({...t,active:n(t.active),target:n(t.target)})})}exports.bindPendingSelection=r,exports.clearPendingSelection=n,exports.selectionFromSnapshot=t;
1
+ let e=require("@agimon-ai/doompi-config/piContext");function t(e){return{version:1,majorMode:e.majorMode,domains:[...e.domains],profile:e.profile,compositionFingerprint:e.compositionFingerprint}}function n(t,n){let r=(0,e.requireDoomConfigContext)(n),i=r.pendingSelection;i&&((0,e.supersedeDoomConfigTransition)(t,i),(0,e.replaceDoomConfigContext)(n,Object.freeze({...r,pendingSelection:void 0})))}function r(e,t){let n=e=>Object.freeze({...e,domains:Object.freeze([...e.domains])});return Object.freeze({...e,pendingSelection:Object.freeze({...t,active:n(t.active),target:n(t.target)})})}exports.bindPendingSelection=r,exports.clearPendingSelection=n,exports.selectionFromSnapshot=t;
2
2
  //# sourceMappingURL=pendingSelection.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pendingSelection.cjs","names":["requireDoomConfigContext","provideDoomConfigContext"],"sources":["../../src/services/pendingSelection.ts"],"sourcesContent":["import {\n provideDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigContext, DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport type { TransitionSelectionSnapshot } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\n/** The journal shape a transition records for the session that resumes after it. */\nexport function selectionFromSnapshot(snapshot: TransitionSelectionSnapshot) {\n return {\n version: 1 as const,\n majorMode: snapshot.majorMode,\n domains: [...snapshot.domains],\n profile: snapshot.profile,\n compositionFingerprint: snapshot.compositionFingerprint,\n };\n}\n\nexport function clearPendingSelection(pi: ExtensionAPI, ctx: ExtensionContext): void {\n const context = requireDoomConfigContext(ctx);\n const pendingSelection = context.pendingSelection;\n if (!pendingSelection) return;\n supersedeDoomConfigTransition(pi, pendingSelection);\n void provideDoomConfigContext(ctx, Object.freeze({ ...context, pendingSelection: undefined }));\n}\n\nexport function bindPendingSelection(\n context: DoomConfigContext,\n pendingSelection: DoomConfigPendingSelection,\n): DoomConfigContext {\n const freezeSelection = (selection: DoomConfigPendingSelection['active']) =>\n Object.freeze({ ...selection, domains: Object.freeze([...selection.domains]) });\n return Object.freeze({\n ...context,\n pendingSelection: Object.freeze({\n ...pendingSelection,\n active: freezeSelection(pendingSelection.active),\n target: freezeSelection(pendingSelection.target),\n }),\n });\n}\n"],"mappings":"oDAUA,SAAgB,EAAsB,EAAuC,CAC3E,MAAO,CACL,QAAS,EACT,UAAW,EAAS,UACpB,QAAS,CAAC,GAAG,EAAS,OAAO,EAC7B,QAAS,EAAS,QAClB,uBAAwB,EAAS,sBACnC,CACF,CAEA,SAAgB,EAAsB,EAAkB,EAA6B,CACnF,IAAM,GAAA,EAAUA,EAAAA,yBAAAA,CAAyB,CAAG,EACtC,EAAmB,EAAQ,iBAC5B,KACL,EAAA,EAAA,8BAAA,CAA8B,EAAI,CAAgB,GAClD,EAAKC,EAAAA,yBAAAA,CAAyB,EAAK,OAAO,OAAO,CAAE,GAAG,EAAS,iBAAkB,IAAA,EAAU,CAAC,CAAC,EAC/F,CAEA,SAAgB,EACd,EACA,EACmB,CACnB,IAAM,EAAmB,GACvB,OAAO,OAAO,CAAE,GAAG,EAAW,QAAS,OAAO,OAAO,CAAC,GAAG,EAAU,OAAO,CAAC,CAAE,CAAC,EAChF,OAAO,OAAO,OAAO,CACnB,GAAG,EACH,iBAAkB,OAAO,OAAO,CAC9B,GAAG,EACH,OAAQ,EAAgB,EAAiB,MAAM,EAC/C,OAAQ,EAAgB,EAAiB,MAAM,CACjD,CAAC,CACH,CAAC,CACH"}
1
+ {"version":3,"file":"pendingSelection.cjs","names":["requireDoomConfigContext"],"sources":["../../src/services/pendingSelection.ts"],"sourcesContent":["import {\n replaceDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigContext, DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport type { TransitionSelectionSnapshot } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\n/** The journal shape a transition records for the session that resumes after it. */\nexport function selectionFromSnapshot(snapshot: TransitionSelectionSnapshot) {\n return {\n version: 1 as const,\n majorMode: snapshot.majorMode,\n domains: [...snapshot.domains],\n profile: snapshot.profile,\n compositionFingerprint: snapshot.compositionFingerprint,\n };\n}\n\nexport function clearPendingSelection(pi: ExtensionAPI, cordis: Context): void {\n const context = requireDoomConfigContext(cordis);\n const pendingSelection = context.pendingSelection;\n if (!pendingSelection) return;\n supersedeDoomConfigTransition(pi, pendingSelection);\n replaceDoomConfigContext(cordis, Object.freeze({ ...context, pendingSelection: undefined }));\n}\n\nexport function bindPendingSelection(\n context: DoomConfigContext,\n pendingSelection: DoomConfigPendingSelection,\n): DoomConfigContext {\n const freezeSelection = (selection: DoomConfigPendingSelection['active']) =>\n Object.freeze({ ...selection, domains: Object.freeze([...selection.domains]) });\n return Object.freeze({\n ...context,\n pendingSelection: Object.freeze({\n ...pendingSelection,\n active: freezeSelection(pendingSelection.active),\n target: freezeSelection(pendingSelection.target),\n }),\n });\n}\n"],"mappings":"oDAWA,SAAgB,EAAsB,EAAuC,CAC3E,MAAO,CACL,QAAS,EACT,UAAW,EAAS,UACpB,QAAS,CAAC,GAAG,EAAS,OAAO,EAC7B,QAAS,EAAS,QAClB,uBAAwB,EAAS,sBACnC,CACF,CAEA,SAAgB,EAAsB,EAAkB,EAAuB,CAC7E,IAAM,GAAA,EAAUA,EAAAA,yBAAAA,CAAyB,CAAM,EACzC,EAAmB,EAAQ,iBAC5B,KACL,EAAA,EAAA,8BAAA,CAA8B,EAAI,CAAgB,GAClD,EAAA,EAAA,yBAAA,CAAyB,EAAQ,OAAO,OAAO,CAAE,GAAG,EAAS,iBAAkB,IAAA,EAAU,CAAC,CAAC,EAC7F,CAEA,SAAgB,EACd,EACA,EACmB,CACnB,IAAM,EAAmB,GACvB,OAAO,OAAO,CAAE,GAAG,EAAW,QAAS,OAAO,OAAO,CAAC,GAAG,EAAU,OAAO,CAAC,CAAE,CAAC,EAChF,OAAO,OAAO,OAAO,CACnB,GAAG,EACH,iBAAkB,OAAO,OAAO,CAC9B,GAAG,EACH,OAAQ,EAAgB,EAAiB,MAAM,EAC/C,OAAQ,EAAgB,EAAiB,MAAM,CACjD,CAAC,CACH,CAAC,CACH"}
@@ -1,4 +1,5 @@
1
- import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
1
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { Context } from "@deepseek-ai/cordis";
2
3
  import { TransitionSelectionSnapshot } from "@agimon-ai/doompi-extension-contracts/transition";
3
4
  import { DoomConfigContext, DoomConfigPendingSelection } from "@agimon-ai/doompi-config/types";
4
5
  //#region src/services/pendingSelection.d.ts
@@ -10,7 +11,7 @@ declare function selectionFromSnapshot(snapshot: TransitionSelectionSnapshot): {
10
11
  profile: string | undefined;
11
12
  compositionFingerprint: string | undefined;
12
13
  };
13
- declare function clearPendingSelection(pi: ExtensionAPI, ctx: ExtensionContext): void;
14
+ declare function clearPendingSelection(pi: ExtensionAPI, cordis: Context): void;
14
15
  declare function bindPendingSelection(context: DoomConfigContext, pendingSelection: DoomConfigPendingSelection): DoomConfigContext;
15
16
  //#endregion
16
17
  export { bindPendingSelection, clearPendingSelection, selectionFromSnapshot };
@@ -1 +1 @@
1
- {"version":3,"file":"pendingSelection.d.cts","names":[],"sources":["../../src/services/pendingSelection.ts"],"mappings":";;;;;iBAUgB,sBAAsB,UAAU;;;;;;;iBAUhC,sBAAsB,IAAI,cAAc,KAAK;iBAQ7C,qBACd,SAAS,mBACT,kBAAkB,6BACjB"}
1
+ {"version":3,"file":"pendingSelection.d.cts","names":[],"sources":["../../src/services/pendingSelection.ts"],"mappings":";;;;;;iBAWgB,sBAAsB,UAAU;;;;;;;iBAUhC,sBAAsB,IAAI,cAAc,QAAQ;iBAQhD,qBACd,SAAS,mBACT,kBAAkB,6BACjB"}
@@ -1,5 +1,6 @@
1
1
  import { TransitionSelectionSnapshot } from "@agimon-ai/doompi-extension-contracts/transition";
2
- import { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ import { Context } from "@deepseek-ai/cordis";
3
4
  import { DoomConfigContext, DoomConfigPendingSelection } from "@agimon-ai/doompi-config/types";
4
5
  //#region src/services/pendingSelection.d.ts
5
6
  /** The journal shape a transition records for the session that resumes after it. */
@@ -10,7 +11,7 @@ declare function selectionFromSnapshot(snapshot: TransitionSelectionSnapshot): {
10
11
  profile: string | undefined;
11
12
  compositionFingerprint: string | undefined;
12
13
  };
13
- declare function clearPendingSelection(pi: ExtensionAPI, ctx: ExtensionContext): void;
14
+ declare function clearPendingSelection(pi: ExtensionAPI, cordis: Context): void;
14
15
  declare function bindPendingSelection(context: DoomConfigContext, pendingSelection: DoomConfigPendingSelection): DoomConfigContext;
15
16
  //#endregion
16
17
  export { bindPendingSelection, clearPendingSelection, selectionFromSnapshot };
@@ -1 +1 @@
1
- {"version":3,"file":"pendingSelection.d.mts","names":[],"sources":["../../src/services/pendingSelection.ts"],"mappings":";;;;;iBAUgB,sBAAsB,UAAU;;;;;;;iBAUhC,sBAAsB,IAAI,cAAc,KAAK;iBAQ7C,qBACd,SAAS,mBACT,kBAAkB,6BACjB"}
1
+ {"version":3,"file":"pendingSelection.d.mts","names":[],"sources":["../../src/services/pendingSelection.ts"],"mappings":";;;;;;iBAWgB,sBAAsB,UAAU;;;;;;;iBAUhC,sBAAsB,IAAI,cAAc,QAAQ;iBAQhD,qBACd,SAAS,mBACT,kBAAkB,6BACjB"}
@@ -1,2 +1,2 @@
1
- import{provideDoomConfigContext as e,requireDoomConfigContext as t,supersedeDoomConfigTransition as n}from"@agimon-ai/doompi-config/piContext";function r(e){return{version:1,majorMode:e.majorMode,domains:[...e.domains],profile:e.profile,compositionFingerprint:e.compositionFingerprint}}function i(r,i){let a=t(i),o=a.pendingSelection;o&&(n(r,o),e(i,Object.freeze({...a,pendingSelection:void 0})))}function a(e,t){let n=e=>Object.freeze({...e,domains:Object.freeze([...e.domains])});return Object.freeze({...e,pendingSelection:Object.freeze({...t,active:n(t.active),target:n(t.target)})})}export{a as bindPendingSelection,i as clearPendingSelection,r as selectionFromSnapshot};
1
+ import{replaceDoomConfigContext as e,requireDoomConfigContext as t,supersedeDoomConfigTransition as n}from"@agimon-ai/doompi-config/piContext";function r(e){return{version:1,majorMode:e.majorMode,domains:[...e.domains],profile:e.profile,compositionFingerprint:e.compositionFingerprint}}function i(r,i){let a=t(i),o=a.pendingSelection;o&&(n(r,o),e(i,Object.freeze({...a,pendingSelection:void 0})))}function a(e,t){let n=e=>Object.freeze({...e,domains:Object.freeze([...e.domains])});return Object.freeze({...e,pendingSelection:Object.freeze({...t,active:n(t.active),target:n(t.target)})})}export{a as bindPendingSelection,i as clearPendingSelection,r as selectionFromSnapshot};
2
2
  //# sourceMappingURL=pendingSelection.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pendingSelection.mjs","names":[],"sources":["../../src/services/pendingSelection.ts"],"sourcesContent":["import {\n provideDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigContext, DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport type { TransitionSelectionSnapshot } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\n\n/** The journal shape a transition records for the session that resumes after it. */\nexport function selectionFromSnapshot(snapshot: TransitionSelectionSnapshot) {\n return {\n version: 1 as const,\n majorMode: snapshot.majorMode,\n domains: [...snapshot.domains],\n profile: snapshot.profile,\n compositionFingerprint: snapshot.compositionFingerprint,\n };\n}\n\nexport function clearPendingSelection(pi: ExtensionAPI, ctx: ExtensionContext): void {\n const context = requireDoomConfigContext(ctx);\n const pendingSelection = context.pendingSelection;\n if (!pendingSelection) return;\n supersedeDoomConfigTransition(pi, pendingSelection);\n void provideDoomConfigContext(ctx, Object.freeze({ ...context, pendingSelection: undefined }));\n}\n\nexport function bindPendingSelection(\n context: DoomConfigContext,\n pendingSelection: DoomConfigPendingSelection,\n): DoomConfigContext {\n const freezeSelection = (selection: DoomConfigPendingSelection['active']) =>\n Object.freeze({ ...selection, domains: Object.freeze([...selection.domains]) });\n return Object.freeze({\n ...context,\n pendingSelection: Object.freeze({\n ...pendingSelection,\n active: freezeSelection(pendingSelection.active),\n target: freezeSelection(pendingSelection.target),\n }),\n });\n}\n"],"mappings":"+IAUA,SAAgB,EAAsB,EAAuC,CAC3E,MAAO,CACL,QAAS,EACT,UAAW,EAAS,UACpB,QAAS,CAAC,GAAG,EAAS,OAAO,EAC7B,QAAS,EAAS,QAClB,uBAAwB,EAAS,sBACnC,CACF,CAEA,SAAgB,EAAsB,EAAkB,EAA6B,CACnF,IAAM,EAAU,EAAyB,CAAG,EACtC,EAAmB,EAAQ,iBAC5B,IACL,EAA8B,EAAI,CAAgB,EAClD,EAA8B,EAAK,OAAO,OAAO,CAAE,GAAG,EAAS,iBAAkB,IAAA,EAAU,CAAC,CAAC,EAC/F,CAEA,SAAgB,EACd,EACA,EACmB,CACnB,IAAM,EAAmB,GACvB,OAAO,OAAO,CAAE,GAAG,EAAW,QAAS,OAAO,OAAO,CAAC,GAAG,EAAU,OAAO,CAAC,CAAE,CAAC,EAChF,OAAO,OAAO,OAAO,CACnB,GAAG,EACH,iBAAkB,OAAO,OAAO,CAC9B,GAAG,EACH,OAAQ,EAAgB,EAAiB,MAAM,EAC/C,OAAQ,EAAgB,EAAiB,MAAM,CACjD,CAAC,CACH,CAAC,CACH"}
1
+ {"version":3,"file":"pendingSelection.mjs","names":[],"sources":["../../src/services/pendingSelection.ts"],"sourcesContent":["import {\n replaceDoomConfigContext,\n requireDoomConfigContext,\n supersedeDoomConfigTransition,\n} from '@agimon-ai/doompi-config/piContext';\nimport type { DoomConfigContext, DoomConfigPendingSelection } from '@agimon-ai/doompi-config/types';\nimport type { TransitionSelectionSnapshot } from '@agimon-ai/doompi-extension-contracts/transition';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\n/** The journal shape a transition records for the session that resumes after it. */\nexport function selectionFromSnapshot(snapshot: TransitionSelectionSnapshot) {\n return {\n version: 1 as const,\n majorMode: snapshot.majorMode,\n domains: [...snapshot.domains],\n profile: snapshot.profile,\n compositionFingerprint: snapshot.compositionFingerprint,\n };\n}\n\nexport function clearPendingSelection(pi: ExtensionAPI, cordis: Context): void {\n const context = requireDoomConfigContext(cordis);\n const pendingSelection = context.pendingSelection;\n if (!pendingSelection) return;\n supersedeDoomConfigTransition(pi, pendingSelection);\n replaceDoomConfigContext(cordis, Object.freeze({ ...context, pendingSelection: undefined }));\n}\n\nexport function bindPendingSelection(\n context: DoomConfigContext,\n pendingSelection: DoomConfigPendingSelection,\n): DoomConfigContext {\n const freezeSelection = (selection: DoomConfigPendingSelection['active']) =>\n Object.freeze({ ...selection, domains: Object.freeze([...selection.domains]) });\n return Object.freeze({\n ...context,\n pendingSelection: Object.freeze({\n ...pendingSelection,\n active: freezeSelection(pendingSelection.active),\n target: freezeSelection(pendingSelection.target),\n }),\n });\n}\n"],"mappings":"+IAWA,SAAgB,EAAsB,EAAuC,CAC3E,MAAO,CACL,QAAS,EACT,UAAW,EAAS,UACpB,QAAS,CAAC,GAAG,EAAS,OAAO,EAC7B,QAAS,EAAS,QAClB,uBAAwB,EAAS,sBACnC,CACF,CAEA,SAAgB,EAAsB,EAAkB,EAAuB,CAC7E,IAAM,EAAU,EAAyB,CAAM,EACzC,EAAmB,EAAQ,iBAC5B,IACL,EAA8B,EAAI,CAAgB,EAClD,EAAyB,EAAQ,OAAO,OAAO,CAAE,GAAG,EAAS,iBAAkB,IAAA,EAAU,CAAC,CAAC,EAC7F,CAEA,SAAgB,EACd,EACA,EACmB,CACnB,IAAM,EAAmB,GACvB,OAAO,OAAO,CAAE,GAAG,EAAW,QAAS,OAAO,OAAO,CAAC,GAAG,EAAU,OAAO,CAAC,CAAE,CAAC,EAChF,OAAO,OAAO,OAAO,CACnB,GAAG,EACH,iBAAkB,OAAO,OAAO,CAC9B,GAAG,EACH,OAAQ,EAAgB,EAAiB,MAAM,EAC/C,OAAQ,EAAgB,EAAiB,MAAM,CACjD,CAAC,CACH,CAAC,CACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-major-mode",
3
- "version": "0.0.1-alpha.2",
3
+ "version": "0.0.1-alpha.3",
4
4
  "description": "Named major-mode selection and layer composition switching for DoomPi sessions.",
5
5
  "keywords": [
6
6
  "ai",
@@ -47,10 +47,10 @@
47
47
  "dependencies": {
48
48
  "@deepseek-ai/cordis": "4.0.1",
49
49
  "typebox": "1.1.38",
50
- "@agimon-ai/doompi-config": "0.0.1-alpha.24",
51
- "@agimon-ai/doompi-telemetry": "0.0.1-alpha.24",
52
- "@agimon-ai/doompi-ui": "0.0.1-alpha.24",
53
- "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.24"
50
+ "@agimon-ai/doompi-ui": "0.0.1-alpha.25",
51
+ "@agimon-ai/doompi-config": "0.0.1-alpha.25",
52
+ "@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.25",
53
+ "@agimon-ai/doompi-telemetry": "0.0.1-alpha.25"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@deepseek-ai/cordis": "4.0.1",
@@ -61,7 +61,7 @@
61
61
  "tsdown": "0.22.14",
62
62
  "typescript": "6.0.3",
63
63
  "vitest": "4.1.10",
64
- "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.24"
64
+ "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.25"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@earendil-works/pi-coding-agent": "0.84.2",