@imgly/codesign-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (816) hide show
  1. package/LICENSE.md +16 -0
  2. package/README.md +158 -0
  3. package/assets/docs/api/SKILL.md +49 -0
  4. package/assets/docs/api/index.d.ts +10518 -0
  5. package/assets/docs/guide/SKILL.md +142 -0
  6. package/assets/docs/guide/actions.md +1038 -0
  7. package/assets/docs/guide/animation/create/base.md +467 -0
  8. package/assets/docs/guide/animation/create/text.md +453 -0
  9. package/assets/docs/guide/animation/create.md +558 -0
  10. package/assets/docs/guide/animation/edit.md +501 -0
  11. package/assets/docs/guide/animation/overview.md +22 -0
  12. package/assets/docs/guide/animation/types.md +430 -0
  13. package/assets/docs/guide/animation.md +23 -0
  14. package/assets/docs/guide/api/AssetAPI.md +602 -0
  15. package/assets/docs/guide/api/BlockAPI.md +6152 -0
  16. package/assets/docs/guide/api/CreativeEngine.md +180 -0
  17. package/assets/docs/guide/api/EditorAPI.md +1261 -0
  18. package/assets/docs/guide/api/EventAPI.md +25 -0
  19. package/assets/docs/guide/api/SceneAPI.md +729 -0
  20. package/assets/docs/guide/api/VariableAPI.md +59 -0
  21. package/assets/docs/guide/api/types.md +71 -0
  22. package/assets/docs/guide/api-reference/overview.md +20 -0
  23. package/assets/docs/guide/automation/auto-resize.md +412 -0
  24. package/assets/docs/guide/automation/batch-processing.md +474 -0
  25. package/assets/docs/guide/automation/data-merge.md +406 -0
  26. package/assets/docs/guide/automation/design-generation.md +107 -0
  27. package/assets/docs/guide/automation/overview.md +16 -0
  28. package/assets/docs/guide/automation.md +24 -0
  29. package/assets/docs/guide/browser-support.md +38 -0
  30. package/assets/docs/guide/capabilities.md +18 -0
  31. package/assets/docs/guide/colors/adjust.md +551 -0
  32. package/assets/docs/guide/colors/apply.md +349 -0
  33. package/assets/docs/guide/colors/basics.md +440 -0
  34. package/assets/docs/guide/colors/conversion.md +504 -0
  35. package/assets/docs/guide/colors/create-color-palette.md +426 -0
  36. package/assets/docs/guide/colors/for-print/cmyk.md +577 -0
  37. package/assets/docs/guide/colors/for-print/spot.md +751 -0
  38. package/assets/docs/guide/colors/for-print.md +21 -0
  39. package/assets/docs/guide/colors/for-screen/p3.md +60 -0
  40. package/assets/docs/guide/colors/for-screen/srgb.md +463 -0
  41. package/assets/docs/guide/colors/for-screen.md +21 -0
  42. package/assets/docs/guide/colors/overview.md +20 -0
  43. package/assets/docs/guide/colors/replace.md +535 -0
  44. package/assets/docs/guide/colors.md +28 -0
  45. package/assets/docs/guide/compatibility.md +27 -0
  46. package/assets/docs/guide/concepts/architecture.md +99 -0
  47. package/assets/docs/guide/concepts/assets.md +360 -0
  48. package/assets/docs/guide/concepts/blocks.md +750 -0
  49. package/assets/docs/guide/concepts/buffers.md +546 -0
  50. package/assets/docs/guide/concepts/design-units.md +333 -0
  51. package/assets/docs/guide/concepts/edit-modes.md +431 -0
  52. package/assets/docs/guide/concepts/editing-workflow.md +303 -0
  53. package/assets/docs/guide/concepts/events.md +466 -0
  54. package/assets/docs/guide/concepts/headless-mode/browser.md +291 -0
  55. package/assets/docs/guide/concepts/pages.md +396 -0
  56. package/assets/docs/guide/concepts/resources.md +496 -0
  57. package/assets/docs/guide/concepts/scenes.md +443 -0
  58. package/assets/docs/guide/concepts/templating.md +194 -0
  59. package/assets/docs/guide/concepts/terminology.md +296 -0
  60. package/assets/docs/guide/concepts/undo-and-history.md +461 -0
  61. package/assets/docs/guide/concepts.md +38 -0
  62. package/assets/docs/guide/configuration.md +469 -0
  63. package/assets/docs/guide/conversion/overview.md +22 -0
  64. package/assets/docs/guide/conversion/to-base64.md +234 -0
  65. package/assets/docs/guide/conversion/to-pdf.md +616 -0
  66. package/assets/docs/guide/conversion/to-png.md +290 -0
  67. package/assets/docs/guide/conversion.md +23 -0
  68. package/assets/docs/guide/create-audio/audio/add-music.md +430 -0
  69. package/assets/docs/guide/create-audio/audio/add-sound-effects.md +664 -0
  70. package/assets/docs/guide/create-audio/audio/loop.md +370 -0
  71. package/assets/docs/guide/create-audio/audio.md +336 -0
  72. package/assets/docs/guide/create-composition/add-background.md +395 -0
  73. package/assets/docs/guide/create-composition/blend-modes.md +372 -0
  74. package/assets/docs/guide/create-composition/collage.md +432 -0
  75. package/assets/docs/guide/create-composition/group-and-ungroup.md +388 -0
  76. package/assets/docs/guide/create-composition/layer-management.md +503 -0
  77. package/assets/docs/guide/create-composition/layout.md +396 -0
  78. package/assets/docs/guide/create-composition/lock-design.md +362 -0
  79. package/assets/docs/guide/create-composition/multi-page.md +204 -0
  80. package/assets/docs/guide/create-composition/overview.md +18 -0
  81. package/assets/docs/guide/create-composition/programmatic.md +593 -0
  82. package/assets/docs/guide/create-composition.md +30 -0
  83. package/assets/docs/guide/create-templates/add-dynamic-content/placeholders.md +688 -0
  84. package/assets/docs/guide/create-templates/add-dynamic-content/set-editing-constraints.md +600 -0
  85. package/assets/docs/guide/create-templates/add-dynamic-content/text-variables.md +647 -0
  86. package/assets/docs/guide/create-templates/add-dynamic-content.md +307 -0
  87. package/assets/docs/guide/create-templates/add-to-template-library.md +297 -0
  88. package/assets/docs/guide/create-templates/edit-or-remove.md +441 -0
  89. package/assets/docs/guide/create-templates/from-scratch.md +558 -0
  90. package/assets/docs/guide/create-templates/import/from-scene-file.md +440 -0
  91. package/assets/docs/guide/create-templates/import.md +244 -0
  92. package/assets/docs/guide/create-templates/lock.md +325 -0
  93. package/assets/docs/guide/create-templates/overview.md +16 -0
  94. package/assets/docs/guide/create-templates.md +32 -0
  95. package/assets/docs/guide/create-video/audio/adjust-speed.md +302 -0
  96. package/assets/docs/guide/create-video/audio/adjust-volume.md +346 -0
  97. package/assets/docs/guide/create-video/control.md +285 -0
  98. package/assets/docs/guide/create-video/limitations.md +396 -0
  99. package/assets/docs/guide/create-video/overview.md +224 -0
  100. package/assets/docs/guide/create-video/timeline-editor.md +622 -0
  101. package/assets/docs/guide/create-video/update-caption-presets.md +676 -0
  102. package/assets/docs/guide/create-video.md +32 -0
  103. package/assets/docs/guide/edit-image/add-watermark.md +497 -0
  104. package/assets/docs/guide/edit-image/overview.md +22 -0
  105. package/assets/docs/guide/edit-image/remove-bg.md +420 -0
  106. package/assets/docs/guide/edit-image/replace-colors.md +680 -0
  107. package/assets/docs/guide/edit-image/transform/crop.md +523 -0
  108. package/assets/docs/guide/edit-image/transform/move.md +279 -0
  109. package/assets/docs/guide/edit-image/transform/resize.md +301 -0
  110. package/assets/docs/guide/edit-image/transform/rotate.md +408 -0
  111. package/assets/docs/guide/edit-image/transform/scale.md +278 -0
  112. package/assets/docs/guide/edit-image/transform.md +24 -0
  113. package/assets/docs/guide/edit-image/vectorize.md +204 -0
  114. package/assets/docs/guide/edit-image.md +25 -0
  115. package/assets/docs/guide/edit-video/add-captions.md +589 -0
  116. package/assets/docs/guide/edit-video/add-watermark.md +429 -0
  117. package/assets/docs/guide/edit-video/join-and-arrange.md +540 -0
  118. package/assets/docs/guide/edit-video/redaction.md +544 -0
  119. package/assets/docs/guide/edit-video/split.md +634 -0
  120. package/assets/docs/guide/edit-video/transform/crop.md +380 -0
  121. package/assets/docs/guide/edit-video/transform/flip.md +182 -0
  122. package/assets/docs/guide/edit-video/transform/move.md +413 -0
  123. package/assets/docs/guide/edit-video/transform/resize.md +534 -0
  124. package/assets/docs/guide/edit-video/transform/rotate.md +312 -0
  125. package/assets/docs/guide/edit-video/transform/scale.md +603 -0
  126. package/assets/docs/guide/edit-video/transform.md +25 -0
  127. package/assets/docs/guide/edit-video/trim.md +773 -0
  128. package/assets/docs/guide/engine-interface.md +108 -0
  129. package/assets/docs/guide/export-save-publish/create-thumbnail.md +292 -0
  130. package/assets/docs/guide/export-save-publish/export/compress.md +639 -0
  131. package/assets/docs/guide/export-save-publish/export/overview.md +576 -0
  132. package/assets/docs/guide/export-save-publish/export/partial-export.md +694 -0
  133. package/assets/docs/guide/export-save-publish/export/size-limits.md +401 -0
  134. package/assets/docs/guide/export-save-publish/export/to-html5.md +474 -0
  135. package/assets/docs/guide/export-save-publish/export/to-jpeg.md +312 -0
  136. package/assets/docs/guide/export-save-publish/export/to-mp4.md +364 -0
  137. package/assets/docs/guide/export-save-publish/export/to-pdf.md +389 -0
  138. package/assets/docs/guide/export-save-publish/export/to-png.md +255 -0
  139. package/assets/docs/guide/export-save-publish/export/to-raw-data.md +303 -0
  140. package/assets/docs/guide/export-save-publish/export/to-webp.md +261 -0
  141. package/assets/docs/guide/export-save-publish/export/with-color-mask.md +278 -0
  142. package/assets/docs/guide/export-save-publish/export.md +36 -0
  143. package/assets/docs/guide/export-save-publish/for-printing.md +423 -0
  144. package/assets/docs/guide/export-save-publish/for-social-media.md +318 -0
  145. package/assets/docs/guide/export-save-publish/pre-export-validation.md +698 -0
  146. package/assets/docs/guide/export-save-publish/save.md +340 -0
  147. package/assets/docs/guide/export-save-publish/store-custom-metadata.md +367 -0
  148. package/assets/docs/guide/file-format-support.md +34 -0
  149. package/assets/docs/guide/fills/color.md +678 -0
  150. package/assets/docs/guide/fills/image.md +539 -0
  151. package/assets/docs/guide/fills/overview.md +144 -0
  152. package/assets/docs/guide/fills/video.md +641 -0
  153. package/assets/docs/guide/fills.md +24 -0
  154. package/assets/docs/guide/filters-and-effects/apply.md +1019 -0
  155. package/assets/docs/guide/filters-and-effects/blur.md +382 -0
  156. package/assets/docs/guide/filters-and-effects/chroma-key-green-screen.md +445 -0
  157. package/assets/docs/guide/filters-and-effects/create-custom-filters.md +614 -0
  158. package/assets/docs/guide/filters-and-effects/create-custom-lut-filter.md +426 -0
  159. package/assets/docs/guide/filters-and-effects/distortion.md +527 -0
  160. package/assets/docs/guide/filters-and-effects/duotone.md +602 -0
  161. package/assets/docs/guide/filters-and-effects/gradients.md +1311 -0
  162. package/assets/docs/guide/filters-and-effects/overview.md +22 -0
  163. package/assets/docs/guide/filters-and-effects/support.md +623 -0
  164. package/assets/docs/guide/filters-and-effects.md +28 -0
  165. package/assets/docs/guide/get-started/agent-skills.md +119 -0
  166. package/assets/docs/guide/get-started/build-with-ai.md +45 -0
  167. package/assets/docs/guide/get-started/mcp-server.md +119 -0
  168. package/assets/docs/guide/get-started/overview.md +28 -0
  169. package/assets/docs/guide/get-started/vanilla-js/quickstart.md +175 -0
  170. package/assets/docs/guide/grid-and-rulers.md +222 -0
  171. package/assets/docs/guide/guides/export-save-publish/export/audio.md +224 -0
  172. package/assets/docs/guide/guides/text/rendering-internals.md +796 -0
  173. package/assets/docs/guide/guides.md +49 -0
  174. package/assets/docs/guide/import-media/asset-library.md +23 -0
  175. package/assets/docs/guide/import-media/asset-panel/basics.md +324 -0
  176. package/assets/docs/guide/import-media/asset-panel/customize.md +478 -0
  177. package/assets/docs/guide/import-media/asset-panel/refresh-assets.md +415 -0
  178. package/assets/docs/guide/import-media/asset-panel/thumbnails.md +633 -0
  179. package/assets/docs/guide/import-media/capture-from-camera/record-video.md +137 -0
  180. package/assets/docs/guide/import-media/capture-from-camera.md +20 -0
  181. package/assets/docs/guide/import-media/concepts.md +173 -0
  182. package/assets/docs/guide/import-media/content-json-schema.md +615 -0
  183. package/assets/docs/guide/import-media/default-assets.md +381 -0
  184. package/assets/docs/guide/import-media/edit-or-remove-assets.md +489 -0
  185. package/assets/docs/guide/import-media/file-format-support.md +178 -0
  186. package/assets/docs/guide/import-media/from-local-source/user-upload.md +438 -0
  187. package/assets/docs/guide/import-media/from-local-source.md +20 -0
  188. package/assets/docs/guide/import-media/from-remote-source/asset-versioning.md +390 -0
  189. package/assets/docs/guide/import-media/from-remote-source/getty-images.md +627 -0
  190. package/assets/docs/guide/import-media/from-remote-source/imgly-premium-assets.md +625 -0
  191. package/assets/docs/guide/import-media/from-remote-source/pexels.md +692 -0
  192. package/assets/docs/guide/import-media/from-remote-source/remote-asset.md +473 -0
  193. package/assets/docs/guide/import-media/from-remote-source/soundstripe.md +497 -0
  194. package/assets/docs/guide/import-media/from-remote-source/third-party.md +51 -0
  195. package/assets/docs/guide/import-media/from-remote-source/unsplash.md +914 -0
  196. package/assets/docs/guide/import-media/from-remote-source/your-server.md +764 -0
  197. package/assets/docs/guide/import-media/from-remote-source.md +28 -0
  198. package/assets/docs/guide/import-media/overview.md +32 -0
  199. package/assets/docs/guide/import-media/retrieve-mimetype.md +274 -0
  200. package/assets/docs/guide/import-media/size-limits.md +20 -0
  201. package/assets/docs/guide/import-media/source-sets.md +476 -0
  202. package/assets/docs/guide/import-media.md +32 -0
  203. package/assets/docs/guide/insert-media/audio.md +291 -0
  204. package/assets/docs/guide/insert-media/images.md +380 -0
  205. package/assets/docs/guide/insert-media/position-and-align.md +734 -0
  206. package/assets/docs/guide/insert-media/shapes-or-stickers.md +799 -0
  207. package/assets/docs/guide/insert-media/videos.md +308 -0
  208. package/assets/docs/guide/insert-media.md +24 -0
  209. package/assets/docs/guide/key-capabilities.md +24 -0
  210. package/assets/docs/guide/key-concepts.md +83 -0
  211. package/assets/docs/guide/licensing.md +45 -0
  212. package/assets/docs/guide/llms-txt.md +53 -0
  213. package/assets/docs/guide/open-the-editor/blank-canvas.md +124 -0
  214. package/assets/docs/guide/open-the-editor/from-htmlcanvas.md +228 -0
  215. package/assets/docs/guide/open-the-editor/from-image.md +205 -0
  216. package/assets/docs/guide/open-the-editor/from-template.md +189 -0
  217. package/assets/docs/guide/open-the-editor/from-video.md +274 -0
  218. package/assets/docs/guide/open-the-editor/import-design/from-archive.md +504 -0
  219. package/assets/docs/guide/open-the-editor/import-design/from-indesign.md +680 -0
  220. package/assets/docs/guide/open-the-editor/import-design/from-photoshop.md +865 -0
  221. package/assets/docs/guide/open-the-editor/import-design.md +481 -0
  222. package/assets/docs/guide/open-the-editor/load-scene.md +178 -0
  223. package/assets/docs/guide/open-the-editor/overview.md +20 -0
  224. package/assets/docs/guide/open-the-editor/set-zoom-level.md +303 -0
  225. package/assets/docs/guide/open-the-editor/uri-resolver.md +347 -0
  226. package/assets/docs/guide/open-the-editor.md +29 -0
  227. package/assets/docs/guide/outlines/overview.md +14 -0
  228. package/assets/docs/guide/outlines/shadows-and-glows.md +515 -0
  229. package/assets/docs/guide/outlines/strokes.md +292 -0
  230. package/assets/docs/guide/outlines.md +22 -0
  231. package/assets/docs/guide/overview.md +22 -0
  232. package/assets/docs/guide/performance.md +217 -0
  233. package/assets/docs/guide/plugins/asset-sources.md +553 -0
  234. package/assets/docs/guide/plugins/print-ready-pdf.md +549 -0
  235. package/assets/docs/guide/plugins.md +36 -0
  236. package/assets/docs/guide/rules/asset-handling.md +180 -0
  237. package/assets/docs/guide/rules/common-pitfalls.md +272 -0
  238. package/assets/docs/guide/rules/content-fill-mode.md +29 -0
  239. package/assets/docs/guide/rules/enforce-brand-guidelines.md +672 -0
  240. package/assets/docs/guide/rules/lock-content.md +478 -0
  241. package/assets/docs/guide/rules/moderate-content.md +761 -0
  242. package/assets/docs/guide/rules/overview.md +514 -0
  243. package/assets/docs/guide/rules/silent-init-errors.md +137 -0
  244. package/assets/docs/guide/rules/verify-properties-before-use.md +78 -0
  245. package/assets/docs/guide/rules.md +23 -0
  246. package/assets/docs/guide/security.md +199 -0
  247. package/assets/docs/guide/serve-assets.md +332 -0
  248. package/assets/docs/guide/settings.md +199 -0
  249. package/assets/docs/guide/shapes.md +23 -0
  250. package/assets/docs/guide/starterkits/3d-mockup-editor.md +748 -0
  251. package/assets/docs/guide/starterkits/advanced-editor.md +698 -0
  252. package/assets/docs/guide/starterkits/advanced-video-editor.md +696 -0
  253. package/assets/docs/guide/starterkits/ai-editor.md +749 -0
  254. package/assets/docs/guide/starterkits/airtable-image-editor.md +672 -0
  255. package/assets/docs/guide/starterkits/apparel-ui.md +188 -0
  256. package/assets/docs/guide/starterkits/assets.md +27 -0
  257. package/assets/docs/guide/starterkits/auto-resize.md +586 -0
  258. package/assets/docs/guide/starterkits/automated-video-generation.md +692 -0
  259. package/assets/docs/guide/starterkits/background-removal-editor.md +480 -0
  260. package/assets/docs/guide/starterkits/content-moderation.md +863 -0
  261. package/assets/docs/guide/starterkits/creative-automation.md +28 -0
  262. package/assets/docs/guide/starterkits/custom-built-uis.md +26 -0
  263. package/assets/docs/guide/starterkits/customization.md +29 -0
  264. package/assets/docs/guide/starterkits/cutout-lines-editor.md +470 -0
  265. package/assets/docs/guide/starterkits/data-merge.md +850 -0
  266. package/assets/docs/guide/starterkits/design-editor.md +698 -0
  267. package/assets/docs/guide/starterkits/design-generation.md +719 -0
  268. package/assets/docs/guide/starterkits/design-validation.md +808 -0
  269. package/assets/docs/guide/starterkits/editor-ui-configurations.md +14 -0
  270. package/assets/docs/guide/starterkits/export-options.md +724 -0
  271. package/assets/docs/guide/starterkits/export-using-renderer.md +708 -0
  272. package/assets/docs/guide/starterkits/extensibility.md +28 -0
  273. package/assets/docs/guide/starterkits/force-crop-editor.md +675 -0
  274. package/assets/docs/guide/starterkits/form-based-template-adoption.md +522 -0
  275. package/assets/docs/guide/starterkits/getty-images-editor.md +700 -0
  276. package/assets/docs/guide/starterkits/html5-ads-exporter.md +719 -0
  277. package/assets/docs/guide/starterkits/indesign-template-import.md +580 -0
  278. package/assets/docs/guide/starterkits/layouts-editor.md +724 -0
  279. package/assets/docs/guide/starterkits/mobile-ui.md +185 -0
  280. package/assets/docs/guide/starterkits/mockup-editor.md +745 -0
  281. package/assets/docs/guide/starterkits/multi-image-generation.md +542 -0
  282. package/assets/docs/guide/starterkits/page-sizes-editor.md +657 -0
  283. package/assets/docs/guide/starterkits/pexels-image-editor.md +665 -0
  284. package/assets/docs/guide/starterkits/photo-editor.md +755 -0
  285. package/assets/docs/guide/starterkits/photo-ui.md +186 -0
  286. package/assets/docs/guide/starterkits/photobook-ui.md +188 -0
  287. package/assets/docs/guide/starterkits/placeholders.md +678 -0
  288. package/assets/docs/guide/starterkits/player.md +405 -0
  289. package/assets/docs/guide/starterkits/plugins.md +25 -0
  290. package/assets/docs/guide/starterkits/postcard-editor.md +202 -0
  291. package/assets/docs/guide/starterkits/pptx-template-import.md +581 -0
  292. package/assets/docs/guide/starterkits/print-ready-pdf-editor.md +746 -0
  293. package/assets/docs/guide/starterkits/product-editor.md +773 -0
  294. package/assets/docs/guide/starterkits/psd-template-import.md +580 -0
  295. package/assets/docs/guide/starterkits/qr-code-editor.md +470 -0
  296. package/assets/docs/guide/starterkits/single-page-editor.md +661 -0
  297. package/assets/docs/guide/starterkits/start-with-image.md +684 -0
  298. package/assets/docs/guide/starterkits/start-with-video.md +651 -0
  299. package/assets/docs/guide/starterkits/t-shirt-designer.md +742 -0
  300. package/assets/docs/guide/starterkits/templating.md +23 -0
  301. package/assets/docs/guide/starterkits/theming.md +662 -0
  302. package/assets/docs/guide/starterkits/translation-internationalization.md +662 -0
  303. package/assets/docs/guide/starterkits/unsplash-editor.md +839 -0
  304. package/assets/docs/guide/starterkits/vectorizer-editor.md +466 -0
  305. package/assets/docs/guide/starterkits/version-history.md +745 -0
  306. package/assets/docs/guide/starterkits/video-animations.md +853 -0
  307. package/assets/docs/guide/starterkits/video-captions.md +884 -0
  308. package/assets/docs/guide/starterkits/video-editing.md +25 -0
  309. package/assets/docs/guide/starterkits/video-editor.md +696 -0
  310. package/assets/docs/guide/starterkits/video-export-options.md +676 -0
  311. package/assets/docs/guide/starterkits/viewer.md +400 -0
  312. package/assets/docs/guide/starterkits.md +41 -0
  313. package/assets/docs/guide/stickers-and-shapes/combine.md +743 -0
  314. package/assets/docs/guide/stickers-and-shapes/create-cutout.md +425 -0
  315. package/assets/docs/guide/stickers-and-shapes/create-edit/create-shapes.md +794 -0
  316. package/assets/docs/guide/stickers-and-shapes/create-edit/create-stickers.md +290 -0
  317. package/assets/docs/guide/stickers-and-shapes/create-edit/edit-shapes.md +211 -0
  318. package/assets/docs/guide/stickers-and-shapes/create-edit/vector-edit.md +362 -0
  319. package/assets/docs/guide/stickers-and-shapes/insert-qr-code.md +208 -0
  320. package/assets/docs/guide/stickers.md +21 -0
  321. package/assets/docs/guide/text/add.md +641 -0
  322. package/assets/docs/guide/text/adjust-spacing.md +288 -0
  323. package/assets/docs/guide/text/auto-size.md +404 -0
  324. package/assets/docs/guide/text/custom-fonts.md +401 -0
  325. package/assets/docs/guide/text/decorations.md +330 -0
  326. package/assets/docs/guide/text/edit.md +458 -0
  327. package/assets/docs/guide/text/effects.md +244 -0
  328. package/assets/docs/guide/text/emojis.md +310 -0
  329. package/assets/docs/guide/text/enumerations.md +258 -0
  330. package/assets/docs/guide/text/language-support.md +604 -0
  331. package/assets/docs/guide/text/overview.md +14 -0
  332. package/assets/docs/guide/text/styling.md +390 -0
  333. package/assets/docs/guide/text/text-designs.md +834 -0
  334. package/assets/docs/guide/text.md +33 -0
  335. package/assets/docs/guide/to-v1-10.md +131 -0
  336. package/assets/docs/guide/to-v1-13.md +165 -0
  337. package/assets/docs/guide/to-v1-19.md +315 -0
  338. package/assets/docs/guide/to-v1-32.md +110 -0
  339. package/assets/docs/guide/to-v1-69.md +468 -0
  340. package/assets/docs/guide/to-v1-72.md +193 -0
  341. package/assets/docs/guide/upgrade.md +25 -0
  342. package/assets/docs/guide/use-templates/apply-template.md +279 -0
  343. package/assets/docs/guide/use-templates/generate.md +405 -0
  344. package/assets/docs/guide/use-templates/library.md +450 -0
  345. package/assets/docs/guide/use-templates/overview.md +20 -0
  346. package/assets/docs/guide/use-templates/programmatic.md +482 -0
  347. package/assets/docs/guide/use-templates/replace-content.md +399 -0
  348. package/assets/docs/guide/user-interface/ai-integration/audio-generation.md +428 -0
  349. package/assets/docs/guide/user-interface/ai-integration/auto-captions.md +337 -0
  350. package/assets/docs/guide/user-interface/ai-integration/custom-provider.md +853 -0
  351. package/assets/docs/guide/user-interface/ai-integration/gateway-provider.md +1045 -0
  352. package/assets/docs/guide/user-interface/ai-integration/image-generation.md +641 -0
  353. package/assets/docs/guide/user-interface/ai-integration/integrate.md +966 -0
  354. package/assets/docs/guide/user-interface/ai-integration/proxy-server.md +99 -0
  355. package/assets/docs/guide/user-interface/ai-integration/text-generation.md +498 -0
  356. package/assets/docs/guide/user-interface/ai-integration/video-generation.md +493 -0
  357. package/assets/docs/guide/user-interface/ai-integration.md +30 -0
  358. package/assets/docs/guide/user-interface/appearance/change-ui-font.md +316 -0
  359. package/assets/docs/guide/user-interface/appearance/custom-labels.md +509 -0
  360. package/assets/docs/guide/user-interface/appearance/icons.md +373 -0
  361. package/assets/docs/guide/user-interface/appearance/theming.md +665 -0
  362. package/assets/docs/guide/user-interface/appearance.md +23 -0
  363. package/assets/docs/guide/user-interface/build-your-own-ui.md +620 -0
  364. package/assets/docs/guide/user-interface/customization/canvas-menu.md +412 -0
  365. package/assets/docs/guide/user-interface/customization/canvas.md +281 -0
  366. package/assets/docs/guide/user-interface/customization/color-palette.md +413 -0
  367. package/assets/docs/guide/user-interface/customization/crop-presets.md +384 -0
  368. package/assets/docs/guide/user-interface/customization/disable-or-enable.md +676 -0
  369. package/assets/docs/guide/user-interface/customization/dock.md +399 -0
  370. package/assets/docs/guide/user-interface/customization/force-crop.md +289 -0
  371. package/assets/docs/guide/user-interface/customization/inspector-bar.md +371 -0
  372. package/assets/docs/guide/user-interface/customization/navigation-bar.md +516 -0
  373. package/assets/docs/guide/user-interface/customization/page-format.md +436 -0
  374. package/assets/docs/guide/user-interface/customization/panel.md +605 -0
  375. package/assets/docs/guide/user-interface/customization/quick-start/add-action-buttons.md +531 -0
  376. package/assets/docs/guide/user-interface/customization/quick-start/add-dock-buttons.md +358 -0
  377. package/assets/docs/guide/user-interface/customization/quick-start/create-custom-components.md +374 -0
  378. package/assets/docs/guide/user-interface/customization/quick-start/reorder-components.md +323 -0
  379. package/assets/docs/guide/user-interface/customization/quick-start/show-hide-components.md +294 -0
  380. package/assets/docs/guide/user-interface/customization/quick-start.md +12 -0
  381. package/assets/docs/guide/user-interface/customization/reference/component-order-api.md +519 -0
  382. package/assets/docs/guide/user-interface/customization/reference/component-reference.md +333 -0
  383. package/assets/docs/guide/user-interface/customization/reference.md +12 -0
  384. package/assets/docs/guide/user-interface/customization.md +39 -0
  385. package/assets/docs/guide/user-interface/localization.md +633 -0
  386. package/assets/docs/guide/user-interface/overview.md +167 -0
  387. package/assets/docs/guide/user-interface/ui-extensions/add-custom-feature.md +411 -0
  388. package/assets/docs/guide/user-interface/ui-extensions/asset-library.md +721 -0
  389. package/assets/docs/guide/user-interface/ui-extensions/create-custom-panel.md +331 -0
  390. package/assets/docs/guide/user-interface/ui-extensions/customize-behaviour.md +553 -0
  391. package/assets/docs/guide/user-interface/ui-extensions/notifications-and-dialogs.md +672 -0
  392. package/assets/docs/guide/user-interface/ui-extensions/quick-actions.md +415 -0
  393. package/assets/docs/guide/user-interface/ui-extensions/register-new-component.md +521 -0
  394. package/assets/docs/guide/user-interface/ui-extensions.md +26 -0
  395. package/assets/docs/guide/user-interface.md +25 -0
  396. package/assets/docs/guide/what-is-cesdk.md +319 -0
  397. package/assets/docs/handbook/SKILL.md +521 -0
  398. package/assets/prompts/evals-assetGenerate.md +12 -0
  399. package/assets/prompts/evals-brutalistCore.md +34 -0
  400. package/assets/prompts/evals-danskCatalogue.md +31 -0
  401. package/assets/prompts/evals-exportRoundTrip.md +12 -0
  402. package/assets/prompts/evals-inspectPriorCode.md +16 -0
  403. package/assets/prompts/evals-listProjectFiles.md +6 -0
  404. package/assets/prompts/evals-readAndExplainScript.md +6 -0
  405. package/assets/prompts/evals-resumeAcrossRestart.md +15 -0
  406. package/assets/prompts/evals-rewindRecovery.md +10 -0
  407. package/assets/prompts/evals-searchAcrossFiles.md +6 -0
  408. package/assets/prompts/evals-weddingCard.md +20 -0
  409. package/assets/prompts/explain.md +6 -0
  410. package/assets/prompts/review.md +6 -0
  411. package/dist/assets/inline.generated.d.ts +2 -0
  412. package/dist/assets/inline.generated.d.ts.map +1 -0
  413. package/dist/assets/inline.generated.js +413 -0
  414. package/dist/assets/inline.generated.js.map +1 -0
  415. package/dist/assets/load-browser.d.ts +8 -0
  416. package/dist/assets/load-browser.d.ts.map +1 -0
  417. package/dist/assets/load-browser.js +11 -0
  418. package/dist/assets/load-browser.js.map +1 -0
  419. package/dist/assets/load-node.d.ts +8 -0
  420. package/dist/assets/load-node.d.ts.map +1 -0
  421. package/dist/assets/load-node.js +11 -0
  422. package/dist/assets/load-node.js.map +1 -0
  423. package/dist/cli/http.d.ts +2 -0
  424. package/dist/cli/http.d.ts.map +1 -0
  425. package/dist/cli/http.js +231 -0
  426. package/dist/cli/http.js.map +1 -0
  427. package/dist/cli/redirect-console.d.ts +10 -0
  428. package/dist/cli/redirect-console.d.ts.map +1 -0
  429. package/dist/cli/redirect-console.js +18 -0
  430. package/dist/cli/redirect-console.js.map +1 -0
  431. package/dist/cli/resolve-license.d.ts +2 -0
  432. package/dist/cli/resolve-license.d.ts.map +1 -0
  433. package/dist/cli/resolve-license.js +13 -0
  434. package/dist/cli/resolve-license.js.map +1 -0
  435. package/dist/cli/stdio.d.ts +2 -0
  436. package/dist/cli/stdio.d.ts.map +1 -0
  437. package/dist/cli/stdio.js +124 -0
  438. package/dist/cli/stdio.js.map +1 -0
  439. package/dist/cli/trial-license.generated.d.ts +2 -0
  440. package/dist/cli/trial-license.generated.d.ts.map +1 -0
  441. package/dist/cli/trial-license.generated.js +4 -0
  442. package/dist/cli/trial-license.generated.js.map +1 -0
  443. package/dist/cli.d.ts +3 -0
  444. package/dist/cli.d.ts.map +1 -0
  445. package/dist/cli.js +64 -0
  446. package/dist/cli.js.map +1 -0
  447. package/dist/config.d.ts +61 -0
  448. package/dist/config.d.ts.map +1 -0
  449. package/dist/config.js +102 -0
  450. package/dist/config.js.map +1 -0
  451. package/dist/cross-ref.d.ts +2 -0
  452. package/dist/cross-ref.d.ts.map +1 -0
  453. package/dist/cross-ref.js +31 -0
  454. package/dist/cross-ref.js.map +1 -0
  455. package/dist/dashboard/router.d.ts +3 -0
  456. package/dist/dashboard/router.d.ts.map +1 -0
  457. package/dist/dashboard/router.js +19 -0
  458. package/dist/dashboard/router.js.map +1 -0
  459. package/dist/dashboard/spa-assets.generated.d.ts +2 -0
  460. package/dist/dashboard/spa-assets.generated.d.ts.map +1 -0
  461. package/dist/dashboard/spa-assets.generated.js +220 -0
  462. package/dist/dashboard/spa-assets.generated.js.map +1 -0
  463. package/dist/engine/asset-sources.d.ts +17 -0
  464. package/dist/engine/asset-sources.d.ts.map +1 -0
  465. package/dist/engine/asset-sources.js +75 -0
  466. package/dist/engine/asset-sources.js.map +1 -0
  467. package/dist/engine/cesdk-adapter.d.ts +10 -0
  468. package/dist/engine/cesdk-adapter.d.ts.map +1 -0
  469. package/dist/engine/cesdk-adapter.js +19 -0
  470. package/dist/engine/cesdk-adapter.js.map +1 -0
  471. package/dist/engine/index.d.ts +3 -0
  472. package/dist/engine/index.d.ts.map +1 -0
  473. package/dist/engine/index.js +3 -0
  474. package/dist/engine/index.js.map +1 -0
  475. package/dist/engine/mutex.d.ts +5 -0
  476. package/dist/engine/mutex.d.ts.map +1 -0
  477. package/dist/engine/mutex.js +42 -0
  478. package/dist/engine/mutex.js.map +1 -0
  479. package/dist/engine/session.d.ts +50 -0
  480. package/dist/engine/session.d.ts.map +1 -0
  481. package/dist/engine/session.js +95 -0
  482. package/dist/engine/session.js.map +1 -0
  483. package/dist/engine/uri-resolver.d.ts +14 -0
  484. package/dist/engine/uri-resolver.d.ts.map +1 -0
  485. package/dist/engine/uri-resolver.js +12 -0
  486. package/dist/engine/uri-resolver.js.map +1 -0
  487. package/dist/frontmatter.d.ts +15 -0
  488. package/dist/frontmatter.d.ts.map +1 -0
  489. package/dist/frontmatter.js +46 -0
  490. package/dist/frontmatter.js.map +1 -0
  491. package/dist/gateway/hosted-stub.d.ts +6 -0
  492. package/dist/gateway/hosted-stub.d.ts.map +1 -0
  493. package/dist/gateway/hosted-stub.js +11 -0
  494. package/dist/gateway/hosted-stub.js.map +1 -0
  495. package/dist/gateway/index.d.ts +4 -0
  496. package/dist/gateway/index.d.ts.map +1 -0
  497. package/dist/gateway/index.js +4 -0
  498. package/dist/gateway/index.js.map +1 -0
  499. package/dist/gateway/local.d.ts +14 -0
  500. package/dist/gateway/local.d.ts.map +1 -0
  501. package/dist/gateway/local.js +41 -0
  502. package/dist/gateway/local.js.map +1 -0
  503. package/dist/gateway/types.d.ts +24 -0
  504. package/dist/gateway/types.d.ts.map +1 -0
  505. package/dist/gateway/types.js +7 -0
  506. package/dist/gateway/types.js.map +1 -0
  507. package/dist/http/server.d.ts +80 -0
  508. package/dist/http/server.d.ts.map +1 -0
  509. package/dist/http/server.js +183 -0
  510. package/dist/http/server.js.map +1 -0
  511. package/dist/http/session-manager.d.ts +42 -0
  512. package/dist/http/session-manager.d.ts.map +1 -0
  513. package/dist/http/session-manager.js +82 -0
  514. package/dist/http/session-manager.js.map +1 -0
  515. package/dist/http/workspace-auth.d.ts +9 -0
  516. package/dist/http/workspace-auth.d.ts.map +1 -0
  517. package/dist/http/workspace-auth.js +29 -0
  518. package/dist/http/workspace-auth.js.map +1 -0
  519. package/dist/index.d.ts +10 -0
  520. package/dist/index.d.ts.map +1 -0
  521. package/dist/index.js +10 -0
  522. package/dist/index.js.map +1 -0
  523. package/dist/metrics/mount.d.ts +11 -0
  524. package/dist/metrics/mount.d.ts.map +1 -0
  525. package/dist/metrics/mount.js +13 -0
  526. package/dist/metrics/mount.js.map +1 -0
  527. package/dist/metrics/recorder.d.ts +55 -0
  528. package/dist/metrics/recorder.d.ts.map +1 -0
  529. package/dist/metrics/recorder.js +97 -0
  530. package/dist/metrics/recorder.js.map +1 -0
  531. package/dist/revisions/hash.d.ts +7 -0
  532. package/dist/revisions/hash.d.ts.map +1 -0
  533. package/dist/revisions/hash.js +24 -0
  534. package/dist/revisions/hash.js.map +1 -0
  535. package/dist/revisions/index.d.ts +4 -0
  536. package/dist/revisions/index.d.ts.map +1 -0
  537. package/dist/revisions/index.js +4 -0
  538. package/dist/revisions/index.js.map +1 -0
  539. package/dist/revisions/store.d.ts +69 -0
  540. package/dist/revisions/store.d.ts.map +1 -0
  541. package/dist/revisions/store.js +196 -0
  542. package/dist/revisions/store.js.map +1 -0
  543. package/dist/revisions/types.d.ts +39 -0
  544. package/dist/revisions/types.d.ts.map +1 -0
  545. package/dist/revisions/types.js +2 -0
  546. package/dist/revisions/types.js.map +1 -0
  547. package/dist/server.d.ts +51 -0
  548. package/dist/server.d.ts.map +1 -0
  549. package/dist/server.js +175 -0
  550. package/dist/server.js.map +1 -0
  551. package/dist/skill-tools.d.ts +3 -0
  552. package/dist/skill-tools.d.ts.map +1 -0
  553. package/dist/skill-tools.js +105 -0
  554. package/dist/skill-tools.js.map +1 -0
  555. package/dist/test/test/cli/dispatcher.test.d.ts +2 -0
  556. package/dist/test/test/cli/dispatcher.test.d.ts.map +1 -0
  557. package/dist/test/test/cli/dispatcher.test.js +47 -0
  558. package/dist/test/test/cli/dispatcher.test.js.map +1 -0
  559. package/dist/test/test/cross-ref.test.d.ts +2 -0
  560. package/dist/test/test/cross-ref.test.d.ts.map +1 -0
  561. package/dist/test/test/cross-ref.test.js +39 -0
  562. package/dist/test/test/cross-ref.test.js.map +1 -0
  563. package/dist/test/test/engine/session.test.d.ts +2 -0
  564. package/dist/test/test/engine/session.test.d.ts.map +1 -0
  565. package/dist/test/test/engine/session.test.js +144 -0
  566. package/dist/test/test/engine/session.test.js.map +1 -0
  567. package/dist/test/test/engine/uri-resolver.test.d.ts +2 -0
  568. package/dist/test/test/engine/uri-resolver.test.d.ts.map +1 -0
  569. package/dist/test/test/engine/uri-resolver.test.js +38 -0
  570. package/dist/test/test/engine/uri-resolver.test.js.map +1 -0
  571. package/dist/test/test/frontmatter.test.d.ts +2 -0
  572. package/dist/test/test/frontmatter.test.d.ts.map +1 -0
  573. package/dist/test/test/frontmatter.test.js +55 -0
  574. package/dist/test/test/frontmatter.test.js.map +1 -0
  575. package/dist/test/test/gateway/hosted-stub.test.d.ts +2 -0
  576. package/dist/test/test/gateway/hosted-stub.test.d.ts.map +1 -0
  577. package/dist/test/test/gateway/hosted-stub.test.js +11 -0
  578. package/dist/test/test/gateway/hosted-stub.test.js.map +1 -0
  579. package/dist/test/test/gateway/local.test.d.ts +2 -0
  580. package/dist/test/test/gateway/local.test.d.ts.map +1 -0
  581. package/dist/test/test/gateway/local.test.js +29 -0
  582. package/dist/test/test/gateway/local.test.js.map +1 -0
  583. package/dist/test/test/handbook-contract.test.d.ts +2 -0
  584. package/dist/test/test/handbook-contract.test.d.ts.map +1 -0
  585. package/dist/test/test/handbook-contract.test.js +71 -0
  586. package/dist/test/test/handbook-contract.test.js.map +1 -0
  587. package/dist/test/test/http/server.test.d.ts +2 -0
  588. package/dist/test/test/http/server.test.d.ts.map +1 -0
  589. package/dist/test/test/http/server.test.js +245 -0
  590. package/dist/test/test/http/server.test.js.map +1 -0
  591. package/dist/test/test/http/session-manager.test.d.ts +2 -0
  592. package/dist/test/test/http/session-manager.test.d.ts.map +1 -0
  593. package/dist/test/test/http/session-manager.test.js +83 -0
  594. package/dist/test/test/http/session-manager.test.js.map +1 -0
  595. package/dist/test/test/revisions/hash.test.d.ts +2 -0
  596. package/dist/test/test/revisions/hash.test.d.ts.map +1 -0
  597. package/dist/test/test/revisions/hash.test.js +33 -0
  598. package/dist/test/test/revisions/hash.test.js.map +1 -0
  599. package/dist/test/test/revisions/store.test.d.ts +2 -0
  600. package/dist/test/test/revisions/store.test.d.ts.map +1 -0
  601. package/dist/test/test/revisions/store.test.js +245 -0
  602. package/dist/test/test/revisions/store.test.js.map +1 -0
  603. package/dist/test/test/server.test.d.ts +2 -0
  604. package/dist/test/test/server.test.d.ts.map +1 -0
  605. package/dist/test/test/server.test.js +157 -0
  606. package/dist/test/test/server.test.js.map +1 -0
  607. package/dist/test/test/skill-tools.test.d.ts +2 -0
  608. package/dist/test/test/skill-tools.test.d.ts.map +1 -0
  609. package/dist/test/test/skill-tools.test.js +84 -0
  610. package/dist/test/test/skill-tools.test.js.map +1 -0
  611. package/dist/test/test/smoke.test.d.ts +2 -0
  612. package/dist/test/test/smoke.test.d.ts.map +1 -0
  613. package/dist/test/test/smoke.test.js +8 -0
  614. package/dist/test/test/smoke.test.js.map +1 -0
  615. package/dist/test/test/tools/asset-generate.test.d.ts +2 -0
  616. package/dist/test/test/tools/asset-generate.test.d.ts.map +1 -0
  617. package/dist/test/test/tools/asset-generate.test.js +66 -0
  618. package/dist/test/test/tools/asset-generate.test.js.map +1 -0
  619. package/dist/test/test/tools/edit.test.d.ts +2 -0
  620. package/dist/test/test/tools/edit.test.d.ts.map +1 -0
  621. package/dist/test/test/tools/edit.test.js +205 -0
  622. package/dist/test/test/tools/edit.test.js.map +1 -0
  623. package/dist/test/test/tools/export.test.d.ts +2 -0
  624. package/dist/test/test/tools/export.test.d.ts.map +1 -0
  625. package/dist/test/test/tools/export.test.js +144 -0
  626. package/dist/test/test/tools/export.test.js.map +1 -0
  627. package/dist/test/test/tools/history.test.d.ts +2 -0
  628. package/dist/test/test/tools/history.test.d.ts.map +1 -0
  629. package/dist/test/test/tools/history.test.js +29 -0
  630. package/dist/test/test/tools/history.test.js.map +1 -0
  631. package/dist/test/test/tools/inspect.test.d.ts +2 -0
  632. package/dist/test/test/tools/inspect.test.d.ts.map +1 -0
  633. package/dist/test/test/tools/inspect.test.js +62 -0
  634. package/dist/test/test/tools/inspect.test.js.map +1 -0
  635. package/dist/test/test/tools/list.test.d.ts +2 -0
  636. package/dist/test/test/tools/list.test.d.ts.map +1 -0
  637. package/dist/test/test/tools/list.test.js +23 -0
  638. package/dist/test/test/tools/list.test.js.map +1 -0
  639. package/dist/test/test/tools/open-editor.test.d.ts +2 -0
  640. package/dist/test/test/tools/open-editor.test.d.ts.map +1 -0
  641. package/dist/test/test/tools/open-editor.test.js +53 -0
  642. package/dist/test/test/tools/open-editor.test.js.map +1 -0
  643. package/dist/test/test/tools/preview.test.d.ts +2 -0
  644. package/dist/test/test/tools/preview.test.d.ts.map +1 -0
  645. package/dist/test/test/tools/preview.test.js +73 -0
  646. package/dist/test/test/tools/preview.test.js.map +1 -0
  647. package/dist/test/test/tools/rename.test.d.ts +2 -0
  648. package/dist/test/test/tools/rename.test.d.ts.map +1 -0
  649. package/dist/test/test/tools/rename.test.js +17 -0
  650. package/dist/test/test/tools/rename.test.js.map +1 -0
  651. package/dist/test/test/viewer/broadcaster.test.d.ts +2 -0
  652. package/dist/test/test/viewer/broadcaster.test.d.ts.map +1 -0
  653. package/dist/test/test/viewer/broadcaster.test.js +53 -0
  654. package/dist/test/test/viewer/broadcaster.test.js.map +1 -0
  655. package/dist/test/test/viewer/resource-route.test.d.ts +2 -0
  656. package/dist/test/test/viewer/resource-route.test.d.ts.map +1 -0
  657. package/dist/test/test/viewer/resource-route.test.js +70 -0
  658. package/dist/test/test/viewer/resource-route.test.js.map +1 -0
  659. package/dist/test/test/viewer/router.test.d.ts +2 -0
  660. package/dist/test/test/viewer/router.test.d.ts.map +1 -0
  661. package/dist/test/test/viewer/router.test.js +171 -0
  662. package/dist/test/test/viewer/router.test.js.map +1 -0
  663. package/dist/test/test/viewer/url-builder.test.d.ts +2 -0
  664. package/dist/test/test/viewer/url-builder.test.d.ts.map +1 -0
  665. package/dist/test/test/viewer/url-builder.test.js +31 -0
  666. package/dist/test/test/viewer/url-builder.test.js.map +1 -0
  667. package/dist/test/test/workspace/hosted-stub.test.d.ts +2 -0
  668. package/dist/test/test/workspace/hosted-stub.test.d.ts.map +1 -0
  669. package/dist/test/test/workspace/hosted-stub.test.js +30 -0
  670. package/dist/test/test/workspace/hosted-stub.test.js.map +1 -0
  671. package/dist/test/test/workspace/in-memory.test.d.ts +2 -0
  672. package/dist/test/test/workspace/in-memory.test.d.ts.map +1 -0
  673. package/dist/test/test/workspace/in-memory.test.js +4 -0
  674. package/dist/test/test/workspace/in-memory.test.js.map +1 -0
  675. package/dist/test/test/workspace/node-fs.test.d.ts +2 -0
  676. package/dist/test/test/workspace/node-fs.test.d.ts.map +1 -0
  677. package/dist/test/test/workspace/node-fs.test.js +20 -0
  678. package/dist/test/test/workspace/node-fs.test.js.map +1 -0
  679. package/dist/test/test/workspace/shared-contract.d.ts +3 -0
  680. package/dist/test/test/workspace/shared-contract.d.ts.map +1 -0
  681. package/dist/test/test/workspace/shared-contract.js +92 -0
  682. package/dist/test/test/workspace/shared-contract.js.map +1 -0
  683. package/dist/test/tsconfig.test.tsbuildinfo +1 -0
  684. package/dist/test/vitest.config.d.ts +3 -0
  685. package/dist/test/vitest.config.d.ts.map +1 -0
  686. package/dist/test/vitest.config.js +8 -0
  687. package/dist/test/vitest.config.js.map +1 -0
  688. package/dist/tools/asset-generate.d.ts +12 -0
  689. package/dist/tools/asset-generate.d.ts.map +1 -0
  690. package/dist/tools/asset-generate.js +112 -0
  691. package/dist/tools/asset-generate.js.map +1 -0
  692. package/dist/tools/asset-search.d.ts +10 -0
  693. package/dist/tools/asset-search.d.ts.map +1 -0
  694. package/dist/tools/asset-search.js +120 -0
  695. package/dist/tools/asset-search.js.map +1 -0
  696. package/dist/tools/content-types.d.ts +11 -0
  697. package/dist/tools/content-types.d.ts.map +1 -0
  698. package/dist/tools/content-types.js +2 -0
  699. package/dist/tools/content-types.js.map +1 -0
  700. package/dist/tools/edit.d.ts +29 -0
  701. package/dist/tools/edit.d.ts.map +1 -0
  702. package/dist/tools/edit.js +165 -0
  703. package/dist/tools/edit.js.map +1 -0
  704. package/dist/tools/engine.d.ts +31 -0
  705. package/dist/tools/engine.d.ts.map +1 -0
  706. package/dist/tools/engine.js +59 -0
  707. package/dist/tools/engine.js.map +1 -0
  708. package/dist/tools/export.d.ts +19 -0
  709. package/dist/tools/export.d.ts.map +1 -0
  710. package/dist/tools/export.js +179 -0
  711. package/dist/tools/export.js.map +1 -0
  712. package/dist/tools/history.d.ts +7 -0
  713. package/dist/tools/history.d.ts.map +1 -0
  714. package/dist/tools/history.js +54 -0
  715. package/dist/tools/history.js.map +1 -0
  716. package/dist/tools/index.d.ts +35 -0
  717. package/dist/tools/index.d.ts.map +1 -0
  718. package/dist/tools/index.js +72 -0
  719. package/dist/tools/index.js.map +1 -0
  720. package/dist/tools/inspect.d.ts +7 -0
  721. package/dist/tools/inspect.d.ts.map +1 -0
  722. package/dist/tools/inspect.js +80 -0
  723. package/dist/tools/inspect.js.map +1 -0
  724. package/dist/tools/list.d.ts +7 -0
  725. package/dist/tools/list.d.ts.map +1 -0
  726. package/dist/tools/list.js +18 -0
  727. package/dist/tools/list.js.map +1 -0
  728. package/dist/tools/metrics.d.ts +11 -0
  729. package/dist/tools/metrics.d.ts.map +1 -0
  730. package/dist/tools/metrics.js +28 -0
  731. package/dist/tools/metrics.js.map +1 -0
  732. package/dist/tools/open-editor.d.ts +10 -0
  733. package/dist/tools/open-editor.d.ts.map +1 -0
  734. package/dist/tools/open-editor.js +62 -0
  735. package/dist/tools/open-editor.js.map +1 -0
  736. package/dist/tools/preview.d.ts +12 -0
  737. package/dist/tools/preview.d.ts.map +1 -0
  738. package/dist/tools/preview.js +104 -0
  739. package/dist/tools/preview.js.map +1 -0
  740. package/dist/tools/rename.d.ts +7 -0
  741. package/dist/tools/rename.d.ts.map +1 -0
  742. package/dist/tools/rename.js +39 -0
  743. package/dist/tools/rename.js.map +1 -0
  744. package/dist/tools/result.d.ts +12 -0
  745. package/dist/tools/result.d.ts.map +1 -0
  746. package/dist/tools/result.js +55 -0
  747. package/dist/tools/result.js.map +1 -0
  748. package/dist/tools/save.d.ts +19 -0
  749. package/dist/tools/save.d.ts.map +1 -0
  750. package/dist/tools/save.js +117 -0
  751. package/dist/tools/save.js.map +1 -0
  752. package/dist/viewer/broadcaster.d.ts +13 -0
  753. package/dist/viewer/broadcaster.d.ts.map +1 -0
  754. package/dist/viewer/broadcaster.js +44 -0
  755. package/dist/viewer/broadcaster.js.map +1 -0
  756. package/dist/viewer/index.d.ts +7 -0
  757. package/dist/viewer/index.d.ts.map +1 -0
  758. package/dist/viewer/index.js +7 -0
  759. package/dist/viewer/index.js.map +1 -0
  760. package/dist/viewer/listener.d.ts +16 -0
  761. package/dist/viewer/listener.d.ts.map +1 -0
  762. package/dist/viewer/listener.js +30 -0
  763. package/dist/viewer/listener.js.map +1 -0
  764. package/dist/viewer/presigned-r2-url-builder.d.ts +30 -0
  765. package/dist/viewer/presigned-r2-url-builder.d.ts.map +1 -0
  766. package/dist/viewer/presigned-r2-url-builder.js +40 -0
  767. package/dist/viewer/presigned-r2-url-builder.js.map +1 -0
  768. package/dist/viewer/resource-route.d.ts +9 -0
  769. package/dist/viewer/resource-route.d.ts.map +1 -0
  770. package/dist/viewer/resource-route.js +59 -0
  771. package/dist/viewer/resource-route.js.map +1 -0
  772. package/dist/viewer/router.d.ts +20 -0
  773. package/dist/viewer/router.d.ts.map +1 -0
  774. package/dist/viewer/router.js +142 -0
  775. package/dist/viewer/router.js.map +1 -0
  776. package/dist/viewer/session-mount.d.ts +10 -0
  777. package/dist/viewer/session-mount.d.ts.map +1 -0
  778. package/dist/viewer/session-mount.js +24 -0
  779. package/dist/viewer/session-mount.js.map +1 -0
  780. package/dist/viewer/spa-assets.generated.d.ts +2 -0
  781. package/dist/viewer/spa-assets.generated.d.ts.map +1 -0
  782. package/dist/viewer/spa-assets.generated.js +989 -0
  783. package/dist/viewer/spa-assets.generated.js.map +1 -0
  784. package/dist/viewer/url-builder.d.ts +48 -0
  785. package/dist/viewer/url-builder.d.ts.map +1 -0
  786. package/dist/viewer/url-builder.js +38 -0
  787. package/dist/viewer/url-builder.js.map +1 -0
  788. package/dist/workspace/hosted-stub.d.ts +28 -0
  789. package/dist/workspace/hosted-stub.d.ts.map +1 -0
  790. package/dist/workspace/hosted-stub.js +44 -0
  791. package/dist/workspace/hosted-stub.js.map +1 -0
  792. package/dist/workspace/in-memory.d.ts +23 -0
  793. package/dist/workspace/in-memory.d.ts.map +1 -0
  794. package/dist/workspace/in-memory.js +161 -0
  795. package/dist/workspace/in-memory.js.map +1 -0
  796. package/dist/workspace/index.d.ts +6 -0
  797. package/dist/workspace/index.d.ts.map +1 -0
  798. package/dist/workspace/index.js +6 -0
  799. package/dist/workspace/index.js.map +1 -0
  800. package/dist/workspace/node-fs.d.ts +23 -0
  801. package/dist/workspace/node-fs.d.ts.map +1 -0
  802. package/dist/workspace/node-fs.js +90 -0
  803. package/dist/workspace/node-fs.js.map +1 -0
  804. package/dist/workspace/s3.d.ts +32 -0
  805. package/dist/workspace/s3.d.ts.map +1 -0
  806. package/dist/workspace/s3.js +191 -0
  807. package/dist/workspace/s3.js.map +1 -0
  808. package/dist/workspace/scoped.d.ts +32 -0
  809. package/dist/workspace/scoped.d.ts.map +1 -0
  810. package/dist/workspace/scoped.js +76 -0
  811. package/dist/workspace/scoped.js.map +1 -0
  812. package/dist/workspace/types.d.ts +75 -0
  813. package/dist/workspace/types.d.ts.map +1 -0
  814. package/dist/workspace/types.js +18 -0
  815. package/dist/workspace/types.js.map +1 -0
  816. package/package.json +80 -0
@@ -0,0 +1,55 @@
1
+ export interface MetricsRecorderOptions {
2
+ /** Max tool-call records kept in the recent-calls ring. Default 100. */
3
+ recentLimit?: number;
4
+ /** Max per-tool durations retained for percentile math. Default 256. */
5
+ sampleSize?: number;
6
+ /** Process-memory sampling interval in ms. Default 5000. */
7
+ memorySampleMs?: number;
8
+ }
9
+ export interface ToolStat {
10
+ tool: string;
11
+ count: number;
12
+ errorCount: number;
13
+ min: number;
14
+ max: number;
15
+ mean: number;
16
+ p50: number;
17
+ p95: number;
18
+ }
19
+ export interface MemorySample {
20
+ rss: number;
21
+ heapUsed: number;
22
+ external: number;
23
+ arrayBuffers: number;
24
+ }
25
+ export interface ToolCallRecord {
26
+ tool: string;
27
+ durationMs: number;
28
+ ok: boolean;
29
+ ts: number;
30
+ }
31
+ export interface MetricsSnapshot {
32
+ tools: ToolStat[];
33
+ recent: ToolCallRecord[];
34
+ memory: MemorySample | null;
35
+ }
36
+ export declare class MetricsRecorder {
37
+ private readonly recentLimit;
38
+ private readonly sampleSize;
39
+ private readonly memorySampleMs;
40
+ private readonly recent;
41
+ private readonly tools;
42
+ private memory;
43
+ private timer;
44
+ constructor(opts?: MetricsRecorderOptions);
45
+ record(event: {
46
+ tool: string;
47
+ durationMs: number;
48
+ ok: boolean;
49
+ }): void;
50
+ sampleMemory(): void;
51
+ start(): void;
52
+ stop(): void;
53
+ snapshot(): MetricsSnapshot;
54
+ }
55
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/metrics/recorder.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;CAC7B;AAiBD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8B;IACpD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,KAAK,CAA+C;gBAEhD,IAAI,GAAE,sBAA2B;IAM7C,MAAM,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IAoBtE,YAAY,IAAI,IAAI;IAUpB,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAMZ,QAAQ,IAAI,eAAe;CAmB5B"}
@@ -0,0 +1,97 @@
1
+ // packages/codesign-mcp/src/metrics/recorder.ts
2
+ //
3
+ // In-memory, process-global performance recorder for the MCP server. Times
4
+ // every tool call (TOTAL wall-time only — "Approach A"), samples process
5
+ // memory on a timer, and exposes a point-in-time snapshot for the /metrics
6
+ // route and the dashboard SPA. Ephemeral: all state lives in memory and resets
7
+ // on restart. No persistence, no time-series, no secrets.
8
+ //
9
+ // APPROACH-A LIMITATION (deliberate, design §3): the recorder is fed by a
10
+ // single wrapper AROUND each tool call (see server.ts), so it observes only
11
+ // total wall-time. It cannot split engine-lock wait from execution, nor detect
12
+ // a cold engine reload — those happen INSIDE the call and are invisible to an
13
+ // outer wrapper. The deeper splits are a future addition (design §8) and must
14
+ // NOT couple Mutex / EngineSession to this recorder.
15
+ /** Nearest-rank percentile over an ascending-sorted sample. */
16
+ function percentile(sorted, p) {
17
+ if (sorted.length === 0)
18
+ return 0;
19
+ const rank = Math.ceil((p / 100) * sorted.length);
20
+ const idx = Math.min(sorted.length - 1, Math.max(0, rank - 1));
21
+ return sorted[idx];
22
+ }
23
+ export class MetricsRecorder {
24
+ constructor(opts = {}) {
25
+ this.recent = [];
26
+ this.tools = new Map();
27
+ this.memory = null;
28
+ this.timer = null;
29
+ this.recentLimit = opts.recentLimit ?? 100;
30
+ this.sampleSize = opts.sampleSize ?? 256;
31
+ this.memorySampleMs = opts.memorySampleMs ?? 5000;
32
+ }
33
+ record(event) {
34
+ this.recent.push({
35
+ tool: event.tool,
36
+ durationMs: event.durationMs,
37
+ ok: event.ok,
38
+ ts: Date.now()
39
+ });
40
+ if (this.recent.length > this.recentLimit)
41
+ this.recent.shift();
42
+ let agg = this.tools.get(event.tool);
43
+ if (!agg) {
44
+ agg = { count: 0, errorCount: 0, durations: [] };
45
+ this.tools.set(event.tool, agg);
46
+ }
47
+ agg.count += 1;
48
+ if (!event.ok)
49
+ agg.errorCount += 1;
50
+ agg.durations.push(event.durationMs);
51
+ if (agg.durations.length > this.sampleSize)
52
+ agg.durations.shift();
53
+ }
54
+ sampleMemory() {
55
+ const m = process.memoryUsage();
56
+ this.memory = {
57
+ rss: m.rss,
58
+ heapUsed: m.heapUsed,
59
+ external: m.external,
60
+ arrayBuffers: m.arrayBuffers
61
+ };
62
+ }
63
+ start() {
64
+ if (this.timer)
65
+ return;
66
+ this.sampleMemory(); // seed so the first snapshot isn't null
67
+ this.timer = setInterval(() => this.sampleMemory(), this.memorySampleMs);
68
+ // Never keep the event loop alive on the metrics timer alone.
69
+ this.timer.unref();
70
+ }
71
+ stop() {
72
+ if (!this.timer)
73
+ return;
74
+ clearInterval(this.timer);
75
+ this.timer = null;
76
+ }
77
+ snapshot() {
78
+ const tools = [];
79
+ for (const [tool, agg] of this.tools) {
80
+ const sorted = [...agg.durations].sort((a, b) => a - b);
81
+ const n = sorted.length;
82
+ const sum = sorted.reduce((s, d) => s + d, 0);
83
+ tools.push({
84
+ tool,
85
+ count: agg.count,
86
+ errorCount: agg.errorCount,
87
+ min: n ? sorted[0] : 0,
88
+ max: n ? sorted[n - 1] : 0,
89
+ mean: n ? sum / n : 0,
90
+ p50: percentile(sorted, 50),
91
+ p95: percentile(sorted, 95)
92
+ });
93
+ }
94
+ return { tools, recent: [...this.recent], memory: this.memory };
95
+ }
96
+ }
97
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/metrics/recorder.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/metrics/recorder.ts\n//\n// In-memory, process-global performance recorder for the MCP server. Times\n// every tool call (TOTAL wall-time only — \"Approach A\"), samples process\n// memory on a timer, and exposes a point-in-time snapshot for the /metrics\n// route and the dashboard SPA. Ephemeral: all state lives in memory and resets\n// on restart. No persistence, no time-series, no secrets.\n//\n// APPROACH-A LIMITATION (deliberate, design §3): the recorder is fed by a\n// single wrapper AROUND each tool call (see server.ts), so it observes only\n// total wall-time. It cannot split engine-lock wait from execution, nor detect\n// a cold engine reload — those happen INSIDE the call and are invisible to an\n// outer wrapper. The deeper splits are a future addition (design §8) and must\n// NOT couple Mutex / EngineSession to this recorder.\n\nexport interface MetricsRecorderOptions {\n /** Max tool-call records kept in the recent-calls ring. Default 100. */\n recentLimit?: number;\n /** Max per-tool durations retained for percentile math. Default 256. */\n sampleSize?: number;\n /** Process-memory sampling interval in ms. Default 5000. */\n memorySampleMs?: number;\n}\n\nexport interface ToolStat {\n tool: string;\n count: number;\n errorCount: number;\n min: number;\n max: number;\n mean: number;\n p50: number;\n p95: number;\n}\n\nexport interface MemorySample {\n rss: number;\n heapUsed: number;\n external: number;\n arrayBuffers: number;\n}\n\nexport interface ToolCallRecord {\n tool: string;\n durationMs: number;\n ok: boolean;\n ts: number;\n}\n\nexport interface MetricsSnapshot {\n tools: ToolStat[];\n recent: ToolCallRecord[];\n memory: MemorySample | null;\n}\n\n/** Per-tool running aggregate. `durations` is a bounded, most-recent sample. */\ninterface ToolAgg {\n count: number; // lifetime\n errorCount: number; // lifetime\n durations: number[]; // bounded to sampleSize; oldest shifted out\n}\n\n/** Nearest-rank percentile over an ascending-sorted sample. */\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0;\n const rank = Math.ceil((p / 100) * sorted.length);\n const idx = Math.min(sorted.length - 1, Math.max(0, rank - 1));\n return sorted[idx];\n}\n\nexport class MetricsRecorder {\n private readonly recentLimit: number;\n private readonly sampleSize: number;\n private readonly memorySampleMs: number;\n private readonly recent: ToolCallRecord[] = [];\n private readonly tools = new Map<string, ToolAgg>();\n private memory: MemorySample | null = null;\n private timer: ReturnType<typeof setInterval> | null = null;\n\n constructor(opts: MetricsRecorderOptions = {}) {\n this.recentLimit = opts.recentLimit ?? 100;\n this.sampleSize = opts.sampleSize ?? 256;\n this.memorySampleMs = opts.memorySampleMs ?? 5000;\n }\n\n record(event: { tool: string; durationMs: number; ok: boolean }): void {\n this.recent.push({\n tool: event.tool,\n durationMs: event.durationMs,\n ok: event.ok,\n ts: Date.now()\n });\n if (this.recent.length > this.recentLimit) this.recent.shift();\n\n let agg = this.tools.get(event.tool);\n if (!agg) {\n agg = { count: 0, errorCount: 0, durations: [] };\n this.tools.set(event.tool, agg);\n }\n agg.count += 1;\n if (!event.ok) agg.errorCount += 1;\n agg.durations.push(event.durationMs);\n if (agg.durations.length > this.sampleSize) agg.durations.shift();\n }\n\n sampleMemory(): void {\n const m = process.memoryUsage();\n this.memory = {\n rss: m.rss,\n heapUsed: m.heapUsed,\n external: m.external,\n arrayBuffers: m.arrayBuffers\n };\n }\n\n start(): void {\n if (this.timer) return;\n this.sampleMemory(); // seed so the first snapshot isn't null\n this.timer = setInterval(() => this.sampleMemory(), this.memorySampleMs);\n // Never keep the event loop alive on the metrics timer alone.\n this.timer.unref();\n }\n\n stop(): void {\n if (!this.timer) return;\n clearInterval(this.timer);\n this.timer = null;\n }\n\n snapshot(): MetricsSnapshot {\n const tools: ToolStat[] = [];\n for (const [tool, agg] of this.tools) {\n const sorted = [...agg.durations].sort((a, b) => a - b);\n const n = sorted.length;\n const sum = sorted.reduce((s, d) => s + d, 0);\n tools.push({\n tool,\n count: agg.count,\n errorCount: agg.errorCount,\n min: n ? sorted[0] : 0,\n max: n ? sorted[n - 1] : 0,\n mean: n ? sum / n : 0,\n p50: percentile(sorted, 50),\n p95: percentile(sorted, 95)\n });\n }\n return { tools, recent: [...this.recent], memory: this.memory };\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export interface RevisionIdInput {
2
+ scene: string;
3
+ parent: string | null;
4
+ note?: string;
5
+ }
6
+ export declare function revisionId(input: RevisionIdInput): Promise<string>;
7
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/revisions/hash.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CASxE"}
@@ -0,0 +1,24 @@
1
+ //
2
+ // Revision id = first 12 hex chars of sha-256("<scene>|<parent>|<note>").
3
+ //
4
+ // Why 12: 48 bits = 281 trillion. Per workspace, even 1M revisions has a
5
+ // collision probability < 2e-9 (birthday bound). Cheap to extend later — the
6
+ // hash is opaque to callers.
7
+ //
8
+ // Why sha-256: ubiquitous, `globalThis.crypto.subtle` natively supports it
9
+ // (engineering-principles §5: no CryptoProvider abstraction). blake3 would be
10
+ // marginally faster but adds a dep for a function we call ~once per edit.
11
+ //
12
+ // Why include `note` in the digest: two identical edits with different notes
13
+ // must produce distinct revisions (spec §4.3). Otherwise the second one would
14
+ // overwrite the first's metadata file (also a constant key) silently.
15
+ export async function revisionId(input) {
16
+ const buf = new TextEncoder().encode(`${input.scene}|${input.parent ?? ''}|${input.note ?? ''}`);
17
+ const digest = await globalThis.crypto.subtle.digest('SHA-256', buf);
18
+ const view = new Uint8Array(digest);
19
+ let hex = '';
20
+ for (let i = 0; i < 6; i++)
21
+ hex += view[i].toString(16).padStart(2, '0');
22
+ return hex;
23
+ }
24
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/revisions/hash.ts"],"names":[],"mappings":"AAAA,EAAE;AACF,0EAA0E;AAC1E,EAAE;AACF,yEAAyE;AACzE,6EAA6E;AAC7E,6BAA6B;AAC7B,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,0EAA0E;AAC1E,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,sEAAsE;AAQtE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAClC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,CAC3D,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACzE,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["//\n// Revision id = first 12 hex chars of sha-256(\"<scene>|<parent>|<note>\").\n//\n// Why 12: 48 bits = 281 trillion. Per workspace, even 1M revisions has a\n// collision probability < 2e-9 (birthday bound). Cheap to extend later — the\n// hash is opaque to callers.\n//\n// Why sha-256: ubiquitous, `globalThis.crypto.subtle` natively supports it\n// (engineering-principles §5: no CryptoProvider abstraction). blake3 would be\n// marginally faster but adds a dep for a function we call ~once per edit.\n//\n// Why include `note` in the digest: two identical edits with different notes\n// must produce distinct revisions (spec §4.3). Otherwise the second one would\n// overwrite the first's metadata file (also a constant key) silently.\n\nexport interface RevisionIdInput {\n scene: string;\n parent: string | null;\n note?: string;\n}\n\nexport async function revisionId(input: RevisionIdInput): Promise<string> {\n const buf = new TextEncoder().encode(\n `${input.scene}|${input.parent ?? ''}|${input.note ?? ''}`\n );\n const digest = await globalThis.crypto.subtle.digest('SHA-256', buf);\n const view = new Uint8Array(digest);\n let hex = '';\n for (let i = 0; i < 6; i++) hex += view[i].toString(16).padStart(2, '0');\n return hex;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export { revisionId } from './hash.js';
2
+ export { RevisionStore, type WriteRevisionInput } from './store.js';
3
+ export * from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/revisions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACpE,cAAc,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { revisionId } from './hash.js';
2
+ export { RevisionStore } from './store.js';
3
+ export * from './types.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/revisions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAA2B,MAAM,YAAY,CAAC;AACpE,cAAc,YAAY,CAAC","sourcesContent":["export { revisionId } from './hash.js';\nexport { RevisionStore, type WriteRevisionInput } from './store.js';\nexport * from './types.js';\n"]}
@@ -0,0 +1,69 @@
1
+ import type { WorkspaceFS } from '../workspace/types.js';
2
+ import type { Revision, RevisionNode, RootEntry } from './types.js';
3
+ export interface WriteRevisionInput {
4
+ scene: string;
5
+ parent: string | null;
6
+ title?: string;
7
+ note?: string;
8
+ /**
9
+ * Optional: the JS source that produced this revision. Persisted as a
10
+ * sibling `<id>.code.js` file so a future agent (via the `inspect` tool)
11
+ * can read what operations led to this state. Not part of `revisionId`.
12
+ */
13
+ code?: string;
14
+ }
15
+ export declare class RevisionStore {
16
+ private readonly fs;
17
+ constructor(fs: WorkspaceFS);
18
+ private objectsPath;
19
+ private journalPath;
20
+ private titlePath;
21
+ private appendTitle;
22
+ private readMeta;
23
+ write(input: WriteRevisionInput): Promise<Revision>;
24
+ /**
25
+ * Read the JS source that produced a revision, if it was written through
26
+ * the `edit` tool. Returns undefined when the revision has no associated
27
+ * code file (e.g. future import / convert paths). Throws ENOENT only when
28
+ * the revision id itself is unknown — callers should `.read(id)` first to
29
+ * surface that.
30
+ */
31
+ readCode(id: string): Promise<string | undefined>;
32
+ read(id: string): Promise<Revision>;
33
+ /**
34
+ * Current title for a lineage root = the latest `titles/<root>/` event.
35
+ * Falls back to "Untitled" when the root has no title events (e.g. an
36
+ * unknown root id). Public because the viewer renders the live title.
37
+ */
38
+ currentTitle(root: string): Promise<string>;
39
+ /**
40
+ * Reconstruct the root index by folding the journal: for each root, the
41
+ * entry with the greatest padded timestamp is the latest leaf. No mutable
42
+ * index, no roots.json. Newest-first by updatedAt.
43
+ */
44
+ listRoots(): Promise<Array<{
45
+ rootRevision: string;
46
+ } & RootEntry>>;
47
+ /** Walk from `revision` back to the root. Returns the chain (root first → revision last). */
48
+ historyOf(revision: string): Promise<Revision[]>;
49
+ /**
50
+ * Every revision in the design tree that `root` belongs to, as metadata-only
51
+ * nodes sorted by `createdAt` ascending. `root` may be any revision id in the
52
+ * design — it is resolved to its lineage root (consistent with `historyOf` /
53
+ * `renameRoot`). An id not present in the store yields `[]`.
54
+ *
55
+ * Walks all of `objects/`. Cheap at POC scale; a Phase-2 per-root index would
56
+ * replace it.
57
+ */
58
+ treeOf(root: string): Promise<RevisionNode[]>;
59
+ /**
60
+ * Rename the root of `revision`'s lineage by appending a title event.
61
+ * `revision` may be mid-chain — its `meta.root` points at the lineage root.
62
+ * Titles are append-only (immutable revisions are never rewritten); the
63
+ * "current" title is the latest event (see `currentTitle`).
64
+ */
65
+ renameRoot(revision: string, title: string): Promise<{
66
+ rootRevision: string;
67
+ }>;
68
+ }
69
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/revisions/store.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EACV,QAAQ,EAER,YAAY,EACZ,SAAS,EACV,MAAM,YAAY,CAAC;AAapB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,WAAW;IAE5C,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;YAIH,WAAW;YAQX,QAAQ;IAMhB,KAAK,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAgCzD;;;;;;OAMG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAMjD,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAUzC;;;;OAIG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASjD;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IAiBvE,6FAA6F;IACvF,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAWtD;;;;;;;;OAQG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAqDnD;;;;;OAKG;IACG,UAAU,CACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAKrC"}
@@ -0,0 +1,196 @@
1
+ import { revisionId } from './hash.js';
2
+ const OBJECTS_DIR = 'objects';
3
+ const JOURNAL_DIR = 'journal';
4
+ const TITLES_DIR = 'titles';
5
+ // Zero-pad createdAtMs so a lexical `readdir` sort equals chronological order.
6
+ // 16 digits covers epoch-ms well beyond the year 5000.
7
+ const TS_WIDTH = 16;
8
+ function padTs(ms) {
9
+ return String(ms).padStart(TS_WIDTH, '0');
10
+ }
11
+ export class RevisionStore {
12
+ constructor(fs) {
13
+ this.fs = fs;
14
+ }
15
+ objectsPath(id, ext) {
16
+ return `${OBJECTS_DIR}/${id.slice(0, 2)}/${id.slice(2)}.${ext}`;
17
+ }
18
+ journalPath(root, createdAt, leaf) {
19
+ return `${JOURNAL_DIR}/${root}/${padTs(createdAt)}-${leaf}`;
20
+ }
21
+ titlePath(root, createdAt) {
22
+ return `${TITLES_DIR}/${root}/${padTs(createdAt)}`;
23
+ }
24
+ async appendTitle(root, title, createdAt) {
25
+ await this.fs.writeFile(this.titlePath(root, createdAt), title);
26
+ }
27
+ async readMeta(id) {
28
+ return JSON.parse(await this.fs.readFile(this.objectsPath(id, 'json'), 'utf8'));
29
+ }
30
+ async write(input) {
31
+ const id = await revisionId({
32
+ scene: input.scene,
33
+ parent: input.parent,
34
+ note: input.note
35
+ });
36
+ const createdAt = Date.now();
37
+ const root = input.parent === null ? id : (await this.readMeta(input.parent)).root;
38
+ const meta = {
39
+ parent: input.parent,
40
+ root,
41
+ createdAt,
42
+ ...(input.title !== undefined ? { title: input.title } : {}),
43
+ ...(input.note !== undefined ? { note: input.note } : {})
44
+ };
45
+ const scenePath = this.objectsPath(id, 'scene');
46
+ const metaPath = this.objectsPath(id, 'json');
47
+ await this.fs.writeFile(scenePath, input.scene);
48
+ await this.fs.writeFile(metaPath, JSON.stringify(meta));
49
+ if (input.code !== undefined) {
50
+ await this.fs.writeFile(this.objectsPath(id, 'code.js'), input.code);
51
+ }
52
+ // Append-only index: one write-once journal entry per revision.
53
+ await this.fs.writeFile(this.journalPath(root, createdAt, id), '');
54
+ // Seed the title tree on root creation so listRoots needs no objects reads.
55
+ if (input.parent === null) {
56
+ await this.appendTitle(root, input.title ?? 'Untitled', createdAt);
57
+ }
58
+ return { id, meta, scene: input.scene };
59
+ }
60
+ /**
61
+ * Read the JS source that produced a revision, if it was written through
62
+ * the `edit` tool. Returns undefined when the revision has no associated
63
+ * code file (e.g. future import / convert paths). Throws ENOENT only when
64
+ * the revision id itself is unknown — callers should `.read(id)` first to
65
+ * surface that.
66
+ */
67
+ async readCode(id) {
68
+ const path = this.objectsPath(id, 'code.js');
69
+ if (!(await this.fs.exists(path)))
70
+ return undefined;
71
+ return await this.fs.readFile(path, 'utf8');
72
+ }
73
+ async read(id) {
74
+ const scene = await this.fs.readFile(this.objectsPath(id, 'scene'), 'utf8');
75
+ const metaText = await this.fs.readFile(this.objectsPath(id, 'json'), 'utf8');
76
+ const meta = JSON.parse(metaText);
77
+ return { id, meta, scene };
78
+ }
79
+ /**
80
+ * Current title for a lineage root = the latest `titles/<root>/` event.
81
+ * Falls back to "Untitled" when the root has no title events (e.g. an
82
+ * unknown root id). Public because the viewer renders the live title.
83
+ */
84
+ async currentTitle(root) {
85
+ const dir = `${TITLES_DIR}/${root}`;
86
+ if (!(await this.fs.exists(dir)))
87
+ return 'Untitled';
88
+ const events = await this.fs.readdir(dir);
89
+ if (events.length === 0)
90
+ return 'Untitled';
91
+ events.sort(); // padded-ts filenames: lexical sort == chronological
92
+ return this.fs.readFile(`${dir}/${events[events.length - 1]}`, 'utf8');
93
+ }
94
+ /**
95
+ * Reconstruct the root index by folding the journal: for each root, the
96
+ * entry with the greatest padded timestamp is the latest leaf. No mutable
97
+ * index, no roots.json. Newest-first by updatedAt.
98
+ */
99
+ async listRoots() {
100
+ if (!(await this.fs.exists(JOURNAL_DIR)))
101
+ return [];
102
+ const out = [];
103
+ for (const root of await this.fs.readdir(JOURNAL_DIR)) {
104
+ const entries = await this.fs.readdir(`${JOURNAL_DIR}/${root}`);
105
+ if (entries.length === 0)
106
+ continue;
107
+ entries.sort(); // padded-ts filenames: lexical sort == chronological
108
+ const latest = entries[entries.length - 1];
109
+ const dash = latest.indexOf('-');
110
+ const updatedAt = Number(latest.slice(0, dash));
111
+ const latestLeaf = latest.slice(dash + 1);
112
+ const title = await this.currentTitle(root);
113
+ out.push({ rootRevision: root, title, latestLeaf, updatedAt });
114
+ }
115
+ return out.sort((a, b) => b.updatedAt - a.updatedAt);
116
+ }
117
+ /** Walk from `revision` back to the root. Returns the chain (root first → revision last). */
118
+ async historyOf(revision) {
119
+ const chain = [];
120
+ let cur = revision;
121
+ while (cur !== null) {
122
+ const rev = await this.read(cur);
123
+ chain.unshift(rev);
124
+ cur = rev.meta.parent;
125
+ }
126
+ return chain;
127
+ }
128
+ /**
129
+ * Every revision in the design tree that `root` belongs to, as metadata-only
130
+ * nodes sorted by `createdAt` ascending. `root` may be any revision id in the
131
+ * design — it is resolved to its lineage root (consistent with `historyOf` /
132
+ * `renameRoot`). An id not present in the store yields `[]`.
133
+ *
134
+ * Walks all of `objects/`. Cheap at POC scale; a Phase-2 per-root index would
135
+ * replace it.
136
+ */
137
+ async treeOf(root) {
138
+ if (!(await this.fs.exists(OBJECTS_DIR)))
139
+ return [];
140
+ // Read every revision's metadata into an id -> meta map.
141
+ const metas = new Map();
142
+ for (const shard of await this.fs.readdir(OBJECTS_DIR)) {
143
+ for (const entry of await this.fs.readdir(`${OBJECTS_DIR}/${shard}`)) {
144
+ if (!entry.endsWith('.json'))
145
+ continue;
146
+ const id = shard + entry.slice(0, -'.json'.length);
147
+ metas.set(id, JSON.parse(await this.fs.readFile(`${OBJECTS_DIR}/${shard}/${entry}`, 'utf8')));
148
+ }
149
+ }
150
+ if (!metas.has(root))
151
+ return [];
152
+ // Resolve `root` to the true lineage root.
153
+ let lineageRoot = root;
154
+ for (let meta = metas.get(lineageRoot); meta?.parent != null; meta = metas.get(lineageRoot)) {
155
+ lineageRoot = meta.parent;
156
+ }
157
+ // Index children by parent.
158
+ const children = new Map();
159
+ for (const [id, meta] of metas) {
160
+ if (meta.parent != null) {
161
+ const siblings = children.get(meta.parent) ?? [];
162
+ siblings.push(id);
163
+ children.set(meta.parent, siblings);
164
+ }
165
+ }
166
+ // BFS from the lineage root; collect the connected tree.
167
+ const nodes = [];
168
+ const queue = [lineageRoot];
169
+ for (let id = queue.shift(); id !== undefined; id = queue.shift()) {
170
+ const meta = metas.get(id);
171
+ if (meta === undefined)
172
+ continue;
173
+ nodes.push({
174
+ id,
175
+ parent: meta.parent,
176
+ note: meta.note,
177
+ createdAt: meta.createdAt
178
+ });
179
+ queue.push(...(children.get(id) ?? []));
180
+ }
181
+ nodes.sort((a, b) => a.createdAt - b.createdAt);
182
+ return nodes;
183
+ }
184
+ /**
185
+ * Rename the root of `revision`'s lineage by appending a title event.
186
+ * `revision` may be mid-chain — its `meta.root` points at the lineage root.
187
+ * Titles are append-only (immutable revisions are never rewritten); the
188
+ * "current" title is the latest event (see `currentTitle`).
189
+ */
190
+ async renameRoot(revision, title) {
191
+ const { root } = await this.readMeta(revision);
192
+ await this.appendTitle(root, title, Date.now());
193
+ return { rootRevision: root };
194
+ }
195
+ }
196
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/revisions/store.ts"],"names":[],"mappings":"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","sourcesContent":["//\n// RevisionStore — pure logic over a WorkspaceFS. Sharded `objects/<ab>/<rest>`\n// layout (git-style), fully immutable/content-addressed. The index is\n// append-only and event-sourced: every write appends a write-once\n// `journal/<root>/<paddedTs>-<leaf>` entry, and titles are append-only\n// `titles/<root>/<paddedTs>` events. `listRoots`/`currentTitle` reconstruct\n// state by folding a `readdir` — no mutable file, no lock, no external DB.\n//\n// Each revision can have up to three sibling files:\n// <id>.scene → scene bytes (always present)\n// <id>.json → meta {parent, note?, title?, createdAt} (always present)\n// <id>.code.js → the JS that the `edit` tool ran to produce this revision\n// (present only when written through the edit tool; never\n// for revisions written by future import / convert paths)\n// Code is intentionally NOT in `revisionId` — the id identifies the scene\n// state, not the path that produced it. Two distinct code paths arriving at\n// the same scene with the same parent+note are the same revision.\n//\nimport type { WorkspaceFS } from '../workspace/types.js';\nimport { revisionId } from './hash.js';\nimport type {\n Revision,\n RevisionMeta,\n RevisionNode,\n RootEntry\n} from './types.js';\n\nconst OBJECTS_DIR = 'objects';\nconst JOURNAL_DIR = 'journal';\nconst TITLES_DIR = 'titles';\n// Zero-pad createdAtMs so a lexical `readdir` sort equals chronological order.\n// 16 digits covers epoch-ms well beyond the year 5000.\nconst TS_WIDTH = 16;\n\nfunction padTs(ms: number): string {\n return String(ms).padStart(TS_WIDTH, '0');\n}\n\nexport interface WriteRevisionInput {\n scene: string;\n parent: string | null;\n title?: string;\n note?: string;\n /**\n * Optional: the JS source that produced this revision. Persisted as a\n * sibling `<id>.code.js` file so a future agent (via the `inspect` tool)\n * can read what operations led to this state. Not part of `revisionId`.\n */\n code?: string;\n}\n\nexport class RevisionStore {\n constructor(private readonly fs: WorkspaceFS) {}\n\n private objectsPath(id: string, ext: 'scene' | 'json' | 'code.js'): string {\n return `${OBJECTS_DIR}/${id.slice(0, 2)}/${id.slice(2)}.${ext}`;\n }\n\n private journalPath(root: string, createdAt: number, leaf: string): string {\n return `${JOURNAL_DIR}/${root}/${padTs(createdAt)}-${leaf}`;\n }\n\n private titlePath(root: string, createdAt: number): string {\n return `${TITLES_DIR}/${root}/${padTs(createdAt)}`;\n }\n\n private async appendTitle(\n root: string,\n title: string,\n createdAt: number\n ): Promise<void> {\n await this.fs.writeFile(this.titlePath(root, createdAt), title);\n }\n\n private async readMeta(id: string): Promise<RevisionMeta> {\n return JSON.parse(\n await this.fs.readFile(this.objectsPath(id, 'json'), 'utf8')\n ) as RevisionMeta;\n }\n\n async write(input: WriteRevisionInput): Promise<Revision> {\n const id = await revisionId({\n scene: input.scene,\n parent: input.parent,\n note: input.note\n });\n const createdAt = Date.now();\n const root =\n input.parent === null ? id : (await this.readMeta(input.parent)).root;\n const meta: RevisionMeta = {\n parent: input.parent,\n root,\n createdAt,\n ...(input.title !== undefined ? { title: input.title } : {}),\n ...(input.note !== undefined ? { note: input.note } : {})\n };\n const scenePath = this.objectsPath(id, 'scene');\n const metaPath = this.objectsPath(id, 'json');\n await this.fs.writeFile(scenePath, input.scene);\n await this.fs.writeFile(metaPath, JSON.stringify(meta));\n if (input.code !== undefined) {\n await this.fs.writeFile(this.objectsPath(id, 'code.js'), input.code);\n }\n // Append-only index: one write-once journal entry per revision.\n await this.fs.writeFile(this.journalPath(root, createdAt, id), '');\n // Seed the title tree on root creation so listRoots needs no objects reads.\n if (input.parent === null) {\n await this.appendTitle(root, input.title ?? 'Untitled', createdAt);\n }\n return { id, meta, scene: input.scene };\n }\n\n /**\n * Read the JS source that produced a revision, if it was written through\n * the `edit` tool. Returns undefined when the revision has no associated\n * code file (e.g. future import / convert paths). Throws ENOENT only when\n * the revision id itself is unknown — callers should `.read(id)` first to\n * surface that.\n */\n async readCode(id: string): Promise<string | undefined> {\n const path = this.objectsPath(id, 'code.js');\n if (!(await this.fs.exists(path))) return undefined;\n return await this.fs.readFile(path, 'utf8');\n }\n\n async read(id: string): Promise<Revision> {\n const scene = await this.fs.readFile(this.objectsPath(id, 'scene'), 'utf8');\n const metaText = await this.fs.readFile(\n this.objectsPath(id, 'json'),\n 'utf8'\n );\n const meta = JSON.parse(metaText) as RevisionMeta;\n return { id, meta, scene };\n }\n\n /**\n * Current title for a lineage root = the latest `titles/<root>/` event.\n * Falls back to \"Untitled\" when the root has no title events (e.g. an\n * unknown root id). Public because the viewer renders the live title.\n */\n async currentTitle(root: string): Promise<string> {\n const dir = `${TITLES_DIR}/${root}`;\n if (!(await this.fs.exists(dir))) return 'Untitled';\n const events = await this.fs.readdir(dir);\n if (events.length === 0) return 'Untitled';\n events.sort(); // padded-ts filenames: lexical sort == chronological\n return this.fs.readFile(`${dir}/${events[events.length - 1]}`, 'utf8');\n }\n\n /**\n * Reconstruct the root index by folding the journal: for each root, the\n * entry with the greatest padded timestamp is the latest leaf. No mutable\n * index, no roots.json. Newest-first by updatedAt.\n */\n async listRoots(): Promise<Array<{ rootRevision: string } & RootEntry>> {\n if (!(await this.fs.exists(JOURNAL_DIR))) return [];\n const out: Array<{ rootRevision: string } & RootEntry> = [];\n for (const root of await this.fs.readdir(JOURNAL_DIR)) {\n const entries = await this.fs.readdir(`${JOURNAL_DIR}/${root}`);\n if (entries.length === 0) continue;\n entries.sort(); // padded-ts filenames: lexical sort == chronological\n const latest = entries[entries.length - 1];\n const dash = latest.indexOf('-');\n const updatedAt = Number(latest.slice(0, dash));\n const latestLeaf = latest.slice(dash + 1);\n const title = await this.currentTitle(root);\n out.push({ rootRevision: root, title, latestLeaf, updatedAt });\n }\n return out.sort((a, b) => b.updatedAt - a.updatedAt);\n }\n\n /** Walk from `revision` back to the root. Returns the chain (root first → revision last). */\n async historyOf(revision: string): Promise<Revision[]> {\n const chain: Revision[] = [];\n let cur: string | null = revision;\n while (cur !== null) {\n const rev = await this.read(cur);\n chain.unshift(rev);\n cur = rev.meta.parent;\n }\n return chain;\n }\n\n /**\n * Every revision in the design tree that `root` belongs to, as metadata-only\n * nodes sorted by `createdAt` ascending. `root` may be any revision id in the\n * design — it is resolved to its lineage root (consistent with `historyOf` /\n * `renameRoot`). An id not present in the store yields `[]`.\n *\n * Walks all of `objects/`. Cheap at POC scale; a Phase-2 per-root index would\n * replace it.\n */\n async treeOf(root: string): Promise<RevisionNode[]> {\n if (!(await this.fs.exists(OBJECTS_DIR))) return [];\n // Read every revision's metadata into an id -> meta map.\n const metas = new Map<string, RevisionMeta>();\n for (const shard of await this.fs.readdir(OBJECTS_DIR)) {\n for (const entry of await this.fs.readdir(`${OBJECTS_DIR}/${shard}`)) {\n if (!entry.endsWith('.json')) continue;\n const id = shard + entry.slice(0, -'.json'.length);\n metas.set(\n id,\n JSON.parse(\n await this.fs.readFile(`${OBJECTS_DIR}/${shard}/${entry}`, 'utf8')\n ) as RevisionMeta\n );\n }\n }\n if (!metas.has(root)) return [];\n // Resolve `root` to the true lineage root.\n let lineageRoot = root;\n for (\n let meta = metas.get(lineageRoot);\n meta?.parent != null;\n meta = metas.get(lineageRoot)\n ) {\n lineageRoot = meta.parent;\n }\n // Index children by parent.\n const children = new Map<string, string[]>();\n for (const [id, meta] of metas) {\n if (meta.parent != null) {\n const siblings = children.get(meta.parent) ?? [];\n siblings.push(id);\n children.set(meta.parent, siblings);\n }\n }\n // BFS from the lineage root; collect the connected tree.\n const nodes: RevisionNode[] = [];\n const queue: string[] = [lineageRoot];\n for (let id = queue.shift(); id !== undefined; id = queue.shift()) {\n const meta = metas.get(id);\n if (meta === undefined) continue;\n nodes.push({\n id,\n parent: meta.parent,\n note: meta.note,\n createdAt: meta.createdAt\n });\n queue.push(...(children.get(id) ?? []));\n }\n nodes.sort((a, b) => a.createdAt - b.createdAt);\n return nodes;\n }\n\n /**\n * Rename the root of `revision`'s lineage by appending a title event.\n * `revision` may be mid-chain — its `meta.root` points at the lineage root.\n * Titles are append-only (immutable revisions are never rewritten); the\n * \"current\" title is the latest event (see `currentTitle`).\n */\n async renameRoot(\n revision: string,\n title: string\n ): Promise<{ rootRevision: string }> {\n const { root } = await this.readMeta(revision);\n await this.appendTitle(root, title, Date.now());\n return { rootRevision: root };\n }\n}\n"]}
@@ -0,0 +1,39 @@
1
+ /** Persisted metadata for one revision (next to the .scene file). */
2
+ export interface RevisionMeta {
3
+ /** Parent revision id, or null for a root revision. */
4
+ parent: string | null;
5
+ /**
6
+ * Lineage root revision id. For a root revision (parent === null) this
7
+ * equals the revision's own id. Denormalized so a child resolves its root
8
+ * with one parent read instead of walking the whole chain. Not part of
9
+ * `revisionId` (the hash is scene + parent + note).
10
+ */
11
+ root: string;
12
+ /** Creation-time design title — seeded ONLY on root revisions. For the live/current title (after renames) use `RevisionStore.currentTitle()`. */
13
+ title?: string;
14
+ /** Freeform note from the agent describing what this edit accomplished. */
15
+ note?: string;
16
+ /** UNIX-epoch ms when this revision was written. */
17
+ createdAt: number;
18
+ }
19
+ /** One revision as the agent + viewer see it: id + meta + scene bytes (string). */
20
+ export interface Revision {
21
+ id: string;
22
+ meta: RevisionMeta;
23
+ scene: string;
24
+ }
25
+ /** Shape of one entry returned by `listRoots()` (reconstructed from the journal + title events). */
26
+ export interface RootEntry {
27
+ title: string;
28
+ /** The most recently written leaf for this root (the "latest tip"). */
29
+ latestLeaf: string;
30
+ updatedAt: number;
31
+ }
32
+ /** One revision as the viewer's tree panel sees it: metadata only, no scene. */
33
+ export interface RevisionNode {
34
+ id: string;
35
+ parent: string | null;
36
+ note?: string;
37
+ createdAt: number;
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/revisions/types.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,iJAAiJ;IACjJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,mFAAmF;AACnF,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,oGAAoG;AACpG,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/revisions/types.ts"],"names":[],"mappings":"","sourcesContent":["/** Persisted metadata for one revision (next to the .scene file). */\nexport interface RevisionMeta {\n /** Parent revision id, or null for a root revision. */\n parent: string | null;\n /**\n * Lineage root revision id. For a root revision (parent === null) this\n * equals the revision's own id. Denormalized so a child resolves its root\n * with one parent read instead of walking the whole chain. Not part of\n * `revisionId` (the hash is scene + parent + note).\n */\n root: string;\n /** Creation-time design title — seeded ONLY on root revisions. For the live/current title (after renames) use `RevisionStore.currentTitle()`. */\n title?: string;\n /** Freeform note from the agent describing what this edit accomplished. */\n note?: string;\n /** UNIX-epoch ms when this revision was written. */\n createdAt: number;\n}\n\n/** One revision as the agent + viewer see it: id + meta + scene bytes (string). */\nexport interface Revision {\n id: string;\n meta: RevisionMeta;\n scene: string;\n}\n\n/** Shape of one entry returned by `listRoots()` (reconstructed from the journal + title events). */\nexport interface RootEntry {\n title: string;\n /** The most recently written leaf for this root (the \"latest tip\"). */\n latestLeaf: string;\n updatedAt: number;\n}\n\n/** One revision as the viewer's tree panel sees it: metadata only, no scene. */\nexport interface RevisionNode {\n id: string;\n parent: string | null;\n note?: string;\n createdAt: number;\n}\n"]}