skilld-harness 3.2.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -5
- package/dist/_chunks/skills.mjs +35 -18
- package/dist/_chunks/skills.mjs.map +1 -1
- package/dist/index.d.mts +56 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +226 -57
- package/dist/index.mjs.map +1 -1
- package/dist/sandbox-local.d.mts +11 -3
- package/dist/sandbox-local.d.mts.map +1 -1
- package/dist/sandbox-local.mjs +50 -7
- package/dist/sandbox-local.mjs.map +1 -1
- package/dist/skills/generate-package-skill/SKILL.md +116 -63
- package/dist/skills/generate-package-skill/assets/harness-request.md +3 -0
- package/dist/skills/generate-package-skill/scripts/serve-fixture.mjs +233 -0
- package/dist/skills/generate-project-skill/SKILL.md +1 -0
- package/dist/skills/review-skill/SKILL.md +4 -2
- package/dist/skills/skilld/SKILL.md +91 -2
- package/dist/skills.d.mts +8 -3
- package/dist/skills.d.mts.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["invalid","invalid","unavailable"],"sources":["../src/internal/result.ts","../src/internal/input.ts","../src/internal/output/collect.ts","../src/internal/output/promote.ts","../src/internal/output/project.ts","../src/internal/output/validate.ts","../src/internal/source/host.ts","../src/internal/source/archive.ts","../src/internal/source/npm.ts","../src/harness.ts"],"sourcesContent":["export type Result<T, E>\n = | { readonly _tag: 'Ok', readonly value: T }\n | { readonly _tag: 'Err', readonly error: E }\n\nexport const ok = <T>(value: T): Result<T, never> => ({ _tag: 'Ok', value })\nexport const err = <E>(error: E): Result<never, E> => ({ _tag: 'Err', error })\n","import type { SkillOutputPolicy, SkillRun, SkillRunError } from '../types.ts'\nimport type { Result } from './result.ts'\nimport { resolve } from 'node:path'\nimport { isSkillName, resolveWithin } from './paths.ts'\nimport { err, ok } from './result.ts'\n\nfunction invalid(message: string): Result<never, SkillRunError> {\n return err({ _tag: 'InvalidInput', message })\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nexport function parseSkillRun(input: SkillRun): Result<SkillRun, SkillRunError> {\n if (!input || typeof input !== 'object' || !('_tag' in input))\n return invalid('Skill run input must be an object with a tag.')\n\n if (input._tag === 'PackageSkill') {\n if (!input.source || !input.destination)\n return invalid('Package Skill input is incomplete.')\n if (!isNonEmptyString(input.destination.rootDir) || !isSkillName(input.destination.name))\n return invalid('Package Skill destination is invalid.')\n if (input.source._tag === 'NpmPackage') {\n if (!isNonEmptyString(input.source.spec))\n return invalid('npm package spec is required.')\n return ok({\n _tag: 'PackageSkill',\n source: { _tag: 'NpmPackage', spec: input.source.spec },\n destination: { rootDir: resolve(input.destination.rootDir), name: input.destination.name },\n })\n }\n if (input.source._tag === 'LocalPackage') {\n if (!isNonEmptyString(input.source.rootDir) || !isNonEmptyString(input.source.packageDir))\n return invalid('Local package paths are required.')\n if (resolveWithin(input.source.rootDir, input.source.packageDir) === null)\n return invalid('Local package directory must stay inside its root directory.')\n return ok({\n _tag: 'PackageSkill',\n source: {\n _tag: 'LocalPackage',\n rootDir: resolve(input.source.rootDir),\n packageDir: input.source.packageDir,\n },\n destination: { rootDir: resolve(input.destination.rootDir), name: input.destination.name },\n })\n }\n return invalid('Package source tag is invalid.')\n }\n\n if (input._tag === 'ProjectSkill') {\n if (!isNonEmptyString(input.projectDir) || !input.destination)\n return invalid('Project Skill input is incomplete.')\n if (!isNonEmptyString(input.destination.rootDir) || !isSkillName(input.destination.name))\n return invalid('Project Skill destination is invalid.')\n return ok({\n _tag: 'ProjectSkill',\n projectDir: resolve(input.projectDir),\n destination: { rootDir: resolve(input.destination.rootDir), name: input.destination.name },\n })\n }\n\n if (input._tag === 'ReviewSkill') {\n if (!isNonEmptyString(input.skillDir))\n return invalid('Skill review directory is required.')\n return ok({ _tag: 'ReviewSkill', skillDir: resolve(input.skillDir) })\n }\n\n return invalid('Skill run tag is invalid.')\n}\n\nexport function parseOutputPolicy(policy: SkillOutputPolicy): SkillOutputPolicy {\n for (const [name, value] of Object.entries(policy)) {\n if (!Number.isSafeInteger(value) || value <= 0)\n throw new TypeError(`${name} must be a positive integer.`)\n }\n return Object.freeze(policy)\n}\n","import type { SkillOutputPolicy, SkillRunError } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { HarnessAgentSandboxConfig } from '@ai-sdk/harness/agent'\nimport { normalizeOutputPath } from '../paths.ts'\nimport { err, ok } from '../result.ts'\n\nexport type SandboxSession = Parameters<NonNullable<HarnessAgentSandboxConfig['onSession']>>[0]['session']\n\nexport interface CollectedFile {\n readonly path: string\n readonly content: Uint8Array\n}\n\nconst invalid = (message: string, issues: ReadonlyArray<string>): Result<never, SkillRunError> =>\n err({ _tag: 'InvalidSkill', message, issues })\n\nconst inventory = async (\n sandbox: SandboxSession,\n outputDir: string,\n signal?: AbortSignal,\n): Promise<Result<ReadonlyArray<{ type: string, path: string, size: number }>, SkillRunError>> => {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n const command = 'find -P \"$SKILLD_OUTPUT\" -mindepth 1 -printf \\'%y\\\\0%P\\\\0%s\\\\0\\''\n const result = await Promise.resolve().then(() => sandbox.run({\n command,\n env: { LC_ALL: 'C', SKILLD_OUTPUT: outputDir },\n abortSignal: signal,\n })).catch(error => error as Error)\n if (result instanceof Error)\n return invalid('Harness output cannot be inspected.', [result.message])\n if (result.exitCode !== 0)\n return invalid('Harness output directory is missing.', [result.stderr.trim() || 'No output directory.'])\n\n const fields = result.stdout.split('\\0')\n if (fields.at(-1) === '')\n fields.pop()\n if (fields.length % 3 !== 0)\n return invalid('Harness output inventory is invalid.', ['File inventory has an incomplete entry.'])\n\n const entries: Array<{ type: string, path: string, size: number }> = []\n for (let index = 0; index < fields.length; index += 3) {\n const type = fields[index]\n const path = fields[index + 1]\n const size = Number(fields[index + 2])\n if (!type || !path || !Number.isSafeInteger(size) || size < 0)\n return invalid('Harness output inventory is invalid.', ['File inventory has invalid fields.'])\n entries.push({ type, path, size })\n }\n return ok(entries)\n}\n\nexport const collectSandboxOutput = async (\n sandbox: SandboxSession,\n outputDir: string,\n policy: SkillOutputPolicy,\n signal?: AbortSignal,\n): Promise<Result<ReadonlyArray<CollectedFile>, SkillRunError>> => {\n const before = await inventory(sandbox, outputDir, signal)\n if (before._tag === 'Err')\n return before\n\n const files: CollectedFile[] = []\n const seen = new Set<string>()\n let totalBytes = 0\n for (const entry of before.value) {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n const path = normalizeOutputPath(entry.path)\n if (path === null)\n return invalid('Harness output contains an invalid path.', [entry.path])\n if (entry.type === 'd')\n continue\n if (entry.type !== 'f')\n return invalid('Harness output contains a linked or special entry.', [path])\n if (seen.has(path))\n return invalid('Harness output contains duplicate paths.', [path])\n if (files.length >= policy.maxOutputFiles)\n return invalid('Harness output contains too many files.', [`Limit: ${policy.maxOutputFiles}`])\n if (entry.size > policy.maxOutputFileBytes)\n return invalid('Harness output contains an oversized file.', [path])\n if (totalBytes + entry.size > policy.maxOutputBytes)\n return invalid('Harness output exceeds the total byte limit.', [`Limit: ${policy.maxOutputBytes}`])\n\n const content = await Promise.resolve().then(() => sandbox.readBinaryFile({ path: `${outputDir}/${path}`, abortSignal: signal })).catch(error => error as Error)\n if (content instanceof Error) {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n return invalid('Harness output cannot be read.', [path, content.message])\n }\n if (content === null || content.byteLength !== entry.size)\n return invalid('Harness output changed during collection.', [path])\n seen.add(path)\n files.push({ path, content: Uint8Array.from(content) })\n totalBytes += content.byteLength\n }\n\n const after = await inventory(sandbox, outputDir, signal)\n if (after._tag === 'Err')\n return after\n if (JSON.stringify(before.value) !== JSON.stringify(after.value))\n return invalid('Harness output changed during collection.', ['File inventory changed.'])\n\n files.sort((left, right) => left.path.localeCompare(right.path))\n return ok(files)\n}\n","import type { GeneratedSkill, SkillRunError, SourceAttempt } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { CollectedFile } from './collect.ts'\nimport { randomUUID } from 'node:crypto'\nimport { lstat, mkdir, open, realpath, rename, rm, rmdir, unlink, writeFile } from 'node:fs/promises'\nimport { dirname, join, resolve } from 'node:path'\nimport { err, ok } from '../result.ts'\n\nfunction pathError(message: string, path: string): Result<never, SkillRunError> {\n return err({ _tag: 'UnsafeOutputPath', message, path })\n}\n\nconst missing = Symbol('missing')\n\nasync function statOrMissing(path: string) {\n return lstat(path).catch(error => (error as NodeJS.ErrnoException).code === 'ENOENT' ? missing : Promise.reject(error))\n}\n\nexport const promoteSkill = async (\n rootDir: string,\n name: string,\n files: ReadonlyArray<CollectedFile>,\n attempts: ReadonlyArray<SourceAttempt>,\n): Promise<Result<GeneratedSkill, SkillRunError>> => {\n const root = resolve(rootDir)\n let rootStat = await statOrMissing(root).catch(error => error as Error)\n if (rootStat instanceof Error)\n return pathError('Output root cannot be inspected.', root)\n let createdRoot = false\n if (rootStat === missing) {\n const parent = dirname(root)\n const parentStat = await statOrMissing(parent).catch(error => error as Error)\n if (parentStat instanceof Error || parentStat === missing || !parentStat.isDirectory() || parentStat.isSymbolicLink())\n return pathError('Output root parent must be an existing directory.', parent)\n const canonicalParent = await realpath(parent).catch(error => error as Error)\n if (canonicalParent instanceof Error || canonicalParent !== parent)\n return pathError('Output root parent must not pass through a symbolic link.', parent)\n const created = await mkdir(root, { mode: 0o700 }).then(() => true, error => error as NodeJS.ErrnoException)\n if (created instanceof Error && created.code !== 'EEXIST')\n return pathError('Output root cannot be created.', root)\n createdRoot = created === true\n rootStat = await statOrMissing(root).catch(error => error as Error)\n }\n if (rootStat instanceof Error || rootStat === missing || !rootStat.isDirectory() || rootStat.isSymbolicLink())\n return pathError('Output root must be a directory, not a symbolic link.', root)\n const canonicalRoot = await realpath(root).catch(error => error as Error)\n if (canonicalRoot instanceof Error)\n return pathError('Output root cannot be resolved.', root)\n if (canonicalRoot !== root)\n return pathError('Output root must not pass through a symbolic link.', root)\n\n const target = join(root, name)\n const targetStat = await statOrMissing(target).catch(error => error as Error)\n if (targetStat instanceof Error)\n return pathError('Output path cannot be inspected.', target)\n if (targetStat !== missing && (!targetStat.isDirectory() || targetStat.isSymbolicLink()))\n return pathError('Output path must be a directory, not a symbolic link.', target)\n\n const lockPath = join(root, `.skilld-${name}.lock`)\n const lock = await open(lockPath, 'wx').catch(error => error as NodeJS.ErrnoException)\n if (lock instanceof Error) {\n if (lock.code === 'EEXIST')\n return err({ _tag: 'OutputBusy', message: 'Another Skill run owns this output path.', path: target })\n return err({ _tag: 'PromotionFailed', message: 'Output lock could not be created.', path: target, cause: lock })\n }\n\n const nonce = randomUUID()\n const staging = join(root, `.skilld-${name}-${nonce}.next`)\n const backup = join(root, `.skilld-${name}-${nonce}.previous`)\n let movedCurrent = false\n let promoted = false\n let failureMessage = 'Skill output could not be promoted.'\n let failureCause: unknown\n\n try {\n await mkdir(staging, { mode: 0o700 })\n for (const file of files) {\n const destination = join(staging, file.path)\n await mkdir(dirname(destination), { recursive: true, mode: 0o700 })\n await writeFile(destination, file.content, { flag: 'wx', mode: 0o600 })\n }\n\n if (targetStat !== missing) {\n await rename(target, backup)\n movedCurrent = true\n }\n await rename(staging, target)\n promoted = true\n }\n catch (cause) {\n failureCause = cause\n if (movedCurrent && !promoted) {\n const current = await statOrMissing(target).catch(error => error as Error)\n if (current instanceof Error) {\n failureMessage = 'Skill output rollback could not inspect its destination.'\n failureCause = new AggregateError([cause, current])\n }\n if (current === missing) {\n const rollback = await rename(backup, target).catch(error => error as Error)\n if (rollback instanceof Error) {\n failureMessage = 'Skill output rollback failed.'\n failureCause = new AggregateError([cause, rollback])\n }\n }\n }\n }\n\n const lockCleanupErrors: unknown[] = []\n await lock.close().catch(error => lockCleanupErrors.push(error))\n await unlink(lockPath).catch(error => lockCleanupErrors.push(error))\n\n if (promoted) {\n const warnings: string[] = []\n if (lockCleanupErrors.length > 0) {\n const detail = lockCleanupErrors.map(error => error instanceof Error ? error.message : String(error)).join('; ')\n warnings.push(`Output lock cleanup failed at ${lockPath}: ${detail}`)\n }\n if (movedCurrent) {\n const backupCleanup = await rm(backup, { recursive: true }).catch(error => error as Error)\n if (backupCleanup instanceof Error)\n warnings.push(`Previous Skill cleanup failed at ${backup}: ${backupCleanup.message}`)\n }\n return ok({\n _tag: 'GeneratedSkill',\n name,\n outputDir: target,\n files: files.map(file => ({ path: file.path, bytes: file.content.byteLength })),\n sourceAttempts: attempts,\n warnings,\n })\n }\n\n const cleanupErrors = [...lockCleanupErrors]\n await rm(staging, { recursive: true, force: true }).catch(error => cleanupErrors.push(error))\n if (createdRoot)\n await rmdir(root).catch(error => cleanupErrors.push(error))\n const causes = failureCause === undefined ? cleanupErrors : [failureCause, ...cleanupErrors]\n const cause = causes.length <= 1 ? causes[0] : new AggregateError(causes, 'Skill output cleanup failed.')\n return err({ _tag: 'PromotionFailed', message: failureMessage, path: target, cause })\n}\n","/** A search command the Agent can repeat, matched on whole words. */\nconst searchCommand = /\\b(?:git grep|grep|rg)\\b/\n\n/** Inline code spans, which is where a Skill writes its file pointers. */\nconst inlineCode = /`([^`\\n]+)`/g\n\n/** Fenced blocks, which hold commands rather than pointers. */\nconst fencedBlock = /```[^\\n]*\\n[\\s\\S]*?```/g\n\n/**\n * A Skill may report a file the project lacks, such as a missing entry point.\n * A sentence that denies a path states a fact about the project, not a pointer.\n * A sentence that tells the Agent to create a file gives a task, not a pointer.\n * The check reads whole paragraphs, so a hard-wrapped denial still covers the\n * code spans in its own sentence.\n */\nconst denial = /\\b(no|not|none|never|absent|missing|lacks|without|instead|rather|empty|undeclared|unavailable|nothing)\\b|\\bdoes ?n[o']t\\b/i\n\nconst creation = /\\b(?:copy|create|write|generate)\\b/i\n\nfunction fencedBlocks(markdown: string): ReadonlyArray<string> {\n return markdown.match(fencedBlock) ?? []\n}\n\n/**\n * Prose paragraphs, with fenced commands removed so a command never reads as a\n * pointer. A soft-wrapped sentence keeps its words together: the lines of a\n * paragraph join before any check runs.\n */\nfunction proseParagraphs(markdown: string): ReadonlyArray<string> {\n return markdown\n .replace(fencedBlock, '')\n .split(/\\n[ \\t]*\\n/)\n .map(paragraph => paragraph.replace(/\\n/g, ' ').trim())\n .filter(paragraph => paragraph.length > 0)\n}\n\n/**\n * Extensions a real file pointer carries. A token ending elsewhere, such as\n * the `.0` in a version, carries no path shape.\n */\nconst pathExtension = /\\.(?:md|mdx|json|jsonc|ts|tsx|mts|cts|js|mjs|cjs|jsx|vue|svelte|txt|yml|yaml|toml|html|css|scss|rs|py|go|sh|lock|env|csv|xml)$/i\n\n/** A release number such as `20.19.0` or `v20` states a version, never a path. */\nconst versionShape = /^v?\\d+(?:\\.\\d+)*$/i\n\n/** A product name such as `Node.js` or `node.js` names a tool, never a file. */\nconst productName = /^[A-Za-z][A-Za-z0-9_]*\\.[A-Za-z0-9]+$/\n\n/**\n * A token counts as a file pointer only when it cannot be anything else.\n * A false pointer fails a correct Skill, so every rule here excludes rather than includes.\n */\nfunction pathCandidate(token: string): string | null {\n if (token.length === 0 || /\\s/.test(token))\n return null\n // A flag, a variable, a comment, or a placeholder is never a pointer.\n if (/^[-$#<{[]/.test(token))\n return null\n // A URL, a package specifier, or a shell construct is never a pointer.\n if (token.includes('://') || /[()|;&\"'@:]/.test(token))\n return null\n const trimmed = token.replace(/^\\.\\//, '').replace(/\\/+$/, '')\n if (trimmed.length === 0 || trimmed.startsWith('..'))\n return null\n // A version, a product name, or a numbered reference such as `HTTP/2` is never a pointer.\n if (versionShape.test(trimmed) || productName.test(trimmed) || /\\/\\d+$/.test(trimmed))\n return null\n // A pointer carries a slash-qualified path or a known file extension.\n if (!trimmed.includes('/') && !pathExtension.test(trimmed))\n return null\n return trimmed\n}\n\n/** The literal prefix of a glob, which is the part a real path must start with. */\nfunction literalPrefix(candidate: string): string {\n const wildcard = candidate.search(/[*?]/)\n if (wildcard === -1)\n return candidate\n const cut = candidate.slice(0, wildcard).replace(/[^/]*$/, '')\n return cut.replace(/\\/+$/, '')\n}\n\nfunction resolves(candidate: string, known: ReadonlySet<string>): boolean {\n if (known.has(candidate))\n return true\n const prefix = literalPrefix(candidate)\n if (prefix.length === 0)\n return true\n for (const path of known) {\n // A known template such as `.env.example` implies the file it is copied to.\n if (path.startsWith(`${candidate}.`))\n return true\n // A directory pointer resolves when the project holds a file under it.\n if (path === prefix || path.startsWith(`${prefix}/`))\n return true\n }\n return false\n}\n\nexport interface ProjectSkillInput {\n /** The generated SKILL.md text. */\n readonly markdown: string\n /** Project-relative paths the Harness prepared for the Agent. */\n readonly projectPaths: ReadonlyArray<string>\n /** Output-relative paths the Skill writes beside SKILL.md. */\n readonly outputPaths: ReadonlyArray<string>\n}\n\n/**\n * Check that a project Skill points at files the project contains and gives a\n * search the Agent can repeat. The Agent cannot verify its own pointers.\n *\n * The Harness hides generated directories from the Agent, so a pointer at one is\n * invention like any other. A sentence that states a path is missing, or that\n * tells the Agent to create one, passes: it reports a fact or gives a task, not\n * a pointer. The sentence may wrap across prose lines within its paragraph.\n */\nexport function checkProjectSkill(input: ProjectSkillInput): ReadonlyArray<string> {\n const issues: string[] = []\n const known = new Set([...input.projectPaths, ...input.outputPaths])\n const unknown = new Set<string>()\n\n for (const paragraph of proseParagraphs(input.markdown)) {\n if (denial.test(paragraph) || creation.test(paragraph))\n continue\n for (const match of paragraph.matchAll(inlineCode)) {\n const candidate = pathCandidate(match[1]!.trim())\n if (candidate !== null && !resolves(candidate, known))\n unknown.add(candidate)\n }\n }\n\n for (const path of [...unknown].sort())\n issues.push(`SKILL.md points at a path the project does not contain: ${path}.`)\n\n const inline = [...input.markdown.matchAll(inlineCode)].map(match => match[1]!)\n const commands = [...fencedBlocks(input.markdown), ...inline].join('\\n')\n if (!searchCommand.test(commands))\n issues.push('SKILL.md must give the Agent at least one search command it can repeat.')\n\n return issues\n}\n","import type { SkillReview, SkillReviewFinding, SkillRunError } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { CollectedFile } from './collect.ts'\nimport { parseDocument } from 'yaml'\nimport { isSkillName, normalizeOutputPath } from '../paths.ts'\nimport { checkProjectSkill } from './project.ts'\nimport { err, ok } from '../result.ts'\n\nconst allowedFrontmatter = new Set([\n 'name',\n 'description',\n 'license',\n 'compatibility',\n 'metadata',\n 'allowed-tools',\n])\n\nconst invalid = (issues: ReadonlyArray<string>): Result<never, SkillRunError> =>\n err({ _tag: 'InvalidSkill', message: 'Skill output failed deterministic checks.', issues })\n\nfunction decodeText(content: Uint8Array): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(content)\n }\n catch {\n return null\n }\n}\n\nconst isStringMap = (value: unknown): boolean =>\n value !== null\n && typeof value === 'object'\n && !Array.isArray(value)\n && Object.values(value).every(item => typeof item === 'string')\n\nexport const validateGeneratedSkill = (\n name: string,\n files: ReadonlyArray<CollectedFile>,\n project?: ReadonlyArray<string>,\n): Result<void, SkillRunError> => {\n const issues: string[] = []\n const skillFiles = files.filter(file => file.path === 'SKILL.md')\n if (skillFiles.length !== 1)\n return invalid(['Output must contain exactly one SKILL.md file.'])\n\n const source = decodeText(skillFiles[0]!.content)\n if (source === null)\n return invalid(['SKILL.md must contain valid UTF-8 text.'])\n if (project !== undefined) {\n issues.push(...checkProjectSkill({\n markdown: source,\n projectPaths: project,\n outputPaths: files.map(file => file.path),\n }))\n }\n const match = source.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n([\\s\\S]*)$/)\n if (!match)\n return invalid(['SKILL.md must start with YAML frontmatter.'])\n if (match[2]?.trim().length === 0)\n issues.push('SKILL.md instructions must not be empty.')\n\n const document = parseDocument(match[1]!, { uniqueKeys: true })\n for (const error of document.errors)\n issues.push(`Frontmatter: ${error.message}`)\n for (const warning of document.warnings)\n issues.push(`Frontmatter: ${warning.message}`)\n\n const value = document.errors.length === 0 ? document.toJS() as unknown : null\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n issues.push('Frontmatter must be a mapping.')\n return invalid(issues)\n }\n\n const frontmatter = value as Record<string, unknown>\n for (const key of Object.keys(frontmatter)) {\n if (!allowedFrontmatter.has(key))\n issues.push(`Frontmatter field is not supported: ${key}`)\n }\n if (frontmatter.name !== name)\n issues.push('Frontmatter name must match the Skill directory name.')\n if (typeof frontmatter.name !== 'string' || !isSkillName(frontmatter.name))\n issues.push('Frontmatter name is invalid.')\n if (typeof frontmatter.description !== 'string' || frontmatter.description.trim().length === 0 || frontmatter.description.length > 1024)\n issues.push('Frontmatter description must contain 1 to 1024 characters.')\n if (frontmatter.license !== undefined && typeof frontmatter.license !== 'string')\n issues.push('Frontmatter license must be a string.')\n if (frontmatter.compatibility !== undefined && (typeof frontmatter.compatibility !== 'string' || frontmatter.compatibility.length > 500))\n issues.push('Frontmatter compatibility must be a string of at most 500 characters.')\n if (frontmatter.metadata !== undefined && !isStringMap(frontmatter.metadata))\n issues.push('Frontmatter metadata must map strings to strings.')\n if (frontmatter['allowed-tools'] !== undefined && typeof frontmatter['allowed-tools'] !== 'string')\n issues.push('Frontmatter allowed-tools must be a string.')\n\n return issues.length === 0 ? ok(undefined) : invalid(issues)\n}\n\nconst findingLevels = new Set(['error', 'warning', 'note'])\n\nexport const validateSkillReview = (\n files: ReadonlyArray<CollectedFile>,\n): Result<SkillReview, SkillRunError> => {\n if (files.length !== 1 || files[0]?.path !== 'review.json')\n return invalid(['Review output must contain only review.json.'])\n\n let value: unknown\n try {\n const source = decodeText(files[0].content)\n if (source === null)\n return invalid(['review.json must contain valid UTF-8 text.'])\n value = JSON.parse(source)\n }\n catch {\n return invalid(['review.json must contain valid JSON.'])\n }\n if (!value || typeof value !== 'object' || Array.isArray(value))\n return invalid(['review.json must contain an object.'])\n\n const review = value as Record<string, unknown>\n if (Object.keys(review).some(key => key !== 'summary' && key !== 'findings'))\n return invalid(['review.json contains unsupported fields.'])\n if (typeof review.summary !== 'string' || review.summary.trim().length === 0)\n return invalid(['Review summary is required.'])\n if (!Array.isArray(review.findings))\n return invalid(['Review findings must be an array.'])\n\n const findings: SkillReviewFinding[] = []\n for (const item of review.findings) {\n if (!item || typeof item !== 'object' || Array.isArray(item))\n return invalid(['Each review finding must be an object.'])\n const finding = item as Record<string, unknown>\n if (Object.keys(finding).some(key => !['level', 'path', 'message', 'fix'].includes(key)))\n return invalid(['A review finding contains unsupported fields.'])\n if (typeof finding.level !== 'string' || !findingLevels.has(finding.level))\n return invalid(['A review finding level is invalid.'])\n if (typeof finding.path !== 'string' || normalizeOutputPath(finding.path) === null)\n return invalid(['A review finding path is invalid.'])\n if (typeof finding.message !== 'string' || finding.message.trim().length === 0 || typeof finding.fix !== 'string' || finding.fix.trim().length === 0)\n return invalid(['A review finding is incomplete.'])\n findings.push(finding as unknown as SkillReviewFinding)\n }\n\n return ok({ _tag: 'SkillReview', summary: review.summary, findings })\n}\n","import type { SkillOutputPolicy, SkillRunError, SourceAttempt } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport { constants } from 'node:fs'\nimport { lstat, open, opendir, realpath } from 'node:fs/promises'\nimport { join, relative, resolve, sep } from 'node:path'\nimport { err, ok } from '../result.ts'\n\nexport interface PreparedFile {\n readonly path: string\n readonly content: Uint8Array\n}\n\nexport interface PreparedSource {\n readonly files: ReadonlyArray<PreparedFile>\n readonly attempts: ReadonlyArray<SourceAttempt>\n readonly npmResolution?: {\n readonly package: string\n readonly version: string\n }\n}\n\nconst ignoredNames = new Set([\n '.git',\n '.hg',\n '.next',\n '.nuxt',\n '.output',\n '.skilld',\n '.turbo',\n 'coverage',\n 'dist',\n 'node_modules',\n 'target',\n])\n\nexport async function collectHostDirectory(directory: string, policy: SkillOutputPolicy, sourceLabel = directory, signal?: AbortSignal): Promise<Result<PreparedSource, SkillRunError>> {\n const root = resolve(directory)\n const unavailable = (message: string, cause?: unknown): Result<never, SkillRunError> => err({\n _tag: 'SourceUnavailable',\n message,\n attempts: [{ source: sourceLabel, status: 'skipped', reason: message }],\n cause,\n })\n const cancelled = (): Result<never, SkillRunError> => err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n if (signal?.aborted)\n return cancelled()\n const rootStat = await lstat(root).catch(error => error as NodeJS.ErrnoException)\n if (rootStat instanceof Error)\n return unavailable('Source directory is unavailable.', rootStat)\n if (!rootStat.isDirectory() || rootStat.isSymbolicLink())\n return unavailable('Source path must be a directory, not a symbolic link.')\n const canonicalRoot = await realpath(root).catch(error => error as NodeJS.ErrnoException)\n if (canonicalRoot instanceof Error)\n return unavailable('Source directory cannot be resolved.', canonicalRoot)\n if (canonicalRoot !== root)\n return unavailable('Source path must not pass through a symbolic link.')\n\n const files: PreparedFile[] = []\n let totalBytes = 0\n\n const walk = async (current: string): Promise<Result<void, SkillRunError>> => {\n if (signal?.aborted)\n return cancelled()\n const canonicalCurrent = await realpath(current).catch(error => error as NodeJS.ErrnoException)\n if (canonicalCurrent instanceof Error || canonicalCurrent !== current)\n return unavailable('Source directory changed during collection.', canonicalCurrent instanceof Error ? canonicalCurrent : undefined)\n const directoryHandle = await opendir(current).catch(error => error as NodeJS.ErrnoException)\n if (directoryHandle instanceof Error)\n return unavailable('Source directory cannot be read.', directoryHandle)\n\n for await (const entry of directoryHandle) {\n if (signal?.aborted)\n return cancelled()\n if (ignoredNames.has(entry.name))\n continue\n const absolute = join(current, entry.name)\n const stat = await lstat(absolute).catch(error => error as NodeJS.ErrnoException)\n if (stat instanceof Error)\n return unavailable('Source entry cannot be read.', stat)\n if (stat.isSymbolicLink())\n return unavailable('Source contains a symbolic link.')\n if (stat.isDirectory()) {\n const nested = await walk(absolute)\n if (nested._tag === 'Err')\n return nested\n continue\n }\n if (!stat.isFile())\n return unavailable('Source contains a special file.')\n\n const path = relative(root, absolute).split(sep).join('/')\n const handle = await open(absolute, constants.O_RDONLY | constants.O_NOFOLLOW).catch(error => error as NodeJS.ErrnoException)\n if (handle instanceof Error)\n return unavailable('Source file cannot be opened without following links.', handle)\n const openedStat = await handle.stat().catch(error => error as NodeJS.ErrnoException)\n if (openedStat instanceof Error) {\n await handle.close()\n return unavailable('Source file cannot be inspected.', openedStat)\n }\n if (!openedStat.isFile() || openedStat.dev !== stat.dev || openedStat.ino !== stat.ino) {\n await handle.close()\n return unavailable('Source file changed during collection.')\n }\n if (openedStat.size > policy.maxSourceFileBytes) {\n await handle.close()\n continue\n }\n if (files.length >= policy.maxSourceFiles) {\n await handle.close()\n return unavailable('Source contains too many files.')\n }\n if (totalBytes + openedStat.size > policy.maxSourceBytes) {\n await handle.close()\n return unavailable('Source exceeds the total byte limit.')\n }\n\n const content = await handle.readFile().catch(error => error as NodeJS.ErrnoException)\n await handle.close()\n if (content instanceof Error)\n return unavailable('Source file cannot be read.', content)\n if (content.byteLength !== openedStat.size)\n return unavailable('Source file changed during collection.')\n if (signal?.aborted)\n return cancelled()\n files.push({ path, content })\n totalBytes += content.byteLength\n }\n return ok(undefined)\n }\n\n const walked = await walk(root)\n if (walked._tag === 'Err')\n return walked\n if (files.length === 0)\n return unavailable('Source directory has no usable files.')\n\n files.sort((left, right) => left.path.localeCompare(right.path))\n return ok({ files, attempts: [{ source: sourceLabel, status: 'used' }] })\n}\n","import type { SkillOutputPolicy, SkillRunError } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { PreparedFile } from './host.ts'\nimport { Readable } from 'node:stream'\nimport { createGunzip } from 'node:zlib'\nimport { normalizeOutputPath } from '../paths.ts'\nimport { err, ok } from '../result.ts'\n\nconst blockBytes = 512\n\nexport type ArchiveLayout = 'npm' | 'github'\n\ninterface PendingEntry {\n readonly kind: 'directory' | 'file' | 'metadata' | 'skip'\n readonly path?: string\n readonly metadataType?: 'long-path' | 'pax'\n readonly size: number\n remaining: number\n padding: number\n readonly chunks: Array<Buffer<ArrayBufferLike>>\n}\n\nfunction unavailable(message: string, cause?: unknown): Result<never, SkillRunError> {\n return err({ _tag: 'SourceUnavailable', message, attempts: [], cause })\n}\n\nfunction readString(buffer: Uint8Array, start: number, length: number): string {\n const bytes = buffer.subarray(start, start + length)\n const zero = bytes.indexOf(0)\n return Buffer.from(zero === -1 ? bytes : bytes.subarray(0, zero)).toString('utf8').trim()\n}\n\nfunction readOctal(buffer: Uint8Array, start: number, length: number): number | null {\n const value = readString(buffer, start, length).replace(/^\\s+|\\s+$/g, '')\n if (!/^[0-7]+$/.test(value))\n return null\n const parsed = Number.parseInt(value, 8)\n return Number.isSafeInteger(parsed) ? parsed : null\n}\n\nfunction hasValidChecksum(header: Uint8Array): boolean {\n const expected = readOctal(header, 148, 8)\n if (expected === null)\n return false\n let actual = 0\n for (let index = 0; index < header.byteLength; index += 1)\n actual += index >= 148 && index < 156 ? 32 : header[index]!\n return actual === expected\n}\n\nfunction parsePaxPath(content: Uint8Array): string | null {\n const text = Buffer.from(content).toString('utf8')\n let offset = 0\n let path: string | null = null\n while (offset < text.length) {\n const space = text.indexOf(' ', offset)\n if (space === -1)\n return null\n const length = Number.parseInt(text.slice(offset, space), 10)\n if (!Number.isSafeInteger(length) || length <= 0 || offset + length > text.length)\n return null\n const record = text.slice(space + 1, offset + length - 1)\n const equals = record.indexOf('=')\n if (equals !== -1 && record.slice(0, equals) === 'path')\n path = record.slice(equals + 1)\n offset += length\n }\n return path\n}\n\nfunction archivePath(value: string, layout: ArchiveLayout): string | null {\n const normalized = normalizeOutputPath(value)\n if (normalized === null)\n return null\n const segments = normalized.split('/')\n if (layout === 'npm') {\n if (segments[0] !== 'package' || segments.length < 2)\n return null\n }\n else if (segments.length < 2) {\n return null\n }\n return normalizeOutputPath(segments.slice(1).join('/'))\n}\n\nfunction entryContent(entry: PendingEntry): Buffer<ArrayBufferLike> {\n return entry.chunks.length === 1\n ? entry.chunks[0]!\n : Buffer.concat(entry.chunks, entry.size)\n}\n\nexport async function extractArchive(\n compressed: AsyncIterable<Uint8Array>,\n policy: SkillOutputPolicy,\n layout: ArchiveLayout,\n): Promise<Result<ReadonlyArray<PreparedFile>, SkillRunError>> {\n const source = Readable.from(compressed)\n const gunzip = createGunzip()\n source.on('error', error => gunzip.destroy(error))\n source.pipe(gunzip)\n const files: PreparedFile[] = []\n const seen = new Set<string>()\n const maxArchiveBytes = policy.maxSourceBytes + (policy.maxSourceFiles + 2) * blockBytes * 2\n let archiveBytes = 0\n let fileEntries = 0\n let nextPath: string | null = null\n let pending: Buffer<ArrayBufferLike> = Buffer.alloc(0)\n let entry: PendingEntry | null = null\n let totalBytes = 0\n let ended = false\n\n try {\n for await (const value of gunzip) {\n const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value as Uint8Array)\n archiveBytes += chunk.byteLength\n if (archiveBytes > maxArchiveBytes)\n return unavailable('Source archive exceeds the uncompressed byte limit.')\n pending = pending.byteLength === 0 ? chunk : Buffer.concat([pending, chunk])\n\n while (pending.byteLength > 0) {\n if (ended) {\n if (pending.some(byte => byte !== 0))\n return unavailable('Source archive has data after its end marker.')\n pending = Buffer.alloc(0)\n break\n }\n\n if (entry !== null) {\n if (entry.remaining > 0) {\n const consumed = Math.min(entry.remaining, pending.byteLength)\n if (entry.kind === 'file' || entry.kind === 'metadata')\n entry.chunks.push(pending.subarray(0, consumed))\n pending = pending.subarray(consumed)\n entry.remaining -= consumed\n if (entry.remaining > 0)\n break\n }\n if (entry.padding > 0) {\n const consumed = Math.min(entry.padding, pending.byteLength)\n pending = pending.subarray(consumed)\n entry.padding -= consumed\n if (entry.padding > 0)\n break\n }\n\n if (entry.kind === 'metadata') {\n const content = entryContent(entry)\n nextPath = entry.metadataType === 'pax'\n ? parsePaxPath(content)\n : content.toString('utf8').replace(/\\0.*$/s, '').trim()\n if (nextPath === null || nextPath.length === 0)\n return unavailable('Source archive has invalid path metadata.')\n }\n else if (entry.kind === 'file' && entry.path) {\n files.push({ path: entry.path, content: Uint8Array.from(entryContent(entry)) })\n totalBytes += entry.size\n }\n entry = null\n continue\n }\n\n if (pending.byteLength < blockBytes)\n break\n const header = pending.subarray(0, blockBytes)\n pending = pending.subarray(blockBytes)\n if (header.every(byte => byte === 0)) {\n ended = true\n continue\n }\n if (!hasValidChecksum(header))\n return unavailable('Source archive has an invalid header checksum.')\n\n const size = readOctal(header, 124, 12)\n if (size === null)\n return unavailable('Source archive has an invalid entry size.')\n const name = readString(header, 0, 100)\n const prefix = readString(header, 345, 155)\n const headerPath = prefix.length > 0 ? `${prefix}/${name}` : name\n const type = String.fromCharCode(header[156] ?? 0)\n const padding = (blockBytes - size % blockBytes) % blockBytes\n\n if (type === 'x' || type === 'L') {\n if (size > policy.maxSourceFileBytes)\n return unavailable('Source archive path metadata exceeds the file byte limit.')\n entry = {\n kind: 'metadata',\n metadataType: type === 'x' ? 'pax' : 'long-path',\n size,\n remaining: size,\n padding,\n chunks: [],\n }\n continue\n }\n if (type === '5') {\n nextPath = null\n entry = { kind: 'directory', size, remaining: size, padding, chunks: [] }\n continue\n }\n if (type !== '0' && type !== '\\0')\n return unavailable('Source archive contains a linked or special entry.')\n\n const path = archivePath(nextPath ?? headerPath, layout)\n nextPath = null\n if (path === null)\n return unavailable('Source archive contains an invalid path.')\n if (seen.has(path))\n return unavailable('Source archive contains duplicate paths.')\n seen.add(path)\n fileEntries += 1\n if (fileEntries > policy.maxSourceFiles)\n return unavailable('Source archive contains too many files.')\n if (size <= policy.maxSourceFileBytes && totalBytes + size > policy.maxSourceBytes)\n return unavailable('Source archive exceeds the total byte limit.')\n\n entry = {\n kind: size > policy.maxSourceFileBytes ? 'skip' : 'file',\n path,\n size,\n remaining: size,\n padding,\n chunks: [],\n }\n }\n }\n }\n catch (cause) {\n const message = cause instanceof Error ? cause.message : ''\n return unavailable(message.startsWith('Source archive ')\n ? message\n : 'Source archive is not valid gzip data.', cause)\n }\n\n if (entry !== null || pending.some(byte => byte !== 0) || !ended)\n return unavailable('Source archive ended before its final entry.')\n if (files.length === 0)\n return unavailable('Source archive has no usable files.')\n files.sort((left, right) => left.path.localeCompare(right.path))\n return ok(files)\n}\n","import type { Hash } from 'node:crypto'\nimport type { SkillOutputPolicy, SkillRunError, SourceAttempt } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { PreparedFile, PreparedSource } from './host.ts'\nimport { createHash } from 'node:crypto'\nimport { posix } from 'node:path'\nimport { err, ok } from '../result.ts'\nimport { extractArchive } from './archive.ts'\n\ninterface NpmDist {\n readonly tarball: string\n readonly integrity?: string\n readonly shasum?: string\n}\n\ninterface NpmRepository {\n readonly type?: string\n readonly url?: string\n}\n\ninterface NpmVersion {\n readonly version: string\n readonly dist: NpmDist\n readonly gitHead?: string\n readonly repository?: NpmRepository | string\n}\n\ninterface IntegrityVerifier {\n readonly update: (content: Uint8Array) => void\n readonly valid: () => boolean\n}\n\nconst packageSpecPattern = /^(@[^/@]+\\/[^/@]+|[^/@]+)(?:@(\\S+))?$/\nconst exactVersionPattern = /^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[\\da-z-]+(?:\\.[\\da-z-]+)*)?(?:\\+[\\da-z-]+(?:\\.[\\da-z-]+)*)?$/i\nconst gitCommitPattern = /^[0-9a-f]{40}$/i\nconst npmRequestTimeoutMs = 30_000\nconst npmRedirectLimit = 3\nconst packumentByteLimit = 10 * 1024 * 1024\n\nexport type FetchClient = (input: string | URL | Request, init?: RequestInit) => Promise<Response>\n\nfunction unavailable(message: string, attempts: ReadonlyArray<SourceAttempt>, cause?: unknown): Result<never, SkillRunError> {\n return err({ _tag: 'SourceUnavailable', message, attempts, cause })\n}\n\nfunction parsePackageSpec(spec: string): { name: string, version: string } | null {\n const match = spec.match(packageSpecPattern)\n return match?.[1] ? { name: match[1], version: match[2] ?? 'latest' } : null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction parseRepository(value: unknown): NpmRepository | string | undefined {\n if (typeof value === 'string')\n return value\n if (!isRecord(value))\n return undefined\n return {\n type: typeof value.type === 'string' ? value.type : undefined,\n url: typeof value.url === 'string' ? value.url : undefined,\n }\n}\n\nfunction parseVersion(packument: unknown, requested: string): { resolvedVersion: string, version: NpmVersion, repository?: NpmRepository | string } | null {\n if (!isRecord(packument) || !isRecord(packument['dist-tags']) || !isRecord(packument.versions))\n return null\n const tagged = packument['dist-tags'][requested]\n const resolvedVersion = typeof tagged === 'string' ? tagged : requested\n const value = packument.versions[resolvedVersion]\n if (!isRecord(value) || typeof value.version !== 'string' || !isRecord(value.dist) || typeof value.dist.tarball !== 'string')\n return null\n return {\n resolvedVersion,\n repository: parseRepository(packument.repository),\n version: {\n version: value.version,\n gitHead: typeof value.gitHead === 'string' ? value.gitHead : undefined,\n repository: parseRepository(value.repository),\n dist: {\n tarball: value.dist.tarball,\n integrity: typeof value.dist.integrity === 'string' ? value.dist.integrity : undefined,\n shasum: typeof value.dist.shasum === 'string' ? value.dist.shasum : undefined,\n },\n },\n }\n}\n\nasync function cancelBody(response: Response): Promise<void> {\n if (!response.body)\n return\n // A failed cleanup cannot replace the source failure.\n await response.body.cancel().catch(() => undefined)\n}\n\nfunction declaredBytes(response: Response): number | null {\n const value = response.headers.get('content-length')\n if (value === null || !/^\\d+$/.test(value))\n return null\n const bytes = Number(value)\n return Number.isSafeInteger(bytes) ? bytes : null\n}\n\nasync function* responseChunks(\n response: Response,\n maxBytes: number,\n limitMessage: string,\n onChunk: (content: Uint8Array) => void = () => {},\n): AsyncGenerator<Uint8Array> {\n const declared = declaredBytes(response)\n if (declared !== null && declared > maxBytes) {\n await cancelBody(response)\n throw new Error(limitMessage)\n }\n if (!response.body)\n return\n\n const reader = response.body.getReader()\n let complete = false\n let totalBytes = 0\n try {\n while (true) {\n const result = await reader.read()\n if (result.done) {\n complete = true\n return\n }\n totalBytes += result.value.byteLength\n if (totalBytes > maxBytes)\n throw new Error(limitMessage)\n onChunk(result.value)\n yield result.value\n }\n }\n finally {\n if (!complete) {\n // A failed cleanup cannot replace the source failure.\n await reader.cancel().catch(() => undefined)\n }\n reader.releaseLock()\n }\n}\n\nasync function readBoundedResponse(response: Response, maxBytes: number): Promise<Result<Uint8Array, SkillRunError>> {\n const chunks: Uint8Array[] = []\n let totalBytes = 0\n try {\n for await (const chunk of responseChunks(response, maxBytes, 'npm response exceeds the byte limit.')) {\n chunks.push(chunk)\n totalBytes += chunk.byteLength\n }\n }\n catch (cause) {\n return unavailable(cause instanceof Error ? cause.message : 'npm response cannot be read.', [], cause)\n }\n return ok(Uint8Array.from(Buffer.concat(chunks, totalBytes)))\n}\n\nasync function fetchWithRedirects(fetchClient: FetchClient, url: string, init: RequestInit = {}, signal?: AbortSignal): Promise<Result<Response, SkillRunError>> {\n const timeout = AbortSignal.timeout(npmRequestTimeoutMs)\n const requestSignal = signal ? AbortSignal.any([signal, timeout]) : timeout\n let current = url\n for (let redirects = 0; redirects <= npmRedirectLimit; redirects += 1) {\n const response = await fetchClient(current, { ...init, redirect: 'manual', signal: requestSignal }).catch(error => error as Error)\n if (response instanceof Error)\n return unavailable(timeout.aborted ? 'npm request timed out.' : 'npm request failed.', [], response)\n if (![301, 302, 303, 307, 308].includes(response.status))\n return ok(response)\n if (redirects === npmRedirectLimit) {\n await cancelBody(response)\n return unavailable('npm request exceeded the redirect limit.', [])\n }\n const location = response.headers.get('location')\n if (!location) {\n await cancelBody(response)\n return unavailable('npm redirect is missing its location.', [])\n }\n const redirected = await Promise.resolve().then(() => new URL(location, current)).catch(() => null)\n if (redirected === null) {\n await cancelBody(response)\n return unavailable('npm redirect location is invalid.', [])\n }\n if (redirected.protocol !== 'https:') {\n await cancelBody(response)\n return unavailable('npm redirect URL must use HTTPS.', [])\n }\n await cancelBody(response)\n current = redirected.href\n }\n return unavailable('npm request exceeded the redirect limit.', [])\n}\n\nfunction createIntegrityVerifier(dist: NpmDist): IntegrityVerifier | null {\n const values = dist.integrity?.split(/\\s+/).filter(Boolean) ?? []\n let expected = values.flatMap((value) => {\n const match = value.match(/^(sha(?:1|256|384|512))-([A-Za-z0-9+/=]+)$/)\n return match?.[1] && match[2] ? [{ algorithm: match[1], digest: match[2] }] : []\n })\n if (expected.length > 0) {\n const strength = { sha1: 1, sha256: 2, sha384: 3, sha512: 4 } as const\n const strongest = Math.max(...expected.map(value => strength[value.algorithm as keyof typeof strength]))\n expected = expected.filter(value => strength[value.algorithm as keyof typeof strength] === strongest)\n }\n if (values.length === 0 && dist.shasum && /^[0-9a-f]{40}$/i.test(dist.shasum))\n expected.push({ algorithm: 'sha1', digest: Buffer.from(dist.shasum, 'hex').toString('base64') })\n if (expected.length === 0)\n return null\n\n const hashes = new Map<string, Hash>()\n for (const value of expected)\n hashes.set(value.algorithm, createHash(value.algorithm))\n return {\n update(content) {\n for (const hash of hashes.values())\n hash.update(content)\n },\n valid() {\n const actual = new Map([...hashes].map(([algorithm, hash]) => [algorithm, hash.digest('base64')]))\n return expected.some(value => actual.get(value.algorithm) === value.digest)\n },\n }\n}\n\nfunction repositoryUrl(repository: NpmRepository | string | undefined): string | null {\n if (typeof repository === 'string')\n return repository\n return typeof repository?.url === 'string' ? repository.url : null\n}\n\nfunction githubArchiveUrl(repository: NpmRepository | string | undefined, gitHead: string | undefined): string | null {\n if (!gitHead || !gitCommitPattern.test(gitHead))\n return null\n const source = repositoryUrl(repository)\n if (source === null)\n return null\n const match = source.match(/^(?:(?:git\\+)?https?:\\/\\/(?:git@)?github\\.com\\/|git:\\/\\/github\\.com\\/|git@github\\.com:)([\\w.-]+)\\/([\\w.-]+?)(?:\\.git)?\\/?$/)\n if (!match?.[1] || !match[2])\n return null\n return `https://codeload.github.com/${encodeURIComponent(match[1])}/${encodeURIComponent(match[2])}/tar.gz/${gitHead}`\n}\n\nfunction skipped(source: string, reason: string): SourceAttempt {\n return { source, status: 'skipped', reason }\n}\n\nfunction used(source: string): SourceAttempt {\n return { source, status: 'used' }\n}\n\nfunction withAttempts(error: SkillRunError, attempts: ReadonlyArray<SourceAttempt>): Result<never, SkillRunError> {\n return error._tag === 'SourceUnavailable'\n ? unavailable(error.message, attempts, error.cause)\n : err(error)\n}\n\nfunction remainingPolicy(policy: SkillOutputPolicy, files: ReadonlyArray<PreparedFile>): SkillOutputPolicy | null {\n const usedBytes = files.reduce((total, file) => total + file.content.byteLength, 0)\n const maxSourceFiles = policy.maxSourceFiles - files.length\n const maxSourceBytes = policy.maxSourceBytes - usedBytes\n if (maxSourceFiles <= 0 || maxSourceBytes <= 0)\n return null\n return { ...policy, maxSourceFiles, maxSourceBytes }\n}\n\nasync function extractResponse(\n response: Response,\n policy: SkillOutputPolicy,\n layout: 'github' | 'npm',\n verifier?: IntegrityVerifier,\n): Promise<Result<ReadonlyArray<PreparedFile>, SkillRunError>> {\n return extractArchive(\n responseChunks(\n response,\n policy.maxSourceBytes,\n 'Source archive exceeds the compressed byte limit.',\n content => verifier?.update(content),\n ),\n policy,\n layout,\n )\n}\n\nexport async function prepareNpmPackage(spec: string, policy: SkillOutputPolicy, fetchClient: FetchClient, signal?: AbortSignal): Promise<Result<PreparedSource, SkillRunError>> {\n const parsed = parsePackageSpec(spec)\n if (parsed === null)\n return unavailable('npm package spec is invalid.', [])\n\n const attempts: SourceAttempt[] = []\n const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(parsed.name)}`\n const registryResponse = await fetchWithRedirects(fetchClient, registryUrl, {\n headers: { accept: 'application/vnd.npm.install-v1+json' },\n }, signal)\n if (registryResponse._tag === 'Err')\n return withAttempts(registryResponse.error, [skipped(registryUrl, registryResponse.error.message)])\n const response = registryResponse.value\n if (!response.ok) {\n await cancelBody(response)\n const message = `npm registry returned HTTP ${response.status}.`\n return unavailable(message, [skipped(registryUrl, message)])\n }\n\n const packumentBytes = await readBoundedResponse(response, packumentByteLimit)\n if (packumentBytes._tag === 'Err')\n return withAttempts(packumentBytes.error, [skipped(registryUrl, packumentBytes.error.message)])\n\n let packument: unknown\n try {\n packument = JSON.parse(Buffer.from(packumentBytes.value).toString('utf8')) as unknown\n }\n catch (cause) {\n const message = 'npm registry returned invalid package data.'\n return unavailable(message, [skipped(registryUrl, message)], cause)\n }\n\n const resolution = parseVersion(packument, parsed.version)\n if (resolution === null || !exactVersionPattern.test(resolution.resolvedVersion) || resolution.version.version !== resolution.resolvedVersion) {\n const message = 'npm package did not resolve to an exact version.'\n return unavailable(message, [skipped(registryUrl, message)])\n }\n const { repository, resolvedVersion, version } = resolution\n if (!version.dist.tarball.startsWith('https://')) {\n const message = 'npm package archive URL must use HTTPS.'\n return unavailable(message, [skipped(registryUrl, message)])\n }\n attempts.push(used(registryUrl))\n\n const fetchedArchive = await fetchWithRedirects(fetchClient, version.dist.tarball, {}, signal)\n if (fetchedArchive._tag === 'Err')\n return withAttempts(fetchedArchive.error, [...attempts, skipped(version.dist.tarball, fetchedArchive.error.message)])\n const archiveResponse = fetchedArchive.value\n if (!archiveResponse.ok) {\n await cancelBody(archiveResponse)\n const message = `npm package archive returned HTTP ${archiveResponse.status}.`\n return unavailable(message, [...attempts, skipped(version.dist.tarball, message)])\n }\n\n const verifier = createIntegrityVerifier(version.dist)\n if (verifier === null) {\n await cancelBody(archiveResponse)\n const message = 'npm package archive has no supported integrity value.'\n return unavailable(message, [...attempts, skipped(version.dist.tarball, message)])\n }\n const extracted = await extractResponse(archiveResponse, policy, 'npm', verifier)\n if (extracted._tag === 'Err')\n return withAttempts(extracted.error, [...attempts, skipped(version.dist.tarball, extracted.error.message)])\n if (!verifier.valid()) {\n const message = 'npm package archive integrity check failed.'\n return unavailable(message, [...attempts, skipped(version.dist.tarball, message)])\n }\n attempts.push(used(version.dist.tarball))\n let files = [...extracted.value]\n\n const repositoryArchive = githubArchiveUrl(version.repository ?? repository, version.gitHead)\n const available = remainingPolicy(policy, files)\n if (repositoryArchive !== null && available === null) {\n attempts.push(skipped(repositoryArchive, 'Prepared package files reached the source limit.'))\n }\n else if (repositoryArchive !== null && available !== null) {\n const fetchedRepository = await fetchWithRedirects(fetchClient, repositoryArchive, {}, signal)\n if (fetchedRepository._tag === 'Err') {\n attempts.push(skipped(repositoryArchive, fetchedRepository.error.message))\n }\n else if (!fetchedRepository.value.ok) {\n const message = `GitHub source archive returned HTTP ${fetchedRepository.value.status}.`\n await cancelBody(fetchedRepository.value)\n attempts.push(skipped(repositoryArchive, message))\n }\n else {\n const repositoryFiles = await extractResponse(fetchedRepository.value, available, 'github')\n if (repositoryFiles._tag === 'Err') {\n attempts.push(skipped(repositoryArchive, repositoryFiles.error.message))\n }\n else {\n files = [\n ...files,\n ...repositoryFiles.value.map(file => ({ ...file, path: posix.join('repository', file.path) })),\n ]\n attempts.push(used(repositoryArchive))\n }\n }\n }\n\n files.sort((left, right) => left.path.localeCompare(right.path))\n return ok({\n files,\n attempts,\n npmResolution: { package: parsed.name, version: resolvedVersion },\n })\n}\n","import type { HarnessV1Skill } from '@ai-sdk/harness'\nimport type { SandboxSession } from './internal/output/collect.ts'\nimport type { Result } from './internal/result.ts'\nimport type { PreparedSource } from './internal/source/host.ts'\nimport type { FetchClient } from './internal/source/npm.ts'\nimport type {\n CreateSkillHarnessOptions,\n SkillDestination,\n SkillHarness,\n SkillOutputPolicy,\n SkillRun,\n SkillRunError,\n SkillRunResult,\n} from './types.ts'\nimport { lstat, realpath } from 'node:fs/promises'\nimport { join, posix, resolve } from 'node:path'\nimport { HarnessAgent } from '@ai-sdk/harness/agent'\nimport { parseOutputPolicy, parseSkillRun } from './internal/input.ts'\nimport { collectSandboxOutput } from './internal/output/collect.ts'\nimport { promoteSkill } from './internal/output/promote.ts'\nimport { validateGeneratedSkill, validateSkillReview } from './internal/output/validate.ts'\nimport { resolveWithin } from './internal/paths.ts'\nimport { err, ok } from './internal/result.ts'\nimport { collectHostDirectory } from './internal/source/host.ts'\nimport { prepareNpmPackage } from './internal/source/npm.ts'\nimport { DEFAULT_OUTPUT_POLICY, loadSkilldMaintainedSkill } from './skills.ts'\n\ninterface PreparedRun {\n readonly skillName: 'generate-package-skill' | 'generate-project-skill' | 'review-skill'\n readonly outputName: string\n readonly source: PreparedSource\n readonly current?: PreparedSource\n readonly destination?: SkillDestination\n}\n\ninterface ActiveSandbox {\n readonly sandbox: SandboxSession\n readonly workDir: string\n}\n\nfunction cancelled(): SkillRunResult {\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n}\n\nasync function prepareCurrentSkill(destination: SkillDestination, policy: SkillOutputPolicy, signal?: AbortSignal): Promise<Result<PreparedSource | undefined, SkillRunError>> {\n const root = resolve(destination.rootDir)\n const rootStat = await lstat(root).catch(error => error as NodeJS.ErrnoException)\n if (rootStat instanceof Error) {\n if (rootStat.code === 'ENOENT')\n return ok(undefined)\n return err({ _tag: 'UnsafeOutputPath', message: 'Output root cannot be inspected.', path: root })\n }\n if (!rootStat.isDirectory() || rootStat.isSymbolicLink())\n return err({ _tag: 'UnsafeOutputPath', message: 'Output root must be a directory, not a symbolic link.', path: root })\n const canonicalRoot = await realpath(root).catch(error => error as Error)\n if (canonicalRoot instanceof Error || canonicalRoot !== root)\n return err({ _tag: 'UnsafeOutputPath', message: 'Output root must not pass through a symbolic link.', path: root })\n\n const target = join(root, destination.name)\n const targetStat = await lstat(target).catch(error => error as NodeJS.ErrnoException)\n if (targetStat instanceof Error) {\n if (targetStat.code === 'ENOENT')\n return ok(undefined)\n return err({ _tag: 'UnsafeOutputPath', message: 'Output path cannot be inspected.', path: target })\n }\n if (!targetStat.isDirectory() || targetStat.isSymbolicLink())\n return err({ _tag: 'UnsafeOutputPath', message: 'Output path must be a directory, not a symbolic link.', path: target })\n return collectHostDirectory(target, policy, 'current Skill', signal)\n}\n\nasync function prepareRun(input: SkillRun, policy: SkillOutputPolicy, fetchClient: FetchClient, signal?: AbortSignal): Promise<Result<PreparedRun, SkillRunError>> {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n\n const current = input._tag === 'ReviewSkill'\n ? ok(undefined)\n : await prepareCurrentSkill(input.destination, policy, signal)\n if (current._tag === 'Err')\n return current\n\n if (input._tag === 'ProjectSkill') {\n const source = await collectHostDirectory(input.projectDir, policy, input.projectDir, signal)\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'generate-project-skill', outputName: input.destination.name, source: source.value, current: current.value, destination: input.destination })\n }\n\n if (input._tag === 'ReviewSkill') {\n const source = await collectHostDirectory(input.skillDir, policy, input.skillDir, signal)\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'review-skill', outputName: 'review', source: source.value })\n }\n\n if (input.source._tag === 'NpmPackage') {\n const source = await prepareNpmPackage(input.source.spec, policy, fetchClient, signal)\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'generate-package-skill', outputName: input.destination.name, source: source.value, current: current.value, destination: input.destination })\n }\n\n const packageDir = resolveWithin(input.source.rootDir, input.source.packageDir)\n if (packageDir === null)\n return err({ _tag: 'InvalidInput', message: 'Local package directory must stay inside its root directory.' })\n const manifest = await lstat(join(packageDir, 'package.json')).catch(error => error as NodeJS.ErrnoException)\n if (manifest instanceof Error || !manifest.isFile() || manifest.isSymbolicLink()) {\n return err({\n _tag: 'SourceUnavailable',\n message: 'Local package directory must contain package.json.',\n attempts: [{ source: packageDir, status: 'skipped', reason: 'package.json is unavailable.' }],\n })\n }\n\n const source = await collectHostDirectory(packageDir, policy, packageDir, signal)\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'generate-package-skill', outputName: input.destination.name, source: source.value, current: current.value, destination: input.destination })\n}\n\nfunction requestContent(skill: HarnessV1Skill): string {\n const request = skill.files?.find(file => file.path === 'assets/harness-request.md')\n if (!request)\n throw new Error(`Harness request asset is missing for ${skill.name}.`)\n return request.content\n}\n\nfunction renderRequest(template: string, sourcePath: string, currentSkillPath: string, outputPath: string, skillName: string): string {\n return template\n .replaceAll('{{SOURCE_PATH}}', sourcePath)\n .replaceAll('{{CURRENT_SKILL_PATH}}', currentSkillPath)\n .replaceAll('{{OUTPUT_PATH}}', outputPath)\n .replaceAll('{{SKILL_NAME}}', skillName)\n}\n\nasync function writePreparedSource(active: ActiveSandbox, prepared: PreparedRun, signal?: AbortSignal): Promise<void> {\n const sourcePath = posix.join(active.workDir, 'input/source')\n const reset = await active.sandbox.run({\n command: 'rm -rf -- \"$SKILLD_INPUT\" \"$SKILLD_OUTPUT\" && mkdir -p -- \"$SKILLD_INPUT\"',\n env: {\n SKILLD_INPUT: posix.join(active.workDir, 'input'),\n SKILLD_OUTPUT: posix.join(active.workDir, 'skilld-output'),\n },\n abortSignal: signal,\n })\n if (reset.exitCode !== 0)\n throw new Error(reset.stderr.trim() || 'Harness work directory cannot be prepared.')\n for (const file of prepared.source.files) {\n await active.sandbox.writeBinaryFile({\n path: posix.join(sourcePath, file.path),\n content: file.content,\n abortSignal: signal,\n })\n }\n for (const file of prepared.current?.files ?? []) {\n await active.sandbox.writeBinaryFile({\n path: posix.join(active.workDir, 'input/current-skill', file.path),\n content: file.content,\n abortSignal: signal,\n })\n }\n await active.sandbox.writeTextFile({\n path: posix.join(active.workDir, 'input/source-manifest.json'),\n content: `${JSON.stringify({\n sourceAttempts: prepared.source.attempts,\n npmResolution: prepared.source.npmResolution,\n hasCurrentSkill: prepared.current !== undefined,\n }, null, 2)}\\n`,\n abortSignal: signal,\n })\n}\n\nfunction toAgentError(cause: unknown, signal?: AbortSignal): SkillRunResult {\n return signal?.aborted\n ? cancelled()\n : err({ _tag: 'AgentFailed', message: 'Harness Agent failed during the Skill run.', cause })\n}\n\nexport function createSkillHarness(options: CreateSkillHarnessOptions): SkillHarness {\n const policy = parseOutputPolicy({ ...DEFAULT_OUTPUT_POLICY, ...options.outputPolicy })\n const fetchClient: FetchClient = options.fetch ?? globalThis.fetch.bind(globalThis)\n const sandboxConfig = { ...options.sandboxConfig }\n const harness = options.harness\n const sandbox = options.sandbox\n\n return {\n run: async (input, runOptions = {}): Promise<SkillRunResult> => {\n const parsed = parseSkillRun(input)\n if (parsed._tag === 'Err')\n return parsed\n\n const prepared = await prepareRun(parsed.value, policy, fetchClient, runOptions.signal)\n if (prepared._tag === 'Err')\n return prepared\n\n const skill = await loadSkilldMaintainedSkill(prepared.value.skillName)\n let active: ActiveSandbox | undefined\n const userOnSession = sandboxConfig.onSession\n const agent = new HarnessAgent({\n harness,\n sandbox,\n skills: [skill],\n permissionMode: 'allow-all',\n sandboxConfig: {\n ...sandboxConfig,\n onSession: async (sessionOptions) => {\n active = { sandbox: sessionOptions.session, workDir: sessionOptions.sessionWorkDir }\n await writePreparedSource(active, prepared.value, runOptions.signal)\n await userOnSession?.(sessionOptions)\n },\n },\n })\n\n const sessionResult = await agent.createSession({ abortSignal: runOptions.signal }).then(ok, cause => err(cause))\n if (sessionResult._tag === 'Err')\n return toAgentError(sessionResult.error, runOptions.signal)\n const session = sessionResult.value\n\n try {\n if (!active)\n return err({ _tag: 'AgentFailed', message: 'Harness did not provide its sandbox session.' })\n const sourcePath = posix.join(active.workDir, 'input/source')\n const currentSkillPath = posix.join(active.workDir, 'input/current-skill')\n const outputPath = posix.join(active.workDir, 'skilld-output', prepared.value.outputName)\n const prompt = renderRequest(requestContent(skill), sourcePath, currentSkillPath, outputPath, prepared.value.outputName)\n const generated = await agent.generate({ session, prompt, abortSignal: runOptions.signal }).then(ok, cause => err(cause))\n if (generated._tag === 'Err')\n return toAgentError(generated.error, runOptions.signal)\n if (runOptions.signal?.aborted)\n return cancelled()\n\n const collected = await collectSandboxOutput(active.sandbox, outputPath, policy, runOptions.signal)\n if (collected._tag === 'Err')\n return collected\n\n if (prepared.value.skillName === 'review-skill')\n return validateSkillReview(collected.value)\n\n const validated = validateGeneratedSkill(\n prepared.value.outputName,\n collected.value,\n prepared.value.skillName === 'generate-project-skill'\n ? prepared.value.source.files.map(file => file.path)\n : undefined,\n )\n if (validated._tag === 'Err')\n return validated\n if (!prepared.value.destination)\n return err({ _tag: 'InvalidInput', message: 'Skill destination is required.' })\n return promoteSkill(\n prepared.value.destination.rootDir,\n prepared.value.destination.name,\n collected.value,\n prepared.value.source.attempts,\n )\n }\n finally {\n await session.destroy()\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;AAIA,MAAa,MAAS,WAAgC;CAAE,MAAM;CAAM;AAAM;AAC1E,MAAa,OAAU,WAAgC;CAAE,MAAM;CAAO;AAAM;ACC5E,SAASA,UAAQ,SAA+C;CAC9D,OAAO,IAAI;EAAE,MAAM;EAAgB;CAAQ,CAAC;AAC9C;AAEA,SAAS,iBAAiB,OAAiC;CACzD,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,CAAC,CAAC,SAAS;AAC5D;AAEA,SAAgB,cAAc,OAAkD;CAC9E,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,EAAE,UAAU,QACrD,OAAOA,UAAQ,+CAA+C;CAEhE,IAAI,MAAM,SAAS,gBAAgB;EACjC,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,aAC1B,OAAOA,UAAQ,oCAAoC;EACrD,IAAI,CAAC,iBAAiB,MAAM,YAAY,OAAO,KAAK,CAAC,YAAY,MAAM,YAAY,IAAI,GACrF,OAAOA,UAAQ,uCAAuC;EACxD,IAAI,MAAM,OAAO,SAAS,cAAc;GACtC,IAAI,CAAC,iBAAiB,MAAM,OAAO,IAAI,GACrC,OAAOA,UAAQ,+BAA+B;GAChD,OAAO,GAAG;IACR,MAAM;IACN,QAAQ;KAAE,MAAM;KAAc,MAAM,MAAM,OAAO;IAAK;IACtD,aAAa;KAAE,SAAS,QAAQ,MAAM,YAAY,OAAO;KAAG,MAAM,MAAM,YAAY;IAAK;GAC3F,CAAC;EACH;EACA,IAAI,MAAM,OAAO,SAAS,gBAAgB;GACxC,IAAI,CAAC,iBAAiB,MAAM,OAAO,OAAO,KAAK,CAAC,iBAAiB,MAAM,OAAO,UAAU,GACtF,OAAOA,UAAQ,mCAAmC;GACpD,IAAI,cAAc,MAAM,OAAO,SAAS,MAAM,OAAO,UAAU,MAAM,MACnE,OAAOA,UAAQ,8DAA8D;GAC/E,OAAO,GAAG;IACR,MAAM;IACN,QAAQ;KACN,MAAM;KACN,SAAS,QAAQ,MAAM,OAAO,OAAO;KACrC,YAAY,MAAM,OAAO;IAC3B;IACA,aAAa;KAAE,SAAS,QAAQ,MAAM,YAAY,OAAO;KAAG,MAAM,MAAM,YAAY;IAAK;GAC3F,CAAC;EACH;EACA,OAAOA,UAAQ,gCAAgC;CACjD;CAEA,IAAI,MAAM,SAAS,gBAAgB;EACjC,IAAI,CAAC,iBAAiB,MAAM,UAAU,KAAK,CAAC,MAAM,aAChD,OAAOA,UAAQ,oCAAoC;EACrD,IAAI,CAAC,iBAAiB,MAAM,YAAY,OAAO,KAAK,CAAC,YAAY,MAAM,YAAY,IAAI,GACrF,OAAOA,UAAQ,uCAAuC;EACxD,OAAO,GAAG;GACR,MAAM;GACN,YAAY,QAAQ,MAAM,UAAU;GACpC,aAAa;IAAE,SAAS,QAAQ,MAAM,YAAY,OAAO;IAAG,MAAM,MAAM,YAAY;GAAK;EAC3F,CAAC;CACH;CAEA,IAAI,MAAM,SAAS,eAAe;EAChC,IAAI,CAAC,iBAAiB,MAAM,QAAQ,GAClC,OAAOA,UAAQ,qCAAqC;EACtD,OAAO,GAAG;GAAE,MAAM;GAAe,UAAU,QAAQ,MAAM,QAAQ;EAAE,CAAC;CACtE;CAEA,OAAOA,UAAQ,2BAA2B;AAC5C;AAEA,SAAgB,kBAAkB,QAA8C;CAC9E,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,MAAM,GAC/C,IAAI,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GAC3C,MAAM,IAAI,UAAU,GAAG,KAAK,6BAA6B;CAE7D,OAAO,OAAO,OAAO,MAAM;AAC7B;AChEA,MAAMC,aAAW,SAAiB,WAChC,IAAI;CAAE,MAAM;CAAgB;CAAS;AAAO,CAAC;AAE/C,MAAM,YAAY,OAChB,SACA,WACA,WACgG;CAChG,IAAI,QAAQ,SACV,OAAO,IAAI;EAAE,MAAM;EAAa,SAAS;CAA2B,CAAC;CACvE,MAAM,UAAU;CAChB,MAAM,SAAS,MAAM,QAAQ,QAAQ,CAAC,CAAC,WAAW,QAAQ,IAAI;EAC5D;EACA,KAAK;GAAE,QAAQ;GAAK,eAAe;EAAU;EAC7C,aAAa;CACf,CAAC,CAAC,CAAC,CAAC,OAAM,UAAS,KAAc;CACjC,IAAI,kBAAkB,OACpB,OAAOA,UAAQ,uCAAuC,CAAC,OAAO,OAAO,CAAC;CACxE,IAAI,OAAO,aAAa,GACtB,OAAOA,UAAQ,wCAAwC,CAAC,OAAO,OAAO,KAAK,KAAK,sBAAsB,CAAC;CAEzG,MAAM,SAAS,OAAO,OAAO,MAAM,IAAI;CACvC,IAAI,OAAO,GAAG,EAAE,MAAM,IACpB,OAAO,IAAI;CACb,IAAI,OAAO,SAAS,MAAM,GACxB,OAAOA,UAAQ,wCAAwC,CAAC,yCAAyC,CAAC;CAEpG,MAAM,UAA+D,CAAC;CACtE,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAAG;EACrD,MAAM,OAAO,OAAO;EACpB,MAAM,OAAO,OAAO,QAAQ;EAC5B,MAAM,OAAO,OAAO,OAAO,QAAQ,EAAE;EACrC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,cAAc,IAAI,KAAK,OAAO,GAC1D,OAAOA,UAAQ,wCAAwC,CAAC,oCAAoC,CAAC;EAC/F,QAAQ,KAAK;GAAE;GAAM;GAAM;EAAK,CAAC;CACnC;CACA,OAAO,GAAG,OAAO;AACnB;AAEA,MAAa,uBAAuB,OAClC,SACA,WACA,QACA,WACiE;CACjE,MAAM,SAAS,MAAM,UAAU,SAAS,WAAW,MAAM;CACzD,IAAI,OAAO,SAAS,OAClB,OAAO;CAET,MAAM,QAAyB,CAAC;CAChC,MAAM,uBAAO,IAAI,IAAY;CAC7B,IAAI,aAAa;CACjB,KAAK,MAAM,SAAS,OAAO,OAAO;EAChC,IAAI,QAAQ,SACV,OAAO,IAAI;GAAE,MAAM;GAAa,SAAS;EAA2B,CAAC;EACvE,MAAM,OAAO,oBAAoB,MAAM,IAAI;EAC3C,IAAI,SAAS,MACX,OAAOA,UAAQ,4CAA4C,CAAC,MAAM,IAAI,CAAC;EACzE,IAAI,MAAM,SAAS,KACjB;EACF,IAAI,MAAM,SAAS,KACjB,OAAOA,UAAQ,sDAAsD,CAAC,IAAI,CAAC;EAC7E,IAAI,KAAK,IAAI,IAAI,GACf,OAAOA,UAAQ,4CAA4C,CAAC,IAAI,CAAC;EACnE,IAAI,MAAM,UAAU,OAAO,gBACzB,OAAOA,UAAQ,2CAA2C,CAAC,UAAU,OAAO,gBAAgB,CAAC;EAC/F,IAAI,MAAM,OAAO,OAAO,oBACtB,OAAOA,UAAQ,8CAA8C,CAAC,IAAI,CAAC;EACrE,IAAI,aAAa,MAAM,OAAO,OAAO,gBACnC,OAAOA,UAAQ,gDAAgD,CAAC,UAAU,OAAO,gBAAgB,CAAC;EAEpG,MAAM,UAAU,MAAM,QAAQ,QAAQ,CAAC,CAAC,WAAW,QAAQ,eAAe;GAAE,MAAM,GAAG,UAAU,GAAG;GAAQ,aAAa;EAAO,CAAC,CAAC,CAAC,CAAC,OAAM,UAAS,KAAc;EAC/J,IAAI,mBAAmB,OAAO;GAC5B,IAAI,QAAQ,SACV,OAAO,IAAI;IAAE,MAAM;IAAa,SAAS;GAA2B,CAAC;GACvE,OAAOA,UAAQ,kCAAkC,CAAC,MAAM,QAAQ,OAAO,CAAC;EAC1E;EACA,IAAI,YAAY,QAAQ,QAAQ,eAAe,MAAM,MACnD,OAAOA,UAAQ,6CAA6C,CAAC,IAAI,CAAC;EACpE,KAAK,IAAI,IAAI;EACb,MAAM,KAAK;GAAE;GAAM,SAAS,WAAW,KAAK,OAAO;EAAE,CAAC;EACtD,cAAc,QAAQ;CACxB;CAEA,MAAM,QAAQ,MAAM,UAAU,SAAS,WAAW,MAAM;CACxD,IAAI,MAAM,SAAS,OACjB,OAAO;CACT,IAAI,KAAK,UAAU,OAAO,KAAK,MAAM,KAAK,UAAU,MAAM,KAAK,GAC7D,OAAOA,UAAQ,6CAA6C,CAAC,yBAAyB,CAAC;CAEzF,MAAM,MAAM,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;CAC/D,OAAO,GAAG,KAAK;AACjB;ACjGA,SAAS,UAAU,SAAiB,MAA4C;CAC9E,OAAO,IAAI;EAAE,MAAM;EAAoB;EAAS;CAAK,CAAC;AACxD;AAEA,MAAM,UAAU,OAAO,SAAS;AAEhC,eAAe,cAAc,MAAc;CACzC,OAAO,MAAM,IAAI,CAAC,CAAC,OAAM,UAAU,MAAgC,SAAS,WAAW,UAAU,QAAQ,OAAO,KAAK,CAAC;AACxH;AAEA,MAAa,eAAe,OAC1B,SACA,MACA,OACA,aACmD;CACnD,MAAM,OAAO,QAAQ,OAAO;CAC5B,IAAI,WAAW,MAAM,cAAc,IAAI,CAAC,CAAC,OAAM,UAAS,KAAc;CACtE,IAAI,oBAAoB,OACtB,OAAO,UAAU,oCAAoC,IAAI;CAC3D,IAAI,cAAc;CAClB,IAAI,aAAa,SAAS;EACxB,MAAM,SAAS,QAAQ,IAAI;EAC3B,MAAM,aAAa,MAAM,cAAc,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;EAC5E,IAAI,sBAAsB,SAAS,eAAe,WAAW,CAAC,WAAW,YAAY,KAAK,WAAW,eAAe,GAClH,OAAO,UAAU,qDAAqD,MAAM;EAC9E,MAAM,kBAAkB,MAAM,SAAS,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;EAC5E,IAAI,2BAA2B,SAAS,oBAAoB,QAC1D,OAAO,UAAU,6DAA6D,MAAM;EACtF,MAAM,UAAU,MAAM,MAAM,MAAM,EAAE,MAAM,IAAM,CAAC,CAAC,CAAC,WAAW,OAAM,UAAS,KAA8B;EAC3G,IAAI,mBAAmB,SAAS,QAAQ,SAAS,UAC/C,OAAO,UAAU,kCAAkC,IAAI;EACzD,cAAc,YAAY;EAC1B,WAAW,MAAM,cAAc,IAAI,CAAC,CAAC,OAAM,UAAS,KAAc;CACpE;CACA,IAAI,oBAAoB,SAAS,aAAa,WAAW,CAAC,SAAS,YAAY,KAAK,SAAS,eAAe,GAC1G,OAAO,UAAU,yDAAyD,IAAI;CAChF,MAAM,gBAAgB,MAAM,SAAS,IAAI,CAAC,CAAC,OAAM,UAAS,KAAc;CACxE,IAAI,yBAAyB,OAC3B,OAAO,UAAU,mCAAmC,IAAI;CAC1D,IAAI,kBAAkB,MACpB,OAAO,UAAU,sDAAsD,IAAI;CAE7E,MAAM,SAAS,KAAK,MAAM,IAAI;CAC9B,MAAM,aAAa,MAAM,cAAc,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;CAC5E,IAAI,sBAAsB,OACxB,OAAO,UAAU,oCAAoC,MAAM;CAC7D,IAAI,eAAe,YAAY,CAAC,WAAW,YAAY,KAAK,WAAW,eAAe,IACpF,OAAO,UAAU,yDAAyD,MAAM;CAElF,MAAM,WAAW,KAAK,MAAM,WAAW,KAAK,MAAM;CAClD,MAAM,OAAO,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,OAAM,UAAS,KAA8B;CACrF,IAAI,gBAAgB,OAAO;EACzB,IAAI,KAAK,SAAS,UAChB,OAAO,IAAI;GAAE,MAAM;GAAc,SAAS;GAA4C,MAAM;EAAO,CAAC;EACtG,OAAO,IAAI;GAAE,MAAM;GAAmB,SAAS;GAAqC,MAAM;GAAQ,OAAO;EAAK,CAAC;CACjH;CAEA,MAAM,QAAQ,WAAW;CACzB,MAAM,UAAU,KAAK,MAAM,WAAW,KAAK,GAAG,MAAM,MAAM;CAC1D,MAAM,SAAS,KAAK,MAAM,WAAW,KAAK,GAAG,MAAM,UAAU;CAC7D,IAAI,eAAe;CACnB,IAAI,WAAW;CACf,IAAI,iBAAiB;CACrB,IAAI;CAEJ,IAAI;EACF,MAAM,MAAM,SAAS,EAAE,MAAM,IAAM,CAAC;EACpC,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,cAAc,KAAK,SAAS,KAAK,IAAI;GAC3C,MAAM,MAAM,QAAQ,WAAW,GAAG;IAAE,WAAW;IAAM,MAAM;GAAM,CAAC;GAClE,MAAM,UAAU,aAAa,KAAK,SAAS;IAAE,MAAM;IAAM,MAAM;GAAM,CAAC;EACxE;EAEA,IAAI,eAAe,SAAS;GAC1B,MAAM,OAAO,QAAQ,MAAM;GAC3B,eAAe;EACjB;EACA,MAAM,OAAO,SAAS,MAAM;EAC5B,WAAW;CACb,SACO,OAAO;EACZ,eAAe;EACf,IAAI,gBAAgB,CAAC,UAAU;GAC7B,MAAM,UAAU,MAAM,cAAc,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;GACzE,IAAI,mBAAmB,OAAO;IAC5B,iBAAiB;IACjB,eAAe,IAAI,eAAe,CAAC,OAAO,OAAO,CAAC;GACpD;GACA,IAAI,YAAY,SAAS;IACvB,MAAM,WAAW,MAAM,OAAO,QAAQ,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;IAC3E,IAAI,oBAAoB,OAAO;KAC7B,iBAAiB;KACjB,eAAe,IAAI,eAAe,CAAC,OAAO,QAAQ,CAAC;IACrD;GACF;EACF;CACF;CAEA,MAAM,oBAA+B,CAAC;CACtC,MAAM,KAAK,MAAM,CAAC,CAAC,OAAM,UAAS,kBAAkB,KAAK,KAAK,CAAC;CAC/D,MAAM,OAAO,QAAQ,CAAC,CAAC,OAAM,UAAS,kBAAkB,KAAK,KAAK,CAAC;CAEnE,IAAI,UAAU;EACZ,MAAM,WAAqB,CAAC;EAC5B,IAAI,kBAAkB,SAAS,GAAG;GAChC,MAAM,SAAS,kBAAkB,KAAI,UAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;GAC/G,SAAS,KAAK,iCAAiC,SAAS,IAAI,QAAQ;EACtE;EACA,IAAI,cAAc;GAChB,MAAM,gBAAgB,MAAM,GAAG,QAAQ,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,OAAM,UAAS,KAAc;GACzF,IAAI,yBAAyB,OAC3B,SAAS,KAAK,oCAAoC,OAAO,IAAI,cAAc,SAAS;EACxF;EACA,OAAO,GAAG;GACR,MAAM;GACN;GACA,WAAW;GACX,OAAO,MAAM,KAAI,UAAS;IAAE,MAAM,KAAK;IAAM,OAAO,KAAK,QAAQ;GAAW,EAAE;GAC9E,gBAAgB;GAChB;EACF,CAAC;CACH;CAEA,MAAM,gBAAgB,CAAC,GAAG,iBAAiB;CAC3C,MAAM,GAAG,SAAS;EAAE,WAAW;EAAM,OAAO;CAAK,CAAC,CAAC,CAAC,OAAM,UAAS,cAAc,KAAK,KAAK,CAAC;CAC5F,IAAI,aACF,MAAM,MAAM,IAAI,CAAC,CAAC,OAAM,UAAS,cAAc,KAAK,KAAK,CAAC;CAC5D,MAAM,SAAS,iBAAiB,KAAA,IAAY,gBAAgB,CAAC,cAAc,GAAG,aAAa;CAC3F,MAAM,QAAQ,OAAO,UAAU,IAAI,OAAO,KAAK,IAAI,eAAe,QAAQ,8BAA8B;CACxG,OAAO,IAAI;EAAE,MAAM;EAAmB,SAAS;EAAgB,MAAM;EAAQ;CAAM,CAAC;AACtF;AC1IA,MAAM,gBAAgB;AAGtB,MAAM,aAAa;AAGnB,MAAM,cAAc;;;;;;AASpB,SAAM,gBAAS,UAAA;CAEf,OAAM,SAAW,QAAA,aAAA,EAAA,CAAA,CAAA,MAAA,YAAA,CAAA,CAAA,KAAA,cAAA,UAAA,QAAA,OAAA,GAAA,CAAA,CAAA,KAAA,CAAA,CAAA,CAAA,QAAA,cAAA,UAAA,SAAA,CAAA;AAEjB;AAEA,MAAA,gBAAA;;;AAOA,SAAS,cAAA,OAAgB;CACvB,IAAA,MAAO,WACJ,KAAQ,KAAA,KAAA,KACR,GAAA,OAAM;CAGX,IAAA,YAAA,KAAA,KAAA,GAAA,OAAA;;;;;CAMA,IAAA,CAAM,QAAA,SAAgB,GAAA,KAAA,CAAA,cAAA,KAAA,OAAA,GAAA,OAAA;;AAGtB;AAGA,SAAM,cAAc,WAAA;;;;;AAMpB,SAAS,SAAA,WAAc,OAA8B;CACnD,IAAI,MAAM,IAAA,SAAW,GAAK,OAAK;CAG/B,MAAI,SAAA,cACF,SAAO;CAET,IAAI,OAAM,WAAS,GAAK,OAAK;CAE7B,KAAA,MAAM,QAAU,OAAM;EACtB,IAAI,KAAA,WAAQ,GAAW,UAAK,EAAQ,GAAA,OAAA;EAGpC,IAAI,SAAA,UAAkB,KAAO,WAAK,GAAA,OAAY,EAAK,GAAA,OAAO;CAG1D;CAEA,OAAO;AACT;AAGA,SAAS,kBAAc,OAA2B;CAChD,MAAM,SAAA,CAAA;CACN,MAAI,wBACK,IAAA,IAAA,CAAA,GAAA,MAAA,cAAA,GAAA,MAAA,WAAA,CAAA;CAET,MAAA,0BAD+B,IAAU,IAAA;CAE3C,KAAA,MAAA,aAAA,gBAAA,MAAA,QAAA,GAAA;EAEA,IAAA,OAAS,KAAS,SAAA,KAAmB,SAAqC,KAAA,SAAA,GAAA;EACxE,KAAI,MAAM,SAAI,UACZ,SAAO,UAAA,GAAA;GACT,MAAM,YAAS,cAAc,MAAS,EAAA,CAAA,KAAA,CAAA;GACtC,IAAI,cAAO,QACT,CAAA,SAAO,WAAA,KAAA,GAAA,QAAA,IAAA,SAAA;EACT;CAEE;CAGA,KAAI,MAAA,QAAS,CAAA,GAAA,OAAe,CAAA,CAAA,KAAA,GAAW,OAAG,KAAS,2DAC1C,KAAA,EAAA;CACX,MAAA,SAAA,CAAA,GAAA,MAAA,SAAA,SAAA,UAAA,CAAA,CAAA,CAAA,KAAA,UAAA,MAAA,EAAA;CACA,MAAA,WAAO,CAAA,GAAA,aAAA,MAAA,QAAA,GAAA,GAAA,MAAA,CAAA,CAAA,KAAA,IAAA;CACT,IAAA,CAAA,cAAA,KAAA,QAAA,GAAA,OAAA,KAAA,yEAAA;;;;;;;;;CAoBA;AACE,CAAA;AACA,MAAA,WAAM,WAAA,IAAQ;CACd,MAAM;CAEN,SAAK;CACH;AAEA,CAAA;AACE,SAAM,WAAA,SAAY;CAClB,IAAA;EAEF,OAAA,IAAA,YAAA,SAAA,EAAA,OAAA,KAAA,CAAA,CAAA,CAAA,OAAA,OAAA;CACF,QAAA;EAEA,OAAK;CAGL;AACA;AACA,MAAK,eAAc,UAAK,UACtB,QAAY,OAAA,UAAA,YAAA,CAAA,MAAA,QAAA,KAAA,KAAA,OAAA,OAAA,KAAyE,CAAA,CAAA,OAAA,SAAA,OAAA,SAAA,QAAA;AAEvF,MAAA,0BAAO,MAAA,OAAA,YAAA;CACT,MAAA,SAAA,CAAA;;CCtIA,IAAA,WAAM,WAAA,GAAA,OAAA,QAAqB,CAAA,gDAAQ,CAAA;CACjC,MAAA,SAAA,WAAA,WAAA,EAAA,CAAA,OAAA;CACA,IAAA,WAAA,MAAA,OAAA,QAAA,CAAA,yCAAA,CAAA;CACA,IAAA,YAAA,KAAA,GAAA,OAAA,KAAA,GAAA,kBAAA;EACA,UAAA;EACA,cAAA;EACA,aAAA,MAAA,KAAA,SAAA,KAAA,IAAA;CACD,CAAA,CAAA;CAED,MAAM,QAAA,OAAW,MACf,4CAAI;CAAE,IAAA,CAAA,OAAM,OAAA,QAAA,CAAA,4CAAA,CAAA;CAAgB,IAAA,MAAS,EAAA,EAAA,KAAA,CAAA,CAAA,WAAA,GAAA,OAAA,KAAA,0CAAA;CAA6C,MAAA,WAAA,cAAA,MAAA,IAAA,EAAA,YAAA,KAAA,CAAA;CAAQ,KAAA,MAAA,SAAA,SAAA,QAAA,OAAA,KAAA,gBAAA,MAAA,SAAA;CAE5F,KAAA,MAAS,WAAW,SAAoC,UAAA,OAAA,KAAA,gBAAA,QAAA,SAAA;CACtD,MAAI,QAAA,SAAA,OAAA,WAAA,IAAA,SAAA,KAAA,IAAA;CACF,IAAA,CAAA,SAAW,OAAA,UAAY,YAAkB,MAAO,QAAQ,KAAA,GAAO;EACjE,OACM,KAAA,gCAAA;EACJ,OAAO,QAAA,MAAA;CACT;CACF,MAAA,cAAA;CAEA,KAAM,MAAA,OAAA,OAAe,KACnB,WAAU,GAAA,IACP,CAAA,mBAAiB,IAAA,GAAA,GAChB,OAAM,KAAA,uCACc,KAAM;CAEhC,IAAA,YAAa,SAAA,MACX,OACA,KAAA,uDAEgC;CAChC,IAAA,OAAM,YAAoB,SAAA,YAAA,CAAA,YAAA,YAAA,IAAA,GAAA,OAAA,KAAA,8BAAA;CAC1B,IAAA,OAAM,YAAa,gBAAa,YAAa,YAAS,YAAU,KAAA,CAAA,CAAA,WAAA,KAAA,YAAA,YAAA,SAAA,MAAA,OAAA,KAAA,4DAAA;CAChE,IAAI,YAAW,YAAW,KACxB,KAAO,OAAS,YAAA,YAAA,UAAA,OAAA,KAAA,uCAAiD;CAEnE,IAAA,YAAe,kBAAW,KAAa,MAAE,OAAO,YAAA,kBAAA,YAAA,YAAA,cAAA,SAAA,MAAA,OAAA,KAAA,uEAAA;CAChD,IAAI,YAAW,aACN,KAAA,KAAS,CAAA,YAAA,YAAA,QAAA,GAAA,OAA0C,KAAA,mDAAA;CAC5D,IAAI,YAAY,qBACF,KAAG,KAAA,OAAA,YAAkB,qBAAA,UAAA,OAAA,KAAA,6CAAA;CAC/B,OAAA,OAAU,WAAA,IAAA,GAAA,KAAA,CAAA,IAAA,QAAA,MAAA;AACV;AACA,MAAA,gCAA+B,IAAK,IAAI;CAC1C;CAEF;CACA;AAEA,CAAA;AAGA,MAAA,uBAAiB,UAAoB;CACrC,IAAA,MAAK,WAAe,KAAA,MAAS,EAAA,EAAA,SACpB,eAAK,OAAgB,QAAM,CAAA,8CAAS,CAAA;CAC7C,IAAA;CAGA,IAAA;EACA,MAAK,SAAS,WAAO,MAAU,EAAA,CAAA,OAAY;EACzC,IAAA,WAAY,MAAA,OAAA,QAAA,CAAA,4CAAgC,CAAA;EAC5C,QAAO,KAAA,MAAQ,MAAM;CACvB,QAAA;EAEA,OAAM,QAAA,CAAA,sCAAc,CAAA;CACpB;CAIA,IAAI,CAAA,SAAA,OAAY,UACd,YAAY,MAAA,QAAA,KAAA,GAAA,OAAA,QAAA,CAAA,qCAAuD,CAAA;CACrE,MAAI,SAAO;CAEX,IAAI,OAAO,KAAA,MAAA,CAAY,CAAA,MAAA,QAAA,QAAgB,aAAY,QAAY,UAAY,GAAK,OAAE,QAAW,CAAA,0CAC3F,CAAA;CACF,IAAI,OAAA,OAAY,YAAY,YAAa,OAAO,QAAY,KAAA,CAAA,CAAA,WAAY,GAAA,OACtE,QAAY,CAAA,6BAAA,CAAA;CACd,IAAI,CAAA,MAAA,QAAY,OAAA,QAAkB,GAAA,OAAA,QAAqB,CAAA,mCAA8B,CAAA;CAErF,MAAI,WAAY,CAAA;CAEhB,KAAI,MAAA,QAAY,OAAA,UAAA;EAGhB,IAAA,CAAA,QAAc,OAAA,SAAe,YAAgB,MAAA,QAAc,IAAA,GAAA,OAAA,QAAA,CAAA,wCAAA,CAAA;EAC7D,MAAA,UAAA;EAEA,IAAM,OAAA,KAAA,OAAA,CAAA,CAAA,MAAA,QAAgB,CAAI;GAAK;GAAS;GAAW;GAAO;EAE1D,CAAA,CAAA,SAAa,GAAA,CAAA,GAAA,OAAA,QACX,CAAA,+CACuC,CAAA;EACvC,IAAI,OAAM,QAAA,UAAgB,YAAU,CAAA,cAAS,IAC3C,QAAO,KAAA,GAAS,OAAA,QAAA,CAAA,oCAA+C,CAAA;EAEjE,IAAI,OAAA,QAAA,SAAA,YAAA,oBAAA,QAAA,IAAA,MAAA,MAAA,OAAA,QAAA,CAAA,mCAAA,CAAA;EACJ,IAAI,OAAA,QAAA,YAAA,YAAA,QAAA,QAAA,KAAA,CAAA,CAAA,WAAA,KAAA,OAAA,QAAA,QAAA,YAAA,QAAA,IAAA,KAAA,CAAA,CAAA,WAAA,GAAA,OAAA,QAAA,CAAA,iCAAA,CAAA;EACF,SAAM,KAAA,OAAS;CACf;CAEA,OAAA,GAAQ;EACV,MAAA;EAEE,SAAO,OAAS;EAClB;CACA,CAAA;AAGA;AAGA,MAAI,+BAA0B,IAAA,IAAY;CAE1C;CAGA;CACA;CACE;CAEA;CACA;CAAuC;CAAS;CAAQ;CAAW;CAAK;AAExE,CAAA;AAEA,eAAW,qBAAiB,WAAY,QAAA,cAAoB,WAAkB,QAC5E;CACF,MAAI,OAAO,QAAQ,SAAA;CAEnB,MAAA,eAAc,SAAwC,UAAA,IAAA;EACxD,MAAA;EAEA;EAAY,UAAM,CAAA;GAAe,QAAS;GAAgB,QAAA;GAAU,QAAA;EACtE,CAAA;;CCzHA,CAAA;CACE,MAAA,kBAAA,IAAA;EACA,MAAA;EACA,SAAA;CACA,CAAA;CACA,IAAA,QAAA,SAAA,OAAA,UAAA;CACA,MAAA,WAAA,MAAA,MAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CACA,IAAA,oBAAA,OAAA,OAAA,YAAA,oCAAA,QAAA;CACA,IAAA,CAAA,SAAA,YAAA,KAAA,SAAA,eAAA,GAAA,OAAA,YAAA,uDAAA;CACA,MAAA,gBAAA,MAAA,SAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CACA,IAAA,yBAAA,OAAA,OAAA,YAAA,wCAAA,aAAA;CACA,IAAA,kBAAA,MAAA,OAAA,YAAA,oDAAA;CACD,MAAA,QAAA,CAAA;CAED,IAAA,aAAsB;CACpB,MAAM,OAAO,OAAA,YAAiB;EAC9B,IAAA,QAAM,SAAe,OAAA,UAAiB;EACpC,MAAM,mBAAA,MAAA,SAAA,OAAA,CAAA,CAAA,OAAA,UAAA,KAAA;EACN,IAAA,4BAAA,SAAA,qBAAA,SAAA,OAAA,YAAA,+CAAA,4BAAA,QAAA,mBAAA,KAAA,CAAA;EACA,MAAA,kBAAW,MAAA,QAAA,OAAA,CAAA,CAAA,OAAA,UAAA,KAAA;EAAE,IAAA,2BAAQ,OAAA,OAAA,YAAA,oCAAA,eAAA;EAAa,WAAQ,MAAA,SAAA,iBAAA;GAAW,IAAA,QAAQ,SAAA,OAAA,UAAA;GAAS,IAAA,aAAA,IAAA,MAAA,IAAA,GAAA;GACtE,MAAA,WAAA,KAAA,SAAA,MAAA,IAAA;GACD,MAAA,OAAA,MAAA,MAAA,QAAA,CAAA,CAAA,OAAA,UAAA,KAAA;GACD,IAAM,gBAAA,OAAoD,OAAA,YAAA,gCAAA,IAAA;GAAE,IAAA,KAAM,eAAA,GAAA,OAAA,YAAA,kCAAA;GAAa,IAAA,KAAS,YAAA,GAAA;IAA4B,MAAA,SAAA,MAAA,KAAA,QAAA;IACpH,IAAI,OAAQ,SACV,OAAO,OAAA;IACT;GACA;GAEA,IAAK,CAAA,KAAA,OAAS,GAAA,OAAY,YAAc,iCAC/B;GACT,MAAM,OAAA,SAAgB,MAAM,QAAS,CAAA,CAAA,MAAM,GAAA,CAAM,CAAA,KAAA,GAAA;GACjD,MAAI,SAAA,MAAA,KAAA,UACF,UAAO,WAAY,UAAA,UAAA,CAAA,CAAA,OAAA,UAAwC,KAAA;GAC7D,IAAI,kBAAkB,OACpB,OAAO,YAAY,yDAAoD,MAAA;GAEzE,MAAM,aAAyB,MAAA,OAAA,KAAA,CAAA,CAAA,OAAA,UAAA,KAAA;GAC/B,IAAI,sBAAa,OAAA;IAEjB,MAAM,OAAO,MAAO;IAClB,OAAI,YACF,oCAAiB,UAAA;GACnB;GACA,IAAI,CAAA,WAAA,OAAA,KAAA,WAA4B,QAAS,KAAA,OAAA,WACvC,QAAO,KAAA,KAAA;IACT,MAAM,OAAA,MAAA;IACN,OAAI,YAAA,wCACiB;GAErB;GACE,IAAI,WAAQ,OACV,OAAO,oBAAU;IACnB,MAAI,OAAA,MAAa;IAEjB;GACA;GACA,IAAI,MAAA,UAAgB,OAClB,gBAAO;IACT,MAAI,OAAK,MAAA;IAET,OAAI,YAAK,iCAAe;GACtB;GACA,IAAA,aAAW,WACT,OAAO,OAAA,gBAAA;IACT,MAAA,OAAA,MAAA;IACF,OAAA,YAAA,sCAAA;GACA;GAGA,MAAM,UAAO,MAAS,OAAM,SAAU,CAAA,CAAA,OAAS,UAAU,KAAA;GACzD,MAAM,OAAA,MAAS;GACf,IAAI,mBAAkB,OACpB,OAAO,YAAY,+BAAA,OAAA;GACrB,IAAA,QAAM,eAAmB,WAAa,MAAC,OAAM,YAAuC,wCAAA;GACpF,IAAI,QAAA,SAAA,OAAsB,UAAO;GAC/B,MAAA,KAAM;IACN;IACF;GACA,CAAA;GACE,cAAa,QAAM;EACnB;EACF,OAAA,GAAA,KAAA,CAAA;CACA;CACE,MAAA,SAAM,MAAO,KAAM,IAAA;CACnB,IAAA,OAAA,SAAA,OAAA,OAAA;CACF,IAAA,MAAA,WAAA,GAAA,OAAA,YAAA,uCAAA;CACA,MAAI,MAAM,MAAA,UAAU,KAAO,KAAA,cAAgB,MAAA,IAAA,CAAA;CACzC,OAAA,GAAM;EACN;EACF,UAAA,CAAA;GACA,QAAI;GACF,QAAM;EACN,CAAA;CACF,CAAA;AAEA;AAEA,MAAA,aAAI;AAEJ,SAAI,cAAQ,SAAe,OAAA;CAE3B,OAAI,IAAA;EAEJ,MAAA;EAAa;EAAM,UAAA,CAAA;EAAQ;CAC3B,CAAA;AACF;AACA,SAAO,WAAY,QAAA,OAAA,QAAA;CACrB,MAAA,QAAA,OAAA,SAAA,OAAA,QAAA,MAAA;CAEA,MAAM,OAAA,MAAS,QAAW,CAAA;CAC1B,OAAI,OAAO,KAAA,SACT,KAAA,QAAO,MAAA,SAAA,GAAA,IAAA,CAAA,CAAA,CAAA,SAAA,MAAA,CAAA,CAAA,KAAA;AACT;AAGA,SAAM,UAAY,QAAA,OAAe,QAAK;CACtC,MAAA,QAAU,WAAA,QAAA,OAAA,MAAA,CAAA,CAAA,QAAA,cAAA,EAAA;CAAE,IAAA,CAAA,WAAA,KAAA,KAAA,GAAA,OAAA;CAAO,MAAA,SAAW,OAAA,SAAA,OAAA,CAAA;CAAE,OAAA,OAAQ,cAAA,MAAA,IAAA,SAAA;AAAa;AAAe,SAAC,iBAAA,QAAA;CAAE,MAAC,WAAA,UAAA,QAAA,KAAA,CAAA;CAC1E,IAAA,aAAA,MAAA,OAAA;;CClIA,KAAM,IAAA,QAAA,GAAa,QAAA,OAAA,YAAA,SAAA,GAAA,UAAA,SAAA,OAAA,QAAA,MAAA,KAAA,OAAA;CAcnB,OAAA,WAASC;AACP;AAAa,SAAM,aAAA,SAAA;CAAqB,MAAA,OAAA,OAAA,KAAA,OAAA,CAAA,CAAA,SAAA,MAAA;CAAS,IAAA,SAAW;CAAG,IAAA,OAAA;CAAM,OAAC,SAAA,KAAA,QAAA;EACxE,MAAA,QAAA,KAAA,QAAA,KAAA,MAAA;EAEA,IAAA,UAAS,IAAW,OAAA;EAClB,MAAM,SAAQ,OAAO,SAAS,KAAO,MAAA,QAAc,KAAA,GAAA,EAAA;EACnD,IAAA,CAAM,OAAO,cAAc,MAAC,KAAA,UAAA,KAAA,SAAA,SAAA,KAAA,QAAA,OAAA;EAC5B,MAAO,SAAO,KAAK,MAAA,QAAc,GAAA,SAAc,SAAS,CAAA;EAC1D,MAAA,SAAA,OAAA,QAAA,GAAA;EAEA,IAAA,WAAS,MAAU,OAAoB,MAAe,GAAA,MAA+B,MAAA,QAAA,OAAA,OAAA,MAAA,SAAA,CAAA;EACnF,UAAM;CACN;CAEA,OAAM;AACN;AACF,SAAA,YAAA,OAAA,QAAA;CAEA,MAAA,aAAS,oBAA8C,KAAA;CACrD,IAAA,eAAiB,MAAA,OAAU;CAC3B,MAAI,WAAa,WACf,MAAO,GAAA;CACT,IAAI,WAAS,OACb;MAAK,SAAI,OAAW,aAAQ,SAAO,SAAY,GAAA,OAC7C;CAAA,OACK,IAAA,SAAW,SAAA,GAAA,OAAA;CACpB,OAAA,oBAAA,SAAA,MAAA,CAAA,CAAA,CAAA,KAAA,GAAA,CAAA;AAEA;AACE,SAAM,aAAc,OAAK;CACzB,OAAI,MAAS,OAAA,WAAA,IAAA,MAAA,OAAA,KAAA,OAAA,OAAA,MAAA,QAAA,MAAA,IAAA;AACb;AACA,eAAO,eAAsB,YAAA,QAAA,QAAA;CAC3B,MAAA,SAAc,SAAK,KAAQ,UAAW;CACtC,MAAI,SAAU,aACL;CACT,OAAM,GAAA,UAAS,UAAO,OAAc,QAAM,KAAA,CAAQ;CAClD,OAAK,KAAA,MAAO;CAEZ,MAAA,QAAM,CAAA;CACN,MAAA,uBAAsB,IAAQ,IAAG;CACjC,MAAI,kBAAiB,OAAO,kBAAe,OAAM,iBACjC,KAAM,aAAU;CAChC,IAAA,eAAU;CACZ,IAAA,cAAA;CACA,IAAA,WAAO;CACT,IAAA,UAAA,OAAA,MAAA,CAAA;CAEA,IAAA,QAAS;CACP,IAAA,aAAM;CACN,IAAI,QAAA;CAEJ,IAAA;EACA,WAAI,MAAW,SACb,QAAA;GAAI,MAAA,QAAS,OAAO,SAAA,KAAa,IAAA,QAAS,OACxC,KAAA,KAAO;GAAG,gBAEL,MAAS;GAGlB,IAAA,eAAO,iBAA6B,OAAS,cAAS,qDAAA;GACxD,UAAA,QAAA,eAAA,IAAA,QAAA,OAAA,OAAA,CAAA,SAAA,KAAA,CAAA;GAEA,OAAS,QAAA,aAA2D,GAAA;IAClE,IAAO,OAAM;KAGf,IAAA,QAAA,MAAA,SAAA,SAAA,CAAA,GAAA,OAAA,cAAA,+CAAA;KAEA,UAAsB,OAAA,MAAA,CAAA;KAKpB;IACA;IACA,IAAO,UAAG,MAAS;KACnB,IAAO,MAAK,YAAM,GAAA;MAClB,MAAM,WAAyB,KAAA,IAAA,MAAA,WAAA,QAAA,UAAA;MAC/B,IAAM,MAAA,SAAA,UAAW,MAAY,SAAA,YAAA,MAAA,OAAA,KAAA,QAAA,SAAA,GAAA,QAAA,CAAA;MAC7B,UAAM,QAAA,SAAyB,QAAA;MAC3B,MAAA,aAAe;MACf,IAAA,MAAA,YAAc,GAAA;KACd;KACA,IAAA,MAAmC,UAAO,GAAM;MAChD,MAAA,WAA6B,KAAA,IAAA,MAAA,SAAA,QAAA,UAAA;MAC7B,UAAA,QAAa,SAAA,QAAA;MACb,MAAA,WAAQ;MAER,IAAA,MAAA,UAAA,GAAA;KACF;KACE,IAAM,MAAA,SAAe,YAAS;MAC9B,MAAA,UAAgB,aAAM,KAAA;MACtB,WAAI,MAAe,iBACjB,QAAOA,aAAY,OAAA,IAAA,QAAA,SAAA,MAAA,CAAA,CAAA,QAAA,UAAqD,EAAA,CAAA,CAAA,KAAA;MAC1E,IAAA,aAAkB,QAAA,SAAmB,WAAQ,GAAA,OAAO,cAAiB,2CAAM;KAE3E,OAAO,IAAA,MAAQ,SAAa,UAAG,MAAA,MAAA;MAC7B,MAAI,KAAO;OACT,MAAI,MAAQ;OAEZ,SAAU,WAAO,KAAO,aAAA,KAAA,CAAA;MACxB,CAAA;MACF,cAAA,MAAA;KAEA;KACE,QAAI;KACF;IACA;IAEA,IAAA,QAAU,aAAQ,YAAiB;IACnC,MAAA,SAAM,QAAa,SAAA,GAAA,UAAA;IACnB,UAAI,QAAM,SACR,UAAA;IACJ,IAAA,OAAA,OAAA,SAAA,SAAA,CAAA,GAAA;KACA,QAAI;KACF;IACA;IACA,IAAA,CAAA,iBAAiB,MAAA,GAAA,OAAA,cAAA,gDAAA;IACjB,MAAI,OAAM,UAAU,QAClB,KAAA,EAAA;IACJ,IAAA,SAAA,MAAA,OAAA,cAAA,2CAAA;IAEA,MAAI,OAAM,WAAS,QAAY,GAAA,GAAA;IAC7B,MAAA,SAAM,WAAU,QAAa,KAAK,GAAA;IAClC,MAAA,aAAiB,OAAA,SAAA,IAAiB,GAAA,OAC9B,GAAA,SAAa;IAEjB,MAAI,OAAA,OAAa,aAAQ,OAAS,QAAW,CAAA;IAE/C,MAAA,WACS,aAAe,OAAU,cAAY;IAC5C,IAAA,SAAW,OAAA,SAAA,KAAA;KAAE,IAAA,OAAM,OAAM,oBAAA,OAAA,cAAA,2DAAA;KAAM,QAAA;MAA8C,MAAC;MAC9E,cAAc,SAAM,MAAA,QAAA;MACtB;MACA,WAAQ;MACR;MACF,QAAA,CAAA;KAEA;KAEA;IACA;IACA,IAAI,SAAO,KAAM;KACf,WAAQ;KACR,QAAA;MACF,MAAA;MACA;MAGA,WAAa;MACb;MAEA,QAAM,CAAA;KACN;KACA;IACA;IACA,IAAA,SAAM,OAAW,SAAA,MAAa,OAAO,cAAc,oDAAA;IAEnD,MAAI,OAAS,YAAO,YAAc,YAAA,MAAA;IAChC,WAAI;IAEJ,IAAA,SAAQ,MAAA,OAAA,cAAA,0CAAA;IACN,IAAA,KAAM,IAAA,IAAA,GAAA,OAAA,cAAA,0CAAA;IACN,KAAA,IAAA,IAAA;IACA,eAAA;IACA,IAAA,cAAW,OAAA,gBAAA,OAAA,cAAA,yCAAA;IACX,IAAA,QAAA,OAAA,sBAAA,aAAA,OAAA,OAAA,gBAAA,OAAA,cAAA,8CAAA;IACA,QAAA;KACF,MAAA,OAAA,OAAA,qBAAA,SAAA;KACA;KACF;KACA,WAAI;KACF;KACA,QAAQ,CAAA;IAAE;GAAmB;EAAM;CAAiB,SAAA,OAAA;EAAS,MAAA,UAAS,iBAAA,QAAA,MAAA,UAAA;EAAE,OAAA,cAAA,QAAA,WAAA,iBAAA,IAAA,UAAA,0CAAA,KAAA;CACxE;CACF,IAAA,UAAA,QAAA,QAAA,MAAA,SAAA,SAAA,CAAA,KAAA,CAAA,OAAA,OAAA,cAAA,8CAAA;CACA,IAAA,MAAI,WAAS,GAAO,OAAA,cACXA,qCAAY;CAErB,MAAA,MAAM,MAAO,UAAY,KAAA,KAAA,cAAwB,MAAM,IAAA,CAAA;CACvD,OAAA,GAAA,KAAW;AACX;AAIA,MAAA,qBAAa;AACb,MAAA,sBAAe;AACf,MAAA,mBAAkB;AAElB,MAAA,sBAAmB;AAGnB,MAAA,mBAAQ;AACN,MAAA,qBAAoB;AACpB,SAAA,YAAA,SAAA,UAAA,OAAA;CACA,OAAA,IAAA;EACA,MAAA;EACA;EACA;EACF;CACF,CAAA;AACF;AACF,SAAA,iBACc,MAAA;CACZ,MAAA,QAAM,KAAU,MAAA,kBAAyB;CACzC,OAAA,QAAOA,KAAAA;EAGT,MAAA,MAAA;EAEA,SAAI,MAAU,MAAQ;CAEtB,IAAI;AAEJ;AACA,SAAO,SAAQ,OAAA;CACjB,OAAA,OAAA,UAAA,YAAA,UAAA,QAAA,CAAA,MAAA,QAAA,KAAA;;AC/MA,SAAM,gBAAA,OAAqB;CAC3B,IAAA,OAAM,UAAA,UAAsB,OAAA;CAC5B,IAAA,CAAM,SAAA,KAAA,GAAA,OAAmB,KAAA;CACzB,OAAM;EACN,MAAM,OAAA,MAAA,SAAmB,WAAA,MAAA,OAAA,KAAA;EACzB,KAAM,OAAA,MAAA,QAAqB,WAAA,MAAA,MAAA,KAAA;CAI3B;AACE;AAAa,SAAM,aAAA,WAAA,WAAA;CAAqB,IAAA,CAAA,SAAA,SAAA,KAAA,CAAA,SAAA,UAAA,YAAA,KAAA,CAAA,SAAA,UAAA,QAAA,GAAA,OAAA;CAAS,MAAA,SAAA,UAAA,YAAA,CAAA;CAAU,MAAA,kBAAA,OAAA,WAAA,WAAA,SAAA;CAAM,MAAC,QAAA,UAAA,SAAA;CACpE,IAAA,CAAA,SAAA,KAAA,KAAA,OAAA,MAAA,YAAA,YAAA,CAAA,SAAA,MAAA,IAAA,KAAA,OAAA,MAAA,KAAA,YAAA,UAAA,OAAA;CAEA,OAAA;EACE;EACA,YAAO,gBAAa,UAAA,UAAA;EAAE,SAAM;GAAU,SAAS,MAAM;GAAe,SAAI,OAAA,MAAA,YAAA,WAAA,MAAA,UAAA,KAAA;GAC1E,YAAA,gBAAA,MAAA,UAAA;GAEA,MAAS;IACP,SAAO,MAAO,KAAA;IAChB,WAAA,OAAA,MAAA,KAAA,cAAA,WAAA,MAAA,KAAA,YAAA,KAAA;IAEA,QAAS,OAAA,MAAgB,KAAA,WAAoD,WAAA,MAAA,KAAA,SAAA,KAAA;GAC3E;EAEA;CAEA;AACE;AACA,eAAY,WAAM,UAAQ;CAC5B,IAAA,CAAA,SAAA,MAAA;CACF,MAAA,SAAA,KAAA,OAAA,CAAA,CAAA,YAAA,KAAA,CAAA;AAEA;AACE,SAAK,cAAS,UAAe;CAE7B,MAAM,QAAA,SAAS,QAAU,IAAA,gBAAa;CACtC,IAAA,UAAM,QAAA,CAAA,QAAyB,KAAA,KAAA,GAAW,OAAA;CAC1C,MAAM,QAAQ,OAAA,KAAU;CACxB,OAAK,OAAS,cAAU,KAAO,IAAM,QAAA;AAErC;AACE,gBAAA,eAAA,UAAA,UAAA,cAAA,gBAAA,CAAA,GAAA;CACA,MAAA,WAAY,cAAgB,QAAU;CACtC,IAAA,aAAS,QAAA,WAAA,UAAA;EACP,MAAA,WAAe,QAAA;EACf,MAAA,IAAS,MAAA,YAAa;CACtB;CACA,IAAA,CAAA,SAAM,MAAA;CACJ,MAAA,SAAS,SAAW,KAAA,UAAA;CACpB,IAAA,WAAW;CACX,IAAA,aAAQ;CACV,IAAA;EACF,OAAA,MAAA;GACF,MAAA,SAAA,MAAA,OAAA,KAAA;GACF,IAAA,OAAA,MAAA;IAEA,WAAe;IACb;GAGA;GACF,cAAA,OAAA,MAAA;GAEA,IAAA,aAAS,UAAc,MAAmC,IAAA,MAAA,YAAA;GACxD,QAAM,OAAQ,KAAA;GACd,MAAI,OAAU;EAEd;CACA,UAAO;EACT,IAAA,CAAA,UAAA,MAAA,OAAA,OAAA,CAAA,CAAA,YAAA,KAAA,CAAA;EAEA,OAAA,YAAgB;CAMd;AACA;AACE,eAAM,oBAAmB,UAAA,UAAA;CACzB,MAAA,SAAU,CAAA;CACZ,IAAA,aAAA;CACA,IAAI;EAGJ,WAAM,MAAS,SAAS,eAAe,UAAA,UAAA,sCAAA,GAAA;GACvC,OAAI,KAAA,KAAW;GACf,cAAI,MAAa;EACjB;CACE,SAAO,OAAM;EACX,OAAM,YAAS,iBAAkB,QAAA,MAAA,UAAA,gCAAA,CAAA,GAAA,KAAA;CACjC;CACE,OAAA,GAAA,WAAW,KAAA,OAAA,OAAA,QAAA,UAAA,CAAA,CAAA;AACX;AACF,eAAA,mBAAA,aAAA,KAAA,OAAA,CAAA,GAAA,QAAA;CACA,MAAA,UAAc,YAAO,QAAM,mBAAA;CAC3B,MAAI,gBAAa,SACf,YAAU,IAAM,CAAA,QAAA,OAAY,CAAA,IAAA;CAC9B,IAAA,UAAQ;CACR,KAAA,IAAM,YAAO,GAAA,aAAA,kBAAA,aAAA,GAAA;EACf,MAAA,WAAA,MAAA,YAAA,SAAA;GACF,GAAA;GAEE,UAAK;GAIL,QAAO;EACT,CAAA,CAAA,CAAA,OAAA,UAAA,KAAA;EACF,IAAA,oBAAA,OAAA,OAAA,YAAA,QAAA,UAAA,2BAAA,uBAAA,CAAA,GAAA,QAAA;EAEA,IAAA,CAAA;GACE;GACA;GACA;GACE;GACE;EACA,CAAA,CAAA,SAAA,SAAc,MAAM,GAAA,OAAA,GAAA,QAAA;EACtB,IAAA,cAAA,kBAAA;GACF,MAAA,WACc,QAAA;GACZ,OAAO,YAAY,4CAAyC,CAAA,CAAA;EAC9D;EACA,MAAO,WAAG,SAAgB,QAAO,IAAA,UAAe;EAClD,IAAA,CAAA,UAAA;GAEA,MAAA,WAAe,QAAA;GACb,OAAM,YAAU,yCAAuC,CAAA,CAAA;EACvD;EACA,MAAI,aAAU,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,IAAA,IAAA,UAAA,OAAA,CAAA,CAAA,CAAA,YAAA,IAAA;EACd,IAAK,eAAI,MAAe;GACtB,MAAM,WAAW,QAAM;GAAuB,OAAG,YAAA,qCAAA,CAAA,CAAA;EAAM;EAAoB,IAAA,WAAQ,aAAA,UAAA;GAAe,MAAE,WAAM,QAAuB;GACjI,OAAI,YAAA,oCACiB,CAAA,CAAQ;EAC7B;EAAM,MAAA,WAAA,QAAA;EAAK,UAAA,WAAA;CAAK;CAAK,OAAA,YAAA,4CAAA,CAAA,CAAA;AAAK;AAAG,SAAE,wBAC7B,MAAO;CACT,MAAI,SAAA,KAAc,WAAA,MAAkB,KAAA,CAAA,CAAA,OAAA,OAAA,KAAA,CAAA;CAClC,IAAA,WAAM,OAAW,SAAQ,UAAA;EACzB,MAAA,QAAO,MAAY,MAAA,4CAA8C;EACnE,OAAA,QAAA,MAAA,MAAA,KAAA,CAAA;GACA,WAAM,MAAW;GACjB,QAAK,MAAU;EACb,CAAA,IAAA,CAAA;CACA,CAAA;CACF,IAAA,SAAA,SAAA,GAAA;EACA,MAAM,WAAA;GACN,MAAI;GACF,QAAM;GACN,QAAO;GACT,QAAA;EACA;EACE,MAAA,YAAiB,KAAA,IAAQ,GAAA,SAAA,KAAA,UAAA,SAAA,MAAA,UAAA,CAAA;EACzB,WAAO,SAAY,QAAA,UAAA,SAAA,MAAA,eAAsC,SAAA;CAC3D;CACA,IAAA,OAAM,WAAW,KAAQ,KAAA,UAAA,kBAAA,KAAA,KAAA,MAAA,GAAA,SAAA,KAAA;EACzB,WAAU;EACZ,QAAA,OAAA,KAAA,KAAA,QAAA,KAAA,CAAA,CAAA,SAAA,QAAA;CACA,CAAA;CACF,IAAA,SAAA,WAAA,GAAA,OAAA;CAEA,MAAA,yBAAS,IAAwB,IAAyC;CACxE,KAAA,MAAM,SAAc,UAAA,OAAiB,IAAA,MAAO,WAAc,WAAM,MAAA,SAAA,CAAA;CAChE,OAAI;EACF,OAAM,SAAQ;GACd,KAAA,MAAO,QAAQ,OAAY,OAAM,GAAA,KAAA,OAAA,OAAA;EAAE;EAAqB,QAAA;GAAkB,MAAK,SAAA,IAAA,IAAA,CAAA,GAAA,MAAA,CAAA,CAAA,KAAA,CAAA,WAAA,UAAA,CAAA,WAAA,KAAA,OAAA,QAAA,CAAA,CAAA,CAAA;GAChF,OAAA,SAAA,MAAA,UAAA,OAAA,IAAA,MAAA,SAAA,MAAA,MAAA,MAAA;EACD;CACE;AAAmB;AAAS,SAAA,cAAQ,YAAA;CAAG,IAAA,OAAQ,eAAA,UAAA,OAAA;CAAG,OAAA,OAAQ,YAAA,QAAA,WAAA,WAAA,MAAA;AAAE;AAC5D,SAAM,iBAAiB,YAAO,SAAa;CAC3C,IAAA,CAAA,WAAW,CAAA,iBAAgB,KAAS,OAAA,GAAS,OAAM;CACrD,MAAA,SAAA,cAAA,UAAA;CACA,IAAI,WAAO,MAAA,OAAgB;CACT,MAAA,QAAW,OAAA,MAAA,4HAAA;CAAQ,IAAA,CAAA,QAAQ,MAAO,CAAA,MAAU,IAAA,OAAQ;CAA0B,OAAC,+BAAA,mBAAA,MAAA,EAAA,EAAA,GAAA,mBAAA,MAAA,EAAA,EAAA,UAAA;AACjG;AAGA,SAAM,QAAA,QAAA,QAAS;CACf,OAAK;EAEL;EACE,QAAO;EACL;CAEF;AACA;AACE,SAAM,KAAA,QAAa;CACnB,OAAA;EACF;EACF,QAAA;CACF;AAEA;AACE,SAAI,aAAO,OAAe,UACxB;CACF,OAAO,MAAA,SAAO,sBAAoB,YAAsB,MAAM,SAAA,UAAA,MAAA,KAAA,IAAA,IAAA,KAAA;AAChE;AAEA,SAAS,gBAAA,QAAiB,OAAgD;CACxE,MAAK,YAAY,MAAA,QAAA,OAAsB,SAAO,QACrC,KAAA,QAAA,YAAA,CAAA;CACT,MAAM,iBAAS,OAAc,iBAAU,MAAA;CACvC,MAAI,iBACF,OAAO,iBAAA;CACT,IAAA,kBAAqB,KAAM,kBAAA,GAAA,OAAA;CAC3B,OAAK;EAEL,GAAA;EACF;EAEA;CACE;AAAS;AAAQ,eAAQ,gBAAA,UAAA,QAAA,QAAA,UAAA;CAAW,OAAA,eAAA,eAAA,UAAA,OAAA,gBAAA,sDAAA,YAAA,UAAA,OAAA,OAAA,CAAA,GAAA,QAAA,MAAA;AAAO;AAC7C,eAAA,kBAAA,MAAA,QAAA,aAAA,QAAA;CAEA,MAAA,SAAc,iBAA+B,IAAA;CAC3C,IAAA,WAAO,MAAA,OAAA,YAAA,gCAAA,CAAA,CAAA;CAAE,MAAA,WAAA,CAAA;CAAQ,MAAA,cAAQ,8BAAA,mBAAA,OAAA,IAAA;CAAO,MAAA,mBAAA,MAAA,mBAAA,aAAA,aAAA,EAAA,SAAA,EAAA,QAAA,sCAAA,EAAA,GAAA,MAAA;CAClC,IAAA,iBAAA,SAAA,OAAA,OAAA,aAAA,iBAAA,OAAA,CAAA,QAAA,aAAA,iBAAA,MAAA,OAAA,CAAA,CAAA;CAEA,MAAA,WAAS,iBAAmC;CAC1C,IAAA,CAAA,SAAa,IAAA;EAGf,MAAA,WAAA,QAAA;EAEA,MAAA,UAAS,8BAAyG,SAAA,OAAA;EAChH,OAAM,YAAY,SAAM,CAAA,QAAQ,aAAgB,OAAQ,CAAA,CAAA;CACxD;CACA,MAAM,iBAAiB,MAAA,oBAAwB,UAAA,kBAAA;CAC/C,IAAI,eAAA,SAAuB,OAAA,OAAA,aAClB,eAAA,OAAA,CAAA,QAAA,aAAA,eAAA,MAAA,OAAA,CAAA,CAAA;CACT,IAAA;CAAS,IAAG;EAAQ,YAAA,KAAA,MAAA,OAAA,KAAA,eAAA,KAAA,CAAA,CAAA,SAAA,MAAA,CAAA;CAAgB,SAAA,OAAA;EAAe,MAAA,UAAA;EACrD,OAAA,YAAA,SAAA,CAAA,QAAA,aAAA,OAAA,CAAA,GAAA,KAAA;CAEA;CAME,MAAA,aAAO,aACL,WACE,OACA,OAAO;CAOb,IAAA,eAAA,QAAA,CAAA,oBAAA,KAAA,WAAA,eAAA,KAAA,WAAA,QAAA,YAAA,WAAA,iBAAA;EAEA,MAAA,UAAsB;EACpB,OAAM,YAAS,SAAA,CAAA,QAAqB,aAAA,OAAA,CAAA,CAAA;CACpC;CAGA,MAAM,EAAA,YAA6B,iBAAA,YAAA;CACnC,IAAA,CAAA,QAAM,KAAA,QAAc,WAAA,UAAA,GAA8B;EAClD,MAAM,UAAA;EAGN,OAAI,YAAA,SAAiB,CAAS,QAC5B,aAAO,OAAa,CAAA,CAAA;CACtB;CACA,SAAK,KAAS,KAAI,WAAA,CAAA;CAChB,MAAA,iBAAiB,MAAQ,mBAAA,aAAA,QAAA,KAAA,SAAA,CAAA,GAAA,MAAA;CACzB,IAAA,eAAgB,SAAA,OAAA,OAAA,aAA8B,eAAgB,OAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,eAAA,MAAA,OAAA,CAAA,CAAA;CAC9D,MAAA,kBAAmB,eAAkB;CACvC,IAAA,CAAA,gBAAA,IAAA;EAEA,MAAM,WAAA,eAAuB;EAC7B,MAAI,UAAA,qCACK,gBAA4B,OAAO;EAE5C,OAAI,YAAA,SAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,OAAA,CAAA,CAAA;CACJ;CACE,MAAA,WAAY,wBAAuB,QAAA,IAAe;CACpD,IAAA,aACc,MAAA;EACZ,MAAM,WAAU,eAAA;EAChB,MAAA,UAAO;EACT,OAAA,YAAA,SAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,OAAA,CAAA,CAAA;CAEA;CACA,MAAI,YAAA,MAAe,gBAAS,iBAAyB,QAAW,OAAA,QAAe;CAC7E,IAAA,UAAM,SAAU,OAAA,OAAA,aAAA,UAAA,OAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,UAAA,MAAA,OAAA,CAAA,CAAA;CAChB,IAAA,CAAA,SAAO,MAAY,GAAA;EACrB,MAAA,UAAA;EACA,OAAQ,YAAY,SAAA,CAAA,GAAA,UAAiB,QAAY,QAAA,KAAA,SAAA,OAAA,CAAA,CAAA;CACjD;CACE,SAAM,KAAA,KAAU,QAAA,KAAA,OAAA,CAAA;CAChB,IAAA,QAAO,CAAA,GAAA,UAAY,KAAU;CAC/B,MAAA,oBAAA,iBAAA,QAAA,cAAA,YAAA,QAAA,OAAA;CACA,MAAA,YAAc,gBAAiB,QAAA,KAAA;CAE/B,IAAA,sBAAuB,QAAM,cAAmB,MAAA,SAAa,KAAA,QAAa,mBAAmB,kDAAA,CAAA;MACzF,IAAA,sBAAwB,QAC1B,cAAO,MAAa;EACtB,MAAM,oBAAkB,MAAA,mBAAe,aAAA,mBAAA,CAAA,GAAA,MAAA;EACvC,IAAK,kBAAgB,SAAI,OAAA,SAAA,KAAA,QAAA,mBAAA,kBAAA,MAAA,OAAA,CAAA;OACvB,IAAM,CAAA,kBAAW,MAAe,IAAA;GAChC,MAAM,UAAU,uCAAqC,kBAAgB,MAAO,OAAA;GAC5E,MAAO,WAAA,kBAAyB,KAAA;GAClC,SAAA,KAAA,QAAA,mBAAA,OAAA,CAAA;EAEA,OAAM;GACN,MAAI,kBAAmB,MAAA,gBAAA,kBAAA,OAAA,WAAA,QAAA;GACrB,IAAA,gBAAiB,SAAA,OAAe,SAAA,KAAA,QAAA,mBAAA,gBAAA,MAAA,OAAA,CAAA;QAC1B;IACN,QAAO,CAAA,GAAA,OAAY,GAAA,gBAAa,MAAU,KAAQ,UAAQ;KAC5D,GAAA;KACA,MAAM,MAAA,KAAY,cAAM,KAAgB,IAAA;IACxC,EAAI,CAAA;IAEJ,SAAK,KAAS,KAAM,iBAAG,CAAA;GACrB;EACA;CACF;CACA,MAAA,MAAS,MAAK,UAAa,KAAK,KAAA,cAAQ,MAAA,IAAA,CAAA;CACxC,OAAI,GAAA;EAEJ;EACA;EACA,eAAI;GAGC,SAAI,OAAA;GACP,SAAM;EACN;CAGK,CAAA;AACH;AAEA,SAAA,YAAc;CAChB,OAAA,IACK;EACH,MAAA;EACA,SAAI;CAGC,CAAA;AACH;AAE0C,eAAG,oBAAA,aAAA,QAAA,QAAA;CAAM,MAAA,OAAM,QAAW,YAAA,OAAmB;CAAM,MAC7F,WAAA,MAAA,MAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CACA,IAAA,oBAAmB,OAAA;EACrB,IAAA,SAAA,SAAA,UAAA,OAAA,GAAA,KAAA,CAAA;EACF,OAAA,IAAA;GACF,MAAA;GAEA,SAAM;GACN,MAAO;EACL,CAAA;CACA;CACA,IAAA,CAAA,SAAA,YAAe,KAAA,SAAA,eAAA,GAAA,OAAA,IAAA;EAAE,MAAA;EAAsB,SAAA;EAAyB,MAAA;CAClE,CAAC;CACH,MAAA,gBAAA,MAAA,SAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;;EC7VA,MAAA;EACE,SAAO;EAAM,MAAM;CAAa,CAAA;CAAoC,MAAC,SAAA,KAAA,MAAA,YAAA,IAAA;CACvE,MAAA,aAAA,MAAA,MAAA,MAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CAEA,IAAA,sBAAe,OAAA;EACb,IAAA,WAAa,SAAQ,UAAY,OAAO,GAAA,KAAA,CAAA;EACxC,OAAM,IAAA;GACN,MAAI;GACF,SAAI;GAEJ,MAAO;EAAM,CAAA;CAA0B;CAA6C,IAAA,CAAA,WAAM,YAAA,KAAA,WAAA,eAAA,GAAA,OAAA,IAAA;EAAK,MAAC;EAClG,SAAA;EACA,MAAK;CACU,CAAA;CAA0B,OAAA,qBAAS,QAAA,QAAA,iBAAA,MAAA;AAAyD;AAAW,eAAC,WAAA,OAAA,QAAA,aAAA,QAAA;CACvH,IAAA,QAAM,SAAA,OAAsB,IAAA;EAC5B,MAAI;EACW,SAAM;CAAoB,CAAA;CAA+D,MAAA,UAAM,MAAA,SAAA,gBAAA,GAAA,KAAA,CAAA,IAAA,MAAA,oBAAA,MAAA,aAAA,QAAA,MAAA;CAAK,IAAC,QAAA,SAAA,OAAA,OAAA;CAEpH,IAAA,MAAM,SAAS,gBAAW;EAC1B,MAAM,SAAA,MAAa,qBAAoB,MAAM,YAAuC,QAAA,MAAA,YAAA,MAAA;EACpF,OAAI,OAAA,SAAA,QAAsB,SAAO,GAAA;GAC/B,WAAI;GAEJ,YAAW,MAAA,YAAA;GAAE,QAAM,OAAA;GAAoB,SAAS,QAAA;GAAoC,aAAM,MAAA;EAAO,CAAC;CACpG;CACA,IAAI,MAAC,SAAW,eAAiB;EAClB,MAAM,SAAA,MAAA,qBAAA,MAAA,UAAA,QAAA,MAAA,UAAA,MAAA;EAAoB,OAAA,OAAS,SAAA,QAAA,SAAA,GAAA;GAAyD,WAAM;GAAQ,YAAA;GACzH,QAAO,OAAA;EACT,CAAA;CAEA;CACE,IAAI,MAAA,OAAQ,SACV,cAAW;EAAE,MAAM,SAAA,MAAA,kBAAA,MAAA,OAAA,MAAA,QAAA,aAAA,MAAA;EAAa,IAAA,QAAS,SAAA,OAAA,IAAA;GAA4B,MAAA;GAEvE,SAAM;EAGN,CAAA;EAGA,OAAI,OAAM,SAAS,QAAA,SAAgB,GAAA;GACjC,WAAM;GACN,YAAO,MAAO,YACV;GACK,QAAA,OAAW;GAA0B,SAAA,QAAY;GAAwB,aAAQ,MAAO;EAAO,CAAA;CAAwB;CAA+B,MAAC,aAAA,cAAA,MAAA,OAAA,SAAA,MAAA,OAAA,UAAA;CAClK,IAAA,eAAA,MAAA,OAAA,IAAA;EAEA,MAAI;EACF,SAAM;CACN,CAAA;CAES,MAAA,WAAW,MAAA,MAAA,KAAA,YAAA,cAAA,CAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CAAgB,IAAA,oBAAY,SAAA,CAAA,SAAA,OAAA,KAAA,SAAA,eAAA,GAAA,OAAA,IAAA;EAAU,MAAA;EAAqB,SAAC;EAClF,UAAA,CAAA;GAEA,QAAU;GACR,QAAM;GACN,QAAI;EACW,CAAA;CAAmB,CAAA;CAAoC,MAAC,SAAA,MAAA,qBAAA,YAAA,QAAA,YAAA,MAAA;CACvE,OAAA,OAAO,SAAO,QAAS,SACnB,GACA;EAAK,WAAA;EAAqC,YAAA,MAAY,YAAM;EAAkB,QAAA,OAAQ;EAAc,SAAA,QAAS;EAAe,aAAA,MAAa;CAAkB,CAAA;AACjK;AAEA,SAAM,eAAa,OAAA;CACnB,MAAI,UAAA,MAAe,OACjB,MAAO,SAAI,KAAA,SAAA,2BAAA;CAAE,IAAA,CAAA,SAAM,MAAA,IAAA,MAAA,wCAAA,MAAA,KAAA,EAAA;CAAgB,OAAA,QAAS;AAA+D;AAC7G,SAAM,cAAW,UAAY,YAAK,kBAA4B,YAAO,WAAuC;CAC5G,OAAI,SAAA,WAAoB,mBAAmB,UAAY,CAAA,CAAA,WAAS,0BACnD,gBAAA,CAAA,CAAA,WAAA,mBAAA,UAAA,CAAA,CAAA,WAAA,kBAAA,SAAA;AACT;AACA,eAAS,oBAAA,QAAA,UAAA,QAAA;CACT,MAAA,aAAW,MAAA,KAAA,OAAA,SAAA,cAAA;CAAE,MAAA,QAAQ,MAAA,OAAA,QAAA,IAAA;EAAY,SAAQ;EAAW,KAAA;GAAwC,cAAA,MAAA,KAAA,OAAA,SAAA,OAAA;GAC7F,eAAA,MAAA,KAAA,OAAA,SAAA,eAAA;EAGH;EACA,aAAc;CAEL,CAAA;CAAqC,IAAA,MAAA,aAAkB,GAAA,MAAY,IAAA,MAAA,MAAA,OAAA,KAAA,KAAA,4CAAA;CAAM,KAAA,MAAQ,QAAO,SAAA,OAAA,OAAA,MAAA,OAAA,QAAA,gBAAA;EAAO,MAAA,MAAS,KAAQ,YAAA,KAAA,IAAA;EAAO,SAAA,KAAa;EAAmB,aAAA;CAClK,CAAA;CAEA,KAAA,MAAS,QAAA,SAAe,SAA+B,SAAA,CAAA,GAAA,MAAA,OAAA,QAAA,gBAAA;EACrD,MAAM,MAAA,KAAU,OAAM,SAAO,uBAAkB,KAAS,IAAA;EACxD,SAAK,KACH;EACF,aAAO;CACT,CAAA;CAEA,MAAA,OAAS,QAAA,cAAgC;EACvC,MAAO,MAAA,KACJ,OAAA,SAAW,4BACX;EAGL,SAAA,GAAA,KAAA,UAAA;GAEA,gBAAe,SAAA,OAAoB;GACjC,eAAM,SAAmB,OAAK;GAC9B,iBAAc,SAAa,YAAY,KAAA;EACrC,GAAA,MAAS,CAAA,EAAA;EACT,aAAK;CACH,CAAA;AACA;AACF,SAAA,aAAA,OAAA,QAAA;CACA,OAAA,QAAa,UAAA,UAAA,IAAA,IAAA;EACd,MAAA;EACD,SAAU;EAEV;CAEI,CAAA;AACA;AACA,SAAA,mBAAa,SAAA;CACf,MAAC,SAAA,kBAAA;EAEH,GAAA;EAEI,GAAA,QAAM;CACN,CAAA;CACA,MAAA,cAAa,QAAA,SAAA,WAAA,MAAA,KAAA,UAAA;CACf,MAAC,gBAAA,EAAA,GAAA,QAAA,cAAA;CAEH,MAAM,UAAO,QAAQ;CACnB,MAAA,UAAY,QAAK;CACjB,OAAA,EAAA,KAAY,OAAK,OAAU,aAAA,CAAA,MAAA;EACzB,MAAA,SAAA,cAAyB,KAAO;EAChC,IAAA,OAAA,SAAe,OAAS,OAAO;EAC/B,MAAA,WAAA,MAAiB,WAAS,OAAY,OAAA,QAAA,aAAA,WAAA,MAAA;EACxC,IAAG,SAAS,SAAA,OAAA,OAAA;EACZ,MAAA,QAAa,MAAA,0BAAA,SAAA,MAAA,SAAA;EACd,IAAA;EACH,MAAA,gBAAA,cAAA;EAEA,MAAA,QAAS,IAAA,aAA6B;GACpC;GAEU;GAAqB,QAAS,CAAA,KAAA;GAA8C,gBAAA;GAAO,eAAA;IAC/F,GAAA;IAEA,WAAgB,OAAA,mBAAqE;KACnF,SAAM;MAAgC,SAAA,eAAA;MAA0B,SAAQ,eAAA;KAAc;KACtF,MAAM,oBAAmC,QAAS,SAAA,OAAiB,WAAK,MAAU;KAClF,MAAM,gBAAkB,cAAW;IACnC;GACA;EAEA,CAAA;EAEI,MAAM,gBAAS,MAAA,MAAmB,cAAA,EAAA,aAAA,WAAA,OAAA,CAAA,CAAA,CAAA,KAAA,KAAA,UAAA,IAAA,KAAA,CAAA;EAClC,IAAI,cAAO,SACT,OAAO,OAAA,aAAA,cAAA,OAAA,WAAA,MAAA;EAET,MAAM,UAAA,cAAiB;EACvB,IAAI;GAGJ,IAAA,CAAM,QAAQ,OAAM,IAAA;IACpB,MAAI;IACJ,SAAM;GACN,CAAA;GACE,MAAA,aAAA,MAAA,KAAA,OAAA,SAAA,cAAA;GACA,MAAA,mBAAA,MAAA,KAAA,OAAA,SAAA,qBAAA;GACA,MAAA,aAAc,MAAA,KAAA,OAAA,SAAA,iBAAA,SAAA,MAAA,UAAA;GACd,MAAA,SAAA,cAAgB,eAAA,KAAA,GAAA,YAAA,kBAAA,YAAA,SAAA,MAAA,UAAA;GAChB,MAAA,YAAe,MAAA,MAAA,SAAA;IACb;IACA;IACE,aAAS,WAAA;GAAE,CAAA,CAAA,CAAA,KAAA,KAAS,UAAA,IAAe,KAAA,CAAA;GAAS,IAAA,UAAS,SAAA,OAAe,OAAA,aAAA,UAAA,OAAA,WAAA,MAAA;GAAe,IAAA,WAAA,QAAA,SAAA,OAAA,UAAA;GACnF,MAAA,YAAM,MAAA,qBAAqC,OAAO,SAAA,YAAiB,QAAA,WAAA,MAAA;GACnE,IAAA,UAAM,SAAA,OAAgB,OAAA;GACxB,IAAA,SAAA,MAAA,cAAA,gBAAA,OAAA,oBAAA,UAAA,KAAA;GACF,MAAA,YAAA,uBAAA,SAAA,MAAA,YAAA,UAAA,OAAA,SAAA,MAAA,cAAA,2BAAA,SAAA,MAAA,OAAA,MAAA,KAAA,SAAA,KAAA,IAAA,IAAA,KAAA,CAAA;GACD,IAAA,UAAA,SAAA,OAAA,OAAA;GAED,IAAA,CAAM,SAAA,MAAA,aAA4B,OAAA,IAAA;IAClC,MAAI;IAEJ,SAAM;GAEN,CAAA;GACE,OAAK,aACI,SAAI,MAAA,YAAA,SAAA,SAAA,MAAA,YAAA,MAAA,UAAA,OAAA,SAAA,MAAA,OAAA,QAAA;EAAE,UAAM;GAAe,MAAA,QAAS,QAAA;EAA+C;CAC5F,EAAA;AACA;AAEA,SAAM"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["invalid","invalid","unavailable"],"sources":["../src/internal/result.ts","../src/internal/input.ts","../src/internal/output/collect.ts","../src/internal/output/promote.ts","../src/internal/output/project.ts","../src/internal/output/validate.ts","../src/internal/source/host.ts","../src/internal/source/archive.ts","../src/internal/source/npm.ts","../src/harness.ts"],"sourcesContent":["export type Result<T, E>\n = | { readonly _tag: 'Ok', readonly value: T }\n | { readonly _tag: 'Err', readonly error: E }\n\nexport const ok = <T>(value: T): Result<T, never> => ({ _tag: 'Ok', value })\nexport const err = <E>(error: E): Result<never, E> => ({ _tag: 'Err', error })\n","import type { SkillOutputPolicy, SkillRun, SkillRunError } from '../types.ts'\nimport type { Result } from './result.ts'\nimport { resolve } from 'node:path'\nimport { isSkillName, resolveWithin } from './paths.ts'\nimport { err, ok } from './result.ts'\n\nfunction invalid(message: string): Result<never, SkillRunError> {\n return err({ _tag: 'InvalidInput', message })\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nexport function parseSkillRun(input: SkillRun): Result<SkillRun, SkillRunError> {\n if (!input || typeof input !== 'object' || !('_tag' in input))\n return invalid('Skill run input must be an object with a tag.')\n\n if (input._tag === 'PackageSkill') {\n if (!input.source || !input.destination)\n return invalid('Package Skill input is incomplete.')\n if (!isNonEmptyString(input.destination.rootDir) || !isSkillName(input.destination.name))\n return invalid('Package Skill destination is invalid.')\n if (input.source._tag === 'NpmPackage') {\n if (!isNonEmptyString(input.source.spec))\n return invalid('npm package spec is required.')\n return ok({\n _tag: 'PackageSkill',\n source: { _tag: 'NpmPackage', spec: input.source.spec },\n destination: { rootDir: resolve(input.destination.rootDir), name: input.destination.name },\n })\n }\n if (input.source._tag === 'LocalPackage') {\n if (!isNonEmptyString(input.source.rootDir) || !isNonEmptyString(input.source.packageDir))\n return invalid('Local package paths are required.')\n if (resolveWithin(input.source.rootDir, input.source.packageDir) === null)\n return invalid('Local package directory must stay inside its root directory.')\n return ok({\n _tag: 'PackageSkill',\n source: {\n _tag: 'LocalPackage',\n rootDir: resolve(input.source.rootDir),\n packageDir: input.source.packageDir,\n },\n destination: { rootDir: resolve(input.destination.rootDir), name: input.destination.name },\n })\n }\n return invalid('Package source tag is invalid.')\n }\n\n if (input._tag === 'ProjectSkill') {\n if (!isNonEmptyString(input.projectDir) || !input.destination)\n return invalid('Project Skill input is incomplete.')\n if (!isNonEmptyString(input.destination.rootDir) || !isSkillName(input.destination.name))\n return invalid('Project Skill destination is invalid.')\n return ok({\n _tag: 'ProjectSkill',\n projectDir: resolve(input.projectDir),\n destination: { rootDir: resolve(input.destination.rootDir), name: input.destination.name },\n })\n }\n\n if (input._tag === 'ReviewSkill') {\n if (!isNonEmptyString(input.skillDir))\n return invalid('Skill review directory is required.')\n return ok({ _tag: 'ReviewSkill', skillDir: resolve(input.skillDir) })\n }\n\n return invalid('Skill run tag is invalid.')\n}\n\nexport function parseOutputPolicy(policy: SkillOutputPolicy): SkillOutputPolicy {\n for (const [name, value] of Object.entries(policy)) {\n if (!Number.isSafeInteger(value) || value <= 0)\n throw new TypeError(`${name} must be a positive integer.`)\n }\n return Object.freeze(policy)\n}\n","import type { SkillOutputPolicy, SkillRunError } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { HarnessAgentSandboxConfig } from '@ai-sdk/harness/agent'\nimport { normalizeOutputPath } from '../paths.ts'\nimport { err, ok } from '../result.ts'\n\nexport type SandboxSession = Parameters<NonNullable<HarnessAgentSandboxConfig['onSession']>>[0]['session']\n\nexport interface CollectedFile {\n readonly path: string\n readonly content: Uint8Array\n}\n\nconst invalid = (message: string, issues: ReadonlyArray<string>): Result<never, SkillRunError> =>\n err({ _tag: 'InvalidSkill', message, issues })\n\nconst inventory = async (\n sandbox: SandboxSession,\n outputDir: string,\n signal?: AbortSignal,\n): Promise<Result<ReadonlyArray<{ type: string, path: string, size: number }>, SkillRunError>> => {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n const command = 'find -P \"$SKILLD_OUTPUT\" -mindepth 1 -printf \\'%y\\\\0%P\\\\0%s\\\\0\\''\n const result = await Promise.resolve().then(() => sandbox.run({\n command,\n env: { LC_ALL: 'C', SKILLD_OUTPUT: outputDir },\n abortSignal: signal,\n })).catch(error => error as Error)\n if (result instanceof Error)\n return invalid('Harness output cannot be inspected.', [result.message])\n if (result.exitCode !== 0)\n return invalid('Harness output directory is missing.', [result.stderr.trim() || 'No output directory.'])\n\n const fields = result.stdout.split('\\0')\n if (fields.at(-1) === '')\n fields.pop()\n if (fields.length % 3 !== 0)\n return invalid('Harness output inventory is invalid.', ['File inventory has an incomplete entry.'])\n\n const entries: Array<{ type: string, path: string, size: number }> = []\n for (let index = 0; index < fields.length; index += 3) {\n const type = fields[index]\n const path = fields[index + 1]\n const size = Number(fields[index + 2])\n if (!type || !path || !Number.isSafeInteger(size) || size < 0)\n return invalid('Harness output inventory is invalid.', ['File inventory has invalid fields.'])\n entries.push({ type, path, size })\n }\n return ok(entries)\n}\n\nexport const collectSandboxOutput = async (\n sandbox: SandboxSession,\n outputDir: string,\n policy: SkillOutputPolicy,\n signal?: AbortSignal,\n): Promise<Result<ReadonlyArray<CollectedFile>, SkillRunError>> => {\n const before = await inventory(sandbox, outputDir, signal)\n if (before._tag === 'Err')\n return before\n\n const files: CollectedFile[] = []\n const seen = new Set<string>()\n let totalBytes = 0\n for (const entry of before.value) {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n const path = normalizeOutputPath(entry.path)\n if (path === null)\n return invalid('Harness output contains an invalid path.', [entry.path])\n if (entry.type === 'd')\n continue\n if (entry.type !== 'f')\n return invalid('Harness output contains a linked or special entry.', [path])\n if (seen.has(path))\n return invalid('Harness output contains duplicate paths.', [path])\n if (files.length >= policy.maxOutputFiles)\n return invalid('Harness output contains too many files.', [`Limit: ${policy.maxOutputFiles}`])\n if (entry.size > policy.maxOutputFileBytes)\n return invalid('Harness output contains an oversized file.', [path])\n if (totalBytes + entry.size > policy.maxOutputBytes)\n return invalid('Harness output exceeds the total byte limit.', [`Limit: ${policy.maxOutputBytes}`])\n\n const content = await Promise.resolve().then(() => sandbox.readBinaryFile({ path: `${outputDir}/${path}`, abortSignal: signal })).catch(error => error as Error)\n if (content instanceof Error) {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n return invalid('Harness output cannot be read.', [path, content.message])\n }\n if (content === null || content.byteLength !== entry.size)\n return invalid('Harness output changed during collection.', [path])\n seen.add(path)\n files.push({ path, content: Uint8Array.from(content) })\n totalBytes += content.byteLength\n }\n\n const after = await inventory(sandbox, outputDir, signal)\n if (after._tag === 'Err')\n return after\n if (JSON.stringify(before.value) !== JSON.stringify(after.value))\n return invalid('Harness output changed during collection.', ['File inventory changed.'])\n\n files.sort((left, right) => left.path.localeCompare(right.path))\n return ok(files)\n}\n","import type { GeneratedSkill, SkillRunError, SourceAttempt } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { CollectedFile } from './collect.ts'\nimport { randomUUID } from 'node:crypto'\nimport { lstat, mkdir, open, realpath, rename, rm, rmdir, unlink, writeFile } from 'node:fs/promises'\nimport { dirname, join, resolve } from 'node:path'\nimport { err, ok } from '../result.ts'\n\nfunction pathError(message: string, path: string): Result<never, SkillRunError> {\n return err({ _tag: 'UnsafeOutputPath', message, path })\n}\n\nconst missing = Symbol('missing')\n\n/** A Skill at its destination, and the cleanup problems left behind. */\nexport interface PromotedSkill {\n readonly skill: GeneratedSkill\n readonly warnings: ReadonlyArray<string>\n}\n\nasync function statOrMissing(path: string) {\n return lstat(path).catch(error => (error as NodeJS.ErrnoException).code === 'ENOENT' ? missing : Promise.reject(error))\n}\n\nexport const promoteSkill = async (\n rootDir: string,\n name: string,\n files: ReadonlyArray<CollectedFile>,\n attempts: ReadonlyArray<SourceAttempt>,\n): Promise<Result<PromotedSkill, SkillRunError>> => {\n const root = resolve(rootDir)\n let rootStat = await statOrMissing(root).catch(error => error as Error)\n if (rootStat instanceof Error)\n return pathError('Output root cannot be inspected.', root)\n let createdRoot = false\n if (rootStat === missing) {\n const parent = dirname(root)\n const parentStat = await statOrMissing(parent).catch(error => error as Error)\n if (parentStat instanceof Error || parentStat === missing || !parentStat.isDirectory() || parentStat.isSymbolicLink())\n return pathError('Output root parent must be an existing directory.', parent)\n const canonicalParent = await realpath(parent).catch(error => error as Error)\n if (canonicalParent instanceof Error || canonicalParent !== parent)\n return pathError('Output root parent must not pass through a symbolic link.', parent)\n const created = await mkdir(root, { mode: 0o700 }).then(() => true, error => error as NodeJS.ErrnoException)\n if (created instanceof Error && created.code !== 'EEXIST')\n return pathError('Output root cannot be created.', root)\n createdRoot = created === true\n rootStat = await statOrMissing(root).catch(error => error as Error)\n }\n if (rootStat instanceof Error || rootStat === missing || !rootStat.isDirectory() || rootStat.isSymbolicLink())\n return pathError('Output root must be a directory, not a symbolic link.', root)\n const canonicalRoot = await realpath(root).catch(error => error as Error)\n if (canonicalRoot instanceof Error)\n return pathError('Output root cannot be resolved.', root)\n if (canonicalRoot !== root)\n return pathError('Output root must not pass through a symbolic link.', root)\n\n const target = join(root, name)\n const targetStat = await statOrMissing(target).catch(error => error as Error)\n if (targetStat instanceof Error)\n return pathError('Output path cannot be inspected.', target)\n if (targetStat !== missing && (!targetStat.isDirectory() || targetStat.isSymbolicLink()))\n return pathError('Output path must be a directory, not a symbolic link.', target)\n\n const lockPath = join(root, `.skilld-${name}.lock`)\n const lock = await open(lockPath, 'wx').catch(error => error as NodeJS.ErrnoException)\n if (lock instanceof Error) {\n if (lock.code === 'EEXIST')\n return err({ _tag: 'OutputBusy', message: 'Another Skill run owns this output path.', path: target })\n return err({ _tag: 'PromotionFailed', message: 'Output lock could not be created.', path: target, cause: lock })\n }\n\n const nonce = randomUUID()\n const staging = join(root, `.skilld-${name}-${nonce}.next`)\n const backup = join(root, `.skilld-${name}-${nonce}.previous`)\n let movedCurrent = false\n let promoted = false\n let failureMessage = 'Skill output could not be promoted.'\n let failureCause: unknown\n\n try {\n await mkdir(staging, { mode: 0o700 })\n for (const file of files) {\n const destination = join(staging, file.path)\n await mkdir(dirname(destination), { recursive: true, mode: 0o700 })\n await writeFile(destination, file.content, { flag: 'wx', mode: 0o600 })\n }\n\n if (targetStat !== missing) {\n await rename(target, backup)\n movedCurrent = true\n }\n await rename(staging, target)\n promoted = true\n }\n catch (cause) {\n failureCause = cause\n if (movedCurrent && !promoted) {\n const current = await statOrMissing(target).catch(error => error as Error)\n if (current instanceof Error) {\n failureMessage = 'Skill output rollback could not inspect its destination.'\n failureCause = new AggregateError([cause, current])\n }\n if (current === missing) {\n const rollback = await rename(backup, target).catch(error => error as Error)\n if (rollback instanceof Error) {\n failureMessage = 'Skill output rollback failed.'\n failureCause = new AggregateError([cause, rollback])\n }\n }\n }\n }\n\n const lockCleanupErrors: unknown[] = []\n await lock.close().catch(error => lockCleanupErrors.push(error))\n await unlink(lockPath).catch(error => lockCleanupErrors.push(error))\n\n if (promoted) {\n const warnings: string[] = []\n if (lockCleanupErrors.length > 0) {\n const detail = lockCleanupErrors.map(error => error instanceof Error ? error.message : String(error)).join('; ')\n warnings.push(`Output lock cleanup failed at ${lockPath}: ${detail}`)\n }\n if (movedCurrent) {\n const backupCleanup = await rm(backup, { recursive: true }).catch(error => error as Error)\n if (backupCleanup instanceof Error)\n warnings.push(`Previous Skill cleanup failed at ${backup}: ${backupCleanup.message}`)\n }\n return ok({\n skill: {\n _tag: 'GeneratedSkill',\n name,\n outputDir: target,\n files: files.map(file => ({ path: file.path, bytes: file.content.byteLength })),\n sourceAttempts: attempts,\n },\n warnings,\n })\n }\n\n const cleanupErrors = [...lockCleanupErrors]\n await rm(staging, { recursive: true, force: true }).catch(error => cleanupErrors.push(error))\n if (createdRoot)\n await rmdir(root).catch(error => cleanupErrors.push(error))\n const causes = failureCause === undefined ? cleanupErrors : [failureCause, ...cleanupErrors]\n const cause = causes.length <= 1 ? causes[0] : new AggregateError(causes, 'Skill output cleanup failed.')\n return err({ _tag: 'PromotionFailed', message: failureMessage, path: target, cause })\n}\n","/** A search command the Agent can repeat, matched on whole words. */\nconst searchCommand = /\\b(?:git grep|grep|rg)\\b/\n\n/** Inline code spans, which is where a Skill writes its file pointers. */\nconst inlineCode = /`([^`\\n]+)`/g\n\n/** Fenced blocks, which hold commands rather than pointers. */\nconst fencedBlock = /```[^\\n]*\\n[\\s\\S]*?```/g\n\n/**\n * A Skill may report a file the project lacks, such as a missing entry point.\n * A sentence that denies a path states a fact about the project, not a pointer.\n * A sentence that tells the Agent to create a file gives a task, not a pointer.\n * The check reads whole paragraphs, so a hard-wrapped denial still covers the\n * code spans in its own sentence.\n */\nconst denial = /\\b(no|not|none|never|absent|missing|lacks|without|instead|rather|empty|undeclared|unavailable|nothing)\\b|\\bdoes ?n[o']t\\b/i\n\nconst creation = /\\b(?:copy|create|write|generate)\\b/i\n\nfunction fencedBlocks(markdown: string): ReadonlyArray<string> {\n return markdown.match(fencedBlock) ?? []\n}\n\n/**\n * Prose paragraphs, with fenced commands removed so a command never reads as a\n * pointer. A soft-wrapped sentence keeps its words together: the lines of a\n * paragraph join before any check runs.\n */\nfunction proseParagraphs(markdown: string): ReadonlyArray<string> {\n return markdown\n .replace(fencedBlock, '')\n .split(/\\n[ \\t]*\\n/)\n .map(paragraph => paragraph.replace(/\\n/g, ' ').trim())\n .filter(paragraph => paragraph.length > 0)\n}\n\n/**\n * Extensions a real file pointer carries. A token ending elsewhere, such as\n * the `.0` in a version, carries no path shape.\n */\nconst pathExtension = /\\.(?:md|mdx|json|jsonc|ts|tsx|mts|cts|js|mjs|cjs|jsx|vue|svelte|txt|yml|yaml|toml|html|css|scss|rs|py|go|sh|lock|env|csv|xml)$/i\n\n/** A release number such as `20.19.0` or `v20` states a version, never a path. */\nconst versionShape = /^v?\\d+(?:\\.\\d+)*$/i\n\n/** A product name such as `Node.js` or `node.js` names a tool, never a file. */\nconst productName = /^[A-Za-z][A-Za-z0-9_]*\\.[A-Za-z0-9]+$/\n\n/**\n * A token counts as a file pointer only when it cannot be anything else.\n * A false pointer fails a correct Skill, so every rule here excludes rather than includes.\n */\nfunction pathCandidate(token: string): string | null {\n if (token.length === 0 || /\\s/.test(token))\n return null\n // A flag, a variable, a comment, or a placeholder is never a pointer.\n if (/^[-$#<{[]/.test(token))\n return null\n // A URL, a package specifier, or a shell construct is never a pointer.\n if (token.includes('://') || /[()|;&\"'@:]/.test(token))\n return null\n const trimmed = token.replace(/^\\.\\//, '').replace(/\\/+$/, '')\n if (trimmed.length === 0 || trimmed.startsWith('..'))\n return null\n // A version, a product name, or a numbered reference such as `HTTP/2` is never a pointer.\n if (versionShape.test(trimmed) || productName.test(trimmed) || /\\/\\d+$/.test(trimmed))\n return null\n // A pointer carries a slash-qualified path or a known file extension.\n if (!trimmed.includes('/') && !pathExtension.test(trimmed))\n return null\n return trimmed\n}\n\n/** The literal prefix of a glob, which is the part a real path must start with. */\nfunction literalPrefix(candidate: string): string {\n const wildcard = candidate.search(/[*?]/)\n if (wildcard === -1)\n return candidate\n const cut = candidate.slice(0, wildcard).replace(/[^/]*$/, '')\n return cut.replace(/\\/+$/, '')\n}\n\nfunction resolves(candidate: string, known: ReadonlySet<string>): boolean {\n if (known.has(candidate))\n return true\n const prefix = literalPrefix(candidate)\n if (prefix.length === 0)\n return true\n for (const path of known) {\n // A known template such as `.env.example` implies the file it is copied to.\n if (path.startsWith(`${candidate}.`))\n return true\n // A directory pointer resolves when the project holds a file under it.\n if (path === prefix || path.startsWith(`${prefix}/`))\n return true\n }\n return false\n}\n\nexport interface ProjectSkillInput {\n /** The generated SKILL.md text. */\n readonly markdown: string\n /** Project-relative paths the Harness prepared for the Agent. */\n readonly projectPaths: ReadonlyArray<string>\n /** Output-relative paths the Skill writes beside SKILL.md. */\n readonly outputPaths: ReadonlyArray<string>\n}\n\n/**\n * Check that a project Skill points at files the project contains and gives a\n * search the Agent can repeat. The Agent cannot verify its own pointers.\n *\n * The Harness hides generated directories from the Agent, so a pointer at one is\n * invention like any other. A sentence that states a path is missing, or that\n * tells the Agent to create one, passes: it reports a fact or gives a task, not\n * a pointer. The sentence may wrap across prose lines within its paragraph.\n */\nexport function checkProjectSkill(input: ProjectSkillInput): ReadonlyArray<string> {\n const issues: string[] = []\n const known = new Set([...input.projectPaths, ...input.outputPaths])\n const unknown = new Set<string>()\n\n for (const paragraph of proseParagraphs(input.markdown)) {\n if (denial.test(paragraph) || creation.test(paragraph))\n continue\n for (const match of paragraph.matchAll(inlineCode)) {\n const candidate = pathCandidate(match[1]!.trim())\n if (candidate !== null && !resolves(candidate, known))\n unknown.add(candidate)\n }\n }\n\n for (const path of [...unknown].sort())\n issues.push(`SKILL.md points at a path the project does not contain: ${path}.`)\n\n const inline = [...input.markdown.matchAll(inlineCode)].map(match => match[1]!)\n const commands = [...fencedBlocks(input.markdown), ...inline].join('\\n')\n if (!searchCommand.test(commands))\n issues.push('SKILL.md must give the Agent at least one search command it can repeat.')\n\n return issues\n}\n","import type { SkillReview, SkillReviewFinding, SkillRunError } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { CollectedFile } from './collect.ts'\nimport { parseDocument } from 'yaml'\nimport { isSkillName, normalizeOutputPath } from '../paths.ts'\nimport { checkProjectSkill } from './project.ts'\nimport { err, ok } from '../result.ts'\n\n/** Both generation Skills say the frontmatter must contain only these fields. */\nconst allowedFrontmatter = new Set(['name', 'description'])\n\n/** `generate-package-skill`: \"Keep `SKILL.md` under 500 lines.\" */\nconst packageSkillLineLimit = 500\n\n/** `generate-package-skill`: \"Write at most eight reference files.\" */\nconst packageSkillReferenceLimit = 8\n\n/**\n * The Skill that produced the output decides which of its written rules apply.\n * A project Skill also carries the project paths its pointers must resolve to.\n */\nexport type GenerationContract\n = | { readonly _tag: 'PackageSkill' }\n | { readonly _tag: 'ProjectSkill', readonly projectPaths: ReadonlyArray<string> }\n\nconst invalid = (issues: ReadonlyArray<string>): Result<never, SkillRunError> =>\n err({ _tag: 'InvalidSkill', message: 'Skill output failed deterministic checks.', issues })\n\nfunction decodeText(content: Uint8Array): string | null {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(content)\n }\n catch {\n return null\n }\n}\n\n/** Markdown link targets, inline or reference style, without anchors or titles. */\nfunction linkTargets(markdown: string): ReadonlySet<string> {\n const targets = new Set<string>()\n const add = (raw: string): void => {\n const target = raw.trim().replace(/^<|>$/g, '').split(/\\s/)[0]!.replace(/[#?].*$/, '').replace(/^\\.\\//, '')\n if (target.length > 0)\n targets.add(target)\n }\n for (const match of markdown.matchAll(/\\]\\(([^)\\n]+)\\)/g))\n add(match[1]!)\n for (const match of markdown.matchAll(/^\\s*\\[[^\\]\\n]+\\]:\\s*(\\S+)/gm))\n add(match[1]!)\n for (const match of markdown.matchAll(/`([^`\\n]+)`/g))\n add(match[1]!)\n return targets\n}\n\nfunction lineCount(text: string): number {\n const lines = text.split('\\n')\n return lines.at(-1) === '' ? lines.length - 1 : lines.length\n}\n\n/** The written structure rules of the generation Skills, checked on the output. */\nfunction structureIssues(markdown: string, files: ReadonlyArray<CollectedFile>, contract: GenerationContract): ReadonlyArray<string> {\n const issues: string[] = []\n const referencePaths = files.map(file => file.path).filter(path => path.startsWith('references/')).sort()\n if (contract._tag === 'PackageSkill') {\n const lines = lineCount(markdown)\n if (lines >= packageSkillLineLimit)\n issues.push(`SKILL.md must stay under ${packageSkillLineLimit} lines; it has ${lines}.`)\n if (referencePaths.length > packageSkillReferenceLimit)\n issues.push(`A package Skill may write at most ${packageSkillReferenceLimit} reference files; it wrote ${referencePaths.length}.`)\n }\n const linked = linkTargets(markdown)\n for (const path of referencePaths) {\n if (!linked.has(path))\n issues.push(`SKILL.md must link ${path}.`)\n }\n return issues\n}\n\nexport const validateGeneratedSkill = (\n name: string,\n files: ReadonlyArray<CollectedFile>,\n contract: GenerationContract,\n): Result<void, SkillRunError> => {\n const issues: string[] = []\n const skillFiles = files.filter(file => file.path === 'SKILL.md')\n if (skillFiles.length !== 1)\n return invalid(['Output must contain exactly one SKILL.md file.'])\n\n const source = decodeText(skillFiles[0]!.content)\n if (source === null)\n return invalid(['SKILL.md must contain valid UTF-8 text.'])\n if (contract._tag === 'ProjectSkill') {\n issues.push(...checkProjectSkill({\n markdown: source,\n projectPaths: contract.projectPaths,\n outputPaths: files.map(file => file.path),\n }))\n }\n const match = source.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n([\\s\\S]*)$/)\n if (!match)\n return invalid(['SKILL.md must start with YAML frontmatter.'])\n if (match[2]?.trim().length === 0)\n issues.push('SKILL.md instructions must not be empty.')\n\n const document = parseDocument(match[1]!, { uniqueKeys: true })\n for (const error of document.errors)\n issues.push(`Frontmatter: ${error.message}`)\n for (const warning of document.warnings)\n issues.push(`Frontmatter: ${warning.message}`)\n\n const value = document.errors.length === 0 ? document.toJS() as unknown : null\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n issues.push('Frontmatter must be a mapping.')\n return invalid(issues)\n }\n\n const frontmatter = value as Record<string, unknown>\n for (const key of Object.keys(frontmatter)) {\n if (!allowedFrontmatter.has(key))\n issues.push(`Frontmatter field is not supported: ${key}`)\n }\n if (frontmatter.name !== name)\n issues.push('Frontmatter name must match the Skill directory name.')\n if (typeof frontmatter.name !== 'string' || !isSkillName(frontmatter.name))\n issues.push('Frontmatter name is invalid.')\n if (typeof frontmatter.description !== 'string' || frontmatter.description.trim().length === 0 || frontmatter.description.length > 1024)\n issues.push('Frontmatter description must contain 1 to 1024 characters.')\n issues.push(...structureIssues(source, files, contract))\n\n return issues.length === 0 ? ok(undefined) : invalid(issues)\n}\n\nconst findingLevels = new Set(['error', 'warning', 'note'])\n\nexport const validateSkillReview = (\n files: ReadonlyArray<CollectedFile>,\n): Result<SkillReview, SkillRunError> => {\n if (files.length !== 1 || files[0]?.path !== 'review.json')\n return invalid(['Review output must contain only review.json.'])\n\n let value: unknown\n try {\n const source = decodeText(files[0].content)\n if (source === null)\n return invalid(['review.json must contain valid UTF-8 text.'])\n value = JSON.parse(source)\n }\n catch {\n return invalid(['review.json must contain valid JSON.'])\n }\n if (!value || typeof value !== 'object' || Array.isArray(value))\n return invalid(['review.json must contain an object.'])\n\n const review = value as Record<string, unknown>\n if (Object.keys(review).some(key => key !== 'summary' && key !== 'findings'))\n return invalid(['review.json contains unsupported fields.'])\n if (typeof review.summary !== 'string' || review.summary.trim().length === 0)\n return invalid(['Review summary is required.'])\n if (!Array.isArray(review.findings))\n return invalid(['Review findings must be an array.'])\n\n const findings: SkillReviewFinding[] = []\n for (const item of review.findings) {\n if (!item || typeof item !== 'object' || Array.isArray(item))\n return invalid(['Each review finding must be an object.'])\n const finding = item as Record<string, unknown>\n if (Object.keys(finding).some(key => !['level', 'path', 'message', 'fix'].includes(key)))\n return invalid(['A review finding contains unsupported fields.'])\n if (typeof finding.level !== 'string' || !findingLevels.has(finding.level))\n return invalid(['A review finding level is invalid.'])\n if (typeof finding.path !== 'string' || normalizeOutputPath(finding.path) === null)\n return invalid(['A review finding path is invalid.'])\n if (typeof finding.message !== 'string' || finding.message.trim().length === 0 || typeof finding.fix !== 'string' || finding.fix.trim().length === 0)\n return invalid(['A review finding is incomplete.'])\n findings.push(finding as unknown as SkillReviewFinding)\n }\n\n return ok({ _tag: 'SkillReview', summary: review.summary, findings })\n}\n","import type { SkillOutputPolicy, SkillRunError, SourceAttempt } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport { constants } from 'node:fs'\nimport { lstat, open, opendir, realpath } from 'node:fs/promises'\nimport { join, relative, resolve, sep } from 'node:path'\nimport { err, ok } from '../result.ts'\n\nexport interface PreparedFile {\n readonly path: string\n readonly content: Uint8Array\n}\n\n/** A source file the Harness left out because it exceeds the file byte limit. */\nexport interface SkippedSourceFile {\n readonly path: string\n readonly bytes: number\n}\n\nexport interface PreparedSource {\n readonly files: ReadonlyArray<PreparedFile>\n /** Files left out for size. The Agent and the caller both see this list. */\n readonly skippedFiles: ReadonlyArray<SkippedSourceFile>\n readonly attempts: ReadonlyArray<SourceAttempt>\n readonly npmResolution?: {\n readonly package: string\n readonly version: string\n }\n}\n\n/** One warning per skipped file, in the words the result reports. */\nexport function skippedFileWarnings(skipped: ReadonlyArray<SkippedSourceFile>, policy: SkillOutputPolicy): ReadonlyArray<string> {\n return skipped.map(file =>\n `Source file ${file.path} was left out: ${file.bytes} bytes exceeds the ${policy.maxSourceFileBytes} byte file limit.`)\n}\n\nconst ignoredNames = new Set([\n '.git',\n '.hg',\n '.next',\n '.nuxt',\n '.output',\n '.skilld',\n '.turbo',\n 'coverage',\n 'dist',\n 'node_modules',\n 'target',\n])\n\nexport async function collectHostDirectory(directory: string, policy: SkillOutputPolicy, sourceLabel = directory, signal?: AbortSignal): Promise<Result<PreparedSource, SkillRunError>> {\n const root = resolve(directory)\n const unavailable = (message: string, cause?: unknown): Result<never, SkillRunError> => err({\n _tag: 'SourceUnavailable',\n message,\n attempts: [{ source: sourceLabel, status: 'skipped', reason: message }],\n cause,\n })\n const cancelled = (): Result<never, SkillRunError> => err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n if (signal?.aborted)\n return cancelled()\n const rootStat = await lstat(root).catch(error => error as NodeJS.ErrnoException)\n if (rootStat instanceof Error)\n return unavailable('Source directory is unavailable.', rootStat)\n if (!rootStat.isDirectory() || rootStat.isSymbolicLink())\n return unavailable('Source path must be a directory, not a symbolic link.')\n const canonicalRoot = await realpath(root).catch(error => error as NodeJS.ErrnoException)\n if (canonicalRoot instanceof Error)\n return unavailable('Source directory cannot be resolved.', canonicalRoot)\n if (canonicalRoot !== root)\n return unavailable('Source path must not pass through a symbolic link.')\n\n const files: PreparedFile[] = []\n const skippedFiles: SkippedSourceFile[] = []\n let totalBytes = 0\n const relativePath = (absolute: string): string => relative(root, absolute).split(sep).join('/')\n /** An entry-level failure names the entry, so the caller can find and fix it. */\n const entryUnavailable = (absolute: string, message: string, cause?: unknown, fix?: string): Result<never, SkillRunError> =>\n unavailable(`${message}: ${relativePath(absolute)}.${fix === undefined ? '' : ` ${fix}`}`, cause)\n\n const walk = async (current: string): Promise<Result<void, SkillRunError>> => {\n if (signal?.aborted)\n return cancelled()\n const canonicalCurrent = await realpath(current).catch(error => error as NodeJS.ErrnoException)\n if (canonicalCurrent instanceof Error || canonicalCurrent !== current)\n return unavailable('Source directory changed during collection.', canonicalCurrent instanceof Error ? canonicalCurrent : undefined)\n const directoryHandle = await opendir(current).catch(error => error as NodeJS.ErrnoException)\n if (directoryHandle instanceof Error)\n return unavailable('Source directory cannot be read.', directoryHandle)\n\n for await (const entry of directoryHandle) {\n if (signal?.aborted)\n return cancelled()\n if (ignoredNames.has(entry.name))\n continue\n const absolute = join(current, entry.name)\n const stat = await lstat(absolute).catch(error => error as NodeJS.ErrnoException)\n if (stat instanceof Error)\n return entryUnavailable(absolute, 'Source entry cannot be read', stat)\n if (stat.isSymbolicLink())\n return entryUnavailable(absolute, 'Source contains a symbolic link', undefined, 'Remove the link, or pass a clean export such as a `git archive` of the directory.')\n if (stat.isDirectory()) {\n const nested = await walk(absolute)\n if (nested._tag === 'Err')\n return nested\n continue\n }\n if (!stat.isFile())\n return entryUnavailable(absolute, 'Source contains a special file')\n\n const path = relativePath(absolute)\n const handle = await open(absolute, constants.O_RDONLY | constants.O_NOFOLLOW).catch(error => error as NodeJS.ErrnoException)\n if (handle instanceof Error)\n return entryUnavailable(absolute, 'Source file cannot be opened without following links', handle)\n const openedStat = await handle.stat().catch(error => error as NodeJS.ErrnoException)\n if (openedStat instanceof Error) {\n await handle.close()\n return entryUnavailable(absolute, 'Source file cannot be inspected', openedStat)\n }\n if (!openedStat.isFile() || openedStat.dev !== stat.dev || openedStat.ino !== stat.ino) {\n await handle.close()\n return entryUnavailable(absolute, 'Source file changed during collection')\n }\n if (openedStat.size > policy.maxSourceFileBytes) {\n await handle.close()\n skippedFiles.push({ path, bytes: openedStat.size })\n continue\n }\n if (files.length >= policy.maxSourceFiles) {\n await handle.close()\n return unavailable('Source contains too many files.')\n }\n if (totalBytes + openedStat.size > policy.maxSourceBytes) {\n await handle.close()\n return unavailable('Source exceeds the total byte limit.')\n }\n\n const content = await handle.readFile().catch(error => error as NodeJS.ErrnoException)\n await handle.close()\n if (content instanceof Error)\n return entryUnavailable(absolute, 'Source file cannot be read', content)\n if (content.byteLength !== openedStat.size)\n return entryUnavailable(absolute, 'Source file changed during collection')\n if (signal?.aborted)\n return cancelled()\n files.push({ path, content })\n totalBytes += content.byteLength\n }\n return ok(undefined)\n }\n\n const walked = await walk(root)\n if (walked._tag === 'Err')\n return walked\n if (files.length === 0)\n return unavailable('Source directory has no usable files.')\n\n files.sort((left, right) => left.path.localeCompare(right.path))\n skippedFiles.sort((left, right) => left.path.localeCompare(right.path))\n return ok({ files, skippedFiles, attempts: [{ source: sourceLabel, status: 'used' }] })\n}\n","import type { SkillOutputPolicy, SkillRunError } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { PreparedFile, SkippedSourceFile } from './host.ts'\nimport { Readable } from 'node:stream'\nimport { createGunzip } from 'node:zlib'\nimport { normalizeOutputPath } from '../paths.ts'\nimport { err, ok } from '../result.ts'\n\nconst blockBytes = 512\n\nexport type ArchiveLayout = 'npm' | 'github'\n\ninterface PendingEntry {\n readonly kind: 'directory' | 'file' | 'metadata' | 'skip'\n readonly path?: string\n readonly metadataType?: 'long-path' | 'pax'\n readonly size: number\n remaining: number\n padding: number\n readonly chunks: Array<Buffer<ArrayBufferLike>>\n}\n\nfunction unavailable(message: string, cause?: unknown): Result<never, SkillRunError> {\n return err({ _tag: 'SourceUnavailable', message, attempts: [], cause })\n}\n\nfunction readString(buffer: Uint8Array, start: number, length: number): string {\n const bytes = buffer.subarray(start, start + length)\n const zero = bytes.indexOf(0)\n return Buffer.from(zero === -1 ? bytes : bytes.subarray(0, zero)).toString('utf8').trim()\n}\n\nfunction readOctal(buffer: Uint8Array, start: number, length: number): number | null {\n const value = readString(buffer, start, length).replace(/^\\s+|\\s+$/g, '')\n if (!/^[0-7]+$/.test(value))\n return null\n const parsed = Number.parseInt(value, 8)\n return Number.isSafeInteger(parsed) ? parsed : null\n}\n\nfunction hasValidChecksum(header: Uint8Array): boolean {\n const expected = readOctal(header, 148, 8)\n if (expected === null)\n return false\n let actual = 0\n for (let index = 0; index < header.byteLength; index += 1)\n actual += index >= 148 && index < 156 ? 32 : header[index]!\n return actual === expected\n}\n\nfunction parsePaxPath(content: Uint8Array): string | null {\n const text = Buffer.from(content).toString('utf8')\n let offset = 0\n let path: string | null = null\n while (offset < text.length) {\n const space = text.indexOf(' ', offset)\n if (space === -1)\n return null\n const length = Number.parseInt(text.slice(offset, space), 10)\n if (!Number.isSafeInteger(length) || length <= 0 || offset + length > text.length)\n return null\n const record = text.slice(space + 1, offset + length - 1)\n const equals = record.indexOf('=')\n if (equals !== -1 && record.slice(0, equals) === 'path')\n path = record.slice(equals + 1)\n offset += length\n }\n return path\n}\n\nfunction archivePath(value: string, layout: ArchiveLayout): string | null {\n const normalized = normalizeOutputPath(value)\n if (normalized === null)\n return null\n const segments = normalized.split('/')\n if (layout === 'npm') {\n if (segments[0] !== 'package' || segments.length < 2)\n return null\n }\n else if (segments.length < 2) {\n return null\n }\n return normalizeOutputPath(segments.slice(1).join('/'))\n}\n\nfunction entryContent(entry: PendingEntry): Buffer<ArrayBufferLike> {\n return entry.chunks.length === 1\n ? entry.chunks[0]!\n : Buffer.concat(entry.chunks, entry.size)\n}\n\nexport interface ExtractedArchive {\n readonly files: ReadonlyArray<PreparedFile>\n readonly skippedFiles: ReadonlyArray<SkippedSourceFile>\n}\n\nexport async function extractArchive(\n compressed: AsyncIterable<Uint8Array>,\n policy: SkillOutputPolicy,\n layout: ArchiveLayout,\n): Promise<Result<ExtractedArchive, SkillRunError>> {\n const source = Readable.from(compressed)\n const gunzip = createGunzip()\n source.on('error', error => gunzip.destroy(error))\n source.pipe(gunzip)\n const files: PreparedFile[] = []\n const skippedFiles: SkippedSourceFile[] = []\n const seen = new Set<string>()\n const maxArchiveBytes = policy.maxSourceBytes + (policy.maxSourceFiles + 2) * blockBytes * 2\n let archiveBytes = 0\n let fileEntries = 0\n let nextPath: string | null = null\n let pending: Buffer<ArrayBufferLike> = Buffer.alloc(0)\n let entry: PendingEntry | null = null\n let totalBytes = 0\n let ended = false\n\n try {\n for await (const value of gunzip) {\n const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value as Uint8Array)\n archiveBytes += chunk.byteLength\n if (archiveBytes > maxArchiveBytes)\n return unavailable('Source archive exceeds the uncompressed byte limit.')\n pending = pending.byteLength === 0 ? chunk : Buffer.concat([pending, chunk])\n\n while (pending.byteLength > 0) {\n if (ended) {\n if (pending.some(byte => byte !== 0))\n return unavailable('Source archive has data after its end marker.')\n pending = Buffer.alloc(0)\n break\n }\n\n if (entry !== null) {\n if (entry.remaining > 0) {\n const consumed = Math.min(entry.remaining, pending.byteLength)\n if (entry.kind === 'file' || entry.kind === 'metadata')\n entry.chunks.push(pending.subarray(0, consumed))\n pending = pending.subarray(consumed)\n entry.remaining -= consumed\n if (entry.remaining > 0)\n break\n }\n if (entry.padding > 0) {\n const consumed = Math.min(entry.padding, pending.byteLength)\n pending = pending.subarray(consumed)\n entry.padding -= consumed\n if (entry.padding > 0)\n break\n }\n\n if (entry.kind === 'metadata') {\n const content = entryContent(entry)\n nextPath = entry.metadataType === 'pax'\n ? parsePaxPath(content)\n : content.toString('utf8').replace(/\\0.*$/s, '').trim()\n if (nextPath === null || nextPath.length === 0)\n return unavailable('Source archive has invalid path metadata.')\n }\n else if (entry.kind === 'file' && entry.path) {\n files.push({ path: entry.path, content: Uint8Array.from(entryContent(entry)) })\n totalBytes += entry.size\n }\n entry = null\n continue\n }\n\n if (pending.byteLength < blockBytes)\n break\n const header = pending.subarray(0, blockBytes)\n pending = pending.subarray(blockBytes)\n if (header.every(byte => byte === 0)) {\n ended = true\n continue\n }\n if (!hasValidChecksum(header))\n return unavailable('Source archive has an invalid header checksum.')\n\n const size = readOctal(header, 124, 12)\n if (size === null)\n return unavailable('Source archive has an invalid entry size.')\n const name = readString(header, 0, 100)\n const prefix = readString(header, 345, 155)\n const headerPath = prefix.length > 0 ? `${prefix}/${name}` : name\n const type = String.fromCharCode(header[156] ?? 0)\n const padding = (blockBytes - size % blockBytes) % blockBytes\n\n if (type === 'x' || type === 'L') {\n if (size > policy.maxSourceFileBytes)\n return unavailable('Source archive path metadata exceeds the file byte limit.')\n entry = {\n kind: 'metadata',\n metadataType: type === 'x' ? 'pax' : 'long-path',\n size,\n remaining: size,\n padding,\n chunks: [],\n }\n continue\n }\n if (type === '5') {\n nextPath = null\n entry = { kind: 'directory', size, remaining: size, padding, chunks: [] }\n continue\n }\n if (type !== '0' && type !== '\\0')\n return unavailable(`Source archive contains a linked or special entry: ${nextPath ?? headerPath}.`)\n\n const path = archivePath(nextPath ?? headerPath, layout)\n nextPath = null\n if (path === null)\n return unavailable('Source archive contains an invalid path.')\n if (seen.has(path))\n return unavailable('Source archive contains duplicate paths.')\n seen.add(path)\n fileEntries += 1\n if (fileEntries > policy.maxSourceFiles)\n return unavailable('Source archive contains too many files.')\n if (size <= policy.maxSourceFileBytes && totalBytes + size > policy.maxSourceBytes)\n return unavailable('Source archive exceeds the total byte limit.')\n if (size > policy.maxSourceFileBytes)\n skippedFiles.push({ path, bytes: size })\n\n entry = {\n kind: size > policy.maxSourceFileBytes ? 'skip' : 'file',\n path,\n size,\n remaining: size,\n padding,\n chunks: [],\n }\n }\n }\n }\n catch (cause) {\n const message = cause instanceof Error ? cause.message : ''\n return unavailable(message.startsWith('Source archive ')\n ? message\n : 'Source archive is not valid gzip data.', cause)\n }\n\n if (entry !== null || pending.some(byte => byte !== 0) || !ended)\n return unavailable('Source archive ended before its final entry.')\n if (files.length === 0)\n return unavailable('Source archive has no usable files.')\n files.sort((left, right) => left.path.localeCompare(right.path))\n skippedFiles.sort((left, right) => left.path.localeCompare(right.path))\n return ok({ files, skippedFiles })\n}\n","import type { Hash } from 'node:crypto'\nimport type { SkillOutputPolicy, SkillRunError, SourceAttempt } from '../../types.ts'\nimport type { Result } from '../result.ts'\nimport type { ExtractedArchive } from './archive.ts'\nimport type { PreparedFile, PreparedSource } from './host.ts'\nimport { createHash } from 'node:crypto'\nimport { posix } from 'node:path'\nimport { err, ok } from '../result.ts'\nimport { extractArchive } from './archive.ts'\n\ninterface NpmDist {\n readonly tarball: string\n readonly integrity?: string\n readonly shasum?: string\n}\n\ninterface NpmRepository {\n readonly type?: string\n readonly url?: string\n}\n\ninterface NpmVersion {\n readonly version: string\n readonly dist: NpmDist\n readonly gitHead?: string\n readonly repository?: NpmRepository | string\n}\n\ninterface IntegrityVerifier {\n readonly update: (content: Uint8Array) => void\n readonly valid: () => boolean\n}\n\nconst packageSpecPattern = /^(@[^/@]+\\/[^/@]+|[^/@]+)(?:@(\\S+))?$/\nconst exactVersionPattern = /^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[\\da-z-]+(?:\\.[\\da-z-]+)*)?(?:\\+[\\da-z-]+(?:\\.[\\da-z-]+)*)?$/i\nconst gitCommitPattern = /^[0-9a-f]{40}$/i\nconst npmRequestTimeoutMs = 30_000\nconst npmRedirectLimit = 3\nconst packumentByteLimit = 10 * 1024 * 1024\n\nexport type FetchClient = (input: string | URL | Request, init?: RequestInit) => Promise<Response>\n\nfunction unavailable(message: string, attempts: ReadonlyArray<SourceAttempt>, cause?: unknown): Result<never, SkillRunError> {\n return err({ _tag: 'SourceUnavailable', message, attempts, cause })\n}\n\nfunction parsePackageSpec(spec: string): { name: string, version: string } | null {\n const match = spec.match(packageSpecPattern)\n return match?.[1] ? { name: match[1], version: match[2] ?? 'latest' } : null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction parseRepository(value: unknown): NpmRepository | string | undefined {\n if (typeof value === 'string')\n return value\n if (!isRecord(value))\n return undefined\n return {\n type: typeof value.type === 'string' ? value.type : undefined,\n url: typeof value.url === 'string' ? value.url : undefined,\n }\n}\n\nfunction parseVersion(packument: unknown, requested: string): { resolvedVersion: string, version: NpmVersion, repository?: NpmRepository | string } | null {\n if (!isRecord(packument) || !isRecord(packument['dist-tags']) || !isRecord(packument.versions))\n return null\n const tagged = packument['dist-tags'][requested]\n const resolvedVersion = typeof tagged === 'string' ? tagged : requested\n const value = packument.versions[resolvedVersion]\n if (!isRecord(value) || typeof value.version !== 'string' || !isRecord(value.dist) || typeof value.dist.tarball !== 'string')\n return null\n return {\n resolvedVersion,\n repository: parseRepository(packument.repository),\n version: {\n version: value.version,\n gitHead: typeof value.gitHead === 'string' ? value.gitHead : undefined,\n repository: parseRepository(value.repository),\n dist: {\n tarball: value.dist.tarball,\n integrity: typeof value.dist.integrity === 'string' ? value.dist.integrity : undefined,\n shasum: typeof value.dist.shasum === 'string' ? value.dist.shasum : undefined,\n },\n },\n }\n}\n\nasync function cancelBody(response: Response): Promise<void> {\n if (!response.body)\n return\n // A failed cleanup cannot replace the source failure.\n await response.body.cancel().catch(() => undefined)\n}\n\nfunction declaredBytes(response: Response): number | null {\n const value = response.headers.get('content-length')\n if (value === null || !/^\\d+$/.test(value))\n return null\n const bytes = Number(value)\n return Number.isSafeInteger(bytes) ? bytes : null\n}\n\nasync function* responseChunks(\n response: Response,\n maxBytes: number,\n limitMessage: string,\n onChunk: (content: Uint8Array) => void = () => {},\n): AsyncGenerator<Uint8Array> {\n const declared = declaredBytes(response)\n if (declared !== null && declared > maxBytes) {\n await cancelBody(response)\n throw new Error(limitMessage)\n }\n if (!response.body)\n return\n\n const reader = response.body.getReader()\n let complete = false\n let totalBytes = 0\n try {\n while (true) {\n const result = await reader.read()\n if (result.done) {\n complete = true\n return\n }\n totalBytes += result.value.byteLength\n if (totalBytes > maxBytes)\n throw new Error(limitMessage)\n onChunk(result.value)\n yield result.value\n }\n }\n finally {\n if (!complete) {\n // A failed cleanup cannot replace the source failure.\n await reader.cancel().catch(() => undefined)\n }\n reader.releaseLock()\n }\n}\n\nasync function readBoundedResponse(response: Response, maxBytes: number): Promise<Result<Uint8Array, SkillRunError>> {\n const chunks: Uint8Array[] = []\n let totalBytes = 0\n try {\n for await (const chunk of responseChunks(response, maxBytes, 'npm response exceeds the byte limit.')) {\n chunks.push(chunk)\n totalBytes += chunk.byteLength\n }\n }\n catch (cause) {\n return unavailable(cause instanceof Error ? cause.message : 'npm response cannot be read.', [], cause)\n }\n return ok(Uint8Array.from(Buffer.concat(chunks, totalBytes)))\n}\n\nasync function fetchWithRedirects(fetchClient: FetchClient, url: string, init: RequestInit = {}, signal?: AbortSignal): Promise<Result<Response, SkillRunError>> {\n const timeout = AbortSignal.timeout(npmRequestTimeoutMs)\n const requestSignal = signal ? AbortSignal.any([signal, timeout]) : timeout\n let current = url\n for (let redirects = 0; redirects <= npmRedirectLimit; redirects += 1) {\n const response = await fetchClient(current, { ...init, redirect: 'manual', signal: requestSignal }).catch(error => error as Error)\n if (response instanceof Error)\n return unavailable(timeout.aborted ? 'npm request timed out.' : 'npm request failed.', [], response)\n if (![301, 302, 303, 307, 308].includes(response.status))\n return ok(response)\n if (redirects === npmRedirectLimit) {\n await cancelBody(response)\n return unavailable('npm request exceeded the redirect limit.', [])\n }\n const location = response.headers.get('location')\n if (!location) {\n await cancelBody(response)\n return unavailable('npm redirect is missing its location.', [])\n }\n const redirected = await Promise.resolve().then(() => new URL(location, current)).catch(() => null)\n if (redirected === null) {\n await cancelBody(response)\n return unavailable('npm redirect location is invalid.', [])\n }\n if (redirected.protocol !== 'https:') {\n await cancelBody(response)\n return unavailable('npm redirect URL must use HTTPS.', [])\n }\n await cancelBody(response)\n current = redirected.href\n }\n return unavailable('npm request exceeded the redirect limit.', [])\n}\n\nfunction createIntegrityVerifier(dist: NpmDist): IntegrityVerifier | null {\n const values = dist.integrity?.split(/\\s+/).filter(Boolean) ?? []\n let expected = values.flatMap((value) => {\n const match = value.match(/^(sha(?:1|256|384|512))-([A-Za-z0-9+/=]+)$/)\n return match?.[1] && match[2] ? [{ algorithm: match[1], digest: match[2] }] : []\n })\n if (expected.length > 0) {\n const strength = { sha1: 1, sha256: 2, sha384: 3, sha512: 4 } as const\n const strongest = Math.max(...expected.map(value => strength[value.algorithm as keyof typeof strength]))\n expected = expected.filter(value => strength[value.algorithm as keyof typeof strength] === strongest)\n }\n if (values.length === 0 && dist.shasum && /^[0-9a-f]{40}$/i.test(dist.shasum))\n expected.push({ algorithm: 'sha1', digest: Buffer.from(dist.shasum, 'hex').toString('base64') })\n if (expected.length === 0)\n return null\n\n const hashes = new Map<string, Hash>()\n for (const value of expected)\n hashes.set(value.algorithm, createHash(value.algorithm))\n return {\n update(content) {\n for (const hash of hashes.values())\n hash.update(content)\n },\n valid() {\n const actual = new Map([...hashes].map(([algorithm, hash]) => [algorithm, hash.digest('base64')]))\n return expected.some(value => actual.get(value.algorithm) === value.digest)\n },\n }\n}\n\nfunction repositoryUrl(repository: NpmRepository | string | undefined): string | null {\n if (typeof repository === 'string')\n return repository\n return typeof repository?.url === 'string' ? repository.url : null\n}\n\nfunction githubArchiveUrl(repository: NpmRepository | string | undefined, gitHead: string | undefined): string | null {\n if (!gitHead || !gitCommitPattern.test(gitHead))\n return null\n const source = repositoryUrl(repository)\n if (source === null)\n return null\n const match = source.match(/^(?:(?:git\\+)?https?:\\/\\/(?:git@)?github\\.com\\/|git:\\/\\/github\\.com\\/|git@github\\.com:)([\\w.-]+)\\/([\\w.-]+?)(?:\\.git)?\\/?$/)\n if (!match?.[1] || !match[2])\n return null\n return `https://codeload.github.com/${encodeURIComponent(match[1])}/${encodeURIComponent(match[2])}/tar.gz/${gitHead}`\n}\n\nfunction skipped(source: string, reason: string): SourceAttempt {\n return { source, status: 'skipped', reason }\n}\n\nfunction used(source: string): SourceAttempt {\n return { source, status: 'used' }\n}\n\nfunction withAttempts(error: SkillRunError, attempts: ReadonlyArray<SourceAttempt>): Result<never, SkillRunError> {\n return error._tag === 'SourceUnavailable'\n ? unavailable(error.message, attempts, error.cause)\n : err(error)\n}\n\nfunction remainingPolicy(policy: SkillOutputPolicy, files: ReadonlyArray<PreparedFile>): SkillOutputPolicy | null {\n const usedBytes = files.reduce((total, file) => total + file.content.byteLength, 0)\n const maxSourceFiles = policy.maxSourceFiles - files.length\n const maxSourceBytes = policy.maxSourceBytes - usedBytes\n if (maxSourceFiles <= 0 || maxSourceBytes <= 0)\n return null\n return { ...policy, maxSourceFiles, maxSourceBytes }\n}\n\nasync function extractResponse(\n response: Response,\n policy: SkillOutputPolicy,\n layout: 'github' | 'npm',\n verifier?: IntegrityVerifier,\n): Promise<Result<ExtractedArchive, SkillRunError>> {\n return extractArchive(\n responseChunks(\n response,\n policy.maxSourceBytes,\n 'Source archive exceeds the compressed byte limit.',\n content => verifier?.update(content),\n ),\n policy,\n layout,\n )\n}\n\nexport async function prepareNpmPackage(spec: string, policy: SkillOutputPolicy, fetchClient: FetchClient, signal?: AbortSignal): Promise<Result<PreparedSource, SkillRunError>> {\n const parsed = parsePackageSpec(spec)\n if (parsed === null)\n return unavailable('npm package spec is invalid.', [])\n\n const attempts: SourceAttempt[] = []\n const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(parsed.name)}`\n const registryResponse = await fetchWithRedirects(fetchClient, registryUrl, {\n headers: { accept: 'application/vnd.npm.install-v1+json' },\n }, signal)\n if (registryResponse._tag === 'Err')\n return withAttempts(registryResponse.error, [skipped(registryUrl, registryResponse.error.message)])\n const response = registryResponse.value\n if (!response.ok) {\n await cancelBody(response)\n const message = `npm registry returned HTTP ${response.status}.`\n return unavailable(message, [skipped(registryUrl, message)])\n }\n\n const packumentBytes = await readBoundedResponse(response, packumentByteLimit)\n if (packumentBytes._tag === 'Err')\n return withAttempts(packumentBytes.error, [skipped(registryUrl, packumentBytes.error.message)])\n\n let packument: unknown\n try {\n packument = JSON.parse(Buffer.from(packumentBytes.value).toString('utf8')) as unknown\n }\n catch (cause) {\n const message = 'npm registry returned invalid package data.'\n return unavailable(message, [skipped(registryUrl, message)], cause)\n }\n\n const resolution = parseVersion(packument, parsed.version)\n if (resolution === null || !exactVersionPattern.test(resolution.resolvedVersion) || resolution.version.version !== resolution.resolvedVersion) {\n const message = 'npm package did not resolve to an exact version.'\n return unavailable(message, [skipped(registryUrl, message)])\n }\n const { repository, resolvedVersion, version } = resolution\n if (!version.dist.tarball.startsWith('https://')) {\n const message = 'npm package archive URL must use HTTPS.'\n return unavailable(message, [skipped(registryUrl, message)])\n }\n attempts.push(used(registryUrl))\n\n const fetchedArchive = await fetchWithRedirects(fetchClient, version.dist.tarball, {}, signal)\n if (fetchedArchive._tag === 'Err')\n return withAttempts(fetchedArchive.error, [...attempts, skipped(version.dist.tarball, fetchedArchive.error.message)])\n const archiveResponse = fetchedArchive.value\n if (!archiveResponse.ok) {\n await cancelBody(archiveResponse)\n const message = `npm package archive returned HTTP ${archiveResponse.status}.`\n return unavailable(message, [...attempts, skipped(version.dist.tarball, message)])\n }\n\n const verifier = createIntegrityVerifier(version.dist)\n if (verifier === null) {\n await cancelBody(archiveResponse)\n const message = 'npm package archive has no supported integrity value.'\n return unavailable(message, [...attempts, skipped(version.dist.tarball, message)])\n }\n const extracted = await extractResponse(archiveResponse, policy, 'npm', verifier)\n if (extracted._tag === 'Err')\n return withAttempts(extracted.error, [...attempts, skipped(version.dist.tarball, extracted.error.message)])\n if (!verifier.valid()) {\n const message = 'npm package archive integrity check failed.'\n return unavailable(message, [...attempts, skipped(version.dist.tarball, message)])\n }\n attempts.push(used(version.dist.tarball))\n let files = [...extracted.value.files]\n let skippedFiles = [...extracted.value.skippedFiles]\n\n const repositoryArchive = githubArchiveUrl(version.repository ?? repository, version.gitHead)\n const available = remainingPolicy(policy, files)\n if (repositoryArchive !== null && available === null) {\n attempts.push(skipped(repositoryArchive, 'Prepared package files reached the source limit.'))\n }\n else if (repositoryArchive !== null && available !== null) {\n const fetchedRepository = await fetchWithRedirects(fetchClient, repositoryArchive, {}, signal)\n if (fetchedRepository._tag === 'Err') {\n attempts.push(skipped(repositoryArchive, fetchedRepository.error.message))\n }\n else if (!fetchedRepository.value.ok) {\n const message = `GitHub source archive returned HTTP ${fetchedRepository.value.status}.`\n await cancelBody(fetchedRepository.value)\n attempts.push(skipped(repositoryArchive, message))\n }\n else {\n const repositoryFiles = await extractResponse(fetchedRepository.value, available, 'github')\n if (repositoryFiles._tag === 'Err') {\n attempts.push(skipped(repositoryArchive, repositoryFiles.error.message))\n }\n else {\n files = [\n ...files,\n ...repositoryFiles.value.files.map(file => ({ ...file, path: posix.join('repository', file.path) })),\n ]\n skippedFiles = [\n ...skippedFiles,\n ...repositoryFiles.value.skippedFiles.map(file => ({ ...file, path: posix.join('repository', file.path) })),\n ]\n attempts.push(used(repositoryArchive))\n }\n }\n }\n\n files.sort((left, right) => left.path.localeCompare(right.path))\n skippedFiles.sort((left, right) => left.path.localeCompare(right.path))\n return ok({\n files,\n skippedFiles,\n attempts,\n npmResolution: { package: parsed.name, version: resolvedVersion },\n })\n}\n","import type { HarnessV1NetworkSandboxSession, HarnessV1Skill } from '@ai-sdk/harness'\nimport type { SandboxSession } from './internal/output/collect.ts'\nimport type { Result } from './internal/result.ts'\nimport type { PreparedSource } from './internal/source/host.ts'\nimport type { FetchClient } from './internal/source/npm.ts'\nimport type {\n CreateSkillHarnessOptions,\n GeneratedSkill,\n SkillDestination,\n SkillHarness,\n SkillOutputPolicy,\n SkillReview,\n SkillRun,\n SkillRunError,\n SkillRunEvent,\n SkillRunOptions,\n SkillRunReport,\n SkillRunResult,\n SkillRunUsage,\n} from './types.ts'\nimport { lstat, realpath } from 'node:fs/promises'\nimport { basename, join, posix, resolve } from 'node:path'\nimport { HarnessAgent } from '@ai-sdk/harness/agent'\nimport { parseOutputPolicy, parseSkillRun } from './internal/input.ts'\nimport { collectSandboxOutput } from './internal/output/collect.ts'\nimport { promoteSkill } from './internal/output/promote.ts'\nimport { validateGeneratedSkill, validateSkillReview } from './internal/output/validate.ts'\nimport { resolveWithin } from './internal/paths.ts'\nimport { err, ok } from './internal/result.ts'\nimport { collectHostDirectory, skippedFileWarnings } from './internal/source/host.ts'\nimport { prepareNpmPackage } from './internal/source/npm.ts'\nimport { DEFAULT_OUTPUT_POLICY, loadSkilldMaintainedSkill } from './skills.ts'\n\ninterface PreparedRun {\n readonly skillName: 'generate-package-skill' | 'generate-project-skill' | 'review-skill'\n readonly outputName: string\n readonly source: PreparedSource\n // Path under `input/source`. A reviewed Skill keeps its directory name, so\n // review-skill can compare that name with the frontmatter `name`.\n readonly sourceDir: string\n readonly current?: PreparedSource\n readonly destination?: SkillDestination\n}\n\ninterface ActiveSandbox {\n readonly sandbox: SandboxSession\n readonly workDir: string\n}\n\n/** The outcome of one Skill run before the Harness attaches its report. */\ntype RunOutcome = Result<GeneratedSkill | SkillReview, SkillRunError>\n\n/** Collects the cost of one Skill run and every warning beside its outcome. */\ninterface RunLog {\n /** Forwards an event to the caller and counts each finished step. */\n readonly emit: (event: SkillRunEvent) => void\n readonly warn: (warning: string) => void\n /** Replaces the counted steps with the totals the Agent reported at its end. */\n readonly settle: (usage: SkillRunUsage, steps: number) => void\n readonly report: () => SkillRunReport\n}\n\nfunction addCount(total: number | undefined, count: number | undefined): number | undefined {\n return total === undefined ? count : count === undefined ? total : total + count\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (typeof value === 'object' || typeof value === 'function')\n && value !== null\n && typeof (value as { then?: unknown }).then === 'function'\n}\n\nfunction createRunLog(onEvent: SkillRunOptions['onEvent']): RunLog {\n const warnings: string[] = []\n const eventFailures = new Set<string>()\n let usage: SkillRunUsage = { inputTokens: undefined, cachedInputTokens: undefined, outputTokens: undefined }\n let steps = 0\n // The Agent SDK drops callback errors, so surface them on the report instead.\n const fail = (cause: unknown) => {\n eventFailures.add(`onEvent failed: ${cause instanceof Error ? cause.message : String(cause)}`)\n }\n return {\n emit: (event) => {\n if (event._tag === 'StepFinish') {\n steps += 1\n usage = {\n inputTokens: addCount(usage.inputTokens, event.usage.inputTokens),\n cachedInputTokens: addCount(usage.cachedInputTokens, event.usage.cachedInputTokens),\n outputTokens: addCount(usage.outputTokens, event.usage.outputTokens),\n }\n }\n if (!onEvent)\n return\n try {\n const returned: unknown = onEvent(event)\n // An async listener or custom thenable would otherwise reject unhandled and can end the host process.\n if (isPromiseLike(returned))\n Promise.resolve(returned).catch(fail)\n }\n catch (cause) {\n fail(cause)\n }\n },\n warn: warning => warnings.push(warning),\n settle: (total, count) => {\n usage = total\n steps = count\n },\n report: () => ({ usage, steps, warnings: [...warnings, ...eventFailures] }),\n }\n}\n\n/** The fields this package reads from the Agent SDK usage report. */\ninterface AgentUsage {\n readonly inputTokens: number | undefined\n readonly inputTokenDetails: { readonly cacheReadTokens: number | undefined }\n readonly outputTokens: number | undefined\n}\n\nfunction toUsage(usage: AgentUsage): SkillRunUsage {\n return {\n inputTokens: usage.inputTokens,\n cachedInputTokens: usage.inputTokenDetails.cacheReadTokens,\n outputTokens: usage.outputTokens,\n }\n}\n\nfunction cancelled(): RunOutcome {\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n}\n\nasync function prepareCurrentSkill(destination: SkillDestination, policy: SkillOutputPolicy, signal?: AbortSignal): Promise<Result<PreparedSource | undefined, SkillRunError>> {\n const root = resolve(destination.rootDir)\n const rootStat = await lstat(root).catch(error => error as NodeJS.ErrnoException)\n if (rootStat instanceof Error) {\n if (rootStat.code === 'ENOENT')\n return ok(undefined)\n return err({ _tag: 'UnsafeOutputPath', message: 'Output root cannot be inspected.', path: root })\n }\n if (!rootStat.isDirectory() || rootStat.isSymbolicLink())\n return err({ _tag: 'UnsafeOutputPath', message: 'Output root must be a directory, not a symbolic link.', path: root })\n const canonicalRoot = await realpath(root).catch(error => error as Error)\n if (canonicalRoot instanceof Error || canonicalRoot !== root)\n return err({ _tag: 'UnsafeOutputPath', message: 'Output root must not pass through a symbolic link.', path: root })\n\n const target = join(root, destination.name)\n const targetStat = await lstat(target).catch(error => error as NodeJS.ErrnoException)\n if (targetStat instanceof Error) {\n if (targetStat.code === 'ENOENT')\n return ok(undefined)\n return err({ _tag: 'UnsafeOutputPath', message: 'Output path cannot be inspected.', path: target })\n }\n if (!targetStat.isDirectory() || targetStat.isSymbolicLink())\n return err({ _tag: 'UnsafeOutputPath', message: 'Output path must be a directory, not a symbolic link.', path: target })\n return collectHostDirectory(target, policy, 'current Skill', signal)\n}\n\nasync function prepareRun(input: SkillRun, policy: SkillOutputPolicy, fetchClient: FetchClient, signal?: AbortSignal): Promise<Result<PreparedRun, SkillRunError>> {\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n\n const current = input._tag === 'ReviewSkill'\n ? ok(undefined)\n : await prepareCurrentSkill(input.destination, policy, signal)\n if (current._tag === 'Err')\n return current\n\n if (input._tag === 'ProjectSkill') {\n const source = await collectHostDirectory(input.projectDir, policy, input.projectDir, signal)\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'generate-project-skill', outputName: input.destination.name, source: source.value, sourceDir: '', current: current.value, destination: input.destination })\n }\n\n if (input._tag === 'ReviewSkill') {\n const source = await collectHostDirectory(input.skillDir, policy, input.skillDir, signal)\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'review-skill', outputName: 'review', source: source.value, sourceDir: basename(input.skillDir) })\n }\n\n if (input.source._tag === 'NpmPackage') {\n const source = await prepareNpmPackage(input.source.spec, policy, fetchClient, signal)\n if (signal?.aborted)\n return err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' })\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'generate-package-skill', outputName: input.destination.name, source: source.value, sourceDir: '', current: current.value, destination: input.destination })\n }\n\n const packageDir = resolveWithin(input.source.rootDir, input.source.packageDir)\n if (packageDir === null)\n return err({ _tag: 'InvalidInput', message: 'Local package directory must stay inside its root directory.' })\n const manifest = await lstat(join(packageDir, 'package.json')).catch(error => error as NodeJS.ErrnoException)\n if (manifest instanceof Error || !manifest.isFile() || manifest.isSymbolicLink()) {\n return err({\n _tag: 'SourceUnavailable',\n message: 'Local package directory must contain package.json.',\n attempts: [{ source: packageDir, status: 'skipped', reason: 'package.json is unavailable.' }],\n })\n }\n\n const source = await collectHostDirectory(packageDir, policy, packageDir, signal)\n return source._tag === 'Err'\n ? source\n : ok({ skillName: 'generate-package-skill', outputName: input.destination.name, source: source.value, sourceDir: '', current: current.value, destination: input.destination })\n}\n\nfunction requestContent(skill: HarnessV1Skill): string {\n const request = skill.files?.find(file => file.path === 'assets/harness-request.md')\n if (!request)\n throw new Error(`Harness request asset is missing for ${skill.name}.`)\n return request.content\n}\n\nfunction renderRequest(template: string, sourcePath: string, currentSkillPath: string, outputPath: string, skillName: string): string {\n return template\n .replaceAll('{{SOURCE_PATH}}', sourcePath)\n .replaceAll('{{CURRENT_SKILL_PATH}}', currentSkillPath)\n .replaceAll('{{OUTPUT_PATH}}', outputPath)\n .replaceAll('{{SKILL_NAME}}', skillName)\n}\n\nfunction sourcePathOf(active: ActiveSandbox, prepared: PreparedRun): string {\n return posix.join(active.workDir, 'input/source', prepared.sourceDir)\n}\n\nasync function writePreparedSource(active: ActiveSandbox, prepared: PreparedRun, signal?: AbortSignal): Promise<void> {\n const sourcePath = sourcePathOf(active, prepared)\n const reset = await active.sandbox.run({\n command: 'rm -rf -- \"$SKILLD_INPUT\" \"$SKILLD_OUTPUT\" && mkdir -p -- \"$SKILLD_INPUT\"',\n env: {\n SKILLD_INPUT: posix.join(active.workDir, 'input'),\n SKILLD_OUTPUT: posix.join(active.workDir, 'skilld-output'),\n },\n abortSignal: signal,\n })\n if (reset.exitCode !== 0)\n throw new Error(reset.stderr.trim() || 'Harness work directory cannot be prepared.')\n for (const file of prepared.source.files) {\n await active.sandbox.writeBinaryFile({\n path: posix.join(sourcePath, file.path),\n content: file.content,\n abortSignal: signal,\n })\n }\n for (const file of prepared.current?.files ?? []) {\n await active.sandbox.writeBinaryFile({\n path: posix.join(active.workDir, 'input/current-skill', file.path),\n content: file.content,\n abortSignal: signal,\n })\n }\n await active.sandbox.writeTextFile({\n path: posix.join(active.workDir, 'input/source-manifest.json'),\n content: `${JSON.stringify({\n sourceAttempts: prepared.source.attempts,\n skippedFiles: prepared.source.skippedFiles,\n npmResolution: prepared.source.npmResolution,\n hasCurrentSkill: prepared.current !== undefined,\n }, null, 2)}\\n`,\n abortSignal: signal,\n })\n}\n\nfunction toAgentError(cause: unknown, signal?: AbortSignal): RunOutcome {\n return signal?.aborted\n ? cancelled()\n : err({ _tag: 'AgentFailed', message: 'Harness Agent failed during the Skill run.', cause })\n}\n\nexport function createSkillHarness(options: CreateSkillHarnessOptions): SkillHarness {\n const policy = parseOutputPolicy({ ...DEFAULT_OUTPUT_POLICY, ...options.outputPolicy })\n const fetchClient: FetchClient = options.fetch ?? globalThis.fetch.bind(globalThis)\n const sandboxConfig = { ...options.sandboxConfig }\n const harness = options.harness\n const sandbox = options.sandbox\n\n return {\n // Each input tag maps to one Skill, and that Skill decides the value tag,\n // so the wide result is the narrowed result for this input.\n run: <Run extends SkillRun>(input: Run, runOptions: SkillRunOptions = {}) =>\n runSkill(input, runOptions) as Promise<SkillRunResult<Run['_tag']>>,\n }\n\n async function runSkill(input: SkillRun, runOptions: SkillRunOptions): Promise<SkillRunResult> {\n const log = createRunLog(runOptions.onEvent)\n const outcome = await runLogged(input, runOptions, log)\n const report = log.report()\n return outcome._tag === 'Ok'\n ? { _tag: 'Ok', value: outcome.value, report }\n : { _tag: 'Err', error: outcome.error, report }\n }\n\n async function runLogged(input: SkillRun, runOptions: SkillRunOptions, log: RunLog): Promise<RunOutcome> {\n const parsed = parseSkillRun(input)\n if (parsed._tag === 'Err')\n return parsed\n\n const prepared = await prepareRun(parsed.value, policy, fetchClient, runOptions.signal)\n if (prepared._tag === 'Err')\n return prepared\n for (const warning of skippedFileWarnings(prepared.value.source.skippedFiles, policy))\n log.warn(warning)\n\n const skill = await loadSkilldMaintainedSkill(prepared.value.skillName)\n // The Harness creates and owns the sandbox session, and hands it to the\n // Agent. The Agent never sees the provider, so it never destroys the\n // session itself, and the deprecated provider path stays unused.\n const sandboxSession = await sandbox.createSession({ abortSignal: runOptions.signal }).then(ok, cause => err(cause))\n if (sandboxSession._tag === 'Err')\n return toAgentError(sandboxSession.error, runOptions.signal)\n const result = await runAgent(prepared.value, skill, sandboxSession.value, log, runOptions.signal)\n const destroyed = await Promise.resolve(sandboxSession.value.destroy()).then(() => undefined, cause => cause as unknown)\n if (destroyed !== undefined)\n log.warn(`Sandbox session cleanup failed: ${destroyed instanceof Error ? destroyed.message : String(destroyed)}`)\n return result\n }\n\n async function runAgent(\n prepared: PreparedRun,\n skill: HarnessV1Skill,\n sandboxSession: HarnessV1NetworkSandboxSession,\n log: RunLog,\n signal?: AbortSignal,\n ): Promise<RunOutcome> {\n let active: ActiveSandbox | undefined\n const userOnSession = sandboxConfig.onSession\n const agent = new HarnessAgent({\n harness,\n skills: [skill],\n permissionMode: 'allow-all',\n sandboxConfig: {\n ...sandboxConfig,\n onSession: async (sessionOptions) => {\n active = { sandbox: sessionOptions.session, workDir: sessionOptions.sessionWorkDir }\n await writePreparedSource(active, prepared, signal)\n await userOnSession?.(sessionOptions)\n },\n },\n })\n\n const sessionResult = await agent.createSession({ sandboxSession, abortSignal: signal }).then(ok, cause => err(cause))\n if (sessionResult._tag === 'Err')\n return toAgentError(sessionResult.error, signal)\n const session = sessionResult.value\n\n try {\n if (!active)\n return err({ _tag: 'AgentFailed', message: 'Harness did not provide its sandbox session.' })\n const sourcePath = sourcePathOf(active, prepared)\n const currentSkillPath = posix.join(active.workDir, 'input/current-skill')\n const outputPath = posix.join(active.workDir, 'skilld-output', prepared.outputName)\n const prompt = renderRequest(requestContent(skill), sourcePath, currentSkillPath, outputPath, prepared.outputName)\n let step = 0\n const generated = await agent.generate({\n session,\n prompt,\n abortSignal: signal,\n onStepStart: (event) => {\n step = event.stepNumber\n log.emit({ _tag: 'StepStart', step })\n },\n onToolExecutionStart: ({ toolCall }) => {\n log.emit({ _tag: 'ToolCall', step, toolName: toolCall.toolName, toolCallId: toolCall.toolCallId, input: toolCall.input })\n },\n onStepEnd: (result) => {\n log.emit({ _tag: 'StepFinish', step: result.stepNumber, finishReason: result.finishReason, usage: toUsage(result.usage) })\n },\n }).then(ok, cause => err(cause))\n if (generated._tag === 'Err')\n return toAgentError(generated.error, signal)\n log.settle(toUsage(generated.value.totalUsage), generated.value.steps.length)\n if (signal?.aborted)\n return cancelled()\n\n const collected = await collectSandboxOutput(active.sandbox, outputPath, policy, signal)\n if (collected._tag === 'Err')\n return collected\n\n if (prepared.skillName === 'review-skill')\n return validateSkillReview(collected.value)\n\n const validated = validateGeneratedSkill(\n prepared.outputName,\n collected.value,\n prepared.skillName === 'generate-project-skill'\n ? { _tag: 'ProjectSkill', projectPaths: prepared.source.files.map(file => file.path) }\n : { _tag: 'PackageSkill' },\n )\n if (validated._tag === 'Err')\n return validated\n if (!prepared.destination)\n return err({ _tag: 'InvalidInput', message: 'Skill destination is required.' })\n const promoted = await promoteSkill(\n prepared.destination.rootDir,\n prepared.destination.name,\n collected.value,\n prepared.source.attempts,\n )\n if (promoted._tag === 'Err')\n return promoted\n for (const warning of promoted.value.warnings)\n log.warn(warning)\n return ok(promoted.value.skill)\n }\n finally {\n await session.destroy()\n }\n }\n}\n"],"mappings":";;;;;;;;;AAIA,MAAa,MAAS,WAAgC;CAAE,MAAM;CAAM;AAAM;AAC1E,MAAa,OAAU,WAAgC;CAAE,MAAM;CAAO;AAAM;ACC5E,SAASA,UAAQ,SAA+C;CAC9D,OAAO,IAAI;EAAE,MAAM;EAAgB;CAAQ,CAAC;AAC9C;AAEA,SAAS,iBAAiB,OAAiC;CACzD,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,CAAC,CAAC,SAAS;AAC5D;AAEA,SAAgB,cAAc,OAAkD;CAC9E,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,EAAE,UAAU,QACrD,OAAOA,UAAQ,+CAA+C;CAEhE,IAAI,MAAM,SAAS,gBAAgB;EACjC,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,aAC1B,OAAOA,UAAQ,oCAAoC;EACrD,IAAI,CAAC,iBAAiB,MAAM,YAAY,OAAO,KAAK,CAAC,YAAY,MAAM,YAAY,IAAI,GACrF,OAAOA,UAAQ,uCAAuC;EACxD,IAAI,MAAM,OAAO,SAAS,cAAc;GACtC,IAAI,CAAC,iBAAiB,MAAM,OAAO,IAAI,GACrC,OAAOA,UAAQ,+BAA+B;GAChD,OAAO,GAAG;IACR,MAAM;IACN,QAAQ;KAAE,MAAM;KAAc,MAAM,MAAM,OAAO;IAAK;IACtD,aAAa;KAAE,SAAS,QAAQ,MAAM,YAAY,OAAO;KAAG,MAAM,MAAM,YAAY;IAAK;GAC3F,CAAC;EACH;EACA,IAAI,MAAM,OAAO,SAAS,gBAAgB;GACxC,IAAI,CAAC,iBAAiB,MAAM,OAAO,OAAO,KAAK,CAAC,iBAAiB,MAAM,OAAO,UAAU,GACtF,OAAOA,UAAQ,mCAAmC;GACpD,IAAI,cAAc,MAAM,OAAO,SAAS,MAAM,OAAO,UAAU,MAAM,MACnE,OAAOA,UAAQ,8DAA8D;GAC/E,OAAO,GAAG;IACR,MAAM;IACN,QAAQ;KACN,MAAM;KACN,SAAS,QAAQ,MAAM,OAAO,OAAO;KACrC,YAAY,MAAM,OAAO;IAC3B;IACA,aAAa;KAAE,SAAS,QAAQ,MAAM,YAAY,OAAO;KAAG,MAAM,MAAM,YAAY;IAAK;GAC3F,CAAC;EACH;EACA,OAAOA,UAAQ,gCAAgC;CACjD;CAEA,IAAI,MAAM,SAAS,gBAAgB;EACjC,IAAI,CAAC,iBAAiB,MAAM,UAAU,KAAK,CAAC,MAAM,aAChD,OAAOA,UAAQ,oCAAoC;EACrD,IAAI,CAAC,iBAAiB,MAAM,YAAY,OAAO,KAAK,CAAC,YAAY,MAAM,YAAY,IAAI,GACrF,OAAOA,UAAQ,uCAAuC;EACxD,OAAO,GAAG;GACR,MAAM;GACN,YAAY,QAAQ,MAAM,UAAU;GACpC,aAAa;IAAE,SAAS,QAAQ,MAAM,YAAY,OAAO;IAAG,MAAM,MAAM,YAAY;GAAK;EAC3F,CAAC;CACH;CAEA,IAAI,MAAM,SAAS,eAAe;EAChC,IAAI,CAAC,iBAAiB,MAAM,QAAQ,GAClC,OAAOA,UAAQ,qCAAqC;EACtD,OAAO,GAAG;GAAE,MAAM;GAAe,UAAU,QAAQ,MAAM,QAAQ;EAAE,CAAC;CACtE;CAEA,OAAOA,UAAQ,2BAA2B;AAC5C;AAEA,SAAgB,kBAAkB,QAA8C;CAC9E,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,MAAM,GAC/C,IAAI,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GAC3C,MAAM,IAAI,UAAU,GAAG,KAAK,6BAA6B;CAE7D,OAAO,OAAO,OAAO,MAAM;AAC7B;AChEA,MAAMC,aAAW,SAAiB,WAChC,IAAI;CAAE,MAAM;CAAgB;CAAS;AAAO,CAAC;AAE/C,MAAM,YAAY,OAChB,SACA,WACA,WACgG;CAChG,IAAI,QAAQ,SACV,OAAO,IAAI;EAAE,MAAM;EAAa,SAAS;CAA2B,CAAC;CACvE,MAAM,UAAU;CAChB,MAAM,SAAS,MAAM,QAAQ,QAAQ,CAAC,CAAC,WAAW,QAAQ,IAAI;EAC5D;EACA,KAAK;GAAE,QAAQ;GAAK,eAAe;EAAU;EAC7C,aAAa;CACf,CAAC,CAAC,CAAC,CAAC,OAAM,UAAS,KAAc;CACjC,IAAI,kBAAkB,OACpB,OAAOA,UAAQ,uCAAuC,CAAC,OAAO,OAAO,CAAC;CACxE,IAAI,OAAO,aAAa,GACtB,OAAOA,UAAQ,wCAAwC,CAAC,OAAO,OAAO,KAAK,KAAK,sBAAsB,CAAC;CAEzG,MAAM,SAAS,OAAO,OAAO,MAAM,IAAI;CACvC,IAAI,OAAO,GAAG,EAAE,MAAM,IACpB,OAAO,IAAI;CACb,IAAI,OAAO,SAAS,MAAM,GACxB,OAAOA,UAAQ,wCAAwC,CAAC,yCAAyC,CAAC;CAEpG,MAAM,UAA+D,CAAC;CACtE,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAAG;EACrD,MAAM,OAAO,OAAO;EACpB,MAAM,OAAO,OAAO,QAAQ;EAC5B,MAAM,OAAO,OAAO,OAAO,QAAQ,EAAE;EACrC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,cAAc,IAAI,KAAK,OAAO,GAC1D,OAAOA,UAAQ,wCAAwC,CAAC,oCAAoC,CAAC;EAC/F,QAAQ,KAAK;GAAE;GAAM;GAAM;EAAK,CAAC;CACnC;CACA,OAAO,GAAG,OAAO;AACnB;AAEA,MAAa,uBAAuB,OAClC,SACA,WACA,QACA,WACiE;CACjE,MAAM,SAAS,MAAM,UAAU,SAAS,WAAW,MAAM;CACzD,IAAI,OAAO,SAAS,OAClB,OAAO;CAET,MAAM,QAAyB,CAAC;CAChC,MAAM,uBAAO,IAAI,IAAY;CAC7B,IAAI,aAAa;CACjB,KAAK,MAAM,SAAS,OAAO,OAAO;EAChC,IAAI,QAAQ,SACV,OAAO,IAAI;GAAE,MAAM;GAAa,SAAS;EAA2B,CAAC;EACvE,MAAM,OAAO,oBAAoB,MAAM,IAAI;EAC3C,IAAI,SAAS,MACX,OAAOA,UAAQ,4CAA4C,CAAC,MAAM,IAAI,CAAC;EACzE,IAAI,MAAM,SAAS,KACjB;EACF,IAAI,MAAM,SAAS,KACjB,OAAOA,UAAQ,sDAAsD,CAAC,IAAI,CAAC;EAC7E,IAAI,KAAK,IAAI,IAAI,GACf,OAAOA,UAAQ,4CAA4C,CAAC,IAAI,CAAC;EACnE,IAAI,MAAM,UAAU,OAAO,gBACzB,OAAOA,UAAQ,2CAA2C,CAAC,UAAU,OAAO,gBAAgB,CAAC;EAC/F,IAAI,MAAM,OAAO,OAAO,oBACtB,OAAOA,UAAQ,8CAA8C,CAAC,IAAI,CAAC;EACrE,IAAI,aAAa,MAAM,OAAO,OAAO,gBACnC,OAAOA,UAAQ,gDAAgD,CAAC,UAAU,OAAO,gBAAgB,CAAC;EAEpG,MAAM,UAAU,MAAM,QAAQ,QAAQ,CAAC,CAAC,WAAW,QAAQ,eAAe;GAAE,MAAM,GAAG,UAAU,GAAG;GAAQ,aAAa;EAAO,CAAC,CAAC,CAAC,CAAC,OAAM,UAAS,KAAc;EAC/J,IAAI,mBAAmB,OAAO;GAC5B,IAAI,QAAQ,SACV,OAAO,IAAI;IAAE,MAAM;IAAa,SAAS;GAA2B,CAAC;GACvE,OAAOA,UAAQ,kCAAkC,CAAC,MAAM,QAAQ,OAAO,CAAC;EAC1E;EACA,IAAI,YAAY,QAAQ,QAAQ,eAAe,MAAM,MACnD,OAAOA,UAAQ,6CAA6C,CAAC,IAAI,CAAC;EACpE,KAAK,IAAI,IAAI;EACb,MAAM,KAAK;GAAE;GAAM,SAAS,WAAW,KAAK,OAAO;EAAE,CAAC;EACtD,cAAc,QAAQ;CACxB;CAEA,MAAM,QAAQ,MAAM,UAAU,SAAS,WAAW,MAAM;CACxD,IAAI,MAAM,SAAS,OACjB,OAAO;CACT,IAAI,KAAK,UAAU,OAAO,KAAK,MAAM,KAAK,UAAU,MAAM,KAAK,GAC7D,OAAOA,UAAQ,6CAA6C,CAAC,yBAAyB,CAAC;CAEzF,MAAM,MAAM,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;CAC/D,OAAO,GAAG,KAAK;AACjB;ACjGA,SAAS,UAAU,SAAiB,MAA4C;CAC9E,OAAO,IAAI;EAAE,MAAM;EAAoB;EAAS;CAAK,CAAC;AACxD;AAEA,MAAM,UAAU,OAAO,SAAS;AAQhC,eAAe,cAAc,MAAc;CACzC,OAAO,MAAM,IAAI,CAAC,CAAC,OAAM,UAAU,MAAgC,SAAS,WAAW,UAAU,QAAQ,OAAO,KAAK,CAAC;AACxH;AAEA,MAAa,eAAe,OAC1B,SACA,MACA,OACA,aACkD;CAClD,MAAM,OAAO,QAAQ,OAAO;CAC5B,IAAI,WAAW,MAAM,cAAc,IAAI,CAAC,CAAC,OAAM,UAAS,KAAc;CACtE,IAAI,oBAAoB,OACtB,OAAO,UAAU,oCAAoC,IAAI;CAC3D,IAAI,cAAc;CAClB,IAAI,aAAa,SAAS;EACxB,MAAM,SAAS,QAAQ,IAAI;EAC3B,MAAM,aAAa,MAAM,cAAc,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;EAC5E,IAAI,sBAAsB,SAAS,eAAe,WAAW,CAAC,WAAW,YAAY,KAAK,WAAW,eAAe,GAClH,OAAO,UAAU,qDAAqD,MAAM;EAC9E,MAAM,kBAAkB,MAAM,SAAS,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;EAC5E,IAAI,2BAA2B,SAAS,oBAAoB,QAC1D,OAAO,UAAU,6DAA6D,MAAM;EACtF,MAAM,UAAU,MAAM,MAAM,MAAM,EAAE,MAAM,IAAM,CAAC,CAAC,CAAC,WAAW,OAAM,UAAS,KAA8B;EAC3G,IAAI,mBAAmB,SAAS,QAAQ,SAAS,UAC/C,OAAO,UAAU,kCAAkC,IAAI;EACzD,cAAc,YAAY;EAC1B,WAAW,MAAM,cAAc,IAAI,CAAC,CAAC,OAAM,UAAS,KAAc;CACpE;CACA,IAAI,oBAAoB,SAAS,aAAa,WAAW,CAAC,SAAS,YAAY,KAAK,SAAS,eAAe,GAC1G,OAAO,UAAU,yDAAyD,IAAI;CAChF,MAAM,gBAAgB,MAAM,SAAS,IAAI,CAAC,CAAC,OAAM,UAAS,KAAc;CACxE,IAAI,yBAAyB,OAC3B,OAAO,UAAU,mCAAmC,IAAI;CAC1D,IAAI,kBAAkB,MACpB,OAAO,UAAU,sDAAsD,IAAI;CAE7E,MAAM,SAAS,KAAK,MAAM,IAAI;CAC9B,MAAM,aAAa,MAAM,cAAc,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;CAC5E,IAAI,sBAAsB,OACxB,OAAO,UAAU,oCAAoC,MAAM;CAC7D,IAAI,eAAe,YAAY,CAAC,WAAW,YAAY,KAAK,WAAW,eAAe,IACpF,OAAO,UAAU,yDAAyD,MAAM;CAElF,MAAM,WAAW,KAAK,MAAM,WAAW,KAAK,MAAM;CAClD,MAAM,OAAO,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,OAAM,UAAS,KAA8B;CACrF,IAAI,gBAAgB,OAAO;EACzB,IAAI,KAAK,SAAS,UAChB,OAAO,IAAI;GAAE,MAAM;GAAc,SAAS;GAA4C,MAAM;EAAO,CAAC;EACtG,OAAO,IAAI;GAAE,MAAM;GAAmB,SAAS;GAAqC,MAAM;GAAQ,OAAO;EAAK,CAAC;CACjH;CAEA,MAAM,QAAQ,WAAW;CACzB,MAAM,UAAU,KAAK,MAAM,WAAW,KAAK,GAAG,MAAM,MAAM;CAC1D,MAAM,SAAS,KAAK,MAAM,WAAW,KAAK,GAAG,MAAM,UAAU;CAC7D,IAAI,eAAe;CACnB,IAAI,WAAW;CACf,IAAI,iBAAiB;CACrB,IAAI;CAEJ,IAAI;EACF,MAAM,MAAM,SAAS,EAAE,MAAM,IAAM,CAAC;EACpC,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,cAAc,KAAK,SAAS,KAAK,IAAI;GAC3C,MAAM,MAAM,QAAQ,WAAW,GAAG;IAAE,WAAW;IAAM,MAAM;GAAM,CAAC;GAClE,MAAM,UAAU,aAAa,KAAK,SAAS;IAAE,MAAM;IAAM,MAAM;GAAM,CAAC;EACxE;EAEA,IAAI,eAAe,SAAS;GAC1B,MAAM,OAAO,QAAQ,MAAM;GAC3B,eAAe;EACjB;EACA,MAAM,OAAO,SAAS,MAAM;EAC5B,WAAW;CACb,SACO,OAAO;EACZ,eAAe;EACf,IAAI,gBAAgB,CAAC,UAAU;GAC7B,MAAM,UAAU,MAAM,cAAc,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;GACzE,IAAI,mBAAmB,OAAO;IAC5B,iBAAiB;IACjB,eAAe,IAAI,eAAe,CAAC,OAAO,OAAO,CAAC;GACpD;GACA,IAAI,YAAY,SAAS;IACvB,MAAM,WAAW,MAAM,OAAO,QAAQ,MAAM,CAAC,CAAC,OAAM,UAAS,KAAc;IAC3E,IAAI,oBAAoB,OAAO;KAC7B,iBAAiB;KACjB,eAAe,IAAI,eAAe,CAAC,OAAO,QAAQ,CAAC;IACrD;GACF;EACF;CACF;CAEA,MAAM,oBAA+B,CAAC;CACtC,MAAM,KAAK,MAAM,CAAC,CAAC,OAAM,UAAS,kBAAkB,KAAK,KAAK,CAAC;CAC/D,MAAM,OAAO,QAAQ,CAAC,CAAC,OAAM,UAAS,kBAAkB,KAAK,KAAK,CAAC;CAEnE,IAAI,UAAU;EACZ,MAAM,WAAqB,CAAC;EAC5B,IAAI,kBAAkB,SAAS,GAAG;GAChC,MAAM,SAAS,kBAAkB,KAAI,UAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;GAC/G,SAAS,KAAK,iCAAiC,SAAS,IAAI,QAAQ;EACtE;EACA,IAAI,cAAc;GAChB,MAAM,gBAAgB,MAAM,GAAG,QAAQ,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,OAAM,UAAS,KAAc;GACzF,IAAI,yBAAyB,OAC3B,SAAS,KAAK,oCAAoC,OAAO,IAAI,cAAc,SAAS;EACxF;EACA,OAAO,GAAG;GACR,OAAO;IACL,MAAM;IACN;IACA,WAAW;IACX,OAAO,MAAM,KAAI,UAAS;KAAE,MAAM,KAAK;KAAM,OAAO,KAAK,QAAQ;IAAW,EAAE;IAC9E,gBAAgB;GAClB;GACA;EACF,CAAC;CACH;CAEA,MAAM,gBAAgB,CAAC,GAAG,iBAAiB;CAC3C,MAAM,GAAG,SAAS;EAAE,WAAW;EAAM,OAAO;CAAK,CAAC,CAAC,CAAC,OAAM,UAAS,cAAc,KAAK,KAAK,CAAC;CAC5F,IAAI,aACF,MAAM,MAAM,IAAI,CAAC,CAAC,OAAM,UAAS,cAAc,KAAK,KAAK,CAAC;CAC5D,MAAM,SAAS,iBAAiB,KAAA,IAAY,gBAAgB,CAAC,cAAc,GAAG,aAAa;CAC3F,MAAM,QAAQ,OAAO,UAAU,IAAI,OAAO,KAAK,IAAI,eAAe,QAAQ,8BAA8B;CACxG,OAAO,IAAI;EAAE,MAAM;EAAmB,SAAS;EAAgB,MAAM;EAAQ;CAAM,CAAC;AACtF;AClJA,MAAM,gBAAgB;AAGtB,MAAM,aAAa;AAGnB,MAAM,cAAc;;;;;;AASpB,SAAM,gBAAS,UAAA;CAEf,OAAM,SAAW,QAAA,aAAA,EAAA,CAAA,CAAA,MAAA,YAAA,CAAA,CAAA,KAAA,cAAA,UAAA,QAAA,OAAA,GAAA,CAAA,CAAA,KAAA,CAAA,CAAA,CAAA,QAAA,cAAA,UAAA,SAAA,CAAA;AAEjB;AAEA,MAAA,gBAAA;;;AAOA,SAAS,cAAA,OAAgB;CACvB,IAAA,MAAO,WACJ,KAAQ,KAAA,KAAA,KACR,GAAA,OAAM;CAGX,IAAA,YAAA,KAAA,KAAA,GAAA,OAAA;;;;;CAMA,IAAA,CAAM,QAAA,SAAgB,GAAA,KAAA,CAAA,cAAA,KAAA,OAAA,GAAA,OAAA;;AAGtB;AAGA,SAAM,cAAc,WAAA;;;;;AAMpB,SAAS,SAAA,WAAc,OAA8B;CACnD,IAAI,MAAM,IAAA,SAAW,GAAK,OAAK;CAG/B,MAAI,SAAA,cACF,SAAO;CAET,IAAI,OAAM,WAAS,GAAK,OAAK;CAE7B,KAAA,MAAM,QAAU,OAAM;EACtB,IAAI,KAAA,WAAQ,GAAW,UAAK,EAAQ,GAAA,OAAA;EAGpC,IAAI,SAAA,UAAkB,KAAO,WAAK,GAAA,OAAY,EAAK,GAAA,OAAO;CAG1D;CAEA,OAAO;AACT;AAGA,SAAS,kBAAc,OAA2B;CAChD,MAAM,SAAA,CAAA;CACN,MAAI,wBACK,IAAA,IAAA,CAAA,GAAA,MAAA,cAAA,GAAA,MAAA,WAAA,CAAA;CAET,MAAA,0BAD+B,IAAU,IAAA;CAE3C,KAAA,MAAA,aAAA,gBAAA,MAAA,QAAA,GAAA;EAEA,IAAA,OAAS,KAAS,SAAA,KAAmB,SAAqC,KAAA,SAAA,GAAA;EACxE,KAAI,MAAM,SAAI,UACZ,SAAO,UAAA,GAAA;GACT,MAAM,YAAS,cAAc,MAAS,EAAA,CAAA,KAAA,CAAA;GACtC,IAAI,cAAO,QACT,CAAA,SAAO,WAAA,KAAA,GAAA,QAAA,IAAA,SAAA;EACT;CAEE;CAGA,KAAI,MAAA,QAAS,CAAA,GAAA,OAAe,CAAA,CAAA,KAAA,GAAW,OAAG,KAAS,2DAC1C,KAAA,EAAA;CACX,MAAA,SAAA,CAAA,GAAA,MAAA,SAAA,SAAA,UAAA,CAAA,CAAA,CAAA,KAAA,UAAA,MAAA,EAAA;CACA,MAAA,WAAO,CAAA,GAAA,aAAA,MAAA,QAAA,GAAA,GAAA,MAAA,CAAA,CAAA,KAAA,IAAA;CACT,IAAA,CAAA,cAAA,KAAA,QAAA,GAAA,OAAA,KAAA,yEAAA;;;;;;AAoBA,MAAA,WAAgB,WAAkB,IAAA;CAChC,MAAM;CACN,SAAM;CACN;AAEA,CAAA;AACE,SAAI,WAAY,SAAS;CAEzB,IAAA;EACE,OAAM,IAAA,YAAY,SAAA,EAAc,OAAQ,KAAE,CAAK,CAAC,CAAA,OAAA,OAAA;CAChD,QAAI;EAEN,OAAA;CACF;AAEA;AAIA,SAAM,YAAY,UAAG;CACrB,MAAK,0BAA2B,IAC9B,IAAA;CAEF,MAAA,OAAO,QAAA;EACT,MAAA,SAAA,IAAA,KAAA,CAAA,CAAA,QAAA,UAAA,EAAA,CAAA,CAAA,MAAA,IAAA,CAAA,CAAA,EAAA,CAAA,QAAA,WAAA,EAAA,CAAA,CAAA,QAAA,SAAA,EAAA;;;CCrIA,KAAM,MAAA,SAAA,SAAA,SAAA,kBAA8B,GAAQ,IAAA,MAAA,EAAA;;CAG5C,KAAM,MAAA,SAAA,SAAwB,SAAA,cAAA,GAAA,IAAA,MAAA,EAAA;;AAG9B;AAUA,SAAM,UAAW,MAAA;CACT,MAAM,QAAA,KAAA,MAAA,IAAA;CAAgB,OAAA,MAAS,GAAA,EAAA,MAAA,KAAA,MAAA,SAAA,IAAA,MAAA;AAA6C;AAEpF,SAAS,gBAAW,UAAoC,OAAA,UAAA;CACtD,MAAI,SAAA,CAAA;CACF,MAAA,iBAAW,MAAY,KAAS,SAAS,KAAM,IAAE,CAAA,CAAA,QAAO,SAAO,KAAA,WAAA,aAAA,CAAA,CAAA,CAAA,KAAA;CACjE,IAAA,SACM,SAAA,gBAAA;EACJ,MAAA,QAAO,UAAA,QAAA;EACT,IAAA,SAAA,uBAAA,OAAA,KAAA,4BAAA,sBAAA,iBAAA,MAAA,EAAA;EACF,IAAA,eAAA,SAAA,4BAAA,OAAA,KAAA,qCAAA,2BAAA,6BAAA,eAAA,OAAA,EAAA;;CAGA,MAAA,SAAS,YAAY,QAAuC;CAC1D,KAAA,MAAM,QAAA,gBAAU,IAAI,CAAY,OAAA,IAAA,IAAA,GAAA,OAAA,KAAA,sBAAA,KAAA,EAAA;CAChC,OAAM;AACJ;AACA,MAAI,0BACF,MAAY,OAAM,aAAA;CACtB,MAAA,SAAA,CAAA;CACA,MAAK,aAAM,MAAS,QAAS,SAAS,KAAA,SAAkB,UAClD;CACN,IAAA,WAAW,WAAS,GAAS,OAAA,QAAS,CAAA,gDACvB,CAAA;CACf,MAAK,SAAM,WAAS,WAAS,EAAS,CAAA,OAAA;CAEtC,IAAA,WAAO,MAAA,OAAA,QAAA,CAAA,yCAAA,CAAA;CACT,IAAA,SAAA,SAAA,gBAAA,OAAA,KAAA,GAAA,kBAAA;EAEA,UAAS;EACP,cAAc,SAAK;EACnB,aAAa,MAAK,KAAM,SAAK,KAAM,IAAA;CACrC,CAAA,CAAA;;CAGA,IAAA,CAAA,OAAS,OAAA,QAAgB,CAAA,4CAA4G,CAAA;CACnI,IAAA,MAAM,EAAA,EAAA,KAAoB,CAAA,CAAA,WAAA,GAAA,OAAA,KAAA,0CAAA;CAC1B,MAAM,WAAA,cAAuB,MAAI,IAAA,EAAQ,YAAW,KAAA,CAAA;CACpD,KAAI,MAAA,SAAS,SAAS,QAAA,OAAgB,KAAA,gBAAA,MAAA,SAAA;CACpC,KAAA,MAAM,WAAQ,SAAU,UAAQ,OAAA,KAAA,gBAAA,QAAA,SAAA;CAChC,MAAI,QAAS,SAAA,OAAA,WACX,IAAO,SAAK,KAAA,IAAA;CACd,IAAA,CAAI,SAAA,OAAe,UAAS,YAAA,MAAA,QAC1B,KAAA,GAAO;EACX,OAAA,KAAA,gCAAA;EACA,OAAM,QAAS,MAAA;CACf;CAIA,MAAA,cAAO;CACT,KAAA,MAAA,OAAA,OAAA,KAAA,WAAA,GAAA,IAAA,CAAA,mBAAA,IAAA,GAAA,GAAA,OAAA,KAAA,uCAAA,KAAA;CAEA,IAAA,YAAa,SAAA,MACX,OACA,KAAA,uDAEgC;CAChC,IAAA,OAAM,YAAoB,SAAA,YAAA,CAAA,YAAA,YAAA,IAAA,GAAA,OAAA,KAAA,8BAAA;CAC1B,IAAA,OAAM,YAAa,gBAAa,YAAa,YAAS,YAAU,KAAA,CAAA,CAAA,WAAA,KAAA,YAAA,YAAA,SAAA,MAAA,OAAA,KAAA,4DAAA;CAChE,OAAI,KAAA,GAAW,gBACb,QAAO,OAAS,QAAA,CAAA;CAElB,OAAM,OAAA,WAAS,IAAW,GAAA,KAAW,CAAA,IAAI,QAAO,MAAA;AAChD;AAEA,MAAI,gCAAkB,IACpB,IAAO;CACL;CACA;CACA;AACF,CAAA;AAEF,MAAA,uBAA2B,UAAA;CAC3B,IAAI,MAAC,WACI,KAAA,MAAS,EAAA,EAAA,SAAA,eAAA,OAAA,QAA6C,CAAA,8CAAA,CAAA;CAC/D,IAAI;CAGJ,IAAA;EACA,MAAK,SAAM,WAAS,MAAS,EAAA,CAAA,OAC3B;EACF,IAAK,WAAM,MAAW,OAAA,QAAS,CAAA,4CACO,CAAA;EAEtC,QAAM,KAAQ,MAAA,MAAS;CACvB,QAAK;EACH,OAAO,QAAK,CAAA,sCAAgC,CAAA;CAC5C;CACF,IAAA,CAAA,SAAA,OAAA,UAAA,YAAA,MAAA,QAAA,KAAA,GAAA,OAAA,QAAA,CAAA,qCAAA,CAAA;CAEA,MAAM,SAAA;CACN,IAAA,OAAW,KAAA,MAAO,CAAA,CAAA,MAAY,QAAA,QAC5B,aAAK,QAAA,UAA0B,GAC7B,OAAO,QAAK,CAAA,0CAA4C,CAAA;CAE5D,IAAI,OAAA,OAAY,YAAS,YAChB,OAAK,QAAA,KAAA,CAAA,CAAA,WAAA,GAAA,OAAA,QAAA,CAAA,6BAAuD,CAAA;CACrE,IAAI,CAAA,MAAO,QAAA,OAAY,QAAS,GAAA,OAAY,QAAC,CAAA,mCAC/B,CAAA;CACd,MAAI,WAAO,CAAA;CAEX,KAAA,MAAO,QAAQ,OAAA,UAAgB;EAE/B,IAAA,CAAA,QAAc,OAAA,SAAe,YAAgB,MAAA,QAAc,IAAA,GAAA,OAAA,QAAA,CAAA,wCAAA,CAAA;EAC7D,MAAA,UAAA;EAEA,IAAM,OAAA,KAAA,OAAA,CAAA,CAAA,MAAA,QAAgB,CAAI;GAAK;GAAS;GAAW;GAAO;EAE1D,CAAA,CAAA,SAAa,GAAA,CAAA,GAAA,OAAA,QACX,CAAA,+CACuC,CAAA;EACvC,IAAI,OAAM,QAAA,UAAgB,YAAU,CAAA,cAAS,IAC3C,QAAO,KAAA,GAAS,OAAA,QAAA,CAAA,oCAA+C,CAAA;EAEjE,IAAI,OAAA,QAAA,SAAA,YAAA,oBAAA,QAAA,IAAA,MAAA,MAAA,OAAA,QAAA,CAAA,mCAAA,CAAA;EACJ,IAAI,OAAA,QAAA,YAAA,YAAA,QAAA,QAAA,KAAA,CAAA,CAAA,WAAA,KAAA,OAAA,QAAA,QAAA,YAAA,QAAA,IAAA,KAAA,CAAA,CAAA,WAAA,GAAA,OAAA,QAAA,CAAA,iCAAA,CAAA;EACF,SAAM,KAAA,OAAS;CACf;CAEA,OAAA,GAAQ;EACV,MAAA;EAEE,SAAO,OAAS;EAClB;CACA,CAAA;AAGA;AAKA,SAAK,oBAAqB,SACxB,QAAO;CAET,OAAM,QAAA,KAAkC,SAAA,eAAA,KAAA,KAAA,iBAAA,KAAA,MAAA,qBAAA,OAAA,mBAAA,kBAAA;AACxC;AACE,MAAI,+BAAyB,IAAA,IAAY;CAEzC;CACA;CAAuC;CAAS;CAAQ;CAAW;CAAK;CAExE;CAEA;CAEA;CAEA;AACF,CAAA;AAEA,eAAU,qBAAA,WAAA,QAAA,cAAA,WAAA,QAAA;CAAE,MAAA,OAAM,QAAA,SAAA;CAAe,MAAA,eAAgB,SAAA,UAAA,IAAA;EAAS,MAAA;EAAU;EACtE,UAAA,CAAA;;;GCpJA,QAAgB;EACd,CAAA;EAEF;CAEA,CAAA;CACE,MAAA,kBAAA,IAAA;EACA,MAAA;EACA,SAAA;CACA,CAAA;CACA,IAAA,QAAA,SAAA,OAAA,UAAA;CACA,MAAA,WAAA,MAAA,MAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CACA,IAAA,oBAAA,OAAA,OAAA,YAAA,oCAAA,QAAA;CACA,IAAA,CAAA,SAAA,YAAA,KAAA,SAAA,eAAA,GAAA,OAAA,YAAA,uDAAA;CACA,MAAA,gBAAA,MAAA,SAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CACA,IAAA,yBAAA,OAAA,OAAA,YAAA,wCAAA,aAAA;CACA,IAAA,kBAAA,MAAA,OAAA,YAAA,oDAAA;CACD,MAAA,QAAA,CAAA;CAED,MAAA,eAAsB,CAAA;CACpB,IAAA,aAAa;CACb,MAAM,gBAAe,aAAiB,SAAsD,MAAA,QAAA,CAAA,CAAA,MAAA,GAAA,CAAA,CAAA,KAAA,GAAA;CAE1F,MAAA,oBAAA,UAAA,SAAA,OAAA,QAAA,YAAA,GAAA,QAAA,IAAA,aAAA,QAAA,EAAA,GAAA,QAAA,KAAA,IAAA,KAAA,IAAA,SAAA,KAAA;CACA,MAAA,OAAW,OAAA,YAAA;EAAE,IAAA,QAAQ,SAAA,OAAA,UAAA;EAAa,MAAA,mBAAQ,MAAA,SAAA,OAAA,CAAA,CAAA,OAAA,UAAA,KAAA;EAAW,IAAA,4BAAQ,SAAA,qBAAA,SAAA,OAAA,YAAA,+CAAA,4BAAA,QAAA,mBAAA,KAAA,CAAA;EAAQ,MAAC,kBAAA,MAAA,QAAA,OAAA,CAAA,CAAA,OAAA,UAAA,KAAA;EACtE,IAAA,2BAAA,OAAA,OAAA,YAAA,oCAAA,eAAA;EACD,WAAA,MAAA,SAAA,iBAAA;GACD,IAAM,QAAA,SAAA,OAAoD,UAAA;GAAE,IAAA,aAAM,IAAA,MAAA,IAAA,GAAA;GAAa,MAAA,WAAS,KAAA,SAAA,MAAA,IAAA;GAA4B,MAAA,OAAA,MAAA,MAAA,QAAA,CAAA,CAAA,OAAA,UAAA,KAAA;GACpH,IAAI,gBACF,OAAO,OAAA,iBAAU,UAAA,+BAAA,IAAA;GACnB,IAAM,KAAA,eAAiB,GAAM,OAAM,iBAAe,UAA8B,mCAAA,KAAA,GAAA,mFAAA;GAChF,IAAI,KAAA,YAAA,GAAoB;IAExB,MAAK,SAAS,MAAA,KAAY,QAAK;IAE/B,IAAM,OAAA,SAAgB,OAAM,OAAS;IACrC;GAEA;GAGA,IAAM,CAAA,KAAA,OAAyB,GAAA,OAAA,iBAAA,UAAA,gCAAA;GAC/B,MAAM,OAAA,aAAqC,QAAA;GAC3C,MAAI,SAAa,MAAA,KAAA,UAAA,UAAA,WAAA,UAAA,UAAA,CAAA,CAAA,OAAA,UAAA,KAAA;GACjB,IAAM,kBAAgB,OAAA,OAA6B,iBAAe,UAAU,wDAAmB,MAAA;;GAE/F,IAAM,sBAAoB,OAAA;IAG1B,MAAM,OAAO,MAAO;IAClB,OAAI,iBACF,UAAO,mCAAU,UAAA;GACnB;GACA,IAAI,CAAA,WAAA,OAAA,KAAA,WAA4B,QAAS,KAAA,OAAA,WACvC,QAAO,KAAA,KAAA;IACT,MAAM,OAAA,MAAA;IACN,OAAI,iBAAA,UAA2B,uCACV;GAErB;GACE,IAAI,WAAQ,OACV,OAAO,oBAAU;IACnB,MAAI,OAAA,MAAa;IAEjB,aAAM,KAAW;KACjB;KACA,OAAI,WAAgB;IAEpB,CAAA;IAEA;GACE;GACA,IAAA,MAAI,UAAO,OAAS,gBACX;IACT,MAAA,OAAA,MAAA;IACF,OAAA,YAAA,iCAAA;GACA;GAGA,IAAA,aAAa,WAAa,OAAQ,OAAA,gBAAA;IAClC,MAAM,OAAA,MAAS;IACf,OAAI,YAAA,sCACsB;GAC1B;GACA,MAAI,UAAA,MAAA,OAAsB,SAAO,CAAA,CAAA,OAAA,UAAA,KAAA;GAC/B,MAAA,OAAM,MAAO;GACb,IAAA,mBAAO,OAAiB,OAAU,iBAAA,UAAA,8BAA6C,OAAA;GACjF,IAAA,QAAA,eAAA,WAAA,MAAA,OAAA,iBAAA,UAAA,uCAAA;GACA,IAAI,QAAC,SAAW,OAAY,UAAA;GAC1B,MAAA,KAAM;IACN;IACF;GACA,CAAA;GACE,cAAa,QAAM;EACnB;EAAoB,OAAA,GAAA,KAAA,CAAA;CAAM;CAAuB,MAAC,SAAA,MAAA,KAAA,IAAA;CAClD,IAAA,OAAA,SAAA,OAAA,OAAA;CACF,IAAA,MAAA,WAAA,GAAA,OAAA,YAAA,uCAAA;CACA,MAAI,MAAM,MAAA,UAAU,KAAO,KAAA,cAAgB,MAAA,IAAA,CAAA;CACzC,aAAM,MAAO,MAAM,UAAA,KAAA,KAAA,cAAA,MAAA,IAAA,CAAA;CACnB,OAAA,GAAO;EACT;EACA;EACE,UAAM,CAAA;GACN,QAAO;GACT,QAAA;EAEA,CAAA;CACA,CAAA;AACA;AAIA,MAAA,aAAY;AAEZ,SAAM,cAAK,SAAA,OAAA;CAAE,OAAA,IAAA;EAAM,MAAA;EAAQ;EAC3B,UAAA,CAAA;EACF;CACA,CAAA;AACF;AAEA,SAAM,WAAS,QAAW,OAAI,QAAA;CAC9B,MAAI,QAAO,OAAS,SAClB,OAAO,QAAA,MAAA;CACT,MAAI,OAAM,MAAA,QACR,CAAA;CAEF,OAAM,OAAM,KAAM,SAAU,KAAK,QAAK,MAAA,SAAc,GAAM,IAAK,CAAA,CAAA,CAAA,SAAA,MAAA,CAAA,CAAA,KAAA;AAC/D;AACA,SAAO,UAAG,QAAA,OAAA,QAAA;CAAE,MAAA,QAAA,WAAA,QAAA,OAAA,MAAA,CAAA,CAAA,QAAA,cAAA,EAAA;CAAO,IAAA,CAAA,WAAA,KAAA,KAAA,GAAA,OAAA;CAAc,MAAA,SAAW,OAAA,SAAA,OAAA,CAAA;CAAE,OAAA,OAAQ,cAAA,MAAA,IAAA,SAAA;AAAa;AAAe,SAAC,iBAAA,QAAA;CAAE,MAAC,WAAA,UAAA,QAAA,KAAA,CAAA;CACxF,IAAA,aAAA,MAAA,OAAA;;CCvJA,KAAM,IAAA,QAAA,GAAa,QAAA,OAAA,YAAA,SAAA,GAAA,UAAA,SAAA,OAAA,QAAA,MAAA,KAAA,OAAA;CAcnB,OAAA,WAASC;AACP;AAAa,SAAM,aAAA,SAAA;CAAqB,MAAA,OAAA,OAAA,KAAA,OAAA,CAAA,CAAA,SAAA,MAAA;CAAS,IAAA,SAAW;CAAG,IAAA,OAAA;CAAM,OAAC,SAAA,KAAA,QAAA;EACxE,MAAA,QAAA,KAAA,QAAA,KAAA,MAAA;EAEA,IAAA,UAAS,IAAW,OAAA;EAClB,MAAM,SAAQ,OAAO,SAAS,KAAO,MAAA,QAAc,KAAA,GAAA,EAAA;EACnD,IAAA,CAAM,OAAO,cAAc,MAAC,KAAA,UAAA,KAAA,SAAA,SAAA,KAAA,QAAA,OAAA;EAC5B,MAAO,SAAO,KAAK,MAAA,QAAc,GAAA,SAAc,SAAS,CAAA;EAC1D,MAAA,SAAA,OAAA,QAAA,GAAA;EAEA,IAAA,WAAS,MAAU,OAAoB,MAAe,GAAA,MAA+B,MAAA,QAAA,OAAA,OAAA,MAAA,SAAA,CAAA;EACnF,UAAM;CACN;CAEA,OAAM;AACN;AACF,SAAA,YAAA,OAAA,QAAA;CAEA,MAAA,aAAS,oBAA8C,KAAA;CACrD,IAAA,eAAiB,MAAA,OAAU;CAC3B,MAAI,WAAa,WACf,MAAO,GAAA;CACT,IAAI,WAAS,OACb;MAAK,SAAI,OAAW,aAAQ,SAAO,SAAY,GAAA,OAC7C;CAAA,OACK,IAAA,SAAW,SAAA,GAAA,OAAA;CACpB,OAAA,oBAAA,SAAA,MAAA,CAAA,CAAA,CAAA,KAAA,GAAA,CAAA;AAEA;AACE,SAAM,aAAc,OAAK;CACzB,OAAI,MAAS,OAAA,WAAA,IAAA,MAAA,OAAA,KAAA,OAAA,OAAA,MAAA,QAAA,MAAA,IAAA;AACb;AACA,eAAO,eAAsB,YAAA,QAAA,QAAA;CAC3B,MAAA,SAAc,SAAK,KAAQ,UAAW;CACtC,MAAI,SAAU,aACL;CACT,OAAM,GAAA,UAAS,UAAO,OAAc,QAAM,KAAA,CAAQ;CAClD,OAAK,KAAA,MAAO;CAEZ,MAAA,QAAM,CAAA;CACN,MAAA,eAAe,CAAA;CACf,MAAI,uBAAwB,IAAA,IAAM;CAElC,MAAA,kBAAU,OAAA,kBAAA,OAAA,iBAAA,KAAA,aAAA;CACZ,IAAA,eAAA;CACA,IAAA,cAAO;CACT,IAAA,WAAA;CAEA,IAAA,UAAS,OAAY,MAAe,CAAA;CAClC,IAAA,QAAM;CACN,IAAI,aAAA;CAEJ,IAAA,QAAM;CACN,IAAI;EACE,WAAA,MAAS,SAAO,QAAa;GACrB,MAET,QAAI,OAAS,SAChB,KAAA,IAAO,QAAA,OAAA,KAAA,KAAA;GAET,gBAAO,MAAA;GACT,IAAA,eAAA,iBAAA,OAAA,cAAA,qDAAA;GAEA,UAAS,QAAA,eAA2D,IAAA,QAAA,OAAA,OAAA,CAAA,SAAA,KAAA,CAAA;GAClE,OAAO,QAAM,aAAO,GAAW;IAGjC,IAAA,OAAA;KAOA,IAAA,QAAsB,MAAA,SACpB,SAAA,CACA,GAAA,OACA,cACkD,+CAAA;KAClD,UAAM,OAAS,MAAS,CAAA;KACxB;IACA;IACA,IAAO,UAAK,MAAM;KAClB,IAAM,MAAwB,YAAC,GAAA;MAC/B,MAAM,WAAqC,KAAA,IAAA,MAAA,WAAA,QAAA,UAAA;MAC3C,IAAM,MAAA,SAAA,UAAW,MAAY,SAAA,YAAA,MAAA,OAAA,KAAA,QAAA,SAAA,GAAA,QAAA,CAAA;MAC7B,UAAM,QAAA,SAAyB,QAAA;MAC3B,MAAA,aAAe;MACf,IAAA,MAAA,YAAc,GAAA;KACd;KACA,IAAA,MAAmC,UAAO,GAAM;MAChD,MAAA,WAA6B,KAAA,IAAA,MAAA,SAAA,QAAA,UAAA;MAC7B,UAAA,QAAa,SAAA,QAAA;MACb,MAAA,WAAQ;MAER,IAAA,MAAA,UAAA,GAAA;KACF;KACE,IAAM,MAAA,SAAe,YAAS;MAC9B,MAAA,UAAgB,aAAM,KAAA;MACtB,WAAI,MAAe,iBACjB,QAAOA,aAAY,OAAA,IAAA,QAAA,SAAA,MAAA,CAAA,CAAA,QAAA,UAAqD,EAAA,CAAA,CAAA,KAAA;MAC1E,IAAA,aAAkB,QAAA,SAAmB,WAAQ,GAAA,OAAO,cAAiB,2CAAM;KAE3E,OAAO,IAAA,MAAQ,SAAa,UAAG,MAAA,MAAA;MAC7B,MAAI,KAAO;OACT,MAAI,MAAQ;OAEZ,SAAU,WAAO,KAAO,aAAA,KAAA,CAAA;MACxB,CAAA;MACF,cAAA,MAAA;KAEA;KACE,QAAI;KACF;IACA;IAEA,IAAA,QAAU,aAAQ,YAAiB;IACnC,MAAA,SAAM,QAAa,SAAA,GAAA,UAAA;IACnB,UAAI,QAAM,SACR,UAAA;IACJ,IAAA,OAAA,OAAA,SAAA,SAAA,CAAA,GAAA;KACA,QAAI;KACF;IACA;IACA,IAAA,CAAA,iBAAiB,MAAA,GAAA,OAAA,cAAA,gDAAA;IACjB,MAAI,OAAM,UAAU,QAClB,KAAA,EAAA;IACJ,IAAA,SAAA,MAAA,OAAA,cAAA,2CAAA;IAEA,MAAI,OAAM,WAAS,QAAY,GAAA,GAAA;IAC7B,MAAA,SAAM,WAAU,QAAa,KAAK,GAAA;IAClC,MAAA,aAAiB,OAAA,SAAA,IAAiB,GAAA,OAC9B,GAAA,SAAa;IAEjB,MAAI,OAAA,OAAa,aAAQ,OAAS,QAAW,CAAA;IAE/C,MAAA,WACS,aAAe,OAAU,cAAY;IAC5C,IAAA,SAAW,OAAA,SAAA,KAAA;KAAE,IAAA,OAAM,OAAM,oBAAA,OAAA,cAAA,2DAAA;KAAM,QAAA;MAA8C,MAAC;MAC9E,cAAc,SAAM,MAAA,QAAA;MACtB;MACA,WAAQ;MACR;MACF,QAAA,CAAA;KAEA;KAEA;IACA;IACA,IAAI,SAAO,KAAM;KACf,WAAQ;KACR,QAAA;MACF,MAAA;MACA;MAGA,WAAa;MACb;MAEA,QAAM,CAAA;KACN;KACA;IACA;IACA,IAAA,SAAM,OAAW,SAAA,MAAa,OAAO,cAAc,sDAAA,YAAA,WAAA,EAAA;IAEnD,MAAI,OAAS,YAAO,YAAc,YAAA,MAAA;IAChC,WAAI;IAEJ,IAAA,SAAQ,MAAA,OAAA,cAAA,0CAAA;IACN,IAAA,KAAM,IAAA,IAAA,GAAA,OAAA,cAAA,0CAAA;IACN,KAAA,IAAA,IAAA;IACA,eAAA;IACA,IAAA,cAAW,OAAA,gBAAA,OAAA,cAAA,yCAAA;IACX,IAAA,QAAA,OAAA,sBAAA,aAAA,OAAA,OAAA,gBAAA,OAAA,cAAA,8CAAA;IACA,IAAA,OAAS,OAAA,oBAAA,aAAA,KAAA;KACX;KACA,OAAA;IACF,CAAA;IACA,QAAI;KACF,MAAA,OAAW,OAAA,qBAAA,SAAA;KACX;KAAU;KAAmB,WAAA;KAAM;KAAiB,QAAA,CAAA;IAAS;GAAW;EACxE;CACF,SAAA,OAAA;EACA,MAAI,UAAS,iBAAgB,QAC3B,MAAOA,UAAAA;EAET,OAAA,cAAa,QAAY,WAAY,iBAAkB,IAAA,UAAA,0CAAA,KAAA;CACvD;CACA,IAAA,UAAI,QACF,QAAOA,MAAAA,SAAY,SAAA,CAAA,KAAA,CAAA,OAAA,OAAA,cAA0C,8CAAA;CAC/D,IAAA,MAAI,WAAa,GACf,OAAOA,cAAY,qCAAA;CACrB,MAAA,MAAS,MAAI,UAAA,KAAA,KAAA,cAAA,MAAA,IAAA,CAAA;CACb,aAAA,MAAe,MAAA,UAAA,KAAA,KAAA,cAAA,MAAA,IAAA,CAAA;CACf,OAAI,GAAA;EAEJ;EAEA;CACsB,CAAA;AAAM;AAE5B,MAAA,qBAAQ;AACN,MAAA,sBAAoB;AACpB,MAAA,mBAAA;AACA,MAAA,sBAAA;AACA,MAAA,mBAAW;AACX,MAAA,qBAAA;AACA,SAAA,YAAS,SAAA,UAAA,OAAA;CACX,OAAA,IAAA;EACF,MAAA;EACF;EACF;EAEE;CACA,CAAA;AAGF;AAEA,SAAI,iBAAkB,MAAQ;CAE9B,MAAI,QAAM,KAAA,MACR,kBAAOA;CACT,OAAM,QAAM,KAAM;EAClB,MAAA,MAAa;EACb,SAAU,MAAA,MAAA;CAAE,IAAA;AAAO;AAAa,SAAC,SAAA,OAAA;CACnC,OAAA,OAAA,UAAA,YAAA,UAAA,QAAA,CAAA,MAAA,QAAA,KAAA;;ACvNA,SAAM,gBAAA,OAAqB;CAC3B,IAAA,OAAM,UAAA,UAAsB,OAAA;CAC5B,IAAA,CAAM,SAAA,KAAA,GAAA,OAAmB,KAAA;CACzB,OAAM;EACN,MAAM,OAAA,MAAA,SAAmB,WAAA,MAAA,OAAA,KAAA;EACzB,KAAM,OAAA,MAAA,QAAqB,WAAA,MAAA,MAAA,KAAA;CAI3B;AACE;AAAa,SAAM,aAAA,WAAA,WAAA;CAAqB,IAAA,CAAA,SAAA,SAAA,KAAA,CAAA,SAAA,UAAA,YAAA,KAAA,CAAA,SAAA,UAAA,QAAA,GAAA,OAAA;CAAS,MAAA,SAAA,UAAA,YAAA,CAAA;CAAU,MAAA,kBAAA,OAAA,WAAA,WAAA,SAAA;CAAM,MAAC,QAAA,UAAA,SAAA;CACpE,IAAA,CAAA,SAAA,KAAA,KAAA,OAAA,MAAA,YAAA,YAAA,CAAA,SAAA,MAAA,IAAA,KAAA,OAAA,MAAA,KAAA,YAAA,UAAA,OAAA;CAEA,OAAA;EACE;EACA,YAAO,gBAAa,UAAA,UAAA;EAAE,SAAM;GAAU,SAAS,MAAM;GAAe,SAAI,OAAA,MAAA,YAAA,WAAA,MAAA,UAAA,KAAA;GAC1E,YAAA,gBAAA,MAAA,UAAA;GAEA,MAAS;IACP,SAAO,MAAO,KAAA;IAChB,WAAA,OAAA,MAAA,KAAA,cAAA,WAAA,MAAA,KAAA,YAAA,KAAA;IAEA,QAAS,OAAA,MAAgB,KAAA,WAAoD,WAAA,MAAA,KAAA,SAAA,KAAA;GAC3E;EAEA;CAEA;AACE;AACA,eAAY,WAAM,UAAQ;CAC5B,IAAA,CAAA,SAAA,MAAA;CACF,MAAA,SAAA,KAAA,OAAA,CAAA,CAAA,YAAA,KAAA,CAAA;AAEA;AACE,SAAK,cAAS,UAAe;CAE7B,MAAM,QAAA,SAAS,QAAU,IAAA,gBAAa;CACtC,IAAA,UAAM,QAAA,CAAA,QAAyB,KAAA,KAAA,GAAW,OAAA;CAC1C,MAAM,QAAQ,OAAA,KAAU;CACxB,OAAK,OAAS,cAAU,KAAO,IAAM,QAAA;AAErC;AACE,gBAAA,eAAA,UAAA,UAAA,cAAA,gBAAA,CAAA,GAAA;CACA,MAAA,WAAY,cAAgB,QAAU;CACtC,IAAA,aAAS,QAAA,WAAA,UAAA;EACP,MAAA,WAAe,QAAA;EACf,MAAA,IAAS,MAAA,YAAa;CACtB;CACA,IAAA,CAAA,SAAM,MAAA;CACJ,MAAA,SAAS,SAAW,KAAA,UAAA;CACpB,IAAA,WAAW;CACX,IAAA,aAAQ;CACV,IAAA;EACF,OAAA,MAAA;GACF,MAAA,SAAA,MAAA,OAAA,KAAA;GACF,IAAA,OAAA,MAAA;IAEA,WAAe;IACb;GAGA;GACF,cAAA,OAAA,MAAA;GAEA,IAAA,aAAS,UAAc,MAAmC,IAAA,MAAA,YAAA;GACxD,QAAM,OAAQ,KAAA;GACd,MAAI,OAAU;EAEd;CACA,UAAO;EACT,IAAA,CAAA,UAAA,MAAA,OAAA,OAAA,CAAA,CAAA,YAAA,KAAA,CAAA;EAEA,OAAA,YAAgB;CAMd;AACA;AACE,eAAM,oBAAmB,UAAA,UAAA;CACzB,MAAA,SAAU,CAAA;CACZ,IAAA,aAAA;CACA,IAAI;EAGJ,WAAM,MAAS,SAAS,eAAe,UAAA,UAAA,sCAAA,GAAA;GACvC,OAAI,KAAA,KAAW;GACf,cAAI,MAAa;EACjB;CACE,SAAO,OAAM;EACX,OAAM,YAAS,iBAAkB,QAAA,MAAA,UAAA,gCAAA,CAAA,GAAA,KAAA;CACjC;CACE,OAAA,GAAA,WAAW,KAAA,OAAA,OAAA,QAAA,UAAA,CAAA,CAAA;AACX;AACF,eAAA,mBAAA,aAAA,KAAA,OAAA,CAAA,GAAA,QAAA;CACA,MAAA,UAAc,YAAO,QAAM,mBAAA;CAC3B,MAAI,gBAAa,SACf,YAAU,IAAM,CAAA,QAAA,OAAY,CAAA,IAAA;CAC9B,IAAA,UAAQ;CACR,KAAA,IAAM,YAAO,GAAA,aAAA,kBAAA,aAAA,GAAA;EACf,MAAA,WAAA,MAAA,YAAA,SAAA;GACF,GAAA;GAEE,UAAK;GAIL,QAAO;EACT,CAAA,CAAA,CAAA,OAAA,UAAA,KAAA;EACF,IAAA,oBAAA,OAAA,OAAA,YAAA,QAAA,UAAA,2BAAA,uBAAA,CAAA,GAAA,QAAA;EAEA,IAAA,CAAA;GACE;GACA;GACA;GACE;GACE;EACA,CAAA,CAAA,SAAA,SAAc,MAAM,GAAA,OAAA,GAAA,QAAA;EACtB,IAAA,cAAA,kBAAA;GACF,MAAA,WACc,QAAA;GACZ,OAAO,YAAY,4CAAyC,CAAA,CAAA;EAC9D;EACA,MAAO,WAAG,SAAgB,QAAO,IAAA,UAAe;EAClD,IAAA,CAAA,UAAA;GAEA,MAAA,WAAe,QAAA;GACb,OAAM,YAAU,yCAAuC,CAAA,CAAA;EACvD;EACA,MAAI,aAAU,MAAA,QAAA,QAAA,CAAA,CAAA,WAAA,IAAA,IAAA,UAAA,OAAA,CAAA,CAAA,CAAA,YAAA,IAAA;EACd,IAAK,eAAI,MAAe;GACtB,MAAM,WAAW,QAAM;GAAuB,OAAG,YAAA,qCAAA,CAAA,CAAA;EAAM;EAAoB,IAAA,WAAQ,aAAA,UAAA;GAAe,MAAE,WAAM,QAAuB;GACjI,OAAI,YAAA,oCACiB,CAAA,CAAQ;EAC7B;EAAM,MAAA,WAAA,QAAA;EAAK,UAAA,WAAA;CAAK;CAAK,OAAA,YAAA,4CAAA,CAAA,CAAA;AAAK;AAAG,SAAE,wBAC7B,MAAO;CACT,MAAI,SAAA,KAAc,WAAA,MAAkB,KAAA,CAAA,CAAA,OAAA,OAAA,KAAA,CAAA;CAClC,IAAA,WAAM,OAAW,SAAQ,UAAA;EACzB,MAAA,QAAO,MAAY,MAAA,4CAA8C;EACnE,OAAA,QAAA,MAAA,MAAA,KAAA,CAAA;GACA,WAAM,MAAW;GACjB,QAAK,MAAU;EACb,CAAA,IAAA,CAAA;CACA,CAAA;CACF,IAAA,SAAA,SAAA,GAAA;EACA,MAAM,WAAA;GACN,MAAI;GACF,QAAM;GACN,QAAO;GACT,QAAA;EACA;EACE,MAAA,YAAiB,KAAA,IAAQ,GAAA,SAAA,KAAA,UAAA,SAAA,MAAA,UAAA,CAAA;EACzB,WAAO,SAAY,QAAA,UAAA,SAAA,MAAA,eAAsC,SAAA;CAC3D;CACA,IAAA,OAAM,WAAW,KAAQ,KAAA,UAAA,kBAAA,KAAA,KAAA,MAAA,GAAA,SAAA,KAAA;EACzB,WAAU;EACZ,QAAA,OAAA,KAAA,KAAA,QAAA,KAAA,CAAA,CAAA,SAAA,QAAA;CACA,CAAA;CACF,IAAA,SAAA,WAAA,GAAA,OAAA;CAEA,MAAA,yBAAS,IAAwB,IAAyC;CACxE,KAAA,MAAM,SAAc,UAAA,OAAiB,IAAA,MAAO,WAAc,WAAM,MAAA,SAAA,CAAA;CAChE,OAAI;EACF,OAAM,SAAQ;GACd,KAAA,MAAO,QAAQ,OAAY,OAAM,GAAA,KAAA,OAAA,OAAA;EAAE;EAAqB,QAAA;GAAkB,MAAK,SAAA,IAAA,IAAA,CAAA,GAAA,MAAA,CAAA,CAAA,KAAA,CAAA,WAAA,UAAA,CAAA,WAAA,KAAA,OAAA,QAAA,CAAA,CAAA,CAAA;GAChF,OAAA,SAAA,MAAA,UAAA,OAAA,IAAA,MAAA,SAAA,MAAA,MAAA,MAAA;EACD;CACE;AAAmB;AAAS,SAAA,cAAQ,YAAA;CAAG,IAAA,OAAQ,eAAA,UAAA,OAAA;CAAG,OAAA,OAAQ,YAAA,QAAA,WAAA,WAAA,MAAA;AAAE;AAC5D,SAAM,iBAAiB,YAAO,SAAa;CAC3C,IAAA,CAAA,WAAW,CAAA,iBAAgB,KAAS,OAAA,GAAS,OAAM;CACrD,MAAA,SAAA,cAAA,UAAA;CACA,IAAI,WAAO,MAAA,OAAgB;CACT,MAAA,QAAW,OAAA,MAAA,4HAAA;CAAQ,IAAA,CAAA,QAAQ,MAAO,CAAA,MAAU,IAAA,OAAQ;CAA0B,OAAC,+BAAA,mBAAA,MAAA,EAAA,EAAA,GAAA,mBAAA,MAAA,EAAA,EAAA,UAAA;AACjG;AAGA,SAAM,QAAA,QAAA,QAAS;CACf,OAAK;EAEL;EACE,QAAO;EACL;CAEF;AACA;AACE,SAAM,KAAA,QAAa;CACnB,OAAA;EACF;EACF,QAAA;CACF;AAEA;AACE,SAAI,aAAO,OAAe,UACxB;CACF,OAAO,MAAA,SAAO,sBAAoB,YAAsB,MAAM,SAAA,UAAA,MAAA,KAAA,IAAA,IAAA,KAAA;AAChE;AAEA,SAAS,gBAAA,QAAiB,OAAgD;CACxE,MAAK,YAAY,MAAA,QAAA,OAAsB,SAAO,QACrC,KAAA,QAAA,YAAA,CAAA;CACT,MAAM,iBAAS,OAAc,iBAAU,MAAA;CACvC,MAAI,iBACF,OAAO,iBAAA;CACT,IAAA,kBAAqB,KAAM,kBAAA,GAAA,OAAA;CAC3B,OAAK;EAEL,GAAA;EACF;EAEA;CACE;AAAS;AAAQ,eAAQ,gBAAA,UAAA,QAAA,QAAA,UAAA;CAAW,OAAA,eAAA,eAAA,UAAA,OAAA,gBAAA,sDAAA,YAAA,UAAA,OAAA,OAAA,CAAA,GAAA,QAAA,MAAA;AAAO;AAC7C,eAAA,kBAAA,MAAA,QAAA,aAAA,QAAA;CAEA,MAAA,SAAc,iBAA+B,IAAA;CAC3C,IAAA,WAAO,MAAA,OAAA,YAAA,gCAAA,CAAA,CAAA;CAAE,MAAA,WAAA,CAAA;CAAQ,MAAA,cAAQ,8BAAA,mBAAA,OAAA,IAAA;CAAO,MAAA,mBAAA,MAAA,mBAAA,aAAA,aAAA,EAAA,SAAA,EAAA,QAAA,sCAAA,EAAA,GAAA,MAAA;CAClC,IAAA,iBAAA,SAAA,OAAA,OAAA,aAAA,iBAAA,OAAA,CAAA,QAAA,aAAA,iBAAA,MAAA,OAAA,CAAA,CAAA;CAEA,MAAA,WAAS,iBAAmC;CAC1C,IAAA,CAAA,SAAa,IAAA;EAGf,MAAA,WAAA,QAAA;EAEA,MAAA,UAAS,8BAAyG,SAAA,OAAA;EAChH,OAAM,YAAY,SAAM,CAAA,QAAQ,aAAgB,OAAQ,CAAA,CAAA;CACxD;CACA,MAAM,iBAAiB,MAAA,oBAAwB,UAAA,kBAAA;CAC/C,IAAI,eAAA,SAAuB,OAAA,OAAA,aAClB,eAAA,OAAA,CAAA,QAAA,aAAA,eAAA,MAAA,OAAA,CAAA,CAAA;CACT,IAAA;CAAS,IAAG;EAAQ,YAAA,KAAA,MAAA,OAAA,KAAA,eAAA,KAAA,CAAA,CAAA,SAAA,MAAA,CAAA;CAAgB,SAAA,OAAA;EAAe,MAAA,UAAA;EACrD,OAAA,YAAA,SAAA,CAAA,QAAA,aAAA,OAAA,CAAA,GAAA,KAAA;CAEA;CAME,MAAA,aAAO,aACL,WACE,OACA,OAAO;CAOb,IAAA,eAAA,QAAA,CAAA,oBAAA,KAAA,WAAA,eAAA,KAAA,WAAA,QAAA,YAAA,WAAA,iBAAA;EAEA,MAAA,UAAsB;EACpB,OAAM,YAAS,SAAA,CAAA,QAAqB,aAAA,OAAA,CAAA,CAAA;CACpC;CAGA,MAAM,EAAA,YAA6B,iBAAA,YAAA;CACnC,IAAA,CAAA,QAAM,KAAA,QAAc,WAAA,UAAA,GAA8B;EAClD,MAAM,UAAA;EAGN,OAAI,YAAA,SAAiB,CAAS,QAC5B,aAAO,OAAa,CAAA,CAAA;CACtB;CACA,SAAK,KAAS,KAAI,WAAA,CAAA;CAChB,MAAA,iBAAiB,MAAQ,mBAAA,aAAA,QAAA,KAAA,SAAA,CAAA,GAAA,MAAA;CACzB,IAAA,eAAgB,SAAA,OAAA,OAAA,aAA8B,eAAgB,OAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,eAAA,MAAA,OAAA,CAAA,CAAA;CAC9D,MAAA,kBAAmB,eAAkB;CACvC,IAAA,CAAA,gBAAA,IAAA;EAEA,MAAM,WAAA,eAAuB;EAC7B,MAAI,UAAA,qCACK,gBAA4B,OAAO;EAE5C,OAAI,YAAA,SAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,OAAA,CAAA,CAAA;CACJ;CACE,MAAA,WAAY,wBAAuB,QAAA,IAAe;CACpD,IAAA,aACc,MAAA;EACZ,MAAM,WAAU,eAAA;EAChB,MAAA,UAAO;EACT,OAAA,YAAA,SAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,OAAA,CAAA,CAAA;CAEA;CACA,MAAI,YAAA,MAAe,gBAAS,iBAAyB,QAAW,OAAA,QAAe;CAC7E,IAAA,UAAM,SAAU,OAAA,OAAA,aAAA,UAAA,OAAA,CAAA,GAAA,UAAA,QAAA,QAAA,KAAA,SAAA,UAAA,MAAA,OAAA,CAAA,CAAA;CAChB,IAAA,CAAA,SAAO,MAAY,GAAA;EACrB,MAAA,UAAA;EACA,OAAQ,YAAY,SAAA,CAAA,GAAA,UAAiB,QAAY,QAAA,KAAA,SAAA,OAAA,CAAA,CAAA;CACjD;CACE,SAAM,KAAA,KAAU,QAAA,KAAA,OAAA,CAAA;CAChB,IAAA,QAAO,CAAA,GAAA,UAAY,MAAU,KAAA;CAC/B,IAAA,eAAA,CAAA,GAAA,UAAA,MAAA,YAAA;CACA,MAAA,oBAAmB,iBAAY,QAAA,cAAA,YAAA,QAAA,OAAA;CAE/B,MAAM,YAAA,gBAAuB,QAAA,KAAA;CAC7B,IAAI,sBAAe,QAAS,cACnB,MAAA,SAAa,KAAA,QAAe,mBAAqB,kDAAmD,CAAA;MAC7G,IAAM,sBAAkB,QAAe,cAAA,MAAA;EACvC,MAAK,oBAAoB,MAAA,mBAAA,aAAA,mBAAA,CAAA,GAAA,MAAA;EACvB,IAAA,kBAAiB,SAAA,OAAe,SAAA,KAAA,QAAA,mBAAA,kBAAA,MAAA,OAAA,CAAA;OAChC,IAAM,CAAA,kBAAU,MAAA,IAAA;GAChB,MAAO,UAAA,uCAA2C,kBAAsB,MAAQ,OAAC;GACnF,MAAA,WAAA,kBAAA,KAAA;GAEA,SAAM,KAAA,QAAW,mBAAwB,OAAQ,CAAA;EACjD,OAAI;GACF,MAAM,kBAAW,MAAA,gBAAe,kBAAA,OAAA,WAAA,QAAA;GAChC,IAAA,gBAAgB,SAAA,OAAA,SAAA,KAAA,QAAA,mBAAA,gBAAA,MAAA,OAAA,CAAA;QAChB;IACF,QAAA,CAAA,GAAA,OAAA,GAAA,gBAAA,MAAA,MAAA,KAAA,UAAA;KACA,GAAM;KACF,MAAA,MAAU,KAAA,cACZ,KAAO,IAAA;IACT,EAAK,CAAA;IACH,eAAgB,CAAA,GAAA,cAAA,GAAA,gBAAA,MAAA,aAAA,KAAA,UAAA;KAChB,GAAA;KACF,MAAA,MAAA,KAAA,cAAA,KAAA,IAAA;IACA,EAAA,CAAA;IACA,SAAY,KAAI,KAAA,iBAAqB,CAAA;GACrC;EAEA;CACA;CACA,MAAI,MAAA,MAAA,UAAsB,KAAA,KAAQ,cAAc,MAC9C,IAAA,CAAS;CAEN,aAAI,MAAA,MAAA,UAAsB,KAAQ,KAAA,cAAoB,MAAA,IAAA,CAAA;CACzD,OAAM,GAAA;EACN;EAGK;EACH;EACA,eAAM;GACN,SAAS,OAAK;GAChB,SACK;EACH;CACA,CAAA;AAGK;AAG6C,SAAG,SAAA,OAAA,OAAA;CAAM,OAAA,UAAY,KAAK,IAAA,QAAA,UAAuB,KAAA,IAAA,QAAA,QAAA;AAAE;AAEnG,SAAA,cACK,OAAA;CACkD,QAAG,OAAA,UAAA,YAAA,OAAA,UAAA,eAAA,UAAA,QAAA,OAAA,MAAA,SAAA;AAAM;AAA0C,SAC1G,aAAA,SAAA;CACA,MAAA,WAAc,CAAA;CAChB,MAAA,gCAAA,IAAA,IAAA;CACF,IAAA,QAAA;EACF,aAAA,KAAA;EAEA,mBAAkB,KAAA;EAClB,cAAa,KAAM;CACnB;CACE,IAAA,QAAA;CACA,MAAA,QAAA,UAAA;EACA,cAAA,IAAA,mBAAA,iBAAA,QAAA,MAAA,UAAA,OAAA,KAAA,GAAA;CACA;CAAiB,OAAA;EAAsB,OAAA,UAAS;GAAgB,IAAA,MAAA,SAAA,cAAA;IACjE,SAAA;IACH,QAAA;;KC/UA,mBAAkB,SAA0E,MAAA,mBAAA,MAAA,MAAA,iBAAA;KAC1F,cAAiB,SAAY,MAAA,cAAkB,MAAY,MAAA,YAAgB;IAC7E;GAEA;GACE,IAAA,CAAA,SAAe;GAGjB,IAAA;IAEA,MAAS,WAAA,QAAa,KAA6C;IACjE,IAAM,cAAsB,QAAA,GAAA,QAAA,QAAA,QAAA,CAAA,CAAA,MAAA,IAAA;GAC5B,SAAM,OAAA;IACN,KAAI,KAAuB;GAAE;EAAwB;EAA8B,OAAA,YAAc,SAAA,KAAA,OAAA;EAAU,SAAA,OAAA,UAAA;GAC3G,QAAI;GAEJ,QAAM;EACJ;EACF,eAAA;GACA;GACE;GACE,UAAU,CAAA,GAAA,UAAS,GAAA,aAAc;EAC/B;CACA;AACE;AACA,SAAA,QAAA,OAAmB;CACnB,OAAA;EACF,aAAA,MAAA;EACF,mBAAA,MAAA,kBAAA;EACA,cAAK,MACH;CACF;AACE;AAEA,SAAI,YAAA;CAEN,OAAA,IACO;EACL,MAAA;EACF,SAAA;CACF,CAAA;AACA;AACA,eAAS,oBAAiB,aAAA,QAAA,QAAA;CACxB,MAAA,OAAQ,QAAA,YAAA,OAAA;CACR,MAAA,WAAQ,MAAA,MAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CACV,IAAA,oBAAA,OAAA;EACA,IAAA,SAAA,SAAe,UAAA,OAAA,GAAA,KAAA,CAAA;EAAE,OAAA,IAAA;GAAO,MAAA;GAAO,SAAA;GAA0C,MAAA;EAC3E,CAAA;CACF;CASA,IAAA,CAAA,SAAS,YAA0C,KAAA,SAAA,eAAA,GAAA,OAAA,IAAA;EACjD,MAAO;EACL,SAAA;EACA,MAAA;CACA,CAAA;CACF,MAAA,gBAAA,MAAA,SAAA,IAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CACF,IAAA,yBAAA,SAAA,kBAAA,MAAA,OAAA,IAAA;EAEA,MAAA;EACE,SAAO;EAAM,MAAM;CAAa,CAAA;CAAoC,MAAC,SAAA,KAAA,MAAA,YAAA,IAAA;CACvE,MAAA,aAAA,MAAA,MAAA,MAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CAEA,IAAA,sBAAe,OAAA;EACb,IAAA,WAAa,SAAQ,UAAY,OAAO,GAAA,KAAA,CAAA;EACxC,OAAM,IAAA;GACN,MAAI;GACF,SAAI;GAEJ,MAAO;EAAM,CAAA;CAA0B;CAA6C,IAAA,CAAA,WAAM,YAAA,KAAA,WAAA,eAAA,GAAA,OAAA,IAAA;EAAK,MAAC;EAClG,SAAA;EACA,MAAK;CACU,CAAA;CAA0B,OAAA,qBAAS,QAAA,QAAA,iBAAA,MAAA;AAAyD;AAAW,eAAC,WAAA,OAAA,QAAA,aAAA,QAAA;CACvH,IAAA,QAAM,SAAA,OAAsB,IAAA;EAC5B,MAAI;EACW,SAAM;CAAoB,CAAA;CAA+D,MAAA,UAAM,MAAA,SAAA,gBAAA,GAAA,KAAA,CAAA,IAAA,MAAA,oBAAA,MAAA,aAAA,QAAA,MAAA;CAAK,IAAC,QAAA,SAAA,OAAA,OAAA;CAEpH,IAAA,MAAM,SAAS,gBAAW;EAC1B,MAAM,SAAA,MAAa,qBAAoB,MAAM,YAAuC,QAAA,MAAA,YAAA,MAAA;EACpF,OAAI,OAAA,SAAA,QAAsB,SAAO,GAAA;GAC/B,WAAI;GAEJ,YAAW,MAAA,YAAA;GAAE,QAAM,OAAA;GAAoB,WAAS;GAAoC,SAAM,QAAA;GAAQ,aAAA,MAAA;EACpG,CAAA;CACA;CACe,IAAA,MAAM,SAAA,eAAA;EAAoB,MAAA,SAAS,MAAA,qBAAA,MAAA,UAAA,QAAA,MAAA,UAAA,MAAA;EAAyD,OAAM,OAAA,SAAA,QAAA,SAAA,GAAA;GAAQ,WAAA;GACzH,YAAO;GACT,QAAA,OAAA;GAEA,WAAA,SAAe,MAAW,QAAiB;EACzC,CAAA;CACe;CAAmB,IAAA,MAAS,OAAA,SAAA,cAAA;EAA4B,MAAA,SAAA,MAAA,kBAAA,MAAA,OAAA,MAAA,QAAA,aAAA,MAAA;EAEvE,IAAA,QAAM,SAAgB,OAAA,IAAS;GAG/B,MAAI;GAGJ,SAAU;EACR,CAAA;EACA,OAAO,OAAO,SAAS,QACnB,SACA,GAAG;GAAE,WAAW;GAA0B,YAAY,MAAM,YAAY;GAAM,QAAQ,OAAO;GAAO,WAAW;GAAI,SAAS,QAAQ;GAAO,aAAa,MAAM;EAAY,CAAC;CACjL;CAEA,MAAI,aAAe,cAAA,MAAe,OAAA,SAAA,MAAA,OAAA,UAAA;CAChC,IAAA,eAAe,MAAM,OAAA,IAAA;EACrB,MAAA;EAES,SAAA;CAA2B,CAAA;CAAsB,MAAA,WAAe,MAAA,MAAA,KAAA,YAAA,cAAA,CAAA,CAAA,CAAA,OAAA,UAAA,KAAA;CAAO,IAAA,oBAAoB,SAAM,CAAA,SAAQ,OAAA,KAAA,SAAA,eAAA,GAAA,OAAA,IAAA;EAAE,MAAC;EACvH,SAAA;EAEA,UAAU,CAAA;GACR,QAAM;GACN,QAAI;GACW,QAAM;EAAa,CAAA;CAAoC,CAAA;CACtE,MAAA,SAAc,MAAA,qBAEV,YAAG,QAAA,YAAA,MAAA;CAAE,OAAA,OAAW,SAAA,QAAA,SAAA,GAAA;EAA0B,WAAA;EAAoC,YAAQ,MAAO,YAAA;EAAO,QAAA,OAAW;EAAI,WAAS;EAAe,SAAA,QAAa;EAAkB,aAAC,MAAA;CACjL,CAAA;AAEA;AACA,SAAI,eAAe,OACjB;CAAa,MAAA,UAAM,MAAA,OAAA,MAAA,SAAA,KAAA,SAAA,2BAAA;CAAgB,IAAA,CAAA,SAAS,MAAA,IAAA,MAAA,wCAAA,MAAA,KAAA,EAAA;CAA+D,OAAC,QAAA;AAC9G;AACA,SAAI,cAAA,UAAoB,YAAmB,kBAAY,YAAS,WAC9D;CACE,OAAM,SAAA,WAAA,mBAAA,UAAA,CAAA,CAAA,WAAA,0BAAA,gBAAA,CAAA,CAAA,WAAA,mBAAA,UAAA,CAAA,CAAA,WAAA,kBAAA,SAAA;AACN;AACA,SAAA,aAAW,QAAA,UAAA;CAAE,OAAA,MAAQ,KAAA,OAAA,SAAA,gBAAA,SAAA,SAAA;AAAY;AAAmB,eAAQ,oBAAA,QAAA,UAAA,QAAA;CAA+B,MAAC,aAAA,aAAA,QAAA,QAAA;CAC9F,MAAC,QAAA,MAAA,OAAA,QAAA,IAAA;EAGH,SAAM;EACN,KAAA;GAES,cAAW,MAAA,KAAA,OAAA,SAAA,OAAA;GAA0B,eAAY,MAAM,KAAA,OAAY,SAAA,eAAA;EAAM;EAAsB,aAAW;CAAI,CAAA;CAAwB,IAAA,MAAA,aAAmB,GAAA,MAAA,IAAA,MAAA,MAAA,OAAA,KAAA,KAAA,4CAAA;CAAY,KAAC,MAAA,QAAA,SAAA,OAAA,OAAA,MAAA,OAAA,QAAA,gBAAA;EACjL,MAAA,MAAA,KAAA,YAAA,KAAA,IAAA;EAEA,SAAS,KAAA;EACP,aAAM;CACN,CAAA;CAEA,KAAA,MAAO,QAAQ,SAAA,SAAA,SAAA,CAAA,GAAA,MAAA,OAAA,QAAA,gBAAA;EACjB,MAAA,MAAA,KAAA,OAAA,SAAA,uBAAA,KAAA,IAAA;EAEA,SAAS,KAAA;EACP,aAAO;CAKT,CAAA;CAEA,MAAA,OAAS,QAAa,cAAuB;EAC3C,MAAO,MAAM,KAAK,OAAO,SAAS,4BAAyB;EAC7D,SAAA,GAAA,KAAA,UAAA;GAEA,gBAAe,SAAA,OAAoB;GACjC,cAAM,SAAa,OAAa;GAChC,eAAc,SAAM,OAAO;GACzB,iBAAS,SAAA,YAAA,KAAA;EACT,GAAA,MAAK,CAAA,EAAA;EACH,aAAA;CACA,CAAA;AACF;AACA,SAAA,aAAa,OAAA,QAAA;CACf,OAAC,QAAA,UAAA,UAAA,IAAA,IAAA;EACD,MAAI;EAEJ,SAAK;EAED;CACA,CAAA;AACA;AACF,SAAC,mBAAA,SAAA;CAEH,MAAK,SAAM,kBAAiB;EAExB,GAAA;EACA,GAAA,QAAS;CACT,CAAA;CACF,MAAC,cAAA,QAAA,SAAA,WAAA,MAAA,KAAA,UAAA;CAEH,MAAM,gBAAe,EAAA,GAAA,QAAc,cAAA;CACjC,MAAA,UAAY,QAAK;CACjB,MAAA,UAAY,QAAK;CACf,OAAA,EAAA,MAAA,OAAgB,aAAgB,CAAA,MAAA,SAAA,OAAA,UAAA,EAAA;CAChC,eAAA,SAAc,OAAS,YAAO;EAC9B,MAAA,MAAA,aAAwB,WAAO,OAAA;EAC/B,MAAA,UAAA,MAAiB,UAAS,OAAY,YAAA,GAAA;EACxC,MAAG,SAAS,IAAA,OAAA;EACZ,OAAA,QAAa,SAAA,OAAA;GACd,MAAA;GACH,OAAA,QAAA;GAEA;EACE,IAAA;GAEU,MAAM;GAAe,OAAA,QAAS;GAA8C;EAAO;CAC/F;CAEA,eAAgB,UAAA,OAAmB,YAAkD,KAAA;EACnF,MAAM,SAAS,cAAA,KAAkB;EAAE,IAAG,OAAA,SAAA,OAAA,OAAA;EAAuB,MAAG,WAAQ,MAAA,WAAA,OAAA,OAAA,QAAA,aAAA,WAAA,MAAA;EAAc,IAAA,SAAA,SAAA,OAAA,OAAA;EACtF,KAAM,MAAA,WAA2B,oBAAiB,SAAW,MAAM,OAAK,cAAU,MAAA,GAAA,IAAA,KAAA,OAAA;EAClF,MAAM,QAAA,MAAA,0BAA6B,SAAc,MAAA,SAAA;EACjD,MAAM,iBAAkB,MAAA,QAAA,cAAA,EAAA,aAAA,WAAA,OAAA,CAAA,CAAA,CAAA,KAAA,KAAA,UAAA,IAAA,KAAA,CAAA;EACxB,IAAA,eAAgB,SAAQ,OAAA,OAAA,aAAA,eAAA,OAAA,WAAA,MAAA;EAExB,MAAO,SAGuB,MAAY,SAAA,SAA+B,OACrE,OAAS,eAAiB,OAC9B,KAAA,WAAA,MAAA;EAEA,MAAA,YAAe,MAAS,QAAiB,QAAA,eAAsD,MAAA,QAAA,CAAA,CAAA,CAAA,WAAA,KAAA,IAAA,UAAA,KAAA;EAC7F,IAAA,cAAY,KAAA,GAAa,IAAA,KAAA,mCAAkB,qBAAA,QAAA,UAAA,UAAA,OAAA,SAAA,GAAA;EAC3C,OAAM;CACN;CACA,eAAO,SAAQ,UACX,OAAA,gBAAA,KAAA,QAAA;EAAE,IAAA;EAAY,MAAA,gBAAe,cAAA;EAAO,MAAA,QAAA,IAAA,aAAA;GAAO;GACzC,QAAM,CAAA,KAAA;GAAO,gBAAe;GAAO,eAAA;IAAO,GAAA;IAClD,WAAA,OAAA,mBAAA;KAEA,SAAA;MACE,SAAM,eAAS;MACX,SAAO,eACT;KAEF;KACA,MAAI,oBACF,QAAO,UAAA,MAAA;KACT,MAAK,gBAAiB,cAAA;IAGtB;GAIA;EACA,CAAA;EAEA,MAAM,gBAAe,MAAA,MAAS,cAAgB;GAC9C;GACA,aAAI;EAEJ,CAAA,CAAA,CAAA,KAAO,KAAA,UAAA,IAAA,KAAA,CAAA;EACT,IAAA,cAAA,SAAA,OAAA,OAAA,aAAA,cAAA,OAAA,MAAA;EAEA,MAAA,UAAe,cACb;EAMA,IAAI;GACJ,IAAA,CAAM,QAAA,OAAA,IAAgB;IACtB,MAAM;IACJ,SAAA;GACA,CAAA;GACA,MAAA,aAAgB,aAAA,QAAA,QAAA;GAChB,MAAA,mBAAe,MAAA,KAAA,OAAA,SAAA,qBAAA;GACb,MAAG,aAAA,MAAA,KAAA,OAAA,SAAA,iBAAA,SAAA,UAAA;GACH,MAAA,SAAW,cAAO,eAAmB,KAAA,GAAA,YAAA,kBAAA,YAAA,SAAA,UAAA;GACnC,IAAA,OAAS;GAAE,MAAA,YAAS,MAAA,MAAe,SAAA;IAAS;IAAuC;IACnF,aAAM;IACN,cAAM,UAAgB;KACxB,OAAA,MAAA;KACF,IAAA,KAAA;MACD,MAAA;MAED;KAAkD,CAAA;IAAgB;IAAsB,uBAAmB,EAAI,eAAM;KACrH,IAAI,KAAA;MAEJ,MAAM;MAEF;MACF,UACE,SAAO;MAAM,YAAM,SAAA;MAAe,OAAS,SAAA;KAAgD,CAAA;IAC7F;IACA,YAAM,WAAA;KACN,IAAM,KAAA;MACN,MAAM;MACN,MAAI,OAAO;MACX,cAAM,OAAkB;MACtB,OAAA,QAAA,OAAA,KAAA;KACA,CAAA;IACA;GACA,CAAA,CAAA,CAAA,KAAA,KAAA,UAAc,IAAU,KAAA,CAAA;GACtB,IAAA,UAAO,SAAM,OAAA,OAAA,aAAA,UAAA,OAAA,MAAA;GACb,IAAA,OAAS,QAAA,UAAA,MAAA,UAAA,GAAA,UAAA,MAAA,MAAA,MAAA;GAAE,IAAA,QAAM,SAAA,OAAA,UAAA;GAAa,MAAA,YAAA,MAAA,qBAAA,OAAA,SAAA,YAAA,QAAA,MAAA;GAAK,IAAC,UAAA,SAAA,OAAA,OAAA;GACtC,IAAA,SAAA,cAAA,gBAAA,OAAA,oBAAA,UAAA,KAAA;GACA,MAAA,YAAA,uBAAwC,SAAA,YAAA,UAAA,OAAA,SAAA,cAAA,2BAAA;IACtC,MAAI;IAAO,cAAM,SAAA,OAAA,MAAA,KAAA,SAAA,KAAA,IAAA;GAAY,IAAA,EAAA,MAAA,eAAA,CAAA;GAAM,IAAA,UAAU,SAAS,OAAA,OAAA;GAAU,IAAA,CAAA,SAAA,aAAqB,OAAA,IAAA;IAAY,MAAA;IAAsB,SAAC;GAC1H,CAAA;GACA,MAAA,WAAY,MAAA,aAAW,SAAA,YAAA,SAAA,SAAA,YAAA,MAAA,UAAA,OAAA,SAAA,OAAA,QAAA;GACrB,IAAA,SAAS,SAAA,OAAA,OAAA;GAAE,KAAA,MAAM,WAAA,SAAA,MAAA,UAAA,IAAA,KAAA,OAAA;GAAc,OAAA,GAAM,SAAO,MAAA,KAAA;EAAY,UAAA;GAAmC,MAAA,QAAO,QAAQ;EAAc;CAC1H;AACF;AAGA,SAAI"}
|
package/dist/sandbox-local.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { HarnessV1SandboxProvider } from "@ai-sdk/harness";
|
|
2
2
|
/**
|
|
3
3
|
* The local sandbox runs real processes on this computer.
|
|
4
|
-
* It
|
|
4
|
+
* It gives each session its own home directory and a minimal environment.
|
|
5
|
+
* It is not a security boundary: every process can still read the whole computer.
|
|
5
6
|
* Use a hosted sandbox provider when the Harness must contain what it runs.
|
|
6
7
|
*/
|
|
7
8
|
export interface CreateLocalSandboxOptions {
|
|
@@ -11,6 +12,12 @@ export interface CreateLocalSandboxOptions {
|
|
|
11
12
|
readonly port?: number;
|
|
12
13
|
/** Keep the session root after `destroy`. The default removes it. */
|
|
13
14
|
readonly keepRoot?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* More environment variables for every process in the session, such as a
|
|
17
|
+
* registry URL or proxy settings. Harness adapters pass their own credentials,
|
|
18
|
+
* so the session does not need the caller's API keys.
|
|
19
|
+
*/
|
|
20
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
14
21
|
}
|
|
15
22
|
/**
|
|
16
23
|
* Create a sandbox provider that runs Harness sessions on this computer.
|
|
@@ -18,8 +25,9 @@ export interface CreateLocalSandboxOptions {
|
|
|
18
25
|
* The session needs POSIX `sh` at `/bin/sh` and GNU `find`, because the Harness
|
|
19
26
|
* inventories output with `find -printf`. It runs on Linux, and not on macOS or
|
|
20
27
|
* Windows. It exposes one port on `127.0.0.1` for bridge-backed Harness
|
|
21
|
-
* adapters.
|
|
22
|
-
*
|
|
28
|
+
* adapters. Each session gets its own home directory under the session root and
|
|
29
|
+
* a minimal environment, and `destroy` removes both. It applies no process
|
|
30
|
+
* isolation: every process can still read and write the whole computer.
|
|
23
31
|
*/
|
|
24
32
|
export declare function createLocalSandbox(options?: CreateLocalSandboxOptions): HarnessV1SandboxProvider;
|
|
25
33
|
//# sourceMappingURL=sandbox-local.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-local.d.mts","names":[],"sources":["../src/sandbox-local.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"sandbox-local.d.mts","names":[],"sources":["../src/sandbox-local.ts"],"mappings":";;;;;;;iBAeiB;;WAEN;;WAEA;;WAEA;;;;;;WAMA,MAAM,SAAS;;;;;;;;;;;;wBAqSV,mBAAmB,UAAS,4BAAiC"}
|