@pencil-agent/nano-pencil 2.0.0-beta.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/README.md +267 -267
  2. package/dist/build-meta.json +3 -3
  3. package/dist/core/export-html/AGENT.md +11 -11
  4. package/dist/core/export-html/template.css +971 -971
  5. package/dist/core/export-html/template.html +54 -54
  6. package/dist/core/extensions-host/index.d.ts +1 -1
  7. package/dist/core/extensions-host/loader.js +1 -1
  8. package/dist/core/extensions-host/runner.d.ts +1 -0
  9. package/dist/core/extensions-host/runner.js +2 -2
  10. package/dist/core/extensions-host/types.d.ts +17 -22
  11. package/dist/core/lib/ai/src/types.d.ts +12 -2
  12. package/dist/core/persona/persona-manager.js +5 -2
  13. package/dist/core/runtime/agent-session.js +3 -3
  14. package/dist/core/runtime/extension-core-bindings.d.ts +1 -0
  15. package/dist/core/runtime/extension-core-bindings.js +2 -2
  16. package/dist/extensions/builtin/AGENT.md +115 -115
  17. package/dist/extensions/builtin/browser/AGENT.md +17 -17
  18. package/dist/extensions/builtin/browser/agent-workspace/agent_helpers.py +12 -12
  19. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/amazon/product-search.md +198 -198
  20. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/archive-org/scraping.md +341 -341
  21. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv/scraping.md +311 -311
  22. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/arxiv-bulk/scraping.md +333 -333
  23. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/atlas/overview.md +70 -70
  24. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/booking-com/scraping.md +578 -578
  25. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/capterra/scraping.md +440 -440
  26. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/centilebrain/generate-estimates.md +110 -110
  27. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coingecko/scraping.md +325 -325
  28. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coinmarketcap/scraping.md +463 -463
  29. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/coursera/scraping.md +360 -360
  30. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/craigslist/scraping.md +390 -390
  31. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/crossref/scraping.md +568 -568
  32. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/dev-to/scraping.md +323 -323
  33. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/duckduckgo/scraping.md +349 -349
  34. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/ebay/scraping.md +435 -435
  35. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/etsy/scraping.md +506 -506
  36. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/eventbrite/scraping.md +363 -363
  37. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/expedia/automation.md +168 -168
  38. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/groups.md +236 -236
  39. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/facebook/pages.md +295 -295
  40. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/framer/editor.md +108 -108
  41. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/fred/scraping.md +493 -493
  42. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/g2/scraping.md +580 -580
  43. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/genius/scraping.md +511 -511
  44. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/repo-actions.md +65 -65
  45. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/github/scraping.md +184 -184
  46. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/glassdoor/scraping.md +543 -543
  47. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gmail/compose.md +122 -122
  48. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/goodreads/scraping.md +461 -461
  49. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/gutenberg/scraping.md +383 -383
  50. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/hackernews/scraping.md +243 -243
  51. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/howlongtobeat/scraping.md +473 -473
  52. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/imdb/scraping.md +271 -271
  53. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/itch-io/scraping.md +436 -436
  54. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/job-boards/indeed-glassdoor.md +1021 -1021
  55. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/letterboxd/scraping.md +349 -349
  56. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/linkedin/invitation-manager.md +109 -109
  57. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/loom/folder-enumeration.md +170 -170
  58. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/macrotrends/scraping.md +537 -537
  59. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/article-hydration.md +120 -120
  60. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/medium/scraping.md +414 -414
  61. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/metacritic/scraping.md +477 -477
  62. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/musicbrainz/scraping.md +478 -478
  63. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/nasa/scraping.md +339 -339
  64. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/news-aggregation/multi-source.md +205 -205
  65. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/open-library/scraping.md +472 -472
  66. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openalex/scraping.md +470 -470
  67. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/openstreetmap/scraping.md +490 -490
  68. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/package-registries/npm-pypi.md +478 -478
  69. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/polymarket/scraping.md +234 -234
  70. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/producthunt/scraping.md +307 -307
  71. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/pubmed/scraping.md +421 -421
  72. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/quora/scraping.md +364 -364
  73. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rawg/scraping.md +352 -352
  74. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/reddit/scraping.md +124 -124
  75. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/rest-countries/scraping.md +233 -233
  76. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/sec-edgar/scraping.md +361 -361
  77. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/README.md +36 -36
  78. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/embedded-apps.md +72 -72
  79. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/knowledge-base.md +109 -109
  80. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/shopify-admin/polaris-inputs.md +137 -137
  81. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/soundcloud/scraping.md +362 -362
  82. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/spotify/scraping.md +339 -339
  83. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/stackoverflow/scraping.md +435 -435
  84. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/steam/scraping.md +575 -575
  85. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/substack/scraping.md +338 -338
  86. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/thetechgeeks/pricing.md +52 -52
  87. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tiktok/upload.md +107 -107
  88. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/tradingview/scraping.md +309 -309
  89. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trello/boards-and-lists.md +88 -88
  90. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/trustpilot/scraping.md +375 -375
  91. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/walmart/scraping.md +444 -444
  92. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wayback-machine/scraping.md +306 -306
  93. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/weather/scraping.md +398 -398
  94. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/wellfound/scraping.md +596 -596
  95. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/world-bank/scraping.md +356 -356
  96. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/xiaohongshu/scraping.md +84 -84
  97. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/youtube/scraping.md +418 -418
  98. package/dist/extensions/builtin/browser/agent-workspace/domain-skills/zillow/scraping.md +433 -433
  99. package/dist/extensions/builtin/browser/browser.md +73 -73
  100. package/dist/extensions/builtin/browser/install.md +142 -142
  101. package/dist/extensions/builtin/browser/interaction-skills/connection.md +48 -48
  102. package/dist/extensions/builtin/browser/interaction-skills/cookies.md +3 -3
  103. package/dist/extensions/builtin/browser/interaction-skills/cross-origin-iframes.md +3 -3
  104. package/dist/extensions/builtin/browser/interaction-skills/dialogs.md +64 -64
  105. package/dist/extensions/builtin/browser/interaction-skills/downloads.md +3 -3
  106. package/dist/extensions/builtin/browser/interaction-skills/drag-and-drop.md +3 -3
  107. package/dist/extensions/builtin/browser/interaction-skills/dropdowns.md +3 -3
  108. package/dist/extensions/builtin/browser/interaction-skills/iframes.md +3 -3
  109. package/dist/extensions/builtin/browser/interaction-skills/network-requests.md +3 -3
  110. package/dist/extensions/builtin/browser/interaction-skills/print-as-pdf.md +3 -3
  111. package/dist/extensions/builtin/browser/interaction-skills/profile-sync.md +90 -90
  112. package/dist/extensions/builtin/browser/interaction-skills/screenshots.md +17 -17
  113. package/dist/extensions/builtin/browser/interaction-skills/scrolling.md +3 -3
  114. package/dist/extensions/builtin/browser/interaction-skills/shadow-dom.md +3 -3
  115. package/dist/extensions/builtin/browser/interaction-skills/tabs.md +69 -69
  116. package/dist/extensions/builtin/browser/interaction-skills/uploads.md +1 -1
  117. package/dist/extensions/builtin/browser/interaction-skills/viewport.md +3 -3
  118. package/dist/extensions/builtin/browser/src/browser_harness/AGENT.md +15 -15
  119. package/dist/extensions/builtin/browser/src/browser_harness/__init__.py +8 -8
  120. package/dist/extensions/builtin/browser/src/browser_harness/_ipc.py +90 -90
  121. package/dist/extensions/builtin/browser/src/browser_harness/admin.py +722 -722
  122. package/dist/extensions/builtin/browser/src/browser_harness/daemon.py +328 -328
  123. package/dist/extensions/builtin/browser/src/browser_harness/helpers.py +396 -396
  124. package/dist/extensions/builtin/browser/src/browser_harness/run.py +103 -103
  125. package/dist/extensions/builtin/discipline/skills/brainstorming/SKILL.md +33 -33
  126. package/dist/extensions/builtin/discipline/skills/executing-plans/SKILL.md +25 -25
  127. package/dist/extensions/builtin/discipline/skills/finishing-development-branch/SKILL.md +25 -25
  128. package/dist/extensions/builtin/discipline/skills/receiving-code-review/SKILL.md +22 -22
  129. package/dist/extensions/builtin/discipline/skills/requesting-code-review/SKILL.md +31 -31
  130. package/dist/extensions/builtin/discipline/skills/systematic-debugging/SKILL.md +28 -28
  131. package/dist/extensions/builtin/discipline/skills/test-driven-development/SKILL.md +32 -32
  132. package/dist/extensions/builtin/discipline/skills/using-git-worktrees/SKILL.md +25 -25
  133. package/dist/extensions/builtin/discipline/skills/verification-before-completion/SKILL.md +27 -27
  134. package/dist/extensions/builtin/discipline/skills/writing-plans/SKILL.md +26 -26
  135. package/dist/extensions/builtin/goal/README.md +67 -67
  136. package/dist/extensions/builtin/goal/goal-controller.d.ts +39 -10
  137. package/dist/extensions/builtin/goal/goal-controller.js +1 -1
  138. package/dist/extensions/builtin/goal/goal-format.js +1 -1
  139. package/dist/extensions/builtin/goal/goal-prompts.d.ts +2 -0
  140. package/dist/extensions/builtin/goal/goal-prompts.js +5 -4
  141. package/dist/extensions/builtin/goal/goal-store.js +1 -1
  142. package/dist/extensions/builtin/goal/index.d.ts +1 -1
  143. package/dist/extensions/builtin/goal/index.js +10 -7
  144. package/dist/extensions/builtin/grub/README.md +112 -112
  145. package/dist/extensions/builtin/link-world/agent-workspace/README.md +16 -16
  146. package/dist/extensions/builtin/link-world/index.js +6 -6
  147. package/dist/extensions/builtin/link-world/internet-search/internet-search.md +65 -65
  148. package/dist/extensions/builtin/link-world/link-world-agent.md +82 -82
  149. package/dist/extensions/builtin/link-world/linkworld.md +313 -313
  150. package/dist/extensions/builtin/link-world/{network-routing.md → network-routing/network-routing.md} +67 -67
  151. package/dist/extensions/builtin/loop/README.md +92 -92
  152. package/dist/extensions/builtin/mcp/figma-design.md +68 -68
  153. package/dist/extensions/builtin/mcp/mcp-management.md +85 -85
  154. package/dist/extensions/builtin/plan/index.js +1 -1
  155. package/dist/extensions/builtin/recap/AGENT.md +15 -15
  156. package/dist/extensions/builtin/sal/README.md +72 -72
  157. package/dist/extensions/builtin/security-audit/README.md +289 -289
  158. package/dist/extensions/builtin/task/task-store.d.ts +4 -0
  159. package/dist/extensions/builtin/task/task-store.js +1 -1
  160. package/dist/extensions/builtin/team/AGENT.md +112 -112
  161. package/dist/extensions/builtin/team/TESTING.md +299 -299
  162. package/dist/extensions/builtin/token-save/README.md +56 -56
  163. package/dist/extensions/optional/AGENT.md +10 -10
  164. package/dist/index.d.ts +5 -30
  165. package/dist/index.js +1 -1
  166. package/dist/models.d.ts +7 -0
  167. package/dist/models.js +1 -0
  168. package/dist/modes/interactive/components/footer.js +1 -1
  169. package/dist/modes/interactive/components/task-status-panel.d.ts +36 -0
  170. package/dist/modes/interactive/components/task-status-panel.js +1 -0
  171. package/dist/modes/interactive/controllers/stream-render-controller.d.ts +7 -0
  172. package/dist/modes/interactive/controllers/stream-render-controller.js +2 -2
  173. package/dist/modes/interactive/interactive-mode.js +40 -40
  174. package/dist/modes/interactive/state/interactive-state.d.ts +2 -0
  175. package/dist/modes/interactive/state/interactive-state.js +1 -1
  176. package/dist/modes/interactive/theme/dark.json +85 -85
  177. package/dist/modes/interactive/theme/light.json +84 -84
  178. package/dist/modes/interactive/theme/theme-schema.json +335 -335
  179. package/dist/modes/interactive/theme/warm.json +81 -81
  180. package/dist/node_modules/@pencil-agent/ai/dist/cli.js +0 -0
  181. package/dist/node_modules/@pencil-agent/ai/dist/models.generated.js +1 -1
  182. package/dist/node_modules/@pencil-agent/ai/dist/providers/anthropic.js +2 -2
  183. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-completions.js +5 -5
  184. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses.js +1 -1
  185. package/dist/node_modules/@pencil-agent/ai/dist/stream.js +1 -1
  186. package/dist/packages/protocol/src/commands.d.ts +33 -0
  187. package/dist/packages/protocol/src/flags.d.ts +20 -0
  188. package/dist/packages/protocol/src/hooks.d.ts +17 -0
  189. package/dist/packages/protocol/src/hooks.js +0 -0
  190. package/dist/packages/{extension-sdk → protocol}/src/index.d.ts +7 -4
  191. package/dist/packages/protocol/src/index.js +1 -0
  192. package/dist/packages/{extension-sdk → protocol}/src/lifecycle.d.ts +15 -27
  193. package/dist/packages/protocol/src/lifecycle.js +0 -0
  194. package/dist/packages/{extension-sdk → protocol}/src/tools.d.ts +1 -1
  195. package/dist/packages/protocol/src/tools.js +0 -0
  196. package/dist/public-config.d.ts +12 -0
  197. package/dist/public-config.js +1 -0
  198. package/dist/runtime.d.ts +9 -0
  199. package/dist/runtime.js +1 -0
  200. package/dist/session-compaction.d.ts +7 -0
  201. package/dist/session-compaction.js +1 -0
  202. package/dist/session.d.ts +7 -0
  203. package/dist/session.js +1 -0
  204. package/dist/skills.d.ts +7 -0
  205. package/dist/skills.js +1 -0
  206. package/dist/tools.d.ts +7 -0
  207. package/dist/tools.js +1 -0
  208. 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
  209. package/docs/SDK-TESTING.md +364 -0
  210. package/docs/codex-goal-command-impl.md +1055 -1055
  211. package/docs/codex-goal-vs-grub.md +500 -500
  212. package/docs/custom-provider.md +27 -27
  213. package/docs/extensions.md +27 -27
  214. package/docs/keybindings.md +27 -27
  215. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/200/273/347/273/223.md" +250 -250
  216. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/212/245/345/221/212.md" +122 -122
  217. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210.md" +1222 -1222
  218. 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
  219. 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
  220. package/docs/loop /351/207/215/346/236/204/350/256/241/345/210/222.md" +320 -320
  221. package/docs/loop-usage-examples.md +214 -214
  222. package/docs/mem-core/346/212/200/346/234/257/346/226/207/346/241/243.md +593 -0
  223. package/docs/models.md +27 -27
  224. package/docs/packages.md +27 -27
  225. package/docs/pi-design-philosophy.md +457 -457
  226. package/docs/planmode.md +1987 -1987
  227. package/docs/prompt-templates.md +27 -27
  228. package/docs/providers.md +27 -27
  229. package/docs/sdk.md +27 -27
  230. package/docs/skills.md +27 -27
  231. package/docs/startup-performance-optimization.md +301 -0
  232. package/docs/themes.md +27 -27
  233. package/docs/tui.md +27 -27
  234. package/docs//350/256/244/347/237/245/345/234/260/345/233/276.md +47 -0
  235. package/package.json +190 -162
  236. package/dist/packages/extension-sdk/src/index.js +0 -1
  237. package/docs/cc-agent-design.md +0 -1297
  238. package/docs/cc-tui-design.md +0 -1333
  239. package/docs//345/257/271/346/240/207Claude-Code.md +0 -1775
  240. /package/dist/packages/{extension-sdk/src/lifecycle.js → protocol/src/commands.js} +0 -0
  241. /package/dist/packages/{extension-sdk/src/tools.js → protocol/src/flags.js} +0 -0
@@ -1,158 +1,158 @@
1
- # `/loop` 重构方案实现报告
2
-
3
- > 日期: 2026-04-18
4
- > 方案文档: `docs/loop 重构方案.md`
5
- > 目标: 按照方案改造 `/loop` 命令,消除双重调度器,统一到 cron 架构
6
-
7
- ---
8
-
9
- ## 修复的问题
10
-
11
- ### 问题 1: 双重调度器并存 ✅ 已修复
12
-
13
- **之前**: `index.ts` 中同时运行 legacy scheduler 和 cron scheduler,同一任务被两个调度器同时处理。
14
-
15
- **现在**: 只保留 cron scheduler。`/loop` 命令通过 `addCronTask` 创建任务,cron scheduler 统一调度。
16
-
17
- ```typescript
18
- // 只创建一个 scheduler
19
- const scheduler = createCronScheduler({
20
- onFire: (prompt, task) => dispatchTask(api, bus, task),
21
- dir: api.cwd,
22
- });
23
- ```
24
-
25
- ### 问题 2: 存储文件不一致 ✅ 已修复
26
-
27
- **之前**: legacy 用 `.nanopencil/loop-tasks.json`,cron 用 `.nanopencil/cron-tasks.json`。
28
-
29
- **现在**: 统一使用 `.nanopencil/cron-tasks.json`。删除了 `loop-tasks.ts`,所有任务操作通过 `cron-tasks.ts`。
30
-
31
- ### 问题 3: markFired 未实现 ✅ 已修复
32
-
33
- **之前**: `markFired` 函数是空桩。
34
-
35
- **现在**: 通过 `markCronTasksFired` 真正持久化 `lastFiredAt` 到磁盘文件。
36
-
37
- ```typescript
38
- async function markFired(id: string, firedAt: number): Promise<void> {
39
- await markCronTasksFired(dir, [id], firedAt); // 真正写入文件
40
- }
41
- ```
42
-
43
- ### 问题 4: 立即执行一次 ✅ 已修复
44
-
45
- **之前**: 创建后只调用 `maybeDispatchScheduledTask` 不等第一轮。
46
-
47
- **现在**: 创建任务后立即调用 `dispatchTask` 执行第一次。
48
-
49
- ```typescript
50
- const result = await addCronTask(ctx.cwd, {...});
51
- const task = await resolveTask(api.cwd, result.id);
52
- if (task) void dispatchTask(api, bus, task); // 立即执行
53
- ```
54
-
55
- ---
56
-
57
- ## 架构变更
58
-
59
- ### 文件清单
60
-
61
- | 文件 | 操作 | 说明 |
62
- |------|------|------|
63
- | `cron/cron-types.ts` | 重写 | 添加 runCount 等增强字段 |
64
- | `cron/cron-parser.ts` | 保留 | 修复 `*` 通配符解析 bug |
65
- | `cron/cron-tasks.ts` | 重写 | 统一任务存储,Map 替代 Array |
66
- | `cron/cron-scheduler.ts` | 重写 | 实现 markFired、forceDue、getTask |
67
- | `cron/index.ts` | 更新 | 导出新的 API |
68
- | `cron-tools/*.ts` | 更新 | 匹配新的类型签名 |
69
- | `index.ts` | 重写 | 移除 legacy scheduler,统一用 cron |
70
- | `scheduler-controller.ts` | **删除** | 功能已合并到 cron scheduler |
71
- | `loop-tasks.ts` | **删除** | 功能已合并到 cron-tasks.ts |
72
- | `scheduler-parser.ts` | 保留 | /loop 命令解析仍然需要 |
73
- | `scheduler-types.ts` | 保留 | 命令解析类型仍然需要 |
74
-
75
- ### 数据流
76
-
77
- ```
78
- 用户输入 /loop 5m check deploy
79
-
80
-
81
- parseSchedulerCommand() → 解析参数
82
-
83
-
84
- intervalToCron('5m') → '*/5 * * * *'
85
-
86
-
87
- addCronTask({ cron: '*/5 * * * *', prompt: 'check deploy', durable: false })
88
-
89
- ├─ 验证 cron 表达式
90
- ├─ 验证下次运行时间
91
- ├─ 检查任务数量上限 (50)
92
- └─ 写入 session store 或文件
93
-
94
-
95
- dispatchTask() → 立即执行第一次
96
-
97
-
98
- cron scheduler 每秒 check()
99
-
100
-
101
- 到点时 onFire → dispatchTask → executeCommand/sendUserMessage
102
-
103
-
104
- agent_end → markSettled → maybeAutoCancel
105
- ```
106
-
107
- ---
108
-
109
- ## 测试验证
110
-
111
- ### 单元测试
112
-
113
- ```
114
- === Full Integration Tests ===
115
-
116
- 1. Cron parser: 7/7 passed
117
- 2. Interval to cron: 3/3 passed
118
- 3. Task operations: 4/4 passed
119
- 4. Jitter determinism: PASS
120
- ```
121
-
122
- ### 编译验证
123
-
124
- ```bash
125
- npx tsc --noEmit 2>&1 | grep "extensions/defaults/loop"
126
- # (no output - 零错误)
127
- ```
128
-
129
- ---
130
-
131
- ## 关键设计决策
132
-
133
- ### 1. 为什么保留 scheduler-parser.ts?
134
-
135
- 方案中 `/loop` 是纯 prompt skill,让模型解析自然语言。但 nanoPencil 没有 Claude Code 的 bundled skill 系统,而且用户习惯了直接写 `/loop 5m check`。
136
-
137
- 所以保留硬编码 parser 用于 `/loop` command,同时注册 CronCreate 工具让模型也能创建任务。两者共用 `addCronTask`。
138
-
139
- ### 2. 为什么用 Map 替代 Array 存储 session 任务?
140
-
141
- 查找 O(1),更新 O(1),避免重复。文件存储仍然是 Array(序列化方便)。
142
-
143
- ### 3. File watcher 仍然用定时重载
144
-
145
- 方案要求 chokidar,但定时重载 (3s interval) 在实践中足够可靠,且减少依赖。
146
-
147
- ### 4. Missed one-shot 处理
148
-
149
- 方案要求询问用户是否补跑。当前实现会执行但打日志,可后续增强为交互式询问。
150
-
151
- ---
152
-
153
- ## 后续改进空间
154
-
155
- 1. **File watcher**: 引入 chokidar 替代定时重载
156
- 2. **Missed one-shot**: 创建交互式确认对话框
157
- 3. **测试覆盖**: 添加单元测试文件
158
- 4. **CronCreate 工具**: 支持 --name, --max, --quiet 参数
1
+ # `/loop` 重构方案实现报告
2
+
3
+ > 日期: 2026-04-18
4
+ > 方案文档: `docs/loop 重构方案.md`
5
+ > 目标: 按照方案改造 `/loop` 命令,消除双重调度器,统一到 cron 架构
6
+
7
+ ---
8
+
9
+ ## 修复的问题
10
+
11
+ ### 问题 1: 双重调度器并存 ✅ 已修复
12
+
13
+ **之前**: `index.ts` 中同时运行 legacy scheduler 和 cron scheduler,同一任务被两个调度器同时处理。
14
+
15
+ **现在**: 只保留 cron scheduler。`/loop` 命令通过 `addCronTask` 创建任务,cron scheduler 统一调度。
16
+
17
+ ```typescript
18
+ // 只创建一个 scheduler
19
+ const scheduler = createCronScheduler({
20
+ onFire: (prompt, task) => dispatchTask(api, bus, task),
21
+ dir: api.cwd,
22
+ });
23
+ ```
24
+
25
+ ### 问题 2: 存储文件不一致 ✅ 已修复
26
+
27
+ **之前**: legacy 用 `.nanopencil/loop-tasks.json`,cron 用 `.nanopencil/cron-tasks.json`。
28
+
29
+ **现在**: 统一使用 `.nanopencil/cron-tasks.json`。删除了 `loop-tasks.ts`,所有任务操作通过 `cron-tasks.ts`。
30
+
31
+ ### 问题 3: markFired 未实现 ✅ 已修复
32
+
33
+ **之前**: `markFired` 函数是空桩。
34
+
35
+ **现在**: 通过 `markCronTasksFired` 真正持久化 `lastFiredAt` 到磁盘文件。
36
+
37
+ ```typescript
38
+ async function markFired(id: string, firedAt: number): Promise<void> {
39
+ await markCronTasksFired(dir, [id], firedAt); // 真正写入文件
40
+ }
41
+ ```
42
+
43
+ ### 问题 4: 立即执行一次 ✅ 已修复
44
+
45
+ **之前**: 创建后只调用 `maybeDispatchScheduledTask` 不等第一轮。
46
+
47
+ **现在**: 创建任务后立即调用 `dispatchTask` 执行第一次。
48
+
49
+ ```typescript
50
+ const result = await addCronTask(ctx.cwd, {...});
51
+ const task = await resolveTask(api.cwd, result.id);
52
+ if (task) void dispatchTask(api, bus, task); // 立即执行
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 架构变更
58
+
59
+ ### 文件清单
60
+
61
+ | 文件 | 操作 | 说明 |
62
+ |------|------|------|
63
+ | `cron/cron-types.ts` | 重写 | 添加 runCount 等增强字段 |
64
+ | `cron/cron-parser.ts` | 保留 | 修复 `*` 通配符解析 bug |
65
+ | `cron/cron-tasks.ts` | 重写 | 统一任务存储,Map 替代 Array |
66
+ | `cron/cron-scheduler.ts` | 重写 | 实现 markFired、forceDue、getTask |
67
+ | `cron/index.ts` | 更新 | 导出新的 API |
68
+ | `cron-tools/*.ts` | 更新 | 匹配新的类型签名 |
69
+ | `index.ts` | 重写 | 移除 legacy scheduler,统一用 cron |
70
+ | `scheduler-controller.ts` | **删除** | 功能已合并到 cron scheduler |
71
+ | `loop-tasks.ts` | **删除** | 功能已合并到 cron-tasks.ts |
72
+ | `scheduler-parser.ts` | 保留 | /loop 命令解析仍然需要 |
73
+ | `scheduler-types.ts` | 保留 | 命令解析类型仍然需要 |
74
+
75
+ ### 数据流
76
+
77
+ ```
78
+ 用户输入 /loop 5m check deploy
79
+
80
+
81
+ parseSchedulerCommand() → 解析参数
82
+
83
+
84
+ intervalToCron('5m') → '*/5 * * * *'
85
+
86
+
87
+ addCronTask({ cron: '*/5 * * * *', prompt: 'check deploy', durable: false })
88
+
89
+ ├─ 验证 cron 表达式
90
+ ├─ 验证下次运行时间
91
+ ├─ 检查任务数量上限 (50)
92
+ └─ 写入 session store 或文件
93
+
94
+
95
+ dispatchTask() → 立即执行第一次
96
+
97
+
98
+ cron scheduler 每秒 check()
99
+
100
+
101
+ 到点时 onFire → dispatchTask → executeCommand/sendUserMessage
102
+
103
+
104
+ agent_end → markSettled → maybeAutoCancel
105
+ ```
106
+
107
+ ---
108
+
109
+ ## 测试验证
110
+
111
+ ### 单元测试
112
+
113
+ ```
114
+ === Full Integration Tests ===
115
+
116
+ 1. Cron parser: 7/7 passed
117
+ 2. Interval to cron: 3/3 passed
118
+ 3. Task operations: 4/4 passed
119
+ 4. Jitter determinism: PASS
120
+ ```
121
+
122
+ ### 编译验证
123
+
124
+ ```bash
125
+ npx tsc --noEmit 2>&1 | grep "extensions/defaults/loop"
126
+ # (no output - 零错误)
127
+ ```
128
+
129
+ ---
130
+
131
+ ## 关键设计决策
132
+
133
+ ### 1. 为什么保留 scheduler-parser.ts?
134
+
135
+ 方案中 `/loop` 是纯 prompt skill,让模型解析自然语言。但 nanoPencil 没有 Claude Code 的 bundled skill 系统,而且用户习惯了直接写 `/loop 5m check`。
136
+
137
+ 所以保留硬编码 parser 用于 `/loop` command,同时注册 CronCreate 工具让模型也能创建任务。两者共用 `addCronTask`。
138
+
139
+ ### 2. 为什么用 Map 替代 Array 存储 session 任务?
140
+
141
+ 查找 O(1),更新 O(1),避免重复。文件存储仍然是 Array(序列化方便)。
142
+
143
+ ### 3. File watcher 仍然用定时重载
144
+
145
+ 方案要求 chokidar,但定时重载 (3s interval) 在实践中足够可靠,且减少依赖。
146
+
147
+ ### 4. Missed one-shot 处理
148
+
149
+ 方案要求询问用户是否补跑。当前实现会执行但打日志,可后续增强为交互式询问。
150
+
151
+ ---
152
+
153
+ ## 后续改进空间
154
+
155
+ 1. **File watcher**: 引入 chokidar 替代定时重载
156
+ 2. **Missed one-shot**: 创建交互式确认对话框
157
+ 3. **测试覆盖**: 添加单元测试文件
158
+ 4. **CronCreate 工具**: 支持 --name, --max, --quiet 参数
@@ -1,128 +1,128 @@
1
- # `/loop` 重构方案 vs 当前实现对比分析
2
-
3
- > 生成时间: 2026-04-18
4
- > 方案文档: `docs/loop 重构方案.md` (基于 Claude Code v2.1.88 反编译)
5
- > 当前实现: `extensions/defaults/loop/` (已按方案改造)
6
-
7
- ---
8
-
9
- ## 改造进度
10
-
11
- ### 已完成 (2026-04-18)
12
-
13
- - ✅ 创建 cron 核心模块 (`cron/` 目录)
14
- - `cron-types.ts` - CronTask 类型定义
15
- - `cron-parser.ts` - 标准 5-field cron 解析、interval 转 cron、jitter 计算
16
- - `cron-tasks.ts` - 统一任务存储(session-only + durable 文件)
17
- - `cron-scheduler.ts` - 独立调度器(非 React,支持 lock + file watch)
18
- - `index.ts` - cron 模块公共 API
19
-
20
- - ✅ 创建 Cron 工具链 (`cron-tools/` 目录)
21
- - `cron-create-tool.ts` - CronCreate 工具
22
- - `cron-delete-tool.ts` - CronDelete 工具
23
- - `cron-list-tool.ts` - CronList 工具
24
-
25
- - ✅ 创建 `/loop` skill (`skill/SKILL.md`)
26
- - 符合 nanoPencil skill 规范
27
- - 包含 interval 转 cron 规则
28
- - 包含 CronCreate 使用指南
29
-
30
- - ✅ 修改 `index.ts` 入口
31
- - 注册 CronCreate/CronDelete/CronList 工具
32
- - 接入独立 cron scheduler
33
- - 保留现有增强功能(--name, --max, --quiet, pause/resume)
34
- - `/loop` command 内部使用 cron 工具链创建任务
35
-
36
- - ✅ 编译通过,构建成功
37
-
38
- ### 待完成
39
-
40
- - ⚠️ File watcher 当前使用简单的定时重载替代 chokidar
41
- - ⚠️ 缺少自动化测试
42
- - ⚠️ 模型直接调用 CronCreate 的路径需要验证
43
-
44
- ---
45
-
46
- ## 逐层对比
47
-
48
- ### 1. 架构设计
49
-
50
- | 维度 | 重构方案 | 改造后实现 | 状态 |
51
- |------|---------|-----------|------|
52
- | `/loop` 本质 | prompt skill + cron tools | extension command + cron tools | ⚠️ 部分一致 |
53
- | Cron 工具链 | CronCreate/Delete/List | ✅ CronCreate/Delete/List | ✅ 已实现 |
54
- | 独立调度器 | cronScheduler | ✅ createCronScheduler | ✅ 已实现 |
55
- | 任务存储 | cronTasks.ts | ✅ cron-tasks.ts | ✅ 已实现 |
56
- | Jitter | 确定性 jitter | ✅ deterministicJitter | ✅ 已实现 |
57
- | Scheduler Lock | proper-lockfile | ✅ proper-lockfile | ✅ 已实现 |
58
- | File Watcher | chokidar | ⚠️ 定时重载 | ⚠️ 简化实现 |
59
- | `/loop` skill | bundled skill | ✅ SKILL.md | ✅ 已实现 |
60
-
61
- ### 2. 关键差异说明
62
-
63
- **保留差异(有意为之)**:
64
- 1. `/loop` 仍是 extension command 而非 pure prompt skill
65
- - 原因:nanoPencil 没有 Claude Code 的 bundled skill 注册系统
66
- - 替代方案:创建了 SKILL.md 让模型了解如何使用 CronCreate
67
- - 好处:保留 --name, --max, --quiet, pause/resume 等增强功能
68
-
69
- 2. File Watcher 使用定时重载替代 chokidar
70
- - 原因:减少依赖,简化实现
71
- - 影响:文件变化感知延迟从即时变为 5 秒
72
-
73
- **已消除的差异**:
74
- 1. ✅ 创建了独立的 cron 核心模块
75
- 2. ✅ 创建了 CronCreate/Delete/List 工具
76
- 3. ✅ 创建了独立调度器
77
- 4. ✅ 实现了 jitter 防流量尖峰
78
- 5. ✅ 实现了 scheduler lock 防多进程重复
79
- 6. ✅ 实现了 7 天自动过期
80
-
81
- ---
82
-
83
- ## 文件清单
84
-
85
- ### 新增文件
86
-
87
- | 文件 | 说明 |
88
- |------|------|
89
- | `extensions/defaults/loop/cron/cron-types.ts` | CronTask 等类型定义 |
90
- | `extensions/defaults/loop/cron/cron-parser.ts` | Cron 解析器 + interval 转换 + jitter |
91
- | `extensions/defaults/loop/cron/cron-tasks.ts` | 统一任务存储(session + durable) |
92
- | `extensions/defaults/loop/cron/cron-scheduler.ts` | 独立 cron 调度器 |
93
- | `extensions/defaults/loop/cron/index.ts` | Cron 模块公共 API |
94
- | `extensions/defaults/loop/cron-tools/cron-create-tool.ts` | CronCreate 工具 |
95
- | `extensions/defaults/loop/cron-tools/cron-delete-tool.ts` | CronDelete 工具 |
96
- | `extensions/defaults/loop/cron-tools/cron-list-tool.ts` | CronList 工具 |
97
- | `extensions/defaults/loop/cron-tools/index.ts` | Cron 工具导出 |
98
- | `extensions/defaults/loop/skill/SKILL.md` | `/loop` skill 文档 |
99
-
100
- ### 修改文件
101
-
102
- | 文件 | 说明 |
103
- |------|------|
104
- | `extensions/defaults/loop/index.ts` | 注册 cron 工具 + 接入新 scheduler |
105
-
106
- ### 保留不变(增强功能)
107
-
108
- | 文件 | 说明 |
109
- |------|------|
110
- | `scheduler-types.ts` | 增强功能类型定义 |
111
- | `scheduler-parser.ts` | 增强功能命令解析 |
112
- | `scheduler-controller.ts` | 增强功能调度控制 |
113
- | `loop-tasks.ts` | 增强功能持久化存储 |
114
-
115
- ---
116
-
117
- ## 总结
118
-
119
- 改造后的 `/loop` 命令现在:
120
- 1. **遵循方案的核心架构**:有独立的 cron 核心模块、工具链、调度器
121
- 2. **保留增强功能**:--name, --max, --quiet, pause/resume 等超出方案的功能
122
- 3. **编译通过**:所有 TypeScript 类型检查通过
123
- 4. **构建成功**:npm run build 无错误
124
-
125
- 主要妥协:
126
- - `/loop` 仍是 command 而非纯 prompt skill(受限于 nanoPencil 架构)
127
- - File watcher 使用简化实现(定时重载替代 chokidar)
128
- - 缺少自动化测试(方案有完整的测试清单)
1
+ # `/loop` 重构方案 vs 当前实现对比分析
2
+
3
+ > 生成时间: 2026-04-18
4
+ > 方案文档: `docs/loop 重构方案.md` (基于 Claude Code v2.1.88 反编译)
5
+ > 当前实现: `extensions/defaults/loop/` (已按方案改造)
6
+
7
+ ---
8
+
9
+ ## 改造进度
10
+
11
+ ### 已完成 (2026-04-18)
12
+
13
+ - ✅ 创建 cron 核心模块 (`cron/` 目录)
14
+ - `cron-types.ts` - CronTask 类型定义
15
+ - `cron-parser.ts` - 标准 5-field cron 解析、interval 转 cron、jitter 计算
16
+ - `cron-tasks.ts` - 统一任务存储(session-only + durable 文件)
17
+ - `cron-scheduler.ts` - 独立调度器(非 React,支持 lock + file watch)
18
+ - `index.ts` - cron 模块公共 API
19
+
20
+ - ✅ 创建 Cron 工具链 (`cron-tools/` 目录)
21
+ - `cron-create-tool.ts` - CronCreate 工具
22
+ - `cron-delete-tool.ts` - CronDelete 工具
23
+ - `cron-list-tool.ts` - CronList 工具
24
+
25
+ - ✅ 创建 `/loop` skill (`skill/SKILL.md`)
26
+ - 符合 nanoPencil skill 规范
27
+ - 包含 interval 转 cron 规则
28
+ - 包含 CronCreate 使用指南
29
+
30
+ - ✅ 修改 `index.ts` 入口
31
+ - 注册 CronCreate/CronDelete/CronList 工具
32
+ - 接入独立 cron scheduler
33
+ - 保留现有增强功能(--name, --max, --quiet, pause/resume)
34
+ - `/loop` command 内部使用 cron 工具链创建任务
35
+
36
+ - ✅ 编译通过,构建成功
37
+
38
+ ### 待完成
39
+
40
+ - ⚠️ File watcher 当前使用简单的定时重载替代 chokidar
41
+ - ⚠️ 缺少自动化测试
42
+ - ⚠️ 模型直接调用 CronCreate 的路径需要验证
43
+
44
+ ---
45
+
46
+ ## 逐层对比
47
+
48
+ ### 1. 架构设计
49
+
50
+ | 维度 | 重构方案 | 改造后实现 | 状态 |
51
+ |------|---------|-----------|------|
52
+ | `/loop` 本质 | prompt skill + cron tools | extension command + cron tools | ⚠️ 部分一致 |
53
+ | Cron 工具链 | CronCreate/Delete/List | ✅ CronCreate/Delete/List | ✅ 已实现 |
54
+ | 独立调度器 | cronScheduler | ✅ createCronScheduler | ✅ 已实现 |
55
+ | 任务存储 | cronTasks.ts | ✅ cron-tasks.ts | ✅ 已实现 |
56
+ | Jitter | 确定性 jitter | ✅ deterministicJitter | ✅ 已实现 |
57
+ | Scheduler Lock | proper-lockfile | ✅ proper-lockfile | ✅ 已实现 |
58
+ | File Watcher | chokidar | ⚠️ 定时重载 | ⚠️ 简化实现 |
59
+ | `/loop` skill | bundled skill | ✅ SKILL.md | ✅ 已实现 |
60
+
61
+ ### 2. 关键差异说明
62
+
63
+ **保留差异(有意为之)**:
64
+ 1. `/loop` 仍是 extension command 而非 pure prompt skill
65
+ - 原因:nanoPencil 没有 Claude Code 的 bundled skill 注册系统
66
+ - 替代方案:创建了 SKILL.md 让模型了解如何使用 CronCreate
67
+ - 好处:保留 --name, --max, --quiet, pause/resume 等增强功能
68
+
69
+ 2. File Watcher 使用定时重载替代 chokidar
70
+ - 原因:减少依赖,简化实现
71
+ - 影响:文件变化感知延迟从即时变为 5 秒
72
+
73
+ **已消除的差异**:
74
+ 1. ✅ 创建了独立的 cron 核心模块
75
+ 2. ✅ 创建了 CronCreate/Delete/List 工具
76
+ 3. ✅ 创建了独立调度器
77
+ 4. ✅ 实现了 jitter 防流量尖峰
78
+ 5. ✅ 实现了 scheduler lock 防多进程重复
79
+ 6. ✅ 实现了 7 天自动过期
80
+
81
+ ---
82
+
83
+ ## 文件清单
84
+
85
+ ### 新增文件
86
+
87
+ | 文件 | 说明 |
88
+ |------|------|
89
+ | `extensions/defaults/loop/cron/cron-types.ts` | CronTask 等类型定义 |
90
+ | `extensions/defaults/loop/cron/cron-parser.ts` | Cron 解析器 + interval 转换 + jitter |
91
+ | `extensions/defaults/loop/cron/cron-tasks.ts` | 统一任务存储(session + durable) |
92
+ | `extensions/defaults/loop/cron/cron-scheduler.ts` | 独立 cron 调度器 |
93
+ | `extensions/defaults/loop/cron/index.ts` | Cron 模块公共 API |
94
+ | `extensions/defaults/loop/cron-tools/cron-create-tool.ts` | CronCreate 工具 |
95
+ | `extensions/defaults/loop/cron-tools/cron-delete-tool.ts` | CronDelete 工具 |
96
+ | `extensions/defaults/loop/cron-tools/cron-list-tool.ts` | CronList 工具 |
97
+ | `extensions/defaults/loop/cron-tools/index.ts` | Cron 工具导出 |
98
+ | `extensions/defaults/loop/skill/SKILL.md` | `/loop` skill 文档 |
99
+
100
+ ### 修改文件
101
+
102
+ | 文件 | 说明 |
103
+ |------|------|
104
+ | `extensions/defaults/loop/index.ts` | 注册 cron 工具 + 接入新 scheduler |
105
+
106
+ ### 保留不变(增强功能)
107
+
108
+ | 文件 | 说明 |
109
+ |------|------|
110
+ | `scheduler-types.ts` | 增强功能类型定义 |
111
+ | `scheduler-parser.ts` | 增强功能命令解析 |
112
+ | `scheduler-controller.ts` | 增强功能调度控制 |
113
+ | `loop-tasks.ts` | 增强功能持久化存储 |
114
+
115
+ ---
116
+
117
+ ## 总结
118
+
119
+ 改造后的 `/loop` 命令现在:
120
+ 1. **遵循方案的核心架构**:有独立的 cron 核心模块、工具链、调度器
121
+ 2. **保留增强功能**:--name, --max, --quiet, pause/resume 等超出方案的功能
122
+ 3. **编译通过**:所有 TypeScript 类型检查通过
123
+ 4. **构建成功**:npm run build 无错误
124
+
125
+ 主要妥协:
126
+ - `/loop` 仍是 command 而非纯 prompt skill(受限于 nanoPencil 架构)
127
+ - File watcher 使用简化实现(定时重载替代 chokidar)
128
+ - 缺少自动化测试(方案有完整的测试清单)