base_parts_ai 1.0.30

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.
@@ -0,0 +1,26 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npm test:*)",
5
+ "Bash(npx mocha:*)",
6
+ "Bash(node -e:*)",
7
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node -e \"\"var p = require\\(''commander''\\); console.log\\(typeof p\\); console.log\\(Object.keys\\(p\\).slice\\(0,10\\)\\);\"\"\")",
8
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node -e \"\"var p = require\\(''commander''\\); console.log\\(typeof p\\); console.log\\(JSON.stringify\\(Object.keys\\(p\\)\\)\\);\"\"\")",
9
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && cat node_modules/commander/package.json | findstr \"\"version\"\"\")",
10
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node -e \"\"var p = require\\(''commander''\\); console.log\\(typeof p\\); console.log\\(typeof p.command\\); console.log\\(typeof p.Command\\);\"\"\")",
11
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node bin\\\\jcc.js --help\")",
12
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node bin\\\\jcc.js setapi --help 2>&1\")",
13
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node bin\\\\jcc.js setapi --help\")",
14
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node -e \"\"var {Command}=require\\(''commander''\\);var p=new Command\\(\\);p.command\\(''setapi''\\).action\\(function\\(\\){console.log\\(''ok''\\)}\\);p.parse\\([''node'',''test'',''setapi'']\\)\"\"\")",
15
+ "Bash(cmd.exe /c \"node -e \"\"var {Command}=require\\(''commander''\\);console.log\\(''ok''\\);\"\" 2>&1\")",
16
+ "Bash(cmd.exe /c \"cd /d F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai && node -e \"\"try{var r=require\\(''commander''\\);console.log\\(typeof r\\);console.log\\(typeof r.Command\\);console.log\\(typeof r.program\\);}catch\\(e\\){console.error\\(e.message\\);}\"\"\")",
17
+ "Bash(powershell -Command \"cd ''F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai''; node -e \"\"var r=require\\(''commander''\\);console.log\\(typeof r\\);console.log\\(typeof r.Command\\);\"\"\")",
18
+ "Bash(powershell -Command \"cd ''F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai''; node --check bin\\\\jcc.js; echo ''syntax ok''\")",
19
+ "Bash(powershell -Command:*)",
20
+ "Bash(cmd.exe /c \"if exist F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai\\\\test_home rmdir /s /q F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai\\\\test_home && mkdir F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai\\\\test_home && echo done\")",
21
+ "Bash(cmd.exe /c \"mkdir F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai\\\\test_home && echo done\")",
22
+ "Bash(powershell -NoProfile -Command:*)",
23
+ "Bash(cmd.exe /c \"set JCC_TEST_HOME=F:\\\\Pro_My_New\\\\jnode_base_parts\\\\base_parts_ai\\\\test_home && node -e \"\"process.chdir\\(''F:/Pro_My_New/jnode_base_parts/base_parts_ai''\\); var getBuildCfg; eval\\(require\\(''fs''\\).readFileSync\\(''./bin/jcc.js'',''utf8''\\).split\\(''program.parse''\\)[0].replace\\(''#!/usr/bin/env node'',''''\\)\\); var cfg=getBuildCfg\\({}\\); console.log\\(JSON.stringify\\({claudeSettingsPath:cfg.claudeSettingsPath,jccJsonPath:cfg.jccJsonPath},null,2\\)\\);\"\"\")"
24
+ ]
25
+ }
26
+ }
package/.eslintrc.js ADDED
@@ -0,0 +1,264 @@
1
+ module.exports = {
2
+ "env": {
3
+ "node" : true,
4
+ "browser": true,
5
+ "commonjs": true,
6
+ "es6": true,
7
+ "mocha" : true
8
+ },
9
+ "parserOptions": {
10
+ "ecmaVersion": "latest"
11
+ // "sourceType": "module",
12
+ // "ecmaFeatures": {
13
+ // "jsx": true
14
+ // }
15
+ },
16
+ "extends": "eslint:recommended",
17
+ "rules": {
18
+ "accessor-pairs": "error",
19
+ "array-bracket-newline": "error",
20
+ "array-bracket-spacing": "error",
21
+ "array-callback-return": "error",
22
+ "array-element-newline": "off",
23
+ "arrow-body-style": "off",
24
+ "arrow-parens": [
25
+ "error",
26
+ "always"
27
+ ],
28
+ "arrow-spacing": "warn",
29
+ "block-scoped-var": "off",
30
+ "block-spacing": [
31
+ "error",
32
+ "always"
33
+ ],
34
+ "brace-style": "off",
35
+ "callback-return": "error",
36
+ "camelcase": "off",
37
+ "capitalized-comments": "off",
38
+ "class-methods-use-this": "off",
39
+ "comma-dangle": "off",
40
+ "comma-spacing": "off",
41
+ "comma-style": [
42
+ "error",
43
+ "last"
44
+ ],
45
+ "complexity": [0, 30],
46
+ "computed-property-spacing": [
47
+ "error",
48
+ "never"
49
+ ],
50
+ "consistent-return": "off",
51
+ "consistent-this": "off",
52
+ "curly": "off",
53
+ "default-case": "error",
54
+ "dot-location": "off",
55
+ "dot-notation": "off",
56
+ "eol-last": "off",
57
+ "eqeqeq": "error",
58
+ "for-direction": "error",
59
+ "func-call-spacing": "error",
60
+ "func-name-matching": "error",
61
+ "func-names": [
62
+ "error",
63
+ "never"
64
+ ],
65
+ "func-style": "off",
66
+ "function-paren-newline": "off",
67
+ "generator-star-spacing": "off",
68
+ "getter-return": "error",
69
+ "global-require": "off",
70
+ "guard-for-in": "off",
71
+ "handle-callback-err": "off",
72
+ "id-blacklist": "error",
73
+ "id-length": "off",
74
+ "id-match": "error",
75
+ "indent": "off",
76
+ "indent-legacy": "off",
77
+ "init-declarations": "off",
78
+ "jsx-quotes": "error",
79
+ "key-spacing": "off",
80
+ "keyword-spacing": "off",
81
+ "line-comment-position": "off",
82
+ "linebreak-style": "off",
83
+ "lines-around-comment": "off",
84
+ "lines-around-directive": "off",
85
+ "max-depth": [0, 5],
86
+ "max-len": "off",
87
+ "max-lines": "off",
88
+ "max-nested-callbacks": "error",
89
+ "max-params": "off",
90
+ "max-statements": "off",
91
+ "max-statements-per-line": "off",
92
+ "new-parens": "error",
93
+ "newline-after-var": "off",
94
+ "newline-before-return": "off",
95
+ "newline-per-chained-call": "off",
96
+ "no-alert": "error",
97
+ "no-array-constructor": "error",
98
+ "no-await-in-loop": "off",
99
+ "no-bitwise": "error",
100
+ "no-buffer-constructor": "off",
101
+ "no-caller": "error",
102
+ "no-catch-shadow": "error",
103
+ "no-confusing-arrow": "error",
104
+ "no-continue": "off",
105
+ "no-div-regex": "error",
106
+ "no-duplicate-imports": "error",
107
+ "no-else-return": "off",
108
+ "no-empty-function": "off",
109
+ "no-empty": "off",
110
+ "no-eq-null": "error",
111
+ "no-eval": "error",
112
+ "no-extend-native": "error",
113
+ "no-extra-bind": "error",
114
+ "no-extra-label": "error",
115
+ "no-extra-parens": "off",
116
+ "no-floating-decimal": "error",
117
+ "no-implicit-coercion": "off",
118
+ "no-implicit-globals": "error",
119
+ "no-implied-eval": "error",
120
+ "no-inline-comments": "off",
121
+ "no-inner-declarations": [
122
+ "error",
123
+ "functions"
124
+ ],
125
+ "no-invalid-this": "off",
126
+ "no-iterator": "error",
127
+ "no-label-var": "error",
128
+ "no-labels": "error",
129
+ "no-lone-blocks": "off",
130
+ "no-lonely-if": "error",
131
+ "no-loop-func": "off",
132
+ "no-magic-numbers": "off",
133
+ "no-mixed-operators": "error",
134
+ "no-mixed-requires": "warn",
135
+ "no-multi-assign": "error",
136
+ "no-multi-spaces": "off",
137
+ "no-multi-str": "error",
138
+ "no-multiple-empty-lines": "off",
139
+ "no-native-reassign": "error",
140
+ "no-negated-condition": "off",
141
+ "no-negated-in-lhs": "error",
142
+ "no-nested-ternary": "off",
143
+ "no-new": "error",
144
+ "no-new-func": "error",
145
+ "no-new-object": "error",
146
+ "no-new-require": "error",
147
+ "no-new-wrappers": "error",
148
+ "no-octal-escape": "off",
149
+ "no-param-reassign": "off",
150
+ "no-path-concat": "off",
151
+ "no-plusplus": "off",
152
+ "no-process-env": "off",
153
+ "no-process-exit": "off",
154
+ "no-proto": "error",
155
+ "no-prototype-builtins": "off",
156
+ "no-restricted-globals": "error",
157
+ "no-restricted-imports": "error",
158
+ "no-restricted-modules": "error",
159
+ "no-restricted-properties": "error",
160
+ "no-restricted-syntax": "error",
161
+ "no-return-assign": "error",
162
+ "no-return-await": "error",
163
+ "no-script-url": "error",
164
+ "no-self-compare": "error",
165
+ "no-sequences": "error",
166
+ "no-shadow": "off",
167
+ "no-shadow-restricted-names": "error",
168
+ "no-spaced-func": "error",
169
+ "no-sync": "off",
170
+ "no-tabs": "error",
171
+ "no-template-curly-in-string": "error",
172
+ "no-ternary": "off",
173
+ "no-throw-literal": "error",
174
+ "no-trailing-spaces": "off",
175
+ "no-undef-init": "error",
176
+ "no-undefined": "off",
177
+ "no-underscore-dangle": "off",
178
+ "no-unmodified-loop-condition": "error",
179
+ "no-unneeded-ternary": "off",
180
+ "no-unused-expressions": "error",
181
+ "no-use-before-define": "off",
182
+ "no-useless-call": "error",
183
+ "no-useless-computed-key": "error",
184
+ "no-useless-concat": "error",
185
+ "no-useless-constructor": "off",
186
+ "no-useless-rename": "error",
187
+ "no-useless-return": "warn",
188
+ "no-var": "off",
189
+ "no-void": "error",
190
+ "no-warning-comments": "error",
191
+ "no-whitespace-before-property": "error",
192
+ "no-with": "error",
193
+ "object-curly-newline": "off",
194
+ "object-curly-spacing": "off",
195
+ "object-property-newline": "off",
196
+ "object-shorthand": "off",
197
+ "one-var": "off",
198
+ "one-var-declaration-per-line": "warn",
199
+ "no-unused-vars": "warn",
200
+ "operator-assignment": [
201
+ "error",
202
+ "always"
203
+ ],
204
+ "operator-linebreak": [
205
+ "error",
206
+ "before"
207
+ ],
208
+ "padded-blocks": "off",
209
+ "padding-line-between-statements": "error",
210
+ "prefer-arrow-callback": "off",
211
+ "prefer-const": "off",
212
+ "prefer-destructuring": "off",
213
+ "prefer-numeric-literals": "error",
214
+ "prefer-promise-reject-errors": "error",
215
+ "prefer-reflect": "off",
216
+ "prefer-rest-params": "off",
217
+ "prefer-spread": "error",
218
+ "prefer-template": "off",
219
+ "quote-props": "off",
220
+ "quotes": "off",
221
+ "radix": [
222
+ "error",
223
+ "always"
224
+ ],
225
+ "require-await": "off",
226
+ "require-jsdoc": "off",
227
+ "rest-spread-spacing": "error",
228
+ "semi": "off",
229
+ "semi-spacing": "off",
230
+ "semi-style": [
231
+ "error",
232
+ "last"
233
+ ],
234
+ "sort-imports": "error",
235
+ "sort-keys": "off",
236
+ "sort-vars": "warn",
237
+ "space-before-blocks": "off",
238
+ "space-before-function-paren": "off",
239
+ "space-in-parens": [
240
+ "error",
241
+ "never"
242
+ ],
243
+ "space-infix-ops": "off",
244
+ "space-unary-ops": "off",
245
+ "spaced-comment": "off",
246
+ "strict": "off",
247
+ "switch-colon-spacing": "error",
248
+ "symbol-description": "off",
249
+ "template-curly-spacing": "error",
250
+ "template-tag-spacing": "error",
251
+ "unicode-bom": [
252
+ "error",
253
+ "never"
254
+ ],
255
+ "valid-jsdoc": "off",
256
+ "vars-on-top": "off",
257
+ "wrap-iife": "off",
258
+ "wrap-regex": "error",
259
+ "yield-star-spacing": "error",
260
+ "yoda": "off",
261
+ "no-console": "off",
262
+ "require-yield": "off"
263
+ }
264
+ };
package/CLAUDE.md ADDED
@@ -0,0 +1,93 @@
1
+ # CLAUDE.md
2
+
3
+ 本文件为 Claude Code (claude.ai/code) 提供在操作此代码仓库时的指导。
4
+
5
+ ## 项目概述
6
+
7
+ `base_parts_ai` 是一个用于辅助 AI 项目的工具集,提供 CLI 命令行工具 `jcc`。
8
+
9
+ ## 项目结构
10
+
11
+ ```
12
+ bin/
13
+ jcc.js # CLI 入口,注册所有命令,含 getBuildCfg / loadLib
14
+ lib/
15
+ claude_utils.js # 共享工具:渠道列表、读写JSON、脱敏显示等
16
+ setapi.js # setapi 命令:交互式选择 AI 渠道
17
+ setkey.js # setkey 命令:设置 AI Key
18
+ test_jcc.js # 功能测试脚本(npm test)
19
+ ```
20
+
21
+ ## 已实现命令
22
+
23
+ ### `jcc setapi`
24
+ 交互式选择 AI 渠道,将渠道 id 写入 `~/.claude/settings.json` 的 `__jid` 字段。
25
+ - 将选中渠道的 `envObj` 通过 `Object.assign` 合并到 `settings.env`,合并后值为 `null` 或 `""` 的字段一律删除
26
+ - 同时写入固定字段到 `settings.json`:`hooks`(SessionStart curl 上报)、`language`(简体中文)、`autoUpdatesChannel`(stable)
27
+ - 同时写入固定字段到 `~/.claude.json`:`autoUpdaterStatus: 'disabled'`、`hasCompletedOnboarding: true`
28
+ - 若该渠道有缓存 Key(来自 `~/.claude/jcc.json`),自动切换;若无,提示用户输入并保存
29
+ - 切换后检测 Claude 版本:若当前版本与渠道 `ccVersion` 不符,自动从 OSS 下载对应 tgz 并通过 `npm install -g` 安装
30
+
31
+ ### `jcc setkey`
32
+ 设置当前渠道的 API Key,写入 `settings.json` 并缓存到 `jcc.json`。
33
+ - 当前渠道通过 `settings.__jid` 字段识别
34
+ - 若 `__jid` 无法匹配已知渠道,Key 仅写入 `settings.json`,不缓存到 `jcc.json`
35
+
36
+ ## 关键设计
37
+
38
+ - **热更新**:`loadLib(name)` 每次清除 require 缓存,修改 lib 下的 js 无需重启
39
+ - **路径变量**:`getBuildCfg` 中统一管理 `claudeJsonPath` / `claudeSettingsPath` / `jccJsonPath`
40
+ - **版本号**:`getBuildCfg` 通过子进程 `npm root -g` 获取全局包路径,读取 `@anthropic-ai/claude-code/package.json` 提取版本号到 `buildCfg.claudeVersion`
41
+ - **渠道标识**:选中渠道的 id 强制写入 `settings.__jid`,`getCurrentInfo` 以此匹配渠道
42
+ - **目录自动创建**:首次运行自动创建 `~/.claude/` 目录和空 `settings.json`
43
+ - **测试隔离**:设置环境变量 `JCC_TEST_HOME` 可将所有文件读写重定向到测试目录,不影响真实环境
44
+ - **渠道列表**:写死在 `lib/claude_utils.js` 的 `API_CHANNELS` 数组中,每个渠道含 `envObj`(完整 env 对象)和 `ccVersion`(要求的 Claude 版本),差异化配置直接在 `envObj` 中声明
45
+
46
+ ## 渠道结构
47
+
48
+ `API_CHANNELS` 中每个渠道对象的字段:
49
+
50
+ | 字段 | 类型 | 说明 |
51
+ |-------------|------|----------------------------------------------|
52
+ | `id` | string | 唯一标识,写入 `settings.__jid` |
53
+ | `name` | string | 显示名称 |
54
+ | `description` | string | 简短描述 |
55
+ | `ccVersion` | string | 该渠道要求的 Claude Code 版本号 |
56
+ | `envObj` | object | 完整 env 配置对象,合并到 `settings.env` |
57
+
58
+ `envObj` 通过两个基础模板叠加构建:
59
+ - `jpub_EnvObj`:所有渠道共有的公共字段(`DISABLE_AUTOUPDATER`、`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` 等)
60
+ - `jai_EnvObj`:JAI 自建网关专用字段(`ANTHROPIC_BASE_URL`、`ANTHROPIC_DEFAULT_*_MODEL`)
61
+
62
+ 当前渠道列表:
63
+
64
+ | id | 说明 | ccVersion |
65
+ |---------------------|-------------------------------|-----------|
66
+ | `jai_claude_128k` | JAI 自建网关,Claude 128K上下文 | 2.1.22 |
67
+ | `jai_low_cost` | JAI 低成本(GLM-5/GLM-4.7) | 2.1.22 |
68
+ | `jth_BestAiGate` | Best Ai Gate 第三方网关 | 2.1.22 |
69
+ | `jth_pincc_1M` | Pincc 1M 上下文网关 | 2.1.76 |
70
+
71
+ ## 注意事项
72
+
73
+ - commander 版本为 v14+,需用 `new Command()` 实例化,action 用 `function(){}` + `this.opts()`
74
+ - inquirer 版本为 v13+(package.json 中为 `inquirer ^13.x`),setapi.js / setkey.js 中使用 `@inquirer/prompts` 的具名函数(`select`、`input`)代替旧式 `prompt([...])`
75
+ - 编写代码时关键操作及函数、类、变量、接口等定义都要加上中文注释
76
+
77
+ ## 测试
78
+
79
+ ```bash
80
+ npm test
81
+ ```
82
+
83
+ 测试脚本 `test_jcc.js` 共 10 个用例,覆盖:
84
+ 1. 目录自动创建
85
+ 2. `loadSettings` 读取空文件
86
+ 3. `setapi` envObj 合并写入(含 hooks / language / claudeJson 固定字段)
87
+ 4. `getCurrentInfo` 渠道识别
88
+ 5. `setkey` 更新 Key 并同步 jcc.json
89
+ 6. 切换渠道时 envObj 覆盖逻辑(`ANTHROPIC_DEFAULT_OPUS_MODEL` 空值被清除)
90
+ 7. `API_CHANNELS` 列表结构验证(含 ccVersion / envObj)
91
+ 8. `maskKey` 脱敏显示
92
+ 9. `jai_low_cost` 渠道 GLM 模型字段验证
93
+ 10. `printCurrentInfo` smoke test(不抛异常)
package/NEXT.md ADDED
@@ -0,0 +1 @@
1
+
package/bin/jcc.js ADDED
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+
3
+ var jutils = require('base_parts');
4
+ var jlog = jutils.jlog(__filename);
5
+
6
+ var fs = require('fs');
7
+ var os = require('os');
8
+ var path = require('path');
9
+ // commander v14+ 改为具名导出,需用 Command 类实例化
10
+ var { Command } = require('commander');
11
+ var program = new Command();
12
+
13
+
14
+ // 关闭日志输出
15
+ jlog.setEnable(false, "*");
16
+
17
+
18
+ /**
19
+ * 获取配置文件
20
+ * @param {string} cmd 命令行
21
+ * @returns {*} 配置段
22
+ */
23
+ function getBuildCfg(cmd) {
24
+ // 配置路径
25
+ if (!cmd.config) {
26
+ cmd.config = process.cwd() + "/jai_cfg.json";
27
+ }
28
+ cmd.config = path.resolve(cmd.config);
29
+
30
+ // 读入配置
31
+ // console.log("Read jai_cfg.json ...");
32
+ var buildCfg = {}
33
+ try {
34
+ // console.log("[Config path] " + cmd.config);
35
+ buildCfg = JSON.parse(jutils.jsonTrim(fs.readFileSync(cmd.config, "utf8")));
36
+ } catch (error) {
37
+ // console.log("[Notice] not found jai_cfg.json");
38
+ }
39
+
40
+ // 详情输出
41
+ buildCfg.details = cmd.details;
42
+
43
+ // 缺省路径
44
+ if (!buildCfg.rootPath) {
45
+ buildCfg.rootPath = process.cwd();
46
+ }
47
+ buildCfg.rootPath = path.resolve(buildCfg.rootPath);
48
+ // console.log("[Root path] " + buildCfg.rootPath);
49
+
50
+ // 从 npm 全局目录下的 @anthropic-ai/claude-code/package.json 提取 Claude 版本号
51
+ try {
52
+ // 通过子进程执行 npm root -g 获取全局包根目录,兼容不同系统安装位置
53
+ var npmRootG = require('child_process').execSync('npm root -g', { encoding: 'utf8' }).trim();
54
+ var claudePkgPath = path.join(npmRootG, '@anthropic-ai', 'claude-code', 'package.json');
55
+ var claudePkg = JSON.parse(fs.readFileSync(claudePkgPath, 'utf8'));
56
+ buildCfg.claudeVersion = claudePkg.version || '';
57
+ } catch (e) {
58
+ buildCfg.claudeVersion = '';
59
+ }
60
+ console.log("[Claude version] " + (buildCfg.claudeVersion || '(未找到)'));
61
+
62
+ // Claude 配置文件路径(跨平台支持)
63
+ // 支持环境变量 JCC_TEST_HOME 覆盖 homedir,方便测试时隔离环境
64
+ var homeDir = process.env.JCC_TEST_HOME || os.homedir();
65
+ // ~/.claude.json 全局配置
66
+ buildCfg.claudeJsonPath = path.join(homeDir, '.claude.json');
67
+ // ~/.claude/settings.json Claude Code 设置文件
68
+ buildCfg.claudeSettingsPath = path.join(homeDir, '.claude', 'settings.json');
69
+ // ~/.claude/jcc.json 自定义渠道Key存储文件
70
+ buildCfg.jccJsonPath = path.join(homeDir, '.claude', 'jcc.json');
71
+
72
+ // 确保 ~/.claude 目录存在,防止未安装 Claude 时崩溃
73
+ var claudeDir = path.join(homeDir, '.claude');
74
+ if (!fs.existsSync(claudeDir)) {
75
+ fs.mkdirSync(claudeDir, { recursive: true });
76
+ console.log('[Init] 已创建目录: ' + claudeDir);
77
+ }
78
+ // 确保 settings.json 存在(空对象兜底)
79
+ if (!fs.existsSync(buildCfg.claudeSettingsPath)) {
80
+ fs.writeFileSync(buildCfg.claudeSettingsPath, '{}', 'utf8');
81
+ console.log('[Init] 已创建文件: ' + buildCfg.claudeSettingsPath);
82
+ }
83
+
84
+ return buildCfg;
85
+ }
86
+
87
+ /**
88
+ * 动态加载 lib 下的命令模块(热更新)
89
+ * @param {string} libName lib目录下的文件名(不含.js)
90
+ * @returns {Function} 导出的模块函数
91
+ */
92
+ function loadLib(libName) {
93
+ var libPath = path.resolve(__dirname, '../lib/' + libName + '.js');
94
+ // 清除 require 缓存,实现热更新
95
+ delete require.cache[require.resolve(libPath)];
96
+ return require(libPath);
97
+ }
98
+
99
+ // 命令:setapi —— 选择 AI 渠道,修改 Claude settings.json 中的 ANTHROPIC_BASE_URL
100
+ program
101
+ .command('setapi')
102
+ // .option('-c, --config <file>', 'Config file,default:jai_cfg.json')
103
+ .action(async function () {
104
+ // commander v14:通过 this.opts() 获取选项
105
+ var opts = this.opts();
106
+ var buildCfg = getBuildCfg(opts);
107
+ await loadLib('setapi')(opts, buildCfg);
108
+ console.log("\nfinish");
109
+ });
110
+
111
+ // 命令:setkey —— 设置 AI Key,修改 Claude settings.json 中的 ANTHROPIC_API_KEY
112
+ program
113
+ .command('setkey')
114
+ // .option('-c, --config <file>', 'Config file,default:jai_cfg.json')
115
+ .action(async function () {
116
+ // commander v14:通过 this.opts() 获取选项
117
+ var opts = this.opts();
118
+ var buildCfg = getBuildCfg(opts);
119
+ await loadLib('setkey')(opts, buildCfg);
120
+ console.log("\nfinish");
121
+ });
122
+
123
+
124
+ // 若未传入任何子命令,默认执行 setapi
125
+ if (process.argv.length <= 2) {
126
+ process.argv.push('setapi');
127
+ }
128
+
129
+ // 开始解析
130
+ program.parse(process.argv);
131
+
132
+
133
+