@agentguardx/helper 0.3.89 → 0.3.91
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/lib/wizard.cjs +24 -9
- package/package.json +7 -7
package/lib/wizard.cjs
CHANGED
|
@@ -45,6 +45,9 @@ async function question(ask, label, masked = false) {
|
|
|
45
45
|
}
|
|
46
46
|
async function choose(ask, label, options, multiple = false) {
|
|
47
47
|
let cursor = 0, selected = new Set();
|
|
48
|
+
// 上一步输入残留的回车(例如粘贴地址时末尾带的换行)会在菜单刚出现时立刻到达,
|
|
49
|
+
// 不能把它当成对默认项的选择;菜单显示后短时间内的回车一律忽略。
|
|
50
|
+
const shownAt = Date.now();
|
|
48
51
|
const render = first => {
|
|
49
52
|
if (!first) process.stdout.write(`\x1b[${options.length}A`);
|
|
50
53
|
options.forEach((option, index) => process.stdout.write(`\x1b[2K\r${cursor === index ? '›' : ' '} ${multiple ? `[${selected.has(index) ? '✓' : ' '}] ` : ''}${option.label}\n`));
|
|
@@ -53,6 +56,7 @@ async function choose(ask, label, options, multiple = false) {
|
|
|
53
56
|
if (key.name === 'up') cursor = (cursor + options.length - 1) % options.length;
|
|
54
57
|
else if (key.name === 'down') cursor = (cursor + 1) % options.length;
|
|
55
58
|
else if (multiple && key.name === 'space') selected.has(cursor) ? selected.delete(cursor) : selected.add(cursor);
|
|
59
|
+
else if ((key.name === 'return' || key.name === 'enter') && Date.now() - shownAt < 300) return;
|
|
56
60
|
else if (key.name === 'return' || key.name === 'enter') { done(multiple ? [...selected].sort().map(i => options[i].value) : options[cursor].value); return; }
|
|
57
61
|
render(false);
|
|
58
62
|
});
|
|
@@ -87,19 +91,22 @@ function config(server) {
|
|
|
87
91
|
request.on('timeout', () => request.destroy()); request.on('error', () => reject(new Error('server_config_unavailable')));
|
|
88
92
|
});
|
|
89
93
|
}
|
|
90
|
-
function
|
|
94
|
+
function supportedTools() {
|
|
91
95
|
const home = os.homedir(), windows = process.platform === 'win32';
|
|
92
96
|
const command = name => (process.env.PATH || '').split(path.delimiter).some(dir => (windows ? ['', '.exe', '.cmd', '.bat'] : ['']).some(ext => {
|
|
93
97
|
try { const file = path.join(dir, name + ext); return fs.statSync(file).isFile() && (windows || (fs.accessSync(file, fs.constants.X_OK), true)); } catch { return false; }
|
|
94
98
|
}));
|
|
95
99
|
const apps = (mac, win) => process.platform === 'darwin' ? ['/Applications', path.join(home, 'Applications')].some(dir => fs.existsSync(path.join(dir, mac))) : windows && !!process.env.LOCALAPPDATA && fs.existsSync(path.join(process.env.LOCALAPPDATA, win));
|
|
96
100
|
return [
|
|
97
|
-
{ label: 'OpenCode(模型与远程 MCP)', value: 'opencode', present: command('opencode') },
|
|
98
|
-
{ label: 'OpenClaw(模型)', value: 'openclaw', present: command('openclaw') },
|
|
99
|
-
{ label: 'Cursor(远程 MCP)', value: 'cursor', present: command('cursor') || apps('Cursor.app', 'Programs/Cursor/Cursor.exe') },
|
|
100
|
-
{ label: 'Claude Desktop(MCP 桥接)', value: 'claude-desktop', present: command('claude-desktop') || apps('Claude.app', 'AnthropicClaude/Claude.exe') },
|
|
101
|
-
{ label: 'Cherry Studio(手动填写说明)', value: 'cherry-studio', present: apps('Cherry Studio.app', 'Programs/Cherry Studio/Cherry Studio.exe') },
|
|
102
|
-
]
|
|
101
|
+
{ label: 'OpenCode(模型与远程 MCP)', value: 'opencode', present: command('opencode'), install: 'npm i -g opencode-ai' },
|
|
102
|
+
{ label: 'OpenClaw(模型)', value: 'openclaw', present: command('openclaw'), install: '按 OpenClaw 官方说明安装' },
|
|
103
|
+
{ label: 'Cursor(远程 MCP)', value: 'cursor', present: command('cursor') || apps('Cursor.app', 'Programs/Cursor/Cursor.exe'), install: '从 cursor.com 下载安装' },
|
|
104
|
+
{ label: 'Claude Desktop(MCP 桥接)', value: 'claude-desktop', present: command('claude-desktop') || apps('Claude.app', 'AnthropicClaude/Claude.exe'), install: '从 claude.ai/download 下载安装' },
|
|
105
|
+
{ label: 'Cherry Studio(手动填写说明)', value: 'cherry-studio', present: apps('Cherry Studio.app', 'Programs/Cherry Studio/Cherry Studio.exe'), install: '从 cherry-ai.com 下载安装' },
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
function detectedTools() {
|
|
109
|
+
return supportedTools().filter(item => item.present);
|
|
103
110
|
}
|
|
104
111
|
async function currentServer(runtime, prefix, flagServer) {
|
|
105
112
|
// Priority --server > AGENTGUARD_SERVER > saved configuration is resolved by the Go core.
|
|
@@ -142,7 +149,10 @@ async function init(runtime, args) {
|
|
|
142
149
|
const choices = [{ label: '浏览器网页授权登录(以控制台当前登录的人授权)', value: 'browser' }, { label: '粘贴个人访问令牌', value: 'token' }];
|
|
143
150
|
let httpFlags = [];
|
|
144
151
|
if (new URL(server).protocol === 'http:') {
|
|
145
|
-
const
|
|
152
|
+
const loopback = ['127.0.0.1', 'localhost', '[::1]'].includes(new URL(server).hostname);
|
|
153
|
+
const consent = loopback ? { acknowledged: true } : await queryConsent(runtime, server, prefix);
|
|
154
|
+
// 本机回环地址不经过网络,没有中间人可读取,不再询问明文风险。
|
|
155
|
+
if (loopback) process.stdout.write('本机地址,不经过网络传输,无需明文风险确认。\n');
|
|
146
156
|
if (!consent.acknowledged) {
|
|
147
157
|
const answer = await choose(ask, 'HTTP 会以明文传输登录信息、个人令牌和业务内容,网络中间人可能读取或篡改。是否确认对该服务器继续?', [
|
|
148
158
|
{ label: '取消,不发送登录信息或令牌', value: false },
|
|
@@ -187,7 +197,12 @@ async function init(runtime, args) {
|
|
|
187
197
|
} else code = await run(runtime, [...prefix, 'login', '--server', server, ...httpFlags, '--defer-notice'], '');
|
|
188
198
|
if (code) { process.exitCode = code; return; }
|
|
189
199
|
const tools = detectedTools();
|
|
190
|
-
|
|
200
|
+
const missing = supportedTools().filter(item => !item.present);
|
|
201
|
+
if (missing.length) {
|
|
202
|
+
process.stdout.write('以下支持的工具在本机未检测到,安装后运行 npx @agentguardx/helper connect <工具名> 接入:\n');
|
|
203
|
+
for (const item of missing) process.stdout.write(` - ${item.label}:${item.install}(工具名 ${item.value})\n`);
|
|
204
|
+
}
|
|
205
|
+
if (!tools.length) process.stdout.write('本机暂未检测到支持的工具。\n');
|
|
191
206
|
else {
|
|
192
207
|
const selected = await choose(ask, '选择要接入的已检测工具', tools, true);
|
|
193
208
|
for (const tool of selected) { code = await run(runtime, [...prefix, 'connect', tool], ''); if (code) { process.exitCode = code; return; } }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentguardx/helper",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.91",
|
|
4
4
|
"description": "AgentGuard \u5458\u5de5\u63a5\u5165\u52a9\u624b",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"engines": {
|
|
@@ -19,12 +19,12 @@
|
|
|
19
19
|
"preuninstall": "node lib/preuninstall.cjs"
|
|
20
20
|
},
|
|
21
21
|
"optionalDependencies": {
|
|
22
|
-
"@agentguardx/helper-darwin-x64": "0.3.
|
|
23
|
-
"@agentguardx/helper-darwin-arm64": "0.3.
|
|
24
|
-
"@agentguardx/helper-linux-x64": "0.3.
|
|
25
|
-
"@agentguardx/helper-linux-arm64": "0.3.
|
|
26
|
-
"@agentguardx/helper-win32-x64": "0.3.
|
|
27
|
-
"@agentguardx/helper-win32-arm64": "0.3.
|
|
22
|
+
"@agentguardx/helper-darwin-x64": "0.3.91",
|
|
23
|
+
"@agentguardx/helper-darwin-arm64": "0.3.91",
|
|
24
|
+
"@agentguardx/helper-linux-x64": "0.3.91",
|
|
25
|
+
"@agentguardx/helper-linux-arm64": "0.3.91",
|
|
26
|
+
"@agentguardx/helper-win32-x64": "0.3.91",
|
|
27
|
+
"@agentguardx/helper-win32-arm64": "0.3.91"
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|