* fix(apple): prevent stale model thinking state
* test(apple): complete attachment transport fixture
* fix(apple): scope model patch ordering by route identity
* chore(apple): sync native CI metadata
* fix(ios): stop camera work when invoke is cancelled
* fix(ios): mark AVFoundation cancellation boundary
* chore(ios): refresh native i18n inventory
* fix(camera): clean up cancelled warm-up sessions
* fix(ios): make camera cancellation lifecycle-safe
---------
Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* refactor(voice): dedupe talk audio primitives into OpenClawKit
One buffered TTS clip player (watchdog + metering) shared by iOS and
macOS replaces the near-identical pair; macOS TalkPlaybackResult was a
field-for-field duplicate of StreamingPlaybackResult and is gone. One
AVAudioPCMBuffer RMS helper replaces five per-file copies; the metered
PCM passthrough moves into PCMPlaybackEnvelope; TalkModeManager's
duplicated ElevenLabs PCM-then-mp3-retry blocks collapse into one
helper. Net -378 lines, no behavior change.
* fix(ios): drop stray blank line and resync i18n inventory
* fix(ios): drop stray blank line after helper extraction
* feat(voice): universal talk waveform driven by real audio levels
One shared Siri-style talk animation across iOS, watchOS, macOS, and
Android (TalkWaveformView + exact Compose port), replacing per-platform
fakes: synthetic speaking pulses, constant speech-detected power, static
Android bar rows, flat realtime listening. Listening/recording follow
live mic levels on every route; agent speech follows the real playback
envelope (AVAudioPlayer metering + playback-aligned PCM envelope +
WebRTC stats); voice-note recording shows a live capture wave.
* fix(android): order waveform imports and sync native i18n inventory
* chore(i18n): resync native inventory after rebase
* Preserve iOS chat activity on foreground refresh
Show an activity indicator when foreground history reports session activity without a chat in-flight snapshot, while keeping unanswered turns blocked and clearing the fallback state on answers, terminal events, session changes, and timeout.
* fix(ios): preserve foreground run ownership
* chore(ios): sync native string inventory
* chore: keep release changelog owned
---------
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(shared): skip app-group identity migration when OPENCLAW_STATE_DIR is overridden
An unentitled process (mac app, swift test runners) with a fresh state dir
imported the machine's real app-group device identity and auth tokens into
any explicitly overridden state dir, violating the documented legacy-fallback
contract. On developer Macs this leaked real operator/node device tokens into
per-test temp state dirs, breaking the nil-token expectations in
GatewayNodeSessionTests (non bootstrap hello / untrusted bootstrap hello)
for local swift test runs while clean CI passed.
Migration now requires no OPENCLAW_STATE_DIR override, with a regression
test. StateDirectoryIsolationTrait owns per-test state-dir pinning (fresh
temp dir per gated test, env restored to launch value or a run-scoped
quarantine dir, never unset), replacing the hand-rolled setenv/defer
boilerplate in every gated test.
* test(shared): remove redundant throws annotations
* fix(macos): preserve device identity storage
Avoid selecting App Group identity storage when the running app lacks the matching application-groups entitlement, so unentitled macOS builds fall back to the legacy writable identity directory. Existing unrecognized identity files are now preserved instead of being replaced by a newly generated identity, matching the no-overwrite behavior already used for recognized invalid identity data.
* fix(macos): repair identity CI coverage
Limit the App Group entitlement probe to macOS builds so iOS keeps its existing App Group path behavior. Update the state-dir identity regression to assert the new no-overwrite contract for invalid identity-shaped files.
* fix(macos): migrate existing app group identity on legacy fallback
Unentitled macOS builds now migrate a readable App Group device identity
into the selected legacy store before falling back, so an upgrade preserves
the existing device id instead of minting a new one.
* fix(macos): migrate device auth store with identity on app group fallback
The app group to legacy identity migration now carries the sibling
device-auth store file, so an unentitled build keeps its stored device
tokens (keyed by the migrated deviceId) instead of re-pairing. The
process-immutable entitlement check is resolved once per process rather
than creating a SecTask on every state-dir lookup, and the migration
source API returns an identity+auth pair struct.
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
The shared chat session sheet (iOS chat + macOS webchat) gains server-backed
search (sessions.list search param, 250ms debounce, cancellation-safe local
fallback when offline), an Active/Archived scope, swipe/context actions for
pin/rename/archive with optimistic updates and rollback, pin indicators, and
restore-on-open for archived rows. Archiving the open session switches back
to the main session so the composer never points at a send-rejecting session.
OpenClawChatTransport consolidates the two list requirements into canonical
listSessions(limit:search:archived:) with forwarding sugars (unreleased
internal API; all in-repo conformers updated: iOS gateway transport, demo and
fixture transports, previews, macOS webchat, test fakes). macOS webchat also
implements patchSession, giving the sheet's controls a live transport there.
OpenClawChatSessionEntry becomes var-based and gains pinnedAt/archivedAt;
the two full-init rebuild blocks in ChatViewModel collapse to copy-mutation
(the pattern that silently dropped newly added fields), preserving main's
model-identity/thinking-metadata semantics. A shared session list organizer
mirrors gateway ordering (pinnedAt desc, updatedAt desc, key) for cached and
offline lists, and pinned sessions survive the 24h recency cutoff in the
session picker.
Refs #100712