@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,96 @@
1
+ /**
2
+ * mcp/tools/tier-gate.js —— 按账号档位(auth/tier.js)给 MCP 工具套闸的包装器(08-21 晚)。
3
+ *
4
+ * 为什么是包装器而不是改工具本体:generate-image.js / web-search.js 都是行数棘轮
5
+ * 冻结的胖户(拆不抬),而且"谁能用这个工具"跟"这个工具怎么干活"本来就是两层。
6
+ * 闸按**项目 owner** 算(同 publish_site / paint_still / roll_film 一把尺),不看请求者、
7
+ * 不看会话跑在哪个模型上(用户 08-21 拍板:只做档位隔离,不做模型隔离)。
8
+ *
9
+ * 用法(mcp/index.js 工具列表里):
10
+ * withTierGate(makeGenerateImageTool({...}), 'imageGen', projectId)
11
+ * withTierGate(makeWebSearchTool({...}), 'webSearch', projectId) // basic 档附带日上限
12
+ */
13
+ import { getProject } from '../../../projects/store.js';
14
+ import { getUserById } from '../../../auth/users-store.js';
15
+ import { can, webSearchDailyCap, DENIAL } from '../../../auth/tier.js';
16
+ import { makeRateWindow } from '../../../lib/rate-window.js';
17
+ import { checkQuota, imageChargeUsd } from '../../../lib/quota.js';
18
+
19
+ /** 项目 owner 的用户对象;无主 / 找不到 → null(tier.can(null) 一律 false,fail-closed) */
20
+ export function ownerOfProject(projectId) {
21
+ const ownerId = projectId ? getProject(projectId)?.ownerId : null;
22
+ return ownerId ? getUserById(ownerId) : null;
23
+ }
24
+
25
+ // basic 档 web_search 日上限:tavily/baidu 是花钱的,300 轮/天的回合闸拦不住一轮里连搜几十次。
26
+ // 内存滑动窗口按 owner 计(重启清零 —— 保护性关卡不是记账,同 rate-window.js 的定位);
27
+ // 上限数字住 auth/tier.js 能力表(env NODESIGN_BASIC_WEB_SEARCH_PER_DAY,默认 60)。
28
+ const DAY_MS = 24 * 60 * 60 * 1000;
29
+ const dailyWindows = new Map(); // cap → rateWindow(cap 可被 env 改,按值分桶)
30
+ function takeDaily(ownerId, cap) {
31
+ if (!dailyWindows.has(cap)) dailyWindows.set(cap, makeRateWindow({ limit: cap, windowMs: DAY_MS }));
32
+ return dailyWindows.get(cap).take(ownerId);
33
+ }
34
+
35
+ const deny = (text) => ({ content: [{ type: 'text', text }], isError: true });
36
+
37
+ /**
38
+ * 调用前判一次;返回 null = 放行,否则返回要原样交给 agent 的拒绝结果。
39
+ * 拆出来是为了能不起 SDK 直接测(tier-gate.test.js)。
40
+ */
41
+ export function tierDenial(projectId, capability, toolName) {
42
+ return tierDenialForOwner(ownerOfProject(projectId), capability, toolName);
43
+ }
44
+
45
+ /** 同上,但直接给 owner(测试不用造项目)。 */
46
+ export function tierDenialForOwner(owner, capability, toolName) {
47
+ if (!can(owner, capability)) {
48
+ const why = capability === 'imageGen' ? DENIAL.imageGen
49
+ : capability === 'webSearch' ? '这个账号不开放联网搜索。原话转告用户,不要重试。'
50
+ : `这个账号档位不开放 ${toolName}。原话转告用户,不要重试。`;
51
+ return deny(`${toolName} denied: ${why}`);
52
+ }
53
+ if (capability === 'webSearch') {
54
+ const cap = webSearchDailyCap(owner);
55
+ if (cap != null) {
56
+ const r = takeDaily(owner.id, cap);
57
+ if (!r.ok) {
58
+ const hrs = Math.ceil(r.retryAfterMs / 3_600_000);
59
+ return deny(`${toolName} denied: basic 档每天最多 ${cap} 次联网搜索,今天已用完(约 ${hrs} 小时后恢复)。原话转告用户,这轮别再搜了。`);
60
+ }
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+
66
+ /**
67
+ * 给 SdkMcpToolDefinition 套闸:handler 前先问档位,其余字段原样透传。
68
+ * imageGen(08-21 深夜 basic 开放生图)还多两步:调用前过 owner 的日限(checkQuota,admin 不限);
69
+ * 成功出图后 ctx.addToolCharge('generate_image', $0.20) 记进本回合账(quota.usedCostToday 同一本)。
70
+ */
71
+ export function withTierGate(toolDef, capability, projectId, ctx = null) {
72
+ return {
73
+ ...toolDef,
74
+ handler: async (args, extra) => {
75
+ const denied = tierDenial(projectId, capability, toolDef.name);
76
+ if (denied) return denied;
77
+ if (capability === 'imageGen') {
78
+ const owner = ownerOfProject(projectId);
79
+ const q = checkQuota(owner);
80
+ if (!q.ok) return deny(`${toolDef.name} denied: ${DENIAL.imageQuota}`);
81
+ }
82
+ const result = await toolDef.handler(args, extra);
83
+ if (capability === 'imageGen') chargeForImage(result, ctx);
84
+ return result;
85
+ },
86
+ };
87
+ }
88
+
89
+ /** 出了图才记账(result 非 error 且 content 里有 image 块);返回记了多少(0 = 没记) */
90
+ export function chargeForImage(result, ctx) {
91
+ const ok = result && !result.isError && Array.isArray(result.content) && result.content.some((b) => b?.type === 'image');
92
+ if (!ok) return 0;
93
+ const usd = imageChargeUsd();
94
+ ctx?.addToolCharge?.('generate_image', usd);
95
+ return usd;
96
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * mcp/tools/trace-motion.js — trace_motion(2026-08-19,问题库 iss_mszv782a_toab)
3
+ *
4
+ * ## 为什么有这个工具
5
+ *
6
+ * 胶片条(screenshot_canvas frames)解决"看得见",这个解决"量得出"。上报里
7
+ * 的三类事故它都能直接抓:
8
+ * - 装弹位姿写到镜头背后(z=-2.76,镜头在 -2.68)—— 采一条 z 曲线,数字直接露馅,
9
+ * 不用赌"恰好在静帧上也是错的"
10
+ * - 两个 tween 之间硬切 —— 单帧跳变检测,标出时刻
11
+ * - 过冲回稳 170ms 够不够 —— overshoot% 和 settle 时刻都是量出来的数
12
+ * 帧健康(fps/p95/最长帧)顺带回传:按帧衰减、卡顿这类"环境恰好跑得慢才暴露"
13
+ * 的问题从此不靠运气。
14
+ *
15
+ * ## 数字怎么读
16
+ *
17
+ * ⚠️ 同 profile_scroll:1 vCPU、录制自身有开销,绝对帧率不代表用户设备。
18
+ * 曲线形状(过冲/硬切/稳定时间)不受影响 —— 它们跟的是页面自己的时钟。
19
+ */
20
+
21
+ import { tool } from '@anthropic-ai/claude-agent-sdk';
22
+ import { z } from 'zod';
23
+ import { resolveCanvasTarget, CANVAS_PATH_DESC, KIND_SITE, requireBrowsable } from '../../../lib/artifact-target.js';
24
+ import { resolveDeckSize, extractDeckAspect } from '../../../shared/deck.js';
25
+ import { degradedNote } from './helpers/perception-page.js';
26
+ import { acquireArtifactPage, LIVE_PARAM_DESC } from './helpers/acquire-page.js';
27
+ import { runWaitFor, runBeforeShot, attachPageDiagnostics, normalizeShot } from './helpers/shot-pipeline.js';
28
+ import { recordMotion, seriesReport, chartSvg, fmtNum, motionCaptionLines } from './helpers/motion-lab.js';
29
+ import { wheelScroll, elementMotionReport, elementMotionLines } from './helpers/motion-scroll.js';
30
+ import { promises as fs } from 'node:fs';
31
+
32
+ export function makeTraceMotionTool({ workspaceRoot, projectId, sessionId }) {
33
+ return tool(
34
+ 'trace_motion',
35
+ `Numerically trace a motion: sample JS expressions once per animation frame
36
+ while a move plays, and get back per-curve statistics plus ONE rendered chart
37
+ image. This is the instrument for easing quality — where a screenshot guesses,
38
+ this measures.
39
+
40
+ Give it named expressions (page context, evaluated every rAF):
41
+ expressions: { gun_y: "window.game.gun.position.y",
42
+ cam_z: "window.game.camera.position.z" }
43
+ plus trigger:"window.game.startReload()" (JS that starts the move) and/or
44
+ click:"#fire" (a REAL trusted click — needed for pointer lock / AudioContext).
45
+
46
+ Per curve you get: first/final/min/max, overshoot % of travel, settle time
47
+ (last moment it was >3% of travel away from final), and HARD CUTS — single-frame
48
+ jumps >22% of range, i.e. the visible snap between two tweens or a teleporting
49
+ bone. The chart draws every curve (normalized, real ranges in the legend) with
50
+ cut moments marked in red. Also returned: frame health (fps / p95 / worst frame
51
+ — catches per-frame decay written without dt, and jank) and an audio event log
52
+ (when media.play()/bufferSource.start() fired — you cannot hear, but you can
53
+ check sync against the motion).
54
+
55
+ Use it when:
56
+ - an easing feels wrong and you need to see WHERE (attack too soft? no follow-
57
+ through? overshoot 0%?) — sample the animated property itself
58
+ - you suspect a position/rotation goes somewhere silly (behind the camera,
59
+ under the floor) — sample it; the numbers do not depend on luck
60
+ - the user says an animation is janky/mushy — run with no expressions at all:
61
+ you still get frame health during the move
62
+ - two tweens meet and you want to prove the transition is C1-smooth — the cut
63
+ detector is exactly that check
64
+
65
+ Works on any browsable artifact (deck or site). ⚠️ Absolute fps numbers are from
66
+ a 1-vCPU box with recording overhead — use them for A/B, not as the user's
67
+ experience. Curve SHAPES (overshoot, cuts, settle) follow the page's own clock
68
+ and are trustworthy.
69
+
70
+ For SEEING the frames instead of measuring them, use screenshot_canvas with
71
+ frames:[...] (filmstrip contact sheet).`,
72
+ {
73
+ path: z.string().optional().describe(CANVAS_PATH_DESC),
74
+ live: z.boolean().optional().describe(LIVE_PARAM_DESC),
75
+ scrollBy: z.number().min(-8000).max(8000).optional()
76
+ .describe('Pixels of REAL wheel scrolling dispatched over the recording window (positive = down): trace scroll-driven motion (ScrollTrigger scrub, parallax, reveals) the way a visitor triggers it. Can combine with trigger/click.'),
77
+ elements: z.boolean().optional()
78
+ .describe('Also run the element probe (default true): which elements moved / faded / scaled during the recording, by how much and when — the no-expression way to see who moves.'),
79
+ expressions: z
80
+ .record(z.string(), z.string())
81
+ .optional()
82
+ .describe('Named JS expressions sampled every animation frame, e.g. {"gun_y": "window.game.gun.position.y"}. Names: ASCII letters/digits/underscore. Max 6. Each must evaluate to a number. Omit to trace frame health only.'),
83
+ durationMs: z
84
+ .number()
85
+ .int()
86
+ .min(300)
87
+ .max(15000)
88
+ .optional()
89
+ .describe('How long to record after the trigger (default 2000ms). Cover the whole move plus a settle margin.'),
90
+ trigger: z
91
+ .string()
92
+ .optional()
93
+ .describe('JS snippet that STARTS the motion, evaluated in page context at t=0 (await OK). Omit to trace whatever is already animating.'),
94
+ click: z
95
+ .string()
96
+ .optional()
97
+ .describe('CSS selector to REAL-click at t=0 (trusted user gesture — pointer lock, AudioContext, autoplay). Fires before trigger if both given.'),
98
+ waitFor: z
99
+ .string()
100
+ .optional()
101
+ .describe('JS expression polled every 100ms until truthy before anything else runs (15s budget) — wait for slow boots: "window.__game".'),
102
+ beforeShot: z
103
+ .string()
104
+ .optional()
105
+ .describe('Setup JS run after waitFor, before recording starts (10s budget) — e.g. skip an intro, select a weapon.'),
106
+ viewport: z
107
+ .object({
108
+ width: z.number().int().min(320).max(3840),
109
+ height: z.number().int().min(240).max(2160),
110
+ })
111
+ .optional()
112
+ .describe('Browser viewport; defaults to the deck aspect (decks) or 1440x900 (sites).'),
113
+ },
114
+ async ({ path: relPath, expressions, durationMs, trigger, click, waitFor, beforeShot, viewport, live, scrollBy, elements }) => {
115
+ const target = await resolveCanvasTarget(workspaceRoot, relPath, sessionId);
116
+ if (!target.ok) return { content: [{ type: 'text', text: target.message }], isError: true };
117
+ const guard = requireBrowsable(target);
118
+ if (guard) return { content: [{ type: 'text', text: guard }], isError: true };
119
+
120
+ const names = Object.keys(expressions || {});
121
+ if (names.length > 6) {
122
+ return { content: [{ type: 'text', text: 'Max 6 expressions per trace — run twice instead.' }], isError: true };
123
+ }
124
+ const badName = names.find((n) => !/^[A-Za-z_][A-Za-z0-9_]{0,39}$/.test(n));
125
+ if (badName) {
126
+ return { content: [{ type: 'text', text: `Expression name "${badName}" — use ASCII letters/digits/underscore only.` }], isError: true };
127
+ }
128
+
129
+ let vp = viewport;
130
+ if (!vp) {
131
+ if (target.kind === KIND_SITE) vp = { width: 1440, height: 900 };
132
+ else {
133
+ const html = await fs.readFile(target.absPath, 'utf8').catch(() => '');
134
+ const d = resolveDeckSize(extractDeckAspect(html));
135
+ vp = { width: d.width, height: d.height };
136
+ }
137
+ }
138
+
139
+ const dur = durationMs ?? 2000;
140
+ let acq;
141
+ try {
142
+ acq = await acquireArtifactPage({ projectId, workspaceRoot, target, live, viewport: vp });
143
+ const page = acq.page;
144
+ const opened = acq;
145
+ if (acq.live) vp = acq.viewport;
146
+ const diag = attachPageDiagnostics(page);
147
+
148
+ const waitForNote = waitFor ? await runWaitFor(page, waitFor) : null;
149
+ const beforeShotNote = beforeShot ? await runBeforeShot(page, beforeShot) : null;
150
+
151
+ // 纯数值通道:不开 screencast,jpeg 编码那份 CPU 省给页面本身
152
+ const y0 = await page.evaluate(() => window.scrollY).catch(() => 0);
153
+ const during = scrollBy ? (p) => wheelScroll(p, { px: scrollBy, durationMs: Math.max(200, dur - 100) }) : null;
154
+ const rec = await recordMotion(page, {
155
+ durationMs: dur, trigger, click, during, expressions, wantShots: false, probeElements: elements !== false,
156
+ });
157
+ const y1 = await page.evaluate(() => window.scrollY).catch(() => y0);
158
+ const probe = elements !== false ? elementMotionReport(rec.elems, { scrolledPx: y1 - y0 }) : null;
159
+
160
+ const lines = [];
161
+ const degraded = degradedNote(opened);
162
+ if (degraded) lines.push(degraded, '');
163
+ if (acq.liveNote) lines.push(acq.liveNote, '');
164
+ if (acq.gotoNote) lines.push(acq.gotoNote, '');
165
+ lines.push(`trace_motion — ${target.relPath} @ ${vp.width}x${vp.height}, ${dur}ms after t=0${trigger || click ? '' : ' (no trigger — ambient recording)'}`);
166
+
167
+ const seriesList = [];
168
+ for (const name of names) {
169
+ if (rec.errs[name]) {
170
+ lines.push(`✗ ${name}: ${rec.errs[name]}`);
171
+ continue;
172
+ }
173
+ const points = rec.rows.map((r) => ({ t: r.t, v: r[name] }));
174
+ const rep = seriesReport(points);
175
+ if (!rep.ok) {
176
+ lines.push(`✗ ${name}: only ${rep.n} numeric samples — nothing to say`);
177
+ continue;
178
+ }
179
+ seriesList.push({ name, points, report: rep });
180
+ const bits = [
181
+ `${name}: ${fmtNum(rep.first)} → ${fmtNum(rep.final)} (min ${fmtNum(rep.min)}, max ${fmtNum(rep.max)}, ${rep.n} samples)`,
182
+ ];
183
+ if (rep.still) {
184
+ bits.push(' ⚠ value never changed — the expression is right but nothing moved (wrong object? move never started?)');
185
+ } else {
186
+ bits.push(` overshoot ${rep.overshootPct.toFixed(1)}% of travel, settled by ~${Math.round(rep.settleMs)}ms`);
187
+ if (rep.cuts.length) {
188
+ bits.push(` ⚠ HARD CUT at ${rep.cuts.map((t) => `${t}ms`).join(', ')} — single-frame jump >22% of range (tween boundary snap / teleport)`);
189
+ }
190
+ }
191
+ lines.push(...bits);
192
+ }
193
+
194
+ if (probe) lines.push('', ...elementMotionLines(probe));
195
+ lines.push('', ...motionCaptionLines(rec));
196
+ const diagText = diag.summary();
197
+ if (diagText) lines.push(diagText);
198
+
199
+ const content = [{ type: 'text', text: lines.join('\n') }];
200
+ if (seriesList.length) {
201
+ const { default: sharp } = await import('sharp');
202
+ const svg = chartSvg(seriesList, dur);
203
+ const png = await sharp(Buffer.from(svg)).png().toBuffer();
204
+ const shot = await normalizeShot(png);
205
+ content.push({ type: 'image', data: shot.data, mimeType: shot.mimeType });
206
+ }
207
+ return { content };
208
+ } catch (err) {
209
+ return { content: [{ type: 'text', text: `trace_motion failed: ${err?.message || String(err)}` }], isError: true };
210
+ } finally {
211
+ await acq?.release?.(); // 一次性:关浏览器;live:松会话锁
212
+ }
213
+ },
214
+ );
215
+ }