Files
tutti/packages/workbench/host/scripts/check-built-boundaries.mjs
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

133 lines
3.7 KiB
JavaScript

import { readFile, readdir } from "node:fs/promises";
import { join } from "node:path";
const packageRoot = new URL("..", import.meta.url);
const workspaceRoot = new URL("../../../../", import.meta.url);
const distRoot = new URL("dist/", packageRoot);
for (const path of await listFiles(distRoot, ".js")) {
const runtime = await readFile(new URL(path, distRoot), "utf8");
if (/(?:from\s+|import\s*)["']react(?:\/[^"']*)?["']/.test(runtime)) {
throw new Error(
`@tutti-os/workbench-host emitted a React runtime import: ${path}`
);
}
if (
/(?:from\s+|import\s*)["']@tutti-os\/workbench-surface["']/.test(runtime)
) {
throw new Error(
`@tutti-os/workbench-host emitted a Workbench surface runtime import: ${path}`
);
}
}
const surfaceRoot = new URL("packages/workbench/surface/", workspaceRoot);
for (const path of await listFiles(surfaceRoot, ".json", ".ts", ".tsx")) {
const source = await readFile(new URL(path, surfaceRoot), "utf8");
if (source.includes("@tutti-os/workbench-host")) {
throw new Error(
`@tutti-os/workbench-surface must not depend on host: ${path}`
);
}
}
await assertNoSurfaceHostDependencyCycle();
console.log("workbench host built boundary check passed");
async function assertNoSurfaceHostDependencyCycle() {
const packageManifests = new Map();
const packagesRoot = new URL("packages/", workspaceRoot);
for (const group of await readdir(packagesRoot, { withFileTypes: true })) {
if (!group.isDirectory()) {
continue;
}
const groupRoot = new URL(`${group.name}/`, packagesRoot);
for (const packageEntry of await readdir(groupRoot, {
withFileTypes: true
})) {
if (!packageEntry.isDirectory()) {
continue;
}
try {
const manifest = JSON.parse(
await readFile(
new URL(`${packageEntry.name}/package.json`, groupRoot),
"utf8"
)
);
if (typeof manifest.name === "string") {
packageManifests.set(manifest.name, manifest);
}
} catch (error) {
if (error?.code !== "ENOENT") {
throw error;
}
}
}
}
const pending = [
{
name: "@tutti-os/workbench-surface",
path: ["@tutti-os/workbench-surface"]
}
];
const visited = new Set();
while (pending.length > 0) {
const current = pending.shift();
if (!current || visited.has(current.name)) {
continue;
}
visited.add(current.name);
const manifest = packageManifests.get(current.name);
if (!manifest) {
continue;
}
for (const field of [
"dependencies",
"optionalDependencies",
"peerDependencies"
]) {
for (const dependencyName of Object.keys(manifest[field] ?? {})) {
if (dependencyName === "@tutti-os/workbench-host") {
throw new Error(
`Workbench package dependency cycle: ${[
...current.path,
dependencyName
].join(" -> ")}`
);
}
if (packageManifests.has(dependencyName)) {
pending.push({
name: dependencyName,
path: [...current.path, dependencyName]
});
}
}
}
}
}
async function listFiles(root, ...extensions) {
const paths = [];
await visit("");
return paths;
async function visit(relativeDirectory) {
const entries = await readdir(new URL(relativeDirectory, root), {
withFileTypes: true
});
for (const entry of entries) {
const relativePath = join(relativeDirectory, entry.name);
if (entry.isDirectory()) {
await visit(`${relativePath}/`);
} else if (
extensions.some((extension) => entry.name.endsWith(extension))
) {
paths.push(relativePath);
}
}
}
}