@nimblebrain/mpak-sdk 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +241 -115
- package/dist/index.cjs +867 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +484 -159
- package/dist/index.d.ts +484 -159
- package/dist/index.js +857 -164
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/errors.ts"],"sourcesContent":["import { createHash } from 'crypto';\nimport type {\n MpakClientConfig,\n BundleSearchParams,\n BundleDetailResponse,\n BundleVersionsResponse,\n BundleVersionResponse,\n BundleDownloadResponse,\n SkillDetailResponse,\n SkillDownloadResponse,\n SkillSearchParams,\n Platform,\n SkillReference,\n GithubSkillReference,\n UrlSkillReference,\n ResolvedSkill,\n} from './types.js';\nimport type { BundleSearchResponse, SkillSearchResponse } from '@nimblebrain/mpak-schemas';\nimport { MpakNotFoundError, MpakIntegrityError, MpakNetworkError } from './errors.js';\n\nconst DEFAULT_REGISTRY_URL = 'https://registry.mpak.dev';\nconst DEFAULT_TIMEOUT = 30000;\n\n/**\n * Client for interacting with the mpak registry\n *\n * Requires Node.js 18+ for native fetch support.\n * Uses jszip for skill bundle extraction.\n */\nexport class MpakClient {\n private readonly registryUrl: string;\n private readonly timeout: number;\n private readonly userAgent: string | undefined;\n\n constructor(config: MpakClientConfig = {}) {\n this.registryUrl = config.registryUrl ?? DEFAULT_REGISTRY_URL;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n this.userAgent = config.userAgent;\n }\n\n // ===========================================================================\n // Bundle API\n // ===========================================================================\n\n /**\n * Search for bundles\n */\n async searchBundles(params: BundleSearchParams = {}): Promise<BundleSearchResponse> {\n const searchParams = new URLSearchParams();\n if (params.q) searchParams.set('q', params.q);\n if (params.type) searchParams.set('type', params.type);\n if (params.sort) searchParams.set('sort', params.sort);\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n\n const queryString = searchParams.toString();\n const url = `${this.registryUrl}/v1/bundles/search${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError('bundles/search endpoint');\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to search bundles: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleSearchResponse>;\n }\n\n /**\n * Get bundle details\n */\n async getBundle(name: string): Promise<BundleDetailResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleDetailResponse>;\n }\n\n /**\n * Get all versions of a bundle\n */\n async getBundleVersions(name: string): Promise<BundleVersionsResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}/versions`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle versions: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleVersionsResponse>;\n }\n\n /**\n * Get a specific version of a bundle\n */\n async getBundleVersion(name: string, version: string): Promise<BundleVersionResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle version: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleVersionResponse>;\n }\n\n /**\n * Get download info for a bundle\n */\n async getBundleDownload(\n name: string,\n version: string,\n platform?: Platform,\n ): Promise<BundleDownloadResponse> {\n this.validateScopedName(name);\n\n const params = new URLSearchParams();\n if (platform) {\n params.set('os', platform.os);\n params.set('arch', platform.arch);\n }\n\n const queryString = params.toString();\n const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}/download${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleDownloadResponse>;\n }\n\n // ===========================================================================\n // Skill API\n // ===========================================================================\n\n /**\n * Search for skills\n */\n async searchSkills(params: SkillSearchParams = {}): Promise<SkillSearchResponse> {\n const searchParams = new URLSearchParams();\n if (params.q) searchParams.set('q', params.q);\n if (params.tags) searchParams.set('tags', params.tags);\n if (params.category) searchParams.set('category', params.category);\n if (params.surface) searchParams.set('surface', params.surface);\n if (params.sort) searchParams.set('sort', params.sort);\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n\n const queryString = searchParams.toString();\n const url = `${this.registryUrl}/v1/skills/search${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError('skills/search endpoint');\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to search skills: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillSearchResponse>;\n }\n\n /**\n * Get skill details\n */\n async getSkill(name: string): Promise<SkillDetailResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDetailResponse>;\n }\n\n /**\n * Get download info for a skill (latest version)\n */\n async getSkillDownload(name: string): Promise<SkillDownloadResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}/download`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDownloadResponse>;\n }\n\n /**\n * Get download info for a specific skill version\n */\n async getSkillVersionDownload(name: string, version: string): Promise<SkillDownloadResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}/versions/${version}/download`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDownloadResponse>;\n }\n\n /**\n * Download skill content and verify integrity\n *\n * @throws {MpakIntegrityError} If expectedSha256 is provided and doesn't match (fail-closed)\n */\n async downloadSkillContent(\n downloadUrl: string,\n expectedSha256?: string,\n ): Promise<{ content: string; verified: boolean }> {\n const response = await this.fetchWithTimeout(downloadUrl);\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to download skill: HTTP ${response.status}`);\n }\n\n const content = await response.text();\n\n if (expectedSha256) {\n const actualHash = this.computeSha256(content);\n if (actualHash !== expectedSha256) {\n throw new MpakIntegrityError(expectedSha256, actualHash);\n }\n return { content, verified: true };\n }\n\n return { content, verified: false };\n }\n\n /**\n * Resolve a skill reference to actual content\n *\n * Supports mpak, github, and url sources. This is the main method for\n * fetching skill content from any supported source.\n *\n * @throws {MpakNotFoundError} If skill not found\n * @throws {MpakIntegrityError} If integrity check fails (fail-closed)\n * @throws {MpakNetworkError} For network failures\n *\n * @example\n * ```typescript\n * // Resolve from mpak registry\n * const skill = await client.resolveSkillRef({\n * source: 'mpak',\n * name: '@nimblebraininc/folk-crm',\n * version: '1.3.0',\n * });\n *\n * // Resolve from GitHub\n * const skill = await client.resolveSkillRef({\n * source: 'github',\n * name: '@example/my-skill',\n * version: 'v1.0.0',\n * repo: 'owner/repo',\n * path: 'skills/my-skill/SKILL.md',\n * });\n *\n * // Resolve from URL\n * const skill = await client.resolveSkillRef({\n * source: 'url',\n * name: '@example/custom',\n * version: '1.0.0',\n * url: 'https://example.com/skill.md',\n * });\n * ```\n */\n async resolveSkillRef(ref: SkillReference): Promise<ResolvedSkill> {\n switch (ref.source) {\n case 'mpak':\n return this.resolveMpakSkill(ref);\n case 'github':\n return this.resolveGithubSkill(ref);\n case 'url':\n return this.resolveUrlSkill(ref);\n default: {\n const _exhaustive: never = ref;\n throw new Error(`Unknown skill source: ${(_exhaustive as SkillReference).source}`);\n }\n }\n }\n\n /**\n * Resolve a skill from mpak registry\n *\n * The API returns a ZIP bundle containing SKILL.md and metadata.\n */\n private async resolveMpakSkill(ref: SkillReference & { source: 'mpak' }): Promise<ResolvedSkill> {\n const url = `${this.registryUrl}/v1/skills/${ref.name}/versions/${ref.version}/download`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${ref.name}@${ref.version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to fetch skill: HTTP ${response.status}`);\n }\n\n // Response is a ZIP file - extract SKILL.md\n const zipBuffer = await response.arrayBuffer();\n const content = await this.extractSkillFromZip(zipBuffer, ref.name);\n\n if (ref.integrity) {\n this.verifyIntegrityOrThrow(content, ref.integrity);\n return { content, version: ref.version, source: 'mpak', verified: true };\n }\n\n return { content, version: ref.version, source: 'mpak', verified: false };\n }\n\n /**\n * Resolve a skill from GitHub releases\n */\n private async resolveGithubSkill(ref: GithubSkillReference): Promise<ResolvedSkill> {\n const url = `https://github.com/${ref.repo}/releases/download/${ref.version}/${ref.path}`;\n const response = await this.fetchWithTimeout(url);\n\n if (!response.ok) {\n throw new MpakNotFoundError(`github:${ref.repo}/${ref.path}@${ref.version}`);\n }\n\n const content = await response.text();\n\n if (ref.integrity) {\n this.verifyIntegrityOrThrow(content, ref.integrity);\n return {\n content,\n version: ref.version,\n source: 'github',\n verified: true,\n };\n }\n\n return {\n content,\n version: ref.version,\n source: 'github',\n verified: false,\n };\n }\n\n /**\n * Resolve a skill from a direct URL\n */\n private async resolveUrlSkill(ref: UrlSkillReference): Promise<ResolvedSkill> {\n const response = await this.fetchWithTimeout(ref.url);\n\n if (!response.ok) {\n throw new MpakNotFoundError(`url:${ref.url}`);\n }\n\n const content = await response.text();\n\n if (ref.integrity) {\n this.verifyIntegrityOrThrow(content, ref.integrity);\n return { content, version: ref.version, source: 'url', verified: true };\n }\n\n return { content, version: ref.version, source: 'url', verified: false };\n }\n\n /**\n * Extract SKILL.md content from a skill bundle ZIP\n */\n private async extractSkillFromZip(zipBuffer: ArrayBuffer, skillName: string): Promise<string> {\n const JSZip = (await import('jszip')).default;\n const zip = await JSZip.loadAsync(zipBuffer);\n\n // Skill name format: @scope/name -> folder is just 'name'\n const folderName = skillName.split('/').pop() ?? skillName;\n const skillPath = `${folderName}/SKILL.md`;\n\n const skillFile = zip.file(skillPath);\n if (!skillFile) {\n // Try without folder prefix\n const altFile = zip.file('SKILL.md');\n if (!altFile) {\n throw new MpakNotFoundError(`SKILL.md not found in bundle for ${skillName}`);\n }\n return altFile.async('string');\n }\n\n return skillFile.async('string');\n }\n\n /**\n * Verify content integrity and throw if mismatch (fail-closed)\n */\n private verifyIntegrityOrThrow(content: string, integrity: string): void {\n const expectedHash = this.extractHash(integrity);\n const actualHash = this.computeSha256(content);\n\n if (actualHash !== expectedHash) {\n throw new MpakIntegrityError(expectedHash, actualHash);\n }\n }\n\n /**\n * Extract hash from integrity string (removes prefix)\n */\n private extractHash(integrity: string): string {\n if (integrity.startsWith('sha256:')) {\n return integrity.slice(7);\n }\n if (integrity.startsWith('sha256-')) {\n return integrity.slice(7);\n }\n return integrity;\n }\n\n // ===========================================================================\n // Utility Methods\n // ===========================================================================\n\n /**\n * Detect the current platform\n */\n static detectPlatform(): Platform {\n const nodePlatform = process.platform;\n const nodeArch = process.arch;\n\n let os: string;\n switch (nodePlatform) {\n case 'darwin':\n os = 'darwin';\n break;\n case 'win32':\n os = 'win32';\n break;\n case 'linux':\n os = 'linux';\n break;\n default:\n os = 'any';\n }\n\n let arch: string;\n switch (nodeArch) {\n case 'x64':\n arch = 'x64';\n break;\n case 'arm64':\n arch = 'arm64';\n break;\n default:\n arch = 'any';\n }\n\n return { os, arch };\n }\n\n /**\n * Compute SHA256 hash of content\n */\n private computeSha256(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n }\n\n /**\n * Validate that a name is scoped (@scope/name)\n */\n private validateScopedName(name: string): void {\n if (!name.startsWith('@')) {\n throw new Error('Package name must be scoped (e.g., @scope/package-name)');\n }\n }\n\n /**\n * Fetch with timeout support\n */\n private async fetchWithTimeout(url: string, init?: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, this.timeout);\n\n const headers: Record<string, string> = {\n ...(init?.headers as Record<string, string>),\n };\n if (this.userAgent) {\n headers['User-Agent'] = this.userAgent;\n }\n\n try {\n return await fetch(url, {\n ...init,\n headers,\n signal: controller.signal,\n });\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw new MpakNetworkError(`Request timeout after ${this.timeout}ms`);\n }\n throw new MpakNetworkError(error instanceof Error ? error.message : 'Network error');\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * Base error class for mpak SDK errors\n */\nexport class MpakError extends Error {\n code: string;\n statusCode: number | undefined;\n\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'MpakError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Thrown when a requested resource is not found (404)\n */\nexport class MpakNotFoundError extends MpakError {\n constructor(resource: string) {\n super(`Resource not found: ${resource}`, 'NOT_FOUND', 404);\n this.name = 'MpakNotFoundError';\n }\n}\n\n/**\n * Thrown when integrity verification fails (hash mismatch)\n * This is a fail-closed error - content is NOT returned when this is thrown\n */\nexport class MpakIntegrityError extends MpakError {\n expected: string;\n actual: string;\n\n constructor(expected: string, actual: string) {\n super(`Integrity mismatch: expected ${expected}, got ${actual}`, 'INTEGRITY_MISMATCH');\n this.name = 'MpakIntegrityError';\n this.expected = expected;\n this.actual = actual;\n }\n}\n\n/**\n * Thrown for network-related failures (timeouts, connection errors)\n */\nexport class MpakNetworkError extends MpakError {\n constructor(message: string) {\n super(message, 'NETWORK_ERROR');\n this.name = 'MpakNetworkError';\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/mpakSDK.ts","../src/cache.ts","../src/client.ts","../src/errors.ts","../src/helpers.ts","../src/config-manager.ts","../src/utils.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { chmodSync, existsSync, rmSync, writeFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport type { McpbManifest } from '@nimblebrain/mpak-schemas';\nimport { McpbManifestSchema } from '@nimblebrain/mpak-schemas';\nimport { MpakBundleCache } from './cache.js';\nimport { MpakClient } from './client.js';\nimport { MpakConfigManager } from './config-manager.js';\nimport { MpakCacheCorruptedError, MpakConfigError, MpakInvalidBundleError } from './errors.js';\nimport {\n extractZip,\n hashBundlePath,\n localBundleNeedsExtract,\n readJsonFromFile,\n} from './helpers.js';\nimport type { MpakClientConfig } from './types.js';\n\n/**\n * Options for the {@link Mpak} facade.\n *\n * All fields are optional — sensible defaults are derived from\n * `MpakConfigManager` (registry URL, mpakHome) when omitted.\n */\nexport interface MpakOptions {\n /** Root directory for mpak state. Defaults to `~/.mpak`. */\n mpakHome?: string;\n /** Registry URL override. Defaults to `MpakConfigManager.getRegistryUrl()`. */\n registryUrl?: string;\n /** Request timeout in milliseconds for the client. */\n timeout?: number;\n /** User-Agent string sent with every request. */\n userAgent?: string;\n}\n\n/**\n * Specifies which bundle to prepare.\n *\n * - `{ name, version? }` — registry bundle. Omit `version` for \"latest\".\n * - `{ local }` — a local `.mcpb` file on disk. The caller is responsible for\n * validating that the path exists and has a `.mcpb` extension before calling.\n */\nexport type PrepareServerSpec = { name: string; version?: string } | { local: string };\n\n/**\n * Options for {@link Mpak.prepareServer}.\n */\nexport interface PrepareServerOptions {\n /** Skip cache and re-download/re-extract. */\n force?: boolean;\n /** Extra environment variables merged on top of the manifest env. */\n env?: Record<string, string>;\n /**\n * Directory for `MPAK_WORKSPACE` — where stateful bundles write\n * project-local data (databases, logs, etc.). Defaults to `process.cwd()/.mpak`.\n */\n workspaceDir?: string;\n}\n\n/**\n * Fully resolved server configuration, ready to spawn.\n */\nexport interface ServerCommand {\n /** The executable command (e.g. `\"node\"`, `\"python3\"`, or an absolute binary path). */\n command: string;\n /** Arguments to pass to the command. */\n args: string[];\n /** Environment variables (manifest env + user config substitutions + caller overrides). */\n env: Record<string, string>;\n /** Working directory for the spawned process — the extracted bundle's cache directory. */\n cwd: string;\n /** The resolved package name. */\n name: string;\n /** The resolved version string. */\n version: string;\n}\n\n/**\n * Top-level facade that wires together the SDK's core components:\n * `MpakConfigManager`, `MpakClient`, and `BundleCache`.\n *\n * Provides a single entry point for the common setup pattern,\n * while still exposing each component for direct use.\n *\n * @example\n * ```ts\n * import { MpakSDK } from '@nimblebrain/mpak-sdk';\n *\n * const mpak = new MpakSDK();\n *\n * // Prepare a server for spawning\n * const server = await mpak.prepareServer('@scope/pkg');\n * const child = spawn(server.command, server.args, {\n * env: { ...server.env, ...process.env },\n * cwd: server.cwd,\n * stdio: 'inherit',\n * });\n *\n * // Access components directly\n * mpak.config.setPackageConfigValue('@scope/pkg', 'api_key', 'sk-...');\n * const bundles = await mpak.client.searchBundles({ q: 'mcp' });\n * ```\n */\nexport class Mpak {\n /** User configuration manager (`config.json`). */\n readonly configManager: MpakConfigManager;\n /** Registry API client. */\n readonly client: MpakClient;\n /** Local bundle cache. */\n readonly bundleCache: MpakBundleCache;\n\n constructor(options?: MpakOptions) {\n // initialize config\n const configOptions: { mpakHome?: string; registryUrl?: string } = {};\n if (options?.mpakHome !== undefined) configOptions.mpakHome = options.mpakHome;\n if (options?.registryUrl !== undefined) configOptions.registryUrl = options.registryUrl;\n this.configManager = new MpakConfigManager(configOptions);\n\n // initialize client\n const clientConfig: MpakClientConfig = {\n registryUrl: this.configManager.getRegistryUrl(),\n };\n if (options?.timeout !== undefined) clientConfig.timeout = options.timeout;\n if (options?.userAgent !== undefined) clientConfig.userAgent = options.userAgent;\n this.client = new MpakClient(clientConfig);\n\n // initialize cache\n this.bundleCache = new MpakBundleCache(this.client, {\n mpakHome: this.configManager.mpakHome,\n });\n }\n\n /**\n * Prepare a bundle for execution.\n *\n * Accepts either a registry spec (`{ name, version? }`) or a local bundle\n * spec (`{ local }`). Downloads/extracts as needed, reads the manifest,\n * validates user config, and resolves the command, args, and env needed\n * to spawn the MCP server process.\n *\n * @param spec - Which bundle to prepare. See {@link PrepareServerSpec}.\n * @param options - Force re-download/re-extract, extra env, and workspace dir.\n *\n * @throws {MpakConfigError} If required user config values are missing.\n * @throws {MpakCacheCorruptedError} If the manifest is missing or corrupt after download.\n */\n async prepareServer(\n spec: PrepareServerSpec,\n options?: PrepareServerOptions,\n ): Promise<ServerCommand> {\n let cacheDir: string;\n let name: string;\n let version: string;\n let manifest: McpbManifest;\n\n if ('local' in spec) {\n ({ cacheDir, name, version, manifest } = await this.prepareLocalBundle(spec.local, options));\n } else {\n ({ cacheDir, name, version, manifest } = await this.prepareRegistryBundle(\n spec.name,\n spec.version,\n options,\n ));\n }\n\n // Gather and validate user config\n const userConfigValues = this.gatherUserConfig(name, manifest);\n\n // Build command/args/env\n const { command, args, env } = this.resolveCommand(manifest, cacheDir, userConfigValues);\n\n // Set MPAK_WORKSPACE\n env['MPAK_WORKSPACE'] = options?.workspaceDir ?? join(process.cwd(), '.mpak');\n\n // Merge caller-provided env (wins over defaults)\n if (options?.env) {\n Object.assign(env, options.env);\n }\n\n return { command, args, env, cwd: cacheDir, name, version };\n }\n\n // ===========================================================================\n // Private helpers\n // ===========================================================================\n\n /**\n * Load a registry bundle into cache and read its manifest.\n */\n private async prepareRegistryBundle(\n packageName: string,\n version: string | undefined,\n options?: PrepareServerOptions,\n ): Promise<{ cacheDir: string; name: string; version: string; manifest: McpbManifest }> {\n const loadOptions: { version?: string; force?: boolean } = {};\n if (version !== undefined) loadOptions.version = version;\n if (options?.force !== undefined) loadOptions.force = options.force;\n const loadResult = await this.bundleCache.loadBundle(packageName, loadOptions);\n\n const manifest = this.bundleCache.getBundleManifest(packageName);\n if (!manifest) {\n throw new MpakCacheCorruptedError(\n `Manifest file missing for ${packageName}`,\n join(this.bundleCache.cacheHome, packageName),\n );\n }\n\n return {\n cacheDir: loadResult.cacheDir,\n name: packageName,\n version: loadResult.version,\n manifest,\n };\n }\n\n /**\n * Extract a local `.mcpb` bundle (if stale) and read its manifest.\n * Local bundles are cached under `<cacheHome>/_local/<hash>`.\n *\n * The caller is responsible for validating that `bundlePath` exists\n * and has a `.mcpb` extension before calling this method.\n */\n private async prepareLocalBundle(\n bundlePath: string,\n options?: PrepareServerOptions,\n ): Promise<{ cacheDir: string; name: string; version: string; manifest: McpbManifest }> {\n const absolutePath = resolve(bundlePath);\n const hash = hashBundlePath(absolutePath);\n const cacheDir = join(this.bundleCache.cacheHome, '_local', hash);\n\n const needsExtract = options?.force || localBundleNeedsExtract(absolutePath, cacheDir);\n\n if (needsExtract) {\n if (existsSync(cacheDir)) {\n rmSync(cacheDir, { recursive: true, force: true });\n }\n\n try {\n extractZip(absolutePath, cacheDir);\n } catch (err) {\n throw new MpakInvalidBundleError(\n err instanceof Error ? err.message : String(err),\n absolutePath,\n err instanceof Error ? err : undefined,\n );\n }\n\n writeFileSync(\n join(cacheDir, '.mpak-local-meta.json'),\n JSON.stringify({\n localPath: absolutePath,\n extractedAt: new Date().toISOString(),\n }),\n );\n }\n\n let manifest: McpbManifest;\n try {\n manifest = readJsonFromFile(join(cacheDir, 'manifest.json'), McpbManifestSchema);\n } catch (err) {\n throw new MpakInvalidBundleError(\n err instanceof Error ? err.message : String(err),\n absolutePath,\n err instanceof Error ? err : undefined,\n );\n }\n\n return { cacheDir, name: manifest.name, version: manifest.version, manifest };\n }\n\n /**\n * Gather stored user config values and validate that all required fields are present.\n * @throws If required config values are missing.\n */\n private gatherUserConfig(packageName: string, manifest: McpbManifest): Record<string, string> {\n if (!manifest.user_config || Object.keys(manifest.user_config).length === 0) {\n return {};\n }\n\n const storedConfig = this.configManager.getPackageConfig(packageName) ?? {};\n const result: Record<string, string> = {};\n const missingFields: Array<{\n key: string;\n title: string;\n description?: string;\n sensitive: boolean;\n }> = [];\n\n for (const [fieldName, fieldData] of Object.entries(manifest.user_config)) {\n const storedValue = storedConfig[fieldName];\n\n if (storedValue !== undefined) {\n result[fieldName] = storedValue;\n } else if (fieldData.default !== undefined && fieldData.default !== null) {\n result[fieldName] = String(fieldData.default);\n } else if (fieldData.required) {\n const field: (typeof missingFields)[number] = {\n key: fieldName,\n title: fieldData.title ?? fieldName,\n sensitive: fieldData.sensitive ?? false,\n };\n if (fieldData.description !== undefined) {\n field.description = fieldData.description;\n }\n missingFields.push(field);\n }\n }\n\n if (missingFields.length > 0) {\n throw new MpakConfigError(packageName, missingFields);\n }\n\n return result;\n }\n\n /**\n * Resolve the manifest's `server` block into a spawnable command, args, and env.\n *\n * Handles three server types:\n * - **binary** — runs the compiled executable at `entry_point`, chmod'd +x.\n * - **node** — runs `mcp_config.command` (default `\"node\"`) with `mcp_config.args`,\n * or falls back to `node <entry_point>` when args are empty.\n * - **python** — like node, but resolves `python3`/`python` at runtime and\n * prepends `<cacheDir>/deps` to `PYTHONPATH` for bundled dependencies.\n *\n * All `${__dirname}` placeholders in args are replaced with `cacheDir`.\n * All `${user_config.*}` placeholders in env are replaced with gathered user values.\n *\n * @throws For unsupported server types.\n */\n private resolveCommand(\n manifest: McpbManifest,\n cacheDir: string,\n userConfigValues: Record<string, string>,\n ): { command: string; args: string[]; env: Record<string, string> } {\n const { type, entry_point, mcp_config } = manifest.server;\n\n // Substitute user_config placeholders in manifest env\n const env = Mpak.substituteEnvVars(mcp_config.env, userConfigValues);\n\n let command: string;\n let args: string[];\n\n switch (type) {\n case 'binary': {\n command = join(cacheDir, entry_point);\n args = Mpak.resolveArgs(mcp_config.args ?? [], cacheDir);\n try {\n chmodSync(command, 0o755);\n } catch {\n // Ignore chmod errors on Windows\n }\n break;\n }\n\n case 'node': {\n command = mcp_config.command || 'node';\n args =\n mcp_config.args.length > 0\n ? Mpak.resolveArgs(mcp_config.args, cacheDir)\n : [join(cacheDir, entry_point)];\n break;\n }\n\n case 'python': {\n command =\n mcp_config.command === 'python'\n ? Mpak.findPythonCommand()\n : mcp_config.command || Mpak.findPythonCommand();\n args =\n mcp_config.args.length > 0\n ? Mpak.resolveArgs(mcp_config.args, cacheDir)\n : [join(cacheDir, entry_point)];\n\n // Set PYTHONPATH to deps/ directory\n const depsDir = join(cacheDir, 'deps');\n env['PYTHONPATH'] = env['PYTHONPATH'] ? `${depsDir}:${env['PYTHONPATH']}` : depsDir;\n break;\n }\n\n case 'uv': {\n command = mcp_config.command || 'uv';\n args =\n mcp_config.args.length > 0\n ? Mpak.resolveArgs(mcp_config.args, cacheDir)\n : ['run', join(cacheDir, entry_point)];\n break;\n }\n\n default: {\n const _exhaustive: never = type;\n throw new MpakCacheCorruptedError(\n `Unsupported server type \"${_exhaustive}\" in manifest for ${manifest.name}`,\n cacheDir,\n );\n }\n }\n\n return { command, args, env };\n }\n\n /**\n * Substitute `${__dirname}` placeholders in args.\n */\n private static resolveArgs(args: string[], cacheDir: string): string[] {\n return args.map((arg) => arg.replace(/\\$\\{__dirname\\}/g, cacheDir));\n }\n\n /**\n * Substitute `${user_config.*}` placeholders in env vars.\n */\n private static substituteEnvVars(\n env: Record<string, string> | undefined,\n userConfigValues: Record<string, string>,\n ): Record<string, string> {\n if (!env) return {};\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n result[key] = value.replace(\n /\\$\\{user_config\\.([^}]+)\\}/g,\n (match, configKey: string) => userConfigValues[configKey] ?? match,\n );\n }\n return result;\n }\n\n /**\n * Find a working Python executable. Tries `python3` first, falls back to `python`.\n */\n private static findPythonCommand(): string {\n const result = spawnSync('python3', ['--version'], { stdio: 'pipe' });\n if (result.status === 0) {\n return 'python3';\n }\n return 'python';\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport { existsSync, readdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { homedir, tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type {\n CachedBundleInfo,\n CacheMetadata,\n DownloadInfo,\n McpbManifest,\n} from '@nimblebrain/mpak-schemas';\nimport { CacheMetadataSchema, McpbManifestSchema } from '@nimblebrain/mpak-schemas';\nimport { MpakClient } from './client.js';\nimport { MpakCacheCorruptedError } from './errors.js';\nimport { extractZip, isSemverEqual, readJsonFromFile, UPDATE_CHECK_TTL_MS } from './helpers.js';\n\nexport interface MpakBundleCacheOptions {\n mpakHome?: string;\n}\n\n/**\n * Manages the local bundle cache (`~/.mpak/cache/`).\n *\n * Handles downloading, extracting, and tracking cached bundles.\n * The cache directory is derived from `mpakHome` — the root directory\n * for all mpak state. Consumers can wire this to `MpakConfigManager.mpakHome`\n * for a shared base, or pass any directory.\n *\n * Requires an `MpakClient` for registry operations (download, update checks).\n *\n * @example\n * ```ts\n * // Via MpakSDK facade (recommended)\n * const mpak = new MpakSDK();\n * await mpak.cache.loadBundle('@scope/name');\n *\n * // Standalone\n * const client = new MpakClient();\n * const cache = new MpakBundleCache(client, { mpakHome: '/path/to/.mpak' });\n * await cache.loadBundle('@scope/name');\n * ```\n */\nexport class MpakBundleCache {\n public readonly cacheHome: string;\n private readonly mpakClient: MpakClient;\n\n constructor(client: MpakClient, options?: MpakBundleCacheOptions) {\n this.mpakClient = client;\n\n this.cacheHome = join(options?.mpakHome ?? join(homedir(), '.mpak'), 'cache');\n }\n\n /**\n * Compute the cache path for a package. Does not create the directory.\n * @example getPackageCachePath('@scope/name') => '<cacheBase>/scope-name'\n */\n getBundleCacheDirName(packageName: string): string {\n const safeName = packageName.replace('@', '').replace('/', '-');\n return join(this.cacheHome, safeName);\n }\n\n /**\n * Read and validate cache metadata for a package.\n * Returns `null` if the package does not exist in the cache.\n * throws Error if metadata is corrupt\n */\n getBundleMetadata(packageName: string): CacheMetadata | null {\n const packageCacheDir = this.getBundleCacheDirName(packageName);\n\n if (!existsSync(packageCacheDir)) {\n return null;\n }\n\n const metaPath = join(packageCacheDir, '.mpak-meta.json');\n\n try {\n return readJsonFromFile(metaPath, CacheMetadataSchema);\n } catch (err) {\n throw new MpakCacheCorruptedError(\n err instanceof Error ? err.message : String(err),\n metaPath,\n err instanceof Error ? err : undefined,\n );\n }\n }\n\n /**\n * Read and validate the MCPB manifest from a cached package.\n * Returns `null` if the package is not cached (directory doesn't exist).\n *\n * @throws {MpakCacheCorruptedError} If the cache directory exists but\n * `manifest.json` is missing, contains invalid JSON, or fails schema validation.\n */\n getBundleManifest(packageName: string): McpbManifest | null {\n const dir = this.getBundleCacheDirName(packageName);\n\n if (!existsSync(dir)) {\n return null;\n }\n\n const manifestPath = join(dir, 'manifest.json');\n\n try {\n return readJsonFromFile(manifestPath, McpbManifestSchema);\n } catch (err) {\n throw new MpakCacheCorruptedError(\n err instanceof Error ? err.message : String(err),\n manifestPath,\n err instanceof Error ? err : undefined,\n );\n }\n }\n\n /**\n * Scan the cache directory and return metadata for every cached registry bundle.\n * Skips the `_local/` directory (local dev bundles) and entries with\n * missing/corrupt metadata or manifests.\n */\n listCachedBundles(): CachedBundleInfo[] {\n if (!existsSync(this.cacheHome)) return [];\n\n const entries = readdirSync(this.cacheHome, { withFileTypes: true });\n const bundles: CachedBundleInfo[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name === '_local') continue;\n\n const cacheDir = join(this.cacheHome, entry.name);\n try {\n const manifest = readJsonFromFile(join(cacheDir, 'manifest.json'), McpbManifestSchema);\n const meta = this.getBundleMetadata(manifest.name);\n if (!meta) continue;\n\n bundles.push({\n name: manifest.name,\n version: meta.version,\n pulledAt: meta.pulledAt,\n cacheDir: cacheDir,\n });\n } catch {\n // in case an entry is corrupted, it should not be listed\n }\n }\n\n return bundles;\n }\n\n /**\n * Remove a cached bundle from disk.\n * @returns `true` if the bundle was cached and removed, `false` if it wasn't cached.\n */\n removeCachedBundle(packageName: string): boolean {\n const dir = this.getBundleCacheDirName(packageName);\n if (!existsSync(dir)) return false;\n rmSync(dir, { recursive: true, force: true });\n return true;\n }\n\n /**\n * Load a bundle into the local cache, downloading from the registry only\n * if the cache is missing or stale. Returns the cache directory and version.\n *\n * Requires an `MpakClient` to be provided at construction time.\n *\n * @param name - Scoped package name (e.g. `@scope/bundle`)\n * @param options.version - Specific version to load. Omit for \"latest\".\n * @param options.force - Skip cache checks and always re-download.\n *\n * @returns `cacheDir` — path to the extracted bundle on disk,\n * `version` — the resolved version string,\n * `pulled` — whether a download actually occurred.\n *\n * @throws If no `MpakClient` was provided at construction time.\n */\n async loadBundle(\n name: string,\n options?: { version?: string; force?: boolean },\n ): Promise<{ cacheDir: string; version: string; pulled: boolean }> {\n const { version: requestedVersion, force = false } = options ?? {};\n const cacheDir = this.getBundleCacheDirName(name);\n\n let cachedMeta: CacheMetadata | null = null;\n try {\n cachedMeta = this.getBundleMetadata(name);\n } catch {\n // Treat cache as non existent if cache is corrupt\n }\n\n /*\n We immediately return from cache when\n 1. Not forced, AND\n 2. Cache exists, AND\n 3. Either no version requested, OR cached version matches requested version\n If any fails, we go to registry\n */\n\n if (\n !options?.force &&\n !!cachedMeta &&\n (!requestedVersion || isSemverEqual(cachedMeta.version, requestedVersion))\n ) {\n return { cacheDir, version: cachedMeta.version, pulled: false };\n }\n\n // Get download info from registry\n const platform = MpakClient.detectPlatform();\n const downloadInfo = await this.mpakClient.getBundleDownload(\n name,\n requestedVersion ?? 'latest',\n platform,\n );\n\n // Registry resolved to the same version we already have — skip download\n if (!force && cachedMeta && isSemverEqual(cachedMeta.version, downloadInfo.bundle.version)) {\n // Update lastCheckedAt since we just verified with the registry\n this.writeCacheMetadata(name, {\n ...cachedMeta,\n lastCheckedAt: new Date().toISOString(),\n });\n return { cacheDir, version: cachedMeta.version, pulled: false };\n }\n\n // Download and extract\n await this.downloadAndExtract(name, downloadInfo);\n return { cacheDir, version: downloadInfo.bundle.version, pulled: true };\n }\n\n /**\n * Fire-and-forget background check for bundle updates.\n * Return the latest version string if an update is available, null otherwise (not cached, skipped, up-to-date, or error).\n * The caller can just check `if (result) { console.log(\"update available: \" + result) }`\n * @param packageName - Scoped package name (e.g. `@scope/bundle`)\n */\n async checkForUpdate(packageName: string, options?: { force?: boolean }): Promise<string | null> {\n const cachedMeta = this.getBundleMetadata(packageName);\n if (!cachedMeta) return null;\n\n // Skip if checked within the TTL (unless force is set)\n if (!options?.force && cachedMeta.lastCheckedAt) {\n const elapsed = Date.now() - new Date(cachedMeta.lastCheckedAt).getTime();\n if (elapsed < UPDATE_CHECK_TTL_MS) return null;\n }\n\n try {\n const detail = await this.mpakClient.getBundle(packageName);\n\n // Update lastCheckedAt regardless of whether there's an update\n this.writeCacheMetadata(packageName, {\n ...cachedMeta,\n lastCheckedAt: new Date().toISOString(),\n });\n\n if (!isSemverEqual(detail.latest_version, cachedMeta.version)) {\n return detail.latest_version;\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n // ===========================================================================\n // Private methods\n // ===========================================================================\n\n /**\n * Write cache metadata for a package.\n * @throws If the metadata fails schema validation.\n */\n private writeCacheMetadata(packageName: string, metadata: CacheMetadata): void {\n const metaPath = join(this.getBundleCacheDirName(packageName), '.mpak-meta.json');\n\n writeFileSync(metaPath, JSON.stringify(metadata, null, 2));\n }\n\n /**\n * Download a bundle using pre-resolved download info, extract it into\n * the cache, and write metadata.\n */\n private async downloadAndExtract(name: string, downloadInfo: DownloadInfo): Promise<void> {\n const bundle = downloadInfo.bundle;\n const cacheDir = this.getBundleCacheDirName(name);\n\n // Download to temp file (using OS temp dir, not inside cache)\n const tempPath = join(tmpdir(), `mpak-${Date.now()}-${randomUUID().slice(0, 8)}.mcpb`);\n\n try {\n const data = await this.mpakClient.downloadContent(downloadInfo.url, bundle.sha256);\n writeFileSync(tempPath, data);\n\n // Clear old cache and extract\n if (existsSync(cacheDir)) {\n rmSync(cacheDir, { recursive: true, force: true });\n }\n\n extractZip(tempPath, cacheDir);\n\n // Write metadata\n this.writeCacheMetadata(name, {\n version: bundle.version,\n pulledAt: new Date().toISOString(),\n platform: bundle.platform,\n });\n } finally {\n rmSync(tempPath, { force: true });\n }\n }\n}\n","import type {\n BundleDetail,\n BundleSearchResponse,\n DownloadInfo,\n PlatformInfo,\n SkillDetail,\n SkillDownloadInfo,\n SkillSearchResponse,\n VersionDetail,\n VersionsResponse,\n} from '@nimblebrain/mpak-schemas';\nimport { createHash } from 'node:crypto';\nimport { MpakError, MpakIntegrityError, MpakNetworkError, MpakNotFoundError } from './errors.js';\nimport type { BundleSearchParams, MpakClientConfig, SkillSearchParams } from './types.js';\n\nconst DEFAULT_REGISTRY_URL = 'https://registry.mpak.dev';\nconst DEFAULT_TIMEOUT = 30000;\n\n/**\n * Client for interacting with the mpak registry\n *\n * Requires Node.js 18+ for native fetch support.\n */\nexport class MpakClient {\n private readonly registryUrl: string;\n private readonly timeout: number;\n private readonly userAgent: string | undefined;\n\n constructor(config: MpakClientConfig = {}) {\n this.registryUrl = config.registryUrl ?? DEFAULT_REGISTRY_URL;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n this.userAgent = config.userAgent;\n }\n\n // ===========================================================================\n // Bundle API\n // ===========================================================================\n\n /**\n * Search for bundles\n */\n async searchBundles(params: BundleSearchParams = {}): Promise<BundleSearchResponse> {\n const searchParams = new URLSearchParams();\n if (params.q) searchParams.set('q', params.q);\n if (params.type) searchParams.set('type', params.type);\n if (params.sort) searchParams.set('sort', params.sort);\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n\n const queryString = searchParams.toString();\n const url = `${this.registryUrl}/v1/bundles/search${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError('bundles/search endpoint');\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to search bundles: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleSearchResponse>;\n }\n\n /**\n * Get bundle details\n */\n async getBundle(name: string): Promise<BundleDetail> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<BundleDetail>;\n }\n\n /**\n * Get all versions of a bundle\n */\n async getBundleVersions(name: string): Promise<VersionsResponse> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}/versions`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle versions: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<VersionsResponse>;\n }\n\n /**\n * Get a specific version of a bundle\n */\n async getBundleVersion(name: string, version: string): Promise<VersionDetail> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle version: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<VersionDetail>;\n }\n\n /**\n * Get download info for a bundle\n */\n async getBundleDownload(\n name: string,\n version: string,\n platform?: PlatformInfo,\n ): Promise<DownloadInfo> {\n this.validateScopedName(name);\n\n const params = new URLSearchParams();\n if (platform) {\n params.set('os', platform.os);\n params.set('arch', platform.arch);\n }\n\n const queryString = params.toString();\n const url = `${this.registryUrl}/v1/bundles/${name}/versions/${version}/download${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get bundle download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<DownloadInfo>;\n }\n\n // ===========================================================================\n // Skill API\n // ===========================================================================\n\n /**\n * Search for skills\n */\n async searchSkills(params: SkillSearchParams = {}): Promise<SkillSearchResponse> {\n const searchParams = new URLSearchParams();\n if (params.q) searchParams.set('q', params.q);\n if (params.tags) searchParams.set('tags', params.tags);\n if (params.category) searchParams.set('category', params.category);\n if (params.sort) searchParams.set('sort', params.sort);\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n\n const queryString = searchParams.toString();\n const url = `${this.registryUrl}/v1/skills/search${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError('skills/search endpoint');\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to search skills: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillSearchResponse>;\n }\n\n /**\n * Get skill details\n */\n async getSkill(name: string): Promise<SkillDetail> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}`;\n const response = await this.fetchWithTimeout(url);\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDetail>;\n }\n\n /**\n * Get download info for a skill (latest version)\n */\n async getSkillDownload(name: string): Promise<SkillDownloadInfo> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}/download`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(name);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDownloadInfo>;\n }\n\n /**\n * Get download info for a specific skill version\n */\n async getSkillVersionDownload(name: string, version: string): Promise<SkillDownloadInfo> {\n this.validateScopedName(name);\n\n const url = `${this.registryUrl}/v1/skills/${name}/versions/${version}/download`;\n\n const response = await this.fetchWithTimeout(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (response.status === 404) {\n throw new MpakNotFoundError(`${name}@${version}`);\n }\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to get skill download: HTTP ${response.status}`);\n }\n\n return response.json() as Promise<SkillDownloadInfo>;\n }\n\n // ===========================================================================\n // Download Methods\n // ===========================================================================\n\n /**\n * Download content from a URL and verify its SHA-256 integrity.\n *\n * @throws {MpakIntegrityError} If SHA-256 doesn't match\n * @throws {MpakNetworkError} For network failures\n */\n async downloadContent(url: string, sha256: string): Promise<Uint8Array> {\n const response = await this.fetchWithTimeout(url);\n\n if (!response.ok) {\n throw new MpakNetworkError(`Failed to download: HTTP ${response.status}`);\n }\n\n const downloadedRawData = new Uint8Array(await response.arrayBuffer());\n\n const computedHash = this.computeSha256(downloadedRawData);\n if (computedHash !== sha256) {\n throw new MpakIntegrityError(sha256, computedHash);\n }\n\n return downloadedRawData;\n }\n\n /**\n * Download a bundle by name, with optional version and platform.\n * Defaults to latest version and auto-detected platform.\n *\n * @throws {MpakNotFoundError} If bundle not found\n * @throws {MpakIntegrityError} If SHA-256 doesn't match\n * @throws {MpakNetworkError} For network failures\n */\n async downloadBundle(\n name: string,\n version?: string,\n platform?: PlatformInfo,\n ): Promise<{\n data: Uint8Array;\n metadata: DownloadInfo['bundle'];\n }> {\n const resolvedPlatform = platform ?? MpakClient.detectPlatform();\n const resolvedVersion = version ?? 'latest';\n\n const downloadInfo = await this.getBundleDownload(name, resolvedVersion, resolvedPlatform);\n const data = await this.downloadContent(downloadInfo.url, downloadInfo.bundle.sha256);\n\n return { data, metadata: downloadInfo.bundle };\n }\n\n /**\n * Download a skill bundle by name, with optional version.\n * Defaults to latest version.\n *\n * @throws {MpakNotFoundError} If skill not found\n * @throws {MpakIntegrityError} If SHA-256 doesn't match\n * @throws {MpakNetworkError} For network failures\n */\n async downloadSkillBundle(\n name: string,\n version?: string,\n ): Promise<{\n data: Uint8Array;\n metadata: SkillDownloadInfo['skill'];\n }> {\n const resolvedVersion = version ?? 'latest';\n\n const downloadInfo = await this.getSkillVersionDownload(name, resolvedVersion);\n const data = await this.downloadContent(downloadInfo.url, downloadInfo.skill.sha256);\n\n return { data, metadata: downloadInfo.skill };\n }\n\n // ===========================================================================\n // Utility Methods\n // ===========================================================================\n\n /**\n * Detect the current platform\n */\n static detectPlatform(): PlatformInfo {\n const nodePlatform = process.platform;\n const nodeArch = process.arch;\n\n let os: string;\n switch (nodePlatform) {\n case 'darwin':\n os = 'darwin';\n break;\n case 'win32':\n os = 'win32';\n break;\n case 'linux':\n os = 'linux';\n break;\n default:\n os = 'any';\n }\n\n let arch: string;\n switch (nodeArch) {\n case 'x64':\n arch = 'x64';\n break;\n case 'arm64':\n arch = 'arm64';\n break;\n default:\n arch = 'any';\n }\n\n return { os, arch };\n }\n\n /**\n * Compute SHA256 hash of content\n */\n private computeSha256(content: string | Uint8Array): string {\n return createHash('sha256').update(content).digest('hex');\n }\n\n /**\n * Validate that a name is scoped (@scope/name)\n */\n private validateScopedName(name: string): void {\n if (!name.startsWith('@')) {\n throw new MpakError(\n 'Package name must be scoped (e.g., @scope/package-name)',\n 'INVALID_SPEC',\n );\n }\n }\n\n /**\n * Fetch with timeout support\n */\n private async fetchWithTimeout(url: string, init?: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, this.timeout);\n\n const headers: Record<string, string> = {\n ...(init?.headers as Record<string, string>),\n };\n if (this.userAgent) {\n headers['User-Agent'] = this.userAgent;\n }\n\n try {\n return await fetch(url, {\n ...init,\n headers,\n signal: controller.signal,\n });\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n throw new MpakNetworkError(`Request timeout after ${this.timeout}ms`);\n }\n throw new MpakNetworkError(error instanceof Error ? error.message : 'Network error');\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * Base error class for mpak SDK errors\n */\nexport class MpakError extends Error {\n code: string;\n statusCode: number | undefined;\n\n constructor(message: string, code: string, statusCode?: number) {\n super(message);\n this.name = 'MpakError';\n this.code = code;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Thrown when a requested resource is not found (404)\n */\nexport class MpakNotFoundError extends MpakError {\n constructor(resource: string) {\n super(`Resource not found: ${resource}`, 'NOT_FOUND', 404);\n this.name = 'MpakNotFoundError';\n }\n}\n\n/**\n * Thrown when integrity verification fails (hash mismatch)\n * This is a fail-closed error - content is NOT returned when this is thrown\n */\nexport class MpakIntegrityError extends MpakError {\n expected: string;\n actual: string;\n\n constructor(expected: string, actual: string) {\n super(`Integrity mismatch: expected ${expected}, got ${actual}`, 'INTEGRITY_MISMATCH');\n this.name = 'MpakIntegrityError';\n this.expected = expected;\n this.actual = actual;\n }\n}\n\n/**\n * Thrown for network-related failures (timeouts, connection errors)\n */\nexport class MpakNetworkError extends MpakError {\n constructor(message: string) {\n super(message, 'NETWORK_ERROR');\n this.name = 'MpakNetworkError';\n }\n}\n\n/**\n * Thrown when the config file cannot be read, parsed, or validated.\n *\n * @param message - Human-readable description of what went wrong\n * @param configPath - Absolute path to the config file that failed\n * @param cause - The underlying error (parse failure, read error, etc.)\n */\nexport class MpakConfigCorruptedError extends MpakError {\n constructor(\n message: string,\n public readonly configPath: string,\n public override readonly cause?: Error,\n ) {\n super(message, 'CONFIG_CORRUPTED');\n this.name = 'MpakConfigCorruptedError';\n }\n}\n\n/**\n * Thrown when required user config fields are missing for a package.\n *\n * @param packageName - The package that requires config\n * @param missingFields - Structured list of missing fields\n */\n/**\n * Thrown when cache metadata or manifest is missing, corrupt, or fails validation.\n *\n * @param message - Human-readable description of what went wrong\n * @param filePath - Absolute path to the file that failed\n * @param cause - The underlying error (parse failure, validation error, etc.)\n */\nexport class MpakCacheCorruptedError extends MpakError {\n constructor(\n message: string,\n public readonly filePath: string,\n public override readonly cause?: Error,\n ) {\n super(message, 'CACHE_CORRUPTED');\n this.name = 'MpakCacheCorruptedError';\n }\n}\n\n/**\n * Thrown when a local `.mcpb` bundle is invalid — e.g. manifest is missing,\n * contains invalid JSON, or fails schema validation.\n *\n * @param message - Human-readable description of what went wrong\n * @param bundlePath - Absolute path to the `.mcpb` file\n * @param cause - The underlying error\n */\nexport class MpakInvalidBundleError extends MpakError {\n constructor(\n message: string,\n public readonly bundlePath: string,\n public override readonly cause?: Error,\n ) {\n super(message, 'INVALID_BUNDLE');\n this.name = 'MpakInvalidBundleError';\n }\n}\n\nexport class MpakConfigError extends MpakError {\n constructor(\n public readonly packageName: string,\n public readonly missingFields: Array<{\n key: string;\n title: string;\n description?: string;\n sensitive: boolean;\n }>,\n ) {\n const fieldNames = missingFields.map((f) => f.title).join(', ');\n super(`Missing required config for ${packageName}: ${fieldNames}`, 'CONFIG_MISSING');\n this.name = 'MpakConfigError';\n }\n}\n","import { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, statSync } from 'node:fs';\nimport { resolve, join } from 'node:path';\nimport type { z } from 'zod';\nimport { MpakCacheCorruptedError, MpakError } from './errors.js';\n\n/**\n * Maximum allowed uncompressed size for a bundle (500MB).\n */\nexport const MAX_UNCOMPRESSED_SIZE = 500 * 1024 * 1024;\n\n/**\n * TTL for update checks — skip if last check was within this window (1 hour).\n */\nexport const UPDATE_CHECK_TTL_MS = 60 * 60 * 1000;\n\n/**\n * Compare two semver strings for equality, ignoring leading 'v' prefix.\n */\nexport function isSemverEqual(a: string, b: string): boolean {\n return a.replace(/^v/, '') === b.replace(/^v/, '');\n}\n\n/**\n * Check uncompressed size and extract a ZIP file to a directory.\n * Rejects bundles exceeding {@link MAX_UNCOMPRESSED_SIZE} (zip-bomb protection).\n *\n * Requires the `unzip` system command to be available on PATH.\n *\n * @throws If uncompressed size exceeds the limit or extraction fails.\n */\nexport function extractZip(zipPath: string, destDir: string): void {\n // Check uncompressed size before extraction\n try {\n const listOutput = execFileSync('unzip', ['-l', zipPath], {\n stdio: 'pipe',\n encoding: 'utf8',\n });\n const totalMatch = listOutput.match(/^\\s*(\\d+)\\s+\\d+\\s+files?$/m);\n if (totalMatch) {\n const totalSize = parseInt(totalMatch[1] ?? '0', 10);\n if (totalSize > MAX_UNCOMPRESSED_SIZE) {\n throw new MpakCacheCorruptedError(\n `Bundle uncompressed size (${Math.round(totalSize / 1024 / 1024)}MB) exceeds maximum allowed (${MAX_UNCOMPRESSED_SIZE / (1024 * 1024)}MB)`,\n zipPath,\n );\n }\n }\n } catch (error: unknown) {\n if (error instanceof MpakCacheCorruptedError) {\n throw error;\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new MpakCacheCorruptedError(\n `Cannot verify bundle size before extraction: ${message}`,\n zipPath,\n error instanceof Error ? error : undefined,\n );\n }\n\n mkdirSync(destDir, { recursive: true });\n execFileSync('unzip', ['-o', '-q', zipPath, '-d', destDir], {\n stdio: 'pipe',\n });\n}\n\n/**\n * Compute a stable, short hash for a local bundle's absolute path.\n * Used to derive a unique cache directory under `_local/`.\n *\n * @param bundlePath - Path to the `.mcpb` file (resolved to absolute internally).\n * @returns A 12-character hex string.\n */\nexport function hashBundlePath(bundlePath: string): string {\n return createHash('md5').update(resolve(bundlePath)).digest('hex').slice(0, 12);\n}\n\n/**\n * Check whether a local bundle needs re-extraction.\n *\n * Returns `true` (needs extract) when:\n * - The cache directory has no `.mpak-local-meta.json`\n * - The `.mcpb` file's mtime is newer than the recorded extraction time\n * - The metadata file is corrupt or unreadable\n *\n * @param bundlePath - Absolute path to the `.mcpb` file.\n * @param cacheDir - The extracted cache directory for this local bundle.\n */\nexport function localBundleNeedsExtract(bundlePath: string, cacheDir: string): boolean {\n const metaPath = join(cacheDir, '.mpak-local-meta.json');\n if (!existsSync(metaPath)) return true;\n\n try {\n const meta = JSON.parse(readFileSync(metaPath, 'utf8')) as { extractedAt?: string };\n if (!meta.extractedAt) return true;\n const bundleStat = statSync(bundlePath);\n return bundleStat.mtimeMs > new Date(meta.extractedAt).getTime();\n } catch {\n return true;\n }\n}\n\n/**\n * Read a JSON file, parse it, and validate against a Zod schema.\n *\n * Throws generic {@link MpakError} — callers should catch and re-throw\n * with a context-specific error (e.g. `MpakCacheCorruptedError`).\n *\n * @param filePath - Absolute path to the JSON file\n * @param schema - Zod schema to validate the parsed content against\n * @returns The validated data matching the schema's output type\n *\n * @throws {MpakError} If the file does not exist, contains invalid JSON,\n * or fails schema validation.\n */\nexport function readJsonFromFile<T extends z.ZodTypeAny>(filePath: string, schema: T): z.output<T> {\n if (!existsSync(filePath)) {\n throw new MpakError(`File does not exist: ${filePath}`, 'FILE_NOT_FOUND');\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(filePath, 'utf8'));\n } catch {\n throw new MpakError(`File is not valid JSON: ${filePath}`, 'INVALID_JSON');\n }\n\n const result = schema.safeParse(raw);\n if (!result.success) {\n throw new MpakError(\n `File failed validation: ${filePath} — ${result.error.issues[0]?.message ?? 'unknown error'}`,\n 'VALIDATION_FAILED',\n );\n }\n\n return result.data;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { z } from 'zod';\nimport { MpakConfigCorruptedError } from './errors.js';\n\n/**\n * Current config schema version.\n */\nexport const CONFIG_VERSION = '1.0.0';\n\n/**\n * Zod schema for per-package user configuration.\n * Each key-value pair represents a user-supplied config value\n * (e.g. API keys, workspace IDs) referenced via `${user_config.*}` in manifests.\n */\nconst PackageConfigSchema = z.record(z.string(), z.string());\n\n/**\n * Zod schema for the mpak config file (`config.json`).\n *\n * `.strict()` rejects unknown fields — if the file contains keys we don't\n * recognise, it's treated as corrupted rather than silently ignored.\n */\nconst MpakConfigSchema = z\n .object({\n version: z.string(),\n lastUpdated: z.string(),\n registryUrl: z.string().optional(),\n packages: z.record(z.string(), PackageConfigSchema).optional(),\n })\n .strict();\n\n/**\n * Per-package user configuration — a string-to-string map of values\n * that bundles reference via `${user_config.*}` placeholders.\n */\nexport type PackageConfig = z.infer<typeof PackageConfigSchema>;\n\n/**\n * The full shape of the mpak config file.\n *\n * - `version` — schema version (always {@link CONFIG_VERSION})\n * - `lastUpdated` — ISO timestamp, updated on every write\n * - `registryUrl` — optional registry URL override\n * - `packages` — per-package user config values keyed by scoped package name\n */\nexport type MpakConfig = z.infer<typeof MpakConfigSchema>;\n\n/**\n * Manages the mpak user configuration file (`config.json`).\n *\n * Handles:\n * - **Registry URL** — custom registry endpoint with hardcoded default fallback\n * - **Per-package config** — key-value pairs for `${user_config.*}` substitution\n *\n * The config is lazy-loaded on first access and cached in memory.\n * The config directory is created lazily on first write — read-only usage\n * never touches the filesystem.\n * All writes are validated against the schema before flushing to disk\n * with `0o600` permissions (owner read/write only).\n *\n * @example\n * ```ts\n * // Default: ~/.mpak/config.json\n * const config = new MpakConfigManager();\n *\n * // Custom home and registry URL\n * const config = new MpakConfigManager({ mpakHome: '/tmp/test-mpak', registryUrl: 'https://custom.registry.dev' });\n *\n * // Registry URL (config > default)\n * config.getRegistryUrl();\n *\n * // Per-package user config for ${user_config.*} substitution\n * config.setPackageConfigValue('@scope/bundle', 'api_key', 'sk-...');\n * config.getPackageConfig('@scope/bundle'); // { api_key: 'sk-...' }\n * ```\n */\nexport interface MpakConfigManagerOptions {\n mpakHome?: string;\n registryUrl?: string;\n}\n\nexport class MpakConfigManager {\n readonly mpakHome: string;\n private configFile: string;\n private config: MpakConfig | null = null;\n\n constructor(options?: MpakConfigManagerOptions) {\n this.mpakHome = resolve(options?.mpakHome ?? join(homedir(), '.mpak'));\n this.configFile = join(this.mpakHome, 'config.json');\n if (options?.registryUrl !== undefined) {\n this.setRegistryUrl(options.registryUrl);\n }\n }\n\n // ===========================================================================\n // Public methods\n // ===========================================================================\n\n /**\n * Resolve the registry URL with a 2-tier fallback:\n * 1. Saved value in config file\n * 2. Default: `https://registry.mpak.dev`\n *\n * @returns The resolved registry URL\n */\n getRegistryUrl(): string {\n const config = this.loadConfig();\n return config.registryUrl || 'https://registry.mpak.dev';\n }\n\n /**\n * Get all stored user config values for a package.\n *\n * @param packageName - Scoped package name (e.g. `@scope/bundle`)\n * @returns The key-value map, or `undefined` if the package has no stored config\n */\n getPackageConfig(packageName: string): PackageConfig | undefined {\n const config = this.loadConfig();\n return config.packages?.[packageName];\n }\n\n /**\n * Store a user config value for a package. Creates the package entry if needed.\n *\n * @param packageName - Scoped package name (e.g. `@scope/bundle`)\n * @param key - The config key (e.g. `api_key`)\n * @param value - The value to store\n */\n setPackageConfigValue(packageName: string, key: string, value: string): void {\n const config = this.loadConfig();\n if (!config.packages) {\n config.packages = {};\n }\n if (!config.packages[packageName]) {\n config.packages[packageName] = {};\n }\n config.packages[packageName][key] = value;\n this.saveConfig();\n }\n\n /**\n * Remove all stored config for a package.\n *\n * @param packageName - Scoped package name (e.g. `@scope/bundle`)\n * @returns `true` if the package had config that was removed, `false` if it didn't exist\n */\n clearPackageConfig(packageName: string): boolean {\n const config = this.loadConfig();\n if (config.packages?.[packageName]) {\n delete config.packages[packageName];\n this.saveConfig();\n return true;\n }\n return false;\n }\n\n /**\n * Remove a single config value for a package. If this was the last key,\n * the package entry is cleaned up entirely.\n *\n * @param packageName - Scoped package name (e.g. `@scope/bundle`)\n * @param key - The config key to remove\n * @returns `true` if the key existed and was removed, `false` otherwise\n */\n clearPackageConfigValue(packageName: string, key: string): boolean {\n const config = this.loadConfig();\n if (config.packages?.[packageName]?.[key] !== undefined) {\n delete config.packages[packageName][key];\n if (Object.keys(config.packages[packageName]).length === 0) {\n delete config.packages[packageName];\n }\n this.saveConfig();\n return true;\n }\n return false;\n }\n\n /**\n * List all package names that have stored user config.\n *\n * @returns Array of scoped package names (e.g. `['@scope/pkg1', '@scope/pkg2']`)\n */\n getPackageNames(): string[] {\n const config = this.loadConfig();\n return Object.keys(config.packages || {});\n }\n\n // ===========================================================================\n // Private methods\n // ===========================================================================\n\n /**\n * Load the config from disk, or create a fresh one if the file doesn't exist yet.\n * The result is cached — subsequent calls return the in-memory copy without\n * re-reading the file.\n *\n * @returns The validated config object\n * @throws {MpakConfigCorruptedError} If the file exists but contains invalid JSON or fails schema validation\n */\n private loadConfig(): MpakConfig {\n if (this.config) {\n return this.config;\n }\n\n if (!existsSync(this.configFile)) {\n this.config = {\n version: CONFIG_VERSION,\n lastUpdated: new Date().toISOString(),\n };\n return this.config;\n }\n\n this.config = this.readAndValidateConfig();\n return this.config;\n }\n\n /**\n * Read the config file from disk, parse JSON, and validate against the schema.\n *\n * @returns The validated config object\n * @throws {MpakConfigCorruptedError} If the file can't be read, contains invalid JSON,\n * or doesn't match the expected schema\n */\n private readAndValidateConfig(): MpakConfig {\n let configJson: string;\n try {\n configJson = readFileSync(this.configFile, 'utf8');\n } catch (err) {\n throw new MpakConfigCorruptedError(\n `Failed to read config file: ${err instanceof Error ? err.message : String(err)}`,\n this.configFile,\n err instanceof Error ? err : undefined,\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(configJson);\n } catch (err) {\n throw new MpakConfigCorruptedError(\n `Config file contains invalid JSON: ${err instanceof Error ? err.message : String(err)}`,\n this.configFile,\n err instanceof Error ? err : undefined,\n );\n }\n\n const result = MpakConfigSchema.safeParse(parsed);\n if (!result.success) {\n const message = result.error.issues[0]?.message ?? 'Invalid config';\n throw new MpakConfigCorruptedError(message, this.configFile);\n }\n return result.data;\n }\n\n /**\n * Flush the in-memory config to disk. Creates the config directory if needed,\n * validates against the schema, updates `lastUpdated`, and writes\n * with mode `0o600` (owner read/write only — config may contain secrets).\n *\n * @throws {MpakConfigCorruptedError} If the in-memory config fails schema validation\n */\n private saveConfig(): void {\n if (!this.config) {\n throw new MpakConfigCorruptedError(\n `saveConfig called before config was loaded`,\n this.configFile,\n );\n }\n if (!existsSync(this.mpakHome)) {\n mkdirSync(this.mpakHome, { recursive: true, mode: 0o700 });\n }\n this.config.lastUpdated = new Date().toISOString();\n const result = MpakConfigSchema.safeParse(this.config);\n if (!result.success) {\n const message = result.error.issues[0]?.message ?? 'Invalid config';\n throw new MpakConfigCorruptedError(message, this.configFile);\n }\n const configJson = JSON.stringify(result.data, null, 2);\n writeFileSync(this.configFile, configJson, { mode: 0o600 });\n }\n\n /**\n * Persist a custom registry URL to the config file.\n *\n * @param url - The registry URL to save (e.g. `https://registry.example.com`)\n */\n private setRegistryUrl(url: string): void {\n const config = this.loadConfig();\n config.registryUrl = url;\n this.saveConfig();\n }\n}\n","import { MpakError } from './errors.js';\n\n/**\n * Parse a scoped package spec (`@scope/name` or `@scope/name@version`)\n * into its name and optional version components.\n *\n * @throws {MpakError} If the spec is not a valid scoped package name.\n *\n * @example\n * parsePackageSpec('@scope/name') // { name: '@scope/name' }\n * parsePackageSpec('@scope/name@1.0.0') // { name: '@scope/name', version: '1.0.0' }\n */\nexport function parsePackageSpec(spec: string): {\n name: string;\n version?: string;\n} {\n const lastAtIndex = spec.lastIndexOf('@');\n\n let name: string;\n let version: string | undefined;\n\n if (lastAtIndex > 0) {\n name = spec.substring(0, lastAtIndex);\n version = spec.substring(lastAtIndex + 1);\n } else {\n name = spec;\n }\n\n if (!name.startsWith('@') || !name.includes('/')) {\n throw new MpakError(\n `Invalid package spec: \"${spec}\". Expected scoped format: @scope/name`,\n 'INVALID_SPEC',\n );\n }\n\n return version ? { name, version } : { name };\n}\n"],"mappings":"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","names":["existsSync","rmSync","writeFileSync","join","resolve","McpbManifestSchema","existsSync","join","createHash","createHash","join","existsSync","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","join","resolve","resolve","join","homedir","existsSync","readFileSync","mkdirSync","writeFileSync","join","resolve","existsSync","rmSync","writeFileSync","McpbManifestSchema"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nimblebrain/mpak-sdk",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "TypeScript SDK for mpak registry - MCPB bundles and Agent Skills",
|
|
5
5
|
"author": "NimbleBrain Inc <engineering@mpak.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -50,11 +50,12 @@
|
|
|
50
50
|
"node": ">=22"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"
|
|
54
|
-
"@nimblebrain/mpak-schemas": "0.
|
|
53
|
+
"zod": "^4.3.6",
|
|
54
|
+
"@nimblebrain/mpak-schemas": "0.2.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/node": "^22.0.0",
|
|
58
|
+
"jszip": "^3.10.1",
|
|
58
59
|
"tsup": "^8.4.0",
|
|
59
60
|
"typescript": "^5.7.0",
|
|
60
61
|
"vitest": "^3.0.0"
|