@cleocode/caamp 1.7.1 → 1.8.0
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.
- package/README.md +0 -0
- package/dist/{chunk-6T3TJQFF.js → chunk-YWO4I7LI.js} +162 -837
- package/dist/chunk-YWO4I7LI.js.map +1 -0
- package/dist/chunk-ZVRDBY6L.js +756 -0
- package/dist/chunk-ZVRDBY6L.js.map +1 -0
- package/dist/cli.d.ts +0 -0
- package/dist/cli.js +20 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +194 -12
- package/dist/index.js +201 -47
- package/dist/index.js.map +1 -1
- package/dist/injector-XGI7NNZA.js +19 -0
- package/dist/injector-XGI7NNZA.js.map +1 -0
- package/package.json +1 -1
- package/providers/registry.json +0 -0
- package/dist/chunk-6T3TJQFF.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/instructions/injector.ts","../src/core/instructions/templates.ts","../src/core/registry/providers.ts","../src/core/paths/standard.ts","../src/core/platform-paths.ts"],"sourcesContent":["/**\n * Marker-based instruction file injection\n *\n * Injects content blocks between CAAMP markers in instruction files\n * (CLAUDE.md, AGENTS.md, GEMINI.md).\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { mkdir } from \"node:fs/promises\";\nimport type { InjectionStatus, InjectionCheckResult, Provider } from \"../../types.js\";\nimport { buildInjectionContent, type InjectionTemplate } from \"./templates.js\";\nimport { getProvider } from \"../registry/providers.js\";\n\nconst MARKER_START = \"<!-- CAAMP:START -->\";\nconst MARKER_END = \"<!-- CAAMP:END -->\";\nconst MARKER_PATTERN = /<!-- CAAMP:START -->[\\s\\S]*?<!-- CAAMP:END -->/;\n\n/**\n * Check the status of a CAAMP injection block in an instruction file.\n *\n * Returns the injection status:\n * - `\"missing\"` - File does not exist\n * - `\"none\"` - File exists but has no CAAMP markers\n * - `\"current\"` - CAAMP block exists and matches expected content (or no expected content given)\n * - `\"outdated\"` - CAAMP block exists but differs from expected content\n *\n * @param filePath - Absolute path to the instruction file\n * @param expectedContent - Optional expected content to compare against\n * @returns The injection status\n *\n * @example\n * ```typescript\n * const status = await checkInjection(\"/project/CLAUDE.md\", expectedContent);\n * if (status === \"outdated\") {\n * console.log(\"CAAMP injection needs updating\");\n * }\n * ```\n */\nexport async function checkInjection(\n filePath: string,\n expectedContent?: string,\n): Promise<InjectionStatus> {\n if (!existsSync(filePath)) return \"missing\";\n\n const content = await readFile(filePath, \"utf-8\");\n\n if (!MARKER_PATTERN.test(content)) return \"none\";\n\n if (expectedContent) {\n const blockContent = extractBlock(content);\n if (blockContent && blockContent.trim() === expectedContent.trim()) {\n return \"current\";\n }\n return \"outdated\";\n }\n\n return \"current\";\n}\n\n/** Extract the content between CAAMP markers */\nfunction extractBlock(content: string): string | null {\n const match = content.match(MARKER_PATTERN);\n if (!match) return null;\n\n return match[0]\n .replace(MARKER_START, \"\")\n .replace(MARKER_END, \"\")\n .trim();\n}\n\n/** Build the injection block */\nfunction buildBlock(content: string): string {\n return `${MARKER_START}\\n${content}\\n${MARKER_END}`;\n}\n\n/**\n * Inject content into an instruction file between CAAMP markers.\n *\n * Behavior depends on the file state:\n * - File does not exist: creates the file with the injection block → `\"created\"`\n * - File exists without markers: prepends the injection block → `\"added\"`\n * - File exists with markers, content differs: replaces the block → `\"updated\"`\n * - File exists with markers, content matches: no-op → `\"intact\"`\n *\n * This function is **idempotent** — calling it multiple times with the same\n * content will not modify the file after the first write.\n *\n * @param filePath - Absolute path to the instruction file\n * @param content - Content to inject between CAAMP markers\n * @returns Action taken: `\"created\"`, `\"added\"`, `\"updated\"`, or `\"intact\"`\n *\n * @example\n * ```typescript\n * const action = await inject(\"/project/CLAUDE.md\", \"## My Config\\nSome content\");\n * console.log(`File ${action}`); // \"created\" on first call, \"intact\" on subsequent\n * ```\n */\nexport async function inject(\n filePath: string,\n content: string,\n): Promise<\"created\" | \"added\" | \"updated\" | \"intact\"> {\n const block = buildBlock(content);\n\n // Ensure parent directory exists\n await mkdir(dirname(filePath), { recursive: true });\n\n if (!existsSync(filePath)) {\n // Create new file with injection block\n await writeFile(filePath, `${block}\\n`, \"utf-8\");\n return \"created\";\n }\n\n const existing = await readFile(filePath, \"utf-8\");\n\n if (MARKER_PATTERN.test(existing)) {\n // Check if existing content already matches (idempotency)\n const existingBlock = extractBlock(existing);\n if (existingBlock !== null && existingBlock.trim() === content.trim()) {\n return \"intact\";\n }\n\n // Replace existing block with new content\n const updated = existing.replace(MARKER_PATTERN, block);\n await writeFile(filePath, updated, \"utf-8\");\n return \"updated\";\n }\n\n // Prepend block to existing content\n const updated = `${block}\\n\\n${existing}`;\n await writeFile(filePath, updated, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Remove the CAAMP injection block from an instruction file.\n *\n * If removing the block would leave the file empty, the file is deleted entirely.\n *\n * @param filePath - Absolute path to the instruction file\n * @returns `true` if a CAAMP block was found and removed, `false` otherwise\n *\n * @example\n * ```typescript\n * const removed = await removeInjection(\"/project/CLAUDE.md\");\n * ```\n */\nexport async function removeInjection(filePath: string): Promise<boolean> {\n if (!existsSync(filePath)) return false;\n\n const content = await readFile(filePath, \"utf-8\");\n if (!MARKER_PATTERN.test(content)) return false;\n\n const cleaned = content\n .replace(MARKER_PATTERN, \"\")\n .replace(/^\\n{2,}/, \"\\n\")\n .trim();\n\n if (!cleaned) {\n // File would be empty - remove it entirely\n const { rm } = await import(\"node:fs/promises\");\n await rm(filePath);\n } else {\n await writeFile(filePath, `${cleaned}\\n`, \"utf-8\");\n }\n\n return true;\n}\n\n/**\n * Check injection status across all providers' instruction files.\n *\n * Deduplicates by file path since multiple providers may share the same\n * instruction file (e.g. many providers use `AGENTS.md`).\n *\n * @param providers - Array of providers to check\n * @param projectDir - Absolute path to the project directory\n * @param scope - Whether to check project or global instruction files\n * @param expectedContent - Optional expected content to compare against\n * @returns Array of injection check results, one per unique instruction file\n *\n * @example\n * ```typescript\n * const results = await checkAllInjections(providers, \"/project\", \"project\");\n * const outdated = results.filter(r => r.status === \"outdated\");\n * ```\n */\nexport async function checkAllInjections(\n providers: Provider[],\n projectDir: string,\n scope: \"project\" | \"global\",\n expectedContent?: string,\n): Promise<InjectionCheckResult[]> {\n const results: InjectionCheckResult[] = [];\n const checked = new Set<string>();\n\n for (const provider of providers) {\n const filePath = scope === \"global\"\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n\n // Skip duplicates (multiple providers share same instruction file)\n if (checked.has(filePath)) continue;\n checked.add(filePath);\n\n const status = await checkInjection(filePath, expectedContent);\n\n results.push({\n file: filePath,\n provider: provider.id,\n status,\n fileExists: existsSync(filePath),\n });\n }\n\n return results;\n}\n\n/**\n * Inject content into all providers' instruction files.\n *\n * Deduplicates by file path to avoid injecting the same file multiple times.\n *\n * @param providers - Array of providers to inject into\n * @param projectDir - Absolute path to the project directory\n * @param scope - Whether to target project or global instruction files\n * @param content - Content to inject between CAAMP markers\n * @returns Map of file path to action taken (`\"created\"`, `\"added\"`, `\"updated\"`, or `\"intact\"`)\n *\n * @example\n * ```typescript\n * const results = await injectAll(providers, \"/project\", \"project\", content);\n * for (const [file, action] of results) {\n * console.log(`${file}: ${action}`);\n * }\n * ```\n */\nexport async function injectAll(\n providers: Provider[],\n projectDir: string,\n scope: \"project\" | \"global\",\n content: string,\n): Promise<Map<string, \"created\" | \"added\" | \"updated\" | \"intact\">> {\n const results = new Map<string, \"created\" | \"added\" | \"updated\" | \"intact\">();\n const injected = new Set<string>();\n\n for (const provider of providers) {\n const filePath = scope === \"global\"\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n\n // Skip duplicates\n if (injected.has(filePath)) continue;\n injected.add(filePath);\n\n const action = await inject(filePath, content);\n results.set(filePath, action);\n }\n\n return results;\n}\n\n// ── Provider Instruction File API ─────────────────────────────────\n\n/**\n * Options for ensuring a provider instruction file.\n */\nexport interface EnsureProviderInstructionFileOptions {\n /** `@` references to inject (e.g. `[\"@AGENTS.md\"]`). */\n references: string[];\n /** Optional inline content blocks. */\n content?: string[];\n /** Whether this is a global or project-level file. Defaults to `\"project\"`. */\n scope?: \"project\" | \"global\";\n}\n\n/**\n * Result of ensuring a provider instruction file.\n */\nexport interface EnsureProviderInstructionFileResult {\n /** Absolute path to the instruction file. */\n filePath: string;\n /** Instruction file name from the provider registry. */\n instructFile: string;\n /** Action taken. */\n action: \"created\" | \"added\" | \"updated\" | \"intact\";\n /** Provider ID. */\n providerId: string;\n}\n\n/**\n * Ensure a provider's instruction file exists with the correct CAAMP block.\n *\n * This is the canonical API for adapters and external packages to manage\n * provider instruction files. Instead of directly creating/modifying\n * CLAUDE.md, GEMINI.md, etc., callers should use this function to\n * delegate instruction file management to CAAMP.\n *\n * The instruction file name is resolved from CAAMP's provider registry\n * (single source of truth), not hardcoded by the caller.\n *\n * @param providerId - Provider ID from the registry (e.g. `\"claude-code\"`, `\"gemini-cli\"`)\n * @param projectDir - Absolute path to the project directory\n * @param options - References, content, and scope configuration\n * @returns Result with file path, action taken, and provider metadata\n * @throws {Error} If the provider ID is not found in the registry\n *\n * @example\n * ```typescript\n * // Adapter delegates instruction file creation to CAAMP:\n * const result = await ensureProviderInstructionFile(\"claude-code\", \"/project\", {\n * references: [\"@AGENTS.md\"],\n * });\n * // result.filePath → \"/project/CLAUDE.md\"\n * // result.action → \"created\" | \"added\" | \"updated\" | \"intact\"\n *\n * // Global scope:\n * const globalResult = await ensureProviderInstructionFile(\"claude-code\", homedir(), {\n * references: [\"@~/.agents/AGENTS.md\"],\n * scope: \"global\",\n * });\n * ```\n */\nexport async function ensureProviderInstructionFile(\n providerId: string,\n projectDir: string,\n options: EnsureProviderInstructionFileOptions,\n): Promise<EnsureProviderInstructionFileResult> {\n const provider = getProvider(providerId);\n if (!provider) {\n throw new Error(`Unknown provider: \"${providerId}\". Check CAAMP provider registry.`);\n }\n\n const scope = options.scope ?? \"project\";\n const filePath = scope === \"global\"\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n\n const template: InjectionTemplate = {\n references: options.references,\n content: options.content,\n };\n\n const injectionContent = buildInjectionContent(template);\n const action = await inject(filePath, injectionContent);\n\n return {\n filePath,\n instructFile: provider.instructFile,\n action,\n providerId: provider.id,\n };\n}\n\n/**\n * Ensure instruction files for multiple providers at once.\n *\n * Deduplicates by file path — providers sharing the same instruction file\n * (e.g. many providers use AGENTS.md) are only written once.\n *\n * @param providerIds - Array of provider IDs from the registry\n * @param projectDir - Absolute path to the project directory\n * @param options - References, content, and scope configuration\n * @returns Array of results, one per unique instruction file\n * @throws {Error} If any provider ID is not found in the registry\n *\n * @example\n * ```typescript\n * const results = await ensureAllProviderInstructionFiles(\n * [\"claude-code\", \"cursor\", \"gemini-cli\"],\n * \"/project\",\n * { references: [\"@AGENTS.md\"] },\n * );\n * ```\n */\nexport async function ensureAllProviderInstructionFiles(\n providerIds: string[],\n projectDir: string,\n options: EnsureProviderInstructionFileOptions,\n): Promise<EnsureProviderInstructionFileResult[]> {\n const results: EnsureProviderInstructionFileResult[] = [];\n const processed = new Set<string>();\n\n for (const providerId of providerIds) {\n const provider = getProvider(providerId);\n if (!provider) {\n throw new Error(`Unknown provider: \"${providerId}\". Check CAAMP provider registry.`);\n }\n\n const scope = options.scope ?? \"project\";\n const filePath = scope === \"global\"\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n\n // Skip duplicates (multiple providers may share the same instruction file)\n if (processed.has(filePath)) continue;\n processed.add(filePath);\n\n const template: InjectionTemplate = {\n references: options.references,\n content: options.content,\n };\n\n const injectionContent = buildInjectionContent(template);\n const action = await inject(filePath, injectionContent);\n\n results.push({\n filePath,\n instructFile: provider.instructFile,\n action,\n providerId: provider.id,\n });\n }\n\n return results;\n}\n","/**\n * Instruction template management\n *\n * Generates injection content based on provider capabilities.\n * Includes structured InjectionTemplate API for project-level customization.\n */\n\nimport type { Provider } from \"../../types.js\";\n\n// ── InjectionTemplate API ───────────────────────────────────────────\n\n/**\n * Structured template for injection content.\n *\n * Projects use this to define what goes between CAAMP markers in\n * instruction files, rather than passing ad-hoc strings.\n */\nexport interface InjectionTemplate {\n /** @ references to include (e.g. `\"@AGENTS.md\"`, `\"@.cleo/project-context.json\"`). */\n references: string[];\n /** Inline content blocks (raw markdown/text). */\n content?: string[];\n}\n\n/**\n * Build injection content from a structured template.\n *\n * Produces a string suitable for injection between CAAMP markers.\n * References are output as `@` lines, content blocks are appended as-is.\n *\n * @param template - Template defining references and content\n * @returns Formatted injection content string\n *\n * @example\n * ```typescript\n * const content = buildInjectionContent({\n * references: [\"@AGENTS.md\"],\n * });\n * // Returns: \"@AGENTS.md\"\n *\n * const content2 = buildInjectionContent({\n * references: [\"@AGENTS.md\", \"@.cleo/project-context.json\"],\n * content: [\"# Custom Section\", \"Some extra info\"],\n * });\n * ```\n */\nexport function buildInjectionContent(template: InjectionTemplate): string {\n const lines: string[] = [];\n\n for (const ref of template.references) {\n lines.push(ref);\n }\n\n if (template.content && template.content.length > 0) {\n if (lines.length > 0) {\n lines.push(\"\");\n }\n lines.push(...template.content);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Parse injection content back into template form.\n *\n * Lines starting with `@` are treated as references.\n * All other non-empty lines are treated as content blocks.\n *\n * @param content - Raw injection content string\n * @returns Parsed InjectionTemplate\n *\n * @example\n * ```typescript\n * const template = parseInjectionContent(\"@AGENTS.md\\n@.cleo/config.json\");\n * // { references: [\"@AGENTS.md\", \"@.cleo/config.json\"], content: [] }\n * ```\n */\nexport function parseInjectionContent(content: string): InjectionTemplate {\n const references: string[] = [];\n const contentLines: string[] = [];\n\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n if (trimmed.startsWith(\"@\")) {\n references.push(trimmed);\n } else {\n contentLines.push(line);\n }\n }\n\n return {\n references,\n content: contentLines.length > 0 ? contentLines : undefined,\n };\n}\n\n// ── Legacy API (preserved) ──────────────────────────────────────────\n\n/**\n * Generate a standard CAAMP injection block for instruction files.\n *\n * Produces markdown content suitable for injection between CAAMP markers.\n * Optionally includes MCP server and custom content sections.\n *\n * @param options - Optional configuration for the generated content\n * @param options.mcpServerName - MCP server name to include a server section\n * @param options.customContent - Additional custom markdown content to append\n * @returns Generated markdown string\n *\n * @example\n * ```typescript\n * const content = generateInjectionContent({ mcpServerName: \"filesystem\" });\n * ```\n */\nexport function generateInjectionContent(options?: {\n mcpServerName?: string;\n customContent?: string;\n}): string {\n const lines: string[] = [];\n\n lines.push(\"## CAAMP Managed Configuration\");\n lines.push(\"\");\n lines.push(\"This section is managed by [CAAMP](https://github.com/caamp/caamp).\");\n lines.push(\"Do not edit between the CAAMP markers manually.\");\n\n if (options?.mcpServerName) {\n lines.push(\"\");\n lines.push(`### MCP Server: ${options.mcpServerName}`);\n lines.push(`Configured via \\`caamp mcp install\\`.`);\n }\n\n if (options?.customContent) {\n lines.push(\"\");\n lines.push(options.customContent);\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Generate a skills discovery section for instruction files */\nexport function generateSkillsSection(skillNames: string[]): string {\n if (skillNames.length === 0) return \"\";\n\n const lines: string[] = [];\n lines.push(\"### Installed Skills\");\n lines.push(\"\");\n\n for (const name of skillNames) {\n lines.push(`- \\`${name}\\` - Available via SKILL.md`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Get the correct instruction file name for a provider */\nexport function getInstructFile(provider: Provider): string {\n return provider.instructFile;\n}\n\n/**\n * Group providers by their instruction file name.\n *\n * Useful for determining which providers share the same instruction file\n * (e.g. multiple providers using `AGENTS.md`).\n *\n * @param providers - Array of providers to group\n * @returns Map from instruction file name to array of providers using that file\n *\n * @example\n * ```typescript\n * const groups = groupByInstructFile(getAllProviders());\n * for (const [file, providers] of groups) {\n * console.log(`${file}: ${providers.map(p => p.id).join(\", \")}`);\n * }\n * ```\n */\nexport function groupByInstructFile(providers: Provider[]): Map<string, Provider[]> {\n const groups = new Map<string, Provider[]>();\n\n for (const provider of providers) {\n const existing = groups.get(provider.instructFile) ?? [];\n existing.push(provider);\n groups.set(provider.instructFile, existing);\n }\n\n return groups;\n}\n","/**\n * Provider registry loader\n *\n * Loads providers from providers/registry.json and resolves\n * platform-specific paths at runtime.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n ConfigFormat,\n DetectionMethod,\n Provider,\n ProviderCapabilities,\n ProviderHooksCapability,\n ProviderPriority,\n ProviderSkillsCapability,\n ProviderSpawnCapability,\n ProviderStatus,\n TransportType,\n} from \"../../types.js\";\nimport { type PathScope, resolveProvidersRegistryPath, resolveProviderSkillsDir, resolveRegistryTemplatePath } from \"../paths/standard.js\";\nimport type { HookEvent, ProviderRegistry, RegistryCapabilities, RegistryProvider, SkillsPrecedence, SpawnMechanism } from \"./types.js\";\n\n// ── Capability Defaults ──────────────────────────────────────────────\n\nconst DEFAULT_SKILLS_CAPABILITY: ProviderSkillsCapability = {\n agentsGlobalPath: null,\n agentsProjectPath: null,\n precedence: \"vendor-only\",\n};\n\nconst DEFAULT_HOOKS_CAPABILITY: ProviderHooksCapability = {\n supported: [],\n hookConfigPath: null,\n hookFormat: null,\n};\n\nconst DEFAULT_SPAWN_CAPABILITY: ProviderSpawnCapability = {\n supportsSubagents: false,\n supportsProgrammaticSpawn: false,\n supportsInterAgentComms: false,\n supportsParallelSpawn: false,\n spawnMechanism: null,\n};\n\nfunction resolveCapabilities(raw?: RegistryCapabilities): ProviderCapabilities {\n const skills: ProviderSkillsCapability = raw?.skills\n ? {\n agentsGlobalPath: raw.skills.agentsGlobalPath\n ? resolveRegistryTemplatePath(raw.skills.agentsGlobalPath)\n : null,\n agentsProjectPath: raw.skills.agentsProjectPath,\n precedence: raw.skills.precedence,\n }\n : { ...DEFAULT_SKILLS_CAPABILITY };\n\n const hooks: ProviderHooksCapability = raw?.hooks\n ? {\n supported: raw.hooks.supported as HookEvent[],\n hookConfigPath: raw.hooks.hookConfigPath\n ? resolveRegistryTemplatePath(raw.hooks.hookConfigPath)\n : null,\n hookFormat: raw.hooks.hookFormat as ProviderHooksCapability[\"hookFormat\"],\n }\n : { ...DEFAULT_HOOKS_CAPABILITY, supported: [] };\n\n const spawn: ProviderSpawnCapability = raw?.spawn\n ? {\n supportsSubagents: raw.spawn.supportsSubagents,\n supportsProgrammaticSpawn: raw.spawn.supportsProgrammaticSpawn,\n supportsInterAgentComms: raw.spawn.supportsInterAgentComms,\n supportsParallelSpawn: raw.spawn.supportsParallelSpawn,\n spawnMechanism: raw.spawn.spawnMechanism as SpawnMechanism | null,\n }\n : { ...DEFAULT_SPAWN_CAPABILITY };\n\n return { skills, hooks, spawn };\n}\n\nfunction findRegistryPath(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n return resolveProvidersRegistryPath(thisDir);\n}\n\nlet _registry: ProviderRegistry | null = null;\nlet _providers: Map<string, Provider> | null = null;\nlet _aliasMap: Map<string, string> | null = null;\n\nfunction resolveProvider(raw: RegistryProvider): Provider {\n return {\n id: raw.id,\n toolName: raw.toolName,\n vendor: raw.vendor,\n agentFlag: raw.agentFlag,\n aliases: raw.aliases,\n pathGlobal: resolveRegistryTemplatePath(raw.pathGlobal),\n pathProject: raw.pathProject,\n instructFile: raw.instructFile,\n configKey: raw.configKey,\n configFormat: raw.configFormat as ConfigFormat,\n configPathGlobal: resolveRegistryTemplatePath(raw.configPathGlobal),\n configPathProject: raw.configPathProject,\n pathSkills: resolveRegistryTemplatePath(raw.pathSkills),\n pathProjectSkills: raw.pathProjectSkills,\n detection: {\n methods: raw.detection.methods as DetectionMethod[],\n binary: raw.detection.binary,\n directories: raw.detection.directories?.map(resolveRegistryTemplatePath),\n appBundle: raw.detection.appBundle,\n flatpakId: raw.detection.flatpakId,\n },\n supportedTransports: raw.supportedTransports as TransportType[],\n supportsHeaders: raw.supportsHeaders,\n priority: raw.priority as ProviderPriority,\n status: raw.status as ProviderStatus,\n agentSkillsCompatible: raw.agentSkillsCompatible,\n capabilities: resolveCapabilities(raw.capabilities),\n };\n}\n\nfunction loadRegistry(): ProviderRegistry {\n if (_registry) return _registry;\n\n const registryPath = findRegistryPath();\n const raw = readFileSync(registryPath, \"utf-8\");\n _registry = JSON.parse(raw) as ProviderRegistry;\n return _registry;\n}\n\nfunction ensureProviders(): void {\n if (_providers) return;\n\n const registry = loadRegistry();\n _providers = new Map<string, Provider>();\n _aliasMap = new Map<string, string>();\n\n for (const [id, raw] of Object.entries(registry.providers)) {\n const provider = resolveProvider(raw);\n _providers.set(id, provider);\n\n // Build alias map\n for (const alias of provider.aliases) {\n _aliasMap.set(alias, id);\n }\n }\n}\n\n/**\n * Retrieve all registered providers with resolved platform paths.\n *\n * Providers are lazily loaded from `providers/registry.json` on first call\n * and cached for subsequent calls.\n *\n * @returns Array of all provider definitions\n *\n * @example\n * ```typescript\n * const providers = getAllProviders();\n * console.log(`${providers.length} providers registered`);\n * ```\n */\nexport function getAllProviders(): Provider[] {\n ensureProviders();\n if (!_providers) return [];\n return Array.from(_providers.values());\n}\n\n/**\n * Look up a provider by its ID or any of its aliases.\n *\n * @param idOrAlias - Provider ID (e.g. `\"claude-code\"`) or alias (e.g. `\"claude\"`)\n * @returns The matching provider, or `undefined` if not found\n *\n * @example\n * ```typescript\n * const provider = getProvider(\"claude\");\n * // Returns the claude-code provider via alias resolution\n * ```\n */\nexport function getProvider(idOrAlias: string): Provider | undefined {\n ensureProviders();\n const resolved = _aliasMap?.get(idOrAlias) ?? idOrAlias;\n return _providers?.get(resolved);\n}\n\n/**\n * Resolve an alias to its canonical provider ID.\n *\n * If the input is already a canonical ID (or unrecognized), it is returned as-is.\n *\n * @param idOrAlias - Provider ID or alias to resolve\n * @returns The canonical provider ID\n *\n * @example\n * ```typescript\n * resolveAlias(\"claude\"); // \"claude-code\"\n * resolveAlias(\"claude-code\"); // \"claude-code\"\n * resolveAlias(\"unknown\"); // \"unknown\"\n * ```\n */\nexport function resolveAlias(idOrAlias: string): string {\n ensureProviders();\n return _aliasMap?.get(idOrAlias) ?? idOrAlias;\n}\n\n/**\n * Filter providers by their priority tier.\n *\n * @param priority - Priority level to filter by (`\"high\"`, `\"medium\"`, or `\"low\"`)\n * @returns Array of providers matching the given priority\n *\n * @example\n * ```typescript\n * const highPriority = getProvidersByPriority(\"high\");\n * ```\n */\nexport function getProvidersByPriority(priority: ProviderPriority): Provider[] {\n return getAllProviders().filter((p) => p.priority === priority);\n}\n\n/**\n * Filter providers by their lifecycle status.\n *\n * @param status - Status to filter by (`\"active\"`, `\"beta\"`, `\"deprecated\"`, or `\"planned\"`)\n * @returns Array of providers matching the given status\n *\n * @example\n * ```typescript\n * const active = getProvidersByStatus(\"active\");\n * ```\n */\nexport function getProvidersByStatus(status: ProviderStatus): Provider[] {\n return getAllProviders().filter((p) => p.status === status);\n}\n\n/**\n * Filter providers that use a specific instruction file.\n *\n * Multiple providers often share the same instruction file (e.g. many use `\"AGENTS.md\"`).\n *\n * @param file - Instruction file name (e.g. `\"CLAUDE.md\"`, `\"AGENTS.md\"`)\n * @returns Array of providers that use the given instruction file\n *\n * @example\n * ```typescript\n * const claudeProviders = getProvidersByInstructFile(\"CLAUDE.md\");\n * ```\n */\nexport function getProvidersByInstructFile(file: string): Provider[] {\n return getAllProviders().filter((p) => p.instructFile === file);\n}\n\n/**\n * Get the set of all unique instruction file names across all providers.\n *\n * @returns Array of unique instruction file names (e.g. `[\"CLAUDE.md\", \"AGENTS.md\", \"GEMINI.md\"]`)\n *\n * @example\n * ```typescript\n * const files = getInstructionFiles();\n * // [\"CLAUDE.md\", \"AGENTS.md\", \"GEMINI.md\"]\n * ```\n */\nexport function getInstructionFiles(): string[] {\n const files = new Set<string>();\n for (const p of getAllProviders()) {\n files.add(p.instructFile);\n }\n return Array.from(files);\n}\n\n/**\n * Get the total number of registered providers.\n *\n * @returns Count of providers in the registry\n *\n * @example\n * ```typescript\n * console.log(`Registry has ${getProviderCount()} providers`);\n * ```\n */\nexport function getProviderCount(): number {\n ensureProviders();\n return _providers?.size ?? 0;\n}\n\n/**\n * Get the semantic version string of the provider registry.\n *\n * @returns Version string from `providers/registry.json` (e.g. `\"1.0.0\"`)\n *\n * @example\n * ```typescript\n * console.log(`Registry version: ${getRegistryVersion()}`);\n * ```\n */\nexport function getRegistryVersion(): string {\n return loadRegistry().version;\n}\n\n/**\n * Filter providers that support a specific hook event.\n *\n * @param event - Hook event to filter by (e.g. `\"onToolComplete\"`)\n * @returns Array of providers whose hooks capability includes the given event\n *\n * @example\n * ```typescript\n * const providers = getProvidersByHookEvent(\"onToolComplete\");\n * ```\n */\nexport function getProvidersByHookEvent(event: HookEvent): Provider[] {\n return getAllProviders().filter((p) => p.capabilities.hooks.supported.includes(event));\n}\n\n/**\n * Get hook events common to all specified providers.\n *\n * If providerIds is provided, returns the intersection of their supported events.\n * If providerIds is undefined or empty, uses all providers.\n *\n * @param providerIds - Optional array of provider IDs to intersect\n * @returns Array of hook events supported by ALL specified providers\n *\n * @example\n * ```typescript\n * const common = getCommonHookEvents([\"claude-code\", \"gemini-cli\"]);\n * ```\n */\nexport function getCommonHookEvents(providerIds?: string[]): HookEvent[] {\n const providers = providerIds && providerIds.length > 0\n ? providerIds.map((id) => getProvider(id)).filter((p): p is Provider => p !== undefined)\n : getAllProviders();\n\n if (providers.length === 0) return [];\n\n const first = providers[0]!.capabilities.hooks.supported as HookEvent[];\n return first.filter((event) =>\n providers.every((p) => p.capabilities.hooks.supported.includes(event)),\n );\n}\n\n/**\n * Check whether a provider supports a specific capability via dot-path query.\n *\n * The dot-path addresses a value inside `provider.capabilities`. For boolean\n * fields the provider \"supports\" the capability when the value is `true`.\n * For non-boolean fields the provider \"supports\" it when the value is neither\n * `null` nor `undefined` (and, for arrays, non-empty).\n *\n * @param provider - Provider to inspect\n * @param dotPath - Dot-delimited capability path (e.g. `\"spawn.supportsSubagents\"`, `\"hooks.supported\"`)\n * @returns `true` when the provider has the specified capability\n *\n * @example\n * ```typescript\n * const claude = getProvider(\"claude-code\");\n * providerSupports(claude!, \"spawn.supportsSubagents\"); // true\n * ```\n */\nexport function providerSupports(provider: Provider, dotPath: string): boolean {\n const parts = dotPath.split(\".\");\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let current: any = provider.capabilities;\n for (const part of parts) {\n if (current == null || typeof current !== \"object\") return false;\n current = current[part];\n }\n if (typeof current === \"boolean\") return current;\n if (Array.isArray(current)) return current.length > 0;\n return current != null;\n}\n\n/**\n * Filter providers that support spawning subagents.\n *\n * @returns Array of providers where `capabilities.spawn.supportsSubagents === true`\n *\n * @example\n * ```typescript\n * const spawnCapable = getSpawnCapableProviders();\n * ```\n */\nexport function getSpawnCapableProviders(): Provider[] {\n return getAllProviders().filter((p) => p.capabilities.spawn.supportsSubagents);\n}\n\n/**\n * Filter providers by a specific boolean spawn capability flag.\n *\n * @param flag - One of the four boolean flags on {@link ProviderSpawnCapability}\n * (`\"supportsSubagents\"`, `\"supportsProgrammaticSpawn\"`,\n * `\"supportsInterAgentComms\"`, `\"supportsParallelSpawn\"`)\n * @returns Array of providers where the specified flag is `true`\n *\n * @example\n * ```typescript\n * const parallel = getProvidersBySpawnCapability(\"supportsParallelSpawn\");\n * ```\n */\nexport function getProvidersBySpawnCapability(\n flag: keyof Omit<ProviderSpawnCapability, \"spawnMechanism\">,\n): Provider[] {\n return getAllProviders().filter((p) => p.capabilities.spawn[flag] === true);\n}\n\n/** Reset cached data (for testing) */\nexport function resetRegistry(): void {\n _registry = null;\n _providers = null;\n _aliasMap = null;\n}\n\n// ── Skills Query Functions ──────────────────────────────────────────\n\n/**\n * Filter providers by their skills precedence value.\n *\n * @param precedence - Skills precedence to filter by\n * @returns Array of providers matching the given precedence\n */\nexport function getProvidersBySkillsPrecedence(precedence: SkillsPrecedence): Provider[] {\n return getAllProviders().filter((p) => p.capabilities.skills.precedence === precedence);\n}\n\n/**\n * Get the effective skills paths for a provider, ordered by precedence.\n *\n * @param provider - Provider to resolve paths for\n * @param scope - Whether to resolve global or project paths\n * @param projectDir - Project directory for project-scope resolution\n * @returns Ordered array of paths with source and scope metadata\n */\nexport function getEffectiveSkillsPaths(\n provider: Provider,\n scope: PathScope,\n projectDir?: string,\n): Array<{ path: string; source: string; scope: string }> {\n const vendorPath = resolveProviderSkillsDir(provider, scope, projectDir);\n const { precedence, agentsGlobalPath, agentsProjectPath } = provider.capabilities.skills;\n\n const resolveAgentsPath = (): string | null => {\n if (scope === \"global\" && agentsGlobalPath) return agentsGlobalPath;\n if (scope === \"project\" && agentsProjectPath && projectDir) {\n return join(projectDir, agentsProjectPath);\n }\n return null;\n };\n\n const agentsPath = resolveAgentsPath();\n const scopeLabel = scope === \"global\" ? \"global\" : \"project\";\n\n switch (precedence) {\n case \"vendor-only\":\n return [{ path: vendorPath, source: \"vendor\", scope: scopeLabel }];\n case \"agents-canonical\":\n return agentsPath ? [{ path: agentsPath, source: \"agents\", scope: scopeLabel }] : [];\n case \"agents-first\":\n return [\n ...(agentsPath ? [{ path: agentsPath, source: \"agents\", scope: scopeLabel }] : []),\n { path: vendorPath, source: \"vendor\", scope: scopeLabel },\n ];\n case \"agents-supported\":\n return [\n { path: vendorPath, source: \"vendor\", scope: scopeLabel },\n ...(agentsPath ? [{ path: agentsPath, source: \"agents\", scope: scopeLabel }] : []),\n ];\n case \"vendor-global-agents-project\":\n if (scope === \"global\") {\n return [{ path: vendorPath, source: \"vendor\", scope: \"global\" }];\n }\n return [\n ...(agentsPath ? [{ path: agentsPath, source: \"agents\", scope: \"project\" }] : []),\n { path: vendorPath, source: \"vendor\", scope: \"project\" },\n ];\n default:\n return [{ path: vendorPath, source: \"vendor\", scope: scopeLabel }];\n }\n}\n\n/**\n * Build a full skills map for all providers.\n *\n * @returns Array of skills map entries with provider ID, tool name, precedence, and paths\n */\nexport function buildSkillsMap(): Array<{\n providerId: string;\n toolName: string;\n precedence: SkillsPrecedence;\n paths: { global: string | null; project: string | null };\n}> {\n return getAllProviders().map((p) => {\n const { precedence, agentsGlobalPath, agentsProjectPath } = p.capabilities.skills;\n const isVendorOnly = precedence === \"vendor-only\";\n return {\n providerId: p.id,\n toolName: p.toolName,\n precedence,\n paths: {\n global: isVendorOnly ? p.pathSkills : (agentsGlobalPath ?? null),\n project: isVendorOnly ? p.pathProjectSkills : (agentsProjectPath ?? null),\n },\n };\n });\n}\n\n/**\n * Get capabilities for a provider by ID or alias.\n *\n * @param idOrAlias - Provider ID or alias\n * @returns The provider's capabilities, or undefined if not found\n */\nexport function getProviderCapabilities(idOrAlias: string): ProviderCapabilities | undefined {\n return getProvider(idOrAlias)?.capabilities;\n}\n\n/**\n * Check if a provider supports a capability using ID/alias lookup.\n *\n * Convenience wrapper that resolves the provider first, then delegates\n * to the provider-level {@link providerSupports}.\n *\n * @param idOrAlias - Provider ID or alias\n * @param capabilityPath - Dot-path into capabilities (e.g. \"spawn.supportsSubagents\")\n * @returns true if the provider supports the capability, false otherwise\n */\nexport function providerSupportsById(idOrAlias: string, capabilityPath: string): boolean {\n const provider = getProvider(idOrAlias);\n if (!provider) return false;\n return providerSupports(provider, capabilityPath);\n}\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { Provider } from \"../../types.js\";\nimport { getPlatformPaths } from \"../platform-paths.js\";\n\nexport type PathScope = \"project\" | \"global\";\n\nexport interface PlatformLocations {\n home: string;\n config: string;\n vscodeConfig: string;\n zedConfig: string;\n claudeDesktopConfig: string;\n applications: string[];\n}\n\nexport function getPlatformLocations(): PlatformLocations {\n const home = homedir();\n const platform = process.platform;\n\n if (platform === \"win32\") {\n const appData = process.env[\"APPDATA\"] ?? join(home, \"AppData\", \"Roaming\");\n return {\n home,\n config: appData,\n vscodeConfig: join(appData, \"Code\", \"User\"),\n zedConfig: join(appData, \"Zed\"),\n claudeDesktopConfig: join(appData, \"Claude\"),\n applications: [],\n };\n }\n\n if (platform === \"darwin\") {\n const config = process.env[\"XDG_CONFIG_HOME\"] ?? join(home, \".config\");\n return {\n home,\n config,\n vscodeConfig: join(home, \"Library\", \"Application Support\", \"Code\", \"User\"),\n zedConfig: join(home, \"Library\", \"Application Support\", \"Zed\"),\n claudeDesktopConfig: join(home, \"Library\", \"Application Support\", \"Claude\"),\n applications: [\"/Applications\", join(home, \"Applications\")],\n };\n }\n\n const config = process.env[\"XDG_CONFIG_HOME\"] ?? join(home, \".config\");\n return {\n home,\n config,\n vscodeConfig: join(config, \"Code\", \"User\"),\n zedConfig: join(config, \"zed\"),\n claudeDesktopConfig: join(config, \"Claude\"),\n applications: [],\n };\n}\n\nexport function getAgentsHome(): string {\n return getPlatformPaths().data;\n}\n\nexport function getProjectAgentsDir(projectRoot = process.cwd()): string {\n return join(projectRoot, \".agents\");\n}\n\nexport function resolveProjectPath(relativePath: string, projectDir = process.cwd()): string {\n return join(projectDir, relativePath);\n}\n\nexport function getCanonicalSkillsDir(): string {\n return join(getAgentsHome(), \"skills\");\n}\n\nexport function getLockFilePath(): string {\n return join(getAgentsHome(), \".caamp-lock.json\");\n}\n\n// ── .agents/ Standard Directory Structure ────────────────────────────\n\n/**\n * Get the MCP directory within `.agents/`.\n *\n * @param scope - `\"global\"` for `~/.agents/mcp/`, `\"project\"` for `<project>/.agents/mcp/`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n */\nexport function getAgentsMcpDir(scope: PathScope = \"global\", projectDir?: string): string {\n if (scope === \"global\") return join(getAgentsHome(), \"mcp\");\n return join(projectDir ?? process.cwd(), \".agents\", \"mcp\");\n}\n\n/**\n * Get the MCP servers.json path within `.agents/`.\n *\n * Per the `.agents/` standard (Section 9), this is the canonical MCP\n * server registry that should be checked before legacy per-provider configs.\n *\n * @param scope - `\"global\"` for `~/.agents/mcp/servers.json`, `\"project\"` for `<project>/.agents/mcp/servers.json`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n */\nexport function getAgentsMcpServersPath(scope: PathScope = \"global\", projectDir?: string): string {\n return join(getAgentsMcpDir(scope, projectDir), \"servers.json\");\n}\n\n/**\n * Get the primary AGENTS.md instruction file path within `.agents/`.\n *\n * @param scope - `\"global\"` for `~/.agents/AGENTS.md`, `\"project\"` for `<project>/.agents/AGENTS.md`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n */\nexport function getAgentsInstructFile(scope: PathScope = \"global\", projectDir?: string): string {\n if (scope === \"global\") return join(getAgentsHome(), \"AGENTS.md\");\n return join(projectDir ?? process.cwd(), \".agents\", \"AGENTS.md\");\n}\n\n/**\n * Get the config.toml path within `.agents/`.\n *\n * @param scope - `\"global\"` for `~/.agents/config.toml`, `\"project\"` for `<project>/.agents/config.toml`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n */\nexport function getAgentsConfigPath(scope: PathScope = \"global\", projectDir?: string): string {\n if (scope === \"global\") return join(getAgentsHome(), \"config.toml\");\n return join(projectDir ?? process.cwd(), \".agents\", \"config.toml\");\n}\n\n/**\n * Get the wiki directory within `.agents/`.\n *\n * @param scope - `\"global\"` or `\"project\"`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n */\nexport function getAgentsWikiDir(scope: PathScope = \"global\", projectDir?: string): string {\n if (scope === \"global\") return join(getAgentsHome(), \"wiki\");\n return join(projectDir ?? process.cwd(), \".agents\", \"wiki\");\n}\n\n/**\n * Get the spec directory within `.agents/`.\n *\n * @param scope - `\"global\"` or `\"project\"`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n */\nexport function getAgentsSpecDir(scope: PathScope = \"global\", projectDir?: string): string {\n if (scope === \"global\") return join(getAgentsHome(), \"spec\");\n return join(projectDir ?? process.cwd(), \".agents\", \"spec\");\n}\n\n/**\n * Get the links directory within `.agents/`.\n *\n * @param scope - `\"global\"` or `\"project\"`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n */\nexport function getAgentsLinksDir(scope: PathScope = \"global\", projectDir?: string): string {\n if (scope === \"global\") return join(getAgentsHome(), \"links\");\n return join(projectDir ?? process.cwd(), \".agents\", \"links\");\n}\n\nexport function resolveRegistryTemplatePath(template: string): string {\n const locations = getPlatformLocations();\n return template\n .replace(/\\$HOME/g, locations.home)\n .replace(/\\$CONFIG/g, locations.config)\n .replace(/\\$VSCODE_CONFIG/g, locations.vscodeConfig)\n .replace(/\\$ZED_CONFIG/g, locations.zedConfig)\n .replace(/\\$CLAUDE_DESKTOP_CONFIG/g, locations.claudeDesktopConfig)\n .replace(/\\$AGENTS_HOME/g, getAgentsHome());\n}\n\nexport function resolveProviderConfigPath(\n provider: Provider,\n scope: PathScope,\n projectDir = process.cwd(),\n): string | null {\n if (scope === \"global\") {\n return provider.configPathGlobal;\n }\n if (!provider.configPathProject) {\n return null;\n }\n return resolveProjectPath(provider.configPathProject, projectDir);\n}\n\nexport function resolvePreferredConfigScope(provider: Provider, useGlobalFlag?: boolean): PathScope {\n if (useGlobalFlag) {\n return \"global\";\n }\n return provider.configPathProject ? \"project\" : \"global\";\n}\n\nexport function resolveProviderSkillsDir(\n provider: Provider,\n scope: PathScope,\n projectDir = process.cwd(),\n): string {\n if (scope === \"global\") {\n return provider.pathSkills;\n }\n return resolveProjectPath(provider.pathProjectSkills, projectDir);\n}\n\n/**\n * Get ALL target directories for skill installation based on the provider's\n * skills precedence setting.\n *\n * @param provider - Provider to resolve paths for\n * @param scope - Whether to resolve global or project paths\n * @param projectDir - Project directory for project-scope resolution\n * @returns Array of target directories for symlink creation\n */\nexport function resolveProviderSkillsDirs(\n provider: Provider,\n scope: PathScope,\n projectDir = process.cwd(),\n): string[] {\n const vendorPath = resolveProviderSkillsDir(provider, scope, projectDir);\n const precedence = provider.capabilities?.skills?.precedence ?? \"vendor-only\";\n\n const resolveAgentsPath = (): string | null => {\n if (scope === \"global\") {\n return provider.capabilities?.skills?.agentsGlobalPath ?? null;\n }\n const projectRelative = provider.capabilities?.skills?.agentsProjectPath ?? null;\n return projectRelative ? join(projectDir, projectRelative) : null;\n };\n\n switch (precedence) {\n case \"vendor-only\":\n return [vendorPath];\n\n case \"agents-canonical\": {\n const agentsPath = resolveAgentsPath();\n return agentsPath ? [agentsPath] : [vendorPath];\n }\n\n case \"agents-first\": {\n const agentsPath = resolveAgentsPath();\n return agentsPath ? [agentsPath, vendorPath] : [vendorPath];\n }\n\n case \"agents-supported\": {\n const agentsPath = resolveAgentsPath();\n return agentsPath ? [vendorPath, agentsPath] : [vendorPath];\n }\n\n case \"vendor-global-agents-project\": {\n if (scope === \"global\") {\n return [vendorPath];\n }\n const agentsPath = resolveAgentsPath();\n return agentsPath ? [agentsPath, vendorPath] : [vendorPath];\n }\n\n default:\n return [vendorPath];\n }\n}\n\nexport function resolveProviderProjectPath(provider: Provider, projectDir = process.cwd()): string {\n return resolveProjectPath(provider.pathProject, projectDir);\n}\n\nexport function resolveProvidersRegistryPath(startDir: string): string {\n const candidates = [\n join(startDir, \"..\", \"..\", \"..\", \"providers\", \"registry.json\"),\n join(startDir, \"..\", \"providers\", \"registry.json\"),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n let current = startDir;\n for (let i = 0; i < 8; i += 1) {\n const candidate = join(current, \"providers\", \"registry.json\");\n if (existsSync(candidate)) {\n return candidate;\n }\n current = dirname(current);\n }\n\n throw new Error(`Cannot find providers/registry.json (searched from ${startDir})`);\n}\n\nexport function normalizeSkillSubPath(path: string | undefined): string | undefined {\n if (!path) return undefined;\n const normalized = path.replace(/\\\\/g, \"/\").replace(/^\\/+/, \"\").replace(/\\/SKILL\\.md$/i, \"\").trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\nexport function buildSkillSubPathCandidates(\n marketplacePath: string | undefined,\n parsedPath: string | undefined,\n): (string | undefined)[] {\n const candidates: (string | undefined)[] = [];\n const base = normalizeSkillSubPath(marketplacePath);\n const parsed = normalizeSkillSubPath(parsedPath);\n\n if (base) candidates.push(base);\n if (parsed) candidates.push(parsed);\n\n const knownPrefixes = [\".agents\", \".claude\"];\n for (const value of [base, parsed]) {\n if (!value || !value.startsWith(\"skills/\")) continue;\n for (const prefix of knownPrefixes) {\n candidates.push(`${prefix}/${value}`);\n }\n }\n\n if (candidates.length === 0) {\n candidates.push(undefined);\n }\n\n return Array.from(new Set(candidates));\n}\n","/**\n * Central OS platform path resolution using env-paths.\n *\n * Provides OS-appropriate paths for CAAMP's global directories using\n * XDG conventions on Linux, standard conventions on macOS/Windows.\n * Results are cached for the process lifetime. Env vars take precedence.\n *\n * Platform path defaults:\n * data: ~/.local/share/agents | ~/Library/Application Support/agents | %LOCALAPPDATA%\\agents\\Data\n * config: ~/.config/agents | ~/Library/Preferences/agents | %APPDATA%\\agents\\Config\n * cache: ~/.cache/agents | ~/Library/Caches/agents | %LOCALAPPDATA%\\agents\\Cache\n * log: ~/.local/state/agents | ~/Library/Logs/agents | %LOCALAPPDATA%\\agents\\Log\n * temp: /tmp/<user>/agents | /var/folders/.../agents | %TEMP%\\agents\n *\n * AGENTS_HOME env var overrides the data path for backward compatibility\n * with existing ~/.agents installations.\n */\n\nimport envPaths from 'env-paths';\nimport { arch, homedir, hostname, platform, release } from 'node:os';\nimport { isAbsolute, join, resolve } from 'node:path';\n\nconst APP_NAME = 'agents';\n\n/**\n * Normalize an AGENTS_HOME env var value to an absolute path.\n * Returns undefined when the value is absent, empty, or whitespace-only\n * (callers should fall back to the OS default in that case).\n */\nfunction resolveAgentsHomeOverride(value: string | undefined): string | undefined {\n if (value === undefined) return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n if (trimmed === '~') return homedir();\n if (trimmed.startsWith('~/')) return join(homedir(), trimmed.slice(2));\n if (isAbsolute(trimmed)) return resolve(trimmed);\n return resolve(homedir(), trimmed);\n}\n\nexport interface PlatformPaths {\n /** User data dir. Override with AGENTS_HOME env var. */\n data: string;\n /** OS config dir (XDG_CONFIG_HOME / Library/Preferences / %APPDATA%). */\n config: string;\n /** OS cache dir. */\n cache: string;\n /** OS log dir. */\n log: string;\n /** OS temp dir. */\n temp: string;\n}\n\nexport interface SystemInfo {\n platform: NodeJS.Platform;\n arch: string;\n release: string;\n hostname: string;\n nodeVersion: string;\n paths: PlatformPaths;\n}\n\nlet _paths: PlatformPaths | null = null;\nlet _sysInfo: SystemInfo | null = null;\nlet _lastAgentsHome: string | undefined = undefined;\n\n/**\n * Get OS-appropriate paths for CAAMP's global directories.\n * Cached after first call. AGENTS_HOME env var overrides the data path.\n * Cache auto-invalidates when AGENTS_HOME changes (supports test isolation).\n */\nexport function getPlatformPaths(): PlatformPaths {\n const currentAgentsHome = process.env['AGENTS_HOME'];\n\n // Invalidate if AGENTS_HOME changed since last cache build\n if (_paths && currentAgentsHome !== _lastAgentsHome) {\n _paths = null;\n _sysInfo = null;\n }\n\n if (_paths) return _paths;\n\n const ep = envPaths(APP_NAME, { suffix: '' });\n _lastAgentsHome = currentAgentsHome;\n\n _paths = {\n data: resolveAgentsHomeOverride(currentAgentsHome) ?? ep.data,\n config: ep.config,\n cache: ep.cache,\n log: ep.log,\n temp: ep.temp,\n };\n\n return _paths;\n}\n\n/**\n * Get a cached system information snapshot.\n * Captured once and reused for the process lifetime.\n */\nexport function getSystemInfo(): SystemInfo {\n if (_sysInfo) return _sysInfo;\n\n const paths = getPlatformPaths();\n\n _sysInfo = {\n platform: platform(),\n arch: arch(),\n release: release(),\n hostname: hostname(),\n nodeVersion: process.version,\n paths,\n };\n\n return _sysInfo;\n}\n\n/**\n * Invalidate the path and system info caches.\n * Use in tests after mutating AGENTS_HOME env var.\n * @internal\n */\nexport function _resetPlatformPathsCache(): void {\n _paths = null;\n _sysInfo = null;\n _lastAgentsHome = undefined;\n}\n"],"mappings":";;;;;;;AAOA,SAAS,UAAU,iBAAiB;AACpC,SAAS,cAAAA,mBAAkB;AAC3B,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAC9B,SAAS,aAAa;;;ACoCf,SAAS,sBAAsB,UAAqC;AACzE,QAAM,QAAkB,CAAC;AAEzB,aAAW,OAAO,SAAS,YAAY;AACrC,UAAM,KAAK,GAAG;AAAA,EAChB;AAEA,MAAI,SAAS,WAAW,SAAS,QAAQ,SAAS,GAAG;AACnD,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,KAAK,EAAE;AAAA,IACf;AACA,UAAM,KAAK,GAAG,SAAS,OAAO;AAAA,EAChC;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAiBO,SAAS,sBAAsB,SAAoC;AACxE,QAAM,aAAuB,CAAC;AAC9B,QAAM,eAAyB,CAAC;AAEhC,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAS;AAEd,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,iBAAW,KAAK,OAAO;AAAA,IACzB,OAAO;AACL,mBAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,aAAa,SAAS,IAAI,eAAe;AAAA,EACpD;AACF;AAoBO,SAAS,yBAAyB,SAG9B;AACT,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,gCAAgC;AAC3C,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,qEAAqE;AAChF,QAAM,KAAK,iDAAiD;AAE5D,MAAI,SAAS,eAAe;AAC1B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,mBAAmB,QAAQ,aAAa,EAAE;AACrD,UAAM,KAAK,uCAAuC;AAAA,EACpD;AAEA,MAAI,SAAS,eAAe;AAC1B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,QAAQ,aAAa;AAAA,EAClC;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,sBAAsB,YAA8B;AAClE,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,sBAAsB;AACjC,QAAM,KAAK,EAAE;AAEb,aAAW,QAAQ,YAAY;AAC7B,UAAM,KAAK,OAAO,IAAI,6BAA6B;AAAA,EACrD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAwBO,SAAS,oBAAoB,WAAgD;AAClF,QAAM,SAAS,oBAAI,IAAwB;AAE3C,aAAW,YAAY,WAAW;AAChC,UAAM,WAAW,OAAO,IAAI,SAAS,YAAY,KAAK,CAAC;AACvD,aAAS,KAAK,QAAQ;AACtB,WAAO,IAAI,SAAS,cAAc,QAAQ;AAAA,EAC5C;AAEA,SAAO;AACT;;;ACtLA,SAAS,oBAAoB;AAC7B,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAC9B,SAAS,qBAAqB;;;ACT9B,SAAS,kBAAkB;AAC3B,SAAS,WAAAC,gBAAe;AACxB,SAAS,SAAS,QAAAC,aAAY;;;ACgB9B,OAAO,cAAc;AACrB,SAAS,MAAM,SAAS,UAAU,UAAU,eAAe;AAC3D,SAAS,YAAY,MAAM,eAAe;AAE1C,IAAM,WAAW;AAOjB,SAAS,0BAA0B,OAA+C;AAChF,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,MAAI,YAAY,IAAK,QAAO,QAAQ;AACpC,MAAI,QAAQ,WAAW,IAAI,EAAG,QAAO,KAAK,QAAQ,GAAG,QAAQ,MAAM,CAAC,CAAC;AACrE,MAAI,WAAW,OAAO,EAAG,QAAO,QAAQ,OAAO;AAC/C,SAAO,QAAQ,QAAQ,GAAG,OAAO;AACnC;AAwBA,IAAI,SAA+B;AACnC,IAAI,WAA8B;AAClC,IAAI,kBAAsC;AAOnC,SAAS,mBAAkC;AAChD,QAAM,oBAAoB,QAAQ,IAAI,aAAa;AAGnD,MAAI,UAAU,sBAAsB,iBAAiB;AACnD,aAAS;AACT,eAAW;AAAA,EACb;AAEA,MAAI,OAAQ,QAAO;AAEnB,QAAM,KAAK,SAAS,UAAU,EAAE,QAAQ,GAAG,CAAC;AAC5C,oBAAkB;AAElB,WAAS;AAAA,IACP,MAAM,0BAA0B,iBAAiB,KAAK,GAAG;AAAA,IACzD,QAAQ,GAAG;AAAA,IACX,OAAO,GAAG;AAAA,IACV,KAAK,GAAG;AAAA,IACR,MAAM,GAAG;AAAA,EACX;AAEA,SAAO;AACT;AAMO,SAAS,gBAA4B;AAC1C,MAAI,SAAU,QAAO;AAErB,QAAM,QAAQ,iBAAiB;AAE/B,aAAW;AAAA,IACT,UAAU,SAAS;AAAA,IACnB,MAAM,KAAK;AAAA,IACX,SAAS,QAAQ;AAAA,IACjB,UAAU,SAAS;AAAA,IACnB,aAAa,QAAQ;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,2BAAiC;AAC/C,WAAS;AACT,aAAW;AACX,oBAAkB;AACpB;;;AD5GO,SAAS,uBAA0C;AACxD,QAAM,OAAOC,SAAQ;AACrB,QAAMC,YAAW,QAAQ;AAEzB,MAAIA,cAAa,SAAS;AACxB,UAAM,UAAU,QAAQ,IAAI,SAAS,KAAKC,MAAK,MAAM,WAAW,SAAS;AACzE,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,cAAcA,MAAK,SAAS,QAAQ,MAAM;AAAA,MAC1C,WAAWA,MAAK,SAAS,KAAK;AAAA,MAC9B,qBAAqBA,MAAK,SAAS,QAAQ;AAAA,MAC3C,cAAc,CAAC;AAAA,IACjB;AAAA,EACF;AAEA,MAAID,cAAa,UAAU;AACzB,UAAME,UAAS,QAAQ,IAAI,iBAAiB,KAAKD,MAAK,MAAM,SAAS;AACrE,WAAO;AAAA,MACL;AAAA,MACA,QAAAC;AAAA,MACA,cAAcD,MAAK,MAAM,WAAW,uBAAuB,QAAQ,MAAM;AAAA,MACzE,WAAWA,MAAK,MAAM,WAAW,uBAAuB,KAAK;AAAA,MAC7D,qBAAqBA,MAAK,MAAM,WAAW,uBAAuB,QAAQ;AAAA,MAC1E,cAAc,CAAC,iBAAiBA,MAAK,MAAM,cAAc,CAAC;AAAA,IAC5D;AAAA,EACF;AAEA,QAAM,SAAS,QAAQ,IAAI,iBAAiB,KAAKA,MAAK,MAAM,SAAS;AACrE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,cAAcA,MAAK,QAAQ,QAAQ,MAAM;AAAA,IACzC,WAAWA,MAAK,QAAQ,KAAK;AAAA,IAC7B,qBAAqBA,MAAK,QAAQ,QAAQ;AAAA,IAC1C,cAAc,CAAC;AAAA,EACjB;AACF;AAEO,SAAS,gBAAwB;AACtC,SAAO,iBAAiB,EAAE;AAC5B;AAEO,SAAS,oBAAoB,cAAc,QAAQ,IAAI,GAAW;AACvE,SAAOA,MAAK,aAAa,SAAS;AACpC;AAEO,SAAS,mBAAmB,cAAsB,aAAa,QAAQ,IAAI,GAAW;AAC3F,SAAOA,MAAK,YAAY,YAAY;AACtC;AAEO,SAAS,wBAAgC;AAC9C,SAAOA,MAAK,cAAc,GAAG,QAAQ;AACvC;AAEO,SAAS,kBAA0B;AACxC,SAAOA,MAAK,cAAc,GAAG,kBAAkB;AACjD;AAUO,SAAS,gBAAgB,QAAmB,UAAU,YAA6B;AACxF,MAAI,UAAU,SAAU,QAAOA,MAAK,cAAc,GAAG,KAAK;AAC1D,SAAOA,MAAK,cAAc,QAAQ,IAAI,GAAG,WAAW,KAAK;AAC3D;AAWO,SAAS,wBAAwB,QAAmB,UAAU,YAA6B;AAChG,SAAOA,MAAK,gBAAgB,OAAO,UAAU,GAAG,cAAc;AAChE;AAQO,SAAS,sBAAsB,QAAmB,UAAU,YAA6B;AAC9F,MAAI,UAAU,SAAU,QAAOA,MAAK,cAAc,GAAG,WAAW;AAChE,SAAOA,MAAK,cAAc,QAAQ,IAAI,GAAG,WAAW,WAAW;AACjE;AAQO,SAAS,oBAAoB,QAAmB,UAAU,YAA6B;AAC5F,MAAI,UAAU,SAAU,QAAOA,MAAK,cAAc,GAAG,aAAa;AAClE,SAAOA,MAAK,cAAc,QAAQ,IAAI,GAAG,WAAW,aAAa;AACnE;AAQO,SAAS,iBAAiB,QAAmB,UAAU,YAA6B;AACzF,MAAI,UAAU,SAAU,QAAOA,MAAK,cAAc,GAAG,MAAM;AAC3D,SAAOA,MAAK,cAAc,QAAQ,IAAI,GAAG,WAAW,MAAM;AAC5D;AAQO,SAAS,iBAAiB,QAAmB,UAAU,YAA6B;AACzF,MAAI,UAAU,SAAU,QAAOA,MAAK,cAAc,GAAG,MAAM;AAC3D,SAAOA,MAAK,cAAc,QAAQ,IAAI,GAAG,WAAW,MAAM;AAC5D;AAQO,SAAS,kBAAkB,QAAmB,UAAU,YAA6B;AAC1F,MAAI,UAAU,SAAU,QAAOA,MAAK,cAAc,GAAG,OAAO;AAC5D,SAAOA,MAAK,cAAc,QAAQ,IAAI,GAAG,WAAW,OAAO;AAC7D;AAEO,SAAS,4BAA4B,UAA0B;AACpE,QAAM,YAAY,qBAAqB;AACvC,SAAO,SACJ,QAAQ,WAAW,UAAU,IAAI,EACjC,QAAQ,aAAa,UAAU,MAAM,EACrC,QAAQ,oBAAoB,UAAU,YAAY,EAClD,QAAQ,iBAAiB,UAAU,SAAS,EAC5C,QAAQ,4BAA4B,UAAU,mBAAmB,EACjE,QAAQ,kBAAkB,cAAc,CAAC;AAC9C;AAEO,SAAS,0BACd,UACA,OACA,aAAa,QAAQ,IAAI,GACV;AACf,MAAI,UAAU,UAAU;AACtB,WAAO,SAAS;AAAA,EAClB;AACA,MAAI,CAAC,SAAS,mBAAmB;AAC/B,WAAO;AAAA,EACT;AACA,SAAO,mBAAmB,SAAS,mBAAmB,UAAU;AAClE;AAEO,SAAS,4BAA4B,UAAoB,eAAoC;AAClG,MAAI,eAAe;AACjB,WAAO;AAAA,EACT;AACA,SAAO,SAAS,oBAAoB,YAAY;AAClD;AAEO,SAAS,yBACd,UACA,OACA,aAAa,QAAQ,IAAI,GACjB;AACR,MAAI,UAAU,UAAU;AACtB,WAAO,SAAS;AAAA,EAClB;AACA,SAAO,mBAAmB,SAAS,mBAAmB,UAAU;AAClE;AAWO,SAAS,0BACd,UACA,OACA,aAAa,QAAQ,IAAI,GACf;AACV,QAAM,aAAa,yBAAyB,UAAU,OAAO,UAAU;AACvE,QAAM,aAAa,SAAS,cAAc,QAAQ,cAAc;AAEhE,QAAM,oBAAoB,MAAqB;AAC7C,QAAI,UAAU,UAAU;AACtB,aAAO,SAAS,cAAc,QAAQ,oBAAoB;AAAA,IAC5D;AACA,UAAM,kBAAkB,SAAS,cAAc,QAAQ,qBAAqB;AAC5E,WAAO,kBAAkBA,MAAK,YAAY,eAAe,IAAI;AAAA,EAC/D;AAEA,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,aAAO,CAAC,UAAU;AAAA,IAEpB,KAAK,oBAAoB;AACvB,YAAM,aAAa,kBAAkB;AACrC,aAAO,aAAa,CAAC,UAAU,IAAI,CAAC,UAAU;AAAA,IAChD;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,aAAa,kBAAkB;AACrC,aAAO,aAAa,CAAC,YAAY,UAAU,IAAI,CAAC,UAAU;AAAA,IAC5D;AAAA,IAEA,KAAK,oBAAoB;AACvB,YAAM,aAAa,kBAAkB;AACrC,aAAO,aAAa,CAAC,YAAY,UAAU,IAAI,CAAC,UAAU;AAAA,IAC5D;AAAA,IAEA,KAAK,gCAAgC;AACnC,UAAI,UAAU,UAAU;AACtB,eAAO,CAAC,UAAU;AAAA,MACpB;AACA,YAAM,aAAa,kBAAkB;AACrC,aAAO,aAAa,CAAC,YAAY,UAAU,IAAI,CAAC,UAAU;AAAA,IAC5D;AAAA,IAEA;AACE,aAAO,CAAC,UAAU;AAAA,EACtB;AACF;AAEO,SAAS,2BAA2B,UAAoB,aAAa,QAAQ,IAAI,GAAW;AACjG,SAAO,mBAAmB,SAAS,aAAa,UAAU;AAC5D;AAEO,SAAS,6BAA6B,UAA0B;AACrE,QAAM,aAAa;AAAA,IACjBA,MAAK,UAAU,MAAM,MAAM,MAAM,aAAa,eAAe;AAAA,IAC7DA,MAAK,UAAU,MAAM,aAAa,eAAe;AAAA,EACnD;AAEA,aAAW,aAAa,YAAY;AAClC,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;AAC7B,UAAM,YAAYA,MAAK,SAAS,aAAa,eAAe;AAC5D,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,IACT;AACA,cAAU,QAAQ,OAAO;AAAA,EAC3B;AAEA,QAAM,IAAI,MAAM,sDAAsD,QAAQ,GAAG;AACnF;AAEO,SAAS,sBAAsB,MAA8C;AAClF,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,aAAa,KAAK,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE,EAAE,QAAQ,iBAAiB,EAAE,EAAE,KAAK;AAClG,SAAO,WAAW,SAAS,IAAI,aAAa;AAC9C;AAEO,SAAS,4BACd,iBACA,YACwB;AACxB,QAAM,aAAqC,CAAC;AAC5C,QAAM,OAAO,sBAAsB,eAAe;AAClD,QAAM,SAAS,sBAAsB,UAAU;AAE/C,MAAI,KAAM,YAAW,KAAK,IAAI;AAC9B,MAAI,OAAQ,YAAW,KAAK,MAAM;AAElC,QAAM,gBAAgB,CAAC,WAAW,SAAS;AAC3C,aAAW,SAAS,CAAC,MAAM,MAAM,GAAG;AAClC,QAAI,CAAC,SAAS,CAAC,MAAM,WAAW,SAAS,EAAG;AAC5C,eAAW,UAAU,eAAe;AAClC,iBAAW,KAAK,GAAG,MAAM,IAAI,KAAK,EAAE;AAAA,IACtC;AAAA,EACF;AAEA,MAAI,WAAW,WAAW,GAAG;AAC3B,eAAW,KAAK,MAAS;AAAA,EAC3B;AAEA,SAAO,MAAM,KAAK,IAAI,IAAI,UAAU,CAAC;AACvC;;;ADhSA,IAAM,4BAAsD;AAAA,EAC1D,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,YAAY;AACd;AAEA,IAAM,2BAAoD;AAAA,EACxD,WAAW,CAAC;AAAA,EACZ,gBAAgB;AAAA,EAChB,YAAY;AACd;AAEA,IAAM,2BAAoD;AAAA,EACxD,mBAAmB;AAAA,EACnB,2BAA2B;AAAA,EAC3B,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,gBAAgB;AAClB;AAEA,SAAS,oBAAoB,KAAkD;AAC7E,QAAM,SAAmC,KAAK,SAC1C;AAAA,IACE,kBAAkB,IAAI,OAAO,mBACzB,4BAA4B,IAAI,OAAO,gBAAgB,IACvD;AAAA,IACJ,mBAAmB,IAAI,OAAO;AAAA,IAC9B,YAAY,IAAI,OAAO;AAAA,EACzB,IACA,EAAE,GAAG,0BAA0B;AAEnC,QAAM,QAAiC,KAAK,QACxC;AAAA,IACE,WAAW,IAAI,MAAM;AAAA,IACrB,gBAAgB,IAAI,MAAM,iBACtB,4BAA4B,IAAI,MAAM,cAAc,IACpD;AAAA,IACJ,YAAY,IAAI,MAAM;AAAA,EACxB,IACA,EAAE,GAAG,0BAA0B,WAAW,CAAC,EAAE;AAEjD,QAAM,QAAiC,KAAK,QACxC;AAAA,IACE,mBAAmB,IAAI,MAAM;AAAA,IAC7B,2BAA2B,IAAI,MAAM;AAAA,IACrC,yBAAyB,IAAI,MAAM;AAAA,IACnC,uBAAuB,IAAI,MAAM;AAAA,IACjC,gBAAgB,IAAI,MAAM;AAAA,EAC5B,IACA,EAAE,GAAG,yBAAyB;AAElC,SAAO,EAAE,QAAQ,OAAO,MAAM;AAChC;AAEA,SAAS,mBAA2B;AAClC,QAAM,UAAUE,SAAQ,cAAc,YAAY,GAAG,CAAC;AACtD,SAAO,6BAA6B,OAAO;AAC7C;AAEA,IAAI,YAAqC;AACzC,IAAI,aAA2C;AAC/C,IAAI,YAAwC;AAE5C,SAAS,gBAAgB,KAAiC;AACxD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,UAAU,IAAI;AAAA,IACd,QAAQ,IAAI;AAAA,IACZ,WAAW,IAAI;AAAA,IACf,SAAS,IAAI;AAAA,IACb,YAAY,4BAA4B,IAAI,UAAU;AAAA,IACtD,aAAa,IAAI;AAAA,IACjB,cAAc,IAAI;AAAA,IAClB,WAAW,IAAI;AAAA,IACf,cAAc,IAAI;AAAA,IAClB,kBAAkB,4BAA4B,IAAI,gBAAgB;AAAA,IAClE,mBAAmB,IAAI;AAAA,IACvB,YAAY,4BAA4B,IAAI,UAAU;AAAA,IACtD,mBAAmB,IAAI;AAAA,IACvB,WAAW;AAAA,MACT,SAAS,IAAI,UAAU;AAAA,MACvB,QAAQ,IAAI,UAAU;AAAA,MACtB,aAAa,IAAI,UAAU,aAAa,IAAI,2BAA2B;AAAA,MACvE,WAAW,IAAI,UAAU;AAAA,MACzB,WAAW,IAAI,UAAU;AAAA,IAC3B;AAAA,IACA,qBAAqB,IAAI;AAAA,IACzB,iBAAiB,IAAI;AAAA,IACrB,UAAU,IAAI;AAAA,IACd,QAAQ,IAAI;AAAA,IACZ,uBAAuB,IAAI;AAAA,IAC3B,cAAc,oBAAoB,IAAI,YAAY;AAAA,EACpD;AACF;AAEA,SAAS,eAAiC;AACxC,MAAI,UAAW,QAAO;AAEtB,QAAM,eAAe,iBAAiB;AACtC,QAAM,MAAM,aAAa,cAAc,OAAO;AAC9C,cAAY,KAAK,MAAM,GAAG;AAC1B,SAAO;AACT;AAEA,SAAS,kBAAwB;AAC/B,MAAI,WAAY;AAEhB,QAAM,WAAW,aAAa;AAC9B,eAAa,oBAAI,IAAsB;AACvC,cAAY,oBAAI,IAAoB;AAEpC,aAAW,CAAC,IAAI,GAAG,KAAK,OAAO,QAAQ,SAAS,SAAS,GAAG;AAC1D,UAAM,WAAW,gBAAgB,GAAG;AACpC,eAAW,IAAI,IAAI,QAAQ;AAG3B,eAAW,SAAS,SAAS,SAAS;AACpC,gBAAU,IAAI,OAAO,EAAE;AAAA,IACzB;AAAA,EACF;AACF;AAgBO,SAAS,kBAA8B;AAC5C,kBAAgB;AAChB,MAAI,CAAC,WAAY,QAAO,CAAC;AACzB,SAAO,MAAM,KAAK,WAAW,OAAO,CAAC;AACvC;AAcO,SAAS,YAAY,WAAyC;AACnE,kBAAgB;AAChB,QAAM,WAAW,WAAW,IAAI,SAAS,KAAK;AAC9C,SAAO,YAAY,IAAI,QAAQ;AACjC;AAiBO,SAAS,aAAa,WAA2B;AACtD,kBAAgB;AAChB,SAAO,WAAW,IAAI,SAAS,KAAK;AACtC;AAaO,SAAS,uBAAuB,UAAwC;AAC7E,SAAO,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ;AAChE;AAaO,SAAS,qBAAqB,QAAoC;AACvE,SAAO,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM;AAC5D;AAeO,SAAS,2BAA2B,MAA0B;AACnE,SAAO,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,iBAAiB,IAAI;AAChE;AAaO,SAAS,sBAAgC;AAC9C,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,KAAK,gBAAgB,GAAG;AACjC,UAAM,IAAI,EAAE,YAAY;AAAA,EAC1B;AACA,SAAO,MAAM,KAAK,KAAK;AACzB;AAYO,SAAS,mBAA2B;AACzC,kBAAgB;AAChB,SAAO,YAAY,QAAQ;AAC7B;AAYO,SAAS,qBAA6B;AAC3C,SAAO,aAAa,EAAE;AACxB;AAaO,SAAS,wBAAwB,OAA8B;AACpE,SAAO,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM,UAAU,SAAS,KAAK,CAAC;AACvF;AAgBO,SAAS,oBAAoB,aAAqC;AACvE,QAAM,YAAY,eAAe,YAAY,SAAS,IAClD,YAAY,IAAI,CAAC,OAAO,YAAY,EAAE,CAAC,EAAE,OAAO,CAAC,MAAqB,MAAM,MAAS,IACrF,gBAAgB;AAEpB,MAAI,UAAU,WAAW,EAAG,QAAO,CAAC;AAEpC,QAAM,QAAQ,UAAU,CAAC,EAAG,aAAa,MAAM;AAC/C,SAAO,MAAM;AAAA,IAAO,CAAC,UACnB,UAAU,MAAM,CAAC,MAAM,EAAE,aAAa,MAAM,UAAU,SAAS,KAAK,CAAC;AAAA,EACvE;AACF;AAoBO,SAAS,iBAAiB,UAAoB,SAA0B;AAC7E,QAAM,QAAQ,QAAQ,MAAM,GAAG;AAE/B,MAAI,UAAe,SAAS;AAC5B,aAAW,QAAQ,OAAO;AACxB,QAAI,WAAW,QAAQ,OAAO,YAAY,SAAU,QAAO;AAC3D,cAAU,QAAQ,IAAI;AAAA,EACxB;AACA,MAAI,OAAO,YAAY,UAAW,QAAO;AACzC,MAAI,MAAM,QAAQ,OAAO,EAAG,QAAO,QAAQ,SAAS;AACpD,SAAO,WAAW;AACpB;AAYO,SAAS,2BAAuC;AACrD,SAAO,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM,iBAAiB;AAC/E;AAeO,SAAS,8BACd,MACY;AACZ,SAAO,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM,IAAI,MAAM,IAAI;AAC5E;AAiBO,SAAS,+BAA+B,YAA0C;AACvF,SAAO,gBAAgB,EAAE,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,eAAe,UAAU;AACxF;AAUO,SAAS,wBACd,UACA,OACA,YACwD;AACxD,QAAM,aAAa,yBAAyB,UAAU,OAAO,UAAU;AACvE,QAAM,EAAE,YAAY,kBAAkB,kBAAkB,IAAI,SAAS,aAAa;AAElF,QAAM,oBAAoB,MAAqB;AAC7C,QAAI,UAAU,YAAY,iBAAkB,QAAO;AACnD,QAAI,UAAU,aAAa,qBAAqB,YAAY;AAC1D,aAAOC,MAAK,YAAY,iBAAiB;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,kBAAkB;AACrC,QAAM,aAAa,UAAU,WAAW,WAAW;AAEnD,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,aAAO,CAAC,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,WAAW,CAAC;AAAA,IACnE,KAAK;AACH,aAAO,aAAa,CAAC,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,WAAW,CAAC,IAAI,CAAC;AAAA,IACrF,KAAK;AACH,aAAO;AAAA,QACL,GAAI,aAAa,CAAC,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,WAAW,CAAC,IAAI,CAAC;AAAA,QAChF,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,WAAW;AAAA,MAC1D;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,WAAW;AAAA,QACxD,GAAI,aAAa,CAAC,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,WAAW,CAAC,IAAI,CAAC;AAAA,MAClF;AAAA,IACF,KAAK;AACH,UAAI,UAAU,UAAU;AACtB,eAAO,CAAC,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,SAAS,CAAC;AAAA,MACjE;AACA,aAAO;AAAA,QACL,GAAI,aAAa,CAAC,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,UAAU,CAAC,IAAI,CAAC;AAAA,QAC/E,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,UAAU;AAAA,MACzD;AAAA,IACF;AACE,aAAO,CAAC,EAAE,MAAM,YAAY,QAAQ,UAAU,OAAO,WAAW,CAAC;AAAA,EACrE;AACF;AAOO,SAAS,iBAKb;AACD,SAAO,gBAAgB,EAAE,IAAI,CAAC,MAAM;AAClC,UAAM,EAAE,YAAY,kBAAkB,kBAAkB,IAAI,EAAE,aAAa;AAC3E,UAAM,eAAe,eAAe;AACpC,WAAO;AAAA,MACL,YAAY,EAAE;AAAA,MACd,UAAU,EAAE;AAAA,MACZ;AAAA,MACA,OAAO;AAAA,QACL,QAAQ,eAAe,EAAE,aAAc,oBAAoB;AAAA,QAC3D,SAAS,eAAe,EAAE,oBAAqB,qBAAqB;AAAA,MACtE;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAQO,SAAS,wBAAwB,WAAqD;AAC3F,SAAO,YAAY,SAAS,GAAG;AACjC;AAYO,SAAS,qBAAqB,WAAmB,gBAAiC;AACvF,QAAM,WAAW,YAAY,SAAS;AACtC,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,iBAAiB,UAAU,cAAc;AAClD;;;AFrgBA,IAAM,eAAe;AACrB,IAAM,aAAa;AACnB,IAAM,iBAAiB;AAuBvB,eAAsB,eACpB,UACA,iBAC0B;AAC1B,MAAI,CAACC,YAAW,QAAQ,EAAG,QAAO;AAElC,QAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAEhD,MAAI,CAAC,eAAe,KAAK,OAAO,EAAG,QAAO;AAE1C,MAAI,iBAAiB;AACnB,UAAM,eAAe,aAAa,OAAO;AACzC,QAAI,gBAAgB,aAAa,KAAK,MAAM,gBAAgB,KAAK,GAAG;AAClE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAGA,SAAS,aAAa,SAAgC;AACpD,QAAM,QAAQ,QAAQ,MAAM,cAAc;AAC1C,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAO,MAAM,CAAC,EACX,QAAQ,cAAc,EAAE,EACxB,QAAQ,YAAY,EAAE,EACtB,KAAK;AACV;AAGA,SAAS,WAAW,SAAyB;AAC3C,SAAO,GAAG,YAAY;AAAA,EAAK,OAAO;AAAA,EAAK,UAAU;AACnD;AAwBA,eAAsB,OACpB,UACA,SACqD;AACrD,QAAM,QAAQ,WAAW,OAAO;AAGhC,QAAM,MAAMC,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAElD,MAAI,CAACD,YAAW,QAAQ,GAAG;AAEzB,UAAM,UAAU,UAAU,GAAG,KAAK;AAAA,GAAM,OAAO;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,MAAM,SAAS,UAAU,OAAO;AAEjD,MAAI,eAAe,KAAK,QAAQ,GAAG;AAEjC,UAAM,gBAAgB,aAAa,QAAQ;AAC3C,QAAI,kBAAkB,QAAQ,cAAc,KAAK,MAAM,QAAQ,KAAK,GAAG;AACrE,aAAO;AAAA,IACT;AAGA,UAAME,WAAU,SAAS,QAAQ,gBAAgB,KAAK;AACtD,UAAM,UAAU,UAAUA,UAAS,OAAO;AAC1C,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,GAAG,KAAK;AAAA;AAAA,EAAO,QAAQ;AACvC,QAAM,UAAU,UAAU,SAAS,OAAO;AAC1C,SAAO;AACT;AAeA,eAAsB,gBAAgB,UAAoC;AACxE,MAAI,CAACF,YAAW,QAAQ,EAAG,QAAO;AAElC,QAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,MAAI,CAAC,eAAe,KAAK,OAAO,EAAG,QAAO;AAE1C,QAAM,UAAU,QACb,QAAQ,gBAAgB,EAAE,EAC1B,QAAQ,WAAW,IAAI,EACvB,KAAK;AAER,MAAI,CAAC,SAAS;AAEZ,UAAM,EAAE,GAAG,IAAI,MAAM,OAAO,aAAkB;AAC9C,UAAM,GAAG,QAAQ;AAAA,EACnB,OAAO;AACL,UAAM,UAAU,UAAU,GAAG,OAAO;AAAA,GAAM,OAAO;AAAA,EACnD;AAEA,SAAO;AACT;AAoBA,eAAsB,mBACpB,WACA,YACA,OACA,iBACiC;AACjC,QAAM,UAAkC,CAAC;AACzC,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,YAAY,WAAW;AAChC,UAAM,WAAW,UAAU,WACvBG,MAAK,SAAS,YAAY,SAAS,YAAY,IAC/CA,MAAK,YAAY,SAAS,YAAY;AAG1C,QAAI,QAAQ,IAAI,QAAQ,EAAG;AAC3B,YAAQ,IAAI,QAAQ;AAEpB,UAAM,SAAS,MAAM,eAAe,UAAU,eAAe;AAE7D,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,UAAU,SAAS;AAAA,MACnB;AAAA,MACA,YAAYH,YAAW,QAAQ;AAAA,IACjC,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAqBA,eAAsB,UACpB,WACA,YACA,OACA,SACkE;AAClE,QAAM,UAAU,oBAAI,IAAwD;AAC5E,QAAM,WAAW,oBAAI,IAAY;AAEjC,aAAW,YAAY,WAAW;AAChC,UAAM,WAAW,UAAU,WACvBG,MAAK,SAAS,YAAY,SAAS,YAAY,IAC/CA,MAAK,YAAY,SAAS,YAAY;AAG1C,QAAI,SAAS,IAAI,QAAQ,EAAG;AAC5B,aAAS,IAAI,QAAQ;AAErB,UAAM,SAAS,MAAM,OAAO,UAAU,OAAO;AAC7C,YAAQ,IAAI,UAAU,MAAM;AAAA,EAC9B;AAEA,SAAO;AACT;AA+DA,eAAsB,8BACpB,YACA,YACA,SAC8C;AAC9C,QAAM,WAAW,YAAY,UAAU;AACvC,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,sBAAsB,UAAU,mCAAmC;AAAA,EACrF;AAEA,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,WAAW,UAAU,WACvBA,MAAK,SAAS,YAAY,SAAS,YAAY,IAC/CA,MAAK,YAAY,SAAS,YAAY;AAE1C,QAAM,WAA8B;AAAA,IAClC,YAAY,QAAQ;AAAA,IACpB,SAAS,QAAQ;AAAA,EACnB;AAEA,QAAM,mBAAmB,sBAAsB,QAAQ;AACvD,QAAM,SAAS,MAAM,OAAO,UAAU,gBAAgB;AAEtD,SAAO;AAAA,IACL;AAAA,IACA,cAAc,SAAS;AAAA,IACvB;AAAA,IACA,YAAY,SAAS;AAAA,EACvB;AACF;AAuBA,eAAsB,kCACpB,aACA,YACA,SACgD;AAChD,QAAM,UAAiD,CAAC;AACxD,QAAM,YAAY,oBAAI,IAAY;AAElC,aAAW,cAAc,aAAa;AACpC,UAAM,WAAW,YAAY,UAAU;AACvC,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,sBAAsB,UAAU,mCAAmC;AAAA,IACrF;AAEA,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,WAAW,UAAU,WACvBA,MAAK,SAAS,YAAY,SAAS,YAAY,IAC/CA,MAAK,YAAY,SAAS,YAAY;AAG1C,QAAI,UAAU,IAAI,QAAQ,EAAG;AAC7B,cAAU,IAAI,QAAQ;AAEtB,UAAM,WAA8B;AAAA,MAClC,YAAY,QAAQ;AAAA,MACpB,SAAS,QAAQ;AAAA,IACnB;AAEA,UAAM,mBAAmB,sBAAsB,QAAQ;AACvD,UAAM,SAAS,MAAM,OAAO,UAAU,gBAAgB;AAEtD,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,cAAc,SAAS;AAAA,MACvB;AAAA,MACA,YAAY,SAAS;AAAA,IACvB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":["existsSync","join","dirname","dirname","join","homedir","join","homedir","platform","join","config","dirname","join","existsSync","dirname","updated","join"]}
|
package/dist/cli.d.ts
CHANGED
|
File without changes
|
package/dist/cli.js
CHANGED
|
@@ -6,9 +6,6 @@ import {
|
|
|
6
6
|
applyMcpInstallWithPolicy,
|
|
7
7
|
buildCleoProfile,
|
|
8
8
|
buildServerConfig,
|
|
9
|
-
buildSkillSubPathCandidates,
|
|
10
|
-
buildSkillsMap,
|
|
11
|
-
checkAllInjections,
|
|
12
9
|
checkCommandReachability,
|
|
13
10
|
checkSkillUpdate,
|
|
14
11
|
configureProviderGlobalAndProject,
|
|
@@ -20,21 +17,11 @@ import {
|
|
|
20
17
|
extractVersionTag,
|
|
21
18
|
formatNetworkError,
|
|
22
19
|
formatSkillRecommendations,
|
|
23
|
-
generateInjectionContent,
|
|
24
|
-
getAllProviders,
|
|
25
|
-
getCommonHookEvents,
|
|
26
20
|
getInstalledProviders,
|
|
27
|
-
getProvider,
|
|
28
|
-
getProviderCount,
|
|
29
|
-
getProvidersByHookEvent,
|
|
30
|
-
getProvidersByPriority,
|
|
31
|
-
getRegistryVersion,
|
|
32
21
|
getSkill,
|
|
33
22
|
getSkillDir,
|
|
34
23
|
getTrackedMcpServers,
|
|
35
24
|
getTrackedSkills,
|
|
36
|
-
groupByInstructFile,
|
|
37
|
-
injectAll,
|
|
38
25
|
installBatchWithRollback,
|
|
39
26
|
installMcpServerToAll,
|
|
40
27
|
installSkill,
|
|
@@ -50,7 +37,6 @@ import {
|
|
|
50
37
|
normalizeCleoChannel,
|
|
51
38
|
parseEnvAssignments,
|
|
52
39
|
parseSource,
|
|
53
|
-
providerSupports,
|
|
54
40
|
readConfig,
|
|
55
41
|
readLockFile,
|
|
56
42
|
recommendSkills,
|
|
@@ -64,10 +50,7 @@ import {
|
|
|
64
50
|
resolveChannelFromServerName,
|
|
65
51
|
resolveCleoServerName,
|
|
66
52
|
resolveConfigPath,
|
|
67
|
-
resolvePreferredConfigScope,
|
|
68
53
|
resolveProfile,
|
|
69
|
-
resolveProviderConfigPath,
|
|
70
|
-
resolveProviderSkillsDir,
|
|
71
54
|
scanDirectory,
|
|
72
55
|
scanFile,
|
|
73
56
|
selectProvidersByMinimumPriority,
|
|
@@ -78,7 +61,26 @@ import {
|
|
|
78
61
|
tokenizeCriteriaValue,
|
|
79
62
|
updateInstructionsSingleOperation,
|
|
80
63
|
validateSkill
|
|
81
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-YWO4I7LI.js";
|
|
65
|
+
import {
|
|
66
|
+
buildSkillSubPathCandidates,
|
|
67
|
+
buildSkillsMap,
|
|
68
|
+
checkAllInjections,
|
|
69
|
+
generateInjectionContent,
|
|
70
|
+
getAllProviders,
|
|
71
|
+
getCommonHookEvents,
|
|
72
|
+
getProvider,
|
|
73
|
+
getProviderCount,
|
|
74
|
+
getProvidersByHookEvent,
|
|
75
|
+
getProvidersByPriority,
|
|
76
|
+
getRegistryVersion,
|
|
77
|
+
groupByInstructFile,
|
|
78
|
+
injectAll,
|
|
79
|
+
providerSupports,
|
|
80
|
+
resolvePreferredConfigScope,
|
|
81
|
+
resolveProviderConfigPath,
|
|
82
|
+
resolveProviderSkillsDir
|
|
83
|
+
} from "./chunk-ZVRDBY6L.js";
|
|
82
84
|
|
|
83
85
|
// src/cli.ts
|
|
84
86
|
import { Command } from "commander";
|