Skip to content

feat: add ASR and LLM connections - #25

Merged
LRainner merged 4 commits into
masterfrom
feat/asr-llm-connections
Jun 19, 2026
Merged

feat: add ASR and LLM connections#25
LRainner merged 4 commits into
masterfrom
feat/asr-llm-connections

Conversation

@LRainner

Copy link
Copy Markdown
Owner

Summary

  • Add independent ASR and LLM connection lists with active connection selection
  • Update desktop Settings to add, delete, rename, and switch ASR/LLM connections
  • Preserve legacy config compatibility and update example config

Closes #24

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for managing multiple independent ASR and LLM API connections, allowing users to save, switch, and configure multiple providers in the UI. The backend configuration has been updated to support connection lists with automatic migration from legacy single-value settings, accompanied by robust unit tests. Feedback on these changes highlights opportunities to improve robustness and compatibility, including adding a safety guard for uninitialized configurations in the frontend, trimming input values (endpoints, models, API keys) on both sides to prevent whitespace issues, replacing unstable Rust let_chains with standard nested if let statements for stable compiler compatibility, and optimizing struct cloning in the configuration normalization logic.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +1521 to +1522
function ensureConnectionShape() {
if (!currentConfig.asr) currentConfig.asr = {};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Add a guard to prevent a TypeError if currentConfig is null or undefined when ensureConnectionShape is called (for example, if the configuration fails to load or if an event handler triggers before initialization completes).

Suggested change
function ensureConnectionShape() {
if (!currentConfig.asr) currentConfig.asr = {};
function ensureConnectionShape() {
if (!currentConfig) return;
if (!currentConfig.asr) currentConfig.asr = {};

Comment thread apps/desktop/frontend/index.html Outdated
Comment on lines +1610 to +1631
function saveAsrConnectionFields(connectionId = currentConfig.asr.active_connection) {
ensureConnectionShape();
const connection = currentConfig.asr.connections.find(c => c.id === connectionId);
if (!connection) return;
connection.name = document.getElementById('asr-connection-name').value || connection.id;
connection.provider = document.getElementById('asr-provider').value || 'mock';
connection.endpoint = document.getElementById('asr-endpoint').value || null;
connection.api_key = document.getElementById('asr-api-key').value || null;
connection.model = document.getElementById('asr-model').value || null;
connection.language = document.getElementById('asr-language').value || null;
}

function saveLlmConnectionFields(connectionId = currentConfig.llm.active_connection) {
ensureConnectionShape();
const connection = currentConfig.llm.connections.find(c => c.id === connectionId);
if (!connection) return;
connection.name = document.getElementById('llm-connection-name').value || connection.id;
connection.provider = document.getElementById('llm-provider').value || 'mock';
connection.endpoint = document.getElementById('llm-endpoint').value || null;
connection.api_key = document.getElementById('llm-api-key').value || null;
connection.model = document.getElementById('llm-model').value || null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Trimming the input values before saving them to the connection object is highly recommended. Since isValidEndpoint trims the endpoint value during validation, not trimming it here can lead to saving values with leading/trailing whitespaces (e.g., " http://api.openai.com/v1 "), which might cause URI parsing or connection failures in the Rust backend.

    function saveAsrConnectionFields(connectionId = currentConfig.asr.active_connection) {
      ensureConnectionShape();
      const connection = currentConfig.asr.connections.find(c => c.id === connectionId);
      if (!connection) return;
      connection.name = document.getElementById('asr-connection-name').value.trim() || connection.id;
      connection.provider = document.getElementById('asr-provider').value || 'mock';
      connection.endpoint = document.getElementById('asr-endpoint').value.trim() || null;
      connection.api_key = document.getElementById('asr-api-key').value.trim() || null;
      connection.model = document.getElementById('asr-model').value.trim() || null;
      connection.language = document.getElementById('asr-language').value.trim() || null;
    }

    function saveLlmConnectionFields(connectionId = currentConfig.llm.active_connection) {
      ensureConnectionShape();
      const connection = currentConfig.llm.connections.find(c => c.id === connectionId);
      if (!connection) return;
      connection.name = document.getElementById('llm-connection-name').value.trim() || connection.id;
      connection.provider = document.getElementById('llm-provider').value || 'mock';
      connection.endpoint = document.getElementById('llm-endpoint').value.trim() || null;
      connection.api_key = document.getElementById('llm-api-key').value.trim() || null;
      connection.model = document.getElementById('llm-model').value.trim() || null;
    }

Comment thread crates/config/src/lib.rs
Comment on lines +179 to +186
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The use of let_chains (e.g., && let Some(first) = ...) is an unstable Rust feature that requires a nightly compiler and the #![feature(let_chains)] attribute. To ensure compatibility with the stable Rust compiler and improve portability, it is better to use standard nested if let statements.

Suggested change
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
{
if let Some(first) = self.connections.first() {
self.active_connection = first.id.clone();
}
}

Comment thread crates/config/src/lib.rs
Comment on lines +188 to +194
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
self.language = active.language;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using .cloned() on active_connection_config() clones the entire AsrConnection struct, only to immediately discard most of its fields. It is more idiomatic and efficient to borrow the active connection and clone only the individual fields that are needed.

Suggested change
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
self.language = active.language;
}
if let Some(active) = self.active_connection_config() {
self.provider = active.provider.clone();
self.endpoint = active.endpoint.clone();
self.model = active.model.clone();
self.api_key = active.api_key.clone();
self.language = active.language.clone();
}

Comment thread crates/config/src/lib.rs
Comment on lines +226 to +233
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The use of let_chains (e.g., && let Some(first) = ...) is an unstable Rust feature that requires a nightly compiler and the #![feature(let_chains)] attribute. To ensure compatibility with the stable Rust compiler and improve portability, it is better to use standard nested if let statements.

Suggested change
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
{
if let Some(first) = self.connections.first() {
self.active_connection = first.id.clone();
}
}

Comment thread crates/config/src/lib.rs
Comment on lines +235 to +240
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using .cloned() on active_connection_config() clones the entire LlmConnection struct, only to immediately discard most of its fields. It is more idiomatic and efficient to borrow the active connection and clone only the individual fields that are needed.

Suggested change
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
}
if let Some(active) = self.active_connection_config() {
self.provider = active.provider.clone();
self.endpoint = active.endpoint.clone();
self.model = active.model.clone();
self.api_key = active.api_key.clone();
}

Comment thread crates/core/src/lib.rs
Comment on lines +71 to 74
let endpoint = connection
.endpoint
.as_deref()
.unwrap_or("https://api.openai.com/v1");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The endpoint field is not trimmed or validated for empty strings on the Rust side. If a user accidentally saves a configuration with leading or trailing whitespaces (which is a common copy-paste error), it can cause URI parsing or connection failures. Trimming and filtering out empty strings makes the provider creation much more robust.

            let endpoint = connection
                .endpoint
                .as_deref()
                .map(|s| s.trim())
                .filter(|s| !s.is_empty())
                .unwrap_or("https://api.openai.com/v1");

Comment thread crates/core/src/lib.rs Outdated
.filter(|s| !s.is_empty())
});
let model = config.asr.model.as_deref().unwrap_or("whisper-1");
let model = connection.model.as_deref().unwrap_or("whisper-1");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The model field is not trimmed or validated for empty strings on the Rust side. Trimming and filtering out empty strings makes the provider creation much more robust against accidental whitespace in the configuration.

            let model = connection
                .model
                .as_deref()
                .map(|s| s.trim())
                .filter(|s| !s.is_empty())
                .unwrap_or("whisper-1");

Comment thread crates/core/src/lib.rs
Comment on lines +117 to 120
let endpoint = connection
.endpoint
.as_deref()
.unwrap_or("https://api.openai.com/v1");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The endpoint field is not trimmed or validated for empty strings on the Rust side. If a user accidentally saves a configuration with leading or trailing whitespaces (which is a common copy-paste error), it can cause URI parsing or connection failures. Trimming and filtering out empty strings makes the provider creation much more robust.

            let endpoint = connection
                .endpoint
                .as_deref()
                .map(|s| s.trim())
                .filter(|s| !s.is_empty())
                .unwrap_or("https://api.openai.com/v1");

Comment thread crates/core/src/lib.rs Outdated
});

let model = config.llm.model.as_deref().unwrap_or("gpt-4o-mini");
let model = connection.model.as_deref().unwrap_or("gpt-4o-mini");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The model field is not trimmed or validated for empty strings on the Rust side. Trimming and filtering out empty strings makes the provider creation much more robust against accidental whitespace in the configuration.

            let model = connection
                .model
                .as_deref()
                .map(|s| s.trim())
                .filter(|s| !s.is_empty())
                .unwrap_or("gpt-4o-mini");

Co-Authored-By: Claude <noreply@anthropic.com>
@LRainner

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the ability to save, manage, and switch between multiple independent ASR and LLM API connections, migrating existing single-value configurations automatically. The changes span the frontend UI, localization files, and backend Rust configuration management. Feedback on these changes highlights potential TypeErrors in the frontend JavaScript when resolving active connections or loading fields, the use of the unstable Rust let_chains feature which breaks stable compiler compatibility, and incomplete Chinese translations in the localization files.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread apps/desktop/frontend/index.html Outdated
Comment on lines +1612 to +1615
function saveAsrConnectionFields(connectionId = currentConfig.asr.active_connection) {
if (!ensureConnectionShape()) return;
const connection = currentConfig.asr.connections.find(c => c.id === connectionId);
if (!connection) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Evaluating currentConfig.asr.active_connection as a default parameter will throw a TypeError if currentConfig is null at call time. This bypasses the ensureConnectionShape() safety check inside the function body. It is safer to resolve the active connection ID inside the function after the safety check.

Suggested change
function saveAsrConnectionFields(connectionId = currentConfig.asr.active_connection) {
if (!ensureConnectionShape()) return;
const connection = currentConfig.asr.connections.find(c => c.id === connectionId);
if (!connection) return;
function saveAsrConnectionFields(connectionId) {
if (!ensureConnectionShape()) return;
const id = connectionId || currentConfig.asr.active_connection;
const connection = currentConfig.asr.connections.find(c => c.id === id);
if (!connection) return;

Comment thread apps/desktop/frontend/index.html Outdated
Comment on lines +1624 to +1627
function saveLlmConnectionFields(connectionId = currentConfig.llm.active_connection) {
if (!ensureConnectionShape()) return;
const connection = currentConfig.llm.connections.find(c => c.id === connectionId);
if (!connection) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Evaluating currentConfig.llm.active_connection as a default parameter will throw a TypeError if currentConfig is null at call time. This bypasses the ensureConnectionShape() safety check inside the function body. It is safer to resolve the active connection ID inside the function after the safety check.

Suggested change
function saveLlmConnectionFields(connectionId = currentConfig.llm.active_connection) {
if (!ensureConnectionShape()) return;
const connection = currentConfig.llm.connections.find(c => c.id === connectionId);
if (!connection) return;
function saveLlmConnectionFields(connectionId) {
if (!ensureConnectionShape()) return;
const id = connectionId || currentConfig.llm.active_connection;
const connection = currentConfig.llm.connections.find(c => c.id === id);
if (!connection) return;

Comment on lines +1595 to +1596
function loadAsrConnectionFields(connection) {
document.getElementById('asr-connection-name').value = connection.name || '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Add a defensive guard to prevent a TypeError if connection is null or undefined when this function is called.

Suggested change
function loadAsrConnectionFields(connection) {
document.getElementById('asr-connection-name').value = connection.name || '';
function loadAsrConnectionFields(connection) {
if (!connection) return;
document.getElementById('asr-connection-name').value = connection.name || '';

Comment on lines +1604 to +1605
function loadLlmConnectionFields(connection) {
document.getElementById('llm-connection-name').value = connection.name || '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Add a defensive guard to prevent a TypeError if connection is null or undefined when this function is called.

Suggested change
function loadLlmConnectionFields(connection) {
document.getElementById('llm-connection-name').value = connection.name || '';
function loadLlmConnectionFields(connection) {
if (!connection) return;
document.getElementById('llm-connection-name').value = connection.name || '';

Comment thread crates/config/src/lib.rs
Comment on lines +179 to +186
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The let_chains feature (&& let Some(...)) is currently unstable in Rust and requires a nightly compiler. To maintain compatibility with stable Rust, rewrite this using nested if let statements.

Suggested change
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
{
if let Some(first) = self.connections.first() {
self.active_connection = first.id.clone();
}
}

Comment thread crates/config/src/lib.rs
Comment on lines +226 to +233
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The let_chains feature (&& let Some(...)) is currently unstable in Rust and requires a nightly compiler. To maintain compatibility with stable Rust, rewrite this using nested if let statements.

Suggested change
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
{
if let Some(first) = self.connections.first() {
self.active_connection = first.id.clone();
}
}

Comment on lines +79 to +80
"settings.asr_connections": "ASR Connections",
"settings.llm_connections": "LLM Connections",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Translate the connection labels to Chinese to ensure complete localization of the user interface.

Suggested change
"settings.asr_connections": "ASR Connections",
"settings.llm_connections": "LLM Connections",
"settings.asr_connections": "ASR 连接",
"settings.llm_connections": "LLM 连接",

Comment on lines +87 to +88
"settings.new_asr_connection": "新的 ASR Connection",
"settings.new_llm_connection": "新的 LLM Connection",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Translate the connection labels to Chinese to ensure complete localization of the user interface.

Suggested change
"settings.new_asr_connection": "新的 ASR Connection",
"settings.new_llm_connection": "新的 LLM Connection",
"settings.new_asr_connection": "新的 ASR 连接",
"settings.new_llm_connection": "新的 LLM 连接",

Co-Authored-By: Claude <noreply@anthropic.com>
@LRainner

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for managing multiple independent ASR and LLM API connections, allowing users to save, delete, and switch between different configurations. The changes span the frontend UI, localization files, configuration structs, and core provider initialization logic, including backward-compatible migration for legacy single-value configurations. The review feedback suggests several robustness improvements: using window.crypto instead of the global crypto object in the frontend to prevent potential ReferenceError in older webviews, and trimming/filtering whitespace from provider and language configuration strings in the Rust core to prevent matching or initialization failures.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +1516 to +1519
function createConnectionId(prefix) {
if (crypto?.randomUUID) return `${prefix}-${crypto.randomUUID()}`;
return `${prefix}-${Date.now()}`;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Referencing the global crypto object directly can throw a ReferenceError if it is not defined in the environment (e.g., in older webviews or specific non-browser environments). Referencing it via window.crypto is safer as it will safely evaluate to undefined instead of throwing an error.

Suggested change
function createConnectionId(prefix) {
if (crypto?.randomUUID) return `${prefix}-${crypto.randomUUID()}`;
return `${prefix}-${Date.now()}`;
}
function createConnectionId(prefix) {
if (window.crypto?.randomUUID) return `${prefix}-${window.crypto.randomUUID()}`;
return `${prefix}-${Date.now()}`;
}

Comment thread crates/core/src/lib.rs Outdated
.active_connection_config()
.ok_or_else(|| anyhow::anyhow!("active ASR connection not found"))?;

match connection.provider.as_str() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Trimming the provider string before matching ensures that any accidental leading or trailing whitespace in the configuration file or user input does not cause the provider matching to fail.

Suggested change
match connection.provider.as_str() {
match connection.provider.trim() {

Comment thread crates/core/src/lib.rs Outdated
Comment on lines 101 to 103
if let Some(lang) = &connection.language {
provider = provider.with_language(lang.clone());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Trimming and filtering the language string ensures that empty or whitespace-only language codes are not passed to the ASR provider, which could cause errors or unexpected behavior.

            if let Some(lang) = connection
                .language
                .as_deref()
                .map(|s| s.trim())
                .filter(|s| !s.is_empty())
            {
                provider = provider.with_language(lang.to_string());
            }

Comment thread crates/core/src/lib.rs Outdated
.active_connection_config()
.ok_or_else(|| anyhow::anyhow!("active LLM connection not found"))?;

match connection.provider.as_str() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Trimming the provider string before matching ensures that any accidental leading or trailing whitespace in the configuration file or user input does not cause the provider matching to fail.

Suggested change
match connection.provider.as_str() {
match connection.provider.trim() {

Co-Authored-By: Claude <noreply@anthropic.com>
@LRainner

Copy link
Copy Markdown
Owner Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for multiple independent ASR and LLM API connections, allowing users to save, manage, and switch between them in the settings. It updates the configuration structures, adds normalization logic to migrate legacy single-value configurations, and implements the corresponding frontend UI and state management. Feedback on the changes highlights a compatibility issue where the unstable let_chains feature (&& let) is used, which will cause compilation errors on stable Rust toolchains. Additionally, the reviewer pointed out inefficient cloning of entire connection structs during normalization and suggested cloning only the required fields instead.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/config/src/lib.rs
Comment on lines +179 to +186
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Using the unstable let_chains feature (&& let) will cause compilation errors on stable Rust toolchains. It is highly recommended to rewrite this using standard nested if let statements to ensure compatibility with stable Rust.

Suggested change
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
{
if let Some(first) = self.connections.first() {
self.active_connection = first.id.clone();
}
}

Comment thread crates/config/src/lib.rs
Comment on lines +226 to +233
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Using the unstable let_chains feature (&& let) will cause compilation errors on stable Rust toolchains. It is highly recommended to rewrite this using standard nested if let statements to ensure compatibility with stable Rust.

Suggested change
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
&& let Some(first) = self.connections.first()
{
self.active_connection = first.id.clone();
}
if !self
.connections
.iter()
.any(|connection| connection.id == self.active_connection)
{
if let Some(first) = self.connections.first() {
self.active_connection = first.id.clone();
}
}

Comment thread crates/config/src/lib.rs
Comment on lines +188 to +194
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
self.language = active.language;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Cloning the entire AsrConnection struct is unnecessary and inefficient because we only need to copy a subset of its fields to self. We can avoid this overhead by referencing the active connection directly and cloning only the required fields.

Suggested change
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
self.language = active.language;
}
if let Some(active) = self.active_connection_config() {
self.provider = active.provider.clone();
self.endpoint = active.endpoint.clone();
self.model = active.model.clone();
self.api_key = active.api_key.clone();
self.language = active.language.clone();
}

Comment thread crates/config/src/lib.rs
Comment on lines +235 to +240
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Cloning the entire LlmConnection struct is unnecessary and inefficient because we only need to copy a subset of its fields to self. We can avoid this overhead by referencing the active connection directly and cloning only the required fields.

Suggested change
if let Some(active) = self.active_connection_config().cloned() {
self.provider = active.provider;
self.endpoint = active.endpoint;
self.model = active.model;
self.api_key = active.api_key;
}
if let Some(active) = self.active_connection_config() {
self.provider = active.provider.clone();
self.endpoint = active.endpoint.clone();
self.model = active.model.clone();
self.api_key = active.api_key.clone();
}

@LRainner
LRainner merged commit abe604c into master Jun 19, 2026
9 of 10 checks passed
@LRainner
LRainner deleted the feat/asr-llm-connections branch June 19, 2026 01:55
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.

重新设计 ASR/LLM Connection 配置管理

1 participant