@pencil-agent/nano-pencil 2.0.0 → 2.0.1

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.
Files changed (195) hide show
  1. package/README.md +267 -267
  2. package/dist/build-meta.json +3 -3
  3. package/dist/core/export-html/AGENT.md +11 -11
  4. package/dist/core/export-html/template.css +971 -971
  5. package/dist/core/export-html/template.html +54 -54
  6. package/dist/core/mcp/mcp-client.d.ts +3 -1
  7. package/dist/core/mcp/mcp-client.js +6 -6
  8. package/dist/core/mcp/mcp-config.d.ts +3 -3
  9. package/dist/core/mcp/mcp-config.js +1 -1
  10. package/dist/core/mcp/mcp-manager.d.ts +5 -1
  11. package/dist/core/mcp/mcp-manager.js +1 -1
  12. package/dist/core/platform/config/resource-loader.d.ts +2 -0
  13. package/dist/core/platform/config/resource-loader.js +2 -2
  14. package/dist/core/runtime/agent-session.d.ts +12 -0
  15. package/dist/core/runtime/agent-session.js +8 -8
  16. package/dist/core/runtime/sdk.d.ts +8 -0
  17. package/dist/core/runtime/sdk.js +1 -1
  18. package/dist/extensions/builtin/AGENT.md +115 -115
  19. package/dist/extensions/builtin/browser/AGENT.md +17 -17
  20. package/dist/extensions/builtin/browser/agent-workspace/agent_helpers.py +12 -12
  21. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/amazon/product-search.md +198 -198
  22. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/archive-org/scraping.md +341 -341
  23. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv/scraping.md +311 -311
  24. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv-bulk/scraping.md +333 -333
  25. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/atlas/overview.md +70 -70
  26. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/booking-com/scraping.md +578 -578
  27. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/capterra/scraping.md +440 -440
  28. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/centilebrain/generate-estimates.md +110 -110
  29. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coingecko/scraping.md +325 -325
  30. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coinmarketcap/scraping.md +463 -463
  31. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coursera/scraping.md +360 -360
  32. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/craigslist/scraping.md +390 -390
  33. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/crossref/scraping.md +568 -568
  34. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/dev-to/scraping.md +323 -323
  35. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/duckduckgo/scraping.md +349 -349
  36. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/ebay/scraping.md +435 -435
  37. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/etsy/scraping.md +506 -506
  38. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/eventbrite/scraping.md +363 -363
  39. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/expedia/automation.md +168 -168
  40. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/groups.md +236 -236
  41. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/pages.md +295 -295
  42. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/framer/editor.md +108 -108
  43. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/fred/scraping.md +493 -493
  44. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/g2/scraping.md +580 -580
  45. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/genius/scraping.md +511 -511
  46. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/repo-actions.md +65 -65
  47. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/scraping.md +184 -184
  48. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/glassdoor/scraping.md +543 -543
  49. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gmail/compose.md +122 -122
  50. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/goodreads/scraping.md +461 -461
  51. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gutenberg/scraping.md +383 -383
  52. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/hackernews/scraping.md +243 -243
  53. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/howlongtobeat/scraping.md +473 -473
  54. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/imdb/scraping.md +271 -271
  55. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/itch-io/scraping.md +436 -436
  56. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/job-boards/indeed-glassdoor.md +1021 -1021
  57. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/letterboxd/scraping.md +349 -349
  58. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/linkedin/invitation-manager.md +109 -109
  59. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/loom/folder-enumeration.md +170 -170
  60. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/macrotrends/scraping.md +537 -537
  61. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/article-hydration.md +120 -120
  62. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/scraping.md +414 -414
  63. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/metacritic/scraping.md +477 -477
  64. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/musicbrainz/scraping.md +478 -478
  65. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/nasa/scraping.md +339 -339
  66. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/news-aggregation/multi-source.md +205 -205
  67. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/open-library/scraping.md +472 -472
  68. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openalex/scraping.md +470 -470
  69. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openstreetmap/scraping.md +490 -490
  70. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/package-registries/npm-pypi.md +478 -478
  71. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/polymarket/scraping.md +234 -234
  72. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/producthunt/scraping.md +307 -307
  73. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/pubmed/scraping.md +421 -421
  74. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/quora/scraping.md +364 -364
  75. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rawg/scraping.md +352 -352
  76. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/reddit/scraping.md +124 -124
  77. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rest-countries/scraping.md +233 -233
  78. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/sec-edgar/scraping.md +361 -361
  79. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/README.md +36 -36
  80. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/embedded-apps.md +72 -72
  81. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/knowledge-base.md +109 -109
  82. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/polaris-inputs.md +137 -137
  83. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/soundcloud/scraping.md +362 -362
  84. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/spotify/scraping.md +339 -339
  85. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/stackoverflow/scraping.md +435 -435
  86. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/steam/scraping.md +575 -575
  87. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/substack/scraping.md +338 -338
  88. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/thetechgeeks/pricing.md +52 -52
  89. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tiktok/upload.md +107 -107
  90. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tradingview/scraping.md +309 -309
  91. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trello/boards-and-lists.md +88 -88
  92. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trustpilot/scraping.md +375 -375
  93. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/walmart/scraping.md +444 -444
  94. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wayback-machine/scraping.md +306 -306
  95. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/weather/scraping.md +398 -398
  96. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wellfound/scraping.md +596 -596
  97. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/world-bank/scraping.md +356 -356
  98. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/xiaohongshu/scraping.md +84 -84
  99. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/youtube/scraping.md +418 -418
  100. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/zillow/scraping.md +433 -433
  101. package/dist/extensions/builtin/browser/browser.md +73 -73
  102. package/dist/extensions/builtin/browser/install.md +142 -142
  103. package/dist/extensions/builtin/browser/interaction-skills/connection.md +48 -48
  104. package/dist/extensions/builtin/browser/interaction-skills/cookies.md +3 -3
  105. package/dist/extensions/builtin/browser/interaction-skills/cross-origin-iframes.md +3 -3
  106. package/dist/extensions/builtin/browser/interaction-skills/dialogs.md +64 -64
  107. package/dist/extensions/builtin/browser/interaction-skills/downloads.md +3 -3
  108. package/dist/extensions/builtin/browser/interaction-skills/drag-and-drop.md +3 -3
  109. package/dist/extensions/builtin/browser/interaction-skills/dropdowns.md +3 -3
  110. package/dist/extensions/builtin/browser/interaction-skills/iframes.md +3 -3
  111. package/dist/extensions/builtin/browser/interaction-skills/network-requests.md +3 -3
  112. package/dist/extensions/builtin/browser/interaction-skills/print-as-pdf.md +3 -3
  113. package/dist/extensions/builtin/browser/interaction-skills/profile-sync.md +90 -90
  114. package/dist/extensions/builtin/browser/interaction-skills/screenshots.md +17 -17
  115. package/dist/extensions/builtin/browser/interaction-skills/scrolling.md +3 -3
  116. package/dist/extensions/builtin/browser/interaction-skills/shadow-dom.md +3 -3
  117. package/dist/extensions/builtin/browser/interaction-skills/tabs.md +69 -69
  118. package/dist/extensions/builtin/browser/interaction-skills/uploads.md +1 -1
  119. package/dist/extensions/builtin/browser/interaction-skills/viewport.md +3 -3
  120. package/dist/extensions/builtin/browser/src/browser_harness/AGENT.md +15 -15
  121. package/dist/extensions/builtin/browser/src/browser_harness/__init__.py +8 -8
  122. package/dist/extensions/builtin/browser/src/browser_harness/_ipc.py +90 -90
  123. package/dist/extensions/builtin/browser/src/browser_harness/admin.py +722 -722
  124. package/dist/extensions/builtin/browser/src/browser_harness/daemon.py +328 -328
  125. package/dist/extensions/builtin/browser/src/browser_harness/helpers.py +396 -396
  126. package/dist/extensions/builtin/browser/src/browser_harness/run.py +103 -103
  127. package/dist/extensions/builtin/discipline/skills/brainstorming/SKILL.md +33 -33
  128. package/dist/extensions/builtin/discipline/skills/executing-plans/SKILL.md +25 -25
  129. package/dist/extensions/builtin/discipline/skills/finishing-development-branch/SKILL.md +25 -25
  130. package/dist/extensions/builtin/discipline/skills/receiving-code-review/SKILL.md +22 -22
  131. package/dist/extensions/builtin/discipline/skills/requesting-code-review/SKILL.md +31 -31
  132. package/dist/extensions/builtin/discipline/skills/systematic-debugging/SKILL.md +28 -28
  133. package/dist/extensions/builtin/discipline/skills/test-driven-development/SKILL.md +32 -32
  134. package/dist/extensions/builtin/discipline/skills/using-git-worktrees/SKILL.md +25 -25
  135. package/dist/extensions/builtin/discipline/skills/verification-before-completion/SKILL.md +27 -27
  136. package/dist/extensions/builtin/discipline/skills/writing-plans/SKILL.md +26 -26
  137. package/dist/extensions/builtin/goal/README.md +67 -67
  138. package/dist/extensions/builtin/grub/README.md +112 -112
  139. package/dist/extensions/builtin/link-world/agent-workspace/README.md +16 -16
  140. package/dist/extensions/builtin/link-world/internet-search/internet-search.md +65 -65
  141. package/dist/extensions/builtin/link-world/link-world-agent.md +82 -82
  142. package/dist/extensions/builtin/link-world/linkworld.md +313 -313
  143. package/dist/extensions/builtin/link-world/network-routing/network-routing.md +67 -67
  144. package/dist/extensions/builtin/loop/README.md +92 -92
  145. package/dist/extensions/builtin/mcp/figma-design.md +68 -68
  146. package/dist/extensions/builtin/mcp/mcp-management.md +85 -85
  147. package/dist/extensions/builtin/recap/AGENT.md +15 -15
  148. package/dist/extensions/builtin/sal/README.md +72 -72
  149. package/dist/extensions/builtin/security-audit/README.md +289 -289
  150. package/dist/extensions/builtin/team/AGENT.md +112 -112
  151. package/dist/extensions/builtin/team/TESTING.md +299 -299
  152. package/dist/extensions/builtin/token-save/README.md +56 -56
  153. package/dist/extensions/optional/AGENT.md +10 -10
  154. package/dist/modes/interactive/interactive-mode.js +36 -36
  155. package/dist/modes/interactive/theme/dark.json +85 -85
  156. package/dist/modes/interactive/theme/light.json +84 -84
  157. package/dist/modes/interactive/theme/theme-schema.json +335 -335
  158. package/dist/modes/interactive/theme/warm.json +81 -81
  159. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop.js +3 -2
  160. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-agent-loop.js +2 -1
  161. package/dist/node_modules/@pencil-agent/ai/dist/cli.js +0 -0
  162. package/docs/cc-agent-design.md +1297 -0
  163. package/docs/cc-tui-design.md +1333 -0
  164. package/docs/codex-goal-command-impl.md +1055 -1055
  165. package/docs/codex-goal-vs-grub.md +500 -500
  166. package/docs/custom-provider.md +27 -27
  167. package/docs/extensions.md +27 -27
  168. package/docs/keybindings.md +27 -27
  169. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/200/273/347/273/223.md" +250 -250
  170. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/212/245/345/221/212.md" +122 -122
  171. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210.md" +1222 -1222
  172. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210/345/256/236/347/216/260/346/212/245/345/221/212.md" +158 -158
  173. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210/345/257/271/346/257/224/345/210/206/346/236/220.md" +128 -128
  174. package/docs/loop /351/207/215/346/236/204/350/256/241/345/210/222.md" +320 -320
  175. package/docs/loop-usage-examples.md +214 -214
  176. package/docs/models.md +27 -27
  177. package/docs/nanoPencil-/345/255/246/344/271/240/350/256/241/345/210/222.md +170 -0
  178. package/docs/packages.md +27 -27
  179. package/docs/pi-design-philosophy.md +457 -457
  180. package/docs/planmode.md +1987 -1987
  181. package/docs/prompt-templates.md +27 -27
  182. package/docs/providers.md +27 -27
  183. package/docs/scan-report.md +3820 -0
  184. package/docs/sdk.md +27 -27
  185. package/docs/skills.md +27 -27
  186. package/docs/themes.md +27 -27
  187. package/docs/tui.md +27 -27
  188. package/docs//345/257/271/346/240/207Claude-Code.md +1775 -0
  189. package/docs//351/230/277/351/207/214/345/267/264/345/267/264/350/264/242/346/212/245/345/210/206/346/236/220/344/271/246.md +261 -0
  190. package/package.json +190 -190
  191. package/docs/ACP/345/215/217/350/256/256/351/233/206/346/210/220/345/274/200/345/217/221/346/226/207/346/241/243.md +0 -851
  192. package/docs/SDK-TESTING.md +0 -364
  193. package/docs/mem-core/346/212/200/346/234/257/346/226/207/346/241/243.md +0 -593
  194. package/docs/startup-performance-optimization.md +0 -301
  195. package/docs//350/256/244/347/237/245/345/234/260/345/233/276.md +0 -47
@@ -1,851 +0,0 @@
1
- # nanoPencil ACP 协议集成开发文档
2
-
3
- > **状态**:待开发
4
- >
5
- > **目标版本**:1.12.0
6
- >
7
- > **ACP 版本**:0.16.x(@agentclientprotocol/sdk)
8
- >
9
- > **相关文档**:
10
- > - ACP 官方:https://agentclientprotocol.com
11
- > - TypeScript SDK:https://agentclientprotocol.github.io/typescript-sdk
12
- > - 参考实现:[Gemini CLI ACP Agent](https://github.com/google-gemini/gemini-cli)
13
-
14
- ---
15
-
16
- ## 目录
17
-
18
- - [一、背景与动机](#一背景与动机)
19
- - [二、ACP 协议概述](#二acp-协议概述)
20
- - [三、现有架构分析](#三现有架构分析)
21
- - [四、改动方案](#四改动方案)
22
- - [五、详细设计](#五详细设计)
23
- - [六、事件映射表](#六事件映射表)
24
- - [七、文件变更总览](#七文件变更总览)
25
- - [八、实施步骤](#八实施步骤)
26
- - [九、验收标准](#九验收标准)
27
- - [十、附录](#十附录)
28
-
29
- ---
30
-
31
- ## 一、背景与动机
32
-
33
- ### 1.1 什么是 ACP
34
-
35
- ACP(Agent Client Protocol)是由 Zed 发起的开放标准,定义了代码编辑器(Client)与 AI 编码代理(Agent)之间的通信协议。基于 JSON-RPC 2.0,通过 stdin/stdout 进行双向通信。
36
-
37
- ### 1.2 为什么 nanoPencil 需要支持 ACP
38
-
39
- | 维度 | 当前状态 | 支持 ACP 后 |
40
- |------|---------|------------|
41
- | 编辑器集成 | 仅自有 RPC 协议,Pencil Desktop 专用 | 兼容 Zed、JetBrains 等所有 ACP Client |
42
- | 外部调用 | 需要了解自定义 RPC 协议 | 标准协议,零学习成本 |
43
- | 生态兼容 | 独立生态 | 与 Claude Code、Gemini CLI、Copilot 等互通 |
44
- | 维护成本 | 自维护私有协议 | 社区维护开放标准 |
45
-
46
- ### 1.3 设计原则
47
-
48
- 1. **增量集成** — ACP 作为新的运行模式,不影响现有 Interactive / Print / RPC 三种模式
49
- 2. **复用核心** — 复用 `AgentSession` 和 `createAgentSession` SDK,仅在 I/O 层适配
50
- 3. **最小改动** — 核心改动集中在新增 `modes/acp/` 目录,对现有代码改动控制在 30 行以内
51
-
52
- ---
53
-
54
- ## 二、ACP 协议概述
55
-
56
- ### 2.1 通信模型
57
-
58
- ```
59
- ┌─────────────────┐ JSON-RPC 2.0 ┌─────────────────┐
60
- │ Client (编辑器) │ ◄──── stdin/stdout ────────► │ Agent (CLI) │
61
- │ Zed / JetBrains │ │ nanoPencil │
62
- └─────────────────┘ └─────────────────┘
63
- ```
64
-
65
- - **Client → Agent**(方法调用):`initialize`、`session/new`、`session/prompt`、`session/cancel`
66
- - **Agent → Client**(通知):`session/update`(流式文本、工具调用、思考过程等)
67
- - **Agent → Client**(方法调用):`session/request_permission`(请求工具执行授权)
68
-
69
- ### 2.2 一次完整的 Prompt Turn
70
-
71
- ```
72
- Client Agent (nanoPencil)
73
- │ │
74
- │──── session/prompt (用户消息) ──────────────►│
75
- │ │── 调用 LLM
76
- │◄─── session/update (thinking) ────────────── │
77
- │◄─── session/update (agent_message_chunk) ──── │
78
- │◄─── session/update (tool_call, pending) ───── │
79
- │ │
80
- │◄─── session/request_permission ────────────── │ (可选)
81
- │──── permission response ──────────────────► │
82
- │ │── 执行工具
83
- │◄─── session/update (tool_call_update) ────── │
84
- │ │── 将结果送回 LLM
85
- │◄─── session/update (agent_message_chunk) ──── │
86
- │ │
87
- │◄─── session/prompt response (end_turn) ────── │
88
- ```
89
-
90
- ### 2.3 关键消息格式
91
-
92
- **initialize 响应**:
93
- ```json
94
- {
95
- "protocolVersion": "2025-03-26",
96
- "agentCapabilities": {
97
- "loadSession": false
98
- }
99
- }
100
- ```
101
-
102
- **session/update 通知(文本块)**:
103
- ```json
104
- {
105
- "jsonrpc": "2.0",
106
- "method": "session/update",
107
- "params": {
108
- "sessionId": "sess_abc",
109
- "update": {
110
- "sessionUpdate": "agent_message_chunk",
111
- "content": { "type": "text", "text": "好的," }
112
- }
113
- }
114
- }
115
- ```
116
-
117
- **session/update 通知(工具调用)**:
118
- ```json
119
- {
120
- "jsonrpc": "2.0",
121
- "method": "session/update",
122
- "params": {
123
- "sessionId": "sess_abc",
124
- "update": {
125
- "sessionUpdate": "tool_call",
126
- "toolCallId": "call_001",
127
- "title": "Reading file",
128
- "kind": "read",
129
- "status": "pending",
130
- "locations": [{ "path": "/project/src/main.ts" }]
131
- }
132
- }
133
- }
134
- ```
135
-
136
- **session/prompt 响应**:
137
- ```json
138
- {
139
- "jsonrpc": "2.0",
140
- "id": 2,
141
- "result": { "stopReason": "end_turn" }
142
- }
143
- ```
144
-
145
- ---
146
-
147
- ## 三、现有架构分析
148
-
149
- ### 3.1 nanoPencil 运行模式架构
150
-
151
- ```
152
- cli.ts → main.ts → parseArgs()
153
- → createAgentSession()
154
- → 模式选择:
155
- ├── Interactive (TUI)
156
- ├── Print (stdout 输出)
157
- ├── RPC (自定义 JSON Lines)
158
- └── ACP (新增 ✦)
159
- ```
160
-
161
- 所有模式共享同一个 `AgentSession` 核心,区别仅在 I/O 层。
162
-
163
- ### 3.2 核心接口
164
-
165
- **AgentSession** 提供:
166
- - `session.prompt(message, options)` — 发送用户消息并触发 Agent 循环
167
- - `session.subscribe(listener)` — 订阅 `AgentSessionEvent` 事件流
168
- - `session.abort()` — 中止当前 turn
169
- - `session.bindExtensions(options)` — 绑定扩展 UI 上下文
170
- - `session.steer(message)` / `session.followUp(message)` — 流式中追加消息
171
-
172
- **AgentSessionEvent** 事件类型:
173
- ```typescript
174
- type AgentSessionEvent =
175
- | AgentEvent // agent-core 事件
176
- | { type: "auto_compaction_start"; ... }
177
- | { type: "auto_compaction_end"; ... }
178
- | { type: "auto_retry_start"; ... }
179
- | { type: "auto_retry_end"; ... };
180
- ```
181
-
182
- **AgentEvent** 事件类型:
183
- ```typescript
184
- type AgentEvent =
185
- | { type: "agent_start" }
186
- | { type: "agent_end"; messages: AgentMessage[] }
187
- | { type: "turn_start" }
188
- | { type: "turn_end"; message: AgentMessage; toolResults: ToolResultMessage[] }
189
- | { type: "message_start"; message: AgentMessage }
190
- | { type: "message_update"; message: AgentMessage; assistantMessageEvent: AssistantMessageEvent }
191
- | { type: "message_end"; message: AgentMessage }
192
- | { type: "tool_execution_start"; toolCallId: string; toolName: string; args: any }
193
- | { type: "tool_execution_update"; toolCallId: string; toolName: string; args: any; partialResult: any }
194
- | { type: "tool_execution_end"; toolCallId: string; toolName: string; result: any; isError: boolean };
195
- ```
196
-
197
- **AssistantMessageEvent** 事件类型(在 message_update 中传递):
198
- ```typescript
199
- type AssistantMessageEvent =
200
- | { type: "text_start"; ... }
201
- | { type: "text_delta"; delta: string; ... }
202
- | { type: "text_end"; ... }
203
- | { type: "thinking_start"; ... }
204
- | { type: "thinking_delta"; delta: string; ... }
205
- | { type: "thinking_end"; ... }
206
- | { type: "toolcall_start"; ... }
207
- | { type: "toolcall_delta"; delta: string; ... }
208
- | { type: "toolcall_end"; toolCall: ToolCall; ... }
209
- | { type: "done"; reason: "stop" | "length" | "toolUse"; ... }
210
- | { type: "error"; ... };
211
- ```
212
-
213
- ### 3.3 RPC 模式参考
214
-
215
- 现有 RPC 模式 (`modes/rpc/rpc-mode.ts`) 是 ACP 模式的最佳参考:
216
-
217
- - **相同点**:stdin/stdout 双向通信、无头模式、事件流转发
218
- - **不同点**:RPC 用自定义 JSON Lines;ACP 用标准 JSON-RPC 2.0 + SDK
219
-
220
- RPC 模式核心流程:
221
- 1. `session.bindExtensions()` 绑定扩展(非 TUI 环境)
222
- 2. `session.subscribe(event => output(event))` 转发事件
223
- 3. `readline` 逐行读取 stdin → `handleCommand()` 处理命令
224
- 4. 返回 `new Promise(() => {})` 保持进程存活
225
-
226
- ACP 模式将遵循相同模式,但使用 `AgentSideConnection` + `ndJsonStream` 替代手动 readline。
227
-
228
- ---
229
-
230
- ## 四、改动方案
231
-
232
- ### 4.1 改动文件清单
233
-
234
- | 文件 | 操作 | 改动量 | 说明 |
235
- |------|------|--------|------|
236
- | `package.json` | 修改 | +1 行 | 新增 `@agentclientprotocol/sdk` 依赖 |
237
- | `cli/args.ts` | 修改 | +5 行 | 新增 `--acp` 参数 |
238
- | `main.ts` | 修改 | +10 行 | ACP 模式分支 + stdin 跳过 |
239
- | `modes/acp/acp-mode.ts` | **新增** | ~300 行 | ACP Agent 模式核心 |
240
- | `modes/index.ts` | 修改 | +1 行 | 导出 `runAcpMode` |
241
-
242
- **总计:~320 行新增,~15 行改动**
243
-
244
- ### 4.2 不变的文件
245
-
246
- 以下文件**完全不需要修改**:
247
-
248
- ```
249
- core/runtime/agent-session.ts ✓ 核心逻辑不变
250
- core/runtime/sdk.ts ✓ SDK 接口不变
251
- packages/agent-core/ ✓ agent-core 不变
252
- packages/ai/ ✓ AI 层不变
253
- modes/interactive/ ✓ 交互模式不变
254
- modes/print-mode.ts ✓ Print 模式不变
255
- modes/rpc/ ✓ RPC 模式不变
256
- core/extensions/ ✓ 扩展系统不变
257
- core/tools/ ✓ 工具系统不变
258
- ```
259
-
260
- ---
261
-
262
- ## 五、详细设计
263
-
264
- ### 5.1 依赖变更 — `package.json`
265
-
266
- 在 `dependencies` 中新增:
267
-
268
- ```json
269
- {
270
- "dependencies": {
271
- "@agentclientprotocol/sdk": "^0.16.1"
272
- }
273
- }
274
- ```
275
-
276
- ### 5.2 CLI 参数 — `cli/args.ts`
277
-
278
- 在 `Args` 接口中新增字段:
279
-
280
- ```typescript
281
- export interface Args {
282
- // ...existing fields...
283
- /** Enable ACP (Agent Client Protocol) mode for editor integration */
284
- acp?: boolean;
285
- }
286
- ```
287
-
288
- 在 `parseArgs` 函数中添加解析:
289
-
290
- ```typescript
291
- } else if (arg === "--acp") {
292
- result.acp = true;
293
- ```
294
-
295
- 在 `printHelp` 中添加说明:
296
-
297
- ```
298
- --acp Run as ACP Agent (for editor integration)
299
- ```
300
-
301
- ### 5.3 模式选择 — `main.ts`
302
-
303
- #### 5.3.1 跳过 stdin 管道读取
304
-
305
- ```typescript
306
- // 现有代码 (约第 707 行):
307
- if (parsed.mode !== "rpc") {
308
-
309
- // 改为:
310
- if (parsed.mode !== "rpc" && !parsed.acp) {
311
- ```
312
-
313
- #### 5.3.2 添加 ACP 模式分支
314
-
315
- ```typescript
316
- // 现有代码 (约第 825 行):
317
- if (mode === "rpc") {
318
- await runRpcMode(session);
319
- } else if (isInteractive) {
320
-
321
- // 改为:
322
- if (parsed.acp) {
323
- const { runAcpMode } = await import("./modes/acp/acp-mode.js");
324
- await runAcpMode(session);
325
- } else if (mode === "rpc") {
326
- await runRpcMode(session);
327
- } else if (isInteractive) {
328
- ```
329
-
330
- 使用动态 `import()` 确保不使用 ACP 模式时不加载 SDK,减少启动时间。
331
-
332
- ### 5.4 ACP Agent 模式 — `modes/acp/acp-mode.ts`
333
-
334
- 这是核心新增文件。实现 ACP `Agent` 接口,将 `AgentSession` 的事件流映射为 ACP 协议消息。
335
-
336
- #### 5.4.1 整体结构
337
-
338
- ```typescript
339
- import * as acp from "@agentclientprotocol/sdk";
340
- import { Readable, Writable } from "node:stream";
341
- import type { AgentSession } from "../../core/runtime/agent-session.js";
342
- import { VERSION } from "../../config.js";
343
-
344
- /**
345
- * NanoPencilAgent - 实现 ACP Agent 接口
346
- *
347
- * 将 nanoPencil 的 AgentSession 包装为 ACP Agent,
348
- * 通过 stdin/stdout 与 ACP Client 通信。
349
- */
350
- class NanoPencilAgent implements acp.Agent {
351
- private connection: acp.AgentSideConnection;
352
- private session: AgentSession;
353
- private activeSessions: Map<string, { abortController: AbortController | null }>;
354
-
355
- constructor(connection: acp.AgentSideConnection, session: AgentSession) { ... }
356
-
357
- async initialize(params: acp.InitializeRequest): Promise<acp.InitializeResult> { ... }
358
- async newSession(params: acp.NewSessionRequest): Promise<acp.NewSessionResult> { ... }
359
- async authenticate(params: acp.AuthenticateRequest): Promise<acp.AuthenticateResult> { ... }
360
- async prompt(params: acp.PromptRequest): Promise<acp.PromptResult> { ... }
361
- async cancel(params: acp.CancelNotification): Promise<void> { ... }
362
- async setSessionMode(params: acp.SetSessionModeRequest): Promise<acp.SetSessionModeResult> { ... }
363
- }
364
-
365
- export async function runAcpMode(session: AgentSession): Promise<never> { ... }
366
- ```
367
-
368
- #### 5.4.2 `initialize` — 协商版本和能力
369
-
370
- ```typescript
371
- async initialize(params: acp.InitializeRequest): Promise<acp.InitializeResult> {
372
- return {
373
- protocolVersion: acp.PROTOCOL_VERSION,
374
- agentCapabilities: {
375
- loadSession: false, // 暂不支持 loadSession
376
- },
377
- };
378
- }
379
- ```
380
-
381
- #### 5.4.3 `newSession` — 创建会话
382
-
383
- ```typescript
384
- async newSession(params: acp.NewSessionRequest): Promise<acp.NewSessionResult> {
385
- const sessionId = `sess-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
386
- this.activeSessions.set(sessionId, { abortController: null });
387
- return { sessionId };
388
- }
389
- ```
390
-
391
- #### 5.4.4 `prompt` — 核心交互
392
-
393
- 这是最复杂的方法,负责:
394
- 1. 从 ACP prompt 内容中提取文本
395
- 2. 订阅 `AgentSessionEvent` 并转换为 ACP `session/update`
396
- 3. 调用 `session.prompt()` 阻塞直到 turn 结束
397
- 4. 返回 `stopReason`
398
-
399
- ```typescript
400
- async prompt(params: acp.PromptRequest): Promise<acp.PromptResult> {
401
- const { sessionId, prompt } = params;
402
- const sessionState = this.activeSessions.get(sessionId);
403
- if (!sessionState) throw new Error(`Session ${sessionId} not found`);
404
-
405
- // 中止之前的 prompt(如果有)
406
- sessionState.abortController?.abort();
407
- sessionState.abortController = new AbortController();
408
-
409
- // 提取文本
410
- const userText = prompt
411
- .filter((block): block is acp.TextContent => block.type === "text")
412
- .map((block) => block.text)
413
- .join("\n");
414
-
415
- // 订阅事件并转发为 ACP session/update
416
- const unsubscribe = this.session.subscribe((event) => {
417
- this.mapEventToAcp(sessionId, event);
418
- });
419
-
420
- try {
421
- await this.session.prompt(userText, { source: "acp" });
422
- return { stopReason: "end_turn" };
423
- } catch (error) {
424
- if (sessionState.abortController.signal.aborted) {
425
- return { stopReason: "cancelled" };
426
- }
427
- return { stopReason: "error" };
428
- } finally {
429
- unsubscribe();
430
- sessionState.abortController = null;
431
- }
432
- }
433
- ```
434
-
435
- #### 5.4.5 `cancel` — 中止当前 turn
436
-
437
- ```typescript
438
- async cancel(params: acp.CancelNotification): Promise<void> {
439
- const sessionState = this.activeSessions.get(params.sessionId);
440
- if (sessionState) {
441
- sessionState.abortController?.abort();
442
- await this.session.abort();
443
- }
444
- }
445
- ```
446
-
447
- #### 5.4.6 事件映射方法
448
-
449
- ```typescript
450
- private mapEventToAcp(sessionId: string, event: AgentSessionEvent): void {
451
- switch (event.type) {
452
- case "message_update": {
453
- const sub = event.assistantMessageEvent;
454
- switch (sub.type) {
455
- case "text_delta":
456
- this.connection.sessionUpdate({
457
- sessionId,
458
- update: {
459
- sessionUpdate: "agent_message_chunk",
460
- content: { type: "text", text: sub.delta },
461
- },
462
- });
463
- break;
464
-
465
- case "thinking_delta":
466
- this.connection.sessionUpdate({
467
- sessionId,
468
- update: {
469
- sessionUpdate: "agent_message_chunk",
470
- content: { type: "thought", text: sub.delta },
471
- },
472
- });
473
- break;
474
-
475
- // toolcall_start, toolcall_end 等在 tool_execution_* 事件中处理
476
- }
477
- break;
478
- }
479
-
480
- case "tool_execution_start":
481
- this.connection.sessionUpdate({
482
- sessionId,
483
- update: {
484
- sessionUpdate: "tool_call",
485
- toolCallId: event.toolCallId,
486
- title: `${event.toolName}`,
487
- kind: this.mapToolKind(event.toolName),
488
- status: "pending",
489
- rawInput: event.args,
490
- },
491
- });
492
- break;
493
-
494
- case "tool_execution_end":
495
- this.connection.sessionUpdate({
496
- sessionId,
497
- update: {
498
- sessionUpdate: "tool_call_update",
499
- toolCallId: event.toolCallId,
500
- status: event.isError ? "errored" : "completed",
501
- content: [{
502
- type: "content",
503
- content: {
504
- type: "text",
505
- text: typeof event.result === "string"
506
- ? event.result
507
- : JSON.stringify(event.result, null, 2),
508
- },
509
- }],
510
- rawOutput: event.result,
511
- },
512
- });
513
- break;
514
-
515
- // agent_start, agent_end, turn_start, turn_end 等不需要映射
516
- }
517
- }
518
- ```
519
-
520
- #### 5.4.7 工具类型映射
521
-
522
- ACP 定义了标准化的工具 `kind`:
523
-
524
- ```typescript
525
- private mapToolKind(toolName: string): string {
526
- switch (toolName) {
527
- case "read": return "read";
528
- case "edit": return "edit";
529
- case "write": return "write";
530
- case "bash": return "command";
531
- case "grep": return "read";
532
- case "find": return "read";
533
- case "ls": return "read";
534
- default: return "other";
535
- }
536
- }
537
- ```
538
-
539
- #### 5.4.8 扩展 UI Context
540
-
541
- ACP 模式需要一个无头环境的扩展 UI Context,与 RPC 模式类似。可以从 `modes/rpc/rpc-mode.ts` 第 120-274 行的 `createExtensionUIContext()` 复制并简化:
542
-
543
- ```typescript
544
- function createAcpExtensionUIContext(): ExtensionUIContext {
545
- return {
546
- // 对话式交互 → 静默返回默认值
547
- select: async () => undefined,
548
- confirm: async () => false,
549
- input: async () => undefined,
550
- editor: async () => undefined,
551
-
552
- // 通知/状态 → 输出到 stderr(不干扰 ACP 协议的 stdout)
553
- notify(message, type) {
554
- process.stderr.write(`[${type ?? "info"}] ${message}\n`);
555
- },
556
- setStatus() {},
557
- setWorkingMessage() {},
558
- setWidget() {},
559
- setFooter() {},
560
- setHeader() {},
561
- setTitle() {},
562
- setEditorComponent() {},
563
- pasteToEditor() {},
564
- setEditorText() {},
565
- getEditorText: () => "",
566
-
567
- async custom() { return undefined as never; },
568
- onTerminalInput: () => () => {},
569
- get theme() { return theme; },
570
- getAllThemes: () => [],
571
- getTheme: () => undefined,
572
- setTheme: () => ({ success: false, error: "Theme not supported in ACP mode" }),
573
- getToolsExpanded: () => false,
574
- setToolsExpanded() {},
575
- };
576
- }
577
- ```
578
-
579
- #### 5.4.9 `runAcpMode` 入口函数
580
-
581
- ```typescript
582
- export async function runAcpMode(session: AgentSession): Promise<never> {
583
- // 绑定扩展
584
- await session.bindExtensions({
585
- uiContext: createAcpExtensionUIContext(),
586
- commandContextActions: {
587
- waitForIdle: () => session.agent.waitForIdle(),
588
- newSession: async (options) => {
589
- const success = await session.newSession(options);
590
- return { cancelled: !success };
591
- },
592
- fork: async (entryId) => {
593
- const result = await session.fork(entryId);
594
- return { cancelled: result.cancelled };
595
- },
596
- navigateTree: async (targetId, options) => {
597
- const result = await session.navigateTree(targetId, options);
598
- return { cancelled: result.cancelled };
599
- },
600
- switchSession: async (sessionPath) => {
601
- const success = await session.switchSession(sessionPath);
602
- return { cancelled: !success };
603
- },
604
- reload: async () => { await session.reload(); },
605
- },
606
- shutdownHandler: () => { process.exit(0); },
607
- onError: (err) => {
608
- process.stderr.write(
609
- `[extension_error] ${err.extensionPath}: ${err.error}\n`
610
- );
611
- },
612
- });
613
-
614
- // 建立 ACP 连接(stdin/stdout)
615
- const input = Writable.toWeb(process.stdout);
616
- const output = Readable.toWeb(process.stdin) as ReadableStream<Uint8Array>;
617
- const stream = acp.ndJsonStream(input, output);
618
-
619
- new acp.AgentSideConnection(
620
- (conn) => new NanoPencilAgent(conn, session),
621
- stream,
622
- );
623
-
624
- // 保持进程存活
625
- return new Promise(() => {});
626
- }
627
- ```
628
-
629
- ### 5.5 导出 — `modes/index.ts`
630
-
631
- 新增导出:
632
-
633
- ```typescript
634
- export { runAcpMode } from "./acp/acp-mode.js";
635
- ```
636
-
637
- ---
638
-
639
- ## 六、事件映射表
640
-
641
- ### 6.1 AgentSessionEvent → ACP session/update 完整映射
642
-
643
- | nanoPencil 事件 | 子事件 | ACP sessionUpdate 类型 | 说明 |
644
- |-----------------|--------|----------------------|------|
645
- | `message_update` | `text_delta` | `agent_message_chunk` (text) | 流式文本增量 |
646
- | `message_update` | `text_start` | — | 不需要映射 |
647
- | `message_update` | `text_end` | — | 不需要映射 |
648
- | `message_update` | `thinking_delta` | `agent_message_chunk` (thought) | 思考过程增量 |
649
- | `message_update` | `thinking_start` | — | 不需要映射 |
650
- | `message_update` | `thinking_end` | — | 不需要映射 |
651
- | `message_update` | `toolcall_start` | — | 由 `tool_execution_start` 处理 |
652
- | `message_update` | `toolcall_delta` | — | 参数流式(可忽略) |
653
- | `message_update` | `toolcall_end` | — | 由 `tool_execution_start` 处理 |
654
- | `message_update` | `done` | — | 由 prompt 返回值处理 |
655
- | `message_update` | `error` | — | 由 prompt 异常处理 |
656
- | `tool_execution_start` | — | `tool_call` (pending) | 工具开始执行 |
657
- | `tool_execution_update` | — | `tool_call_update` (partial) | 工具中间输出(可选) |
658
- | `tool_execution_end` | — | `tool_call_update` (completed/errored) | 工具执行完成 |
659
- | `agent_start` | — | — | 不需要映射 |
660
- | `agent_end` | — | — | 由 prompt 返回值处理 |
661
- | `turn_start` | — | — | 不需要映射 |
662
- | `turn_end` | — | — | 由 prompt 返回值处理 |
663
- | `message_start` | — | — | 不需要映射 |
664
- | `message_end` | — | — | 不需要映射 |
665
- | `auto_compaction_start` | — | — | 可通过 stderr 日志 |
666
- | `auto_compaction_end` | — | — | 可通过 stderr 日志 |
667
- | `auto_retry_start` | — | — | 可通过 stderr 日志 |
668
- | `auto_retry_end` | — | — | 可通过 stderr 日志 |
669
-
670
- ### 6.2 工具名称 → ACP tool kind 映射
671
-
672
- | nanoPencil 工具名 | ACP kind | 说明 |
673
- |-------------------|----------|------|
674
- | `read` | `read` | 文件读取 |
675
- | `edit` | `edit` | 文件编辑 |
676
- | `write` | `write` | 文件写入 |
677
- | `bash` | `command` | 命令执行 |
678
- | `grep` | `read` | 内容搜索 |
679
- | `find` | `read` | 文件搜索 |
680
- | `ls` | `read` | 目录列表 |
681
- | `source` | `read` | 源码分析 |
682
- | MCP 工具 | `other` | MCP 扩展工具 |
683
- | 扩展注册工具 | `other` | 扩展自定义工具 |
684
-
685
- ### 6.3 ACP stopReason 映射
686
-
687
- | nanoPencil 结果 | ACP stopReason | 条件 |
688
- |-----------------|---------------|------|
689
- | prompt 正常完成 | `end_turn` | `session.prompt()` resolve |
690
- | 用户取消 | `cancelled` | `session.abort()` 或 AbortController |
691
- | LLM 错误 | `error` | `session.prompt()` reject(非取消) |
692
-
693
- ---
694
-
695
- ## 七、文件变更总览
696
-
697
- ### 7.1 新增文件
698
-
699
- ```
700
- modes/acp/acp-mode.ts # ACP Agent 模式核心(~300 行)
701
- ```
702
-
703
- ### 7.2 修改文件
704
-
705
- ```
706
- package.json # +1 依赖
707
- cli/args.ts # +5 行(--acp 参数)
708
- main.ts # +10 行(ACP 分支 + stdin 跳过)
709
- modes/index.ts # +1 行(导出)
710
- ```
711
-
712
- ### 7.3 不变文件
713
-
714
- ```
715
- core/runtime/agent-session.ts ✓ 核心不变
716
- core/runtime/sdk.ts ✓ SDK 不变
717
- modes/interactive/ ✓ 交互模式不变
718
- modes/print-mode.ts ✓ Print 模式不变
719
- modes/rpc/ ✓ RPC 模式不变
720
- packages/agent-core/ ✓ agent-core 不变
721
- packages/ai/ ✓ AI 层不变
722
- core/extensions/ ✓ 扩展系统不变
723
- core/tools/ ✓ 工具系统不变
724
- ```
725
-
726
- ---
727
-
728
- ## 八、实施步骤
729
-
730
- ### Step 1:安装依赖
731
-
732
- ```bash
733
- npm install @agentclientprotocol/sdk
734
- ```
735
-
736
- ### Step 2:添加 --acp 参数
737
-
738
- 修改 `cli/args.ts`:
739
- - `Args` 接口新增 `acp?: boolean`
740
- - `parseArgs` 中处理 `--acp`
741
- - `printHelp` 中添加说明
742
-
743
- ### Step 3:创建 ACP 模式
744
-
745
- 新增 `modes/acp/acp-mode.ts`:
746
- 1. 实现 `NanoPencilAgent` 类(implements `acp.Agent`)
747
- 2. 实现 `createAcpExtensionUIContext()`
748
- 3. 实现 `runAcpMode(session)` 入口函数
749
- 4. 实现事件映射 `mapEventToAcp()`
750
-
751
- ### Step 4:接入主流程
752
-
753
- 修改 `main.ts`:
754
- - stdin 读取跳过 ACP 模式
755
- - 模式选择添加 ACP 分支
756
-
757
- 修改 `modes/index.ts`:
758
- - 导出 `runAcpMode`
759
-
760
- ### Step 5:构建与手动测试
761
-
762
- ```bash
763
- # 构建
764
- npm run build
765
-
766
- # 测试 ACP 模式启动
767
- echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"clientInfo":{"name":"test","version":"1.0"},"capabilities":{}}}' | node dist/cli.js --acp
768
-
769
- # 预期输出(stdout):
770
- # {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-03-26","agentCapabilities":{"loadSession":false}}}
771
- ```
772
-
773
- ### Step 6:端到端测试
774
-
775
- 使用 ACP Client 进行端到端验证:
776
-
777
- ```bash
778
- # 方式 1:使用 Zed 编辑器
779
- # 在 Zed 的 Agent 设置中添加 nanoPencil:
780
- # Command: nanopencil --acp
781
-
782
- # 方式 2:使用 ACP SDK 自带的 ClientSideConnection 编写测试客户端
783
- ```
784
-
785
- ---
786
-
787
- ## 九、验收标准
788
-
789
- | 编号 | 验收项 | 验证方法 |
790
- |------|--------|----------|
791
- | AC-1 | `nanopencil --acp` 启动后等待 stdin | 手动运行,进程不退出 |
792
- | AC-2 | 发送 `initialize` 收到正确响应 | echo JSON-RPC → stdin,检查 stdout |
793
- | AC-3 | 发送 `session/new` 返回 `sessionId` | echo JSON-RPC → stdin |
794
- | AC-4 | 发送 `session/prompt` 后收到流式 `session/update` | 观察 stdout 逐条 JSON-RPC 通知 |
795
- | AC-5 | 文本流式输出为 `agent_message_chunk` (text) | 检查 `sessionUpdate` 字段 |
796
- | AC-6 | 思考过程输出为 `agent_message_chunk` (thought) | 使用 thinking 模型测试 |
797
- | AC-7 | 工具调用输出 `tool_call` (pending) + `tool_call_update` (completed) | Agent 执行工具时观察 |
798
- | AC-8 | Turn 结束时 `session/prompt` 响应包含 `stopReason: "end_turn"` | 检查 JSON-RPC 响应 |
799
- | AC-9 | 发送 `session/cancel` 后 turn 中止 | 长 prompt 期间发送 cancel |
800
- | AC-10 | 现有 Interactive / Print / RPC 模式不受影响 | 分别运行三种模式验证 |
801
- | AC-11 | `npm run build` 编译通过 | CI 构建 |
802
- | AC-12 | 扩展系统在 ACP 模式下正常加载 | 观察 stderr 日志 |
803
-
804
- ---
805
-
806
- ## 十、附录
807
-
808
- ### 附录 A:ACP 协议与 nanoPencil RPC 对比
809
-
810
- | 维度 | nanoPencil RPC | ACP |
811
- |------|---------------|-----|
812
- | 协议标准 | 自定义 JSON Lines | JSON-RPC 2.0 开放标准 |
813
- | SDK 支持 | 自实现 | `@agentclientprotocol/sdk` |
814
- | 请求格式 | `{ type, id?, ... }` | `{ jsonrpc: "2.0", method, params, id }` |
815
- | 响应格式 | `{ type: "response", command, success }` | `{ jsonrpc: "2.0", result/error, id }` |
816
- | 事件格式 | 原始 `AgentSessionEvent` | `session/update` 通知 |
817
- | Client 兼容 | Pencil Desktop 专用 | Zed、JetBrains 等通用 |
818
- | 功能丰富度 | 完整(模型切换、compaction 等) | 基础 prompt/cancel |
819
- | 扩展 UI | 通过 `extension_ui_request` | 不支持(需自定义扩展) |
820
-
821
- > RPC 模式保留用于 Pencil Desktop 深度集成,ACP 模式用于通用编辑器集成。两者共存。
822
-
823
- ### 附录 B:已知 ACP 兼容编辑器
824
-
825
- | 编辑器 | ACP Client 支持 | 状态 |
826
- |--------|----------------|------|
827
- | Zed | 原生支持 | 已发布 |
828
- | JetBrains IDEs | 原生支持 | 已发布 |
829
- | VS Code | 通过扩展 | 社区支持 |
830
- | Cursor | 通过扩展 | 社区支持 |
831
-
832
- ### 附录 C:已知 ACP Agent
833
-
834
- | Agent | 启动命令 | 说明 |
835
- |-------|---------|------|
836
- | Claude Code | `claude --acp` | Anthropic |
837
- | Gemini CLI | `gemini --acp` | Google |
838
- | GitHub Copilot | `github-copilot --acp` | GitHub |
839
- | Codex CLI | `codex --acp` | OpenAI |
840
- | Goose | `goose --acp` | Square |
841
- | **nanoPencil** | **`nanopencil --acp`** | **本项目** |
842
-
843
- ### 附录 D:后续演进方向
844
-
845
- 1. **loadSession 支持** — 实现 ACP `session/load`,复用 nanoPencil 的 SessionManager
846
- 2. **权限请求** — 对 bash/edit/write 工具通过 `requestPermission` 请求用户授权
847
- 3. **Plan 支持** — 将 plan-mode 扩展的计划步骤映射为 ACP plan update
848
- 4. **Slash Commands** — 通过 ACP `available_commands_update` 广播可用命令
849
- 5. **Session Modes** — 映射 nanoPencil 的 thinking level 为 ACP session mode
850
- 6. **文件系统集成** — 实现 ACP 的 `fs/readTextFile` / `fs/writeTextFile`,使用 Client 的文件系统
851
- 7. **终端集成** — 实现 ACP 的 `terminal/*` 方法,使用 Client 的终端执行 bash