/** * Agent package format — canonical packing, validation, and identity. * * A package is a plugin directory with plugin.json plus any combination of * agents/, skills/, .mcp.json, tools/worker-module.js, and mcp-servers/**. * Every source kind (github/ado/url/upload) normalizes through this module: * validate → canonical tar.gz → sha256. The tarball is canonical — packing * the same content always yields byte-identical output — because the sha256 * carries no-op elision at publish time and download verification on workers. * * The tar writer/reader here is deliberately hand-rolled ustar rather than a * spawn of system tar: GNU and bsdtar disagree on ordering, mtime, and header * details, and canonical bytes are a correctness property, not a convenience. * See docs/proposals/agent-packages.md. * * plugin.json IS the package manifest. Identity (name/version/description) * is required; a package may ADDITIONALLY declare its artifact layout — * agents/skills/mcpConfig/mcpServers/tools/include, every path relative to * the manifest — and lay files out however it likes. Publishing stages the * declared artifacts into the canonical layout (agents/, skills/, .mcp.json, * mcp-servers/, tools/worker-module.js) and rewrites plugin.json with the * canonicalized paths, so the runtime and every downstream consumer see one * layout. Packages without layout fields keep today's convention scan, * byte-for-byte (no silent sha changes for existing packages). */ /** * Deterministic UUID reserving the artifact-store "session" that holds every * agent-package tarball. Same derivation shape as systemAgentUUID, distinct * prefix so the namespaces can never collide. */ export declare function agentPackagesArtifactSessionId(): string; /** * Canonical artifact filename for a published package version. The sha12 * suffix makes the blob content-addressed: a publish that loses the * same-semver race wrote a DIFFERENT blob than the winner, so its cleanup * can never clobber the winning version's bytes. */ export declare function agentPackageArtifactFilename(name: string, semver: string, sha256: string): string; /** * The runtime resolver matches agents case/punctuation-insensitively and * also tries a trailing-"agent"-stripped variant (session-proxy.ts * resolveAgentConfig). Collision guards MUST use the same normalization or * "Swee-per" shadows "sweeper" at runtime while validating clean. */ export declare function normalizeAgentName(value: string | undefined): string; export declare function isValidSemver(version: string): boolean; /** Standard semver precedence: -1 / 0 / 1. Build metadata ignored. */ export declare function compareSemver(a: string, b: string): number; export interface ExtractedTarEntry { name: string; body: Buffer; } /** * Read a canonical package tar.gz. Strict by design: only regular files and * directories, no links of any kind, no absolute paths, no "..", no pax * extensions — canonical tars are produced exclusively by packAgentPackage. */ export declare function readAgentPackageTarGz(targz: Buffer): ExtractedTarEntry[]; /** Extract a canonical package tar.gz under destDir (created if needed). */ export declare function extractAgentPackageTarGz(targz: Buffer, destDir: string): void; export declare const AGENT_PACKAGE_MAX_COMPRESSED_BYTES: number; export interface PackedAgentPackage { targz: Buffer; /** * Identity hash — sha256 of the UNCOMPRESSED canonical tar, NOT the gz * bytes. The deflate stream varies across zlib builds, so hashing the * gz would make byte-identical content hash differently after a Node * upgrade and trip the immutability check. The tar bytes are fully * deterministic by construction. */ sha256: string; rawBytes: number; fileCount: number; } /** * Pack a validated package directory into the canonical tar.gz. * Deterministic: sorted entries, zeroed mtime/uid/gid, normalized modes * (0755 dirs, 0644 files), gzip level 9 with a normalized gzip header. */ export declare function packAgentPackage(rootDir: string): PackedAgentPackage; /** sha256 of the canonical tar inside a package tar.gz (the identity hash). */ export declare function agentPackageTarSha256(targz: Buffer): string; /** Artifact layout a plugin.json may declare; paths relative to the file. */ export interface AgentPackageLayout { /** Paths to .agent.md files. */ agents: string[]; /** Paths to skill DIRECTORIES (each must contain SKILL.md). */ skills: string[]; /** Path to the MCP servers config JSON (canonical: .mcp.json). */ mcpConfig: string | null; /** Paths to MCP server code files or directories. */ mcpServers: string[]; /** Path to the worker tool module (canonical: tools/worker-module.js). */ tools: string | null; /** Extra files/directories shipped verbatim at their relative paths. */ include: string[]; } export declare const AGENT_PACKAGE_LAYOUT_FIELDS: readonly ["agents", "skills", "mcpConfig", "mcpServers", "tools", "include"]; /** The per-package changelog. Always staged when present — see stageAgentPackageDir. */ export declare const PACKAGE_CHANGELOG_FILE = "CHANGELOG.md"; /** * Parse the optional layout fields from a parsed plugin.json. Returns null * (with no issues) when the manifest declares no layout — convention mode. */ export declare function parseAgentPackageLayout(pluginJson: any, issues: AgentPackageIssue[]): AgentPackageLayout | null; export interface StagedAgentPackage { /** Directory to validate + pack: rootDir itself in convention mode. */ dir: string; /** True when a staging copy was produced from a declared layout. */ staged: boolean; /** Layout issues; staging is aborted when any are errors. */ issues: AgentPackageIssue[]; /** Remove the staging copy (no-op in convention mode). */ cleanup: () => void; } /** * Stage a package directory for validation + packing. * * Convention mode (no layout fields): returns rootDir untouched. * Manifest mode: copies exactly the declared artifacts into a temp dir in * the CANONICAL layout — agents/, skills//, .mcp.json, * mcp-servers/, tools/worker-module.js, include verbatim — and * writes plugin.json back with canonicalized layout paths. The staged tree * is what gets validated, packed, hashed, and unpacked on workers, so the * authored layout is a pure authoring convenience with one canonical truth. */ export declare function stageAgentPackageDir(rootDir: string): StagedAgentPackage; export interface AgentPackageIssue { code: string; message: string; file?: string; } export interface AgentPackageManifest { name: string; version: string; /** * Friendly display name from plugin.json. The picker groups agents into a * section per package, and a DNS-label package name ("finance-research-lab") * is a poor section header — this is what people actually recognise. Falls * back to `name` when unset. */ title?: string; description?: string; agents: Array<{ name: string; title?: string; description?: string; tools?: string[]; skills?: string[]; mcpServers?: string[]; splash?: string; splashMobile?: string; initialPrompt?: string; initialRequiredTool?: string; startedBy?: string[]; supportsDirectStart?: boolean; }>; skills: Array<{ name: string; description?: string; }>; mcpServers: string[]; hasTools: boolean; fileCount: number; rawBytes: number; } export interface AgentPackageValidation { ok: boolean; errors: AgentPackageIssue[]; warnings: AgentPackageIssue[]; manifest?: AgentPackageManifest; } export interface ValidateAgentPackageOptions { /** Baked agent names a package may not shadow. */ reservedAgentNames?: string[]; /** * MCP server names the deployment catalog defines. A package `.mcp.json` * may not define one of these: the catalog is flat, every worker drops * the package's definition at load, so reject it up front. */ reservedMcpServerNames?: string[]; /** Skip `node --check` (used by pure-parse test paths). */ skipSyntaxCheck?: boolean; /** Internal: rootDir is already a staged canonical tree — do not re-stage. */ preStaged?: boolean; } /** * Full registration-time validation. Every rejection here is user-facing UX: * messages state the rule and the fix, and the CLI `validate` command prints * them verbatim — keep them exact and keep the tests asserting them exact. */ export declare function validateAgentPackageDir(rootDir: string, opts?: ValidateAgentPackageOptions): Promise; //# sourceMappingURL=agent-package-format.d.ts.map