/** * `gsk skills pull --out ` — client-side writer for the backend * `skills_pull` action. * * Why client-side: an HTTP/JSON tool can't materialise a file tree on the * user's machine. The backend `skills_pull` action returns the skill's files * as `{ path, content_base64 }` rows; this helper decodes them and writes the * tree to disk — same split as `sb-git clone-url --execute` — plus a * `.genspark-skill.json` provenance sidecar so the tree stays identifiable * and refresh-able. Pull is an authoring/export flow (pull → edit → re-upload), * not a runtime mount path. */ /** Skill-slug shape the backend enforces (single path component, no separators * or `..`). Defined here — the lowest module in the skills-CLI import graph * (skills-sync imports `safeJoin` from it) — and re-used by skills-sync so the * client can't drift from the server's slug contract. */ export declare const SLUG_RE: RegExp; /** One file row from the backend `skills_pull` response. */ export interface SkillFile { path: string; size?: number; content_base64: string; } /** Shape of the `data` field returned by the backend `skills_pull` action. */ export interface SkillPullData { slug: string; ref?: string; owner?: string; publisher_type?: string; name?: string; commit?: string; file_count?: number; total_bytes?: number; files: SkillFile[]; } /** * Provenance sidecar written next to the pulled files. This is what turns a * pulled tree from an anonymous file dump into a managed artifact: it records * WHICH skill (owner/slug) at WHICH commit landed here, so a later pull of the * same skill can refresh the directory in place instead of being refused. */ export declare const SIDECAR_FILENAME = ".genspark-skill.json"; export interface SkillSidecar { ref?: string; owner?: string; slug?: string; commit?: string; publisher_type?: string; pulled_at?: string; file_count?: number; content_hash?: string; } /** Parse the sidecar in `dest`, or null when absent/unreadable. */ export declare function readSidecar(dest: string): SkillSidecar | null; /** Hash the tree currently on disk under `dir`, excluding the sidecar file. */ export declare function hashTree(dir: string): string; /** * Resolve the destination directory and decide whether this pull is a * sidecar-matched in-place REFRESH. Default dest: the slug in the current * directory; an explicit `--out` is honored (with `~` expansion). * * A non-empty existing directory is refused UNLESS its sidecar attests it * holds a previous pull of the SAME skill (slug match, and owner match when * both sides carry one) AND that pull is PRISTINE — the on-disk tree still * hashes to what the sidecar recorded. A pristine match refreshes in place; an * edited tree (or a same-skill dir with no recorded hash) is refused so a * re-pull never silently destroys local edits (the pull → edit → re-upload * authoring flow). A non-matching dir is refused so a pull never merges into an * unrelated tree. */ export declare function resolvePullDest(slug: string, explicit: string | undefined, pulled?: { slug: string; owner?: string; }): { dest: string; refresh: boolean; }; /** * Resolve a server-provided relative file path against `dest`, rejecting any * path that would escape the destination (absolute paths, `..` traversal). * The backend already constrains paths to the skill subtree; this is * defense-in-depth so a crafted response can't write outside `--out`. */ export declare function safeJoin(dest: string, relPath: string): string; /** * Write a `skills_pull` response to disk. Returns 0 on success, non-zero on * any failure (matches the exit-code contract the caller propagates via * `process.exit`). */ export declare function writeSkillFiles(data: SkillPullData, explicitDest: string | undefined): number; //# sourceMappingURL=skills-pull.d.ts.map