skilld-harness 3.6.5 → 3.6.8
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 +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -2
- package/dist/index.mjs.map +1 -1
- package/dist/skills/generate-package-skill/SKILL.md +6 -2
- package/dist/skills/generate-package-skill/assets/harness-request.md +1 -2
- package/dist/skills/harness-skills.json +1 -0
- package/dist/skills/skilld/SKILL.md +23 -0
- package/dist/skills/skilld-maintained-skills.json +3 -1
- package/dist/skills/skilld-tui-design/SKILL.md +100 -0
- package/dist/skills/skilld-tui-design/references/source-review.md +54 -0
- package/dist/skills/update-package-skill/SKILL.md +63 -0
- package/dist/skills/update-package-skill/assets/harness-request.md +13 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,6 +41,7 @@ const result = await skillHarness.run({
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Every run returns a tagged `Ok` or `Err` value.
|
|
44
|
+
A `PackageSkill` run whose destination already holds the Skill runs `update-package-skill`, which tests only what the release changed. Without one it runs `generate-package-skill`.
|
|
44
45
|
The input tag sets the `Ok` value: `PackageSkill` and `ProjectSkill` return a `GeneratedSkill`, and `ReviewSkill` returns a `SkillReview`.
|
|
45
46
|
Both `Ok` and `Err` carry a `report`, so a failed run still reports its cost.
|
|
46
47
|
`report.usage` holds input, cached input, and output tokens.
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/harness.ts"],"mappings":";;UAGiB;WACN;WACA;;KAGC;WAEC;WACA;;WAGA;WACA;WACA;;KAGD;WAEC;WACA,QAAQ;WACR,aAAa;;WAGb;WACA;WACA,aAAa;;WAGb;WACA;;UAGI;WACN;WACA;WACA;WACA;WACA;WACA;;;UAIM;;WAEN;;WAEA;WACA;;;KAIC;WACK;WAA4B;;WAE9B;WACA;WACA;WACA;WACA;;WAGA;WACA;WACA;WACA,OAAO;;UAGL;WACN,SAAS;;;;;WAKT,WAAW,OAAO;;UAGZ;WACN;WACA;;UAGM;WACN;WACA;WACA;;UAGM;WACN;WACA;WACA;WACA,OAAO,cAAc;WACrB,gBAAgB,cAAc;;UAGxB;WACN;WACA;WACA;WACA;;UAGM;WACN;WACA;WACA,UAAU,cAAc;;KAGvB;WACK;WAA+B;;WAEjC;WACA;WACA,UAAU,cAAc;WACxB;;WAEE;WAA8B;WAA0B;;WACxD;WAA+B;WAA0B,QAAQ;;WACjE;WAAmC;WAA0B;;WAC7D;WAA6B;WAA0B;;WACvD;WAAkC;WAA0B;WAAuB;;WACnF;WAA4B;;;UAG5B;WACN,cAAc;WACd,cAAc;WACd,aAAa;;;;;;UAOP;;WAEN,OAAO;;WAEP;;;;;WAKA,UAAU;;KAGT,eAAe,YAAY,mBAAmB;WACzC;WAAqB,OAAO,eAAe;WAAe,QAAQ;;WAClE;WAAsB,OAAO;WAAwB,QAAQ;;UAE7D;WACN,MAAM,YAAY,UAAU,OAAO,KAAK,UAAU,oBAAoB,QAAQ,eAAe;;UAGvF;WACN,SAAS;;WAET,SAAS;;WAET,gBAAgB;WAChB,eAAe,QAAQ;;WAEvB,SAAS,gBAAgB,MAAM,SAAS,OAAO,gBAAgB,QAAQ;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/harness.ts"],"mappings":";;UAGiB;WACN;WACA;;KAGC;WAEC;WACA;;WAGA;WACA;WACA;;KAGD;WAEC;WACA,QAAQ;WACR,aAAa;;WAGb;WACA;WACA,aAAa;;WAGb;WACA;;UAGI;WACN;WACA;WACA;WACA;WACA;WACA;;;UAIM;;WAEN;;WAEA;WACA;;;KAIC;WACK;WAA4B;;WAE9B;WACA;WACA;WACA;WACA;;WAGA;WACA;WACA;WACA,OAAO;;UAGL;WACN,SAAS;;;;;WAKT,WAAW,OAAO;;UAGZ;WACN;WACA;;UAGM;WACN;WACA;WACA;;UAGM;WACN;WACA;WACA;WACA,OAAO,cAAc;WACrB,gBAAgB,cAAc;;UAGxB;WACN;WACA;WACA;WACA;;UAGM;WACN;WACA;WACA,UAAU,cAAc;;KAGvB;WACK;WAA+B;;WAEjC;WACA;WACA,UAAU,cAAc;WACxB;;WAEE;WAA8B;WAA0B;;WACxD;WAA+B;WAA0B,QAAQ;;WACjE;WAAmC;WAA0B;;WAC7D;WAA6B;WAA0B;;WACvD;WAAkC;WAA0B;WAAuB;;WACnF;WAA4B;;;UAG5B;WACN,cAAc;WACd,cAAc;WACd,aAAa;;;;;;UAOP;;WAEN,OAAO;;WAEP;;;;;WAKA,UAAU;;KAGT,eAAe,YAAY,mBAAmB;WACzC;WAAqB,OAAO,eAAe;WAAe,QAAQ;;WAClE;WAAsB,OAAO;WAAwB,QAAQ;;UAE7D;WACN,MAAM,YAAY,UAAU,OAAO,KAAK,UAAU,oBAAoB,QAAQ,eAAe;;UAGvF;WACN,SAAS;;WAET,SAAS;;WAET,gBAAgB;WAChB,eAAe,QAAQ;;WAEvB,SAAS,gBAAgB,MAAM,SAAS,OAAO,gBAAgB,QAAQ;;wBCkIlE,mBAAmB,SAAS,4BAA4B"}
|
package/dist/index.mjs
CHANGED
|
@@ -1240,7 +1240,7 @@ async function prepareRun(input, policy, fetchClient, signal) {
|
|
|
1240
1240
|
message: "Skill run was cancelled."
|
|
1241
1241
|
});
|
|
1242
1242
|
return source._tag === "Err" ? source : ok({
|
|
1243
|
-
skillName:
|
|
1243
|
+
skillName: packageSkillName(current.value),
|
|
1244
1244
|
outputName: input.destination.name,
|
|
1245
1245
|
source: source.value,
|
|
1246
1246
|
sourceDir: "",
|
|
@@ -1265,7 +1265,7 @@ async function prepareRun(input, policy, fetchClient, signal) {
|
|
|
1265
1265
|
});
|
|
1266
1266
|
const source = await collectHostDirectory(packageDir, policy, packageDir, signal);
|
|
1267
1267
|
return source._tag === "Err" ? source : ok({
|
|
1268
|
-
skillName:
|
|
1268
|
+
skillName: packageSkillName(current.value),
|
|
1269
1269
|
outputName: input.destination.name,
|
|
1270
1270
|
source: source.value,
|
|
1271
1271
|
sourceDir: "",
|
|
@@ -1273,6 +1273,9 @@ async function prepareRun(input, policy, fetchClient, signal) {
|
|
|
1273
1273
|
destination: input.destination
|
|
1274
1274
|
});
|
|
1275
1275
|
}
|
|
1276
|
+
function packageSkillName(current) {
|
|
1277
|
+
return current === void 0 ? "generate-package-skill" : "update-package-skill";
|
|
1278
|
+
}
|
|
1276
1279
|
function requestContent(skill) {
|
|
1277
1280
|
const request = skill.files?.find((file) => file.path === "assets/harness-request.md");
|
|
1278
1281
|
if (!request) throw new Error(`Harness request asset is missing for ${skill.name}.`);
|
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\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 { isScalar, parseDocument, Scalar } 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 * Skill loaders and viewers parse frontmatter with different YAML parsers.\n * A plain one-line description without these characters reads the same in all of them.\n */\nconst riskyDescription = /[\"`%]/\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 const description = document.get('description', true)\n if (typeof frontmatter.description === 'string' && (!isScalar(description) || description.type !== Scalar.PLAIN || riskyDescription.test(frontmatter.description)))\n issues.push('Frontmatter description must be one plain line without double quotes, backticks, or %. Name symptoms in plain words.')\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 { CollectedFile, 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\n/** An unknown count in any turn keeps the total unknown. */\nfunction sumUsage(a: SkillRunUsage, b: SkillRunUsage): SkillRunUsage {\n const sum = (x: number | undefined, y: number | undefined) => x === undefined || y === undefined ? undefined : x + y\n return { inputTokens: sum(a.inputTokens, b.inputTokens), cachedInputTokens: sum(a.cachedInputTokens, b.cachedInputTokens), outputTokens: sum(a.outputTokens, b.outputTokens) }\n}\n\n/** Turns the Agent gets to fix output that failed the deterministic checks, in the same session. */\nconst OUTPUT_REPAIR_TURNS = 2\n\nfunction repairRequest(outputPath: string, issues: ReadonlyArray<string>): string {\n return [\n `The Harness checked the output at \\`${outputPath}\\` and found these problems:`,\n '',\n ...issues.map(issue => `- ${issue}`),\n '',\n `Fix each problem in place. Write no files outside \\`${outputPath}\\`. Finish when the output passes these checks.`,\n ].join('\\n')\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 agentError(cause: unknown, signal?: AbortSignal): SkillRunError {\n return signal?.aborted\n ? { _tag: 'Cancelled', message: 'Skill run was cancelled.' }\n : { _tag: 'AgentFailed', message: 'Harness Agent failed during the Skill run.', cause }\n}\n\nfunction toAgentError(cause: unknown, signal?: AbortSignal): RunOutcome {\n return err(agentError(cause, signal))\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 const outputSandbox = active.sandbox\n // Steps count across turns, so a repair turn continues the numbering.\n let step = 0\n let stepOffset = 0\n let usage: SkillRunUsage | undefined\n const turn = async (text: string): Promise<Result<void, SkillRunError>> => {\n const generated = await agent.generate({\n session,\n prompt: text,\n abortSignal: signal,\n onStepStart: (event) => {\n step = stepOffset + 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: stepOffset + result.stepNumber, finishReason: result.finishReason, usage: toUsage(result.usage) })\n },\n }).then(ok, cause => err(cause))\n if (generated._tag === 'Err')\n return err(agentError(generated.error, signal))\n const turnUsage = toUsage(generated.value.totalUsage)\n usage = usage ? sumUsage(usage, turnUsage) : turnUsage\n stepOffset += generated.value.steps.length\n log.settle(usage, stepOffset)\n return signal?.aborted ? err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' }) : ok(undefined)\n }\n const check = async (): Promise<Result<ReadonlyArray<CollectedFile>, SkillRunError>> => {\n const collected = await collectSandboxOutput(outputSandbox, outputPath, policy, signal)\n if (collected._tag === 'Err')\n return collected\n const validated = prepared.skillName === 'review-skill'\n ? validateSkillReview(collected.value)\n : 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 return validated._tag === 'Err' ? validated : ok(collected.value)\n }\n\n const first = await turn(prompt)\n if (first._tag === 'Err')\n return first\n let checked = await check()\n // A failed check goes back to the Agent, which still holds its context, instead of failing the run.\n for (let repair = 1; repair <= OUTPUT_REPAIR_TURNS && checked._tag === 'Err' && checked.error._tag === 'InvalidSkill'; repair++) {\n log.warn(`Output checks failed; repair turn ${repair} of ${OUTPUT_REPAIR_TURNS}: ${checked.error.issues.join(' ')}`)\n const repaired = await turn(repairRequest(outputPath, checked.error.issues))\n if (repaired._tag === 'Err')\n return repaired\n checked = await check()\n }\n if (checked._tag === 'Err')\n return checked\n const collected = checked\n\n if (prepared.skillName === 'review-skill')\n return validateSkillReview(collected.value)\n\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":"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"}
|
|
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 { isScalar, parseDocument, Scalar } 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 * Skill loaders and viewers parse frontmatter with different YAML parsers.\n * A plain one-line description without these characters reads the same in all of them.\n */\nconst riskyDescription = /[\"`%]/\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 const description = document.get('description', true)\n if (typeof frontmatter.description === 'string' && (!isScalar(description) || description.type !== Scalar.PLAIN || riskyDescription.test(frontmatter.description)))\n issues.push('Frontmatter description must be one plain line without double quotes, backticks, or %. Name symptoms in plain words.')\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 { CollectedFile, 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' | 'update-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\n/** An unknown count in any turn keeps the total unknown. */\nfunction sumUsage(a: SkillRunUsage, b: SkillRunUsage): SkillRunUsage {\n const sum = (x: number | undefined, y: number | undefined) => x === undefined || y === undefined ? undefined : x + y\n return { inputTokens: sum(a.inputTokens, b.inputTokens), cachedInputTokens: sum(a.cachedInputTokens, b.cachedInputTokens), outputTokens: sum(a.outputTokens, b.outputTokens) }\n}\n\n/** Turns the Agent gets to fix output that failed the deterministic checks, in the same session. */\nconst OUTPUT_REPAIR_TURNS = 2\n\nfunction repairRequest(outputPath: string, issues: ReadonlyArray<string>): string {\n return [\n `The Harness checked the output at \\`${outputPath}\\` and found these problems:`,\n '',\n ...issues.map(issue => `- ${issue}`),\n '',\n `Fix each problem in place. Write no files outside \\`${outputPath}\\`. Finish when the output passes these checks.`,\n ].join('\\n')\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: packageSkillName(current.value), 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: packageSkillName(current.value), outputName: input.destination.name, source: source.value, sourceDir: '', current: current.value, destination: input.destination })\n}\n\n/** A destination that already holds the Skill gets an update run, which tests only what the release changed. */\nfunction packageSkillName(current: PreparedSource | undefined): 'generate-package-skill' | 'update-package-skill' {\n return current === undefined ? 'generate-package-skill' : 'update-package-skill'\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 agentError(cause: unknown, signal?: AbortSignal): SkillRunError {\n return signal?.aborted\n ? { _tag: 'Cancelled', message: 'Skill run was cancelled.' }\n : { _tag: 'AgentFailed', message: 'Harness Agent failed during the Skill run.', cause }\n}\n\nfunction toAgentError(cause: unknown, signal?: AbortSignal): RunOutcome {\n return err(agentError(cause, signal))\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 const outputSandbox = active.sandbox\n // Steps count across turns, so a repair turn continues the numbering.\n let step = 0\n let stepOffset = 0\n let usage: SkillRunUsage | undefined\n const turn = async (text: string): Promise<Result<void, SkillRunError>> => {\n const generated = await agent.generate({\n session,\n prompt: text,\n abortSignal: signal,\n onStepStart: (event) => {\n step = stepOffset + 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: stepOffset + result.stepNumber, finishReason: result.finishReason, usage: toUsage(result.usage) })\n },\n }).then(ok, cause => err(cause))\n if (generated._tag === 'Err')\n return err(agentError(generated.error, signal))\n const turnUsage = toUsage(generated.value.totalUsage)\n usage = usage ? sumUsage(usage, turnUsage) : turnUsage\n stepOffset += generated.value.steps.length\n log.settle(usage, stepOffset)\n return signal?.aborted ? err({ _tag: 'Cancelled', message: 'Skill run was cancelled.' }) : ok(undefined)\n }\n const check = async (): Promise<Result<ReadonlyArray<CollectedFile>, SkillRunError>> => {\n const collected = await collectSandboxOutput(outputSandbox, outputPath, policy, signal)\n if (collected._tag === 'Err')\n return collected\n const validated = prepared.skillName === 'review-skill'\n ? validateSkillReview(collected.value)\n : 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 return validated._tag === 'Err' ? validated : ok(collected.value)\n }\n\n const first = await turn(prompt)\n if (first._tag === 'Err')\n return first\n let checked = await check()\n // A failed check goes back to the Agent, which still holds its context, instead of failing the run.\n for (let repair = 1; repair <= OUTPUT_REPAIR_TURNS && checked._tag === 'Err' && checked.error._tag === 'InvalidSkill'; repair++) {\n log.warn(`Output checks failed; repair turn ${repair} of ${OUTPUT_REPAIR_TURNS}: ${checked.error.issues.join(' ')}`)\n const repaired = await turn(repairRequest(outputPath, checked.error.issues))\n if (repaired._tag === 'Err')\n return repaired\n checked = await check()\n }\n if (checked._tag === 'Err')\n return checked\n const collected = checked\n\n if (prepared.skillName === 'review-skill')\n return validateSkillReview(collected.value)\n\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":"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"}
|
|
@@ -27,7 +27,7 @@ Skip an internal package, whose users are the repository's own packages, such as
|
|
|
27
27
|
5. Read the current official docs and examples, and release notes only for breaking changes and removed APIs.
|
|
28
28
|
When docs cover several frameworks, read the consumer's framework pages first, then the core pages they link.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
To update an existing Skill after a release, use `update-package-skill`. It tests only what the release changed.
|
|
31
31
|
|
|
32
32
|
## 2. Test the examples
|
|
33
33
|
|
|
@@ -57,7 +57,7 @@ Observed behaviour beats documentation.
|
|
|
57
57
|
For a binary, use `--fetch-raw PATH --out DIR`. `DIR/responses.json` lists each status, content type, and response headers.
|
|
58
58
|
For an HTTP client package, start a fake target on port 0 inside the test, and assert on the requests it receives.
|
|
59
59
|
Without `--fetch`, it holds the server until SIGTERM. Background it with your tool's option; `&` and `nohup` die with the shell call.
|
|
60
|
-
Never kill by port or with `pkill -f`: another Agent can own that process.
|
|
60
|
+
Start servers from your own test script and record each process ID you start; stop only those. Never kill by port or with `pkill -f`: another Agent can own that process.
|
|
61
61
|
In a browser, set a desktop user agent; a package can treat `HeadlessChrome` as a bot.
|
|
62
62
|
4. If documentation and behaviour disagree, write the behaviour and report the mismatch.
|
|
63
63
|
5. Keep an unrunnable example only when the types prove it; report it untested.
|
|
@@ -144,6 +144,10 @@ Report to the user:
|
|
|
144
144
|
Give each item expected, observed, a minimal repro with its output, and a source link at the release tag. File it only if asked.
|
|
145
145
|
- The source path or documentation URL behind each version-specific rule.
|
|
146
146
|
- If the Skill sits inside the published package directory, add its directory to `files` in `package.json`. After one build, list packed files with `npm pack --dry-run --ignore-scripts`; `pnpm pack` rejects that flag.
|
|
147
|
+
- For npm packages, use `skills/<name>/SKILL.md` beside the package's `package.json`. Include linked files in the tarball.
|
|
148
|
+
[pnpm 12.11 and newer](https://pnpm.io/agent-skills) link Skills from approved direct dependencies.
|
|
149
|
+
Document `pnpm approve` for developers who want these links. Approval covers every Skill and later version of the package.
|
|
150
|
+
Never approve a package for the user without their request. pnpm owns its links, dependency updates, and removal.
|
|
147
151
|
- Edit the README beside the Skill's `package.json`. If it already links the skilld.dev page, keep that link. Else add the badge below after the others.
|
|
148
152
|
Replace a `skilld add` tip that names this package in place with the tip below. Else add the tip after the install command.
|
|
149
153
|
Replace `OWNER`, `REPOSITORY`, and `PACKAGE`. Count every `SKILL.md` in the Repository, hidden Agent folders included; the skilld.dev indexer skips test and fixture folders.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Harness request
|
|
2
2
|
|
|
3
3
|
Use the prepared package source at `{{SOURCE_PATH}}`.
|
|
4
|
-
If it exists, use the current Skill at `{{CURRENT_SKILL_PATH}}` as the update baseline.
|
|
5
4
|
Generate the package Skill at `{{OUTPUT_PATH}}`.
|
|
6
5
|
The Skill directory name must be `{{SKILL_NAME}}`.
|
|
7
6
|
|
|
@@ -13,4 +12,4 @@ List each documentation and behaviour mismatch in your final message.
|
|
|
13
12
|
Write no files outside `{{OUTPUT_PATH}}`. Build fixtures in a scratch directory outside it.
|
|
14
13
|
Write only `SKILL.md` and Markdown files under `references/`: at most 9 files and 64 KiB in total. Skillgen rejects other output.
|
|
15
14
|
Finish only after checking every output rule in this Skill.
|
|
16
|
-
After you finish, the Harness checks the output
|
|
15
|
+
Do not install or run `skilld`. After you finish, the Harness checks the output and returns each failed check to you; fix them in place.
|
|
@@ -16,6 +16,7 @@ Use `--json` with `search`, `run`, and `update --check`.
|
|
|
16
16
|
Use `--json` with `view` of a registry ref, and with every registry and account command below.
|
|
17
17
|
Their `data` is the skilld.dev answer. A command whose answer has no body returns `data: null`.
|
|
18
18
|
Use `--json` with `sync` and `sync --check` for declared Skills.
|
|
19
|
+
Use `doctor --json` for read-only Skill discovery and cleanup findings.
|
|
19
20
|
The remaining commands do not support JSON output.
|
|
20
21
|
Use `--plain` when another command needs stable text.
|
|
21
22
|
|
|
@@ -421,6 +422,28 @@ Use `outdated` for stale, unverified, local, and unmanaged Skill reports.
|
|
|
421
422
|
Read every proposed command before using it.
|
|
422
423
|
Never delete an unmanaged Skill unless the user names it for removal.
|
|
423
424
|
|
|
425
|
+
## Review Skill files across projects
|
|
426
|
+
|
|
427
|
+
Run `skilld doctor --json` to scan the user's home directory.
|
|
428
|
+
Pass explicit roots to narrow the scan or inspect files outside home.
|
|
429
|
+
The default scan excludes dependencies, caches, generated files, backups, and Git worktrees.
|
|
430
|
+
Use `--exclude GLOB` to prune more paths.
|
|
431
|
+
Use `--include-excluded` or `--include-worktrees` only when those files matter to the task.
|
|
432
|
+
|
|
433
|
+
Read owner labels, duplicate paths, source matches, and scan problems separately.
|
|
434
|
+
The `pnpm` owner names Skills linked from npm dependencies. Update these through pnpm, not skilld.
|
|
435
|
+
Doctor never migrates or removes pnpm-owned links. `outdated --all` excludes them from replacement suggestions.
|
|
436
|
+
Exit code `1` with success data means some files could not be checked.
|
|
437
|
+
Use `--check-sources` for up to 20 source candidates through skilld.dev.
|
|
438
|
+
A name match alone never establishes provenance.
|
|
439
|
+
|
|
440
|
+
The interactive `skilld doctor` separates skills.sh installs with Tab.
|
|
441
|
+
The user can review migration with `m` or removal with `d`.
|
|
442
|
+
Each action shows affected paths and requires confirmation.
|
|
443
|
+
Backups include original files, lock metadata, and recovery instructions.
|
|
444
|
+
Use the existing update workflow for skilld installs.
|
|
445
|
+
Historical commit searches and project-to-global deduplication are outside Doctor's current actions.
|
|
446
|
+
|
|
424
447
|
## Manage account authentication
|
|
425
448
|
|
|
426
449
|
Check account authentication before starting login:
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skilld-tui-design
|
|
3
|
+
description: Designs and verifies skilld CLI output, terminal pickers, and full-screen flows. Use for terminal colours, loading feedback, keyboard controls, layout, errors, or end-to-end CLI UX reviews.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Design skilld CLI interactions
|
|
8
|
+
|
|
9
|
+
Build the user's whole command journey, including failure, cancellation, and the return to their shell.
|
|
10
|
+
Read [source decisions](references/source-review.md) for the two reviewed Skills and their exact revisions.
|
|
11
|
+
|
|
12
|
+
## Establish the contract
|
|
13
|
+
|
|
14
|
+
Read the project's `GLOSSARY.md`, `COPY.md`, and `VISION.md` when present.
|
|
15
|
+
Keep canonical nouns and strings. Use short sentences with one idea each.
|
|
16
|
+
Inspect the command parser, output renderer, and terminal lifecycle before changing behavior.
|
|
17
|
+
Classify each affected surface as static output, a picker, a prompt, or a full-screen view.
|
|
18
|
+
Include command help, parser errors, startup notices, and progress indicators in the inventory.
|
|
19
|
+
List its starting state, successful outcome, expected failures, and cancellation behavior.
|
|
20
|
+
Keep the existing JSON envelope, streams, and exit codes unless the task changes that contract.
|
|
21
|
+
|
|
22
|
+
Use the existing shared renderer and semantic palette.
|
|
23
|
+
Avoid adding a second framework or per-screen theme.
|
|
24
|
+
Start with `crates/skilld-ui`, `crates/skilld-command/src/output.rs`, and `crates/skilld-native/src`.
|
|
25
|
+
Inspect command help and routing in `crates/skilld-command/src/lib.rs`.
|
|
26
|
+
|
|
27
|
+
## Put the decision first
|
|
28
|
+
|
|
29
|
+
Static output starts with the requested result or the failed action.
|
|
30
|
+
Group repeated records consistently. Place supporting metadata below each record.
|
|
31
|
+
Use spacing and headings before adding boxes.
|
|
32
|
+
Keep commands copyable. Preserve whitespace inside quoted arguments.
|
|
33
|
+
Wrap prose and paths by terminal cells. Preserve the original value in machine output.
|
|
34
|
+
Give empty results a useful next action based on available commands.
|
|
35
|
+
|
|
36
|
+
Pickers show the question, query, matching count, selected item, and valid keys.
|
|
37
|
+
Full-screen views keep scope and current state visible.
|
|
38
|
+
For large inventories, start with recommendations and counts. Open projects or folders before listing individual Skills.
|
|
39
|
+
Use words for findings. Label identical copies as duplicates and show their paths; separate symlinks from directory copies.
|
|
40
|
+
State when a filter changes only the view. An action review must still list every affected target.
|
|
41
|
+
Spend rows on the user's decision. Do not reserve space for decorative panels.
|
|
42
|
+
If a pane cannot show complete content, provide reachable scrolling or a detail view.
|
|
43
|
+
At smaller sizes, simplify the layout before hiding required information.
|
|
44
|
+
If the screen is unusable, block hidden actions and show the required size.
|
|
45
|
+
|
|
46
|
+
## Use colour with independent cues
|
|
47
|
+
|
|
48
|
+
Inherit the terminal's foreground and background for body text.
|
|
49
|
+
Share roles for brand, action, secondary information, success, warning, error, focus, and selection.
|
|
50
|
+
Use one action accent across screens. Reserve status colours for actual status.
|
|
51
|
+
Show ownership as a label, without implying safety or success.
|
|
52
|
+
Pair colour with words, markers, bold text, or inverse selection.
|
|
53
|
+
Make pane focus visible when colour is disabled.
|
|
54
|
+
Honor `NO_COLOR`, `TERM=dumb`, and existing output capability detection.
|
|
55
|
+
Never claim contrast across unknown terminal themes from one screenshot.
|
|
56
|
+
|
|
57
|
+
## Make state and input agree
|
|
58
|
+
|
|
59
|
+
Use explicit states for loading, browsing, editing, review, applying, completion, and failure.
|
|
60
|
+
Prefer tagged states carrying their required data over overlapping pending flags.
|
|
61
|
+
Keep filesystem and network work outside the input loop.
|
|
62
|
+
If operations can overlap, identify their results so stale work cannot replace the current view.
|
|
63
|
+
Derive available actions and footer hints from the same state rules.
|
|
64
|
+
Keep query editing separate from global shortcuts. Typing `q` in a query must remain possible.
|
|
65
|
+
Make Escape predictable: cancel editing or review before leaving the whole screen.
|
|
66
|
+
Preserve selection by stable identity when refreshing data.
|
|
67
|
+
Bound scrolling and expose position when the remaining content is otherwise unclear.
|
|
68
|
+
Provide discoverable help when the current footer cannot explain all controls.
|
|
69
|
+
|
|
70
|
+
## Explain waiting and outcomes
|
|
71
|
+
|
|
72
|
+
Show the operation, scope, elapsed time, and available cancellation action.
|
|
73
|
+
When the total is unknown, show activity and observed counts without a percentage.
|
|
74
|
+
When the total is known, show completed and total work.
|
|
75
|
+
Keep previous results readable during refresh when they remain relevant. Label them as previous results if refresh fails.
|
|
76
|
+
Keep errors visible until the user changes state or dismisses them.
|
|
77
|
+
Do not replace an error with a filter label or a generic loading message.
|
|
78
|
+
Describe partial completion explicitly. Preserve recovery and backup paths.
|
|
79
|
+
|
|
80
|
+
Before a destructive change, show the exact action, item, paths, and content replacement.
|
|
81
|
+
Require deliberate confirmation of that specific plan.
|
|
82
|
+
Discard stale activation keys before entering consent states. Preserve cancellation requests.
|
|
83
|
+
If writes cannot stop safely, defer exit and say so. Never display a cancellation key that does nothing.
|
|
84
|
+
Restore the terminal on success, failure, and cancellation.
|
|
85
|
+
After leaving the alternate screen, print a durable summary of completed changes and recovery paths.
|
|
86
|
+
Provenance describes source evidence. It never proves that instructions are safe.
|
|
87
|
+
|
|
88
|
+
## Verify the whole journey
|
|
89
|
+
|
|
90
|
+
Run focused behavior tests for changed transitions and regressions.
|
|
91
|
+
Use the real renderer for layout tests. Do not test source text or private implementation shape.
|
|
92
|
+
Inspect actual terminal captures, including colour and monochrome.
|
|
93
|
+
Cover normal and narrow sizes, short screens, Unicode names, long paths, and resize during confirmation.
|
|
94
|
+
Exercise loading, empty results, errors, filtering, review, cancellation, completion, and return to the shell.
|
|
95
|
+
Use disposable fixtures for migration, removal, and restoration.
|
|
96
|
+
Check plain and JSON output separately for escape sequences, stream changes, and exit codes.
|
|
97
|
+
Run the repository's required checks after integration.
|
|
98
|
+
|
|
99
|
+
Report what changed and what was exercised. Identify any live path that remains untested.
|
|
100
|
+
Do not treat passing snapshots as proof of keyboard behavior or terminal restoration.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Source decisions
|
|
2
|
+
|
|
3
|
+
This Skill contains original guidance for skilld CLI work.
|
|
4
|
+
Two upstream Skills informed the design. Their application scaffolds and scripts were not incorporated.
|
|
5
|
+
|
|
6
|
+
## tui-design
|
|
7
|
+
|
|
8
|
+
Author: Diego Marino.
|
|
9
|
+
Repository: `diegomarino/tui-design`.
|
|
10
|
+
Revision: `57c199f22dbf04f057c279431d45346cc1fd5dcd`.
|
|
11
|
+
[Reviewed SKILL.md](https://github.com/diegomarino/tui-design/blob/57c199f22dbf04f057c279431d45346cc1fd5dcd/skills/tui-design/SKILL.md).
|
|
12
|
+
License: MIT, declared in the reviewed Skill frontmatter.
|
|
13
|
+
|
|
14
|
+
Adopted ideas:
|
|
15
|
+
|
|
16
|
+
- Classify static output, pickers, and full-screen interactions separately.
|
|
17
|
+
- Use semantic colours with independent selection and status cues.
|
|
18
|
+
- Design around terminal cells and inspect actual rendered evidence.
|
|
19
|
+
- Preserve selection and distinguish unknown totals from measured progress.
|
|
20
|
+
- Treat plain output and terminal restoration as product behavior.
|
|
21
|
+
|
|
22
|
+
Excluded prescriptions:
|
|
23
|
+
|
|
24
|
+
- Mandatory concept counts, large token schemas, and subjective craft scores.
|
|
25
|
+
- Python mock tooling and copied starter applications.
|
|
26
|
+
- Forced dark themes or universal shortcut sets.
|
|
27
|
+
- Mandatory NDJSON, additive-only schemas, and errors-last ordering.
|
|
28
|
+
|
|
29
|
+
These prescriptions conflict with skilld's existing contracts or add work without improving the user's decision.
|
|
30
|
+
|
|
31
|
+
## tui-development
|
|
32
|
+
|
|
33
|
+
Author: NVIDIA.
|
|
34
|
+
Repository: `NVIDIA/OpenShell`.
|
|
35
|
+
Revision: `fb8f6c0885127fe4ca29993739131a3bdbaed477`.
|
|
36
|
+
[Reviewed SKILL.md](https://github.com/NVIDIA/OpenShell/blob/fb8f6c0885127fe4ca29993739131a3bdbaed477/.agents/skills/tui-development/SKILL.md).
|
|
37
|
+
License: [Apache-2.0 at the reviewed revision](https://github.com/NVIDIA/OpenShell/blob/fb8f6c0885127fe4ca29993739131a3bdbaed477/LICENSE).
|
|
38
|
+
|
|
39
|
+
Adopted ideas:
|
|
40
|
+
|
|
41
|
+
- Keep long operations outside the input loop.
|
|
42
|
+
- Represent lifecycle states explicitly and route background results through events.
|
|
43
|
+
- Make focus, valid actions, scope, and outcomes visible.
|
|
44
|
+
- Review file changes before applying them.
|
|
45
|
+
|
|
46
|
+
Excluded prescriptions:
|
|
47
|
+
|
|
48
|
+
- OpenShell branding, topology, deployment commands, and splash screens.
|
|
49
|
+
- Mandatory Tokio, unbounded channels, and fixed network timeouts.
|
|
50
|
+
- Independent pending flags and forced interruption during writes.
|
|
51
|
+
|
|
52
|
+
The synthesis uses skilld's current host boundaries, shared rendering, and terminal lifecycle.
|
|
53
|
+
It adds durable shell summaries and actual terminal journey verification beyond the upstream build guidance.
|
|
54
|
+
It introduces no deployment, privilege, or installation requirements.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: update-package-skill
|
|
3
|
+
description: Updates an existing package Skill for a new release of its npm or local package by testing only what changed since the version the Skill names. Use when a maintainer asks to refresh a package Skill after a release, or when a SKILL.md names an older tested version than the package.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Update a package Skill
|
|
7
|
+
|
|
8
|
+
Bring an existing package Skill to a new package version with the smallest correct edit.
|
|
9
|
+
The current Skill was tested against an earlier version. Trust what the release did not touch.
|
|
10
|
+
To write a Skill from nothing, use `generate-package-skill`.
|
|
11
|
+
|
|
12
|
+
## Inputs
|
|
13
|
+
|
|
14
|
+
- The current Skill directory, and the package at the new version: a name and version, a directory, or prepared source.
|
|
15
|
+
- The tested version is the version the Skill's first paragraph names. If it names none, stop and report that the Skill needs a full rewrite.
|
|
16
|
+
- If the tested version equals the new version, change nothing and report that.
|
|
17
|
+
|
|
18
|
+
## 1. Copy, then diff
|
|
19
|
+
|
|
20
|
+
1. Copy the current Skill to the destination unchanged. Edit only the copy.
|
|
21
|
+
2. Diff the two published versions: `npm diff --diff=PACKAGE@OLD --diff=PACKAGE@NEW`. For a local package, diff the old tarball against the packed build.
|
|
22
|
+
3. Read the changelog or release notes between the two versions.
|
|
23
|
+
4. List what changed for a consumer: exports, types, options and their defaults, config keys, error messages, CLI flags, peer ranges, engines, and behaviour the notes describe.
|
|
24
|
+
|
|
25
|
+
## 2. Map changes to the Skill
|
|
26
|
+
|
|
27
|
+
For each change, find the Skill lines it affects: a claim, an example, a trap, a version limit.
|
|
28
|
+
A change is relevant when it affects a Skill line, or when it adds or breaks something an Agent would get wrong: a new trap, a renamed call, a new required setup step.
|
|
29
|
+
Internals, refactors, and fixes the Skill never mentioned are not relevant.
|
|
30
|
+
|
|
31
|
+
If no change is relevant, leave the copy byte-identical and stop. Report "no change needed" with a one-line diff summary.
|
|
32
|
+
|
|
33
|
+
## 3. Test the affected lines
|
|
34
|
+
|
|
35
|
+
1. Create one consumer fixture outside the package source, with its own `pnpm-workspace.yaml`. Install the new version and the documented peers.
|
|
36
|
+
2. Run each affected example and claim, and each example you add. Compare output with the claim: return values, type errors, build logs, exit codes.
|
|
37
|
+
3. Run each with one failure input as well, such as a bad option or an unreachable URL.
|
|
38
|
+
4. Do not re-run untouched examples. The earlier version's tests cover them.
|
|
39
|
+
5. Wrap every run in `timeout 120`. Start servers from your own script, record each process ID you start, and stop only those. Never kill by port or with `pkill -f`.
|
|
40
|
+
6. Spend about 20 tool calls on testing. Report an affected claim you could not test as untested; never claim it passed.
|
|
41
|
+
|
|
42
|
+
## 4. Edit
|
|
43
|
+
|
|
44
|
+
- Change only affected lines, and add what the release needs: a new trap, an old call → new call row, a new common task.
|
|
45
|
+
- Delete lines the release made false, and version limits it fixed.
|
|
46
|
+
- Update the tested version in the first paragraph. Other version literals go stale; avoid them.
|
|
47
|
+
- Keep the wording, order, and formatting of untouched lines exactly. The diff must show only what the release changed.
|
|
48
|
+
- Update the description only when a trigger changed, such as a renamed export or a new config key.
|
|
49
|
+
|
|
50
|
+
Keep the format rules:
|
|
51
|
+
|
|
52
|
+
- The frontmatter contains only `name` and `description`. The name matches the directory.
|
|
53
|
+
- The description is one plain YAML line without double quotes, backticks, or `%`.
|
|
54
|
+
- `SKILL.md` stays under 500 lines. Write at most eight reference files, each linked from `SKILL.md`.
|
|
55
|
+
|
|
56
|
+
## 5. Report
|
|
57
|
+
|
|
58
|
+
- The tested version, old → new, and the files you changed.
|
|
59
|
+
- Each changed line with the diff hunk or release note behind it.
|
|
60
|
+
- Each affected claim left untested.
|
|
61
|
+
- Each mismatch between the new docs and observed behaviour: example, documented result, observed result. These are package bugs.
|
|
62
|
+
|
|
63
|
+
For a direct run, show the Skill diff for review. A direct run has no Harness checks; never claim it passed them.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Harness request
|
|
2
|
+
|
|
3
|
+
The current Skill is at `{{CURRENT_SKILL_PATH}}`.
|
|
4
|
+
The prepared package source for the new version is at `{{SOURCE_PATH}}`.
|
|
5
|
+
Write the updated Skill at `{{OUTPUT_PATH}}`. The Skill directory name must be `{{SKILL_NAME}}`.
|
|
6
|
+
|
|
7
|
+
Read this Skill fully before writing files.
|
|
8
|
+
Copy the current Skill to `{{OUTPUT_PATH}}` first. If no change is relevant, leave it byte-identical and finish.
|
|
9
|
+
The network allows the npm registry and GitHub source archives only. Fetch the tested version from npm for the diff.
|
|
10
|
+
Build fixtures in a scratch directory. Write no other files outside `{{OUTPUT_PATH}}`.
|
|
11
|
+
Write only `SKILL.md` and Markdown files under `references/`: at most 9 files and 64 KiB in total. Skillgen rejects other output.
|
|
12
|
+
Do not install or run `skilld`. After you finish, the Harness checks the output and returns each failed check to you.
|
|
13
|
+
List each untested affected claim and each documentation mismatch in your final message.
|