Skip to content

field name didn't match with frontend request#5

Closed
yeoleobun wants to merge 1 commit into
restsend:mainfrom
yeoleobun:patch0
Closed

field name didn't match with frontend request#5
yeoleobun wants to merge 1 commit into
restsend:mainfrom
yeoleobun:patch0

Conversation

@yeoleobun

Copy link
Copy Markdown
Collaborator

The front end use field name model, but back end use model_type.

if (this.config.asr.model) asrConfig.model = this.config.asr.model;

They are not matching, so back end will use default model 16_zh_en and ignore the model parameter in request.

@shenjinti

Copy link
Copy Markdown
Contributor

Should modify the field name in agent.js to -> modelType.
Since rustpbxgo uses the modelType field name, this field cannot be modified.

@shenjinti shenjinti closed this Jul 17, 2025
@yeoleobun
yeoleobun deleted the patch0 branch August 5, 2025 03:05
yeoleobun pushed a commit to yeoleobun/rustpbx that referenced this pull request Mar 16, 2026
fix(tts): timestamp gap between tts track, and clock rate for g722
anujarkitekt added a commit to parvbhullar/media-gateway that referenced this pull request May 24, 2026
…apacity, CDR, leak fix, metrics

Six related changes that move the SIP↔WebRTC bridge from
"smoke-tested end-to-end" to "ready for real customers".

1. Codec passthrough on the SIP leg (restsend#1)
- The SIP-side transcoder cap was hardcoded to `AudioCapability::pcmu()`
  regardless of what the carrier offered. Any carrier negotiating
  G.722, PCMA, or Opus-on-SIP would have its audio silently corrupted
  because the bridge would feed packets to a PCMU decoder.
- New `sip_side_audio_offer()` advertises opus, g722, pcmu, pcma on
  the inbound RTP PC. `build_inbound_rtp_pc` now also returns the
  negotiated `AudioCapability` (intersect carrier-offered set with
  our supported set in carrier-preference order — first match wins).
  Rejects with a clear error if the carrier offered nothing we
  support (was previously a silent fall-through to PCMU).
- G.729 deliberately omitted (patent-encumbered; no real
  encoder/decoder in rustrtc's default build).
- `dispatch_webrtc` plumbs the negotiated codec into
  `BridgePeer::setup_bridge_with_codecs` as the RTP-side cap. 4
  tests: PCMA-only, opus-on-SIP, multi-codec carrier preference,
  unsupported-only rejection.

2. DTMF pass-through (RFC 2833 / RFC 4733) — SIP → WebRTC (restsend#2)
- `sip_side_audio_offer()` now also includes
  `AudioCapability::telephone_event()`. WebRTC-side capability list
  in `build_outbound_webrtc_pc` adds telephone-event alongside the
  voice codec.
- The voice-codec intersection logic filters out telephone-event
  (it's signaling, not voice — would crash the transcoder if picked).
  Telephone-event PT is captured separately from the carrier's offer
  and used to install `BridgePeer::set_dtmf_sink(BridgeEndpoint::Rtp,
  dtmf_pt, ...)`. The bridge data plane already had the
  skip-transcoding-for-DTMF check (`media/bridge.rs:1328-1337`); it
  was no-op only because no sink was ever installed. With the sink
  in place, RFC 2833 telephone-event RTP packets flow verbatim from
  the SIP carrier to the WebRTC bot.
- Reverse direction (WebRTC bot → SIP carrier DTMF) is intentionally
  deferred — same sink-install pattern but keyed on the bot's
  negotiated PT from the answer SDP. Defer until needed; most
  use cases are SIP → bot.
- 3 tests: voice-vs-DTMF separation, non-standard DTMF PT respect,
  no-DTMF graceful fallback (carrier didn't offer it → sink not
  installed, debug log notes DTMF is in-band-only).

3. Capacity caps applied to webrtc dispatch (restsend#6)
- `TrunkCapacityState` + `TrunkCapacityGate` were Phase 5/T artifacts
  that had no live caller in the SIP path; the gate was never wired
  to anything. WebRTC dispatch was equally unmetered.
- New `lookup_webrtc_capacity_limits` helper in webrtc_route_dispatch
  reads `max_concurrent` + `max_cps` from the trunk row.
- `dispatch_webrtc_bridge` (call.rs) now consults the gate at the
  start of dispatch:
    * Both limits None → unlimited, skip gate.
    * `CallsExhausted` → 503 + log + CDR.
    * `CpsExhausted` → 503 + log + CDR.
    * `Ok(permit)` → stash on `WebRtcBridgeSession._permit`; RAII Drop
      releases the slot at BYE-time teardown.

4. CDR rows for bridge calls (restsend#5)
- Bridge calls used to be invisible to the CDR pipeline — billing
  and audit blind. New
  `proxy::webrtc_bridge_sessions::emit_bridge_call_record` + the
  `BridgeCallRecordInfo` shape grouping the constructor args.
- `WebRtcBridgeSession` gains 8 CDR fields (call_id, caller_uri,
  callee_uri, from_number, to_number, trunk_name, trunk_id,
  start_time) populated at dispatch time.
- Failure paths in dispatch_webrtc_bridge emit failed-call CDRs
  (capacity exhausted, dispatch error, reply_with failure, missing
  SDP, bad UTF-8, no DB connection). Success path emits the final
  CDR at BYE-time teardown with status_code=200 and
  hangup_reason=ByCaller (or Failed on adapter.close error).
- Reuses existing `CallRecord` schema; bridge calls are tagged via
  `metadata.call_type="webrtc_bridge"` so reports can filter them.
  CDR write failures log warn and never block the call.
- 2 unit tests for the emit helper (completed + failed dispositions).

5. Session-leak fix on dispatch failure (restsend#9)
- Race condition in dispatch_webrtc: after the remote bot accepts
  the offer (signaling adapter returns NegotiateOutcome with a
  SessionHandle), any subsequent failure — SDP parse, set_remote_
  description, audio_capability_for, setup_bridge_with_codecs — would
  return Err without invoking `adapter.close(ctx, &session)`. The
  bot's session leaked until its own idle timeout (often minutes).
  Same problem on the SIP side: `tx.reply_with` failure after the
  bot accepted left the session orphaned.
- Fix: post-negotiate steps in dispatch_webrtc are wrapped in a
  closure that calls `adapter.close()` first on any error, then
  propagates. `DispatchOutcome` now carries the `SignalingContext`
  so the caller (proxy::call) can drive `adapter.close` on its own
  reply_with failure without re-deriving endpoint_url/auth_header
  from the DB.
- Unit test injects a probe adapter that returns garbage answer
  SDP; asserts close fires exactly once with the right session
  handle before the function returns Err.

6. Bridge Prometheus metrics (restsend#8)
- 4 new metrics under the `rustpbx_bridge_*` namespace:
    * `rustpbx_bridge_sessions_active` (gauge) —
      inc on WebRtcBridgeSessions::insert, dec on remove.
    * `rustpbx_bridge_dispatch_total{outcome}` (counter) —
      labels: success / signaling_error / rtp_setup_error /
      reply_error. Outcomes mutually exclusive: success emits from
      call.rs only after reply_with succeeds.
    * `rustpbx_bridge_signaling_latency_seconds{adapter}` (histogram) —
      time spent in `adapter.negotiate`, labeled by adapter name.
    * `rustpbx_bridge_bye_total{outcome}` (counter) — ok /
      teardown_error, emitted from teardown_webrtc_bridge_if_present.
- Uses the same `metrics::` macro API as the rest of the codebase
  (no new deps). Observability addon exposes them at `/metrics`
  Prometheus endpoint once enabled.

cargo check --release: clean.
cargo test --release --lib proxy::bridge::webrtc: 14/14 pass
(11 with this commit, + 3 from the codec passthrough commit that
landed in the previous PR).
cargo test --release --lib proxy::webrtc_bridge_sessions: 3/3.

Open follow-ups (none blocking):
- Bot → SIP DTMF (reverse of restsend#2): symmetric `set_dtmf_sink` on
  BridgeEndpoint::WebRtc keyed on the bot-negotiated telephone-event PT.
- Re-INVITE handling (hold/resume/mid-call codec change): SIP dialog
  state machine extension; needs softphone-driven verification.
- Real-audio end-to-end validation with actual Pipecat (not just the
  mock-offer test server).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants