@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
@@ -95,7 +95,7 @@ const MAX_FPS = 120;
95
95
  const MIN_SUPPORTED_MACOS_MAJOR = 26;
96
96
  const MIN_SUPPORTED_MACOS_MINOR = 4;
97
97
  const LISTING_CAPTURE_HOOK_TIMEOUT_MS = 60000;
98
- const LISTING_CAPTURE_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';
98
+ const LISTING_CAPTURE_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";
99
99
  const SURFACE_CAPTURE_DIMENSIONS = {
100
100
  DESKTOP: { width: 1280, height: 720 },
101
101
  MOBILE_LANDSCAPE: { width: 844, height: 390 },
@@ -107,15 +107,15 @@ const MIN_LISTING_VISIBLE_PIXEL_RATIO = 0.005;
107
107
  const MIN_LISTING_MOTION_MEAN_DELTA = 0.002;
108
108
  const MIN_LISTING_MOTION_CHANGED_PIXEL_RATIO = 0.01;
109
109
  const SURFACE_OUTPUT_SLUG = {
110
- DESKTOP: 'desktop',
111
- MOBILE_LANDSCAPE: 'mobile-landscape',
112
- MOBILE_PORTRAIT: 'mobile-portrait',
110
+ DESKTOP: "desktop",
111
+ MOBILE_LANDSCAPE: "mobile-landscape",
112
+ MOBILE_PORTRAIT: "mobile-portrait",
113
113
  };
114
114
  function resolveListingCaptureRouteSegment(previewable) {
115
115
  if (!previewable) {
116
- throw new Error('listing_preview_support_missing');
116
+ throw new Error("listing_preview_support_missing");
117
117
  }
118
- return 'dev-preview';
118
+ return "dev-preview";
119
119
  }
120
120
  function resolveCaptureListingDevRouterPort(env = process.env) {
121
121
  return (0, dev_1.resolveCliDevRouterPort)(env);
@@ -125,23 +125,23 @@ function resolveListingCaptureLocalDevPort(devRouterPort) {
125
125
  }
126
126
  function buildListingCaptureFrameUrl({ webBase, currentUsername, appTypeSlug, appName, routeSegment, localDevPort, captureSession, }) {
127
127
  const frameUrlObject = new URL(`${(0, appUrls_1.normalizePlaydropWebBase)(webBase)}/creators/${encodeURIComponent(currentUsername)}/apps/${appTypeSlug}/${encodeURIComponent(appName)}/${routeSegment}`);
128
- frameUrlObject.searchParams.set('launchCheck', '1');
129
- frameUrlObject.searchParams.set('captureShell', 'listing');
130
- frameUrlObject.searchParams.set('mobileFrameHost', 'admin');
128
+ frameUrlObject.searchParams.set("launchCheck", "1");
129
+ frameUrlObject.searchParams.set("captureShell", "listing");
130
+ frameUrlObject.searchParams.set("mobileFrameHost", "admin");
131
131
  if (localDevPort !== null) {
132
- frameUrlObject.searchParams.set('localDevPort', String(localDevPort));
132
+ frameUrlObject.searchParams.set("localDevPort", String(localDevPort));
133
133
  }
134
134
  (0, appUrls_1.appendTaskCaptureSession)(frameUrlObject, captureSession);
135
135
  return frameUrlObject.toString();
136
136
  }
137
137
  function resolveListingCaptureSceneId(width, height) {
138
- return height > width ? 'listing-portrait' : 'listing-landscape';
138
+ return height > width ? "listing-portrait" : "listing-landscape";
139
139
  }
140
140
  function parsePositiveNumber(raw, fallback, fieldName, { minimum = 0, maximum = Number.POSITIVE_INFINITY, integer = false, } = {}) {
141
141
  if (raw === undefined) {
142
142
  return fallback;
143
143
  }
144
- const parsed = typeof raw === 'number' ? raw : Number.parseFloat(String(raw));
144
+ const parsed = typeof raw === "number" ? raw : Number.parseFloat(String(raw));
145
145
  if (!Number.isFinite(parsed)) {
146
146
  throw new Error(`${fieldName}_invalid`);
147
147
  }
@@ -154,27 +154,27 @@ function parsePositiveNumber(raw, fallback, fieldName, { minimum = 0, maximum =
154
154
  return parsed;
155
155
  }
156
156
  function parseCaptureListingOptions(targetArg, options = {}) {
157
- const durationSeconds = parsePositiveNumber(options.duration, DEFAULT_DURATION_SECONDS, 'duration', {
157
+ const durationSeconds = parsePositiveNumber(options.duration, DEFAULT_DURATION_SECONDS, "duration", {
158
158
  minimum: MIN_CAPTURE_SECONDS,
159
159
  maximum: MAX_CAPTURE_SECONDS,
160
160
  });
161
161
  const explicitDimensions = options.width !== undefined || options.height !== undefined;
162
- const width = parsePositiveNumber(options.width, DEFAULT_WIDTH, 'width', {
162
+ const width = parsePositiveNumber(options.width, DEFAULT_WIDTH, "width", {
163
163
  minimum: MIN_DIMENSION,
164
164
  maximum: MAX_DIMENSION,
165
165
  integer: true,
166
166
  });
167
- const height = parsePositiveNumber(options.height, DEFAULT_HEIGHT, 'height', {
167
+ const height = parsePositiveNumber(options.height, DEFAULT_HEIGHT, "height", {
168
168
  minimum: MIN_DIMENSION,
169
169
  maximum: MAX_DIMENSION,
170
170
  integer: true,
171
171
  });
172
- const fps = parsePositiveNumber(options.fps, DEFAULT_FPS, 'fps', {
172
+ const fps = parsePositiveNumber(options.fps, DEFAULT_FPS, "fps", {
173
173
  minimum: 1,
174
174
  maximum: MAX_FPS,
175
175
  integer: true,
176
176
  });
177
- const posterAtSeconds = parsePositiveNumber(options.posterAt, DEFAULT_POSTER_AT_SECONDS, 'poster_at', {
177
+ const posterAtSeconds = parsePositiveNumber(options.posterAt, DEFAULT_POSTER_AT_SECONDS, "poster_at", {
178
178
  minimum: 0,
179
179
  maximum: durationSeconds,
180
180
  });
@@ -198,36 +198,34 @@ function parseCaptureListingOptions(targetArg, options = {}) {
198
198
  function resolveCaptureListingExplicitOutputDir(outputDirInput, cwdResolvedOutputDir, projectDir) {
199
199
  if (!outputDirInput || !cwdResolvedOutputDir)
200
200
  return null;
201
- return (0, node_path_1.isAbsolute)(outputDirInput)
202
- ? cwdResolvedOutputDir
203
- : (0, node_path_1.resolve)(projectDir, outputDirInput);
201
+ return (0, node_path_1.isAbsolute)(outputDirInput) ? cwdResolvedOutputDir : (0, node_path_1.resolve)(projectDir, outputDirInput);
204
202
  }
205
203
  function readMacOsVersion() {
206
- const result = (0, node_child_process_1.spawnSync)('sw_vers', ['-productVersion'], {
207
- encoding: 'utf8',
204
+ const result = (0, node_child_process_1.spawnSync)("sw_vers", ["-productVersion"], {
205
+ encoding: "utf8",
208
206
  });
209
207
  if (result.status !== 0) {
210
- throw new Error('macos_version_probe_failed');
208
+ throw new Error("macos_version_probe_failed");
211
209
  }
212
210
  return result.stdout.trim();
213
211
  }
214
- function assertSupportedListingEnvironment(platform = process.platform, macosVersion = platform === 'darwin' ? readMacOsVersion() : '') {
215
- if (platform !== 'darwin') {
216
- throw new Error('unsupported_platform');
217
- }
218
- const [majorRaw, minorRaw] = macosVersion.split('.');
219
- const major = Number.parseInt(majorRaw ?? '', 10);
220
- const minor = Number.parseInt(minorRaw ?? '', 10);
221
- if (!Number.isInteger(major)
222
- || !Number.isInteger(minor)
223
- || major !== MIN_SUPPORTED_MACOS_MAJOR
224
- || minor < MIN_SUPPORTED_MACOS_MINOR) {
212
+ function assertSupportedListingEnvironment(platform = process.platform, macosVersion = platform === "darwin" ? readMacOsVersion() : "") {
213
+ if (platform !== "darwin") {
214
+ throw new Error("unsupported_platform");
215
+ }
216
+ const [majorRaw, minorRaw] = macosVersion.split(".");
217
+ const major = Number.parseInt(majorRaw ?? "", 10);
218
+ const minor = Number.parseInt(minorRaw ?? "", 10);
219
+ if (!Number.isInteger(major) ||
220
+ !Number.isInteger(minor) ||
221
+ major !== MIN_SUPPORTED_MACOS_MAJOR ||
222
+ minor < MIN_SUPPORTED_MACOS_MINOR) {
225
223
  throw new Error(`unsupported_macos_version:${macosVersion}`);
226
224
  }
227
225
  }
228
226
  function commandExists(command) {
229
- const result = (0, node_child_process_1.spawnSync)('which', [command], {
230
- encoding: 'utf8',
227
+ const result = (0, node_child_process_1.spawnSync)("which", [command], {
228
+ encoding: "utf8",
231
229
  });
232
230
  return result.status === 0 && result.stdout.trim().length > 0;
233
231
  }
@@ -239,20 +237,20 @@ function resolveListingRecorderPath(workerHome) {
239
237
  }
240
238
  function buildTimestampFolder(date = new Date()) {
241
239
  const iso = date.toISOString();
242
- return iso.replace(/[:]/g, '-').replace(/\.\d{3}Z$/, 'Z');
240
+ return iso.replace(/[:]/g, "-").replace(/\.\d{3}Z$/, "Z");
243
241
  }
244
242
  async function ensureOutputPaths(appName, explicitOutputDir) {
245
243
  const outputDir = explicitOutputDir
246
244
  ? explicitOutputDir
247
- : (0, node_path_1.resolve)(process.cwd(), 'output', 'listing-capture', appName, buildTimestampFolder());
245
+ : (0, node_path_1.resolve)(process.cwd(), "output", "listing-capture", appName, buildTimestampFolder());
248
246
  await (0, promises_1.mkdir)(outputDir, { recursive: true });
249
247
  return {
250
248
  outputDir,
251
- reportPath: (0, node_path_1.join)(outputDir, 'capture-report.json'),
249
+ reportPath: (0, node_path_1.join)(outputDir, "capture-report.json"),
252
250
  };
253
251
  }
254
252
  function buildSurfaceOutputPaths(outputDir, surface, useSurfacePrefix) {
255
- const prefix = useSurfacePrefix ? `${SURFACE_OUTPUT_SLUG[surface]}-` : '';
253
+ const prefix = useSurfacePrefix ? `${SURFACE_OUTPUT_SLUG[surface]}-` : "";
256
254
  return {
257
255
  rawVideoPath: (0, node_path_1.join)(outputDir, `${prefix}listing-raw.mp4`),
258
256
  metadataPath: (0, node_path_1.join)(outputDir, `${prefix}listing-raw.json`),
@@ -261,9 +259,7 @@ function buildSurfaceOutputPaths(outputDir, surface, useSurfacePrefix) {
261
259
  };
262
260
  }
263
261
  function resolveWorkerCaptureOutputDir(projectDir, isWorkerGameTask) {
264
- return isWorkerGameTask
265
- ? (0, node_path_1.join)(projectDir, 'assets', 'marketing', 'playdrop', 'capture')
266
- : null;
262
+ return isWorkerGameTask ? (0, node_path_1.join)(projectDir, "assets", "marketing", "playdrop", "capture") : null;
267
263
  }
268
264
  function resolveCaptureDimensions(surface, parsedOptions) {
269
265
  if (parsedOptions.explicitDimensions) {
@@ -275,7 +271,7 @@ function resolveCaptureDimensions(surface, parsedOptions) {
275
271
  return SURFACE_CAPTURE_DIMENSIONS[surface];
276
272
  }
277
273
  function resolveListingCaptureBrowserContextOptions(surface, dimensions) {
278
- if (surface === 'DESKTOP') {
274
+ if (surface === "DESKTOP") {
279
275
  return { viewport: null };
280
276
  }
281
277
  return {
@@ -291,26 +287,26 @@ function resolveListingCaptureBrowserContextOptions(surface, dimensions) {
291
287
  }
292
288
  async function grantListingBrowserLocalNetworkAccess(context, origin) {
293
289
  const grantPermissions = context.grantPermissions;
294
- if (typeof grantPermissions !== 'function') {
290
+ if (typeof grantPermissions !== "function") {
295
291
  return;
296
292
  }
297
- await grantPermissions.call(context, ['local-network-access'], { origin });
293
+ await grantPermissions.call(context, ["local-network-access"], { origin });
298
294
  }
299
295
  async function launchListingBrowser(initialViewport, automationOrigin, contextOptions) {
300
- const playwright = await Promise.resolve().then(() => __importStar(require('playwright-core')));
296
+ const playwright = await Promise.resolve().then(() => __importStar(require("playwright-core")));
301
297
  const args = [
302
- '--no-sandbox',
303
- '--disable-web-security',
304
- '--app=about:blank',
298
+ "--no-sandbox",
299
+ "--disable-web-security",
300
+ "--app=about:blank",
305
301
  `--window-size=${initialViewport.width},${initialViewport.height}`,
306
- '--autoplay-policy=no-user-gesture-required',
307
- '--disable-extensions',
308
- '--disable-background-networking',
309
- '--disable-component-update',
310
- '--disable-sync',
311
- '--metrics-recording-only',
312
- '--no-first-run',
313
- '--no-default-browser-check',
302
+ "--autoplay-policy=no-user-gesture-required",
303
+ "--disable-extensions",
304
+ "--disable-background-networking",
305
+ "--disable-component-update",
306
+ "--disable-sync",
307
+ "--metrics-recording-only",
308
+ "--no-first-run",
309
+ "--no-default-browser-check",
314
310
  ];
315
311
  try {
316
312
  const server = await playwright.chromium.launchServer({
@@ -320,7 +316,7 @@ async function launchListingBrowser(initialViewport, automationOrigin, contextOp
320
316
  const processId = server.process()?.pid ?? 0;
321
317
  if (processId <= 0) {
322
318
  await server.close();
323
- throw new Error('browser_process_missing');
319
+ throw new Error("browser_process_missing");
324
320
  }
325
321
  const browser = await playwright.chromium.connect(server.wsEndpoint());
326
322
  const context = await browser.newContext(contextOptions);
@@ -355,23 +351,23 @@ async function launchListingBrowser(initialViewport, automationOrigin, contextOp
355
351
  };
356
352
  }
357
353
  catch (error) {
358
- throw (0, playwright_1.createPlaywrightLaunchError)('playdrop', error);
354
+ throw (0, playwright_1.createPlaywrightLaunchError)("playdrop", error);
359
355
  }
360
356
  }
361
357
  async function waitForHostedGameMeasurement(page, timeoutMs) {
362
358
  const startedAt = Date.now();
363
- let lastSignature = '';
359
+ let lastSignature = "";
364
360
  let stableHits = 0;
365
361
  while (Date.now() - startedAt < timeoutMs) {
366
362
  try {
367
363
  const measurement = await page.evaluate((selector) => {
368
364
  const frame = document.querySelector(selector);
369
365
  if (!(frame instanceof HTMLIFrameElement)) {
370
- throw new Error('hosted_game_frame_missing');
366
+ throw new Error("hosted_game_frame_missing");
371
367
  }
372
368
  const rect = frame.getBoundingClientRect();
373
369
  if (rect.width <= 0 || rect.height <= 0) {
374
- throw new Error('hosted_game_frame_hidden');
370
+ throw new Error("hosted_game_frame_hidden");
375
371
  }
376
372
  return {
377
373
  outerWidth: window.outerWidth,
@@ -413,17 +409,19 @@ async function waitForHostedGameMeasurement(page, timeoutMs) {
413
409
  }
414
410
  }
415
411
  catch (error) {
416
- if (error instanceof Error && error.message !== 'hosted_game_frame_missing' && error.message !== 'hosted_game_frame_hidden') {
412
+ if (error instanceof Error &&
413
+ error.message !== "hosted_game_frame_missing" &&
414
+ error.message !== "hosted_game_frame_hidden") {
417
415
  throw error;
418
416
  }
419
417
  }
420
418
  await page.waitForTimeout(250);
421
419
  }
422
- throw new Error('hosted_game_measurement_timeout');
420
+ throw new Error("hosted_game_measurement_timeout");
423
421
  }
424
422
  async function waitForHostedGameFrame(page, timeoutMs) {
425
423
  const frameHandle = await page.waitForSelector(CAPTURE_FRAME_SELECTOR, {
426
- state: 'attached',
424
+ state: "attached",
427
425
  timeout: timeoutMs,
428
426
  });
429
427
  const startedAt = Date.now();
@@ -434,19 +432,19 @@ async function waitForHostedGameFrame(page, timeoutMs) {
434
432
  }
435
433
  await page.waitForTimeout(200);
436
434
  }
437
- throw new Error('hosted_game_frame_missing');
435
+ throw new Error("hosted_game_frame_missing");
438
436
  }
439
437
  async function prepareHostedListingScene(page, sceneId) {
440
438
  const frame = await waitForHostedGameFrame(page, LISTING_CAPTURE_HOOK_TIMEOUT_MS);
441
439
  await frame.waitForFunction(() => {
442
440
  const captureWindow = window;
443
- return typeof captureWindow.__listingCapture?.prepare === 'function';
441
+ return typeof captureWindow.__listingCapture?.prepare === "function";
444
442
  }, undefined, { timeout: LISTING_CAPTURE_HOOK_TIMEOUT_MS });
445
443
  await frame.evaluate(async (requestedSceneId) => {
446
444
  const captureWindow = window;
447
445
  const hook = captureWindow.__listingCapture;
448
- if (!hook || typeof hook.prepare !== 'function') {
449
- throw new Error('listing_capture_hook_missing');
446
+ if (!hook || typeof hook.prepare !== "function") {
447
+ throw new Error("listing_capture_hook_missing");
450
448
  }
451
449
  await hook.prepare(requestedSceneId);
452
450
  }, sceneId);
@@ -455,38 +453,34 @@ async function startHostedListingAudioCapture(page) {
455
453
  const frame = await waitForHostedGameFrame(page, 20000);
456
454
  await frame.waitForFunction(() => {
457
455
  const captureWindow = window;
458
- return typeof captureWindow.__listingCapture?.startAudioCapture === 'function';
456
+ return typeof captureWindow.__listingCapture?.startAudioCapture === "function";
459
457
  }, undefined, { timeout: 20000 });
460
458
  await frame.evaluate(async () => {
461
459
  const captureWindow = window;
462
460
  const hook = captureWindow.__listingCapture;
463
- if (!hook || typeof hook.startAudioCapture !== 'function') {
464
- throw new Error('listing_audio_capture_hook_missing');
461
+ if (!hook || typeof hook.startAudioCapture !== "function") {
462
+ throw new Error("listing_audio_capture_hook_missing");
465
463
  }
466
464
  await hook.startAudioCapture();
467
465
  });
468
466
  }
469
467
  function assertExportedListingAudio(value) {
470
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
471
- throw new Error('listing_audio_capture_export_missing');
472
- }
473
- const mimeType = typeof value.mimeType === 'string'
474
- ? value.mimeType.trim()
475
- : '';
476
- const base64 = typeof value.base64 === 'string'
477
- ? value.base64.trim()
478
- : '';
468
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
469
+ throw new Error("listing_audio_capture_export_missing");
470
+ }
471
+ const mimeType = typeof value.mimeType === "string" ? value.mimeType.trim() : "";
472
+ const base64 = typeof value.base64 === "string" ? value.base64.trim() : "";
479
473
  if (!mimeType || !base64) {
480
- throw new Error('listing_audio_capture_export_missing');
474
+ throw new Error("listing_audio_capture_export_missing");
481
475
  }
482
476
  return { mimeType, base64 };
483
477
  }
484
478
  function resolveExportedAudioFileName(mimeType) {
485
- if (mimeType.includes('webm')) {
486
- return 'listing-audio.webm';
479
+ if (mimeType.includes("webm")) {
480
+ return "listing-audio.webm";
487
481
  }
488
- if (mimeType.includes('mp4') || mimeType.includes('aac') || mimeType.includes('m4a')) {
489
- return 'listing-audio.m4a';
482
+ if (mimeType.includes("mp4") || mimeType.includes("aac") || mimeType.includes("m4a")) {
483
+ return "listing-audio.m4a";
490
484
  }
491
485
  throw new Error(`unsupported_listing_audio_mime_type:${mimeType}`);
492
486
  }
@@ -495,13 +489,13 @@ async function stopHostedListingAudioCapture(page, outputDir) {
495
489
  const exportedAudio = assertExportedListingAudio(await frame.evaluate(async () => {
496
490
  const captureWindow = window;
497
491
  const hook = captureWindow.__listingCapture;
498
- if (!hook || typeof hook.stopAudioCapture !== 'function') {
499
- throw new Error('listing_audio_capture_hook_missing');
492
+ if (!hook || typeof hook.stopAudioCapture !== "function") {
493
+ throw new Error("listing_audio_capture_hook_missing");
500
494
  }
501
495
  return hook.stopAudioCapture();
502
496
  }));
503
497
  const filePath = (0, node_path_1.join)(outputDir, resolveExportedAudioFileName(exportedAudio.mimeType));
504
- await (0, promises_1.writeFile)(filePath, Buffer.from(exportedAudio.base64, 'base64'));
498
+ await (0, promises_1.writeFile)(filePath, Buffer.from(exportedAudio.base64, "base64"));
505
499
  return filePath;
506
500
  }
507
501
  async function assertHostedListingAudioCaptureContract(page, outputDir) {
@@ -513,13 +507,9 @@ async function fitWindowToRequestedGameplay(page, requestedWidth, requestedHeigh
513
507
  const cdpSession = await page.context().newCDPSession(page);
514
508
  let measurement = await waitForHostedGameMeasurement(page, 15000);
515
509
  for (let attempt = 0; attempt < 5; attempt += 1) {
516
- const windowState = await cdpSession.send('Browser.getWindowForTarget');
517
- const currentWidth = typeof windowState.bounds.width === 'number'
518
- ? windowState.bounds.width
519
- : Math.round(measurement.outerWidth);
520
- const currentHeight = typeof windowState.bounds.height === 'number'
521
- ? windowState.bounds.height
522
- : Math.round(measurement.outerHeight);
510
+ const windowState = await cdpSession.send("Browser.getWindowForTarget");
511
+ const currentWidth = typeof windowState.bounds.width === "number" ? windowState.bounds.width : Math.round(measurement.outerWidth);
512
+ const currentHeight = typeof windowState.bounds.height === "number" ? windowState.bounds.height : Math.round(measurement.outerHeight);
523
513
  const deltaWidth = requestedWidth - Math.round(measurement.iframeRect.width);
524
514
  const deltaHeight = requestedHeight - Math.round(measurement.iframeRect.height);
525
515
  if (Math.abs(deltaWidth) <= 1 && Math.abs(deltaHeight) <= 1) {
@@ -531,7 +521,7 @@ async function fitWindowToRequestedGameplay(page, requestedWidth, requestedHeigh
531
521
  }
532
522
  const nextWidth = Math.max(400, currentWidth + deltaWidth);
533
523
  const nextHeight = Math.max(300, currentHeight + deltaHeight);
534
- await cdpSession.send('Browser.setWindowBounds', {
524
+ await cdpSession.send("Browser.setWindowBounds", {
535
525
  windowId: windowState.windowId,
536
526
  bounds: {
537
527
  width: nextWidth,
@@ -541,7 +531,7 @@ async function fitWindowToRequestedGameplay(page, requestedWidth, requestedHeigh
541
531
  await page.waitForTimeout(800);
542
532
  measurement = await waitForHostedGameMeasurement(page, 8000);
543
533
  }
544
- throw new Error('hosted_game_resize_failed');
534
+ throw new Error("hosted_game_resize_failed");
545
535
  }
546
536
  function assertListingCaptureWindowCanContainViewport(measurement, windowBounds) {
547
537
  const requiredWidth = Math.ceil(measurement.innerWidth);
@@ -557,33 +547,33 @@ function roundCropValue(value) {
557
547
  }
558
548
  function computeRecordedCrop(measurement, recorder, rawWidth, rawHeight) {
559
549
  if (measurement.outerWidth <= 0 || measurement.outerHeight <= 0) {
560
- throw new Error('invalid_window_geometry');
550
+ throw new Error("invalid_window_geometry");
561
551
  }
562
552
  if (measurement.innerWidth <= 0 || measurement.innerHeight <= 0) {
563
- throw new Error('invalid_viewport_geometry');
553
+ throw new Error("invalid_viewport_geometry");
564
554
  }
565
555
  if (rawWidth <= 0 || rawHeight <= 0) {
566
- throw new Error('invalid_raw_dimensions');
556
+ throw new Error("invalid_raw_dimensions");
567
557
  }
568
558
  const nativeOuterWidth = recorder.windowFramePoints.width;
569
559
  const nativeOuterHeight = recorder.windowFramePoints.height;
570
560
  if (nativeOuterWidth <= 0 || nativeOuterHeight <= 0) {
571
- throw new Error('invalid_native_window_geometry');
561
+ throw new Error("invalid_native_window_geometry");
572
562
  }
573
563
  const horizontalChrome = nativeOuterWidth - measurement.innerWidth;
574
564
  const verticalChrome = nativeOuterHeight - measurement.innerHeight;
575
565
  if (horizontalChrome < 0 || verticalChrome < 0) {
576
- throw new Error('invalid_chrome_geometry');
566
+ throw new Error("invalid_chrome_geometry");
577
567
  }
578
- const usesSyntheticMobileWindow = Math.abs(measurement.outerWidth - measurement.innerWidth) <= 1
579
- && Math.abs(measurement.outerHeight - measurement.innerHeight) <= 1
580
- && (Math.abs(nativeOuterWidth - measurement.outerWidth) > 1
581
- || Math.abs(nativeOuterHeight - measurement.outerHeight) > 1);
568
+ const usesSyntheticMobileWindow = Math.abs(measurement.outerWidth - measurement.innerWidth) <= 1 &&
569
+ Math.abs(measurement.outerHeight - measurement.innerHeight) <= 1 &&
570
+ (Math.abs(nativeOuterWidth - measurement.outerWidth) > 1 ||
571
+ Math.abs(nativeOuterHeight - measurement.outerHeight) > 1);
582
572
  const leftChrome = usesSyntheticMobileWindow ? 0 : horizontalChrome / 2;
583
573
  const bottomChrome = usesSyntheticMobileWindow ? 0 : leftChrome;
584
574
  const topChrome = verticalChrome - bottomChrome;
585
575
  if (topChrome < 0) {
586
- throw new Error('invalid_vertical_chrome_geometry');
576
+ throw new Error("invalid_vertical_chrome_geometry");
587
577
  }
588
578
  const cropLeftCss = leftChrome + measurement.iframeRect.left;
589
579
  const cropTopCss = topChrome + measurement.iframeRect.top;
@@ -594,60 +584,50 @@ function computeRecordedCrop(measurement, recorder, rawWidth, rawHeight) {
594
584
  const width = roundCropValue(measurement.iframeRect.width * scaleX);
595
585
  const height = roundCropValue(measurement.iframeRect.height * scaleY);
596
586
  if (x < 0 || y < 0 || width <= 0 || height <= 0) {
597
- throw new Error('invalid_crop_geometry');
587
+ throw new Error("invalid_crop_geometry");
598
588
  }
599
589
  if (x + width > rawWidth || y + height > rawHeight) {
600
- throw new Error('crop_out_of_bounds');
590
+ throw new Error("crop_out_of_bounds");
601
591
  }
602
592
  return { x, y, width, height };
603
593
  }
604
594
  function runTool(command, args, failureCode, deadlineAt) {
605
595
  const result = (0, node_child_process_1.spawnSync)(command, args, {
606
- encoding: 'utf8',
596
+ encoding: "utf8",
607
597
  maxBuffer: 20 * 1024 * 1024,
608
598
  timeout: (0, listingCaptureLease_1.remainingListingCaptureTime)(deadlineAt),
609
- killSignal: 'SIGKILL',
599
+ killSignal: "SIGKILL",
610
600
  });
611
- if (result.error?.code === 'ETIMEDOUT') {
612
- throw new Error('listing_capture_timeout');
601
+ if (result.error?.code === "ETIMEDOUT") {
602
+ throw new Error("listing_capture_timeout");
613
603
  }
614
604
  if (result.status !== 0) {
615
- const stderr = result.stderr?.trim() || '';
616
- const stdout = result.stdout?.trim() || '';
617
- const combined = [stdout, stderr].filter(Boolean).join('\n');
605
+ const stderr = result.stderr?.trim() || "";
606
+ const stdout = result.stdout?.trim() || "";
607
+ const combined = [stdout, stderr].filter(Boolean).join("\n");
618
608
  throw new Error(`${failureCode}:${combined}`);
619
609
  }
620
610
  return {
621
- stdout: result.stdout || '',
622
- stderr: result.stderr || '',
611
+ stdout: result.stdout || "",
612
+ stderr: result.stderr || "",
623
613
  };
624
614
  }
625
615
  async function probeMediaFile(filePath, deadlineAt) {
626
- const { stdout } = runTool('ffprobe', [
627
- '-v',
628
- 'error',
629
- '-show_streams',
630
- '-show_format',
631
- '-of',
632
- 'json',
633
- filePath,
634
- ], 'ffprobe_failed', deadlineAt);
616
+ const { stdout } = runTool("ffprobe", ["-v", "error", "-show_streams", "-show_format", "-of", "json", filePath], "ffprobe_failed", deadlineAt);
635
617
  return JSON.parse(stdout);
636
618
  }
637
619
  async function computeFileSha256(filePath) {
638
- return (0, node_crypto_1.createHash)('sha256').update(await (0, promises_1.readFile)(filePath)).digest('hex');
620
+ return (0, node_crypto_1.createHash)("sha256")
621
+ .update(await (0, promises_1.readFile)(filePath))
622
+ .digest("hex");
639
623
  }
640
624
  async function readListingValidationPixels(filePath) {
641
- return (0, sharp_1.default)(filePath)
642
- .resize(64, 64, { fit: 'fill' })
643
- .greyscale()
644
- .raw()
645
- .toBuffer();
625
+ return (0, sharp_1.default)(filePath).resize(64, 64, { fit: "fill" }).greyscale().raw().toBuffer();
646
626
  }
647
627
  async function measureListingFrameVisibility(filePath) {
648
628
  const pixels = await readListingValidationPixels(filePath);
649
629
  if (pixels.length === 0) {
650
- throw new Error('listing_capture_frame_pixels_missing');
630
+ throw new Error("listing_capture_frame_pixels_missing");
651
631
  }
652
632
  let total = 0;
653
633
  let visiblePixels = 0;
@@ -663,8 +643,8 @@ async function measureListingFrameVisibility(filePath) {
663
643
  }
664
644
  async function assertListingCaptureFrameVisible(surface, label, filePath) {
665
645
  const visibility = await measureListingFrameVisibility(filePath);
666
- if (visibility.meanLuma < MIN_LISTING_FRAME_MEAN_LUMA
667
- && visibility.visiblePixelRatio < MIN_LISTING_VISIBLE_PIXEL_RATIO) {
646
+ if (visibility.meanLuma < MIN_LISTING_FRAME_MEAN_LUMA &&
647
+ visibility.visiblePixelRatio < MIN_LISTING_VISIBLE_PIXEL_RATIO) {
668
648
  throw new Error(`listing_capture_black_frame:${surface}:${label}`);
669
649
  }
670
650
  }
@@ -674,7 +654,7 @@ async function measureListingFrameMotion(firstPath, lastPath) {
674
654
  readListingValidationPixels(lastPath),
675
655
  ]);
676
656
  if (first.length !== last.length || first.length === 0) {
677
- throw new Error('listing_capture_frame_shape_mismatch');
657
+ throw new Error("listing_capture_frame_shape_mismatch");
678
658
  }
679
659
  let deltaTotal = 0;
680
660
  let changedPixels = 0;
@@ -690,39 +670,39 @@ async function measureListingFrameMotion(firstPath, lastPath) {
690
670
  };
691
671
  }
692
672
  function calculateListingFrameSimilarity(referencePath, capturedPath, deadlineAt) {
693
- const { stderr } = runTool('ffmpeg', [
694
- '-hide_banner',
695
- '-i',
673
+ const { stderr } = runTool("ffmpeg", [
674
+ "-hide_banner",
675
+ "-i",
696
676
  referencePath,
697
- '-i',
677
+ "-i",
698
678
  capturedPath,
699
- '-filter_complex',
700
- '[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',
701
- '-f',
702
- 'null',
703
- '-',
704
- ], 'ffmpeg_failed', deadlineAt);
679
+ "-filter_complex",
680
+ "[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",
681
+ "-f",
682
+ "null",
683
+ "-",
684
+ ], "ffmpeg_failed", deadlineAt);
705
685
  const match = stderr.match(/All:([0-9.]+)/);
706
686
  if (!match) {
707
- throw new Error('listing_capture_similarity_missing');
687
+ throw new Error("listing_capture_similarity_missing");
708
688
  }
709
689
  return Number.parseFloat(match[1]);
710
690
  }
711
691
  function assertListingCapturePixelMetrics(surface, metrics) {
712
- if (!Number.isFinite(metrics.referenceFrameSimilarity)
713
- || metrics.referenceFrameSimilarity < MIN_LISTING_REFERENCE_FRAME_SIMILARITY) {
714
- throw new Error(`listing_capture_wrong_game:${surface}:${Number.isFinite(metrics.referenceFrameSimilarity) ? metrics.referenceFrameSimilarity.toFixed(3) : 'unknown'}`);
692
+ if (!Number.isFinite(metrics.referenceFrameSimilarity) ||
693
+ metrics.referenceFrameSimilarity < MIN_LISTING_REFERENCE_FRAME_SIMILARITY) {
694
+ throw new Error(`listing_capture_wrong_game:${surface}:${Number.isFinite(metrics.referenceFrameSimilarity) ? metrics.referenceFrameSimilarity.toFixed(3) : "unknown"}`);
715
695
  }
716
- if (metrics.firstFrameMeanLuma < MIN_LISTING_FRAME_MEAN_LUMA
717
- && metrics.firstFrameVisiblePixelRatio < MIN_LISTING_VISIBLE_PIXEL_RATIO) {
696
+ if (metrics.firstFrameMeanLuma < MIN_LISTING_FRAME_MEAN_LUMA &&
697
+ metrics.firstFrameVisiblePixelRatio < MIN_LISTING_VISIBLE_PIXEL_RATIO) {
718
698
  throw new Error(`listing_capture_black_frame:${surface}:first`);
719
699
  }
720
- if (metrics.posterFrameMeanLuma < MIN_LISTING_FRAME_MEAN_LUMA
721
- && metrics.posterFrameVisiblePixelRatio < MIN_LISTING_VISIBLE_PIXEL_RATIO) {
700
+ if (metrics.posterFrameMeanLuma < MIN_LISTING_FRAME_MEAN_LUMA &&
701
+ metrics.posterFrameVisiblePixelRatio < MIN_LISTING_VISIBLE_PIXEL_RATIO) {
722
702
  throw new Error(`listing_capture_black_frame:${surface}:poster`);
723
703
  }
724
- if (metrics.motionMeanDelta < MIN_LISTING_MOTION_MEAN_DELTA
725
- && metrics.motionChangedPixelRatio < MIN_LISTING_MOTION_CHANGED_PIXEL_RATIO) {
704
+ if (metrics.motionMeanDelta < MIN_LISTING_MOTION_MEAN_DELTA &&
705
+ metrics.motionChangedPixelRatio < MIN_LISTING_MOTION_CHANGED_PIXEL_RATIO) {
726
706
  throw new Error(`listing_capture_stale_video:${surface}`);
727
707
  }
728
708
  }
@@ -742,25 +722,16 @@ async function validateListingCapturePixels(input) {
742
722
  motionChangedPixelRatio: motion.changedPixelRatio,
743
723
  };
744
724
  assertListingCapturePixelMetrics(input.surface, metrics);
745
- return { status: 'passed', ...metrics };
725
+ return { status: "passed", ...metrics };
746
726
  }
747
727
  function extractListingValidationFrame(videoPath, atSeconds, outputPath, deadlineAt) {
748
- runTool('ffmpeg', [
749
- '-y',
750
- '-ss',
751
- String(atSeconds),
752
- '-i',
753
- videoPath,
754
- '-frames:v',
755
- '1',
756
- outputPath,
757
- ], 'ffmpeg_failed', deadlineAt);
728
+ runTool("ffmpeg", ["-y", "-ss", String(atSeconds), "-i", videoPath, "-frames:v", "1", outputPath], "ffmpeg_failed", deadlineAt);
758
729
  }
759
730
  function parseFrameRate(raw) {
760
731
  if (!raw) {
761
732
  return null;
762
733
  }
763
- const parts = raw.split('/');
734
+ const parts = raw.split("/");
764
735
  if (parts.length !== 2) {
765
736
  const parsed = Number.parseFloat(raw);
766
737
  return Number.isFinite(parsed) ? parsed : null;
@@ -773,144 +744,152 @@ function parseFrameRate(raw) {
773
744
  return numerator / denominator;
774
745
  }
775
746
  function extractVideoStream(probe) {
776
- const videoStream = probe.streams?.find(stream => stream.codec_type === 'video');
777
- if (!videoStream || typeof videoStream.width !== 'number' || typeof videoStream.height !== 'number') {
778
- throw new Error('video_stream_missing');
747
+ const videoStream = probe.streams?.find((stream) => stream.codec_type === "video");
748
+ if (!videoStream || typeof videoStream.width !== "number" || typeof videoStream.height !== "number") {
749
+ throw new Error("video_stream_missing");
779
750
  }
780
751
  return videoStream;
781
752
  }
782
753
  function countAudioStreams(probe) {
783
- return probe.streams?.filter(stream => stream.codec_type === 'audio').length ?? 0;
754
+ return probe.streams?.filter((stream) => stream.codec_type === "audio").length ?? 0;
784
755
  }
785
756
  function readDurationSeconds(probe) {
786
757
  const raw = probe.format?.duration;
787
758
  const parsed = raw ? Number.parseFloat(raw) : Number.NaN;
788
759
  if (!Number.isFinite(parsed)) {
789
- throw new Error('duration_missing');
760
+ throw new Error("duration_missing");
790
761
  }
791
762
  return parsed;
792
763
  }
793
764
  async function runListingRecorder(recorderPath, pid, durationSeconds, rawOutputPath, metadataPath, audio, deadlineAt) {
794
765
  const args = [
795
- '--pid',
766
+ "--pid",
796
767
  String(pid),
797
- '--duration',
768
+ "--duration",
798
769
  String(durationSeconds),
799
- '--output',
770
+ "--output",
800
771
  rawOutputPath,
801
- '--metadata',
772
+ "--metadata",
802
773
  metadataPath,
803
774
  ];
804
775
  if (audio) {
805
- args.push('--audio');
776
+ args.push("--audio");
806
777
  }
807
778
  const result = (0, node_child_process_1.spawnSync)(recorderPath, args, {
808
- encoding: 'utf8',
779
+ encoding: "utf8",
809
780
  maxBuffer: 10 * 1024 * 1024,
810
781
  timeout: (0, listingCaptureLease_1.remainingListingCaptureTime)(deadlineAt),
811
- killSignal: 'SIGKILL',
782
+ killSignal: "SIGKILL",
812
783
  });
813
- if (result.error?.code === 'ETIMEDOUT') {
814
- throw new Error('listing_capture_timeout');
784
+ if (result.error?.code === "ETIMEDOUT") {
785
+ throw new Error("listing_capture_timeout");
815
786
  }
816
787
  if (result.status !== 0) {
817
- const message = result.stderr?.trim() || result.stdout?.trim() || 'Native recorder failed.';
788
+ const message = result.stderr?.trim() || result.stdout?.trim() || "Native recorder failed.";
818
789
  throw new Error(`listing_recorder_failed:${message}`);
819
790
  }
820
- const metadata = JSON.parse(await (0, promises_1.readFile)(metadataPath, 'utf8'));
791
+ const metadata = JSON.parse(await (0, promises_1.readFile)(metadataPath, "utf8"));
821
792
  return metadata;
822
793
  }
823
794
  function formatCommandError(error) {
824
- if (error.message === 'unsupported_platform') {
795
+ if (error.message === "unsupported_platform") {
825
796
  return {
826
- message: 'Game media capture only runs on macOS.',
797
+ message: "Game media capture only runs on macOS.",
827
798
  suggestions: [],
828
799
  };
829
800
  }
830
- if (error.message.startsWith('unsupported_macos_version:')) {
831
- const version = error.message.split(':')[1] || 'unknown';
801
+ if (error.message.startsWith("unsupported_macos_version:")) {
802
+ const version = error.message.split(":")[1] || "unknown";
832
803
  return {
833
804
  message: `Game media capture requires macOS ${MIN_SUPPORTED_MACOS_MAJOR}.${MIN_SUPPORTED_MACOS_MINOR} or newer on this machine. Current version: ${version}.`,
834
805
  suggestions: [],
835
806
  };
836
807
  }
837
- if (error.message === 'macos_version_probe_failed') {
808
+ if (error.message === "macos_version_probe_failed") {
838
809
  return {
839
- message: 'Could not determine the local macOS version.',
810
+ message: "Could not determine the local macOS version.",
840
811
  suggestions: [],
841
812
  };
842
813
  }
843
- if (error.message === 'listing_capture_timeout' || error.message.startsWith('listing_capture_lease_timeout:')) {
814
+ if (error.message === "listing_capture_timeout" || error.message.startsWith("listing_capture_lease_timeout:")) {
844
815
  return {
845
- message: 'Listing capture did not finish within 30 minutes.',
816
+ message: "Listing capture did not finish within 30 minutes.",
846
817
  suggestions: [],
847
818
  };
848
819
  }
849
- if (error.message === 'listing_preview_support_missing') {
820
+ if (error.message === "listing_preview_support_missing") {
850
821
  return {
851
- message: 'This game does not declare preview support, so listing capture cannot run.',
852
- suggestions: ['Set previewable: true in catalogue.json, implement the preview scene and __listingCapture hooks, then rerun "playdrop project capture".'],
822
+ message: "This game does not declare preview support, so listing capture cannot run.",
823
+ suggestions: [
824
+ 'Set previewable: true in catalogue.json, implement the preview scene and __listingCapture hooks, then rerun "playdrop project capture".',
825
+ ],
853
826
  };
854
827
  }
855
- if (error.message === 'listing_audio_capture_export_missing') {
828
+ if (error.message === "listing_audio_capture_export_missing") {
856
829
  return {
857
- message: 'The game preview audio hook did not export recorded audio.',
858
- suggestions: ['Make window.__listingCapture.stopAudioCapture() resolve { mimeType, base64 }; toggling game audio on or off is not an export.'],
830
+ message: "The game preview audio hook did not export recorded audio.",
831
+ suggestions: [
832
+ "Make window.__listingCapture.stopAudioCapture() resolve { mimeType, base64 }; toggling game audio on or off is not an export.",
833
+ ],
859
834
  };
860
835
  }
861
- if (error.message === 'listing_capture_runtime_already_recorded') {
836
+ if (error.message === "listing_capture_runtime_already_recorded") {
862
837
  return {
863
- message: 'This exact game runtime already has a canonical recording with different capture settings.',
864
- suggestions: ['Use the existing video, or change and revalidate the preview implementation before recording the changed runtime once.'],
838
+ message: "This exact game runtime already has a canonical recording with different capture settings.",
839
+ suggestions: [
840
+ "Use the existing video, or change and revalidate the preview implementation before recording the changed runtime once.",
841
+ ],
865
842
  };
866
843
  }
867
- if (error.message === 'listing_capture_current_report_incomplete') {
844
+ if (error.message === "listing_capture_current_report_incomplete") {
868
845
  return {
869
- message: 'The canonical capture report is incomplete for this runtime.',
870
- suggestions: ['Fix or remove the incomplete canonical capture directory, then record the runtime once.'],
846
+ message: "The canonical capture report is incomplete for this runtime.",
847
+ suggestions: ["Fix or remove the incomplete canonical capture directory, then record the runtime once."],
871
848
  };
872
849
  }
873
- if (error.message === 'listing_capture_report_pixels_unvalidated'
874
- || error.message.startsWith('listing_capture_artifact_changed:')) {
850
+ if (error.message === "listing_capture_report_pixels_unvalidated" ||
851
+ error.message.startsWith("listing_capture_artifact_changed:")) {
875
852
  return {
876
- message: 'The existing canonical recording is unvalidated or its files changed after capture.',
853
+ message: "The existing canonical recording is unvalidated or its files changed after capture.",
877
854
  suggestions: ['Remove the invalid capture directory and rerun "playdrop project capture" once.'],
878
855
  };
879
856
  }
880
- if (error.message.startsWith('listing_capture_dimensions_exceed_display:')) {
881
- const [, requested = 'unknown', available = 'unknown'] = error.message.split(':');
857
+ if (error.message.startsWith("listing_capture_dimensions_exceed_display:")) {
858
+ const [, requested = "unknown", available = "unknown"] = error.message.split(":");
882
859
  return {
883
860
  message: `Requested capture size ${requested} cannot fit in this worker's ${available} browser window.`,
884
- suggestions: ['Omit --width and --height to use the safe surface defaults, or request dimensions that fit this display.'],
861
+ suggestions: [
862
+ "Omit --width and --height to use the safe surface defaults, or request dimensions that fit this display.",
863
+ ],
885
864
  };
886
865
  }
887
- if (error.message.startsWith('listing_recorder_failed:')) {
866
+ if (error.message.startsWith("listing_recorder_failed:")) {
888
867
  return {
889
- message: error.message.slice('listing_recorder_failed:'.length),
868
+ message: error.message.slice("listing_recorder_failed:".length),
890
869
  suggestions: [],
891
870
  };
892
871
  }
893
- if (error.message.startsWith('ffprobe_failed:') || error.message.startsWith('ffmpeg_failed:')) {
872
+ if (error.message.startsWith("ffprobe_failed:") || error.message.startsWith("ffmpeg_failed:")) {
894
873
  return {
895
- message: error.message.slice(error.message.indexOf(':') + 1).trim() || 'ffmpeg validation failed.',
874
+ message: error.message.slice(error.message.indexOf(":") + 1).trim() || "ffmpeg validation failed.",
896
875
  suggestions: [],
897
876
  };
898
877
  }
899
- if (error.message.startsWith('listing_capture_wrong_game:')) {
878
+ if (error.message.startsWith("listing_capture_wrong_game:")) {
900
879
  return {
901
- message: 'The recorded pixels do not match the selected game preview.',
880
+ message: "The recorded pixels do not match the selected game preview.",
902
881
  suggestions: ['Verify preview mode shows the selected game, then rerun "playdrop project capture".'],
903
882
  };
904
883
  }
905
- if (error.message.startsWith('listing_capture_black_frame:')) {
884
+ if (error.message.startsWith("listing_capture_black_frame:")) {
906
885
  return {
907
- message: 'The gameplay recording contains a black first frame or poster.',
886
+ message: "The gameplay recording contains a black first frame or poster.",
908
887
  suggestions: ['Make preview mode visibly ready before capture starts, then rerun "playdrop project capture".'],
909
888
  };
910
889
  }
911
- if (error.message.startsWith('listing_capture_stale_video:')) {
890
+ if (error.message.startsWith("listing_capture_stale_video:")) {
912
891
  return {
913
- message: 'The gameplay recording is visually static.',
892
+ message: "The gameplay recording is visually static.",
914
893
  suggestions: ['Make preview mode show real gameplay motion, then rerun "playdrop project capture".'],
915
894
  };
916
895
  }
@@ -921,62 +900,53 @@ function formatCommandError(error) {
921
900
  }
922
901
  async function encodeListingVideo(rawVideoPath, finalVideoPath, posterPath, crop, width, height, fps, posterAtSeconds, deadlineAt) {
923
902
  const filter = `crop=${crop.width}:${crop.height}:${crop.x}:${crop.y},scale=${width}:${height}:flags=lanczos,fps=${fps}`;
924
- runTool('ffmpeg', [
925
- '-y',
926
- '-i',
903
+ runTool("ffmpeg", [
904
+ "-y",
905
+ "-i",
927
906
  rawVideoPath,
928
- '-vf',
907
+ "-vf",
929
908
  filter,
930
- '-c:v',
931
- 'h264_videotoolbox',
932
- '-pix_fmt',
933
- 'yuv420p',
934
- '-c:a',
935
- 'aac',
936
- finalVideoPath,
937
- ], 'ffmpeg_failed', deadlineAt);
938
- runTool('ffmpeg', [
939
- '-y',
940
- '-ss',
941
- String(posterAtSeconds),
942
- '-i',
909
+ "-c:v",
910
+ "h264_videotoolbox",
911
+ "-pix_fmt",
912
+ "yuv420p",
913
+ "-c:a",
914
+ "aac",
943
915
  finalVideoPath,
944
- '-frames:v',
945
- '1',
946
- posterPath,
947
- ], 'ffmpeg_failed', deadlineAt);
916
+ ], "ffmpeg_failed", deadlineAt);
917
+ runTool("ffmpeg", ["-y", "-ss", String(posterAtSeconds), "-i", finalVideoPath, "-frames:v", "1", posterPath], "ffmpeg_failed", deadlineAt);
948
918
  }
949
919
  function captureCommandMatchesExceptPoster(capture, surface, parsedOptions) {
950
920
  const dimensions = resolveCaptureDimensions(surface, parsedOptions);
951
- return capture.command.durationSeconds === parsedOptions.durationSeconds
952
- && capture.command.width === dimensions.width
953
- && capture.command.height === dimensions.height
954
- && capture.command.fps === parsedOptions.fps
955
- && capture.command.audio === parsedOptions.audio
956
- && capture.command.keepRaw === parsedOptions.keepRaw;
921
+ return (capture.command.durationSeconds === parsedOptions.durationSeconds &&
922
+ capture.command.width === dimensions.width &&
923
+ capture.command.height === dimensions.height &&
924
+ capture.command.fps === parsedOptions.fps &&
925
+ capture.command.audio === parsedOptions.audio &&
926
+ capture.command.keepRaw === parsedOptions.keepRaw);
957
927
  }
958
928
  function resolveCurrentCaptureReuseAction(captures, surfaces, parsedOptions) {
959
929
  if (captures.length !== surfaces.length) {
960
- throw new Error('listing_capture_current_report_incomplete');
930
+ throw new Error("listing_capture_current_report_incomplete");
961
931
  }
962
932
  const orderedCaptures = surfaces.map((surface) => captures.find((candidate) => candidate.surface === surface));
963
933
  if (orderedCaptures.some((capture) => !capture)) {
964
- throw new Error('listing_capture_current_report_incomplete');
934
+ throw new Error("listing_capture_current_report_incomplete");
965
935
  }
966
936
  if (orderedCaptures.some((capture, index) => !captureCommandMatchesExceptPoster(capture, surfaces[index], parsedOptions))) {
967
- throw new Error('listing_capture_runtime_already_recorded');
937
+ throw new Error("listing_capture_runtime_already_recorded");
968
938
  }
969
939
  return orderedCaptures.some((capture) => capture.command.posterAtSeconds !== parsedOptions.posterAtSeconds)
970
- ? 'refresh_poster'
971
- : 'reuse';
940
+ ? "refresh_poster"
941
+ : "reuse";
972
942
  }
973
943
  async function reuseCurrentListingCapture(input) {
974
944
  let report;
975
945
  try {
976
- report = JSON.parse(await (0, promises_1.readFile)(input.outputPaths.reportPath, 'utf8'));
946
+ report = JSON.parse(await (0, promises_1.readFile)(input.outputPaths.reportPath, "utf8"));
977
947
  }
978
948
  catch (error) {
979
- if (error?.code === 'ENOENT') {
949
+ if (error?.code === "ENOENT") {
980
950
  return false;
981
951
  }
982
952
  throw new Error(`listing_capture_report_invalid:${input.outputPaths.reportPath}`);
@@ -984,8 +954,8 @@ async function reuseCurrentListingCapture(input) {
984
954
  if (report.appName !== input.appName) {
985
955
  throw new Error(`listing_capture_report_app_mismatch:${report.appName}:${input.appName}`);
986
956
  }
987
- if (report.binding?.pixelValidation !== 'passed') {
988
- throw new Error('listing_capture_report_pixels_unvalidated');
957
+ if (report.binding?.pixelValidation !== "passed") {
958
+ throw new Error("listing_capture_report_pixels_unvalidated");
989
959
  }
990
960
  if (!input.runtimeBundleHash || report.binding?.runtimeBundleHash !== input.runtimeBundleHash) {
991
961
  return false;
@@ -1004,47 +974,35 @@ async function reuseCurrentListingCapture(input) {
1004
974
  }
1005
975
  }
1006
976
  }
1007
- if (action === 'reuse') {
1008
- console.log('[listing] The current runtime already has a matching canonical capture; reusing it.');
977
+ if (action === "reuse") {
978
+ console.log("[listing] The current runtime already has a matching canonical capture; reusing it.");
1009
979
  console.log(`[listing] Existing report: ${(0, node_path_1.relative)(process.cwd(), input.outputPaths.reportPath) || input.outputPaths.reportPath}`);
1010
980
  return true;
1011
981
  }
1012
982
  for (const capture of captures) {
1013
- runTool('ffmpeg', [
1014
- '-y',
1015
- '-ss',
983
+ runTool("ffmpeg", [
984
+ "-y",
985
+ "-ss",
1016
986
  String(input.parsedOptions.posterAtSeconds),
1017
- '-i',
987
+ "-i",
1018
988
  capture.finalVideo.path,
1019
- '-frames:v',
1020
- '1',
989
+ "-frames:v",
990
+ "1",
1021
991
  capture.posterPath,
1022
- ], 'ffmpeg_failed', input.deadlineAt);
992
+ ], "ffmpeg_failed", input.deadlineAt);
1023
993
  capture.command.posterAtSeconds = input.parsedOptions.posterAtSeconds;
1024
- const artifactKey = (0, node_path_1.relative)(input.outputPaths.outputDir, capture.posterPath) || 'poster.png';
994
+ const artifactKey = (0, node_path_1.relative)(input.outputPaths.outputDir, capture.posterPath) || "poster.png";
1025
995
  report.binding.artifactHashes[artifactKey] = await computeFileSha256(capture.posterPath);
1026
- await assertListingCaptureFrameVisible(capture.surface, 'poster', capture.posterPath);
996
+ await assertListingCaptureFrameVisible(capture.surface, "poster", capture.posterPath);
1027
997
  }
1028
- await (0, promises_1.writeFile)(input.outputPaths.reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
998
+ await (0, promises_1.writeFile)(input.outputPaths.reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
1029
999
  console.log(`[listing] Refreshed the canonical poster at ${input.parsedOptions.posterAtSeconds}s without relaunching the game.`);
1030
1000
  console.log(`[listing] Updated report: ${(0, node_path_1.relative)(process.cwd(), input.outputPaths.reportPath) || input.outputPaths.reportPath}`);
1031
1001
  return true;
1032
1002
  }
1033
1003
  async function muxListingAudio(finalVideoPath, audioPath, deadlineAt) {
1034
1004
  const muxedVideoPath = `${finalVideoPath}.muxed.mp4`;
1035
- runTool('ffmpeg', [
1036
- '-y',
1037
- '-i',
1038
- finalVideoPath,
1039
- '-i',
1040
- audioPath,
1041
- '-c:v',
1042
- 'copy',
1043
- '-c:a',
1044
- 'aac',
1045
- '-shortest',
1046
- muxedVideoPath,
1047
- ], 'ffmpeg_failed', deadlineAt);
1005
+ runTool("ffmpeg", ["-y", "-i", finalVideoPath, "-i", audioPath, "-c:v", "copy", "-c:a", "aac", "-shortest", muxedVideoPath], "ffmpeg_failed", deadlineAt);
1048
1006
  await (0, promises_1.rename)(muxedVideoPath, finalVideoPath);
1049
1007
  }
1050
1008
  function ensureTolerance(actual, expected, tolerance, failureCode) {
@@ -1056,7 +1014,7 @@ function createWarnings(finalProbe, requestedAudio) {
1056
1014
  const warnings = [];
1057
1015
  const audioTrackCount = countAudioStreams(finalProbe);
1058
1016
  if (!requestedAudio && audioTrackCount > 0) {
1059
- warnings.push('final output contains audio even though --audio was not requested');
1017
+ warnings.push("final output contains audio even though --audio was not requested");
1060
1018
  }
1061
1019
  return warnings;
1062
1020
  }
@@ -1065,7 +1023,7 @@ function ensureCaptureListingToolAvailable(command) {
1065
1023
  return true;
1066
1024
  }
1067
1025
  (0, messages_1.printErrorWithHelp)(`${command} is required for listing capture.`, [`Install ${command} and make sure it is available on PATH.`], {
1068
- command: 'project capture',
1026
+ command: "project capture",
1069
1027
  });
1070
1028
  process.exitCode = 1;
1071
1029
  return false;
@@ -1076,7 +1034,7 @@ async function ensureListingRecorderAvailable(recorderPath) {
1076
1034
  return true;
1077
1035
  }
1078
1036
  catch {
1079
- (0, messages_1.printErrorWithHelp)(`Native recorder binary was not found at ${recorderPath}.`, ['Start the PlayDrop worker once on this Mac to install the recorder from the PlayDrop CDN.'], { command: 'project capture' });
1037
+ (0, messages_1.printErrorWithHelp)(`Native recorder binary was not found at ${recorderPath}.`, ["Start the PlayDrop worker once on this Mac to install the recorder from the PlayDrop CDN."], { command: "project capture" });
1080
1038
  process.exitCode = 1;
1081
1039
  return false;
1082
1040
  }
@@ -1087,13 +1045,13 @@ function resolveCaptureListingTarget(parsedOptions) {
1087
1045
  }
1088
1046
  catch (error) {
1089
1047
  const code = error?.code;
1090
- const message = error?.message || 'Unable to resolve capture target.';
1091
- const suggestions = code === 'app_required'
1048
+ const message = error?.message || "Unable to resolve capture target.";
1049
+ const suggestions = code === "app_required"
1092
1050
  ? ['Use "--app <name>" to choose which app to capture.']
1093
- : code === 'catalogue_missing'
1094
- ? ['Run the command inside a Playdrop workspace or pass the direct HTML file path.']
1095
- : ['Provide a valid app target or HTML file path.'];
1096
- (0, messages_1.printErrorWithHelp)(message, suggestions, { command: 'project capture' });
1051
+ : code === "catalogue_missing"
1052
+ ? ["Run the command inside a Playdrop workspace or pass the direct HTML file path."]
1053
+ : ["Provide a valid app target or HTML file path."];
1054
+ (0, messages_1.printErrorWithHelp)(message, suggestions, { command: "project capture" });
1097
1055
  process.exitCode = 1;
1098
1056
  return null;
1099
1057
  }
@@ -1108,15 +1066,15 @@ async function captureListing(targetArg, options = {}) {
1108
1066
  }
1109
1067
  catch (error) {
1110
1068
  const detail = formatCommandError(error instanceof Error ? error : new Error(String(error)));
1111
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project capture' });
1069
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project capture" });
1112
1070
  process.exitCode = 1;
1113
1071
  return;
1114
1072
  }
1115
- if (!ensureCaptureListingToolAvailable('ffmpeg') || !ensureCaptureListingToolAvailable('ffprobe')) {
1073
+ if (!ensureCaptureListingToolAvailable("ffmpeg") || !ensureCaptureListingToolAvailable("ffprobe")) {
1116
1074
  return;
1117
1075
  }
1118
1076
  const recorderPath = resolveListingRecorderPath();
1119
- if (!await ensureListingRecorderAvailable(recorderPath)) {
1077
+ if (!(await ensureListingRecorderAvailable(recorderPath))) {
1120
1078
  return;
1121
1079
  }
1122
1080
  const resolvedTarget = resolveCaptureListingTarget(parsedOptions);
@@ -1140,7 +1098,7 @@ async function captureListing(targetArg, options = {}) {
1140
1098
  }
1141
1099
  catch (error) {
1142
1100
  const detail = formatCommandError(error instanceof Error ? error : new Error(String(error)));
1143
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project capture' });
1101
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project capture" });
1144
1102
  process.exitCode = 1;
1145
1103
  return;
1146
1104
  }
@@ -1152,15 +1110,15 @@ async function captureListing(targetArg, options = {}) {
1152
1110
  }
1153
1111
  catch (error) {
1154
1112
  const detail = formatCommandError(error instanceof Error ? error : new Error(String(error)));
1155
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project capture' });
1113
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project capture" });
1156
1114
  process.exitCode = 1;
1157
1115
  return;
1158
1116
  }
1159
1117
  const explicitOutputDir = resolveCaptureListingExplicitOutputDir(parsedOptions.outputDirInput, parsedOptions.outputDir, projectDir);
1160
1118
  const outputPaths = await ensureOutputPaths(appName, explicitOutputDir ?? resolveWorkerCaptureOutputDir(projectDir, isWorkerGameTask));
1161
- const devScriptAvailable = Boolean(projectInfo.projectDir && projectInfo.packageJson && typeof projectInfo.packageJson.scripts?.dev === 'string');
1162
- await (0, commandContext_1.withEnvironment)('project capture', 'Capturing game media', async ({ client, env, envConfig, account, workspaceAuth }) => {
1163
- let currentUsername = '';
1119
+ const devScriptAvailable = Boolean(projectInfo.projectDir && projectInfo.packageJson && typeof projectInfo.packageJson.scripts?.dev === "string");
1120
+ await (0, commandContext_1.withEnvironment)("project capture", "Capturing game media", async ({ client, env, envConfig, account, workspaceAuth }) => {
1121
+ let currentUsername = "";
1164
1122
  try {
1165
1123
  currentUsername = await (0, devShared_1.resolveDevCreatorUsername)({
1166
1124
  client,
@@ -1173,7 +1131,7 @@ async function captureListing(targetArg, options = {}) {
1173
1131
  return;
1174
1132
  }
1175
1133
  if (error instanceof types_1.UnsupportedClientError) {
1176
- (0, http_1.handleUnsupportedError)(error, 'Authentication');
1134
+ (0, http_1.handleUnsupportedError)(error, "Authentication");
1177
1135
  process.exitCode = 1;
1178
1136
  return;
1179
1137
  }
@@ -1181,12 +1139,12 @@ async function captureListing(targetArg, options = {}) {
1181
1139
  (0, messages_1.printErrorWithHelp)(`Could not fetch your account (status ${error.status}).`, [
1182
1140
  'Run "playdrop auth login" to refresh your session.',
1183
1141
  'Use "playdrop auth whoami" afterwards to verify the current account.',
1184
- ], { command: 'project capture' });
1142
+ ], { command: "project capture" });
1185
1143
  process.exitCode = 1;
1186
1144
  return;
1187
1145
  }
1188
1146
  if ((0, devShared_1.isNetworkError)(error)) {
1189
- (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to resolve your account.', 'project capture');
1147
+ (0, messages_1.printNetworkIssue)("Could not reach the Playdrop API to resolve your account.", "project capture");
1190
1148
  process.exitCode = 1;
1191
1149
  return;
1192
1150
  }
@@ -1201,17 +1159,17 @@ async function captureListing(targetArg, options = {}) {
1201
1159
  return;
1202
1160
  }
1203
1161
  if (error instanceof types_1.UnsupportedClientError) {
1204
- (0, http_1.handleUnsupportedError)(error, 'Game media capture');
1162
+ (0, http_1.handleUnsupportedError)(error, "Game media capture");
1205
1163
  process.exitCode = 1;
1206
1164
  return;
1207
1165
  }
1208
1166
  if (error instanceof types_1.ApiError && error.status === 404) {
1209
- (0, messages_1.printErrorWithHelp)(`App ${currentUsername}/${appName} is not registered on ${env}.`, [`Run "playdrop project create app ${appName}" before using listing capture.`], { command: 'project capture' });
1167
+ (0, messages_1.printErrorWithHelp)(`App ${currentUsername}/${appName} is not registered on ${env}.`, [`Run "playdrop project create app ${appName}" before using listing capture.`], { command: "project capture" });
1210
1168
  process.exitCode = 1;
1211
1169
  return;
1212
1170
  }
1213
1171
  if ((0, devShared_1.isNetworkError)(error)) {
1214
- (0, messages_1.printNetworkIssue)('Could not verify the app registration.', 'project capture');
1172
+ (0, messages_1.printNetworkIssue)("Could not verify the app registration.", "project capture");
1215
1173
  process.exitCode = 1;
1216
1174
  return;
1217
1175
  }
@@ -1222,7 +1180,7 @@ async function captureListing(targetArg, options = {}) {
1222
1180
  captureSession = (0, taskCaptureSession_1.resolveTaskCaptureSession)(workspaceAuth, registeredApp);
1223
1181
  }
1224
1182
  catch (error) {
1225
- (0, messages_1.printErrorWithHelp)(error?.message || 'Worker capture session is invalid.', ['Run this command from the active worker task workspace.'], { command: 'project capture' });
1183
+ (0, messages_1.printErrorWithHelp)(error?.message || "Worker capture session is invalid.", ["Run this command from the active worker task workspace."], { command: "project capture" });
1226
1184
  process.exitCode = 1;
1227
1185
  return;
1228
1186
  }
@@ -1230,7 +1188,7 @@ async function captureListing(targetArg, options = {}) {
1230
1188
  console.log(`[listing] Preparing ${entryLabel} for ${env} (${appTypeSlug}).`);
1231
1189
  const taskLookup = (0, catalogue_1.findAppTaskByFile)(resolvedTarget.htmlPath);
1232
1190
  if (taskLookup.errors.length > 0) {
1233
- (0, messages_1.printErrorWithHelp)(taskLookup.errors[0] || 'Failed to resolve the app task from catalogue.json.', taskLookup.errors.slice(1), { command: 'project capture' });
1191
+ (0, messages_1.printErrorWithHelp)(taskLookup.errors[0] || "Failed to resolve the app task from catalogue.json.", taskLookup.errors.slice(1), { command: "project capture" });
1234
1192
  process.exitCode = 1;
1235
1193
  return;
1236
1194
  }
@@ -1243,7 +1201,7 @@ async function captureListing(targetArg, options = {}) {
1243
1201
  runtimeBundleHash = (await (0, build_1.buildApp)(captureTask)).bundleHash;
1244
1202
  }
1245
1203
  catch (error) {
1246
- (0, messages_1.printErrorWithHelp)(error instanceof Error ? error.message : String(error), ['Fix the game build before recording final gameplay.'], { command: 'project capture' });
1204
+ (0, messages_1.printErrorWithHelp)(error instanceof Error ? error.message : String(error), ["Fix the game build before recording final gameplay."], { command: "project capture" });
1247
1205
  process.exitCode = 1;
1248
1206
  return;
1249
1207
  }
@@ -1264,7 +1222,7 @@ async function captureListing(targetArg, options = {}) {
1264
1222
  }
1265
1223
  catch (error) {
1266
1224
  const detail = formatCommandError(error instanceof Error ? error : new Error(String(error)));
1267
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project capture' });
1225
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project capture" });
1268
1226
  process.exitCode = 1;
1269
1227
  return;
1270
1228
  }
@@ -1282,12 +1240,12 @@ async function captureListing(targetArg, options = {}) {
1282
1240
  apiBase: envConfig.apiBase,
1283
1241
  task: taskLookup.task,
1284
1242
  creatorUsername: currentUsername,
1285
- appBaseUrl: new URL('.', localDevAppUrl).toString(),
1243
+ appBaseUrl: new URL(".", localDevAppUrl).toString(),
1286
1244
  });
1287
1245
  }
1288
1246
  catch (error) {
1289
1247
  const formatted = (0, dev_1.formatDevRuntimeAssetManifestFailure)(error);
1290
- (0, messages_1.printErrorWithHelp)(formatted.message, formatted.suggestions, { command: 'project capture' });
1248
+ (0, messages_1.printErrorWithHelp)(formatted.message, formatted.suggestions, { command: "project capture" });
1291
1249
  process.exitCode = 1;
1292
1250
  return;
1293
1251
  }
@@ -1345,9 +1303,9 @@ async function captureListing(targetArg, options = {}) {
1345
1303
  }
1346
1304
  }
1347
1305
  if (devServerStartedByCapture) {
1348
- await new Promise(resolve => setTimeout(resolve, 1000));
1306
+ await new Promise((resolve) => setTimeout(resolve, 1000));
1349
1307
  }
1350
- const webBase = envConfig.webBase ?? 'https://www.playdrop.ai';
1308
+ const webBase = envConfig.webBase ?? "https://www.playdrop.ai";
1351
1309
  const routeSegment = resolveListingCaptureRouteSegment(declaresPreviewSupport);
1352
1310
  const localDevPort = resolveListingCaptureLocalDevPort(devRouterPort);
1353
1311
  const frameUrl = buildListingCaptureFrameUrl({
@@ -1362,7 +1320,7 @@ async function captureListing(targetArg, options = {}) {
1362
1320
  const frameUrlObject = new URL(frameUrl);
1363
1321
  const reportFrameUrl = (0, appUrls_1.redactTaskCaptureSession)(frameUrl);
1364
1322
  console.log(`[listing] Opening ${reportFrameUrl}`);
1365
- const shouldExportPreviewAudio = parsedOptions.audio && routeSegment === 'dev-preview';
1323
+ const shouldExportPreviewAudio = parsedOptions.audio && routeSegment === "dev-preview";
1366
1324
  const surfaces = resolvedTarget.surfaceTargets.list;
1367
1325
  const useSurfacePrefix = surfaces.length > 1;
1368
1326
  const captures = [];
@@ -1373,7 +1331,7 @@ async function captureListing(targetArg, options = {}) {
1373
1331
  const dimensions = resolveCaptureDimensions(surface, parsedOptions);
1374
1332
  const captureSceneId = resolveListingCaptureSceneId(dimensions.width, dimensions.height);
1375
1333
  const surfaceOutputPaths = buildSurfaceOutputPaths(outputPaths.outputDir, surface, useSurfacePrefix);
1376
- const validationPrefix = useSurfacePrefix ? `${surface.toLowerCase().replace(/_/g, '-')}-` : '';
1334
+ const validationPrefix = useSurfacePrefix ? `${surface.toLowerCase().replace(/_/g, "-")}-` : "";
1377
1335
  const validationPaths = {
1378
1336
  reference: (0, node_path_1.join)(outputPaths.outputDir, `.${validationPrefix}capture-reference.png`),
1379
1337
  first: (0, node_path_1.join)(outputPaths.outputDir, `.${validationPrefix}capture-first.png`),
@@ -1383,9 +1341,9 @@ async function captureListing(targetArg, options = {}) {
1383
1341
  const contextOptions = resolveListingCaptureBrowserContextOptions(surface, dimensions);
1384
1342
  browserHandle = await launchListingBrowser(dimensions, frameUrlObject.origin, contextOptions);
1385
1343
  try {
1386
- await browserHandle.page.goto(frameUrl, { waitUntil: 'domcontentloaded' });
1344
+ await browserHandle.page.goto(frameUrl, { waitUntil: "domcontentloaded" });
1387
1345
  await browserHandle.page.waitForTimeout(1000);
1388
- if (routeSegment === 'dev-preview') {
1346
+ if (routeSegment === "dev-preview") {
1389
1347
  console.log(`[listing] Preparing preview scene ${captureSceneId}.`);
1390
1348
  await prepareHostedListingScene(browserHandle.page, captureSceneId);
1391
1349
  await browserHandle.page.waitForTimeout(1000);
@@ -1393,13 +1351,13 @@ async function captureListing(targetArg, options = {}) {
1393
1351
  const measurement = await fitWindowToRequestedGameplay(browserHandle.page, dimensions.width, dimensions.height);
1394
1352
  console.log(`[listing] Gameplay frame ${Math.round(measurement.iframeRect.width)}x${Math.round(measurement.iframeRect.height)} in window ${Math.round(measurement.outerWidth)}x${Math.round(measurement.outerHeight)}.`);
1395
1353
  if (shouldExportPreviewAudio) {
1396
- console.log('[listing] Checking the in-app preview audio export contract.');
1354
+ console.log("[listing] Checking the in-app preview audio export contract.");
1397
1355
  await assertHostedListingAudioCaptureContract(browserHandle.page, outputPaths.outputDir);
1398
- console.log('[listing] Starting in-app preview audio capture.');
1356
+ console.log("[listing] Starting in-app preview audio capture.");
1399
1357
  await startHostedListingAudioCapture(browserHandle.page);
1400
1358
  }
1401
1359
  await browserHandle.page.waitForTimeout(750);
1402
- console.log('[listing] Waiting for the machine capture lease.');
1360
+ console.log("[listing] Waiting for the machine capture lease.");
1403
1361
  const captureLease = await (0, listingCaptureLease_1.acquireListingCaptureLease)({
1404
1362
  deadlineAt: captureDeadlineAt,
1405
1363
  workspaceDir: (0, node_path_1.dirname)(resolvedTarget.htmlPath),
@@ -1430,11 +1388,11 @@ async function captureListing(targetArg, options = {}) {
1430
1388
  const finalDurationSeconds = readDurationSeconds(finalProbe);
1431
1389
  const finalAudioTrackCount = countAudioStreams(finalProbe);
1432
1390
  const finalFps = parseFrameRate(finalVideoStream.avg_frame_rate);
1433
- ensureTolerance(finalVideoStream.width, dimensions.width, 0, 'final_width_mismatch');
1434
- ensureTolerance(finalVideoStream.height, dimensions.height, 0, 'final_height_mismatch');
1435
- ensureTolerance(finalDurationSeconds, parsedOptions.durationSeconds, 1.5, 'final_duration_mismatch');
1391
+ ensureTolerance(finalVideoStream.width, dimensions.width, 0, "final_width_mismatch");
1392
+ ensureTolerance(finalVideoStream.height, dimensions.height, 0, "final_height_mismatch");
1393
+ ensureTolerance(finalDurationSeconds, parsedOptions.durationSeconds, 1.5, "final_duration_mismatch");
1436
1394
  if (parsedOptions.audio && finalAudioTrackCount === 0) {
1437
- throw new Error('audio_track_missing');
1395
+ throw new Error("audio_track_missing");
1438
1396
  }
1439
1397
  extractListingValidationFrame(surfaceOutputPaths.finalVideoPath, Math.min(0.1, finalDurationSeconds / 4), validationPaths.first, captureDeadlineAt);
1440
1398
  extractListingValidationFrame(surfaceOutputPaths.finalVideoPath, Math.max(0, finalDurationSeconds - 0.1), validationPaths.last, captureDeadlineAt);
@@ -1450,8 +1408,10 @@ async function captureListing(targetArg, options = {}) {
1450
1408
  for (const warning of warnings) {
1451
1409
  allWarnings.push(`${surface}: ${warning}`);
1452
1410
  }
1453
- artifactHashes[(0, node_path_1.relative)(outputPaths.outputDir, surfaceOutputPaths.finalVideoPath) || 'listing.mp4'] = await computeFileSha256(surfaceOutputPaths.finalVideoPath);
1454
- artifactHashes[(0, node_path_1.relative)(outputPaths.outputDir, surfaceOutputPaths.posterPath) || 'poster.png'] = await computeFileSha256(surfaceOutputPaths.posterPath);
1411
+ artifactHashes[(0, node_path_1.relative)(outputPaths.outputDir, surfaceOutputPaths.finalVideoPath) || "listing.mp4"] =
1412
+ await computeFileSha256(surfaceOutputPaths.finalVideoPath);
1413
+ artifactHashes[(0, node_path_1.relative)(outputPaths.outputDir, surfaceOutputPaths.posterPath) || "poster.png"] =
1414
+ await computeFileSha256(surfaceOutputPaths.posterPath);
1455
1415
  capturedSurfaces.push(surface);
1456
1416
  captures.push({
1457
1417
  surface,
@@ -1512,11 +1472,11 @@ async function captureListing(targetArg, options = {}) {
1512
1472
  binding: {
1513
1473
  artifactHashes,
1514
1474
  capturedSurfaces,
1515
- pixelValidation: 'passed',
1475
+ pixelValidation: "passed",
1516
1476
  runtimeBundleHash,
1517
1477
  },
1518
1478
  };
1519
- await (0, promises_1.writeFile)(outputPaths.reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
1479
+ await (0, promises_1.writeFile)(outputPaths.reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
1520
1480
  console.log(`[listing] Saved report to ${(0, node_path_1.relative)(process.cwd(), outputPaths.reportPath) || outputPaths.reportPath}`);
1521
1481
  }
1522
1482
  catch (error) {
@@ -1524,12 +1484,12 @@ async function captureListing(targetArg, options = {}) {
1524
1484
  return;
1525
1485
  }
1526
1486
  if (error instanceof types_1.UnsupportedClientError) {
1527
- (0, http_1.handleUnsupportedError)(error, 'Game media capture');
1487
+ (0, http_1.handleUnsupportedError)(error, "Game media capture");
1528
1488
  process.exitCode = 1;
1529
1489
  return;
1530
1490
  }
1531
1491
  const detail = formatCommandError(error instanceof Error ? error : new Error(String(error)));
1532
- (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: 'project capture' });
1492
+ (0, messages_1.printErrorWithHelp)(detail.message, detail.suggestions, { command: "project capture" });
1533
1493
  process.exitCode = 1;
1534
1494
  }
1535
1495
  finally {