From a7604f659194edbfbd11321a5b5d16780b84a02e Mon Sep 17 00:00:00 2001 From: claude-code-best Date: Fri, 3 Apr 2026 14:22:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20/login=20=E5=91=BD=E4=BB=A4=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=87=AA=E5=AE=9A=E4=B9=89=20anthropic=20=E7=BB=88?= =?UTF-8?q?=E7=AB=AF=E7=99=BB=E9=99=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DEV-LOG.md | 34 +++++++ README.md | 35 +++++++ src/components/ConsoleOAuthFlow.tsx | 144 +++++++++++++++++++++++++++- 3 files changed, 208 insertions(+), 5 deletions(-) diff --git a/DEV-LOG.md b/DEV-LOG.md index 3c2a94fc0..c84f2e59e 100644 --- a/DEV-LOG.md +++ b/DEV-LOG.md @@ -168,3 +168,37 @@ GrowthBook 功能开关系统原为 Anthropic 内部构建设计,硬编码 SDK 注意: - `USER_TYPE=ant` 启用 alt-screen 全屏模式,中心区域满屏是预期行为 - `global.d.ts` 中剩余未 stub 的全局函数(`getAntModels` 等)遇到 `X is not defined` 时按同样模式处理 + +--- + +## /login 添加 Custom Platform 选项 (2026-04-03) + +在 `/login` 命令的登录方式选择列表中新增 "Custom Platform" 选项(位于第一位),允许用户直接在终端配置第三方 API 兼容服务的 Base URL、API Key 和三种模型映射,保存到 `~/.claude/settings.json`。 + +**修改文件:** + +| 文件 | 变更 | +|------|------| +| `src/components/ConsoleOAuthFlow.tsx` | `OAuthStatus` 类型新增 `custom_platform` state(含 `baseUrl`、`apiKey`、`haikuModel`、`sonnetModel`、`opusModel`、`activeField`);`idle` case Select 选项新增 Custom Platform 并排第一位;新增 `custom_platform` case 渲染 5 字段表单(Tab/Shift+Tab 切换、focus 高亮、Enter 跳转/保存);Select onChange 处理 `custom_platform` 初始状态(从 `process.env` 预填当前值);`OAuthStatusMessageProps` 类型及调用处新增 `onDone` prop | +| `src/components/ConsoleOAuthFlow.tsx` | 新增 `updateSettingsForSource` import | + +**UI 交互:** +- 5 个字段同屏:Base URL、API Key、Haiku Model、Sonnet Model、Opus Model +- 当前活动字段的标签用 `suggestion` 背景色 + `inverseText` 反色高亮 +- Tab / Shift+Tab 在字段间切换,各自保留输入值 +- 每个字段按 Enter 跳到下一个,最后一个字段 (Opus) 按 Enter 保存 +- 模型字段自动从 `process.env` 读取当前配置作为预填值,无值则空 +- 保存时调用 `updateSettingsForSource('userSettings', { env })` 写入 settings.json,同时更新 `process.env` + +**保存的 settings.json env 字段:** +```json +{ + "ANTHROPIC_BASE_URL": "...", + "ANTHROPIC_AUTH_TOKEN": "...", + "ANTHROPIC_DEFAULT_HAIKU_MODEL": "...", + "ANTHROPIC_DEFAULT_SONNET_MODEL": "...", + "ANTHROPIC_DEFAULT_OPUS_MODEL": "..." +} +``` + +非空字段才写入,保存后立即生效(`onDone()` 触发 `onChangeAPIKey()` 刷新 API 客户端)。 diff --git a/README.md b/README.md index 1fa7e6c45..d1f8cf576 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ - [x] 关闭自动更新; - [x] 添加自定义 sentry 错误上报支持 [文档](https://ccb.agent-aura.top/docs/internals/sentry-setup) - [x] 添加自定义 GrowthBook 支持 (GB 也是开源的, 现在你可以配置一个自定义的遥控平台) [文档](https://ccb.agent-aura.top/docs/internals/growthbook-adapter) + - [x] 自定义 login 模式, 大家可以用这个配置 Claude 的模型! - [ ] V6 大规模重构石山代码, 全面模块分包 - [ ] V6 将会为全新分支, 届时 main 分支将会封存为历史版本 @@ -72,6 +73,40 @@ bun run build 如果遇到 bug 请直接提一个 issues, 我们优先解决 +### 新人配置 /login + +首次运行后,在 REPL 中输入 `/login` 命令进入登录配置界面,选择 **Custom Platform** 即可对接第三方 API 兼容服务(无需 Anthropic 官方账号)。 + +需要填写的字段: + +| 字段 | 说明 | 示例 | +|------|------|------| +| Base URL | API 服务地址 | `https://api.example.com/v1` | +| API Key | 认证密钥 | `sk-xxx` | +| Haiku Model | 快速模型 ID | `claude-haiku-4-5-20251001` | +| Sonnet Model | 均衡模型 ID | `claude-sonnet-4-6` | +| Opus Model | 高性能模型 ID | `claude-opus-4-6` | + +- **Tab / Shift+Tab** 切换字段,**Enter** 确认并跳到下一个,最后一个字段按 Enter 保存 +- 模型字段会自动读取当前环境变量预填 +- 配置保存到 `~/.claude/settings.json` 的 `env` 字段,保存后立即生效 + +也可以直接编辑 `~/.claude/settings.json`: + +```json +{ + "env": { + "ANTHROPIC_BASE_URL": "https://api.example.com/v1", + "ANTHROPIC_AUTH_TOKEN": "sk-xxx", + "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5-20251001", + "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-6", + "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-6" + } +} +``` + +> 支持所有 Anthropic API 兼容服务(如 OpenRouter、AWS Bedrock 代理等),只要接口兼容 Messages API 即可。 + ## Feature Flags 所有功能开关通过 `FEATURE_=1` 环境变量启用,例如: diff --git a/src/components/ConsoleOAuthFlow.tsx b/src/components/ConsoleOAuthFlow.tsx index 8d5fc122c..7d777cb18 100644 --- a/src/components/ConsoleOAuthFlow.tsx +++ b/src/components/ConsoleOAuthFlow.tsx @@ -12,7 +12,7 @@ import { sendNotification } from '../services/notifier.js'; import { OAuthService } from '../services/oauth/index.js'; import { getOauthAccountInfo, validateForceLoginOrg } from '../utils/auth.js'; import { logError } from '../utils/log.js'; -import { getSettings_DEPRECATED } from '../utils/settings/settings.js'; +import { getSettings_DEPRECATED, updateSettingsForSource } from '../utils/settings/settings.js'; import { Select } from './CustomSelect/select.js'; import { KeyboardShortcutHint } from './design-system/KeyboardShortcutHint.js'; import { Spinner } from './Spinner.js'; @@ -29,6 +29,15 @@ type OAuthStatus = { | { state: 'platform_setup'; } // Show platform setup info (Bedrock/Vertex/Foundry) +| { + state: 'custom_platform'; + baseUrl: string; + apiKey: string; + haikuModel: string; + sonnetModel: string; + opusModel: string; + activeField: 'base_url' | 'api_key' | 'haiku_model' | 'sonnet_model' | 'opus_model'; +} // Custom platform: configure API endpoint and model names | { state: 'ready_to_start'; } // Flow started, waiting for browser to open @@ -325,7 +334,7 @@ export function ConsoleOAuthFlow({ } - + ; } @@ -343,6 +352,7 @@ type OAuthStatusMessageProps = { handleSubmitCode: (value: string, url: string) => void; setOAuthStatus: (status: OAuthStatus) => void; setLoginWithClaudeAi: (value: boolean) => void; + onDone: () => void; }; function OAuthStatusMessage(t0) { const $ = _c(51); @@ -359,7 +369,8 @@ function OAuthStatusMessage(t0) { textInputColumns, handleSubmitCode, setOAuthStatus, - setLoginWithClaudeAi + setLoginWithClaudeAi, + onDone } = t0; switch (oauthStatus.state) { case "idle": @@ -402,7 +413,10 @@ function OAuthStatusMessage(t0) { } let t6; if ($[5] === Symbol.for("react.memo_cache_sentinel")) { - t6 = [t4, t5, { + t6 = [{ + label: Custom Platform ·{" "}Configure your own API endpoint{"\n"}, + value: "custom_platform" + }, t4, t5, { label: 3rd-party platform ·{" "}Amazon Bedrock, Microsoft Foundry, or Vertex AI{"\n"}, value: "platform" }]; @@ -413,7 +427,18 @@ function OAuthStatusMessage(t0) { let t7; if ($[6] !== setLoginWithClaudeAi || $[7] !== setOAuthStatus) { t7 =