mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:40:44 +00:00
fix(plugins): align clawhub clawpack downloads
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
const crypto = require("node:crypto");
|
||||
const fs = require("node:fs");
|
||||
const http = require("node:http");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
const { createRequire } = require("node:module");
|
||||
|
||||
@@ -8,18 +9,82 @@ const profile = process.argv[2];
|
||||
const portFile = process.argv[3];
|
||||
const requireFromApp = createRequire(path.join(process.cwd(), "package.json"));
|
||||
const JSZip = requireFromApp("jszip");
|
||||
const tar = requireFromApp("tar");
|
||||
const packageName = "@openclaw/kitchen-sink";
|
||||
const pluginId = "openclaw-kitchen-sink-fixture";
|
||||
|
||||
const buildClawPackSummary = ({ sha256hash, manifestSha256, size }) => ({
|
||||
available: true,
|
||||
specVersion: 1,
|
||||
format: "clawpack.zip",
|
||||
sha256: sha256hash,
|
||||
size,
|
||||
manifestSha256,
|
||||
const buildArtifactSummary = ({
|
||||
clawpackSha256,
|
||||
clawpackSize,
|
||||
npmIntegrity,
|
||||
npmShasum,
|
||||
npmTarballName,
|
||||
}) => ({
|
||||
kind: "npm-pack",
|
||||
format: "tgz",
|
||||
sha256: clawpackSha256,
|
||||
size: clawpackSize,
|
||||
npmIntegrity,
|
||||
npmShasum,
|
||||
npmTarballName,
|
||||
});
|
||||
|
||||
const buildClawPackSummary = ({
|
||||
clawpackSha256,
|
||||
clawpackSize,
|
||||
npmIntegrity,
|
||||
npmShasum,
|
||||
npmTarballName,
|
||||
}) => ({
|
||||
available: true,
|
||||
format: "tgz",
|
||||
sha256: clawpackSha256,
|
||||
size: clawpackSize,
|
||||
npmIntegrity,
|
||||
npmShasum,
|
||||
npmTarballName,
|
||||
});
|
||||
|
||||
async function buildNpmPackArtifact(fixture) {
|
||||
const packRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), "openclaw-clawhub-fixture-"));
|
||||
try {
|
||||
const packageDir = path.join(packRoot, "package");
|
||||
await fs.promises.mkdir(packageDir, { recursive: true });
|
||||
await fs.promises.writeFile(
|
||||
path.join(packageDir, "package.json"),
|
||||
`${JSON.stringify(fixture.packageJson, null, 2)}\n`,
|
||||
);
|
||||
await fs.promises.writeFile(path.join(packageDir, "index.js"), fixture.indexJs);
|
||||
await fs.promises.writeFile(
|
||||
path.join(packageDir, "openclaw.plugin.json"),
|
||||
`${JSON.stringify(fixture.manifest, null, 2)}\n`,
|
||||
);
|
||||
const npmTarballName = `${packageName.replace(/^@/, "").replace("/", "-")}-${fixture.version}.tgz`;
|
||||
const archivePath = path.join(packRoot, npmTarballName);
|
||||
await tar.c(
|
||||
{
|
||||
cwd: packRoot,
|
||||
file: archivePath,
|
||||
gzip: true,
|
||||
portable: true,
|
||||
noMtime: true,
|
||||
},
|
||||
["package"],
|
||||
);
|
||||
const archive = await fs.promises.readFile(archivePath);
|
||||
return {
|
||||
archive,
|
||||
clawpackSha256: crypto.createHash("sha256").update(archive).digest("hex"),
|
||||
clawpackSize: archive.length,
|
||||
npmIntegrity: `sha512-${crypto.createHash("sha512").update(archive).digest("base64")}`,
|
||||
npmShasum: crypto.createHash("sha1").update(archive).digest("hex"),
|
||||
npmTarballName,
|
||||
};
|
||||
} finally {
|
||||
await fs.promises.rm(packRoot, { recursive: true, force: true }).catch(() => undefined);
|
||||
}
|
||||
}
|
||||
|
||||
const profiles = {
|
||||
"kitchen-sink-plugin": {
|
||||
version: "0.1.3",
|
||||
@@ -98,6 +163,7 @@ export default definePluginEntry({
|
||||
},
|
||||
packageDetail(artifact) {
|
||||
const clawpack = buildClawPackSummary(artifact);
|
||||
const packageArtifact = buildArtifactSummary(artifact);
|
||||
const packageDetail = {
|
||||
package: {
|
||||
name: packageName,
|
||||
@@ -131,6 +197,7 @@ export default definePluginEntry({
|
||||
hasProvenance: false,
|
||||
scanStatus: "passed",
|
||||
},
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
};
|
||||
@@ -151,6 +218,7 @@ export default definePluginEntry({
|
||||
compatibility: packageDetail.package.compatibility,
|
||||
capabilities: packageDetail.package.capabilities,
|
||||
verification: packageDetail.package.verification,
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
},
|
||||
@@ -209,6 +277,7 @@ export default definePluginEntry({
|
||||
minGatewayVersion: "2026.4.26",
|
||||
};
|
||||
const clawpack = buildClawPackSummary(artifact);
|
||||
const packageArtifact = buildArtifactSummary(artifact);
|
||||
return {
|
||||
packageDetail: {
|
||||
package: {
|
||||
@@ -222,6 +291,7 @@ export default definePluginEntry({
|
||||
createdAt: 0,
|
||||
updatedAt: 0,
|
||||
compatibility,
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
},
|
||||
@@ -232,6 +302,7 @@ export default definePluginEntry({
|
||||
changelog: "Kitchen-sink fixture package for Docker plugin E2E.",
|
||||
sha256hash: artifact.sha256hash,
|
||||
compatibility,
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
},
|
||||
@@ -257,11 +328,10 @@ async function main() {
|
||||
|
||||
const archive = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
||||
const sha256hash = crypto.createHash("sha256").update(archive).digest("hex");
|
||||
const manifestSha256 = crypto.createHash("sha256").update(manifestJson).digest("hex");
|
||||
const clawpack = await buildNpmPackArtifact(fixture);
|
||||
const { packageDetail, versionDetail, betaStatus } = fixture.packageDetail({
|
||||
sha256hash,
|
||||
manifestSha256,
|
||||
size: archive.length,
|
||||
...clawpack,
|
||||
});
|
||||
|
||||
const json = (response, value, status = 200) => {
|
||||
@@ -304,15 +374,17 @@ async function main() {
|
||||
}
|
||||
if (
|
||||
url.pathname ===
|
||||
`/api/v1/packages/${encodeURIComponent(packageName)}/versions/${fixture.version}/clawpack`
|
||||
`/api/v1/packages/${encodeURIComponent(packageName)}/versions/${fixture.version}/artifact/download`
|
||||
) {
|
||||
response.writeHead(200, {
|
||||
"content-type": "application/zip",
|
||||
"content-length": String(archive.length),
|
||||
"X-ClawHub-ClawPack-Sha256": sha256hash,
|
||||
"X-ClawHub-ClawPack-Spec-Version": "1",
|
||||
"content-type": "application/octet-stream",
|
||||
"content-length": String(clawpack.archive.length),
|
||||
"X-ClawHub-Artifact-Type": "npm-pack-tarball",
|
||||
"X-ClawHub-Artifact-Sha256": clawpack.clawpackSha256,
|
||||
"X-ClawHub-Npm-Integrity": clawpack.npmIntegrity,
|
||||
"X-ClawHub-Npm-Shasum": clawpack.npmShasum,
|
||||
});
|
||||
response.end(archive);
|
||||
response.end(clawpack.archive);
|
||||
return;
|
||||
}
|
||||
response.writeHead(404, { "content-type": "text/plain" });
|
||||
|
||||
@@ -389,12 +389,7 @@ function assertInstalled() {
|
||||
if (!record.version || !record.integrity || !record.resolvedAt) {
|
||||
throw new Error(`missing ClawHub resolution metadata: ${JSON.stringify(record)}`);
|
||||
}
|
||||
if (
|
||||
!record.clawpackSha256 ||
|
||||
record.clawpackSpecVersion !== 1 ||
|
||||
!record.clawpackManifestSha256 ||
|
||||
typeof record.clawpackSize !== "number"
|
||||
) {
|
||||
if (!record.clawpackSha256 || typeof record.clawpackSize !== "number") {
|
||||
throw new Error(`missing kitchen-sink ClawPack metadata: ${JSON.stringify(record)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,12 +534,7 @@ function assertClawHubInstalled() {
|
||||
if (typeof record.installPath !== "string" || record.installPath.length === 0) {
|
||||
throw new Error(`missing ClawHub install path for ${pluginId}`);
|
||||
}
|
||||
if (
|
||||
!record.clawpackSha256 ||
|
||||
record.clawpackSpecVersion !== 1 ||
|
||||
!record.clawpackManifestSha256 ||
|
||||
typeof record.clawpackSize !== "number"
|
||||
) {
|
||||
if (!record.clawpackSha256 || typeof record.clawpackSize !== "number") {
|
||||
throw new Error(`missing ClawHub ClawPack metadata for ${pluginId}: ${JSON.stringify(record)}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user