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 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
+
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.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.exe"
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",