deepminer-cli 0.1.24 → 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 +44 -6
- package/bin/dm-cli-darwin-amd64 +0 -0
- package/bin/dm-cli-darwin-arm64 +0 -0
- package/bin/dm-cli-linux-amd64 +0 -0
- package/bin/dm-cli-windows-amd64.exe +0 -0
- package/package.json +1 -1
- package/scripts/_dm-cli +193 -37
- package/scripts/run.js +162 -36
package/README.md
CHANGED
|
@@ -11,8 +11,10 @@ DeepMiner 系统的命令行工具,用于管理认证、配置和 AI 会话。
|
|
|
11
11
|
- **配置管理**: API 端点配置
|
|
12
12
|
- **安全存储**: Token 以受限权限存储在本地
|
|
13
13
|
- **文件上传**: 上传文件到 OSS,带文件大小验证
|
|
14
|
-
- **AI 会话**:
|
|
14
|
+
- **AI 会话**: 启动/继续/停止 AI 助手会话,支持自定义消息、会话追问和 claw_param 参数
|
|
15
15
|
- **JSON 输出**: 所有命令支持 `--json` 结构化输出,适合 AI agent 和脚本调用
|
|
16
|
+
- **错误提示**: 错误响应包含 `hint` 字段,提供可操作的修复建议
|
|
17
|
+
- **Dry Run**: `--dry-run` 预览 HTTP 请求而不实际执行
|
|
16
18
|
- **CLI Schema**: 内置 `schema` 命令输出机器可读的能力描述
|
|
17
19
|
- **zsh 自动补全**: 安装后自动配置
|
|
18
20
|
|
|
@@ -48,9 +50,15 @@ dm-cli auth switch <space_id>
|
|
|
48
50
|
# 4. 查看状态
|
|
49
51
|
dm-cli auth status
|
|
50
52
|
|
|
51
|
-
# 5. 启动 AI
|
|
53
|
+
# 5. 启动 AI 会话(返回 agent_run_id、thread_id)
|
|
52
54
|
dm-cli agent start-thread --message "你好"
|
|
53
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
|
+
|
|
54
62
|
# 6. 上传文件
|
|
55
63
|
dm-cli file upload --file document.pdf
|
|
56
64
|
|
|
@@ -110,7 +118,9 @@ dm-cli file upload --file <路径> --id <ID> # 上传文件(指
|
|
|
110
118
|
```bash
|
|
111
119
|
dm-cli agent start-thread # 使用默认消息 "你好"
|
|
112
120
|
dm-cli agent start-thread --message <消息> # 自定义消息
|
|
113
|
-
dm-cli agent start-thread --message <消息> --
|
|
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
|
|
114
124
|
```
|
|
115
125
|
|
|
116
126
|
#### claw_param 参数说明
|
|
@@ -154,18 +164,46 @@ dm-cli --help # 显示帮助信息
|
|
|
154
164
|
| Flag | 说明 |
|
|
155
165
|
|------|------|
|
|
156
166
|
| `--json` | 以 JSON 格式输出结果 |
|
|
167
|
+
| `--dry-run` | 预览 HTTP 请求而不实际执行 |
|
|
157
168
|
| `--help` | 显示帮助信息 |
|
|
158
169
|
|
|
159
|
-
JSON
|
|
170
|
+
### JSON 输出格式
|
|
171
|
+
|
|
172
|
+
成功:
|
|
160
173
|
```json
|
|
161
174
|
{"ok": true, "data": {...}}
|
|
162
175
|
```
|
|
163
176
|
|
|
164
|
-
|
|
177
|
+
错误(含修复建议):
|
|
165
178
|
```json
|
|
166
|
-
{"ok": false, "error": {"type": "auth", "message": "未登陆"}}
|
|
179
|
+
{"ok": false, "error": {"type": "auth", "message": "未登陆", "hint": "运行 'dm-cli auth login --username <user> --password <pass>' 登录"}}
|
|
167
180
|
```
|
|
168
181
|
|
|
182
|
+
`hint` 字段提供可操作的修复建议,AI agent 可直接据此自动恢复。
|
|
183
|
+
|
|
184
|
+
### Dry Run 模式
|
|
185
|
+
|
|
186
|
+
使用 `--dry-run` 预览请求而不实际执行,适合调试和 AI agent 安全验证:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
dm-cli --dry-run auth login --username user --password pass
|
|
190
|
+
# [DRY RUN] POST https://api.example.com/api/auth/authentication/login
|
|
191
|
+
# Headers:
|
|
192
|
+
# Content-Type: application/json
|
|
193
|
+
# Body:
|
|
194
|
+
# {"username": "user", "password": "pass"}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
JSON 模式:
|
|
198
|
+
```bash
|
|
199
|
+
dm-cli --dry-run --json agent start-thread --message "你好"
|
|
200
|
+
```
|
|
201
|
+
```json
|
|
202
|
+
{"ok": true, "dry_run": true, "data": {"method": "POST", "url": "...", "headers": {...}, "body": {...}}}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
只读命令(`config show`、`auth status`、`version`、`schema`)和纯本地操作(`config init`、`auth logout`)不受 `--dry-run` 影响,正常执行。
|
|
206
|
+
|
|
169
207
|
## 文件说明
|
|
170
208
|
|
|
171
209
|
### 配置文件:`~/.dm-cli/config.json`
|
package/bin/dm-cli-darwin-amd64
CHANGED
|
Binary file
|
package/bin/dm-cli-darwin-arm64
CHANGED
|
Binary file
|
package/bin/dm-cli-linux-amd64
CHANGED
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/scripts/_dm-cli
CHANGED
|
@@ -1,43 +1,199 @@
|
|
|
1
1
|
#compdef dm-cli
|
|
2
2
|
|
|
3
3
|
_dm_cli() {
|
|
4
|
-
local
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
66
|
-
}
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
67
94
|
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
73
|
-
|
|
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
|
-
|
|
77
|
-
process.exit(code);
|
|
78
|
-
});
|
|
204
|
+
main();
|