Commit Graph

5 Commits

Author SHA1 Message Date
matevip
6390abdecc fix(llm): apply read timeout to streaming chat WebClient (openai-compat + anthropic) 2026-04-30 08:54:46 +08:00
matevip
a7938b0e68 feat(anthropic): wire Claude Code OAuth into chat model 2026-04-26 08:34:08 +08:00
matevip
23a6d16778 feat(model-catalog): add Claude 4.7 + GPT-5.5 sampling-params handling 2026-04-26 08:32:45 +08:00
matevip
6c15622b59 refactor(llm): RFC-009 PR-0b — migrate DashScope + Anthropic helpers out of AgentGraphBuilder
PR-0 only installed the strategy seam; the actual ~600 LOC of provider-
specific construction stayed in AgentGraphBuilder as transitional public
helpers. PR-0b moves the DashScope + Anthropic halves into their builders
proper. (OpenAI larger refactor — 5 sub-helpers including Kimi/o-series
special cases — is left for a follow-up PR-0c.)

AgentDashScopeChatModelBuilder now owns:
  - buildDashScopeApi (with provider/env/reflection key+url fallback chain)
  - buildDashScopeOptions (model/temp/max-tokens/topP + built-in search)
  - normalizeDashScopeBaseUrl (strip /compatible-mode/, return null for SDK default)
  - readApiKeyFromDefaultChatModel + readBaseUrlFromDefaultChatModel +
    readDashScopeApiFromDefaultChatModel (reflection-based final fallback)
  - isBuiltinSearchEnabled (renamed from isDashScopeSearchEnabled, called
    by AgentGraphBuilder.build via the now-injected dashScopeBuilder ref)

AgentAnthropicChatModelBuilder now owns:
  - buildAnthropicApi (key validation, applyHttpTimeouts duplicated locally)
  - buildAnthropicOptions (extended-thinking budget mapping low/medium/high/max
    → 4k/8k/16k/32k, temperature=1 enforcement, RFC-014 prompt cache options)

AgentGraphBuilder dropped:
  - DashScope: ~120 LOC (api + options + 4 helpers + isDashScopeSearchEnabled)
  - Anthropic: ~75 LOC (api + options)
  - DashScopeChatModel + DashScopeConnectionProperties fields (unused after move)
  - Deprecated single-fallback buildFallbackModel (no callers, superseded
    by buildFallbackChain since RFC-009 PR-1)
  - 5 imports for moved DashScope/Anthropic types

Net: -154 LOC in AgentGraphBuilder (1721 → 1567), +372 across the two new
builders. Strategy seam is now real for 3 of 4 protocols (ChatGPT was
already standalone, OpenAI is PR-0c). 220/220 tests still green — no
behavior change.
2026-04-19 19:22:57 +08:00
matevip
3b11a3def6 fix(failover): AUTH_ERROR triggers fallback chain + UI splits provider 401 from session expiry
Two related issues from the Kimi-401 user report:

1. Backend (NodeStreamingChatHelper): a primary AUTH_ERROR (e.g. Kimi 401
   with an invalid API key) returned immediately without trying the
   fallback chain — a fallback provider with a different, valid key
   never got a chance. Even with DashScope correctly configured as the
   fallback, the user chat dead-ended on a 401.

   The original assumption ("auth never self-heals so do not retry")
   holds for the primary same-model retry loop but is wrong for the
   fallback chain — different providers have different keys. Apply the
   same break-into-fallback policy that BILLING and MODEL_NOT_FOUND
   already use. recordPrimary(false) is preserved so the cooldown
   counter still accumulates.

2. Frontend (chatError.ts + i18n): the error-text matching for
   /认证|auth|unauthorized|401/i was so broad it matched the substring
   "auth" inside URLs like https://api.kimi.com/.../auth, classifying
   any model 401 as user "session expired" and rendering the misleading
   "页面将自动跳转到登录页" copy. (The redirect itself only fires from
   /api/v1/auth/* axios paths and SSE-connection 401s, not from this
   payload-text path — but the copy alone is the worst kind of false
   alarm.)

   Add a new ChatErrorCategory provider_auth_error and split the
   pattern matching: narrow auth_expired (HTTP 401 / 登录已过期 /
   session expired / 凭证失效) is matched FIRST, then the broad
   401-ish pattern routes to provider_auth_error. BACKEND_ERROR_TYPE_MAP
   for AUTH_ERROR is also remapped, since structured backend payloads
   currently always come from LLM providers — never from our own
   /api/v1/auth path.

Tests
- NodeStreamingChatHelperFailoverTest (5 cases): primary 401 →
  fallback succeeds; chain skips auth-failing fallback to next healthy
  one; whole-chain failure surfaces last AUTH_ERROR (no silent drop);
  BILLING regression unchanged; primary-success path does not touch
  chain
- Browser preview verified: new i18n keys resolve in en-US, classifier
  correctly routes "[错误] 401 from kimi.com" → provider_auth_error
  while "[错误] HTTP 401 from /api/v1/auth/ping" stays auth_expired
- 186 tests pass (was 181 + 5 new); vue-tsc clean

Do-not-touch list: handleAuthFailure() in useStream/api/index.ts (real
session-expiry path) is unmodified — only the misclassification
upstream is fixed. auth_expired i18n copy is unchanged.
2026-04-19 17:45:15 +08:00