UNPKG

aiwg

Version:

Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo

134 lines 5.45 kB
/** * Namespace-aware Skill Deployment Adapter * * Implements per-platform namespace deployment strategy per ADR: * .aiwg/architecture/adr-skill-namespace-strategy.md * * Platform groups: * Group A (deep-recursion): Claude Code, Cursor, Codex, OpenCode, OpenClaw * → Deploy both canonical subdir layout AND prefixed slug fallback. * Group B (one-level): Factory AI, Warp, Windsurf * → Deploy only the prefixed slug; no subdir (would break one-level discovery). * Group C (unknown): GitHub Copilot * → Deploy only the prefixed slug (safe default until recursion depth confirmed). * Group D (mcp-skip): Hermes * → Skip file deployment, emit guidance pointing to hermes-quickstart.md. * * @implements #704 * @see collision-detector.ts for pre-deployment collision checking (#697) */ import type { Platform } from '../../agents/types.js'; /** * Namespace deployment group per ADR. */ export type DeploymentGroup = 'deep-recursion' | 'one-level' | 'unknown' | 'mcp-skip'; /** * Whether the skills root resolves relative to the project directory or * the user's home directory. */ export type PathType = 'project' | 'home-dir'; /** * Per-platform namespace deployment adapter configuration. */ export interface NamespaceAdapter { /** Platform this adapter handles */ platform: Platform; /** * Deployment group, determines how many target paths are produced: * - deep-recursion: subdir layout + prefixed slug * - one-level / unknown: prefixed slug only * - mcp-skip: no files written */ deploymentGroup: DeploymentGroup; /** Whether skills root resolves relative to project or home directory */ pathType: PathType; /** Skills base directory (relative to project root, or relative to homedir) */ skillsBaseDir: string; /** * Whether to produce the canonical `{baseDir}/{namespace}/{slug}/` path. * True for Group A (deep recursion) only. * False for all other groups — would break one-level discovery. */ subdirLayout: boolean; /** Maximum name field length (SKILL.md frontmatter truncation) */ maxNameLength?: number; /** Maximum description field length (SKILL.md frontmatter truncation) */ maxDescriptionLength?: number; /** Text appended to description field (e.g. Factory suffix) */ appendToDescription?: string; } /** * A single file deployment instruction. */ export interface DeploymentPlan { /** Absolute path to write the SKILL.md file */ targetPath: string; /** File content (may differ from source when frontmatter is mutated) */ content: string; /** Human-readable description for logging */ label: string; } /** * Result of resolving namespace deployment plans for one skill. */ export interface NamespaceDeployResult { platform: Platform; skillName: string; /** Plans to execute (empty when skip=true) */ plans: DeploymentPlan[]; /** When true, no files should be written */ skip: boolean; /** Guidance message when skip=true (e.g. Hermes manual setup note) */ skipMessage?: string; } /** * Per-platform adapter table. * Keyed by Platform value; includes a 'generic' fallback. */ export declare const NAMESPACE_ADAPTERS: Record<Platform | 'generic', NamespaceAdapter>; /** * Resolve absolute skills root for a platform + project combination. * Home-dir platforms (Codex, OpenClaw, Hermes) use os.homedir(). */ export declare function resolveSkillsRoot(adapter: NamespaceAdapter, projectPath: string): string; /** * Compute canonical namespaced slug. * Idempotent: if `skillName` already starts with `{namespace}-`, returns it unchanged. * * @example * computePrefixedSlug('sync', 'aiwg') // → 'aiwg-sync' * computePrefixedSlug('aiwg-sync', 'aiwg') // → 'aiwg-sync' */ export declare function computePrefixedSlug(skillName: string, namespace: string): string; /** * Apply platform-specific frontmatter mutations to SKILL.md content. * * Mutations applied (when configured): * - Inject `namespace: {namespace}` into frontmatter if not present * - Truncate `name` to `maxNameLength` * - Append `appendToDescription` suffix to `description` * - Truncate `description` to `maxDescriptionLength` * * Returns the original content unchanged when no mutations are needed. */ export declare function mutateFrontmatter(content: string, adapter: NamespaceAdapter, namespace: string): string; /** * Get the namespace adapter for a platform. * Falls back to 'generic' for unrecognised platforms. */ export declare function getAdapter(platform: Platform | string): NamespaceAdapter; /** * Resolve deployment plans for a skill on a given platform. * * Calls `checkCollisions()` before writing should be done at the call site * (see collision-detector.ts, #697). * * @param platform - Target platform * @param projectPath - Absolute project root directory * @param skillName - Skill folder name (e.g. 'sync', 'aiwg-sync') * @param sourceContent - Raw content of the source SKILL.md file * @param namespace - Namespace prefix (default: 'aiwg') * @returns NamespaceDeployResult with plans to execute (or skip=true for Hermes) */ export declare function getDeploymentPlans(platform: Platform | string, projectPath: string, skillName: string, sourceContent: string, namespace?: string): NamespaceDeployResult; //# sourceMappingURL=namespace-adapter.d.ts.map