Commit Graph

16019 Commits

Author SHA1 Message Date
Peter Steinberger
7e29d604ba test(agents): dedupe agent and cron test scaffolds 2026-03-02 07:13:10 +00:00
Veast
281494ae52 fix(browser): include Chrome stderr and sandbox hint in CDP startup error (#29355)
* fix(browser): include Chrome stderr and sandbox hint in CDP startup error (#29312)

When Chrome fails to start and CDP times out, the error message previously
contained no diagnostic information, making it impossible to determine why
Chrome couldn't start (e.g. missing --no-sandbox in containers, GPU issues,
shared memory errors).

This change:
- Collects Chrome's stderr output and includes up to 2000 chars in the error
- On Linux, if noSandbox is not set, appends a hint to try browser.noSandbox: true

Closes #29312

* chore(browser): format chrome startup diagnostics

* fix(browser): detach stderr listener after Chrome starts to prevent memory leak

Named the anonymous listener so it can be removed via proc.stderr.off()
once CDP is confirmed reachable. Also clears the stderrChunks array on
success so the buffered data is eligible for GC.

Fixes the unbounded memory growth reported in code review: a long-lived
Chrome process emitting periodic warnings would keep appending to
stderrChunks indefinitely since the listener was never removed.

Addresses review comment from chatgpt-codex-connector on PR #29355.

* changelog: note cdp startup diagnostics improvement

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: 派尼尔 <painier@openclaw.ai>
2026-03-01 23:08:52 -08:00
jamtujest
cb491dfde5 feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments

Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).

Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
  build sandbox image, configure sandbox defaults, add group_add

All changes are opt-in. Zero impact on existing deployments.

Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh

Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address code review feedback on sandbox support

- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
  to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
  report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
  is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
  by using printf instead of echo with line continuation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove `local` outside function and guard sandbox behind Docker CLI check

- Remove `local` keyword from top-level `sandbox_config_ok` assignment
  which caused script exit under `set -euo pipefail` (bash `local`
  outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
  runs `docker --version` inside the container and skips sandbox setup
  with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: defer docker.sock mount until sandbox prerequisites pass

Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host

Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.

Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(docker): fix sandbox docs URL in setup output

* Docker: harden sandbox setup fallback behavior

* Tests: cover docker-setup sandbox edge paths

* Docker: roll back sandbox mode on partial config failure

* Tests: assert sandbox mode rollback on partial setup

* Docs: document Docker sandbox bootstrap env controls

* Changelog: credit Docker sandbox bootstrap hardening

* Update CHANGELOG.md

* Docker: verify Docker apt signing key fingerprint

* Docker: avoid sandbox overlay deps during policy writes

* Tests: assert no-deps sandbox rollback gateway recreate

* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars

---------

Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 23:06:10 -08:00
Tyler Yust
f918b336d1 fix: agent-only announce path, BB message IDs, sender identity, SSRF allowlist (#23970)
* fix(agents): defer announces until descendant cleanup settles

* fix(bluebubbles): harden message metadata extraction

* feat(contributors): rank by composite score (commits, PRs, LOC, tenure)

* refactor(control-ui): move method guard after path checks to improve request handling

* fix subagent completion announce when only current run is pending

* fix(subagents): keep orchestrator runs active until descendants finish

* fix: prepare PR feedback follow-ups (#23970) (thanks @tyler6204)
2026-03-01 22:52:11 -08:00
Peter Steinberger
cfba64c9db test: fix pdf-tool fetch/model config mock typings 2026-03-02 06:48:01 +00:00
Peter Steinberger
e876c2c3b3 fix: finalize headless profile default landing (#14944) (thanks @BenediktSchackenberg) 2026-03-02 06:48:01 +00:00
Benedikt Schackenberg
d03928bb69 test: Add tests for headless/noSandbox profile preference
Cover all cases requested in review:
1. headless=true → defaultProfile = 'openclaw'
2. noSandbox=true → defaultProfile = 'openclaw'
3. both false → defaultProfile = 'chrome' (existing behavior)
4. explicit defaultProfile config overrides preference logic
5. custom profiles work in headless mode

Fixes: #14895
2026-03-02 06:48:01 +00:00
Benedikt Schackenberg
3e3b49cb94 fix(browser): prefer openclaw profile in headless/noSandbox environments
In headless or noSandbox server environments (like Ubuntu Server), the
Chrome extension relay cannot work because there is no GUI browser to
attach to. Previously, the default profile was 'chrome' (extension relay)
which caused snapshot/screenshot operations to fail with:

  'Chrome extension relay is running, but no tab is connected...'

This fix prefers the 'openclaw' profile (Playwright native mode) when
browser.headless=true or browser.noSandbox=true, while preserving the
'chrome' default for GUI environments where extension relay works.

Fixes: https://github.com/openclaw/openclaw/issues/14895

🤖 AI-assisted (Claude), fully tested: pnpm build && pnpm check && pnpm test
2026-03-02 06:48:01 +00:00
Tyler Yust
d0ac1b0195 feat: add PDF analysis tool with native provider support (#31319)
* feat: add PDF analysis tool with native provider support

New `pdf` tool for analyzing PDF documents with model-powered analysis.

Architecture:
- Native PDF path: sends raw PDF bytes directly to providers that support
  inline document input (Anthropic via DocumentBlockParam, Google Gemini
  via inlineData with application/pdf MIME type)
- Extraction fallback: for providers without native PDF support, extracts
  text via pdfjs-dist and rasterizes pages to images via @napi-rs/canvas,
  then sends through the standard vision/text completion path

Key features:
- Single PDF (`pdf` param) or multiple PDFs (`pdfs` array, up to 10)
- Page range selection (`pages` param, e.g. "1-5", "1,3,7-9")
- Model override (`model` param) and file size limits (`maxBytesMb`)
- Auto-detects provider capability and falls back gracefully
- Same security patterns as image tool (SSRF guards, sandbox support,
  local path roots, workspace-only policy)

Config (agents.defaults):
- pdfModel: primary/fallbacks (defaults to imageModel, then session model)
- pdfMaxBytesMb: max PDF file size (default: 10)
- pdfMaxPages: max pages to process (default: 20)

Model catalog:
- Extended ModelInputType to include "document" alongside "text"/"image"
- Added modelSupportsDocument() capability check

Files:
- src/agents/tools/pdf-tool.ts - main tool factory
- src/agents/tools/pdf-tool.helpers.ts - helpers (page range, config, etc.)
- src/agents/tools/pdf-native-providers.ts - direct API calls for Anthropic/Google
- src/agents/tools/pdf-tool.test.ts - 43 tests covering all paths
- Modified: model-catalog.ts, openclaw-tools.ts, config schema/types/labels/help

* fix: prepare pdf tool for merge (#31319) (thanks @tyler6204)
2026-03-01 22:39:12 -08:00
Peter Steinberger
31b6e58a1b docs: add relay reattach changelog attribution (#28725) (thanks @stone-jin) 2026-03-02 06:38:21 +00:00
stone-jin
04b3a51d3a fix(browser): preserve debugger attachment across relay disconnects during navigation reattach 2026-03-02 06:38:21 +00:00
Peter Steinberger
18cd77c8ce fix: cover relay reannounce minimal target path (#27630) (thanks @markmusson) 2026-03-02 06:33:28 +00:00
Mark Musson
591ff3c1c8 fix(browser-relay): fallback to cached targetId on target info lookup failure 2026-03-02 06:33:28 +00:00
Vincent Koc
3ae8e5ee91 Docs: add changelog entry for auth permission error (#31367)
* Docs: add changelog entry for auth permission error

* Update CHANGELOG.md
2026-03-01 22:30:47 -08:00
Peter Steinberger
b3cf6e7d77 fix: harden relay reconnect grace coverage (#30232) (thanks @Sid-Qin) 2026-03-02 06:28:50 +00:00
SidQin-cyber
f77f3fb839 fix(browser): tolerate brief extension relay disconnects on attached tabs
Keep extension relay tab metadata available across short extension worker drops and allow CDP clients to connect while waiting for reconnect. This prevents false "no tab connected" failures in environments where the extension worker disconnects transiently (e.g. WSLg/MV3).
2026-03-02 06:28:50 +00:00
Peter Steinberger
0eebae44f6 fix: test browser.request profile body fallback (#28852) (thanks @Sid-Qin) 2026-03-02 06:26:35 +00:00
SidQin-cyber
fa875a6bf7 fix(gateway): honor browser profile from request body for node proxy calls
Gateway browser.request only read profile from query.profile before invoking
browser.proxy on nodes. Calls that passed profile in POST body silently fell
back to the default profile, which could switch users into chrome extension
mode even when they explicitly requested openclaw profile.

Use query profile first, then fall back to body.profile when present.

Closes #28687
2026-03-02 06:26:35 +00:00
Sid
40e078a567 fix(auth): classify permission_error as auth_permanent for profile fallback (#31324)
When an OAuth auth profile returns HTTP 403 with permission_error
(e.g. expired plan), the error was not matched by the authPermanent
patterns. This caused the profile to receive only a short cooldown
instead of being disabled, so the gateway kept retrying the same
broken profile indefinitely.

Add "permission_error" and "not allowed for this organization" to
the authPermanent error patterns so these errors trigger the longer
billing/auth_permanent disable window and proper profile rotation.

Closes #31306

Made-with: Cursor

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 22:26:05 -08:00
Timothy Jordan
f2dbaf70fa docs: add Vercel sponsorship (#29270)
* docs: add Vercel sponsorship

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: fix README formatting

* docs: resize Vercel sponsor logo to match other logos

* docs: scale down Vercel SVG viewBox to match other sponsor logos

* Fixed ordering.

* md error fix

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 06:25:46 +00:00
SidQin-cyber
821b7c80a6 fix(browser): avoid extension profile startup deadlock in browser start
browser start for driver=extension required websocket tab attachment during
ensureBrowserAvailable, which can deadlock startup because tabs can only
attach after relay startup succeeds.

For extension profiles, only require relay HTTP reachability in startup and
leave tab attachment checks to ensureTabAvailable when a concrete tab action
is requested.

Closes #28701
2026-03-02 06:19:36 +00:00
Peter Steinberger
5b8f492a48 fix(security): harden spoofed system marker handling 2026-03-02 06:19:16 +00:00
SidQin-cyber
7c9d2c1d48 fix(browser): retry relay navigation after frame detach
Retry browser navigate once after transient frame-detached/target-closed errors by forcing a clean Playwright reconnect, so extension-relay sessions stay controllable across navigation swaps.

Closes #29431
2026-03-02 06:14:52 +00:00
zerone0x
376a52a5ba fix: use 0o644 for inbound media files to allow sandbox read access (#17943)
* fix: use 0o644 for inbound media files to allow sandbox read access

Inbound media files were saved with 0o600 permissions, making them
unreadable from Docker sandbox containers running as different users.

Change to 0o644 (world-readable) so sandboxed agents can access
downloaded attachments.

Fixes #17941

Co-Authored-By: Claude <noreply@anthropic.com>

* test(media): assert URL-sourced inbound files use 0o644

* test(media): make redirect file-mode assertion platform-aware

* docs(media): clarify 0o644 is for sandbox UID compatibility

---------

Co-authored-by: zerone0x <zerone0x@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 22:14:39 -08:00
AaronWander
366374b4ff Sandbox: add actionable error when docker missing (#28547)
Co-authored-by: AaronWander <siralonne@163.com>
2026-03-01 22:14:26 -08:00
Peter Steinberger
3049ca840f docs: replace bare provider URLs with markdown links 2026-03-02 06:01:29 +00:00
Jannes Stubbemann
5bb26bf22a fix(browser): skip port ownership check for remote CDP profiles (#28780)
* fix(browser): skip port ownership check for remote CDP profiles

When a browser profile has a non-loopback cdpUrl (e.g. Browserless,
Kubernetes sidecar, or any external CDP service), the port-ownership
check incorrectly fires because we don't "own" the remote process.
This causes "Port is in use but not by openclaw" even though the
remote CDP service is working and reachable.

Guard the ownership error with !remoteCdp so remote profiles fall
through to the WebSocket retry/attach logic instead.

Fixes #15582

* fix: add TypeScript null guard for profileState.running

* chore(changelog): note remote CDP ownership fix credits

Refs #15582

* Update CHANGELOG.md

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 22:00:16 -08:00
Sahil Satralkar
cda119b052 fix: handle missing systemctl in containers (#26089) (#26699)
* Daemon: handle missing systemctl in containers

* Daemon: harden missing-systemctl detection

* Daemon tests: cover systemctl spawn failure path

* Changelog: note container systemctl service-check fix

* Update CHANGELOG.md

* Daemon: fail closed on unknown systemctl is-enabled errors

* Daemon tests: cover is-enabled unknown-error path

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 21:48:06 -08:00
Peter Steinberger
5d78fcf1b5 docs: add missing message channels to readme 2026-03-02 05:46:57 +00:00
Peter Steinberger
bc0288bcfb docs: clarify adaptive thinking and openai websocket docs 2026-03-02 05:46:57 +00:00
Sid
e1e715c53d fix(gateway): skip device pairing for local backend self-connections (#30801)
* fix(gateway): skip device pairing for local backend self-connections

When gateway.tls is enabled, sessions_spawn (and other internal
callGateway operations) creates a new WebSocket to the gateway.
The gateway treated this self-connection like any external client
and enforced device pairing, rejecting it with "pairing required"
(close code 1008). This made sub-agent spawning impossible when
TLS was enabled in Docker with bind: "lan".

Skip pairing for connections that are gateway-client self-connections
from localhost with valid shared auth (token/password). These are
internal backend calls (e.g. sessions_spawn, subagent-announce) that
already have valid credentials and connect from the same host.

Closes #30740

* gateway: tighten backend self-pair bypass guard

* tests: cover backend self-pairing local-vs-remote auth path

* changelog: add gateway tls pairing fix credit

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 21:46:33 -08:00
Sid
3002f13ca7 feat(config): add openclaw config validate and improve startup error messages (#31220)
Merged via squash.

Prepared head SHA: 4598f2a541
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-02 00:45:51 -05:00
Vincent Koc
5a2200b280 fix(sessions): harden recycled PID lock recovery follow-up (#31320)
* fix: detect PID recycling in session write lock staleness check

The session lock uses isPidAlive() to determine if a lock holder is
still running. In containers, PID recycling can cause a different
process to inherit the same PID, making the lock appear valid when
the original holder is dead.

Record the process start time (field 22 of /proc/pid/stat) in the
lock file and compare it during staleness checks. If the PID is alive
but its start time differs from the recorded value, the lock is
treated as stale and reclaimed immediately.

Backward compatible: lock files without starttime are handled with
the existing PID-alive + age-based logic. Non-Linux platforms skip
the starttime check entirely (getProcessStartTime returns null).

* shared: harden pid starttime parsing

* sessions: validate lock pid/starttime payloads

* changelog: note recycled PID lock recovery fix

* changelog: credit hiroki and vincent on lock recovery fix

---------

Co-authored-by: HirokiKobayashi-R <hiroki@rhems-japan.co.jp>
2026-03-01 21:42:22 -08:00
Ayaan Zaidi
548a502c69 docs: sync android node docs with current pairing and capabilities 2026-03-02 11:08:51 +05:30
Nikolay Petrov
a9f1188785 sessions_spawn: inline attachments with redaction, lifecycle cleanup, and docs (#16761)
Add inline file attachment support for sessions_spawn (subagent runtime only):

- Schema: attachments[] (name, content, encoding, mimeType) and attachAs.mountPath hint
- Materialization: files written to .openclaw/attachments/<uuid>/ with manifest.json
- Validation: strict base64 decode, filename checks, size limits, duplicate detection
- Transcript redaction: sanitizeToolCallInputs redacts attachment content from persisted transcripts
- Lifecycle cleanup: safeRemoveAttachmentsDir with symlink-safe path containment check
- Config: tools.sessions_spawn.attachments (enabled, maxFiles, maxFileBytes, maxTotalBytes, retainOnSessionKeep)
- Registry: attachmentsDir/attachmentsRootDir/retainAttachmentsOnKeep on SubagentRunRecord
- ACP rejection: attachments rejected for runtime=acp with clear error message
- Docs: updated tools/index.md, concepts/session-tool.md, configuration-reference.md
- Tests: 85 new/updated tests across 5 test files

Fixes:
- Guard fs.rm in materialization catch block with try/catch (review concern #1)
- Remove unreachable fallback in safeRemoveAttachmentsDir (review concern #7)
- Move attachment cleanup out of retry path to avoid timing issues with announce loop

Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
Co-authored-by: napetrov <napetrov@users.noreply.github.com>
2026-03-01 21:33:51 -08:00
Peter Steinberger
842deefe5d test: split fast lane from channel and gateway suites 2026-03-02 05:33:07 +00:00
Peter Steinberger
a13586619b test: move integration-heavy suites to e2e lane 2026-03-02 05:33:07 +00:00
Peter Steinberger
656121a12b test: micro-optimize hot unit test files 2026-03-02 05:33:07 +00:00
Peter Steinberger
1de3200973 refactor(infra): centralize boundary traversal and root path checks 2026-03-02 05:20:19 +00:00
Peter Steinberger
7fcec6ca3e refactor(streaming): share approval and stream message builders 2026-03-02 05:20:19 +00:00
Peter Steinberger
6b78544f82 refactor(commands): unify repeated ACP and routing flows 2026-03-02 05:20:19 +00:00
Peter Steinberger
2d31126e6a refactor(shared): extract reused path and normalization helpers 2026-03-02 05:20:19 +00:00
Peter Steinberger
264599cc1d refactor(core): share JSON utf8 byte counting helper 2026-03-02 05:20:19 +00:00
Peter Steinberger
4a1be98254 fix(diffs): harden viewer security and docs 2026-03-02 05:07:09 +00:00
Peter Steinberger
0ab2c82624 docs: dedupe 2026.3.1 changelog entries 2026-03-02 05:04:28 +00:00
Peter Steinberger
6ba7238ac6 build: bump versions to 2026.3.2 2026-03-02 04:55:53 +00:00
Umut CAN
d2472af724 Chore: add Dockerfile HEALTHCHECK and debug-log silent catch blocks (#11478)
* Docker: add /healthz-based container HEALTHCHECK

* Docs/Docker: document built-in image HEALTHCHECK

* Changelog: note Dockerfile healthcheck probe

* Docs/Docker: explain HEALTHCHECK behavior in plain language

* Docker: relax HEALTHCHECK interval to 3m

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 20:52:14 -08:00
Peter Steinberger
2a8ac974e1 build: prepare 2026.3.1 latest release 2026-03-02 04:50:11 +00:00
Alberto Leal
449511484d fix(gateway): allow ws:// to private network addresses (#28670)
* fix(gateway): allow ws:// to RFC 1918 private network addresses

resolve ws-private-network conflicts

* gateway: keep ws security strict-by-default with private opt-in

* gateway: apply private ws opt-in in connection detail guard

* gateway: apply private ws opt-in in websocket client

* onboarding: gate private ws urls behind explicit opt-in

* gateway tests: enforce strict ws defaults with private opt-in

* onboarding tests: validate private ws opt-in behavior

* gateway client tests: cover private ws env override

* gateway call tests: cover private ws env override

* changelog: add ws strict-default security entry for pr 28670

* docs(onboard): document private ws break-glass env

* docs(gateway): add private ws env to remote guide

* docs(docker): add private ws break-glass env var

* docs(security): add private ws break-glass guidance

* docs(config): document OPENCLAW_ALLOW_PRIVATE_WS

* Update CHANGELOG.md

* gateway: normalize private-ws host classification

* test(gateway): cover non-unicast ipv6 private-ws edges

* changelog: rename insecure private ws break-glass env

* docs(onboard): rename insecure private ws env

* docs(gateway): rename insecure private ws env in config reference

* docs(gateway): rename insecure private ws env in remote guide

* docs(security): rename insecure private ws env

* docs(docker): rename insecure private ws env

* test(onboard): rename insecure private ws env

* onboard: rename insecure private ws env

* test(gateway): rename insecure private ws env in call tests

* gateway: rename insecure private ws env in call flow

* test(gateway): rename insecure private ws env in client tests

* gateway: rename insecure private ws env in client

* docker: pass insecure private ws env to services

* docker-setup: persist insecure private ws env

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-01 20:49:45 -08:00
Peter Steinberger
d76b224e20 docs: update appcast for 2026.3.1 v2026.3.1 2026-03-02 04:41:39 +00:00