@vgai/editor 0.2.0 → 0.4.0-canary.20260715.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 (430) hide show
  1. package/README.md +24 -0
  2. package/dist/assets/axe-C7YBtOuM.js +30 -0
  3. package/dist/assets/browserAll-DDtGGE48.js +1 -0
  4. package/dist/assets/create-runtime-DbTlBlKG.js +1 -0
  5. package/dist/assets/{game-BI111o5f.js → game-BE0r7DMI.js} +3 -3
  6. package/dist/assets/game-BdTHR2_X.js +1 -0
  7. package/dist/assets/{game-pt_1lQLv.js → game-C3iQGSqo.js} +1 -1
  8. package/dist/assets/game-CcHfYxjP.js +1 -0
  9. package/dist/assets/game-Cqzj_lpD.js +1 -0
  10. package/dist/assets/game-DSZdeCHu.js +1 -0
  11. package/dist/assets/game-Dch9sAPc.js +1 -0
  12. package/dist/assets/{game-xsOho_wg.js → game-SAFn90pA.js} +3 -3
  13. package/dist/assets/game-loop-DMIgSMV-.js +1 -0
  14. package/dist/assets/{game-source-CvidN7AB.js → game-source-Dk83w26t.js} +1 -1
  15. package/dist/assets/{index-Bp5cecD6.js → index-4idIsHHJ.js} +2 -2
  16. package/dist/assets/{index-DL7RcQ0n.js → index-C-LhOTBN.js} +1 -1
  17. package/dist/assets/{index-Cs8xwv3e.js → index-CDkxceqE.js} +1 -1
  18. package/dist/assets/index-CQEfi217.js +15412 -0
  19. package/dist/assets/index-Dvi-V0NE.css +1 -0
  20. package/dist/assets/ingest-siblings-s0P5I1Ub.js +1 -0
  21. package/dist/assets/mount-manifest-DXMOlF79.js +1 -0
  22. package/dist/assets/react-18-C9eHn8x1.js +1 -0
  23. package/dist/assets/webworkerAll-Fn0e-ouF.js +1 -0
  24. package/dist/assets/world-documents-GM0a9Kv7.js +1 -0
  25. package/dist/index.html +15 -13
  26. package/dist/ingest/racing-game/vgai.game.json +5 -4
  27. package/dist/ingest/simcity/vgai.game.json +5 -4
  28. package/dist/ingest/tanks/vgai.game.json +5 -4
  29. package/dist/project-scripts.bundle.js +3917 -0
  30. package/dist/scenes/untitled.vscn.json +2 -0
  31. package/dist-server/packaged.mjs +7697 -3435
  32. package/package.json +31 -4
  33. package/scripts/probe-reporter.ts +349 -0
  34. package/scripts/run-probe.ts +2260 -0
  35. package/server/asset-catalog-audit.ts +268 -0
  36. package/server/asset-catalog-v2.ts +146 -0
  37. package/server/asset-library-routes.ts +276 -58
  38. package/server/canonical-path.ts +1 -1
  39. package/server/dev.ts +148 -44
  40. package/server/editor-server.ts +888 -61
  41. package/server/editor-sse.ts +115 -4
  42. package/server/harness-chat-service.ts +796 -0
  43. package/server/local-asset-catalog.ts +157 -22
  44. package/server/packaged.ts +51 -21
  45. package/server/process-shutdown.ts +136 -0
  46. package/server/prod.ts +9 -6
  47. package/server/project-hmr-files.ts +41 -0
  48. package/server/project-operations.ts +343 -0
  49. package/server/project-optimize-deps-entries.ts +4 -4
  50. package/server/project-output-writer.ts +156 -0
  51. package/server/project-validation.ts +140 -0
  52. package/server/project-view.ts +8 -50
  53. package/server/server-utils.ts +75 -10
  54. package/server/session-registry.ts +12 -0
  55. package/src/EditorContext.tsx +107 -3
  56. package/src/action-registry.ts +115 -17
  57. package/src/adapter-resolver.ts +213 -478
  58. package/src/asset-events.ts +64 -1
  59. package/src/asset-preview.ts +906 -0
  60. package/src/asset-selection.ts +121 -0
  61. package/src/asset-workflow/asset-capabilities.ts +259 -0
  62. package/src/asset-workflow/asset-editor-errors.ts +46 -0
  63. package/src/asset-workflow/asset-import-pipeline.ts +176 -0
  64. package/src/asset-workflow/asset-library-query.ts +107 -0
  65. package/src/asset-workflow/asset-types.ts +192 -0
  66. package/src/asset-workflow/asset-workflow-quality.ts +65 -0
  67. package/src/asset-workflow/import-contract.ts +113 -0
  68. package/src/asset-workflow/model-conversion.ts +126 -0
  69. package/src/asset-workflow/model-inspection.ts +185 -0
  70. package/src/asset-workflow/project-asset-commands.ts +23 -0
  71. package/src/asset-workflow/project-asset-health.ts +153 -0
  72. package/src/asset-workflow/project-asset-operations.ts +119 -0
  73. package/src/asset-workflow/thumbnail-system.ts +172 -0
  74. package/src/authoring/active-systems.ts +15 -0
  75. package/src/authoring/boundary-authoring-adapter.ts +16 -5
  76. package/src/authoring/composite-authoring-adapter.ts +305 -124
  77. package/src/authoring/design-time-layers.ts +300 -117
  78. package/src/authoring/edit-mode-authoring.ts +278 -293
  79. package/src/authoring/embed-only-adapter.ts +4 -2
  80. package/src/authoring/first-party-hierarchy-menu.ts +7 -2
  81. package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
  82. package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
  83. package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
  84. package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
  85. package/src/authoring/first-party-inspector/register.tsx +13 -2
  86. package/src/authoring/ingest-authoring-adapter.ts +142 -45
  87. package/src/authoring/mount-failure-report.ts +5 -5
  88. package/src/authoring/provenance.ts +41 -0
  89. package/src/authoring/react-dom-authoring-adapter.ts +92 -92
  90. package/src/authoring/react-inspector-section.tsx +489 -51
  91. package/src/authoring/react-world-authoring-adapter.ts +541 -306
  92. package/src/authoring/story-overlay.ts +1 -1
  93. package/src/authoring/story-types.ts +11 -0
  94. package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
  95. package/src/authoring/viewport-tool-context.ts +78 -0
  96. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  97. package/src/authoring/world-hidden-viewport.ts +186 -0
  98. package/src/authoring/world-pan-state.ts +33 -17
  99. package/src/authoring/world-session-state.ts +1 -1
  100. package/src/authoring/world2d-authoring-adapter.ts +109 -52
  101. package/src/availability-tick.ts +56 -0
  102. package/src/browser-play-entry.ts +5 -5
  103. package/src/browser-project-scripts.ts +1 -0
  104. package/src/build-identity.ts +15 -0
  105. package/src/command-listener.ts +893 -19
  106. package/src/components/AlignToolbar.tsx +74 -63
  107. package/src/components/AppRoot.tsx +193 -26
  108. package/src/components/ApplicationMenus.tsx +272 -0
  109. package/src/components/AssetBrowser.tsx +1450 -293
  110. package/src/components/AssetEditorShell.tsx +141 -0
  111. package/src/components/AssetImportDetails.tsx +218 -0
  112. package/src/components/AssetLibraryPanel.tsx +14 -0
  113. package/src/components/CameraInfo.tsx +11 -20
  114. package/src/components/CenterDocuments.tsx +585 -0
  115. package/src/components/CommandPalette.tsx +75 -30
  116. package/src/components/ConsolePanel.css +55 -0
  117. package/src/components/ConsolePanel.tsx +57 -112
  118. package/src/components/DebugConsolePanel.tsx +461 -0
  119. package/src/components/DebuggerPanel.tsx +165 -0
  120. package/src/components/DefaultEditorLayout.tsx +167 -231
  121. package/src/components/GameHierarchy.tsx +873 -290
  122. package/src/components/GamePerformanceOverlay.tsx +46 -0
  123. package/src/components/HarnessChatPanel.tsx +2352 -0
  124. package/src/components/HistoryPanel.tsx +226 -0
  125. package/src/components/Inspector.tsx +153 -99
  126. package/src/components/InspectorToolSection.tsx +6 -4
  127. package/src/components/MountFailureBanner.tsx +31 -48
  128. package/src/components/NetworkSection.tsx +25 -14
  129. package/src/components/OnlineAssetBrowser.tsx +794 -343
  130. package/src/components/OverlayReportBanner.tsx +38 -64
  131. package/src/components/PerformancePanel.tsx +206 -0
  132. package/src/components/PlayBar.tsx +93 -263
  133. package/src/components/PrefabSaveDialog.tsx +55 -127
  134. package/src/components/ProjectHeader.css +60 -0
  135. package/src/components/ProjectHeader.tsx +170 -105
  136. package/src/components/ProjectScreen.tsx +246 -184
  137. package/src/components/ReactCanvasControls.tsx +185 -0
  138. package/src/components/ResolutionPicker.tsx +85 -0
  139. package/src/components/RootActivateDialog.tsx +39 -68
  140. package/src/components/SaveDialog.tsx +55 -127
  141. package/src/components/SaveStatus.tsx +11 -29
  142. package/src/components/StartupLoadingScreen.tsx +96 -0
  143. package/src/components/StateWatchPanel.tsx +302 -0
  144. package/src/components/StatsOverlay.tsx +12 -5
  145. package/src/components/StatusBar.tsx +64 -0
  146. package/src/components/ThemeManagerDialog.css +89 -0
  147. package/src/components/ThemeManagerDialog.tsx +371 -0
  148. package/src/components/ToolHost.tsx +26 -15
  149. package/src/components/Toolbar.tsx +117 -214
  150. package/src/components/VgaiVoxelLogo.tsx +89 -0
  151. package/src/components/ViewportOverlay.tsx +97 -172
  152. package/src/components/ViewportPanel.tsx +130 -31
  153. package/src/components/WorkspaceDock.tsx +891 -0
  154. package/src/components/WorldSelectionOverlay.tsx +51 -63
  155. package/src/components/WorldTextEditor.tsx +9 -5
  156. package/src/components/asset-documents.tsx +390 -0
  157. package/src/components/asset-editor-persistence.ts +44 -0
  158. package/src/components/asset-selection-section.tsx +338 -0
  159. package/src/components/asset-viewers/AudioViewer.tsx +73 -21
  160. package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
  161. package/src/components/asset-viewers/ImageViewer.tsx +43 -11
  162. package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
  163. package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
  164. package/src/components/asset-viewers/ModelViewer.tsx +805 -121
  165. package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
  166. package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
  167. package/src/components/asset-workflow.css +506 -0
  168. package/src/components/build-documents.tsx +696 -0
  169. package/src/components/core-utilities.tsx +75 -0
  170. package/src/components/data-documents.tsx +364 -0
  171. package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
  172. package/src/components/debugger-panel-state.ts +57 -0
  173. package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
  174. package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
  175. package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
  176. package/src/components/inspector-widgets/FontPicker.tsx +13 -21
  177. package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
  178. package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
  179. package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
  180. package/src/components/inspector-widgets/shared.tsx +90 -49
  181. package/src/components/inspectors/AnimationSection.tsx +39 -40
  182. package/src/components/inspectors/AudioSection.tsx +28 -39
  183. package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
  184. package/src/components/inspectors/CameraSection.tsx +14 -23
  185. package/src/components/inspectors/ComponentsSection.tsx +39 -43
  186. package/src/components/inspectors/JointsSection.tsx +34 -43
  187. package/src/components/inspectors/LightSection.tsx +90 -35
  188. package/src/components/inspectors/MaterialSection.tsx +137 -174
  189. package/src/components/inspectors/MeshSection.tsx +9 -17
  190. package/src/components/inspectors/NavigationSection.tsx +8 -15
  191. package/src/components/inspectors/ParticleSection.tsx +91 -76
  192. package/src/components/inspectors/PhysicsSection.tsx +42 -46
  193. package/src/components/inspectors/PostProcessingSection.tsx +28 -36
  194. package/src/components/inspectors/RenderingSection.tsx +12 -20
  195. package/src/components/inspectors/ShadowSection.tsx +7 -8
  196. package/src/components/inspectors/SplineSection.tsx +31 -42
  197. package/src/components/inspectors/TransformSection.tsx +14 -22
  198. package/src/components/patterns/Dialog.tsx +95 -0
  199. package/src/components/patterns/Fields.tsx +44 -0
  200. package/src/components/patterns/List.tsx +25 -0
  201. package/src/components/patterns/StateSurface.tsx +40 -0
  202. package/src/components/patterns/Surfaces.tsx +115 -0
  203. package/src/components/patterns/Tabs.tsx +80 -0
  204. package/src/components/patterns/Toolbar.tsx +51 -0
  205. package/src/components/patterns/Tree.tsx +72 -0
  206. package/src/components/primitives/Button.tsx +46 -0
  207. package/src/components/primitives/ColorInput.tsx +11 -47
  208. package/src/components/primitives/EditorIcon.tsx +99 -0
  209. package/src/components/primitives/FormControls.tsx +71 -0
  210. package/src/components/primitives/JsonInput.tsx +15 -2
  211. package/src/components/primitives/Layout.tsx +100 -0
  212. package/src/components/primitives/Menu.tsx +105 -0
  213. package/src/components/primitives/NumberInput.tsx +8 -35
  214. package/src/components/primitives/Panel.tsx +49 -44
  215. package/src/components/primitives/SectionHeader.tsx +10 -28
  216. package/src/components/primitives/Text.tsx +46 -0
  217. package/src/components/primitives/Tooltip.tsx +20 -12
  218. package/src/components/primitives/Vec3Input.tsx +3 -0
  219. package/src/components/primitives/banner-tones.ts +33 -0
  220. package/src/components/primitives/editor-icons.ts +102 -0
  221. package/src/components/primitives/panel-header-styles.ts +30 -0
  222. package/src/components/project-operation-documents.tsx +226 -0
  223. package/src/components/status-contributions.tsx +175 -0
  224. package/src/components/story-documents-register.ts +15 -0
  225. package/src/components/story-documents.tsx +1185 -0
  226. package/src/components/tool-documents.tsx +110 -0
  227. package/src/components/workspace-dock.css +293 -0
  228. package/src/components/workspace-history.ts +33 -0
  229. package/src/components/world-documents.tsx +145 -0
  230. package/src/components/xstate-documents.tsx +209 -0
  231. package/src/composite-screenshot.ts +248 -0
  232. package/src/design-system/index.ts +70 -0
  233. package/src/design-system-stories/Foundation.stories.tsx +183 -0
  234. package/src/design-system-stories/Patterns.stories.tsx +251 -0
  235. package/src/design-system-stories/Workspace.stories.tsx +538 -0
  236. package/src/doctor/report.ts +57 -13
  237. package/src/editor-api.ts +295 -31
  238. package/src/editor-compatibility.ts +200 -0
  239. package/src/editor-console.ts +35 -17
  240. package/src/editor-hotkeys.ts +85 -33
  241. package/src/editor-store.ts +538 -233
  242. package/src/editor-viewport.ts +160 -34
  243. package/src/entity-factory.ts +14 -3
  244. package/src/gizmo-registry.ts +21 -5
  245. package/src/harness-chat-editor-context.ts +37 -0
  246. package/src/harness-chat-indicator.ts +68 -0
  247. package/src/harness-chat-layout.ts +53 -0
  248. package/src/harness-chat-lifecycle.ts +170 -0
  249. package/src/harness-chat-reconnect.ts +85 -0
  250. package/src/harness-chat-types.ts +409 -0
  251. package/src/hierarchy-drop.ts +50 -0
  252. package/src/hierarchy-expansion-state.ts +100 -0
  253. package/src/hierarchy-menu-registry.ts +1 -1
  254. package/src/hierarchy-projection.ts +76 -0
  255. package/src/history/editor-session.ts +21 -0
  256. package/src/history/history-commands.ts +147 -0
  257. package/src/history/history-service.ts +904 -0
  258. package/src/history/json-history-resource.ts +165 -0
  259. package/src/history/persistence-coordinator.ts +35 -0
  260. package/src/history/project-file-history.ts +266 -0
  261. package/src/history/project-root-history-backends.ts +53 -0
  262. package/src/history/resource-registry.ts +209 -0
  263. package/src/history/snapshot-store.ts +108 -0
  264. package/src/history/source-history-backend.ts +374 -0
  265. package/src/history/types.ts +100 -0
  266. package/src/hmr-registration-group.ts +67 -0
  267. package/src/hmr-stable-react-context.ts +23 -0
  268. package/src/hosted-example.ts +12 -2
  269. package/src/hotkeys.ts +89 -18
  270. package/src/ingest/discovery-react.ts +9 -10
  271. package/src/ingest/discovery.ts +4 -4
  272. package/src/ingest/discovery2d.ts +5 -5
  273. package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
  274. package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
  275. package/src/ingest/games/games-fps/vgai.game.json +3 -3
  276. package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
  277. package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
  278. package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
  279. package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
  280. package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
  281. package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
  282. package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
  283. package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
  284. package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
  285. package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
  286. package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
  287. package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
  288. package/src/ingest/types.ts +1 -1
  289. package/src/ingest-mode.ts +47 -52
  290. package/src/ingest-siblings.ts +23 -33
  291. package/src/initial-scene.ts +1 -2
  292. package/src/main.tsx +16 -8
  293. package/src/manifest-project.ts +10 -12
  294. package/src/model-thumbnail.ts +261 -26
  295. package/src/module-mode.ts +44 -50
  296. package/src/play-log-events.ts +26 -0
  297. package/src/play-mode.ts +495 -401
  298. package/src/play-scene-adoption.ts +23 -0
  299. package/src/playground/main.ts +68 -24
  300. package/src/playwright-shim.ts +473 -0
  301. package/src/project-manager.ts +90 -10
  302. package/src/project-operations.ts +112 -0
  303. package/src/project-story-discovery.ts +25 -0
  304. package/src/project-tool-discovery.ts +43 -0
  305. package/src/scene-serializer.ts +0 -6
  306. package/src/scene-sync.ts +7 -2
  307. package/src/script-loader.ts +3 -3
  308. package/src/skeleton-helper.ts +57 -0
  309. package/src/storage/seed.ts +68 -8
  310. package/src/stories/StoryPreviewMount.tsx +265 -0
  311. package/src/stories/action-stories.fixture.tsx +44 -0
  312. package/src/stories/button-stories.fixture.tsx +50 -0
  313. package/src/stories/compose-project-stories.ts +182 -0
  314. package/src/stories/loader-stories.fixture.tsx +53 -0
  315. package/src/stories/story-discovery.ts +130 -0
  316. package/src/stories/story-registry.ts +146 -0
  317. package/src/theme-css.ts +1049 -0
  318. package/src/theme-library.ts +238 -0
  319. package/src/theme-preference.ts +130 -0
  320. package/src/theme.ts +527 -0
  321. package/src/tool-loader.ts +80 -24
  322. package/src/ui-source/inspect.ts +27 -4
  323. package/src/ui-source/source-write-backend.ts +83 -22
  324. package/src/widgets/index.ts +9 -18
  325. package/src/workspace-aux-commands.ts +11 -0
  326. package/src/workspace-dock-controller.ts +64 -0
  327. package/src/workspace-document-ids.ts +5 -0
  328. package/src/workspace-document-registry.ts +367 -0
  329. package/src/workspace-state-persistence.ts +455 -0
  330. package/src/workspace-status-registry.ts +110 -0
  331. package/src/workspace-utility-commands.ts +49 -0
  332. package/src/workspace-utility-registry.ts +161 -0
  333. package/src/world-document-routing.ts +16 -0
  334. package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
  335. package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
  336. package/src/xstate-inspect/use-live-actor-state.ts +39 -0
  337. package/src/xstate-inspect/xstate-graph.ts +265 -0
  338. package/src/xstate-inspect/xstate-layout.ts +76 -0
  339. package/src/z-index.ts +26 -0
  340. package/template/.claude/skills/editor/SKILL.md +129 -90
  341. package/template/AGENTS.md +1110 -0
  342. package/template/CLAUDE.md +1 -512
  343. package/template/IDIOMS.md +50 -0
  344. package/template/check-idioms.ts +706 -0
  345. package/template/manifest-entry-modules-plugin.ts +53 -0
  346. package/template/package.json +13 -4
  347. package/template/public/scenes/default.scn2d.json +6 -0
  348. package/template/public/scenes/default.vscn.json +7 -1
  349. package/template/public/scenes/untitled.vscn.json +10 -0
  350. package/template/scripts/playtest.ts +40 -0
  351. package/template/server/loopback.ts +75 -0
  352. package/template/server/rooms/arena-room.ts +69 -1
  353. package/template/server/rooms/game-room.ts +68 -1
  354. package/template/src/data/README.md +9 -4
  355. package/template/src/data/data-ref.ts +35 -0
  356. package/template/src/data/tuning.schema.ts +1 -1
  357. package/template/src/main.ts +41 -62
  358. package/template/src/manifest-entry-modules.d.ts +3 -0
  359. package/template/src/operations/README.md +88 -0
  360. package/template/src/runtime/pixi-adapter.ts +24 -0
  361. package/template/src/scripts/components/data-spinner.ts +43 -2
  362. package/template/src/scripts/components/spin-lap-math.ts +27 -0
  363. package/template/src/tools/README.md +5 -3
  364. package/template/src/tools/example.tool.tsx +13 -7
  365. package/template/src/ui/Button.stories.tsx +66 -0
  366. package/template/src/ui/RebindPanel.tsx +2 -6
  367. package/template/src/ui/game.tsx +17 -0
  368. package/template/tests/acceptance/example.spec.ts +64 -0
  369. package/template/tests/logic/example.test.ts +31 -0
  370. package/template/tests/logic/room.test.ts +100 -0
  371. package/template/tests/tsconfig.json +30 -0
  372. package/template/validate-manifest.ts +5 -5
  373. package/template/validate-scenes.ts +50 -18
  374. package/template/vgai.game.json +20 -13
  375. package/template/vite.config.ts +77 -16
  376. package/vite-plugin-ui-oid.ts +261 -17
  377. package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
  378. package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
  379. package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
  380. package/dist/assets/browserAll-CEkWYlFk.js +0 -1
  381. package/dist/assets/create-runtime-DYIWr3va.js +0 -1
  382. package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
  383. package/dist/assets/game-8SDZPPgH.js +0 -1
  384. package/dist/assets/game-CevorxyV.js +0 -1
  385. package/dist/assets/game-Di7XlywD.js +0 -1
  386. package/dist/assets/game-DjnCaw8R.js +0 -1
  387. package/dist/assets/game-Q9A0aXSV.js +0 -1
  388. package/dist/assets/index-CPVV6pjw.js +0 -1
  389. package/dist/assets/index-CpOnYyeD.js +0 -213
  390. package/dist/assets/index-Dr8H_6Rl.js +0 -1
  391. package/dist/assets/index-_bCaipUk.js +0 -13650
  392. package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
  393. package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
  394. package/dist/assets/scene-query-BivAHhJu.js +0 -1
  395. package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
  396. package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
  397. package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
  398. package/src/authoring/scene-ui-layer.ts +0 -485
  399. package/src/authoring/ui-authoring-adapter.ts +0 -325
  400. package/src/authoring/ui-hierarchy-menu.ts +0 -40
  401. package/src/authoring/ui-inspector-sections.tsx +0 -156
  402. package/src/authoring/undo-timeline.ts +0 -145
  403. package/src/components/BottomPanel.tsx +0 -326
  404. package/src/components/BuildPanel.tsx +0 -455
  405. package/src/components/FolderTree.tsx +0 -179
  406. package/src/components/RightPanel.tsx +0 -166
  407. package/src/components/WorldContextMenu.tsx +0 -257
  408. package/src/components/asset-viewers/AssetViewer.tsx +0 -38
  409. package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
  410. package/src/scene-ui-mode/active-scene-ui.ts +0 -58
  411. package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
  412. package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
  413. package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
  414. package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
  415. package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
  416. package/src/ui-editor/inspector.tsx +0 -563
  417. package/src/ui-editor/node-ops.ts +0 -266
  418. package/src/ui-editor/overlay.tsx +0 -380
  419. package/src/ui-editor/palette.tsx +0 -114
  420. package/src/ui-editor/react-store.ts +0 -78
  421. package/src/ui-editor/timeline-panel.tsx +0 -443
  422. package/src/ui-editor/ui-edit-store.ts +0 -552
  423. package/src/ui-editor/ui-prefab.ts +0 -95
  424. package/template/project.json +0 -9
  425. package/template/src/scripts/main.ts +0 -94
  426. package/template/src/ui/DefaultHud.tsx +0 -40
  427. package/template/src/ui/game-state.tsx +0 -37
  428. package/template/src/ui/mount-default-hud.tsx +0 -19
  429. package/template/src/ui/mount-ui.ts +0 -15
  430. package/vite-plugin-react-world-provider.ts +0 -81
package/package.json CHANGED
@@ -2,12 +2,22 @@
2
2
  "name": "@vgai/editor",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "AGPL-3.0-only",
5
- "version": "0.2.0",
5
+ "version": "0.4.0-canary.20260715.0",
6
6
  "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/volter-ai/vgai-engine.git",
10
+ "directory": "packages/editor"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
7
15
  "files": [
8
16
  "dist",
9
17
  "dist-server",
10
18
  "server",
19
+ "scripts/run-probe.ts",
20
+ "scripts/probe-reporter.ts",
11
21
  "src",
12
22
  "vite-plugin-*.ts",
13
23
  "template"
@@ -17,20 +27,37 @@
17
27
  },
18
28
  "scripts": {
19
29
  "build": "cd ../.. && npx vite build --outDir packages/editor/dist --emptyOutDir",
20
- "build:server": "npx esbuild server/packaged.ts --bundle --platform=node --format=esm --outfile=dist-server/packaged.mjs --tsconfig=../../tsconfig.server.json --external:express --external:chokidar --external:vite --external:esbuild --external:typescript",
21
- "prepack": "npm run build && npm run build:server"
30
+ "build:server": "npx esbuild server/packaged.ts --bundle --platform=node --format=esm --outfile=dist-server/packaged.mjs --tsconfig=../../tsconfig.server.json --external:express --external:chokidar --external:vite --external:esbuild --external:typescript --external:@volter-ai-dev/supercode-client --external:@volter-ai-dev/supercode-harness-sdk",
31
+ "prepack": "npm run build && npm run build:server",
32
+ "storybook": "storybook dev -p 6006 --config-dir .storybook",
33
+ "storybook:build": "storybook build --config-dir .storybook",
34
+ "storybook:test:visual": "playwright test -c playwright.storybook.config.ts"
22
35
  },
23
36
  "dependencies": {
37
+ "@fortawesome/fontawesome-svg-core": "^7.2.0",
38
+ "@fortawesome/free-solid-svg-icons": "^7.2.0",
39
+ "@fortawesome/react-fontawesome": "^3.2.0",
24
40
  "@pixi/tilemap": "^5.0.0",
25
- "@vgai/engine": "^0.3.0",
41
+ "@vgai/engine": "0.4.0-canary.20260715.0",
42
+ "axe-core": "^4.12.1",
26
43
  "chokidar": "^5.0.0",
44
+ "dockview-react": "^7.0.2",
27
45
  "esbuild": "^0.25.12",
28
46
  "express": "^5.2.1",
47
+ "react-markdown": "^10.1.0",
48
+ "remark-gfm": "^4.0.1",
29
49
  "typescript": "^5.6.0",
30
50
  "vite": "^6.0.0"
31
51
  },
52
+ "optionalDependencies": {
53
+ "@volter-ai-dev/supercode": "^0.2.1",
54
+ "@volter-ai-dev/supercode-client": "^0.3.0",
55
+ "@volter-ai-dev/supercode-harness-sdk": "^0.2.0"
56
+ },
32
57
  "devDependencies": {
58
+ "@storybook/addon-a11y": "^9.1.20",
33
59
  "@storybook/react": "^9.1.20",
60
+ "@storybook/react-vite": "^9.1.20",
34
61
  "storybook": "^9.1.20"
35
62
  }
36
63
  }
@@ -0,0 +1,349 @@
1
+ /**
2
+ * `vgai probe`'s own Playwright reporter (ACCEPTANCE-DRIVER-BUILD-PLAN.md
3
+ * Task 3.4 steps 4/7, docs/ACCEPTANCE-DRIVER-SPEC.md §2.2) — writes the
4
+ * versioned `last-run.json` envelope every `vgai probe` run produces.
5
+ *
6
+ * This module is loaded by Playwright INSIDE the spawned `npx playwright
7
+ * test` process (referenced by absolute path from the generated config's
8
+ * `reporter` list — see `run-probe.ts`'s `buildProbeConfigSource`). It only
9
+ * ever sees Playwright's own Reporter API (`TestCase`/`TestResult`/
10
+ * `FullResult`) — never a live `Page`/`Browser` handle (those belong to the
11
+ * `game` fixture in `@vgai/probe`, a different module this reporter does not
12
+ * import and must not duplicate).
13
+ *
14
+ * Playwright's `TestError` type (`playwright/types/testReporter.d.ts`) has NO
15
+ * generic `data` field — only `message`/`stack`/`cause`/`location`/`snippet`/
16
+ * `value` survive a thrown Error's properties across the worker boundary.
17
+ * `@vgai/probe`'s `ProbeFailure`/`ProbeError` DO carry a rich `.data` object
18
+ * when caught inside the SAME process (see its own `errors.ts`), but that
19
+ * structure is invisible here — `failure-block.ts`'s `assembleFailureBlock`
20
+ * renders the identical eight-member block to BOTH the assertion `message`
21
+ * and its `data` (Task 3.3's contract: "renders... to the assertion message
22
+ * AND as structured data"), so `result.error.message` (or the first of
23
+ * `result.errors`) already contains the full contract text; this reporter
24
+ * treats it as the source of truth rather than reconstructing a lost object.
25
+ * A best-effort `code` is recovered by checking whether the message begins
26
+ * with one of `@vgai/probe`'s frozen error-code tokens (a match on the
27
+ * FROZEN CODE embedded in the message by that package's own `errors.ts`, not
28
+ * a prose heuristic — see `classifyFailureCode`).
29
+ */
30
+
31
+ import { mkdirSync, writeFileSync } from 'node:fs';
32
+ import { dirname } from 'node:path';
33
+ import type { FullResult, Reporter, TestCase, TestResult } from '@playwright/test/reporter';
34
+
35
+ export const PROBE_REPORT_VERSION = 1 as const;
36
+
37
+ export interface ProbeVerdict {
38
+ title: string;
39
+ file: string;
40
+ line: number;
41
+ status: 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted';
42
+ durationMs: number;
43
+ retry: number;
44
+ }
45
+
46
+ export interface ProbeFailureAttachment {
47
+ name: string;
48
+ contentType: string;
49
+ path?: string;
50
+ }
51
+
52
+ export interface ProbeFailureRecord {
53
+ title: string;
54
+ file: string;
55
+ line: number;
56
+ /** Best-effort, recovered from the frozen code token at the start of the
57
+ * message (see module doc) — `null` when no known token matched (an
58
+ * ordinary `expect()` assertion failure, not a `@vgai/probe` error). */
59
+ code: string | null;
60
+ /** D3: which `GAME_SEAM_NEVER_APPEARED` sub-case this is, recovered the
61
+ * same way (a stable message prefix — see `classifyGameSeamSubCase`).
62
+ * `null` for every other code, including when `code` itself is `null`. */
63
+ subCase: 'page-threw' | 'no-bridge' | null;
64
+ /** The full rendered failure-block text (or plain assertion message) —
65
+ * see the module doc for why this, not a lost `.data` object, is the
66
+ * structured contract this reporter can actually observe. */
67
+ message: string;
68
+ attachments: ProbeFailureAttachment[];
69
+ }
70
+
71
+ export interface ProbePerfSample {
72
+ title: string;
73
+ wallMs: number;
74
+ }
75
+
76
+ export interface LastRunEnvelope {
77
+ probeReportVersion: 1;
78
+ project: string;
79
+ startedAt: string;
80
+ finishedAt: string;
81
+ status: FullResult['status'];
82
+ verdicts: ProbeVerdict[];
83
+ failures: ProbeFailureRecord[];
84
+ artifacts: { outputDir: string };
85
+ perf: {
86
+ /** Honest-degrade note (never a fabricated fps/sim-speed number): full
87
+ * per-test fps/frame-time-percentile/sim-speed capture needs page-side
88
+ * instrumentation living in `@vgai/probe`'s fixture teardown (a
89
+ * different package/agent's territory) — this reporter can only see
90
+ * Playwright's own wall-clock `duration` per test. */
91
+ note: string;
92
+ samples: ProbePerfSample[];
93
+ };
94
+ /** AC-B1.7 — set ONLY on the synthetic envelope {@link buildWedgeEnvelope}
95
+ * writes when `run-probe.ts`'s `main()` kills the child as a harness
96
+ * wedge (exit 5): this class's `Reporter.onEnd` (the normal writer of
97
+ * this file) never runs in that case — the child is killed mid-suite, not
98
+ * finished — so an ordinary run's envelope never carries this field at
99
+ * all. A consumer (`--last-failure`, a panel, a human `cat`-ing the file)
100
+ * can check this BEFORE trusting `status`/`verdicts`/`failures` as "what
101
+ * actually ran": a wedge envelope's `verdicts`/`failures` are always empty
102
+ * by construction, not because nothing failed. */
103
+ wedged?: true;
104
+ }
105
+
106
+ /** Frozen error-code tokens `@vgai/probe`'s `errors.ts`/`failure-block.ts`
107
+ * put at the START of a thrown error's message — see the module doc for why
108
+ * matching these specific tokens is not the banned "identify a failure by
109
+ * parsing message prose" pattern (Ground rule 4): it is the one channel
110
+ * through which a frozen `code` survives the Playwright reporter boundary
111
+ * at all. */
112
+ const KNOWN_MESSAGE_CODE_PREFIXES: ReadonlyArray<{ prefix: string; code: string }> = [
113
+ { prefix: 'PROBE_ENV_MISSING:', code: 'PROBE_ENV_MISSING' },
114
+ { prefix: 'GAME_SEAM_NEVER_APPEARED:', code: 'GAME_SEAM_NEVER_APPEARED' },
115
+ { prefix: 'INPUT_GATED:', code: 'INPUT_GATED' },
116
+ { prefix: 'game.waitFor timed out', code: 'WAIT_FOR_TIMEOUT' },
117
+ { prefix: 'game.events.expect failed', code: 'EVENTS_EXPECT_FAILED' },
118
+ ];
119
+
120
+ /** Strips the assisted-tier warning header (failure-block.ts prepends a line
121
+ * before the headline) so prefix-matching still works on a
122
+ * consumed-assisted-state failure. Shared by `classifyFailureCode` and
123
+ * `classifyGameSeamSubCase`. */
124
+ function stripWarningHeader(message: string): string {
125
+ return message.startsWith('⚠') ? (message.split('\n').slice(1).join('\n') ?? message) : message;
126
+ }
127
+
128
+ export function classifyFailureCode(message: string | undefined): string | null {
129
+ if (!message) return null;
130
+ const withoutWarningHeader = stripWarningHeader(message);
131
+ for (const { prefix, code } of KNOWN_MESSAGE_CODE_PREFIXES) {
132
+ if (withoutWarningHeader.startsWith(prefix)) return code;
133
+ }
134
+ return null;
135
+ }
136
+
137
+ /** D3: recovers `GAME_SEAM_NEVER_APPEARED`'s sub-case from the stable message
138
+ * prefix `@vgai/probe`'s `gameSeamNeverAppearedError` embeds (its own
139
+ * `data.subCase` does not survive the Playwright reporter boundary — see
140
+ * this module's doc comment). `null` for any other failure, including a
141
+ * `GAME_SEAM_NEVER_APPEARED` message that somehow carries neither prefix
142
+ * (shouldn't happen — defensive, not silently misclassified as one or the
143
+ * other). */
144
+ export function classifyGameSeamSubCase(
145
+ message: string | undefined,
146
+ ): 'page-threw' | 'no-bridge' | null {
147
+ if (!message) return null;
148
+ const withoutWarningHeader = stripWarningHeader(message);
149
+ if (withoutWarningHeader.startsWith('GAME_SEAM_NEVER_APPEARED:page-threw:')) return 'page-threw';
150
+ if (withoutWarningHeader.startsWith('GAME_SEAM_NEVER_APPEARED:no-bridge:')) return 'no-bridge';
151
+ return null;
152
+ }
153
+
154
+ /** Minimal duck-typed views of Playwright's real `TestCase`/`TestResult` —
155
+ * named separately so unit tests can construct plain fixtures without
156
+ * standing up a real Playwright run (this module's exported pure functions
157
+ * never require the real classes, only these shapes). */
158
+ export interface MinimalTestCase {
159
+ title: string;
160
+ location: { file: string; line: number };
161
+ }
162
+ export interface MinimalTestResult {
163
+ status: 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted';
164
+ duration: number;
165
+ retry: number;
166
+ errors: ReadonlyArray<{ message?: string }>;
167
+ attachments: ReadonlyArray<{ name: string; contentType: string; path?: string }>;
168
+ }
169
+
170
+ export function buildVerdict(test: MinimalTestCase, result: MinimalTestResult): ProbeVerdict {
171
+ return {
172
+ title: test.title,
173
+ file: test.location.file,
174
+ line: test.location.line,
175
+ status: result.status,
176
+ durationMs: result.duration,
177
+ retry: result.retry,
178
+ };
179
+ }
180
+
181
+ /** `null` for a passed/skipped result — only failed/timedOut/interrupted
182
+ * results produce a failure record. */
183
+ export function buildFailureRecord(
184
+ test: MinimalTestCase,
185
+ result: MinimalTestResult,
186
+ ): ProbeFailureRecord | null {
187
+ if (result.status === 'passed' || result.status === 'skipped') return null;
188
+ const firstError = result.errors[0];
189
+ const message = firstError?.message ?? `${test.title}: ${result.status} with no captured error`;
190
+ return {
191
+ title: test.title,
192
+ file: test.location.file,
193
+ line: test.location.line,
194
+ code: classifyFailureCode(firstError?.message),
195
+ subCase: classifyGameSeamSubCase(firstError?.message),
196
+ message,
197
+ attachments: result.attachments.map((a) => ({
198
+ name: a.name,
199
+ contentType: a.contentType,
200
+ ...(a.path !== undefined ? { path: a.path } : {}),
201
+ })),
202
+ };
203
+ }
204
+
205
+ export interface BuildLastRunEnvelopeInput {
206
+ project: string;
207
+ startedAt: string;
208
+ finishedAt: string;
209
+ status: FullResult['status'];
210
+ verdicts: ProbeVerdict[];
211
+ failures: ProbeFailureRecord[];
212
+ outputDir: string;
213
+ }
214
+
215
+ /** Task 3.4's exit-code table needs "3 missing capability" distinguished
216
+ * from an ordinary spec failure: true only when EVERY failure in the run
217
+ * is the fixture's own `GAME_SEAM_NEVER_APPEARED` AND its `no-bridge`
218
+ * sub-case (D3) — the page loaded fine but no debug bridge ever appeared.
219
+ * The OTHER sub-case, `page-threw` (the game's own setup code crashed
220
+ * before the bridge could install), is a real spec/build failure and must
221
+ * classify as exit 1, not exit 3 — a mix of either sub-case plus an
222
+ * ordinary assertion failure is likewise a real spec failure (exit 1), not
223
+ * purely a missing capability. */
224
+ export function allFailuresAreMissingCapability(failures: readonly ProbeFailureRecord[]): boolean {
225
+ return (
226
+ failures.length > 0 &&
227
+ failures.every((f) => f.code === 'GAME_SEAM_NEVER_APPEARED' && f.subCase === 'no-bridge')
228
+ );
229
+ }
230
+
231
+ export function buildLastRunEnvelope(input: BuildLastRunEnvelopeInput): LastRunEnvelope {
232
+ return {
233
+ probeReportVersion: PROBE_REPORT_VERSION,
234
+ project: input.project,
235
+ startedAt: input.startedAt,
236
+ finishedAt: input.finishedAt,
237
+ status: input.status,
238
+ verdicts: input.verdicts,
239
+ failures: input.failures,
240
+ artifacts: { outputDir: input.outputDir },
241
+ perf: {
242
+ note:
243
+ 'wall-clock duration only — full fps/frame-time-percentile/sim-speed capture needs ' +
244
+ "page-side instrumentation in @vgai/probe's fixture teardown, not yet wired here.",
245
+ samples: input.verdicts.map((v) => ({ title: v.title, wallMs: v.durationMs })),
246
+ },
247
+ };
248
+ }
249
+
250
+ export interface BuildWedgeEnvelopeInput {
251
+ project: string;
252
+ startedAt: string;
253
+ /** The actual silent-window budget that triggered the kill
254
+ * (`strikeIntervalMs * strikesToWedge`) — see `run-probe.ts`'s
255
+ * `runPlaywrightSuite` doc comment; never hardcoded here so the note below
256
+ * never lies about a test-shrunk budget. */
257
+ wedgeSilenceMs: number;
258
+ outputDir: string;
259
+ }
260
+
261
+ /**
262
+ * AC-B1.7 — the envelope `run-probe.ts`'s `main()` writes to `last-run.json`
263
+ * on a harness wedge (exit 5) INSTEAD of `ProbeJsonReporter.onEnd` (which
264
+ * never runs: the child is killed mid-suite, not finished — see
265
+ * `runPlaywrightSuite`'s `wedgeTriggered` doc comment for the exact
266
+ * mechanics). Without this, `clearStaleLastRun`'s own D4(a) delete (this
267
+ * module's header doc references it) leaves NO `last-run.json` at all after
268
+ * a wedge — a caller reading the file (`--last-failure`, a panel) would see
269
+ * "no file" and have no way to distinguish "no run has ever happened" from
270
+ * "a run just wedged". `verdicts`/`failures` are always empty here — not
271
+ * because nothing failed, but because no test in this run ever reached
272
+ * `onTestEnd` at all; `status: 'interrupted'` is Playwright's own closest
273
+ * documented meaning ("interrupted by the user" — this harness playing that
274
+ * role on the child's behalf), and `wedged: true` is the unambiguous marker
275
+ * a consumer should actually key off rather than inferring intent from
276
+ * `status` prose.
277
+ */
278
+ export function buildWedgeEnvelope(input: BuildWedgeEnvelopeInput): LastRunEnvelope {
279
+ const silenceSeconds = Math.round(input.wedgeSilenceMs / 1000);
280
+ return {
281
+ probeReportVersion: PROBE_REPORT_VERSION,
282
+ project: input.project,
283
+ startedAt: input.startedAt,
284
+ finishedAt: new Date().toISOString(),
285
+ status: 'interrupted',
286
+ verdicts: [],
287
+ failures: [],
288
+ artifacts: { outputDir: input.outputDir },
289
+ wedged: true,
290
+ perf: {
291
+ note:
292
+ `harness wedge: the child produced no output for ${silenceSeconds}s and was killed ` +
293
+ '(exit 5) before any test reached onTestEnd — there are no verdicts/failures to report ' +
294
+ 'from this run; see docs/ACCEPTANCE-DRIVER-SPEC.md §2.2.',
295
+ samples: [],
296
+ },
297
+ };
298
+ }
299
+
300
+ export interface ProbeJsonReporterOptions {
301
+ /** Absolute path to write the envelope to (`.vgai/probe/last-run.json`). */
302
+ outputFile: string;
303
+ /** Absolute project directory — carried into the envelope's `project`. */
304
+ projectDir: string;
305
+ /** Absolute artifacts directory (`.vgai/probe/last-run/`) — carried into `artifacts.outputDir`. */
306
+ outputDir: string;
307
+ }
308
+
309
+ /** The real Playwright-facing reporter — a thin glue layer over the pure
310
+ * functions above. Constructed by Playwright itself via the generated
311
+ * config's `reporter: [[<this module's path>, options]]` entry. */
312
+ export default class ProbeJsonReporter implements Reporter {
313
+ private readonly opts: ProbeJsonReporterOptions;
314
+ private readonly startedAt = new Date().toISOString();
315
+ private verdicts: ProbeVerdict[] = [];
316
+ private failures: ProbeFailureRecord[] = [];
317
+
318
+ constructor(opts: ProbeJsonReporterOptions) {
319
+ this.opts = opts;
320
+ }
321
+
322
+ onTestEnd(test: TestCase, result: TestResult): void {
323
+ const minimalTest: MinimalTestCase = { title: test.title, location: test.location };
324
+ const minimalResult: MinimalTestResult = {
325
+ status: result.status,
326
+ duration: result.duration,
327
+ retry: result.retry,
328
+ errors: result.errors,
329
+ attachments: result.attachments,
330
+ };
331
+ this.verdicts.push(buildVerdict(minimalTest, minimalResult));
332
+ const failure = buildFailureRecord(minimalTest, minimalResult);
333
+ if (failure) this.failures.push(failure);
334
+ }
335
+
336
+ onEnd(result: FullResult): void {
337
+ const envelope = buildLastRunEnvelope({
338
+ project: this.opts.projectDir,
339
+ startedAt: this.startedAt,
340
+ finishedAt: new Date().toISOString(),
341
+ status: result.status,
342
+ verdicts: this.verdicts,
343
+ failures: this.failures,
344
+ outputDir: this.opts.outputDir,
345
+ });
346
+ mkdirSync(dirname(this.opts.outputFile), { recursive: true });
347
+ writeFileSync(this.opts.outputFile, `${JSON.stringify(envelope, null, 2)}\n`);
348
+ }
349
+ }