mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 13:04:47 +00:00
193 lines
6.6 KiB
JavaScript
193 lines
6.6 KiB
JavaScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const command = process.argv[2];
|
|
|
|
function assert(condition, message) {
|
|
if (!condition) {
|
|
throw new Error(message);
|
|
}
|
|
}
|
|
|
|
function readJson(file) {
|
|
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
}
|
|
|
|
function configPath() {
|
|
return (
|
|
process.env.OPENCLAW_CONFIG_PATH ??
|
|
path.join(process.env.HOME ?? "", ".openclaw", "openclaw.json")
|
|
);
|
|
}
|
|
|
|
function writeConfig(cfg) {
|
|
fs.writeFileSync(configPath(), `${JSON.stringify(cfg, null, 2)}\n`);
|
|
}
|
|
|
|
function authProfilesPath() {
|
|
return path.join(
|
|
process.env.HOME ?? "",
|
|
".openclaw",
|
|
"agents",
|
|
"main",
|
|
"agent",
|
|
"auth-profiles.json",
|
|
);
|
|
}
|
|
|
|
function readStateText() {
|
|
const paths = [configPath(), authProfilesPath()].filter((file) => fs.existsSync(file));
|
|
return paths.map((file) => fs.readFileSync(file, "utf8")).join("\n");
|
|
}
|
|
|
|
function configureMockOpenAi() {
|
|
const mockPort = Number(process.argv[3]);
|
|
const cfg = readJson(configPath());
|
|
const cost = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
cfg.models = {
|
|
...cfg.models,
|
|
mode: "merge",
|
|
providers: {
|
|
...cfg.models?.providers,
|
|
openai: {
|
|
...cfg.models?.providers?.openai,
|
|
baseUrl: `http://127.0.0.1:${mockPort}/v1`,
|
|
apiKey: { source: "env", provider: "default", id: "OPENAI_API_KEY" },
|
|
api: "openai-responses",
|
|
request: { ...cfg.models?.providers?.openai?.request, allowPrivateNetwork: true },
|
|
models: [
|
|
{
|
|
id: "gpt-5.5",
|
|
name: "gpt-5.5",
|
|
api: "openai-responses",
|
|
reasoning: false,
|
|
input: ["text", "image"],
|
|
cost,
|
|
contextWindow: 128000,
|
|
contextTokens: 96000,
|
|
maxTokens: 4096,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
};
|
|
cfg.agents = {
|
|
...cfg.agents,
|
|
defaults: {
|
|
...cfg.agents?.defaults,
|
|
model: { primary: "openai/gpt-5.5" },
|
|
imageModel: { primary: "openai/gpt-5.5", timeoutMs: 30_000 },
|
|
imageGenerationModel: { primary: "openai/gpt-image-1", timeoutMs: 30_000 },
|
|
models: {
|
|
...cfg.agents?.defaults?.models,
|
|
"openai/gpt-5.5": { params: { transport: "sse", openaiWsWarmup: false } },
|
|
},
|
|
},
|
|
};
|
|
cfg.plugins = {
|
|
...cfg.plugins,
|
|
enabled: true,
|
|
};
|
|
writeConfig(cfg);
|
|
}
|
|
|
|
function assertOpenAiEnvRef() {
|
|
const rawKey = process.argv[3];
|
|
const state = readStateText();
|
|
assert(state.includes("OPENAI_API_KEY"), "OpenAI env ref was not persisted");
|
|
assert(!state.includes(rawKey), "raw OpenAI key was persisted");
|
|
assert(fs.existsSync(configPath()), "openclaw.json missing");
|
|
}
|
|
|
|
function assertAgentTurn() {
|
|
const marker = process.argv[3];
|
|
const outputPath = process.argv[4];
|
|
const requestLogPath = process.argv[5];
|
|
const output = fs.readFileSync(outputPath, "utf8");
|
|
assert(output.includes(marker), `agent output did not contain ${marker}. Output: ${output}`);
|
|
const requestLog = fs.existsSync(requestLogPath) ? fs.readFileSync(requestLogPath, "utf8") : "";
|
|
assert(/\/v1\/(responses|chat\/completions)/u.test(requestLog), "mock OpenAI was not used");
|
|
}
|
|
|
|
function assertFileContains() {
|
|
const file = process.argv[3];
|
|
const needle = process.argv[4];
|
|
const raw = fs.readFileSync(file, "utf8");
|
|
assert(raw.includes(needle), `${file} did not contain ${needle}. Output: ${raw}`);
|
|
}
|
|
|
|
function assertImageDescribe() {
|
|
const outputPath = process.argv[3];
|
|
const requestLogPath = process.argv[4];
|
|
const payload = readJson(outputPath);
|
|
assert(payload.ok === true, `image describe failed: ${JSON.stringify(payload)}`);
|
|
assert(payload.capability === "image.describe", "wrong image describe capability");
|
|
const output = payload.outputs?.[0];
|
|
assert(output?.text?.includes("OPENCLAW_E2E_OK"), "image description marker missing");
|
|
assert(output.provider === "openai", `unexpected image provider: ${output?.provider}`);
|
|
const requestLog = fs.existsSync(requestLogPath) ? fs.readFileSync(requestLogPath, "utf8") : "";
|
|
assert(requestLog.includes("/v1/responses"), "image describe did not hit Responses API");
|
|
}
|
|
|
|
function assertImageGenerate() {
|
|
const outputPath = process.argv[3];
|
|
const requestLogPath = process.argv[4];
|
|
const payload = readJson(outputPath);
|
|
assert(payload.ok === true, `image generation failed: ${JSON.stringify(payload)}`);
|
|
assert(payload.capability === "image.generate", "wrong image generation capability");
|
|
const output = payload.outputs?.[0];
|
|
assert(output?.path && fs.existsSync(output.path), `generated image missing: ${output?.path}`);
|
|
assert(output.mimeType === "image/png", `unexpected generated mime type: ${output.mimeType}`);
|
|
assert(payload.provider === "openai", `unexpected generation provider: ${payload.provider}`);
|
|
const requestLog = fs.existsSync(requestLogPath) ? fs.readFileSync(requestLogPath, "utf8") : "";
|
|
assert(requestLog.includes("/v1/images/generations"), "image generation endpoint was not used");
|
|
}
|
|
|
|
function assertMemorySearch() {
|
|
const outputPath = process.argv[3];
|
|
const needle = process.argv[4];
|
|
const payload = readJson(outputPath);
|
|
const haystack = JSON.stringify(payload);
|
|
assert(haystack.includes(needle), `memory search missed ${needle}: ${haystack}`);
|
|
}
|
|
|
|
function assertPluginUninstalled() {
|
|
const pluginId = process.argv[3];
|
|
const cliRoot = process.argv[4];
|
|
const cfg = readJson(configPath());
|
|
const recordsPath = path.join(process.env.HOME ?? "", ".openclaw", "plugins", "installs.json");
|
|
const records = fs.existsSync(recordsPath) ? readJson(recordsPath) : {};
|
|
const installRecords = records.installRecords ?? records.records ?? {};
|
|
assert(!installRecords[pluginId], `install record still present for ${pluginId}`);
|
|
assert(!cfg.plugins?.entries?.[pluginId], `plugin config entry still present for ${pluginId}`);
|
|
const managedRoot = path.join(
|
|
process.env.HOME ?? "",
|
|
".openclaw",
|
|
"plugins",
|
|
"installed",
|
|
pluginId,
|
|
);
|
|
assert(!fs.existsSync(managedRoot), `managed plugin directory still present: ${managedRoot}`);
|
|
if (cliRoot) {
|
|
const list = JSON.stringify(records);
|
|
assert(!list.includes(cliRoot), `install records still mention CLI root ${cliRoot}`);
|
|
}
|
|
}
|
|
|
|
const commands = {
|
|
"configure-mock-openai": configureMockOpenAi,
|
|
"assert-openai-env-ref": assertOpenAiEnvRef,
|
|
"assert-agent-turn": assertAgentTurn,
|
|
"assert-file-contains": assertFileContains,
|
|
"assert-image-describe": assertImageDescribe,
|
|
"assert-image-generate": assertImageGenerate,
|
|
"assert-memory-search": assertMemorySearch,
|
|
"assert-plugin-uninstalled": assertPluginUninstalled,
|
|
};
|
|
|
|
const fn = commands[command];
|
|
if (!fn) {
|
|
throw new Error(`unknown release scenario assertion command: ${command ?? "<missing>"}`);
|
|
}
|
|
await fn();
|