{"version":3,"file":"sync.cjs","names":["AGENT_FILES","isAgentId","join","existsSync","resolve","dirname","parseAgentFile","readFile","decodeNative","parseJson","validatePolicy","mostRestrictiveMode","collectRules","deduplicateRules","isPermissionMode","CODECS","UnsupportedCapabilityError","OmpEncoded","editOmpConfig","parseYaml","ompGlobalConfigPath","writeFile","mkdir"],"sources":["../src/sync.ts"],"sourcesContent":["/**\n * Permission policy sync — detect, merge, and write agent configs.\n *\n * Walks up the directory tree, detects all agent permission configs, decodes into canonical rules,\n * merges them, and writes back.\n *\n * Merge semantics:\n *\n * - Rules: union with deny-first (deny > ask > allow for same tool/pattern)\n * - DefaultMode: most restrictive wins\n * - Agent-specific fields (sandbox, profiles, network): from canonical only\n *\n * Write-back:\n *\n * - `.agents/permissions.json` always gets the full merged canonical form\n * - Native agent configs get their encoded form from the canonical merge\n * - `.agents/permissions.local.json` is read but never written\n * - Codex skipped (TOML), Crush skipped (no file)\n * - Oh My Pi: the project's `.omp/config.yml` is read and written like any native config, and the\n *   global config in its agent directory is read too, since OMP replaces the global\n *   `bash.patterns` with the project's rather than joining them; the global file is written only\n *   with `ompGlobal`. Only `bash.patterns` and `tools.approvalMode` change, the rest of the YAML\n *   is kept, and the old file is always backed up first.\n */\n\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { parse as parseYaml } from \"yaml\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { AgentPermissionPolicy, type Rule } from \"./schema.ts\";\nimport { CODECS, OmpEncoded, type AgentId } from \"./compat/codecs.ts\";\nimport { UnsupportedCapabilityError } from \"./compat/unsupported.ts\";\nimport { isAgentId, isPermissionMode } from \"./guards.ts\";\nimport {\n  collectRules,\n  deduplicateRules,\n  mostRestrictiveMode,\n} from \"./evaluate.ts\";\nimport {\n  AGENT_FILES,\n  decodeNative,\n  editOmpConfig,\n  ompGlobalConfigPath,\n  parseAgentFile,\n  parseJson,\n  validatePolicy,\n} from \"./agent-files.ts\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SyncOptions {\n  /** Starting directory. */\n  cwd: string;\n  /** Number of parent directories to ascend (0 = cwd only). Infinity = root. */\n  up: number;\n  /** Agents to include in bidirectional sync. Empty = all detected. */\n  with: AgentId[];\n  /** Agents to exclude from bidirectional sync. */\n  without: AgentId[];\n  /** Apply changes without prompting. */\n  yes: boolean;\n  /** Show changes only, never write. */\n  dryRun: boolean;\n  /** Create config files that don't exist. */\n  create: boolean;\n  /** Show verbose output (rule provenance). */\n  verbose: boolean;\n  /** Write .bak files before overwriting. Oh My Pi's config is always backed up. */\n  backup: boolean;\n  /** Oh My Pi's agent directory, which holds its global config (see `defaultOmpAgentDir`). */\n  ompAgentDir: string;\n  /** Also write Oh My Pi's global config, which every OMP session on the machine reads. */\n  ompGlobal: boolean;\n}\n\nexport interface SyncResult {\n  /** Per-file changes that would be applied. */\n  changes: FileChange[];\n  /** Whether changes were applied. */\n  applied: boolean;\n  /**\n   * Agents whose native format cannot enforce a rule in the merged policy. When any are listed\n   * nothing is written, since a partial sync would leave the refused agents on a looser policy.\n   */\n  refused: UnsupportedCapabilityError[];\n}\n\nexport interface FileChange {\n  /** Absolute path to the file. */\n  path: string;\n  /** Agent this file belongs to. */\n  agent: AgentId | \"canonical\";\n  /** \"create\" | \"update\" */\n  kind: \"create\" | \"update\";\n  /** Current content (null for new files). */\n  current: string | null;\n  /** Proposed content. */\n  proposed: string;\n}\n\n// ---------------------------------------------------------------------------\n// Agent file detection\n// ---------------------------------------------------------------------------\n\ninterface AgentFile {\n  agent: AgentId | \"canonical\";\n  /** Absolute path to the config file. */\n  path: string;\n  /** Whether this is a local override (read-only, never written). */\n  local: boolean;\n}\n\n/** Detect which agent files exist in a directory. */\nfunction detectFiles(dir: string): AgentFile[] {\n  const found: AgentFile[] = [];\n\n  for (const [key, def] of Object.entries(AGENT_FILES)) {\n    if (!isAgentId(key) && key !== \"canonical\") continue;\n    const agent: AgentId | \"canonical\" = key;\n    const main = join(dir, def.name);\n    if (existsSync(main)) {\n      found.push({ agent, path: main, local: false });\n    }\n    if (def.localName) {\n      const local = join(dir, def.localName);\n      if (existsSync(local)) {\n        found.push({ agent, path: local, local: true });\n      }\n    }\n  }\n\n  return found;\n}\n\n/** Walk up from cwd, collecting agent files. */\nfunction collectFiles(cwd: string, up: number): AgentFile[] {\n  const files: AgentFile[] = [];\n  let current = resolve(cwd);\n  let remaining = up === Infinity ? Number.MAX_SAFE_INTEGER : up + 1;\n\n  while (remaining > 0) {\n    const found = detectFiles(current);\n    files.push(...found);\n    remaining--;\n\n    const parent = dirname(current);\n    if (parent === current) break; // reached root\n\n    current = parent;\n  }\n\n  return files;\n}\n\n// ---------------------------------------------------------------------------\n// Reading and decoding\n// ---------------------------------------------------------------------------\n\nexport interface DecodedSource {\n  file: AgentFile;\n  policy: AgentPermissionPolicy;\n}\n\nasync function readAndDecode(\n  file: AgentFile,\n  agentFilter: Set<string> | undefined,\n): Promise<DecodedSource | undefined> {\n  // Skip if --with/--without excludes this agent\n  if (\n    agentFilter &&\n    !agentFilter.has(file.agent) &&\n    file.agent !== \"canonical\"\n  ) {\n    return undefined;\n  }\n\n  const def = AGENT_FILES[file.agent];\n\n  // Skip agents without extract/wrap (crush, codex) or without a file def\n  if (def.extract === undefined) return undefined;\n\n  // OMP's config is written by editing it in place, so one that cannot be read is an error: skipping\n  // it would let the write replace entries nobody read.\n  if (file.agent === \"omp\") {\n    const parsed = parseAgentFile(\n      \"omp\",\n      await readFile(file.path, \"utf-8\"),\n      file.path,\n    );\n    if (!parsed.ok) throw new Error(parsed.error);\n    const result = decodeNative(\"omp\", parsed.value);\n    if (!result.ok) throw new Error(`${file.path}: ${result.error}`);\n    return { file, policy: result.value };\n  }\n\n  // Read and parse\n  let content: string;\n  try {\n    content = await readFile(file.path, \"utf-8\");\n  } catch {\n    return undefined;\n  }\n  const parsed = parseJson(content, file.path);\n  if (!parsed.ok) return undefined;\n\n  // Canonical files parse directly\n  if (file.agent === \"canonical\") {\n    const validated = validatePolicy(parsed.value);\n    if (!validated.ok) return undefined;\n    return { file, policy: validated.value };\n  }\n\n  // Native files — extract, decode, validate\n  const result = decodeNative(file.agent, parsed.value);\n  if (!result.ok) return undefined;\n  return { file, policy: result.value };\n}\n\n// ---------------------------------------------------------------------------\n// Merging\n// ---------------------------------------------------------------------------\n\n/** Two delegation blocks as one that is at least as strict as each, keeping the other keys of both. */\nfunction mergeDelegation(\n  a: AgentPermissionPolicy[\"delegation\"],\n  b: NonNullable<AgentPermissionPolicy[\"delegation\"]>,\n): NonNullable<AgentPermissionPolicy[\"delegation\"]> {\n  const merged = { ...a, ...b };\n  const depths = [a?.maxDepth, b.maxDepth].filter((d) => d !== undefined);\n  if (depths.length > 0) merged.maxDepth = Math.min(...depths);\n  const barred = [...(a?.nonDelegable ?? []), ...(b.nonDelegable ?? [])];\n  if (barred.length > 0) merged.nonDelegable = [...new Set(barred)];\n  return merged;\n}\n\nfunction mergePolicies(sources: DecodedSource[]): AgentPermissionPolicy {\n  if (sources.length === 0) {\n    return {};\n  }\n\n  let defaultMode: string | undefined;\n  const allRules: Rule[] = [];\n  const additionalDirectories: string[] = [];\n  let sandbox: AgentPermissionPolicy[\"sandbox\"];\n  let network: AgentPermissionPolicy[\"network\"];\n  let profiles: AgentPermissionPolicy[\"profiles\"];\n  let activeProfile: string | undefined;\n  let delegation: AgentPermissionPolicy[\"delegation\"];\n  let env: AgentPermissionPolicy[\"env\"];\n  const roles: NonNullable<AgentPermissionPolicy[\"roles\"]> = {};\n\n  for (const { policy } of sources) {\n    // defaultMode: most restrictive wins\n    defaultMode = mostRestrictiveMode(defaultMode, policy.defaultMode);\n\n    // Rules: collect then deduplicate with deny-first priority. Roles are kept as roles below, so\n    // the written file is not rewritten into rules that carry a role condition.\n    allRules.push(\n      ...collectRules({ rules: policy.rules, permissions: policy.permissions }),\n    );\n\n    // Roles: each role's lists joined across sources\n    for (const [role, tiers] of Object.entries(policy.roles ?? {})) {\n      const joined = (roles[role] ??= {});\n      for (const tier of [\"deny\", \"ask\", \"allow\"] as const) {\n        const merged = [...(joined[tier] ?? []), ...(tiers[tier] ?? [])];\n        if (merged.length > 0) joined[tier] = [...new Set(merged)];\n      }\n    }\n\n    // Additional directories: union\n    if (policy.permissions?.additionalDirectories) {\n      for (const dir of policy.permissions.additionalDirectories) {\n        if (!additionalDirectories.includes(dir)) {\n          additionalDirectories.push(dir);\n        }\n      }\n    }\n\n    // Agent-specific fields: take from canonical source if present,\n    // otherwise from the first source that has them\n    if (policy.sandbox) sandbox = { ...sandbox, ...policy.sandbox };\n    if (policy.network) network = { ...network, ...policy.network };\n    if (policy.profiles) profiles = { ...(profiles ?? {}), ...policy.profiles };\n    if (policy.activeProfile) activeProfile = policy.activeProfile;\n    // Delegation limits only tighten: the shallowest maxDepth, every nonDelegable rule\n    if (policy.delegation) {\n      delegation = mergeDelegation(delegation, policy.delegation);\n    }\n    if (policy.env) env = { ...(env ?? {}), ...policy.env };\n  }\n\n  const rules = deduplicateRules(allRules);\n\n  const result: AgentPermissionPolicy = {};\n\n  if (defaultMode !== undefined && isPermissionMode(defaultMode))\n    result.defaultMode = defaultMode;\n\n  if (rules.length > 0) result.rules = rules;\n\n  if (additionalDirectories.length > 0) {\n    result.permissions = { additionalDirectories };\n  }\n\n  if (sandbox) result.sandbox = sandbox;\n  if (network) result.network = network;\n  if (profiles && Object.keys(profiles).length > 0) result.profiles = profiles;\n  if (activeProfile) result.activeProfile = activeProfile;\n  if (delegation) result.delegation = delegation;\n  if (Object.keys(roles).length > 0) result.roles = roles;\n  if (env && Object.keys(env).length > 0) result.env = env;\n\n  return result;\n}\n\n// ---------------------------------------------------------------------------\n// Encoding and write-back\n// ---------------------------------------------------------------------------\n\ninterface WriteTarget {\n  agent: AgentId | \"canonical\";\n  path: string;\n  /** The file's new content, given its current content (`null` for a new file). */\n  render: (current: string | null) => string;\n  exists: boolean;\n}\n\n/** What sync needs from a codec, so the encoding step can be tested without real agent formats. */\ninterface Encoder {\n  encode(canonical: AgentPermissionPolicy): unknown;\n}\n\n/**\n * Work out the files to write. An agent whose codec refuses the merged policy is reported in\n * `refused` and never skipped silently.\n *\n * @param ompGlobalPath Oh My Pi's global config, written as well when given.\n */\nexport function computeWriteTargets(\n  cwd: string,\n  merged: AgentPermissionPolicy,\n  sources: DecodedSource[],\n  agentFilter: Set<string> | undefined,\n  create: boolean,\n  codecs: Readonly<Record<AgentId, Encoder>> = CODECS,\n  ompGlobalPath?: string,\n): { targets: WriteTarget[]; refused: UnsupportedCapabilityError[] } {\n  const targets: WriteTarget[] = [];\n  const refused: UnsupportedCapabilityError[] = [];\n\n  // Always write canonical at cwd (unless excluded)\n  const canonicalPath = join(cwd, \".agents\", \"permissions.json\");\n  const schemaUrl =\n    \"https://github.com/Mearman/agent-permissions/releases/latest/download/agent-permissions.schema.json\";\n  const canonicalWithSchema = { $schema: schemaUrl, ...merged };\n  if (!agentFilter || agentFilter.has(\"canonical\")) {\n    const content = JSON.stringify(canonicalWithSchema, null, 2) + \"\\n\";\n    targets.push({\n      agent: \"canonical\",\n      path: canonicalPath,\n      render: () => content,\n      exists: existsSync(canonicalPath),\n    });\n  }\n\n  // Write native configs at cwd\n  for (const key of Object.keys(codecs)) {\n    if (!isAgentId(key)) continue;\n    const agent: AgentId = key;\n    if (agentFilter && !agentFilter.has(agent)) continue;\n    if (agent === \"codex\" || agent === \"crush\") continue; // TOML / no file\n\n    const def = AGENT_FILES[agent];\n    const filePath = join(cwd, def.name);\n    const fileExists = existsSync(filePath);\n\n    if (!fileExists && !create) continue;\n\n    // Check if there's a source from this agent (or create is enabled)\n    const hasSource = sources.some((s) => s.file.agent === agent);\n    if (!hasSource && !create) continue;\n\n    let encoded: unknown;\n    try {\n      encoded = codecs[agent].encode(merged);\n    } catch (e) {\n      if (e instanceof UnsupportedCapabilityError) {\n        refused.push(e);\n        continue;\n      }\n      throw e;\n    }\n\n    if (agent === \"omp\") {\n      targets.push(ompTarget(filePath, OmpEncoded.parse(encoded)));\n      continue;\n    }\n\n    // Wrap in native config structure (e.g. { permissions: ... })\n    if (def.wrap) encoded = def.wrap(encoded);\n    const content = JSON.stringify(encoded, null, 2) + \"\\n\";\n\n    targets.push({\n      agent,\n      path: filePath,\n      render: () => content,\n      exists: fileExists,\n    });\n  }\n\n  // OMP's global config, when asked for, unless the project file's encoding was already refused\n  if (\n    ompGlobalPath !== undefined &&\n    (!agentFilter || agentFilter.has(\"omp\")) &&\n    (existsSync(ompGlobalPath) || create) &&\n    !refused.some((r) => r.agent === \"omp\")\n  ) {\n    try {\n      targets.push(\n        ompTarget(ompGlobalPath, OmpEncoded.parse(codecs.omp.encode(merged))),\n      );\n    } catch (e) {\n      if (!(e instanceof UnsupportedCapabilityError)) throw e;\n      refused.push(e);\n    }\n  }\n\n  return { targets, refused };\n}\n\n/** An OMP config target, edited in place so only the keys the codec writes change. */\nfunction ompTarget(path: string, encoded: OmpEncoded): WriteTarget {\n  return {\n    agent: \"omp\",\n    path,\n    render: (current) => editOmpConfig(current, encoded),\n    exists: existsSync(path),\n  };\n}\n\n/** Whether a file's current and proposed content hold the same data, whatever the formatting. */\nfunction sameData(\n  agent: AgentId | \"canonical\",\n  current: string,\n  proposed: string,\n): boolean {\n  if (agent === \"omp\") {\n    return (\n      JSON.stringify(parseYaml(current)) === JSON.stringify(parseYaml(proposed))\n    );\n  }\n  try {\n    const currentParsed: unknown = JSON.parse(current);\n    const proposedParsed: unknown = JSON.parse(proposed);\n    return JSON.stringify(currentParsed) === JSON.stringify(proposedParsed);\n  } catch {\n    return current === proposed;\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Diff display\n// ---------------------------------------------------------------------------\n\nfunction formatChange(change: FileChange): string {\n  const kind = change.kind === \"create\" ? \"+\" : \"~\";\n  const label = change.agent === \"canonical\" ? \"canonical\" : change.agent;\n\n  let output = `${kind} ${label}: ${change.path}\\n`;\n\n  if (change.kind === \"create\") {\n    output += \"  (new file)\\n\";\n    // Show first few lines\n    const lines = change.proposed.split(\"\\n\").slice(0, 10);\n    for (const line of lines) {\n      output += `  ${line}\\n`;\n    }\n    if (change.proposed.split(\"\\n\").length > 10) {\n      output += \"  ...\\n\";\n    }\n  } else {\n    // Show diff-like summary\n    const currentLines = (change.current ?? \"\").split(\"\\n\");\n    const proposedLines = change.proposed.split(\"\\n\");\n\n    const added = proposedLines.filter((l) => !currentLines.includes(l));\n    const removed = currentLines.filter((l) => !proposedLines.includes(l));\n\n    for (const line of removed.slice(0, 20)) {\n      if (line.trim()) output += `  - ${line}\\n`;\n    }\n    for (const line of added.slice(0, 20)) {\n      if (line.trim()) output += `  + ${line}\\n`;\n    }\n\n    if (added.length > 20 || removed.length > 20) {\n      output += `  ... (${String(added.length)} additions, ${String(removed.length)} removals)\\n`;\n    }\n  }\n\n  return output;\n}\n\n// ---------------------------------------------------------------------------\n// Main sync function\n// ---------------------------------------------------------------------------\n\nexport async function sync(options: SyncOptions): Promise<SyncResult> {\n  const {\n    cwd,\n    up,\n    with: withList,\n    without: withoutList,\n    yes,\n    dryRun,\n    create,\n    verbose,\n    backup,\n    ompAgentDir,\n    ompGlobal,\n  } = options;\n\n  // Build agent filter from --with/--without\n  const agentFilter = buildAgentFilter(withList, withoutList);\n\n  // 1. Collect files by walking up, plus OMP's global config, which OMP reads beneath every project\n  const files = collectFiles(cwd, up);\n  const ompGlobalPath = ompGlobalConfigPath(ompAgentDir);\n  if (\n    (!agentFilter || agentFilter.has(\"omp\")) &&\n    existsSync(ompGlobalPath) &&\n    !files.some((f) => f.path === ompGlobalPath)\n  ) {\n    files.push({ agent: \"omp\", path: ompGlobalPath, local: false });\n  }\n\n  if (files.length === 0) {\n    process.stderr.write(\n      \"No permission configs found. Create .agents/permissions.json to get started.\\n\",\n    );\n    return { changes: [], applied: false, refused: [] };\n  }\n\n  if (verbose) {\n    process.stderr.write(\"Detected config files:\\n\");\n    for (const f of files) {\n      const local = f.local ? \" (local, read-only)\" : \"\";\n      process.stderr.write(`  ${f.agent}: ${f.path}${local}\\n`);\n    }\n    process.stderr.write(\"\\n\");\n  }\n\n  // 2. Read and decode all sources\n  const sources: DecodedSource[] = [];\n  for (const file of files) {\n    // Skip local files for write-back consideration\n    const decoded = await readAndDecode(file, agentFilter);\n    if (decoded) {\n      sources.push(decoded);\n      if (verbose) {\n        const rules = collectRules(decoded.policy);\n        process.stderr.write(\n          `  ${file.agent} (${file.path}): ${String(rules.length)} rules, mode=${decoded.policy.defaultMode ?? \"standard\"}\\n`,\n        );\n      }\n    }\n  }\n\n  if (sources.length === 0) {\n    process.stderr.write(\"No readable permission configs found.\\n\");\n    return { changes: [], applied: false, refused: [] };\n  }\n\n  // 3. Merge all sources\n  const merged = mergePolicies(sources);\n\n  if (verbose) {\n    const rules = collectRules(merged);\n    process.stderr.write(\n      `\\nMerged: ${String(rules.length)} rules, mode=${merged.defaultMode ?? \"standard\"}\\n`,\n    );\n  }\n\n  // 4. Compute write targets\n  const { targets, refused } = computeWriteTargets(\n    cwd,\n    merged,\n    sources,\n    agentFilter,\n    create,\n    CODECS,\n    ompGlobal ? ompGlobalPath : undefined,\n  );\n\n  if (refused.length > 0) {\n    for (const error of refused)\n      process.stderr.write(`error: ${error.message}\\n`);\n    process.stderr.write(\n      \"Nothing was written. Fix the rules above, or leave the agent out with --without.\\n\",\n    );\n    return { changes: [], applied: false, refused };\n  }\n\n  if (targets.length === 0) {\n    process.stderr.write(\"No write targets.\\n\");\n    return { changes: [], applied: false, refused: [] };\n  }\n\n  // 5. Build changes\n  const changes: FileChange[] = [];\n  for (const target of targets) {\n    let current: string | null = null;\n    if (target.exists) {\n      try {\n        current = await readFile(target.path, \"utf-8\");\n      } catch {\n        current = null;\n      }\n    }\n\n    const proposed = target.render(current);\n\n    // Skip if content is semantically identical\n    if (current !== null) {\n      if (sameData(target.agent, current, proposed)) continue;\n    } else if (proposed === \"\") {\n      continue;\n    }\n\n    changes.push({\n      path: target.path,\n      agent: target.agent,\n      kind: target.exists ? \"update\" : \"create\",\n      current,\n      proposed,\n    });\n  }\n\n  if (changes.length === 0) {\n    process.stderr.write(\"Already in sync — no changes needed.\\n\");\n    return { changes: [], applied: true, refused: [] };\n  }\n\n  // 6. Display changes\n  process.stderr.write(\"\\nChanges:\\n\\n\");\n  for (const change of changes) {\n    process.stderr.write(formatChange(change));\n    process.stderr.write(\"\\n\");\n  }\n\n  // 7. Apply or prompt\n  if (dryRun) {\n    process.stderr.write(\"(dry run — no changes written)\\n\");\n    return { changes, applied: false, refused: [] };\n  }\n\n  if (!yes) {\n    process.stderr.write(\"Apply these changes? [y/N] \");\n    const answer = await readLine();\n    if (answer.toLowerCase() !== \"y\" && answer.toLowerCase() !== \"yes\") {\n      process.stderr.write(\"Aborted.\\n\");\n      return { changes, applied: false, refused: [] };\n    }\n  }\n\n  // 8. Write files\n  for (const change of changes) {\n    // Backup if requested and file exists. OMP's config is hand-written and holds much more than\n    // permissions, so it is always backed up.\n    if ((backup || change.agent === \"omp\") && change.current !== null) {\n      await writeFile(change.path + \".bak\", change.current);\n    }\n\n    // Ensure directory exists\n    const dir = dirname(change.path);\n    await mkdir(dir, { recursive: true });\n\n    await writeFile(change.path, change.proposed);\n  }\n\n  process.stderr.write(`Applied ${String(changes.length)} change(s).\\n`);\n  return { changes, applied: true, refused: [] };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction readLine(): Promise<string> {\n  return new Promise((resolve) => {\n    process.stdin.setEncoding(\"utf-8\");\n    process.stdin.once(\"data\", (data: string) => {\n      resolve(data.trim());\n    });\n  });\n}\n\n/**\n * Build an agent filter from --with and --without lists. Returns undefined when no filtering is\n * needed (all agents included). --with and --without are mutually exclusive.\n */\nfunction buildAgentFilter(\n  withList: AgentId[],\n  withoutList: AgentId[],\n): Set<string> | undefined {\n  if (withList.length > 0) {\n    // --with: only include listed agents + canonical\n    const filter = new Set<string>(withList);\n    filter.add(\"canonical\");\n    return filter;\n  }\n\n  if (withoutList.length > 0) {\n    // --without: include all except listed\n    const allAgents = [...Object.keys(CODECS), \"canonical\"];\n    // Set<string> so the filter can compare plain key strings against the excluded names.\n    const excluded = new Set<string>(withoutList);\n    return new Set(allAgents.filter((a) => !excluded.has(a)));\n  }\n\n  return undefined;\n}\n"],"mappings":"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"}