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(``); } } } return `${cells.join("")}`; } function permissionText(status) { if (status === "granted") return "已授权"; if (status === "missing") return "未授权"; return "待确认"; } function setupActionRows(status) { return status.permissionSetup.actions .map((action) => { const tone = statusTone(action.status); const preflight = action.canPreflight ? "可预触发" : "需手动开启"; return `
${escapeHtml(action.label)}
${escapeHtml(action.description)} · ${escapeHtml(preflight)}
${escapeHtml(permissionText(action.status))} 打开设置
`; }) .join(""); } function skillRows(status) { const skills = status.skills?.items ?? []; if (skills.length === 0) { return `
本机暂无已同步 Skill。绑定账号后可由 Boss 后台下发或同步本机 Codex Skill。
`; } return skills .map((skill) => { const pathLabel = skill.path ? skill.path.replace(os.homedir(), "~") : "未记录路径"; return `
${escapeHtml(skill.name)}
${escapeHtml(skill.category)} · ${escapeHtml(pathLabel)}
已部署
`; }) .join(""); } const BOSS_AGENT_TABS = new Set(["overview", "permissions", "skills", "license", "logs"]); export function normalizeBossAgentTab(value = "overview") { const tab = nonEmpty(value) ?? "overview"; return BOSS_AGENT_TABS.has(tab) ? tab : "overview"; } export function renderBossAgentHtml(status, options = {}) { return renderBossAgentHtmlBase(status, options); } export async function renderBossAgentHtmlWithQr(status, options = {}) { let qrImageDataUrl = ""; if (!status.binding.bound && status.binding.qrPayload) { try { const qrModule = await import("qrcode"); const toDataURL = qrModule.toDataURL ?? qrModule.default?.toDataURL; if (typeof toDataURL === "function") { qrImageDataUrl = await toDataURL(status.binding.qrPayload, { errorCorrectionLevel: "M", margin: 1, width: 288, color: { dark: "#18211a", light: "#ffffff", }, }); } } catch { qrImageDataUrl = ""; } } return renderBossAgentHtmlBase(status, { ...options, qrImageDataUrl }); } function activeClass(activeTab, tab) { return activeTab === tab ? ` class="active"` : ""; } function renderBossAgentNav(status, activeTab) { return ``; } function renderTopbar(status, title = "boss-agent", subtitle = "企业电脑接入端") { return `

${escapeHtml(title)}

${escapeHtml(subtitle)}
${escapeHtml(status.server.ok ? `已连接 ${status.server.endpoint}` : "服务器未连接")}
`; } function renderOverviewTab(status, { bound, heroTitle, heroSubtitle, qrBlock }) { return `${renderTopbar(status)}
${qrBlock}

${escapeHtml(heroTitle)}

${escapeHtml(heroSubtitle)}

${escapeHtml(bound ? `账号:${status.binding.account}` : status.binding.qrExpiresInLabel)}

绑定状态

账号${escapeHtml(status.binding.account)}
设备${escapeHtml(status.device.name)}
角色${escapeHtml(status.device.role)}
设备 ID${escapeHtml(status.device.id)}
账号登录状态
${escapeHtml(bound ? "已绑定" : "等待绑定")}
${escapeHtml(bound ? status.binding.account : "使用 Boss APP 扫码完成绑定")}
当前 API 使用情况
${escapeHtml(status.api.primary)}
备用 API:${escapeHtml(status.api.backup)}
服务器连接
${escapeHtml(status.server.ok ? "正常" : "异常")}
${escapeHtml(status.server.latencyLabel)}
正版授权
${escapeHtml(status.license.label)}
到期:${escapeHtml(status.license.expiresAtLabel)}

授权信息

企业${escapeHtml(status.license.enterpriseName)}
授权到期${escapeHtml(status.license.expiresAtLabel)}
权限范围${escapeHtml(status.license.scope)}
`; } function renderPermissionsTab(status) { return `${renderTopbar(status, "本机权限获取", "一次性完成本机接管权限配置")}

${escapeHtml(status.permissionSetup.title)}

${escapeHtml(status.permissionSetup.goal)} 权限结论:${escapeHtml(status.permissions.summary)}。当前状态:${escapeHtml(status.permissionSetup.summary)} 后续静默使用依赖系统持久授权。

${escapeHtml(status.permissionSetup.primaryAction.label)}
${setupActionRows(status)}
${escapeHtml(status.permissionSetup.persistenceNote)}
`; } function renderSkillsTab(status) { return `${renderTopbar(status, "Skill", "部署在本机并可被 Boss 调用的能力")}

Skill 部署情况

${skillRows(status)}
Skill 用于把本机可复用能力分发给 Boss APP 和主 Agent;后续企业后台可按账号、设备和权限策略下发。
`; } function renderLicenseTab(status) { return `${renderTopbar(status, "绑定与授权", "账号、设备、服务器和正版授权状态")}

绑定状态

账号${escapeHtml(status.binding.account)}
设备${escapeHtml(status.device.name)}
角色${escapeHtml(status.device.role)}
设备 ID${escapeHtml(status.device.id)}

授权信息

企业${escapeHtml(status.license.enterpriseName)}
授权到期${escapeHtml(status.license.expiresAtLabel)}
权限范围${escapeHtml(status.license.scope)}
${escapeHtml(status.permissionReadiness.detail)}
`; } function renderLogsTab(status) { return `${renderTopbar(status, "日志", "本机 agent 最近运行状态")}

暂无日志面板

当前版本先保留入口;运行日志仍写入本机 LaunchAgent 日志和 Boss 后台事件。
`; } function renderBossAgentTabContent(status, activeTab, viewModel) { if (activeTab === "permissions") return renderPermissionsTab(status); if (activeTab === "skills") return renderSkillsTab(status); if (activeTab === "license") return renderLicenseTab(status); if (activeTab === "logs") return renderLogsTab(status); return renderOverviewTab(status, viewModel); } function renderBossAgentHtmlBase(status, options = {}) { const activeTab = normalizeBossAgentTab(options.activeTab); const bound = status.binding.bound; const heroTitle = bound ? "这台电脑已接入 Boss" : "扫码绑定 Boss APP"; const heroSubtitle = bound ? "本机 agent 正在接收企业控制台调度,可用于桌面控制、浏览器控制和 Skill 同步。" : "使用 Boss APP 扫码,将这台电脑加入企业账号。"; const qrBlock = bound ? `
${escapeHtml(status.device.avatar)}
` : `
${ options.qrImageDataUrl ? `Boss APP 绑定二维码` : renderPseudoQrSvg(status.binding.qrPayload) }
`; const viewModel = { bound, heroTitle, heroSubtitle, qrBlock }; return ` boss-agent
${renderBossAgentTabContent(status, activeTab, viewModel)}
`; } function runCommand(command, args, timeoutMs = 2500) { return new Promise((resolve) => { const child = spawn(command, args, { stdio: ["ignore", "pipe", "pipe"], }); let stdout = ""; let stderr = ""; const timer = setTimeout(() => { child.kill("SIGKILL"); }, timeoutMs); 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", (error) => { clearTimeout(timer); resolve({ ok: false, stdout, stderr: error.message }); }); child.on("close", (code) => { clearTimeout(timer); resolve({ ok: code === 0, stdout: stdout.trim(), stderr: stderr.trim() }); }); }); } export function resolveBossAgentPermissionSettingsUrl(target = "all") { return MACOS_PERMISSION_SETTINGS[target] ?? MACOS_PERMISSION_SETTINGS.all; } export async function openBossAgentPermissionSettings(target = "all", platform = process.platform) { const settingsUrl = resolveBossAgentPermissionSettingsUrl(target); if (platform !== "darwin") { return { ok: false, target, settingsUrl, message: "当前平台暂不支持自动打开系统隐私设置,请在系统设置中手动完成授权。", }; } const result = await runCommand("open", [settingsUrl], 2500); return { ok: result.ok, target, settingsUrl, message: result.ok ? "已打开系统权限设置。" : result.stderr || result.stdout || "打开系统权限设置失败。", }; } export async function detectLocalComputerPermissions(platform = process.platform) { if (platform !== "darwin") { return { accessibility: "unknown", screenRecording: "unknown", automation: "unknown", }; } const accessibility = await runCommand("osascript", [ "-e", 'tell application "System Events" to get UI elements enabled', ]); const automation = await runCommand("osascript", ["-e", 'tell application "Finder" to get name']); const screenshotPath = path.join(os.tmpdir(), `boss-agent-permission-${Date.now()}.png`); const screen = await runCommand("screencapture", ["-x", "-t", "png", screenshotPath], 3500); let screenRecording = "missing"; if (screen.ok) { try { const info = await stat(screenshotPath); screenRecording = info.size > 1024 ? "granted" : "unknown"; } catch { screenRecording = "unknown"; } finally { await rm(screenshotPath, { force: true }).catch(() => {}); } } return { accessibility: accessibility.ok && /true/i.test(accessibility.stdout) ? "granted" : "missing", screenRecording, automation: automation.ok ? "granted" : "missing", }; }