Prepare self-contained open-source release (#1)

* feat: prepare self-contained open-source release

* fix: canonicalize missing managed paths

---------

Co-authored-by: luckyyzh <luckyyzh@users.noreply.github.com>
This commit is contained in:
Zihao Yang
2026-07-31 03:39:54 +08:00
committed by GitHub
co-authored by luckyyzh
parent 7392ab9dd7
commit 5c9c6631f5
34 changed files with 1310 additions and 137 deletions
+87
View File
@@ -0,0 +1,87 @@
import { spawnSync } from "node:child_process";
import { existsSync } from "node:fs";
import { platform } from "node:os";
import { join } from "node:path";
import { pathToFileURL } from "node:url";
import {
agentDir,
dataDir,
managedEnvironment,
resourcesDir,
rootDir,
} from "./profile.mjs";
Object.assign(process.env, managedEnvironment());
const codingAgentEntry = pathToFileURL(
join(rootDir, "pi-web", "node_modules", "@earendil-works", "pi-coding-agent", "dist", "index.js"),
).href;
const { DefaultResourceLoader } = await import(codingAgentEntry);
const loader = new DefaultResourceLoader({
cwd: join(dataDir, "workspaces", "default"),
agentDir,
additionalExtensionPaths: [join(resourcesDir, "extensions")],
additionalSkillPaths: [join(resourcesDir, "skills")],
});
await loader.reload();
const loaded = loader.getExtensions();
if (loaded.errors.length > 0) {
for (const error of loaded.errors) console.error(`Extension load error: ${error.error}`);
process.exit(1);
}
const tools = new Set(loaded.extensions.flatMap((extension) => [...extension.tools.keys()]));
const commands = new Set(loaded.extensions.flatMap((extension) => [...extension.commands.keys()]));
const requiredTools = [
"web_search",
"mcp",
"lens_diagnostics",
"subagent",
"web_fetch",
"memory_write",
"resolve-library-id",
"query-docs",
];
const requiredCommands = ["checkpoint", "rewind"];
const missing = [
...requiredTools.filter((name) => !tools.has(name)).map((name) => `tool:${name}`),
...requiredCommands.filter((name) => !commands.has(name)).map((name) => `command:/${name}`),
];
if (missing.length > 0) {
console.error(`Managed Pi profile is incomplete: ${missing.join(", ")}`);
process.exit(1);
}
const npmCliPath = process.env.npm_execpath;
if (!npmCliPath) {
console.error("Run the managed profile check through npm: npm run check:profile");
process.exit(1);
}
const playwrightResult = spawnSync(
process.execPath,
[npmCliPath, "exec", "--yes", "--package=@playwright/mcp@0.0.78", "--", "playwright-mcp", "--version"],
{ cwd: rootDir, env: process.env, encoding: "utf8" },
);
if (playwrightResult.error || playwrightResult.status !== 0) {
process.stderr.write(playwrightResult.stderr ?? "");
console.error("Unable to cache @playwright/mcp@0.0.78 for the managed MCP profile.");
process.exit(playwrightResult.status ?? 1);
}
if (platform() === "win32") {
const edgeCandidates = [
join(process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)", "Microsoft", "Edge", "Application", "msedge.exe"),
join(process.env.ProgramFiles ?? "C:\\Program Files", "Microsoft", "Edge", "Application", "msedge.exe"),
];
if (!edgeCandidates.some(existsSync)) {
console.error("Microsoft Edge is required by config/mcp.default.json but was not found.");
process.exit(1);
}
}
console.log(
`Managed Pi profile ready: ${loaded.extensions.length} extension(s), ${tools.size} tool(s), ${commands.size} command(s).`,
);