@unitsvc/cc-helper 1.1.1 → 1.1.3
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-zh.md +95 -121
- package/README.md +95 -121
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README-zh.md
CHANGED
|
@@ -6,16 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
> 一键解锁 Claude Code 隐藏超能力:`/loop`、`/btw`、`/keybindings`、`/context1m` 和 `MCPSearch`
|
|
8
8
|
|
|
9
|
-
## 目录
|
|
10
|
-
|
|
11
|
-
| 分类 | 内容 |
|
|
12
|
-
| ------------ | --------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
-
| **快速开始** | [环境要求](#环境要求) · [安装](#安装) · [使用方法](#使用方法) · [命令说明](#命令说明) |
|
|
14
|
-
| **核心功能** | [`/loop`](#什么是-loop) · [`/btw`](#什么是-btw) · [`/keybindings`](#什么是-keybindings) · [`/context1m`](#什么是-context1m) |
|
|
15
|
-
| **工具搜索** | [概述](#什么是工具搜索) · [配置说明](#配置说明) |
|
|
16
|
-
| **配置命令** | [plan](#plan-命令) · [vault](#vault-命令) · [env](#env-命令) · [sync](#sync-命令) |
|
|
17
|
-
| **更多** | [功能特点](#功能特点) · [支持平台](#支持平台) · [许可证](#许可证) · [安全](#安全) |
|
|
18
|
-
|
|
19
9
|
---
|
|
20
10
|
|
|
21
11
|
## 环境要求
|
|
@@ -107,11 +97,81 @@ npx @unitsvc/cc-helper disable
|
|
|
107
97
|
|
|
108
98
|
---
|
|
109
99
|
|
|
110
|
-
##
|
|
100
|
+
## 配置命令
|
|
111
101
|
|
|
112
|
-
|
|
102
|
+
### plan 命令
|
|
103
|
+
|
|
104
|
+
配置 AI Provider,支持 vault 加密存储。
|
|
113
105
|
|
|
114
|
-
|
|
106
|
+
```bash
|
|
107
|
+
# 添加 Provider(自动保存到 vault + settings.json)
|
|
108
|
+
cc-helper plan add -p bailian -k YOUR_API_KEY
|
|
109
|
+
cc-helper plan add -p minimaxi -k YOUR_API_KEY --mcp
|
|
110
|
+
|
|
111
|
+
# 切换 Provider
|
|
112
|
+
cc-helper plan switch -p zai
|
|
113
|
+
|
|
114
|
+
# 列出 Provider
|
|
115
|
+
cc-helper plan list
|
|
116
|
+
|
|
117
|
+
# 导出配置
|
|
118
|
+
cc-helper plan export --all-env -o config.json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**支持的 Provider:**
|
|
122
|
+
|
|
123
|
+
| Provider | 说明 |
|
|
124
|
+
| ---------- | ------------ |
|
|
125
|
+
| `bailian` | (CN) Aliyun |
|
|
126
|
+
| `minimaxi` | (CN) MiniMax |
|
|
127
|
+
| `glm` | (CN) Zhipu |
|
|
128
|
+
| `zai` | (EN) Zhipu |
|
|
129
|
+
|
|
130
|
+
### vault 命令
|
|
131
|
+
|
|
132
|
+
安全的密钥存储,加密存储在 `cc-helper.json` 中。
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
cc-helper vault list # 列出密钥
|
|
136
|
+
cc-helper vault set bailian default -k "KEY" # 设置
|
|
137
|
+
cc-helper vault get bailian default # 获取并解密
|
|
138
|
+
cc-helper vault delete bailian default # 删除
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### env 命令
|
|
142
|
+
|
|
143
|
+
多环境配置(default、work、staging 等)。
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
cc-helper env list # 列出环境
|
|
147
|
+
cc-helper env create work # 创建
|
|
148
|
+
cc-helper env switch work # 切换
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### sync 命令
|
|
152
|
+
|
|
153
|
+
将配置导出/导入到 Git 仓库,支持 JWE 加密。
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# 登录 GitHub
|
|
157
|
+
cc-helper sync login -r https://github.com/user/repo -t ghp_xxx
|
|
158
|
+
|
|
159
|
+
# 导出
|
|
160
|
+
cc-helper sync export
|
|
161
|
+
cc-helper sync export --file config.json
|
|
162
|
+
cc-helper sync export --workspace test
|
|
163
|
+
|
|
164
|
+
# 导入
|
|
165
|
+
cc-helper sync import
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 核心功能详解
|
|
171
|
+
|
|
172
|
+
### `/loop` - 定时重复提示
|
|
173
|
+
|
|
174
|
+
定时重复提示,适用于轮询部署、监控 PR、设置提醒、定时执行工作流。
|
|
115
175
|
|
|
116
176
|
```
|
|
117
177
|
/loop [间隔时间] <提示内容>
|
|
@@ -125,8 +185,6 @@ npx @unitsvc/cc-helper disable
|
|
|
125
185
|
/loop remind me to push the release at 3pm
|
|
126
186
|
```
|
|
127
187
|
|
|
128
|
-
### 间隔时间格式
|
|
129
|
-
|
|
130
188
|
| 形式 | 示例 | 解析间隔 |
|
|
131
189
|
| ---------- | --------------------------- | ------------ |
|
|
132
190
|
| 前置时间 | `/loop 30m check` | 每 30 分钟 |
|
|
@@ -135,26 +193,22 @@ npx @unitsvc/cc-helper disable
|
|
|
135
193
|
|
|
136
194
|
支持单位:`s`(秒)、`m`(分)、`h`(时)、`d`(天)
|
|
137
195
|
|
|
138
|
-
|
|
196
|
+
**核心特性:**
|
|
139
197
|
|
|
140
198
|
- **会话级别**:任务仅在当前会话中存在,退出即消失
|
|
141
199
|
- **自动过期**:3 天后自动过期
|
|
142
200
|
- **抖动保护**:小偏移量防止 API 惊群效应
|
|
143
201
|
- **低优先级**:在你与 Claude 交互间隙触发
|
|
144
202
|
|
|
145
|
-
### 管理任务
|
|
146
|
-
|
|
147
203
|
```
|
|
148
204
|
what scheduled tasks do I have? # 列出所有任务
|
|
149
205
|
cancel the deploy check job # 按描述或 ID 取消
|
|
150
206
|
```
|
|
151
207
|
|
|
152
|
-
|
|
208
|
+
### `/btw` - 旁支问题
|
|
153
209
|
|
|
154
210
|
在不打断主对话的情况下提问旁支问题。
|
|
155
211
|
|
|
156
|
-
### 使用方法
|
|
157
|
-
|
|
158
212
|
```
|
|
159
213
|
/btw <问题>
|
|
160
214
|
```
|
|
@@ -167,9 +221,9 @@ cancel the deploy check job # 按描述或 ID 取消
|
|
|
167
221
|
/btw 为什么这里要用 async/await?
|
|
168
222
|
```
|
|
169
223
|
|
|
170
|
-
|
|
224
|
+
### `/keybindings` - 自定义键盘快捷键
|
|
171
225
|
|
|
172
|
-
|
|
226
|
+
在 `~/.claude/keybindings.json` 中配置:
|
|
173
227
|
|
|
174
228
|
```json
|
|
175
229
|
{
|
|
@@ -181,60 +235,48 @@ cancel the deploy check job # 按描述或 ID 取消
|
|
|
181
235
|
}
|
|
182
236
|
```
|
|
183
237
|
|
|
184
|
-
|
|
238
|
+
### `/context1m` - 1M 上下文
|
|
185
239
|
|
|
186
240
|
为 Claude Opus 模型启用 1M token 上下文窗口。
|
|
187
241
|
|
|
188
|
-
|
|
242
|
+
**要求:**
|
|
189
243
|
|
|
190
244
|
- Claude Code v2.1.76 或更高版本
|
|
191
245
|
- Claude Opus 4+ 模型
|
|
192
246
|
- 可能需要 Pro 计划或官方 API
|
|
193
247
|
|
|
194
|
-
### 使用方法
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
npx @unitsvc/cc-helper enable context1m # 别名: 1m, 1M
|
|
198
|
-
```
|
|
199
|
-
|
|
200
248
|

|
|
201
249
|
|
|
202
|
-
|
|
250
|
+
**扩展思维与上下文长度:**
|
|
203
251
|
|
|
204
252
|
| 模型 | 最大思维链长度 | 上下文长度 |
|
|
205
|
-
| -------------------- |
|
|
206
|
-
| qwen3.5-plus |
|
|
207
|
-
| qwen3-coder-plus |
|
|
208
|
-
| qwen3-max-2026-01-23 |
|
|
209
|
-
| qwen3-coder-next |
|
|
210
|
-
| kimi-k2.5 |
|
|
211
|
-
| MiniMax-M2.5 |
|
|
212
|
-
| glm-5 |
|
|
213
|
-
| glm-4.7 |
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
## 什么是工具搜索?
|
|
253
|
+
| -------------------- | -------------: | ---------: |
|
|
254
|
+
| qwen3.5-plus | 81,920 | 1,000,000 |
|
|
255
|
+
| qwen3-coder-plus | 不支持 | 1,000,000 |
|
|
256
|
+
| qwen3-max-2026-01-23 | 81,920 | 262,144 |
|
|
257
|
+
| qwen3-coder-next | 不支持 | 262,144 |
|
|
258
|
+
| kimi-k2.5 | 81,920 | 262,144 |
|
|
259
|
+
| MiniMax-M2.5 | 32,768 | 204,800 |
|
|
260
|
+
| glm-5 | 32,768 | 202,752 |
|
|
261
|
+
| glm-4.7 | 32,768 | 202,752 |
|
|
262
|
+
|
|
263
|
+
### 工具搜索
|
|
218
264
|
|
|
219
265
|
在运行时动态搜索和加载工具,而非一次性发送所有工具定义。节省 token 并提高性能。
|
|
220
266
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
Claude Code 在使用第三方 API 代理时默认禁用工具搜索。此功能为这些代理启用工具搜索。
|
|
267
|
+
**为什么为第三方 API 启用?** Claude Code 在使用第三方 API 代理时默认禁用工具搜索。此功能为这些代理启用工具搜索。
|
|
224
268
|
|
|
225
|
-
|
|
269
|
+
**优势:**
|
|
226
270
|
|
|
227
271
|
- **Token 效率**:减少大型 MCP 工具目录的上下文占用
|
|
228
272
|
- **性能提升**:延迟加载,响应更快
|
|
229
273
|
- **代理兼容**:支持 Kimi 和其他提供商
|
|
230
274
|
|
|
231
|
-
|
|
275
|
+
**要求:**
|
|
232
276
|
|
|
233
277
|
- 代理必须支持 API 响应中的 `tool_reference` 块
|
|
234
278
|
- 仅支持 Claude Sonnet 4+ 和 Opus 4+ 模型(不支持 Haiku)
|
|
235
279
|
|
|
236
|
-
### 配置说明
|
|
237
|
-
|
|
238
280
|
通过 `ENABLE_TOOL_SEARCH` 环境变量控制:
|
|
239
281
|
|
|
240
282
|
| 值 | 行为 |
|
|
@@ -251,7 +293,7 @@ ENABLE_TOOL_SEARCH=false claude # 禁用
|
|
|
251
293
|
ENABLE_TOOL_SEARCH=true claude # 始终启用
|
|
252
294
|
```
|
|
253
295
|
|
|
254
|
-
|
|
296
|
+
禁用 MCPSearch 工具:
|
|
255
297
|
|
|
256
298
|
```json
|
|
257
299
|
{
|
|
@@ -263,74 +305,6 @@ ENABLE_TOOL_SEARCH=true claude # 始终启用
|
|
|
263
305
|
|
|
264
306
|
---
|
|
265
307
|
|
|
266
|
-
## plan 命令
|
|
267
|
-
|
|
268
|
-
配置 AI Provider,支持 vault 加密存储。
|
|
269
|
-
|
|
270
|
-
```bash
|
|
271
|
-
# 添加 Provider(自动保存到 vault + settings.json)
|
|
272
|
-
cc-helper plan add -p bailian -k YOUR_API_KEY
|
|
273
|
-
cc-helper plan add -p minimaxi -k YOUR_API_KEY --mcp
|
|
274
|
-
|
|
275
|
-
# 切换 Provider
|
|
276
|
-
cc-helper plan switch -p zai
|
|
277
|
-
|
|
278
|
-
# 列出 Provider
|
|
279
|
-
cc-helper plan list
|
|
280
|
-
|
|
281
|
-
# 导出配置
|
|
282
|
-
cc-helper plan export --all-env -o config.json
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
**支持的 Provider:**
|
|
286
|
-
|
|
287
|
-
| Provider | 说明 |
|
|
288
|
-
| ---------- | ------------ |
|
|
289
|
-
| `bailian` | (CN) Aliyun |
|
|
290
|
-
| `minimaxi` | (CN) MiniMax |
|
|
291
|
-
| `glm` | (CN) Zhipu |
|
|
292
|
-
| `zai` | (EN) Zhipu |
|
|
293
|
-
|
|
294
|
-
## vault 命令
|
|
295
|
-
|
|
296
|
-
安全的密钥存储,加密存储在 `cc-helper.json` 中。
|
|
297
|
-
|
|
298
|
-
```bash
|
|
299
|
-
cc-helper vault list # 列出密钥
|
|
300
|
-
cc-helper vault set bailian default -k "KEY" # 设置
|
|
301
|
-
cc-helper vault get bailian default # 获取并解密
|
|
302
|
-
cc-helper vault delete bailian default # 删除
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
## env 命令
|
|
306
|
-
|
|
307
|
-
多环境配置(default、work、staging 等)。
|
|
308
|
-
|
|
309
|
-
```bash
|
|
310
|
-
cc-helper env list # 列出环境
|
|
311
|
-
cc-helper env create work # 创建
|
|
312
|
-
cc-helper env switch work # 切换
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
## sync 命令
|
|
316
|
-
|
|
317
|
-
将配置导出/导入到 Git 仓库,支持 JWE 加密。
|
|
318
|
-
|
|
319
|
-
```bash
|
|
320
|
-
# 登录 GitHub
|
|
321
|
-
cc-helper sync login -r https://github.com/user/repo -t ghp_xxx
|
|
322
|
-
|
|
323
|
-
# 导出
|
|
324
|
-
cc-helper sync export
|
|
325
|
-
cc-helper sync export --file config.json
|
|
326
|
-
cc-helper sync export --workspace test
|
|
327
|
-
|
|
328
|
-
# 导入
|
|
329
|
-
cc-helper sync import
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
308
|
## 功能特点
|
|
335
309
|
|
|
336
310
|
| 功能 | 说明 |
|
package/README.md
CHANGED
|
@@ -6,16 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
> One command to unlock Claude Code's hidden superpowers: `/loop`, `/btw`, `/keybindings`, `/context1m`, and `MCPSearch`
|
|
8
8
|
|
|
9
|
-
## Table of Contents
|
|
10
|
-
|
|
11
|
-
| Category | Content |
|
|
12
|
-
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
-
| **Quick Start** | [Requirements](#requirements) · [Installation](#installation) · [Usage](#usage) · [Commands](#commands) |
|
|
14
|
-
| **Core Features** | [`/loop`](#what-is-loop) · [`/btw`](#what-is-btw) · [`/keybindings`](#what-is-keybindings) · [`/context1m`](#what-is-context1m) |
|
|
15
|
-
| **Tool Search** | [Overview](#what-is-tool-search) · [Configuration](#configuration) |
|
|
16
|
-
| **Commands** | [plan](#plan-command) · [vault](#vault-command) · [env](#env-command) · [sync](#sync-command) |
|
|
17
|
-
| **More** | [Features](#features) · [Platforms](#platforms) · [License](#license) · [Security](#security) |
|
|
18
|
-
|
|
19
9
|
---
|
|
20
10
|
|
|
21
11
|
## Requirements
|
|
@@ -107,11 +97,81 @@ npx @unitsvc/cc-helper disable
|
|
|
107
97
|
|
|
108
98
|
---
|
|
109
99
|
|
|
110
|
-
##
|
|
100
|
+
## Configuration Commands
|
|
101
|
+
|
|
102
|
+
### plan Command
|
|
103
|
+
|
|
104
|
+
Configure AI providers with vault-based secret storage.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Add provider (auto-saves to vault + settings.json)
|
|
108
|
+
cc-helper plan add -p bailian -k YOUR_API_KEY
|
|
109
|
+
cc-helper plan add -p minimaxi -k YOUR_API_KEY --mcp
|
|
110
|
+
|
|
111
|
+
# Switch provider
|
|
112
|
+
cc-helper plan switch -p zai
|
|
113
|
+
|
|
114
|
+
# List providers
|
|
115
|
+
cc-helper plan list
|
|
116
|
+
|
|
117
|
+
# Export config
|
|
118
|
+
cc-helper plan export --all-env -o config.json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Supported Providers:**
|
|
122
|
+
|
|
123
|
+
| Provider | Description |
|
|
124
|
+
| ---------- | ------------ |
|
|
125
|
+
| `bailian` | (CN) Aliyun |
|
|
126
|
+
| `minimaxi` | (CN) MiniMax |
|
|
127
|
+
| `glm` | (CN) Zhipu |
|
|
128
|
+
| `zai` | (EN) Zhipu |
|
|
129
|
+
|
|
130
|
+
### vault Command
|
|
131
|
+
|
|
132
|
+
Secure API key storage, encrypted in `cc-helper.json`.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
cc-helper vault list # List secrets
|
|
136
|
+
cc-helper vault set bailian default -k "KEY" # Set
|
|
137
|
+
cc-helper vault get bailian default # Get & decrypt
|
|
138
|
+
cc-helper vault delete bailian default # Delete
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### env Command
|
|
142
|
+
|
|
143
|
+
Multiple environments (default, work, staging, etc.).
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
cc-helper env list # List environments
|
|
147
|
+
cc-helper env create work # Create
|
|
148
|
+
cc-helper env switch work # Switch
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### sync Command
|
|
152
|
+
|
|
153
|
+
Export/import config to Git repository with JWE encryption.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Login to GitHub
|
|
157
|
+
cc-helper sync login -r https://github.com/user/repo -t ghp_xxx
|
|
158
|
+
|
|
159
|
+
# Export
|
|
160
|
+
cc-helper sync export
|
|
161
|
+
cc-helper sync export --file config.json
|
|
162
|
+
cc-helper sync export --workspace test
|
|
163
|
+
|
|
164
|
+
# Import
|
|
165
|
+
cc-helper sync import
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Core Features
|
|
111
171
|
|
|
112
|
-
|
|
172
|
+
### `/loop` - Scheduled Recurring Prompts
|
|
113
173
|
|
|
114
|
-
|
|
174
|
+
Schedule prompts for polling deployments, babysitting PRs, setting reminders, or running workflows on an interval.
|
|
115
175
|
|
|
116
176
|
```
|
|
117
177
|
/loop [interval] <prompt>
|
|
@@ -125,8 +185,6 @@ Schedule recurring prompts for polling deployments, babysitting PRs, setting rem
|
|
|
125
185
|
/loop remind me to push the release at 3pm
|
|
126
186
|
```
|
|
127
187
|
|
|
128
|
-
### Interval Formats
|
|
129
|
-
|
|
130
188
|
| Form | Example | Parsed Interval |
|
|
131
189
|
| ---------------- | --------------------------- | ---------------------- |
|
|
132
190
|
| Leading token | `/loop 30m check` | every 30 minutes |
|
|
@@ -135,26 +193,22 @@ Schedule recurring prompts for polling deployments, babysitting PRs, setting rem
|
|
|
135
193
|
|
|
136
194
|
Supported units: `s` (seconds), `m` (minutes), `h` (hours), `d` (days)
|
|
137
195
|
|
|
138
|
-
|
|
196
|
+
**Key Features:**
|
|
139
197
|
|
|
140
198
|
- **Session-scoped**: Tasks live in the current session and disappear on exit
|
|
141
199
|
- **Auto-expiry**: Tasks expire after 3 days
|
|
142
200
|
- **Jitter protection**: Small offsets prevent API thundering herd
|
|
143
201
|
- **Low priority**: Fires between your turns, not while Claude is busy
|
|
144
202
|
|
|
145
|
-
### Managing Tasks
|
|
146
|
-
|
|
147
203
|
```
|
|
148
204
|
what scheduled tasks do I have? # List all tasks
|
|
149
205
|
cancel the deploy check job # Cancel by description or ID
|
|
150
206
|
```
|
|
151
207
|
|
|
152
|
-
|
|
208
|
+
### `/btw` - Side Questions
|
|
153
209
|
|
|
154
210
|
Ask side questions without disrupting the main conversation flow.
|
|
155
211
|
|
|
156
|
-
### Usage
|
|
157
|
-
|
|
158
212
|
```
|
|
159
213
|
/btw <question>
|
|
160
214
|
```
|
|
@@ -167,9 +221,9 @@ Ask side questions without disrupting the main conversation flow.
|
|
|
167
221
|
/btw why use async/await in this case?
|
|
168
222
|
```
|
|
169
223
|
|
|
170
|
-
|
|
224
|
+
### `/keybindings` - Custom Keyboard Shortcuts
|
|
171
225
|
|
|
172
|
-
|
|
226
|
+
Configure in `~/.claude/keybindings.json`:
|
|
173
227
|
|
|
174
228
|
```json
|
|
175
229
|
{
|
|
@@ -181,60 +235,48 @@ Custom keyboard shortcuts. Configure in `~/.claude/keybindings.json`:
|
|
|
181
235
|
}
|
|
182
236
|
```
|
|
183
237
|
|
|
184
|
-
|
|
238
|
+
### `/context1m` - 1M Token Context
|
|
185
239
|
|
|
186
240
|
Enable 1M token context window for Claude Opus models.
|
|
187
241
|
|
|
188
|
-
|
|
242
|
+
**Requirements:**
|
|
189
243
|
|
|
190
244
|
- Claude Code v2.1.76 or higher
|
|
191
245
|
- Claude Opus 4+ model
|
|
192
246
|
- May require Pro plan or first-party API
|
|
193
247
|
|
|
194
|
-
### Usage
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
npx @unitsvc/cc-helper enable context1m # or: 1m, 1M
|
|
198
|
-
```
|
|
199
|
-
|
|
200
248
|

|
|
201
249
|
|
|
202
|
-
|
|
250
|
+
**Extended Thinking & Context Length:**
|
|
203
251
|
|
|
204
252
|
| Model | Max Thinking Tokens | Context Length |
|
|
205
|
-
| -------------------- |
|
|
206
|
-
| qwen3.5-plus |
|
|
207
|
-
| qwen3-coder-plus |
|
|
208
|
-
| qwen3-max-2026-01-23 |
|
|
209
|
-
| qwen3-coder-next |
|
|
210
|
-
| kimi-k2.5 |
|
|
211
|
-
| MiniMax-M2.5 |
|
|
212
|
-
| glm-5 |
|
|
213
|
-
| glm-4.7 |
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
## What is Tool Search?
|
|
253
|
+
| -------------------- | ------------------: | -------------: |
|
|
254
|
+
| qwen3.5-plus | 81,920 | 1,000,000 |
|
|
255
|
+
| qwen3-coder-plus | Not supported | 1,000,000 |
|
|
256
|
+
| qwen3-max-2026-01-23 | 81,920 | 262,144 |
|
|
257
|
+
| qwen3-coder-next | Not supported | 262,144 |
|
|
258
|
+
| kimi-k2.5 | 81,920 | 262,144 |
|
|
259
|
+
| MiniMax-M2.5 | 32,768 | 204,800 |
|
|
260
|
+
| glm-5 | 32,768 | 202,752 |
|
|
261
|
+
| glm-4.7 | 32,768 | 202,752 |
|
|
262
|
+
|
|
263
|
+
### Tool Search
|
|
218
264
|
|
|
219
265
|
Dynamically search and load tools at runtime instead of sending all tool definitions upfront. Saves tokens and improves performance.
|
|
220
266
|
|
|
221
|
-
|
|
267
|
+
**Why Third-Party APIs?** Claude Code disables Tool Search for third-party proxies by default. This feature enables it.
|
|
222
268
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
### Benefits
|
|
269
|
+
**Benefits:**
|
|
226
270
|
|
|
227
271
|
- **Token efficiency**: Reduces context usage for large MCP tool catalogs
|
|
228
272
|
- **Better performance**: Faster response with deferred loading
|
|
229
273
|
- **Proxy compatibility**: Works with Kimi and other providers
|
|
230
274
|
|
|
231
|
-
|
|
275
|
+
**Requirements:**
|
|
232
276
|
|
|
233
277
|
- Proxy must support `tool_reference` blocks
|
|
234
278
|
- Claude Sonnet 4+ or Opus 4+ models only (not Haiku)
|
|
235
279
|
|
|
236
|
-
### Configuration
|
|
237
|
-
|
|
238
280
|
Control via `ENABLE_TOOL_SEARCH` environment variable:
|
|
239
281
|
|
|
240
282
|
| Value | Behavior |
|
|
@@ -251,7 +293,7 @@ ENABLE_TOOL_SEARCH=false claude # Disable
|
|
|
251
293
|
ENABLE_TOOL_SEARCH=true claude # Always enable
|
|
252
294
|
```
|
|
253
295
|
|
|
254
|
-
|
|
296
|
+
Disable MCPSearch Tool:
|
|
255
297
|
|
|
256
298
|
```json
|
|
257
299
|
{
|
|
@@ -263,74 +305,6 @@ ENABLE_TOOL_SEARCH=true claude # Always enable
|
|
|
263
305
|
|
|
264
306
|
---
|
|
265
307
|
|
|
266
|
-
## plan Command
|
|
267
|
-
|
|
268
|
-
Configure AI providers with vault-based secret storage.
|
|
269
|
-
|
|
270
|
-
```bash
|
|
271
|
-
# Add provider (auto-saves to vault + settings.json)
|
|
272
|
-
cc-helper plan add -p bailian -k YOUR_API_KEY
|
|
273
|
-
cc-helper plan add -p minimaxi -k YOUR_API_KEY --mcp
|
|
274
|
-
|
|
275
|
-
# Switch provider
|
|
276
|
-
cc-helper plan switch -p zai
|
|
277
|
-
|
|
278
|
-
# List providers
|
|
279
|
-
cc-helper plan list
|
|
280
|
-
|
|
281
|
-
# Export config
|
|
282
|
-
cc-helper plan export --all-env -o config.json
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
**Supported Providers:**
|
|
286
|
-
|
|
287
|
-
| Provider | Description |
|
|
288
|
-
| ---------- | ------------ |
|
|
289
|
-
| `bailian` | (CN) Aliyun |
|
|
290
|
-
| `minimaxi` | (CN) MiniMax |
|
|
291
|
-
| `glm` | (CN) Zhipu |
|
|
292
|
-
| `zai` | (EN) Zhipu |
|
|
293
|
-
|
|
294
|
-
## vault Command
|
|
295
|
-
|
|
296
|
-
Secure API key storage, encrypted in `cc-helper.json`.
|
|
297
|
-
|
|
298
|
-
```bash
|
|
299
|
-
cc-helper vault list # List secrets
|
|
300
|
-
cc-helper vault set bailian default -k "KEY" # Set
|
|
301
|
-
cc-helper vault get bailian default # Get & decrypt
|
|
302
|
-
cc-helper vault delete bailian default # Delete
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
## env Command
|
|
306
|
-
|
|
307
|
-
Multiple environments (default, work, staging, etc.).
|
|
308
|
-
|
|
309
|
-
```bash
|
|
310
|
-
cc-helper env list # List environments
|
|
311
|
-
cc-helper env create work # Create
|
|
312
|
-
cc-helper env switch work # Switch
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
## sync Command
|
|
316
|
-
|
|
317
|
-
Export/import config to Git repository with JWE encryption.
|
|
318
|
-
|
|
319
|
-
```bash
|
|
320
|
-
# Login to GitHub
|
|
321
|
-
cc-helper sync login -r https://github.com/user/repo -t ghp_xxx
|
|
322
|
-
|
|
323
|
-
# Export
|
|
324
|
-
cc-helper sync export
|
|
325
|
-
cc-helper sync export --file config.json
|
|
326
|
-
cc-helper sync export --workspace test
|
|
327
|
-
|
|
328
|
-
# Import
|
|
329
|
-
cc-helper sync import
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
308
|
## Features
|
|
335
309
|
|
|
336
310
|
| Feature | Description |
|
package/dist/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var ce=Object.create;var v=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var
|
|
2
|
+
"use strict";var ce=Object.create;var v=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var pe=Object.getPrototypeOf,de=Object.prototype.hasOwnProperty;var me=(e,n)=>{for(var r in n)v(e,r,{get:n[r],enumerable:!0})},Z=(e,n,r,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of fe(n))!de.call(e,t)&&t!==r&&v(e,t,{get:()=>n[t],enumerable:!(o=le(n,t))||o.enumerable});return e};var d=(e,n,r)=>(r=e!=null?ce(pe(e)):{},Z(n||!e||!e.__esModule?v(r,"default",{value:e,enumerable:!0}):r,e)),ue=e=>Z(v({},"__esModule",{value:!0}),e);var ve={};me(ve,{ensureBinary:()=>I,getBinaryPath:()=>w,main:()=>ne,uninstall:()=>C});module.exports=ue(ve);var te=require("child_process");var l=d(require("fs")),F=d(require("os")),$=d(require("path")),Q=require("child_process");var L=d(require("os")),M=d(require("path")),ge={darwin:"darwin",linux:"linux",win32:"windows"},he={x64:"amd64",arm64:"arm64"};function k(){let e=L.default.platform(),n=L.default.arch(),r=ge[e],o=he[n];if(!r)throw new Error(`Unsupported platform: ${e}`);if(!o)throw new Error(`Unsupported arch: ${n}`);return{platform:r,arch:o}}var R=e=>e==="windows"?"cc-helper.exe":"cc-helper";function E(e,n,r){let o=e.replace(/^v/,"");return n==="windows"?`cc-helper_${o}_${n}_${r}.zip`:`cc-helper_${o}_${n}_${r}.tar.gz`}var w=()=>{let{platform:e}=k();return M.default.join(__dirname,"bin",R(e))};var y=d(require("fs")),H=d(require("path")),q=d(require("http")),G=d(require("https"));function S(e){try{y.default.existsSync(e)&&y.default.unlinkSync(e)}catch{}}async function A(e,n,r=3){for(let o=0;o<r;o++)try{await new Promise((t,i)=>{let p=(e.startsWith("https")?G.default:q.default).get(e,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}},c=>{if(c.statusCode===301||c.statusCode===302){let m=c.headers.location;if(m){A(m,n,r).then(t).catch(i);return}}if(c.statusCode!==200){i(new Error(`HTTP ${c.statusCode}`));return}let s=H.default.dirname(n);y.default.existsSync(s)||y.default.mkdirSync(s,{recursive:!0});let g=y.default.createWriteStream(n);c.pipe(g),g.on("finish",()=>{g.close(m=>{m?i(m):t()})}),g.on("error",m=>{S(n),i(m)}),c.on("error",m=>{S(n),i(m)})});p.setTimeout(3e4,()=>{p.destroy(),i(new Error("Timeout"))}),p.on("error",c=>{S(n),i(c)})});return}catch(t){if(S(n),o===r-1)throw t;console.log(`warn cc-helper retry ${o+1}/${r}`),await new Promise(i=>setTimeout(i,1e3*(o+1)))}}var f=d(require("fs")),u=d(require("path")),_=d(require("zlib"));async function we(e,n){let r=0;for(;r+512<=e.length;){let o=e.subarray(r,r+512);if(o.every(c=>c===0))break;let t=o.subarray(0,100).toString().replace(/\0.*$/,""),i=o.subarray(345,500).toString().replace(/\0.*$/,"");i&&(t=`${i}/${t}`),t.startsWith("package/")&&(t=t.slice(8)),t=t.replace(/\//g,u.default.sep);let a=parseInt(o.subarray(124,136).toString().trim(),8)||0,p=o[156];if(r+=512,a>0&&t&&(p===0||p===48)){let c=u.default.join(n,t);await f.default.promises.mkdir(u.default.dirname(c),{recursive:!0}),await f.default.promises.writeFile(c,e.subarray(r,r+a)),r+=Math.ceil(a/512)*512}}}async function ye(e,n){await f.default.promises.mkdir(n,{recursive:!0});let r=await f.default.promises.readFile(e),o;try{o=_.default.unzipSync(r)}catch(t){throw new Error(`Failed to decompress tar.gz: ${t.message}`)}await we(o,n)}async function xe(e,n){await f.default.promises.mkdir(n,{recursive:!0});let r=await f.default.promises.readFile(e);if(r.length<22)throw new Error(`Invalid ZIP: file too small (${r.length} bytes)`);let o=Buffer.from([80,75,5,6]),t=r.length-22;for(;t>=0&&!r.subarray(t,t+4).equals(o);)t--;if(t<0)throw new Error(`Invalid ZIP: missing end of central directory (file may be corrupted or incomplete, size: ${r.length} bytes)`);if(t+22>r.length)throw new Error("Invalid ZIP: truncated EOCD record");let i=r.readUInt32LE(t+16),a=r.readUInt32LE(t+12),p=i+a;if(i>=r.length||p>r.length)throw new Error(`Invalid ZIP: central directory out of bounds (cdOffset: ${i}, cdEnd: ${p}, fileSize: ${r.length})`);let c=Buffer.from([80,75,1,2]),s=i;for(;s<p;){if(s+46>r.length)throw new Error(`Invalid ZIP: truncated central directory at position ${s}`);if(!r.subarray(s,s+4).equals(c))throw new Error(`Invalid ZIP: invalid central directory signature at position ${s}`);let g=r.readUInt16LE(s+28),m=r.readUInt16LE(s+30),N=r.readUInt16LE(s+32),x=r.readUInt32LE(s+42),oe=r.readUInt32LE(s+20),Ee=r.readUInt32LE(s+24),Se=r.readUInt16LE(s+10);if(s+46+g+m+N>r.length)throw new Error(`Invalid ZIP: truncated central directory entry at position ${s}`);let h=r.subarray(s+46,s+46+g).toString();if(s+=46+g+m+N,h.endsWith("/")){await f.default.promises.mkdir(u.default.join(n,h.replace(/\//g,u.default.sep)),{recursive:!0});continue}if(h=h.replace(/\//g,u.default.sep),x+30>r.length)throw new Error(`Invalid ZIP: local header out of bounds for ${h}`);let P=r.readUInt16LE(x+8),ie=r.readUInt16LE(x+26),se=r.readUInt16LE(x+28),b=x+30+ie+se,D=oe;if(b+D>r.length)throw new Error(`Invalid ZIP: truncated file data for ${h}`);let O=r.subarray(b,b+D),U=u.default.join(n,h);await f.default.promises.mkdir(u.default.dirname(U),{recursive:!0});try{if(P===8)await f.default.promises.writeFile(U,_.default.inflateRawSync(O));else if(P===0)await f.default.promises.writeFile(U,O);else throw new Error(`Unsupported compression method ${P} for ${h}`)}catch(ae){throw new Error(`Failed to decompress ${h}: ${ae.message}`)}}}async function K(e,n,r){r==="windows"?await xe(e,n):await ye(e,n)}function V(e,n){let r=u.default.join(e,n);if(f.default.existsSync(r))return r;for(let o of f.default.readdirSync(e)){let t=u.default.join(e,o,n);if(f.default.statSync(u.default.join(e,o)).isDirectory()&&f.default.existsSync(t))return t}throw new Error(`Binary ${n} not found`)}var j=d(require("https"));var z="next-bin",T="cc-helper";function J(e){return new Promise((n,r)=>{let o=`https://api.github.com${e}`,t=j.default.get(o,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}},i=>{let a="";i.on("data",p=>a+=p),i.on("end",()=>{i.statusCode!==200?r(new Error(`GitHub API error: ${i.statusCode}`)):n(JSON.parse(a))})});t.setTimeout(15e3,()=>{t.destroy(),r(new Error("GitHub API timeout"))}),t.on("error",r)})}async function W(){return(await J(`/repos/${z}/${T}/releases/latest`)).tag_name.replace(/^v/,"")}async function X(e,n){var t;let r=await J(`/repos/${z}/${T}/releases?per_page=10`),o=e==="windows"?`_${e}_${n}.zip`:`_${e}_${n}.tar.gz`;for(let i of r)if((t=i.assets)!=null&&t.some(a=>a.name.includes(o)))return i.tag_name.replace(/^v/,"");throw new Error(`No binary found for ${e}-${n}`)}function Y(e,n,r,o){let t=e.startsWith("v")?e:`v${e}`,i=`https://github.com/${z}/${T}/releases/download/${t}/${E(e,n,r)}`;return o?`${o}/${i}`:i}async function B(e,n,r,o,t){let i=E(e,n,r),a=$.default.join(F.default.tmpdir(),i),p=Y(e,n,r,t);console.log(`info cc-helper@${e} Installing for ${n}-${r}`),t&&console.log("info cc-helper Using proxy:",t);try{await A(p,a)}catch(s){throw t||console.log("warn cc-helper Download failed, try: npx @unitsvc/cc-helper --proxy enable"),s}let c=$.default.join(F.default.tmpdir(),`cc-helper_${Date.now()}`);l.default.mkdirSync(c,{recursive:!0});try{await K(a,c,n);let s=V(c,R(n)),g=$.default.dirname(o);l.default.existsSync(g)||l.default.mkdirSync(g,{recursive:!0}),l.default.existsSync(o)&&l.default.unlinkSync(o),l.default.copyFileSync(s,o),process.platform!=="win32"&&l.default.chmodSync(o,493),console.log("info cc-helper Installed to",o)}finally{let s=l.default.rmSync||l.default.rmdirSync;try{s(c,{recursive:!0,force:!0})}catch{}l.default.existsSync(a)&&l.default.unlinkSync(a)}}async function I(e=null,n){let{platform:r,arch:o}=k(),t=w();if(l.default.existsSync(t))return t;if(e)try{return await B(e,r,o,t,n),t}catch(a){if(!a.message.includes("404"))throw a;console.log(`warn cc-helper@${e} not available, using latest`)}let i=await W(n);try{await B(i,r,o,t,n)}catch(a){if(!a.message.includes("404"))throw a;i=await X(r,o,n),await B(i,r,o,t,n)}return t}function C(){let e=w(),n=$.default.dirname(e);l.default.existsSync(e)?(l.default.unlinkSync(e),console.log("info cc-helper Removed binary:",e)):console.log("info cc-helper No binary found"),l.default.existsSync(n)&&l.default.readdirSync(n).length===0&&l.default.rmdirSync(n),console.log("info cc-helper To complete uninstallation, run:"),console.log(" npm uninstall -g @unitsvc/cc-helper")}async function $e(e){if(!l.default.existsSync(e))return null;try{return(0,Q.execSync)(`"${e}" --version`,{timeout:5e3}).toString().trim().replace(/^v/i,"")}catch{return null}}async function ee(e){let n=w(),r=await W(e),o=await $e(n);return{current:o,latest:r,needsUpdate:!o||o!==r}}function re(e){let n=[],r,o="https://edgeone.gh-proxy.org";for(let t=0;t<e.length;t++)e[t]==="--proxy"?t+1<e.length&&(e[t+1].startsWith("http://")||e[t+1].startsWith("https://"))?(r=e[t+1],t++):r=o:e[t].startsWith("--proxy=")?r=e[t].slice(8)||o:n.push(e[t]);return{proxy:r,remainingArgs:n}}async function ne(){let e=process.argv.slice(2);if(e[0]==="uninstall"){C();return}if(e[0]==="update"){let{proxy:o}=re(e.slice(1)),{current:t,latest:i,needsUpdate:a}=await ee();if(!a){console.log(`info cc-helper Already at latest version: ${t}`);return}console.log(`info cc-helper Updating from ${t||"unknown"} to ${i}`),await I(i,o);return}let{proxy:n,remainingArgs:r}=re(e);try{let o=await I(null,n),t=(0,te.spawn)(o,r,{stdio:"inherit"});t.on("close",i=>process.exit(i??1)),t.on("error",i=>{console.error("ERR! cc-helper",i.message),process.exit(1)})}catch(o){console.error("ERR! cc-helper",o.message),process.exit(1)}}require.main===module&&ne();0&&(module.exports={ensureBinary,getBinaryPath,main,uninstall});
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var ar=Object.create;var
|
|
1
|
+
"use strict";var ar=Object.create;var P=Object.defineProperty;var cr=Object.getOwnPropertyDescriptor;var lr=Object.getOwnPropertyNames;var fr=Object.getPrototypeOf,mr=Object.prototype.hasOwnProperty;var dr=(e,t)=>{for(var r in t)P(e,r,{get:t[r],enumerable:!0})},H=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of lr(t))!mr.call(e,n)&&n!==r&&P(e,n,{get:()=>t[n],enumerable:!(o=cr(t,n))||o.enumerable});return e};var d=(e,t,r)=>(r=e!=null?ar(fr(e)):{},H(t||!e||!e.__esModule?P(r,"default",{value:e,enumerable:!0}):r,e)),ur=e=>H(P({},"__esModule",{value:!0}),e);var $r={};dr($r,{checkForUpdate:()=>tr,ensureBinary:()=>F,findReleaseWithBinary:()=>U,getArchiveName:()=>w,getBinaryName:()=>v,getBinaryPath:()=>y,getCurrentVersion:()=>D,getDownloadUrl:()=>L,getLatestVersion:()=>E,getPlatform:()=>S,install:()=>rr,uninstall:()=>er});module.exports=ur($r);var l=d(require("fs")),C=d(require("os")),I=d(require("path")),Y=require("child_process");var _=d(require("os")),G=d(require("path")),pr={darwin:"darwin",linux:"linux",win32:"windows"},gr={x64:"amd64",arm64:"arm64"};function S(){let e=_.default.platform(),t=_.default.arch(),r=pr[e],o=gr[t];if(!r)throw new Error(`Unsupported platform: ${e}`);if(!o)throw new Error(`Unsupported arch: ${t}`);return{platform:r,arch:o}}var v=e=>e==="windows"?"cc-helper.exe":"cc-helper";function w(e,t,r){let o=e.replace(/^v/,"");return t==="windows"?`cc-helper_${o}_${t}_${r}.zip`:`cc-helper_${o}_${t}_${r}.tar.gz`}var y=()=>{let{platform:e}=S();return G.default.join(__dirname,"bin",v(e))};var $=d(require("fs")),q=d(require("path")),K=d(require("http")),V=d(require("https"));function b(e){try{$.default.existsSync(e)&&$.default.unlinkSync(e)}catch{}}async function R(e,t,r=3){for(let o=0;o<r;o++)try{await new Promise((n,i)=>{let m=(e.startsWith("https")?V.default:K.default).get(e,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}},c=>{if(c.statusCode===301||c.statusCode===302){let u=c.headers.location;if(u){R(u,t,r).then(n).catch(i);return}}if(c.statusCode!==200){i(new Error(`HTTP ${c.statusCode}`));return}let s=q.default.dirname(t);$.default.existsSync(s)||$.default.mkdirSync(s,{recursive:!0});let g=$.default.createWriteStream(t);c.pipe(g),g.on("finish",()=>{g.close(u=>{u?i(u):n()})}),g.on("error",u=>{b(t),i(u)}),c.on("error",u=>{b(t),i(u)})});m.setTimeout(3e4,()=>{m.destroy(),i(new Error("Timeout"))}),m.on("error",c=>{b(t),i(c)})});return}catch(n){if(b(t),o===r-1)throw n;console.log(`warn cc-helper retry ${o+1}/${r}`),await new Promise(i=>setTimeout(i,1e3*(o+1)))}}var f=d(require("fs")),p=d(require("path")),T=d(require("zlib"));async function hr(e,t){let r=0;for(;r+512<=e.length;){let o=e.subarray(r,r+512);if(o.every(c=>c===0))break;let n=o.subarray(0,100).toString().replace(/\0.*$/,""),i=o.subarray(345,500).toString().replace(/\0.*$/,"");i&&(n=`${i}/${n}`),n.startsWith("package/")&&(n=n.slice(8)),n=n.replace(/\//g,p.default.sep);let a=parseInt(o.subarray(124,136).toString().trim(),8)||0,m=o[156];if(r+=512,a>0&&n&&(m===0||m===48)){let c=p.default.join(t,n);await f.default.promises.mkdir(p.default.dirname(c),{recursive:!0}),await f.default.promises.writeFile(c,e.subarray(r,r+a)),r+=Math.ceil(a/512)*512}}}async function wr(e,t){await f.default.promises.mkdir(t,{recursive:!0});let r=await f.default.promises.readFile(e),o;try{o=T.default.unzipSync(r)}catch(n){throw new Error(`Failed to decompress tar.gz: ${n.message}`)}await hr(o,t)}async function yr(e,t){await f.default.promises.mkdir(t,{recursive:!0});let r=await f.default.promises.readFile(e);if(r.length<22)throw new Error(`Invalid ZIP: file too small (${r.length} bytes)`);let o=Buffer.from([80,75,5,6]),n=r.length-22;for(;n>=0&&!r.subarray(n,n+4).equals(o);)n--;if(n<0)throw new Error(`Invalid ZIP: missing end of central directory (file may be corrupted or incomplete, size: ${r.length} bytes)`);if(n+22>r.length)throw new Error("Invalid ZIP: truncated EOCD record");let i=r.readUInt32LE(n+16),a=r.readUInt32LE(n+12),m=i+a;if(i>=r.length||m>r.length)throw new Error(`Invalid ZIP: central directory out of bounds (cdOffset: ${i}, cdEnd: ${m}, fileSize: ${r.length})`);let c=Buffer.from([80,75,1,2]),s=i;for(;s<m;){if(s+46>r.length)throw new Error(`Invalid ZIP: truncated central directory at position ${s}`);if(!r.subarray(s,s+4).equals(c))throw new Error(`Invalid ZIP: invalid central directory signature at position ${s}`);let g=r.readUInt16LE(s+28),u=r.readUInt16LE(s+30),Z=r.readUInt16LE(s+32),x=r.readUInt32LE(s+42),nr=r.readUInt32LE(s+20),xr=r.readUInt32LE(s+24),Sr=r.readUInt16LE(s+10);if(s+46+g+u+Z>r.length)throw new Error(`Invalid ZIP: truncated central directory entry at position ${s}`);let h=r.subarray(s+46,s+46+g).toString();if(s+=46+g+u+Z,h.endsWith("/")){await f.default.promises.mkdir(p.default.join(t,h.replace(/\//g,p.default.sep)),{recursive:!0});continue}if(h=h.replace(/\//g,p.default.sep),x+30>r.length)throw new Error(`Invalid ZIP: local header out of bounds for ${h}`);let k=r.readUInt16LE(x+8),or=r.readUInt16LE(x+26),ir=r.readUInt16LE(x+28),B=x+30+or+ir,M=nr;if(B+M>r.length)throw new Error(`Invalid ZIP: truncated file data for ${h}`);let O=r.subarray(B,B+M),z=p.default.join(t,h);await f.default.promises.mkdir(p.default.dirname(z),{recursive:!0});try{if(k===8)await f.default.promises.writeFile(z,T.default.inflateRawSync(O));else if(k===0)await f.default.promises.writeFile(z,O);else throw new Error(`Unsupported compression method ${k} for ${h}`)}catch(sr){throw new Error(`Failed to decompress ${h}: ${sr.message}`)}}}async function j(e,t,r){r==="windows"?await yr(e,t):await wr(e,t)}function J(e,t){let r=p.default.join(e,t);if(f.default.existsSync(r))return r;for(let o of f.default.readdirSync(e)){let n=p.default.join(e,o,t);if(f.default.statSync(p.default.join(e,o)).isDirectory()&&f.default.existsSync(n))return n}throw new Error(`Binary ${t} not found`)}var Q=d(require("https"));var W="next-bin",A="cc-helper";function X(e){return new Promise((t,r)=>{let o=`https://api.github.com${e}`,n=Q.default.get(o,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}},i=>{let a="";i.on("data",m=>a+=m),i.on("end",()=>{i.statusCode!==200?r(new Error(`GitHub API error: ${i.statusCode}`)):t(JSON.parse(a))})});n.setTimeout(15e3,()=>{n.destroy(),r(new Error("GitHub API timeout"))}),n.on("error",r)})}async function E(){return(await X(`/repos/${W}/${A}/releases/latest`)).tag_name.replace(/^v/,"")}async function U(e,t){var n;let r=await X(`/repos/${W}/${A}/releases?per_page=10`),o=e==="windows"?`_${e}_${t}.zip`:`_${e}_${t}.tar.gz`;for(let i of r)if((n=i.assets)!=null&&n.some(a=>a.name.includes(o)))return i.tag_name.replace(/^v/,"");throw new Error(`No binary found for ${e}-${t}`)}function L(e,t,r,o){let n=e.startsWith("v")?e:`v${e}`,i=`https://github.com/${W}/${A}/releases/download/${n}/${w(e,t,r)}`;return o?`${o}/${i}`:i}async function N(e,t,r,o,n){let i=w(e,t,r),a=I.default.join(C.default.tmpdir(),i),m=L(e,t,r,n);console.log(`info cc-helper@${e} Installing for ${t}-${r}`),n&&console.log("info cc-helper Using proxy:",n);try{await R(m,a)}catch(s){throw n||console.log("warn cc-helper Download failed, try: npx @unitsvc/cc-helper --proxy enable"),s}let c=I.default.join(C.default.tmpdir(),`cc-helper_${Date.now()}`);l.default.mkdirSync(c,{recursive:!0});try{await j(a,c,t);let s=J(c,v(t)),g=I.default.dirname(o);l.default.existsSync(g)||l.default.mkdirSync(g,{recursive:!0}),l.default.existsSync(o)&&l.default.unlinkSync(o),l.default.copyFileSync(s,o),process.platform!=="win32"&&l.default.chmodSync(o,493),console.log("info cc-helper Installed to",o)}finally{let s=l.default.rmSync||l.default.rmdirSync;try{s(c,{recursive:!0,force:!0})}catch{}l.default.existsSync(a)&&l.default.unlinkSync(a)}}async function F(e=null,t){let{platform:r,arch:o}=S(),n=y();if(l.default.existsSync(n))return n;if(e)try{return await N(e,r,o,n,t),n}catch(a){if(!a.message.includes("404"))throw a;console.log(`warn cc-helper@${e} not available, using latest`)}let i=await E(t);try{await N(i,r,o,n,t)}catch(a){if(!a.message.includes("404"))throw a;i=await U(r,o,t),await N(i,r,o,n,t)}return n}async function rr(e=null,t){try{await F(e,t)}catch(r){console.error("ERR! cc-helper",r.message)}}function er(){let e=y(),t=I.default.dirname(e);l.default.existsSync(e)?(l.default.unlinkSync(e),console.log("info cc-helper Removed binary:",e)):console.log("info cc-helper No binary found"),l.default.existsSync(t)&&l.default.readdirSync(t).length===0&&l.default.rmdirSync(t),console.log("info cc-helper To complete uninstallation, run:"),console.log(" npm uninstall -g @unitsvc/cc-helper")}async function D(e){if(!l.default.existsSync(e))return null;try{return(0,Y.execSync)(`"${e}" --version`,{timeout:5e3}).toString().trim().replace(/^v/i,"")}catch{return null}}async function tr(e){let t=y(),r=await E(e),o=await D(t);return{current:o,latest:r,needsUpdate:!o||o!==r}}0&&(module.exports={checkForUpdate,ensureBinary,findReleaseWithBinary,getArchiveName,getBinaryName,getBinaryPath,getCurrentVersion,getDownloadUrl,getLatestVersion,getPlatform,install,uninstall});
|