Commit Graph

69226 Commits

Author SHA1 Message Date
Peter Steinberger
ca0a63fb43 perf(ci): retune cli-runner stripe packing hints from measured runs
Validation run 29487321249 measured stripe 2 at 179s (hint said 110)
while stripes 1/3 run light; the index striping concentrates import cost
unevenly. Weight the hints accordingly so no compact bin overpacks past
the 260s target.
2026-07-16 04:14:53 -07:00
Vito Cappello
92075dd72a fix(secrets): inactive web refs no longer block agent turns (#108485)
* fix(secrets): accept inactive refs from partial fallback

* fix(secrets): fail closed on unknown web provider owners

* test(gateway): isolate web secret startup fixtures

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:13:40 -07:00
zhanxingxin1998
5810de21b9 fix(clickclack): prevent reconnect from skipping in-flight events (#108577)
* fix(clickclack): commit websocket cursors after processing

Serialize realtime events and wait for queued handlers before reconnecting so only successfully processed cursors advance.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(clickclack): replay failed websocket events

Keep the last successful cursor when realtime handling fails, then reconnect through durable backlog recovery before reopening the stream.

Co-authored-by: 詹幸心0668001037 <zhan.xingxin@xydigit.com>

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:12:54 -07:00
Peter Steinberger
d739daef10 fix(ci): handle Android license pipe closure 2026-07-16 12:12:18 +01:00
Peter Steinberger
d5eebf02e2 fix(workboard): record resolved runtime metadata instead of hardcoded codex engine (#108887)
* fix(workboard): record resolved runtime metadata instead of hardcoded codex engine

Workboard executions labeled every dispatched run engine=codex, model=default,
and id suffix :codex even for Claude/other harness agents. The gateway agent
admission phase now returns the resolved {harness, provider, model} for plugin
subagent runs; the dispatcher records it verbatim and omits engine/model when
unresolved. Engine becomes an open runtime identifier in the workboard
contract (built-in launch choices stay a closed list), store/UI normalizers
preserve historical labels as written instead of inventing codex, and new
execution ids use an :agent-session suffix. Fixes #108362

* fix(workboard): accept undefined engine in ui engineModel helper
2026-07-16 04:10:27 -07:00
Alix-007
f538addc66 fix(ci): bound non-root NodeSource setup download (#108911) 2026-07-16 04:08:47 -07:00
Alix-007
0ca1d23517 fix(sandbox): keep CDP probes within startup deadline (#108670)
* fix(sandbox): bound CDP probes to startup deadline

* test(sandbox): prove stalled CDP deadline

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:05:18 -07:00
Alix-007
93c1543efc fix(qqbot): bound channel API response reads (#108895)
* fix(qqbot): bound channel API response reads

* refactor(qqbot): centralize channel API cleanup

Co-authored-by: Alix-007 <li.long15@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:04:24 -07:00
xingzhou
0c067fbfa4 fix(ui): reject nondecimal cron repeat amounts (#107480)
* fix(ui): reject nondecimal cron repeat amounts

* fix(ui): satisfy cron LOC ratchet

* fix(ui): validate cron intervals exactly

Co-authored-by: xingzhou <zhang.guiping@xydigit.com>

* chore(pr): stage cron UI proof

Co-authored-by: xingzhou <zhang.guiping@xydigit.com>

* chore(pr): remove staged cron UI proof

Co-authored-by: xingzhou <zhang.guiping@xydigit.com>

* fix(ui): remove unused cron type export

Co-authored-by: xingzhou <zhang.guiping@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-16 04:04:01 -07:00
Peter Steinberger
66604df9b6 refactor(channels): share retry helpers and remove dead state probes (#108903)
* refactor(channels): generalize channel retry runner and retry-after parsing; drop dead configured-state probes

* fix(channels): align retry and metadata contracts
2026-07-16 04:03:15 -07:00
Wynne668
7241b2bc80 fix(vault): reject oversized credential files (#108761)
* fix(vault): bound token and JWT file reads

* fix(vault): remove awaits from synchronous credential reads
2026-07-16 04:02:44 -07:00
Peter Steinberger
3550d3140e fix(line): validate generic batch media URLs (#108917) 2026-07-16 03:59:26 -07:00
Yuval Dinodia
d15d3e17ec fix(gateway): scope node pairing management to caller device (#104989)
Apply the existing device-token ownership rule to node pairing list, approve, reject, and rename. Preserve shared-auth, admin, and self-service management while preventing cross-device enumeration and mutation.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:58:11 -07:00
Peter Steinberger
06e3a09bd8 fix(ci): preserve advisory release checks 2026-07-16 11:56:01 +01:00
Peter Steinberger
6f8c759b4c refactor(cron): share task history timestamp (#108914) 2026-07-16 03:55:39 -07:00
Peter Steinberger
fd3300a8e0 fix(plugin-sdk): refresh generated API baseline (#108910) 2026-07-16 03:52:02 -07:00
qingminlong
b1e814f57a fix(docs): report malformed search JSON with CLI context (#108364)
* fix(docs): report malformed search JSON with CLI context

* test(docs): tighten malformed response assertion

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:51:52 -07:00
Peter Steinberger
93c9d2a20c fix(ios): stop fresh setup from failing after pairing (#108779)
* fix(ios): make setup keychain handoff atomic

* fix(ios): refresh native i18n inventory
2026-07-16 03:50:54 -07:00
Peter Steinberger
5c027fba14 chore(plugin-sdk): refresh merged API baseline (#108913) 2026-07-16 03:50:51 -07:00
xingzhou
6e594ca7ca fix(qa-lab): preserve Unicode in capped evidence previews (#108545)
* fix(qa-lab): preserve UTF-8 evidence previews

* fix(qa-lab): complete short evidence preview reads

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:50:30 -07:00
zhanxingxin1998
866050fc1c fix(ui): honor UTC in usage session detail timelines (#108579)
* fix(ui): honor timezone in usage detail timeline

Apply the selected local or UTC calendar boundaries to session detail points and keep the full final day.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test(ui): make usage timezone regression deterministic

Model a non-UTC local calendar through Date getters instead of relying on runtime TZ mutation.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test(ui): type local date getter mocks

Annotate Date receivers so the deterministic timezone regression passes strict test type checking.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(ui): complete usage timeline timezone handling

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:48:35 -07:00
Peter Steinberger
0b97e22a10 test(e2e): synchronize npm upstream body timeout (#108873)
Co-authored-by: Alix-007 <li.long15@xydigit.com>
2026-07-16 03:48:02 -07:00
Ian Alloway
dbcf7abda1 fix(anthropic-vertex): keep ADC fetch provider-local (#108350)
* fix(anthropic-vertex): shim native fetch so Google auth avoids gaxios's node-fetch import

@anthropic-ai/vertex-sdk's bundled gaxios only uses native fetch when a
global `window.fetch` exists; otherwise it dynamically imports
`node-fetch`, which can fail to resolve depending on how the plugin's
dependencies are installed. That failure surfaces deep inside gaxios's
token-exchange path as "Cannot convert undefined or null to object",
breaking every Vertex auth request (#107341). The same gaxios root
cause hit a different provider in #41380, where a global window.fetch
shim was the confirmed workaround.

Fixes #107341

* fix(anthropic-vertex): compare window directly against undefined

oxlint's unicorn/no-typeof-undefined flagged the typeof check; a
direct comparison is safe here since target.window is a property
access, not a possibly-undeclared identifier.

* fix(anthropic-vertex): keep ADC fetch provider-local

Co-authored-by: Ian Alloway <ian@allowayllc.com>

* test(anthropic-vertex): inject auth in API fixtures

Co-authored-by: Ian Alloway <ian@allowayllc.com>

* refactor(anthropic-vertex): clarify auth transport contract

Co-authored-by: Ian Alloway <ian@allowayllc.com>

* fix(anthropic-vertex): preserve ADC proxy routing

* chore: leave changelog to release workflow

---------

Co-authored-by: Ian Alloway <ian@allowayllc.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:47:40 -07:00
Wynne668
b7e099d36e fix(gateway): agent model overrides cannot be cleared (#108734)
* fix(gateway): allow clearing agent model overrides

* fix(protocol): preserve Swift agent model compatibility

* fix(protocol): preserve null when Swift decodes agent updates

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:46:37 -07:00
Peter Steinberger
f180638e87 test(docker): extract setup harness (#108797) 2026-07-16 03:44:17 -07:00
Yuval Dinodia
0317d7e628 fix(memory-core): write MEMORY.md atomically during short-term promotion (#108397)
* fix(memory-core): write MEMORY.md atomically during short-term promotion

applyShortTermPromotions rewrote MEMORY.md with a single non-atomic
fs.writeFile, which truncates the file before streaming the new content.
An OS write failure part way through (for example EFBIG on a size-limited
or full volume) left MEMORY.md truncated to the bytes written before the
failure, permanently dropping user long-term memory. The dreaming cron
path invokes this writer automatically, and the recall store is only
updated after the write, so the promotion stays eligible and the next
run reads the already-truncated file.

Route the write through replaceFileAtomic (temp file, fsync, atomic
rename), the same durable-write helper the sibling DREAMS.md writer in
this extension already uses. On failure the temp file is discarded and
the existing MEMORY.md is left untouched; on success the content and the
existing file mode are preserved.

* fix(memory-core): harden atomic promotion durability

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:43:21 -07:00
Alix-007
1ae12955f3 fix(docker): bound Docker GPG key download (#108894) 2026-07-16 03:42:07 -07:00
Alix-007
60987aa96d fix(qa-channel): bound stalled bus requests (#108684)
* fix(qa-channel): bound stalled bus requests

* test(qa-channel): cover stalled bus response bodies

* test(qa-channel): make stalled-body timeout deterministic

* style(qa-channel): format timeout regression

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:41:51 -07:00
Peter Steinberger
e0ffbd90d9 fix(ci): isolate bounded metadata retries (#108804)
* fix(ci): bound Mantis runner IP retries

* fix(e2e): isolate Windows metadata retries

* fix(ci): validate complete runner IPv4

Co-authored-by: Alix-007 <li.long15@xydigit.com>

---------

Co-authored-by: Alix-007 <li.long15@xydigit.com>
2026-07-16 03:39:31 -07:00
Eden
d572c5cb2d fix(line): run post-ack webhook processing on its own admitted work root (#107734)
* fix(line): run post-ack webhook processing on its own admitted work root

LINE acks the webhook and dispatches event processing fire-and-forget on
the same async chain. The HTTP request admission that chain inherited is
released as soon as the route handler returns, and a released admission
refuses subordinate queue work - so every LINE inbound agent turn fails
with "GatewayDrainingError: Gateway is draining; new tasks are not
accepted" even though the gateway is healthy. DMs, group mentions, and
postbacks are all affected; the user-visible symptom is the bot replying
"Sorry, I encountered an error processing your message." to everything.

Add runDetachedWebhookWork to the plugin-sdk webhook-request-guards
surface (a thin wrapper over the gateway independent-root continuation,
the same shape core uses in gateway/server/hooks.ts) and route all three
LINE ack-first dispatch sites through it: the gateway monitor handler
(the live path), and the createLineNodeWebhookHandler / Express
middleware handlers (public webhook building blocks an embedder can
register under the gateway). #65375 unified these three into one ack-first
pattern; keeping the detach consistent avoids re-introducing the same
latent defect in the two that are not on the live gateway path today.

The continuation is reserved synchronously while the request is still
admitted, so the detached processing stays accepted and a real restart
drain can wait for it instead of stranding it mid-turn.

Tests pin every layer: the guards suite proves detached post-ack work is
admitted after the request admission is released (and that the inherited
chain without the helper is refused); the monitor lifecycle suite and the
webhook-node suite assert each dispatch site goes through the detached
root. Red/green verified: reverting any dispatch fails its test.

* fix(plugin-sdk): account for runDetachedWebhookWork in public surface budget

* fix(channels): track detached webhook processing

Co-authored-by: 許元豪 <146086744+edenfunf@users.noreply.github.com>

* docs: refresh generated docs map

* chore(plugin-sdk): refresh API baseline

* fix(webhooks): preserve post-ack ordering

* test(plugin-sdk): satisfy detached work lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:39:02 -07:00
Peter Steinberger
b6b8e59b9e refactor(ci): share Android toolchain setup (#108855)
* refactor(ci): share Android toolchain setup

* fix(ci): preserve frozen Android targets
2026-07-16 03:38:31 -07:00
Eden
80de877ed3 fix(line): support /allowlist config edits (#106638)
* feat(line): wire base.allowlist config-edit adapter

LINE was the only DM/group channel without a base.allowlist adapter, so
`openclaw allow line` / the /allowlist command replied "does not support"
instead of editing the LINE allowlist. Reuse buildDmGroupAccountAllowlistAdapter
(DM + group + per-group-override scopes), matching Telegram/Signal; entry
normalization flows through the existing lineConfigAdapter.formatAllowFrom.

* fix(allowlist): preserve inherited account entries

* fix(allowlist): preserve all-scope store edits

Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>

* test(allowlist): import config type

Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>

* fix(allowlist): preserve empty effective overrides

Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>

* fix(allowlist): reject group-only store edits

Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>

* fix(allowlist): preserve cleared channel overrides

Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:38:13 -07:00
Nik
3f819ab0cc fix(embedded-runner): clear tool-search catalog when a run aborts during prep (#108114)
* fix(embedded-runner): clear tool-search catalog when a run aborts during prep

* fix(embedded-runner): point catalog test at relocated tool-search test api
2026-07-16 13:37:32 +03:00
Peter Steinberger
2c7cf8d745 perf(ci): scale Vitest workers with runner class and share serial module cache (#108788)
* perf(ci): scale Vitest workers with runner class and share serial module cache

Compact node-test jobs pinned OPENCLAW_VITEST_MAX_WORKERS=2 regardless of
runner size, so import-bound suites (30-45s of module-graph import per
file) crawled: runner-cli spent 284s on 5s of tests, commands-1 296s on
10s. With serial plans the budget now scales with the class (6 on 8vcpu,
3 on 4vcpu); timing-sensitive groups (tooling, tui-pty, infra-process)
stay pinned to 2 via plan-level env. Serial bins share one Vitest
fs-module-cache path so later plans reuse the first plan's transforms.
The import-bound commands stripes and security suite move to the 8vcpu
class, and packing hints refresh from serial-run measurements (run
29481835688).

* perf(ci): stripe cli-runner suite and pin media-ui worker budget

The agents-core config runs files serially (fileParallelism false guards
shared module state), so raising the worker budget cannot help its
import-heavy cli-runner suite (~35s module import per file, 213s serial).
Stripe it three ways so bins parallelize the imports instead. media-ui
hosts browser locator tests that timed out at 6 workers on the first
validation run; pin it to the proven 2-worker budget. commands-1's hint
drops to its measured 6-worker runtime.
2026-07-16 03:36:37 -07:00
Hosan
7bc43f50b7 fix(message): reject invalid read targets without fallback (#108637)
* fix(message): fail closed on invalid read targets

* fix(message): scope read channel validation

* fix(message): fail closed on explicit read scope

---------

Co-authored-by: Hosan <200961079+hosanxiv@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:36:32 -07:00
Peter Steinberger
e95577ded7 fix(e2e): bound macOS Discord host requests (#108880) 2026-07-16 03:36:20 -07:00
NIO
dacf164793 fix(gateway-client): bound websocket opening handshake waits (#108348)
* fix(gateway-client): bound websocket opening handshake waits

* test(gateway-client): harden handshake timeout proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:36:17 -07:00
Peter Steinberger
5d9c114fa6 fix: keep isolated gateways quiet and Codex terminals interactive (#108871)
* fix(gateway): harden session recovery paths

* fix(terminal): normalize padded TERM values

* chore: defer gateway release notes

* test(terminal): type TERM test environments
2026-07-16 03:35:17 -07:00
xingzhou
c7f58f5bed fix(gateway): suppress MCP notification responses (#101730)
* fix(gateway): suppress mcp notification responses

* fix(gateway): MCP clients receive responses for JSON-RPC notifications

* Handle MCP lifecycle notifications before tool resolution

* Filter notification entries from internal-error batches

* fix(gateway): centralize MCP response eligibility

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>

* test(gateway): use public MCP loopback helper

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:34:01 -07:00
Henk ter Harmsel
0497148458 fix(acpx): stop creating empty stderr logs (#106799)
* fix(acpx): avoid empty stderr log files

* fix(acpx): clear stale stderr logs before launch

* test(acpx): keep stderr cleanup best effort

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:33:11 -07:00
Shubhankar Tripathy
6390edec25 fix(memory-lancedb): prevent cross-agent memory leakage (#103799)
* fix(memory-lancedb): gate auto-recall and auto-capture on per-agent memorySearch.enabled (#103590)

The before_prompt_build auto-recall hook only checked the plugin-level
autoRecall flag, so agents configured with memorySearch.enabled: false
still received <relevant-memories> injected from the shared LanceDB store
- leaking one agent's private memories into another agent's prompts. Gate
both recall injection and agent_end auto-capture on the current agent's
memorySearch.enabled (per-agent entry wins over agents.defaults; unset
means enabled), mirroring core resolveMemorySearchConfig semantics.

* fix(memory-lancedb): normalize agent ids before the memorySearch gate

Review follow-up on #103799: a configured id like 'XiaoHuo' or one with
surrounding whitespace missed the exact-match per-agent override and
inherited the enabled default, leaving the disclosure path active.
Normalize both the hook agent id and configured entry ids with the SDK
normalizeAgentId before comparing.

* fix(memory-lancedb): resolve the per-agent memorySearch gate via resolveAgentConfig

* fix(memory): isolate LanceDB rows by agent

Co-authored-by: Shubhankar Tripathy <reach2shubhankar@gmail.com>

* fix(memory): isolate LanceDB rows by agent

Co-authored-by: Shubhankar Tripathy <reach2shubhankar@gmail.com>

* refactor(memory): keep LanceDB store types private

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:33:08 -07:00
wuqxuan
045a02b7ad fix(codex): make status context freshness truthful (#107813)
* fix(codex): project absolute thread tokenUsage into attemptUsage (#107324)

* fix(codex): keep thread totalUsage off per-attempt fields

* fix(codex): make status context freshness truthful

Co-authored-by: wuqingxuan <wu.qingxuan@xydigit.com>

* fix(codex): preserve usage through timeout recovery

Co-authored-by: wuqingxuan <wu.qingxuan@xydigit.com>

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:32:08 -07:00
Jason (Json)
73980e7e42 fix(codex): remove duplicate provider setup choice (#107979)
* fix(codex): stop advertising harness as model provider

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>

* fix(wizard): keep migration plugins out of optional setup

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:31:11 -07:00
yyj-xydt
f444dfafc5 fix(line): avoid exposing media URLs in errors (#108657)
* fix(line): avoid exposing media URLs in errors

* test(line): cover media URL redaction paths

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:28:40 -07:00
mushuiyu886
4b9c78a674 fix(cron): preserve same-id history across stores (#108730) 2026-07-16 03:28:11 -07:00
Alix-007
de10d98c81 fix(e2e): bound OpenShell installer fetch (#108810) 2026-07-16 03:27:03 -07:00
Peter Steinberger
2488d794ca feat(ui): expand child sessions in sidebar (#108838)
* feat(ui): expand child sessions in sidebar

* test(ui): type child session list options

* refactor(ui): split child session data helpers

* fix(ui): preserve session link semantics

* fix(ui): retry incomplete child session loads

* chore: keep release changelog owner-only
2026-07-16 03:26:49 -07:00
Alexis Gallagher
7a3c26b509 fix(codex): preserve subagent completions after sessions_yield (#105724)
* fix(codex): preserve subagent completions across sessions_yield

* fix(codex): confirm steering delivery before yield

Co-authored-by: Alexis Gallagher <alexis@alexisgallagher.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:26:33 -07:00
Monkey-wusky
8ebb1d2aec fix(sessions): complete tail-read windows despite short positional reads (#108655)
* fix(sessions): complete tail-read windows despite short positional reads

Replace single-shot handle.read() calls in two session tail-read
paths with readFileWindowFully so multibyte-range positional reads
do not silently return incomplete tail data on network filesystems.

- readRecentTranscriptTailLinesAsync: tail-window read for recent
  session messages now loops until the requested window fills
- readLastMessagePreviewFromOpenTranscriptAsync: last-message
  preview tail read now loops until the requested window fills

The same readFileWindowFully helper was introduced in #108253 and
expanded with a sync variant in #108127 (both by sunlit-deng).

* fix(sessions): complete sync title preview reads

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 03:25:55 -07:00
Peter Steinberger
3280a0df9a test(retry): port negative matrix for provider-wrapped statuses
Ports the unique coverage from #108126 onto the parser landed via #106850:
wrapped 401/403/404 and quota-exhausted 429 stay non-retryable, an
envelope embedded in user text is ignored, and a short-window wrapped
429 retries. Credit @zhanxingxin1998.
2026-07-16 11:22:13 +01:00