Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 106 additions & 0 deletions docs/api-providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# API 提供商集成

> 记录 Claude Code 支持的 API 提供商、配置方式、模型映射和集成细节。

## 支持的提供商

| 提供商 | modelType | 环境变量前缀 | API 兼容层 |
|--------|-----------|-------------|-----------|
| Anthropic (默认) | anthropic | ANTHROPIC_* | 原生 SDK |
| OpenAI | openai | OPENAI_* | OpenAI Chat Completions |
| Gemini | gemini | GEMINI_* | Gemini Generate Content |
| xAI Grok | grok | GROK_* / XAI_* | OpenAI 兼容 |
| **阿里云百炼 (DashScope)** | **anthropic** | **DASHSCOPE_* → ANTHROPIC_*** | **Anthropic 原生 SDK** |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix emphasis parsing in provider table cell.

The DASHSCOPE_* → ANTHROPIC_* cell triggers markdown emphasis parsing/lint issues due to raw *. Prefer inline code or escaped asterisks.

🛠️ Suggested markdown fix
-| **阿里云百炼 (DashScope)** | **anthropic** | **DASHSCOPE_* → ANTHROPIC_*** | **Anthropic 原生 SDK** |
+| 阿里云百炼 (DashScope) | anthropic | `DASHSCOPE_*` → `ANTHROPIC_*` | Anthropic 原生 SDK |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| **阿里云百炼 (DashScope)** | **anthropic** | **DASHSCOPE_* → ANTHROPIC_*** | **Anthropic 原生 SDK** |
| 阿里云百炼 (DashScope) | anthropic | `DASHSCOPE_*``ANTHROPIC_*` | Anthropic 原生 SDK |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/api-providers.md` at line 13, The table cell containing "DASHSCOPE_* →
ANTHROPIC_*" is causing markdown emphasis parsing due to the raw asterisks;
update that cell to use inline code backticks around the tokens (e.g.,
`DASHSCOPE_* → ANTHROPIC_*`) or escape the asterisks (DASHSCOPE_\* →
ANTHROPIC_\*) so the asterisks are rendered literally; modify the table row with
the provider label "阿里云百炼 (DashScope)" and the cell containing DASHSCOPE_* →
ANTHROPIC_* accordingly.

| Amazon Bedrock | — | — | AWS SDK |
| Vertex AI | — | — | Google Cloud SDK |
| Azure Foundry | — | — | Azure SDK |

## 阿里云百炼 (DashScope)

### 概述

DashScope 是阿里云百炼平台的 **Anthropic 兼容 API** 端点。URL 路径 `/apps/anthropic` 明确表明其使用 Anthropic 接口协议。代码中将 `DASHSCOPE_*` 环境变量映射为 `ANTHROPIC_*`,然后走 firstParty Anthropic SDK 路径,**不经过 OpenAI 兼容层**。

### 默认配置

| 项目 | 值 |
|------|-----|
| Base URL | `https://coding.dashscope.aliyuncs.com/apps/anthropic` |
| OPUS 默认模型 | `qwen3-max-2026-01-23` |
| SONNET 默认模型 | `qwen3.6-plus` |
| HAIKU 默认模型 | `qwen3-coder-plus` |

### 支持的模型

| 模型 | 推荐用途 |
|------|---------|
| qwen3-max-2026-01-23 | OPUS 级能力 |
| qwen3.6-plus | SONNET 级能力 |
| qwen3.5-plus | SONNET 级备选 |
| qwen3-coder-next | 编码专用 |
| qwen3-coder-plus | HAIKU 级编码 |
| glm-5 | 智谱最新 |
| glm-4.7 | 智谱稳定 |
| kimi-k2.5 | 月之暗面 |
| MiniMax-M2.5 | MiniMax |

### 环境变量

| 变量名 | 必需 | 默认值 | 说明 |
|--------|------|--------|------|
| `DASHSCOPE_API_KEY` | 是 | — | DashScope API 密钥 → 映射为 `ANTHROPIC_AUTH_TOKEN` |
| `DASHSCOPE_BASE_URL` | 否 | `https://coding.dashscope.aliyuncs.com/apps/anthropic` | 自定义 API 端点 → 映射为 `ANTHROPIC_BASE_URL` |
| `DASHSCOPE_DEFAULT_OPUS_MODEL` | 否 | `qwen3-max-2026-01-23` | OPUS 级模型 |
| `DASHSCOPE_DEFAULT_SONNET_MODEL` | 否 | `qwen3.6-plus` | SONNET 级模型 |
| `DASHSCOPE_DEFAULT_HAIKU_MODEL` | 否 | `qwen3-coder-plus` | HAIKU 级模型 |
| `CLAUDE_CODE_USE_DASHSCOPE` | 否 | — | 环境变量启用 |

### 架构

```
用户输入 → /login → ConsoleOAuthFlow (DashScope UI)
→ 设置 modelType: 'anthropic'
→ 写入 ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN

启动 → getAPIProvider() 返回 'dashscope'
→ claude.ts 映射 DASHSCOPE_* → ANTHROPIC_* env
Comment on lines +61 to +66
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Provider selection flow is internally inconsistent.

Line 62 says /login writes modelType: 'anthropic', but Line 65 says getAPIProvider() returns 'dashscope'. Those cannot both be true unless an extra env-flag path is explicitly documented. This can lead to incorrect user configuration.

Based on learnings: Model provider selection follows the priority order: modelType parameter > environment variables > default firstParty; register new providers in src/utils/model/providers.ts.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/api-providers.md` around lines 61 - 66, The docs show conflicting
provider selection: ConsoleOAuthFlow setting modelType: 'anthropic' versus
getAPIProvider() returning 'dashscope'; update the documentation to reflect the
actual selection priority (modelType parameter > environment variables > default
firstParty) and explicitly describe the env-flag mapping path used by claude.ts
(DASHSCOPE_* → ANTHROPIC_*), and mention that new providers must be registered
in src/utils/model/providers.ts; ensure you reference ConsoleOAuthFlow,
modelType, getAPIProvider(), claude.ts, and src/utils/model/providers.ts so
readers know where to change behavior or add providers.

→ Anthropic SDK 自动读取 ANTHROPIC_BASE_URL
→ API 调用 DashScope Anthropic 兼容端点
```
Comment on lines +60 to +69
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language tag to the fenced block.

The fenced code block has no language identifier (markdownlint MD040).

🛠️ Suggested markdown fix
-```
+```text
 用户输入 → /login → ConsoleOAuthFlow (DashScope UI)
                 → 设置 modelType: 'anthropic'
                 → 写入 ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN
@@
      → Anthropic SDK 自动读取 ANTHROPIC_BASE_URL
      → API 调用 DashScope Anthropic 兼容端点
-```
+```
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 60-60: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/api-providers.md` around lines 60 - 69, The fenced code block starting
with "用户输入 → /login → ConsoleOAuthFlow (DashScope UI)" is missing a language
identifier; update the opening fence to include a language tag (e.g., change ```
to ```text) so the block becomes ```text ... ``` to satisfy markdownlint MD040.


### 关键文件

| 文件 | 作用 |
|------|------|
| `src/utils/model/providers.ts` | 添加 `'dashscope'` 到 APIProvider 类型和 `getAPIProvider()` |
| `src/utils/model/model.ts` | 3 个 getDefault 函数添加 DASHSCOPE_DEFAULT_* env 检查 |
| `src/services/api/claude.ts` | dashscope provider 映射 env → firstParty Anthropic 路径 |
| `src/components/ConsoleOAuthFlow.tsx` | DashScope 登录表单,保存为 `modelType: 'anthropic'` |

### 通过 /login 配置

1. 运行 `/login`
2. 选择 **"阿里云百炼 (DashScope) · Anthropic-compatible API"**
3. 输入 API Key(预填默认值,可直接修改)
4. 可选修改 Base URL、模型名称
5. 保存后重启生效

### 手动配置

```bash
# 环境变量方式
export DASHSCOPE_API_KEY="your-api-key"
export DASHSCOPE_BASE_URL="https://coding.dashscope.aliyuncs.com/apps/anthropic"

# 或在 ~/.claude/settings.json 中配置
{
"modelType": "anthropic",
"env": {
"ANTHROPIC_BASE_URL": "https://coding.dashscope.aliyuncs.com/apps/anthropic",
"ANTHROPIC_AUTH_TOKEN": "your-api-key",
"DASHSCOPE_DEFAULT_SONNET_MODEL": "qwen3.6-plus",
"DASHSCOPE_DEFAULT_OPUS_MODEL": "qwen3-max-2026-01-23",
"DASHSCOPE_DEFAULT_HAIKU_MODEL": "qwen3-coder-plus"
}
}
```
121 changes: 121 additions & 0 deletions docs/ui-rendering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# UI 渲染与界面层

> 记录 Claude Code 终端 UI(Ink 框架)的渲染行为、布局模式、常见问题及修复。

## LogoV2 启动欢迎界面

### 组件结构

```
LogoV2.tsx (src/components/LogoV2/)
├── CondensedLogo.tsx — 缩略模式(无边框,日常最常见)
├── LogoV2.tsx — 完整模式(有边框)/ 紧凑模式(有边框)
├── CondensedLogo.tsx — 缩略模式(无边框,日常最常见)
├── Clawd.tsx — ASCII 猫吉祥物
├── AnimatedClawd.tsx — 动画版 Clawd
├── FeedColumn.tsx — 右侧信息流(活动记录/更新日志)
└── WelcomeV2.tsx — 首次 Onboarding 欢迎文本
```
Comment on lines +9 to +18
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix the component-tree snippet.

This fence is missing a language tag (MD040), the root is labeled as a file even though it has children, and CondensedLogo.tsx appears twice.

📝 Suggested edit
-```
-LogoV2.tsx (src/components/LogoV2/)
-├── CondensedLogo.tsx   — 缩略模式(无边框,日常最常见)
-├── LogoV2.tsx          — 完整模式(有边框)/ 紧凑模式(有边框)
-├── CondensedLogo.tsx   — 缩略模式(无边框,日常最常见)
+```text
+src/components/LogoV2/
+├── LogoV2.tsx          — 完整模式(有边框)/ 紧凑模式(有边框)
+├── CondensedLogo.tsx   — 缩略模式(当前已永久关闭)
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 9-9: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/ui-rendering.md` around lines 9 - 18, Update the component-tree snippet
in docs/ui-rendering.md by replacing the current fenced block with a
language-tagged code fence (use "text"), make the root a directory path instead
of a file (e.g., "src/components/LogoV2/"), and remove the duplicated
CondensedLogo.tsx entry so the tree lists only the unique files; target the
snippet showing "LogoV2.tsx (src/components/LogoV2/)" and the duplicate
"CondensedLogo.tsx" lines and adjust their descriptions as needed (e.g., keep
"LogoV2.tsx" and a single "CondensedLogo.tsx" line with the correct note).


### 三种渲染模式

| 模式 | 触发条件 | 边框 | 说明 |
|------|---------|------|------|
| **缩略模式** (Condensed) | ~~无 Release Notes 且无首次引导~~ | ❌ | **已永久关闭**(2026-04-10),不再进入 |
| **紧凑模式** (Compact) | 终端宽度 < 70 列 | ✅ | 紫色圆角边框,内容居中 |
| **完整模式** (Full) | 默认路径 | ✅ | 紫色圆角边框,双栏布局 + 信息流 |

> **注**:缩略模式已在 `LogoV2.tsx` 中永久关闭(`isCondensedMode = false`),所有启动都走完整模式或紧凑模式。

### 模式判断逻辑(源码:`src/components/LogoV2/LogoV2.tsx`)

```typescript
// 原始逻辑:三种模式切换
const isCondensedMode =
!hasReleaseNotes &&
!showOnboarding &&
!isEnvTruthy(process.env.CLAUDE_CODE_FORCE_FULL_LOGO)

// 环境变量强制:始终显示完整模式
// CLAUDE_CODE_FORCE_FULL_LOGO=1 bun run dev
```

**CondensedLogo 内部**(`src/components/LogoV2/CondensedLogo.tsx`):无任何边框,纯文本 + ASCII 猫。
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Refresh this sentence to match the current code.

CondensedLogo.tsx now renders a rounded bordered container with borderText, so describing it as “无任何边框” is no longer accurate.

📝 Suggested edit
-**CondensedLogo 内部**(`src/components/LogoV2/CondensedLogo.tsx`):无任何边框,纯文本 + ASCII 猫。
+**CondensedLogo 内部**(`src/components/LogoV2/CondensedLogo.tsx`):当前实现也会渲染圆角边框和标题,但运行时路径已被永久关闭。
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**CondensedLogo 内部**`src/components/LogoV2/CondensedLogo.tsx`):无任何边框,纯文本 + ASCII 猫
**CondensedLogo 内部**`src/components/LogoV2/CondensedLogo.tsx`):当前实现也会渲染圆角边框和标题,但运行时路径已被永久关闭
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/ui-rendering.md` at line 43, Update the doc sentence that describes
CondensedLogo to reflect the current implementation: replace "无任何边框,纯文本 + ASCII
猫" with a description that the CondensedLogo component (CondensedLogo) renders a
rounded container with a visible border and displays the `borderText` value
alongside the ASCII cat; mention that the container is rounded and bordered
rather than borderless so the docs match the component behavior.


### 边框渲染机制

边框由 `@anthropic/ink` 的 `Box` 组件通过 `cli-boxes` 库绘制:

- `borderStyle="round"` → 使用 `cli-boxes` 的 `round` 样式(`╭─╮` `│` `╰─╯`)
- `borderColor="claude"` → 紫色主题色
- `borderText` → 边框顶部嵌入标题文本 "Claude Code"

详见 `packages/@ant/ink/src/core/render-border.ts`。

## 常见问题

### 问题:启动时欢迎边框时有时无

**原因**:日常启动(无 Release Notes、非首次使用)走缩略模式,不显示边框。

**修复**:在 `LogoV2.tsx` 中永久关闭缩略模式:

```diff
- const isCondensedMode =
- !hasReleaseNotes &&
- !showOnboarding &&
- !isEnvTruthy(process.env.CLAUDE_CODE_FORCE_FULL_LOGO)
+ const isCondensedMode = false

- if (
- !hasReleaseNotes &&
- !showOnboarding &&
- !isEnvTruthy(process.env.CLAUDE_CODE_FORCE_FULL_LOGO)
- ) {
+ if (false) {
return <CondensedLogo />
}
```

修改后,无论何种情况启动,都会显示完整模式的紫色圆角边框。

**影响**:
- 每次启动都会渲染完整的边框 + 信息流(活动记录或更新日志)
- 轻微增加启动渲染开销(从 0 边框到有边框双栏)
- 不再走 CondensedLogo(节省了 GuestPassesUpsell 等副作用计数逻辑)

### 问题:终端宽度不足导致边框变形

**原因**:`getLayoutMode(columns)` 在终端 < 70 列时切换到 compact 模式。

**参考**:`src/utils/logoV2Utils.ts` — `getLayoutMode(columns: number): LayoutMode`

### 问题:Recent Activity 显示 "No recent activity"

**原因**:`src/setup.ts` 中 `getRecentActivity()` 只在 `hasReleaseNotes` 为 true 时才调用。日常启动(无新 Release Notes)时,`cachedActivity` 始终为空数组。

**修复**(`src/setup.ts` 第 383-395 行):

```diff
if (!isBareMode()) {
- const { hasReleaseNotes } = await checkForReleaseNotes(
- getGlobalConfig().lastReleaseNotesSeen,
- )
- if (hasReleaseNotes) {
- await getRecentActivity()
- }
+ // Populate release notes cache (side effect: fetches changelog if needed)
+ void checkForReleaseNotes(getGlobalConfig().lastReleaseNotesSeen)
+ // Load recent activity unconditionally (not tied to release notes)
+ try {
+ await getRecentActivity()
+ } catch (error) {
+ logError('Failed to load recent activity:', error)
+ }
}
```

**关键变化**:
1. `getRecentActivity()` 从 `if (hasReleaseNotes)` 块中移出,无条件调用
2. 增加 try-catch 防止损坏的会话文件阻塞启动
3. `checkForReleaseNotes` 改为 `void` 调用(保留 cache 填充的副作用,但不阻塞等待结果)
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@
"docs:dev": "npx mintlify dev",
"rcs": "bun run scripts/rcs.ts"
},
"dependencies": {},
"dependencies": {
"string-width": "^8.2.0"
},
"devDependencies": {
"openai": "^6.33.0",
"@alcalzone/ansi-tokenize": "^0.3.0",
Expand Down
Loading