Commit Graph

39138 Commits

Author SHA1 Message Date
Peter Steinberger
85e4bb438d fix: generated images no longer post twice (#110366)
* fix(agents): prevent duplicate generated media delivery

* fix(ios): sync reasoning activity translations

* fix(media): preserve malformed parent paths

* fix(media): distinguish network media references
2026-07-18 05:57:45 +01:00
Peter Steinberger
a89f01abf4 perf(sqlite): fast schema gates, background integrity verification, and downgrade protection (#110271)
* perf(sqlite): gate schema version before integrity scans and quarantine terminal open failures

* feat(gateway): refuse incompatible database schemas at boot and verify integrity in the background

* feat(update): refuse installing builds that cannot open the current databases

* docs: add database schema reference with version history and downgrade guidance

* test(update): tolerate optional runner options in git-mutation mocks

* refactor(update): split npm package-target metadata out of update-check

* chore: model verifier internals for knip and regenerate docs map

* chore(i18n): resync stale iOS localization catalog

* chore: allowlist read-only preflight and verifier raw SQLite access
2026-07-18 05:49:39 +01:00
Jason (Json)
2a2e97b960 feat(gateway): add ticketed read-only MCP App host (#109861)
* Gateway: add ticketed MCP Apps standalone host

* Test: tighten MCP App conformance fixture types

* Gateway: support MCP App ping requests

* Test: satisfy MCP App conformance lint

* Test: load MCP App host modules in page
2026-07-17 22:16:57 -06:00
Peter Steinberger
d45e024dca fix(cron): persist startup catch-up deferrals (#110351) 2026-07-18 04:12:15 +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
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
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
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
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
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
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
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
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
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
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
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
Peter Steinberger
9a30b607c5 test: speed up gateway async polling (#110289) 2026-07-18 02:11:50 +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
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
maweibin
3a4e2ef65f fix(auto-reply): treat U+2028/U+2029 as paragraph boundaries when chunking (#103518)
* fix(auto-reply): treat U+2028/U+2029 as paragraph boundaries when chunking

chunkByParagraph normalized only CR/CRLF before blank-line paragraph detection,
so model output using Unicode LINE/PARAGRAPH SEPARATOR (U+2028/U+2029) instead
of a blank line was not split at those boundaries and fell back to length-based
splitting. Normalize U+2028/U+2029 to \n alongside CR/CRLF, matching how the
Control UI markdown renderer handles them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(auto-reply): normalize U+2028 as line break, U+2029 as blank-line paragraph boundary

Distinguish U+2028 (LINE SEPARATOR) from U+2029 (PARAGRAPH SEPARATOR):
U+2029 becomes \n\n (blank line — paragraph boundary) while U+2028
becomes \n (single newline — intra-paragraph line break).

The original fix mapped both to \n, so standalone U+2029 still
produced single-line text without a blank-line gap — paragraph
detection failed. The combined U+2028
 input accidentally
produced the right blank-line sequence, which masked the bug.

Adds individual tests for lone U+2029 (splits at paragraph boundary),
lone U+2028 (stays within paragraph), and consecutive U+2028

(combined blank line — matches \n\n behavior).

* test(auto-reply): simplify Unicode separator cases

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 01:53:25 +01:00
Peter Steinberger
96add8ec3a fix(gateway): reject malformed MCP sandbox policy (#110275)
* fix(gateway): reject malformed MCP sandbox policy

* style(test): format MCP sandbox cases
2026-07-18 01:50:55 +01:00
Peter Steinberger
92e8e8bca6 test: move deferred-event-buffer test to its packages/ai owner and drop dead protocol test 2026-07-17 17:36:48 -07:00
zengLingbiao
88263e34b4 test(cron): add unit tests for assertCronDeliveryInputNonBlankFields (#98668) 2026-07-17 17:21:27 -07:00
zengLingbiao
2666cf7174 test(shared): add unit tests for createDeferredEventBuffer (#98670) 2026-07-17 17:21:18 -07:00
zengLingbiao
5982882055 test(tools): add unit tests for toToolProtocolDescriptor and toToolProtocolDescriptors (#98797) 2026-07-17 17:21:08 -07:00
zengLingbiao
256a2ece73 test(shared): add unit tests for modelKey (#98795) 2026-07-17 17:20:59 -07:00
zengLingbiao
e517d187d2 test(utils): add unit tests for parseJsonWithJson5Fallback (#98801)
* test(utils): add unit tests for parseJsonWithJson5Fallback

* test(utils): verify JSON.parse fast path with spy, per ClawSweeper review

- Add vi.spyOn to prove JSON.parse is called (not JSON5) for strict JSON
- Add spy to prove JSON5.parse is called on fallback path
- Run full src/utils test suite (263 tests passed)
2026-07-17 17:20:16 -07:00
zengLingbiao
f64c35be30 test(utils): add unit tests for safeJsonStringify (#98667) 2026-07-17 17:20:03 -07:00
zengLingbiao
1d64790bf2 test(shared): add unit tests for normalizeNodePresenceAliveReason (#98802)
* test(shared): add unit tests for normalizeNodePresenceAliveReason

* fix(test): add missing bg_app_refresh and significant_location assertions
2026-07-17 17:19:54 -07:00
DaigoSoup
025cecf1f9 fix: avoid false macOS gateway restart failures (#109955)
* fix: wait through launchd KeepAlive restart throttling

* ci: retrigger checks

* test: make update restart test platform-independent

---------

Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-07-17 17:19:23 -07:00
Peter Steinberger
897198b9f5 feat(gateway): typed structured questions on openclaw.chat with live option cards (#110242)
* feat(gateway): typed structured questions on openclaw.chat

The chat result gains an additive optional question field (2-4 options, one
recommended max, per-option reply text). Producers: the two onboarding welcome
variants (apply-setup yes/ask, ready next-step) and hosted wizard select/confirm
steps, which mirror the awaited step so card clients render real wizard choices.
Prose replies always stand alone for text-only clients (macOS app, TUI). The
custodian page consumes the typed field and drops the PR1 string-marker parser
(never shipped in a release); cards send the option reply while the transcript
shows the label.

* chore: keep OnboardingWelcome type module-local

* chore(protocol): regenerate Swift bindings for the chat question field
2026-07-18 01:14:44 +01:00
Heming Zeng
72e4b77921 fix(config): prune cron-run descendant sessions (#105633) 2026-07-18 01:10:33 +01:00
zengLingbiao
73685b4e7c fix(mcp): guard malformed CSP JSON decode (#108883)
When decodeMcpAppSandboxCsp receives a base64-encoded value that
decodes to non-JSON text, JSON.parse throws an unhandled exception.
Add a try-catch so the function returns undefined instead of crashing.
2026-07-17 17:09:21 -07:00
zengLingbiao
ec35d6b5ba test(shared): add unit tests for agent liveness state helpers (#98546) 2026-07-17 17:09:02 -07:00
zengLingbiao
58a86297f8 test(shared): add unit tests for parseConfigPathArrayIndex (#98543) 2026-07-17 17:08:50 -07:00
zengLingbiao
bd966771a7 test(utils): add unit tests for formatTokenCount (#98541)
* test(utils): add unit tests for formatTokenCount

* fix(test): use Number.NaN/Number.POSITIVE_INFINITY per oxlint unicorn/prefer-number-properties

* test(utils): fold formatTokenCount boundary tests into existing usage-format test

Move edge case coverage (invalid inputs, zero/negative, exact boundaries,
thousands overflow) into src/utils/usage-format.test.ts instead of a
separate colocated test file per reviewer feedback.
2026-07-17 17:08:42 -07:00
Peter Steinberger
a6102690dd perf(ci): cut the pre-fan-out critical path and bin canonical main runs (#110183)
* perf(ci): cut the pre-fan-out critical path on canonical runs

Two changes to the run head and matrix shape:

1. runner-admission was a hosted 90s sleep every run queued behind
(observed 1.7min hosted-queue latency before the sleep started). The
debounce now lives at the tail of preflight: heavy jobs all need
preflight, so a superseding main push still cancels the run before
fan-out while only one 4 vCPU runner has been spent, and preflight's
own work usually exceeds the window so the residual sleep is zero.
security-fast (hosted, dependency-free) starts immediately.

2. Canonical main pushes now use the compact bin plan like PRs: the
82-job named matrix drained the runner pool for ~4.5min (job starts
trickled from minute 5.2 to 9.7 in run 29592647843) with no
branch-protection consumer for per-shard names on main. Coverage is
identical; dispatch/release-gate runs keep the full named matrix.

* perf(test): boot TUI PTY suite fixtures concurrently

tsx+TUI startup dominated the harness file's wall time and the three
suite PTYs booted serially. Boot them concurrently in beforeAll
(allSettled so a failed boot still assigns survivors for afterAll
cleanup); the env-specific fixtures never receive input, so their tests
only await their own readiness output. The slow-startup test now proves
frame ordering on the append-only output, which the old sequential
waits did not. File wall 10.2s -> ~4.9s, 3/3 repeat runs green.

* docs(ci): align gate and debounce descriptions with the removed admission job

* test(tooling): wait for readiness file content, not existence

writeFileSync creates the file before its bytes land, so the existence
poll raced the child's write on loaded runners and read an empty ready
file (observed in compact-small-4, run 29615028678). Poll for non-empty
content at both readiness sites.
2026-07-18 01:05:07 +01:00
Peter Steinberger
987e2ff436 fix(gateway): preserve provider failure outcomes (#110252) 2026-07-18 01:04:37 +01:00
Peter Steinberger
d371ea1f01 perf(agents): wave-1 tool output contracts for code mode (#110215)
* feat(agents): keep output contracts complete across opaque schema leaves

* test(agents): add code mode schema-hint hot-path micro-benchmark

* test(agents): count raw-first inspection execs per tool in live bench

* feat(agents): expand compact output contract hints

* feat(agents): declare wave one tool output contracts

* docs(tools): list built-in output contracts

* fix(agents): bound union scans before literal-union analysis

* fix(agents): keep wave-1 contract schemas module-local and type-exact
2026-07-18 01:02:18 +01:00