Commit Graph

3718 Commits

Author SHA1 Message Date
Ben.Li
b170c08e6d fix(ios): reject loopback-prefix hosts for auth retry (#99859)
* fix(ios): require parsed loopback hosts for auth retry

* fix(ios): narrow device token retry loopback trust

* test(ios): cover trusted auth retry hosts

* docs(changelog): position iOS auth retry fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 02:05:21 +01:00
Peter Steinberger
5d8293c1fe feat(ios): read-only offline cache for chat sessions and transcripts (#100219)
* feat(ios): read-only offline cache for chat sessions and transcripts

Cache-first cold open for the iOS chat tab: the last known transcript and
session list render immediately from a local SQLite cache, then live gateway
history replaces them wholesale through the existing reconciliation path.
When the gateway is unreachable, recent sessions and transcripts stay
browsable read-only; sending remains gated by the existing connection state.

- New OpenClawChatTranscriptCache protocol seam plus SQLite-backed store in
  OpenClawChatUI (raw SQLite3, no new dependencies), scoped per gateway
  stableID so transcripts never leak across paired gateways.
- Bounds: 50 sessions, 50 transcripts, 200 messages per session; text rows
  only (attachment/binary payloads and tool arguments are stripped).
- Disposable cache: schema versioned via user_version; any open/schema/decode
  mismatch drops and rebuilds silently. File protection
  completeUntilFirstUserAuthentication on iOS.
- View model pre-paints from cache only until a live response applies
  (hasAppliedLiveHistory/hasAppliedLiveSessions guards); write-through is
  chained and off the render path.
- iOS wiring keys the chat view model identity on transport mode plus cache
  gateway ID so switching paired gateways rebuilds the view model.

Part of #100194

* fix(ios): harden offline transcript cache

* fix(ios): expose offline cached sessions

* fix(ios): isolate transcript caches by gateway

* chore(i18n): sync native inventory

* fix(ios): allow cache extension to replace messages
2026-07-06 01:02:15 +01:00
qingminlong
6a62a04f59 fix(android): synchronize realtime tool completions (#100049)
* fix(android): synchronize realtime tool completions

* refactor(android): unify realtime tool completion state

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 00:49:21 +01:00
Peter Steinberger
5c3e938e70 feat(android): syntax-highlighted code blocks in chat (#100217)
* feat(android): syntax-highlight fenced code blocks in chat markdown

* fix(android): handle escaped triple quotes in highlighting

* docs(changelog): note Android code highlighting

* docs(changelog): keep Android highlighting unreleased

* chore(android): sync native i18n inventory
2026-07-06 00:27:40 +01:00
Peter Steinberger
65aec96440 fix(ios): simplify development app name (#100466) 2026-07-06 00:22:14 +01:00
Peter Steinberger
aaf5ab910c fix: land ten small reliability fixes (#100483)
* fix(agents): harden LSP process failures

Source: #100450

Co-authored-by: morluto <williamlin1327@gmail.com>

* fix(sandbox): report effective workspace layout

Sources: #100435, #100439

Co-authored-by: Aniruddha Adak <aniruddhaadak80@users.noreply.github.com>

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

* fix(security): fail install checks on stream errors

Source: #100413

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(android): normalize all-day calendar events

Source: #100032

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>

* fix(ios): serialize push-to-talk lifecycle

Source: #99942

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>

* fix(talk): reject inherited provider names

Source: #99849

Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>

* fix(android): stop voice capture in background

Source: #99840

Co-authored-by: xialonglee <li.xialong@xydigit.com>

* fix(cron): preserve fallback result classification

Source: #99913

Co-authored-by: jincheng-xydt <xu.jincheng@xydigit.com>

* fix(google): bound Vertex response decompression

Source: #99812

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>

* fix(plugins): report malformed discovery JSON

Source: #99892

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* test(sandbox): configure non-default workspace fixture

* test: fix small-fix batch validation

---------

Co-authored-by: morluto <williamlin1327@gmail.com>
Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>
Co-authored-by: xialonglee <li.xialong@xydigit.com>
Co-authored-by: jincheng-xydt <xu.jincheng@xydigit.com>
Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>
2026-07-06 00:08:51 +01:00
Peter Steinberger
655b18c706 fix(macos): dashboard window keeps a dead SSH tunnel port after tunnel restart (#100488)
* fix(macos): follow gateway endpoint changes in the open Dashboard window

In remote SSH mode the Dashboard window baked the forwarded tunnel's
local port into the WebView URL and injected auth at open time; when
RemoteTunnelManager recreated the tunnel on a new ephemeral port the
open window reconnected to the dead port forever. DashboardManager now
subscribes to GatewayEndpointStore and, while the window is open,
re-injects auth for the new origin and reloads the WebView without
stealing focus. Dashboard log lines now strip the #token= fragment so
endpoint changes never write credentials to unified logs.

Fixes #100476

* test(macos): drop stale hasCrestodianSetupAuth assertions

OnboardingView.hasCrestodianSetupAuth was removed with the replaced
OnboardingView+CrestodianSetup source in #100288, leaving the macOS
test target failing to compile on main. Delete the test for the
removed internal helper.
2026-07-06 00:06:43 +01:00
Peter Steinberger
37c67b0d27 fix(macos): reduce idle CPU wakeups (#100463)
* fix(macos): reduce idle CPU wakeups

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory

* chore(macos): sync native i18n inventory
2026-07-05 23:35:50 +01:00
WhatsSkiLL
978b425f98 fix(android): stabilize shell navigation layout (#100382)
* fix(android): stabilize shell navigation layout

* fix(android): target active shell navigation layout

* fix(android): initialize chat cache from preference owner

* chore(android): sync native i18n inventory

* chore(android): sync native i18n inventory

---------

Co-authored-by: IWhatsskill <IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 23:03:30 +01:00
github-actions[bot]
45f561ab6c chore(i18n): refresh native locales 2026-07-05 21:41:36 +00:00
Peter Steinberger
a4b032e5d7 fix: harden subprocess, maintenance, and output paths (#100440)
* fix(agents): contain exec output stream failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(tui): contain local shell stream failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(process): contain command output stream failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(skills): isolate remote bin refresh failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(agents): contain background subagent sweep failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(skills): report directory scan failures

Co-authored-by: wendy-chsy <wan.wenyan@xydigit.com>

* fix(agents): classify plugin approval gateway failures

Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>

* fix(exec): preserve sanitized control-byte evidence

Co-authored-by: Lavya Tandel <lavya@loom.local>

* fix(shared): unwrap standalone parameter tags

Co-authored-by: nankingjing <1079826437@qq.com>

* fix(android): fail shared capture on audio read errors

Co-authored-by: NianJiuZst <3235467914@qq.com>

* docs(changelog): record small bugfix sweep

* fix(output): preserve sanitizer boundary semantics

* test: align sanitizer and sweeper regressions

* fix(terminal): preserve text after lone C1 controls

---------

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: wendy-chsy <wan.wenyan@xydigit.com>
Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>
Co-authored-by: Lavya Tandel <lavya@loom.local>
Co-authored-by: nankingjing <1079826437@qq.com>
Co-authored-by: NianJiuZst <3235467914@qq.com>
2026-07-05 22:21:54 +01:00
Peter Steinberger
8c19dbfb62 feat(ios): export chat transcripts as Markdown via the share sheet (#100417)
* feat(ios): export chat transcripts as Markdown via the share sheet

* chore(ios): sync native i18n inventory
2026-07-05 22:14:44 +01:00
github-actions[bot]
660d752b34 chore(i18n): refresh native locales 2026-07-05 21:05:06 +00:00
Peter Steinberger
77575d74f6 feat(android): add durable offline command outbox for chat sends (#100290) 2026-07-05 21:45:36 +01:00
Peter Steinberger
bf156386aa feat(chat-ui): structured haptic feedback for chat events (#100416) 2026-07-05 21:42:44 +01:00
Peter Steinberger
09f9a85145 feat(android): read-only offline cache for chat sessions and transcripts (#100227)
* feat(android): add read-only offline cache for chat sessions and transcripts

Cache-first cold open plus offline browsing of the session list and cached
transcripts. Room DB (KSP) scoped by stable gateway identity, bounded to
50 sessions / 200 text-only messages per session with eviction on write,
destructive migrations only. Live chat.history/sessions.list responses
replace cached rows wholesale via the existing generation-tracked
reconciliation path; sending stays behind the existing health gate.
Pairing/auth resets and gateway-side session deletes purge cached rows.

Part of #100194

* chore(android): sync native i18n inventory

* fix(android): bind transcript cache writes to gateway scope

* docs(changelog): note Android offline chat cache

* chore(android): refresh native i18n inventory

* docs(changelog): keep Android offline cache unreleased

* docs(changelog): drop PR-carried entry; release generation owns CHANGELOG
2026-07-05 21:14:46 +01:00
github-actions[bot]
ae65251fdf chore(i18n): refresh native locales 2026-07-05 19:52:02 +00:00
PollyBot13
a320f775f0 fix(ios): defer QR pairing after scanner dismissal (#99572)
* fix(ios): defer QR pairing after scanner dismissal

* fix(ios): process QR pairing after scanner dismissal

* fix(ios): harden QR scanner handoff

* fix(ios): give QR scanner dismissal more time

* fix(ios): keep onboarding open for QR trust prompt

* fix(ios): keep QR trust prompt owned by onboarding

* fix(ios): recover operator pairing after QR bootstrap

* fix(ios): cancel stale QR scanner handoffs

Co-authored-by: PollyBot13 <pollybot13@gmail.com>

* fix(ios): defer QR setup until onboarding closes

* fix(ios): keep QR setup links with visible settings

* fix(ios): consume setup links during onboarding

* fix(ios): handle setup links during onboarding launch

* fix(ios): route setup links through active onboarding

* fix(ios): harden QR gateway handoff

* fix(ios): cancel superseded gateway attempts

* fix(ios): serialize scanner result delivery

* fix(ios): prevent stale gateway reconnects

* fix(ios): serialize gateway target handoff

* fix(ios): disable stale gateway relaunch route

* fix(ios): await staged bootstrap reset

* test(ios): bound gateway reset handoff

* fix(ios): preserve explicit gateway handoff

* fix(ios): harden gateway lifecycle ownership

* chore(ios): sync native i18n inventory

* test(ios): align gateway ownership assertions

* refactor(ios): remove superseded gateway helpers

* fix(ios): keep gateway auth route scoped

* fix(ios): restore gateway target review state

* fix(protocol): refresh Swift plugin approval model

* test(ios): isolate state directory overrides

* fix(ios): preserve watch alerts across gateway switches

* fix(ios): bind deferred work to gateway ownership

* docs(changelog): credit iOS gateway handoff fix

* chore(i18n): sync native app inventory

* test(ios): remove unused Watch approval hooks

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 12:31:53 -07:00
Peter Steinberger
f1641571f1 feat(android): restore in-flight runs after reconnect (#100384)
Consume the gateway's canonical reconnect snapshot (chat.history inFlightRun)
to re-adopt still-streaming runs after reconnect, cold start, and seq-gap
recovery in the Android ChatController. Mirrors the iOS contract from #100277.
Part of #100197.
2026-07-05 12:30:02 -07:00
Peter Steinberger
1833c0d771 test(ios): add deterministic streaming replay harness for shared chat pipeline (#100201) 2026-07-05 12:27:57 -07:00
Peter Steinberger
c730d8f1f1 feat(logbook): automatic work journal plugin with Control UI timeline tab (#99930)
* feat(logbook): automatic work journal plugin with a plugin-contributed Control UI tab

Squash of PR #99930 work for rebase onto the Control UI route refactor:
- extensions/logbook: Dayflow-style capture -> observations -> timeline cards
  pipeline with SQLite store, node capture commands, standup/ask, retention
- plugin SDK/gateway seam: surface "tab" Control UI descriptors projected
  into hello-ok controlUiTabs (scope-filtered, deterministic order)
- Control UI: dynamic plugin tabs with bundled Logbook view
- docs, tests, labeler wiring

* feat(ui): port plugin tabs and Logbook to the route-owned Control UI architecture

- shared /plugin route carries the tab id in the query (?id=<tab>), matching
  the router's exact-path contract
- openclaw-plugin-page renders bundled views (Logbook), sandboxed plugin
  frames (descriptor path), or the unavailable card
- sidebar renders hello controlUiTabs after each group's static routes
- Logbook view/controller live under ui/src/pages/plugin/

* fix(ui): namespace plugin tabs by pluginId to prevent cross-plugin tab id collisions

* fix(logbook): prefer app capture nodes and rotate off failing nodes

* fix(plugins): reject protocol-relative Control UI tab paths

* fix(logbook): harden automatic journal

* docs(changelog): remove maintainer self-credit

* chore(ui): refresh locale metadata after rebase

* fix(logbook): preserve analysis window boundaries

* fix(logbook): align status privacy and timezone

* fix(ui): stop hidden plugin tab polling
2026-07-05 11:50:44 -07:00
Peter Steinberger
3f380635f5 feat(chat-ui): syntax-highlighted code blocks and native tables in chat markdown (#100207)
* feat(chat-ui): syntax-highlighted code blocks and native GFM tables in shared chat markdown (#100195)

* chore(chat-ui): sync native i18n inventory

* fix(chat-ui): harden native markdown rendering

* refactor(chat-ui): split HTML block patterns

* refactor(chat-ui): parse markdown blocks with swift-markdown

* style(chat-ui): satisfy SwiftFormat lint

* fix(ios): bundle markdown dependency licenses

* style(ios): normalize markdown license file

* fix(ios): keep native markdown cards legible
2026-07-05 11:38:05 -07:00
Peter Steinberger
b22c36f112 fix: land ten small reliability fixes (#100399)
* fix(cron): reject sub-millisecond durations

* fix(skill-workshop): preserve proposal terminal newline

Preserve proposal_content exactly at the agent tool boundary and make
renderProposalMarkdown defensively emit a terminal newline.

Add focused regressions for the tool write path and markdown renderer.

* fix(skill-workshop): reject blank raw proposal content

* fix: treat empty-string optional integer tool params as unset

Optional positive-integer tool params (e.g. Telegram replyTo/threadId)
threw ToolInputError when a tool-calling model populated them with an
empty-string or whitespace-only default. Those defaults carry no value,
so readPositiveIntegerParam/readNonNegativeIntegerParam now treat a
blank string as unset (undefined) instead of throwing, while still
rejecting genuinely invalid present values (0, "42.5", "-3"). This
prevents silent message-delivery failures when models emit empty
routing-param defaults. Adds unit tests covering blank vs invalid.

* fix(gateway): log start session persistence failures

The gateway session-lifecycle "start" event persistence
(persistGatewaySessionLifecycleEvent, which surfaces write failures via
requireWriteSuccess) was fired as void ...catch(() => undefined), swallowing
the rejection with zero logging. A failed start-marker write silently dropped
the run's start record from restart-recovery accounting, with no
operator-visible trace.

The sibling terminal-phase catch already logs this since #97839; the start
path was the unfixed sibling. Mirror that fix: log the swallowed start-phase
persistence failure with the same redacted message shape via formatForLog,
keeping the fire-and-forget semantics unchanged. Adds a focused regression
test asserting the log fires on start-persist rejection.

* fix(memory): report close-time pending work failures

* fix(shared): return "" from sliceUtf16Safe when end <= start, matching native .slice

sliceUtf16Safe silently swapped reversed bounds (to < from) instead of
returning "" like String.prototype.slice, creating a subtle footgun for
callers with dynamic start/end pairs.

Caller scan across src/, extensions/, and packages/ confirmed no production
code relies on the old swap behavior — all callers use (text, 0, N) or
(text, -N) forms only.

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

* fix(plugins): require plugin manifest in npm verifier

* fix(android): propagate CancellationException in CameraHandler catch blocks

Catch (err: Throwable) swallows kotlinx.coroutines.CancellationException,
breaking structured concurrency when the coroutine scope is cancelled
during camera operations (handleList/handleSnap/handleClip).

Add CancellationException rethrow before each Throwable catch to match
the existing pattern used in GatewaySession and TalkModeManager.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(android): propagate CancellationException past GatewaySession invoke boundary

* chore: sync native i18n inventory after gateway session line shift

* fix(agents): prevent native hook relay bridge race condition on renew and registration

Remove synchronous bridge record write after server.listen() that races
before the TCP server binds, and guard renew handler with server.listening
check to prevent stale relay registrations.

Closes #98650

* fix: harden small reliability fixes

Co-authored-by: cxbAsDev <cxbAsDev@users.noreply.github.com>

* docs(agents): explain buffered LSP spawn failures

* docs(agents): clarify LSP spawn timeout invariant

---------

Co-authored-by: qingminlong <qing.minlong@xydigit.com>
Co-authored-by: anyech <anyech@gmail.com>
Co-authored-by: snotty <snotty@users.noreply.github.com>
Co-authored-by: masatohoshino <g515hoshino@gmail.com>
Co-authored-by: lin-hongkuan <lin-hongkuan@users.noreply.github.com>
Co-authored-by: simon-w <weng.qimeng@xydigit.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: 宇宙熊Yzx <53250620+849261680@users.noreply.github.com>
Co-authored-by: xialonglee <li.xialong@xydigit.com>
Co-authored-by: nankingjing <1079826437@qq.com>
Co-authored-by: cxbAsDev <cxbAsDev@users.noreply.github.com>
2026-07-05 11:12:55 -07:00
Peter Steinberger
444d54c538 fix(ios): avoid inactive Voice Wake audio startup (#100370)
* fix(ios): avoid inactive voice wake audio startup

* fix(ios): avoid inactive voice wake audio startup

* fix(ios): avoid inactive voice wake audio startup
2026-07-05 09:58:28 -07:00
Peter Steinberger
70f2bef6b4 fix(ios): persist queued Watch replies (#100372)
* fix(ios): persist queued watch replies

Route Apple Watch quick replies through the durable, gateway-scoped Watch message outbox with restart-safe routing and deduplication.

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>

* fix(ios): preserve pre-upgrade Watch replies

Bind shipped notification prompts without routing metadata to the current Gateway once, while keeping explicit and persisted Gateway owners fail-closed.

---------

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
2026-07-05 09:14:49 -07:00
Peter Steinberger
f607ba0691 feat(control-ui): session grouping with drag & drop and channel categorization (#100262)
* feat(control-ui): session grouping with drag & drop and channel categorization

* fix(control-ui): restrict session drag&drop to private session-key payloads

* chore(i18n): translate session grouping strings across control ui locales

* chore(protocol): regenerate swift gateway models for session category

* chore(protocol): regenerate swift gateway models for session category
2026-07-05 09:13:17 -07:00
Peter Steinberger
535ad8a0c3 test(ios): import pairing protocol model (#100355)
* test(ios): import pairing protocol model

* test(ios): import pairing protocol model
2026-07-05 08:49:34 -07:00
Jason
95ebb3dc1e fix(tui): surface safe tool-validation abort diagnostics (#91002)
* fix(tui): show last tool-error summary on aborted runs

When a run ends while looping on tool-call validation errors the TUI showed
only "run aborted". Carry the last tool failure on the terminal lifecycle
metadata and render a sanitized one-line summary on the abort line, e.g.
"run aborted: edit tool validation failed: edits: must have required properties edits".
Argument dumps are stripped; with no summary it stays "run aborted".

Refs #90982

* fix(tui): secure abort validation diagnostics

* docs(changelog): move TUI fix to unreleased

* docs(changelog): aggregate TUI fixes

* fix(tui): scope abort validation diagnostics

* docs(changelog): restore unreleased spacing

* fix(tui): scope abort validation diagnostics

* fix(tui): scope abort validation diagnostics

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 08:30:20 -07:00
Peter Steinberger
862de9f1a1 fix(pairing): advertise reachable Tailnet routes (#100317)
* fix(pairing): advertise reachable tailnet routes

* fix(pairing): satisfy native and SDK checks

* fix(ios): cancel stale pairing route probes

* test(pairing): document LAN-only Serve fallback

* fix(ios): preserve pairing result initializer
2026-07-05 07:43:43 -07:00
github-actions[bot]
f0ecc16629 chore(i18n): refresh native locales 2026-07-05 14:22:16 +00:00
Peter Steinberger
2bc50d0656 feat: verify AI access during macOS onboarding before the first chat (#100288)
* feat(crestodian): add live-tested structured inference setup (detect/activate gateway RPCs)

* feat(macos): redesign onboarding around a verified Connect-your-AI step

* docs: describe the verified AI onboarding step and gemini setup ladder entry

* chore(macos): drop replaced OnboardingView+CrestodianSetup source

* fix(macos): keep the AI-detect error card from pairing with an unproven empty-state claim

* chore(protocol): regenerate Swift gateway models for crestodian.setup methods

* test(crestodian): give setup-inference mocks explicit params for test-types lane

* chore(i18n): sync native app string inventory for onboarding redesign

* chore(i18n): sync native app string inventory for onboarding redesign
2026-07-05 06:59:30 -07:00
Peter Steinberger
245092dc3a feat(ios): add Apple Watch voice turns (#100283)
* feat(ios): add Apple Watch voice turns

* chore(ios): sync native i18n inventory

* fix(ios): preserve Watch message label
2026-07-05 06:40:03 -07:00
Peter Steinberger
9ba14b80ab fix(ios): own gateway setup deep-link delivery (#100328) 2026-07-05 06:01:15 -07:00
Peter Steinberger
deac98eb72 fix: harden small runtime and installer edge cases (#100258)
* fix(media): preserve dollar sequences in transcript echoes

Co-authored-by: uditDewan <udit.dewan21@gmail.com>

* fix(mcp): catch rejected gateway event handlers

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(auto-reply): support punctuated silent token prefixes

Co-authored-by: simon-w <weng.qimeng@xydigit.com>

* fix(discord): keep voice log previews UTF-16 safe

Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>

* fix(clawrouter): bound usage response reads

Co-authored-by: 杨浩宇0668001029 <yang.haoyu@xydigit.com>

* fix(browser): bound CDP JSON response reads

Co-authored-by: hailory <hailory@xydigit.com>

* fix(status): include current time in session status

Co-authored-by: connermo <conner.mo@gmail.com>

* fix(installer): require Arch detection before pacman

Co-authored-by: Iliya Abolghasemi <gfaerny@gmail.com>

* fix(apps): default TLS gateway deep links to port 443

Co-authored-by: ben.li <li.yang6@xydigit.com>

* fix(infra): keep Undici terminated exceptions nonfatal

Co-authored-by: harjoth <harjoth.khara@gmail.com>

* fix(auto-reply): avoid Unicode-unsafe token spread

---------

Co-authored-by: uditDewan <udit.dewan21@gmail.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: simon-w <weng.qimeng@xydigit.com>
Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>
Co-authored-by: 杨浩宇0668001029 <yang.haoyu@xydigit.com>
Co-authored-by: hailory <hailory@xydigit.com>
Co-authored-by: connermo <conner.mo@gmail.com>
Co-authored-by: Iliya Abolghasemi <gfaerny@gmail.com>
Co-authored-by: ben.li <li.yang6@xydigit.com>
Co-authored-by: harjoth <harjoth.khara@gmail.com>
2026-07-05 05:33:11 -07:00
Peter Steinberger
1403c64799 fix(protocol): regenerate Swift gateway models for approvalReviewerDeviceIds
The plugin-approvals schema gained approvalReviewerDeviceIds (#100251)
without refreshing the generated Swift model, so the bundled-protocol
drift gate fails on every PR. Mechanical pnpm protocol:gen:swift output.
2026-07-05 03:38:08 -07:00
Ben.Li
8df18050d5 fix(android): default manual TLS port to 18789 except Tailscale hosts (#99865)
* fix(android): default manual TLS port to 18789 except Tailscale hosts

Match iOS resolveManualPort so blank-port TLS manual connects use 443 only for .ts.net hosts and 18789 elsewhere; update Connect port hints accordingly.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): sync i18n and align manual port hints with resolver

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(android): unify blank manual gateway ports

* fix(android): normalize tailnet port hints

* refactor(android): drop legacy connection UI delta

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-05 03:17:08 -07:00
Peter Steinberger
3f493aa6d0 chore(android): add deterministic chat streaming replay test harness (#100200)
* test(android): add deterministic chat streaming replay harness (#100196)

* test(android): emit protocol-valid chat replay events
2026-07-05 03:16:55 -07:00
Peter Steinberger
5af24d16bf chore(ci): fail CI when gateway events go unhandled by the mobile apps (#100206)
* ci: guard gateway protocol event coverage for iOS/Android clients (#100198)

Adds scripts/check-protocol-event-coverage.mjs, which derives the
server->client event catalog from GATEWAY_EVENTS in
src/gateway/server-methods-list.ts, extracts the events each mobile app
handles from Swift/Kotlin dispatch sites, and fails on gateway events no
client handles unless allowlisted with a reason in
scripts/protocol-event-coverage.allowlist.json. Wired as
pnpm check:protocol-coverage in the CI guards shard.

* fix(ci): scope Kotlin event extraction to handle*Event dispatch functions (#100198)

Bare event == "..." literals in predicate helpers outside the dispatch
path (gatewayEventInvalidatesNodesDevices in NodeRuntime.kt, which has no
production caller) counted as Android coverage, silently masking that
node.pair.requested/resolved have no live handler. Kotlin extraction now
only reads when(event) labels and event comparisons inside fun
handle*Event(...) bodies; node.pair.* moved to the Android allowlist with
a truthful reason. Swift extraction stays tree-wide because consumption
there always reads .event off a received EventFrame.

* fix(android): remove dead node pairing event helper

* fix(ci): preserve protocol allowlist parse errors

* test(ci): align tooling import plan
2026-07-05 03:06:52 -07:00
Peter Steinberger
0720b322fe fix(ios): remove debug icon outer rim (#100259) 2026-07-05 02:50:07 -07:00
github-actions[bot]
ad4809f677 chore(i18n): refresh native locales 2026-07-05 09:23:42 +00:00
Peter Steinberger
9c5ea29e38 test: stabilize OpenClawKit async tests (#100243) 2026-07-05 02:12:06 -07:00
Peter Steinberger
e60c510560 feat(ios): distinguish debug app builds (#100222)
* feat(ios): distinguish debug app builds

* feat(ios): distinguish debug app builds

* feat(ios): emphasize debug app icons

* feat(ios): emphasize debug app icons
2026-07-05 02:01:26 -07:00
Vincent Koc
bb1e0ad724 fix(apps): refresh native i18n inventory 2026-07-05 10:32:46 +02:00
Peter Steinberger
4deb63c979 fix(crestodian): repair post-merge checks (#100223) 2026-07-05 01:17:58 -07:00
Peter Steinberger
05c9dccf35 feat(apps): match the mascot design to the openclaw.ai hero
Aligns the shared OpenClawMascotView with the website hero styling:
per-part bounding-box gradients (SVG objectBoundingBox semantics; the
claws were nearly flat-colored before), antenna stroke width 2, eye
glow r=2, float depth -8% of size, and a light-scheme palette from the
site theme variables. The float now offsets the whole canvas like the
site floats the hero container, so the antennae no longer clip at the
float peak.

macOS adopts the hero glow treatment: the About pane mascot gets the
coral silhouette drop-shadow with the teal hover glow and 1.1 hover
scale, and the onboarding hero replaces its hand-rolled breathing glow
circle with the same silhouette glow.
2026-07-05 01:13:26 -07:00
Peter Steinberger
07bf384a8b feat(crestodian): conversational agent-loop onboarding across CLI, web install, and macOS app (#99935)
* feat(crestodian): AI-first conversational onboarding with typed-op guardrails

Interactive `openclaw onboard` (and bare `openclaw` on a fresh install) now
opens the Crestodian conversation: detection-backed first-run proposal
(Claude Code/Codex logins, API keys), persona AI turns for every free-form
message (configless local-runtime fallback, 60s deadline, deterministic
degradation), approval-gated typed operations, chat-hosted channel setup
(`connect <channel>`), config get/schema read ops with secret redaction, and
a post-write validation hook that feeds schema errors back for a self-fix
turn. Adds the additive gateway `crestodian.chat` method so app clients run
the same conversation. Classic wizard stays behind --classic/explicit flags;
non-interactive automation unchanged; `--modern` becomes a deprecated alias
for `openclaw crestodian`.

* feat(macos): Crestodian chat onboarding and importance-ordered permissions

Replace the gateway step-wizard page with a Crestodian chat over the new
crestodian.chat method (works before any model auth exists), sort the
permissions page by importance with no scrolling, drop the redundant manual
refresh, and bump the onboarding version.

* feat(crestodian): run the custodian on the real agent loop with a ring-zero tool

Crestodian conversations now execute through the same embedded agent runner
as regular agents: a persistent agent session with a single construction-gated
`crestodian` tool wrapping the typed operations (read actions free; mutations
require approved=true asserted from explicit user consent, audited, with
post-write config validation fed back into the loop). The engine prefers the
loop (configured models or the Codex app-server fallback) and degrades to the
single-turn planner, then to deterministic commands. Setup approval seeds the
crestodian exec approval so local model harnesses can run; the configless
Codex backend config now enables exec and direct tool loading (it was
dead-on-arrival behind tools.exec.mode=deny and the tool-search index).

* test(crestodian): type the engine mock signatures for the core test lane

* fix(crestodian): map the advertised create_agent tool action

* fix(crestodian): host-verified approval arming and a macOS setup completion gate

Review findings: the model-supplied approved flag alone could authorize
ring-zero mutations (prompt injection / model error), and removing the macOS
wizard gate let users Next past the Crestodian page with nothing configured.
Mutating tool actions now also require host-verified consent (the engine arms
approval only when the user's actual message is an explicit yes), and local
macOS onboarding blocks advancing until setup authored the config, using the
same signal the old step wizard checked.

* fix(crestodian): bind approval to the exact proposed operation and gate dot navigation

A generic yes no longer authorizes arbitrary mutations: denied mutating tool
calls register a canonical operation fingerprint (host-owned, per session),
and an armed turn executes only the identical call, once. The denial message
is arming-aware so the approved turn self-heals in one roundtrip, and the
agent protocol pre-registers proposals. macOS onboarding page dots now honor
the same setup-completion gate as the Next button.

* fix(crestodian): redact sensitive wizard answers, skip logged-out CLIs, gate programmatic advance

Sensitive channel-wizard answers (tokens, passwords) are redacted from the
AI-visible conversation history; setup and the onboarding welcome never pick
or advertise a definitively logged-out CLI as the model; and macOS
handleNext() honors the page gates for programmatic callers (chat handoff)
just like the Next button.

* fix(crestodian): align the onboarding welcome's configured predicate with the app gate

A valid config carrying only a default model (partial/hand-written) now still
gets the first-run proposal instead of the ready guide, so the macOS setup
gate can always be satisfied from the conversation.

* fix(crestodian): armed turns can never mint their own executable proposal

An approval-mismatched call inside an armed turn no longer re-registers and
invites a retry (which let the model swap the approved operation for another
in the same turn); it voids the approval entirely and requires a fresh yes.
Proposals register only in unarmed turns, which the agent protocol already
does when proposing.

* fix(onboard): route any explicit setup flag to the classic wizard

* fix(ci): satisfy new lint rules, tool-display guard, and generated artifacts for crestodian

* chore(i18n): refresh native inventory after permissions copy wrap

* fix(crestodian): harden conversational onboarding

* docs(crestodian): document conversational onboarding

* test(crestodian): type embedded runner mock

* fix(crestodian): close onboarding security gaps

* chore: retrigger ci
2026-07-05 01:02:53 -07:00
Peter Steinberger
c64a306f90 fix(macos): preserve PATH for SSH helpers (#100214) 2026-07-05 00:45:08 -07:00
github-actions[bot]
8be1d366a1 chore(i18n): refresh native locales 2026-07-05 06:42:53 +00:00
Peter Steinberger
f052a2f23b feat(macos): animate the OpenClaw mascot in About and onboarding
Ports the animated OpenClawMascotView to the macOS app: the About pane
icon and the onboarding hero now render the Canvas+TimelineView mascot
(float/blink/antenna-wiggle/claw-snap, still under Reduce Motion)
instead of the static app icon.

The view moves from apps/ios into the shared OpenClawChatUI target of
OpenClawKit so iOS and macOS consume one copy; the iOS lint filelist
tracks the moved file.
2026-07-04 23:20:11 -07:00
github-actions[bot]
e069cb26f7 chore(i18n): refresh native locales 2026-07-05 04:04:27 +00:00