@agentforge/skills 0.15.7 → 0.15.9

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/index.cjs CHANGED
@@ -502,7 +502,7 @@ var SkillRegistry = class {
502
502
  });
503
503
  logger3.warn("Skipping invalid skill", {
504
504
  skillPath: candidate.skillPath,
505
- error: result.error
505
+ ...result.error ? { error: result.error } : {}
506
506
  });
507
507
  continue;
508
508
  }
@@ -706,7 +706,7 @@ var SkillRegistry = class {
706
706
  logger3.debug("Skill prompt generation produced empty result", {
707
707
  totalDiscovered: this.size(),
708
708
  filterApplied: !!(options?.skills && options.skills.length > 0),
709
- maxCap: this.config.maxDiscoveredSkills
709
+ ...this.config.maxDiscoveredSkills !== void 0 ? { maxCap: this.config.maxDiscoveredSkills } : {}
710
710
  });
711
711
  return "";
712
712
  }
@@ -728,7 +728,7 @@ ${skillEntries.join("\n")}
728
728
  skillCount: skills.length,
729
729
  totalDiscovered: this.size(),
730
730
  filterApplied: !!(options?.skills && options.skills.length > 0),
731
- maxCap: this.config.maxDiscoveredSkills,
731
+ ...this.config.maxDiscoveredSkills !== void 0 ? { maxCap: this.config.maxDiscoveredSkills } : {},
732
732
  estimatedTokens,
733
733
  xmlLength: xml.length
734
734
  });
@@ -783,7 +783,7 @@ ${skillEntries.join("\n")}
783
783
  logger3.error("Skill event handler error", {
784
784
  event,
785
785
  error: error instanceof Error ? error.message : String(error),
786
- stack: error instanceof Error ? error.stack : void 0
786
+ ...error instanceof Error && error.stack ? { stack: error.stack } : {}
787
787
  });
788
788
  }
789
789
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/parser.ts","../src/scanner.ts","../src/trust.ts","../src/activation.ts","../src/registry.ts"],"names":["TrustPolicyReason","SkillRegistryEvent","matter","createLogger","LogLevel","resolve","homedir","existsSync","readdirSync","statSync","readFileSync","basename","logger","z","isAbsolute","relative","realpathSync","ToolBuilder","ToolCategory","resolvePath"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Skill System Types\n *\n * Core type definitions for the AgentForge Agent Skills system.\n * These types align with the Agent Skills specification (https://agentskills.io/specification).\n */\n\n// ─── Trust Policy Types ──────────────────────────────────────────────────\n\n/**\n * Trust level for a skill root directory.\n *\n * - `workspace` — Skills from the project workspace (highest trust, scripts allowed)\n * - `trusted` — Explicitly trusted skill roots (scripts allowed)\n * - `untrusted` — Untrusted roots like community packs (scripts blocked by default)\n */\nexport type TrustLevel = 'workspace' | 'trusted' | 'untrusted';\n\n/**\n * Configuration for a skill root with an explicit trust level.\n *\n * @example\n * ```ts\n * const roots: SkillRootConfig[] = [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community-skills', trust: 'untrusted' },\n * ];\n * ```\n */\nexport interface SkillRootConfig {\n /** Directory path to scan for skills */\n path: string;\n /** Trust level assigned to all skills discovered from this root */\n trust: TrustLevel;\n}\n\n/**\n * Policy decision returned by trust enforcement checks.\n */\nexport interface TrustPolicyDecision {\n /** Whether the action is allowed */\n allowed: boolean;\n /** Machine-readable reason code for auditing */\n reason: TrustPolicyReason;\n /** Human-readable explanation */\n message: string;\n}\n\n/**\n * Reason codes for trust policy decisions.\n *\n * Used for structured logging and auditing of guardrail behavior.\n */\nexport enum TrustPolicyReason {\n /** Resource is not a script — no trust check needed */\n NOT_SCRIPT = 'not-script',\n /** Skill root has workspace trust — scripts allowed */\n WORKSPACE_TRUST = 'workspace-trust',\n /** Skill root has explicit trusted status — scripts allowed */\n TRUSTED_ROOT = 'trusted-root',\n /** Skill root is untrusted — scripts denied by default */\n UNTRUSTED_SCRIPT_DENIED = 'untrusted-script-denied',\n /** Untrusted script access was explicitly allowed via config override */\n UNTRUSTED_SCRIPT_ALLOWED = 'untrusted-script-allowed-override',\n /** Trust level is unknown — treated as untrusted for security */\n UNKNOWN_TRUST_LEVEL = 'unknown-trust-level',\n}\n\n/**\n * Parsed metadata from a SKILL.md frontmatter block.\n *\n * Required fields: `name`, `description`.\n * All other fields are optional per the Agent Skills spec.\n */\nexport interface SkillMetadata {\n /** Skill name (1-64 chars, lowercase alphanumeric + hyphens, must match parent dir name) */\n name: string;\n /** Human-readable description (1-1024 chars) */\n description: string;\n /** SPDX license identifier */\n license?: string;\n /** List of compatible agent frameworks / tool hosts */\n compatibility?: string[];\n /** Arbitrary key-value metadata (author, version, etc.) */\n metadata?: Record<string, unknown>;\n /** Tools that this skill is allowed to use */\n allowedTools?: string[];\n}\n\n/**\n * A fully resolved skill entry in the registry.\n *\n * Contains parsed metadata plus internal tracking fields\n * that are not part of the SKILL.md frontmatter.\n */\nexport interface Skill {\n /** Parsed frontmatter metadata */\n metadata: SkillMetadata;\n /** Absolute path to the skill directory */\n skillPath: string;\n /** Which configured skill root this was discovered from */\n rootPath: string;\n /** Trust level assigned to this skill (inherited from root config) */\n trustLevel: TrustLevel;\n}\n\n/**\n * Configuration for the SkillRegistry.\n */\nexport interface SkillRegistryConfig {\n /**\n * Array of directory paths to scan for skills.\n *\n * Each entry can be a plain string (defaults to `'untrusted'` trust level)\n * or a `SkillRootConfig` object with an explicit trust level.\n *\n * Paths may be absolute or relative (resolved against `cwd`).\n * The `~` prefix is expanded to `$HOME`.\n *\n * @example\n * ```ts\n * // Simple string roots (default to 'untrusted')\n * skillRoots: ['.agentskills', '~/.agentskills']\n *\n * // Trust-aware roots\n * skillRoots: [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community', trust: 'untrusted' },\n * ]\n * ```\n */\n skillRoots: Array<string | SkillRootConfig>;\n\n /**\n * Feature flag to enable Agent Skills in system prompts.\n *\n * When `false` (default), `generatePrompt()` returns an empty string\n * so agents operate with unmodified system prompts.\n *\n * @default false\n */\n enabled?: boolean;\n\n /**\n * Maximum number of skills to include in generated prompts.\n *\n * Caps prompt token usage when many skills are discovered.\n * Skills are included in discovery order (first root first).\n * When undefined, all discovered skills are included.\n */\n maxDiscoveredSkills?: number;\n\n /**\n * Allow script resources from untrusted roots.\n *\n * When `true`, scripts from `scripts/` directories in untrusted\n * skill roots are returned instead of being denied. This disables\n * the default-deny policy for untrusted scripts.\n *\n * **Security warning:** Only enable when you have reviewed all\n * skill packs from untrusted roots.\n *\n * @default false\n */\n allowUntrustedScripts?: boolean;\n}\n\n/**\n * Options for `SkillRegistry.generatePrompt()`.\n */\nexport interface SkillPromptOptions {\n /**\n * Subset of skill names to include in the generated prompt.\n *\n * When provided, only skills matching these names appear in the\n * `<available_skills>` XML block. This enables creating focused\n * agents with different skill sets from the same registry.\n *\n * When omitted or empty, all discovered skills are included.\n *\n * @example ['code-review', 'testing-strategy']\n */\n skills?: string[];\n}\n\n/**\n * Events emitted by the SkillRegistry during discovery and usage.\n */\nexport enum SkillRegistryEvent {\n /** Emitted when a valid skill is discovered during scanning */\n SKILL_DISCOVERED = 'skill:discovered',\n /** Emitted when a skill parse or validation issue is encountered */\n SKILL_WARNING = 'skill:warning',\n /** Emitted when a skill is activated (full body loaded) */\n SKILL_ACTIVATED = 'skill:activated',\n /** Emitted when a skill resource file is loaded */\n SKILL_RESOURCE_LOADED = 'skill:resource-loaded',\n /** Emitted when a trust policy denies access to a resource */\n TRUST_POLICY_DENIED = 'trust:policy-denied',\n /** Emitted when a trust policy allows access (for auditing) */\n TRUST_POLICY_ALLOWED = 'trust:policy-allowed',\n}\n\n/**\n * Event handler type for skill registry events.\n */\nexport type SkillEventHandler = (data: unknown) => void;\n\n/**\n * Result of parsing a single SKILL.md file.\n */\nexport interface SkillParseResult {\n /** Whether parsing and validation succeeded */\n success: boolean;\n /** Parsed metadata (present when success is true) */\n metadata?: SkillMetadata;\n /** The raw markdown body below the frontmatter (present when success is true) */\n body?: string;\n /** Error description (present when success is false) */\n error?: string;\n}\n\n/**\n * Validation error detail.\n */\nexport interface SkillValidationError {\n /** Which field failed validation */\n field: string;\n /** Human-readable error message */\n message: string;\n}\n","/**\n * SKILL.md Frontmatter Parser\n *\n * Parses YAML frontmatter from SKILL.md files and validates\n * against the Agent Skills specification constraints.\n *\n * @see https://agentskills.io/specification\n */\n\nimport matter from 'gray-matter';\nimport type { SkillMetadata, SkillParseResult, SkillValidationError } from './types.js';\n\n/**\n * Skill name validation constraints (per spec).\n *\n * - 1-64 characters\n * - Lowercase alphanumeric and hyphens only\n * - No leading, trailing, or consecutive hyphens\n */\nconst SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\nconst SKILL_NAME_MAX_LENGTH = 64;\nconst SKILL_DESCRIPTION_MAX_LENGTH = 1024;\n\n/**\n * Validate the `name` field per the Agent Skills spec.\n *\n * @param name - The name value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillName(name: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (name === undefined || name === null) {\n errors.push({ field: 'name', message: 'name is required' });\n return errors;\n }\n\n if (typeof name !== 'string') {\n errors.push({ field: 'name', message: 'name must be a string' });\n return errors;\n }\n\n if (name.length === 0) {\n errors.push({ field: 'name', message: 'name must not be empty' });\n return errors;\n }\n\n if (name.length > SKILL_NAME_MAX_LENGTH) {\n errors.push({\n field: 'name',\n message: `name must be at most ${SKILL_NAME_MAX_LENGTH} characters (got ${name.length})`,\n });\n return errors;\n }\n\n if (!SKILL_NAME_PATTERN.test(name)) {\n errors.push({\n field: 'name',\n message: 'name must be lowercase alphanumeric with hyphens, no leading/trailing/consecutive hyphens',\n });\n }\n\n if (name.includes('--')) {\n errors.push({\n field: 'name',\n message: 'name must not contain consecutive hyphens',\n });\n }\n\n return errors;\n}\n\n/**\n * Validate the `description` field per the Agent Skills spec.\n *\n * @param description - The description value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillDescription(description: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (description === undefined || description === null) {\n errors.push({ field: 'description', message: 'description is required' });\n return errors;\n }\n\n if (typeof description !== 'string') {\n errors.push({ field: 'description', message: 'description must be a string' });\n return errors;\n }\n\n if (description.trim().length === 0) {\n errors.push({ field: 'description', message: 'description must not be empty' });\n return errors;\n }\n\n if (description.length > SKILL_DESCRIPTION_MAX_LENGTH) {\n errors.push({\n field: 'description',\n message: `description must be at most ${SKILL_DESCRIPTION_MAX_LENGTH} characters (got ${description.length})`,\n });\n }\n\n return errors;\n}\n\n/**\n * Validate that the skill name matches its parent directory name (per spec).\n *\n * @param name - The name from frontmatter\n * @param dirName - The parent directory name\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillNameMatchesDir(name: string, dirName: string): SkillValidationError[] {\n if (name !== dirName) {\n return [{\n field: 'name',\n message: `name \"${name}\" must match parent directory name \"${dirName}\"`,\n }];\n }\n return [];\n}\n\n/**\n * Parse and validate a SKILL.md file's raw content.\n *\n * Extracts YAML frontmatter using gray-matter, then validates\n * required and optional fields against spec constraints.\n *\n * @param content - Raw file content of the SKILL.md\n * @param dirName - Parent directory name for name-match validation\n * @returns Parse result with metadata or error\n */\nexport function parseSkillContent(content: string, dirName: string): SkillParseResult {\n let parsed: matter.GrayMatterFile<string>;\n\n try {\n parsed = matter(content);\n } catch (err) {\n return {\n success: false,\n error: `Failed to parse frontmatter: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n const data = parsed.data;\n\n // Validate required fields\n const errors: SkillValidationError[] = [\n ...validateSkillName(data.name),\n ...validateSkillDescription(data.description),\n ];\n\n // If name is valid, validate it matches directory name\n if (typeof data.name === 'string' && data.name.length > 0 && SKILL_NAME_PATTERN.test(data.name)) {\n errors.push(...validateSkillNameMatchesDir(data.name, dirName));\n }\n\n if (errors.length > 0) {\n return {\n success: false,\n error: errors.map((e) => `${e.field}: ${e.message}`).join('; '),\n };\n }\n\n // Build metadata from validated fields\n const metadata: SkillMetadata = {\n name: data.name as string,\n description: data.description as string,\n };\n\n // Optional fields\n if (data.license !== undefined) {\n metadata.license = String(data.license);\n }\n\n if (Array.isArray(data.compatibility)) {\n metadata.compatibility = data.compatibility.map(String);\n }\n\n if (data.metadata !== undefined && typeof data.metadata === 'object' && data.metadata !== null) {\n metadata.metadata = data.metadata as Record<string, unknown>;\n }\n\n if (Array.isArray(data['allowed-tools'])) {\n metadata.allowedTools = data['allowed-tools'].map(String);\n }\n\n return {\n success: true,\n metadata,\n body: parsed.content,\n };\n}\n","/**\n * Skill Directory Scanner\n *\n * Scans configured skill roots for directories containing valid SKILL.md files.\n * Returns a list of candidate skill paths for the parser to process.\n */\n\nimport { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';\nimport { resolve, basename } from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:scanner', { level: LogLevel.INFO });\n\n/**\n * Discovered skill candidate — a directory containing a SKILL.md file.\n */\nexport interface SkillCandidate {\n /** Absolute path to the skill directory */\n skillPath: string;\n /** The parent directory name (expected to match the skill name) */\n dirName: string;\n /** Raw content of the SKILL.md file */\n content: string;\n /** Which configured root this came from */\n rootPath: string;\n}\n\n/**\n * Expand `~` prefix to the user's home directory.\n */\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2));\n }\n return p;\n}\n\n/**\n * Scan a single skill root for directories containing SKILL.md.\n *\n * @param rootPath - The root directory to scan (may not exist)\n * @returns Array of valid skill candidates found under this root\n */\nexport function scanSkillRoot(rootPath: string): SkillCandidate[] {\n const resolvedRoot = resolve(expandHome(rootPath));\n const candidates: SkillCandidate[] = [];\n\n if (!existsSync(resolvedRoot)) {\n logger.debug('Skill root does not exist, skipping', { rootPath: resolvedRoot });\n return candidates;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(resolvedRoot);\n } catch (err) {\n logger.warn('Failed to read skill root directory', {\n rootPath: resolvedRoot,\n error: err instanceof Error ? err.message : String(err),\n });\n return candidates;\n }\n\n for (const entry of entries) {\n const entryPath = resolve(resolvedRoot, entry);\n\n // Only process directories\n let stat;\n try {\n stat = statSync(entryPath);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) {\n continue;\n }\n\n // Check for SKILL.md inside the directory\n const skillMdPath = resolve(entryPath, 'SKILL.md');\n if (!existsSync(skillMdPath)) {\n continue;\n }\n\n // Read the SKILL.md content\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n candidates.push({\n skillPath: entryPath,\n dirName: basename(entryPath),\n content,\n rootPath: resolvedRoot,\n });\n } catch (err) {\n logger.warn('Failed to read SKILL.md', {\n path: skillMdPath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n logger.debug('Scanned skill root', {\n rootPath: resolvedRoot,\n candidatesFound: candidates.length,\n });\n\n return candidates;\n}\n\n/**\n * Scan multiple skill roots for directories containing SKILL.md.\n *\n * @param skillRoots - Array of root paths to scan\n * @returns Array of all skill candidates found across all roots\n */\nexport function scanAllSkillRoots(skillRoots: string[]): SkillCandidate[] {\n const allCandidates: SkillCandidate[] = [];\n\n for (const root of skillRoots) {\n const candidates = scanSkillRoot(root);\n allCandidates.push(...candidates);\n }\n\n logger.info('Skill discovery complete', {\n rootsScanned: skillRoots.length,\n totalCandidates: allCandidates.length,\n });\n\n return allCandidates;\n}\n","/**\n * Skill Trust Policy Engine\n *\n * Enforces trust-level-based access control for skill resources.\n * Scripts from untrusted roots are denied by default unless explicitly allowed.\n *\n * Trust levels:\n * - `workspace` — Project-local skills, highest trust. Scripts always allowed.\n * - `trusted` — Explicitly trusted roots. Scripts allowed.\n * - `untrusted` — Community or third-party skills. Scripts denied by default.\n *\n * @see https://agentskills.io/specification\n */\n\nimport type { TrustLevel, TrustPolicyDecision, SkillRootConfig } from './types.js';\nimport { TrustPolicyReason } from './types.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────\n\n/**\n * Resource path prefix that requires trust enforcement.\n *\n * Only resources under `scripts/` are subject to trust policy checks.\n * Other directories (references/, assets/, etc.) are always accessible.\n */\nconst SCRIPT_PATH_PREFIX = 'scripts/';\nconst SCRIPT_PATH_EXACT = 'scripts';\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Normalize a skill root config entry.\n *\n * String entries default to `'untrusted'` trust level for safe defaults.\n *\n * @param root - A string path or SkillRootConfig object\n * @returns Normalized SkillRootConfig with explicit trust level\n */\nexport function normalizeRootConfig(root: string | SkillRootConfig): SkillRootConfig {\n if (typeof root === 'string') {\n return { path: root, trust: 'untrusted' };\n }\n return root;\n}\n\n/**\n * Check whether a resource path refers to a script.\n *\n * A resource is considered a script if its relative path starts with\n * `scripts/` or is exactly `scripts`, after normalizing path separators,\n * stripping leading \"./\" segments, and ignoring case.\n *\n * @param resourcePath - Relative path within the skill directory\n * @returns True if the resource is in the scripts/ directory\n */\nexport function isScriptResource(resourcePath: string): boolean {\n // Normalize to forward slashes and trim for consistent checking\n let normalized = resourcePath.trim().replace(/\\\\/g, '/');\n\n // Collapse repeated separators (e.g., \"scripts//setup.sh\" → \"scripts/setup.sh\")\n normalized = normalized.replace(/\\/+/g, '/');\n\n // Strip leading \"./\" segments (e.g., \"./scripts/setup.sh\" → \"scripts/setup.sh\")\n while (normalized.startsWith('./')) {\n normalized = normalized.slice(2);\n }\n\n // Case-insensitive comparison to handle case-insensitive file systems\n const lower = normalized.toLowerCase();\n\n return lower === SCRIPT_PATH_EXACT\n || lower.startsWith(SCRIPT_PATH_PREFIX);\n}\n\n// ─── Policy Engine ───────────────────────────────────────────────────────\n\n/**\n * Evaluate the trust policy for a resource access request.\n *\n * Non-script resources are always allowed regardless of trust level.\n * Script resources require `workspace` or `trusted` trust, or the\n * `allowUntrustedScripts` override to be enabled.\n *\n * @param resourcePath - Relative path to the resource within the skill directory\n * @param trustLevel - Trust level of the skill's root directory\n * @param allowUntrustedScripts - Override flag to permit untrusted scripts\n * @returns Policy decision with allow/deny, reason code, and message\n */\nexport function evaluateTrustPolicy(\n resourcePath: string,\n trustLevel: TrustLevel,\n allowUntrustedScripts: boolean = false,\n): TrustPolicyDecision {\n // Non-script resources — no policy enforcement needed\n if (!isScriptResource(resourcePath)) {\n return {\n allowed: true,\n reason: TrustPolicyReason.NOT_SCRIPT,\n message: 'Resource is not a script — no trust check required',\n };\n }\n\n // Script resources — check trust level\n switch (trustLevel) {\n case 'workspace':\n return {\n allowed: true,\n reason: TrustPolicyReason.WORKSPACE_TRUST,\n message: 'Script allowed — skill root has workspace trust',\n };\n\n case 'trusted':\n return {\n allowed: true,\n reason: TrustPolicyReason.TRUSTED_ROOT,\n message: 'Script allowed — skill root is explicitly trusted',\n };\n\n case 'untrusted':\n if (allowUntrustedScripts) {\n return {\n allowed: true,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_ALLOWED,\n message: 'Script from untrusted root allowed via allowUntrustedScripts override',\n };\n }\n return {\n allowed: false,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_DENIED,\n message: `Script access denied — skill root is untrusted. ` +\n `Scripts from untrusted roots are blocked by default for security. ` +\n `To allow, set 'allowUntrustedScripts: true' in SkillRegistryConfig or ` +\n `promote the skill root to 'trusted' or 'workspace' trust level.`,\n };\n\n default:\n return {\n allowed: false,\n reason: TrustPolicyReason.UNKNOWN_TRUST_LEVEL,\n message: `Script access denied — trust level \"${trustLevel}\" is unknown and is treated as untrusted for security.`,\n };\n }\n}\n","/**\n * Skill Activation Tools\n *\n * Provides `activate-skill` and `read-skill-resource` tools built with\n * the AgentForge tool builder API. These tools enable agents to load\n * skill instructions on demand and access skill resources at runtime.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const [activateSkill, readSkillResource] = createSkillActivationTools(registry);\n * // activateSkill — load full SKILL.md body\n * // readSkillResource — load a resource file from a skill\n *\n * // Or use the convenience method:\n * const [activateSkill, readSkillResource] = registry.toActivationTools();\n * ```\n */\n\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { resolve, relative, isAbsolute } from 'node:path';\nimport matter from 'gray-matter';\nimport { z } from 'zod';\nimport { ToolBuilder, ToolCategory, createLogger, LogLevel } from '@agentforge/core';\nimport type { Tool } from '@agentforge/core';\nimport type { SkillRegistry } from './registry.js';\nimport { SkillRegistryEvent, TrustPolicyReason } from './types.js';\nimport { evaluateTrustPolicy } from './trust.js';\n\nconst logger = createLogger('agentforge:skills:activation', { level: LogLevel.INFO });\n\n// ─── Schemas ─────────────────────────────────────────────────────────────\n\nconst activateSkillSchema = z.object({\n name: z.string().describe('The name of the skill to activate (e.g., \"code-review\")'),\n});\n\nconst readSkillResourceSchema = z.object({\n name: z.string().describe('The name of the skill that owns the resource'),\n path: z.string().describe('Relative path to the resource file within the skill directory (e.g., \"references/GUIDE.md\", \"scripts/setup.sh\")'),\n});\n\n// ─── Path Security ───────────────────────────────────────────────────────\n\n/**\n * Resolve a resource path within a skill root, blocking path traversal.\n *\n * @param skillPath - Absolute path to the skill directory\n * @param resourcePath - Relative path to the resource file\n * @returns Absolute path to the resource, or an error string\n */\nexport function resolveResourcePath(\n skillPath: string,\n resourcePath: string,\n): { success: true; resolvedPath: string } | { success: false; error: string } {\n // Reject absolute paths using platform-aware check\n if (isAbsolute(resourcePath)) {\n return { success: false, error: 'Absolute resource paths are not allowed' };\n }\n\n // Reject traversal via segment-based '..' detection\n // Split on both '/' and '\\' to handle cross-platform separators\n const segments = resourcePath.split(/[/\\\\]/);\n if (segments.some((seg) => seg === '..')) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Resolve and verify containment (final guard)\n const resolvedPath = resolve(skillPath, resourcePath);\n const resolvedSkillPath = resolve(skillPath);\n\n // Ensure the resolved path is within the skill directory\n const rel = relative(resolvedSkillPath, resolvedPath);\n if (rel.startsWith('..') || resolve(resolvedSkillPath, rel) !== resolvedPath) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Guard against symlink escapes: resolve real filesystem paths and\n // verify that the real target still sits under the real skill root.\n // This prevents a symlink inside the skill dir from pointing outside.\n try {\n const realSkillRoot = realpathSync(resolvedSkillPath);\n const realTarget = realpathSync(resolvedPath);\n const realRel = relative(realSkillRoot, realTarget);\n if (realRel.startsWith('..') || isAbsolute(realRel)) {\n return { success: false, error: 'Symlink target escapes the skill directory — access denied' };\n }\n } catch {\n // File doesn't exist yet (or can't be stat'd) — skip symlink check.\n // The caller (readFileSync) will produce a clear error if missing.\n }\n\n return { success: true, resolvedPath };\n}\n\n// ─── Tool Factories ──────────────────────────────────────────────────────\n\n/**\n * Create the `activate-skill` tool bound to a registry instance.\n *\n * Resolves the skill by name, reads the full SKILL.md file, and returns\n * the body content (below frontmatter).\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createActivateSkillTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof activateSkillSchema>, string> {\n return new ToolBuilder<z.infer<typeof activateSkillSchema>, string>()\n .name('activate-skill')\n .description(\n 'Activate an Agent Skill by name, loading its full instructions. ' +\n 'Returns the complete SKILL.md body content for the named skill. ' +\n 'Use this when you see a relevant skill in <available_skills> and want to follow its instructions.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'activation', 'agent-skills'])\n .schema(activateSkillSchema)\n .implement(async ({ name }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill activation failed — not found', { name, availableCount: availableNames.length });\n return errorMsg;\n }\n\n // Read the full SKILL.md body from disk (progressive disclosure)\n const skillMdPath = resolve(skill.skillPath, 'SKILL.md');\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n\n // Extract body below frontmatter\n const body = extractBody(content);\n\n logger.info('Skill activated', {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_ACTIVATED, {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n return body;\n } catch (error) {\n const errorMsg = `Failed to read skill \"${name}\" instructions: ${error instanceof Error ? error.message : String(error)}`;\n logger.error('Skill activation failed — read error', {\n name,\n skillPath: skill.skillPath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create the `read-skill-resource` tool bound to a registry instance.\n *\n * Resolves the skill by name, validates the resource path (blocking\n * traversal), and returns the file content.\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createReadSkillResourceTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof readSkillResourceSchema>, string> {\n return new ToolBuilder<z.infer<typeof readSkillResourceSchema>, string>()\n .name('read-skill-resource')\n .description(\n 'Read a resource file from an activated Agent Skill. ' +\n 'Returns the content of a file within the skill directory (e.g., references/, scripts/, assets/). ' +\n 'The path must be relative to the skill root and cannot traverse outside it.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'resource', 'agent-skills'])\n .schema(readSkillResourceSchema)\n .implement(async ({ name, path: resourcePath }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill resource load failed — skill not found', { name, resourcePath });\n return errorMsg;\n }\n\n // Resolve and validate the resource path\n const pathResult = resolveResourcePath(skill.skillPath, resourcePath);\n if (!pathResult.success) {\n logger.warn('Skill resource load blocked — path traversal', {\n name,\n resourcePath,\n error: pathResult.error,\n });\n return pathResult.error;\n }\n\n // Enforce trust policy for script resources\n const policyDecision = evaluateTrustPolicy(\n resourcePath,\n skill.trustLevel,\n registry.getAllowUntrustedScripts(),\n );\n\n if (!policyDecision.allowed) {\n logger.warn('Skill resource load blocked — trust policy', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_DENIED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n return policyDecision.message;\n }\n\n // Log allowed policy decisions for auditing (scripts only)\n if (policyDecision.reason !== TrustPolicyReason.NOT_SCRIPT) {\n logger.info('Skill resource trust policy — allowed', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_ALLOWED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n }\n\n try {\n const content = readFileSync(pathResult.resolvedPath, 'utf-8');\n\n logger.info('Skill resource loaded', {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_RESOURCE_LOADED, {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n return content;\n } catch (error) {\n const errorMsg = `Failed to read resource \"${resourcePath}\" from skill \"${name}\": ${error instanceof Error ? error.message : String(error)}`;\n logger.warn('Skill resource load failed — file not found or unreadable', {\n name,\n resourcePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create both skill activation tools bound to a registry instance.\n *\n * @param registry - The SkillRegistry to bind tools to\n * @returns Array of both tools [activate-skill, read-skill-resource]\n */\nexport function createSkillActivationTools(\n registry: SkillRegistry,\n): [Tool<z.infer<typeof activateSkillSchema>, string>, Tool<z.infer<typeof readSkillResourceSchema>, string>] {\n return [\n createActivateSkillTool(registry),\n createReadSkillResourceTool(registry),\n ];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Extract the body content below YAML frontmatter from a SKILL.md file.\n *\n * Delegates to `gray-matter` for consistent frontmatter handling across\n * the codebase (matches `parseSkillContent()` in parser.ts).\n *\n * @param content - The full SKILL.md file content\n * @returns The body content below the frontmatter\n */\nfunction extractBody(content: string): string {\n return matter(content).content.trim();\n}\n","/**\n * Skill Registry\n *\n * Central registry for discovering, storing, and querying Agent Skills.\n * Mirrors ToolRegistry but uses folder-based auto-discovery instead\n * of programmatic registration.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills'],\n * });\n *\n * // Query discovered skills\n * const skill = registry.get('code-review');\n * const allSkills = registry.getAll();\n *\n * // Listen for events\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n\nimport type {\n Skill,\n SkillRegistryConfig,\n SkillPromptOptions,\n SkillEventHandler,\n TrustLevel,\n} from './types.js';\nimport { SkillRegistryEvent } from './types.js';\nimport { scanAllSkillRoots, expandHome } from './scanner.js';\nimport { parseSkillContent } from './parser.js';\nimport { createSkillActivationTools } from './activation.js';\nimport { normalizeRootConfig } from './trust.js';\nimport { resolve as resolvePath } from 'node:path';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:registry', { level: LogLevel.INFO });\n\n/**\n * Skill Registry — auto-discovers skills from configured folder paths.\n *\n * Parallel to ToolRegistry:\n * | ToolRegistry | SkillRegistry |\n * |--------------------------|------------------------------------------|\n * | registry.register(tool) | new SkillRegistry({ skillRoots }) |\n * | registry.get('name') | skillRegistry.get('name') |\n * | registry.getAll() | skillRegistry.getAll() |\n * | registry.has('name') | skillRegistry.has('name') |\n * | registry.size() | skillRegistry.size() |\n * | registry.generatePrompt()| skillRegistry.generatePrompt() |\n * | registry.toLangChainTools()| skillRegistry.toActivationTools() |\n */\nexport class SkillRegistry {\n private skills: Map<string, Skill> = new Map();\n private eventHandlers: Map<SkillRegistryEvent, Set<SkillEventHandler>> = new Map();\n private readonly config: SkillRegistryConfig;\n private scanErrors: Array<{ path: string; error: string }> = [];\n /** Maps resolved root paths → trust levels for skill trust assignment */\n private rootTrustMap: Map<string, TrustLevel> = new Map();\n\n /**\n * Create a SkillRegistry and immediately scan configured roots for skills.\n *\n * @param config - Registry configuration with skill root paths\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills', './project-skills'],\n * });\n * console.log(`Discovered ${registry.size()} skills`);\n * ```\n */\n constructor(config: SkillRegistryConfig) {\n this.config = config;\n this.discover();\n }\n\n /**\n * Scan all configured roots and populate the registry.\n *\n * Called automatically during construction. Can be called again\n * to re-scan (clears existing skills first).\n */\n discover(): void {\n this.skills.clear();\n this.scanErrors = [];\n this.rootTrustMap.clear();\n\n // Normalize roots: extract plain paths for the scanner and build trust map\n const normalizedRoots = this.config.skillRoots.map(normalizeRootConfig);\n const plainPaths = normalizedRoots.map((r) => r.path);\n\n // Build trust map (resolve paths to match scanner output)\n for (const root of normalizedRoots) {\n const resolvedPath = resolvePath(expandHome(root.path));\n this.rootTrustMap.set(resolvedPath, root.trust);\n }\n\n const candidates = scanAllSkillRoots(plainPaths);\n\n let successCount = 0;\n let warningCount = 0;\n\n for (const candidate of candidates) {\n const result = parseSkillContent(candidate.content, candidate.dirName);\n\n if (!result.success) {\n warningCount++;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: result.error || 'Unknown parse error',\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n error: result.error,\n });\n logger.warn('Skipping invalid skill', {\n skillPath: candidate.skillPath,\n error: result.error,\n });\n continue;\n }\n\n const skill: Skill = {\n metadata: result.metadata!,\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n trustLevel: this.rootTrustMap.get(candidate.rootPath) ?? 'untrusted',\n };\n\n // Handle duplicate skill names — first root wins (deterministic precedence)\n if (this.skills.has(skill.metadata.name)) {\n const existing = this.skills.get(skill.metadata.name)!;\n warningCount++;\n const warningMsg = `Duplicate skill name \"${skill.metadata.name}\" from \"${candidate.rootPath}\" — ` +\n `keeping version from \"${existing.rootPath}\" (first root takes precedence)`;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: warningMsg,\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n duplicateOf: existing.skillPath,\n error: warningMsg,\n });\n logger.warn('Duplicate skill name, keeping first', {\n name: skill.metadata.name,\n kept: existing.skillPath,\n skipped: candidate.skillPath,\n });\n continue;\n }\n\n this.skills.set(skill.metadata.name, skill);\n successCount++;\n\n this.emit(SkillRegistryEvent.SKILL_DISCOVERED, skill);\n logger.debug('Skill discovered', {\n name: skill.metadata.name,\n description: skill.metadata.description.slice(0, 80),\n skillPath: skill.skillPath,\n });\n }\n\n logger.info('Skill registry populated', {\n rootsScanned: this.config.skillRoots.length,\n skillsDiscovered: successCount,\n warnings: warningCount,\n });\n }\n\n // ─── Query API (parallel to ToolRegistry) ──────────────────────────────\n\n /**\n * Get a skill by name.\n *\n * @param name - The skill name\n * @returns The skill, or undefined if not found\n *\n * @example\n * ```ts\n * const skill = registry.get('code-review');\n * if (skill) {\n * console.log(skill.metadata.description);\n * }\n * ```\n */\n get(name: string): Skill | undefined {\n return this.skills.get(name);\n }\n\n /**\n * Get all discovered skills.\n *\n * @returns Array of all skills\n *\n * @example\n * ```ts\n * const allSkills = registry.getAll();\n * console.log(`Total skills: ${allSkills.length}`);\n * ```\n */\n getAll(): Skill[] {\n return Array.from(this.skills.values());\n }\n\n /**\n * Check if a skill exists in the registry.\n *\n * @param name - The skill name\n * @returns True if the skill exists\n *\n * @example\n * ```ts\n * if (registry.has('code-review')) {\n * console.log('Skill available!');\n * }\n * ```\n */\n has(name: string): boolean {\n return this.skills.has(name);\n }\n\n /**\n * Get the number of discovered skills.\n *\n * @returns Number of skills in the registry\n *\n * @example\n * ```ts\n * console.log(`Registry has ${registry.size()} skills`);\n * ```\n */\n size(): number {\n return this.skills.size;\n }\n\n /**\n * Get all skill names.\n *\n * @returns Array of skill names\n */\n getNames(): string[] {\n return Array.from(this.skills.keys());\n }\n\n /**\n * Get errors/warnings from the last scan.\n *\n * Useful for diagnostics and observability.\n *\n * @returns Array of scan errors with paths\n */\n getScanErrors(): ReadonlyArray<{ path: string; error: string }> {\n return this.scanErrors;\n }\n\n /**\n * Check whether untrusted script access is allowed via config override.\n *\n * Used by activation tools to pass the override flag to trust policy checks.\n *\n * @returns True if `allowUntrustedScripts` is set in config\n */\n getAllowUntrustedScripts(): boolean {\n return this.config.allowUntrustedScripts ?? false;\n }\n\n /**\n * Get the `allowed-tools` list for a skill.\n *\n * Returns the `allowedTools` array from the skill's frontmatter metadata,\n * enabling agents to filter their tool set based on what the skill expects.\n *\n * @param name - The skill name\n * @returns Array of allowed tool names, or undefined if skill not found or field not set\n *\n * @example\n * ```ts\n * const allowed = registry.getAllowedTools('code-review');\n * if (allowed) {\n * const filteredTools = allTools.filter(t => allowed.includes(t.name));\n * }\n * ```\n */\n getAllowedTools(name: string): string[] | undefined {\n const skill = this.skills.get(name);\n return skill?.metadata.allowedTools;\n }\n\n // ─── Prompt Generation ─────────────────────────────────────────────────\n\n /**\n * Generate an `<available_skills>` XML block for system prompt injection.\n *\n * Returns an empty string when:\n * - `config.enabled` is `false` (default) — agents operate with unmodified prompts\n * - No skills match the filter criteria\n *\n * The output composes naturally with `toolRegistry.generatePrompt()` —\n * simply concatenate both into the system prompt.\n *\n * @param options - Optional filtering (subset of skill names)\n * @returns XML string or empty string\n *\n * @example\n * ```ts\n * // All skills\n * const xml = registry.generatePrompt();\n *\n * // Subset for a focused agent\n * const xml = registry.generatePrompt({ skills: ['code-review', 'testing'] });\n *\n * // Compose with tool prompt\n * const systemPrompt = [\n * toolRegistry.generatePrompt(),\n * skillRegistry.generatePrompt(),\n * ].filter(Boolean).join('\\n\\n');\n * ```\n */\n generatePrompt(options?: SkillPromptOptions): string {\n // Feature flag gate — disabled by default\n if (!this.config.enabled) {\n logger.debug('Skill prompt generation skipped (disabled)', {\n enabled: this.config.enabled ?? false,\n });\n return '';\n }\n\n // Resolve which skills to include\n let skills = this.getAll();\n\n // Apply subset filter if provided\n if (options?.skills && options.skills.length > 0) {\n const requested = new Set(options.skills);\n skills = skills.filter((s) => requested.has(s.metadata.name));\n }\n\n // Apply maxDiscoveredSkills cap\n if (this.config.maxDiscoveredSkills !== undefined && this.config.maxDiscoveredSkills >= 0) {\n skills = skills.slice(0, this.config.maxDiscoveredSkills);\n }\n\n // No skills — return empty string\n if (skills.length === 0) {\n logger.debug('Skill prompt generation produced empty result', {\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n maxCap: this.config.maxDiscoveredSkills,\n });\n return '';\n }\n\n // Generate XML\n const skillEntries = skills.map((skill) => {\n const lines = [\n ' <skill>',\n ` <name>${escapeXml(skill.metadata.name)}</name>`,\n ` <description>${escapeXml(skill.metadata.description)}</description>`,\n ` <location>${escapeXml(skill.skillPath)}</location>`,\n ' </skill>',\n ];\n return lines.join('\\n');\n });\n\n const xml = `<available_skills>\\n${skillEntries.join('\\n')}\\n</available_skills>`;\n\n // Estimate token count (~4 chars per token, rough heuristic)\n const estimatedTokens = Math.ceil(xml.length / 4);\n\n logger.info('Skill prompt generated', {\n skillCount: skills.length,\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n maxCap: this.config.maxDiscoveredSkills,\n estimatedTokens,\n xmlLength: xml.length,\n });\n\n return xml;\n }\n\n // ─── Event System ──────────────────────────────────────────────────────\n\n /**\n * Register an event handler.\n *\n * @param event - The event to listen for\n * @param handler - The handler function\n *\n * @example\n * ```ts\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n on(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * Unregister an event handler.\n *\n * @param event - The event to stop listening for\n * @param handler - The handler function to remove\n */\n off(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n\n /**\n * Emit an event to all registered handlers.\n *\n * @param event - The event to emit\n * @param data - The event data\n * @private\n */\n private emit(event: SkillRegistryEvent, data: unknown): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(data);\n } catch (error) {\n logger.error('Skill event handler error', {\n event,\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n });\n }\n }\n\n /**\n * Emit an event (public API for activation tools).\n *\n * Used by skill activation tools to emit `skill:activated` and\n * `skill:resource-loaded` events through the registry's event system.\n *\n * @param event - The event to emit\n * @param data - The event data\n */\n emitEvent(event: SkillRegistryEvent, data: unknown): void {\n this.emit(event, data);\n }\n\n // ─── Tool Integration ────────────────────────────────────────────────\n\n /**\n * Create activation tools pre-wired to this registry instance.\n *\n * Returns `activate-skill` and `read-skill-resource` tools that\n * agents can use to load skill instructions and resources on demand.\n *\n * @returns Array of [activate-skill, read-skill-resource] tools\n *\n * @example\n * ```ts\n * const agent = createReActAgent({\n * model: llm,\n * tools: [\n * ...toolRegistry.toLangChainTools(),\n * ...skillRegistry.toActivationTools(),\n * ],\n * });\n * ```\n */\n toActivationTools(): ReturnType<typeof createSkillActivationTools> {\n return createSkillActivationTools(this);\n }\n}\n\n/**\n * Escape special XML characters in a string.\n *\n * @param str - The string to escape\n * @returns Escaped string safe for XML content\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/parser.ts","../src/scanner.ts","../src/trust.ts","../src/activation.ts","../src/registry.ts"],"names":["TrustPolicyReason","SkillRegistryEvent","matter","createLogger","LogLevel","resolve","homedir","existsSync","readdirSync","statSync","readFileSync","basename","logger","z","isAbsolute","relative","realpathSync","ToolBuilder","ToolCategory","resolvePath"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Skill System Types\n *\n * Core type definitions for the AgentForge Agent Skills system.\n * These types align with the Agent Skills specification (https://agentskills.io/specification).\n */\n\n// ─── Trust Policy Types ──────────────────────────────────────────────────\n\n/**\n * Trust level for a skill root directory.\n *\n * - `workspace` — Skills from the project workspace (highest trust, scripts allowed)\n * - `trusted` — Explicitly trusted skill roots (scripts allowed)\n * - `untrusted` — Untrusted roots like community packs (scripts blocked by default)\n */\nexport type TrustLevel = 'workspace' | 'trusted' | 'untrusted';\n\n/**\n * Configuration for a skill root with an explicit trust level.\n *\n * @example\n * ```ts\n * const roots: SkillRootConfig[] = [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community-skills', trust: 'untrusted' },\n * ];\n * ```\n */\nexport interface SkillRootConfig {\n /** Directory path to scan for skills */\n path: string;\n /** Trust level assigned to all skills discovered from this root */\n trust: TrustLevel;\n}\n\n/**\n * Policy decision returned by trust enforcement checks.\n */\nexport interface TrustPolicyDecision {\n /** Whether the action is allowed */\n allowed: boolean;\n /** Machine-readable reason code for auditing */\n reason: TrustPolicyReason;\n /** Human-readable explanation */\n message: string;\n}\n\n/**\n * Reason codes for trust policy decisions.\n *\n * Used for structured logging and auditing of guardrail behavior.\n */\nexport enum TrustPolicyReason {\n /** Resource is not a script — no trust check needed */\n NOT_SCRIPT = 'not-script',\n /** Skill root has workspace trust — scripts allowed */\n WORKSPACE_TRUST = 'workspace-trust',\n /** Skill root has explicit trusted status — scripts allowed */\n TRUSTED_ROOT = 'trusted-root',\n /** Skill root is untrusted — scripts denied by default */\n UNTRUSTED_SCRIPT_DENIED = 'untrusted-script-denied',\n /** Untrusted script access was explicitly allowed via config override */\n UNTRUSTED_SCRIPT_ALLOWED = 'untrusted-script-allowed-override',\n /** Trust level is unknown — treated as untrusted for security */\n UNKNOWN_TRUST_LEVEL = 'unknown-trust-level',\n}\n\n/**\n * Parsed metadata from a SKILL.md frontmatter block.\n *\n * Required fields: `name`, `description`.\n * All other fields are optional per the Agent Skills spec.\n */\nexport interface SkillMetadata {\n /** Skill name (1-64 chars, lowercase alphanumeric + hyphens, must match parent dir name) */\n name: string;\n /** Human-readable description (1-1024 chars) */\n description: string;\n /** SPDX license identifier */\n license?: string;\n /** List of compatible agent frameworks / tool hosts */\n compatibility?: string[];\n /** Arbitrary key-value metadata (author, version, etc.) */\n metadata?: Record<string, unknown>;\n /** Tools that this skill is allowed to use */\n allowedTools?: string[];\n}\n\n/**\n * A fully resolved skill entry in the registry.\n *\n * Contains parsed metadata plus internal tracking fields\n * that are not part of the SKILL.md frontmatter.\n */\nexport interface Skill {\n /** Parsed frontmatter metadata */\n metadata: SkillMetadata;\n /** Absolute path to the skill directory */\n skillPath: string;\n /** Which configured skill root this was discovered from */\n rootPath: string;\n /** Trust level assigned to this skill (inherited from root config) */\n trustLevel: TrustLevel;\n}\n\n/**\n * Configuration for the SkillRegistry.\n */\nexport interface SkillRegistryConfig {\n /**\n * Array of directory paths to scan for skills.\n *\n * Each entry can be a plain string (defaults to `'untrusted'` trust level)\n * or a `SkillRootConfig` object with an explicit trust level.\n *\n * Paths may be absolute or relative (resolved against `cwd`).\n * The `~` prefix is expanded to `$HOME`.\n *\n * @example\n * ```ts\n * // Simple string roots (default to 'untrusted')\n * skillRoots: ['.agentskills', '~/.agentskills']\n *\n * // Trust-aware roots\n * skillRoots: [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community', trust: 'untrusted' },\n * ]\n * ```\n */\n skillRoots: Array<string | SkillRootConfig>;\n\n /**\n * Feature flag to enable Agent Skills in system prompts.\n *\n * When `false` (default), `generatePrompt()` returns an empty string\n * so agents operate with unmodified system prompts.\n *\n * @default false\n */\n enabled?: boolean;\n\n /**\n * Maximum number of skills to include in generated prompts.\n *\n * Caps prompt token usage when many skills are discovered.\n * Skills are included in discovery order (first root first).\n * When undefined, all discovered skills are included.\n */\n maxDiscoveredSkills?: number;\n\n /**\n * Allow script resources from untrusted roots.\n *\n * When `true`, scripts from `scripts/` directories in untrusted\n * skill roots are returned instead of being denied. This disables\n * the default-deny policy for untrusted scripts.\n *\n * **Security warning:** Only enable when you have reviewed all\n * skill packs from untrusted roots.\n *\n * @default false\n */\n allowUntrustedScripts?: boolean;\n}\n\n/**\n * Options for `SkillRegistry.generatePrompt()`.\n */\nexport interface SkillPromptOptions {\n /**\n * Subset of skill names to include in the generated prompt.\n *\n * When provided, only skills matching these names appear in the\n * `<available_skills>` XML block. This enables creating focused\n * agents with different skill sets from the same registry.\n *\n * When omitted or empty, all discovered skills are included.\n *\n * @example ['code-review', 'testing-strategy']\n */\n skills?: string[];\n}\n\n/**\n * Events emitted by the SkillRegistry during discovery and usage.\n */\nexport enum SkillRegistryEvent {\n /** Emitted when a valid skill is discovered during scanning */\n SKILL_DISCOVERED = 'skill:discovered',\n /** Emitted when a skill parse or validation issue is encountered */\n SKILL_WARNING = 'skill:warning',\n /** Emitted when a skill is activated (full body loaded) */\n SKILL_ACTIVATED = 'skill:activated',\n /** Emitted when a skill resource file is loaded */\n SKILL_RESOURCE_LOADED = 'skill:resource-loaded',\n /** Emitted when a trust policy denies access to a resource */\n TRUST_POLICY_DENIED = 'trust:policy-denied',\n /** Emitted when a trust policy allows access (for auditing) */\n TRUST_POLICY_ALLOWED = 'trust:policy-allowed',\n}\n\n/**\n * Event handler type for skill registry events.\n */\nexport type SkillEventHandler = (data: unknown) => void;\n\n/**\n * Result of parsing a single SKILL.md file.\n */\nexport interface SkillParseResult {\n /** Whether parsing and validation succeeded */\n success: boolean;\n /** Parsed metadata (present when success is true) */\n metadata?: SkillMetadata;\n /** The raw markdown body below the frontmatter (present when success is true) */\n body?: string;\n /** Error description (present when success is false) */\n error?: string;\n}\n\n/**\n * Validation error detail.\n */\nexport interface SkillValidationError {\n /** Which field failed validation */\n field: string;\n /** Human-readable error message */\n message: string;\n}\n","/**\n * SKILL.md Frontmatter Parser\n *\n * Parses YAML frontmatter from SKILL.md files and validates\n * against the Agent Skills specification constraints.\n *\n * @see https://agentskills.io/specification\n */\n\nimport matter from 'gray-matter';\nimport type { SkillMetadata, SkillParseResult, SkillValidationError } from './types.js';\n\n/**\n * Skill name validation constraints (per spec).\n *\n * - 1-64 characters\n * - Lowercase alphanumeric and hyphens only\n * - No leading, trailing, or consecutive hyphens\n */\nconst SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\nconst SKILL_NAME_MAX_LENGTH = 64;\nconst SKILL_DESCRIPTION_MAX_LENGTH = 1024;\n\n/**\n * Validate the `name` field per the Agent Skills spec.\n *\n * @param name - The name value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillName(name: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (name === undefined || name === null) {\n errors.push({ field: 'name', message: 'name is required' });\n return errors;\n }\n\n if (typeof name !== 'string') {\n errors.push({ field: 'name', message: 'name must be a string' });\n return errors;\n }\n\n if (name.length === 0) {\n errors.push({ field: 'name', message: 'name must not be empty' });\n return errors;\n }\n\n if (name.length > SKILL_NAME_MAX_LENGTH) {\n errors.push({\n field: 'name',\n message: `name must be at most ${SKILL_NAME_MAX_LENGTH} characters (got ${name.length})`,\n });\n return errors;\n }\n\n if (!SKILL_NAME_PATTERN.test(name)) {\n errors.push({\n field: 'name',\n message: 'name must be lowercase alphanumeric with hyphens, no leading/trailing/consecutive hyphens',\n });\n }\n\n if (name.includes('--')) {\n errors.push({\n field: 'name',\n message: 'name must not contain consecutive hyphens',\n });\n }\n\n return errors;\n}\n\n/**\n * Validate the `description` field per the Agent Skills spec.\n *\n * @param description - The description value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillDescription(description: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (description === undefined || description === null) {\n errors.push({ field: 'description', message: 'description is required' });\n return errors;\n }\n\n if (typeof description !== 'string') {\n errors.push({ field: 'description', message: 'description must be a string' });\n return errors;\n }\n\n if (description.trim().length === 0) {\n errors.push({ field: 'description', message: 'description must not be empty' });\n return errors;\n }\n\n if (description.length > SKILL_DESCRIPTION_MAX_LENGTH) {\n errors.push({\n field: 'description',\n message: `description must be at most ${SKILL_DESCRIPTION_MAX_LENGTH} characters (got ${description.length})`,\n });\n }\n\n return errors;\n}\n\n/**\n * Validate that the skill name matches its parent directory name (per spec).\n *\n * @param name - The name from frontmatter\n * @param dirName - The parent directory name\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillNameMatchesDir(name: string, dirName: string): SkillValidationError[] {\n if (name !== dirName) {\n return [{\n field: 'name',\n message: `name \"${name}\" must match parent directory name \"${dirName}\"`,\n }];\n }\n return [];\n}\n\n/**\n * Parse and validate a SKILL.md file's raw content.\n *\n * Extracts YAML frontmatter using gray-matter, then validates\n * required and optional fields against spec constraints.\n *\n * @param content - Raw file content of the SKILL.md\n * @param dirName - Parent directory name for name-match validation\n * @returns Parse result with metadata or error\n */\nexport function parseSkillContent(content: string, dirName: string): SkillParseResult {\n let parsed: matter.GrayMatterFile<string>;\n\n try {\n parsed = matter(content);\n } catch (err) {\n return {\n success: false,\n error: `Failed to parse frontmatter: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n const data = parsed.data;\n\n // Validate required fields\n const errors: SkillValidationError[] = [\n ...validateSkillName(data.name),\n ...validateSkillDescription(data.description),\n ];\n\n // If name is valid, validate it matches directory name\n if (typeof data.name === 'string' && data.name.length > 0 && SKILL_NAME_PATTERN.test(data.name)) {\n errors.push(...validateSkillNameMatchesDir(data.name, dirName));\n }\n\n if (errors.length > 0) {\n return {\n success: false,\n error: errors.map((e) => `${e.field}: ${e.message}`).join('; '),\n };\n }\n\n // Build metadata from validated fields\n const metadata: SkillMetadata = {\n name: data.name as string,\n description: data.description as string,\n };\n\n // Optional fields\n if (data.license !== undefined) {\n metadata.license = String(data.license);\n }\n\n if (Array.isArray(data.compatibility)) {\n metadata.compatibility = data.compatibility.map(String);\n }\n\n if (data.metadata !== undefined && typeof data.metadata === 'object' && data.metadata !== null) {\n metadata.metadata = data.metadata as Record<string, unknown>;\n }\n\n if (Array.isArray(data['allowed-tools'])) {\n metadata.allowedTools = data['allowed-tools'].map(String);\n }\n\n return {\n success: true,\n metadata,\n body: parsed.content,\n };\n}\n","/**\n * Skill Directory Scanner\n *\n * Scans configured skill roots for directories containing valid SKILL.md files.\n * Returns a list of candidate skill paths for the parser to process.\n */\n\nimport { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';\nimport { resolve, basename } from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:scanner', { level: LogLevel.INFO });\n\n/**\n * Discovered skill candidate — a directory containing a SKILL.md file.\n */\nexport interface SkillCandidate {\n /** Absolute path to the skill directory */\n skillPath: string;\n /** The parent directory name (expected to match the skill name) */\n dirName: string;\n /** Raw content of the SKILL.md file */\n content: string;\n /** Which configured root this came from */\n rootPath: string;\n}\n\n/**\n * Expand `~` prefix to the user's home directory.\n */\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2));\n }\n return p;\n}\n\n/**\n * Scan a single skill root for directories containing SKILL.md.\n *\n * @param rootPath - The root directory to scan (may not exist)\n * @returns Array of valid skill candidates found under this root\n */\nexport function scanSkillRoot(rootPath: string): SkillCandidate[] {\n const resolvedRoot = resolve(expandHome(rootPath));\n const candidates: SkillCandidate[] = [];\n\n if (!existsSync(resolvedRoot)) {\n logger.debug('Skill root does not exist, skipping', { rootPath: resolvedRoot });\n return candidates;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(resolvedRoot);\n } catch (err) {\n logger.warn('Failed to read skill root directory', {\n rootPath: resolvedRoot,\n error: err instanceof Error ? err.message : String(err),\n });\n return candidates;\n }\n\n for (const entry of entries) {\n const entryPath = resolve(resolvedRoot, entry);\n\n // Only process directories\n let stat;\n try {\n stat = statSync(entryPath);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) {\n continue;\n }\n\n // Check for SKILL.md inside the directory\n const skillMdPath = resolve(entryPath, 'SKILL.md');\n if (!existsSync(skillMdPath)) {\n continue;\n }\n\n // Read the SKILL.md content\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n candidates.push({\n skillPath: entryPath,\n dirName: basename(entryPath),\n content,\n rootPath: resolvedRoot,\n });\n } catch (err) {\n logger.warn('Failed to read SKILL.md', {\n path: skillMdPath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n logger.debug('Scanned skill root', {\n rootPath: resolvedRoot,\n candidatesFound: candidates.length,\n });\n\n return candidates;\n}\n\n/**\n * Scan multiple skill roots for directories containing SKILL.md.\n *\n * @param skillRoots - Array of root paths to scan\n * @returns Array of all skill candidates found across all roots\n */\nexport function scanAllSkillRoots(skillRoots: string[]): SkillCandidate[] {\n const allCandidates: SkillCandidate[] = [];\n\n for (const root of skillRoots) {\n const candidates = scanSkillRoot(root);\n allCandidates.push(...candidates);\n }\n\n logger.info('Skill discovery complete', {\n rootsScanned: skillRoots.length,\n totalCandidates: allCandidates.length,\n });\n\n return allCandidates;\n}\n","/**\n * Skill Trust Policy Engine\n *\n * Enforces trust-level-based access control for skill resources.\n * Scripts from untrusted roots are denied by default unless explicitly allowed.\n *\n * Trust levels:\n * - `workspace` — Project-local skills, highest trust. Scripts always allowed.\n * - `trusted` — Explicitly trusted roots. Scripts allowed.\n * - `untrusted` — Community or third-party skills. Scripts denied by default.\n *\n * @see https://agentskills.io/specification\n */\n\nimport type { TrustLevel, TrustPolicyDecision, SkillRootConfig } from './types.js';\nimport { TrustPolicyReason } from './types.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────\n\n/**\n * Resource path prefix that requires trust enforcement.\n *\n * Only resources under `scripts/` are subject to trust policy checks.\n * Other directories (references/, assets/, etc.) are always accessible.\n */\nconst SCRIPT_PATH_PREFIX = 'scripts/';\nconst SCRIPT_PATH_EXACT = 'scripts';\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Normalize a skill root config entry.\n *\n * String entries default to `'untrusted'` trust level for safe defaults.\n *\n * @param root - A string path or SkillRootConfig object\n * @returns Normalized SkillRootConfig with explicit trust level\n */\nexport function normalizeRootConfig(root: string | SkillRootConfig): SkillRootConfig {\n if (typeof root === 'string') {\n return { path: root, trust: 'untrusted' };\n }\n return root;\n}\n\n/**\n * Check whether a resource path refers to a script.\n *\n * A resource is considered a script if its relative path starts with\n * `scripts/` or is exactly `scripts`, after normalizing path separators,\n * stripping leading \"./\" segments, and ignoring case.\n *\n * @param resourcePath - Relative path within the skill directory\n * @returns True if the resource is in the scripts/ directory\n */\nexport function isScriptResource(resourcePath: string): boolean {\n // Normalize to forward slashes and trim for consistent checking\n let normalized = resourcePath.trim().replace(/\\\\/g, '/');\n\n // Collapse repeated separators (e.g., \"scripts//setup.sh\" → \"scripts/setup.sh\")\n normalized = normalized.replace(/\\/+/g, '/');\n\n // Strip leading \"./\" segments (e.g., \"./scripts/setup.sh\" → \"scripts/setup.sh\")\n while (normalized.startsWith('./')) {\n normalized = normalized.slice(2);\n }\n\n // Case-insensitive comparison to handle case-insensitive file systems\n const lower = normalized.toLowerCase();\n\n return lower === SCRIPT_PATH_EXACT\n || lower.startsWith(SCRIPT_PATH_PREFIX);\n}\n\n// ─── Policy Engine ───────────────────────────────────────────────────────\n\n/**\n * Evaluate the trust policy for a resource access request.\n *\n * Non-script resources are always allowed regardless of trust level.\n * Script resources require `workspace` or `trusted` trust, or the\n * `allowUntrustedScripts` override to be enabled.\n *\n * @param resourcePath - Relative path to the resource within the skill directory\n * @param trustLevel - Trust level of the skill's root directory\n * @param allowUntrustedScripts - Override flag to permit untrusted scripts\n * @returns Policy decision with allow/deny, reason code, and message\n */\nexport function evaluateTrustPolicy(\n resourcePath: string,\n trustLevel: TrustLevel,\n allowUntrustedScripts: boolean = false,\n): TrustPolicyDecision {\n // Non-script resources — no policy enforcement needed\n if (!isScriptResource(resourcePath)) {\n return {\n allowed: true,\n reason: TrustPolicyReason.NOT_SCRIPT,\n message: 'Resource is not a script — no trust check required',\n };\n }\n\n // Script resources — check trust level\n switch (trustLevel) {\n case 'workspace':\n return {\n allowed: true,\n reason: TrustPolicyReason.WORKSPACE_TRUST,\n message: 'Script allowed — skill root has workspace trust',\n };\n\n case 'trusted':\n return {\n allowed: true,\n reason: TrustPolicyReason.TRUSTED_ROOT,\n message: 'Script allowed — skill root is explicitly trusted',\n };\n\n case 'untrusted':\n if (allowUntrustedScripts) {\n return {\n allowed: true,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_ALLOWED,\n message: 'Script from untrusted root allowed via allowUntrustedScripts override',\n };\n }\n return {\n allowed: false,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_DENIED,\n message: `Script access denied — skill root is untrusted. ` +\n `Scripts from untrusted roots are blocked by default for security. ` +\n `To allow, set 'allowUntrustedScripts: true' in SkillRegistryConfig or ` +\n `promote the skill root to 'trusted' or 'workspace' trust level.`,\n };\n\n default:\n return {\n allowed: false,\n reason: TrustPolicyReason.UNKNOWN_TRUST_LEVEL,\n message: `Script access denied — trust level \"${trustLevel}\" is unknown and is treated as untrusted for security.`,\n };\n }\n}\n","/**\n * Skill Activation Tools\n *\n * Provides `activate-skill` and `read-skill-resource` tools built with\n * the AgentForge tool builder API. These tools enable agents to load\n * skill instructions on demand and access skill resources at runtime.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const [activateSkill, readSkillResource] = createSkillActivationTools(registry);\n * // activateSkill — load full SKILL.md body\n * // readSkillResource — load a resource file from a skill\n *\n * // Or use the convenience method:\n * const [activateSkill, readSkillResource] = registry.toActivationTools();\n * ```\n */\n\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { resolve, relative, isAbsolute } from 'node:path';\nimport matter from 'gray-matter';\nimport { z } from 'zod';\nimport { ToolBuilder, ToolCategory, createLogger, LogLevel } from '@agentforge/core';\nimport type { Tool } from '@agentforge/core';\nimport type { SkillRegistry } from './registry.js';\nimport { SkillRegistryEvent, TrustPolicyReason } from './types.js';\nimport { evaluateTrustPolicy } from './trust.js';\n\nconst logger = createLogger('agentforge:skills:activation', { level: LogLevel.INFO });\n\n// ─── Schemas ─────────────────────────────────────────────────────────────\n\nconst activateSkillSchema = z.object({\n name: z.string().describe('The name of the skill to activate (e.g., \"code-review\")'),\n});\n\nconst readSkillResourceSchema = z.object({\n name: z.string().describe('The name of the skill that owns the resource'),\n path: z.string().describe('Relative path to the resource file within the skill directory (e.g., \"references/GUIDE.md\", \"scripts/setup.sh\")'),\n});\n\n// ─── Path Security ───────────────────────────────────────────────────────\n\n/**\n * Resolve a resource path within a skill root, blocking path traversal.\n *\n * @param skillPath - Absolute path to the skill directory\n * @param resourcePath - Relative path to the resource file\n * @returns Absolute path to the resource, or an error string\n */\nexport function resolveResourcePath(\n skillPath: string,\n resourcePath: string,\n): { success: true; resolvedPath: string } | { success: false; error: string } {\n // Reject absolute paths using platform-aware check\n if (isAbsolute(resourcePath)) {\n return { success: false, error: 'Absolute resource paths are not allowed' };\n }\n\n // Reject traversal via segment-based '..' detection\n // Split on both '/' and '\\' to handle cross-platform separators\n const segments = resourcePath.split(/[/\\\\]/);\n if (segments.some((seg) => seg === '..')) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Resolve and verify containment (final guard)\n const resolvedPath = resolve(skillPath, resourcePath);\n const resolvedSkillPath = resolve(skillPath);\n\n // Ensure the resolved path is within the skill directory\n const rel = relative(resolvedSkillPath, resolvedPath);\n if (rel.startsWith('..') || resolve(resolvedSkillPath, rel) !== resolvedPath) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Guard against symlink escapes: resolve real filesystem paths and\n // verify that the real target still sits under the real skill root.\n // This prevents a symlink inside the skill dir from pointing outside.\n try {\n const realSkillRoot = realpathSync(resolvedSkillPath);\n const realTarget = realpathSync(resolvedPath);\n const realRel = relative(realSkillRoot, realTarget);\n if (realRel.startsWith('..') || isAbsolute(realRel)) {\n return { success: false, error: 'Symlink target escapes the skill directory — access denied' };\n }\n } catch {\n // File doesn't exist yet (or can't be stat'd) — skip symlink check.\n // The caller (readFileSync) will produce a clear error if missing.\n }\n\n return { success: true, resolvedPath };\n}\n\n// ─── Tool Factories ──────────────────────────────────────────────────────\n\n/**\n * Create the `activate-skill` tool bound to a registry instance.\n *\n * Resolves the skill by name, reads the full SKILL.md file, and returns\n * the body content (below frontmatter).\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createActivateSkillTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof activateSkillSchema>, string> {\n return new ToolBuilder<z.infer<typeof activateSkillSchema>, string>()\n .name('activate-skill')\n .description(\n 'Activate an Agent Skill by name, loading its full instructions. ' +\n 'Returns the complete SKILL.md body content for the named skill. ' +\n 'Use this when you see a relevant skill in <available_skills> and want to follow its instructions.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'activation', 'agent-skills'])\n .schema(activateSkillSchema)\n .implement(async ({ name }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill activation failed — not found', { name, availableCount: availableNames.length });\n return errorMsg;\n }\n\n // Read the full SKILL.md body from disk (progressive disclosure)\n const skillMdPath = resolve(skill.skillPath, 'SKILL.md');\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n\n // Extract body below frontmatter\n const body = extractBody(content);\n\n logger.info('Skill activated', {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_ACTIVATED, {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n return body;\n } catch (error) {\n const errorMsg = `Failed to read skill \"${name}\" instructions: ${error instanceof Error ? error.message : String(error)}`;\n logger.error('Skill activation failed — read error', {\n name,\n skillPath: skill.skillPath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create the `read-skill-resource` tool bound to a registry instance.\n *\n * Resolves the skill by name, validates the resource path (blocking\n * traversal), and returns the file content.\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createReadSkillResourceTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof readSkillResourceSchema>, string> {\n return new ToolBuilder<z.infer<typeof readSkillResourceSchema>, string>()\n .name('read-skill-resource')\n .description(\n 'Read a resource file from an activated Agent Skill. ' +\n 'Returns the content of a file within the skill directory (e.g., references/, scripts/, assets/). ' +\n 'The path must be relative to the skill root and cannot traverse outside it.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'resource', 'agent-skills'])\n .schema(readSkillResourceSchema)\n .implement(async ({ name, path: resourcePath }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill resource load failed — skill not found', { name, resourcePath });\n return errorMsg;\n }\n\n // Resolve and validate the resource path\n const pathResult = resolveResourcePath(skill.skillPath, resourcePath);\n if (!pathResult.success) {\n logger.warn('Skill resource load blocked — path traversal', {\n name,\n resourcePath,\n error: pathResult.error,\n });\n return pathResult.error;\n }\n\n // Enforce trust policy for script resources\n const policyDecision = evaluateTrustPolicy(\n resourcePath,\n skill.trustLevel,\n registry.getAllowUntrustedScripts(),\n );\n\n if (!policyDecision.allowed) {\n logger.warn('Skill resource load blocked — trust policy', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_DENIED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n return policyDecision.message;\n }\n\n // Log allowed policy decisions for auditing (scripts only)\n if (policyDecision.reason !== TrustPolicyReason.NOT_SCRIPT) {\n logger.info('Skill resource trust policy — allowed', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_ALLOWED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n }\n\n try {\n const content = readFileSync(pathResult.resolvedPath, 'utf-8');\n\n logger.info('Skill resource loaded', {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_RESOURCE_LOADED, {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n return content;\n } catch (error) {\n const errorMsg = `Failed to read resource \"${resourcePath}\" from skill \"${name}\": ${error instanceof Error ? error.message : String(error)}`;\n logger.warn('Skill resource load failed — file not found or unreadable', {\n name,\n resourcePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create both skill activation tools bound to a registry instance.\n *\n * @param registry - The SkillRegistry to bind tools to\n * @returns Array of both tools [activate-skill, read-skill-resource]\n */\nexport function createSkillActivationTools(\n registry: SkillRegistry,\n): [Tool<z.infer<typeof activateSkillSchema>, string>, Tool<z.infer<typeof readSkillResourceSchema>, string>] {\n return [\n createActivateSkillTool(registry),\n createReadSkillResourceTool(registry),\n ];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Extract the body content below YAML frontmatter from a SKILL.md file.\n *\n * Delegates to `gray-matter` for consistent frontmatter handling across\n * the codebase (matches `parseSkillContent()` in parser.ts).\n *\n * @param content - The full SKILL.md file content\n * @returns The body content below the frontmatter\n */\nfunction extractBody(content: string): string {\n return matter(content).content.trim();\n}\n","/**\n * Skill Registry\n *\n * Central registry for discovering, storing, and querying Agent Skills.\n * Mirrors ToolRegistry but uses folder-based auto-discovery instead\n * of programmatic registration.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills'],\n * });\n *\n * // Query discovered skills\n * const skill = registry.get('code-review');\n * const allSkills = registry.getAll();\n *\n * // Listen for events\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n\nimport type {\n Skill,\n SkillRegistryConfig,\n SkillPromptOptions,\n SkillEventHandler,\n TrustLevel,\n} from './types.js';\nimport { SkillRegistryEvent } from './types.js';\nimport { scanAllSkillRoots, expandHome } from './scanner.js';\nimport { parseSkillContent } from './parser.js';\nimport { createSkillActivationTools } from './activation.js';\nimport { normalizeRootConfig } from './trust.js';\nimport { resolve as resolvePath } from 'node:path';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:registry', { level: LogLevel.INFO });\n\n/**\n * Skill Registry — auto-discovers skills from configured folder paths.\n *\n * Parallel to ToolRegistry:\n * | ToolRegistry | SkillRegistry |\n * |--------------------------|------------------------------------------|\n * | registry.register(tool) | new SkillRegistry({ skillRoots }) |\n * | registry.get('name') | skillRegistry.get('name') |\n * | registry.getAll() | skillRegistry.getAll() |\n * | registry.has('name') | skillRegistry.has('name') |\n * | registry.size() | skillRegistry.size() |\n * | registry.generatePrompt()| skillRegistry.generatePrompt() |\n * | registry.toLangChainTools()| skillRegistry.toActivationTools() |\n */\nexport class SkillRegistry {\n private skills: Map<string, Skill> = new Map();\n private eventHandlers: Map<SkillRegistryEvent, Set<SkillEventHandler>> = new Map();\n private readonly config: SkillRegistryConfig;\n private scanErrors: Array<{ path: string; error: string }> = [];\n /** Maps resolved root paths → trust levels for skill trust assignment */\n private rootTrustMap: Map<string, TrustLevel> = new Map();\n\n /**\n * Create a SkillRegistry and immediately scan configured roots for skills.\n *\n * @param config - Registry configuration with skill root paths\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills', './project-skills'],\n * });\n * console.log(`Discovered ${registry.size()} skills`);\n * ```\n */\n constructor(config: SkillRegistryConfig) {\n this.config = config;\n this.discover();\n }\n\n /**\n * Scan all configured roots and populate the registry.\n *\n * Called automatically during construction. Can be called again\n * to re-scan (clears existing skills first).\n */\n discover(): void {\n this.skills.clear();\n this.scanErrors = [];\n this.rootTrustMap.clear();\n\n // Normalize roots: extract plain paths for the scanner and build trust map\n const normalizedRoots = this.config.skillRoots.map(normalizeRootConfig);\n const plainPaths = normalizedRoots.map((r) => r.path);\n\n // Build trust map (resolve paths to match scanner output)\n for (const root of normalizedRoots) {\n const resolvedPath = resolvePath(expandHome(root.path));\n this.rootTrustMap.set(resolvedPath, root.trust);\n }\n\n const candidates = scanAllSkillRoots(plainPaths);\n\n let successCount = 0;\n let warningCount = 0;\n\n for (const candidate of candidates) {\n const result = parseSkillContent(candidate.content, candidate.dirName);\n\n if (!result.success) {\n warningCount++;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: result.error || 'Unknown parse error',\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n error: result.error,\n });\n logger.warn('Skipping invalid skill', {\n skillPath: candidate.skillPath,\n ...(result.error ? { error: result.error } : {}),\n });\n continue;\n }\n\n const skill: Skill = {\n metadata: result.metadata!,\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n trustLevel: this.rootTrustMap.get(candidate.rootPath) ?? 'untrusted',\n };\n\n // Handle duplicate skill names — first root wins (deterministic precedence)\n if (this.skills.has(skill.metadata.name)) {\n const existing = this.skills.get(skill.metadata.name)!;\n warningCount++;\n const warningMsg = `Duplicate skill name \"${skill.metadata.name}\" from \"${candidate.rootPath}\" — ` +\n `keeping version from \"${existing.rootPath}\" (first root takes precedence)`;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: warningMsg,\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n duplicateOf: existing.skillPath,\n error: warningMsg,\n });\n logger.warn('Duplicate skill name, keeping first', {\n name: skill.metadata.name,\n kept: existing.skillPath,\n skipped: candidate.skillPath,\n });\n continue;\n }\n\n this.skills.set(skill.metadata.name, skill);\n successCount++;\n\n this.emit(SkillRegistryEvent.SKILL_DISCOVERED, skill);\n logger.debug('Skill discovered', {\n name: skill.metadata.name,\n description: skill.metadata.description.slice(0, 80),\n skillPath: skill.skillPath,\n });\n }\n\n logger.info('Skill registry populated', {\n rootsScanned: this.config.skillRoots.length,\n skillsDiscovered: successCount,\n warnings: warningCount,\n });\n }\n\n // ─── Query API (parallel to ToolRegistry) ──────────────────────────────\n\n /**\n * Get a skill by name.\n *\n * @param name - The skill name\n * @returns The skill, or undefined if not found\n *\n * @example\n * ```ts\n * const skill = registry.get('code-review');\n * if (skill) {\n * console.log(skill.metadata.description);\n * }\n * ```\n */\n get(name: string): Skill | undefined {\n return this.skills.get(name);\n }\n\n /**\n * Get all discovered skills.\n *\n * @returns Array of all skills\n *\n * @example\n * ```ts\n * const allSkills = registry.getAll();\n * console.log(`Total skills: ${allSkills.length}`);\n * ```\n */\n getAll(): Skill[] {\n return Array.from(this.skills.values());\n }\n\n /**\n * Check if a skill exists in the registry.\n *\n * @param name - The skill name\n * @returns True if the skill exists\n *\n * @example\n * ```ts\n * if (registry.has('code-review')) {\n * console.log('Skill available!');\n * }\n * ```\n */\n has(name: string): boolean {\n return this.skills.has(name);\n }\n\n /**\n * Get the number of discovered skills.\n *\n * @returns Number of skills in the registry\n *\n * @example\n * ```ts\n * console.log(`Registry has ${registry.size()} skills`);\n * ```\n */\n size(): number {\n return this.skills.size;\n }\n\n /**\n * Get all skill names.\n *\n * @returns Array of skill names\n */\n getNames(): string[] {\n return Array.from(this.skills.keys());\n }\n\n /**\n * Get errors/warnings from the last scan.\n *\n * Useful for diagnostics and observability.\n *\n * @returns Array of scan errors with paths\n */\n getScanErrors(): ReadonlyArray<{ path: string; error: string }> {\n return this.scanErrors;\n }\n\n /**\n * Check whether untrusted script access is allowed via config override.\n *\n * Used by activation tools to pass the override flag to trust policy checks.\n *\n * @returns True if `allowUntrustedScripts` is set in config\n */\n getAllowUntrustedScripts(): boolean {\n return this.config.allowUntrustedScripts ?? false;\n }\n\n /**\n * Get the `allowed-tools` list for a skill.\n *\n * Returns the `allowedTools` array from the skill's frontmatter metadata,\n * enabling agents to filter their tool set based on what the skill expects.\n *\n * @param name - The skill name\n * @returns Array of allowed tool names, or undefined if skill not found or field not set\n *\n * @example\n * ```ts\n * const allowed = registry.getAllowedTools('code-review');\n * if (allowed) {\n * const filteredTools = allTools.filter(t => allowed.includes(t.name));\n * }\n * ```\n */\n getAllowedTools(name: string): string[] | undefined {\n const skill = this.skills.get(name);\n return skill?.metadata.allowedTools;\n }\n\n // ─── Prompt Generation ─────────────────────────────────────────────────\n\n /**\n * Generate an `<available_skills>` XML block for system prompt injection.\n *\n * Returns an empty string when:\n * - `config.enabled` is `false` (default) — agents operate with unmodified prompts\n * - No skills match the filter criteria\n *\n * The output composes naturally with `toolRegistry.generatePrompt()` —\n * simply concatenate both into the system prompt.\n *\n * @param options - Optional filtering (subset of skill names)\n * @returns XML string or empty string\n *\n * @example\n * ```ts\n * // All skills\n * const xml = registry.generatePrompt();\n *\n * // Subset for a focused agent\n * const xml = registry.generatePrompt({ skills: ['code-review', 'testing'] });\n *\n * // Compose with tool prompt\n * const systemPrompt = [\n * toolRegistry.generatePrompt(),\n * skillRegistry.generatePrompt(),\n * ].filter(Boolean).join('\\n\\n');\n * ```\n */\n generatePrompt(options?: SkillPromptOptions): string {\n // Feature flag gate — disabled by default\n if (!this.config.enabled) {\n logger.debug('Skill prompt generation skipped (disabled)', {\n enabled: this.config.enabled ?? false,\n });\n return '';\n }\n\n // Resolve which skills to include\n let skills = this.getAll();\n\n // Apply subset filter if provided\n if (options?.skills && options.skills.length > 0) {\n const requested = new Set(options.skills);\n skills = skills.filter((s) => requested.has(s.metadata.name));\n }\n\n // Apply maxDiscoveredSkills cap\n if (this.config.maxDiscoveredSkills !== undefined && this.config.maxDiscoveredSkills >= 0) {\n skills = skills.slice(0, this.config.maxDiscoveredSkills);\n }\n\n // No skills — return empty string\n if (skills.length === 0) {\n logger.debug('Skill prompt generation produced empty result', {\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n ...(this.config.maxDiscoveredSkills !== undefined\n ? { maxCap: this.config.maxDiscoveredSkills }\n : {}),\n });\n return '';\n }\n\n // Generate XML\n const skillEntries = skills.map((skill) => {\n const lines = [\n ' <skill>',\n ` <name>${escapeXml(skill.metadata.name)}</name>`,\n ` <description>${escapeXml(skill.metadata.description)}</description>`,\n ` <location>${escapeXml(skill.skillPath)}</location>`,\n ' </skill>',\n ];\n return lines.join('\\n');\n });\n\n const xml = `<available_skills>\\n${skillEntries.join('\\n')}\\n</available_skills>`;\n\n // Estimate token count (~4 chars per token, rough heuristic)\n const estimatedTokens = Math.ceil(xml.length / 4);\n\n logger.info('Skill prompt generated', {\n skillCount: skills.length,\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n ...(this.config.maxDiscoveredSkills !== undefined\n ? { maxCap: this.config.maxDiscoveredSkills }\n : {}),\n estimatedTokens,\n xmlLength: xml.length,\n });\n\n return xml;\n }\n\n // ─── Event System ──────────────────────────────────────────────────────\n\n /**\n * Register an event handler.\n *\n * @param event - The event to listen for\n * @param handler - The handler function\n *\n * @example\n * ```ts\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n on(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * Unregister an event handler.\n *\n * @param event - The event to stop listening for\n * @param handler - The handler function to remove\n */\n off(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n\n /**\n * Emit an event to all registered handlers.\n *\n * @param event - The event to emit\n * @param data - The event data\n * @private\n */\n private emit(event: SkillRegistryEvent, data: unknown): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(data);\n } catch (error) {\n logger.error('Skill event handler error', {\n event,\n error: error instanceof Error ? error.message : String(error),\n ...(error instanceof Error && error.stack ? { stack: error.stack } : {}),\n });\n }\n });\n }\n }\n\n /**\n * Emit an event (public API for activation tools).\n *\n * Used by skill activation tools to emit `skill:activated` and\n * `skill:resource-loaded` events through the registry's event system.\n *\n * @param event - The event to emit\n * @param data - The event data\n */\n emitEvent(event: SkillRegistryEvent, data: unknown): void {\n this.emit(event, data);\n }\n\n // ─── Tool Integration ────────────────────────────────────────────────\n\n /**\n * Create activation tools pre-wired to this registry instance.\n *\n * Returns `activate-skill` and `read-skill-resource` tools that\n * agents can use to load skill instructions and resources on demand.\n *\n * @returns Array of [activate-skill, read-skill-resource] tools\n *\n * @example\n * ```ts\n * const agent = createReActAgent({\n * model: llm,\n * tools: [\n * ...toolRegistry.toLangChainTools(),\n * ...skillRegistry.toActivationTools(),\n * ],\n * });\n * ```\n */\n toActivationTools(): ReturnType<typeof createSkillActivationTools> {\n return createSkillActivationTools(this);\n }\n}\n\n/**\n * Escape special XML characters in a string.\n *\n * @param str - The string to escape\n * @returns Escaped string safe for XML content\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n"]}
package/dist/index.js CHANGED
@@ -496,7 +496,7 @@ var SkillRegistry = class {
496
496
  });
497
497
  logger3.warn("Skipping invalid skill", {
498
498
  skillPath: candidate.skillPath,
499
- error: result.error
499
+ ...result.error ? { error: result.error } : {}
500
500
  });
501
501
  continue;
502
502
  }
@@ -700,7 +700,7 @@ var SkillRegistry = class {
700
700
  logger3.debug("Skill prompt generation produced empty result", {
701
701
  totalDiscovered: this.size(),
702
702
  filterApplied: !!(options?.skills && options.skills.length > 0),
703
- maxCap: this.config.maxDiscoveredSkills
703
+ ...this.config.maxDiscoveredSkills !== void 0 ? { maxCap: this.config.maxDiscoveredSkills } : {}
704
704
  });
705
705
  return "";
706
706
  }
@@ -722,7 +722,7 @@ ${skillEntries.join("\n")}
722
722
  skillCount: skills.length,
723
723
  totalDiscovered: this.size(),
724
724
  filterApplied: !!(options?.skills && options.skills.length > 0),
725
- maxCap: this.config.maxDiscoveredSkills,
725
+ ...this.config.maxDiscoveredSkills !== void 0 ? { maxCap: this.config.maxDiscoveredSkills } : {},
726
726
  estimatedTokens,
727
727
  xmlLength: xml.length
728
728
  });
@@ -777,7 +777,7 @@ ${skillEntries.join("\n")}
777
777
  logger3.error("Skill event handler error", {
778
778
  event,
779
779
  error: error instanceof Error ? error.message : String(error),
780
- stack: error instanceof Error ? error.stack : void 0
780
+ ...error instanceof Error && error.stack ? { stack: error.stack } : {}
781
781
  });
782
782
  }
783
783
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/parser.ts","../src/scanner.ts","../src/trust.ts","../src/activation.ts","../src/registry.ts"],"names":["TrustPolicyReason","SkillRegistryEvent","logger","createLogger","LogLevel","resolve","readFileSync","matter","resolvePath"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Skill System Types\n *\n * Core type definitions for the AgentForge Agent Skills system.\n * These types align with the Agent Skills specification (https://agentskills.io/specification).\n */\n\n// ─── Trust Policy Types ──────────────────────────────────────────────────\n\n/**\n * Trust level for a skill root directory.\n *\n * - `workspace` — Skills from the project workspace (highest trust, scripts allowed)\n * - `trusted` — Explicitly trusted skill roots (scripts allowed)\n * - `untrusted` — Untrusted roots like community packs (scripts blocked by default)\n */\nexport type TrustLevel = 'workspace' | 'trusted' | 'untrusted';\n\n/**\n * Configuration for a skill root with an explicit trust level.\n *\n * @example\n * ```ts\n * const roots: SkillRootConfig[] = [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community-skills', trust: 'untrusted' },\n * ];\n * ```\n */\nexport interface SkillRootConfig {\n /** Directory path to scan for skills */\n path: string;\n /** Trust level assigned to all skills discovered from this root */\n trust: TrustLevel;\n}\n\n/**\n * Policy decision returned by trust enforcement checks.\n */\nexport interface TrustPolicyDecision {\n /** Whether the action is allowed */\n allowed: boolean;\n /** Machine-readable reason code for auditing */\n reason: TrustPolicyReason;\n /** Human-readable explanation */\n message: string;\n}\n\n/**\n * Reason codes for trust policy decisions.\n *\n * Used for structured logging and auditing of guardrail behavior.\n */\nexport enum TrustPolicyReason {\n /** Resource is not a script — no trust check needed */\n NOT_SCRIPT = 'not-script',\n /** Skill root has workspace trust — scripts allowed */\n WORKSPACE_TRUST = 'workspace-trust',\n /** Skill root has explicit trusted status — scripts allowed */\n TRUSTED_ROOT = 'trusted-root',\n /** Skill root is untrusted — scripts denied by default */\n UNTRUSTED_SCRIPT_DENIED = 'untrusted-script-denied',\n /** Untrusted script access was explicitly allowed via config override */\n UNTRUSTED_SCRIPT_ALLOWED = 'untrusted-script-allowed-override',\n /** Trust level is unknown — treated as untrusted for security */\n UNKNOWN_TRUST_LEVEL = 'unknown-trust-level',\n}\n\n/**\n * Parsed metadata from a SKILL.md frontmatter block.\n *\n * Required fields: `name`, `description`.\n * All other fields are optional per the Agent Skills spec.\n */\nexport interface SkillMetadata {\n /** Skill name (1-64 chars, lowercase alphanumeric + hyphens, must match parent dir name) */\n name: string;\n /** Human-readable description (1-1024 chars) */\n description: string;\n /** SPDX license identifier */\n license?: string;\n /** List of compatible agent frameworks / tool hosts */\n compatibility?: string[];\n /** Arbitrary key-value metadata (author, version, etc.) */\n metadata?: Record<string, unknown>;\n /** Tools that this skill is allowed to use */\n allowedTools?: string[];\n}\n\n/**\n * A fully resolved skill entry in the registry.\n *\n * Contains parsed metadata plus internal tracking fields\n * that are not part of the SKILL.md frontmatter.\n */\nexport interface Skill {\n /** Parsed frontmatter metadata */\n metadata: SkillMetadata;\n /** Absolute path to the skill directory */\n skillPath: string;\n /** Which configured skill root this was discovered from */\n rootPath: string;\n /** Trust level assigned to this skill (inherited from root config) */\n trustLevel: TrustLevel;\n}\n\n/**\n * Configuration for the SkillRegistry.\n */\nexport interface SkillRegistryConfig {\n /**\n * Array of directory paths to scan for skills.\n *\n * Each entry can be a plain string (defaults to `'untrusted'` trust level)\n * or a `SkillRootConfig` object with an explicit trust level.\n *\n * Paths may be absolute or relative (resolved against `cwd`).\n * The `~` prefix is expanded to `$HOME`.\n *\n * @example\n * ```ts\n * // Simple string roots (default to 'untrusted')\n * skillRoots: ['.agentskills', '~/.agentskills']\n *\n * // Trust-aware roots\n * skillRoots: [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community', trust: 'untrusted' },\n * ]\n * ```\n */\n skillRoots: Array<string | SkillRootConfig>;\n\n /**\n * Feature flag to enable Agent Skills in system prompts.\n *\n * When `false` (default), `generatePrompt()` returns an empty string\n * so agents operate with unmodified system prompts.\n *\n * @default false\n */\n enabled?: boolean;\n\n /**\n * Maximum number of skills to include in generated prompts.\n *\n * Caps prompt token usage when many skills are discovered.\n * Skills are included in discovery order (first root first).\n * When undefined, all discovered skills are included.\n */\n maxDiscoveredSkills?: number;\n\n /**\n * Allow script resources from untrusted roots.\n *\n * When `true`, scripts from `scripts/` directories in untrusted\n * skill roots are returned instead of being denied. This disables\n * the default-deny policy for untrusted scripts.\n *\n * **Security warning:** Only enable when you have reviewed all\n * skill packs from untrusted roots.\n *\n * @default false\n */\n allowUntrustedScripts?: boolean;\n}\n\n/**\n * Options for `SkillRegistry.generatePrompt()`.\n */\nexport interface SkillPromptOptions {\n /**\n * Subset of skill names to include in the generated prompt.\n *\n * When provided, only skills matching these names appear in the\n * `<available_skills>` XML block. This enables creating focused\n * agents with different skill sets from the same registry.\n *\n * When omitted or empty, all discovered skills are included.\n *\n * @example ['code-review', 'testing-strategy']\n */\n skills?: string[];\n}\n\n/**\n * Events emitted by the SkillRegistry during discovery and usage.\n */\nexport enum SkillRegistryEvent {\n /** Emitted when a valid skill is discovered during scanning */\n SKILL_DISCOVERED = 'skill:discovered',\n /** Emitted when a skill parse or validation issue is encountered */\n SKILL_WARNING = 'skill:warning',\n /** Emitted when a skill is activated (full body loaded) */\n SKILL_ACTIVATED = 'skill:activated',\n /** Emitted when a skill resource file is loaded */\n SKILL_RESOURCE_LOADED = 'skill:resource-loaded',\n /** Emitted when a trust policy denies access to a resource */\n TRUST_POLICY_DENIED = 'trust:policy-denied',\n /** Emitted when a trust policy allows access (for auditing) */\n TRUST_POLICY_ALLOWED = 'trust:policy-allowed',\n}\n\n/**\n * Event handler type for skill registry events.\n */\nexport type SkillEventHandler = (data: unknown) => void;\n\n/**\n * Result of parsing a single SKILL.md file.\n */\nexport interface SkillParseResult {\n /** Whether parsing and validation succeeded */\n success: boolean;\n /** Parsed metadata (present when success is true) */\n metadata?: SkillMetadata;\n /** The raw markdown body below the frontmatter (present when success is true) */\n body?: string;\n /** Error description (present when success is false) */\n error?: string;\n}\n\n/**\n * Validation error detail.\n */\nexport interface SkillValidationError {\n /** Which field failed validation */\n field: string;\n /** Human-readable error message */\n message: string;\n}\n","/**\n * SKILL.md Frontmatter Parser\n *\n * Parses YAML frontmatter from SKILL.md files and validates\n * against the Agent Skills specification constraints.\n *\n * @see https://agentskills.io/specification\n */\n\nimport matter from 'gray-matter';\nimport type { SkillMetadata, SkillParseResult, SkillValidationError } from './types.js';\n\n/**\n * Skill name validation constraints (per spec).\n *\n * - 1-64 characters\n * - Lowercase alphanumeric and hyphens only\n * - No leading, trailing, or consecutive hyphens\n */\nconst SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\nconst SKILL_NAME_MAX_LENGTH = 64;\nconst SKILL_DESCRIPTION_MAX_LENGTH = 1024;\n\n/**\n * Validate the `name` field per the Agent Skills spec.\n *\n * @param name - The name value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillName(name: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (name === undefined || name === null) {\n errors.push({ field: 'name', message: 'name is required' });\n return errors;\n }\n\n if (typeof name !== 'string') {\n errors.push({ field: 'name', message: 'name must be a string' });\n return errors;\n }\n\n if (name.length === 0) {\n errors.push({ field: 'name', message: 'name must not be empty' });\n return errors;\n }\n\n if (name.length > SKILL_NAME_MAX_LENGTH) {\n errors.push({\n field: 'name',\n message: `name must be at most ${SKILL_NAME_MAX_LENGTH} characters (got ${name.length})`,\n });\n return errors;\n }\n\n if (!SKILL_NAME_PATTERN.test(name)) {\n errors.push({\n field: 'name',\n message: 'name must be lowercase alphanumeric with hyphens, no leading/trailing/consecutive hyphens',\n });\n }\n\n if (name.includes('--')) {\n errors.push({\n field: 'name',\n message: 'name must not contain consecutive hyphens',\n });\n }\n\n return errors;\n}\n\n/**\n * Validate the `description` field per the Agent Skills spec.\n *\n * @param description - The description value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillDescription(description: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (description === undefined || description === null) {\n errors.push({ field: 'description', message: 'description is required' });\n return errors;\n }\n\n if (typeof description !== 'string') {\n errors.push({ field: 'description', message: 'description must be a string' });\n return errors;\n }\n\n if (description.trim().length === 0) {\n errors.push({ field: 'description', message: 'description must not be empty' });\n return errors;\n }\n\n if (description.length > SKILL_DESCRIPTION_MAX_LENGTH) {\n errors.push({\n field: 'description',\n message: `description must be at most ${SKILL_DESCRIPTION_MAX_LENGTH} characters (got ${description.length})`,\n });\n }\n\n return errors;\n}\n\n/**\n * Validate that the skill name matches its parent directory name (per spec).\n *\n * @param name - The name from frontmatter\n * @param dirName - The parent directory name\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillNameMatchesDir(name: string, dirName: string): SkillValidationError[] {\n if (name !== dirName) {\n return [{\n field: 'name',\n message: `name \"${name}\" must match parent directory name \"${dirName}\"`,\n }];\n }\n return [];\n}\n\n/**\n * Parse and validate a SKILL.md file's raw content.\n *\n * Extracts YAML frontmatter using gray-matter, then validates\n * required and optional fields against spec constraints.\n *\n * @param content - Raw file content of the SKILL.md\n * @param dirName - Parent directory name for name-match validation\n * @returns Parse result with metadata or error\n */\nexport function parseSkillContent(content: string, dirName: string): SkillParseResult {\n let parsed: matter.GrayMatterFile<string>;\n\n try {\n parsed = matter(content);\n } catch (err) {\n return {\n success: false,\n error: `Failed to parse frontmatter: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n const data = parsed.data;\n\n // Validate required fields\n const errors: SkillValidationError[] = [\n ...validateSkillName(data.name),\n ...validateSkillDescription(data.description),\n ];\n\n // If name is valid, validate it matches directory name\n if (typeof data.name === 'string' && data.name.length > 0 && SKILL_NAME_PATTERN.test(data.name)) {\n errors.push(...validateSkillNameMatchesDir(data.name, dirName));\n }\n\n if (errors.length > 0) {\n return {\n success: false,\n error: errors.map((e) => `${e.field}: ${e.message}`).join('; '),\n };\n }\n\n // Build metadata from validated fields\n const metadata: SkillMetadata = {\n name: data.name as string,\n description: data.description as string,\n };\n\n // Optional fields\n if (data.license !== undefined) {\n metadata.license = String(data.license);\n }\n\n if (Array.isArray(data.compatibility)) {\n metadata.compatibility = data.compatibility.map(String);\n }\n\n if (data.metadata !== undefined && typeof data.metadata === 'object' && data.metadata !== null) {\n metadata.metadata = data.metadata as Record<string, unknown>;\n }\n\n if (Array.isArray(data['allowed-tools'])) {\n metadata.allowedTools = data['allowed-tools'].map(String);\n }\n\n return {\n success: true,\n metadata,\n body: parsed.content,\n };\n}\n","/**\n * Skill Directory Scanner\n *\n * Scans configured skill roots for directories containing valid SKILL.md files.\n * Returns a list of candidate skill paths for the parser to process.\n */\n\nimport { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';\nimport { resolve, basename } from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:scanner', { level: LogLevel.INFO });\n\n/**\n * Discovered skill candidate — a directory containing a SKILL.md file.\n */\nexport interface SkillCandidate {\n /** Absolute path to the skill directory */\n skillPath: string;\n /** The parent directory name (expected to match the skill name) */\n dirName: string;\n /** Raw content of the SKILL.md file */\n content: string;\n /** Which configured root this came from */\n rootPath: string;\n}\n\n/**\n * Expand `~` prefix to the user's home directory.\n */\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2));\n }\n return p;\n}\n\n/**\n * Scan a single skill root for directories containing SKILL.md.\n *\n * @param rootPath - The root directory to scan (may not exist)\n * @returns Array of valid skill candidates found under this root\n */\nexport function scanSkillRoot(rootPath: string): SkillCandidate[] {\n const resolvedRoot = resolve(expandHome(rootPath));\n const candidates: SkillCandidate[] = [];\n\n if (!existsSync(resolvedRoot)) {\n logger.debug('Skill root does not exist, skipping', { rootPath: resolvedRoot });\n return candidates;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(resolvedRoot);\n } catch (err) {\n logger.warn('Failed to read skill root directory', {\n rootPath: resolvedRoot,\n error: err instanceof Error ? err.message : String(err),\n });\n return candidates;\n }\n\n for (const entry of entries) {\n const entryPath = resolve(resolvedRoot, entry);\n\n // Only process directories\n let stat;\n try {\n stat = statSync(entryPath);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) {\n continue;\n }\n\n // Check for SKILL.md inside the directory\n const skillMdPath = resolve(entryPath, 'SKILL.md');\n if (!existsSync(skillMdPath)) {\n continue;\n }\n\n // Read the SKILL.md content\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n candidates.push({\n skillPath: entryPath,\n dirName: basename(entryPath),\n content,\n rootPath: resolvedRoot,\n });\n } catch (err) {\n logger.warn('Failed to read SKILL.md', {\n path: skillMdPath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n logger.debug('Scanned skill root', {\n rootPath: resolvedRoot,\n candidatesFound: candidates.length,\n });\n\n return candidates;\n}\n\n/**\n * Scan multiple skill roots for directories containing SKILL.md.\n *\n * @param skillRoots - Array of root paths to scan\n * @returns Array of all skill candidates found across all roots\n */\nexport function scanAllSkillRoots(skillRoots: string[]): SkillCandidate[] {\n const allCandidates: SkillCandidate[] = [];\n\n for (const root of skillRoots) {\n const candidates = scanSkillRoot(root);\n allCandidates.push(...candidates);\n }\n\n logger.info('Skill discovery complete', {\n rootsScanned: skillRoots.length,\n totalCandidates: allCandidates.length,\n });\n\n return allCandidates;\n}\n","/**\n * Skill Trust Policy Engine\n *\n * Enforces trust-level-based access control for skill resources.\n * Scripts from untrusted roots are denied by default unless explicitly allowed.\n *\n * Trust levels:\n * - `workspace` — Project-local skills, highest trust. Scripts always allowed.\n * - `trusted` — Explicitly trusted roots. Scripts allowed.\n * - `untrusted` — Community or third-party skills. Scripts denied by default.\n *\n * @see https://agentskills.io/specification\n */\n\nimport type { TrustLevel, TrustPolicyDecision, SkillRootConfig } from './types.js';\nimport { TrustPolicyReason } from './types.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────\n\n/**\n * Resource path prefix that requires trust enforcement.\n *\n * Only resources under `scripts/` are subject to trust policy checks.\n * Other directories (references/, assets/, etc.) are always accessible.\n */\nconst SCRIPT_PATH_PREFIX = 'scripts/';\nconst SCRIPT_PATH_EXACT = 'scripts';\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Normalize a skill root config entry.\n *\n * String entries default to `'untrusted'` trust level for safe defaults.\n *\n * @param root - A string path or SkillRootConfig object\n * @returns Normalized SkillRootConfig with explicit trust level\n */\nexport function normalizeRootConfig(root: string | SkillRootConfig): SkillRootConfig {\n if (typeof root === 'string') {\n return { path: root, trust: 'untrusted' };\n }\n return root;\n}\n\n/**\n * Check whether a resource path refers to a script.\n *\n * A resource is considered a script if its relative path starts with\n * `scripts/` or is exactly `scripts`, after normalizing path separators,\n * stripping leading \"./\" segments, and ignoring case.\n *\n * @param resourcePath - Relative path within the skill directory\n * @returns True if the resource is in the scripts/ directory\n */\nexport function isScriptResource(resourcePath: string): boolean {\n // Normalize to forward slashes and trim for consistent checking\n let normalized = resourcePath.trim().replace(/\\\\/g, '/');\n\n // Collapse repeated separators (e.g., \"scripts//setup.sh\" → \"scripts/setup.sh\")\n normalized = normalized.replace(/\\/+/g, '/');\n\n // Strip leading \"./\" segments (e.g., \"./scripts/setup.sh\" → \"scripts/setup.sh\")\n while (normalized.startsWith('./')) {\n normalized = normalized.slice(2);\n }\n\n // Case-insensitive comparison to handle case-insensitive file systems\n const lower = normalized.toLowerCase();\n\n return lower === SCRIPT_PATH_EXACT\n || lower.startsWith(SCRIPT_PATH_PREFIX);\n}\n\n// ─── Policy Engine ───────────────────────────────────────────────────────\n\n/**\n * Evaluate the trust policy for a resource access request.\n *\n * Non-script resources are always allowed regardless of trust level.\n * Script resources require `workspace` or `trusted` trust, or the\n * `allowUntrustedScripts` override to be enabled.\n *\n * @param resourcePath - Relative path to the resource within the skill directory\n * @param trustLevel - Trust level of the skill's root directory\n * @param allowUntrustedScripts - Override flag to permit untrusted scripts\n * @returns Policy decision with allow/deny, reason code, and message\n */\nexport function evaluateTrustPolicy(\n resourcePath: string,\n trustLevel: TrustLevel,\n allowUntrustedScripts: boolean = false,\n): TrustPolicyDecision {\n // Non-script resources — no policy enforcement needed\n if (!isScriptResource(resourcePath)) {\n return {\n allowed: true,\n reason: TrustPolicyReason.NOT_SCRIPT,\n message: 'Resource is not a script — no trust check required',\n };\n }\n\n // Script resources — check trust level\n switch (trustLevel) {\n case 'workspace':\n return {\n allowed: true,\n reason: TrustPolicyReason.WORKSPACE_TRUST,\n message: 'Script allowed — skill root has workspace trust',\n };\n\n case 'trusted':\n return {\n allowed: true,\n reason: TrustPolicyReason.TRUSTED_ROOT,\n message: 'Script allowed — skill root is explicitly trusted',\n };\n\n case 'untrusted':\n if (allowUntrustedScripts) {\n return {\n allowed: true,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_ALLOWED,\n message: 'Script from untrusted root allowed via allowUntrustedScripts override',\n };\n }\n return {\n allowed: false,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_DENIED,\n message: `Script access denied — skill root is untrusted. ` +\n `Scripts from untrusted roots are blocked by default for security. ` +\n `To allow, set 'allowUntrustedScripts: true' in SkillRegistryConfig or ` +\n `promote the skill root to 'trusted' or 'workspace' trust level.`,\n };\n\n default:\n return {\n allowed: false,\n reason: TrustPolicyReason.UNKNOWN_TRUST_LEVEL,\n message: `Script access denied — trust level \"${trustLevel}\" is unknown and is treated as untrusted for security.`,\n };\n }\n}\n","/**\n * Skill Activation Tools\n *\n * Provides `activate-skill` and `read-skill-resource` tools built with\n * the AgentForge tool builder API. These tools enable agents to load\n * skill instructions on demand and access skill resources at runtime.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const [activateSkill, readSkillResource] = createSkillActivationTools(registry);\n * // activateSkill — load full SKILL.md body\n * // readSkillResource — load a resource file from a skill\n *\n * // Or use the convenience method:\n * const [activateSkill, readSkillResource] = registry.toActivationTools();\n * ```\n */\n\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { resolve, relative, isAbsolute } from 'node:path';\nimport matter from 'gray-matter';\nimport { z } from 'zod';\nimport { ToolBuilder, ToolCategory, createLogger, LogLevel } from '@agentforge/core';\nimport type { Tool } from '@agentforge/core';\nimport type { SkillRegistry } from './registry.js';\nimport { SkillRegistryEvent, TrustPolicyReason } from './types.js';\nimport { evaluateTrustPolicy } from './trust.js';\n\nconst logger = createLogger('agentforge:skills:activation', { level: LogLevel.INFO });\n\n// ─── Schemas ─────────────────────────────────────────────────────────────\n\nconst activateSkillSchema = z.object({\n name: z.string().describe('The name of the skill to activate (e.g., \"code-review\")'),\n});\n\nconst readSkillResourceSchema = z.object({\n name: z.string().describe('The name of the skill that owns the resource'),\n path: z.string().describe('Relative path to the resource file within the skill directory (e.g., \"references/GUIDE.md\", \"scripts/setup.sh\")'),\n});\n\n// ─── Path Security ───────────────────────────────────────────────────────\n\n/**\n * Resolve a resource path within a skill root, blocking path traversal.\n *\n * @param skillPath - Absolute path to the skill directory\n * @param resourcePath - Relative path to the resource file\n * @returns Absolute path to the resource, or an error string\n */\nexport function resolveResourcePath(\n skillPath: string,\n resourcePath: string,\n): { success: true; resolvedPath: string } | { success: false; error: string } {\n // Reject absolute paths using platform-aware check\n if (isAbsolute(resourcePath)) {\n return { success: false, error: 'Absolute resource paths are not allowed' };\n }\n\n // Reject traversal via segment-based '..' detection\n // Split on both '/' and '\\' to handle cross-platform separators\n const segments = resourcePath.split(/[/\\\\]/);\n if (segments.some((seg) => seg === '..')) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Resolve and verify containment (final guard)\n const resolvedPath = resolve(skillPath, resourcePath);\n const resolvedSkillPath = resolve(skillPath);\n\n // Ensure the resolved path is within the skill directory\n const rel = relative(resolvedSkillPath, resolvedPath);\n if (rel.startsWith('..') || resolve(resolvedSkillPath, rel) !== resolvedPath) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Guard against symlink escapes: resolve real filesystem paths and\n // verify that the real target still sits under the real skill root.\n // This prevents a symlink inside the skill dir from pointing outside.\n try {\n const realSkillRoot = realpathSync(resolvedSkillPath);\n const realTarget = realpathSync(resolvedPath);\n const realRel = relative(realSkillRoot, realTarget);\n if (realRel.startsWith('..') || isAbsolute(realRel)) {\n return { success: false, error: 'Symlink target escapes the skill directory — access denied' };\n }\n } catch {\n // File doesn't exist yet (or can't be stat'd) — skip symlink check.\n // The caller (readFileSync) will produce a clear error if missing.\n }\n\n return { success: true, resolvedPath };\n}\n\n// ─── Tool Factories ──────────────────────────────────────────────────────\n\n/**\n * Create the `activate-skill` tool bound to a registry instance.\n *\n * Resolves the skill by name, reads the full SKILL.md file, and returns\n * the body content (below frontmatter).\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createActivateSkillTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof activateSkillSchema>, string> {\n return new ToolBuilder<z.infer<typeof activateSkillSchema>, string>()\n .name('activate-skill')\n .description(\n 'Activate an Agent Skill by name, loading its full instructions. ' +\n 'Returns the complete SKILL.md body content for the named skill. ' +\n 'Use this when you see a relevant skill in <available_skills> and want to follow its instructions.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'activation', 'agent-skills'])\n .schema(activateSkillSchema)\n .implement(async ({ name }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill activation failed — not found', { name, availableCount: availableNames.length });\n return errorMsg;\n }\n\n // Read the full SKILL.md body from disk (progressive disclosure)\n const skillMdPath = resolve(skill.skillPath, 'SKILL.md');\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n\n // Extract body below frontmatter\n const body = extractBody(content);\n\n logger.info('Skill activated', {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_ACTIVATED, {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n return body;\n } catch (error) {\n const errorMsg = `Failed to read skill \"${name}\" instructions: ${error instanceof Error ? error.message : String(error)}`;\n logger.error('Skill activation failed — read error', {\n name,\n skillPath: skill.skillPath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create the `read-skill-resource` tool bound to a registry instance.\n *\n * Resolves the skill by name, validates the resource path (blocking\n * traversal), and returns the file content.\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createReadSkillResourceTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof readSkillResourceSchema>, string> {\n return new ToolBuilder<z.infer<typeof readSkillResourceSchema>, string>()\n .name('read-skill-resource')\n .description(\n 'Read a resource file from an activated Agent Skill. ' +\n 'Returns the content of a file within the skill directory (e.g., references/, scripts/, assets/). ' +\n 'The path must be relative to the skill root and cannot traverse outside it.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'resource', 'agent-skills'])\n .schema(readSkillResourceSchema)\n .implement(async ({ name, path: resourcePath }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill resource load failed — skill not found', { name, resourcePath });\n return errorMsg;\n }\n\n // Resolve and validate the resource path\n const pathResult = resolveResourcePath(skill.skillPath, resourcePath);\n if (!pathResult.success) {\n logger.warn('Skill resource load blocked — path traversal', {\n name,\n resourcePath,\n error: pathResult.error,\n });\n return pathResult.error;\n }\n\n // Enforce trust policy for script resources\n const policyDecision = evaluateTrustPolicy(\n resourcePath,\n skill.trustLevel,\n registry.getAllowUntrustedScripts(),\n );\n\n if (!policyDecision.allowed) {\n logger.warn('Skill resource load blocked — trust policy', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_DENIED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n return policyDecision.message;\n }\n\n // Log allowed policy decisions for auditing (scripts only)\n if (policyDecision.reason !== TrustPolicyReason.NOT_SCRIPT) {\n logger.info('Skill resource trust policy — allowed', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_ALLOWED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n }\n\n try {\n const content = readFileSync(pathResult.resolvedPath, 'utf-8');\n\n logger.info('Skill resource loaded', {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_RESOURCE_LOADED, {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n return content;\n } catch (error) {\n const errorMsg = `Failed to read resource \"${resourcePath}\" from skill \"${name}\": ${error instanceof Error ? error.message : String(error)}`;\n logger.warn('Skill resource load failed — file not found or unreadable', {\n name,\n resourcePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create both skill activation tools bound to a registry instance.\n *\n * @param registry - The SkillRegistry to bind tools to\n * @returns Array of both tools [activate-skill, read-skill-resource]\n */\nexport function createSkillActivationTools(\n registry: SkillRegistry,\n): [Tool<z.infer<typeof activateSkillSchema>, string>, Tool<z.infer<typeof readSkillResourceSchema>, string>] {\n return [\n createActivateSkillTool(registry),\n createReadSkillResourceTool(registry),\n ];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Extract the body content below YAML frontmatter from a SKILL.md file.\n *\n * Delegates to `gray-matter` for consistent frontmatter handling across\n * the codebase (matches `parseSkillContent()` in parser.ts).\n *\n * @param content - The full SKILL.md file content\n * @returns The body content below the frontmatter\n */\nfunction extractBody(content: string): string {\n return matter(content).content.trim();\n}\n","/**\n * Skill Registry\n *\n * Central registry for discovering, storing, and querying Agent Skills.\n * Mirrors ToolRegistry but uses folder-based auto-discovery instead\n * of programmatic registration.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills'],\n * });\n *\n * // Query discovered skills\n * const skill = registry.get('code-review');\n * const allSkills = registry.getAll();\n *\n * // Listen for events\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n\nimport type {\n Skill,\n SkillRegistryConfig,\n SkillPromptOptions,\n SkillEventHandler,\n TrustLevel,\n} from './types.js';\nimport { SkillRegistryEvent } from './types.js';\nimport { scanAllSkillRoots, expandHome } from './scanner.js';\nimport { parseSkillContent } from './parser.js';\nimport { createSkillActivationTools } from './activation.js';\nimport { normalizeRootConfig } from './trust.js';\nimport { resolve as resolvePath } from 'node:path';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:registry', { level: LogLevel.INFO });\n\n/**\n * Skill Registry — auto-discovers skills from configured folder paths.\n *\n * Parallel to ToolRegistry:\n * | ToolRegistry | SkillRegistry |\n * |--------------------------|------------------------------------------|\n * | registry.register(tool) | new SkillRegistry({ skillRoots }) |\n * | registry.get('name') | skillRegistry.get('name') |\n * | registry.getAll() | skillRegistry.getAll() |\n * | registry.has('name') | skillRegistry.has('name') |\n * | registry.size() | skillRegistry.size() |\n * | registry.generatePrompt()| skillRegistry.generatePrompt() |\n * | registry.toLangChainTools()| skillRegistry.toActivationTools() |\n */\nexport class SkillRegistry {\n private skills: Map<string, Skill> = new Map();\n private eventHandlers: Map<SkillRegistryEvent, Set<SkillEventHandler>> = new Map();\n private readonly config: SkillRegistryConfig;\n private scanErrors: Array<{ path: string; error: string }> = [];\n /** Maps resolved root paths → trust levels for skill trust assignment */\n private rootTrustMap: Map<string, TrustLevel> = new Map();\n\n /**\n * Create a SkillRegistry and immediately scan configured roots for skills.\n *\n * @param config - Registry configuration with skill root paths\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills', './project-skills'],\n * });\n * console.log(`Discovered ${registry.size()} skills`);\n * ```\n */\n constructor(config: SkillRegistryConfig) {\n this.config = config;\n this.discover();\n }\n\n /**\n * Scan all configured roots and populate the registry.\n *\n * Called automatically during construction. Can be called again\n * to re-scan (clears existing skills first).\n */\n discover(): void {\n this.skills.clear();\n this.scanErrors = [];\n this.rootTrustMap.clear();\n\n // Normalize roots: extract plain paths for the scanner and build trust map\n const normalizedRoots = this.config.skillRoots.map(normalizeRootConfig);\n const plainPaths = normalizedRoots.map((r) => r.path);\n\n // Build trust map (resolve paths to match scanner output)\n for (const root of normalizedRoots) {\n const resolvedPath = resolvePath(expandHome(root.path));\n this.rootTrustMap.set(resolvedPath, root.trust);\n }\n\n const candidates = scanAllSkillRoots(plainPaths);\n\n let successCount = 0;\n let warningCount = 0;\n\n for (const candidate of candidates) {\n const result = parseSkillContent(candidate.content, candidate.dirName);\n\n if (!result.success) {\n warningCount++;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: result.error || 'Unknown parse error',\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n error: result.error,\n });\n logger.warn('Skipping invalid skill', {\n skillPath: candidate.skillPath,\n error: result.error,\n });\n continue;\n }\n\n const skill: Skill = {\n metadata: result.metadata!,\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n trustLevel: this.rootTrustMap.get(candidate.rootPath) ?? 'untrusted',\n };\n\n // Handle duplicate skill names — first root wins (deterministic precedence)\n if (this.skills.has(skill.metadata.name)) {\n const existing = this.skills.get(skill.metadata.name)!;\n warningCount++;\n const warningMsg = `Duplicate skill name \"${skill.metadata.name}\" from \"${candidate.rootPath}\" — ` +\n `keeping version from \"${existing.rootPath}\" (first root takes precedence)`;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: warningMsg,\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n duplicateOf: existing.skillPath,\n error: warningMsg,\n });\n logger.warn('Duplicate skill name, keeping first', {\n name: skill.metadata.name,\n kept: existing.skillPath,\n skipped: candidate.skillPath,\n });\n continue;\n }\n\n this.skills.set(skill.metadata.name, skill);\n successCount++;\n\n this.emit(SkillRegistryEvent.SKILL_DISCOVERED, skill);\n logger.debug('Skill discovered', {\n name: skill.metadata.name,\n description: skill.metadata.description.slice(0, 80),\n skillPath: skill.skillPath,\n });\n }\n\n logger.info('Skill registry populated', {\n rootsScanned: this.config.skillRoots.length,\n skillsDiscovered: successCount,\n warnings: warningCount,\n });\n }\n\n // ─── Query API (parallel to ToolRegistry) ──────────────────────────────\n\n /**\n * Get a skill by name.\n *\n * @param name - The skill name\n * @returns The skill, or undefined if not found\n *\n * @example\n * ```ts\n * const skill = registry.get('code-review');\n * if (skill) {\n * console.log(skill.metadata.description);\n * }\n * ```\n */\n get(name: string): Skill | undefined {\n return this.skills.get(name);\n }\n\n /**\n * Get all discovered skills.\n *\n * @returns Array of all skills\n *\n * @example\n * ```ts\n * const allSkills = registry.getAll();\n * console.log(`Total skills: ${allSkills.length}`);\n * ```\n */\n getAll(): Skill[] {\n return Array.from(this.skills.values());\n }\n\n /**\n * Check if a skill exists in the registry.\n *\n * @param name - The skill name\n * @returns True if the skill exists\n *\n * @example\n * ```ts\n * if (registry.has('code-review')) {\n * console.log('Skill available!');\n * }\n * ```\n */\n has(name: string): boolean {\n return this.skills.has(name);\n }\n\n /**\n * Get the number of discovered skills.\n *\n * @returns Number of skills in the registry\n *\n * @example\n * ```ts\n * console.log(`Registry has ${registry.size()} skills`);\n * ```\n */\n size(): number {\n return this.skills.size;\n }\n\n /**\n * Get all skill names.\n *\n * @returns Array of skill names\n */\n getNames(): string[] {\n return Array.from(this.skills.keys());\n }\n\n /**\n * Get errors/warnings from the last scan.\n *\n * Useful for diagnostics and observability.\n *\n * @returns Array of scan errors with paths\n */\n getScanErrors(): ReadonlyArray<{ path: string; error: string }> {\n return this.scanErrors;\n }\n\n /**\n * Check whether untrusted script access is allowed via config override.\n *\n * Used by activation tools to pass the override flag to trust policy checks.\n *\n * @returns True if `allowUntrustedScripts` is set in config\n */\n getAllowUntrustedScripts(): boolean {\n return this.config.allowUntrustedScripts ?? false;\n }\n\n /**\n * Get the `allowed-tools` list for a skill.\n *\n * Returns the `allowedTools` array from the skill's frontmatter metadata,\n * enabling agents to filter their tool set based on what the skill expects.\n *\n * @param name - The skill name\n * @returns Array of allowed tool names, or undefined if skill not found or field not set\n *\n * @example\n * ```ts\n * const allowed = registry.getAllowedTools('code-review');\n * if (allowed) {\n * const filteredTools = allTools.filter(t => allowed.includes(t.name));\n * }\n * ```\n */\n getAllowedTools(name: string): string[] | undefined {\n const skill = this.skills.get(name);\n return skill?.metadata.allowedTools;\n }\n\n // ─── Prompt Generation ─────────────────────────────────────────────────\n\n /**\n * Generate an `<available_skills>` XML block for system prompt injection.\n *\n * Returns an empty string when:\n * - `config.enabled` is `false` (default) — agents operate with unmodified prompts\n * - No skills match the filter criteria\n *\n * The output composes naturally with `toolRegistry.generatePrompt()` —\n * simply concatenate both into the system prompt.\n *\n * @param options - Optional filtering (subset of skill names)\n * @returns XML string or empty string\n *\n * @example\n * ```ts\n * // All skills\n * const xml = registry.generatePrompt();\n *\n * // Subset for a focused agent\n * const xml = registry.generatePrompt({ skills: ['code-review', 'testing'] });\n *\n * // Compose with tool prompt\n * const systemPrompt = [\n * toolRegistry.generatePrompt(),\n * skillRegistry.generatePrompt(),\n * ].filter(Boolean).join('\\n\\n');\n * ```\n */\n generatePrompt(options?: SkillPromptOptions): string {\n // Feature flag gate — disabled by default\n if (!this.config.enabled) {\n logger.debug('Skill prompt generation skipped (disabled)', {\n enabled: this.config.enabled ?? false,\n });\n return '';\n }\n\n // Resolve which skills to include\n let skills = this.getAll();\n\n // Apply subset filter if provided\n if (options?.skills && options.skills.length > 0) {\n const requested = new Set(options.skills);\n skills = skills.filter((s) => requested.has(s.metadata.name));\n }\n\n // Apply maxDiscoveredSkills cap\n if (this.config.maxDiscoveredSkills !== undefined && this.config.maxDiscoveredSkills >= 0) {\n skills = skills.slice(0, this.config.maxDiscoveredSkills);\n }\n\n // No skills — return empty string\n if (skills.length === 0) {\n logger.debug('Skill prompt generation produced empty result', {\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n maxCap: this.config.maxDiscoveredSkills,\n });\n return '';\n }\n\n // Generate XML\n const skillEntries = skills.map((skill) => {\n const lines = [\n ' <skill>',\n ` <name>${escapeXml(skill.metadata.name)}</name>`,\n ` <description>${escapeXml(skill.metadata.description)}</description>`,\n ` <location>${escapeXml(skill.skillPath)}</location>`,\n ' </skill>',\n ];\n return lines.join('\\n');\n });\n\n const xml = `<available_skills>\\n${skillEntries.join('\\n')}\\n</available_skills>`;\n\n // Estimate token count (~4 chars per token, rough heuristic)\n const estimatedTokens = Math.ceil(xml.length / 4);\n\n logger.info('Skill prompt generated', {\n skillCount: skills.length,\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n maxCap: this.config.maxDiscoveredSkills,\n estimatedTokens,\n xmlLength: xml.length,\n });\n\n return xml;\n }\n\n // ─── Event System ──────────────────────────────────────────────────────\n\n /**\n * Register an event handler.\n *\n * @param event - The event to listen for\n * @param handler - The handler function\n *\n * @example\n * ```ts\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n on(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * Unregister an event handler.\n *\n * @param event - The event to stop listening for\n * @param handler - The handler function to remove\n */\n off(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n\n /**\n * Emit an event to all registered handlers.\n *\n * @param event - The event to emit\n * @param data - The event data\n * @private\n */\n private emit(event: SkillRegistryEvent, data: unknown): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(data);\n } catch (error) {\n logger.error('Skill event handler error', {\n event,\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n });\n }\n }\n\n /**\n * Emit an event (public API for activation tools).\n *\n * Used by skill activation tools to emit `skill:activated` and\n * `skill:resource-loaded` events through the registry's event system.\n *\n * @param event - The event to emit\n * @param data - The event data\n */\n emitEvent(event: SkillRegistryEvent, data: unknown): void {\n this.emit(event, data);\n }\n\n // ─── Tool Integration ────────────────────────────────────────────────\n\n /**\n * Create activation tools pre-wired to this registry instance.\n *\n * Returns `activate-skill` and `read-skill-resource` tools that\n * agents can use to load skill instructions and resources on demand.\n *\n * @returns Array of [activate-skill, read-skill-resource] tools\n *\n * @example\n * ```ts\n * const agent = createReActAgent({\n * model: llm,\n * tools: [\n * ...toolRegistry.toLangChainTools(),\n * ...skillRegistry.toActivationTools(),\n * ],\n * });\n * ```\n */\n toActivationTools(): ReturnType<typeof createSkillActivationTools> {\n return createSkillActivationTools(this);\n }\n}\n\n/**\n * Escape special XML characters in a string.\n *\n * @param str - The string to escape\n * @returns Escaped string safe for XML content\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/parser.ts","../src/scanner.ts","../src/trust.ts","../src/activation.ts","../src/registry.ts"],"names":["TrustPolicyReason","SkillRegistryEvent","logger","createLogger","LogLevel","resolve","readFileSync","matter","resolvePath"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Skill System Types\n *\n * Core type definitions for the AgentForge Agent Skills system.\n * These types align with the Agent Skills specification (https://agentskills.io/specification).\n */\n\n// ─── Trust Policy Types ──────────────────────────────────────────────────\n\n/**\n * Trust level for a skill root directory.\n *\n * - `workspace` — Skills from the project workspace (highest trust, scripts allowed)\n * - `trusted` — Explicitly trusted skill roots (scripts allowed)\n * - `untrusted` — Untrusted roots like community packs (scripts blocked by default)\n */\nexport type TrustLevel = 'workspace' | 'trusted' | 'untrusted';\n\n/**\n * Configuration for a skill root with an explicit trust level.\n *\n * @example\n * ```ts\n * const roots: SkillRootConfig[] = [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community-skills', trust: 'untrusted' },\n * ];\n * ```\n */\nexport interface SkillRootConfig {\n /** Directory path to scan for skills */\n path: string;\n /** Trust level assigned to all skills discovered from this root */\n trust: TrustLevel;\n}\n\n/**\n * Policy decision returned by trust enforcement checks.\n */\nexport interface TrustPolicyDecision {\n /** Whether the action is allowed */\n allowed: boolean;\n /** Machine-readable reason code for auditing */\n reason: TrustPolicyReason;\n /** Human-readable explanation */\n message: string;\n}\n\n/**\n * Reason codes for trust policy decisions.\n *\n * Used for structured logging and auditing of guardrail behavior.\n */\nexport enum TrustPolicyReason {\n /** Resource is not a script — no trust check needed */\n NOT_SCRIPT = 'not-script',\n /** Skill root has workspace trust — scripts allowed */\n WORKSPACE_TRUST = 'workspace-trust',\n /** Skill root has explicit trusted status — scripts allowed */\n TRUSTED_ROOT = 'trusted-root',\n /** Skill root is untrusted — scripts denied by default */\n UNTRUSTED_SCRIPT_DENIED = 'untrusted-script-denied',\n /** Untrusted script access was explicitly allowed via config override */\n UNTRUSTED_SCRIPT_ALLOWED = 'untrusted-script-allowed-override',\n /** Trust level is unknown — treated as untrusted for security */\n UNKNOWN_TRUST_LEVEL = 'unknown-trust-level',\n}\n\n/**\n * Parsed metadata from a SKILL.md frontmatter block.\n *\n * Required fields: `name`, `description`.\n * All other fields are optional per the Agent Skills spec.\n */\nexport interface SkillMetadata {\n /** Skill name (1-64 chars, lowercase alphanumeric + hyphens, must match parent dir name) */\n name: string;\n /** Human-readable description (1-1024 chars) */\n description: string;\n /** SPDX license identifier */\n license?: string;\n /** List of compatible agent frameworks / tool hosts */\n compatibility?: string[];\n /** Arbitrary key-value metadata (author, version, etc.) */\n metadata?: Record<string, unknown>;\n /** Tools that this skill is allowed to use */\n allowedTools?: string[];\n}\n\n/**\n * A fully resolved skill entry in the registry.\n *\n * Contains parsed metadata plus internal tracking fields\n * that are not part of the SKILL.md frontmatter.\n */\nexport interface Skill {\n /** Parsed frontmatter metadata */\n metadata: SkillMetadata;\n /** Absolute path to the skill directory */\n skillPath: string;\n /** Which configured skill root this was discovered from */\n rootPath: string;\n /** Trust level assigned to this skill (inherited from root config) */\n trustLevel: TrustLevel;\n}\n\n/**\n * Configuration for the SkillRegistry.\n */\nexport interface SkillRegistryConfig {\n /**\n * Array of directory paths to scan for skills.\n *\n * Each entry can be a plain string (defaults to `'untrusted'` trust level)\n * or a `SkillRootConfig` object with an explicit trust level.\n *\n * Paths may be absolute or relative (resolved against `cwd`).\n * The `~` prefix is expanded to `$HOME`.\n *\n * @example\n * ```ts\n * // Simple string roots (default to 'untrusted')\n * skillRoots: ['.agentskills', '~/.agentskills']\n *\n * // Trust-aware roots\n * skillRoots: [\n * { path: '.agentskills', trust: 'workspace' },\n * { path: '~/.agentskills', trust: 'trusted' },\n * { path: '/shared/community', trust: 'untrusted' },\n * ]\n * ```\n */\n skillRoots: Array<string | SkillRootConfig>;\n\n /**\n * Feature flag to enable Agent Skills in system prompts.\n *\n * When `false` (default), `generatePrompt()` returns an empty string\n * so agents operate with unmodified system prompts.\n *\n * @default false\n */\n enabled?: boolean;\n\n /**\n * Maximum number of skills to include in generated prompts.\n *\n * Caps prompt token usage when many skills are discovered.\n * Skills are included in discovery order (first root first).\n * When undefined, all discovered skills are included.\n */\n maxDiscoveredSkills?: number;\n\n /**\n * Allow script resources from untrusted roots.\n *\n * When `true`, scripts from `scripts/` directories in untrusted\n * skill roots are returned instead of being denied. This disables\n * the default-deny policy for untrusted scripts.\n *\n * **Security warning:** Only enable when you have reviewed all\n * skill packs from untrusted roots.\n *\n * @default false\n */\n allowUntrustedScripts?: boolean;\n}\n\n/**\n * Options for `SkillRegistry.generatePrompt()`.\n */\nexport interface SkillPromptOptions {\n /**\n * Subset of skill names to include in the generated prompt.\n *\n * When provided, only skills matching these names appear in the\n * `<available_skills>` XML block. This enables creating focused\n * agents with different skill sets from the same registry.\n *\n * When omitted or empty, all discovered skills are included.\n *\n * @example ['code-review', 'testing-strategy']\n */\n skills?: string[];\n}\n\n/**\n * Events emitted by the SkillRegistry during discovery and usage.\n */\nexport enum SkillRegistryEvent {\n /** Emitted when a valid skill is discovered during scanning */\n SKILL_DISCOVERED = 'skill:discovered',\n /** Emitted when a skill parse or validation issue is encountered */\n SKILL_WARNING = 'skill:warning',\n /** Emitted when a skill is activated (full body loaded) */\n SKILL_ACTIVATED = 'skill:activated',\n /** Emitted when a skill resource file is loaded */\n SKILL_RESOURCE_LOADED = 'skill:resource-loaded',\n /** Emitted when a trust policy denies access to a resource */\n TRUST_POLICY_DENIED = 'trust:policy-denied',\n /** Emitted when a trust policy allows access (for auditing) */\n TRUST_POLICY_ALLOWED = 'trust:policy-allowed',\n}\n\n/**\n * Event handler type for skill registry events.\n */\nexport type SkillEventHandler = (data: unknown) => void;\n\n/**\n * Result of parsing a single SKILL.md file.\n */\nexport interface SkillParseResult {\n /** Whether parsing and validation succeeded */\n success: boolean;\n /** Parsed metadata (present when success is true) */\n metadata?: SkillMetadata;\n /** The raw markdown body below the frontmatter (present when success is true) */\n body?: string;\n /** Error description (present when success is false) */\n error?: string;\n}\n\n/**\n * Validation error detail.\n */\nexport interface SkillValidationError {\n /** Which field failed validation */\n field: string;\n /** Human-readable error message */\n message: string;\n}\n","/**\n * SKILL.md Frontmatter Parser\n *\n * Parses YAML frontmatter from SKILL.md files and validates\n * against the Agent Skills specification constraints.\n *\n * @see https://agentskills.io/specification\n */\n\nimport matter from 'gray-matter';\nimport type { SkillMetadata, SkillParseResult, SkillValidationError } from './types.js';\n\n/**\n * Skill name validation constraints (per spec).\n *\n * - 1-64 characters\n * - Lowercase alphanumeric and hyphens only\n * - No leading, trailing, or consecutive hyphens\n */\nconst SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\nconst SKILL_NAME_MAX_LENGTH = 64;\nconst SKILL_DESCRIPTION_MAX_LENGTH = 1024;\n\n/**\n * Validate the `name` field per the Agent Skills spec.\n *\n * @param name - The name value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillName(name: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (name === undefined || name === null) {\n errors.push({ field: 'name', message: 'name is required' });\n return errors;\n }\n\n if (typeof name !== 'string') {\n errors.push({ field: 'name', message: 'name must be a string' });\n return errors;\n }\n\n if (name.length === 0) {\n errors.push({ field: 'name', message: 'name must not be empty' });\n return errors;\n }\n\n if (name.length > SKILL_NAME_MAX_LENGTH) {\n errors.push({\n field: 'name',\n message: `name must be at most ${SKILL_NAME_MAX_LENGTH} characters (got ${name.length})`,\n });\n return errors;\n }\n\n if (!SKILL_NAME_PATTERN.test(name)) {\n errors.push({\n field: 'name',\n message: 'name must be lowercase alphanumeric with hyphens, no leading/trailing/consecutive hyphens',\n });\n }\n\n if (name.includes('--')) {\n errors.push({\n field: 'name',\n message: 'name must not contain consecutive hyphens',\n });\n }\n\n return errors;\n}\n\n/**\n * Validate the `description` field per the Agent Skills spec.\n *\n * @param description - The description value from frontmatter\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillDescription(description: unknown): SkillValidationError[] {\n const errors: SkillValidationError[] = [];\n\n if (description === undefined || description === null) {\n errors.push({ field: 'description', message: 'description is required' });\n return errors;\n }\n\n if (typeof description !== 'string') {\n errors.push({ field: 'description', message: 'description must be a string' });\n return errors;\n }\n\n if (description.trim().length === 0) {\n errors.push({ field: 'description', message: 'description must not be empty' });\n return errors;\n }\n\n if (description.length > SKILL_DESCRIPTION_MAX_LENGTH) {\n errors.push({\n field: 'description',\n message: `description must be at most ${SKILL_DESCRIPTION_MAX_LENGTH} characters (got ${description.length})`,\n });\n }\n\n return errors;\n}\n\n/**\n * Validate that the skill name matches its parent directory name (per spec).\n *\n * @param name - The name from frontmatter\n * @param dirName - The parent directory name\n * @returns Array of validation errors (empty = valid)\n */\nexport function validateSkillNameMatchesDir(name: string, dirName: string): SkillValidationError[] {\n if (name !== dirName) {\n return [{\n field: 'name',\n message: `name \"${name}\" must match parent directory name \"${dirName}\"`,\n }];\n }\n return [];\n}\n\n/**\n * Parse and validate a SKILL.md file's raw content.\n *\n * Extracts YAML frontmatter using gray-matter, then validates\n * required and optional fields against spec constraints.\n *\n * @param content - Raw file content of the SKILL.md\n * @param dirName - Parent directory name for name-match validation\n * @returns Parse result with metadata or error\n */\nexport function parseSkillContent(content: string, dirName: string): SkillParseResult {\n let parsed: matter.GrayMatterFile<string>;\n\n try {\n parsed = matter(content);\n } catch (err) {\n return {\n success: false,\n error: `Failed to parse frontmatter: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n const data = parsed.data;\n\n // Validate required fields\n const errors: SkillValidationError[] = [\n ...validateSkillName(data.name),\n ...validateSkillDescription(data.description),\n ];\n\n // If name is valid, validate it matches directory name\n if (typeof data.name === 'string' && data.name.length > 0 && SKILL_NAME_PATTERN.test(data.name)) {\n errors.push(...validateSkillNameMatchesDir(data.name, dirName));\n }\n\n if (errors.length > 0) {\n return {\n success: false,\n error: errors.map((e) => `${e.field}: ${e.message}`).join('; '),\n };\n }\n\n // Build metadata from validated fields\n const metadata: SkillMetadata = {\n name: data.name as string,\n description: data.description as string,\n };\n\n // Optional fields\n if (data.license !== undefined) {\n metadata.license = String(data.license);\n }\n\n if (Array.isArray(data.compatibility)) {\n metadata.compatibility = data.compatibility.map(String);\n }\n\n if (data.metadata !== undefined && typeof data.metadata === 'object' && data.metadata !== null) {\n metadata.metadata = data.metadata as Record<string, unknown>;\n }\n\n if (Array.isArray(data['allowed-tools'])) {\n metadata.allowedTools = data['allowed-tools'].map(String);\n }\n\n return {\n success: true,\n metadata,\n body: parsed.content,\n };\n}\n","/**\n * Skill Directory Scanner\n *\n * Scans configured skill roots for directories containing valid SKILL.md files.\n * Returns a list of candidate skill paths for the parser to process.\n */\n\nimport { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';\nimport { resolve, basename } from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:scanner', { level: LogLevel.INFO });\n\n/**\n * Discovered skill candidate — a directory containing a SKILL.md file.\n */\nexport interface SkillCandidate {\n /** Absolute path to the skill directory */\n skillPath: string;\n /** The parent directory name (expected to match the skill name) */\n dirName: string;\n /** Raw content of the SKILL.md file */\n content: string;\n /** Which configured root this came from */\n rootPath: string;\n}\n\n/**\n * Expand `~` prefix to the user's home directory.\n */\nexport function expandHome(p: string): string {\n if (p.startsWith('~/') || p === '~') {\n return resolve(homedir(), p.slice(2));\n }\n return p;\n}\n\n/**\n * Scan a single skill root for directories containing SKILL.md.\n *\n * @param rootPath - The root directory to scan (may not exist)\n * @returns Array of valid skill candidates found under this root\n */\nexport function scanSkillRoot(rootPath: string): SkillCandidate[] {\n const resolvedRoot = resolve(expandHome(rootPath));\n const candidates: SkillCandidate[] = [];\n\n if (!existsSync(resolvedRoot)) {\n logger.debug('Skill root does not exist, skipping', { rootPath: resolvedRoot });\n return candidates;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(resolvedRoot);\n } catch (err) {\n logger.warn('Failed to read skill root directory', {\n rootPath: resolvedRoot,\n error: err instanceof Error ? err.message : String(err),\n });\n return candidates;\n }\n\n for (const entry of entries) {\n const entryPath = resolve(resolvedRoot, entry);\n\n // Only process directories\n let stat;\n try {\n stat = statSync(entryPath);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) {\n continue;\n }\n\n // Check for SKILL.md inside the directory\n const skillMdPath = resolve(entryPath, 'SKILL.md');\n if (!existsSync(skillMdPath)) {\n continue;\n }\n\n // Read the SKILL.md content\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n candidates.push({\n skillPath: entryPath,\n dirName: basename(entryPath),\n content,\n rootPath: resolvedRoot,\n });\n } catch (err) {\n logger.warn('Failed to read SKILL.md', {\n path: skillMdPath,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n logger.debug('Scanned skill root', {\n rootPath: resolvedRoot,\n candidatesFound: candidates.length,\n });\n\n return candidates;\n}\n\n/**\n * Scan multiple skill roots for directories containing SKILL.md.\n *\n * @param skillRoots - Array of root paths to scan\n * @returns Array of all skill candidates found across all roots\n */\nexport function scanAllSkillRoots(skillRoots: string[]): SkillCandidate[] {\n const allCandidates: SkillCandidate[] = [];\n\n for (const root of skillRoots) {\n const candidates = scanSkillRoot(root);\n allCandidates.push(...candidates);\n }\n\n logger.info('Skill discovery complete', {\n rootsScanned: skillRoots.length,\n totalCandidates: allCandidates.length,\n });\n\n return allCandidates;\n}\n","/**\n * Skill Trust Policy Engine\n *\n * Enforces trust-level-based access control for skill resources.\n * Scripts from untrusted roots are denied by default unless explicitly allowed.\n *\n * Trust levels:\n * - `workspace` — Project-local skills, highest trust. Scripts always allowed.\n * - `trusted` — Explicitly trusted roots. Scripts allowed.\n * - `untrusted` — Community or third-party skills. Scripts denied by default.\n *\n * @see https://agentskills.io/specification\n */\n\nimport type { TrustLevel, TrustPolicyDecision, SkillRootConfig } from './types.js';\nimport { TrustPolicyReason } from './types.js';\n\n// ─── Constants ───────────────────────────────────────────────────────────\n\n/**\n * Resource path prefix that requires trust enforcement.\n *\n * Only resources under `scripts/` are subject to trust policy checks.\n * Other directories (references/, assets/, etc.) are always accessible.\n */\nconst SCRIPT_PATH_PREFIX = 'scripts/';\nconst SCRIPT_PATH_EXACT = 'scripts';\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Normalize a skill root config entry.\n *\n * String entries default to `'untrusted'` trust level for safe defaults.\n *\n * @param root - A string path or SkillRootConfig object\n * @returns Normalized SkillRootConfig with explicit trust level\n */\nexport function normalizeRootConfig(root: string | SkillRootConfig): SkillRootConfig {\n if (typeof root === 'string') {\n return { path: root, trust: 'untrusted' };\n }\n return root;\n}\n\n/**\n * Check whether a resource path refers to a script.\n *\n * A resource is considered a script if its relative path starts with\n * `scripts/` or is exactly `scripts`, after normalizing path separators,\n * stripping leading \"./\" segments, and ignoring case.\n *\n * @param resourcePath - Relative path within the skill directory\n * @returns True if the resource is in the scripts/ directory\n */\nexport function isScriptResource(resourcePath: string): boolean {\n // Normalize to forward slashes and trim for consistent checking\n let normalized = resourcePath.trim().replace(/\\\\/g, '/');\n\n // Collapse repeated separators (e.g., \"scripts//setup.sh\" → \"scripts/setup.sh\")\n normalized = normalized.replace(/\\/+/g, '/');\n\n // Strip leading \"./\" segments (e.g., \"./scripts/setup.sh\" → \"scripts/setup.sh\")\n while (normalized.startsWith('./')) {\n normalized = normalized.slice(2);\n }\n\n // Case-insensitive comparison to handle case-insensitive file systems\n const lower = normalized.toLowerCase();\n\n return lower === SCRIPT_PATH_EXACT\n || lower.startsWith(SCRIPT_PATH_PREFIX);\n}\n\n// ─── Policy Engine ───────────────────────────────────────────────────────\n\n/**\n * Evaluate the trust policy for a resource access request.\n *\n * Non-script resources are always allowed regardless of trust level.\n * Script resources require `workspace` or `trusted` trust, or the\n * `allowUntrustedScripts` override to be enabled.\n *\n * @param resourcePath - Relative path to the resource within the skill directory\n * @param trustLevel - Trust level of the skill's root directory\n * @param allowUntrustedScripts - Override flag to permit untrusted scripts\n * @returns Policy decision with allow/deny, reason code, and message\n */\nexport function evaluateTrustPolicy(\n resourcePath: string,\n trustLevel: TrustLevel,\n allowUntrustedScripts: boolean = false,\n): TrustPolicyDecision {\n // Non-script resources — no policy enforcement needed\n if (!isScriptResource(resourcePath)) {\n return {\n allowed: true,\n reason: TrustPolicyReason.NOT_SCRIPT,\n message: 'Resource is not a script — no trust check required',\n };\n }\n\n // Script resources — check trust level\n switch (trustLevel) {\n case 'workspace':\n return {\n allowed: true,\n reason: TrustPolicyReason.WORKSPACE_TRUST,\n message: 'Script allowed — skill root has workspace trust',\n };\n\n case 'trusted':\n return {\n allowed: true,\n reason: TrustPolicyReason.TRUSTED_ROOT,\n message: 'Script allowed — skill root is explicitly trusted',\n };\n\n case 'untrusted':\n if (allowUntrustedScripts) {\n return {\n allowed: true,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_ALLOWED,\n message: 'Script from untrusted root allowed via allowUntrustedScripts override',\n };\n }\n return {\n allowed: false,\n reason: TrustPolicyReason.UNTRUSTED_SCRIPT_DENIED,\n message: `Script access denied — skill root is untrusted. ` +\n `Scripts from untrusted roots are blocked by default for security. ` +\n `To allow, set 'allowUntrustedScripts: true' in SkillRegistryConfig or ` +\n `promote the skill root to 'trusted' or 'workspace' trust level.`,\n };\n\n default:\n return {\n allowed: false,\n reason: TrustPolicyReason.UNKNOWN_TRUST_LEVEL,\n message: `Script access denied — trust level \"${trustLevel}\" is unknown and is treated as untrusted for security.`,\n };\n }\n}\n","/**\n * Skill Activation Tools\n *\n * Provides `activate-skill` and `read-skill-resource` tools built with\n * the AgentForge tool builder API. These tools enable agents to load\n * skill instructions on demand and access skill resources at runtime.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const [activateSkill, readSkillResource] = createSkillActivationTools(registry);\n * // activateSkill — load full SKILL.md body\n * // readSkillResource — load a resource file from a skill\n *\n * // Or use the convenience method:\n * const [activateSkill, readSkillResource] = registry.toActivationTools();\n * ```\n */\n\nimport { readFileSync, realpathSync } from 'node:fs';\nimport { resolve, relative, isAbsolute } from 'node:path';\nimport matter from 'gray-matter';\nimport { z } from 'zod';\nimport { ToolBuilder, ToolCategory, createLogger, LogLevel } from '@agentforge/core';\nimport type { Tool } from '@agentforge/core';\nimport type { SkillRegistry } from './registry.js';\nimport { SkillRegistryEvent, TrustPolicyReason } from './types.js';\nimport { evaluateTrustPolicy } from './trust.js';\n\nconst logger = createLogger('agentforge:skills:activation', { level: LogLevel.INFO });\n\n// ─── Schemas ─────────────────────────────────────────────────────────────\n\nconst activateSkillSchema = z.object({\n name: z.string().describe('The name of the skill to activate (e.g., \"code-review\")'),\n});\n\nconst readSkillResourceSchema = z.object({\n name: z.string().describe('The name of the skill that owns the resource'),\n path: z.string().describe('Relative path to the resource file within the skill directory (e.g., \"references/GUIDE.md\", \"scripts/setup.sh\")'),\n});\n\n// ─── Path Security ───────────────────────────────────────────────────────\n\n/**\n * Resolve a resource path within a skill root, blocking path traversal.\n *\n * @param skillPath - Absolute path to the skill directory\n * @param resourcePath - Relative path to the resource file\n * @returns Absolute path to the resource, or an error string\n */\nexport function resolveResourcePath(\n skillPath: string,\n resourcePath: string,\n): { success: true; resolvedPath: string } | { success: false; error: string } {\n // Reject absolute paths using platform-aware check\n if (isAbsolute(resourcePath)) {\n return { success: false, error: 'Absolute resource paths are not allowed' };\n }\n\n // Reject traversal via segment-based '..' detection\n // Split on both '/' and '\\' to handle cross-platform separators\n const segments = resourcePath.split(/[/\\\\]/);\n if (segments.some((seg) => seg === '..')) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Resolve and verify containment (final guard)\n const resolvedPath = resolve(skillPath, resourcePath);\n const resolvedSkillPath = resolve(skillPath);\n\n // Ensure the resolved path is within the skill directory\n const rel = relative(resolvedSkillPath, resolvedPath);\n if (rel.startsWith('..') || resolve(resolvedSkillPath, rel) !== resolvedPath) {\n return { success: false, error: 'Path traversal is not allowed — resource paths must stay within the skill directory' };\n }\n\n // Guard against symlink escapes: resolve real filesystem paths and\n // verify that the real target still sits under the real skill root.\n // This prevents a symlink inside the skill dir from pointing outside.\n try {\n const realSkillRoot = realpathSync(resolvedSkillPath);\n const realTarget = realpathSync(resolvedPath);\n const realRel = relative(realSkillRoot, realTarget);\n if (realRel.startsWith('..') || isAbsolute(realRel)) {\n return { success: false, error: 'Symlink target escapes the skill directory — access denied' };\n }\n } catch {\n // File doesn't exist yet (or can't be stat'd) — skip symlink check.\n // The caller (readFileSync) will produce a clear error if missing.\n }\n\n return { success: true, resolvedPath };\n}\n\n// ─── Tool Factories ──────────────────────────────────────────────────────\n\n/**\n * Create the `activate-skill` tool bound to a registry instance.\n *\n * Resolves the skill by name, reads the full SKILL.md file, and returns\n * the body content (below frontmatter).\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createActivateSkillTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof activateSkillSchema>, string> {\n return new ToolBuilder<z.infer<typeof activateSkillSchema>, string>()\n .name('activate-skill')\n .description(\n 'Activate an Agent Skill by name, loading its full instructions. ' +\n 'Returns the complete SKILL.md body content for the named skill. ' +\n 'Use this when you see a relevant skill in <available_skills> and want to follow its instructions.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'activation', 'agent-skills'])\n .schema(activateSkillSchema)\n .implement(async ({ name }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill activation failed — not found', { name, availableCount: availableNames.length });\n return errorMsg;\n }\n\n // Read the full SKILL.md body from disk (progressive disclosure)\n const skillMdPath = resolve(skill.skillPath, 'SKILL.md');\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n\n // Extract body below frontmatter\n const body = extractBody(content);\n\n logger.info('Skill activated', {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_ACTIVATED, {\n name: skill.metadata.name,\n skillPath: skill.skillPath,\n bodyLength: body.length,\n });\n\n return body;\n } catch (error) {\n const errorMsg = `Failed to read skill \"${name}\" instructions: ${error instanceof Error ? error.message : String(error)}`;\n logger.error('Skill activation failed — read error', {\n name,\n skillPath: skill.skillPath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create the `read-skill-resource` tool bound to a registry instance.\n *\n * Resolves the skill by name, validates the resource path (blocking\n * traversal), and returns the file content.\n *\n * @param registry - The SkillRegistry to resolve skills from\n * @returns An AgentForge Tool\n */\nexport function createReadSkillResourceTool(\n registry: SkillRegistry,\n): Tool<z.infer<typeof readSkillResourceSchema>, string> {\n return new ToolBuilder<z.infer<typeof readSkillResourceSchema>, string>()\n .name('read-skill-resource')\n .description(\n 'Read a resource file from an activated Agent Skill. ' +\n 'Returns the content of a file within the skill directory (e.g., references/, scripts/, assets/). ' +\n 'The path must be relative to the skill root and cannot traverse outside it.',\n )\n .category(ToolCategory.SKILLS)\n .tags(['skill', 'resource', 'agent-skills'])\n .schema(readSkillResourceSchema)\n .implement(async ({ name, path: resourcePath }) => {\n const skill = registry.get(name);\n\n if (!skill) {\n const availableNames = registry.getNames();\n const suggestion = availableNames.length > 0\n ? ` Available skills: ${availableNames.join(', ')}`\n : ' No skills are currently registered.';\n const errorMsg = `Skill \"${name}\" not found.${suggestion}`;\n\n logger.warn('Skill resource load failed — skill not found', { name, resourcePath });\n return errorMsg;\n }\n\n // Resolve and validate the resource path\n const pathResult = resolveResourcePath(skill.skillPath, resourcePath);\n if (!pathResult.success) {\n logger.warn('Skill resource load blocked — path traversal', {\n name,\n resourcePath,\n error: pathResult.error,\n });\n return pathResult.error;\n }\n\n // Enforce trust policy for script resources\n const policyDecision = evaluateTrustPolicy(\n resourcePath,\n skill.trustLevel,\n registry.getAllowUntrustedScripts(),\n );\n\n if (!policyDecision.allowed) {\n logger.warn('Skill resource load blocked — trust policy', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_DENIED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n message: policyDecision.message,\n });\n\n return policyDecision.message;\n }\n\n // Log allowed policy decisions for auditing (scripts only)\n if (policyDecision.reason !== TrustPolicyReason.NOT_SCRIPT) {\n logger.info('Skill resource trust policy — allowed', {\n name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n\n registry.emitEvent(SkillRegistryEvent.TRUST_POLICY_ALLOWED, {\n name: skill.metadata.name,\n resourcePath,\n trustLevel: skill.trustLevel,\n reason: policyDecision.reason,\n });\n }\n\n try {\n const content = readFileSync(pathResult.resolvedPath, 'utf-8');\n\n logger.info('Skill resource loaded', {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n registry.emitEvent(SkillRegistryEvent.SKILL_RESOURCE_LOADED, {\n name: skill.metadata.name,\n resourcePath,\n resolvedPath: pathResult.resolvedPath,\n contentLength: content.length,\n });\n\n return content;\n } catch (error) {\n const errorMsg = `Failed to read resource \"${resourcePath}\" from skill \"${name}\": ${error instanceof Error ? error.message : String(error)}`;\n logger.warn('Skill resource load failed — file not found or unreadable', {\n name,\n resourcePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return errorMsg;\n }\n })\n .build();\n}\n\n/**\n * Create both skill activation tools bound to a registry instance.\n *\n * @param registry - The SkillRegistry to bind tools to\n * @returns Array of both tools [activate-skill, read-skill-resource]\n */\nexport function createSkillActivationTools(\n registry: SkillRegistry,\n): [Tool<z.infer<typeof activateSkillSchema>, string>, Tool<z.infer<typeof readSkillResourceSchema>, string>] {\n return [\n createActivateSkillTool(registry),\n createReadSkillResourceTool(registry),\n ];\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Extract the body content below YAML frontmatter from a SKILL.md file.\n *\n * Delegates to `gray-matter` for consistent frontmatter handling across\n * the codebase (matches `parseSkillContent()` in parser.ts).\n *\n * @param content - The full SKILL.md file content\n * @returns The body content below the frontmatter\n */\nfunction extractBody(content: string): string {\n return matter(content).content.trim();\n}\n","/**\n * Skill Registry\n *\n * Central registry for discovering, storing, and querying Agent Skills.\n * Mirrors ToolRegistry but uses folder-based auto-discovery instead\n * of programmatic registration.\n *\n * @see https://agentskills.io/specification\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills'],\n * });\n *\n * // Query discovered skills\n * const skill = registry.get('code-review');\n * const allSkills = registry.getAll();\n *\n * // Listen for events\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n\nimport type {\n Skill,\n SkillRegistryConfig,\n SkillPromptOptions,\n SkillEventHandler,\n TrustLevel,\n} from './types.js';\nimport { SkillRegistryEvent } from './types.js';\nimport { scanAllSkillRoots, expandHome } from './scanner.js';\nimport { parseSkillContent } from './parser.js';\nimport { createSkillActivationTools } from './activation.js';\nimport { normalizeRootConfig } from './trust.js';\nimport { resolve as resolvePath } from 'node:path';\nimport { createLogger, LogLevel } from '@agentforge/core';\n\nconst logger = createLogger('agentforge:skills:registry', { level: LogLevel.INFO });\n\n/**\n * Skill Registry — auto-discovers skills from configured folder paths.\n *\n * Parallel to ToolRegistry:\n * | ToolRegistry | SkillRegistry |\n * |--------------------------|------------------------------------------|\n * | registry.register(tool) | new SkillRegistry({ skillRoots }) |\n * | registry.get('name') | skillRegistry.get('name') |\n * | registry.getAll() | skillRegistry.getAll() |\n * | registry.has('name') | skillRegistry.has('name') |\n * | registry.size() | skillRegistry.size() |\n * | registry.generatePrompt()| skillRegistry.generatePrompt() |\n * | registry.toLangChainTools()| skillRegistry.toActivationTools() |\n */\nexport class SkillRegistry {\n private skills: Map<string, Skill> = new Map();\n private eventHandlers: Map<SkillRegistryEvent, Set<SkillEventHandler>> = new Map();\n private readonly config: SkillRegistryConfig;\n private scanErrors: Array<{ path: string; error: string }> = [];\n /** Maps resolved root paths → trust levels for skill trust assignment */\n private rootTrustMap: Map<string, TrustLevel> = new Map();\n\n /**\n * Create a SkillRegistry and immediately scan configured roots for skills.\n *\n * @param config - Registry configuration with skill root paths\n *\n * @example\n * ```ts\n * const registry = new SkillRegistry({\n * skillRoots: ['.agentskills', '~/.agentskills', './project-skills'],\n * });\n * console.log(`Discovered ${registry.size()} skills`);\n * ```\n */\n constructor(config: SkillRegistryConfig) {\n this.config = config;\n this.discover();\n }\n\n /**\n * Scan all configured roots and populate the registry.\n *\n * Called automatically during construction. Can be called again\n * to re-scan (clears existing skills first).\n */\n discover(): void {\n this.skills.clear();\n this.scanErrors = [];\n this.rootTrustMap.clear();\n\n // Normalize roots: extract plain paths for the scanner and build trust map\n const normalizedRoots = this.config.skillRoots.map(normalizeRootConfig);\n const plainPaths = normalizedRoots.map((r) => r.path);\n\n // Build trust map (resolve paths to match scanner output)\n for (const root of normalizedRoots) {\n const resolvedPath = resolvePath(expandHome(root.path));\n this.rootTrustMap.set(resolvedPath, root.trust);\n }\n\n const candidates = scanAllSkillRoots(plainPaths);\n\n let successCount = 0;\n let warningCount = 0;\n\n for (const candidate of candidates) {\n const result = parseSkillContent(candidate.content, candidate.dirName);\n\n if (!result.success) {\n warningCount++;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: result.error || 'Unknown parse error',\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n error: result.error,\n });\n logger.warn('Skipping invalid skill', {\n skillPath: candidate.skillPath,\n ...(result.error ? { error: result.error } : {}),\n });\n continue;\n }\n\n const skill: Skill = {\n metadata: result.metadata!,\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n trustLevel: this.rootTrustMap.get(candidate.rootPath) ?? 'untrusted',\n };\n\n // Handle duplicate skill names — first root wins (deterministic precedence)\n if (this.skills.has(skill.metadata.name)) {\n const existing = this.skills.get(skill.metadata.name)!;\n warningCount++;\n const warningMsg = `Duplicate skill name \"${skill.metadata.name}\" from \"${candidate.rootPath}\" — ` +\n `keeping version from \"${existing.rootPath}\" (first root takes precedence)`;\n this.scanErrors.push({\n path: candidate.skillPath,\n error: warningMsg,\n });\n this.emit(SkillRegistryEvent.SKILL_WARNING, {\n skillPath: candidate.skillPath,\n rootPath: candidate.rootPath,\n duplicateOf: existing.skillPath,\n error: warningMsg,\n });\n logger.warn('Duplicate skill name, keeping first', {\n name: skill.metadata.name,\n kept: existing.skillPath,\n skipped: candidate.skillPath,\n });\n continue;\n }\n\n this.skills.set(skill.metadata.name, skill);\n successCount++;\n\n this.emit(SkillRegistryEvent.SKILL_DISCOVERED, skill);\n logger.debug('Skill discovered', {\n name: skill.metadata.name,\n description: skill.metadata.description.slice(0, 80),\n skillPath: skill.skillPath,\n });\n }\n\n logger.info('Skill registry populated', {\n rootsScanned: this.config.skillRoots.length,\n skillsDiscovered: successCount,\n warnings: warningCount,\n });\n }\n\n // ─── Query API (parallel to ToolRegistry) ──────────────────────────────\n\n /**\n * Get a skill by name.\n *\n * @param name - The skill name\n * @returns The skill, or undefined if not found\n *\n * @example\n * ```ts\n * const skill = registry.get('code-review');\n * if (skill) {\n * console.log(skill.metadata.description);\n * }\n * ```\n */\n get(name: string): Skill | undefined {\n return this.skills.get(name);\n }\n\n /**\n * Get all discovered skills.\n *\n * @returns Array of all skills\n *\n * @example\n * ```ts\n * const allSkills = registry.getAll();\n * console.log(`Total skills: ${allSkills.length}`);\n * ```\n */\n getAll(): Skill[] {\n return Array.from(this.skills.values());\n }\n\n /**\n * Check if a skill exists in the registry.\n *\n * @param name - The skill name\n * @returns True if the skill exists\n *\n * @example\n * ```ts\n * if (registry.has('code-review')) {\n * console.log('Skill available!');\n * }\n * ```\n */\n has(name: string): boolean {\n return this.skills.has(name);\n }\n\n /**\n * Get the number of discovered skills.\n *\n * @returns Number of skills in the registry\n *\n * @example\n * ```ts\n * console.log(`Registry has ${registry.size()} skills`);\n * ```\n */\n size(): number {\n return this.skills.size;\n }\n\n /**\n * Get all skill names.\n *\n * @returns Array of skill names\n */\n getNames(): string[] {\n return Array.from(this.skills.keys());\n }\n\n /**\n * Get errors/warnings from the last scan.\n *\n * Useful for diagnostics and observability.\n *\n * @returns Array of scan errors with paths\n */\n getScanErrors(): ReadonlyArray<{ path: string; error: string }> {\n return this.scanErrors;\n }\n\n /**\n * Check whether untrusted script access is allowed via config override.\n *\n * Used by activation tools to pass the override flag to trust policy checks.\n *\n * @returns True if `allowUntrustedScripts` is set in config\n */\n getAllowUntrustedScripts(): boolean {\n return this.config.allowUntrustedScripts ?? false;\n }\n\n /**\n * Get the `allowed-tools` list for a skill.\n *\n * Returns the `allowedTools` array from the skill's frontmatter metadata,\n * enabling agents to filter their tool set based on what the skill expects.\n *\n * @param name - The skill name\n * @returns Array of allowed tool names, or undefined if skill not found or field not set\n *\n * @example\n * ```ts\n * const allowed = registry.getAllowedTools('code-review');\n * if (allowed) {\n * const filteredTools = allTools.filter(t => allowed.includes(t.name));\n * }\n * ```\n */\n getAllowedTools(name: string): string[] | undefined {\n const skill = this.skills.get(name);\n return skill?.metadata.allowedTools;\n }\n\n // ─── Prompt Generation ─────────────────────────────────────────────────\n\n /**\n * Generate an `<available_skills>` XML block for system prompt injection.\n *\n * Returns an empty string when:\n * - `config.enabled` is `false` (default) — agents operate with unmodified prompts\n * - No skills match the filter criteria\n *\n * The output composes naturally with `toolRegistry.generatePrompt()` —\n * simply concatenate both into the system prompt.\n *\n * @param options - Optional filtering (subset of skill names)\n * @returns XML string or empty string\n *\n * @example\n * ```ts\n * // All skills\n * const xml = registry.generatePrompt();\n *\n * // Subset for a focused agent\n * const xml = registry.generatePrompt({ skills: ['code-review', 'testing'] });\n *\n * // Compose with tool prompt\n * const systemPrompt = [\n * toolRegistry.generatePrompt(),\n * skillRegistry.generatePrompt(),\n * ].filter(Boolean).join('\\n\\n');\n * ```\n */\n generatePrompt(options?: SkillPromptOptions): string {\n // Feature flag gate — disabled by default\n if (!this.config.enabled) {\n logger.debug('Skill prompt generation skipped (disabled)', {\n enabled: this.config.enabled ?? false,\n });\n return '';\n }\n\n // Resolve which skills to include\n let skills = this.getAll();\n\n // Apply subset filter if provided\n if (options?.skills && options.skills.length > 0) {\n const requested = new Set(options.skills);\n skills = skills.filter((s) => requested.has(s.metadata.name));\n }\n\n // Apply maxDiscoveredSkills cap\n if (this.config.maxDiscoveredSkills !== undefined && this.config.maxDiscoveredSkills >= 0) {\n skills = skills.slice(0, this.config.maxDiscoveredSkills);\n }\n\n // No skills — return empty string\n if (skills.length === 0) {\n logger.debug('Skill prompt generation produced empty result', {\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n ...(this.config.maxDiscoveredSkills !== undefined\n ? { maxCap: this.config.maxDiscoveredSkills }\n : {}),\n });\n return '';\n }\n\n // Generate XML\n const skillEntries = skills.map((skill) => {\n const lines = [\n ' <skill>',\n ` <name>${escapeXml(skill.metadata.name)}</name>`,\n ` <description>${escapeXml(skill.metadata.description)}</description>`,\n ` <location>${escapeXml(skill.skillPath)}</location>`,\n ' </skill>',\n ];\n return lines.join('\\n');\n });\n\n const xml = `<available_skills>\\n${skillEntries.join('\\n')}\\n</available_skills>`;\n\n // Estimate token count (~4 chars per token, rough heuristic)\n const estimatedTokens = Math.ceil(xml.length / 4);\n\n logger.info('Skill prompt generated', {\n skillCount: skills.length,\n totalDiscovered: this.size(),\n filterApplied: !!(options?.skills && options.skills.length > 0),\n ...(this.config.maxDiscoveredSkills !== undefined\n ? { maxCap: this.config.maxDiscoveredSkills }\n : {}),\n estimatedTokens,\n xmlLength: xml.length,\n });\n\n return xml;\n }\n\n // ─── Event System ──────────────────────────────────────────────────────\n\n /**\n * Register an event handler.\n *\n * @param event - The event to listen for\n * @param handler - The handler function\n *\n * @example\n * ```ts\n * registry.on(SkillRegistryEvent.SKILL_DISCOVERED, (skill) => {\n * console.log('Found skill:', skill.metadata.name);\n * });\n * ```\n */\n on(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler);\n }\n\n /**\n * Unregister an event handler.\n *\n * @param event - The event to stop listening for\n * @param handler - The handler function to remove\n */\n off(event: SkillRegistryEvent, handler: SkillEventHandler): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n\n /**\n * Emit an event to all registered handlers.\n *\n * @param event - The event to emit\n * @param data - The event data\n * @private\n */\n private emit(event: SkillRegistryEvent, data: unknown): void {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(data);\n } catch (error) {\n logger.error('Skill event handler error', {\n event,\n error: error instanceof Error ? error.message : String(error),\n ...(error instanceof Error && error.stack ? { stack: error.stack } : {}),\n });\n }\n });\n }\n }\n\n /**\n * Emit an event (public API for activation tools).\n *\n * Used by skill activation tools to emit `skill:activated` and\n * `skill:resource-loaded` events through the registry's event system.\n *\n * @param event - The event to emit\n * @param data - The event data\n */\n emitEvent(event: SkillRegistryEvent, data: unknown): void {\n this.emit(event, data);\n }\n\n // ─── Tool Integration ────────────────────────────────────────────────\n\n /**\n * Create activation tools pre-wired to this registry instance.\n *\n * Returns `activate-skill` and `read-skill-resource` tools that\n * agents can use to load skill instructions and resources on demand.\n *\n * @returns Array of [activate-skill, read-skill-resource] tools\n *\n * @example\n * ```ts\n * const agent = createReActAgent({\n * model: llm,\n * tools: [\n * ...toolRegistry.toLangChainTools(),\n * ...skillRegistry.toActivationTools(),\n * ],\n * });\n * ```\n */\n toActivationTools(): ReturnType<typeof createSkillActivationTools> {\n return createSkillActivationTools(this);\n }\n}\n\n/**\n * Escape special XML characters in a string.\n *\n * @param str - The string to escape\n * @returns Escaped string safe for XML content\n */\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge/skills",
3
- "version": "0.15.7",
3
+ "version": "0.15.9",
4
4
  "description": "Composable skill system for building modular TypeScript AI agents: author skills, register capabilities, and compose behaviors.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "README.md"
19
19
  ],
20
20
  "dependencies": {
21
- "@agentforge/core": "0.15.7",
21
+ "@agentforge/core": "0.15.9",
22
22
  "gray-matter": "^4.0.3",
23
23
  "zod": "^3.24.1"
24
24
  },