Reporter measured `agents list --json` at ~7-9s on a fast host (~11s in
container) on 2026.4.23, while peer `--json` commands like
`channels list`, `cron list --all`, and `sessions ... --all-agents`
stay sub-second. Their cold-call dashboard endpoint dropped from 27s to
~2s after a local dist patch — they could even retire the 5-min cache
TTL workaround they had shipped to dodge it.
Root cause: `agents list` inherits `loadPlugins: 'always'` from the
parent `agents` policy in command-catalog, then `agentsListCommand`
calls `buildProviderStatusIndex(cfg)` unconditionally — both paths
trigger the bundled-extension import waterfall (~60+ extension index.js
modules).
`channels list` already uses `loadPlugins: 'never'` and proves the
shape is right; this PR matches that shape with the safer `text-only`
variant so human invocations are unchanged.
Two-line fix per reporter:
1. `src/cli/command-catalog.ts` — opt agents list into `text-only`,
the same plugin-preload policy bucket that already exists. Plugin
preload runs for human text output, skips for `--json`.
2. `src/commands/agents.commands.list.ts` — skip
`buildProviderStatusIndex` (and the per-summary provider
enrichment loop) when `opts.json`. Provider info is only rendered
in human text output via `formatSummary`, so dropping it from JSON
has no observable effect on existing callers that consume `id`,
`name`, `model`, `bindings`, `isDefault`, `identity*`, `workspace`,
or `agentDir`. `routes` is config-derived and continues to be set
in both modes.
Tests:
- new assertion in command-startup-policy.test.ts: `agents list` with
jsonOutputMode:true now resolves to `loadPlugins: false` (was
effectively `true` via the parent `agents` 'always' policy).
- existing assertion that human (jsonOutputMode:false) still triggers
plugin load is preserved verbatim.
6/6 tests pass. Lint clean.
Out of scope:
- `--bindings` flag opt-in for restoring providers in JSON output:
worth adding later if any consumer needs it; reporter said dashboard
consumers don't.
- Broader plugin-discovery cache work (#67040, #71690) which addresses
the same family of cold-start cost.
* feat(talk): add distinct system sounds for each Talk Mode phase
Play a short system sound on phase transitions to give the user
audible feedback:
- thinking: Tink
- speaking: Pop
- listening (after speech interrupted): Bottle
- listening (after thinking): Submarine
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(talk): add right Shift key to interrupt Talk Mode speech
Add TalkSpeechInterruptMonitor — a dedicated global key monitor that
listens for right Shift (keyCode 60) to interrupt Talk Mode speech.
Independent of Push-to-Talk, so it works even when PTT is disabled.
Stops only the current response; the next conversation cycle
continues normally via sendAndSpeak's resumeListeningIfNeeded flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(talk): increase silence detection timeout for CJK locales
Korean, Japanese, and Chinese speakers need longer pauses between
phrases. When the app locale is CJK, enforce a minimum 2000ms
silence window (vs the default 1500ms) to avoid premature
transcript submission.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(talk): remove force-unwraps and log CJK silence clamp in reloadConfig
Replace non-idiomatic force-unwraps (cfg.voiceId!, cfg.modelId!) with
safe flatMap unwrapping, and add an info log when CJK locale clamps the
silence timeout so the override is observable in diagnostics.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(talk): add settings toggle to mute phase-transition sounds
Add a "Play phase-transition sounds" checkbox to Voice Wake settings.
When disabled, Talk Mode phase transitions (Tink/Pop/Bottle/Submarine)
are silent. Defaults to enabled to preserve existing behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(talk): add toggle for Right Option speech interrupt
Add a "Press Right Option to stop speech" checkbox to Voice Wake
settings. Also change the interrupt key from right Shift to right
Option (keyCode 61) to avoid conflicts with typing.
Defaults to enabled to preserve existing behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(talk): disable Push-to-Talk while Talk Mode is active
Talk Mode and Push-to-Talk both use the right Option key (keyCode 61).
Disable PTT when Talk Mode is enabled to prevent conflicting handlers,
and restore PTT when Talk Mode is disabled.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(talk): show info when PTT is paused during Talk Mode
Display a footnote under the Push-to-Talk toggle when both PTT and
Talk Mode are enabled, explaining that PTT is paused while Talk Mode
is active and resumes when Talk Mode is turned off.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fixup: SwiftFormat lint on TalkModeController phase sound switch
Resolves macos-swift CI lint failures introduced by Korean
comment formatting in 'feat(talk): add distinct system sounds for each Talk Mode phase'.
- Collapse consecutive spaces between sound name and comment
- Move floating comments above the listening case expression so
they're at the correct indent level
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: hongsw <hongsw@hongswui-Macmini.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Fabian Williams <fabian@adotob.com>
Pre-existing lint errors blocking the macos-swift CI check on every
PR that touches Swift code. Apply the wrapMultilineStatementBraces
rule by moving the opening brace of the multi-line if/else if to its
own line.
- apps/macos/Sources/OpenClaw/ExecAllowlistMatcher.swift:17
- apps/macos/Sources/OpenClaw/ExecApprovals.swift:621
Pure formatting change; no behavioral effect.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Translate OpenClaw `mcp.servers.*.transport` entries into the downstream Claude/Gemini CLI `type` field before writing bundle MCP config.
Also keeps the plugin-sdk bundled-entry fast-path fixture unambiguously CommonJS on Node 24 after runtime-deps mirroring adds a `type: "module"` boundary.
Co-authored-by: Blockchain-Oracle <ajweb3dev@gmail.com>
Image generation and media understanding both thread the
sanitized models.providers.google.request config (including
allowPrivateNetwork) into resolveGoogleGenerativeAiHttpRequestConfig.
Speech synthesis omitted that arg, so TTS always saw
allowPrivateNetwork: false regardless of config — silently falling
back to a different speech provider when the configured Google TTS
endpoint resolved to a private/internal IP (proxies, custom backends,
test mocks).
Mirror the image-generation-provider pattern: thread request through
synthesizeGoogleTtsPcm at both call sites (synthesize and
synthesizeTelephony).
Follow-up to #67216.
* fix(github-copilot): preserve all reasoning IDs and add gpt-5.3-codex support
The existing guard (8fd15ed0e5) only skipped rewriting reasoning item IDs
when encrypted_content was a non-null string. When gpt-5.3-codex is used
via GitHub Copilot, the model falls through to the forward-compat catch-all
with reasoning:false, so encrypted_content is never requested and arrives
as null — bypassing the guard and causing a rewrite. Copilot validates
reasoning item IDs server-side regardless of whether the client includes
encrypted_content, so the rewritten id triggers the 400 error.
Two changes:
1. connection-bound-ids.ts: skip ALL reasoning items unconditionally.
Reasoning items always reference server-side state bound to their
original ID; rewriting any of them breaks Copilot's lookup.
2. models.ts + index.ts: extend the forward-compat cloning logic to
cover gpt-5.3-codex (adds it to the template-target set and to
CODEX_TEMPLATE_MODEL_IDS so it can also serve as a template source
for gpt-5.4). Adds gpt-5.3-codex to COPILOT_XHIGH_MODEL_IDS for
the thinking profile.
Thanks @InvalidPandaa.
* docs(github-copilot): clarify gpt-5.3-codex is a no-op template for itself
https://claude.ai/code/session_01EAFmq4WyKkiUkVAqRXp4Bm
* fix(github-copilot): remove dead reasoning prefix branch in deriveReplacementId
https://claude.ai/code/session_01EAFmq4WyKkiUkVAqRXp4Bm
* fix(github-copilot): align reasoning id replay tests
* test(plugin-sdk): use cjs sidecar for require fast path
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
mushuiyu_xydt's commit 0e1ef93e84 (#61155) routes MiniMax image
generation requests to the dedicated image endpoint
(api.minimax.io/v1/image_generation), ignoring models.providers.minimax.baseUrl
(which targets the chat/Anthropic-compatible API), and adds
MINIMAX_API_HOST support for the CN api.minimaxi.com endpoint. The
CHANGELOG entry covered it but docs/providers/minimax.md image-generation
section did not. Add a paragraph naming both endpoints and the
MINIMAX_API_HOST override.