@phi-code-admin/camofox-browser 1.0.0 → 1.0.2

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.
Files changed (53) hide show
  1. package/AGENTS.md +571 -571
  2. package/Dockerfile +86 -86
  3. package/LICENSE +21 -21
  4. package/README.md +691 -691
  5. package/camofox.config.json +10 -10
  6. package/lib/auth.js +134 -134
  7. package/lib/camoufox-executable.js +189 -189
  8. package/lib/config.js +153 -153
  9. package/lib/cookies.js +119 -119
  10. package/lib/downloads.js +168 -168
  11. package/lib/extract.js +74 -74
  12. package/lib/fly.js +54 -54
  13. package/lib/images.js +88 -88
  14. package/lib/inflight.js +16 -16
  15. package/lib/launcher.js +47 -47
  16. package/lib/macros.js +31 -31
  17. package/lib/metrics.js +184 -184
  18. package/lib/openapi.js +105 -105
  19. package/lib/persistence.js +89 -89
  20. package/lib/plugins.js +178 -175
  21. package/lib/proxy.js +277 -277
  22. package/lib/reporter.js +1102 -1102
  23. package/lib/request-utils.js +59 -59
  24. package/lib/resources.js +76 -76
  25. package/lib/snapshot.js +41 -41
  26. package/lib/tmp-cleanup.js +108 -108
  27. package/lib/tracing.js +137 -137
  28. package/openclaw.plugin.json +268 -268
  29. package/package.json +148 -148
  30. package/plugin.ts +758 -758
  31. package/plugins/persistence/AGENTS.md +37 -37
  32. package/plugins/persistence/README.md +48 -48
  33. package/plugins/persistence/index.js +124 -124
  34. package/plugins/vnc/AGENTS.md +42 -42
  35. package/plugins/vnc/README.md +165 -165
  36. package/plugins/vnc/apt.txt +7 -7
  37. package/plugins/vnc/index.js +142 -142
  38. package/plugins/vnc/spawn.js +8 -8
  39. package/plugins/vnc/vnc-launcher.js +64 -64
  40. package/plugins/vnc/vnc-watcher.sh +82 -82
  41. package/plugins/youtube/AGENTS.md +25 -25
  42. package/plugins/youtube/apt.txt +1 -1
  43. package/plugins/youtube/index.js +206 -206
  44. package/plugins/youtube/post-install.sh +5 -5
  45. package/plugins/youtube/youtube.js +301 -301
  46. package/run.sh +37 -37
  47. package/scripts/exec.js +8 -8
  48. package/scripts/generate-openapi.js +24 -24
  49. package/scripts/install-plugin-deps.sh +63 -63
  50. package/scripts/plugin.js +342 -342
  51. package/scripts/sync-version.js +25 -25
  52. package/server.js +6062 -6059
  53. package/tsconfig.json +12 -12
@@ -1,64 +1,64 @@
1
- /**
2
- * VNC launcher -- owns all process spawning and env reads.
3
- * Isolated from route handlers to keep subprocess management separate.
4
- */
5
-
6
- import { spawn } from './spawn.js';
7
- import path from 'node:path';
8
- import { fileURLToPath } from 'node:url';
9
-
10
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
-
12
- /**
13
- * Resolve VNC configuration from pluginConfig + env var fallbacks.
14
- * All process.env reads live here -- callers get a plain config object.
15
- */
16
- export function resolveVncConfig(pluginConfig = {}) {
17
- const enabled = process.env.ENABLE_VNC === '1' || pluginConfig.enabled === true;
18
-
19
- const rawResolution = process.env.VNC_RESOLUTION || pluginConfig.resolution || '1920x1080';
20
- const resolution = rawResolution.includes('x', rawResolution.indexOf('x') + 1)
21
- ? rawResolution
22
- : `${rawResolution}x24`;
23
-
24
- const vncPassword = process.env.VNC_PASSWORD || pluginConfig.password || '';
25
- const viewOnly = process.env.VIEW_ONLY === '1' || pluginConfig.viewOnly === true;
26
- const vncPort = process.env.VNC_PORT || pluginConfig.vncPort || '5900';
27
- const novncPort = process.env.NOVNC_PORT || pluginConfig.novncPort || '6080';
28
-
29
- return { enabled, resolution, vncPassword, viewOnly, vncPort, novncPort };
30
- }
31
-
32
- /**
33
- * Start the vnc-watcher.sh child process.
34
- * Returns the spawned ChildProcess.
35
- */
36
- export function startWatcher({ resolution, vncPassword, viewOnly, vncPort, novncPort, log, events }) {
37
- const watcherPath = path.join(__dirname, 'vnc-watcher.sh');
38
- const watcher = spawn('sh', [watcherPath], {
39
- env: {
40
- ...process.env,
41
- VNC_PASSWORD: vncPassword,
42
- VNC_RESOLUTION: resolution,
43
- VIEW_ONLY: viewOnly ? '1' : '0',
44
- VNC_PORT: String(vncPort),
45
- NOVNC_PORT: String(novncPort),
46
- },
47
- stdio: ['ignore', 'inherit', 'inherit'],
48
- detached: false,
49
- });
50
-
51
- watcher.on('error', (err) => {
52
- log('error', 'vnc watcher failed to start', { error: err.message });
53
- });
54
-
55
- watcher.on('exit', (code, signal) => {
56
- log('warn', 'vnc watcher exited', { code, signal });
57
- events.emit('vnc:watcher:stopped', { code, signal });
58
- });
59
-
60
- log('info', 'vnc watcher started', { pid: watcher.pid });
61
- events.emit('vnc:watcher:started', { pid: watcher.pid });
62
-
63
- return watcher;
64
- }
1
+ /**
2
+ * VNC launcher -- owns all process spawning and env reads.
3
+ * Isolated from route handlers to keep subprocess management separate.
4
+ */
5
+
6
+ import { spawn } from './spawn.js';
7
+ import path from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+
12
+ /**
13
+ * Resolve VNC configuration from pluginConfig + env var fallbacks.
14
+ * All process.env reads live here -- callers get a plain config object.
15
+ */
16
+ export function resolveVncConfig(pluginConfig = {}) {
17
+ const enabled = process.env.ENABLE_VNC === '1' || pluginConfig.enabled === true;
18
+
19
+ const rawResolution = process.env.VNC_RESOLUTION || pluginConfig.resolution || '1920x1080';
20
+ const resolution = rawResolution.includes('x', rawResolution.indexOf('x') + 1)
21
+ ? rawResolution
22
+ : `${rawResolution}x24`;
23
+
24
+ const vncPassword = process.env.VNC_PASSWORD || pluginConfig.password || '';
25
+ const viewOnly = process.env.VIEW_ONLY === '1' || pluginConfig.viewOnly === true;
26
+ const vncPort = process.env.VNC_PORT || pluginConfig.vncPort || '5900';
27
+ const novncPort = process.env.NOVNC_PORT || pluginConfig.novncPort || '6080';
28
+
29
+ return { enabled, resolution, vncPassword, viewOnly, vncPort, novncPort };
30
+ }
31
+
32
+ /**
33
+ * Start the vnc-watcher.sh child process.
34
+ * Returns the spawned ChildProcess.
35
+ */
36
+ export function startWatcher({ resolution, vncPassword, viewOnly, vncPort, novncPort, log, events }) {
37
+ const watcherPath = path.join(__dirname, 'vnc-watcher.sh');
38
+ const watcher = spawn('sh', [watcherPath], {
39
+ env: {
40
+ ...process.env,
41
+ VNC_PASSWORD: vncPassword,
42
+ VNC_RESOLUTION: resolution,
43
+ VIEW_ONLY: viewOnly ? '1' : '0',
44
+ VNC_PORT: String(vncPort),
45
+ NOVNC_PORT: String(novncPort),
46
+ },
47
+ stdio: ['ignore', 'inherit', 'inherit'],
48
+ detached: false,
49
+ });
50
+
51
+ watcher.on('error', (err) => {
52
+ log('error', 'vnc watcher failed to start', { error: err.message });
53
+ });
54
+
55
+ watcher.on('exit', (code, signal) => {
56
+ log('warn', 'vnc watcher exited', { code, signal });
57
+ events.emit('vnc:watcher:stopped', { code, signal });
58
+ });
59
+
60
+ log('info', 'vnc watcher started', { pid: watcher.pid });
61
+ events.emit('vnc:watcher:started', { pid: watcher.pid });
62
+
63
+ return watcher;
64
+ }
@@ -1,82 +1,82 @@
1
- #!/bin/sh
2
- # VNC watcher: detects Camoufox's dynamically-assigned Xvfb display and attaches
3
- # x11vnc + noVNC to it. Handles browser restarts (re-attaches on display change).
4
- #
5
- # Called by the VNC plugin via child_process.spawn. Not meant to run standalone.
6
- #
7
- # Env vars (set by the plugin):
8
- # VNC_PASSWORD If set, x11vnc requires this password
9
- # VIEW_ONLY "1" for view-only mode
10
- # VNC_PORT VNC port (default: 5900)
11
- # NOVNC_PORT noVNC websocket port (default: 6080)
12
-
13
- set -e
14
-
15
- VNC_PORT="${VNC_PORT:-5900}"
16
- NOVNC_PORT="${NOVNC_PORT:-6080}"
17
- VNC_RESOLUTION="${VNC_RESOLUTION:-1920x1080x24}"
18
-
19
- log() { printf '[vnc-watcher] %s\n' "$*" >&2; }
20
-
21
- CURRENT_DISPLAY=""
22
- X11VNC_PID=""
23
-
24
- # Prepare password file if requested
25
- PASSFILE=""
26
- if [ -n "${VNC_PASSWORD:-}" ]; then
27
- mkdir -p /tmp/.vnc
28
- x11vnc -storepasswd "$VNC_PASSWORD" /tmp/.vnc/passwd >/dev/null 2>&1
29
- PASSFILE="/tmp/.vnc/passwd"
30
- log "x11vnc: password protected"
31
- else
32
- log "x11vnc: NO password (bind $NOVNC_PORT to 127.0.0.1 on host + SSH tunnel)"
33
- fi
34
-
35
- # Start noVNC (websockify) -- proxies to x11vnc regardless of whether it's up yet
36
- NOVNC_DIR="/usr/share/novnc"
37
- if [ ! -d "$NOVNC_DIR" ]; then
38
- log "ERROR: $NOVNC_DIR not found; noVNC cannot start"
39
- exit 1
40
- fi
41
- VNC_BIND="${VNC_BIND:-127.0.0.1}"
42
- log "Starting noVNC (websockify) on $VNC_BIND:$NOVNC_PORT -> 127.0.0.1:$VNC_PORT"
43
- websockify --web "$NOVNC_DIR" "$VNC_BIND:$NOVNC_PORT" "127.0.0.1:$VNC_PORT" >/var/log/novnc.log 2>&1 &
44
-
45
- log "VNC watcher started -- will attach x11vnc when Camoufox's Xvfb appears"
46
-
47
- while true; do
48
- # Find Xvfb with our patched resolution
49
- FOUND=$(ps -eo args= 2>/dev/null | awk -v res="$VNC_RESOLUTION" '
50
- /\/Xvfb :[0-9]+/ && index($0, res) {
51
- for (i=1;i<=NF;i++) if ($i ~ /^:[0-9]+$/) { print $i; exit }
52
- }
53
- ' | head -1)
54
-
55
- if [ -n "$FOUND" ] && [ "$FOUND" != "$CURRENT_DISPLAY" ]; then
56
- # New or changed display -- (re)attach x11vnc
57
- if [ -n "$X11VNC_PID" ] && kill -0 "$X11VNC_PID" 2>/dev/null; then
58
- log "Camoufox display changed ($CURRENT_DISPLAY -> $FOUND), restarting x11vnc"
59
- kill "$X11VNC_PID" 2>/dev/null || true
60
- sleep 0.5
61
- fi
62
-
63
- CURRENT_DISPLAY="$FOUND"
64
- log "Attaching x11vnc to DISPLAY=$CURRENT_DISPLAY"
65
-
66
- X11VNC_ARGS="-display $CURRENT_DISPLAY -forever -shared -rfbport $VNC_PORT -noxdamage -quiet -bg -o /var/log/x11vnc.log"
67
- [ "${VIEW_ONLY:-0}" = "1" ] && X11VNC_ARGS="$X11VNC_ARGS -viewonly"
68
- if [ -n "$PASSFILE" ]; then
69
- X11VNC_ARGS="$X11VNC_ARGS -rfbauth $PASSFILE"
70
- else
71
- X11VNC_ARGS="$X11VNC_ARGS -nopw"
72
- fi
73
-
74
- # shellcheck disable=SC2086
75
- x11vnc $X11VNC_ARGS
76
- sleep 1
77
- X11VNC_PID=$(pgrep -f "x11vnc.*-display $CURRENT_DISPLAY" | head -1)
78
- log "x11vnc running (pid=$X11VNC_PID) on DISPLAY=$CURRENT_DISPLAY"
79
- fi
80
-
81
- sleep 2
82
- done
1
+ #!/bin/sh
2
+ # VNC watcher: detects Camoufox's dynamically-assigned Xvfb display and attaches
3
+ # x11vnc + noVNC to it. Handles browser restarts (re-attaches on display change).
4
+ #
5
+ # Called by the VNC plugin via child_process.spawn. Not meant to run standalone.
6
+ #
7
+ # Env vars (set by the plugin):
8
+ # VNC_PASSWORD If set, x11vnc requires this password
9
+ # VIEW_ONLY "1" for view-only mode
10
+ # VNC_PORT VNC port (default: 5900)
11
+ # NOVNC_PORT noVNC websocket port (default: 6080)
12
+
13
+ set -e
14
+
15
+ VNC_PORT="${VNC_PORT:-5900}"
16
+ NOVNC_PORT="${NOVNC_PORT:-6080}"
17
+ VNC_RESOLUTION="${VNC_RESOLUTION:-1920x1080x24}"
18
+
19
+ log() { printf '[vnc-watcher] %s\n' "$*" >&2; }
20
+
21
+ CURRENT_DISPLAY=""
22
+ X11VNC_PID=""
23
+
24
+ # Prepare password file if requested
25
+ PASSFILE=""
26
+ if [ -n "${VNC_PASSWORD:-}" ]; then
27
+ mkdir -p /tmp/.vnc
28
+ x11vnc -storepasswd "$VNC_PASSWORD" /tmp/.vnc/passwd >/dev/null 2>&1
29
+ PASSFILE="/tmp/.vnc/passwd"
30
+ log "x11vnc: password protected"
31
+ else
32
+ log "x11vnc: NO password (bind $NOVNC_PORT to 127.0.0.1 on host + SSH tunnel)"
33
+ fi
34
+
35
+ # Start noVNC (websockify) -- proxies to x11vnc regardless of whether it's up yet
36
+ NOVNC_DIR="/usr/share/novnc"
37
+ if [ ! -d "$NOVNC_DIR" ]; then
38
+ log "ERROR: $NOVNC_DIR not found; noVNC cannot start"
39
+ exit 1
40
+ fi
41
+ VNC_BIND="${VNC_BIND:-127.0.0.1}"
42
+ log "Starting noVNC (websockify) on $VNC_BIND:$NOVNC_PORT -> 127.0.0.1:$VNC_PORT"
43
+ websockify --web "$NOVNC_DIR" "$VNC_BIND:$NOVNC_PORT" "127.0.0.1:$VNC_PORT" >/var/log/novnc.log 2>&1 &
44
+
45
+ log "VNC watcher started -- will attach x11vnc when Camoufox's Xvfb appears"
46
+
47
+ while true; do
48
+ # Find Xvfb with our patched resolution
49
+ FOUND=$(ps -eo args= 2>/dev/null | awk -v res="$VNC_RESOLUTION" '
50
+ /\/Xvfb :[0-9]+/ && index($0, res) {
51
+ for (i=1;i<=NF;i++) if ($i ~ /^:[0-9]+$/) { print $i; exit }
52
+ }
53
+ ' | head -1)
54
+
55
+ if [ -n "$FOUND" ] && [ "$FOUND" != "$CURRENT_DISPLAY" ]; then
56
+ # New or changed display -- (re)attach x11vnc
57
+ if [ -n "$X11VNC_PID" ] && kill -0 "$X11VNC_PID" 2>/dev/null; then
58
+ log "Camoufox display changed ($CURRENT_DISPLAY -> $FOUND), restarting x11vnc"
59
+ kill "$X11VNC_PID" 2>/dev/null || true
60
+ sleep 0.5
61
+ fi
62
+
63
+ CURRENT_DISPLAY="$FOUND"
64
+ log "Attaching x11vnc to DISPLAY=$CURRENT_DISPLAY"
65
+
66
+ X11VNC_ARGS="-display $CURRENT_DISPLAY -forever -shared -rfbport $VNC_PORT -noxdamage -quiet -bg -o /var/log/x11vnc.log"
67
+ [ "${VIEW_ONLY:-0}" = "1" ] && X11VNC_ARGS="$X11VNC_ARGS -viewonly"
68
+ if [ -n "$PASSFILE" ]; then
69
+ X11VNC_ARGS="$X11VNC_ARGS -rfbauth $PASSFILE"
70
+ else
71
+ X11VNC_ARGS="$X11VNC_ARGS -nopw"
72
+ fi
73
+
74
+ # shellcheck disable=SC2086
75
+ x11vnc $X11VNC_ARGS
76
+ sleep 1
77
+ X11VNC_PID=$(pgrep -f "x11vnc.*-display $CURRENT_DISPLAY" | head -1)
78
+ log "x11vnc running (pid=$X11VNC_PID) on DISPLAY=$CURRENT_DISPLAY"
79
+ fi
80
+
81
+ sleep 2
82
+ done
@@ -1,25 +1,25 @@
1
- # YouTube Plugin — Agent Guide
2
-
3
- Extracts video transcripts via yt-dlp (preferred) with Playwright browser fallback.
4
-
5
- ## Endpoint
6
-
7
- `POST /youtube/transcript` — unauthenticated by default (set `"auth": true` in plugin config to require auth).
8
-
9
- ## Key Files
10
-
11
- - `index.js` — route handler + browser fallback logic
12
- - `youtube.js` — yt-dlp process management + transcript parsing (`child_process` isolated here)
13
- - `youtube.test.js` — parser unit tests
14
- - `apt.txt` — system deps (python3-minimal for yt-dlp)
15
- - `post-install.sh` — downloads yt-dlp binary
16
-
17
- ## Code Separation
18
-
19
- `child_process` is in `youtube.js`, route handlers are in `index.js` — separate files per project conventions.
20
-
21
- ## Maintainers
22
-
23
- - [@pradeepe](https://github.com/pradeepe) — extracted from core into plugin system
24
-
25
- For PRs touching this plugin, tag the maintainers above for review.
1
+ # YouTube Plugin — Agent Guide
2
+
3
+ Extracts video transcripts via yt-dlp (preferred) with Playwright browser fallback.
4
+
5
+ ## Endpoint
6
+
7
+ `POST /youtube/transcript` — unauthenticated by default (set `"auth": true` in plugin config to require auth).
8
+
9
+ ## Key Files
10
+
11
+ - `index.js` — route handler + browser fallback logic
12
+ - `youtube.js` — yt-dlp process management + transcript parsing (`child_process` isolated here)
13
+ - `youtube.test.js` — parser unit tests
14
+ - `apt.txt` — system deps (python3-minimal for yt-dlp)
15
+ - `post-install.sh` — downloads yt-dlp binary
16
+
17
+ ## Code Separation
18
+
19
+ `child_process` is in `youtube.js`, route handlers are in `index.js` — separate files per project conventions.
20
+
21
+ ## Maintainers
22
+
23
+ - [@pradeepe](https://github.com/pradeepe) — extracted from core into plugin system
24
+
25
+ For PRs touching this plugin, tag the maintainers above for review.
@@ -1 +1 @@
1
- python3-minimal
1
+ python3-minimal