Commit Graph

11010 Commits

Author SHA1 Message Date
Peter Steinberger 3a49aa1ac6 improve: split hosted Windows CI into three lanes (#123577)
* ci: split Windows tests into three lanes

* test: cover three-way Windows CI partition
2026-08-14 02:40:02 -07:00
Peter Steinberger 8865c2539b ci: shorten hosted PR path (#123570) 2026-08-14 02:11:25 -07:00
Peter Steinberger c0930de5de fix(secrets): scope egress sentinels to Gateway and survive client tunnel resets (#123527)
* fix(secrets): scope exec egress proxy to gateway

* fix(secrets): keep a client reset from crashing the egress proxy host
2026-08-14 01:56:29 -07:00
Peter Steinberger 65597f93b0 fix: restore default-profile backup archives (#123504)
* fix(backup): make default-profile backups restorable

* fix(backup): preserve restore cleanup context

* refactor(backup): drop preserve-caught-error suppression via hoisted cleanup error

* refactor(backup): hoist restore failure handling out of catch scopes
2026-08-14 01:39:08 -07:00
Peter Steinberger 749340fc16 ci: widen hybrid Blacksmith routing (#123552) 2026-08-14 01:37:32 -07:00
Peter Steinberger db2854e681 docs(macos): document cookie sync to a remote computer (#123537)
* docs(macos): document cookie sync to a remote computer

Add a Settings > General > Cookie sync section to the macOS platform guide,
alongside the existing browser-login import docs: off-by-default toggle, domain
allowlist, target profile, remote-mode requirement, host-local decryption, and
the DBSC caveat. Cross-links the browser CLI cookie-sync reference.

* docs(macos): clarify cookie sync status
2026-08-14 00:35:13 -07:00
Peter Steinberger e51ee089b7 improve: add hybrid CI runner backend (#123479)
* ci: add hybrid runner backend

* test: admit hybrid backend in CI fixture
2026-08-14 00:19:28 -07:00
Peter Steinberger 2ef92d0bbe feat: cookie sync from Mac to a remote Gateway browser profile (#123494)
* feat(browser): sync system cookies to a remote gateway profile

Add `openclaw browser cookie-sync`: decrypt allowlisted macOS Chrome-family
cookies locally and push them into a managed profile on a possibly-remote
Gateway over the existing operator channel. --watch re-syncs on cookie-DB
changes with a single Keychain prompt per session.

- New POST /cookies/set-many batch route (mirrors /cookies/set)
- Extract one canonical readSystemProfileCookies reused by import + sync
- Mandatory domain allowlist (never syncs an unrestricted cookie jar)
- Decryption stays host-local (macOS); no cookie values are logged

* feat(macos): cookie sync checkbox and configuration UI

Add an off-by-default 'Cookie sync' section (Settings > General): a toggle, an
editable domain allowlist editor, and a target-profile field, actionable only in
remote-gateway mode. CookieSyncManager supervises `openclaw browser cookie-sync
--watch` against the connected Gateway when enabled, resolving a LOCAL CLI (never
the SSH-redirect path, since decryption is host-local) and injecting gateway
URL + token/password via environment, never argv. A status row surfaces
running/stopped/error and the last sync summary.

* fix(macos): satisfy cookie sync lint gates

* chore(i18n): register cookie sync native source strings

Regenerate apps/.i18n/native-source.json baseline for the new macOS Cookie
sync settings strings (additive only). Satisfies the native:i18n:verify gate;
generated locale artifacts are refreshed separately by the locale-refresh job.
2026-08-13 23:47:26 -07:00
Peter Steinberger 312397ab4d feat(providers): add GLM 5.3 support (#123523) 2026-08-13 23:34:50 -07:00
Peter Steinberger 848a7e30b3 refactor(computer-use): one canonical wire contract + node-host provider seam (#123509)
* refactor(computer-use): add provider seam

* refactor(computer-use): retry provider open after failure; drop changelog entry
2026-08-13 23:32:32 -07:00
Peter Steinberger 252bb545b4 fix(macos): keep background hosts out of GUI keychain (#123500)
Background-only Bridge and Mac-node launches keep GUI onboarding and saved Gateway-profile Keychain state cold while preserving environment/config-owned Gateway connectivity.
2026-08-13 23:28:26 -07:00
Peter Steinberger 7cadfb0bd6 fix: speed up local node launches and isolate scratch state (#123503)
* perf(node-host): reuse advertised worker build identity

* fix(agents): keep default workspaces inside state dir

* fix(plugins): package llama.cpp private SSRF runtime

* fix(node-host): silence missing skills directory
2026-08-13 23:24:54 -07:00
Peter Steinberger ee258beba6 fix(reef): diagnose relay protocol skew (#123498) 2026-08-13 22:47:53 -07:00
Peter Steinberger 1400049ae9 improve(ci): cut hosted test import time with warm caches (#123465)
* perf(ci): restore hosted test caches across lanes

* perf(ci): restore caches in remaining Vitest lanes
2026-08-13 22:41:27 -07:00
Peter Steinberger ebd0133be2 fix(agents): preserve Swarm collector errors (#123468) 2026-08-13 22:05:10 -07:00
Peter Steinberger 737982d5fe fix(macos): adopt Peekaboo 4.1 bridge contracts (#123420)
* feat(macos): adopt checked Peekaboo bridge runtime

* fix(macos): preserve bridge snapshot retention

* docs(macos): clarify bridge client identity

* fix(macos): retry transient timestamp signing

* build(macos): pin embedded Peekaboo runtime

* fix(macos): expose embedded bridge source identity

* test(macos): isolate gateway launch agent hooks

(cherry picked from commit 7da18c5fee43fed7e8dfa42c4851f99d035b2a36)

* test(macos): pin gateway command mode

* fix(macos): preserve Peekaboo bridge provenance
2026-08-13 22:03:47 -07:00
Peter Steinberger 7026cf2f21 fix(delivery): bound failed-row retention lifecycle (#123410) 2026-08-13 22:03:33 -07:00
Peter Steinberger 928942d48d feat(sessions): legacy-main session migration engine (#123424)
* feat(sessions): add legacy main migration engine

* fix(sessions): keep migration types internal

* fix(sessions): harden legacy main migration convergence

* fix(sessions): prefer stale migration claims over lock errors

* fix(sessions): keep unresolved owner notices nonblocking
2026-08-13 21:33:37 -07:00
Peter Steinberger 25d4807b38 feat(anthropic): opt-in server-side compaction (compact-2026-01-12) (#123402)
* feat(anthropic): add server-side compaction replay

* docs(anthropic): document server compaction

* test(anthropic): harden compaction live probe

Fix the live fixture baseUrl (the SDK appends /v1 itself), fail fast on
errored turns instead of silently looping, assert request-side injection
before capture, and log per-turn stream outcomes for live debugging.

* test(anthropic): keep live settings type module-local

* refactor(agents): split transcript replay sanitizers

* test(anthropic): move compaction live probe into plugin tree

* refactor(anthropic): consolidate compaction replay duplication

* test(anthropic): align compaction threshold host coverage

* test(anthropic): fabricate checkpoints via capture tracker

Keeps captureAnthropicCompaction module-local; knip flags exports whose
only consumers are tests.
2026-08-13 21:28:19 -07:00
Peter Steinberger 860aeed8f6 feat(gateway): transfer node worker workspaces (#123280)
* feat(gateway): transfer node worker workspaces

* fix(gateway): harden node workspace transfer

* fix(gateway): isolate transfer HTTP contract

* fix(gateway): trim transfer HTTP exports
2026-08-13 21:00:44 -07:00
Peter Steinberger b9c6789560 feat(secrets): authenticated egress substitution proxy with destination binding (#123216)
* feat(secrets): add authenticated egress substitution proxy

* feat(secrets): bind egress substitution to hosts

* ci(codeql): classify egress proxy bypass tunnel in network boundary query

* refactor(proxy-capture): use the canonical IP parser instead of node:net

* fix(secrets): compare proxy tokens with a process-keyed MAC
2026-08-13 20:49:31 -07:00
Peter Steinberger 575467aa58 fix(openai): unify server-side compaction gates and harden compaction recovery (#123397)
* fix(openai): unify server compaction policy

* fix(openai): preserve managed responses aliases

* fix(compaction): harden bounded recovery

* refactor(compaction): simplify orphan output classifier

* fix(compaction): unanchor overflow classifiers and route image constant through runtime facade

* test(openai): use provider input config in compaction parity

* test(openai): model default compaction route accurately

* fix(openai): isolate responses payload policy imports

* fix(ai): remove unused responses api re-export

* fix(plugins): resolve responses policy source alias
2026-08-13 20:45:07 -07:00
Peter Steinberger c06f993b5c fix(ci): restore hosted cache writers (#123440) 2026-08-13 20:16:54 -07:00
Peter Steinberger 47d3661c58 fix(ci): balance QA smoke profile parts (#123434) 2026-08-13 20:08:51 -07:00
Bek eb1035e861 fix(codex): retain direct-child hook policy after parent yield (#122503) 2026-08-13 22:51:34 -04:00
Patrick Erichsen 387937f27b fix: forward skill evaluation correlation (#123425) 2026-08-13 19:38:52 -07:00
Peter Steinberger 257eb21235 improve(ci): shorten GitHub-hosted Node matrix (#123406)
* improve(ci): shorten GitHub-hosted matrix wall time

* fix(ci): keep hosted dependency setup store-only

* fix(ci): split the hosted tooling tail
2026-08-13 19:32:50 -07:00
Peter Steinberger 23c9c04572 fix(sessions): hide unowned host catalogs on multi-user gateways (#123421)
* fix(sessions): scope catalogs by caller identity

* fix(llama-cpp): keep doctor imports lightweight
2026-08-13 19:28:22 -07:00
Peter Steinberger b376b13fec feat(docker): weekly refresh of published moving image tags (#123348)
* feat(docker): schedule image refreshes

* docs(docker): explain weekly image refreshes

* test(scripts): gate workflow-step execution on bash 4 mapfile support

Stock macOS bash 3.2 lacks mapfile; CI truth is Linux bash 5.

* test: cover docker-release suffix threading and sanctioned second caller

* test(codex): wire run-attempt-state into the attempt-extra project

#123345 added the file without a project owner; the full-suite coverage
guard fails for any PR that runs it.

* fix(ci): run build-artifacts PR validation on hosted runners

ci-build-artifacts-testbox.yml pinned PR runs to blacksmith-16vcpu and
ran Testbox lifecycle steps unconditionally, so the prepare-run landing
gate starved for every PR during a Blacksmith outage even with
OPENCLAW_CI_RUNNER_BACKEND=github. PR events now build on ubuntu-24.04
with dispatch-only Testbox steps, mirroring ci-check-testbox.yml.

* test(ci): align build-artifacts dispatch guard
2026-08-13 19:20:05 -07:00
Peter Steinberger 18163ba269 feat(skills): resolve explicit $skill references on every channel (#123387)
* feat(skills): resolve explicit $skill references on every channel

Explicit $skill-name references from authorized senders now resolve on all
channels, not only WebChat/Control UI, and explicitly referenced skills are
always invoked: disable-model-invocation keeps a skill out of model-initiated
selection but no longer blocks user-initiated explicit references. Hidden
skills carry their SKILL.md path in the injected instruction since the model
cannot discover them from the available-skills prompt.

Part of #123367

* fix(ci): dedupe run-attempt-state vitest lane ownership

Main is red on the full-suite ownership audit from the #123235 x #123363 double-registration race. Keep run-attempt-state.test.ts beside its run-attempt siblings in the extra lane and heal the audit here per the land-onto-red-main policy.
2026-08-13 18:02:25 -07:00
Peter Steinberger 438d035885 feat(gateway): launch workers on paired nodes (#123157)
* feat(gateway): launch workers on paired nodes

* docs(plan): track node worker launch wire

* fix(runners): restore node workspace ownership

Rehydrate durable workspace bindings after Gateway restart, fence timed-out node tunnel starts, and refuse incomplete clone fallback for submodule and Git LFS workspaces.

* test(runners): isolate node launch fixtures
2026-08-13 18:02:18 -07:00
Peter Steinberger 7a378f1f8e improve(ci): rebalance GitHub-hosted compact test lanes (#123383)
* perf(ci): rebalance GitHub-hosted compact hints

* test(ci): exclude failed hosted timing samples

* fix(ci): keep Codex state test in one Vitest lane
2026-08-13 17:45:33 -07:00
Peter Steinberger d2dad76ecd feat(doctor): relocate shared auth store into state DB (#123349)
* feat(doctor): relocate shared auth store into state DB

* fix(doctor): make shared auth relocation crash-safe

* fix(doctor): skip disabled shared auth inspection

* fix(doctor): break shared auth migration cycle

* fix(doctor): remove unused migration type export

* fix(test): remove duplicate Codex attempt shard
2026-08-13 17:44:02 -07:00
Peter Steinberger 1348387076 refactor(plugins): replace node-llama-cpp with managed llama-server (#123105)
Move llama.cpp chat and local embeddings onto a verified externally managed llama-server runtime. Remove the in-process native runtime, forked embedding workers, and node-llama-cpp dependency while preserving guided setup, local GGUF models, tool-capable agent runs, diagnostics, and operator docs.
2026-08-13 16:58:20 -07:00
joshavant 639e7718f3 fix(models): preserve refresh generation and fallback 2026-08-13 18:57:50 -05:00
joshavant 6659007352 fix(models): preserve explicit discovery outcomes 2026-08-13 18:57:50 -05:00
joshavant d83f7b815d fix(models): defer live catalog discovery 2026-08-13 18:57:50 -05:00
Peter Steinberger 6995f98243 ci: split remaining GitHub-hosted tail lanes (#123364)
* ci: codify manual-only Node 22 compatibility

* ci: split remaining hosted tail lanes

* fix(qa-lab): carry the validated part index into the plan id type

* test(ci): repair hosted tail lane guards
2026-08-13 16:52:25 -07:00
Peter Steinberger c9621adf3e feat(google): add Gemini 3.7 Flash with LOW thinking floor (#123366)
* feat(google): add Gemini 3.7 Flash to the model catalog

* fix(google): floor Gemini 3.7 Flash thinking at LOW — MINIMAL retired upstream

* fix(google): satisfy no-map-spread in catalog row builder
2026-08-13 16:34:13 -07:00
Peter Steinberger b1491356df ci: shard hosted UI e2e further (#123329) 2026-08-13 15:20:37 -07:00
Peter Steinberger 4a5aeb8dd2 improve(ci): shorten GitHub-hosted outage runs (#123294)
* ci: run push compacts without tooling lanes and stripe giants three-way

* fix(ci): keep CompactNodeTestPlanMode internal

knip --production flags the exported type as unused; no external module
imports it.

* ci: shard hosted lint and node tests

Split core oxlint across hosted runners and use backend-specific compact Node admission caps while preserving Blacksmith behavior.

* test(ci): guard plugin prerelease planner isolation
2026-08-13 15:19:15 -07:00
Peter Steinberger b3d5265f58 fix(docker): harden runtime images against CVE surface (#123282)
* fix(docker): harden runtime image dependencies

* chore(deps): update container security dependencies

* docs(docker): explain image security contents

* test(browser): align file-chooser and install tests with #114506 contract

* test(browser): restore extension install test isolation

* test(browser): add temporary CI diagnostics for pre-registration refusal

* test(browser): make install fixture interpreter hermetic

The suite passed process.execPath as the native-host interpreter; on
GitHub-hosted runners the hostedtoolcache node binary is group/world-
writable, which installChromeExtensionBootstrap correctly refuses, so
every registration test failed CI-only. The fixture now provides an
owned 0700 interpreter; only the launcher-exec test keeps the real
node it must spawn.

* fix(qa-lab): stop re-polling after a probe consumes the discovery deadline

The Matrix health-probe loop re-entered when the probe timeout fired
marginally before Date.now() crossed the deadline, starting a doomed
extra probe. Flaked on contended CI runners as 'expected 1 fetch, got
2'. A timed-out probe now ends discovery.

* test(ui): poll the callout inset invariant in device-scope E2E

One-shot boundingBox reads raced the nav-collapse transition and
intermittently measured a 20px stale offset on CI.
2026-08-13 14:02:39 -07:00
Peter Steinberger 2dcd47d4f4 feat(runners): remember offline devices (#123198)
* feat(runners): remember offline devices

Persist exact node connection end timestamps and keep execution-capable offline devices visible with quiet lifecycle history in the session picker.

* test(ui): keep offline devices disabled
2026-08-13 13:49:00 -07:00
ClawSweeper 036bcc1a65 fix(agents): self-heal unsupported harness transports (#123258)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-13 13:08:35 -07:00
Peter Steinberger 927a97c1ea fix: keep automation delivery owned in multi-agent fleets (#123283)
* fix: preserve automation owner during channel bootstrap

* fix: retain scoped runtime during cron delivery

* style: format cron delivery regression

* chore: defer release changelog entry
2026-08-13 12:52:34 -07:00
Peter Steinberger 21d59e16e2 feat(gateway): monitor cloud session disk space (#123177)
* feat(gateway): monitor cloud session disk space

* fix(gateway): keep disk monitor contract acyclic
2026-08-13 12:47:53 -07:00
Peter Steinberger b233ea7957 fix(health): surface blocked ingress lanes (#123234) 2026-08-13 12:44:59 -07:00
Peter Steinberger 8e0f464a5f fix(gateway): suppress ambient channel auto-enable (#123174) 2026-08-13 11:20:40 -07:00
Peter Steinberger 11b3bf374c feat(slack): unify the native progress turn into one streamed message (#122976)
* feat(slack): unify the native progress turn into one streamed message

Native progress mode now streams the whole turn into a single Slack message:
narration flows as markdown_text chunks interleaved with plan/task chunks,
task rows carry file-path details and +N/-N output, the terminal task links
the session via url_source, and the final answer lands through stopStream in
the same message. Media/oversized/error finals keep their normal-delivery
fallbacks.

Deletes the finished-card receipt collapse (the '\u{1F6E0} N tool calls · ⏱ Ns' edit)
outright: the card now stays as its finished self.

Live-verified on a real workspace: exactly one bot message per turn.

* fix(slack): serialize native stream updates and keep append-only rendered text monotonic

Overlapping progress updates (compositor render, narration payload, final)
computed their narration delta before awaiting the network and committed
state only afterwards, so concurrent updates re-appended identical
narration into the streamed message (each status line landed 3x live).
A single ordering chain now makes each update's compute -> append -> commit
atomic.

applyAppendOnlyStreamUpdate also replaced the accumulated rendered text
with the incoming cumulative partial once an appended chunk had diverged
rendered from source, dropping content the sink already displayed; rendered
now only ever extends.

* fix(slack): stop refreshing thread status once a turn has visible output

Slack clears the assistant thread status as soon as the app puts anything
in the thread, and renders its own rotating agent-working row ("Generating
response...", "Finding answers...") for every status write after that -- it
ignores the app-supplied string. The typing keepalive re-set the status
every 3s for up to 60s, so each turn painted a duplicate status row under
the streamed card or progress message.

The status write is now gated on the turn having visible output, which the
dispatcher already tracks (delivered reply, committed preview, or posted
draft message). The first status still fires before any output, so slow
turns keep their indicator, and the typing reaction is tracked separately
so a suppressed status write still cleans up its reaction.

* fix(slack): let the plan card own the status line instead of echoing it

The status headline and plan explanation fed both the streamed narration
markdown and the plan card title, so every headline rendered twice: once as
static text and once in the card that keeps updating it in place. Narration
now carries only authored commentary and reasoning, and a preamble payload
whose text the card title already shows is not streamed again.

* feat(slack): make the native agent card the default progress surface

Slack's native plan/task card was opt-in behind streaming.progress
.nativeTaskCards while the Block Kit session card shipped as the default.
The native surface is the better product on every axis we can measure --
one streamed message instead of three artifacts, live task rows with file
paths and diff counts, and Slack's own agent chrome -- so it becomes the
default and an explicit false selects the Block Kit card instead.

The session link is now emitted only when it can actually work: the
operator set gateway.publicOrigin and left the Control UI enabled.
Installations with no externally reachable Gateway get no link rather than
a dead one.

The progress card still only appears for turns that do real work; the
existing compositor start gate keeps plain question-and-answer turns
card-free.

* fix(slack): finish the final inside a buffered native stream

A short narration leaves the SDK session un-flushed, so `delivered` stays
false until `stop` makes its first network call. Requiring delivery before
finishing in-stream sent the final through normal delivery and then
finalized the stream anyway, producing exactly the second message this path
exists to prevent. Stop-time rejection already falls back via
SlackStreamNotDeliveredError, so a live session is enough.

Addresses the ClawSweeper P1/P2 finding on this PR.

* refactor(slack): collapse duplicate streaming surfaces and drop dead code

Cleanup pass over the progress/streaming neighborhood, all verified unused
by exhaustive reference search:

- Deleted buildSlackProgressStreamStartChunks/UpdateChunks: byte-identical
  pass-throughs to the same builder, plus the render-module branch that
  chose between them. One exported builder now.
- Collapsed slackStreaming.draftMode, a lossless restatement of the mode it
  was derived from, and its outbound mapper; nine comparisons now read the
  mode directly. Inbound legacy parsing stays for doctor migration.
- Dropped stopSlackStream's text parameter, the draft stream's stop() member
  and onMessageSent hook, a redundant nativeStreaming argument, four dead
  members on the progress runtime, and two single-expression wrappers.
- Deduped the native card title, which was computed twice per render.

Production LOC for the whole PR drops from +216 to +114.

* chore(config): regenerate bundled channel metadata for the Slack card default

The generated metadata still carried the old opt-in help text and
default-false description for streaming.progress.nativeTaskCards, so
config UI and diagnostics would publish stale guidance.

* fix(slack): un-export the now-internal legacy draft-mode type

Collapsing draftMode removed the type's only external consumer, so knip
flagged it as an unused export. Doctor migration still parses these legacy
values inbound, so the type stays module-local.
2026-08-13 11:19:32 -07:00
Peter Steinberger 2a70d849e8 improve(ci): stripe giant compact test groups (#123142)
* ci: stripe media-ui, gateway-core, and security compact groups

* fix(ci): preserve compact stripe config ownership
2026-08-13 10:46:38 -07:00