Skip to content

fix(llm): 允许无密钥 LLM 配置#193

Merged
H-Chris233 merged 4 commits into
Open-Less:mainfrom
H-Chris233:main
May 3, 2026
Merged

fix(llm): 允许无密钥 LLM 配置#193
H-Chris233 merged 4 commits into
Open-Less:mainfrom
H-Chris233:main

Conversation

@H-Chris233
Copy link
Copy Markdown
Collaborator

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

User description

摘要

Fixes #192

本 PR 修复 LLM 配置时 API Key 被强制要求的问题。

部分本地或自托管 OpenAI-compatible LLM endpoint 不需要 API Key,例如本地 11443 类服务或内网代理服务。此前 LLM 验证和运行时 polish 路径会把空 API Key 直接视为凭据缺失,导致这类 endpoint 即使本身可用,也会在客户端被提前判定为配置错误。

本次改动允许 OpenAI-compatible LLM 在 API Key 为空时继续验证和运行。API Key 为空时不会发送 Authorization header;API Key 非空时继续发送 Authorization: Bearer ...。ASR 路径仍保持 API Key 必填,避免把 LLM 的无密钥兼容逻辑扩散到语音识别服务。

修复 / 新增 / 改进

  • LLM provider 配置读取时不再强制要求 API Key。

  • ASR provider 配置读取仍保持 API Key 必填。

  • LLM polish 非流式请求中:

    • API Key 为空时不发送 Authorization header
    • API Key 非空时继续发送 Authorization: Bearer ...
  • LLM streaming 请求中:

    • API Key 为空时不发送 Authorization header
    • API Key 非空时继续发送 Authorization: Bearer ...
  • coordinator 运行时 polish / translate / chat 路径不再因为 LLM API Key 为空提前失败。

  • 设置页 LLM 验证可以覆盖无密钥 OpenAI-compatible endpoint。

  • 保持现有 HTTP status 错误映射不变。

  • 新增测试覆盖:

    • API Key 为空时,chat completion 请求不会包含 Authorization: Bearer
    • 无密钥请求成功时仍能返回最终文本

兼容

  • 不包含:

    • 不放宽 ASR API Key 要求。
    • 不改变凭据存储格式。
    • 不改变 provider 配置结构。
    • 不改变已有带 API Key endpoint 的请求行为。
    • 不修改 HTTP status 错误映射。
    • 不引入新依赖。
    • 不在日志或 UI 中打印明文 API Key。
  • 对现有用户 / 本地环境 / 构建流程的影响:

    • 使用云端 OpenAI-compatible LLM 且已配置 API Key 的用户无行为变化。
    • 使用本地或自托管无密钥 LLM endpoint 的用户,可以在 API Key 留空时完成验证和 polish 调用。
    • ASR 仍要求 API Key。
    • 构建流程无变化。

测试计划

  • 命令:npm run build

  • 结果:通过

  • 证据路径:本地构建输出

  • 命令:cargo test --lib

  • 结果:通过

  • 证据路径:本地测试输出

  • 真实无密钥 OpenAI-compatible endpoint 联调

  • 说明:未在测试 harness 之外使用真实 keyless endpoint 验证 live 行为。

主要改动文件

  • openless-all/app/src-tauri/src/commands.rs
  • openless-all/app/src-tauri/src/coordinator.rs
  • openless-all/app/src-tauri/src/polish.rs

备注

本 PR 只允许 OpenAI-compatible LLM 路径接受空 API Key。空 Key 时不会伪造 Authorization header;非空 Key 时仍沿用现有 Bearer 鉴权行为。ASR 仍保持密钥必填。


PR Type

Bug fix, Tests


Description

  • Allow empty API key for LLM providers in config, HTTP requests, and coordinator flows

    • read_openai_provider_config uses api_key_required flag (false for LLM, true for ASR)
    • fetch_provider_models and polish requests omit Authorization header when key blank
  • Coordinator Ark content paths now require either API key or custom endpoint to prevent leaks

    • resolve_ark_endpoint errors if key empty and no custom endpoint provided
  • Retain mandatory API key for ASR provider

  • Add unit tests for keyless LLM headers, endpoint policy, and successful completion


Diagram Walkthrough

flowchart LR
    A["read_openai_provider_config"] -->|"llm: key optional"| B["LLM provider"]
    A -->|"asr: key required"| C["ASR provider unchanged"]
    B --> D["HTTP requests: omit Authorization if key empty"]
    B --> E["coordinator: resolve_ark_endpoint blocks empty key without custom endpoint"]
    D --> F["Tests check header omission"]
    E --> G["Tests check endpoint policy"]
Loading

File Walkthrough

Relevant files
Bug fix
commands.rs
Make LLM API key optional in provider config and model fetch

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

  • Add api_key_required flag to differentiate LLM (false) and ASR (true)
    provider config
  • Conditionally check for empty API key only when required
  • In fetch_provider_models, set Authorization header only if API key is
    non-empty
  • Add test verifying Authorization header omitted when API key is absent
+72/-17 
polish.rs
Remove mandatory key check, conditionally send Authorization header

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

  • Remove MissingCredentials early return in chat_completion and
    answer_chat_streaming
  • Conditionally add Authorization header only if API key is non-empty
  • Add test that chat completion succeeds and omits Authorization when
    key empty
+70/-18 
Error handling
coordinator.rs
Guard Ark content flows, allow keyless with custom endpoint

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

  • Remove early bail on empty API key in polish, translate, and QA chat
    paths
  • Introduce resolve_ark_endpoint that allows keyless only when custom
    endpoint is provided
  • Block access to default Ark endpoint when API key empty to prevent
    content leaks
  • Add tests for endpoint resolution policy (blank key rejected, custom
    endpoint allowed)
+46/-19 

Some OpenAI-compatible LLM endpoints do not require an API key, so the LLM validation and runtime polish paths should not invent one or fail early when the key field is blank. The client now omits the Authorization header when the key is empty, the coordinator stops treating a blank LLM key as a hard error, and the settings validation continues to distinguish a missing model from a genuinely failed connection.

Constraint: Keep the change minimal and preserve the existing HTTP-status error mapping.
Rejected: Keep key-required behavior for all LLM endpoints | it mislabels keyless endpoints such as local 11443-style servers as invalid.
Confidence: high
Scope-risk: moderate
Directive: Empty LLM API keys are allowed only for the OpenAI-compatible path; ASR remains key-required.
Tested: npm run build; cargo test --lib
Not-tested: Live behavior against a real keyless endpoint outside the test harness
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: 0fe00ced9a

ℹ️ 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 +187 to 188
if api_key_required && api_key.trim().is_empty() {
return Err("API Key 为空".to_string());
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 Skip auth header for keyless LLM model discovery

This change allows empty API keys for llm, but the model-listing path still unconditionally sends Authorization: Bearer {api_key} in fetch_provider_models. When the key is empty, some OpenAI-compatible endpoints reject the empty Bearer credential, so the Settings “Fetch models” flow fails even though keyless LLM polish/validation now works. Please make model discovery omit Authorization when the key is blank, matching the new keyless behavior.

Useful? React with 👍 / 👎.

Model discovery now matches the keyless LLM path by omitting Authorization when the stored API key is blank. This keeps Fetch models usable for endpoints that reject empty Bearer credentials while preserving authenticated discovery for configured providers.

Constraint: ASR still requires an API key
Rejected: send a fake or empty Bearer header | breaks keyless endpoints
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce auth headers for blank LLM keys without a provider-specific requirement
Tested: cargo test --lib fetch_provider_models_omits_authorization_when_api_key_is_empty; rustfmt --edition 2021 --check src/commands.rs
Not-tested: full frontend integration flow
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: 1d0dcef18c

ℹ️ 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 1591 to 1593
let api_key = CredentialsVault::get(CredentialAccount::ArkApiKey)?.unwrap_or_default();
if api_key.is_empty() {
anyhow::bail!("ark api key missing");
}
let model = CredentialsVault::get(CredentialAccount::ArkModelId)?
.filter(|s| !s.is_empty())
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 Restore no-key guard before default Ark endpoint fallback

In polish_text the API-key emptiness check was removed, but this function still falls back to the public Ark URL when no endpoint is configured. That means users with an empty ArkApiKey (including fresh installs with default Light mode) now send raw transcript content to https://ark.cn-beijing.volces.com/... and only fail after the network call, whereas previously the request was blocked locally. This is a privacy and behavior regression introduced by this commit; the same pattern also appears in translate_text and answer_chat_dispatch.

Useful? React with 👍 / 👎.

Polish, translate, and QA chat now fail locally when ArkApiKey is blank, so fresh installs and keyless LLM setups do not leak transcript content to the default public Ark endpoint. Model discovery remains keyless because it is a separate non-content path.

Constraint: LLM model discovery must stay keyless
Rejected: rely on downstream provider auth failures | leaks user content over the network
Confidence: high
Scope-risk: narrow
Directive: Keep the blank-key guard ahead of any Ark endpoint fallback in content-sending flows
Tested: cargo test --lib require_ark_api_key_rejects_blank_key; rustfmt --edition 2021 --check src/coordinator.rs
Not-tested: full UI settings flow
@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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

PR Reviewer Guide 🔍

(Review updated until commit b85006c)

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis ✅

192 - Fully compliant

Compliant requirements:

  • LLM provider 配置读取不再强制要求 API Key
  • LLM 验证和运行时请求在 API Key 为空时不再发送 Authorization header
  • ASR provider 配置仍保持 API Key 必填
  • 新增了覆盖无密钥场景的测试
⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

…k leakage

Content flows now allow empty Ark API keys only when a custom Ark endpoint is configured. If both key and endpoint are empty, we fail locally instead of falling back to the public Ark endpoint, preserving the privacy guard while restoring ticket Open-Less#192 keyless self-hosted behavior.

Constraint: Keep no-key self-hosted OpenAI-compatible LLM support from issue Open-Less#192
Constraint: Prevent transcript content from being sent to default public Ark endpoint when key is empty
Rejected: unconditional API-key requirement in coordinator | breaks keyless self-hosted usage
Rejected: unconditional default-endpoint fallback | risks accidental data egress on fresh installs
Confidence: high
Scope-risk: narrow
Directive: Any future endpoint fallback change must preserve the blank-key + blank-endpoint local guard for content-sending flows
Tested: rustfmt --edition 2021 --check src/coordinator.rs; cargo test --lib resolve_ark_endpoint_
Not-tested: end-to-end UI interaction for keyless custom endpoint polish/translate/chat
@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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

Persistent review updated to latest commit b85006c

@H-Chris233 H-Chris233 merged commit a2a5605 into Open-Less:main May 3, 2026
2 checks passed
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.

LLM配置时密钥不应是必填项

1 participant