feat: purge legacy agent hosts and land vault Chrome extension path

Retire ACP/Hermes/OpenCode surfaces and rename hermes_tools to
mnote_agent_tools so Page AI stays on Pi Lab only. Add Chrome vault
extension + extension token route, pre-release purge design, and soft-retire
legacy smokes for the small-group production cut.
This commit is contained in:
Agent Board
2026-07-25 14:25:37 +08:00
parent bc6f8488ee
commit 262e66b02e
137 changed files with 9018 additions and 46049 deletions
+2 -79
View File
@@ -1,15 +1,12 @@
#!/usr/bin/env node
/**
* 热启动 mnote-web 单入口,以及按需启用的 FastAPI / opencode
* 热启动 mnote-web 单入口,以及按需启用的 FastAPI。
* Page AI 仅走 Pi Lab/api/page-ai/pi/*);不再启动 OpenCode。
* 可使用以下环境变量调整行为:
* - ENABLE_BACKEND:设为 "1" or "true" 时启用默认 FastAPI 后端
* - BACKEND_CMD:覆盖 FastAPI 启动命令;设置后即视为显式启用后端
* - SKIP_BACKEND:设为 "1" or "true" 可强制跳过 FastAPI 后端
* - ENABLE_OPENCODE:设为 "1" or "true" 时启用 opencode serve;默认不启动
* - OPENCODE_CMD:覆盖 opencode 启动命令;设置后即视为显式启用 opencode
* - SKIP_OPENCODE:设为 "1" or "true" 可强制跳过 opencode
* - MNOTE_OPENCODE_XDG_ROOT / MNOTE_OPENCODE_HOMEopencode 专用运行目录
* - MNOTE_CONTROL_PLANE_BACKEND:控制面后端,默认 libsql-local;可设 turso-remote / turso-local-replica / turso-synced
* - MNOTE_TURSO_LOCAL_PATHlibsql-local 本地库路径,默认 /mnt/Data1T/Mnote_data/control-plane/control-plane-libsql.db
* - MNOTE_PAGE_AI_PI_WARMUP:设为 "1" or "true" 时,在 mnote-web 可用后预启动 Pi Lab runtime / MCP cache
@@ -54,7 +51,6 @@ function resolveBackendExecutable(envName, fallbackName) {
const pythonBin = resolveBackendExecutable("PYTHON_BIN", "python");
const backendPortFromEnv = Number(process.env.BACKEND_PORT || 8000);
const opencodePortFromEnv = Number(process.env.OPENCODE_PORT || 4096);
const defaultControlPlaneDir = "/mnt/Data1T/Mnote_data/control-plane";
function hasCommand(command) {
@@ -79,41 +75,6 @@ function buildDefaultBackendCommand(port) {
return `${pythonBin} -m uvicorn app.main:app --reload --port ${port}`;
}
function buildDefaultOpencodeCommand(port) {
const opencodeXdgRoot = process.env.MNOTE_OPENCODE_XDG_ROOT || "/mnt/Data1T/Mnote_data/opencode/runtime";
const opencodeHome = process.env.MNOTE_OPENCODE_HOME || "/mnt/Data1T/Mnote_data/opencode/home";
const modelEnvNames = [
"OPENCODE_API_KEY",
"OPENAI_API_KEY",
"OPENAI_BASE_URL",
"ANTHROPIC_API_KEY",
"GOOGLE_API_KEY",
"GOOGLE_GENERATIVE_AI_API_KEY",
"DEEPSEEK_API_KEY",
"GEMINI_API_KEY",
"MISTRAL_API_KEY",
"OPENROUTER_API_KEY",
"GROQ_API_KEY",
"XAI_API_KEY",
"AZURE_OPENAI_API_KEY",
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
];
const opencodeEnv = [
"env",
...modelEnvNames.map((name) => `-u ${name}`),
`HOME=${JSON.stringify(opencodeHome)}`,
`XDG_CONFIG_HOME=${JSON.stringify(path.join(opencodeXdgRoot, "config"))}`,
`XDG_DATA_HOME=${JSON.stringify(path.join(opencodeXdgRoot, "data"))}`,
`XDG_STATE_HOME=${JSON.stringify(path.join(opencodeXdgRoot, "state"))}`,
`XDG_CACHE_HOME=${JSON.stringify(path.join(opencodeXdgRoot, "cache"))}`,
].join(" ");
return [
`mkdir -p ${JSON.stringify(opencodeXdgRoot)} ${JSON.stringify(opencodeHome)}`,
`while true; do script -qfec ${JSON.stringify(`${opencodeEnv} opencode serve --hostname=127.0.0.1 --port ${port} --print-logs`)} /dev/null; sleep 1; done`,
].join(" && ");
}
function isEnabledEnv(value) {
const normalized = String(value || "").toLowerCase();
return normalized === "1" || normalized === "true";
@@ -125,12 +86,6 @@ function shouldStartBackend(env = process.env) {
return isEnabledEnv(env.ENABLE_BACKEND);
}
function shouldStartOpencode(env = process.env) {
if (isEnabledEnv(env.SKIP_OPENCODE)) return false;
if (String(env.OPENCODE_CMD || "").trim()) return true;
return isEnabledEnv(env.ENABLE_OPENCODE);
}
function resolveRuntimePlan(env = process.env) {
const frontendPort = Number(env.FRONTEND_PORT || 3000);
const skipGateway = false;
@@ -162,7 +117,6 @@ function resolveRuntimePlan(env = process.env) {
MNOTE_WEB_BIND: env.MNOTE_WEB_BIND || `0.0.0.0:${publicPort}`,
MNOTE_WEB_PUBLIC_BIND: env.MNOTE_WEB_PUBLIC_BIND || `127.0.0.1:${publicPort}`,
MNOTE_KNOWLEDGE_PROVIDER: env.MNOTE_KNOWLEDGE_PROVIDER || "lightrag_legacy",
MNOTE_OPENCODE_BASE_URL: env.MNOTE_OPENCODE_BASE_URL || `http://127.0.0.1:${opencodePortFromEnv}`,
...controlPlaneEnv,
},
};
@@ -195,17 +149,6 @@ const tasks = [
},
]
: []),
...(shouldStartOpencode(process.env)
? [
{
name: "opencode",
command:
process.env.OPENCODE_CMD ||
buildDefaultOpencodeCommand(opencodePortFromEnv),
cwd: rootDir,
},
]
: []),
];
function findTask(name) {
@@ -707,24 +650,6 @@ async function main() {
}
const desiredOpencodePort = opencodePortFromEnv;
if (shouldStartOpencode(process.env) && !process.env.OPENCODE_CMD) {
const opencodePortOk = await ensurePortFree(desiredOpencodePort, "opencode");
if (!opencodePortOk) {
console.error(`opencode 端口 ${desiredOpencodePort} 无法释放,已中止启动。`);
process.exit(1);
}
const opencodeTask = findTask("opencode");
if (!opencodeTask) {
throw new Error("缺少 opencode 任务配置");
}
opencodeTask.command = buildDefaultOpencodeCommand(desiredOpencodePort);
} else if (isEnabledEnv(process.env.SKIP_OPENCODE)) {
logPrefix("opencode", "已跳过 opencodeSKIP_OPENCODE=1)。");
} else if (!shouldStartOpencode(process.env)) {
}
if (tasks.length === 0) {
console.error("未配置任何可运行的任务,检查环境变量设置。");
process.exit(1);
@@ -744,7 +669,6 @@ if (require.main === module) {
}
module.exports = {
buildDefaultOpencodeCommand,
collectStaleMnoteWebCargoPids,
ensurePortFree,
getListeningPidsByPort,
@@ -757,7 +681,6 @@ module.exports = {
resolveBackendExecutable,
schedulePiLabWarmup,
shouldStartBackend,
shouldStartOpencode,
stopStaleMnoteWebCargoProcesses,
terminatePid,
};