@harmonyos-arkts/opencode-acp 0.0.3 → 0.0.6

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.
@@ -27,15 +27,15 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
27
27
 
28
28
  ## 暴露的 MCP 操作
29
29
 
30
- | extMethod 名 | 对应 SDK 调用 | 说明 |
31
- |---|---|---|
32
- | `mcp/status` | `sdk.mcp.status()` | 获取所有 MCP 服务器状态 |
33
- | `mcp/add` | `sdk.mcp.add()` | 添加 MCP 服务器 |
34
- | `mcp/connect` | `sdk.mcp.connect()` | 连接已禁用的服务器 |
35
- | `mcp/disconnect` | `sdk.mcp.disconnect()` | 断开服务器 |
36
- | `mcp/auth/start` | `sdk.mcp.auth.start()` | 启动 OAuth 认证 |
37
- | `mcp/auth/callback` | `sdk.mcp.auth.callback()` | 完成 OAuth 认证 |
38
- | `mcp/auth/remove` | `sdk.mcp.auth.remove()` | 删除 OAuth 凭据 |
30
+ | extMethod 名 | 对应 SDK 调用 | 说明 |
31
+ | ------------------- | ------------------------- | ----------------------- |
32
+ | `mcp/status` | `sdk.mcp.status()` | 获取所有 MCP 服务器状态 |
33
+ | `mcp/add` | `sdk.mcp.add()` | 添加 MCP 服务器 |
34
+ | `mcp/connect` | `sdk.mcp.connect()` | 连接已禁用的服务器 |
35
+ | `mcp/disconnect` | `sdk.mcp.disconnect()` | 断开服务器 |
36
+ | `mcp/auth/start` | `sdk.mcp.auth.start()` | 启动 OAuth 认证 |
37
+ | `mcp/auth/callback` | `sdk.mcp.auth.callback()` | 完成 OAuth 认证 |
38
+ | `mcp/auth/remove` | `sdk.mcp.auth.remove()` | 删除 OAuth 凭据 |
39
39
 
40
40
  ### 各操作详细签名
41
41
 
@@ -44,13 +44,15 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
44
44
  获取所有已配置 MCP 服务器的连接状态。
45
45
 
46
46
  **请求参数:**
47
+
47
48
  ```typescript
48
49
  {
49
- sessionId: string // 用于获取 cwd
50
+ sessionId: string; // 用于获取 cwd
50
51
  }
51
52
  ```
52
53
 
53
54
  **响应:**
55
+
54
56
  ```typescript
55
57
  {
56
58
  [serverName: string]: {
@@ -65,6 +67,7 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
65
67
  动态添加 MCP 服务器。
66
68
 
67
69
  **请求参数:**
70
+
68
71
  ```typescript
69
72
  {
70
73
  sessionId: string
@@ -89,6 +92,7 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
89
92
  ```
90
93
 
91
94
  **响应:**
95
+
92
96
  ```typescript
93
97
  {
94
98
  [serverName: string]: McpStatus // 添加后所有服务器状态
@@ -100,17 +104,19 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
100
104
  连接一个已禁用/断开的 MCP 服务器。
101
105
 
102
106
  **请求参数:**
107
+
103
108
  ```typescript
104
109
  {
105
- sessionId: string
106
- name: string
110
+ sessionId: string;
111
+ name: string;
107
112
  }
108
113
  ```
109
114
 
110
115
  **响应:**
116
+
111
117
  ```typescript
112
118
  {
113
- success: true
119
+ success: true;
114
120
  }
115
121
  ```
116
122
 
@@ -119,17 +125,19 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
119
125
  断开一个 MCP 服务器。
120
126
 
121
127
  **请求参数:**
128
+
122
129
  ```typescript
123
130
  {
124
- sessionId: string
125
- name: string
131
+ sessionId: string;
132
+ name: string;
126
133
  }
127
134
  ```
128
135
 
129
136
  **响应:**
137
+
130
138
  ```typescript
131
139
  {
132
- success: true
140
+ success: true;
133
141
  }
134
142
  ```
135
143
 
@@ -138,18 +146,20 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
138
146
  启动 OAuth 认证流程,返回授权 URL。
139
147
 
140
148
  **请求参数:**
149
+
141
150
  ```typescript
142
151
  {
143
- sessionId: string
144
- name: string
152
+ sessionId: string;
153
+ name: string;
145
154
  }
146
155
  ```
147
156
 
148
157
  **响应:**
158
+
149
159
  ```typescript
150
160
  {
151
- authorizationUrl: string
152
- oauthState: string
161
+ authorizationUrl: string;
162
+ oauthState: string;
153
163
  }
154
164
  ```
155
165
 
@@ -160,17 +170,19 @@ ACP Client (Editor) ← stdio/JSON-RPC → Harmony-ACP ← HTTP/SSE → OpenCode
160
170
  用授权码完成 OAuth 认证。
161
171
 
162
172
  **请求参数:**
173
+
163
174
  ```typescript
164
175
  {
165
- sessionId: string
166
- name: string
167
- code: string // OAuth 授权码
176
+ sessionId: string;
177
+ name: string;
178
+ code: string; // OAuth 授权码
168
179
  }
169
180
  ```
170
181
 
171
182
  **响应:**
183
+
172
184
  ```typescript
173
- McpStatus // 认证后的服务器状态
185
+ McpStatus; // 认证后的服务器状态
174
186
  ```
175
187
 
176
188
  #### `mcp/auth/remove`
@@ -178,17 +190,19 @@ McpStatus // 认证后的服务器状态
178
190
  删除 MCP 服务器的 OAuth 凭据。
179
191
 
180
192
  **请求参数:**
193
+
181
194
  ```typescript
182
195
  {
183
- sessionId: string
184
- name: string
196
+ sessionId: string;
197
+ name: string;
185
198
  }
186
199
  ```
187
200
 
188
201
  **响应:**
202
+
189
203
  ```typescript
190
204
  {
191
- success: true
205
+ success: true;
192
206
  }
193
207
  ```
194
208
 
@@ -202,52 +216,52 @@ McpStatus // 认证后的服务器状态
202
216
 
203
217
  ```typescript
204
218
  // src/mcp-manager.ts
205
- import type { OpencodeClient } from "@opencode-ai/sdk/v2"
206
- import { ocCall } from "./logger.js"
219
+ import type { OpencodeClient } from "@opencode-ai/sdk/v2";
220
+ import { ocCall } from "./logger.js";
207
221
 
208
222
  export class McpManager {
209
223
  constructor(private sdk: OpencodeClient) {}
210
224
 
211
225
  async status(directory: string) {
212
- ocCall("mcp.status", { directory })
213
- const result = await this.sdk.mcp.status({ directory })
214
- return result.data ?? {}
226
+ ocCall("mcp.status", { directory });
227
+ const result = await this.sdk.mcp.status({ directory });
228
+ return result.data ?? {};
215
229
  }
216
230
 
217
231
  async add(directory: string, name: string, config: any) {
218
- ocCall("mcp.add", { directory, name })
219
- const result = await this.sdk.mcp.add({ directory, name, config })
220
- return result.data ?? {}
232
+ ocCall("mcp.add", { directory, name });
233
+ const result = await this.sdk.mcp.add({ directory, name, config });
234
+ return result.data ?? {};
221
235
  }
222
236
 
223
237
  async connect(directory: string, name: string) {
224
- ocCall("mcp.connect", { directory, name })
225
- await this.sdk.mcp.connect({ directory, name })
226
- return { success: true }
238
+ ocCall("mcp.connect", { directory, name });
239
+ await this.sdk.mcp.connect({ directory, name });
240
+ return { success: true };
227
241
  }
228
242
 
229
243
  async disconnect(directory: string, name: string) {
230
- ocCall("mcp.disconnect", { directory, name })
231
- await this.sdk.mcp.disconnect({ directory, name })
232
- return { success: true }
244
+ ocCall("mcp.disconnect", { directory, name });
245
+ await this.sdk.mcp.disconnect({ directory, name });
246
+ return { success: true };
233
247
  }
234
248
 
235
249
  async startAuth(directory: string, name: string) {
236
- ocCall("mcp.auth.start", { directory, name })
237
- const result = await this.sdk.mcp.auth.start({ directory, name })
238
- return result.data
250
+ ocCall("mcp.auth.start", { directory, name });
251
+ const result = await this.sdk.mcp.auth.start({ directory, name });
252
+ return result.data;
239
253
  }
240
254
 
241
255
  async callbackAuth(directory: string, name: string, code: string) {
242
- ocCall("mcp.auth.callback", { directory, name })
243
- const result = await this.sdk.mcp.auth.callback({ directory, name, code })
244
- return result.data
256
+ ocCall("mcp.auth.callback", { directory, name });
257
+ const result = await this.sdk.mcp.auth.callback({ directory, name, code });
258
+ return result.data;
245
259
  }
246
260
 
247
261
  async removeAuth(directory: string, name: string) {
248
- ocCall("mcp.auth.remove", { directory, name })
249
- await this.sdk.mcp.auth.remove({ directory, name })
250
- return { success: true }
262
+ ocCall("mcp.auth.remove", { directory, name });
263
+ await this.sdk.mcp.auth.remove({ directory, name });
264
+ return { success: true };
251
265
  }
252
266
  }
253
267
  ```
@@ -259,45 +273,47 @@ export class McpManager {
259
273
  ```typescript
260
274
  // agent.ts 中添加
261
275
 
262
- import { McpManager } from "./mcp-manager.js"
276
+ import { McpManager } from "./mcp-manager.js";
263
277
 
264
278
  export class Agent implements ACPAgent {
265
- private mcpManager: McpManager
279
+ private mcpManager: McpManager;
266
280
 
267
281
  constructor(config: ACPConfig) {
268
282
  // ...
269
- this.mcpManager = new McpManager(config.sdk)
283
+ this.mcpManager = new McpManager(config.sdk);
270
284
  }
271
285
 
272
286
  async extMethod(method: string, params: Record<string, unknown>): Promise<Record<string, unknown>> {
273
287
  if (method.startsWith("mcp/")) {
274
- return this.handleMcpMethod(method, params)
288
+ return this.handleMcpMethod(method, params);
275
289
  }
276
- throw new Error(`Unknown extMethod: ${method}`)
290
+ throw new Error(`Unknown extMethod: ${method}`);
277
291
  }
278
292
 
279
293
  private async handleMcpMethod(method: string, params: Record<string, unknown>) {
280
- const sessionId = params.sessionId as string
281
- const session = this.sessionManager.get(sessionId)
282
- const directory = session.cwd
294
+ const sessionId = params.sessionId as string;
295
+ const session = this.sessionManager.get(sessionId);
296
+ const directory = session.cwd;
283
297
 
284
298
  switch (method) {
285
299
  case "mcp/status":
286
- return this.mcpManager.status(directory) as Promise<Record<string, unknown>>
300
+ return this.mcpManager.status(directory) as Promise<Record<string, unknown>>;
287
301
  case "mcp/add":
288
- return this.mcpManager.add(directory, params.name as string, params.config) as Promise<Record<string, unknown>>
302
+ return this.mcpManager.add(directory, params.name as string, params.config) as Promise<Record<string, unknown>>;
289
303
  case "mcp/connect":
290
- return this.mcpManager.connect(directory, params.name as string)
304
+ return this.mcpManager.connect(directory, params.name as string);
291
305
  case "mcp/disconnect":
292
- return this.mcpManager.disconnect(directory, params.name as string)
306
+ return this.mcpManager.disconnect(directory, params.name as string);
293
307
  case "mcp/auth/start":
294
- return this.mcpManager.startAuth(directory, params.name as string) as Promise<Record<string, unknown>>
308
+ return this.mcpManager.startAuth(directory, params.name as string) as Promise<Record<string, unknown>>;
295
309
  case "mcp/auth/callback":
296
- return this.mcpManager.callbackAuth(directory, params.name as string, params.code as string) as Promise<Record<string, unknown>>
310
+ return this.mcpManager.callbackAuth(directory, params.name as string, params.code as string) as Promise<
311
+ Record<string, unknown>
312
+ >;
297
313
  case "mcp/auth/remove":
298
- return this.mcpManager.removeAuth(directory, params.name as string)
314
+ return this.mcpManager.removeAuth(directory, params.name as string);
299
315
  default:
300
- throw new Error(`Unknown MCP method: ${method}`)
316
+ throw new Error(`Unknown MCP method: ${method}`);
301
317
  }
302
318
  }
303
319
  }
@@ -342,16 +358,16 @@ mcp: {
342
358
 
343
359
  ## 关键文件清单
344
360
 
345
- | 文件 | 操作 | 说明 |
346
- |---|---|---|
347
- | `src/mcp-manager.ts` | **新建** | MCP 操作封装,代理 SDK 调用 |
348
- | `src/agent.ts` | **修改** | 添加 extMethod 路由、集成 McpManager、迁移 MCP 注册逻辑 |
349
- | `src/types.ts` | **修改** | 添加 MCP 相关类型(可选) |
350
- | `src/__tests__/mcp-manager.test.ts` | **新建** | McpManager 单元测试 |
351
- | `src/__tests__/agent.test.ts` | **修改** | 添加 extMethod 测试 |
352
- | `src/__tests__/helpers/mock-sdk.ts` | **修改** | 补全 MCP mock 方法 |
353
- | `README.md` | **修改** | 文档更新 |
354
- | `CHANGELOG.md` | **修改** | 记录变更 |
361
+ | 文件 | 操作 | 说明 |
362
+ | ----------------------------------- | -------- | ------------------------------------------------------- |
363
+ | `src/mcp-manager.ts` | **新建** | MCP 操作封装,代理 SDK 调用 |
364
+ | `src/agent.ts` | **修改** | 添加 extMethod 路由、集成 McpManager、迁移 MCP 注册逻辑 |
365
+ | `src/types.ts` | **修改** | 添加 MCP 相关类型(可选) |
366
+ | `src/__tests__/mcp-manager.test.ts` | **新建** | McpManager 单元测试 |
367
+ | `src/__tests__/agent.test.ts` | **修改** | 添加 extMethod 测试 |
368
+ | `src/__tests__/helpers/mock-sdk.ts` | **修改** | 补全 MCP mock 方法 |
369
+ | `README.md` | **修改** | 文档更新 |
370
+ | `CHANGELOG.md` | **修改** | 记录变更 |
355
371
 
356
372
  ## 复用
357
373
 
@@ -4,20 +4,20 @@
4
4
 
5
5
  OpenCode 有两个层面的 provider 数据:
6
6
 
7
- | 数据源 | 接口 | 内容 | 用途 |
8
- |--------|------|------|------|
9
- | **数据库全量** | `GET /provider` | models.dev 中的所有 provider(70+) | 发现哪些 provider 可配置 |
10
- | **运行时可用** | `GET /config/providers` | 有凭证或 autoload 的 provider + 模型列表 | 模型选择下拉框 |
7
+ | 数据源 | 接口 | 内容 | 用途 |
8
+ | -------------- | ----------------------- | ---------------------------------------- | ------------------------ |
9
+ | **数据库全量** | `GET /provider` | models.dev 中的所有 provider(70+) | 发现哪些 provider 可配置 |
10
+ | **运行时可用** | `GET /config/providers` | 有凭证或 autoload 的 provider + 模型列表 | 模型选择下拉框 |
11
11
 
12
12
  **关键**:`GET /config/providers` 返回的不是"有 API Key 的 provider",而是 `s.providers` 这个内部状态。进入 `s.providers` 的条件(`provider/provider.ts:1076-1285`):
13
13
 
14
- | 条件 | 代码位置 | 说明 |
15
- |------|---------|------|
16
- | 配置文件声明了 provider | 1124 行 | `opencode.json` 中 `provider.<id>` 有配置 |
17
- | 环境变量有 key | 1211 行 | 如 `ANTHROPIC_API_KEY=xxx` |
18
- | auth.json 有 key | 1224 行 | 通过 `PUT /auth/:providerID` 存入的 |
19
- | Plugin auth loader | 1237 行 | Plugin 提供的认证加载器 |
20
- | **Custom loader autoload** | 1258 行 | **`opencode` provider 始终 autoload** |
14
+ | 条件 | 代码位置 | 说明 |
15
+ | -------------------------- | -------- | ----------------------------------------- |
16
+ | 配置文件声明了 provider | 1124 行 | `opencode.json` 中 `provider.<id>` 有配置 |
17
+ | 环境变量有 key | 1211 行 | 如 `ANTHROPIC_API_KEY=xxx` |
18
+ | auth.json 有 key | 1224 行 | 通过 `PUT /auth/:providerID` 存入的 |
19
+ | Plugin auth loader | 1237 行 | Plugin 提供的认证加载器 |
20
+ | **Custom loader autoload** | 1258 行 | **`opencode` provider 始终 autoload** |
21
21
 
22
22
  ### `opencode` Provider 的特殊性
23
23
 
@@ -28,14 +28,14 @@ OpenCode 有两个层面的 provider 数据:
28
28
  if (!ok) {
29
29
  // 删除付费模型,保留免费模型(cost.input === 0)
30
30
  for (const [key, value] of Object.entries(input.models)) {
31
- if (value.cost.input === 0) continue
32
- delete input.models[key]
31
+ if (value.cost.input === 0) continue;
32
+ delete input.models[key];
33
33
  }
34
34
  }
35
35
  return {
36
- autoload: Object.keys(input.models).length > 0, // 有免费模型就 autoload
37
- options: ok ? {} : { apiKey: "public" }, // 无 key 用 "public"
38
- }
36
+ autoload: Object.keys(input.models).length > 0, // 有免费模型就 autoload
37
+ options: ok ? {} : { apiKey: "public" }, // 无 key 用 "public"
38
+ };
39
39
  ```
40
40
 
41
41
  **这意味着**:即使零配置,`GET /config/providers` 也会返回 `opencode` provider,包含所有免费模型(如 `glm-4.6`、`big-pickle` 等)。TUI 的 `/models` 能看到 GLM 模型就是这个原因。
@@ -258,36 +258,36 @@ VSCode harmony-acp OpenCode Server
258
258
 
259
259
  ### 控制面路由(`routes/control/index.ts`)
260
260
 
261
- | 方法 | 路径 | 用途 |
262
- |------|------|------|
263
- | `PUT` | `/auth/:providerID` | 设置 API Key,写入 `~/.opencode/data/auth.json` |
264
- | `DELETE` | `/auth/:providerID` | 移除凭证 |
261
+ | 方法 | 路径 | 用途 |
262
+ | -------- | ------------------- | ----------------------------------------------- |
263
+ | `PUT` | `/auth/:providerID` | 设置 API Key,写入 `~/.opencode/data/auth.json` |
264
+ | `DELETE` | `/auth/:providerID` | 移除凭证 |
265
265
 
266
266
  ### 实例面路由(`routes/instance/provider.ts`)
267
267
 
268
- | 方法 | 路径 | 用途 |
269
- |------|------|------|
270
- | `GET` | `/provider` | 返回全量 provider 列表 + connected 状态 |
271
- | `GET` | `/provider/auth` | 返回每个 provider 的认证方式(API Key / OAuth) |
268
+ | 方法 | 路径 | 用途 |
269
+ | ------ | ------------------------------ | ----------------------------------------------------- |
270
+ | `GET` | `/provider` | 返回全量 provider 列表 + connected 状态 |
271
+ | `GET` | `/provider/auth` | 返回每个 provider 的认证方式(API Key / OAuth) |
272
272
  | `POST` | `/:providerID/oauth/authorize` | OAuth 授权(仅 Plugin 注册了 OAuth hook 的 provider) |
273
- | `POST` | `/:providerID/oauth/callback` | OAuth 回调 |
273
+ | `POST` | `/:providerID/oauth/callback` | OAuth 回调 |
274
274
 
275
275
  ### 实例面路由(`routes/instance/config.ts`)
276
276
 
277
- | 方法 | 路径 | 用途 |
278
- |------|------|------|
277
+ | 方法 | 路径 | 用途 |
278
+ | ----- | ------------------- | -------------------------------------------------------------- |
279
279
  | `GET` | `/config/providers` | 返回 `s.providers`(有凭证或 autoload 的 provider + 模型列表) |
280
280
 
281
281
  ## 两个 Provider 接口的区别
282
282
 
283
- | | `GET /provider` | `GET /config/providers` |
284
- |---|---|---|
285
- | 数据源 | models.dev 全量数据库 + connected 状态 | `s.providers` 内部状态(有凭证/autoload) |
286
- | 返回范围 | **所有** provider(70+) | 仅"可用"的 provider |
287
- | 用途 | 发现可配置的 provider、展示配置入口 | 模型选择下拉框的数据源 |
288
- | 返回格式 | `{ all, default, connected }` | `{ providers, default }` |
289
- | ACP extMethod | `provider/list` | 无(harmony-acp 内部调用) |
290
- | TUI 使用 | `store.provider_next` | `store.provider`(`/models` 下拉框) |
283
+ | | `GET /provider` | `GET /config/providers` |
284
+ | ------------- | -------------------------------------- | ----------------------------------------- |
285
+ | 数据源 | models.dev 全量数据库 + connected 状态 | `s.providers` 内部状态(有凭证/autoload) |
286
+ | 返回范围 | **所有** provider(70+) | 仅"可用"的 provider |
287
+ | 用途 | 发现可配置的 provider、展示配置入口 | 模型选择下拉框的数据源 |
288
+ | 返回格式 | `{ all, default, connected }` | `{ providers, default }` |
289
+ | ACP extMethod | `provider/list` | 无(harmony-acp 内部调用) |
290
+ | TUI 使用 | `store.provider_next` | `store.provider`(`/models` 下拉框) |
291
291
 
292
292
  ## API Key 有效性判定
293
293
 
@@ -24,6 +24,7 @@ OpenCode session 表已持久化 `summary_additions`/`summary_deletions`/`summar
24
24
  5. **文件级 diff 已有通道** — edit tool 的 tool_call_update 已返回 diff,无需重复传输
25
25
 
26
26
  **数据格式:**
27
+
27
28
  ```typescript
28
29
  usage_update._meta.codeChange = {
29
30
  additions: number
@@ -84,9 +85,9 @@ usage_update._meta.codeChange = {
84
85
 
85
86
  ```typescript
86
87
  export interface CodeChangeStats {
87
- additions: number
88
- deletions: number
89
- files: number
88
+ additions: number;
89
+ deletions: number;
90
+ files: number;
90
91
  }
91
92
  ```
92
93
 
@@ -113,6 +114,7 @@ case "session.diff": {
113
114
  ```
114
115
 
115
116
  新增实例变量和方法:
117
+
116
118
  - `diffStats: Map<string, CodeChangeStats>` — 存储 session 级 diff 聚合
117
119
  - `getDiffStats(sessionId)` — 供 agent.ts 读取
118
120
  - `setDiffStats(sessionId, stats)` — 供 agent.ts 回填历史数据
@@ -166,13 +168,13 @@ _meta: {
166
168
  从返回数据中提取 summary,存入 EventHandler 的 `diffStats` map:
167
169
 
168
170
  ```typescript
169
- const session = await this.sdk.session.get({ sessionID, directory })
171
+ const session = await this.sdk.session.get({ sessionID, directory });
170
172
  if (session.data?.summary) {
171
173
  this.eventHandler.setDiffStats(sessionID, {
172
174
  additions: session.data.summary.additions,
173
175
  deletions: session.data.summary.deletions,
174
176
  files: session.data.summary.files,
175
- })
177
+ });
176
178
  }
177
179
  ```
178
180
 
@@ -188,22 +190,22 @@ if (session.data?.summary) {
188
190
 
189
191
  ## 涉及文件
190
192
 
191
- | 文件 | 修改内容 |
192
- |------|---------|
193
- | `src/types.ts` | 新增 `CodeChangeStats` 接口 |
194
- | `src/event-handler.ts` | 新增 `session.diff` 事件处理 + `diffStats` map + get/set/clear 方法 |
195
- | `src/agent.ts` | `sendUsageUpdate()` 附加 `_meta.codeChange`;`loadSession()`/`resumeSession()` 读取 `session.summary` |
193
+ | 文件 | 修改内容 |
194
+ | ---------------------- | ----------------------------------------------------------------------------------------------------- |
195
+ | `src/types.ts` | 新增 `CodeChangeStats` 接口 |
196
+ | `src/event-handler.ts` | 新增 `session.diff` 事件处理 + `diffStats` map + get/set/clear 方法 |
197
+ | `src/agent.ts` | `sendUsageUpdate()` 附加 `_meta.codeChange`;`loadSession()`/`resumeSession()` 读取 `session.summary` |
196
198
 
197
199
  ---
198
200
 
199
201
  ## 依赖的 OpenCode 现有能力
200
202
 
201
- | 能力 | 来源 | 说明 |
202
- |------|------|------|
203
- | `session.diff` SSE 事件 | OpenCode SDK `EventSessionDiff` | session 代码变更时实时推送 `SnapshotFileDiff[]` |
204
- | `Session.summary` 字段 | OpenCode SDK `Session` 类型 | 含 `additions`/`deletions`/`files`/`diffs` |
205
- | `UsageUpdate._meta` | ACP 协议 | `{ [key: string]: unknown }` 扩展字段 |
206
- | 已有 `_meta` 扩展模式 | harmony-acp `sendUsageUpdate()` | 已传递 `parentCost`/`childCost`/`childSessionCount` |
203
+ | 能力 | 来源 | 说明 |
204
+ | ----------------------- | ------------------------------- | --------------------------------------------------- |
205
+ | `session.diff` SSE 事件 | OpenCode SDK `EventSessionDiff` | session 代码变更时实时推送 `SnapshotFileDiff[]` |
206
+ | `Session.summary` 字段 | OpenCode SDK `Session` 类型 | 含 `additions`/`deletions`/`files`/`diffs` |
207
+ | `UsageUpdate._meta` | ACP 协议 | `{ [key: string]: unknown }` 扩展字段 |
208
+ | 已有 `_meta` 扩展模式 | harmony-acp `sendUsageUpdate()` | 已传递 `parentCost`/`childCost`/`childSessionCount` |
207
209
 
208
210
  ---
209
211
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harmonyos-arkts/opencode-acp",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "description": "Enhanced ACP (Agent Client Protocol) server for OpenCode with subagent visibility",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -23,6 +23,7 @@
23
23
  "test": "vitest run",
24
24
  "test:watch": "vitest",
25
25
  "test:integration": "node scripts/test-integration.mjs",
26
+ "test:mcp": "node scripts/test-mcp-extmethod.mjs",
26
27
  "logs": "node scripts/view-log.mjs",
27
28
  "logs:filter": "node scripts/view-log.mjs --filter"
28
29
  },
@@ -39,6 +40,6 @@
39
40
  "vitest": "^4.1.5"
40
41
  },
41
42
  "engines": {
42
- "node": ">=18.0.0"
43
+ "node": ">=20.0.0"
43
44
  }
44
45
  }