@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,90 @@
1
+ // `node:fs/promises`-backed WorkspaceFS rooted at a host directory. The bulk
2
+ // of methods are thin passthroughs; the exceptions are documented inline:
3
+ // - writeFile creates parent dirs (our consumers expect that; node does not)
4
+ // - exists is implemented in terms of stat (node deprecates fs.exists)
5
+ import { promises as nodeFs } from 'node:fs';
6
+ import { dirname, normalize as nodeNormalize, resolve as resolvePath } from 'node:path';
7
+ function toPosix(p) {
8
+ return p.replace(/\\/g, '/');
9
+ }
10
+ export class NodeWorkspaceFS {
11
+ constructor(root) {
12
+ this.root = root;
13
+ }
14
+ abs(path) {
15
+ // Strip leading slash so `resolve` doesn't escape root.
16
+ const trimmed = path.startsWith('/') ? path.slice(1) : path;
17
+ const resolved = resolvePath(this.root, nodeNormalize(trimmed));
18
+ const rootResolved = resolvePath(this.root);
19
+ if (resolved !== rootResolved &&
20
+ !resolved.startsWith(`${rootResolved}/`) &&
21
+ !resolved.startsWith(`${rootResolved}\\`)) {
22
+ const err = new Error(`path escapes workspace root: ${path}`);
23
+ err.code = 'EACCES';
24
+ throw err;
25
+ }
26
+ return resolved;
27
+ }
28
+ async readFile(path, options) {
29
+ const encoding = typeof options === 'string' ? options : (options?.encoding ?? null);
30
+ const abs = this.abs(path);
31
+ if (encoding === 'utf8' || encoding === 'utf-8')
32
+ return nodeFs.readFile(abs, 'utf8');
33
+ const buf = await nodeFs.readFile(abs);
34
+ return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
35
+ }
36
+ async writeFile(path, data) {
37
+ const abs = this.abs(path);
38
+ await nodeFs.mkdir(dirname(abs), { recursive: true });
39
+ await nodeFs.writeFile(abs, data);
40
+ }
41
+ async stat(path) {
42
+ const st = await nodeFs.stat(this.abs(path));
43
+ return {
44
+ size: st.size,
45
+ mtimeMs: st.mtimeMs,
46
+ isFile: () => st.isFile(),
47
+ isDirectory: () => st.isDirectory()
48
+ };
49
+ }
50
+ async exists(path) {
51
+ try {
52
+ await nodeFs.stat(this.abs(path));
53
+ return true;
54
+ }
55
+ catch (err) {
56
+ if (err.code === 'ENOENT')
57
+ return false;
58
+ throw err;
59
+ }
60
+ }
61
+ async readdir(path, options) {
62
+ const abs = this.abs(path);
63
+ if (options?.withFileTypes) {
64
+ const entries = await nodeFs.readdir(abs, { withFileTypes: true });
65
+ return entries.map((e) => ({
66
+ name: toPosix(e.name),
67
+ isFile: () => e.isFile(),
68
+ isDirectory: () => e.isDirectory()
69
+ }));
70
+ }
71
+ return (await nodeFs.readdir(abs)).map(toPosix);
72
+ }
73
+ async mkdir(path, options) {
74
+ await nodeFs.mkdir(this.abs(path), { recursive: options?.recursive });
75
+ }
76
+ async rm(path, options) {
77
+ const rmOptions = {};
78
+ if (options?.recursive !== undefined)
79
+ rmOptions.recursive = options.recursive;
80
+ if (options?.force !== undefined)
81
+ rmOptions.force = options.force;
82
+ await nodeFs.rm(this.abs(path), rmOptions);
83
+ }
84
+ async rename(oldPath, newPath) {
85
+ const newAbs = this.abs(newPath);
86
+ await nodeFs.mkdir(dirname(newAbs), { recursive: true });
87
+ await nodeFs.rename(this.abs(oldPath), newAbs);
88
+ }
89
+ }
90
+ //# sourceMappingURL=node-fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-fs.js","sourceRoot":"","sources":["../../src/workspace/node-fs.ts"],"names":[],"mappings":"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","sourcesContent":["// `node:fs/promises`-backed WorkspaceFS rooted at a host directory. The bulk\n// of methods are thin passthroughs; the exceptions are documented inline:\n// - writeFile creates parent dirs (our consumers expect that; node does not)\n// - exists is implemented in terms of stat (node deprecates fs.exists)\nimport { promises as nodeFs } from 'node:fs';\nimport {\n dirname,\n normalize as nodeNormalize,\n resolve as resolvePath\n} from 'node:path';\nimport type {\n Dirent,\n FileHandleStats,\n MkdirOptions,\n ReaddirOptions,\n ReadFileOptions,\n WorkspaceFS\n} from './types.js';\n\nfunction toPosix(p: string): string {\n return p.replace(/\\\\/g, '/');\n}\n\nexport class NodeWorkspaceFS implements WorkspaceFS {\n constructor(public readonly root: string) {}\n\n private abs(path: string): string {\n // Strip leading slash so `resolve` doesn't escape root.\n const trimmed = path.startsWith('/') ? path.slice(1) : path;\n const resolved = resolvePath(this.root, nodeNormalize(trimmed));\n const rootResolved = resolvePath(this.root);\n if (\n resolved !== rootResolved &&\n !resolved.startsWith(`${rootResolved}/`) &&\n !resolved.startsWith(`${rootResolved}\\\\`)\n ) {\n const err = new Error(`path escapes workspace root: ${path}`) as Error & {\n code: string;\n };\n err.code = 'EACCES';\n throw err;\n }\n return resolved;\n }\n\n async readFile(path: string): Promise<Uint8Array>;\n async readFile(path: string, encoding: 'utf8' | 'utf-8'): Promise<string>;\n async readFile(\n path: string,\n options: ReadFileOptions\n ): Promise<Uint8Array | string>;\n async readFile(\n path: string,\n options?: 'utf8' | 'utf-8' | ReadFileOptions\n ): Promise<Uint8Array | string> {\n const encoding =\n typeof options === 'string' ? options : (options?.encoding ?? null);\n const abs = this.abs(path);\n if (encoding === 'utf8' || encoding === 'utf-8')\n return nodeFs.readFile(abs, 'utf8');\n const buf = await nodeFs.readFile(abs);\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n }\n\n async writeFile(path: string, data: Uint8Array | string): Promise<void> {\n const abs = this.abs(path);\n await nodeFs.mkdir(dirname(abs), { recursive: true });\n await nodeFs.writeFile(abs, data);\n }\n\n async stat(path: string): Promise<FileHandleStats> {\n const st = await nodeFs.stat(this.abs(path));\n return {\n size: st.size,\n mtimeMs: st.mtimeMs,\n isFile: () => st.isFile(),\n isDirectory: () => st.isDirectory()\n };\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await nodeFs.stat(this.abs(path));\n return true;\n } catch (err) {\n if ((err as { code?: string }).code === 'ENOENT') return false;\n throw err;\n }\n }\n\n async readdir(path: string): Promise<string[]>;\n async readdir(\n path: string,\n options: { withFileTypes: true }\n ): Promise<Dirent[]>;\n async readdir(\n path: string,\n options?: ReaddirOptions\n ): Promise<string[] | Dirent[]> {\n const abs = this.abs(path);\n if (options?.withFileTypes) {\n const entries = await nodeFs.readdir(abs, { withFileTypes: true });\n return entries.map(\n (e): Dirent => ({\n name: toPosix(e.name),\n isFile: () => e.isFile(),\n isDirectory: () => e.isDirectory()\n })\n );\n }\n return (await nodeFs.readdir(abs)).map(toPosix);\n }\n\n async mkdir(path: string, options?: MkdirOptions): Promise<void> {\n await nodeFs.mkdir(this.abs(path), { recursive: options?.recursive });\n }\n\n async rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean }\n ): Promise<void> {\n const rmOptions: { recursive?: boolean; force?: boolean } = {};\n if (options?.recursive !== undefined)\n rmOptions.recursive = options.recursive;\n if (options?.force !== undefined) rmOptions.force = options.force;\n await nodeFs.rm(this.abs(path), rmOptions);\n }\n\n async rename(oldPath: string, newPath: string): Promise<void> {\n const newAbs = this.abs(newPath);\n await nodeFs.mkdir(dirname(newAbs), { recursive: true });\n await nodeFs.rename(this.abs(oldPath), newAbs);\n }\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { type Dirent, type FileHandleStats, type MkdirOptions, type ReadFileOptions, type WorkspaceFS } from './types.js';
2
+ /** The subset of the AWS SDK S3Client the adapter uses (also lets tests inject a fake). */
3
+ export interface S3Like {
4
+ send(command: unknown): Promise<unknown>;
5
+ }
6
+ export interface S3WorkspaceFSOptions {
7
+ client: S3Like;
8
+ bucket: string;
9
+ }
10
+ export declare class S3WorkspaceFS implements WorkspaceFS {
11
+ private readonly client;
12
+ private readonly bucket;
13
+ constructor(opts: S3WorkspaceFSOptions);
14
+ private getBytes;
15
+ readFile(path: string): Promise<Uint8Array>;
16
+ readFile(path: string, encoding: 'utf8' | 'utf-8'): Promise<string>;
17
+ readFile(path: string, options: ReadFileOptions): Promise<Uint8Array | string>;
18
+ writeFile(path: string, data: Uint8Array | string): Promise<void>;
19
+ stat(path: string): Promise<FileHandleStats>;
20
+ exists(path: string): Promise<boolean>;
21
+ readdir(path: string): Promise<string[]>;
22
+ readdir(path: string, options: {
23
+ withFileTypes: true;
24
+ }): Promise<Dirent[]>;
25
+ mkdir(_path: string, _options?: MkdirOptions): Promise<void>;
26
+ rm(path: string, options?: {
27
+ recursive?: boolean;
28
+ force?: boolean;
29
+ }): Promise<void>;
30
+ rename(oldPath: string, newPath: string): Promise<void>;
31
+ }
32
+ //# sourceMappingURL=s3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/workspace/s3.ts"],"names":[],"mappings":"AAqBA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,eAAe,EAEpB,KAAK,YAAY,EAEjB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB,2FAA2F;AAC3F,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAwBD,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,IAAI,EAAE,oBAAoB;YAKxB,QAAQ;IAoBhB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IACnE,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC;IAazB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA4B5C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBtC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IACxC,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,aAAa,EAAE,IAAI,CAAA;KAAE,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC;IAuDd,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5D,EAAE,CACN,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACjD,OAAO,CAAC,IAAI,CAAC;IAqCV,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ9D"}
@@ -0,0 +1,191 @@
1
+ // packages/codesign-mcp/src/workspace/s3.ts
2
+ //
3
+ // Direct S3/R2 WorkspaceFS. Works against AWS S3 and Cloudflare R2 (via its
4
+ // S3-compatible endpoint with R2 API tokens — a binding is a Workers-runtime
5
+ // API NOT available inside a container, see spec §9.2). Tenant-agnostic and
6
+ // rooted at the bucket; ScopedWorkspaceFS adds the `workspaces/<id>/` prefix.
7
+ //
8
+ // Contract notes (spec §4.3/§4.5):
9
+ // - writeFile is a single awaited PutObject -> durable-on-return.
10
+ // - hot-path reads are by-id GetObject; a bounded retry (READ_RETRIES) absorbs
11
+ // a rare read-after-write 404, then a persistent miss surfaces as ENOENT.
12
+ //
13
+ // NOT exported from workspace/index.ts on purpose: keeps @aws-sdk/client-s3 out
14
+ // of the browser bundle. cli/http.ts imports it directly (node-only).
15
+ import { DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand } from '@aws-sdk/client-s3';
16
+ import { fsError } from './types.js';
17
+ const READ_RETRIES = 3;
18
+ // ~120ms between read retries: long enough to span typical eventual-consistency
19
+ // propagation on R2/S3, short enough not to stall the hot read path.
20
+ const RETRY_DELAY_MS = 120;
21
+ function is404(err) {
22
+ const e = err;
23
+ return (e?.name === 'NoSuchKey' ||
24
+ e?.name === 'NotFound' ||
25
+ e?.$metadata?.httpStatusCode === 404);
26
+ }
27
+ function delay(ms) {
28
+ return new Promise((resolve) => setTimeout(resolve, ms));
29
+ }
30
+ function normalizeKey(path) {
31
+ return path.startsWith('/') ? path.slice(1) : path;
32
+ }
33
+ export class S3WorkspaceFS {
34
+ constructor(opts) {
35
+ this.client = opts.client;
36
+ this.bucket = opts.bucket;
37
+ }
38
+ async getBytes(key) {
39
+ let lastErr;
40
+ for (let attempt = 0; attempt < READ_RETRIES; attempt++) {
41
+ try {
42
+ const res = (await this.client.send(new GetObjectCommand({ Bucket: this.bucket, Key: key })));
43
+ const body = res.Body;
44
+ if (!body)
45
+ throw fsError('ENOENT', `empty body: ${key}`);
46
+ return await body.transformToByteArray();
47
+ }
48
+ catch (err) {
49
+ lastErr = err;
50
+ if (!is404(err))
51
+ throw err;
52
+ if (attempt < READ_RETRIES - 1)
53
+ await delay(RETRY_DELAY_MS);
54
+ }
55
+ }
56
+ if (is404(lastErr))
57
+ throw fsError('ENOENT', `no such key: ${key}`);
58
+ throw lastErr;
59
+ }
60
+ async readFile(path, options) {
61
+ const bytes = await this.getBytes(normalizeKey(path));
62
+ const encoding = typeof options === 'string' ? options : (options?.encoding ?? null);
63
+ if (encoding === 'utf8' || encoding === 'utf-8')
64
+ return new TextDecoder('utf-8').decode(bytes);
65
+ return bytes;
66
+ }
67
+ async writeFile(path, data) {
68
+ const body = typeof data === 'string' ? new TextEncoder().encode(data) : data;
69
+ await this.client.send(new PutObjectCommand({
70
+ Bucket: this.bucket,
71
+ Key: normalizeKey(path),
72
+ Body: body
73
+ }));
74
+ }
75
+ async stat(path) {
76
+ const key = normalizeKey(path);
77
+ try {
78
+ const head = (await this.client.send(new HeadObjectCommand({ Bucket: this.bucket, Key: key })));
79
+ return {
80
+ size: head.ContentLength ?? 0,
81
+ mtimeMs: head.LastModified ? head.LastModified.getTime() : 0,
82
+ isFile: () => true,
83
+ isDirectory: () => false
84
+ };
85
+ }
86
+ catch (err) {
87
+ if (is404(err)) {
88
+ if (await this.exists(key)) {
89
+ return {
90
+ size: 0,
91
+ mtimeMs: 0,
92
+ isFile: () => false,
93
+ isDirectory: () => true
94
+ };
95
+ }
96
+ throw fsError('ENOENT', `no such key: ${key}`);
97
+ }
98
+ throw err;
99
+ }
100
+ }
101
+ async exists(path) {
102
+ const key = normalizeKey(path);
103
+ try {
104
+ await this.client.send(new HeadObjectCommand({ Bucket: this.bucket, Key: key }));
105
+ return true;
106
+ }
107
+ catch (err) {
108
+ if (!is404(err))
109
+ throw err;
110
+ }
111
+ const res = (await this.client.send(new ListObjectsV2Command({
112
+ Bucket: this.bucket,
113
+ Prefix: `${key}/`,
114
+ MaxKeys: 1
115
+ })));
116
+ return (res.Contents?.length ?? 0) > 0;
117
+ }
118
+ async readdir(path, options) {
119
+ const key = normalizeKey(path);
120
+ const prefix = key === '' ? '' : `${key}/`;
121
+ const files = [];
122
+ const dirs = [];
123
+ let token;
124
+ do {
125
+ const res = (await this.client.send(new ListObjectsV2Command({
126
+ Bucket: this.bucket,
127
+ Prefix: prefix,
128
+ Delimiter: '/',
129
+ ContinuationToken: token
130
+ })));
131
+ for (const c of res.Contents ?? []) {
132
+ if (c.Key && c.Key !== prefix)
133
+ files.push(c.Key.slice(prefix.length));
134
+ }
135
+ for (const p of res.CommonPrefixes ?? []) {
136
+ if (p.Prefix)
137
+ dirs.push(p.Prefix.slice(prefix.length).replace(/\/$/, ''));
138
+ }
139
+ token = res.IsTruncated ? res.NextContinuationToken : undefined;
140
+ } while (token);
141
+ if (options?.withFileTypes) {
142
+ return [
143
+ ...dirs.map((name) => ({
144
+ name,
145
+ isFile: () => false,
146
+ isDirectory: () => true
147
+ })),
148
+ ...files.map((name) => ({
149
+ name,
150
+ isFile: () => true,
151
+ isDirectory: () => false
152
+ }))
153
+ ];
154
+ }
155
+ return [...dirs, ...files];
156
+ }
157
+ async mkdir(_path, _options) {
158
+ // S3 has no directories; mkdir is a no-op (keys imply their prefixes).
159
+ }
160
+ async rm(path, options) {
161
+ const key = normalizeKey(path);
162
+ if (options?.recursive) {
163
+ let token;
164
+ do {
165
+ const res = (await this.client.send(new ListObjectsV2Command({
166
+ Bucket: this.bucket,
167
+ Prefix: `${key}/`,
168
+ ContinuationToken: token
169
+ })));
170
+ for (const c of res.Contents ?? []) {
171
+ if (c.Key)
172
+ await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: c.Key }));
173
+ }
174
+ token = res.IsTruncated ? res.NextContinuationToken : undefined;
175
+ } while (token);
176
+ // node:fs.rm(path,{recursive:true}) removes the path itself too; an S3
177
+ // delete of a missing key is a no-op, so this is safe whether or not
178
+ // `key` exists as an object in its own right.
179
+ await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: key }));
180
+ return;
181
+ }
182
+ await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: key }));
183
+ }
184
+ async rename(oldPath, newPath) {
185
+ const oldKey = normalizeKey(oldPath);
186
+ const bytes = await this.getBytes(oldKey);
187
+ await this.writeFile(newPath, bytes);
188
+ await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: oldKey }));
189
+ }
190
+ }
191
+ //# sourceMappingURL=s3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/workspace/s3.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/workspace/s3.ts\n//\n// Direct S3/R2 WorkspaceFS. Works against AWS S3 and Cloudflare R2 (via its\n// S3-compatible endpoint with R2 API tokens — a binding is a Workers-runtime\n// API NOT available inside a container, see spec §9.2). Tenant-agnostic and\n// rooted at the bucket; ScopedWorkspaceFS adds the `workspaces/<id>/` prefix.\n//\n// Contract notes (spec §4.3/§4.5):\n// - writeFile is a single awaited PutObject -> durable-on-return.\n// - hot-path reads are by-id GetObject; a bounded retry (READ_RETRIES) absorbs\n// a rare read-after-write 404, then a persistent miss surfaces as ENOENT.\n//\n// NOT exported from workspace/index.ts on purpose: keeps @aws-sdk/client-s3 out\n// of the browser bundle. cli/http.ts imports it directly (node-only).\nimport {\n DeleteObjectCommand,\n GetObjectCommand,\n HeadObjectCommand,\n ListObjectsV2Command,\n PutObjectCommand\n} from '@aws-sdk/client-s3';\nimport {\n type Dirent,\n type FileHandleStats,\n fsError,\n type MkdirOptions,\n type ReaddirOptions,\n type ReadFileOptions,\n type WorkspaceFS\n} from './types.js';\n\n/** The subset of the AWS SDK S3Client the adapter uses (also lets tests inject a fake). */\nexport interface S3Like {\n send(command: unknown): Promise<unknown>;\n}\n\nexport interface S3WorkspaceFSOptions {\n client: S3Like;\n bucket: string;\n}\n\nconst READ_RETRIES = 3;\n// ~120ms between read retries: long enough to span typical eventual-consistency\n// propagation on R2/S3, short enough not to stall the hot read path.\nconst RETRY_DELAY_MS = 120;\n\nfunction is404(err: unknown): boolean {\n const e = err as { name?: string; $metadata?: { httpStatusCode?: number } };\n return (\n e?.name === 'NoSuchKey' ||\n e?.name === 'NotFound' ||\n e?.$metadata?.httpStatusCode === 404\n );\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction normalizeKey(path: string): string {\n return path.startsWith('/') ? path.slice(1) : path;\n}\n\nexport class S3WorkspaceFS implements WorkspaceFS {\n private readonly client: S3Like;\n private readonly bucket: string;\n\n constructor(opts: S3WorkspaceFSOptions) {\n this.client = opts.client;\n this.bucket = opts.bucket;\n }\n\n private async getBytes(key: string): Promise<Uint8Array> {\n let lastErr: unknown;\n for (let attempt = 0; attempt < READ_RETRIES; attempt++) {\n try {\n const res = (await this.client.send(\n new GetObjectCommand({ Bucket: this.bucket, Key: key })\n )) as { Body?: { transformToByteArray(): Promise<Uint8Array> } };\n const body = res.Body;\n if (!body) throw fsError('ENOENT', `empty body: ${key}`);\n return await body.transformToByteArray();\n } catch (err) {\n lastErr = err;\n if (!is404(err)) throw err;\n if (attempt < READ_RETRIES - 1) await delay(RETRY_DELAY_MS);\n }\n }\n if (is404(lastErr)) throw fsError('ENOENT', `no such key: ${key}`);\n throw lastErr;\n }\n\n async readFile(path: string): Promise<Uint8Array>;\n async readFile(path: string, encoding: 'utf8' | 'utf-8'): Promise<string>;\n async readFile(\n path: string,\n options: ReadFileOptions\n ): Promise<Uint8Array | string>;\n async readFile(\n path: string,\n options?: 'utf8' | 'utf-8' | ReadFileOptions\n ): Promise<Uint8Array | string> {\n const bytes = await this.getBytes(normalizeKey(path));\n const encoding =\n typeof options === 'string' ? options : (options?.encoding ?? null);\n if (encoding === 'utf8' || encoding === 'utf-8')\n return new TextDecoder('utf-8').decode(bytes);\n return bytes;\n }\n\n async writeFile(path: string, data: Uint8Array | string): Promise<void> {\n const body =\n typeof data === 'string' ? new TextEncoder().encode(data) : data;\n await this.client.send(\n new PutObjectCommand({\n Bucket: this.bucket,\n Key: normalizeKey(path),\n Body: body\n })\n );\n }\n\n async stat(path: string): Promise<FileHandleStats> {\n const key = normalizeKey(path);\n try {\n const head = (await this.client.send(\n new HeadObjectCommand({ Bucket: this.bucket, Key: key })\n )) as { ContentLength?: number; LastModified?: Date };\n return {\n size: head.ContentLength ?? 0,\n mtimeMs: head.LastModified ? head.LastModified.getTime() : 0,\n isFile: () => true,\n isDirectory: () => false\n };\n } catch (err) {\n if (is404(err)) {\n if (await this.exists(key)) {\n return {\n size: 0,\n mtimeMs: 0,\n isFile: () => false,\n isDirectory: () => true\n };\n }\n throw fsError('ENOENT', `no such key: ${key}`);\n }\n throw err;\n }\n }\n\n async exists(path: string): Promise<boolean> {\n const key = normalizeKey(path);\n try {\n await this.client.send(\n new HeadObjectCommand({ Bucket: this.bucket, Key: key })\n );\n return true;\n } catch (err) {\n if (!is404(err)) throw err;\n }\n const res = (await this.client.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: `${key}/`,\n MaxKeys: 1\n })\n )) as { Contents?: unknown[] };\n return (res.Contents?.length ?? 0) > 0;\n }\n\n async readdir(path: string): Promise<string[]>;\n async readdir(\n path: string,\n options: { withFileTypes: true }\n ): Promise<Dirent[]>;\n async readdir(\n path: string,\n options?: ReaddirOptions\n ): Promise<string[] | Dirent[]> {\n const key = normalizeKey(path);\n const prefix = key === '' ? '' : `${key}/`;\n const files: string[] = [];\n const dirs: string[] = [];\n let token: string | undefined;\n do {\n const res = (await this.client.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: prefix,\n Delimiter: '/',\n ContinuationToken: token\n })\n )) as {\n Contents?: Array<{ Key?: string }>;\n CommonPrefixes?: Array<{ Prefix?: string }>;\n IsTruncated?: boolean;\n NextContinuationToken?: string;\n };\n for (const c of res.Contents ?? []) {\n if (c.Key && c.Key !== prefix) files.push(c.Key.slice(prefix.length));\n }\n for (const p of res.CommonPrefixes ?? []) {\n if (p.Prefix)\n dirs.push(p.Prefix.slice(prefix.length).replace(/\\/$/, ''));\n }\n token = res.IsTruncated ? res.NextContinuationToken : undefined;\n } while (token);\n\n if (options?.withFileTypes) {\n return [\n ...dirs.map(\n (name): Dirent => ({\n name,\n isFile: () => false,\n isDirectory: () => true\n })\n ),\n ...files.map(\n (name): Dirent => ({\n name,\n isFile: () => true,\n isDirectory: () => false\n })\n )\n ];\n }\n return [...dirs, ...files];\n }\n\n async mkdir(_path: string, _options?: MkdirOptions): Promise<void> {\n // S3 has no directories; mkdir is a no-op (keys imply their prefixes).\n }\n\n async rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean }\n ): Promise<void> {\n const key = normalizeKey(path);\n if (options?.recursive) {\n let token: string | undefined;\n do {\n const res = (await this.client.send(\n new ListObjectsV2Command({\n Bucket: this.bucket,\n Prefix: `${key}/`,\n ContinuationToken: token\n })\n )) as {\n Contents?: Array<{ Key?: string }>;\n IsTruncated?: boolean;\n NextContinuationToken?: string;\n };\n for (const c of res.Contents ?? []) {\n if (c.Key)\n await this.client.send(\n new DeleteObjectCommand({ Bucket: this.bucket, Key: c.Key })\n );\n }\n token = res.IsTruncated ? res.NextContinuationToken : undefined;\n } while (token);\n // node:fs.rm(path,{recursive:true}) removes the path itself too; an S3\n // delete of a missing key is a no-op, so this is safe whether or not\n // `key` exists as an object in its own right.\n await this.client.send(\n new DeleteObjectCommand({ Bucket: this.bucket, Key: key })\n );\n return;\n }\n await this.client.send(\n new DeleteObjectCommand({ Bucket: this.bucket, Key: key })\n );\n }\n\n async rename(oldPath: string, newPath: string): Promise<void> {\n const oldKey = normalizeKey(oldPath);\n const bytes = await this.getBytes(oldKey);\n await this.writeFile(newPath, bytes);\n await this.client.send(\n new DeleteObjectCommand({ Bucket: this.bucket, Key: oldKey })\n );\n }\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { type Dirent, type FileHandleStats, type MkdirOptions, type ReaddirOptions, type ReadFileOptions, type WorkspaceFS } from './types.js';
2
+ /**
3
+ * Validate an opaque, front-asserted workspaceId as a relative path prefix.
4
+ * Internal `/` is allowed (namespaces like `u/usr_8842`, `s/<sessionId>`);
5
+ * empty ids, leading `/`, `.`/`..` segments, empty segments, backslashes, and
6
+ * control characters are rejected. Throws `Error & { code: 'EINVAL' }`.
7
+ */
8
+ export declare function sanitizeWorkspaceId(id: string): string;
9
+ export declare class ScopedWorkspaceFS implements WorkspaceFS {
10
+ private readonly inner;
11
+ private readonly prefix;
12
+ constructor(inner: WorkspaceFS, workspaceId: string);
13
+ private scoped;
14
+ readFile(path: string): Promise<Uint8Array>;
15
+ readFile(path: string, encoding: 'utf8' | 'utf-8'): Promise<string>;
16
+ readFile(path: string, options: ReadFileOptions): Promise<Uint8Array | string>;
17
+ writeFile(path: string, data: Uint8Array | string): Promise<void>;
18
+ stat(path: string): Promise<FileHandleStats>;
19
+ exists(path: string): Promise<boolean>;
20
+ readdir(path: string): Promise<string[]>;
21
+ readdir(path: string, options: {
22
+ withFileTypes: true;
23
+ }): Promise<Dirent[]>;
24
+ readdir(path: string, options?: ReaddirOptions): Promise<string[] | Dirent[]>;
25
+ mkdir(path: string, options?: MkdirOptions): Promise<void>;
26
+ rm(path: string, options?: {
27
+ recursive?: boolean;
28
+ force?: boolean;
29
+ }): Promise<void>;
30
+ rename(oldPath: string, newPath: string): Promise<void>;
31
+ }
32
+ //# sourceMappingURL=scoped.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped.d.ts","sourceRoot":"","sources":["../../src/workspace/scoped.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,eAAe,EAEpB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAatD;AAED,qBAAa,iBAAkB,YAAW,WAAW;IAIjD,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,KAAK,EAAE,WAAW,EACnC,WAAW,EAAE,MAAM;IAKrB,OAAO,CAAC,MAAM;IAKd,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IACnE,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC;IAW/B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI5C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAItC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IACxC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,aAAa,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAC1E,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAW7E,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,EAAE,CACA,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACjD,OAAO,CAAC,IAAI,CAAC;IAIhB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGxD"}
@@ -0,0 +1,76 @@
1
+ // packages/codesign-mcp/src/workspace/scoped.ts
2
+ //
3
+ // ScopedWorkspaceFS decorates a WorkspaceFS, prefixing every path with
4
+ // `workspaces/<workspaceId>/`. The workspaceId is an opaque, front-asserted
5
+ // string (see docs/specs/2026-06-09-codesign-mcp-hosted-onprem-design.md §3.1):
6
+ // the container is blind to whether it names a user, a session, or a shared
7
+ // workspace, and to whether it is durable or ephemeral. The decorator's one
8
+ // job is to sanitise it as a path segment so an opaque id can never escape its
9
+ // prefix (§3.3). RevisionStore stays tenant-agnostic; this is the only place
10
+ // tenancy enters the storage path. Overloads are delegated by branching (no
11
+ // `as any`), mirroring node-fs.ts.
12
+ import { fsError } from './types.js';
13
+ /**
14
+ * Validate an opaque, front-asserted workspaceId as a relative path prefix.
15
+ * Internal `/` is allowed (namespaces like `u/usr_8842`, `s/<sessionId>`);
16
+ * empty ids, leading `/`, `.`/`..` segments, empty segments, backslashes, and
17
+ * control characters are rejected. Throws `Error & { code: 'EINVAL' }`.
18
+ */
19
+ export function sanitizeWorkspaceId(id) {
20
+ if (id.length === 0)
21
+ throw fsError('EINVAL', 'workspaceId must be non-empty');
22
+ if (id.startsWith('/'))
23
+ throw fsError('EINVAL', `workspaceId must not start with '/': ${id}`);
24
+ for (const segment of id.split('/')) {
25
+ if (segment === '' || segment === '.' || segment === '..')
26
+ throw fsError('EINVAL', `workspaceId has an invalid path segment: ${id}`);
27
+ // Reject control characters (0x00-0x1f) and backslashes.
28
+ // eslint-disable-next-line no-control-regex
29
+ if (/[\x00-\x1f\\]/.test(segment))
30
+ throw fsError('EINVAL', `workspaceId has illegal characters: ${id}`);
31
+ }
32
+ return id;
33
+ }
34
+ export class ScopedWorkspaceFS {
35
+ constructor(inner, workspaceId) {
36
+ this.inner = inner;
37
+ this.prefix = `workspaces/${sanitizeWorkspaceId(workspaceId)}`;
38
+ }
39
+ scoped(path) {
40
+ const rel = path.startsWith('/') ? path.slice(1) : path;
41
+ return `${this.prefix}/${rel}`;
42
+ }
43
+ readFile(path, options) {
44
+ const p = this.scoped(path);
45
+ if (options === undefined)
46
+ return this.inner.readFile(p);
47
+ if (typeof options === 'string')
48
+ return this.inner.readFile(p, options);
49
+ return this.inner.readFile(p, options);
50
+ }
51
+ writeFile(path, data) {
52
+ return this.inner.writeFile(this.scoped(path), data);
53
+ }
54
+ stat(path) {
55
+ return this.inner.stat(this.scoped(path));
56
+ }
57
+ exists(path) {
58
+ return this.inner.exists(this.scoped(path));
59
+ }
60
+ readdir(path, options) {
61
+ const p = this.scoped(path);
62
+ if (options?.withFileTypes)
63
+ return this.inner.readdir(p, { withFileTypes: true });
64
+ return this.inner.readdir(p, options);
65
+ }
66
+ mkdir(path, options) {
67
+ return this.inner.mkdir(this.scoped(path), options);
68
+ }
69
+ rm(path, options) {
70
+ return this.inner.rm(this.scoped(path), options);
71
+ }
72
+ rename(oldPath, newPath) {
73
+ return this.inner.rename(this.scoped(oldPath), this.scoped(newPath));
74
+ }
75
+ }
76
+ //# sourceMappingURL=scoped.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped.js","sourceRoot":"","sources":["../../src/workspace/scoped.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/codesign-mcp/src/workspace/scoped.ts\n//\n// ScopedWorkspaceFS decorates a WorkspaceFS, prefixing every path with\n// `workspaces/<workspaceId>/`. The workspaceId is an opaque, front-asserted\n// string (see docs/specs/2026-06-09-codesign-mcp-hosted-onprem-design.md §3.1):\n// the container is blind to whether it names a user, a session, or a shared\n// workspace, and to whether it is durable or ephemeral. The decorator's one\n// job is to sanitise it as a path segment so an opaque id can never escape its\n// prefix (§3.3). RevisionStore stays tenant-agnostic; this is the only place\n// tenancy enters the storage path. Overloads are delegated by branching (no\n// `as any`), mirroring node-fs.ts.\nimport {\n type Dirent,\n type FileHandleStats,\n fsError,\n type MkdirOptions,\n type ReaddirOptions,\n type ReadFileOptions,\n type WorkspaceFS\n} from './types.js';\n\n/**\n * Validate an opaque, front-asserted workspaceId as a relative path prefix.\n * Internal `/` is allowed (namespaces like `u/usr_8842`, `s/<sessionId>`);\n * empty ids, leading `/`, `.`/`..` segments, empty segments, backslashes, and\n * control characters are rejected. Throws `Error & { code: 'EINVAL' }`.\n */\nexport function sanitizeWorkspaceId(id: string): string {\n if (id.length === 0) throw fsError('EINVAL', 'workspaceId must be non-empty');\n if (id.startsWith('/'))\n throw fsError('EINVAL', `workspaceId must not start with '/': ${id}`);\n for (const segment of id.split('/')) {\n if (segment === '' || segment === '.' || segment === '..')\n throw fsError('EINVAL', `workspaceId has an invalid path segment: ${id}`);\n // Reject control characters (0x00-0x1f) and backslashes.\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1f\\\\]/.test(segment))\n throw fsError('EINVAL', `workspaceId has illegal characters: ${id}`);\n }\n return id;\n}\n\nexport class ScopedWorkspaceFS implements WorkspaceFS {\n private readonly prefix: string;\n\n constructor(\n private readonly inner: WorkspaceFS,\n workspaceId: string\n ) {\n this.prefix = `workspaces/${sanitizeWorkspaceId(workspaceId)}`;\n }\n\n private scoped(path: string): string {\n const rel = path.startsWith('/') ? path.slice(1) : path;\n return `${this.prefix}/${rel}`;\n }\n\n readFile(path: string): Promise<Uint8Array>;\n readFile(path: string, encoding: 'utf8' | 'utf-8'): Promise<string>;\n readFile(\n path: string,\n options: ReadFileOptions\n ): Promise<Uint8Array | string>;\n readFile(\n path: string,\n options?: 'utf8' | 'utf-8' | ReadFileOptions\n ): Promise<Uint8Array | string> {\n const p = this.scoped(path);\n if (options === undefined) return this.inner.readFile(p);\n if (typeof options === 'string') return this.inner.readFile(p, options);\n return this.inner.readFile(p, options);\n }\n\n writeFile(path: string, data: Uint8Array | string): Promise<void> {\n return this.inner.writeFile(this.scoped(path), data);\n }\n\n stat(path: string): Promise<FileHandleStats> {\n return this.inner.stat(this.scoped(path));\n }\n\n exists(path: string): Promise<boolean> {\n return this.inner.exists(this.scoped(path));\n }\n\n readdir(path: string): Promise<string[]>;\n readdir(path: string, options: { withFileTypes: true }): Promise<Dirent[]>;\n readdir(path: string, options?: ReaddirOptions): Promise<string[] | Dirent[]>;\n readdir(\n path: string,\n options?: ReaddirOptions\n ): Promise<string[] | Dirent[]> {\n const p = this.scoped(path);\n if (options?.withFileTypes)\n return this.inner.readdir(p, { withFileTypes: true });\n return this.inner.readdir(p, options);\n }\n\n mkdir(path: string, options?: MkdirOptions): Promise<void> {\n return this.inner.mkdir(this.scoped(path), options);\n }\n\n rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean }\n ): Promise<void> {\n return this.inner.rm(this.scoped(path), options);\n }\n\n rename(oldPath: string, newPath: string): Promise<void> {\n return this.inner.rename(this.scoped(oldPath), this.scoped(newPath));\n }\n}\n"]}
@@ -0,0 +1,75 @@
1
+ export interface FileHandleStats {
2
+ /** Size in bytes. */
3
+ size: number;
4
+ /** UNIX-epoch ms. */
5
+ mtimeMs: number;
6
+ isFile(): boolean;
7
+ isDirectory(): boolean;
8
+ }
9
+ export interface ReadFileOptions {
10
+ encoding?: 'utf8' | 'utf-8' | null;
11
+ }
12
+ export interface MkdirOptions {
13
+ recursive?: boolean;
14
+ }
15
+ export interface ReaddirOptions {
16
+ withFileTypes?: boolean;
17
+ }
18
+ export interface Dirent {
19
+ name: string;
20
+ isFile(): boolean;
21
+ isDirectory(): boolean;
22
+ }
23
+ /**
24
+ * The workspace filesystem. Paths are forward-slash POSIX style, absolute
25
+ * within the workspace root (e.g. `objects/3a/2b1c.scene`, leading `/`
26
+ * optional; impls normalise). The workspace owns its root; consumers never
27
+ * see absolute disk paths.
28
+ *
29
+ * Error contract: throws `Error & { code: string }` with node-standard codes —
30
+ * `ENOENT`, `EEXIST`, `ENOTDIR`, `ENOSYS`.
31
+ */
32
+ export interface WorkspaceFS {
33
+ /** Read a file as bytes. Throws ENOENT if missing. */
34
+ readFile(path: string): Promise<Uint8Array>;
35
+ /** Read a file as UTF-8 string. Convenience over `readFile` + decode. */
36
+ readFile(path: string, encoding: 'utf8' | 'utf-8'): Promise<string>;
37
+ readFile(path: string, options: ReadFileOptions): Promise<Uint8Array | string>;
38
+ /**
39
+ * Write a file. Creates parent dirs implicitly (matches our usage; node
40
+ * does not).
41
+ *
42
+ * CONTRACT — durable-on-return: this MUST NOT resolve until the bytes are
43
+ * durably readable by other instances sharing this backend. The revision
44
+ * store's cross-instance correctness depends on it (see the design doc
45
+ * §4.3/§4.5): a by-id read on another container, issued only after this
46
+ * write's caller responded, must never 404. A direct awaited R2/S3 PUT
47
+ * satisfies this; a write-back-caching FUSE mount does NOT — do not back a
48
+ * WorkspaceFS with one.
49
+ */
50
+ writeFile(path: string, data: Uint8Array | string): Promise<void>;
51
+ /** Stat a file/dir. Throws ENOENT if missing. */
52
+ stat(path: string): Promise<FileHandleStats>;
53
+ /** True iff `path` exists. Convenience — node has no `exists` (deprecated). */
54
+ exists(path: string): Promise<boolean>;
55
+ /** Read a directory listing. */
56
+ readdir(path: string): Promise<string[]>;
57
+ readdir(path: string, options: {
58
+ withFileTypes: true;
59
+ }): Promise<Dirent[]>;
60
+ readdir(path: string, options?: ReaddirOptions): Promise<string[] | Dirent[]>;
61
+ /** Create a directory. `recursive: true` matches `mkdir -p`. */
62
+ mkdir(path: string, options?: MkdirOptions): Promise<void>;
63
+ /** Remove a file or directory. `recursive` removes subtrees. */
64
+ rm(path: string, options?: {
65
+ recursive?: boolean;
66
+ force?: boolean;
67
+ }): Promise<void>;
68
+ /** Rename or move a path. Atomic where supported. */
69
+ rename(oldPath: string, newPath: string): Promise<void>;
70
+ }
71
+ /** Construct a node-shaped FS error. */
72
+ export declare function fsError(code: string, message: string): Error & {
73
+ code: string;
74
+ };
75
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workspace/types.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,IAAI,OAAO,CAAC;IAClB,WAAW,IAAI,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,IAAI,OAAO,CAAC;IAClB,WAAW,IAAI,OAAO,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IAEhC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE,iDAAiD;IACjD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE7C,+EAA+E;IAC/E,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvC,gCAAgC;IAChC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,aAAa,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAE9E,gEAAgE;IAChE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3D,gEAAgE;IAChE,EAAE,CACA,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACjD,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,qDAAqD;IACrD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,wCAAwC;AACxC,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAI1B"}
@@ -0,0 +1,18 @@
1
+ // packages/codesign-mcp/src/workspace/types.ts
2
+ //
3
+ // `WorkspaceFS` mirrors `node:fs/promises` exactly for the subset codesign-mcp
4
+ // needs. This is a hard repo rule (`.claude/rules/platform-matches-node.md`):
5
+ // method names, parameter shapes, return shapes, and error semantics match
6
+ // node so a `NodeWorkspaceFS` is essentially a passthrough, and any future
7
+ // backend (S3-backed, in-process, sandbox VFS) is a drop-in.
8
+ //
9
+ // Subset, not superset: we only expose methods we use. When we need a
10
+ // convenience that doesn't exist on `node:fs/promises`, we name it differently
11
+ // (e.g. `readFileBytes` — not added yet, kept here as the precedent).
12
+ /** Construct a node-shaped FS error. */
13
+ export function fsError(code, message) {
14
+ const err = new Error(message);
15
+ err.code = code;
16
+ return err;
17
+ }
18
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/workspace/types.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,6DAA6D;AAC7D,EAAE;AACF,sEAAsE;AACtE,+EAA+E;AAC/E,sEAAsE;AAsFtE,wCAAwC;AACxC,MAAM,UAAU,OAAO,CACrB,IAAY,EACZ,OAAe;IAEf,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAA6B,CAAC;IAC3D,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAChB,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["// packages/codesign-mcp/src/workspace/types.ts\n//\n// `WorkspaceFS` mirrors `node:fs/promises` exactly for the subset codesign-mcp\n// needs. This is a hard repo rule (`.claude/rules/platform-matches-node.md`):\n// method names, parameter shapes, return shapes, and error semantics match\n// node so a `NodeWorkspaceFS` is essentially a passthrough, and any future\n// backend (S3-backed, in-process, sandbox VFS) is a drop-in.\n//\n// Subset, not superset: we only expose methods we use. When we need a\n// convenience that doesn't exist on `node:fs/promises`, we name it differently\n// (e.g. `readFileBytes` — not added yet, kept here as the precedent).\n\nexport interface FileHandleStats {\n /** Size in bytes. */\n size: number;\n /** UNIX-epoch ms. */\n mtimeMs: number;\n isFile(): boolean;\n isDirectory(): boolean;\n}\n\nexport interface ReadFileOptions {\n encoding?: 'utf8' | 'utf-8' | null;\n}\n\nexport interface MkdirOptions {\n recursive?: boolean;\n}\n\nexport interface ReaddirOptions {\n withFileTypes?: boolean;\n}\n\nexport interface Dirent {\n name: string;\n isFile(): boolean;\n isDirectory(): boolean;\n}\n\n/**\n * The workspace filesystem. Paths are forward-slash POSIX style, absolute\n * within the workspace root (e.g. `objects/3a/2b1c.scene`, leading `/`\n * optional; impls normalise). The workspace owns its root; consumers never\n * see absolute disk paths.\n *\n * Error contract: throws `Error & { code: string }` with node-standard codes —\n * `ENOENT`, `EEXIST`, `ENOTDIR`, `ENOSYS`.\n */\nexport interface WorkspaceFS {\n /** Read a file as bytes. Throws ENOENT if missing. */\n readFile(path: string): Promise<Uint8Array>;\n /** Read a file as UTF-8 string. Convenience over `readFile` + decode. */\n readFile(path: string, encoding: 'utf8' | 'utf-8'): Promise<string>;\n readFile(\n path: string,\n options: ReadFileOptions\n ): Promise<Uint8Array | string>;\n\n /**\n * Write a file. Creates parent dirs implicitly (matches our usage; node\n * does not).\n *\n * CONTRACT — durable-on-return: this MUST NOT resolve until the bytes are\n * durably readable by other instances sharing this backend. The revision\n * store's cross-instance correctness depends on it (see the design doc\n * §4.3/§4.5): a by-id read on another container, issued only after this\n * write's caller responded, must never 404. A direct awaited R2/S3 PUT\n * satisfies this; a write-back-caching FUSE mount does NOT — do not back a\n * WorkspaceFS with one.\n */\n writeFile(path: string, data: Uint8Array | string): Promise<void>;\n\n /** Stat a file/dir. Throws ENOENT if missing. */\n stat(path: string): Promise<FileHandleStats>;\n\n /** True iff `path` exists. Convenience — node has no `exists` (deprecated). */\n exists(path: string): Promise<boolean>;\n\n /** Read a directory listing. */\n readdir(path: string): Promise<string[]>;\n readdir(path: string, options: { withFileTypes: true }): Promise<Dirent[]>;\n readdir(path: string, options?: ReaddirOptions): Promise<string[] | Dirent[]>;\n\n /** Create a directory. `recursive: true` matches `mkdir -p`. */\n mkdir(path: string, options?: MkdirOptions): Promise<void>;\n\n /** Remove a file or directory. `recursive` removes subtrees. */\n rm(\n path: string,\n options?: { recursive?: boolean; force?: boolean }\n ): Promise<void>;\n\n /** Rename or move a path. Atomic where supported. */\n rename(oldPath: string, newPath: string): Promise<void>;\n}\n\n/** Construct a node-shaped FS error. */\nexport function fsError(\n code: string,\n message: string\n): Error & { code: string } {\n const err = new Error(message) as Error & { code: string };\n err.code = code;\n return err;\n}\n"]}