@pencil-agent/nano-pencil 2.0.1 → 2.0.2
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 +267 -267
- package/dist/build-meta.json +3 -3
- package/dist/core/export-html/AGENT.md +11 -11
- package/dist/core/export-html/template.css +971 -971
- package/dist/core/export-html/template.html +54 -54
- package/dist/core/model/custom-providers.js +1 -1
- package/dist/core/model-registry.js +5 -5
- package/dist/extensions/builtin/AGENT.md +115 -115
- package/dist/extensions/builtin/browser/AGENT.md +17 -17
- package/dist/extensions/builtin/browser/agent-workspace/agent_helpers.py +12 -12
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/amazon/product-search.md +198 -198
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/archive-org/scraping.md +341 -341
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv/scraping.md +311 -311
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv-bulk/scraping.md +333 -333
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/atlas/overview.md +70 -70
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/booking-com/scraping.md +578 -578
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/capterra/scraping.md +440 -440
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/centilebrain/generate-estimates.md +110 -110
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coingecko/scraping.md +325 -325
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coinmarketcap/scraping.md +463 -463
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coursera/scraping.md +360 -360
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/craigslist/scraping.md +390 -390
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/crossref/scraping.md +568 -568
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/dev-to/scraping.md +323 -323
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/duckduckgo/scraping.md +349 -349
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/ebay/scraping.md +435 -435
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/etsy/scraping.md +506 -506
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/eventbrite/scraping.md +363 -363
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/expedia/automation.md +168 -168
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/groups.md +236 -236
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/pages.md +295 -295
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/framer/editor.md +108 -108
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/fred/scraping.md +493 -493
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/g2/scraping.md +580 -580
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/genius/scraping.md +511 -511
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/repo-actions.md +65 -65
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/scraping.md +184 -184
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/glassdoor/scraping.md +543 -543
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gmail/compose.md +122 -122
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/goodreads/scraping.md +461 -461
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gutenberg/scraping.md +383 -383
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/hackernews/scraping.md +243 -243
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/howlongtobeat/scraping.md +473 -473
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/imdb/scraping.md +271 -271
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/itch-io/scraping.md +436 -436
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/job-boards/indeed-glassdoor.md +1021 -1021
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/letterboxd/scraping.md +349 -349
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/linkedin/invitation-manager.md +109 -109
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/loom/folder-enumeration.md +170 -170
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/macrotrends/scraping.md +537 -537
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/article-hydration.md +120 -120
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/scraping.md +414 -414
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/metacritic/scraping.md +477 -477
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/musicbrainz/scraping.md +478 -478
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/nasa/scraping.md +339 -339
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/news-aggregation/multi-source.md +205 -205
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/open-library/scraping.md +472 -472
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openalex/scraping.md +470 -470
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openstreetmap/scraping.md +490 -490
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/package-registries/npm-pypi.md +478 -478
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/polymarket/scraping.md +234 -234
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/producthunt/scraping.md +307 -307
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/pubmed/scraping.md +421 -421
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/quora/scraping.md +364 -364
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rawg/scraping.md +352 -352
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/reddit/scraping.md +124 -124
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rest-countries/scraping.md +233 -233
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/sec-edgar/scraping.md +361 -361
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/README.md +36 -36
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/embedded-apps.md +72 -72
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/knowledge-base.md +109 -109
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/polaris-inputs.md +137 -137
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/soundcloud/scraping.md +362 -362
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/spotify/scraping.md +339 -339
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/stackoverflow/scraping.md +435 -435
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/steam/scraping.md +575 -575
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/substack/scraping.md +338 -338
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/thetechgeeks/pricing.md +52 -52
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tiktok/upload.md +107 -107
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tradingview/scraping.md +309 -309
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trello/boards-and-lists.md +88 -88
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trustpilot/scraping.md +375 -375
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/walmart/scraping.md +444 -444
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wayback-machine/scraping.md +306 -306
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/weather/scraping.md +398 -398
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wellfound/scraping.md +596 -596
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/world-bank/scraping.md +356 -356
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/xiaohongshu/scraping.md +84 -84
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/youtube/scraping.md +418 -418
- package/dist/extensions/builtin/browser/agent-workspace/domain-skills/zillow/scraping.md +433 -433
- package/dist/extensions/builtin/browser/browser.md +73 -73
- package/dist/extensions/builtin/browser/install.md +142 -142
- package/dist/extensions/builtin/browser/interaction-skills/connection.md +48 -48
- package/dist/extensions/builtin/browser/interaction-skills/cookies.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/cross-origin-iframes.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/dialogs.md +64 -64
- package/dist/extensions/builtin/browser/interaction-skills/downloads.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/drag-and-drop.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/dropdowns.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/iframes.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/network-requests.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/print-as-pdf.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/profile-sync.md +90 -90
- package/dist/extensions/builtin/browser/interaction-skills/screenshots.md +17 -17
- package/dist/extensions/builtin/browser/interaction-skills/scrolling.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/shadow-dom.md +3 -3
- package/dist/extensions/builtin/browser/interaction-skills/tabs.md +69 -69
- package/dist/extensions/builtin/browser/interaction-skills/uploads.md +1 -1
- package/dist/extensions/builtin/browser/interaction-skills/viewport.md +3 -3
- package/dist/extensions/builtin/browser/src/browser_harness/AGENT.md +15 -15
- package/dist/extensions/builtin/browser/src/browser_harness/__init__.py +8 -8
- package/dist/extensions/builtin/browser/src/browser_harness/_ipc.py +90 -90
- package/dist/extensions/builtin/browser/src/browser_harness/admin.py +722 -722
- package/dist/extensions/builtin/browser/src/browser_harness/daemon.py +328 -328
- package/dist/extensions/builtin/browser/src/browser_harness/helpers.py +396 -396
- package/dist/extensions/builtin/browser/src/browser_harness/run.py +103 -103
- package/dist/extensions/builtin/discipline/skills/brainstorming/SKILL.md +33 -33
- package/dist/extensions/builtin/discipline/skills/executing-plans/SKILL.md +25 -25
- package/dist/extensions/builtin/discipline/skills/finishing-development-branch/SKILL.md +25 -25
- package/dist/extensions/builtin/discipline/skills/receiving-code-review/SKILL.md +22 -22
- package/dist/extensions/builtin/discipline/skills/requesting-code-review/SKILL.md +31 -31
- package/dist/extensions/builtin/discipline/skills/systematic-debugging/SKILL.md +28 -28
- package/dist/extensions/builtin/discipline/skills/test-driven-development/SKILL.md +32 -32
- package/dist/extensions/builtin/discipline/skills/using-git-worktrees/SKILL.md +25 -25
- package/dist/extensions/builtin/discipline/skills/verification-before-completion/SKILL.md +27 -27
- package/dist/extensions/builtin/discipline/skills/writing-plans/SKILL.md +26 -26
- package/dist/extensions/builtin/goal/README.md +67 -67
- package/dist/extensions/builtin/grub/README.md +112 -112
- package/dist/extensions/builtin/link-world/agent-workspace/README.md +16 -16
- package/dist/extensions/builtin/link-world/internet-search/internet-search.md +65 -65
- package/dist/extensions/builtin/link-world/link-world-agent.md +82 -82
- package/dist/extensions/builtin/link-world/linkworld.md +313 -313
- package/dist/extensions/builtin/link-world/network-routing/network-routing.md +67 -67
- package/dist/extensions/builtin/loop/README.md +92 -92
- package/dist/extensions/builtin/mcp/figma-design.md +68 -68
- package/dist/extensions/builtin/mcp/mcp-management.md +85 -85
- package/dist/extensions/builtin/recap/AGENT.md +15 -15
- package/dist/extensions/builtin/sal/README.md +72 -72
- package/dist/extensions/builtin/security-audit/README.md +289 -289
- package/dist/extensions/builtin/team/AGENT.md +112 -112
- package/dist/extensions/builtin/team/TESTING.md +299 -299
- package/dist/extensions/builtin/token-save/README.md +56 -56
- package/dist/extensions/optional/AGENT.md +10 -10
- package/dist/modes/interactive/controllers/input-submit-controller.js +2 -2
- package/dist/modes/interactive/controllers/stream-render-controller.js +2 -2
- package/dist/modes/interactive/interactive-mode.js +19 -19
- package/dist/modes/interactive/theme/dark.json +85 -85
- package/dist/modes/interactive/theme/light.json +84 -84
- package/dist/modes/interactive/theme/theme-schema.json +335 -335
- package/dist/modes/interactive/theme/warm.json +81 -81
- package/dist/node_modules/@pencil-agent/ai/dist/cli.js +0 -0
- package/dist/node_modules/@pencil-agent/ai/dist/models.generated.js +1 -1
- 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 +851 -0
- package/docs/SDK-TESTING.md +364 -0
- package/docs/codex-goal-command-impl.md +1055 -1055
- package/docs/codex-goal-vs-grub.md +500 -500
- package/docs/custom-provider.md +27 -27
- package/docs/extensions.md +27 -27
- package/docs/keybindings.md +27 -27
- package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/200/273/347/273/223.md" +250 -250
- package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/212/245/345/221/212.md" +122 -122
- package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210.md" +1222 -1222
- 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
- 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
- package/docs/loop /351/207/215/346/236/204/350/256/241/345/210/222.md" +320 -320
- package/docs/loop-usage-examples.md +214 -214
- package/docs/mem-core/346/212/200/346/234/257/346/226/207/346/241/243.md +593 -0
- package/docs/models.md +27 -27
- package/docs/packages.md +27 -27
- package/docs/pi-design-philosophy.md +457 -457
- package/docs/planmode.md +1987 -1987
- package/docs/prompt-templates.md +27 -27
- package/docs/providers.md +27 -27
- package/docs/sdk.md +27 -27
- package/docs/skills.md +27 -27
- package/docs/startup-performance-optimization.md +301 -0
- package/docs/themes.md +27 -27
- package/docs/tui.md +27 -27
- package/docs//350/256/244/347/237/245/345/234/260/345/233/276.md +47 -0
- package/package.json +190 -190
- package/docs/cc-agent-design.md +0 -1297
- package/docs/cc-tui-design.md +0 -1333
- package/docs/nanoPencil-/345/255/246/344/271/240/350/256/241/345/210/222.md +0 -170
- package/docs/scan-report.md +0 -3820
- package/docs//345/257/271/346/240/207Claude-Code.md +0 -1775
- 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 +0 -261
package/docs/scan-report.md
DELETED
|
@@ -1,3820 +0,0 @@
|
|
|
1
|
-
# nanoPencil vs Claude Code — 代码扫描报告
|
|
2
|
-
|
|
3
|
-
> 自动扫描:每 30 分钟对照 CC 源码逐模块检查,记录缺陷与改进建议。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 2026-06-12 — Task 系统全面扫描
|
|
8
|
-
|
|
9
|
-
扫描范围:`extensions/builtin/task/` 全部文件 + `modes/interactive/components/task-status-panel.ts`
|
|
10
|
-
|
|
11
|
-
### 1. task-store.ts — 并发与数据完整性
|
|
12
|
-
|
|
13
|
-
| 严重度 | 发现 |
|
|
14
|
-
|--------|------|
|
|
15
|
-
| **CRITICAL** | **无文件锁。** CC 使用 `proper-lockfile`(30 次重试退避)序列化跨进程并发写入。nanoPencil 无任何锁机制。两个并发 `createTask` 可能读到相同的 `findHighestTaskId`,产生重复 ID,后写覆盖前写。 |
|
|
16
|
-
| **WARNING** | **无 `updateTaskUnsafe` 变体。** CC 区分 locked/unlocked 更新路径以避免级联操作死锁(如 `deleteTask` 持有列表锁时调用 `updateTask`)。nanoPencil 的 `deleteTask` 调用 `updateTask` 会重新从磁盘读取——竞争条件下可能丢失中间写入。 |
|
|
17
|
-
| **INFO** | **`writeHighWaterMark` 非原子。** CC 同样用普通 `writeFile`,行为一致。但 HWM 写入和 `deleteTask` 中的 `unlink` 不在同一个临界区,崩溃时可能出现 HWM 已更新但文件未删除。 |
|
|
18
|
-
| **INFO** | **`listTasks` 是 O(N) readFile。** 两者都 readdir + N×readFile,无分页或缓存。持平。 |
|
|
19
|
-
|
|
20
|
-
### 2. TaskCreateTool
|
|
21
|
-
|
|
22
|
-
| 严重度 | 发现 |
|
|
23
|
-
|--------|------|
|
|
24
|
-
| **CRITICAL** | **缺少 `executeTaskCreatedHooks`。** CC 在创建后运行生命周期钩子,如果任何阻塞钩子失败则回滚(删除任务)。nanoPencil 无钩子系统。 |
|
|
25
|
-
| **WARNING** | **无 auto-expand UI 信号。** CC 创建任务时调用 `context.setAppState({ expandedView: 'tasks' })` 自动展开面板。nanoPencil 不会自动打开面板。 |
|
|
26
|
-
| **INFO** | 无 `isConcurrencySafe` / `shouldDefer` / `isReadOnly` 注解。CC 特有的工具元数据,取决于 agent 框架是否需要。 |
|
|
27
|
-
|
|
28
|
-
### 3. TaskUpdateTool
|
|
29
|
-
|
|
30
|
-
| 严重度 | 发现 |
|
|
31
|
-
|--------|------|
|
|
32
|
-
| **CRITICAL** | **缺少 `executeTaskCompletedHooks`。** CC 运行完成钩子并在钩子失败时阻止状态变更。nanoPencil 无条件应用更新。 |
|
|
33
|
-
| **WARNING** | **缺少 teammate 自动 owner 分配。** CC 在 swarm 模式下移动到 `in_progress` 时自动设置 `owner = getAgentName()`。 |
|
|
34
|
-
| **WARNING** | **缺少 teammate 邮箱通知。** CC 在 owner 变更时调用 `writeToMailbox`。 |
|
|
35
|
-
| **WARNING** | **验证提示仅文本。** CC 返回结构化 `verificationNudgeNeeded: boolean`,nanoPencil 嵌入为文本字符串。 |
|
|
36
|
-
|
|
37
|
-
### 4. TaskListTool
|
|
38
|
-
|
|
39
|
-
| 严重度 | 发现 |
|
|
40
|
-
|--------|------|
|
|
41
|
-
| **INFO** | 功能等价。过滤 `_internal` 元数据,解析已完成的阻塞者,输出格式一致。 |
|
|
42
|
-
|
|
43
|
-
### 5. TaskGetTool
|
|
44
|
-
|
|
45
|
-
| 严重度 | 发现 |
|
|
46
|
-
|--------|------|
|
|
47
|
-
| **INFO** | 功能等价。CC 有 Zod schema 验证和旧状态迁移(`open` → `pending`),nanoPencil 做基础属性检查。遗留数据可能返回 `null`。 |
|
|
48
|
-
|
|
49
|
-
### 6. TaskStopTool / TaskOutputTool
|
|
50
|
-
|
|
51
|
-
| 严重度 | 发现 |
|
|
52
|
-
|--------|------|
|
|
53
|
-
| **INFO** | nanoPencil 特有工具,CC 无直接等价物。实现正确。 |
|
|
54
|
-
|
|
55
|
-
### 7. task-status-panel.ts — TUI 组件
|
|
56
|
-
|
|
57
|
-
| 严重度 | 发现 |
|
|
58
|
-
|--------|------|
|
|
59
|
-
| **WARNING** | **无 `RECENT_COMPLETED_TTL_MS`(30s)逻辑。** CC 的 `TaskListV2` 追踪任务完成时间,30s 内保持视觉突出。nanoPencil 对所有已完成任务一视同仁。 |
|
|
60
|
-
| **WARNING** | **无 teammate 颜色/活动显示。** CC 显示每个 teammate 的颜色和实时活动描述。 |
|
|
61
|
-
| **INFO** | **已有 5s auto-hide。** nanoPencil 已实现全部完成后 5 秒自动清理,与 CC 一致。 |
|
|
62
|
-
|
|
63
|
-
### 8. useTasksV2 / TasksV2Store(nanoPencil 缺失)
|
|
64
|
-
|
|
65
|
-
| 严重度 | 发现 |
|
|
66
|
-
|--------|------|
|
|
67
|
-
| **CRITICAL** | **无响应式数据层。** CC 的 `TasksV2Store` 单例使用 `fs.watch` + `onTasksUpdated` 信号 + 5s 轮询兜底 + 防抖驱动 UI。nanoPencil 仅有进程内信号,无文件监听、无轮询。外部进程(子 agent)修改 task 文件时面板不会更新。 |
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
### 汇总
|
|
72
|
-
|
|
73
|
-
| 严重度 | 数量 |
|
|
74
|
-
|--------|------|
|
|
75
|
-
| CRITICAL | 4(无文件锁、缺创建钩子、缺完成钩子、无响应式数据层) |
|
|
76
|
-
| WARNING | 6(无 updateTaskUnsafe、无 auto-expand、无 teammate 特性×2、无 recency 追踪、无 auto-hide) |
|
|
77
|
-
| INFO | 6 |
|
|
78
|
-
|
|
79
|
-
**优先修复项:**
|
|
80
|
-
1. 添加文件级锁(proper-lockfile 或类似方案)到 `createTask` 和 `updateTask`
|
|
81
|
-
2. 实现 task 创建/完成事件的钩子执行管线
|
|
82
|
-
3. 添加 `fs.watch` + 轮询兜底以支持跨进程变更通知
|
|
83
|
-
4. 移植 CC 的 30s recency 追踪逻辑
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## 2026-06-12 — ToolExecutionComponent 渲染系统扫描
|
|
88
|
-
|
|
89
|
-
扫描范围:`modes/interactive/components/tool-execution.ts` + `diff.ts` + `visual-truncate.ts`
|
|
90
|
-
|
|
91
|
-
### 架构对比
|
|
92
|
-
|
|
93
|
-
CC 使用 React 组件树 + 每个 Tool 独立的 `UI.tsx` 模块,渲染分为 `renderToolUseMessage` / `renderToolResultMessage` / `renderToolUseErrorMessage`。nanoPencil 使用单体 `ToolExecutionComponent`(886 行)通过大 switch 处理所有内置工具,自定义工具走 `renderCall/renderResult`。设计合理但结构不同。
|
|
94
|
-
|
|
95
|
-
### 1. Read 工具
|
|
96
|
-
|
|
97
|
-
| 严重度 | 发现 |
|
|
98
|
-
|--------|------|
|
|
99
|
-
| **INFO** | 功能等价。两者都显示路径+行范围,折叠截断 10 行,有语法高亮。CC 用 `FilePathLink`(可点击),nanoPencil 用下划线样式。 |
|
|
100
|
-
|
|
101
|
-
### 2. Write 工具
|
|
102
|
-
|
|
103
|
-
| 严重度 | 发现 |
|
|
104
|
-
|--------|------|
|
|
105
|
-
| **HIGH** | **缺少 write-over-existing-file 的 diff 渲染。** CC 区分 create vs update,对覆盖已有文件显示结构化 diff(`FileEditToolUpdatedMessage`)。nanoPencil 始终显示内容预览,覆盖场景下用户看不到改了什么。 |
|
|
106
|
-
| **INFO** | 两者都显示前 10 行 + 语法高亮 + 行数统计。 |
|
|
107
|
-
|
|
108
|
-
### 3. Edit 工具
|
|
109
|
-
|
|
110
|
-
| 严重度 | 发现 |
|
|
111
|
-
|--------|------|
|
|
112
|
-
| **MEDIUM** | **diff 无语法高亮和行号。** CC 使用 Rust NAPI `ColorDiff` 模块生成带语法高亮的结构化 diff + gutter 行号。nanoPencil 的 `renderDiff` 是纯着色文本 + word-level diff,无语法高亮、无行号。 |
|
|
113
|
-
| **MEDIUM** | **不支持 `replace_all` 和 `edits[]`(hashline edits)。** CC 的 edit 工具支持批量编辑,nanoPencil 仅支持单次 oldText/newText 替换。 |
|
|
114
|
-
| **INFO** | `computeEditDiff` 异步预览 + `setArgsComplete` 触发时机正确。edit 的 args 完整性检测逻辑合理。 |
|
|
115
|
-
|
|
116
|
-
### 4. Bash 工具
|
|
117
|
-
|
|
118
|
-
| 严重度 | 发现 |
|
|
119
|
-
|--------|------|
|
|
120
|
-
| **LOW** | **无 `sed -i` 命令检测。** CC 检测 sed 原地编辑命令并渲染为文件编辑 diff。nanoPencil 统一按 bash 输出处理。 |
|
|
121
|
-
| **LOW** | **无后台任务支持(ctrl+b)。** CC 支持 bash 后台执行,nanoPencil 无此功能。 |
|
|
122
|
-
| **INFO** | `truncateToVisualLines` 实现正确,5 行预览 + 展开/折叠逻辑与 CC 等价。超时显示、截断警告都已覆盖。 |
|
|
123
|
-
|
|
124
|
-
### 5. Grep/Glob/Find/ls
|
|
125
|
-
|
|
126
|
-
| 严重度 | 发现 |
|
|
127
|
-
|--------|------|
|
|
128
|
-
| **MEDIUM** | **Grep 输出无模式区分。** CC 支持三种输出模式(`content`/`files_with_matches`/`count`)各有专属渲染。nanoPencil 统一按原始文本处理。 |
|
|
129
|
-
| **INFO** | 截断逻辑(15-20 行)与 CC 一致。entry/result limit 警告已覆盖。 |
|
|
130
|
-
|
|
131
|
-
### 6. Diff 渲染(diff.ts)
|
|
132
|
-
|
|
133
|
-
| 严重度 | 发现 |
|
|
134
|
-
|--------|------|
|
|
135
|
-
| **MEDIUM** | **无 diff 内语法高亮。** CC 的 `StructuredDiff.tsx` 在 diff hunk 内做语法高亮 + gutter 行号 + `WeakMap` 渲染缓存。nanoPencil 154 行的 `diff.ts` 做行级 + word-level diff,纯着色文本。 |
|
|
136
|
-
| **INFO** | word-level diff(`diffWords`)实现正确,inverse 样式标记变更 token。 |
|
|
137
|
-
|
|
138
|
-
### 7. 图片处理
|
|
139
|
-
|
|
140
|
-
| 严重度 | 发现 |
|
|
141
|
-
|--------|------|
|
|
142
|
-
| **INFO** | Kitty 协议转换(非 PNG → PNG)+ `imageFallback` 降级逻辑完整,与 CC 等价。 |
|
|
143
|
-
|
|
144
|
-
### 8. 流式部分更新
|
|
145
|
-
|
|
146
|
-
| 严重度 | 发现 |
|
|
147
|
-
|--------|------|
|
|
148
|
-
| **INFO** | `WriteHighlightCache` 增量语法高亮缓存设计高效。前 50 行全量刷新 + 后续行单行高亮,平衡了性能和正确性。 |
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
### 汇总
|
|
153
|
-
|
|
154
|
-
| 严重度 | 数量 |
|
|
155
|
-
|--------|------|
|
|
156
|
-
| HIGH | 1(write 覆盖文件无 diff) |
|
|
157
|
-
| MEDIUM | 3(diff 无语法高亮、不支持 replace_all/edits[]、grep 无模式区分) |
|
|
158
|
-
| LOW | 2(sed -i 检测、后台任务) |
|
|
159
|
-
| INFO | 6 |
|
|
160
|
-
|
|
161
|
-
**优先修复项:**
|
|
162
|
-
1. Write 覆盖已有文件时显示 diff 而非内容预览
|
|
163
|
-
2. Diff 渲染增加语法高亮和行号
|
|
164
|
-
3. Edit 工具支持 `replace_all` 和 `edits[]` 批量编辑
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## 2026-06-12 — Slash Command 系统扫描
|
|
169
|
-
|
|
170
|
-
扫描范围:`core/slash-commands.ts` + `slash-command-catalog.ts` + `modes/interactive/controllers/slash-dispatcher-controller.ts` + `modes/interactive/slash-command-arguments.ts`
|
|
171
|
-
|
|
172
|
-
### 1. 命令注册与发现
|
|
173
|
-
|
|
174
|
-
| 严重度 | 发现 |
|
|
175
|
-
|--------|------|
|
|
176
|
-
| **MEDIUM** | **无 `aliases` 支持。** CC 支持命令别名快捷方式,nanoPencil 无此功能。 |
|
|
177
|
-
| **MEDIUM** | **无 `isEnabled`/`availability`/`isHidden` 字段。** CC 支持功能开关、权限过滤、隐藏命令。nanoPencil 的内置命令类型缺少这些元数据。 |
|
|
178
|
-
| **INFO** | `buildSessionSlashCommands()` 合并内置、扩展、prompt 模板、skills 的逻辑正确。扩展命令名与内置命令冲突检测已覆盖。 |
|
|
179
|
-
|
|
180
|
-
### 2. 命令解析
|
|
181
|
-
|
|
182
|
-
| 严重度 | 发现 |
|
|
183
|
-
|--------|------|
|
|
184
|
-
| **MEDIUM** | **无集中式解析器。** CC 有专用 `parseSlashCommand()` 产出 `{ commandName, args, isMcp }`。nanoPencil 在 dispatcher 中内联 `text.indexOf(" ")` + 各 handler 手动 `text.slice(N).trim()` 硬编码偏移量,脆弱且重复。 |
|
|
185
|
-
| **LOW** | **不支持 MCP 命令语法。** CC 支持 `/tool (MCP) args` 格式,nanoPencil 无此解析。 |
|
|
186
|
-
|
|
187
|
-
### 3. 命令执行与错误处理
|
|
188
|
-
|
|
189
|
-
| 严重度 | 发现 |
|
|
190
|
-
|--------|------|
|
|
191
|
-
| **HIGH** | **Dispatcher 无 try/catch。** `SlashDispatcherController.execute()` 第 84-106 行无任何错误边界。async handler(如 `/model`、`/mcp`)失败时产生未处理的 promise rejection,可能导致会话崩溃。 |
|
|
192
|
-
| **INFO** | CC 有完整的执行管线:abort controller、进度消息、遥测事件、`MalformedCommandError`/`AbortError` 类型异常。nanoPencil 均缺失但非阻塞。 |
|
|
193
|
-
|
|
194
|
-
### 4. 自动补全
|
|
195
|
-
|
|
196
|
-
| 严重度 | 发现 |
|
|
197
|
-
|--------|------|
|
|
198
|
-
| **LOW** | **无模糊匹配。** CC 使用 Fuse.js 加权多键匹配(name/parts/aliases/description)。nanoPencil 仅 `startsWith` 前缀匹配。 |
|
|
199
|
-
| **LOW** | **无使用频率排序。** CC 根据历史使用频率提升排序。 |
|
|
200
|
-
| **INFO** | 7 个内置命令的参数补全(model/thinking/mcp/language/persona 等)实现正确。 |
|
|
201
|
-
|
|
202
|
-
### 5. 帮助文本生成
|
|
203
|
-
|
|
204
|
-
| 严重度 | 发现 |
|
|
205
|
-
|--------|------|
|
|
206
|
-
| **MEDIUM** | **无 `/help` 命令。** 用户无法通过 slash 命令查看帮助。CC 有专用 `help` 命令渲染完整命令参考。 |
|
|
207
|
-
| **INFO** | `getLocalizedCommands()` 提供 i18n 支持 + 8 个分类标签,`formatSlashCommandDescription()` 渲染正确。 |
|
|
208
|
-
|
|
209
|
-
### 6. 缺失命令 vs CC
|
|
210
|
-
|
|
211
|
-
CC 有 ~90+ 命令,nanoPencil 有 35 个。显著缺失:`help`、`clear`、`config`、`cost`、`diff`、`doctor`、`review`、`commit`、`init`、`permissions`、`hooks`、`effort`、`resume`(会话选择器)、`vim`、`theme`、`color`、`files`、`branch`、`plan`、`skills`、`plugin`、`tasks`、`stats` 等。
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
### 汇总
|
|
216
|
-
|
|
217
|
-
| 严重度 | 数量 |
|
|
218
|
-
|--------|------|
|
|
219
|
-
| HIGH | 1(dispatcher 无 try/catch) |
|
|
220
|
-
| MEDIUM | 4(无 aliases、无 isEnabled/availability、无集中式解析器、无 /help) |
|
|
221
|
-
| LOW | 3(无 MCP 语法、无模糊匹配、无使用频率排序) |
|
|
222
|
-
| INFO | 3 |
|
|
223
|
-
|
|
224
|
-
**优先修复项:**
|
|
225
|
-
1. Dispatcher 添加 try/catch 错误边界,防止 async handler 崩溃会话
|
|
226
|
-
2. 实现集中式 `parseSlashCommand()` 解析器
|
|
227
|
-
3. 添加 `/help` 命令
|
|
228
|
-
|
|
229
|
-
---
|
|
230
|
-
|
|
231
|
-
## 2026-06-12 — Persona 系统扫描
|
|
232
|
-
|
|
233
|
-
扫描范围:`core/persona/persona-manager.ts` + `core/platform/config/resource-loader.ts` + `modes/interactive/interactive-mode.ts`(persona 切换逻辑)+ `extensions/builtin/presence/`
|
|
234
|
-
|
|
235
|
-
> 注:CC 无 persona/身份管理系统,此系统为 nanoPencil 原创扩展。以下对比侧重实现质量和缺陷检查。
|
|
236
|
-
|
|
237
|
-
### 1. PersonaManager CRUD
|
|
238
|
-
|
|
239
|
-
| 严重度 | 发现 |
|
|
240
|
-
|--------|------|
|
|
241
|
-
| **INFO** | **`"general"` 死代码。** `normalizePersonaId` 第 23 行 `if (!trimmed) return "general"` 永远不会执行,因为 `getActivePersonaId` 在无状态时返回 `"vex"`。注释说 "returning to general" 但实际行为是返回 "vex"。 |
|
|
242
|
-
| **INFO** | **`listPersonas` 重复 normalize。** 已经 normalize 的目录名会被再次 normalize,如果目录名含被剥离字符(如 `.`)可能导致误判。防御性但可能困惑用户。 |
|
|
243
|
-
| **INFO** | `writeFileSync` 用于所有写入,单线程 REPL 循环下无并发风险,但无原子写入(tmp+rename)。 |
|
|
244
|
-
|
|
245
|
-
### 2. Resource Loader 完整性保护
|
|
246
|
-
|
|
247
|
-
| 严重度 | 发现 |
|
|
248
|
-
|--------|------|
|
|
249
|
-
| **MEDIUM** | **默认 persona `vex` 绕过完整性保护。** 条件 `if (activePersonaId && pencilPathToLoad === personaPencilPath)` — 当 `activePersonaId` 是 `"vex"` 且用户创建了 `vex/` 目录时,persona PENCIL.md 会被加载但**不附加完整性保护块**,因为 `"vex"` 是 truthy 值通过了检查。应额外排除默认 persona ID。 |
|
|
250
|
-
| **INFO** | `seenPaths` 去重防止重复包含。persona PENCIL.md 优先级高于全局 `.PENCIL.md` 的逻辑正确。 |
|
|
251
|
-
|
|
252
|
-
### 3. Persona 切换
|
|
253
|
-
|
|
254
|
-
| 严重度 | 发现 |
|
|
255
|
-
|--------|------|
|
|
256
|
-
| **MEDIUM** | **无 env var 清理机制。** `NANOPENCIL_JUST_SWITCHED_PERSONA` 标志设置后无过期/清理。会话崩溃时该标志在 `process.env` 中永久残留。 |
|
|
257
|
-
| **INFO** | `switchPersona` fork 会话 + 设置 4 个 env var + reload 的流程设计扎实。`applyPersonaFromSessionIfAny` 在会话恢复时正确重新应用 persona。 |
|
|
258
|
-
|
|
259
|
-
### 4. Presence / 问候扩展
|
|
260
|
-
|
|
261
|
-
| 严重度 | 发现 |
|
|
262
|
-
|--------|------|
|
|
263
|
-
| **INFO** | **无缺陷。** 从 PENCIL.md `## Presence` 读取 persona 特定的开场/空闲问候行,回退到 i18n 默认值。错误处理一致 try/catch + 静默降级。定时器在会话关闭时正确清理。30s 防抖防止刷屏。 |
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
### 汇总
|
|
268
|
-
|
|
269
|
-
| 严重度 | 数量 |
|
|
270
|
-
|--------|------|
|
|
271
|
-
| MEDIUM | 2(默认 persona 绕过完整性保护、env var 无清理) |
|
|
272
|
-
| INFO | 5(死代码、重复 normalize、非原子写入、切换流程扎实、presence 无缺陷) |
|
|
273
|
-
|
|
274
|
-
**优先修复项:**
|
|
275
|
-
1. `resource-loader.ts` 完整性保护条件排除默认 persona ID(`vex`)
|
|
276
|
-
2. `NANOPENCIL_JUST_SWITCHED_PERSONA` 标志添加消费后清理
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
## 2026-06-12 — Extensions Host 系统扫描
|
|
281
|
-
|
|
282
|
-
扫描范围:`core/extensions-host/` 全部文件(loader.ts、runner.ts、types.ts)
|
|
283
|
-
|
|
284
|
-
### 1. 扩展加载与发现
|
|
285
|
-
|
|
286
|
-
| 严重度 | 发现 |
|
|
287
|
-
|--------|------|
|
|
288
|
-
| **INFO** | 4 层发现机制(项目级、全局、显式配置路径、npm opt-in)设计合理。`jiti` 加载 TS/JS 扩展,`Promise.all` 并行加载,错误收集不中断。 |
|
|
289
|
-
| **INFO** | CC 有完整的 marketplace 生态(注册表、依赖解析、版本控制、黑名单、自动更新)。nanoPencil 缺失这些但非阻塞——当前规模不需要 marketplace。 |
|
|
290
|
-
|
|
291
|
-
### 2. 工具注册与冲突解决
|
|
292
|
-
|
|
293
|
-
| 严重度 | 发现 |
|
|
294
|
-
|--------|------|
|
|
295
|
-
| **MEDIUM** | **工具名冲突静默丢弃。** `getAllRegisteredTools()` 使用先注册先得策略,第二个同名工具被静默跳过,无诊断警告。命令/快捷键冲突有警告,工具冲突没有。`runner.ts` 第 388-394 行。 |
|
|
296
|
-
| **INFO** | CC 不向插件暴露工具注册 API,避免了此问题。nanoPencil 的工具注册是更丰富的 API 表面的一部分。 |
|
|
297
|
-
|
|
298
|
-
### 3. Hook 执行管线
|
|
299
|
-
|
|
300
|
-
| 严重度 | 发现 |
|
|
301
|
-
|--------|------|
|
|
302
|
-
| **HIGH** | **`emitToolCall` 缺少 try/catch。** `runner.ts` 第 922 行的 `emitToolCall` 未包裹错误处理,handler 抛异常会向上冒泡未处理。其他 emit 方法(`emitToolResult`、`emitContext`)都有 catch。**不一致且有崩溃风险。** |
|
|
303
|
-
| **MEDIUM** | **缺失 ~8 个生命周期事件。** CC 有 `SubagentStart`、`SubagentStop`、`TaskCreated`、`TaskCompleted`、`FileChanged`、`CwdChanged`、`WorktreeCreate`、`WorktreeRemove` 等,nanoPencil 均缺失。 |
|
|
304
|
-
| **INFO** | 其他 hook 路径的错误隔离良好:每个 handler 独立 try/catch,错误路由到 `emitError()` 不中断管线。`before_agent_start` 有 1500ms 超时 + 限频警告。 |
|
|
305
|
-
|
|
306
|
-
### 4. MCP 服务器集成
|
|
307
|
-
|
|
308
|
-
| 严重度 | 发现 |
|
|
309
|
-
|--------|------|
|
|
310
|
-
| **INFO** | nanoPencil 将 MCP 委托给内置扩展(`builtin/mcp`),扩展宿主无直接 MCP 感知。分离干净但意味着无 MCP 特定的错误处理或生命周期管理。CC 将 MCP 深度集成到插件生命周期中。 |
|
|
311
|
-
|
|
312
|
-
### 5. 扩展 API 表面
|
|
313
|
-
|
|
314
|
-
| 严重度 | 发现 |
|
|
315
|
-
|--------|------|
|
|
316
|
-
| **INFO** | nanoPencil 的 API 显著比 CC 更丰富:事件订阅、工具/命令/快捷键/标志注册、UI 上下文(对话框、组件、编辑器)、会话管理、模型控制、Provider 注册、一次性 LLM 补全、OAuth。CC 通过声明式 manifest 补偿。 |
|
|
317
|
-
|
|
318
|
-
### 6. 扩展崩溃错误处理
|
|
319
|
-
|
|
320
|
-
| 严重度 | 发现 |
|
|
321
|
-
|--------|------|
|
|
322
|
-
| **MEDIUM** | **`loadExtensionFromFactory` 无错误处理。** `loader.ts` 第 331 行,factory 抛异常直接传播,而 `loadExtension`(第 302 行)有 catch。不一致。 |
|
|
323
|
-
| **INFO** | 其他路径错误隔离良好:加载时 try/catch 收集错误、hook handler 独立 catch、`wrapToolWithExtensions` 捕获 tool_call/tool_result 钩子错误。无沙箱/进程隔离。 |
|
|
324
|
-
|
|
325
|
-
### 7. 其他缺失
|
|
326
|
-
|
|
327
|
-
| 严重度 | 发现 |
|
|
328
|
-
|--------|------|
|
|
329
|
-
| **LOW** | **无热重载机制。** CC 有 `clearPluginHookCache()` + `setupPluginHookHotReload()`。nanoPencil 需手动触发 reload。 |
|
|
330
|
-
| **LOW** | **无循环依赖检测。** CC 有 `dependencyResolver.ts` 处理依赖图。 |
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
### 汇总
|
|
335
|
-
|
|
336
|
-
| 严重度 | 数量 |
|
|
337
|
-
|--------|------|
|
|
338
|
-
| HIGH | 1(`emitToolCall` 缺 try/catch) |
|
|
339
|
-
| MEDIUM | 3(工具名冲突静默、缺失生命周期事件、factory 加载无 catch) |
|
|
340
|
-
| LOW | 2(无热重载、无循环依赖检测) |
|
|
341
|
-
| INFO | 5 |
|
|
342
|
-
|
|
343
|
-
**优先修复项:**
|
|
344
|
-
1. `emitToolCall` 添加 try/catch 错误隔离(与其他 emit 方法一致)
|
|
345
|
-
2. 工具名冲突添加警告日志
|
|
346
|
-
3. `loadExtensionFromFactory` 添加 try/catch
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
|
|
350
|
-
## 2026-06-12 — Interactive Mode Controller 扫描
|
|
351
|
-
|
|
352
|
-
扫描范围:`modes/interactive/interactive-mode.ts` + `modes/interactive/controllers/` 全部控制器
|
|
353
|
-
|
|
354
|
-
### 1. 并发保护
|
|
355
|
-
|
|
356
|
-
| 严重度 | 发现 |
|
|
357
|
-
|--------|------|
|
|
358
|
-
| **HIGH** | **无 QueryGuard 等价机制。** CC 使用 3 状态 `QueryGuard`(`idle`→`dispatching`→`running`)+ 代计数器防止双重提交。nanoPencil 的主循环是简单的 `while(true)` + `await session.prompt()`,`onSubmit` 回调与主循环之间存在竞态窗口。`isStreaming()` 检查部分缓解但不完全——在 idle 检查和 `await handleIdleSubmit` 之间仍有事件交错的可能。 |
|
|
359
|
-
|
|
360
|
-
### 2. Compaction 期间消息队列
|
|
361
|
-
|
|
362
|
-
| 严重度 | 发现 |
|
|
363
|
-
|--------|------|
|
|
364
|
-
| **MEDIUM** | **无优先级队列。** CC 使用统一优先级队列(`now`/`next`/`later`),确保系统通知不饿死用户输入。nanoPencil 的 `compactionQueuedMessages` 是纯 FIFO 数组,无优先级区分。 |
|
|
365
|
-
| **LOW** | **无可恢复的编辑器缓冲。** CC 的 `popAllEditable` 允许通过快捷键将排队消息恢复到编辑器。nanoPencil 缺失此功能。 |
|
|
366
|
-
|
|
367
|
-
### 3. 中止/中断处理
|
|
368
|
-
|
|
369
|
-
| 严重度 | 发现 |
|
|
370
|
-
|--------|------|
|
|
371
|
-
| **MEDIUM** | **Ctrl+C 静默丢弃输入。** `InterruptController.handleCtrlC` 单击时清空编辑器,用户已输入的文本被丢弃且无法撤销。CC 保留输入缓冲区。 |
|
|
372
|
-
| **LOW** | **无后台 agent kill 支持。** CC 有 `chat:killAgents` 双击确认停止后台子 agent。nanoPencil 缺失。 |
|
|
373
|
-
| **INFO** | 中断优先级排序(loader abort > streaming abort > bash abort > bash-mode exit > double-tap tree/fork)设计合理。Ctrl+Z 挂起已实现。 |
|
|
374
|
-
|
|
375
|
-
### 4. 错误恢复
|
|
376
|
-
|
|
377
|
-
| 严重度 | 发现 |
|
|
378
|
-
|--------|------|
|
|
379
|
-
| **MEDIUM** | **无 auto-compaction 熔断器。** CC 有 `MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3`,连续失败后停止重试。nanoPencil 无此限制,反复 compaction 失败会无限浪费 API 调用。 |
|
|
380
|
-
| **MEDIUM** | **无瞬态错误重试。** 429 限流、网络超时等错误直接展示给用户,无自动重试逻辑。CC 有 auto-retry with exponential backoff。 |
|
|
381
|
-
| **INFO** | `handleIdleSubmit` 捕获 `promptAfterRender` 错误并回滚 optimistic message,`flushCompactionQueue` 在错误时恢复排队消息。基本错误恢复已覆盖。 |
|
|
382
|
-
|
|
383
|
-
### 5. 优雅关闭
|
|
384
|
-
|
|
385
|
-
| 严重度 | 发现 |
|
|
386
|
-
|--------|------|
|
|
387
|
-
| **MEDIUM** | **无 failsafe 定时器。** `shutdown()` 向扩展发送 `session_shutdown`(5s 超时),但如果扩展 handler 永久阻塞,进程会挂起。CC 有 failsafe timer + SIGKILL 兜底。 |
|
|
388
|
-
| **LOW** | **无终端模式清理。** CC 退出时清理 alt-screen、Kitty keyboard、focus reporting、bracketed paste。nanoPencil 仅 drain 输入 1s + `process.exit(0)`,异常退出时终端状态可能泄漏。 |
|
|
389
|
-
|
|
390
|
-
### 6. Optimistic UI
|
|
391
|
-
|
|
392
|
-
| 严重度 | 发现 |
|
|
393
|
-
|--------|------|
|
|
394
|
-
| **LOW** | **仅回滚首个 optimistic message。** 多次快速提交时如果第二个失败,只回滚第一个。CC 的 React 状态协调处理更干净。 |
|
|
395
|
-
| **INFO** | `StreamRenderController.message_start` 正确检测并去重 optimistic messages。回滚逻辑 `rollbackFirstOptimisticUserMessageIfMatches` 实现正确。 |
|
|
396
|
-
|
|
397
|
-
### 7. 会话生命周期
|
|
398
|
-
|
|
399
|
-
| 严重度 | 发现 |
|
|
400
|
-
|--------|------|
|
|
401
|
-
| **LOW** | **无会话后台/前台切换支持。** CC 有 `useSessionBackgrounding` 处理前后台转换。nanoPencil 缺失。 |
|
|
402
|
-
| **INFO** | `SessionManager` 持久化会话状态,`session_shutdown` 事件正确传播到扩展。主循环结构合理。 |
|
|
403
|
-
|
|
404
|
-
---
|
|
405
|
-
|
|
406
|
-
### 汇总
|
|
407
|
-
|
|
408
|
-
| 严重度 | 数量 |
|
|
409
|
-
|--------|------|
|
|
410
|
-
| HIGH | 1(无 QueryGuard 并发保护) |
|
|
411
|
-
| MEDIUM | 5(无优先级队列、Ctrl+C 丢弃输入、无 compaction 熔断器、无瞬态重试、无 failsafe 定时器) |
|
|
412
|
-
| LOW | 4(无可恢复缓冲、无 agent kill、无终端清理、optimistic 回滚不完整) |
|
|
413
|
-
| INFO | 3 |
|
|
414
|
-
|
|
415
|
-
**优先修复项:**
|
|
416
|
-
1. 实现 QueryGuard 或等价的提交互斥机制,防止双重提交竞态
|
|
417
|
-
2. Auto-compaction 添加熔断器(连续失败 N 次后停止)
|
|
418
|
-
3. Ctrl+C 单击时保留编辑器输入缓冲区
|
|
419
|
-
|
|
420
|
-
---
|
|
421
|
-
|
|
422
|
-
## 2026-06-12 — Stream Render Controller 扫描
|
|
423
|
-
|
|
424
|
-
扫描范围:`modes/interactive/controllers/stream-render-controller.ts` + `streaming-preview.ts` + `task-status-panel.ts`
|
|
425
|
-
|
|
426
|
-
### 1. 事件处理完整性
|
|
427
|
-
|
|
428
|
-
| 严重度 | 发现 |
|
|
429
|
-
|--------|------|
|
|
430
|
-
| **INFO** | 所有核心生命周期事件已覆盖:`agent_start`、`message_start/update/end`、`tool_execution_start/update/end`、`agent_end`、`auto_compaction_start/end`、`auto_retry_start/end`、`sub_agent_*`。 |
|
|
431
|
-
| **INFO** | CC 有 `StreamingToolExecutor` 并行处理单条消息中的多个 tool call。nanoPencil 通过 `has()` 守卫顺序处理,行为一致。 |
|
|
432
|
-
| **LOW** | **无 `tool_execution_cancel` 事件处理。** CC 可取消执行中的工具。nanoPencil 仅通过 abort 路径(`agent_end` + `stopReason === "aborted"`)处理。 |
|
|
433
|
-
|
|
434
|
-
### 2. 内存泄漏与清理
|
|
435
|
-
|
|
436
|
-
| 严重度 | 发现 |
|
|
437
|
-
|--------|------|
|
|
438
|
-
| **MEDIUM** | **`taskUpdateUnsubscribe` 未在 `agent_end` 清理。** `onTasksUpdated` 订阅在 `agent_start` 创建但 `agent_end` 不取消。闭包(捕获 `state`、`ui`、`statusContainer`)跨 turn 存活。`agent_start` 的 `?.()` 取消前一个订阅可缓解顺序场景,但 crash/force-quit 时泄漏。 |
|
|
439
|
-
| **INFO** | `agent_end` 清理全面:停止 loader、移除 streamingComponent、清空 pendingTools、移除 sub-agent/plan/task/streaming-preview 面板、clearAttachments。 |
|
|
440
|
-
|
|
441
|
-
### 3. Auto-Compaction/Retry 覆盖层
|
|
442
|
-
|
|
443
|
-
| 严重度 | 发现 |
|
|
444
|
-
|--------|------|
|
|
445
|
-
| **MEDIUM** | **`auto_compaction_start` 清空整个 `statusContainer`。** 这会同时销毁 loader、streaming preview 和 task panel。CC 的 React 声明式渲染是替换而非销毁。nanoPencil 的命令式模型中 task panel 在 compaction 期间丢失,直到下次 `onTasksUpdated` 回调才重建。 |
|
|
446
|
-
| **INFO** | Escape handler 交换逻辑正确:保存当前 handler → 安装 abort handler → 恢复。`agent_start` 处理 retry handler 残留的边界情况也已覆盖。 |
|
|
447
|
-
|
|
448
|
-
### 4. Sub-Agent 面板集成
|
|
449
|
-
|
|
450
|
-
| 严重度 | 发现 |
|
|
451
|
-
|--------|------|
|
|
452
|
-
| **INFO** | 正确。sub-agent 事件内联处理,懒创建面板,`agent_end` 正确清理面板和状态。 |
|
|
453
|
-
|
|
454
|
-
### 5. Task Status Panel(新增)
|
|
455
|
-
|
|
456
|
-
| 严重度 | 发现 |
|
|
457
|
-
|--------|------|
|
|
458
|
-
| **LOW** | **Auto-hide 定时器有微竞态。** 全部完成后 5 秒定时器重置 task list,但如果新 `agent_start` 在定时器前触发,旧定时器可能在新 turn 中触发。`resetTaskList` 是幂等的所以无数据损坏,但面板可能闪烁。 |
|
|
459
|
-
| **INFO** | 信号订阅 + 磁盘重读 + 优先级排序 + 自动隐藏逻辑整体正确。 |
|
|
460
|
-
|
|
461
|
-
### 6. Streaming Preview(新增)
|
|
462
|
-
|
|
463
|
-
| 严重度 | 发现 |
|
|
464
|
-
|--------|------|
|
|
465
|
-
| **INFO** | 正确且最小化。`message_update` 时更新最后 3 行文本,`agent_end` 清理。无内部状态,无泄漏风险。 |
|
|
466
|
-
|
|
467
|
-
### 7. 对比 CC Spinner/StatusLine
|
|
468
|
-
|
|
469
|
-
| 严重度 | 发现 |
|
|
470
|
-
|--------|------|
|
|
471
|
-
| **INFO** | CC 的 `Spinner.tsx` 有多种模式(thinking/streaming/tool)、shimmer 动画、teammate 树、token 计数器、预算追踪。nanoPencil 的 `PencilLoader` 是单一工作指示器。预期差异——TUI 架构限制。 |
|
|
472
|
-
| **INFO** | CC 的 `StatusLine.tsx` 显示模型名、工作区、成本、上下文用量、限流、vim 模式等。nanoPencil 通过 `surface.showStatus()` 临时显示。功能差距但非正确性问题。 |
|
|
473
|
-
|
|
474
|
-
---
|
|
475
|
-
|
|
476
|
-
### 汇总
|
|
477
|
-
|
|
478
|
-
| 严重度 | 数量 |
|
|
479
|
-
|--------|------|
|
|
480
|
-
| MEDIUM | 2(taskUpdateUnsubscribe 未清理、compaction 清空 statusContainer) |
|
|
481
|
-
| LOW | 2(tool_execution_cancel 缺失、auto-hide 定时器微竞态) |
|
|
482
|
-
| INFO | 7 |
|
|
483
|
-
|
|
484
|
-
**优先修复项:**
|
|
485
|
-
1. `agent_end` 中添加 `this.taskUpdateUnsubscribe?.()` 清理订阅
|
|
486
|
-
2. `auto_compaction_start` 保留 task panel 和 streaming preview,仅替换 loader
|
|
487
|
-
|
|
488
|
-
---
|
|
489
|
-
|
|
490
|
-
## 2026-06-12 — Autocomplete 系统扫描
|
|
491
|
-
|
|
492
|
-
扫描范围:`core/lib/tui/src/autocomplete.ts` + `modes/interactive/slash-command-arguments.ts` + TUI editor 集成
|
|
493
|
-
|
|
494
|
-
### 1. Slash 命令名自动补全
|
|
495
|
-
|
|
496
|
-
| 严重度 | 发现 |
|
|
497
|
-
|--------|------|
|
|
498
|
-
| **MEDIUM** | **自定义 fuzzy 质量不如 Fuse.js。** CC 用 Fuse.js + 缓存索引 + 多级排序(exact name > exact alias > prefix name > prefix alias > fuzzy)。nanoPencil 用自定义 `weightedFuzzyFilter`,无 alias 支持、无 part-key 分割(如 `com-mit`)、无缓存索引。每次按键重新过滤全量命令列表。 |
|
|
499
|
-
| **MEDIUM** | **`weightedFuzzyFilter` 有 bug 风险。** 字段不匹配时 `Infinity` 被计入分数,但只要任一字段匹配就 `hasMatch = true`——可能产生仅 description 匹配而 name 不匹配的反直觉结果。 |
|
|
500
|
-
| **INFO** | 命令名匹配权重(name 3、description 0.5)合理。结果上限 10 个可接受。 |
|
|
501
|
-
|
|
502
|
-
### 2. Slash 命令参数自动补全
|
|
503
|
-
|
|
504
|
-
| 严重度 | 发现 |
|
|
505
|
-
|--------|------|
|
|
506
|
-
| **INFO** | **比 CC 更丰富。** nanoPencil 有 7 个命令的专用参数补全(model/thinking/agent-loop/mcp/language/persona/login),CC 无等价模块。结构清晰,token-index 上下文正确。 |
|
|
507
|
-
| **LOW** | **纯前缀匹配。** `/model son` 不匹配 `claude-sonnet`。CC 的命令建议用 Fuse.js fuzzy 匹配。 |
|
|
508
|
-
|
|
509
|
-
### 3. 文件路径自动补全
|
|
510
|
-
|
|
511
|
-
| 严重度 | 发现 |
|
|
512
|
-
|--------|------|
|
|
513
|
-
| **HIGH** | **同步 I/O 阻塞事件循环。** `readdirSync` 和 `spawnSync(fd)` 每次 Tab/@ 触发都阻塞 TUI 线程。CC 用 async git + Rust native nucleo 索引 + 渐进式查询 + 后台刷新。 |
|
|
514
|
-
| **HIGH** | **无 LRU 缓存。** 每次 Tab 都重新读目录。CC 有 500 条目 5 分钟 TTL 的 LRU 缓存。 |
|
|
515
|
-
| **MEDIUM** | **`readdirSync` 路径无 `.gitignore` 过滤。** `fd` 路径默认遵守 `.gitignore` 但 `fd` 可能未安装。CC 有完整的 `.ignore`/`.rgignore` 模式支持。 |
|
|
516
|
-
| **MEDIUM** | **无后台刷新。** CC 有 5 节流的后台缓存刷新 + 渐进式索引构建。nanoPencil 无此机制。 |
|
|
517
|
-
| **INFO** | 评分逻辑(exact > prefix > substring > path-substring)合理。结果上限 20 个。 |
|
|
518
|
-
|
|
519
|
-
### 4. 补全显示与键盘导航
|
|
520
|
-
|
|
521
|
-
| 严重度 | 发现 |
|
|
522
|
-
|--------|------|
|
|
523
|
-
| **LOW** | **无 shell history ghost text。** CC 有 `!` 前缀的历史命令内联预览。nanoPencil 缺失。 |
|
|
524
|
-
| **LOW** | **无 MCP resource/agent 建议。** CC 的统一弹出框包含 MCP 资源和 agent 建议。 |
|
|
525
|
-
| **LOW** | **选择状态不跨重建保留。** CC 有 `getPreservedSelection` 在建议列表变化时保留选中项。nanoPencil 每次重置。 |
|
|
526
|
-
| **INFO** | `CombinedAutocompleteProvider` 同时提供 `getSuggestions` 和 `applyCompletion`,TUI editor 层处理弹出框渲染和键盘绑定。 |
|
|
527
|
-
|
|
528
|
-
---
|
|
529
|
-
|
|
530
|
-
### 汇总
|
|
531
|
-
|
|
532
|
-
| 严重度 | 数量 |
|
|
533
|
-
|--------|------|
|
|
534
|
-
| HIGH | 2(同步 I/O 阻塞、无 LRU 缓存) |
|
|
535
|
-
| MEDIUM | 3(fuzzy 质量、fuzzy bug 风险、无 gitignore 过滤) |
|
|
536
|
-
| LOW | 4(纯前缀匹配、无 shell history、无 MCP 建议、选择不保留) |
|
|
537
|
-
| INFO | 3 |
|
|
538
|
-
|
|
539
|
-
**优先修复项:**
|
|
540
|
-
1. 将 `spawnSync(fd)` 替换为异步调用 + LRU 缓存(500 条目 5 分钟 TTL)
|
|
541
|
-
2. `readdirSync` 路径添加 `.gitignore` 过滤
|
|
542
|
-
3. `weightedFuzzyFilter` 修复 Infinity 分数 bug,或迁移到 Fuse.js
|
|
543
|
-
|
|
544
|
-
---
|
|
545
|
-
|
|
546
|
-
## 2026-06-12 — Session Management 扫描
|
|
547
|
-
|
|
548
|
-
扫描范围:`core/runtime/session-manager.ts` + `modes/interactive/controllers/session-lifecycle-controller.ts`
|
|
549
|
-
|
|
550
|
-
### 1. 会话创建与持久化
|
|
551
|
-
|
|
552
|
-
| 严重度 | 发现 |
|
|
553
|
-
|--------|------|
|
|
554
|
-
| **HIGH** | **无原子写入。** `appendFileSync` 直接写目标文件,crash 时可能产生部分 JSON 行导致损坏。CC 用 `ftruncate` 做安全原地编辑。`_rewriteFile()` 用 `writeFileSync` 全量覆盖,无 tmp+rename 模式,中断时会话被毁。 |
|
|
555
|
-
| **MEDIUM** | **无预写备份。** CC 有 tombstone + 50MB 大小守卫。nanoPencil 的 `_rewriteFile()` 直接覆盖,无备份。 |
|
|
556
|
-
| **INFO** | JSONL 格式 + 会话头(id/timestamp/cwd/parentSession)设计合理。`parseSessionEntries` 跳过格式错误行可缓解数据丢失但不防止静默损坏。 |
|
|
557
|
-
|
|
558
|
-
### 2. 会话恢复
|
|
559
|
-
|
|
560
|
-
| 严重度 | 发现 |
|
|
561
|
-
|--------|------|
|
|
562
|
-
| **HIGH** | **状态恢复严重不完整。** CC 恢复:文件历史、归属状态、成本追踪、worktree 上下文、todo 列表、agent 类型、模型覆盖。nanoPencil 仅恢复 model + thinking level。 |
|
|
563
|
-
| **MEDIUM** | **不恢复 agent 类型。** CC 跨会话持久化和恢复 agent 类型,nanoPencil 缺失。 |
|
|
564
|
-
| **MEDIUM** | **不恢复 todo/task 列表。** CC 从会话恢复 todo 状态,nanoPencil 的 task 系统与会话管理无集成。 |
|
|
565
|
-
| **INFO** | `switchSession` 正确断开 agent → 加载文件 → 重建 SessionContext → 恢复 model/thinking → 重连。流程合理但恢复内容不足。 |
|
|
566
|
-
|
|
567
|
-
### 3. 会话 Fork/Branch
|
|
568
|
-
|
|
569
|
-
| 严重度 | 发现 |
|
|
570
|
-
|--------|------|
|
|
571
|
-
| **INFO** | **比 CC 更丰富。** 基于树的 append-only 分支结构 + leaf 指针 + branch summary + 标签保留,设计优秀。CC 用更简单的扁平转录。 |
|
|
572
|
-
| **LOW** | **无内容替换记录转发。** CC fork 时复制 `ContentReplacementRecord`,nanoPencil 不追踪内容替换。 |
|
|
573
|
-
| **LOW** | **无会话所有权守卫。** CC fork 时剥离 worktree session 防止误删,nanoPencil 无此保护。 |
|
|
574
|
-
|
|
575
|
-
### 4. 会话列表/切换
|
|
576
|
-
|
|
577
|
-
| 严重度 | 发现 |
|
|
578
|
-
|--------|------|
|
|
579
|
-
| **MEDIUM** | **列表性能差。** `listAll()` 解析所有 JSONL 文件提取元数据。CC 用 head/tail 读取 + 缓存。大量会话时 nanoPencil 会很慢。 |
|
|
580
|
-
| **MEDIUM** | **无会话删除。** `SessionManager` 无 `delete()` 方法。CC 支持 tombstone 删除。 |
|
|
581
|
-
|
|
582
|
-
### 5. 会话清理
|
|
583
|
-
|
|
584
|
-
| 严重度 | 发现 |
|
|
585
|
-
|--------|------|
|
|
586
|
-
| **HIGH** | **完全缺失。** 无 TTL、无修剪、无最大会话数限制。会话无限增长,磁盘用量失控。CC 有 `cleanupPeriodDays` 设置 + 退出时清理。 |
|
|
587
|
-
|
|
588
|
-
### 6. 消息存储格式
|
|
589
|
-
|
|
590
|
-
| 严重度 | 发现 |
|
|
591
|
-
|--------|------|
|
|
592
|
-
| **INFO** | 类型化条目系统(`SessionMessageEntry`、`CustomMessageEntry`、`CompactionEntry`、`BranchSummaryEntry`、`ModelChangeEntry`、`ThinkingLevelChangeEntry`、`LabelEntry`)结构优秀,比 CC 更类型化。 |
|
|
593
|
-
|
|
594
|
-
### 7. 错误恢复
|
|
595
|
-
|
|
596
|
-
| 严重度 | 发现 |
|
|
597
|
-
|--------|------|
|
|
598
|
-
| **MEDIUM** | **部分损坏时静默丢失数据。** 单个损坏行导致 `loadEntriesFromFile` 丢失该行之后的所有条目。CC 用分段读取处理更优雅。 |
|
|
599
|
-
| **MEDIUM** | **`_rewriteFile` 无备份。** 覆盖前不保存旧版本,中断时会话永久丢失。 |
|
|
600
|
-
|
|
601
|
-
---
|
|
602
|
-
|
|
603
|
-
### 汇总
|
|
604
|
-
|
|
605
|
-
| 严重度 | 数量 |
|
|
606
|
-
|--------|------|
|
|
607
|
-
| HIGH | 3(无原子写入、状态恢复不完整、无会话清理) |
|
|
608
|
-
| MEDIUM | 6(无预写备份、不恢复 agent/todo、列表性能差、无删除、损坏数据丢失、rewrite 无备份) |
|
|
609
|
-
| LOW | 2(无内容替换转发、无所有权守卫) |
|
|
610
|
-
| INFO | 2 |
|
|
611
|
-
|
|
612
|
-
**优先修复项:**
|
|
613
|
-
1. `_rewriteFile` 改用 tmp+rename 原子写入
|
|
614
|
-
2. 添加会话清理机制(TTL + 最大数量)
|
|
615
|
-
3. 扩展状态恢复范围(至少恢复 task 列表和 agent 类型)
|
|
616
|
-
|
|
617
|
-
---
|
|
618
|
-
|
|
619
|
-
## 2026-06-12 — Provider/Model 系统扫描
|
|
620
|
-
|
|
621
|
-
扫描范围:`core/model-registry.ts` + `core/runtime/model-controller.ts` + `core/lib/ai/src/stream.ts` + `core/runtime/retry-coordinator.ts`
|
|
622
|
-
|
|
623
|
-
> 注:nanoPencil 支持 20+ provider,CC 仅支持 4 个 Anthropic 变体。以下侧重高可用性和缺陷检查。
|
|
624
|
-
|
|
625
|
-
### 1. Provider 注册与发现
|
|
626
|
-
|
|
627
|
-
| 严重度 | 发现 |
|
|
628
|
-
|--------|------|
|
|
629
|
-
| **INFO** | **比 CC 更丰富。** `ModelRegistry` 合并内置模型 + `models.json` 自定义 + 远程 `/models` 端点发现。支持懒加载 provider、发现缓存 TTL、自定义协议(Anthropic-compat、OpenAI-compat)。CC 仅 env-var 选择单一 provider。 |
|
|
630
|
-
|
|
631
|
-
### 2. 模型选择与切换
|
|
632
|
-
|
|
633
|
-
| 严重度 | 发现 |
|
|
634
|
-
|--------|------|
|
|
635
|
-
| **MEDIUM** | **无 529 过载自动降级。** CC 在连续 3 次 529 后自动从 Opus 降级到 Sonnet。nanoPencil 无等价机制——过载时直接报错给用户。 |
|
|
636
|
-
| **INFO** | 模型循环(`cycleModel` 前后切换)、thinking level 耦合、OAuth token 验证、glob 模式过滤——比 CC 更精细。 |
|
|
637
|
-
|
|
638
|
-
### 3. 重试逻辑与限流处理
|
|
639
|
-
|
|
640
|
-
| 严重度 | 发现 |
|
|
641
|
-
|--------|------|
|
|
642
|
-
| **MEDIUM** | **重试次数过低。** Stream 层 3 次重试 vs CC 的 10 次。瞬态 provider 中断时 nanoPencil 过早放弃。 |
|
|
643
|
-
| **MEDIUM** | **无 529 专项处理。** CC 将 529(overloaded)作为独立错误类 + 连续计数 + 模型降级。nanoPencil 的 `retry-coordinator.ts` regex 仅匹配消息文本中的 "overloaded",不处理原始状态码 529。 |
|
|
644
|
-
| **MEDIUM** | **`Retry-After` 仅从错误消息文本解析。** CC 从 HTTP 响应头通过 SDK 读取。provider 实现中未解析实际 HTTP 头。 |
|
|
645
|
-
| **LOW** | **无持久/无人值守重试模式。** CC 支持长时间运行会话的无限重试(5 分钟退避上限 + 6 小时重置上限)。 |
|
|
646
|
-
| **LOW** | **无 `x-should-retry` 头支持。** OpenRouter、Vercel Gateway 等 provider 实现此头,nanoPencil 未利用。 |
|
|
647
|
-
| **INFO** | 指数退避(1s 基础、30s 上限)+ jitter + 可重试错误分类(429/5xx/ECONNRESET/ETIMEDOUT)基本正确。 |
|
|
648
|
-
|
|
649
|
-
### 4. 错误处理完整性
|
|
650
|
-
|
|
651
|
-
| 严重度 | 发现 |
|
|
652
|
-
|--------|------|
|
|
653
|
-
| **MEDIUM** | **错误分类不够细。** CC 有 ~25 种类型化错误(rate-limit 类型检测、overage、prompt-too-long + token gap、PDF 错误、图片大小、tool_use/tool_result 不匹配、OAuth 撤销、组织禁用等)。nanoPencil 用基础 regex 分类。 |
|
|
654
|
-
| **INFO** | 上下文溢出检测覆盖 14 种 provider 模式(Anthropic/OpenAI/Google/xAI/Groq/OpenRouter/llama.cpp/LM Studio 等),比 CC 更广。 |
|
|
655
|
-
|
|
656
|
-
### 5. 模型成本追踪
|
|
657
|
-
|
|
658
|
-
| 严重度 | 发现 |
|
|
659
|
-
|--------|------|
|
|
660
|
-
| **INFO** | `calculateCost()` 按每百万 token 定价计算 input/output/cache 成本,实现正确。 |
|
|
661
|
-
|
|
662
|
-
### 6. 上下文溢出检测
|
|
663
|
-
|
|
664
|
-
| 严重度 | 发现 |
|
|
665
|
-
|--------|------|
|
|
666
|
-
| **INFO** | 14 种 regex 模式 + 静默溢出检测(usage input vs context window)。多 provider 覆盖与 nanoPencil 的多 provider 使命一致,优于 CC。 |
|
|
667
|
-
|
|
668
|
-
---
|
|
669
|
-
|
|
670
|
-
### 汇总
|
|
671
|
-
|
|
672
|
-
| 严重度 | 数量 |
|
|
673
|
-
|--------|------|
|
|
674
|
-
| MEDIUM | 4(无 529 降级、重试次数低、Retry-After 仅文本解析、错误分类不细) |
|
|
675
|
-
| LOW | 2(无持久重试、无 x-should-retry) |
|
|
676
|
-
| INFO | 5 |
|
|
677
|
-
|
|
678
|
-
**优先修复项:**
|
|
679
|
-
1. Stream 重试次数从 3 提升到 5-6,支持配置覆盖
|
|
680
|
-
2. 添加 529 专项处理 + 连续计数 + 自动模型降级
|
|
681
|
-
3. Provider 实现中解析 HTTP `Retry-After` 响应头
|
|
682
|
-
|
|
683
|
-
---
|
|
684
|
-
|
|
685
|
-
## 2026-06-12 — Buddy/Pet 系统扫描
|
|
686
|
-
|
|
687
|
-
扫描范围:`modes/interactive/components/buddy/` 全部文件,对照 CC `src/buddy/` 模块(types.ts, sprites.ts, companion.ts, CompanionSprite.tsx, useBuddyNotification.tsx 等)
|
|
688
|
-
|
|
689
|
-
### 架构对比
|
|
690
|
-
|
|
691
|
-
CC 有 7 个文件按职责分离(types, sprites, companion logic, prompt injection, React rendering, notifications),深度集成到 React REPL。nanoPencil 有 2 个专用文件(`pet-sprites.ts`, `editor-buddy-layout.ts`),使用 TUI 命令式组件模型,结构更简洁。
|
|
692
|
-
|
|
693
|
-
### 1. 正确性缺陷
|
|
694
|
-
|
|
695
|
-
| 严重度 | 发现 |
|
|
696
|
-
|--------|------|
|
|
697
|
-
| **BUG** | **闪烁动画仅在 idle + frame 0 时生效。** `startAnimation()` tick 函数在 `this.state !== "idle" \|\| this.currentFrame !== 0` 时直接 return。虽然 `setState()` 会重置 frame 为 0 使闪烁恢复,但 blink timer 在 2500ms 固定间隔运行,无生命周期感知(TUI 挂起时仍在运行)。 |
|
|
698
|
-
| **BUG** | **blinkResetTimer 无重复保护。** `tick` 内 `setTimeout` 设置 `this.blinkResetTimer` 但不检查是否已有 pending timer。理论上可能产生重叠 timer(虽然当前 guard 使可能性极低)。 |
|
|
699
|
-
| **BUG** | **Sprite frame 取模无边界检查。** `this.sprite.states[this.state]` 理论上可能返回 `undefined`(如果 state 被运行时篡改)。TypeScript 编译时阻止,但运行时可变性存在风险。 |
|
|
700
|
-
|
|
701
|
-
### 2. 缺失错误处理
|
|
702
|
-
|
|
703
|
-
| 严重度 | 发现 |
|
|
704
|
-
|--------|------|
|
|
705
|
-
| **MEDIUM** | **无终端宽度适配。** CC 有 `MIN_COLS_FOR_FULL_SPRITE = 100`,窄终端自动折叠为单行表情。nanoPencil 的 `EditorBuddyLayout` 始终渲染 30 字符宽的 sprite 列,在 <50 列终端上会破坏布局。 |
|
|
706
|
-
| **MEDIUM** | **Speech bubble 存储但从未渲染。** `setSpeechBubble(text)` 保存文本并触发 re-render,但 `render()` 方法从不包含 `this.speechBubble`。这是死代码——数据写入无输出。 |
|
|
707
|
-
| **LOW** | **`buddySpecies` 无范围校验。** SettingsManager 保存整数索引,用户可设置任意数字。`ALL_SPRITES[spriteIndex % ALL_SPRITES.length]` 防崩溃,但无合理范围验证。 |
|
|
708
|
-
|
|
709
|
-
### 3. 高可用性
|
|
710
|
-
|
|
711
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
712
|
-
|------|-----------|-----|------|
|
|
713
|
-
| 状态持久化 | SettingsManager 持久化 `buddyEnabled`/`buddySpecies` | 全局 config 存储 `companion`(name+personality+hatchedAt) | 持平 |
|
|
714
|
-
| 确定性生成 | 无(用户手动选 sprite index) | `hash(userId)` → Mulberry32 PRNG → 同用户始终同 companion | **CC 优势**:抗配置篡改 |
|
|
715
|
-
| Timer 清理 | `dispose()` 清理 blink interval + reset timer | React effect cleanup | 持平 |
|
|
716
|
-
| 崩溃恢复 | 重启为 idle 状态 | 从 config 读取 + bones 重新生成 | 持平(均可接受) |
|
|
717
|
-
|
|
718
|
-
### 4. CC 功能差距
|
|
719
|
-
|
|
720
|
-
**关键缺失:**
|
|
721
|
-
|
|
722
|
-
| 功能 | CC | nanoPencil |
|
|
723
|
-
|------|-----|-----------|
|
|
724
|
-
| 物种多样性 | 18 种(duck, goose, blob, cat, dragon, octopus...) | 仅 6 种猫变体 |
|
|
725
|
-
| 稀有度系统 | 5 级稀有度 + 加权随机 + 视觉指示 | 无 |
|
|
726
|
-
| 确定性生成 | `hash(userId)` → 同用户始终同 companion | 手动选择 index |
|
|
727
|
-
| 孵化/命名 | `/buddy` 触发孵化,LLM 生成名字+性格 | 无孵化流程,名字硬编码 |
|
|
728
|
-
| Speech bubble 渲染 | 完整气泡(自动换行、淡出动画、尾部方向) | `setSpeechBubble()` 存在但从未显示 |
|
|
729
|
-
| 宠物互动 | `/buddy pet` 触发爱心动画 | 无 |
|
|
730
|
-
| 静音选项 | `companionMuted` config | 无(仅启用/禁用) |
|
|
731
|
-
| 系统提示注入 | Companion 名字+物种注入 LLM system prompt | 无 |
|
|
732
|
-
| 反应系统 | `fireCompanionObserver` 分析对话生成反应 | 无 |
|
|
733
|
-
| 帽子/眼睛/闪光 | 8 种帽子、6 种眼睛、1% 闪光变体 | 无 |
|
|
734
|
-
| Stats 系统 | 5 项统计(DEBUGGING, PATIENCE, CHAOS...) | 无 |
|
|
735
|
-
|
|
736
|
-
**中等缺失:**
|
|
737
|
-
1. 无 `/buddy` slash command
|
|
738
|
-
2. 无 LLM 集成(companion 不知道自己的存在)
|
|
739
|
-
3. 无 footer 选择器集成
|
|
740
|
-
4. 无窄终端自动折叠
|
|
741
|
-
5. 无 fullscreen 浮动气泡
|
|
742
|
-
|
|
743
|
-
### 5. 代码质量对比
|
|
744
|
-
|
|
745
|
-
**nanoPencil 优势:**
|
|
746
|
-
- 更简洁的架构(2 文件 vs CC 的 7 文件),适合当前功能范围
|
|
747
|
-
- 清晰的 JSDoc 头部(WHO/FROM/TO/HERE 模式)
|
|
748
|
-
- 干净的关注点分离(BuddyPetComponent 自包含,EditorBuddyLayout 处理布局)
|
|
749
|
-
|
|
750
|
-
**nanoPencil 弱点:**
|
|
751
|
-
- **死代码**:`speechBubble` 字段和 `setSpeechBubble()` 方法从未在渲染中使用
|
|
752
|
-
- **魔法数字**:`IDLE_BLINK_INTERVAL_MS=2500`, `BUDDY_COLUMN_WIDTH=30` 缺乏文档说明
|
|
753
|
-
- **动画单一**:6 个 sprite 全部使用相同的 2 帧动画(眨眼交替),CC 每物种有 3 帧 + 不同 fidget 模式
|
|
754
|
-
- **硬编码 sprite 数据**:内联字符串数组,未与渲染逻辑分离。CC 使用 `{E}` 占位符模板系统支持眼睛替换
|
|
755
|
-
|
|
756
|
-
### 汇总
|
|
757
|
-
|
|
758
|
-
| 严重度 | 数量 |
|
|
759
|
-
|--------|------|
|
|
760
|
-
| BUG | 3(闪烁 timer 生命周期、重叠 timer 风险、frame 边界) |
|
|
761
|
-
| MEDIUM | 3(无窄终端适配、speech bubble 死代码、species 范围无校验) |
|
|
762
|
-
| LOW | 1 |
|
|
763
|
-
|
|
764
|
-
**优先修复项:**
|
|
765
|
-
1. 实现 speech bubble 渲染(数据已存储但从未显示——功能性缺陷)
|
|
766
|
-
2. 添加窄终端适配(<80 列时隐藏或折叠 sprite 列)
|
|
767
|
-
3. 清理或接入 `setSpeechBubble()` 死代码
|
|
768
|
-
4. 考虑添加 `/buddy` slash command 提供基本控制
|
|
769
|
-
|
|
770
|
-
---
|
|
771
|
-
|
|
772
|
-
## 2026-06-12 — Keybindings 系统扫描
|
|
773
|
-
|
|
774
|
-
扫描范围:`core/lib/tui/src/keybindings.ts`, `core/lib/tui/src/keys.ts`, `core/platform/keybindings.ts`, 对照 CC `src/keybindings/` 模块(defaultBindings.ts, parser.ts, match.ts, resolver.ts, loadUserBindings.ts, validate.ts, reservedShortcuts.ts)
|
|
775
|
-
|
|
776
|
-
### 架构对比
|
|
777
|
-
|
|
778
|
-
nanoPencil 使用两层架构:Tier 1 Editor Keybindings(编辑器级动作)+ Tier 2 App Keybindings(应用级动作),通过全局单例 `EditorKeybindingsManager` 分发。CC 使用统一的上下文感知系统(18 个上下文),基于 React Context + Hooks 声明式绑定,支持多键和弦序列(如 `ctrl+k ctrl+s`)。
|
|
779
|
-
|
|
780
|
-
### 1. 正确性缺陷
|
|
781
|
-
|
|
782
|
-
| 严重度 | 发现 |
|
|
783
|
-
|--------|------|
|
|
784
|
-
| **MEDIUM** | **全局可变单例反模式。** `globalEditorKeybindings` 通过 `setEditorKeybindings()` 设置。若 `create()` 被多次调用(如 session 切换),持有旧引用的组件会静默使用过期绑定。CC 通过 React Context 传播变更。 |
|
|
785
|
-
| **MEDIUM** | **不支持 unbind/null-action。** `EditorKeybindingsConfig` 类型为 `KeyId \| KeyId[]`,无法取消默认绑定。CC 的 schema 支持 `z.null()` 取消默认。 |
|
|
786
|
-
| **MEDIUM** | **Alt+Enter 在 Kitty 协议激活时返回 false。** `keys.ts` 第 761-778 行:当 Kitty 协议激活且 CSI-u 序列不匹配时直接返回 false,无 fallback。对比 `shift+enter` 有 `\x1b\r` 和 `\n` 回退。 |
|
|
787
|
-
| **LOW** | **F-Key 修饰符全部拒绝。** `keys.ts` 第 968-985 行:所有带修饰符的 F 键组合(如 Ctrl+F5、Shift+F12)直接返回 false。CC 无此限制。 |
|
|
788
|
-
|
|
789
|
-
### 2. 缺陷
|
|
790
|
-
|
|
791
|
-
| 严重度 | 发现 |
|
|
792
|
-
|--------|------|
|
|
793
|
-
| **HIGH** | **用户配置无校验。** `loadFromFile()` 对 `JSON.parse` 错误静默返回 `{}`,action 名称拼写错误被完全忽略。CC 使用 Zod schema 校验,检查无效上下文/动作/重复键/保留快捷键,提供可操作错误信息。 |
|
|
794
|
-
| **MEDIUM** | **无热重载。** CC 用 chokidar 监听 `keybindings.json` 变更并自动重载。nanoPencil 仅启动时读取一次,用户必须重启才能生效。 |
|
|
795
|
-
| **MEDIUM** | **无冲突检测。** 无法检测用户配置的键绑定是否与其他绑定冲突。CC 的 `validate.ts` 检查同上下文内的重复键和保留快捷键。 |
|
|
796
|
-
| **MEDIUM** | **配置错误无恢复。** CC 的 `loadUserBindings.ts` 有多层错误处理(解析错误、结构校验、原始 JSON 重复键检测)。nanoPencil 任何错误都返回空对象,丢失所有用户自定义且无诊断信号。 |
|
|
797
|
-
| **LOW** | **双 Escape 映射歧义。** `keys.ts` 第 1092 行:`\x1b\x1b` 映射为 `ctrl+alt+[` 而非 `meta+escape`,可能混淆期望双 Escape 为独立键的用户。 |
|
|
798
|
-
|
|
799
|
-
### 3. 高可用性
|
|
800
|
-
|
|
801
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
802
|
-
|------|-----------|-----|------|
|
|
803
|
-
| 配置监听 | 无 | chokidar 文件监听 + 500ms 稳定阈值 + 订阅模型 | **CC 优势** |
|
|
804
|
-
| 错误降级 | 静默返回空对象 | 始终返回有效结果(默认+用户合并 或 纯默认),日志+通知系统警告 | **CC 优势** |
|
|
805
|
-
| 诊断工具 | `docs/keybindings.md` 全部 TODO | `/doctor` 命令集成 + 通知系统警告 | **CC 优势** |
|
|
806
|
-
| Schema 验证 | 无 | JSON Schema + `$schema` 字段供编辑器自动补全 | **CC 优势** |
|
|
807
|
-
|
|
808
|
-
### 4. CC 功能差距
|
|
809
|
-
|
|
810
|
-
**关键缺失:**
|
|
811
|
-
|
|
812
|
-
| 功能 | CC | nanoPencil |
|
|
813
|
-
|------|-----|-----------|
|
|
814
|
-
| 上下文感知绑定 | 18 个上下文(Global, Chat, Autocomplete, Settings...),同一键在不同上下文有不同含义 | 仅 2 层(editor + app),无上下文概念 |
|
|
815
|
-
| 多键和弦序列 | 支持 `ctrl+k ctrl+s` 等序列,1 秒超时 | 无 |
|
|
816
|
-
| 用户自定义 JSON | `~/.claude/keybindings.json` + schema 校验 + `/keybindings` 命令 | 读取 `keybindings.json` 但无校验、无命令、无文档 |
|
|
817
|
-
| 命令绑定 | 支持 `"ctrl+k": "command:help"` 绑定到 slash command | 无 |
|
|
818
|
-
| 平台感知默认值 | Windows `alt+v` 粘贴、macOS 保留 Cmd+C/V 等 | 平台无关 |
|
|
819
|
-
| 保留快捷键感知 | `NON_REBINDABLE`/`TERMINAL_RESERVED`/`MACOS_RESERVED` 三级 | 无 |
|
|
820
|
-
| 平台感知显示 | macOS 显示 "opt" 其他显示 "alt"、"cmd" vs "super" | 原始修饰符名称 |
|
|
821
|
-
| 配置热重载 | chokidar 监听 + 订阅模型 | 无 |
|
|
822
|
-
| JSON Schema | 自动生成供编辑器验证 | 无 |
|
|
823
|
-
| `/doctor` 集成 | 显示键绑定问题 | 无 |
|
|
824
|
-
|
|
825
|
-
### 5. 代码质量对比
|
|
826
|
-
|
|
827
|
-
**nanoPencil 优势:**
|
|
828
|
-
- **类型安全 KeyId**:模板字面量类型提供编译时安全性,优于 CC 的运行时校验
|
|
829
|
-
- **Key 辅助对象**:`Key.ctrl("c")`, `Key.ctrlShift("p")` 提供优秀的 IDE 自动补全
|
|
830
|
-
- **Kitty 协议支持**:完整支持 flag 2(按键释放/重复)、flag 4(备用键)、非拉丁布局基础键回退
|
|
831
|
-
- **Kill ring 和 undo**:Emacs 风格的 kill ring 和带合并的 undo 系统
|
|
832
|
-
|
|
833
|
-
**nanoPencil 弱点:**
|
|
834
|
-
- 全局可变状态(单例模式脆弱)
|
|
835
|
-
- 无配置校验(盲目信任用户输入)
|
|
836
|
-
- 300+ 行 `matchesKey()` switch 语句同时处理 legacy 和 Kitty 序列,CC 的结构化解析+匹配更清晰
|
|
837
|
-
- `docs/keybindings.md` 全部 TODO
|
|
838
|
-
|
|
839
|
-
### 汇总
|
|
840
|
-
|
|
841
|
-
| 严重度 | 数量 |
|
|
842
|
-
|--------|------|
|
|
843
|
-
| HIGH | 1(配置无校验——静默吞错) |
|
|
844
|
-
| MEDIUM | 6(全局单例、无 unbind、Alt+Enter bug、无热重载、无冲突检测、无错误恢复) |
|
|
845
|
-
| LOW | 3(F-Key 限制、双 Escape 映射、文档空) |
|
|
846
|
-
|
|
847
|
-
**优先修复项:**
|
|
848
|
-
1. 添加 `keybindings.json` 校验(至少检查 action 名称有效性 + 重复键警告)
|
|
849
|
-
2. 修复 Alt+Enter 在 Kitty 协议下的 fallback
|
|
850
|
-
3. 实现配置热重载(chokidar 监听文件变更)
|
|
851
|
-
4. 添加上下文感知绑定(至少区分 Autocomplete/Settings/Chat 上下文)
|
|
852
|
-
|
|
853
|
-
---
|
|
854
|
-
|
|
855
|
-
## 2026-06-12 — Memory 系统扫描
|
|
856
|
-
|
|
857
|
-
扫描范围:`packages/mem-core/` 全部文件(engine.ts, store.ts, store-v2.ts, scoring.ts, types.ts 等)+ `extensions/builtin/memory/extension.ts`,对照 CC `src/memdir/` 模块(teamMemPaths.ts, teamMemPrompts.ts, memoryTypes.ts, memoryAge.ts, extractMemories.ts, autoDream.ts, sessionMemory.ts)
|
|
858
|
-
|
|
859
|
-
### 架构对比
|
|
860
|
-
|
|
861
|
-
nanoPencil 实现了认知记忆架构:5 层记忆(episode, facet, semantic, procedural, state)+ 图链接系统 + 嵌入索引 + 渐进三层注入(active/cue/dormant)+ 艾宾浩斯间隔重复。CC 实现了文件记忆系统:Markdown 文件 + YAML frontmatter + MEMORY.md 索引,由 LLM 自身通过工具管理。
|
|
862
|
-
|
|
863
|
-
**核心区别:** nanoPencil 的记忆由代码引擎自动提取/管理(更自动化但不透明),CC 的记忆由 LLM 直接读写文件(更透明但依赖模型判断)。
|
|
864
|
-
|
|
865
|
-
### 1. 正确性缺陷
|
|
866
|
-
|
|
867
|
-
| 严重度 | 发现 |
|
|
868
|
-
|--------|------|
|
|
869
|
-
| **CRITICAL** | **`saveV2Snapshot` 并发竞态(store-v2.ts:128-138)。** 7 个存储文件通过 `Promise.all` 并行写入。进程崩溃时部分文件写入新数据、部分保留旧数据,存储不一致。无 WAL、无原子多文件提交、无版本校验。 |
|
|
870
|
-
| **HIGH** | **`writeJson` 非原子写入(store.ts:28-30)。** 直接调用 `writeFile`,崩溃时文件损坏。`grub-persistence.ts` 正确使用 tmp+rename 模式,但核心 `store.ts` 未使用。 |
|
|
871
|
-
| **MEDIUM** | **`ensureDir` 竞态(store.ts:14-15)。** `existsSync` + `mkdir` 存在竞态窗口。`mkdir({recursive:true})` 本身安全,但 `existsSync` 检查多余。 |
|
|
872
|
-
| **MEDIUM** | **`reinforceEntries` 读-改-写竞态(engine.ts:2218-2231)。** 加载全量条目 → 内存修改 → 全量写回。并发调用 `getMemoryInjection`(如 `before_agent_start`)可能互相覆盖。 |
|
|
873
|
-
| **LOW** | **`getMemoryInjection` 缩进异常(engine.ts:500-501)。** 方法体多一级缩进,疑似复制粘贴残留。 |
|
|
874
|
-
|
|
875
|
-
### 2. 缺陷
|
|
876
|
-
|
|
877
|
-
| 严重度 | 发现 |
|
|
878
|
-
|--------|------|
|
|
879
|
-
| **HIGH** | **`readJson` 静默吞错(store.ts:18-26)。** catch 块返回 fallback 值,无法区分"文件不存在"和"文件损坏"。无日志、无诊断。CC 有路径遍历攻击防护(280+ 行校验)、悬空符号链接检测、`ELOOP` 检测。 |
|
|
880
|
-
| **HIGH** | **`forgetEntry` 传入 `Infinity` 作为 max(engine.ts:1550)。** 删除条目时禁用驱逐限制,条目数永不封顶。应使用类别配置的 max 值。 |
|
|
881
|
-
| **MEDIUM** | **`buildRuntimeMemoryView` 冗余双重过滤(engine.ts:2084)。** `byType(runtimeEntries, "fact").filter(entry => entry.type === "fact")` — 第二次过滤是无操作的复制粘贴残留。 |
|
|
882
|
-
| **MEDIUM** | **`extractAndStore` 无 AbortSignal 传播(engine.ts:207-245)。** 6 个并行 save 调用无法取消。session 关闭时无法中断提取。 |
|
|
883
|
-
| **MEDIUM** | **无损坏恢复。** JSON 文件截断(如磁盘满)时静默作为空数组处理,整个类别的记忆存储丢失。 |
|
|
884
|
-
|
|
885
|
-
### 3. 高可用性
|
|
886
|
-
|
|
887
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
888
|
-
|------|-----------|-----|------|
|
|
889
|
-
| 原子写入 | 非原子 `writeFile` | 模型通过 Write 工具写入(tmp+rename) | **CC 优势** |
|
|
890
|
-
| 路径安全 | 无校验 | 280+ 行路径遍历防护、符号链接检测、Unicode 攻击防护 | **CC 优势** |
|
|
891
|
-
| 并发控制 | 无文件锁 | `tryAcquireConsolidationLock()` 跨 session 锁 | **CC 优势** |
|
|
892
|
-
| 维护前备份 | `createMaintenanceBackup` 完整备份 | 无 | **nanoPencil 优势** |
|
|
893
|
-
| 启动维护 | `runStartupMaintenance` 去重+迁移+归档 | 无等价物 | **nanoPencil 优势** |
|
|
894
|
-
| 崩溃恢复 | JSON 截断 → 数据丢失 | 文件损坏 → 诊断+降级 | **CC 优势** |
|
|
895
|
-
| 会话记忆 | 仅 session 结束时保存 episode | `sessionMemory.ts` 中途更新工作记忆 | **CC 优势** |
|
|
896
|
-
|
|
897
|
-
### 4. CC 功能差距
|
|
898
|
-
|
|
899
|
-
**关键缺失:**
|
|
900
|
-
|
|
901
|
-
| 功能 | CC | nanoPencil |
|
|
902
|
-
|------|-----|-----------|
|
|
903
|
-
| 文件化记忆+LLM 自管理 | LLM 通过文件工具读写 MEMORY.md + 主题文件 | 代码引擎管理 JSON blob,LLM 无直接控制 |
|
|
904
|
-
| MEMORY.md 可读索引 | 人类可读索引+文件链接,可直接编辑 | JSON blob 不透明,不可浏览/编辑/版本控制 |
|
|
905
|
-
| Team 记忆+范围隔离 | 完整 private/team 范围、符号链接安全、跨用户同步 | 仅有范围类型定义,无实现 |
|
|
906
|
-
| Session 工作记忆 | 中途更新的工作记忆文件 | 仅 session 结束保存 episode |
|
|
907
|
-
| 子进程提取 | fork 子进程共享 prompt cache,用工具写入 | 同步 fire-and-forget,无 cache 共享 |
|
|
908
|
-
| 记忆新鲜度警告 | 47 天前的记忆 → "声明可能过时" | 无等价物 |
|
|
909
|
-
| LLM 相关性选择 | Sonnet 侧查询选 top 5 | 评分算法(时间衰减+重要性+标签),无 LLM |
|
|
910
|
-
| `/remember` 技能 | 审查记忆全景,建议升级/降级 | 无 |
|
|
911
|
-
| 安全:路径遍历防护 | 280+ 行防护(空字节、URL 编码、Unicode 规范化、符号链接循环) | 无 |
|
|
912
|
-
|
|
913
|
-
**nanoPencil 独有优势:**
|
|
914
|
-
|
|
915
|
-
| 功能 | nanoPencil | CC |
|
|
916
|
-
|------|-----------|-----|
|
|
917
|
-
| 认知记忆模型 | 5 层架构+图链接+冲突检测 | 扁平文件,无结构关系 |
|
|
918
|
-
| 艾宾浩斯间隔重复 | `R = e^(-t*ln2/S)` 强度随回忆增长 | 无 |
|
|
919
|
-
| 渐进三层注入 | Active(完整)→ Cue(摘要)→ Dormant(不注入) | 一层(选中或未选中) |
|
|
920
|
-
| 嵌入索引语义搜索 | 哈希嵌入向量相似度搜索 | LLM 文本选择 |
|
|
921
|
-
| 归档/复活系统 | 过时记忆归档,相关查询时自动复活 | 无归档概念 |
|
|
922
|
-
| 冲突检测+解决 | 检测冲突记忆,建议合并/降级/忘记/标记情境 | 无 |
|
|
923
|
-
| 洞察报告 | 完整 HTML 报告(模式、挣扎、根因分析) | 无 |
|
|
924
|
-
| 双提取 | LLM + 正则启发式回退 | 仅 LLM |
|
|
925
|
-
| I18n | 中英文 | 仅英文 |
|
|
926
|
-
| 双时间模型 | `created`(摄入时间)+ `eventTime`(事件时间) | 仅文件修改时间 |
|
|
927
|
-
|
|
928
|
-
### 5. 代码质量对比
|
|
929
|
-
|
|
930
|
-
**nanoPencil 优势:**
|
|
931
|
-
- 优秀的 JSDoc 标注(WHO/FROM/TO/HERE 约定)
|
|
932
|
-
- 完整测试覆盖(test/ 目录 20+ 测试文件)
|
|
933
|
-
- 良好的类型定义+向后兼容迁移路径(如 `migrateEntry`)
|
|
934
|
-
|
|
935
|
-
**nanoPencil 弱点:**
|
|
936
|
-
- `engine.ts` 2,397 行 — God class,职责过多
|
|
937
|
-
- 错误处理不一致:部分方法 throw、部分返回 null、部分静默 catch
|
|
938
|
-
- `forgetEntry` 用 `Infinity` 作为 max,疑似 bug
|
|
939
|
-
- 2084 行双重过滤,复制粘贴残留
|
|
940
|
-
|
|
941
|
-
### 汇总
|
|
942
|
-
|
|
943
|
-
| 严重度 | 数量 |
|
|
944
|
-
|--------|------|
|
|
945
|
-
| CRITICAL | 1(saveV2Snapshot 并发竞态) |
|
|
946
|
-
| HIGH | 3(非原子写入、readJson 静默吞错、forgetEntry Infinity max) |
|
|
947
|
-
| MEDIUM | 4(ensureDir 竞态、reinforceEntries 竞态、冗余过滤、无 AbortSignal) |
|
|
948
|
-
| LOW | 1(缩进异常) |
|
|
949
|
-
|
|
950
|
-
**优先修复项:**
|
|
951
|
-
1. `store.ts` 的 `writeJson` 改用 tmp+rename 原子写入(`grub-persistence.ts` 已有参考实现)
|
|
952
|
-
2. `saveV2Snapshot` 添加顺序写入或事务日志
|
|
953
|
-
3. `forgetEntry` 使用类别配置的 max 替代 `Infinity`
|
|
954
|
-
4. `readJson` 增加日志区分文件不存在 vs 文件损坏
|
|
955
|
-
5. `extractAndStore` 支持 AbortSignal 传播
|
|
956
|
-
|
|
957
|
-
---
|
|
958
|
-
|
|
959
|
-
## 2026-06-12 — Diff/Patch 系统扫描
|
|
960
|
-
|
|
961
|
-
扫描范围:`core/tools/edit.ts`, `core/tools/edit-diff.ts`, `core/tools/write.ts`, `core/tools/file-state-cache.ts`, `modes/interactive/components/diff.ts`, `modes/interactive/components/tool-execution.ts`,对照 CC `src/tools/FileEditTool/` + `src/utils/diff.ts` + `src/utils/fileHistory.ts` + `src/components/diff/DiffDialog.tsx`
|
|
962
|
-
|
|
963
|
-
### 1. 正确性缺陷
|
|
964
|
-
|
|
965
|
-
| 严重度 | 发现 |
|
|
966
|
-
|--------|------|
|
|
967
|
-
| **CRITICAL** | **Fuzzy 匹配静默修改整个文件内容。** `edit-diff.ts:110-116` 将 `contentForReplacement` 设为 `fuzzyContent`(规范化后)。替换操作作用于规范化内容,导致整个文件的尾随空格被剥离、智能引号转 ASCII、Unicode 破折号转连字符。CC 的 `findActualString` 仅规范化匹配区域。Markdown 硬换行(两尾随空格)会被静默破坏。 |
|
|
968
|
-
| **HIGH** | **Write 工具存储错误的过期时间戳。** `write.ts:116-119` 使用 `Date.now()` 而非 `postWriteStat.mtimeMs`。`Date.now()` 远大于 `mtimeMs`,导致过期检查 `currentStat.mtimeMs > cachedState.timestamp` 几乎永不触发,过期检测完全失效。 |
|
|
969
|
-
| **MEDIUM** | **出现次数计数双重规范化。** `edit.ts:175-177` 对已规范化的内容再次调用 `normalizeForFuzzyMatch` 计数。若 `normalizeForFuzzyMatch` 相对于 `normalizeToLF` 非幂等(当前是,但契约未文档化),可能产生错误计数。 |
|
|
970
|
-
| **MEDIUM** | **错误类型不一致。** `edit.ts:119` 构造 `new Error("File not found")`,但 `edit.ts:255` 直接 reject 原始 error 对象。行为正确但代码风格不一致。 |
|
|
971
|
-
| **LOW** | **空字符串处理未验证。** CC 校验 `old_string === ''` 仅在创建新文件时有效。nanoPencil 无此守卫,`fuzzyFindText` 查找空字符串行为未测试。 |
|
|
972
|
-
|
|
973
|
-
### 2. 缺陷
|
|
974
|
-
|
|
975
|
-
| 严重度 | 发现 |
|
|
976
|
-
|--------|------|
|
|
977
|
-
| **HIGH** | **无 `replace_all` 参数。** CC 支持 `replace_all: boolean` 替换所有出现。nanoPencil 在多处出现时直接拒绝(`edit.ts:179-189`)。LLM 重命名变量(出现 10 次)时 CC 一次调用即可,nanoPencil 需 10 次或每次提供足够上下文。 |
|
|
978
|
-
| **HIGH** | **无文件历史/快照/回滚系统。** CC 有 1116 行的 `fileHistory.ts`:版本备份、每轮快照、完整回滚、session resume 支持。nanoPencil **零等价物**——编辑出错只能手动恢复。这是两个系统间最大的功能差距。 |
|
|
979
|
-
| **MEDIUM** | **无 API token 反净化。** CC 的 `DESANITIZATIONS` 映射将 `<fnr>` 还原为 `<function_results>`、`\n\nH:` 还原为 `\n\nHuman:`。LLM 输出的 `old_string` 包含净化 token 时 CC 透明处理,nanoPencil 会静默 "String not found"。 |
|
|
980
|
-
| **MEDIUM** | **无引号风格保留。** CC 的 `preserveQuoteStyle` 检测弯引号并保持一致。nanoPencil 将弯引号规范化为 ASCII 后不恢复,编辑区域与文件其余部分引号风格不一致。 |
|
|
981
|
-
| **MEDIUM** | **无 UTF-16LE 编码检测。** CC 检测 UTF-8/UTF-16LE 编码和 LF/CRLF 行尾。nanoPencil 仅规范化 CRLF→LF,编辑 UTF-16LE 文件会损坏。 |
|
|
982
|
-
| **MEDIUM** | **无大文件保护。** CC 定义 `MAX_EDIT_FILE_SIZE = 1 GiB` 防止 OOM。nanoPencil 无等价守卫。 |
|
|
983
|
-
| **MEDIUM** | **无 diff 计算超时。** CC 定义 `DIFF_TIMEOUT_MS = 5_000`。nanoPencil 使用 `Diff.diffLines` 无超时,大文件可能长时间阻塞事件循环。 |
|
|
984
|
-
| **LOW** | **Abort signal handler 泄漏风险。** `edit.ts:97-107` 的 abort handler 在某些 early return 分支未清理。`{ once: true }` 最终会清理,但 `removeEventListener` 仅在部分分支调用。 |
|
|
985
|
-
| **LOW** | **无 Jupyter notebook 守卫。** CC 拒绝编辑 `.ipynb` 文件并引导至 `NotebookEditTool`。nanoPencil 无此守卫,编辑 notebook 可能静默损坏。 |
|
|
986
|
-
|
|
987
|
-
### 3. 高可用性
|
|
988
|
-
|
|
989
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
990
|
-
|------|-----------|-----|------|
|
|
991
|
-
| 文件历史/快照 | **无** | `fileHistory.ts` 1116 行:版本备份、轮次快照、完整回滚、session resume | **CC 压倒性优势** |
|
|
992
|
-
| 回滚能力 | 无 | `fileHistoryRewind` 恢复所有文件到任意快照 | **CC 压倒性优势** |
|
|
993
|
-
| 结构化补丁输出 | 纯文本 diff | `structuredPatch` 数组(hunk 对象) | **CC 优势** |
|
|
994
|
-
| Diff 浏览 UI | 内联 `renderDiff()` | `DiffDialog.tsx` 键盘导航、文件列表、hunk 渲染 | **CC 优势** |
|
|
995
|
-
| 编辑预览 | `computeEditDiff` 预执行 diff 预览 | 无等价物(diff 后执行计算) | **nanoPencil 优势** |
|
|
996
|
-
| 可插拔后端 | `EditOperations`/`WriteOperations` 接口支持 SSH | 无等价抽象 | **nanoPencil 优势** |
|
|
997
|
-
| LRU 缓存 | `FileStateCache` 双维淘汰(条目+字节) | 简单方法 | **nanoPencil 优势** |
|
|
998
|
-
| 遥测 | 无 | `tengu_edit_string_lengths`, `tengu_file_changed` 等 | **CC 优势** |
|
|
999
|
-
|
|
1000
|
-
### 4. CC 功能差距
|
|
1001
|
-
|
|
1002
|
-
| 功能 | CC | nanoPencil |
|
|
1003
|
-
|------|-----|-----------|
|
|
1004
|
-
| `replace_all` 参数 | 支持 | 不支持 |
|
|
1005
|
-
| 多编辑输入(edits 数组) | `getPatchForEdits` 支持链式编辑+冲突检测 | 仅单编辑 |
|
|
1006
|
-
| API token 反净化 | `DESANITIZATIONS` 映射 | 无 |
|
|
1007
|
-
| 弯引号保留 | `preserveQuoteStyle` | 无 |
|
|
1008
|
-
| UTF-16LE 编码检测 | `readFileSyncWithMetadata` | 无 |
|
|
1009
|
-
| 大文件保护 | 1 GiB 限制 | 无 |
|
|
1010
|
-
| Diff 超时 | 5 秒 | 无 |
|
|
1011
|
-
| Jupyter 守卫 | 拒绝 `.ipynb` | 无 |
|
|
1012
|
-
| 文件历史/快照/回滚 | 完整系统 | **无** |
|
|
1013
|
-
| 结构化补丁输出 | hunk 数组 | 纯文本 |
|
|
1014
|
-
| 轮次 diff 聚合 | `useTurnDiffs` hook | 无 |
|
|
1015
|
-
| `/diff` 命令+对话 UI | `DiffDialog.tsx` | 无 |
|
|
1016
|
-
| LSP 集成 | didChange/didSave | 无 |
|
|
1017
|
-
| UNC 路径安全守卫 | 有 | 无 |
|
|
1018
|
-
| 编辑去重 | `areFileEditsInputsEquivalent` | 无 |
|
|
1019
|
-
| 输入规范化层 | `normalizeFileEditInput` | 无 |
|
|
1020
|
-
|
|
1021
|
-
### 5. 代码质量对比
|
|
1022
|
-
|
|
1023
|
-
**nanoPencil 优势:**
|
|
1024
|
-
- 可插拔后端接口(`EditOperations`/`WriteOperations`)支持远程文件系统
|
|
1025
|
-
- `FileStateCache` 纯 LRU 实现,双维淘汰(条目数+字节数)
|
|
1026
|
-
- `computeEditDiff` 预执行 diff 预览,CC 无等价物
|
|
1027
|
-
- `editDiffPreview` 模式在工具执行前异步计算 diff 提供即时视觉反馈
|
|
1028
|
-
|
|
1029
|
-
**nanoPencil 弱点:**
|
|
1030
|
-
- `edit.ts` 的 Promise wrapper 是反模式(async IIFE 内嵌 `new Promise`)
|
|
1031
|
-
- Fuzzy 匹配过度规范化——规范化整个文件而非仅匹配区域
|
|
1032
|
-
- `detectLineEnding` 检测逻辑微妙:混合行尾时返回先出现的而非主导的
|
|
1033
|
-
|
|
1034
|
-
### 汇总
|
|
1035
|
-
|
|
1036
|
-
| 严重度 | 数量 |
|
|
1037
|
-
|--------|------|
|
|
1038
|
-
| CRITICAL | 1(fuzzy 匹配静默损坏整个文件) |
|
|
1039
|
-
| HIGH | 3(write 时间戳错误、无 replace_all、无文件历史) |
|
|
1040
|
-
| MEDIUM | 7(双重规范化、错误类型、API 反净化、引号保留、UTF-16LE、大文件、diff 超时) |
|
|
1041
|
-
| LOW | 3(空字符串、abort 泄漏、Jupyter 守卫) |
|
|
1042
|
-
|
|
1043
|
-
**优先修复项:**
|
|
1044
|
-
1. **CRITICAL**: 修复 fuzzy 匹配——仅规范化匹配区域,替换后映射回原始内容
|
|
1045
|
-
2. **CRITICAL**: 修复 write 工具时间戳——使用 `postWriteStat.mtimeMs` 替代 `Date.now()`
|
|
1046
|
-
3. **HIGH**: 添加 `replace_all` 参数
|
|
1047
|
-
4. **HIGH**: 实现最小文件历史系统(至少支持每轮备份+单文件回滚)
|
|
1048
|
-
5. **HIGH**: 返回结构化 patch 输出(hunk 数组)
|
|
1049
|
-
|
|
1050
|
-
---
|
|
1051
|
-
|
|
1052
|
-
## 2026-06-12 — Git 集成系统扫描
|
|
1053
|
-
|
|
1054
|
-
扫描范围:`core/tools/bash.ts`(sandbox git 模式)、`utils/git.ts`(URL 解析)、`core/workspace/worktree-manager.ts`,对照 CC `src/utils/git.ts` + `src/utils/git/` + `src/tools/BashTool/readOnlyValidation.ts` + `src/tools/BashTool/bashPermissions.ts` + `src/utils/gitDiff.ts` + `src/tools/shared/gitOperationTracking.ts`
|
|
1055
|
-
|
|
1056
|
-
### 架构对比
|
|
1057
|
-
|
|
1058
|
-
CC 有 ~8000 行 git 集成,分层清晰:核心工具(git.ts)、文件系统级状态读取(gitFilesystem.ts)、配置解析(gitConfigParser.ts)、gitignore 管理、diff 计算、只读命令验证(~50 条目)、bash 权限守卫、操作追踪。nanoPencil 仅有一个 sandbox regex 阻止 git 写操作 + `WorktreeManager` 管理子代理工作区。
|
|
1059
|
-
|
|
1060
|
-
### 1. 安全缺陷
|
|
1061
|
-
|
|
1062
|
-
| 严重度 | 发现 |
|
|
1063
|
-
|--------|------|
|
|
1064
|
-
| **CRITICAL** | **无 bare-repo 攻击检测。** CC 有 `isCurrentDirectoryBareGitRepo()` + 5 层防御(git 内部路径写入检测、cd+git 组合命令阻止、管道段检测)。nanoPencil **零防护**——攻击者可构造恶意仓库通过 hooks 执行任意代码。 |
|
|
1065
|
-
| **CRITICAL** | **无 cd+git 组合命令阻止。** CC 的 `bashPermissions.ts` 阻止包含 `cd` 和 `git` 的复合命令,`bashCommandHelpers.ts` 检测管道段中的 cd+git。nanoPencil 无等价防护。 |
|
|
1066
|
-
| **HIGH** | **Sandbox regex 漏洞百出。** `bash.ts:461` 的 regex 未阻止:`git stash push/drop/pop/apply`、`git branch -d/-D`、`git tag -d`、`git config --global`、`git gc`、`git clean -f`、`git update-ref`、`git restore`。CC 的 `GIT_READ_ONLY_COMMANDS` 有 ~50 条目+逐 flag 校验。 |
|
|
1067
|
-
| **HIGH** | **无 git 命令规范化。** `NO_COLOR=1 git commit -m "fix"` 绕过 nanoPencil regex(期望 `\bgit\s+` 开头)。CC 的 `isNormalizedGitCommand()` 先 `stripSafeWrappers()` 去除环境变量/timeout/nice 等再匹配。 |
|
|
1068
|
-
| **HIGH** | **无 git-internal 路径写入检测。** CC 检测对 `.git/` 目录的写入尝试。nanoPencil 无此防护。 |
|
|
1069
|
-
| **MEDIUM** | **无只读命令白名单。** CC 对 ~25 个 git 子命令定义安全 flag 白名单(如 `git diff` 允许 `--stat`/`--name-only`/`-p` 但阻止 `--output`)。nanoPencil 无显式白名单,`git status`/`git diff`/`git log` 可能被 regex 误伤。 |
|
|
1070
|
-
|
|
1071
|
-
### 2. 正确性缺陷
|
|
1072
|
-
|
|
1073
|
-
| 严重度 | 发现 |
|
|
1074
|
-
|--------|------|
|
|
1075
|
-
| **HIGH** | **无临时 git 状态检测。** CC 的 `isInTransientGitState()` 检查 `MERGE_HEAD`/`REBASE_HEAD`/`CHERRY_PICK_HEAD`/`REVERT_HEAD` 文件。合并/变基期间工作树包含非用户意图的变更,diff 输出会误导。nanoPencil 无等价物。 |
|
|
1076
|
-
| **MEDIUM** | **`utils/git.ts` 文件名误导。** 该文件仅做 git URL 解析(用于包管理),与 git 仓库操作无关。CC 的同名文件是完整的 git 操作模块。 |
|
|
1077
|
-
| **MEDIUM** | **`findGitRoot` 缺失。** CC 的 `findGitRoot` 向上遍历目录树找 `.git`,LRU 缓存,处理 worktree/submodule。nanoPencil 完全依赖 git 子进程发现仓库状态,更慢且无法同步调用。 |
|
|
1078
|
-
|
|
1079
|
-
### 3. 高可用性
|
|
1080
|
-
|
|
1081
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1082
|
-
|------|-----------|-----|------|
|
|
1083
|
-
| Git 状态缓存 | 无,每次查询 spawn 子进程 | 双层:同步 LRU + `fs.watchFile` 监听 `.git/HEAD`/`.git/config` | **CC 压倒性优势** |
|
|
1084
|
-
| 状态快照 | 无 | `preserveGitStateForIssue()` 捕获 merge-base、patch、未跟踪文件、format-patch | **CC 优势** |
|
|
1085
|
-
| Worktree 安全 | `createGitWorktree()` 直接信任 git 结果 | `resolveCanonicalRoot()` 验证 gitdir 链接、symlink、bare-repo | **CC 优势** |
|
|
1086
|
-
| Stash 操作 | 无 | `stashToCleanState()` 先 stage 未跟踪文件再 stash 防数据丢失 | **CC 优势** |
|
|
1087
|
-
| Worktree 创建 | 直接 `git worktree add`,不 stash 变更 | stash-to-clean-state 后创建 | **CC 优势** |
|
|
1088
|
-
|
|
1089
|
-
### 4. CC 功能差距
|
|
1090
|
-
|
|
1091
|
-
**关键缺失:**
|
|
1092
|
-
|
|
1093
|
-
| 功能 | CC | nanoPencil |
|
|
1094
|
-
|------|-----|-----------|
|
|
1095
|
-
| Git commit/PR 指令 | system prompt 中完整安全协议+分步指令(HEREDOC、并行 status/diff/log、force push 警告) | 无 |
|
|
1096
|
-
| 只读命令验证 | ~50 条目 + 逐 flag 白名单 + 回调验证器 | 单 regex(漏洞百出) |
|
|
1097
|
-
| Git 操作追踪 | 278 行:commit/push/cherry-pick/merge/rebase 检测 + OTLP 计数 + session-PR 自动关联 | 无 |
|
|
1098
|
-
| 文件系统 git 状态 | `GitFileWatcher` 监听 `.git/HEAD`/`.git/config` + LRU 缓存 | 无 |
|
|
1099
|
-
| `.git/config` 解析器 | 轻量解析器(大小写不敏感 section、转义、引号值) | 无 |
|
|
1100
|
-
| Gitignore 管理 | `isPathGitignored()`、`addFileGlobRuleToGitignore()` | 无 |
|
|
1101
|
-
| Bare-repo 安全 | 5 层防御 | 无 |
|
|
1102
|
-
| 暂态状态检测 | MERGE_HEAD/REBASE_HEAD/CHERRY_PICK_HEAD/REVERT_HEAD | 无 |
|
|
1103
|
-
| 单文件 git diff | `fetchSingleFileGitDiff()` 对比 merge-base | 仅本地文件 diff |
|
|
1104
|
-
| 安全 ref 名验证 | `isSafeRefName()` 拒绝路径遍历/元字符/前导破折号 | 无 |
|
|
1105
|
-
|
|
1106
|
-
### 5. 代码质量对比
|
|
1107
|
-
|
|
1108
|
-
**nanoPencil 优势:**
|
|
1109
|
-
- `WorktreeManager` 封装了完整的快照工作流(创建→检测→生成 patch→应用→清理)
|
|
1110
|
-
|
|
1111
|
-
**nanoPencil 弱点:**
|
|
1112
|
-
- Sandbox regex 单点防护,无规范化、无白名单、无深层防御
|
|
1113
|
-
- `WorktreeManager` 混合关注点(临时目录+快照+git worktree+变更检测+patch 生成+应用+清理)
|
|
1114
|
-
- `utils/git.ts` 文件名误导
|
|
1115
|
-
|
|
1116
|
-
### 汇总
|
|
1117
|
-
|
|
1118
|
-
| 严重度 | 数量 |
|
|
1119
|
-
|--------|------|
|
|
1120
|
-
| CRITICAL | 2(bare-repo 攻击、cd+git 组合命令) |
|
|
1121
|
-
| HIGH | 4(sandbox regex 漏洞、无命令规范化、无 git-internal 路径检测、无暂态状态检测) |
|
|
1122
|
-
| MEDIUM | 3(无只读白名单、文件名误导、无 findGitRoot) |
|
|
1123
|
-
| LOW | 0 |
|
|
1124
|
-
|
|
1125
|
-
**优先修复项:**
|
|
1126
|
-
1. **CRITICAL**: 实现 bare-repo 攻击检测 + cd+git 组合命令阻止
|
|
1127
|
-
2. **CRITICAL**: 重写 sandbox git 模式——从 regex 升级为白名单+逐 flag 校验
|
|
1128
|
-
3. **HIGH**: 添加 git 命令规范化(去除环境变量/安全包装器后匹配)
|
|
1129
|
-
4. **HIGH**: 添加暂态 git 状态检测(MERGE_HEAD/REBASE_HEAD 等)
|
|
1130
|
-
5. **HIGH**: 在 system prompt 中添加 git commit/PR 安全指令
|
|
1131
|
-
|
|
1132
|
-
---
|
|
1133
|
-
|
|
1134
|
-
## 2026-06-12 — Theme/样式系统扫描
|
|
1135
|
-
|
|
1136
|
-
扫描范围:`core/theme-contract.ts`, `modes/interactive/theme/theme.ts`, `modes/interactive/theme/{dark,light,warm}.json`, `modes/interactive/components/theme-selector.ts`, 对照 CC `src/utils/theme.ts` + `src/utils/systemTheme.ts` + `src/components/design-system/` + `src/ink/colorize.ts` + `src/ink/styles.ts`
|
|
1137
|
-
|
|
1138
|
-
### 架构对比
|
|
1139
|
-
|
|
1140
|
-
nanoPencil 使用 JSON 文件+TypeBox schema 验证+`globalThis` Proxy 跨模块共享+自定义 ANSI 渲染器。CC 使用 React Context(ThemeProvider)+ 硬编码 TypeScript 主题对象+ThemedText/ThemedBox 组件抽象。
|
|
1141
|
-
|
|
1142
|
-
**nanoPencil 独有优势:** JSON 文件主题(用户可自定义)、`vars` 变量系统、TypeBox schema 验证。
|
|
1143
|
-
**CC 独有优势:** 无自定义主题支持但有 daltonized(色盲友好)主题、auto 模式实时终端检测、预览+取消工作流。
|
|
1144
|
-
|
|
1145
|
-
### 1. 正确性缺陷
|
|
1146
|
-
|
|
1147
|
-
| 严重度 | 发现 |
|
|
1148
|
-
|--------|------|
|
|
1149
|
-
| **MEDIUM** | **`getThemeExportColors` 变量解析路径损坏。** `theme.ts:872-882` 使用 `value.startsWith("$")` 检查变量引用,但主题 JSON 的 `vars`/`colors` 系统不使用 `$` 前缀(裸名引用如 `"accent"`)。`$`-prefix 分支永远不会匹配,export colors 中的变量引用会原样返回字面量字符串。`resolveThemeColors`(line 291)使用正确的裸名解析,但 `getThemeExportColors` 走了错误路径。 |
|
|
1150
|
-
| **LOW** | **`getCliHighlightTheme` 缓存失效逻辑误导。** `theme.ts:923-929` 用对象身份比较 (`!==`),但 `theme` 是 Proxy,身份始终相同。缓存实际上通过闭包动态读取 `globalThis[THEME_KEY]` 所以结果正确,但意图不清晰,首次切换后每次都会不必要地重建缓存对象。 |
|
|
1151
|
-
| **LOW** | **`isLightTheme` 过于简单。** 仅检查 `themeName === "light"`,自定义浅色主题不会被识别。CC 补偿了 `auto` 模式查询终端背景亮度。 |
|
|
1152
|
-
|
|
1153
|
-
### 2. 缺陷
|
|
1154
|
-
|
|
1155
|
-
| 严重度 | 发现 |
|
|
1156
|
-
|--------|------|
|
|
1157
|
-
| **MEDIUM** | **主题 watcher 错误静默吞没。** `theme.ts:738,758-760` catch 块无日志无用户通知。CC 至少通过 ThemePicker UI 通知用户。 |
|
|
1158
|
-
| **MEDIUM** | **自定义主题目录扫描无预验证。** `getAvailableThemes()` 将所有 `.json` 文件加入列表,损坏文件会出现在列表中但选择时回退到 dark,无诊断信号。 |
|
|
1159
|
-
| **MEDIUM** | **主题 watcher rename 事件原子保存竞态。** 使用原子保存(tmp+rename)的编辑器会触发 rename fallback,文件不存在时回退到 dark 并永久关闭 watcher。用户需重新选择主题才能恢复。 |
|
|
1160
|
-
| **LOW** | **模块级可变状态无清理保证。** `BUILTIN_THEMES`、`currentThemeName`、`themeWatcher` 等都是模块级变量,多 loader 加载时状态分裂。`globalThis` Proxy 仅缓解 theme 实例的共享问题。 |
|
|
1161
|
-
|
|
1162
|
-
### 3. 高可用性
|
|
1163
|
-
|
|
1164
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1165
|
-
|------|-----------|-----|------|
|
|
1166
|
-
| 主题持久化 | `settingsManager.setTheme()` 存储主题名 | `saveGlobalConfig` | 持平 |
|
|
1167
|
-
| 错误恢复 | 回退到 dark | 回退到 dark + ThemePicker UI | **CC 优势** |
|
|
1168
|
-
| Auto 模式 | `COLORFGBG` 启动时读取,静态 | OSC 11 实时查询 + `systemThemeWatcher` 动态切换 | **CC 优势** |
|
|
1169
|
-
| 自定义主题 | JSON 文件+文件 watcher | 不支持自定义主题 | **nanoPencil 优势** |
|
|
1170
|
-
| 预览+取消 | `onThemePreview` 直接应用,取消不回退 | `setPreviewTheme` + `cancelPreview` 可逆工作流 | **CC 优势** |
|
|
1171
|
-
| 色盲友好 | 无 | `light-daltonized`/`dark-daltonized` 主题 | **CC 优势** |
|
|
1172
|
-
| 16 色终端 | 256 色回退(hexTo256) | 专用 `light-ansi`/`dark-ansi` 16 色主题 | **CC 优势** |
|
|
1173
|
-
|
|
1174
|
-
### 4. CC 功能差距
|
|
1175
|
-
|
|
1176
|
-
| 功能 | CC | nanoPencil |
|
|
1177
|
-
|------|-----|-----------|
|
|
1178
|
-
| 色盲友好主题 | `light-daltonized`/`dark-daltonized`(蓝橙替代红绿) | 无 |
|
|
1179
|
-
| ANSI-only 16 色主题 | `light-ansi`/`dark-ansi` | 无(仅 256 色回退) |
|
|
1180
|
-
| Auto 模式+实时检测 | OSC 11 查询 + systemThemeWatcher | `COLORFGBG` 启动时读取 |
|
|
1181
|
-
| 预览+取消工作流 | `setPreviewTheme`/`savePreview`/`cancelPreview` | 直接应用,取消不回退 |
|
|
1182
|
-
| Shimmer 动画颜色 | `claudeShimmer`/`permissionShimmer`/`warningShimmer` 等 | 无 |
|
|
1183
|
-
| Agent 专用颜色 | `red_FOR_SUBAGENTS_ONLY` 等 | 无 |
|
|
1184
|
-
| 结构化文本样式 | `TextStyles` 类型(对象式样式组合) | 直接 ANSI 字符串 |
|
|
1185
|
-
| ThemedText/ThemedBox | 自动解析主题键的组件抽象 | 手动 `theme.fg("accent", text)` |
|
|
1186
|
-
| Hover 颜色上下文 | `TextHoverColorContext` | 无 |
|
|
1187
|
-
| Rate limit/Memory 颜色 | `rate_limit_fill`/`memoryBackgroundColor` 等 | 无 |
|
|
1188
|
-
| 选区背景色 | `selectionBg` | 无 |
|
|
1189
|
-
| 原生语法高亮 | `color-diff-napi` | `cli-highlight`(功能较少) |
|
|
1190
|
-
|
|
1191
|
-
### 5. 代码质量对比
|
|
1192
|
-
|
|
1193
|
-
**nanoPencil 优势:**
|
|
1194
|
-
- `theme-contract.ts` 纯类型无导入,干净的 contract/implementation 分离
|
|
1195
|
-
- JSON 文件主题 + TypeBox schema 提供编译时+运行时双重保证
|
|
1196
|
-
- `vars` 变量系统减少主题文件中的重复
|
|
1197
|
-
- 主题验证失败时的详细错误信息(列出缺失的 color token)
|
|
1198
|
-
- `cli-highlight` 懒加载优化启动性能
|
|
1199
|
-
|
|
1200
|
-
**nanoPencil 弱点:**
|
|
1201
|
-
- `getThemeExportColors` 的 `$`-prefix 解析路径损坏
|
|
1202
|
-
- `ThemeImpl` 预计算 ANSI 转义字符串,返回的部分应用字符串无法进一步组合
|
|
1203
|
-
- Global Proxy 模式不寻常,可能混淆贡献者
|
|
1204
|
-
- `docs/themes.md` 全部 TODO
|
|
1205
|
-
- 无主题系统单元测试
|
|
1206
|
-
|
|
1207
|
-
**CC 弱点:**
|
|
1208
|
-
- 主题定义硬编码在 TypeScript 中(600+ 行颜色值),不支持自定义主题
|
|
1209
|
-
- Theme 类型 80+ 属性,命名不一致(如 `claudeBlue_FOR_SYSTEM_SPINNER`)
|
|
1210
|
-
- 编译后的 React 输出(`_c` memo cache)提交到源码中
|
|
1211
|
-
|
|
1212
|
-
### 汇总
|
|
1213
|
-
|
|
1214
|
-
| 严重度 | 数量 |
|
|
1215
|
-
|--------|------|
|
|
1216
|
-
| MEDIUM | 4(export colors 解析损坏、watcher 错误吞没、无预验证、rename 竞态) |
|
|
1217
|
-
| LOW | 3(缓存失效逻辑、isLightTheme 过于简单、模块级可变状态) |
|
|
1218
|
-
|
|
1219
|
-
**优先修复项:**
|
|
1220
|
-
1. 修复 `getThemeExportColors` 的变量解析——使用裸名引用替代 `$`-prefix
|
|
1221
|
-
2. 主题 watcher 的 rename 事件添加文件重建延迟检测(避免原子保存触发 fallback)
|
|
1222
|
-
3. 添加主题预览+取消工作流(预览时暂存原主题,取消时恢复)
|
|
1223
|
-
4. 添加 auto 模式——至少在启动时用 OSC 11 查询终端背景
|
|
1224
|
-
|
|
1225
|
-
---
|
|
1226
|
-
|
|
1227
|
-
## 2026-06-12 — TUI 框架核心扫描
|
|
1228
|
-
|
|
1229
|
-
扫描范围:`core/lib/tui/src/` 全部文件(tui.ts, terminal.ts, component.ts, container.ts, text.ts, input.ts, spacer.ts, box.ts, select-list.ts, utils.ts, overlay.ts 等),对照 CC `src/ink/` + `src/components/design-system/`
|
|
1230
|
-
|
|
1231
|
-
### 架构对比
|
|
1232
|
-
|
|
1233
|
-
**根本性差异:** CC 使用 React + Yoga 布局引擎 + 基于 Int32Array 的 cell 级屏幕缓冲 + 差异渲染。nanoPencil 使用命令式类组件 + `render(width): string[]` 返回文本行 + 字符串级差异渲染。CC 有完整的 CSS Flexbox 布局、事件系统、鼠标支持、文本选择、虚拟滚动。nanoPencil 仅手动垂直堆叠。
|
|
1234
|
-
|
|
1235
|
-
### 1. 正确性缺陷
|
|
1236
|
-
|
|
1237
|
-
| 严重度 | 发现 |
|
|
1238
|
-
|--------|------|
|
|
1239
|
-
| **MEDIUM** | **`visibleWidth()` ANSI 剥离 regex 不完整。** `utils.ts:125-131` 的 regex `\x1b\[[0-9;]*[mGKHJ]` 仅处理有限 CSI 终端字节。CC 使用 `strip-ansi` 库处理所有 CSI 序列。包含光标移动(`\x1b[3B`)、设备属性等序列时宽度计算错误,可能导致渲染崩溃。 |
|
|
1240
|
-
| **MEDIUM** | **Tab 宽度硬编码为 3 空格。** `text.ts:68` 和 `utils.ts:121` 全局 3 空格。CC 使用标准 8 列 tab-stop 对齐。非标准 tab 导致对齐错位。 |
|
|
1241
|
-
| **MEDIUM** | **Select-list 仅支持 `startsWith` 过滤。** `select-list.ts:47` 仅匹配开头。CC 支持完整子串/fuzzy 匹配。用户无法通过输入中间字符查找选项。 |
|
|
1242
|
-
| **LOW** | **`Spacer.render()` 返回空字符串。** `spacer.ts:31` 返回 `""` 而非 `" ".repeat(width)`。在 Box 内有背景时由 `applyBg` 填充,但作为 Container 直接子项时创建宽度为 0 的"隐形"行。 |
|
|
1243
|
-
| **LOW** | **`Input.render()` prompt 硬编码为 `"> "`。** `input.ts:433` 不可配置。CC 通过 props 接受任意 prompt。 |
|
|
1244
|
-
| **LOW** | **`Text.render()` 空文本返回不一致。** 文本为空且 paddingY=0 时可能返回 `[]` 或 `[""]`,取决于代码路径。 |
|
|
1245
|
-
| **LOW** | **`TUI.doRender()` 崩溃路径先 stop 再 throw。** `tui.ts:1123-1134` 先调用 `this.stop()` 再 throw,终端状态不一致。 |
|
|
1246
|
-
|
|
1247
|
-
### 2. 缺陷
|
|
1248
|
-
|
|
1249
|
-
| 严重度 | 发现 |
|
|
1250
|
-
|--------|------|
|
|
1251
|
-
| **HIGH** | **无事件系统。** CC 有完整 DOM 式事件模型(capture/bubble、stopPropagation、ClickEvent/FocusEvent/KeyboardEvent/InputEvent)。nanoPencil 组件仅接收原始键字符串,无事件对象、无冒泡、无捕获阶段。无法实现鼠标输入、焦点导航、事件委托。 |
|
|
1252
|
-
| **HIGH** | **无布局引擎。** CC 使用 Yoga(CSS Flexbox:row/column、flex-grow/shrink/basis、align/justify/wrap、position、overflow、margin/padding/border/gap、百分比 sizing)。nanoPencil 仅手动垂直堆叠,Box 仅有 paddingX/paddingY/bgFn。这是最大的架构差距。 |
|
|
1253
|
-
| **HIGH** | **无 ScrollBox/虚拟滚动。** CC 的 `overflow: scroll` 支持虚拟滚动、viewport 裁剪、sticky scroll、scroll-to-element、DECSTBM 硬件滚动优化。nanoPencil 无法处理长内容而不全量重渲染。 |
|
|
1254
|
-
| **MEDIUM** | **无崩溃恢复/终端状态保护。** CC 有 AlternateScreen、信号处理器(SIGINT/SIGTERM)恢复终端状态。nanoPencil 依赖调用方调用 `TUI.stop()`,未处理异常时终端留在 raw mode+隐藏光标。 |
|
|
1255
|
-
| **MEDIUM** | **`ProcessTerminal.stop()` 不排空输入。** `terminal.ts:254-291` 恢复 raw mode 前不调用 `drainInput()`。缓冲的 Kitty 协议响应可能泄漏到父 shell。 |
|
|
1256
|
-
| **MEDIUM** | **`parseCellSizeResponse()` 无超时处理。** `tui.ts:597` 部分转义序列未完成时立即放弃,终端响应缓冲区可能被当作用户输入消费,产生幻影按键。 |
|
|
1257
|
-
| **MEDIUM** | **`Box.setBgFn()` 缓存检测用采样值。** `box.ts:103` 用 `bgFn("test")` 采样。两个不同 bgFn 对 "test" 输出相同但对实际内容输出不同时缓存过期。 |
|
|
1258
|
-
| **LOW** | **非 TTY 环境无优雅降级。** `ProcessTerminal` 未检查 `process.stdout.isTTY` 就调用 `setRawMode(true)`,管道输出时崩溃。 |
|
|
1259
|
-
| **LOW** | **无 SIGCONT 处理。** `Ctrl+Z` + `fg` 后终端尺寸可能过期。 |
|
|
1260
|
-
|
|
1261
|
-
### 3. 高可用性
|
|
1262
|
-
|
|
1263
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1264
|
-
|------|-----------|-----|------|
|
|
1265
|
-
| 布局引擎 | 无(手动堆叠) | Yoga CSS Flexbox | **CC 压倒性优势** |
|
|
1266
|
-
| 屏幕缓冲 | 字符串级 diff | Int32Array cell 级+damage tracking+双缓冲 | **CC 压倒性优势** |
|
|
1267
|
-
| 事件系统 | 原始字符串 passthrough | DOM 式 capture/bubble+完整事件类型 | **CC 压倒性优势** |
|
|
1268
|
-
| 虚拟滚动 | 无 | ScrollBox+viewport culling+硬件滚动 | **CC 优势** |
|
|
1269
|
-
| 崩溃恢复 | 依赖调用方 stop() | 信号处理器+AlternateScreen | **CC 优势** |
|
|
1270
|
-
| 鼠标支持 | 无 | SGR 鼠标追踪+hit-test | **CC 优势** |
|
|
1271
|
-
| 文本选择 | 无 | Selection+NoSelect+clipboard | **CC 优势** |
|
|
1272
|
-
| 终端兼容性 | Kitty 协议+blocklist+同步输出 | Kitty+XTVERSION 探测+更多 bug 规避 | 持平 |
|
|
1273
|
-
| 文档 | WHO/FROM/TO/HERE JSDoc | 最少文件级文档 | **nanoPencil 优势** |
|
|
1274
|
-
| 调试 | 多级 debug+崩溃日志 | 性能检测+重绘调试 | 持平 |
|
|
1275
|
-
|
|
1276
|
-
### 4. CC 功能差距(主要项)
|
|
1277
|
-
|
|
1278
|
-
| 功能 | CC | nanoPencil |
|
|
1279
|
-
|------|-----|-----------|
|
|
1280
|
-
| CSS Flexbox 布局 | Yoga:row/column、flex-grow/shrink/basis、align/justify/wrap、position、overflow | 手动垂直堆叠 |
|
|
1281
|
-
| React 组件模型 | JSX+reconciler+hooks | 命令式类+render(width) |
|
|
1282
|
-
| 8 种文本换行 | wrap/wrap-trim/end/middle/truncate-* | 仅 word wrap |
|
|
1283
|
-
| ScrollBox | 虚拟滚动+viewport culling+sticky scroll+硬件滚动 | 无 |
|
|
1284
|
-
| Alternate Screen | 进入/退出+鼠标追踪+主屏保留 | 无 |
|
|
1285
|
-
| 鼠标支持 | SGR 追踪+hit-test+mouseenter/mouseleave | 无 |
|
|
1286
|
-
| 文本选择/复制 | Selection+NoSelect+highlight+clipboard | 无 |
|
|
1287
|
-
| 搜索高亮 | 逐 cell 搜索高亮+当前位置追踪 | 无 |
|
|
1288
|
-
| 焦点管理 | FocusManager+focus stack+tabIndex+autoFocus | 单一 focused 布尔值 |
|
|
1289
|
-
| 事件系统 | capture/bubble+stopPropagation+ClickEvent/FocusEvent/KeyboardEvent | 原始字符串 |
|
|
1290
|
-
| OSC 8 超链接 | cell 级超链接+HyperlinkPool | 无 |
|
|
1291
|
-
| BiDi 文本 | reorderBidi() | 无 |
|
|
1292
|
-
| Cell 级差异渲染 | diffEach() Int32Array+damage tracking+blit 优化 | 字符串行级 diff |
|
|
1293
|
-
| 屏幕缓冲 | Int32Array packed cells+CharPool/StylePool/HyperlinkPool+双缓冲 | 无 |
|
|
1294
|
-
| 完整 SGR 样式 | color/bg/bold/dim/italic/underline/strikethrough/inverse/opacity+StylePool | bgFn 回调 |
|
|
1295
|
-
| 图片渲染 | Kitty/iTerm2 内联图片 | 独立 Image 组件 |
|
|
1296
|
-
| 性能检测 | commit/yoga/render/scroll timing+重绘调试 | 仅文件 debug 日志 |
|
|
1297
|
-
| 进度报告 | OSC 9;4 终端任务栏进度 | 无 |
|
|
1298
|
-
| NoSelect 组件 | 排除选择区域 | 无 |
|
|
1299
|
-
| Soft wrap 追踪 | 逐行 softWrap 位图 | 无 |
|
|
1300
|
-
|
|
1301
|
-
### 5. 代码质量对比
|
|
1302
|
-
|
|
1303
|
-
**nanoPencil 优势:**
|
|
1304
|
-
- 优秀的 WHO/FROM/TO/HERE JSDoc 文档(CC 缺少文件级文档)
|
|
1305
|
-
- 清晰的 barrel exports 和模块组织
|
|
1306
|
-
- 回归测试覆盖(image line 检测、regional indicator 宽度、overlay 样式泄漏)
|
|
1307
|
-
- 多级调试(NANOPENCIL_DEBUG_RENDER/REDRAW/TUI_DEBUG)
|
|
1308
|
-
|
|
1309
|
-
**nanoPencil 弱点:**
|
|
1310
|
-
- 字符串级渲染——比较渲染字符串做 diff 是 O(n) per line per frame,CC 比较 packed 64-bit 整数(cache-friendly,可 SIMD 优化)
|
|
1311
|
-
- 无布局和渲染分离——每个组件同时负责两者(CC 分离为 yoga layout → output rendering → screen diffing 三阶段)
|
|
1312
|
-
- 手动 ANSI 解析(regex)——CC 使用 `@alcalzone/ansi-tokenize` 正确处理所有 ANSI 序列类型
|
|
1313
|
-
- `visibleWidth()` 缓存无大小限制——CC 的 `charCache` 超过 16384 条目时清空
|
|
1314
|
-
|
|
1315
|
-
### 汇总
|
|
1316
|
-
|
|
1317
|
-
| 严重度 | 数量 |
|
|
1318
|
-
|--------|------|
|
|
1319
|
-
| HIGH | 3(无事件系统、无布局引擎、无虚拟滚动) |
|
|
1320
|
-
| MEDIUM | 6(ANSI 剥离不完整、tab 硬编码、startsWith 过滤、无崩溃恢复、stop 不排空、cellSize 无超时、bgFn 采样) |
|
|
1321
|
-
| LOW | 5(Spacer 空字符串、Input prompt 硬编码、Text 空文本、doRender 崩溃、非 TTY、SIGCONT) |
|
|
1322
|
-
|
|
1323
|
-
**优先修复项:**
|
|
1324
|
-
1. **HIGH**: 修复 `visibleWidth()` ANSI 剥离——使用完整的 ANSI 解析库或扩展 regex 覆盖所有 CSI 序列
|
|
1325
|
-
2. **HIGH**: Tab 宽度改为 8 空格(标准 tab-stop)或实现 tab-stop 对齐
|
|
1326
|
-
3. **HIGH**: Select-list 改为子串/fuzzy 匹配
|
|
1327
|
-
4. **MEDIUM**: `ProcessTerminal.stop()` 添加 `drainInput()` 调用
|
|
1328
|
-
5. **MEDIUM**: 添加 SIGINT/SIGTERM 信号处理器恢复终端状态
|
|
1329
|
-
|
|
1330
|
-
**注意:** 布局引擎、事件系统、虚拟滚动等是架构级差距,需要长期规划而非简单修复。
|
|
1331
|
-
|
|
1332
|
-
---
|
|
1333
|
-
|
|
1334
|
-
## 2026-06-12 — Config/Settings 系统扫描
|
|
1335
|
-
|
|
1336
|
-
扫描范围:`core/platform/config/settings-manager.ts` (1309行), `auth-storage.ts`, `resolve-config-value.ts`, `resource-loader.ts`, `config.ts`, 对照 CC `src/utils/settings/` (12文件) + `src/utils/config.ts` (1824行)
|
|
1337
|
-
|
|
1338
|
-
### 架构对比
|
|
1339
|
-
|
|
1340
|
-
nanoPencil 使用 2 层配置(global + project)+ 单一 `SettingsManager` 大类(1309 行)。CC 使用 5 层配置 cascade(user→project→local→flag→policy)+ 12 文件精细分离(types/cache/validation/changeDetector/mdm)+ Zod v4 schema 验证。
|
|
1341
|
-
|
|
1342
|
-
### 1. 正确性缺陷
|
|
1343
|
-
|
|
1344
|
-
| 严重度 | 发现 |
|
|
1345
|
-
|--------|------|
|
|
1346
|
-
| **HIGH** | **`resolveConfigValue` 将环境变量未设置误作字面字符串。** `resolve-config-value.ts:22`:`process.env[config]` 未设置时返回 config 本身(如 `"MY_API_KEY"`)而非 `undefined`。API key 字段会静默使用变量名作为 key,产生混淆的 401 错误。空字符串 env var 也因 `||` 被视为"未设置"。 |
|
|
1347
|
-
| **HIGH** | **Settings.json 无 schema 验证。** `settings-manager.ts:429` 直接 `JSON.parse` + `as Settings` 类型断言。拼写错误(`"defaltProvider"`/`"showImags"`)被静默忽略,用户无反馈。CC 使用 Zod v4 + `.safeParse()` + 人类可读错误+建议+文档链接。 |
|
|
1348
|
-
| **MEDIUM** | **`deepMergeSettings` 仅合并一层。** `settings-manager.ts:162-190` 浅展开 `{...base, ...override}`。当前两层嵌套刚好正确,但三层嵌套(如 `settings.nanomem.autoDream.enabled`)会丢失 base 值。CC 用 `lodash.mergeWith` 真正递归深合并。 |
|
|
1349
|
-
| **LOW** | **`getClearOnShrink` 读取旧 env var 前缀。** `settings-manager.ts:1147` 使用 `PI_CLEAR_ON_SHRINK`(旧前缀),其余代码用 `NANOPENCIL_*`。迁移未完成。 |
|
|
1350
|
-
|
|
1351
|
-
### 2. 缺陷
|
|
1352
|
-
|
|
1353
|
-
| 严重度 | 发现 |
|
|
1354
|
-
|--------|------|
|
|
1355
|
-
| **HIGH** | **无配置文件变更监听。** 无 chokidar/fs.watch。多实例(两个终端)修改 settings.json 时互相无感知,静默不一致。CC 有 `changeDetector.ts` (489行):chokidar 监听+写入稳定性阈值(1s)+删除宽限期(1.7s)+自写检测(5s)+ConfigChange hooks。 |
|
|
1356
|
-
| **HIGH** | **无配置写入前备份。** 直接覆盖写入,断电/崩溃时永久丢失。CC 每次写入前创建时间戳备份(`~/.claude/backups/`),保留最近 5 个,损坏文件单独备份(`.corrupted.*`)并提供恢复指令。 |
|
|
1357
|
-
| **HIGH** | **无损坏恢复。** JSON 解析失败时静默回退到默认值,用户无通知,无备份恢复尝试。CC 的恢复流程:备份损坏文件→搜索最近备份→stderr 输出恢复指令→记录分析事件→`wouldLoseAuthState` 守卫防止覆盖好的缓存配置。 |
|
|
1358
|
-
| **MEDIUM** | **`withLock` 首次创建竞态。** `settings-manager.ts:214-242` 仅在文件存在时加锁。两个进程首次创建 settings.json 时都跳过锁,同时写入,一个丢失。`withLockAsync` 使用 `lockfile.lockSync` 阻塞事件循环。 |
|
|
1359
|
-
| **MEDIUM** | **SettingsManager 1309 行 God class。** 合并了类型定义、深合并、文件存储、内存存储、迁移逻辑、40+ getter/setter。CC 拆分为 12 个文件各司其职。 |
|
|
1360
|
-
| **LOW** | **Setter 代码大量重复。** ~30 个 setter 遵循相同模式(初始化嵌套对象→赋值→markModified→save)。可用 `setNestedField(scope, path, value)` 辅助函数消除。 |
|
|
1361
|
-
|
|
1362
|
-
### 3. 高可用性
|
|
1363
|
-
|
|
1364
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1365
|
-
|------|-----------|-----|------|
|
|
1366
|
-
| 配置源层数 | 2(global/project) | 5(user/project/local/flag/policy) | **CC 优势** |
|
|
1367
|
-
| Schema 验证 | 无(JSON.parse + as) | Zod v4 + safeParse + 错误消息+建议+文档链接 | **CC 压倒性优势** |
|
|
1368
|
-
| 文件变更监听 | 无 | chokidar + 写入稳定性+删除宽限+自写检测 | **CC 压倒性优势** |
|
|
1369
|
-
| 写入备份 | 无 | 时间戳备份+最近 5 个+损坏隔离 | **CC 压倒性优势** |
|
|
1370
|
-
| 损坏恢复 | 静默回退默认值 | 备份损坏→搜索最近→恢复指令→守卫 | **CC 优势** |
|
|
1371
|
-
| MDM/企业策略 | 无 | macOS plist/Windows registry/远程托管 | **CC 优势** |
|
|
1372
|
-
| 缓存架构 | 无缓存(每次读磁盘) | 三级缓存(session/source/file) | **CC 优势** |
|
|
1373
|
-
| 本地覆盖 | 无 localSettings | `localSettings` 自动加入 .gitignore | **CC 优势** |
|
|
1374
|
-
| 配置工具 | 无 | ConfigTool(LLM 读写配置) | **CC 优势** |
|
|
1375
|
-
| Storage 接口 | `SettingsStorage` 接口+InMemory 实现 | 无等价抽象 | **nanoPencil 优势** |
|
|
1376
|
-
| 文档 | WHO/FROM/TO/HERE JSDoc | 向后兼容性文档 | 持平 |
|
|
1377
|
-
|
|
1378
|
-
### 4. CC 功能差距
|
|
1379
|
-
|
|
1380
|
-
| 功能 | CC | nanoPencil |
|
|
1381
|
-
|------|-----|-----------|
|
|
1382
|
-
| Zod schema 验证 | 100+ 字段+类型强制+枚举+regex+自定义验证器 | 无 |
|
|
1383
|
-
| 5 层配置 cascade | user→project→local→flag→policy | 2 层(global/project) |
|
|
1384
|
-
| 文件变更监听 | chokidar+debounce+grace periods+内部写检测 | 无 |
|
|
1385
|
-
| 配置备份+恢复 | 时间戳备份+损坏隔离+恢复指令 | 无 |
|
|
1386
|
-
| MDM 企业策略 | macOS plist/Windows registry/远程托管 | 无 |
|
|
1387
|
-
| ConfigChange hooks | 设置变更前后钩子 | 无 |
|
|
1388
|
-
| 验证错误消息 | 人类可读+建议+文档链接 | 无 |
|
|
1389
|
-
| Gitignore 自动添加 | localSettings 自动加入 .gitignore | 无 |
|
|
1390
|
-
| ConfigTool | LLM 通过工具读写设置 | 无 |
|
|
1391
|
-
| Auth-loss 守卫 | 检测损坏读取,拒绝覆盖 | 无 |
|
|
1392
|
-
| Settings with sources API | `getSettingsWithSources()` 显示来源 | 无 |
|
|
1393
|
-
| Schema JSON URL | 发布到 schemastore.org 供 IDE 自动补全 | 无 |
|
|
1394
|
-
| 三级缓存 | session/source/file 级缓存 | 无 |
|
|
1395
|
-
| `--setting-sources` CLI | 过滤活动源 | 无 |
|
|
1396
|
-
| Cowork 模式 | 独立 `cowork_settings.json` | 无 |
|
|
1397
|
-
| 远程托管设置 | API 获取企业设置 | 无 |
|
|
1398
|
-
| 重入守卫 | `insideGetConfig` 防无限递归 | 无 |
|
|
1399
|
-
|
|
1400
|
-
### 5. 代码质量对比
|
|
1401
|
-
|
|
1402
|
-
**nanoPencil 优势:**
|
|
1403
|
-
- `SettingsStorage` 接口+`InMemorySettingsStorage` 测试实现(仓库模式)
|
|
1404
|
-
- 每个设置有专用 getter/setter(明确可审计)
|
|
1405
|
-
- WHO/FROM/TO/HERE JSDoc 文档
|
|
1406
|
-
|
|
1407
|
-
**nanoPencil 弱点:**
|
|
1408
|
-
- SettingsManager 1309 行 God class
|
|
1409
|
-
- ~30 个 setter 大量重复代码
|
|
1410
|
-
- `save()` vs `saveProjectSettings()` 不对称
|
|
1411
|
-
- 混合同步/异步无清晰策略(`withLockAsync` 内部用 `lockSync` 阻塞事件循环)
|
|
1412
|
-
|
|
1413
|
-
**CC 弱点:**
|
|
1414
|
-
- `config.ts` 1824 行单体文件
|
|
1415
|
-
- `GlobalConfig` 类型 100+ 字段(许多是一次性追踪标志)
|
|
1416
|
-
|
|
1417
|
-
### 汇总
|
|
1418
|
-
|
|
1419
|
-
| 严重度 | 数量 |
|
|
1420
|
-
|--------|------|
|
|
1421
|
-
| HIGH | 4(resolveConfigValue 误返回、无 schema 验证、无文件监听、无备份/恢复) |
|
|
1422
|
-
| MEDIUM | 3(深合并仅一层、withLock 竞态、SettingsManager 过大) |
|
|
1423
|
-
| LOW | 2(旧 env var 前缀、setter 重复) |
|
|
1424
|
-
|
|
1425
|
-
**优先修复项:**
|
|
1426
|
-
1. **CRITICAL**: 修复 `resolveConfigValue`——env var 未设置时返回 `undefined`,空字符串也应视为有效值
|
|
1427
|
-
2. **CRITICAL**: 添加 Settings Zod schema 验证——至少验证字段存在性和类型
|
|
1428
|
-
3. **HIGH**: 写入前创建备份(至少保留最近 1 个)
|
|
1429
|
-
4. **HIGH**: 添加 chokidar 文件变更监听(至少支持多实例同步)
|
|
1430
|
-
5. **HIGH**: 损坏恢复——JSON 解析失败时搜索备份并通知用户
|
|
1431
|
-
|
|
1432
|
-
---
|
|
1433
|
-
|
|
1434
|
-
## 2026-06-12 — LLM 通信层扫描
|
|
1435
|
-
|
|
1436
|
-
扫描范围:`core/lib/ai/src/`(stream.ts, api-registry.ts, types.ts, utils/event-stream.ts, providers/*.ts, overflow.ts, debug-logger.ts),对照 CC `src/services/api/claude.ts` (3400行) + `withRetry.ts` (823行) + `errors.ts` (1208行) + `errorUtils.ts` + `client.ts`
|
|
1437
|
-
|
|
1438
|
-
### 架构对比
|
|
1439
|
-
|
|
1440
|
-
nanoPencil 使用模块化 provider 架构:每个 provider 独立文件+统一接口+懒加载注册。CC 使用单体 `claude.ts`(3400行)+ 独立重试/错误分类/客户端构造文件。nanoPencil 架构更清洁,但 CC 的错误处理和重试逻辑远更完善。
|
|
1441
|
-
|
|
1442
|
-
### 1. 正确性缺陷
|
|
1443
|
-
|
|
1444
|
-
| 严重度 | 发现 |
|
|
1445
|
-
|--------|------|
|
|
1446
|
-
| **CRITICAL** | **重试时丢弃部分事件。** `stream.ts:396-399`:`if (attempt === 0) { outerStream.push(event); }` 重试时不转发中间事件。消费者看到事件中途停止,无终止事件,然后什么都没有,直到重试成功或终止。无重试进行中的信号。CC 在 API 调用级别重试,部分结果从不到达消费者。 |
|
|
1447
|
-
| **HIGH** | **`mapStopReason` 对未知值 throw。** `anthropic.ts:916`:注释说"handle gracefully"但代码 throw Error,会崩溃流并产生用户错误消息。 |
|
|
1448
|
-
| **HIGH** | **OpenAI `mapStopReason` 的 `never` 检查。** `openai-completions.ts:907-911`:`const _exhaustive: never = reason; throw`。OpenAI 定期添加新 `finish_reason` 值,会直接崩溃流。 |
|
|
1449
|
-
| **MEDIUM** | **Bedrock `mapStopReason` 静默映射未知值为 "error"。** `amazon-bedrock.ts:688`:避免崩溃但用户看到错误而非正常处理。 |
|
|
1450
|
-
|
|
1451
|
-
### 2. 缺陷
|
|
1452
|
-
|
|
1453
|
-
| 严重度 | 发现 |
|
|
1454
|
-
|--------|------|
|
|
1455
|
-
| **HIGH** | **无 HTTP 级错误分类。** 重试逻辑用 regex 匹配错误消息字符串。CC 有 40+ 具体错误分类分支:SSL/TLS 证书错误、HTTP 状态码(401/403/408/413/429/529 等子类别)、Provider 特定错误(Bedrock/Vertex/Azure auth)、内容错误(prompt too long/PDF/image size)、CloudFlare HTML 清理、OAuth token 撤销检测。 |
|
|
1456
|
-
| **HIGH** | **无 401 auth token 刷新。** CC 在 401/403 时自动刷新 OAuth token 并重建客户端。nanoPencil 用过期 token 重试,浪费重试次数。 |
|
|
1457
|
-
| **HIGH** | **无过期连接检测。** CC 检测 ECONNRESET/EPIPE 禁用连接池。nanoPencil 用同一池化连接重试。 |
|
|
1458
|
-
| **MEDIUM** | **无 529 过载专项处理。** CC 有连续错误追踪+fallback 模型触发+持久重试模式+fast-mode 冷却。nanoPencil 当作普通可重试错误。 |
|
|
1459
|
-
| **MEDIUM** | **无 `x-should-retry` 响应头。** CC 读取此头决定是否重试。nanoPencil 完全忽略响应头。 |
|
|
1460
|
-
| **MEDIUM** | **无 context overflow 自动恢复。** CC 检测 `max_tokens` 溢出后自动调整参数重试。nanoPencil 检测到但不重试。 |
|
|
1461
|
-
| **MEDIUM** | **无速率限制头解析。** CC 读取 `anthropic-ratelimit-unified-reset` 等待实际重置时间。nanoPencil 无速率限制感知。 |
|
|
1462
|
-
| **LOW** | **`debug-logger.ts` 使用同步 `appendFileSync`。** 每次日志调用阻塞事件循环。`rotateIfNeeded` 用 `require("fs")` 而非已导入的 `fs`。 |
|
|
1463
|
-
|
|
1464
|
-
### 3. 高可用性
|
|
1465
|
-
|
|
1466
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1467
|
-
|------|-----------|-----|------|
|
|
1468
|
-
| 最大重试次数 | 3 | 10(可配置) | **CC 优势** |
|
|
1469
|
-
| 529 过载处理 | 通用可重试 | 连续追踪+fallback+持久模式+fast-mode | **CC 压倒性优势** |
|
|
1470
|
-
| Auth token 刷新 | 无 | 401/403 自动刷新 OAuth | **CC 压倒性优势** |
|
|
1471
|
-
| 过期连接处理 | 无 | ECONNRESET/EPIPE 检测+禁用连接池 | **CC 优势** |
|
|
1472
|
-
| Context overflow | 检测但不恢复 | 自动调整 max_tokens 重试 | **CC 优势** |
|
|
1473
|
-
| 模型 fallback | 无 | Opus→Sonnet 持续 529 降级 | **CC 优势** |
|
|
1474
|
-
| 速率限制头 | 无 | 读取 `anthropic-ratelimit-*` | **CC 优势** |
|
|
1475
|
-
| 持久/无人重试 | 无 | 无限重试+心跳+6 小时重置 | **CC 优势** |
|
|
1476
|
-
| 错误分类 | 字符串匹配 | 40+ 具体类型+人类可读消息 | **CC 压倒性优势** |
|
|
1477
|
-
| Provider 架构 | 模块化+懒加载+统一接口 | 单体 claude.ts | **nanoPencil 优势** |
|
|
1478
|
-
| 类型安全 | TypeScript 泛型 | 类型安全但耦合 Anthropic | 持平 |
|
|
1479
|
-
|
|
1480
|
-
### 4. CC 功能差距
|
|
1481
|
-
|
|
1482
|
-
| 功能 | CC | nanoPencil |
|
|
1483
|
-
|------|-----|-----------|
|
|
1484
|
-
| 529 过载处理 | 连续追踪+fallback 模型+持久重试+fast-mode | 通用可重试 |
|
|
1485
|
-
| Auth token 刷新 | OAuth 401 自动刷新+客户端重建 | 无 |
|
|
1486
|
-
| 过期连接检测 | ECONNRESET/EPIPE+连接池禁用 | 无 |
|
|
1487
|
-
| Context overflow 恢复 | 自动调整 max_tokens 重试 | 检测不恢复 |
|
|
1488
|
-
| 模型 fallback | Opus→Sonnet 持续 529 | 无 |
|
|
1489
|
-
| 速率限制头 | `anthropic-ratelimit-unified-reset` | 无 |
|
|
1490
|
-
| 持久无人重试 | 无限重试+心跳+5 分钟退避+6 小时重置 | 无 |
|
|
1491
|
-
| 40+ 错误分类 | SSL/HTTP/Provider/Content/OAuth | 字符串 regex |
|
|
1492
|
-
| CloudFlare HTML 清理 | 错误页面→可读消息 | 无 |
|
|
1493
|
-
| 流式 VCR/录制 | `withStreamingVCR` 回放 | 无 |
|
|
1494
|
-
| 客户端请求 ID | UUID 超时关联 | 无 |
|
|
1495
|
-
| API 超时配置 | `API_TIMEOUT_MS` 环境变量 | SDK 默认 |
|
|
1496
|
-
| Prompt cache 断裂检测 | 记录 cache 状态,检测断裂 | 无 |
|
|
1497
|
-
| Microcompact/自适应上下文 | API 上下文管理 | 无 |
|
|
1498
|
-
| Tool use/result 配对验证 | `ensureToolResultPairing` 去重 | 仅 transform-messages |
|
|
1499
|
-
| 快速模式 | 速度切换+冷却 | 无 |
|
|
1500
|
-
| Anti-distillation | 假 tool 注入 | 无 |
|
|
1501
|
-
|
|
1502
|
-
### 5. 代码质量对比
|
|
1503
|
-
|
|
1504
|
-
**nanoPencil 优势:**
|
|
1505
|
-
- 模块化 provider 架构:每个 provider 独立文件+统一接口
|
|
1506
|
-
- TypeScript 泛型类型安全(`Model<TApi>`, `StreamFunction<TApi, TOptions>`)
|
|
1507
|
-
- 懒加载 provider 注册
|
|
1508
|
-
- `EventStream` 类设计良好(异步迭代+final-result 追踪)
|
|
1509
|
-
- `overflow.ts` 检测全面(14+ provider 特定模式)
|
|
1510
|
-
- WHO/FROM/TO/HERE JSDoc 文档
|
|
1511
|
-
|
|
1512
|
-
**nanoPencil 弱点:**
|
|
1513
|
-
- `stream.ts` 重试包装器复杂且有部分事件丢弃 bug
|
|
1514
|
-
- 错误处理薄弱——错误仅字符串化推送
|
|
1515
|
-
- `debug-logger.ts` 同步 `appendFileSync` 阻塞事件循环
|
|
1516
|
-
- 无结构化错误类型——一切为 `AssistantMessage` + `errorMessage: string`
|
|
1517
|
-
|
|
1518
|
-
**CC 弱点:**
|
|
1519
|
-
- `claude.ts` 3400 行单体
|
|
1520
|
-
- 耦合 Anthropic 特定 API 和 beta headers
|
|
1521
|
-
- feature-flag 条件散布
|
|
1522
|
-
|
|
1523
|
-
### 汇总
|
|
1524
|
-
|
|
1525
|
-
| 严重度 | 数量 |
|
|
1526
|
-
|--------|------|
|
|
1527
|
-
| CRITICAL | 1(重试丢弃部分事件) |
|
|
1528
|
-
| HIGH | 4(mapStopReason throw×2、无错误分类、无 auth 刷新、无过期连接检测) |
|
|
1529
|
-
| MEDIUM | 4(529 无专项、无 x-should-retry、无 overflow 恢复、无速率限制头) |
|
|
1530
|
-
| LOW | 1(同步日志) |
|
|
1531
|
-
|
|
1532
|
-
**优先修复项:**
|
|
1533
|
-
1. **CRITICAL**: 修复重试时部分事件丢弃——重试前发送"重试中"信号或缓冲完整流
|
|
1534
|
-
2. **HIGH**: `mapStopReason` 对未知值降级为 `"end_turn"` 而非 throw
|
|
1535
|
-
3. **HIGH**: 添加 401/403 auth token 刷新(至少支持 OAuth provider)
|
|
1536
|
-
4. **HIGH**: 添加结构化错误分类(至少区分 401/429/529/network)
|
|
1537
|
-
5. **MEDIUM**: 重试次数从 3 提升到 10
|
|
1538
|
-
6. **MEDIUM**: 添加 529 连续追踪+模型 fallback
|
|
1539
|
-
|
|
1540
|
-
---
|
|
1541
|
-
|
|
1542
|
-
## 2026-06-12 — Agent Core 主循环扫描
|
|
1543
|
-
|
|
1544
|
-
扫描范围:`core/lib/agent-core/src/`(agent-loop.ts 1158行, agent.ts 737行, types.ts 463行, errors.ts 201行, continuations.ts, tool-results.ts, stream-events.ts, structured-adaptive-*.ts)+ `core/runtime/`(agent-session.ts, compaction-controller.ts, retry-coordinator.ts),对照 CC `src/query.ts` (1736行) + `src/QueryEngine.ts` + `src/utils/conversationRecovery.ts` (598行) + `src/query/stopHooks.ts`
|
|
1545
|
-
|
|
1546
|
-
### 架构对比
|
|
1547
|
-
|
|
1548
|
-
nanoPencil 有两套循环:标准 `agent-loop.ts`(1158行)和 `structured-adaptive-agent-loop.ts`(弱模型兼容)。CC 有 `query.ts`(1736行)+ 独立模块(stopHooks/toolOrchestration/StreamingToolExecutor/transitions)。nanoPencil 错误层次更优(AgentError 类层次 vs CC 的字符串匹配),但 CC 的上下文管理远更完善。
|
|
1549
|
-
|
|
1550
|
-
### 1. 正确性缺陷
|
|
1551
|
-
|
|
1552
|
-
| 严重度 | 发现 |
|
|
1553
|
-
|--------|------|
|
|
1554
|
-
| **MEDIUM** | **`endWithLoopError()` 缺少 `turn_end` 事件。** `agent-loop.ts:190-218`:错误路径发射 `message_start`/`message_end` 但不发射 `turn_end`,导致 `agent_result` 事件携带 `turnCount:0`/`toolCallCount:0`,即使已执行多轮。正常路径(line 500)始终发射 `turn_end`。 |
|
|
1555
|
-
| **MEDIUM** | **`isStreaming` 守卫非重入安全。** `agent.ts:476`:`prompt()` 检查 `isStreaming` 后 throw,但无锁。两个并发 `prompt()` 调用在微任务中可同时通过检查。CC 用单线程 generator 模式避免。 |
|
|
1556
|
-
| **MEDIUM** | **`waitForAssistantStream` abort 时可能泄漏资源。** `agent-loop.ts:709-717`:返回 "aborted" 时不调用 `responseIterator.return()`。对比 line 750 的逐事件 abort 有显式清理。流迭代器可能未正确清理。 |
|
|
1557
|
-
| **LOW** | **`resolveRunningPrompt` 内存保留风险。** `agent.ts:548-549`:若 `_runLoop` 在 finally 前抛出异常,promise 永不 settle,`waitForIdle()` 永久挂起。 |
|
|
1558
|
-
|
|
1559
|
-
### 2. 缺陷
|
|
1560
|
-
|
|
1561
|
-
| 严重度 | 发现 |
|
|
1562
|
-
|--------|------|
|
|
1563
|
-
| **HIGH** | **无响应式压缩(reactive compaction)。** CC 的 `reactiveCompact` 在 413/prompt-too-long 时压缩上下文立即重试,支持多层策略(context collapse drain → reactive compact → surface error)。nanoPencil 仅有手动压缩+API 调用前检查,`recoverModelError` 最多重试 1 次。 |
|
|
1564
|
-
| **HIGH** | **无多层上下文管理。** CC 有 snipCompact(历史裁剪)+ microcompact(tool-result 级压缩)+ contextCollapse(旧消息归档)+ autoCompact。nanoPencil 仅有全量压缩。长 session 中 tool results 仅截断不总结。 |
|
|
1565
|
-
| **HIGH** | **无会话恢复中断检测。** CC 的 `deserializeMessagesWithInterruptDetection()` 检测 session 中断轮次并注入 "Continue from where you left off" 合成消息。nanoPencil 有 session 持久化但无中断检测。 |
|
|
1566
|
-
| **MEDIUM** | **标准循环无流式工具执行。** CC 的 `StreamingToolExecutor` 在流式传输期间就开始执行工具。nanoPencil 标准循环等待完整响应后批量执行(line 936-1060)。仅 structured-adaptive 路径有早期执行。 |
|
|
1567
|
-
| **MEDIUM** | **无 fallback 模型。** CC 的 `FallbackTriggeredError` 在模型过载时自动切换。nanoPencil 仅通过 `recoverModelError` 单次重试。 |
|
|
1568
|
-
| **MEDIUM** | **无 529 指数退避重试。** CC 有 10 次重试+指数退避+前台/后台策略+无人值守模式。nanoPencil 的 `RetryCoordinator` 较简单。 |
|
|
1569
|
-
| **LOW** | **无 tool-result 持久化替换。** CC 的 `toolResultStorage` 用引用替换大结果并持久化。nanoPencil 恢复 session 时需全量保留在内存。 |
|
|
1570
|
-
| **LOW** | **无文件历史快照。** CC 保存 `FileHistorySnapshot` 恢复文件状态缓存。nanoPencil 无文件状态缓存。 |
|
|
1571
|
-
|
|
1572
|
-
### 3. 高可用性
|
|
1573
|
-
|
|
1574
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1575
|
-
|------|-----------|-----|------|
|
|
1576
|
-
| 响应式压缩 | 无(仅手动+预检查) | 413 时自动压缩+多层策略 | **CC 压倒性优势** |
|
|
1577
|
-
| 多层上下文 | 全量压缩 | snip/micro/contextCollapse/auto | **CC 压倒性优势** |
|
|
1578
|
-
| 会话恢复 | SessionManager 持久化 | 中断检测+"Continue"注入 | **CC 优势** |
|
|
1579
|
-
| 流式工具执行 | 仅弱模型路径 | 标准路径支持 | **CC 优势** |
|
|
1580
|
-
| Fallback 模型 | 无 | 自动切换 | **CC 优势** |
|
|
1581
|
-
| 重试策略 | 基本重试 | 10 次+指数退避+per-source 策略 | **CC 优势** |
|
|
1582
|
-
| Tool-result 预算 | 截断 | 引用替换+持久化 | **CC 优势** |
|
|
1583
|
-
| 错误层次 | AgentError 类层次 | 字符串匹配 | **nanoPencil 优势** |
|
|
1584
|
-
| 类型系统 | 显式 Transition/Policy/Result 类型 | 散布在各处 | **nanoPencil 优势** |
|
|
1585
|
-
| 多 Provider | streamProxy+多 provider | 仅 Anthropic | **nanoPencil 优势** |
|
|
1586
|
-
| 能力接口 | 窄 capability interfaces(DI) | 大 context 对象直接传递 | **nanoPencil 优势** |
|
|
1587
|
-
|
|
1588
|
-
### 4. CC 功能差距
|
|
1589
|
-
|
|
1590
|
-
| 功能 | CC | nanoPencil |
|
|
1591
|
-
|------|-----|-----------|
|
|
1592
|
-
| 响应式压缩 | 413 时自动压缩+多层恢复 | 无 |
|
|
1593
|
-
| Microcompact | tool-result 级智能压缩 | 仅截断 |
|
|
1594
|
-
| Context collapse | 旧消息渐进归档 | 无 |
|
|
1595
|
-
| Snip compact | 历史裁剪 | 无 |
|
|
1596
|
-
| 流式工具执行 | 标准路径流式期间执行 | 仅弱模型路径 |
|
|
1597
|
-
| Fallback 模型 | 自动模型切换+签名剥离 | 无 |
|
|
1598
|
-
| 529/429 指数退避 | 10 次+退避+per-source 策略 | 基本 |
|
|
1599
|
-
| 会话恢复中断检测 | `detectTurnInterruption` | 无 |
|
|
1600
|
-
| Tool-result 预算 | 内容替换+磁盘持久化 | 截断 |
|
|
1601
|
-
| 文件历史快照 | `FileHistorySnapshot` | 无 |
|
|
1602
|
-
| Session 记忆提取 | extractMemories+autoDream | 无 |
|
|
1603
|
-
| Prompt 建议 | 有 | 无 |
|
|
1604
|
-
| Skill 发现预取 | 有 | 无 |
|
|
1605
|
-
|
|
1606
|
-
### 5. 代码质量对比
|
|
1607
|
-
|
|
1608
|
-
**nanoPencil 优势:**
|
|
1609
|
-
- `AgentError` 类层次(NetworkError/RateLimitError/ContextOverflowError 等)+ `classifyApiError()` + `retriable` 标志
|
|
1610
|
-
- 显式类型定义(AgentLoopTransition/AgentRunPolicy/AgentRunResult)
|
|
1611
|
-
- 能力接口模式(`session-context.ts` 窄接口替代完整 AgentSession)
|
|
1612
|
-
- WHO/FROM/TO/HERE JSDoc 文档
|
|
1613
|
-
|
|
1614
|
-
**nanoPencil 弱点:**
|
|
1615
|
-
- `agent-loop.ts` 1158 行处理一切(循环控制+工具执行+流式+错误恢复+后续+转向+stop hooks+token 预算)
|
|
1616
|
-
- 标准循环用 `let` 变量追踪状态(CC 用 State 对象+immutable-at-boundary)
|
|
1617
|
-
- 标准循环无流式工具执行(仅弱模型路径有)
|
|
1618
|
-
|
|
1619
|
-
### 汇总
|
|
1620
|
-
|
|
1621
|
-
| 严重度 | 数量 |
|
|
1622
|
-
|--------|------|
|
|
1623
|
-
| HIGH | 3(无响应式压缩、无多层上下文、无会话恢复中断检测) |
|
|
1624
|
-
| MEDIUM | 5(turn_end 缺失、isStreaming 竞态、abort 泄漏、无流式工具、无 fallback、无 529 退避) |
|
|
1625
|
-
| LOW | 3(resolveRunningPrompt、tool-result 持久化、文件历史快照) |
|
|
1626
|
-
|
|
1627
|
-
**优先修复项:**
|
|
1628
|
-
1. **HIGH**: 实现响应式压缩——413/prompt-too-long 时自动压缩并重试
|
|
1629
|
-
2. **HIGH**: 标准循环支持流式工具执行(tool_use 块到达时即开始执行)
|
|
1630
|
-
3. **HIGH**: 添加会话恢复中断检测(resume 时检测中断轮次+注入继续消息)
|
|
1631
|
-
4. **MEDIUM**: 修复 `endWithLoopError()` 发射 `turn_end` 事件
|
|
1632
|
-
5. **MEDIUM**: 添加 fallback 模型机制
|
|
1633
|
-
6. **MEDIUM**: 重试策略升级为 10 次+指数退避
|
|
1634
|
-
|
|
1635
|
-
**注意:** nanoPencil 在错误层次、类型系统、多 Provider 支持方面优于 CC,这些是架构优势应保持。
|
|
1636
|
-
|
|
1637
|
-
---
|
|
1638
|
-
|
|
1639
|
-
## 2026-06-12 — Prompt 构建 / System Message 系统扫描
|
|
1640
|
-
|
|
1641
|
-
扫描范围:`core/prompt/system-prompt.ts` (325行), `core/runtime/prompt-assembly.ts`, `core/prompt/prompt-templates.ts`, `core/sub-agent/agent-prompt-builder.ts`, `core/session/compaction/compaction.ts`, 对照 CC `src/constants/prompts.ts` (~915行) + `src/utils/systemPrompt.ts` + `src/utils/systemPromptSections.ts` + `src/services/compact/prompt.ts` + `src/services/SessionMemory/prompts.ts`
|
|
1642
|
-
|
|
1643
|
-
### 架构对比
|
|
1644
|
-
|
|
1645
|
-
nanoPencil 使用扁平管线:单一 `buildSystemPrompt()` 函数(325行)+ `.md` 模板系统。CC 使用深度分层+缓存感知架构:~20 个 section 函数+5 级优先级 cascade(override>coordinator>agent>custom>default)+ memoized section+静态/动态边界标记+session memory 系统。
|
|
1646
|
-
|
|
1647
|
-
### 1. 正确性缺陷
|
|
1648
|
-
|
|
1649
|
-
| 严重度 | 发现 |
|
|
1650
|
-
|--------|------|
|
|
1651
|
-
| **MEDIUM** | **`customPrompt` 路径忽略 extension tool guidance。** `system-prompt.ts:80-112`:当 `customPrompt` 存在时,`extensionToolsGuidance` 参数被接受但从未注入。扩展提供的工具指导在自定义 prompt(如 pencil.md)激活时丢失。 |
|
|
1652
|
-
| **MEDIUM** | **Extension 工具名称冲突无验证。** `system-prompt.ts:128-138`:扩展工具若与内置工具同名,内置描述静默胜出。无名称唯一性验证。 |
|
|
1653
|
-
| **LOW** | **`parseCommandArgs` 不支持反斜杠转义。** `prompt-templates.ts:28-59`:处理单/双引号但无 `\` 转义支持。 |
|
|
1654
|
-
|
|
1655
|
-
### 2. 缺陷
|
|
1656
|
-
|
|
1657
|
-
| 严重度 | 发现 |
|
|
1658
|
-
|--------|------|
|
|
1659
|
-
| **HIGH** | **无 prompt cache 感知。** CC 有 `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` 标记分离静态(可全局缓存)vs 动态内容+`systemPromptSection()` memoization+`shouldUseGlobalCacheScope()`。nanoPencil 每轮从头重建完整 prompt,无法利用 Anthropic prompt caching,API 成本显著增加。 |
|
|
1660
|
-
| **HIGH** | **无 token 预算/上下文窗口感知。** `buildSystemPrompt()` 构建单一字符串无 token 估计。CC 有 `getCharBudget()` + `formatCommandsWithinBudget()` 截断 skill 列表到 1% 上下文窗口。nanoPencil 的 `formatSkillsForPrompt()` 无大小限制,大量 skills 时可能消耗大量上下文。 |
|
|
1661
|
-
| **MEDIUM** | **压缩 prompt 缺少 "no tools" 前言。** CC 的 compact prompt 包含 `CRITICAL: Respond with TEXT ONLY. Do NOT call any tools.`。nanoPencil 的 `compaction.ts:443` 无此警告,模型可能在总结时尝试工具调用。 |
|
|
1662
|
-
| **MEDIUM** | **无 `formatCompactSummary()` 后处理。** CC 剥离 `<analysis>` 标签+替换 `<summary>` 为可读标题。nanoPencil 返回原始模型输出。 |
|
|
1663
|
-
| **MEDIUM** | **`buildSystemPrompt` 同步阻塞。** CC 的 `getSystemPrompt()` async 并行调用 skills/env/settings。nanoPencil 同步构建,无法并行加载 memory、计算 env info。 |
|
|
1664
|
-
| **LOW** | **customPrompt 路径 section 顺序/条件不一致。** skill section 的门控条件在 custom 和 default 路径间微妙不同。 |
|
|
1665
|
-
|
|
1666
|
-
### 3. 高可用性
|
|
1667
|
-
|
|
1668
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1669
|
-
|------|-----------|-----|------|
|
|
1670
|
-
| Prompt caching | 无感知,每轮全量重建 | 静态/动态边界+memoized section+cache scope | **CC 压倒性优势** |
|
|
1671
|
-
| Session memory | 无 | 9 结构化 section+自定义模板+token 预算 | **CC 压倒性优势** |
|
|
1672
|
-
| 压缩元数据 | 原始 summary | transcript 路径+保留消息标记+继续指令 | **CC 优势** |
|
|
1673
|
-
| 部分压缩 | 仅全量 | full/partial(from/to)/partial_up_to | **CC 优势** |
|
|
1674
|
-
| 环境信息 | 日期+工作目录 | git 状态+平台+shell+OS+model+knowledge cutoff | **CC 优势** |
|
|
1675
|
-
| 模板系统 | `.md` 文件+frontmatter | 函数式 section+testable | 持平 |
|
|
1676
|
-
| I18n | 中英文扩展 prompt | 仅英文 | **nanoPencil 优势** |
|
|
1677
|
-
|
|
1678
|
-
### 4. CC 功能差距
|
|
1679
|
-
|
|
1680
|
-
| 功能 | CC | nanoPencil |
|
|
1681
|
-
|------|-----|-----------|
|
|
1682
|
-
| Prompt cache 感知 | 静态/动态边界+memoized section+cache scope | 无 |
|
|
1683
|
-
| 5 级优先级 cascade | override>coordinator>agent>custom>default | 二元(custom/default) |
|
|
1684
|
-
| 品牌 SystemPrompt 类型 | `asSystemPrompt()` 不可变数组 | 普通字符串 |
|
|
1685
|
-
| 环境信息 section | git/平台/shell/OS/model/knowledge cutoff | 日期+目录 |
|
|
1686
|
-
| Session memory | 9 结构化 section+自定义模板 | 无 |
|
|
1687
|
-
| 语言偏好 | `getLanguageSection()` | 无 |
|
|
1688
|
-
| 输出样式系统 | `getOutputStyleSection()` | 无 |
|
|
1689
|
-
| 网络风险指令 | `CYBER_RISK_INSTRUCTION` | 无 |
|
|
1690
|
-
| 操作谨慎 section | 可逆性+爆炸半径+确认时机 | 极简指导 |
|
|
1691
|
-
| system-reminder 标签感知 | 显式告知模型 | 无 |
|
|
1692
|
-
| Scratchpad 目录 | session 专用临时目录 | 无 |
|
|
1693
|
-
| MCP 指令 | `getMcpInstructionsSection()` | 无 |
|
|
1694
|
-
| Function result 清除 | `getFunctionResultClearingSection()` | 无 |
|
|
1695
|
-
| 主动/自主模式 prompt | 详细自主工作指令 | grub 扩展部分覆盖 |
|
|
1696
|
-
| Knowledge cutoff | 告知模型截止日期 | 无 |
|
|
1697
|
-
| Tool 反模式指导 | "When NOT to use" 详细说明 | 极简 |
|
|
1698
|
-
| Brief 模式 | `BRIEF_PROACTIVE_SECTION` | 无 |
|
|
1699
|
-
| Token budget prompt | 告知模型目标 token 数 | 无 |
|
|
1700
|
-
| Fork 子代理指导 | "When to fork"/"Don't peek"/"Don't race" | 仅 notes 注入 |
|
|
1701
|
-
| Skill 预算截断 | `formatCommandsWithinBudget()` 1% 上下文 | 无限制 |
|
|
1702
|
-
| 记忆提取 prompt | 结构化记忆+MEMORY.md 索引 | 无 |
|
|
1703
|
-
| 压缩 no-tools 前言 | `CRITICAL: TEXT ONLY` | 无 |
|
|
1704
|
-
| 压缩后处理 | 剥离 analysis 标签+格式化 | 原始输出 |
|
|
1705
|
-
| Section 并行解析 | `resolveSystemPromptSections()` 并行+缓存 | 同步全量 |
|
|
1706
|
-
|
|
1707
|
-
### 5. 代码质量对比
|
|
1708
|
-
|
|
1709
|
-
**nanoPencil 优势:**
|
|
1710
|
-
- WHO/FROM/TO/HERE JSDoc 文档
|
|
1711
|
-
- `.md` 模板+frontmatter 系统灵活
|
|
1712
|
-
- 扩展 prompt 有良好 i18n 支持(teach/grub)
|
|
1713
|
-
- XML 转义(`escapeXml()`)正确
|
|
1714
|
-
|
|
1715
|
-
**nanoPencil 弱点:**
|
|
1716
|
-
- `buildSystemPrompt()` 325 行单体函数+两条代码路径
|
|
1717
|
-
- 无 prompt 内容测试覆盖(仅一个 soul 测试文件)
|
|
1718
|
-
- 硬编码 prompt 字符串(CC 拆分为 15+ 可测试函数)
|
|
1719
|
-
- 无 `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` 概念
|
|
1720
|
-
- `docs/prompt-templates.md` 全部 TODO
|
|
1721
|
-
|
|
1722
|
-
**CC 弱点:**
|
|
1723
|
-
- `prompts.ts` 915 行 section 函数虽分解但仍庞大
|
|
1724
|
-
- 某些 section 命名不一致(`getSimpleDoingTasksSection` vs `getActionsSection`)
|
|
1725
|
-
|
|
1726
|
-
### 汇总
|
|
1727
|
-
|
|
1728
|
-
| 严重度 | 数量 |
|
|
1729
|
-
|--------|------|
|
|
1730
|
-
| HIGH | 2(无 prompt cache 感知、无 token 预算) |
|
|
1731
|
-
| MEDIUM | 4(customPrompt 忽略扩展工具、名称冲突无验证、压缩无 no-tools、无后处理、同步阻塞) |
|
|
1732
|
-
| LOW | 2(转义支持、section 条件不一致) |
|
|
1733
|
-
|
|
1734
|
-
**优先修复项:**
|
|
1735
|
-
1. **HIGH**: 实现 prompt cache 感知——至少分离静态/动态边界,静态部分每轮复用
|
|
1736
|
-
2. **HIGH**: 添加 token 预算——skill 列表截断到上下文窗口的 1%
|
|
1737
|
-
3. **MEDIUM**: 压缩 prompt 添加 `NO_TOOLS_PREAMBLE`
|
|
1738
|
-
4. **MEDIUM**: 压缩结果后处理——剥离 analysis 标签
|
|
1739
|
-
5. **MEDIUM**: 修复 `customPrompt` 路径注入 extension tool guidance
|
|
1740
|
-
6. **MEDIUM**: 添加环境信息 section(git 状态+平台+shell+OS+model)
|
|
1741
|
-
|
|
1742
|
-
**已完成 21 轮扫描。** 所有核心子系统已覆盖。
|
|
1743
|
-
|
|
1744
|
-
---
|
|
1745
|
-
|
|
1746
|
-
## 2026-06-12 — Tool 注册/管理框架扫描
|
|
1747
|
-
|
|
1748
|
-
扫描范围:`core/tools/orchestrator.ts` (135行), `core/runtime/tool-runtime-controller.ts`, `core/extensions-host/wrapper.ts`, `core/extensions-host/loader.ts`, `core/lib/agent-core/src/types.ts` (AgentTool 定义), `core/lib/agent-core/src/structured-adaptive-tool-orchestration.ts`, 对照 CC `src/Tool.ts` (~40 方法), `src/tools.ts`, `src/services/tools/toolExecution.ts` (1750行), `src/services/tools/toolHooks.ts`, `src/services/tools/toolOrchestration.ts`, `src/utils/toolResultStorage.ts` (1040行), `src/utils/toolSearch.ts`, `src/utils/toolSchemaCache.ts`
|
|
1749
|
-
|
|
1750
|
-
### 架构对比
|
|
1751
|
-
|
|
1752
|
-
nanoPencil 工具框架分层清晰(agent-core/types → extensions-host/types → orchestrator → tool-runtime-controller),但 `ToolOrchestrator` 仅 135 行 Map 包装器。CC 有 12 文件深度集成:执行管线 1750 行、hook 系统、权限模型、结果持久化 1040 行、延迟工具发现、schema 缓存。
|
|
1753
|
-
|
|
1754
|
-
### 1. 正确性缺陷
|
|
1755
|
-
|
|
1756
|
-
| 严重度 | 发现 |
|
|
1757
|
-
|--------|------|
|
|
1758
|
-
| **MEDIUM** | **`registerTool` 静默覆盖同名工具。** `orchestrator.ts:104`:`this._toolRegistry.set(name, tool)` 无碰撞检测或警告。CC 的 `assembleToolPool` 用 `uniqBy` 保留首个注册工具+MCP 去重日志。 |
|
|
1759
|
-
| **MEDIUM** | **默认活跃工具列表硬编码。** `tool-runtime-controller.ts:126-128`:`["read", "bash", "edit", "write", "time"]` 写死 5 个。新增基础工具需手动更新。CC 动态从 `getAllBaseTools()` + `isEnabled()` 构建。 |
|
|
1760
|
-
| **MEDIUM** | **扩展工具无名称前缀强制。** `loader.ts:156`:直接存储 `definition.name`,可能与基础工具碰撞。CC 用 `mcp__<server>__<tool>` 前缀防止碰撞。 |
|
|
1761
|
-
| **LOW** | **`replaceTools` 静默裁剪过期活跃工具。** `orchestrator.ts:50-56`:新工具集不包含旧活跃名时静默丢弃,无日志。 |
|
|
1762
|
-
|
|
1763
|
-
### 2. 缺陷
|
|
1764
|
-
|
|
1765
|
-
| 严重度 | 发现 |
|
|
1766
|
-
|--------|------|
|
|
1767
|
-
| **HIGH** | **无 input schema 校验。** CC 在每次工具调用前用 Zod `safeParse` 校验,返回结构化错误(哪个参数错、什么类型、期望什么)。nanoPencil 仅有基础 `validateToolArguments()`,无丰富错误消息供模型修正。 |
|
|
1768
|
-
| **HIGH** | **无工具结果磁盘持久化。** CC 的 `toolResultStorage.ts` (1040行) 超限时保存到磁盘+预览+路径引用。nanoPencil 仅截断,大结果永久丢失。 |
|
|
1769
|
-
| **HIGH** | **无权限模型。** CC 有规则权限+hook 权限+交互提示+自动模式分类器+拒绝追踪+OTel 日志。nanoPencil 仅有基础 `canUseTool` 回调返回 allow/deny。 |
|
|
1770
|
-
| **MEDIUM** | **扩展 wrapper 丢失非 Error 类型。** `wrapper.ts:123`:`throw new Error(message || String(err))` 包装任何非 Error 值为通用 Error,丢失原始类型。CC 保留 AbortError/ShellError/TelemetrySafeError。 |
|
|
1771
|
-
| **MEDIUM** | **标准循环无 abort 信号检查。** CC 在每次工具执行前检查 `signal.aborted`。nanoPencil 标准循环的批量工具调用中,中断时剩余工具可能仍执行。 |
|
|
1772
|
-
| **MEDIUM** | **无 prompt cache 优化。** CC 缓存 schema+排序工具池+内容替换状态。nanoPencil 每次重新渲染 schema,可能破坏 prompt cache。 |
|
|
1773
|
-
| **LOW** | **`tools-manager.ts` 重复 JSDoc。** 第 31-32 行 `DEFAULT_NETWORK_TIMEOUT_MS` 有两个相同 JSDoc 块,复制粘贴残留。 |
|
|
1774
|
-
|
|
1775
|
-
### 3. 高可用性
|
|
1776
|
-
|
|
1777
|
-
| 项目 | nanoPencil | CC | 评价 |
|
|
1778
|
-
|------|-----------|-----|------|
|
|
1779
|
-
| 工具结果持久化 | 截断 | 磁盘保存+预览+路径引用+session 恢复 | **CC 压倒性优势** |
|
|
1780
|
-
| 权限模型 | 基础回调 | 规则+hook+分类器+交互+拒绝追踪 | **CC 压倒性优势** |
|
|
1781
|
-
| Hook 系统 | tool_call/tool_result | PreToolUse/PostToolUse/PostToolUseFailure/PermissionDenied | **CC 优势** |
|
|
1782
|
-
| Schema 缓存 | 无 | session 级缓存防止 cache bust | **CC 优势** |
|
|
1783
|
-
| 内容替换状态 | 无 | 跨 turn 字节一致重放保护 prompt cache | **CC 优势** |
|
|
1784
|
-
| 延迟工具加载 | 无 | ToolSearchTool 按需发现 | **CC 优势** |
|
|
1785
|
-
| 预算执行 | 逐工具截断 | 每消息 200K 总预算+最大持久化 | **CC 优势** |
|
|
1786
|
-
| 扩展系统 | 4 层加载器+host-agnostic SDK | MCP 命名+连接生命周期 | 持平 |
|
|
1787
|
-
| TypeBox schema | 运行时类型验证 | Zod | 持平 |
|
|
1788
|
-
|
|
1789
|
-
### 4. CC 功能差距
|
|
1790
|
-
|
|
1791
|
-
| 功能 | CC | nanoPencil |
|
|
1792
|
-
|------|-----|-----------|
|
|
1793
|
-
| ~40 方法 Tool 类型 | isReadOnly/isDestructive/isOpenWorld/checkPermissions/prompt()/toAutoClassifierInput 等 | ~8 属性 |
|
|
1794
|
-
| 工具搜索/延迟加载 | ToolSearchTool 按需发现,支持数百 MCP 工具 | 无 |
|
|
1795
|
-
| Pre/Post hook 系统 | allow/deny/ask+输入修改+继续阻止+失败 hook+PermissionDenied | tool_call/tool_result |
|
|
1796
|
-
| 多层权限 | 规则权限+hook+分类器+交互+拒绝追踪 | 基础回调 |
|
|
1797
|
-
| 结果磁盘持久化 | 超限保存+预览+路径引用 | 截断 |
|
|
1798
|
-
| Prompt cache 优化 | schema 缓存+排序工具池+内容替换状态 | 无 |
|
|
1799
|
-
| 每消息预算 | 200K 总预算 | 逐工具截断 |
|
|
1800
|
-
| 拒绝规则预过滤 | 模型可见前移除被拒工具 | 仅 activeToolNames |
|
|
1801
|
-
| 协调器模式工具过滤 | COORDINATOR_MODE_ALLOWED_TOOLS 等 | canUseTool 回调 |
|
|
1802
|
-
| MCP 原生集成 | mcp__server__tool 命名+连接生命周期+auth 恢复 | 扩展包装 |
|
|
1803
|
-
| Tool 预设 | --tools flag+预设 | 无 |
|
|
1804
|
-
| Feature-gated 注册 | bun:bundle feature() 死代码消除 | 无条件注册 |
|
|
1805
|
-
| 集中常量 | toolLimits.ts 50K/100K/400K/200K | 分散 |
|
|
1806
|
-
|
|
1807
|
-
### 5. 代码质量对比
|
|
1808
|
-
|
|
1809
|
-
**nanoPencil 优势:**
|
|
1810
|
-
- 清晰的关注点分离(4 层架构)
|
|
1811
|
-
- 扩展系统设计良好(4 层加载器+host-agnostic SDK)
|
|
1812
|
-
- TypeBox schema 运行时验证
|
|
1813
|
-
- 结构化自适应循环的批处理逻辑清晰
|
|
1814
|
-
|
|
1815
|
-
**nanoPencil 弱点:**
|
|
1816
|
-
- `ToolOrchestrator` 过薄(135 行 Map 包装器,无验证/碰撞检测/事件/生命周期)
|
|
1817
|
-
- `ToolRuntimeController.build()` 60 行处理一切
|
|
1818
|
-
- 扩展 wrapper 双重包装交互不清晰
|
|
1819
|
-
- 硬编码默认工具列表
|
|
1820
|
-
- 命名不一致(ToolDefinition/AgentTool/RegisteredTool/ToolInfo)
|
|
1821
|
-
|
|
1822
|
-
### 汇总
|
|
1823
|
-
|
|
1824
|
-
| 严重度 | 数量 |
|
|
1825
|
-
|--------|------|
|
|
1826
|
-
| HIGH | 3(无 schema 校验、无结果持久化、无权限模型) |
|
|
1827
|
-
| MEDIUM | 5(名称覆盖、硬编码列表、无前缀、wrapper 类型丢失、无 abort 检查、无 cache 优化) |
|
|
1828
|
-
| LOW | 2(replaceTools 静默裁剪、重复 JSDoc) |
|
|
1829
|
-
|
|
1830
|
-
**优先修复项:**
|
|
1831
|
-
1. **HIGH**: 实现工具结果磁盘持久化(超限时保存+预览+路径引用)
|
|
1832
|
-
2. **HIGH**: 添加 input schema 校验(Zod safeParse + 结构化错误消息)
|
|
1833
|
-
3. **HIGH**: 实现基础权限模型(至少支持规则权限+交互提示)
|
|
1834
|
-
4. **MEDIUM**: `registerTool` 添加碰撞检测+日志
|
|
1835
|
-
5. **MEDIUM**: 默认活跃工具列表从注册表动态构建
|
|
1836
|
-
6. **MEDIUM**: 扩展工具添加名称前缀防止碰撞
|
|
1837
|
-
|
|
1838
|
-
---
|
|
1839
|
-
|
|
1840
|
-
**已完成 22 轮扫描。** 工具框架已覆盖。
|
|
1841
|
-
|
|
1842
|
-
---
|
|
1843
|
-
|
|
1844
|
-
## Round 23 — Notification System(通知系统)
|
|
1845
|
-
|
|
1846
|
-
**扫描时间**: 2026-06-12
|
|
1847
|
-
**扫描模块**: `modes/interactive/components/notification-queue.ts`, `interactive-mode.ts` (showStatus/showError/showWarning), `stream-render-controller.ts`
|
|
1848
|
-
**对比**: CC `src/services/notifier.ts`, `src/ink/useTerminalNotification.ts`, `src/context/notifications.tsx`, `src/hooks/useNotifyAfterTimeout.ts`, `src/hooks/notifs/` (16 hooks)
|
|
1849
|
-
|
|
1850
|
-
### 1. 架构对比
|
|
1851
|
-
|
|
1852
|
-
| 维度 | nanoPencil | Claude Code |
|
|
1853
|
-
|------|-----------|-------------|
|
|
1854
|
-
| 框架 | 自定义 TUI(`@pencil-agent/tui`)命令式 `Container`/`Text` | React + Ink |
|
|
1855
|
-
| 队列模型 | 多可见(同时 3 条),按优先级+时间排序 | 单条显示 + 优先级队列 |
|
|
1856
|
-
| 去重策略 | key 替换 | key 去重 + `fold` 合并器 + `invalidates` |
|
|
1857
|
-
| 渲染 | `Text` 组件通过 `tui.requestRender()` | React state 驱动 |
|
|
1858
|
-
| 桌面通知 | 无 | 多通道(iTerm2/Kitty/Ghostty/BEL)自动检测 |
|
|
1859
|
-
| 空闲检测 | 无 | `useNotifyAfterTimeout` 6 秒阈值 |
|
|
1860
|
-
| 进度条 | 无 | OSC 9;4 终端进度条 |
|
|
1861
|
-
| 通知钩子 | 无 | 16+ 专用钩子(rate limit, deprecation, MCP, LSP 等) |
|
|
1862
|
-
| 扩展 API | `notify(message, type)` → 委托 showStatus | `addNotification(Notification)` 完整队列集成 |
|
|
1863
|
-
| 后台任务通知 | 无(task panel 存在) | `collapseBackgroundBashNotifications` 合并 |
|
|
1864
|
-
| 状态消息风格 | 聊天内文本 5s 自动消失 | Prompt footer overlay + 队列 |
|
|
1865
|
-
|
|
1866
|
-
### 2. 正确性缺陷
|
|
1867
|
-
|
|
1868
|
-
**Defect 1 — `scheduleDismiss` 忽略自定义 `duration`(BUG)**
|
|
1869
|
-
`notification-queue.ts` L126-131:`scheduleDismiss` 始终使用 `PRIORITY_DURATION[item.priority]`,即使 `options.duration` 已设置。dedup 替换路径(L86-96)重新调度时丢失自定义 duration,导致通知提前或延迟消失。
|
|
1870
|
-
|
|
1871
|
-
**Defect 2 — `showStatus` 去重竞态**
|
|
1872
|
-
`interactive-mode.ts` L2300:连续状态消息更新同一 `lastStatusText` 组件。如果 status 后紧跟 error,status 可能在用户阅读前被覆盖。
|
|
1873
|
-
|
|
1874
|
-
### 3. 高可用差距
|
|
1875
|
-
|
|
1876
|
-
| 差距 | 影响 | 严重度 |
|
|
1877
|
-
|------|------|--------|
|
|
1878
|
-
| 无桌面/OS 通知 | 后台任务完成时用户切到其他窗口会完全错过 | **CRITICAL** |
|
|
1879
|
-
| 无空闲检测通知 | 长时间任务完成后无法提醒不在终端的用户 | **CRITICAL** |
|
|
1880
|
-
| 无终端响铃(BEL) | 无法产生可听反馈 | **HIGH** |
|
|
1881
|
-
| 无终端进度条 | iTerm2/Ghostty dock 图标无进度显示 | **MEDIUM** |
|
|
1882
|
-
| 无后台 bash 完成通知 | 后台命令静默完成 | **LOW**(task panel 部分覆盖) |
|
|
1883
|
-
| 无钩子式通知扩展 | 无法自定义通知回调(如发 Slack) | **MEDIUM** |
|
|
1884
|
-
| 无可配置通知通道 | 用户无法选择首选通知方式 | **MEDIUM** |
|
|
1885
|
-
|
|
1886
|
-
### 4. CC 功能差距
|
|
1887
|
-
|
|
1888
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
1889
|
-
|---------|----------------|--------|
|
|
1890
|
-
| 桌面通知(iTerm2/Kitty/Ghostty/BEL) | 未实现 | **CRITICAL** |
|
|
1891
|
-
| 空闲检测延迟通知 | 未实现 | **CRITICAL** |
|
|
1892
|
-
| 终端响铃 | 未实现 | **HIGH** |
|
|
1893
|
-
| 终端进度条(OSC 9;4) | 未实现 | **MEDIUM** |
|
|
1894
|
-
| 通知钩子(用户自定义回调) | 未实现 | **MEDIUM** |
|
|
1895
|
-
| `fold` 合并器 | 未实现 | **LOW** |
|
|
1896
|
-
| `invalidates` 跨通知消除 | 未实现 | **LOW** |
|
|
1897
|
-
| 16+ 上下文通知钩子 | 未实现(缺少对应子系统) | **MEDIUM** |
|
|
1898
|
-
| 可配置通知通道偏好 | 未实现 | **MEDIUM** |
|
|
1899
|
-
| 通知分析追踪 | 未实现 | **LOW** |
|
|
1900
|
-
| 背景 bash 通知合并 | 未实现 | **LOW** |
|
|
1901
|
-
|
|
1902
|
-
### 5. nanoPencil 优势
|
|
1903
|
-
|
|
1904
|
-
- **多可见队列**:同时显示 3 条通知(CC 仅 1 条),信息密度更高
|
|
1905
|
-
- **Buddy 宠物集成**:`showError` 触发宠物气泡反馈,比纯文字更生动
|
|
1906
|
-
- **4 级优先级 + 不同超时**:immediate 3s / high 5s / medium 8s / low 12s,比 CC 统一 8s 更精细
|
|
1907
|
-
- **队列容量 20 条**:比 CC 单条显示更不容易丢失通知
|
|
1908
|
-
|
|
1909
|
-
### 汇总
|
|
1910
|
-
|
|
1911
|
-
| 严重度 | 数量 |
|
|
1912
|
-
|--------|------|
|
|
1913
|
-
| CRITICAL | 2(无桌面通知、无空闲检测) |
|
|
1914
|
-
| HIGH | 1(无终端响铃) |
|
|
1915
|
-
| MEDIUM | 4(无进度条、无钩子、无可配置通道、无上下文钩子) |
|
|
1916
|
-
| LOW | 3(无 fold/invalidates、无后台合并、自定义 duration bug) |
|
|
1917
|
-
|
|
1918
|
-
**优先修复项:**
|
|
1919
|
-
1. **CRITICAL**: 实现桌面通知服务(先支持终端自动检测 + BEL 降级)
|
|
1920
|
-
2. **CRITICAL**: 添加空闲检测通知(长任务完成后 6s 无输入触发桌面通知)
|
|
1921
|
-
3. **HIGH**: 添加终端 BEL 响铃支持(最简单的可听反馈)
|
|
1922
|
-
4. **MEDIUM**: 实现 OSC 9;4 进度条报告
|
|
1923
|
-
5. **MEDIUM**: 修复 `scheduleDismiss` 自定义 duration bug
|
|
1924
|
-
6. **MEDIUM**: 添加通知钩子扩展点
|
|
1925
|
-
|
|
1926
|
-
---
|
|
1927
|
-
|
|
1928
|
-
**已完成 23 轮扫描。** 通知系统已覆盖。
|
|
1929
|
-
|
|
1930
|
-
---
|
|
1931
|
-
|
|
1932
|
-
## Round 24 — Sub-agent System(子代理系统)
|
|
1933
|
-
|
|
1934
|
-
**扫描时间**: 2026-06-12
|
|
1935
|
-
**扫描模块**: `core/sub-agent/`(15 个文件), `core/workspace/worktree-manager.ts`, `extensions/builtin/subagent/`, `extensions/builtin/team/`
|
|
1936
|
-
**对比**: CC `src/tools/AgentTool/`(10+ 文件), `src/utils/worktree.ts`, `src/utils/forkedAgent.ts`, `src/tasks/LocalAgentTask/`
|
|
1937
|
-
|
|
1938
|
-
### 1. 架构对比
|
|
1939
|
-
|
|
1940
|
-
| 维度 | nanoPencil | Claude Code |
|
|
1941
|
-
|------|-----------|-------------|
|
|
1942
|
-
| 架构风格 | 清晰分层(types/backend/runtime/tool/registry) | 较单体(AgentTool.tsx ~1400 行) |
|
|
1943
|
-
| 子进程后端 | 仅存根(echo 循环) | 远程 CCR 支持(ant-only) |
|
|
1944
|
-
| Fork 系统 | 基础 `forksParentContext` | 完整 fork + cache 共享 + 行为指令 + worktree 通知 |
|
|
1945
|
-
| Team 系统 | 独立扩展(mailbox/tasks/transcripts) | 集成在 AgentTool(`spawnTeammate` + swarm) |
|
|
1946
|
-
| Worktree 工具 | `WorktreeManager` 类 + snapshot 降级 | hook 支持 + slug 验证 + symlink 优化 |
|
|
1947
|
-
| 代理摘要/进度 | 无 | `startAgentSummarization()` + AgentSummary 服务 |
|
|
1948
|
-
| 安全分类器 | 正则启发式 | LLM 转录分类器(`classifyYoloAction`) |
|
|
1949
|
-
| 代理记忆 | 引用但未深度实现 | 完整(snapshots, project scope) |
|
|
1950
|
-
| 代理 UI | 基础 `sub-agent-panel.ts` | React 组件(TeammateSpinnerTree, AgentsList) |
|
|
1951
|
-
| Feature gating | 无 | GrowthBook feature flags |
|
|
1952
|
-
|
|
1953
|
-
### 2. 正确性缺陷
|
|
1954
|
-
|
|
1955
|
-
**Defect 1 — `SubAgentRuntime.spawn()` 清理竞态(LOW)**
|
|
1956
|
-
`sub-agent-runtime.ts` L32-34:`handle.result().finally()` 删除 `activeAgents` 条目。如果 `result()` 在 `spawn()` 返回 handle 前解析,handle 会立即从 map 中移除。实际风险低(异步执行保证安全窗口)。
|
|
1957
|
-
|
|
1958
|
-
**Defect 2 — 子进程后端是非功能存根(MEDIUM)**
|
|
1959
|
-
`subprocess-backend.ts` + `subprocess-worker.ts`:worker 线程仅运行 echo 循环,不执行 LLM 查询。已导出但无实际功能,调用方可能误用。
|
|
1960
|
-
|
|
1961
|
-
**Defect 3 — SendMessage 工具是空操作(HIGH)**
|
|
1962
|
-
`send-message-tool.ts` L93-98:TODO 注释确认消息未实际注入到运行中的 agent。LLM 调用后会认为消息已发送,但实际未送达。
|
|
1963
|
-
|
|
1964
|
-
**Defect 4 — Handoff 分类器使用正则而非 LLM(MEDIUM)**
|
|
1965
|
-
`agent-handoff-safety.ts` L122-168:正则匹配 `curl|sh`、`rm -rf /` 等模式,无法检测细微安全违规。`part.args` 可能是对象而非字符串,`JSON.stringify` 可能不匹配。
|
|
1966
|
-
|
|
1967
|
-
**Defect 5 — Worktree 清理创建新 WorktreeManager 实例(LOW)**
|
|
1968
|
-
`agent-tool.ts` L590:`config.worktreeManager ?? new WorktreeManager()` 创建无状态的新实例,依赖 `resolveWorktreeOwner()` 降级。
|
|
1969
|
-
|
|
1970
|
-
**Defect 6 — 后台代理完成无通知(MEDIUM)**
|
|
1971
|
-
`agent-output-persistence.ts`:写入输出文件但无机制提醒父代理。CC 有 `enqueueAgentNotification()` 注入用户消息。
|
|
1972
|
-
|
|
1973
|
-
**Defect 7 — 名称注册表持久化竞态(MEDIUM)**
|
|
1974
|
-
`agent-registry.ts` L166-205:`loadNameRegistry()` 在构造函数中异步加载,首次 `resolve()` 调用时注册表可能尚未就绪。
|
|
1975
|
-
|
|
1976
|
-
### 3. 高可用差距
|
|
1977
|
-
|
|
1978
|
-
| 差距 | 影响 | 严重度 |
|
|
1979
|
-
|------|------|--------|
|
|
1980
|
-
| 无代理恢复/重放 | 崩溃后状态丢失 | **HIGH** |
|
|
1981
|
-
| 无进程崩溃恢复 | 子进程存根无实际隔离 | **HIGH** |
|
|
1982
|
-
| 无 worktree mtime 更新 | 恢复的 worktree 可能被清理 | **MEDIUM** |
|
|
1983
|
-
| 无过期 worktree 清理 | 孤儿 worktree 堆积 | **MEDIUM** |
|
|
1984
|
-
| 无前台→后台提升 | 运行中代理无法转后台 | **MEDIUM** |
|
|
1985
|
-
| 无代理进度摘要 | 长时间代理无中间反馈 | **MEDIUM** |
|
|
1986
|
-
|
|
1987
|
-
### 4. CC 功能差距
|
|
1988
|
-
|
|
1989
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
1990
|
-
|---------|----------------|--------|
|
|
1991
|
-
| Fork 子代理(cache 共享、行为指令、worktree 通知) | 基础 `forksParentContext` | **HIGH** |
|
|
1992
|
-
| LLM 转录分类器 | 正则启发式 | **HIGH** |
|
|
1993
|
-
| 代理恢复(transcript 持久化+重建) | 未实现 | **HIGH** |
|
|
1994
|
-
| 后台代理通知注入 | 未实现 | **HIGH** |
|
|
1995
|
-
| 远程/CCR 代理执行 | 未实现 | **LOW**(ant-only) |
|
|
1996
|
-
| 代理颜色管理+分组 UI | 基础 | **LOW** |
|
|
1997
|
-
| 代理记忆系统(snapshots, project scope) | 引用但未实现 | **MEDIUM** |
|
|
1998
|
-
| Skill 预加载 | 未实现 | **LOW** |
|
|
1999
|
-
| 代理 frontmatter hooks | 未实现 | **LOW** |
|
|
2000
|
-
| 代理 MCP 服务器初始化 | 引用但未连接 | **MEDIUM** |
|
|
2001
|
-
| Perfetto 追踪 | 基础 telemetry | **LOW** |
|
|
2002
|
-
| Tool result cache 稳定性 | 未实现 | **MEDIUM** |
|
|
2003
|
-
| Query source 追踪 | 未实现 | **LOW** |
|
|
2004
|
-
| 前台代理注册 | 未实现 | **MEDIUM** |
|
|
2005
|
-
| Team swarm 集成 | 独立扩展 | **MEDIUM** |
|
|
2006
|
-
|
|
2007
|
-
### 5. nanoPencil 优势
|
|
2008
|
-
|
|
2009
|
-
- **清晰分层架构**:types/backend/runtime/tool/registry 5 层分离,比 CC 的单体 AgentTool.tsx 更易维护
|
|
2010
|
-
- **独立 Team 扩展**:mailbox + task store + transcript writer 模块化设计
|
|
2011
|
-
- **Agent 定义注册表**:磁盘持久化名称注册表,CC 仅内存
|
|
2012
|
-
- **Snapshot worktree 降级**:非 git 仓库时自动降级到目录复制
|
|
2013
|
-
|
|
2014
|
-
### 汇总
|
|
2015
|
-
|
|
2016
|
-
| 严重度 | 数量 |
|
|
2017
|
-
|--------|------|
|
|
2018
|
-
| HIGH | 4(SendMessage 空操作、无恢复、无通知注入、Fork 不完整) |
|
|
2019
|
-
| MEDIUM | 7(子进程存根、正则分类器、无进度摘要、无 MCP 初始化、无记忆、无前台注册、名称注册竞态) |
|
|
2020
|
-
| LOW | 4(清理竞态、worktree 新实例、远程执行、UI 差距) |
|
|
2021
|
-
|
|
2022
|
-
**优先修复项:**
|
|
2023
|
-
1. **HIGH**: 实现 SendMessage 实际消息投递
|
|
2024
|
-
2. **HIGH**: 实现后台代理完成通知注入
|
|
2025
|
-
3. **HIGH**: 完善 Fork 子代理(cache 共享 + 行为指令)
|
|
2026
|
-
4. **HIGH**: 实现代理恢复机制(transcript 持久化 + 重建)
|
|
2027
|
-
5. **MEDIUM**: 连接代理 MCP 服务器初始化
|
|
2028
|
-
6. **MEDIUM**: 添加前台代理注册 + 进度追踪
|
|
2029
|
-
|
|
2030
|
-
---
|
|
2031
|
-
|
|
2032
|
-
**已完成 24 轮扫描。** 子代理系统已覆盖。
|
|
2033
|
-
|
|
2034
|
-
---
|
|
2035
|
-
|
|
2036
|
-
## Round 25 — Skills System(技能系统)
|
|
2037
|
-
|
|
2038
|
-
**扫描时间**: 2026-06-12
|
|
2039
|
-
**扫描模块**: `core/skills.ts`, `core/slash-commands.ts`, `core/runtime/slash-command-catalog.ts`, `core/runtime/agent-session.ts` (skill expansion)
|
|
2040
|
-
**对比**: CC `src/skills/loadSkillsDir.ts`, `src/skills/bundledSkills.ts`, `src/skills/bundled/` (17+), `src/tools/SkillTool/`, `src/utils/argumentSubstitution.ts`, `src/tools/AgentTool/runAgent.ts`
|
|
2041
|
-
|
|
2042
|
-
### 1. 架构对比
|
|
2043
|
-
|
|
2044
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2045
|
-
|------|-----------|-------------|
|
|
2046
|
-
| 核心类型 | `Skill`(6 字段:name/desc/filePath/baseDir/source/disableModelInvocation) | `Command`(15+ 字段:name/desc/whenToUse/argumentHint/allowedTools/model/effort/context/hooks/paths 等) |
|
|
2047
|
-
| 加载路径 | 同步扫描 `~/.pencils/agent/skills/` + `.nanopencil/skills/` | 异步扫描 managed/user/project/additional/legacy 5 级目录 + 动态发现 |
|
|
2048
|
-
| 系统提示注入 | XML `<available_skills>` 列表,模型用 read 工具按需加载 | `Skill` 工具注册,模型可主动调用任意 skill |
|
|
2049
|
-
| 用户调用 | `/skill:name args` → 读文件 + 包装 `<skill>` XML | `/skill-name` → `processSlashCommand()` + 模型可调 `Skill` 工具 |
|
|
2050
|
-
| 参数替换 | 无(args 原始拼接) | 完整(`$ARGUMENTS`/`$0`-`$N`/命名 `$foo` + shell-quote) |
|
|
2051
|
-
| Agent 预加载 | `AgentDefinition.skills` 已声明但未使用 | `runAgent.ts` 解析 skill 名称 + 加载内容 + 注入 `initialMessages` |
|
|
2052
|
-
| 条件激活 | 无 | `paths` frontmatter(gitignore 模式匹配) |
|
|
2053
|
-
| 动态发现 | 无 | 从编辑文件路径向上遍历发现嵌套 skill 目录 |
|
|
2054
|
-
| 内置 skills | 无 | 17+(simplify/verify/debug/skillify/remember/loop 等) |
|
|
2055
|
-
| MCP 集成 | 无 | MCP skill bridge + 远程发现 |
|
|
2056
|
-
| 缓存失效 | 无 | `skillsLoaded` signal + `clearSkillCaches()` |
|
|
2057
|
-
|
|
2058
|
-
### 2. 正确性缺陷
|
|
2059
|
-
|
|
2060
|
-
**Defect 1 — Agent `skills` 字段是死代码(HIGH)**
|
|
2061
|
-
`agent-definition.ts` L137:`skills` 已声明并从 frontmatter 解析,但 `agent-tool.ts` 从未读取或使用。Agent 生成时 skill 列表被静默忽略。CC 在 `runAgent.ts` L577-646 预加载 skills 到 `initialMessages`。
|
|
2062
|
-
|
|
2063
|
-
**Defect 2 — `_expandSkillCommand` 跳过参数替换(HIGH)**
|
|
2064
|
-
`agent-session.ts` L1241-1268:读取 skill 文件、剥离 frontmatter、包装 `<skill>` XML,但:
|
|
2065
|
-
- 不执行 `$ARGUMENTS` / 命名参数替换
|
|
2066
|
-
- 不遵守 `allowed-tools` 限制
|
|
2067
|
-
- 不遵守 `model` 覆盖
|
|
2068
|
-
- 不执行 `!` 代码块中的 shell 命令
|
|
2069
|
-
- 不处理 `context: fork` 隔离执行
|
|
2070
|
-
用户调用的 skill 中 `$ARGUMENTS` 占位符保持原样文本。
|
|
2071
|
-
|
|
2072
|
-
**Defect 3 — 同步阻塞 I/O 加载 skills(MEDIUM)**
|
|
2073
|
-
`core/skills.ts`:所有文件系统操作使用 `readFileSync`/`readdirSync`/`statSync`。CC 使用异步 `fs/promises` + `Promise.all` 并行加载。大型 skill 目录会阻塞事件循环。
|
|
2074
|
-
|
|
2075
|
-
**Defect 4 — 无缓存失效信号(MEDIUM)**
|
|
2076
|
-
`resource-loader.ts`:CC 创建 `skillsLoaded` signal 供其他模块订阅。nanoPencil 无等效机制——skill 变更后系统提示和命令目录直到下次完整重载才更新。
|
|
2077
|
-
|
|
2078
|
-
**Defect 5 — 空描述 skill 静默丢弃(LOW)**
|
|
2079
|
-
`core/skills.ts` L266:`frontmatter.description` 为空时 skill 被静默丢弃,无用户可见警告。
|
|
2080
|
-
|
|
2081
|
-
### 3. 高可用差距
|
|
2082
|
-
|
|
2083
|
-
| 差距 | 影响 | 严重度 |
|
|
2084
|
-
|------|------|--------|
|
|
2085
|
-
| 无动态 skill 发现 | 子目录中的 skills 不可发现 | **HIGH** |
|
|
2086
|
-
| 无条件 skill 激活 | 无法按文件类型范围激活 skills | **MEDIUM** |
|
|
2087
|
-
| 无定向 skill 缓存重载 | skill 变更需完整重载 | **MEDIUM** |
|
|
2088
|
-
| 同步阻塞文件 I/O | 大目录加载时 UI 卡顿 | **MEDIUM** |
|
|
2089
|
-
|
|
2090
|
-
### 4. CC 功能差距
|
|
2091
|
-
|
|
2092
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2093
|
-
|---------|----------------|--------|
|
|
2094
|
-
| `Skill` 工具(模型主动调用) | 未实现 | **HIGH** |
|
|
2095
|
-
| `whenToUse` 指导字段 | 未实现 | **HIGH** |
|
|
2096
|
-
| 参数替换(`$ARGUMENTS`/命名参数) | 未实现 | **HIGH** |
|
|
2097
|
-
| `allowed-tools` 执行限制 | 未实现 | **MEDIUM** |
|
|
2098
|
-
| 每 skill `model` 覆盖 | 未实现 | **MEDIUM** |
|
|
2099
|
-
| `context: fork` 隔离执行 | 未实现 | **MEDIUM** |
|
|
2100
|
-
| skill 内 `hooks` | 未实现 | **MEDIUM** |
|
|
2101
|
-
| `paths` 条件激活 | 未实现 | **MEDIUM** |
|
|
2102
|
-
| 内置 skills(17+) | 无 | **LOW** |
|
|
2103
|
-
| MCP/plugin skill 集成 | 未实现 | **LOW** |
|
|
2104
|
-
| `user-invocable` 标志 | 未实现 | **LOW** |
|
|
2105
|
-
| 每 skill `effort` 设置 | 未实现 | **LOW** |
|
|
2106
|
-
| 权限系统 | 未实现 | **MEDIUM** |
|
|
2107
|
-
| 预算感知 skill 列表 | 未实现 | **LOW** |
|
|
2108
|
-
| `skillRoot` 文件提取 | 未实现 | **LOW** |
|
|
2109
|
-
| `version` 字段 | 未实现 | **LOW** |
|
|
2110
|
-
| 使用追踪/分析 | 未实现 | **LOW** |
|
|
2111
|
-
|
|
2112
|
-
### 5. nanoPencil 优势
|
|
2113
|
-
|
|
2114
|
-
- **realpath 去重**:`realpathSync` 解析符号链接避免重复,与 CC 对齐
|
|
2115
|
-
- **扩展系统集成**:skills 可通过扩展路径加载
|
|
2116
|
-
- **XML 包装格式**:`<skill>` 标签清晰界定 skill 内容边界
|
|
2117
|
-
|
|
2118
|
-
### 汇总
|
|
2119
|
-
|
|
2120
|
-
| 严重度 | 数量 |
|
|
2121
|
-
|--------|------|
|
|
2122
|
-
| HIGH | 3(skills 死代码、无参数替换、无动态发现) |
|
|
2123
|
-
| MEDIUM | 6(同步 I/O、无缓存失效、无条件激活、无 allowed-tools、无 fork 执行、无 hooks) |
|
|
2124
|
-
| LOW | 5(空描述丢弃、无内置 skills、无 MCP 集成、无版本、无预算列表) |
|
|
2125
|
-
|
|
2126
|
-
**优先修复项:**
|
|
2127
|
-
1. **HIGH**: 在 `agent-tool.ts` 中连接 `AgentDefinition.skills` 预加载
|
|
2128
|
-
2. **HIGH**: 实现 `_expandSkillCommand` 参数替换(`$ARGUMENTS`/命名参数)
|
|
2129
|
-
3. **HIGH**: 添加 `whenToUse` 到 `Skill` 接口并在系统提示中展示
|
|
2130
|
-
4. **HIGH**: 构建 `Skill` 工具供模型主动调用
|
|
2131
|
-
5. **MEDIUM**: 切换 skill 加载到异步 I/O + 并行读取
|
|
2132
|
-
6. **MEDIUM**: 添加 `allowed-tools` 执行限制
|
|
2133
|
-
|
|
2134
|
-
---
|
|
2135
|
-
|
|
2136
|
-
**已完成 25 轮扫描。** 技能系统已覆盖。
|
|
2137
|
-
|
|
2138
|
-
---
|
|
2139
|
-
|
|
2140
|
-
## Round 26 — Cron/Scheduler System(定时任务系统)
|
|
2141
|
-
|
|
2142
|
-
**扫描时间**: 2026-06-12
|
|
2143
|
-
**扫描模块**: `extensions/builtin/loop/cron/`(cron-parser.ts, cron-tasks.ts, cron-scheduler.ts, cron-tasks-lock.ts), `extensions/builtin/loop/cron-tools/`(cron-create/delete/list-tool.ts), `extensions/builtin/loop/loop-skill.ts`, `extensions/builtin/loop/index.ts`
|
|
2144
|
-
**对比**: CC `src/utils/cron.ts`, `src/utils/cronTasks.ts`, `src/utils/cronScheduler.ts`, `src/utils/cronTasksLock.ts`, `src/utils/cronJitterConfig.ts`, `src/tools/ScheduleCronTool/`, `src/skills/bundled/loop.ts`, `src/hooks/useScheduledTasks.ts`
|
|
2145
|
-
|
|
2146
|
-
### 1. 架构对比
|
|
2147
|
-
|
|
2148
|
-
**核心评估:nanoPencil 的 cron 系统是 CC 的忠实 1:1 移植。**
|
|
2149
|
-
|
|
2150
|
-
| 组件 | CC | nanoPencil | 对齐度 |
|
|
2151
|
-
|------|-----|-----------|--------|
|
|
2152
|
-
| Cron 解析器 | `src/utils/cron.ts` | `cron-parser.ts` | 1:1 |
|
|
2153
|
-
| 任务存储 | `src/utils/cronTasks.ts` | `cron-tasks.ts` | 1:1 |
|
|
2154
|
-
| 调度器核心 | `src/utils/cronScheduler.ts` | `cron-scheduler.ts` | 1:1 |
|
|
2155
|
-
| 调度器锁 | `src/utils/cronTasksLock.ts` | `cron-tasks-lock.ts` | 1:1 |
|
|
2156
|
-
| Jitter 配置 | `src/utils/cronJitterConfig.ts` | 硬编码默认值 | 部分 |
|
|
2157
|
-
| CronCreate 工具 | `CronCreateTool.ts` | `cron-create-tool.ts` | 1:1 |
|
|
2158
|
-
| CronDelete 工具 | `CronDeleteTool.ts` | `cron-delete-tool.ts` | 1:1 |
|
|
2159
|
-
| CronList 工具 | `CronListTool.ts` | `cron-list-tool.ts` | 1:1 |
|
|
2160
|
-
| /loop skill | `src/skills/bundled/loop.ts` | `loop-skill.ts` | 1:1 |
|
|
2161
|
-
| REPL 集成 | `useScheduledTasks` React hook | 扩展 `index.ts` | 架构不同 |
|
|
2162
|
-
|
|
2163
|
-
**关键结构差异**:CC 使用 React hook(`useScheduledTasks`)+ 优先级队列(`enqueuePendingNotification` priority `'later'`)。nanoPencil 使用扩展架构 + `api.sendUserMessage(prompt, { deliverAs: "followUp" })`。
|
|
2164
|
-
|
|
2165
|
-
**Session 任务状态**:CC 存储在集中式 bootstrap state(`STATE.sessionCronTasks`)。nanoPencil 存储在模块级 `Map<string, CronTask>`。两种方式对各自架构都正确。
|
|
2166
|
-
|
|
2167
|
-
### 2. 正确性缺陷
|
|
2168
|
-
|
|
2169
|
-
**Defect 1 — `removeCronTasks` 行为分歧(MEDIUM)**
|
|
2170
|
-
`cron-tasks.ts` L248-260:nanoPencil 总是先扫描 session store,然后条件读取文件。CC 在 `dir === undefined` 时才扫描 session store。当 `dir` 已提供且任务 ID 同时存在于 session 和文件时,session 删除会短路导致文件副本残留。
|
|
2171
|
-
|
|
2172
|
-
**Defect 2 — `readCronTasks` 静默吞错(LOW)**
|
|
2173
|
-
`cron-tasks.ts` L112-156:nanoPencil 使用 `catch { return [] }` 静默忽略所有错误。CC 使用 `isFsInaccessible(e)` 区分权限错误并调用 `logError(e)`。损坏或权限拒绝的 cron 文件对用户不可见。
|
|
2174
|
-
|
|
2175
|
-
**Defect 3 — 工具输入缺少 `semanticBoolean`(LOW)**
|
|
2176
|
-
`cron-create-tool.ts`:CC 用 `semanticBoolean()` 包装 `recurring`/`durable` 参数(接受布尔值和字符串 "true"/"false")。nanoPencil 使用 `Type.Boolean()`,模型传字符串时可能拒绝。
|
|
2177
|
-
|
|
2178
|
-
**Defect 4 — `DEFAULT_MAX_AGE_DAYS` 硬编码(LOW)**
|
|
2179
|
-
`prompt.ts` L15:nanoPencil 硬编码 `7`。CC 从 `DEFAULT_CRON_JITTER_CONFIG.recurringMaxAgeMs` 派生。当前值相同但未来可能分歧。
|
|
2180
|
-
|
|
2181
|
-
**Defect 5 — Issue 0013 路径不匹配(INFO)**
|
|
2182
|
-
`issues/0013-cron-tasks-path-mismatch.md`:历史问题记录,durable cron 写入路径 vs 读取路径不一致。当前代码已使用 `ctx.agentDir`/`api.agentDir` 统一,但 issue 状态仍为 open。
|
|
2183
|
-
|
|
2184
|
-
### 3. 高可用差距
|
|
2185
|
-
|
|
2186
|
-
| 差距 | 影响 | 严重度 |
|
|
2187
|
-
|------|------|--------|
|
|
2188
|
-
| 无分析/调试日志 | 生产环境无法诊断 cron 问题 | **MEDIUM** |
|
|
2189
|
-
| 无运行时 jitter 调优 | :00 负载峰值无法分散 | **MEDIUM** |
|
|
2190
|
-
| 无 `isKilled` 门控 | 无法远程停止已运行的调度器 | **LOW** |
|
|
2191
|
-
| 无崩溃时锁释放注册 | SIGKILL 后锁文件孤儿化(PID 探测可恢复) | **LOW** |
|
|
2192
|
-
| 无 `DISABLE_CRON` 环境变量 | 无法本地禁用 cron | **LOW** |
|
|
2193
|
-
|
|
2194
|
-
### 4. CC 功能差距
|
|
2195
|
-
|
|
2196
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2197
|
-
|---------|----------------|--------|
|
|
2198
|
-
| Teammate 集成(agent 归属/隔离/清理) | `agentId` 字段存在但无工具/调度器逻辑 | **HIGH** |
|
|
2199
|
-
| `setScheduledTasksEnabled` 协调 | 仅内部轮询 | **MEDIUM** |
|
|
2200
|
-
| 工作负载归因(`WORKLOAD_CRON` 标签) | 无 | **MEDIUM** |
|
|
2201
|
-
| 优先级队列(`isMeta` + `priority: 'later'`) | `sendUserMessage` followUp | **MEDIUM** |
|
|
2202
|
-
| 事件追踪(fire/missed/expired) | 无 | **LOW** |
|
|
2203
|
-
| `isConcurrencySafe`/`isReadOnly` 标志 | 扩展 API 不支持 | **LOW** |
|
|
2204
|
-
| GrowthBook 动态配置 | 硬编码默认值 | **LOW** |
|
|
2205
|
-
|
|
2206
|
-
### 5. nanoPencil 优势
|
|
2207
|
-
|
|
2208
|
-
- **扩展架构集成**:通过扩展 API 暴露,比 React hook 更模块化
|
|
2209
|
-
- **1:1 忠实移植**:cron 解析、next-run 计算、jitter 算法、锁协议、调度器 tick 循环功能完全一致
|
|
2210
|
-
- **简化参数模型**:`dir` 参数必需而非可选,减少歧义
|
|
2211
|
-
|
|
2212
|
-
### 汇总
|
|
2213
|
-
|
|
2214
|
-
| 严重度 | 数量 |
|
|
2215
|
-
|--------|------|
|
|
2216
|
-
| HIGH | 1(无 teammate 支持) |
|
|
2217
|
-
| MEDIUM | 4(removeCronTasks 行为分歧、无分析日志、无 jitter 调优、无优先级队列) |
|
|
2218
|
-
| LOW | 6(静默吞错、无 semanticBoolean、硬编码天数、无 killswitch、无崩溃锁释放、无 DISABLE_CRON) |
|
|
2219
|
-
|
|
2220
|
-
**优先修复项:**
|
|
2221
|
-
1. **HIGH**: 实现 teammate cron 归属/隔离/清理逻辑
|
|
2222
|
-
2. **MEDIUM**: 修复 `removeCronTasks` 行为与 CC 对齐
|
|
2223
|
-
3. **MEDIUM**: 添加 cron 分析事件(fire/missed/expired)
|
|
2224
|
-
4. **MEDIUM**: 实现 `readCronTasks` 错误分类(区分权限错误)
|
|
2225
|
-
5. **LOW**: 添加 `semanticBoolean` 包装器
|
|
2226
|
-
|
|
2227
|
-
---
|
|
2228
|
-
|
|
2229
|
-
**已完成 26 轮扫描。** 定时任务系统已覆盖。
|
|
2230
|
-
|
|
2231
|
-
---
|
|
2232
|
-
|
|
2233
|
-
## Round 27 — Plan System(计划系统)
|
|
2234
|
-
|
|
2235
|
-
**扫描时间**: 2026-06-12
|
|
2236
|
-
**扫描模块**: `extensions/builtin/plan/`(8 文件:index.ts, enter-plan-mode-tool.ts, exit-plan-mode-tool.ts, plan-file-manager.ts, plan-permissions.ts, plan-validation.ts, plan-agents.ts, teammate-approval.ts), `modes/interactive/components/plan-mode-panel.ts`
|
|
2237
|
-
**对比**: CC `src/tools/EnterPlanModeTool/`, `src/tools/ExitPlanModeTool/`, `src/utils/plans.ts`, `src/plan/`, `src/components/` (plan UI)
|
|
2238
|
-
|
|
2239
|
-
### 1. 架构对比
|
|
2240
|
-
|
|
2241
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2242
|
-
|------|-----------|-------------|
|
|
2243
|
-
| 实现位置 | 扩展模块(`extensions/builtin/plan/`) | 核心工具 + 工具模块 + React UI(6+ 目录) |
|
|
2244
|
-
| 状态存储 | WeakMap + session entries(`PLAN_CUSTOM_TYPE`) | 全局 AppState + ToolPermissionContext |
|
|
2245
|
-
| 权限门控 | `tool_call` 事件拦截器返回 `{ block: true }` | 每工具 `isReadOnly()` + 分类器集成 |
|
|
2246
|
-
| UI 框架 | 自定义 TUI(`ctx.ui.select()` 字符串选择) | React Ink(Select 组件 + 权限对话框) |
|
|
2247
|
-
| A/B 测试 | 无 | `PewterLedgerVariant` 实验框架 |
|
|
2248
|
-
| 子代理集成 | `plan-agents.ts` 定义 Explore/Plan 提示 | `planAgent.ts` + `exploreAgent.ts` 内置代理 |
|
|
2249
|
-
| Plan 文件管理 | `~/.nanopencil/plans/{slug}.md`(adjective-noun slug) | `~/.claude/plans/{slug}.md`(`generateWordSlug()`) |
|
|
2250
|
-
| 工作流 | 5 阶段顺序 + 访谈模式(env var 门控) | 5 阶段顺序 + 访谈模式(feature flag 门控) |
|
|
2251
|
-
|
|
2252
|
-
### 2. 正确性缺陷
|
|
2253
|
-
|
|
2254
|
-
**BUG 1 — `getPlanSlug` 碰撞后返回冲突 slug(MEDIUM)**
|
|
2255
|
-
`plan-file-manager.ts` L211-216:10 次重试全部命中已存在文件时,`slug` 保持最后一个已存在值,返回后会覆盖或冲突。应添加 timestamp/UUID 降级。
|
|
2256
|
-
|
|
2257
|
-
**BUG 2 — `ExitPlanMode` select 回退路径静默(LOW)**
|
|
2258
|
-
`exit-plan-mode-tool.ts` L327:非预期选择值静默降级为 "standard" 模式。`ctx.ui.select()` 返回 `undefined` 时仍会调用 `handlePlanModeExit` 清除 widget,模型可能无明确指引。
|
|
2259
|
-
|
|
2260
|
-
**BUG 3 — 测试不覆盖审批流程(LOW)**
|
|
2261
|
-
`test/plan-mode.test.ts` L217:`select: async () => undefined` 从未测试实际审批选择路径,只测试降级行为。
|
|
2262
|
-
|
|
2263
|
-
**DEFECT 1 — `ALL_BLOCKED_TOOLS` 包含死名称(LOW)**
|
|
2264
|
-
`plan-permissions.ts` L18-26:`write_file`/`edit_file`/`replace`/`create_file`/`delete_file` 不是实际工具名(实际为 `write`/`edit`),集合部分为死代码。
|
|
2265
|
-
|
|
2266
|
-
**DEFECT 2 — Plan 验证正则过于宽松(LOW)**
|
|
2267
|
-
`plan-validation.ts` L9-14:只需标题包含 "Context"/"Approach"/"Files"/"Test" 即通过,无实质内容验证。
|
|
2268
|
-
|
|
2269
|
-
**DEFECT 3 — `getPlansDirectory` 缓存竞态(LOW)**
|
|
2270
|
-
`plan-file-manager.ts` L168-193:模块级缓存变量在并发调用时可能返回过期值。
|
|
2271
|
-
|
|
2272
|
-
### 3. 高可用差距
|
|
2273
|
-
|
|
2274
|
-
| 差距 | 影响 | 严重度 |
|
|
2275
|
-
|------|------|--------|
|
|
2276
|
-
| 无远程会话 plan 快照 | 远程会话崩溃后 plan 丢失 | **HIGH** |
|
|
2277
|
-
| 无消息历史 plan 恢复 | 无法从 ExitPlanMode 输入重建 plan | **HIGH** |
|
|
2278
|
-
| 文件系统 mailbox 无锁 | 并发写入可能损坏(标记 `@deprecated`) | **MEDIUM** |
|
|
2279
|
-
| 无 auto-compaction plan 保留 | 上下文压缩时 plan 内容可能丢失 | **MEDIUM** |
|
|
2280
|
-
| 模块级 `pendingPlan` 进程全局 | 多会话共享进程时互相覆盖 | **MEDIUM** |
|
|
2281
|
-
|
|
2282
|
-
### 4. CC 功能差距
|
|
2283
|
-
|
|
2284
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2285
|
-
|---------|----------------|--------|
|
|
2286
|
-
| React TUI 审批对话框 | 字符串 select | **MEDIUM** |
|
|
2287
|
-
| Plan 拒绝消息组件 | 无(仅抛错误文本) | **LOW** |
|
|
2288
|
-
| Plan-to-implement 消息 | 无(plan 作为纯文本嵌入工具结果) | **LOW** |
|
|
2289
|
-
| Auto-mode 集成(分类器+电路断路器) | 仅有 `prePlanMode` | **HIGH** |
|
|
2290
|
-
| A/B 测试框架 | 无 | **LOW** |
|
|
2291
|
-
| 远程会话 plan 快照持久化 | 无 | **HIGH** |
|
|
2292
|
-
| 从消息历史恢复 plan | 无 | **HIGH** |
|
|
2293
|
-
| Feature-flagged 代理数量 | 仅 env var | **LOW** |
|
|
2294
|
-
| Ant/External 用户提示区分 | 单一提示 | **LOW** |
|
|
2295
|
-
| 动态工具列表(`hasEmbeddedSearchTools`) | 硬编码工具名 | **LOW** |
|
|
2296
|
-
| `allowedPrompts` 权限集成 | Schema 接受但未执行 | **MEDIUM** |
|
|
2297
|
-
| TeamCreateTool 并行提示 | 无 | **LOW** |
|
|
2298
|
-
| 子代理专用 plan 指令 | 基础(通过提示文本) | **LOW** |
|
|
2299
|
-
|
|
2300
|
-
### 5. nanoPencil 优势
|
|
2301
|
-
|
|
2302
|
-
- **扩展架构封装**:作为自包含扩展模块,比 CC 分散在 6+ 目录更易维护
|
|
2303
|
-
- **WeakMap 状态管理**:比全局 AppState 更安全,避免跨会话泄漏
|
|
2304
|
-
- **事件拦截权限门控**:统一的 `tool_call` 事件处理比逐工具 `isReadOnly()` 更集中
|
|
2305
|
-
- **访谈模式**:已实现(虽为 env var 门控),CC 同样支持
|
|
2306
|
-
|
|
2307
|
-
### 汇总
|
|
2308
|
-
|
|
2309
|
-
| 严重度 | 数量 |
|
|
2310
|
-
|--------|------|
|
|
2311
|
-
| HIGH | 3(无远程快照、无 plan 恢复、无 auto-mode 集成) |
|
|
2312
|
-
| MEDIUM | 5(slug 碰撞、mailbox 无锁、无 compaction 保留、进程全局状态、allowedPrompts 未集成) |
|
|
2313
|
-
| LOW | 7(select 回退、测试不足、死工具名、宽松验证、缓存竞态、无拒绝 UI、无 A/B 测试) |
|
|
2314
|
-
|
|
2315
|
-
**优先修复项:**
|
|
2316
|
-
1. **HIGH**: 实现 plan 文件恢复机制(从 ExitPlanMode 输入 + 消息历史重建)
|
|
2317
|
-
2. **HIGH**: 实现 auto-compaction plan 保留(注入 `plan_file_reference` 附件)
|
|
2318
|
-
3. **HIGH**: 集成 auto-mode 分类器到 plan 模式
|
|
2319
|
-
4. **MEDIUM**: 修复 `getPlanSlug` 碰撞降级(添加 timestamp/UUID)
|
|
2320
|
-
5. **MEDIUM**: 修复 `ALL_BLOCKED_TOOLS` 使用实际工具名
|
|
2321
|
-
6. **MEDIUM**: 添加 `allowedPrompts` 权限系统集成
|
|
2322
|
-
|
|
2323
|
-
---
|
|
2324
|
-
|
|
2325
|
-
**已完成 27 轮扫描。** 计划系统已覆盖。
|
|
2326
|
-
|
|
2327
|
-
---
|
|
2328
|
-
|
|
2329
|
-
## Round 28 — Image Handling(图片处理)
|
|
2330
|
-
|
|
2331
|
-
**扫描时间**: 2026-06-12
|
|
2332
|
-
**扫描模块**: `utils/mime.ts`, `utils/photon.ts`, `modes/utils/image-resize.ts`, `modes/utils/image-convert.ts`, `modes/utils/clipboard-image.ts`, `core/lib/tui/src/terminal-image.ts`, `core/lib/tui/src/components/image.ts`, `modes/interactive/controllers/image-pipeline-controller.ts`
|
|
2333
|
-
**对比**: CC `src/tools/FileReadTool/imageProcessor.ts`, `src/utils/imageResizer.ts`, `src/utils/imagePaste.ts`, `src/utils/screenshotClipboard.ts`, `src/utils/imageStore.ts`, `src/utils/imageValidation.ts`, `src/components/ClickableImageRef.tsx`
|
|
2334
|
-
|
|
2335
|
-
### 1. 架构对比
|
|
2336
|
-
|
|
2337
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2338
|
-
|------|-----------|-------------|
|
|
2339
|
-
| 图像处理引擎 | Photon(Rust/WASM)+ `fs.readFileSync` monkey-patch | Sharp(原生 Node)+ NAPI 降级 |
|
|
2340
|
-
| 终端图片显示 | Kitty 图形协议(分块+图片 ID)+ iTerm2 内联 | 纯文本 `[Image #N]` 可点击链接 |
|
|
2341
|
-
| 压缩策略 | Lanczos3 缩放 → 质量递减 → 尺寸递减 | 渐进缩放 → 调色板 PNG(64 色)→ JPEG 多质量 → 超压缩降级 |
|
|
2342
|
-
| 剪贴板 I/O | Wayland/X11/macOS(同步 `spawnSync`) | macOS/Linux/Windows(异步 + 原生快速路径) |
|
|
2343
|
-
| 图片持久化 | 写入项目 cwd,会话结束清理 | `~/.claude/image-cache/` LRU 200 张 + 跨会话清理 |
|
|
2344
|
-
| Token 感知 | 无(固定 4.5MB 限制) | `compressImageBufferWithTokenLimit()` 映射 token 预算到字节 |
|
|
2345
|
-
| API 验证 | 无 | `validateImagesForAPI()` 硬门控 5MB base64 |
|
|
2346
|
-
| Windows 支持 | 无 | 完整 PowerShell 剪贴板 |
|
|
2347
|
-
| 多格式解析 | PNG/JPEG/GIF/WebP 头部直接解析(无需完整解码) | Sharp 元数据(需完整解码) |
|
|
2348
|
-
| 截图导出 | 无 | `screenshotClipboard.ts` ANSI→PNG→剪贴板 |
|
|
2349
|
-
| 多 provider 测试 | 11 家 provider 单元测试 | 无 |
|
|
2350
|
-
|
|
2351
|
-
**nanoPencil 优势:终端内联图片渲染** — Kitty/iTerm2 像素级渲染,CC 仅文本引用。
|
|
2352
|
-
|
|
2353
|
-
### 2. 正确性缺陷
|
|
2354
|
-
|
|
2355
|
-
**CRITICAL — `convertToPng()` 忽略输入格式**
|
|
2356
|
-
`image-convert.ts` L13-44:始终调用 `image.get_bytes()` 返回 PNG。4.9MB JPEG 输入会产生 15MB+ PNG,远超 API 5MB base64 限制。无转换后大小检查,不尝试保留 JPEG 格式。
|
|
2357
|
-
|
|
2358
|
-
**HIGH — `convertToPng()` 在剪贴板管道中无大小守卫**
|
|
2359
|
-
`clipboard-image.ts` L72-91:BMP 转 PNG 后无大小检查,大 BMP 产生的 PNG 直接流入 LLM。
|
|
2360
|
-
|
|
2361
|
-
**HIGH — 同步剪贴板读取阻塞事件循环**
|
|
2362
|
-
`clipboard-image.ts` L93-119:`spawnSync()` 阻塞最多 3000ms。CC 使用异步 `execFileNoThrowWithCwd()`。
|
|
2363
|
-
|
|
2364
|
-
**MEDIUM — `resizeImage()` Photon 失败时静默返回原图**
|
|
2365
|
-
`image-resize.ts` L68-80:WASM 加载失败时返回 `wasResized: false`,静默传递超大图片。CC 抛出 `ImageResizeError`。
|
|
2366
|
-
|
|
2367
|
-
**MEDIUM — `getPngDimensions()` 未验证 IHDR 块类型**
|
|
2368
|
-
`terminal-image.ts` L208-227:检查 PNG 签名但未验证字节 8-11 的 IHDR 块类型,损坏 PNG 可能产生错误尺寸。
|
|
2369
|
-
|
|
2370
|
-
**LOW — 图片管道写入项目 cwd**
|
|
2371
|
-
`image-pipeline-controller.ts` L343-349:`_np_clipboard_image_N.png` 写入项目根目录,崩溃后残留污染 git status。
|
|
2372
|
-
|
|
2373
|
-
**LOW — `tryBothFormats()` 每次分配双倍缓冲区**
|
|
2374
|
-
`image-resize.ts` L118-136:同时生成 PNG 和 JPEG 缓冲区再选小的,大图片时内存/CPU 翻倍。
|
|
2375
|
-
|
|
2376
|
-
### 3. 高可用差距
|
|
2377
|
-
|
|
2378
|
-
| 差距 | 影响 | 严重度 |
|
|
2379
|
-
|------|------|--------|
|
|
2380
|
-
| 无 API 级大小验证 | 超大图片到达 API 后返回不透明错误 | **HIGH** |
|
|
2381
|
-
| Photon 失败静默降级 | 超大图片未经压缩直接发送 | **HIGH** |
|
|
2382
|
-
| 同步剪贴板 I/O | 大截图阻塞事件循环 3s | **HIGH** |
|
|
2383
|
-
| 无 magic bytes 格式检测 | 仅依赖 `file-type` 库嗅探 | **MEDIUM** |
|
|
2384
|
-
| 剪贴板文件清理竞态 | 崩溃后项目目录残留临时文件 | **MEDIUM** |
|
|
2385
|
-
| 无空图片守卫 | 0 字节输入静默通过 | **MEDIUM** |
|
|
2386
|
-
|
|
2387
|
-
### 4. CC 功能差距
|
|
2388
|
-
|
|
2389
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2390
|
-
|---------|----------------|--------|
|
|
2391
|
-
| API 边界大小验证(`validateImagesForAPI`) | 未实现 | **HIGH** |
|
|
2392
|
-
| Token 预算感知压缩 | 未实现(固定 4.5MB) | **HIGH** |
|
|
2393
|
-
| Windows 剪贴板支持 | 未实现 | **HIGH** |
|
|
2394
|
-
| 持久化图片存储(LRU 200 张) | 写入项目 cwd | **MEDIUM** |
|
|
2395
|
-
| 剪贴板图片提示(焦点恢复通知) | 未实现 | **MEDIUM** |
|
|
2396
|
-
| 多阶段压缩管道(调色板 PNG + 多质量 JPEG) | 简化管道 | **MEDIUM** |
|
|
2397
|
-
| 截图到剪贴板(ANSI→PNG) | 未实现 | **MEDIUM** |
|
|
2398
|
-
| ANSI→PNG 转换 | 未实现 | **MEDIUM** |
|
|
2399
|
-
| 原生剪贴板模块(macOS NAPI ~5ms) | 同步 spawn ~1.5s | **LOW** |
|
|
2400
|
-
| BMP magic bytes 检测 | 仅 Wayland 路径 | **LOW** |
|
|
2401
|
-
| macOS 截图路径薄空格处理 | 未实现 | **LOW** |
|
|
2402
|
-
| 设备文件阻塞守卫 | 未实现 | **LOW** |
|
|
2403
|
-
|
|
2404
|
-
### 5. nanoPencil 独有优势
|
|
2405
|
-
|
|
2406
|
-
- **终端内联图片渲染**:Kitty + iTerm2 像素级显示,CC 无此能力
|
|
2407
|
-
- **11 provider 图片测试**:Anthropic/OpenAI/Google/Mistral/Bedrock 等全面覆盖
|
|
2408
|
-
- **Base64 头部直接解析**:无需完整解码即可获取 PNG/JPEG/GIF/WebP 尺寸
|
|
2409
|
-
- **Wayland 优先检测**:Linux 剪贴板先尝试 wl-paste 再降级 xclip
|
|
2410
|
-
- **`isImageLine()` 检测**:Kitty/iTerm2 图片行回归测试
|
|
2411
|
-
|
|
2412
|
-
### 汇总
|
|
2413
|
-
|
|
2414
|
-
| 严重度 | 数量 |
|
|
2415
|
-
|--------|------|
|
|
2416
|
-
| CRITICAL | 1(convertToPng 格式膨胀) |
|
|
2417
|
-
| HIGH | 4(无 API 验证、无 token 压缩、同步 I/O、无 Windows) |
|
|
2418
|
-
| MEDIUM | 6(静默降级、IHDR 验证、空守卫、magic bytes、清理竞态、多阶段压缩) |
|
|
2419
|
-
| LOW | 5(cwd 文件、双缓冲区、NAPI、BMP 检测、设备守卫) |
|
|
2420
|
-
|
|
2421
|
-
**优先修复项:**
|
|
2422
|
-
1. **CRITICAL**: 修复 `convertToPng()` 保留 JPEG 格式(使用 `get_bytes_jpeg()`)
|
|
2423
|
-
2. **HIGH**: 添加 `validateImagesForAPI()` API 边界大小验证
|
|
2424
|
-
3. **HIGH**: 将剪贴板读取改为异步(替换 `spawnSync`)
|
|
2425
|
-
4. **HIGH**: 添加 `resizeImage()` 空图片 + Photon 失败守卫
|
|
2426
|
-
5. **MEDIUM**: 将剪贴板临时文件写入 `os.tmpdir()` 而非项目 cwd
|
|
2427
|
-
6. **MEDIUM**: 添加 Windows PowerShell 剪贴板支持
|
|
2428
|
-
|
|
2429
|
-
---
|
|
2430
|
-
|
|
2431
|
-
**已完成 28 轮扫描。** 图片处理已覆盖。
|
|
2432
|
-
|
|
2433
|
-
---
|
|
2434
|
-
|
|
2435
|
-
## Round 29 — Sandbox/Security System(沙箱/安全系统)
|
|
2436
|
-
|
|
2437
|
-
**扫描时间**: 2026-06-12
|
|
2438
|
-
**扫描模块**: `core/tools/bash.ts`(sandbox hook L452-628), `extensions/builtin/security-audit/`(DangerDetector, Interceptor, AuditLogger), `core/sub-agent/agent-handoff-safety.ts`, `core/sub-agent/agent-tool-filter.ts`
|
|
2439
|
-
**对比**: CC `src/utils/sandbox/sandbox-adapter.ts`(986 行), `src/utils/permissions/`, `src/tools/BashTool/bashSecurity.ts`, `src/utils/permissions/yoloClassifier.ts`, `src/utils/permissions/dangerousPatterns.ts`
|
|
2440
|
-
|
|
2441
|
-
### 1. 架构对比
|
|
2442
|
-
|
|
2443
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2444
|
-
|------|-----------|-------------|
|
|
2445
|
-
| 安全范式 | **审计导向** — 应用层 regex 屏障 | **执行导向** — OS 级沙箱 + 多层防御 |
|
|
2446
|
-
| OS 级沙箱 | 无 | Seatbelt(macOS)+ bwrap(Linux/WSL2) |
|
|
2447
|
-
| 文件系统限制 | Regex-only,审计模式下不强制 | 内核级 denyRead/denyWrite/allowWrite glob 支持 |
|
|
2448
|
-
| 网络限制 | 无 | 域名 allow/deny 列表 + 代理端口 + unix socket |
|
|
2449
|
-
| 命令分析 | 正则匹配(~15 模式) | Tree-sitter AST 解析 + 23+ 注入检测 + 语义分析 |
|
|
2450
|
-
| 权限模式 | 2 种(plan + default) | 6 种(default/plan/acceptEdits/bypassPermissions/dontAsk/auto) |
|
|
2451
|
-
| 权限规则 | 配置白名单 | 10+ 来源的 allow/deny/ask 规则管道(tool-level/prefix/exact/wildcard) |
|
|
2452
|
-
| AI 分类器 | 无(仅启发式) | 两阶段 LLM 分类器 + 转录上下文 |
|
|
2453
|
-
| 危险命令模式 | ~15 regex | 50+ 模式(含 zsh builtins/进程替换/控制字符/unicode 空白) |
|
|
2454
|
-
| Git 安全 | 仅 force push(审计模式) | bare repo 攻击防护 + cd+git 阻断 + worktree 检测 + 命令后擦除 |
|
|
2455
|
-
| 路径验证 | 无 | 完整路径约束 + 重定向分析 + 危险文件保护 |
|
|
2456
|
-
| 拒绝追踪 | 无 | 连续拒绝追踪 + 总拒绝限制 + 自动降级到提示 |
|
|
2457
|
-
| 策略锁定 | 无 | 策略锁定设置不可本地覆盖 |
|
|
2458
|
-
| 子代理分类器 | 启发式(7 模式) | 完整 LLM 分类器 |
|
|
2459
|
-
|
|
2460
|
-
### 2. 正确性缺陷
|
|
2461
|
-
|
|
2462
|
-
**CRITICAL — 无 OS 级沙箱**
|
|
2463
|
-
`core/tools/bash.ts`:命令通过 `child_process.spawn(detached: true)` 以完整用户权限执行。Regex 沙箱是唯一屏障,足够聪明的 LLM 可轻易绕过。
|
|
2464
|
-
|
|
2465
|
-
**CRITICAL — Regex 沙箱可被绕过**
|
|
2466
|
-
`bash.ts` L452-474:`SANDBOX_BLOCKED_PATTERNS` 存在已知缺口:
|
|
2467
|
-
- `git stash push/drop/pop/apply` 未阻断
|
|
2468
|
-
- `git branch -d/-D` 未阻断
|
|
2469
|
-
- `git tag -d`、`git config --global`、`git clean -f`、`git update-ref`、`git restore` 未阻断
|
|
2470
|
-
- `>` 重定向正则有根本缺陷(`\s>` 匹配多字符序列内部)
|
|
2471
|
-
|
|
2472
|
-
**HIGH — 无命令注入检测**
|
|
2473
|
-
无 tree-sitter AST 解析,无 shell-quote 验证,无 backtick/替换检测。CC 有 23+ 安全检查类别。
|
|
2474
|
-
|
|
2475
|
-
**HIGH — 无网络限制**
|
|
2476
|
-
`curl`、`wget`、`nc` 等网络工具可自由建立出站连接。
|
|
2477
|
-
|
|
2478
|
-
**HIGH — 无文件系统路径限制**
|
|
2479
|
-
无机制将写入限制在项目目录内。`DangerDetector` 在审计模式下仅信息性记录。
|
|
2480
|
-
|
|
2481
|
-
**HIGH — Regex 命令分词不可靠**
|
|
2482
|
-
`tokenizeSimpleShell`(L578-624)不处理:进程替换 `<(cmd)`、算术扩展 `$(( ))`、brace 展开 `{a,b,c}`、heredocs `<<EOF`。
|
|
2483
|
-
|
|
2484
|
-
**MEDIUM — 沙箱消息 shell 注入**
|
|
2485
|
-
`bash.ts` L500-503:`blockedMessage` 通过模板字面量插入 shell 命令,自定义消息未消毒。
|
|
2486
|
-
|
|
2487
|
-
**MEDIUM — 安全审计默认仅审计**
|
|
2488
|
-
`interface.ts` L198:`enableInterception: false` 默认值意味着即使检测到危险命令也不拦截。
|
|
2489
|
-
|
|
2490
|
-
### 3. 高可用差距
|
|
2491
|
-
|
|
2492
|
-
| 差距 | 影响 | 严重度 |
|
|
2493
|
-
|------|------|--------|
|
|
2494
|
-
| 安全审计扩展加载失败无降级 | 安全门控静默丢失 | **HIGH** |
|
|
2495
|
-
| 审计日志同步 I/O | 每次工具调用阻塞事件循环 | **MEDIUM** |
|
|
2496
|
-
| 沙箱 hook 异常时命令可能仍执行 | 路径解析失败绕过沙箱 | **HIGH** |
|
|
2497
|
-
| 后台任务 Map 进程重启丢失 | 孤儿临时文件未清理 | **LOW** |
|
|
2498
|
-
| 无违规聚合存储 | 审计模式违规仅日志不汇总 | **MEDIUM** |
|
|
2499
|
-
|
|
2500
|
-
### 4. CC 功能差距
|
|
2501
|
-
|
|
2502
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2503
|
-
|---------|----------------|--------|
|
|
2504
|
-
| OS 级沙箱(Seatbelt/bwrap) | 无 | **CRITICAL** |
|
|
2505
|
-
| 文件系统写入限制 | Regex-only | **CRITICAL** |
|
|
2506
|
-
| 网络域名限制 | 无 | **CRITICAL** |
|
|
2507
|
-
| Regex 沙箱可绕过 | 仅 regex | **CRITICAL** |
|
|
2508
|
-
| 命令注入检测(23+ 检查) | 无 | **HIGH** |
|
|
2509
|
-
| Tree-sitter AST 分析 | 无 | **HIGH** |
|
|
2510
|
-
| AI 权限分类器 | 无 | **HIGH** |
|
|
2511
|
-
| 权限模式(6 种 vs 2 种) | 仅 2 种 | **HIGH** |
|
|
2512
|
-
| allow/deny/ask 规则管道 | 仅白名单 | **HIGH** |
|
|
2513
|
-
| Git 安全守卫 | 仅 force push | **HIGH** |
|
|
2514
|
-
| 路径约束验证 | 无 | **HIGH** |
|
|
2515
|
-
| Sed 约束检查 | 无 | **MEDIUM** |
|
|
2516
|
-
| 命令操作符处理 | 无 | **MEDIUM** |
|
|
2517
|
-
| 多源设置配置 | 单一 env var | **MEDIUM** |
|
|
2518
|
-
| 子代理 LLM 分类器 | 启发式 | **MEDIUM** |
|
|
2519
|
-
| 危险文件保护 | 无 | **MEDIUM** |
|
|
2520
|
-
| 拒绝追踪 | 无 | **MEDIUM** |
|
|
2521
|
-
| 策略锁定 | 无 | **MEDIUM** |
|
|
2522
|
-
| 排除命令特性 | 无 | **LOW** |
|
|
2523
|
-
| Auto-mode AI | 无 | **LOW** |
|
|
2524
|
-
|
|
2525
|
-
### 5. nanoPencil 优势
|
|
2526
|
-
|
|
2527
|
-
- **扩展架构安全审计**:作为扩展模块可独立启用/禁用,比 CC 内嵌更灵活
|
|
2528
|
-
- **三级拦截模式**:audit/confirm/strict 可按需选择
|
|
2529
|
-
- **事件驱动**:通过 `tool_call` 事件统一拦截,不侵入工具代码
|
|
2530
|
-
|
|
2531
|
-
### 汇总
|
|
2532
|
-
|
|
2533
|
-
| 严重度 | 数量 |
|
|
2534
|
-
|--------|------|
|
|
2535
|
-
| CRITICAL | 4(无 OS 沙箱、无 FS 限制、无网络限制、regex 可绕过) |
|
|
2536
|
-
| HIGH | 7(无注入检测、无 AST、无 AI 分类器、权限模式不足、无规则管道、Git 安全不足、无路径验证) |
|
|
2537
|
-
| MEDIUM | 7(shell 注入、审计默认值、扩展降级、同步 I/O、沙箱恢复、违规存储、子代理分类器) |
|
|
2538
|
-
| LOW | 3(审计日志明文、后台任务清理、排除命令) |
|
|
2539
|
-
|
|
2540
|
-
**优先修复项:**
|
|
2541
|
-
1. **CRITICAL**: 集成 OS 级沙箱(至少 bwrap for Linux,seatbelt for macOS)
|
|
2542
|
-
2. **CRITICAL**: 添加网络域名限制(至少支持 `allowedDomains` 配置)
|
|
2543
|
-
3. **HIGH**: 实现 tree-sitter AST 命令分析替代 regex
|
|
2544
|
-
4. **HIGH**: 添加 allow/deny/ask 权限规则管道
|
|
2545
|
-
5. **HIGH**: 完善 Git 安全守卫(bare repo、cd+git、branch -d 等)
|
|
2546
|
-
6. **MEDIUM**: 修复安全审计默认启用拦截(`enableInterception: true`)
|
|
2547
|
-
|
|
2548
|
-
---
|
|
2549
|
-
|
|
2550
|
-
**已完成 29 轮扫描。** 沙箱/安全系统已覆盖。
|
|
2551
|
-
|
|
2552
|
-
---
|
|
2553
|
-
|
|
2554
|
-
## Round 30 — CLI Entry Point(CLI 入口)
|
|
2555
|
-
|
|
2556
|
-
**扫描时间**: 2026-06-12
|
|
2557
|
-
**扫描模块**: `cli.ts`, `cli/args.ts`, `main.ts`
|
|
2558
|
-
**对比**: CC `src/entrypoints/cli.tsx`, `src/main.tsx`(Commander.js + 50+ 选项 + 50+ 子命令)
|
|
2559
|
-
|
|
2560
|
-
### 1. 架构对比
|
|
2561
|
-
|
|
2562
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2563
|
-
|------|-----------|-------------|
|
|
2564
|
-
| 入口文件 | `cli.ts`(`#!/usr/bin/env node`) | `src/entrypoints/cli.tsx` |
|
|
2565
|
-
| 参数解析 | 手写 for 循环(~80 个 else-if 分支) | Commander.js(`@commander-js/extra-typings`) |
|
|
2566
|
-
| 子命令路由 | 手动 if/else 匹配 `args[0]`(4 个子命令) | Commander `.command().action()` 树(50+ 子命令) |
|
|
2567
|
-
| 快速路径 | 2 个(`--version`/`--help`) | ~15 个(version/daemon/bridge/bg/templates/runners/worktree 等) |
|
|
2568
|
-
| 版本常量 | 运行时磁盘读取 `package.json` | 编译时内联 `MACRO.VERSION` |
|
|
2569
|
-
| 启动 profiling | `profileCheckpoint()` | `profileCheckpoint()`(相同模式) |
|
|
2570
|
-
| 初始化系统 | 内联在 `main()` 函数中 | 独立 `init()`(memoized) |
|
|
2571
|
-
| Feature gating | 运行时 `APP_NAME` 检查 | 编译时 `feature()` DCE |
|
|
2572
|
-
| 扩展 flag 发现 | 两阶段解析(核心→扩展加载→重解析) | 扩展在 commander 解析后加载 |
|
|
2573
|
-
| 预导入并行 | 无 | `startMdmRawRead()` + `startKeychainPrefetch()` |
|
|
2574
|
-
|
|
2575
|
-
### 2. 正确性缺陷
|
|
2576
|
-
|
|
2577
|
-
**Defect 1 — 未知 flag 静默忽略(MEDIUM)**
|
|
2578
|
-
`cli/args.ts` L299-310:`--modle` 等拼写错误无警告。CC 的 Commander.js 默认对未知选项报错。
|
|
2579
|
-
|
|
2580
|
-
**Defect 2 — `process.exit(1)` 无优雅关闭(LOW)**
|
|
2581
|
-
`main.ts` L541/588/683/909/997/1118:致命错误使用裸 `process.exit(1)`,清理处理器(session 状态写入、输出刷新)可能不运行。CC 有 `gracefulShutdown()` + `registerCleanup()` 系统。
|
|
2582
|
-
|
|
2583
|
-
**Defect 3 — `process.exitCode = 1` 无显式退出(LOW)**
|
|
2584
|
-
`main.ts` L336/344/373/432:设置 `exitCode` 但不调用 `process.exit()`,依赖事件循环排空。
|
|
2585
|
-
|
|
2586
|
-
**Defect 4 — 版本显示磁盘 I/O(LOW)**
|
|
2587
|
-
`cli.ts` L17-25:`--version` 快速路径读取并解析 `package.json`。CC 使用编译时内联常量零导入。
|
|
2588
|
-
|
|
2589
|
-
**Defect 5 — `--cwd ~` 不展开(LOW)**
|
|
2590
|
-
`main.ts` L200-204:`resolveWorkingDirectory` 调用 `path.resolve()` 不展开 `~`。`--cwd ~/projects` 解析为 `<cwd>/~/projects`。
|
|
2591
|
-
|
|
2592
|
-
**Defect 6 — `--mode` 无值验证(LOW)**
|
|
2593
|
-
`cli/args.ts` L149-153:`--mode` 接受 `text`/`json`/`rpc`,但无效值静默忽略无警告。
|
|
2594
|
-
|
|
2595
|
-
### 3. 高可用差距
|
|
2596
|
-
|
|
2597
|
-
| 差距 | 影响 | 严重度 |
|
|
2598
|
-
|------|------|--------|
|
|
2599
|
-
| 无自动更新检查 | 用户无法得知新版本 | **HIGH** |
|
|
2600
|
-
| 无 `doctor` 命令 | 无法诊断安装问题 | **MEDIUM** |
|
|
2601
|
-
| 无优雅关闭系统 | 错误退出可能丢失 session 状态 | **MEDIUM** |
|
|
2602
|
-
| 无远程管理设置/企业策略 | 无法集中推送配置 | **MEDIUM** |
|
|
2603
|
-
| 无 telemetry | 最小可观测性 | **LOW** |
|
|
2604
|
-
|
|
2605
|
-
### 4. CC 功能差距
|
|
2606
|
-
|
|
2607
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2608
|
-
|---------|----------------|--------|
|
|
2609
|
-
| Commander.js CLI 框架 | 手写 80 分支 parser | **HIGH** |
|
|
2610
|
-
| 50+ 子命令(mcp/auth/plugin/doctor/task/auto-mode 等) | 4 个子命令 | **HIGH** |
|
|
2611
|
-
| 自动更新机制(npm/Homebrew/winget) | 无 | **HIGH** |
|
|
2612
|
-
| `doctor` 健康检查 | 无 | **MEDIUM** |
|
|
2613
|
-
| `auth login/status/logout` | env vars + models.json | **MEDIUM** |
|
|
2614
|
-
| `mcp serve/add/remove/list/get` | 默认开启无 CLI 管理 | **MEDIUM** |
|
|
2615
|
-
| `--output-format stream-json` | `--mode json`(基础) | **MEDIUM** |
|
|
2616
|
-
| `--permission-mode` | `--no-tools`/`--tools` | **MEDIUM** |
|
|
2617
|
-
| 编译时 feature gating DCE | 运行时检查 | **MEDIUM** |
|
|
2618
|
-
| 预导入并行(MDM + keychain) | 无 | **MEDIUM** |
|
|
2619
|
-
| `--bare` 轻量模式 | `--offline`(仅网络) | **LOW** |
|
|
2620
|
-
| `--settings` 运行时加载 | 仅 `settings.json` | **LOW** |
|
|
2621
|
-
| `plugin marketplace` 生命周期 | 基础 install/remove | **LOW** |
|
|
2622
|
-
| `--json-schema` 结构化输出 | 无 | **LOW** |
|
|
2623
|
-
| `~` 展开 | 不支持 | **LOW** |
|
|
2624
|
-
|
|
2625
|
-
### 5. nanoPencil 优势
|
|
2626
|
-
|
|
2627
|
-
- **两阶段扩展 flag 解析**:先解析核心 flag → 加载扩展 → 再解析扩展 flag,比 CC 的单一阶段更灵活
|
|
2628
|
-
- **零依赖参数解析**:无外部库依赖,bundle 更小
|
|
2629
|
-
- **快速路径延迟导入**:`--version`/`--help` 在 `import("./main.js")` 前退出,与 CC 模式一致
|
|
2630
|
-
|
|
2631
|
-
### 汇总
|
|
2632
|
-
|
|
2633
|
-
| 严重度 | 数量 |
|
|
2634
|
-
|--------|------|
|
|
2635
|
-
| HIGH | 3(无 CLI 框架、子命令不足、无更新机制) |
|
|
2636
|
-
| MEDIUM | 7(未知 flag 静默、无 doctor、无优雅关闭、无企业策略、无 auth CLI、无 MCP CLI、无 stream-json) |
|
|
2637
|
-
| LOW | 6(exitCode、版本 I/O、tilde、mode 验证、bare、settings) |
|
|
2638
|
-
|
|
2639
|
-
**优先修复项:**
|
|
2640
|
-
1. **HIGH**: 添加 `update`/`upgrade` 子命令(npm registry 版本检查 + 自动更新)
|
|
2641
|
-
2. **HIGH**: 添加未知 flag 警告(至少 `console.warn`)
|
|
2642
|
-
3. **MEDIUM**: 实现 `gracefulShutdown()` 清理注册系统
|
|
2643
|
-
4. **MEDIUM**: 添加 `doctor` 健康检查命令
|
|
2644
|
-
5. **MEDIUM**: 添加 `auth login/status/logout` 子命令
|
|
2645
|
-
6. **LOW**: 修复 `--cwd ~` 展开
|
|
2646
|
-
|
|
2647
|
-
---
|
|
2648
|
-
|
|
2649
|
-
**已完成 30 轮扫描。** CLI 入口已覆盖。
|
|
2650
|
-
|
|
2651
|
-
---
|
|
2652
|
-
|
|
2653
|
-
## Round 31 — Plugin/Extension Loading Framework(插件/扩展加载框架)
|
|
2654
|
-
|
|
2655
|
-
**扫描时间**: 2026-06-12
|
|
2656
|
-
**扫描模块**: `core/extensions-host/loader.ts`(4 层发现 + jiti 加载), `core/extensions-host/runner.ts`(生命周期+事件), `core/extensions-host/types.ts`(1474 行类型定义), `core/extensions-host/wrapper.ts`(工具包装), `builtin-extensions.ts`(25+ 内置扩展注册)
|
|
2657
|
-
**对比**: CC `src/utils/plugins/pluginLoader.ts`, `src/types/plugin.ts`, `src/utils/plugins/installedPluginsManager.ts`, `src/utils/plugins/marketplaceManager.ts`, `src/utils/plugins/pluginAutoupdate.ts`, `src/utils/plugins/pluginPolicy.ts`, `src/commands/plugin/`(17 文件 300K+)
|
|
2658
|
-
|
|
2659
|
-
### 1. 架构对比
|
|
2660
|
-
|
|
2661
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2662
|
-
|------|-----------|-------------|
|
|
2663
|
-
| 发现模型 | 4 层(项目/全局/配置路径/npm) | 3 层(session/marketplace/builtin) |
|
|
2664
|
-
| 加载机制 | `jiti`(TS JIT 导入) | 标准 Node.js `import()` |
|
|
2665
|
-
| 扩展契约 | 导出工厂函数 `(api) => void` | 结构化清单 `plugin.json` + markdown 命令 |
|
|
2666
|
-
| 事件/Hook 系统 | 30+ 类型化事件 + 编程式处理器 | 20+ matcher-based hooks + JSON 配置 |
|
|
2667
|
-
| 注册能力 | 工具/命令/事件/快捷键/flag/消息渲染器/provider | Markdown 命令 + hooks + MCP/LSP 服务器 |
|
|
2668
|
-
| 内置扩展 | 25+(`builtin-extensions.ts` + 风险元数据) | 内置插件注册表 |
|
|
2669
|
-
| 启用/禁用 | 无(内置扩展始终加载) | 完整 enable/disable + 持久化 |
|
|
2670
|
-
| 版本管理 | 无 | 版本化缓存 + V1/V2 迁移 + 回滚 |
|
|
2671
|
-
| 自动更新 | 无 | 后台自动更新 + 通知 |
|
|
2672
|
-
| Marketplace | 无(仅 npm 层发现) | 完整 marketplace 系统 + UI |
|
|
2673
|
-
| 企业策略 | 无 | 策略强制/禁用 + 黑名单 |
|
|
2674
|
-
| UI 管理 | 配置文件 | `/plugin` 交互式 UI(17 文件) |
|
|
2675
|
-
| 沙箱 | 无(同进程完整 API 访问) | 无 |
|
|
2676
|
-
| 依赖解析 | 无 | `dependencyResolver.ts` |
|
|
2677
|
-
| 每插件配置 | 共享 Settings | `pluginOptionsStorage.ts` + UI |
|
|
2678
|
-
| 错误类型 | `{ path, error }` 扁平字符串 | 20+ 变体判别联合 |
|
|
2679
|
-
|
|
2680
|
-
### 2. 正确性缺陷
|
|
2681
|
-
|
|
2682
|
-
**Defect 1 — 内置扩展无法禁用(HIGH)**
|
|
2683
|
-
`builtin-extensions.ts` L129-362:`getBuiltinExtensionPaths()` 无条件推送所有 `defaultEnabled` 扩展。`settings.extensions[]` 仅添加不减去。用户无法禁用 `team` 等内置扩展。
|
|
2684
|
-
|
|
2685
|
-
**Defect 2 — 并行加载隐藏顺序依赖(MEDIUM)**
|
|
2686
|
-
`loader.ts` L348-383:`Promise.all` 并行加载,但 SAL 必须在 NanoMem 之前加载(L141-147),diagnostics 必须首先加载(L130-135)。实际执行顺序不确定。
|
|
2687
|
-
|
|
2688
|
-
**Defect 3 — 无扩展级沙箱(HIGH)**
|
|
2689
|
-
扩展在同进程中运行,拥有完整 Node.js/Bun API 访问。`ExtensionAPI.exec()` 提供直接 shell 执行能力。`riskLevel` 元数据仅为信息性不强制执行。
|
|
2690
|
-
|
|
2691
|
-
**Defect 4 — `before_agent_start` 超时静默丢弃(MEDIUM)**
|
|
2692
|
-
`runner.ts` L276-292:处理器超时(默认 1500ms)后静默跳过,仅限频控制台警告。关键扩展的系统提示注入可能被静默丢失。
|
|
2693
|
-
|
|
2694
|
-
**Defect 5 — `emitToolCall` 未捕获处理器错误(MEDIUM)**
|
|
2695
|
-
`runner.ts` L922-943:与 `emitToolResult`(L872-920 有 try/catch)不同,`emitToolCall` 的单个处理器异常会传播并阻断后续处理器。
|
|
2696
|
-
|
|
2697
|
-
### 3. 高可用差距
|
|
2698
|
-
|
|
2699
|
-
| 差距 | 影响 | 严重度 |
|
|
2700
|
-
|------|------|--------|
|
|
2701
|
-
| 无热重载 | 扩展更改需重启 session | **MEDIUM** |
|
|
2702
|
-
| 无版本管理/回滚 | npm 更新后无迁移路径 | **HIGH** |
|
|
2703
|
-
| 无健康监控/熔断器 | 持续失败的扩展永远记录错误 | **MEDIUM** |
|
|
2704
|
-
| 无资源隔离 | 共享 EventBus,内存泄漏影响所有扩展 | **MEDIUM** |
|
|
2705
|
-
| 仅 `before_agent_start` 有超时 | 其他事件处理器无超时保护 | **MEDIUM** |
|
|
2706
|
-
|
|
2707
|
-
### 4. CC 功能差距
|
|
2708
|
-
|
|
2709
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2710
|
-
|---------|----------------|--------|
|
|
2711
|
-
| Marketplace/商店系统 | 仅 npm 层发现 | **HIGH** |
|
|
2712
|
-
| 插件启用/禁用 UI | 配置文件 | **HIGH** |
|
|
2713
|
-
| 插件版本化 + 缓存管理 | 无 | **HIGH** |
|
|
2714
|
-
| 插件自动更新 | 无 | **HIGH** |
|
|
2715
|
-
| 企业策略强制 | 无 | **HIGH** |
|
|
2716
|
-
| 插件黑名单 | 无 | **HIGH** |
|
|
2717
|
-
| 插件依赖解析 | 无 | **MEDIUM** |
|
|
2718
|
-
| 每插件配置存储 | 共享 Settings | **MEDIUM** |
|
|
2719
|
-
| 结构化清单验证 | 工厂函数检查 | **MEDIUM** |
|
|
2720
|
-
| 插件错误类型判别 | 扁平字符串 | **MEDIUM** |
|
|
2721
|
-
| `clearPluginCache()` | 无 | **MEDIUM** |
|
|
2722
|
-
| 插件回滚 | 无 | **MEDIUM** |
|
|
2723
|
-
|
|
2724
|
-
### 5. nanoPencil 独有优势
|
|
2725
|
-
|
|
2726
|
-
- **更强大的扩展 API**:编程式工具注册、类型化事件、TUI 组件、provider 注册、LLM completion 访问
|
|
2727
|
-
- **30+ 类型化事件系统**:覆盖 session/agent/工具/模型/输入/上下文全生命周期
|
|
2728
|
-
- **风险元数据**:`riskLevel`/`writesWorkspace`/`externalProcess` 等信息性标签
|
|
2729
|
-
- **jiti JIT 加载**:支持 TS/ESM 零编译加载
|
|
2730
|
-
- **消息渲染器**:扩展可注册自定义消息渲染
|
|
2731
|
-
- **Provider 注册**:扩展可注册模型 provider
|
|
2732
|
-
- **TypeBox schema**:运行时类型验证
|
|
2733
|
-
|
|
2734
|
-
### 汇总
|
|
2735
|
-
|
|
2736
|
-
| 严重度 | 数量 |
|
|
2737
|
-
|--------|------|
|
|
2738
|
-
| HIGH | 5(无法禁用内置、无沙箱、无版本管理、无 marketplace、无企业策略) |
|
|
2739
|
-
| MEDIUM | 7(并行加载顺序、超时静默、emitToolCall 错误、无热重载、无健康监控、无资源隔离、无依赖解析) |
|
|
2740
|
-
| LOW | 0 |
|
|
2741
|
-
|
|
2742
|
-
**优先修复项:**
|
|
2743
|
-
1. **HIGH**: 添加内置扩展启用/禁用配置(`settings.disabledExtensions[]`)
|
|
2744
|
-
2. **HIGH**: 添加扩展版本化 + 缓存目录管理
|
|
2745
|
-
3. **HIGH**: 实现基础 marketplace 发现(npm registry 搜索 + 安装)
|
|
2746
|
-
4. **MEDIUM**: 修复 `emitToolCall` 添加 try/catch 隔离
|
|
2747
|
-
5. **MEDIUM**: 添加所有事件处理器超时保护
|
|
2748
|
-
6. **MEDIUM**: 实现扩展健康监控 + 自动禁用(N 次错误后熔断)
|
|
2749
|
-
|
|
2750
|
-
---
|
|
2751
|
-
|
|
2752
|
-
**已完成 31 轮扫描。** 插件/扩展加载框架已覆盖。
|
|
2753
|
-
|
|
2754
|
-
---
|
|
2755
|
-
|
|
2756
|
-
## Round 32 — Context Management / Compaction(上下文管理/压缩系统)
|
|
2757
|
-
|
|
2758
|
-
**扫描时间**: 2026-06-12
|
|
2759
|
-
**扫描模块**: `core/session/compaction/compaction.ts`, `core/runtime/compaction-controller.ts`, `core/runtime/agent-session.ts`(_checkCompaction), `core/lib/agent-core/src/agent-loop.ts`, `core/lib/agent-core/src/agent-loop-tool-results.ts`, `core/lib/ai/src/utils/overflow.ts`
|
|
2760
|
-
**对比**: CC `src/services/compact/`(compact.ts 1700+ 行, microCompact.ts, autoCompact.ts, sessionMemoryCompact.ts, postCompactCleanup.ts, grouping.ts, compactWarningState.ts), `src/utils/conversationRecovery.ts`, `src/services/tokenEstimation.ts`
|
|
2761
|
-
|
|
2762
|
-
### 1. 架构对比
|
|
2763
|
-
|
|
2764
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2765
|
-
|------|-----------|-------------|
|
|
2766
|
-
| 压缩层级 | 单层(全量 LLM 摘要) | 5 层防御深度(microcompact → session memory → partial → full → PTL retry) |
|
|
2767
|
-
| Microcompact | 无 | 3 级:cached MC、time-based MC、API context management |
|
|
2768
|
-
| Session Memory 压缩 | 无 | 预提取 session memory 作为摘要(无 LLM 调用) |
|
|
2769
|
-
| Token 计数 | chars/4 启发式 | API 粗估锚定 + `countTokensWithAPI()` 精确计数 |
|
|
2770
|
-
| 触发时机 | 响应后检查(`agent_end`) | 请求前检查(`shouldAutoCompact()`) |
|
|
2771
|
-
| 熔断器 | 无 | `MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3` |
|
|
2772
|
-
| PTL 重试 | 无 | `truncateHeadForPTLRetry()` 最多 3 次 |
|
|
2773
|
-
| 压缩后清理 | 无 | 10+ 缓存清理(file state/memory/系统提示/classifier 等) |
|
|
2774
|
-
| 压缩后恢复 | 无 | 重读 top 5 文件 + skill/plan 附件恢复 |
|
|
2775
|
-
| 图片剥离 | 无 | `stripImagesFromMessages()` 替换为 `[image]` 标记 |
|
|
2776
|
-
| 消息分组 | 入口级切割点 | `groupMessagesByApiRound()` 安全分割 |
|
|
2777
|
-
| 会话恢复 | 无 | `conversationRecovery.ts`(孤立 tool_use 过滤、中断检测) |
|
|
2778
|
-
| Prompt cache 共享 | 独立 `completeSimple()` 调用 | fork agent 共享 cache |
|
|
2779
|
-
| 部分压缩 | 无 | `partialCompactConversation` 双向支持 |
|
|
2780
|
-
| 树分支摘要 | 完整支持(`generateBranchSummary()`) | 无(线性消息历史) |
|
|
2781
|
-
| 迭代摘要更新 | `UPDATE_SUMMARIZATION_PROMPT` 合并 | 每次生成全新摘要 |
|
|
2782
|
-
| 文件操作追踪 | `<read-files>` + `<modified-files>` 段 | 无 |
|
|
2783
|
-
| 多 provider 溢出检测 | 15+ provider 正则模式 | 主要 Anthropic |
|
|
2784
|
-
|
|
2785
|
-
### 2. 正确性缺陷
|
|
2786
|
-
|
|
2787
|
-
**Defect 1 — Token 估算低估(HIGH)**
|
|
2788
|
-
`compaction.ts` L224-282:`estimateTokens()` 使用 chars/4 启发式。图片硬编码 4800 字符(1200 token),JSON 参数有括号/引号/键名开销。低估导致压缩触发延迟,可能在上下文已满后才触发。
|
|
2789
|
-
|
|
2790
|
-
**Defect 2 — 无请求前 token 估算(HIGH)**
|
|
2791
|
-
仅在 `agent_end` 后检查。请求略超上下文窗口时会先失败再触发溢出恢复,浪费一次 API 调用。CC 在发送请求前主动压缩。
|
|
2792
|
-
|
|
2793
|
-
**Defect 3 — 无压缩失败熔断器(HIGH)**
|
|
2794
|
-
无等效 `MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES`。压缩反复失败时无限重试。CC 全球 1279 session 触发过 50+ 连续失败,浪费 ~250K API 调用/天。
|
|
2795
|
-
|
|
2796
|
-
**Defect 4 — 切割点检测代码异味(LOW)**
|
|
2797
|
-
`findValidCutPoints()` L291-326:switch 空 case 块无 break,`branch_summary`/`custom_message` 检查重复。
|
|
2798
|
-
|
|
2799
|
-
### 3. 高可用差距
|
|
2800
|
-
|
|
2801
|
-
| 差距 | 影响 | 严重度 |
|
|
2802
|
-
|------|------|--------|
|
|
2803
|
-
| 无 microcompact(工具结果清理) | 工具结果累积到全量压缩才清理 | **CRITICAL** |
|
|
2804
|
-
| 无 session memory 压缩 | 每次压缩都需 LLM 调用 | **CRITICAL** |
|
|
2805
|
-
| 无 API token 计数 | chars/4 启发式不精确 | **HIGH** |
|
|
2806
|
-
| 无熔断器 | 压缩失败无限重试 | **HIGH** |
|
|
2807
|
-
| 无 PTL 重试 | 压缩本身溢出时无法恢复 | **HIGH** |
|
|
2808
|
-
| 无响应式压缩(413 降级) | prompt-too-long 不可恢复 | **HIGH** |
|
|
2809
|
-
| 无压缩后文件/skill/plan 恢复 | 模型丢失最近读取的文件 | **HIGH** |
|
|
2810
|
-
| 无压缩后缓存清理 | 压缩后可能使用过期缓存 | **MEDIUM** |
|
|
2811
|
-
| 无图片剥离 | 大图片导致压缩请求本身溢出 | **MEDIUM** |
|
|
2812
|
-
| 无会话恢复 | 恢复 session 可能有孤立 tool_use | **MEDIUM** |
|
|
2813
|
-
| 无 API-round 分组 | 切割点可能落在 API-round 中间 | **MEDIUM** |
|
|
2814
|
-
| 无 prompt cache 共享 | 压缩不复用主对话 cache | **MEDIUM** |
|
|
2815
|
-
|
|
2816
|
-
### 4. CC 功能差距
|
|
2817
|
-
|
|
2818
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
2819
|
-
|---------|----------------|--------|
|
|
2820
|
-
| Microcompact(3 级工具结果清理) | 无 | **CRITICAL** |
|
|
2821
|
-
| Session Memory 压缩(无 LLM 调用) | 无 | **CRITICAL** |
|
|
2822
|
-
| API token 计数 | 无 | **HIGH** |
|
|
2823
|
-
| 压缩熔断器 | 无 | **HIGH** |
|
|
2824
|
-
| PTL 重试 | 无 | **HIGH** |
|
|
2825
|
-
| 响应式压缩(413 fallback) | 无 | **HIGH** |
|
|
2826
|
-
| 压缩后文件/skill/plan 恢复 | 无 | **HIGH** |
|
|
2827
|
-
| 压缩后缓存清理(10+ 项) | 无 | **MEDIUM** |
|
|
2828
|
-
| 图片/文档剥离 | 无 | **MEDIUM** |
|
|
2829
|
-
| 部分压缩(pivot-based) | 无 | **MEDIUM** |
|
|
2830
|
-
| API-round 安全分组 | 无 | **MEDIUM** |
|
|
2831
|
-
| 会话恢复(中断检测) | 无 | **MEDIUM** |
|
|
2832
|
-
| Context collapse | 无 | **MEDIUM** |
|
|
2833
|
-
| 压缩警告抑制 | 无 | **LOW** |
|
|
2834
|
-
| 重压缩追踪 | 无 | **LOW** |
|
|
2835
|
-
| Token 预算解析("+500k" 语法) | 无 | **LOW** |
|
|
2836
|
-
|
|
2837
|
-
### 5. nanoPencil 独有优势
|
|
2838
|
-
|
|
2839
|
-
- **树分支摘要**:完整树模型 + 弃用分支摘要
|
|
2840
|
-
- **迭代摘要更新**:`UPDATE_SUMMARIZATION_PROMPT` 合并已有摘要,CC 每次全新生成
|
|
2841
|
-
- **文件操作追踪**:`<read-files>` + `<modified-files>` 跨压缩保留
|
|
2842
|
-
- **Turn-prefix 摘要**:中 turn 分割时单独摘要前缀
|
|
2843
|
-
- **15+ provider 溢出检测**:Cerebras/Mistral/z.ai/Ollama 等全覆盖
|
|
2844
|
-
|
|
2845
|
-
### 汇总
|
|
2846
|
-
|
|
2847
|
-
| 严重度 | 数量 |
|
|
2848
|
-
|--------|------|
|
|
2849
|
-
| CRITICAL | 2(无 microcompact、无 session memory 压缩) |
|
|
2850
|
-
| HIGH | 6(无 API token 计数、无熔断器、无 PTL 重试、无 413 fallback、无压缩后恢复、token 低估) |
|
|
2851
|
-
| MEDIUM | 6(无压缩后清理、无图片剥离、无部分压缩、无 API-round 分组、无会话恢复、无 cache 共享) |
|
|
2852
|
-
| LOW | 3(切割点异味、无警告抑制、无重压缩追踪) |
|
|
2853
|
-
|
|
2854
|
-
**优先修复项:**
|
|
2855
|
-
1. **CRITICAL**: 实现 microcompact(工具结果清理)— 压缩工具结果到摘要/路径引用
|
|
2856
|
-
2. **CRITICAL**: 实现 session memory 压缩(预提取摘要避免 LLM 调用)
|
|
2857
|
-
3. **HIGH**: 添加压缩熔断器(3 次连续失败后停止重试)
|
|
2858
|
-
4. **HIGH**: 实现请求前 token 估算 + 主动压缩
|
|
2859
|
-
5. **HIGH**: 添加 PTL 重试(压缩本身溢出时截断头部重试)
|
|
2860
|
-
6. **HIGH**: 实现压缩后文件/skill/plan 恢复
|
|
2861
|
-
|
|
2862
|
-
---
|
|
2863
|
-
|
|
2864
|
-
**已完成 32 轮扫描。** 上下文管理/压缩系统已覆盖。
|
|
2865
|
-
|
|
2866
|
-
---
|
|
2867
|
-
|
|
2868
|
-
## Round 33 — Model Selector UI(模型选择器 UI)
|
|
2869
|
-
|
|
2870
|
-
**扫描时间**: 2026-06-12
|
|
2871
|
-
**扫描模块**: `modes/interactive/components/model-selector.ts`(430 行), `modes/interactive/controllers/model-overlay-controller.ts`(523 行), `modes/interactive/components/provider-selector.ts`, `modes/interactive/components/scoped-models-selector.ts`, `core/model-registry.ts`(1044 行), `core/model-resolver.ts`
|
|
2872
|
-
**对比**: CC `src/components/ModelPicker.tsx`(448 行), `src/components/agents/ModelSelector.tsx`(67 行), `src/components/CustomSelect/select.tsx`, `src/utils/model/modelOptions.ts`(541 行), `src/utils/model/model.ts`(625 行)
|
|
2873
|
-
|
|
2874
|
-
### 1. 架构对比
|
|
2875
|
-
|
|
2876
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2877
|
-
|------|-----------|-------------|
|
|
2878
|
-
| UI 框架 | 自定义命令式 TUI(`@pencil-agent/tui`)类继承 | React Ink 函数组件 |
|
|
2879
|
-
| 组件结构 | `ModelSelectorComponent`(430 行)+ `ModelOverlayController`(523 行)+ 6 个端口接口 | `ModelPicker`(448 行)+ `Select` 原语 |
|
|
2880
|
-
| 搜索过滤 | `fuzzyFilter` 模糊匹配(id + provider) | 无搜索(固定列表) |
|
|
2881
|
-
| Provider 选择 | 二级选择器(先 provider 后 model) | 扁平列表 |
|
|
2882
|
-
| 远程发现 | Ctrl+R 触发 `refreshWithDiscovery` | 无(静态配置) |
|
|
2883
|
-
| OpenRouter 添加 | Ctrl+N 交互式添加模型 ID | 无 |
|
|
2884
|
-
| Scoped 模型 | 专用 `ScopedModelsSelectorComponent`(toggle/reorder/persist) | 无 |
|
|
2885
|
-
| API key 提示 | `[needs API key]` 每模型显示 | 无 |
|
|
2886
|
-
| 远程模型标记 | `(remote)` 徽章 | 无 |
|
|
2887
|
-
| Thinking 级别 | 选择器内显示循环状态 | 独立 effort cycling(左右箭头) |
|
|
2888
|
-
| Tier 感知 | 无(扁平列表) | 按用户 tier 显示不同选项(Max/Pro/PAYG/3P) |
|
|
2889
|
-
| 定价显示 | 无 | `$3.75/M tokens` 描述 |
|
|
2890
|
-
| 升级提示 | 无 | "Newer version available" |
|
|
2891
|
-
| 模型验证 | 无(信任 registry) | `validateModel()` 检查存在性 |
|
|
2892
|
-
| 分析日志 | 无 | 记录 from/to 模型变更 |
|
|
2893
|
-
| Fast mode | 无 | 集成切换+通知 |
|
|
2894
|
-
|
|
2895
|
-
### 2. 正确性缺陷
|
|
2896
|
-
|
|
2897
|
-
**Defect 1 — 构造函数异步加载竞态(LOW)**
|
|
2898
|
-
`model-selector.ts` L151:`loadModels().then(...)` 在构造函数中异步调用。如果 `handleInput` 在 promise 解析前触发,`filteredModels` 为空,Enter 键无响应(有 `if (selectedModel)` 守卫,安全但用户困惑)。
|
|
2899
|
-
|
|
2900
|
-
**Defect 2 — `selectedIndex` 空列表 clamp(LOW)**
|
|
2901
|
-
L207-210:空列表时 `Math.max(0, -1)` 返回 0,`selectedIndex` 为无效索引。无害(不会访问元素)但代码异味。
|
|
2902
|
-
|
|
2903
|
-
**Defect 3 — 搜索无 debounce(LOW)**
|
|
2904
|
-
L383-384:每次按键调用 `filterModels`。大模型列表(数百 OpenRouter 模型)可能卡顿。
|
|
2905
|
-
|
|
2906
|
-
**Defect 4 — `writeFileSync` 阻塞(LOW)**
|
|
2907
|
-
`model-registry.ts` L1013:`appendOpenRouterModel` 同步写盘,可能阻塞事件循环。
|
|
2908
|
-
|
|
2909
|
-
### 3. 高可用差距
|
|
2910
|
-
|
|
2911
|
-
| 差距 | 影响 | 严重度 |
|
|
2912
|
-
|------|------|--------|
|
|
2913
|
-
| 模型 registry 加载失败无降级 | 选择器显示空列表+错误,无重试 | **LOW** |
|
|
2914
|
-
| 远程发现刷新无超时 | 慢网络时 "Refreshing..." 永久显示 | **LOW** |
|
|
2915
|
-
| 初始加载无 loading 指示器 | 异步加载期间显示空列表 | **LOW** |
|
|
2916
|
-
| Provider 失败无熔断器 | 持续失败的 provider 无退避机制 | **LOW** |
|
|
2917
|
-
|
|
2918
|
-
### 4. nanoPencil 独有优势(CC 无此功能)
|
|
2919
|
-
|
|
2920
|
-
- **模糊搜索**:CC 模型选择器完全无搜索能力
|
|
2921
|
-
- **二级 provider 选择**:先选 provider 再选 model
|
|
2922
|
-
- **远程模型发现**:Ctrl+R 从远程 registry 刷新
|
|
2923
|
-
- **OpenRouter 交互式添加**:Ctrl+N 输入模型 ID
|
|
2924
|
-
- **Scoped 模型管理**:toggle + reorder + persist
|
|
2925
|
-
- **API key 提示**:每模型显示认证状态
|
|
2926
|
-
- **端口接口 DI**:6 个端口接口,依赖注入清晰
|
|
2927
|
-
|
|
2928
|
-
### 5. CC 独有优势(nanoPencil 无此功能)
|
|
2929
|
-
|
|
2930
|
-
- **Tier 感知**:按订阅层级显示不同选项
|
|
2931
|
-
- **定价显示**:每模型显示价格
|
|
2932
|
-
- **Effort cycling**:左右箭头切换 thinking 级别
|
|
2933
|
-
- **Fast mode 集成**:模型切换自动 toggle fast mode
|
|
2934
|
-
- **模型验证**:设置前检查存在性
|
|
2935
|
-
- **分析日志**:记录模型变更
|
|
2936
|
-
|
|
2937
|
-
### 汇总
|
|
2938
|
-
|
|
2939
|
-
| 严重度 | 数量 |
|
|
2940
|
-
|--------|------|
|
|
2941
|
-
| HIGH | 0 |
|
|
2942
|
-
| MEDIUM | 0 |
|
|
2943
|
-
| LOW | 4(异步竞态、空列表 clamp、无 debounce、同步 I/O) |
|
|
2944
|
-
|
|
2945
|
-
**评估**:nanoPencil 的模型选择器在交互能力上显著优于 CC(模糊搜索、provider 分层、远程发现、scoped 管理)。CC 在业务逻辑上更成熟(tier 感知、定价、验证)。两者互补而非直接竞争。这是本轮扫描中 nanoPencil 表现最好的模块。
|
|
2946
|
-
|
|
2947
|
-
**优先修复项:**
|
|
2948
|
-
1. **LOW**: 添加搜索 debounce(50ms)
|
|
2949
|
-
2. **LOW**: 添加初始加载 loading 指示器
|
|
2950
|
-
3. **LOW**: 添加远程发现超时(30s)
|
|
2951
|
-
4. **LOW**: `appendOpenRouterModel` 改为异步写入
|
|
2952
|
-
|
|
2953
|
-
---
|
|
2954
|
-
|
|
2955
|
-
**已完成 33 轮扫描。** 模型选择器 UI 已覆盖。
|
|
2956
|
-
|
|
2957
|
-
---
|
|
2958
|
-
|
|
2959
|
-
## Round 34 — History/Transcript System(历史/转录系统)
|
|
2960
|
-
|
|
2961
|
-
**扫描时间**: 2026-06-12
|
|
2962
|
-
**扫描模块**: `core/session/session-manager.ts`(~1493 行), `core/messages.ts`, `core/runtime/agent-session.ts`(~2515 行), `core/runtime/session-lifecycle-controller.ts`, `core/runtime/session-tree-controller.ts`
|
|
2963
|
-
**对比**: CC `src/utils/sessionStorage.ts`(~4600 行), `src/utils/sessionStoragePortable.ts`, `src/utils/sessionRestore.ts`, `src/history.ts`, `src/utils/transcriptSearch.ts`, `src/types/logs.ts`
|
|
2964
|
-
|
|
2965
|
-
### 1. 架构对比
|
|
2966
|
-
|
|
2967
|
-
| 维度 | nanoPencil | Claude Code |
|
|
2968
|
-
|------|-----------|-------------|
|
|
2969
|
-
| 数据结构 | **树 + 叶指针**(id/parentId/leafId) | **线性链表**(uuid/parentUuid) |
|
|
2970
|
-
| 文件格式 | JSONL | JSONL |
|
|
2971
|
-
| 分支支持 | 原生(叶指针移动) | Fork 创建新 session 文件 |
|
|
2972
|
-
| 分支摘要 | 原生 `BranchSummaryEntry` | 非原生(基于 fork) |
|
|
2973
|
-
| 条目类型 | 8 种类型化变体 | 20+ 条目类型 |
|
|
2974
|
-
| Session 版本化 | v1/v2/v3 迁移 | 无显式版本化 |
|
|
2975
|
-
| 压缩边界 | LLM 摘要条目 | `compact_boundary` 系统消息 |
|
|
2976
|
-
| 大文件优化 | 全文件读取+解析 | fd 级跳过 + 分块读取 + 边界截断 |
|
|
2977
|
-
| 转录搜索 | 无 | WeakMap 缓存按类型文本提取 |
|
|
2978
|
-
| Prompt 历史 | 无 | `history.jsonl` + paste 引用 |
|
|
2979
|
-
| Sidechain 转录 | 无(代码中 TODO) | 每 agent 独立 JSONL |
|
|
2980
|
-
| 文件锁定 | 无 | lockfile-based |
|
|
2981
|
-
| 并发 session | 无 | `concurrentSessions.ts` |
|
|
2982
|
-
| 内容替换追踪 | 无 | `ContentReplacementEntry` |
|
|
2983
|
-
| 上下文折叠 | 无 | marble-origami entries |
|
|
2984
|
-
| 导出 | HTML | /share + asciicast |
|
|
2985
|
-
|
|
2986
|
-
### 2. 正确性缺陷
|
|
2987
|
-
|
|
2988
|
-
**Defect 1 — JSONL 解析静默跳过损坏行(LOW)**
|
|
2989
|
-
`loadEntriesFromFile`/`parseSessionEntries`:catch 块静默跳过格式错误行。崩溃时半写行被丢弃,无完整性验证检查树结构。
|
|
2990
|
-
|
|
2991
|
-
**Defect 2 — `leafId` 假设文件顺序即树遍历顺序(LOW)**
|
|
2992
|
-
`_buildIndex()` L788-804:`leafId` 设为文件最后条目。假设 append-only 不变式成立。手动编辑或损坏文件会产生错误叶指针。
|
|
2993
|
-
|
|
2994
|
-
**Defect 3 — `getChildren()` 线性扫描全部条目(LOW)**
|
|
2995
|
-
每次调用遍历整个 `byId` map,O(n) 复杂度。大 session 性能差。
|
|
2996
|
-
|
|
2997
|
-
**Defect 4 — `convertToLlm()` 可能静默丢弃新消息类型(MEDIUM)**
|
|
2998
|
-
`default` 分支返回 `undefined` 被过滤。通过 declaration merging 扩展的 `CustomAgentMessages` 新类型可能被静默丢弃。
|
|
2999
|
-
|
|
3000
|
-
### 3. 高可用差距
|
|
3001
|
-
|
|
3002
|
-
| 差距 | 影响 | 严重度 |
|
|
3003
|
-
|------|------|--------|
|
|
3004
|
-
| 无文件写入锁定 | 多进程写同一文件可能交错损坏 | **MEDIUM** |
|
|
3005
|
-
| `_rewriteFile()` 非原子写入 | 崩溃时截断丢失全部条目 | **MEDIUM** |
|
|
3006
|
-
| 无飞行中条目崩溃恢复 | 崩溃在内存追加和磁盘持久化之间丢失条目 | **LOW** |
|
|
3007
|
-
| 无 session 文件完整性验证 | 打开时不验证树结构有效性 | **LOW** |
|
|
3008
|
-
|
|
3009
|
-
### 4. CC 功能差距
|
|
3010
|
-
|
|
3011
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
3012
|
-
|---------|----------------|--------|
|
|
3013
|
-
| 转录搜索(Ctrl+R) | 无 | **HIGH** |
|
|
3014
|
-
| Sidechain 转录记录 | 无(TODO) | **HIGH** |
|
|
3015
|
-
| Prompt 历史(Up-arrow 跨 session) | 无 | **MEDIUM** |
|
|
3016
|
-
| 大 session compact-boundary 优化 | 全文件读取 | **MEDIUM** |
|
|
3017
|
-
| 文件锁定 | 无 | **MEDIUM** |
|
|
3018
|
-
| 并发 session 冲突解决 | 无 | **LOW** |
|
|
3019
|
-
| 内容替换追踪 | 无 | **LOW** |
|
|
3020
|
-
| Session 元数据(title/tag/agent color/PR link) | 仅 `SessionInfoEntry` | **LOW** |
|
|
3021
|
-
| 上下文折叠(marble-origami) | 无 | **LOW** |
|
|
3022
|
-
| Worktree 状态持久化 | 无 | **LOW** |
|
|
3023
|
-
|
|
3024
|
-
### 5. nanoPencil 独有优势
|
|
3025
|
-
|
|
3026
|
-
- **树模型架构优越**:叶指针方式自然支持树导航,无需创建新 session 文件
|
|
3027
|
-
- **原生分支摘要**:`BranchSummaryEntry` 弃用分支自动摘要
|
|
3028
|
-
- **Session 版本化迁移**:v1→v2→v3 显式迁移路径
|
|
3029
|
-
- **8 种类型化条目**:discriminated union 比 CC 的 20+ 更聚焦
|
|
3030
|
-
|
|
3031
|
-
### 汇总
|
|
3032
|
-
|
|
3033
|
-
| 严重度 | 数量 |
|
|
3034
|
-
|--------|------|
|
|
3035
|
-
| HIGH | 2(无转录搜索、无 sidechain 转录) |
|
|
3036
|
-
| MEDIUM | 4(无 prompt 历史、无大文件优化、无文件锁定、convertToLlm 丢弃风险) |
|
|
3037
|
-
| LOW | 6(JSONL 解析、leafId 假设、getChildren O(n)、完整性验证、并发、崩溃恢复) |
|
|
3038
|
-
|
|
3039
|
-
**优先修复项:**
|
|
3040
|
-
1. **HIGH**: 实现转录搜索(WeakMap 缓存 + 按类型文本提取)
|
|
3041
|
-
2. **HIGH**: 实现 sidechain 转录记录(子代理独立 JSONL)
|
|
3042
|
-
3. **MEDIUM**: 添加 prompt 历史文件(`~/.nanopencil/history.jsonl`)
|
|
3043
|
-
4. **MEDIUM**: 添加大 session compact-boundary 优化(fd 级跳过)
|
|
3044
|
-
5. **MEDIUM**: 添加文件锁定(lockfile)
|
|
3045
|
-
|
|
3046
|
-
---
|
|
3047
|
-
|
|
3048
|
-
**已完成 34 轮扫描。** 历史/转录系统已覆盖。
|
|
3049
|
-
|
|
3050
|
-
---
|
|
3051
|
-
|
|
3052
|
-
## Round 35 — File Watching System(文件监听系统)
|
|
3053
|
-
|
|
3054
|
-
**扫描时间**: 2026-06-12
|
|
3055
|
-
**扫描模块**: `modes/interactive/theme/theme.ts`(theme watcher), `modes/interactive/footer-data-provider.ts`(git watcher), `extensions/builtin/loop/cron/cron-scheduler.ts`(cron watcher)
|
|
3056
|
-
**对比**: CC 10 个独立 watcher(settings/skill/FileChanged/teamMemory/task/git/config/keybinding/cron/cleanupRegistry)
|
|
3057
|
-
|
|
3058
|
-
### 1. 架构对比
|
|
3059
|
-
|
|
3060
|
-
| 维度 | nanoPencil | Claude Code |
|
|
3061
|
-
|------|-----------|-------------|
|
|
3062
|
-
| Watcher 数量 | 4 个 | 10 个独立 watcher |
|
|
3063
|
-
| Settings 热重载 | 无 | chokidar + 删除宽限 + 内部写入抑制 + MDM 轮询 |
|
|
3064
|
-
| Skill 热重载 | 无 | chokidar + Bun 轮询降级 + debounce |
|
|
3065
|
-
| FileChanged hooks | 无 | chokidar + 动态路径更新 |
|
|
3066
|
-
| Task 列表 watcher | 无 | fs.watch + debounce + claim 逻辑 |
|
|
3067
|
-
| Git 缓存层 | 仅基础目录 watch | fs.watchFile + 缓存失效 + 分支追踪 |
|
|
3068
|
-
| 清理注册表 | 无 | 集中 `registerCleanup()` |
|
|
3069
|
-
| 内部写入抑制 | 无 | `markInternalWrite`/`consumeInternalWrite` |
|
|
3070
|
-
| 团队记忆同步 | 无 | fs.watch({recursive}) + debounce |
|
|
3071
|
-
| Keybinding 热重载 | 无 | chokidar |
|
|
3072
|
-
| Cron scheduler | **对齐**(1:1 移植) | chokidar |
|
|
3073
|
-
|
|
3074
|
-
### 2. 正确性缺陷
|
|
3075
|
-
|
|
3076
|
-
**Defect 1 — Theme watcher debounce 创建孤儿计时器(LOW)**
|
|
3077
|
-
`theme.ts` L727-757:`fs.watch` 回调中 `setTimeout` 每次事件创建新计时器但不取消前一个。快速保存可能触发两次重载。
|
|
3078
|
-
|
|
3079
|
-
**Defect 2 — Theme watcher 未注册清理(MEDIUM)**
|
|
3080
|
-
`theme.ts` L764-769:`stopThemeWatcher()` 仅在 theme 切换时显式调用。进程终止时 `fs.watch` 文件描述符泄漏。
|
|
3081
|
-
|
|
3082
|
-
**Defect 3 — Git watcher 错误后静默死亡不恢复(LOW)**
|
|
3083
|
-
`footer-data-provider.ts` L142-147:`fs.watch` 错误后关闭 watcher 设为 null,不重启。分支显示过期直到下次手动操作。
|
|
3084
|
-
|
|
3085
|
-
**Defect 4 — FooterDataProvider 无 dispose 方法(MEDIUM)**
|
|
3086
|
-
`footer-data-provider.ts`:CWD 变更丢弃实例时 `fs.watch` handle 永不关闭。
|
|
3087
|
-
|
|
3088
|
-
### 3. 高可用差距
|
|
3089
|
-
|
|
3090
|
-
| 差距 | 影响 | 严重度 |
|
|
3091
|
-
|------|------|--------|
|
|
3092
|
-
| 无 settings 热重载 | 外部编辑 settings.json 直到重启才生效 | **HIGH** |
|
|
3093
|
-
| 无 skill/command 热重载 | git pull 添加的 skill 直到重启才被发现 | **HIGH** |
|
|
3094
|
-
| 无 .env/.envrc 变更检测 | 环境变量文件变更不刷新 | **MEDIUM** |
|
|
3095
|
-
| 无跨进程 task 发现 | 子代理创建的 task 不自动显示 | **MEDIUM** |
|
|
3096
|
-
| 无优雅关闭 | SIGTERM 时不关闭 watch handle(Linux inotify 泄漏) | **MEDIUM** |
|
|
3097
|
-
|
|
3098
|
-
### 4. CC 功能差距
|
|
3099
|
-
|
|
3100
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
3101
|
-
|---------|----------------|--------|
|
|
3102
|
-
| Settings 热重载(chokidar + 删除宽限 + 写入抑制) | 无 | **HIGH** |
|
|
3103
|
-
| Skill 热重载(chokidar + debounce) | 无 | **HIGH** |
|
|
3104
|
-
| FileChanged hooks(.envrc/.env) | 无 | **MEDIUM** |
|
|
3105
|
-
| Task 列表 watcher | 无 | **MEDIUM** |
|
|
3106
|
-
| 清理注册表(集中 registerCleanup) | 无 | **MEDIUM** |
|
|
3107
|
-
| 团队记忆同步 | 无 | **MEDIUM** |
|
|
3108
|
-
| Git 缓存层(HEAD/config/branch ref 缓存) | 仅基础目录 watch | **MEDIUM** |
|
|
3109
|
-
| Keybinding 热重载 | 无 | **LOW** |
|
|
3110
|
-
| 内部写入抑制 | 无 | **LOW** |
|
|
3111
|
-
| 全局配置新鲜度检测 | 无 | **LOW** |
|
|
3112
|
-
| Test override hooks | 无 | **LOW** |
|
|
3113
|
-
| Cron scheduler | **对齐** | OK |
|
|
3114
|
-
|
|
3115
|
-
### 5. nanoPencil 独有优势
|
|
3116
|
-
|
|
3117
|
-
- 无(CC 在此领域全面领先)
|
|
3118
|
-
|
|
3119
|
-
### 汇总
|
|
3120
|
-
|
|
3121
|
-
| 严重度 | 数量 |
|
|
3122
|
-
|--------|------|
|
|
3123
|
-
| HIGH | 2(无 settings 热重载、无 skill 热重载) |
|
|
3124
|
-
| MEDIUM | 5(无 FileChanged hooks、无 task watcher、无清理注册表、无团队记忆、无 git 缓存) |
|
|
3125
|
-
| LOW | 7(theme debounce、theme 清理、git 错误恢复、dispose、内部写入、配置新鲜度、keybinding) |
|
|
3126
|
-
|
|
3127
|
-
**优先修复项:**
|
|
3128
|
-
1. **MEDIUM**: 创建集中清理注册表(`registerCleanup()`)— 解锁所有未来 watcher 的安全关闭
|
|
3129
|
-
2. **HIGH**: 实现 settings 变更检测器(chokidar 或 polling)
|
|
3130
|
-
3. **HIGH**: 实现 skill/command 变更检测器
|
|
3131
|
-
4. **MEDIUM**: 修复 theme watcher 和 git watcher 清理注册
|
|
3132
|
-
5. **MEDIUM**: 实现 FileChanged hook watcher(.envrc/.env)
|
|
3133
|
-
|
|
3134
|
-
---
|
|
3135
|
-
|
|
3136
|
-
**已完成 35 轮扫描。** 文件监听系统已覆盖。
|
|
3137
|
-
|
|
3138
|
-
---
|
|
3139
|
-
|
|
3140
|
-
# 全部 40 轮扫描完成 — 总结
|
|
3141
|
-
|
|
3142
|
-
## 累计发现
|
|
3143
|
-
|
|
3144
|
-
| 严重度 | 数量 |
|
|
3145
|
-
|--------|------|
|
|
3146
|
-
| CRITICAL | 20 |
|
|
3147
|
-
| HIGH | 107+ |
|
|
3148
|
-
| MEDIUM | 178+ |
|
|
3149
|
-
| LOW | 116+ |
|
|
3150
|
-
|
|
3151
|
-
## 跨模块 Top 5 优先修复项
|
|
3152
|
-
|
|
3153
|
-
1. **CRITICAL — 安全**:集成 OS 级沙箱(Seatbelt/bwrap),当前 regex 沙箱可被绕过
|
|
3154
|
-
2. **CRITICAL — 上下文管理**:实现 microcompact + session memory 压缩(当前全量 LLM 摘要是唯一路径)
|
|
3155
|
-
3. **CRITICAL — 数据完整性**:修复 Diff/Patch fuzzy matching 静默规范化(破坏 Markdown 硬换行)
|
|
3156
|
-
4. **CRITICAL — LLM 通信**:修复流重试丢弃部分事件(消费者看到流中途停止)
|
|
3157
|
-
5. **HIGH — 配置**:添加配置备份 + schema 验证 + 文件变更监听
|
|
3158
|
-
|
|
3159
|
-
## nanoPencil 独有优势
|
|
3160
|
-
|
|
3161
|
-
- 终端内联图片渲染(Kitty/iTerm2)
|
|
3162
|
-
- 30+ 类型化扩展事件系统
|
|
3163
|
-
- 5 层认知记忆模型 + Ebbinghaus 间隔重复
|
|
3164
|
-
- 11 provider 图片测试覆盖
|
|
3165
|
-
- Buddy 宠物系统
|
|
3166
|
-
- 两阶段扩展 flag 解析
|
|
3167
|
-
- 扩展 API 比 CC markdown 命令更强大
|
|
3168
|
-
- 树分支摘要 + 迭代摘要更新(CC 线性历史每次全新生成)
|
|
3169
|
-
- 15+ provider 溢出检测(CC 主要 Anthropic)
|
|
3170
|
-
- 文件操作追踪跨压缩保留
|
|
3171
|
-
- 树模型 session 架构(叶指针自然支持分支导航)
|
|
3172
|
-
- 原生分支摘要 + Session 版本化迁移
|
|
3173
|
-
|
|
3174
|
-
---
|
|
3175
|
-
|
|
3176
|
-
## Round 36 — Auth Storage & Provider Registration(认证存储与 Provider 注册)
|
|
3177
|
-
|
|
3178
|
-
**扫描时间**: 2026-06-12
|
|
3179
|
-
**扫描模块**: `core/platform/config/auth-storage.ts`, OAuth providers, model registry
|
|
3180
|
-
**对比**: CC macOS Keychain + OAuth service + MCP OAuth
|
|
3181
|
-
|
|
3182
|
-
### 1. 架构对比
|
|
3183
|
-
|
|
3184
|
-
| 维度 | nanoPencil | Claude Code |
|
|
3185
|
-
|------|-----------|-------------|
|
|
3186
|
-
| 凭据存储 | JSON 文件 + `proper-lockfile` | macOS Keychain (`security` CLI) + OAuth service |
|
|
3187
|
-
| 存储加密 | 无(明文 JSON) | OS 级加密(Keychain) |
|
|
3188
|
-
| OAuth Provider 数量 | 6 个(Anthropic/OpenAI/Google/GitHub/Microsoft/xAI) | 1 个(Anthropic) |
|
|
3189
|
-
| 环境变量映射 | 20+ 个 | 少量 |
|
|
3190
|
-
| MCP OAuth | 无 | 支持任意 MCP server OAuth |
|
|
3191
|
-
| 跨进程协调 | `proper-lockfile` | OS keychain 天然原子 |
|
|
3192
|
-
| Token 刷新 | 手动(provider 内部) | OAuth service 统一管理 |
|
|
3193
|
-
| 401 恢复 | 无 | 自动 token 刷新 + 重试 |
|
|
3194
|
-
| Provider 扩展 | 注册表模式(可插拔) | 硬编码 |
|
|
3195
|
-
| 远程模型发现 | 支持(Ctrl+R) | 无 |
|
|
3196
|
-
|
|
3197
|
-
### 2. 正确性缺陷
|
|
3198
|
-
|
|
3199
|
-
**Defect 1 — 明文存储 API keys(HIGH)**
|
|
3200
|
-
`auth-storage.ts`:所有 OAuth token 和 API key 以明文 JSON 写入 `~/.nanopencil/auth.json`。任何有文件读权限的进程/用户可获取全部凭据。
|
|
3201
|
-
|
|
3202
|
-
**Defect 2 — 无 OS keychain 集成(HIGH)**
|
|
3203
|
-
macOS Keychain / Linux Secret Service / Windows Credential Manager 均未使用。CC 在 macOS 上通过 `security` CLI 存取,Linux 上通过 `secret-service` D-Bus API。
|
|
3204
|
-
|
|
3205
|
-
### 3. 高可用差距
|
|
3206
|
-
|
|
3207
|
-
| 差距 | 影响 | 严重度 |
|
|
3208
|
-
|------|------|--------|
|
|
3209
|
-
| 明文凭据存储 | 文件系统访问即可泄露全部 API keys | **HIGH** |
|
|
3210
|
-
| 无 OS keychain 集成 | 无法利用平台安全基础设施 | **HIGH** |
|
|
3211
|
-
| 无跨进程 token 刷新协调 | 多实例同时刷新可能产生竞态 | **MEDIUM** |
|
|
3212
|
-
| 无 MCP OAuth 支持 | 无法认证任意 MCP server | **MEDIUM** |
|
|
3213
|
-
| 无 401 自动恢复 | token 过期后需用户手动干预 | **MEDIUM** |
|
|
3214
|
-
| Linux 无安全存储降级 | Linux 上明文存储无替代方案 | **MEDIUM** |
|
|
3215
|
-
| AWS/GCP token 刷新 | 长期 token 无自动续期 | **LOW** |
|
|
3216
|
-
| 无 apiKeyHelper 外部工具 | 无法集成企业密钥管理 | **LOW** |
|
|
3217
|
-
| 无订阅管理 | 无法显示/管理订阅状态 | **LOW** |
|
|
3218
|
-
| 无凭据审批流 | 新凭据无用户确认步骤 | **LOW** |
|
|
3219
|
-
| 无 managed context 隔离 | 托管环境无独立存储区域 | **LOW** |
|
|
3220
|
-
|
|
3221
|
-
### 4. nanoPencil 独有优势
|
|
3222
|
-
|
|
3223
|
-
- **6 个 OAuth Provider**:CC 仅 Anthropic 一个
|
|
3224
|
-
- **20+ 环境变量映射**:覆盖主流 provider 的各种 key 变体
|
|
3225
|
-
- **可插拔 Provider 注册表**:扩展可注册新 provider
|
|
3226
|
-
- **远程模型发现**:Ctrl+R 从远程 registry 刷新可用模型
|
|
3227
|
-
- **OpenRouter 交互式添加**:Ctrl+N 输入模型 ID
|
|
3228
|
-
- **Scoped 模型管理**:按项目/角色绑定模型
|
|
3229
|
-
|
|
3230
|
-
### 5. CC 独有优势
|
|
3231
|
-
|
|
3232
|
-
- **OS Keychain 集成**:凭据受操作系统保护
|
|
3233
|
-
- **MCP OAuth**:任意 MCP server 可配置 OAuth
|
|
3234
|
-
- **统一 OAuth Service**:token 刷新/401 恢复集中管理
|
|
3235
|
-
- **apiKeyHelper**:企业密钥管理集成
|
|
3236
|
-
|
|
3237
|
-
### 汇总
|
|
3238
|
-
|
|
3239
|
-
| 严重度 | 数量 |
|
|
3240
|
-
|--------|------|
|
|
3241
|
-
| HIGH | 2(明文存储、无 OS keychain) |
|
|
3242
|
-
| MEDIUM | 4(跨进程刷新、MCP OAuth、401 恢复、Linux 安全存储) |
|
|
3243
|
-
| LOW | 5(AWS/GCP 刷新、apiKeyHelper、订阅管理、凭据审批、managed context) |
|
|
3244
|
-
|
|
3245
|
-
**优先修复项:**
|
|
3246
|
-
1. **HIGH**: 集成 OS keychain(macOS Keychain / Linux Secret Service / Windows Credential Manager)
|
|
3247
|
-
2. **HIGH**: 实现凭据加密存储(至少 AES-256 加密本地文件)
|
|
3248
|
-
3. **MEDIUM**: 添加 401 自动 token 刷新 + 重试
|
|
3249
|
-
4. **MEDIUM**: 实现 MCP OAuth 支持
|
|
3250
|
-
|
|
3251
|
-
---
|
|
3252
|
-
|
|
3253
|
-
**已完成 36 轮扫描。** 认证存储与 Provider 注册已覆盖。
|
|
3254
|
-
|
|
3255
|
-
---
|
|
3256
|
-
|
|
3257
|
-
## Round 37 — Telemetry/Analytics System(遥测/分析系统)
|
|
3258
|
-
|
|
3259
|
-
**扫描时间**: 2026-06-12
|
|
3260
|
-
**扫描模块**: `core/platform/telemetry/batching-dispatcher.ts`, `core/platform/telemetry/insforge-base.ts`, `core/platform/telemetry/ext-events.ts`, `core/sub-agent/agent-telemetry.ts`, `extensions/builtin/token-save/tracking.ts`
|
|
3261
|
-
**对比**: CC OpenTelemetry SDK (metrics/logs/traces), `FirstPartyEventLoggingExporter`, GrowthBook sampling, Perfetto traces, BigQuery metrics, Datadog dashboards
|
|
3262
|
-
|
|
3263
|
-
### 1. 架构对比
|
|
3264
|
-
|
|
3265
|
-
| 维度 | nanoPencil | Claude Code |
|
|
3266
|
-
|------|-----------|-------------|
|
|
3267
|
-
| 核心框架 | 自定义 `BatchingDispatcher<T>` + `InsforgeHttpClient` (PostgREST) | 完整 OpenTelemetry SDK(metrics/logs/traces) |
|
|
3268
|
-
| 传输层 | PostgREST HTTP(单一后端) | 多通道:OTLP (gRPC/HTTP), Prometheus, Datadog HTTP, 1P `/api/event_logging/batch`, BigQuery |
|
|
3269
|
-
| 事件类型 | 3 个类型化表:`ext_command_events`, `ext_llm_calls`, `ext_hook_events` + SAL eval 表 | 数十个命名事件 + OTel metrics (counters/histograms) + OTel spans + Perfetto trace events + BigQuery |
|
|
3270
|
-
| 分布式追踪 | 无(无 OpenTelemetry,无 span 层级) | 完整 span 层级:interaction > LLM request > tool > hook |
|
|
3271
|
-
| 采样策略 | `HOOK_SAMPLE_RATES` 静态常量(tool_* 10%, 其他 100%) | GrowthBook 动态 `tengu_event_sampling_config` 每事件名 |
|
|
3272
|
-
| 批处理 | `BatchingDispatcher<T>` 2s debounce,串行 drain | OTel `BatchLogRecordProcessor` + `PeriodicExportingMetricReader` + 磁盘重试 |
|
|
3273
|
-
| 重试/韧性 | Fire-and-forget;失败仅发诊断事件 | 二次退避重试 + 磁盘持久化失败事件 + 启动时跨 run 重试 |
|
|
3274
|
-
| 隐私控制 | 凭据文件 `enabled: false` | 3 级:`default`/`no-telemetry`/`essential-traffic` + 组织级 opt-out + 每 sink killswitch |
|
|
3275
|
-
| Opt-out | 删除凭据文件 | `DISABLE_TELEMETRY=1`, `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`, 组织 API |
|
|
3276
|
-
| PII 保护 | `classifyArgsSignature()` 永不记录原始参数 | `AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS` 编译时标记 + `_PROTO_*` 列访问控制 |
|
|
3277
|
-
| 错误报告 | `TelemetryDiagnostic` 源/严重度/类别/指纹 | `logError()` + OTel span `recordException` + Perfetto error flags |
|
|
3278
|
-
| 可视化 | PostgREST 查询 + smoke test 脚本 | OTel OTLP traces + Perfetto + BigQuery + Datadog |
|
|
3279
|
-
| 后端 killswitch | 无 | GrowthBook 每 sink killswitch |
|
|
3280
|
-
| Feature gating | 无 | Statsig feature gates |
|
|
3281
|
-
|
|
3282
|
-
### 2. 正确性缺陷
|
|
3283
|
-
|
|
3284
|
-
**Defect 1 — 无重试的 flush 失败导致事件永久丢失(HIGH)**
|
|
3285
|
-
`batching-dispatcher.ts` L80-96:HTTP POST 失败时事件被 splice 丢弃,仅发诊断事件。CC 的 `FirstPartyEventLoggingExporter` 有磁盘持久化 + 二次退避重试。
|
|
3286
|
-
|
|
3287
|
-
**Defect 2 — Promise 永不 reject(HIGH)**
|
|
3288
|
-
`insforge-base.ts` L92-168:网络/超时时 `resolve({ok: false})`,调用方无法区分"发送失败"和"从未发送"。CC 使用 `resultCallback` 模式显式 FAILED 状态。
|
|
3289
|
-
|
|
3290
|
-
**Defect 3 — EventBus 注入丢失时遥测静默消失(MEDIUM)**
|
|
3291
|
-
`agent-telemetry.ts` L124-129:`_emitToEventBus` 空 catch 吞掉所有错误。如果 EventBus 从未注入,全部 agent 遥测丢失无任何指示。
|
|
3292
|
-
|
|
3293
|
-
**Defect 4 — 每次调用创建新 HttpClient/Dispatcher(MEDIUM)**
|
|
3294
|
-
`ext-events.ts` L125-145:`createExtensionTelemetrySink` 每次创建新实例,无连接池。CC 共享 MeterProvider/LoggerProvider/TracerProvider 单例。
|
|
3295
|
-
|
|
3296
|
-
**Defect 5 — persist 错误静默吞掉(LOW)**
|
|
3297
|
-
`token-save/tracking.ts` L39,88-96:`void this.persist(record)` 错误被忽略,目录不可写时历史静默不完整。
|
|
3298
|
-
|
|
3299
|
-
### 3. 高可用差距
|
|
3300
|
-
|
|
3301
|
-
| 差距 | 影响 | 严重度 |
|
|
3302
|
-
|------|------|--------|
|
|
3303
|
-
| 无失败事件磁盘持久化 | HTTP POST 失败事件永久丢失 | **HIGH** |
|
|
3304
|
-
| 无跨 run 重试 | 进程退出时缓冲区事件丢失 | **HIGH** |
|
|
3305
|
-
| 无健康检查熔断器 | 端点宕机时每次 flush 阻塞 5s 超时 | **MEDIUM** |
|
|
3306
|
-
| 无优雅关闭保证 | 无 `process.on('beforeExit')` 清理注册 | **MEDIUM** |
|
|
3307
|
-
| 单一传输依赖 | insforge 不可达时全部遥测丢失 | **LOW** |
|
|
3308
|
-
|
|
3309
|
-
### 4. CC 功能差距
|
|
3310
|
-
|
|
3311
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
3312
|
-
|---------|----------------|--------|
|
|
3313
|
-
| 分布式追踪 / span 层级 | 无 | **HIGH** |
|
|
3314
|
-
| Metrics 系统(counters/histograms) | 无 | **HIGH** |
|
|
3315
|
-
| 3 级隐私 opt-out 框架 | 仅凭据 on/off | **HIGH** |
|
|
3316
|
-
| Perfetto 追踪可视化 | 无 | **MEDIUM** |
|
|
3317
|
-
| 丰富事件元数据(30+ 字段) | 最少元数据 | **MEDIUM** |
|
|
3318
|
-
| 动态采样(GrowthBook) | 静态常量 | **MEDIUM** |
|
|
3319
|
-
| 插件/扩展专用遥测 | 仅按名称追踪 | **MEDIUM** |
|
|
3320
|
-
| 用户分桶(基数控制) | 无 | **LOW** |
|
|
3321
|
-
| `_PROTO_*` PII 列分离 | 无 | **LOW** |
|
|
3322
|
-
| sink 注入前事件队列 | 无(丢失) | **LOW** |
|
|
3323
|
-
|
|
3324
|
-
### 5. nanoPencil 独有优势
|
|
3325
|
-
|
|
3326
|
-
- **扩展遥测是一等公民**:`ext_command_events` / `ext_llm_calls` / `ext_hook_events` 三表提供专用扩展可观测层
|
|
3327
|
-
- **空闲思考检测**:`isUserInitiated` 字段 + smoke test 探针检测 hook 静默调用 LLM
|
|
3328
|
-
- **SAL eval 遥测深度集成**:5 个 PostgREST 表 + 自动幂等 `ensureRunExists`
|
|
3329
|
-
- **`classifyArgsSignature()` 隐私保护**:永不记录原始参数文本,零 PII
|
|
3330
|
-
- **每行存储 `sampleRate`**:仪表板可通过 `count(*) * (1.0 / avg(sample_rate))` 外推真实计数
|
|
3331
|
-
- **`ExtCallerContext` AsyncLocalStorage**:轻量零依赖归因总线
|
|
3332
|
-
- **Smoke test 脚本**:自包含遥测健康检查
|
|
3333
|
-
- **Token 节省追踪**:本地分析每个命令的 token 节省量
|
|
3334
|
-
|
|
3335
|
-
### 汇总
|
|
3336
|
-
|
|
3337
|
-
| 严重度 | 数量 |
|
|
3338
|
-
|--------|------|
|
|
3339
|
-
| HIGH | 5(flush 失败丢事件、Promise 不 reject、无分布式追踪、无 metrics、无隐私框架) |
|
|
3340
|
-
| MEDIUM | 6(EventBus 丢失、无连接池、无熔断器、无优雅关闭、无 Perfetto、无动态采样) |
|
|
3341
|
-
| LOW | 5(persist 错误、单一传输、用户分桶、PII 列、sink 前队列) |
|
|
3342
|
-
|
|
3343
|
-
**优先修复项:**
|
|
3344
|
-
1. **HIGH**: 为 `BatchingDispatcher` 添加磁盘持久化失败事件 + 跨 run 重试
|
|
3345
|
-
2. **HIGH**: 添加 `process.on('beforeExit')` 清理钩子确保缓冲区 drain
|
|
3346
|
-
3. **HIGH**: 添加用户面向的 opt-out 环境变量(`NANOPENCIL_DISABLE_TELEMETRY=1`)
|
|
3347
|
-
4. **MEDIUM**: 为 `InsforgeHttpClient` 添加熔断器(N 次连续超时后暂停)
|
|
3348
|
-
5. **MEDIUM**: 添加基本事件计数器/metrics 层
|
|
3349
|
-
|
|
3350
|
-
---
|
|
3351
|
-
|
|
3352
|
-
**已完成 37 轮扫描。** 遥测/分析系统已覆盖。
|
|
3353
|
-
|
|
3354
|
-
---
|
|
3355
|
-
|
|
3356
|
-
## Round 38 — MCP (Model Context Protocol) 系统
|
|
3357
|
-
|
|
3358
|
-
**扫描时间**: 2026-06-12
|
|
3359
|
-
**扫描模块**: `core/mcp/mcp-client.ts`, `core/mcp/mcp-config.ts`, `core/mcp/mcp-guidance.ts`, `core/mcp/mcp-manager.ts`
|
|
3360
|
-
**对比**: CC `src/services/mcp/`(22+ 文件, 12000+ LOC), `@modelcontextprotocol/sdk`, `McpOAuthClientProvider`
|
|
3361
|
-
|
|
3362
|
-
### 1. 架构对比
|
|
3363
|
-
|
|
3364
|
-
| 维度 | nanoPencil | Claude Code |
|
|
3365
|
-
|------|-----------|-------------|
|
|
3366
|
-
| 代码规模 | ~6 文件, ~1200 LOC | ~22 文件, ~12000+ LOC |
|
|
3367
|
-
| 协议 SDK | 手写 JSON-RPC over stdio/HTTP | 官方 `@modelcontextprotocol/sdk` |
|
|
3368
|
-
| 传输类型 | `stdio`, `sse`(桩), `http` | `stdio`, `sse`, `http`, `ws`, `sse-ide`, `ws-ide`, `sdk`, `claudeai-proxy` |
|
|
3369
|
-
| 协议版本 | `2024-11-05`(主体)+ `2024-10-07`(回退) | `2025-03-26`(header)+ SDK 默认 |
|
|
3370
|
-
| Tool 发现 | `tools/list` + cursor 分页 | `tools/list` via SDK + LRU 缓存 |
|
|
3371
|
-
| Resource 访问 | **未实现** | `resources/list` + `resources/read` 工具 |
|
|
3372
|
-
| Prompt 模板 | **未实现** | `prompts/list` + `prompts/get` 映射为斜杠命令 |
|
|
3373
|
-
| OAuth/Auth | Figma 专用 OAuth(PKCE, DCR, refresh) | 通用 OAuth 2.0 + PKCE + DCR 任意 MCP server + XAA |
|
|
3374
|
-
| 安全存储 | `AuthStorage`(JSON 文件) | OS Keychain(macOS Keychain, 跨进程安全) |
|
|
3375
|
-
| 配置作用域 | 单一 `mcp.json` 文件 | 7 级:enterprise/user/local/project/dynamic/claudeai/managed |
|
|
3376
|
-
| 服务端生命周期 | `startServer()`/`stopServer()` | Memoized `connectToServer()` + `reconnectMcpServerImpl()` |
|
|
3377
|
-
| 重连机制 | **无** — server 挂了需重启 session | 自动:onerror 追踪 + 连续错误计数 + 缓存失效 + 透明重连 |
|
|
3378
|
-
| 权限模型 | 配置中 enable/disable | 企业 allowlist/denylist + 项目审批对话框 + plugin-only 策略 |
|
|
3379
|
-
| 错误处理 | 基础 try/catch | 结构化:`McpAuthError`/`McpToolCallError`/`McpSessionExpiredError` + session 过期检测 |
|
|
3380
|
-
| 工具结果处理 | 基础文本拼接 | Token 计数 + 截断 + 图片压缩 + 二进制 blob 持久化 + `_meta` 转发 |
|
|
3381
|
-
| Elicitation | **未实现** | 完整 `ElicitRequestSchema` handler |
|
|
3382
|
-
| Server instructions | **未实现** | 捕获并注入模型 system context |
|
|
3383
|
-
| 工具注解 (_meta) | **未实现** | `searchHint`/`alwaysLoad`/`tool.annotations.title` |
|
|
3384
|
-
| 批量连接 | 顺序 `for...of` | 并发 `pMap`(本地 3, 远程 20 并发限制) |
|
|
3385
|
-
| 动态 headers | 仅静态 `headers` 字段 | 静态 + `headersHelper` 脚本(每请求动态) |
|
|
3386
|
-
| 环境变量展开 | 仅 `{cwd}` 占位符 | 完整 `${VAR}` 展开(command/args/env/url/headers) |
|
|
3387
|
-
| WebSocket 传输 | **未实现** | 自定义 `WebSocketTransport` |
|
|
3388
|
-
| InProcess 传输 | **未实现** | `InProcessTransport` |
|
|
3389
|
-
| 输出存储 | **未实现** | `mcpOutputStorage` 大二进制输出 |
|
|
3390
|
-
| Server 审批 UI | 无 | `mcpServerApproval.tsx` 项目级审批 |
|
|
3391
|
-
|
|
3392
|
-
### 2. 正确性缺陷
|
|
3393
|
-
|
|
3394
|
-
**Defect 1 — SSE 传输未实现但静默返回成功(CRITICAL)**
|
|
3395
|
-
`mcp-client.ts:762-765`:`startServer()` 对 SSE 类型直接 `return true`,不连接不加载工具。`callSSETool()` L1037-1051 返回静态错误字符串。用户配置 SSE server 会误认为已连接,所有工具调用返回误导性错误。
|
|
3396
|
-
|
|
3397
|
-
**Defect 2 — 协议版本 header 与 body 不一致(HIGH)**
|
|
3398
|
-
`mcp-client.ts:483` 发送 `MCP-Protocol-Version: 2025-03-26` header,但 L510/664 的 `initialize` body 发送 `protocolVersion: "2024-11-05"`。严格检查两端的 server 会拒绝连接。
|
|
3399
|
-
|
|
3400
|
-
**Defect 3 — Stdio 无 Content-Length 帧(MEDIUM)**
|
|
3401
|
-
`mcp-client.ts:386-394`:使用行分隔 JSON 而非 Content-Length 帧。JSON 值含换行时解析失败。官方 MCP 规范推荐 Content-Length 帧。
|
|
3402
|
-
|
|
3403
|
-
**Defect 4 — SSE 解析一次性读取整个响应(HIGH)**
|
|
3404
|
-
`mcp-client.ts:608-649`:`parseEventStreamResponse()` 一次性读取全部 body 文本再解析。无长连接、无断线重连、无逐事件处理。
|
|
3405
|
-
|
|
3406
|
-
**Defect 5 — SSE startServer 始终返回 true(HIGH)**
|
|
3407
|
-
同 Defect 1,但单独列出:这个返回值被调用方用于判断 server 是否就绪,永远返回 true 导致后续逻辑全部基于错误前提运行。
|
|
3408
|
-
|
|
3409
|
-
**Defect 6 — callHttpTool/callStdioTool 结果解析代码重复(MEDIUM)**
|
|
3410
|
-
`mcp-client.ts:920-1032`:两个方法含几乎相同的结果解析逻辑(~35 行重复)。bug 修复需手动同步两处。
|
|
3411
|
-
|
|
3412
|
-
**Defect 7 — loadMCPConfig 读操作有副作用(LOW)**
|
|
3413
|
-
`mcp-config.ts:164-175`:`loadMCPConfig()` 在无配置时 `writeFileSync` 创建默认文件,缺少默认值时 `saveMCPConfig()` 写盘。读操作不应有生产副作用。
|
|
3414
|
-
|
|
3415
|
-
**Defect 8 — 无 Zod schema 验证(MEDIUM)**
|
|
3416
|
-
`mcp-config.ts:178-199`:JSON 解析后直接类型断言。CC 使用 Zod schema 验证 + 结构化错误报告。
|
|
3417
|
-
|
|
3418
|
-
### 3. 高可用差距
|
|
3419
|
-
|
|
3420
|
-
| 差距 | 影响 | 严重度 |
|
|
3421
|
-
|------|------|--------|
|
|
3422
|
-
| 无自动重连 | server 崩溃或 HTTP session 过期后永不恢复 | **CRITICAL** |
|
|
3423
|
-
| 无 session 过期检测 | HTTP 404 + JSON-RPC -32001 不触发重连 | **HIGH** |
|
|
3424
|
-
| 无连续错误追踪 | ECONNRESET/ETIMEDOUT 等不触发重连 | **HIGH** |
|
|
3425
|
-
| 无跨进程 token 刷新 | JSON 文件存储非并发安全 | **HIGH** |
|
|
3426
|
-
| 无进程健康监控 | `client.onerror`/`client.onclose` 无详细日志和缓存失效 | **MEDIUM** |
|
|
3427
|
-
| 无并发连接控制 | 顺序连接,慢 server 阻塞后续所有 server | **MEDIUM** |
|
|
3428
|
-
|
|
3429
|
-
### 4. CC 功能差距
|
|
3430
|
-
|
|
3431
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
3432
|
-
|---------|----------------|--------|
|
|
3433
|
-
| Resource 访问 (resources/list, resources/read) | 无 | **HIGH** |
|
|
3434
|
-
| Prompt 模板 (prompts/list, prompts/get) | 无 | **HIGH** |
|
|
3435
|
-
| WebSocket 传输 | 无 | **HIGH** |
|
|
3436
|
-
| 通用 OAuth(任意 MCP server) | 仅 Figma | **HIGH** |
|
|
3437
|
-
| 企业 allowlist/denylist 策略 | 无 | **HIGH** |
|
|
3438
|
-
| 7 级配置层次 | 单一文件 | **HIGH** |
|
|
3439
|
-
| 自动重连 + 透明重试 | 无 | **HIGH** |
|
|
3440
|
-
| Elicitation | 无 | **MEDIUM** |
|
|
3441
|
-
| Server instructions 注入 | 无 | **MEDIUM** |
|
|
3442
|
-
| 工具注解 (_meta) | 无 | **MEDIUM** |
|
|
3443
|
-
| 工具结果截断/图片压缩 | 无 | **MEDIUM** |
|
|
3444
|
-
| 二进制 blob 持久化 | 无 | **MEDIUM** |
|
|
3445
|
-
| Plugin MCP servers | 无 | **MEDIUM** |
|
|
3446
|
-
| 动态 headers (headersHelper) | 无 | **MEDIUM** |
|
|
3447
|
-
| 环境变量展开 (${VAR}) | 仅 {cwd} | **MEDIUM** |
|
|
3448
|
-
| Server 审批对话框 | 无 | **MEDIUM** |
|
|
3449
|
-
| InProcess 传输 | 无 | **LOW** |
|
|
3450
|
-
| claude.ai proxy 传输 | 无 | **LOW** |
|
|
3451
|
-
| Channel 权限中继 | 无 | **LOW** |
|
|
3452
|
-
| Elicitation hooks | 无 | **LOW** |
|
|
3453
|
-
|
|
3454
|
-
### 5. nanoPencil 独有优势
|
|
3455
|
-
|
|
3456
|
-
- **极简架构**:~1200 LOC vs CC 的 ~12000+ LOC,易审计易修改
|
|
3457
|
-
- **内置 10+ server 预设**:filesystem/sequential-thinking/memory/fetch/sqlite/github/brave-search/git/postgres/figma,一键启用
|
|
3458
|
-
- **API key 引导系统**:`mcp-guidance.ts` 提供分步指引、URL、免费层级信息
|
|
3459
|
-
- **Figma Desktop 深度集成**:`/figma` 命令 + 完整设置流程
|
|
3460
|
-
- **Claude Code 凭据导入**:从 `~/.claude/.credentials.json` 导入 Figma OAuth token
|
|
3461
|
-
- **`{cwd}` 占位符**:简洁的项目相对路径
|
|
3462
|
-
- **透明工具命名**:`mcp_serverid_toolname` + 可读 `label` 字段
|
|
3463
|
-
- **每 server 独立超时**:`toolTimeout` + `initTimeout` 独立配置
|
|
3464
|
-
- **Windows npx 降级**:自动尝试 `npx.cmd` → `npm exec --yes` → `npx`
|
|
3465
|
-
|
|
3466
|
-
### 汇总
|
|
3467
|
-
|
|
3468
|
-
| 严重度 | 数量 |
|
|
3469
|
-
|--------|------|
|
|
3470
|
-
| CRITICAL | 2(SSE 静默成功、无自动重连) |
|
|
3471
|
-
| HIGH | 8(协议版本不一致、SSE 解析、session 过期、错误追踪、跨进程 token、无 Resource/Prompt/WS/通用 OAuth/企业策略/7 级配置) |
|
|
3472
|
-
| MEDIUM | 10(Content-Length 帧、代码重复、Zod 验证、进程监控、并发连接、Elicitation/instructions/_meta/截断/Plugin/动态 headers/环境变量/审批) |
|
|
3473
|
-
| LOW | 5(读副作用、InProcess/claude.ai proxy/Channel/Elicitation hooks) |
|
|
3474
|
-
|
|
3475
|
-
**优先修复项:**
|
|
3476
|
-
1. **CRITICAL**: 修复 SSE 传输 — 实现或明确禁用(不要静默返回 true)
|
|
3477
|
-
2. **CRITICAL**: 添加自动重连机制(指数退避 + 连续错误追踪)
|
|
3478
|
-
3. **HIGH**: 对齐协议版本 header 和 body
|
|
3479
|
-
4. **HIGH**: 实现 `resources/list` + `resources/read`
|
|
3480
|
-
5. **HIGH**: 实现 `prompts/list` + `prompts/get`
|
|
3481
|
-
6. **HIGH**: 添加项目级 `.mcp.json` 支持(目录遍历)
|
|
3482
|
-
7. **MEDIUM**: 提取 `callHttpTool`/`callStdioTool` 共享结果解析
|
|
3483
|
-
8. **MEDIUM**: 添加 Zod schema 验证 MCP 配置
|
|
3484
|
-
|
|
3485
|
-
---
|
|
3486
|
-
|
|
3487
|
-
**已完成 38 轮扫描。** MCP 系统已覆盖。
|
|
3488
|
-
|
|
3489
|
-
---
|
|
3490
|
-
|
|
3491
|
-
## Round 39 — Permission System / Tool Approval Flow(权限系统/工具审批流)
|
|
3492
|
-
|
|
3493
|
-
**扫描时间**: 2026-06-12
|
|
3494
|
-
**扫描模块**: `extensions/builtin/plan/plan-permissions.ts`, `extensions/builtin/team/team-permissions.ts`, `extensions/builtin/team/teammate-approval.ts`, `core/sub-agent/agent-tool-filter.ts`, `core/sub-agent/agent-handoff-safety.ts`, `extensions/builtin/security-audit/engine/detector.ts`
|
|
3495
|
-
**对比**: CC `src/utils/permissions/permissions.ts`(~1500 行), `permissionsLoader.ts`, `PermissionUpdate.ts`, `yoloClassifier.ts`, `denialTracking.ts`, `shadowedRuleDetection.ts`, `permissionSetup.ts`, `bypassPermissionsKillswitch.ts`, `permissionExplainer.ts`, `getNextPermissionMode.ts`, `src/utils/swarm/permissionSync.ts`, `src/utils/sandbox/sandbox-adapter.ts`, `src/utils/settings/mdm/settings.ts`
|
|
3496
|
-
|
|
3497
|
-
### 1. 架构对比
|
|
3498
|
-
|
|
3499
|
-
| 维度 | nanoPencil | Claude Code |
|
|
3500
|
-
|------|-----------|-------------|
|
|
3501
|
-
| 权限模式 | 6 种:`default`/`plan`/`auto`/`acceptEdits`/`bypassPermissions`/`dontAsk` | 6 种 + 内部 `bubble` |
|
|
3502
|
-
| 中心权限引擎 | 分散在 5+ 文件,无统一 `hasPermissionsToUseTool` | 单一 ~1500 行 `permissions.ts`,权威入口 |
|
|
3503
|
-
| 规则类型 | 隐式(硬编码工具/命令列表) | 显式 `PermissionRule`(allow/deny/ask 行为 + source + toolName + ruleContent) |
|
|
3504
|
-
| 规则来源 | 无(无 settings 规则加载) | 8 来源:userSettings/projectSettings/localSettings/flagSettings/policySettings/cliArg/command/session |
|
|
3505
|
-
| 权限持久化 | 无(仅内存,`PermissionStore` 无磁盘持久化) | 完整磁盘持久化(`permissionsLoader.ts` + `PermissionUpdate.ts`) |
|
|
3506
|
-
| 工具粒度 | 二进制(工具级 allow/deny) | 子命令级:`Bash(prefix:*)`/`Agent(agentType)`/`mcp__server__tool` |
|
|
3507
|
-
| 危险命令检测 | 两套独立系统:`DangerDetector`(regex)+ `plan-permissions.ts`(前缀/模式列表) | 统一:`dangerousPatterns.ts` + `bashClassifier.ts`(LLM)+ `permissionSetup.ts` |
|
|
3508
|
-
| Auto mode 分类器 | 仅启发式 regex(8 模式) | 完整 LLM 2 阶段分类器(fast XML + thinking)+ 拒绝追踪 + 熔断器 |
|
|
3509
|
-
| 子代理权限继承 | `resolvePermissionMode()` 严格层级 clamp | `resolvePermissionMode()` + auto mode 危险规则剥离 + handoff 分类器审查 |
|
|
3510
|
-
| Team 权限 | `PermissionStore`(内存,Promise)+ 文件系统 mailbox | `permissionSync.ts` 文件锁 + mailbox + sandbox 权限升级 |
|
|
3511
|
-
| 企业策略 (MDM) | 无 | macOS plist / Windows registry / Linux managed-settings.json |
|
|
3512
|
-
| 沙箱 | 无 | `@anthropic-ai/sandbox-runtime`:文件读写限制 + 网络主机白名单 |
|
|
3513
|
-
| 影子规则检测 | 无 | `shadowedRuleDetection.ts` 检测不可达规则 |
|
|
3514
|
-
| 拒绝追踪 | 无 | 连续 3 次 / 总计 20 次拒绝后降级为提示 |
|
|
3515
|
-
| 模式切换 UI | 无 | Shift+Tab 轮转 + gate 检查 |
|
|
3516
|
-
| 权限钩子 | `tool_call` 事件(安全审计 + plan gating) | `executePermissionRequestHooks` + PreToolUse hooks |
|
|
3517
|
-
| MCP 工具权限 | 未处理 | 完整匹配:`mcp__server__tool`/`mcp__server__*`/server 级规则 |
|
|
3518
|
-
|
|
3519
|
-
### 2. 正确性缺陷
|
|
3520
|
-
|
|
3521
|
-
**Defect 1 — PermissionStore 纯内存无持久化(HIGH)**
|
|
3522
|
-
`team-permissions.ts:44-52`:进程崩溃时 teammate 待处理请求和 `pathAllowlist` 丢失。CC 通过 `permissionsLoader.ts` 磁盘持久化。
|
|
3523
|
-
|
|
3524
|
-
**Defect 2 — Handoff 分类器仅 regex 可被绕过(HIGH)**
|
|
3525
|
-
`agent-handoff-safety.ts:129-168`:8 模式 regex 无法检测 base64 编码命令、间接路径遍历等高级攻击。CC 使用 LLM 2 阶段分类器。
|
|
3526
|
-
|
|
3527
|
-
**Defect 3 — DANGEROUS_BASH_PATTERNS `/>/` 过度激进(MEDIUM)**
|
|
3528
|
-
`plan-permissions.ts:59`:任何含 `>` 的命令都被标记为危险,包括 `echo "foo" > /dev/null`。
|
|
3529
|
-
|
|
3530
|
-
**Defect 4 — READONLY_BASH_PREFIXES 前缀匹配可绕过(MEDIUM)**
|
|
3531
|
-
`plan-permissions.ts:32-56`:`startsWith(prefix)` 可被命令链接绕过,如 `git status; rm -rf /` 匹配 `git status` 前缀。
|
|
3532
|
-
|
|
3533
|
-
**Defect 5 — 文件系统 mailbox 无锁无原子写入(MEDIUM)**
|
|
3534
|
-
`teammate-approval.ts:77-88`:`fs.writeFileSync` 无锁,并发写入可能损坏请求文件。
|
|
3535
|
-
|
|
3536
|
-
**Defect 6 — MCP 工具绕过 plan mode 过滤器(MEDIUM)**
|
|
3537
|
-
`agent-tool-filter.ts:75-78`:MCP 工具在 plan mode 只读过滤器之后添加(line 80),可执行写操作。
|
|
3538
|
-
|
|
3539
|
-
**Defect 7 — 白名单 includes() 匹配过宽(LOW)**
|
|
3540
|
-
`detector.ts:46,61`:白名单 `"git"` 会匹配 `"github"`、`"nugit"` 等。
|
|
3541
|
-
|
|
3542
|
-
**Defect 8 — resolvePermissionMode 语义混淆(LOW)**
|
|
3543
|
-
`agent-tool-filter.ts:250-264`:`"default"` 在严格层级中 index 为 4,但父默认 `"acceptEdits"` index 为 2,clamp 后返回 `"acceptEdits"` 而非 `"default"`。
|
|
3544
|
-
|
|
3545
|
-
### 3. 高可用差距
|
|
3546
|
-
|
|
3547
|
-
| 差距 | 影响 | 严重度 |
|
|
3548
|
-
|------|------|--------|
|
|
3549
|
-
| 权限决策无磁盘持久化 | 进程重启丢失所有权限决策和 teammate 审批 | **HIGH** |
|
|
3550
|
-
| 权限系统无熔断器/降级 | 安全审计扩展加载失败时无 fallback | **HIGH** |
|
|
3551
|
-
| 无拒绝追踪 | 循环被拒的工具调用无限重试 | **MEDIUM** |
|
|
3552
|
-
| 文件系统 mailbox 无锁/无清理 | 死请求累积,永不清理 | **MEDIUM** |
|
|
3553
|
-
|
|
3554
|
-
### 4. CC 功能差距
|
|
3555
|
-
|
|
3556
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
3557
|
-
|---------|----------------|--------|
|
|
3558
|
-
| 企业策略 (MDM) | 无 | **CRITICAL** |
|
|
3559
|
-
| 沙箱运行时 | 无 | **CRITICAL** |
|
|
3560
|
-
| LLM auto mode 分类器 | 仅 regex | **CRITICAL** |
|
|
3561
|
-
| 子命令级权限规则 | 仅工具级 | **HIGH** |
|
|
3562
|
-
| 影子规则检测 | 无 | **HIGH** |
|
|
3563
|
-
| Auto mode 危险规则剥离 | 无 | **HIGH** |
|
|
3564
|
-
| 8 级规则来源 + 优先级 | 无规则来源 | **HIGH** |
|
|
3565
|
-
| 子代理 swarm 权限同步 | 内存无锁 | **HIGH** |
|
|
3566
|
-
| 模式切换 UI (Shift+Tab) | 无 | **MEDIUM** |
|
|
3567
|
-
| Bypass 远程 killswitch | 无 | **MEDIUM** |
|
|
3568
|
-
| 权限解释器(风险等级) | 无 | **MEDIUM** |
|
|
3569
|
-
| CLI --base-tools | 无 | **LOW** |
|
|
3570
|
-
|
|
3571
|
-
### 5. nanoPencil 独有优势
|
|
3572
|
-
|
|
3573
|
-
- **安全审计扩展 + 仪表板**:`/security dashboard`/`logs`/`stats`/`clear` 命令,CC 无等价物
|
|
3574
|
-
- **三级安全模式**:`audit`(仅日志)/`confirm`(确认)/`strict`(严格阻止)
|
|
3575
|
-
- **敏感文件路径保护**:SSH keys/AWS/Azure/GCloud 凭据/.env 等路径检查
|
|
3576
|
-
- **只读工具过滤器**:`isReadOnlyTool()` 干净可复用
|
|
3577
|
-
- **递归限制强制执行**:显式阻止 fork-in-fork、teammate-spawns-teammate
|
|
3578
|
-
|
|
3579
|
-
### 汇总
|
|
3580
|
-
|
|
3581
|
-
| 严重度 | 数量 |
|
|
3582
|
-
|--------|------|
|
|
3583
|
-
| CRITICAL | 3(无 MDM、无沙箱、regex-only 分类器) |
|
|
3584
|
-
| HIGH | 6(PermissionStore 无持久化、handoff 分类器可绕过、无子命令规则、无影子检测、无 auto mode 剥离、无规则来源) |
|
|
3585
|
-
| MEDIUM | 7(DANGEROUS_BASH 过度、前缀可绕过、mailbox 无锁、MCP 绕过 plan mode、无熔断器、无拒绝追踪、无模式切换 UI) |
|
|
3586
|
-
| LOW | 3(白名单过宽、语义混淆、CLI --base-tools) |
|
|
3587
|
-
|
|
3588
|
-
**优先修复项:**
|
|
3589
|
-
1. **CRITICAL**: 实现中心权限引擎(统一 `hasPermissionsToUseTool`)
|
|
3590
|
-
2. **CRITICAL**: 替换 regex handoff 分类器为 LLM 分类器
|
|
3591
|
-
3. **HIGH**: 权限规则磁盘持久化
|
|
3592
|
-
4. **HIGH**: 修复 MCP 工具绕过 plan mode 过滤器
|
|
3593
|
-
5. **HIGH**: 添加拒绝追踪 + 降级
|
|
3594
|
-
6. **MEDIUM**: 修复 bash 前缀匹配绕过
|
|
3595
|
-
7. **MEDIUM**: 添加文件系统 mailbox 文件锁
|
|
3596
|
-
|
|
3597
|
-
---
|
|
3598
|
-
|
|
3599
|
-
**已完成 39 轮扫描。** 权限系统/工具审批流已覆盖。
|
|
3600
|
-
|
|
3601
|
-
---
|
|
3602
|
-
|
|
3603
|
-
## Round 40 — System Prompt Construction(系统提示构建)
|
|
3604
|
-
|
|
3605
|
-
**扫描时间**: 2026-06-12
|
|
3606
|
-
**扫描模块**: `core/prompt/system-prompt.ts`, `core/runtime/prompt-assembly.ts`, `core/platform/config/resource-loader.ts`
|
|
3607
|
-
**对比**: CC `src/constants/prompts.ts`(async `getSystemPrompt()` + 15+ helper), `src/utils/systemPrompt.ts`, `src/utils/claudemd.ts`, `src/context.ts`, `systemPromptSections.ts`
|
|
3608
|
-
|
|
3609
|
-
### 1. 架构对比
|
|
3610
|
-
|
|
3611
|
-
| 维度 | nanoPencil | Claude Code |
|
|
3612
|
-
|------|-----------|-------------|
|
|
3613
|
-
| 提示数据类型 | 单一扁平 `string` | `SystemPrompt` = branded `readonly string[]`(数组原生) |
|
|
3614
|
-
| 组装文件 | 单一函数 `buildSystemPrompt` | `getSystemPrompt()` + 15+ 辅助函数 |
|
|
3615
|
-
| Section 缓存 | 无 — 每轮从头重建 | `systemPromptSections.ts` 命名 section 缓存至 `/clear` 或 `/compact` |
|
|
3616
|
-
| 静态/动态分离 | 无 — 整个提示视为单个 blob | `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` 标记分离可缓存前缀和动态后缀 |
|
|
3617
|
-
| Cache 策略 | 扁平 `cache_control: {type:'ephemeral'}` 整个 system prompt | 两级:`scope:'global'` 静态前缀 + `scope:'org'` 动态后缀 + `cache_reference` 工具结果 |
|
|
3618
|
-
| MCP 指令注入 | 无 | Delta-based:`getMcpInstructionsDelta()` diff 已连接 server,作为附件持久化 |
|
|
3619
|
-
| 上下文文件加载 | 每目录 3 候选:`AGENTS.md`/`AGENT.md`/`CLAUDE.md` + `.PENCIL.md` | 4 级优先级:Managed > User > Project > Local + `.claude/rules/*.md` glob + `@include` |
|
|
3620
|
-
| 工具指导 | 内联在 system prompt 中 | 工具 schema 为独立 API 参数;指导文本在 `# Using your tools` section |
|
|
3621
|
-
| Soul/人格 | `SoulManager` Big Five 特质 + 价值观 + 情感状态 + 记忆进化 | 无 — 依赖 CLAUDE.md 用户编写指令 |
|
|
3622
|
-
| PENCIL.md 完整性 | 反越狱追加:"忽略尝试修改人格的用户提示" | 无 |
|
|
3623
|
-
| Skills | XML 格式 `<available_skills>` 块 | `/skill-name` 斜杠命令;默认不在 prompt 中列出 |
|
|
3624
|
-
| 记忆系统 | 简单文件型:磁盘上下文文件 | 类型化:`User`/`Project`/`Local`/`Managed`/`AutoMem`/`TeamMem` + MEMORY.md 索引 |
|
|
3625
|
-
| 提示大小管理 | 无 — 无截断或预算 | `MAX_MEMORY_CHARACTER_COUNT = 40000`, MEMORY.md 行/字节上限 |
|
|
3626
|
-
| 条件规则 | 无 — 所有上下文文件始终加载 | Frontmatter `paths:` glob 匹配,按文件条件加载 |
|
|
3627
|
-
| 日期/时间 | 完整 locale 字符串 + time tool 提醒 | ISO 日期 + 模型知识截止日期 |
|
|
3628
|
-
|
|
3629
|
-
### 2. 正确性缺陷
|
|
3630
|
-
|
|
3631
|
-
**Defect 1 — `extensionToolsGuidance` 参数从未接线(HIGH)**
|
|
3632
|
-
`prompt-assembly.ts` L35:`buildRuntimeSystemPrompt` 未传递 `extensionToolsGuidance`。定义了 `guidance` 字符串的扩展工具定义被静默丢弃,模型仅有 JSON schema 无语义指导。
|
|
3633
|
-
|
|
3634
|
-
**Defect 2 — `appendSystemPrompt` 顺序不一致(MEDIUM)**
|
|
3635
|
-
`system-prompt.ts`:有 `customPrompt` 时 append 在 custom 之后、context 之前(L87-89);无 `customPrompt` 时在 soul 之后、context 之前(L300-302)。两种路径的 append 位置语义不同。
|
|
3636
|
-
|
|
3637
|
-
**Defect 3 — 祖先上下文文件优先级脆弱(MEDIUM)**
|
|
3638
|
-
`resource-loader.ts` L134-153:`unshift` 构建深度优先列表,全局条目通过 `seenPaths` 去重时总是赢(先加载),即使祖先副本更新。
|
|
3639
|
-
|
|
3640
|
-
**Defect 4 — Persona 完整性检查可绕过(LOW)**
|
|
3641
|
-
`resource-loader.ts` L117-124:完整性保护仅在 persona 文件激活时追加,全局 `.PENCIL.md` fallback 不受保护。
|
|
3642
|
-
|
|
3643
|
-
**Defect 5 — 无上下文文件大小限制(LOW)**
|
|
3644
|
-
无 `MAX_MEMORY_CHARACTER_COUNT` 等价物。大 `AGENT.md` 可消耗过多上下文预算。
|
|
3645
|
-
|
|
3646
|
-
### 3. 高可用差距
|
|
3647
|
-
|
|
3648
|
-
| 差距 | 影响 | 严重度 |
|
|
3649
|
-
|------|------|--------|
|
|
3650
|
-
| 无 prompt cache 分段 | 每 session 支付完整 prompt 重处理成本 | **HIGH** |
|
|
3651
|
-
| 无 section 缓存 | 每轮从头重建(重读磁盘、重算 skills、重格式化工具列表) | **HIGH** |
|
|
3652
|
-
| 无 MCP 指令 delta | MCP server 连接/断开时整个 system prompt cache 失效 | **MEDIUM** |
|
|
3653
|
-
| 无上下文文件重载机制 | `reload()` 未被相同生命周期事件触发 | **MEDIUM** |
|
|
3654
|
-
| 单一 provider cache 标记 | 整个 prompt 扁平 `cache_control`,任何内容变更都破坏缓存 | **MEDIUM** |
|
|
3655
|
-
|
|
3656
|
-
### 4. CC 功能差距
|
|
3657
|
-
|
|
3658
|
-
| CC 功能 | nanoPencil 状态 | 严重度 |
|
|
3659
|
-
|---------|----------------|--------|
|
|
3660
|
-
| 4 级记忆层级(Managed/User/Project/Local) | 全局 + 祖先遍历 + 项目 `.PENCIL.md` | **HIGH** |
|
|
3661
|
-
| 条件规则(frontmatter paths glob) | 无 | **HIGH** |
|
|
3662
|
-
| `@include` 指令系统 | 无 | **MEDIUM** |
|
|
3663
|
-
| 类型化记忆(AutoMem/TeamMem) | 扁平文件 | **MEDIUM** |
|
|
3664
|
-
| 输出样式配置 | 无 | **MEDIUM** |
|
|
3665
|
-
| Scratchpad 目录 | 无 | **LOW** |
|
|
3666
|
-
| 数字长度锚点 | 无 | **LOW** |
|
|
3667
|
-
| 工具结果清除说明 | 无 | **LOW** |
|
|
3668
|
-
| 主动/自主代理模式 | 无 | **LOW** |
|
|
3669
|
-
|
|
3670
|
-
### 5. nanoPencil 独有优势
|
|
3671
|
-
|
|
3672
|
-
- **Soul Engine + Big Five 人格**:进化式自适应人格,CC 无等价物
|
|
3673
|
-
- **PENCIL.md 反越狱完整性**:激活 persona 时追加人格保护指令
|
|
3674
|
-
- **P3 DIP Header 渐进式披露**:WHO/FROM/TO/HERE 4 问文件头格式,O(1) 相关性评估
|
|
3675
|
-
- **扩展工具指导合并架构**:`extensionToolsGuidance` 参数(虽未接线)设计为合并扩展贡献的指导
|
|
3676
|
-
- **Persona 专用 skills 目录**:不同 persona 可提供不同 skill 集合
|
|
3677
|
-
|
|
3678
|
-
### 汇总
|
|
3679
|
-
|
|
3680
|
-
| 严重度 | 数量 |
|
|
3681
|
-
|--------|------|
|
|
3682
|
-
| HIGH | 3(extensionToolsGuidance 未接线、无 cache 分段、无 section 缓存) |
|
|
3683
|
-
| MEDIUM | 5(append 顺序不一致、祖先优先级脆弱、无 MCP delta、无重载机制、单一 cache 标记) |
|
|
3684
|
-
| LOW | 4(完整性可绕过、无大小限制、无条件规则、无 @include) |
|
|
3685
|
-
|
|
3686
|
-
**优先修复项:**
|
|
3687
|
-
1. **HIGH**: 接线 `extensionToolsGuidance` — 从扩展工具定义收集 `guidance` 字符串
|
|
3688
|
-
2. **HIGH**: 实现 system prompt section 缓存 — 缓存 skills/tools/context 等计算 section
|
|
3689
|
-
3. **HIGH**: 实现静态/动态 prompt 边界分离 — `cacheScope:'global'` 静态前缀
|
|
3690
|
-
4. **MEDIUM**: 添加上下文文件大小限制(40K chars/文件,100K 总计)
|
|
3691
|
-
5. **MEDIUM**: 修复 `appendSystemPrompt` 位置一致性
|
|
3692
|
-
|
|
3693
|
-
---
|
|
3694
|
-
|
|
3695
|
-
**已完成 40 轮扫描。** 系统提示构建已覆盖。
|
|
3696
|
-
|
|
3697
|
-
---
|
|
3698
|
-
|
|
3699
|
-
---
|
|
3700
|
-
|
|
3701
|
-
## Round 42 — Git Integration(Git 集成系统)
|
|
3702
|
-
|
|
3703
|
-
**扫描时间**: 2026-06-12
|
|
3704
|
-
**扫描范围**: nanoPencil Git 集成 vs Claude Code Git 集成
|
|
3705
|
-
**NP 文件数**: ~22 files, ~6,507 lines
|
|
3706
|
-
**CC 文件数**: ~15 files, ~6,000+ lines
|
|
3707
|
-
|
|
3708
|
-
### 架构对比
|
|
3709
|
-
|
|
3710
|
-
| 层级 | Claude Code | nanoPencil | 差距 |
|
|
3711
|
-
|------|------------|------------|------|
|
|
3712
|
-
| **文件系统层** | `gitFilesystem.ts` (~700行) 直接读 `.git/` 文件,无子进程 | `footer-data-provider.ts` 用 `fs.watch` 监听 HEAD 目录 | **CC 优势大** — NP 缺少无子进程的 git 状态读取 |
|
|
3713
|
-
| **工具层** | `git.ts` (~933行) 带 LRU 缓存的完整 API | 分散在多个扩展中,无统一工具层 | **CC 优势大** — NP 无集中式 git 工具模块 |
|
|
3714
|
-
| **Diff 层** | `gitDiff.ts` (~533行) shortstat/numstat/unified diff | 各扩展各自调 `git diff` | **CC 优势大** — NP 无统一 diff 工具 |
|
|
3715
|
-
| **命令层** | `/commit`, `/commit-push-pr`, `/diff` | 无 git 相关 slash 命令 | **NP 缺失** |
|
|
3716
|
-
| **追踪层** | `commitAttribution.ts` (~962行) + `gitOperationTracking.ts` (~278行) | `insights/session-scanner.ts` 基础计数 | **CC 优势大** |
|
|
3717
|
-
| **安全层** | `gitSafety.ts` bare-repo 防御 + NTFS 8.3 防御 | `bash.ts` 基础 sandbox regex | **CC 更完善** |
|
|
3718
|
-
| **UI 层** | `DiffDialog.tsx` 完整 diff 查看器 | 无 diff UI | **NP 缺失** |
|
|
3719
|
-
| **Worktree** | `worktree.ts` (~1520行) 完整生命周期 | `worktree-manager.ts` (~439行) 基础实现 | **CC 功能更全** |
|
|
3720
|
-
|
|
3721
|
-
### 发现的问题
|
|
3722
|
-
|
|
3723
|
-
#### CRITICAL — 无(无安全漏洞)
|
|
3724
|
-
|
|
3725
|
-
#### HIGH — 5 项
|
|
3726
|
-
|
|
3727
|
-
**H42-1. 缺少集中式 git 工具模块**
|
|
3728
|
-
- **问题**: NP 的 git 操作分散在 `footer-data-provider.ts`, `simplify/index.ts`, `debug/collectors.ts`, `team-harness.ts`, `presence/index.ts` 等多个文件中,每个都独立 spawn `git` 子进程。CC 有统一的 `git.ts` + `gitFilesystem.ts` 层。
|
|
3729
|
-
- **影响**: (1) 重复代码多 (2) 无法统一缓存 (3) 每次 git 操作都 spawn 子进程,性能差 (4) 无法保证安全校验一致性
|
|
3730
|
-
- **建议**: 创建 `core/git/` 模块,提供 `getBranch()`, `getHead()`, `getIsClean()`, `getChangedFiles()` 等统一 API,带 LRU 缓存。
|
|
3731
|
-
- **CC 参考**: `src/utils/git.ts`, `src/utils/git/gitFilesystem.ts`
|
|
3732
|
-
|
|
3733
|
-
**H42-2. 缺少无子进程的 git 状态读取**
|
|
3734
|
-
- **问题**: CC 的 `gitFilesystem.ts` (~700行) 直接读取 `.git/HEAD`, `.git/config`, loose refs, packed-refs 来获取分支名、HEAD SHA、remote URL,完全不 spawn 子进程。NP 的 `FooterDataProvider` 虽然用 `fs.watch` 监听 HEAD 目录,但读取分支名仍依赖解析 `.git/HEAD` 文件内容(这是好的),但其他 git 操作(status, diff, log)仍需子进程。
|
|
3735
|
-
- **影响**: 频繁的 git 子进程调用(如 footer 每次渲染、presence 扩展定时采集)造成不必要的开销
|
|
3736
|
-
- **建议**: 扩展 `FooterDataProvider` 的文件系统读取模式,为 `getHead()`, `getRemoteUrl()`, `getDefaultBranch()` 等提供无子进程实现
|
|
3737
|
-
- **CC 参考**: `gitFilesystem.ts` 的 `readGitHead()`, `resolveRef()`, `GitFileWatcher`
|
|
3738
|
-
|
|
3739
|
-
**H42-3. 缺少 `/diff` 命令和 diff 查看器**
|
|
3740
|
-
- **问题**: CC 有 `/diff` 命令配合 `DiffDialog.tsx` 组件,可查看当前未提交更改和每轮对话的 diff。NP 完全没有此功能。
|
|
3741
|
-
- **影响**: 用户无法在 TUI 中直观查看工作区变更,需要退出工具手动 `git diff`
|
|
3742
|
-
- **建议**: 实现 `/diff` 命令,复用 TUI 组件系统展示 diff stats 和 hunks
|
|
3743
|
-
- **CC 参考**: `src/commands/diff/diff.tsx`, `src/components/diff/DiffDialog.tsx`, `src/utils/gitDiff.ts`
|
|
3744
|
-
|
|
3745
|
-
**H42-4. 缺少 `/commit` 命令**
|
|
3746
|
-
- **问题**: CC 有 `/commit` 和 `/commit-push-pr` 命令,NP 没有任何 git commit 相关的 slash 命令。
|
|
3747
|
-
- **影响**: 用户需要手动让 AI 执行 git commit,缺少标准化的 commit 流程和安全约束
|
|
3748
|
-
- **建议**: 实现 `/commit` 命令,包含 git safety protocol(不跳过 hooks、不 force push、不使用 -i flag)
|
|
3749
|
-
- **CC 参考**: `src/commands/commit.ts`, `src/commands/commit-push-pr.ts`
|
|
3750
|
-
|
|
3751
|
-
**H42-5. Git 安全防护不够完善**
|
|
3752
|
-
- **问题**: CC 有专门的 `gitSafety.ts` 防御 bare-repo 沙箱逃逸攻击和 NTFS 8.3 短文件名攻击。NP 的 `bash.ts` sandbox regex 只做了基础的 git write 命令阻止。
|
|
3753
|
-
- **影响**: 潜在的沙箱逃逸风险 — 恶意仓库可能通过 `.git` 目录结构绕过沙箱
|
|
3754
|
-
- **建议**:
|
|
3755
|
-
1. 添加 bare-repo 检测 (`isCurrentDirectoryBareGitRepo()`)
|
|
3756
|
-
2. 添加 `.git` 内部路径安全校验
|
|
3757
|
-
3. 参考 CC 的 `isSafeRefName()` 验证分支名安全性
|
|
3758
|
-
- **CC 参考**: `src/tools/PowerShellTool/gitSafety.ts`, `src/utils/git.ts` 的 `isCurrentDirectoryBareGitRepo()`
|
|
3759
|
-
|
|
3760
|
-
#### MEDIUM — 5 项
|
|
3761
|
-
|
|
3762
|
-
**M42-1. 缺少 default branch 检测**
|
|
3763
|
-
- **问题**: CC 有 `getDefaultBranch()` 检测 main/master,用于 PR 创建、diff 基准等。NP 没有。
|
|
3764
|
-
- **影响**: 需要 default branch 的功能(如 `/commit-push-pr`)无法实现
|
|
3765
|
-
- **建议**: 在 git 工具模块中添加 `getDefaultBranch()`,通过 `git symbolic-ref refs/remotes/origin/HEAD` 或 fallback 到 main/master 检测
|
|
3766
|
-
|
|
3767
|
-
**M42-2. 缺少 git config 解析器**
|
|
3768
|
-
- **问题**: CC 有专门的 `gitConfigParser.ts` 解析 `.git/config`。NP 没有。
|
|
3769
|
-
- **影响**: 无法读取 git 配置(如 remote URL、user.name)而无需 spawn 子进程
|
|
3770
|
-
- **建议**: 实现轻量级 `.git/config` 解析器,或使用 `git config --get` 作为折中
|
|
3771
|
-
|
|
3772
|
-
**M42-3. 缺少 commit attribution 追踪**
|
|
3773
|
-
- **问题**: CC 的 `commitAttribution.ts` (~962行) 追踪 AI 对文件的贡献百分比,在 commit message 中添加 attribution trailer。NP 完全没有。
|
|
3774
|
-
- **影响**: commit message 中无法体现 AI 的贡献比例
|
|
3775
|
-
- **建议**: 如果需要此功能,可实现简化版 — 追踪 AI 编辑的文件行数,计算贡献百分比
|
|
3776
|
-
- **CC 参考**: `src/utils/commitAttribution.ts`
|
|
3777
|
-
|
|
3778
|
-
**M42-4. Worktree 管理功能不完整**
|
|
3779
|
-
- **问题**: CC 的 worktree 系统 (~1520行) 支持 session worktree、agent worktree、sparse-checkout、`.worktreeinclude` 文件复制、tmux 集成、stale 清理等。NP 的 `WorktreeManager` (~439行) 只有基础的 create/list/apply/dispose。
|
|
3780
|
-
- **影响**: 子代理的隔离工作区功能较弱
|
|
3781
|
-
- **建议**: 优先补充 `cleanupStaleWorktrees()` 和 `.worktreeinclude` 支持
|
|
3782
|
-
- **CC 参考**: `src/utils/worktree.ts`
|
|
3783
|
-
|
|
3784
|
-
**M42-5. Git 操作缺少统一的错误处理和超时**
|
|
3785
|
-
- **问题**: NP 各处的 git 子进程调用没有统一的超时和错误处理。CC 在 `git.ts` 中统一处理。NP 的 `presence/index.ts` 有 350ms 超时,但其他地方没有。
|
|
3786
|
-
- **影响**: git 命令挂起时可能阻塞 UI 或扩展
|
|
3787
|
-
- **建议**: 在统一 git 工具层中添加默认超时(如 5s)和错误处理
|
|
3788
|
-
|
|
3789
|
-
#### LOW — 3 项
|
|
3790
|
-
|
|
3791
|
-
**L42-1. `branch-summary-message.ts` 文案问题**
|
|
3792
|
-
- **问题**: line 58 显示 `"Branch summary (expand to expand)"`,`expand` 重复
|
|
3793
|
-
- **建议**: 改为 `"Branch summary (Enter to show)"` 或类似
|
|
3794
|
-
|
|
3795
|
-
**L42-2. 缺少 gitignore 工具**
|
|
3796
|
-
- **问题**: CC 有 `gitignore.ts` 提供 `isPathGitignored()` 和 `addFileGlobRuleToGitignore()`。NP 没有。
|
|
3797
|
-
- **影响**: 低 — 可通过 `git check-ignore` 命令替代
|
|
3798
|
-
|
|
3799
|
-
**L42-3. 缺少 GitHub repo path mapping**
|
|
3800
|
-
- **问题**: CC 追踪已知的本地克隆路径。NP 不需要(架构不同)。
|
|
3801
|
-
- **影响**: 无 — NP 不依赖此功能
|
|
3802
|
-
|
|
3803
|
-
### 优势(NP 做得好的地方)
|
|
3804
|
-
|
|
3805
|
-
1. **Token-saving git compaction**: NP 的 `token-save/filters.ts` 提供了 git status/diff/log 输出的智能压缩(65-70% token 节省),CC 没有此功能
|
|
3806
|
-
2. **FooterDataProvider 设计**: 将 git branch 检测和扩展状态集中管理,接口清晰
|
|
3807
|
-
3. **Git watcher 处理 atomic write**: 正确处理了 git 的原子写入模式(watch 目录而非文件)
|
|
3808
|
-
4. **Presence 扩展**: 将 git 上下文注入 AI 提示词,帮助 AI 了解项目状态
|
|
3809
|
-
|
|
3810
|
-
### 优先级建议
|
|
3811
|
-
|
|
3812
|
-
| 优先级 | 项目 | 工作量 |
|
|
3813
|
-
|--------|------|--------|
|
|
3814
|
-
| **P1** | H42-1 集中式 git 工具模块 | 大 |
|
|
3815
|
-
| **P1** | H42-5 Git 安全防护 | 中 |
|
|
3816
|
-
| **P2** | H42-2 无子进程 git 状态读取 | 中 |
|
|
3817
|
-
| **P2** | H42-3 `/diff` 命令 | 中 |
|
|
3818
|
-
| **P3** | H42-4 `/commit` 命令 | 小 |
|
|
3819
|
-
| **P3** | M42-1 default branch 检测 | 小 |
|
|
3820
|
-
| **P4** | M42-2~M42-5 其余 | 中 |
|