import type { SkillKind, SkillMeta } from "./registry-types.js"; import { type SkillValidationResult } from "./skill-validation.js"; import { normalizePortableSkillName, readPortableSkillManifest } from "./portable-skills-files.js"; import type { BulkPortPortableSkillOptions, BulkPortResult, PortableSkillOptions, PortableSkillRunOptions, PortableSkillRunResult, PortableSkillSummary, PortableSkillWriteResult, PortPortableSkillOptions, ScaffoldPortableSkillOptions } from "./portable-skills-types.js"; export { normalizePortableSkillName, readPortableSkillManifest, }; export * from "./portable-skills-types.js"; /** * Resolve the corpus: the directory holding one folder per installed skill. * * Precedence is explicit-over-ambient, most specific first: * 1. `options.rootDir` - the corpus, named outright (no `installed` suffix) * 2. `options.homeDir` - /.hasna/skills/installed * 3. `getDataDir()` - /installed, where the app folder is * $HASNA_SKILLS_DIR, else ~/.hasna/skills * * The app folder holds app data (config.json, skills.db, auth.json); the corpus * is a named subfolder of it, matching every sibling Hasna app. One variable * relocates the app folder and the corpus moves with it. * * `options.homeDir` used to sit *below* the $HASNA_SKILLS_DIR lookup, so an * ambient environment variable silently overrode an argument the caller had * passed deliberately - the caller could not target a directory at all once the * variable was set anywhere in the process. Reading the environment is now left * entirely to getDataDir(), so there is one place that knows the variable's name * and one rule for which source wins. */ export declare function getPortableSkillsRoot(options?: PortableSkillOptions): string; export declare function getPortableSkillPath(name: string, options?: PortableSkillOptions): string; export declare function findPortableSkill(name: string, options?: PortableSkillOptions): PortableSkillSummary | null; export declare function listPortableSkills(options?: PortableSkillOptions): PortableSkillSummary[]; export declare function listPortableSkillMetas(options?: PortableSkillOptions): SkillMeta[]; export declare function isOfficialSkillName(name: string): boolean; export declare function scaffoldPortableSkill(name: string, options?: ScaffoldPortableSkillOptions): PortableSkillWriteResult; /** * Import every immediate subfolder of a directory as a portable skill. * Skip-on-error by default: non-skill folders and per-skill failures are recorded * in the summary instead of aborting the whole run. */ export declare function portPortableSkillDirectory(sourceDir: string, options?: BulkPortPortableSkillOptions): BulkPortResult; export declare function portPortableSkill(sourcePath: string, options?: PortPortableSkillOptions): PortableSkillWriteResult; /** Metadata a Skills instance reports for a skill, used to fill the corpus manifest. */ export interface CorpusSkillMeta { displayName?: string; description?: string; category?: string; tags?: string[]; version?: string; kind?: SkillKind; } export interface WriteCorpusSkillInput { name: string; /** The SKILL.md document as served by the instance. Written verbatim. */ skillMd: string; meta?: CorpusSkillMeta | null; } /** * Write a skill fetched from a Skills instance into the local corpus * (~/.hasna/skills/installed//), so loadRegistry() surfaces it to both the CLI * (`skills list --all`) and the MCP (`list_skills`) with no further step — the whole * point of the pull: the corpus is already a first-class registry source. * * SKILL.md is written verbatim: it is the agent-facing artifact and the registry's * frontmatter source. A canonical skill.json is written beside it so * listPortableSkillMetas() reports the right kind/category/tags/version even when the * fetched SKILL.md carries thin frontmatter. * * Idempotent: re-writing the same fetched bytes yields byte-identical files. It * overwrites SKILL.md and skill.json — the instance is the source of truth for a pulled * skill — but removes nothing else, so a re-pull never destroys sibling files. */ export declare function writeCorpusSkill(input: WriteCorpusSkillInput, options?: PortableSkillOptions): PortableSkillWriteResult; export declare function validatePortableSkillDirectory(name: string, skillPath: string): SkillValidationResult; export declare function runPortableSkill(name: string, args: string[], options?: PortableSkillRunOptions): Promise;