feat: 支持 Kiro (AWS CodeWhisperer/Q) 提供商及 OIDC 认证流程#4125
Open
simonsmh wants to merge 1927 commits into
Open
Conversation
- Add Claude Desktop Official to the Claude Desktop preset list. - Treat selected official presets as official mode in the form. - Cover the official preset with a preset-order regression test.
- Add the Claude Desktop provider guide in English, Chinese, and Japanese. - Add localized screenshots for import, provider setup, model mapping, and local routing. - Link the guide from the v3.15.0 release notes and user manual indexes.
…231#2827) - Add active flag pattern to 3 useEffect hooks in App.tsx to prevent event listener leaks when component unmounts before async setup completes - Add guard check in useSettings.ts to prevent undefined from being stored in localStorage when payload.language is missing Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix(session): 修复session log模式下子Agent token统计遗漏 collect_jsonl_files() 只扫描了两层目录,遗漏了子Agent的JSONL日志文件, 导致子Agent的独立token使用数据完全未统计到session费用中。 (仅影响session log模式,proxy代理模式不受影响) * refactor(session): optimize collect_jsonl_files logic - Replace two independent if statements with if-else for mutually exclusive conditions - Remove unnecessary clone() when pushing file paths - Add clarifying comments for main session vs subagent files - Apply cargo fmt for consistent formatting Performance improvement: Eliminates redundant clone() operations when processing .jsonl files, as a path cannot be both a file and a directory. --------- Co-authored-by: Jason <farion1231@gmail.com>
…signature for synthesized tool call IDs (farion1231#2814) * fix(gemini-native): resolve functionResponse.name and thought_signature replay for synthesized tool call IDs Two related bugs in the Gemini Native format conversion layer: 1. **functionResponse.name resolution** (422 error): When Gemini's parallel function calls omit the id field, cc-switch synthesizes gemini_synth_* IDs. These are stored in the shadow store but can be lost in long sessions, causing subsequent tool_result blocks to fail. Fix: pre-scan all assistant messages in the request body to seed the tool_name_by_id map, and add a last-resort fallback that scans the current content array for matching tool_use blocks. 2. **thought_signature replay** (400 error): The Anthropic Messages format strips thoughtSignature from tool_use blocks, but Gemini requires it on every functionCall in multi-turn tool-use exchanges. Fix: build a thought_signature_by_id map from shadow turns and attach thoughtSignature when converting tool_use back to functionCall. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * style: run cargo fmt on transform_gemini.rs --------- Co-authored-by: Tiancrimson <tiancrimson@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Jason <farion1231@gmail.com>
* feat: add Xiaomi MiMo token plan presets * fix: update Xiaomi MiMo provider presets * fix: align MiMo V2.5 model specs with official documentation - Update maxTokens from 32000 to 131072 (128K) for mimo-v2.5-pro and mimo-v2.5 - Update contextWindow from 262144 to 1048576 (1M) for mimo-v2.5 - Aligns with official specs from Xiaomi MiMo documentation - Ensures consistency between OpenClaw and OpenCode presets --------- Co-authored-by: Jason <farion1231@gmail.com>
… tabs (farion1231#2801) When Ghostty is already running, `open -a` silently ignores `--args`, and `open -na` clones all existing tabs into the new instance. Add a dedicated `launch_macos_ghostty` that uses `--quit-after-last-window-closed=true` and `-e bash <script>` to spawn a single clean window running claude. Also change `launch_macos_open_app` from `open -a` to `open -na` so other terminals (Alacritty/Kitty/WezTerm/Kaku) correctly open a new window when already running. Closes farion1231#2798
…arion1231#2793) The step was 0.01, preventing input of prices like DeepSeek's cache read cost ($0.0028/million tokens). Extract step value to a constant and apply to all four price fields. Closes farion1231#2503
…ion1231#2784) * fix(skills): install correct skill from skills.sh search results When multiple skills share the same directory name across different repos, SkillCard was passing directory to onInstall/onUninstall, causing handleInstall to always match the first result. Switch to using the unique key field (directory:repoOwner:repoName) for precise identification. * test(skills): add regression test for skills.sh install by key Verifies that clicking install on the second card when two skills share the same directory name correctly installs the second skill, not the first. --------- Co-authored-by: mrzhao <mrzhao@iflytek.com>
- Sync zh/en/ja manuals with Claude Desktop and Hermes support - Update install requirements, official channels, and release asset guidance - Document Usage Hero, Codex OAuth live models, Save Anyway, Hermes sessions, and Warp launch - Correct tray and app-scope descriptions to match current implementation
- Remove LionCC sponsor entry from all README files (en/zh/ja) - Remove LionCCAPI presets from all provider configs - Remove lionccapi i18n keys from all locales - Keep lioncc.png icon file as requested
…takeover - Provider: add uses_managed_account_auth / is_github_copilot helpers to identify managed-account providers (GitHub Copilot / Codex OAuth) - ProxyService: choose auth policy by provider type when taking over Claude Live config. Managed accounts drop token env keys and write only the ANTHROPIC_API_KEY placeholder; other providers keep the existing ANTHROPIC_AUTH_TOKEN fallback behavior - Forwarder: add outbound guard that refuses to send the PROXY_MANAGED placeholder upstream to *.githubcopilot.com and chatgpt.com /backend-api/codex - Add unit tests covering detection, injection, and the outbound guard
- Add a Codex API format selector and routing badge for Chat Completions providers. - Convert Codex Responses requests to upstream Chat Completions when routing is required. - Convert Chat Completions JSON and SSE responses back to Responses format. - Keep generated Codex wire_api values on Responses for Codex compatibility. - Add i18n labels, provider metadata handling, and focused conversion tests.
- Convert Chat reasoning_content and reasoning fields into Responses reasoning output items. - Emit Responses reasoning summary SSE events for streamed Chat reasoning deltas. - Preserve output ordering when reasoning, text, and tool calls are streamed together. - Add regression coverage for data-only Chat SSE errors, multiple tool calls, and compact routing.
- Split leading <think> blocks from Chat content into Responses reasoning output. - Keep assistant text output free of inline thinking tags. - Support streamed inline thinking blocks before normal text deltas. - Add regression coverage for MiniMax-style inline thinking responses.
- Remove personal tap requirement from all READMEs (en/zh/ja) - Update v3.15.0 release notes to highlight official cask availability - Add celebration banner noting Homebrew official repository inclusion - Simplify installation to single command: brew install --cask cc-switch
增加 Windows 运行后无提示的修复方法
- Add Codex provider API format selection and model mapping for Chat-only upstreams. - Convert Codex Responses requests to Chat Completions and rebuild Chat responses as Responses output. - Preserve reasoning_content across non-streaming, streaming, tool calls, and previous_response_id follow-ups. - Add a bounded Codex Chat history cache for restoring tool calls before tool outputs. - Cover Chat bridge, compact routing, streaming, and history recovery with focused tests.
- Stop deriving Codex session/cache identity from `previous_response_id`. - Canonicalize parseable JSON string payloads in Chat and Responses tool conversions. - Add regression coverage for cache-sensitive conversion behavior.
- Add unique call-id fallback when Codex omits or rewrites previous_response_id. - Keep ambiguous call ids unresolved to avoid cross-request history leaks. - Cover fallback and ambiguity behavior with regression tests.
- Remove mergeCodexDefaultCatalogModelForSave implicit injection (P1) The model mapping table is now the single source of truth; no hidden entries are prepended on save. - Sync first catalog row model into config.toml on save Ensures Codex default request model matches the table's first entry instead of retaining a stale template value. - Remove API Format selector from CodexFormFields (P3) wire_api is always 'responses'; the selector confused users into thinking they were changing the upstream protocol. Only the 'Needs Local Routing' toggle remains. - Add restart hint to model mapping i18n text (P2) model_catalog_json is loaded at Codex startup; users are now informed that a restart is needed after changes. - Unify write_codex_live_with_catalog helper (P4) Replaces three scattered prepare+write call sites in config.rs, provider/live.rs, and proxy.rs with a single entry point. - Clean up useCodexConfigState dead state (P3 follow-up) Remove codexModelName, codexContextWindow, codexAutoCompactLimit and their handlers/effects since no component consumes them after the UI consolidation.
Break bidirectional sync cycle between catalogRows (child) and catalogModels (parent): - Remove catalogModels from child→parent effect dependencies - Track last sent data in ref to avoid redundant callbacks - Sync ref when parent pushes new data to prevent false positives Fixes severe UI jittering when adding/editing catalog entries.
The provider panel health check sent a real streaming model request, which many third-party providers block (401/403/WAF), causing false negatives while only stable official endpoints passed. Replace it with a lightweight reachability probe: GET the provider base_url and treat any HTTP response (200/4xx/5xx) as reachable; only DNS/connect/TLS/timeout count as failure. Latency is the probe's TTFB. Backend (services/stream_check.rs): rewrite ~2200 -> ~350 lines, dropping real-request building, format conversion, auth and API-path resolution while keeping per-app base_url extraction. Defaults: 8s timeout, 1 retry, 1500ms degraded threshold. Failover invariant: the reachability check must never reset the circuit breaker (reachable != usable; a 403 host is reachable but broken for real traffic). Remove the resetCircuitBreaker call from useStreamCheck; failover failure detection stays driven solely by real proxy traffic (forwarder/circuit_breaker untouched). useResetCircuitBreaker is kept dormant for a future manual-recovery entry. Open the check to all providers: drop the official/copilot/codex-oauth/third-party gating and the 'sends a real request' confirm dialog. For official providers whose base_url is intentionally empty, fall back to the endpoint the client actually uses (Claude -> api.anthropic.com, Codex -> chatgpt.com/backend-api/codex, Gemini -> generativelanguage). Non-official providers with a missing base_url still error to avoid a false green light. Claude Desktop Official is native 1P mode (talks to claude.ai, cc-switch not in the request path, no reliable endpoint) so its button stays hidden. Slim StreamCheckConfig and per-provider testConfig to timeout/threshold/retries (drop test model + prompt); sync zh/en/ja/zh-TW. Retain the now-unused anthropic_to_openai/anthropic_to_gemini transform utilities and their test suites.
… restore 6s degraded threshold Official providers (Claude/Codex/Gemini/Claude Desktop) use OAuth with an intentionally empty base_url and connect via the client's default endpoint, so cc-switch has no reliable reachability target. Probing a guessed endpoint either hits the wrong target or returns a meaningless green light. Hide the connectivity button for category === 'official'; reachability stays available for copilot/codex-oauth/third-party/custom providers, which is where the old real-request probe produced false negatives. Revert the official base_url fallback added earlier — resolve_base_url is back to extract-or-error. The 1500ms degraded threshold was too strict; normal ~1s probe latencies showed as 'slow'. Restore the original 6000ms scale (default + config panel + per-provider range). Keep the reachability-appropriate 8s timeout / 1 retry.
Display the Fable 5 Verified banner to the right of the app name and version block on the settings About page, marking this as a special build. Center the version badge under the app name so the two rows share a common axis. The app-side asset lives at src/assets/fable5-verified.png (imported via the @ alias and bundled by Vite); the original source banner is kept under assets/partners/banners/ alongside the other partner banners.
- useUsageQuery: retry once + keep-last-good — show the last successful
result for up to 10min when a query fails transiently (network/timeout/
HTTP 5xx), so a single blip no longer flips the card to red. Deterministic
failures (auth, empty key, unknown provider, 4xx) surface immediately and
clear the snapshot so a stale quota can't resurface after credentials change.
- bump native balance/coding-plan/subscription request timeouts 10s -> 15s
for slow cross-border endpoints.
- coding_plan: return explicit errors ("API key is empty" / "Unknown coding
plan provider") instead of a blank failure, mirroring balance.
- add unit tests for keep-last-good and transient/deterministic classification.
Fan out the six tool version probes concurrently instead of awaiting one sequential batch, so each tool card updates the moment its own check finishes rather than waiting for the slowest one. - loadAllToolVersions now calls refreshToolVersions per tool via Promise.all, reusing the existing per-name merge and per-tool loading flags - card loading derives from per-tool state (loadingTools[t] || (isLoadingTools && !resolved)) so a resolved card leaves loading independently while the batch is still in flight - WSL shell/flag selects reuse the per-card loading flag, matching the install/update buttons' early-enable behavior This also drops total wall time from the sum of six sequential probes to the slowest single probe. get_single_tool_version_impl is already isolated and read-only (shared HTTP client, spawn_blocking subprocess, no shared state), so concurrent probes are safe.
getVersion() is a local, millisecond call but was awaited together with loadAllToolVersions() in a single Promise.all, so setVersion and setIsLoadingVersion only fired after all six tool checks finished. The version badge under the app icon therefore waited for the whole batch. Split the mount effect into two independent chains: loadAppVersion sets the app version (and clears its loading flag) the moment getVersion() resolves, while loadAllToolVersions runs its own progressive fan-out. The two no longer block each other.
Settings uses Radix tabs, which unmount inactive tab content. Every time the About tab was reopened, AboutSection remounted and its mount effect re-ran all six tool version probes (a `--version` subprocess plus an npm/github/pypi request each) -- wasteful, since versions rarely change within a session and a manual Refresh already exists. Add a module-scoped cache (lives for the app session, survives unmount/remount) with a 10-minute TTL: - on remount within the TTL the cached results are reused, skipping all probes; state is lazily initialized from the cache so the first paint shows the values with no loading flash - a stale cache shows the old values immediately and revalidates per tool in the background (stale-while-revalidate) - the Refresh button forces a re-probe; single-tool refreshes (shell change / post-update) update cached data without resetting the TTL - cold-cache entries start at at=0 (a "not yet fully loaded" sentinel) so a partial cache left by a mid-probe tab switch is treated as stale and re-fetched rather than served as if complete; the real timestamp is only stamped once a full load finishes The app's own version is cached too, purely to avoid a loading flash on remount.
…spatch installs Codex ships as an npm platform-dispatch package (JS launcher @openai/codex + per-platform binary optional deps like @openai/codex-darwin-arm64). The upgrade chain ran `<bin>/codex update || <bin>/npm i -g @openai/codex@latest`, which can leave codex throwing "Missing optional dependency @openai/codex-darwin-arm64": - `codex update` on an npm install is a bare `npm install -g @openai/codex` that prints success and exits 0 even when the platform binary fails to land, short-circuiting the `||` npm fallback. - The npm fallback is a no-op when version==latest and only targets the main package, so it can never re-land the missing platform binary. Fixes: (1) remove codex from prefers_official_update (Posix+Windows) so npm-managed codex no longer runs the false-success `codex update`; (2) add a runnable=false gate in installs_anchored_command emitting an uninstall+install self-heal — the only repair that re-lands the platform binary; (3) narrow by source/real to npm-managed sources (nvm/fnm/mise/homebrew, non-brew-formula) so broken brew-formula/volta/bun installs fall back to their own anchored commands instead of being mis-repaired with npm. Reuses the existing enumerate runnable signal; no new FS probing.
Remove the gold star badge and the partner promotion banner for MiniMax by deleting the isPartner flag from all 12 MiniMax presets (cn + en) across claude, claude-desktop, codex, opencode, openclaw, and hermes. Both the preset-selector star (gated on isPartner) and the API-key promotion banner (gated on isPartner && partnerPromotionKey) disappear as a result. The partnerPromotionKey and the minimax_cn/minimax_en i18n copy are kept dormant so the partnership can be re-enabled with a single line if needed. MiniMax stays as a regular cn_official provider, keeping its icon and theme.
…mo copy - Replace activity/agentplan links with the new codingplan invite URL (ac=MMAP8JTTCAQ2, rc=6J6FV5N2) across all 6 app presets - Refresh partnerPromotion copy in all 4 locales: two-month 75% off plus invite code 6J6FV5N2; correct product name from Agent Plan to Coding Plan - README: swap the CN-mainland redirect link in EN/DE, refresh the ZH promo copy, and add the redirect link to the JA BytePlus entry
- Bump version to 3.16.3 (package.json, tauri.conf.json, Cargo.toml, Cargo.lock) - Add CHANGELOG entry for v3.16.3 (59 commits since v3.16.2) - Add trilingual release notes (zh / en / ja) under docs/release-notes/
…ndling OAuth & credentials: - Add Google/GitHub social PKCE login (localhost:3128 callback) and merged web-login entry; IdC/Builder ID device-code flow with 10-region auto-detect - Import-on-click sharing of kiro-cli / Kiro IDE credentials (removable, no auto-reappear); lenient expires_at parsing + multi-layer refresh cascade - Fix blocking-lock panic (async save_to_disk, no tokio lock in sync paths) Proxy & transform: - Classify Kiro provider in ClaudeAdapter (provider_type, needs_transform, api_format whitelist, managed-account auth) so requests reach local routing - Route Kiro to runtime root '/' with AWS headers, transform Anthropic->Kiro body, aggregate eventstream for non-streaming clients - Map SSO region to deployed API region (us-east-1/eu-central-1) for runtime, management and refresh URLs; fetch profileArn via ListAvailableProfiles - Fix model-id mapping (preserve brand hyphens), conversationId uuid fallback Model capabilities: - Parse additionalModelRequestFieldsSchema into a global caps cache; gate output_config.effort on model support, warm cache on first thinking request, and keep a 400 additionalModelRequestFields strip-and-retry fallback UI & misc: - Add Kiro apiFormat option + model-fetch in both Claude and Claude Desktop forms; allow-create RegionCombobox; Kiro connectivity check in stream_check
…tiple components - Standardize formatting in ProviderCard, ClaudeFormFields, KiroAuthSection, ProviderForm, RegionCombobox, and useManagedAuth hooks. - Enhance SVG structure in AuthCenterPanel for better clarity. - Update Kiro-related translations in both English and Chinese locales. - Adjust region detection logic in KiroAuthManager and proxy providers for improved accuracy. - Refactor JSON handling in streaming and transformation functions for consistency.
Previously Kiro auth commands always returned default_account_id: None, causing the UI to never show which Kiro account was the default. Added KiroAuthManager::default_account_id() getter and wired it into auth_poll_for_account, auth_list_accounts, auth_get_status, auth_kiro_social_login, and auth_kiro_import_dynamic.
When Kiro streaming chunks don't align with JSON object boundaries,
parse_kiro_events would drop incomplete patterns by returning an empty
remainder. This caused event loss when a chunk ended mid-JSON (e.g.
{"con without the closing }).
Now preserves the trailing MAX_PATTERN_LEN-1 bytes (24 bytes for the
longest pattern {"contextUsagePercentage":) when no complete pattern
is found, allowing the next chunk to complete the partial event.
Added test parse_preserves_partial_pattern_across_chunks.
Improve Kiro proxy forwarder, claude/kiro provider transforms, streaming event handling, and auth commands. Apply cargo fmt formatting.
- kiro_eventstream_to_anthropic_response returns Result; error events now propagate as ProxyError instead of fabricating a successful empty message - get_valid_token_for_account gates dynamic kiro-cli/IDE reads on the account still being registered, so removed imported accounts no longer authenticate
Add ksk_-prefixed API key auth alongside the existing OIDC/social/import flows. API keys are long-lived bearer tokens used directly with no OIDC exchange or refresh. - kiro_auth: is_api_key helper, apikey_login (GetProfile validation), skip refresh for apikey accounts, fetch_profile_arn branches to GetProfile (vs ListAvailableProfiles) for API keys - claude/kiro/stream_check: add tokentype: API_KEY header on management and runtime calls; stream_check now also sends the AmazonQ-For-CLI UA - new auth_kiro_api_key_login Tauri command + frontend binding/hook/UI
…s empty Builder ID accounts sometimes get an empty ListAvailableProfiles result, leaving profileArn unset and breaking runtime requests. Add a shared Builder ID profileArn fallback applied only when auth_method=="idc" and start_url is the default Builder ID start URL; enterprise IdC, social and API-key accounts are unaffected and keep their own profileArn resolution.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary / 概述
本 PR 实现了对 Kiro (AWS CodeWhisperer/Q) 提供商的完整支持。这包括 OIDC 认证流(AWS IAM Identity Center / Builder ID 以及社交登录)、本地凭证一键导入与刷新管理、Anthropic API 格式到 Kiro 格式的代理与转换路由、模型能力缓存与处理、以及配套的 Frontend UI。
Related Issue / 关联 Issue
Fixes #533
Fixes #1443
Screenshots / 截图
Checklist / 检查清单
pnpm typecheckpasses / 通过 TypeScript 类型检查pnpm format:checkpasses / 通过代码格式检查cargo clippypasses (if Rust code changed) / 通过 Clippy 检查(如修改了 Rust 代码)主要改动
1. 认证与凭证管理 (OAuth & Credentials)
localhost:3128作为回调)和统一的 Web 登录入口。kiro-cli/ Kiro IDE 凭证一键导入并进行共享。expires_at解析的容错性,设计了多层 Refresh Token 级联刷新机制。async save_to_disk,避免在同步代码路径中引入 tokio 阻塞锁,修复了潜在的 blocking-lock 导致 Panic 的问题。2. 代理路由与格式转换 (Proxy & Request Transform)
ClaudeAdapter中对 Kiro 类型进行分类支持(配置provider_type,needs_transform,api_format白名单及托管账号认证机制),使 Claude Desktop / Web 请求能正确路由至本地代理。us-east-1/eu-central-1)。ListAvailableProfiles接口拉取profileArn。conversationId的请求增加 UUID Fallback 兜底逻辑。3. 模型能力处理 (Model Capabilities)
additionalModelRequestFieldsSchema解析并缓存至全局 Model Capabilities 缓存中。output_config.effort等高级参数进行按需门控(Gating);在首次发起 Thinking 请求时自动预热缓存。400错误,会自动清理additionalModelRequestFields字段后发起二次重试,保障请求成功率。4. UI 界面与联通性测试 (UI & Connectivity)
apiFormat配置与一键拉取模型支持。RegionCombobox组件,支持用户手动输入或搜索选择 AWS 区域。stream_check连通性测试模块中集成 Kiro 接口检测,方便用户排查网络与凭证问题。