Commit Graph

80848 Commits

Author SHA1 Message Date
ClawSweeper fa407417f0 fix(ui): honor categories for child sessions (#126388)
* fix(ui): honor categories for child sessions

* fix(ui): admit categorized child sessions as roots

* fix(ui): keep sidebar files within line budget

* fix(ui): include cached categorized children

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-19 15:39:24 -06:00
Peter Steinberger a3ca8466ee fix(ui): refresh device labels after rename (#126432)
* fix(ui): refresh device labels after rename

* fix(ci): classify device label refresh event for mobile

* chore(protocol): regenerate Android gateway events
2026-08-19 14:18:50 -07:00
Peter Steinberger 513ec6218c fix(crabbox): harden worker desktop setup (#126417)
* fix(crabbox): harden desktop provisioning

* docs(gateway): clarify worker desktop routes
2026-08-19 14:13:06 -07:00
ClawSweeper d8fd2937aa fix(ui): keep mobile sidebar session menus reachable (#126355)
* fix(ui): keep mobile sidebar menus in viewport

* fix(ui): bound compact sidebar menu height

* fix(ui): restore Open PR cursor marker

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-19 14:00:39 -07:00
Vincent Koc ee6cab4a2e fix(e2e): use packaged CLI in git fixtures (#126383) 2026-08-20 05:00:25 +08:00
Vincent Koc 42a4db5f42 fix(qa): wait for config restart wake (#126368) 2026-08-20 05:00:23 +08:00
Peter Steinberger 0135046830 refactor(llama-cpp): use one provider for managed and existing servers (#126434)
* refactor(llama-cpp): unify server ownership modes

* test(llama-cpp): preserve shared discovery limits

* fix(plugin-sdk): retain provider auth removal export
2026-08-19 13:57:33 -07:00
Peter Steinberger 8513204e51 fix(file-transfer): report fetched file count accurately (#126439)
Count successful directory fetches from the extracted regular-file manifest while retaining the node wire count for compatibility.
2026-08-19 13:54:40 -07:00
Josh Avant 61416e1254 fix(feishu): honor disabled default tool accounts (#126412) 2026-08-19 13:47:23 -07:00
Peter Steinberger 108a737552 test(ui): await anchored model picker geometry (#126438) 2026-08-19 13:47:20 -07:00
Peter Steinberger 14c02a43ab fix(mcp): stop revoked App actions after catalog waits (#126415)
* fix(mcp): revalidate app grants after catalog work

* test(mcp): track grant proof temp state

* test(browser): use canonical graceful stop budget
2026-08-19 13:35:01 -07:00
Peter Steinberger a1db88b2c5 fix: show useful automation failure details (#126384)
* fix(cron): show useful automation failure details

* test(cron): align failure detail expectations

* fix(cron): use trusted failure details

* fix(cron): preserve event callback shape
2026-08-19 13:34:30 -07:00
Peter Steinberger db533799d5 fix(qa): reject incomplete evidence runs (#126407)
* fix(qa): enforce terminal evidence lifecycle

* test(qa): mark CPU fixture summary completed

* fix(qa): fence calls after flow timeout
2026-08-19 13:30:02 -07:00
Shakker f68503084b fix: scope selected provider hook loading (#126427)
Scope selected-model hook fallback loading to the selected provider so unrelated plugins no longer delay onboarding.

Fixes #126408.
2026-08-19 21:09:38 +01:00
Peter Steinberger fd2fccbc8e docs(agents): restore the non-default scope for systemAgent ownership (#126431)
Live-testing #126377 in a real explicit fleet surfaced an inaccuracy that PR
introduced. It dropped 'Other agent-scoped methods do not use this setting as a
general default', which is still true: only models.list, models.authStatus,
skills.status, and doctor.memory.status opt in, while the generic Gateway
resolver in agent-id-shared.ts deliberately does not.

Verified against a live gateway and CLI on a three-agent explicit fleet with
systemAgent.agentId set: 'openclaw models list', 'openclaw sessions', stored
session lookup, and TUI startup all still require an explicit agent. Name those
surfaces so operators know where the owner does and does not apply.
2026-08-19 13:08:34 -07:00
Samuel Judson 24a1139188 fix: move raw call transcripts from system to user prompt to protect provenance (#123846)
* Move raw transcript from system to user prompt to protect provenance.

* Type fix.

* fix(voice-call): harden transcript context handling

* fix(voice-call): initialize inbound Twilio control state

* test(voice-call): align runtime coordinator fixture

---------

Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
2026-08-19 13:07:59 -07:00
Peter Steinberger 1ef2ebf114 fix(cli): CLI commands crash on multi-agent rosters without --agent (#126418)
* fix(cli): route bare startup on configured inference, not a default agent

Bare `openclaw` resolved a single "default" agent to decide whether inference
was configured. On an explicit multi-agent roster (agents.ownership="explicit"
with 2+ entries) that resolution has no answer, so startup threw
AgentSelectionRequiredError instead of launching the TUI or onboarding.

The branch only needs to know whether inference is configured at all, so it now
asks exactly that across the roster and hands off to the TUI, which already
owns agent selection and resolves by workspace path first. Routing ambiguous
rosters to onboarding instead would have dropped a working multi-agent install
back into the setup wizard.

* fix(cli): honor the configured system agent for model read commands

`openclaw models status`, `models list`, `models auth list`, and
`models auth-order get` resolved a deprecated "default" agent when --agent was
omitted, so they threw AgentSelectionRequiredError on an explicit multi-agent
roster. schema.help.core.ts already documents agents.defaults.systemAgent.agentId
as the owner for these unscoped reads, and the Gateway twins
(models.ts, models-auth-status.ts) already honored it; only the local CLI paths
did not.

resolveModelsTargetAgent now takes a closed read/mutation mode. Reads resolve
explicit --agent, then the configured system agent, then a sole agent.
Credential mutations still require an explicit owner rather than guessing which
agent to write into, and say so with a flag that exists on those commands.

The deprecated resolver is gone from this owner. Help text for the two commands
whose default changed now names the system agent.
2026-08-19 13:02:19 -07:00
Peter Steinberger 2d13e16705 fix: harden node desktop carrier (#126425) 2026-08-19 12:57:26 -07:00
Peter Steinberger 5eda48ed99 fix(ui): recover failed lazy surfaces (#126409) 2026-08-19 12:27:35 -07:00
Peter Steinberger 615ff6ac94 fix: queued deliveries never recover at startup in multi-agent fleets (#126377)
* fix(outbound): resolve ambient delivery owner through the system-agent chain

Agent-less outbound channel bootstrap resolved its owner via the deprecated
throwing resolver, so multi-agent explicit-ownership configs with only
agents.defaults.systemAgent.agentId set threw AgentSelectionRequiredError from
inside gateway delivery recovery, aborting the whole drain ("Delivery recovery
failed") for every queued entry.

Bootstrap now follows the same ambient owner chain heartbeats and cron use
(legacy default, then systemAgent, then sole agent), consolidated into one
canonical tryResolveAmbientOwnerAgentId in agent-scope-config; the duplicated
chain in cron/agent-id.ts is deleted and heartbeat resolution reuses the
helper. Truly ownerless fleets no longer throw either: bootstrap proceeds with
global-scope plugin discovery only, never selecting an agent workspace, so
per-entry delivery outcomes stay recorded instead of one entry starving the
recovery loop.

Regression tests fail pre-fix: agent-less bootstrap routes through the
configured system-agent owner, and ownerless fleets bootstrap without
throwing.

* refactor(agents): route ambient owner resolution through one canonical chain

The idiom `tryResolveLegacyCompatibilityAgentId(cfg) ?? resolveDefaultAgentId(cfg)`
was copied across nine ambient surfaces. It reads like a fallback but is not: when
the first call returns undefined, resolveDefaultAgentId reduces to resolveSoleAgentId
and throws, so the second leg only ever throws — and neither leg consults
agents.defaults.systemAgent.agentId. Every one of those surfaces raised
AgentSelectionRequiredError in explicit fleets that own ambient work through a
system agent.

Promote the chain to one owner in agent-scope-config: tryResolveAmbientOwnerAgentId
(undefined when ownerless) and resolveAmbientOwnerAgentId (throws with the caller's
existing selection context). The throwing variant is a drop-in for every former
composite: identical message when a fleet has no owner, but the system-agent leg
now resolves.

Converted: resolveDefaultAgentDir (the shared producer behind auth, model catalog,
doctor, wizard, and Plugin SDK helpers), config identity-avatar validation, prepared
model catalog and registry, session reset, Talk target, main-session routing and its
routing-contract fingerprint, session store targets, hooks CLI, plugin LLM
completion, and first-run onboarding.

resolveDefaultAgentId keeps backing explicit-selection surfaces where 'pass --agent'
is the right answer; its deprecation note now sends ambient callers to the new
helper.

* fix(sessions,hooks): keep agent-narrowing surfaces on explicit selection

CI caught the over-reach: session-store listing and hooks status reporting are
deliberately explicit-selection surfaces, not ambient system work. Both narrow
output to one agent, so adopting agents.defaults.systemAgent.agentId would hide
the other agents' sessions/hooks instead of failing with the escape hatches the
operator needs. sessions.default-agent-store.test.ts pins that contract by
configuring a system agent and still expecting the --agent/--all-agents error.

Restore the prior behavior at both sites, spelled honestly as
tryResolveLegacyCompatibilityAgentId ?? resolveSoleAgentId — provably identical
to the old composite, since the composite's second leg could only ever throw —
with a comment recording why these two resist the ambient chain.

* test: declare the ambient owner binding in agent-scope mock factories

Explicit vi.mock factories enumerate exports, so production calling
resolveAmbientOwnerAgentId broke prepared-model-catalog, prepared-model-registry,
and channel-resolution with 'No "resolveAmbientOwnerAgentId" export is defined on
the ... mock'. Declare it in the four factories; channel-resolution now drives the
non-throwing variant the bootstrap actually calls.

Also restore session-store targets and hooks status to their exact previous code.
Both stay out of the ambient chain by design, so the smallest correct diff at an
out-of-scope site is none: they now differ from main only by the comment recording
why they resist it.

* fix(models): resolve the model-config workspace through the ambient owner

ClawSweeper P1: prepareModelsConfigContext resolved agentDir through
resolveDefaultAgentDir (ambient chain) but its workspace through
resolveDefaultAgentId (deprecated throwing chain), so explicit fleets owned by a
system agent still failed model preparation on the workspace lookup — a one-sided
fix inside a single function.

Both halves now resolve the same ambient owner.

* docs(agents): describe the widened ambient system-agent ownership

config-agents.md claimed 'Other agent-scoped methods do not use this setting as
a general default', which this branch makes false: systemAgent.agentId is now
the ambient owner for agent dir/workspace resolution, outbound bootstrap and
delivery recovery, main-session routing, Talk, and onboarding.

Record the widened set, the two surfaces that deliberately still demand explicit
selection (sessions, hooks), and delivery recovery's per-entry degradation.
2026-08-19 12:24:25 -07:00
Peter Steinberger 0b715e3f5b refactor(ui): share Control UI resource route contract (#126386)
* refactor(ui): share Control UI resource route contract

Gateway and Control UI now share browser-safe resource route grammar, while authorization and domain validation remain handler-owned.

* perf(ui): keep resource routes out of startup

Narrow browser-safe contract modules and the lazy authenticated avatar loader keep route/cache code out of the startup chunk while the stable Gateway barrel remains compatible.
2026-08-19 12:20:22 -07:00
Peter Steinberger 84c2111b30 fix: restore cloud worker Desktop on node-backed Crabbox workers (#126393)
* fix(gateway): carry cloud worker desktops over nodes

* fix(crabbox): restore node-backed worker desktops

* refactor(crabbox): split worker provider owners
2026-08-19 11:50:48 -07:00
Peter Steinberger 5976e74d1c fix(ui): close dashboard side panel in split view (#126397) 2026-08-19 11:36:46 -07:00
Peter Steinberger e47637809c fix(ui): render one assistant reply when history and the terminal event race (#126382)
* fix(ui): render one assistant reply when history and the terminal event race

A finished run's reply reached the Control UI twice: the durable transcript
row and the pane's own terminal projection shared no identity, so the
projection reducer kept both and the transcript collapsed them behind the
"x2" duplicate badge. The gateway's chat final event carries no message id,
and a durable assistant row carries no run id, so the reducer's same-run
promotion could never match them. A WeakMap side channel hid the duplicate
only when history happened to be applied before the terminal event arrived,
which made the badge look intermittent.

The pane now admits the durable assistant row of the run it is finishing
through the reducer, attributed to that run, so the durable row adopts the
terminal projection in place; the reducer refuses to downgrade a row that
already carries a transcript id back to an id-less projection.

Splits the run-terminal bookkeeping tests into a sibling file to stay under
the max-lines ratchet.

* fix(ui): bind a late reply row to its run only when it carries that reply

The terminal tombstone outlives its run by design, so attributing every
unowned assistant row to it could stamp a delayed older row with a newer
run's id; the reducer then matched that row to the newer run's terminal
projection and replaced the answer the user should see. The tombstone now
claims only the row carrying the reply already projected for that run.
2026-08-19 11:33:22 -07:00
Peter Steinberger 61d217fd2a fix: stop routing IDs from masquerading as delivery receipts (#126385)
* fix(channels): separate routing from receipt identity

Routing identifiers no longer fabricate message delivery evidence; provider-canonical thread placement is preserved.

* fix(channels): preserve conflicting receipt threads

Keep aggregate thread placement absent when provider receipt parts disagree, even when a requested route thread is available.
2026-08-19 11:33:16 -07:00
Peter Steinberger 341551937e fix(agents): preserve empty CLI subagent completions (#126379)
* fix(agents): preserve empty CLI subagent completions

* chore(qa): remove retired Matrix coverage leaf

* refactor: consolidate shared runtime ownership

* fix(scripts): keep runtime build coercion dependency-light

* chore: remove release-owned changelog entry
2026-08-19 11:30:43 -07:00
Peter Steinberger 8a9e21d3bc fix(providers): prevent malformed streamed tool calls (#126391)
Co-authored-by: 曾令彪 0668001395 <zeng.lingbiao@xydigit.com>
2026-08-19 11:30:09 -07:00
Ben Badejo 0a8f2c1845 fix(matrix): recover providers after disconnected sync stop (#125362)
* fix(matrix): recover poisoned sync generations

* fix(matrix): compile private sync resolver boundary

* fix(matrix): retain incomplete retirement poison

---------

Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
2026-08-19 11:30:04 -07:00
Peter Steinberger 38a45c2220 fix(status): bound macOS gateway status probes (#126394) 2026-08-19 11:28:23 -07:00
ClawSweeper 76fc15c515 fix(ui): dedupe streamed final assistant messages (#126367)
Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-19 12:26:01 -06:00
Peter Steinberger 03a48b5801 fix(agents): preserve prompt cache boundary keys (#126380) 2026-08-19 11:09:57 -07:00
Peter Steinberger 0606e31d0e feat(gateway): broker GitHub publication (#126306)
* feat(gateway): broker GitHub publication

* refactor(gateway): split publication owners

* fix(gateway): enforce publication branch authority

* fix(gateway): bind publication to remote identity

* fix(gateway): bind publication recovery to remote state

* fix(gateway): preserve publication git state

* fix(gateway): retain publication recovery authority

* fix(gateway): commit publication index atomically

* fix(gateway): narrow publication index errors

* refactor(gateway): keep publication CAS errors private

* fix(gateway): recover publication index transactions

* fix(agents): describe GitHub publication tool

* fix(gateway): harden publication base fetch

* fix(gateway): reject publication filter semantics

* fix(gateway): verify publication creation base

* refactor(agents): align publication tool options

* fix(gateway): isolate publication object lineage

* refactor(gateway): use shared table probe

* test(gateway): keep publication helpers in routed suite

* perf(ui): lazy-load GitHub publication request

* fix(gateway): preserve publication support contracts

* fix(gateway): recover publication before authority checks

* fix(gateway): fence local publication snapshots

* fix(android): format generated protocol models

* fix(gateway): harden publication recovery

* fix(gateway): fence publication recovery

* fix(ui): reset completed publication cycles
2026-08-19 11:05:12 -07:00
Peter Steinberger 51599041bc fix: explain preserved session worktrees accurately (#126347)
* fix(sessions): report worktree preservation reasons

* fix(sessions): align preservation checks with current main

* perf(ui): keep preservation copy within startup budget

* perf(ui): reuse localized preservation copy

* test(ui): match preserved worktree confirmation copy

* test(ui): await committed raw config state
2026-08-19 10:59:42 -07:00
Peter Steinberger 1410ffcd23 fix(ui): show real avatars in session hovercards (#126372)
* fix(ui): show channel avatars in session hovercards

* fix(ui): preserve hovercard avatar fallback
2026-08-19 10:54:56 -07:00
Peter Steinberger 1d52299bca fix(ui): preserve device token state across reconnects (#126362) 2026-08-19 10:51:42 -07:00
Peter Steinberger 6267703b30 refactor(canvas): share eligible node selection (#126374) 2026-08-19 10:51:02 -07:00
Peter Steinberger 55fb2c8606 fix(ui): prevent duplicate assistant bubbles after history refresh (#126364)
* fix(ui): stabilize chat history dedupe identity

* fix(ui): narrow chat history dedupe identity
2026-08-19 10:48:33 -07:00
Peter Steinberger 7e353d750a fix(qa): prevent reserved gateway port startup deadlock (#126370)
* fix(qa): close probes on reserved gateway ports

* fix(qa): keep port sockets at the gateway boundary
2026-08-19 10:46:44 -07:00
Peter Steinberger 558a270bb2 fix: clean up failed CAF staging (#126378) 2026-08-19 10:45:31 -07:00
ClawSweeper e474d23e65 fix(doctor): recover recreated legacy workspace state (#126059)
* test(doctor): cover interrupted recreated workspace state

* fix(doctor): recover recreated legacy workspace state

---------

Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-19 10:29:54 -07:00
Vincent Koc 957f013454 test(plugins): refresh Codex exec scan baseline (#126215)
Punchcard-Session: frost-orchard-lantern-ze
2026-08-20 01:23:17 +08:00
Peter Steinberger 7c1779e6e3 refactor(llama-cpp): adopt canonical runtime owners (#126371) 2026-08-19 10:17:59 -07:00
Peter Steinberger 61221c4c20 fix(doctor): prevent update repair OOM on large session stores (#126353)
* fix(doctor): bound large session-store repairs

Prevent post-core update finalization from retaining complete session JSON corpora. Move Doctor repair planning and rewrites onto ordered bounded SQLite owner scans with stale-decision revalidation and selective hydration.

Co-authored-by: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com>

* test(doctor): expose memory helper to deadcode scan

---------

Co-authored-by: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com>
2026-08-19 10:14:00 -07:00
alexeysophia 80dcef5044 fix: large base64 attachments on /v1/responses crash the gateway with heap OOM (#126017)
* fix(media): stop canonicalizeBase64 allocating one cons-string node per char

Per-character append built a rope of ~25 bytes per input character, all
live until the final join — a 20 MB base64 attachment transiently needed
~700-900 MB of heap and OOM-crashed the gateway on POST /v1/responses.
Validate in the same single pass but collect contiguous non-whitespace
runs as slices; already-canonical input is returned unchanged with zero
allocations. Measured: 15 MiB attachment 659 MB -> 0 MB transient heap,
4.3 s -> 0.2 s.

* fix(media): bound canonicalizeBase64 cleanup memory by input length

Review found the run-slicing cleanup unbounded for adversarial input:
alternating data characters and whitespace retains one slice object per
run (measured 421 MB of heap for an 8 MiB payload shredded to one run
per character). Replace the run collection with a single output buffer
materialized on the first whitespace and filled in the same validating
pass: canonical input still returns unchanged with zero allocations, and
any whitespace shape now costs at most one buffer bounded by the input
length (measured 0 MB heap delta, 210 ms for the same shredded payload).
Adds the many-short-runs regression test the review asked for, guarding
both heapUsed and arrayBuffers.

* refactor(media): condense canonicalizeBase64 invariant comment

Review asked for the repository's 1-3-line invariant form: keep why the
buffer is lazy and bounded, drop the implementation-history narration.

* chore: retrigger CI (flaky gateway-server shard)

* test(media): update base64 memory comment

Punchcard-Session: frost-cedar-willow-ae

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-08-20 01:11:37 +08:00
Peter Steinberger c5b7739ed5 fix(cron): report removed-agent notification failures (#126361) 2026-08-19 10:10:01 -07:00
Peter Steinberger 4bc6853a32 fix(onboard): keep agent names on guided setup (#126365) 2026-08-19 10:07:30 -07:00
Peter Steinberger 0abc5130c9 fix(tests): deflake qa-lab process-group pid-file waits (#126351)
The model catalog abort test waited for pid-file existence, but the
catalog child's writeFileSync exposes an open-truncate window: the
test could read the file empty and fail on a NaN pid assertion
(CI run 32231699569, checks-node-changed-extensions-config-37).

Add a qa-lab-local process-wait test helper that waits for the
asserted state (a parseable pid) with generous 10s deadlines and
self-diagnosing timeout errors, and consolidate the two hand-rolled
helper copies in model-catalog.runtime.test.ts and
test-file-scenario-command-lifecycle.test.ts onto it. Also retire
the stale 1.7s abort-settle ceiling (calibrated against a removed
1.5s in-plugin kill grace) in favor of a 5s bound with the contract
documented.
2026-08-19 09:56:21 -07:00
Vincent Koc 9d4ba33c4a test(plugins): complete runtime registry fixtures (#126258) 2026-08-20 00:52:41 +08:00
Peter Steinberger 5549fdc70f test(mac): speed up elevation host suite (#126338)
* test(mac): speed up elevation host suite

* test(process): restore no-output startup margin
2026-08-19 09:46:23 -07:00
Vincent Koc bd77ee1031 fix(ci): retain pending QA workflow calls (#126254) 2026-08-20 00:34:26 +08:00