deepminer-cli 0.1.25 → 0.1.26

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
@@ -11,7 +11,7 @@ DeepMiner 系统的命令行工具,用于管理认证、配置和 AI 会话。
11
11
  - **配置管理**: API 端点配置
12
12
  - **安全存储**: Token 以受限权限存储在本地
13
13
  - **文件上传**: 上传文件到 OSS,带文件大小验证
14
- - **AI 会话**: 启动 AI 助手会话,支持自定义消息和 claw_param 参数
14
+ - **AI 会话**: 启动/继续/停止 AI 助手会话,支持自定义消息、会话追问和 claw_param 参数
15
15
  - **JSON 输出**: 所有命令支持 `--json` 结构化输出,适合 AI agent 和脚本调用
16
16
  - **错误提示**: 错误响应包含 `hint` 字段,提供可操作的修复建议
17
17
  - **Dry Run**: `--dry-run` 预览 HTTP 请求而不实际执行
@@ -50,9 +50,15 @@ dm-cli auth switch <space_id>
50
50
  # 4. 查看状态
51
51
  dm-cli auth status
52
52
 
53
- # 5. 启动 AI 会话
53
+ # 5. 启动 AI 会话(返回 agent_run_id、thread_id)
54
54
  dm-cli agent start-thread --message "你好"
55
55
 
56
+ # 5a. 在已有会话中继续追问
57
+ dm-cli agent start-thread --message "继续聊" --thread-id <thread_id>
58
+
59
+ # 5b. 停止正在运行的 Agent
60
+ dm-cli agent stop --agent-run-id <agent_run_id>
61
+
56
62
  # 6. 上传文件
57
63
  dm-cli file upload --file document.pdf
58
64
 
@@ -112,7 +118,9 @@ dm-cli file upload --file <路径> --id <ID> # 上传文件(指
112
118
  ```bash
113
119
  dm-cli agent start-thread # 使用默认消息 "你好"
114
120
  dm-cli agent start-thread --message <消息> # 自定义消息
115
- dm-cli agent start-thread --message <消息> --claw-param <JSON> # 完整参数
121
+ dm-cli agent start-thread --message <消息> --thread-id <会话ID> # 在已有会话中继续追问
122
+ dm-cli agent start-thread --message <消息> --claw-param <JSON> # 附带渠道参数
123
+ dm-cli agent stop --agent-run-id <运行ID> # 停止正在运行的 Agent
116
124
  ```
117
125
 
118
126
  #### claw_param 参数说明
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepminer-cli",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "DeepMiner CLI - Command-line tool for DM system with cross-platform support, JWT authentication, and workspace management",
5
5
  "keywords": [
6
6
  "deepminer",
package/scripts/_dm-cli CHANGED
@@ -1,43 +1,199 @@
1
1
  #compdef dm-cli
2
2
 
3
3
  _dm_cli() {
4
- local -a commands
5
- local -i idx
6
-
7
- # 找到当前位置
8
- for ((idx = 2; idx < $#words; idx++)); do
9
- if [[ "${words[idx]}" != -* ]]; then
10
- break
11
- fi
12
- done
13
-
14
- # 如果只有 dm-cli,显示顶级命令
15
- if [[ $idx -eq $#words ]]; then
16
- commands=(
17
- 'config:管理配置'
18
- 'auth:用户认证'
19
- 'agent:AI 助手相关命令'
20
- 'file:文件管理'
21
- 'schema:输出 CLI Schema 定义'
22
- 'version:显示版本号'
23
- )
24
- _describe 'command' commands
25
- return
26
- fi
27
-
28
- # 根据第一个参数显示子命令
29
- case "${words[$idx]}" in
30
- config)
31
- _describe 'config subcommand' '(init:初始化配置 show:显示配置)'
32
- ;;
33
- auth)
34
- _describe 'auth subcommand' '(login:登录 logout:登出 status:显示状态 switch:切换空间)'
35
- ;;
36
- agent)
37
- _describe 'agent subcommand' '(start-thread:发起AI会话)'
38
- ;;
39
- file)
40
- _describe 'file subcommand' '(upload:上传文件)'
4
+ local context state state_descr line
5
+ typeset -A opt_args
6
+
7
+ _arguments -C \
8
+ '--json[以 JSON 格式输出]' \
9
+ '--dry-run[预览请求而不执行]' \
10
+ '(- *)--help[显示帮助]' \
11
+ '(-): :->command' \
12
+ '(-)*:: :->args'
13
+
14
+ case "$state" in
15
+ command)
16
+ local -a commands=(
17
+ 'config:管理配置'
18
+ 'auth:用户认证'
19
+ 'agent:AI 助手相关命令'
20
+ 'file:文件管理'
21
+ 'schema:输出 CLI Schema 定义'
22
+ 'version:显示版本号'
23
+ )
24
+ _describe -t commands 'command' commands
25
+ ;;
26
+ args)
27
+ case "${line[1]}" in
28
+ config) _dm_cli_config ;;
29
+ auth) _dm_cli_auth ;;
30
+ agent) _dm_cli_agent ;;
31
+ file) _dm_cli_file ;;
32
+ schema) _dm_cli_schema ;;
33
+ esac
34
+ ;;
35
+ esac
36
+ }
37
+
38
+ _dm_cli_config() {
39
+ local context state state_descr line
40
+ typeset -A opt_args
41
+
42
+ _arguments -C \
43
+ '(-): :->subcommand' \
44
+ '(-)*:: :->args'
45
+
46
+ case "$state" in
47
+ subcommand)
48
+ local -a subcommands=(
49
+ 'init:初始化配置'
50
+ 'show:显示当前配置'
51
+ )
52
+ _describe -t subcommands 'subcommand' subcommands
53
+ ;;
54
+ args)
55
+ case "${line[1]}" in
56
+ init)
57
+ _arguments \
58
+ '--endpoint=[API 端点 URL]:url' \
59
+ '--json[以 JSON 格式输出]' \
60
+ '--dry-run[预览请求]' \
61
+ '--help[显示帮助]'
62
+ ;;
63
+ show)
64
+ _arguments \
65
+ '--json[以 JSON 格式输出]' \
66
+ '--dry-run[预览请求]' \
67
+ '--help[显示帮助]'
68
+ ;;
69
+ esac
70
+ ;;
71
+ esac
72
+ }
73
+
74
+ _dm_cli_auth() {
75
+ local context state state_descr line
76
+ typeset -A opt_args
77
+
78
+ _arguments -C \
79
+ '(-): :->subcommand' \
80
+ '(-)*:: :->args'
81
+
82
+ case "$state" in
83
+ subcommand)
84
+ local -a subcommands=(
85
+ 'login:登录 DM 系统'
86
+ 'logout:退出登录'
87
+ 'status:显示登录状态'
88
+ 'switch:切换空间'
89
+ )
90
+ _describe -t subcommands 'subcommand' subcommands
91
+ ;;
92
+ args)
93
+ case "${line[1]}" in
94
+ login)
95
+ _arguments \
96
+ '--username=[用户名]:username' \
97
+ '--password=[密码]:password' \
98
+ '--json[以 JSON 格式输出]' \
99
+ '--dry-run[预览请求]' \
100
+ '--help[显示帮助]'
101
+ ;;
102
+ logout|status)
103
+ _arguments \
104
+ '--json[以 JSON 格式输出]' \
105
+ '--dry-run[预览请求]' \
106
+ '--help[显示帮助]'
107
+ ;;
108
+ switch)
109
+ _arguments \
110
+ '1:space_id' \
111
+ '--json[以 JSON 格式输出]' \
112
+ '--dry-run[预览请求]' \
113
+ '--help[显示帮助]'
114
+ ;;
115
+ esac
41
116
  ;;
42
117
  esac
43
118
  }
119
+
120
+ _dm_cli_agent() {
121
+ local context state state_descr line
122
+ typeset -A opt_args
123
+
124
+ _arguments -C \
125
+ '(-): :->subcommand' \
126
+ '(-)*:: :->args'
127
+
128
+ case "$state" in
129
+ subcommand)
130
+ local -a subcommands=(
131
+ 'start-thread:发起 AI 会话'
132
+ 'stop:停止 Agent 运行'
133
+ )
134
+ _describe -t subcommands 'subcommand' subcommands
135
+ ;;
136
+ args)
137
+ case "${line[1]}" in
138
+ start-thread)
139
+ _arguments \
140
+ '--message=[消息内容]:message' \
141
+ '--thread-id=[会话 ID]:thread_id' \
142
+ '--claw-param=[JSON 参数]:json' \
143
+ '--json[以 JSON 格式输出]' \
144
+ '--dry-run[预览请求]' \
145
+ '--help[显示帮助]'
146
+ ;;
147
+ stop)
148
+ _arguments \
149
+ '--agent-run-id=[Agent 运行 ID]:run_id' \
150
+ '--json[以 JSON 格式输出]' \
151
+ '--dry-run[预览请求]' \
152
+ '--help[显示帮助]'
153
+ ;;
154
+ esac
155
+ ;;
156
+ esac
157
+ }
158
+
159
+ _dm_cli_file() {
160
+ local context state state_descr line
161
+ typeset -A opt_args
162
+
163
+ _arguments -C \
164
+ '(-): :->subcommand' \
165
+ '(-)*:: :->args'
166
+
167
+ case "$state" in
168
+ subcommand)
169
+ local -a subcommands=(
170
+ 'upload:上传文件'
171
+ )
172
+ _describe -t subcommands 'subcommand' subcommands
173
+ ;;
174
+ args)
175
+ case "${line[1]}" in
176
+ upload)
177
+ _arguments \
178
+ '--file=[文件路径]:file:_files' \
179
+ '--name=[远程文件名]:name' \
180
+ '--feature=[功能类型]:feature' \
181
+ '--id=[文件 ID]:id' \
182
+ '--json[以 JSON 格式输出]' \
183
+ '--dry-run[预览请求]' \
184
+ '--help[显示帮助]'
185
+ ;;
186
+ esac
187
+ ;;
188
+ esac
189
+ }
190
+
191
+ _dm_cli_schema() {
192
+ _arguments \
193
+ '--pretty[格式化输出 JSON]' \
194
+ '--json[以 JSON 格式输出]' \
195
+ '--dry-run[预览请求]' \
196
+ '--help[显示帮助]'
197
+ }
198
+
199
+ _dm_cli "$@"
package/scripts/run.js CHANGED
@@ -4,6 +4,9 @@ const { spawn, execSync } = require('child_process');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
6
  const fs = require('fs');
7
+ const https = require('https');
8
+
9
+ const pkg = require('../package.json');
7
10
 
8
11
  const platform = os.platform();
9
12
  const arch = os.arch();
@@ -32,47 +35,170 @@ const isWindows = platform === 'win32';
32
35
  const binaryName = `dm-cli-${stdPlatform}-${stdArch}${isWindows ? '.exe' : ''}`;
33
36
  const binaryPath = path.join(__dirname, '..', 'bin', binaryName);
34
37
 
35
- // Ensure symlink exists on first run (for global installs)
36
- try {
37
- const npmPrefix = execSync('npm config get prefix', { encoding: 'utf-8', stdio: 'pipe' }).trim();
38
- const npmBinDir = path.join(npmPrefix, 'bin');
39
- const npmBinPath = path.join(npmBinDir, 'dm-cli');
40
- const thisFile = __filename;
41
-
42
- if (!fs.existsSync(npmBinPath) && platform !== 'win32') {
43
- try {
44
- execSync(`ln -sf "${thisFile}" "${npmBinPath}"`, { stdio: 'ignore' });
45
- } catch (e) {
46
- // Silent fail
38
+ // --- Auto-update logic ---
39
+
40
+ const UPDATE_CHECK_INTERVAL = 60 * 60 * 1000; // 1 hour
41
+ const CACHE_DIR = path.join(os.homedir(), '.dm-cli');
42
+ const CACHE_FILE = path.join(CACHE_DIR, '.update-check');
43
+
44
+ function readCache() {
45
+ try {
46
+ const data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));
47
+ return data;
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+
53
+ function writeCache(latest) {
54
+ try {
55
+ if (!fs.existsSync(CACHE_DIR)) {
56
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
47
57
  }
58
+ fs.writeFileSync(CACHE_FILE, JSON.stringify({
59
+ checkedAt: Date.now(),
60
+ latest
61
+ }));
62
+ } catch {
63
+ // silent
48
64
  }
49
- } catch (e) {
50
- // Silent fail
51
65
  }
52
66
 
53
- // Spawn the binary and forward all arguments
54
- const child = spawn(binaryPath, process.argv.slice(2), {
55
- stdio: 'inherit',
56
- windowsHide: true
57
- });
58
-
59
- child.on('error', (err) => {
60
- if (err.code === 'ENOENT') {
61
- console.error(`❌ Binary not found: ${binaryPath}`);
62
- } else {
63
- console.error(`❌ Error: ${err.message}`);
67
+ function fetchLatestVersion() {
68
+ return new Promise((resolve, reject) => {
69
+ const req = https.get('https://registry.npmjs.org/deepminer-cli/latest', { timeout: 5000 }, res => {
70
+ let data = '';
71
+ res.on('data', chunk => data += chunk);
72
+ res.on('end', () => {
73
+ try {
74
+ resolve(JSON.parse(data).version);
75
+ } catch {
76
+ reject(new Error('parse error'));
77
+ }
78
+ });
79
+ });
80
+ req.on('error', reject);
81
+ req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
82
+ });
83
+ }
84
+
85
+ function compareVersions(a, b) {
86
+ const pa = a.split('.').map(Number);
87
+ const pb = b.split('.').map(Number);
88
+ for (let i = 0; i < 3; i++) {
89
+ if ((pa[i] || 0) < (pb[i] || 0)) return -1;
90
+ if ((pa[i] || 0) > (pb[i] || 0)) return 1;
64
91
  }
65
- process.exit(1);
66
- });
92
+ return 0;
93
+ }
67
94
 
68
- process.on('SIGINT', () => {
69
- child.kill('SIGINT');
70
- });
95
+ function doUpdate() {
96
+ console.error(`⬆️ 正在自动更新 dm-cli ...`);
97
+ try {
98
+ execSync('npm install -g deepminer-cli', { stdio: 'inherit', timeout: 60000 });
99
+ console.error(`✅ dm-cli 已更新到最新版本`);
100
+ return true;
101
+ } catch {
102
+ console.error(`⚠️ 自动更新失败,继续使用当前版本`);
103
+ return false;
104
+ }
105
+ }
71
106
 
72
- process.on('SIGTERM', () => {
73
- child.kill('SIGTERM');
74
- });
107
+ async function checkAndUpdate() {
108
+ const currentVersion = pkg.version;
109
+
110
+ // Check cache first
111
+ const cache = readCache();
112
+ if (cache && (Date.now() - cache.checkedAt) < UPDATE_CHECK_INTERVAL) {
113
+ // Within cache window, use cached result
114
+ if (cache.latest && compareVersions(currentVersion, cache.latest) < 0) {
115
+ return doUpdate();
116
+ }
117
+ return false;
118
+ }
119
+
120
+ // Fetch latest version from npm
121
+ try {
122
+ const latest = await fetchLatestVersion();
123
+ writeCache(latest);
124
+ if (compareVersions(currentVersion, latest) < 0) {
125
+ return doUpdate();
126
+ }
127
+ } catch {
128
+ // Network error, skip update check
129
+ }
130
+ return false;
131
+ }
132
+
133
+ // --- Main execution ---
134
+
135
+ async function main() {
136
+ // Skip update check for version/help commands or if DM_CLI_NO_UPDATE is set
137
+ const args = process.argv.slice(2);
138
+ const skipUpdate = process.env.DM_CLI_NO_UPDATE === '1'
139
+ || args.includes('version')
140
+ || args.includes('--help')
141
+ || args.includes('-h');
142
+
143
+ if (!skipUpdate) {
144
+ const updated = await checkAndUpdate();
145
+ if (updated) {
146
+ // After update, re-exec with the new binary
147
+ const child = spawn(process.argv[0], process.argv.slice(1), {
148
+ stdio: 'inherit',
149
+ env: { ...process.env, DM_CLI_NO_UPDATE: '1' },
150
+ windowsHide: true
151
+ });
152
+ child.on('exit', code => process.exit(code || 0));
153
+ child.on('error', () => process.exit(1));
154
+ return;
155
+ }
156
+ }
157
+
158
+ // Ensure symlink exists on first run (for global installs)
159
+ try {
160
+ const npmPrefix = execSync('npm config get prefix', { encoding: 'utf-8', stdio: 'pipe' }).trim();
161
+ const npmBinDir = path.join(npmPrefix, 'bin');
162
+ const npmBinPath = path.join(npmBinDir, 'dm-cli');
163
+ const thisFile = __filename;
164
+
165
+ if (!fs.existsSync(npmBinPath) && platform !== 'win32') {
166
+ try {
167
+ execSync(`ln -sf "${thisFile}" "${npmBinPath}"`, { stdio: 'ignore' });
168
+ } catch (e) {
169
+ // Silent fail
170
+ }
171
+ }
172
+ } catch (e) {
173
+ // Silent fail
174
+ }
175
+
176
+ // Spawn the binary and forward all arguments
177
+ const child = spawn(binaryPath, args, {
178
+ stdio: 'inherit',
179
+ windowsHide: true
180
+ });
181
+
182
+ child.on('error', (err) => {
183
+ if (err.code === 'ENOENT') {
184
+ console.error(`❌ Binary not found: ${binaryPath}`);
185
+ } else {
186
+ console.error(`❌ Error: ${err.message}`);
187
+ }
188
+ process.exit(1);
189
+ });
190
+
191
+ process.on('SIGINT', () => {
192
+ child.kill('SIGINT');
193
+ });
194
+
195
+ process.on('SIGTERM', () => {
196
+ child.kill('SIGTERM');
197
+ });
198
+
199
+ child.on('exit', (code) => {
200
+ process.exit(code);
201
+ });
202
+ }
75
203
 
76
- child.on('exit', (code) => {
77
- process.exit(code);
78
- });
204
+ main();