mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-23 06:01:11 +00:00
* feat(linux): canvas via CLI-node + Tauri app IPC bridge * refactor: extract gateway helper modules * build(linux-canvas): register plugin package in lockfile * fix(linux-canvas): move canvas advertise test out of core, regen docs/protocol/deadcode * fix(gateway): break node-catalog/registry import cycle via leaf normalize module; add canvas glossary term * style: oxfmt invoke.ts and runtime.ts after buildNodeEventParams extraction * fix(linux): load Canvas WebView via dedicated data_directory context Wry's Linux/WebKitGTK incognito mode discards Tauri's registered WebContext (wry webkitgtk/mod.rs), so the Canvas window got a fresh ephemeral context without the openclaw-canvas:// scheme handler — the bundled A2UI page never committed (stayed about:blank) and every A2UI command timed out. Use an isolated cache-backed data_directory instead, which keeps the protocol handler while still isolating Canvas storage from the dashboard window. * fix(linux): keep Canvas WebView ephemeral via incognito + data_directory Autoreview flagged that a dedicated data_directory alone persists Canvas browser state (cookies, localStorage, IndexedDB, service workers) across restarts, so an agent that navigates Canvas to a site could leak an authenticated session into a later session. iOS uses a non-persistent store; Linux should match. Add .incognito(true) alongside .data_directory(): the distinct directory gives Tauri a fresh WebContext key so it still attaches the openclaw-canvas:// protocol closure, and incognito makes Wry swap in a fresh *ephemeral* context carrying those protocols. Live-verified on a Wayland/WebKitGTK box: the bundled page still loads (location.href=openclaw-canvas://localhost/index.html, openclawA2UI present, A2UI renders) and the canvas-webview dir holds no persistent cookie/storage files.
44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
export function resolveLinuxCanvasSocketPath(
|
|
env: NodeJS.ProcessEnv = process.env,
|
|
uid: number | undefined = process.getuid?.(),
|
|
): string {
|
|
const runtimeDir = env.XDG_RUNTIME_DIR?.trim();
|
|
if (runtimeDir) {
|
|
return path.join(runtimeDir, "openclaw-canvas.sock");
|
|
}
|
|
return path.join("/tmp", `openclaw-canvas-${uid ?? "unknown"}.sock`);
|
|
}
|
|
|
|
export function linuxCanvasSocketExists(socketPath: string): boolean {
|
|
try {
|
|
const stat = fs.lstatSync(socketPath);
|
|
const uid = process.geteuid?.() ?? process.getuid?.();
|
|
if (!stat.isSocket() || (uid !== undefined && stat.uid !== uid) || (stat.mode & 0o077) !== 0) {
|
|
return false;
|
|
}
|
|
const procSockets = fs.readFileSync("/proc/net/unix", "utf8");
|
|
return procSockets.split("\n").some((line) => line.endsWith(` ${socketPath}`));
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function watchLinuxCanvasSocket(socketPath: string, onChange: () => void): () => void {
|
|
const directory = path.dirname(socketPath);
|
|
const socketName = path.basename(socketPath);
|
|
try {
|
|
const watcher = fs.watch(directory, (_event, filename) => {
|
|
if (!filename || filename === socketName) {
|
|
onChange();
|
|
}
|
|
});
|
|
watcher.on("error", () => {});
|
|
return () => watcher.close();
|
|
} catch {
|
|
return () => {};
|
|
}
|
|
}
|