Skip to content

feat(settings): add end-to-end ASR provider validation#251

Merged
H-Chris233 merged 6 commits into
Open-Less:mainfrom
H-Chris233:feat/asr-e2e-validation
May 4, 2026
Merged

feat(settings): add end-to-end ASR provider validation#251
H-Chris233 merged 6 commits into
Open-Less:mainfrom
H-Chris233:feat/asr-e2e-validation

Conversation

@H-Chris233
Copy link
Copy Markdown
Collaborator

@H-Chris233 H-Chris233 commented May 4, 2026

User description

Summary

  • add ASR provider validation parity with LLM validation in Settings
  • move ASR validation from model-list reachability to a real /audio/transcriptions chain check with the selected model
  • harden validation path: endpoint normalization, HTTPS guard (localhost exception), response-size cap, and stable backend error codes
  • map new ASR validation errors to i18n messages in Settings

Validation

  • npm run build
  • cargo check -q

Closes #242


PR Type

Enhancement, Tests


Description

  • Add end‑to‑end ASR connection check via /audio/transcriptions with a silence WAV

  • Harden validation: URL normalisation, HTTPS enforcement (localhost excluded), response‑size cap

  • Map new ASR validation error codes to i18n strings in Settings UI

  • Add unit tests for asr_transcriptions_url and enable reqwest stream feature


Diagram Walkthrough

flowchart LR
  A["validate_asr_provider"] --> B["read config & model"]
  B --> C["asr_transcriptions_url"]
  C --> D["POST /audio/transcriptions"]
  D --> E["check status & response size"]
  E --> F["parse JSON & verify text field"]
  F --> G["map result to i18n error code"]
  G --> H["display message in Settings UI"]
Loading

File Walkthrough

Relevant files
Enhancement
commands.rs
Add end‑to‑end ASR validation via transcription endpoint 

openless-all/app/src-tauri/src/commands.rs

  • Replace trivial ASR validation with validate_asr_provider that
    performs a real transcription call
  • Implement validate_asr_transcription: sends a 250 ms silence WAV,
    checks HTTP status, enforces a 1 MB response cap, and verifies the
    JSON text field
  • Add asr_transcriptions_url to normalise base URL paths and enforce
    HTTPS (except localhost)
  • Add encode_wav_16k_mono_silence helper to create the test audio
    payload
  • Include test cases for asr_transcriptions_url covering different input
    URL patterns
+146/-8 
en.ts
Add English i18n for ASR validation errors                             

openless-all/app/src/i18n/en.ts

  • Add English translations for new ASR‑specific validation errors
    (endpoint HTTPS requirement, invalid JSON, missing text field,
    response too large)
+5/-0     
zh-CN.ts
Add Chinese i18n for ASR validation errors                             

openless-all/app/src/i18n/zh-CN.ts

  • Add Chinese translations for the same ASR validation error messages
+5/-0     
Settings.tsx
Map new ASR validation errors to Settings UI messages       

openless-all/app/src/pages/Settings.tsx

  • Treat asrModelMissing the same as llmModelMissing during validation
  • Handle modelsEmpty error uniformly for both LLM and ASR providers
  • Extend providerErrorMessage to map the new stable backend error codes
    to i18n keys
+13/-1   
Dependencies
Cargo.toml
Enable reqwest stream feature for ASR response reading     

openless-all/app/src-tauri/Cargo.toml

  • Add stream feature to reqwest dependency for streaming response body
    during ASR validation
+1/-1     

H-Chris233 added 3 commits May 4, 2026 20:27
Issue Open-Less#242 asks ASR to reach parity with LLM availability checks. Validation now requires a configured ASR model and verifies it exists in the provider model list, instead of only checking endpoint/auth reachability.

Constraint: Keep existing settings flow and IPC shape with minimal UI change

Rejected: Add a new ASR test-audio transcription request | adds latency and provider-specific request complexity

Confidence: high

Scope-risk: narrow

Directive: Keep validate and fetch-models semantics aligned; validate should fail when configured model cannot actually be selected

Tested: npm run build; cargo check -q

Not-tested: Manual Settings UI interaction against live third-party ASR endpoints
ASR validation now runs one end-to-end /audio/transcriptions request with the currently selected model and a tiny bundled silence WAV payload. This verifies endpoint, auth, model routing, and response schema in one pass instead of model-list reachability only.

Constraint: Keep UI/API contract unchanged and avoid touching recording pipeline

Rejected: Reuse live microphone capture in settings validation | invasive and non-deterministic for quick checks

Confidence: high

Scope-risk: narrow

Directive: Preserve providerHttpStatus:* error marker so frontend can keep status-specific guidance

Tested: npm run build; cargo check -q

Not-tested: Live validation against every third-party ASR provider implementation
Follow-up fixes from dual review keep the new end-to-end ASR check while removing compatibility and robustness regressions: normalize transcription endpoint URL, enforce HTTPS except localhost, cap response size, and switch to stable backend error codes mapped in i18n.

Constraint: Preserve issue Open-Less#242 full-chain validation behavior with minimal surface change

Rejected: Revert to model-list-only validation | no longer verifies real transcription route

Confidence: high

Scope-risk: narrow

Directive: Keep providerHttpStatus:* and stable error-code contract synchronized with Settings error mapping

Tested: npm run build; cargo check -q

Not-tested: Manual validation against all third-party ASR endpoints
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73dbd4cef7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +300 to +303
if trimmed.ends_with("/audio/transcriptions") {
return Ok(trimmed.to_string());
}
Ok(format!("{trimmed}/audio/transcriptions"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize ASR base URLs before appending transcription path

asr_transcriptions_url only preserves URLs that already end with /audio/transcriptions; otherwise it blindly appends that suffix. This breaks validation for endpoint formats the app already accepts elsewhere (for example /chat/completions or /models, which models_url normalizes), producing invalid paths like .../chat/completions/audio/transcriptions and causing false validation failures for otherwise working provider configs.

Useful? React with 👍 / 👎.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

PR Reviewer Guide 🔍

(Review updated until commit cb2eb8e)

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis ✅

242 - Fully compliant

Compliant requirements:

  • Add ASR provider validation feature similar to the existing LLM validation
  • The validation should perform an end‑to‑end check (e.g., using the real /audio/transcriptions endpoint)
  • Include proper error handling and user‑facing messages for ASR validation failures
  • Support internationalisation (i18n) for the new messages
⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

Some OpenAI-compatible deployments expose ASR under a base URL that already ends with /audio. ASR validation now treats that as a valid prefix and appends only /transcriptions to avoid generating /audio/audio/transcriptions.

Constraint: Keep ASR validation URL normalization conservative and backwards-compatible

Rejected: Full URL path rewrite heuristics | risk of breaking custom reverse-proxy layouts

Confidence: high

Scope-risk: narrow

Tested: cargo test -q
@H-Chris233
Copy link
Copy Markdown
Collaborator Author

已按 review 建议修复:asr_transcriptions_url 现在支持 base 以 /audio 结尾的配置,避免生成 /audio/audio/transcriptions,并补了对应单测。commit: fd60f81

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fd60f815c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +300 to +304
if trimmed.ends_with("/audio/transcriptions") {
return Ok(trimmed.to_string());
}
if trimmed.ends_with("/audio") {
return Ok(format!("{trimmed}/transcriptions"));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Align ASR endpoint normalization with runtime request path

asr_transcriptions_url now treats endpoints that already end in /audio or /audio/transcriptions as valid for connection checks, but the production transcription path still appends "/audio/transcriptions" unconditionally in src-tauri/src/asr/whisper.rs (format!("{}/audio/transcriptions", base_url)). That means validation can succeed for values like https://host/v1/audio/transcriptions while real dictation later calls .../audio/transcriptions/audio/transcriptions and fails, producing a false-positive health check for users.

Useful? React with 👍 / 👎.

if (message === 'providerResponseTooLarge') return t('settings.providers.responseTooLarge');
if (message === 'asrInvalidJson') return t('settings.providers.asrInvalidJson');
if (message === 'asrMissingTextField') return t('settings.providers.asrMissingTextField');
if (message === 'providerNetworkError') return t('common.networkError');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Define translation for mapped network validation error

providerErrorMessage maps providerNetworkError to t('common.networkError'), but neither en.ts nor zh-CN.ts defines common.networkError. When ASR validation hits a network failure, the UI will show a raw missing-key string instead of a user-friendly message, so the new error-code mapping degrades the settings UX in a common failure path.

Useful? React with 👍 / 👎.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Persistent review updated to latest commit fd60f81

Addresses review feedback: ASR validation now recognizes OpenAI-style /chat/completions endpoints when building the /audio/transcriptions URL, and response-size protection is enforced while streaming the body instead of after buffering it all.

Constraint: Keep ASR validation behavior provider-agnostic and minimal in scope

Rejected: Heuristic URL rewrites beyond known suffixes | risk of breaking custom reverse proxies

Confidence: high

Scope-risk: narrow

Directive: If changing reqwest features, keep Cargo.lock in sync and re-run tests

Tested: cargo test -q
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@H-Chris233
Copy link
Copy Markdown
Collaborator Author

已处理 reviewer guide 的两点:

  1. URL normalization:asr_transcriptions_url 现在支持 OpenAI 风格 /chat/completions endpoint(会改写为 /audio/transcriptions),并补单测。
  2. Memory cap:响应体改为 bytes_stream 边读边限长,避免在无 Content-Length 的 chunked 大响应下先整体缓冲导致内存 DoS。
    同时为 reqwest 开启 stream feature。commit: df2d51e

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Persistent review updated to latest commit df2d51e

ASR validation URL normalization now edits the parsed URL path instead of string-appending to the raw endpoint, so endpoints with query parameters (e.g. api-version) remain valid after adding /audio/transcriptions.

Constraint: Keep endpoint normalization minimal and avoid changing query/fragment semantics

Rejected: Drop query parameters during validation | would break Azure-style OpenAI-compatible deployments

Confidence: high

Scope-risk: narrow

Tested: cargo test -q
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@H-Chris233
Copy link
Copy Markdown
Collaborator Author

已修复 URL Parsing:asr_transcriptions_url 现在基于 Url 解析后仅修改 path(保留 query/fragment),避免带 query 的 endpoint 被拼坏;并补了 query 参数的单测。commit: cb2eb8e

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Persistent review updated to latest commit cb2eb8e

@H-Chris233 H-Chris233 merged commit 88452cb into Open-Less:main May 4, 2026
2 checks passed
@H-Chris233 H-Chris233 deleted the feat/asr-e2e-validation branch May 4, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ASR)ASR模型验证

1 participant