fix(server): use the keys the user sent, and more review fixes

Found by the second PR review:
- With AWS_BEARER_TOKEN_BEDROCK set on the server, a request with the
  user's AWS keys ran on the server's token: the Bedrock SDK prefers it.
  Checked with Bedrock: invalid user keys used to get an answer.
- An OpenAI key with the official URL filled in (the settings form does
  that) went to the Responses API. Back to main's rule: a configured base
  URL uses Chat Completions.
- A user's Ollama key went to the server's OLLAMA_BASE_URL, for chat and
  for the model list. Like every other provider, it goes to the user's
  base URL or Ollama Cloud.
- The server's keyless Ollama and EdgeOne were not counted in the quota.
- AI_MODEL models on the server's keys ran on any provider with a server
  key, not only on AI_PROVIDER.
- A user's Azure key without a base URL used the server's resource name.
- The admin panel's Test button failed whenever access codes were set.
- DeepSeek's errors in the stream (plain text) were shown as they were,
  without a hint and also on the server's keys. Bedrock's throttling in
  the stream was not recognised as a rate limit.
- The EdgeOne function accepted text/plain; x=application/json, which
  other sites can send without a CORS preflight.
- Desktop app: a launch that found the old port taken for a moment (the
  previous version still quitting after an update) remembered the new
  port for good. The new port is kept only when Windows reserves the old
  one. A failed read of the presets file moved it aside as corrupt, and a
  save could then replace the presets. Switching presets on the same port
  now reloads the page. The dev launcher no longer misses a preset change
  made before or during a restart.
This commit is contained in:
dayuan.jiang
2026-10-05 10:52:37 +09:00
parent 080f44716f
commit d5f31cb253
19 changed files with 499 additions and 91 deletions
+12 -3
View File
@@ -80,7 +80,8 @@ const GENERAL_TEXTS: Array<[RegExp, LLMErrorCode]> = [
/invalid[_ ]api[_ ]key|incorrect api key|unauthorized/i,
"invalid_api_key",
],
[/rate limit|too many requests/i, "rate_limited"],
// "too many tokens": Bedrock's throttling
[/rate limit|too many requests|too many tokens/i, "rate_limited"],
[
/Cannot connect to API|ECONNREFUSED|ENOTFOUND|ECONNRESET|ETIMEDOUT|fetch failed/i,
"cannot_connect",
@@ -115,8 +116,16 @@ function problemDetail(body: string): string | undefined {
* it can name the server's account, role or internal hosts.
*/
export function streamErrorText(error: unknown, hideDetails = false): string {
// The SDK passes an invalid tool call's error as a plain string
if (typeof error === "string") return error
// The SDK passes an invalid tool call's error as a plain string. Other
// strings come from providers (DeepSeek's SDK sends stream errors so).
if (
typeof error === "string" &&
/^(Invalid input for tool|Model tried to call unavailable tool)/.test(
error,
)
) {
return error
}
if (isToolCallError(error)) return (error as Error).message
const classified = classifyLLMError(error)
if (hideDetails) {