mirror of
https://github.com/openclaw/openclaw.git
synced 2026-09-28 14:12:28 +08:00
Use transactions on the actual SQLite state and device databases for ordinary writes. Remove redundant coordination databases, transport, and exclusion layers while preserving bounded process ownership for startup, schema work, and offline maintenance. Tie test and QA scratch retirement to settled workers and native resources, preserve active plugin captures, and join SDK declaration compiler processes before synchronous semantic rendering. Validation: main-tier CI on5e731c1f64had 144 successful jobs and one Windows ACP initialization timeout. Qualified unchanged replay 36314027585 passed all 896 tests with the original 48-file order, six projects, toolchain, and deadlines. The original timeout remains unexplained and recorded in the PR. Reviewed main-conflict integration through39caa592efpasses focused SQLite, Doctor, image, and Cron proof plus affected typechecks and lint. No accepted actionable independent-review findings remain. Squash landing of #157413 under explicit maintainer authority to resolve logical main drift and admin-merge using the completed CI evidence. No PR-specific schema or public configuration migration.
102 lines
3.6 KiB
TypeScript
102 lines
3.6 KiB
TypeScript
import { readFileSync, statSync } from "node:fs";
|
|
import { dirname, relative, resolve } from "node:path";
|
|
import * as ts from "typescript/unstable/ast";
|
|
import { expect, it } from "vitest";
|
|
import { createNativeTypeScriptParser } from "../../scripts/lib/native-typescript.mts";
|
|
|
|
const components = [
|
|
"scripts/pr",
|
|
"scripts/pr-lib",
|
|
...readFileSync("scripts/pr-lib/wrapper-components.txt", "utf8").trim().split("\n"),
|
|
];
|
|
|
|
it.each([
|
|
"src/infra/gateway-state-owner.ts",
|
|
"src/plugins/discovery.ts",
|
|
"src/infra/sqlite-readonly-location.worker.ts",
|
|
])(
|
|
"retains %s and its relative ESM runtime dependencies in the wrapper inventory",
|
|
(entrypoint) => {
|
|
const root = process.cwd();
|
|
const pending = [entrypoint];
|
|
const visited = new Set<string>();
|
|
const missing = new Set<string>();
|
|
const parser = createNativeTypeScriptParser({ cwd: root });
|
|
try {
|
|
while (pending.length > 0) {
|
|
const file = pending.pop();
|
|
if (!file || visited.has(file)) {
|
|
continue;
|
|
}
|
|
visited.add(file);
|
|
if (
|
|
!components.some((component) => file === component || file.startsWith(`${component}/`))
|
|
) {
|
|
missing.add(file);
|
|
}
|
|
const absolute = resolve(root, file);
|
|
const source = parser.parseSourceFile(file, readFileSync(absolute, "utf8"));
|
|
const enqueue = (specifier: string) => {
|
|
if (!specifier.startsWith(".")) {
|
|
return;
|
|
}
|
|
const literal = resolve(dirname(absolute), specifier);
|
|
// Explicit runtime files win over adjacent declarations selected by TypeScript.
|
|
const target = [literal, literal.replace(/\.([cm]?)js$/, ".$1ts")].find((candidate) =>
|
|
statSync(candidate, { throwIfNoEntry: false })?.isFile(),
|
|
);
|
|
if (!target || /\.d\.[cm]?ts$/.test(target)) {
|
|
throw new Error(`Cannot resolve wrapper runtime dependency ${file}: ${specifier}`);
|
|
}
|
|
pending.push(relative(root, target).replaceAll("\\", "/"));
|
|
};
|
|
const visit = (node: ts.Node): void => {
|
|
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
const clause = node.importClause;
|
|
const bindings = clause?.namedBindings;
|
|
if (
|
|
!clause ||
|
|
(clause.phaseModifier !== ts.SyntaxKind.TypeKeyword &&
|
|
(clause.name ||
|
|
!bindings ||
|
|
ts.isNamespaceImport(bindings) ||
|
|
bindings.elements.some((element) => !element.isTypeOnly)))
|
|
) {
|
|
enqueue(node.moduleSpecifier.text);
|
|
}
|
|
return;
|
|
}
|
|
if (ts.isExportDeclaration(node)) {
|
|
const clause = node.exportClause;
|
|
if (
|
|
node.moduleSpecifier &&
|
|
ts.isStringLiteral(node.moduleSpecifier) &&
|
|
!node.isTypeOnly &&
|
|
(!clause ||
|
|
ts.isNamespaceExport(clause) ||
|
|
clause.elements.some((element) => !element.isTypeOnly))
|
|
) {
|
|
enqueue(node.moduleSpecifier.text);
|
|
}
|
|
return;
|
|
}
|
|
if (ts.isImportTypeNode(node)) {
|
|
return;
|
|
}
|
|
if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
|
|
const argument = node.arguments[0];
|
|
if (argument && ts.isStringLiteralLikeNode(argument)) {
|
|
enqueue(argument.text);
|
|
}
|
|
}
|
|
node.forEachChild(visit);
|
|
};
|
|
visit(source);
|
|
}
|
|
} finally {
|
|
parser.close();
|
|
}
|
|
expect([...missing].toSorted()).toEqual([]);
|
|
},
|
|
);
|