ai-account-switch 1.9.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.playwright-mcp/grid-view-before.png +0 -0
- package/.playwright-mcp/list-view.png +0 -0
- package/CLAUDE.md +338 -0
- package/README.md +3 -1
- package/package.json +45 -45
- package/src/accounts/base-account.js +39 -0
- package/src/accounts/ccr-account.js +118 -0
- package/src/accounts/claude-account.js +62 -0
- package/src/accounts/codex-account.js +192 -0
- package/src/accounts/droids-account.js +80 -0
- package/src/accounts/index.js +29 -0
- package/src/commands/account.js +68 -0
- package/src/commands/env.js +728 -0
- package/src/commands/helpers.js +32 -0
- package/src/commands/index.js +22 -1
- package/src/commands/mcp.js +71 -13
- package/src/config/global-config.js +266 -0
- package/src/config/project-config.js +255 -0
- package/src/config.js +129 -1300
- package/src/config.js.bak +1593 -0
- package/src/constants.js +86 -0
- package/src/generators/base-generator.js +124 -0
- package/src/generators/ccr-generator.js +113 -0
- package/src/generators/claude-generator.js +124 -0
- package/src/generators/codex-generator.js +207 -0
- package/src/generators/droids-generator.js +49 -0
- package/src/generators/index.js +29 -0
- package/src/index.js +63 -1
- package/src/mcp/mcp-manager.js +309 -0
- package/src/ui-server.js +1093 -9
|
Binary file
|
|
Binary file
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
本文件为 Claude Code (claude.ai/code) 在此仓库中工作时提供指导。
|
|
4
|
+
|
|
5
|
+
## 项目概述
|
|
6
|
+
|
|
7
|
+
AI Account Switch (ais) 是一个跨平台的命令行工具,用于在项目级别管理和切换不同的 AI 服务账号(Claude、Codex、CCR、Droids)。它会自动为各种 AI 工具生成配置文件,并提供 CLI 和 Web UI 两种界面。
|
|
8
|
+
|
|
9
|
+
## 开发命令
|
|
10
|
+
|
|
11
|
+
### 测试
|
|
12
|
+
```bash
|
|
13
|
+
# 本地运行 CLI 工具
|
|
14
|
+
npm test
|
|
15
|
+
|
|
16
|
+
# 全局链接以便测试
|
|
17
|
+
npm link
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 安装
|
|
21
|
+
```bash
|
|
22
|
+
# 安装依赖
|
|
23
|
+
npm install
|
|
24
|
+
|
|
25
|
+
# 开发时全局链接
|
|
26
|
+
npm link
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 架构设计
|
|
30
|
+
|
|
31
|
+
### 核心组件
|
|
32
|
+
|
|
33
|
+
**ConfigManager (`src/config.js`)**
|
|
34
|
+
- 中央配置管理类
|
|
35
|
+
- 处理全局配置 (`~/.ai-account-switch/config.json`) 和项目配置 (`.ais-project-config`)
|
|
36
|
+
- 实现智能目录检测(类似 git 向上搜索)
|
|
37
|
+
- 管理账号 ID、MCP 服务器和模型组
|
|
38
|
+
- 关键方法:
|
|
39
|
+
- `findProjectRoot()` - 向上搜索项目配置
|
|
40
|
+
- `readGlobalConfig()` / `saveGlobalConfig()` - 全局账号存储
|
|
41
|
+
- `readProjectConfig()` / `saveProjectConfig()` - 项目特定设置
|
|
42
|
+
- `generateClaudeConfig()` - 创建 `.claude/settings.local.json`
|
|
43
|
+
- `generateCodexProfile()` - 创建 Codex TOML profiles
|
|
44
|
+
- `generateCCRConfig()` - 更新 CCR router 配置
|
|
45
|
+
- `generateDroidsConfig()` - 创建 Droids JSON 配置
|
|
46
|
+
|
|
47
|
+
**命令模块 (`src/commands/`)**
|
|
48
|
+
- 模块化命令结构,单一职责
|
|
49
|
+
- `account.js` - 账号 CRUD 操作(添加、列表、使用、删除、导出)
|
|
50
|
+
- `model.js` - Claude 账号的模型组管理
|
|
51
|
+
- `mcp.js` - MCP (Model Context Protocol) 服务器管理
|
|
52
|
+
- `env.js` - 环境变量管理(列表、添加、设置、删除、显示、清空、编辑)
|
|
53
|
+
- `utility.js` - 诊断和辅助命令(doctor、paths)
|
|
54
|
+
- `helpers.js` - 共享工具函数(maskApiKey、验证)
|
|
55
|
+
- `index.js` - 统一导出接口
|
|
56
|
+
|
|
57
|
+
**Web UI 服务器 (`src/ui-server.js`)**
|
|
58
|
+
- 内嵌 HTML/CSS/JS 的 HTTP 服务器
|
|
59
|
+
- 提供账号管理的单页应用
|
|
60
|
+
- 账号、MCP 和环境变量操作的 REST API 端点
|
|
61
|
+
- 使用随机高位端口(49152-65535)避免冲突
|
|
62
|
+
- 支持双语界面(中文/英文)
|
|
63
|
+
|
|
64
|
+
**CLI 入口点 (`src/index.js`)**
|
|
65
|
+
- 基于 Commander.js 的 CLI 界面
|
|
66
|
+
- 定义所有命令和子命令
|
|
67
|
+
- 双语帮助文本(中文/英文)
|
|
68
|
+
|
|
69
|
+
### 生成的配置文件
|
|
70
|
+
|
|
71
|
+
**Claude Code 集成**
|
|
72
|
+
- `.claude/settings.local.json` - 项目级 Claude 配置
|
|
73
|
+
- 包含 `env.ANTHROPIC_AUTH_TOKEN` 和 `env.ANTHROPIC_BASE_URL`
|
|
74
|
+
- 包含账号配置中的自定义环境变量
|
|
75
|
+
- 自动添加到 `.gitignore`
|
|
76
|
+
|
|
77
|
+
**Codex 集成**
|
|
78
|
+
- `~/.codex/config.toml` - 全局 Codex profiles
|
|
79
|
+
- `.codex-profile` - 项目级 profile 引用
|
|
80
|
+
- 使用 OpenAI 兼容的 `wire_api = "chat"` 格式
|
|
81
|
+
- 支持三种 wire API 模式:chat、responses、env
|
|
82
|
+
- 自动为仅域名的 URL 添加 `/v1`
|
|
83
|
+
|
|
84
|
+
**CCR (Claude Code Router) 集成**
|
|
85
|
+
- `~/.claude-code-router/config.json` - CCR 配置
|
|
86
|
+
- 更新 Providers 和 Router 部分
|
|
87
|
+
- 配置更改后自动重启 CCR router
|
|
88
|
+
- 路由到本地 CCR 端点(默认端口 3456)
|
|
89
|
+
|
|
90
|
+
**Droids 集成**
|
|
91
|
+
- `.droids/config.json` - 项目级 Droids 配置
|
|
92
|
+
- 简单的模型配置结构
|
|
93
|
+
|
|
94
|
+
**MCP 集成**
|
|
95
|
+
- 在 `~/.ai-account-switch/config.json` 中全局管理
|
|
96
|
+
- 项目级启用状态在项目配置中跟踪
|
|
97
|
+
- 同步到 `.claude/settings.local.json` 的 `mcpServers` 键下
|
|
98
|
+
- 支持 stdio、sse 和 http 服务器类型
|
|
99
|
+
- 支持三种作用范围(scope):
|
|
100
|
+
- `local`(默认):仅当前项目可用,配置存储在全局,启用状态在项目配置中
|
|
101
|
+
- `project`:与项目成员共享,配置存储在项目配置的 `projectMcpServers` 中
|
|
102
|
+
- `user`:当前用户所有项目可用,配置存储在全局,自动在所有项目中启用
|
|
103
|
+
|
|
104
|
+
**环境变量管理 (env)**
|
|
105
|
+
- 项目级别:存储在 `.claude/settings.local.json` 的 `env` 属性中
|
|
106
|
+
- 用户级别:存储在 `~/.claude/settings.json` 的 `env` 属性中(跨平台兼容)
|
|
107
|
+
- 支持的命令:
|
|
108
|
+
- `ais env list` - 列出所有环境变量(项目和用户级别)
|
|
109
|
+
- `ais env add` - 交互式添加环境变量
|
|
110
|
+
- `ais env set <key> <value>` - 直接设置环境变量
|
|
111
|
+
- `ais env remove` / `ais env rm` - 交互式删除环境变量
|
|
112
|
+
- `ais env unset <key>` - 直接删除环境变量
|
|
113
|
+
- `ais env show <key>` - 显示特定环境变量的值
|
|
114
|
+
- `ais env clear` - 清空所有环境变量
|
|
115
|
+
- `ais env edit` - 交互式编辑环境变量
|
|
116
|
+
- 配置合并:更新环境变量时保留其他配置设置(permissions、statusLine、enabledPlugins)
|
|
117
|
+
- Web UI 支持:提供环境变量的可视化管理和编辑
|
|
118
|
+
|
|
119
|
+
### 账号类型及其行为
|
|
120
|
+
|
|
121
|
+
**Claude**
|
|
122
|
+
- 标准 Anthropic API 集成
|
|
123
|
+
- 支持包含多个模型配置的复杂模型组
|
|
124
|
+
- 环境变量传递给 Claude Code
|
|
125
|
+
|
|
126
|
+
**Codex**
|
|
127
|
+
- 在 `~/.codex/config.toml` 中生成 TOML profiles
|
|
128
|
+
- 创建项目级 `.codex-profile` 文件
|
|
129
|
+
- 处理重复 profile 清理
|
|
130
|
+
- 智能 URL 处理(需要时自动添加 `/v1`)
|
|
131
|
+
- 支持 wire_api 模式选择(chat/responses/env)
|
|
132
|
+
|
|
133
|
+
**CCR (Claude Code Router)**
|
|
134
|
+
- 同时更新 Provider 和 Router 配置
|
|
135
|
+
- 需要三种模型类型:default、background、think
|
|
136
|
+
- 在 Provider 配置中自动去重模型
|
|
137
|
+
- 通过 `ccr restart` 自动重启 CCR router
|
|
138
|
+
|
|
139
|
+
**Droids**
|
|
140
|
+
- 简单的配置结构
|
|
141
|
+
- 可选的模型规格
|
|
142
|
+
- 项目级 `.droids/config.json`
|
|
143
|
+
|
|
144
|
+
### 关键设计模式
|
|
145
|
+
|
|
146
|
+
**智能目录检测**
|
|
147
|
+
- 类似 git 的 `.git` 目录搜索
|
|
148
|
+
- `findProjectRoot()` 向上遍历目录树
|
|
149
|
+
- 允许命令在任何子目录中工作
|
|
150
|
+
- 如果未找到项目配置则回退到当前目录
|
|
151
|
+
|
|
152
|
+
**账号 ID 系统**
|
|
153
|
+
- 自动递增的数字 ID(从 1 开始)
|
|
154
|
+
- 允许通过 `ais use 1` 快速切换而不是完整名称
|
|
155
|
+
- 向后兼容现有账号
|
|
156
|
+
- 首次运行时在迁移期间分配 ID
|
|
157
|
+
|
|
158
|
+
**模型组**
|
|
159
|
+
- 每个 Claude 账号可以有多个模型组
|
|
160
|
+
- 活动模型组决定使用哪些模型
|
|
161
|
+
- 切换模型组会自动更新 Claude 配置
|
|
162
|
+
- 支持 DEFAULT_MODEL 作为未指定模型的回退
|
|
163
|
+
|
|
164
|
+
**MCP 服务器管理**
|
|
165
|
+
- 全局服务器定义,项目级启用
|
|
166
|
+
- 与 `.mcp.json` 双向同步(导入/导出)
|
|
167
|
+
- 通过 spawn/HTTP 请求进行连接测试
|
|
168
|
+
- 三种服务器类型,不同的配置模式
|
|
169
|
+
- 支持三种作用范围(scope):
|
|
170
|
+
- `local`:仅当前项目可用,服务器定义在全局配置,启用状态在项目配置中
|
|
171
|
+
- `project`:与项目成员共享,服务器定义存储在项目配置的 `projectMcpServers` 中
|
|
172
|
+
- `user`:当前用户所有项目可用,服务器定义在全局配置,自动在所有项目中启用
|
|
173
|
+
|
|
174
|
+
**配置隔离**
|
|
175
|
+
- 全局账号存储在用户主目录
|
|
176
|
+
- 项目配置从不包含敏感数据(仅账号引用)
|
|
177
|
+
- 自动更新 `.gitignore` 以保护敏感文件
|
|
178
|
+
- 通过 `os.homedir()` 和 `path.join()` 处理跨平台路径
|
|
179
|
+
|
|
180
|
+
## 重要实现细节
|
|
181
|
+
|
|
182
|
+
### Wire API 模式处理(Codex)
|
|
183
|
+
添加 Codex 账号时,工具支持三种 wire API 模式:
|
|
184
|
+
- `chat`(默认)- OpenAI 兼容的聊天格式
|
|
185
|
+
- `responses` - Anthropic responses 格式
|
|
186
|
+
- `env` - 使用环境变量进行身份验证
|
|
187
|
+
|
|
188
|
+
模式存储在账号配置中,并在生成 Codex profiles 时应用。
|
|
189
|
+
|
|
190
|
+
### URL 规范化(Codex)
|
|
191
|
+
工具智能处理 API URL:
|
|
192
|
+
- 仅域名的 URL(如 `https://api.example.com`)→ 自动添加 `/v1`
|
|
193
|
+
- 带路径的 URL(如 `https://api.example.com/v2`)→ 保持原样
|
|
194
|
+
- 这可以防止常见的 Cloudflare 400 错误
|
|
195
|
+
|
|
196
|
+
### CCR Router 集成
|
|
197
|
+
使用 CCR 账号时:
|
|
198
|
+
1. 使用 Provider 和 Router 配置更新 `~/.claude-code-router/config.json`
|
|
199
|
+
2. 从配置中动态读取 CCR 端口(默认 3456)
|
|
200
|
+
3. 生成指向 `http://127.0.0.1:{port}` 的 `.claude/settings.local.json`
|
|
201
|
+
4. 尝试通过 `ccr restart` 命令重启 CCR
|
|
202
|
+
5. 如果未找到 CCR CLI,提供清晰的后续步骤
|
|
203
|
+
|
|
204
|
+
### Doctor 命令
|
|
205
|
+
`ais doctor` 命令通过检查以下内容诊断配置问题:
|
|
206
|
+
- 当前目录和项目根目录
|
|
207
|
+
- AIS 项目配置是否存在
|
|
208
|
+
- Claude Code 配置(`.claude/settings.local.json`)
|
|
209
|
+
- 全局 Claude 配置(`~/.claude/settings.json`)
|
|
210
|
+
- 账号类型特定的配置(Codex TOML、CCR JSON、Droids JSON)
|
|
211
|
+
- 提供可操作的修复建议
|
|
212
|
+
|
|
213
|
+
### Web UI 架构
|
|
214
|
+
UI 服务器将所有 HTML/CSS/JS 嵌入单个文件:
|
|
215
|
+
- 无外部依赖或构建步骤
|
|
216
|
+
- 为根路径提供静态 HTML
|
|
217
|
+
- 数据操作的 REST API 端点
|
|
218
|
+
- 自动端口冲突解决
|
|
219
|
+
- 启动时自动打开浏览器
|
|
220
|
+
|
|
221
|
+
### 环境变量管理实现细节
|
|
222
|
+
**跨平台路径处理**
|
|
223
|
+
- 使用 `ConfigManager.getClaudeUserConfigPath()` 方法获取用户配置文件路径
|
|
224
|
+
- 优先级顺序:`~/.claude/settings.json` > 平台特定路径 > `~/.claude.json`(遗留)
|
|
225
|
+
- Windows 支持:`%APPDATA%\claude\settings.json`
|
|
226
|
+
- macOS/Linux 支持:`~/.config/claude/settings.json`
|
|
227
|
+
|
|
228
|
+
**配置合并策略**
|
|
229
|
+
- 读取现有配置文件,保留非 `env` 属性设置
|
|
230
|
+
- 仅更新 `env` 属性,不覆盖 `permissions`、`statusLine`、`enabledPlugins` 等
|
|
231
|
+
- 确保 `env` 属性存在,避免 `undefined` 错误
|
|
232
|
+
|
|
233
|
+
**命令模式**
|
|
234
|
+
- 交互式命令(add、remove、edit):使用 Inquirer.js 提供友好的用户界面
|
|
235
|
+
- 非交互式命令(set、unset、show):适合脚本和自动化
|
|
236
|
+
- 支持通过 `--level` 选项指定项目或用户级别
|
|
237
|
+
|
|
238
|
+
**安全性考虑**
|
|
239
|
+
- 显示环境变量时自动屏蔽包含 `KEY` 或 `TOKEN` 的变量值
|
|
240
|
+
- 支持在 Web UI 中安全地编辑敏感变量
|
|
241
|
+
|
|
242
|
+
## 测试注意事项
|
|
243
|
+
|
|
244
|
+
测试或修改时:
|
|
245
|
+
- 测试跨平台行为(macOS、Linux、Windows)
|
|
246
|
+
- 验证 `.gitignore` 更新正常工作
|
|
247
|
+
- 从各种子目录测试目录检测
|
|
248
|
+
- 确保账号 ID 迁移适用于现有配置
|
|
249
|
+
- 测试所有账号类型(Claude、Codex、CCR、Droids)
|
|
250
|
+
- 验证 MCP 服务器连接测试
|
|
251
|
+
- 在不同浏览器中测试 Web UI
|
|
252
|
+
- 测试环境变量命令的跨平台路径解析
|
|
253
|
+
- 验证环境变量配置合并不会丢失其他设置
|
|
254
|
+
- 测试环境变量在项目和用户级别的正确隔离
|
|
255
|
+
|
|
256
|
+
## 常见陷阱
|
|
257
|
+
|
|
258
|
+
**Codex Profile 重复**
|
|
259
|
+
- 写入新 profile 之前必须清理旧 profile
|
|
260
|
+
- 使用正则表达式匹配包括嵌套内容的整个 profile 部分
|
|
261
|
+
- 使用各种 TOML 结构进行测试
|
|
262
|
+
|
|
263
|
+
**CCR Router 重启**
|
|
264
|
+
- CCR CLI 必须已安装并在 PATH 中
|
|
265
|
+
- 优雅处理未找到 `ccr` 命令的情况
|
|
266
|
+
- 提供手动重启的清晰说明
|
|
267
|
+
|
|
268
|
+
**路径处理**
|
|
269
|
+
- 始终使用 `path.join()` 以实现跨平台兼容性
|
|
270
|
+
- 使用 `os.homedir()` 而不是 `~` 扩展
|
|
271
|
+
- 正确处理路径中的空格
|
|
272
|
+
|
|
273
|
+
**配置合并**
|
|
274
|
+
- 更新配置时,保留现有的非 AIS 设置
|
|
275
|
+
- 不要覆盖用户的自定义权限或其他设置
|
|
276
|
+
- 仅更新 AIS 管理的特定部分
|
|
277
|
+
|
|
278
|
+
**环境变量配置处理**
|
|
279
|
+
- 读取配置时确保 `env` 属性存在,避免 `undefined` 错误
|
|
280
|
+
- 写入配置时必须先读取现有配置,只合并 `env` 属性
|
|
281
|
+
- 使用跨平台兼容的路径方法 `ConfigManager.getClaudeUserConfigPath()`
|
|
282
|
+
- 不同操作系统的用户配置文件路径可能不同(Windows 使用 APPDATA,macOS/Linux 使用 .config)
|
|
283
|
+
|
|
284
|
+
**终端颜色使用规范**
|
|
285
|
+
⚠️ **重要:所有 CLI 输出必须严格遵守以下颜色规范**
|
|
286
|
+
|
|
287
|
+
| 颜色 | 用途 | 示例 |
|
|
288
|
+
|------|------|------|
|
|
289
|
+
| `chalk.green` | ✅ 成功操作、可用状态、完成标记 | `console.log(chalk.green('✓ Account added successfully!'))` |
|
|
290
|
+
| `chalk.red` | ❌ 错误、失败、不可用状态 | `console.error(chalk.red('✗ Error:'), error.message)` |
|
|
291
|
+
| `chalk.yellow` | ⚠️ 警告、取消操作、未配置、信息提示 | `console.log(chalk.yellow('⚠ No account set'))` |
|
|
292
|
+
| `chalk.cyan` | 📋 **标签**(如 "Path:", "Config:", "Level:")、信息标题、变量名 | `` `${chalk.cyan('Path:')} ${path}` `` |
|
|
293
|
+
| `chalk.yellow` | **变量值** | `` `${chalk.cyan(key)} = ${chalk.yellow(value)}` `` |
|
|
294
|
+
| `chalk.gray` | 辅助信息、次要内容、bullet 点 | `console.log(chalk.gray(' • Server name'))` |
|
|
295
|
+
| `chalk.bold` | 🔍 标题、章节标题 | `console.log(chalk.bold('COMMANDS:'))` |
|
|
296
|
+
| `chalk.green.bold` | 活动状态标记 | `console.log(chalk.green.bold('● Active'))` |
|
|
297
|
+
|
|
298
|
+
**格式规范:**
|
|
299
|
+
- **标签格式**:`` `${chalk.cyan('Label:')} value` ``(标签用 cyan,值用默认颜色)
|
|
300
|
+
- **错误格式**:`console.error(chalk.red('✗ Error:'), error.message)`
|
|
301
|
+
- **成功格式**:`console.log(chalk.green('✓ Success message'))`
|
|
302
|
+
- **警告格式**:`console.log(chalk.yellow('⚠ Warning message'))`
|
|
303
|
+
- **标题格式**:`console.log(chalk.bold('Section Title:'))`
|
|
304
|
+
|
|
305
|
+
**反面示例(禁止使用):**
|
|
306
|
+
```javascript
|
|
307
|
+
// ❌ 错误:标签不应该用 gray
|
|
308
|
+
console.log(chalk.gray(` Config: ${configPath}`));
|
|
309
|
+
|
|
310
|
+
// ❌ 错误:标签不应该用 bold
|
|
311
|
+
console.log(chalk.bold('Level:'), 'Project');
|
|
312
|
+
|
|
313
|
+
// ❌ 错误:不应该整行用一种颜色
|
|
314
|
+
console.log(chalk.cyan(` Config file: ${configPath}`));
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**正确示例:**
|
|
318
|
+
```javascript
|
|
319
|
+
// ✅ 正确:标签用 cyan,值用默认颜色
|
|
320
|
+
console.log(` ${chalk.cyan('Config:')} ${configPath}`);
|
|
321
|
+
|
|
322
|
+
// ✅ 正确:标题用 cyan
|
|
323
|
+
console.log(chalk.cyan(`\n📋 Environment Variables\n`));
|
|
324
|
+
|
|
325
|
+
// ✅ 正确:变量名用 cyan,值用 yellow
|
|
326
|
+
console.log(` ${chalk.gray('•')} ${chalk.cyan(key)} = ${chalk.yellow(value)}`);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## 文件命名约定
|
|
330
|
+
|
|
331
|
+
- 全局配置:`~/.ai-account-switch/config.json`
|
|
332
|
+
- 项目配置:`.ais-project-config`
|
|
333
|
+
- Claude 配置:`.claude/settings.local.json`
|
|
334
|
+
- Claude 用户配置:`~/.claude/settings.json`(跨平台:Windows `%APPDATA%\claude\settings.json`,macOS/Linux `~/.config/claude/settings.json`)
|
|
335
|
+
- Codex profile:`.codex-profile`
|
|
336
|
+
- Codex 全局:`~/.codex/config.toml`
|
|
337
|
+
- CCR 配置:`~/.claude-code-router/config.json`
|
|
338
|
+
- Droids 配置:`.droids/config.json`
|
package/README.md
CHANGED
|
@@ -1024,7 +1024,9 @@ ais mcp remove filesystem
|
|
|
1024
1024
|
MIT License - 欢迎在你的项目中使用此工具!
|
|
1025
1025
|
|
|
1026
1026
|
## 更新日志
|
|
1027
|
-
|
|
1027
|
+
### v1.9.1
|
|
1028
|
+
- **codex帐号添加env 配置方式**:
|
|
1029
|
+
- codex 支持env 临时export user-api-key 的方式认证.
|
|
1028
1030
|
### v1.9.0
|
|
1029
1031
|
- **账号ID功能**:
|
|
1030
1032
|
- 为每个账号自动分配唯一数字ID(从1开始递增)
|
package/package.json
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
2
|
+
"name": "ai-account-switch",
|
|
3
|
+
"version": "1.12.0",
|
|
4
|
+
"description": "A cross-platform CLI tool to manage and switch Claude/Codex/Droids account configurations",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ais": "./bin/ais.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node src/index.js",
|
|
11
|
+
"link": "npm link"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"cli",
|
|
15
|
+
"claude",
|
|
16
|
+
"codex",
|
|
17
|
+
"droids",
|
|
18
|
+
"account",
|
|
19
|
+
"switch",
|
|
20
|
+
"cross-platform",
|
|
21
|
+
"claude-code",
|
|
22
|
+
"ai",
|
|
23
|
+
"ai-assistant"
|
|
24
|
+
],
|
|
25
|
+
"author": "deanwanghewei@gmail.com",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"commander": "^11.0.0",
|
|
32
|
+
"chalk": "^4.1.2",
|
|
33
|
+
"inquirer": "^8.2.5"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=16.0.0"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/DeanWanghewei/ai-agent-user-swith.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/DeanWanghewei/ai-agent-user-swith/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/DeanWanghewei/ai-agent-user-swith#readme"
|
|
46
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Account Strategy
|
|
3
|
+
* Provides default behavior for account type-specific operations
|
|
4
|
+
*/
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
|
|
7
|
+
class BaseAccountStrategy {
|
|
8
|
+
constructor(accountType) {
|
|
9
|
+
this.accountType = accountType;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
showConfigTips() {
|
|
13
|
+
// Default: no tips
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async collectTypeSpecificData(inquirer) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
showUsageInstructions(accountName) {
|
|
21
|
+
console.log(
|
|
22
|
+
chalk.bold.cyan("\n📖 Usage Instructions (使用说明):\n")
|
|
23
|
+
);
|
|
24
|
+
console.log(
|
|
25
|
+
chalk.white("1. Switch to this account in your project (在项目中切换到此账号):")
|
|
26
|
+
);
|
|
27
|
+
console.log(chalk.cyan(` ais use ${accountName}\n`));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
showPostSwitchMessage(account) {
|
|
31
|
+
console.log(
|
|
32
|
+
chalk.cyan(
|
|
33
|
+
`✓ Configuration generated (配置已生成)`
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = BaseAccountStrategy;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CCR Account Strategy
|
|
3
|
+
* Handles CCR-specific account operations
|
|
4
|
+
*/
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const BaseAccountStrategy = require('./base-account');
|
|
7
|
+
|
|
8
|
+
class CCRAccountStrategy extends BaseAccountStrategy {
|
|
9
|
+
constructor() {
|
|
10
|
+
super('CCR');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
showConfigTips() {
|
|
14
|
+
console.log(
|
|
15
|
+
chalk.cyan("\n📝 CCR Configuration Tips (CCR 配置提示):")
|
|
16
|
+
);
|
|
17
|
+
console.log(
|
|
18
|
+
" • CCR configuration will be stored in ~/.claude-code-router/config.json"
|
|
19
|
+
);
|
|
20
|
+
console.log(
|
|
21
|
+
" • You need to provide Provider name and models (您需要提供 Provider 名称和模型列表)"
|
|
22
|
+
);
|
|
23
|
+
console.log(
|
|
24
|
+
" • Router configuration will be automatically updated (Router 配置将自动更新)\n"
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async collectTypeSpecificData(inquirer) {
|
|
29
|
+
const ccrConfig = await inquirer.prompt([
|
|
30
|
+
{
|
|
31
|
+
type: "input",
|
|
32
|
+
name: "providerName",
|
|
33
|
+
message: "Enter Provider name (请输入 Provider 名称):",
|
|
34
|
+
validate: (input) =>
|
|
35
|
+
input.trim() !== "" || "Provider name is required (Provider 名称不能为空)",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "input",
|
|
39
|
+
name: "defaultModel",
|
|
40
|
+
message: "Enter default model (请输入 default 模型):",
|
|
41
|
+
validate: (input) =>
|
|
42
|
+
input.trim() !== "" || "Default model is required (默认模型不能为空)",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: "input",
|
|
46
|
+
name: "backgroundModel",
|
|
47
|
+
message: "Enter background model (请输入 background 模型):",
|
|
48
|
+
validate: (input) =>
|
|
49
|
+
input.trim() !== "" || "Background model is required (background 模型不能为空)",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: "input",
|
|
53
|
+
name: "thinkModel",
|
|
54
|
+
message: "Enter think model (请输入 think 模型):",
|
|
55
|
+
validate: (input) =>
|
|
56
|
+
input.trim() !== "" || "Think model is required (think 模型不能为空)",
|
|
57
|
+
},
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
const models = [
|
|
61
|
+
ccrConfig.defaultModel.trim(),
|
|
62
|
+
ccrConfig.backgroundModel.trim(),
|
|
63
|
+
ccrConfig.thinkModel.trim()
|
|
64
|
+
];
|
|
65
|
+
const uniqueModels = [...new Set(models)];
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
ccrConfig: {
|
|
69
|
+
providerName: ccrConfig.providerName.trim(),
|
|
70
|
+
models: uniqueModels,
|
|
71
|
+
defaultModel: ccrConfig.defaultModel.trim(),
|
|
72
|
+
backgroundModel: ccrConfig.backgroundModel.trim(),
|
|
73
|
+
thinkModel: ccrConfig.thinkModel.trim(),
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
showUsageInstructions(accountName) {
|
|
79
|
+
super.showUsageInstructions(accountName);
|
|
80
|
+
console.log(
|
|
81
|
+
chalk.white(
|
|
82
|
+
"2. CCR configuration will be updated in ~/.claude-code-router/config.json"
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
showPostSwitchMessage(account) {
|
|
88
|
+
console.log(
|
|
89
|
+
chalk.cyan(
|
|
90
|
+
`✓ CCR configuration updated at: ~/.claude-code-router/config.json`
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
console.log(
|
|
94
|
+
chalk.cyan(
|
|
95
|
+
`✓ Claude configuration generated at: .claude/settings.local.json`
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
console.log("");
|
|
99
|
+
console.log(chalk.bold.cyan("📖 Next Steps (下一步):"));
|
|
100
|
+
console.log(
|
|
101
|
+
chalk.yellow(
|
|
102
|
+
` Start interactive session: ${chalk.bold("claude")}`
|
|
103
|
+
)
|
|
104
|
+
);
|
|
105
|
+
console.log(
|
|
106
|
+
chalk.white(
|
|
107
|
+
" This will enter project-level interactive mode (这将进入项目级交互模式)"
|
|
108
|
+
)
|
|
109
|
+
);
|
|
110
|
+
console.log(
|
|
111
|
+
chalk.white(
|
|
112
|
+
" Claude Code will use CCR Router to route requests (Claude Code 将使用 CCR Router 路由请求)"
|
|
113
|
+
)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = CCRAccountStrategy;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Account Strategy
|
|
3
|
+
* Handles Claude-specific account operations
|
|
4
|
+
*/
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const BaseAccountStrategy = require('./base-account');
|
|
7
|
+
|
|
8
|
+
class ClaudeAccountStrategy extends BaseAccountStrategy {
|
|
9
|
+
constructor() {
|
|
10
|
+
super('Claude');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
showConfigTips() {
|
|
14
|
+
// No special tips needed for Claude accounts
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async collectTypeSpecificData(inquirer) {
|
|
18
|
+
// Claude accounts use model groups, handled separately
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
showUsageInstructions(accountName) {
|
|
23
|
+
super.showUsageInstructions(accountName);
|
|
24
|
+
console.log(
|
|
25
|
+
chalk.white(
|
|
26
|
+
"2. Start Claude Code in your project directory (在项目目录中启动 Claude Code)"
|
|
27
|
+
)
|
|
28
|
+
);
|
|
29
|
+
console.log(
|
|
30
|
+
chalk.white(
|
|
31
|
+
"3. Claude Code will automatically use the project configuration (Claude Code 将自动使用项目配置)\n"
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
showPostSwitchMessage(account) {
|
|
37
|
+
console.log(
|
|
38
|
+
chalk.cyan(
|
|
39
|
+
`✓ Claude configuration generated at: .claude/settings.local.json`
|
|
40
|
+
)
|
|
41
|
+
);
|
|
42
|
+
console.log("");
|
|
43
|
+
console.log(chalk.bold.cyan("📖 Next Steps (下一步):"));
|
|
44
|
+
console.log(
|
|
45
|
+
chalk.yellow(
|
|
46
|
+
` Start interactive session: ${chalk.bold("claude")}`
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
console.log(
|
|
50
|
+
chalk.white(
|
|
51
|
+
" This will enter project-level interactive mode (这将进入项目级交互模式)"
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
console.log(
|
|
55
|
+
chalk.white(
|
|
56
|
+
" Claude Code will automatically use the project configuration (Claude Code 将自动使用项目配置)"
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = ClaudeAccountStrategy;
|