Commit Graph

5224 Commits

Author SHA1 Message Date
Peter Steinberger 1998fd8e0f fix(ios): preserve keyboard feedback during voice capture (#129462) 2026-08-25 10:22:24 -07:00
Peter Steinberger d050cf956b fix(macos): confirm closing onboarding during API key verification (#129447) 2026-08-25 10:09:21 -07:00
Peter Steinberger 830700d04b fix(macos): reject failing Gateway runtime probes (#129453) 2026-08-25 09:45:39 -07:00
Peter Steinberger 2a33d749e5 fix(macos): keep onboarding progress aligned with recommended setup (#129435) 2026-08-25 09:31:07 -07:00
Peter Steinberger 6ad7915c05 fix(macos): expose channel account failures in settings (#129400) 2026-08-25 08:55:22 -07:00
Peter Steinberger 9444aa5a0a fix(mac): skip network interfaces without an address (#129265) 2026-08-25 06:09:26 -07:00
WhatsSkiLL 0b867e14fe feat(android): unify agent and session pickers (#128309)
* feat(android): unify agent and session pickers

Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>

* chore:refresh-native-i18n-inventory

Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>

* fix:preserve-unknown-chat-agent-selection

Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>

* fix(android): keep unknown agent picker usable

Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Solvely-Colin <211764741+Solvely-Colin@users.noreply.github.com>
Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-25 08:11:36 -04:00
Peter Steinberger 4dc7bb7411 chore(deps): refresh dependencies after seven-day cooldown (#129187)
* chore(deps): refresh dependencies after cooldown

* fix(gateway): emit append-only Responses content events

* chore(deps): retain unverified Sherpa runtime
2026-08-25 05:00:46 -07:00
Peter Steinberger 22fa9f5786 fix(linux): first-run desktop onboarding automatically connects working AI (#129211)
* fix(linux): make desktop AI onboarding work automatically

* fix(linux): harden provider ownership and onboarding lifecycle

* test(ui): document partial onboarding context fixture

* fix(linux): preserve operator-owned onboarding API keys

* fix(linux): retire previously managed provider credentials

* fix(linux): retain rotated onboarding provider credentials
2026-08-25 04:47:35 -07:00
Peter Steinberger d632304dc4 fix(ios): retire stale foreground gateway health probes (#129194) 2026-08-25 02:59:27 -07:00
Peter Steinberger 7a5de93228 refactor(apple): share chat payload normalization (#129113)
Amp-Thread-ID: https://ampcode.com/threads/T-01a037b7-9244-7298-b368-3faab8a11cbf

Co-authored-by: Amp <amp@ampcode.com>
2026-08-25 02:54:40 -07:00
Peter Steinberger 2464c5c637 fix(android): preserve photo orientation in chat images (#129136) 2026-08-25 01:29:33 -07:00
Vitor Cepeda Lopes de969db2c3 fix(macos): make OpenClaw settings pane responsive (#128177) 2026-08-25 01:27:34 -07:00
Peter Steinberger d1eead9e70 fix(android): preserve gateway context paths in control pages (#129087) 2026-08-25 01:07:02 -07:00
Peter Steinberger 0528f44ce4 fix(ios): settle expired background refreshes exactly once (#129097) 2026-08-25 00:35:51 -07:00
Peter Steinberger 50b3e4bc5b fix(android): keep unavailable SMS out of onboarding approval (#129077) 2026-08-25 00:35:01 -07:00
Peter Steinberger 0a04f23bc3 fix(android): select writable calendars for new events (#129055) 2026-08-24 23:53:07 -07:00
Peter Steinberger e861bf2cee fix(ios): report no data for throttled silent pushes (#129026) 2026-08-24 23:16:47 -07:00
Peter Steinberger 058a72fe66 fix(update): bind managed handoffs to exact targets (#128868)
* fix(update): bind managed handoffs to exact targets

* fix(update): preserve campaigns on target mismatch

* fix(update): fence active campaign updates
2026-08-24 17:01:11 -07:00
Vincent Koc e27433c22e improve(ci): shard iOS screenshot capture (#128460)
* perf(ci): shard iOS screenshot capture

* fix(ci): bind iOS screenshot shard evidence

* fix(ci): preserve screenshot capture attempts

* fix(ci): align screenshot shards with Xcode 26.6

* fix(ci): provision screenshot shard Fastlane

* fix(ci): normalize Fastlane provenance version

* fix(ci): select installed Fastlane version
2026-08-24 16:59:06 -07:00
Vitor Cepeda Lopes b71a09fd8a fix(macos): return paired-node Codex catalogs without native supervision (#126811)
* fix(macos): route Codex catalog to plugin worker

* fix(macos): freeze Codex catalog ownership per invoke

---------

Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
2026-08-24 16:24:27 -07:00
ClawSweeper a5b5920444 feat(ui): configure capabilities before session start [AI-assisted] (#128081)
* feat(ui): configure capabilities before session start

Reuse the active-chat Plus menu on new sessions, move Draft into it, and persist admin-scoped tool overrides before the initial turn. Closes #128079.

* test(ui): follow new-session Draft menu

* refactor(ui): reconcile new-session capability ownership

* fix(ui): gate terminal launch on capability overrides

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-24 11:47:12 -07:00
Vincent Koc 88f417d328 fix(ci): pin iOS Fastlane toolchain (#128735)
* fix(ci): pin iOS Fastlane toolchain

* fix(ci): enforce locked iOS Fastlane path

* fix(ci): route iOS docs through bundle

* fix(ci): pin all documented iOS Fastlane commands

* fix(ci): make iOS bundle selection canonical

* fix(ci): enforce the locked iOS Fastlane path

* fix(ci): pin Bundler in iOS wrapper

* fix(ci): require the iOS Fastlane Gemfile

* fix(docs): pin direct iOS Fastlane bundle
2026-08-24 11:45:05 -07:00
Peter Steinberger 053b89d80f improve(ui): open short session links without extra lookup (#128778)
* perf(ui): remove short session route waterfall

* docs: clarify short link gateway requirement
2026-08-24 09:33:20 -07:00
openclaw-mantis[bot] 61bc753da3 chore(i18n): refresh native locales (#128759)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-24 08:21:09 -07:00
Peter Steinberger 2b8fe12f0b fix(apple): surface rejected chat session settings (#128737) 2026-08-24 06:49:50 -07:00
Kaneki ca3c3db1af fix(android): preserve capture dates and requested photo resolution (#125550)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-24 06:39:43 -07:00
Peter Steinberger b145e25fea fix(ui): resume session starts after Gateway reconnects (#128661)
* fix(ui): resume session creation after reconnects

* improve(ui): remove redundant appearance reset buttons

* fix(ui): align session protocol and appearance validation

* fix(ui): retain promoted placement session ownership

* fix(gateway): isolate session creation capacity by owner

* test(ui): stabilize hovercard bridge pointer movement
2026-08-24 06:36:51 -07:00
WhatsSkiLL fb576e3518 feat(android): group sidebar sessions (#128092)
* fix(android): group drawer sessions

* fix(android): isolate generated locale files

* fix(android): hide empty sidebar groups

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
2026-08-24 06:34:42 -07:00
Peter Steinberger 0fbb5dd00e fix(android): normalize optional motion date ranges (#128734) 2026-08-24 06:29:54 -07:00
Peter Steinberger 898b1ce4b3 fix(android): fence canceled voice-note permission callbacks (#128733) 2026-08-24 06:23:17 -07:00
Peter Steinberger 99e5eaea77 fix(ios): report unavailable when network observation times out (#128724) 2026-08-24 06:08:12 -07:00
Peter Steinberger f90a9c720e fix(android): gateway accent color is fetched but never applied to the app theme (#128702)
* fix(android): apply the gateway accent color to the Claw design theme

The Android app fetched config.ui.seamColor into a StateFlow that no
Compose surface consumed, so gateway accents were silently dropped. The
accent now resolves with Control UI precedence (ui.prefs.accent over
ui.seamColor) and overrides the Claw accent/accentSoft/accentBorder
tokens in ShellScreen and OnboardingFlow; Material You system chrome is
untouched. With no gateway accent set the hardcoded ClawDark/ClawLight
palettes apply unchanged, replacing two mismatched hardcoded defaults.

* fix(android): invoke branding refresh on connect and match gateway accent precedence

ClawSweeper findings: refreshBrandingFromGateway had no call site (the
accent state stayed null), and a present non-string user accent must not
fall through to seamColor per the gateway's nullish selection. The
refresh now runs in the post-connection coroutine alongside wake-word
and exec-approval refreshes.
2026-08-24 05:42:56 -07:00
Peter Steinberger 33b10fe4aa fix(macos): user accent from Control UI is clobbered by config snapshots and never live-updates the chat window (#128703)
* fix(macos): honor user accent precedence in config snapshot and live-update chat window

The Control UI user accent (ui.prefs.accent) landed in #128432/#128577 with
precedence user accent -> operator ui.seamColor -> theme default, and the
gateway's talk.config payload already applies it. The macOS app had two gaps:

- ChannelsStore.applyUIConfig read raw ui.seamColor from the config.get
  snapshot and clobbered the user accent set from talk.config depending on
  arrival order. It now resolves ui.prefs.accent ?? ui.seamColor via a
  testable helper mirroring the gateway precedence.
- The native chat window read AppStateStore.seamColorHex once at window
  construction, so accent changes never live-updated. MacChatSurface now
  reads the @Observable store in body, deleting the one-shot userAccent
  plumbing.

Docs: configuration-reference.md documents the precedence for native-app
chrome. Regression test fails pre-fix (snapshot returned the operator seam
color instead of the user accent).

* fix(macos): refresh config from gateway config.changed events

Addresses the review finding that no macOS consumer turned the gateway's
hash-only config.changed broadcast into refreshed shared state, so a
Control UI accent change never reached an open native chat window while
the app ran. ChannelsStore now subscribes to gateway pushes and re-fetches
config.get on config.changed, reconnect snapshots, and sequence gaps.

The refresh applies non-force so an in-progress local settings draft wins
(the gateway rejects stale-hash writes anyway). The in-flight reload queue
gains a closed pending level (none/refresh/force) so a refresh arriving
during a load is coalesced instead of dropped, and a requeued refresh
cannot clobber a dirty draft the way the old boolean force-pending did.
2026-08-24 05:37:59 -07:00
Peter Steinberger 234df15a6d chore: refresh dependencies after seven-day cooldown (#128414)
* build(deps): refresh dependencies after cooldown

Apply dependency, toolchain, action, image, and exact tool updates released by the inclusive 2026-08-16 seven-day cutoff. Adapt owner boundaries for the resulting CUA, logging, Teams, Markdown, native, and test-harness contract changes while retaining versions blocked by upstream compatibility constraints.

* fix(ui): align markdown renderer env typing

* fix(deps): align postcss and mistral peer contracts

* fix(deps): repair refreshed dependency contracts

* fix(deps): retain tslog startup budget

* fix(ci): verify Android tools with SHA-256

* fix(ci): fence Android SDK cache version
2026-08-24 03:01:54 -07:00
Peter Steinberger 0155d95524 feat(ios): adopt gateway user accent in chat (#128599)
* feat(ios): adopt gateway user accent in chat

The iOS chat surface previously always used the hardcoded brand accent.
Read ui.prefs.accent ?? ui.seamColor (the Control UI user-accent
contract) from the existing config.get branding refresh and feed it to
the shared chat kit's userAccent seam, matching the macOS chat window.
Invalid values fall through; accent resets on gateway switch.

* fix(ios): contrast-aware accent ink and live config.changed refresh

Address ClawSweeper review findings: the shared chat kit now derives
user-text/send-glyph ink from the accent via the Control UI WCAG rule
(relative luminance > 0.179 -> black), fixing unreadable light accents
on iOS and macOS alike; the iOS server-event switch routes
config.changed through the guarded branding refresh so an accent
change reaches a connected app without reconnect.
2026-08-24 02:46:06 -07:00
Peter Steinberger e834b355f2 fix(android): prevent expired subagent tasks from reappearing (#128612)
* fix(android): prevent expired subagent tasks from reappearing

Co-authored-by: 李琪0668001400 <li.qi16@xydigit.com>

* test(android): format subagent lifecycle assertions

* style(android): separate subagent lifecycle invariant comment

---------

Co-authored-by: 李琪0668001400 <li.qi16@xydigit.com>
2026-08-24 02:14:51 -07:00
Peter Steinberger f6aa7c24f1 fix(linux): truthful install failures, post-install repair, reachable reinstall (#128614)
The Linux desktop companion could complete a CLI install and still claim
'Installation did not finish' with circular update advice, discarding the
real failure. Verified end-to-end in a clean Ubuntu VM across all three
release channels:

- cli.rs: failed CLI commands now surface their stderr tail (deduped, last
  12 lines) instead of being mislabeled as JSON parse failures.
- gateway.rs: missing dashboard --json support maps to an honest curated
  message pointing at Beta/Development channels, not a circular npm-update
  hint.
- main.rs: run 'doctor --fix --non-interactive' right after install so the
  CLI repairs config/state before Gateway readiness checks; wrap
  post-install failures as 'installed, but connecting failed: <reason>'.
- installer.rs: keep structured step events out of the prose failure tail.
- ui/main.js: humanize streamed install steps, render real errors on the
  failure screen, and always offer Reinstall from connection failures.
- scripts/install-cli.sh: service refresh uses 'gateway status --json' with
  the bundled node runtime, corepack failure falls back to npm, dev channel
  clones with --filter=blob:none.
2026-08-24 02:01:15 -07:00
Peter Steinberger 554fb212c9 fix(nodes): report camera positions the hardware actually reached (#128595)
* fix(nodes): report camera positions the hardware actually reached

`camera.ptz.control` returned a position it never verified, and
`camera.snap`/`camera.clip` could capture from a camera the caller did
not ask for. Both told the agent an action succeeded when it had not.

PTZ read its post-write status from the same UVC connection that issued
the write. Gimbal cameras echo a pending setpoint back on the writing
connection, so the check confirmed its own write. Those cameras also
service camera-terminal controls only while a video stream is active, and
no capture session was held, so writes could be discarded entirely while
reads returned phantom values.

Hold a frame-discarding capture session across every PTZ operation, close
the writing controller, and verify through a fresh connection against each
axis's advertised resolution. An axis that misses now reports through the
existing CAMERA_PTZ_PARTIAL outcome with observed versus requested values
and what to check next.

Apple camera selection accepted an explicit deviceId and silently fell
back to the default camera when nothing matched. Linux already rejected
this, and CameraPTZService already rejected it in the same app. Centralize
exact selection in OpenClawKit so macOS and iOS both fail with a
device-not-found error; the facing/default fallback stays only for
requests that supply no deviceId.

camera.ptz.status now activates the camera and its privacy indicator for
the duration of the read. That is the cost of returning real positions.

* fix(nodes): tell callers how to recover from an unknown camera ID

Device IDs change when cameras are reconnected, so a bare
device-not-found error dead-ends the caller. Both Apple errors and the
docs now point at camera.list for current IDs.

Addresses the ClawSweeper P2 finding on #128595.
2026-08-24 01:56:12 -07:00
Milton 9b2b195e10 fix(android): enforce location freshness across live updates (#128439)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-24 01:37:06 -07:00
Peter Steinberger 53dcaaedec feat(gateway): generic operator roles for non-maintainer access (#128548)
* feat(gateway): generic operator roles for non-maintainer access

Adds gateway.roles: named role bundles over a closed capability set —
sessions.others (none/view/suggest/write), an agents allowlist, and an
operator-scope ceiling. Roles are person-level (additive user_profiles.role
column, SQLite stays at v9); users.setRole (admin-only) assigns them. With
no gateway.roles config, behavior is unchanged for solo deployments.

Enforcement is deny-by-default from a host-minted actor identity
(system vs operator+profileId on server-only client.internal, never
accepted from the wire) and covers every entry point: WS RPCs, OpenAI-compat
and Responses HTTP, tools invocation, cron, questions, usage, task
suggestions, session catalog/sharing/reads. The agents allowlist gates both
session creation and run-start on existing sessions. Subagent completion
announce and descendant wake mint explicit system authority so role
boundaries never silently drop parent notifications.

The enforcement surface is expressed through a narrow policy vocabulary
(operatorSessionCap, hasOperatorBoundary, authorizeSessionSharing) rather
than per-handler policy internals.

* fix(gateway): heal PR CI after rebase onto main

- Break import cycles: extract GatewayOperatorRoleActor leaf contract; merge
  session-group-mutation-targets into session-sharing-target-input.
- Split sessions-suggestions.test.ts (max-lines) into a visibility suite.
- Add users.setRole to the 2026.8 train registry test and regenerate the
  Kotlin protocol client.
- Startup UNAVAILABLE gating now precedes session authorization: session
  stores are not loaded during startup, so authorization reads would deny
  with a misleading non-retryable error.
- sessions.assignOwner keeps its documented visibility-authorized contract
  when no operator role caps the caller; view/suggest-capped roles still
  cannot reassign foreign session ownership.
- Test stubs updated for main's socket readyState guard (#128144) and the
  system-authority arg on channel-native resets.

* test(gateway): chat.send pending-profile dispatch carries its required session target

chat.send requires a non-empty sessionKey at the protocol level; the mutation
pipeline now rejects targetless frames before profile-dependent dispatch, so
the pending-profile test must send a realistic frame.
2026-08-24 01:20:03 -07:00
clawSean af384662f7 fix(ios): keep tool details visible in dark mode (#124021) 2026-08-24 01:05:45 -07:00
Peter Steinberger 6530948812 fix(location): reject future-dated cached fixes (#128591) 2026-08-24 00:57:04 -07:00
Kaneki 444d79aea3 fix(android): normalize null calendar and contact write fields (#125527)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: 涧波 <jianbo@digitallifes.org>
2026-08-24 00:33:37 -07:00
hidenori-endo 10050cb07e fix(android): preserve channel sender labels across chat history (#119864)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-24 00:24:43 -07:00
xingzhou 446c8c131a fix(ios): device status leaves battery monitoring enabled (#128174)
* fix(ios): restore battery monitoring after device status

* fix(ios): preserve native battery monitoring ownership

* test(ios): make battery ownership regression deterministic

* fix(ios): avoid Swift Testing key-path inference failure
2026-08-23 23:12:34 -07:00
Peter Steinberger 6178409d9a fix(dashboard): preserve widget content ownership (#128489) 2026-08-23 21:53:39 -07:00
Peter Steinberger 0978d55b05 feat(nodes): automatic device placement for sessions.dispatch (#128421)
* feat(nodes): automatic device placement for sessions.dispatch

sessions.dispatch gains autoDevice: true — the gateway selects the eligible
session-host node with the most available worker slots (deterministic
tie-break), retries up to three candidates when a node churns at the
pre-provisioning eligibility fence, and reports the chosen device in the
placement runner projection. Control UI offers Any available node with
actionable disabled reasons. No-eligible-host failures state why.

* fix(ui): break draft-place-state/draft-session-placement import cycle

resolveDraftSessionPlacement only needs four scalar fields; a structural
param type replaces the Pick<DraftPlaceState,...> import that created the
madge cycle.

* fix(ui): keep the devices section hidden when no devices are paired

The Any available node row lives inside the Your devices section; rendering
it with zero paired devices resurrected the section on gateway-only setups.
Gate it on device presence — Connect a machine remains the discoverability
path — and cover both the empty and non-hostable cases.

* fix(gateway): project dispatch runner state through the canonical reader

The dispatch reply no longer synthesizes an available device runner; it uses
the fenced workerPlacementRunnerAvailabilityReader (and disk-space reader)
exactly like session reads, so a node lost after durable provisioning
projects offline consistently. Documents placement.runner.deviceId in the
protocol reference.
2026-08-23 21:08:33 -07:00
Peter Steinberger 9284e23cdd feat(control-ui): show client IP and time zone on the activity identity card (#128438)
* feat(control-ui): show client IP and time zone on the activity identity card

The Activity identity card showed only host and platform, so an operator
looking at a teammate could not tell where that person was connecting from.
Presence already carried a best-effort `ip`, and it was simply not rendered.

Add the client's self-reported IANA time zone to the connect handshake and
presence entry, and render both `ip` and `timeZone` on the device row. The
time zone matters because the connecting address is frequently unusable for
location: connect handling omits `ip` for loopback clients, and tunneled or
Tailscale clients land in private/CGNAT ranges. A browser knows its own zone
regardless of how it reached the gateway.

Both protocol additions are optional fields, so no version bump is needed.

* build(protocol): regenerate Swift models for presence timeZone
2026-08-23 20:07:06 -07:00
Peter Steinberger bb6e4b1dee fix(apps): prevent stale Now Playing after ownership changes (#128381) 2026-08-23 15:20:21 -07:00