First connects backed by stored auth (URL/session token, password, or an
approved device token) now paint a small wiggling OpenClaw mark (delayed
fade-in, reduced-motion aware) until the hello resolves. The login gate
still owns credential-less first opens, rejected credentials, and manual
gate submissions.
Closes#101847
* feat(cron): add headless code-mode driver and trigger-script evaluator
Part A of cron event triggers: runCodeModeScriptHeadless runs a script
to completion (exec/settle/resume, no snapshots, no session), plus the
cron-facing evaluator with per-job tool catalog cache, semaphore, 16KB
state cap, and closed failure taxonomy.
* fix(cron): correct trigger-script bootstrap flags and cache narrowing
* feat(cron): add event triggers (polled condition-watcher scripts)
Part B: trigger field on cron jobs gated by cron.triggers.enabled;
timer evaluates the script each due tick, quiet ticks leave no run
history, fired runs append the script message to the payload; once
semantics, min-interval floor, SQLite columns, RPC/CLI/agent-tool
surfaces, and docs.
* fix(cron): propagate triggerEval through startup catch-up outcomes
* fix(cron): honor cron staggering on quiet trigger ticks; fix trigger test types
* fix(cron): reject with Error reason in trigger-script abort test
* fix(cron): regenerate protocol/docs/snapshot artifacts and break madge cycle for trigger types
CI fixes for #101195: trigger evaluator result types move to the cron
types leaf (madge cycle), cron tool schema inventory gains trigger,
Swift protocol bindings + docs map + Linux prompt snapshots regenerated.
* fix(cron): drop underscore-dangle names in trigger code sync assert
* fix(cron): adopt registerHeadlessToolSearchCatalog after tool-search symbol localization
Upstream #101831 made registerToolSearchCatalog module-private; fold the
headless ref-only catalog registration into one public seam.
* fix(gateway): support native Windows exec approvals
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* chore: defer changelog entry to release
* test: use tracked approvals temp directories
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* feat(ui): redesign dashboard chrome with tiny top bar and sidebar search
Move the sidebar toggle to the top bar as a macOS-style panel button
(collapse on desktop, drawer on tablet/mobile), move search into a
sidebar field that opens the command palette, and move the color-mode
toggle into the sidebar footer. Shrink the top bar to 44px, make the
terminal toggle a quiet ghost button, and drop the shadow plate behind
the macOS titlebar brand mark so the transparent mascot renders bare.
Adds the missing common.colorModeOption i18n key (theme buttons were
announcing the raw key) and removes the dead theme-orb styles.
* fix(ui): translate common.colorModeOption across locale bundles
The i18n sync initially recorded English fallbacks for the new key,
which the ships-no-recorded-English-fallbacks gate rejects. Regenerated
with a real translation provider; all 20 locales now carry translated
values (fallbacks=0).
* refactor(ui): unify the topbar sidebar toggle into one button
One button drives both modes: rail collapse on desktop and the
slide-over drawer at the ≤1100px breakpoint, decided via matchMedia
(with the legacy addListener fallback used elsewhere in bootstrap).
Replaces the previous pair of CSS-swapped buttons.
* ci(mantis): add web ui chat proof lane
* ci(mantis): tighten web ui proof candidate parsing
* ci: tighten Mantis Web UI proof lane
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix: show exported tool results in trace viewers
* fix(diagnostics-otel): emit semconv response key and execute_tool identity so trace viewers show tool results
---------
Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
* feat: add openclaw promos CLI for ClawHub promotional model offers
* fix: harden promos claim auth validation and sanitize remote promo text
* fix: enforce promo window client-side and validate slug contract
* fix: shell-safe model ref contract and explicit --api-key override
* fix: hold promotion aliases to the models alias contract
* docs: document argv-credential contract and env alternative for promos claim
* fix: enforce provider plugin enablement on the credential-reuse claim path
* fix: require plugin install before credential-reuse shortcut in promos claim
* fix: run runtime plugin repair on promo defaults and harden identifier parsing
* fix: distinct message for contract-invalid promo aliases
* fix(cli): validate promotion plugin contracts
* fix(cli): recheck promotion window before claim
* feat(cli): surface ClawHub promotions in models list via the hosted feed
Passive discovery for promotional model offers. A cadence-gated (24h),
fail-silent conditional GET of ClawHub's immutable promotions feed
snapshot (If-None-Match -> 304, short 2.5s timeout, unauthenticated so
CDN caches stay unfragmented) is cached in two new shared-state-DB
tables, fully separate from update_check_state. models list renders an
'Available via promotion' group for live offers whose models are not in
the user's configured set (including the zero-row fresh-install path),
tags claimed models promo / promo ended from provenance recorded at
claim time, and prints a one-time notice per newly seen offer; promos
list and claim mark offers as seen. Machine outputs stay clean, snapshot
sequence is monotonic against stale edges, and claims still revalidate
against the live API so the kill switch always wins.
* style: satisfy lint on promotions feed additions
no-useless-fallback-in-spread on the optional request headers and
no-map-spread in claim-provenance row mapping.
* fix(cli): harden promotions feed cache
* fix(cli): honor live promotion validity
* refactor(codex): raise app-server floor to 0.142 and drop range-compat protocol paths
* refactor(codex): model subagent mirror state as one map
* style(codex): format event-projector
* test(codex): drop unused shared-client test import
* refactor(codex): drop v1-era notification field aliases
* fix(codex): teach models to load deferred native spawn_agent via tool_search
* docs(codex): realign harness config tables
* docs(changelog): note Codex app-server protocol update
* feat(browser): direct extension→gateway relay path for remote Chrome (#53599)
Let the OpenClaw Chrome extension pair directly to a remote gateway over
wss:// with no OpenClaw node host on the browser machine — the managed-hosting
path from #53599 (extension is the only thing installed on the laptop).
- Gateway route /browser/extension registered by the browser plugin with
auth:"plugin" + no nodeCapability, so the gateway does not pre-enforce token
auth (browser WebSockets cannot send an Authorization header). The upgrade
handler self-validates the host-local relay secret from ?token=, origin-checks
chrome-extension://, resolves the extension profile, then attaches the socket
to the same ExtensionRelayBridge the loopback relay uses. All CDP synthesis,
tab-group scoping, and the in-process Playwright /cdp client are unchanged.
- `openclaw browser extension pair --gateway-url wss://host` prints a
wss://host/browser/extension#<secret> string; the path ends in /extension so
the extension's existing pairing parser accepts it with zero extension code
changes.
- relay-server: extract attachExtensionWebSocket + export requestToken /
isAllowedExtensionOrigin / EXTENSION_RELAY_MAX_PAYLOAD_BYTES so loopback and
gateway paths share one bind + one frame cap.
- runtime-lifecycle: dispose the shared gateway WebSocketServer on shutdown.
- docs: three remote topologies (same host / direct-to-gateway / via node host).
Coverage: 6 unit tests for the handler's path/503/403/404/401/attach branches.
The full extension→bridge→CDP→Chrome loop over /browser/extension was live-proven
with a real Chrome + the built extension. The real gateway upgrade→handleUpgrade
dispatch for an auth:"plugin" unprotected route is verified against core
(server-http.ts, plugins-http.ts, route-auth.ts).
* fix(browser): harden remote extension pairing
Behavior: a plugin before_agent_finalize hook that never resolves could previously freeze an agent run forever after a successful compaction retry, with no errors and no recovery from a gateway restart; this was the frozen-runner mechanism behind #84777. before_agent_finalize now has the same 15s default budget as sibling modifying hooks and fails open with the original final answer, converting the freeze into a bounded delay.
Surface: plugin hook runner defaults (src/plugins/hooks.ts), docs/plugins/hooks.md.
Refs #84777.
Fixes rough edges in the standalone install flow (install.sh -> openclaw onboard), found and verified by running the flow in a clean container and on a clean macOS Tahoe VM:
- Provider auth setup failures (e.g. the preselected "Anthropic Claude CLI" option on a host without a Claude CLI login) no longer kill the whole wizard. The interactive wizard notes the error and returns to the provider picker; explicit --auth-choice automation still fails fast.
- Onboarding config now persists before the channel/search/skills steps, so a crash or cancel during channel pairing no longer loses auth + gateway decisions.
- With model auth skipped, finalize no longer auto-sends the "Wake up, my friend!" message (which always failed with a provider auth error). The hatch seed is gated on usable model credentials and a "Model auth missing" note explains the next step.
- Search provider picker no longer labels non-key credentials (e.g. SearXNG base URL) as "API key required".
- install.sh no longer warns "PATH missing npm global bin dir" with manual fix steps after it already persisted the export line; it reports the PATH was updated and how to reload the current shell.
- Removed the dead interactive hooks onboarding step (setupInternalHooks); quickstart enables default hooks silently.
Verified live per fix in a clean Debian/Node 24 container and on a clean macOS 26.5 Parallels VM (wizard re-prompt, SearXNG label), plus wizard/onboard test suites and tsgo:core.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Tracks per-skill usage from the skill.used diagnostic event (trusted-only
delivery, file-scoped identity), sweeps workshop-created skills daily from
gateway maintenance (active -> stale 30d -> archived 90d, pinned bypass,
restore-only unarchive, files never touched), filters archived skills from
snapshots fail-open, reports workspace-scoped overlap candidates, and adds
openclaw skills curator CLI, additive gateway methods, and a warn-only
doctor finding. Zero new config keys; SQLite/Kysely state only.
* feat(ui): rename, delete, and toggle sidebar session groups
Sidebar group headers gain a kebab + right-click menu with Rename group,
New group, and Delete group. Rename/delete enumerate every member session
(active + archived, across agents) via unbounded sessions.list queries and
patch category per session; delete keeps sessions and moves them to
Ungrouped. Stored-but-empty groups render as sections, and the sidebar
sort popover gains a persisted Group by toggle (Custom groups / None).
* test(ui): capture sidebar group management UI proof shots
* fix(ui): page session-group enumeration past the gateway's 100-row default
sessions.list caps an absent limit at SESSIONS_LIST_DEFAULT_LIMIT (100), so
the rename/delete member enumeration now walks nextOffset pages explicitly;
a silent cap would strand members in the old group on stores >100 sessions.
* chore(i18n): restore fallback-key tracking for new sidebar group strings after rebase
* chore(i18n): translate new sidebar group strings across locales