base_parts_ai 1.0.56 → 1.0.57

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 CHANGED
@@ -7,7 +7,7 @@
7
7
  npx base_parts_ai
8
8
  ```
9
9
 
10
- 无参数时会让用户选择 `jcc`、`jcx`、`weds` 或 `ucx`,再继续执行对应配置流程。
10
+ 无参数时会让用户选择 `jcc`、`jcx`、`weds`、`ucx` 或 `jgrok`,再继续执行对应流程。
11
11
 
12
12
  也可以明确指定工具,适合脚本或需要带参数的场景:
13
13
 
@@ -16,6 +16,7 @@ npx base_parts_ai jcc
16
16
  npx base_parts_ai jcx
17
17
  npx base_parts_ai weds
18
18
  npx base_parts_ai ucx
19
+ npx base_parts_ai jgrok
19
20
  npx base_parts_ai jcc setapi
20
21
  npx base_parts_ai jcx setapi
21
22
  npx base_parts_ai weds setapi
@@ -28,18 +29,21 @@ npx base_parts_ai --help
28
29
  npx base_parts_ai --version
29
30
  ```
30
31
 
31
- 通过 `base_parts_ai` 入口执行时,会屏蔽 `base_parts_ai` 自身自动升级;`jcc`、`jcx`、`weds`、`ucx` 单独运行行为保持不变。
32
+ 通过 `base_parts_ai` 入口执行时,会屏蔽 `base_parts_ai` 自身自动升级;`jcc`、`jcx`、`weds`、`ucx`、`jgrok` 单独运行行为保持不变。
32
33
 
33
34
  全局安装后也可以直接运行:
34
35
 
35
36
  ```powershell
36
37
  ucx
38
+ jgrok
37
39
  ```
38
40
 
39
41
  `ucx` 会扫描用户主目录下一层的 `~/.codex` 与 `~/.codex_*`。账号名优先用 `auth.json` 中非空 `OPENAI_API_KEY` 的脱敏短名,否则用 JWT email;不会自动创建空的 `~/.codex`。
40
42
 
43
+ `jgrok` 若 `~/.grok/.env` 不存在则写入代理示例并打印绝对路径,请编辑后再运行。已存在则把该文件注入环境变量:本机没有 `grok` 时通过腾讯云 npm 源安装 `@xai-official/grok`(安装不注入环境变量),然后启动 `grok`,用户参数原样透传。
44
+
41
45
  ## 下载发布的包
42
- https://registry.npmjs.org/base_parts_ai/-/base_parts_ai-1.0.56.tgz
46
+ https://registry.npmjs.org/base_parts_ai/-/base_parts_ai-1.0.57.tgz
43
47
 
44
48
  ## 然后放在jdwfiles目录下
45
49
  https://jdwfiles.oss-cn-hangzhou.aliyuncs.com/npm_pkg/base_parts_ai-1.0.34.tgz
package/bin/jgrok.js ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ var os = require('os');
6
+ var path = require('path');
7
+
8
+ /**
9
+ * 构建 jgrok 运行配置,只解析主目录
10
+ * @returns {{ homeDir: string }}
11
+ */
12
+ function getBuildCfg() {
13
+ var homeDir = process.env.JCC_TEST_HOME || os.homedir();
14
+ return { homeDir: homeDir };
15
+ }
16
+
17
+ /**
18
+ * 动态加载 lib 下的命令模块,便于本地开发时读取最新文件
19
+ * @param {string} libName lib 目录下的文件名(不含 .js)
20
+ * @returns {Function}
21
+ */
22
+ function loadLib(libName) {
23
+ var libPath = path.resolve(__dirname, '../lib/' + libName + '.js');
24
+ delete require.cache[require.resolve(libPath)];
25
+ return require(libPath);
26
+ }
27
+
28
+ /**
29
+ * 运行 jgrok CLI,参数全部透传给 grok,可供命令行直接执行或被 base_parts_ai require 调用
30
+ * @param {Array<string>} args 用户参数,不包含 node 和脚本路径
31
+ * @returns {Promise<number>}
32
+ */
33
+ async function runCli(args) {
34
+ var buildCfg = getBuildCfg();
35
+ return await loadLib('jgrok')(args || [], buildCfg);
36
+ }
37
+
38
+ if (require.main === module) {
39
+ runCli(process.argv.slice(2)).then(function (code) {
40
+ process.exit(typeof code === 'number' ? code : 0);
41
+ }).catch(function (err) {
42
+ console.error('jgrok 执行失败:', err.message);
43
+ process.exit(1);
44
+ });
45
+ }
46
+
47
+ module.exports = runCli;
@@ -17,5 +17,6 @@ console.log(c.cyan + ' ║ ' + c.yellow + '安装完成!输入以下命令
17
17
  console.log(c.cyan + ' ║ ' + c.green + 'jcc' + c.white + ' 配置或安装 ClaudeCode' + c.reset);
18
18
  console.log(c.cyan + ' ║ ' + c.green + 'weds' + c.white + ' 配置或安装 weds ClaudeCode' + c.reset);
19
19
  console.log(c.cyan + ' ║ ' + c.green + 'ucx' + c.white + ' 切换 Codex 账号' + c.reset);
20
+ console.log(c.cyan + ' ║ ' + c.green + 'jgrok' + c.white + ' 带代理环境启动 grok' + c.reset);
20
21
  console.log(c.cyan + ' ╚══════════════════════════════════════════╝' + c.reset);
21
22
  console.log('');
package/lib/ai_utils.js CHANGED
@@ -51,7 +51,7 @@ async function fetchRemoteText(url, timeoutMs) {
51
51
 
52
52
  /**
53
53
  * 从当前入口文件名推断正在运行的 CLI 命令名
54
- * @returns {string} jcc、jcx、weds、ucx 或空字符串
54
+ * @returns {string} jcc、jcx、weds、ucx、jgrok 或空字符串
55
55
  */
56
56
  function getCurrentCliName() {
57
57
  var entryName = path.basename(process.argv[1] || '').toLowerCase();
@@ -59,6 +59,7 @@ function getCurrentCliName() {
59
59
  if (entryName === 'jcc' || entryName === 'jcc.js') return 'jcc';
60
60
  if (entryName === 'weds' || entryName === 'weds.js') return 'weds';
61
61
  if (entryName === 'ucx' || entryName === 'ucx.js') return 'ucx';
62
+ if (entryName === 'jgrok' || entryName === 'jgrok.js') return 'jgrok';
62
63
  return '';
63
64
  }
64
65
 
package/lib/jgrok.js ADDED
@@ -0,0 +1,202 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * jgrok 命令:检测并安装 grok,注入 ~/.grok/.env 后启动官方 grok
5
+ * 首次创建 .env 只提示编辑,不启动 grok
6
+ */
7
+
8
+ var fs = require('fs');
9
+ var os = require('os');
10
+ var path = require('path');
11
+ var childProcess = require('child_process');
12
+
13
+ /** ~/.grok/.env 自定义代理示例内容 */
14
+ var GROK_ENV_DEMO = [
15
+ 'HTTP_PROXY=http://127.0.0.1:11811',
16
+ 'HTTPS_PROXY=http://127.0.0.1:11811',
17
+ 'ALL_PROXY=http://127.0.0.1:11811',
18
+ 'NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16',
19
+ '',
20
+ ].join('\n');
21
+
22
+ /** 缺失 grok 时走腾讯云 npm 源安装,不加 --force,安装时不注入环境变量 */
23
+ var GROK_INSTALL_CMD = 'npm install -g @xai-official/grok --registry=https://mirrors.cloud.tencent.com/npm/';
24
+
25
+ /**
26
+ * 解析用户主目录:优先 buildCfg.homeDir,再 JCC_TEST_HOME,最后 os.homedir()
27
+ * @param {object} [buildCfg] 入口传入的配置
28
+ * @returns {string}
29
+ */
30
+ function getHomeDir(buildCfg) {
31
+ if (buildCfg && buildCfg.homeDir) {
32
+ return buildCfg.homeDir;
33
+ }
34
+ return process.env.JCC_TEST_HOME || os.homedir();
35
+ }
36
+
37
+ /**
38
+ * 获取 ~/.grok 目录路径
39
+ * @param {string} homeDir 用户主目录
40
+ * @returns {string}
41
+ */
42
+ function getGrokDir(homeDir) {
43
+ return path.join(homeDir, '.grok');
44
+ }
45
+
46
+ /**
47
+ * 获取 ~/.grok/.env 绝对路径
48
+ * @param {string} homeDir 用户主目录
49
+ * @returns {string}
50
+ */
51
+ function getGrokEnvPath(homeDir) {
52
+ return path.join(getGrokDir(homeDir), '.env');
53
+ }
54
+
55
+ /**
56
+ * 解析 KEY=VALUE 文本,跳过空行和 # 注释,去掉值两端成对引号
57
+ * @param {string} content .env 文件内容
58
+ * @returns {object}
59
+ */
60
+ function parseEnvFile(content) {
61
+ var env = {};
62
+ String(content || '').replace(/^\uFEFF/, '').split(/\r?\n/).forEach(function (line) {
63
+ var trimmed = line.trim();
64
+ if (!trimmed || trimmed.charAt(0) === '#') {
65
+ return;
66
+ }
67
+ var eq = trimmed.indexOf('=');
68
+ if (eq <= 0) {
69
+ return;
70
+ }
71
+ var key = trimmed.slice(0, eq).trim();
72
+ var value = trimmed.slice(eq + 1).trim();
73
+ var quote = value.charAt(0);
74
+ if ((quote === '"' || quote === "'") && value.length >= 2 && value.charAt(value.length - 1) === quote) {
75
+ value = value.slice(1, -1);
76
+ }
77
+ env[key] = value;
78
+ });
79
+ return env;
80
+ }
81
+
82
+ /**
83
+ * 检测本机是否存在指定命令:Windows 用 where,其它用 which
84
+ * @param {string} name 命令名
85
+ * @param {object} [options] 可选配置,execImpl 用于注入 execSync
86
+ * @returns {boolean}
87
+ */
88
+ function commandExists(name, options) {
89
+ options = options || {};
90
+ var exec = options.execImpl || childProcess.execSync;
91
+ var cmd = process.platform === 'win32' ? ('where ' + name) : ('which ' + name);
92
+ try {
93
+ exec(cmd, { stdio: 'ignore' });
94
+ return true;
95
+ } catch (e) {
96
+ return false;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * 本机没有 grok 时通过腾讯云 npm 源全局安装,安装失败向上抛错
102
+ * 安装不注入 ~/.grok/.env,直接走镜像源
103
+ * @param {object} [options] 可选配置,execImpl 用于注入 execSync
104
+ * @returns {void}
105
+ */
106
+ function ensureGrokInstalled(options) {
107
+ if (commandExists('grok', options)) {
108
+ return;
109
+ }
110
+ options = options || {};
111
+ var exec = options.execImpl || childProcess.execSync;
112
+ console.log('未检测到 grok,正在从腾讯云 npm 源安装 @xai-official/grok ...');
113
+ exec(GROK_INSTALL_CMD, { stdio: 'inherit' });
114
+ }
115
+
116
+ /**
117
+ * 确保 ~/.grok/.env 存在;不存在则写入代理示例,已存在则不覆盖
118
+ * @param {string} homeDir 用户主目录
119
+ * @returns {{ created: boolean, envPath: string }}
120
+ */
121
+ function ensureGrokEnvFile(homeDir) {
122
+ var grokDir = getGrokDir(homeDir);
123
+ var envPath = getGrokEnvPath(homeDir);
124
+ if (!fs.existsSync(grokDir)) {
125
+ fs.mkdirSync(grokDir, { recursive: true });
126
+ }
127
+ if (fs.existsSync(envPath)) {
128
+ return { created: false, envPath: envPath };
129
+ }
130
+ fs.writeFileSync(envPath, GROK_ENV_DEMO, 'utf8');
131
+ return { created: true, envPath: envPath };
132
+ }
133
+
134
+ /**
135
+ * 将 .env 解析结果覆盖到当前进程环境副本上,供子进程使用
136
+ * @param {string} content .env 文件内容
137
+ * @returns {object}
138
+ */
139
+ function buildChildEnv(content) {
140
+ return Object.assign({}, process.env, parseEnvFile(content));
141
+ }
142
+
143
+ /**
144
+ * 启动官方 grok,Windows 走 shell 以便找到 grok.cmd
145
+ * @param {Array<string>} args 透传给 grok 的参数
146
+ * @param {object} childEnv 注入后的环境变量
147
+ * @param {object} [options] 可选配置,spawnImpl 用于注入 spawnSync
148
+ * @returns {number} grok 退出码
149
+ */
150
+ function spawnGrok(args, childEnv, options) {
151
+ options = options || {};
152
+ var spawn = options.spawnImpl || childProcess.spawnSync;
153
+ var result = spawn('grok', args || [], {
154
+ stdio: 'inherit',
155
+ shell: process.platform === 'win32',
156
+ env: childEnv,
157
+ }) || {};
158
+ if (result.error) {
159
+ throw result.error;
160
+ }
161
+ if (result.signal) {
162
+ return 1;
163
+ }
164
+ return typeof result.status === 'number' ? result.status : 0;
165
+ }
166
+
167
+ /**
168
+ * 执行 jgrok:先处理 .env,首次创建则提示编辑;否则注入环境后安装并启动 grok
169
+ * @param {Array<string>} args 透传给 grok 的参数
170
+ * @param {object} buildCfg 含 homeDir 的配置
171
+ * @param {object} [options] 可选配置,execImpl/spawnImpl 用于单测注入
172
+ * @returns {Promise<number>} 退出码
173
+ */
174
+ async function runJgrok(args, buildCfg, options) {
175
+ options = options || {};
176
+ var homeDir = getHomeDir(buildCfg);
177
+ var envResult = ensureGrokEnvFile(homeDir);
178
+ if (envResult.created) {
179
+ console.log('已首次创建 grok 环境文件,请编辑后再运行 jgrok:');
180
+ console.log(envResult.envPath);
181
+ return 0;
182
+ }
183
+ var childEnv = buildChildEnv(fs.readFileSync(envResult.envPath, 'utf8'));
184
+ ensureGrokInstalled(options);
185
+ return spawnGrok(args || [], childEnv, options);
186
+ }
187
+
188
+ runJgrok._private = {
189
+ GROK_ENV_DEMO: GROK_ENV_DEMO,
190
+ GROK_INSTALL_CMD: GROK_INSTALL_CMD,
191
+ getHomeDir: getHomeDir,
192
+ getGrokDir: getGrokDir,
193
+ getGrokEnvPath: getGrokEnvPath,
194
+ parseEnvFile: parseEnvFile,
195
+ commandExists: commandExists,
196
+ ensureGrokInstalled: ensureGrokInstalled,
197
+ ensureGrokEnvFile: ensureGrokEnvFile,
198
+ buildChildEnv: buildChildEnv,
199
+ spawnGrok: spawnGrok,
200
+ };
201
+
202
+ module.exports = runJgrok;
package/main.js CHANGED
@@ -6,7 +6,7 @@ var path = require('path');
6
6
  var inquirer = require('inquirer');
7
7
  var packageJson = require('./package.json');
8
8
 
9
- var VALID_TARGETS = ['jcc', 'jcx', 'weds', 'ucx'];
9
+ var VALID_TARGETS = ['jcc', 'jcx', 'weds', 'ucx', 'jgrok'];
10
10
 
11
11
  /**
12
12
  * 打印 base_parts_ai 入口命令的中文帮助信息
@@ -17,11 +17,12 @@ function printUsage() {
17
17
  'base_parts_ai 入口工具',
18
18
  '',
19
19
  '用法:',
20
- ' base_parts_ai 选择 jcc、jcx、weds 或 ucx 后继续执行',
20
+ ' base_parts_ai 选择 jcc、jcx、weds、ucx 或 jgrok 后继续执行',
21
21
  ' base_parts_ai jcc [参数...] 执行 Claude Code 配置工具',
22
22
  ' base_parts_ai jcx [参数...] 执行 Codex 配置工具',
23
23
  ' base_parts_ai weds [参数...] 执行 weds Claude Code 配置工具',
24
24
  ' base_parts_ai ucx [参数...] 通过目录改名切换 Codex 账号',
25
+ ' base_parts_ai jgrok [参数...] 注入 ~/.grok/.env 后启动 grok',
25
26
  ' base_parts_ai --help 显示入口帮助',
26
27
  ' base_parts_ai --version 显示当前版本',
27
28
  '',
@@ -57,13 +58,13 @@ function resolveTarget(args) {
57
58
 
58
59
  return {
59
60
  type: 'error',
60
- message: '参数无效:有参数时必须先明确指定 jcc、jcx、weds 或 ucx。',
61
+ message: '参数无效:有参数时必须先明确指定 jcc、jcx、weds、ucx 或 jgrok。',
61
62
  };
62
63
  }
63
64
 
64
65
  /**
65
66
  * 让用户选择要继续执行的配置工具
66
- * @returns {Promise<string>} jcc、jcx、weds 或 ucx
67
+ * @returns {Promise<string>} jcc、jcx、weds、ucx 或 jgrok
67
68
  */
68
69
  async function selectTarget() {
69
70
  var answer = await inquirer.prompt([{
@@ -75,6 +76,7 @@ async function selectTarget() {
75
76
  { name: 'jcx - Codex 配置工具', value: 'jcx' },
76
77
  { name: 'weds - weds Claude Code 配置工具', value: 'weds' },
77
78
  { name: 'ucx - 切换 Codex 账号', value: 'ucx' },
79
+ { name: 'jgrok - 带代理环境启动 grok', value: 'jgrok' },
78
80
  ],
79
81
  }]);
80
82
  return answer.target;
@@ -82,7 +84,7 @@ async function selectTarget() {
82
84
 
83
85
  /**
84
86
  * 获取当前包内目标 CLI 脚本路径
85
- * @param {string} target jcc、jcx、weds 或 ucx
87
+ * @param {string} target jcc、jcx、weds、ucx 或 jgrok
86
88
  * @returns {string}
87
89
  */
88
90
  function getTargetScriptPath(target) {
@@ -90,8 +92,8 @@ function getTargetScriptPath(target) {
90
92
  }
91
93
 
92
94
  /**
93
- * 加载当前包内的 jcc/jcx/weds/ucx 入口函数
94
- * @param {string} target jcc、jcx、weds 或 ucx
95
+ * 加载当前包内的 jcc/jcx/weds/ucx/jgrok 入口函数
96
+ * @param {string} target jcc、jcx、weds、ucx 或 jgrok
95
97
  * @returns {Function}
96
98
  */
97
99
  function loadTargetCli(target) {
@@ -99,8 +101,8 @@ function loadTargetCli(target) {
99
101
  }
100
102
 
101
103
  /**
102
- * 同进程执行当前包内的 jcc/jcx/weds/ucx 入口,并临时注入跳过自身升级的环境变量
103
- * @param {string} target jcc、jcx、weds 或 ucx
104
+ * 同进程执行当前包内的 jcc/jcx/weds/ucx/jgrok 入口,并临时注入跳过自身升级的环境变量
105
+ * @param {string} target jcc、jcx、weds、ucx 或 jgrok
104
106
  * @param {Array<string>} args 透传给目标入口的参数
105
107
  * @param {Function} loader 测试用入口加载函数,默认 loadTargetCli
106
108
  * @returns {Promise<number>} 退出码
@@ -113,8 +115,8 @@ async function runTarget(target, args, loader) {
113
115
  if (typeof runCli !== 'function') {
114
116
  throw new Error(target + ' 入口没有导出可调用函数');
115
117
  }
116
- await runCli(args || []);
117
- return 0;
118
+ var result = await runCli(args || []);
119
+ return typeof result === 'number' ? result : 0;
118
120
  } finally {
119
121
  if (typeof oldSkipSelfUpdate === 'undefined') {
120
122
  delete process.env.BASE_PARTS_AI_SKIP_SELF_UPDATE;
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "base_parts_ai",
3
- "version": "1.0.56",
3
+ "version": "1.0.57",
4
4
  "description": "jaskle base_parts_ai",
5
5
  "main": "./main.js",
6
6
  "registry": true,
7
7
  "directories": {},
8
8
  "scripts": {
9
- "test": "node ./test_project_md_rename.js && node ./test_main.js && node ./test_jcc.js && node ./test_jcx.js && node ./test_ucx.js",
9
+ "test": "node ./test_project_md_rename.js && node ./test_main.js && node ./test_jcc.js && node ./test_jcx.js && node ./test_ucx.js && node ./test_jgrok.js",
10
10
  "jcc": "node ./bin/jcc.js",
11
11
  "jcx": "node ./bin/jcx.js",
12
12
  "weds": "node ./bin/weds.js",
13
13
  "ucx": "node ./bin/ucx.js",
14
+ "jgrok": "node ./bin/jgrok.js",
14
15
  "base_parts_ai": "node ./main.js",
15
16
  "__postinstall": "node ./bin/postinstall.js"
16
17
  },
@@ -19,7 +20,8 @@
19
20
  "jcc": "./bin/jcc.js",
20
21
  "jcx": "./bin/jcx.js",
21
22
  "weds": "./bin/weds.js",
22
- "ucx": "./bin/ucx.js"
23
+ "ucx": "./bin/ucx.js",
24
+ "jgrok": "./bin/jgrok.js"
23
25
  },
24
26
  "files": [
25
27
  "main.js",