{"version":3,"file":"contextContributions.cjs","names":[],"sources":["../../src/services/contextContributions.ts"],"sourcesContent":["import type {\n  DoomContextContribution,\n  DoomContextContributionEntry,\n  DoomContextContributionError,\n  DoomContextContributionRegistration,\n  DoomContextContributionsService,\n  DoomContextContributionsSnapshot,\n} from '../schemas/contextContributions.ts';\n\ninterface StoredContribution extends DoomContextContribution {\n  readonly key: string;\n}\n\nfunction compareContributions(left: DoomContextContribution, right: DoomContextContribution): number {\n  const sourceOrder = left.source < right.source ? -1 : left.source > right.source ? 1 : 0;\n  const idOrder = left.id < right.id ? -1 : left.id > right.id ? 1 : 0;\n  return left.order - right.order || sourceOrder || idOrder;\n}\n\nfunction assertNonEmpty(value: string, field: string): void {\n  if (value.trim().length === 0) throw new Error(`Doom context contribution ${field} must not be empty.`);\n}\n\nfunction contributionErrorMessage(error: unknown): string {\n  return error instanceof Error ? error.message : String(error);\n}\n\n/** Creates the host-owned aggregation service for one Doom session generation. */\nexport function createDoomContextContributionsService(generation: string): DoomContextContributionsService {\n  if (!generation) throw new Error('Doom context contributions require a session generation.');\n\n  const contributions = new Map<string, StoredContribution>();\n  return Object.freeze({\n    generation,\n    register(contribution: DoomContextContribution): DoomContextContributionRegistration {\n      assertNonEmpty(contribution.source, 'source');\n      assertNonEmpty(contribution.id, 'id');\n      assertNonEmpty(contribution.label, 'label');\n      if (!Number.isFinite(contribution.order)) {\n        throw new Error('Doom context contribution order must be a finite number.');\n      }\n      if (typeof contribution.snapshot !== 'function') {\n        throw new Error('Doom context contribution snapshot must be a function.');\n      }\n\n      const key = JSON.stringify([contribution.source, contribution.id]);\n      if (contributions.has(key)) {\n        throw new Error(`Doom context contribution is already registered: ${contribution.source}/${contribution.id}.`);\n      }\n      const stored: StoredContribution = Object.freeze({\n        key,\n        source: contribution.source,\n        id: contribution.id,\n        label: contribution.label,\n        order: contribution.order,\n        snapshot: () => contribution.snapshot(),\n      });\n      contributions.set(key, stored);\n\n      let disposed = false;\n      return Object.freeze({\n        dispose(): void {\n          if (disposed) return;\n          disposed = true;\n          if (contributions.get(key) === stored) contributions.delete(key);\n        },\n      });\n    },\n    snapshot(): DoomContextContributionsSnapshot {\n      const entries: DoomContextContributionEntry[] = [];\n      const errors: DoomContextContributionError[] = [];\n      const ordered = [...contributions.values()].sort(compareContributions);\n\n      for (const contribution of ordered) {\n        const identity = {\n          source: contribution.source,\n          id: contribution.id,\n          label: contribution.label,\n          order: contribution.order,\n        };\n        try {\n          const text = contribution.snapshot();\n          if (text === undefined) continue;\n          if (typeof text !== 'string') throw new Error('Snapshot returned a non-string value.');\n          entries.push(Object.freeze({ ...identity, text }));\n        } catch (error) {\n          errors.push(Object.freeze({ ...identity, message: contributionErrorMessage(error) }));\n        }\n      }\n\n      return Object.freeze({ entries: Object.freeze(entries), errors: Object.freeze(errors) });\n    },\n  });\n}\n"],"mappings":"AAaA,SAAS,EAAqB,EAA+B,EAAwC,CACnG,IAAM,EAAc,EAAK,OAAS,EAAM,OAAS,GAAK,IAAK,OAAS,EAAM,QACpE,EAAU,EAAK,GAAK,EAAM,GAAK,GAAK,IAAK,GAAK,EAAM,IAC1D,OAAO,EAAK,MAAQ,EAAM,OAAS,GAAe,CACpD,CAEA,SAAS,EAAe,EAAe,EAAqB,CAC1D,GAAI,EAAM,KAAK,CAAC,CAAC,SAAW,EAAG,MAAU,MAAM,6BAA6B,EAAM,oBAAoB,CACxG,CAEA,SAAS,EAAyB,EAAwB,CACxD,OAAO,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAC9D,CAGA,SAAgB,EAAsC,EAAqD,CACzG,GAAI,CAAC,EAAY,MAAU,MAAM,0DAA0D,EAE3F,IAAM,EAAgB,IAAI,IAC1B,OAAO,OAAO,OAAO,CACnB,aACA,SAAS,EAA4E,CAInF,GAHA,EAAe,EAAa,OAAQ,QAAQ,EAC5C,EAAe,EAAa,GAAI,IAAI,EACpC,EAAe,EAAa,MAAO,OAAO,EACtC,CAAC,OAAO,SAAS,EAAa,KAAK,EACrC,MAAU,MAAM,0DAA0D,EAE5E,GAAI,OAAO,EAAa,UAAa,WACnC,MAAU,MAAM,wDAAwD,EAG1E,IAAM,EAAM,KAAK,UAAU,CAAC,EAAa,OAAQ,EAAa,EAAE,CAAC,EACjE,GAAI,EAAc,IAAI,CAAG,EACvB,MAAU,MAAM,oDAAoD,EAAa,OAAO,GAAG,EAAa,GAAG,EAAE,EAE/G,IAAM,EAA6B,OAAO,OAAO,CAC/C,MACA,OAAQ,EAAa,OACrB,GAAI,EAAa,GACjB,MAAO,EAAa,MACpB,MAAO,EAAa,MACpB,aAAgB,EAAa,SAAS,CACxC,CAAC,EACD,EAAc,IAAI,EAAK,CAAM,EAE7B,IAAI,EAAW,GACf,OAAO,OAAO,OAAO,CACnB,SAAgB,CACV,IACJ,EAAW,GACP,EAAc,IAAI,CAAG,IAAM,GAAQ,EAAc,OAAO,CAAG,EACjE,CACF,CAAC,CACH,EACA,UAA6C,CAC3C,IAAM,EAA0C,CAAC,EAC3C,EAAyC,CAAC,EAC1C,EAAU,CAAC,GAAG,EAAc,OAAO,CAAC,CAAC,CAAC,KAAK,CAAoB,EAErE,IAAK,IAAM,KAAgB,EAAS,CAClC,IAAM,EAAW,CACf,OAAQ,EAAa,OACrB,GAAI,EAAa,GACjB,MAAO,EAAa,MACpB,MAAO,EAAa,KACtB,EACA,GAAI,CACF,IAAM,EAAO,EAAa,SAAS,EACnC,GAAI,IAAS,IAAA,GAAW,SACxB,GAAI,OAAO,GAAS,SAAU,MAAU,MAAM,uCAAuC,EACrF,EAAQ,KAAK,OAAO,OAAO,CAAE,GAAG,EAAU,MAAK,CAAC,CAAC,CACnD,OAAS,EAAO,CACd,EAAO,KAAK,OAAO,OAAO,CAAE,GAAG,EAAU,QAAS,EAAyB,CAAK,CAAE,CAAC,CAAC,CACtF,CACF,CAEA,OAAO,OAAO,OAAO,CAAE,QAAS,OAAO,OAAO,CAAO,EAAG,OAAQ,OAAO,OAAO,CAAM,CAAE,CAAC,CACzF,CACF,CAAC,CACH"}