ace-tool-windows 0.1.3 → 0.1.4

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
@@ -1,260 +1,248 @@
1
- # ace-tool-windows
2
-
3
- Rust + Win32 的 MCP Server(stdio),提供 `search_context` 与 `enhance_prompt`,并用原生 Win32 GUI 替代浏览器交互。
4
-
5
- > 原项目:https://github.com/eastxiaodong/ace-tool
6
-
7
- ## 目录
8
-
9
- - 项目简介
10
- - 功能特性
11
- - 环境要求
1
+ # ace-tool-windows
2
+
3
+ Rust + Win32 的 MCP Server(stdio),提供 `search_context` 与 `enhance_prompt`,并用原生 Win32 GUI 替代浏览器交互。
4
+
5
+ > 原项目:https://github.com/eastxiaodong/ace-tool
6
+
7
+ ## 目录
8
+
9
+ - 项目简介
10
+ - 功能特性
11
+ - 环境要求
12
12
  - 快速开始
13
13
  - 配置为 MCP Server
14
- - 从源码运行
15
- - MCP 工具说明
16
- - 配置说明
17
- - npm 打包与发布
18
- - 项目结构
19
- - 对齐清单(Node 版本)
20
- - 测试
21
- - License
22
- - 致谢
23
-
24
- ## 项目简介
25
-
26
- 本仓库是 ace-tool 的 Rust + Win32 重写版本,目标与 Node 版本功能 1:1 对齐,同时保持 MCP stdio 兼容,供 Codex 客户端调用。
27
-
28
- ## 功能特性
29
-
30
- - MCP JSON-RPC over stdio,支持工具列举与调用
31
- - `search_context`:索引 + 检索代码库上下文
32
- - `enhance_prompt`:调用远端增强服务,支持中文/英文自动判断
33
- - Win32 GUI 交互窗口,提供继续增强 / 使用原始 / 结束对话
34
- - 本地索引与日志输出(`.ace-tool/`)
35
-
36
- ## 环境要求
37
-
38
- - Windows 10/11(Win32 GUI)
39
- - Rust 工具链(建议稳定版)
40
- - Node.js + npm(用于发布到 npm)
41
-
42
- ## 快速开始
43
-
44
- 全局安装后使用:
45
-
46
- ```powershell
47
- npm i -g ace-tool-windows
48
- ace-tool-win --base-url <URL> --token <TOKEN> [--enable-log]
49
- ```
50
-
51
- ## 配置为 MCP Server
52
-
53
- 本项目是 MCP stdio Server。配置时只需要声明 command + args,不需要额外端口配置。
54
-
55
- 说明:不同 MCP 客户端字段名可能是 `mcpServers` 或 `servers`,以客户端文档为准。下面给出两种常见 JSON 格式。
56
-
57
- ### 方式一:mcpServers 格式(常见)
58
-
59
- 使用 npm 全局命令:
60
-
61
- ```json
62
- {
63
- "mcpServers": {
64
- "ace-tool-windows": {
65
- "command": "ace-tool-win",
66
- "args": ["--base-url", "<URL>", "--token", "<TOKEN>", "--enable-log"]
67
- }
68
- }
69
- }
70
- ```
71
-
72
- 使用本地 exe 路径:
73
-
74
- ```json
75
- {
76
- "mcpServers": {
77
- "ace-tool-windows": {
78
- "command": "C:\\\\path\\\\to\\\\ace-tool-win.exe",
79
- "args": ["--base-url", "<URL>", "--token", "<TOKEN>"]
80
- }
81
- }
82
- }
83
- ```
84
-
85
- ### 方式二:JSON 模式(servers 格式)
86
-
87
- ```json
88
- {
89
- "servers": {
90
- "ace-tool-windows": {
91
- "command": "ace-tool-win",
92
- "args": ["--base-url", "<URL>", "--token", "<TOKEN>"]
93
- }
94
- }
95
- }
96
- ```
97
-
98
- ### 参数说明
99
-
100
- - `--base-url` 必填,服务地址;未写协议会自动补 `https://`
101
- - `--token` 必填,ACE 服务 Token
102
- - `--enable-log` 可选,写入 `.ace-tool/ace-tool.log`
103
-
104
- > 提示:`enhance_prompt` 会弹 Win32 窗口确认;如果只想后台检索,可只调用 `search_context`。
105
-
106
- ## 从源码运行
107
-
108
- ```powershell
109
- # 在仓库根目录
110
- cargo run -- --base-url <URL> --token <TOKEN> [--enable-log]
111
- ```
112
-
113
- ## MCP 工具说明
114
-
115
- ### search_context
116
-
117
- - 传入项目根路径与检索 query
118
- - 自动进行索引(`.ace-tool/index.json`)
119
- - 调用 `/agents/codebase-retrieval` 返回 formatted_retrieval
120
-
121
- ### enhance_prompt
122
-
123
- - 调用 `/prompt-enhancer`
124
- - 语言检测:中文输入 -> 中文输出;英文输入 -> 英文输出
125
- - 工具名映射:`codebase-retrieval` -> `search_context`
126
- - 8 分钟超时回退到原始 prompt
127
-
128
- ## 配置说明
129
-
130
- 必填参数:
131
- - `--base-url`
132
- - `--token`
133
-
134
- 可选参数:
135
- - `--enable-log`(写入 `.ace-tool/ace-tool.log`)
136
-
137
- ### 认证 URL 与 Token 获取
138
-
139
- 认证服务的 URL 与 Token 获取方式以原项目说明为准,建议先阅读原项目文档与相关讨论:
140
-
141
- - 原项目仓库:https://github.com/eastxiaodong/ace-tool
142
- - Issue #6: baseUrl 和 Token 有办法获取吗?
143
-
144
- 注意:Issue #6 中有用户提到 baseUrl 直接指向 augmentcode.com,但未给出 Token 的官方获取流程,请以服务提供方的最新说明为准。
145
-
146
- ## npm 打包与发布
147
-
148
- 构建 + 拷贝 exe:
149
-
150
- ```powershell
151
- npm run build:bin
152
- ```
153
-
154
- 本地打包验证:
155
-
156
- ```powershell
157
- npm run pack:local
158
- ```
159
-
160
- 发布到 npm(首次需登录):
161
-
162
- ```powershell
163
- npm publish --access public
164
- ```
165
-
166
- ## 项目结构
167
-
168
- ```
169
- ace-tool-windows/
170
- - Cargo.toml
171
- - package.json
172
- - README.md
173
- - src/
174
- - main.rs
175
- - mcp/
176
- - index/
177
- - enhancer/
178
- - ui/
179
- - utils/
180
- - tests/
181
- ```
182
-
183
- ## 对齐清单(Node 版本)
184
-
185
- ### MCP 协议
186
- - [ ] 基于 stdio 的 JSON-RPC
187
- - [ ] ListTools 返回 search_context + enhance_prompt schema
188
- - [ ] CallTool 按名称分发并返回 content[].text
189
- - [ ] MCP logging 通道推送(level + data)
190
-
191
- ### CLI / 配置
192
- - [ ] 必填参数:--base-url、--token
193
- - [ ] 可选参数:--enable-log
194
- - [ ] base_url 自动规范化(必须 https,去掉末尾 /)
195
-
196
- ### 项目数据
197
- - [ ] 项目根目录创建 .ace-tool/
198
- - [ ] index.json 写入 .ace-tool/
199
- - [ ] --enable-log 时写入 ace-tool.log
200
- - [ ] .ace-tool 自动加入 .gitignore
201
-
202
- ### search_context 工具
203
- - [ ] project_root_path / query 输入校验
204
- - [ ] 路径统一为正斜杠
205
- - [ ] 目录存在性与类型检查
206
- - [ ] 检索前自动索引
207
- - [ ] POST {baseUrl}/agents/codebase-retrieval
208
- - [ ] 返回 formatted_retrieval 或友好错误信息
209
-
210
- ### 索引行为
211
- - [ ] 默认文本后缀与排除规则与 Node 一致
212
- - [ ] 读取编码兜底(utf-8、gbk、gb2312、latin1)
213
- - [ ] 二进制内容检测并跳过
214
- - [ ] 清洗控制字符
215
- - [ ] 按 maxLinesPerBlob 分片(默认 800)
216
- - [ ] Blob 名称 hash:SHA-256(path + content)
217
- - [ ] MAX_BLOB_SIZE:单 blob 500KB
218
- - [ ] MAX_BATCH_SIZE:单批 5MB
219
- - [ ] 基于 index.json 的增量索引
220
- - [ ] 按 blob 数量自适应上传策略(batch size + 并发)
221
- - [ ] 指数退避重试 + 友好错误映射
222
-
223
- ### enhance_prompt 工具
224
- - [ ] POST {baseUrl}/prompt-enhancer(payload 含 nodes/chat_history/blobs)
225
- - [ ] 语言检测(中文输入 -> 中文输出;英文输入 -> 英文输出)
226
- - [ ] 工具名映射:codebase-retrieval -> search_context
227
- - [ ] 8 分钟超时并回退到原始 prompt
228
-
229
- ### Win32 UI(替代浏览器 UI)
230
- - [ ] 四个动作:发送增强 / 使用原始 / 继续增强 / 结束对话
231
- - [ ] Session 状态:pending / completed / timeout
232
- - [ ] UI 与增强流程通过通道协作
233
-
234
- ### 错误提示
235
- - [ ] Token 无效(401)/ 访问被拒绝(403)
236
- - [ ] SSL 错误 / 非 https / DNS / 超时 / 连接被拒绝
237
- - [ ] 路径不存在 / 非目录 / 空索引
238
-
239
- ### 日志格式
240
- - [ ] MCP logging 推送(level + data)
241
- - [ ] 文件日志行格式:"YYYY-MM-DD HH:MM:SS | LEVEL | message"
242
- - [ ] 新日志流写入 Session 分隔符
243
-
244
- ## 测试
245
-
246
- ```powershell
247
- cargo test
248
- ```
249
-
250
- ## License
251
-
252
- Apache-2.0
253
-
254
- ## 致谢
255
-
256
- - 原项目:ace-tool(https://github.com/eastxiaodong/ace-tool)
14
+ - 从源码运行
15
+ - MCP 工具说明
16
+ - 配置说明
17
+ - npm 打包与发布
18
+ - 项目结构
19
+ - 对齐清单(Node 版本)
20
+ - 测试
21
+ - License
22
+ - 致谢
23
+
24
+ ## 项目简介
25
+
26
+ 本仓库是 ace-tool 的 Rust + Win32 重写版本,目标与 Node 版本功能 1:1 对齐,同时保持 MCP stdio 兼容,供 Codex 客户端调用。
27
+
28
+ ## 功能特性
29
+
30
+ - MCP JSON-RPC over stdio,支持工具列举与调用
31
+ - `search_context`:索引 + 检索代码库上下文
32
+ - `enhance_prompt`:调用远端增强服务,支持中文/英文自动判断
33
+ - Win32 GUI 交互窗口,提供继续增强 / 使用原始 / 结束对话
34
+ - 本地索引与日志输出(`.ace-tool/`)
35
+
36
+ ## 环境要求
37
+
38
+ - Windows 10/11(Win32 GUI)
39
+ - Rust 工具链(建议稳定版)
40
+ - Node.js + npm(用于发布到 npm)
41
+
42
+ ## 快速开始
43
+
44
+ 全局安装后使用:
45
+
46
+ ```powershell
47
+ npm i -g ace-tool-windows
48
+ ace-tool-win --base-url <URL> --token <TOKEN> [--enable-log]
49
+ ```
50
+
51
+ ## 配置为 MCP Server
52
+
53
+ 本项目是 MCP stdio Server。配置时只需要声明 command + args,不需要额外端口配置。
54
+
55
+ 说明:不同 MCP 客户端字段名可能是 `mcpServers` 或 `servers`,以客户端文档为准。下面给出两种常见 JSON 格式。
56
+
57
+ ### 方式一:mcpServers 格式(常见)
58
+
59
+ 使用 npm 全局命令:
60
+
61
+ ```json
62
+ {
63
+ "mcpServers": {
64
+ "ace-tool-windows": {
65
+ "command": "ace-tool-win",
66
+ "args": ["--base-url", "<URL>", "--token", "<TOKEN>", "--enable-log"]
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ 使用本地 exe 路径:
73
+
74
+ ```json
75
+ {
76
+ "mcpServers": {
77
+ "ace-tool-windows": {
78
+ "command": "C:\\\\path\\\\to\\\\ace-tool-win.exe",
79
+ "args": ["--base-url", "<URL>", "--token", "<TOKEN>"]
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ ### 方式二:JSON 模式(servers 格式)
86
+
87
+ ```json
88
+ {
89
+ "servers": {
90
+ "ace-tool-windows": {
91
+ "command": "ace-tool-win",
92
+ "args": ["--base-url", "<URL>", "--token", "<TOKEN>"]
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### 参数说明
99
+
100
+ - `--base-url` 必填,服务地址;未写协议会自动补 `https://`
101
+ - `--token` 必填,ACE 服务 Token
102
+ - `--enable-log` 可选,写入 `.ace-tool/ace-tool.log`
103
+
104
+ > 提示:`enhance_prompt` 会弹 Win32 窗口确认;如果只想后台检索,可只调用 `search_context`。
105
+ ## 从源码运行
106
+
107
+ ```powershell
108
+ # 在仓库根目录
109
+ cargo run -- --base-url <URL> --token <TOKEN> [--enable-log]
110
+ ```
111
+
112
+ ## MCP 工具说明
113
+
114
+ ### search_context
257
115
 
116
+ - 传入项目根路径与检索 query
117
+ - 自动进行索引(`.ace-tool/index.json`)
118
+ - 调用 `/agents/codebase-retrieval` 返回 formatted_retrieval
258
119
 
120
+ ### enhance_prompt
121
+
122
+ - 调用 `/prompt-enhancer`
123
+ - 语言检测:中文输入 -> 中文输出;英文输入 -> 英文输出
124
+ - 工具名映射:`codebase-retrieval` -> `search_context`
125
+ - 8 分钟超时回退到原始 prompt
126
+
127
+ ## 配置说明
128
+
129
+ 必填参数:
130
+ - `--base-url`
131
+ - `--token`
132
+
133
+ 可选参数:
134
+ - `--enable-log`(写入 `.ace-tool/ace-tool.log`)
135
+
136
+ ## npm 打包与发布
137
+
138
+ 构建 + 拷贝 exe:
139
+
140
+ ```powershell
141
+ npm run build:bin
142
+ ```
143
+
144
+ 本地打包验证:
145
+
146
+ ```powershell
147
+ npm run pack:local
148
+ ```
149
+
150
+ 发布到 npm(首次需登录):
151
+
152
+ ```powershell
153
+ npm publish --access public
154
+ ```
155
+
156
+ ## 项目结构
157
+
158
+ ```
159
+ ace-tool-windows/
160
+ - Cargo.toml
161
+ - package.json
162
+ - README.md
163
+ - src/
164
+ - main.rs
165
+ - mcp/
166
+ - index/
167
+ - enhancer/
168
+ - ui/
169
+ - utils/
170
+ - tests/
171
+ ```
172
+
173
+ ## 对齐清单(Node 版本)
174
+
175
+ ### MCP 协议
176
+ - [ ] 基于 stdio 的 JSON-RPC
177
+ - [ ] ListTools 返回 search_context + enhance_prompt schema
178
+ - [ ] CallTool 按名称分发并返回 content[].text
179
+ - [ ] MCP logging 通道推送(level + data)
180
+
181
+ ### CLI / 配置
182
+ - [ ] 必填参数:--base-url、--token
183
+ - [ ] 可选参数:--enable-log
184
+ - [ ] base_url 自动规范化(必须 https,去掉末尾 /)
185
+
186
+ ### 项目数据
187
+ - [ ] 项目根目录创建 .ace-tool/
188
+ - [ ] index.json 写入 .ace-tool/
189
+ - [ ] --enable-log 时写入 ace-tool.log
190
+ - [ ] .ace-tool 自动加入 .gitignore
191
+
192
+ ### search_context 工具
193
+ - [ ] project_root_path / query 输入校验
194
+ - [ ] 路径统一为正斜杠
195
+ - [ ] 目录存在性与类型检查
196
+ - [ ] 检索前自动索引
197
+ - [ ] POST {baseUrl}/agents/codebase-retrieval
198
+ - [ ] 返回 formatted_retrieval 或友好错误信息
199
+
200
+ ### 索引行为
201
+ - [ ] 默认文本后缀与排除规则与 Node 一致
202
+ - [ ] 读取编码兜底(utf-8、gbk、gb2312、latin1)
203
+ - [ ] 二进制内容检测并跳过
204
+ - [ ] 清洗控制字符
205
+ - [ ] 按 maxLinesPerBlob 分片(默认 800)
206
+ - [ ] Blob 名称 hash:SHA-256(path + content)
207
+ - [ ] MAX_BLOB_SIZE:单 blob 500KB
208
+ - [ ] MAX_BATCH_SIZE:单批 5MB
209
+ - [ ] 基于 index.json 的增量索引
210
+ - [ ] 按 blob 数量自适应上传策略(batch size + 并发)
211
+ - [ ] 指数退避重试 + 友好错误映射
212
+
213
+ ### enhance_prompt 工具
214
+ - [ ] POST {baseUrl}/prompt-enhancer(payload 含 nodes/chat_history/blobs)
215
+ - [ ] 语言检测(中文输入 -> 中文输出;英文输入 -> 英文输出)
216
+ - [ ] 工具名映射:codebase-retrieval -> search_context
217
+ - [ ] 8 分钟超时并回退到原始 prompt
218
+
219
+ ### Win32 UI(替代浏览器 UI)
220
+ - [ ] 四个动作:发送增强 / 使用原始 / 继续增强 / 结束对话
221
+ - [ ] Session 状态:pending / completed / timeout
222
+ - [ ] UI 与增强流程通过通道协作
223
+
224
+ ### 错误提示
225
+ - [ ] Token 无效(401)/ 访问被拒绝(403)
226
+ - [ ] SSL 错误 / 非 https / DNS / 超时 / 连接被拒绝
227
+ - [ ] 路径不存在 / 非目录 / 空索引
228
+
229
+ ### 日志格式
230
+ - [ ] MCP logging 推送(level + data)
231
+ - [ ] 文件日志行格式:"YYYY-MM-DD HH:MM:SS | LEVEL | message"
232
+ - [ ] 新日志流写入 Session 分隔符
233
+
234
+ ## 测试
235
+
236
+ ```powershell
237
+ cargo test
238
+ ```
239
+
240
+ ## License
241
+
242
+ Apache-2.0
243
+
244
+ ## 致谢
245
+
246
+ - 原项目:ace-tool(https://github.com/eastxiaodong/ace-tool)
259
247
 
260
248
 
Binary file
package/package.json CHANGED
@@ -1,43 +1,39 @@
1
- {
2
- "name": "ace-tool-windows",
3
- "version": "0.1.3",
4
- "description": "ACE MCP server for Windows (Win32)",
5
- "bin": {
6
- "ace-tool-win": "bin/ace-tool-win.js"
7
- },
8
- "os": [
9
- "win32"
10
- ],
11
- "cpu": [
12
- "x64"
13
- ],
14
- "files": [
15
- "bin/ace-tool-win.js",
16
- "bin/ace-tool-win.exe",
17
- "README.md",
18
- "LICENSE"
19
- ],
20
- "license": "Apache-2.0",
21
- "scripts": {
22
- "build:bin": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-bin.ps1",
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"
28
- },
29
- "repository": {
30
- "type": "git",
31
- "url": "git+https://github.com/doudouHubs/ace-tool-windows.git"
32
- },
33
- "bugs": {
34
- "url": "https://github.com/doudouHubs/ace-tool-windows/issues"
35
- },
36
- "homepage": "https://github.com/doudouHubs/ace-tool-windows#readme",
37
- "keywords": [
38
- "mcp",
39
- "ace-tool",
40
- "win32",
41
- "windows"
42
- ]
43
- }
1
+ {
2
+ "name": "ace-tool-windows",
3
+ "version": "0.1.4",
4
+ "description": "ACE MCP server for Windows (Win32)",
5
+ "bin": {
6
+ "ace-tool-win": "bin/ace-tool-win.exe"
7
+ },
8
+ "os": [
9
+ "win32"
10
+ ],
11
+ "cpu": [
12
+ "x64"
13
+ ],
14
+ "files": [
15
+ "bin/ace-tool-win.exe",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "license": "Apache-2.0",
20
+ "scripts": {
21
+ "release": "cargo build --release",
22
+ "build:bin": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-bin.ps1",
23
+ "pack:local": "npm run build:bin && npm pack"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/doudouHubs/ace-tool-windows.git"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/doudouHubs/ace-tool-windows/issues"
31
+ },
32
+ "homepage": "https://github.com/doudouHubs/ace-tool-windows#readme",
33
+ "keywords": [
34
+ "mcp",
35
+ "ace-tool",
36
+ "win32",
37
+ "windows"
38
+ ]
39
+ }
@@ -1,237 +0,0 @@
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
- });