@xiaobuyu/nodesign 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (372) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +140 -0
  3. package/bin/nodesign.js +176 -0
  4. package/package.json +104 -0
  5. package/server/api/README.md +45 -0
  6. package/server/api/_guard.js +75 -0
  7. package/server/api/admin.js +187 -0
  8. package/server/api/assets/docx-page.js +103 -0
  9. package/server/api/assets/helpers.js +22 -0
  10. package/server/api/assets/notes.js +144 -0
  11. package/server/api/assets.js +896 -0
  12. package/server/api/board.js +57 -0
  13. package/server/api/browse.js +138 -0
  14. package/server/api/canvas.js +444 -0
  15. package/server/api/chatai.js +324 -0
  16. package/server/api/exports/build-standalone.js +980 -0
  17. package/server/api/exports/cards.js +118 -0
  18. package/server/api/exports/docx-pdf.js +46 -0
  19. package/server/api/exports/export-page.js +142 -0
  20. package/server/api/exports/handoff.js +147 -0
  21. package/server/api/exports.js +690 -0
  22. package/server/api/instruction.js +75 -0
  23. package/server/api/local.js +115 -0
  24. package/server/api/me.js +116 -0
  25. package/server/api/memory.js +185 -0
  26. package/server/api/pending-changes.js +366 -0
  27. package/server/api/plugins.js +164 -0
  28. package/server/api/projects.js +220 -0
  29. package/server/api/publish.js +64 -0
  30. package/server/api/recent.js +73 -0
  31. package/server/api/sessions.js +589 -0
  32. package/server/api/skills.js +77 -0
  33. package/server/api/standalone-fit.js +168 -0
  34. package/server/api/turn-compose.js +180 -0
  35. package/server/api/turn-inflight.js +44 -0
  36. package/server/api/turn.js +669 -0
  37. package/server/auth/README.md +17 -0
  38. package/server/auth/middleware.js +138 -0
  39. package/server/auth/origin-guard.js +71 -0
  40. package/server/auth/session.js +108 -0
  41. package/server/auth/tier.js +113 -0
  42. package/server/auth/users-store.js +348 -0
  43. package/server/edit/README.md +29 -0
  44. package/server/engine/README.md +113 -0
  45. package/server/engine/agent/agent-shared.js +550 -0
  46. package/server/engine/agent/auto-mode-default-hard-deny.txt +4 -0
  47. package/server/engine/agent/auto-mode-rules.js +78 -0
  48. package/server/engine/agent/context.js +418 -0
  49. package/server/engine/agent/events.js +464 -0
  50. package/server/engine/agent/hooks/canvas-validate.js +199 -0
  51. package/server/engine/agent/hooks/failure.js +120 -0
  52. package/server/engine/agent/hooks/file-events.js +75 -0
  53. package/server/engine/agent/hooks/lifecycle.js +233 -0
  54. package/server/engine/agent/hooks/post-canvas-focus.js +80 -0
  55. package/server/engine/agent/hooks/post-guidance.js +206 -0
  56. package/server/engine/agent/hooks/post-subagent-report.js +104 -0
  57. package/server/engine/agent/hooks/post-trim.js +58 -0
  58. package/server/engine/agent/hooks/pre-board-neighborhood.js +34 -0
  59. package/server/engine/agent/hooks/pre-defaults.js +84 -0
  60. package/server/engine/agent/hooks/pre-injectors.js +277 -0
  61. package/server/engine/agent/hooks/pre-performance-log-guard.js +78 -0
  62. package/server/engine/agent/hooks/pre-starter-files.js +61 -0
  63. package/server/engine/agent/hooks/pre-workspace-scope-guard.js +78 -0
  64. package/server/engine/agent/hooks/site-validate.js +94 -0
  65. package/server/engine/agent/hooks/tool-prompts.js +31 -0
  66. package/server/engine/agent/hooks/turn-state-memory.js +56 -0
  67. package/server/engine/agent/hooks/user-prompt-submit.js +215 -0
  68. package/server/engine/agent/hooks.js +354 -0
  69. package/server/engine/agent/init-contract.js +69 -0
  70. package/server/engine/agent/isolation.js +159 -0
  71. package/server/engine/agent/model-context.js +359 -0
  72. package/server/engine/agent/model-table.js +292 -0
  73. package/server/engine/agent/plugin-loader.js +266 -0
  74. package/server/engine/agent/prompts/nodesign-prelude.md +336 -0
  75. package/server/engine/agent/prompts/tools/ask-user-question-protocol.md +71 -0
  76. package/server/engine/agent/prompts/tools/direct-edit-protocol.md +98 -0
  77. package/server/engine/agent/prompts/tools/generate-image-cookbook.gemini-gateway.md +583 -0
  78. package/server/engine/agent/prompts/tools/generate-image-cookbook.md +483 -0
  79. package/server/engine/agent/prompts/tools/hybrid-reference.md +100 -0
  80. package/server/engine/agent/prompts/tools/paint-still-cookbook.md +270 -0
  81. package/server/engine/agent/prompts/tools/roll-film-cookbook.md +70 -0
  82. package/server/engine/agent/prompts/tools/site-reference.md +106 -0
  83. package/server/engine/agent/prompts/tools/tweaks-syntax.md +125 -0
  84. package/server/engine/agent/prompts/tools/vision-checker-dispatch.md +48 -0
  85. package/server/engine/agent/session-loop.js +1024 -0
  86. package/server/engine/agent/session-model.js +164 -0
  87. package/server/engine/agent/skill.js +204 -0
  88. package/server/engine/agent/system-prompts.js +86 -0
  89. package/server/engine/agent/task-events.js +78 -0
  90. package/server/engine/agents/ds-extractor.md +132 -0
  91. package/server/engine/agents/explorer.md +190 -0
  92. package/server/engine/agents/index.js +230 -0
  93. package/server/engine/agents/schemas/design-system.json +156 -0
  94. package/server/engine/agents/schemas/tweak-schema.json +113 -0
  95. package/server/engine/agents/tweak-proposer.md +127 -0
  96. package/server/engine/agents/vision-checker.md +254 -0
  97. package/server/engine/browse/capture.js +422 -0
  98. package/server/engine/browse/card.js +137 -0
  99. package/server/engine/browse/handover.js +59 -0
  100. package/server/engine/browse/page-digest.js +119 -0
  101. package/server/engine/browse/refs.js +196 -0
  102. package/server/engine/browse/registry.js +307 -0
  103. package/server/engine/browse/screencast.js +170 -0
  104. package/server/engine/browse/state.js +121 -0
  105. package/server/engine/chatai/chat-log.js +79 -0
  106. package/server/engine/chatai/index.js +193 -0
  107. package/server/engine/chatai/openai-compat.js +152 -0
  108. package/server/engine/chatai/orchestrate.js +309 -0
  109. package/server/engine/chatai/perform.js +40 -0
  110. package/server/engine/chatai/summarize.js +79 -0
  111. package/server/engine/mcp/capability-gate.js +52 -0
  112. package/server/engine/mcp/index.js +339 -0
  113. package/server/engine/mcp/param-sanitizer.js +142 -0
  114. package/server/engine/mcp/tools/arrange-on-board.js +124 -0
  115. package/server/engine/mcp/tools/artifact-session.js +278 -0
  116. package/server/engine/mcp/tools/browse-computer.js +421 -0
  117. package/server/engine/mcp/tools/browse-find-batch.js +183 -0
  118. package/server/engine/mcp/tools/browse-screenshot.js +157 -0
  119. package/server/engine/mcp/tools/browse.js +480 -0
  120. package/server/engine/mcp/tools/build-docx.js +101 -0
  121. package/server/engine/mcp/tools/clear-pending-changes.js +99 -0
  122. package/server/engine/mcp/tools/create-on-board.js +155 -0
  123. package/server/engine/mcp/tools/crystallize-skill.js +168 -0
  124. package/server/engine/mcp/tools/deliver-files.js +0 -0
  125. package/server/engine/mcp/tools/explain-style.js +237 -0
  126. package/server/engine/mcp/tools/export-handoff.js +133 -0
  127. package/server/engine/mcp/tools/expose-tweaks.js +149 -0
  128. package/server/engine/mcp/tools/generate-image.js +842 -0
  129. package/server/engine/mcp/tools/get-computed-styles.js +164 -0
  130. package/server/engine/mcp/tools/get-pending-changes.js +205 -0
  131. package/server/engine/mcp/tools/h3box-ssh.js +84 -0
  132. package/server/engine/mcp/tools/helpers/acquire-page.js +82 -0
  133. package/server/engine/mcp/tools/helpers/motion-lab.js +554 -0
  134. package/server/engine/mcp/tools/helpers/motion-scroll.js +112 -0
  135. package/server/engine/mcp/tools/helpers/perception-page.js +215 -0
  136. package/server/engine/mcp/tools/helpers/reference-download.js +103 -0
  137. package/server/engine/mcp/tools/helpers/rembg-bridge.py +80 -0
  138. package/server/engine/mcp/tools/helpers/rembg.js +273 -0
  139. package/server/engine/mcp/tools/helpers/shot-pipeline.js +280 -0
  140. package/server/engine/mcp/tools/highlight.js +68 -0
  141. package/server/engine/mcp/tools/list-pages.js +222 -0
  142. package/server/engine/mcp/tools/lookup-tags.js +59 -0
  143. package/server/engine/mcp/tools/navigate-to-page.js +60 -0
  144. package/server/engine/mcp/tools/organize-board.js +64 -0
  145. package/server/engine/mcp/tools/paint-still.js +434 -0
  146. package/server/engine/mcp/tools/pin-to-board.js +130 -0
  147. package/server/engine/mcp/tools/preview-deck.js +130 -0
  148. package/server/engine/mcp/tools/profile-scroll.js +305 -0
  149. package/server/engine/mcp/tools/publish-site.js +102 -0
  150. package/server/engine/mcp/tools/query-elements.js +195 -0
  151. package/server/engine/mcp/tools/read-board.js +103 -0
  152. package/server/engine/mcp/tools/read-document.js +93 -0
  153. package/server/engine/mcp/tools/read-page.js +264 -0
  154. package/server/engine/mcp/tools/read-tavern-json.js +143 -0
  155. package/server/engine/mcp/tools/record-decision.js +140 -0
  156. package/server/engine/mcp/tools/relate-on-board.js +110 -0
  157. package/server/engine/mcp/tools/remove-background.js +391 -0
  158. package/server/engine/mcp/tools/report-issue.js +115 -0
  159. package/server/engine/mcp/tools/roll-film.js +266 -0
  160. package/server/engine/mcp/tools/screenshot-docx.js +138 -0
  161. package/server/engine/mcp/tools/screenshot-url.js +195 -0
  162. package/server/engine/mcp/tools/screenshot.js +583 -0
  163. package/server/engine/mcp/tools/tier-gate.js +96 -0
  164. package/server/engine/mcp/tools/trace-motion.js +215 -0
  165. package/server/engine/mcp/tools/web-search.js +548 -0
  166. package/server/engine/motion/inventory.js +349 -0
  167. package/server/engine/perception/session.js +235 -0
  168. package/server/engine/plugins/nodesign/.claude-plugin/plugin.json +5 -0
  169. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/SKILL.md +192 -0
  170. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/canvas.template.html +667 -0
  171. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/hybrid-grid.md +22 -0
  172. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/image-led-cover.md +25 -0
  173. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/portrait.md +23 -0
  174. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/quote-backdrop.md +21 -0
  175. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/section-divider.md +23 -0
  176. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/text-led.md +21 -0
  177. package/server/engine/plugins/nodesign/skills/docx-craft/SKILL.md +162 -0
  178. package/server/engine/plugins/nodesign/skills/docx-craft/references/token-schema.md +407 -0
  179. package/server/engine/plugins/nodesign/skills/docx-craft//346/226/207/346/241/243.template.json +80 -0
  180. package/server/engine/plugins/nodesign/skills/rp-craft/SKILL.md +228 -0
  181. 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 -0
  182. package/server/engine/plugins/nodesign/skills/rp-craft//346/274/224/345/207/272.template.js +268 -0
  183. package/server/engine/plugins/nodesign/skills/site-craft/SKILL.md +323 -0
  184. package/server/engine/plugins/nodesign/skills/site-craft/patterns/build-lane.md +134 -0
  185. package/server/engine/plugins/nodesign/skills/site-craft/patterns/cutout-collage.md +61 -0
  186. package/server/engine/plugins/nodesign/skills/site-craft/patterns/mock-app.md +163 -0
  187. package/server/engine/plugins/nodesign/skills/site-craft/patterns/page-transitions.md +86 -0
  188. package/server/engine/runs/active-runs.js +698 -0
  189. package/server/engine/runs/live-turn.js +252 -0
  190. package/server/engine/runs/store.js +364 -0
  191. package/server/engine/runs/turn-relay.js +217 -0
  192. package/server/engine/runtime/workspace.js +164 -0
  193. package/server/index.js +235 -0
  194. package/server/lib/artifact-file-path.js +80 -0
  195. package/server/lib/artifact-target.js +284 -0
  196. package/server/lib/asset-refs.js +239 -0
  197. package/server/lib/async-queue.js +104 -0
  198. package/server/lib/auto-relations.js +130 -0
  199. package/server/lib/binding-types.js +60 -0
  200. package/server/lib/board-kind-sizes.js +62 -0
  201. package/server/lib/board-relations.js +133 -0
  202. package/server/lib/browse-proxy.js +180 -0
  203. package/server/lib/canvas-id.js +36 -0
  204. package/server/lib/cover.js +227 -0
  205. package/server/lib/danbooru-tags.js +291 -0
  206. package/server/lib/doc-extract.js +156 -0
  207. package/server/lib/docx/build-from-source.js +260 -0
  208. package/server/lib/docx/build.js +490 -0
  209. package/server/lib/docx/dump-styles.js +287 -0
  210. package/server/lib/docx/fonts/nodesign-cjk.conf +164 -0
  211. package/server/lib/docx/merge-runs.js +129 -0
  212. package/server/lib/docx/numbering.js +218 -0
  213. package/server/lib/docx/order.js +152 -0
  214. package/server/lib/docx/rawzip.js +172 -0
  215. package/server/lib/docx/render.js +92 -0
  216. package/server/lib/docx/text-lint.js +225 -0
  217. package/server/lib/docx/tokens.js +335 -0
  218. package/server/lib/docx/units.js +29 -0
  219. package/server/lib/docx/xml.js +291 -0
  220. package/server/lib/docx-pages.js +187 -0
  221. package/server/lib/export-collect.js +289 -0
  222. package/server/lib/export-package.js +210 -0
  223. package/server/lib/html-srcset.js +145 -0
  224. package/server/lib/image-variant.js +460 -0
  225. package/server/lib/ingress/forward-openai-chat.js +305 -0
  226. package/server/lib/ingress/openai-chat.js +491 -0
  227. package/server/lib/ingress/session-notice.js +66 -0
  228. package/server/lib/ingress/session-routes.js +68 -0
  229. package/server/lib/ingress/slot-probe.js +130 -0
  230. package/server/lib/ingress/upstream-billing.js +52 -0
  231. package/server/lib/ingress/upstream-fail-streak.js +72 -0
  232. package/server/lib/ingress/upstream-truncation.js +48 -0
  233. package/server/lib/issues-store.js +182 -0
  234. package/server/lib/kinds/deck.js +72 -0
  235. package/server/lib/kinds/docx.js +283 -0
  236. package/server/lib/kinds/file-kinds.js +113 -0
  237. package/server/lib/kinds/index.js +202 -0
  238. package/server/lib/kinds/site.js +161 -0
  239. package/server/lib/model-ingress.js +543 -0
  240. package/server/lib/moderation.js +255 -0
  241. package/server/lib/notice-store.js +103 -0
  242. package/server/lib/plugin-install.js +104 -0
  243. package/server/lib/plugin-validator.js +721 -0
  244. package/server/lib/publish-store.js +115 -0
  245. package/server/lib/quick-summary.js +52 -0
  246. package/server/lib/quota.js +270 -0
  247. package/server/lib/rate-window.js +29 -0
  248. package/server/lib/reference-assets.js +92 -0
  249. package/server/lib/region-shot.js +135 -0
  250. package/server/lib/safe-path.js +73 -0
  251. package/server/lib/sdk-session.js +33 -0
  252. package/server/lib/showcase-store.js +92 -0
  253. package/server/lib/site-publish.js +465 -0
  254. package/server/lib/ssrf-guard.js +432 -0
  255. package/server/lib/task-scan.js +158 -0
  256. package/server/lib/tavern-json.js +154 -0
  257. package/server/lib/video-variant.js +237 -0
  258. package/server/lib/workspace-path.js +33 -0
  259. package/server/ops/fix-sdk-musl.mjs +40 -0
  260. package/server/ops/install-macos-fonts.sh +114 -0
  261. package/server/ops/macos-fonts.conf +336 -0
  262. package/server/ops/sandbox-shim/bwrap +57 -0
  263. package/server/projects/assets-summary.js +119 -0
  264. package/server/projects/auto-name.js +53 -0
  265. package/server/projects/board-store.js +640 -0
  266. package/server/projects/move-entry.js +103 -0
  267. package/server/projects/store.js +270 -0
  268. package/server/projects/ui-config.js +54 -0
  269. package/server/projects/workspace-templates.js +53 -0
  270. package/server/projects/workspace.js +1025 -0
  271. package/server/runtime/capabilities.js +153 -0
  272. package/server/runtime/local-config.js +177 -0
  273. package/server/runtime/local-env.js +88 -0
  274. package/server/runtime/platform.js +342 -0
  275. package/server/runtime/profile.js +72 -0
  276. package/server/services/rembg-launcher.js +313 -0
  277. package/server/services/rembg-service.py +334 -0
  278. package/server/shared/README.md +25 -0
  279. package/server/shared/deck.js +54 -0
  280. package/server/shared/time.js +49 -0
  281. package/server/style-pipeline/README.md +53 -0
  282. package/server/ws/broker.js +36 -0
  283. package/server/ws/browse-channel.js +177 -0
  284. package/server/ws/index.js +386 -0
  285. package/web/README.md +89 -0
  286. package/web/dist/assets/BrowserWindow-Dc7J7CYc.js +11 -0
  287. package/web/dist/assets/DeckWindow-4G0xX7P3.js +16 -0
  288. package/web/dist/assets/DocxWindow-BXQsoPkh.js +16 -0
  289. package/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  290. package/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  291. package/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  292. package/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  293. package/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  294. package/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  295. package/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  296. package/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  297. package/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  298. package/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  299. package/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  300. package/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  301. package/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  302. package/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  303. package/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  304. package/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  305. package/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  306. package/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  307. package/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  308. package/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  309. package/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  310. package/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  311. package/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  312. package/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  313. package/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  314. package/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  315. package/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  316. package/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  317. package/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  318. package/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  319. package/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  320. package/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  321. package/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  322. package/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  323. package/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  324. package/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  325. package/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  326. package/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  327. package/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  328. package/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  329. package/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  330. package/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  331. package/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  332. package/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  333. package/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  334. package/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  335. package/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  336. package/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  337. package/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  338. package/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  339. package/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  340. package/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  341. package/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  342. package/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  343. package/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  344. package/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  345. package/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  346. package/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  347. package/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  348. package/web/dist/assets/SiteWindow-D6eS-2gM.js +18 -0
  349. package/web/dist/assets/again-D8tfgKKO.webp +0 -0
  350. package/web/dist/assets/caveat-nd-CP6HlsNg.woff2 +0 -0
  351. package/web/dist/assets/clock-xJhvfYpS.webp +0 -0
  352. package/web/dist/assets/film-cut-BBKMwH7q.webp +0 -0
  353. package/web/dist/assets/film-still-BZ_DL9Tt.webp +0 -0
  354. package/web/dist/assets/index-C0KUf6Wd.css +1 -0
  355. package/web/dist/assets/index-Cbl3ATvp.js +2125 -0
  356. package/web/dist/assets/ink-desk-BRbxeDsR.webp +0 -0
  357. package/web/dist/assets/ink-night-Bz4BT3XH.webp +0 -0
  358. package/web/dist/assets/ink-portrait-C0DM4V8Q.webp +0 -0
  359. package/web/dist/assets/longcang-regular-C0uvTuKa.woff2 +0 -0
  360. package/web/dist/assets/lxgw-nd-bold-DbRfiTgo.woff2 +0 -0
  361. package/web/dist/assets/lxgw-nd-regular-CpMw9Ehg.woff2 +0 -0
  362. package/web/dist/assets/pending-edit-apply-DTjo2geW.js +31 -0
  363. package/web/dist/assets/question-8H4HSqxh.webp +0 -0
  364. package/web/dist/assets/reject-BaPJqElj.webp +0 -0
  365. package/web/dist/assets/rotate-cw-LMT3x1Zj.js +11 -0
  366. package/web/dist/assets/rp-portrait-CbrGpew2.webp +0 -0
  367. package/web/dist/assets/rp-street-C4jVKjxx.webp +0 -0
  368. package/web/dist/assets/square-dashed-mouse-pointer-CBoAkfhi.js +11 -0
  369. package/web/dist/assets/tangle-DIxHVNuT.webp +0 -0
  370. package/web/dist/assets/thisone-BylZKglV.webp +0 -0
  371. package/web/dist/assets/thumb-DO1wfK1I.webp +0 -0
  372. package/web/dist/index.html +18 -0
@@ -0,0 +1,278 @@
1
+ /**
2
+ * mcp/tools/artifact-session.js — 产物会话四件:artifact_open / artifact_computer /
3
+ * artifact_find / artifact_batch(2026-08-21)
4
+ *
5
+ * 成品检查的交互半边。以前七个感知工具全是一次性的(开一只新浏览器、量、关),
6
+ * "点开菜单 → 填表 → 提交 → 看校验"只能靠 beforeShot 塞 JS 假装;hover 态、焦点
7
+ * 顺序、方向键连按、拖拽、pointer lock 这些只认真实手势。现在:
8
+ *
9
+ * artifact_open 打开(或重载)一个产物到常驻会话,状态跨调用留着
10
+ * artifact_computer browser_computer 同一套动作(runAction 共享一份),对着会话页
11
+ * artifact_find 词法找元 → ref(refs.js 共享一份)
12
+ * artifact_batch 一次往返跑一串(makeBatchTool 共享一份合同)
13
+ *
14
+ * 老工具(screenshot_canvas / trace_motion / get_computed_styles / explain_style /
15
+ * query_elements)加 `live:true` 就对着会话里**现在这一页**量,胶片条/示波器/级联
16
+ * 解释全能骑在交互态上 —— 那是它们各自独有、browser use 没有的量具。
17
+ *
18
+ * 坐标:产物视口按形态定(站 1440×900、deck 1920×1080…),截图可能被归一化缩过,
19
+ * 会话记 frame={w,h,scale},模型读到的坐标 ÷ scale = 页面像素。artifact_open 的
20
+ * 返回会把截图尺寸说清楚。
21
+ */
22
+
23
+ import { tool } from '@anthropic-ai/claude-agent-sdk';
24
+ import { z } from 'zod';
25
+ import { openSession, withSession, changedSinceOpen, peekSession, defaultViewportFor } from '../../perception/session.js';
26
+ import { findInPage, formatMatches } from '../../browse/refs.js';
27
+ import { runAction, ACTIONS_DOC, COMPUTER_SCHEMA, actionErrorText } from './browse-computer.js';
28
+ import { makeBatchTool, HALT_TEXT } from './browse-find-batch.js';
29
+ import { normalizeShot, visionTokens } from './helpers/shot-pipeline.js';
30
+ import { degradedNote } from './helpers/perception-page.js';
31
+ import { acquireArtifactPage, LIVE_PARAM_DESC } from './helpers/acquire-page.js';
32
+ import { collectMotionInventory, formatMotionInventory } from '../../motion/inventory.js';
33
+ import { CANVAS_PATH_DESC, resolveCanvasTarget, requireBrowsable } from '../../../lib/artifact-target.js';
34
+
35
+ const asText = (text, isError = false) => ({ content: [{ type: 'text', text }], ...(isError ? { isError: true } : {}) });
36
+
37
+ /** 会话页截图(不存桌面卡 —— 那是浏览通道的事);caption 说清截图空间 */
38
+ async function sessionShot(entry, lead) {
39
+ const buf = await entry.page.screenshot({ type: 'png' });
40
+ const shot = await normalizeShot(buf);
41
+ const f = entry.frame;
42
+ return {
43
+ content: [
44
+ { type: 'text', text: [lead, `${f.w}×${f.h} (${f.scale < 1 ? `viewport ${entry.viewport.width}×${entry.viewport.height} scaled ×${f.scale.toFixed(2)}; ` : ''}coordinates you use next are these screenshot pixels, ≈${visionTokens(f.w, f.h)} tokens)`, shot.note].filter(Boolean).join(' · ') },
45
+ { type: 'image', data: shot.data, mimeType: shot.mimeType },
46
+ ],
47
+ };
48
+ }
49
+
50
+ async function changedNote(entry) {
51
+ const changed = await changedSinceOpen(entry);
52
+ if (!changed.length) return null;
53
+ const shown = changed.slice(0, 5).join(', ');
54
+ return `⚠ files changed since this page was opened (${shown}${changed.length > 5 ? ` +${changed.length - 5}` : ''}) — the page is showing the OLD version. artifact_open again to reload (state resets).`;
55
+ }
56
+
57
+ export function makeArtifactOpenTool({ projectId, workspaceRoot, sessionId }) {
58
+ return tool(
59
+ 'artifact_open',
60
+ `Open one of your artifacts (a site page, a deck, a game) in a persistent
61
+ session browser — the starting point for interactive checking. Unlike
62
+ screenshot_canvas (fresh load every call), the page stays open between calls:
63
+ menus you open stay open, text you type stays typed, a game keeps its state.
64
+ Then use artifact_computer (click / type / keys / drag / scroll / zoom /
65
+ screenshot), artifact_find (element refs), artifact_batch (several steps in one
66
+ round trip), and the measuring tools with live:true (screenshot_canvas filmstrip,
67
+ trace_motion, get_computed_styles, explain_style, query_elements) to inspect
68
+ the CURRENT interactive state.
69
+
70
+ Opening the same file again reloads it (state resets). Opening a different file
71
+ or device replaces the session. The page is loaded over http like the user
72
+ preview (fetch/localStorage behave the same). After you edit files the open page
73
+ is stale — every artifact_* result reminds you; reopen to see the new version.
74
+
75
+ Returns the screenshot size: coordinates you pass to artifact_computer are
76
+ pixels of that screenshot (a deck at 1920×1080 is scaled down to fit the vision
77
+ limit; the mapping is handled for you).`,
78
+ {
79
+ path: z.string().optional().describe(CANVAS_PATH_DESC),
80
+ device: z.enum(['desktop', 'tablet', 'mobile']).optional()
81
+ .describe('SITE ONLY. Real device width to render at: desktop=1440, tablet=834, mobile=390. Default desktop.'),
82
+ viewport: z.object({ width: z.number().int().min(320).max(2560), height: z.number().int().min(240).max(2560) }).optional()
83
+ .describe('Explicit viewport; defaults to the artifact kind (site → device width × 900, deck → its aspect).'),
84
+ },
85
+ async ({ path: relPath, device, viewport }) => {
86
+ try {
87
+ const { entry, reloaded, gotoNote } = await openSession({ projectId, workspaceRoot, sessionId, relPath, device, viewport });
88
+ const f = entry.frame;
89
+ const lines = [
90
+ `${reloaded ? 'Reloaded' : 'Opened'} ${entry.target.relPath} (${entry.target.kind}) at viewport ${entry.viewport.width}×${entry.viewport.height}.`,
91
+ `Screenshots are ${f.w}×${f.h}${f.scale < 1 ? ` (viewport scaled ×${f.scale.toFixed(2)} to fit the vision limit — you still just use screenshot pixels)` : ' (1:1 with the viewport)'}, ≈${visionTokens(f.w, f.h)} tokens each.`,
92
+ entry.viaHttp ? 'Loaded over http, same origin as the user preview.' : null,
93
+ degradedNote(entry),
94
+ gotoNote,
95
+ 'Next: artifact_computer screenshot to look, artifact_find to get refs, or artifact_batch to do several steps at once.',
96
+ ].filter(Boolean);
97
+ return asText(lines.join('\n'));
98
+ } catch (err) {
99
+ return asText(`artifact_open 失败:${err.message}`, true);
100
+ }
101
+ },
102
+ );
103
+ }
104
+
105
+ export function makeArtifactComputerTool({ projectId }) {
106
+ return tool(
107
+ 'artifact_computer',
108
+ `Pointer, keyboard and pixel-level capture on the page open in the artifact
109
+ session (artifact_open first). Same actions as browser_computer, aimed at YOUR
110
+ artifact: click through your own UI, fill your own forms, play your own game
111
+ with real key presses, drag your own sliders, hover to reveal your own tooltips,
112
+ zoom into your own small text.
113
+
114
+ Coordinates are pixels of the session screenshot (origin top-left; size is
115
+ reported by artifact_open and by every screenshot). After zoom, coordinates
116
+ are STILL full-screenshot pixels. Or target an element by ref from
117
+ artifact_find.
118
+
119
+ ${ACTIONS_DOC}
120
+
121
+ One action per call. For a sequence (click field → type → Enter → look) use
122
+ artifact_batch. To MEASURE the state you reached (easing filmstrip, computed
123
+ styles, cascade), call screenshot_canvas / trace_motion / get_computed_styles /
124
+ explain_style / query_elements with live:true.`,
125
+ COMPUTER_SCHEMA,
126
+ async (a) => {
127
+ try {
128
+ return await withSession(projectId, async (entry) => {
129
+ const { page } = entry;
130
+ const before = page.url();
131
+ // 站内导航(点了 about.html)也要报:判据同 browser_computer —— 主帧发出导航请求
132
+ let navStarted = false;
133
+ const onReq = (req) => { try { if (req.isNavigationRequest() && req.frame() === page.mainFrame()) navStarted = true; } catch { /* */ } };
134
+ page.on('request', onReq);
135
+ let r;
136
+ try {
137
+ r = await runAction(page, a, { frame: entry.frame, shot: (_p, lead) => sessionShot(entry, lead) });
138
+ } catch (err) {
139
+ page.off('request', onReq);
140
+ return asText(actionErrorText(a.action, err), true);
141
+ }
142
+ if (/click|key|type/.test(a.action) && !page.isClosed()) await page.waitForTimeout(250);
143
+ page.off('request', onReq);
144
+ if (!page.isClosed() && (navStarted || page.url() !== before)) {
145
+ await page.waitForLoadState('domcontentloaded', { timeout: 8000 }).catch(() => {});
146
+ }
147
+ if (!page.isClosed() && page.url() !== before) {
148
+ const title = await page.title().catch(() => '');
149
+ let where = page.url();
150
+ try { where = decodeURIComponent(new URL(where).pathname.replace(/^.*\/artifact-file\//, '')); } catch { /* */ }
151
+ r.content.unshift({ type: 'text', text: `→ page changed: ${title || '(no title)'} — ${where} (refs from before are gone)` });
152
+ }
153
+ const note = await changedNote(entry);
154
+ if (note) r.content.push({ type: 'text', text: note });
155
+ return r;
156
+ });
157
+ } catch (err) {
158
+ return asText(`artifact_computer 失败:${err.message}`, true);
159
+ }
160
+ },
161
+ );
162
+ }
163
+
164
+ export function makeArtifactFindTool({ projectId }) {
165
+ return tool(
166
+ 'artifact_find',
167
+ `Find elements on the page open in the artifact session by describing them
168
+ ("submit button", "price input", "第二张卡片 链接"). Returns up to 20 matches
169
+ with refs (ref_N) for artifact_computer and their screenshot coordinates.
170
+ Matching is LEXICAL (visible text / aria-label / placeholder / alt / role /
171
+ href), not semantic — use the words that appear on the element. You wrote this
172
+ page, so a CSS selector via query_elements is often just as good; refs shine for
173
+ canvas/WebGL UIs and anything you'd otherwise have to click by pixel. Refs die
174
+ on reload/navigation.`,
175
+ {
176
+ query: z.string().min(1).max(120).describe('Words shown on the element plus an optional role word.'),
177
+ limit: z.number().int().min(1).max(20).optional().describe('Max matches (default 20).'),
178
+ },
179
+ async ({ query, limit }) => {
180
+ try {
181
+ return await withSession(projectId, async (entry) => {
182
+ const r = await findInPage(entry.page, { query, limit: limit ?? 20 });
183
+ const s = entry.frame.scale;
184
+ if (s < 1) {
185
+ r.matches = r.matches.map(m => ({ ...m, x: Math.round(m.x * s), y: Math.round(m.y * s), w: Math.round(m.w * s), h: Math.round(m.h * s) }));
186
+ }
187
+ const lines = formatMatches(r, query).map(l => l.replace('browser_computer', 'artifact_computer').replace('browser_read', 'query_elements').replace('browser_find', 'artifact_find'));
188
+ const note = await changedNote(entry);
189
+ return asText([...lines, note].filter(Boolean).join('\n'));
190
+ });
191
+ } catch (err) {
192
+ return asText(`artifact_find 失败:${err.message}`, true);
193
+ }
194
+ },
195
+ );
196
+ }
197
+
198
+ /**
199
+ * artifact_motion:自己的产物"靠什么在动"——跟 browser_capture 的 motion 档**同一份引擎**
200
+ * (engine/motion/inventory.js),只是对着产物页。默认新开一只可复现;live:true 对着会话页
201
+ * (会真滚一遍再滚回顶,reveal 会被触发 —— 查交互态之前先想清楚要不要)。
202
+ */
203
+ export function makeArtifactMotionTool({ projectId, workspaceRoot, sessionId }) {
204
+ return tool(
205
+ 'artifact_motion',
206
+ `Inventory of WHAT moves on your artifact page and how: every stylesheet
207
+ scanned for @keyframes / animation / transition / CSS scroll-driven animation
208
+ (animation-timeline, scroll(), view()) / scroll-snap / sticky / reduced-motion;
209
+ the browser's running animations (getAnimations: durations, easings, keyframes);
210
+ motion libraries (GSAP + each ScrollTrigger's start/end/scrub/pin, Lenis, AOS…);
211
+ and a REAL wheel scroll through the page that tells apart reveal-on-scroll
212
+ elements (with their transition), scrub/parallax elements, and scroll hijacking.
213
+
214
+ Same engine as browser_capture{kinds:['motion']} on reference sites — so you can
215
+ compare "theirs vs mine" on equal terms: did my reveals actually wire up, is my
216
+ ScrollTrigger range what I meant, did I forget prefers-reduced-motion. Pure
217
+ declarations in your CSS you can Read; this tells you what the BROWSER sees at
218
+ runtime, which is what the user sees.
219
+
220
+ Fresh load by default (reproducible). live:true runs it on the artifact session's
221
+ current page (it scrolls the page and returns to top — reveals get triggered).
222
+ For how the motion LOOKS use screenshot_canvas frames; for numbers use trace_motion.`,
223
+ {
224
+ path: z.string().optional().describe(CANVAS_PATH_DESC),
225
+ device: z.enum(['desktop', 'tablet', 'mobile']).optional().describe('SITE ONLY, fresh-load mode: viewport width to inventory at (default desktop).'),
226
+ live: z.boolean().optional().describe(LIVE_PARAM_DESC),
227
+ },
228
+ async ({ path: relPath, device, live }) => {
229
+ let acq;
230
+ try {
231
+ const target = await resolveCanvasTarget(workspaceRoot, relPath, sessionId);
232
+ if (!target || !target.ok) return asText(target?.message || 'No artifact found — pass path.', true);
233
+ const guard = requireBrowsable(target);
234
+ if (guard) return asText(guard, true);
235
+ const vp = await defaultViewportFor(target, device);
236
+ acq = await acquireArtifactPage({ projectId, workspaceRoot, target, live, viewport: vp });
237
+ const inv = await collectMotionInventory(acq.page);
238
+ const lines = [
239
+ `motion inventory — ${target.relPath} @ ${acq.viewport.width}x${acq.viewport.height}`,
240
+ degradedNote(acq), acq.liveNote, acq.gotoNote, '',
241
+ ...formatMotionInventory(inv),
242
+ '', '→ to SEE it: screenshot_canvas { frames:[2-30 ms offsets], trigger/click or live:true }; to MEASURE a curve: trace_motion.',
243
+ ].filter(l => l != null);
244
+ return asText(lines.join('\n'));
245
+ } catch (err) {
246
+ return asText(`artifact_motion 失败:${err.message}`, true);
247
+ } finally {
248
+ await acq?.release?.();
249
+ }
250
+ },
251
+ );
252
+ }
253
+
254
+ /** artifact_batch 能跑的:会话四件 + 五个能 live 的量具(它们在 batch 里要自己带 live:true) */
255
+ export const ARTIFACT_BATCHABLE = [
256
+ 'artifact_open', 'artifact_computer', 'artifact_find', 'artifact_motion',
257
+ 'screenshot_canvas', 'trace_motion', 'get_computed_styles', 'explain_style', 'query_elements',
258
+ ];
259
+
260
+ export function makeArtifactBatchTool({ tools }) {
261
+ const names = ARTIFACT_BATCHABLE.filter(n => tools.some(t => t.name === n));
262
+ return makeBatchTool({
263
+ name: 'artifact_batch',
264
+ tools,
265
+ batchable: ARTIFACT_BATCHABLE,
266
+ finalShot: { name: 'artifact_computer', input: { action: 'screenshot' } },
267
+ description: `Run several artifact-session steps in ONE round trip: open → click → type →
268
+ key → look, or click → trace_motion(live:true) → screenshot. Items run in order
269
+ and STOP at the first error; later items get "${HALT_TEXT}". A session
270
+ screenshot is appended at the end unless the last item already produced an
271
+ image (or screenshotAfter:false). Measuring tools inside a batch need
272
+ live:true in their input or they will open their own fresh page. Coordinates
273
+ refer to the screenshot you saw BEFORE the call. Batchable: ${names.join(', ')}.
274
+ Example: [{"name":"artifact_open","input":{}},{"name":"artifact_find","input":{"query":"start button"}},{"name":"artifact_computer","input":{"action":"left_click","ref":"ref_1"}},{"name":"artifact_computer","input":{"action":"key","text":"ArrowRight","repeat":10}},{"name":"screenshot_canvas","input":{"live":true,"frames":[0,120,240,480]}}]`,
275
+ });
276
+ }
277
+
278
+ export { peekSession };