mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-30 16:23:35 +08:00
When a third-party Anthropic-compatible gateway (typical: Bedrock-backed proxies like the user's mimo setup) can't relay Anthropic's `thinking` field, it returns 400s like "该模型不支持 'additionalModelRequestFields' 字段" — the gateway has wrapped the unknown Anthropic param into AWS Bedrock's `additionalModelRequestFields`, and Bedrock rejects on the target model. The user reported a 4.5 model on mimo failing this way while the same model on kiro-account-manager 1.7.5 (which doesn't go through Bedrock) was fine. End-to-end fix: detect the failure pattern, sticky-mark the provider, auto-restart the sidecar with `CLAUDE_CODE_DISABLE_THINKING=1`, and surface a Settings badge so the user knows what happened. Mirrors the desktop providerCompatStore pattern from PR #4 (fake tool_use detection) — two compat dimensions, same re-arm-on-edit semantics, same UX shape. Server side ----------- - `SavedProvider` schema gains `thinkingIncompatible?: boolean` and `thinkingIncompatibleReason?: string` (max 500 chars). Fully back-compat: missing field reads as undefined. - `ProviderService.markThinkingIncompatible(id, reason)` writes the flag, idempotent for identical reasons (no thrash on a burst of the same error). Returns null for unknown ids and openai-official. - `ProviderService.updateProvider` auto-clears the flag on any edit — user changing config = "I'm fixing it" → fresh chance. - `buildProviderManagedEnv` injects `CLAUDE_CODE_DISABLE_THINKING=1` when the flag is true, so the next sidecar launch goes out without thinking entirely. - WS handler runs `detectThinkingIncompatMessage` on every error ServerMessage forwarded to the desktop. On match, fires: 1. `markThinkingIncompatible` (persists) 2. `provider_compat_event` WS message to the desktop 3. `enqueueRuntimeTransition` → `scheduleRestartSessionWithRuntimeConfig` (same graceful path used by set_runtime_config — never tears down a streaming response mid-flight) Process-local dedup so a burst of identical errors doesn't restart the sidecar repeatedly. - Detection regex deliberately narrow: /additionalModelRequestFields/i /\bthinking\b[^.]*\b(not supported|unsupported|invalid| disabled|rejected)\b/i /unknown.{0,40}\bthinking\b/i False positives would permanently disable thinking on the wrong provider until the user edited its config. Desktop side ------------ - New ServerMessage variant `provider_compat_event` plumbed through both server and desktop chat type unions. - `providerCompatStore` gains `thinkingIncompatibleProviderIds: Set<string>`, `recordThinkingIncompatible(id, reason)` action, `hasProviderThinkingIncompatible(id)` helper. Persisted to the same localStorage key as the fake-tool_use counter, alongside it. Dedup: re-firing for an already-flagged provider doesn't re-toast. - `clearProvider(id)` now clears BOTH dimensions, matching the server-side updateProvider behavior. - `chatStore` switch dispatches the new event to the store. - `Settings → Provider` row renders a separate "思考不兼容" badge (psychology_alt icon) next to the existing "工具调用异常" badge. Both badges can show simultaneously when a provider has both problems; both are cleared by the same edit-and-save action. - 5 locales (en/zh/zh-TW/jp/kr) get 3 new keys each: badge label, badge tooltip, and toast message. Tests ----- - `src/server/ws/thinkingIncompat.test.ts` (NEW, 6 cases): regex pinning — Bedrock additionalModelRequestFields rejections / thinking-rejection phrases / unrelated 4xx / passing mentions of thinking / null-empty defensive / case-insensitive. - `src/server/__tests__/providers.test.ts` (5 added): markThinkingIncompatible persists / truncates 500-char reason / idempotent / null-for-unknown-id / null-for-openai-official / updateProvider auto-clears. - `src/server/__tests__/provider-runtime-env.test.ts` (2 added): `CLAUDE_CODE_DISABLE_THINKING=1` injected when flag true / absent when flag false (back-compat with v0.5.7 providers.json). - `desktop/src/stores/providerCompatStore.test.ts` (6 added): records flag + one-time toast / persists set / hydrates from localStorage / clearProvider clears both dimensions / null-empty defensive / hasProviderThinkingIncompatible reflects current state. Folded into the unreleased v0.5.8 release notes — fold both this fix and the PR #5 (handoff fixes) into the same 0.5.8 release. Tested: - bun run lint (desktop) clean - bun test src/server/{ws/thinkingIncompat,__tests__/providers, __tests__/provider-runtime-env}.test.ts → 87 + 6 = 93 pass - bunx vitest run src/stores/providerCompatStore.test.ts → 14 pass - bunx vitest run src/components/chat/AssistantMessage.faketooluse.test.tsx → 6 pass (regression check, no breakage from the new chatStore dispatcher case) Confidence: high Scope-risk: narrow — additive types throughout (back-compat with v0.5.7 providers.json), narrow detection regex, dedup guard prevents restart loops, edit-to-clear gives users an easy escape hatch. Co-authored-by: 你的姓名 <you@example.com>
Claude Code Haha Desktop
基于 Tauri 2 + React 的桌面客户端。
开发
bun install
bun run tauri dev
构建
# macOS (Apple Silicon)
./scripts/build-macos-arm64.sh
# Windows (x64, MSI only)
.\scripts\build-windows-x64.ps1
构建产物位于 build-artifacts/ 目录,文件名会显式包含平台、架构和包类型。
常见问题
macOS 提示"已损坏,无法打开"
xattr -cr /Applications/Claude\ Code\ Haha.app