zidane 6.1.12 → 6.1.13
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/{acp-D-k-L0DX.js → acp-BqfKqQ9x.js} +2 -2
- package/dist/{acp-D-k-L0DX.js.map → acp-BqfKqQ9x.js.map} +1 -1
- package/dist/acp-cli.js +2 -2
- package/dist/acp.d.ts +1 -1
- package/dist/acp.js +1 -1
- package/dist/{agent-BJ1NC1pA.js → agent-CZ3WSWqR.js} +3 -3
- package/dist/agent-CZ3WSWqR.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat/pure.js +1 -1
- package/dist/chat.d.ts +4 -4
- package/dist/chat.js +4 -4
- package/dist/contexts/daytona.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{index-2MYNIBnZ.d.ts → index-X02SI0nt.d.ts} +2 -1
- package/dist/index-X02SI0nt.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/{login-DhnmYiia.js → login-Bp_tRj_e.js} +2 -2
- package/dist/{login-DhnmYiia.js.map → login-Bp_tRj_e.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/{resolve-CC8Lmwcj.js → resolve-HtxmBWs9.js} +11 -3
- package/dist/resolve-HtxmBWs9.js.map +1 -0
- package/dist/restate.d.ts +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/{skills-BjeXSRlQ.js → skills-BlmY7QhV.js} +2 -2
- package/dist/{skills-BjeXSRlQ.js.map → skills-BlmY7QhV.js.map} +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +2 -2
- package/dist/{tool-formatters-BWzn4rp_.d.ts → tool-formatters-kg8O6wHZ.d.ts} +2 -2
- package/dist/{tool-formatters-BWzn4rp_.d.ts.map → tool-formatters-kg8O6wHZ.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-CzLl7Y1I.d.ts → transcript-anchors-DAF4RbyU.d.ts} +2 -2
- package/dist/{transcript-anchors-CzLl7Y1I.d.ts.map → transcript-anchors-DAF4RbyU.d.ts.map} +1 -1
- package/dist/{transcript-anchors-BNpLnru1.js → transcript-anchors-DAf0Mr_9.js} +4 -4
- package/dist/{transcript-anchors-BNpLnru1.js.map → transcript-anchors-DAf0Mr_9.js.map} +1 -1
- package/dist/tui.d.ts +3 -3
- package/dist/tui.js +8 -10
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-BkGio0n2.js → turn-operations-D9p-y9EC.js} +8 -4
- package/dist/turn-operations-D9p-y9EC.js.map +1 -0
- package/dist/{turn-operations-BrYae3Rp.d.ts → turn-operations-zkZ1L0eb.d.ts} +3 -3
- package/dist/{turn-operations-BrYae3Rp.d.ts.map → turn-operations-zkZ1L0eb.d.ts.map} +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +3 -2
- package/dist/agent-BJ1NC1pA.js.map +0 -1
- package/dist/index-2MYNIBnZ.d.ts.map +0 -1
- package/dist/resolve-CC8Lmwcj.js.map +0 -1
- package/dist/turn-operations-BkGio0n2.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-HtxmBWs9.js","names":[],"sources":["../src/chat/project-root.ts","../src/chat/project-user-paths.ts","../src/skills/validate.ts","../src/skills/interpolate.ts","../src/xml.ts","../src/install/source.ts","../src/skills/activation.ts","../src/skills/allowed-tools.ts","../src/skills/catalog.ts","../src/skills/discovery.ts","../src/skills/writer.ts","../src/skills/resolve.ts"],"sourcesContent":["/**\n * Git root detection — walks parents from `cwd` looking for a `.git`\n * entry, returning the absolute path of the repo root or `null` when\n * the search reaches the filesystem root.\n *\n * Why parent-walk over `git rev-parse --show-toplevel`:\n *\n * - Zero dependencies (no shell-out, no git binary requirement,\n * works even when `git` is missing from `PATH`).\n * - Pure-sync, deterministic, easy to test against tmp dirs.\n * - Equally fast in practice — most lookups are a single `existsSync`.\n *\n * Recognizes `.git` as either:\n *\n * - A directory (standard repo layout).\n * - A file containing `gitdir: …` (worktrees + submodules).\n *\n * Bare repos (no working tree) are intentionally NOT detected here —\n * the TUI's data dir contract is \"project working tree\", and a bare\n * repo has no working files to scope sessions against.\n */\n\nimport { existsSync, statSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\n\n/**\n * Walk parents of `cwd` looking for a `.git` entry. Returns the\n * absolute path of the directory containing `.git`, or `null` when no\n * git repo is found above `cwd`.\n *\n * Stops at the filesystem root (`/`) — no infinite loop on `dirname`'s\n * idempotent root case (`dirname('/')` returns `/`).\n */\nexport function findGitRoot(cwd: string = process.cwd()): string | null {\n let dir = resolve(cwd)\n // Guard against pathological inputs (junction loops, mount cycles)\n // by bounding the walk. 64 levels is well past anything sane and\n // avoids a pathological infinite loop on misconfigured volumes.\n for (let depth = 0; depth < 64; depth++) {\n if (hasGitMarker(dir))\n return dir\n const parent = dirname(dir)\n if (parent === dir)\n return null // reached filesystem root\n dir = parent\n }\n return null\n}\n\n/**\n * `.git` exists as a directory (standard repo) OR as a file containing\n * a `gitdir:` pointer (worktree / submodule). Tolerant on stat failures\n * — a permission error on a parent directory shouldn't crash the walk.\n */\nfunction hasGitMarker(dir: string): boolean {\n const candidate = resolve(dir, '.git')\n try {\n if (!existsSync(candidate))\n return false\n const stat = statSync(candidate)\n return stat.isDirectory() || stat.isFile()\n }\n catch {\n return false\n }\n}\n","/**\n * Shared search-path builder for project + user config discovery.\n *\n * Both Skills (`skills/<name>/SKILL.md`) and MCP servers (`mcps.json`)\n * follow the same first-found-wins order:\n *\n * 1. `{project-root}/.agents/<sub>` — project, agnostic convention\n * 2. `{project-root}/.{prefix}/<sub>` — project, zidane (`.zidane` default)\n * 3. `~/.agents/<sub>` — user, agnostic\n * 4. `~/.{prefix}/<sub>` — user, zidane\n *\n * `{project-root}` is the git root walked up from `cwd` when present,\n * else `cwd` itself. This pairs with the project-scoped session\n * storage (`resolveStoragePaths`) so all three project-aware surfaces\n * — sessions, mcps, skills — anchor at the same `.{prefix}/`.\n *\n * Centralizing the pattern keeps the four paths in one place — a third\n * discovery surface (hooks, rules, …) gets the same convention for free\n * and stays in lock-step on a prefix bump.\n */\n\nimport { homedir } from 'node:os'\nimport { resolve } from 'node:path'\nimport { findGitRoot } from './project-root'\n\n/** A discovered path tagged with whether it lives in the project or the user dir. */\nexport interface ProjectUserPath {\n path: string\n source: 'project' | 'user'\n}\n\n/**\n * Resolve the four search paths for a given subdirectory (`skills`,\n * `mcps.json`, …). Returns absolute paths regardless of whether they\n * exist — the caller chooses to `existsSync`-filter or feed straight\n * into a tolerant discovery routine.\n */\nexport function projectUserPaths(opts: {\n /** Subdirectory or filename relative to each search root. E.g. `'skills'`, `'mcps.json'`. */\n subPath: string\n /** Discovery cwd. Default: `process.cwd()`. */\n cwd?: string\n /** User home directory. Default: `os.homedir()`. */\n home?: string\n /** Storage prefix. Leading dot tolerated. Default: `'.zidane'`. */\n prefix?: string\n}): ProjectUserPath[] {\n const cwd = opts.cwd ?? process.cwd()\n const home = opts.home ?? homedir()\n // Anchor the project search at the git root when one exists — so a\n // subdir invocation (e.g. `cd repo/packages/foo`) still finds the\n // repo-level `.zidane/mcps.json`. Falls back to `cwd` outside git.\n const projectRoot = findGitRoot(cwd) ?? cwd\n // `prefix` arrives as `.zidane` in `ResolvedConfig`; trim the leading dot\n // for the symmetric `.agents` / `.zidane` convention.\n const prefix = (opts.prefix ?? '.zidane').replace(/^\\./, '')\n return [\n { path: resolve(projectRoot, `.agents/${opts.subPath}`), source: 'project' },\n { path: resolve(projectRoot, `.${prefix}/${opts.subPath}`), source: 'project' },\n { path: resolve(home, `.agents/${opts.subPath}`), source: 'user' },\n { path: resolve(home, `.${prefix}/${opts.subPath}`), source: 'user' },\n ]\n}\n","/**\n * Strict validators for Agent Skills.\n *\n * Applied on the authoring path (`defineSkill`, `writeSkillToDisk`). Parser-time\n * validation is intentionally lenient — see `parseSkillFile` for diagnostic collection.\n */\n\nimport type { SkillConfig } from './types'\nimport { realpath } from 'node:fs/promises'\nimport { basename } from 'node:path'\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst NAME_MAX = 64\nconst DESCRIPTION_MAX = 1024\nconst COMPATIBILITY_MAX = 500\n\nconst SKILL_NAME_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/\nconst CONSECUTIVE_HYPHENS_RE = /--/\n\n// Accepts both Claude-Code-style PascalCase (`Bash`, `Read`) AND snake_case\n// (`skills_use`, `read_file`, `mcp_fs_read`) tool names. Spec leaves the\n// naming convention to the client.\nconst ALLOWED_TOOL_PATTERN_RE = /^([\\w-]+)(?:\\(([^)]*)\\))?$/\n\n// Path-sandbox regexes (hoisted to avoid per-call recompilation).\nconst ABS_WINDOWS_PATH_RE = /^[a-z]:[\\\\/]/i\nconst PATH_SEPARATOR_RE = /[\\\\/]/\nconst TRAILING_SLASHES_RE = /\\/+$/\n\n// ---------------------------------------------------------------------------\n// Validation result\n// ---------------------------------------------------------------------------\n\n/**\n * A single issue surfaced by skill-authoring validation.\n * Distinct from `ValidationResult` in `tools/validation.ts` (tool-input JSON\n * schema validation) — different domain, different module.\n */\nexport interface SkillValidationIssue {\n /** Stable machine-readable code for consumer matching. */\n code: string\n /** Human-readable description. */\n message: string\n /** Frontmatter field name the issue relates to, when applicable. */\n field?: string\n}\n\nexport interface SkillValidationResult {\n valid: boolean\n errors: SkillValidationIssue[]\n}\n\n// ---------------------------------------------------------------------------\n// Name validation (strict — spec rules)\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a skill name per the spec:\n * - 1–64 characters\n * - Lowercase alphanumeric + hyphens only\n * - Must not start or end with a hyphen\n * - Must not contain consecutive hyphens\n *\n * The parent-directory match is validated separately (it requires knowing the\n * skill's `location`, which this function does not).\n */\nexport function validateSkillName(name: string): boolean {\n if (typeof name !== 'string')\n return false\n if (name.length < 1 || name.length > NAME_MAX)\n return false\n if (CONSECUTIVE_HYPHENS_RE.test(name))\n return false\n return SKILL_NAME_RE.test(name)\n}\n\n// ---------------------------------------------------------------------------\n// Authoring-time validation (`defineSkill`, `writeSkillToDisk`)\n// ---------------------------------------------------------------------------\n\n/**\n * Strict validation for a skill that is about to be authored / written to disk.\n * Rejects anything that would violate the spec. Use the lenient parser path\n * (`parseSkillFile`) for loading third-party skills.\n */\nexport function validateSkillForWrite(skill: SkillConfig): SkillValidationResult {\n const errors: SkillValidationIssue[] = []\n\n // Name\n if (!validateSkillName(skill.name)) {\n errors.push({\n code: 'invalid-name',\n message: `Skill name \"${skill.name}\" must be 1-64 chars, lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens.`,\n field: 'name',\n })\n }\n\n // Name must match parent directory when location is present\n if (skill.location) {\n const dirName = basename(skill.baseDir ?? '')\n if (dirName && dirName !== skill.name) {\n errors.push({\n code: 'name-mismatch-directory',\n message: `Skill name \"${skill.name}\" must match parent directory name \"${dirName}\".`,\n field: 'name',\n })\n }\n }\n\n // Description\n if (typeof skill.description !== 'string' || skill.description.length < 1) {\n errors.push({\n code: 'missing-description',\n message: 'Skill description is required (non-empty).',\n field: 'description',\n })\n }\n else if (skill.description.length > DESCRIPTION_MAX) {\n errors.push({\n code: 'description-too-long',\n message: `Skill description must be at most ${DESCRIPTION_MAX} characters (got ${skill.description.length}).`,\n field: 'description',\n })\n }\n\n // Compatibility (optional)\n if (skill.compatibility !== undefined) {\n if (typeof skill.compatibility !== 'string' || skill.compatibility.length === 0) {\n errors.push({\n code: 'invalid-compatibility',\n message: 'Compatibility must be a non-empty string when provided.',\n field: 'compatibility',\n })\n }\n else if (skill.compatibility.length > COMPATIBILITY_MAX) {\n errors.push({\n code: 'compatibility-too-long',\n message: `Compatibility must be at most ${COMPATIBILITY_MAX} characters (got ${skill.compatibility.length}).`,\n field: 'compatibility',\n })\n }\n }\n\n // Metadata values must be strings per spec\n if (skill.metadata) {\n for (const [key, value] of Object.entries(skill.metadata)) {\n if (typeof value !== 'string') {\n errors.push({\n code: 'invalid-metadata-value',\n message: `Metadata value for \"${key}\" must be a string (spec: \"A map from string keys to string values\").`,\n field: 'metadata',\n })\n }\n }\n }\n\n // Allowed-tools entries must be parseable patterns\n if (skill.allowedTools) {\n for (const pattern of skill.allowedTools) {\n if (!ALLOWED_TOOL_PATTERN_RE.test(pattern)) {\n errors.push({\n code: 'invalid-allowed-tool-pattern',\n message: `Allowed-tools entry \"${pattern}\" is not a recognized pattern (expected \"ToolName\" or \"ToolName(arg:*)\").`,\n field: 'allowed-tools',\n })\n }\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n\n// ---------------------------------------------------------------------------\n// Resource path sandbox\n// ---------------------------------------------------------------------------\n\n/**\n * Validate that `relPath` stays inside `baseDir` when resolved.\n *\n * Rejects:\n * - Absolute paths (`/etc/passwd`, `C:\\…`)\n * - Parent traversal (`..` segments that escape baseDir)\n * - Null-byte tricks\n *\n * Returns `{ valid: true, absolutePath }` on success or `{ valid: false, error }`\n * with a human-readable reason.\n */\nexport function validateResourcePath(\n relPath: string,\n baseDir: string,\n): { valid: true, absolutePath: string } | { valid: false, error: string } {\n if (typeof relPath !== 'string' || relPath.length === 0)\n return { valid: false, error: 'Resource path must be a non-empty string.' }\n\n if (relPath.includes('\\0'))\n return { valid: false, error: 'Resource path contains a null byte.' }\n\n // Reject absolute paths upfront — both POSIX and Windows forms.\n if (relPath.startsWith('/') || ABS_WINDOWS_PATH_RE.test(relPath))\n return { valid: false, error: `Absolute paths are not allowed (\"${relPath}\").` }\n\n // Normalize and ensure we stay under baseDir.\n const segments: string[] = []\n for (const segment of relPath.split(PATH_SEPARATOR_RE)) {\n if (segment === '' || segment === '.')\n continue\n if (segment === '..') {\n if (segments.length === 0) {\n return {\n valid: false,\n error: `Resource path \"${relPath}\" escapes the skill directory.`,\n }\n }\n segments.pop()\n continue\n }\n segments.push(segment)\n }\n\n if (segments.length === 0)\n return { valid: false, error: 'Resource path resolves to the skill root itself.' }\n\n const absolutePath = `${baseDir.replace(TRAILING_SLASHES_RE, '')}/${segments.join('/')}`\n return { valid: true, absolutePath }\n}\n\n/**\n * Symlink-hardened variant of {@link validateResourcePath}: after the lexical\n * check passes, resolve both the target and `baseDir` through `realpath` and\n * re-confirm the target still lives under the skill directory. A symlink\n * placed inside the skill dir pointing at e.g. `/etc/passwd` passes the\n * lexical check but fails here.\n *\n * Falls back to the lexical verdict when `realpath` fails (target or baseDir\n * not present on the LOCAL filesystem) — the common causes are a remote\n * execution context (docker/sandbox, where the local realpath is meaningless\n * and the remote side resolves the path itself) or a not-yet-existing file.\n * The returned `absolutePath` is always the lexical one: it's what the\n * execution context resolves; realpath here is verification only.\n */\nexport async function validateResourcePathReal(\n relPath: string,\n baseDir: string,\n): Promise<{ valid: true, absolutePath: string } | { valid: false, error: string }> {\n const lexical = validateResourcePath(relPath, baseDir)\n if (!lexical.valid)\n return lexical\n\n try {\n const [realBase, realTarget] = await Promise.all([\n realpath(baseDir),\n realpath(lexical.absolutePath),\n ])\n const prefix = realBase.replace(TRAILING_SLASHES_RE, '')\n if (realTarget !== prefix && !realTarget.startsWith(`${prefix}/`)) {\n return {\n valid: false,\n error: `Resource path \"${relPath}\" escapes the skill directory via a symlink.`,\n }\n }\n }\n catch {\n // Local realpath unavailable — fall back to the lexical check.\n }\n return lexical\n}\n\n// ---------------------------------------------------------------------------\n// Allowed-tools matching\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a single `allowed-tools` entry into its tool name + optional argument pattern.\n *\n * Examples:\n * - `Read` → `{ tool: 'Read' }`\n * - `Bash(git:*)` → `{ tool: 'Bash', argPrefix: 'git' }`\n */\nexport function parseAllowedToolPattern(entry: string): { tool: string, argPrefix?: string } | null {\n const m = entry.trim().match(ALLOWED_TOOL_PATTERN_RE)\n if (!m)\n return null\n const tool = m[1]\n const arg = m[2]\n if (!arg)\n return { tool }\n\n // Accept `git:*` (prefix wildcard) and `git` (literal). Future: full glob.\n if (arg.endsWith(':*'))\n return { tool, argPrefix: arg.slice(0, -2) }\n return { tool, argPrefix: arg }\n}\n\n/**\n * Check whether a tool call (identified by its wire/displayName and argument input)\n * matches a skill's allow-list entry.\n *\n * Matching rules (Zidane's interpretation of the spec's unspecified syntax):\n * - Exact match: displayName === pattern (no parens).\n * - Prefix match: for `Tool(arg:*)`, displayName === 'Tool' AND **any** string\n * value in the input object starts with `arg`. This is intentionally\n * permissive: it doesn't depend on a convention about which property carries\n * the \"command\" (schemas vary across tools), and for the common\n * `shell({ command: 'git …' })` shape it behaves identically to a \"primary\n * string\" rule.\n * - For tools whose inputs carry no string values, the arg-match returns false.\n */\nexport function matchesAllowedTool(\n displayName: string,\n input: Record<string, unknown>,\n pattern: string,\n): boolean {\n const parsed = parseAllowedToolPattern(pattern)\n if (!parsed)\n return false\n if (parsed.tool !== displayName)\n return false\n if (parsed.argPrefix === undefined)\n return true\n\n // Match if any string input value starts with the arg prefix. More robust\n // than picking a single \"first\" value (object property order is a subtle\n // brittleness surface we avoid).\n for (const value of Object.values(input)) {\n if (typeof value === 'string' && value.startsWith(parsed.argPrefix))\n return true\n }\n return false\n}\n\n/**\n * Test whether a tool call is allowed by the union of `allowedTools` across a set\n * of active skills. Returns `true` when the union is empty (permissive default)\n * OR when any entry matches.\n */\nexport function isToolAllowedByUnion(\n displayName: string,\n input: Record<string, unknown>,\n union: readonly string[],\n): boolean {\n if (union.length === 0)\n return true\n return union.some(pattern => matchesAllowedTool(displayName, input, pattern))\n}\n","/**\n * Shell interpolation for skill instructions.\n *\n * The `!\\`command\\`` syntax runs shell commands as a preprocessing step\n * before skill content is sent to the agent. The command output replaces\n * the placeholder — the agent only sees the final result.\n *\n * Example:\n * - PR diff: !\\`gh pr diff\\`\n * → - PR diff: <actual diff output>\n */\n\nimport type { ExecutionContext, ExecutionHandle } from '../contexts'\nimport { errorMessage } from '../errors'\n\n/** Regex to match !`command` patterns in skill instructions */\nconst SHELL_INTERPOLATION_RE = /!`([^`]+)`/g\n\n/**\n * Replace every !\\`command\\` pattern with a static placeholder, without\n * executing anything. Used when shell interpolation is disabled\n * (`SkillsConfig.allowShellInterpolation: false`): skill content can be\n * third-party input, and running its embedded commands on activation\n * bypasses the allowed-tools gate.\n */\nexport function stripShellInterpolations(instructions: string): string {\n return instructions.replace(SHELL_INTERPOLATION_RE, '[shell interpolation disabled]')\n}\n\nexport interface InterpolateShellCommandsOptions {\n /**\n * Called once per !\\`command\\` that failed (non-zero exit or exec throw)\n * with the command text and the inline placeholder it was replaced with.\n * Lets callers surface a visible warning instead of activation silently\n * proceeding on partial content.\n */\n onFailure?: (command: string, placeholder: string) => void\n /**\n * Optional per-command approval gate, invoked BEFORE each !\\`command\\` runs.\n * Return `false` to skip executing that command — it is replaced with a\n * `[shell interpolation not approved]` placeholder instead of its output.\n * When omitted, every command runs (back-compat).\n */\n approve?: (command: string) => boolean | Promise<boolean>\n}\n\n/**\n * Interpolate shell commands in skill instructions.\n *\n * Runs each !\\`command\\` through the execution context and replaces\n * the placeholder with the command's stdout. If a command fails,\n * the placeholder is replaced with an error message (and\n * `options.onFailure` is notified when provided).\n *\n * @param instructions - Raw skill instructions with potential !\\`command\\` patterns\n * @param execution - The execution context to run commands in\n * @param handle - The active execution handle\n * @returns Instructions with all !\\`command\\` patterns replaced by output\n */\nexport async function interpolateShellCommands(\n instructions: string,\n execution: ExecutionContext,\n handle: ExecutionHandle,\n options: InterpolateShellCommandsOptions = {},\n): Promise<string> {\n const matches = [...instructions.matchAll(SHELL_INTERPOLATION_RE)]\n if (matches.length === 0)\n return instructions\n\n // Collect all commands with their positions for precise replacement\n const replacements: { index: number, length: number, output: string }[] = []\n\n for (const match of matches) {\n const command = match[1]\n const index = match.index!\n const length = match[0].length\n\n if (options.approve) {\n let approved = false\n try {\n approved = await options.approve(command)\n }\n catch {\n approved = false\n }\n if (!approved) {\n const placeholder = '[shell interpolation not approved]'\n options.onFailure?.(command, placeholder)\n replacements.push({ index, length, output: placeholder })\n continue\n }\n }\n\n try {\n const result = await execution.exec(handle, command, { timeout: 30 })\n if (result.exitCode === 0) {\n replacements.push({ index, length, output: result.stdout.trim() })\n }\n else {\n const placeholder = `[command failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}]`\n options.onFailure?.(command, placeholder)\n replacements.push({ index, length, output: placeholder })\n }\n }\n catch (err) {\n const placeholder = `[command error: ${errorMessage(err)}]`\n options.onFailure?.(command, placeholder)\n replacements.push({ index, length, output: placeholder })\n }\n }\n\n // Apply replacements in reverse order to preserve positions\n let result = instructions\n for (let i = replacements.length - 1; i >= 0; i--) {\n const { index, length, output } = replacements[i]\n result = result.slice(0, index) + output + result.slice(index + length)\n }\n\n return result\n}\n","/**\n * Minimal XML helpers used by catalog/result builders that emit\n * model-facing pseudo-XML (skills catalog, searchable_tools, tool_search\n * results, skill_content wrappers).\n *\n * Scope: attribute / text-node escaping only — we do NOT emit a full XML\n * document, the model sees these strings as free-form text. Centralised\n * here so the four near-identical copies in `agent.ts`, `skills/catalog.ts`,\n * `tools/skills-use.ts`, and `tools/tool-search.ts` don't drift.\n */\n\nconst RE_AMP = /&/g\nconst RE_LT = /</g\nconst RE_GT = />/g\nconst RE_QUOT = /\"/g\n\nexport function escapeXml(str: string): string {\n return str\n .replace(RE_AMP, '&')\n .replace(RE_LT, '<')\n .replace(RE_GT, '>')\n .replace(RE_QUOT, '"')\n}\n","/**\n * Shared install-source layer — the source-agnostic half of \"install a\n * thing from github/npm\". Extracted from the extensions installer so\n * SKILL installs (and any future installable artifact) reuse the exact\n * same spec grammar, fetch pipeline, and hardening instead of forking\n * them:\n *\n * - Spec grammar: `owner/repo[#ref][:subdir]`, `github:owner/repo`,\n * pasted GitHub URLs (including `/tree/<ref>/<path>`),\n * `pkg[@version]`, `@scope/pkg[@version]`.\n * - Fetch: `git clone --depth 1` (records the exact commit) with a\n * codeload-tarball fallback, npm registry resolve (exact versions +\n * dist-tags) + tarball download. Downloads are double-capped at\n * {@link MAX_DOWNLOAD_BYTES} (content-length header AND post-hoc for\n * chunked responses). Extraction requires `tar` on PATH.\n * - All side effects go through the injectable {@link InstallIo} seams\n * so tests stay offline and hosts can instrument.\n *\n * Flavor-specific concerns stay OUT of this module: candidate\n * enumeration, validation, target roots, provenance files, dependency\n * installs. Flavors subclass {@link InstallSourceError} to widen the\n * error-code union while keeping `.code`-based handling uniform.\n */\n\nimport { execFile } from 'node:child_process'\nimport { lstatSync, mkdirSync, realpathSync, rmSync, writeFileSync } from 'node:fs'\nimport { delimiter, join, resolve, sep } from 'node:path'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type InstallScope = 'project' | 'user'\n\nexport type InstallSource\n = | {\n kind: 'github'\n owner: string\n repo: string\n /** Branch, tag (`#ref` or `@ref`), or the `/tree/<ref>` URL segment. */\n ref?: string\n /** Repo-relative directory to root the search in (`:path` suffix). */\n subdir?: string\n }\n | { kind: 'npm', pkg: string, version?: string }\n\n/**\n * Base error for install pipelines. `code` is a plain string here so\n * flavors (extensions, skills) can widen it with their own codes while\n * callers keep a single `err.code` switch. The base layer itself only\n * throws `'invalid-source'` and `'fetch-failed'`.\n */\nexport class InstallSourceError extends Error {\n readonly code: string\n /** Set for candidate-selection errors — the names the caller can pick from. */\n readonly candidates?: readonly string[]\n constructor(code: string, message: string, candidates?: readonly string[]) {\n super(message)\n this.name = 'InstallSourceError'\n this.code = code\n if (candidates)\n this.candidates = candidates\n }\n}\n\n/**\n * Injectable side-effect seams — tests swap these to stay offline; hosts\n * normally omit the whole object.\n */\nexport interface InstallIo {\n fetch?: typeof fetch\n exec?: (cmd: string, args: readonly string[], opts: { cwd?: string, env?: Record<string, string> }) => Promise<{ ok: boolean, stdout: string, stderr: string }>\n which?: (cmd: string) => string | null\n}\n\nexport interface FetchSourceResult {\n /** Human-readable provenance, e.g. `npm:foo@1.2.3` / `github:owner/repo@main`. */\n provenance: string\n /** Exact commit SHA (git clone path only) — anchors update no-op checks. */\n commit?: string\n}\n\n// ---------------------------------------------------------------------------\n// Source spec parsing\n// ---------------------------------------------------------------------------\n\nconst GITHUB_TREE_URL_RE = /^(?:https?:\\/\\/)?(?:www\\.)?github\\.com\\/([^/\\s]+)\\/([^/\\s#@:]+?)(?:\\.git)?\\/tree\\/([^/\\s:]+)(?:\\/([^\\s:]+?))?\\/?$/\nconst GITHUB_URL_RE = /^(?:https?:\\/\\/)?(?:www\\.)?github\\.com\\/([^/\\s]+)\\/([^/\\s#@:]+?)(?:\\.git)?\\/?$/\nconst OWNER_REPO_RE = /^([\\w.-]+)\\/([\\w.-]+)$/\nconst GITHUB_REF_RE = /^[\\w./-]+$/\nconst NPM_NAME_RE = /^(@[\\w.-]+\\/[\\w.-]+|[\\w.-]+)(?:@([\\w.^~><=*-]+))?$/\n\n/** Structural validation for a `:subdir` suffix — repo-relative, no escapes. */\nfunction parseSubdir(rawSubdir: string, raw: string): string {\n const subdir = rawSubdir.replace(/^\\.\\//, '').replace(/\\/+$/, '')\n const segments = subdir.split('/')\n const bad = subdir.length === 0\n || subdir.startsWith('/')\n || subdir.includes('\\\\')\n || segments.some(s => s.length === 0 || s === '.' || s === '..')\n if (bad)\n throw new InstallSourceError('invalid-source', `\"${raw}\" has an invalid subdirectory — expected a repo-relative path (no leading /, no ..).`)\n return subdir\n}\n\n/**\n * Classify a raw source string:\n *\n * - `github:owner/repo`, `owner/repo`, GitHub URLs (including\n * `/tree/<ref>/<path>` links) → GitHub. Optional `#ref` (or the\n * legacy `@ref`) pins a branch/tag; optional `:path/to/dir` roots the\n * candidate search in a subdirectory: `owner/repo#branch:packages/x`.\n * - `@scope/pkg[@version]`, `pkg[@version]` → npm (no subdir support —\n * flavors expose their own selector for multi-candidate packages).\n *\n * The one ambiguity — `a/b` — is resolved as GitHub: npm's slash names\n * are always scoped (`@scope/…`), so a bare `owner/repo` can only be a\n * repo. Throws `invalid-source` on anything else.\n */\nexport function parseInstallSource(raw: string): InstallSource {\n const spec = raw.trim()\n if (spec.length === 0)\n throw new InstallSourceError('invalid-source', 'Empty source. Expected `owner/repo`, `github:owner/repo`, a GitHub URL, or an npm package name.')\n\n const explicitGithub = spec.startsWith('github:')\n const body = explicitGithub ? spec.slice('github:'.length) : spec\n\n // Pasted GitHub “tree” links carry both the ref and the subdir. Branch\n // names with slashes are inherently ambiguous in these URLs (GitHub has\n // the same problem) — the first segment after /tree/ is taken as the ref.\n const tree = GITHUB_TREE_URL_RE.exec(body)\n if (tree) {\n return {\n kind: 'github',\n owner: tree[1] as string,\n repo: tree[2] as string,\n ref: tree[3] as string,\n ...(tree[4] ? { subdir: parseSubdir(tree[4], raw) } : {}),\n }\n }\n\n const url = GITHUB_URL_RE.exec(body)\n if (url)\n return { kind: 'github', owner: url[1] as string, repo: url[2] as string }\n\n if (body.startsWith('@')) {\n if (explicitGithub)\n throw new InstallSourceError('invalid-source', `\"${raw}\" mixes the github: prefix with an npm scoped name.`)\n if (body.includes(':'))\n throw new InstallSourceError('invalid-source', `\"${raw}\": subdirectories (\\`:path\\`) are only supported for GitHub sources.`)\n const m = NPM_NAME_RE.exec(body)\n if (!m)\n throw new InstallSourceError('invalid-source', `\"${raw}\" is not a valid npm package spec.`)\n return { kind: 'npm', pkg: m[1] as string, ...(m[2] ? { version: m[2] } : {}) }\n }\n\n if (body.includes('/')) {\n // Shorthand grammar: owner/repo[#ref | @ref][:subdir]. The subdir is\n // split first (paths may contain `@`), then the ref — `#` preferred,\n // `@` kept for the originally-shipped syntax.\n const colonIdx = body.indexOf(':')\n const specPart = colonIdx === -1 ? body : body.slice(0, colonIdx)\n const subdir = colonIdx === -1 ? undefined : parseSubdir(body.slice(colonIdx + 1), raw)\n const hashIdx = specPart.indexOf('#')\n const refIdx = hashIdx >= 0 ? hashIdx : specPart.indexOf('@')\n const repoPart = refIdx === -1 ? specPart : specPart.slice(0, refIdx)\n const ref = refIdx === -1 ? undefined : specPart.slice(refIdx + 1)\n const m = OWNER_REPO_RE.exec(repoPart)\n if (!m || (ref !== undefined && !GITHUB_REF_RE.test(ref)))\n throw new InstallSourceError('invalid-source', `\"${raw}\" is not a valid GitHub repo spec (expected owner/repo, optionally #ref and :subdir).`)\n return {\n kind: 'github',\n owner: m[1] as string,\n repo: m[2] as string,\n ...(ref ? { ref } : {}),\n ...(subdir ? { subdir } : {}),\n }\n }\n\n if (explicitGithub)\n throw new InstallSourceError('invalid-source', `\"${raw}\" is missing the repo part (expected github:owner/repo).`)\n if (body.includes(':'))\n throw new InstallSourceError('invalid-source', `\"${raw}\": subdirectories (\\`:path\\`) are only supported for GitHub sources.`)\n const m = NPM_NAME_RE.exec(body)\n if (!m)\n throw new InstallSourceError('invalid-source', `\"${raw}\" is not a valid npm package spec.`)\n return { kind: 'npm', pkg: m[1] as string, ...(m[2] ? { version: m[2] } : {}) }\n}\n\n// ---------------------------------------------------------------------------\n// Fetch\n// ---------------------------------------------------------------------------\n\n/**\n * Materialize the source into `destDir` (created by the caller, assumed\n * empty). Returns the provenance string plus, for git clones, the exact\n * commit SHA (the tarball fallback can't know it — codeload doesn't\n * expose the resolved commit).\n */\nexport async function fetchInstallSource(\n source: InstallSource,\n destDir: string,\n io: InstallIo = {},\n onProgress?: (message: string) => void,\n): Promise<FetchSourceResult> {\n const exec = io.exec ?? defaultExec\n const which = io.which ?? defaultWhich\n const fetchImpl = io.fetch ?? fetch\n\n if (source.kind === 'github') {\n const label = `${source.owner}/${source.repo}${source.ref ? `@${source.ref}` : ''}${source.subdir ? `:${source.subdir}` : ''}`\n if (which('git')) {\n onProgress?.(`cloning github.com/${label}…`)\n // The whole repo is cloned even for `:subdir` installs — shallow +\n // single-branch keeps that cheap, and only the subdir is copied out.\n const args = ['clone', '--depth', '1', '--single-branch']\n if (source.ref)\n args.push('--branch', source.ref)\n args.push(`https://github.com/${source.owner}/${source.repo}.git`, destDir)\n // GIT_TERMINAL_PROMPT=0: a private/nonexistent repo must fail fast\n // with a clear error — git's interactive credential prompt would\n // otherwise leak into the host TUI and hang the install. Users who\n // want authenticated (SSH) fetches configure git itself:\n // git config --global url.\"git@github.com:\".insteadOf \"https://github.com/\"\n // — honored automatically since we shell out to the system git.\n const res = await exec('git', args, { env: { GIT_TERMINAL_PROMPT: '0' } })\n if (!res.ok) {\n const authFailure = /could not read username|terminal prompts disabled|authentication failed/i.test(res.stderr)\n const hint = authFailure\n ? ' (private repo? configure git for SSH: git config --global url.\"git@github.com:\".insteadOf \"https://github.com/\")'\n : ''\n throw new InstallSourceError('fetch-failed', `git clone failed for ${label}: ${lastLine(res.stderr)}${hint}`)\n }\n // Record the exact commit BEFORE dropping .git — this is what lets\n // a later update detect \"nothing changed\" without re-cloning.\n // Non-fatal: a missing SHA only degrades the no-op check.\n const head = await exec('git', ['rev-parse', 'HEAD'], { cwd: destDir })\n const commit = head.ok && /^[0-9a-f]{40}$/.test(head.stdout.trim()) ? head.stdout.trim() : undefined\n rmSync(join(destDir, '.git'), { recursive: true, force: true })\n return { provenance: `github:${label}`, ...(commit ? { commit } : {}) }\n }\n // No git on PATH — fall back to the codeload tarball (public repos only).\n onProgress?.(`downloading github.com/${label} tarball…`)\n const ref = source.ref ?? 'HEAD'\n const tarUrl = `https://codeload.github.com/${source.owner}/${source.repo}/tar.gz/${ref}`\n await downloadAndExtract(tarUrl, destDir, { exec, fetchImpl, which, what: label })\n return { provenance: `github:${label}` }\n }\n\n onProgress?.(`resolving npm:${source.pkg}…`)\n const { version, tarball } = await resolveNpmVersion(source, fetchImpl)\n onProgress?.(`downloading npm:${source.pkg}@${version}…`)\n await downloadAndExtract(tarball, destDir, { exec, fetchImpl, which, what: `${source.pkg}@${version}` })\n return { provenance: `npm:${source.pkg}@${version}` }\n}\n\n/**\n * Registry lookup shared by the fetch path and update no-op checks.\n * Exact versions and dist-tags only — range resolution is out of scope.\n */\nexport async function resolveNpmVersion(\n source: Extract<InstallSource, { kind: 'npm' }>,\n fetchImpl: typeof fetch,\n): Promise<{ version: string, tarball: string }> {\n const registryUrl = `https://registry.npmjs.org/${source.pkg.replace('/', '%2F')}`\n let meta: { 'versions'?: Record<string, { dist?: { tarball?: string } }>, 'dist-tags'?: Record<string, string> }\n try {\n const res = await fetchImpl(registryUrl)\n if (!res.ok)\n throw new Error(`registry returned ${res.status}`)\n meta = await res.json() as typeof meta\n }\n catch (err) {\n throw new InstallSourceError('fetch-failed', `Could not resolve npm package \"${source.pkg}\": ${errorText(err)}`)\n }\n const version = source.version && meta.versions?.[source.version]\n ? source.version\n : meta['dist-tags']?.[source.version ?? 'latest']\n const tarball = version ? meta.versions?.[version]?.dist?.tarball : undefined\n if (!version || !tarball) {\n throw new InstallSourceError(\n 'fetch-failed',\n `npm package \"${source.pkg}\" has no ${source.version ? `version/tag \"${source.version}\"` : 'latest version'} (exact versions and dist-tags only — ranges are not resolved).`,\n )\n }\n return { version, tarball }\n}\n\n/**\n * OOM guard: tarballs are buffered in memory before extraction, so an\n * unexpectedly huge (or hostile) URL must fail fast instead of ballooning\n * RSS. Install sources are source trees — 64MB is already generous.\n */\nexport const MAX_DOWNLOAD_BYTES = 64 * 1024 * 1024\n\nasync function downloadAndExtract(\n url: string,\n destDir: string,\n opts: { exec: NonNullable<InstallIo['exec']>, fetchImpl: typeof fetch, which: NonNullable<InstallIo['which']>, what: string },\n): Promise<void> {\n let bytes: ArrayBuffer\n try {\n const res = await opts.fetchImpl(url)\n if (!res.ok)\n throw new Error(`download returned ${res.status}`)\n const declared = Number(res.headers.get('content-length') ?? '0')\n if (declared > MAX_DOWNLOAD_BYTES)\n throw new Error(`archive is ${Math.round(declared / 1024 / 1024)}MB — larger than the ${MAX_DOWNLOAD_BYTES / 1024 / 1024}MB limit`)\n bytes = await res.arrayBuffer()\n // Chunked responses carry no content-length — enforce after the fact\n // (bounded harm: one oversized buffer, immediately released on throw).\n if (bytes.byteLength > MAX_DOWNLOAD_BYTES)\n throw new Error(`archive is ${Math.round(bytes.byteLength / 1024 / 1024)}MB — larger than the ${MAX_DOWNLOAD_BYTES / 1024 / 1024}MB limit`)\n }\n catch (err) {\n throw new InstallSourceError('fetch-failed', `Download failed for ${opts.what}: ${errorText(err)}`)\n }\n if (!opts.which('tar'))\n throw new InstallSourceError('fetch-failed', `Extracting ${opts.what} requires \\`tar\\` on PATH (or install git for the clone path).`)\n const tarPath = join(destDir, '.zidane-install.tgz')\n mkdirSync(destDir, { recursive: true })\n writeFileSync(tarPath, new Uint8Array(bytes))\n // Both GitHub and npm tarballs wrap contents in one top-level dir\n // (`repo-ref/`, `package/`) — strip it.\n const res = await opts.exec('tar', ['-xzf', tarPath, '-C', destDir, '--strip-components=1'], {})\n rmSync(tarPath, { force: true })\n if (!res.ok)\n throw new InstallSourceError('fetch-failed', `Extracting ${opts.what} failed: ${lastLine(res.stderr)}`)\n}\n\n// ---------------------------------------------------------------------------\n// Subdir containment\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a `:subdir` inside a fetched tree with PHYSICAL containment:\n * string-level prefix check first, then realpath both sides and re-check\n * so a malicious repo shipping a symlink (`evil -> /`) can't walk the\n * candidate search (and any follow-up validation) onto the local\n * filesystem. Returns the physical directory, or a typed refusal the\n * flavor maps onto its own error vocabulary.\n */\nexport function resolveSubdirRoot(\n fetchedInto: string,\n subdir: string,\n): { ok: true, dir: string } | { ok: false, reason: 'escape' | 'escape-symlink' | 'missing' } {\n const resolved = resolve(fetchedInto, subdir)\n if (!resolved.startsWith(fetchedInto + sep))\n return { ok: false, reason: 'escape' }\n let physical: string | null = null\n try {\n physical = realpathSync(resolved)\n }\n catch {}\n if (physical === null || !isDirectory(physical))\n return { ok: false, reason: 'missing' }\n const physicalRoot = realpathSync(fetchedInto)\n if (physical !== physicalRoot && !physical.startsWith(physicalRoot + sep))\n return { ok: false, reason: 'escape-symlink' }\n return { ok: true, dir: physical }\n}\n\nfunction isDirectory(path: string): boolean {\n try {\n return lstatSync(path).isDirectory()\n }\n catch {\n return false\n }\n}\n\n// ---------------------------------------------------------------------------\n// Default IO\n// ---------------------------------------------------------------------------\n\nexport function defaultExec(cmd: string, args: readonly string[], opts: { cwd?: string, env?: Record<string, string> }): Promise<{ ok: boolean, stdout: string, stderr: string }> {\n return new Promise((resolvePromise) => {\n // `env` EXTENDS the inherited environment (execFile's own `env` would\n // replace it, dropping PATH/HOME/SSH_AUTH_SOCK).\n const env = opts.env ? { ...process.env, ...opts.env } : undefined\n execFile(cmd, [...args], { cwd: opts.cwd, env, maxBuffer: 16 * 1024 * 1024 }, (err, stdout, stderr) => {\n resolvePromise({ ok: !err, stdout: String(stdout), stderr: String(stderr) })\n })\n })\n}\n\nexport function defaultWhich(cmd: string): string | null {\n const exts = process.platform === 'win32' ? ['.exe', '.cmd', '.bat', ''] : ['']\n for (const dir of (process.env.PATH ?? '').split(delimiter)) {\n if (!dir)\n continue\n for (const ext of exts) {\n const full = resolve(dir, cmd + ext)\n try {\n if (lstatSync(full).isFile())\n return full\n }\n catch {\n continue\n }\n }\n }\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n/** Last non-empty line of a command's output — the useful bit of tool noise. */\nexport function lastLine(text: string): string {\n const lines = text.trim().split('\\n').filter(l => l.trim().length > 0)\n return lines[lines.length - 1]?.trim() ?? ''\n}\n\nfunction errorText(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n","/**\n * Per-agent skill activation state machine.\n *\n * Tracks which skills are active across a run. The three skills tools\n * (`skills_use` / `skills_read` / `skills_run_script`) read from this state\n * for gating + listing. Allowed-tools enforcement reads from it too.\n *\n * Lifecycle:\n * - Storage lives on the agent instance (created once in `createAgent`), but\n * every `run()` ends with an implicit deactivate-all pass (reason `'run-end'`)\n * so activation does **not** persist across run boundaries. To keep a skill\n * active across successive runs, call `agent.activateSkill(name)` before each\n * run — the explicit-activation path is idempotent.\n * - `agent.reset()` clears the state with reason `'reset'`.\n * - On session-resume, carried-forward `skills_use` tool_call blocks (in prior\n * assistant turns) are replayed at run-start to rehydrate state with\n * `via: 'resume'`.\n *\n * The caps (`maxActive` from SkillsConfig) is enforced here — returning `false`\n * from `activate()` when the cap is hit lets the caller surface an actionable\n * \"max skills active\" error to the model.\n */\n\nimport type { SkillConfig } from './types'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** How a skill was activated. Surfaced in `skills:activate` hook ctx. */\nexport type ActivationVia = 'model' | 'explicit' | 'resume'\n\n/**\n * Reason a skill was deactivated. Surfaced in `skills:deactivate` hook ctx.\n *\n * - `'run-end'` — the implicit deactivate-all pass at each `run()` boundary.\n * - `'explicit'` — the host called `agent.deactivateSkill(name)`.\n * - `'reset'` — `agent.reset()` cleared the activation state along with\n * everything else.\n * - `'model'` — the model called `skills_use({ mode: 'deactivate', name })`\n * to release a skill's allow-list mid-run. Session-resume rehydration\n * honors the most recent `mode` per skill, so a model-driven deactivate\n * sticks across the next turn (no surprise re-activation).\n */\nexport type DeactivationReason = 'run-end' | 'explicit' | 'reset' | 'model'\n\n/** A skill currently active in the state machine. */\nexport interface ActiveSkill {\n skill: SkillConfig\n activatedAt: number\n activatedVia: ActivationVia\n}\n\n/**\n * Per-agent skill activation state. Public read-surface is the `active()` list\n * and `isActive(name)` predicate; writes go through `activate()` / `deactivate()`.\n */\nexport interface SkillActivationState {\n /** List of currently active skills in activation order. Returns a snapshot. */\n active: () => readonly ActiveSkill[]\n /** Is the skill with this canonical name currently active? */\n isActive: (name: string) => boolean\n /** Retrieve the `ActiveSkill` record by name, or `undefined`. */\n get: (name: string) => ActiveSkill | undefined\n /**\n * Mark a skill as active.\n * - Returns `'ok'` on a fresh activation (caller should fire `skills:activate`).\n * - Returns `'already-active'` if the skill was already in the set (idempotent).\n * - Returns `'cap-reached'` if the `maxActive` cap would be exceeded. State is unchanged.\n */\n activate: (skill: SkillConfig, via: ActivationVia) => 'ok' | 'already-active' | 'cap-reached'\n /**\n * Mark a skill as inactive. Returns the removed `ActiveSkill` record or `undefined`\n * if it wasn't active. Callers fire `skills:deactivate` on removal.\n */\n deactivate: (name: string) => ActiveSkill | undefined\n /** Remove every active skill. Returns the list of removed records. */\n clear: () => readonly ActiveSkill[]\n}\n\nexport interface SkillActivationStateOptions {\n /**\n * Cap on concurrent activations. `undefined` (the default) disables the cap.\n * When set, `activate()` returns `'cap-reached'` once the set is at size `maxActive`.\n */\n maxActive?: number\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createSkillActivationState(\n options: SkillActivationStateOptions = {},\n): SkillActivationState {\n const byName = new Map<string, ActiveSkill>()\n const maxActive = typeof options.maxActive === 'number' && options.maxActive > 0\n ? options.maxActive\n : undefined\n\n return {\n active() {\n return [...byName.values()]\n },\n\n isActive(name) {\n return byName.has(name)\n },\n\n get(name) {\n return byName.get(name)\n },\n\n activate(skill, via) {\n if (byName.has(skill.name))\n return 'already-active'\n if (maxActive !== undefined && byName.size >= maxActive)\n return 'cap-reached'\n byName.set(skill.name, {\n skill,\n activatedAt: Date.now(),\n activatedVia: via,\n })\n return 'ok'\n },\n\n deactivate(name) {\n const existing = byName.get(name)\n if (!existing)\n return undefined\n byName.delete(name)\n return existing\n },\n\n clear() {\n const snapshot = [...byName.values()]\n byName.clear()\n return snapshot\n },\n }\n}\n","/**\n * `allowed-tools` enforcement middleware.\n *\n * Installed by the agent on `tool:gate` and `mcp:tool:gate`. Computes the\n * union of `allowedTools` patterns across currently-active skills; blocks any\n * tool call whose `displayName` is not in that union. The three injected\n * skills tools (`skills_use` / `skills_read` / `skills_run_script`) are\n * implicitly allowed so a skill declaring an allow-list cannot lock out the\n * scaffolding that lets it run at all.\n *\n * The match target is `displayName` (wire / LLM-facing name), not the\n * canonical name, because skill authors write allow-list entries to match\n * what the model sees.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks } from '../agent'\nimport type { McpToolHookContext, ToolHookContext } from '../types'\nimport type { SkillActivationState } from './activation'\nimport { AgentToolNotAllowedError } from '../errors'\nimport { isToolAllowedByUnion } from './validate'\n\n/** Tools that are always allowed regardless of the active skills' allow-list. */\nexport const IMPLICITLY_ALLOWED_SKILL_TOOLS: readonly string[] = [\n 'skills_use',\n 'skills_read',\n 'skills_run_script',\n]\n\n/**\n * Register `tool:gate` / `mcp:tool:gate` handlers that enforce the union of\n * `allowedTools` across active skills.\n *\n * No-op when no active skill declares an allow-list (permissive default —\n * matches the spec's \"experimental\" note for `allowed-tools`).\n *\n * Returns an `uninstall` fn. The agent calls this at run end to detach the\n * handlers and prevent cross-run hook leaks.\n */\nexport function installAllowedToolsGate(\n hooks: Hookable<AgentHooks>,\n state: SkillActivationState,\n): () => void {\n function effectiveUnion(): { union: string[], active: string[] } {\n const active = state.active()\n const declared: string[] = []\n for (const record of active) {\n if (record.skill.allowedTools?.length)\n declared.push(...record.skill.allowedTools)\n }\n return {\n union: declared.length > 0 ? [...declared, ...IMPLICITLY_ALLOWED_SKILL_TOOLS] : [],\n active: active.map(a => a.skill.name),\n }\n }\n\n function gateHandler(ctx: ToolHookContext & { block: boolean, reason: string }) {\n // Honor a prior gate's refusal — keeps the gate stack order-independent.\n // Without this, a later-registered gate could silently overwrite an\n // earlier refusal's reason on the same call.\n if (ctx.block)\n return\n const { union, active } = effectiveUnion()\n if (union.length === 0)\n return\n if (isToolAllowedByUnion(ctx.displayName, ctx.input, union))\n return\n const err = new AgentToolNotAllowedError({\n toolName: ctx.name,\n displayName: ctx.displayName,\n allowedUnion: union,\n activeSkills: active,\n })\n ctx.block = true\n ctx.reason = err.message\n }\n\n function mcpGateHandler(ctx: McpToolHookContext & { block: boolean, reason: string }) {\n if (ctx.block)\n return\n const { union, active } = effectiveUnion()\n if (union.length === 0)\n return\n if (isToolAllowedByUnion(ctx.displayName, ctx.input, union))\n return\n const err = new AgentToolNotAllowedError({\n toolName: `mcp_${ctx.server}_${ctx.tool}`,\n displayName: ctx.displayName,\n allowedUnion: union,\n activeSkills: active,\n })\n ctx.block = true\n ctx.reason = err.message\n }\n\n const unregisterTool = hooks.hook('tool:gate', gateHandler)\n const unregisterMcp = hooks.hook('mcp:tool:gate', mcpGateHandler)\n\n return function uninstall() {\n unregisterTool()\n unregisterMcp()\n }\n}\n","/**\n * Skill catalog generation.\n *\n * Builds the system prompt section that discloses available skills to the\n * agent — tier 1 of progressive disclosure per the Agent Skills spec.\n *\n * The catalog's behavioral prose branches on which activation mechanism is\n * active for the run:\n *\n * - When the `skills_use` tool is auto-injected (the default for a non-empty\n * catalog), the prose tells the model to call `skills_use` with the skill's\n * name. The agent returns a structured `<skill_content>` block.\n * - When the skills tool is opted out (`SkillsConfig.tool: false`), the prose\n * falls back to the file-read pattern — the model reads `SKILL.md` itself\n * via its file-read tool.\n */\n\nimport type { SkillConfig } from './types'\nimport { escapeXml } from '../xml'\n\nexport interface BuildCatalogOptions {\n /**\n * When true (the default), the prose instructs the model to call\n * `skills_use`. Set to false when `SkillsConfig.tool === false` so the\n * system prompt matches the active activation mechanism.\n */\n skillsToolRegistered?: boolean\n /**\n * Name of the tool the model should use to read `SKILL.md` files when\n * `skillsToolRegistered` is false. Defaults to `'read_file'`.\n */\n readToolName?: string\n}\n\n/**\n * Build the skill catalog XML and behavioral instructions for the system prompt.\n */\nexport function buildCatalog(\n skills: SkillConfig[],\n options: BuildCatalogOptions = {},\n): string {\n if (skills.length === 0)\n return ''\n\n const skillsToolRegistered = options.skillsToolRegistered ?? true\n const readToolName = options.readToolName ?? 'read_file'\n\n const entries = skills.map((skill) => {\n const locationLine = skill.location\n ? `\\n <location>${escapeXml(skill.location)}</location>`\n : ''\n return ` <skill>\n <name>${escapeXml(skill.name)}</name>\n <description>${escapeXml(skill.description)}</description>${locationLine}\n </skill>`\n }).join('\\n')\n\n // Separate instructions for fs-based vs inline skills\n const hasFsSkills = skills.some(s => s.location)\n const hasInlineSkills = skills.some(s => !s.location)\n\n const behavioralParts: string[] = []\n\n behavioralParts.push(\n 'The following skills provide specialized instructions for specific tasks.',\n 'When a task matches a skill\\'s description, activate the skill to load its full instructions before proceeding.',\n )\n\n if (skillsToolRegistered) {\n behavioralParts.push(\n 'To activate a skill, call the `skills_use` tool with the skill\\'s name. '\n + 'The response contains the full instructions and any bundled resources you can then load '\n + 'via `skills_read` (reference files) or execute via `skills_run_script` (scripts/ directory).',\n 'Relative paths referenced in a skill\\'s instructions resolve against the skill directory noted in the `skills_use` response.',\n )\n }\n else if (hasFsSkills) {\n behavioralParts.push(\n `For skills with a <location>, use the ${readToolName} tool to read the SKILL.md file at that path.`,\n 'When a skill references relative paths, resolve them against the skill\\'s directory (the parent of SKILL.md) and use absolute paths in tool calls.',\n )\n }\n\n if (hasInlineSkills && !skillsToolRegistered) {\n behavioralParts.push(\n 'Skills without a <location> have their instructions included directly in <instructions> tags below.',\n )\n }\n\n // Build the full catalog block\n const parts: string[] = [\n behavioralParts.join('\\n'),\n '',\n '<available_skills>',\n entries,\n '</available_skills>',\n ]\n\n // Append inline skill instructions directly — but only when the model has no\n // other way to reach them (`skills_use` also handles inline skills when\n // registered, so we skip the duplicate copy in that case).\n if (hasInlineSkills && !skillsToolRegistered) {\n parts.push('')\n for (const skill of skills) {\n if (!skill.location && skill.instructions) {\n parts.push(`<skill_instructions name=\"${escapeXml(skill.name)}\">`)\n parts.push(skill.instructions)\n if (skill.resources && skill.resources.length > 0) {\n parts.push('')\n parts.push('<skill_resources>')\n for (const res of skill.resources) {\n parts.push(` <file type=\"${res.type}\">${escapeXml(res.path)}</file>`)\n }\n parts.push('</skill_resources>')\n }\n parts.push('</skill_instructions>')\n }\n }\n }\n\n return parts.join('\\n')\n}\n","/**\n * Skill discovery and parsing.\n *\n * Scans filesystem directories for SKILL.md files following the\n * Agent Skills specification (agentskills.io/specification).\n *\n * Parsing is intentionally **lenient** — per the spec's client-implementation\n * guide: warn, don't block. Diagnostics are attached to the returned\n * SkillConfig for host UIs to surface; only unrecoverable errors (missing\n * description, unparseable YAML) skip the skill entirely.\n */\n\nimport type { SkillConfig, SkillDiagnostic, SkillResource, SkillSource } from './types'\nimport { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { validateSkillName } from './validate'\n\n// ---------------------------------------------------------------------------\n// Regexes\n// ---------------------------------------------------------------------------\n\n// Frontmatter regex — opening ---, content, closing ---, optional body.\n// Tolerates CRLF line endings on the opening and closing fences (authoring\n// tools on Windows sometimes persist them mid-file).\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/\n\nconst INDENT_RE = /^[ \\t]{2,}/\nconst KV_RE = /^([^:]+):(.*)$/\nconst DOUBLE_QUOTED_RE = /^\"((?:\\\\.|[^\"\\\\])*)\"$/\nconst SINGLE_QUOTED_RE = /^'((?:''|[^'])*)'$/\nconst DQ_ESCAPE_RE = /\\\\([\"\\\\/bfnrt])/g\nconst WHITESPACE_SPLIT_RE = /\\s+/\nconst PARAGRAPH_SPLIT_RE = /\\n\\n/\nconst COMMA_OR_SPACE_RE = /[,\\s]+/\n/**\n * Block-list bullet (`- value`) under an indented frontmatter key. A\n * single dash followed by either a space or end-of-line; bare `-` is a\n * list item with an empty value (preserved by callers as `\"\"` because\n * the spec doesn't disallow it).\n */\nconst LIST_ITEM_RE = /^-(?:\\s+|$)/\n/**\n * Flow-style list scalar (`[a, b, c]`). Anchored, non-nested, single\n * pass — we trim the outer brackets and let the caller split on\n * commas. Anything more complex (nested brackets, quoted commas)\n * falls through to the whitespace-split branch, where the bracket\n * characters become visible authoring errors instead of silent garbage.\n *\n * Carefully written without overlapping `\\s*` runs so it's not\n * ReDoS-prone: the body class `[^[\\]]*` already swallows whitespace,\n * so wrapping it in `\\s*…\\s*` would let the regex engine\n * non-deterministically split a run of spaces between the body and\n * the boundary quantifiers.\n */\nconst FLOW_LIST_RE = /^\\[([^[\\]]*)\\]$/\n\n/**\n * Common kebab/camel/snake misspellings of multi-word spec frontmatter\n * keys. The Agent Skills spec mandates kebab-case (`allowed-tools`), but\n * authors raised on JS / Python idioms naturally reach for camelCase\n * (`allowedTools`) or snake_case (`allowed_tools`) — and the consequences\n * of a silent mismatch on `allowed-tools` specifically are nasty: the\n * skill loads fine, looks active in the UI, the model reads the body\n * and tells the user \"tools are restricted\", but the `tool:gate`\n * middleware finds nothing in the union and runs permissively. So we\n * look for these alts at parse time, migrate the value to the canonical\n * key, and emit a diagnostic so the next person sees the issue clearly.\n *\n * Keep the value space tight — accepting too many shapes erodes the\n * \"lenient load, strict authoring\" principle. Add entries only for keys\n * that are (a) multi-word (single-word keys have no ambiguity), (b) in\n * active use, and (c) cause silent failures when missing (gate keys,\n * security gates, …).\n */\nconst FRONTMATTER_KEY_ALIASES: ReadonlyMap<string, readonly string[]> = new Map([\n ['allowed-tools', ['allowedTools', 'allowed_tools']],\n])\n\n/**\n * Mutate `frontmatter` so any well-known alt-spelling of a canonical\n * spec key gets folded into the canonical slot. Idempotent — when the\n * canonical key is already set the function is a no-op even if an\n * alt-spelling is also present (canonical wins; alt is ignored).\n *\n * Pushes a `frontmatter-key-alt-spelling` diagnostic per migration so\n * the SkillConfig's `.diagnostics` carries an actionable hint into any\n * host UI surfacing skill load issues.\n */\nfunction normalizeKeyAliases(\n frontmatter: Record<string, unknown>,\n diagnostics: SkillDiagnostic[],\n): void {\n for (const [canonical, aliases] of FRONTMATTER_KEY_ALIASES) {\n if (frontmatter[canonical] !== undefined)\n continue\n for (const alias of aliases) {\n if (frontmatter[alias] === undefined)\n continue\n frontmatter[canonical] = frontmatter[alias]\n diagnostics.push({\n severity: 'warning',\n code: 'frontmatter-key-alt-spelling',\n message: `Frontmatter field \"${alias}\" is not a spec key — the spec uses \"${canonical}\" (kebab-case). Reading the value from \"${alias}\" as a courtesy; rename it to \"${canonical}\" to silence this warning.`,\n field: alias,\n })\n break // canonical claimed by the first matching alias\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Frontmatter parsing\n// ---------------------------------------------------------------------------\n\ninterface ParsedSkillFile {\n frontmatter: Record<string, unknown>\n body: string\n diagnostics: SkillDiagnostic[]\n}\n\n/**\n * Parse a SKILL.md file into frontmatter + body.\n *\n * Uses a simple regex-based YAML extractor that handles:\n * - Flat key: value pairs\n * - Quoted values\n * - One-level nested maps (for `metadata:`)\n * - One-level nested block lists, `key:` followed by indented `- item`\n * lines (for `allowed-tools` and any future array fields). Items are\n * unquoted with the same rules as scalar values.\n * - Flow-style scalars are preserved verbatim — interpretation (e.g.\n * `[a, b]` as a list) is left to per-field consumers via\n * {@link takeStringOrArray}.\n * - Lenient recovery from unquoted-colon values (e.g.\n * `description: Use when: the user asks …`) via a quote-wrap retry.\n */\nexport function parseFrontmatter(content: string): ParsedSkillFile {\n const diagnostics: SkillDiagnostic[] = []\n const match = content.match(FRONTMATTER_RE)\n if (!match) {\n return { frontmatter: {}, body: content.trim(), diagnostics }\n }\n\n const yamlBlock = match[1]\n const body = match[2].trim()\n\n // Simple YAML parser for flat key-values, one-level nested maps, AND\n // one-level nested block lists. The block-list extension is what makes\n // `allowed-tools:\\n - tool_name` parse correctly — without it, every\n // such field used to silently collapse to `[object Object]` via the\n // `String(...)` coercion path in `takeString`, producing a wide-open\n // gate. Mix-of-shapes (a list of `- item` lines AND `key: value` lines\n // under the same parent key) keeps whichever flavor was opened first\n // and emits a diagnostic so the author sees the problem.\n const frontmatter: Record<string, unknown> = {}\n let currentKey: string | null = null\n let currentMap: Record<string, string> | null = null\n let currentList: string[] | null = null\n\n const flushPending = () => {\n if (currentKey === null)\n return\n if (currentList !== null) {\n frontmatter[currentKey] = currentList\n }\n else if (currentMap !== null) {\n // Keep historical behavior for map-shaped pending values even when\n // empty — `metadata:` with no children parses to `{}` so downstream\n // consumers see \"field present, no rows\" rather than \"missing\".\n frontmatter[currentKey] = currentMap\n }\n currentKey = null\n currentMap = null\n currentList = null\n }\n\n for (const line of yamlBlock.split('\\n')) {\n // Skip empty lines and comments\n if (!line.trim() || line.trim().startsWith('#'))\n continue\n\n // Nested under the most recent open key. Two shapes: `- item`\n // (block list) and `nested-key: value` (map).\n if (currentKey !== null && INDENT_RE.test(line)) {\n const stripped = line.trim()\n\n // List item — `- value` (single dash + space). Backed by a regex\n // so a value that happens to start with `-` (\"-Wall\") inside a\n // map row doesn't trip it.\n if (LIST_ITEM_RE.test(stripped)) {\n if (currentMap !== null && Object.keys(currentMap).length > 0) {\n diagnostics.push({\n severity: 'warning',\n code: 'mixed-list-and-map',\n message: `Frontmatter field \"${currentKey}\" mixes list items and map entries — keeping the map and dropping the list items.`,\n field: currentKey,\n })\n continue\n }\n currentList = currentList ?? []\n currentList.push(unquoteYaml(stripped.slice(1).trim()))\n continue\n }\n\n // Map entry — `key: value`.\n const nestedMatch = stripped.match(KV_RE)\n if (nestedMatch) {\n if (currentList !== null) {\n diagnostics.push({\n severity: 'warning',\n code: 'mixed-list-and-map',\n message: `Frontmatter field \"${currentKey}\" mixes list items and map entries — keeping the list and dropping the map entries.`,\n field: currentKey,\n })\n continue\n }\n currentMap = currentMap ?? {}\n const val = nestedMatch[2].trim()\n currentMap[nestedMatch[1].trim()] = unquoteYaml(val)\n }\n continue\n }\n\n // Top-level key — flush whatever was pending under the prior one.\n flushPending()\n\n // Split on first colon only — lenient for values containing colons.\n const kvMatch = matchFirstColon(line)\n if (!kvMatch)\n continue\n\n const key = kvMatch.key.trim()\n const rawValue = kvMatch.value.trim()\n\n if (!rawValue) {\n // Block-style nested value — list OR map. We don't know which\n // yet; the first indented child line decides. Both slots start\n // null and the indented-line branch above promotes one of them.\n currentKey = key\n }\n else {\n frontmatter[key] = unquoteYaml(rawValue)\n }\n }\n\n // Flush the trailing pending value, if any.\n flushPending()\n\n return { frontmatter, body, diagnostics }\n}\n\nfunction matchFirstColon(line: string): { key: string, value: string } | null {\n const idx = line.indexOf(':')\n if (idx < 0)\n return null\n const key = line.slice(0, idx)\n const value = line.slice(idx + 1)\n // Reject accidental matches where key contains spaces before the colon wider\n // than a normal YAML key (defensive against \"some prose: foo\" in body leak).\n if (!KV_RE.test(`${key}:`))\n return null\n return { key, value }\n}\n\n/**\n * Strip outer quotes and decode YAML-style escapes.\n *\n * - Double-quoted values honor `\\\"`, `\\\\`, `\\n`, `\\r`, `\\t`, `\\b`, `\\f`, `\\/`.\n * - Single-quoted values honor `''` (the YAML single-quote escape for a literal `'`).\n * - Trailing inline comments on unquoted values (` # comment`) are dropped.\n * - Unquoted values are returned as-is (trimmed by caller).\n *\n * Skill frontmatter in the wild uses a narrow YAML subset — this is\n * sufficient for every field in the current spec and the common authoring\n * tools. Block scalars (`|`, `>`) and flow sequences are intentionally left\n * unsupported: they'd only appear in a bespoke workflow, and silently\n * half-supporting them is worse than rejecting them obviously.\n */\nfunction unquoteYaml(val: string): string {\n const dq = val.match(DOUBLE_QUOTED_RE)\n if (dq) {\n return dq[1].replace(DQ_ESCAPE_RE, (_, ch) => {\n switch (ch) {\n case '\"': return '\"'\n case '\\\\': return '\\\\'\n case '/': return '/'\n case 'b': return '\\b'\n case 'f': return '\\f'\n case 'n': return '\\n'\n case 'r': return '\\r'\n case 't': return '\\t'\n default: return ch\n }\n })\n }\n const sq = val.match(SINGLE_QUOTED_RE)\n if (sq) {\n return sq[1].replace(/''/g, '\\'')\n }\n // Strip trailing inline comment only when clearly separated (\"value # note\"\n // is a comment; \"value#tag\" is a literal). Preserves content on values that\n // legitimately contain `#` as part of text.\n const hashIdx = val.indexOf(' #')\n if (hashIdx >= 0)\n return val.slice(0, hashIdx).trimEnd()\n return val\n}\n\n/**\n * Narrow a frontmatter field to a string. Produces a diagnostic when present\n * but not a string, so malformed YAML (e.g. `name: 123`) surfaces as a\n * warning instead of silently coerced downstream via `as string`.\n */\nfunction takeString(\n frontmatter: Record<string, unknown>,\n key: string,\n diagnostics: SkillDiagnostic[],\n): string | undefined {\n const raw = frontmatter[key]\n if (raw === undefined || raw === null)\n return undefined\n if (typeof raw === 'string')\n return raw\n // Refuse object / array values instead of coercing via `String(...)`.\n // The historical coerce produced `'[object Object]'` for a block-list-\n // parsed array, which then split into garbage entries downstream (see\n // {@link takeStringOrArray} for the array path). For genuinely scalar\n // fields (`name`, `description`, …) the array-or-object shape is a\n // structural author error, and silently coercing it would hide that.\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-field-type',\n message: `Frontmatter field \"${key}\" expected string, got ${Array.isArray(raw) ? 'array' : typeof raw}. Skipping.`,\n field: key,\n })\n return undefined\n}\n\n/**\n * Accept either a YAML scalar (whitespace-separated tokens, the\n * spec-canonical form) OR a YAML block / flow list (`- item` or\n * `[a, b]`). Returns the field as a normalized `string[]`, or\n * `undefined` when the field is absent or empty.\n *\n * Used for list-shaped fields like `allowed-tools` whose authoring\n * surface has always been \"either a space-separated string OR a\n * list\" in skill files in the wild (Claude Code's docs use both\n * interchangeably). Pre-fix, the parser silently turned the list\n * forms into `[object Object]` / `[\"[a\", \"b]\"]` and the\n * allowed-tools gate would never match anything — opening it wide.\n *\n * Diagnostics are pushed for unexpected shapes (number, plain\n * object, etc.) and the field is dropped to avoid silent corruption.\n */\nfunction takeStringOrArray(\n frontmatter: Record<string, unknown>,\n key: string,\n diagnostics: SkillDiagnostic[],\n): string[] | undefined {\n const raw = frontmatter[key]\n if (raw === undefined || raw === null)\n return undefined\n\n if (Array.isArray(raw)) {\n // Already an array from the block-list path. Coerce each entry to\n // string defensively (a number `42` becomes `\"42\"`); drop empties.\n const items = raw\n .filter((v): v is string | number | boolean => v !== null && v !== undefined)\n .map(v => typeof v === 'string' ? v : String(v))\n .map(v => v.trim())\n .filter(v => v.length > 0)\n return items.length > 0 ? items : undefined\n }\n\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (trimmed.length === 0)\n return undefined\n\n // Flow-style list (`[a, b, c]`): strip the brackets and split on\n // commas. We don't try to be a full flow-YAML parser — nested\n // brackets, quoted commas inside elements, etc. fall through to\n // the whitespace-split branch (which produces \"a,\", \"b,\", \"c]\" —\n // not ideal but visibly broken to the author).\n const flowMatch = trimmed.match(FLOW_LIST_RE)\n if (flowMatch) {\n return flowMatch[1]\n .split(',')\n .map(s => s.trim())\n .filter(Boolean)\n }\n\n // Spec-canonical whitespace-separated form.\n return trimmed.split(WHITESPACE_SPLIT_RE).filter(Boolean)\n }\n\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-field-type',\n message: `Frontmatter field \"${key}\" expected string or list, got ${typeof raw}. Skipping.`,\n field: key,\n })\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// Resource enumeration\n// ---------------------------------------------------------------------------\n\nconst RESOURCE_DIRS: Record<string, SkillResource['type']> = {\n scripts: 'script',\n references: 'reference',\n assets: 'asset',\n}\n\nfunction enumerateResources(baseDir: string): SkillResource[] {\n const resources: SkillResource[] = []\n\n for (const [dir, type] of Object.entries(RESOURCE_DIRS)) {\n const dirPath = join(baseDir, dir)\n if (!existsSync(dirPath) || !statSync(dirPath).isDirectory())\n continue\n try {\n // `readdirSync` with `recursive: true` returns `string | Buffer`; we\n // opt into the `encoding: 'utf8'` overload via `withFileTypes: false`\n // default and string-encoded filenames. Guard the Buffer case in case\n // a platform quirk (non-UTF8 filenames on Linux) slips through.\n const files = readdirSync(dirPath, { recursive: true })\n for (const file of files) {\n const rel = typeof file === 'string' ? file : file.toString('utf-8')\n const fullPath = join(dirPath, rel)\n if (statSync(fullPath).isFile()) {\n resources.push({ path: join(dir, rel), type })\n }\n }\n }\n catch {\n // Skip unreadable directories\n }\n }\n\n // Also enumerate other files in the root (excluding SKILL.md)\n try {\n for (const entry of readdirSync(baseDir)) {\n if (entry === 'SKILL.md')\n continue\n const entryPath = join(baseDir, entry)\n if (statSync(entryPath).isFile()) {\n resources.push({ path: entry, type: 'other' })\n }\n }\n }\n catch {\n // Skip unreadable root\n }\n\n return resources\n}\n\n// ---------------------------------------------------------------------------\n// Parse a single SKILL.md file\n// ---------------------------------------------------------------------------\n\ninterface ParseSkillOptions {\n /** Source tag to attach to the returned SkillConfig. */\n source?: SkillSource\n}\n\n/**\n * Parse a SKILL.md file into a SkillConfig (lenient).\n *\n * Returns `null` only when the skill is fundamentally unusable:\n * - The file is missing\n * - The description is absent (required by spec for disclosure)\n *\n * All other issues are surfaced as `SkillConfig.diagnostics` with severity\n * `warning`. Deprecated top-level fields (`paths`, `model`, `thinking`) are\n * auto-migrated into `metadata['zidane.*']`.\n */\nexport async function parseSkillFile(\n filePath: string,\n options: ParseSkillOptions = {},\n): Promise<SkillConfig | null> {\n const absPath = resolve(filePath)\n if (!existsSync(absPath))\n return null\n\n const content = readFileSync(absPath, 'utf-8')\n const { frontmatter, body, diagnostics } = parseFrontmatter(content)\n\n // Normalize common JS/Python-style alt-spellings of multi-word spec\n // keys (e.g. `allowedTools` → `allowed-tools`) BEFORE any per-field\n // extraction so the rest of this function sees the canonical layout.\n // See `FRONTMATTER_KEY_ALIASES` for the supported set.\n normalizeKeyAliases(frontmatter, diagnostics)\n\n // Description: frontmatter > first paragraph of body > skip\n let description = takeString(frontmatter, 'description', diagnostics)\n if (!description && body) {\n const firstParagraph = body.split(PARAGRAPH_SPLIT_RE)[0]?.trim()\n if (firstParagraph)\n description = firstParagraph\n }\n if (!description)\n return null\n\n if (description.length > 1024) {\n diagnostics.push({\n severity: 'warning',\n code: 'description-too-long',\n message: `Description exceeds spec limit of 1024 characters (got ${description.length}). Loading anyway.`,\n field: 'description',\n })\n }\n\n const baseDir = dirname(absPath)\n const dirName = basename(baseDir)\n const frontmatterName = takeString(frontmatter, 'name', diagnostics)\n const name = frontmatterName || dirName\n\n // Lenient name checks\n if (frontmatterName && frontmatterName !== dirName) {\n diagnostics.push({\n severity: 'warning',\n code: 'name-mismatch-directory',\n message: `Skill name \"${frontmatterName}\" does not match parent directory \"${dirName}\". Loading anyway.`,\n field: 'name',\n })\n }\n if (name.length > 64) {\n diagnostics.push({\n severity: 'warning',\n code: 'name-too-long',\n message: `Skill name \"${name}\" exceeds spec limit of 64 characters. Loading anyway.`,\n field: 'name',\n })\n }\n if (!validateSkillName(name)) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-name-format',\n message: `Skill name \"${name}\" does not match spec format (lowercase alphanumeric + hyphens, no leading/trailing/consecutive hyphens). Loading anyway.`,\n field: 'name',\n })\n }\n\n const config: SkillConfig = {\n name,\n description,\n instructions: body,\n source: options.source ?? 'project',\n location: absPath,\n baseDir,\n resources: enumerateResources(baseDir),\n }\n\n const license = takeString(frontmatter, 'license', diagnostics)\n if (license)\n config.license = license\n\n const compatibility = takeString(frontmatter, 'compatibility', diagnostics)\n if (compatibility) {\n if (compatibility.length > 500) {\n diagnostics.push({\n severity: 'warning',\n code: 'compatibility-too-long',\n message: `Compatibility exceeds spec limit of 500 characters (got ${compatibility.length}). Loading anyway.`,\n field: 'compatibility',\n })\n }\n config.compatibility = compatibility\n }\n\n // Metadata — spec-compliant flat bag\n const metadata: Record<string, string> = {}\n const rawMetadata = frontmatter.metadata\n if (rawMetadata && typeof rawMetadata === 'object' && !Array.isArray(rawMetadata)) {\n for (const [k, v] of Object.entries(rawMetadata as Record<string, unknown>)) {\n if (typeof v !== 'string') {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-metadata-value',\n message: `Metadata value for \"${k}\" is not a string; coerced. (Spec requires string values.)`,\n field: 'metadata',\n })\n metadata[k] = String(v)\n continue\n }\n metadata[k] = v\n }\n }\n else if (rawMetadata !== undefined) {\n diagnostics.push({\n severity: 'warning',\n code: 'invalid-metadata-shape',\n message: `Frontmatter \"metadata\" expected a map, got ${Array.isArray(rawMetadata) ? 'array' : typeof rawMetadata}. Ignored.`,\n field: 'metadata',\n })\n }\n\n // Auto-migrate deprecated top-level fields into metadata.zidane.*\n const pathsField = takeString(frontmatter, 'paths', diagnostics)\n if (pathsField) {\n metadata['zidane.paths'] = pathsField.split(COMMA_OR_SPACE_RE).filter(Boolean).join(',')\n diagnostics.push({\n severity: 'warning',\n code: 'deprecated-top-level-field',\n message: '`paths` is not a spec field and is deprecated — moved to `metadata[\"zidane.paths\"]`.',\n field: 'paths',\n })\n }\n const modelField = takeString(frontmatter, 'model', diagnostics)\n if (modelField) {\n metadata['zidane.model'] = modelField\n diagnostics.push({\n severity: 'warning',\n code: 'deprecated-top-level-field',\n message: '`model` is not a spec field and is deprecated — moved to `metadata[\"zidane.model\"]`.',\n field: 'model',\n })\n }\n const thinkingField = takeString(frontmatter, 'thinking', diagnostics)\n const effortField = thinkingField ? undefined : takeString(frontmatter, 'effort', diagnostics)\n const legacyThinking = thinkingField ?? effortField\n if (legacyThinking) {\n metadata['zidane.thinking'] = legacyThinking\n diagnostics.push({\n severity: 'warning',\n code: 'deprecated-top-level-field',\n message: `\\`${thinkingField ? 'thinking' : 'effort'}\\` is not a spec field and is deprecated — moved to \\`metadata[\"zidane.thinking\"]\\`.`,\n field: thinkingField ? 'thinking' : 'effort',\n })\n }\n\n if (Object.keys(metadata).length > 0)\n config.metadata = metadata\n\n // `allowed-tools` historically accepted a whitespace-separated string;\n // we now also accept YAML block lists (`-` bullets) and flow lists\n // (`[a, b]`) so the spec-conformant authoring shapes don't silently\n // produce a garbage list that opens the gate wide. See\n // {@link takeStringOrArray} for the full coercion matrix.\n const allowedTools = takeStringOrArray(frontmatter, 'allowed-tools', diagnostics)\n if (allowedTools && allowedTools.length > 0) {\n config.allowedTools = allowedTools\n }\n\n if (diagnostics.length > 0)\n config.diagnostics = diagnostics\n\n return config\n}\n\n// ---------------------------------------------------------------------------\n// Directory scanning\n// ---------------------------------------------------------------------------\n\nconst SKIP_DIRS = new Set(['.git', 'node_modules', '.DS_Store', 'dist', 'build'])\n\nfunction findSkillDirs(root: string, maxDepth = 4, _depth = 0): string[] {\n if (_depth > maxDepth)\n return []\n if (!existsSync(root) || !statSync(root).isDirectory())\n return []\n\n const results: string[] = []\n try {\n for (const entry of readdirSync(root)) {\n if (SKIP_DIRS.has(entry))\n continue\n const entryPath = join(root, entry)\n if (!statSync(entryPath).isDirectory())\n continue\n\n const skillFile = join(entryPath, 'SKILL.md')\n if (existsSync(skillFile) && statSync(skillFile).isFile()) {\n results.push(skillFile)\n }\n else {\n // Recurse deeper\n results.push(...findSkillDirs(entryPath, maxDepth, _depth + 1))\n }\n }\n }\n catch {\n // Skip unreadable directories\n }\n return results\n}\n\n// ---------------------------------------------------------------------------\n// Default scan paths\n// ---------------------------------------------------------------------------\n\n/** A scan path paired with the source tag that should be attached to any skills found in it. */\nexport interface SourcedScanPath {\n path: string\n source: SkillSource\n}\n\n/**\n * Return the default scan paths tagged by source. Project-scope paths come\n * first; their skills therefore win on name collisions against user-scope\n * skills (first-found wins in discovery).\n */\nexport function getDefaultScanPaths(): SourcedScanPath[] {\n const home = homedir()\n const cwd = process.cwd()\n return [\n // Project-level (higher priority)\n { path: join(cwd, '.agents', 'skills'), source: 'project' },\n { path: join(cwd, '.zidane', 'skills'), source: 'project' },\n // User-level (lower priority)\n { path: join(home, '.agents', 'skills'), source: 'user' },\n { path: join(home, '.zidane', 'skills'), source: 'user' },\n ]\n}\n\n/**\n * Infer a source tag for a user-provided scan path.\n * Paths under `$HOME` are treated as 'user'; everything else as 'project'.\n */\nexport function inferSource(path: string): SkillSource {\n return path.startsWith(homedir()) ? 'user' : 'project'\n}\n\n// ---------------------------------------------------------------------------\n// Discover skills from filesystem\n// ---------------------------------------------------------------------------\n\n/**\n * Discover skills from sourced filesystem paths.\n * Each path is scanned for subdirectories containing SKILL.md.\n * Earlier paths have higher priority (first-found wins on name collision).\n *\n * `signal` is checked between each `parseSkillFile` so a rapid `cwd` switch\n * in the host (TUI / GUI) can stop a long scan without leaking I/O. Aborts\n * reject with the signal's `reason` (or a default `AbortError`) — same shape\n * `AbortSignal.throwIfAborted()` produces in modern runtimes.\n */\nexport async function discoverSkills(\n paths: SourcedScanPath[],\n signal?: AbortSignal,\n): Promise<SkillConfig[]> {\n const skillsByName = new Map<string, SkillConfig>()\n\n for (const { path: scanPath, source } of paths) {\n signal?.throwIfAborted?.()\n const skillFiles = findSkillDirs(resolve(scanPath))\n for (const file of skillFiles) {\n signal?.throwIfAborted?.()\n const skill = await parseSkillFile(file, { source })\n if (!skill)\n continue\n if (skillsByName.has(skill.name)) {\n // First-found wins — append a collision diagnostic to the winning skill.\n const existing = skillsByName.get(skill.name)!\n const diag: SkillDiagnostic = {\n severity: 'warning',\n code: 'name-collision-shadowed',\n message: `A skill with name \"${skill.name}\" was also found at ${file} (source: ${source}); shadowed by ${existing.location} (source: ${existing.source}).`,\n }\n existing.diagnostics = [...(existing.diagnostics ?? []), diag]\n continue\n }\n skillsByName.set(skill.name, skill)\n }\n }\n\n return [...skillsByName.values()]\n}\n","/**\n * Skill writer — materializes inline SkillConfig objects to disk as proper\n * SKILL.md files so they participate fully in the filesystem-based skill system.\n *\n * Strict-validates each skill before writing (see `validateSkillForWrite`).\n */\n\nimport type { SkillConfig } from './types'\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { validateSkillForWrite } from './validate'\n\n// ---------------------------------------------------------------------------\n// Frontmatter serialization\n// ---------------------------------------------------------------------------\n\nconst YAML_RESERVED_RE = /[:#&*!|>%@`]/\nconst YAML_EDGE_OR_QUOTE_RE = /^\\s|\\s$|[\"']/\nconst DQUOTE_RE = /\"/g\nconst LEADING_NEWLINES_RE = /^\\n+/\n\nfunction yamlEscape(value: string): string {\n // Quote values that contain YAML-reserved characters (colons, quotes, leading\n // special chars). Keeps round-trip safety for descriptions like\n // \"Use when: the user asks …\".\n if (YAML_RESERVED_RE.test(value) || YAML_EDGE_OR_QUOTE_RE.test(value) || value === '')\n return `\"${value.replace(DQUOTE_RE, '\\\\\"')}\"`\n return value\n}\n\nfunction serializeFrontmatter(skill: SkillConfig): string {\n const lines: string[] = ['---']\n\n lines.push(`name: ${yamlEscape(skill.name)}`)\n lines.push(`description: ${yamlEscape(skill.description)}`)\n\n if (skill.license)\n lines.push(`license: ${yamlEscape(skill.license)}`)\n if (skill.compatibility)\n lines.push(`compatibility: ${yamlEscape(skill.compatibility)}`)\n if (skill.allowedTools?.length)\n lines.push(`allowed-tools: ${skill.allowedTools.join(' ')}`)\n\n if (skill.metadata && Object.keys(skill.metadata).length > 0) {\n lines.push('metadata:')\n for (const [key, value] of Object.entries(skill.metadata)) {\n // Always quote metadata values — preserves string-looking numerics (\"1.0\")\n // and string-valued booleans (\"true\") from YAML's implicit type coercion.\n // Dot-keys (e.g. `zidane.paths`) are accepted verbatim by YAML.\n lines.push(` ${key}: \"${value.replace(DQUOTE_RE, '\\\\\"')}\"`)\n }\n }\n\n lines.push('---')\n return lines.join('\\n')\n}\n\n// ---------------------------------------------------------------------------\n// Write a single skill to disk\n// ---------------------------------------------------------------------------\n\n/**\n * Write a `SkillConfig` to disk as a proper skill directory with SKILL.md.\n * Returns the path to the written SKILL.md file.\n *\n * Throws if the skill fails `validateSkillForWrite` — the authoring path is\n * strict on purpose. For loading third-party skills, use `parseSkillFile`\n * directly (lenient).\n */\nexport function writeSkillToDisk(skill: SkillConfig, targetDir: string): string {\n const result = validateSkillForWrite(skill)\n if (!result.valid) {\n const summary = result.errors\n .map(e => ` - [${e.code}] ${e.message}`)\n .join('\\n')\n throw new Error(`Cannot write invalid skill \"${skill.name}\":\\n${summary}`)\n }\n\n const skillDir = join(targetDir, skill.name)\n mkdirSync(skillDir, { recursive: true })\n\n const frontmatter = serializeFrontmatter(skill)\n // Normalize: strip any leading newlines on the body so we never emit a\n // double-blank-line between the frontmatter fence and the instructions,\n // and always end the file with a single trailing newline.\n const bodyTrimmed = skill.instructions ? skill.instructions.replace(LEADING_NEWLINES_RE, '') : ''\n const content = bodyTrimmed\n ? `${frontmatter}\\n\\n${bodyTrimmed}\\n`\n : `${frontmatter}\\n`\n\n const skillPath = join(skillDir, 'SKILL.md')\n writeFileSync(skillPath, content)\n\n return skillPath\n}\n\n// ---------------------------------------------------------------------------\n// Write multiple skills to a directory\n// ---------------------------------------------------------------------------\n\n/**\n * Write multiple `SkillConfig` objects to a target directory.\n * Each skill gets its own subdirectory with a SKILL.md file.\n * Returns the target directory path (for use as a scan path).\n */\nexport function writeSkillsToDisk(skills: SkillConfig[], targetDir: string): string {\n mkdirSync(targetDir, { recursive: true })\n for (const skill of skills) {\n writeSkillToDisk(skill, targetDir)\n }\n return targetDir\n}\n","/**\n * Skill resolution — discovers filesystem skills, writes dynamic skills,\n * merges with any host-provided catalog, and applies filtering.\n */\n\nimport type { SourcedScanPath } from './discovery'\nimport type { SkillConfig, SkillDiagnostic, SkillsConfig } from './types'\nimport { mkdtempSync, rmSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { discoverSkills, getDefaultScanPaths, inferSource } from './discovery'\nimport { writeSkillsToDisk } from './writer'\n\n// ---------------------------------------------------------------------------\n// Resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolved-skills bundle: the materialized list plus a `cleanup` fn that\n * removes any temporary directory created for `config.write` skills.\n *\n * Inline skills must live on disk for the lifetime of the agent (the\n * `skills_read` / `skills_run_script` tools resolve relative paths against\n * `baseDir`), so cleanup is deferred to `agent.destroy()`. When no temp\n * directory was created, `cleanup` is a no-op.\n */\nexport interface ResolvedSkillsBundle {\n skills: SkillConfig[]\n cleanup: () => void\n}\n\n/**\n * Resolve all skills from a SkillsConfig:\n *\n * 1. Materialize `config.write` entries to a temp directory, tagged as `inline`\n * 2. Combine with default + user-provided scan paths (project-first, user-next)\n * 3. Run lenient disk discovery\n * 4. Merge with any host-provided `config.catalog`. Catalog entries seed the\n * resolution map FIRST, so they shadow disk-discovered skills with the\n * same name (shadow diagnostic attached to the winner — same shape as\n * the disk-vs-disk collision case).\n * 5. Apply filters: optional project-skill trust gate, `exclude`,\n * `enabled` allowlist\n *\n * Returns `{ skills, cleanup }` — call `cleanup()` on agent destroy to remove\n * the temp directory created for inline `config.write` skills. The agent\n * factory wires this automatically; standalone callers must invoke it\n * themselves to avoid leaking OS temp.\n */\nexport async function resolveSkills(config: SkillsConfig): Promise<ResolvedSkillsBundle> {\n const sourcedPaths: SourcedScanPath[] = []\n let writeDir: string | undefined\n\n if (!config.skipDefaultPaths) {\n sourcedPaths.push(...getDefaultScanPaths())\n }\n\n // User-provided scan paths: infer source from path prefix.\n for (const p of config.scan ?? []) {\n sourcedPaths.push({ path: p, source: inferSource(p) })\n }\n\n // Inline skills materialized to a temp directory and scanned as 'inline'.\n if (config.write?.length) {\n writeDir = mkdtempSync(join(tmpdir(), 'zidane-skills-'))\n writeSkillsToDisk(config.write, writeDir)\n sourcedPaths.push({ path: writeDir, source: 'inline' })\n }\n\n // Disk discovery (first-found-wins inside `discoverSkills` per its own\n // source-priority order).\n const diskSkills = await discoverSkills(sourcedPaths)\n\n // Merge: catalog entries seed the map first → they shadow disk skills\n // on name collision. Shallow-clone each catalog entry so we don't bleed\n // shadow diagnostics back into the caller's SkillsConfig.\n const skillsByName = new Map<string, SkillConfig>()\n for (const entry of config.catalog ?? []) {\n skillsByName.set(entry.name, { ...entry })\n }\n for (const skill of diskSkills) {\n const existing = skillsByName.get(skill.name)\n if (existing) {\n const loserLoc = skill.location ?? '(unknown)'\n const winnerLoc = existing.location ?? '(catalog)'\n const diag: SkillDiagnostic = {\n severity: 'warning',\n code: 'name-collision-shadowed',\n message: `A skill with name \"${skill.name}\" was also found at ${loserLoc} (source: ${skill.source ?? 'project'}); shadowed by ${winnerLoc} (source: ${existing.source ?? 'inline'}).`,\n }\n existing.diagnostics = [...(existing.diagnostics ?? []), diag]\n continue\n }\n skillsByName.set(skill.name, skill)\n }\n let skills = [...skillsByName.values()]\n\n // Optional trust gate: drop project-scoped skills when the host hasn't\n // marked the project as trusted. Undefined source is treated as `'project'`\n // (conservative default — an untrusted environment should skip unclassified\n // skills rather than silently loading them). Catalog entries are subject\n // to the same gate; hosts wanting their catalog to bypass it should tag\n // their entries with a non-`project` source (`'user'`, `'inline'`, `'builtin'`).\n if (config.trustProjectSkills === false) {\n skills = skills.filter(s => s.source !== undefined && s.source !== 'project')\n }\n\n // Filter out `exclude`\n const exclude = new Set(config.exclude ?? [])\n let filtered = skills.filter(s => !exclude.has(s.name))\n\n // Apply `enabled` allowlist when it's an array of skill names\n if (Array.isArray(config.enabled)) {\n const allowlist = new Set(config.enabled)\n filtered = filtered.filter(s => allowlist.has(s.name))\n }\n\n const cleanup = writeDir\n ? () => {\n try {\n rmSync(writeDir!, { recursive: true, force: true })\n }\n catch {\n // Best-effort — temp directory may have been removed by the OS or\n // a sibling cleanup. Don't crash agent destroy.\n }\n }\n : () => {}\n\n return { skills: filtered, cleanup }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,YAAY,MAAc,QAAQ,IAAI,GAAkB;CACtE,IAAI,MAAM,QAAQ,GAAG;CAIrB,KAAK,IAAI,QAAQ,GAAG,QAAQ,IAAI,SAAS;EACvC,IAAI,aAAa,GAAG,GAClB,OAAO;EACT,MAAM,SAAS,QAAQ,GAAG;EAC1B,IAAI,WAAW,KACb,OAAO;EACT,MAAM;CACR;CACA,OAAO;AACT;;;;;;AAOA,SAAS,aAAa,KAAsB;CAC1C,MAAM,YAAY,QAAQ,KAAK,MAAM;CACrC,IAAI;EACF,IAAI,CAAC,WAAW,SAAS,GACvB,OAAO;EACT,MAAM,OAAO,SAAS,SAAS;EAC/B,OAAO,KAAK,YAAY,KAAK,KAAK,OAAO;CAC3C,QACM;EACJ,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5BA,SAAgB,iBAAiB,MASX;CACpB,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;CACpC,MAAM,OAAO,KAAK,QAAQ,QAAQ;CAIlC,MAAM,cAAc,YAAY,GAAG,KAAK;CAGxC,MAAM,UAAU,KAAK,UAAU,UAAA,CAAW,QAAQ,OAAO,EAAE;CAC3D,OAAO;EACL;GAAE,MAAM,QAAQ,aAAa,WAAW,KAAK,SAAS;GAAG,QAAQ;EAAU;EAC3E;GAAE,MAAM,QAAQ,aAAa,IAAI,OAAO,GAAG,KAAK,SAAS;GAAG,QAAQ;EAAU;EAC9E;GAAE,MAAM,QAAQ,MAAM,WAAW,KAAK,SAAS;GAAG,QAAQ;EAAO;EACjE;GAAE,MAAM,QAAQ,MAAM,IAAI,OAAO,GAAG,KAAK,SAAS;GAAG,QAAQ;EAAO;CACtE;AACF;;;AC/CA,MAAM,WAAW;AACjB,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAE1B,MAAM,gBAAgB;AACtB,MAAM,yBAAyB;AAK/B,MAAM,0BAA0B;AAGhC,MAAM,sBAAsB;AAC5B,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;;;;;;;;;;;AAuC5B,SAAgB,kBAAkB,MAAuB;CACvD,IAAI,OAAO,SAAS,UAClB,OAAO;CACT,IAAI,KAAK,SAAS,KAAK,KAAK,SAAS,UACnC,OAAO;CACT,IAAI,uBAAuB,KAAK,IAAI,GAClC,OAAO;CACT,OAAO,cAAc,KAAK,IAAI;AAChC;;;;;;AAWA,SAAgB,sBAAsB,OAA2C;CAC/E,MAAM,SAAiC,CAAC;CAGxC,IAAI,CAAC,kBAAkB,MAAM,IAAI,GAC/B,OAAO,KAAK;EACV,MAAM;EACN,SAAS,eAAe,MAAM,KAAK;EACnC,OAAO;CACT,CAAC;CAIH,IAAI,MAAM,UAAU;EAClB,MAAM,UAAU,SAAS,MAAM,WAAW,EAAE;EAC5C,IAAI,WAAW,YAAY,MAAM,MAC/B,OAAO,KAAK;GACV,MAAM;GACN,SAAS,eAAe,MAAM,KAAK,sCAAsC,QAAQ;GACjF,OAAO;EACT,CAAC;CAEL;CAGA,IAAI,OAAO,MAAM,gBAAgB,YAAY,MAAM,YAAY,SAAS,GACtE,OAAO,KAAK;EACV,MAAM;EACN,SAAS;EACT,OAAO;CACT,CAAC;MAEE,IAAI,MAAM,YAAY,SAAS,iBAClC,OAAO,KAAK;EACV,MAAM;EACN,SAAS,qCAAqC,gBAAgB,mBAAmB,MAAM,YAAY,OAAO;EAC1G,OAAO;CACT,CAAC;CAIH,IAAI,MAAM,kBAAkB,KAAA;MACtB,OAAO,MAAM,kBAAkB,YAAY,MAAM,cAAc,WAAW,GAC5E,OAAO,KAAK;GACV,MAAM;GACN,SAAS;GACT,OAAO;EACT,CAAC;OAEE,IAAI,MAAM,cAAc,SAAS,mBACpC,OAAO,KAAK;GACV,MAAM;GACN,SAAS,iCAAiC,kBAAkB,mBAAmB,MAAM,cAAc,OAAO;GAC1G,OAAO;EACT,CAAC;CAAA;CAKL,IAAI,MAAM;OACH,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,QAAQ,GACtD,IAAI,OAAO,UAAU,UACnB,OAAO,KAAK;GACV,MAAM;GACN,SAAS,uBAAuB,IAAI;GACpC,OAAO;EACT,CAAC;CAAA;CAMP,IAAI,MAAM;OACH,MAAM,WAAW,MAAM,cAC1B,IAAI,CAAC,wBAAwB,KAAK,OAAO,GACvC,OAAO,KAAK;GACV,MAAM;GACN,SAAS,wBAAwB,QAAQ;GACzC,OAAO;EACT,CAAC;CAAA;CAKP,OAAO;EAAE,OAAO,OAAO,WAAW;EAAG;CAAO;AAC9C;;;;;;;;;;;;AAiBA,SAAgB,qBACd,SACA,SACyE;CACzE,IAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,GACpD,OAAO;EAAE,OAAO;EAAO,OAAO;CAA4C;CAE5E,IAAI,QAAQ,SAAS,IAAI,GACvB,OAAO;EAAE,OAAO;EAAO,OAAO;CAAsC;CAGtE,IAAI,QAAQ,WAAW,GAAG,KAAK,oBAAoB,KAAK,OAAO,GAC7D,OAAO;EAAE,OAAO;EAAO,OAAO,oCAAoC,QAAQ;CAAK;CAGjF,MAAM,WAAqB,CAAC;CAC5B,KAAK,MAAM,WAAW,QAAQ,MAAM,iBAAiB,GAAG;EACtD,IAAI,YAAY,MAAM,YAAY,KAChC;EACF,IAAI,YAAY,MAAM;GACpB,IAAI,SAAS,WAAW,GACtB,OAAO;IACL,OAAO;IACP,OAAO,kBAAkB,QAAQ;GACnC;GAEF,SAAS,IAAI;GACb;EACF;EACA,SAAS,KAAK,OAAO;CACvB;CAEA,IAAI,SAAS,WAAW,GACtB,OAAO;EAAE,OAAO;EAAO,OAAO;CAAmD;CAGnF,OAAO;EAAE,OAAO;EAAM,cAAA,GADE,QAAQ,QAAQ,qBAAqB,EAAE,EAAE,GAAG,SAAS,KAAK,GAAG;CAClD;AACrC;;;;;;;;;;;;;;;AAgBA,eAAsB,yBACpB,SACA,SACkF;CAClF,MAAM,UAAU,qBAAqB,SAAS,OAAO;CACrD,IAAI,CAAC,QAAQ,OACX,OAAO;CAET,IAAI;EACF,MAAM,CAAC,UAAU,cAAc,MAAM,QAAQ,IAAI,CAC/C,SAAS,OAAO,GAChB,SAAS,QAAQ,YAAY,CAC/B,CAAC;EACD,MAAM,SAAS,SAAS,QAAQ,qBAAqB,EAAE;EACvD,IAAI,eAAe,UAAU,CAAC,WAAW,WAAW,GAAG,OAAO,EAAE,GAC9D,OAAO;GACL,OAAO;GACP,OAAO,kBAAkB,QAAQ;EACnC;CAEJ,QACM,CAEN;CACA,OAAO;AACT;;;;;;;;AAaA,SAAgB,wBAAwB,OAA4D;CAClG,MAAM,IAAI,MAAM,KAAK,CAAC,CAAC,MAAM,uBAAuB;CACpD,IAAI,CAAC,GACH,OAAO;CACT,MAAM,OAAO,EAAE;CACf,MAAM,MAAM,EAAE;CACd,IAAI,CAAC,KACH,OAAO,EAAE,KAAK;CAGhB,IAAI,IAAI,SAAS,IAAI,GACnB,OAAO;EAAE;EAAM,WAAW,IAAI,MAAM,GAAG,EAAE;CAAE;CAC7C,OAAO;EAAE;EAAM,WAAW;CAAI;AAChC;;;;;;;;;;;;;;;AAgBA,SAAgB,mBACd,aACA,OACA,SACS;CACT,MAAM,SAAS,wBAAwB,OAAO;CAC9C,IAAI,CAAC,QACH,OAAO;CACT,IAAI,OAAO,SAAS,aAClB,OAAO;CACT,IAAI,OAAO,cAAc,KAAA,GACvB,OAAO;CAKT,KAAK,MAAM,SAAS,OAAO,OAAO,KAAK,GACrC,IAAI,OAAO,UAAU,YAAY,MAAM,WAAW,OAAO,SAAS,GAChE,OAAO;CAEX,OAAO;AACT;;;;;;AAOA,SAAgB,qBACd,aACA,OACA,OACS;CACT,IAAI,MAAM,WAAW,GACnB,OAAO;CACT,OAAO,MAAM,MAAK,YAAW,mBAAmB,aAAa,OAAO,OAAO,CAAC;AAC9E;;;;AC1UA,MAAM,yBAAyB;;;;;;;;AAS/B,SAAgB,yBAAyB,cAA8B;CACrE,OAAO,aAAa,QAAQ,wBAAwB,gCAAgC;AACtF;;;;;;;;;;;;;;AAgCA,eAAsB,yBACpB,cACA,WACA,QACA,UAA2C,CAAC,GAC3B;CACjB,MAAM,UAAU,CAAC,GAAG,aAAa,SAAS,sBAAsB,CAAC;CACjE,IAAI,QAAQ,WAAW,GACrB,OAAO;CAGT,MAAM,eAAoE,CAAC;CAE3E,KAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,UAAU,MAAM;EACtB,MAAM,QAAQ,MAAM;EACpB,MAAM,SAAS,MAAM,EAAE,CAAC;EAExB,IAAI,QAAQ,SAAS;GACnB,IAAI,WAAW;GACf,IAAI;IACF,WAAW,MAAM,QAAQ,QAAQ,OAAO;GAC1C,QACM;IACJ,WAAW;GACb;GACA,IAAI,CAAC,UAAU;IACb,MAAM,cAAc;IACpB,QAAQ,YAAY,SAAS,WAAW;IACxC,aAAa,KAAK;KAAE;KAAO;KAAQ,QAAQ;IAAY,CAAC;IACxD;GACF;EACF;EAEA,IAAI;GACF,MAAM,SAAS,MAAM,UAAU,KAAK,QAAQ,SAAS,EAAE,SAAS,GAAG,CAAC;GACpE,IAAI,OAAO,aAAa,GACtB,aAAa,KAAK;IAAE;IAAO;IAAQ,QAAQ,OAAO,OAAO,KAAK;GAAE,CAAC;QAE9D;IACH,MAAM,cAAc,yBAAyB,OAAO,SAAS,KAAK,OAAO,OAAO,KAAK,KAAK,OAAO,OAAO,KAAK,EAAE;IAC/G,QAAQ,YAAY,SAAS,WAAW;IACxC,aAAa,KAAK;KAAE;KAAO;KAAQ,QAAQ;IAAY,CAAC;GAC1D;EACF,SACO,KAAK;GACV,MAAM,cAAc,mBAAmB,aAAa,GAAG,EAAE;GACzD,QAAQ,YAAY,SAAS,WAAW;GACxC,aAAa,KAAK;IAAE;IAAO;IAAQ,QAAQ;GAAY,CAAC;EAC1D;CACF;CAGA,IAAI,SAAS;CACb,KAAK,IAAI,IAAI,aAAa,SAAS,GAAG,KAAK,GAAG,KAAK;EACjD,MAAM,EAAE,OAAO,QAAQ,WAAW,aAAa;EAC/C,SAAS,OAAO,MAAM,GAAG,KAAK,IAAI,SAAS,OAAO,MAAM,QAAQ,MAAM;CACxE;CAEA,OAAO;AACT;;;;;;;;;;;;;AC5GA,MAAM,SAAS;AACf,MAAM,QAAQ;AACd,MAAM,QAAQ;AACd,MAAM,UAAU;AAEhB,SAAgB,UAAU,KAAqB;CAC7C,OAAO,IACJ,QAAQ,QAAQ,OAAO,CAAC,CACxB,QAAQ,OAAO,MAAM,CAAC,CACtB,QAAQ,OAAO,MAAM,CAAC,CACtB,QAAQ,SAAS,QAAQ;AAC9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC8BA,IAAa,qBAAb,cAAwC,MAAM;CAC5C;;CAEA;CACA,YAAY,MAAc,SAAiB,YAAgC;EACzE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,IAAI,YACF,KAAK,aAAa;CACtB;AACF;AAuBA,MAAM,qBAAqB;AAC3B,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AACtB,MAAM,cAAc;;AAGpB,SAAS,YAAY,WAAmB,KAAqB;CAC3D,MAAM,SAAS,UAAU,QAAQ,SAAS,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE;CAChE,MAAM,WAAW,OAAO,MAAM,GAAG;CAKjC,IAJY,OAAO,WAAW,KACzB,OAAO,WAAW,GAAG,KACrB,OAAO,SAAS,IAAI,KACpB,SAAS,MAAK,MAAK,EAAE,WAAW,KAAK,MAAM,OAAO,MAAM,IAAI,GAE/D,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,qFAAqF;CAC9I,OAAO;AACT;;;;;;;;;;;;;;;AAgBA,SAAgB,mBAAmB,KAA4B;CAC7D,MAAM,OAAO,IAAI,KAAK;CACtB,IAAI,KAAK,WAAW,GAClB,MAAM,IAAI,mBAAmB,kBAAkB,iGAAiG;CAElJ,MAAM,iBAAiB,KAAK,WAAW,SAAS;CAChD,MAAM,OAAO,iBAAiB,KAAK,MAAM,CAAgB,IAAI;CAK7D,MAAM,OAAO,mBAAmB,KAAK,IAAI;CACzC,IAAI,MACF,OAAO;EACL,MAAM;EACN,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,KAAK,KAAK;EACV,GAAI,KAAK,KAAK,EAAE,QAAQ,YAAY,KAAK,IAAI,GAAG,EAAE,IAAI,CAAC;CACzD;CAGF,MAAM,MAAM,cAAc,KAAK,IAAI;CACnC,IAAI,KACF,OAAO;EAAE,MAAM;EAAU,OAAO,IAAI;EAAc,MAAM,IAAI;CAAa;CAE3E,IAAI,KAAK,WAAW,GAAG,GAAG;EACxB,IAAI,gBACF,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,oDAAoD;EAC7G,IAAI,KAAK,SAAS,GAAG,GACnB,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,qEAAqE;EAC9H,MAAM,IAAI,YAAY,KAAK,IAAI;EAC/B,IAAI,CAAC,GACH,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,mCAAmC;EAC5F,OAAO;GAAE,MAAM;GAAO,KAAK,EAAE;GAAc,GAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;EAAG;CAChF;CAEA,IAAI,KAAK,SAAS,GAAG,GAAG;EAItB,MAAM,WAAW,KAAK,QAAQ,GAAG;EACjC,MAAM,WAAW,aAAa,KAAK,OAAO,KAAK,MAAM,GAAG,QAAQ;EAChE,MAAM,SAAS,aAAa,KAAK,KAAA,IAAY,YAAY,KAAK,MAAM,WAAW,CAAC,GAAG,GAAG;EACtF,MAAM,UAAU,SAAS,QAAQ,GAAG;EACpC,MAAM,SAAS,WAAW,IAAI,UAAU,SAAS,QAAQ,GAAG;EAC5D,MAAM,WAAW,WAAW,KAAK,WAAW,SAAS,MAAM,GAAG,MAAM;EACpE,MAAM,MAAM,WAAW,KAAK,KAAA,IAAY,SAAS,MAAM,SAAS,CAAC;EACjE,MAAM,IAAI,cAAc,KAAK,QAAQ;EACrC,IAAI,CAAC,KAAM,QAAQ,KAAA,KAAa,CAAC,cAAc,KAAK,GAAG,GACrD,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,sFAAsF;EAC/I,OAAO;GACL,MAAM;GACN,OAAO,EAAE;GACT,MAAM,EAAE;GACR,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;GACrB,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;EAC7B;CACF;CAEA,IAAI,gBACF,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,yDAAyD;CAClH,IAAI,KAAK,SAAS,GAAG,GACnB,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,qEAAqE;CAC9H,MAAM,IAAI,YAAY,KAAK,IAAI;CAC/B,IAAI,CAAC,GACH,MAAM,IAAI,mBAAmB,kBAAkB,IAAI,IAAI,mCAAmC;CAC5F,OAAO;EAAE,MAAM;EAAO,KAAK,EAAE;EAAc,GAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;CAAG;AAChF;;;;;;;AAYA,eAAsB,mBACpB,QACA,SACA,KAAgB,CAAC,GACjB,YAC4B;CAC5B,MAAM,OAAO,GAAG,QAAQ;CACxB,MAAM,QAAQ,GAAG,SAAS;CAC1B,MAAM,YAAY,GAAG,SAAS;CAE9B,IAAI,OAAO,SAAS,UAAU;EAC5B,MAAM,QAAQ,GAAG,OAAO,MAAM,GAAG,OAAO,OAAO,OAAO,MAAM,IAAI,OAAO,QAAQ,KAAK,OAAO,SAAS,IAAI,OAAO,WAAW;EAC1H,IAAI,MAAM,KAAK,GAAG;GAChB,aAAa,sBAAsB,MAAM,EAAE;GAG3C,MAAM,OAAO;IAAC;IAAS;IAAW;IAAK;GAAiB;GACxD,IAAI,OAAO,KACT,KAAK,KAAK,YAAY,OAAO,GAAG;GAClC,KAAK,KAAK,sBAAsB,OAAO,MAAM,GAAG,OAAO,KAAK,OAAO,OAAO;GAO1E,MAAM,MAAM,MAAM,KAAK,OAAO,MAAM,EAAE,KAAK,EAAE,qBAAqB,IAAI,EAAE,CAAC;GACzE,IAAI,CAAC,IAAI,IAAI;IAEX,MAAM,OADc,2EAA2E,KAAK,IAAI,MACjF,IACnB,0HACA;IACJ,MAAM,IAAI,mBAAmB,gBAAgB,wBAAwB,MAAM,IAAI,SAAS,IAAI,MAAM,IAAI,MAAM;GAC9G;GAIA,MAAM,OAAO,MAAM,KAAK,OAAO,CAAC,aAAa,MAAM,GAAG,EAAE,KAAK,QAAQ,CAAC;GACtE,MAAM,SAAS,KAAK,MAAM,iBAAiB,KAAK,KAAK,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,KAAK,IAAI,KAAA;GAC3F,OAAO,KAAK,SAAS,MAAM,GAAG;IAAE,WAAW;IAAM,OAAO;GAAK,CAAC;GAC9D,OAAO;IAAE,YAAY,UAAU;IAAS,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;GAAG;EACxE;EAEA,aAAa,0BAA0B,MAAM,UAAU;EACvD,MAAM,MAAM,OAAO,OAAO;EAE1B,MAAM,mBAAmB,+BADqB,OAAO,MAAM,GAAG,OAAO,KAAK,UAAU,OACnD,SAAS;GAAE;GAAM;GAAW;GAAO,MAAM;EAAM,CAAC;EACjF,OAAO,EAAE,YAAY,UAAU,QAAQ;CACzC;CAEA,aAAa,iBAAiB,OAAO,IAAI,EAAE;CAC3C,MAAM,EAAE,SAAS,YAAY,MAAM,kBAAkB,QAAQ,SAAS;CACtE,aAAa,mBAAmB,OAAO,IAAI,GAAG,QAAQ,EAAE;CACxD,MAAM,mBAAmB,SAAS,SAAS;EAAE;EAAM;EAAW;EAAO,MAAM,GAAG,OAAO,IAAI,GAAG;CAAU,CAAC;CACvG,OAAO,EAAE,YAAY,OAAO,OAAO,IAAI,GAAG,UAAU;AACtD;;;;;AAMA,eAAsB,kBACpB,QACA,WAC+C;CAC/C,MAAM,cAAc,8BAA8B,OAAO,IAAI,QAAQ,KAAK,KAAK;CAC/E,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,MAAM,UAAU,WAAW;EACvC,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MAAM,qBAAqB,IAAI,QAAQ;EACnD,OAAO,MAAM,IAAI,KAAK;CACxB,SACO,KAAK;EACV,MAAM,IAAI,mBAAmB,gBAAgB,kCAAkC,OAAO,IAAI,KAAK,UAAU,GAAG,GAAG;CACjH;CACA,MAAM,UAAU,OAAO,WAAW,KAAK,WAAW,OAAO,WACrD,OAAO,UACP,KAAK,YAAY,GAAG,OAAO,WAAW;CAC1C,MAAM,UAAU,UAAU,KAAK,WAAW,QAAQ,EAAE,MAAM,UAAU,KAAA;CACpE,IAAI,CAAC,WAAW,CAAC,SACf,MAAM,IAAI,mBACR,gBACA,gBAAgB,OAAO,IAAI,WAAW,OAAO,UAAU,gBAAgB,OAAO,QAAQ,KAAK,iBAAiB,gEAC9G;CAEF,OAAO;EAAE;EAAS;CAAQ;AAC5B;;;;;;AAOA,MAAa,qBAAqB,KAAK,OAAO;AAE9C,eAAe,mBACb,KACA,SACA,MACe;CACf,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,MAAM,KAAK,UAAU,GAAG;EACpC,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MAAM,qBAAqB,IAAI,QAAQ;EACnD,MAAM,WAAW,OAAO,IAAI,QAAQ,IAAI,gBAAgB,KAAK,GAAG;EAChE,IAAI,WAAA,UACF,MAAM,IAAI,MAAM,cAAc,KAAK,MAAM,WAAW,OAAO,IAAI,EAAE,uBAAuB,qBAAqB,OAAO,KAAK,SAAS;EACpI,QAAQ,MAAM,IAAI,YAAY;EAG9B,IAAI,MAAM,aAAA,UACR,MAAM,IAAI,MAAM,cAAc,KAAK,MAAM,MAAM,aAAa,OAAO,IAAI,EAAE,uBAAuB,qBAAqB,OAAO,KAAK,SAAS;CAC9I,SACO,KAAK;EACV,MAAM,IAAI,mBAAmB,gBAAgB,uBAAuB,KAAK,KAAK,IAAI,UAAU,GAAG,GAAG;CACpG;CACA,IAAI,CAAC,KAAK,MAAM,KAAK,GACnB,MAAM,IAAI,mBAAmB,gBAAgB,cAAc,KAAK,KAAK,+DAA+D;CACtI,MAAM,UAAU,KAAK,SAAS,qBAAqB;CACnD,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;CACtC,cAAc,SAAS,IAAI,WAAW,KAAK,CAAC;CAG5C,MAAM,MAAM,MAAM,KAAK,KAAK,OAAO;EAAC;EAAQ;EAAS;EAAM;EAAS;CAAsB,GAAG,CAAC,CAAC;CAC/F,OAAO,SAAS,EAAE,OAAO,KAAK,CAAC;CAC/B,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,mBAAmB,gBAAgB,cAAc,KAAK,KAAK,WAAW,SAAS,IAAI,MAAM,GAAG;AAC1G;;;;;;;;;AAcA,SAAgB,kBACd,aACA,QAC4F;CAC5F,MAAM,WAAW,QAAQ,aAAa,MAAM;CAC5C,IAAI,CAAC,SAAS,WAAW,cAAc,GAAG,GACxC,OAAO;EAAE,IAAI;EAAO,QAAQ;CAAS;CACvC,IAAI,WAA0B;CAC9B,IAAI;EACF,WAAW,aAAa,QAAQ;CAClC,QACM,CAAC;CACP,IAAI,aAAa,QAAQ,CAAC,YAAY,QAAQ,GAC5C,OAAO;EAAE,IAAI;EAAO,QAAQ;CAAU;CACxC,MAAM,eAAe,aAAa,WAAW;CAC7C,IAAI,aAAa,gBAAgB,CAAC,SAAS,WAAW,eAAe,GAAG,GACtE,OAAO;EAAE,IAAI;EAAO,QAAQ;CAAiB;CAC/C,OAAO;EAAE,IAAI;EAAM,KAAK;CAAS;AACnC;AAEA,SAAS,YAAY,MAAuB;CAC1C,IAAI;EACF,OAAO,UAAU,IAAI,CAAC,CAAC,YAAY;CACrC,QACM;EACJ,OAAO;CACT;AACF;AAMA,SAAgB,YAAY,KAAa,MAAyB,MAAgH;CAChL,OAAO,IAAI,SAAS,mBAAmB;EAGrC,MAAM,MAAM,KAAK,MAAM;GAAE,GAAG,QAAQ;GAAK,GAAG,KAAK;EAAI,IAAI,KAAA;EACzD,SAAS,KAAK,CAAC,GAAG,IAAI,GAAG;GAAE,KAAK,KAAK;GAAK;GAAK,WAAW,KAAK,OAAO;EAAK,IAAI,KAAK,QAAQ,WAAW;GACrG,eAAe;IAAE,IAAI,CAAC;IAAK,QAAQ,OAAO,MAAM;IAAG,QAAQ,OAAO,MAAM;GAAE,CAAC;EAC7E,CAAC;CACH,CAAC;AACH;AAEA,SAAgB,aAAa,KAA4B;CACvD,MAAM,OAAO,QAAQ,aAAa,UAAU;EAAC;EAAQ;EAAQ;EAAQ;CAAE,IAAI,CAAC,EAAE;CAC9E,KAAK,MAAM,QAAQ,QAAQ,IAAI,QAAQ,GAAA,CAAI,MAAM,SAAS,GAAG;EAC3D,IAAI,CAAC,KACH;EACF,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,OAAO,QAAQ,KAAK,MAAM,GAAG;GACnC,IAAI;IACF,IAAI,UAAU,IAAI,CAAC,CAAC,OAAO,GACzB,OAAO;GACX,QACM;IACJ;GACF;EACF;CACF;CACA,OAAO;AACT;;AAOA,SAAgB,SAAS,MAAsB;CAC7C,MAAM,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAO,MAAK,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC;CACrE,OAAO,MAAM,MAAM,SAAS,EAAE,EAAE,KAAK,KAAK;AAC5C;AAEA,SAAS,UAAU,KAAsB;CACvC,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACxD;;;ACrUA,SAAgB,2BACd,UAAuC,CAAC,GAClB;CACtB,MAAM,yBAAS,IAAI,IAAyB;CAC5C,MAAM,YAAY,OAAO,QAAQ,cAAc,YAAY,QAAQ,YAAY,IAC3E,QAAQ,YACR,KAAA;CAEJ,OAAO;EACL,SAAS;GACP,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC;EAC5B;EAEA,SAAS,MAAM;GACb,OAAO,OAAO,IAAI,IAAI;EACxB;EAEA,IAAI,MAAM;GACR,OAAO,OAAO,IAAI,IAAI;EACxB;EAEA,SAAS,OAAO,KAAK;GACnB,IAAI,OAAO,IAAI,MAAM,IAAI,GACvB,OAAO;GACT,IAAI,cAAc,KAAA,KAAa,OAAO,QAAQ,WAC5C,OAAO;GACT,OAAO,IAAI,MAAM,MAAM;IACrB;IACA,aAAa,KAAK,IAAI;IACtB,cAAc;GAChB,CAAC;GACD,OAAO;EACT;EAEA,WAAW,MAAM;GACf,MAAM,WAAW,OAAO,IAAI,IAAI;GAChC,IAAI,CAAC,UACH,OAAO,KAAA;GACT,OAAO,OAAO,IAAI;GAClB,OAAO;EACT;EAEA,QAAQ;GACN,MAAM,WAAW,CAAC,GAAG,OAAO,OAAO,CAAC;GACpC,OAAO,MAAM;GACb,OAAO;EACT;CACF;AACF;;;;ACrHA,MAAa,iCAAoD;CAC/D;CACA;CACA;AACF;;;;;;;;;;;AAYA,SAAgB,wBACd,OACA,OACY;CACZ,SAAS,iBAAwD;EAC/D,MAAM,SAAS,MAAM,OAAO;EAC5B,MAAM,WAAqB,CAAC;EAC5B,KAAK,MAAM,UAAU,QACnB,IAAI,OAAO,MAAM,cAAc,QAC7B,SAAS,KAAK,GAAG,OAAO,MAAM,YAAY;EAE9C,OAAO;GACL,OAAO,SAAS,SAAS,IAAI,CAAC,GAAG,UAAU,GAAG,8BAA8B,IAAI,CAAC;GACjF,QAAQ,OAAO,KAAI,MAAK,EAAE,MAAM,IAAI;EACtC;CACF;CAEA,SAAS,YAAY,KAA2D;EAI9E,IAAI,IAAI,OACN;EACF,MAAM,EAAE,OAAO,WAAW,eAAe;EACzC,IAAI,MAAM,WAAW,GACnB;EACF,IAAI,qBAAqB,IAAI,aAAa,IAAI,OAAO,KAAK,GACxD;EACF,MAAM,MAAM,IAAI,yBAAyB;GACvC,UAAU,IAAI;GACd,aAAa,IAAI;GACjB,cAAc;GACd,cAAc;EAChB,CAAC;EACD,IAAI,QAAQ;EACZ,IAAI,SAAS,IAAI;CACnB;CAEA,SAAS,eAAe,KAA8D;EACpF,IAAI,IAAI,OACN;EACF,MAAM,EAAE,OAAO,WAAW,eAAe;EACzC,IAAI,MAAM,WAAW,GACnB;EACF,IAAI,qBAAqB,IAAI,aAAa,IAAI,OAAO,KAAK,GACxD;EACF,MAAM,MAAM,IAAI,yBAAyB;GACvC,UAAU,OAAO,IAAI,OAAO,GAAG,IAAI;GACnC,aAAa,IAAI;GACjB,cAAc;GACd,cAAc;EAChB,CAAC;EACD,IAAI,QAAQ;EACZ,IAAI,SAAS,IAAI;CACnB;CAEA,MAAM,iBAAiB,MAAM,KAAK,aAAa,WAAW;CAC1D,MAAM,gBAAgB,MAAM,KAAK,iBAAiB,cAAc;CAEhE,OAAO,SAAS,YAAY;EAC1B,eAAe;EACf,cAAc;CAChB;AACF;;;;;;ACjEA,SAAgB,aACd,QACA,UAA+B,CAAC,GACxB;CACR,IAAI,OAAO,WAAW,GACpB,OAAO;CAET,MAAM,uBAAuB,QAAQ,wBAAwB;CAC7D,MAAM,eAAe,QAAQ,gBAAgB;CAE7C,MAAM,UAAU,OAAO,KAAK,UAAU;EACpC,MAAM,eAAe,MAAM,WACvB,mBAAmB,UAAU,MAAM,QAAQ,EAAE,eAC7C;EACJ,OAAO;YACC,UAAU,MAAM,IAAI,EAAE;mBACf,UAAU,MAAM,WAAW,EAAE,gBAAgB,aAAa;;CAE3E,CAAC,CAAC,CAAC,KAAK,IAAI;CAGZ,MAAM,cAAc,OAAO,MAAK,MAAK,EAAE,QAAQ;CAC/C,MAAM,kBAAkB,OAAO,MAAK,MAAK,CAAC,EAAE,QAAQ;CAEpD,MAAM,kBAA4B,CAAC;CAEnC,gBAAgB,KACd,6EACA,gHACF;CAEA,IAAI,sBACF,gBAAgB,KACd,+PAGA,6HACF;MAEG,IAAI,aACP,gBAAgB,KACd,yCAAyC,aAAa,gDACtD,mJACF;CAGF,IAAI,mBAAmB,CAAC,sBACtB,gBAAgB,KACd,qGACF;CAIF,MAAM,QAAkB;EACtB,gBAAgB,KAAK,IAAI;EACzB;EACA;EACA;EACA;CACF;CAKA,IAAI,mBAAmB,CAAC,sBAAsB;EAC5C,MAAM,KAAK,EAAE;EACb,KAAK,MAAM,SAAS,QAClB,IAAI,CAAC,MAAM,YAAY,MAAM,cAAc;GACzC,MAAM,KAAK,6BAA6B,UAAU,MAAM,IAAI,EAAE,GAAG;GACjE,MAAM,KAAK,MAAM,YAAY;GAC7B,IAAI,MAAM,aAAa,MAAM,UAAU,SAAS,GAAG;IACjD,MAAM,KAAK,EAAE;IACb,MAAM,KAAK,mBAAmB;IAC9B,KAAK,MAAM,OAAO,MAAM,WACtB,MAAM,KAAK,iBAAiB,IAAI,KAAK,IAAI,UAAU,IAAI,IAAI,EAAE,QAAQ;IAEvE,MAAM,KAAK,oBAAoB;GACjC;GACA,MAAM,KAAK,uBAAuB;EACpC;CAEJ;CAEA,OAAO,MAAM,KAAK,IAAI;AACxB;;;AChGA,MAAM,iBAAiB;AAEvB,MAAM,YAAY;AAClB,MAAM,QAAQ;AACd,MAAM,mBAAmB;AACzB,MAAM,mBAAmB;AACzB,MAAM,eAAe;AACrB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;;;;;;;AAO1B,MAAM,eAAe;;;;;;;;;;;;;;AAcrB,MAAM,eAAe;;;;;;;;;;;;;;;;;;;AAoBrB,MAAM,0CAAkE,IAAI,IAAI,CAC9E,CAAC,iBAAiB,CAAC,gBAAgB,eAAe,CAAC,CACrD,CAAC;;;;;;;;;;;AAYD,SAAS,oBACP,aACA,aACM;CACN,KAAK,MAAM,CAAC,WAAW,YAAY,yBAAyB;EAC1D,IAAI,YAAY,eAAe,KAAA,GAC7B;EACF,KAAK,MAAM,SAAS,SAAS;GAC3B,IAAI,YAAY,WAAW,KAAA,GACzB;GACF,YAAY,aAAa,YAAY;GACrC,YAAY,KAAK;IACf,UAAU;IACV,MAAM;IACN,SAAS,sBAAsB,MAAM,uCAAuC,UAAU,0CAA0C,MAAM,iCAAiC,UAAU;IACjL,OAAO;GACT,CAAC;GACD;EACF;CACF;AACF;;;;;;;;;;;;;;;;;AA4BA,SAAgB,iBAAiB,SAAkC;CACjE,MAAM,cAAiC,CAAC;CACxC,MAAM,QAAQ,QAAQ,MAAM,cAAc;CAC1C,IAAI,CAAC,OACH,OAAO;EAAE,aAAa,CAAC;EAAG,MAAM,QAAQ,KAAK;EAAG;CAAY;CAG9D,MAAM,YAAY,MAAM;CACxB,MAAM,OAAO,MAAM,EAAE,CAAC,KAAK;CAU3B,MAAM,cAAuC,CAAC;CAC9C,IAAI,aAA4B;CAChC,IAAI,aAA4C;CAChD,IAAI,cAA+B;CAEnC,MAAM,qBAAqB;EACzB,IAAI,eAAe,MACjB;EACF,IAAI,gBAAgB,MAClB,YAAY,cAAc;OAEvB,IAAI,eAAe,MAItB,YAAY,cAAc;EAE5B,aAAa;EACb,aAAa;EACb,cAAc;CAChB;CAEA,KAAK,MAAM,QAAQ,UAAU,MAAM,IAAI,GAAG;EAExC,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC,WAAW,GAAG,GAC5C;EAIF,IAAI,eAAe,QAAQ,UAAU,KAAK,IAAI,GAAG;GAC/C,MAAM,WAAW,KAAK,KAAK;GAK3B,IAAI,aAAa,KAAK,QAAQ,GAAG;IAC/B,IAAI,eAAe,QAAQ,OAAO,KAAK,UAAU,CAAC,CAAC,SAAS,GAAG;KAC7D,YAAY,KAAK;MACf,UAAU;MACV,MAAM;MACN,SAAS,sBAAsB,WAAW;MAC1C,OAAO;KACT,CAAC;KACD;IACF;IACA,cAAc,eAAe,CAAC;IAC9B,YAAY,KAAK,YAAY,SAAS,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACtD;GACF;GAGA,MAAM,cAAc,SAAS,MAAM,KAAK;GACxC,IAAI,aAAa;IACf,IAAI,gBAAgB,MAAM;KACxB,YAAY,KAAK;MACf,UAAU;MACV,MAAM;MACN,SAAS,sBAAsB,WAAW;MAC1C,OAAO;KACT,CAAC;KACD;IACF;IACA,aAAa,cAAc,CAAC;IAC5B,MAAM,MAAM,YAAY,EAAE,CAAC,KAAK;IAChC,WAAW,YAAY,EAAE,CAAC,KAAK,KAAK,YAAY,GAAG;GACrD;GACA;EACF;EAGA,aAAa;EAGb,MAAM,UAAU,gBAAgB,IAAI;EACpC,IAAI,CAAC,SACH;EAEF,MAAM,MAAM,QAAQ,IAAI,KAAK;EAC7B,MAAM,WAAW,QAAQ,MAAM,KAAK;EAEpC,IAAI,CAAC,UAIH,aAAa;OAGb,YAAY,OAAO,YAAY,QAAQ;CAE3C;CAGA,aAAa;CAEb,OAAO;EAAE;EAAa;EAAM;CAAY;AAC1C;AAEA,SAAS,gBAAgB,MAAqD;CAC5E,MAAM,MAAM,KAAK,QAAQ,GAAG;CAC5B,IAAI,MAAM,GACR,OAAO;CACT,MAAM,MAAM,KAAK,MAAM,GAAG,GAAG;CAC7B,MAAM,QAAQ,KAAK,MAAM,MAAM,CAAC;CAGhC,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,EAAE,GACvB,OAAO;CACT,OAAO;EAAE;EAAK;CAAM;AACtB;;;;;;;;;;;;;;;AAgBA,SAAS,YAAY,KAAqB;CACxC,MAAM,KAAK,IAAI,MAAM,gBAAgB;CACrC,IAAI,IACF,OAAO,GAAG,EAAE,CAAC,QAAQ,eAAe,GAAG,OAAO;EAC5C,QAAQ,IAAR;GACE,KAAK,MAAK,OAAO;GACjB,KAAK,MAAM,OAAO;GAClB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,KAAK,KAAK,OAAO;GACjB,SAAS,OAAO;EAClB;CACF,CAAC;CAEH,MAAM,KAAK,IAAI,MAAM,gBAAgB;CACrC,IAAI,IACF,OAAO,GAAG,EAAE,CAAC,QAAQ,OAAO,GAAI;CAKlC,MAAM,UAAU,IAAI,QAAQ,IAAI;CAChC,IAAI,WAAW,GACb,OAAO,IAAI,MAAM,GAAG,OAAO,CAAC,CAAC,QAAQ;CACvC,OAAO;AACT;;;;;;AAOA,SAAS,WACP,aACA,KACA,aACoB;CACpB,MAAM,MAAM,YAAY;CACxB,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAC/B,OAAO,KAAA;CACT,IAAI,OAAO,QAAQ,UACjB,OAAO;CAOT,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,sBAAsB,IAAI,yBAAyB,MAAM,QAAQ,GAAG,IAAI,UAAU,OAAO,IAAI;EACtG,OAAO;CACT,CAAC;AAEH;;;;;;;;;;;;;;;;;AAkBA,SAAS,kBACP,aACA,KACA,aACsB;CACtB,MAAM,MAAM,YAAY;CACxB,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAC/B,OAAO,KAAA;CAET,IAAI,MAAM,QAAQ,GAAG,GAAG;EAGtB,MAAM,QAAQ,IACX,QAAQ,MAAsC,MAAM,QAAQ,MAAM,KAAA,CAAS,CAAC,CAC5E,KAAI,MAAK,OAAO,MAAM,WAAW,IAAI,OAAO,CAAC,CAAC,CAAC,CAC/C,KAAI,MAAK,EAAE,KAAK,CAAC,CAAC,CAClB,QAAO,MAAK,EAAE,SAAS,CAAC;EAC3B,OAAO,MAAM,SAAS,IAAI,QAAQ,KAAA;CACpC;CAEA,IAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,UAAU,IAAI,KAAK;EACzB,IAAI,QAAQ,WAAW,GACrB,OAAO,KAAA;EAOT,MAAM,YAAY,QAAQ,MAAM,YAAY;EAC5C,IAAI,WACF,OAAO,UAAU,EAAE,CAChB,MAAM,GAAG,CAAC,CACV,KAAI,MAAK,EAAE,KAAK,CAAC,CAAC,CAClB,OAAO,OAAO;EAInB,OAAO,QAAQ,MAAM,mBAAmB,CAAC,CAAC,OAAO,OAAO;CAC1D;CAEA,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,sBAAsB,IAAI,iCAAiC,OAAO,IAAI;EAC/E,OAAO;CACT,CAAC;AAEH;AAMA,MAAM,gBAAuD;CAC3D,SAAS;CACT,YAAY;CACZ,QAAQ;AACV;AAEA,SAAS,mBAAmB,SAAkC;CAC5D,MAAM,YAA6B,CAAC;CAEpC,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,aAAa,GAAG;EACvD,MAAM,UAAU,KAAK,SAAS,GAAG;EACjC,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,SAAS,OAAO,CAAC,CAAC,YAAY,GACzD;EACF,IAAI;GAKF,MAAM,QAAQ,YAAY,SAAS,EAAE,WAAW,KAAK,CAAC;GACtD,KAAK,MAAM,QAAQ,OAAO;IACxB,MAAM,MAAM,OAAO,SAAS,WAAW,OAAO,KAAK,SAAS,OAAO;IAEnE,IAAI,SADa,KAAK,SAAS,GACX,CAAC,CAAC,CAAC,OAAO,GAC5B,UAAU,KAAK;KAAE,MAAM,KAAK,KAAK,GAAG;KAAG;IAAK,CAAC;GAEjD;EACF,QACM,CAEN;CACF;CAGA,IAAI;EACF,KAAK,MAAM,SAAS,YAAY,OAAO,GAAG;GACxC,IAAI,UAAU,YACZ;GAEF,IAAI,SADc,KAAK,SAAS,KACX,CAAC,CAAC,CAAC,OAAO,GAC7B,UAAU,KAAK;IAAE,MAAM;IAAO,MAAM;GAAQ,CAAC;EAEjD;CACF,QACM,CAEN;CAEA,OAAO;AACT;;;;;;;;;;;;AAsBA,eAAsB,eACpB,UACA,UAA6B,CAAC,GACD;CAC7B,MAAM,UAAU,QAAQ,QAAQ;CAChC,IAAI,CAAC,WAAW,OAAO,GACrB,OAAO;CAGT,MAAM,EAAE,aAAa,MAAM,gBAAgB,iBAD3B,aAAa,SAAS,OAC4B,CAAC;CAMnE,oBAAoB,aAAa,WAAW;CAG5C,IAAI,cAAc,WAAW,aAAa,eAAe,WAAW;CACpE,IAAI,CAAC,eAAe,MAAM;EACxB,MAAM,iBAAiB,KAAK,MAAM,kBAAkB,CAAC,CAAC,EAAE,EAAE,KAAK;EAC/D,IAAI,gBACF,cAAc;CAClB;CACA,IAAI,CAAC,aACH,OAAO;CAET,IAAI,YAAY,SAAS,MACvB,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,0DAA0D,YAAY,OAAO;EACtF,OAAO;CACT,CAAC;CAGH,MAAM,UAAU,QAAQ,OAAO;CAC/B,MAAM,UAAU,SAAS,OAAO;CAChC,MAAM,kBAAkB,WAAW,aAAa,QAAQ,WAAW;CACnE,MAAM,OAAO,mBAAmB;CAGhC,IAAI,mBAAmB,oBAAoB,SACzC,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,eAAe,gBAAgB,qCAAqC,QAAQ;EACrF,OAAO;CACT,CAAC;CAEH,IAAI,KAAK,SAAS,IAChB,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,eAAe,KAAK;EAC7B,OAAO;CACT,CAAC;CAEH,IAAI,CAAC,kBAAkB,IAAI,GACzB,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,eAAe,KAAK;EAC7B,OAAO;CACT,CAAC;CAGH,MAAM,SAAsB;EAC1B;EACA;EACA,cAAc;EACd,QAAQ,QAAQ,UAAU;EAC1B,UAAU;EACV;EACA,WAAW,mBAAmB,OAAO;CACvC;CAEA,MAAM,UAAU,WAAW,aAAa,WAAW,WAAW;CAC9D,IAAI,SACF,OAAO,UAAU;CAEnB,MAAM,gBAAgB,WAAW,aAAa,iBAAiB,WAAW;CAC1E,IAAI,eAAe;EACjB,IAAI,cAAc,SAAS,KACzB,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS,2DAA2D,cAAc,OAAO;GACzF,OAAO;EACT,CAAC;EAEH,OAAO,gBAAgB;CACzB;CAGA,MAAM,WAAmC,CAAC;CAC1C,MAAM,cAAc,YAAY;CAChC,IAAI,eAAe,OAAO,gBAAgB,YAAY,CAAC,MAAM,QAAQ,WAAW,GAC9E,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,WAAsC,GAAG;EAC3E,IAAI,OAAO,MAAM,UAAU;GACzB,YAAY,KAAK;IACf,UAAU;IACV,MAAM;IACN,SAAS,uBAAuB,EAAE;IAClC,OAAO;GACT,CAAC;GACD,SAAS,KAAK,OAAO,CAAC;GACtB;EACF;EACA,SAAS,KAAK;CAChB;MAEG,IAAI,gBAAgB,KAAA,GACvB,YAAY,KAAK;EACf,UAAU;EACV,MAAM;EACN,SAAS,8CAA8C,MAAM,QAAQ,WAAW,IAAI,UAAU,OAAO,YAAY;EACjH,OAAO;CACT,CAAC;CAIH,MAAM,aAAa,WAAW,aAAa,SAAS,WAAW;CAC/D,IAAI,YAAY;EACd,SAAS,kBAAkB,WAAW,MAAM,iBAAiB,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EACvF,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS;GACT,OAAO;EACT,CAAC;CACH;CACA,MAAM,aAAa,WAAW,aAAa,SAAS,WAAW;CAC/D,IAAI,YAAY;EACd,SAAS,kBAAkB;EAC3B,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS;GACT,OAAO;EACT,CAAC;CACH;CACA,MAAM,gBAAgB,WAAW,aAAa,YAAY,WAAW;CACrE,MAAM,cAAc,gBAAgB,KAAA,IAAY,WAAW,aAAa,UAAU,WAAW;CAC7F,MAAM,iBAAiB,iBAAiB;CACxC,IAAI,gBAAgB;EAClB,SAAS,qBAAqB;EAC9B,YAAY,KAAK;GACf,UAAU;GACV,MAAM;GACN,SAAS,KAAK,gBAAgB,aAAa,SAAS;GACpD,OAAO,gBAAgB,aAAa;EACtC,CAAC;CACH;CAEA,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,SAAS,GACjC,OAAO,WAAW;CAOpB,MAAM,eAAe,kBAAkB,aAAa,iBAAiB,WAAW;CAChF,IAAI,gBAAgB,aAAa,SAAS,GACxC,OAAO,eAAe;CAGxB,IAAI,YAAY,SAAS,GACvB,OAAO,cAAc;CAEvB,OAAO;AACT;AAMA,MAAM,4BAAY,IAAI,IAAI;CAAC;CAAQ;CAAgB;CAAa;CAAQ;AAAO,CAAC;AAEhF,SAAS,cAAc,MAAc,WAAW,GAAG,SAAS,GAAa;CACvE,IAAI,SAAS,UACX,OAAO,CAAC;CACV,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,YAAY,GACnD,OAAO,CAAC;CAEV,MAAM,UAAoB,CAAC;CAC3B,IAAI;EACF,KAAK,MAAM,SAAS,YAAY,IAAI,GAAG;GACrC,IAAI,UAAU,IAAI,KAAK,GACrB;GACF,MAAM,YAAY,KAAK,MAAM,KAAK;GAClC,IAAI,CAAC,SAAS,SAAS,CAAC,CAAC,YAAY,GACnC;GAEF,MAAM,YAAY,KAAK,WAAW,UAAU;GAC5C,IAAI,WAAW,SAAS,KAAK,SAAS,SAAS,CAAC,CAAC,OAAO,GACtD,QAAQ,KAAK,SAAS;QAItB,QAAQ,KAAK,GAAG,cAAc,WAAW,UAAU,SAAS,CAAC,CAAC;EAElE;CACF,QACM,CAEN;CACA,OAAO;AACT;;;;;;AAiBA,SAAgB,sBAAyC;CACvD,MAAM,OAAO,QAAQ;CACrB,MAAM,MAAM,QAAQ,IAAI;CACxB,OAAO;EAEL;GAAE,MAAM,KAAK,KAAK,WAAW,QAAQ;GAAG,QAAQ;EAAU;EAC1D;GAAE,MAAM,KAAK,KAAK,WAAW,QAAQ;GAAG,QAAQ;EAAU;EAE1D;GAAE,MAAM,KAAK,MAAM,WAAW,QAAQ;GAAG,QAAQ;EAAO;EACxD;GAAE,MAAM,KAAK,MAAM,WAAW,QAAQ;GAAG,QAAQ;EAAO;CAC1D;AACF;;;;;AAMA,SAAgB,YAAY,MAA2B;CACrD,OAAO,KAAK,WAAW,QAAQ,CAAC,IAAI,SAAS;AAC/C;;;;;;;;;;;AAgBA,eAAsB,eACpB,OACA,QACwB;CACxB,MAAM,+BAAe,IAAI,IAAyB;CAElD,KAAK,MAAM,EAAE,MAAM,UAAU,YAAY,OAAO;EAC9C,QAAQ,iBAAiB;EACzB,MAAM,aAAa,cAAc,QAAQ,QAAQ,CAAC;EAClD,KAAK,MAAM,QAAQ,YAAY;GAC7B,QAAQ,iBAAiB;GACzB,MAAM,QAAQ,MAAM,eAAe,MAAM,EAAE,OAAO,CAAC;GACnD,IAAI,CAAC,OACH;GACF,IAAI,aAAa,IAAI,MAAM,IAAI,GAAG;IAEhC,MAAM,WAAW,aAAa,IAAI,MAAM,IAAI;IAC5C,MAAM,OAAwB;KAC5B,UAAU;KACV,MAAM;KACN,SAAS,sBAAsB,MAAM,KAAK,sBAAsB,KAAK,YAAY,OAAO,iBAAiB,SAAS,SAAS,YAAY,SAAS,OAAO;IACzJ;IACA,SAAS,cAAc,CAAC,GAAI,SAAS,eAAe,CAAC,GAAI,IAAI;IAC7D;GACF;GACA,aAAa,IAAI,MAAM,MAAM,KAAK;EACpC;CACF;CAEA,OAAO,CAAC,GAAG,aAAa,OAAO,CAAC;AAClC;;;ACnvBA,MAAM,mBAAmB;AACzB,MAAM,wBAAwB;AAC9B,MAAM,YAAY;AAClB,MAAM,sBAAsB;AAE5B,SAAS,WAAW,OAAuB;CAIzC,IAAI,iBAAiB,KAAK,KAAK,KAAK,sBAAsB,KAAK,KAAK,KAAK,UAAU,IACjF,OAAO,IAAI,MAAM,QAAQ,WAAW,MAAK,EAAE;CAC7C,OAAO;AACT;AAEA,SAAS,qBAAqB,OAA4B;CACxD,MAAM,QAAkB,CAAC,KAAK;CAE9B,MAAM,KAAK,SAAS,WAAW,MAAM,IAAI,GAAG;CAC5C,MAAM,KAAK,gBAAgB,WAAW,MAAM,WAAW,GAAG;CAE1D,IAAI,MAAM,SACR,MAAM,KAAK,YAAY,WAAW,MAAM,OAAO,GAAG;CACpD,IAAI,MAAM,eACR,MAAM,KAAK,kBAAkB,WAAW,MAAM,aAAa,GAAG;CAChE,IAAI,MAAM,cAAc,QACtB,MAAM,KAAK,kBAAkB,MAAM,aAAa,KAAK,GAAG,GAAG;CAE7D,IAAI,MAAM,YAAY,OAAO,KAAK,MAAM,QAAQ,CAAC,CAAC,SAAS,GAAG;EAC5D,MAAM,KAAK,WAAW;EACtB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,QAAQ,GAItD,MAAM,KAAK,KAAK,IAAI,KAAK,MAAM,QAAQ,WAAW,MAAK,EAAE,EAAE;CAE/D;CAEA,MAAM,KAAK,KAAK;CAChB,OAAO,MAAM,KAAK,IAAI;AACxB;;;;;;;;;AAcA,SAAgB,iBAAiB,OAAoB,WAA2B;CAC9E,MAAM,SAAS,sBAAsB,KAAK;CAC1C,IAAI,CAAC,OAAO,OAAO;EACjB,MAAM,UAAU,OAAO,OACpB,KAAI,MAAK,QAAQ,EAAE,KAAK,IAAI,EAAE,SAAS,CAAC,CACxC,KAAK,IAAI;EACZ,MAAM,IAAI,MAAM,+BAA+B,MAAM,KAAK,MAAM,SAAS;CAC3E;CAEA,MAAM,WAAW,KAAK,WAAW,MAAM,IAAI;CAC3C,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;CAEvC,MAAM,cAAc,qBAAqB,KAAK;CAI9C,MAAM,cAAc,MAAM,eAAe,MAAM,aAAa,QAAQ,qBAAqB,EAAE,IAAI;CAC/F,MAAM,UAAU,cACZ,GAAG,YAAY,MAAM,YAAY,MACjC,GAAG,YAAY;CAEnB,MAAM,YAAY,KAAK,UAAU,UAAU;CAC3C,cAAc,WAAW,OAAO;CAEhC,OAAO;AACT;;;;;;AAWA,SAAgB,kBAAkB,QAAuB,WAA2B;CAClF,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;CACxC,KAAK,MAAM,SAAS,QAClB,iBAAiB,OAAO,SAAS;CAEnC,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;AC9DA,eAAsB,cAAc,QAAqD;CACvF,MAAM,eAAkC,CAAC;CACzC,IAAI;CAEJ,IAAI,CAAC,OAAO,kBACV,aAAa,KAAK,GAAG,oBAAoB,CAAC;CAI5C,KAAK,MAAM,KAAK,OAAO,QAAQ,CAAC,GAC9B,aAAa,KAAK;EAAE,MAAM;EAAG,QAAQ,YAAY,CAAC;CAAE,CAAC;CAIvD,IAAI,OAAO,OAAO,QAAQ;EACxB,WAAW,YAAY,KAAK,OAAO,GAAG,gBAAgB,CAAC;EACvD,kBAAkB,OAAO,OAAO,QAAQ;EACxC,aAAa,KAAK;GAAE,MAAM;GAAU,QAAQ;EAAS,CAAC;CACxD;CAIA,MAAM,aAAa,MAAM,eAAe,YAAY;CAKpD,MAAM,+BAAe,IAAI,IAAyB;CAClD,KAAK,MAAM,SAAS,OAAO,WAAW,CAAC,GACrC,aAAa,IAAI,MAAM,MAAM,EAAE,GAAG,MAAM,CAAC;CAE3C,KAAK,MAAM,SAAS,YAAY;EAC9B,MAAM,WAAW,aAAa,IAAI,MAAM,IAAI;EAC5C,IAAI,UAAU;GACZ,MAAM,WAAW,MAAM,YAAY;GACnC,MAAM,YAAY,SAAS,YAAY;GACvC,MAAM,OAAwB;IAC5B,UAAU;IACV,MAAM;IACN,SAAS,sBAAsB,MAAM,KAAK,sBAAsB,SAAS,YAAY,MAAM,UAAU,UAAU,iBAAiB,UAAU,YAAY,SAAS,UAAU,SAAS;GACpL;GACA,SAAS,cAAc,CAAC,GAAI,SAAS,eAAe,CAAC,GAAI,IAAI;GAC7D;EACF;EACA,aAAa,IAAI,MAAM,MAAM,KAAK;CACpC;CACA,IAAI,SAAS,CAAC,GAAG,aAAa,OAAO,CAAC;CAQtC,IAAI,OAAO,uBAAuB,OAChC,SAAS,OAAO,QAAO,MAAK,EAAE,WAAW,KAAA,KAAa,EAAE,WAAW,SAAS;CAI9E,MAAM,UAAU,IAAI,IAAI,OAAO,WAAW,CAAC,CAAC;CAC5C,IAAI,WAAW,OAAO,QAAO,MAAK,CAAC,QAAQ,IAAI,EAAE,IAAI,CAAC;CAGtD,IAAI,MAAM,QAAQ,OAAO,OAAO,GAAG;EACjC,MAAM,YAAY,IAAI,IAAI,OAAO,OAAO;EACxC,WAAW,SAAS,QAAO,MAAK,UAAU,IAAI,EAAE,IAAI,CAAC;CACvD;CAcA,OAAO;EAAE,QAAQ;EAAU,SAZX,iBACN;GACJ,IAAI;IACF,OAAO,UAAW;KAAE,WAAW;KAAM,OAAO;IAAK,CAAC;GACpD,QACM,CAGN;EACF,UACM,CAAC;CAEwB;AACrC"}
|
package/dist/restate.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bi as McpToolWrap, Bp as StreamOptions, Dd as AgentBehavior, Lp as Provider, Nf as ToolContext, Od as AgentClock, Pf as ToolDef, bf as ToolResultContent, gf as ToolBatchExecutor, np as SessionStore, zi as McpToolMeta } from "./index-
|
|
1
|
+
import { Bi as McpToolWrap, Bp as StreamOptions, Dd as AgentBehavior, Lp as Provider, Nf as ToolContext, Od as AgentClock, Pf as ToolDef, bf as ToolResultContent, gf as ToolBatchExecutor, np as SessionStore, zi as McpToolMeta } from "./index-X02SI0nt.js";
|
|
2
2
|
import { h as TaskExitInfo, l as ExecutionHandle, m as TaskEntry, o as DetachedTasksCapability } from "./types-BDccavwj.js";
|
|
3
3
|
|
|
4
4
|
//#region src/restate/types.d.ts
|
package/dist/session/sqlite.d.ts
CHANGED
package/dist/session.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $f as SessionData, Ep as autoDetectAndConvert, Fp as toOpenAI, Ip as toWireMessages, Mp as fromOpenAI, Pp as toAnthropic, Qf as Session, Zf as CreateSessionOptions, ap as deleteExtensionSessionState, cf as SessionContentBlock, cp as loadSession, df as SessionMessage, dp as RemoteStoreOptions, ep as SessionMetaRow, ff as SessionTurn, fp as createRemoteStore, gp as createFileMapStore, hp as FileMapStoreOptions, ip as currentExtensionSession, jp as fromAnthropic, lp as setExtensionSessionState, mp as FileMapAdapter, np as SessionStore, op as demoteStaleRunningStatus, pp as createMemoryStore, rp as createSession, sp as getExtensionSessionState, tp as SessionRun, up as withExtensionSession, wp as ToWireMessagesOptions } from "./index-
|
|
1
|
+
import { $f as SessionData, Ep as autoDetectAndConvert, Fp as toOpenAI, Ip as toWireMessages, Mp as fromOpenAI, Pp as toAnthropic, Qf as Session, Zf as CreateSessionOptions, ap as deleteExtensionSessionState, cf as SessionContentBlock, cp as loadSession, df as SessionMessage, dp as RemoteStoreOptions, ep as SessionMetaRow, ff as SessionTurn, fp as createRemoteStore, gp as createFileMapStore, hp as FileMapStoreOptions, ip as currentExtensionSession, jp as fromAnthropic, lp as setExtensionSessionState, mp as FileMapAdapter, np as SessionStore, op as demoteStaleRunningStatus, pp as createMemoryStore, rp as createSession, sp as getExtensionSessionState, tp as SessionRun, up as withExtensionSession, wp as ToWireMessagesOptions } from "./index-X02SI0nt.js";
|
|
2
2
|
export { CreateSessionOptions, type FileMapAdapter, type FileMapStoreOptions, type RemoteStoreOptions, Session, type SessionContentBlock, SessionData, type SessionMessage, SessionMetaRow, SessionRun, SessionStore, type SessionTurn, type ToWireMessagesOptions, autoDetectAndConvert, createFileMapStore, createMemoryStore, createRemoteStore, createSession, currentExtensionSession, deleteExtensionSessionState, demoteStaleRunningStatus, fromAnthropic, fromOpenAI, getExtensionSessionState, loadSession, setExtensionSessionState, toAnthropic, toOpenAI, toWireMessages, withExtensionSession };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { l as errorMessage } from "./errors-DJUxZg9b.js";
|
|
2
|
-
import { A as validateSkillName, _ as lastLine, b as resolveSubdirRoot, c as parseSkillFile, g as fetchInstallSource, h as defaultWhich, j as projectUserPaths, k as validateSkillForWrite, m as defaultExec, p as InstallSourceError, v as parseInstallSource } from "./resolve-
|
|
2
|
+
import { A as validateSkillName, _ as lastLine, b as resolveSubdirRoot, c as parseSkillFile, g as fetchInstallSource, h as defaultWhich, j as projectUserPaths, k as validateSkillForWrite, m as defaultExec, p as InstallSourceError, v as parseInstallSource } from "./resolve-HtxmBWs9.js";
|
|
3
3
|
import { basename, join, resolve } from "node:path";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
@@ -292,4 +292,4 @@ function defineSkill(config) {
|
|
|
292
292
|
//#endregion
|
|
293
293
|
export { listSkillCandidates as a, installSkillFromSpec as i, SKILL_PROVENANCE_FILE as n, parseSkillInstallSpec as o, SkillInstallError as r, readSkillProvenance as s, defineSkill as t };
|
|
294
294
|
|
|
295
|
-
//# sourceMappingURL=skills-
|
|
295
|
+
//# sourceMappingURL=skills-BlmY7QhV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills-BjeXSRlQ.js","names":[],"sources":["../src/skills/install.ts","../src/skills/index.ts"],"sourcesContent":["/**\n * Skill installation — fetch a skill (or a collection of skills) from\n * GitHub / npm / skills.sh and land it under the zidane skills root,\n * where the existing discovery scan picks it up.\n *\n * Built on the shared install layer (`src/install/source.ts`), so the\n * spec grammar, transports, download caps, and subdir containment are\n * byte-identical with the extensions installer. What differs:\n *\n * - **Validation never executes code.** A skill is data: candidates\n * are validated by parsing `SKILL.md` (lenient parser, same one\n * discovery uses) — unlike extensions, whose validation must import\n * the module. Installing a hostile skill can plant instructions,\n * never run a process.\n * - **skills.sh interop, two-way.** The spec grammar accepts pasted\n * `https://skills.sh/<owner>/<repo>[/<skill>]` catalog URLs (mapped\n * to the GitHub repo + a skill selector — skills.sh uses GitHub as\n * its registry). And when the `skills` CLI is on PATH,\n * {@link installSkillFromSpec} delegates to it (`skills add … -y`)\n * so installs land in the user's cross-agent `.agents/skills/`\n * layout and feed the skills.sh lockfile/leaderboard; without the\n * CLI the native fetch path installs the same repos directly.\n * - **Target roots**: `~/.zidane/skills/<name>` (user) or\n * `<gitRoot>/.zidane/skills/<name>` (project) — both already on\n * discovery's default scan paths.\n *\n * Same hardening as extensions: staged `mkdtemp` fetch, physical\n * symlink containment for `:subdir`, folder-safe names, overwrite with\n * backup/rollback, and a provenance file (`.zidane-install.json`) so a\n * future update flow can replay the spec.\n */\n\nimport type { InstallIo, InstallScope, InstallSource } from '../install/source'\nimport { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { basename, join, resolve } from 'node:path'\nimport { projectUserPaths } from '../chat/project-user-paths'\nimport { errorMessage } from '../errors'\nimport { defaultExec, defaultWhich, fetchInstallSource, InstallSourceError, lastLine, parseInstallSource, resolveSubdirRoot } from '../install/source'\nimport { parseSkillFile } from './discovery'\nimport { validateSkillName } from './validate'\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport type SkillInstallErrorCode\n = | 'invalid-source'\n | 'fetch-failed'\n | 'no-skill'\n | 'multiple-candidates'\n | 'validate-failed'\n | 'exists'\n | 'cli-failed'\n | 'io-failed'\n\nexport class SkillInstallError extends InstallSourceError {\n declare readonly code: SkillInstallErrorCode\n constructor(code: SkillInstallErrorCode, message: string, candidates?: readonly string[]) {\n super(code, message, candidates)\n this.name = 'SkillInstallError'\n }\n}\n\nfunction rethrowAsSkillError(err: unknown): never {\n if (err instanceof InstallSourceError && !(err instanceof SkillInstallError))\n throw new SkillInstallError(err.code as SkillInstallErrorCode, err.message, err.candidates)\n throw err\n}\n\n// ---------------------------------------------------------------------------\n// Spec parsing (shared grammar + the skills.sh catalog URL form)\n// ---------------------------------------------------------------------------\n\nconst SKILLS_SH_URL_RE = /^(?:https?:\\/\\/)?(?:www\\.)?skills\\.sh\\/([\\w.-]+)\\/([\\w.-]+)(?:\\/([\\w.-]+))?\\/?$/\n\nexport interface SkillInstallSpec {\n source: InstallSource\n /**\n * Skill name selector for multi-skill sources. From a skills.sh URL's\n * third segment or the caller's explicit pick after a\n * `multiple-candidates` error.\n */\n skill?: string\n /**\n * The spec string to hand the `skills` CLI (its `add` argument).\n * skills.sh URLs pass through verbatim — the CLI understands them —\n * while parsed shorthand re-serializes to `owner/repo`.\n */\n cliSpec: string\n}\n\n/**\n * Parse a raw skill source. Accepts everything the shared grammar does\n * (`owner/repo[#ref][:subdir]`, GitHub URLs, `pkg@version`, …) plus\n * pasted skills.sh catalog URLs — `skills.sh/vercel-labs/agent-skills/\n * react-best-practices` maps to the backing GitHub repo with the third\n * segment as the skill selector.\n */\nexport function parseSkillInstallSpec(raw: string): SkillInstallSpec {\n const spec = raw.trim()\n const skillsSh = SKILLS_SH_URL_RE.exec(spec)\n if (skillsSh) {\n return {\n source: { kind: 'github', owner: skillsSh[1] as string, repo: skillsSh[2] as string },\n ...(skillsSh[3] ? { skill: skillsSh[3] } : {}),\n cliSpec: `${skillsSh[1]}/${skillsSh[2]}`,\n }\n }\n try {\n const source = parseInstallSource(spec)\n return { source, cliSpec: spec }\n }\n catch (err) {\n rethrowAsSkillError(err)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Candidate enumeration + validation (data-only — no code execution)\n// ---------------------------------------------------------------------------\n\nexport interface SkillInstallCandidate {\n /** Directory name candidate (validated against SKILL.md frontmatter later). */\n name: string\n dir: string\n /**\n * Root-relative path (`engineering/tdd`) — the unambiguous selector\n * when the same skill NAME exists in several category directories.\n */\n rel: string\n}\n\n/**\n * How deep the candidate walk descends. Real-world collections nest\n * skills under category directories (`skills/engineering/tdd/SKILL.md`\n * in mattpocock/skills; `.github/skills/…` elsewhere) — one-level\n * enumeration missed all of them. Four levels covers every observed\n * layout while keeping the walk trivially bounded on the staged tree.\n */\nconst CANDIDATE_WALK_MAX_DEPTH = 4\n\n/**\n * List installable skills inside a fetched tree.\n *\n * A skill is ANY directory containing a `SKILL.md` — found by a\n * bounded recursive walk (depth {@link CANDIDATE_WALK_MAX_DEPTH}),\n * skipping dot-dirs and `node_modules`, and never descending INTO a\n * skill (its `references/` / `scripts/` subtree ships with it, it\n * doesn't nest further candidates). A root-level `SKILL.md` means\n * \"repo IS the skill\" and short-circuits, named from the fallback.\n *\n * Candidates carry their root-relative path (`rel`) so same-named\n * skills in different categories stay individually addressable.\n * Sorted by `rel`.\n */\nexport function listSkillCandidates(dir: string, fallbackName: string): SkillInstallCandidate[] {\n if (existsSync(join(dir, 'SKILL.md')))\n return [{ name: sanitizeName(fallbackName), dir, rel: '.' }]\n const out: SkillInstallCandidate[] = []\n const walk = (current: string, rel: string, depth: number): void => {\n if (depth > CANDIDATE_WALK_MAX_DEPTH)\n return\n for (const entry of readdirSync(current, { withFileTypes: true })) {\n if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules')\n continue\n const childDir = join(current, entry.name)\n const childRel = rel.length === 0 ? entry.name : `${rel}/${entry.name}`\n if (existsSync(join(childDir, 'SKILL.md')))\n out.push({ name: entry.name, dir: childDir, rel: childRel })\n else\n walk(childDir, childRel, depth + 1)\n }\n }\n walk(dir, '', 1)\n return out.sort((a, b) => a.rel.localeCompare(b.rel))\n}\n\n/** Human-readable candidate list for error messages — capped, rel-qualified when ambiguous. */\nfunction describeCandidates(candidates: readonly SkillInstallCandidate[]): string {\n const nameCounts = new Map<string, number>()\n for (const c of candidates)\n nameCounts.set(c.name, (nameCounts.get(c.name) ?? 0) + 1)\n const labels = candidates.map(c => ((nameCounts.get(c.name) ?? 0) > 1 ? c.rel : c.name))\n const shown = labels.slice(0, 20)\n const more = labels.length - shown.length\n return shown.join(', ') + (more > 0 ? `, … and ${more} more` : '')\n}\n\n/**\n * Validate a staged candidate by PARSING its SKILL.md — the same lenient\n * parser discovery runs, so \"installs cleanly\" and \"discovers cleanly\"\n * are the same predicate. Returns the frontmatter name (which wins over\n * the directory-derived candidate name for the target folder).\n */\nasync function validateSkillCandidate(candidate: SkillInstallCandidate): Promise<{ name: string }> {\n const parsed = await parseSkillFile(join(candidate.dir, 'SKILL.md'))\n if (!parsed)\n throw new SkillInstallError('validate-failed', `${candidate.dir}/SKILL.md is not a valid skill (missing name or description in frontmatter).`)\n const name = parsed.name\n if (!validateSkillName(name))\n throw new SkillInstallError('validate-failed', `Skill name \"${name}\" is invalid (lowercase alphanumerics + single hyphens, max 64 chars).`)\n return { name }\n}\n\n// ---------------------------------------------------------------------------\n// Install\n// ---------------------------------------------------------------------------\n\nexport interface SkillInstallOptions {\n /** Raw source spec — see {@link parseSkillInstallSpec} for the grammar. */\n source: string\n scope: InstallScope\n /** Pick one skill from a multi-skill source (names from the `multiple-candidates` error). */\n skill?: string\n /** Overwrite an existing install of the same name. */\n overwrite?: boolean\n cwd?: string\n home?: string\n /** Storage prefix (default `.zidane`) — mirrors `ResolvedConfig.prefix`. */\n prefix?: string\n io?: InstallIo\n onProgress?: (message: string) => void\n /**\n * Prefer the skills.sh CLI when `skills` is on PATH (default true).\n * The CLI owns scope + layout decisions (`.agents/skills/`, their\n * lockfile); the native path is the fallback and the forced path in\n * tests. Set false to always install natively.\n */\n preferSkillsCli?: boolean\n}\n\nexport interface SkillInstallResult {\n /** Final skill name(s) installed. The CLI path reports the spec, not names. */\n installed: readonly string[]\n /** Absolute target directory (native path only — the CLI owns its layout). */\n dir?: string\n /** `skills-cli` when delegated to the skills.sh CLI, else `native`. */\n engine: 'skills-cli' | 'native'\n provenance?: string\n}\n\n/**\n * Install a skill (or one skill out of a multi-skill source).\n *\n * Engine selection: the skills.sh CLI when present on PATH (unless\n * `preferSkillsCli: false`), else the native fetch pipeline. Both accept\n * the same specs; the CLI path additionally understands anything newer\n * their grammar grows, since the spec passes through verbatim.\n */\nexport async function installSkillFromSpec(opts: SkillInstallOptions): Promise<SkillInstallResult> {\n const io = opts.io ?? {}\n const which = io.which ?? defaultWhich\n const spec = parseSkillInstallSpec(opts.source)\n const skillSelector = opts.skill ?? spec.skill\n\n if ((opts.preferSkillsCli ?? true) && which('skills'))\n return await installViaSkillsCli(spec, skillSelector, opts)\n\n return await installNatively(spec, skillSelector, opts)\n}\n\n/**\n * Delegate to the skills.sh CLI. Non-interactive by construction: `-y`\n * skips confirmation prompts, `-g` maps our `user` scope to their\n * global scope (project scope is their default, keyed off cwd). The CLI\n * decides the on-disk layout (`.agents/skills/`), which zidane's\n * discovery already scans.\n */\nasync function installViaSkillsCli(\n spec: SkillInstallSpec,\n skillSelector: string | undefined,\n opts: SkillInstallOptions,\n): Promise<SkillInstallResult> {\n const exec = opts.io?.exec ?? defaultExec\n const args = ['add', spec.cliSpec, '-y']\n if (skillSelector)\n args.push('--skill', skillSelector)\n if (opts.scope === 'user')\n args.push('-g')\n opts.onProgress?.(`skills add ${spec.cliSpec}${skillSelector ? ` --skill ${skillSelector}` : ''}…`)\n const res = await exec('skills', args, { cwd: opts.cwd ?? process.cwd() })\n if (!res.ok)\n throw new SkillInstallError('cli-failed', `skills.sh CLI failed: ${lastLine(res.stderr) || lastLine(res.stdout) || 'unknown error'}`)\n return {\n installed: [skillSelector ?? spec.cliSpec],\n engine: 'skills-cli',\n }\n}\n\nasync function installNatively(\n spec: SkillInstallSpec,\n skillSelector: string | undefined,\n opts: SkillInstallOptions,\n): Promise<SkillInstallResult> {\n const io = opts.io ?? {}\n const source = spec.source\n const stage = mkdtempSync(join(tmpdir(), 'zidane-skill-install-'))\n try {\n const fetchedInto = join(stage, 'fetched')\n mkdirSync(fetchedInto, { recursive: true })\n let provenance: string\n try {\n provenance = (await fetchInstallSource(source, fetchedInto, io, opts.onProgress)).provenance\n }\n catch (err) {\n rethrowAsSkillError(err)\n }\n\n // `:subdir` re-roots the search — same physical containment as\n // extensions (hostile symlinks must not walk out of the stage).\n let candidateRoot = fetchedInto\n let fallbackName = source.kind === 'github' ? source.repo : source.pkg\n if (source.kind === 'github' && source.subdir) {\n const rooted = resolveSubdirRoot(fetchedInto, source.subdir)\n if (!rooted.ok) {\n if (rooted.reason === 'missing')\n throw new SkillInstallError('no-skill', `\"${source.subdir}\" is not a directory in ${source.owner}/${source.repo}.`)\n throw new SkillInstallError('invalid-source', `Subdirectory \"${source.subdir}\" escapes the repository root${rooted.reason === 'escape-symlink' ? ' through a symlink' : ''}.`)\n }\n candidateRoot = rooted.dir\n fallbackName = basename(resolve(fetchedInto, source.subdir))\n }\n\n const candidates = listSkillCandidates(candidateRoot, fallbackName)\n if (candidates.length === 0)\n throw new SkillInstallError('no-skill', `No skill found in ${opts.source} — no SKILL.md anywhere in the tree (searched ${CANDIDATE_WALK_MAX_DEPTH} levels deep).`)\n let picked: SkillInstallCandidate\n if (skillSelector) {\n // Selector matches the skill name OR its root-relative path — the\n // path form disambiguates same-named skills in different category\n // directories (`engineering/tdd` vs `personal/tdd`).\n const matches = candidates.filter(c => c.name === skillSelector || c.rel === skillSelector)\n if (matches.length === 0)\n throw new SkillInstallError('no-skill', `No skill named \"${skillSelector}\" in ${opts.source}. Available: ${describeCandidates(candidates)}`, candidates.map(c => c.rel))\n if (matches.length > 1)\n throw new SkillInstallError('multiple-candidates', `\"${skillSelector}\" is ambiguous in ${opts.source} — pick a path: ${matches.map(c => c.rel).join(', ')}`, matches.map(c => c.rel))\n picked = matches[0] as SkillInstallCandidate\n }\n else if (candidates.length > 1) {\n throw new SkillInstallError('multiple-candidates', `${opts.source} contains ${candidates.length} skills — pick one: ${describeCandidates(candidates)}`, candidates.map(c => c.rel))\n }\n else {\n picked = candidates[0] as SkillInstallCandidate\n }\n\n // Frontmatter name wins over the directory-derived candidate name —\n // mirrors \"target folder is named from the VALIDATED definition\".\n const { name } = await validateSkillCandidate(picked)\n\n const root = scopeRoot(opts)\n const targetDir = join(root, name)\n const backupDir = `${targetDir}.zidane-backup`\n if (existsSync(targetDir) && !opts.overwrite)\n throw new SkillInstallError('exists', `Skill \"${name}\" is already installed at ${targetDir}. Overwrite to replace it.`)\n\n mkdirSync(root, { recursive: true })\n const hadPrevious = existsSync(targetDir)\n if (hadPrevious) {\n rmSync(backupDir, { recursive: true, force: true })\n renameSync(targetDir, backupDir)\n }\n try {\n // `dereference` materializes in-tree symlinked files so the install\n // has no dangling links once the stage is deleted.\n cpSync(picked.dir, targetDir, { recursive: true, dereference: true })\n writeProvenance(targetDir, { spec: opts.source, ...(skillSelector ? { skill: skillSelector } : {}), scope: opts.scope, provenance, installedAt: Date.now() })\n }\n catch (err) {\n rmSync(targetDir, { recursive: true, force: true })\n if (hadPrevious)\n renameSync(backupDir, targetDir)\n throw new SkillInstallError('io-failed', `Writing ${targetDir} failed: ${errorMessage(err)}`)\n }\n rmSync(backupDir, { recursive: true, force: true })\n\n return { installed: [name], dir: targetDir, engine: 'native', provenance }\n }\n finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Provenance sidecar — lets a future update flow replay the recorded spec. */\nexport const SKILL_PROVENANCE_FILE = '.zidane-install.json'\n\ninterface SkillProvenance {\n spec: string\n skill?: string\n scope: InstallScope\n provenance: string\n installedAt: number\n}\n\nfunction writeProvenance(dir: string, data: SkillProvenance): void {\n writeFileSync(join(dir, SKILL_PROVENANCE_FILE), `${JSON.stringify(data, null, 2)}\\n`)\n}\n\n/** Read a skill directory's install provenance, `null` for hand-authored skills. */\nexport function readSkillProvenance(dir: string): (SkillProvenance & { spec: string }) | null {\n try {\n const raw = JSON.parse(readFileSync(join(dir, SKILL_PROVENANCE_FILE), 'utf8')) as Partial<SkillProvenance>\n return typeof raw.spec === 'string' && raw.spec.length > 0 ? (raw as SkillProvenance) : null\n }\n catch {\n return null\n }\n}\n\n/**\n * Native-install target root: the `<prefix>/skills` flavor of the\n * project/user convention (`~/.zidane/skills`, `<gitRoot>/.zidane/skills`).\n * The `.agents/skills` siblings stay read-only for us — they belong to\n * the cross-agent ecosystem (and the skills.sh CLI writes there).\n */\nfunction scopeRoot(opts: SkillInstallOptions): string {\n const roots = projectUserPaths({\n subPath: 'skills',\n ...(opts.cwd ? { cwd: opts.cwd } : {}),\n ...(opts.home ? { home: opts.home } : {}),\n ...(opts.prefix ? { prefix: opts.prefix } : {}),\n })\n const root = roots.find(r => r.source === opts.scope && r.path.includes(`.${(opts.prefix ?? '.zidane').replace(/^\\./, '')}`))\n if (!root)\n throw new SkillInstallError('io-failed', `No ${opts.scope} skills root resolved.`)\n return root.path\n}\n\nfunction sanitizeName(raw: string): string {\n const cleaned = raw.toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '').replace(/-{2,}/g, '-')\n return cleaned.length > 0 ? cleaned : 'skill'\n}\n","import type { SkillConfig } from './types'\nimport { validateSkillForWrite } from './validate'\n\nexport {\n type ActivationVia,\n type ActiveSkill,\n createSkillActivationState,\n type DeactivationReason,\n type SkillActivationState,\n type SkillActivationStateOptions,\n} from './activation'\nexport {\n IMPLICITLY_ALLOWED_SKILL_TOOLS,\n installAllowedToolsGate,\n} from './allowed-tools'\nexport { buildCatalog } from './catalog'\nexport {\n discoverSkills,\n getDefaultScanPaths,\n inferSource,\n parseFrontmatter,\n parseSkillFile,\n} from './discovery'\nexport type { SourcedScanPath } from './discovery'\nexport {\n installSkillFromSpec,\n listSkillCandidates,\n parseSkillInstallSpec,\n readSkillProvenance,\n SKILL_PROVENANCE_FILE,\n SkillInstallError,\n} from './install'\nexport type {\n SkillInstallCandidate,\n SkillInstallErrorCode,\n SkillInstallOptions,\n SkillInstallResult,\n SkillInstallSpec,\n} from './install'\nexport { interpolateShellCommands, stripShellInterpolations } from './interpolate'\nexport type { InterpolateShellCommandsOptions } from './interpolate'\nexport { resolveSkills } from './resolve'\nexport type {\n ShellInterpolationApproval,\n SkillConfig,\n SkillDiagnostic,\n SkillResource,\n SkillsConfig,\n SkillSource,\n} from './types'\nexport {\n isToolAllowedByUnion,\n matchesAllowedTool,\n parseAllowedToolPattern,\n validateResourcePath,\n validateResourcePathReal,\n validateSkillForWrite,\n validateSkillName,\n} from './validate'\nexport type { SkillValidationIssue, SkillValidationResult } from './validate'\nexport { writeSkillsToDisk, writeSkillToDisk } from './writer'\n\n// ---------------------------------------------------------------------------\n// defineSkill helper\n// ---------------------------------------------------------------------------\n\n/**\n * Define an inline skill configuration.\n *\n * Strict-validates at author-time — throws if the config would be rejected by\n * `writeSkillToDisk` or the spec. Source defaults to `'inline'`.\n */\nexport function defineSkill(config: Omit<SkillConfig, 'source'> & { source?: SkillConfig['source'] }): SkillConfig {\n const normalized: SkillConfig = {\n ...config,\n source: config.source ?? 'inline',\n }\n const result = validateSkillForWrite(normalized)\n if (!result.valid) {\n const summary = result.errors.map(e => ` - [${e.code}] ${e.message}`).join('\\n')\n throw new Error(`Invalid skill \"${normalized.name}\":\\n${summary}`)\n }\n return normalized\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"skills-BlmY7QhV.js","names":[],"sources":["../src/skills/install.ts","../src/skills/index.ts"],"sourcesContent":["/**\n * Skill installation — fetch a skill (or a collection of skills) from\n * GitHub / npm / skills.sh and land it under the zidane skills root,\n * where the existing discovery scan picks it up.\n *\n * Built on the shared install layer (`src/install/source.ts`), so the\n * spec grammar, transports, download caps, and subdir containment are\n * byte-identical with the extensions installer. What differs:\n *\n * - **Validation never executes code.** A skill is data: candidates\n * are validated by parsing `SKILL.md` (lenient parser, same one\n * discovery uses) — unlike extensions, whose validation must import\n * the module. Installing a hostile skill can plant instructions,\n * never run a process.\n * - **skills.sh interop, two-way.** The spec grammar accepts pasted\n * `https://skills.sh/<owner>/<repo>[/<skill>]` catalog URLs (mapped\n * to the GitHub repo + a skill selector — skills.sh uses GitHub as\n * its registry). And when the `skills` CLI is on PATH,\n * {@link installSkillFromSpec} delegates to it (`skills add … -y`)\n * so installs land in the user's cross-agent `.agents/skills/`\n * layout and feed the skills.sh lockfile/leaderboard; without the\n * CLI the native fetch path installs the same repos directly.\n * - **Target roots**: `~/.zidane/skills/<name>` (user) or\n * `<gitRoot>/.zidane/skills/<name>` (project) — both already on\n * discovery's default scan paths.\n *\n * Same hardening as extensions: staged `mkdtemp` fetch, physical\n * symlink containment for `:subdir`, folder-safe names, overwrite with\n * backup/rollback, and a provenance file (`.zidane-install.json`) so a\n * future update flow can replay the spec.\n */\n\nimport type { InstallIo, InstallScope, InstallSource } from '../install/source'\nimport { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { basename, join, resolve } from 'node:path'\nimport { projectUserPaths } from '../chat/project-user-paths'\nimport { errorMessage } from '../errors'\nimport { defaultExec, defaultWhich, fetchInstallSource, InstallSourceError, lastLine, parseInstallSource, resolveSubdirRoot } from '../install/source'\nimport { parseSkillFile } from './discovery'\nimport { validateSkillName } from './validate'\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport type SkillInstallErrorCode\n = | 'invalid-source'\n | 'fetch-failed'\n | 'no-skill'\n | 'multiple-candidates'\n | 'validate-failed'\n | 'exists'\n | 'cli-failed'\n | 'io-failed'\n\nexport class SkillInstallError extends InstallSourceError {\n declare readonly code: SkillInstallErrorCode\n constructor(code: SkillInstallErrorCode, message: string, candidates?: readonly string[]) {\n super(code, message, candidates)\n this.name = 'SkillInstallError'\n }\n}\n\nfunction rethrowAsSkillError(err: unknown): never {\n if (err instanceof InstallSourceError && !(err instanceof SkillInstallError))\n throw new SkillInstallError(err.code as SkillInstallErrorCode, err.message, err.candidates)\n throw err\n}\n\n// ---------------------------------------------------------------------------\n// Spec parsing (shared grammar + the skills.sh catalog URL form)\n// ---------------------------------------------------------------------------\n\nconst SKILLS_SH_URL_RE = /^(?:https?:\\/\\/)?(?:www\\.)?skills\\.sh\\/([\\w.-]+)\\/([\\w.-]+)(?:\\/([\\w.-]+))?\\/?$/\n\nexport interface SkillInstallSpec {\n source: InstallSource\n /**\n * Skill name selector for multi-skill sources. From a skills.sh URL's\n * third segment or the caller's explicit pick after a\n * `multiple-candidates` error.\n */\n skill?: string\n /**\n * The spec string to hand the `skills` CLI (its `add` argument).\n * skills.sh URLs pass through verbatim — the CLI understands them —\n * while parsed shorthand re-serializes to `owner/repo`.\n */\n cliSpec: string\n}\n\n/**\n * Parse a raw skill source. Accepts everything the shared grammar does\n * (`owner/repo[#ref][:subdir]`, GitHub URLs, `pkg@version`, …) plus\n * pasted skills.sh catalog URLs — `skills.sh/vercel-labs/agent-skills/\n * react-best-practices` maps to the backing GitHub repo with the third\n * segment as the skill selector.\n */\nexport function parseSkillInstallSpec(raw: string): SkillInstallSpec {\n const spec = raw.trim()\n const skillsSh = SKILLS_SH_URL_RE.exec(spec)\n if (skillsSh) {\n return {\n source: { kind: 'github', owner: skillsSh[1] as string, repo: skillsSh[2] as string },\n ...(skillsSh[3] ? { skill: skillsSh[3] } : {}),\n cliSpec: `${skillsSh[1]}/${skillsSh[2]}`,\n }\n }\n try {\n const source = parseInstallSource(spec)\n return { source, cliSpec: spec }\n }\n catch (err) {\n rethrowAsSkillError(err)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Candidate enumeration + validation (data-only — no code execution)\n// ---------------------------------------------------------------------------\n\nexport interface SkillInstallCandidate {\n /** Directory name candidate (validated against SKILL.md frontmatter later). */\n name: string\n dir: string\n /**\n * Root-relative path (`engineering/tdd`) — the unambiguous selector\n * when the same skill NAME exists in several category directories.\n */\n rel: string\n}\n\n/**\n * How deep the candidate walk descends. Real-world collections nest\n * skills under category directories (`skills/engineering/tdd/SKILL.md`\n * in mattpocock/skills; `.github/skills/…` elsewhere) — one-level\n * enumeration missed all of them. Four levels covers every observed\n * layout while keeping the walk trivially bounded on the staged tree.\n */\nconst CANDIDATE_WALK_MAX_DEPTH = 4\n\n/**\n * List installable skills inside a fetched tree.\n *\n * A skill is ANY directory containing a `SKILL.md` — found by a\n * bounded recursive walk (depth {@link CANDIDATE_WALK_MAX_DEPTH}),\n * skipping dot-dirs and `node_modules`, and never descending INTO a\n * skill (its `references/` / `scripts/` subtree ships with it, it\n * doesn't nest further candidates). A root-level `SKILL.md` means\n * \"repo IS the skill\" and short-circuits, named from the fallback.\n *\n * Candidates carry their root-relative path (`rel`) so same-named\n * skills in different categories stay individually addressable.\n * Sorted by `rel`.\n */\nexport function listSkillCandidates(dir: string, fallbackName: string): SkillInstallCandidate[] {\n if (existsSync(join(dir, 'SKILL.md')))\n return [{ name: sanitizeName(fallbackName), dir, rel: '.' }]\n const out: SkillInstallCandidate[] = []\n const walk = (current: string, rel: string, depth: number): void => {\n if (depth > CANDIDATE_WALK_MAX_DEPTH)\n return\n for (const entry of readdirSync(current, { withFileTypes: true })) {\n if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === 'node_modules')\n continue\n const childDir = join(current, entry.name)\n const childRel = rel.length === 0 ? entry.name : `${rel}/${entry.name}`\n if (existsSync(join(childDir, 'SKILL.md')))\n out.push({ name: entry.name, dir: childDir, rel: childRel })\n else\n walk(childDir, childRel, depth + 1)\n }\n }\n walk(dir, '', 1)\n return out.sort((a, b) => a.rel.localeCompare(b.rel))\n}\n\n/** Human-readable candidate list for error messages — capped, rel-qualified when ambiguous. */\nfunction describeCandidates(candidates: readonly SkillInstallCandidate[]): string {\n const nameCounts = new Map<string, number>()\n for (const c of candidates)\n nameCounts.set(c.name, (nameCounts.get(c.name) ?? 0) + 1)\n const labels = candidates.map(c => ((nameCounts.get(c.name) ?? 0) > 1 ? c.rel : c.name))\n const shown = labels.slice(0, 20)\n const more = labels.length - shown.length\n return shown.join(', ') + (more > 0 ? `, … and ${more} more` : '')\n}\n\n/**\n * Validate a staged candidate by PARSING its SKILL.md — the same lenient\n * parser discovery runs, so \"installs cleanly\" and \"discovers cleanly\"\n * are the same predicate. Returns the frontmatter name (which wins over\n * the directory-derived candidate name for the target folder).\n */\nasync function validateSkillCandidate(candidate: SkillInstallCandidate): Promise<{ name: string }> {\n const parsed = await parseSkillFile(join(candidate.dir, 'SKILL.md'))\n if (!parsed)\n throw new SkillInstallError('validate-failed', `${candidate.dir}/SKILL.md is not a valid skill (missing name or description in frontmatter).`)\n const name = parsed.name\n if (!validateSkillName(name))\n throw new SkillInstallError('validate-failed', `Skill name \"${name}\" is invalid (lowercase alphanumerics + single hyphens, max 64 chars).`)\n return { name }\n}\n\n// ---------------------------------------------------------------------------\n// Install\n// ---------------------------------------------------------------------------\n\nexport interface SkillInstallOptions {\n /** Raw source spec — see {@link parseSkillInstallSpec} for the grammar. */\n source: string\n scope: InstallScope\n /** Pick one skill from a multi-skill source (names from the `multiple-candidates` error). */\n skill?: string\n /** Overwrite an existing install of the same name. */\n overwrite?: boolean\n cwd?: string\n home?: string\n /** Storage prefix (default `.zidane`) — mirrors `ResolvedConfig.prefix`. */\n prefix?: string\n io?: InstallIo\n onProgress?: (message: string) => void\n /**\n * Prefer the skills.sh CLI when `skills` is on PATH (default true).\n * The CLI owns scope + layout decisions (`.agents/skills/`, their\n * lockfile); the native path is the fallback and the forced path in\n * tests. Set false to always install natively.\n */\n preferSkillsCli?: boolean\n}\n\nexport interface SkillInstallResult {\n /** Final skill name(s) installed. The CLI path reports the spec, not names. */\n installed: readonly string[]\n /** Absolute target directory (native path only — the CLI owns its layout). */\n dir?: string\n /** `skills-cli` when delegated to the skills.sh CLI, else `native`. */\n engine: 'skills-cli' | 'native'\n provenance?: string\n}\n\n/**\n * Install a skill (or one skill out of a multi-skill source).\n *\n * Engine selection: the skills.sh CLI when present on PATH (unless\n * `preferSkillsCli: false`), else the native fetch pipeline. Both accept\n * the same specs; the CLI path additionally understands anything newer\n * their grammar grows, since the spec passes through verbatim.\n */\nexport async function installSkillFromSpec(opts: SkillInstallOptions): Promise<SkillInstallResult> {\n const io = opts.io ?? {}\n const which = io.which ?? defaultWhich\n const spec = parseSkillInstallSpec(opts.source)\n const skillSelector = opts.skill ?? spec.skill\n\n if ((opts.preferSkillsCli ?? true) && which('skills'))\n return await installViaSkillsCli(spec, skillSelector, opts)\n\n return await installNatively(spec, skillSelector, opts)\n}\n\n/**\n * Delegate to the skills.sh CLI. Non-interactive by construction: `-y`\n * skips confirmation prompts, `-g` maps our `user` scope to their\n * global scope (project scope is their default, keyed off cwd). The CLI\n * decides the on-disk layout (`.agents/skills/`), which zidane's\n * discovery already scans.\n */\nasync function installViaSkillsCli(\n spec: SkillInstallSpec,\n skillSelector: string | undefined,\n opts: SkillInstallOptions,\n): Promise<SkillInstallResult> {\n const exec = opts.io?.exec ?? defaultExec\n const args = ['add', spec.cliSpec, '-y']\n if (skillSelector)\n args.push('--skill', skillSelector)\n if (opts.scope === 'user')\n args.push('-g')\n opts.onProgress?.(`skills add ${spec.cliSpec}${skillSelector ? ` --skill ${skillSelector}` : ''}…`)\n const res = await exec('skills', args, { cwd: opts.cwd ?? process.cwd() })\n if (!res.ok)\n throw new SkillInstallError('cli-failed', `skills.sh CLI failed: ${lastLine(res.stderr) || lastLine(res.stdout) || 'unknown error'}`)\n return {\n installed: [skillSelector ?? spec.cliSpec],\n engine: 'skills-cli',\n }\n}\n\nasync function installNatively(\n spec: SkillInstallSpec,\n skillSelector: string | undefined,\n opts: SkillInstallOptions,\n): Promise<SkillInstallResult> {\n const io = opts.io ?? {}\n const source = spec.source\n const stage = mkdtempSync(join(tmpdir(), 'zidane-skill-install-'))\n try {\n const fetchedInto = join(stage, 'fetched')\n mkdirSync(fetchedInto, { recursive: true })\n let provenance: string\n try {\n provenance = (await fetchInstallSource(source, fetchedInto, io, opts.onProgress)).provenance\n }\n catch (err) {\n rethrowAsSkillError(err)\n }\n\n // `:subdir` re-roots the search — same physical containment as\n // extensions (hostile symlinks must not walk out of the stage).\n let candidateRoot = fetchedInto\n let fallbackName = source.kind === 'github' ? source.repo : source.pkg\n if (source.kind === 'github' && source.subdir) {\n const rooted = resolveSubdirRoot(fetchedInto, source.subdir)\n if (!rooted.ok) {\n if (rooted.reason === 'missing')\n throw new SkillInstallError('no-skill', `\"${source.subdir}\" is not a directory in ${source.owner}/${source.repo}.`)\n throw new SkillInstallError('invalid-source', `Subdirectory \"${source.subdir}\" escapes the repository root${rooted.reason === 'escape-symlink' ? ' through a symlink' : ''}.`)\n }\n candidateRoot = rooted.dir\n fallbackName = basename(resolve(fetchedInto, source.subdir))\n }\n\n const candidates = listSkillCandidates(candidateRoot, fallbackName)\n if (candidates.length === 0)\n throw new SkillInstallError('no-skill', `No skill found in ${opts.source} — no SKILL.md anywhere in the tree (searched ${CANDIDATE_WALK_MAX_DEPTH} levels deep).`)\n let picked: SkillInstallCandidate\n if (skillSelector) {\n // Selector matches the skill name OR its root-relative path — the\n // path form disambiguates same-named skills in different category\n // directories (`engineering/tdd` vs `personal/tdd`).\n const matches = candidates.filter(c => c.name === skillSelector || c.rel === skillSelector)\n if (matches.length === 0)\n throw new SkillInstallError('no-skill', `No skill named \"${skillSelector}\" in ${opts.source}. Available: ${describeCandidates(candidates)}`, candidates.map(c => c.rel))\n if (matches.length > 1)\n throw new SkillInstallError('multiple-candidates', `\"${skillSelector}\" is ambiguous in ${opts.source} — pick a path: ${matches.map(c => c.rel).join(', ')}`, matches.map(c => c.rel))\n picked = matches[0] as SkillInstallCandidate\n }\n else if (candidates.length > 1) {\n throw new SkillInstallError('multiple-candidates', `${opts.source} contains ${candidates.length} skills — pick one: ${describeCandidates(candidates)}`, candidates.map(c => c.rel))\n }\n else {\n picked = candidates[0] as SkillInstallCandidate\n }\n\n // Frontmatter name wins over the directory-derived candidate name —\n // mirrors \"target folder is named from the VALIDATED definition\".\n const { name } = await validateSkillCandidate(picked)\n\n const root = scopeRoot(opts)\n const targetDir = join(root, name)\n const backupDir = `${targetDir}.zidane-backup`\n if (existsSync(targetDir) && !opts.overwrite)\n throw new SkillInstallError('exists', `Skill \"${name}\" is already installed at ${targetDir}. Overwrite to replace it.`)\n\n mkdirSync(root, { recursive: true })\n const hadPrevious = existsSync(targetDir)\n if (hadPrevious) {\n rmSync(backupDir, { recursive: true, force: true })\n renameSync(targetDir, backupDir)\n }\n try {\n // `dereference` materializes in-tree symlinked files so the install\n // has no dangling links once the stage is deleted.\n cpSync(picked.dir, targetDir, { recursive: true, dereference: true })\n writeProvenance(targetDir, { spec: opts.source, ...(skillSelector ? { skill: skillSelector } : {}), scope: opts.scope, provenance, installedAt: Date.now() })\n }\n catch (err) {\n rmSync(targetDir, { recursive: true, force: true })\n if (hadPrevious)\n renameSync(backupDir, targetDir)\n throw new SkillInstallError('io-failed', `Writing ${targetDir} failed: ${errorMessage(err)}`)\n }\n rmSync(backupDir, { recursive: true, force: true })\n\n return { installed: [name], dir: targetDir, engine: 'native', provenance }\n }\n finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Provenance sidecar — lets a future update flow replay the recorded spec. */\nexport const SKILL_PROVENANCE_FILE = '.zidane-install.json'\n\ninterface SkillProvenance {\n spec: string\n skill?: string\n scope: InstallScope\n provenance: string\n installedAt: number\n}\n\nfunction writeProvenance(dir: string, data: SkillProvenance): void {\n writeFileSync(join(dir, SKILL_PROVENANCE_FILE), `${JSON.stringify(data, null, 2)}\\n`)\n}\n\n/** Read a skill directory's install provenance, `null` for hand-authored skills. */\nexport function readSkillProvenance(dir: string): (SkillProvenance & { spec: string }) | null {\n try {\n const raw = JSON.parse(readFileSync(join(dir, SKILL_PROVENANCE_FILE), 'utf8')) as Partial<SkillProvenance>\n return typeof raw.spec === 'string' && raw.spec.length > 0 ? (raw as SkillProvenance) : null\n }\n catch {\n return null\n }\n}\n\n/**\n * Native-install target root: the `<prefix>/skills` flavor of the\n * project/user convention (`~/.zidane/skills`, `<gitRoot>/.zidane/skills`).\n * The `.agents/skills` siblings stay read-only for us — they belong to\n * the cross-agent ecosystem (and the skills.sh CLI writes there).\n */\nfunction scopeRoot(opts: SkillInstallOptions): string {\n const roots = projectUserPaths({\n subPath: 'skills',\n ...(opts.cwd ? { cwd: opts.cwd } : {}),\n ...(opts.home ? { home: opts.home } : {}),\n ...(opts.prefix ? { prefix: opts.prefix } : {}),\n })\n const root = roots.find(r => r.source === opts.scope && r.path.includes(`.${(opts.prefix ?? '.zidane').replace(/^\\./, '')}`))\n if (!root)\n throw new SkillInstallError('io-failed', `No ${opts.scope} skills root resolved.`)\n return root.path\n}\n\nfunction sanitizeName(raw: string): string {\n const cleaned = raw.toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '').replace(/-{2,}/g, '-')\n return cleaned.length > 0 ? cleaned : 'skill'\n}\n","import type { SkillConfig } from './types'\nimport { validateSkillForWrite } from './validate'\n\nexport {\n type ActivationVia,\n type ActiveSkill,\n createSkillActivationState,\n type DeactivationReason,\n type SkillActivationState,\n type SkillActivationStateOptions,\n} from './activation'\nexport {\n IMPLICITLY_ALLOWED_SKILL_TOOLS,\n installAllowedToolsGate,\n} from './allowed-tools'\nexport { buildCatalog } from './catalog'\nexport {\n discoverSkills,\n getDefaultScanPaths,\n inferSource,\n parseFrontmatter,\n parseSkillFile,\n} from './discovery'\nexport type { SourcedScanPath } from './discovery'\nexport {\n installSkillFromSpec,\n listSkillCandidates,\n parseSkillInstallSpec,\n readSkillProvenance,\n SKILL_PROVENANCE_FILE,\n SkillInstallError,\n} from './install'\nexport type {\n SkillInstallCandidate,\n SkillInstallErrorCode,\n SkillInstallOptions,\n SkillInstallResult,\n SkillInstallSpec,\n} from './install'\nexport { interpolateShellCommands, stripShellInterpolations } from './interpolate'\nexport type { InterpolateShellCommandsOptions } from './interpolate'\nexport { resolveSkills } from './resolve'\nexport type {\n ShellInterpolationApproval,\n SkillConfig,\n SkillDiagnostic,\n SkillResource,\n SkillsConfig,\n SkillSource,\n} from './types'\nexport {\n isToolAllowedByUnion,\n matchesAllowedTool,\n parseAllowedToolPattern,\n validateResourcePath,\n validateResourcePathReal,\n validateSkillForWrite,\n validateSkillName,\n} from './validate'\nexport type { SkillValidationIssue, SkillValidationResult } from './validate'\nexport { writeSkillsToDisk, writeSkillToDisk } from './writer'\n\n// ---------------------------------------------------------------------------\n// defineSkill helper\n// ---------------------------------------------------------------------------\n\n/**\n * Define an inline skill configuration.\n *\n * Strict-validates at author-time — throws if the config would be rejected by\n * `writeSkillToDisk` or the spec. Source defaults to `'inline'`.\n */\nexport function defineSkill(config: Omit<SkillConfig, 'source'> & { source?: SkillConfig['source'] }): SkillConfig {\n const normalized: SkillConfig = {\n ...config,\n source: config.source ?? 'inline',\n }\n const result = validateSkillForWrite(normalized)\n if (!result.valid) {\n const summary = result.errors.map(e => ` - [${e.code}] ${e.message}`).join('\\n')\n throw new Error(`Invalid skill \"${normalized.name}\":\\n${summary}`)\n }\n return normalized\n}\n"],"mappings":"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"}
|
package/dist/skills.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $s as SourcedScanPath, As as SkillValidationResult, Bs as interpolateShellCommands, Ds as writeSkillToDisk, Es as defineSkill, Fs as validateResourcePathReal, Gf as ShellInterpolationApproval, Gs as SkillInstallErrorCode, Hs as SKILL_PROVENANCE_FILE, Is as validateSkillForWrite, Jf as SkillResource, Js as SkillInstallSpec, Kf as SkillConfig, Ks as SkillInstallOptions, Ls as validateSkillName, Ms as matchesAllowedTool, Ns as parseAllowedToolPattern, Os as writeSkillsToDisk, Ps as validateResourcePath, Qs as readSkillProvenance, Rs as resolveSkills, Us as SkillInstallCandidate, Vs as stripShellInterpolations, Ws as SkillInstallError, Xf as SkillsConfig, Xs as listSkillCandidates, Yf as SkillSource, Ys as installSkillFromSpec, Zs as parseSkillInstallSpec, ac as buildCatalog, cc as ActivationVia, dc as SkillActivationState, ec as discoverSkills, fc as SkillActivationStateOptions, ic as parseSkillFile, js as isToolAllowedByUnion, ks as SkillValidationIssue, lc as ActiveSkill, nc as inferSource, oc as IMPLICITLY_ALLOWED_SKILL_TOOLS, pc as createSkillActivationState, qf as SkillDiagnostic, qs as SkillInstallResult, rc as parseFrontmatter, sc as installAllowedToolsGate, tc as getDefaultScanPaths, uc as DeactivationReason, zs as InterpolateShellCommandsOptions } from "./index-
|
|
1
|
+
import { $s as SourcedScanPath, As as SkillValidationResult, Bs as interpolateShellCommands, Ds as writeSkillToDisk, Es as defineSkill, Fs as validateResourcePathReal, Gf as ShellInterpolationApproval, Gs as SkillInstallErrorCode, Hs as SKILL_PROVENANCE_FILE, Is as validateSkillForWrite, Jf as SkillResource, Js as SkillInstallSpec, Kf as SkillConfig, Ks as SkillInstallOptions, Ls as validateSkillName, Ms as matchesAllowedTool, Ns as parseAllowedToolPattern, Os as writeSkillsToDisk, Ps as validateResourcePath, Qs as readSkillProvenance, Rs as resolveSkills, Us as SkillInstallCandidate, Vs as stripShellInterpolations, Ws as SkillInstallError, Xf as SkillsConfig, Xs as listSkillCandidates, Yf as SkillSource, Ys as installSkillFromSpec, Zs as parseSkillInstallSpec, ac as buildCatalog, cc as ActivationVia, dc as SkillActivationState, ec as discoverSkills, fc as SkillActivationStateOptions, ic as parseSkillFile, js as isToolAllowedByUnion, ks as SkillValidationIssue, lc as ActiveSkill, nc as inferSource, oc as IMPLICITLY_ALLOWED_SKILL_TOOLS, pc as createSkillActivationState, qf as SkillDiagnostic, qs as SkillInstallResult, rc as parseFrontmatter, sc as installAllowedToolsGate, tc as getDefaultScanPaths, uc as DeactivationReason, zs as InterpolateShellCommandsOptions } from "./index-X02SI0nt.js";
|
|
2
2
|
export { type ActivationVia, type ActiveSkill, type DeactivationReason, IMPLICITLY_ALLOWED_SKILL_TOOLS, type InterpolateShellCommandsOptions, SKILL_PROVENANCE_FILE, type ShellInterpolationApproval, type SkillActivationState, type SkillActivationStateOptions, type SkillConfig, type SkillDiagnostic, type SkillInstallCandidate, SkillInstallError, type SkillInstallErrorCode, type SkillInstallOptions, type SkillInstallResult, type SkillInstallSpec, type SkillResource, type SkillSource, type SkillValidationIssue, type SkillValidationResult, type SkillsConfig, type SourcedScanPath, buildCatalog, createSkillActivationState, defineSkill, discoverSkills, getDefaultScanPaths, inferSource, installAllowedToolsGate, installSkillFromSpec, interpolateShellCommands, isToolAllowedByUnion, listSkillCandidates, matchesAllowedTool, parseAllowedToolPattern, parseFrontmatter, parseSkillFile, parseSkillInstallSpec, readSkillProvenance, resolveSkills, stripShellInterpolations, validateResourcePath, validateResourcePathReal, validateSkillForWrite, validateSkillName, writeSkillToDisk, writeSkillsToDisk };
|
package/dist/skills.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as validateSkillName, C as stripShellInterpolations, D as validateResourcePath, E as parseAllowedToolPattern, O as validateResourcePathReal, S as interpolateShellCommands, T as matchesAllowedTool, a as getDefaultScanPaths, c as parseSkillFile, d as installAllowedToolsGate, f as createSkillActivationState, i as discoverSkills, k as validateSkillForWrite, l as buildCatalog, n as writeSkillToDisk, o as inferSource, r as writeSkillsToDisk, s as parseFrontmatter, t as resolveSkills, u as IMPLICITLY_ALLOWED_SKILL_TOOLS, w as isToolAllowedByUnion } from "./resolve-
|
|
2
|
-
import { a as listSkillCandidates, i as installSkillFromSpec, n as SKILL_PROVENANCE_FILE, o as parseSkillInstallSpec, r as SkillInstallError, s as readSkillProvenance, t as defineSkill } from "./skills-
|
|
1
|
+
import { A as validateSkillName, C as stripShellInterpolations, D as validateResourcePath, E as parseAllowedToolPattern, O as validateResourcePathReal, S as interpolateShellCommands, T as matchesAllowedTool, a as getDefaultScanPaths, c as parseSkillFile, d as installAllowedToolsGate, f as createSkillActivationState, i as discoverSkills, k as validateSkillForWrite, l as buildCatalog, n as writeSkillToDisk, o as inferSource, r as writeSkillsToDisk, s as parseFrontmatter, t as resolveSkills, u as IMPLICITLY_ALLOWED_SKILL_TOOLS, w as isToolAllowedByUnion } from "./resolve-HtxmBWs9.js";
|
|
2
|
+
import { a as listSkillCandidates, i as installSkillFromSpec, n as SKILL_PROVENANCE_FILE, o as parseSkillInstallSpec, r as SkillInstallError, s as readSkillProvenance, t as defineSkill } from "./skills-BlmY7QhV.js";
|
|
3
3
|
export { IMPLICITLY_ALLOWED_SKILL_TOOLS, SKILL_PROVENANCE_FILE, SkillInstallError, buildCatalog, createSkillActivationState, defineSkill, discoverSkills, getDefaultScanPaths, inferSource, installAllowedToolsGate, installSkillFromSpec, interpolateShellCommands, isToolAllowedByUnion, listSkillCandidates, matchesAllowedTool, parseAllowedToolPattern, parseFrontmatter, parseSkillFile, parseSkillInstallSpec, readSkillProvenance, resolveSkills, stripShellInterpolations, validateResourcePath, validateResourcePathReal, validateSkillForWrite, validateSkillName, writeSkillToDisk, writeSkillsToDisk };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bu as ProviderKey, Du as StreamEvent, Eu as Settings, Wu as ModelInfo, zu as ProviderAuth } from "./index-
|
|
1
|
+
import { Bu as ProviderKey, Du as StreamEvent, Eu as Settings, Wu as ModelInfo, zu as ProviderAuth } from "./index-X02SI0nt.js";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/chat/turn-selection.d.ts
|
|
@@ -432,4 +432,4 @@ declare function displayNameFor(name: string, input?: Record<string, unknown>):
|
|
|
432
432
|
declare function formatToolCall(name: string, input: Record<string, unknown>): ToolFormatLine | null;
|
|
433
433
|
//#endregion
|
|
434
434
|
export { turnSelectionOwnership as A, useSafeModeActions as C, isTurnHighlighted as D, isEditErrorResult as E, isVisible as O, SafeModeProvider as S, EDIT_TOOL_NAMES as T, splitMarkdownCodeBlocks as _, formatToolCall as a, RequestApproval as b, splitPromptSegments as c, filterModelCatalog as d, indexOfEntry as f, normalizeMarkdownCodeFences as g, chunkMarkdownForRender as h, displayNameFor as i, selectableTurnIds as k, CatalogEntry as l, MarkdownSegment as m, ToolDisplayMeta as n, PromptSegment as o, MARKDOWN_RENDER_CHUNK_TARGET_BYTES as p, ToolFormatLine as r, PromptSegmentRef as s, TOOL_DISPLAY as t, buildModelCatalog as u, ApprovalDecision as v, useSafeModeQueue as w, SafeModeActions as x, ApprovalRequest as y };
|
|
435
|
-
//# sourceMappingURL=tool-formatters-
|
|
435
|
+
//# sourceMappingURL=tool-formatters-kg8O6wHZ.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-formatters-
|
|
1
|
+
{"version":3,"file":"tool-formatters-kg8O6wHZ.d.ts","names":[],"sources":["../src/chat/turn-selection.ts","../src/chat/safe-mode-context.tsx","../src/chat/markdown-segments.ts","../src/chat/model-catalog.ts","../src/chat/prompt-segments.ts","../src/chat/tool-formatters.ts"],"mappings":"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"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $n as waitTask, Bf as hashContent, Cr as glob, Cs as createModelSearchTool, Ff as ToolMap, Hf as hydrateReadStateFromSessionAsync, If as HydrateReadStateOptions, Lf as ReadStateEntry, Nf as ToolContext, Pf as ToolDef, Qn as WAIT_TASK_TIMED_OUT_PREFIX, Rf as ReadStateMap, Sr as grep, Ss as SpawnModelEntry, Ts as matchModelEntries, Uf as readStateKey, Vf as hydrateReadStateFromSession, Wf as resolveReadStateMap, Zn as writeFile, _r as readFile, _s as SubagentDef, ar as ToolSearchToolOptions, br as InteractionToolOptions, bs as createSpawnTool, cr as createSkillsUseTool, dr as SkillsReadToolOptions, ds as ExtensionSubagentDef, er as ValidationResult, fr as createSkillsReadTool, fs as SpawnTaskInput, gr as shell, gs as SpawnToolState, hr as createShellTool, hs as SpawnToolOptions, ir as LazyToolEntry, lr as SkillsRunScriptToolOptions, mr as CreateShellToolOptions, ms as SpawnTool, nr as TailTruncateOptions, or as createToolSearchTool, pr as shellKill, ps as SpawnTaskOutcome, rr as tailTruncate, sr as SkillsUseToolOptions, tr as validateToolArgs, ur as createSkillsRunScriptTool, us as ChildAgent, vr as multiEdit, vs as SubagentOverride, wr as edit, ws as formatModelLine, xr as createInteractionTool, xs as isSpawnTool, yr as listFiles, ys as SubagentRegistry, zf as getReadState } from "./index-
|
|
1
|
+
import { $n as waitTask, Bf as hashContent, Cr as glob, Cs as createModelSearchTool, Ff as ToolMap, Hf as hydrateReadStateFromSessionAsync, If as HydrateReadStateOptions, Lf as ReadStateEntry, Nf as ToolContext, Pf as ToolDef, Qn as WAIT_TASK_TIMED_OUT_PREFIX, Rf as ReadStateMap, Sr as grep, Ss as SpawnModelEntry, Ts as matchModelEntries, Uf as readStateKey, Vf as hydrateReadStateFromSession, Wf as resolveReadStateMap, Zn as writeFile, _r as readFile, _s as SubagentDef, ar as ToolSearchToolOptions, br as InteractionToolOptions, bs as createSpawnTool, cr as createSkillsUseTool, dr as SkillsReadToolOptions, ds as ExtensionSubagentDef, er as ValidationResult, fr as createSkillsReadTool, fs as SpawnTaskInput, gr as shell, gs as SpawnToolState, hr as createShellTool, hs as SpawnToolOptions, ir as LazyToolEntry, lr as SkillsRunScriptToolOptions, mr as CreateShellToolOptions, ms as SpawnTool, nr as TailTruncateOptions, or as createToolSearchTool, pr as shellKill, ps as SpawnTaskOutcome, rr as tailTruncate, sr as SkillsUseToolOptions, tr as validateToolArgs, ur as createSkillsRunScriptTool, us as ChildAgent, vr as multiEdit, vs as SubagentOverride, wr as edit, ws as formatModelLine, xr as createInteractionTool, xs as isSpawnTool, yr as listFiles, ys as SubagentRegistry, zf as getReadState } from "./index-X02SI0nt.js";
|
|
2
2
|
export { type ChildAgent, type CreateShellToolOptions, type ExtensionSubagentDef, type HydrateReadStateOptions, type InteractionToolOptions, type LazyToolEntry, type ReadStateEntry, type ReadStateMap, type SkillsReadToolOptions, type SkillsRunScriptToolOptions, type SkillsUseToolOptions, type SpawnModelEntry, type SpawnTaskInput, type SpawnTaskOutcome, type SpawnTool, type SpawnToolOptions, type SpawnToolState, type SubagentDef, type SubagentOverride, type SubagentRegistry, type TailTruncateOptions, type ToolContext, type ToolDef, type ToolMap, type ToolSearchToolOptions, type ValidationResult, WAIT_TASK_TIMED_OUT_PREFIX, createInteractionTool, createModelSearchTool, createShellTool, createSkillsReadTool, createSkillsRunScriptTool, createSkillsUseTool, createSpawnTool, createToolSearchTool, edit, formatModelLine, getReadState, glob, grep, hashContent, hydrateReadStateFromSession, hydrateReadStateFromSessionAsync, isSpawnTool, listFiles, matchModelEntries, multiEdit, readFile, readStateKey, resolveReadStateMap, shell, shellKill, tailTruncate, validateToolArgs, waitTask, writeFile };
|
package/dist/tools.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { a as hydrateReadStateFromSessionAsync, c as resolveReadStateMap, i as hydrateReadStateFromSession, r as hashContent, s as readStateKey, t as getReadState } from "./read-state-Dq_TXUX1.js";
|
|
2
|
-
import { At as createInteractionTool, Ct as readFile, Dt as formatModelLine, Et as createModelSearchTool, Mt as glob, Nt as edit, Ot as matchModelEntries, Pt as validateToolArgs, St as tailTruncate, Tt as multiEdit, _t as createSkillsRunScriptTool, bt as createShellTool, dt as WAIT_TASK_TIMED_OUT_PREFIX, ft as waitTask, gt as createSkillsUseTool, ht as isSpawnTool, jt as grep, kt as listFiles, mt as createSpawnTool, pt as createToolSearchTool, ut as writeFile, vt as createSkillsReadTool, xt as shell, yt as shellKill } from "./agent-
|
|
2
|
+
import { At as createInteractionTool, Ct as readFile, Dt as formatModelLine, Et as createModelSearchTool, Mt as glob, Nt as edit, Ot as matchModelEntries, Pt as validateToolArgs, St as tailTruncate, Tt as multiEdit, _t as createSkillsRunScriptTool, bt as createShellTool, dt as WAIT_TASK_TIMED_OUT_PREFIX, ft as waitTask, gt as createSkillsUseTool, ht as isSpawnTool, jt as grep, kt as listFiles, mt as createSpawnTool, pt as createToolSearchTool, ut as writeFile, vt as createSkillsReadTool, xt as shell, yt as shellKill } from "./agent-CZ3WSWqR.js";
|
|
3
3
|
export { WAIT_TASK_TIMED_OUT_PREFIX, createInteractionTool, createModelSearchTool, createShellTool, createSkillsReadTool, createSkillsRunScriptTool, createSkillsUseTool, createSpawnTool, createToolSearchTool, edit, formatModelLine, getReadState, glob, grep, hashContent, hydrateReadStateFromSession, hydrateReadStateFromSessionAsync, isSpawnTool, listFiles, matchModelEntries, multiEdit, readFile, readStateKey, resolveReadStateMap, shell, shellKill, tailTruncate, validateToolArgs, waitTask, writeFile };
|