Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
497
scripts/e2e/lib/clawhub-fixture-server.cjs
Normal file
497
scripts/e2e/lib/clawhub-fixture-server.cjs
Normal file
@@ -0,0 +1,497 @@
|
||||
// CommonJS fixture server for ClawHub package/install E2E scenarios.
|
||||
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");
|
||||
|
||||
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 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.2.5",
|
||||
packageJson: {
|
||||
name: packageName,
|
||||
version: "0.2.5",
|
||||
type: "module",
|
||||
dependencies: {
|
||||
"is-number": "7.0.0",
|
||||
},
|
||||
peerDependencies: {
|
||||
openclaw: ">=2026.4.11",
|
||||
},
|
||||
peerDependenciesMeta: {
|
||||
openclaw: {
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
openclaw: { extensions: ["./index.js"] },
|
||||
},
|
||||
indexJs: `import isNumber from "is-number";
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
const dependencyUrl = import.meta.resolve("is-number");
|
||||
const expectedDependencyBaseUrl = new URL("./node_modules/is-number/", import.meta.url).href;
|
||||
if (!dependencyUrl.startsWith(expectedDependencyBaseUrl)) {
|
||||
throw new Error(\`kitchen-sink dependency resolved outside plugin root: \${dependencyUrl}\`);
|
||||
}
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "${pluginId}",
|
||||
name: "OpenClaw Kitchen Sink",
|
||||
register(api) {
|
||||
if (!isNumber(42)) {
|
||||
throw new Error("kitchen-sink dependency sentinel did not load");
|
||||
}
|
||||
api.registerProvider({
|
||||
id: "kitchen-sink-provider",
|
||||
label: "Kitchen Sink Provider",
|
||||
docsPath: "/providers/kitchen-sink",
|
||||
auth: [],
|
||||
});
|
||||
api.registerContextEngine("${pluginId}", () => ({
|
||||
info: {
|
||||
id: "${pluginId}",
|
||||
name: "Kitchen Sink Context Engine",
|
||||
},
|
||||
async ingest() {
|
||||
return { ingested: false };
|
||||
},
|
||||
async assemble(params) {
|
||||
return {
|
||||
messages: params.messages,
|
||||
estimatedTokens: 0,
|
||||
};
|
||||
},
|
||||
async compact() {
|
||||
return {
|
||||
ok: true,
|
||||
compacted: false,
|
||||
reason: "kitchen-sink fixture does not compact",
|
||||
};
|
||||
},
|
||||
}));
|
||||
api.registerChannel({
|
||||
plugin: {
|
||||
id: "kitchen-sink-channel",
|
||||
meta: {
|
||||
id: "kitchen-sink-channel",
|
||||
label: "Kitchen Sink Channel",
|
||||
selectionLabel: "Kitchen Sink",
|
||||
docsPath: "/channels/kitchen-sink",
|
||||
blurb: "Kitchen sink ClawHub fixture channel",
|
||||
},
|
||||
capabilities: { chatTypes: ["direct"] },
|
||||
config: {
|
||||
listAccountIds: () => ["default"],
|
||||
resolveAccount: () => ({ accountId: "default" }),
|
||||
},
|
||||
outbound: { deliveryMode: "direct" },
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
manifest: {
|
||||
id: pluginId,
|
||||
name: "OpenClaw Kitchen Sink",
|
||||
kind: "context-engine",
|
||||
channels: ["kitchen-sink-channel"],
|
||||
channelConfigs: {
|
||||
"kitchen-sink-channel": {
|
||||
schema: {
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
enabled: { type: "boolean", default: true },
|
||||
token: { type: "string" },
|
||||
},
|
||||
},
|
||||
uiHints: {
|
||||
token: {
|
||||
sensitive: true,
|
||||
},
|
||||
},
|
||||
label: "Kitchen Sink",
|
||||
description:
|
||||
"Credential-free channel fixture for deterministic Kitchen Sink install tests.",
|
||||
commands: {
|
||||
nativeCommandsAutoEnabled: true,
|
||||
nativeSkillsAutoEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
providers: ["kitchen-sink-provider"],
|
||||
contracts: {
|
||||
tools: ["kitchen-sink-tool"],
|
||||
},
|
||||
configSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
packageDetail(artifact) {
|
||||
const clawpack = buildClawPackSummary(artifact);
|
||||
const packageArtifact = buildArtifactSummary(artifact);
|
||||
const packageDetail = {
|
||||
package: {
|
||||
name: packageName,
|
||||
displayName: "OpenClaw Kitchen Sink",
|
||||
family: "code-plugin",
|
||||
runtimeId: pluginId,
|
||||
channel: "official",
|
||||
isOfficial: true,
|
||||
summary: "Kitchen sink plugin fixture for prerelease CI.",
|
||||
ownerHandle: "openclaw",
|
||||
createdAt: 0,
|
||||
updatedAt: 0,
|
||||
latestVersion: this.version,
|
||||
tags: { latest: this.version },
|
||||
capabilityTags: ["test-fixture"],
|
||||
executesCode: true,
|
||||
compatibility: {
|
||||
pluginApiRange: ">=2026.4.11",
|
||||
minGatewayVersion: "2026.4.11",
|
||||
},
|
||||
capabilities: {
|
||||
executesCode: true,
|
||||
runtimeId: pluginId,
|
||||
capabilityTags: ["test-fixture"],
|
||||
channels: ["kitchen-sink-channel"],
|
||||
providers: ["kitchen-sink-provider"],
|
||||
},
|
||||
verification: {
|
||||
tier: "source-linked",
|
||||
sourceRepo: "https://github.com/openclaw/kitchen-sink",
|
||||
hasProvenance: false,
|
||||
scanStatus: "passed",
|
||||
},
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
};
|
||||
return {
|
||||
packageDetail,
|
||||
versionDetail: {
|
||||
package: {
|
||||
name: packageName,
|
||||
displayName: "OpenClaw Kitchen Sink",
|
||||
family: "code-plugin",
|
||||
},
|
||||
version: {
|
||||
version: this.version,
|
||||
createdAt: 0,
|
||||
changelog: "Fixture package for kitchen-sink plugin prerelease CI.",
|
||||
distTags: ["latest"],
|
||||
sha256hash: artifact.sha256hash,
|
||||
compatibility: packageDetail.package.compatibility,
|
||||
capabilities: packageDetail.package.capabilities,
|
||||
verification: packageDetail.package.verification,
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
},
|
||||
betaStatus: 404,
|
||||
};
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
version: "0.1.0",
|
||||
packageJson: {
|
||||
name: packageName,
|
||||
version: "0.1.0",
|
||||
dependencies: {
|
||||
"is-number": "7.0.0",
|
||||
},
|
||||
peerDependencies: {
|
||||
openclaw: ">=2026.4.11",
|
||||
},
|
||||
peerDependenciesMeta: {
|
||||
openclaw: {
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
openclaw: { extensions: ["./index.js"] },
|
||||
},
|
||||
indexJs: `module.exports = {
|
||||
id: "${pluginId}",
|
||||
name: "OpenClaw Kitchen Sink",
|
||||
description: "Docker E2E kitchen-sink plugin fixture",
|
||||
register(api) {
|
||||
api.on("before_agent_start", async (event, context) => ({
|
||||
kitchenSink: true,
|
||||
observedEventKeys: Object.keys(event || {}),
|
||||
observedContextKeys: Object.keys(context || {}),
|
||||
}));
|
||||
api.registerTool(() => null, { name: "kitchen_sink_tool" });
|
||||
api.registerGatewayMethod("kitchen-sink.ping", async () => ({ ok: true }));
|
||||
api.registerCli(() => {}, { commands: ["kitchen-sink"] });
|
||||
api.registerService({ id: "kitchen-sink-service", start: () => {} });
|
||||
},
|
||||
};
|
||||
`,
|
||||
manifest: {
|
||||
id: pluginId,
|
||||
contracts: {
|
||||
tools: ["kitchen-sink-tool", "kitchen_sink_tool"],
|
||||
},
|
||||
configSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
packageDetail(artifact) {
|
||||
const compatibility = {
|
||||
pluginApiRange: ">=2026.4.26",
|
||||
minGatewayVersion: "2026.4.26",
|
||||
};
|
||||
const clawpack = buildClawPackSummary(artifact);
|
||||
const packageArtifact = buildArtifactSummary(artifact);
|
||||
return {
|
||||
packageDetail: {
|
||||
package: {
|
||||
name: packageName,
|
||||
displayName: "OpenClaw Kitchen Sink",
|
||||
family: "code-plugin",
|
||||
channel: "official",
|
||||
isOfficial: true,
|
||||
runtimeId: pluginId,
|
||||
latestVersion: this.version,
|
||||
createdAt: 0,
|
||||
updatedAt: 0,
|
||||
compatibility,
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
},
|
||||
versionDetail: {
|
||||
version: {
|
||||
version: this.version,
|
||||
createdAt: 0,
|
||||
changelog: "Kitchen-sink fixture package for Docker plugin E2E.",
|
||||
sha256hash: artifact.sha256hash,
|
||||
compatibility,
|
||||
artifact: packageArtifact,
|
||||
clawpack,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const fixture = profiles[profile];
|
||||
if (!fixture || !portFile) {
|
||||
console.error("usage: clawhub-fixture-server.cjs <kitchen-sink-plugin|plugins> <port-file>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const zip = new JSZip();
|
||||
zip.file("package/package.json", `${JSON.stringify(fixture.packageJson, null, 2)}\n`, {
|
||||
date: new Date(0),
|
||||
});
|
||||
zip.file("package/index.js", fixture.indexJs, { date: new Date(0) });
|
||||
const manifestJson = `${JSON.stringify(fixture.manifest, null, 2)}\n`;
|
||||
zip.file("package/openclaw.plugin.json", manifestJson, { date: new Date(0) });
|
||||
|
||||
const archive = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
||||
const sha256hash = crypto.createHash("sha256").update(archive).digest("hex");
|
||||
const clawpack = await buildNpmPackArtifact(fixture);
|
||||
const { packageDetail, versionDetail, betaStatus } = fixture.packageDetail({
|
||||
sha256hash,
|
||||
...clawpack,
|
||||
});
|
||||
|
||||
const json = (response, value, status = 200) => {
|
||||
response.writeHead(status, { "content-type": "application/json" });
|
||||
response.end(`${JSON.stringify(value)}\n`);
|
||||
};
|
||||
const artifactResolverDetail = {
|
||||
package: versionDetail.package ?? {
|
||||
name: packageName,
|
||||
displayName: packageDetail.package?.displayName ?? "OpenClaw Kitchen Sink",
|
||||
family: packageDetail.package?.family ?? "code-plugin",
|
||||
},
|
||||
version: versionDetail.version,
|
||||
artifact: {
|
||||
source: "clawhub",
|
||||
artifactKind: "npm-pack",
|
||||
packageName,
|
||||
version: fixture.version,
|
||||
artifactSha256: clawpack.clawpackSha256,
|
||||
npmIntegrity: clawpack.npmIntegrity,
|
||||
npmShasum: clawpack.npmShasum,
|
||||
},
|
||||
};
|
||||
const securityDetail = {
|
||||
package: artifactResolverDetail.package,
|
||||
release: {
|
||||
version: fixture.version,
|
||||
},
|
||||
trust: {
|
||||
scanStatus: "clean",
|
||||
moderationState: null,
|
||||
blockedFromDownload: false,
|
||||
reasons: [],
|
||||
pending: false,
|
||||
stale: false,
|
||||
},
|
||||
};
|
||||
|
||||
const server = http.createServer((request, response) => {
|
||||
const url = new URL(request.url, "http://127.0.0.1");
|
||||
if (request.method !== "GET") {
|
||||
response.writeHead(405);
|
||||
response.end("method not allowed");
|
||||
return;
|
||||
}
|
||||
if (url.pathname === `/api/v1/packages/${encodeURIComponent(packageName)}`) {
|
||||
json(response, packageDetail);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
url.pathname ===
|
||||
`/api/v1/packages/${encodeURIComponent(packageName)}/versions/${fixture.version}`
|
||||
) {
|
||||
json(response, versionDetail);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
url.pathname ===
|
||||
`/api/v1/packages/${encodeURIComponent(packageName)}/versions/${fixture.version}/artifact`
|
||||
) {
|
||||
json(response, artifactResolverDetail);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
url.pathname ===
|
||||
`/api/v1/packages/${encodeURIComponent(packageName)}/versions/${fixture.version}/security`
|
||||
) {
|
||||
json(response, securityDetail);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
betaStatus !== undefined &&
|
||||
url.pathname === `/api/v1/packages/${encodeURIComponent(packageName)}/versions/beta`
|
||||
) {
|
||||
json(response, { error: "version not found" }, betaStatus ?? 404);
|
||||
return;
|
||||
}
|
||||
if (url.pathname === `/api/v1/packages/${encodeURIComponent(packageName)}/download`) {
|
||||
response.writeHead(200, {
|
||||
"content-type": "application/zip",
|
||||
"content-length": String(archive.length),
|
||||
});
|
||||
response.end(archive);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
url.pathname ===
|
||||
`/api/v1/packages/${encodeURIComponent(packageName)}/versions/${fixture.version}/artifact/download`
|
||||
) {
|
||||
response.writeHead(200, {
|
||||
"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(clawpack.archive);
|
||||
return;
|
||||
}
|
||||
response.writeHead(404, { "content-type": "text/plain" });
|
||||
response.end(`not found: ${url.pathname}`);
|
||||
});
|
||||
|
||||
server.listen(0, "127.0.0.1", () => {
|
||||
fs.writeFileSync(portFile, String(server.address().port));
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(
|
||||
/** @param {unknown} error */ (error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user