import { spawn } from "node:child_process";
import { rm, stat } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
const PERMISSION_DEFS = [
{
key: "accessibility",
label: "辅助功能",
description: "用于点击、输入和读取可访问控件",
tier: "core",
},
{
key: "screenRecording",
label: "屏幕录制",
description: "用于识别桌面画面和系统弹窗",
tier: "core",
},
{
key: "automation",
label: "自动化控制",
description: "用于控制 Finder、浏览器和企业软件",
tier: "core",
},
];
const EXTENDED_PERMISSION_DEFS = [
{
key: "fullDiskAccess",
label: "全磁盘访问",
description: "用于读取和写入企业授权目录、日志与开发资产",
tier: "extended",
},
{
key: "inputMonitoring",
label: "输入监控",
description: "用于低层热键、复杂输入和部分不可访问控件兜底",
tier: "extended",
},
{
key: "notifications",
label: "通知权限",
description: "用于后台任务、接管结果和风险告警提醒",
tier: "extended",
},
{
key: "microphone",
label: "麦克风",
description: "用于语音指令、会议和音频协作场景",
tier: "extended",
},
{
key: "camera",
label: "摄像头",
description: "用于视觉协作、会议和现场画面确认",
tier: "extended",
},
{
key: "localNetwork",
label: "本地网络",
description: "用于发现和连接局域网设备、开发板与企业内网服务",
tier: "extended",
},
];
const MACOS_PERMISSION_SETTINGS = {
all: "x-apple.systempreferences:com.apple.preference.security?Privacy",
accessibility: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility",
screenRecording: "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture",
automation: "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation",
fullDiskAccess: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles",
inputMonitoring: "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent",
notifications: "x-apple.systempreferences:com.apple.Notifications-Settings.extension",
microphone: "x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone",
camera: "x-apple.systempreferences:com.apple.preference.security?Privacy_Camera",
localNetwork: "x-apple.systempreferences:com.apple.preference.security?Privacy_LocalNetwork",
};
const AUTO_PREFLIGHT_PERMISSION_KEYS = new Set(["accessibility", "screenRecording", "automation"]);
function nonEmpty(value) {
const text = String(value ?? "").trim();
return text || undefined;
}
function escapeHtml(value) {
return String(value ?? "")
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function maskValue(value) {
const text = nonEmpty(value);
if (!text) return "";
if (text.length <= 8) return "••••";
return `${text.slice(0, 4)}••••${text.slice(-4)}`;
}
function normalizePermissionStatus(value) {
return value === "granted" || value === "missing" || value === "unknown" ? value : "unknown";
}
function statusTone(status) {
if (status === "granted" || status === "valid" || status === "connected" || status === "bound") {
return "good";
}
if (status === "missing" || status === "expired" || status === "disconnected") {
return "bad";
}
return "warn";
}
function formatDate(value) {
const text = nonEmpty(value);
if (!text) return "绑定后显示";
const date = new Date(text);
if (Number.isNaN(date.getTime())) return text;
return new Intl.DateTimeFormat("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
}).format(date);
}
function buildBindingPayload(config) {
const controlPlaneUrl = nonEmpty(config.controlPlaneUrl) ?? "https://boss.hyzq.net";
const params = new URLSearchParams({
server: controlPlaneUrl,
deviceId: nonEmpty(config.deviceId) ?? "local-device",
name: nonEmpty(config.name) ?? "本机电脑",
});
const pairingCode = nonEmpty(config.pairingCode);
if (pairingCode) params.set("pairingCode", pairingCode);
return `boss://agent-bind?${params.toString()}`;
}
function resolveApiUsage(config) {
return {
primary:
nonEmpty(config.primaryApiLabel) ??
nonEmpty(config.apiUsage?.primary) ??
nonEmpty(config.masterAgentModel) ??
"由 Boss 后台统一配置",
backup:
nonEmpty(config.backupApiLabel) ??
nonEmpty(config.apiUsage?.backup) ??
"未启用",
status:
nonEmpty(config.apiUsage?.status) ??
(config.masterAgentEnabled === false ? "未启用主 Agent" : "可用"),
};
}
function resolveLicense(config, bound) {
const license = config.license && typeof config.license === "object" ? config.license : {};
if (!bound) {
return {
status: "pending_binding",
label: "未授权 · 绑定后校验",
enterpriseName: "绑定后显示",
expiresAt: nonEmpty(config.licenseExpiresAt) ?? "",
expiresAtLabel: "绑定后显示",
scope: "桌面控制 / 浏览器控制 / Skill 同步",
};
}
const status = nonEmpty(license.status) ?? "valid";
const expiresAt = nonEmpty(license.expiresAt) ?? nonEmpty(config.licenseExpiresAt) ?? "";
return {
status,
label: status === "valid" ? "正版授权正常" : status === "expired" ? "授权已过期" : "授权状态待确认",
enterpriseName: nonEmpty(license.enterpriseName) ?? nonEmpty(config.enterpriseName) ?? "默认公司",
expiresAt,
expiresAtLabel: formatDate(expiresAt),
scope: nonEmpty(license.scope) ?? "桌面控制 / 浏览器控制 / Skill 同步",
};
}
function permissionItems(defs, permissions) {
return defs.map((item) => ({
...item,
status: normalizePermissionStatus(permissions[item.key]),
}));
}
function resolvePermissionReadiness(coreItems, extendedItems) {
const coreGrantedCount = coreItems.filter((item) => item.status === "granted").length;
const extendedGrantedCount = extendedItems.filter((item) => item.status === "granted").length;
const coreReady = coreGrantedCount === coreItems.length;
const fullControlReady = coreReady && extendedGrantedCount === extendedItems.length;
const summary = fullControlReady
? "完整接管权限已具备"
: coreReady
? "核心桌面控制已具备,完整接管待补齐"
: "核心桌面控制待授权,完整接管不可用";
return {
coreReady,
fullControlReady,
coreGrantedCount,
coreTotal: coreItems.length,
extendedGrantedCount,
extendedTotal: extendedItems.length,
summary,
detail:
"辅助功能、屏幕录制、自动化控制是桌面点击输入与画面识别的核心权限;完整接管还需要按业务场景补齐全磁盘访问、输入监控、通知、麦克风、摄像头和本地网络。",
};
}
function buildPermissionSetupPlan(coreItems, extendedItems, readiness) {
const actions = [...coreItems, ...extendedItems].map((item) => ({
key: item.key,
label: item.label,
description: item.description,
tier: item.tier,
status: item.status,
requiredForSilentControl: true,
canPreflight: AUTO_PREFLIGHT_PERMISSION_KEYS.has(item.key),
settingsUrl: MACOS_PERMISSION_SETTINGS[item.key] ?? MACOS_PERMISSION_SETTINGS.all,
openUrl: `/api/v1/boss-agent/permissions/open?target=${encodeURIComponent(item.key)}`,
owner: "boss-agent.app",
}));
const missingActions = actions.filter((action) => action.status !== "granted");
return {
mode: "one_time_setup",
title: "一次完整授权",
goal: "首次把完整接管需要的权限集中配置好,后续控制过程中只做状态校验和静默使用。",
silentUseReady: missingActions.length === 0,
primaryAction: {
label: "打开完整授权向导",
href: "/api/v1/boss-agent/permissions/open?target=all",
settingsUrl: MACOS_PERMISSION_SETTINGS.all,
},
actions,
missingKeys: missingActions.map((action) => action.key),
summary: readiness.fullControlReady
? "完整授权已满足,后续可静默执行。"
: "仍有权限未确认,请在首次配置阶段一次性补齐,避免后续任务执行中断。",
persistenceNote:
"macOS 会把授权持久写入系统隐私数据库;除非用户撤销授权、重装应用或更换运行时签名,否则后续控制不需要重复申请。",
};
}
function resolveSkills(runtime) {
const rawSkills = Array.isArray(runtime.lastSkills) ? runtime.lastSkills : [];
const items = rawSkills
.map((item) => ({
name: nonEmpty(item?.name),
category: nonEmpty(item?.category) ?? "本机",
path: nonEmpty(item?.path) ?? "",
description: nonEmpty(item?.description) ?? "",
status: nonEmpty(item?.status) ?? "deployed",
}))
.filter((item) => item.name);
const syncOk = runtime.lastSkillSyncOk === true;
return {
total: items.length,
items: items.slice(0, 8),
syncOk,
syncStatus: syncOk ? "已同步" : items.length > 0 ? "待确认" : "未同步",
syncAt: nonEmpty(runtime.lastSkillSyncAt) ?? "",
summary: items.length > 0 ? `已部署 ${items.length} 个 Skill` : "本机暂无已同步 Skill",
};
}
export function buildBossAgentStatus(config = {}, runtime = {}, options = {}) {
const now = nonEmpty(options.now) ?? new Date().toISOString();
const token = nonEmpty(runtime.issuedToken) ?? nonEmpty(config.token);
const account = nonEmpty(config.account);
const bound = Boolean(token && account);
const permissions = options.permissions ?? {};
const serverOk = runtime.lastHeartbeatOk === true;
const qrPayload = bound ? "" : buildBindingPayload(config);
const corePermissionItems = permissionItems(PERMISSION_DEFS, permissions);
const extendedPermissionItems = permissionItems(EXTENDED_PERMISSION_DEFS, permissions);
const permissionReadiness = resolvePermissionReadiness(corePermissionItems, extendedPermissionItems);
const permissionSetup = buildPermissionSetupPlan(corePermissionItems, extendedPermissionItems, permissionReadiness);
return {
appName: "boss-agent",
generatedAt: now,
device: {
id: nonEmpty(config.deviceId) ?? "local-device",
name: nonEmpty(config.name) ?? os.hostname() ?? "本机电脑",
avatar: nonEmpty(config.avatar) ?? "B",
role: nonEmpty(config.deviceRole) ?? "企业被控节点",
endpoint: nonEmpty(config.endpoint) ?? "mac://local",
},
binding: {
bound,
status: bound ? "bound" : "unbound",
account: bound ? account : "未绑定",
tokenMasked: bound ? maskValue(token) : "",
pairingCode: bound ? "" : nonEmpty(config.pairingCode) ?? "",
qrPayload,
qrExpiresInLabel: bound ? "" : nonEmpty(config.qrExpiresInLabel) ?? "二维码 04:58 后失效",
},
server: {
ok: serverOk,
status: serverOk ? "connected" : "disconnected",
endpoint: nonEmpty(config.controlPlaneUrl) ?? "未配置服务器",
latencyLabel: nonEmpty(config.serverLatencyLabel) ?? (serverOk ? "延迟 28ms" : "连接异常"),
lastHeartbeatAt: nonEmpty(runtime.lastHeartbeatAt) ?? "",
lastHeartbeatStatus: runtime.lastHeartbeatStatus ?? null,
},
api: resolveApiUsage(config),
license: resolveLicense(config, bound),
permissions: {
summary: permissionReadiness.summary,
items: corePermissionItems,
extendedItems: extendedPermissionItems,
},
permissionReadiness,
permissionSetup,
skills: resolveSkills(runtime),
};
}
function renderPseudoQrSvg(payload) {
const size = 25;
let seed = 0;
for (const char of String(payload || "boss-agent")) {
seed = (seed * 31 + char.charCodeAt(0)) >>> 0;
}
const cells = [];
const finder = (x, y) => x < 7 && y < 7 || x > 17 && y < 7 || x < 7 && y > 17;
for (let y = 0; y < size; y += 1) {
for (let x = 0; x < size; x += 1) {
const finderCell = finder(x, y);
const edge = x === 0 || y === 0 || x === size - 1 || y === size - 1;
const value = finderCell
? !edge && (x % 6 === 1 || y % 6 === 1 || (x % 6 >= 2 && x % 6 <= 4 && y % 6 >= 2 && y % 6 <= 4))
: ((seed + x * 17 + y * 29 + x * y * 7) % 5) < 2;
if (value) {
cells.push(`
${escapeHtml(heroSubtitle)}
${escapeHtml(status.permissionSetup.goal)} 权限结论:${escapeHtml(status.permissions.summary)}。当前状态:${escapeHtml(status.permissionSetup.summary)} 后续静默使用依赖系统持久授权。