{"version":3,"file":"context-catalog.mjs","names":[],"sources":["../../src/extensions/contextCatalog.ts"],"sourcesContent":["import { removeContextDetail, writeContextDetail } from '@agimon-ai/doompi-core/context-detail-store';\nimport { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-core/help';\nimport { DOOM_MCP_STATUS_SERVICE, readDoomMcpStatus } from '@agimon-ai/doompi-core/mcp-status';\nimport { definePiExtension } from '@agimon-ai/doompi-core/pi-extension';\nimport { DOOM_MINOR_MODE_CATALOG_SERVICE, requireMinorModeCatalog } from '@agimon-ai/doompi-minor-mode';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { createContextPublisher, type ContextPublisher } from '../builders/cli/contextCatalog';\nconst HELP_CONTRIBUTION_SOURCE = '@agimon-ai/doompi';\nexport default definePiExtension('@agimon-ai/doompi/context-catalog', ({ pi }) => {\n  let publisher: ContextPublisher | undefined;\n  /**\n   * A handler's context, kept so the prompt can be read when the composition is\n   * published rather than only when an event fires.\n   *\n   * `getSystemPrompt` reads the session's live state and refuses only once the\n   * runner has been replaced, so a retained context answers for the session it\n   * came from or throws. Publishing happens on a timer and on catalog changes,\n   * neither of which carries a context of its own.\n   */\n  let promptContext: { getSystemPrompt: () => string } | undefined;\n  /** Pi hands out the base prompt until a turn replaces it with the one it sent. */\n  let turned = false;\n  const bind = (cordis: Context): void => {\n    cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n      const contribution = requireDoomHelpService(helpContext).register({\n        source: HELP_CONTRIBUTION_SOURCE,\n        moduleUrl: import.meta.url,\n        skills: [\n          {\n            name: 'doompi-author-extension',\n            description:\n              'Create or update a DoomPi extension package inside the DoomPi monorepo or as an external npm package. Use for package layout, Pi discovery entries, shared Cordis lifecycle, package-owned Help, and extension verification.',\n          },\n        ],\n      });\n      return () => contribution.dispose();\n    });\n\n    cordis.inject([DOOM_CORDIS_SESSION_SERVICE, DOOM_MINOR_MODE_CATALOG_SERVICE], (context) => {\n      const session = context.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n      const catalog = requireMinorModeCatalog(context);\n      const current = createContextPublisher(pi, context, {\n        readMinorModes: () =>\n          catalog\n            .getSnapshot()\n            .modes.filter(({ state }) => state.activation === 'active')\n            .map(({ descriptor }) => ({ id: descriptor.id, label: descriptor.label })),\n        readSessionId: () => session.sessionId,\n        writeDetail: (sessionId, revision, items) => void writeContextDetail(sessionId, revision, items),\n        removeDetail: removeContextDetail,\n        readSystemPrompt: () => {\n          try {\n            const text = promptContext?.getSystemPrompt();\n            return text === undefined || text === '' ? undefined : { text, stage: turned ? 'effective' : 'base' };\n          } catch {\n            // A context from a retired runner is stale, not fatal: the panel\n            // reports no prompt until the next event hands over a live one.\n            return undefined;\n          }\n        },\n      });\n      publisher = current;\n      const publish = () => {\n        void current.publish();\n      };\n      const unsubscribe = catalog.subscribe(publish);\n      const timer = setTimeout(publish, 500);\n      context.inject([DOOM_MCP_STATUS_SERVICE], (mcpContext) => {\n        const release = readDoomMcpStatus(mcpContext)?.onChange?.(publish);\n        publish();\n        return release;\n      });\n      return () => {\n        clearTimeout(timer);\n        unsubscribe();\n        current.dispose();\n        if (publisher === current) publisher = undefined;\n      };\n    });\n  };\n  return {\n    services: [bind],\n    events: {\n      session_start(_event, ctx) {\n        promptContext = ctx;\n        void publisher?.publish();\n      },\n      turn_start(_event, ctx) {\n        promptContext = ctx;\n        turned = true;\n        void publisher?.publish();\n      },\n    },\n  };\n});\n"],"mappings":";;;;;;;;AASA,MAAM,2BAA2B;AACjC,IAAA,yBAAe,kBAAkB,sCAAsC,EAAE,SAAS;CAChF,IAAI;;;;;;;;;;CAUJ,IAAI;;CAEJ,IAAI,SAAS;CACb,MAAM,QAAQ,WAA0B;EACtC,OAAO,OAAO,CAAC,iBAAiB,IAAI,gBAAgB;GAClD,MAAM,eAAe,uBAAuB,WAAW,CAAC,CAAC,SAAS;IAChE,QAAQ;IACR,WAAW,YAAY;IACvB,QAAQ,CACN;KACE,MAAM;KACN,aACE;IACJ,CACF;GACF,CAAC;GACD,aAAa,aAAa,QAAQ;EACpC,CAAC;EAED,OAAO,OAAO,CAAC,6BAA6B,+BAA+B,IAAI,YAAY;GACzF,MAAM,UAAU,QAAQ,IAAI,2BAA2B;GACvD,MAAM,UAAU,wBAAwB,OAAO;GAC/C,MAAM,UAAU,uBAAuB,IAAI,SAAS;IAClD,sBACE,QACG,YAAY,CAAC,CACb,MAAM,QAAQ,EAAE,YAAY,MAAM,eAAe,QAAQ,CAAC,CAC1D,KAAK,EAAE,kBAAkB;KAAE,IAAI,WAAW;KAAI,OAAO,WAAW;IAAM,EAAE;IAC7E,qBAAqB,QAAQ;IAC7B,cAAc,WAAW,UAAU,UAAU,KAAK,mBAAmB,WAAW,UAAU,KAAK;IAC/F,cAAc;IACd,wBAAwB;KACtB,IAAI;MACF,MAAM,OAAO,eAAe,gBAAgB;MAC5C,OAAO,SAAS,KAAA,KAAa,SAAS,KAAK,KAAA,IAAY;OAAE;OAAM,OAAO,SAAS,cAAc;MAAO;KACtG,QAAQ;MAGN;KACF;IACF;GACF,CAAC;GACD,YAAY;GACZ,MAAM,gBAAgB;IACpB,QAAa,QAAQ;GACvB;GACA,MAAM,cAAc,QAAQ,UAAU,OAAO;GAC7C,MAAM,QAAQ,WAAW,SAAS,GAAG;GACrC,QAAQ,OAAO,CAAC,uBAAuB,IAAI,eAAe;IACxD,MAAM,UAAU,kBAAkB,UAAU,CAAC,EAAE,WAAW,OAAO;IACjE,QAAQ;IACR,OAAO;GACT,CAAC;GACD,aAAa;IACX,aAAa,KAAK;IAClB,YAAY;IACZ,QAAQ,QAAQ;IAChB,IAAI,cAAc,SAAS,YAAY,KAAA;GACzC;EACF,CAAC;CACH;CACA,OAAO;EACL,UAAU,CAAC,IAAI;EACf,QAAQ;GACN,cAAc,QAAQ,KAAK;IACzB,gBAAgB;IAChB,WAAgB,QAAQ;GAC1B;GACA,WAAW,QAAQ,KAAK;IACtB,gBAAgB;IAChB,SAAS;IACT,WAAgB,QAAQ;GAC1B;EACF;CACF;AACF,CAAC"}