ace-tool-windows 0.1.1 → 0.1.3
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 +2 -1
- package/bin/ace-tool-win.exe +0 -0
- package/bin/ace-tool-win.js +237 -0
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -102,7 +102,7 @@ ace-tool-win --base-url <URL> --token <TOKEN> [--enable-log]
|
|
|
102
102
|
- `--enable-log` 可选,写入 `.ace-tool/ace-tool.log`
|
|
103
103
|
|
|
104
104
|
> 提示:`enhance_prompt` 会弹 Win32 窗口确认;如果只想后台检索,可只调用 `search_context`。
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
## 从源码运行
|
|
107
107
|
|
|
108
108
|
```powershell
|
|
@@ -257,3 +257,4 @@ Apache-2.0
|
|
|
257
257
|
|
|
258
258
|
|
|
259
259
|
|
|
260
|
+
|
package/bin/ace-tool-win.exe
CHANGED
|
Binary file
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { spawn } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const DEFAULT_PROTOCOL_VERSION = '2024-11-05';
|
|
9
|
+
const SUPPORTED_PROTOCOL_VERSIONS = new Set([
|
|
10
|
+
'DRAFT-2026-v1',
|
|
11
|
+
'2025-06-18',
|
|
12
|
+
'2025-03-26',
|
|
13
|
+
'2024-11-05',
|
|
14
|
+
'2024-10-07',
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
function logError(message) {
|
|
18
|
+
process.stderr.write(`${message}\n`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const backendExe = process.env.ACE_TOOL_WIN_EXE || path.join(__dirname, 'ace-tool-win.exe');
|
|
22
|
+
if (!fs.existsSync(backendExe)) {
|
|
23
|
+
logError(`ace-tool-win backend not found: ${backendExe}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const backendArgs = process.argv.slice(2);
|
|
28
|
+
const backend = spawn(backendExe, backendArgs, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
29
|
+
backend.stderr.on('data', (chunk) => process.stderr.write(chunk));
|
|
30
|
+
|
|
31
|
+
let backendClosed = false;
|
|
32
|
+
backend.on('exit', (code) => {
|
|
33
|
+
backendClosed = true;
|
|
34
|
+
logError(`ace-tool-win backend exited (${code ?? 'unknown'})`);
|
|
35
|
+
process.exit(code ?? 1);
|
|
36
|
+
});
|
|
37
|
+
backend.on('error', (error) => {
|
|
38
|
+
backendClosed = true;
|
|
39
|
+
logError(`ace-tool-win backend failed: ${error.message}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
let backendRequestId = 1;
|
|
44
|
+
const backendPending = new Map();
|
|
45
|
+
|
|
46
|
+
function sendBackend(message) {
|
|
47
|
+
if (backendClosed) {
|
|
48
|
+
return Promise.reject(new Error('Backend closed'));
|
|
49
|
+
}
|
|
50
|
+
const payload = JSON.stringify(message);
|
|
51
|
+
const header = `Content-Length: ${Buffer.byteLength(payload)}\r\n\r\n`;
|
|
52
|
+
backend.stdin.write(header + payload);
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
backendPending.set(message.id, { resolve, reject });
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createParser(onMessage) {
|
|
59
|
+
let buffer = Buffer.alloc(0);
|
|
60
|
+
return (chunk) => {
|
|
61
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
62
|
+
while (true) {
|
|
63
|
+
const headerEnd = buffer.indexOf('\r\n\r\n');
|
|
64
|
+
if (headerEnd === -1) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const headerText = buffer.slice(0, headerEnd).toString('utf8');
|
|
68
|
+
const match = headerText.match(/content-length:\s*(\d+)/i);
|
|
69
|
+
if (!match) {
|
|
70
|
+
buffer = buffer.slice(headerEnd + 4);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const contentLength = Number(match[1]);
|
|
74
|
+
const totalLength = headerEnd + 4 + contentLength;
|
|
75
|
+
if (buffer.length < totalLength) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const body = buffer.slice(headerEnd + 4, totalLength).toString('utf8');
|
|
79
|
+
buffer = buffer.slice(totalLength);
|
|
80
|
+
try {
|
|
81
|
+
const message = JSON.parse(body);
|
|
82
|
+
onMessage(message);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
logError(`Failed to parse backend message: ${error.message}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
backend.stdout.on('data', createParser((message) => {
|
|
91
|
+
if (!message || message.id === undefined || message.id === null) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const pending = backendPending.get(message.id);
|
|
95
|
+
if (!pending) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
backendPending.delete(message.id);
|
|
99
|
+
if (message.error) {
|
|
100
|
+
pending.reject(message.error);
|
|
101
|
+
} else {
|
|
102
|
+
pending.resolve(message);
|
|
103
|
+
}
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
const backendReady = (async () => {
|
|
107
|
+
const initMessage = {
|
|
108
|
+
jsonrpc: '2.0',
|
|
109
|
+
id: backendRequestId++,
|
|
110
|
+
method: 'initialize',
|
|
111
|
+
params: {
|
|
112
|
+
protocolVersion: DEFAULT_PROTOCOL_VERSION,
|
|
113
|
+
capabilities: {},
|
|
114
|
+
clientInfo: { name: 'ace-tool-win-proxy', version: '0.1.3' },
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
await sendBackend(initMessage);
|
|
119
|
+
})().catch((error) => {
|
|
120
|
+
logError(`Backend initialize failed: ${error?.message || error}`);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
function sendRouter(message) {
|
|
125
|
+
const payload = JSON.stringify(message);
|
|
126
|
+
const header = `Content-Length: ${Buffer.byteLength(payload)}\r\n\r\n`;
|
|
127
|
+
process.stdout.write(header + payload);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function normalizeMethod(method) {
|
|
131
|
+
const value = (method || '').toLowerCase();
|
|
132
|
+
if (value === 'tools.list' || value === 'tools/list' || value === 'list_tools' || value === 'listtools') {
|
|
133
|
+
return 'tools/list';
|
|
134
|
+
}
|
|
135
|
+
if (value === 'tools.call' || value === 'tools/call' || value === 'call_tool' || value === 'calltool') {
|
|
136
|
+
return 'tools/call';
|
|
137
|
+
}
|
|
138
|
+
if (value === 'initialize') {
|
|
139
|
+
return 'initialize';
|
|
140
|
+
}
|
|
141
|
+
if (value === 'notifications/initialized' || value === 'initialized') {
|
|
142
|
+
return 'initialized';
|
|
143
|
+
}
|
|
144
|
+
return method || '';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
process.stdin.on('data', createParser(async (message) => {
|
|
148
|
+
if (!message || typeof message !== 'object') {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const method = normalizeMethod(message.method);
|
|
153
|
+
const id = message.id;
|
|
154
|
+
|
|
155
|
+
if (method === 'initialized') {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (method === 'initialize') {
|
|
160
|
+
const requested = message.params?.protocolVersion;
|
|
161
|
+
const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.has(requested) ? requested : DEFAULT_PROTOCOL_VERSION;
|
|
162
|
+
sendRouter({
|
|
163
|
+
jsonrpc: '2.0',
|
|
164
|
+
id,
|
|
165
|
+
result: {
|
|
166
|
+
protocolVersion,
|
|
167
|
+
capabilities: { tools: {}, logging: {} },
|
|
168
|
+
serverInfo: { name: 'ace-tool-windows', version: '0.1.3' },
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (method === 'tools/list') {
|
|
175
|
+
await backendReady;
|
|
176
|
+
const backendMessage = {
|
|
177
|
+
jsonrpc: '2.0',
|
|
178
|
+
id: backendRequestId++,
|
|
179
|
+
method: 'tools/list',
|
|
180
|
+
params: message.params || {},
|
|
181
|
+
};
|
|
182
|
+
try {
|
|
183
|
+
const response = await sendBackend(backendMessage);
|
|
184
|
+
if (response.error) {
|
|
185
|
+
sendRouter({ jsonrpc: '2.0', id, error: response.error });
|
|
186
|
+
} else {
|
|
187
|
+
sendRouter({ jsonrpc: '2.0', id, result: response.result });
|
|
188
|
+
}
|
|
189
|
+
} catch (error) {
|
|
190
|
+
sendRouter({
|
|
191
|
+
jsonrpc: '2.0',
|
|
192
|
+
id,
|
|
193
|
+
error: { code: -32000, message: error?.message || 'Backend error' },
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (method === 'tools/call') {
|
|
200
|
+
await backendReady;
|
|
201
|
+
const backendMessage = {
|
|
202
|
+
jsonrpc: '2.0',
|
|
203
|
+
id: backendRequestId++,
|
|
204
|
+
method: 'tools/call',
|
|
205
|
+
params: message.params || {},
|
|
206
|
+
};
|
|
207
|
+
try {
|
|
208
|
+
const response = await sendBackend(backendMessage);
|
|
209
|
+
if (response.error) {
|
|
210
|
+
sendRouter({ jsonrpc: '2.0', id, error: response.error });
|
|
211
|
+
} else {
|
|
212
|
+
sendRouter({ jsonrpc: '2.0', id, result: response.result });
|
|
213
|
+
}
|
|
214
|
+
} catch (error) {
|
|
215
|
+
sendRouter({
|
|
216
|
+
jsonrpc: '2.0',
|
|
217
|
+
id,
|
|
218
|
+
error: { code: -32000, message: error?.message || 'Backend error' },
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (id !== undefined && id !== null) {
|
|
225
|
+
sendRouter({
|
|
226
|
+
jsonrpc: '2.0',
|
|
227
|
+
id,
|
|
228
|
+
error: { code: -32601, message: 'Method not found' },
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}));
|
|
232
|
+
|
|
233
|
+
process.stdin.on('end', () => {
|
|
234
|
+
if (!backendClosed) {
|
|
235
|
+
backend.kill();
|
|
236
|
+
}
|
|
237
|
+
});
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ace-tool-windows",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "ACE MCP server for Windows (Win32)",
|
|
5
5
|
"bin": {
|
|
6
|
-
"ace-tool-win": "bin/ace-tool-win.
|
|
6
|
+
"ace-tool-win": "bin/ace-tool-win.js"
|
|
7
7
|
},
|
|
8
8
|
"os": [
|
|
9
9
|
"win32"
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"x64"
|
|
13
13
|
],
|
|
14
14
|
"files": [
|
|
15
|
+
"bin/ace-tool-win.js",
|
|
15
16
|
"bin/ace-tool-win.exe",
|
|
16
17
|
"README.md",
|
|
17
18
|
"LICENSE"
|
|
@@ -19,7 +20,11 @@
|
|
|
19
20
|
"license": "Apache-2.0",
|
|
20
21
|
"scripts": {
|
|
21
22
|
"build:bin": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-bin.ps1",
|
|
22
|
-
"pack:local": "npm run build:bin && npm pack"
|
|
23
|
+
"pack:local": "npm run build:bin && npm pack",
|
|
24
|
+
"publish:public": "npm run build:bin && npm publish --access public"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
23
28
|
},
|
|
24
29
|
"repository": {
|
|
25
30
|
"type": "git",
|