feat: ship enterprise control and desktop governance

This commit is contained in:
AI Bot
2026-05-11 14:59:26 +08:00
parent 0757d07521
commit a311280238
285 changed files with 48574 additions and 2428 deletions

View File

@@ -0,0 +1,253 @@
#!/usr/bin/env node
import { mkdir, writeFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import { spawn } from "node:child_process";
import path from "node:path";
function writeJson(payload) {
process.stdout.write(`${JSON.stringify(payload)}\n`);
}
async function readStdin() {
const chunks = [];
for await (const chunk of process.stdin) {
chunks.push(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
}
return chunks.join("").trim();
}
function normalizePayload(raw) {
try {
const parsed = JSON.parse(raw);
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
return {
ok: false,
error: "INVALID_BROWSER_CONTROL_PAYLOAD: expected object",
};
}
return {
ok: true,
payload: parsed,
};
} catch {
return {
ok: false,
error: "INVALID_BROWSER_CONTROL_PAYLOAD: invalid json",
};
}
}
function extractTargetUrl(objective) {
const match = String(objective || "").match(/https?:\/\/[^\s、)]+/i);
return match?.[0] || undefined;
}
async function writeArtifact(payload) {
const artifactDir = String(process.env.BOSS_CONTROL_ARTIFACT_DIR || "").trim();
if (!artifactDir) {
return [];
}
await mkdir(artifactDir, { recursive: true });
const requestId =
typeof payload.requestId === "string" && payload.requestId.trim()
? payload.requestId.trim()
: `browser-${Date.now()}`;
const artifactPath = path.join(artifactDir, `${requestId}.json`);
await writeFile(artifactPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
return [
{
kind: "json",
path: artifactPath,
},
];
}
function parseArgs(value) {
return String(value || "")
.trim()
.split(/\s+/)
.filter(Boolean);
}
function parseArgsJson(value) {
const raw = String(value || "").trim();
if (!raw) {
return undefined;
}
try {
const parsed = JSON.parse(raw);
return Array.isArray(parsed) ? parsed.map((item) => String(item)).filter(Boolean) : undefined;
} catch {
return undefined;
}
}
function getBrowserAutomationMode() {
const raw = String(process.env.BOSS_BROWSER_AUTOMATION_MODE || "").trim().toLowerCase();
if (raw === "off" || raw === "fetch" || raw === "playwright" || raw === "auto") {
return raw;
}
return "auto";
}
function resolveCodexHome() {
return String(process.env.CODEX_HOME || "").trim() || path.join(process.env.HOME || "", ".codex");
}
function resolveBundledPlaywrightCommand() {
const wrapper = path.join(resolveCodexHome(), "skills", "playwright", "scripts", "playwright_cli.sh");
return existsSync(wrapper) ? wrapper : undefined;
}
function resolveBrowserAutomationArgs(command, commandArgs, targetUrl, requestId) {
const args = [...commandArgs];
const session =
String(process.env.BOSS_BROWSER_AUTOMATION_SESSION || "").trim() ||
String(requestId || "").trim();
if (session) {
args.push("--session", session);
}
args.push(command, targetUrl);
return args;
}
async function runCommand(command, args) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, {
stdio: ["ignore", "pipe", "pipe"],
});
let stdout = "";
let stderr = "";
child.stdout.setEncoding("utf8");
child.stderr.setEncoding("utf8");
child.stdout.on("data", (chunk) => {
stdout += chunk;
});
child.stderr.on("data", (chunk) => {
stderr += chunk;
});
child.on("error", reject);
child.on("close", (code) => {
if (code !== 0) {
reject(new Error(stderr.trim() || `browser open exit code ${code}`));
return;
}
resolve({ stdout: stdout.trim(), stderr: stderr.trim() });
});
});
}
async function runBrowserAutomation(targetUrl, requestId) {
const command =
String(process.env.BOSS_BROWSER_AUTOMATION_COMMAND || "").trim() || resolveBundledPlaywrightCommand();
if (!command || !targetUrl) {
return undefined;
}
const prefixArgs =
parseArgsJson(process.env.BOSS_BROWSER_AUTOMATION_ARGS_JSON) ??
parseArgs(process.env.BOSS_BROWSER_AUTOMATION_ARGS);
await runCommand(command, resolveBrowserAutomationArgs("open", prefixArgs, targetUrl, requestId));
const title = await runCommand(
command,
resolveBrowserAutomationArgs("eval", prefixArgs, "document.title", requestId),
);
return title.stdout || undefined;
}
async function inspectPageTitle(targetUrl) {
if (!targetUrl) {
return undefined;
}
try {
const response = await fetch(targetUrl, {
redirect: "follow",
signal: AbortSignal.timeout(8000),
});
const contentType = response.headers.get("content-type") || "";
if (!contentType.includes("text/html")) {
return undefined;
}
const html = await response.text();
const title = html.match(/<title[^>]*>([\s\S]*?)<\/title>/i)?.[1]?.replace(/\s+/g, " ").trim();
return title || undefined;
} catch {
return undefined;
}
}
const raw = await readStdin();
const normalized = normalizePayload(raw);
if (!normalized.ok) {
writeJson({
status: "failed",
error: normalized.error,
});
process.exit(0);
}
const payload = normalized.payload;
const currentRequestId = typeof payload.requestId === "string" ? payload.requestId.trim() : "";
const objective =
typeof payload.objective === "string" && payload.objective.trim()
? payload.objective.trim()
: "浏览器控制 smoke 链路正常";
const targetUrl = extractTargetUrl(objective);
const riskLevel =
typeof payload.context?.riskLevel === "string" && payload.context.riskLevel.trim()
? payload.context.riskLevel.trim()
: "unknown";
const dryRun = payload.context?.dryRun === true;
let action = targetUrl ? "open_url" : "browser_smoke";
const configuredAutomationMode = getBrowserAutomationMode();
const automationMode =
configuredAutomationMode === "auto"
? String(process.env.BOSS_BROWSER_AUTOMATION_COMMAND || "").trim() || resolveBundledPlaywrightCommand()
? "playwright"
: "fetch"
: configuredAutomationMode;
const automatedTitle =
targetUrl && !dryRun && automationMode === "playwright"
? await runBrowserAutomation(targetUrl, currentRequestId)
: undefined;
const pageTitle =
automatedTitle ||
(automationMode !== "off" ? await inspectPageTitle(targetUrl) : undefined);
if (targetUrl && !dryRun) {
if (automationMode === "playwright" && automatedTitle) {
action = "browser_automation_executed";
} else {
const command = String(process.env.BOSS_BROWSER_OPEN_COMMAND || "").trim() || "open";
const prefixArgs =
parseArgsJson(process.env.BOSS_BROWSER_OPEN_ARGS_JSON) ??
parseArgs(process.env.BOSS_BROWSER_OPEN_ARGS);
await runCommand(command, [...prefixArgs, targetUrl]);
action = "open_url_executed";
}
}
const artifacts = await writeArtifact({
requestKind: payload.requestKind,
requestId: payload.requestId,
action,
objective,
targetUrl,
dryRun,
riskLevel,
capturedAt: new Date().toISOString(),
});
writeJson({
status: "completed",
requestId: typeof payload.requestId === "string" ? payload.requestId : undefined,
replyBody: pageTitle
? `浏览器控制已完成:${objective}。页面标题:${pageTitle}`
: `浏览器控制已完成:${objective}`,
executionSummary: pageTitle
? `${action} completed (risk=${riskLevel}, title=${pageTitle})`
: `${action} completed (risk=${riskLevel})`,
targetUrl,
artifacts,
});