UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

270 lines (268 loc) 8.41 kB
import { c as resolveGatewayLaunchAgentLabel, d as resolveGatewaySystemdServiceName, f as resolveGatewayWindowsTaskName, n as GATEWAY_SERVICE_KIND, r as GATEWAY_SERVICE_MARKER } from "./constants-ClfJ_wF3.js"; import { n as execSchtasks } from "./service-CIkh5YiN.js"; import path from "node:path"; import fs from "node:fs/promises"; //#region src/daemon/inspect.ts const EXTRA_MARKERS = [ "openclaw", "clawdbot", "moltbot" ]; function renderGatewayServiceCleanupHints(env = process.env) { const profile = env.OPENCLAW_PROFILE; switch (process.platform) { case "darwin": { const label = resolveGatewayLaunchAgentLabel(profile); return [`launchctl bootout gui/$UID/${label}`, `rm ~/Library/LaunchAgents/${label}.plist`]; } case "linux": { const unit = resolveGatewaySystemdServiceName(profile); return [`systemctl --user disable --now ${unit}.service`, `rm ~/.config/systemd/user/${unit}.service`]; } case "win32": return [`schtasks /Delete /TN "${resolveGatewayWindowsTaskName(profile)}" /F`]; default: return []; } } function resolveHomeDir(env) { const home = env.HOME?.trim() || env.USERPROFILE?.trim(); if (!home) throw new Error("Missing HOME"); return home; } function detectMarker(content) { const lower = content.toLowerCase(); for (const marker of EXTRA_MARKERS) if (lower.includes(marker)) return marker; return null; } function hasGatewayServiceMarker(content) { const lower = content.toLowerCase(); const markerKeys = ["openclaw_service_marker"]; const kindKeys = ["openclaw_service_kind"]; const markerValues = [GATEWAY_SERVICE_MARKER.toLowerCase()]; const hasMarkerKey = markerKeys.some((key) => lower.includes(key)); const hasKindKey = kindKeys.some((key) => lower.includes(key)); const hasMarkerValue = markerValues.some((value) => lower.includes(value)); return hasMarkerKey && hasKindKey && hasMarkerValue && lower.includes(GATEWAY_SERVICE_KIND.toLowerCase()); } function isOpenClawGatewayLaunchdService(label, contents) { if (hasGatewayServiceMarker(contents)) return true; if (!contents.toLowerCase().includes("gateway")) return false; return label.startsWith("ai.openclaw."); } function isOpenClawGatewaySystemdService(name, contents) { if (hasGatewayServiceMarker(contents)) return true; if (!name.startsWith("openclaw-gateway")) return false; return contents.toLowerCase().includes("gateway"); } function isOpenClawGatewayTaskName(name) { const normalized = name.trim().toLowerCase(); if (!normalized) return false; return normalized === resolveGatewayWindowsTaskName().toLowerCase() || normalized.startsWith("openclaw gateway"); } function tryExtractPlistLabel(contents) { const match = contents.match(/<key>Label<\/key>\s*<string>([\s\S]*?)<\/string>/i); if (!match) return null; return match[1]?.trim() || null; } function isIgnoredLaunchdLabel(label) { return label === resolveGatewayLaunchAgentLabel(); } function isIgnoredSystemdName(name) { return name === resolveGatewaySystemdServiceName(); } function isLegacyLabel(label) { const lower = label.toLowerCase(); return lower.includes("clawdbot") || lower.includes("moltbot"); } async function readDirEntries(dir) { try { return await fs.readdir(dir); } catch { return []; } } async function readUtf8File(filePath) { try { return await fs.readFile(filePath, "utf8"); } catch { return null; } } async function scanLaunchdDir(params) { const results = []; const entries = await readDirEntries(params.dir); for (const entry of entries) { if (!entry.endsWith(".plist")) continue; const labelFromName = entry.replace(/\.plist$/, ""); if (isIgnoredLaunchdLabel(labelFromName)) continue; const fullPath = path.join(params.dir, entry); const contents = await readUtf8File(fullPath); if (contents === null) continue; const marker = detectMarker(contents); const label = tryExtractPlistLabel(contents) ?? labelFromName; if (!marker) { if (!(isLegacyLabel(labelFromName) || isLegacyLabel(label))) continue; results.push({ platform: "darwin", label, detail: `plist: ${fullPath}`, scope: params.scope, marker: isLegacyLabel(label) ? "clawdbot" : "moltbot", legacy: true }); continue; } if (isIgnoredLaunchdLabel(label)) continue; if (marker === "openclaw" && isOpenClawGatewayLaunchdService(label, contents)) continue; results.push({ platform: "darwin", label, detail: `plist: ${fullPath}`, scope: params.scope, marker, legacy: marker !== "openclaw" || isLegacyLabel(label) }); } return results; } async function scanSystemdDir(params) { const results = []; const entries = await readDirEntries(params.dir); for (const entry of entries) { if (!entry.endsWith(".service")) continue; const name = entry.replace(/\.service$/, ""); if (isIgnoredSystemdName(name)) continue; const fullPath = path.join(params.dir, entry); const contents = await readUtf8File(fullPath); if (contents === null) continue; const marker = detectMarker(contents); if (!marker) continue; if (marker === "openclaw" && isOpenClawGatewaySystemdService(name, contents)) continue; results.push({ platform: "linux", label: entry, detail: `unit: ${fullPath}`, scope: params.scope, marker, legacy: marker !== "openclaw" }); } return results; } function parseSchtasksList(output) { const tasks = []; let current = null; for (const rawLine of output.split(/\r?\n/)) { const line = rawLine.trim(); if (!line) { if (current) { tasks.push(current); current = null; } continue; } const idx = line.indexOf(":"); if (idx <= 0) continue; const key = line.slice(0, idx).trim().toLowerCase(); const value = line.slice(idx + 1).trim(); if (!value) continue; if (key === "taskname") { if (current) tasks.push(current); current = { name: value }; continue; } if (!current) continue; if (key === "task to run") current.taskToRun = value; } if (current) tasks.push(current); return tasks; } async function findExtraGatewayServices(env, opts = {}) { const results = []; const seen = /* @__PURE__ */ new Set(); const push = (svc) => { const key = `${svc.platform}:${svc.label}:${svc.detail}:${svc.scope}`; if (seen.has(key)) return; seen.add(key); results.push(svc); }; if (process.platform === "darwin") { try { const home = resolveHomeDir(env); const userDir = path.join(home, "Library", "LaunchAgents"); for (const svc of await scanLaunchdDir({ dir: userDir, scope: "user" })) push(svc); if (opts.deep) { for (const svc of await scanLaunchdDir({ dir: path.join(path.sep, "Library", "LaunchAgents"), scope: "system" })) push(svc); for (const svc of await scanLaunchdDir({ dir: path.join(path.sep, "Library", "LaunchDaemons"), scope: "system" })) push(svc); } } catch { return results; } return results; } if (process.platform === "linux") { try { const home = resolveHomeDir(env); const userDir = path.join(home, ".config", "systemd", "user"); for (const svc of await scanSystemdDir({ dir: userDir, scope: "user" })) push(svc); if (opts.deep) for (const dir of [ "/etc/systemd/system", "/usr/lib/systemd/system", "/lib/systemd/system" ]) for (const svc of await scanSystemdDir({ dir, scope: "system" })) push(svc); } catch { return results; } return results; } if (process.platform === "win32") { if (!opts.deep) return results; const res = await execSchtasks([ "/Query", "/FO", "LIST", "/V" ]); if (res.code !== 0) return results; const tasks = parseSchtasksList(res.stdout); for (const task of tasks) { const name = task.name.trim(); if (!name) continue; if (isOpenClawGatewayTaskName(name)) continue; const lowerName = name.toLowerCase(); const lowerCommand = task.taskToRun?.toLowerCase() ?? ""; let marker = null; for (const candidate of EXTRA_MARKERS) if (lowerName.includes(candidate) || lowerCommand.includes(candidate)) { marker = candidate; break; } if (!marker) continue; push({ platform: "win32", label: name, detail: task.taskToRun ? `task: ${name}, run: ${task.taskToRun}` : name, scope: "system", marker, legacy: marker !== "openclaw" }); } return results; } return results; } //#endregion export { renderGatewayServiceCleanupHints as n, findExtraGatewayServices as t };