Two issues with image handling in chat:
1. Images pasted/dropped in chat were uploaded to disk but only file
paths were sent as plain text. The model never received actual image
bytes. Now sends base64 image data as `attachments` in the chat.send
RPC so vision-capable models can see images directly.
2. Attached file paths (e.g. assets/screenshot.png) were not prefixed
with the workspace root, unlike [Context: workspace file '...'] paths.
The agent couldn't resolve relative paths. Now both patterns get the
workspace prefix.
Files changed:
- chat-panel.tsx: read images as base64 via FileReader, send as FileUIPart
- chat/route.ts: extract image file parts, prefix attached file paths
- gateway/chat/route.ts: accept attachments in request body
- active-runs.ts: thread attachments through startRun
- agent-runner.ts: forward attachments to chat.send RPC
- chat-message.tsx: render inline image previews in user messages
Made-with: Cursor
The Node.js ws library doesn't send an Origin header by default.
When the client identifies as openclaw-control-ui, the gateway
enforces origin checks and rejects connections with missing origin.
Pass the gateway URL as the Origin header so the gateway's
local-loopback check sees a valid loopback origin and allows it.
Bump to v2.3.20.
Made-with: Cursor
The desktop app runs in daemonless mode without device identity files.
The gateway clears operator scopes for "gateway-client" connections
that lack device identity. Allow the client ID to be overridden via
env var so the desktop can identify as "openclaw-control-ui" and
receive operator scopes with dangerouslyDisableDeviceAuth enabled.
Fallback to "gateway-client" preserves existing behavior for CLI
and web users.
Bump to v2.3.19.
Made-with: Cursor
- Change thinkingLevel from xhigh to high for session patches
- Fix indentation of event handler blocks in wireSubscribeOnlyProcess
and wireChildProcess
- Add user-friendly message when agent run is terminated by the gateway
When DENCHCLAW_DAEMONLESS=1, route the terminal WebSocket through
the app host instead of connecting directly to 127.0.0.1, allowing
it to work in environments without direct port access.
OpenClaw's default agent timeout is 600s (10 min), which consistently kills
long-running agent responses — especially multi-file code generation and
complex multi-tool-call workflows. This triggers:
- 'terminated' errors mid-stream (webchat shows terminated banner)
- Retry storms: same runId retries ~60s apart, then new runIds also fail
- Follow-up messages silently dropped (shouldSkipMessageByAbortCutoff)
Set the default to 86400s (24 hours) during bootstrap so all DenchClaw
installations get a sane timeout out of the box. Note: the runtime code
supports timeoutSeconds=0 (no timeout) but the config schema validation
rejects 0 (exclusiveMinimum: 0), so 86400 is the practical maximum.
Also rename ensureSubagentDefaults -> ensureAgentDefaults since the function
now configures both agent-level and subagent-level settings.
Refs:
- https://github.com/openclaw/openclaw/issues/30487
- https://github.com/openclaw/openclaw/issues/46049
- https://github.com/openclaw/openclaw/issues/30083
Add optional name, email, avatar, and denchOrgId fields to
telemetry.json. When present, all telemetry layers (CLI, web server,
web client, OpenClaw plugin) call PostHog identify() with $name,
$email, $avatar, and dench_org_id person properties.
Remove $process_person_profile:false from all layers so every install
gets a PostHog person profile. Enable session replay with masking
controlled by privacy mode (all text/inputs masked when on, nothing
masked when off).
Move identity injection from static IDENTITY.md generation at workspace seed
time to a runtime `dench-identity` OpenClaw plugin that prepends the system
prompt via the `before_prompt_build` hook. This keeps identity always current
without re-seeding, encourages dynamic skill discovery, and positions
DenchClaw as a CEO orchestrator that delegates to specialist subagents.
Enables apps to access the full DenchClaw platform — CRUD on workspace objects, AI chat with streaming, inter-app messaging, KV store, HTTP proxy, webhooks, cron scheduling, and widget display mode.
- Back up existing app dir before replacing (enables rollback on crash)
- Rollback to previous working runtime when new version fails readiness probe
- Early exit in waitForWebRuntime() when spawned process dies (saves 15s)
- Include web-app.err.log tail in probe failure reason for diagnostics
- Clean up backup after successful probe
Made-with: Cursor
Use per-session gateway lanes (web:sessionId) so concurrent chat tabs
stream independently. Add a 15s recovery window after lifecycle errors
to accept continuation runIds. Route slash commands through chat.send
RPC and forward chat events to the UI.
Chat-slot agents were being persisted as durable entries in openclaw.json,
causing spurious workspace directories (e.g. chat-slot-main-1) to appear.
Only explicit workspace creation via init now creates durable agent entries.
Workspace discovery and session routing ignore chat-slot internals.
Refine the handling of the DENCHCLAW_DAEMONLESS=1 environment variable and --skip-daemon-install flag to ensure consistent behavior across all commands, including bootstrap, update, start, restart, and stop, in environments lacking systemd/launchd.
Support DENCHCLAW_DAEMONLESS=1 env var and --skip-daemon-install flag
across all commands (bootstrap, update, start, restart, stop) to skip
gateway daemon management and LaunchAgent registration in environments
without systemd/launchd.
Pre-onboard config (gateway.mode, gateway.port, plugin trust) used to call
`openclaw config set` before `openclaw onboard` created the profile, causing
"Failed to set ..." errors on fresh installs (#101). All pre-onboard config is
now staged via raw JSON writes. Hidden gateway restarts inside syncBundledPlugins
are removed; one explicit restart happens after all post-onboard config, followed
by retried health probes so bootstrap no longer falsely reports "gateway closed"
while the gateway is simply finishing startup.
Server-side WebSocket connections should not set Origin (a browser security
concept). The header caused the gateway to treat the web runtime as a browser
client, blocking silent local device pairing after device identity auth was
added.
extractUsageFromMessages was summing ALL assistant messages, so each
$ai_generation event reported a growing cumulative total — PostHog's
sum() then massively over-counted costs (e.g. $634 reported vs $73 actual).