Commit Graph

70070 Commits

Author SHA1 Message Date
Peter Steinberger
d45e024dca fix(cron): persist startup catch-up deferrals (#110351) 2026-07-18 04:12:15 +01:00
Peter Steinberger
75d0260e0c ci(release): enforce reusable permission ceiling (#110353) 2026-07-18 04:07:42 +01:00
Peter Steinberger
6e695c5e2c fix(cli): avoid macOS system CA exit hang (#110341)
Respawn one-shot macOS commands with Node's OpenSSL-backed CA store when system CA loading is inherited. This avoids an indefinite shutdown join on the Keychain loader worker while preserving system CA for Gateway, interactive, and explicit --use-system-ca processes.
2026-07-18 04:07:17 +01:00
Peter Steinberger
31ed59bdf6 feat: keep main agents aware of group activity (#110332)
* feat(sessions): auto-watch group activity from main

* feat(sessions): allow watchers to read watched sessions

* fix(sessions): skip group watches for system turns

* fix(sessions): preserve watched session semantics

* fix(channels): propagate effective dm scope

* fix(sessions): canonicalize main watch identity

* fix(sessions): distinguish ambient group watches

* fix(sessions): revoke ineligible ambient watches

* chore: drop CHANGELOG edit (release generation owns it)
2026-07-18 04:06:58 +01:00
Peter Steinberger
9dec7acc91 feat(macos): visible-markdown copy, full-message reader, and independent reasoning/tool toggles (#110276)
* feat(clients): copy visible markdown, full-message reader for truncated messages, and independent reasoning/tool toggles

* chore(i18n): translate new reader and trace strings and regenerate catalogs

* test(ios): adopt reader display-options API in render smoke tests
2026-07-18 04:05:50 +01:00
Peter Steinberger
ff9cb0f679 fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies (#110225)
* fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies

* chore(onboarding): document deliberate dmScope personal-agent default

* docs(security): align formal-verification dmScope claim with the personal-agent default
2026-07-18 03:54:45 +01:00
Vito Cappello
cd1ab40632 fix: gateway boots when a configured plugin payload is broken (#110239)
* fix: quarantine broken plugins during gateway startup

* fix(plugins): preserve degraded boot on package read errors

* fix(gateway): emit quarantine diagnostic once

* fix(gateway): refresh plugin quarantine every boot

* fix(gateway): harden plugin payload quarantine

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* fix(ci): satisfy plugin quarantine checks

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 03:50:50 +01:00
Peter Steinberger
73cf9ee908 feat(ui): Home page and identity-row IA for the five-zone sidebar (#110295)
* feat(ui): Home page, identity row as agent menu, Pages header, Threads-hosted actions

* fix(ui): rename Home badge local shadowing the lit state import
2026-07-18 03:48:32 +01:00
Peter Steinberger
010f662f48 fix(agents): keep declared-output tools visible in the truncated code mode index (#110317) 2026-07-18 03:48:28 +01:00
Peter Steinberger
0a5c2d127f test(qa): acknowledge kitchen sink plugin trust (#110335) 2026-07-18 03:47:43 +01:00
Peter Steinberger
90b4a12ee9 feat(linux): Quick Chat agent switcher, avatars, per-agent routing, and configurable shortcut (#110285)
* feat(linux): expand Quick Chat agent controls

* docs(linux): document Quick Chat controls

* fix(agents): keep avatar summary additive

* refactor(linux): trim Quick Chat dead Default impl and speculative focus-failure recovery

* fix(linux): destroy the Quick Chat window when hide fails after a rejected focus grab

* fix(linux): fail Quick Chat sends when the pinned agent vanishes; classify avatar-only identities as config-derived

* docs(linux): note the accepted cache-fresh send-validation tradeoff

* style: satisfy no-map-spread and rustfmt in Quick Chat parity surfaces
2026-07-18 03:44:49 +01:00
Peter Steinberger
bd8c5399d8 fix: restore iMessage and WhatsApp channel test coverage (#110327)
* test(imessage): mock core turn dispatch for media policy coverage

PR #110095 missed this iMessage media-policy test file.

* test(imessage): mock core turn dispatch for last-route coverage

* test(whatsapp): mock core turn dispatch for broadcast coverage

* test(imessage): drop type-dead terminal-admission branch in media harness
2026-07-18 03:44:10 +01:00
Peter Steinberger
19296b003b improve(agents): normalized web_search output contract with boundary-owned wrapping (#110308)
* feat: normalize web search output contract

* refactor(agents): promote web_search contract from a dedicated output module

* fix(agents): wrap unwrapped web_search text and pass unknown provider payloads through as raw

* fix(agents): gate web_search results branch on conforming rows and cover metadata fields

* fix(agents): gate every provider text path at the web_search boundary

* test(agents): align web_search fixtures with boundary-owned wrapping

* fix(agents): make the web_search boundary own the untrusted-content envelope

* fix(agents): report declared web_search errors first and align the documented contract

* fix(agents): bind envelope stripping to real markers and densify result rows

* fix(agents): emit canonical urls and a closed error code from web_search

* fix(agents): keep structured provider error diagnostics in the wrapped message

* fix(agents): satisfy production export and lint gates for the web_search contract
2026-07-18 03:39:29 +01:00
Peter Steinberger
6a6d3465d8 improve: shorten release candidate validation (#110316)
* ci(release): shorten candidate validation critical path

* ci(test): parallelize memory extension lane

* ci(release): preserve read-only candidate validation
2026-07-18 03:39:03 +01:00
Masato Hoshino
bbaaac4b44 fix(ui): preserve non-minute cron intervals on edit (#110034)
The Control UI rounded any every-schedule interval that is not a whole
number of minutes up to the next minute when reading a job into the edit
form (parseEverySchedule ceil): 30s and 90s and 4m6s all became a whole
number of minutes. Because addCronJob always rebuilds the schedule into
the cron.update patch, any save — including metadata-only edits that
never touch the schedule — silently rewrote the cadence (e.g. 30s → 60s,
90s → 120s) and re-anchored the job. CLI, API, and docs accept these
intervals, and the UI itself can create them, so the editor corrupted
cadences supported everywhere else.

Add a Seconds interval unit and read everyMs back into the largest unit
that divides it exactly (days → hours → minutes → seconds), rendering
sub-second remainders as exact decimal seconds built with BigInt
quotient/remainder. Every integer millisecond up to
Number.MAX_SAFE_INTEGER now round-trips losslessly, so a resave with the
same everyMs preserves the gateway's anchor inheritance. Gateway,
protocol, storage, and cron runtime are unchanged.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 03:34:31 +01:00
WhatsSkiLL
9f25b0dc12 fix(android): polish Wear light and dark surfaces (#110314) 2026-07-18 03:32:43 +01:00
Peter Steinberger
6a0f5541c6 feat(ui): permanent OpenClaw presence — pinned sidebar entry and Settings dock (#110269)
* feat(ui): add permanent OpenClaw navigation

* refactor(ui): drive Exit setup visibility with a typed onboarding property

The route view previously hid the button with an injected style tag (the page
file was owned by a parallel lane); render it conditionally instead.

* test(ui): use the navigation route-load cause literal

* fix(ui): request the caretaker greeting for permanent custodian visits

The onboarding welcome variant seeds the first-run setup proposal; the pinned
sidebar and Settings entries now omit it so post-setup visits get the normal
caretaker greeting, driven by the same route onboarding flag as the chrome.

* fix(ui): restart custodian session on mode change
2026-07-18 03:29:25 +01:00
Peter Steinberger
60ed910639 fix(diagnostics): own run activity listener lifecycle (#110312) 2026-07-18 03:29:06 +01:00
Peter Steinberger
53b53f1977 improve(agents): exact web_fetch output contract with cleaned result shape (#110223)
* feat: add web fetch output contract

* fix(agents): keep web_fetch contract schema module-local

* docs: refresh docs map for the web_fetch result section
2026-07-18 03:28:29 +01:00
Peter Steinberger
8c17d20cd9 improve(ci): preserve complete main validation during merge bursts (#110298)
* ci: serialize main and bound sticky caches

* fix(ci): pin cache warmer to validated SHA

* fix(ci): read current sticky retirement manifest
2026-07-18 03:27:54 +01:00
Peter Steinberger
125934addc feat(ios): harvest shared chat capabilities — verbosity, trace toggle, live talk level, sessions entry (#110254)
* feat(ios): wire verbosity, assistant trace toggle, live talk level, and chat-local sessions entry

* chore(i18n): translate new iOS chat strings and regenerate catalogs
2026-07-18 03:27:45 +01:00
xingzhou
1bd6280f85 fix(doctor): preserve Unicode in migration reports (#104851) 2026-07-18 03:26:39 +01:00
Peter Steinberger
b440cfb15e fix(gateway): occupied non-gateway ports exit nonzero (#110310)
* fix(gateway): reject unrelated occupied ports

* docs(changelog): defer gateway collision note

* test(gateway): isolate unconfirmed lock collision
2026-07-18 03:23:52 +01:00
Peter Steinberger
1746cea939 refactor(test): use shared temp directory cleanup (#110311) 2026-07-18 03:15:38 +01:00
Peter Steinberger
d8f2645c2c refactor(memory-wiki): move compiled cache to plugin state (#110167)
* feat(plugin-sdk): prepare memory prompts asynchronously

* refactor(memory-wiki): move compiled cache to plugin state

* fix(plugin-sdk): export memory prompt preparer type

* refactor(plugin-sdk): keep prompt preparer type private

* test(memory-wiki): isolate compiled cache state

* chore(memory-wiki): satisfy changed gates

* fix(memory): preserve prepared prompts across context engines

* docs(plugin-sdk): refresh API baseline

* fix(memory): revalidate prepared prompt ownership

* fix(codex): propagate sandboxed memory context

* test(memory-wiki): seed durable vault identity

* refactor(memory-wiki): keep cache lifecycle internal

* fix(memory-wiki): harden compiled cache publication

* style(memory-wiki): format cache lifecycle changes

* test(memory-wiki): support extension test lib target

* style(memory-wiki): remove redundant catch

* refactor(memory-wiki): keep vault generation helper private
2026-07-18 03:05:03 +01:00
Peter Steinberger
3d1b771035 fix(ci): catch script declaration drift before merge (#110248)
* fix(ci): verify script declaration contracts

* fix(ci): harden declaration export analysis

* fix(ci): cover opaque script module exports

* test(ci): cover cyclic script declaration barrels
2026-07-18 02:54:26 +01:00
Peter Steinberger
75e4103c57 feat(ui): five-zone sidebar — agent identity card, threads/groups/coding, footer bar (#110259)
* feat(ui): five-zone sidebar with agent identity card, threads/groups/coding zones, and footer bar

* fix(ui): promote main-session children via the gateway row's literal key

* fix(ui): filter and sort promoted main-session threads; hide empty Coding count

* fix(ui): collapsed zones no longer consume the visible session page budget

* fix(ui): a11y — offline card label and catalog lists outside the Coding list container

* fix(ui): zone headers use pre-pagination counts so paged-out zones stay visible

* chore(ui): document catalog-adoption dedup invariant on promoted threads

* chore(ui): seed five-zone sidebar fixtures in the mock-dev harness

* fix(ui): resolve the canonical global main key for the identity card under global scope

* fix(ui): global scope resolves the global sentinel as canonical main even pre-hello

* fix(ui): drop dead channelDisplayLabel, avoid map-spread, type zone test helper
2026-07-18 02:39:17 +01:00
morluto
cf63c83bf6 fix(qa-lab): close transport before gateway teardown (#106027)
* fix(qa-lab): close transport before gateway teardown

* test(qa-lab): bind teardown order to production plan

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:34:11 +01:00
mushuiyu886
8a234980ea fix(usage-bar): bound numeric verb arguments (#105297)
* fix(usage-bar): bound numeric verb arguments

* fix(usage-bar): preserve supported fixed precision

* fix(usage-bar): validate fixed precision

Co-authored-by: 杨浩宇0668001029 <yang.haoyu@xydigit.com>

* docs: refresh generated docs map

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:32:02 +01:00
Vito Cappello
c08ce42cef fix(cli): exit cleanly on migration refusal (#110207)
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
2026-07-18 02:29:44 +01:00
ZOOWH
e9553a80f9 fix(usage): guard malformed Gemini quota buckets (#106420)
* fix(usage): guard malformed Gemini quota buckets

* fix(usage): validate Gemini quota payloads

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:28:33 +01:00
Peter Steinberger
b6bac30e33 refactor(agent-core): delete the unused session harness layer (#110287) 2026-07-18 02:27:48 +01:00
Peter Steinberger
2e70de9d32 fix(mcp): own sandbox CSP fail-closed validation in the decoder (#110267)
* fix(mcp): reject sandbox CSP metadata that normalizes to no policy

A present ?csp= value that decodes to valid JSON but is not a usable CSP
(e.g. null or a wrong-shaped object) normalized to undefined and was
indistinguishable from an absent parameter, so the gateway served proxy
HTML under the default policy. encodeCsp omits the query param entirely
for such values, so a present-but-empty policy is never legitimate;
throw so the sandbox endpoint fails closed with 400. Found by review on
the revert of 73685b4e7c946; the gap predates that commit.

* fix(mcp): treat empty csp query value as malformed, not absent

?csp= with an empty value passed the falsy absent-guard and served proxy
HTML under the default policy. Only a truly absent parameter (null) may
skip validation; an empty string now falls through to JSON.parse and
fails closed with 400.

* refactor(gateway): drop redundant sandbox CSP handler guard

decodeMcpAppSandboxCsp now throws for every present-but-unusable value
(1ca26c508d added the same fail-closed behavior at the handler seam),
so the handler-level 'present but falsy' check is unreachable. Keep the
invariant in the decoder, which owns policy decode semantics.

* fix(test): reset diagnostic listener-presence mirror between non-isolated files

resetOpenClawGlobalDiagnosticState clears the listener sets and deletes
the diagnostic-events state key, but the listener-presence counts live
under a separate globalThis record and survived, so
hasInternalDiagnosticEventListeners() stayed true for every later file
in the worker once any file leaked a registration (e.g. the import-time
listener in src/logging/diagnostic-run-activity.ts whose stop handle is
lost to the module-registry reset). Zero the counts to match the cleared
sets. Root cause of the model-call-diagnostics flake in CI run
29624203224; #110288 added the victim-side reset, this fixes the class.
2026-07-18 02:25:34 +01:00
Peter Steinberger
57a3739622 fix(ci): regenerate docs_map for the live-tests heading 2026-07-17 21:25:29 -04:00
Wynne668
83da9500ae fix(node-host): guard Claude CLI pipe errors (#109794)
* fix(node-host): guard Claude CLI stdout/stderr pipe errors

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(node-host): make request mock generic to fix test-types CI failure

* test(node-host): harden child pipe regression

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:24:02 +01:00
sheyanmin
e57acb1d94 fix(tools-manager): bound GitHub releases response body to prevent unbounded read (#98480)
* fix(tools-manager): bound GitHub releases response body to prevent unbounded read

The agent helper-tool fallback for fd and ripgrep read GitHub's
latest-release response with Response.json(). That consumes the
complete remote body before parsing it, so a faulty or compromised
response could grow agent memory without a bound.

This change makes the release-metadata fetch use the shared
readResponseWithLimit helper with a 1 MiB cap.

Ref. https://github.com/openclaw/openclaw/pull/98480

* fix(tools-manager): use bounded release reader

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:22:49 +01:00
LiLan0125
3ec5ee6bb6 fix(cron): skip completed restart catchup slots (#101998)
* fix(cron): preserve exact restart boundaries

Co-authored-by: 李兰 0668001394 <li.lan3@xydigit.com>

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>

* fix(cron): suppress skipped restart slots

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
2026-07-18 02:19:00 +01:00
Peter Steinberger
7915203f47 test(ui): stabilize chat popover layout bounds (#110290) 2026-07-18 02:17:03 +01:00
Peter Steinberger
8fc859a26a fix: isolate macOS sessions.send follow-up test (#110291)
* test(gateway): isolate follow-up message count

* style(gateway): format follow-up status test
2026-07-18 02:15:58 +01:00
Peter Steinberger
afcca01f40 feat(sessions): raise default session-store disk budget to 10 GiB (#110221) 2026-07-18 02:14:39 +01:00
Peter Steinberger
71b9705029 test(agents): isolate model-call listener state (#110288) 2026-07-18 02:13:49 +01:00
ZOOWH
1c331b9b0f fix(clawrouter): sanitize attribution headers to ByteString (#106454)
* fix(clawrouter): sanitize bounded header ids

Co-authored-by: ZOOWH <xu.wenhan1@xydigit.com>

* fix(clawrouter): keep sanitized ids collision-resistant

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:12:53 +01:00
Peter Steinberger
9a30b607c5 test: speed up gateway async polling (#110289) 2026-07-18 02:11:50 +01:00
Peter Steinberger
0e3afe62c6 test: remove SIGTERM fixture readiness race (#110283) 2026-07-18 02:07:02 +01:00
Peter Steinberger
d2e07d89ae test(config): split help quality fixtures (#110268) 2026-07-18 02:06:38 +01:00
Patrick Erichsen
f9b860fc84 feat(plugins): order featured catalog by recency (#110273) 2026-07-17 18:06:13 -07:00
Leon-SK668
dcd8f962e3 fix(qqbot): add timeouts to API response reads (#103855)
* fix(qqbot): add timeouts to API response reads

* fix(qqbot): use guarded request deadlines

---------

Co-authored-by: Alix-007 <li.long15@xydigit.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:06:09 +01:00
Wynne668
bcc44ba1b1 fix(whatsapp): resolve abortPromise when stop signal already fired (#109903)
* fix(whatsapp): resolve abortPromise when stop signal already fired

waitForClose() races on abortPromise, but a pre-aborted gateway stop
signal never settled that promise because the abort listener was skipped.
Resolve abortPromise immediately when abortSignal.aborted is already true.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(whatsapp): resolve tsgo TS18048 and test mock in pre-aborted abortPromise fix

- Extract params.abortSignal to local const so tsgo can narrow the type
  through else-if control flow, fixing TS18048: possibly undefined
- Remove setupAbortController/ownerAcquireAbortController.abort() from
  the constructor's pre-aborted branch so openConnection() still works
  when the stop signal was already fired at construction time
- Use createSocketWithTransportEmitter() mock in the new test so
  shutdown() cleanup has sock.end() and ws.removeListener() available

* fix(whatsapp): preserve pre-aborted setup cancellation

* fix(whatsapp): unify connection abort handling

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 02:04:59 +01:00
Peter Steinberger
1ca26c508d fix(gateway): reject malformed MCP sandbox policy (#110264)
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-07-17 18:00:46 -07:00
Peter Steinberger
6f0f6af62e fix(discord): preserve gateway messages across dispatch crashes (#110274)
* fix(discord): adopt durable ingress drain for gateway messages

Gateway MESSAGE_CREATE events dispatched with only an in-memory/persistent
5-minute dedupe; a crash between receive and dispatch lost the message (live
sessions replay via RESUME, but session state is memory-only so a cold
restart re-IDENTIFYs — stated platform limitation: the drain closes the
receive->dispatch window, not cold downtime). Raw API messages now journal
durably (event_id = message snowflake, lane per channel/thread) before
normalization; dispatch runs through the core drain with deferred claims,
fan-out adoption, gated settlement, and 30d/5k tombstones. The persistent
guard is deleted after its RESUME duplicate-delivery parity test. Edits stay
outside the queue: only MessageCreateListener is registered, MESSAGE_UPDATE
never dispatches, so snowflake tombstones cannot swallow edit turns; a future
edit dispatcher must namespace its event ids.

Autoreview blocked by codex sandbox network in the build stage; full manual
review performed. Part of the #109657 fleet adoption program (wave 2).

* style(discord): keep drain-internal types and dispatcher unexported

* refactor(discord): move message dispatcher to its own module for the dead-export gate

* fix(discord): shutdown dispatch releases claims instead of tombstoning

Landing autoreview reproduced a real loss race: a dispatch entering after
dispatcher shutdown (or with an aborted signal) returned completed, so the
drain tombstoned a message that never ran and a restarted gateway skipped it
forever. Aborted-before-dispatch now returns failed-retryable so the claim
releases for replay. Test type imports of drain-internal types converted to
factory-derived types so the dead-export gate and typecheck agree.
2026-07-18 01:58:19 +01:00