@cleocode/caamp 2026.5.29 → 2026.5.34
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/dist/{chunk-HFC3WUME.js → chunk-4W35AEYA.js} +5 -22
- package/dist/chunk-4W35AEYA.js.map +1 -0
- package/dist/{chunk-OCQI7UDH.js → chunk-OCI4RYI5.js} +3 -15
- package/dist/chunk-OCI4RYI5.js.map +1 -0
- package/dist/{chunk-YXWL2IXL.js → chunk-OPUPNLUJ.js} +69 -4
- package/dist/chunk-OPUPNLUJ.js.map +1 -0
- package/dist/{chunk-GDEIR34D.js → chunk-SV33CE5X.js} +2 -2
- package/dist/cli.js +6 -6
- package/dist/{hooks-WZ3MTLQF.js → hooks-5EXBKPII.js} +3 -3
- package/dist/index.d.ts +145 -3
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/{injector-J2C4VCJJ.js → injector-F4EHB3CZ.js} +9 -3
- package/package.json +5 -5
- package/providers/registry.json +28 -0
- package/dist/chunk-HFC3WUME.js.map +0 -1
- package/dist/chunk-OCQI7UDH.js.map +0 -1
- package/dist/chunk-YXWL2IXL.js.map +0 -1
- /package/dist/{chunk-GDEIR34D.js.map → chunk-SV33CE5X.js.map} +0 -0
- /package/dist/{hooks-WZ3MTLQF.js.map → hooks-5EXBKPII.js.map} +0 -0
- /package/dist/{injector-J2C4VCJJ.js.map → injector-F4EHB3CZ.js.map} +0 -0
|
@@ -23,6 +23,7 @@ function _resetPlatformPathsCache() {
|
|
|
23
23
|
import { existsSync } from "fs";
|
|
24
24
|
import { homedir } from "os";
|
|
25
25
|
import { dirname, join } from "path";
|
|
26
|
+
import { getCleoHome } from "@cleocode/paths";
|
|
26
27
|
function getPlatformLocations() {
|
|
27
28
|
const home = homedir();
|
|
28
29
|
const platform = process.platform;
|
|
@@ -101,20 +102,7 @@ function getAgentsLinksDir(scope = "global", projectDir) {
|
|
|
101
102
|
return join(projectDir ?? process.cwd(), ".agents", "links");
|
|
102
103
|
}
|
|
103
104
|
function getCleoHomeForTemplate() {
|
|
104
|
-
|
|
105
|
-
if (envOverride && envOverride.trim().length > 0) {
|
|
106
|
-
return envOverride.trim();
|
|
107
|
-
}
|
|
108
|
-
const home = getPlatformLocations().home;
|
|
109
|
-
if (process.platform === "win32") {
|
|
110
|
-
const localAppData = process.env["LOCALAPPDATA"] ?? join(home, "AppData", "Local");
|
|
111
|
-
return join(localAppData, "cleo", "Data");
|
|
112
|
-
}
|
|
113
|
-
if (process.platform === "darwin") {
|
|
114
|
-
return join(home, "Library", "Application Support", "cleo");
|
|
115
|
-
}
|
|
116
|
-
const xdgData = process.env["XDG_DATA_HOME"] ?? join(home, ".local", "share");
|
|
117
|
-
return join(xdgData, "cleo");
|
|
105
|
+
return getCleoHome();
|
|
118
106
|
}
|
|
119
107
|
function resolveRegistryTemplatePath(template) {
|
|
120
108
|
const locations = getPlatformLocations();
|
|
@@ -247,4 +235,4 @@ export {
|
|
|
247
235
|
resolveProvidersRegistryPath,
|
|
248
236
|
buildSkillSubPathCandidates
|
|
249
237
|
};
|
|
250
|
-
//# sourceMappingURL=chunk-
|
|
238
|
+
//# sourceMappingURL=chunk-OCI4RYI5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/platform-paths.ts","../src/core/paths/standard.ts"],"sourcesContent":["/**\n * CAAMP platform-path façade — bound to `(appName='agents', envVar='AGENTS_HOME')`.\n *\n * The shared platform-paths factory now lives in `@cleocode/paths` (the\n * XDG / env-paths SSoT for the CLEO ecosystem). This module re-exposes the\n * factory + types and pre-binds an `agents`-scoped resolver so existing CAAMP\n * consumers keep working unchanged.\n *\n * Platform path defaults (no `AGENTS_HOME` set):\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 (with tilde expansion).\n *\n * @task T1887\n */\n\nimport {\n createPlatformPathsResolver,\n type PlatformPaths,\n type PlatformPathsResolver,\n type SystemInfo,\n} from '@cleocode/paths';\n\nexport type { PlatformPaths, PlatformPathsResolver, SystemInfo };\nexport { createPlatformPathsResolver };\n\nconst agentsResolver = createPlatformPathsResolver('agents', 'AGENTS_HOME');\n\n/**\n * Get OS-appropriate paths for CAAMP's global directories.\n *\n * Reads fresh on every call (env-paths is microsecond-fast). The\n * `AGENTS_HOME` env var overrides the data path with tilde expansion.\n *\n * @public\n */\nexport function getPlatformPaths(): PlatformPaths {\n return agentsResolver.getPlatformPaths();\n}\n\n/**\n * Get a cached system information snapshot.\n *\n * Captured once and reused for the process lifetime. Includes platform,\n * architecture, hostname, Node version, and resolved paths.\n *\n * @public\n */\nexport function getSystemInfo(): SystemInfo {\n return agentsResolver.getSystemInfo();\n}\n\n/**\n * Invalidate the cached system info snapshot. Use in tests after\n * mutating `AGENTS_HOME`.\n *\n * @internal\n */\nexport function _resetPlatformPathsCache(): void {\n agentsResolver.resetCache();\n}\n","import { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { getCleoHome } from '@cleocode/paths';\nimport type { Provider } from '../../types.js';\nimport { getPlatformPaths } from '../platform-paths.js';\n\n/**\n * Scope for path resolution, either global (user home) or project-local.\n *\n * @remarks\n * Global scope resolves paths under the user's home directory (e.g., `~/.agents/`).\n * Project scope resolves paths relative to the project root (e.g., `<project>/.agents/`).\n *\n * @public\n */\nexport type PathScope = 'project' | 'global';\n\n/**\n * Platform-specific directory locations for agent configuration.\n *\n * @remarks\n * Provides resolved paths for the current operating system, accounting for\n * platform differences in config directory locations (XDG on Linux, Library on macOS,\n * AppData on Windows).\n *\n * @public\n */\nexport interface PlatformLocations {\n /** The user's home directory path. */\n home: string;\n /** The platform-specific configuration directory. */\n config: string;\n /** The VS Code user settings directory. */\n vscodeConfig: string;\n /** The Zed editor configuration directory. */\n zedConfig: string;\n /** The Claude Desktop application configuration directory. */\n claudeDesktopConfig: string;\n /** List of application directories (macOS only). */\n applications: string[];\n}\n\n/**\n * Resolves platform-specific directory locations for the current OS.\n *\n * @remarks\n * Detects the current platform and returns appropriate paths for configuration,\n * editor settings, and application directories. Uses `XDG_CONFIG_HOME` on Linux\n * and macOS when available, falls back to conventional defaults. On Windows,\n * uses `APPDATA` or defaults to `~/AppData/Roaming`.\n *\n * @returns Platform-specific directory locations\n *\n * @example\n * ```typescript\n * const locations = getPlatformLocations();\n * console.log(locations.config); // e.g., \"/home/user/.config\"\n * ```\n *\n * @public\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\n/**\n * Returns the global agents home directory path.\n *\n * @remarks\n * Delegates to the platform paths module to resolve the data directory\n * for the current operating system. This is the root for global agent\n * configuration such as canonical skills and lock files.\n *\n * @returns The absolute path to the global agents home directory\n *\n * @example\n * ```typescript\n * const home = getAgentsHome();\n * // e.g., \"/home/user/.local/share/caamp\"\n * ```\n *\n * @public\n */\nexport function getAgentsHome(): string {\n return getPlatformPaths().data;\n}\n\n/**\n * Returns the project-local `.agents` directory path.\n *\n * @remarks\n * Joins the project root with `.agents` to produce the conventional\n * project-scoped agent configuration directory.\n *\n * @param projectRoot - The project root directory, defaults to `process.cwd()`\n * @returns The absolute path to the project's `.agents` directory\n *\n * @example\n * ```typescript\n * const dir = getProjectAgentsDir(\"/home/user/my-project\");\n * // returns \"/home/user/my-project/.agents\"\n * ```\n *\n * @public\n */\nexport function getProjectAgentsDir(projectRoot = process.cwd()): string {\n return join(projectRoot, '.agents');\n}\n\n/**\n * Resolves a relative path against a project directory.\n *\n * @remarks\n * A simple path join utility that combines the project directory with\n * the given relative path to produce an absolute path.\n *\n * @param relativePath - The relative path to resolve\n * @param projectDir - The project root directory, defaults to `process.cwd()`\n * @returns The resolved absolute path\n *\n * @example\n * ```typescript\n * const path = resolveProjectPath(\".agents/config.toml\", \"/home/user/project\");\n * // returns \"/home/user/project/.agents/config.toml\"\n * ```\n *\n * @public\n */\nexport function resolveProjectPath(relativePath: string, projectDir = process.cwd()): string {\n return join(projectDir, relativePath);\n}\n\n/**\n * Returns the canonical skills storage directory path.\n *\n * @remarks\n * Skills are stored once in this canonical directory and symlinked into\n * provider-specific locations. This is the single source of truth for\n * installed skill files.\n *\n * @returns The absolute path to the canonical skills directory\n *\n * @example\n * ```typescript\n * const dir = getCanonicalSkillsDir();\n * // e.g., \"/home/user/.local/share/caamp/skills\"\n * ```\n *\n * @public\n */\nexport function getCanonicalSkillsDir(): string {\n return join(getAgentsHome(), 'skills');\n}\n\n/**\n * Returns the path to the CAAMP lock file.\n *\n * @remarks\n * The lock file tracks installed skills and their versions to enable\n * deterministic reinstallation and conflict detection.\n *\n * @returns The absolute path to the `.caamp-lock.json` file\n *\n * @example\n * ```typescript\n * const lockPath = getLockFilePath();\n * // e.g., \"/home/user/.local/share/caamp/.caamp-lock.json\"\n * ```\n *\n * @public\n */\nexport function getLockFilePath(): string {\n return join(getAgentsHome(), '.caamp-lock.json');\n}\n\n// ── .agents/ Standard Directory Structure ────────────────────────────\n\n/**\n * Gets the MCP directory within the `.agents/` standard structure.\n *\n * @remarks\n * Resolves the MCP configuration directory based on scope. Global scope\n * points to `~/.agents/mcp/`, while project scope points to\n * `<project>/.agents/mcp/`.\n *\n * @param scope - `\"global\"` for `~/.agents/mcp/`, `\"project\"` for `<project>/.agents/mcp/`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n * @returns The absolute path to the MCP directory\n *\n * @example\n * ```typescript\n * const globalMcp = getAgentsMcpDir(\"global\");\n * const projectMcp = getAgentsMcpDir(\"project\", \"/home/user/project\");\n * ```\n *\n * @public\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 * Gets the MCP servers.json path within the `.agents/` standard structure.\n *\n * @remarks\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 * @returns The absolute path to the `servers.json` file\n *\n * @example\n * ```typescript\n * const serversPath = getAgentsMcpServersPath(\"global\");\n * // e.g., \"/home/user/.agents/mcp/servers.json\"\n * ```\n *\n * @public\n */\nexport function getAgentsMcpServersPath(scope: PathScope = 'global', projectDir?: string): string {\n return join(getAgentsMcpDir(scope, projectDir), 'servers.json');\n}\n\n/**\n * Gets the primary AGENTS.md instruction file path within `.agents/`.\n *\n * @remarks\n * Returns the path to the AGENTS.md file for the given scope. This is the\n * standard instruction file that agents read for project or global guidance.\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 * @returns The absolute path to the AGENTS.md file\n *\n * @example\n * ```typescript\n * const agentsFile = getAgentsInstructFile(\"project\", \"/home/user/project\");\n * // returns \"/home/user/project/.agents/AGENTS.md\"\n * ```\n *\n * @public\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 * Gets the config.toml path within the `.agents/` standard structure.\n *\n * @remarks\n * Returns the path to the TOML configuration file for agent settings.\n * Global scope points to `~/.agents/config.toml`, project scope points\n * to `<project>/.agents/config.toml`.\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 * @returns The absolute path to the config.toml file\n *\n * @example\n * ```typescript\n * const configPath = getAgentsConfigPath(\"global\");\n * // e.g., \"/home/user/.agents/config.toml\"\n * ```\n *\n * @public\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 * Gets the wiki directory within the `.agents/` standard structure.\n *\n * @remarks\n * The wiki directory stores markdown documentation files that agents\n * can reference for project or global knowledge.\n *\n * @param scope - `\"global\"` or `\"project\"`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n * @returns The absolute path to the wiki directory\n *\n * @example\n * ```typescript\n * const wikiDir = getAgentsWikiDir(\"project\", \"/home/user/project\");\n * // returns \"/home/user/project/.agents/wiki\"\n * ```\n *\n * @public\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 * Gets the spec directory within the `.agents/` standard structure.\n *\n * @remarks\n * The spec directory stores specification files used by agents for\n * project architecture and design reference.\n *\n * @param scope - `\"global\"` or `\"project\"`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n * @returns The absolute path to the spec directory\n *\n * @example\n * ```typescript\n * const specDir = getAgentsSpecDir(\"global\");\n * // e.g., \"/home/user/.agents/spec\"\n * ```\n *\n * @public\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 * Gets the links directory within the `.agents/` standard structure.\n *\n * @remarks\n * The links directory stores symlinks or references to external resources\n * that agents can follow for additional context.\n *\n * @param scope - `\"global\"` or `\"project\"`\n * @param projectDir - Project root (defaults to `process.cwd()`)\n * @returns The absolute path to the links directory\n *\n * @example\n * ```typescript\n * const linksDir = getAgentsLinksDir(\"project\", \"/home/user/project\");\n * // returns \"/home/user/project/.agents/links\"\n * ```\n *\n * @public\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\n/**\n * Resolve the CLEO home directory for template path expansion.\n *\n * @remarks\n * Delegates to {@link getCleoHome} from `@cleocode/paths`, which is the\n * canonical SSoT for XDG / platform-specific CLEO home resolution.\n *\n * @internal\n */\nfunction getCleoHomeForTemplate(): string {\n return getCleoHome();\n}\n\n/**\n * Resolves a registry template path by substituting platform variables.\n *\n * @remarks\n * Replaces template variables like `$HOME`, `$CONFIG`, `$VSCODE_CONFIG`,\n * `$ZED_CONFIG`, `$CLAUDE_DESKTOP_CONFIG`, `$AGENTS_HOME`, and `$CLEO_HOME`\n * with their actual platform-specific values. Used to resolve paths from\n * the provider registry JSON.\n *\n * @param template - The template string containing `$VARIABLE` placeholders\n * @returns The resolved absolute path with all variables expanded\n *\n * @example\n * ```typescript\n * const path = resolveRegistryTemplatePath(\"$HOME/.config/claude/settings.json\");\n * // e.g., \"/home/user/.config/claude/settings.json\"\n * ```\n *\n * @public\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 .replace(/\\$CLEO_HOME/g, getCleoHomeForTemplate());\n}\n\n/**\n * Resolves the configuration file path for a provider at the given scope.\n *\n * @remarks\n * For global scope, returns the provider's `configPathGlobal` directly.\n * For project scope, joins the project directory with the provider's\n * `configPathProject`. Returns null if the provider has no project-scoped\n * config path defined.\n *\n * @param provider - The provider whose config path to resolve\n * @param scope - Whether to resolve global or project config path\n * @param projectDir - The project root directory, defaults to `process.cwd()`\n * @returns The resolved config file path, or null if unavailable for the given scope\n *\n * @example\n * ```typescript\n * const configPath = resolveProviderConfigPath(provider, \"project\", \"/home/user/project\");\n * if (configPath) {\n * console.log(\"Config at:\", configPath);\n * }\n * ```\n *\n * @public\n */\nexport function resolveProviderConfigPath(\n provider: Provider,\n scope: PathScope,\n projectDir = process.cwd(),\n): string | null {\n const mcp = provider.capabilities.mcp;\n if (!mcp) {\n return null;\n }\n if (scope === 'global') {\n return mcp.configPathGlobal;\n }\n if (!mcp.configPathProject) {\n return null;\n }\n return resolveProjectPath(mcp.configPathProject, projectDir);\n}\n\n/**\n * Determines the preferred configuration scope for a provider.\n *\n * @remarks\n * If the global flag is explicitly set, always returns `\"global\"`. Otherwise,\n * returns `\"project\"` if the provider supports project-scoped configuration,\n * or `\"global\"` as a fallback.\n *\n * @param provider - The provider to determine scope for\n * @param useGlobalFlag - Optional flag to force global scope\n * @returns The preferred path scope for configuration\n *\n * @example\n * ```typescript\n * const scope = resolvePreferredConfigScope(provider, false);\n * // returns \"project\" if provider has configPathProject, otherwise \"global\"\n * ```\n *\n * @public\n */\nexport function resolvePreferredConfigScope(\n provider: Provider,\n useGlobalFlag?: boolean,\n): PathScope {\n if (useGlobalFlag) {\n return 'global';\n }\n return provider.capabilities.mcp?.configPathProject ? 'project' : 'global';\n}\n\n/**\n * Resolves the skills directory path for a provider at the given scope.\n *\n * @remarks\n * For global scope, returns the provider's `pathSkills` directly.\n * For project scope, joins the project directory with the provider's\n * `pathProjectSkills` relative path.\n *\n * @param provider - The provider whose skills directory to resolve\n * @param scope - Whether to resolve global or project skills path\n * @param projectDir - The project root directory, defaults to `process.cwd()`\n * @returns The resolved skills directory path\n *\n * @example\n * ```typescript\n * const skillsDir = resolveProviderSkillsDir(provider, \"global\");\n * // e.g., \"/home/user/.claude/skills\"\n * ```\n *\n * @public\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 * Gets all target directories for skill installation based on provider precedence.\n *\n * @remarks\n * Resolves one or more skill directories based on the provider's skills\n * precedence setting. The precedence determines whether vendor-only, agents-canonical,\n * agents-first, agents-supported, or vendor-global-agents-project strategies are used.\n * Falls back to the vendor path when the agents path is not configured.\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 *\n * @example\n * ```typescript\n * const dirs = resolveProviderSkillsDirs(provider, \"project\", \"/home/user/project\");\n * for (const dir of dirs) {\n * console.log(\"Install skill to:\", dir);\n * }\n * ```\n *\n * @public\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\n/**\n * Resolves a provider's project-level path against a project directory.\n *\n * @remarks\n * Joins the project directory with the provider's `pathProject` relative path\n * to produce an absolute path for project-scoped provider configuration.\n *\n * @param provider - The provider whose project path to resolve\n * @param projectDir - The project root directory, defaults to `process.cwd()`\n * @returns The resolved absolute path for the provider's project directory\n *\n * @example\n * ```typescript\n * const projectPath = resolveProviderProjectPath(provider, \"/home/user/project\");\n * // e.g., \"/home/user/project/.claude\"\n * ```\n *\n * @public\n */\nexport function resolveProviderProjectPath(provider: Provider, projectDir = process.cwd()): string {\n return resolveProjectPath(provider.pathProject, projectDir);\n}\n\n/**\n * Locates the providers registry.json file by searching up from a start directory.\n *\n * @remarks\n * First checks common relative locations (3 levels up and 1 level up),\n * then walks up to 8 parent directories looking for `providers/registry.json`.\n * Throws if the registry file cannot be found.\n *\n * @param startDir - The directory to start searching from\n * @returns The absolute path to the found `providers/registry.json` file\n * @throws Error if `providers/registry.json` cannot be found within 8 parent levels\n *\n * @example\n * ```typescript\n * const registryPath = resolveProvidersRegistryPath(__dirname);\n * // e.g., \"/home/user/caamp/providers/registry.json\"\n * ```\n *\n * @public\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\n/**\n * Normalizes a skill sub-path by cleaning separators and removing SKILL.md suffix.\n *\n * @remarks\n * Converts backslashes to forward slashes, strips leading slashes and\n * trailing `/SKILL.md`, and trims whitespace. Returns undefined for\n * empty or falsy inputs.\n *\n * @param path - The raw skill sub-path to normalize\n * @returns The normalized path, or undefined if the input is empty or falsy\n *\n * @example\n * ```typescript\n * const normalized = normalizeSkillSubPath(\"skills/my-skill/SKILL.md\");\n * // returns \"skills/my-skill\"\n * ```\n *\n * @public\n */\nexport function normalizeSkillSubPath(path: string | undefined): string | undefined {\n if (!path) return undefined;\n const normalized = path\n .replace(/\\\\/g, '/')\n .replace(/^\\/+/, '')\n .replace(/\\/SKILL\\.md$/i, '')\n .trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\n/**\n * Builds a list of candidate sub-paths for skill file resolution.\n *\n * @remarks\n * Normalizes both the marketplace and parsed paths, then generates additional\n * candidates by prepending known prefixes (`.agents`, `.claude`) to paths\n * starting with `skills/`. Returns a deduplicated list of candidates, with\n * an undefined entry as fallback if no candidates are found.\n *\n * @param marketplacePath - The sub-path from the marketplace listing\n * @param parsedPath - The sub-path parsed from the source URL\n * @returns A deduplicated array of candidate sub-paths\n *\n * @example\n * ```typescript\n * const candidates = buildSkillSubPathCandidates(\"skills/my-skill\", undefined);\n * // returns [\"skills/my-skill\", \".agents/skills/my-skill\", \".claude/skills/my-skill\"]\n * ```\n *\n * @public\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?.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"],"mappings":"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","names":["config"]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
resolveProviderSkillsDir,
|
|
3
3
|
resolveProvidersRegistryPath,
|
|
4
4
|
resolveRegistryTemplatePath
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OCI4RYI5.js";
|
|
6
6
|
|
|
7
7
|
// src/core/instructions/injector.ts
|
|
8
8
|
import { existsSync } from "fs";
|
|
@@ -107,6 +107,7 @@ function resolveProvider(raw) {
|
|
|
107
107
|
pathGlobal: resolveRegistryTemplatePath(raw.pathGlobal),
|
|
108
108
|
pathProject: raw.pathProject,
|
|
109
109
|
instructFile: raw.instructFile,
|
|
110
|
+
instructionReferences: raw.instructionReferences ? [...raw.instructionReferences] : [],
|
|
110
111
|
pathSkills: resolveRegistryTemplatePath(raw.pathSkills),
|
|
111
112
|
pathProjectSkills: raw.pathProjectSkills,
|
|
112
113
|
detection: {
|
|
@@ -210,6 +211,10 @@ function getSpawnCapableProviders() {
|
|
|
210
211
|
function getProvidersBySpawnCapability(flag) {
|
|
211
212
|
return getAllProviders().filter((p) => p.capabilities.spawn[flag] === true);
|
|
212
213
|
}
|
|
214
|
+
function getProviderInstructionReferences(idOrAlias) {
|
|
215
|
+
const provider = getProvider(idOrAlias);
|
|
216
|
+
return provider?.instructionReferences ? [...provider.instructionReferences] : [];
|
|
217
|
+
}
|
|
213
218
|
function getProvidersBySkillsPrecedence(precedence) {
|
|
214
219
|
return getAllProviders().filter((p) => p.capabilities.skills.precedence === precedence);
|
|
215
220
|
}
|
|
@@ -349,6 +354,60 @@ var MARKER_START = "<!-- CAAMP:START -->";
|
|
|
349
354
|
var MARKER_END = "<!-- CAAMP:END -->";
|
|
350
355
|
var MARKER_PATTERN = /<!-- CAAMP:START -->[\s\S]*?<!-- CAAMP:END -->/g;
|
|
351
356
|
var MARKER_PATTERN_SINGLE = /<!-- CAAMP:START -->[\s\S]*?<!-- CAAMP:END -->/;
|
|
357
|
+
function parseCaampBlocks(fileContent) {
|
|
358
|
+
const blocks = [];
|
|
359
|
+
const pattern = /<!-- CAAMP:START -->([\s\S]*?)<!-- CAAMP:END -->/g;
|
|
360
|
+
for (let match = pattern.exec(fileContent); match !== null; match = pattern.exec(fileContent)) {
|
|
361
|
+
const raw = match[0];
|
|
362
|
+
const innerContent = match[1] ?? "";
|
|
363
|
+
blocks.push({
|
|
364
|
+
raw,
|
|
365
|
+
content: innerContent.trim(),
|
|
366
|
+
startIndex: match.index,
|
|
367
|
+
endIndex: match.index + raw.length
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
return blocks;
|
|
371
|
+
}
|
|
372
|
+
async function dedupeFile(filePath) {
|
|
373
|
+
if (!existsSync(filePath)) {
|
|
374
|
+
return { filePath, removed: 0, kept: 0, modified: false };
|
|
375
|
+
}
|
|
376
|
+
const fileContent = await readFile(filePath, "utf-8");
|
|
377
|
+
const blocks = parseCaampBlocks(fileContent);
|
|
378
|
+
if (blocks.length === 0) {
|
|
379
|
+
return { filePath, removed: 0, kept: 0, modified: false };
|
|
380
|
+
}
|
|
381
|
+
const lastByContent = /* @__PURE__ */ new Map();
|
|
382
|
+
for (const block of blocks) {
|
|
383
|
+
lastByContent.set(block.content, block);
|
|
384
|
+
}
|
|
385
|
+
const keepSet = new Set(lastByContent.values());
|
|
386
|
+
const removed = blocks.length - keepSet.size;
|
|
387
|
+
if (removed === 0) {
|
|
388
|
+
return { filePath, removed: 0, kept: blocks.length, modified: false };
|
|
389
|
+
}
|
|
390
|
+
let result = "";
|
|
391
|
+
let cursor = 0;
|
|
392
|
+
for (const block of blocks) {
|
|
393
|
+
result += fileContent.slice(cursor, block.startIndex);
|
|
394
|
+
cursor = block.endIndex;
|
|
395
|
+
if (keepSet.has(block)) {
|
|
396
|
+
result += block.raw;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
result += fileContent.slice(cursor);
|
|
400
|
+
result = result.replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
|
|
401
|
+
await writeFile(filePath, result, "utf-8");
|
|
402
|
+
return { filePath, removed, kept: keepSet.size, modified: true };
|
|
403
|
+
}
|
|
404
|
+
async function dedupeFiles(filePaths) {
|
|
405
|
+
const results = [];
|
|
406
|
+
for (const filePath of filePaths) {
|
|
407
|
+
results.push(await dedupeFile(filePath));
|
|
408
|
+
}
|
|
409
|
+
return results;
|
|
410
|
+
}
|
|
352
411
|
async function checkInjection(filePath, expectedContent) {
|
|
353
412
|
if (!existsSync(filePath)) return "missing";
|
|
354
413
|
const content = await readFile(filePath, "utf-8");
|
|
@@ -456,8 +515,9 @@ async function ensureProviderInstructionFile(providerId, projectDir, options) {
|
|
|
456
515
|
}
|
|
457
516
|
const scope = options.scope ?? "project";
|
|
458
517
|
const filePath = scope === "global" ? join2(provider.pathGlobal, provider.instructFile) : join2(projectDir, provider.instructFile);
|
|
518
|
+
const references = options.references ?? getProviderInstructionReferences(providerId);
|
|
459
519
|
const template = {
|
|
460
|
-
references
|
|
520
|
+
references,
|
|
461
521
|
content: options.content
|
|
462
522
|
};
|
|
463
523
|
const injectionContent = buildInjectionContent(template);
|
|
@@ -481,8 +541,9 @@ async function ensureAllProviderInstructionFiles(providerIds, projectDir, option
|
|
|
481
541
|
const filePath = scope === "global" ? join2(provider.pathGlobal, provider.instructFile) : join2(projectDir, provider.instructFile);
|
|
482
542
|
if (processed.has(filePath)) continue;
|
|
483
543
|
processed.add(filePath);
|
|
544
|
+
const references = options.references ?? getProviderInstructionReferences(providerId);
|
|
484
545
|
const template = {
|
|
485
|
-
references
|
|
546
|
+
references,
|
|
486
547
|
content: options.content
|
|
487
548
|
};
|
|
488
549
|
const injectionContent = buildInjectionContent(template);
|
|
@@ -562,6 +623,7 @@ export {
|
|
|
562
623
|
providerSupports,
|
|
563
624
|
getSpawnCapableProviders,
|
|
564
625
|
getProvidersBySpawnCapability,
|
|
626
|
+
getProviderInstructionReferences,
|
|
565
627
|
getProvidersBySkillsPrecedence,
|
|
566
628
|
getEffectiveSkillsPaths,
|
|
567
629
|
buildSkillsMap,
|
|
@@ -572,6 +634,9 @@ export {
|
|
|
572
634
|
generateInjectionContent,
|
|
573
635
|
generateSkillsSection,
|
|
574
636
|
groupByInstructFile,
|
|
637
|
+
parseCaampBlocks,
|
|
638
|
+
dedupeFile,
|
|
639
|
+
dedupeFiles,
|
|
575
640
|
checkInjection,
|
|
576
641
|
inject,
|
|
577
642
|
removeInjection,
|
|
@@ -582,4 +647,4 @@ export {
|
|
|
582
647
|
getProviderAgentFolder,
|
|
583
648
|
writeAgentFileToAllProviders
|
|
584
649
|
};
|
|
585
|
-
//# sourceMappingURL=chunk-
|
|
650
|
+
//# sourceMappingURL=chunk-OPUPNLUJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/instructions/injector.ts","../src/core/registry/providers.ts","../src/core/instructions/templates.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) and agent-definition files\n * (cleo-subagent.md, seed agent profiles) per provider's native folder.\n */\n\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport type { InjectionCheckResult, InjectionStatus, Provider } from '../../types.js';\nimport { getProvider, getProviderInstructionReferences } from '../registry/providers.js';\nimport { buildInjectionContent, type InjectionTemplate } from './templates.js';\n\nconst MARKER_START = '<!-- CAAMP:START -->';\nconst MARKER_END = '<!-- CAAMP:END -->';\nconst MARKER_PATTERN = /<!-- CAAMP:START -->[\\s\\S]*?<!-- CAAMP:END -->/g;\nconst MARKER_PATTERN_SINGLE = /<!-- CAAMP:START -->[\\s\\S]*?<!-- CAAMP:END -->/;\n\n// ── Block parsing ──────────────────────────────────────────────────────────\n\n/**\n * A single parsed CAAMP block extracted from a file.\n *\n * @public\n */\nexport interface CaampBlock {\n /** Raw text of the entire block including markers. */\n raw: string;\n /** Trimmed content between the markers. */\n content: string;\n /** Zero-based character offset of the start of the block in the file. */\n startIndex: number;\n /** Zero-based character offset immediately after the block in the file. */\n endIndex: number;\n}\n\n/**\n * Parse all CAAMP blocks from a file's content string.\n *\n * Returns an array of {@link CaampBlock} objects in order of appearance.\n * Blocks with malformed markers (START without matching END) are silently\n * skipped to avoid crashing on corrupted files.\n *\n * @param fileContent - Raw text content of the file\n * @returns Array of parsed CAAMP blocks\n *\n * @public\n */\nexport function parseCaampBlocks(fileContent: string): CaampBlock[] {\n const blocks: CaampBlock[] = [];\n const pattern = /<!-- CAAMP:START -->([\\s\\S]*?)<!-- CAAMP:END -->/g;\n\n for (let match = pattern.exec(fileContent); match !== null; match = pattern.exec(fileContent)) {\n const raw = match[0];\n const innerContent = match[1] ?? '';\n blocks.push({\n raw,\n content: innerContent.trim(),\n startIndex: match.index,\n endIndex: match.index + raw.length,\n });\n }\n\n return blocks;\n}\n\n/**\n * Result of deduplicating CAAMP blocks in a single file.\n *\n * @public\n */\nexport interface DedupeResult {\n /** Absolute path to the file that was processed. */\n filePath: string;\n /** Number of duplicate blocks removed. */\n removed: number;\n /** Number of unique blocks kept. */\n kept: number;\n /** `true` if the file was modified on disk; `false` if it was already clean. */\n modified: boolean;\n}\n\n/**\n * Deduplicate CAAMP blocks in a file by content.\n *\n * Groups all `<!-- CAAMP:START -->...<!-- CAAMP:END -->` blocks by their\n * trimmed inner content. For each group that has more than one block, keeps\n * only the **last** occurrence (most recently written) and removes the earlier\n * duplicates. Blocks with distinct contents are preserved in their original\n * relative order.\n *\n * Idempotent: calling this on an already-clean file returns `modified: false`\n * and makes no filesystem writes.\n *\n * @param filePath - Absolute path to the file to deduplicate\n * @returns Dedup summary\n *\n * @remarks\n * \"Last occurrence wins\" matches the behaviour of CLEO's injection chain,\n * which writes the canonical `@~/.local/share/cleo/…` path on every session.\n * Stale temp-path blocks from earlier sessions therefore have earlier indices\n * and are removed, leaving the canonical block.\n *\n * @example\n * ```typescript\n * const result = await dedupeFile(\"/home/user/.agents/AGENTS.md\");\n * console.log(`Removed ${result.removed} duplicate(s)`);\n * ```\n *\n * @public\n */\nexport async function dedupeFile(filePath: string): Promise<DedupeResult> {\n if (!existsSync(filePath)) {\n return { filePath, removed: 0, kept: 0, modified: false };\n }\n\n const fileContent = await readFile(filePath, 'utf-8');\n const blocks = parseCaampBlocks(fileContent);\n\n if (blocks.length === 0) {\n return { filePath, removed: 0, kept: 0, modified: false };\n }\n\n // Group by trimmed content — last occurrence wins\n const lastByContent = new Map<string, CaampBlock>();\n for (const block of blocks) {\n lastByContent.set(block.content, block);\n }\n\n const keepSet = new Set<CaampBlock>(lastByContent.values());\n const removed = blocks.length - keepSet.size;\n\n if (removed === 0) {\n // Already clean\n return { filePath, removed: 0, kept: blocks.length, modified: false };\n }\n\n // Rebuild file content: walk through original text, emit blocks that are\n // in keepSet and skip duplicates. Non-block text between blocks is preserved.\n let result = '';\n let cursor = 0;\n\n for (const block of blocks) {\n // Emit any non-block text before this block\n result += fileContent.slice(cursor, block.startIndex);\n cursor = block.endIndex;\n\n if (keepSet.has(block)) {\n result += block.raw;\n }\n // Removed duplicates contribute nothing — surrounding whitespace is\n // normalized by the final collapse step below.\n }\n\n // Emit any trailing text after the last block\n result += fileContent.slice(cursor);\n\n // Normalize: collapse 3+ consecutive newlines → 2, trim trailing whitespace\n result = result.replace(/\\n{3,}/g, '\\n\\n').trimEnd() + '\\n';\n\n await writeFile(filePath, result, 'utf-8');\n\n return { filePath, removed, kept: keepSet.size, modified: true };\n}\n\n/**\n * Deduplicate CAAMP blocks across multiple files.\n *\n * Runs {@link dedupeFile} on each path in order and collects results.\n * Files that do not exist are skipped silently (their result has `removed: 0`).\n *\n * @param filePaths - Array of absolute file paths to process\n * @returns Array of results, one per input path\n *\n * @example\n * ```typescript\n * const results = await dedupeFiles([\n * \"/home/user/.agents/AGENTS.md\",\n * \"/project/AGENTS.md\",\n * ]);\n * const totalRemoved = results.reduce((n, r) => n + r.removed, 0);\n * console.log(`Removed ${totalRemoved} duplicate(s) across ${results.length} files`);\n * ```\n *\n * @public\n */\nexport async function dedupeFiles(filePaths: string[]): Promise<DedupeResult[]> {\n const results: DedupeResult[] = [];\n for (const filePath of filePaths) {\n results.push(await dedupeFile(filePath));\n }\n return results;\n}\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 * @remarks\n * Does not modify the file. Safe to call repeatedly for status checks.\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 *\n * @public\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_SINGLE.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_SINGLE);\n if (!match) return null;\n\n return match[0].replace(MARKER_START, '').replace(MARKER_END, '').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 multiple markers (duplicates): consolidates into single block → `\"consolidated\"`\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\"`, `\"consolidated\"`, `\"updated\"`, or `\"intact\"`\n *\n * @remarks\n * Handles duplicate marker consolidation automatically. When multiple CAAMP\n * blocks are detected (from manual edits or bugs), they are merged into one.\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 *\n * @public\n */\nexport async function inject(\n filePath: string,\n content: string,\n): Promise<'created' | 'added' | 'consolidated' | '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 // Find all CAAMP blocks in the file\n const matches = existing.match(MARKER_PATTERN);\n\n if (matches && matches.length > 0) {\n // Check if there are multiple duplicate blocks\n if (matches.length > 1) {\n // Consolidate all blocks into a single clean block\n const updated = existing\n .replace(MARKER_PATTERN, '')\n .replace(/^\\n{2,}/, '\\n')\n .trim();\n\n // Write the clean content with a single block\n const finalContent = updated ? `${block}\\n\\n${updated}` : `${block}\\n`;\n await writeFile(filePath, finalContent, 'utf-8');\n return 'consolidated';\n }\n\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_SINGLE, 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 * @remarks\n * Cleans up any leftover blank lines after removing the block. If the file\n * would be entirely empty after removal, the file itself is deleted.\n *\n * @example\n * ```typescript\n * const removed = await removeInjection(\"/project/CLAUDE.md\");\n * ```\n *\n * @public\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 * @remarks\n * Multiple providers may share the same instruction file (e.g. many use\n * `AGENTS.md`). This function deduplicates to avoid redundant file reads.\n *\n * @example\n * ```typescript\n * const results = await checkAllInjections(providers, \"/project\", \"project\", expected);\n * const outdated = results.filter(r => r.status === \"outdated\");\n * ```\n *\n * @public\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 =\n 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\"`, `\"consolidated\"`, `\"updated\"`, or `\"intact\"`)\n *\n * @remarks\n * Providers sharing the same instruction file are only written once to avoid\n * conflicting concurrent writes.\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 *\n * @public\n */\nexport async function injectAll(\n providers: Provider[],\n projectDir: string,\n scope: 'project' | 'global',\n content: string,\n): Promise<Map<string, 'created' | 'added' | 'consolidated' | 'updated' | 'intact'>> {\n const results = new Map<string, 'created' | 'added' | 'consolidated' | 'updated' | 'intact'>();\n const injected = new Set<string>();\n\n for (const provider of providers) {\n const filePath =\n 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 *\n * @public\n */\nexport interface EnsureProviderInstructionFileOptions {\n /**\n * `@` references to inject (e.g. `[\"@AGENTS.md\"]`).\n *\n * When omitted or `undefined`, the references declared in the CAAMP provider\n * registry (`provider.instructionReferences`) are used as the default. Callers\n * that supply an explicit array always take precedence over the registry default.\n *\n * @defaultValue Registry `instructionReferences` for the provider\n */\n references?: string[];\n /** Optional inline content blocks. @defaultValue `undefined` */\n content?: string[];\n /** Whether this is a global or project-level file. @defaultValue `\"project\"` */\n scope?: 'project' | 'global';\n}\n\n/**\n * Result of ensuring a provider instruction file.\n *\n * @public\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' | 'consolidated' | '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 * @remarks\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 * const result = await ensureProviderInstructionFile(\"claude-code\", \"/project\", {\n * references: [\"\\@AGENTS.md\"],\n * });\n * ```\n *\n * @public\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 =\n scope === 'global'\n ? join(provider.pathGlobal, provider.instructFile)\n : join(projectDir, provider.instructFile);\n\n // Fall back to the registry default when the caller omits references.\n const references = options.references ?? getProviderInstructionReferences(providerId);\n\n const template: InjectionTemplate = {\n 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 * @remarks\n * Providers sharing the same instruction file (e.g. many use `AGENTS.md`)\n * are only written once, avoiding duplicate blocks.\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 *\n * @public\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 =\n 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 // Fall back to the registry default when the caller omits references.\n const references = options.references ?? getProviderInstructionReferences(providerId);\n\n const template: InjectionTemplate = {\n 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// ── Per-Provider Agent Folder API ─────────────────────────────────\n\n/**\n * Known provider IDs that have a defined agent folder path.\n *\n * @public\n */\nexport type KnownProviderAgentFolderId =\n | 'claude-code'\n | 'claude-sdk'\n | 'opencode'\n | 'codex'\n | 'cursor'\n | 'pi'\n | 'kimi'\n | 'gemini-cli'\n | 'openai-sdk';\n\n/**\n * Resolve the native agent-definition folder path for a given provider.\n *\n * Each AI provider reads agent-definition files (e.g. `cleo-subagent.md`,\n * seed agent profiles) from its own platform-specific directory. This\n * function returns the correct path per provider so the CAAMP injector can\n * write agent files to the right location for every enabled provider.\n *\n * Follows XDG conventions (`~/.config/<provider>/agents/`) for providers\n * that do not have a pre-existing dotfolder convention. Claude Code and\n * Claude SDK both share `~/.claude/agents/` to match the Claude Code\n * native agent-loading path.\n *\n * Returns `null` for unknown provider IDs so callers can handle the gap\n * without throwing.\n *\n * @param providerId - Provider ID from the CAAMP registry (e.g. `\"claude-code\"`, `\"opencode\"`)\n * @returns Absolute path to the provider's agent folder, or `null` if the provider is unknown\n *\n * @example\n * ```typescript\n * const folder = getProviderAgentFolder(\"claude-code\");\n * // => \"/home/user/.claude/agents\"\n *\n * const folder2 = getProviderAgentFolder(\"opencode\");\n * // => \"/home/user/.config/opencode/agents\"\n *\n * const folder3 = getProviderAgentFolder(\"unknown-provider\");\n * // => null\n * ```\n *\n * @public\n */\nexport function getProviderAgentFolder(providerId: string): string | null {\n const home = homedir();\n\n switch (providerId as KnownProviderAgentFolderId) {\n case 'claude-code':\n case 'claude-sdk':\n return join(home, '.claude', 'agents');\n case 'opencode':\n return join(home, '.config', 'opencode', 'agents');\n case 'codex':\n return join(home, '.config', 'codex', 'agents');\n case 'cursor':\n return join(home, '.cursor', 'agents');\n case 'pi':\n return join(home, '.config', 'pi', 'agents');\n case 'kimi':\n return join(home, '.config', 'kimi', 'agents');\n case 'gemini-cli':\n return join(home, '.config', 'gemini', 'agents');\n case 'openai-sdk':\n return join(home, '.config', 'openai', 'agents');\n default:\n return null;\n }\n}\n\n/**\n * Result of writing an agent-definition file to a single provider's agent folder.\n *\n * @public\n */\nexport interface WriteAgentFileResult {\n /** Provider ID the file was written for. */\n providerId: string;\n /** Absolute path to the written agent-definition file. */\n filePath: string;\n /** Action taken. */\n action: 'created' | 'added' | 'consolidated' | 'updated' | 'intact';\n}\n\n/**\n * Options for writing agent-definition files to provider agent folders.\n *\n * @public\n */\nexport interface WriteAgentFileOptions {\n /**\n * File name for the agent-definition file (e.g. `\"cleo-subagent.md\"`).\n * This name is used as-is inside each provider's agent folder.\n */\n fileName: string;\n /** Content to inject between CAAMP markers in the agent-definition file. */\n content: string;\n /**\n * If `true`, skip writing to providers whose agent folder does not yet exist.\n * If `false` (default), the folder is created automatically.\n *\n * @defaultValue false\n */\n skipMissingFolders?: boolean;\n}\n\n/**\n * Write an agent-definition file to every enabled provider's native agent folder.\n *\n * For each provider ID supplied, the file is written to the provider's native\n * agent-definition directory (resolved via {@link getProviderAgentFolder}).\n * Writing is idempotent — if the file already exists with matching content the\n * action is `\"intact\"` and the file is not modified. This ensures that existing\n * `~/.claude/agents/cleo-subagent.md` installs from prior versions are preserved\n * without clobbering.\n *\n * Providers whose folder cannot be resolved (unknown provider IDs) are silently\n * skipped. Providers whose folder does not yet exist on disk are created\n * automatically unless `skipMissingFolders` is set to `true`.\n *\n * @param providerIds - Array of provider IDs to write agent files for\n * @param options - File name, content, and folder-creation behaviour\n * @returns Array of write results, one per provider that was successfully processed\n *\n * @example\n * ```typescript\n * const results = await writeAgentFileToAllProviders(\n * [\"claude-code\", \"opencode\", \"cursor\"],\n * {\n * fileName: \"cleo-subagent.md\",\n * content: \"## CLEO Subagent\\nYou are a CLEO subagent...\",\n * },\n * );\n * for (const r of results) {\n * console.log(`${r.providerId}: ${r.action} → ${r.filePath}`);\n * }\n * ```\n *\n * @public\n */\nexport async function writeAgentFileToAllProviders(\n providerIds: string[],\n options: WriteAgentFileOptions,\n): Promise<WriteAgentFileResult[]> {\n const results: WriteAgentFileResult[] = [];\n const processed = new Set<string>();\n\n for (const providerId of providerIds) {\n const folder = getProviderAgentFolder(providerId);\n if (folder === null) {\n // Unknown provider — skip silently; caller can detect by comparing\n // providerIds.length to results.length.\n continue;\n }\n\n const filePath = join(folder, options.fileName);\n\n // Deduplicate by resolved file path — claude-code and claude-sdk share\n // the same folder so we only write once.\n if (processed.has(filePath)) {\n // Still push a result so the caller sees all providers reflected.\n const existingResult = results.find((r) => r.filePath === filePath);\n if (existingResult) {\n results.push({ providerId, filePath, action: existingResult.action });\n }\n continue;\n }\n processed.add(filePath);\n\n if (options.skipMissingFolders === true && !existsSync(folder)) {\n // Folder does not exist and caller requested we skip rather than create.\n continue;\n }\n\n const action = await inject(filePath, options.content);\n results.push({ providerId, filePath, action });\n }\n\n return results;\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 DetectionMethod,\n Provider,\n ProviderCapabilities,\n ProviderHarnessCapability,\n ProviderHooksCapability,\n ProviderMcpCapability,\n ProviderSkillsCapability,\n ProviderSpawnCapability,\n} from '../../types.js';\nimport {\n type PathScope,\n resolveProviderSkillsDir,\n resolveProvidersRegistryPath,\n resolveRegistryTemplatePath,\n} from '../paths/standard.js';\nimport type {\n HookEvent,\n ProviderPriority,\n ProviderRegistry,\n ProviderStatus,\n RegistryCapabilities,\n RegistryHarnessCapability,\n RegistryHooksCapability,\n RegistryMcpIntegration,\n RegistryProvider,\n RegistrySpawnCapability,\n SkillsPrecedence,\n} 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 hookConfigPathProject: null,\n hookFormat: null,\n nativeEventCatalog: 'canonical',\n canInjectSystemPrompt: false,\n canBlockTools: false,\n};\n\nconst DEFAULT_SPAWN_CAPABILITY: ProviderSpawnCapability = {\n supportsSubagents: false,\n supportsProgrammaticSpawn: false,\n supportsInterAgentComms: false,\n supportsParallelSpawn: false,\n spawnMechanism: null,\n spawnCommand: null,\n};\n\nfunction resolveMcpCapability(raw: RegistryMcpIntegration): ProviderMcpCapability {\n return {\n configKey: raw.configKey,\n configFormat: raw.configFormat,\n configPathGlobal: resolveRegistryTemplatePath(raw.configPathGlobal),\n configPathProject: raw.configPathProject,\n supportedTransports: [...raw.supportedTransports],\n supportsHeaders: raw.supportsHeaders,\n };\n}\n\nfunction resolveHarnessCapability(raw: RegistryHarnessCapability): ProviderHarnessCapability {\n return {\n kind: raw.kind,\n spawnTargets: [...raw.spawnTargets],\n supportsConductorLoop: raw.supportsConductorLoop,\n supportsStageGuidance: raw.supportsStageGuidance,\n supportsCantBridge: raw.supportsCantBridge,\n extensionsPath: resolveRegistryTemplatePath(raw.extensionsPath),\n globalExtensionsHub: raw.globalExtensionsHub\n ? resolveRegistryTemplatePath(raw.globalExtensionsHub)\n : null,\n };\n}\n\nfunction resolveHooksCapability(raw: RegistryHooksCapability): ProviderHooksCapability {\n return {\n supported: [...raw.supported],\n hookConfigPath: raw.hookConfigPath ? resolveRegistryTemplatePath(raw.hookConfigPath) : null,\n hookConfigPathProject: raw.hookConfigPathProject ?? null,\n hookFormat: raw.hookFormat,\n nativeEventCatalog: raw.nativeEventCatalog ?? 'canonical',\n canInjectSystemPrompt: raw.canInjectSystemPrompt ?? false,\n canBlockTools: raw.canBlockTools ?? false,\n };\n}\n\nfunction resolveSpawnCapability(raw: RegistrySpawnCapability): ProviderSpawnCapability {\n return {\n supportsSubagents: raw.supportsSubagents,\n supportsProgrammaticSpawn: raw.supportsProgrammaticSpawn,\n supportsInterAgentComms: raw.supportsInterAgentComms,\n supportsParallelSpawn: raw.supportsParallelSpawn,\n spawnMechanism: raw.spawnMechanism,\n spawnCommand: raw.spawnCommand ? [...raw.spawnCommand] : null,\n };\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 ? resolveHooksCapability(raw.hooks)\n : { ...DEFAULT_HOOKS_CAPABILITY, supported: [] };\n\n const spawn: ProviderSpawnCapability = raw?.spawn\n ? resolveSpawnCapability(raw.spawn)\n : { ...DEFAULT_SPAWN_CAPABILITY };\n\n const mcp: ProviderMcpCapability | null = raw?.mcp ? resolveMcpCapability(raw.mcp) : null;\n\n const harness: ProviderHarnessCapability | null = raw?.harness\n ? resolveHarnessCapability(raw.harness)\n : null;\n\n return { mcp, harness, 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 instructionReferences: raw.instructionReferences ? [...raw.instructionReferences] : [],\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 priority: raw.priority,\n status: raw.status,\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 * @remarks\n * The registry is parsed once and cached in-module state. Platform-specific\n * template paths (e.g. `~/.config/...`) are resolved at load time via\n * {@link resolveRegistryTemplatePath}. Call {@link resetRegistry} to force\n * a reload.\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 *\n * @public\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 * @remarks\n * Alias resolution is performed via an internal map built during registry loading.\n * If the input matches an alias, it is resolved to the canonical provider ID before\n * lookup. If it matches neither an alias nor a canonical ID, `undefined` is returned.\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 *\n * @public\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 * @remarks\n * Alias mappings are built from the `aliases` array in each provider's registry\n * entry. This function is safe to call with canonical IDs -- they pass through unchanged.\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 *\n * @public\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 * @remarks\n * Provider priority is assigned in `providers/registry.json` and indicates the\n * relative importance of a provider for detection ordering and display.\n * Callers filtering by `\"primary\"` should expect zero or one result; the\n * registry loader does not enforce the single-primary invariant.\n *\n * @param priority - Priority level to filter by (`\"primary\"`, `\"high\"`, `\"medium\"`, or `\"low\"`)\n * @returns Array of providers matching the given priority\n *\n * @example\n * ```typescript\n * const highPriority = getProvidersByPriority(\"high\");\n * console.log(highPriority.map(p => p.toolName));\n * ```\n *\n * @public\n */\nexport function getProvidersByPriority(priority: ProviderPriority): Provider[] {\n return getAllProviders().filter((p) => p.priority === priority);\n}\n\n/**\n * Get the single primary harness provider, if any is registered.\n *\n * @remarks\n * Returns the provider with `priority === \"primary\"`. By convention a\n * registry defines at most one primary harness; this function returns\n * the first match if the invariant is violated and logs no warning. Use\n * {@link getProvidersByPriority} instead if you need to diagnose\n * duplicates.\n *\n * @returns The primary provider, or `undefined` if none is registered\n *\n * @example\n * ```typescript\n * const primary = getPrimaryProvider();\n * if (primary) {\n * console.log(`Primary harness: ${primary.toolName}`);\n * }\n * ```\n *\n * @public\n */\nexport function getPrimaryProvider(): Provider | undefined {\n return getAllProviders().find((p) => p.priority === 'primary');\n}\n\n/**\n * Filter providers by their lifecycle status.\n *\n * @remarks\n * Lifecycle status is maintained per-provider in the registry and reflects\n * the provider's stability and support level within CAAMP.\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 * console.log(`${active.length} active providers`);\n * ```\n *\n * @public\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 * @remarks\n * CAAMP supports three instruction file types: `CLAUDE.md`, `AGENTS.md`, and `GEMINI.md`.\n * Most providers read from `AGENTS.md` as the universal standard, while a few\n * have vendor-specific files.\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 * console.log(claudeProviders.map(p => p.id));\n * ```\n *\n * @public\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 * @remarks\n * Iterates over all registered providers and collects the distinct\n * `instructFile` values. The result is deduplicated via a `Set`.\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 *\n * @public\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 * @remarks\n * Triggers lazy loading of the registry if not already loaded.\n * The count reflects the number of entries in `providers/registry.json`.\n *\n * @returns Count of providers in the registry\n *\n * @example\n * ```typescript\n * console.log(`Registry has ${getProviderCount()} providers`);\n * ```\n *\n * @public\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 * @remarks\n * The version is read from the top-level `version` field in `providers/registry.json`\n * and follows semver conventions. It is bumped when provider definitions change.\n *\n * @returns Version string from `providers/registry.json` (e.g. `\"2.0.0\"`)\n *\n * @example\n * ```typescript\n * console.log(`Registry version: ${getRegistryVersion()}`);\n * ```\n *\n * @public\n */\nexport function getRegistryVersion(): string {\n return loadRegistry().version;\n}\n\n/**\n * Filter providers that support a specific hook event.\n *\n * @remarks\n * Hook events are declared per-provider in the `capabilities.hooks.supported`\n * array within the registry. Only providers that explicitly list the event\n * are returned.\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 * console.log(providers.map(p => p.id));\n * ```\n *\n * @public\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 * @remarks\n * Computes the set intersection of `capabilities.hooks.supported` across the\n * target providers. Useful for determining which hook events can be reliably\n * used across a multi-agent installation.\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 * console.log(`${common.length} common hook events`);\n * ```\n *\n * @public\n */\nexport function getCommonHookEvents(providerIds?: string[]): HookEvent[] {\n const providers =\n 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 * @remarks\n * This function traverses the capabilities object using dot-delimited path\n * segments. It handles three value types: booleans (must be `true`), arrays\n * (must be non-empty), and all other values (must be non-null/undefined).\n * Invalid paths return `false`.\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 * providerSupports(claude!, \"hooks.supported\"); // true (non-empty array)\n * ```\n *\n * @public\n */\nexport function providerSupports(provider: Provider, dotPath: string): boolean {\n const parts = dotPath.split('.');\n let current: unknown = provider.capabilities;\n for (const part of parts) {\n if (current == null || typeof current !== 'object') return false;\n current = (current as Record<string, unknown>)[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 * @remarks\n * This is a convenience wrapper that checks the `capabilities.spawn.supportsSubagents`\n * boolean flag. For more granular spawn capability filtering, use\n * {@link getProvidersBySpawnCapability}.\n *\n * @returns Array of providers where `capabilities.spawn.supportsSubagents === true`\n *\n * @example\n * ```typescript\n * const spawnCapable = getSpawnCapableProviders();\n * console.log(spawnCapable.map(p => p.id));\n * ```\n *\n * @public\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 * @remarks\n * The spawn capability has four boolean flags that can be queried independently.\n * The `spawnMechanism` and `spawnCommand` fields are excluded from the flag\n * type since they are not boolean checks.\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 * console.log(parallel.map(p => p.id));\n * ```\n *\n * @see {@link getSpawnCapableProviders}\n *\n * @public\n */\nexport function getProvidersBySpawnCapability(\n flag: keyof Omit<ProviderSpawnCapability, 'spawnMechanism' | 'spawnCommand'>,\n): Provider[] {\n return getAllProviders().filter((p) => p.capabilities.spawn[flag] === true);\n}\n\n/**\n * Reset cached registry data, forcing a reload on next access.\n *\n * @remarks\n * Clears the in-memory provider map, alias map, and raw registry cache.\n * Primarily used in test suites to ensure a clean state between test cases.\n *\n * @example\n * ```typescript\n * resetRegistry();\n * // Next call to getAllProviders() will re-read registry.json\n * ```\n *\n * @public\n */\nexport function resetRegistry(): void {\n _registry = null;\n _providers = null;\n _aliasMap = null;\n}\n\n/**\n * Get the default `@` instruction references for a provider from the registry.\n *\n * Returns the `instructionReferences` array declared in `providers/registry.json`\n * for the given provider ID or alias. These references are the canonical defaults\n * used by {@link ensureProviderInstructionFile} when no explicit `references`\n * argument is supplied by the caller.\n *\n * @remarks\n * The return value is a fresh copy of the registry array — mutating it has no\n * effect on the cached registry state. If the provider is not found or it has\n * no `instructionReferences` entry, an empty array is returned so callers\n * never receive `undefined`.\n *\n * @param idOrAlias - Provider ID (e.g. `\"claude-code\"`) or alias (e.g. `\"claude\"`)\n * @returns Array of `@`-prefixed instruction reference strings, or `[]` if none\n *\n * @example\n * ```typescript\n * const refs = getProviderInstructionReferences(\"claude-code\");\n * // [\"@~/.cleo/templates/CLEO-INJECTION.md\", \"@.cleo/memory-bridge.md\"]\n *\n * const unknown = getProviderInstructionReferences(\"no-such-provider\");\n * // []\n * ```\n *\n * @public\n */\nexport function getProviderInstructionReferences(idOrAlias: string): string[] {\n const provider = getProvider(idOrAlias);\n return provider?.instructionReferences ? [...provider.instructionReferences] : [];\n}\n\n// ── Skills Query Functions ──────────────────────────────────────────\n\n/**\n * Filter providers by their skills precedence value.\n *\n * @remarks\n * Skills precedence controls how a provider resolves skill files when both\n * vendor-specific and `.agents/` standard paths exist. Values include\n * `\"vendor-only\"`, `\"agents-canonical\"`, `\"agents-first\"`, `\"agents-supported\"`,\n * and `\"vendor-global-agents-project\"`.\n *\n * @param precedence - Skills precedence to filter by\n * @returns Array of providers matching the given precedence\n *\n * @example\n * ```typescript\n * const vendorOnly = getProvidersBySkillsPrecedence(\"vendor-only\");\n * console.log(vendorOnly.map(p => p.id));\n * ```\n *\n * @public\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 * @remarks\n * The returned array is ordered by precedence priority. For example, with\n * `\"agents-first\"` precedence the `.agents/` path appears before the vendor\n * path. The `source` field indicates whether the path comes from the vendor\n * directory or the `.agents/` standard directory.\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 *\n * @example\n * ```typescript\n * const provider = getProvider(\"claude-code\")!;\n * const paths = getEffectiveSkillsPaths(provider, \"global\");\n * for (const p of paths) {\n * console.log(`${p.source} (${p.scope}): ${p.path}`);\n * }\n * ```\n *\n * @public\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 * @remarks\n * Produces a summary of each provider's skills configuration including\n * the precedence mode and resolved global/project paths. For `\"vendor-only\"`\n * providers the paths point to the vendor skills directory; for others they\n * point to the `.agents/` standard paths.\n *\n * @returns Array of skills map entries with provider ID, tool name, precedence, and paths\n *\n * @example\n * ```typescript\n * const skillsMap = buildSkillsMap();\n * for (const entry of skillsMap) {\n * console.log(`${entry.providerId}: ${entry.precedence}`);\n * }\n * ```\n *\n * @public\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 * @remarks\n * Shorthand for `getProvider(idOrAlias)?.capabilities`. Returns the full\n * capabilities object containing mcp, harness, skills, hooks, and spawn\n * sub-objects.\n *\n * @param idOrAlias - Provider ID or alias\n * @returns The provider's capabilities, or undefined if not found\n *\n * @example\n * ```typescript\n * const caps = getProviderCapabilities(\"claude-code\");\n * if (caps?.spawn.supportsSubagents) {\n * console.log(\"Supports subagent spawning\");\n * }\n * ```\n *\n * @public\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 * @remarks\n * Returns `false` both when the provider is not found and when the capability\n * is not supported. Use {@link getProvider} first if you need to distinguish\n * between these cases.\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 *\n * @example\n * ```typescript\n * if (providerSupportsById(\"claude-code\", \"spawn.supportsSubagents\")) {\n * console.log(\"Claude Code supports subagent spawning\");\n * }\n * ```\n *\n * @see {@link providerSupports}\n *\n * @public\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","/**\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 * @remarks\n * Projects use this to define what goes between CAAMP markers in\n * instruction files, rather than passing ad-hoc strings.\n *\n * @public\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). @defaultValue `undefined` */\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 * @remarks\n * References are output one per line. Content blocks are appended after a\n * blank separator line when references are present.\n *\n * @example\n * ```typescript\n * const content = buildInjectionContent({\n * references: [\"\\@AGENTS.md\"],\n * });\n * ```\n *\n * @public\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 * @remarks\n * Inverse of {@link buildInjectionContent}. Empty lines are ignored.\n *\n * @example\n * ```typescript\n * const template = parseInjectionContent(\"\\@AGENTS.md\\n\\@.cleo/config.json\");\n * ```\n *\n * @public\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 * @remarks\n * This is the legacy API preserved for backward compatibility. New code\n * should prefer {@link buildInjectionContent} with an `InjectionTemplate`.\n *\n * @param options - Optional configuration for the generated content\n * @returns Generated markdown string\n *\n * @example\n * ```typescript\n * const content = generateInjectionContent({ mcpServerName: \"filesystem\" });\n * ```\n *\n * @public\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/**\n * Generate a skills discovery section for instruction files.\n *\n * @remarks\n * Produces a markdown list of installed skill names. Returns an empty string\n * when no skills are provided.\n *\n * @param skillNames - Array of skill names to list\n * @returns Markdown string listing installed skills\n *\n * @example\n * ```typescript\n * const section = generateSkillsSection([\"code-review\", \"testing\"]);\n * ```\n *\n * @public\n */\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/**\n * Get the correct instruction file name for a provider.\n *\n * @remarks\n * Simple accessor that returns the `instructFile` property from the provider\n * registry entry (e.g. `\"CLAUDE.md\"`, `\"AGENTS.md\"`, `\"GEMINI.md\"`).\n *\n * @param provider - Provider registry entry\n * @returns Instruction file name\n *\n * @example\n * ```typescript\n * const fileName = getInstructFile(provider);\n * // \"CLAUDE.md\"\n * ```\n *\n * @public\n */\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 * @remarks\n * Useful for determining which providers share the same instruction file\n * to avoid duplicate file operations.\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 *\n * @public\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"],"mappings":"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","names":["dirname","join","dirname","updated","join"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveRegistryTemplatePath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OCI4RYI5.js";
|
|
4
4
|
|
|
5
5
|
// src/core/hooks/normalizer.ts
|
|
6
6
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -291,4 +291,4 @@ export {
|
|
|
291
291
|
resolveNativeEvent,
|
|
292
292
|
getHookMappingsVersion
|
|
293
293
|
};
|
|
294
|
-
//# sourceMappingURL=chunk-
|
|
294
|
+
//# sourceMappingURL=chunk-SV33CE5X.js.map
|
package/dist/cli.js
CHANGED
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
tokenizeCriteriaValue,
|
|
53
53
|
updateInstructionsSingleOperation,
|
|
54
54
|
validateSkill
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-4W35AEYA.js";
|
|
56
56
|
import {
|
|
57
57
|
buildSkillsMap,
|
|
58
58
|
checkAllInjections,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
groupByInstructFile,
|
|
66
66
|
injectAll,
|
|
67
67
|
providerSupports
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-OPUPNLUJ.js";
|
|
69
69
|
import {
|
|
70
70
|
CANONICAL_HOOK_EVENTS,
|
|
71
71
|
buildHookMatrix,
|
|
@@ -74,12 +74,12 @@ import {
|
|
|
74
74
|
getHookSupport,
|
|
75
75
|
getProviderSummary,
|
|
76
76
|
translateToAll
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-SV33CE5X.js";
|
|
78
78
|
import {
|
|
79
79
|
buildSkillSubPathCandidates,
|
|
80
80
|
resolveProviderConfigPath,
|
|
81
81
|
resolveProviderSkillsDir
|
|
82
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-OCI4RYI5.js";
|
|
83
83
|
|
|
84
84
|
// src/cli.ts
|
|
85
85
|
import { Command } from "commander";
|
|
@@ -3349,7 +3349,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3349
3349
|
return;
|
|
3350
3350
|
}
|
|
3351
3351
|
if (opts.from) {
|
|
3352
|
-
const { toCanonical } = await import("./hooks-
|
|
3352
|
+
const { toCanonical } = await import("./hooks-5EXBKPII.js");
|
|
3353
3353
|
const canonical2 = toCanonical(event, opts.from);
|
|
3354
3354
|
if (format === "json") {
|
|
3355
3355
|
const envelope = buildEnvelope2(
|
|
@@ -3389,7 +3389,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
|
|
|
3389
3389
|
}
|
|
3390
3390
|
process.exit(1);
|
|
3391
3391
|
}
|
|
3392
|
-
const { getMappedProviderIds } = await import("./hooks-
|
|
3392
|
+
const { getMappedProviderIds } = await import("./hooks-5EXBKPII.js");
|
|
3393
3393
|
const allIds = getMappedProviderIds();
|
|
3394
3394
|
const translations = translateToAll(canonical, allIds);
|
|
3395
3395
|
if (format === "json") {
|
|
@@ -24,8 +24,8 @@ import {
|
|
|
24
24
|
toNative,
|
|
25
25
|
toNativeBatch,
|
|
26
26
|
translateToAll
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-SV33CE5X.js";
|
|
28
|
+
import "./chunk-OCI4RYI5.js";
|
|
29
29
|
export {
|
|
30
30
|
CANONICAL_HOOK_EVENTS,
|
|
31
31
|
HOOK_CATEGORIES,
|
|
@@ -53,4 +53,4 @@ export {
|
|
|
53
53
|
toNativeBatch,
|
|
54
54
|
translateToAll
|
|
55
55
|
};
|
|
56
|
-
//# sourceMappingURL=hooks-
|
|
56
|
+
//# sourceMappingURL=hooks-5EXBKPII.js.map
|