@harmonyos-arkts/opencode-acp 0.0.1 → 0.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,91 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [Unreleased]
6
+
7
+ ### Added
8
+
9
+ - Provider Auth extMethod API:通过 ACP `extMethod("provider/*")` 向 VSCode 暴露 OpenCode 的 API Key 配置能力
10
+ - `provider/list` — 列出所有 provider 及连接状态
11
+ - `provider/auth/methods` — 获取各 provider 的认证方式和 prompts
12
+ - `provider/auth/set` — 设置 API Key 凭证
13
+ - `provider/auth/remove` — 移除 provider 凭证
14
+ - `provider/oauth/authorize` — 发起 OAuth 授权,获取授权 URL
15
+ - `provider/oauth/callback` — 完成 OAuth 回调
16
+ - `initialize()` 返回 `_meta.providers` 包含初始 provider 连接状态,VSCode 无需额外请求即可展示配置入口
17
+ - 新增 `src/auth-provider.ts`:AuthProviderManager 封装所有 SDK auth/provider 调用
18
+
19
+ ### Tests
20
+
21
+ - 新增 `src/__tests__/auth-provider.test.ts`:AuthProviderManager 单元测试(6 个用例)
22
+ - `agent.test.ts` 新增 extMethod 路由测试(11 个用例),含参数校验和错误处理
23
+ - 测试总数从 101 增加到 118
24
+
25
+ ## [0.0.3] - 2026-04-24
26
+
27
+ ### Added
28
+
29
+ - 子 session 完成事件:父 session 的 task 工具完成时发送 `session_info_update` + `status: "completed"`,包含 toolCallCount 和 durationMs
30
+ - 子 session 历史回放:`loadSession` 时自动发现并回放子 session 消息,客户端加载历史 session 时可见子 agent 输出
31
+ - 结构化子 session 元数据:`_meta` 中新增 `agentType`(如 `"explore"`)和 `description`(如 `"Explore project structure"`),客户端无需从 title 解析
32
+ - 子 session 用量汇总:`usage_update` 的 cost 包含所有子 session 开销,`_meta` 中附带 `parentCost`、`childCost`、`childSessionCount`
33
+
34
+ ### Changed
35
+
36
+ - delta 处理性能优化:新增 `messageMetaCache` 缓存消息元数据,每个消息仅拉取一次 SDK(之前每个 delta chunk 拉取一次,N+1 查询问题)
37
+ - buffer flush 性能优化:新增 `sessionBufferIndex` 索引(sessionId → Set\<messageId\>),替代线性扫描全量 messageBuffers
38
+ - `resolveSession` 简化:移除冗余的 `findRootSession` 递归查找和第二次 `tryGet` 调用
39
+ - `announceChildSession` 支持可选 `meta` 参数传递结构化 agentType/description
40
+
41
+ ### Tests
42
+
43
+ - 新增子 session 完成事件测试(task 工具完成 → completion event,非 task 工具 → 无 event)
44
+ - 新增结构化元数据解析测试(title 格式 `"description (@agent subagent)"` → agentType + description)
45
+ - 测试总数从 74 增加到 101(新增 27 个测试用例)
46
+
47
+ ### Fixed
48
+
49
+ - MCP server 注册时正确传递 HTTP headers 和 local environment variables(之前被丢弃为空)
50
+ - MCP server 注册改为并行(`Promise.all`),多个 server 初始化更快
51
+ - `setSessionModel` 正确解析含 variant 的 modelId(如 `claude-sonnet-4/high`),返回 `_meta` 反馈
52
+ - `setSessionConfigOption` 正确处理 variant 和 mode,返回完整模型+模式列表
53
+ - `loadSessionMode` 模型列表包含 variant 选项,返回 `_meta` 含 variant 信息
54
+ - `loadSessionMode` 加载可用 agent/mode 列表并返回(之前固定返回 `undefined`)
55
+ - `setSessionMode` 增加 mode 存在性校验(之前静默接受无效 modeId)
56
+ - `prompt()` 使用动态解析的默认 agent 替代硬编码 `"build"`
57
+ - TodoWrite 工具输出解析为 plan update(历史回放 + 实时事件均已支持)
58
+ - `initialize` 检查 `clientCapabilities._meta["terminal-auth"]`,支持编辑器内登录(Zed 等)
59
+ - `/compact` 命令调用 `session.summarize()` 执行会话压缩(之前会被当成普通 prompt)
60
+ - 自动注入内置 `compact` 命令到 `available_commands_update`
61
+
62
+ ### Added
63
+
64
+ - 添加 Vitest 单元测试框架(74 个测试用例)
65
+ - `src/__tests__/utils.test.ts` — toToolKind / toLocations / parseUri 纯函数测试
66
+ - `src/__tests__/session-manager.test.ts` — SessionManager 父子关系、session 生命周期测试
67
+ - `src/__tests__/logger.test.ts` — Logger 开关、分类、sanitize 测试
68
+ - `src/__tests__/event-handler.test.ts` — SSE 事件路由、权限处理、问题处理、工具状态转换测试
69
+ - 将 `parseUri` 从 `agent.ts` 提取到 `utils.ts` 以便复用和测试
70
+
71
+ ## [0.0.1] - 2026-04-22
72
+
73
+ ### event-handler.ts 改动
74
+
75
+ | 修复 | 说明 |
76
+ | ----------------- | ----------------------------------------------------------------------------------------- |
77
+ | edit 权限写空内容 | 使用 sdk.file.read() 读取原始内容 + applyPatch() 计算差异后的新内容,替代原来发送空字符串 |
78
+ | extMethod 吞错误 | .catch() 内增加 console.error 记录失败原因 |
79
+ | 60s 超时保护 | Promise.race 对 extMethod("questionAsked") 加 60 秒超时 |
80
+ | 转发 tool 上下文 | extMethod 参数中增加 q.tool(messageID + callID) |
81
+ | answers 校验 | 发送前验证 Array<Array<string>> 结构,不合法则 reject |
82
+ | 新增 diff 依赖 | package.json 中添加 diff 包 |
83
+
84
+ ### agent.ts 改动
85
+
86
+ | 修复 | 说明 |
87
+ | -------------------- | -------------------------------------------------------------------------------------------------------------------- |
88
+ | LoadAPIKeyError 处理 | newSession/loadSession/forkSession/resumeSession 均增加 try/catch,检测 API key 错误抛 RequestError.authRequired() |
89
+ | usage_update size | 从 sdk.config.providers() 查询 model.limit.context 替代硬编码 0 |
90
+ | file 类型回放 | processMessage 中新增 file part 回放,支持 file://(resource_link)和 data: URL(image/resource) |
91
+ | resource_link 解析 | convertPromptParts 中实现 parseUri(),支持 file:// 和 zed:// URL 转为 file part;resource 类型也支持 blob 二进制数据 |
package/README.md CHANGED
@@ -46,12 +46,17 @@ await sendToClient({
46
46
  update: {
47
47
  sessionUpdate: "session_info_update",
48
48
  title: "Explore project structure (@explore subagent)",
49
- _meta: { parentSessionId, isSubagent: true },
49
+ _meta: {
50
+ parentSessionId,
51
+ isSubagent: true,
52
+ agentType: "explore",
53
+ description: "Explore project structure",
54
+ },
50
55
  },
51
- })
56
+ });
52
57
  ```
53
58
 
54
- The client can distinguish parent vs child messages by sessionId, and use `_meta.parentSessionId` to display the hierarchy.
59
+ The client can distinguish parent vs child messages by sessionId, and use `_meta.parentSessionId` to display the hierarchy. When the subagent finishes, a `session_info_update` with `status: "completed"` is sent including `toolCallCount` and `durationMs`.
55
60
 
56
61
  ### Message Assembly
57
62
 
@@ -127,13 +132,13 @@ All communication is logged to `~/.harmony-acp/logs/` as JSONL files (auto-rotat
127
132
 
128
133
  ### Log Categories
129
134
 
130
- | Category | Direction | Description |
131
- |----------|-----------|-------------|
132
- | `acp.in` | Editor → Harmony-ACP | Incoming ACP requests (initialize, prompt, newSession, etc.) |
133
- | `acp.out` | Harmony-ACP → Editor | Outgoing ACP responses and session updates |
134
- | `oc.call` | Harmony-ACP → OpenCode | Calls to OpenCode SDK (session.create, session.prompt, etc.) |
135
- | `oc.event` | OpenCode → Harmony-ACP | SSE events (session.created, permission.asked, etc.) |
136
- | `system` | Internal | Lifecycle events (start, stop, errors) |
135
+ | Category | Direction | Description |
136
+ | ---------- | ---------------------- | ------------------------------------------------------------ |
137
+ | `acp.in` | Editor → Harmony-ACP | Incoming ACP requests (initialize, prompt, newSession, etc.) |
138
+ | `acp.out` | Harmony-ACP → Editor | Outgoing ACP responses and session updates |
139
+ | `oc.call` | Harmony-ACP → OpenCode | Calls to OpenCode SDK (session.create, session.prompt, etc.) |
140
+ | `oc.event` | OpenCode → Harmony-ACP | SSE events (session.created, permission.asked, etc.) |
141
+ | `system` | Internal | Lifecycle events (start, stop, errors) |
137
142
 
138
143
  ### Log Viewer
139
144
 
@@ -167,17 +172,18 @@ When using `--content`, assembled messages are displayed with full text:
167
172
 
168
173
  ## Architecture
169
174
 
170
- | File | Purpose |
171
- |------|---------|
172
- | `src/index.ts` | CLI entry: argument parsing, stdio setup, server connection |
173
- | `src/agent.ts` | ACP Agent: implements `Agent` interface, session management, prompting |
174
- | `src/session-manager.ts` | Enhanced session tracking with parent-child relationship index |
175
- | `src/event-handler.ts` | SSE event subscription, routing, and message delta assembly |
176
- | `src/logger.ts` | JSONL structured logging with message assembly support |
177
- | `src/types.ts` | Shared type definitions |
178
- | `src/utils.ts` | Tool kind mapping utilities |
179
- | `scripts/view-log.mjs` | Colorized log viewer |
180
- | `scripts/test-integration.mjs` | Full pipeline integration test |
175
+ | File | Purpose |
176
+ | ------------------------------ | ---------------------------------------------------------------------- |
177
+ | `src/index.ts` | CLI entry: argument parsing, stdio setup, server connection |
178
+ | `src/agent.ts` | ACP Agent: implements `Agent` interface, session management, prompting |
179
+ | `src/auth-provider.ts` | Provider auth manager: wraps SDK calls for API Key/OAuth configuration |
180
+ | `src/session-manager.ts` | Enhanced session tracking with parent-child relationship index |
181
+ | `src/event-handler.ts` | SSE event subscription, routing, and message delta assembly |
182
+ | `src/logger.ts` | JSONL structured logging with message assembly support |
183
+ | `src/types.ts` | Shared type definitions |
184
+ | `src/utils.ts` | Tool kind mapping utilities |
185
+ | `scripts/view-log.mjs` | Colorized log viewer |
186
+ | `scripts/test-integration.mjs` | Full pipeline integration test |
181
187
 
182
188
  ### SessionManager Enhancement
183
189
 
@@ -185,18 +191,64 @@ Unlike OpenCode's built-in `ACPSessionManager` which only knows about explicitly
185
191
 
186
192
  - **Auto-discovers** child sessions via `session.created` SSE events
187
193
  - **Maintains a parent-child index** (`children: Map<parentID, Set<childID>>`)
188
- - **Resolves root sessions** via `findRootSession()` to route child events to the correct ACP client
194
+ - **Aggregates child session costs** for accurate usage reporting
189
195
 
190
196
  ### EventHandler Enhancement
191
197
 
192
198
  The `EventHandler` subscribes to OpenCode's global SSE event stream and handles:
193
199
 
194
- | Event | Behavior |
195
- |-------|----------|
196
- | `session.created` | Auto-registers child sessions, announces as virtual session to client |
197
- | `permission.asked` | Forwards permission requests including those from child sessions |
198
- | `message.part.updated` | Routes tool execution updates from child sessions |
199
- | `message.part.delta` | Accumulates text/reasoning deltas, streams to client, assembles for logging |
200
+ | Event | Behavior |
201
+ | ---------------------- | ------------------------------------------------------------------------------------ |
202
+ | `session.created` | Auto-registers child sessions, announces as virtual session with structured metadata |
203
+ | `permission.asked` | Forwards permission requests including those from child sessions |
204
+ | `message.part.updated` | Routes tool execution updates; sends completion event when task tool finishes |
205
+ | `message.part.delta` | Accumulates text/reasoning deltas using cached metadata (no N+1 queries) |
206
+
207
+ ## Provider Auth extMethod API
208
+
209
+ Harmony-ACP exposes OpenCode's provider auth API to VSCode through ACP `extMethod` calls. This allows users to configure API keys and complete OAuth flows directly from the editor.
210
+
211
+ ### Available Methods
212
+
213
+ | extMethod | Description |
214
+ |-----------|-------------|
215
+ | `provider/list` | List all providers with connected status |
216
+ | `provider/auth/methods` | Get auth methods per provider (API key prompts, OAuth) |
217
+ | `provider/auth/set` | Set API key credentials |
218
+ | `provider/auth/remove` | Remove credentials for a provider |
219
+ | `provider/oauth/authorize` | Start OAuth flow, returns authorization URL |
220
+ | `provider/oauth/callback` | Complete OAuth with authorization code |
221
+
222
+ ### Usage Example (VSCode → Harmony-ACP)
223
+
224
+ ```typescript
225
+ // List providers
226
+ const providers = await extMethod("provider/list", { sessionId });
227
+
228
+ // Set API key
229
+ await extMethod("provider/auth/set", {
230
+ providerID: "anthropic",
231
+ auth: { type: "api", key: "sk-ant-xxx" }
232
+ });
233
+
234
+ // Remove credentials
235
+ await extMethod("provider/auth/remove", { providerID: "anthropic" });
236
+ ```
237
+
238
+ ### Initialize Response
239
+
240
+ The `initialize()` response includes provider connectivity status in `_meta`:
241
+
242
+ ```typescript
243
+ {
244
+ _meta: {
245
+ providers: [
246
+ { id: "anthropic", name: "Anthropic", connected: true },
247
+ { id: "openai", name: "OpenAI", connected: false },
248
+ ]
249
+ }
250
+ }
251
+ ```
200
252
 
201
253
  ## Development
202
254
 
@@ -209,16 +261,26 @@ npm run test:integration # Full pipeline test (requires running OpenCode server
209
261
 
210
262
  ## Comparison with Built-in ACP
211
263
 
212
- | Feature | OpenCode Built-in ACP | Harmony-ACP |
213
- |---------|----------------------|-------------|
214
- | Session management | Top-level only | Top-level + child sessions |
215
- | Subagent tool calls visible | No | Yes |
216
- | Subagent text output visible | No | Yes |
217
- | Subagent permissions forwarded | No | Yes |
218
- | Traffic logging | No | Yes (JSONL, categorized) |
219
- | Message assembly | N/A | Yes (delta → complete) |
220
- | Modifies OpenCode source | N/A | No |
221
- | Runs as independent process | No (integrated) | Yes |
264
+ | Feature | OpenCode Built-in ACP | Harmony-ACP |
265
+ | ------------------------------- | --------------------- | ---------------------------------- |
266
+ | Session management | Top-level only | Top-level + child sessions |
267
+ | Subagent tool calls visible | No | Yes |
268
+ | Subagent text output visible | No | Yes |
269
+ | Subagent permissions forwarded | No | Yes |
270
+ | Subagent completion event | No | Yes (status, duration, tool count) |
271
+ | Subagent history replay on load | No | Yes |
272
+ | Subagent cost aggregation | No | Yes (childCost in usage_update) |
273
+ | Structured subagent metadata | No | Yes (agentType, description) |
274
+ | Traffic logging | No | Yes (JSONL, categorized) |
275
+ | Message assembly | N/A | Yes (delta → complete) |
276
+ | Delta N+1 query optimization | N/A | Yes (message metadata cache) |
277
+ | MCP headers/env passthrough | Yes | Yes |
278
+ | Model variant support | Yes | Yes |
279
+ | Mode/agent list loading | Yes | Yes |
280
+ | TodoWrite → plan update | Yes | Yes |
281
+ | Provider auth via extMethod | No | Yes (API Key + OAuth) |
282
+ | Modifies OpenCode source | N/A | No |
283
+ | Runs as independent process | No (integrated) | Yes |
222
284
 
223
285
  ## License
224
286
 
package/README.zh.md CHANGED
@@ -7,8 +7,7 @@
7
7
  OpenCode 内置的 ACP 有两个关键限制:
8
8
 
9
9
  1. **子代理不可见**:当代理通过 Task 工具派生子代理时,子 session 的事件——工具调用、文本输出、权限请求——对 ACP 客户端(如 Zed、VSCode)完全不可见。原因是内置的 `SessionManager` 只注册顶层 session,来自子 session 的事件会被静默丢弃。
10
-
11
- 2. **无流量可观测性**:无法检查 ACP 客户端与 OpenCode 之间流动的数据,调试困难。
10
+ 2. **无法进行问题回答**:当大模型有问题需要用户回答时,opencode acp没有监听,ACP客户端(如Zed/ VSCode)无法感知
12
11
 
13
12
  Harmony-ACP 在不修改任何 OpenCode 源码的前提下解决了这两个问题。
14
13
 
@@ -26,7 +25,7 @@ Harmony-ACP 在不修改任何 OpenCode 源码的前提下解决了这两个问
26
25
  │ sessionId │
27
26
  │ - 记录全量流量日志 │
28
27
  │ - 自动拼接消息碎片 │
29
- └────────────┬────────────┘
28
+ └────────────┬────────────
30
29
  │ HTTP / SSE
31
30
  ┌────────────▼────────────┐
32
31
  │ opencode serve │ ← 未修改的 OpenCode
@@ -46,7 +45,7 @@ await sendToClient({
46
45
  title: "Explore project structure (@explore subagent)",
47
46
  _meta: { parentSessionId, isSubagent: true },
48
47
  },
49
- })
48
+ });
50
49
  ```
51
50
 
52
51
  客户端通过 sessionId 区分父/子消息,通过 `_meta.parentSessionId` 展示层级关系。
@@ -125,13 +124,13 @@ node dist/index.cjs --server http://localhost:4096
125
124
 
126
125
  ### 日志分类
127
126
 
128
- | 分类 | 方向 | 说明 |
129
- |------|------|------|
130
- | `acp.in` | 编辑器 → Harmony-ACP | 收到的 ACP 请求(initialize、prompt、newSession 等) |
131
- | `acp.out` | Harmony-ACP → 编辑器 | 发出的 ACP 响应和 session 更新 |
132
- | `oc.call` | Harmony-ACP → OpenCode | 对 OpenCode SDK 的调用(session.create、session.prompt 等) |
133
- | `oc.event` | OpenCode → Harmony-ACP | SSE 事件(session.created、permission.asked 等) |
134
- | `system` | 内部 | 生命周期事件(启动、停止、错误) |
127
+ | 分类 | 方向 | 说明 |
128
+ | ---------- | ---------------------- | ----------------------------------------------------------- |
129
+ | `acp.in` | 编辑器 → Harmony-ACP | 收到的 ACP 请求(initialize、prompt、newSession 等) |
130
+ | `acp.out` | Harmony-ACP → 编辑器 | 发出的 ACP 响应和 session 更新 |
131
+ | `oc.call` | Harmony-ACP → OpenCode | 对 OpenCode SDK 的调用(session.create、session.prompt 等) |
132
+ | `oc.event` | OpenCode → Harmony-ACP | SSE 事件(session.created、permission.asked 等) |
133
+ | `system` | 内部 | 生命周期事件(启动、停止、错误) |
135
134
 
136
135
  ### 日志查看器
137
136
 
@@ -165,17 +164,19 @@ node scripts/view-log.mjs --list
165
164
 
166
165
  ## 架构
167
166
 
168
- | 文件 | 职责 |
169
- |------|------|
170
- | `src/index.ts` | 入口:参数解析、stdio 设置、服务器连接 |
171
- | `src/agent.ts` | ACP 代理:实现 `Agent` 接口、session 管理、prompt 转发、日志包装 |
172
- | `src/session-manager.ts` | 增强版 session 管理,维护父子关系索引 |
173
- | `src/event-handler.ts` | SSE 事件订阅、路由和消息 delta 拼装 |
174
- | `src/logger.ts` | JSONL 结构化日志,支持消息拼装 |
175
- | `src/types.ts` | 共享类型定义 |
176
- | `src/utils.ts` | 工具函数(toolKind 映射等) |
177
- | `scripts/view-log.mjs` | 彩色日志查看器 |
178
- | `scripts/test-integration.mjs` | 全链路集成测试 |
167
+ | 文件 | 职责 |
168
+ | ------------------------------ | ---------------------------------------------------------------- |
169
+ | `src/index.ts` | 入口:参数解析、stdio 设置、服务器连接 |
170
+ | `src/agent.ts` | ACP 代理:实现 `Agent` 接口、session 管理、prompt 转发、日志包装 |
171
+ | `src/session-manager.ts` | 增强版 session 管理,维护父子关系索引 |
172
+ | `src/event-handler.ts` | SSE 事件订阅、路由和消息 delta 拼装 |
173
+ | `src/logger.ts` | JSONL 结构化日志,支持消息拼装 |
174
+ | `src/types.ts` | 共享类型定义 |
175
+ | `src/utils.ts` | 工具函数(toolKind 映射等) |
176
+ | `scripts/view-log.mjs` | 彩色日志查看器 |
177
+ | `scripts/test-integration.mjs` | 全链路集成测试 |
178
+
179
+ 各文件的详细分析见 [docs/codebase-overview.md](docs/codebase-overview.md)。
179
180
 
180
181
  ### SessionManager 增强
181
182
 
@@ -189,34 +190,35 @@ node scripts/view-log.mjs --list
189
190
 
190
191
  `EventHandler` 订阅 OpenCode 的全局 SSE 事件流并处理:
191
192
 
192
- | 事件 | 行为 |
193
- |------|------|
194
- | `session.created` | 自动注册子 session,作为虚拟 session 公告给客户端 |
195
- | `permission.asked` | 转发权限请求,包括来自子 session 的请求 |
196
- | `message.part.updated` | 路由子 session 的工具执行状态更新 |
197
- | `message.part.delta` | 累积文本/推理 delta,流式转发给客户端,拼装后写入日志 |
193
+ | 事件 | 行为 |
194
+ | ---------------------- | ----------------------------------------------------- |
195
+ | `session.created` | 自动注册子 session,作为虚拟 session 公告给客户端 |
196
+ | `permission.asked` | 转发权限请求,包括来自子 session 的请求 |
197
+ | `message.part.updated` | 路由子 session 的工具执行状态更新 |
198
+ | `message.part.delta` | 累积文本/推理 delta,流式转发给客户端,拼装后写入日志 |
198
199
 
199
200
  ## 开发
200
201
 
201
202
  ```bash
202
203
  npm run build # esbuild → dist/index.cjs
203
204
  npm run typecheck # TypeScript 类型检查
204
- npm run test # SSE 事件测试(需运行 OpenCode 服务器)
205
+ npm test # 单元测试(Vitest,无需外部依赖)
206
+ npm run test:watch # 单元测试 watch 模式
205
207
  npm run test:integration # 全链路集成测试(需运行 OpenCode 服务器)
206
208
  ```
207
209
 
208
210
  ## 与内置 ACP 对比
209
211
 
210
- | 特性 | OpenCode 内置 ACP | Harmony-ACP |
211
- |------|-------------------|-------------|
212
- | Session 管理 | 仅顶层 session | 顶层 + 子 session |
213
- | 子代理工具调用可见 | 否 | 是 |
214
- | 子代理文本输出可见 | 否 | 是 |
215
- | 子代理权限请求转发 | 否 | 是 |
216
- | 流量日志 | 无 | 有(JSONL,分类记录) |
217
- | 消息碎片拼装 | N/A | 有(delta → 完整消息) |
218
- | 是否修改 OpenCode 源码 | — | 否 |
219
- | 运行方式 | 集成在 OpenCode 进程内 | 独立进程 |
212
+ | 特性 | OpenCode 内置 ACP | Harmony-ACP |
213
+ | ---------------------- | ---------------------- | ---------------------- |
214
+ | Session 管理 | 仅顶层 session | 顶层 + 子 session |
215
+ | 子代理工具调用可见 | 否 | 是 |
216
+ | 子代理文本输出可见 | 否 | 是 |
217
+ | 子代理权限请求转发 | 否 | 是 |
218
+ | 流量日志 | 无 | 有(JSONL,分类记录) |
219
+ | 消息碎片拼装 | N/A | 有(delta → 完整消息) |
220
+ | 是否修改 OpenCode 源码 | — | 否 |
221
+ | 运行方式 | 集成在 OpenCode 进程内 | 独立进程 |
220
222
 
221
223
  ## 许可证
222
224