Commit Graph

71845 Commits

Author SHA1 Message Date
ooiuuii 39c6db44fb fix(update): hide divergence when histories cannot be compared (#111946)
* fix(update): hide incomparable git divergence

Co-authored-by: luyifan <al3060388206@gmail.com>

* fix(update): handle dashed upstream refs

* fix(update): preserve older Git support

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 02:24:04 -07:00
Vincent Koc e9f2bd63a3 refactor(models): share config ref flattening (#113591) 2026-07-25 17:20:38 +08:00
Vitor Cepeda Lopes 2296e898e1 fix(release): stop Windows package descendants after timeout (#111956)
* fix(release): terminate Windows package command trees

* fix(release): type package runner test output

* fix(release): scope package runner normalization to Windows

* test(release): run package timeout proof on Windows CI

---------

Co-authored-by: TheAngryPit <16145902+TheAngryPit@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 02:20:27 -07:00
Peter Steinberger 446816f751 test: table-drive followup scenarios, centralize sanitizer wiring, remove obsolete negatives (#113583)
* test(auto-reply): table-drive followup runner scenarios

* test(channels): centralize sanitizer wiring coverage

* test: remove obsolete negative coverage
2026-07-25 02:14:44 -07:00
Levi Hayes f78d958aca fix(gateway): streamed OpenAI-compatible requests fail with a spurious draining error (#113514)
* fix(gateway): retain root-work admission for streamed HTTP runs

Streaming requests to /v1/chat/completions and /v1/responses dispatch the
agent run from a detached `void (async () => {...})()` that intentionally
outlives the HTTP handler. The handler itself runs inside
runWithGatewayHttpWorkAdmission, which releases its root-work admission as
soon as it returns.

Because the detached run inherits that same AsyncLocalStorage store, it ends
up holding a *released* lease. isGatewaySubordinateWorkAdmissionClosed()
returns `current.released` for an inherited store, so every subordinate
session/lane admission the run subsequently requests is refused with
GatewayDrainingError - on a gateway that is not draining at all.

Symptoms: streamed turns fail partway with "Gateway is draining; new tasks
are not accepted", surfacing to OpenAI-compatible clients as a generic error
chunk. Non-streaming requests are unaffected, because they await the run
inside the handler's still-live admission.

Fix: retain the admission across the handler boundary with
retainGatewayRootWorkAdmissionContinuation() - the helper that already
exists for exactly this case ("Transfers an admitted request root to work
that intentionally outlives its handler") - and release it in the existing
finally block so drain accounting stays balanced.

* test(gateway): cover streamed HTTP admission lifetime

* test(gateway): satisfy deferred timer lint

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 02:14:30 -07:00
Vincent Koc 21667ef33c refactor(telegram): reuse shared error coercion (#113589) 2026-07-25 17:10:51 +08:00
destire-mio 0f92546408 fix(sdk): preserve zero values in normalized event IDs (#113349)
* fix(sdk): preserve zero values in event ids

* test(sdk): isolate zero event ID components

---------

Co-authored-by: destire-mio <248462155+destire-mio@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 02:07:59 -07:00
Peter Steinberger aba0b12014 refactor(browser): split Playwright session manager (#113585) 2026-07-25 01:58:10 -07:00
Peter Steinberger b03570fc60 refactor(infra): stage heartbeat runner (#113570) 2026-07-25 01:57:20 -07:00
Vincent Koc e4d6170237 refactor(matrix): reuse shared error coercion (#113586) 2026-07-25 16:54:55 +08:00
Peter Steinberger 48ab15851b test: consolidate Slack and QMD matrices (#113574) 2026-07-25 01:53:49 -07:00
Ben Badejo c61111ba93 fix(matrix): gateway startup stalls after repeated token rotation (#113489)
* fix(matrix): avoid scanning settled storage roots

* test(matrix): prove unsettled root fallback

---------

Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 01:52:41 -07:00
Peter Steinberger c5a2e9b9fb test(google-meet): deduplicate browser scenarios (#113573) 2026-07-25 01:51:07 -07:00
Vincent Koc e43d68896e fix(sqlite): recover hot rollback journals privately (#113580) 2026-07-25 16:47:27 +08:00
Peter Steinberger 93e0b7fd24 test: deduplicate plugin doctor install fixtures (#113572) 2026-07-25 01:46:53 -07:00
Vincent Koc 7f36147bda refactor(slack): reuse shared error coercion (#113581) 2026-07-25 16:41:46 +08:00
Peter Steinberger dd7f7ada7e feat(sessions): show preambles as live subtitles (#112958)
* feat(sessions): show preambles as live subtitles

* fix(sessions): harden preamble observer ordering

* fix(sessions): suppress duplicate preamble restore

* fix(sessions): preserve preamble observer lifecycle

* fix(ci): satisfy session subtitle checks

* fix(sessions): preserve terminal and preamble dedupe

* fix(sessions): finalize contextless terminal runs

* test(sessions): cover dormant contextless terminals

* fix(sessions): preserve queued preambles across dormancy
2026-07-25 01:26:50 -07:00
Peter Steinberger b0525e1a70 refactor(ai): split OpenAI Responses transport (#113569) 2026-07-25 01:23:28 -07:00
Vincent Koc 3af03aee6c refactor(approvals): share native target resolvers (#113568) 2026-07-25 16:23:14 +08:00
Peter Steinberger 6e604438b6 test(markdown): lock straggler output contracts (#113543) 2026-07-25 01:12:30 -07:00
Peter Steinberger d2b6573690 refactor(channels): remove v2026.7.2-gated compat (flat streaming keys, group intro hint) (#113533)
* refactor(channels): remove flat streaming compat

maintainer-approved early removal of v2026.7.2-gated compat

* refactor(channels): remove group intro hint adapter

maintainer-approved early removal of v2026.7.2-gated compat

Plugin SDK surface baseline update is maintainer-approved for this intentional removal.
2026-07-25 01:09:25 -07:00
Peter Steinberger 2942678214 refactor(memory): split retained state migrations (#113542) 2026-07-25 01:03:35 -07:00
Peter Steinberger a5d758e74b refactor(plugin-sdk): share channel DM policy setup (#113537) 2026-07-25 01:00:53 -07:00
Peter Steinberger 9e9615d7c1 refactor(codex): prune migration pipeline (#113536) 2026-07-25 00:58:11 -07:00
Peter Steinberger 6608e28bce fix(agents): keep relocated auth and shared sessions discoverable (#113559)
* fix(agents): preserve relocated auth and shared stores

* fix(state): avoid control regex in alias probe

* style(state): keep alias probe within line budget
2026-07-25 00:54:08 -07:00
Peter Steinberger e069b9dbdd fix(ui): repair settings titles, scope form-unsafe banner, consolidate advanced settings (#113160)
* feat(ui): repair settings titles, scope form-unsafe banner, consolidate advanced tier

- Advanced/Notifications settings headers rendered raw i18n keys
  (tabs.advanced/tabs.notifications); configPageTitle now resolves through
  the nav registry titleForRoute, deleting the drifting key map.
- Form-unsafe banner is value-aware (only when the user's config has a value
  at a form-unsupported path in the active scope), names the paths, offers an
  Open Raw editor action, and sits in the content column instead of full-bleed.
- Advanced tier collapses to one synced toggle: hidden advanced fields render
  a ghost row that enables the toggle; the Advanced page always reveals and
  hides the toggle; per-section details state and the controlled-open dance
  are deleted; toggle visibility mirrors the renderer's tier split.
- schema.tags no longer tags facet-less paths as "advanced" (common fields
  like update.channel wore a lying chip); the chip is no longer rendered in
  form rows while tag:advanced search keeps working.

* fix(config): dev bootstrap writes canonical agents.entries; finish stale agents.list sweep

- openclaw gateway run --dev failed on a fresh state dir: the bootstrap wrote
  the retired agents.list array and validation rejected its own config
  (Unrecognized key: list). It now writes the keyed agents.entries record;
  new dev.test.ts validates the written shape against the zod schema.
- Revive the dead gateway hot-reload rule: prefix agents.list never matched
  canonical config diffs, so per-agent heartbeat edits fell through to the
  agents:none tail rule; the rule now matches agents.entries.
- config set replacement protection moves from the dead agents.list array
  to the agents.entries map (joins plugins.entries/auth.profiles family).
- Sweep remaining stale agents.list config-path strings in hints, fix-it
  messages, elevated gates, doctor hints, audit text, and type docs to
  agents.entries.*; RPC ids, the internal list projection, and doctor
  legacy-migration references intentionally keep the old name.

* test(ui): derive nav i18n audit from route registry; fix stale bootstrap hint assertion

- Knip flagged navigationCopyEntries (test-only export); the audit now walks
  ALL_ROUTES through prod titleForRoute/subtitleForRoute and rejects raw
  dotted-key output, so no export exists solely for the test.
- commands-context-report expected the retired agents.list[] hint wording.

* fix(config): align rebase resolution with main's roster-aware diagnostic

- tool-policy-diagnostic: keep main's test expectations (dotted
  agents.entries.<id> paths from the roster-aware implementation); our
  pre-rebase bracket-style assertions no longer match any code.
- Reapply the placeholder sweep the conflict resolution dropped:
  generic agents.list[] fallbacks in tool-policy-diagnostic and the audit
  sandbox-mode hint now say agents.entries.*.
2026-07-25 00:51:57 -07:00
Peter Steinberger 29e02e84cd fix(ui): prevent dashboard startup flash (#113558) 2026-07-25 00:49:03 -07:00
Peter Steinberger e94a2e2506 refactor(agents): unify subagent delivery evidence (#113538)
* refactor(agents): unify subagent delivery evidence

* fix(delivery): remove stale context re-export
2026-07-25 00:43:25 -07:00
Peter Steinberger 3018e8b78a refactor: deduplicate micro helpers onto canonical homes (#113534)
* refactor: deduplicate micro helpers

* fix(ai): keep hash prefix helper internal
2026-07-25 00:41:01 -07:00
Vincent Koc 749dbcb2a7 refactor(media): consolidate generated media byte limits (#113556) 2026-07-25 15:39:49 +08:00
Vincent Koc 7a5c47db8e test(sqlite): prove repository interruption recovery (#113555) 2026-07-25 15:37:16 +08:00
Peter Steinberger 4f1b5da9d8 refactor(codex): split app-server config (#113552)
* refactor(codex): split app-server config

* refactor(codex): keep config helper types private
2026-07-25 00:36:50 -07:00
Peter Steinberger 92a35b599a refactor: share channel probe runner (#113540) 2026-07-25 00:24:31 -07:00
Jason (Json) cc1dd8d558 fix(ui): status labels in Control UI fail WCAG AA contrast on their own tint (#113526)
* fix(ui): meet WCAG AA for Control UI status tokens

Status labels (--ok/--warn/--danger/--info) are rendered as text on their
own 8% -subtle tint. Composited over --card and --bg, several pairs fell
below WCAG AA 4.5:1 -- every light-mode token, and --danger/--info in dark.

Retune the failing bases one Tailwind step and re-derive the matching
-subtle/-muted rgba so each pair clears 4.5:1 on card and bg across all six
theme families. Add the missing --info-subtle and adopt it in
.session-avatar--group, whose --ok/--warn siblings were already tokenised.

Non-text uses (status dots, meters, chart bars) only gain contrast, and the
one solid --danger fill carrying white text improves 4.83:1 -> 6.47:1.

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

* docs(ui): state the bound the status contrast audit actually proves

The audit comments named their card/bg bound but not what falls outside it, so
they read as a general guarantee at the exact site the next contributor will
trust. Status labels also land on hover, muted and input surfaces, and one of
those is reachable with real text: the plugins error row sits on a hovered
background at 4.28:1 under dash-light. It improves on the 3.23:1 it replaced,
but it is not AA and the comment should not imply otherwise.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 01:23:31 -06:00
Peter Steinberger e87b3cea18 refactor(plugin-sdk): share doctor key-move builder (#113539) 2026-07-25 00:21:15 -07:00
Peter Steinberger 0881c7d27b refactor: share feishu docx/broadcast and telegram send bookkeeping (#113541)
* refactor(feishu): deduplicate docx insertion stages

* refactor(feishu): share broadcast inbound adapter

* refactor(telegram): share outbound send bookkeeping
2026-07-25 00:18:28 -07:00
Vincent Koc 6734b132f1 test(sqlite): prove restore interruption recovery (#113531) 2026-07-25 15:16:51 +08:00
Peter Steinberger dcaf78735a docs(readme): fix stale claims, restructure, and repair the contributor avatar wall (#113547)
* fix(clawtributors): emit fixed 48px avatar tiles in README wall

* docs(readme): fix stale claims and restructure; apply fixed-size contributor tiles
2026-07-25 00:15:58 -07:00
Vincent Koc f6d456235c refactor(signal): reuse shared error coercion (#113544) 2026-07-25 15:03:40 +08:00
Vincent Koc b4598365d9 refactor(packages): reuse shared error coercion (#113529) 2026-07-25 14:59:59 +08:00
Vincent Koc f4e2be9f82 refactor(agents): reuse markdown code span formatter (#113525) 2026-07-25 14:57:49 +08:00
Vincent Koc 7176dcf314 refactor(anthropic-vertex): share catalog runtime (#113528) 2026-07-25 14:54:05 +08:00
Vincent Koc 9698d38950 refactor(plugins): rely on shared alias resolution (#113523) 2026-07-25 14:30:43 +08:00
Vincent Koc cd53386a05 refactor(wizard): share migration config canonicalization (#113522) 2026-07-25 14:29:55 +08:00
Vincent Koc bcf71e27e6 ci(env): ratchet production variable count (#113519) 2026-07-25 14:07:02 +08:00
Peter Steinberger 7eb9fa3389 refactor(media): read persisted media facts first across all consumers (#113496)
* refactor(media): read persisted media facts first across all consumers

PR 2 of the media legacy retirement program. Gateway display projection,
Control UI (history filtering, attachment rendering, initial-turn
handoff), embedded and plugin-harness hydration, replay/prune, late-media
reconstruction, hooks, media understanding, and trajectory capture now
read nested __openclaw.media facts first. Legacy top-level Media* fields
survive only in the narrow persisted-message compatibility reader (rows
predating the PR-1 dual-write) and the public SDK projection.

Non-goals pinned by tests: rendered batches, reply-payload dedupe,
durable session/outbound queues, and lowercase ReplyPayload.mediaUrl(s)
are untouched contracts.

Consumer matrix covers {legacy-only, facts-only, both-equal,
both-conflict, sparse, type-only, media-only} inputs across every
consumer family; prompt/cache goldens byte-identical; 131-file legacy
consumer sweep run individually (two failures reproduce unchanged on
clean main); 1,047 broad media tests and the full UI lane (5,553) green.

* refactor(media): drop caller-less staging predicate and localize empty-user-row classification

The consumer flip left hasStagedMediaProjection without production
callers (facts-only staging uses hasStagedMediaFacts); delete it and
retest the staged merge matrix against the facts predicate. Unexport
LEGACY_MEDIA_CONTEXT_KEYS (internal only; the derived type stays public).
Move isEmptyUserTextOnlyMessage beside the other message-shape
classifiers in ui/src/lib/chat/message-extract.ts where chat-history
imports it cross-module.

* chore(ui): drop unused hasTranscriptMediaFacts import after predicate move

* chore(ui): localize hasTranscriptMediaFacts after its last external consumer moved in

* style: format staged-media matrix assertion
2026-07-24 23:02:53 -07:00
Vincent Koc bdd5653c3e test(sqlite): prove killed vacuum recovery (#113518) 2026-07-25 13:56:41 +08:00
Peter Steinberger 82d1a03f25 refactor(agents): move implicit-main fallback into load-time roster injection (#112678)
* refactor(agents): require explicit roster defaults

* feat(onboard): create named first roster agent

* refactor(agents): remove runtime main fallbacks

* style(agents): apply roster refactor formatting

* refactor(agents): finish roster-only runtime sweep

* fix(doctor): migrate legacy main session sqlite

* fix(doctor): harden roster session migrations

* fix(onboard): commit first agent atomically

* fix(config): support empty-roster analysis

* fix(agents): preserve legacy main state during creation

* fix(setup): materialize baseline agent roster

* fix(agents): harden legacy default transfer recovery

* fix(agents): simplify roster-only legacy compatibility

* fix(agents): preserve staged first-agent entries

* fix(config): migrate persisted implicit-main rosters

* fix(config): preserve staged empty rosters

* fix(agents): finalize roster-only upgrade paths

* fix(sessions): close legacy main migration outcomes

* fix(config): migrate legacy roster markers at load

* fix(sessions): preserve roster upgrade history

* refactor(sessions): restore lean legacy main compatibility

* fix(setup): prepare first-agent credentials before publish

* fix(config): stabilize roster snapshot migration

* refactor(sessions): shrink legacy main compatibility

* fix(agents): restore roster compatibility fidelity

* fix(sessions): preserve divergent legacy history

* refactor(agents): narrow roster-only scope

* fix(config): isolate roster migration

* test(agents): align roster-only fixtures

* fix(agents): keep main agent undeletable

* fix(agents): harden roster migration invariants

* fix(agents): close setup and audit scope gaps

* fix(cron): scope session reaper throttles by agent

* fix(agents): preserve scoped owner precedence

* fix(config): preserve authored config ownership

* fix(setup): keep default workspace and roster in sync

* fix(setup): preserve default entry workspace on bare runs

* fix(agents): adapt roster rebase to keyed entries

* fix(agents): honor both roster representations

* fix(agents): route roster reads through shared helpers

* fix(config): preserve canonical roster writes

* fix(cron): resolve dynamic default for session reaper

* fix(agents): close dynamic default migration gaps

* fix(agents): align scoped session ownership

* fix(sessions): preserve legacy main directory casing

* fix(agents): align cron and legacy auth ownership

* fix(setup): provision the committed default workspace

* fix(cron): align scoped ownership and reaping

* fix(cron): treat blank agent ids as absent

* fix(cron): retain configured session-store owners

* fix(agents): repair roster-aware CI boundaries

* fix(cron): preserve scoped ownership resolution

* fix(agents): preserve rosterless maintenance paths

* fix(agents): propagate roster ownership through runtime boundaries

* fix(agents): preserve roster ownership across runtime paths

* fix(agents): harden roster diagnostics and legacy routing

* fix(agents): remove redundant diagnostic import

* test(agents): type CLI policy fixture explicitly

* fix(config): preserve canonical roster mutation identity

* fix(doctor): read canonical agent rosters consistently

* fix(config): resolve compound roster unsets safely

* fix(config): finalize main-session reconciliation

* fix(doctor): read canonical session state safely

* fix(sessions): preserve current visibility alias

* fix(config): track roster include provenance

* test(config): type roster provenance cases

* fix(config): refine roster include ownership

* fix(agents): preserve staged roster invariants

* test(config): align fixtures with explicit roster ownership

* test(node-host): preserve optional plan typing

* fix(config): preserve authored roster projections

* test(config): keep raw roster fixtures explicit

* test(config): normalize rosters at runtime fixtures

* fix(config): protect authored roster ownership

* fix(agents): require explicit session ownership

* fix(agents): enforce scoped roster ownership

* fix(sessions): merge fixed-store agent partitions

* fix(agents): harden roster ownership boundaries

* fix(config): reject ambiguous roster projections

* fix(sessions): preserve persisted store ownership

* fix(sessions): keep collision diagnostics additive

* fix(security): scan malformed roster workspaces

* test(config): align snapshot fixtures after rebase

* test(agents): use explicit roster fixtures

* fix(config): harden roster diagnostic boundaries

* fix(sessions): isolate fixed-store agent databases

* test(agents): type malformed default markers

* refactor(sessions): extract store collision resolution

* test(system-agent): split oversized setup coverage

* style(system-agent): format split setup suite

* fix(sessions): preserve promoted store ownership

* fix(sessions): derive scoped owner before target

* fix(sessions): preserve explicit sqlite ownership

* fix(agents): restore roster compatibility across CI

* fix(agents): enforce roster-owned runtime boundaries

* fix(agents): satisfy default lookup lint

* test(sessions): split known-owner coverage

* fix(state): satisfy path identity lint

* fix(agents): preserve malformed roster safety boundaries

* fix(agents): restore roster compatibility at runtime boundaries

* fix(config): satisfy roster boundary type checks

* fix(agents): preserve roster ownership across runtime probes

Setup inference probes now execute as the configured roster owner. Malformed agent-prefixed session rows are intentionally omitted by the fail-closed visibility contract rather than normalized by tests.

* fix(agents): satisfy session list owner lint

* fix(agents): preserve roster-owned runtime boundaries

Restore shared logical rows for exact SQLite session locators while keeping their physical database owner separate. The ownership regression test now constructs an explicit sole-owner database directly instead of relying on first-touch capture, matching the intentional shared-store contract.

* fix(sessions): preserve multiply owned exact stores

* fix(sessions): restore runtime owner boundaries

Keep incognito sentinels agent-owned, fold default-agent approvals into the global snapshot, and preserve the configless legacy-main CLI policy fallback. Also repair the existing CLI watchdog test lifecycle so the compact shard observes its timeout without an unawaited assertion or async timer stall; product behavior is unchanged by that test-only fix.

* test(ci): align owner-scoped fixtures

These assertions are unchanged. The fixtures now declare the intended non-default runner, expose the session-key constant imported by production status code, and select the main approvals bucket explicitly on Windows.

* fix(agents): close final roster ownership gaps
2026-07-24 22:38:09 -07:00
Vincent Koc 5f63f744ea test(sqlite): prove publication interruption recovery (#113512) 2026-07-25 13:09:32 +08:00
Jason (Json) 5cd60fd9fb feat(ui): publish host style variables to embedded MCP apps (#113464)
* feat(ui): publish host style variables to MCP apps

An embedded MCP app received only the `theme` string, so it knew which
appearance was active but nothing about what that appearance resolves to.
Every app therefore had to ship its own palette, and an app installed through
a plugin looked like itself rather than like the surface hosting it.

Publish the Control UI theme as `hostContext.styles.variables`, the field the
MCP Apps specification defines for exactly this. The key set is closed by the
specification, so the mapping is a table from Control UI custom properties to
specification keys; the canonical meaning of each key lives in the carapace
embed contract.

Only keys Control UI can honestly source are published. The specification
lets a host publish any subset and apps resolve the rest from their own
fallbacks, so omitting is preferable to inventing. The body font is
deliberately omitted: it leads with a webfont, and an embedded app may load
fonts only from resource domains it declares itself, so publishing it would
silently resolve to an arbitrary system face. Apps own their sans stack until
Control UI adopts the carapace embed tokens, which define a sandbox-safe one.

Values are read as computed custom properties so nested references are
substituted before crossing into the app's separate origin, where a Control
UI token name would have nothing to resolve against.

Live updates come free: the existing theme subscription already re-sends host
context, and `theme` continues to be published alongside this.

* fix(ui): align MCP app host theme semantics
2026-07-24 23:06:33 -06:00