Skip to content

fix(macos): guard all audio input paths against missing microphone (AI-assisted)#25817

Closed
sfo2001 wants to merge 2 commits intoopenclaw:mainfrom
sfo2001:fix/macos-no-microphone-crash
Closed

fix(macos): guard all audio input paths against missing microphone (AI-assisted)#25817
sfo2001 wants to merge 2 commits intoopenclaw:mainfrom
sfo2001:fix/macos-no-microphone-crash

Conversation

@sfo2001
Copy link
Contributor

@sfo2001 sfo2001 commented Feb 24, 2026

Summary

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

Voice Wake, Talk Mode, Push-to-Talk, and Mic Level Monitor no longer crash when no audio input device is available. Features log an error and remain inactive until a mic is connected.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS (any version supporting OpenClaw)
  • Runtime/container: OpenClaw.app (macOS menubar app)
  • Model/provider: N/A (crash occurs before any model interaction)
  • Integration/channel: N/A
  • Relevant config: Voice Wake enabled (default on first launch)

Steps

  1. Use a Mac without built-in microphone (Mac mini M4, Mac Pro, Mac Studio) with no external audio input connected
  2. Launch OpenClaw.app with Voice Wake enabled
  3. Observe behavior

Expected

App launches normally. Voice features show disabled/error state. No crash.

Actual (before fix)

SIGABRT crash loop. App cannot launch. Users must disable Voice Wake via defaults/plist editing or connect an external mic to break the loop.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

2 smoke tests in AudioInputDeviceObserverTests.swift: (1) hasUsableDefaultInputDeviceReturnsBool verifies the composition logic runs without crashing (result depends on host hardware), (2) hasUsableDefaultInputDeviceConsistentWithComponents validates that the composed method matches calling defaultInputDeviceUID() + aliveInputDeviceUIDs() independently. Tests require Xcode/CI to compile and run; not verified locally (no Xcode on this machine).

Human Verification (required)

  • Verified scenarios: Code review of all 5 guard sites; error propagation paths traced through each caller; confirmed each guard is placed before the first inputNode access; verified hasUsableDefaultInputDevice() uses the same proven CoreAudio APIs already in AudioInputDeviceObserver; verified VoicePushToTalk.startRecognition() nils audioEngine before throwing to avoid retaining a dead engine; reviewed both smoke tests for correctness
  • Edge cases checked: Device UID present but dead (disconnected USB mic -- covered by aliveInputDeviceUIDs() alive check); no device at all (covered by defaultInputDeviceUID() returning nil); haltRecognitionPipeline() in VoiceWakeRuntime accesses self.audioEngine?.inputNode but only when audioEngine was previously started successfully (nil-safe via optional chaining); TOCTOU race (device removed between hasUsableDefaultInputDevice() and inputNode access -- inherent to hardware checks, mitigated by existing try/catch around AVAudioEngine.start())
  • What you did not verify: Runtime testing (requires Mac without mic); Swift compilation (no Xcode available). 2 smoke tests exist but await CI validation.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert the single commit
  • Files/config to restore: None
  • Known bad symptoms reviewers should watch for: hasUsableDefaultInputDevice() returning false negative (device present but check fails) -- voice features would stay inactive despite mic being connected

Risks and Mitigations

  • Risk: hasUsableDefaultInputDevice() false negative on an unusual audio device that reports as non-alive despite being functional
    • Mitigation: Uses the same CoreAudio property queries (kAudioDevicePropertyDeviceIsAlive, kAudioDevicePropertyStreamConfiguration) already proven in AudioInputDeviceObserver.aliveInputDeviceUIDs(), which has been in production since the device observer was introduced. Only adds a set-membership check on top.
  • Risk: TOCTOU race -- device could be removed between hasUsableDefaultInputDevice() returning true and the subsequent inputNode access
    • Mitigation: Inherent to hardware availability checks; cannot be fully eliminated. Existing try/catch around AVAudioEngine.start() handles this case. The guard reduces the crash surface from always-crash to a narrow race window.
  • Risk: TalkModeRuntime.startRecognition() silently returns on missing mic (logs .error, no throw) while the other 4 sites throw NSError
    • Mitigation: Deliberate -- startRecognition() is not a throws function; changing the signature would cascade through callers. The .error log provides diagnostic signal. The caller's state machine does not depend on recognition start succeeding.

Issue archaeology

17 issues filed, 12 closed as duplicates or by stale bot, none with a code fix on main:

#1853 --dup--> #1600 (wrong target: CodeTokenizer, not mic)
#4163 --dup--> #3529
#5407 --dup--> #3529
#5529 --dup--> #3529
#8831 --dup--> #3529
#3529 --dup--> #12169 --stale-bot--> CLOSED
#5099 --dup--> #13808 --dup--> #12169 --stale-bot--> CLOSED
#11834 --dup--> #13808 --dup--> #12169 --stale-bot--> CLOSED
#15740 --dup--> #12169 --stale-bot--> CLOSED
#16118 --dup--> #12169 --stale-bot--> CLOSED
#21492 --claimed-fixed--> closed by steipete (commit 45f7f2f not on main)

4 PRs attempted, all closed without merge:

Files changed (7 files, +65 lines)

File Change
AudioInputDeviceObserver.swift Added hasUsableDefaultInputDevice() static method
VoiceWakeRuntime.swift Guard before inputNode in start(with:) (throws)
TalkModeRuntime.swift Guard before inputNode in startRecognition() (early return + log)
MicLevelMonitor.swift Guard before engine creation in start(onLevel:) (throws)
VoiceWakeTester.swift Guard before engine creation in start(...) (throws)
VoicePushToTalk.swift Guard before inputNode in startRecognition(...) (throws); nils audioEngine before throw
AudioInputDeviceObserverTests.swift Smoke tests for hasUsableDefaultInputDevice() (no-crash + consistency)

AI Disclosure: Code changes were co-authored with Claude Code (Anthropic).
Issue/PR archaeology was performed by Claude Code; I manually verified the duplicate chains, close reasons, and commit references across all 17 linked issues and 4 prior PRs.
Lightly tested: 2 unit tests added but not compiled locally (requires Xcode). Awaiting CI validation.

Greptile Summary

This PR adds a hasUsableDefaultInputDevice() CoreAudio preflight check and guards all 5 AVAudioEngine.inputNode access sites to prevent SIGABRT crashes on Macs without a built-in microphone. The approach is sound: the new method composes two existing, proven CoreAudio queries (defaultInputDeviceUID() and aliveInputDeviceUIDs()), and the guards are placed at the correct points before inputNode access.

However, two of the five guard sites have a critical flaw where the error recovery path itself accesses inputNode on a non-nil engine, re-triggering the same crash:

  • VoiceWakeRuntime.start(with:): The guard throws, but the catch block calls stop()haltRecognitionPipeline(), which accesses self.audioEngine?.inputNode on the engine that was just created before the guard. Fix: nil self.audioEngine before throwing (matching the pattern already used in VoicePushToTalk).
  • TalkModeRuntime.startRecognition(): The guard returns early but leaves self.audioEngine non-nil. When stopRecognition() is later called, it accesses self.audioEngine?.inputNode on the stale engine. Fix: nil self.audioEngine before returning.

The other three guard sites (MicLevelMonitor, VoiceWakeTester, VoicePushToTalk) are correctly implemented — they either place the guard before engine creation or nil the engine before throwing.

Confidence Score: 2/5

  • Two of the five guard sites re-trigger the SIGABRT through their cleanup paths, defeating the purpose of the fix for VoiceWakeRuntime and TalkModeRuntime.
  • The overall approach and 3 of 5 guard sites are correct, but VoiceWakeRuntime (the primary crash site from the issue reports) and TalkModeRuntime will still crash via their error recovery paths accessing inputNode on a non-nil engine. These are one-line fixes (add self.audioEngine = nil before the throw/return), but as-is the PR does not fully resolve the crash for the two most critical code paths.
  • Pay close attention to apps/macos/Sources/OpenClaw/VoiceWakeRuntime.swift and apps/macos/Sources/OpenClaw/TalkModeRuntime.swift — both need self.audioEngine = nil before their guard exit paths.

Last reviewed commit: 1a82915

Add AudioInputDeviceObserver.hasUsableDefaultInputDevice() that verifies
the default input device both exists and is alive with input channels.
Guard all 5 code paths that access AVAudioEngine.inputNode:
VoiceWakeRuntime, TalkModeRuntime, MicLevelMonitor, VoiceWakeTester,
and VoicePushToTalk.

Prevents SIGABRT crash loop on Macs without built-in microphone
(Mac mini, Mac Pro, Mac Studio) when no external audio input is
connected, and when a previously configured mic is disconnected.

Fixes openclaw#16418, fixes openclaw#17484, fixes openclaw#22667, fixes openclaw#23162, fixes openclaw#24677

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

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +169 to +174
guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
throw NSError(
domain: "VoiceWakeRuntime",
code: 1,
userInfo: [NSLocalizedDescriptionKey: "No usable audio input device available"])
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guard fails but engine cleanup accesses inputNode

When hasUsableDefaultInputDevice() returns false, the throw reaches the catch block (line 228), which calls self.stop()haltRecognitionPipeline(). At line 73, haltRecognitionPipeline() accesses self.audioEngine?.inputNode.removeTap(onBus: 0). Since self.audioEngine was just set to a new AVAudioEngine() on lines 164-165 (before this guard), the optional chain does NOT short-circuit, and accessing .inputNode on a device with no mic triggers the same SIGABRT this guard is meant to prevent.

The fix in VoicePushToTalk correctly nils self.audioEngine before throwing (line 248). The same pattern should be applied here:

Suggested change
guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
throw NSError(
domain: "VoiceWakeRuntime",
code: 1,
userInfo: [NSLocalizedDescriptionKey: "No usable audio input device available"])
}
guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
self.audioEngine = nil
throw NSError(
domain: "VoiceWakeRuntime",
code: 1,
userInfo: [NSLocalizedDescriptionKey: "No usable audio input device available"])
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/macos/Sources/OpenClaw/VoiceWakeRuntime.swift
Line: 169-174

Comment:
**Guard fails but engine cleanup accesses `inputNode`**

When `hasUsableDefaultInputDevice()` returns false, the throw reaches the `catch` block (line 228), which calls `self.stop()``haltRecognitionPipeline()`. At line 73, `haltRecognitionPipeline()` accesses `self.audioEngine?.inputNode.removeTap(onBus: 0)`. Since `self.audioEngine` was just set to a new `AVAudioEngine()` on lines 164-165 (before this guard), the optional chain does NOT short-circuit, and accessing `.inputNode` on a device with no mic triggers the same SIGABRT this guard is meant to prevent.

The fix in `VoicePushToTalk` correctly nils `self.audioEngine` before throwing (line 248). The same pattern should be applied here:

```suggestion
            guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
                self.audioEngine = nil
                throw NSError(
                    domain: "VoiceWakeRuntime",
                    code: 1,
                    userInfo: [NSLocalizedDescriptionKey: "No usable audio input device available"])
            }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, fixed in eb3028d. Both VoiceWakeRuntime and TalkModeRuntime had the same issue: audioEngine was created before the guard but not nilled on the failure path. haltRecognitionPipeline()/stopRecognition() would then access .inputNode on the non-nil engine, triggering the same SIGABRT.

Added self.audioEngine = nil before the throw/return in both files, matching the pattern already in VoicePushToTalk, MicLevelMonitor, and VoiceWakeTester.

Comment on lines +188 to +191
guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
self.logger.error("talk mode: no usable audio input device")
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guard fails but engine cleanup accesses inputNode

When hasUsableDefaultInputDevice() returns false, this guard returns early but does NOT nil out self.audioEngine, which was just set to a new AVAudioEngine() on lines 183-184. When stopRecognition() is eventually called (e.g., from stop() → line 150), line 234 accesses self.audioEngine?.inputNode.removeTap(onBus: 0). Since self.audioEngine is non-nil, the optional chain does not short-circuit, and accessing .inputNode on a device with no mic triggers the same SIGABRT this guard is meant to prevent.

Nil out the engine before returning:

Suggested change
guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
self.logger.error("talk mode: no usable audio input device")
return
}
guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
self.audioEngine = nil
self.logger.error("talk mode: no usable audio input device")
return
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/macos/Sources/OpenClaw/TalkModeRuntime.swift
Line: 188-191

Comment:
**Guard fails but engine cleanup accesses `inputNode`**

When `hasUsableDefaultInputDevice()` returns false, this guard returns early but does NOT nil out `self.audioEngine`, which was just set to a new `AVAudioEngine()` on lines 183-184. When `stopRecognition()` is eventually called (e.g., from `stop()` → line 150), line 234 accesses `self.audioEngine?.inputNode.removeTap(onBus: 0)`. Since `self.audioEngine` is non-nil, the optional chain does not short-circuit, and accessing `.inputNode` on a device with no mic triggers the same SIGABRT this guard is meant to prevent.

Nil out the engine before returning:

```suggestion
        guard AudioInputDeviceObserver.hasUsableDefaultInputDevice() else {
            self.audioEngine = nil
            self.logger.error("talk mode: no usable audio input device")
            return
        }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in eb3028d

steipete added a commit that referenced this pull request Feb 25, 2026
Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
@steipete
Copy link
Contributor

Landed on main via commit 236b22b6a.

What I changed while landing:

  • Kept the broad guard coverage and the follow-up audioEngine = nil crash-path fix from this PR.
  • Added changelog entry under 2026.2.24 (Unreleased).
  • Preserved co-authorship in the landing commit.

Validation run on the landing branch:

  • swift test --package-path apps/macos --filter AudioInputDeviceObserverTests
  • swift test --package-path apps/macos --filter VoiceWakeRuntimeTests
  • swift test --package-path apps/macos --filter VoicePushToTalkTests

The full swift test --package-path apps/macos run was attempted but stalled in unrelated long-running tests after partial execution; targeted suites above passed and include touched paths.

Thanks for pushing this through.

@steipete steipete closed this Feb 25, 2026
gavinwxx-vybers added a commit to Vybers-AI/openclaw that referenced this pull request Feb 25, 2026
* ui: block svg data image opens and harden tests

* changelog: credit both chat-image fix contributors

* test(ui): reject base64 SVG data URLs

* changelog: include openclaw#25847 in chat image safety entry (openclaw#25847) (thanks @shakkernerd)

* refactor(ios): drop legacy talk payload and keychain fallbacks

* chore: sync plugin versions to 2026.2.24

* chore: refresh lockfile after plugin devDependency cleanup

* fix(config): soften antigravity removal fallout (openclaw#25538)

Land openclaw#25538 by @chilu18 to keep legacy google-antigravity-auth config entries non-fatal after removal (see openclaw#25862).

Co-authored-by: chilu18 <chilu.machona@icloud.com>

* fix(security): lock sandbox tmp media paths to openclaw roots

* docs(security): document openclaw temp-folder boundary

* fix(security): restrict default safe-bin trusted dirs

* fix: enforce local media root checks for attachment hydration

* fix(synology-chat): fail closed empty allowlist

* docs(changelog): add synology-chat allowlist fail-closed note

* fix: harden routing/session isolation for followups and heartbeat

* feat(sandbox): block container namespace joins by default

* refactor(sandbox): centralize network mode policy helpers

* fix(channels,sandbox): land hard breakage cluster from reviewed PR bases

Lands reviewed fixes based on openclaw#25839 (@pewallin), openclaw#25841 (@joshjhall), and openclaw#25737/@25713 (@DennisGoldfinger/@peteragility), with additional hardening + regression tests for queue cleanup and shell script safety.

Fixes openclaw#25836
Fixes openclaw#25840
Fixes openclaw#25824
Fixes openclaw#25868

Co-authored-by: Peter Wallin <pwallin@gmail.com>
Co-authored-by: Joshua Hall <josh@yaplabs.com>
Co-authored-by: Dennis Goldfinger <dennisgoldfinger@gmail.com>
Co-authored-by: peteragility <peteragility@users.noreply.github.com>

* refactor(synology-chat): centralize DM auth and fail fast startup

* test: add routing/session isolation edge-case regressions

* refactor: centralize followup origin routing helpers

* refactor(outbound): centralize attachment media policy

* refactor: harden safe-bin trusted dir diagnostics

* fix(zalo): enforce group sender policy in groups

* docs: update changelog for safe-bin hardening

* test(line): align tmp-root expectation after sandbox hardening

* fix(web-search): reduce provider auto-detect log noise

* test(matrix,discord,sandbox): expand breakage regression coverage

* refactor(matrix,tests): extract helpers and inject send-queue timing

* refactor(zalo): split monitor access and webhook logic

* Gateway/Security: protect /api/channels plugin root

* fix(telegram): block unauthorized DM media downloads

* Security: sanitize inherited host exec env

* Changelog: add entry for exec env sanitization

* fix(security): classify hook sessions case-insensitively

* refactor(outbound): unify attachment hydration flow

* refactor(telegram): simplify DM media auth precheck flow

* fix(automation): harden announce delivery + cron coding profile (openclaw#25813 openclaw#25821 openclaw#25822)

Co-authored-by: Shawn <shenghuikevin@shenghuideMac-mini.local>
Co-authored-by: 不做了睡大觉 <user@example.com>
Co-authored-by: Marcus Widing <widing.marcus@gmail.com>

* security(voice-call): detect Telnyx webhook replay

* Auto-reply: add exact stop trigger for do not do that

* Auto-reply tests: assert exact do not do that behavior

* Gateway tests: cover exact do not do that stop matching

* Telegram tests: route exact do not do that to control lane

* Changelog: note exact do not do that stop trigger

* refactor(tmp): harden temp boundary guardrails

* fix(whatsapp): stop retry loop on non-retryable 440 close

* test(types): fix ts narrowing regressions in followup and matrix queue tests

* fix(onboard): avoid false 'telegram plugin not available' block

* fix: normalize "bedrock" provider ID to "amazon-bedrock"

Add "bedrock" and "aws-bedrock" as aliases for the canonical
"amazon-bedrock" provider ID in normalizeProviderId().

Without this mapping, configuring a model as "bedrock/..." causes
the auth resolution fallback to miss the Bedrock-specific AWS SDK
path, since the fallback check requires normalized === "amazon-bedrock".
This primarily affects the main agent when the explicit auth override
is not preserved through config merging.

Fixes openclaw#15716

* docs(changelog): backfill landed fix PR entries

* fix(security): harden system.run companion command binding

* fix(discord): land proxy/media/reaction/model-picker regressions

Reimplements core Discord fixes from openclaw#25277 openclaw#25523 openclaw#25575 openclaw#25588 openclaw#25731 with expanded tests.

- thread proxy-aware fetch into inbound attachment/sticker downloads
- fetch /gateway/bot via proxy dispatcher before ws connect
- wire statusReactions emojis/timing overrides into controller
- compact model-picker custom_id keys with backward-compatible parsing

Co-authored-by: openperf <openperf@users.noreply.github.com>
Co-authored-by: chilu18 <chilu18@users.noreply.github.com>
Co-authored-by: Yipsh <Yipsh@users.noreply.github.com>
Co-authored-by: lbo728 <lbo728@users.noreply.github.com>
Co-authored-by: s1korrrr <s1korrrr@users.noreply.github.com>

* docs(changelog): add reporter credit for exec companion hardening

* fix(macos): guard voice audio paths with no input device (openclaw#25817)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>

* fix(macos): prefer openclaw binary while keeping pnpm fallback (openclaw#25512)

Co-authored-by: Peter Machona <7957943+chilu18@users.noreply.github.com>

* Auth: bypass cooldown tracking for OpenRouter

* Auth: use cooldown helper in explicit profile order

* Tests: cover OpenRouter cooldown display bypass

* Tests: skip OpenRouter failure cooldown persistence

* Tests: keep OpenRouter runnable with legacy cooldown markers

* Tests: preserve OpenRouter explicit auth order under cooldown fields

* Changelog: note OpenRouter cooldown bypass

* Changelog: remove unrelated session entries from PR

* Update CHANGELOG.md

* fix(macos): default voice wake forwarding to webchat (openclaw#25440)

Co-authored-by: Peter Machona <7957943+chilu18@users.noreply.github.com>

* fix(macos): keep Return for IME marked text commit (openclaw#25178)

Co-authored-by: jft0m <9837901+bottotl@users.noreply.github.com>

* fix(security): block env depth-overflow approval bypass

* fix(macos): resolve webchat panel corner clipping (openclaw#22458)

Co-authored-by: apethree <3081182+apethree@users.noreply.github.com>
Co-authored-by: agisilaos <3073709+agisilaos@users.noreply.github.com>

* Agents: trust explicit allowlist refs beyond catalog

* Tests: cover allowlist refs missing from catalog

* Gateway tests: accept allowlisted refs absent from catalog

* Gateway tests: include synthetic allowlist models in models.list

* Changelog: note allowlist stale-catalog model selection fix

* fix(discord): harden voice DAVE receive reliability (openclaw#25861)

Reimplements and consolidates related work:
- openclaw#24339 stale disconnect/destroyed session guards
- openclaw#25312 voice listener cleanup on stop
- openclaw#23036 restore @snazzah/davey runtime dependency

Adds Discord voice DAVE config passthrough, repeated decrypt failure
rejoin recovery, regression tests, docs, and changelog updates.

Co-authored-by: Frank Yang <frank.ekn@gmail.com>
Co-authored-by: Do Cao Hieu <admin@docaohieu.com>

* fix(macos): clean warnings and harden gateway/talk config parsing

* docs(discord): document DAVE defaults and decrypt recovery

* test: bridge discord voice private casts via unknown

* docs(changelog): remove next-release shipping sentence

* refactor(exec): split system.run phases and align ts/swift validator contracts

* fix(windows): skip unreliable dev comparison in fs-safe openVerifiedLocalFile

On Windows, device IDs (dev) returned by handle.stat() and fs.lstat()
may differ even for the same file, causing false-positive 'path-mismatch'
errors when reading local media files.

This fix introduces a statsMatch() helper that:
- Always compares inode (ino) values
- Skips device ID (dev) comparison on Windows where it's unreliable
- Maintains full comparison on Unix platforms

Fixes openclaw#25699

* fix: align windows safe-open file identity checks

* refactor: dedupe exec wrapper denial plan and test setup

* fix: harden iMessage echo dedupe and reasoning suppression (openclaw#25897)

* test(media): add win32 dev=0 local media regression

* refactor: extract iMessage echo cache and unify suppression guards

* test: normalize tmp media path assertion for windows

* fix(render): seed Control UI origin config on first boot

The gateway requires controlUi.allowedOrigins when binding to LAN.
On Render, the persistent disk starts empty with no openclaw.json.
Seed a minimal config with dangerouslyAllowHostHeaderOriginFallback
on first boot (safe behind Render's HTTPS reverse proxy).

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

* chore(deps): update dependencies except carbon

* fix(agents): normalize SiliconFlow Pro thinking=off payload (openclaw#25435)

Land PR openclaw#25435 from @Zjianru.
Changelog: add 2026.2.24 fix entry with contributor credit.

Co-authored-by: codez <codezhujr@gmail.com>

* fix(telegram): refresh global undici dispatcher for autoSelectFamily (openclaw#25682)

Land PR openclaw#25682 from @lairtonlelis after maintainer rework:
track dispatcher updates when network decision changes to avoid stale global fetch behavior.

Co-authored-by: Ailton <lairton@telnyx.com>

* fix(synology-chat): land @bmendonca3 fail-closed allowlist follow-up (openclaw#25827)

Carry fail-closed empty-allowlist guard clarity and changelog attribution for PR openclaw#25827.

Co-authored-by: Brian Mendonca <brianmendonca@Brians-MacBook-Air.local>

* fix(agents): reduce billing false positives on long text (openclaw#25680)

Land PR openclaw#25680 from @lairtonlelis.
Retain explicit status/code/http 402 detection for oversized structured payloads.

Co-authored-by: Ailton <lairton@telnyx.com>

* fix(render): add docker entrypoint script for config seeding

The inline shell command in render.yaml's dockerCommand wasn't
reliably creating the seed config. Replace with a proper entrypoint
script that creates a minimal openclaw.json with
dangerouslyAllowHostHeaderOriginFallback on first boot, then starts
the gateway bound to LAN on the PORT env var.

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

* fix(ui): inherit default model fallbacks in agents overview (openclaw#25729)

Land PR openclaw#25729 from @Suko.
Use shared fallback-resolution helper and add regression coverage for default, override, and explicit-empty cases.

Co-authored-by: suko <miha.sukic@gmail.com>

* fix(heartbeat): default target none and internalize relay prompts

* test(windows): normalize risky-path assertions

---------

Co-authored-by: Shakker <shakkerdroid@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: chilu18 <chilu.machona@icloud.com>
Co-authored-by: Peter Wallin <pwallin@gmail.com>
Co-authored-by: Joshua Hall <josh@yaplabs.com>
Co-authored-by: Dennis Goldfinger <dennisgoldfinger@gmail.com>
Co-authored-by: peteragility <peteragility@users.noreply.github.com>
Co-authored-by: Brian Mendonca <brianmendonca@Brians-MacBook-Air.local>
Co-authored-by: Shawn <shenghuikevin@shenghuideMac-mini.local>
Co-authored-by: 不做了睡大觉 <user@example.com>
Co-authored-by: Marcus Widing <widing.marcus@gmail.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Mark Musson <mark@musson.co.za>
Co-authored-by: suko <miha.sukic@gmail.com>
Co-authored-by: Fred White <fwhite13@users.noreply.github.com>
Co-authored-by: openperf <openperf@users.noreply.github.com>
Co-authored-by: chilu18 <chilu18@users.noreply.github.com>
Co-authored-by: Yipsh <Yipsh@users.noreply.github.com>
Co-authored-by: lbo728 <lbo728@users.noreply.github.com>
Co-authored-by: s1korrrr <s1korrrr@users.noreply.github.com>
Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
Co-authored-by: Peter Machona <7957943+chilu18@users.noreply.github.com>
Co-authored-by: jft0m <9837901+bottotl@users.noreply.github.com>
Co-authored-by: apethree <3081182+apethree@users.noreply.github.com>
Co-authored-by: agisilaos <3073709+agisilaos@users.noreply.github.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
Co-authored-by: Do Cao Hieu <admin@docaohieu.com>
Co-authored-by: Gavin X. Wang <gavinvybers@Gavins-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: codez <codezhujr@gmail.com>
Co-authored-by: Ailton <lairton@telnyx.com>
joshavant pushed a commit that referenced this pull request Feb 25, 2026
Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
margulans pushed a commit to margulans/Neiron-AI-assistant that referenced this pull request Feb 25, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
Jackson3195 pushed a commit to Jackson3195/openclaw-with-a-personal-touch that referenced this pull request Feb 25, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
brianleach pushed a commit to brianleach/openclaw that referenced this pull request Feb 26, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
@sfo2001 sfo2001 deleted the fix/macos-no-microphone-crash branch February 26, 2026 17:53
execute008 pushed a commit to execute008/openclaw that referenced this pull request Feb 27, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 1, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
(cherry picked from commit 236b22b)

# Conflicts:
#	CHANGELOG.md
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 3, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
(cherry picked from commit 236b22b)

# Conflicts:
#	CHANGELOG.md
#	apps/macos/Tests/MoltbotIPCTests/AudioInputDeviceObserverTests.swift
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
thebenjaminlee pushed a commit to escape-velocity-ventures/openclaw that referenced this pull request Mar 7, 2026
)

Co-authored-by: Stefan Förster <103369858+sfo2001@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment