@xiaobuyu/nodesign 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/README.md +156 -106
  2. package/bin/nodesign.js +0 -0
  3. package/package.json +1 -1
  4. package/server/api/README.md +45 -45
  5. package/server/api/_guard.js +75 -75
  6. package/server/api/admin.js +187 -187
  7. package/server/api/assets/docx-page.js +103 -103
  8. package/server/api/assets/helpers.js +42 -22
  9. package/server/api/assets/notes.js +194 -144
  10. package/server/api/assets.js +891 -896
  11. package/server/api/board.js +134 -57
  12. package/server/api/browse.js +138 -138
  13. package/server/api/canvas.js +444 -444
  14. package/server/api/chatai.js +324 -324
  15. package/server/api/exports/build-standalone.js +980 -980
  16. package/server/api/exports/cards.js +118 -118
  17. package/server/api/exports/docx-pdf.js +46 -46
  18. package/server/api/exports/export-page.js +142 -142
  19. package/server/api/exports/handoff.js +147 -147
  20. package/server/api/exports.js +690 -690
  21. package/server/api/instruction.js +75 -75
  22. package/server/api/me.js +116 -116
  23. package/server/api/memory.js +185 -185
  24. package/server/api/pending-changes.js +366 -366
  25. package/server/api/plugins.js +164 -164
  26. package/server/api/projects.js +220 -220
  27. package/server/api/publish.js +64 -64
  28. package/server/api/recent.js +73 -73
  29. package/server/api/sessions.js +589 -589
  30. package/server/api/skills.js +77 -77
  31. package/server/api/standalone-fit.js +168 -168
  32. package/server/api/turn-compose.js +180 -180
  33. package/server/api/turn-inflight.js +44 -44
  34. package/server/auth/README.md +17 -17
  35. package/server/auth/middleware.js +138 -138
  36. package/server/auth/origin-guard.js +71 -71
  37. package/server/auth/session.js +108 -108
  38. package/server/auth/tier.js +113 -113
  39. package/server/auth/users-store.js +348 -348
  40. package/server/edit/README.md +29 -29
  41. package/server/engine/README.md +113 -113
  42. package/server/engine/agent/agent-shared.js +550 -550
  43. package/server/engine/agent/auto-mode-default-hard-deny.txt +4 -4
  44. package/server/engine/agent/auto-mode-rules.js +78 -78
  45. package/server/engine/agent/context.js +418 -418
  46. package/server/engine/agent/events.js +465 -464
  47. package/server/engine/agent/hooks/canvas-validate.js +199 -199
  48. package/server/engine/agent/hooks/failure.js +120 -120
  49. package/server/engine/agent/hooks/file-events.js +75 -75
  50. package/server/engine/agent/hooks/lifecycle.js +233 -233
  51. package/server/engine/agent/hooks/post-canvas-focus.js +80 -80
  52. package/server/engine/agent/hooks/post-guidance.js +206 -206
  53. package/server/engine/agent/hooks/post-subagent-report.js +104 -104
  54. package/server/engine/agent/hooks/post-trim.js +58 -58
  55. package/server/engine/agent/hooks/pre-board-neighborhood.js +34 -34
  56. package/server/engine/agent/hooks/pre-defaults.js +84 -84
  57. package/server/engine/agent/hooks/pre-injectors.js +277 -277
  58. package/server/engine/agent/hooks/pre-performance-log-guard.js +78 -78
  59. package/server/engine/agent/hooks/pre-starter-files.js +61 -61
  60. package/server/engine/agent/hooks/pre-workspace-scope-guard.js +78 -78
  61. package/server/engine/agent/hooks/site-validate.js +94 -94
  62. package/server/engine/agent/hooks/tool-prompts.js +31 -31
  63. package/server/engine/agent/hooks/turn-state-memory.js +56 -56
  64. package/server/engine/agent/hooks/user-prompt-submit.js +258 -215
  65. package/server/engine/agent/hooks.js +354 -354
  66. package/server/engine/agent/init-contract.js +69 -69
  67. package/server/engine/agent/isolation.js +159 -159
  68. package/server/engine/agent/model-table.js +292 -292
  69. package/server/engine/agent/plugin-loader.js +266 -266
  70. package/server/engine/agent/prompts/nodesign-prelude.md +388 -336
  71. package/server/engine/agent/prompts/tools/ask-user-question-protocol.md +71 -71
  72. package/server/engine/agent/prompts/tools/direct-edit-protocol.md +98 -98
  73. package/server/engine/agent/prompts/tools/generate-image-cookbook.gemini-gateway.md +583 -583
  74. package/server/engine/agent/prompts/tools/generate-image-cookbook.md +483 -483
  75. package/server/engine/agent/prompts/tools/hybrid-reference.md +100 -100
  76. package/server/engine/agent/prompts/tools/paint-still-cookbook.md +270 -270
  77. package/server/engine/agent/prompts/tools/roll-film-cookbook.md +70 -70
  78. package/server/engine/agent/prompts/tools/site-reference.md +106 -106
  79. package/server/engine/agent/prompts/tools/tweaks-syntax.md +125 -125
  80. package/server/engine/agent/prompts/tools/vision-checker-dispatch.md +48 -48
  81. package/server/engine/agent/session-loop.js +1035 -1024
  82. package/server/engine/agent/session-model.js +164 -164
  83. package/server/engine/agent/skill.js +204 -204
  84. package/server/engine/agent/task-events.js +78 -78
  85. package/server/engine/agents/ds-extractor.md +132 -132
  86. package/server/engine/agents/explorer.md +190 -190
  87. package/server/engine/agents/index.js +230 -230
  88. package/server/engine/agents/schemas/design-system.json +156 -156
  89. package/server/engine/agents/schemas/tweak-schema.json +113 -113
  90. package/server/engine/agents/tweak-proposer.md +127 -127
  91. package/server/engine/agents/vision-checker.md +254 -254
  92. package/server/engine/browse/capture.js +422 -422
  93. package/server/engine/browse/card.js +137 -137
  94. package/server/engine/browse/handover.js +59 -59
  95. package/server/engine/browse/page-digest.js +119 -119
  96. package/server/engine/browse/refs.js +196 -196
  97. package/server/engine/browse/registry.js +307 -307
  98. package/server/engine/browse/screencast.js +170 -170
  99. package/server/engine/browse/state.js +121 -121
  100. package/server/engine/chatai/chat-log.js +79 -79
  101. package/server/engine/chatai/index.js +193 -193
  102. package/server/engine/chatai/openai-compat.js +152 -152
  103. package/server/engine/chatai/orchestrate.js +309 -309
  104. package/server/engine/chatai/perform.js +40 -40
  105. package/server/engine/chatai/summarize.js +79 -79
  106. package/server/engine/mcp/capability-gate.js +52 -52
  107. package/server/engine/mcp/index.js +351 -339
  108. package/server/engine/mcp/param-sanitizer.js +142 -142
  109. package/server/engine/mcp/tools/arrange-on-board.js +124 -124
  110. package/server/engine/mcp/tools/artifact-session.js +278 -278
  111. package/server/engine/mcp/tools/browse-computer.js +421 -421
  112. package/server/engine/mcp/tools/browse-find-batch.js +183 -183
  113. package/server/engine/mcp/tools/browse-screenshot.js +157 -157
  114. package/server/engine/mcp/tools/browse.js +480 -480
  115. package/server/engine/mcp/tools/build-docx.js +101 -101
  116. package/server/engine/mcp/tools/clear-pending-changes.js +99 -99
  117. package/server/engine/mcp/tools/create-on-board.js +152 -155
  118. package/server/engine/mcp/tools/crystallize-skill.js +168 -168
  119. package/server/engine/mcp/tools/edit-sketch.js +167 -0
  120. package/server/engine/mcp/tools/explain-style.js +237 -237
  121. package/server/engine/mcp/tools/export-handoff.js +133 -133
  122. package/server/engine/mcp/tools/expose-tweaks.js +149 -149
  123. package/server/engine/mcp/tools/generate-image.js +842 -842
  124. package/server/engine/mcp/tools/get-computed-styles.js +164 -164
  125. package/server/engine/mcp/tools/get-pending-changes.js +205 -205
  126. package/server/engine/mcp/tools/h3box-ssh.js +84 -84
  127. package/server/engine/mcp/tools/helpers/acquire-page.js +82 -82
  128. package/server/engine/mcp/tools/helpers/motion-lab.js +554 -554
  129. package/server/engine/mcp/tools/helpers/motion-scroll.js +112 -112
  130. package/server/engine/mcp/tools/helpers/perception-page.js +215 -215
  131. package/server/engine/mcp/tools/helpers/reference-download.js +103 -103
  132. package/server/engine/mcp/tools/helpers/rembg-bridge.py +80 -80
  133. package/server/engine/mcp/tools/helpers/shot-pipeline.js +280 -280
  134. package/server/engine/mcp/tools/highlight.js +68 -68
  135. package/server/engine/mcp/tools/list-pages.js +222 -222
  136. package/server/engine/mcp/tools/look-at-board.js +124 -0
  137. package/server/engine/mcp/tools/lookup-tags.js +59 -59
  138. package/server/engine/mcp/tools/navigate-to-page.js +60 -60
  139. package/server/engine/mcp/tools/organize-board.js +64 -64
  140. package/server/engine/mcp/tools/paint-still.js +434 -434
  141. package/server/engine/mcp/tools/pin-to-board.js +130 -130
  142. package/server/engine/mcp/tools/preview-deck.js +130 -130
  143. package/server/engine/mcp/tools/profile-scroll.js +305 -305
  144. package/server/engine/mcp/tools/publish-site.js +102 -102
  145. package/server/engine/mcp/tools/query-elements.js +195 -195
  146. package/server/engine/mcp/tools/read-board.js +190 -103
  147. package/server/engine/mcp/tools/read-document.js +93 -93
  148. package/server/engine/mcp/tools/read-page.js +264 -264
  149. package/server/engine/mcp/tools/read-tavern-json.js +143 -143
  150. package/server/engine/mcp/tools/read-user-view.js +59 -0
  151. package/server/engine/mcp/tools/record-decision.js +140 -140
  152. package/server/engine/mcp/tools/relate-on-board.js +112 -110
  153. package/server/engine/mcp/tools/report-issue.js +115 -115
  154. package/server/engine/mcp/tools/roll-film.js +266 -266
  155. package/server/engine/mcp/tools/screenshot-docx.js +138 -138
  156. package/server/engine/mcp/tools/screenshot-url.js +195 -195
  157. package/server/engine/mcp/tools/screenshot.js +583 -583
  158. package/server/engine/mcp/tools/sketch-on-board.js +337 -0
  159. package/server/engine/mcp/tools/tier-gate.js +96 -96
  160. package/server/engine/mcp/tools/trace-motion.js +215 -215
  161. package/server/engine/mcp/tools/web-search.js +548 -548
  162. package/server/engine/mcp/tools/write-on-board.js +130 -0
  163. package/server/engine/motion/inventory.js +349 -349
  164. package/server/engine/perception/session.js +235 -235
  165. package/server/engine/plugins/nodesign/.claude-plugin/plugin.json +5 -5
  166. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/SKILL.md +199 -192
  167. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/canvas.template.html +667 -667
  168. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/hybrid-grid.md +22 -22
  169. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/image-led-cover.md +25 -25
  170. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/portrait.md +23 -23
  171. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/quote-backdrop.md +21 -21
  172. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/section-divider.md +23 -23
  173. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/text-led.md +21 -21
  174. package/server/engine/plugins/nodesign/skills/docx-craft/SKILL.md +169 -162
  175. package/server/engine/plugins/nodesign/skills/docx-craft/references/token-schema.md +407 -407
  176. package/server/engine/plugins/nodesign/skills/docx-craft//346/226/207/346/241/243.template.json +80 -80
  177. package/server/engine/plugins/nodesign/skills/rp-craft/SKILL.md +235 -228
  178. package/server/engine/plugins/nodesign/skills/rp-craft/patterns//346/274/224/345/207/272/351/241/265-/346/234/200/345/260/217/345/256/236/347/216/260.html +78 -78
  179. package/server/engine/plugins/nodesign/skills/rp-craft//346/274/224/345/207/272.template.js +268 -268
  180. package/server/engine/plugins/nodesign/skills/site-craft/SKILL.md +330 -323
  181. package/server/engine/plugins/nodesign/skills/site-craft/patterns/build-lane.md +134 -134
  182. package/server/engine/plugins/nodesign/skills/site-craft/patterns/cutout-collage.md +61 -61
  183. package/server/engine/plugins/nodesign/skills/site-craft/patterns/mock-app.md +163 -163
  184. package/server/engine/plugins/nodesign/skills/site-craft/patterns/page-transitions.md +86 -86
  185. package/server/engine/runs/active-runs.js +698 -698
  186. package/server/engine/runs/board-tasklist.js +130 -0
  187. package/server/engine/runs/live-turn.js +252 -252
  188. package/server/engine/runs/store.js +364 -364
  189. package/server/engine/runs/turn-relay.js +217 -217
  190. package/server/engine/runtime/workspace.js +164 -164
  191. package/server/index.js +3 -0
  192. package/server/lib/artifact-file-path.js +80 -80
  193. package/server/lib/artifact-target.js +284 -284
  194. package/server/lib/asset-refs.js +239 -239
  195. package/server/lib/async-queue.js +104 -104
  196. package/server/lib/auto-relations.js +130 -130
  197. package/server/lib/binding-types.js +72 -60
  198. package/server/lib/board-graph-export.js +191 -0
  199. package/server/lib/board-groups.js +167 -0
  200. package/server/lib/board-hero.js +76 -0
  201. package/server/lib/board-kind-sizes.js +85 -62
  202. package/server/lib/board-relations.js +133 -133
  203. package/server/lib/browse-proxy.js +180 -180
  204. package/server/lib/canvas-id.js +36 -36
  205. package/server/lib/chalk.js +121 -0
  206. package/server/lib/cover.js +227 -227
  207. package/server/lib/danbooru-tags.js +291 -291
  208. package/server/lib/doc-extract.js +156 -156
  209. package/server/lib/docx/build-from-source.js +260 -260
  210. package/server/lib/docx/build.js +490 -490
  211. package/server/lib/docx/dump-styles.js +287 -287
  212. package/server/lib/docx/fonts/nodesign-cjk.conf +164 -164
  213. package/server/lib/docx/merge-runs.js +129 -129
  214. package/server/lib/docx/numbering.js +218 -218
  215. package/server/lib/docx/order.js +152 -152
  216. package/server/lib/docx/rawzip.js +172 -172
  217. package/server/lib/docx/render.js +92 -92
  218. package/server/lib/docx/text-lint.js +225 -225
  219. package/server/lib/docx/tokens.js +335 -335
  220. package/server/lib/docx/units.js +29 -29
  221. package/server/lib/docx/xml.js +291 -291
  222. package/server/lib/docx-pages.js +187 -187
  223. package/server/lib/export-collect.js +289 -289
  224. package/server/lib/export-package.js +210 -210
  225. package/server/lib/html-srcset.js +145 -145
  226. package/server/lib/image-variant.js +460 -460
  227. package/server/lib/ingress/forward-openai-chat.js +305 -305
  228. package/server/lib/ingress/openai-chat.js +491 -491
  229. package/server/lib/ingress/session-notice.js +66 -66
  230. package/server/lib/ingress/session-routes.js +68 -68
  231. package/server/lib/ingress/slot-probe.js +130 -130
  232. package/server/lib/ingress/upstream-billing.js +52 -52
  233. package/server/lib/ingress/upstream-fail-streak.js +72 -72
  234. package/server/lib/ingress/upstream-truncation.js +48 -48
  235. package/server/lib/issues-store.js +182 -182
  236. package/server/lib/kinds/deck.js +72 -72
  237. package/server/lib/kinds/docx.js +283 -283
  238. package/server/lib/kinds/file-kinds.js +113 -113
  239. package/server/lib/kinds/index.js +202 -202
  240. package/server/lib/kinds/site.js +161 -161
  241. package/server/lib/model-ingress.js +543 -543
  242. package/server/lib/moderation.js +255 -255
  243. package/server/lib/notice-store.js +103 -103
  244. package/server/lib/plugin-install.js +104 -104
  245. package/server/lib/plugin-validator.js +721 -721
  246. package/server/lib/publish-store.js +115 -115
  247. package/server/lib/quick-summary.js +52 -52
  248. package/server/lib/quota.js +270 -270
  249. package/server/lib/rate-window.js +29 -29
  250. package/server/lib/reference-assets.js +92 -92
  251. package/server/lib/region-shot.js +135 -135
  252. package/server/lib/safe-path.js +73 -73
  253. package/server/lib/sdk-session.js +33 -33
  254. package/server/lib/showcase-store.js +92 -92
  255. package/server/lib/site-publish.js +465 -465
  256. package/server/lib/sketch-layout.js +277 -0
  257. package/server/lib/ssrf-guard.js +432 -432
  258. package/server/lib/task-scan.js +158 -158
  259. package/server/lib/tavern-json.js +154 -154
  260. package/server/lib/video-variant.js +237 -237
  261. package/server/lib/workspace-path.js +33 -33
  262. package/server/ops/fix-sdk-musl.mjs +40 -40
  263. package/server/ops/install-macos-fonts.sh +114 -114
  264. package/server/ops/macos-fonts.conf +336 -336
  265. package/server/ops/sandbox-shim/bwrap +57 -57
  266. package/server/projects/assets-summary.js +119 -119
  267. package/server/projects/auto-name.js +53 -53
  268. package/server/projects/board-limits.js +12 -0
  269. package/server/projects/board-sanitize.js +252 -0
  270. package/server/projects/board-store.js +507 -640
  271. package/server/projects/move-entry.js +103 -103
  272. package/server/projects/store.js +270 -270
  273. package/server/projects/ui-config.js +60 -54
  274. package/server/projects/viewpoint-store.js +78 -0
  275. package/server/projects/workspace-templates.js +53 -53
  276. package/server/projects/workspace.js +1025 -1025
  277. package/server/runtime/local-config.js +177 -177
  278. package/server/runtime/profile.js +72 -72
  279. package/server/services/rembg-service.py +334 -334
  280. package/server/shared/README.md +25 -25
  281. package/server/shared/deck.js +54 -54
  282. package/server/shared/time.js +49 -49
  283. package/server/style-pipeline/README.md +53 -53
  284. package/server/ws/broker.js +39 -36
  285. package/server/ws/browse-channel.js +177 -177
  286. package/server/ws/index.js +386 -386
  287. package/web/README.md +89 -89
  288. package/web/dist/assets/BrowserWindow-P_vIdh-G.js +11 -0
  289. package/web/dist/assets/{DeckWindow-4G0xX7P3.js → DeckWindow-BpLv5082.js} +3 -3
  290. package/web/dist/assets/{DocxWindow-BXQsoPkh.js → DocxWindow-DSAU1-tD.js} +4 -4
  291. package/web/dist/assets/MermaidBlock-DR1GikCv.js +313 -0
  292. package/web/dist/assets/SiteWindow-92uBuRRR.js +18 -0
  293. package/web/dist/assets/abnfDiagram-VCTEODGH-uA8Esix4.js +1 -0
  294. package/web/dist/assets/arc-D_khH_xN.js +1 -0
  295. package/web/dist/assets/architectureDiagram-5GKGNRK7-DydJHqOt.js +36 -0
  296. package/web/dist/assets/blockDiagram-NRAW4CY4-B7wBbKiW.js +129 -0
  297. package/web/dist/assets/c4Diagram-UCG6FXSJ-6mrH0x7Y.js +38 -0
  298. package/web/dist/assets/channel-DGkccMO1.js +1 -0
  299. package/web/dist/assets/chunk-2Q5K7J3B-Cuikho5Q.js +1 -0
  300. package/web/dist/assets/chunk-5VM5RSS4-3-KZ5AUz.js +15 -0
  301. package/web/dist/assets/chunk-F27PBJKO-Bkwq2gGU.js +1 -0
  302. package/web/dist/assets/chunk-G27WJ6UU-BLyQzdGE.js +231 -0
  303. package/web/dist/assets/chunk-JWPE2WC7-B7HxxQds.js +1 -0
  304. package/web/dist/assets/chunk-LCL6LL3I-CtXrnUwF.js +206 -0
  305. package/web/dist/assets/chunk-POPQ4Y6H-dxddZlXt.js +1 -0
  306. package/web/dist/assets/chunk-SVP7TREG-DpkmrgHn.js +88 -0
  307. package/web/dist/assets/chunk-XXDRQBXY-BwZ7RbpQ.js +1 -0
  308. package/web/dist/assets/classDiagram-DTDB5LWJ-BGscw3OD.js +1 -0
  309. package/web/dist/assets/classDiagram-v2-JRS7N3AN-BGscw3OD.js +1 -0
  310. package/web/dist/assets/cose-bilkent-JH36ORCC-DGFOsMUt.js +1 -0
  311. package/web/dist/assets/cynefin-OW5HDTMX-DUwn3ehS.js +178 -0
  312. package/web/dist/assets/cynefinDiagram-5FMLGOSQ-DlLAOZ9x.js +62 -0
  313. package/web/dist/assets/cytoscape.esm-BjAbmLdb.js +331 -0
  314. package/web/dist/assets/dagre-3AP2YEHR-CyourLfz.js +4 -0
  315. package/web/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  316. package/web/dist/assets/diagram-S7CK7UJ4-BTMbx2np.js +30 -0
  317. package/web/dist/assets/diagram-UQ7AKVKN-UK94_1-P.js +41 -0
  318. package/web/dist/assets/diagram-VSXAHHWV-C7zS-v9v.js +3 -0
  319. package/web/dist/assets/diagram-VX7I27RA-DKJRa6CK.js +24 -0
  320. package/web/dist/assets/diagram-Z3DM3KII-kUbAfGAp.js +24 -0
  321. package/web/dist/assets/ebnfDiagram-PWID7BFC-CVW16_vb.js +1 -0
  322. package/web/dist/assets/erDiagram-SSCWMZ5O-BRQMFQ5y.js +99 -0
  323. package/web/dist/assets/flowDiagram-A5DVABFB-S34LpLtK.js +168 -0
  324. package/web/dist/assets/ganttDiagram-EL5Y4UJY-BFiqk1-G.js +292 -0
  325. package/web/dist/assets/gitGraphDiagram-WWUBYQGX-LZsrdyyv.js +106 -0
  326. package/web/dist/assets/index-GAamh1p4.js +2152 -0
  327. package/web/dist/assets/infoDiagram-RXCK75RN-0DvN6KIp.js +2 -0
  328. package/web/dist/assets/init-Gi6I4Gst.js +1 -0
  329. package/web/dist/assets/ishikawaDiagram-5VMMS53U-CaY3A-Bx.js +70 -0
  330. package/web/dist/assets/journeyDiagram-EYS64GPL-BBeiaCrj.js +139 -0
  331. package/web/dist/assets/kanban-definition-3QL26DDD-ux42DRXQ.js +89 -0
  332. package/web/dist/assets/layout-CnXiF_NB.js +1 -0
  333. package/web/dist/assets/linear-BMW0u6G6.js +1 -0
  334. package/web/dist/assets/mindmap-definition-FBJOCRG2-hUxSpdKn.js +96 -0
  335. package/web/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  336. package/web/dist/assets/pegDiagram-XKGWAZYB-aCaQPH0w.js +1 -0
  337. package/web/dist/assets/{pending-edit-apply-DTjo2geW.js → pending-edit-apply-AcdOQ9Ij.js} +6 -6
  338. package/web/dist/assets/pieDiagram-E7YTZNPT-CmOEZ8zg.js +39 -0
  339. package/web/dist/assets/quadrantDiagram-AXDQQJYC-VW6fAhsV.js +7 -0
  340. package/web/dist/assets/railroadDiagram-O6MQD6OU-CKJ7Ba5K.js +1 -0
  341. package/web/dist/assets/requirementDiagram-EFPCY7ZU-pNGkq9Vw.js +84 -0
  342. package/web/dist/assets/{rotate-cw-LMT3x1Zj.js → rotate-cw-KAfChbGV.js} +1 -1
  343. package/web/dist/assets/sankeyDiagram-P5KCCOFB-BIMmDTfZ.js +40 -0
  344. package/web/dist/assets/sequenceDiagram-WJ2MYXX4-BBW7wzKY.js +162 -0
  345. package/web/dist/assets/sizeCapture-X5ZJPWSS-DdkXmLYR.js +1 -0
  346. package/web/dist/assets/{square-dashed-mouse-pointer-CBoAkfhi.js → square-dashed-mouse-pointer-CDUlhUP7.js} +1 -1
  347. package/web/dist/assets/stateDiagram-HBIQ2CUA-W313Uz16.js +1 -0
  348. package/web/dist/assets/stateDiagram-v2-4QOOHH4V-DDhJBZzf.js +1 -0
  349. package/web/dist/assets/swimlanes-XN3QIQJK-C29TL26K.js +1 -0
  350. package/web/dist/assets/swimlanesDiagram-VK2B7HYN-BfN-Xdmu.js +8 -0
  351. package/web/dist/assets/timeline-definition-24CTP7MA-CF0JMObX.js +120 -0
  352. package/web/dist/assets/vennDiagram-4TSXK5OY-DrDFsaH3.js +34 -0
  353. package/web/dist/assets/wardleyDiagram-VM6X3IG4-CVrnRIS_.js +78 -0
  354. package/web/dist/assets/xychartDiagram-S5SC5T6Z-BvkN1zsT.js +7 -0
  355. package/web/dist/index.html +17 -17
  356. package/web/dist/assets/BrowserWindow-Dc7J7CYc.js +0 -11
  357. package/web/dist/assets/SiteWindow-D6eS-2gM.js +0 -18
  358. package/web/dist/assets/index-Cbl3ATvp.js +0 -2125
@@ -1,233 +1,233 @@
1
- /**
2
- * 会话生命周期族:SessionStart / Stop / PostCompact / SubagentStart / SubagentStop。
3
- * (2026-08-14 可维护性行动:从 hooks.js 原样迁出,语义零改动)
4
- */
5
- import { Events } from '../events.js';
6
- import { getQuery } from '../../runs/active-runs.js';
7
- import { mutateSpecJson } from '../../../projects/workspace.js';
8
- import { listWorkspaceArtifacts } from '../../../lib/artifact-target.js';
9
- import { resetTurnMemory } from './turn-state-memory.js';
10
-
11
- /**
12
- * Context usage 警告分档(按真实容量算,kimi=256k):
13
- * soft 70% — 提醒:还能再写一阵;下个段落收尾时落档
14
- * firm 85% — 加紧:开始整理结论 / 准备 spec.json
15
- * urgent 92% — 已过 SDK auto-compact 触发线(90%×真实=230k for 256k 容量),立即收尾
16
- */
17
- const CONTEXT_USAGE_WARN_LEVELS = [
18
- { percent: 70, tone: 'soft' },
19
- { percent: 85, tone: 'firm' },
20
- { percent: 92, tone: 'urgent' },
21
- ];
22
-
23
- /**
24
- * SessionStart handler(升级原 noop 占位)。
25
- *
26
- * input: SessionStartHookInput (sdk.d.ts:3577)
27
- * - source: 'startup' | 'resume' | 'clear' | 'compact'
28
- * - agent_type?: string 父 agent 类型(--agent 时有)
29
- * - model?: string
30
- *
31
- * Phase 2 范围:仅 emit 事件让上层可见。不注 additionalContext / initialUserMessage —
32
- * spec.json 的恢复走 UserPromptSubmit 路径(每次用户输入前重新注入),而不是
33
- * SessionStart 一次性注入(一次性注入只在 session 开头有效,跨多个 turn 后过期)。
34
- */
35
- export function makeSessionStartHandler({ ctx }) {
36
- return async (input, _toolUseId, _options) => {
37
- try {
38
- ctx.emit(Events.sessionStart(input.source, input.agent_type, ctx.appModel || input.model));
39
- } catch (err) {
40
- console.warn(`[hooks/SessionStart] handler threw:`, err.message);
41
- }
42
- return {};
43
- };
44
- }
45
-
46
- /**
47
- * Stop handler(P0+ s1 C6)—— agent 准备结束 query 时触发。
48
- *
49
- * 两件事:
50
- * 1. emit run.stop_reflection(hasCanvas 信号给前端)
51
- * 2. SDK getContextUsage 拉上下文占用 → emit run.context_usage + 三档 70/85/92% 注 systemMessage
52
- *
53
- * input: StopHookInput (sdk.d.ts:5247)
54
- * - stop_hook_active: boolean
55
- * - last_assistant_message?: string
56
- */
57
- export function makeStopReflectionHandler({ ctx, workspaceRoot }) {
58
- return async (_input, _toolUseId, _options) => {
59
- let warnContextUsage = null;
60
- try {
61
- // 任务模型下产物住 tasks/<任务>/,这里以前只探 cwd 根的 canvas.html —— 自
62
- // 任务模型上线起就恒为 false,从来没真过。走统一寻址(deck 和站点都算数)。
63
- const hasCanvas = workspaceRoot
64
- ? (await listWorkspaceArtifacts(workspaceRoot)).length > 0
65
- : false;
66
-
67
- ctx.emit({
68
- type: 'run.stop_reflection',
69
- hasCanvas,
70
- });
71
-
72
- // SDK 0.2.86+ getContextUsage —— 每个 turn 收尾时拉一次上下文占用,
73
- // emit 给前端做可视化条 + 三档(70/85/92%)注 systemMessage 提示 agent 主动收尾
74
- // (Kimi gateway 上限 256k,曾经爆过 418k;spoofing 后 SDK auto-compact
75
- // 在 256k×0.9=230k 触发兜底)
76
- if (ctx.runId) {
77
- try {
78
- const query = getQuery(ctx.runId);
79
- if (query?.getContextUsage) {
80
- const usage = await query.getContextUsage();
81
- if (usage && typeof usage.totalTokens === 'number') {
82
- // 2026-07-30:这里原来手搓了第二种事件体 { used, max, percent, categories }。
83
- // 事件名跟 session-loop 那条一样,字段名一个都对不上 —— 前端读的是
84
- // totalTokens / maxTokens / percentage,所以这条在前端一直是纯噪音,
85
- // 全靠 store 的 merge「不覆盖已有值」才没显形。而每个 turn 的**最后**
86
- // 一条 context_usage 恰好总是它,任何"取最新一条"的下游拿到的都是
87
- // 一片 undefined。现在统一走 Events.contextUsage,全局只此一种形状。
88
- const evt = Events.contextUsage(usage, ctx.appModel);
89
- ctx.emit({ ...evt, runId: ctx.runId });
90
-
91
- const used = evt.totalTokens;
92
- const realMax = evt.maxTokens;
93
- const percent = evt.percentage;
94
-
95
- // realMax 有可能是 null(appModel 认不出、SDK 也没给容量)——
96
- // 那时 percentage 退回 SDK 自己的值,但下面的文案要拿 realMax 做减法,
97
- // 算不出容量就不提醒(宁可不说,也别说个编的数字)
98
- const hit = (Number.isFinite(realMax) && realMax > 0)
99
- ? [...CONTEXT_USAGE_WARN_LEVELS].reverse().find((l) => percent >= l.percent)
100
- : null;
101
- if (hit) {
102
- const usedStr = used.toLocaleString();
103
- const maxStr = realMax.toLocaleString();
104
- const remain = Math.max(0, realMax - used).toLocaleString();
105
- let body;
106
- if (hit.tone === 'soft') {
107
- body = `上下文已用 ${percent}%(${usedStr}/${maxStr} tokens),还能再写一阵;下一个段落收尾时把当前进度落一张便利贴(record_decision 或 Write notes/<slug>.md),避免后续 compact 丢上下文。`;
108
- } else if (hit.tone === 'firm') {
109
- body = `上下文已用 ${percent}%(${usedStr}/${maxStr},剩 ~${remain})。从下一轮开始整理结论 / 落档,避免被自动 compact 硬切。`;
110
- } else {
111
- body = `上下文已用 ${percent}%(${usedStr}/${maxStr})。已逼近 SDK auto-compact 触发线(90%);立即收尾或把结论落进便利贴(record_decision / notes/),否则下一轮可能被压缩中断当前思路。`;
112
- }
113
- warnContextUsage = `<system-reminder>\n[context-usage] ${body}\n</system-reminder>`;
114
- }
115
- }
116
- }
117
- } catch (err) {
118
- console.warn(`[hooks/Stop] getContextUsage fail:`, err.message);
119
- }
120
- }
121
- } catch (err) {
122
- console.warn(`[hooks/Stop] handler threw:`, err.message);
123
- }
124
- if (warnContextUsage) {
125
- return { systemMessage: warnContextUsage };
126
- }
127
- return {};
128
- };
129
- }
130
-
131
- /**
132
- * PostCompact handler(P0+ s1 C7)—— SDK 自动 compact 后把 summary 持久化到 spec.json。
133
- *
134
- * input: PostCompactHookInput (sdk.d.ts:1879)
135
- * - trigger: 'manual' | 'auto'
136
- * - compact_summary: string
137
- *
138
- * 失败 fail-soft:spec.json 写不进去 console.warn 但不抛错(不阻塞 query)。
139
- */
140
- export function makePostCompactHandler({ ctx, workspaceRoot, sessionId }) {
141
- return async (input, _toolUseId, _options) => {
142
- try {
143
- // 压缩后上一轮的状态块已经被摘要吞了,"同上轮"没有所指 —— 让下一轮重新全量
144
- resetTurnMemory(sessionId);
145
- if (!workspaceRoot) return {};
146
- const summary = input?.compact_summary;
147
- if (!summary || typeof summary !== 'string') return {};
148
-
149
- // 串行 read-modify-write 防 spec.json 三路并发覆盖(详见 workspace.js mutateSpecJson)
150
- // historyCount 在回调内 capture 出去 —— 之前 emit 里直接引用 spec 是 ReferenceError,
151
- // 整段被 try 静默吞,导致 run.compact_persisted 事件永远不发。
152
- let historyCount = 0;
153
- await mutateSpecJson(workspaceRoot, (spec) => {
154
- if (!Array.isArray(spec.history)) spec.history = [];
155
- spec.history.push({
156
- ts: new Date().toISOString(),
157
- source: 'compact',
158
- trigger: input.trigger || 'auto',
159
- summary,
160
- });
161
- historyCount = spec.history.length;
162
- });
163
-
164
- try {
165
- ctx.emit({
166
- type: 'run.compact_persisted',
167
- trigger: input.trigger || 'auto',
168
- summaryLength: summary.length,
169
- historyCount,
170
- });
171
- } catch { /* emit fail-safe */ }
172
- } catch (err) {
173
- console.warn(`[hooks/PostCompact] handler threw:`, err.message);
174
- }
175
- return {};
176
- };
177
- }
178
-
179
- /**
180
- * SubagentStart handler — 子代理启动时主动 emit 事件给 EventBus。
181
- *
182
- * input: SubagentStartHookInput (sdk.d.ts:5258)
183
- * - agent_id: string
184
- * - agent_type: string
185
- *
186
- * 与 SDK system 'task_started' message 路径并行:task_* message 走的是 SDK
187
- * agentProgressSummaries 通道(30s 摘要),而 hook 是子代理 spawn 时立即触发,
188
- * 时序更前 + 更可靠。session-loop.js 已对 task_started 翻译成 run.task.started,
189
- * 这条 hook emit 的 run.subagent.start 是更主动的入口。
190
- *
191
- * Phase 2 仅 emit;不注入 additionalContext(子代理刚启动还没产出,注啥都早)。
192
- */
193
- export function makeSubagentStartHandler({ ctx }) {
194
- return async (input, _toolUseId, _options) => {
195
- try {
196
- ctx.emit(Events.subagentStart(input.agent_id, input.agent_type));
197
- } catch (err) {
198
- console.warn(`[hooks/SubagentStart] handler threw:`, err.message);
199
- }
200
- return {};
201
- };
202
- }
203
-
204
- /**
205
- * SubagentStop handler — 子代理结束时主动 emit。
206
- *
207
- * input: SubagentStopHookInput (sdk.d.ts:5269)
208
- * - stop_hook_active: boolean
209
- * - agent_id: string
210
- * - agent_transcript_path: string 子代理转录文件路径
211
- * - agent_type: string
212
- * - last_assistant_message?: string 子代理最后一条 assistant 文本
213
- *
214
- * 注意:SubagentStop 没有 specific output 类型(sdk.d.ts:5291 的 union 里没列),
215
- * 只能返回通用 SyncHookJSONOutput(continue/decision/systemMessage)。
216
- * 这里只 emit 不返 specific 输出,符合规范。
217
- */
218
- export function makeSubagentStopHandler({ ctx }) {
219
- return async (input, toolUseId, _options) => {
220
- try {
221
- ctx.emit(Events.subagentStop(
222
- input.agent_id,
223
- input.agent_type,
224
- input.last_assistant_message,
225
- input.agent_transcript_path,
226
- toolUseId, // main agent 调 Task 时的 tool_use_id;前端按它 match 卡
227
- ));
228
- } catch (err) {
229
- console.warn(`[hooks/SubagentStop] handler threw:`, err.message);
230
- }
231
- return {};
232
- };
233
- }
1
+ /**
2
+ * 会话生命周期族:SessionStart / Stop / PostCompact / SubagentStart / SubagentStop。
3
+ * (2026-08-14 可维护性行动:从 hooks.js 原样迁出,语义零改动)
4
+ */
5
+ import { Events } from '../events.js';
6
+ import { getQuery } from '../../runs/active-runs.js';
7
+ import { mutateSpecJson } from '../../../projects/workspace.js';
8
+ import { listWorkspaceArtifacts } from '../../../lib/artifact-target.js';
9
+ import { resetTurnMemory } from './turn-state-memory.js';
10
+
11
+ /**
12
+ * Context usage 警告分档(按真实容量算,kimi=256k):
13
+ * soft 70% — 提醒:还能再写一阵;下个段落收尾时落档
14
+ * firm 85% — 加紧:开始整理结论 / 准备 spec.json
15
+ * urgent 92% — 已过 SDK auto-compact 触发线(90%×真实=230k for 256k 容量),立即收尾
16
+ */
17
+ const CONTEXT_USAGE_WARN_LEVELS = [
18
+ { percent: 70, tone: 'soft' },
19
+ { percent: 85, tone: 'firm' },
20
+ { percent: 92, tone: 'urgent' },
21
+ ];
22
+
23
+ /**
24
+ * SessionStart handler(升级原 noop 占位)。
25
+ *
26
+ * input: SessionStartHookInput (sdk.d.ts:3577)
27
+ * - source: 'startup' | 'resume' | 'clear' | 'compact'
28
+ * - agent_type?: string 父 agent 类型(--agent 时有)
29
+ * - model?: string
30
+ *
31
+ * Phase 2 范围:仅 emit 事件让上层可见。不注 additionalContext / initialUserMessage —
32
+ * spec.json 的恢复走 UserPromptSubmit 路径(每次用户输入前重新注入),而不是
33
+ * SessionStart 一次性注入(一次性注入只在 session 开头有效,跨多个 turn 后过期)。
34
+ */
35
+ export function makeSessionStartHandler({ ctx }) {
36
+ return async (input, _toolUseId, _options) => {
37
+ try {
38
+ ctx.emit(Events.sessionStart(input.source, input.agent_type, ctx.appModel || input.model));
39
+ } catch (err) {
40
+ console.warn(`[hooks/SessionStart] handler threw:`, err.message);
41
+ }
42
+ return {};
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Stop handler(P0+ s1 C6)—— agent 准备结束 query 时触发。
48
+ *
49
+ * 两件事:
50
+ * 1. emit run.stop_reflection(hasCanvas 信号给前端)
51
+ * 2. SDK getContextUsage 拉上下文占用 → emit run.context_usage + 三档 70/85/92% 注 systemMessage
52
+ *
53
+ * input: StopHookInput (sdk.d.ts:5247)
54
+ * - stop_hook_active: boolean
55
+ * - last_assistant_message?: string
56
+ */
57
+ export function makeStopReflectionHandler({ ctx, workspaceRoot }) {
58
+ return async (_input, _toolUseId, _options) => {
59
+ let warnContextUsage = null;
60
+ try {
61
+ // 任务模型下产物住 tasks/<任务>/,这里以前只探 cwd 根的 canvas.html —— 自
62
+ // 任务模型上线起就恒为 false,从来没真过。走统一寻址(deck 和站点都算数)。
63
+ const hasCanvas = workspaceRoot
64
+ ? (await listWorkspaceArtifacts(workspaceRoot)).length > 0
65
+ : false;
66
+
67
+ ctx.emit({
68
+ type: 'run.stop_reflection',
69
+ hasCanvas,
70
+ });
71
+
72
+ // SDK 0.2.86+ getContextUsage —— 每个 turn 收尾时拉一次上下文占用,
73
+ // emit 给前端做可视化条 + 三档(70/85/92%)注 systemMessage 提示 agent 主动收尾
74
+ // (Kimi gateway 上限 256k,曾经爆过 418k;spoofing 后 SDK auto-compact
75
+ // 在 256k×0.9=230k 触发兜底)
76
+ if (ctx.runId) {
77
+ try {
78
+ const query = getQuery(ctx.runId);
79
+ if (query?.getContextUsage) {
80
+ const usage = await query.getContextUsage();
81
+ if (usage && typeof usage.totalTokens === 'number') {
82
+ // 2026-07-30:这里原来手搓了第二种事件体 { used, max, percent, categories }。
83
+ // 事件名跟 session-loop 那条一样,字段名一个都对不上 —— 前端读的是
84
+ // totalTokens / maxTokens / percentage,所以这条在前端一直是纯噪音,
85
+ // 全靠 store 的 merge「不覆盖已有值」才没显形。而每个 turn 的**最后**
86
+ // 一条 context_usage 恰好总是它,任何"取最新一条"的下游拿到的都是
87
+ // 一片 undefined。现在统一走 Events.contextUsage,全局只此一种形状。
88
+ const evt = Events.contextUsage(usage, ctx.appModel);
89
+ ctx.emit({ ...evt, runId: ctx.runId });
90
+
91
+ const used = evt.totalTokens;
92
+ const realMax = evt.maxTokens;
93
+ const percent = evt.percentage;
94
+
95
+ // realMax 有可能是 null(appModel 认不出、SDK 也没给容量)——
96
+ // 那时 percentage 退回 SDK 自己的值,但下面的文案要拿 realMax 做减法,
97
+ // 算不出容量就不提醒(宁可不说,也别说个编的数字)
98
+ const hit = (Number.isFinite(realMax) && realMax > 0)
99
+ ? [...CONTEXT_USAGE_WARN_LEVELS].reverse().find((l) => percent >= l.percent)
100
+ : null;
101
+ if (hit) {
102
+ const usedStr = used.toLocaleString();
103
+ const maxStr = realMax.toLocaleString();
104
+ const remain = Math.max(0, realMax - used).toLocaleString();
105
+ let body;
106
+ if (hit.tone === 'soft') {
107
+ body = `上下文已用 ${percent}%(${usedStr}/${maxStr} tokens),还能再写一阵;下一个段落收尾时把当前进度落一张便利贴(record_decision 或 Write notes/<slug>.md),避免后续 compact 丢上下文。`;
108
+ } else if (hit.tone === 'firm') {
109
+ body = `上下文已用 ${percent}%(${usedStr}/${maxStr},剩 ~${remain})。从下一轮开始整理结论 / 落档,避免被自动 compact 硬切。`;
110
+ } else {
111
+ body = `上下文已用 ${percent}%(${usedStr}/${maxStr})。已逼近 SDK auto-compact 触发线(90%);立即收尾或把结论落进便利贴(record_decision / notes/),否则下一轮可能被压缩中断当前思路。`;
112
+ }
113
+ warnContextUsage = `<system-reminder>\n[context-usage] ${body}\n</system-reminder>`;
114
+ }
115
+ }
116
+ }
117
+ } catch (err) {
118
+ console.warn(`[hooks/Stop] getContextUsage fail:`, err.message);
119
+ }
120
+ }
121
+ } catch (err) {
122
+ console.warn(`[hooks/Stop] handler threw:`, err.message);
123
+ }
124
+ if (warnContextUsage) {
125
+ return { systemMessage: warnContextUsage };
126
+ }
127
+ return {};
128
+ };
129
+ }
130
+
131
+ /**
132
+ * PostCompact handler(P0+ s1 C7)—— SDK 自动 compact 后把 summary 持久化到 spec.json。
133
+ *
134
+ * input: PostCompactHookInput (sdk.d.ts:1879)
135
+ * - trigger: 'manual' | 'auto'
136
+ * - compact_summary: string
137
+ *
138
+ * 失败 fail-soft:spec.json 写不进去 console.warn 但不抛错(不阻塞 query)。
139
+ */
140
+ export function makePostCompactHandler({ ctx, workspaceRoot, sessionId }) {
141
+ return async (input, _toolUseId, _options) => {
142
+ try {
143
+ // 压缩后上一轮的状态块已经被摘要吞了,"同上轮"没有所指 —— 让下一轮重新全量
144
+ resetTurnMemory(sessionId);
145
+ if (!workspaceRoot) return {};
146
+ const summary = input?.compact_summary;
147
+ if (!summary || typeof summary !== 'string') return {};
148
+
149
+ // 串行 read-modify-write 防 spec.json 三路并发覆盖(详见 workspace.js mutateSpecJson)
150
+ // historyCount 在回调内 capture 出去 —— 之前 emit 里直接引用 spec 是 ReferenceError,
151
+ // 整段被 try 静默吞,导致 run.compact_persisted 事件永远不发。
152
+ let historyCount = 0;
153
+ await mutateSpecJson(workspaceRoot, (spec) => {
154
+ if (!Array.isArray(spec.history)) spec.history = [];
155
+ spec.history.push({
156
+ ts: new Date().toISOString(),
157
+ source: 'compact',
158
+ trigger: input.trigger || 'auto',
159
+ summary,
160
+ });
161
+ historyCount = spec.history.length;
162
+ });
163
+
164
+ try {
165
+ ctx.emit({
166
+ type: 'run.compact_persisted',
167
+ trigger: input.trigger || 'auto',
168
+ summaryLength: summary.length,
169
+ historyCount,
170
+ });
171
+ } catch { /* emit fail-safe */ }
172
+ } catch (err) {
173
+ console.warn(`[hooks/PostCompact] handler threw:`, err.message);
174
+ }
175
+ return {};
176
+ };
177
+ }
178
+
179
+ /**
180
+ * SubagentStart handler — 子代理启动时主动 emit 事件给 EventBus。
181
+ *
182
+ * input: SubagentStartHookInput (sdk.d.ts:5258)
183
+ * - agent_id: string
184
+ * - agent_type: string
185
+ *
186
+ * 与 SDK system 'task_started' message 路径并行:task_* message 走的是 SDK
187
+ * agentProgressSummaries 通道(30s 摘要),而 hook 是子代理 spawn 时立即触发,
188
+ * 时序更前 + 更可靠。session-loop.js 已对 task_started 翻译成 run.task.started,
189
+ * 这条 hook emit 的 run.subagent.start 是更主动的入口。
190
+ *
191
+ * Phase 2 仅 emit;不注入 additionalContext(子代理刚启动还没产出,注啥都早)。
192
+ */
193
+ export function makeSubagentStartHandler({ ctx }) {
194
+ return async (input, _toolUseId, _options) => {
195
+ try {
196
+ ctx.emit(Events.subagentStart(input.agent_id, input.agent_type));
197
+ } catch (err) {
198
+ console.warn(`[hooks/SubagentStart] handler threw:`, err.message);
199
+ }
200
+ return {};
201
+ };
202
+ }
203
+
204
+ /**
205
+ * SubagentStop handler — 子代理结束时主动 emit。
206
+ *
207
+ * input: SubagentStopHookInput (sdk.d.ts:5269)
208
+ * - stop_hook_active: boolean
209
+ * - agent_id: string
210
+ * - agent_transcript_path: string 子代理转录文件路径
211
+ * - agent_type: string
212
+ * - last_assistant_message?: string 子代理最后一条 assistant 文本
213
+ *
214
+ * 注意:SubagentStop 没有 specific output 类型(sdk.d.ts:5291 的 union 里没列),
215
+ * 只能返回通用 SyncHookJSONOutput(continue/decision/systemMessage)。
216
+ * 这里只 emit 不返 specific 输出,符合规范。
217
+ */
218
+ export function makeSubagentStopHandler({ ctx }) {
219
+ return async (input, toolUseId, _options) => {
220
+ try {
221
+ ctx.emit(Events.subagentStop(
222
+ input.agent_id,
223
+ input.agent_type,
224
+ input.last_assistant_message,
225
+ input.agent_transcript_path,
226
+ toolUseId, // main agent 调 Task 时的 tool_use_id;前端按它 match 卡
227
+ ));
228
+ } catch (err) {
229
+ console.warn(`[hooks/SubagentStop] handler threw:`, err.message);
230
+ }
231
+ return {};
232
+ };
233
+ }
@@ -1,80 +1,80 @@
1
- /**
2
- * PostToolUse(Edit|Write canvas.html) handler — Canvas 焕新升级 S1d。
3
- * (2026-08-14 可维护性行动:从 hooks.js 原样迁出,语义零改动)
4
- *
5
- * focus_page:检测改动落在哪些 <section data-page="N"> + 改动里有没有
6
- * data-anchor="..." 引用 → emit run.canvas_focus_page(pages, anchor?)
7
- * → 前端 SlideNavigator 自动 scrollIntoView + 1.5s pulse 高亮
8
- *
9
- * 不返 hookSpecificOutput / 不阻塞 agent / 不注 additionalContext。
10
- *
11
- * 检测策略(Edit / Write 都要看):
12
- * - Edit:从 tool_input.new_string 找 data-page / data-anchor
13
- * (保守 — 只看新增的,不重复扫旧 content)
14
- * - Write:从 tool_input.content 找(整文件都是新内容)
15
- * - 非 canvas.html 文件:跳过
16
- * - file_path 是相对 cwd 的,没法判断到底是不是 canvas.html,按 basename 匹配
17
- *
18
- * 失败 fail-soft:emit fail / 解析炸都不抛,console.warn 一行。
19
- */
20
- import { Events } from '../events.js';
21
-
22
- export function makePostToolUseCanvasFocusPageHandler({ ctx }) {
23
- return async (input, _toolUseId, _options) => {
24
- try {
25
- const filePath = input?.tool_input?.file_path;
26
- if (!filePath || typeof filePath !== 'string') return {};
27
- // deck 现在叫 <名>.html(canvas.html 只是常用名):名字兜底 + 读文件看 deck wrap 标记
28
- if (!/\.html?$/i.test(filePath)) return {};
29
- if (!/(?:^|[/\\])canvas\.html$/i.test(filePath)) {
30
- let isDeck = false;
31
- try {
32
- const { promises: fsp } = await import('node:fs');
33
- const head = (await fsp.readFile(filePath, 'utf8')).slice(0, 200_000);
34
- isDeck = head.includes('__nd-deck-wrap');
35
- } catch { /* 相对路径读不到 / 文件没了:不是 deck 就当 */ }
36
- if (!isDeck) return {};
37
- }
38
-
39
- // 取改动文本:Edit 看 new_string,Write 看 content
40
- const toolName = input?.tool_name;
41
- let changeText = '';
42
- if (toolName === 'Edit') {
43
- changeText = String(input?.tool_input?.new_string || '');
44
- } else if (toolName === 'Write') {
45
- changeText = String(input?.tool_input?.content || '');
46
- } else {
47
- return {};
48
- }
49
- if (!changeText) return {};
50
-
51
- // focus_page —— 找 <section ... data-page="N"> + 可选 data-anchor
52
- try {
53
- const pageMatches = [...changeText.matchAll(
54
- /<section\b[^>]*\bdata-page\s*=\s*['"]?(\d+)['"]?/gi
55
- )];
56
- const pages = [...new Set(pageMatches.map(m => parseInt(m[1], 10)))]
57
- .filter(n => Number.isFinite(n));
58
-
59
- // 找 data-anchor — 取第一个,前端用它精确定位元素
60
- const anchorMatch = changeText.match(/\bdata-anchor\s*=\s*['"]([^'"]+)['"]/i);
61
- const anchor = anchorMatch ? anchorMatch[1] : null;
62
-
63
- // Edit 改的是 page 内某段时不会包含 <section data-page>,要从 file path
64
- // 上推 ——但 hook 时 canvas.html 已写完,可以读出来定位。为避免 hook IO
65
- // 阻塞 agent,这次先只 emit 显式带 data-page 的改动;不带 page 但带 anchor
66
- // 也 emit(前端能找到 anchor 元素自己反推 page)。
67
- if (pages.length > 0 || anchor) {
68
- ctx.emit(Events.canvasFocusPage(pages, anchor));
69
- }
70
- } catch (err) {
71
- console.warn(`[hooks/canvas_focus_page] handler partial failure:`, err.message);
72
- }
73
-
74
- return {};
75
- } catch (err) {
76
- console.warn(`[hooks/canvas_focus_page] outer handler threw:`, err.message);
77
- return {};
78
- }
79
- };
80
- }
1
+ /**
2
+ * PostToolUse(Edit|Write canvas.html) handler — Canvas 焕新升级 S1d。
3
+ * (2026-08-14 可维护性行动:从 hooks.js 原样迁出,语义零改动)
4
+ *
5
+ * focus_page:检测改动落在哪些 <section data-page="N"> + 改动里有没有
6
+ * data-anchor="..." 引用 → emit run.canvas_focus_page(pages, anchor?)
7
+ * → 前端 SlideNavigator 自动 scrollIntoView + 1.5s pulse 高亮
8
+ *
9
+ * 不返 hookSpecificOutput / 不阻塞 agent / 不注 additionalContext。
10
+ *
11
+ * 检测策略(Edit / Write 都要看):
12
+ * - Edit:从 tool_input.new_string 找 data-page / data-anchor
13
+ * (保守 — 只看新增的,不重复扫旧 content)
14
+ * - Write:从 tool_input.content 找(整文件都是新内容)
15
+ * - 非 canvas.html 文件:跳过
16
+ * - file_path 是相对 cwd 的,没法判断到底是不是 canvas.html,按 basename 匹配
17
+ *
18
+ * 失败 fail-soft:emit fail / 解析炸都不抛,console.warn 一行。
19
+ */
20
+ import { Events } from '../events.js';
21
+
22
+ export function makePostToolUseCanvasFocusPageHandler({ ctx }) {
23
+ return async (input, _toolUseId, _options) => {
24
+ try {
25
+ const filePath = input?.tool_input?.file_path;
26
+ if (!filePath || typeof filePath !== 'string') return {};
27
+ // deck 现在叫 <名>.html(canvas.html 只是常用名):名字兜底 + 读文件看 deck wrap 标记
28
+ if (!/\.html?$/i.test(filePath)) return {};
29
+ if (!/(?:^|[/\\])canvas\.html$/i.test(filePath)) {
30
+ let isDeck = false;
31
+ try {
32
+ const { promises: fsp } = await import('node:fs');
33
+ const head = (await fsp.readFile(filePath, 'utf8')).slice(0, 200_000);
34
+ isDeck = head.includes('__nd-deck-wrap');
35
+ } catch { /* 相对路径读不到 / 文件没了:不是 deck 就当 */ }
36
+ if (!isDeck) return {};
37
+ }
38
+
39
+ // 取改动文本:Edit 看 new_string,Write 看 content
40
+ const toolName = input?.tool_name;
41
+ let changeText = '';
42
+ if (toolName === 'Edit') {
43
+ changeText = String(input?.tool_input?.new_string || '');
44
+ } else if (toolName === 'Write') {
45
+ changeText = String(input?.tool_input?.content || '');
46
+ } else {
47
+ return {};
48
+ }
49
+ if (!changeText) return {};
50
+
51
+ // focus_page —— 找 <section ... data-page="N"> + 可选 data-anchor
52
+ try {
53
+ const pageMatches = [...changeText.matchAll(
54
+ /<section\b[^>]*\bdata-page\s*=\s*['"]?(\d+)['"]?/gi
55
+ )];
56
+ const pages = [...new Set(pageMatches.map(m => parseInt(m[1], 10)))]
57
+ .filter(n => Number.isFinite(n));
58
+
59
+ // 找 data-anchor — 取第一个,前端用它精确定位元素
60
+ const anchorMatch = changeText.match(/\bdata-anchor\s*=\s*['"]([^'"]+)['"]/i);
61
+ const anchor = anchorMatch ? anchorMatch[1] : null;
62
+
63
+ // Edit 改的是 page 内某段时不会包含 <section data-page>,要从 file path
64
+ // 上推 ——但 hook 时 canvas.html 已写完,可以读出来定位。为避免 hook IO
65
+ // 阻塞 agent,这次先只 emit 显式带 data-page 的改动;不带 page 但带 anchor
66
+ // 也 emit(前端能找到 anchor 元素自己反推 page)。
67
+ if (pages.length > 0 || anchor) {
68
+ ctx.emit(Events.canvasFocusPage(pages, anchor));
69
+ }
70
+ } catch (err) {
71
+ console.warn(`[hooks/canvas_focus_page] handler partial failure:`, err.message);
72
+ }
73
+
74
+ return {};
75
+ } catch (err) {
76
+ console.warn(`[hooks/canvas_focus_page] outer handler threw:`, err.message);
77
+ return {};
78
+ }
79
+ };
80
+ }