ccjk 2.2.2 → 2.2.5
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/dist/chunks/auto-updater.mjs +37 -3
- package/dist/chunks/ccjk-config.mjs +77 -13
- package/dist/chunks/ccr.mjs +8 -11
- package/dist/chunks/ccu.mjs +4 -4
- package/dist/chunks/check-updates.mjs +5 -8
- package/dist/chunks/claude-code-config-manager.mjs +8 -11
- package/dist/chunks/claude-code-incremental-manager.mjs +4 -7
- package/dist/chunks/codex.mjs +496 -17
- package/dist/chunks/commands.mjs +392 -89
- package/dist/chunks/commands2.mjs +109 -0
- package/dist/chunks/config-consolidator.mjs +2 -2
- package/dist/chunks/config-switch.mjs +5 -8
- package/dist/chunks/doctor.mjs +6 -6
- package/dist/chunks/features.mjs +654 -35
- package/dist/chunks/help.mjs +339 -0
- package/dist/chunks/index.mjs +323 -10
- package/dist/chunks/index2.mjs +3 -3
- package/dist/chunks/index3.mjs +1171 -0
- package/dist/chunks/init.mjs +22 -25
- package/dist/chunks/installer.mjs +178 -0
- package/dist/chunks/interview.mjs +6 -6
- package/dist/chunks/mcp-performance.mjs +82 -2
- package/dist/chunks/mcp.mjs +500 -0
- package/dist/chunks/menu.mjs +10 -10
- package/dist/chunks/notification.mjs +5 -5
- package/dist/chunks/onboarding.mjs +6 -6
- package/dist/chunks/package.mjs +1 -1
- package/dist/chunks/platform.mjs +10 -10
- package/dist/chunks/prompts.mjs +7 -8
- package/dist/chunks/session.mjs +2 -2
- package/dist/chunks/skills-sync.mjs +2 -2
- package/dist/chunks/uninstall.mjs +4 -5
- package/dist/chunks/update.mjs +5 -8
- package/dist/chunks/upgrade-manager.mjs +2 -2
- package/dist/{shared/ccjk.Cy-RH2qV.mjs → chunks/version-checker.mjs} +373 -30
- package/dist/cli.mjs +293 -53
- package/dist/i18n/locales/en/agentBrowser.json +79 -0
- package/dist/i18n/locales/en/mcp.json +2 -4
- package/dist/i18n/locales/en/updater.json +5 -2
- package/dist/i18n/locales/zh/agentBrowser.json +79 -0
- package/dist/i18n/locales/zh-CN/common.json +1 -1
- package/dist/i18n/locales/zh-CN/mcp.json +2 -4
- package/dist/i18n/locales/zh-CN/updater.json +5 -2
- package/dist/index.d.mts +8 -584
- package/dist/index.d.ts +8 -584
- package/dist/index.mjs +10 -14
- package/dist/shared/{ccjk.DJM5aVQJ.mjs → ccjk.ByTIGCUC.mjs} +3 -3
- package/dist/shared/{ccjk.qYAnUMuy.mjs → ccjk.CGTmRqsu.mjs} +2 -3
- package/dist/shared/{ccjk.CUdzQluX.mjs → ccjk.CURU8gbR.mjs} +1 -1
- package/dist/{chunks/mcp-market.mjs → shared/ccjk.D-RZS4E2.mjs} +6 -65
- package/dist/shared/{ccjk.B7169qud.mjs → ccjk.tB4-Y4Qb.mjs} +3 -3
- package/package.json +4 -1
- package/templates/common/skills/en/agent-browser.md +258 -0
- package/templates/common/skills/zh-CN/agent-browser.md +260 -0
- package/dist/chunks/claude-config.mjs +0 -228
- package/dist/chunks/features2.mjs +0 -661
- package/dist/chunks/json-config.mjs +0 -59
- package/dist/chunks/mcp-doctor.mjs +0 -160
- package/dist/chunks/mcp-profile.mjs +0 -220
- package/dist/chunks/mcp-release.mjs +0 -138
- package/dist/chunks/shencha.mjs +0 -320
- package/dist/chunks/tools.mjs +0 -169
- package/dist/shared/ccjk.COdsoe-Y.mjs +0 -64
- package/dist/shared/ccjk.DwDtZ5cK.mjs +0 -266
- package/dist/shared/ccjk.n_AtlHzB.mjs +0 -186
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-browser
|
|
3
|
+
description: 零配置无头浏览器自动化,专为 AI 代理设计
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Vercel Labs / CCJK
|
|
6
|
+
category: automation
|
|
7
|
+
triggers:
|
|
8
|
+
- /browser
|
|
9
|
+
- /web
|
|
10
|
+
- /scrape
|
|
11
|
+
- /test-ui
|
|
12
|
+
- /浏览器
|
|
13
|
+
- /网页
|
|
14
|
+
use_when:
|
|
15
|
+
- "用户需要网页自动化或浏览器控制"
|
|
16
|
+
- "用户想要抓取或与网站交互"
|
|
17
|
+
- "用户需要 UI 测试或截图"
|
|
18
|
+
- "用户提到浏览器、网页或网站交互"
|
|
19
|
+
auto_activate: true
|
|
20
|
+
priority: 8
|
|
21
|
+
difficulty: beginner
|
|
22
|
+
tags:
|
|
23
|
+
- browser
|
|
24
|
+
- automation
|
|
25
|
+
- web
|
|
26
|
+
- zero-config
|
|
27
|
+
- ai-native
|
|
28
|
+
dependencies:
|
|
29
|
+
- agent-browser
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# Agent Browser - 零配置网页自动化
|
|
33
|
+
|
|
34
|
+
> **核心理念**: AI 原生、零配置、基于引用的交互
|
|
35
|
+
|
|
36
|
+
专为 AI 代理设计的无头浏览器自动化工具。快速的 Rust CLI,Node.js 作为后备。
|
|
37
|
+
|
|
38
|
+
## 快速开始
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# 一次性安装(通常自动检测,无需手动)
|
|
42
|
+
agent-browser install
|
|
43
|
+
|
|
44
|
+
# 核心工作流
|
|
45
|
+
agent-browser open <url> # 导航
|
|
46
|
+
agent-browser snapshot -i # 获取带引用的交互元素
|
|
47
|
+
agent-browser click @e1 # 通过引用点击
|
|
48
|
+
agent-browser fill @e2 "文本" # 通过引用填充
|
|
49
|
+
agent-browser screenshot page.png # 截图
|
|
50
|
+
agent-browser close # 完成
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 为什么选择 Agent Browser?
|
|
54
|
+
|
|
55
|
+
| 特性 | Agent Browser | 传统 MCP |
|
|
56
|
+
|------|--------------|----------|
|
|
57
|
+
| 配置 | 零配置 | 复杂 JSON 配置 |
|
|
58
|
+
| 速度 | 原生 Rust | Node.js 开销 |
|
|
59
|
+
| AI 原生 | 基于引用 (@e1) | CSS 选择器 |
|
|
60
|
+
| 内存 | 极小 | 重量级守护进程 |
|
|
61
|
+
| 学习曲线 | 5 分钟 | 数小时 |
|
|
62
|
+
|
|
63
|
+
## 核心命令
|
|
64
|
+
|
|
65
|
+
### 导航
|
|
66
|
+
```bash
|
|
67
|
+
agent-browser open example.com # 打开 URL
|
|
68
|
+
agent-browser back # 后退
|
|
69
|
+
agent-browser forward # 前进
|
|
70
|
+
agent-browser reload # 刷新页面
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 快照(AI 优化)
|
|
74
|
+
```bash
|
|
75
|
+
agent-browser snapshot # 完整无障碍树
|
|
76
|
+
agent-browser snapshot -i # 仅交互元素(推荐)
|
|
77
|
+
agent-browser snapshot -c # 紧凑模式
|
|
78
|
+
agent-browser snapshot -d 3 # 限制深度
|
|
79
|
+
agent-browser snapshot -i -c # 组合选项
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**输出示例:**
|
|
83
|
+
```
|
|
84
|
+
- heading "示例域名" [ref=e1] [level=1]
|
|
85
|
+
- button "提交" [ref=e2]
|
|
86
|
+
- textbox "邮箱" [ref=e3]
|
|
87
|
+
- link "了解更多" [ref=e4]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 交互(基于引用)
|
|
91
|
+
```bash
|
|
92
|
+
agent-browser click @e2 # 点击元素
|
|
93
|
+
agent-browser fill @e3 "email@test.com" # 填充输入
|
|
94
|
+
agent-browser hover @e4 # 悬停元素
|
|
95
|
+
agent-browser check @e5 # 勾选复选框
|
|
96
|
+
agent-browser select @e6 "选项" # 选择下拉菜单
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 获取信息
|
|
100
|
+
```bash
|
|
101
|
+
agent-browser get text @e1 # 获取文本内容
|
|
102
|
+
agent-browser get html @e1 # 获取 innerHTML
|
|
103
|
+
agent-browser get value @e3 # 获取输入值
|
|
104
|
+
agent-browser get title # 页面标题
|
|
105
|
+
agent-browser get url # 当前 URL
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### 截图和 PDF
|
|
109
|
+
```bash
|
|
110
|
+
agent-browser screenshot # 视口截图
|
|
111
|
+
agent-browser screenshot --full # 全页面
|
|
112
|
+
agent-browser screenshot page.png # 保存到文件
|
|
113
|
+
agent-browser pdf report.pdf # 保存为 PDF
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 等待操作
|
|
117
|
+
```bash
|
|
118
|
+
agent-browser wait @e1 # 等待元素
|
|
119
|
+
agent-browser wait 2000 # 等待 2 秒
|
|
120
|
+
agent-browser wait --text "欢迎" # 等待文本出现
|
|
121
|
+
agent-browser wait --load networkidle # 等待加载完成
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 最佳 AI 工作流
|
|
125
|
+
|
|
126
|
+
### 模式 1:简单交互
|
|
127
|
+
```bash
|
|
128
|
+
agent-browser open example.com
|
|
129
|
+
agent-browser snapshot -i --json # 解析引用
|
|
130
|
+
agent-browser click @e2 # 执行操作
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 模式 2:表单填写
|
|
134
|
+
```bash
|
|
135
|
+
agent-browser open login.example.com
|
|
136
|
+
agent-browser snapshot -i
|
|
137
|
+
agent-browser fill @e1 "用户名"
|
|
138
|
+
agent-browser fill @e2 "密码"
|
|
139
|
+
agent-browser click @e3 # 提交按钮
|
|
140
|
+
agent-browser wait --text "仪表板"
|
|
141
|
+
agent-browser snapshot -i # 验证成功
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 模式 3:数据提取
|
|
145
|
+
```bash
|
|
146
|
+
agent-browser open data.example.com
|
|
147
|
+
agent-browser snapshot -i
|
|
148
|
+
agent-browser get text @e1 # 提取特定数据
|
|
149
|
+
agent-browser screenshot data.png # 视觉记录
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 模式 4:多页面流程
|
|
153
|
+
```bash
|
|
154
|
+
agent-browser open shop.example.com
|
|
155
|
+
agent-browser snapshot -i
|
|
156
|
+
agent-browser click @e5 # 产品链接
|
|
157
|
+
agent-browser wait --load networkidle
|
|
158
|
+
agent-browser snapshot -i # 新页面引用
|
|
159
|
+
agent-browser click @e2 # 加入购物车
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 会话(并行浏览器)
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# 运行多个隔离会话
|
|
166
|
+
agent-browser --session agent1 open site-a.com
|
|
167
|
+
agent-browser --session agent2 open site-b.com
|
|
168
|
+
|
|
169
|
+
# 列出会话
|
|
170
|
+
agent-browser session list
|
|
171
|
+
|
|
172
|
+
# 每个会话独立拥有:
|
|
173
|
+
# - Cookie 和存储
|
|
174
|
+
# - 导航历史
|
|
175
|
+
# - 认证状态
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## 高级功能
|
|
179
|
+
|
|
180
|
+
### 语义定位器(后备方案)
|
|
181
|
+
```bash
|
|
182
|
+
agent-browser find role button click --name "提交"
|
|
183
|
+
agent-browser find label "邮箱" fill "test@test.com"
|
|
184
|
+
agent-browser find text "登录" click
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 网络控制
|
|
188
|
+
```bash
|
|
189
|
+
agent-browser network requests # 查看请求
|
|
190
|
+
agent-browser network route "**/api" --abort # 阻止请求
|
|
191
|
+
agent-browser set offline on # 离线模式
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 调试模式
|
|
195
|
+
```bash
|
|
196
|
+
agent-browser open example.com --headed # 显示浏览器窗口
|
|
197
|
+
agent-browser console # 查看控制台日志
|
|
198
|
+
agent-browser errors # 查看页面错误
|
|
199
|
+
agent-browser highlight @e1 # 高亮元素
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## 集成示例
|
|
203
|
+
|
|
204
|
+
### 与 Workflow 技能配合
|
|
205
|
+
```bash
|
|
206
|
+
# 在 /workflow 执行阶段
|
|
207
|
+
agent-browser open $TEST_URL
|
|
208
|
+
agent-browser snapshot -i
|
|
209
|
+
# AI 分析快照,识别测试目标
|
|
210
|
+
agent-browser click @e2
|
|
211
|
+
agent-browser wait --text "成功"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### 与 TDD 技能配合
|
|
215
|
+
```bash
|
|
216
|
+
# E2E 测试执行
|
|
217
|
+
agent-browser open localhost:3000
|
|
218
|
+
agent-browser snapshot -i
|
|
219
|
+
agent-browser fill @e1 "测试输入"
|
|
220
|
+
agent-browser click @e2
|
|
221
|
+
agent-browser get text @e3 # 验证输出
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## 最佳实践
|
|
225
|
+
|
|
226
|
+
1. **始终使用 `-i` 标志** 获取快照(仅交互元素)
|
|
227
|
+
2. **使用引用 (@e1)** 而非 CSS 选择器
|
|
228
|
+
3. **页面变化后重新快照** 获取新引用
|
|
229
|
+
4. **使用 `--json` 标志** 进行程序化解析
|
|
230
|
+
5. **配合 wait 使用** 处理动态内容
|
|
231
|
+
|
|
232
|
+
## 故障排除
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# 浏览器未安装
|
|
236
|
+
agent-browser install
|
|
237
|
+
|
|
238
|
+
# Linux 依赖
|
|
239
|
+
agent-browser install --with-deps
|
|
240
|
+
|
|
241
|
+
# 调试问题
|
|
242
|
+
agent-browser open url --headed --debug
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 命令参考
|
|
246
|
+
|
|
247
|
+
| 命令 | 描述 |
|
|
248
|
+
|------|------|
|
|
249
|
+
| `open <url>` | 导航到 URL |
|
|
250
|
+
| `snapshot [-i] [-c]` | 获取无障碍树 |
|
|
251
|
+
| `click @ref` | 点击元素 |
|
|
252
|
+
| `fill @ref "text"` | 填充输入 |
|
|
253
|
+
| `get text @ref` | 获取文本内容 |
|
|
254
|
+
| `screenshot [path]` | 截图 |
|
|
255
|
+
| `wait <ref\|ms\|--text>` | 等待条件 |
|
|
256
|
+
| `close` | 关闭浏览器 |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
**零配置。AI 原生。开箱即用。**
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { join } from 'pathe';
|
|
2
|
-
import { CLAUDE_VSC_CONFIG_FILE, CLAUDE_DIR, ClAUDE_CONFIG_FILE } from './constants.mjs';
|
|
3
|
-
import { ensureI18nInitialized, i18n } from './index2.mjs';
|
|
4
|
-
import { readJsonConfig, writeJsonConfig, backupJsonConfig } from './json-config.mjs';
|
|
5
|
-
import { isWindows, getMcpCommand } from './platform.mjs';
|
|
6
|
-
|
|
7
|
-
function mergeArraysUnique(arr1, arr2) {
|
|
8
|
-
const combined = [...arr1 || [], ...arr2 || []];
|
|
9
|
-
return [...new Set(combined)];
|
|
10
|
-
}
|
|
11
|
-
function isPlainObject(value) {
|
|
12
|
-
return value !== null && typeof value === "object" && value.constructor === Object && Object.prototype.toString.call(value) === "[object Object]";
|
|
13
|
-
}
|
|
14
|
-
function deepMerge(target, source, options = {}) {
|
|
15
|
-
const { mergeArrays = false, arrayMergeStrategy = "replace" } = options;
|
|
16
|
-
const result = { ...target };
|
|
17
|
-
for (const key in source) {
|
|
18
|
-
const sourceValue = source[key];
|
|
19
|
-
const targetValue = result[key];
|
|
20
|
-
if (sourceValue === void 0) {
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
if (isPlainObject(sourceValue) && isPlainObject(targetValue)) {
|
|
24
|
-
result[key] = deepMerge(targetValue, sourceValue, options);
|
|
25
|
-
} else if (Array.isArray(sourceValue)) {
|
|
26
|
-
if (!mergeArrays || !Array.isArray(targetValue)) {
|
|
27
|
-
result[key] = sourceValue;
|
|
28
|
-
} else {
|
|
29
|
-
switch (arrayMergeStrategy) {
|
|
30
|
-
case "concat":
|
|
31
|
-
result[key] = [...targetValue, ...sourceValue];
|
|
32
|
-
break;
|
|
33
|
-
case "unique":
|
|
34
|
-
result[key] = mergeArraysUnique(targetValue, sourceValue);
|
|
35
|
-
break;
|
|
36
|
-
case "replace":
|
|
37
|
-
default:
|
|
38
|
-
result[key] = sourceValue;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
} else {
|
|
43
|
-
result[key] = sourceValue;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
function deepClone(obj) {
|
|
49
|
-
if (obj === null || typeof obj !== "object") {
|
|
50
|
-
return obj;
|
|
51
|
-
}
|
|
52
|
-
if (obj instanceof Date) {
|
|
53
|
-
return new Date(obj.getTime());
|
|
54
|
-
}
|
|
55
|
-
if (Array.isArray(obj)) {
|
|
56
|
-
return obj.map((item) => deepClone(item));
|
|
57
|
-
}
|
|
58
|
-
if (isPlainObject(obj)) {
|
|
59
|
-
const cloned = {};
|
|
60
|
-
for (const key in obj) {
|
|
61
|
-
cloned[key] = deepClone(obj[key]);
|
|
62
|
-
}
|
|
63
|
-
return cloned;
|
|
64
|
-
}
|
|
65
|
-
return obj;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function getMcpConfigPath() {
|
|
69
|
-
return ClAUDE_CONFIG_FILE;
|
|
70
|
-
}
|
|
71
|
-
function readMcpConfig() {
|
|
72
|
-
return readJsonConfig(ClAUDE_CONFIG_FILE);
|
|
73
|
-
}
|
|
74
|
-
function writeMcpConfig(config) {
|
|
75
|
-
writeJsonConfig(ClAUDE_CONFIG_FILE, config);
|
|
76
|
-
}
|
|
77
|
-
function backupMcpConfig() {
|
|
78
|
-
const backupBaseDir = join(CLAUDE_DIR, "backup");
|
|
79
|
-
return backupJsonConfig(ClAUDE_CONFIG_FILE, backupBaseDir);
|
|
80
|
-
}
|
|
81
|
-
function mergeMcpServers(existing, newServers) {
|
|
82
|
-
const config = existing || { mcpServers: {} };
|
|
83
|
-
if (!config.mcpServers) {
|
|
84
|
-
config.mcpServers = {};
|
|
85
|
-
}
|
|
86
|
-
Object.assign(config.mcpServers, newServers);
|
|
87
|
-
return config;
|
|
88
|
-
}
|
|
89
|
-
function applyPlatformCommand(config) {
|
|
90
|
-
if (isWindows() && config.command) {
|
|
91
|
-
const mcpCmd = getMcpCommand(config.command);
|
|
92
|
-
if (mcpCmd[0] === "cmd") {
|
|
93
|
-
config.command = mcpCmd[0];
|
|
94
|
-
config.args = [...mcpCmd.slice(1), ...config.args || []];
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function buildMcpServerConfig(baseConfig, apiKey, placeholder = "YOUR_EXA_API_KEY", envVarName) {
|
|
99
|
-
const config = deepClone(baseConfig);
|
|
100
|
-
applyPlatformCommand(config);
|
|
101
|
-
if (!apiKey) {
|
|
102
|
-
return config;
|
|
103
|
-
}
|
|
104
|
-
if (envVarName && config.env) {
|
|
105
|
-
config.env[envVarName] = apiKey;
|
|
106
|
-
return config;
|
|
107
|
-
}
|
|
108
|
-
if (config.args) {
|
|
109
|
-
config.args = config.args.map((arg) => arg.replace(placeholder, apiKey));
|
|
110
|
-
}
|
|
111
|
-
if (config.url) {
|
|
112
|
-
config.url = config.url.replace(placeholder, apiKey);
|
|
113
|
-
}
|
|
114
|
-
return config;
|
|
115
|
-
}
|
|
116
|
-
function fixWindowsMcpConfig(config) {
|
|
117
|
-
if (!isWindows() || !config.mcpServers) {
|
|
118
|
-
return config;
|
|
119
|
-
}
|
|
120
|
-
const fixed = { ...config };
|
|
121
|
-
for (const [, serverConfig] of Object.entries(fixed.mcpServers)) {
|
|
122
|
-
if (serverConfig && typeof serverConfig === "object" && "command" in serverConfig) {
|
|
123
|
-
applyPlatformCommand(serverConfig);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return fixed;
|
|
127
|
-
}
|
|
128
|
-
function addCompletedOnboarding() {
|
|
129
|
-
try {
|
|
130
|
-
let config = readMcpConfig();
|
|
131
|
-
if (!config) {
|
|
132
|
-
config = { mcpServers: {} };
|
|
133
|
-
}
|
|
134
|
-
if (config.hasCompletedOnboarding === true) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
config.hasCompletedOnboarding = true;
|
|
138
|
-
writeMcpConfig(config);
|
|
139
|
-
} catch (error) {
|
|
140
|
-
console.error("Failed to add onboarding flag", error);
|
|
141
|
-
throw error;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
function ensureApiKeyApproved(config, apiKey) {
|
|
145
|
-
if (!apiKey || typeof apiKey !== "string" || apiKey.trim() === "") {
|
|
146
|
-
return config;
|
|
147
|
-
}
|
|
148
|
-
const truncatedApiKey = apiKey.substring(0, 20);
|
|
149
|
-
const updatedConfig = { ...config };
|
|
150
|
-
if (!updatedConfig.customApiKeyResponses) {
|
|
151
|
-
updatedConfig.customApiKeyResponses = {
|
|
152
|
-
approved: [],
|
|
153
|
-
rejected: []
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
if (!Array.isArray(updatedConfig.customApiKeyResponses.approved)) {
|
|
157
|
-
updatedConfig.customApiKeyResponses.approved = [];
|
|
158
|
-
}
|
|
159
|
-
if (!Array.isArray(updatedConfig.customApiKeyResponses.rejected)) {
|
|
160
|
-
updatedConfig.customApiKeyResponses.rejected = [];
|
|
161
|
-
}
|
|
162
|
-
const rejectedIndex = updatedConfig.customApiKeyResponses.rejected.indexOf(truncatedApiKey);
|
|
163
|
-
if (rejectedIndex > -1) {
|
|
164
|
-
updatedConfig.customApiKeyResponses.rejected.splice(rejectedIndex, 1);
|
|
165
|
-
}
|
|
166
|
-
if (!updatedConfig.customApiKeyResponses.approved.includes(truncatedApiKey)) {
|
|
167
|
-
updatedConfig.customApiKeyResponses.approved.push(truncatedApiKey);
|
|
168
|
-
}
|
|
169
|
-
return updatedConfig;
|
|
170
|
-
}
|
|
171
|
-
function removeApiKeyFromRejected(config, apiKey) {
|
|
172
|
-
if (!config.customApiKeyResponses || !Array.isArray(config.customApiKeyResponses.rejected)) {
|
|
173
|
-
return config;
|
|
174
|
-
}
|
|
175
|
-
const truncatedApiKey = apiKey.substring(0, 20);
|
|
176
|
-
const updatedConfig = { ...config };
|
|
177
|
-
if (updatedConfig.customApiKeyResponses) {
|
|
178
|
-
const rejectedIndex = updatedConfig.customApiKeyResponses.rejected.indexOf(truncatedApiKey);
|
|
179
|
-
if (rejectedIndex > -1) {
|
|
180
|
-
updatedConfig.customApiKeyResponses.rejected.splice(rejectedIndex, 1);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return updatedConfig;
|
|
184
|
-
}
|
|
185
|
-
function manageApiKeyApproval(apiKey) {
|
|
186
|
-
try {
|
|
187
|
-
let config = readMcpConfig();
|
|
188
|
-
if (!config) {
|
|
189
|
-
config = { mcpServers: {} };
|
|
190
|
-
}
|
|
191
|
-
const updatedConfig = ensureApiKeyApproved(config, apiKey);
|
|
192
|
-
writeMcpConfig(updatedConfig);
|
|
193
|
-
} catch (error) {
|
|
194
|
-
ensureI18nInitialized();
|
|
195
|
-
console.error(i18n.t("mcp:apiKeyApprovalFailed"), error);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
function setPrimaryApiKey() {
|
|
199
|
-
try {
|
|
200
|
-
let config = readJsonConfig(CLAUDE_VSC_CONFIG_FILE);
|
|
201
|
-
if (!config) {
|
|
202
|
-
config = {};
|
|
203
|
-
}
|
|
204
|
-
config.primaryApiKey = "ccjk";
|
|
205
|
-
writeJsonConfig(CLAUDE_VSC_CONFIG_FILE, config);
|
|
206
|
-
} catch (error) {
|
|
207
|
-
ensureI18nInitialized();
|
|
208
|
-
console.error(i18n.t("mcp:primaryApiKeySetFailed"), error);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const claudeConfig = {
|
|
213
|
-
__proto__: null,
|
|
214
|
-
addCompletedOnboarding: addCompletedOnboarding,
|
|
215
|
-
backupMcpConfig: backupMcpConfig,
|
|
216
|
-
buildMcpServerConfig: buildMcpServerConfig,
|
|
217
|
-
ensureApiKeyApproved: ensureApiKeyApproved,
|
|
218
|
-
fixWindowsMcpConfig: fixWindowsMcpConfig,
|
|
219
|
-
getMcpConfigPath: getMcpConfigPath,
|
|
220
|
-
manageApiKeyApproval: manageApiKeyApproval,
|
|
221
|
-
mergeMcpServers: mergeMcpServers,
|
|
222
|
-
readMcpConfig: readMcpConfig,
|
|
223
|
-
removeApiKeyFromRejected: removeApiKeyFromRejected,
|
|
224
|
-
setPrimaryApiKey: setPrimaryApiKey,
|
|
225
|
-
writeMcpConfig: writeMcpConfig
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
export { buildMcpServerConfig as a, backupMcpConfig as b, addCompletedOnboarding as c, removeApiKeyFromRejected as d, ensureApiKeyApproved as e, fixWindowsMcpConfig as f, getMcpConfigPath as g, manageApiKeyApproval as h, deepMerge as i, claudeConfig as j, mergeMcpServers as m, readMcpConfig as r, setPrimaryApiKey as s, writeMcpConfig as w };
|