UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

162 lines (161 loc) • 7.27 kB
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs"; import { w as parseStrictPositiveInteger } from "./number-coercion-CuVhdCBs.mjs"; import { n as sha256Hex } from "./node-crypto-BG4u3UnX.mjs"; import "./crypto-digest-y6oZN-_F.mjs"; import { M as normalizeClawHubSha256Hex } from "./official-external-plugin-catalog-Dcv926GC.mjs"; import { b as withClawHubResponse, l as readClawHubBytes, n as createClawHubError, v as resolveClawHubBaseUrl } from "./clawhub-client-D-mEumEV.mjs"; import { n as createTempDownloadTarget } from "./temp-download-DLutZExN.mjs"; import fs from "node:fs/promises"; import { createHash } from "node:crypto"; //#region src/infra/clawhub-artifacts.ts const DEFAULT_GITHUB_CODELOAD_URL = "https://codeload.github.com"; function normalizeGitHubCodeloadBaseUrl() { return (normalizeOptionalString(process.env.CLAWHUB_GITHUB_CODELOAD_BASE_URL) || DEFAULT_GITHUB_CODELOAD_URL).replace(/\/+$/, "") || DEFAULT_GITHUB_CODELOAD_URL; } function buildGitHubZipUrl(repo, commit) { const url = new URL(`${normalizeGitHubCodeloadBaseUrl()}/`); url.pathname = `${url.pathname.replace(/\/+$/, "")}/${repo.split("/").map((segment) => encodeURIComponent(segment)).join("/")}/zip/${encodeURIComponent(commit)}`; return url.toString(); } function safePackageTarballName(name, version) { return `${name.replace(/^@/, "").replace(/[\\/]+/g, "-").replace(/[^A-Za-z0-9._-]/g, "-") || "package"}-${version}.tgz`; } async function stageClawHubArchive(params) { const sha256Digest = params.sha256Hex ?? sha256Hex(params.bytes); const target = await createTempDownloadTarget(params); try { await fs.writeFile(target.path, params.bytes); return { archivePath: target.path, integrity: `sha256-${Buffer.from(sha256Digest, "hex").toString("base64")}`, sha256Hex: sha256Digest, artifact: "archive", ...params.result, cleanup: target.cleanup }; } catch (error) { await target.cleanup().catch(() => void 0); throw error; } } async function fetchClawHubArchive(params, resourceLabel) { return await withClawHubResponse(params, async ({ response, url, hasToken, releaseDeadline }) => { if (!response.ok) throw await createClawHubError(response, url, hasToken, params.timeoutMs); releaseDeadline(); return { bytes: await readClawHubBytes({ response, timeoutMs: params.timeoutMs, resourceLabel }), headers: response.headers }; }); } async function downloadClawHubPackageArchive(params) { if (params.artifact === "clawpack") { if (!params.version) throw new Error("ClawPack package downloads require an explicit version."); const { bytes, headers } = await fetchClawHubArchive({ baseUrl: params.baseUrl, path: `/api/v1/packages/${encodeURIComponent(params.name)}/versions/${encodeURIComponent(params.version)}/artifact/download`, token: params.token, timeoutMs: params.timeoutMs, fetchImpl: params.fetchImpl }, `ClawPack download for ${params.name}@${params.version}`); const sha256Digest = sha256Hex(bytes); const npmIntegrity = `sha512-${createHash("sha512").update(bytes).digest("base64")}`; const npmShasum = createHash("sha1").update(bytes).digest("hex"); const headerSha256 = normalizeClawHubSha256Hex(headers.get("X-ClawHub-Artifact-Sha256") ?? headers.get("X-ClawHub-ClawPack-Sha256") ?? ""); if (!headerSha256) throw new Error(`ClawHub ClawPack download for "${params.name}@${params.version}" is missing X-ClawHub-Artifact-Sha256.`); if (headerSha256 !== sha256Digest) throw new Error(`ClawHub ClawPack download for "${params.name}@${params.version}" declared sha256 ${headerSha256}, got ${sha256Digest}.`); const headerNpmIntegrity = normalizeOptionalString(headers.get("X-ClawHub-Npm-Integrity")); if (headerNpmIntegrity && headerNpmIntegrity !== npmIntegrity) throw new Error(`ClawHub ClawPack download for "${params.name}@${params.version}" declared npm integrity ${headerNpmIntegrity}, got ${npmIntegrity}.`); const headerNpmShasum = normalizeOptionalString(headers.get("X-ClawHub-Npm-Shasum")); if (headerNpmShasum && headerNpmShasum !== npmShasum) throw new Error(`ClawHub ClawPack download for "${params.name}@${params.version}" declared npm shasum ${headerNpmShasum}, got ${npmShasum}.`); const npmTarballName = normalizeOptionalString(headers.get("X-ClawHub-Npm-Tarball-Name")) ?? safePackageTarballName(params.name, params.version); const rawSpecVersion = headers.get("X-ClawHub-ClawPack-Spec-Version"); const specVersion = parseStrictPositiveInteger(rawSpecVersion); return stageClawHubArchive({ prefix: "openclaw-clawhub-clawpack", fileName: npmTarballName, bytes, sha256Hex: sha256Digest, result: { artifact: "clawpack", clawpackHeaderSha256: headerSha256, ...specVersion !== void 0 ? { clawpackHeaderSpecVersion: specVersion } : {}, npmIntegrity, npmShasum, npmTarballName } }); } const search = params.version ? { version: params.version } : params.tag ? { tag: params.tag } : void 0; const { bytes } = await fetchClawHubArchive({ baseUrl: params.baseUrl, path: `/api/v1/packages/${encodeURIComponent(params.name)}/download`, search, token: params.token, timeoutMs: params.timeoutMs, fetchImpl: params.fetchImpl }, `package archive download for ${params.name}`); return stageClawHubArchive({ prefix: "openclaw-clawhub-package", fileName: `${params.name}.zip`, bytes }); } async function downloadClawHubSkillArchive(params) { const { bytes } = await fetchClawHubArchive({ baseUrl: params.baseUrl, path: "/api/v1/download", token: params.token, timeoutMs: params.timeoutMs, fetchImpl: params.fetchImpl, search: { slug: params.slug, ownerHandle: params.ownerHandle, version: params.version, tag: params.version ? void 0 : params.tag } }, `skill archive download for ${params.slug}`); return stageClawHubArchive({ prefix: "openclaw-clawhub-skill", fileName: `${params.slug}.zip`, bytes }); } async function downloadClawHubSkillArchiveUrl(params) { const providedToken = normalizeOptionalString(params.token); const requestUrl = new URL(params.url, `${resolveClawHubBaseUrl(params.baseUrl)}/`); const registryOrigin = new URL(`${resolveClawHubBaseUrl(params.baseUrl)}/`).origin; const skipAuth = providedToken == null && requestUrl.origin !== registryOrigin; const { bytes } = await fetchClawHubArchive({ baseUrl: params.baseUrl, url: params.url, token: providedToken, timeoutMs: params.timeoutMs, fetchImpl: params.fetchImpl, skipAuth }, `skill archive download at ${requestUrl.pathname}`); return stageClawHubArchive({ prefix: "openclaw-clawhub-skill", fileName: "skill.zip", bytes }); } async function downloadClawHubGitHubSkillArchive(params) { const { bytes } = await fetchClawHubArchive({ url: buildGitHubZipUrl(params.repo, params.commit), skipAuth: true, timeoutMs: params.timeoutMs, fetchImpl: params.fetchImpl }, `GitHub source archive for ${params.repo}@${params.commit}`); return stageClawHubArchive({ prefix: "openclaw-clawhub-github-skill", fileName: `${params.commit}.zip`, bytes }); } //#endregion export { downloadClawHubSkillArchiveUrl as i, downloadClawHubPackageArchive as n, downloadClawHubSkillArchive as r, downloadClawHubGitHubSkillArchive as t };