Commit graph

7 commits

Author SHA1 Message Date
RoboClaw
41ee7fb242
fix(voice): keep audio flowing while the Gateway is busy (#154119)
* fix(voice): keep audio flowing while the Gateway is busy

Move Discord voice transport, packet pacing, codecs and capture deadlines into a session-owned worker. Run GPT Live WebRTC and WebSocket media in workers and connect continuous playback with a bounded direct audio port. Preserve authorization, selected-agent work, recording receipts and transcript ownership on main, with generation fencing and ordered teardown.

Validated affected tests, the capture-finalization red/green regression, source and compiled worker lifecycle, root and plugin builds, type/lint/format and line-cap checks.

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>

* fix(voice): keep audio flowing while the Gateway is busy

Worked on by:
- @steipete

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
OpenClaw-Publication: 58c87505-0064-4391-994e-57587279bcca

* fix(voice): use explicit Node message transfer lists

Replace six Node postMessage lint suppressions with explicit empty transfer lists. Preserve the Node messaging contract and the unchanged production suppression allowlist. Reproduced the original CI shard plan before the fix; the same plan, focused worker messaging tests, and type-aware lint pass afterward.

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>

* fix(openai): keep worker runtime out of cold voice catalogs

Load the default media-socket factory only through abort-aware connection admission. Preserve injected factories and WebRTC routing, and centralize unchanged request-ID construction in the wire owner. Keep the cold-catalog contract and line cap intact.

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>

* refactor(openai): keep socket contracts below connection admission

Move unchanged socket interfaces into the existing shared leaf and migrate all private consumers, preserving lazy worker loading without a type import cycle.

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>

* fix(discord): preserve direct speech ownership through playback

Track exact speech with an epoch-scoped shared playback witness. Order completion behind bounded direct-port flush receipts, including no-audio responses, and prevent stale idle or flush events from retiring newer speech. Cover original failures and the pending-flush race with deterministic production-owner regressions.

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>

* fix(discord): preserve audio ownership across worker retirement

Worked on by:
- @steipete

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
OpenClaw-Publication: 6294ffa7-0c2f-456b-9baf-3dcdab60efc8

* refactor(discord): keep the worker status slot private

Worked on by:
- @steipete

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
OpenClaw-Publication: dde5cff1-21c6-4bfa-825e-47c2f1ec2393

---------

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
2026-09-20 21:49:35 -07:00
Peter Steinberger
db6e46a667
fix(test): stop tooling fixtures from silently stalling (#153884)
Keep tooling fixtures limited to their required imports and source files,
and settle child commands through existing cancellation and cleanup owners.
Bind audio mock results to WAV input to remove the completion-order race.

Preserve assertions, timeout and retry policy, and the relocated pnpm lifecycle case.

Validation: fresh merged-context CI run 35531487613 passed; independent P2
review was clean. Local repeat-campaign gaps remain documented in the PR.
2026-09-20 12:48:03 -07:00
Peter Steinberger
d492bb9368
fix(media): report CLI models with missing command or args (#151969)
CLI media models with a missing command or empty argument list passed Doctor. When a command existed but args were absent, the runtime invoked the transcriber without the attachment. Doctor and execution now share the media resolver's minimum-input check. Doctor reports the exact configuration path and a manual fix; execution records a typed refusal before spawning and continues configured fallbacks.

Gateway startup validation remains unchanged. Custom and literal arguments still work, and a valid command returning empty stdout still completes. The Discord fixture now supplies attachment arguments for its empty-output case and waits for owned work to settle on refusals, preserving warning, no-dispatch, and WAV-cleanup coverage.

Release-note context: report incomplete CLI media models in Doctor and prevent command-only transcription attempts while preserving Gateway startup, custom arguments, and configured fallbacks.

Fixes #151883. Thanks to @fede-kamel for reporting and clarifying the missing-args failure. No reporter code was adopted.

Validation: 203 focused tests reported passing, check:changed passing, clean Codex review, and exact-head CI run 35385552484 successful. Landing REST verification found 217 completed checks: 170 successful, 46 skipped, one neutral, and no failures or pending checks. The follow-up from the reviewed production head changes only the Discord integration test.

The published-updater compatibility check was explicitly skipped by maintainer decision: Doctor adds advisory diagnostics only, with no persisted-shape, migration, update-path, or service-lifecycle change. No updater compatibility run is claimed.
2026-09-18 13:41:34 -07:00
Peter Steinberger
ec97febfea
improve(gateway): reduce redundant startup work (#147165)
* improve(gateway): reduce redundant startup work

* test(discord): await transcript conversation dispatch
2026-09-13 09:55:36 -07:00
Peter Steinberger
e96f62c643
fix(discord): prevent voice playback gaps and stale turn controls (#146798)
* fix(discord): smooth voice playback and preserve turn ownership

* test(discord): verify legacy control compatibility and satisfy CI

* refactor(discord): use a duplex Opus stream

* fix(discord): keep revoked voice requests cancelled through dispatch

* test(ui): close named file tab in root identity proof

* test(discord): wait for agent dispatch before resetting voice

* test(gateway): keep CLI auth fixtures isolated through cancellation

* fix(discord): keep cancelled batch voice turns from dispatching
2026-09-13 04:11:01 -07:00
Rodrigo Oliveira
1873328511
fix(media): keep deferred audio and extraction providers discoverable (#139231)
Keep enabled audio and structured-extraction providers discoverable after another media plugin loads, and when shared models select only images. Merge eligible manifest owners at the shared catalog; leave execution selection with the runner and preserve active instances, policy filtering, and selected image loading.

Resolve capability metadata only for normalized, deduplicated untagged provider entries. Pair synthetic audio fixtures with their matching runtime/metadata generation to avoid unrelated cold plugin imports.

Verified the final integration with 69 focused tests, formatting/lint/core typecheck, a fresh independent review, a sealed build, 12 audio/extraction Gateway cases, and three paired full-inventory discovery cases. Exact-head CI 34060063771 succeeded (141 successful jobs, 16 skipped). Production delta: -20 lines. Related #119772 remains open; generic extraction fallback #119773 is outside scope.

Thanks to @rodrigo-fonseca-oliveira for the original diagnosis and fix.

Co-authored-by: Rodrigo Oliveira <rodrfons@hotmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-09-06 14:33:14 -07:00
Peter Steinberger
c6ef1f277e
fix(discord): keep recording independent of voice conversations (#139658)
* fix(discord): keep recording independent of voice conversations

Keep explicit recording owned by its source across connection and manager
replacement. Receive each speaker once, retain packet-time capture authority,
and share completed batch transcription with authorized conversation.

Separate recording progress from conversation admission and replies, fence
incomplete or retired conversation input, and bound receive, conversation,
and queued WAV work. Retain WAV ownership through delayed processing and
cleanup, including when a retired recording hands off to conversation.

Preserve short authorized recording chunks and distinguish completed empty
transcription from omitted media input. Document lifecycle and limit behavior.

Split from #130860. Follows #139484 and #139572. Related: #127426.

* fix(discord): keep package-boundary types portable

Spell the existing channel-resolution union within the plugin and type the
transcript fixture callback with its public SDK contract. This removes a
forbidden normalization-core import and prevents Vitest's private Procedure
type from leaking into generated declarations.

Validation: normalization import guard, all 123 plugin package boundaries,
extension and root integration types, 53 voice cases and two core provider
integrations, and scoped P0-P2 review.

* fix(discord): retain safely bound realtime-only recordings

Preserve existing per-speaker realtime finals when batch audio is disabled
or the actual media runtime confirms no backend is available. Carry packet
capture receipts through delayed admission and wait for every batch result;
successful, silent, failed, mixed, or incomplete input cannot duplicate or
authorize fallback notes. A provider continuity reset permanently retires
the recording owner until a fresh speaker connection establishes receipts.

Bound pending final text and surface limited coverage through /vc status.
Document the independent batch path and the narrower realtime-only contract.

Related to #130860 and #139658.

* test(discord): declare capture-only fixture capability

Keep fake transcript managers aligned with the required realtime capability
query. These integration fixtures have no realtime conversation and return
false without weakening the production interface.

Validation: canonical root test types, provider integration, scoped lint,
and independent P0-P2 review passed.

* refactor(discord): make recording contracts a type-only leaf

Move capture, packet-receipt, and segment-result contracts out of their
runtime owners, breaking the full import graph cycle. Narrow realtime
recording metadata to the three strings it consumes.

All six existing modules emit identical JavaScript; the new leaf emits
none. Validation: both import-cycle guards, three canonical type lanes,
18 focused tests, lint, full build, and scoped P0-P2 review passed.
2026-09-05 23:20:29 -07:00