@ozaiya/openclaw-channel 0.10.16 → 0.10.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,33 +2,37 @@
2
2
  * Records the bot's sandbox/desktop display (Xvfb :1) to an MP4 while a task
3
3
  * runs, so the chat app can replay the task as synchronized video + steps.
4
4
  *
5
- * Recording happens gateway-side because tasks run unattended — the user
6
- * replays them later. We shell out to ffmpeg's x11grab inside the container
7
- * (where DISPLAY=:1 lives), then extract the file via `docker cp`.
5
+ * Three modes, chosen automatically:
6
+ * - "docker" (host gateway): the recorder runs on the host and `docker exec`s
7
+ * ffmpeg into the browser/desktop container, then `docker cp`s the file out.
8
+ * - "http" (compose gateway, e.g. test-two): the agent runs INSIDE a container
9
+ * that has no display — the display lives in a sibling browser container. We
10
+ * can't x11grab it, so the browser container runs a tiny recording-control
11
+ * HTTP server (POST /start, POST /stop -> mp4 bytes) reachable at NOVNC_HOST.
12
+ * - "self" (single-container deployments): record the local :1 directly.
8
13
  *
9
- * Reuses the Docker helpers from desktopContainer.ts. If no recordable
10
- * container exists, or ffmpeg isn't present in the image, startRecording()
11
- * returns null and the task simply has no video (steps-only replay).
14
+ * Best-effort throughout: any failure -> null -> the task has steps-only replay.
12
15
  */
13
16
  import { type ChildProcess } from "node:child_process";
14
17
  export interface RecordingHandle {
15
- containerId: string;
16
- /** Path of the in-container MP4 being written. */
17
- remotePath: string;
18
+ mode: "self" | "docker" | "http";
19
+ /** docker/self mode: the container id ("self") and in-container mp4 path. */
20
+ containerId?: string;
21
+ remotePath?: string;
22
+ proc?: ChildProcess | null;
23
+ /** http mode: base URL of the browser container's recording-control server. */
24
+ controlUrl?: string;
18
25
  /** Date.now() at recording start — the t=0 baseline for step offsets. */
19
26
  startedAt: number;
20
- proc: ChildProcess | null;
21
27
  display: string;
22
28
  }
23
29
  /**
24
- * Start recording the container display. Returns a handle, or null if there's
25
- * nothing to record / ffmpeg is unavailable (the caller treats null as
26
- * "steps-only, no video").
30
+ * Start recording. Returns a handle, or null when nothing is recordable
31
+ * (caller treats null as "steps-only, no video").
27
32
  */
28
33
  export declare function startRecording(taskId: string): RecordingHandle | null;
29
34
  /**
30
- * Stop recording cleanly (SIGINT so the moov atom is finalized) and return the
31
- * MP4 bytes + duration. Returns null on any failure.
35
+ * Stop recording and return the MP4 bytes + duration. Returns null on any failure.
32
36
  */
33
37
  export declare function stopAndExtractRecording(handle: RecordingHandle): Promise<{
34
38
  mp4: Buffer;
@@ -2,26 +2,29 @@
2
2
  * Records the bot's sandbox/desktop display (Xvfb :1) to an MP4 while a task
3
3
  * runs, so the chat app can replay the task as synchronized video + steps.
4
4
  *
5
- * Recording happens gateway-side because tasks run unattended — the user
6
- * replays them later. We shell out to ffmpeg's x11grab inside the container
7
- * (where DISPLAY=:1 lives), then extract the file via `docker cp`.
5
+ * Three modes, chosen automatically:
6
+ * - "docker" (host gateway): the recorder runs on the host and `docker exec`s
7
+ * ffmpeg into the browser/desktop container, then `docker cp`s the file out.
8
+ * - "http" (compose gateway, e.g. test-two): the agent runs INSIDE a container
9
+ * that has no display — the display lives in a sibling browser container. We
10
+ * can't x11grab it, so the browser container runs a tiny recording-control
11
+ * HTTP server (POST /start, POST /stop -> mp4 bytes) reachable at NOVNC_HOST.
12
+ * - "self" (single-container deployments): record the local :1 directly.
8
13
  *
9
- * Reuses the Docker helpers from desktopContainer.ts. If no recordable
10
- * container exists, or ffmpeg isn't present in the image, startRecording()
11
- * returns null and the task simply has no video (steps-only replay).
14
+ * Best-effort throughout: any failure -> null -> the task has steps-only replay.
12
15
  */
13
16
  import { execSync, spawn } from "node:child_process";
14
17
  import * as fs from "node:fs";
15
18
  import * as os from "node:os";
16
19
  import * as path from "node:path";
17
20
  import { docker, dockerEnv, dockerExec, isInContainer } from "./desktopContainer.js";
21
+ const RECORD_CONTROL_PORT = process.env.RECORD_CONTROL_PORT || "8091";
18
22
  /** Find a running container whose display we can record (sandbox browser, then desktop). */
19
23
  function findRecordableContainer() {
20
- if (isInContainer)
21
- return "self";
22
24
  const filters = [
23
25
  "docker ps -q --filter 'label=openclaw.sandboxBrowser=1'",
24
26
  "docker ps -q --filter 'name=sandbox-browser'",
27
+ "docker ps -q --filter 'ancestor=openclaw-sandbox-browser:bookworm-slim'",
25
28
  "docker ps -q --filter 'label=ozaiya.desktop=1'",
26
29
  ];
27
30
  for (const f of filters) {
@@ -36,7 +39,6 @@ function findRecordableContainer() {
36
39
  }
37
40
  return null;
38
41
  }
39
- /** Whether ffmpeg is available inside the container (or on the host, when in-container). */
40
42
  function hasFfmpeg(containerId) {
41
43
  try {
42
44
  if (containerId === "self") {
@@ -54,89 +56,93 @@ function hasFfmpeg(containerId) {
54
56
  function sanitize(taskId) {
55
57
  return taskId.replace(/[^a-zA-Z0-9_.-]/g, "_");
56
58
  }
59
+ function ffArgs(display, out) {
60
+ return [
61
+ "-y", "-f", "x11grab", "-draw_mouse", "1", "-framerate", "8",
62
+ "-i", display, "-codec:v", "libx264", "-preset", "veryfast",
63
+ "-pix_fmt", "yuv420p", "-movflags", "+faststart", out,
64
+ ];
65
+ }
57
66
  /**
58
- * Start recording the container display. Returns a handle, or null if there's
59
- * nothing to record / ffmpeg is unavailable (the caller treats null as
60
- * "steps-only, no video").
67
+ * Start recording. Returns a handle, or null when nothing is recordable
68
+ * (caller treats null as "steps-only, no video").
61
69
  */
62
70
  export function startRecording(taskId) {
63
- const containerId = findRecordableContainer();
71
+ const display = process.env.RECORD_DISPLAY || ":1";
72
+ const startedAt = Date.now();
73
+ // Compose mode: agent container + separate browser container (NOVNC_HOST set).
74
+ // The browser container hosts the recording-control server.
75
+ if (isInContainer && process.env.NOVNC_HOST) {
76
+ const controlUrl = `http://${process.env.NOVNC_HOST}:${RECORD_CONTROL_PORT}`;
77
+ // Fire-and-forget; if the control server is absent the POST just fails.
78
+ fetch(`${controlUrl}/start`, { method: "POST", signal: AbortSignal.timeout(8000) }).catch(() => { });
79
+ return { mode: "http", controlUrl, startedAt, display };
80
+ }
81
+ const containerId = findRecordableContainer() ?? (isInContainer ? "self" : null);
64
82
  if (!containerId)
65
83
  return null;
66
84
  if (!hasFfmpeg(containerId))
67
85
  return null;
68
- const display = process.env.RECORD_DISPLAY || ":1";
69
86
  const remotePath = `/tmp/rec-${sanitize(taskId)}.mp4`;
70
- const ffArgs = [
71
- "-y",
72
- "-f", "x11grab",
73
- "-draw_mouse", "1",
74
- "-framerate", "8",
75
- "-i", display,
76
- "-codec:v", "libx264",
77
- "-preset", "veryfast",
78
- "-pix_fmt", "yuv420p",
79
- "-movflags", "+faststart",
80
- remotePath,
81
- ];
87
+ const args = ffArgs(display, remotePath);
82
88
  let proc;
83
89
  if (containerId === "self") {
84
- proc = spawn("ffmpeg", ffArgs, { env: process.env, stdio: "ignore" });
90
+ proc = spawn("ffmpeg", args, { env: process.env, stdio: "ignore" });
85
91
  }
86
92
  else {
87
- // dockerEnv extends PATH with the standard Docker install locations.
88
- proc = spawn("docker", ["exec", containerId, "ffmpeg", ...ffArgs], { env: dockerEnv, stdio: "ignore" });
93
+ proc = spawn("docker", ["exec", containerId, "ffmpeg", ...args], { env: dockerEnv, stdio: "ignore" });
89
94
  }
90
95
  proc.unref?.();
91
96
  proc.on("error", () => { });
92
- return { containerId, remotePath, startedAt: Date.now(), proc, display };
97
+ return { mode: containerId === "self" ? "self" : "docker", containerId, remotePath, proc, startedAt, display };
93
98
  }
94
99
  /**
95
- * Stop recording cleanly (SIGINT so the moov atom is finalized) and return the
96
- * MP4 bytes + duration. Returns null on any failure.
100
+ * Stop recording and return the MP4 bytes + duration. Returns null on any failure.
97
101
  */
98
102
  export async function stopAndExtractRecording(handle) {
103
+ const durationMs = Date.now() - handle.startedAt;
99
104
  try {
100
- // Send SIGINT to ffmpeg INSIDE the container so it finalizes the file.
101
- const interrupt = `pkill -INT -f '${handle.remotePath}'`;
105
+ if (handle.mode === "http") {
106
+ const res = await fetch(`${handle.controlUrl}/stop`, { method: "POST", signal: AbortSignal.timeout(30_000) });
107
+ if (!res.ok)
108
+ return null;
109
+ const mp4 = Buffer.from(await res.arrayBuffer());
110
+ return mp4.length > 0 ? { mp4, durationMs } : null;
111
+ }
112
+ const cid = handle.containerId;
113
+ const remotePath = handle.remotePath;
114
+ // SIGINT ffmpeg INSIDE the container so it finalizes the moov atom.
115
+ const interrupt = `pkill -INT -f '${remotePath}'`;
102
116
  try {
103
- if (handle.containerId === "self") {
117
+ if (cid === "self")
104
118
  execSync(interrupt, { timeout: 5000, env: process.env });
105
- }
106
- else {
107
- dockerExec(handle.containerId, interrupt, 5000);
108
- }
109
- }
110
- catch {
111
- /* maybe already exiting */
119
+ else
120
+ dockerExec(cid, interrupt, 5000);
112
121
  }
113
- // Give ffmpeg a moment to write the moov atom before we read the file.
122
+ catch { /* maybe already exiting */ }
114
123
  await new Promise((r) => setTimeout(r, 1500));
115
124
  let mp4;
116
- if (handle.containerId === "self") {
117
- mp4 = fs.readFileSync(handle.remotePath);
125
+ if (cid === "self") {
126
+ mp4 = fs.readFileSync(remotePath);
118
127
  }
119
128
  else {
120
129
  const hostTmp = path.join(os.tmpdir(), `ozaiya-rec-${handle.startedAt}.mp4`);
121
- docker(`cp ${handle.containerId}:${handle.remotePath} ${hostTmp}`, 30_000);
130
+ docker(`cp ${cid}:${remotePath} ${hostTmp}`, 30_000);
122
131
  mp4 = fs.readFileSync(hostTmp);
123
132
  try {
124
133
  fs.unlinkSync(hostTmp);
125
134
  }
126
135
  catch { /* ignore */ }
127
136
  }
128
- // Best-effort cleanup of the in-container file.
129
137
  try {
130
- const rm = `rm -f ${handle.remotePath}`;
131
- if (handle.containerId === "self")
138
+ const rm = `rm -f ${remotePath}`;
139
+ if (cid === "self")
132
140
  execSync(rm, { timeout: 5000 });
133
141
  else
134
- dockerExec(handle.containerId, rm, 5000);
142
+ dockerExec(cid, rm, 5000);
135
143
  }
136
144
  catch { /* ignore */ }
137
- if (!mp4 || mp4.length === 0)
138
- return null;
139
- return { mp4, durationMs: Date.now() - handle.startedAt };
145
+ return mp4 && mp4.length > 0 ? { mp4, durationMs } : null;
140
146
  }
141
147
  catch {
142
148
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"desktopRecorder.js","sourceRoot":"","sources":["../../src/desktopRecorder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"desktopRecorder.js","sourceRoot":"","sources":["../../src/desktopRecorder.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ozaiya/openclaw-channel",
3
- "version": "0.10.16",
3
+ "version": "0.10.17",
4
4
  "description": "OpenClaw channel plugin for Ozaiya Chat",
5
5
  "license": "MIT",
6
6
  "type": "module",