import type { Command } from "commander"; import { RemoteSkillsClient } from "../../lib/remote-client.js"; import { type PackedSkillBundle } from "../../lib/skill-bundle.js"; export interface PushSkillOptions { dryRun?: boolean; json?: boolean; version?: string; /** * When the instance already holds this name@version with different content, publish under * the next patch version instead of failing (hasna/apps#1630). */ forceNewVersion?: boolean; client?: RemoteSkillsClient | null; /** Overrides the corpus location. Tests only. */ rootDir?: string; } export interface PushSkillResult { slug: string; path: string; sha256: string; /** Canonical content hash — identical to sha256; named for parity with the bundle manifests. */ contentHash: string; fileCount: number; bundleByteSize: number; unpackedByteSize: number; paths: string[]; published: boolean; status?: number; response?: unknown; /** The version the instance recorded (after any --force-new-version bump). */ version?: string; /** * True when the publish was idempotent: the version this push ended on already * existed on the instance with these exact bytes, so nothing new was recorded * (hasna/apps#1671). Distinct from a fresh "published as X". */ alreadyPublished?: boolean; /** Per-file digests and provenance sent alongside the bundle. */ manifest?: SkillVersionManifest; } export declare class PushSkillError extends Error { readonly detail?: string[] | undefined; constructor(message: string, detail?: string[] | undefined); } export declare function registerPublish(parent: Command): void; export declare function pushSkill(name: string, options?: PushSkillOptions): Promise; /** 1.2.3 -> 1.2.4; anything non-semver gets a numeric suffix so the bump is still unique. */ export declare function bumpPatch(version: string): string; export interface SkillVersionManifest { files: Array<{ path: string; sha256: string; byteSize: number; }>; fileCount: number; unpackedByteSize: number; bundleSha256: string; provenance: { machine: string; agent: string | null; cliVersion: string; gitRemote: string | null; gitSha: string | null; packedAt: string; }; } /** * What travels beside the bundle as manifest.json (hasna/apps#1630): a digest per file so a * pull can be checked file by file, and where the bytes came from. No secrets, no absolute * paths beyond the machine name. */ export declare function buildVersionManifest(skillDir: string, packed: PackedSkillBundle): SkillVersionManifest; /** * Strip userinfo (username/password) from a git remote URL before it is recorded in a * version manifest. Only URL schemes where userinfo is HTTP-style credentials are * stripped: an ssh login user (`ssh://git@host/...`, or scp-style `git@host:path`, * which never parses as a URL) is the transport user, not an embedded credential, and * passes through unchanged. */ export declare function sanitizeGitRemote(url: string | null): string | null; export type { PackedSkillBundle };