[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,628 @@
"use strict";
const { createExecOnSessionApi } = require("./systemManager/execOnSession.cjs");
const { createTmuxOpsApi } = require("./systemManager/tmuxOps.cjs");
const { createDockerOpsApi } = require("./systemManager/dockerOps.cjs");
const { createGpuOpsApi } = require("./systemManager/gpuOps.cjs");
const { createPortOpsApi } = require("./systemManager/portOps.cjs");
const { createServiceOpsApi } = require("./systemManager/serviceOps.cjs");
const {
PROCESS_LIST_PS_COMMAND,
buildStopProcessPsCommand,
CAPABILITY_PROBE_PS_COMMAND,
} = require("./systemManager/windowsPowerShell.cjs");
const CAPABILITY_SCRIPT_POSIX = [
"exec sh -c ",
"'",
'printf "%s\\n" "__NC_OS__=$(uname -s)"; ',
'command -v tmux >/dev/null 2>&1 && printf "%s\\n" __NC_TMUX__=1; ',
'command -v docker >/dev/null 2>&1 && printf "%s\\n" __NC_DOCKER__=1; ',
'command -v nvidia-smi >/dev/null 2>&1 && printf "%s\\n" __NC_NVIDIA_SMI__=1; ',
'command -v npu-smi >/dev/null 2>&1 && printf "%s\\n" __NC_NPU_SMI__=1; ',
'command -v ss >/dev/null 2>&1 && printf "%s\\n" __NC_SS__=1; ',
'command -v netstat >/dev/null 2>&1 && printf "%s\\n" __NC_NETSTAT__=1; ',
'command -v lsof >/dev/null 2>&1 && printf "%s\\n" __NC_LSOF__=1; ',
'command -v systemctl >/dev/null 2>&1 && printf "%s\\n" __NC_SYSTEMCTL__=1',
"'",
].join("");
const PROCESS_LIST_SCRIPT_POSIX = [
"exec sh -c ",
"'",
"ps -eo pid= -o ppid= -o user= -o stat= -o pcpu= -o pmem= -o rss= -o vsz= -o etime= -o args= 2>/dev/null || top -b -n 1 2>/dev/null || ps ww 2>/dev/null || ps 2>/dev/null",
"'",
].join("");
const PROCESS_LIST_MAX_BUFFER = 64 * 1024 * 1024;
function parseCapabilities(stdout, isLocal, localPlatform) {
const text = stdout || "";
let targetOs = "unknown";
if (isLocal) {
if (localPlatform === "linux") targetOs = "linux";
else if (localPlatform === "darwin") targetOs = "darwin";
else if (localPlatform === "win32") targetOs = "win32";
} else {
const osMatch = text.match(/__NC_OS__=([^\r\n]+)/);
const uname = (osMatch?.[1] || "").trim().toLowerCase();
if (uname.includes("linux")) targetOs = "linux";
else if (uname.includes("darwin")) targetOs = "darwin";
else if (uname.includes("windows") || uname.includes("mingw")) targetOs = "win32";
}
// Line-anchored markers only — avoid matching probe-script source echoed by
// noisy shells / vendor CLIs that reprint the command text.
const hasFlag = (name) => new RegExp(`(?:^|\\r?\\n)${name}=1(?:\\r?\\n|$)`).test(text);
const hasTmux = hasFlag("__NC_TMUX__");
const hasDocker = hasFlag("__NC_DOCKER__");
const hasNvidiaSmi = hasFlag("__NC_NVIDIA_SMI__");
const hasNpuSmi = hasFlag("__NC_NPU_SMI__");
const hasSs = hasFlag("__NC_SS__");
const hasNetstat = hasFlag("__NC_NETSTAT__");
const hasLsof = hasFlag("__NC_LSOF__");
const hasSystemctl = hasFlag("__NC_SYSTEMCTL__");
return {
targetOs,
hasTmux,
hasDocker,
hasNvidiaSmi,
hasNpuSmi,
hasSs,
hasNetstat,
hasLsof,
hasSystemctl,
probedAt: Date.now(),
};
}
function parseProcessLines(stdout) {
const processes = [];
for (const line of (stdout || "").split("\n")) {
const trimmed = line.trim();
if (!trimmed) continue;
const m = trimmed.match(/^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+([\d.]+)\s+([\d.]+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.+)$/);
if (m) {
processes.push({
pid: Number(m[1]),
ppid: Number(m[2]),
user: m[3],
stat: m[4],
cpuPercent: Number(m[5]),
memPercent: Number(m[6]),
rssKb: Number(m[7]),
vszKb: Number(m[8]),
elapsed: m[9],
command: m[10],
});
continue;
}
const busyBoxTopMatch = trimmed.match(
/^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d+(?:\.\d+)?[mgtpezy]?)\s+([\d.]+)%?\s+(?:\d+\s+)?([\d.]+)%?\s+(.+)$/i,
);
if (busyBoxTopMatch) {
const suffix = busyBoxTopMatch[5].slice(-1).toLowerCase();
const multipliers = { m: 1024, g: 1024 ** 2, t: 1024 ** 3, p: 1024 ** 4, e: 1024 ** 5, z: 1024 ** 6, y: 1024 ** 7 };
const multiplier = multipliers[suffix] || 1;
processes.push({
pid: Number(busyBoxTopMatch[1]),
ppid: Number(busyBoxTopMatch[2]),
user: busyBoxTopMatch[3],
stat: busyBoxTopMatch[4],
cpuPercent: Number(busyBoxTopMatch[7]),
memPercent: Number(busyBoxTopMatch[6]),
rssKb: 0,
vszKb: Math.round(Number.parseFloat(busyBoxTopMatch[5]) * multiplier),
elapsed: "",
command: busyBoxTopMatch[8],
});
continue;
}
const busyBoxMatch = trimmed.match(/^(\d+)\s+(\S+)\s+(\d+(?:\.\d+)?[mgtpezy]?)\s+(\S+)\s+(.+)$/i);
if (!busyBoxMatch) continue;
const suffix = busyBoxMatch[3].slice(-1).toLowerCase();
const multipliers = { m: 1024, g: 1024 ** 2, t: 1024 ** 3, p: 1024 ** 4, e: 1024 ** 5, z: 1024 ** 6, y: 1024 ** 7 };
const multiplier = multipliers[suffix] || 1;
processes.push({
pid: Number(busyBoxMatch[1]),
ppid: 0,
user: busyBoxMatch[2],
stat: busyBoxMatch[4],
cpuPercent: 0,
memPercent: 0,
rssKb: 0,
vszKb: Math.round(Number.parseFloat(busyBoxMatch[3]) * multiplier),
elapsed: "",
command: busyBoxMatch[5],
});
}
return processes;
}
const ALLOWED_SIGNALS = new Set([
"TERM", "KILL", "STOP", "CONT", "HUP", "INT", "USR1", "USR2",
"1", "2", "9", "15", "18", "19",
]);
function buildProcessSignalCommand(pid, signal, nice) {
if (nice !== undefined && nice !== null) {
const n = Number(nice);
if (!Number.isFinite(n) || n < -20 || n > 19) {
return { error: "Invalid nice value" };
}
return { command: `renice ${Math.trunc(n)} -p ${Number(pid)}` };
}
const sig = String(signal || "TERM").toUpperCase();
if (!ALLOWED_SIGNALS.has(sig)) {
return { error: "Invalid signal" };
}
const numericPid = Number(pid);
if (!Number.isFinite(numericPid) || numericPid <= 0) {
return { error: "Invalid pid" };
}
if (sig === "KILL" || sig === "9") {
return { command: `kill -9 ${numericPid}` };
}
if (sig === "TERM" || sig === "15") {
return { command: `kill -15 ${numericPid}` };
}
if (/^\d+$/.test(sig)) {
return { command: `kill -${sig} ${numericPid}` };
}
return { command: `kill -s ${sig} ${numericPid}` };
}
function createSystemManagerBridge(deps) {
const {
getSessions,
execOnEtSession,
ensureMoshStatsConnection,
process,
} = deps;
const execApi = createExecOnSessionApi({
sessions: { get: (id) => getSessions()?.get(id) },
execOnEtSession,
ensureMoshStatsConnection,
});
const { execOnSession, execOnLocalMachine, isLocalSession, getSession } = execApi;
const tmuxOps = createTmuxOpsApi({ execOnSession });
const dockerOps = createDockerOpsApi({ execOnSession, getSession });
const gpuOps = createGpuOpsApi({
execOnSession,
execOnLocalMachine,
isLocalSession,
process,
});
const portOps = createPortOpsApi({
execOnSession,
execOnLocalMachine,
isLocalSession,
process,
});
const serviceOps = createServiceOpsApi({ execOnSession, getSession });
async function probeCapabilities(event, payload) {
const sessionId = payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
if (isLocalSession(sessionId)) {
const platform = process.platform;
let script = CAPABILITY_SCRIPT_POSIX;
if (platform === "win32") {
const result = await execOnLocalMachine(
[
'Write-Output "__NC_OS__=Windows"; ',
"if (Get-Command tmux -ErrorAction SilentlyContinue) { Write-Output '__NC_TMUX__=1' }; ",
"docker info 2>$null; if ($LASTEXITCODE -eq 0) { Write-Output '__NC_DOCKER__=1' }; ",
"if (Get-Command nvidia-smi -ErrorAction SilentlyContinue) { Write-Output '__NC_NVIDIA_SMI__=1' }; ",
"if (Get-Command npu-smi -ErrorAction SilentlyContinue) { Write-Output '__NC_NPU_SMI__=1' }; ",
// Local Windows uses Get-NetTCPConnection; treat as netstat-capable for tab visibility.
"Write-Output '__NC_NETSTAT__=1'; ",
"if (Get-Command ss -ErrorAction SilentlyContinue) { Write-Output '__NC_SS__=1' }; ",
"if (Get-Command lsof -ErrorAction SilentlyContinue) { Write-Output '__NC_LSOF__=1' }; ",
"if (Get-Command systemctl -ErrorAction SilentlyContinue) { Write-Output '__NC_SYSTEMCTL__=1' }",
].join(""),
8000,
);
if (!result.success) return { success: false, error: result.error || "Probe failed" };
return { success: true, capabilities: parseCapabilities(result.stdout, true, platform) };
}
const result = await execOnLocalMachine(
script.replace(/^exec sh -c '/, "").replace(/'$/, ""),
8000,
);
if (!result.success) {
const fallback = await execOnLocalMachine(
[
"uname -s; ",
"command -v tmux; ",
"command -v docker >/dev/null 2>&1 && echo docker_ok; ",
"command -v nvidia-smi >/dev/null 2>&1 && echo nvidia_ok; ",
"command -v npu-smi >/dev/null 2>&1 && echo npu_ok; ",
"command -v ss >/dev/null 2>&1 && echo ss_ok; ",
"command -v netstat >/dev/null 2>&1 && echo netstat_ok; ",
"command -v lsof >/dev/null 2>&1 && echo lsof_ok; ",
"command -v systemctl >/dev/null 2>&1 && echo systemctl_ok",
].join(""),
8000,
);
if (!fallback.success) return { success: false, error: fallback.error || "Probe failed" };
const text = fallback.stdout || "";
return {
success: true,
capabilities: {
targetOs: platform === "linux" ? "linux" : platform === "darwin" ? "darwin" : "unknown",
hasTmux: text.includes("tmux") && !text.includes("not found"),
hasDocker: text.includes("docker_ok"),
hasNvidiaSmi: text.includes("nvidia_ok"),
hasNpuSmi: text.includes("npu_ok"),
hasSs: text.includes("ss_ok"),
hasNetstat: text.includes("netstat_ok"),
hasLsof: text.includes("lsof_ok"),
hasSystemctl: text.includes("systemctl_ok"),
probedAt: Date.now(),
},
};
}
return { success: true, capabilities: parseCapabilities(result.stdout, true, platform) };
}
const posixResult = await execOnSession(event, sessionId, CAPABILITY_SCRIPT_POSIX, 8000);
if (posixResult.pending) return { success: false, pending: true };
console.log(`[ProbeCapabilities] POSIX result for session ${sessionId}: success=${posixResult.success}, code=${posixResult.code}, error=${JSON.stringify(posixResult.error||'').slice(0,120)}, stdoutSnippet=${JSON.stringify((posixResult.stdout||'').slice(0,200))}`);
if (posixResult.success) {
const parsed = parseCapabilities(posixResult.stdout, false, process.platform);
console.log(`[ProbeCapabilities] POSIX parsed: targetOs=${parsed.targetOs}, hasDocker=${parsed.hasDocker}, hasNetstat=${parsed.hasNetstat}, hasSystemctl=${parsed.hasSystemctl}`);
// If POSIX probe detected a real OS, trust it.
if (parsed.targetOs !== "unknown") {
return { success: true, capabilities: parsed };
}
}
// POSIX failed or got unknown OS — try Windows PowerShell probe.
console.log(`[ProbeCapabilities] POSIX gave unknown OS, falling back to PowerShell probe.`);
const psResult = await execOnSession(event, sessionId, CAPABILITY_PROBE_PS_COMMAND, 10000);
if (psResult.pending) return { success: false, pending: true };
console.log(`[ProbeCapabilities] PowerShell result: success=${psResult.success}, code=${psResult.code}, error=${JSON.stringify(psResult.error||'').slice(0,120)}, stdoutSnippet=${JSON.stringify((psResult.stdout||'').slice(0,200))}`);
if (psResult.success) {
const parsed = parseCapabilities(psResult.stdout, false, process.platform);
console.log(`[ProbeCapabilities] PowerShell parsed: targetOs=${parsed.targetOs}, hasDocker=${parsed.hasDocker}, hasNetstat=${parsed.hasNetstat}, hasSystemctl=${parsed.hasSystemctl}`);
if (parsed.targetOs !== "unknown") {
return { success: true, capabilities: parsed };
}
}
// Neither probe worked — return whatever POSIX had (or an unknown record).
if (!posixResult.success) return { success: false, error: posixResult.error || "Probe failed" };
return { success: true, capabilities: parseCapabilities(posixResult.stdout, false, process.platform) };
}
async function listProcesses(event, payload) {
const sessionId = payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
// Local Windows — already PowerShell.
if (isLocalSession(sessionId) && process.platform === "win32") {
const result = await execOnLocalMachine(
PROCESS_LIST_PS_COMMAND,
10000,
{ maxBuffer: PROCESS_LIST_MAX_BUFFER },
);
if (!result.success) return { success: false, error: result.error };
try {
const raw = JSON.parse(result.stdout || "[]");
const list = Array.isArray(raw) ? raw : [raw];
const processes = list.map((p) => ({
pid: Number(p.ProcessId),
ppid: Number(p.ParentProcessId) || 0,
user: "",
stat: "R",
cpuPercent: Number(p.CpuPercent) || 0,
memPercent: Number(p.MemPercent) || 0,
rssKb: Number(p.WorkingSetKb) || Math.round((Number(p.WorkingSetSize) || 0) / 1024),
vszKb: 0,
elapsed: String(p.Elapsed || ""),
command: String(p.CommandLine || p.Name || ""),
}));
return { success: true, processes };
} catch {
return { success: false, error: "Failed to parse process list" };
}
}
// POSIX first (Linux / macOS / BSD).
const posixResult = await execOnSession(event, sessionId, PROCESS_LIST_SCRIPT_POSIX, 12000, {
maxBuffer: PROCESS_LIST_MAX_BUFFER,
});
if (posixResult.pending) return { success: false, pending: true };
const posixOk = posixResult.success;
const posixProcesses = posixOk ? parseProcessLines(posixResult.stdout) : [];
// If POSIX gave zero processes, try Windows PowerShell (Windows OpenSSH host).
if (!posixOk || posixProcesses.length === 0) {
const psResult = await execOnSession(event, sessionId, PROCESS_LIST_PS_COMMAND, 12000, {
maxBuffer: PROCESS_LIST_MAX_BUFFER,
});
if (psResult.pending) return { success: false, pending: true };
if (psResult.success) {
try {
const raw = JSON.parse(psResult.stdout || "[]");
const list = Array.isArray(raw) ? raw : raw ? [raw] : [];
if (list.length > 0) {
const processes = list.map((p) => ({
pid: Number(p.ProcessId),
ppid: Number(p.ParentProcessId) || 0,
user: "",
stat: "R",
cpuPercent: Number(p.CpuPercent) || 0,
memPercent: Number(p.MemPercent) || 0,
rssKb: Number(p.WorkingSetKb) || 0,
vszKb: 0,
elapsed: String(p.Elapsed || ""),
command: String(p.CommandLine || p.Name || ""),
}));
return { success: true, processes };
}
} catch {
// PowerShell parse failed — fall back to POSIX result or original error.
}
}
}
if (!posixOk) return { success: false, error: posixResult.error || "Failed to list processes" };
return { success: true, processes: posixProcesses };
}
async function signalProcess(event, payload) {
const { sessionId, pid, signal = "TERM", nice } = payload || {};
if (!sessionId || !pid) return { success: false, error: "Missing sessionId or pid" };
const numericPid = Number(pid);
if (!Number.isFinite(numericPid) || numericPid <= 0) {
return { success: false, error: "Invalid pid" };
}
// Local Windows has no POSIX kill; map only TERM/KILL onto Stop-Process.
if (isLocalSession(sessionId) && process.platform === "win32") {
if (nice !== undefined && nice !== null) {
return { success: false, error: "renice is not supported on Windows" };
}
const sig = String(signal || "TERM").toUpperCase();
if (!(sig === "TERM" || sig === "15" || sig === "KILL" || sig === "9")) {
return { success: false, error: `signal ${sig} is not supported on Windows` };
}
const force = sig === "KILL" || sig === "9";
const ps = force
? `Stop-Process -Id ${Math.trunc(numericPid)} -Force -ErrorAction Stop`
: `Stop-Process -Id ${Math.trunc(numericPid)} -ErrorAction Stop`;
const result = await execOnLocalMachine(ps, 5000);
if (!result.success) return { success: false, error: result.error || "Stop-Process failed" };
if (typeof result.code === "number" && result.code !== 0) {
return {
success: false,
error: (result.stderr || result.error || `Stop-Process exited with code ${result.code}`).trim(),
code: result.code,
};
}
return { success: true, code: result.code };
}
const built = buildProcessSignalCommand(pid, signal, nice);
if (built.error) return { success: false, error: built.error };
const result = await execOnSession(event, sessionId, `exec sh -c ${JSON.stringify(built.command)}`, 5000);
if (result.pending) return { success: false, pending: true, error: result.error };
// POSIX worked.
if (result.success && (result.code === 0 || result.code == null)) {
return { success: true, code: result.code ?? 0 };
}
// POSIX failed — try Windows PowerShell Stop-Process.
const sig = String(signal || "TERM").toUpperCase();
const force = sig === "KILL" || sig === "9";
const psCmd = buildStopProcessPsCommand(pid, force);
if (psCmd) {
const psResult = await execOnSession(event, sessionId, psCmd, 8000);
if (psResult.pending) return { success: false, pending: true, error: psResult.error };
if (psResult.success && (psResult.code === 0 || psResult.code == null)) {
return { success: true, code: psResult.code ?? 0 };
}
}
if (!result.success) return { success: false, error: result.error };
if (typeof result.code === "number" && result.code !== 0) {
return {
success: false,
error: (result.stderr || result.error || `kill exited with code ${result.code}`).trim(),
code: result.code,
};
}
return { success: true, code: result.code };
}
async function setupOsc7Tracking(event, payload) {
const sessionId = payload?.sessionId;
const command = payload?.command;
if (!sessionId || typeof command !== "string" || !command.trim()) {
return { success: false, error: "Missing sessionId or command" };
}
const result = await execOnSession(event, sessionId, command, 10000);
if (result.pending) return { success: false, pending: true, error: result.error };
if (!result.success) return { success: false, error: result.error || "Directory tracking setup failed" };
if (typeof result.code === "number" && result.code !== 0) {
const error = String(result.stderr || result.error || `Directory tracking setup failed with exit code ${result.code}`).trim();
return {
success: false,
stdout: result.stdout || "",
stderr: result.stderr || "",
code: result.code,
error,
};
}
return {
success: true,
stdout: result.stdout || "",
stderr: result.stderr || "",
code: result.code ?? 0,
};
}
async function listTmuxSessions(event, payload) {
const sessionId = typeof payload === "string" ? payload : payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
return tmuxOps.listSessions(event, sessionId);
}
async function createTmuxSession(event, payload) {
return tmuxOps.createSession(event, payload);
}
async function listTmuxWindows(event, payload) {
return tmuxOps.listWindows(event, payload);
}
async function listTmuxPanes(event, payload) {
return tmuxOps.listPanes(event, payload);
}
async function listTmuxClients(event, payload) {
return tmuxOps.listClients(event, payload);
}
async function tmuxAction(event, payload) {
const result = await tmuxOps.tmuxAction(event, payload);
if (result.success === false && result.error) {
return { success: false, error: result.error || result.stderr };
}
if (result.success === false) {
return { success: false, error: result.stderr || "tmux command failed" };
}
return { success: true };
}
async function listDockerContainers(event, payload) {
const sessionId = payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
return dockerOps.listContainers(event, sessionId);
}
async function listDockerImages(event, payload) {
const sessionId = payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
return dockerOps.listImages(event, sessionId);
}
async function dockerStats(event, payload) {
return dockerOps.getStats(event, payload);
}
async function dockerInspect(event, payload) {
return dockerOps.inspectContainer(event, payload);
}
async function dockerImageInspect(event, payload) {
return dockerOps.inspectImage(event, payload);
}
async function dockerAction(event, payload) {
const result = await dockerOps.containerAction(event, payload);
if (result.success === false) {
return { success: false, error: result.error || result.stderr || "docker command failed" };
}
return { success: true };
}
async function dockerImageAction(event, payload) {
const result = await dockerOps.imageAction(event, payload);
if (result.success === false) {
return { success: false, error: result.error || result.stderr || "docker command failed" };
}
return { success: true, output: result.stdout };
}
async function listAccelerators(event, payload) {
const sessionId = payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
return gpuOps.listAccelerators(event, sessionId);
}
async function listListeningPorts(event, payload) {
const sessionId = payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
return portOps.listListeningPorts(event, sessionId);
}
async function listSystemServices(event, payload) {
const sessionId = payload?.sessionId;
if (!sessionId) return { success: false, error: "Missing sessionId" };
return serviceOps.listServices(event, sessionId);
}
async function systemServiceAction(event, payload) {
return serviceOps.serviceAction(event, payload);
}
function registerWorkerHandle(ipcMain, terminalWorkerManager, channel) {
ipcMain.handle(channel, (event, payload) => terminalWorkerManager.request(channel, payload, {
webContentsId: event?.sender?.id,
}));
}
function registerHandlers(ipcMain, options = {}) {
const terminalWorkerManager = options.terminalWorkerManager || null;
if (terminalWorkerManager) {
[
"netcatty:system:probeCapabilities",
"netcatty:system:listProcesses",
"netcatty:system:signalProcess",
"netcatty:system:setupOsc7Tracking",
"netcatty:system:listTmuxSessions",
"netcatty:system:createTmuxSession",
"netcatty:system:listTmuxWindows",
"netcatty:system:listTmuxPanes",
"netcatty:system:listTmuxClients",
"netcatty:system:tmuxAction",
"netcatty:system:listDockerContainers",
"netcatty:system:listDockerImages",
"netcatty:system:dockerStats",
"netcatty:system:dockerInspect",
"netcatty:system:dockerImageInspect",
"netcatty:system:dockerAction",
"netcatty:system:dockerImageAction",
"netcatty:system:listAccelerators",
"netcatty:system:listListeningPorts",
"netcatty:system:listSystemServices",
"netcatty:system:systemServiceAction",
].forEach((channel) => registerWorkerHandle(ipcMain, terminalWorkerManager, channel));
return;
}
ipcMain.handle("netcatty:system:probeCapabilities", probeCapabilities);
ipcMain.handle("netcatty:system:listProcesses", listProcesses);
ipcMain.handle("netcatty:system:signalProcess", signalProcess);
ipcMain.handle("netcatty:system:setupOsc7Tracking", setupOsc7Tracking);
ipcMain.handle("netcatty:system:listTmuxSessions", listTmuxSessions);
ipcMain.handle("netcatty:system:createTmuxSession", createTmuxSession);
ipcMain.handle("netcatty:system:listTmuxWindows", listTmuxWindows);
ipcMain.handle("netcatty:system:listTmuxPanes", listTmuxPanes);
ipcMain.handle("netcatty:system:listTmuxClients", listTmuxClients);
ipcMain.handle("netcatty:system:tmuxAction", tmuxAction);
ipcMain.handle("netcatty:system:listDockerContainers", listDockerContainers);
ipcMain.handle("netcatty:system:listDockerImages", listDockerImages);
ipcMain.handle("netcatty:system:dockerStats", dockerStats);
ipcMain.handle("netcatty:system:dockerInspect", dockerInspect);
ipcMain.handle("netcatty:system:dockerImageInspect", dockerImageInspect);
ipcMain.handle("netcatty:system:dockerAction", dockerAction);
ipcMain.handle("netcatty:system:dockerImageAction", dockerImageAction);
ipcMain.handle("netcatty:system:listAccelerators", listAccelerators);
ipcMain.handle("netcatty:system:listListeningPorts", listListeningPorts);
ipcMain.handle("netcatty:system:listSystemServices", listSystemServices);
ipcMain.handle("netcatty:system:systemServiceAction", systemServiceAction);
}
return { registerHandlers, probeCapabilities, listProcesses, signalProcess, setupOsc7Tracking };
}
module.exports = { createSystemManagerBridge };