feat: improve gateway services and auto-reply commands

This commit is contained in:
Peter Steinberger
2026-01-11 02:17:10 +01:00
parent df55d45b6f
commit e0bf86f06c
52 changed files with 888 additions and 213 deletions

View File

@@ -4,12 +4,14 @@ import path from "node:path";
import { promisify } from "node:util";
import {
GATEWAY_LAUNCH_AGENT_LABEL,
GATEWAY_SYSTEMD_SERVICE_NAME,
GATEWAY_WINDOWS_TASK_NAME,
GATEWAY_SERVICE_KIND,
GATEWAY_SERVICE_MARKER,
LEGACY_GATEWAY_LAUNCH_AGENT_LABELS,
LEGACY_GATEWAY_SYSTEMD_SERVICE_NAMES,
LEGACY_GATEWAY_WINDOWS_TASK_NAMES,
resolveGatewayLaunchAgentLabel,
resolveGatewaySystemdServiceName,
resolveGatewayWindowsTaskName,
} from "./constants.js";
export type ExtraGatewayService = {
@@ -26,20 +28,32 @@ export type FindExtraGatewayServicesOptions = {
const EXTRA_MARKERS = ["clawdbot", "clawdis"];
const execFileAsync = promisify(execFile);
export function renderGatewayServiceCleanupHints(): string[] {
export function renderGatewayServiceCleanupHints(
env: Record<string, string | undefined> = process.env as Record<
string,
string | undefined
>,
): string[] {
const profile = env.CLAWDBOT_PROFILE;
switch (process.platform) {
case "darwin":
case "darwin": {
const label = resolveGatewayLaunchAgentLabel(profile);
return [
`launchctl bootout gui/$UID/${GATEWAY_LAUNCH_AGENT_LABEL}`,
`rm ~/Library/LaunchAgents/${GATEWAY_LAUNCH_AGENT_LABEL}.plist`,
`launchctl bootout gui/$UID/${label}`,
`rm ~/Library/LaunchAgents/${label}.plist`,
];
case "linux":
}
case "linux": {
const unit = resolveGatewaySystemdServiceName(profile);
return [
`systemctl --user disable --now ${GATEWAY_SYSTEMD_SERVICE_NAME}.service`,
`rm ~/.config/systemd/user/${GATEWAY_SYSTEMD_SERVICE_NAME}.service`,
`systemctl --user disable --now ${unit}.service`,
`rm ~/.config/systemd/user/${unit}.service`,
];
case "win32":
return [`schtasks /Delete /TN "${GATEWAY_WINDOWS_TASK_NAME}" /F`];
}
case "win32": {
const task = resolveGatewayWindowsTaskName(profile);
return [`schtasks /Delete /TN "${task}" /F`];
}
default:
return [];
}
@@ -56,6 +70,42 @@ function containsMarker(content: string): boolean {
return EXTRA_MARKERS.some((marker) => lower.includes(marker));
}
function hasGatewayServiceMarker(content: string): boolean {
const lower = content.toLowerCase();
return (
lower.includes("clawdbot_service_marker") &&
lower.includes(GATEWAY_SERVICE_MARKER.toLowerCase()) &&
lower.includes("clawdbot_service_kind") &&
lower.includes(GATEWAY_SERVICE_KIND.toLowerCase())
);
}
function isClawdbotGatewayLaunchdService(
label: string,
contents: string,
): boolean {
if (hasGatewayServiceMarker(contents)) return true;
const lowerContents = contents.toLowerCase();
if (!lowerContents.includes("gateway")) return false;
return label.startsWith("com.clawdbot.");
}
function isClawdbotGatewaySystemdService(
name: string,
contents: string,
): boolean {
if (hasGatewayServiceMarker(contents)) return true;
if (!name.startsWith("clawdbot-gateway")) return false;
return contents.toLowerCase().includes("gateway");
}
function isClawdbotGatewayTaskName(name: string): boolean {
const normalized = name.trim().toLowerCase();
if (!normalized) return false;
const defaultName = resolveGatewayWindowsTaskName().toLowerCase();
return normalized === defaultName || normalized.startsWith("clawdbot gateway");
}
function tryExtractPlistLabel(contents: string): string | null {
const match = contents.match(
/<key>Label<\/key>\s*<string>([\s\S]*?)<\/string>/i,
@@ -66,14 +116,14 @@ function tryExtractPlistLabel(contents: string): string | null {
function isIgnoredLaunchdLabel(label: string): boolean {
return (
label === GATEWAY_LAUNCH_AGENT_LABEL ||
label === resolveGatewayLaunchAgentLabel() ||
LEGACY_GATEWAY_LAUNCH_AGENT_LABELS.includes(label)
);
}
function isIgnoredSystemdName(name: string): boolean {
return (
name === GATEWAY_SYSTEMD_SERVICE_NAME ||
name === resolveGatewaySystemdServiceName() ||
LEGACY_GATEWAY_SYSTEMD_SERVICE_NAMES.includes(name)
);
}
@@ -104,6 +154,7 @@ async function scanLaunchdDir(params: {
if (!containsMarker(contents)) continue;
const label = tryExtractPlistLabel(contents) ?? labelFromName;
if (isIgnoredLaunchdLabel(label)) continue;
if (isClawdbotGatewayLaunchdService(label, contents)) continue;
results.push({
platform: "darwin",
label,
@@ -139,6 +190,7 @@ async function scanSystemdDir(params: {
continue;
}
if (!containsMarker(contents)) continue;
if (isClawdbotGatewaySystemdService(name, contents)) continue;
results.push({
platform: "linux",
label: entry,
@@ -302,7 +354,7 @@ export async function findExtraGatewayServices(
for (const task of tasks) {
const name = task.name.trim();
if (!name) continue;
if (name === GATEWAY_WINDOWS_TASK_NAME) continue;
if (isClawdbotGatewayTaskName(name)) continue;
if (LEGACY_GATEWAY_WINDOWS_TASK_NAMES.includes(name)) continue;
const lowerName = name.toLowerCase();
const lowerCommand = task.taskToRun?.toLowerCase() ?? "";