Commit Graph

44463 Commits

Author SHA1 Message Date
Josh Avant d7fe595ebb fix(media): honor sender tool policy for outbound file reads (#125950)
* fix(media): enforce sender policy for outbound reads

* fix(media): block denied attachment fallbacks

* fix(gateway): preserve sender aliases for media policy

* fix(media): scope wildcard and attachment actions

* test(gateway): prove denied media stays unbuffered

* fix(gateway): scope send attachment hydration
2026-08-18 15:49:18 -07:00
Peter Steinberger 1d9cda833f feat(ui): show machine CPU and RAM in the cloud picker (#125696)
The cloud machine picker described each class in prose ("Cheap smoke checks
and small repos"), which was the widest thing in the row, got ellipsized, and
did not say what the operator actually picks on. Machine options now carry the
class shape and the picker renders "32 vCPU · 64 GB" instead.

Crabbox reports per-provider class shapes from `providers --json`; the plugin
reads that catalog once per lifecycle and attaches cpu/memoryGb to each option.
A missing binary, failed command, unparseable output, absent classes, or an
unmatched provider all degrade to label-only rows, so an older Crabbox keeps
working.

`description` was never released, so it is removed rather than deprecated, and
listMachineOptions becomes async for the catalog read. Deletes the duplicate
machine-option projector in the environments server method.
2026-08-18 15:38:15 -07:00
Peter Steinberger f7db0a4c51 fix: show named CLI sessions in the sidebar (#126043)
* fix(gateway): preserve explicit session names

* test(ui): keep session visibility fixture isolated
2026-08-18 15:33:43 -07:00
Peter Steinberger e8312171c1 fix: direct Gateway stops wait for active work (#126024)
* fix(gateway): drain active work on direct stop

* test(ui): isolate widget fetch retry mock
2026-08-18 15:29:52 -07:00
Peter Steinberger 0f08ba4a6e fix(tui): gate startup sends on restored session (#126046) 2026-08-18 15:20:56 -07:00
Peter Steinberger b34eb16071 fix(copilot): restore OpenClaw guidance to agent turns (#125997)
* fix(copilot): add OpenClaw prompt guidance

Copilot append-mode system messages included credential safety, workspace bootstrap, and extra context but omitted OpenClaw delegation and reply-delivery policy.

Build guidance from the final policy-filtered tool surface so visible delegated work, Skill Workshop, and source replies follow the same behavior as Codex.

* fix(copilot): break prompt guidance import cycle

The CI architecture gate detected a cycle through attempt-config and prompt-guidance. Isolate raw-run mode detection in a leaf module.
2026-08-18 15:01:15 -07:00
zengLingbiao 56fb860270 fix(agents): redact reflected credentials from native PDF provider error body and reason phrase (#125499)
* fix(agents): redact reflected credentials from native PDF provider error body and reason phrase

* fix(agents): centralize provider error credential redaction

Redact the exact authentication values sent by native PDF and MiniMax VLM requests before provider-controlled response fields reach agent-facing errors.

Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>
Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: sallyom <somalley@redhat.com>
2026-08-18 17:58:12 -04:00
Peter Steinberger 491dc7f8b1 fix(codex): report native project docs truthfully (#126010) 2026-08-18 14:42:56 -07:00
Patrick Erichsen a13251825a fix(gateway): tolerate locked terminal cleanup (#125058)
Co-authored-by: Jacqueline Henriksen <jjjhenriksen@users.noreply.github.com>
2026-08-18 14:32:45 -07:00
Onur Solmaz 5cabd2b72e Revert "fix(providers): report request acceptance consistently (#125807)" (#126021)
This reverts commit f5e9622fc9.
2026-08-19 00:16:09 +03:00
Peter Steinberger 39b39ca6ee fix(gateway): apply configured edge auth to session-URL targets (#125982)
* fix(gateway): apply configured edge auth to session-URL targets

Follow-up to #125700.

A URL target with explicit auth skipped config loading and silently dropped
gateway.remote.edgeAuth. Config I/O is now skipped only for plaintext loopback
targets.

Also document mandatory passEnv: ["HOME"] for the cloudflared exec provider.

* fix(gateway): keep explicit secure connections working when config is invalid

Addresses the ClawSweeper finding on #125982 by preserving the invalid-config recovery path while still applying configured edge auth.
2026-08-18 14:08:51 -07:00
Peter Steinberger fa62fccb86 refactor(gateway): remove workspace plugin generation projections (#125990)
* refactor(agents): remove workspace plugin generation projections

* test(agents): pass explicit generation in auth refresh
2026-08-18 14:03:27 -07:00
Peter Steinberger f2158a9c36 feat(sessions): keep durable work visible and auto-archive stale sessions (#124925)
* feat(agents): clarify visible session guidance

* feat(sessions): auto-archive inactive dashboard sessions

* fix(sessions): preserve active dashboard sessions during maintenance

* test(sessions): preserve admitted dashboard sessions during archive

* chore: refresh session generated artifacts

* test: align recovery id with transcript redaction

* fix(sessions): report only committed maintenance counts
2026-08-18 14:02:54 -07:00
Onur Solmaz f5e9622fc9 fix(providers): report request acceptance consistently (#125807)
* fix(providers): report request acceptance consistently

* fix(providers): retain response hook compatibility

* fix(providers): keep legacy response hook path

* fix(providers): distinguish rejected response attempts

* fix(providers): keep acceptance evidence truthful

* fix(google): preserve provider acceptance errors

* test(google): satisfy acceptance callback lint

* fix(google): exclude acceptance hooks from retry deadline

* fix(openai): report Codex websocket acceptance

* fix(openai): commit websocket state before acceptance hook

* fix(google): abort pending acceptance callbacks

* fix(providers): abort pending acceptance callbacks

* fix(mistral): report observed HTTP response

* fix(mistral): report rejected HTTP responses

* fix(providers): derive acceptance from HTTP status

* fix(providers): preserve acceptance lifecycle cleanup

* fix(anthropic): report observed HTTP response

* fix(anthropic): report rejected HTTP responses

* fix(plugin-sdk): expose provider lifecycle

* fix(providers): stop after lifecycle abort

* fix(mistral): cancel unread acceptance failures
2026-08-18 23:50:57 +03:00
Peter Steinberger 549e6349f8 fix(workboard): prevent orphaned runs and overwritten cards (#125951)
* fix(workboard): make ownership updates atomic

Persist launch intent before worker acceptance, reconcile accepted identities,
fence cross-host card mutations, and deduplicate session capture in SQLite.

Closes #125932

* test(workboard): keep race fixtures plugin-local

Use a plugin-local synchronization helper and update the sessions-page capture
expectation for the new store-owned RPC.

* fix(workboard): fence lifecycle and restore races

Apply terminal lifecycle state only while the matched association is current,
and converge concurrent archived session restores on the active winner.
2026-08-18 13:50:17 -07:00
Peter Steinberger f97a133254 fix(config): fail config unset on a missing path again (#125958)
runConfigUnset scoped its missing-path error to --dry-run, so the real
invocation printed "No change" and exited 0 while --dry-run on the same
input exited 1 with a specific message. Dry-run exists to predict the
real run, and a typo'd unset in a script reported success.

Restore the failure for both modes, keeping the strict-config assertion
introduced alongside the regression and the JSON5 byte preservation it
was added to guarantee.
2026-08-18 13:45:57 -07:00
Peter Steinberger f59392fdf5 fix(channels): redact logs and reject unknown filters (#125939)
* fix(channels): redact and validate log filters

* fix(logging): preserve filtered redacted channel tails

* fix(channels): match log filters on exact boundaries

* fix(logging): honor redaction off mode
2026-08-18 13:37:17 -07:00
Peter Steinberger 1d36dac99d fix(gateway): retain chat root through error persistence (#125985) 2026-08-18 13:33:35 -07:00
Peter Steinberger d1a194b52f fix(gateway): refresh edited skills in agent RPC sessions (#125962)
* fix(gateway): watch skills for agent RPC turns

* ci: rebalance hosted agent chat shard
2026-08-18 13:06:48 -07:00
Peter Steinberger a99253f73e perf(test): reuse plugin load-context modules (#125965) 2026-08-18 12:26:24 -07:00
Peter Steinberger bb92dc61c8 fix: stop --tag main from failing during npm pack (#125949)
* fix: refuse unsupported OpenClaw source package updates

* refactor: narrow main update refusal
2026-08-18 12:22:45 -07:00
Peter Steinberger 110be8ccb6 fix: resume turns settled during gateway restart drain (#125955)
Keep drain-owned recovery state authoritative when the pre-restart run reaches a normal terminal event, so startup continues the original request without requiring a manual retry.\n\nRelated: #57425
2026-08-18 12:14:16 -07:00
Peter Steinberger 7ae9cbf3bc fix(cli): stop claiming a write when approvals mutations are no-ops (#125960)
`openclaw approvals allowlist add|remove` printed "Writing local approvals."
from the shared target-resolution helper, before the mutation decision was
made. Both idempotent paths ("Already allowlisted.", "Pattern not found.")
returned without saving, so the CLI announced a write that never happened.
`approvals set` had the same problem: it announced the write and then rejected
unparseable input.

Move the announcement from `loadWritableSnapshotTarget` into the local branch
of `saveSnapshotTargeted`, the function that owns the write. Every caller of
the shared seam is fixed at once and exit codes are unchanged: idempotent add
and remove still leave the requested end state satisfied and exit 0.
2026-08-18 12:12:37 -07:00
Peter Steinberger 153ad5ec27 fix(cli): preserve migration agent ownership (#125948) 2026-08-18 12:10:09 -07:00
Peter Steinberger 82d48e0c03 fix(gateway): clean sessionless agent media (#125938) 2026-08-18 12:00:16 -07:00
Peter Steinberger 5301fb5e7f fix(codex): preserve harness trajectories (#125941) 2026-08-18 11:47:09 -07:00
Peter Steinberger 97a4d324f5 fix(gateway): allow non-admin cloud sessions (#125787)
* fix(gateway): allow non-admin cloud sessions

Admin-provisioned shared runners are now usable by operator.write while raw environment, config, and pairing controls remain admin-only.

Closes #125602

* chore(test): prune assertion safety baseline

* refactor(gateway): isolate cloud reclaim lifecycle

* test(gateway): declare Codex dispatch ownership

* test(ui): cover session-scoped cloud cleanup

* perf(ui): trim tooltip startup path

* fix(gateway): fence cloud placement activation

* test(gateway): update move recovery dispatch contract

* fix(gateway): fail closed on placement recovery

* docs(gateway): explain fail-closed move recovery

* refactor(gateway): consolidate session mutation target keys
2026-08-18 11:33:54 -07:00
Peter Steinberger ef22410985 refactor(protocol): remove beta-only expectedRunId from chat.send (#125921)
The Gateway owns start-or-steer at admission (6515f6a255) and no
client produces expectedRunId anymore (d84a910fc8). The field shipped
only in v2026.8.1-beta.2 - never a stable tag - so it is removed rather
than deprecated. Steer sends resolve the selected session's current
operation; the exact-match branch, the operation|run target identity
discriminator, run_mismatch rejection, and the suggestion producers'
active-run-id selection (with its ambiguity failure) are deleted.
Provider-native turn fencing (Codex expectedTurnId) is unchanged:
the backend-captured runId on the injection target remains.
2026-08-18 11:28:36 -07:00
Peter Steinberger 91cc7d512b fix(cli): report broadcast delivery failures (#125915)
* fix(cli): report broadcast delivery failures

* test(qa): wait for descendant process exit
2026-08-18 11:28:13 -07:00
Peter Steinberger 2ffbff0547 refactor(gateway): bind plugin runtimes to their owning instance (#125821)
* refactor(gateway): bind plugin runtimes per instance

* refactor(gateway): migrate ambient context readers

* refactor(gateway): remove global fallback context

* test(gateway): cover reverse instance shutdown

* fix(gateway): preserve plugin runtime owner on reload

* test(gateway): migrate tool invoke context scope

* fix(gateway): bind remaining runtime ownership
2026-08-18 11:10:32 -07:00
Peter Steinberger 6302114879 perf(test): reuse command differential temp root (#125930) 2026-08-18 11:08:35 -07:00
Peter Steinberger 09f543d6c7 fix(tui): block sends until session events are subscribed (#125928)
* fix(tui): gate chat readiness on session subscription

* test(tui): warm subscription readiness regression
2026-08-18 11:08:13 -07:00
Peter Steinberger 3a96fbd64d feat(canvas): present widgets on native device panels (#125818)
* feat(canvas): present widgets on native panels

* refactor(agents): inline gateway caller selection

* fix(canvas): restrict widget panels to macOS

* refactor(agents): reuse resolved spawn workspace
2026-08-18 11:05:41 -07:00
Peter Steinberger 1958551ff9 fix(channels): defer ingress during gateway drain (#125919) 2026-08-18 10:56:05 -07:00
Peter Steinberger 62b2141118 fix: keep turns active when sessions_yield has no child (#125850)
* fix(agents): reject sessions_yield without child completion

* fix(agents): preserve native child yield claims

* chore(agents): keep tool registry within lint limit

* fix(agents): preserve subagent self-yield
2026-08-18 10:53:37 -07:00
Peter Steinberger fd8326c5bf fix(codex): reap sandbox process trees before termination (#125908) 2026-08-18 10:48:10 -07:00
Peter Steinberger fd216cb550 fix: prevent plugin metadata rescans from stalling Gateway (#125596)
* fix(plugins): preserve gateway metadata ownership

Generic runtime contexts no longer displace the Gateway lifecycle snapshot, preventing repeated synchronous plugin inventory validation on session hot paths.

* fix(gateway): reuse lifecycle plugin generation for turns

* test(agents): align static runtime lifecycle expectations

* test(gateway): refresh minimal runtime fixtures

* test(runtime): pass lifecycle metadata explicitly

* fix(skills): reuse gateway metadata for commands

* test(gateway): prepare reply runtime for agent RPCs

* style(agents): format rebased runtime preparation

* test(gateway): prepare runtime for direct agent RPCs

* test(gateway): provide direct agent runtime fixture

* test(gateway): prepare chat send reply runtime

* test(qa): await descendant process exit
2026-08-18 10:47:16 -07:00
Peter Steinberger 0684f50136 fix(gateway): harden hook admission and shutdown (#125893)
* fix(gateway): harden hook admission and shutdown

Flush structured 413 and 408 hook responses before closing oversized or timed-out request sockets, and reject deferred wake requests that target an explicit session.

Direct Gateway close now marks startup and readiness as draining immediately and attempts every HTTP listener shutdown before reporting an incomplete close.

* test(gateway): model request destruction in fuzzing

Give the HTTP request fuzz double the IncomingMessage destroy contract exercised after 413 and 408 responses finish.

* fix(gateway): preserve response and shutdown bounds

Route installed webhook body-limit failures through the shared response-first close owner and require complete Feishu 413/408 responses before terminal connection closure.

Retain the current-main grace bound for agent-harness disposal so one stuck harness cannot block listener teardown.

* test(telegram): model response-close request cleanup

Keep the slow-body request alive through response finish, then assert cleanup when the mock response transport closes.
2026-08-18 10:39:56 -07:00
Peter Steinberger d33ba0015d fix(mcp): preserve recovery text with structured results (#125914)
* fix(mcp): preserve structured result text

* fix(mcp): preserve node-host structured results
2026-08-18 10:36:03 -07:00
Peter Steinberger a7d6256be8 fix(agents): link known progress card references (#125887) 2026-08-18 10:31:28 -07:00
Peter Steinberger bc30277683 perf(test): narrow harness differential mock (#125911) 2026-08-18 10:27:32 -07:00
Peter Steinberger fead7fee27 refactor: consolidate small shared helpers (#125805)
* refactor: consolidate small shared helpers

* fix: reject inherited Parallels smoke arguments

* fix: preserve day-prefixed CPU probe times
2026-08-18 10:23:40 -07:00
Peter Steinberger d204ebe6a4 fix(codex): recover replies after compaction failure (#125895)
Preserve completed tool work when native Codex compaction fails, close failed compaction progress, and bypass unrelated model/auth failover before isolated finalization. Fixes #125789.
2026-08-18 10:22:35 -07:00
Peter Steinberger 96d603f530 fix(gateway): block unauthorized session lifecycle sources (#125889)
* fix(gateway): enforce session participation at lifecycle commits

* refactor(gateway): simplify session target extraction
2026-08-18 10:17:28 -07:00
Peter Steinberger f8ba65636c feat(control-ui): simplified settings experience for non-admin operators (#125492)
* test(control-ui): add --operator-scopes flag to the mock dev server

* feat(control-ui): simplified settings experience for non-admin operators

Non-admin browsers previously saw every settings page, many of which
dead-ended or rendered enabled controls whose RPCs fail with
'missing scope: operator.admin'.

- config.schema drops from operator.admin to operator.read: the schema is a
  static document describing options whose values are already readable via
  read-scoped config.get; admin-only schema only broke read-only settings
  rendering (Automation/Infrastructure/AI Agents/Communications showed
  'Schema unavailable. Use Raw.').
- Settings sidebar and settings search hide admin-only routes (custodian,
  labs, updates, automation, infrastructure, mcp, security, secrets,
  cloud-workers, communications, ai-agents, model-setup) for non-admin
  viewers; legacy gateways without advertised scopes keep the full UI.
- Channels, Devices, Worktrees, Memory Import, Profile gate their mutation
  controls on actual scopes with 'Browsing only…' notices instead of
  enabled-but-failing buttons; Devices no longer fires device.pair.list /
  exec.approvals.get without the scopes to call them (kills the two red
  error callouts on page load).
- Scope-upgrade banner: dismissing it in the guidance phase (no in-app
  upgrade path) now hides it fully instead of leaving a permanent chip.
- Config write coordinator surfaces scope refusals as a visible
  admin-required error instead of silently resolving false.

* test(control-ui): advertise config.schema in the mock dev gateway

ensureSchemaLoaded now checks method advertisement + scope before loading
the schema; the mock harness must advertise config.schema like a real
gateway does or schema-driven settings pages render empty in the mock.

* fix(control-ui): close the worktree create draft on scope downgrade

* perf(doctor): isolate memory health artifact

Doctor lint loaded the broad Memory Core API barrel only to register health checks and read isolated check IDs. That synchronously pulled the full memory public graph into the first lint run, consuming most of the 120-second test budget.

Load a dedicated doctor-health public artifact instead and verify it is packaged. The bisect boundary was 9de3ca5fc9 (#125571); because that commit only adds upgrade-test assets, it exposed a pre-existing runner-sensitive cost rather than introducing the expensive import path.

* test(control-ui): restore device lifecycle test boundary

* perf(control-ui): lazy-load settings sidebar

* fix(ui): recheck access after confirmations

* fix(control-ui): gate presence-driven device reloads on pairing access

The presence connectivity-change path still called device.pair.list without
operator.pairing, the same invariant the pair-event and poller paths already
guard; a limited browser got a doomed RPC on every connectivity change.

* fix(control-ui): fail open on schema loads for legacy scope-less gateways

canCallGatewayMethod hardened to strict advertisement+scope checks (#125478),
which made the new ensureSchemaLoaded gate silently skip config.schema for
legacy hellos without advertised scopes or a method list. Schema loads now
skip only on a definitive denial (method advertised absent, or advertised
scopes without operator.read), reusing the fail-open hasOperatorReadAccess
semantics the rest of the non-admin UI uses; regression test pins the
legacy snapshot path.

* test(control-ui): split schema-access coverage into its own file

runtime-config-capability.test.ts crossed the max-lines cap; the legacy
fail-open regression and its denial counterpart move to a colocated
schema-access test file.

* fix(scripts): keep mapped Vitest lanes at their measured no-output floor

The codex extension shard legitimately works in silence beyond 300s under
the default reporter (measured 61s import + 293s testing at ~95% CPU); the
CI-wide OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=300000 env override shrank the
lane below that and the watchdog killed healthy runs, flipping with
incidental flake output (#125825). Per-config entries in
VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS now act as measured silence floors: a
global env value may widen a mapped lane's window but no longer shrinks it;
unmapped configs and the explicit '0' disable keep env verbatim. Adds the
codex extension lane to the map at the extra-long tier (same class as the
discord entry from #123025).
2026-08-18 10:15:10 -07:00
Peter Steinberger b9d0120ee2 fix(cli): protect immutable deployment artifacts (#125902) 2026-08-18 10:11:43 -07:00
Dallin Romney 1a2af5c690 fix(exec): isolate interactive shell env imports (#125624) 2026-08-18 10:06:19 -07:00
Peter Steinberger b9d0e13b5d fix(agents): share one delegation policy across agent runtimes (#125892)
The `## Delegation` guidance added in #125691 lived only in
buildAgentSystemPrompt, so Codex-runtime agents never received it: the
Codex harness builds its own developer instructions in
extensions/codex/src/app-server/thread-prompt.ts and imports nothing
from the system-prompt builders. Live A/B on gpt-5.6-luna had the native
runtime answer "spawn a visible session" while the Codex runtime
answered "spawn a hidden subagent".

Move the policy into src/agents/delegation-guidance.ts, owning both the
main-session mode resolver and the section text, and export it through
the agent-harness plugin SDK barrel that the Codex harness already uses.
The hidden-delegation vocabulary is injected by each runtime, so core
never names a plugin-owned tool: native passes `sessions_spawn`, Codex
passes native `spawn_agent`. Visible sessions stay `sessions_spawn`
with visible=true on both runtimes because Codex-native children are
never OpenClaw sessions.

Also narrows the Codex line that told the model to use `sessions_spawn`
only for OpenClaw/ACP delegation; it now scopes that to internal
legwork, so user-facing deliverables still route to a visible session.
2026-08-18 09:57:52 -07:00
Peter Steinberger 2bed8caf9e feat(ui): channel conversation avatars in the sidebar (Discord + Slack) (#125668)
* feat(gateway): proxy channel conversation avatars

* feat(discord): capture conversation avatars

* feat(slack): capture DM sender avatars

* test(discord): bind guild avatar mock

* feat(ui): render channel conversation avatars

* fix(ui): align sidebar owner fixtures

* fix(gateway): version channel-avatar routes by media revision

A stable per-session URL let AuthenticatedAvatarRouteLoader's blob and
sticky-404 caches pin a mounted row to a stale or blank avatar after the
backing media changed. Append an opaque digest of the media reference so
replacement and 404-recovery change the route identity.

* test(ui): align sidebar owner facet

* fix(ui): keep owner chip until channel avatar loads

A session with a channelAvatarUrl suppressed its owner chip even while the
blob was loading, auth was not ready, or the route 404ed, leaving an empty
lead slot. The chip now rides as fallback content inside the avatar element
and yields only to a usable image. Covers 404 and auth-pending states;
avatar rows keep renderedOwnerId unset so an owner-viewer stays visible in
the facepile.

* perf(ui): keep channel avatar fallback within budget

* perf(ui): lazy-load the channel avatar element

The avatar element and its authenticated blob loader rode the startup
bundle through session-leading-indicator, pushing startup JS 51 B over the
CI gzip budget. Channel avatars are not startup-critical: register the
element on the first avatar row; the owner-chip fallback covers the
one-time upgrade window. Startup JS returns ~1 KiB under the ceiling.

* build(ui): raise startup baseline for channel avatars

CI-measured startup JS is 344379 B against a 343289 B baseline (+1090 B).
The avatar element and blob loader are code-split out of startup (previous
commit); the residual is the sidebar lead-slot render branch and row
plumbing, which cannot be deferred. Baseline updated via
check-control-ui-performance --update-baseline with CI bytes per the
script's contract; well inside the 4096 B ratchet step and 358400 B
ceiling.
2026-08-18 09:55:50 -07:00
Peter Steinberger 302d05b988 fix(tui): surface interrupted runs after reconnect (#125898) 2026-08-18 09:43:14 -07:00