@playdrop/playdrop-cli 0.16.2 → 0.16.11

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 (383) hide show
  1. package/bin/playdrop +1 -2
  2. package/config/client-meta.json +4 -4
  3. package/dist/apiClient.d.ts +2 -2
  4. package/dist/apiClient.js +16 -20
  5. package/dist/appUrls.d.ts +2 -2
  6. package/dist/appUrls.js +31 -33
  7. package/dist/apps/build.d.ts +2 -2
  8. package/dist/apps/build.js +83 -83
  9. package/dist/apps/index.d.ts +7 -7
  10. package/dist/apps/index.js +8 -8
  11. package/dist/apps/loadCheck.d.ts +28 -16
  12. package/dist/apps/loadCheck.js +411 -279
  13. package/dist/apps/registration.d.ts +3 -3
  14. package/dist/apps/registration.js +1 -1
  15. package/dist/apps/staticHtml.d.ts +3 -3
  16. package/dist/apps/staticHtml.js +90 -91
  17. package/dist/apps/surfaceProfiles.d.ts +2 -2
  18. package/dist/apps/surfaceProfiles.js +6 -6
  19. package/dist/apps/upload.d.ts +5 -5
  20. package/dist/apps/upload.js +75 -81
  21. package/dist/apps/validate.d.ts +2 -2
  22. package/dist/apps/validate.js +18 -22
  23. package/dist/assetSpecs.d.ts +2 -2
  24. package/dist/assetSpecs.js +35 -35
  25. package/dist/assets/model-artifacts.d.ts +1 -1
  26. package/dist/assets/model-artifacts.js +81 -77
  27. package/dist/assets/model-worker.d.ts +1 -1
  28. package/dist/assets/model-worker.js +6 -6
  29. package/dist/browser.js +9 -9
  30. package/dist/catalogue-utils.d.ts +1 -1
  31. package/dist/catalogue-utils.js +26 -26
  32. package/dist/catalogue.d.ts +21 -16
  33. package/dist/catalogue.js +509 -413
  34. package/dist/clientInfo.d.ts +1 -1
  35. package/dist/clientInfo.js +28 -28
  36. package/dist/commandContext.d.ts +5 -5
  37. package/dist/commandContext.js +19 -23
  38. package/dist/commands/accounts.js +6 -6
  39. package/dist/commands/ads.js +16 -16
  40. package/dist/commands/agents.d.ts +2 -2
  41. package/dist/commands/agents.js +131 -127
  42. package/dist/commands/boosts.js +41 -31
  43. package/dist/commands/browse.d.ts +2 -2
  44. package/dist/commands/browse.js +168 -128
  45. package/dist/commands/build.js +9 -9
  46. package/dist/commands/captureListing.d.ts +8 -8
  47. package/dist/commands/captureListing.js +292 -332
  48. package/dist/commands/changelog.js +1 -1
  49. package/dist/commands/chat.js +51 -53
  50. package/dist/commands/check.d.ts +1 -1
  51. package/dist/commands/check.js +44 -44
  52. package/dist/commands/clients.d.ts +3 -3
  53. package/dist/commands/clients.js +67 -64
  54. package/dist/commands/comments.js +36 -29
  55. package/dist/commands/create.js +305 -312
  56. package/dist/commands/createRemixContent.d.ts +1 -1
  57. package/dist/commands/createRemixContent.js +65 -60
  58. package/dist/commands/creations.js +205 -135
  59. package/dist/commands/credits.js +37 -27
  60. package/dist/commands/detail.js +40 -34
  61. package/dist/commands/dev.js +103 -126
  62. package/dist/commands/devBrowser.js +74 -65
  63. package/dist/commands/devRuntimeAssets.d.ts +4 -4
  64. package/dist/commands/devRuntimeAssets.js +38 -40
  65. package/dist/commands/devServer.d.ts +4 -4
  66. package/dist/commands/devServer.js +183 -174
  67. package/dist/commands/devShared.d.ts +3 -3
  68. package/dist/commands/devShared.js +31 -31
  69. package/dist/commands/doctor.d.ts +5 -5
  70. package/dist/commands/doctor.js +63 -57
  71. package/dist/commands/documentation.js +42 -32
  72. package/dist/commands/feedback.js +59 -42
  73. package/dist/commands/format.js +9 -9
  74. package/dist/commands/generation.d.ts +2 -2
  75. package/dist/commands/generation.js +344 -326
  76. package/dist/commands/init.d.ts +4 -4
  77. package/dist/commands/init.js +64 -61
  78. package/dist/commands/login.d.ts +2 -2
  79. package/dist/commands/login.js +42 -62
  80. package/dist/commands/logout.js +4 -4
  81. package/dist/commands/marketing.d.ts +8 -8
  82. package/dist/commands/marketing.js +246 -297
  83. package/dist/commands/notes.js +19 -19
  84. package/dist/commands/notifications.js +34 -22
  85. package/dist/commands/npmProcess.js +3 -3
  86. package/dist/commands/ownedRuntimeImageValidation.d.ts +1 -1
  87. package/dist/commands/ownedRuntimeImageValidation.js +19 -17
  88. package/dist/commands/play.js +12 -21
  89. package/dist/commands/publicPages.js +8 -4
  90. package/dist/commands/review.js +123 -110
  91. package/dist/commands/search.js +107 -88
  92. package/dist/commands/tags.js +10 -12
  93. package/dist/commands/taskCaptureSession.d.ts +3 -3
  94. package/dist/commands/taskCaptureSession.js +3 -3
  95. package/dist/commands/tweaks.js +25 -23
  96. package/dist/commands/upgrade.js +40 -31
  97. package/dist/commands/upload-content.d.ts +5 -5
  98. package/dist/commands/upload-content.js +130 -122
  99. package/dist/commands/upload-graph.d.ts +1 -1
  100. package/dist/commands/upload-graph.js +7 -11
  101. package/dist/commands/upload.d.ts +7 -7
  102. package/dist/commands/upload.js +196 -217
  103. package/dist/commands/validate.js +33 -32
  104. package/dist/commands/versionsBrowse.js +61 -51
  105. package/dist/commands/whoami.js +11 -14
  106. package/dist/commands/worker/archive-staging.d.ts +9 -0
  107. package/dist/commands/worker/archive-staging.js +257 -0
  108. package/dist/commands/worker/instrument-evidence.d.ts +1 -1
  109. package/dist/commands/worker/instrument-evidence.js +41 -43
  110. package/dist/commands/worker/provider-telemetry.d.ts +2 -1
  111. package/dist/commands/worker/provider-telemetry.js +181 -64
  112. package/dist/commands/worker/runtime.d.ts +18 -3
  113. package/dist/commands/worker/runtime.js +291 -239
  114. package/dist/commands/worker.d.ts +83 -22
  115. package/dist/commands/worker.js +1980 -1411
  116. package/dist/commands/workspaces.d.ts +2 -2
  117. package/dist/commands/workspaces.js +57 -57
  118. package/dist/config.js +23 -20
  119. package/dist/devAuth.d.ts +3 -3
  120. package/dist/devAuth.js +20 -17
  121. package/dist/environment.d.ts +1 -1
  122. package/dist/environment.js +34 -34
  123. package/dist/errors.d.ts +1 -1
  124. package/dist/errors.js +7 -7
  125. package/dist/externalAssetPackValidation.d.ts +1 -1
  126. package/dist/externalAssetPackValidation.js +9 -9
  127. package/dist/http.d.ts +1 -1
  128. package/dist/http.js +9 -9
  129. package/dist/index.js +657 -664
  130. package/dist/listingCaptureLease.js +23 -23
  131. package/dist/listingPreflight.d.ts +2 -2
  132. package/dist/listingPreflight.js +33 -33
  133. package/dist/messages.js +6 -14
  134. package/dist/output.js +9 -9
  135. package/dist/playwright.d.ts +1 -1
  136. package/dist/playwright.js +35 -40
  137. package/dist/proxyFetch.js +30 -27
  138. package/dist/recorderRelease.js +8 -8
  139. package/dist/refs.d.ts +5 -5
  140. package/dist/refs.js +40 -37
  141. package/dist/sessionCookie.js +15 -21
  142. package/dist/shellProbe.js +5 -5
  143. package/dist/taskSelection.d.ts +3 -3
  144. package/dist/taskSelection.js +67 -62
  145. package/dist/taskUtils.d.ts +1 -1
  146. package/dist/taskUtils.js +4 -4
  147. package/dist/tweakStaleness.d.ts +3 -3
  148. package/dist/tweakStaleness.js +8 -8
  149. package/dist/uploadLog.d.ts +3 -3
  150. package/dist/uploadLog.js +51 -51
  151. package/dist/versionCompare.js +3 -3
  152. package/dist/workerAppProject.d.ts +1 -1
  153. package/dist/workerAppProject.js +10 -17
  154. package/dist/workspaceAuth.d.ts +1 -1
  155. package/dist/workspaceAuth.js +28 -22
  156. package/node_modules/@playdrop/ai-client/dist/index.d.ts +35 -35
  157. package/node_modules/@playdrop/ai-client/dist/index.d.ts.map +1 -1
  158. package/node_modules/@playdrop/api-client/dist/client.d.ts +34 -33
  159. package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
  160. package/node_modules/@playdrop/api-client/dist/core/errors.d.ts +1 -1
  161. package/node_modules/@playdrop/api-client/dist/core/errors.d.ts.map +1 -1
  162. package/node_modules/@playdrop/api-client/dist/core/request.d.ts +2 -2
  163. package/node_modules/@playdrop/api-client/dist/core/request.d.ts.map +1 -1
  164. package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts +2 -2
  165. package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts.map +1 -1
  166. package/node_modules/@playdrop/api-client/dist/domains/admin.js +4 -1
  167. package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts +4 -3
  168. package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts.map +1 -1
  169. package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.js +12 -0
  170. package/node_modules/@playdrop/api-client/dist/domains/ai.d.ts +2 -2
  171. package/node_modules/@playdrop/api-client/dist/domains/ai.d.ts.map +1 -1
  172. package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts +4 -4
  173. package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -1
  174. package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts +4 -4
  175. package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts.map +1 -1
  176. package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts +4 -4
  177. package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts.map +1 -1
  178. package/node_modules/@playdrop/api-client/dist/domains/auth.d.ts +2 -2
  179. package/node_modules/@playdrop/api-client/dist/domains/auth.d.ts.map +1 -1
  180. package/node_modules/@playdrop/api-client/dist/domains/chat.d.ts +2 -2
  181. package/node_modules/@playdrop/api-client/dist/domains/chat.d.ts.map +1 -1
  182. package/node_modules/@playdrop/api-client/dist/domains/comments.d.ts +3 -3
  183. package/node_modules/@playdrop/api-client/dist/domains/comments.d.ts.map +1 -1
  184. package/node_modules/@playdrop/api-client/dist/domains/free-credits.d.ts +2 -2
  185. package/node_modules/@playdrop/api-client/dist/domains/free-credits.d.ts.map +1 -1
  186. package/node_modules/@playdrop/api-client/dist/domains/me.d.ts +2 -2
  187. package/node_modules/@playdrop/api-client/dist/domains/me.d.ts.map +1 -1
  188. package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts +2 -2
  189. package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts.map +1 -1
  190. package/node_modules/@playdrop/api-client/dist/domains/player-meta.d.ts +2 -2
  191. package/node_modules/@playdrop/api-client/dist/domains/player-meta.d.ts.map +1 -1
  192. package/node_modules/@playdrop/api-client/dist/domains/playtrade.d.ts +3 -3
  193. package/node_modules/@playdrop/api-client/dist/domains/playtrade.d.ts.map +1 -1
  194. package/node_modules/@playdrop/api-client/dist/domains/playtrade.js +2 -2
  195. package/node_modules/@playdrop/api-client/dist/domains/search.d.ts +2 -2
  196. package/node_modules/@playdrop/api-client/dist/domains/search.d.ts.map +1 -1
  197. package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts +2 -2
  198. package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts.map +1 -1
  199. package/node_modules/@playdrop/api-client/dist/index.d.ts +19 -18
  200. package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
  201. package/node_modules/@playdrop/api-client/dist/index.js +7 -2
  202. package/node_modules/@playdrop/boxel-core/dist/src/entity-cleaner.d.ts +1 -1
  203. package/node_modules/@playdrop/boxel-core/dist/src/entity-cleaner.js +47 -47
  204. package/node_modules/@playdrop/boxel-core/dist/src/entity-cleaner.js.map +1 -1
  205. package/node_modules/@playdrop/boxel-core/dist/src/entity-utils.d.ts +3 -3
  206. package/node_modules/@playdrop/boxel-core/dist/src/entity-utils.js +32 -47
  207. package/node_modules/@playdrop/boxel-core/dist/src/entity-utils.js.map +1 -1
  208. package/node_modules/@playdrop/boxel-core/dist/src/format-utils.js +16 -18
  209. package/node_modules/@playdrop/boxel-core/dist/src/format-utils.js.map +1 -1
  210. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/geometry.d.ts +2 -2
  211. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/index.d.ts +4 -4
  212. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/common.d.ts +1 -1
  213. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/index.d.ts +3 -3
  214. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/textured-builder.d.ts +2 -2
  215. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/textured-builder.js +44 -45
  216. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/textured-builder.js.map +1 -1
  217. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/types.d.ts +1 -1
  218. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/voxel-builder.d.ts +2 -2
  219. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/voxel-builder.js +40 -44
  220. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/voxel-builder.js.map +1 -1
  221. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/builder.d.ts +2 -2
  222. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/builder.js +30 -34
  223. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/builder.js.map +1 -1
  224. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/index.d.ts +4 -4
  225. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/index.js.map +1 -1
  226. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/scanner.d.ts +3 -3
  227. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/scanner.js +23 -20
  228. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/scanner.js.map +1 -1
  229. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/artifacts.d.ts +3 -3
  230. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/artifacts.js +3 -3
  231. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/face-map.d.ts +1 -1
  232. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/face-map.js +21 -21
  233. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/face-map.js.map +1 -1
  234. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/templates/index.d.ts +1 -1
  235. package/node_modules/@playdrop/boxel-core/dist/src/humanoid/templates/index.js +2 -2
  236. package/node_modules/@playdrop/boxel-core/dist/src/index.d.ts +19 -19
  237. package/node_modules/@playdrop/boxel-core/dist/src/materials.d.ts +1 -1
  238. package/node_modules/@playdrop/boxel-core/dist/src/materials.js +12 -16
  239. package/node_modules/@playdrop/boxel-core/dist/src/materials.js.map +1 -1
  240. package/node_modules/@playdrop/boxel-core/dist/src/palette_tools.d.ts +1 -1
  241. package/node_modules/@playdrop/boxel-core/dist/src/palette_tools.js +38 -41
  242. package/node_modules/@playdrop/boxel-core/dist/src/palette_tools.js.map +1 -1
  243. package/node_modules/@playdrop/boxel-core/dist/src/serialization.d.ts +1 -1
  244. package/node_modules/@playdrop/boxel-core/dist/src/serialization.js +54 -56
  245. package/node_modules/@playdrop/boxel-core/dist/src/serialization.js.map +1 -1
  246. package/node_modules/@playdrop/boxel-core/dist/src/textures.d.ts +3 -3
  247. package/node_modules/@playdrop/boxel-core/dist/src/textures.js +39 -45
  248. package/node_modules/@playdrop/boxel-core/dist/src/textures.js.map +1 -1
  249. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/infer-face.d.ts +2 -2
  250. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/infer-face.js +39 -43
  251. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/infer-face.js.map +1 -1
  252. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/layer-mode.d.ts +3 -3
  253. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/layer-mode.js +35 -35
  254. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/layer-mode.js.map +1 -1
  255. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/merge-overlay.d.ts +1 -1
  256. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/merge-overlay.js +18 -18
  257. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/merge-overlay.js.map +1 -1
  258. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/slice.d.ts +3 -3
  259. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/slice.js +50 -48
  260. package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/slice.js.map +1 -1
  261. package/node_modules/@playdrop/boxel-core/dist/src/transforms/upscale.d.ts +1 -1
  262. package/node_modules/@playdrop/boxel-core/dist/src/transforms/upscale.js +22 -26
  263. package/node_modules/@playdrop/boxel-core/dist/src/transforms/upscale.js.map +1 -1
  264. package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/slice.d.ts +2 -2
  265. package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/slice.js +8 -8
  266. package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/slice.js.map +1 -1
  267. package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/textured-to-voxel.d.ts +2 -2
  268. package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/textured-to-voxel.js +23 -28
  269. package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/textured-to-voxel.js.map +1 -1
  270. package/node_modules/@playdrop/boxel-core/dist/src/types.d.ts +8 -8
  271. package/node_modules/@playdrop/boxel-core/dist/src/validation.d.ts +1 -1
  272. package/node_modules/@playdrop/boxel-core/dist/src/validation.js +93 -95
  273. package/node_modules/@playdrop/boxel-core/dist/src/validation.js.map +1 -1
  274. package/node_modules/@playdrop/boxel-core/dist/src/voxels/greedy-mesher.d.ts +1 -1
  275. package/node_modules/@playdrop/boxel-core/dist/src/voxels/greedy-mesher.js +2 -2
  276. package/node_modules/@playdrop/boxel-core/dist/src/voxels/greedy-mesher.js.map +1 -1
  277. package/node_modules/@playdrop/boxel-core/dist/src/voxels.d.ts +1 -1
  278. package/node_modules/@playdrop/boxel-core/dist/src/voxels.js +2 -7
  279. package/node_modules/@playdrop/boxel-core/dist/src/voxels.js.map +1 -1
  280. package/node_modules/@playdrop/boxel-three/dist/src/animations.d.ts +3 -3
  281. package/node_modules/@playdrop/boxel-three/dist/src/builders.d.ts +4 -4
  282. package/node_modules/@playdrop/boxel-three/dist/src/context.d.ts +3 -3
  283. package/node_modules/@playdrop/boxel-three/dist/src/exporters/glb.d.ts +6 -6
  284. package/node_modules/@playdrop/boxel-three/dist/src/exporters/glb.js +9 -1
  285. package/node_modules/@playdrop/boxel-three/dist/src/exporters/image.d.ts +3 -3
  286. package/node_modules/@playdrop/boxel-three/dist/src/index.d.ts +17 -17
  287. package/node_modules/@playdrop/boxel-three/dist/src/instantiate.d.ts +9 -9
  288. package/node_modules/@playdrop/boxel-three/dist/src/nodes.d.ts +3 -3
  289. package/node_modules/@playdrop/boxel-three/dist/src/nodes.js +1 -1
  290. package/node_modules/@playdrop/boxel-three/dist/src/overlays.d.ts +2 -2
  291. package/node_modules/@playdrop/boxel-three/dist/src/primitives.d.ts +1 -1
  292. package/node_modules/@playdrop/boxel-three/dist/src/scene.d.ts +1 -1
  293. package/node_modules/@playdrop/boxel-three/dist/src/skinned-mesh.d.ts +2 -2
  294. package/node_modules/@playdrop/boxel-three/dist/src/texture-atlas.d.ts +1 -1
  295. package/node_modules/@playdrop/boxel-three/dist/src/textures.d.ts +3 -3
  296. package/node_modules/@playdrop/boxel-three/dist/src/types.d.ts +4 -4
  297. package/node_modules/@playdrop/boxel-three/dist/src/voxels/faces.d.ts +2 -2
  298. package/node_modules/@playdrop/boxel-three/dist/src/voxels/mesher.d.ts +1 -1
  299. package/node_modules/@playdrop/boxel-three/dist/test/fixtures/render-worker.d.ts +1 -1
  300. package/node_modules/@playdrop/config/client-meta.json +4 -4
  301. package/node_modules/@playdrop/config/dist/src/client-meta.d.ts +1 -1
  302. package/node_modules/@playdrop/config/dist/src/client-meta.d.ts.map +1 -1
  303. package/node_modules/@playdrop/config/dist/src/client-meta.js +10 -10
  304. package/node_modules/@playdrop/config/dist/src/constants.js +10 -10
  305. package/node_modules/@playdrop/config/dist/src/creator-plans.d.ts +1 -1
  306. package/node_modules/@playdrop/config/dist/src/creator-plans.d.ts.map +1 -1
  307. package/node_modules/@playdrop/config/dist/src/creator-plans.js +27 -28
  308. package/node_modules/@playdrop/config/dist/src/deployment.d.ts +4 -4
  309. package/node_modules/@playdrop/config/dist/src/deployment.d.ts.map +1 -1
  310. package/node_modules/@playdrop/config/dist/src/deployment.js +42 -41
  311. package/node_modules/@playdrop/config/dist/src/game-arena.js +12 -12
  312. package/node_modules/@playdrop/config/dist/src/index.d.ts +9 -9
  313. package/node_modules/@playdrop/config/dist/src/index.d.ts.map +1 -1
  314. package/node_modules/@playdrop/config/dist/src/index.js +24 -25
  315. package/node_modules/@playdrop/config/dist/src/public-deployment.d.ts +4 -4
  316. package/node_modules/@playdrop/config/dist/src/public-deployment.d.ts.map +1 -1
  317. package/node_modules/@playdrop/config/dist/src/public-deployment.js +41 -39
  318. package/node_modules/@playdrop/config/dist/src/runtime-client-meta.js +1 -3
  319. package/node_modules/@playdrop/config/dist/src/runtime-service-origins.d.ts.map +1 -1
  320. package/node_modules/@playdrop/config/dist/src/runtime-service-origins.js +23 -25
  321. package/node_modules/@playdrop/config/dist/src/server/fastify.d.ts +5 -5
  322. package/node_modules/@playdrop/config/dist/src/server/fastify.d.ts.map +1 -1
  323. package/node_modules/@playdrop/config/dist/src/server/fastify.js +44 -46
  324. package/node_modules/@playdrop/config/dist/src/server/logging.d.ts +1 -1
  325. package/node_modules/@playdrop/config/dist/src/server/logging.d.ts.map +1 -1
  326. package/node_modules/@playdrop/config/dist/src/server/logging.js +6 -8
  327. package/node_modules/@playdrop/config/dist/src/types.d.ts +2 -2
  328. package/node_modules/@playdrop/config/dist/test/creator-plans.test.js +12 -12
  329. package/node_modules/@playdrop/config/dist/test/deployment.test.js +59 -59
  330. package/node_modules/@playdrop/config/dist/test/fastify.test.js +4 -4
  331. package/node_modules/@playdrop/config/dist/test/game-arena.test.js +8 -8
  332. package/node_modules/@playdrop/config/dist/test/logging.test.js +6 -6
  333. package/node_modules/@playdrop/config/dist/test/validateClientEnvironment.test.js +57 -57
  334. package/node_modules/@playdrop/config/dist/tsconfig.tsbuildinfo +1 -1
  335. package/node_modules/@playdrop/types/dist/agent-task-playtest.d.ts.map +1 -1
  336. package/node_modules/@playdrop/types/dist/agent-task-terminal.d.ts +2 -2
  337. package/node_modules/@playdrop/types/dist/agent-task-terminal.d.ts.map +1 -1
  338. package/node_modules/@playdrop/types/dist/api.d.ts +314 -250
  339. package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
  340. package/node_modules/@playdrop/types/dist/api.js +40 -59
  341. package/node_modules/@playdrop/types/dist/app-capability-filters.d.ts +2 -2
  342. package/node_modules/@playdrop/types/dist/app-playtest-tape.d.ts +6 -6
  343. package/node_modules/@playdrop/types/dist/app-playtest-tape.d.ts.map +1 -1
  344. package/node_modules/@playdrop/types/dist/app-review.d.ts +2 -2
  345. package/node_modules/@playdrop/types/dist/app-review.d.ts.map +1 -1
  346. package/node_modules/@playdrop/types/dist/app-review.js +1 -6
  347. package/node_modules/@playdrop/types/dist/app.d.ts.map +1 -1
  348. package/node_modules/@playdrop/types/dist/asset-pack.d.ts +5 -5
  349. package/node_modules/@playdrop/types/dist/asset-spec.d.ts +4 -4
  350. package/node_modules/@playdrop/types/dist/asset.d.ts +11 -11
  351. package/node_modules/@playdrop/types/dist/attachment-policy.d.ts.map +1 -1
  352. package/node_modules/@playdrop/types/dist/chat.d.ts +3 -3
  353. package/node_modules/@playdrop/types/dist/creator-public-image.d.ts.map +1 -1
  354. package/node_modules/@playdrop/types/dist/graph.d.ts +4 -4
  355. package/node_modules/@playdrop/types/dist/index.d.ts +25 -25
  356. package/node_modules/@playdrop/types/dist/instrument-evidence.d.ts +2 -2
  357. package/node_modules/@playdrop/types/dist/instrument-evidence.d.ts.map +1 -1
  358. package/node_modules/@playdrop/types/dist/instrument-evidence.js +2 -11
  359. package/node_modules/@playdrop/types/dist/locale.d.ts +2 -2
  360. package/node_modules/@playdrop/types/dist/locale.d.ts.map +1 -1
  361. package/node_modules/@playdrop/types/dist/locale.js +2 -17
  362. package/node_modules/@playdrop/types/dist/owned-assets.d.ts +2 -2
  363. package/node_modules/@playdrop/types/dist/owned-assets.d.ts.map +1 -1
  364. package/node_modules/@playdrop/types/dist/player-meta.d.ts +3 -3
  365. package/node_modules/@playdrop/types/dist/player-meta.d.ts.map +1 -1
  366. package/node_modules/@playdrop/types/dist/playtest-notes.d.ts +11 -11
  367. package/node_modules/@playdrop/types/dist/playtest-notes.d.ts.map +1 -1
  368. package/node_modules/@playdrop/types/dist/playtrade.d.ts +8 -5
  369. package/node_modules/@playdrop/types/dist/playtrade.d.ts.map +1 -1
  370. package/node_modules/@playdrop/types/dist/realtime.d.ts +1 -1
  371. package/node_modules/@playdrop/types/dist/tweaks.d.ts +4 -4
  372. package/node_modules/@playdrop/types/dist/tweaks.d.ts.map +1 -1
  373. package/node_modules/@playdrop/types/dist/tweaks.js +12 -2
  374. package/node_modules/@playdrop/types/dist/version.d.ts +14 -14
  375. package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
  376. package/node_modules/@playdrop/types/dist/version.js +4 -1
  377. package/node_modules/@playdrop/vox-three/dist/src/index.d.ts +1 -1
  378. package/node_modules/@playdrop/vox-three/dist/src/vox.d.ts +2 -2
  379. package/node_modules/@playdrop/vox-three/dist/src/vox.js +20 -18
  380. package/node_modules/@playdrop/vox-three/dist/src/vox.js.map +1 -1
  381. package/node_modules/@playdrop/vox-three/dist/test/vox.test.js +11 -14
  382. package/node_modules/@playdrop/vox-three/dist/test/vox.test.js.map +1 -1
  383. package/package.json +1 -1
@@ -27,14 +27,14 @@ const dev_1 = require("./dev");
27
27
  const devRuntimeAssets_1 = require("./devRuntimeAssets");
28
28
  const devServer_1 = require("./devServer");
29
29
  const devShared_1 = require("./devShared");
30
- exports.MARKETING_SURFACES = ['desktop', 'mobile-landscape', 'mobile-portrait'];
31
- exports.MARKETING_AUDIO_POLICIES = ['music-and-sfx', 'sfx-only', 'silent'];
32
- const MOBILE_USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1';
30
+ exports.MARKETING_SURFACES = ["desktop", "mobile-landscape", "mobile-portrait"];
31
+ exports.MARKETING_AUDIO_POLICIES = ["music-and-sfx", "sfx-only", "silent"];
32
+ const MOBILE_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1";
33
33
  const SURFACE_PRESETS = {
34
34
  desktop: {
35
35
  width: 1920,
36
36
  height: 1080,
37
- sceneId: 'listing-landscape',
37
+ sceneId: "listing-landscape",
38
38
  viewport: {
39
39
  width: 1280,
40
40
  height: 720,
@@ -43,10 +43,10 @@ const SURFACE_PRESETS = {
43
43
  hasTouch: false,
44
44
  },
45
45
  },
46
- 'mobile-landscape': {
46
+ "mobile-landscape": {
47
47
  width: 1920,
48
48
  height: 1080,
49
- sceneId: 'listing-landscape',
49
+ sceneId: "listing-landscape",
50
50
  viewport: {
51
51
  width: 896,
52
52
  height: 414,
@@ -56,10 +56,10 @@ const SURFACE_PRESETS = {
56
56
  userAgent: MOBILE_USER_AGENT,
57
57
  },
58
58
  },
59
- 'mobile-portrait': {
59
+ "mobile-portrait": {
60
60
  width: 1080,
61
61
  height: 1920,
62
- sceneId: 'listing-portrait',
62
+ sceneId: "listing-portrait",
63
63
  viewport: {
64
64
  width: 414,
65
65
  height: 896,
@@ -73,7 +73,7 @@ const SURFACE_PRESETS = {
73
73
  const CAPTURE_FRAME_SELECTOR = 'iframe[title="Game"]';
74
74
  const DEFAULT_DURATION_SECONDS = 12;
75
75
  const DEFAULT_FPS = 60;
76
- const DEFAULT_AUDIO_POLICY = 'music-and-sfx';
76
+ const DEFAULT_AUDIO_POLICY = "music-and-sfx";
77
77
  const MIN_DURATION_SECONDS = 1;
78
78
  const MAX_DURATION_SECONDS = 300;
79
79
  const MIN_FPS = 1;
@@ -85,7 +85,7 @@ function parsePositiveNumber(raw, defaultValue, fieldName, minimum, maximum) {
85
85
  if (raw === undefined) {
86
86
  return defaultValue;
87
87
  }
88
- const parsed = typeof raw === 'number' ? raw : Number.parseFloat(String(raw));
88
+ const parsed = typeof raw === "number" ? raw : Number.parseFloat(String(raw));
89
89
  if (!Number.isFinite(parsed)) {
90
90
  throw new Error(`${fieldName}_invalid`);
91
91
  }
@@ -95,7 +95,7 @@ function parsePositiveNumber(raw, defaultValue, fieldName, minimum, maximum) {
95
95
  return parsed;
96
96
  }
97
97
  function normalizeSurface(raw) {
98
- const normalized = raw.trim().toLowerCase().replace(/[_\s]/g, '-');
98
+ const normalized = raw.trim().toLowerCase().replace(/[_\s]/g, "-");
99
99
  if (exports.MARKETING_SURFACES.includes(normalized)) {
100
100
  return normalized;
101
101
  }
@@ -105,7 +105,7 @@ function parseSurfaces(raw) {
105
105
  if (!raw?.trim()) {
106
106
  return [...exports.MARKETING_SURFACES];
107
107
  }
108
- const surfaces = raw.split(',').map(normalizeSurface);
108
+ const surfaces = raw.split(",").map(normalizeSurface);
109
109
  const seen = new Set();
110
110
  const unique = [];
111
111
  for (const surface of surfaces) {
@@ -121,11 +121,11 @@ function parseAudioPolicy(raw) {
121
121
  if (exports.MARKETING_AUDIO_POLICIES.includes(normalized)) {
122
122
  return normalized;
123
123
  }
124
- throw new Error('audio_policy_invalid');
124
+ throw new Error("audio_policy_invalid");
125
125
  }
126
126
  function parseMarketingCaptureOptions(targetArg, options = {}) {
127
- const durationSeconds = parsePositiveNumber(options.duration, DEFAULT_DURATION_SECONDS, 'duration', MIN_DURATION_SECONDS, MAX_DURATION_SECONDS);
128
- const fps = parsePositiveNumber(options.fps, DEFAULT_FPS, 'fps', MIN_FPS, MAX_FPS);
127
+ const durationSeconds = parsePositiveNumber(options.duration, DEFAULT_DURATION_SECONDS, "duration", MIN_DURATION_SECONDS, MAX_DURATION_SECONDS);
128
+ const fps = parsePositiveNumber(options.fps, DEFAULT_FPS, "fps", MIN_FPS, MAX_FPS);
129
129
  const outputDir = options.outputDir?.trim() ? (0, node_path_1.resolve)(process.cwd(), options.outputDir.trim()) : null;
130
130
  const seed = options.seed?.trim() || `marketing-${new Date().toISOString().slice(0, 10)}`;
131
131
  return {
@@ -142,40 +142,40 @@ function parseMarketingCaptureOptions(targetArg, options = {}) {
142
142
  };
143
143
  }
144
144
  function assertSupportedMarketingCapturePlatform(platform = process.platform) {
145
- if (platform !== 'darwin' && platform !== 'win32') {
145
+ if (platform !== "darwin" && platform !== "win32") {
146
146
  throw new Error(`unsupported_marketing_capture_platform:${platform}`);
147
147
  }
148
148
  }
149
149
  function resolveMarketingOutputPaths(projectRoot, _appName, explicitOutputDir) {
150
- const rootDir = explicitOutputDir ?? (0, node_path_1.join)(projectRoot, 'assets', 'marketing');
151
- const marketingRoot = (0, node_path_1.join)(projectRoot, 'assets', 'marketing');
150
+ const rootDir = explicitOutputDir ?? (0, node_path_1.join)(projectRoot, "assets", "marketing");
151
+ const marketingRoot = (0, node_path_1.join)(projectRoot, "assets", "marketing");
152
152
  const rootRelativeToMarketing = (0, node_path_1.relative)(marketingRoot, rootDir);
153
- if (rootRelativeToMarketing === '..' || rootRelativeToMarketing.startsWith(`..${node_path_1.sep}`) || (0, node_path_1.isAbsolute)(rootRelativeToMarketing)) {
153
+ if (rootRelativeToMarketing === ".." ||
154
+ rootRelativeToMarketing.startsWith(`..${node_path_1.sep}`) ||
155
+ (0, node_path_1.isAbsolute)(rootRelativeToMarketing)) {
154
156
  throw new Error(`marketing_output_outside_assets:${rootDir}`);
155
157
  }
156
158
  return {
157
159
  rootDir,
158
- capturesDir: (0, node_path_1.join)(rootDir, 'captures'),
159
- playdropDir: (0, node_path_1.join)(rootDir, 'playdrop'),
160
- socialDir: (0, node_path_1.join)(rootDir, 'social'),
161
- thumbnailsDir: (0, node_path_1.join)(rootDir, 'thumbnails'),
162
- screenshotsDir: (0, node_path_1.join)(rootDir, 'screenshots'),
163
- manifestPath: (0, node_path_1.join)(rootDir, 'capture-manifest.json'),
164
- reportPath: (0, node_path_1.join)(rootDir, 'marketing-report.json'),
160
+ capturesDir: (0, node_path_1.join)(rootDir, "captures"),
161
+ playdropDir: (0, node_path_1.join)(rootDir, "playdrop"),
162
+ socialDir: (0, node_path_1.join)(rootDir, "social"),
163
+ thumbnailsDir: (0, node_path_1.join)(rootDir, "thumbnails"),
164
+ screenshotsDir: (0, node_path_1.join)(rootDir, "screenshots"),
165
+ manifestPath: (0, node_path_1.join)(rootDir, "capture-manifest.json"),
166
+ reportPath: (0, node_path_1.join)(rootDir, "marketing-report.json"),
165
167
  };
166
168
  }
167
169
  function validateMarketingPreviewConfig(rawApp) {
168
170
  const errors = [];
169
- const record = rawApp && typeof rawApp === 'object' ? rawApp : {};
171
+ const record = rawApp && typeof rawApp === "object" ? rawApp : {};
170
172
  if (record.previewable !== true) {
171
- errors.push('catalogue_previewable_missing');
173
+ errors.push("catalogue_previewable_missing");
172
174
  }
173
- const preview = record.preview && typeof record.preview === 'object'
174
- ? record.preview
175
- : null;
176
- const audioPolicy = typeof preview?.audioPolicy === 'string' ? preview.audioPolicy.trim() : '';
175
+ const preview = record.preview && typeof record.preview === "object" ? record.preview : null;
176
+ const audioPolicy = typeof preview?.audioPolicy === "string" ? preview.audioPolicy.trim() : "";
177
177
  if (!audioPolicy) {
178
- errors.push('catalogue_preview_audio_policy_missing');
178
+ errors.push("catalogue_preview_audio_policy_missing");
179
179
  }
180
180
  else if (!exports.MARKETING_AUDIO_POLICIES.includes(audioPolicy)) {
181
181
  errors.push(`catalogue_preview_audio_policy_invalid:${audioPolicy}`);
@@ -187,68 +187,68 @@ function buildMarketingFfmpegArgs(input) {
187
187
  `crop=${input.crop.width}:${input.crop.height}:${input.crop.x}:${input.crop.y}`,
188
188
  `scale=${input.output.width}:${input.output.height}:flags=lanczos`,
189
189
  `fps=${input.fps}`,
190
- ].join(',');
190
+ ].join(",");
191
191
  const commonTail = [
192
- '-t',
192
+ "-t",
193
193
  String(input.durationSeconds),
194
- '-vf',
194
+ "-vf",
195
195
  videoFilter,
196
- '-c:v',
197
- 'libx264',
198
- '-preset',
199
- 'slow',
200
- '-crf',
201
- '16',
202
- '-pix_fmt',
203
- 'yuv420p',
204
- '-movflags',
205
- '+faststart',
196
+ "-c:v",
197
+ "libx264",
198
+ "-preset",
199
+ "slow",
200
+ "-crf",
201
+ "16",
202
+ "-pix_fmt",
203
+ "yuv420p",
204
+ "-movflags",
205
+ "+faststart",
206
206
  input.output.path,
207
207
  ];
208
- if (input.platform === 'darwin') {
209
- const device = input.inputDevice?.trim() || process.env.PLAYDROP_MARKETING_CAPTURE_AVFOUNDATION_DEVICE?.trim() || '1';
208
+ if (input.platform === "darwin") {
209
+ const device = input.inputDevice?.trim() || process.env.PLAYDROP_MARKETING_CAPTURE_AVFOUNDATION_DEVICE?.trim() || "1";
210
210
  return [
211
- '-y',
212
- '-f',
213
- 'avfoundation',
214
- '-framerate',
211
+ "-y",
212
+ "-f",
213
+ "avfoundation",
214
+ "-framerate",
215
215
  String(input.fps),
216
- '-capture_cursor',
217
- '0',
218
- '-i',
216
+ "-capture_cursor",
217
+ "0",
218
+ "-i",
219
219
  `${device}:none`,
220
220
  ...commonTail,
221
221
  ];
222
222
  }
223
- if (input.platform === 'win32') {
223
+ if (input.platform === "win32") {
224
224
  return [
225
- '-y',
226
- '-f',
227
- 'gdigrab',
228
- '-framerate',
225
+ "-y",
226
+ "-f",
227
+ "gdigrab",
228
+ "-framerate",
229
229
  String(input.fps),
230
- '-offset_x',
230
+ "-offset_x",
231
231
  String(input.crop.x),
232
- '-offset_y',
232
+ "-offset_y",
233
233
  String(input.crop.y),
234
- '-video_size',
234
+ "-video_size",
235
235
  `${input.crop.width}x${input.crop.height}`,
236
- '-i',
237
- 'desktop',
238
- '-t',
236
+ "-i",
237
+ "desktop",
238
+ "-t",
239
239
  String(input.durationSeconds),
240
- '-vf',
240
+ "-vf",
241
241
  `scale=${input.output.width}:${input.output.height}:flags=lanczos,fps=${input.fps}`,
242
- '-c:v',
243
- 'libx264',
244
- '-preset',
245
- 'slow',
246
- '-crf',
247
- '16',
248
- '-pix_fmt',
249
- 'yuv420p',
250
- '-movflags',
251
- '+faststart',
242
+ "-c:v",
243
+ "libx264",
244
+ "-preset",
245
+ "slow",
246
+ "-crf",
247
+ "16",
248
+ "-pix_fmt",
249
+ "yuv420p",
250
+ "-movflags",
251
+ "+faststart",
252
252
  input.output.path,
253
253
  ];
254
254
  }
@@ -258,7 +258,7 @@ function buildMarketingCaptureManifest(input) {
258
258
  return {
259
259
  appName: input.appName,
260
260
  createdAt: input.createdAt,
261
- captureSource: 'playdrop-cli-local-screen',
261
+ captureSource: "playdrop-cli-local-screen",
262
262
  captureEngine: input.captureEngine,
263
263
  audioPolicy: input.audioPolicy,
264
264
  seed: input.seed,
@@ -266,53 +266,53 @@ function buildMarketingCaptureManifest(input) {
266
266
  };
267
267
  }
268
268
  function getMarketingCaptureEngine(platform) {
269
- if (platform === 'darwin') {
270
- return 'avfoundation';
269
+ if (platform === "darwin") {
270
+ return "avfoundation";
271
271
  }
272
- if (platform === 'win32') {
273
- return 'gdigrab';
272
+ if (platform === "win32") {
273
+ return "gdigrab";
274
274
  }
275
275
  throw new Error(`unsupported_marketing_capture_platform:${platform}`);
276
276
  }
277
277
  function commandExists(command) {
278
- const result = (0, node_child_process_1.spawnSync)(command, ['-version'], {
279
- encoding: 'utf8',
278
+ const result = (0, node_child_process_1.spawnSync)(command, ["-version"], {
279
+ encoding: "utf8",
280
280
  maxBuffer: 4 * 1024 * 1024,
281
281
  });
282
282
  return result.status === 0;
283
283
  }
284
284
  function runTool(command, args, failureCode) {
285
285
  const result = (0, node_child_process_1.spawnSync)(command, args, {
286
- encoding: 'utf8',
286
+ encoding: "utf8",
287
287
  maxBuffer: 20 * 1024 * 1024,
288
288
  });
289
289
  if (result.status !== 0) {
290
- const stdout = result.stdout?.trim() || '';
291
- const stderr = result.stderr?.trim() || '';
292
- const combined = [stdout, stderr].filter(Boolean).join('\n');
290
+ const stdout = result.stdout?.trim() || "";
291
+ const stderr = result.stderr?.trim() || "";
292
+ const combined = [stdout, stderr].filter(Boolean).join("\n");
293
293
  throw new Error(`${failureCode}:${combined}`);
294
294
  }
295
295
  return {
296
- stdout: result.stdout || '',
297
- stderr: result.stderr || '',
296
+ stdout: result.stdout || "",
297
+ stderr: result.stderr || "",
298
298
  };
299
299
  }
300
300
  function readFfmpegCapabilities() {
301
- const encoders = runTool('ffmpeg', ['-hide_banner', '-encoders'], 'ffmpeg_probe_failed');
302
- const formats = runTool('ffmpeg', ['-hide_banner', '-formats'], 'ffmpeg_probe_failed');
301
+ const encoders = runTool("ffmpeg", ["-hide_banner", "-encoders"], "ffmpeg_probe_failed");
302
+ const formats = runTool("ffmpeg", ["-hide_banner", "-formats"], "ffmpeg_probe_failed");
303
303
  return `${encoders.stdout}\n${encoders.stderr}\n${formats.stdout}\n${formats.stderr}`;
304
304
  }
305
305
  function validateFfmpegCapabilities(platform) {
306
306
  const capabilities = readFfmpegCapabilities();
307
307
  const errors = [];
308
308
  if (!/\blibx264\b/.test(capabilities)) {
309
- errors.push('ffmpeg_libx264_missing');
309
+ errors.push("ffmpeg_libx264_missing");
310
310
  }
311
- if (platform === 'darwin' && !/\bavfoundation\b/.test(capabilities)) {
312
- errors.push('ffmpeg_avfoundation_missing');
311
+ if (platform === "darwin" && !/\bavfoundation\b/.test(capabilities)) {
312
+ errors.push("ffmpeg_avfoundation_missing");
313
313
  }
314
- if (platform === 'win32' && !/\bgdigrab\b/.test(capabilities)) {
315
- errors.push('ffmpeg_gdigrab_missing');
314
+ if (platform === "win32" && !/\bgdigrab\b/.test(capabilities)) {
315
+ errors.push("ffmpeg_gdigrab_missing");
316
316
  }
317
317
  return errors;
318
318
  }
@@ -328,125 +328,125 @@ function loadCatalogueApp(cataloguePath, appName) {
328
328
  if (!cataloguePath || !(0, node_fs_1.existsSync)(cataloguePath)) {
329
329
  return null;
330
330
  }
331
- const raw = JSON.parse((0, node_fs_1.readFileSync)(cataloguePath, 'utf8'));
332
- const apps = raw && typeof raw === 'object' && Array.isArray(raw.apps)
331
+ const raw = JSON.parse((0, node_fs_1.readFileSync)(cataloguePath, "utf8"));
332
+ const apps = raw && typeof raw === "object" && Array.isArray(raw.apps)
333
333
  ? raw.apps
334
334
  : Array.isArray(raw)
335
335
  ? raw
336
336
  : [];
337
- return apps.find(entry => entry && typeof entry === 'object' && entry.name === appName) ?? null;
337
+ return (apps.find((entry) => entry && typeof entry === "object" && entry.name === appName) ?? null);
338
338
  }
339
339
  function formatMarketingError(error) {
340
- if (error.message.startsWith('unsupported_marketing_capture_platform:')) {
341
- const platform = error.message.split(':')[1] || process.platform;
340
+ if (error.message.startsWith("unsupported_marketing_capture_platform:")) {
341
+ const platform = error.message.split(":")[1] || process.platform;
342
342
  return {
343
343
  message: `Marketing capture only supports macOS and Windows in v1. Current platform: ${platform}.`,
344
344
  suggestions: [],
345
345
  };
346
346
  }
347
- if (error.message === 'ffmpeg_missing') {
347
+ if (error.message === "ffmpeg_missing") {
348
348
  return {
349
- message: 'ffmpeg is required for local marketing capture.',
350
- suggestions: ['Install ffmpeg and make sure it is available on PATH.'],
349
+ message: "ffmpeg is required for local marketing capture.",
350
+ suggestions: ["Install ffmpeg and make sure it is available on PATH."],
351
351
  };
352
352
  }
353
- if (error.message === 'ffprobe_missing') {
353
+ if (error.message === "ffprobe_missing") {
354
354
  return {
355
- message: 'ffprobe is required for local marketing capture.',
356
- suggestions: ['Install ffmpeg and make sure ffprobe is available on PATH.'],
355
+ message: "ffprobe is required for local marketing capture.",
356
+ suggestions: ["Install ffmpeg and make sure ffprobe is available on PATH."],
357
357
  };
358
358
  }
359
- if (error.message === 'ffmpeg_libx264_missing') {
359
+ if (error.message === "ffmpeg_libx264_missing") {
360
360
  return {
361
- message: 'ffmpeg must support the libx264 encoder for marketing capture.',
362
- suggestions: ['Install a full ffmpeg build with libx264 enabled.'],
361
+ message: "ffmpeg must support the libx264 encoder for marketing capture.",
362
+ suggestions: ["Install a full ffmpeg build with libx264 enabled."],
363
363
  };
364
364
  }
365
- if (error.message === 'ffmpeg_avfoundation_missing') {
365
+ if (error.message === "ffmpeg_avfoundation_missing") {
366
366
  return {
367
- message: 'ffmpeg must support avfoundation screen capture on macOS.',
368
- suggestions: ['Install a macOS ffmpeg build with avfoundation enabled.'],
367
+ message: "ffmpeg must support avfoundation screen capture on macOS.",
368
+ suggestions: ["Install a macOS ffmpeg build with avfoundation enabled."],
369
369
  };
370
370
  }
371
- if (error.message === 'ffmpeg_gdigrab_missing') {
371
+ if (error.message === "ffmpeg_gdigrab_missing") {
372
372
  return {
373
- message: 'ffmpeg must support gdigrab screen capture on Windows.',
374
- suggestions: ['Install a Windows ffmpeg build with gdigrab enabled.'],
373
+ message: "ffmpeg must support gdigrab screen capture on Windows.",
374
+ suggestions: ["Install a Windows ffmpeg build with gdigrab enabled."],
375
375
  };
376
376
  }
377
- if (error.message.startsWith('marketing_output_outside_assets:')) {
377
+ if (error.message.startsWith("marketing_output_outside_assets:")) {
378
378
  return {
379
- message: 'Marketing capture output must stay under assets/marketing/.',
380
- suggestions: ['Remove --output-dir or set it to assets/marketing or a subdirectory inside assets/marketing.'],
379
+ message: "Marketing capture output must stay under assets/marketing/.",
380
+ suggestions: ["Remove --output-dir or set it to assets/marketing or a subdirectory inside assets/marketing."],
381
381
  };
382
382
  }
383
- if (error.message === 'catalogue_previewable_missing') {
383
+ if (error.message === "catalogue_previewable_missing") {
384
384
  return {
385
- message: 'catalogue.json must mark the app as previewable before marketing capture.',
386
- suggestions: ['Set previewable: true on the app entry.'],
385
+ message: "catalogue.json must mark the app as previewable before marketing capture.",
386
+ suggestions: ["Set previewable: true on the app entry."],
387
387
  };
388
388
  }
389
- if (error.message === 'catalogue_preview_audio_policy_missing') {
389
+ if (error.message === "catalogue_preview_audio_policy_missing") {
390
390
  return {
391
- message: 'catalogue.json must declare preview.audioPolicy before marketing capture.',
392
- suggestions: ['Set preview.audioPolicy to music-and-sfx, sfx-only, or silent.'],
391
+ message: "catalogue.json must declare preview.audioPolicy before marketing capture.",
392
+ suggestions: ["Set preview.audioPolicy to music-and-sfx, sfx-only, or silent."],
393
393
  };
394
394
  }
395
- if (error.message.startsWith('catalogue_preview_audio_policy_invalid:')) {
395
+ if (error.message.startsWith("catalogue_preview_audio_policy_invalid:")) {
396
396
  return {
397
- message: 'catalogue.json preview.audioPolicy must be music-and-sfx, sfx-only, or silent.',
397
+ message: "catalogue.json preview.audioPolicy must be music-and-sfx, sfx-only, or silent.",
398
398
  suggestions: [],
399
399
  };
400
400
  }
401
- if (error.message.startsWith('ffmpeg_failed:') || error.message.startsWith('ffprobe_failed:')) {
401
+ if (error.message.startsWith("ffmpeg_failed:") || error.message.startsWith("ffprobe_failed:")) {
402
402
  return {
403
- message: error.message.slice(error.message.indexOf(':') + 1).trim() || 'ffmpeg failed.',
403
+ message: error.message.slice(error.message.indexOf(":") + 1).trim() || "ffmpeg failed.",
404
404
  suggestions: [],
405
405
  };
406
406
  }
407
- if (error.message === 'marketing_preview_hook_missing') {
407
+ if (error.message === "marketing_preview_hook_missing") {
408
408
  return {
409
- message: 'The game did not expose window.__listingCapture.prepare for marketing preview capture.',
410
- suggestions: ['Implement the PlayDrop preview hook before running marketing capture.'],
409
+ message: "The game did not expose window.__listingCapture.prepare for marketing preview capture.",
410
+ suggestions: ["Implement the PlayDrop preview hook before running marketing capture."],
411
411
  };
412
412
  }
413
- if (error.message === 'marketing_audio_capture_hook_missing') {
413
+ if (error.message === "marketing_audio_capture_hook_missing") {
414
414
  return {
415
- message: 'The game did not expose preview audio capture hooks.',
416
- suggestions: ['Expose startAudioCapture and stopAudioCapture when preview audioPolicy is not silent.'],
415
+ message: "The game did not expose preview audio capture hooks.",
416
+ suggestions: ["Expose startAudioCapture and stopAudioCapture when preview audioPolicy is not silent."],
417
417
  };
418
418
  }
419
- if (error.message.startsWith('marketing_capture_wrong_window:')) {
420
- const [, surface, similarity] = error.message.split(':');
419
+ if (error.message.startsWith("marketing_capture_wrong_window:")) {
420
+ const [, surface, similarity] = error.message.split(":");
421
421
  return {
422
- message: `Marketing capture for ${surface || 'the surface'} does not match the PlayDrop preview frame. Similarity: ${similarity || 'unknown'}.`,
422
+ message: `Marketing capture for ${surface || "the surface"} does not match the PlayDrop preview frame. Similarity: ${similarity || "unknown"}.`,
423
423
  suggestions: [
424
- 'Make sure the visible Chromium window is on the selected capture display.',
425
- 'On macOS, rerun with the correct --screen-device value for the display that contains the PlayDrop preview.',
426
- 'Do not continue with manual or browser-frame capture output.',
424
+ "Make sure the visible Chromium window is on the selected capture display.",
425
+ "On macOS, rerun with the correct --screen-device value for the display that contains the PlayDrop preview.",
426
+ "Do not continue with manual or browser-frame capture output.",
427
427
  ],
428
428
  };
429
429
  }
430
- if (error.message.startsWith('marketing_capture_audio_too_quiet:')) {
431
- const [, surface, integratedLufs, peakDb] = error.message.split(':');
430
+ if (error.message.startsWith("marketing_capture_audio_too_quiet:")) {
431
+ const [, surface, integratedLufs, peakDb] = error.message.split(":");
432
432
  return {
433
- message: `Marketing capture audio for ${surface || 'the surface'} is too quiet (${integratedLufs || '?'} LUFS, peak ${peakDb || '?'} dB).`,
433
+ message: `Marketing capture audio for ${surface || "the surface"} is too quiet (${integratedLufs || "?"} LUFS, peak ${peakDb || "?"} dB).`,
434
434
  suggestions: [
435
- 'Add or raise preview background music and SFX through PlayDrop catalogue audio or PlayDrop AI generation.',
436
- 'Rerun marketing capture after the preview audio is clearly audible.',
435
+ "Add or raise preview background music and SFX through PlayDrop catalogue audio or PlayDrop AI generation.",
436
+ "Rerun marketing capture after the preview audio is clearly audible.",
437
437
  ],
438
438
  };
439
439
  }
440
- if (error.message === 'preview_game_frame_missing') {
440
+ if (error.message === "preview_game_frame_missing") {
441
441
  return {
442
- message: 'The local dev preview did not expose a playable game iframe for capture.',
443
- suggestions: ['Run playdrop project validate . and confirm the app opens on /dev-preview.'],
442
+ message: "The local dev preview did not expose a playable game iframe for capture.",
443
+ suggestions: ["Run playdrop project validate . and confirm the app opens on /dev-preview."],
444
444
  };
445
445
  }
446
- if (error.message === 'preview_game_frame_hidden') {
446
+ if (error.message === "preview_game_frame_hidden") {
447
447
  return {
448
- message: 'The local dev preview game frame is hidden or has no measurable size.',
449
- suggestions: ['Make sure the preview scene renders the game immediately without a menu or loading screen.'],
448
+ message: "The local dev preview game frame is hidden or has no measurable size.",
449
+ suggestions: ["Make sure the preview scene renders the game immediately without a menu or loading screen."],
450
450
  };
451
451
  }
452
452
  return {
@@ -456,11 +456,11 @@ function formatMarketingError(error) {
456
456
  }
457
457
  function ensureToolingAvailable(platform) {
458
458
  assertSupportedMarketingCapturePlatform(platform);
459
- if (!commandExists('ffmpeg')) {
460
- throw new Error('ffmpeg_missing');
459
+ if (!commandExists("ffmpeg")) {
460
+ throw new Error("ffmpeg_missing");
461
461
  }
462
- if (!commandExists('ffprobe')) {
463
- throw new Error('ffprobe_missing');
462
+ if (!commandExists("ffprobe")) {
463
+ throw new Error("ffprobe_missing");
464
464
  }
465
465
  const capabilityErrors = validateFfmpegCapabilities(platform);
466
466
  if (capabilityErrors.length > 0) {
@@ -476,7 +476,7 @@ function resolveProjectRoot(resolvedTarget) {
476
476
  }
477
477
  async function waitForPreviewGameFrame(page, timeoutMs) {
478
478
  const frameHandle = await page.waitForSelector(CAPTURE_FRAME_SELECTOR, {
479
- state: 'attached',
479
+ state: "attached",
480
480
  timeout: timeoutMs,
481
481
  });
482
482
  const startedAt = Date.now();
@@ -487,20 +487,20 @@ async function waitForPreviewGameFrame(page, timeoutMs) {
487
487
  }
488
488
  await page.waitForTimeout(200);
489
489
  }
490
- throw new Error('preview_game_frame_missing');
490
+ throw new Error("preview_game_frame_missing");
491
491
  }
492
492
  async function prepareMarketingPreview(page, surface, audioPolicy, seed) {
493
493
  const frame = await waitForPreviewGameFrame(page, 60000);
494
494
  const preset = SURFACE_PRESETS[surface];
495
495
  await frame.waitForFunction(() => {
496
496
  const captureWindow = window;
497
- return typeof captureWindow.__listingCapture?.prepare === 'function';
497
+ return typeof captureWindow.__listingCapture?.prepare === "function";
498
498
  }, undefined, { timeout: 60000 });
499
499
  await frame.evaluate(async (payload) => {
500
500
  const captureWindow = window;
501
501
  const hook = captureWindow.__listingCapture;
502
- if (!hook || typeof hook.prepare !== 'function') {
503
- throw new Error('marketing_preview_hook_missing');
502
+ if (!hook || typeof hook.prepare !== "function") {
503
+ throw new Error("marketing_preview_hook_missing");
504
504
  }
505
505
  await hook.prepare(payload);
506
506
  }, {
@@ -516,18 +516,18 @@ async function startMarketingAudioCapture(page) {
516
516
  await frame.evaluate(async () => {
517
517
  const captureWindow = window;
518
518
  const hook = captureWindow.__listingCapture;
519
- if (!hook || typeof hook.startAudioCapture !== 'function') {
520
- throw new Error('marketing_audio_capture_hook_missing');
519
+ if (!hook || typeof hook.startAudioCapture !== "function") {
520
+ throw new Error("marketing_audio_capture_hook_missing");
521
521
  }
522
522
  await hook.startAudioCapture();
523
523
  });
524
524
  }
525
525
  function resolveExportedAudioFileName(mimeType) {
526
- if (mimeType.includes('webm')) {
527
- return 'preview-audio.webm';
526
+ if (mimeType.includes("webm")) {
527
+ return "preview-audio.webm";
528
528
  }
529
- if (mimeType.includes('mp4') || mimeType.includes('aac') || mimeType.includes('m4a')) {
530
- return 'preview-audio.m4a';
529
+ if (mimeType.includes("mp4") || mimeType.includes("aac") || mimeType.includes("m4a")) {
530
+ return "preview-audio.m4a";
531
531
  }
532
532
  throw new Error(`unsupported_marketing_audio_mime_type:${mimeType}`);
533
533
  }
@@ -536,27 +536,27 @@ async function stopMarketingAudioCapture(page, outputDir) {
536
536
  const exportedAudio = await frame.evaluate(async () => {
537
537
  const captureWindow = window;
538
538
  const hook = captureWindow.__listingCapture;
539
- if (!hook || typeof hook.stopAudioCapture !== 'function') {
540
- throw new Error('marketing_audio_capture_hook_missing');
539
+ if (!hook || typeof hook.stopAudioCapture !== "function") {
540
+ throw new Error("marketing_audio_capture_hook_missing");
541
541
  }
542
542
  return hook.stopAudioCapture();
543
543
  });
544
544
  const filePath = (0, node_path_1.join)(outputDir, resolveExportedAudioFileName(exportedAudio.mimeType));
545
- await (0, promises_1.writeFile)(filePath, Buffer.from(exportedAudio.base64, 'base64'));
545
+ await (0, promises_1.writeFile)(filePath, Buffer.from(exportedAudio.base64, "base64"));
546
546
  return filePath;
547
547
  }
548
548
  async function measurePreviewGameFrame(page) {
549
549
  const cdpSession = await page.context().newCDPSession(page);
550
- const windowState = await cdpSession.send('Browser.getWindowForTarget');
550
+ const windowState = await cdpSession.send("Browser.getWindowForTarget");
551
551
  const bounds = windowState.bounds ?? {};
552
552
  return await page.evaluate((input) => {
553
553
  const frame = document.querySelector(input.selector);
554
554
  if (!(frame instanceof HTMLIFrameElement)) {
555
- throw new Error('preview_game_frame_missing');
555
+ throw new Error("preview_game_frame_missing");
556
556
  }
557
557
  const rect = frame.getBoundingClientRect();
558
558
  if (rect.width <= 0 || rect.height <= 0) {
559
- throw new Error('preview_game_frame_hidden');
559
+ throw new Error("preview_game_frame_hidden");
560
560
  }
561
561
  return {
562
562
  outerWidth: window.outerWidth,
@@ -593,10 +593,10 @@ async function fitWindowToSurface(page, surface) {
593
593
  if (Math.abs(deltaWidth) <= 1 && Math.abs(deltaHeight) <= 1) {
594
594
  return measurement;
595
595
  }
596
- const windowState = await cdpSession.send('Browser.getWindowForTarget');
597
- const currentWidth = typeof windowState.bounds.width === 'number' ? windowState.bounds.width : Math.round(measurement.outerWidth);
598
- const currentHeight = typeof windowState.bounds.height === 'number' ? windowState.bounds.height : Math.round(measurement.outerHeight);
599
- await cdpSession.send('Browser.setWindowBounds', {
596
+ const windowState = await cdpSession.send("Browser.getWindowForTarget");
597
+ const currentWidth = typeof windowState.bounds.width === "number" ? windowState.bounds.width : Math.round(measurement.outerWidth);
598
+ const currentHeight = typeof windowState.bounds.height === "number" ? windowState.bounds.height : Math.round(measurement.outerHeight);
599
+ await cdpSession.send("Browser.setWindowBounds", {
600
600
  windowId: windowState.windowId,
601
601
  bounds: {
602
602
  width: Math.max(400, currentWidth + deltaWidth),
@@ -609,131 +609,82 @@ async function fitWindowToSurface(page, surface) {
609
609
  return measurement;
610
610
  }
611
611
  function computeScreenCrop(measurement, platform) {
612
- const scale = platform === 'darwin' ? measurement.devicePixelRatio || 1 : 1;
612
+ const scale = platform === "darwin" ? measurement.devicePixelRatio || 1 : 1;
613
613
  const x = Math.round((measurement.windowX + measurement.iframeRect.x) * scale);
614
614
  const y = Math.round((measurement.windowY + measurement.iframeRect.y) * scale);
615
615
  const width = Math.round(measurement.iframeRect.width * scale);
616
616
  const height = Math.round(measurement.iframeRect.height * scale);
617
617
  if (width <= 0 || height <= 0) {
618
- throw new Error('invalid_marketing_capture_crop');
618
+ throw new Error("invalid_marketing_capture_crop");
619
619
  }
620
620
  return { x, y, width, height };
621
621
  }
622
622
  function probeMediaFile(filePath) {
623
- const { stdout } = runTool('ffprobe', [
624
- '-v',
625
- 'error',
626
- '-show_streams',
627
- '-show_format',
628
- '-of',
629
- 'json',
630
- filePath,
631
- ], 'ffprobe_failed');
623
+ const { stdout } = runTool("ffprobe", ["-v", "error", "-show_streams", "-show_format", "-of", "json", filePath], "ffprobe_failed");
632
624
  const probe = JSON.parse(stdout);
633
- const video = probe.streams?.find(stream => stream.codec_type === 'video');
634
- if (!video || typeof video.width !== 'number' || typeof video.height !== 'number') {
635
- throw new Error('marketing_video_stream_missing');
625
+ const video = probe.streams?.find((stream) => stream.codec_type === "video");
626
+ if (!video || typeof video.width !== "number" || typeof video.height !== "number") {
627
+ throw new Error("marketing_video_stream_missing");
636
628
  }
637
629
  const durationSeconds = probe.format?.duration ? Number.parseFloat(probe.format.duration) : Number.NaN;
638
630
  if (!Number.isFinite(durationSeconds)) {
639
- throw new Error('marketing_duration_missing');
631
+ throw new Error("marketing_duration_missing");
640
632
  }
641
633
  return {
642
634
  width: video.width,
643
635
  height: video.height,
644
636
  durationSeconds,
645
- audioTracks: probe.streams?.filter(stream => stream.codec_type === 'audio').length ?? 0,
637
+ audioTracks: probe.streams?.filter((stream) => stream.codec_type === "audio").length ?? 0,
646
638
  };
647
639
  }
648
640
  function muxMarketingAudio(videoPath, audioPath) {
649
641
  const muxedPath = `${videoPath}.muxed.mp4`;
650
- runTool('ffmpeg', [
651
- '-y',
652
- '-i',
653
- videoPath,
654
- '-i',
655
- audioPath,
656
- '-c:v',
657
- 'copy',
658
- '-c:a',
659
- 'aac',
660
- '-shortest',
661
- muxedPath,
662
- ], 'ffmpeg_failed');
642
+ runTool("ffmpeg", ["-y", "-i", videoPath, "-i", audioPath, "-c:v", "copy", "-c:a", "aac", "-shortest", muxedPath], "ffmpeg_failed");
663
643
  (0, node_fs_1.renameSync)(muxedPath, videoPath);
664
644
  }
665
645
  function extractPoster(videoPath, posterPath) {
666
- runTool('ffmpeg', [
667
- '-y',
668
- '-ss',
669
- '2',
670
- '-i',
671
- videoPath,
672
- '-frames:v',
673
- '1',
674
- posterPath,
675
- ], 'ffmpeg_failed');
646
+ runTool("ffmpeg", ["-y", "-ss", "2", "-i", videoPath, "-frames:v", "1", posterPath], "ffmpeg_failed");
676
647
  }
677
648
  async function capturePreviewReferenceFrame(page, outputPath) {
678
649
  await page.locator(CAPTURE_FRAME_SELECTOR).screenshot({ path: outputPath });
679
650
  }
680
651
  function calculatePreviewFrameSimilarity(referencePath, posterPath) {
681
- const { stderr } = runTool('ffmpeg', [
682
- '-hide_banner',
683
- '-i',
652
+ const { stderr } = runTool("ffmpeg", [
653
+ "-hide_banner",
654
+ "-i",
684
655
  referencePath,
685
- '-i',
656
+ "-i",
686
657
  posterPath,
687
- '-filter_complex',
688
- '[0:v]scale=320:320:force_original_aspect_ratio=decrease,pad=320:320:(ow-iw)/2:(oh-ih)/2,format=yuv420p[ref];[1:v]scale=320:320:force_original_aspect_ratio=decrease,pad=320:320:(ow-iw)/2:(oh-ih)/2,format=yuv420p[cap];[ref][cap]ssim',
689
- '-f',
690
- 'null',
691
- '-',
692
- ], 'ffmpeg_failed');
658
+ "-filter_complex",
659
+ "[0:v]scale=320:320:force_original_aspect_ratio=decrease,pad=320:320:(ow-iw)/2:(oh-ih)/2,format=yuv420p[ref];[1:v]scale=320:320:force_original_aspect_ratio=decrease,pad=320:320:(ow-iw)/2:(oh-ih)/2,format=yuv420p[cap];[ref][cap]ssim",
660
+ "-f",
661
+ "null",
662
+ "-",
663
+ ], "ffmpeg_failed");
693
664
  const match = stderr.match(/All:([0-9.]+)/);
694
665
  if (!match) {
695
- throw new Error('marketing_capture_similarity_missing');
666
+ throw new Error("marketing_capture_similarity_missing");
696
667
  }
697
668
  return Number.parseFloat(match[1]);
698
669
  }
699
670
  function validatePreviewFrameSimilarity(surface, similarity) {
700
671
  if (!Number.isFinite(similarity) || similarity < MIN_MARKETING_PREVIEW_FRAME_SIMILARITY) {
701
- throw new Error(`marketing_capture_wrong_window:${surface}:${Number.isFinite(similarity) ? similarity.toFixed(3) : 'unknown'}`);
672
+ throw new Error(`marketing_capture_wrong_window:${surface}:${Number.isFinite(similarity) ? similarity.toFixed(3) : "unknown"}`);
702
673
  }
703
674
  }
704
675
  function measureMarketingAudio(videoPath) {
705
- const ebur = runTool('ffmpeg', [
706
- '-hide_banner',
707
- '-nostats',
708
- '-i',
709
- videoPath,
710
- '-filter_complex',
711
- 'ebur128',
712
- '-f',
713
- 'null',
714
- '-',
715
- ], 'ffmpeg_failed');
676
+ const ebur = runTool("ffmpeg", ["-hide_banner", "-nostats", "-i", videoPath, "-filter_complex", "ebur128", "-f", "null", "-"], "ffmpeg_failed");
716
677
  const eburText = `${ebur.stdout}\n${ebur.stderr}`;
717
678
  const integratedMatches = [...eburText.matchAll(/I:\s*(-?\d+(?:\.\d+)?) LUFS/g)];
718
679
  const integratedLufs = integratedMatches.length
719
- ? Number.parseFloat(integratedMatches[integratedMatches.length - 1]?.[1] ?? '')
680
+ ? Number.parseFloat(integratedMatches[integratedMatches.length - 1]?.[1] ?? "")
720
681
  : Number.NaN;
721
- const volume = runTool('ffmpeg', [
722
- '-hide_banner',
723
- '-nostats',
724
- '-i',
725
- videoPath,
726
- '-af',
727
- 'volumedetect',
728
- '-f',
729
- 'null',
730
- '-',
731
- ], 'ffmpeg_failed');
682
+ const volume = runTool("ffmpeg", ["-hide_banner", "-nostats", "-i", videoPath, "-af", "volumedetect", "-f", "null", "-"], "ffmpeg_failed");
732
683
  const volumeText = `${volume.stdout}\n${volume.stderr}`;
733
684
  const peakMatch = volumeText.match(/max_volume:\s*(-?\d+(?:\.\d+)?) dB/);
734
- const peakDb = peakMatch ? Number.parseFloat(peakMatch[1] ?? '') : Number.NaN;
685
+ const peakDb = peakMatch ? Number.parseFloat(peakMatch[1] ?? "") : Number.NaN;
735
686
  if (!Number.isFinite(integratedLufs) || !Number.isFinite(peakDb)) {
736
- throw new Error('marketing_audio_metrics_missing');
687
+ throw new Error("marketing_audio_metrics_missing");
737
688
  }
738
689
  return { integratedLufs, peakDb };
739
690
  }
@@ -743,20 +694,20 @@ function validateMarketingAudio(surface, metrics) {
743
694
  }
744
695
  }
745
696
  function createMarketingReport(input) {
746
- const warnings = ['Exciting moment validation requires visual review from the marketing-pack workflow.'];
697
+ const warnings = ["Exciting moment validation requires visual review from the marketing-pack workflow."];
747
698
  if (!input.audioValidated) {
748
- warnings.push('Required audio was not validated.');
699
+ warnings.push("Required audio was not validated.");
749
700
  }
750
701
  return {
751
702
  appName: input.appName,
752
703
  createdAt: input.createdAt,
753
- status: 'passed',
704
+ status: "passed",
754
705
  durationSeconds: Math.round((Date.now() - input.startedAt) / 1000),
755
706
  gates: [
756
707
  {
757
- id: 'marketing-capture',
758
- status: 'passed',
759
- summary: 'Local marketing capture completed.',
708
+ id: "marketing-capture",
709
+ status: "passed",
710
+ summary: "Local marketing capture completed.",
760
711
  },
761
712
  ],
762
713
  assetCounts: {
@@ -784,9 +735,7 @@ async function resolveMarketingTarget(parsedOptions) {
784
735
  return (0, devShared_1.resolveDevTarget)(parsedOptions.targetArg, parsedOptions.appName);
785
736
  }
786
737
  catch (error) {
787
- (0, messages_1.printErrorWithHelp)(error?.message || 'Unable to resolve marketing capture target.', [
788
- 'Run the command inside a PlayDrop workspace or pass an app target.',
789
- ], { command: 'project marketing capture' });
738
+ (0, messages_1.printErrorWithHelp)(error?.message || "Unable to resolve marketing capture target.", ["Run the command inside a PlayDrop workspace or pass an app target."], { command: "project marketing capture" });
790
739
  process.exitCode = 1;
791
740
  return null;
792
741
  }
@@ -799,7 +748,7 @@ async function marketingDoctor(targetArg, options = {}) {
799
748
  }
800
749
  catch (error) {
801
750
  const detail = formatMarketingError(error instanceof Error ? error : new Error(String(error)));
802
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project marketing doctor' });
751
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project marketing doctor" });
803
752
  process.exitCode = 1;
804
753
  return;
805
754
  }
@@ -816,18 +765,18 @@ async function marketingDoctor(targetArg, options = {}) {
816
765
  if (previewErrors.length > 0) {
817
766
  throw new Error(previewErrors[0]);
818
767
  }
819
- const userDataDir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'playdrop-marketing-doctor-'));
768
+ const userDataDir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "playdrop-marketing-doctor-"));
820
769
  const context = await (0, playwright_1.launchPersistentChromiumContext)(userDataDir, { viewport: SURFACE_PRESETS.desktop.viewport });
821
770
  await context.close();
822
771
  await (0, promises_1.rm)(userDataDir, { recursive: true, force: true });
823
772
  }
824
773
  catch (error) {
825
774
  const detail = formatMarketingError(error instanceof Error ? error : new Error(String(error)));
826
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project marketing doctor' });
775
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project marketing doctor" });
827
776
  process.exitCode = 1;
828
777
  return;
829
778
  }
830
- console.log('[marketing] Doctor passed.');
779
+ console.log("[marketing] Doctor passed.");
831
780
  }
832
781
  async function marketingCapture(targetArg, options = {}) {
833
782
  const startedAt = Date.now();
@@ -838,7 +787,7 @@ async function marketingCapture(targetArg, options = {}) {
838
787
  }
839
788
  catch (error) {
840
789
  const detail = formatMarketingError(error instanceof Error ? error : new Error(String(error)));
841
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project marketing capture' });
790
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project marketing capture" });
842
791
  process.exitCode = 1;
843
792
  return;
844
793
  }
@@ -859,9 +808,9 @@ async function marketingCapture(targetArg, options = {}) {
859
808
  const projectRoot = resolveProjectRoot(resolvedTarget);
860
809
  const outputPaths = resolveMarketingOutputPaths(projectRoot, appName, parsedOptions.outputDir);
861
810
  const projectInfo = (0, devShared_1.findProjectInfo)(resolvedTarget.htmlPath);
862
- const devScriptAvailable = Boolean(projectInfo.projectDir && projectInfo.packageJson && typeof projectInfo.packageJson.scripts?.dev === 'string');
863
- await (0, commandContext_1.withEnvironment)('project marketing capture', 'Capturing marketing media', async ({ client, env: _env, envConfig }) => {
864
- let currentUsername = '';
811
+ const devScriptAvailable = Boolean(projectInfo.projectDir && projectInfo.packageJson && typeof projectInfo.packageJson.scripts?.dev === "string");
812
+ await (0, commandContext_1.withEnvironment)("project marketing capture", "Capturing marketing media", async ({ client, env: _env, envConfig }) => {
813
+ let currentUsername = "";
865
814
  try {
866
815
  const currentUser = await (0, devShared_1.fetchDevUser)(client);
867
816
  currentUsername = currentUser.username.trim();
@@ -871,7 +820,7 @@ async function marketingCapture(targetArg, options = {}) {
871
820
  return;
872
821
  }
873
822
  if (error instanceof types_1.UnsupportedClientError) {
874
- (0, http_1.handleUnsupportedError)(error, 'Authentication');
823
+ (0, http_1.handleUnsupportedError)(error, "Authentication");
875
824
  process.exitCode = 1;
876
825
  return;
877
826
  }
@@ -879,12 +828,12 @@ async function marketingCapture(targetArg, options = {}) {
879
828
  (0, messages_1.printErrorWithHelp)(`Could not fetch your account (status ${error.status}).`, [
880
829
  'Run "playdrop auth login" to refresh your session.',
881
830
  'Use "playdrop auth whoami" afterwards to verify the current account.',
882
- ], { command: 'project marketing capture' });
831
+ ], { command: "project marketing capture" });
883
832
  process.exitCode = 1;
884
833
  return;
885
834
  }
886
835
  if ((0, devShared_1.isNetworkError)(error)) {
887
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to resolve your account.', 'project marketing capture');
836
+ (0, messages_1.printNetworkIssue)("Could not reach the Playdrop API to resolve your account.", "project marketing capture");
888
837
  process.exitCode = 1;
889
838
  return;
890
839
  }
@@ -892,8 +841,8 @@ async function marketingCapture(targetArg, options = {}) {
892
841
  }
893
842
  const taskLookup = (0, catalogue_1.findAppTaskByFile)(resolvedTarget.htmlPath);
894
843
  if (taskLookup.errors.length > 0) {
895
- (0, messages_1.printErrorWithHelp)(taskLookup.errors[0] || 'Failed to resolve the app task from catalogue.json.', taskLookup.errors.slice(1), {
896
- command: 'project marketing capture',
844
+ (0, messages_1.printErrorWithHelp)(taskLookup.errors[0] || "Failed to resolve the app task from catalogue.json.", taskLookup.errors.slice(1), {
845
+ command: "project marketing capture",
897
846
  });
898
847
  process.exitCode = 1;
899
848
  return;
@@ -906,7 +855,7 @@ async function marketingCapture(targetArg, options = {}) {
906
855
  apiBase: envConfig.apiBase,
907
856
  task: taskLookup.task,
908
857
  creatorUsername: currentUsername,
909
- appBaseUrl: new URL('.', (0, devServer_1.buildLocalDevAppUrl)({
858
+ appBaseUrl: new URL(".", (0, devServer_1.buildLocalDevAppUrl)({
910
859
  creatorUsername: currentUsername,
911
860
  appType: appTypeSlug,
912
861
  appName,
@@ -916,7 +865,7 @@ async function marketingCapture(targetArg, options = {}) {
916
865
  }
917
866
  catch (error) {
918
867
  const formatted = (0, dev_1.formatDevRuntimeAssetManifestFailure)(error);
919
- (0, messages_1.printErrorWithHelp)(formatted.message, formatted.suggestions, { command: 'project marketing capture' });
868
+ (0, messages_1.printErrorWithHelp)(formatted.message, formatted.suggestions, { command: "project marketing capture" });
920
869
  process.exitCode = 1;
921
870
  return;
922
871
  }
@@ -925,8 +874,8 @@ async function marketingCapture(targetArg, options = {}) {
925
874
  const app = loadCatalogueApp(resolvedTarget.cataloguePath, appName);
926
875
  const previewErrors = validateMarketingPreviewConfig(app);
927
876
  if (previewErrors.length > 0) {
928
- const detail = formatMarketingError(new Error(previewErrors[0] || 'Marketing preview configuration is invalid.'));
929
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project marketing capture' });
877
+ const detail = formatMarketingError(new Error(previewErrors[0] || "Marketing preview configuration is invalid."));
878
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project marketing capture" });
930
879
  process.exitCode = 1;
931
880
  return;
932
881
  }
@@ -977,15 +926,15 @@ async function marketingCapture(targetArg, options = {}) {
977
926
  }
978
927
  }
979
928
  if (!serverAlreadyRunning) {
980
- await new Promise(resolve => setTimeout(resolve, 1000));
929
+ await new Promise((resolve) => setTimeout(resolve, 1000));
981
930
  }
982
- const webBase = envConfig.webBase ?? 'https://www.playdrop.ai';
931
+ const webBase = envConfig.webBase ?? "https://www.playdrop.ai";
983
932
  const frameUrlObject = new URL(`${(0, appUrls_1.normalizePlaydropWebBase)(webBase)}/creators/${encodeURIComponent(currentUsername)}/apps/${appTypeSlug}/${encodeURIComponent(appName)}/dev-preview`);
984
- frameUrlObject.searchParams.set('launchCheck', '1');
933
+ frameUrlObject.searchParams.set("launchCheck", "1");
985
934
  const frameUrl = frameUrlObject.toString();
986
- userDataDir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'playdrop-marketing-capture-'));
935
+ userDataDir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "playdrop-marketing-capture-"));
987
936
  const manifestCaptures = [];
988
- let audioValidated = parsedOptions.audioPolicy === 'silent';
937
+ let audioValidated = parsedOptions.audioPolicy === "silent";
989
938
  for (const surface of parsedOptions.surfaces) {
990
939
  const preset = SURFACE_PRESETS[surface];
991
940
  context = await (0, playwright_1.launchPersistentChromiumContext)(userDataDir, {
@@ -996,8 +945,8 @@ async function marketingCapture(targetArg, options = {}) {
996
945
  userAgent: preset.viewport.userAgent,
997
946
  automationOrigin: frameUrlObject.origin,
998
947
  });
999
- const page = context.pages()[0] ?? await context.newPage();
1000
- await page.goto(frameUrl, { waitUntil: 'domcontentloaded' });
948
+ const page = context.pages()[0] ?? (await context.newPage());
949
+ await page.goto(frameUrl, { waitUntil: "domcontentloaded" });
1001
950
  await prepareMarketingPreview(page, surface, parsedOptions.audioPolicy, parsedOptions.seed);
1002
951
  await page.waitForTimeout(1000);
1003
952
  const measurement = await fitWindowToSurface(page, surface);
@@ -1021,11 +970,11 @@ async function marketingCapture(targetArg, options = {}) {
1021
970
  },
1022
971
  });
1023
972
  let audioMetrics = null;
1024
- if (parsedOptions.audioPolicy !== 'silent') {
973
+ if (parsedOptions.audioPolicy !== "silent") {
1025
974
  await startMarketingAudioCapture(page);
1026
975
  }
1027
- runTool('ffmpeg', args, 'ffmpeg_failed');
1028
- if (parsedOptions.audioPolicy !== 'silent') {
976
+ runTool("ffmpeg", args, "ffmpeg_failed");
977
+ if (parsedOptions.audioPolicy !== "silent") {
1029
978
  const audioPath = await stopMarketingAudioCapture(page, outputPaths.capturesDir);
1030
979
  muxMarketingAudio(videoPath, audioPath);
1031
980
  audioMetrics = measureMarketingAudio(videoPath);
@@ -1042,7 +991,7 @@ async function marketingCapture(targetArg, options = {}) {
1042
991
  if (probe.width !== preset.width || probe.height !== preset.height) {
1043
992
  throw new Error(`marketing_capture_dimension_mismatch:${surface}:${probe.width}x${probe.height}`);
1044
993
  }
1045
- if (parsedOptions.audioPolicy !== 'silent' && probe.audioTracks === 0) {
994
+ if (parsedOptions.audioPolicy !== "silent" && probe.audioTracks === 0) {
1046
995
  throw new Error(`marketing_capture_audio_missing:${surface}`);
1047
996
  }
1048
997
  manifestCaptures.push({
@@ -1052,11 +1001,11 @@ async function marketingCapture(targetArg, options = {}) {
1052
1001
  height: preset.height,
1053
1002
  fps: parsedOptions.fps,
1054
1003
  durationSeconds: probe.durationSeconds,
1055
- hasAudio: parsedOptions.audioPolicy !== 'silent',
1004
+ hasAudio: parsedOptions.audioPolicy !== "silent",
1056
1005
  audio: {
1057
1006
  policy: parsedOptions.audioPolicy,
1058
- backgroundMusic: parsedOptions.audioPolicy === 'music-and-sfx',
1059
- sfx: parsedOptions.audioPolicy !== 'silent',
1007
+ backgroundMusic: parsedOptions.audioPolicy === "music-and-sfx",
1008
+ sfx: parsedOptions.audioPolicy !== "silent",
1060
1009
  peakDb: audioMetrics?.peakDb ?? null,
1061
1010
  integratedLufs: audioMetrics?.integratedLufs ?? null,
1062
1011
  },
@@ -1084,14 +1033,14 @@ async function marketingCapture(targetArg, options = {}) {
1084
1033
  fps: parsedOptions.fps,
1085
1034
  audioValidated,
1086
1035
  });
1087
- await (0, promises_1.writeFile)(outputPaths.manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
1088
- await (0, promises_1.writeFile)(outputPaths.reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
1036
+ await (0, promises_1.writeFile)(outputPaths.manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
1037
+ await (0, promises_1.writeFile)(outputPaths.reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
1089
1038
  console.log(`[marketing] Saved capture manifest to ${(0, node_path_1.relative)(process.cwd(), outputPaths.manifestPath) || outputPaths.manifestPath}`);
1090
1039
  console.log(`[marketing] Saved report to ${(0, node_path_1.relative)(process.cwd(), outputPaths.reportPath) || outputPaths.reportPath}`);
1091
1040
  }
1092
1041
  catch (error) {
1093
1042
  const detail = formatMarketingError(error instanceof Error ? error : new Error(String(error)));
1094
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project marketing capture' });
1043
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project marketing capture" });
1095
1044
  process.exitCode = 1;
1096
1045
  }
1097
1046
  finally {