mirror of
https://github.com/openclaw/openclaw.git
synced 2026-09-28 14:12:28 +08:00
* fix(config): preserve authored references during Doctor repair Use canonical authored projection for invalid snapshots so a legacy agent roster can migrate without restoring the retired list or flattening includes. Keep roster-format intent separate from explicit value edits and consume it only after the Doctor write commits. Compare resolved Gateway modes while retaining intentional parameter removal and ambiguous-include safeguards. Derive plugin consent failure from its existing typed outcomes, and arm the transient composer-cue test observer before the user action. Follow-up to #134490. The exact repair patch and all 26 managed-review datasets are unchanged after adopting its landed main base. Independent P0-P2 review, 107 integration cases, and 18 real Doctor cases on this base pass. The earlier 528 config/Doctor cases pass with those owners unchanged. Final packaged Crabbox upgrade and autonomous repair proof remains pending. Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com> * test(update): verify npm artifacts in upgrade recovery Validate automatic plugin recovery against the declared npm source, its managed installation, exact version, artifact integrity, and capability consent. Preserve selected-plugin consent deferral and the explicit ClawHub companion audit. Replace the stale ClawHub-only request expectation with a positive artifact assertion and zero unexpected ClawHub requests. Exercise invalid records and the real phase order, including macOS Bash 3.2 optional arguments. The packaged stable-to-candidate reproduction exposed the obsolete oracle. Focused regressions, all changed checks, and final managed review pass. Full final-package Crabbox verification remains in progress. Related: https://github.com/openclaw/openclaw/pull/134490 * test(ui): wait for draft persistence before legacy seeding Observe the committed nonempty draft and its post-send clear before replacing current metadata with the legacy outbox fixture. This prevents navigation from aborting the clear and restoring the old text and Blob. The native IndexedDB latency reproduction fails before the correction and passes after it. Both original legacy table cases and the changed checks pass. * test(ui): wait for menu readiness in continuation proof Use the shared focus-synchronized submenu helper for both desktop openings of Continue in terminal. Keep the real action clicks, exact handoff and clipboard assertions, reconnect retirement, and mobile pointer flow. Both browser cases and the changed-file gate pass with a clean managed review. Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com> --------- Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { delimiter, join } from "node:path";
|
|
import { pathToFileURL } from "node:url";
|
|
import type { PluginInstallRecord } from "../../src/config/types.plugins.js";
|
|
import { isTrustedOfficialPluginInstallRecord } from "../../src/plugins/official-external-install-records.js";
|
|
|
|
export type PluginInspectFixture = {
|
|
plugin: {
|
|
id: string;
|
|
packageName: string;
|
|
rootDir: string;
|
|
trustedOfficialInstall: boolean;
|
|
};
|
|
install: PluginInstallRecord;
|
|
};
|
|
|
|
export function writePluginInspectFixture(
|
|
binDir: string,
|
|
records: Readonly<Record<string, PluginInstallRecord>>,
|
|
mutate?: (inspections: Record<string, PluginInspectFixture>) => void,
|
|
): NodeJS.ProcessEnv {
|
|
const inspections: Record<string, PluginInspectFixture> = {};
|
|
for (const [pluginId, record] of Object.entries(records)) {
|
|
if (!record.installPath || !existsSync(join(record.installPath, "package.json"))) {
|
|
continue;
|
|
}
|
|
const { name: packageName } = JSON.parse(
|
|
readFileSync(join(record.installPath, "package.json"), "utf8"),
|
|
) as { name: string };
|
|
inspections[pluginId] = {
|
|
plugin: {
|
|
id: pluginId,
|
|
packageName,
|
|
rootDir: record.installPath,
|
|
trustedOfficialInstall: isTrustedOfficialPluginInstallRecord({
|
|
pluginId,
|
|
packageName,
|
|
record,
|
|
}),
|
|
},
|
|
install: { ...record },
|
|
};
|
|
}
|
|
mutate?.(inspections);
|
|
mkdirSync(binDir, { recursive: true });
|
|
const inspectionPath = join(binDir, "plugin-inspections.json");
|
|
writeFileSync(inspectionPath, JSON.stringify(inspections));
|
|
const fixtureScript = join(binDir, "openclaw");
|
|
writeFileSync(
|
|
fixtureScript,
|
|
`#!/usr/bin/env node
|
|
const fs = require("node:fs");
|
|
const args = process.argv.slice(2);
|
|
if (args.join(" ") === "plugins install --help") {
|
|
console.log(" --accept-capabilities Accept capabilities");
|
|
} else if (args.length === 4 && args[0] === "plugins" && args[1] === "inspect" && args[3] === "--json") {
|
|
const inspection = JSON.parse(fs.readFileSync(${JSON.stringify(inspectionPath)}, "utf8"))[args[2]];
|
|
if (!inspection) process.exit(98);
|
|
console.log(JSON.stringify(inspection));
|
|
} else {
|
|
process.exit(97);
|
|
}
|
|
`,
|
|
{ mode: 0o755 },
|
|
);
|
|
// Keep Bash's executable fixture, but let Node callers use an absolute executable on Windows.
|
|
const preloadPath = join(binDir, "plugin-inspect-preload.mjs");
|
|
writeFileSync(
|
|
preloadPath,
|
|
`import childProcess from "node:child_process";
|
|
import { syncBuiltinESMExports } from "node:module";
|
|
const execFileSync = childProcess.execFileSync;
|
|
childProcess.execFileSync = (file, args, options) => {
|
|
if (file === "openclaw") {
|
|
return execFileSync(process.execPath, [${JSON.stringify(fixtureScript)}, ...args], options);
|
|
}
|
|
return execFileSync(file, args, options);
|
|
};
|
|
syncBuiltinESMExports();
|
|
`,
|
|
);
|
|
return {
|
|
NODE_OPTIONS:
|
|
`${process.env.NODE_OPTIONS ?? ""} --import=${pathToFileURL(preloadPath).href}`.trim(),
|
|
PATH: `${binDir}${delimiter}${process.env.PATH ?? ""}`,
|
|
};
|
|
}
|