@rubytech/create-maxy-code 0.1.614 → 0.1.615
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.
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +5 -0
- package/payload/platform/plugins/browser/PLUGIN.md +1 -1
- package/payload/platform/scripts/__tests__/vnc-cdp-liveness.test.sh +270 -19
- package/payload/platform/scripts/vnc.sh +174 -71
- package/payload/server/server.js +413 -250
|
@@ -8,14 +8,16 @@
|
|
|
8
8
|
# Xtigervnc :${VNC_DISPLAY} — virtual X11 display per brand
|
|
9
9
|
# Xtigervnc -rfbport ${RFB_PORT} — RFB port per brand
|
|
10
10
|
# websockify :${WEBSOCKIFY_PORT} — WebSocket bridge per brand
|
|
11
|
-
# Chromium —
|
|
11
|
+
# Chromium — browser with --user-data-dir per brand
|
|
12
12
|
# CDP :${CDP_PORT} — browser plugin (browser-render) CDP endpoint per brand
|
|
13
13
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
14
|
+
# Virtual-mode Chromium is HEADED on the brand's Xtigervnc display. Task 1562
|
|
15
|
+
# made it headless on 2026-07-30 and commit b1b007b03 reverted that the next
|
|
16
|
+
# day: Cloudflare's managed challenge on claude.ai refuses `--headless=new`, so
|
|
17
|
+
# Claude sign-in could never complete. Every consumer (agent browser-* tools,
|
|
18
|
+
# the operator screencast viewer, the Claude sign-in browser) is still a CDP
|
|
19
|
+
# client on ${CDP_PORT} rather than a reader of the RFB port; retiring the
|
|
20
|
+
# now-unread RFB and websockify components is Task 2198.
|
|
19
21
|
#
|
|
20
22
|
# Brand isolation (Tasks 553 + 924): the X display number, Chromium profile,
|
|
21
23
|
# rfbport, websockify port, and CDP port are all brand-scoped so any number
|
|
@@ -41,11 +43,18 @@
|
|
|
41
43
|
# cloudflare-setup actions run via the detached action runner
|
|
42
44
|
# (/api/admin/actions/*) rather than an in-browser terminal.
|
|
43
45
|
#
|
|
44
|
-
# Display modes
|
|
45
|
-
#
|
|
46
|
+
# Display modes, set by the installer --display flag and recorded in the brand
|
|
47
|
+
# .env. resolve_display_mode() is the ONLY reader of DISPLAY_MODE in this
|
|
48
|
+
# script: it prefers the environment variable and falls back to the .env,
|
|
49
|
+
# defaulting to virtual. No unit file in the fleet exports the variable, so a
|
|
50
|
+
# second reader taking the env var directly always resolved to virtual and
|
|
51
|
+
# silently disagreed with the .env — Task 2780.
|
|
52
|
+
# virtual (default) — Chromium runs headed on the brand's Xtigervnc display
|
|
46
53
|
# native — Chromium runs on the login session's real display
|
|
47
54
|
# (discovered via loginctl, NOT from $DISPLAY which
|
|
48
55
|
# is poisoned by the systemd Environment=DISPLAY line)
|
|
56
|
+
# Both modes are supervised by the standing cdp-liveness check; only the launch
|
|
57
|
+
# precondition differs.
|
|
49
58
|
|
|
50
59
|
set -uo pipefail
|
|
51
60
|
|
|
@@ -183,10 +192,23 @@ resolve_websockify_bind() {
|
|
|
183
192
|
# The standing cdp-liveness probe runs every rss-sampler cycle; skip this
|
|
184
193
|
# per-invocation resolution line on that path so vnc-boot.log is not spammed.
|
|
185
194
|
# The FATAL guards above still run (and hard-exit) on every invocation.
|
|
195
|
+
#
|
|
196
|
+
# PER_CYCLE=1 marks that path for every other would-be per-cycle writer too.
|
|
197
|
+
# vnc-boot.log is NOT one of logs-rotate.sh's targets, so nothing bounds it: a
|
|
198
|
+
# writer that fires once per 30s cycle grows it without limit. Keep this file
|
|
199
|
+
# event-driven and let the per-cycle signal go to stdout, which is the
|
|
200
|
+
# rss-sampler's journal and is bounded by journald.
|
|
201
|
+
PER_CYCLE=0
|
|
186
202
|
if [ "${1:-}" != "cdp-liveness" ]; then
|
|
187
203
|
log "[vnc.sh:chromium] bin=${CHROMIUM_BIN} realpath=${CHROMIUM_REALPATH} confinement=${CHROMIUM_CONFINEMENT}"
|
|
204
|
+
else
|
|
205
|
+
PER_CYCLE=1
|
|
188
206
|
fi
|
|
189
207
|
|
|
208
|
+
# log() that is a no-op on the per-cycle path. For detail that is worth having
|
|
209
|
+
# when a launch is attempted but must not accumulate once per cycle forever.
|
|
210
|
+
log_event() { [ "$PER_CYCLE" -eq 1 ] || log "$@"; }
|
|
211
|
+
|
|
190
212
|
kill_stale() {
|
|
191
213
|
# Brand-scoped matchers: pkill on --user-data-dir narrows the
|
|
192
214
|
# Chromium kill to this brand's profile only, so two brands on the same
|
|
@@ -291,52 +313,75 @@ check_window_on_display() {
|
|
|
291
313
|
DISPLAY="$display" xdotool search --onlyvisible --class '[Cc]hrom' >/dev/null 2>&1
|
|
292
314
|
}
|
|
293
315
|
|
|
294
|
-
# Discover the login session
|
|
316
|
+
# Discover the login session Chromium should render onto, by evidence.
|
|
295
317
|
# Uses loginctl (systemd) to bypass the poisoned $DISPLAY env var.
|
|
296
|
-
#
|
|
297
|
-
#
|
|
298
|
-
#
|
|
318
|
+
#
|
|
319
|
+
# Selection is over EVERY listed session, not the first row: on a box with
|
|
320
|
+
# remote tty sessions the first row is one of those, it reports an empty
|
|
321
|
+
# Display, and the old `:0` substitution then reached the right screen by
|
|
322
|
+
# accident on a single-seat desktop and the wrong screen — or none — anywhere
|
|
323
|
+
# else, while still reporting success. A session qualifies only when it is
|
|
324
|
+
# Active=yes, Remote=no, and Type x11 or wayland.
|
|
325
|
+
#
|
|
326
|
+
# Returns 0 with NATIVE_SESSION_TYPE (x11|wayland), NATIVE_DISPLAY and
|
|
327
|
+
# NATIVE_WAYLAND_DISPLAY set. Returns 1 with NATIVE_DISPLAY UNSET, so a caller
|
|
328
|
+
# that ignores the exit status still cannot launch onto a guess.
|
|
299
329
|
discover_native_session() {
|
|
300
|
-
NATIVE_SESSION_TYPE="
|
|
301
|
-
NATIVE_DISPLAY=":0"
|
|
330
|
+
NATIVE_SESSION_TYPE=""
|
|
302
331
|
NATIVE_WAYLAND_DISPLAY=""
|
|
332
|
+
unset NATIVE_DISPLAY
|
|
303
333
|
|
|
304
334
|
if ! command -v loginctl >/dev/null 2>&1; then
|
|
305
|
-
|
|
306
|
-
return
|
|
335
|
+
log_event "[vnc.sh:native] no-graphical-session reason=loginctl-absent"
|
|
336
|
+
return 1
|
|
307
337
|
fi
|
|
308
338
|
|
|
309
|
-
local session_id
|
|
310
|
-
|
|
311
|
-
if [ -z "$
|
|
312
|
-
|
|
313
|
-
return
|
|
339
|
+
local session_ids session_id active remote session_type session_display leader_pid
|
|
340
|
+
session_ids=$(loginctl list-sessions --no-legend 2>/dev/null | awk '{print $1}')
|
|
341
|
+
if [ -z "$session_ids" ]; then
|
|
342
|
+
log_event "[vnc.sh:native] no-graphical-session reason=no-sessions-listed"
|
|
343
|
+
return 1
|
|
314
344
|
fi
|
|
315
345
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
346
|
+
for session_id in $session_ids; do
|
|
347
|
+
active=$(loginctl show-session "$session_id" -p Active --value 2>/dev/null)
|
|
348
|
+
[ "$active" = "yes" ] || continue
|
|
349
|
+
remote=$(loginctl show-session "$session_id" -p Remote --value 2>/dev/null)
|
|
350
|
+
[ "$remote" = "no" ] || continue
|
|
351
|
+
session_type=$(loginctl show-session "$session_id" -p Type --value 2>/dev/null)
|
|
352
|
+
case "$session_type" in x11|wayland) ;; *) continue ;; esac
|
|
353
|
+
|
|
354
|
+
session_display=$(loginctl show-session "$session_id" -p Display --value 2>/dev/null)
|
|
355
|
+
|
|
356
|
+
if [ "$session_type" = "wayland" ]; then
|
|
357
|
+
NATIVE_SESSION_TYPE="wayland"
|
|
358
|
+
NATIVE_DISPLAY="$session_display"
|
|
359
|
+
# Discover WAYLAND_DISPLAY from the session leader's environment; it, not
|
|
360
|
+
# DISPLAY, is the launch vector under the wayland ozone backend.
|
|
361
|
+
leader_pid=$(loginctl show-session "$session_id" -p Leader --value 2>/dev/null)
|
|
362
|
+
if [ -n "$leader_pid" ] && [ -r "/proc/$leader_pid/environ" ]; then
|
|
363
|
+
NATIVE_WAYLAND_DISPLAY=$(tr '\0' '\n' < "/proc/$leader_pid/environ" 2>/dev/null | \
|
|
364
|
+
grep '^WAYLAND_DISPLAY=' | cut -d= -f2)
|
|
365
|
+
fi
|
|
366
|
+
NATIVE_WAYLAND_DISPLAY="${NATIVE_WAYLAND_DISPLAY:-wayland-0}"
|
|
367
|
+
log_event "[vnc.sh:native] session=${session_id} type=wayland display=${NATIVE_DISPLAY:-none} wayland=${NATIVE_WAYLAND_DISPLAY}"
|
|
368
|
+
return 0
|
|
369
|
+
fi
|
|
325
370
|
|
|
326
|
-
#
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
grep '^WAYLAND_DISPLAY=' | cut -d= -f2)
|
|
371
|
+
# x11: $DISPLAY IS the launch vector, so a session that names none does not
|
|
372
|
+
# resolve. Keep scanning rather than substituting a value nothing reported.
|
|
373
|
+
if [ -z "$session_display" ]; then
|
|
374
|
+
log_event "[vnc.sh:native] session=${session_id} type=x11 skipped reason=no-display-value"
|
|
375
|
+
continue
|
|
332
376
|
fi
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
377
|
+
NATIVE_SESSION_TYPE="x11"
|
|
378
|
+
NATIVE_DISPLAY="$session_display"
|
|
379
|
+
log_event "[vnc.sh:native] session=${session_id} type=x11 display=${NATIVE_DISPLAY}"
|
|
380
|
+
return 0
|
|
381
|
+
done
|
|
382
|
+
|
|
383
|
+
log_event "[vnc.sh:native] no-graphical-session reason=no-active-local-graphical-session"
|
|
384
|
+
return 1
|
|
340
385
|
}
|
|
341
386
|
|
|
342
387
|
# Virtual-mode Chromium: HEADED on the brand's Xtigervnc display, driven over
|
|
@@ -408,8 +453,25 @@ start_chrome() {
|
|
|
408
453
|
# admin chat PTY is the only interactive surface.
|
|
409
454
|
# ---------------------------------------------------------------------------
|
|
410
455
|
|
|
456
|
+
# A native launch that cannot name a display must say so on the caller's own
|
|
457
|
+
# op label, so the refusal is visible to whichever grep is watching that path:
|
|
458
|
+
# op=chromium-start on the on-demand ensureCdp path, op=chromium-respawn on the
|
|
459
|
+
# standing-check path. A supervisor that declines to supervise must say so.
|
|
460
|
+
emit_native_decline() {
|
|
461
|
+
echo "[vnc] op=$1 display-mode=native cdp=:${CDP_PORT} outcome=declined reason=no-graphical-session"
|
|
462
|
+
}
|
|
463
|
+
|
|
411
464
|
start_chrome_native() {
|
|
412
|
-
|
|
465
|
+
# The precondition for a native launch is an active local graphical session.
|
|
466
|
+
# Guarded here rather than at the call sites so BOTH callers are covered: the
|
|
467
|
+
# standing check and the on-demand ensureCdp path from the browser-pane route.
|
|
468
|
+
# ensureCdp shells this through execFileSync, which throws on a non-zero exit,
|
|
469
|
+
# so a refusal already surfaces there as restart-chrome-failed → false.
|
|
470
|
+
if ! discover_native_session; then
|
|
471
|
+
log "ERROR: refusing native Chromium launch — no active local graphical session"
|
|
472
|
+
emit_native_decline chromium-start
|
|
473
|
+
return 1
|
|
474
|
+
fi
|
|
413
475
|
|
|
414
476
|
# Brand-scoped Chromium kill: only this brand's profile-bound chromium.
|
|
415
477
|
pkill -f "chromium.*--user-data-dir=${CHROMIUM_PROFILE_DIR}" 2>/dev/null || true
|
|
@@ -469,8 +531,15 @@ start_chrome_native() {
|
|
|
469
531
|
else
|
|
470
532
|
log "WARNING: Chromium CDP up on :${CDP_PORT} but no window visible on ${NATIVE_DISPLAY} (native) — observability-only, not gating"
|
|
471
533
|
fi
|
|
534
|
+
echo "[vnc] op=chromium-start display-mode=native mode=${NATIVE_SESSION_TYPE} cdp=:${CDP_PORT} outcome=ready"
|
|
472
535
|
else
|
|
473
536
|
log "ERROR: Chromium failed to start on ${NATIVE_DISPLAY} (native) — CDP port ${CDP_PORT} not listening (browser-specialist degraded)"
|
|
537
|
+
echo "[vnc] op=chromium-start display-mode=native mode=${NATIVE_SESSION_TYPE} cdp=:${CDP_PORT} outcome=failed"
|
|
538
|
+
# Deliberately still exit 0, matching start_chrome. Only the DECLINE exits
|
|
539
|
+
# non-zero, because that is the case ensureCdp must not mistake for a launch
|
|
540
|
+
# that merely needs longer. A launch that started and failed keeps the old
|
|
541
|
+
# contract: ensureCdp's own waitForPort classifies it, and execFileSync does
|
|
542
|
+
# not throw, so its second grace window is not cut short.
|
|
474
543
|
fi
|
|
475
544
|
}
|
|
476
545
|
|
|
@@ -489,8 +558,22 @@ start_chrome_native() {
|
|
|
489
558
|
# Bounded: after RESPAWN_MAX_FAILS consecutive failed respawns it backs off for
|
|
490
559
|
# RESPAWN_COOLDOWN_SECS so an unlaunchable Chromium does not hot-loop (the
|
|
491
560
|
# snap-confinement FATAL guard at the top of this script already hard-exits
|
|
492
|
-
# before any respawn).
|
|
493
|
-
#
|
|
561
|
+
# before any respawn).
|
|
562
|
+
#
|
|
563
|
+
# Task 2780: BOTH modes are supervised. Native was previously a silent
|
|
564
|
+
# early-return on the reasoning that its Chromium is launched on-demand, so
|
|
565
|
+
# display-up + CDP-down was its normal idle state. That was wrong twice over:
|
|
566
|
+
# the only native launcher needs an operator to act, so an agent's browser call
|
|
567
|
+
# found no browser and nothing in the product started one; and a supervisor
|
|
568
|
+
# that emits nothing while declining to supervise is indistinguishable in the
|
|
569
|
+
# journal from one that is running and finding everything healthy — the blind
|
|
570
|
+
# spot this check exists to remove, reintroduced by its own gate.
|
|
571
|
+
#
|
|
572
|
+
# What differs per mode is only the LAUNCH PRECONDITION. Virtual renders onto
|
|
573
|
+
# the brand's Xtigervnc display, so it keeps the RFB_PORT check and a down
|
|
574
|
+
# display stays the ensureVnc case. Native's precondition is an active local
|
|
575
|
+
# graphical session, enforced inside start_chrome_native. The state file, cap
|
|
576
|
+
# and cooldown are shared unchanged.
|
|
494
577
|
# ---------------------------------------------------------------------------
|
|
495
578
|
RESPAWN_STATE_FILE="${LOG_DIR}/cdp-respawn.state"
|
|
496
579
|
RESPAWN_MAX_FAILS="${RESPAWN_MAX_FAILS:-3}"
|
|
@@ -512,23 +595,32 @@ port_listening() {
|
|
|
512
595
|
}
|
|
513
596
|
|
|
514
597
|
cdp_liveness() {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
# respawn would launch an unsolicited browser on the operator's real display.
|
|
518
|
-
if [ "$(resolve_display_mode)" = "native" ]; then
|
|
519
|
-
return 0
|
|
520
|
-
fi
|
|
598
|
+
local mode
|
|
599
|
+
mode="$(resolve_display_mode)"
|
|
521
600
|
|
|
522
601
|
if port_listening "${CDP_PORT}"; then
|
|
523
|
-
echo "[vnc] op=cdp-liveness display=${VNC_DISPLAY} cdp=:${CDP_PORT} reachable=true"
|
|
602
|
+
echo "[vnc] op=cdp-liveness display-mode=${mode} display=${VNC_DISPLAY} cdp=:${CDP_PORT} reachable=true"
|
|
524
603
|
rm -f "$RESPAWN_STATE_FILE" 2>/dev/null || true
|
|
525
604
|
return 0
|
|
526
605
|
fi
|
|
527
|
-
echo "[vnc] op=cdp-liveness display=${VNC_DISPLAY} cdp=:${CDP_PORT} reachable=false"
|
|
528
|
-
|
|
529
|
-
#
|
|
530
|
-
#
|
|
531
|
-
|
|
606
|
+
echo "[vnc] op=cdp-liveness display-mode=${mode} display=${VNC_DISPLAY} cdp=:${CDP_PORT} reachable=false"
|
|
607
|
+
|
|
608
|
+
# Launch precondition, per mode. Evaluated BEFORE the cooldown gate so a
|
|
609
|
+
# native decline is never silenced by a cooldown a previous failure set.
|
|
610
|
+
if [ "$mode" = "native" ]; then
|
|
611
|
+
# A decline attempts no launch, so there is nothing to hot-loop: it never
|
|
612
|
+
# counts against the cap and never writes the state file. A box whose real
|
|
613
|
+
# display has gone keeps reporting reachable=false plus this decline every
|
|
614
|
+
# cycle, which is the visibility the cap exists to preserve.
|
|
615
|
+
if ! discover_native_session; then
|
|
616
|
+
emit_native_decline chromium-respawn
|
|
617
|
+
return 0
|
|
618
|
+
fi
|
|
619
|
+
else
|
|
620
|
+
# Only the VNC-display Chromium is supervised here. A down display is the
|
|
621
|
+
# VNC-stack-restart case (ensureVnc, on the next browser call).
|
|
622
|
+
port_listening "${RFB_PORT}" || return 0
|
|
623
|
+
fi
|
|
532
624
|
|
|
533
625
|
# Bounded respawn: read the consecutive-failure state.
|
|
534
626
|
local fails=0 last=0 now
|
|
@@ -548,27 +640,37 @@ cdp_liveness() {
|
|
|
548
640
|
return 0
|
|
549
641
|
fi
|
|
550
642
|
|
|
551
|
-
# Relaunch via the existing brand-scoped
|
|
552
|
-
# classify the outcome.
|
|
553
|
-
# CDP port state is settled when
|
|
554
|
-
#
|
|
555
|
-
# vnc.ts consumes
|
|
556
|
-
|
|
643
|
+
# Relaunch via the existing brand-scoped start path for this mode, then
|
|
644
|
+
# re-probe to classify the outcome. Both start paths already block on
|
|
645
|
+
# wait_for_port, so the CDP port state is settled when they return; reading
|
|
646
|
+
# the port directly keeps their exit contracts untouched (the reactive
|
|
647
|
+
# ensureCdp path in vnc.ts consumes them).
|
|
648
|
+
if [ "$mode" = "native" ]; then
|
|
649
|
+
start_chrome_native || true
|
|
650
|
+
else
|
|
651
|
+
start_chrome || true
|
|
652
|
+
fi
|
|
557
653
|
if port_listening "${CDP_PORT}"; then
|
|
558
|
-
echo "[vnc] op=chromium-respawn reason=cdp-unreachable cdp=:${CDP_PORT} outcome=ready"
|
|
654
|
+
echo "[vnc] op=chromium-respawn display-mode=${mode} reason=cdp-unreachable cdp=:${CDP_PORT} outcome=ready"
|
|
559
655
|
rm -f "$RESPAWN_STATE_FILE" 2>/dev/null || true
|
|
560
656
|
else
|
|
561
657
|
# Climb to the cap and hold there; bump last so the next attempt waits a
|
|
562
658
|
# full cooldown rather than retrying every cycle.
|
|
563
659
|
[ "$fails" -lt "$RESPAWN_MAX_FAILS" ] && fails=$(( fails + 1 ))
|
|
564
660
|
printf 'fails=%s\nlast=%s\n' "$fails" "$now" > "$RESPAWN_STATE_FILE"
|
|
565
|
-
echo "[vnc] op=chromium-respawn reason=cdp-unreachable cdp=:${CDP_PORT} outcome=failed"
|
|
661
|
+
echo "[vnc] op=chromium-respawn display-mode=${mode} reason=cdp-unreachable cdp=:${CDP_PORT} outcome=failed"
|
|
566
662
|
fi
|
|
567
663
|
}
|
|
568
664
|
|
|
569
665
|
case "${1:-}" in
|
|
570
666
|
start)
|
|
571
|
-
|
|
667
|
+
# resolve_display_mode() is the ONLY reader of DISPLAY_MODE in this script.
|
|
668
|
+
# Boot previously read the env var directly while the standing check read
|
|
669
|
+
# the brand .env; no unit file in the fleet exports DISPLAY_MODE, so every
|
|
670
|
+
# install whose .env said native still booted the virtual-mode browser
|
|
671
|
+
# while its supervisor believed it was native and supervised nothing.
|
|
672
|
+
START_DISPLAY_MODE="$(resolve_display_mode)"
|
|
673
|
+
log "[vnc.sh] start brand=${BRAND_HOSTNAME} display=${VNC_DISPLAY} rfb=${RFB_PORT} websockify=${WEBSOCKIFY_PORT} cdp=${CDP_PORT} profile=${CHROMIUM_PROFILE_DIR} mode=${START_DISPLAY_MODE}"
|
|
572
674
|
# Collision checks run BEFORE kill_stale: kill_stale removes our own
|
|
573
675
|
# locks/processes, so a check afterwards would always see them empty
|
|
574
676
|
# and never refuse. The checks are no-ops for our own brand's prior
|
|
@@ -616,10 +718,11 @@ case "${1:-}" in
|
|
|
616
718
|
exit 1
|
|
617
719
|
fi
|
|
618
720
|
|
|
619
|
-
# Native mode: VNC stack runs for remote fallback, but Chromium
|
|
620
|
-
#
|
|
621
|
-
|
|
622
|
-
|
|
721
|
+
# Native mode: VNC stack runs for remote fallback, but Chromium is not
|
|
722
|
+
# launched at boot. It comes up on-demand via ensureCdp(transport), and is
|
|
723
|
+
# restored by the standing cdp-liveness check when it dies.
|
|
724
|
+
if [ "${START_DISPLAY_MODE}" = "native" ]; then
|
|
725
|
+
log "Native display mode — skipping boot-time Chromium (launched on-demand and by the standing check)"
|
|
623
726
|
else
|
|
624
727
|
start_chrome
|
|
625
728
|
fi
|