Commit Graph

8747 Commits

Author SHA1 Message Date
Peter Steinberger
dc600d4a77 feat(diffs): changed-files summary nav for multi-file patch diffs (#100753)
* feat(diffs): add changed-files summary nav for multi-file patch diffs

* docs: regenerate docs map for diffs multi-file navigation section

* fix(diffs): respect reduced motion in summary navigation
2026-07-06 16:55:56 +01:00
Peter Steinberger
30e5dfcf02 feat(gateway): read-only agents.workspace list/get browsing RPCs (#100738)
* feat(gateway): add read-only agents.workspace list/get browsing RPCs

* fix(gateway): gate workspace image reads on sniffed magic bytes, not extension

* fix(gateway): tighten workspace browsing boundary

* docs(gateway): clarify workspace read trust scope

* chore(gateway): leave release notes to release flow
2026-07-06 16:41:24 +01:00
Peter Steinberger
add5c513ae feat(ui): stable session order, palette-only search, and macOS titlebar brand for the sidebar (#100648)
* feat(ui): declutter the sidebar — pinned/chats groups, stable ordering, palette session search, titlebar brand in macOS app

- Sessions split into Pinned and Chats groups; pins are exempt from the
  nine-row recency cap and the open session highlights in place instead of
  hoisting to the top, so clicking a row no longer reshuffles the list.
- The command palette (Cmd+K) is the single search: it queries sessions
  across agents server-side and lists matching chats next to nav commands;
  the sidebar session-picker popover and its magnifier are removed, and the
  topbar search pill shrinks to an icon button.
- The sidebar brand row is gone: web keeps the breadcrumb wordmark, and the
  macOS app shows a compact brand mark in the native titlebar strip next to
  the traffic lights (CSS-gated on the injected openclaw-native-macos class).
- The agent filter dropdown becomes a compact scope chip in the Chats group
  header; the welcome badge drops its duplicate claw logo.
- Footer collapses to one icon row (status dot, settings, docs, pairing,
  mobile theme switch); default pinned nav routes are now Overview-only and
  the Recent-collapse preference is retired.

* test(ui): keep sidebar hover-reveal proof before the stability click; refresh locale metadata

Clicking the row leaves :focus-within on it, which keeps the management
actions visible; the hidden-actions assertion must run first.

* test(ui): archive an idle session in the sidebar e2e; assert running rows stay archive-disabled

* fix(ui): drop stale and hidden rows from palette session search

Invalidate the in-flight search and clear results on every query change so a
late-resolving previous-query request cannot leave stale rows selectable, and
run results through getVisibleSessionRows so archived/global/unknown/cron/
subagent rows stay hidden like the sidebar list. Codex review findings.

* fix(ui): over-fetch palette session search so hidden rows cannot starve visible matches

Exclude global/unknown rows server-side and fetch a full 50-row page before
applying the sidebar's hidden-row filter, keeping the 10-row display cap.
Codex review finding.

* chore(i18n): refresh sidebar locale metadata after rebase

* fix(ui): bound command palette session search

* docs: defer release notes to release generation
2026-07-06 16:38:26 +01:00
Peter Steinberger
063eeb69f3 feat(android): support opt-in background location (#100967)
* feat(android): support background location

Co-authored-by: Iori Kojima <iori@iori.dev>

* chore(android): refresh native i18n inventory

* docs(android): move release note to app changelog

---------

Co-authored-by: Iori Kojima <iori@iori.dev>
2026-07-06 16:36:58 +01:00
Peter Steinberger
c0a0c22086 docs: add X-verified builds and devtools to showcase
Second sweep: 13 cards from the openclaw.ai X showcase and Discord
maintainer channel — car negotiation, flight check-in, insurance
claim, Idealista skill, tokenomics cost tracker, Excalidraw
diagrams, GA4 skill, X post pipeline, lab results to Notion,
Pebble Ring voice, creator media studio, HomePod skill, holo cube,
macOS menu bar app — plus a Related link to the full X showcase.
oxfmt 0.57.0 --check passed; hook bypassed (no node_modules in
worktree).
2026-07-06 08:16:12 -07:00
Peter Steinberger
aa1929ccb0 feat(control-ui): multi-pane split view for chat (#100754)
* feat(control-ui): add multi-pane split view to chat

* fix(control-ui): boot classic chat pane without fabricated session key

* fix(control-ui): thread per-pane composer state into session goal pill
2026-07-06 16:01:51 +01:00
Peter Steinberger
1e27467ab0 docs: extend showcase with fresh community projects
Adds 12 community cards sourced from Discord (#skills, #general,
shell-society) and the web: Dropage deploy, anti-scam URL checker,
product-design skill trio, miab-broker, lite-mode, ClawEval,
Music Craft, gardening back office, Obsidian second brain,
family history bot, Action Button walkie-talkie, and Clinch.
All links verified live; oxfmt 0.57.0 --check passed (worktree
lacks node_modules, hook bypassed after proof).
2026-07-06 07:56:14 -07:00
Peter Steinberger
f623d81f52 feat(ui): show background tasks live in the web Control UI (#100789)
* feat(gateway): broadcast task ledger changes as task events

* feat(ui): add background Tasks page to Control UI

* fix(gateway): address tasks page review findings

* fix(ui): surface tasks.cancel refusals on the Tasks page

* fix(gateway): guard stale task observer disposal against replacement gateways

* chore: satisfy lint and docs-map gates for tasks page

* test(gateway): await async agent unsub in stale-dispose test
2026-07-06 14:36:33 +01:00
Peter Steinberger
88f1ec38d4 feat(sessions): grouping, unread state, and full session controls on web, iOS, and Android (#100814)
Gateway (additive, no protocol version bump): SessionEntry gains
lastReadAt/markedUnreadAt/lastActivityAt; session rows expose a derived
unread flag (explicit mark, or last read before latest activity; never-read
sessions stay read so upgrades do not light up). lastActivityAt is stamped
in the canonical post-run store update - user, channel, and cron runs count
as activity; heartbeat, internal-event, and preserved-state runs do not.
sessions.patch gains unread; sessions.create gains fork (transcript fork
from parentSessionKey under the parent lifecycle lock, refusing active,
concurrently-changed, and oversized parents, cross-agent aware).

Web sidebar: Pinned/custom-group/Ungrouped sections, unread dots, kebab and
right-click context menu (pin, mark unread/read, rename, fork, move to group,
archive, delete guarded for agent main sessions and active runs), mark-read
on view with loop-safe re-acknowledgement and failure retry; sessions page
gets unread + fork actions and shared custom-group helpers.

iOS Command Center: grouped sections, unread/pin indicators, Show Archived
gated on per-entry state, full context menu with rename/new-group alerts and
delete confirmation, current-session preview guarantee, read-episode
re-acknowledgement; new patch/delete/fork transport calls; Swift protocol
models regenerated.

Android SessionsScreen: grouped headers, unread/pin indicators, Archived
filter gated on per-entry state, long-press menu with the full control set,
agent-scoped forks, explicit label/category clears from session events,
main-session fallback when archiving/deleting the open chat, read-episode
re-acknowledgement with failure retry.

Closes #100739
2026-07-06 14:30:55 +01:00
Peter Steinberger
f53346944d feat: correlate native search outcomes in audit history (#98704)
* feat: correlate native search outcomes in audit history

Metadata-only audit ledger for agent runs and tool actions in the shared
state DB: stable event identity, closed action/status/error vocabularies,
one-way-hashed tool-call ids, never-inferred terminal outcomes for native
web-search (explicit completed/failed only; otherwise unknown), bounded
retention, audit.list gateway RPC and openclaw audit CLI. Squashed from
the 82-commit audit stack for replay onto current main.

* feat(audit): add audit.enabled config gate (default on)

The metadata-only audit ledger records by default: an audit trail enabled
only after an incident cannot explain the incident, and the rows are
strictly less sensitive than the transcripts every install already
stores. audit.enabled=false stops new writes at the gateway subscription
seam; audit.list and openclaw audit keep serving existing records until
they expire. Documented in the configuration reference, protocol page,
and CLI reference.

* fix: repair full-matrix CI findings after rebase

- break the dynamic-tools/dynamic-tool-execution import cycle by
  extracting resolveCodexToolAbortTerminalReason into a leaf module
- restore main's session-worktree protocol exports lost in the
  index.ts auto-merge
- register the audit event writer worker as a knip entry point
- docs table formatting; subagent wait-cancellation test scoped to its
  audit intent (outcome + timing) and advanced past main's new
  lifecycle-timeout retry grace
2026-07-06 12:30:12 +01:00
Peter Steinberger
827402243d feat: add Anthropic and OpenAI cost history (#100672)
* feat(providers): add admin cost history

* fix(ui): sync cron raw-copy baseline

* fix(usage): harden provider cost credentials

* fix(ui): refresh raw-copy baseline

* docs: refresh documentation map

* fix(ci): sync provider usage baselines

* fix(ui): hide zero-cost history bars

* docs(changelog): defer provider cost note
2026-07-06 12:06:55 +01:00
Piotr Durlej
f46fc8c7ad docs(channels): clarify message receipt evidence (#90063)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 10:39:19 +01:00
Peter Steinberger
b4b1984fe7 feat(gateway): start a new chat session in a managed worktree (#100788)
Adds an additive worktree flag to sessions.create so any new chat can run in an
isolated managed worktree of the agent's git workspace, with the branch checked
out and .worktreeinclude provisioning applied. The session's spawnedCwd points at
the matching subdirectory inside the worktree so chat runs, CLI, and the file
browser execute there. agents.list gains workspaceGit (workspace or an ancestor
is a git checkout) to gate the affordance; web sidebar, iOS, and Android expose a
New-Chat-in-worktree action. Uses the method's operator.write scope, but the
.openclaw/worktree-setup.sh step runs only for operator.admin callers since it
executes repo code. Deleting the session, or leaving via a plain New Chat, clears
the cwd and lossless-removes the worktree; idle GC treats recent session activity
as worktree activity so an active session's checkout is never swept.

Live-verified end-to-end on a real gateway; follow-up to #100535 (issue #100534).
2026-07-06 10:23:41 +01:00
Peter Steinberger
d6801f23d4 feat(browser): restore driver "extension" via a loopback Chrome extension relay (no remote-debugging prompt) (#100619)
* feat(browser): restore driver "extension" via loopback Chrome extension relay

Reintroduces browser profile driver "extension" (removed in 2026.3.22) as a
loopback relay that drives the user's signed-in Chrome through an MV3 extension
instead of the remote-debugging port. This avoids Chrome's blocking "Allow
remote debugging?" prompt, which cannot be clicked when the operator drives
OpenClaw from a phone. Automated tabs live in an "OpenClaw" tab group (the
consent boundary), mirroring the Codex/Claude-in-Chrome model.

- relay bridge synthesizes the CDP browser target surface for Playwright
  connectOverCDP and forwards session-scoped commands to chrome.debugger
- relay server binds loopback only; both sides authenticate with a token
  derived (HMAC-SHA256) from gateway auth, so the raw credential never reaches
  Chrome; extension origin + loopback Host checks guard the upgrade
- built-in "chrome" profile; distinct relay ports per extension profile;
  relay reconciles on auth rotation / cdpPort change and prunes removed profiles
- doctor + status surface the extension transport; doctor keeps repairing the
  retired relay endpoint URL on legacy "extension" profiles

Refs #53599

* feat(browser): bundle the OpenClaw MV3 Chrome extension

Thin MV3 extension (chrome-extension/): a WebSocket client to the loopback
relay plus chrome.debugger forwarding and OpenClaw tab-group management. All
CDP target synthesis lives server-side in the relay bridge, so the extension
stays a dumb transport (the removed 2026.3 extension put that logic in a
1000-line untestable service worker). Popup handles pairing and per-tab share
toggle; `openclaw browser extension path|pair` load and pair it. A build copy
hook stages it into dist so the load path is stable.

Refs #53599

* docs(browser): document the Chrome extension profile

Adds docs/tools/chrome-extension for the restored extension driver (install,
pair, tab-group consent model, security posture) and wires it into the browser
docs profile section and nav.

Refs #53599

* feat(browser): make the extension relay work on remote browser nodes

Derives the relay auth token from a host-local secret in the credentials dir
(created on first use) instead of gateway auth. Each machine that runs a
browser — the gateway host and every browser node host — owns its own token, so
the extension pairs with whichever machine hosts its Chrome and no gateway
credential travels to a node. The node host already runs the shared browser
control bootstrap, so this is all that was missing for cross-machine control.

Also removes the "relay needs gateway auth before it can start" failure mode:
startup and `openclaw browser extension pair` ensure the secret exists.

Refs #53599

* fix(browser): harden relay secret creation and satisfy CI lint/typecheck

- Make the host-local relay secret creation atomic (O_CREAT|O_EXCL + adopt the
  winner on EEXIST) so the gateway service and `extension pair` CLI cannot mint
  divergent tokens on a fresh host (would 401 until restart); credentials dir
  created mode 0700. (adversarial review finding)
- Resolve type-aware oxlint findings across the relay + extension: unknown catch
  vars, addEventListener over ws.on* in the MV3 worker, void async listeners,
  drop useless returns/spreads, Object.assign over map-spread, safe ws frame
  decode (Buffer[]/ArrayBuffer), toSorted.
- Add extensionRelayDefaultPort/extensionRelayPorts to remaining test config
  literals; type the extension relay-core module (.d.ts, excluded from dist);
  regenerate docs_map.

* fix(browser): satisfy OpenGrep security policy on the relay

- Hash both operands before timingSafeEqual so token comparison has no
  length short-circuit (GHSA-JJ6Q-RRRF-H66H).
- Bound the relay WebSocketServer with maxPayload (64 MiB, headroom for CDP
  screenshots/bodies) against oversized frames (GHSA-VW3H-Q6XQ-JJM5).
- Rewrite the config test env helper to avoid the skill-env-host-injection
  shape (GHSA-82G8-464F-2MV7); it is a test-only env swap.
2026-07-06 10:08:27 +01:00
Vincent Koc
8b2e9ddc64 improve(skills): reactive-correction capture with shared workshop invariant (#100576) (#100576)
Reactive corrections ("that's not what I asked", "stop doing X") now
count as durable signals: expanded extraction patterns, vocabulary
routing to existing workspace skills, per-skill grouping. Both capture
modes share one invariant: a bounded signal-fingerprint ring on the
session entry prevents replaying applied/rejected corrections, pending
autocapture-owned proposals are revised instead of skipped, /learn-style
turns suppress duplicate agent-end capture, and extraction runs before
any skill discovery. Autonomy off keeps the suggest-tier offer; autonomy
on files/revises proposals directly.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 09:50:46 +01:00
Masato Hoshino
310c2f58b9 improve(cron): show consecutive failure count and last error in cron CLI output (#99602)
* improve(cron): show consecutive failure count and last error in cron list/show

* improve(cron): show consecutive failure count and last error in cron CLI output

* fix(clownfish): address review for live-pr-inventory-20260706T074223-002 (1)

---------

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
2026-07-06 01:44:51 -07:00
Peter Steinberger
1b44efec8c feat(ui): redesign session goal into interactive composer pill with elapsed time and /goal edit (#100736)
* feat(ui): redesign session goal into interactive composer pill with elapsed time and /goal edit

* docs: align goal command table cell padding

* docs: regenerate docs map for goal Control UI section
2026-07-06 09:42:49 +01:00
Masato Hoshino
e7ca90e3af fix(hooks): flag hook event names that no core trigger emits (#99456)
* fix(hooks): flag hook event names that no trigger site emits

* docs(hooks): clarify bare family subscriptions in unknown-event note

* fix(hooks): word unknown-event diagnostics around core-emitted keys

* fix(hooks): apply unknown-event advisory to legacy config handlers too
2026-07-06 01:30:13 -07:00
Peter Steinberger
8d1668c441 fix(ios): harden Apple Watch pairing activation (#100732) 2026-07-06 09:16:02 +01:00
Peter Steinberger
d7d19a3a8e fix(openai): reuse Codex auth for realtime voice (#100671)
Co-authored-by: Peter Steinberger <steipete@openai.com>
2026-07-06 08:08:26 +01:00
Peter Steinberger
988c4d45dc docs(android): credit landed app improvements (#100702)
* docs(android): credit landed app improvements

* docs: sync ClawHub map
2026-07-06 08:06:54 +01:00
Peter Steinberger
1e2e7fb936 feat(skills): suggest saving detected reusable workflows by default (#95477) (#100692)
Adds the middle tier between capture-off and autonomous capture: when
autonomy is disabled, detected durable-instruction signals record a
one-shot pendingSkillSuggestion on the session entry (signal-hash
fingerprint prevents transcript-history replay), and the next
non-heartbeat turn atomically consumes it and injects one bounded
user-role line offering to save the skill. The agent offers, the user
decides; skill_workshop approval flow unchanged; no new config.
2026-07-06 07:54:51 +01:00
Peter Steinberger
037ad2bdfb feat(telegram): offer BotFather web app flow in setup help and docs (#100540) 2026-07-06 07:48:55 +01:00
Ayaan Zaidi
a18708c5c1 feat(gateway): add persisted crash-loop breaker and fatal-config exit contract
Gateways that crash-loop under systemd/launchd previously flapped forever
with no persisted state and no supervisor signal. The gateway now records
every boot outcome in the shared state DB (gateway_boot_lifecycle); three
unclean boots within five minutes trip a breaker that boots the gateway in
safe mode: full control plane available, channel/provider auto-start
suppressed at the channel-manager seam (startup, config hot-reload,
secrets.reload) with manual channels.start override, one stability bundle
per trip. The breaker re-evaluates each boot and logs recovery when the
window drains. Slow shutdowns record forced_stop and never count as
crashes; /readyz stays ready and reports suppressed channels; the health
monitor treats suppressed accounts as expected-stopped. Fatal invalid-config
errors now exit 78 (EX_CONFIG) on both the startup and unhandled-rejection
paths, engaging the systemd unit's pre-existing RestartPreventExitStatus=78
so supervisors stop relaunching until the config is fixed.
2026-07-06 06:45:55 +00:00
Peter Steinberger
2830b3ef38 fix(browser): diagnose empty WSL2 Chrome replies (#100590)
* fix(browser): diagnose Windows CDP listener mismatch

Base the repair on #93481 while matching Chromium's IPv4-first, IPv6-fallback listener contract and keeping CDP exposure loopback-scoped.

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

* style(docs): format browser troubleshooting table

* docs: refresh browser troubleshooting map

* fix(browser): diagnose reset CDP replies

* docs: refresh browser troubleshooting map

---------

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>
2026-07-06 07:42:02 +01:00
Peter Steinberger
133ca4b469 feat(skills): diagnose skill_workshop hidden by tool policy (#100654)
* feat(skills): diagnose skill_workshop hidden by tool policy (#87570)

Workshop can be enabled and auto-capturing while tools.profile hides the
skill_workshop tool; every inspection surface looked healthy. plugins
inspect and openclaw doctor now name the excluding policy layer (global/
agent/provider profile, allowlist, denylist) and the exact alsoAllow
grant to add, via a shared resolveSkillWorkshopToolPolicyAvailability
helper that /learn's guard now reuses instead of composing policy
itself. Diagnosis only; no policy behavior change.

* ci: retrigger
2026-07-06 07:21:08 +01:00
Peter Steinberger
62d957634c fix(agents): cap effective compaction reserve (#100621)
* fix(agents): cap effective compaction reserve

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* docs(changelog): link small-context compaction fix

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 06:49:44 +01:00
Peter Steinberger
dd972b8bf7 fix: replies fail when memory flush is exhausted (#100618)
* fix(reply): recover from memory flush exhaustion

Co-authored-by: 忻役 <xinyi@mininglamp.com>

Co-authored-by: Jerry-Xin <jerryxin0@gmail.com>

* test(reply): remove unused memory flush result

---------

Co-authored-by: Jerry-Xin <jerryxin0@gmail.com>
2026-07-06 06:41:16 +01:00
Peter Steinberger
d537139521 feat(macos): adopt the shared read-only chat transcript cache (#100275)
* feat(macos): adopt shared read-only chat transcript cache

Cache-first cold open for the macOS chat window/panel: the last known
transcript and session list paint immediately from the shared SQLite
transcript cache, then live gateway history replaces them wholesale.
Recent chats stay browsable read-only while the gateway is unreachable;
sending remains gated by connection state.

- Wires OpenClawChatSQLiteTranscriptCache into WebChatSwiftUIWindowController;
  DB at ~/Library/Application Support/OpenClaw/chat-cache.sqlite.
- Gateway identity (MacChatTranscriptCache.gatewayID), derivable offline:
  local keys on the canonical gateway state dir; remote/direct keys on the
  full canonical URL (scheme, host, resolved port, percent-encoded
  path/query); remote/ssh keys on the SSH target plus the resolved remote
  gateway port, mirroring the tunnel port resolution. Unconfigured mode
  gets no cache.
- macOS file protection: no per-file Data Protection classes; iOS-only
  attribute stays gated behind #if os(iOS) in the shared store, and the
  per-user container plus FileVault protect at rest.
- Onboarding chat stays uncached (transient guided setup session).

Part of #100194

* feat(macos): wire the offline command outbox into chat windows

* style(macos): fix orphaned doc comment; regenerate docs map

* style(macos): doc-comment lint fix; regenerate docs map on current main
2026-07-06 05:57:16 +01:00
Peter Steinberger
6441858e21 docs: refresh generated docs map (#100603) 2026-07-06 05:47:52 +01:00
Sulaga
2b51c255f8 feat(tencent): add Tencent Hy3 provider (TokenHub and TokenPlan) (#99076)
Summary:
- Merged feat(tencent): add Tencent Hy3 provider (TokenHub and TokenPlan) after ClawSweeper review.

Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Included post-review commit in the final squash: fix(tencent): preserve TokenHub auth compatibility
- Included post-review commit in the final squash: refactor(tencent): unify TokenPlan env/flag naming with TokenHub
- Included post-review commit in the final squash: docs: refresh Tencent provider docs metadata
- Included post-review commit in the final squash: fix: allow TokenPlan provider config overlays
- Included post-review commit in the final squash: docs: dedupe Tencent provider glossary labels
- Included post-review commit in the final squash: fix(tencent): repair TokenHub model defaults

Validation:
- ClawSweeper review passed for head 30c9fc130f.
- Required merge gates passed before the squash merge.

Prepared head SHA: 30c9fc130f
Review: https://github.com/openclaw/openclaw/pull/99076#issuecomment-4888527271

Co-authored-by: leisang <leisang@tencent.com>
Co-authored-by: Mason Huang <masonxhuang@tencent.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: hxy91819
2026-07-06 04:29:48 +00:00
harish ganeshmurthy
cfcdf2a519 fix(tui): follow active gateway port (#73338)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-06 05:27:35 +01:00
Peter Steinberger
0acd851a3b feat(agents): add managed git worktree lifecycle (create/provision/snapshot/restore/GC) (#100535)
Centralized managed worktrees under <state-dir>/worktrees/<repo-fingerprint>/<name>
with branch-per-task (openclaw/<name>), .worktreeinclude provisioning, an optional
.openclaw/worktree-setup.sh repo hook, and a SQLite registry in the shared state DB.
Removal always snapshots the tree (untracked included, gitignored excluded) to
refs/openclaw/snapshots/<id>; restore rebuilds the branch at the original commit with
the snapshot content as uncommitted state. Lossless run-end cleanup, 7-day idle GC for
run-owned worktrees (manual exempt), orphan reconciliation, 30-day snapshot retention.
Surfaces: worktrees.* gateway RPC (operator.admin mutations), openclaw worktrees CLI,
Control UI page, plugin-SDK facade + Workboard kind:"worktree" materialization.

E2E-verified on Testbox: full create->work->remove->restore->gc lifecycle.
2026-07-06 05:24:58 +01:00
Peter Steinberger
4b7661e9a0 feat(ios): durable offline command outbox for chat sends (#100331)
* feat(ios): durable offline command outbox for chat sends

Text messages sent while the gateway is unreachable queue in a durable
per-gateway outbox (new outbox_commands table in the per-gateway chat
cache SQLite store, schema v2) instead of failing. Queued bubbles render
with visible Queued/Sending/Not sent states and flush strictly in
createdAt order once transport health recovers; each command's client
UUID rides as the send idempotency key, so at-least-once delivery plus
gateway dedupe keeps the transcript exact.

Contract summary:
- Bounds: 50 queued commands per gateway; refused enqueues keep the
  draft. Queued rows older than 48h expire to failed("expired") rather
  than silently sending stale commands; tap-to-retry refreshes
  createdAt so an expired row can resend as new intent.
- Failure taxonomy: transport-level failures keep rows queued without
  burning retry attempts (backoff ladder, then health drops so the
  reconnect machinery owns pacing); gateway rejections burn attempts
  and fail terminally after 3, with context-menu retry/delete.
- Deletes are tombstoned synchronously and rechecked after the claim
  await so an active flush can never send a removed command; Delete is
  hidden while a bubble is already in flight; offline enqueue is
  guarded against double submit during the health probe.
- Post-reconnect live sends route behind draining outbox rows (FIFO),
  and a cold open assumes a backlog until restore adopts durable rows.
- Crash safety: 'sending' rows revert to 'queued' at startup; flushed
  turns are spliced into the session's cached transcript before their
  outbox row is deleted, and stale history snapshots cannot evict a
  just-flushed turn until a snapshot confirms it.
- Per-gateway scoping and purge ride the transcript cache: one SQLite
  file per gateway; reset/forget drops the queue with the cache.
  Fixture/unpaired transports get no outbox.

Part of #46664

* chore(ios): sync native i18n inventory

* style(chat-ui): satisfy strict SwiftFormat lint (doc comment, scope blank line)
2026-07-06 05:23:46 +01:00
Peter Steinberger
bf04d049fa feat(goals): keep active session goals in per-turn context + continuance QA scenarios (#100468)
* feat(goals): keep active session goals in per-turn context (#100409)

Active goals now inject one bounded user-role context line on every
non-heartbeat turn, refreshed at queued/interrupt admission via
provenance-tracked generated lines so operator stops take effect
immediately. Adds qa/scenarios/goals continuance scenarios and
goals.* coverage IDs.

* docs: regenerate docs map for goal context section

* fix(qa): use requiredChannelDriver instead of execution.channel pin in goal scenarios
2026-07-06 04:55:10 +01:00
Peter Steinberger
f53103de72 fix(skills): make Skill Workshop lifecycle approvals decidable and non-wedging (#91266, #94249, #93173) (#100498)
Approval wait now fits inside the Codex dynamic-tool watchdog (70s +10s
gateway grace under the 90s kill), approval cards carry proposal id,
skill name, description, file count, and body size (spoof-safe
rendering), and timeouts return a structured pending-not-failed outcome
instead of a bare error. Expired requests cannot execute late; no
auto-apply; generic plugin approvals unchanged.
2026-07-06 04:54:48 +01:00
Peter Steinberger
62ecc2306c feat(commands): add /learn to draft skills from recent work (#100442)
* feat(commands): add /learn to draft skills from recent work (#100408)

/learn rewrites the turn into a standards-guided Skill Workshop authoring
instruction: the agent gathers named sources (or distills the current
conversation) and files ONE pending skill proposal via skill_workshop.
Approval flow unchanged; sandboxed/tool-restricted agents get a clear
unavailable reply. Extracts the harness OpenClaw-tools predicate into
shared helpers and reserves the command name against plugin shadowing.

* docs: regenerate docs map for /learn section
2026-07-06 04:54:22 +01:00
Peter Steinberger
07e2d633cc feat: show auto-detected provider plans and billing (#100520)
* feat(providers): auto-discover usage billing

* feat(ui): show provider plans and billing

* fix(ui): translate provider billing labels
2026-07-06 04:53:09 +01:00
Peter Steinberger
2bed394793 feat(gateway): add system.info RPC and Gateway Host card in Settings (#100478)
* feat(gateway): add system.info RPC and Gateway Host card in Settings

Settings quick page now shows where the Gateway runs and how the host
is doing: machine name, LAN address and runtime port, OS, Node/PID,
uptime, CPU count and load, RAM, and free disk on the state-dir volume.
Backed by a new additive operator.read RPC (system.info); the card
polls every 10s while visible and hides for clients without the read
scope or against older gateways.

Refs #100465

* docs: regenerate docs map for Gateway host status section

* fix(gateway): harden system info compatibility

* fix(ui): clear stale gateway host info

* docs(changelog): note gateway host status
2026-07-06 04:29:19 +01:00
sunlit-deng
ae53570ea8 fix(browser): notify agent when click triggers download (#93307)
* fix(browser): drain download saves and use monotonic cursor for act response

- Add drainPendingDownloadSaves() to wait for in-flight saveAs before sampling
- Use monotonic downloadSeq cursor instead of bounded-list length
- Propagate downloads info in POST /act response for click/batch/evaluate

Fixes #93250

* fix(lint): add braces around single-line if returns

Fixes eslint(curly) failures in drainPendingDownloadSaves and
pickNewDownloads. PR #93307 required CI gate.

Ref: ClawSweeper P1 review finding

* fix(browser): scope act download metadata to action

* fix(browser): broadcast downloads to all active captures to prevent misattribution

When concurrent /act calls overlap on the same page, using
state.actionDownloadCaptures.at(-1) assigned downloads to the wrong
action's capture. Push managed save promises to all active captures
so the triggering action always receives its download metadata.

Also adds regression tests: broadcast-to-all-captures, sequential
capture isolation, and strengthen the dispose test to assert no
re-capture after disposal.

* fix(browser): prevent unhandled rejection when download capture action throws before drain

Move managedSave.catch() before the captures-branch check so the
rejection handler always runs, preventing an unhandled promise
rejection when the action throws before drain() is called. Simplify
the handler by removing the now-dead return + catch at the bottom.

* fix(browser): type downloads in BrowserActResponse, fix lint unused var

- Add optional downloads field to BrowserActResponse type contract so
  typed callers of browserAct() can consume the new payload without casts.
- Remove unused afterDispose variable in pw-session tests (lint fix).

* fix(test): correct post-dispose download assertion

capture.promises is not cleared by dispose(), so re-draining a disposed
capture still returns pre-dispose results. This is benign — callers
should drain before disposing. Update the test to assert the actual
behavior (still shows old results, new download not captured).

* test(browser): cover /act download metadata response

* refactor(browser): report action-owned downloads safely

* fix(browser): close action download ownership races

* test(browser): type action download capture mock

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 04:07:16 +01:00
Vincent Koc
0bd2a0b879 ci(sdk): refresh plugin api baseline hash 2026-07-06 05:02:28 +02:00
clawSean
d84aabf642 feat: add channel pairing request hook (#97733)
* feat: add channel pairing request hook

* fix(plugin-sdk): keep pairing hook types internal

* docs: regenerate docs map

* docs: regenerate docs map

* docs: regenerate docs map

* fix(plugin-sdk): keep pairing hook types internal

* fix(plugin-sdk): keep pairing hook types internal

* docs: refresh plugin hook docs

* docs: refresh plugin hook docs

* docs: refresh plugin hook docs

---------

Co-authored-by: clawSean <260045960+clawSean@users.noreply.github.com>
Co-authored-by: Omar Shahine <omarshahine@users.noreply.github.com>
2026-07-05 19:11:58 -07:00
Peter Steinberger
c064cae040 feat(ui): preview GitHub issues and pull requests on hover (#100434)
* feat(ui): add GitHub link hover cards

* chore(ui): sync GitHub hover card copy baseline

* docs(changelog): defer GitHub preview entry
2026-07-06 03:11:46 +01:00
Peter Steinberger
e596e2850d fix(control-ui): keep the dashboard mounted with a reconnect banner on gateway drops (#100479)
* fix(control-ui): keep the dashboard mounted with a reconnect banner on gateway drops

Once a session is established, a dropped gateway WebSocket no longer
unmounts the dashboard into the login gate. The client's close handler
now reports willRetry (the same fact that drives its reconnect
scheduling), the gateway store derives a `reconnecting` snapshot state
from it (everConnected && willRetry), and the app shell stays mounted
with an amber "Gateway connection lost - reconnecting" banner plus a
Retry now action while the client retries with backoff. The login gate
is reserved for first connects, credential rejections, and manual gate
submissions; event-gap recovery also no longer flashes the gate.

createApplicationGateway moved from bootstrap.ts to gateway-store.ts
with an injectable client factory for direct behavior tests. Adds the
previously unstyled `.callout.warn` variant and a "Connection loss and
reconnect" docs section.

Fixes #100475

* chore(i18n): regenerate control-ui locale bundles for connection banner strings

* chore(control-ui): unbreak CI - add reconnecting to overlays snapshot fixture, regenerate docs map

* chore(i18n): re-sync locale metadata after rebase onto refreshed main locales

* chore(i18n): refresh raw-copy baseline after rebase
2026-07-06 02:55:07 +01:00
xingzhou
7a49b160a4 fix(browser): downloads complete over CDP connections (#89416)
* fix(browser): surface navigate downloads in CDP mode

* Validate navigation downloads before saving

* fix(browser): observe navigation download capture timeouts

* refactor(browser): unify managed download capture

* test(browser): satisfy download fixture lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 02:26:20 +01:00
Peter Steinberger
a6e19fe014 fix(slack): avoid repeated thread root media (#100516)
* fix(slack): avoid repeated thread root media

* test(slack): cover reset thread media seeding
2026-07-06 02:17:44 +01:00
Peter Steinberger
60cf7eaa00 feat(ui): make the sidebar session-first and minimal (#100386)
* feat(ui): bolder sidebar minimalism — pinned/chats session groups, compact icon footer, no brand header

* test(ui): align fixtures with single default pinned route; document pinned-cap invariant

* fix(ui): preserve sidebar session groups

* fix(ui): polish minimal sidebar behavior

* fix(ui): avoid duplicate pinned chat fallback

* docs(changelog): note sidebar layout refresh

* chore(i18n): preserve sidebar locale metadata

* fix(ui): reuse localized sessions label

* test(ui): follow localized sessions label

* chore(ui): trim sidebar landing churn

* docs(ui): update minimal sidebar guidance
2026-07-06 02:08:02 +01:00
scoootscooob
7e7fc0075e [codex] Honor all ack scope for room events (#87433)
* fix(discord): honor all ack scope for room events

* fix(channels): align all ack scope for room events

* fix(channels): centralize ambient ack scope

* test(telegram): restore room-event ack fixture

* test(discord): satisfy promise executor lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 01:28:41 +01:00
Peter Steinberger
5d8293c1fe feat(ios): read-only offline cache for chat sessions and transcripts (#100219)
* feat(ios): read-only offline cache for chat sessions and transcripts

Cache-first cold open for the iOS chat tab: the last known transcript and
session list render immediately from a local SQLite cache, then live gateway
history replaces them wholesale through the existing reconciliation path.
When the gateway is unreachable, recent sessions and transcripts stay
browsable read-only; sending remains gated by the existing connection state.

- New OpenClawChatTranscriptCache protocol seam plus SQLite-backed store in
  OpenClawChatUI (raw SQLite3, no new dependencies), scoped per gateway
  stableID so transcripts never leak across paired gateways.
- Bounds: 50 sessions, 50 transcripts, 200 messages per session; text rows
  only (attachment/binary payloads and tool arguments are stripped).
- Disposable cache: schema versioned via user_version; any open/schema/decode
  mismatch drops and rebuilds silently. File protection
  completeUntilFirstUserAuthentication on iOS.
- View model pre-paints from cache only until a live response applies
  (hasAppliedLiveHistory/hasAppliedLiveSessions guards); write-through is
  chained and off the render path.
- iOS wiring keys the chat view model identity on transport mode plus cache
  gateway ID so switching paired gateways rebuilds the view model.

Part of #100194

* fix(ios): harden offline transcript cache

* fix(ios): expose offline cached sessions

* fix(ios): isolate transcript caches by gateway

* chore(i18n): sync native inventory

* fix(ios): allow cache extension to replace messages
2026-07-06 01:02:15 +01:00
Hemant Sudarshan
bacd1c512a fix(browser): time out remote tab enumeration (#80147)
* fix(browser): time out remote tab enumeration

* chore: remove stale changelog entry

* fix(browser): isolate timed-out read cleanup

* fix(browser): isolate timed-out read cleanup

* test(browser): satisfy connection regression lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 00:56:05 +01:00