/** * The skills store: every skill as a file on the workspace's read-only * `/host/` mount, and the cheap two-call surface a harness reads them through. * * The on-disk format is agentskills.io's SKILL.md — the format Claude Code and * Pi already read natively — so projecting a skill for a harness is a COPY, not * a translation. A translation would rewrite tool names, and tool names are * global as authored (build contract §5): a rewritten body would point the * model at a tool that does not exist. * * `/host/**` is a PER-TURN PROJECTION, not stored rows: a composed skill is a * plain code value, so the host's own deploy IS its update path and there is * nothing to migrate, invalidate, or erase. {@link hostSkillFiles} turns the * merged skills into the path→content map the workspace is opened with; the * mount is read-only through the façade, and this module never writes. * * Whatever ends up on the mount is the one source of truth for what exists, * which is why a host's own hand-authored SKILL.md lists beside a composed one * without registering anywhere. */ import type { Skill } from "./capability.js"; export type { Skill }; /** Build contract §3.1 — every skill, read-only for everyone. */ export declare const HOST_SKILLS_MOUNT = "/host/skills"; /** * A skill name is a PATH SEGMENT, so it may only be one. No dots, slashes or * whitespace — nothing that could be spelled as a traversal. Same shape as the * frozen tool-name pattern, deliberately. */ export declare const SAFE_SKILL_NAME: RegExp; export declare const skillPath: (name: string) => string; /** * A companion file beside a skill's SKILL.md, from a path relative to the skill's * own directory. * * Validated here for the same reason {@link skillPath} is: this builds a path * into the projection, and `references/../../../user/apps` would leave the mount. */ export declare const skillFilePath: (name: string, file: string) => string; /** * The slice of the workspace filesystem the skills store touches — READS only, * because `/host/` is read-only and a write through the façade is an EROFS. * * The signatures are just-bash's `IFileSystem` (build contract §3.2) for exactly * these three methods, so the real `WorkspaceFs` — and just-bash's own * `InMemoryFs` — satisfy it structurally, with nothing to adapt. */ export interface SkillsFs { readFile(path: string): Promise; getAllPaths(): string[]; } /** Build contract §1.2 — what a harness sees. `list()` is always cheap enough * to carry every turn; `load()` is the only thing that costs a body. */ export interface TurnSkills { list(): Promise; load(name: string): Promise; } export interface SkillListing { name: string; description: string; } /** One skill as its SKILL.md text: agentskills.io frontmatter, then the body * exactly as authored. */ export declare const renderSkillMd: ({ name, description, body }: Skill) => string; /** * The merged skills as the `/host/skills` half of the workspace's host * projection: path → content, ready to hand to the workspace open call. Each * skill contributes its SKILL.md and whatever companion files it declared. * * It is a plain value because the projection is per turn. Nothing is persisted, * so a skill renamed or reworded between deploys cannot leave a stale copy * behind — the composed skills are simply what exists, every turn. */ export declare const hostSkillFiles: (skills: readonly Skill[]) => Record; /** * The skills surface for one turn. * * The name is the directory's, never the frontmatter's: a hand-edited SKILL.md * whose `name:` disagreed with its folder would otherwise list a name `load()` * cannot resolve. */ export declare const createTurnSkills: (fs: SkillsFs) => TurnSkills;