Skip to content

Conversation

@yujonglee
Copy link
Contributor

@yujonglee yujonglee commented Dec 20, 2025

Summary

Adds replay testing infrastructure for the transcribe-proxy crate, enabling deterministic testing of WebSocket proxy behavior using recorded fixtures. This allows testing edge cases (auth errors, rate limits) without hitting live APIs.

Key additions:

  • WsRecording/WsMessage types for recording and replaying WebSocket message sequences
  • MockUpstreamServer that replays recorded messages with optional timing simulation
  • Fixture files for Deepgram and Soniox (normal transcription, auth errors, rate limits)
  • Recording capability in live tests via environment variables (RECORD_FIXTURES=1)
  • Config support for custom upstream URLs (with_upstream_url)

Code quality improvements:

  • Extracted duplicated analytics setup into finalize_proxy_builder! macro
  • Added encode_optional_binary helper for ping/pong binary encoding
  • Renamed is_server_message/is_client_message to is_from_upstream/is_to_upstream for clarity
  • Added TEST_RESPONSE_TIMEOUT constant to replace magic numbers
  • Documented single-connection limitation in mock server
  • Added tracing::warn for serialization failures during recording

Review & Testing Checklist for Human

  • Verify the finalize_proxy_builder! macro correctly handles both analytics and non-analytics cases (streaming.rs lines 121-144)
  • Check that fixture files in tests/fixtures/ contain valid JSONL and match expected provider response formats
  • Confirm the mock server's single-connection design is acceptable for test isolation needs
  • Run cargo test -p transcribe-proxy --test replay to verify all replay tests pass

Recommended test plan:

  1. Run the replay tests: cargo test -p transcribe-proxy --test replay
  2. Optionally record new fixtures by running live tests with RECORD_FIXTURES=1 FIXTURE_OUTPUT_DIR=./tests/fixtures cargo test -p transcribe-proxy --test providers_e2e

Notes

The mock server intentionally only accepts one connection per instance for test isolation. Each test creates its own mock server.


Link to Devin run: https://app.devin.ai/sessions/7395b0d3df56462fbb7a5baeb1d64d67
Requested by: yujonglee ([email protected]) / @yujonglee

@netlify
Copy link

netlify bot commented Dec 20, 2025

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit fc54b14
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/694644e1a4b0dd0008406459
😎 Deploy Preview https://deploy-preview-2438--hyprnote.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Dec 20, 2025

Deploy Preview for hyprnote-storybook ready!

Name Link
🔨 Latest commit fc54b14
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/694644e11543f10008e3bc3b
😎 Deploy Preview https://deploy-preview-2438--hyprnote-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 20, 2025

📝 Walkthrough

Walkthrough

Adds configurable upstream WebSocket URLs to the STT proxy and routes to them when set. Introduces test infrastructure: WebSocket recording/fixtures, a mock upstream server, helpers, and extensive replay/integration tests for provider behaviors and error scenarios.

Changes

Cohort / File(s) Summary
Config & Routing
crates/transcribe-proxy/src/config.rs, crates/transcribe-proxy/src/routes/streaming.rs
Added pub upstream_urls: HashMap<Provider, String> to SttProxyConfig, plus with_upstream_url() and upstream_url_for(); streaming route now short-circuits to configured upstream URL and centralizes analytics wiring via a new macro.
Test Common API & Exports
crates/transcribe-proxy/tests/common/mod.rs
Added and re-exported fixtures, mock_upstream, and recording modules; exposed load_fixture, MockServerHandle, MockUpstreamConfig, start_mock_server_with_config, WsRecording types, and start_server_with_upstream_url() helper; tightened test_audio_stream() bounds.
Test Fixtures Helpers
crates/transcribe-proxy/tests/common/fixtures.rs
Added fixtures_dir() and load_fixture(name: &str) -> WsRecording helpers that load JSONL fixtures from the tests fixtures directory.
WebSocket Recording Utilities
crates/transcribe-proxy/tests/common/recording.rs
New recording types and APIs: Direction, MessageKind, WsMessage, WsRecording (JSONL load/save, server_messages, transform), WsRecorder, RecordingSession, and RecordingOptions (env-driven). Handles base64 for binary payloads and timing metadata.
Mock Upstream Server (tests)
crates/transcribe-proxy/tests/common/mock_upstream.rs
Implemented MockUpstreamConfig, MockUpstreamServer that replays WsRecording messages with optional timing delays, message mapping to tokio-tungstenite Message, MockUpstreamError, MockServerHandle, and start_mock_server_with_config() to spawn the server.
Test Fixtures (JSONL)
crates/transcribe-proxy/tests/fixtures/*.jsonl
Added multiple JSONL fixtures for Deepgram (normal, auth_error, rate_limit) and Soniox (normal, error) representing recorded server-to-client streams and close events.
Replay Integration Tests
crates/transcribe-proxy/tests/replay.rs
New integration tests exercising proxy replay against mock upstreams: normal flows, auth/rate-limit errors, provider errors, forwarding behavior, and client disconnect handling; includes helpers for connecting and collecting messages.
Live Test Recording Helpers
crates/transcribe-proxy/tests/providers_e2e.rs
Added run_proxy_live_test() and run_proxy_live_test_with_recording() to optionally record live proxy interactions using RecordingOptions and RecordingSession; conditionally saves recordings to disk.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Proxy
    participant MockUpstream as MockUpstream
    participant Recorder as Recording

    Client->>Proxy: WebSocket connect / start session
    activate Proxy

    alt upstream URL configured for provider
        Proxy->>MockUpstream: Connect to configured upstream URL
    else
        Proxy->>Proxy: Perform Auth / Session Init
        Proxy->>MockUpstream: Connect to provider default URL
    end
    activate MockUpstream

    loop replay fixture messages
        MockUpstream->>Proxy: ws message (text/binary/ping/pong/close)
        Proxy->>Client: forward message
        alt recording enabled
            Proxy->>Recorder: record message (JSONL)
        end
    end

    MockUpstream->>Proxy: close
    Proxy->>Client: close
    deactivate MockUpstream
    deactivate Proxy

    opt recording enabled
        Recorder->>Recorder: save JSONL to fixtures directory
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review focus:
    • recording.rs: serde, base64 handling, timing and thread-safety (Arc/Mutex).
    • mock_upstream.rs: async server lifecycle, message mapping (CloseFrame), timing/delay logic.
    • routes/streaming.rs: upstream override precedence and analytics macro integration.
    • Tests (replay.rs, fixtures): correctness of assertions and isolation between tests.

Possibly related PRs

  • New ai proxy #2397 — Modifies SttProxyConfig (fields and builder methods); likely overlaps with upstream URL and config builder changes.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Transcribe-proxy replay testing' directly and clearly describes the main change: adding replay testing infrastructure to the transcribe-proxy crate.
Description check ✅ Passed The description comprehensively explains the replay testing infrastructure additions, including WsRecording types, MockUpstreamServer, fixture files, and configuration support, all of which align with the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch transcribe-proxy-replay

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
crates/transcribe-proxy/tests/common/recording.rs (2)

187-188: Optional: Consider documenting the timestamp range limitation.

The cast from u128 to u64 milliseconds could theoretically overflow after ~584 million years of recording. While this is not a practical concern for test recordings, consider adding a brief comment documenting this limitation for clarity.

💡 Optional clarification
 pub fn elapsed_ms(&self) -> u64 {
+    // Note: Limited to ~584 million years; overflow is not a practical concern for test recordings
     self.start_time.elapsed().as_millis() as u64
 }

207-239: Consider documenting mutex panic behavior.

Lines 222 and 227 use unwrap() on Mutex::lock(), which will panic if the mutex is poisoned (from a panic while locked). While this is generally acceptable in test code where panics are visible and actionable, consider whether documenting this behavior or using expect() with a message would improve debuggability.

💡 Alternative using expect()
 pub fn record_server_text(&self, content: &str) {
-    let mut recorder = self.recorder.lock().unwrap();
+    let mut recorder = self.recorder.lock().expect("recorder mutex poisoned");
     recorder.record_text(Direction::ServerToClient, content);
 }

 pub fn save_to_file(&self, dir: impl AsRef<Path>, suffix: &str) -> std::io::Result<()> {
-    let recorder = self.recorder.lock().unwrap();
+    let recorder = self.recorder.lock().expect("recorder mutex poisoned");
     let recording = recorder.recording();
crates/transcribe-proxy/tests/providers_e2e.rs (2)

56-62: Remove descriptive comments.

Per coding guidelines, comments should be avoided or explain "Why" rather than "What". The comment on line 57 and line 83 describe what the code does, which is already clear from the code itself.

Suggested change
                 Ok(response) => {
-                    // Record the response if recording is enabled
                     if let Some(ref session) = recording_session {
                         if let Ok(json) = serde_json::to_string(&response) {
                             session.record_server_text(&json);
                         }
                     }

83-92: Remove descriptive comment.

Same as above - remove the "Save recording if enabled" comment per coding guidelines.

Suggested change
-    // Save recording if enabled
     if let Some(session) = recording_session {
         if let Some(ref output_dir) = recording_opts.output_dir {
crates/transcribe-proxy/tests/replay.rs (1)

84-87: Close frame assertion may silently pass on missing close.

The if let Some((code, _reason)) pattern means the test passes if no close frame is received. If the proxy fails to forward the close frame, this wouldn't catch it.

Consider asserting close frame presence
-    if let Some((code, _reason)) = close_info {
-        assert_eq!(code, 1000, "Expected normal close code 1000");
-    }
+    let (code, _reason) = close_info.expect("Expected close frame");
+    assert_eq!(code, 1000, "Expected normal close code 1000");
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d49d43 and de097f2.

📒 Files selected for processing (13)
  • crates/transcribe-proxy/src/config.rs (3 hunks)
  • crates/transcribe-proxy/src/routes/streaming.rs (1 hunks)
  • crates/transcribe-proxy/tests/common/fixtures.rs (1 hunks)
  • crates/transcribe-proxy/tests/common/mock_upstream.rs (1 hunks)
  • crates/transcribe-proxy/tests/common/mod.rs (2 hunks)
  • crates/transcribe-proxy/tests/common/recording.rs (1 hunks)
  • crates/transcribe-proxy/tests/fixtures/deepgram_auth_error.jsonl (1 hunks)
  • crates/transcribe-proxy/tests/fixtures/deepgram_normal.jsonl (1 hunks)
  • crates/transcribe-proxy/tests/fixtures/deepgram_rate_limit.jsonl (1 hunks)
  • crates/transcribe-proxy/tests/fixtures/soniox_error.jsonl (1 hunks)
  • crates/transcribe-proxy/tests/fixtures/soniox_normal.jsonl (1 hunks)
  • crates/transcribe-proxy/tests/providers_e2e.rs (4 hunks)
  • crates/transcribe-proxy/tests/replay.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Format using dprint fmt from the root. Do not use cargo fmt.

Files:

  • crates/transcribe-proxy/src/routes/streaming.rs
  • crates/transcribe-proxy/tests/fixtures/soniox_normal.jsonl
  • crates/transcribe-proxy/tests/common/fixtures.rs
  • crates/transcribe-proxy/tests/fixtures/deepgram_rate_limit.jsonl
  • crates/transcribe-proxy/tests/replay.rs
  • crates/transcribe-proxy/src/config.rs
  • crates/transcribe-proxy/tests/fixtures/deepgram_auth_error.jsonl
  • crates/transcribe-proxy/tests/common/mock_upstream.rs
  • crates/transcribe-proxy/tests/fixtures/deepgram_normal.jsonl
  • crates/transcribe-proxy/tests/common/recording.rs
  • crates/transcribe-proxy/tests/fixtures/soniox_error.jsonl
  • crates/transcribe-proxy/tests/common/mod.rs
  • crates/transcribe-proxy/tests/providers_e2e.rs
**/*.{ts,tsx,rs,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

By default, avoid writing comments at all. If you write one, it should be about 'Why', not 'What'.

Files:

  • crates/transcribe-proxy/src/routes/streaming.rs
  • crates/transcribe-proxy/tests/common/fixtures.rs
  • crates/transcribe-proxy/tests/replay.rs
  • crates/transcribe-proxy/src/config.rs
  • crates/transcribe-proxy/tests/common/mock_upstream.rs
  • crates/transcribe-proxy/tests/common/recording.rs
  • crates/transcribe-proxy/tests/common/mod.rs
  • crates/transcribe-proxy/tests/providers_e2e.rs
🧬 Code graph analysis (6)
crates/transcribe-proxy/src/routes/streaming.rs (1)
crates/transcribe-proxy/src/routes/mod.rs (1)
  • provider (23-25)
crates/transcribe-proxy/tests/common/fixtures.rs (1)
crates/transcribe-proxy/tests/common/recording.rs (2)
  • recording (202-204)
  • from_jsonl_file (118-122)
crates/transcribe-proxy/tests/replay.rs (3)
crates/transcribe-proxy/tests/common/fixtures.rs (1)
  • load_fixture (11-14)
crates/transcribe-proxy/tests/common/mock_upstream.rs (3)
  • start_mock_server_with_config (173-198)
  • fast (29-31)
  • default (20-25)
crates/transcribe-proxy/tests/common/mod.rs (1)
  • start_server_with_upstream_url (61-70)
crates/transcribe-proxy/tests/common/recording.rs (2)
crates/transcribe-proxy/src/config.rs (1)
  • new (21-29)
crates/transcribe-proxy/src/routes/mod.rs (1)
  • provider (23-25)
crates/transcribe-proxy/tests/common/mod.rs (6)
crates/transcribe-proxy/tests/common/recording.rs (2)
  • recording (202-204)
  • new (214-219)
crates/transcribe-proxy/tests/common/fixtures.rs (1)
  • load_fixture (11-14)
crates/transcribe-proxy/tests/common/mock_upstream.rs (1)
  • start_mock_server_with_config (173-198)
crates/transcribe-proxy/src/relay/builder.rs (1)
  • upstream_url (112-117)
apps/ai/src/env.rs (1)
  • api_keys (47-49)
crates/transcribe-proxy/src/config.rs (1)
  • new (21-29)
crates/transcribe-proxy/tests/providers_e2e.rs (1)
crates/transcribe-proxy/tests/common/recording.rs (3)
  • recording (202-204)
  • from_env (250-272)
  • new (214-219)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: desktop_ci (linux, depot-ubuntu-24.04-8)
  • GitHub Check: desktop_ci (macos, depot-macos-14)
  • GitHub Check: desktop_ci (linux, depot-ubuntu-22.04-8)
  • GitHub Check: fmt
🔇 Additional comments (22)
crates/transcribe-proxy/tests/common/recording.rs (4)

11-26: LGTM: Well-designed message type system.

The Direction and MessageKind enums provide a clean abstraction for WebSocket message directionality and types. The serde annotations ensure proper JSON serialization for the JSONL fixture format.


28-110: LGTM: Comprehensive message constructors and helpers.

The WsMessage struct and its constructors handle all WebSocket message types appropriately. Base64 encoding for binary data ensures safe storage in JSONL format. The helper methods (is_server_message, is_client_message, decode_binary) provide convenient access patterns.


112-169: LGTM: Robust recording container with flexible I/O.

The WsRecording implementation handles JSONL parsing with proper filtering of comments and empty lines. The transform method provides a functional API for message manipulation, and the iterator helpers support test scenarios efficiently.


241-273: LGTM: Clean environment-driven configuration.

The RecordingOptions::from_env() method provides a clear mechanism to enable recording via the RECORD_FIXTURES environment variable, with appropriate path resolution to the test fixtures directory. The fallback behavior when recording is disabled is sensible.

crates/transcribe-proxy/tests/fixtures/deepgram_auth_error.jsonl (1)

1-2: LGTM: Appropriate auth error fixture.

The fixture correctly models a Deepgram authentication failure with an INVALID_AUTH error message followed by a WebSocket close with code 1008 (Policy Violation), which is the appropriate close code for authentication failures.

crates/transcribe-proxy/tests/fixtures/deepgram_rate_limit.jsonl (1)

1-2: LGTM: Valid rate limit error fixture.

The fixture appropriately represents a Deepgram rate limit scenario with a TOO_MANY_REQUESTS error followed by connection closure. The structure is consistent with other error fixtures.

crates/transcribe-proxy/tests/fixtures/soniox_error.jsonl (1)

1-2: LGTM: Appropriate Soniox error fixture.

The fixture correctly models a Soniox server error with error code 503 and a WebSocket close with code 1011 (Internal Server Error). The error message structure reflects Soniox's API format, which differs from Deepgram's.

crates/transcribe-proxy/tests/fixtures/soniox_normal.jsonl (1)

1-7: LGTM: Comprehensive success scenario fixture.

The fixture provides realistic coverage of a normal Soniox transcription session, including progressive interim results, finalized transcripts, metadata, and proper connection closure with code 1000. This will enable thorough testing of successful transcription flows.

crates/transcribe-proxy/tests/common/fixtures.rs (1)

1-14: LGTM: Clean fixture loading utilities.

The helpers provide a straightforward API for accessing test fixtures. The use of unwrap() on Line 13 is acceptable in test code, as fixture loading failures should cause immediate test failures with clear panic messages.

crates/transcribe-proxy/src/config.rs (1)

17-17: LGTM: Clean configuration extension.

The addition of upstream_urls follows the existing configuration patterns:

  • Properly initialized in the constructor
  • Builder method with_upstream_url is consistent with other with_* methods
  • Accessor upstream_url_for mirrors the existing api_key_for pattern

This provides a clean mechanism for test infrastructure to override upstream endpoints.

Also applies to: 27-27, 46-49, 55-57

crates/transcribe-proxy/src/routes/streaming.rs (1)

41-60: Verify that upstream URL overrides are restricted to test environments.

The custom upstream URL path bypasses the authentication flow, which is appropriate for testing with mock servers. However, ensure that this configuration is only used in test/development environments and cannot be set in production deployments.

Run the following script to check how upstream URLs are configured:

#!/bin/bash
# Description: Check where and how upstream URLs are set to ensure they're only used in tests

# Search for with_upstream_url usage
echo "=== Usage of with_upstream_url ==="
rg -n --type rust 'with_upstream_url' -C 3

# Search for upstream_urls field access
echo -e "\n=== Direct upstream_urls access ==="
rg -n --type rust 'upstream_urls' -C 2

# Check for any production config that might set upstream URLs
echo -e "\n=== Production config files ==="
fd -e toml -e yaml -e json -x cat {} \; -x echo "File: {}" \;
crates/transcribe-proxy/tests/fixtures/deepgram_normal.jsonl (1)

1-7: Well-structured test fixture.

The JSONL fixture correctly models a Deepgram streaming lifecycle with progressive transcript updates, metadata, and a normal close frame. Timestamps are monotonically increasing and the close code 1000 aligns with the standard WebSocket normal closure.

crates/transcribe-proxy/tests/replay.rs (4)

15-27: LGTM!

Clean helper function for establishing WebSocket connections in tests.


29-60: LGTM!

The message collection logic correctly handles text messages, close frames, and errors with a timeout wrapper.


202-229: LGTM!

Good test for verifying message count parity between fixture and proxy output.


231-256: Consider adding assertion after disconnect.

The test verifies the proxy accepts a client disconnect without crashing, but doesn't assert any post-disconnect behavior. This is acceptable for a basic smoke test.

crates/transcribe-proxy/tests/common/mod.rs (2)

3-12: LGTM!

Clean module structure with appropriate re-exports for test utilities.


61-70: LGTM!

Clean helper that properly configures the proxy with a mock API key and upstream URL override for testing.

crates/transcribe-proxy/tests/common/mock_upstream.rs (4)

28-31: Consider clarifying fast() semantics.

fast() currently returns the same as default(). If the intent is "no timing delays", the name is clear. If there's a planned distinction from default, consider documenting it.


112-114: Busy-poll pattern for draining receiver.

The 1ms timeout loop drains incoming client messages. This works but could be simplified with try_next() if available, or the loop could be removed if client messages don't need to be consumed during replay.


121-159: LGTM!

Clean message conversion with proper error handling using thiserror.


195-195: Sleep-based synchronization may be flaky.

The 10ms sleep is a race condition mitigation, but under load the server might not be ready. Consider using a ready signal or retry logic in tests if flakiness occurs.

- Extract duplicated analytics setup into finalize_proxy_builder! macro
- Extract encode_optional_binary helper for ping/pong methods
- Remove redundant MockUpstreamConfig::fast() that just returned default()
- Rename is_server_message/is_client_message to is_from_upstream/is_to_upstream for clarity
- Add TEST_RESPONSE_TIMEOUT constant to replace magic number
- Document single-connection limitation in mock server
- Add tracing::warn for serialization errors in recording

Co-Authored-By: yujonglee <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/transcribe-proxy/tests/replay.rs (1)

86-89: Consider asserting that close frame was received for normal flows.

Using if let Some(...) means the close code assertion is silently skipped when no close frame arrives. For normal transcription tests, you may want to ensure a proper close frame is received.

🔎 Optional: Assert close frame presence for normal flows
-    if let Some((code, _reason)) = close_info {
-        assert_eq!(code, 1000, "Expected normal close code 1000");
-    }
+    let (code, _reason) = close_info.expect("Expected close frame for normal transcription");
+    assert_eq!(code, 1000, "Expected normal close code 1000");
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de097f2 and fc54b14.

📒 Files selected for processing (5)
  • crates/transcribe-proxy/src/routes/streaming.rs (4 hunks)
  • crates/transcribe-proxy/tests/common/mock_upstream.rs (1 hunks)
  • crates/transcribe-proxy/tests/common/recording.rs (1 hunks)
  • crates/transcribe-proxy/tests/providers_e2e.rs (4 hunks)
  • crates/transcribe-proxy/tests/replay.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/transcribe-proxy/tests/common/mock_upstream.rs
  • crates/transcribe-proxy/tests/providers_e2e.rs
🧰 Additional context used
📓 Path-based instructions (2)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Format using dprint fmt from the root. Do not use cargo fmt.

Files:

  • crates/transcribe-proxy/src/routes/streaming.rs
  • crates/transcribe-proxy/tests/replay.rs
  • crates/transcribe-proxy/tests/common/recording.rs
**/*.{ts,tsx,rs,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

By default, avoid writing comments at all. If you write one, it should be about 'Why', not 'What'.

Files:

  • crates/transcribe-proxy/src/routes/streaming.rs
  • crates/transcribe-proxy/tests/replay.rs
  • crates/transcribe-proxy/tests/common/recording.rs
🧬 Code graph analysis (2)
crates/transcribe-proxy/src/routes/streaming.rs (3)
crates/transcribe-proxy/src/relay/builder.rs (3)
  • on_close (98-108)
  • build (164-183)
  • build (215-238)
crates/transcribe-proxy/tests/common/mod.rs (1)
  • report_stt (29-37)
crates/transcribe-proxy/src/upstream_url.rs (1)
  • build (28-50)
crates/transcribe-proxy/tests/common/recording.rs (2)
crates/transcribe-proxy/src/config.rs (1)
  • new (21-29)
crates/transcribe-proxy/src/routes/mod.rs (1)
  • provider (23-25)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Redirect rules - hyprnote-storybook
  • GitHub Check: Header rules - hyprnote-storybook
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote-storybook
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: fmt
  • GitHub Check: desktop_ci (linux, depot-ubuntu-24.04-8)
  • GitHub Check: desktop_ci (macos, depot-macos-14)
  • GitHub Check: desktop_ci (linux, depot-ubuntu-22.04-8)
🔇 Additional comments (15)
crates/transcribe-proxy/src/routes/streaming.rs (3)

121-145: LGTM! Effective refactoring to eliminate duplication.

The macro successfully centralizes analytics integration logic that was previously duplicated in both proxy builder functions. The implementation correctly handles the async closure, clones necessary values, and maintains consistent provider name formatting.


159-159: LGTM! Consistent macro usage.

Both proxy builder functions now use the centralized macro, eliminating the previous inline analytics branches. This improves maintainability and consistency.

Also applies to: 175-175


41-60: Upstream URL feature is test-only and production-safe; no auth bypass risk.

The custom upstream URL path in lines 41-60 only activates in test scenarios. In production code (apps/ai/src/main.rs), SttProxyConfig is instantiated with only API keys, and with_upstream_url() is never called. The upstream_urls HashMap remains empty, so upstream_url_for() always returns None, ensuring authentication logic executes normally in production. The feature is exclusively used for replay testing and mock server scenarios.

crates/transcribe-proxy/tests/replay.rs (6)

17-29: LGTM!

Clean helper function for establishing WebSocket connections with appropriate test error handling.


31-62: LGTM!

Good design: discarding the timeout result allows collecting partial messages when the timeout expires, which is useful for tests that don't expect a clean close.


91-119: LGTM!

Good test coverage for authentication error scenarios with appropriate flexibility for different close code representations.


121-202: LGTM!

Good test coverage for rate limiting, Soniox normal transcription, and Soniox error scenarios. The tests appropriately check for provider-specific error messages and close codes.


204-231: LGTM!

Good approach using the fixture's message count as the expected value to verify the proxy forwards all messages without loss.


233-258: LGTM!

The test verifies that the proxy handles client disconnect without crashing. Using timing configuration ensures messages are still in-flight when disconnect occurs.

crates/transcribe-proxy/tests/common/recording.rs (6)

1-34: LGTM!

Clean definitions with appropriate serde configuration. The tagged enum approach for MessageKind makes the JSONL format self-describing.


36-110: LGTM!

Well-structured message representation with convenient constructors for each message type. The decode_binary returning a Result properly propagates base64 decode errors.


112-169: LGTM!

Good JSONL handling with support for comments and empty lines. The transform method provides useful flexibility for fixture manipulation.


171-205: LGTM!

Clean recorder implementation. The u128 to u64 cast for elapsed milliseconds is safe for any reasonable test duration.


207-239: LGTM!

Thread-safe recording session with proper Arc/Mutex usage. The .unwrap() on mutex locks is acceptable for test utilities since poisoned mutexes indicate prior panics.


241-273: LGTM!

Good approach using env!("CARGO_MANIFEST_DIR") for compile-time resolution of the fixtures directory. Environment variable handling is robust with multiple accepted values.

@yujonglee yujonglee merged commit 0eeacab into main Dec 20, 2025
17 checks passed
@yujonglee yujonglee deleted the transcribe-proxy-replay branch December 20, 2025 10:35
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