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
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.
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.
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.
Integrate version tracking for DenchClaw and OpenClaw into the telemetry system. The versions are now read from the package.json and environment variables, and are included in the PostHog client initialization and telemetry events. This enhancement allows for better monitoring and analytics of the versions in use.
Backend support for multi-session chat: /api/chat/runs endpoint for parent/subagent run status, subagent registry for reading run state, and cascade stop to abort child sessions when stopping a parent.
parseSimpleYaml only matched `key: value` lines (regex required `.+`
after the colon), so `permissions:` followed by indented `- database`
list items was never parsed. This caused app bridge methods like
db.query to always fail with "Unknown method or insufficient
permissions" even when the app manifest granted the database permission.
Change the regex to `.*` to also match keys with no inline value, then
collect subsequent indented `- item` lines into an array.
Closes#87
- Refactor WebSocket connection logic to dynamically fetch the port from the server, improving flexibility.
- Introduce global variables to manage WebSocket server state and port, allowing for better control and error handling.
- Update terminal drawer component to use the new port fetching mechanism, ensuring consistent connection behavior.
The terminal drawer was flickering closed immediately after opening because
the spawned shell process exited with code 1, triggering handleExited →
closeTerminal → onClose which unmounted the entire drawer within ~500ms.
- Stop auto-closing the drawer on process exit so users can see error output
- Extract URL param building into testable buildWorkspaceSyncParams function
that correctly includes terminal state, preventing param stripping on navigation
- Add 21 tests covering terminal param preservation across navigation scenarios
Without error handling, if node-pty require or pty.spawn throws (bad
permissions, missing cwd, stale server), the client gets no response and
the terminal hangs with a blinking cursor. Now sends an exit event back.
xterm.js frontend + node-pty WebSocket server spawning the user's real shell,
with drag-to-resize drawer, multi-terminal tabs, live theme sync, and URL state.
- Convert sync filesystem and DuckDB operations to async across API routes,
workspace lib, and active-runs to prevent event loop blocking during tree
discovery, object lookups, and database queries
- Add "tags" field type for free-form string arrays with parse-tags utility,
TagsBadges/TagsInput UI components, filter operators, and CRM skill docs
- Preserve rich text formatting (bold, italic, code, @mentions) in user chat
messages by sending HTML alongside plain text through the transport layer
- Detect empty-stream errors, improve agent error emission, and add file
mutation queues for concurrent write safety in active-runs
- Add pre-publish standalone node_modules verification in deploy script
checking serverExternalPackages are present
- Extract syncManagedSkills and discoverWorkspaceDirs for multi-workspace
skill syncing, add ensureSeedAssets for runtime app dir
- Bump version 2.1.1 → 2.1.4
sessions.patch for verboseLevel=full was called before the agent RPC
created the session, so it silently failed on new chats. Tool events
were never emitted and the frontend only showed brief text responses.
Now patches both before (for existing sessions) and after the agent RPC
(for newly created sessions). Also adds SSE keepalive to the POST /api/chat
stream to prevent connection drops during long tool executions, and removes
the unused legacy CLI spawn codepath.
The root layout called getOrCreateAnonymousId() in a Server Component
without marking the route as dynamic. Next.js treated it as static,
pre-rendering the developer's UUID into the standalone build shipped
via npm — so every `npx denchclaw` user shared the same PostHog identity.
- Add `export const dynamic = "force-dynamic"` to root layout
- Replace `process.env.HOME || "~"` fallback with `homedir()` in web
telemetry and posthog-analytics plugin (Node.js path.join doesn't
expand "~", creating a relative path under cwd instead)
findObjectDir only searched the workspace root and one level deep, so objects
nested inside category folders (e.g. marketing/influencer/) were not discovered
by the views API. This caused saved views, active_view, and view_settings to
silently return empty for any object beyond depth 1.
Replace the single-level scan with a depth-limited recursive search (max 4
levels), skipping known heavy directories (node_modules, .git, .next, etc.).
The sidebar tree builder (buildTree in tree/route.ts) already walks recursively,
so this brings findObjectDir in line with the rest of the workspace discovery.
Add workspace mock to agent-runner tests, skip PostHog pageviews on cron paths to reduce noise, document web-chat storage path in CRM skill, and include cursor plans and build info.
Move the workspace shell from /workspace to / and introduce a typed URL state codec (parseUrlState/serializeUrlState) for deep-linkable workspace params. Legacy /workspace URLs are still recognized for backward compatibility.
Bootstrap posthog-js with the persisted install ID from the server, forward distinctId to API routes, and restructure feedback traces to use chronological conversation order.
Client-side posthog-js was using a random anonymous ID (reset every
page load) while server-side posthog-node used a deterministic
SHA256(hostname:username) hash. Bootstrap the client with the server's
anonymous ID so both sides share the same per-machine-per-user identity.
- New src/config/paths.test.ts: 11 tests covering resolveGatewayPort
profile-aware precedence (env > config > profile > global default)
- Extend bootstrap-external.test.ts: 15 new tests for
readExistingGatewayPort (config reading, fallback, edge cases) and
isPersistedPortAcceptable (18789 rejection guard, end-to-end composition)
- Extend web-runtime-command.test.ts: 2 new tests verifying the fallback
returns 19001 when manifest has no lastGatewayPort or is null
- Update test fixtures across all test files to expect port 19001
All 5 critical mutations verified: removing profile check, removing
18789 guard, reverting fallback, changing constant, breaking config
reader -- each caught by at least 2 tests.
- Fix bootstrap-command test: mock ensureManagedWebRuntime to probe
directly instead of requiring standalone build on disk
- Add PostHog telemetry to CLI and web app with opt-out support
- Add dench alias package (npm rejects name; kept for future use)
- Bump version to 2.0.4 and publish to npm
- Bump version of denchclaw to 2.0.2 in package.json.
- Add posthog-node and posthog-js dependencies with specified versions.
- Update chokidar dependency in web package.json.
- Modify deploy script to publish an alias package (dench) alongside denchclaw.
This commit introduces several enhancements across the EntryDetailModal and ObjectTable components. Key changes include the addition of a FormattedFieldValue component for consistent display of various field types, improved handling of entry metadata, and the introduction of input type resolution for fields. Additionally, navigation callbacks for entries have been refined to support better interaction within the object table. These updates aim to streamline data presentation and enhance user experience.
This commit refactors the handling of subagent sessions by removing the enrichSubagentMessages function and integrating its functionality into the GET request handler. It also introduces the enrichSubagentSessionFromTranscript function to enhance session data retrieval. Additionally, the persistSubscribeUserMessage function is updated to ensure user messages are saved to the session JSONL file, improving message persistence across page reloads. These changes enhance the clarity and efficiency of subagent session management.