cc-ding 0.0.5 → 0.2.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/README.md +249 -85
- package/dist/bin/cc-ding.js +36 -1
- package/dist/resource/ocr-arm64 +0 -0
- package/dist/resource/ocr-x64 +0 -0
- package/dist/src/biz/api-key-manager.js +3 -1
- package/dist/src/biz/cc-ding-cli.js +85 -1
- package/dist/src/biz/claude-process.js +39 -1
- package/dist/src/biz/commands.js +6 -1
- package/dist/src/biz/cron.js +21 -1
- package/dist/src/biz/doctor.js +2 -1
- package/dist/src/biz/image.js +13 -1
- package/dist/src/biz/lock.js +1 -1
- package/dist/src/biz/menu.js +3 -0
- package/dist/src/biz/messaging.js +6 -1
- package/dist/src/biz/notify.js +1 -0
- package/dist/src/biz/quote.js +9 -1
- package/dist/src/biz/recorder.js +9 -0
- package/dist/src/biz/session.js +14 -1
- package/dist/src/biz/task.js +24 -1
- package/dist/src/biz/todo.js +8 -0
- package/dist/src/biz/types.js +1 -1
- package/dist/src/common.js +1 -1
- package/dist/src/constants.js +1 -1
- package/package.json +7 -5
- package/resource/ocr-arm64 +0 -0
- package/resource/ocr-x64 +0 -0
package/README.md
CHANGED
|
@@ -4,29 +4,37 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/cc-ding)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://nodejs.org)
|
|
7
|
+
[](https://github.com/yihuineng/cc-ding/stargazers)
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
> 将 Claude Code 接入钉钉,构建企业级 AI 协作工作流。
|
|
10
|
+
>
|
|
11
|
+
> Connect Claude Code to DingTalk for enterprise-grade AI collaboration.
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
**[中文](#中文--简体中文)** | **[English](#english)**
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
- **群内多用户** — 白名单内所有成员均可参与同一会话
|
|
14
|
-
- **任务队列** — `/task` 提交任务,按队列顺序执行,完成后自动回复
|
|
15
|
-
- **定时任务** — 自然语言创建 cron,支持暂停 / 恢复 / 删除
|
|
16
|
-
- **图片消息** — 自动接收钉钉图片 / 富文本内嵌图片,可选本地 OCR 识别
|
|
17
|
-
- **API Key 池化** — 429 自动切换、跨天重置,提升服务稳定性
|
|
18
|
-
- **关联群** — 多个群共享同一个 Claude 会话上下文
|
|
15
|
+
---
|
|
19
16
|
|
|
20
|
-
##
|
|
17
|
+
## 中文 | 简体中文
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
将 Claude Code 接入钉钉,实现双向通信。支持多轮对话、任务队列、定时任务、图片识别,帮助团队以最低成本构建可私有化部署的 AI 助手。
|
|
20
|
+
|
|
21
|
+
### 目录
|
|
22
|
+
|
|
23
|
+
- [快速开始](#快速开始)
|
|
24
|
+
- [命令参考](#命令参考)
|
|
25
|
+
- [配置说明](#配置说明)
|
|
26
|
+
- [数据存储](#数据存储)
|
|
27
|
+
- [开发](#开发)
|
|
28
|
+
|
|
29
|
+
### 快速开始
|
|
30
|
+
|
|
31
|
+
#### 安装
|
|
23
32
|
|
|
24
33
|
```bash
|
|
25
34
|
pnpm i cc-ding -g
|
|
26
|
-
cc-ding --help
|
|
27
35
|
```
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
#### 初始化
|
|
30
38
|
|
|
31
39
|
```bash
|
|
32
40
|
cc-ding init -ci {clientId} -cs {clientSecret} -m {手机号}
|
|
@@ -34,107 +42,79 @@ cc-ding init -ci {clientId} -cs {clientSecret} -m {手机号}
|
|
|
34
42
|
|
|
35
43
|
| 参数 | 说明 |
|
|
36
44
|
|------|------|
|
|
37
|
-
| `-ci, --clientId` |
|
|
45
|
+
| `-ci, --clientId` | 钉钉应用 ClientId |
|
|
38
46
|
| `-cs, --clientSecret` | 钉钉 Stream 连接密钥 |
|
|
39
47
|
| `-m, --mobile` | 管理员手机号(自动加入白名单) |
|
|
40
48
|
| `-cn, --clientName` | 机器人名称(可选,默认 "cc助手") |
|
|
41
49
|
|
|
42
|
-
|
|
50
|
+
#### 编辑配置
|
|
43
51
|
|
|
44
|
-
配置文件位于 `~/.cc-ding/{clientId}/config.json
|
|
52
|
+
配置文件位于 `~/.cc-ding/{clientId}/config.json`,参考下方 [配置文件示例](#配置文件示例)。
|
|
45
53
|
|
|
46
|
-
|
|
54
|
+
#### 启动
|
|
47
55
|
|
|
48
56
|
```bash
|
|
49
57
|
# 直接启动
|
|
50
58
|
cc-ding run -ci {clientId}
|
|
51
59
|
|
|
52
|
-
# 推荐:PM2
|
|
60
|
+
# 推荐:PM2 守护进程
|
|
53
61
|
pm2 start --name "cc-ding-{clientId}" npx -- -p cc-ding cc-ding run -ci {clientId}
|
|
54
62
|
```
|
|
55
63
|
|
|
56
|
-
|
|
64
|
+
### 命令参考
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
#### 会话
|
|
59
67
|
|
|
60
68
|
| 命令 | 说明 |
|
|
61
69
|
|------|------|
|
|
62
|
-
| `/help` |
|
|
63
|
-
| `/log [行数]` |
|
|
64
|
-
| `/new [
|
|
65
|
-
| `/resume [
|
|
70
|
+
| `/help` | 查看所有命令 |
|
|
71
|
+
| `/log [行数]` | 查看会话日志 |
|
|
72
|
+
| `/new [消息]` | 开始新对话 |
|
|
73
|
+
| `/resume [ID]` | 恢复历史会话(不指定则恢复最近一个) |
|
|
66
74
|
| `/end` | 结束当前会话 |
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
- 群内所有白名单用户均可参与对话
|
|
76
|
+
> 会话自动持久化到 `active.json`,重启后无缝恢复。群内所有白名单用户均可参与。
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
#### 任务
|
|
72
79
|
|
|
73
80
|
```
|
|
74
|
-
/task
|
|
75
|
-
/task cancel
|
|
81
|
+
/task <描述> # 提交任务(自动排队顺序执行)
|
|
82
|
+
/task cancel # 取消任务
|
|
76
83
|
```
|
|
77
84
|
|
|
78
|
-
|
|
85
|
+
#### 定时任务
|
|
79
86
|
|
|
80
87
|
```
|
|
81
|
-
/cron
|
|
82
|
-
/cron 0 9 * * *
|
|
83
|
-
/cron list
|
|
84
|
-
/cron pause <id>
|
|
85
|
-
/cron delete <id>
|
|
88
|
+
/cron <自然语言> # Claude 自动生成 cron 表达式
|
|
89
|
+
/cron 0 9 * * * <描述> # 直接指定 cron
|
|
90
|
+
/cron list # 查看列表
|
|
91
|
+
/cron pause <id> | resume <id> # 暂停 / 恢复
|
|
92
|
+
/cron delete <id> # 删除
|
|
86
93
|
```
|
|
87
94
|
|
|
88
|
-
|
|
95
|
+
#### 文件操作
|
|
89
96
|
|
|
90
97
|
| 命令 | 说明 |
|
|
91
98
|
|------|------|
|
|
92
|
-
| `/pwd` |
|
|
99
|
+
| `/pwd` | 显示工作目录 |
|
|
93
100
|
| `/ls [目录] [层数]` | 查看目录结构 |
|
|
94
|
-
| `/mkdir
|
|
95
|
-
| `/touch <路径>` | 创建空文件 |
|
|
96
|
-
| `/rm <路径>` | 删除文件或目录 |
|
|
101
|
+
| `/mkdir` / `/touch` / `/rm` | 创建目录 / 创建空文件 / 删除 |
|
|
97
102
|
|
|
98
|
-
|
|
103
|
+
#### 管理命令(仅 owner)
|
|
99
104
|
|
|
100
105
|
| 命令 | 说明 |
|
|
101
106
|
|------|------|
|
|
102
|
-
| `/info [robot\|session\|task]` |
|
|
103
|
-
| `/version` |
|
|
104
|
-
| `/open [shell]` |
|
|
105
|
-
| `/clean [all]` |
|
|
107
|
+
| `/info [robot\|session\|task]` | 查看配置/会话/任务信息 |
|
|
108
|
+
| `/version` | 版本信息 |
|
|
109
|
+
| `/open [shell]` | 打开工作目录 |
|
|
110
|
+
| `/clean [all]` | 清除历史和缓存 |
|
|
106
111
|
| `/reset-apikeycfg` | 重置 API Key 配置 |
|
|
107
112
|
| `/cfg` | 注册当前群到配置 |
|
|
108
113
|
| `/auth [add\|del <用户>]` | 管理群级白名单 |
|
|
109
114
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
### 白名单
|
|
113
|
-
|
|
114
|
-
- **全局白名单**:`config.json` 中的 `whiteUserList`
|
|
115
|
-
- **群级白名单**:`conversations[].whiteUserList`(优先级高于全局)
|
|
116
|
-
- 支持手机号和 userId 两种格式,手机号自动解析为 userId
|
|
117
|
-
|
|
118
|
-
### API Key 池化
|
|
119
|
-
|
|
120
|
-
配置 `apiKeyCfg` 后启用:
|
|
121
|
-
|
|
122
|
-
- 429 错误自动切换到可用 Key
|
|
123
|
-
- 连续 TPM 不稳定时自动换 Key
|
|
124
|
-
- 每日 0 点自动重置 API Key 状态
|
|
125
|
-
|
|
126
|
-
### 图片消息
|
|
127
|
-
|
|
128
|
-
- 支持 `picture` 和 `richText`(含内嵌图片)消息类型
|
|
129
|
-
- 图片自动下载到 `.images/` 目录
|
|
130
|
-
- `useLocalOcr: true`(默认)使用本地 OCR 识别,同时传入原图路径供 Claude 自主查看
|
|
131
|
-
- 设置 `useLocalOcr: false` 关闭 OCR(适用于支持图片识别的模型)
|
|
132
|
-
|
|
133
|
-
### 关联群
|
|
115
|
+
### 配置说明
|
|
134
116
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
## 配置文件示例
|
|
117
|
+
#### 配置文件示例
|
|
138
118
|
|
|
139
119
|
```json
|
|
140
120
|
{
|
|
@@ -151,9 +131,7 @@ pm2 start --name "cc-ding-{clientId}" npx -- -p cc-ding cc-ding run -ci {clientI
|
|
|
151
131
|
"whiteUserList": ["工号1", "工号2"],
|
|
152
132
|
"agent": "指定agent(可选)",
|
|
153
133
|
"useLocalOcr": true,
|
|
154
|
-
"taskCfg": {
|
|
155
|
-
"skill": "指定技能(可选)"
|
|
156
|
-
}
|
|
134
|
+
"taskCfg": { "skill": "指定技能(可选)" }
|
|
157
135
|
}
|
|
158
136
|
],
|
|
159
137
|
"taskQueueSize": 50,
|
|
@@ -161,34 +139,220 @@ pm2 start --name "cc-ding-{clientId}" npx -- -p cc-ding cc-ding run -ci {clientI
|
|
|
161
139
|
"sessionMaxConcurrency": 20,
|
|
162
140
|
"includeThinking": false,
|
|
163
141
|
"resultOnly": true,
|
|
164
|
-
"debug": false
|
|
142
|
+
"debug": false,
|
|
143
|
+
"skipSandbox": false
|
|
165
144
|
}
|
|
166
145
|
```
|
|
167
146
|
|
|
168
|
-
|
|
147
|
+
#### 配置项速查
|
|
148
|
+
|
|
149
|
+
| 配置 | 说明 |
|
|
150
|
+
|------|------|
|
|
151
|
+
| `whiteUserList` | 全局白名单(手机号或 userId) |
|
|
152
|
+
| `conversations[].whiteUserList` | 群级白名单,优先级高于全局 |
|
|
153
|
+
| `apiKeyCfg` | API Key 池化:429 自动切换、每日 0 点重置 |
|
|
154
|
+
| `useLocalOcr` | 图片本地 OCR(默认 `true`),模型支持图片时可设 `false` |
|
|
155
|
+
| `linkConversationId` | 关联群 ID,多群共享同一 Claude 会话上下文 |
|
|
156
|
+
| `skipSandbox` | 跳过沙箱,允许完整文件系统访问(默认 `false`) |
|
|
157
|
+
|
|
158
|
+
### 数据存储
|
|
169
159
|
|
|
170
160
|
所有数据存储在 `~/.cc-ding/{clientId}/` 目录下:
|
|
171
161
|
|
|
172
162
|
| 类型 | 路径 |
|
|
173
163
|
|------|------|
|
|
174
|
-
|
|
|
175
|
-
|
|
|
164
|
+
| 会话 | `{MD5}/.sessions/{claudeSessionId}/session.{json,log}` |
|
|
165
|
+
| 任务 | `{MD5}/.tasks/{时间戳}/task.{json,log}` |
|
|
176
166
|
| 定时任务 | `cron.json` |
|
|
177
167
|
| 图片缓存 | `{MD5}/.images/` |
|
|
178
168
|
| 手机号映射 | `phone-map.json` |
|
|
179
169
|
|
|
180
|
-
|
|
170
|
+
### 开发
|
|
181
171
|
|
|
182
172
|
```bash
|
|
183
173
|
pnpm install
|
|
184
|
-
pnpm run lint
|
|
185
|
-
pnpm run test
|
|
186
|
-
pnpm run build
|
|
174
|
+
pnpm run lint
|
|
175
|
+
pnpm run test
|
|
176
|
+
pnpm run build
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**系统要求:** Node.js >= 24
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## English
|
|
184
|
+
|
|
185
|
+
Connect Claude Code to DingTalk for bidirectional communication. Supports multi-turn conversations, task queues, scheduled jobs, and image recognition — helping teams build privately deployable AI assistants at minimal cost.
|
|
186
|
+
|
|
187
|
+
### Table of Contents
|
|
188
|
+
|
|
189
|
+
- [Quick Start](#quick-start)
|
|
190
|
+
- [Commands](#commands)
|
|
191
|
+
- [Configuration](#configuration)
|
|
192
|
+
- [Data Storage](#data-storage)
|
|
193
|
+
- [Development](#development)
|
|
194
|
+
|
|
195
|
+
### Quick Start
|
|
196
|
+
|
|
197
|
+
#### Install
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
pnpm i cc-ding -g
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### Initialize
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
cc-ding init -ci {clientId} -cs {clientSecret} -m {phone_number}
|
|
187
207
|
```
|
|
188
208
|
|
|
189
|
-
|
|
209
|
+
| Parameter | Description |
|
|
210
|
+
|-----------|-------------|
|
|
211
|
+
| `-ci, --clientId` | DingTalk app ClientId |
|
|
212
|
+
| `-cs, --clientSecret` | DingTalk Stream connection secret |
|
|
213
|
+
| `-m, --mobile` | Admin phone number (auto-added to whitelist) |
|
|
214
|
+
| `-cn, --clientName` | Bot name (optional, default "cc助手") |
|
|
215
|
+
|
|
216
|
+
#### Edit Config
|
|
217
|
+
|
|
218
|
+
Config file is at `~/.cc-ding/{clientId}/config.json`. See [config example](#configuration-example) below.
|
|
219
|
+
|
|
220
|
+
#### Start
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Direct start
|
|
224
|
+
cc-ding run -ci {clientId}
|
|
225
|
+
|
|
226
|
+
# Recommended: PM2 daemon
|
|
227
|
+
pm2 start --name "cc-ding-{clientId}" npx -- -p cc-ding cc-ding run -ci {clientId}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Commands
|
|
231
|
+
|
|
232
|
+
#### Session
|
|
233
|
+
|
|
234
|
+
| Command | Description |
|
|
235
|
+
|---------|-------------|
|
|
236
|
+
| `/help` | View all commands |
|
|
237
|
+
| `/log [lines]` | View session logs |
|
|
238
|
+
| `/new [msg]` | Start a new conversation |
|
|
239
|
+
| `/resume [ID]` | Resume a previous session (latest if omitted) |
|
|
240
|
+
| `/end` | End the current session |
|
|
241
|
+
|
|
242
|
+
> Sessions are auto-persisted to `active.json` and restored on restart. All whitelisted users in the group can participate.
|
|
243
|
+
|
|
244
|
+
#### Task
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
/task <description> # Submit task (auto-queued, sequential execution)
|
|
248
|
+
/task cancel # Cancel a task
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### Scheduled
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
/cron <natural language> # Claude auto-generates cron expression
|
|
255
|
+
/cron 0 9 * * * <description> # Specify cron directly
|
|
256
|
+
/cron list # View all
|
|
257
|
+
/cron pause <id> | resume <id> # Pause / resume
|
|
258
|
+
/cron delete <id> # Delete
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### File Operations
|
|
262
|
+
|
|
263
|
+
| Command | Description |
|
|
264
|
+
|---------|-------------|
|
|
265
|
+
| `/pwd` | Show working directory |
|
|
266
|
+
| `/ls [dir] [depth]` | View directory structure |
|
|
267
|
+
| `/mkdir` / `/touch` / `/rm` | Create dir / Create empty file / Delete |
|
|
268
|
+
|
|
269
|
+
#### Admin (owner only)
|
|
270
|
+
|
|
271
|
+
| Command | Description |
|
|
272
|
+
|---------|-------------|
|
|
273
|
+
| `/info [robot\|session\|task]` | View config/session/task info |
|
|
274
|
+
| `/version` | Version info |
|
|
275
|
+
| `/open [shell]` | Open working directory |
|
|
276
|
+
| `/clean [all]` | Clear history and cache |
|
|
277
|
+
| `/reset-apikeycfg` | Reset API Key configuration |
|
|
278
|
+
| `/cfg` | Register current group to config |
|
|
279
|
+
| `/auth [add\|del <user>]` | Manage group whitelist |
|
|
280
|
+
|
|
281
|
+
### Configuration
|
|
282
|
+
|
|
283
|
+
#### Configuration Example
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"clientName": "cc助手",
|
|
288
|
+
"owner": "your_phone_number",
|
|
289
|
+
"whiteUserList": ["your_phone_number"],
|
|
290
|
+
"clientSecret": "dingtalk_stream_secret",
|
|
291
|
+
"defaultDingToken": "fallback_dingtalk_bot_token",
|
|
292
|
+
"conversations": [
|
|
293
|
+
{
|
|
294
|
+
"conversationId": "group_id",
|
|
295
|
+
"conversationTitle": "group_name",
|
|
296
|
+
"dingToken": "group_bot_token",
|
|
297
|
+
"whiteUserList": ["emp_id_1", "emp_id_2"],
|
|
298
|
+
"agent": "specified_agent (optional)",
|
|
299
|
+
"useLocalOcr": true,
|
|
300
|
+
"taskCfg": { "skill": "specified_skill (optional)" }
|
|
301
|
+
}
|
|
302
|
+
],
|
|
303
|
+
"taskQueueSize": 50,
|
|
304
|
+
"taskHandlerCount": 1,
|
|
305
|
+
"sessionMaxConcurrency": 20,
|
|
306
|
+
"includeThinking": false,
|
|
307
|
+
"resultOnly": true,
|
|
308
|
+
"debug": false,
|
|
309
|
+
"skipSandbox": false
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
#### Config Quick Reference
|
|
314
|
+
|
|
315
|
+
| Config | Description |
|
|
316
|
+
|--------|-------------|
|
|
317
|
+
| `whiteUserList` | Global whitelist (phone or userId) |
|
|
318
|
+
| `conversations[].whiteUserList` | Group-level whitelist, higher priority than global |
|
|
319
|
+
| `apiKeyCfg` | API Key pooling: auto-switch on 429, daily reset at midnight |
|
|
320
|
+
| `useLocalOcr` | Local image OCR (default `true`); set `false` if model supports images natively |
|
|
321
|
+
| `linkConversationId` | Link groups to share one Claude session context |
|
|
322
|
+
| `skipSandbox` | Skip sandbox for full filesystem access (default `false`) |
|
|
323
|
+
|
|
324
|
+
### Data Storage
|
|
325
|
+
|
|
326
|
+
All data is stored under `~/.cc-ding/{clientId}/`:
|
|
327
|
+
|
|
328
|
+
| Type | Path |
|
|
329
|
+
|------|------|
|
|
330
|
+
| Sessions | `{MD5}/.sessions/{claudeSessionId}/session.{json,log}` |
|
|
331
|
+
| Tasks | `{MD5}/.tasks/{timestamp}/task.{json,log}` |
|
|
332
|
+
| Cron jobs | `cron.json` |
|
|
333
|
+
| Image cache | `{MD5}/.images/` |
|
|
334
|
+
| Phone mapping | `phone-map.json` |
|
|
335
|
+
|
|
336
|
+
### Development
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
pnpm install
|
|
340
|
+
pnpm run lint
|
|
341
|
+
pnpm run test
|
|
342
|
+
pnpm run build
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Requirements:** Node.js >= 24
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Star History
|
|
350
|
+
|
|
351
|
+
[](https://github.com/yihuineng/cc-ding/stargazers)
|
|
352
|
+
|
|
353
|
+
## Contributors
|
|
190
354
|
|
|
191
|
-
-
|
|
355
|
+
[](https://github.com/yihuineng/cc-ding/graphs/contributors)
|
|
192
356
|
|
|
193
357
|
## License
|
|
194
358
|
|
package/dist/bin/cc-ding.js
CHANGED
|
@@ -1,2 +1,37 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const common_1=require("../src/common"),commander_1=require("commander"),session_1=require("../src/biz/session"),path_1=__importDefault(require("path")),cc_ding_cli_1=require("../src/biz/cc-ding-cli"),lock_1=require("../src/biz/lock"),doctor_1=require("../src/biz/doctor"),notify_1=require("../src/biz/notify"),fs_1=__importDefault(require("fs"));(0,common_1.loadEnv)(),process.removeAllListeners("warning"),process.setMaxListeners(0),process.on("uncaughtException",function(e){console.log("Caught exception: "+e),process.exit(1)});const program=new commander_1.Command;program.addHelpText("before",`
|
|
3
|
+
cc-ding for connect ClaudeCode to DingDingRobot
|
|
4
|
+
`).addHelpText("after",`
|
|
5
|
+
Examples:
|
|
6
|
+
$ cc-ding init -ci {clientId} -cs {clientSecret} -m {mobile}
|
|
7
|
+
$ cc-ding run -ci {clientId}
|
|
8
|
+
`).version((0,common_1.projUtil)().getPkgVersion()),program.command("init").description("\u521D\u59CB\u5316cc-ding\u914D\u7F6E\u6587\u4EF6, \u751F\u6210\u6700\u7B80config.json").requiredOption("-ci, --clientId <value>","clientId").requiredOption("-cs, --clientSecret <value>","clientSecret (\u9489\u9489Stream\u8FDE\u63A5\u5BC6\u94A5)").requiredOption("-m, --mobile <value>","mobile (\u81EA\u5DF1\u7684\u624B\u673A\u53F7, \u81EA\u52A8\u52A0\u5165\u767D\u540D\u5355)").option("-cn, --clientName <value>","clientName (\u673A\u5668\u4EBA\u540D\u79F0, \u53EF\u9009)").action(async e=>{const n=process.version.slice(1);parseInt(n.split(".")[0],10)<24&&(console.log(`
|
|
9
|
+
\u274C Node \u7248\u672C\u8FC7\u4F4E\uFF0C\u65E0\u6CD5\u6267\u884C init \u547D\u4EE4`),console.log(` \u5F53\u524D\u7248\u672C\uFF1A${n}`),console.log(" \u8981\u6C42\uFF1ANode >= 24"),console.log(`
|
|
10
|
+
\u{1F4A1} \u8BF7\u5347\u7EA7 Node \u7248\u672C\u540E\u91CD\u65B0\u8FD0\u884C
|
|
11
|
+
`),process.exit(1));const i=`${`${(0,session_1.getHomeDir)()}/.cc-ding/${e.clientId}`}/config.json`;fs_1.default.existsSync(i)&&(console.log(`\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728: ${i}`),console.log("\u5982\u9700\u91CD\u65B0\u521D\u59CB\u5316, \u8BF7\u5148\u5220\u9664\u5DF2\u6709\u914D\u7F6E\u6587\u4EF6"),process.exit(1));const t={clientName:e.clientName||"cc\u52A9\u624B",owner:e.mobile,whiteUserList:[e.mobile],clientSecret:e.clientSecret,defaultDingToken:"<\u515C\u5E95\u9489\u9489\u673A\u5668\u4EBAToken-\u7528\u4E8E\u65E0dingToken\u7FA4\u7684\u6D88\u606F\u63A5\u6536>",conversations:[],includeThinking:!1,resultOnly:!0,debug:!1,taskQueueSize:10,taskHandlerCount:1,sessionMaxConcurrency:20,skipSandbox:!1};(0,session_1.initClientDir)(e.clientId,t),console.log("\u914D\u7F6E\u6587\u4EF6\u5DF2\u751F\u6210:",i),console.log(""),console.log("\u540E\u7EED\u6B65\u9AA4:"),console.log(" 1. \u7F16\u8F91 config.json \u6DFB\u52A0 conversations \u914D\u7F6E(\u7FA4\u804A\u9700\u914D\u7F6EdingToken)"),console.log(" 2. \u542F\u52A8\u673A\u5668\u4EBA: cc-ding run -ci",e.clientId),console.log(" 3. \u63A8\u8350PM2\u542F\u52A8:"),console.log(` pm2 start --name "cc-ding-${e.clientId}" npx -- -p cc-ding cc-ding run -ci ${e.clientId}`)}),program.command("run").description(`
|
|
12
|
+
- \u529F\u80FD: \u9489\u9489\u673A\u5668\u4EBA\u5BF9\u63A5\u672C\u5730Claude, \u652F\u6301\u4F1A\u8BDD\u6A21\u5F0F\u548C\u4EFB\u52A1\u961F\u5217\u6A21\u5F0F
|
|
13
|
+
- \u4F1A\u8BDD\u6570\u636E\u8DEF\u5F84: ~/.cc-ding/{clientId}/{MD5}/.sessions/{claudeSessionId}/session.{json|log}
|
|
14
|
+
- \u4EFB\u52A1\u6570\u636E\u8DEF\u5F84: ~/.cc-ding/{clientId}/{MD5}/.tasks/{\u65F6\u95F4\u6233}/task.{json|log}
|
|
15
|
+
- \u5B9A\u65F6\u4EFB\u52A1\u6570\u636E: ~/.cc-ding/{clientId}/cron.json
|
|
16
|
+
- \u542F\u52A8\u65B9\u5F0F: pm2 start --name "cc-ding-{clientId}" npx -- -p cc-ding run -ci {clientId}
|
|
17
|
+
- \u4F1A\u8BDD\u6A21\u5F0F\u8BF4\u660E
|
|
18
|
+
- \u4F1A\u8BDDID: \u7531 Claude \u5206\u914D\u7684 claudeSessionId
|
|
19
|
+
- \u7ED3\u675F\u4F1A\u8BDD: /end
|
|
20
|
+
- \u65B0\u4F1A\u8BDD: /new [\u521D\u59CB\u6D88\u606F] \u5F3A\u5236\u7ED3\u675F\u5F53\u524D\u4F1A\u8BDD\u5E76\u5F00\u542F\u65B0\u4F1A\u8BDD
|
|
21
|
+
- \u6062\u590D\u4F1A\u8BDD: /resume [\u4F1A\u8BDDID] \u6062\u590D\u6307\u5B9A\u5386\u53F2\u4F1A\u8BDD, \u4E0D\u6307\u5B9A\u5219\u6062\u590D\u6700\u8FD1\u4E00\u4E2A
|
|
22
|
+
- \u4F1A\u8BDD\u6301\u4E45\u5316: \u6D3B\u8DC3\u4F1A\u8BDD\u81EA\u52A8\u4FDD\u5B58\u5230 active.json, \u670D\u52A1\u91CD\u542F\u540E\u81EA\u52A8\u6062\u590D
|
|
23
|
+
- \u7FA4\u5185\u591A\u7528\u6237: \u5141\u8BB8\u7FA4\u5185\u6240\u6709\u767D\u540D\u5355\u7528\u6237\u53C2\u4E0E\u5BF9\u8BDD
|
|
24
|
+
- /help: \u67E5\u770B\u6240\u6709\u53EF\u7528\u547D\u4EE4(\u542B\u7248\u672C\u3001\u4F5C\u8005\u3001\u6587\u6863\u94FE\u63A5); /{\u547D\u4EE4} --help \u67E5\u770B\u547D\u4EE4\u8BE6\u7EC6\u7528\u6CD5
|
|
25
|
+
- \u56FE\u7247\u6D88\u606F\u652F\u6301
|
|
26
|
+
- \u652F\u6301\u63A5\u6536\u9489\u9489\u56FE\u7247\u6D88\u606F(picture)\u548C\u5BCC\u6587\u672C\u6D88\u606F(richText, \u542B\u5185\u5D4C\u56FE\u7247)
|
|
27
|
+
- \u56FE\u7247\u81EA\u52A8\u4E0B\u8F7D\u4FDD\u5B58\u5230 <\u4F1A\u8BDD\u76EE\u5F55>/.images/ \u4E0B
|
|
28
|
+
- useLocalOcr: \u9ED8\u8BA4\u5F00\u542F, \u4F7F\u7528\u672C\u5730OCR\u8BC6\u522B\u56FE\u7247\u6587\u5B57, \u540C\u65F6\u4F20\u5165\u539F\u56FE\u8DEF\u5F84\u4F9BClaude\u81EA\u4E3B\u67E5\u770B
|
|
29
|
+
- \u914D\u7F6E\u65B9\u5F0F: conversations[].useLocalOcr = false \u53EF\u5173\u95EDOCR(\u9002\u7528\u4E8E\u652F\u6301\u56FE\u7247\u8BC6\u522B\u7684\u6A21\u578B)
|
|
30
|
+
- \u4EFB\u52A1\u6A21\u5F0F\u8BF4\u660E
|
|
31
|
+
- \u4EFB\u52A1ID: \u4EFB\u52A1\u63A5\u6536\u65F6\u95F4\u6233
|
|
32
|
+
- API Key \u6C60\u5316\u7BA1\u7406(\u53EF\u9009, \u914D\u7F6EapiKeyCfg\u540E\u542F\u7528)
|
|
33
|
+
- 429\u81EA\u52A8\u5207\u6362: \u81EA\u52A8\u5207\u6362\u5230API Key\u6A21\u5F0F
|
|
34
|
+
- Key\u8F6E\u6362: API Key\u9047\u5230429\u6216\u8FDE\u7EEDTPM\u4E0D\u7A33\u5B9A\u65F6\u81EA\u52A8\u6362Key
|
|
35
|
+
- \u8DE8\u5929\u91CD\u7F6E: \u6BCF\u65E5\u81EA\u52A8\u91CD\u7F6EAPI Key\u72B6\u6001
|
|
36
|
+
`).requiredOption("-ci, --clientId <value>","clientId").action(async e=>{(0,session_1.ensureClientDir)(e.clientId);const n=path_1.default.join((0,session_1.getHomeDir)(),".cc-ding",e.clientId);(0,lock_1.acquirePidLock)(n,e.clientId),await new cc_ding_cli_1.DingClaude(e.clientId).run()}),program.command("doctor").description("\u68C0\u67E5\u6307\u5B9Aclient\u7684\u914D\u7F6E\u6587\u4EF6schema\u5408\u6CD5\u6027\u548C\u6709\u6548\u6027").requiredOption("-ci, --clientId <value>","clientId").action(async e=>{const n=path_1.default.join((0,session_1.getHomeDir)(),".cc-ding",e.clientId),c=(0,doctor_1.runDoctor)(n);(0,doctor_1.printDoctorResults)(c)}),program.command("notify").description("\u901A\u8FC7\u9489\u9489\u673A\u5668\u4EBA\u53D1\u9001\u6D88\u606F\u5230\u6307\u5B9A\u7FA4").requiredOption("-ci, --clientId <value>","clientId").requiredOption("-c, --conversations <value>","\u76EE\u6807\u4F1A\u8BDDID\uFF08\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694\uFF09").requiredOption("-m, --message <value>","\u6D88\u606F\u5185\u5BB9").option("-at, --atUserIds <value>","@ \u6307\u5B9A\u7528\u6237\uFF08\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694\uFF09").option("-md, --markdown","\u4F7F\u7528 Markdown \u683C\u5F0F\u53D1\u9001",!1).action(async e=>{const n=e.conversations.split(",").map(i=>i.trim()).filter(Boolean),c=e.atUserIds?e.atUserIds.split(",").map(i=>i.trim()).filter(Boolean):[];console.log(`\u{1F4E4} \u53D1\u9001\u6D88\u606F\u5230 ${n.length} \u4E2A\u4F1A\u8BDD...`);const o=await(0,notify_1.sendNotify)({clientId:e.clientId,message:e.message,conversationIds:n,atUserIds:c,markdown:e.markdown});console.log(`
|
|
37
|
+
\u2705 \u6210\u529F: ${o.success}, \u274C \u5931\u8D25: ${o.fail}`),process.exit(o.fail>0?1:0)}),program.parse(process.argv);
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
'use strict';const a1_0x456413=a1_0x125f;function a1_0x125f(_0x2322b8,_0x55c887){_0x2322b8=_0x2322b8-0xa7;const _0x2d464d=a1_0x2d46();let _0x125f8b=_0x2d464d[_0x2322b8];return _0x125f8b;}(function(_0x8d2d5b,_0x4b8ce8){const _0x5707e7=a1_0x125f,_0x4f4026=_0x8d2d5b();while(!![]){try{const _0x37fee5=-parseInt(_0x5707e7(0xb2))/0x1+-parseInt(_0x5707e7(0x128))/0x2*(parseInt(_0x5707e7(0xc9))/0x3)+-parseInt(_0x5707e7(0xe9))/0x4*(parseInt(_0x5707e7(0x11c))/0x5)+parseInt(_0x5707e7(0x10f))/0x6+parseInt(_0x5707e7(0x10c))/0x7+parseInt(_0x5707e7(0xf4))/0x8+-parseInt(_0x5707e7(0xf2))/0x9*(-parseInt(_0x5707e7(0xd1))/0xa);if(_0x37fee5===_0x4b8ce8)break;else _0x4f4026['push'](_0x4f4026['shift']());}catch(_0x203ac8){_0x4f4026['push'](_0x4f4026['shift']());}}}(a1_0x2d46,0x2df3a));var __importDefault=this&&this['__importDefault']||function(_0x39459d){const _0x115bea=a1_0x125f;return _0x39459d&&_0x39459d[_0x115bea(0xa9)]?_0x39459d:{'default':_0x39459d};};Object['defineProperty'](exports,'__esModule',{'value':!![]}),exports[a1_0x456413(0xfd)]=saveClientConfig,exports[a1_0x456413(0xf6)]=resetApiKeyCfg,exports[a1_0x456413(0xdc)]=scheduleApiKeyCfgDailyReset,exports[a1_0x456413(0xd6)]=settingLabel,exports[a1_0x456413(0x104)]=rotateApiKey,exports[a1_0x456413(0x11f)]=pickValidApiKey,exports[a1_0x456413(0xc4)]=ensureSettingsWithApiKey,exports[a1_0x456413(0xc7)]=isQuotaExhaustedError,exports['isAuthenticationError']=isAuthenticationError,exports[a1_0x456413(0x121)]=readApiKeyFromSettings,exports[a1_0x456413(0xea)]=getForceEnabledSettingsPath,exports['startupCheck']=startupCheck;function a1_0x2d46(){const _0x445905=['default','slice',']\x20==============================\x0a','./session','clientSecret\x20(钉钉\x20Stream\x20Client\x20密钥)','\x20个群配置','settings-tpl.json\x20根元素不是对象','apiKeyCfg.claudeSettings\x20为空,无可用\x20Key','29215HYPKIS','.cc-ding','whiteUserList','pickValidApiKey','keys','readApiKeyFromSettings','claudeSettings','getHomeDir','ANTHROPIC_AUTH_TOKEN','claude\x20命令不可用,请确认\x20Claude\x20Code\x20CLI\x20已安装','CLAUDE_SMALL_FAST_MODEL','settings-tpl.json','34faJCWU','settings-tpl.json\x20解析失败:\x20','exit','toISOString','...','PASS','level','settings-tpl.json\x20不存在:\x20','\x20警告,\x20','getFullYear','dateUtil','push','__esModule','linkConversationId','getClientDir','getMonth',',\x20model:\x20','isArray','config.json\x20','timestamp','clientSecret','256485YBmdUB','群工作目录已就绪:\x20','add','settings-tpl.json\x20有效,env\x20包含:\x20','filter','owner\x20(机器人\x20owner)','pipe','conversationId','\x20致命','which\x20claude','apiKey','apiKeyCfg.claudeSettings\x20不是数组,API\x20Key\x20轮换功能不可用','\x20缺少\x20apiKey','conversations[','random','\x20isValid\x20类型异常:\x20','config.json\x20缺少必填字段:\x20',']\x20启动自检发现致命错误,进程退出','ensureSettingsWithApiKey','[WARN]\x20','settings-ding.json','isQuotaExhaustedError','\x20conversationId\x20重复:\x20','46971EZvtsP','path','conversations','工作目录不可写:\x20','join','some','message','readFileSync','4078590VtDhNZ','群工作目录创建失败:\x20',']\x20已写入\x20Claude\x20配置到\x20','utf-8','resetTime','settingLabel','test','env',',\x20smallModel:\x20',']\x20apiKeyCfg\x20已重置\x20(所有\x20Claude\x20Setting\x20isValid=true)','\x20缺少\x20model','scheduleApiKeyCfgDailyReset','apiKeyCfg','boolean',']\x20从模板创建\x20settings-ding.json:\x20','conversations\x20共\x20','getConversationDir','existsSync','conversations\x20为空数组,可通过\x20/reg\x20命令动态注册','model','FATAL','format','baseUrl','log','140tCFMSL','getForceEnabledSettingsPath','conversationTitle','has','\x20—\x20','\x20apiKey\x20重复:\x20','stringify','WARN','memo','9SeODzh','isValid','509520wkVQIN','\x20缺少\x20conversationId','resetApiKeyCfg',',创建\x20settings-ding.json\x20时将使用空模板','utils-ok','getTime','writeFileSync','/config.json',']\x20检测到\x20settings-ding.json\x20FORCE_ENABLE=','saveClientConfig','getDate',']\x20==========\x20启动自检\x20==========','length','claude\x20命令可用',']\x20Claude\x20Setting\x20已失效:\x20','\x22\x20未在\x20conversations\x20中找到','rotateApiKey','ANTHROPIC_BASE_URL','parse','\x20项,有效\x20','owner','smallModel','object',']\x20apiKeyCfg\x20每日重置已调度,下次重置:\x20','671349pwfSYb','\x20通过,\x20','apiKeyCfg.claudeSettings\x20共\x20','2087526KwKxzg','.claude','ANTHROPIC_MODEL','config','find'];a1_0x2d46=function(){return _0x445905;};return a1_0x2d46();}const fs_1=__importDefault(require('fs')),path_1=__importDefault(require(a1_0x456413(0xca))),child_process_1=require('child_process'),session_1=require(a1_0x456413(0x117)),utils_ok_1=require(a1_0x456413(0xf8));function saveClientConfig(_0x57d208){const _0x24e7bb=a1_0x456413,_0x491d4b=_0x57d208[_0x24e7bb(0xab)]()+_0x24e7bb(0xfb);try{fs_1['default'][_0x24e7bb(0xfa)](_0x491d4b,JSON[_0x24e7bb(0xef)](_0x57d208[_0x24e7bb(0x112)],null,0x2),'utf-8');}catch(_0xee673){console['error']('['+(0x0,session_1[_0x24e7bb(0xb0)])()+']\x20保存\x20config.json\x20失败:',_0xee673);}}function resetApiKeyCfg(_0x2a9ab5){const _0x46343e=a1_0x456413,_0x585bc4=_0x2a9ab5[_0x46343e(0x112)][_0x46343e(0xdd)];if(!_0x585bc4)return;const _0x35e080=new Date();_0x585bc4['resetTime']=utils_ok_1[_0x46343e(0xa7)]['mm'](_0x35e080[_0x46343e(0xf9)]())[_0x46343e(0xe6)]('YYYY-MM-DD\x20HH:mm:ss');let _0xe07065=0x0;for(const _0x3bb3d3 of _0x585bc4['claudeSettings']){!_0x3bb3d3[_0x46343e(0xf3)]&&(_0x3bb3d3['isValid']=!![],_0xe07065++);}_0xe07065>0x0&&console[_0x46343e(0xe8)]('['+(0x0,session_1[_0x46343e(0xb0)])()+']\x20'+_0xe07065+'\x20个已失效\x20Claude\x20Setting\x20重新标记为有效'),saveClientConfig(_0x2a9ab5),console[_0x46343e(0xe8)]('['+(0x0,session_1[_0x46343e(0xb0)])()+_0x46343e(0xda));}function scheduleApiKeyCfgDailyReset(_0x23c28b){const _0x5138b2=()=>{const _0x54fbae=a1_0x125f,_0x4abd55=new Date(),_0x431ffc=new Date(_0x4abd55[_0x54fbae(0x131)](),_0x4abd55[_0x54fbae(0xac)](),_0x4abd55[_0x54fbae(0xfe)]()+0x1,0x0,0x0,0x0,0x0),_0x53e0be=_0x431ffc[_0x54fbae(0xf9)]()-_0x4abd55[_0x54fbae(0xf9)]();setTimeout(()=>{const _0x337bc5=_0x54fbae;console[_0x337bc5(0xe8)]('['+(0x0,session_1[_0x337bc5(0xb0)])()+']\x20定时重置\x20apiKeyCfg\x20(每天0点)'),resetApiKeyCfg(_0x23c28b),_0x5138b2();},_0x53e0be),console[_0x54fbae(0xe8)]('['+(0x0,session_1[_0x54fbae(0xb0)])()+_0x54fbae(0x10b)+_0x431ffc[_0x54fbae(0x12b)]());};_0x5138b2();}function settingLabel(_0x349385){const _0xd39266=a1_0x456413;return _0x349385[_0xd39266(0xf1)]?_0x349385[_0xd39266(0xf1)]:_0xd39266(0x12c)+_0x349385[_0xd39266(0xbc)][_0xd39266(0x115)](-0x6);}function findSettingLabel(_0x216c79,_0x8db208){const _0x55955a=a1_0x456413,_0x30e9d6=_0x216c79[_0x55955a(0x113)](_0x245786=>_0x245786['apiKey']===_0x8db208);return _0x30e9d6?settingLabel(_0x30e9d6):_0x55955a(0x12c)+_0x8db208['slice'](-0x6);}function rotateApiKey(_0x5dfeeb,_0x4fbfe4){const _0x218b8b=a1_0x456413,_0x12c5f6=_0x5dfeeb[_0x218b8b(0x112)]['apiKeyCfg'];if(!_0x12c5f6)return null;for(const _0x55972d of _0x12c5f6['claudeSettings']){if(_0x55972d[_0x218b8b(0xbc)]===_0x4fbfe4&&_0x55972d['isValid']){_0x55972d[_0x218b8b(0xf3)]=![];break;}}const _0x530b84=_0x12c5f6[_0x218b8b(0x122)]['filter'](_0xc75af3=>_0xc75af3[_0x218b8b(0xf3)])[_0x218b8b(0x100)],_0x1507ca=findSettingLabel(_0x12c5f6[_0x218b8b(0x122)],_0x4fbfe4);return console[_0x218b8b(0xe8)]('['+(0x0,session_1[_0x218b8b(0xb0)])()+_0x218b8b(0x102)+_0x1507ca+',\x20剩余有效:\x20'+_0x530b84),saveClientConfig(_0x5dfeeb),pickValidApiKey(_0x5dfeeb);}function pickValidApiKey(_0x3eb232){const _0x312d9a=a1_0x456413,_0x3bfbb7=_0x3eb232[_0x312d9a(0x112)]['apiKeyCfg'];if(!_0x3bfbb7)return null;const _0xe7ac5=_0x3bfbb7[_0x312d9a(0x122)][_0x312d9a(0xb6)](_0xe5f137=>_0xe5f137[_0x312d9a(0xf3)]);if(_0xe7ac5['length']===0x0)return null;return _0xe7ac5[Math['floor'](Math[_0x312d9a(0xc0)]()*_0xe7ac5[_0x312d9a(0x100)])];}function ensureSettingsWithApiKey(_0x403d89,_0x42d31e){const _0x243186=a1_0x456413,_0x5b20ce=path_1[_0x243186(0x114)]['join'](_0x403d89,_0x243186(0x110)),_0x448ece=path_1[_0x243186(0x114)][_0x243186(0xcd)](_0x5b20ce,'settings-ding.json');let _0x527e0a={};if(fs_1[_0x243186(0x114)]['existsSync'](_0x448ece))try{_0x527e0a=JSON['parse'](fs_1[_0x243186(0x114)][_0x243186(0xd0)](_0x448ece,_0x243186(0xd4)));}catch{_0x527e0a={};}else{const _0x2da54f=path_1['default'][_0x243186(0xcd)]((0x0,session_1[_0x243186(0x123)])(),_0x243186(0x11d),_0x243186(0x127));if(fs_1[_0x243186(0x114)][_0x243186(0xe2)](_0x2da54f))try{_0x527e0a=JSON[_0x243186(0x106)](fs_1['default'][_0x243186(0xd0)](_0x2da54f,_0x243186(0xd4))),console[_0x243186(0xe8)]('['+(0x0,session_1[_0x243186(0xb0)])()+_0x243186(0xdf)+_0x2da54f);}catch{_0x527e0a={};}}!_0x527e0a[_0x243186(0xd8)]&&(_0x527e0a[_0x243186(0xd8)]={});let _0x536c7e=![];_0x527e0a[_0x243186(0xd8)][_0x243186(0x124)]!==_0x42d31e['apiKey']&&(_0x527e0a[_0x243186(0xd8)][_0x243186(0x124)]=_0x42d31e[_0x243186(0xbc)],_0x536c7e=!![]);_0x42d31e[_0x243186(0xe7)]&&_0x527e0a[_0x243186(0xd8)]['ANTHROPIC_BASE_URL']!==_0x42d31e[_0x243186(0xe7)]&&(_0x527e0a[_0x243186(0xd8)][_0x243186(0x105)]=_0x42d31e[_0x243186(0xe7)],_0x536c7e=!![]);_0x42d31e[_0x243186(0xe4)]&&_0x527e0a['env'][_0x243186(0x111)]!==_0x42d31e[_0x243186(0xe4)]&&(_0x527e0a['env'][_0x243186(0x111)]=_0x42d31e[_0x243186(0xe4)],_0x536c7e=!![]);const _0x29297a=_0x42d31e[_0x243186(0x109)]||_0x42d31e['model'];return _0x29297a&&_0x527e0a['env'][_0x243186(0x126)]!==_0x29297a&&(_0x527e0a[_0x243186(0xd8)]['CLAUDE_SMALL_FAST_MODEL']=_0x29297a,_0x536c7e=!![]),_0x536c7e&&(fs_1[_0x243186(0x114)]['mkdirSync'](_0x5b20ce,{'recursive':!![]}),fs_1[_0x243186(0x114)][_0x243186(0xfa)](_0x448ece,JSON['stringify'](_0x527e0a,null,0x2),_0x243186(0xd4)),console[_0x243186(0xe8)]('['+(0x0,session_1[_0x243186(0xb0)])()+_0x243186(0xd3)+_0x448ece+'\x20('+settingLabel(_0x42d31e)+_0x243186(0xad)+_0x42d31e[_0x243186(0xe4)]+_0x243186(0xd9)+_0x29297a+')')),_0x448ece;}function isQuotaExhaustedError(_0x1eca93){const _0x5642fb=a1_0x456413;if(/Request\s+rejected.*429/i[_0x5642fb(0xd7)](_0x1eca93))return!![];if(/429.*Request\s+rejected/i['test'](_0x1eca93))return!![];if(/429.*(?:超过.*上限|使用上限|配额|quota|capacity)/i[_0x5642fb(0xd7)](_0x1eca93))return!![];if(/(?:超过.*上限|使用上限|配额|quota|capacity).*429/i[_0x5642fb(0xd7)](_0x1eca93))return!![];return![];}function isAuthenticationError(_0x434481){const _0x5285ad=a1_0x456413;if(/authentication_error/i[_0x5285ad(0xd7)](_0x434481))return!![];if(/401.*(?:未授权|unauthorized|invalid\s*(?:key|token|api)|auth)/i[_0x5285ad(0xd7)](_0x434481))return!![];if(/(?:未授权|unauthorized|invalid\s*(?:key|token|api)|auth).*401/i['test'](_0x434481))return!![];return![];}function readApiKeyFromSettings(_0x31972b){const _0x201b62=a1_0x456413,_0x239751=path_1[_0x201b62(0x114)][_0x201b62(0xcd)](_0x31972b,'.claude',_0x201b62(0xc6));if(!fs_1[_0x201b62(0x114)][_0x201b62(0xe2)](_0x239751))return null;try{const _0xe85b1a=JSON[_0x201b62(0x106)](fs_1[_0x201b62(0x114)][_0x201b62(0xd0)](_0x239751,_0x201b62(0xd4)));return _0xe85b1a[_0x201b62(0xd8)]?.[_0x201b62(0x124)]||null;}catch{return null;}}function getForceEnabledSettingsPath(_0x35eef9){const _0xe00be4=a1_0x456413,_0x19a6c5=path_1['default'][_0xe00be4(0xcd)](_0x35eef9,_0xe00be4(0x110),'settings-ding.json');if(!fs_1[_0xe00be4(0x114)]['existsSync'](_0x19a6c5))return null;try{const _0x1c2687=JSON[_0xe00be4(0x106)](fs_1[_0xe00be4(0x114)][_0xe00be4(0xd0)](_0x19a6c5,_0xe00be4(0xd4))),_0x4ee1d3=_0x1c2687[_0xe00be4(0xd8)]?.['FORCE_ENABLE'];if(_0x4ee1d3!==undefined&&_0x4ee1d3!==![]&&_0x4ee1d3!=='')return console[_0xe00be4(0xe8)]('['+(0x0,session_1[_0xe00be4(0xb0)])()+_0xe00be4(0xfc)+_0x4ee1d3+',强制使用该配置'),_0x19a6c5;return null;}catch{return null;}}function startupCheck(_0x2f159f){const _0xa5f20c=a1_0x456413,_0x5dc717=[],_0x4ff22e=_0x2f159f['config'],_0x220af4=_0x2f159f[_0xa5f20c(0xab)](),_0x491db5=[{'key':_0xa5f20c(0xb1),'label':_0xa5f20c(0x118)},{'key':_0xa5f20c(0x11e),'label':'whiteUserList\x20(白名单用户)'},{'key':_0xa5f20c(0x108),'label':_0xa5f20c(0xb7)}];for(const {key:_0xb88534,label:_0x471542}of _0x491db5){const _0x50b952=_0x4ff22e[_0xb88534];_0x50b952===undefined||_0x50b952===null||_0x50b952===''||Array[_0xa5f20c(0xae)](_0x50b952)&&_0x50b952[_0xa5f20c(0x100)]===0x0?_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xe5),'message':_0xa5f20c(0xc2)+_0x471542}):_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0x12d),'message':_0xa5f20c(0xaf)+_0x471542+'\x20✓'});}if(!Array[_0xa5f20c(0xae)](_0x4ff22e[_0xa5f20c(0xcb)]))_0x5dc717[_0xa5f20c(0xa8)]({'level':'FATAL','message':'conversations\x20应为数组或已配置'});else{if(_0x4ff22e['conversations'][_0xa5f20c(0x100)]===0x0)_0x5dc717['push']({'level':_0xa5f20c(0x12d),'message':_0xa5f20c(0xe3)});else{const _0x405c9c=new Set();for(let _0x18a2a7=0x0;_0x18a2a7<_0x4ff22e[_0xa5f20c(0xcb)]['length'];_0x18a2a7++){const _0x482d52=_0x4ff22e[_0xa5f20c(0xcb)][_0x18a2a7],_0x202b21=_0xa5f20c(0xbf)+_0x18a2a7+']';if(!_0x482d52['conversationId'])_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xe5),'message':_0x202b21+_0xa5f20c(0xf5)});else _0x405c9c[_0xa5f20c(0xec)](_0x482d52['conversationId'])?_0x5dc717[_0xa5f20c(0xa8)]({'level':'WARN','message':_0x202b21+_0xa5f20c(0xc8)+_0x482d52['conversationId']}):_0x405c9c[_0xa5f20c(0xb4)](_0x482d52[_0xa5f20c(0xb9)]);_0x482d52[_0xa5f20c(0xaa)]&&!_0x4ff22e[_0xa5f20c(0xcb)][_0xa5f20c(0xce)](_0x3bd877=>_0x3bd877[_0xa5f20c(0xb9)]===_0x482d52[_0xa5f20c(0xaa)])&&_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':_0x202b21+'\x20linkConversationId\x20\x22'+_0x482d52['linkConversationId']+_0xa5f20c(0x103)});}_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0x12d),'message':_0xa5f20c(0xe0)+_0x4ff22e[_0xa5f20c(0xcb)]['length']+_0xa5f20c(0x119)});}}if(_0x4ff22e[_0xa5f20c(0xdd)]){const _0x45d464=_0x4ff22e[_0xa5f20c(0xdd)];_0x45d464['resetTime']&&_0x5dc717[_0xa5f20c(0xa8)]({'level':'PASS','message':'apiKeyCfg\x20上次重置时间:\x20'+_0x45d464[_0xa5f20c(0xd5)]});if(!Array['isArray'](_0x45d464[_0xa5f20c(0x122)]))_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':_0xa5f20c(0xbd)});else{if(_0x45d464[_0xa5f20c(0x122)][_0xa5f20c(0x100)]===0x0)_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':_0xa5f20c(0x11b)});else{const _0x2c2488=new Set();for(let _0xf2cc34=0x0;_0xf2cc34<_0x45d464[_0xa5f20c(0x122)][_0xa5f20c(0x100)];_0xf2cc34++){const _0x1078cc=_0x45d464['claudeSettings'][_0xf2cc34],_0x33dc9f='apiKeyCfg.claudeSettings['+_0xf2cc34+']';if(!_0x1078cc['apiKey'])_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xe5),'message':_0x33dc9f+_0xa5f20c(0xbe)});else _0x2c2488[_0xa5f20c(0xec)](_0x1078cc[_0xa5f20c(0xbc)])?_0x5dc717[_0xa5f20c(0xa8)]({'level':'WARN','message':_0x33dc9f+_0xa5f20c(0xee)+settingLabel(_0x1078cc)}):_0x2c2488['add'](_0x1078cc[_0xa5f20c(0xbc)]);!_0x1078cc[_0xa5f20c(0xe7)]&&_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':_0x33dc9f+'\x20缺少\x20baseUrl'}),!_0x1078cc[_0xa5f20c(0xe4)]&&_0x5dc717['push']({'level':_0xa5f20c(0xf0),'message':_0x33dc9f+_0xa5f20c(0xdb)}),typeof _0x1078cc[_0xa5f20c(0xf3)]!==_0xa5f20c(0xde)&&_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':_0x33dc9f+_0xa5f20c(0xc1)+typeof _0x1078cc['isValid']});}const _0x40e1fc=_0x45d464[_0xa5f20c(0x122)][_0xa5f20c(0xb6)](_0x441640=>_0x441640['isValid'])[_0xa5f20c(0x100)];_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0x12d),'message':_0xa5f20c(0x10e)+_0x45d464[_0xa5f20c(0x122)][_0xa5f20c(0x100)]+_0xa5f20c(0x107)+_0x40e1fc});}}}const _0x3dacab=path_1[_0xa5f20c(0x114)][_0xa5f20c(0xcd)]((0x0,session_1['getHomeDir'])(),_0xa5f20c(0x11d),'settings-tpl.json');if(fs_1[_0xa5f20c(0x114)][_0xa5f20c(0xe2)](_0x3dacab))try{const _0x2da787=JSON['parse'](fs_1['default'][_0xa5f20c(0xd0)](_0x3dacab,_0xa5f20c(0xd4)));if(typeof _0x2da787!==_0xa5f20c(0x10a)||_0x2da787===null)_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':_0xa5f20c(0x11a)});else{if(!_0x2da787[_0xa5f20c(0xd8)]||typeof _0x2da787[_0xa5f20c(0xd8)]!=='object')_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':'settings-tpl.json\x20缺少\x20env\x20字段,创建\x20settings-ding.json\x20时将不包含预配置环境变量'});else{const _0x3b17c1=Object[_0xa5f20c(0x120)](_0x2da787[_0xa5f20c(0xd8)]);_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0x12d),'message':_0xa5f20c(0xb5)+(_0x3b17c1['join'](',\x20')||'(空)')});}}}catch(_0x443629){_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xf0),'message':_0xa5f20c(0x129)+(_0x443629 instanceof Error?_0x443629['message']:_0x443629)});}else _0x5dc717['push']({'level':_0xa5f20c(0xf0),'message':_0xa5f20c(0x12f)+_0x3dacab+_0xa5f20c(0xf7)});try{(0x0,child_process_1['execSync'])(_0xa5f20c(0xbb),{'stdio':_0xa5f20c(0xb8)}),_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0x12d),'message':_0xa5f20c(0x101)});}catch{_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xe5),'message':_0xa5f20c(0x125)});}try{const _0xbbeccc=path_1[_0xa5f20c(0x114)][_0xa5f20c(0xcd)](_0x220af4,'.healthcheck');fs_1[_0xa5f20c(0x114)][_0xa5f20c(0xfa)](_0xbbeccc,'ok',_0xa5f20c(0xd4)),fs_1['default']['unlinkSync'](_0xbbeccc),_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0x12d),'message':'工作目录可写:\x20'+_0x220af4});}catch(_0x268cb2){_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0xe5),'message':_0xa5f20c(0xcc)+_0x220af4+_0xa5f20c(0xed)+(_0x268cb2 instanceof Error?_0x268cb2['message']:_0x268cb2)});}if(Array['isArray'](_0x4ff22e[_0xa5f20c(0xcb)]))for(const _0x9d62dc of _0x4ff22e[_0xa5f20c(0xcb)]){const _0x17023c=_0x2f159f[_0xa5f20c(0xe1)](_0x9d62dc[_0xa5f20c(0xb9)]);try{fs_1[_0xa5f20c(0x114)]['mkdirSync'](_0x17023c,{'recursive':!![]}),_0x5dc717[_0xa5f20c(0xa8)]({'level':_0xa5f20c(0x12d),'message':_0xa5f20c(0xb3)+(_0x9d62dc[_0xa5f20c(0xeb)]||_0x9d62dc['conversationId'])});}catch(_0x36c496){_0x5dc717[_0xa5f20c(0xa8)]({'level':'WARN','message':_0xa5f20c(0xd2)+_0x17023c+_0xa5f20c(0xed)+(_0x36c496 instanceof Error?_0x36c496[_0xa5f20c(0xcf)]:_0x36c496)});}}console[_0xa5f20c(0xe8)]('\x0a['+(0x0,session_1[_0xa5f20c(0xb0)])()+_0xa5f20c(0xff));const _0x47b19d=_0x5dc717[_0xa5f20c(0xce)](_0x2a2e30=>_0x2a2e30[_0xa5f20c(0x12e)]===_0xa5f20c(0xe5));for(const _0x21bd38 of _0x5dc717){const _0x1ceb28=_0x21bd38[_0xa5f20c(0x12e)]===_0xa5f20c(0x12d)?'✓':_0x21bd38[_0xa5f20c(0x12e)]===_0xa5f20c(0xe5)?'✗':'⚠',_0x4348c6=_0x21bd38[_0xa5f20c(0x12e)]===_0xa5f20c(0x12d)?_0x21bd38[_0xa5f20c(0xcf)]:_0x21bd38[_0xa5f20c(0x12e)]==='FATAL'?'[FATAL]\x20'+_0x21bd38[_0xa5f20c(0xcf)]:_0xa5f20c(0xc5)+_0x21bd38[_0xa5f20c(0xcf)];console['log']('\x20\x20'+_0x1ceb28+'\x20'+_0x4348c6);}const _0x45b838=_0x5dc717[_0xa5f20c(0xb6)](_0x5abbfb=>_0x5abbfb[_0xa5f20c(0x12e)]===_0xa5f20c(0x12d))[_0xa5f20c(0x100)],_0x21fbc1=_0x5dc717[_0xa5f20c(0xb6)](_0x4a3a62=>_0x4a3a62[_0xa5f20c(0x12e)]===_0xa5f20c(0xf0))[_0xa5f20c(0x100)],_0x4dc19c=_0x5dc717[_0xa5f20c(0xb6)](_0x25703d=>_0x25703d[_0xa5f20c(0x12e)]===_0xa5f20c(0xe5))[_0xa5f20c(0x100)];console['log']('['+(0x0,session_1[_0xa5f20c(0xb0)])()+']\x20自检完成:\x20'+_0x45b838+_0xa5f20c(0x10d)+_0x21fbc1+_0xa5f20c(0x130)+_0x4dc19c+_0xa5f20c(0xba)),console[_0xa5f20c(0xe8)]('['+(0x0,session_1[_0xa5f20c(0xb0)])()+_0xa5f20c(0x116)),_0x47b19d&&(console['error']('['+(0x0,session_1[_0xa5f20c(0xb0)])()+_0xa5f20c(0xc3)),process[_0xa5f20c(0x12a)](0x1));}
|
|
1
|
+
"use strict";var __importDefault=this&&this.__importDefault||function(s){return s&&s.__esModule?s:{default:s}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.saveClientConfig=saveClientConfig,exports.resetApiKeyCfg=resetApiKeyCfg,exports.scheduleApiKeyCfgDailyReset=scheduleApiKeyCfgDailyReset,exports.settingLabel=settingLabel,exports.rotateApiKey=rotateApiKey,exports.pickValidApiKey=pickValidApiKey,exports.ensureSettingsWithApiKey=ensureSettingsWithApiKey,exports.isQuotaExhaustedError=isQuotaExhaustedError,exports.isAuthenticationError=isAuthenticationError,exports.readApiKeyFromSettings=readApiKeyFromSettings,exports.getForceEnabledSettingsPath=getForceEnabledSettingsPath,exports.startupCheck=startupCheck;const fs_1=__importDefault(require("fs")),path_1=__importDefault(require("path")),child_process_1=require("child_process"),session_1=require("./session"),utils_ok_1=require("utils-ok");function saveClientConfig(s){const e=`${s.getClientDir()}/config.json`;try{fs_1.default.writeFileSync(e,JSON.stringify(s.config,null,2),"utf-8")}catch(n){console.error(`[${(0,session_1.timestamp)()}] \u4FDD\u5B58 config.json \u5931\u8D25:`,n)}}function resetApiKeyCfg(s){const e=s.config.apiKeyCfg;if(!e)return;const n=new Date;e.resetTime=utils_ok_1.dateUtil.mm(n.getTime()).format("YYYY-MM-DD HH:mm:ss");let i=0;for(const l of e.claudeSettings)l.isValid||(l.isValid=!0,i++);i>0&&console.log(`[${(0,session_1.timestamp)()}] ${i} \u4E2A\u5DF2\u5931\u6548 Claude Setting \u91CD\u65B0\u6807\u8BB0\u4E3A\u6709\u6548`),saveClientConfig(s),console.log(`[${(0,session_1.timestamp)()}] apiKeyCfg \u5DF2\u91CD\u7F6E (\u6240\u6709 Claude Setting isValid=true)`)}function scheduleApiKeyCfgDailyReset(s){const e=()=>{const n=new Date,i=new Date(n.getFullYear(),n.getMonth(),n.getDate()+1,0,0,0,0),l=i.getTime()-n.getTime();setTimeout(()=>{console.log(`[${(0,session_1.timestamp)()}] \u5B9A\u65F6\u91CD\u7F6E apiKeyCfg (\u6BCF\u59290\u70B9)`),resetApiKeyCfg(s),e()},l),console.log(`[${(0,session_1.timestamp)()}] apiKeyCfg \u6BCF\u65E5\u91CD\u7F6E\u5DF2\u8C03\u5EA6\uFF0C\u4E0B\u6B21\u91CD\u7F6E: ${i.toISOString()}`)};e()}function settingLabel(s){return s.memo?s.memo:`...${s.apiKey.slice(-6)}`}function findSettingLabel(s,e){const n=s.find(i=>i.apiKey===e);return n?settingLabel(n):`...${e.slice(-6)}`}function rotateApiKey(s,e){const n=s.config.apiKeyCfg;if(!n)return null;for(const r of n.claudeSettings)if(r.apiKey===e&&r.isValid){r.isValid=!1;break}const i=n.claudeSettings.filter(r=>r.isValid).length,l=findSettingLabel(n.claudeSettings,e);return console.log(`[${(0,session_1.timestamp)()}] Claude Setting \u5DF2\u5931\u6548: ${l}, \u5269\u4F59\u6709\u6548: ${i}`),saveClientConfig(s),pickValidApiKey(s)}function pickValidApiKey(s){const e=s.config.apiKeyCfg;if(!e)return null;const n=e.claudeSettings.filter(i=>i.isValid);return n.length===0?null:n[Math.floor(Math.random()*n.length)]}function ensureSettingsWithApiKey(s,e){const n=path_1.default.join(s,".claude"),i=path_1.default.join(n,"settings-ding.json");let l={};if(fs_1.default.existsSync(i))try{l=JSON.parse(fs_1.default.readFileSync(i,"utf-8"))}catch{l={}}else{const g=path_1.default.join((0,session_1.getHomeDir)(),".cc-ding","settings-tpl.json");if(fs_1.default.existsSync(g))try{l=JSON.parse(fs_1.default.readFileSync(g,"utf-8")),console.log(`[${(0,session_1.timestamp)()}] \u4ECE\u6A21\u677F\u521B\u5EFA settings-ding.json: ${g}`)}catch{l={}}}l.env||(l.env={});let r=!1;l.env.ANTHROPIC_AUTH_TOKEN!==e.apiKey&&(l.env.ANTHROPIC_AUTH_TOKEN=e.apiKey,r=!0),e.baseUrl&&l.env.ANTHROPIC_BASE_URL!==e.baseUrl&&(l.env.ANTHROPIC_BASE_URL=e.baseUrl,r=!0),e.model&&l.env.ANTHROPIC_MODEL!==e.model&&(l.env.ANTHROPIC_MODEL=e.model,r=!0);const f=e.smallModel||e.model;return f&&l.env.CLAUDE_SMALL_FAST_MODEL!==f&&(l.env.CLAUDE_SMALL_FAST_MODEL=f,r=!0),r&&(fs_1.default.mkdirSync(n,{recursive:!0}),fs_1.default.writeFileSync(i,JSON.stringify(l,null,2),"utf-8"),console.log(`[${(0,session_1.timestamp)()}] \u5DF2\u5199\u5165 Claude \u914D\u7F6E\u5230 ${i} (${settingLabel(e)}, model: ${e.model}, smallModel: ${f})`)),i}function isQuotaExhaustedError(s){return!!(/Request\s+rejected.*429/i.test(s)||/429.*Request\s+rejected/i.test(s)||/429.*(?:超过.*上限|使用上限|配额|quota|capacity)/i.test(s)||/(?:超过.*上限|使用上限|配额|quota|capacity).*429/i.test(s))}function isAuthenticationError(s){return!!(/authentication_error/i.test(s)||/401.*(?:未授权|unauthorized|invalid\s*(?:key|token|api)|auth)/i.test(s)||/(?:未授权|unauthorized|invalid\s*(?:key|token|api)|auth).*401/i.test(s))}function readApiKeyFromSettings(s){const e=path_1.default.join(s,".claude","settings-ding.json");if(!fs_1.default.existsSync(e))return null;try{return JSON.parse(fs_1.default.readFileSync(e,"utf-8")).env?.ANTHROPIC_AUTH_TOKEN||null}catch{return null}}function getForceEnabledSettingsPath(s){const e=path_1.default.join(s,".claude","settings-ding.json");if(!fs_1.default.existsSync(e))return null;try{const i=JSON.parse(fs_1.default.readFileSync(e,"utf-8")).env?.FORCE_ENABLE;return i!==void 0&&i!==!1&&i!==""?(console.log(`[${(0,session_1.timestamp)()}] \u68C0\u6D4B\u5230 settings-ding.json FORCE_ENABLE=${i}\uFF0C\u5F3A\u5236\u4F7F\u7528\u8BE5\u914D\u7F6E`),e):null}catch{return null}}function startupCheck(s){const e=[],n=s.config,i=s.getClientDir(),l=[{key:"clientSecret",label:"clientSecret (\u9489\u9489 Stream Client \u5BC6\u94A5)"},{key:"whiteUserList",label:"whiteUserList (\u767D\u540D\u5355\u7528\u6237)"},{key:"owner",label:"owner (\u673A\u5668\u4EBA owner)"}];for(const{key:t,label:a}of l){const o=n[t];o==null||o===""||Array.isArray(o)&&o.length===0?e.push({level:"FATAL",message:`config.json \u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5: ${a}`}):e.push({level:"PASS",message:`config.json ${a} \u2713`})}if(!Array.isArray(n.conversations))e.push({level:"FATAL",message:"conversations \u5E94\u4E3A\u6570\u7EC4\u6216\u5DF2\u914D\u7F6E"});else if(n.conversations.length===0)e.push({level:"PASS",message:"conversations \u4E3A\u7A7A\u6570\u7EC4\uFF0C\u53EF\u901A\u8FC7 /reg \u547D\u4EE4\u52A8\u6001\u6CE8\u518C"});else{const t=new Set;for(let a=0;a<n.conversations.length;a++){const o=n.conversations[a],c=`conversations[${a}]`;o.conversationId?t.has(o.conversationId)?e.push({level:"WARN",message:`${c} conversationId \u91CD\u590D: ${o.conversationId}`}):t.add(o.conversationId):e.push({level:"FATAL",message:`${c} \u7F3A\u5C11 conversationId`}),o.linkConversationId&&!n.conversations.some(u=>u.conversationId===o.linkConversationId)&&e.push({level:"WARN",message:`${c} linkConversationId "${o.linkConversationId}" \u672A\u5728 conversations \u4E2D\u627E\u5230`})}e.push({level:"PASS",message:`conversations \u5171 ${n.conversations.length} \u4E2A\u7FA4\u914D\u7F6E`})}if(n.apiKeyCfg){const t=n.apiKeyCfg;if(t.resetTime&&e.push({level:"PASS",message:`apiKeyCfg \u4E0A\u6B21\u91CD\u7F6E\u65F6\u95F4: ${t.resetTime}`}),!Array.isArray(t.claudeSettings))e.push({level:"WARN",message:"apiKeyCfg.claudeSettings \u4E0D\u662F\u6570\u7EC4\uFF0CAPI Key \u8F6E\u6362\u529F\u80FD\u4E0D\u53EF\u7528"});else if(t.claudeSettings.length===0)e.push({level:"WARN",message:"apiKeyCfg.claudeSettings \u4E3A\u7A7A\uFF0C\u65E0\u53EF\u7528 Key"});else{const a=new Set;for(let c=0;c<t.claudeSettings.length;c++){const u=t.claudeSettings[c],d=`apiKeyCfg.claudeSettings[${c}]`;u.apiKey?a.has(u.apiKey)?e.push({level:"WARN",message:`${d} apiKey \u91CD\u590D: ${settingLabel(u)}`}):a.add(u.apiKey):e.push({level:"FATAL",message:`${d} \u7F3A\u5C11 apiKey`}),u.baseUrl||e.push({level:"WARN",message:`${d} \u7F3A\u5C11 baseUrl`}),u.model||e.push({level:"WARN",message:`${d} \u7F3A\u5C11 model`}),typeof u.isValid!="boolean"&&e.push({level:"WARN",message:`${d} isValid \u7C7B\u578B\u5F02\u5E38: ${typeof u.isValid}`})}const o=t.claudeSettings.filter(c=>c.isValid).length;e.push({level:"PASS",message:`apiKeyCfg.claudeSettings \u5171 ${t.claudeSettings.length} \u9879\uFF0C\u6709\u6548 ${o}`})}}const r=path_1.default.join((0,session_1.getHomeDir)(),".cc-ding","settings-tpl.json");if(fs_1.default.existsSync(r))try{const t=JSON.parse(fs_1.default.readFileSync(r,"utf-8"));if(typeof t!="object"||t===null)e.push({level:"WARN",message:"settings-tpl.json \u6839\u5143\u7D20\u4E0D\u662F\u5BF9\u8C61"});else if(!t.env||typeof t.env!="object")e.push({level:"WARN",message:"settings-tpl.json \u7F3A\u5C11 env \u5B57\u6BB5\uFF0C\u521B\u5EFA settings-ding.json \u65F6\u5C06\u4E0D\u5305\u542B\u9884\u914D\u7F6E\u73AF\u5883\u53D8\u91CF"});else{const a=Object.keys(t.env);e.push({level:"PASS",message:`settings-tpl.json \u6709\u6548\uFF0Cenv \u5305\u542B: ${a.join(", ")||"(\u7A7A)"}`})}}catch(t){e.push({level:"WARN",message:`settings-tpl.json \u89E3\u6790\u5931\u8D25: ${t instanceof Error?t.message:t}`})}else e.push({level:"WARN",message:`settings-tpl.json \u4E0D\u5B58\u5728: ${r}\uFF0C\u521B\u5EFA settings-ding.json \u65F6\u5C06\u4F7F\u7528\u7A7A\u6A21\u677F`});try{(0,child_process_1.execSync)("which claude",{stdio:"pipe"}),e.push({level:"PASS",message:"claude \u547D\u4EE4\u53EF\u7528"})}catch{e.push({level:"FATAL",message:"claude \u547D\u4EE4\u4E0D\u53EF\u7528\uFF0C\u8BF7\u786E\u8BA4 Claude Code CLI \u5DF2\u5B89\u88C5"})}try{const t=path_1.default.join(i,".healthcheck");fs_1.default.writeFileSync(t,"ok","utf-8"),fs_1.default.unlinkSync(t),e.push({level:"PASS",message:`\u5DE5\u4F5C\u76EE\u5F55\u53EF\u5199: ${i}`})}catch(t){e.push({level:"FATAL",message:`\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u53EF\u5199: ${i} \u2014 ${t instanceof Error?t.message:t}`})}if(Array.isArray(n.conversations))for(const t of n.conversations){const a=s.getConversationDir(t.conversationId);try{fs_1.default.mkdirSync(a,{recursive:!0}),e.push({level:"PASS",message:`\u7FA4\u5DE5\u4F5C\u76EE\u5F55\u5DF2\u5C31\u7EEA: ${t.conversationTitle||t.conversationId}`})}catch(o){e.push({level:"WARN",message:`\u7FA4\u5DE5\u4F5C\u76EE\u5F55\u521B\u5EFA\u5931\u8D25: ${a} \u2014 ${o instanceof Error?o.message:o}`})}}console.log(`
|
|
2
|
+
[${(0,session_1.timestamp)()}] ========== \u542F\u52A8\u81EA\u68C0 ==========`);const f=e.some(t=>t.level==="FATAL");for(const t of e){const a=t.level==="PASS"?"\u2713":t.level==="FATAL"?"\u2717":"\u26A0",o=t.level==="PASS"?t.message:t.level==="FATAL"?`[FATAL] ${t.message}`:`[WARN] ${t.message}`;console.log(` ${a} ${o}`)}const g=e.filter(t=>t.level==="PASS").length,p=e.filter(t=>t.level==="WARN").length,v=e.filter(t=>t.level==="FATAL").length;console.log(`[${(0,session_1.timestamp)()}] \u81EA\u68C0\u5B8C\u6210: ${g} \u901A\u8FC7, ${p} \u8B66\u544A, ${v} \u81F4\u547D`),console.log(`[${(0,session_1.timestamp)()}] ==============================
|
|
3
|
+
`),f&&(console.error(`[${(0,session_1.timestamp)()}] \u542F\u52A8\u81EA\u68C0\u53D1\u73B0\u81F4\u547D\u9519\u8BEF\uFF0C\u8FDB\u7A0B\u9000\u51FA`),process.exit(1))}
|