@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.
- package/bin/playdrop +1 -2
- package/config/client-meta.json +4 -4
- package/dist/apiClient.d.ts +2 -2
- package/dist/apiClient.js +16 -20
- package/dist/appUrls.d.ts +2 -2
- package/dist/appUrls.js +31 -33
- package/dist/apps/build.d.ts +2 -2
- package/dist/apps/build.js +83 -83
- package/dist/apps/index.d.ts +7 -7
- package/dist/apps/index.js +8 -8
- package/dist/apps/loadCheck.d.ts +28 -16
- package/dist/apps/loadCheck.js +411 -279
- package/dist/apps/registration.d.ts +3 -3
- package/dist/apps/registration.js +1 -1
- package/dist/apps/staticHtml.d.ts +3 -3
- package/dist/apps/staticHtml.js +90 -91
- package/dist/apps/surfaceProfiles.d.ts +2 -2
- package/dist/apps/surfaceProfiles.js +6 -6
- package/dist/apps/upload.d.ts +5 -5
- package/dist/apps/upload.js +75 -81
- package/dist/apps/validate.d.ts +2 -2
- package/dist/apps/validate.js +18 -22
- package/dist/assetSpecs.d.ts +2 -2
- package/dist/assetSpecs.js +35 -35
- package/dist/assets/model-artifacts.d.ts +1 -1
- package/dist/assets/model-artifacts.js +81 -77
- package/dist/assets/model-worker.d.ts +1 -1
- package/dist/assets/model-worker.js +6 -6
- package/dist/browser.js +9 -9
- package/dist/catalogue-utils.d.ts +1 -1
- package/dist/catalogue-utils.js +26 -26
- package/dist/catalogue.d.ts +21 -16
- package/dist/catalogue.js +509 -413
- package/dist/clientInfo.d.ts +1 -1
- package/dist/clientInfo.js +28 -28
- package/dist/commandContext.d.ts +5 -5
- package/dist/commandContext.js +19 -23
- package/dist/commands/accounts.js +6 -6
- package/dist/commands/ads.js +16 -16
- package/dist/commands/agents.d.ts +2 -2
- package/dist/commands/agents.js +131 -127
- package/dist/commands/boosts.js +41 -31
- package/dist/commands/browse.d.ts +2 -2
- package/dist/commands/browse.js +168 -128
- package/dist/commands/build.js +9 -9
- package/dist/commands/captureListing.d.ts +8 -8
- package/dist/commands/captureListing.js +292 -332
- package/dist/commands/changelog.js +1 -1
- package/dist/commands/chat.js +51 -53
- package/dist/commands/check.d.ts +1 -1
- package/dist/commands/check.js +44 -44
- package/dist/commands/clients.d.ts +3 -3
- package/dist/commands/clients.js +67 -64
- package/dist/commands/comments.js +36 -29
- package/dist/commands/create.js +305 -312
- package/dist/commands/createRemixContent.d.ts +1 -1
- package/dist/commands/createRemixContent.js +65 -60
- package/dist/commands/creations.js +205 -135
- package/dist/commands/credits.js +37 -27
- package/dist/commands/detail.js +40 -34
- package/dist/commands/dev.js +103 -126
- package/dist/commands/devBrowser.js +74 -65
- package/dist/commands/devRuntimeAssets.d.ts +4 -4
- package/dist/commands/devRuntimeAssets.js +38 -40
- package/dist/commands/devServer.d.ts +4 -4
- package/dist/commands/devServer.js +183 -174
- package/dist/commands/devShared.d.ts +3 -3
- package/dist/commands/devShared.js +31 -31
- package/dist/commands/doctor.d.ts +5 -5
- package/dist/commands/doctor.js +63 -57
- package/dist/commands/documentation.js +42 -32
- package/dist/commands/feedback.js +59 -42
- package/dist/commands/format.js +9 -9
- package/dist/commands/generation.d.ts +2 -2
- package/dist/commands/generation.js +344 -326
- package/dist/commands/init.d.ts +4 -4
- package/dist/commands/init.js +64 -61
- package/dist/commands/login.d.ts +2 -2
- package/dist/commands/login.js +42 -62
- package/dist/commands/logout.js +4 -4
- package/dist/commands/marketing.d.ts +8 -8
- package/dist/commands/marketing.js +246 -297
- package/dist/commands/notes.js +19 -19
- package/dist/commands/notifications.js +34 -22
- package/dist/commands/npmProcess.js +3 -3
- package/dist/commands/ownedRuntimeImageValidation.d.ts +1 -1
- package/dist/commands/ownedRuntimeImageValidation.js +19 -17
- package/dist/commands/play.js +12 -21
- package/dist/commands/publicPages.js +8 -4
- package/dist/commands/review.js +123 -110
- package/dist/commands/search.js +107 -88
- package/dist/commands/tags.js +10 -12
- package/dist/commands/taskCaptureSession.d.ts +3 -3
- package/dist/commands/taskCaptureSession.js +3 -3
- package/dist/commands/tweaks.js +25 -23
- package/dist/commands/upgrade.js +40 -31
- package/dist/commands/upload-content.d.ts +5 -5
- package/dist/commands/upload-content.js +130 -122
- package/dist/commands/upload-graph.d.ts +1 -1
- package/dist/commands/upload-graph.js +7 -11
- package/dist/commands/upload.d.ts +7 -7
- package/dist/commands/upload.js +196 -217
- package/dist/commands/validate.js +33 -32
- package/dist/commands/versionsBrowse.js +61 -51
- package/dist/commands/whoami.js +11 -14
- package/dist/commands/worker/archive-staging.d.ts +9 -0
- package/dist/commands/worker/archive-staging.js +257 -0
- package/dist/commands/worker/instrument-evidence.d.ts +1 -1
- package/dist/commands/worker/instrument-evidence.js +41 -43
- package/dist/commands/worker/provider-telemetry.d.ts +2 -1
- package/dist/commands/worker/provider-telemetry.js +181 -64
- package/dist/commands/worker/runtime.d.ts +18 -3
- package/dist/commands/worker/runtime.js +291 -239
- package/dist/commands/worker.d.ts +83 -22
- package/dist/commands/worker.js +1980 -1411
- package/dist/commands/workspaces.d.ts +2 -2
- package/dist/commands/workspaces.js +57 -57
- package/dist/config.js +23 -20
- package/dist/devAuth.d.ts +3 -3
- package/dist/devAuth.js +20 -17
- package/dist/environment.d.ts +1 -1
- package/dist/environment.js +34 -34
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +7 -7
- package/dist/externalAssetPackValidation.d.ts +1 -1
- package/dist/externalAssetPackValidation.js +9 -9
- package/dist/http.d.ts +1 -1
- package/dist/http.js +9 -9
- package/dist/index.js +657 -664
- package/dist/listingCaptureLease.js +23 -23
- package/dist/listingPreflight.d.ts +2 -2
- package/dist/listingPreflight.js +33 -33
- package/dist/messages.js +6 -14
- package/dist/output.js +9 -9
- package/dist/playwright.d.ts +1 -1
- package/dist/playwright.js +35 -40
- package/dist/proxyFetch.js +30 -27
- package/dist/recorderRelease.js +8 -8
- package/dist/refs.d.ts +5 -5
- package/dist/refs.js +40 -37
- package/dist/sessionCookie.js +15 -21
- package/dist/shellProbe.js +5 -5
- package/dist/taskSelection.d.ts +3 -3
- package/dist/taskSelection.js +67 -62
- package/dist/taskUtils.d.ts +1 -1
- package/dist/taskUtils.js +4 -4
- package/dist/tweakStaleness.d.ts +3 -3
- package/dist/tweakStaleness.js +8 -8
- package/dist/uploadLog.d.ts +3 -3
- package/dist/uploadLog.js +51 -51
- package/dist/versionCompare.js +3 -3
- package/dist/workerAppProject.d.ts +1 -1
- package/dist/workerAppProject.js +10 -17
- package/dist/workspaceAuth.d.ts +1 -1
- package/dist/workspaceAuth.js +28 -22
- package/node_modules/@playdrop/ai-client/dist/index.d.ts +35 -35
- package/node_modules/@playdrop/ai-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/client.d.ts +34 -33
- package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/core/errors.d.ts +1 -1
- package/node_modules/@playdrop/api-client/dist/core/errors.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/core/request.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/core/request.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/admin.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/admin.js +4 -1
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts +4 -3
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.js +12 -0
- package/node_modules/@playdrop/api-client/dist/domains/ai.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/ai.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts +4 -4
- package/node_modules/@playdrop/api-client/dist/domains/apps.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts +4 -4
- package/node_modules/@playdrop/api-client/dist/domains/asset-packs.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts +4 -4
- package/node_modules/@playdrop/api-client/dist/domains/assets.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/auth.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/auth.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/chat.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/chat.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/comments.d.ts +3 -3
- package/node_modules/@playdrop/api-client/dist/domains/comments.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/free-credits.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/free-credits.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/me.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/me.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/payments.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/player-meta.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/player-meta.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/playtrade.d.ts +3 -3
- package/node_modules/@playdrop/api-client/dist/domains/playtrade.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/playtrade.js +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/search.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/search.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts +2 -2
- package/node_modules/@playdrop/api-client/dist/domains/tags.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/index.d.ts +19 -18
- package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/index.js +7 -2
- package/node_modules/@playdrop/boxel-core/dist/src/entity-cleaner.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/entity-cleaner.js +47 -47
- package/node_modules/@playdrop/boxel-core/dist/src/entity-cleaner.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/entity-utils.d.ts +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/entity-utils.js +32 -47
- package/node_modules/@playdrop/boxel-core/dist/src/entity-utils.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/format-utils.js +16 -18
- package/node_modules/@playdrop/boxel-core/dist/src/format-utils.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/geometry.d.ts +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/index.d.ts +4 -4
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/common.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/index.d.ts +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/textured-builder.d.ts +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/textured-builder.js +44 -45
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/textured-builder.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/types.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/voxel-builder.d.ts +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/voxel-builder.js +40 -44
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r15/voxel-builder.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/builder.d.ts +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/builder.js +30 -34
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/builder.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/index.d.ts +4 -4
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/index.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/scanner.d.ts +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/scanner.js +23 -20
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/scanner.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/artifacts.d.ts +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/artifacts.js +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/face-map.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/face-map.js +21 -21
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/r6/textures/face-map.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/templates/index.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/humanoid/templates/index.js +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/index.d.ts +19 -19
- package/node_modules/@playdrop/boxel-core/dist/src/materials.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/materials.js +12 -16
- package/node_modules/@playdrop/boxel-core/dist/src/materials.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/palette_tools.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/palette_tools.js +38 -41
- package/node_modules/@playdrop/boxel-core/dist/src/palette_tools.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/serialization.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/serialization.js +54 -56
- package/node_modules/@playdrop/boxel-core/dist/src/serialization.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/textures.d.ts +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/textures.js +39 -45
- package/node_modules/@playdrop/boxel-core/dist/src/textures.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/infer-face.d.ts +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/infer-face.js +39 -43
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/infer-face.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/layer-mode.d.ts +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/layer-mode.js +35 -35
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/layer-mode.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/merge-overlay.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/merge-overlay.js +18 -18
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/merge-overlay.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/slice.d.ts +3 -3
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/slice.js +50 -48
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/textured-boxes/slice.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/upscale.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/upscale.js +22 -26
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/upscale.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/slice.d.ts +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/slice.js +8 -8
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/slice.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/textured-to-voxel.d.ts +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/textured-to-voxel.js +23 -28
- package/node_modules/@playdrop/boxel-core/dist/src/transforms/voxels/textured-to-voxel.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/types.d.ts +8 -8
- package/node_modules/@playdrop/boxel-core/dist/src/validation.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/validation.js +93 -95
- package/node_modules/@playdrop/boxel-core/dist/src/validation.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/voxels/greedy-mesher.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/voxels/greedy-mesher.js +2 -2
- package/node_modules/@playdrop/boxel-core/dist/src/voxels/greedy-mesher.js.map +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/voxels.d.ts +1 -1
- package/node_modules/@playdrop/boxel-core/dist/src/voxels.js +2 -7
- package/node_modules/@playdrop/boxel-core/dist/src/voxels.js.map +1 -1
- package/node_modules/@playdrop/boxel-three/dist/src/animations.d.ts +3 -3
- package/node_modules/@playdrop/boxel-three/dist/src/builders.d.ts +4 -4
- package/node_modules/@playdrop/boxel-three/dist/src/context.d.ts +3 -3
- package/node_modules/@playdrop/boxel-three/dist/src/exporters/glb.d.ts +6 -6
- package/node_modules/@playdrop/boxel-three/dist/src/exporters/glb.js +9 -1
- package/node_modules/@playdrop/boxel-three/dist/src/exporters/image.d.ts +3 -3
- package/node_modules/@playdrop/boxel-three/dist/src/index.d.ts +17 -17
- package/node_modules/@playdrop/boxel-three/dist/src/instantiate.d.ts +9 -9
- package/node_modules/@playdrop/boxel-three/dist/src/nodes.d.ts +3 -3
- package/node_modules/@playdrop/boxel-three/dist/src/nodes.js +1 -1
- package/node_modules/@playdrop/boxel-three/dist/src/overlays.d.ts +2 -2
- package/node_modules/@playdrop/boxel-three/dist/src/primitives.d.ts +1 -1
- package/node_modules/@playdrop/boxel-three/dist/src/scene.d.ts +1 -1
- package/node_modules/@playdrop/boxel-three/dist/src/skinned-mesh.d.ts +2 -2
- package/node_modules/@playdrop/boxel-three/dist/src/texture-atlas.d.ts +1 -1
- package/node_modules/@playdrop/boxel-three/dist/src/textures.d.ts +3 -3
- package/node_modules/@playdrop/boxel-three/dist/src/types.d.ts +4 -4
- package/node_modules/@playdrop/boxel-three/dist/src/voxels/faces.d.ts +2 -2
- package/node_modules/@playdrop/boxel-three/dist/src/voxels/mesher.d.ts +1 -1
- package/node_modules/@playdrop/boxel-three/dist/test/fixtures/render-worker.d.ts +1 -1
- package/node_modules/@playdrop/config/client-meta.json +4 -4
- package/node_modules/@playdrop/config/dist/src/client-meta.d.ts +1 -1
- package/node_modules/@playdrop/config/dist/src/client-meta.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/client-meta.js +10 -10
- package/node_modules/@playdrop/config/dist/src/constants.js +10 -10
- package/node_modules/@playdrop/config/dist/src/creator-plans.d.ts +1 -1
- package/node_modules/@playdrop/config/dist/src/creator-plans.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/creator-plans.js +27 -28
- package/node_modules/@playdrop/config/dist/src/deployment.d.ts +4 -4
- package/node_modules/@playdrop/config/dist/src/deployment.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/deployment.js +42 -41
- package/node_modules/@playdrop/config/dist/src/game-arena.js +12 -12
- package/node_modules/@playdrop/config/dist/src/index.d.ts +9 -9
- package/node_modules/@playdrop/config/dist/src/index.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/index.js +24 -25
- package/node_modules/@playdrop/config/dist/src/public-deployment.d.ts +4 -4
- package/node_modules/@playdrop/config/dist/src/public-deployment.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/public-deployment.js +41 -39
- package/node_modules/@playdrop/config/dist/src/runtime-client-meta.js +1 -3
- package/node_modules/@playdrop/config/dist/src/runtime-service-origins.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/runtime-service-origins.js +23 -25
- package/node_modules/@playdrop/config/dist/src/server/fastify.d.ts +5 -5
- package/node_modules/@playdrop/config/dist/src/server/fastify.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/server/fastify.js +44 -46
- package/node_modules/@playdrop/config/dist/src/server/logging.d.ts +1 -1
- package/node_modules/@playdrop/config/dist/src/server/logging.d.ts.map +1 -1
- package/node_modules/@playdrop/config/dist/src/server/logging.js +6 -8
- package/node_modules/@playdrop/config/dist/src/types.d.ts +2 -2
- package/node_modules/@playdrop/config/dist/test/creator-plans.test.js +12 -12
- package/node_modules/@playdrop/config/dist/test/deployment.test.js +59 -59
- package/node_modules/@playdrop/config/dist/test/fastify.test.js +4 -4
- package/node_modules/@playdrop/config/dist/test/game-arena.test.js +8 -8
- package/node_modules/@playdrop/config/dist/test/logging.test.js +6 -6
- package/node_modules/@playdrop/config/dist/test/validateClientEnvironment.test.js +57 -57
- package/node_modules/@playdrop/config/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@playdrop/types/dist/agent-task-playtest.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/agent-task-terminal.d.ts +2 -2
- package/node_modules/@playdrop/types/dist/agent-task-terminal.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/api.d.ts +314 -250
- package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/api.js +40 -59
- package/node_modules/@playdrop/types/dist/app-capability-filters.d.ts +2 -2
- package/node_modules/@playdrop/types/dist/app-playtest-tape.d.ts +6 -6
- package/node_modules/@playdrop/types/dist/app-playtest-tape.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/app-review.d.ts +2 -2
- package/node_modules/@playdrop/types/dist/app-review.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/app-review.js +1 -6
- package/node_modules/@playdrop/types/dist/app.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/asset-pack.d.ts +5 -5
- package/node_modules/@playdrop/types/dist/asset-spec.d.ts +4 -4
- package/node_modules/@playdrop/types/dist/asset.d.ts +11 -11
- package/node_modules/@playdrop/types/dist/attachment-policy.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/chat.d.ts +3 -3
- package/node_modules/@playdrop/types/dist/creator-public-image.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/graph.d.ts +4 -4
- package/node_modules/@playdrop/types/dist/index.d.ts +25 -25
- package/node_modules/@playdrop/types/dist/instrument-evidence.d.ts +2 -2
- package/node_modules/@playdrop/types/dist/instrument-evidence.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/instrument-evidence.js +2 -11
- package/node_modules/@playdrop/types/dist/locale.d.ts +2 -2
- package/node_modules/@playdrop/types/dist/locale.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/locale.js +2 -17
- package/node_modules/@playdrop/types/dist/owned-assets.d.ts +2 -2
- package/node_modules/@playdrop/types/dist/owned-assets.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/player-meta.d.ts +3 -3
- package/node_modules/@playdrop/types/dist/player-meta.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/playtest-notes.d.ts +11 -11
- package/node_modules/@playdrop/types/dist/playtest-notes.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/playtrade.d.ts +8 -5
- package/node_modules/@playdrop/types/dist/playtrade.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/realtime.d.ts +1 -1
- package/node_modules/@playdrop/types/dist/tweaks.d.ts +4 -4
- package/node_modules/@playdrop/types/dist/tweaks.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/tweaks.js +12 -2
- package/node_modules/@playdrop/types/dist/version.d.ts +14 -14
- package/node_modules/@playdrop/types/dist/version.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/version.js +4 -1
- package/node_modules/@playdrop/vox-three/dist/src/index.d.ts +1 -1
- package/node_modules/@playdrop/vox-three/dist/src/vox.d.ts +2 -2
- package/node_modules/@playdrop/vox-three/dist/src/vox.js +20 -18
- package/node_modules/@playdrop/vox-three/dist/src/vox.js.map +1 -1
- package/node_modules/@playdrop/vox-three/dist/test/vox.test.js +11 -14
- package/node_modules/@playdrop/vox-three/dist/test/vox.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -46,33 +46,33 @@ const commandContext_1 = require("../commandContext");
|
|
|
46
46
|
const errors_1 = require("../errors");
|
|
47
47
|
const messages_1 = require("../messages");
|
|
48
48
|
const output_1 = require("../output");
|
|
49
|
-
const IMAGE_ASPECT_RATIO_SET = new Set([
|
|
50
|
-
const IMAGE_SIZE_SET = new Set([
|
|
51
|
-
const VIDEO_ASPECT_RATIO_SET = new Set([
|
|
49
|
+
const IMAGE_ASPECT_RATIO_SET = new Set(["1:1", "3:4", "9:16", "4:3", "16:9"]);
|
|
50
|
+
const IMAGE_SIZE_SET = new Set(["1K", "4K"]);
|
|
51
|
+
const VIDEO_ASPECT_RATIO_SET = new Set(["16:9", "9:16"]);
|
|
52
52
|
const DEFAULT_SUBCATEGORY_BY_MODALITY = {
|
|
53
|
-
IMAGE:
|
|
54
|
-
MUSIC:
|
|
55
|
-
SFX:
|
|
56
|
-
SPEECH:
|
|
57
|
-
VIDEO:
|
|
58
|
-
MODEL_3D:
|
|
53
|
+
IMAGE: "generic",
|
|
54
|
+
MUSIC: "music",
|
|
55
|
+
SFX: "sfx",
|
|
56
|
+
SPEECH: "speech",
|
|
57
|
+
VIDEO: "generic",
|
|
58
|
+
MODEL_3D: "generic",
|
|
59
59
|
};
|
|
60
|
-
const DEFAULT_IMAGE_ASPECT_RATIO =
|
|
61
|
-
const DEFAULT_IMAGE_SIZE =
|
|
62
|
-
const DEFAULT_VIDEO_ASPECT_RATIO =
|
|
60
|
+
const DEFAULT_IMAGE_ASPECT_RATIO = "1:1";
|
|
61
|
+
const DEFAULT_IMAGE_SIZE = "1K";
|
|
62
|
+
const DEFAULT_VIDEO_ASPECT_RATIO = "16:9";
|
|
63
63
|
const DEFAULT_VIDEO_DURATION_SECONDS = 4;
|
|
64
64
|
const VIDEO_FIRST_LAST_FRAME_DURATION_SECONDS = 8;
|
|
65
|
-
const DEFAULT_MODEL3D_TOPOLOGY =
|
|
65
|
+
const DEFAULT_MODEL3D_TOPOLOGY = "triangle";
|
|
66
66
|
const DEFAULT_MODEL3D_TARGET_POLYCOUNT = 30000;
|
|
67
67
|
const DEFAULT_MODEL3D_SHOULD_REMESH = true;
|
|
68
68
|
const DEFAULT_MODEL3D_SHOULD_TEXTURE = true;
|
|
69
69
|
const GENERATE_DEFAULT_TIMEOUT_SECONDS = 900;
|
|
70
70
|
const GENERATE_DEFAULT_POLL_INTERVAL_MS = 1000;
|
|
71
71
|
const LOCAL_IMAGE_MIME_BY_EXTENSION = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
".png": "image/png",
|
|
73
|
+
".jpg": "image/jpeg",
|
|
74
|
+
".jpeg": "image/jpeg",
|
|
75
|
+
".webp": "image/webp",
|
|
76
76
|
};
|
|
77
77
|
const OUTPUT_IMAGE_MIME_BY_EXTENSION = LOCAL_IMAGE_MIME_BY_EXTENSION;
|
|
78
78
|
const GENERATED_PNG_OUTPUT_MAX_BYTES = config_1.MAX_VERSION_HERO_BYTES;
|
|
@@ -82,67 +82,67 @@ function isPlaydropSpeechVoiceId(value) {
|
|
|
82
82
|
function handleGenerateBuildRequestError(message) {
|
|
83
83
|
const errorByCode = {
|
|
84
84
|
missing_type: {
|
|
85
|
-
title:
|
|
86
|
-
details: [
|
|
85
|
+
title: "A generation type is required.",
|
|
86
|
+
details: ["Use one of: image, music, sfx, speech, video, model_3d."],
|
|
87
87
|
},
|
|
88
88
|
missing_prompt: {
|
|
89
|
-
title:
|
|
89
|
+
title: "A prompt is required.",
|
|
90
90
|
details: ['Example: playdrop ai create image "A pixel art hero portrait"'],
|
|
91
91
|
},
|
|
92
92
|
invalid_type: {
|
|
93
|
-
title:
|
|
94
|
-
details: [
|
|
93
|
+
title: "The generation type is invalid.",
|
|
94
|
+
details: ["Use one of: image, music, sfx, speech, video, model_3d."],
|
|
95
95
|
},
|
|
96
96
|
invalid_duration: {
|
|
97
|
-
title:
|
|
98
|
-
details: [
|
|
97
|
+
title: "The --duration value is invalid.",
|
|
98
|
+
details: ["Use a positive value like 20000, 20s, or 20000ms."],
|
|
99
99
|
},
|
|
100
100
|
invalid_video_duration: {
|
|
101
|
-
title:
|
|
102
|
-
details: [
|
|
101
|
+
title: "The --duration value for video is invalid.",
|
|
102
|
+
details: ["Use 4s or 8s for video generation."],
|
|
103
103
|
},
|
|
104
104
|
invalid_aspect_ratio: {
|
|
105
|
-
title:
|
|
106
|
-
details: [
|
|
105
|
+
title: "The --ratio value is invalid.",
|
|
106
|
+
details: ["Image: 1:1, 3:4, 9:16, 4:3, 16:9. Video: 16:9, 9:16."],
|
|
107
107
|
},
|
|
108
108
|
invalid_image_size: {
|
|
109
|
-
title:
|
|
110
|
-
details: [
|
|
109
|
+
title: "The --size value is invalid.",
|
|
110
|
+
details: ["Image size must be 1K or 4K."],
|
|
111
111
|
},
|
|
112
112
|
image_size_not_supported_for_modality: {
|
|
113
|
-
title:
|
|
113
|
+
title: "The --size option is only supported for image generation.",
|
|
114
114
|
details: ['Use --size 1K or --size 4K with "playdrop ai create image ...".'],
|
|
115
115
|
},
|
|
116
116
|
missing_model3d_images: {
|
|
117
|
-
title:
|
|
118
|
-
details: [
|
|
117
|
+
title: "Model 3D IMAGE source mode requires at least one reference image.",
|
|
118
|
+
details: ["Provide --image1 <url> or --image2 <url>, or switch to --source-mode TEXT."],
|
|
119
119
|
},
|
|
120
120
|
model3d_text_mode_disallows_images: {
|
|
121
|
-
title:
|
|
122
|
-
details: [
|
|
121
|
+
title: "Model 3D TEXT source mode cannot include reference images.",
|
|
122
|
+
details: ["Remove --image1/--image2 or switch to --source-mode IMAGE."],
|
|
123
123
|
},
|
|
124
124
|
invalid_asset_subcategory: {
|
|
125
|
-
title:
|
|
126
|
-
details: [
|
|
125
|
+
title: "The --subcategory value is invalid.",
|
|
126
|
+
details: ["Use a lowercase slug such as generic, music, sfx, or avatar."],
|
|
127
127
|
},
|
|
128
128
|
speech_disallows_subcategory: {
|
|
129
|
-
title:
|
|
130
|
-
details: [
|
|
129
|
+
title: "Speech does not accept --subcategory.",
|
|
130
|
+
details: ["Speech jobs always create AUDIO assets with subcategory speech."],
|
|
131
131
|
},
|
|
132
132
|
invalid_speech_voice_selection: {
|
|
133
|
-
title:
|
|
134
|
-
details: [
|
|
133
|
+
title: "Speech voice options are invalid.",
|
|
134
|
+
details: ["Use either --voice <alias> or --provider-voice-id <id>, but not both."],
|
|
135
135
|
},
|
|
136
136
|
invalid_speech_voice: {
|
|
137
|
-
title:
|
|
138
|
-
details: [`Use one of: ${types_1.PLAYDROP_SPEECH_VOICE_IDS.join(
|
|
137
|
+
title: "The --voice value is invalid.",
|
|
138
|
+
details: [`Use one of: ${types_1.PLAYDROP_SPEECH_VOICE_IDS.join(", ")}.`],
|
|
139
139
|
},
|
|
140
140
|
speech_voice_unavailable: {
|
|
141
|
-
title:
|
|
142
|
-
details: [
|
|
141
|
+
title: "The provider voice is unavailable.",
|
|
142
|
+
details: ["Use a different --provider-voice-id or a curated --voice alias."],
|
|
143
143
|
},
|
|
144
144
|
speech_input_too_long: {
|
|
145
|
-
title:
|
|
145
|
+
title: "The speech input is too long.",
|
|
146
146
|
details: [`Use ${types_1.PLAYDROP_SPEECH_MAX_WORDS} words or fewer.`],
|
|
147
147
|
},
|
|
148
148
|
};
|
|
@@ -150,38 +150,42 @@ function handleGenerateBuildRequestError(message) {
|
|
|
150
150
|
if (!entry) {
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
|
-
(0, messages_1.printErrorWithHelp)(entry.title, entry.details, { command:
|
|
153
|
+
(0, messages_1.printErrorWithHelp)(entry.title, entry.details, { command: "ai create" });
|
|
154
154
|
process.exitCode = 1;
|
|
155
155
|
return true;
|
|
156
156
|
}
|
|
157
157
|
function handleGenerateImageReferenceError(message) {
|
|
158
158
|
const imageRefHandlers = [
|
|
159
159
|
{
|
|
160
|
-
prefix:
|
|
161
|
-
title: (optionName) => `The ${optionName ||
|
|
162
|
-
details: (path) => [path ? `Missing file: ${path}` :
|
|
160
|
+
prefix: "image_ref_not_found:",
|
|
161
|
+
title: (optionName) => `The ${optionName || "image"} reference file was not found.`,
|
|
162
|
+
details: (path) => [path ? `Missing file: ${path}` : "Provide a valid local file path or HTTPS URL."],
|
|
163
163
|
},
|
|
164
164
|
{
|
|
165
|
-
prefix:
|
|
166
|
-
title: (optionName) => `The ${optionName ||
|
|
167
|
-
details: (path) => [path ? `Path must point to a file: ${path}` :
|
|
165
|
+
prefix: "image_ref_not_file:",
|
|
166
|
+
title: (optionName) => `The ${optionName || "image"} reference is not a file.`,
|
|
167
|
+
details: (path) => [path ? `Path must point to a file: ${path}` : "Provide a valid local file path."],
|
|
168
168
|
},
|
|
169
169
|
{
|
|
170
|
-
prefix:
|
|
171
|
-
title: (optionName) => `The ${optionName ||
|
|
172
|
-
details: (scheme) => [`Use an HTTPS URL or a local file path. Received: ${scheme ||
|
|
170
|
+
prefix: "image_ref_invalid_scheme:",
|
|
171
|
+
title: (optionName) => `The ${optionName || "image"} reference URL uses an unsupported scheme.`,
|
|
172
|
+
details: (scheme) => [`Use an HTTPS URL or a local file path. Received: ${scheme || "unknown"}`],
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
|
-
prefix:
|
|
176
|
-
title: (optionName) => `The ${optionName ||
|
|
177
|
-
details: (path) => [
|
|
175
|
+
prefix: "image_ref_signature_mismatch:",
|
|
176
|
+
title: (optionName) => `The ${optionName || "image"} reference file extension does not match its image signature.`,
|
|
177
|
+
details: (path) => [
|
|
178
|
+
path
|
|
179
|
+
? `Fix file type mismatch for: ${path}`
|
|
180
|
+
: "Ensure extension and file signature match (.png, .jpg, .jpeg, .webp).",
|
|
181
|
+
],
|
|
178
182
|
},
|
|
179
183
|
{
|
|
180
|
-
prefix:
|
|
181
|
-
title: (optionName) => `The ${optionName ||
|
|
184
|
+
prefix: "image_ref_unsupported_type:",
|
|
185
|
+
title: (optionName) => `The ${optionName || "image"} reference file type is unsupported.`,
|
|
182
186
|
details: (path) => [
|
|
183
|
-
path ? `Unsupported file: ${path}` :
|
|
184
|
-
|
|
187
|
+
path ? `Unsupported file: ${path}` : "Provide a supported local file.",
|
|
188
|
+
"Supported local image types: .png, .jpg, .jpeg, .webp.",
|
|
185
189
|
],
|
|
186
190
|
},
|
|
187
191
|
];
|
|
@@ -189,8 +193,8 @@ function handleGenerateImageReferenceError(message) {
|
|
|
189
193
|
if (!message.startsWith(handler.prefix)) {
|
|
190
194
|
continue;
|
|
191
195
|
}
|
|
192
|
-
const [, optionName, value] = message.split(
|
|
193
|
-
(0, messages_1.printErrorWithHelp)(handler.title(optionName), handler.details(value), { command:
|
|
196
|
+
const [, optionName, value] = message.split(":");
|
|
197
|
+
(0, messages_1.printErrorWithHelp)(handler.title(optionName), handler.details(value), { command: "ai create" });
|
|
194
198
|
process.exitCode = 1;
|
|
195
199
|
return true;
|
|
196
200
|
}
|
|
@@ -202,43 +206,46 @@ function sleep(ms) {
|
|
|
202
206
|
});
|
|
203
207
|
}
|
|
204
208
|
function normalizeModality(value) {
|
|
205
|
-
const normalized = value
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
209
|
+
const normalized = value
|
|
210
|
+
.trim()
|
|
211
|
+
.toUpperCase()
|
|
212
|
+
.replace(/[-\s]+/g, "_");
|
|
213
|
+
if (normalized === "IMAGE")
|
|
214
|
+
return "IMAGE";
|
|
215
|
+
if (normalized === "MUSIC")
|
|
216
|
+
return "MUSIC";
|
|
217
|
+
if (normalized === "SFX")
|
|
218
|
+
return "SFX";
|
|
219
|
+
if (normalized === "SPEECH")
|
|
220
|
+
return "SPEECH";
|
|
221
|
+
if (normalized === "VIDEO")
|
|
222
|
+
return "VIDEO";
|
|
223
|
+
if (normalized === "MODEL3D" || normalized === "MODEL_3D")
|
|
224
|
+
return "MODEL_3D";
|
|
218
225
|
return null;
|
|
219
226
|
}
|
|
220
227
|
function normalizeVisibility(value) {
|
|
221
|
-
if (typeof value !==
|
|
228
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
222
229
|
return undefined;
|
|
223
230
|
}
|
|
224
231
|
const normalized = value.trim().toUpperCase();
|
|
225
|
-
if (normalized ===
|
|
232
|
+
if (normalized === "PRIVATE" || normalized === "PUBLIC") {
|
|
226
233
|
return normalized;
|
|
227
234
|
}
|
|
228
235
|
return undefined;
|
|
229
236
|
}
|
|
230
237
|
function parseAssetSubcategory(value) {
|
|
231
|
-
if (typeof value !==
|
|
238
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
232
239
|
return undefined;
|
|
233
240
|
}
|
|
234
241
|
const normalized = (0, types_1.normalizeAssetSubcategory)(value);
|
|
235
242
|
if (!(0, types_1.isValidAssetSubcategorySlug)(normalized)) {
|
|
236
|
-
throw new Error(
|
|
243
|
+
throw new Error("invalid_asset_subcategory");
|
|
237
244
|
}
|
|
238
245
|
return normalized;
|
|
239
246
|
}
|
|
240
247
|
function parseOptionalPositiveInt(value, field) {
|
|
241
|
-
if (value === undefined || value === null || value ===
|
|
248
|
+
if (value === undefined || value === null || value === "") {
|
|
242
249
|
return undefined;
|
|
243
250
|
}
|
|
244
251
|
const raw = String(value).trim();
|
|
@@ -252,7 +259,7 @@ function parseOptionalPositiveInt(value, field) {
|
|
|
252
259
|
return parsed;
|
|
253
260
|
}
|
|
254
261
|
function parseOptionalNonNegativeInt(value, field) {
|
|
255
|
-
if (value === undefined || value === null || value ===
|
|
262
|
+
if (value === undefined || value === null || value === "") {
|
|
256
263
|
return undefined;
|
|
257
264
|
}
|
|
258
265
|
const raw = String(value).trim();
|
|
@@ -266,40 +273,40 @@ function parseOptionalNonNegativeInt(value, field) {
|
|
|
266
273
|
return parsed;
|
|
267
274
|
}
|
|
268
275
|
function parseOptionalDuration(value) {
|
|
269
|
-
if (value === undefined || value === null || value ===
|
|
276
|
+
if (value === undefined || value === null || value === "") {
|
|
270
277
|
return undefined;
|
|
271
278
|
}
|
|
272
279
|
const raw = String(value).trim().toLowerCase();
|
|
273
280
|
if (!raw.length) {
|
|
274
281
|
return undefined;
|
|
275
282
|
}
|
|
276
|
-
if (raw.endsWith(
|
|
283
|
+
if (raw.endsWith("ms")) {
|
|
277
284
|
const parsed = Number(raw.slice(0, -2).trim());
|
|
278
285
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
279
|
-
throw new Error(
|
|
286
|
+
throw new Error("invalid_duration");
|
|
280
287
|
}
|
|
281
|
-
return { value: parsed, unit:
|
|
288
|
+
return { value: parsed, unit: "ms" };
|
|
282
289
|
}
|
|
283
|
-
if (raw.endsWith(
|
|
290
|
+
if (raw.endsWith("s")) {
|
|
284
291
|
const parsed = Number(raw.slice(0, -1).trim());
|
|
285
292
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
286
|
-
throw new Error(
|
|
293
|
+
throw new Error("invalid_duration");
|
|
287
294
|
}
|
|
288
|
-
return { value: parsed, unit:
|
|
295
|
+
return { value: parsed, unit: "s" };
|
|
289
296
|
}
|
|
290
297
|
const parsed = Number(raw);
|
|
291
298
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
292
|
-
throw new Error(
|
|
299
|
+
throw new Error("invalid_duration");
|
|
293
300
|
}
|
|
294
|
-
return { value: parsed, unit:
|
|
301
|
+
return { value: parsed, unit: "plain" };
|
|
295
302
|
}
|
|
296
303
|
function parseMusicDurationMs(duration) {
|
|
297
304
|
if (!duration) {
|
|
298
305
|
return undefined;
|
|
299
306
|
}
|
|
300
|
-
const milliseconds = duration.unit ===
|
|
307
|
+
const milliseconds = duration.unit === "s" ? duration.value * 1000 : duration.value;
|
|
301
308
|
if (!Number.isInteger(milliseconds) || milliseconds <= 0) {
|
|
302
|
-
throw new Error(
|
|
309
|
+
throw new Error("invalid_duration");
|
|
303
310
|
}
|
|
304
311
|
return milliseconds;
|
|
305
312
|
}
|
|
@@ -307,9 +314,9 @@ function parseSecondsDuration(duration) {
|
|
|
307
314
|
if (!duration) {
|
|
308
315
|
return undefined;
|
|
309
316
|
}
|
|
310
|
-
const seconds = duration.unit ===
|
|
317
|
+
const seconds = duration.unit === "ms" ? duration.value / 1000 : duration.value;
|
|
311
318
|
if (!Number.isFinite(seconds) || seconds <= 0) {
|
|
312
|
-
throw new Error(
|
|
319
|
+
throw new Error("invalid_duration");
|
|
313
320
|
}
|
|
314
321
|
return seconds;
|
|
315
322
|
}
|
|
@@ -319,16 +326,16 @@ function parseVideoDurationSeconds(duration) {
|
|
|
319
326
|
return undefined;
|
|
320
327
|
}
|
|
321
328
|
if (!Number.isInteger(seconds) || (seconds !== 4 && seconds !== 8)) {
|
|
322
|
-
throw new Error(
|
|
329
|
+
throw new Error("invalid_video_duration");
|
|
323
330
|
}
|
|
324
331
|
return seconds;
|
|
325
332
|
}
|
|
326
333
|
function parseListFormat(raw) {
|
|
327
334
|
if (!raw || raw.trim().length === 0) {
|
|
328
|
-
return
|
|
335
|
+
return "text";
|
|
329
336
|
}
|
|
330
337
|
const normalized = raw.trim().toLowerCase();
|
|
331
|
-
if (normalized ===
|
|
338
|
+
if (normalized === "text" || normalized === "json") {
|
|
332
339
|
return normalized;
|
|
333
340
|
}
|
|
334
341
|
return null;
|
|
@@ -337,15 +344,18 @@ function parseListType(raw) {
|
|
|
337
344
|
if (!raw || raw.trim().length === 0) {
|
|
338
345
|
return undefined;
|
|
339
346
|
}
|
|
340
|
-
const normalized = raw
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
347
|
+
const normalized = raw
|
|
348
|
+
.trim()
|
|
349
|
+
.toLowerCase()
|
|
350
|
+
.replace(/[-\s]+/g, "_");
|
|
351
|
+
if (normalized === "text" ||
|
|
352
|
+
normalized === "json" ||
|
|
353
|
+
normalized === "image" ||
|
|
354
|
+
normalized === "music" ||
|
|
355
|
+
normalized === "sfx" ||
|
|
356
|
+
normalized === "speech" ||
|
|
357
|
+
normalized === "video" ||
|
|
358
|
+
normalized === "model_3d") {
|
|
349
359
|
return normalized;
|
|
350
360
|
}
|
|
351
361
|
return null;
|
|
@@ -354,14 +364,14 @@ function isPngSignature(buffer) {
|
|
|
354
364
|
if (buffer.length < 8) {
|
|
355
365
|
return false;
|
|
356
366
|
}
|
|
357
|
-
return (buffer[0] === 0x89
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
367
|
+
return (buffer[0] === 0x89 &&
|
|
368
|
+
buffer[1] === 0x50 &&
|
|
369
|
+
buffer[2] === 0x4e &&
|
|
370
|
+
buffer[3] === 0x47 &&
|
|
371
|
+
buffer[4] === 0x0d &&
|
|
372
|
+
buffer[5] === 0x0a &&
|
|
373
|
+
buffer[6] === 0x1a &&
|
|
374
|
+
buffer[7] === 0x0a);
|
|
365
375
|
}
|
|
366
376
|
function isJpegSignature(buffer) {
|
|
367
377
|
if (buffer.length < 3) {
|
|
@@ -373,18 +383,17 @@ function isWebpSignature(buffer) {
|
|
|
373
383
|
if (buffer.length < 12) {
|
|
374
384
|
return false;
|
|
375
385
|
}
|
|
376
|
-
return
|
|
377
|
-
&& buffer.toString('ascii', 8, 12) === 'WEBP');
|
|
386
|
+
return buffer.toString("ascii", 0, 4) === "RIFF" && buffer.toString("ascii", 8, 12) === "WEBP";
|
|
378
387
|
}
|
|
379
388
|
function detectLocalImageMimeType(buffer) {
|
|
380
389
|
if (isPngSignature(buffer)) {
|
|
381
|
-
return
|
|
390
|
+
return "image/png";
|
|
382
391
|
}
|
|
383
392
|
if (isJpegSignature(buffer)) {
|
|
384
|
-
return
|
|
393
|
+
return "image/jpeg";
|
|
385
394
|
}
|
|
386
395
|
if (isWebpSignature(buffer)) {
|
|
387
|
-
return
|
|
396
|
+
return "image/webp";
|
|
388
397
|
}
|
|
389
398
|
return null;
|
|
390
399
|
}
|
|
@@ -410,12 +419,12 @@ function resolveLocalImageAttachment(optionName, value) {
|
|
|
410
419
|
throw new Error(`image_ref_signature_mismatch:${optionName}:${resolvedPath}`);
|
|
411
420
|
}
|
|
412
421
|
return {
|
|
413
|
-
data: imageBuffer.toString(
|
|
422
|
+
data: imageBuffer.toString("base64"),
|
|
414
423
|
mimeType: detectedMime,
|
|
415
424
|
};
|
|
416
425
|
}
|
|
417
426
|
function resolveImageAttachment(value, optionName) {
|
|
418
|
-
if (typeof value !==
|
|
427
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
419
428
|
return undefined;
|
|
420
429
|
}
|
|
421
430
|
const trimmed = value.trim();
|
|
@@ -424,84 +433,86 @@ function resolveImageAttachment(value, optionName) {
|
|
|
424
433
|
}
|
|
425
434
|
try {
|
|
426
435
|
const parsed = new URL(trimmed);
|
|
427
|
-
if (parsed.protocol !==
|
|
436
|
+
if (parsed.protocol !== "https:") {
|
|
428
437
|
throw new Error(`image_ref_invalid_scheme:${optionName}:${parsed.protocol}`);
|
|
429
438
|
}
|
|
430
439
|
return { url: trimmed };
|
|
431
440
|
}
|
|
432
441
|
catch (error) {
|
|
433
|
-
if (error instanceof Error && error.message.startsWith(
|
|
442
|
+
if (error instanceof Error && error.message.startsWith("image_ref_invalid_scheme:")) {
|
|
434
443
|
throw error;
|
|
435
444
|
}
|
|
436
445
|
return resolveLocalImageAttachment(optionName, trimmed);
|
|
437
446
|
}
|
|
438
447
|
}
|
|
439
448
|
function buildGenerateRequest(typeInput, promptInput, options) {
|
|
440
|
-
const type = typeof typeInput ===
|
|
449
|
+
const type = typeof typeInput === "string" ? typeInput.trim() : "";
|
|
441
450
|
if (!type.length) {
|
|
442
|
-
throw new Error(
|
|
451
|
+
throw new Error("missing_type");
|
|
443
452
|
}
|
|
444
453
|
const modality = normalizeModality(type);
|
|
445
454
|
if (!modality) {
|
|
446
|
-
throw new Error(
|
|
455
|
+
throw new Error("invalid_type");
|
|
447
456
|
}
|
|
448
|
-
const prompt = modality ===
|
|
449
|
-
? (0, types_1.normalizeSpeechText)(typeof promptInput ===
|
|
450
|
-
: typeof promptInput ===
|
|
457
|
+
const prompt = modality === "SPEECH"
|
|
458
|
+
? (0, types_1.normalizeSpeechText)(typeof promptInput === "string" ? promptInput : "")
|
|
459
|
+
: typeof promptInput === "string"
|
|
451
460
|
? promptInput.trim()
|
|
452
|
-
:
|
|
461
|
+
: "";
|
|
453
462
|
if (!prompt.length) {
|
|
454
|
-
throw new Error(
|
|
463
|
+
throw new Error("missing_prompt");
|
|
455
464
|
}
|
|
456
|
-
if (modality ===
|
|
457
|
-
throw new Error(
|
|
465
|
+
if (modality === "SPEECH" && (0, types_1.countSpeechWords)(prompt) > types_1.PLAYDROP_SPEECH_MAX_WORDS) {
|
|
466
|
+
throw new Error("speech_input_too_long");
|
|
458
467
|
}
|
|
459
468
|
const visibility = normalizeVisibility(options.visibility);
|
|
460
469
|
if (options.visibility && !visibility) {
|
|
461
|
-
throw new Error(
|
|
470
|
+
throw new Error("invalid_visibility");
|
|
462
471
|
}
|
|
463
|
-
const timeoutSeconds = parseOptionalPositiveInt(options.timeoutSeconds,
|
|
464
|
-
const pollIntervalMs = parseOptionalPositiveInt(options.pollIntervalMs,
|
|
472
|
+
const timeoutSeconds = parseOptionalPositiveInt(options.timeoutSeconds, "timeout_seconds") ?? GENERATE_DEFAULT_TIMEOUT_SECONDS;
|
|
473
|
+
const pollIntervalMs = parseOptionalPositiveInt(options.pollIntervalMs, "poll_interval_ms") ?? GENERATE_DEFAULT_POLL_INTERVAL_MS;
|
|
465
474
|
if (pollIntervalMs < 250) {
|
|
466
|
-
throw new Error(
|
|
475
|
+
throw new Error("invalid_poll_interval_ms");
|
|
467
476
|
}
|
|
468
477
|
const duration = parseOptionalDuration(options.duration);
|
|
469
478
|
const request = {
|
|
470
479
|
modality,
|
|
471
480
|
input: prompt,
|
|
472
|
-
assetName: typeof options.assetName ===
|
|
473
|
-
|
|
481
|
+
assetName: typeof options.assetName === "string" && options.assetName.trim().length > 0
|
|
482
|
+
? options.assetName.trim()
|
|
483
|
+
: undefined,
|
|
484
|
+
assetDisplayName: typeof options.assetDisplayName === "string" && options.assetDisplayName.trim().length > 0
|
|
474
485
|
? options.assetDisplayName.trim()
|
|
475
486
|
: undefined,
|
|
476
|
-
assetDescription: typeof options.assetDescription ===
|
|
487
|
+
assetDescription: typeof options.assetDescription === "string" && options.assetDescription.trim().length > 0
|
|
477
488
|
? options.assetDescription.trim()
|
|
478
489
|
: undefined,
|
|
479
|
-
assetVisibility: visibility ??
|
|
480
|
-
attachAppVersionId: parseOptionalPositiveInt(options.attachAppVersionId,
|
|
490
|
+
assetVisibility: visibility ?? "PUBLIC",
|
|
491
|
+
attachAppVersionId: parseOptionalPositiveInt(options.attachAppVersionId, "attach_app_version_id"),
|
|
481
492
|
};
|
|
482
|
-
if (modality !==
|
|
493
|
+
if (modality !== "SPEECH") {
|
|
483
494
|
request.assetSubcategory = parseAssetSubcategory(options.subcategory) ?? DEFAULT_SUBCATEGORY_BY_MODALITY[modality];
|
|
484
495
|
}
|
|
485
|
-
else if (typeof options.subcategory ===
|
|
486
|
-
throw new Error(
|
|
496
|
+
else if (typeof options.subcategory === "string" && options.subcategory.trim().length > 0) {
|
|
497
|
+
throw new Error("speech_disallows_subcategory");
|
|
487
498
|
}
|
|
488
|
-
if (modality ===
|
|
489
|
-
request.image1 = resolveImageAttachment(options.image1,
|
|
490
|
-
request.image2 = resolveImageAttachment(options.image2,
|
|
491
|
-
if (typeof options.ratio ===
|
|
499
|
+
if (modality === "IMAGE") {
|
|
500
|
+
request.image1 = resolveImageAttachment(options.image1, "image1");
|
|
501
|
+
request.image2 = resolveImageAttachment(options.image2, "image2");
|
|
502
|
+
if (typeof options.ratio === "string" && options.ratio.trim().length > 0) {
|
|
492
503
|
const aspectRatio = options.ratio.trim();
|
|
493
504
|
if (!IMAGE_ASPECT_RATIO_SET.has(aspectRatio)) {
|
|
494
|
-
throw new Error(
|
|
505
|
+
throw new Error("invalid_aspect_ratio");
|
|
495
506
|
}
|
|
496
507
|
request.aspectRatio = aspectRatio;
|
|
497
508
|
}
|
|
498
509
|
else {
|
|
499
510
|
request.aspectRatio = DEFAULT_IMAGE_ASPECT_RATIO;
|
|
500
511
|
}
|
|
501
|
-
if (typeof options.size ===
|
|
512
|
+
if (typeof options.size === "string" && options.size.trim().length > 0) {
|
|
502
513
|
const imageSize = options.size.trim().toUpperCase();
|
|
503
514
|
if (!IMAGE_SIZE_SET.has(imageSize)) {
|
|
504
|
-
throw new Error(
|
|
515
|
+
throw new Error("invalid_image_size");
|
|
505
516
|
}
|
|
506
517
|
request.imageSize = imageSize;
|
|
507
518
|
}
|
|
@@ -509,104 +520,116 @@ function buildGenerateRequest(typeInput, promptInput, options) {
|
|
|
509
520
|
request.imageSize = DEFAULT_IMAGE_SIZE;
|
|
510
521
|
}
|
|
511
522
|
}
|
|
512
|
-
else if (typeof options.size ===
|
|
513
|
-
throw new Error(
|
|
523
|
+
else if (typeof options.size === "string" && options.size.trim().length > 0) {
|
|
524
|
+
throw new Error("image_size_not_supported_for_modality");
|
|
514
525
|
}
|
|
515
|
-
if (modality ===
|
|
526
|
+
if (modality === "MUSIC") {
|
|
516
527
|
request.durationMs = parseMusicDurationMs(duration);
|
|
517
528
|
request.forceInstrumental = Boolean(options.instrumental);
|
|
518
|
-
request.coverPrompt =
|
|
529
|
+
request.coverPrompt =
|
|
530
|
+
typeof options.coverPrompt === "string" && options.coverPrompt.trim().length > 0
|
|
531
|
+
? options.coverPrompt.trim()
|
|
532
|
+
: undefined;
|
|
519
533
|
}
|
|
520
|
-
if (modality ===
|
|
534
|
+
if (modality === "SFX") {
|
|
521
535
|
request.durationSeconds = parseSecondsDuration(duration);
|
|
522
536
|
request.loop = Boolean(options.loop);
|
|
523
|
-
request.coverPrompt =
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
537
|
+
request.coverPrompt =
|
|
538
|
+
typeof options.coverPrompt === "string" && options.coverPrompt.trim().length > 0
|
|
539
|
+
? options.coverPrompt.trim()
|
|
540
|
+
: undefined;
|
|
541
|
+
}
|
|
542
|
+
if (modality === "SPEECH") {
|
|
543
|
+
const speechVoice = typeof options.voice === "string" && options.voice.trim().length > 0 ? options.voice.trim() : undefined;
|
|
544
|
+
const speechProviderVoiceId = typeof options.providerVoiceId === "string" && options.providerVoiceId.trim().length > 0
|
|
528
545
|
? options.providerVoiceId.trim()
|
|
529
546
|
: undefined;
|
|
530
547
|
if (speechVoice && speechProviderVoiceId) {
|
|
531
|
-
throw new Error(
|
|
548
|
+
throw new Error("invalid_speech_voice_selection");
|
|
532
549
|
}
|
|
533
550
|
let validatedSpeechVoice;
|
|
534
551
|
if (speechVoice) {
|
|
535
552
|
if (!isPlaydropSpeechVoiceId(speechVoice)) {
|
|
536
|
-
throw new Error(
|
|
553
|
+
throw new Error("invalid_speech_voice");
|
|
537
554
|
}
|
|
538
555
|
validatedSpeechVoice = speechVoice;
|
|
539
556
|
}
|
|
540
557
|
request.speechVoice = validatedSpeechVoice;
|
|
541
558
|
request.speechProviderVoiceId = speechProviderVoiceId;
|
|
542
559
|
}
|
|
543
|
-
if (modality ===
|
|
544
|
-
request.image1 = resolveImageAttachment(options.image1,
|
|
545
|
-
request.image2 = resolveImageAttachment(options.image2,
|
|
560
|
+
if (modality === "VIDEO") {
|
|
561
|
+
request.image1 = resolveImageAttachment(options.image1, "image1");
|
|
562
|
+
request.image2 = resolveImageAttachment(options.image2, "image2");
|
|
546
563
|
const durationSeconds = parseVideoDurationSeconds(duration);
|
|
547
564
|
const hasFirstAndLastFrame = Boolean(request.image1 && request.image2);
|
|
548
565
|
request.durationSeconds = hasFirstAndLastFrame
|
|
549
566
|
? VIDEO_FIRST_LAST_FRAME_DURATION_SECONDS
|
|
550
567
|
: (durationSeconds ?? DEFAULT_VIDEO_DURATION_SECONDS);
|
|
551
|
-
if (typeof options.ratio ===
|
|
568
|
+
if (typeof options.ratio === "string" && options.ratio.trim().length > 0) {
|
|
552
569
|
const aspectRatio = options.ratio.trim();
|
|
553
570
|
if (!VIDEO_ASPECT_RATIO_SET.has(aspectRatio)) {
|
|
554
|
-
throw new Error(
|
|
571
|
+
throw new Error("invalid_aspect_ratio");
|
|
555
572
|
}
|
|
556
573
|
request.aspectRatio = aspectRatio;
|
|
557
574
|
}
|
|
558
575
|
else {
|
|
559
576
|
request.aspectRatio = DEFAULT_VIDEO_ASPECT_RATIO;
|
|
560
577
|
}
|
|
561
|
-
if (options.resolution !== undefined && options.resolution !==
|
|
562
|
-
throw new Error(
|
|
578
|
+
if (options.resolution !== undefined && options.resolution !== "720p") {
|
|
579
|
+
throw new Error("invalid_resolution");
|
|
563
580
|
}
|
|
564
581
|
request.resolution = options.resolution;
|
|
565
582
|
}
|
|
566
|
-
if (modality ===
|
|
567
|
-
const sourceModeInput = typeof options.sourceMode ===
|
|
568
|
-
if (sourceModeInput.length > 0 && sourceModeInput !==
|
|
569
|
-
throw new Error(
|
|
583
|
+
if (modality === "MODEL_3D") {
|
|
584
|
+
const sourceModeInput = typeof options.sourceMode === "string" ? options.sourceMode.trim().toUpperCase() : "";
|
|
585
|
+
if (sourceModeInput.length > 0 && sourceModeInput !== "TEXT" && sourceModeInput !== "IMAGE") {
|
|
586
|
+
throw new Error("invalid_source_mode");
|
|
570
587
|
}
|
|
571
|
-
request.image1 = resolveImageAttachment(options.image1,
|
|
572
|
-
request.image2 = resolveImageAttachment(options.image2,
|
|
588
|
+
request.image1 = resolveImageAttachment(options.image1, "image1");
|
|
589
|
+
request.image2 = resolveImageAttachment(options.image2, "image2");
|
|
573
590
|
const hasInputImages = Boolean(request.image1 || request.image2);
|
|
574
|
-
request.sourceMode =
|
|
575
|
-
? sourceModeInput
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
throw new Error('missing_model3d_images');
|
|
591
|
+
request.sourceMode =
|
|
592
|
+
sourceModeInput.length > 0 ? sourceModeInput : hasInputImages ? "IMAGE" : "TEXT";
|
|
593
|
+
if (request.sourceMode === "IMAGE" && !hasInputImages) {
|
|
594
|
+
throw new Error("missing_model3d_images");
|
|
579
595
|
}
|
|
580
|
-
if (request.sourceMode ===
|
|
581
|
-
throw new Error(
|
|
596
|
+
if (request.sourceMode === "TEXT" && hasInputImages) {
|
|
597
|
+
throw new Error("model3d_text_mode_disallows_images");
|
|
582
598
|
}
|
|
583
|
-
const topology = typeof options.topology ===
|
|
584
|
-
if (topology.length > 0 && topology !==
|
|
585
|
-
throw new Error(
|
|
599
|
+
const topology = typeof options.topology === "string" ? options.topology.trim().toLowerCase() : "";
|
|
600
|
+
if (topology.length > 0 && topology !== "triangle" && topology !== "quad") {
|
|
601
|
+
throw new Error("invalid_topology");
|
|
586
602
|
}
|
|
587
603
|
request.topology = topology.length > 0 ? topology : DEFAULT_MODEL3D_TOPOLOGY;
|
|
588
|
-
request.targetPolycount =
|
|
589
|
-
|
|
590
|
-
request.
|
|
604
|
+
request.targetPolycount =
|
|
605
|
+
parseOptionalPositiveInt(options.polycount, "polycount") ?? DEFAULT_MODEL3D_TARGET_POLYCOUNT;
|
|
606
|
+
request.shouldRemesh = typeof options.remesh === "boolean" ? options.remesh : DEFAULT_MODEL3D_SHOULD_REMESH;
|
|
607
|
+
request.shouldTexture = typeof options.texture === "boolean" ? options.texture : DEFAULT_MODEL3D_SHOULD_TEXTURE;
|
|
591
608
|
}
|
|
592
609
|
return { modality, request, timeoutSeconds, pollIntervalMs };
|
|
593
610
|
}
|
|
594
611
|
function generationPrompt(record) {
|
|
595
|
-
if (
|
|
612
|
+
if ("inputPrompt" in record && typeof record.inputPrompt === "string") {
|
|
596
613
|
return record.inputPrompt;
|
|
597
614
|
}
|
|
598
|
-
return
|
|
615
|
+
return "";
|
|
599
616
|
}
|
|
600
617
|
function generationAssetRef(record) {
|
|
601
618
|
const candidate = record.generatedAsset;
|
|
602
|
-
if (candidate &&
|
|
619
|
+
if (candidate &&
|
|
620
|
+
typeof candidate === "object" &&
|
|
621
|
+
typeof candidate.ref === "string" &&
|
|
622
|
+
candidate.ref.trim().length > 0) {
|
|
603
623
|
return candidate.ref.trim();
|
|
604
624
|
}
|
|
605
625
|
return null;
|
|
606
626
|
}
|
|
607
627
|
function generationAssetSubcategory(record) {
|
|
608
628
|
const candidate = record.generatedAsset;
|
|
609
|
-
if (candidate &&
|
|
629
|
+
if (candidate &&
|
|
630
|
+
typeof candidate === "object" &&
|
|
631
|
+
typeof candidate.subcategory === "string" &&
|
|
632
|
+
candidate.subcategory.trim().length > 0) {
|
|
610
633
|
return candidate.subcategory.trim();
|
|
611
634
|
}
|
|
612
635
|
return null;
|
|
@@ -616,14 +639,14 @@ function printGenerateResult(modality, payload) {
|
|
|
616
639
|
if (payload?.billing?.generationId) {
|
|
617
640
|
console.log(`Generation ID: ${payload.billing.generationId}`);
|
|
618
641
|
}
|
|
619
|
-
if (typeof payload?.cost ===
|
|
642
|
+
if (typeof payload?.cost === "number") {
|
|
620
643
|
console.log(`Cost: ${payload.cost}`);
|
|
621
644
|
}
|
|
622
|
-
if (typeof payload?.createdAt ===
|
|
645
|
+
if (typeof payload?.createdAt === "string") {
|
|
623
646
|
console.log(`Created At: ${payload.createdAt}`);
|
|
624
647
|
}
|
|
625
|
-
const ref = typeof payload?.generatedAsset?.ref ===
|
|
626
|
-
const subcategory = typeof payload?.generatedAsset?.subcategory ===
|
|
648
|
+
const ref = typeof payload?.generatedAsset?.ref === "string" ? payload.generatedAsset.ref : null;
|
|
649
|
+
const subcategory = typeof payload?.generatedAsset?.subcategory === "string" ? payload.generatedAsset.subcategory : null;
|
|
627
650
|
if (ref) {
|
|
628
651
|
console.log(`Generated Asset: ${ref}`);
|
|
629
652
|
if (subcategory) {
|
|
@@ -632,7 +655,7 @@ function printGenerateResult(modality, payload) {
|
|
|
632
655
|
console.log(`Next: run "playdrop detail ${ref}" to inspect the generated asset.`);
|
|
633
656
|
}
|
|
634
657
|
else {
|
|
635
|
-
console.log(
|
|
658
|
+
console.log("Generated Asset: none");
|
|
636
659
|
}
|
|
637
660
|
}
|
|
638
661
|
let pngOutputCrcTable = null;
|
|
@@ -644,7 +667,7 @@ function getPngOutputCrcTable() {
|
|
|
644
667
|
for (let n = 0; n < 256; n++) {
|
|
645
668
|
let c = n;
|
|
646
669
|
for (let k = 0; k < 8; k++) {
|
|
647
|
-
c =
|
|
670
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
648
671
|
}
|
|
649
672
|
table[n] = c >>> 0;
|
|
650
673
|
}
|
|
@@ -662,16 +685,12 @@ function pngOutputCrc32(buffer) {
|
|
|
662
685
|
}
|
|
663
686
|
function createPngOutputTextChunk(keyword, value) {
|
|
664
687
|
const keywordText = keyword.trim().slice(0, 79);
|
|
665
|
-
if (!/^[\x20-\x7e]+$/.test(keywordText) || keywordText.includes(
|
|
666
|
-
throw new Error(
|
|
667
|
-
}
|
|
668
|
-
const textValue = value.replace(/[^\x20-\xff]/g,
|
|
669
|
-
const data = Buffer.concat([
|
|
670
|
-
|
|
671
|
-
Buffer.from([0]),
|
|
672
|
-
Buffer.from(textValue, 'latin1'),
|
|
673
|
-
]);
|
|
674
|
-
const type = Buffer.from('tEXt', 'ascii');
|
|
688
|
+
if (!/^[\x20-\x7e]+$/.test(keywordText) || keywordText.includes("\0")) {
|
|
689
|
+
throw new Error("ai_generation_image_output_metadata_failed");
|
|
690
|
+
}
|
|
691
|
+
const textValue = value.replace(/[^\x20-\xff]/g, " ").slice(0, 4096);
|
|
692
|
+
const data = Buffer.concat([Buffer.from(keywordText, "latin1"), Buffer.from([0]), Buffer.from(textValue, "latin1")]);
|
|
693
|
+
const type = Buffer.from("tEXt", "ascii");
|
|
675
694
|
const length = Buffer.alloc(4);
|
|
676
695
|
length.writeUInt32BE(data.length, 0);
|
|
677
696
|
const crc = Buffer.alloc(4);
|
|
@@ -679,10 +698,10 @@ function createPngOutputTextChunk(keyword, value) {
|
|
|
679
698
|
return Buffer.concat([length, type, data, crc]);
|
|
680
699
|
}
|
|
681
700
|
function extractGeneratedImageUrl(payload) {
|
|
682
|
-
if (typeof payload?.imageUrl ===
|
|
701
|
+
if (typeof payload?.imageUrl === "string" && payload.imageUrl.trim()) {
|
|
683
702
|
return payload.imageUrl.trim();
|
|
684
703
|
}
|
|
685
|
-
if (typeof payload?.outputImage ===
|
|
704
|
+
if (typeof payload?.outputImage === "string" && payload.outputImage.trim()) {
|
|
686
705
|
return payload.outputImage.trim();
|
|
687
706
|
}
|
|
688
707
|
return null;
|
|
@@ -691,15 +710,15 @@ function embedGeneratedImageOutputMetadata(buffer, inputPrompt, payload) {
|
|
|
691
710
|
if (!isPngSignature(buffer)) {
|
|
692
711
|
return buffer;
|
|
693
712
|
}
|
|
694
|
-
const generationId = typeof payload?.billing?.generationId ===
|
|
713
|
+
const generationId = typeof payload?.billing?.generationId === "string"
|
|
695
714
|
? payload.billing.generationId
|
|
696
|
-
: typeof payload?.generationId ===
|
|
715
|
+
: typeof payload?.generationId === "string"
|
|
697
716
|
? payload.generationId
|
|
698
|
-
:
|
|
717
|
+
: "";
|
|
699
718
|
const chunks = [
|
|
700
|
-
createPngOutputTextChunk(
|
|
701
|
-
createPngOutputTextChunk(
|
|
702
|
-
...(generationId ? [createPngOutputTextChunk(
|
|
719
|
+
createPngOutputTextChunk("playdrop:cliOutputTool", "playdrop ai create image --output"),
|
|
720
|
+
createPngOutputTextChunk("playdrop:cliOutputPrompt", inputPrompt),
|
|
721
|
+
...(generationId ? [createPngOutputTextChunk("playdrop:generationId", generationId)] : []),
|
|
703
722
|
];
|
|
704
723
|
const signature = buffer.subarray(0, 8);
|
|
705
724
|
const parts = [signature];
|
|
@@ -709,40 +728,40 @@ function embedGeneratedImageOutputMetadata(buffer, inputPrompt, payload) {
|
|
|
709
728
|
const length = buffer.readUInt32BE(offset);
|
|
710
729
|
const chunkEnd = offset + 12 + length;
|
|
711
730
|
if (chunkEnd > buffer.length) {
|
|
712
|
-
throw new Error(
|
|
731
|
+
throw new Error("ai_generation_image_output_metadata_failed");
|
|
713
732
|
}
|
|
714
|
-
const chunkType = buffer.toString(
|
|
715
|
-
if (chunkType ===
|
|
733
|
+
const chunkType = buffer.toString("ascii", offset + 4, offset + 8);
|
|
734
|
+
if (chunkType === "IEND" && !inserted) {
|
|
716
735
|
parts.push(...chunks);
|
|
717
736
|
inserted = true;
|
|
718
737
|
}
|
|
719
738
|
parts.push(buffer.subarray(offset, chunkEnd));
|
|
720
739
|
offset = chunkEnd;
|
|
721
|
-
if (chunkType ===
|
|
740
|
+
if (chunkType === "IEND") {
|
|
722
741
|
break;
|
|
723
742
|
}
|
|
724
743
|
}
|
|
725
744
|
if (!inserted) {
|
|
726
|
-
throw new Error(
|
|
745
|
+
throw new Error("ai_generation_image_output_metadata_failed");
|
|
727
746
|
}
|
|
728
747
|
return Buffer.concat(parts);
|
|
729
748
|
}
|
|
730
749
|
async function writeGeneratedImageOutput(payload, outputPath, inputPrompt) {
|
|
731
750
|
const imageUrl = extractGeneratedImageUrl(payload);
|
|
732
751
|
if (!imageUrl) {
|
|
733
|
-
throw new Error(
|
|
752
|
+
throw new Error("ai_generation_image_output_missing");
|
|
734
753
|
}
|
|
735
754
|
const response = await fetch(imageUrl);
|
|
736
755
|
if (!response.ok) {
|
|
737
756
|
throw new Error(`ai_generation_image_output_fetch_failed:${response.status}`);
|
|
738
757
|
}
|
|
739
|
-
const contentType = response.headers.get(
|
|
740
|
-
if (!contentType.startsWith(
|
|
741
|
-
throw new Error(`ai_generation_image_output_invalid_content_type:${contentType ||
|
|
758
|
+
const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
|
|
759
|
+
if (!contentType.startsWith("image/")) {
|
|
760
|
+
throw new Error(`ai_generation_image_output_invalid_content_type:${contentType || "unknown"}`);
|
|
742
761
|
}
|
|
743
762
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
744
763
|
if (buffer.length === 0) {
|
|
745
|
-
throw new Error(
|
|
764
|
+
throw new Error("ai_generation_image_output_empty");
|
|
746
765
|
}
|
|
747
766
|
const normalizedBuffer = await normalizeGeneratedImageOutputBuffer(buffer, outputPath);
|
|
748
767
|
const outputBuffer = embedGeneratedImageOutputMetadata(normalizedBuffer, inputPrompt, payload);
|
|
@@ -759,36 +778,36 @@ async function normalizeGeneratedImageOutputBuffer(buffer, outputPath) {
|
|
|
759
778
|
}
|
|
760
779
|
const detectedMimeType = detectLocalImageMimeType(buffer);
|
|
761
780
|
if (!detectedMimeType) {
|
|
762
|
-
throw new Error(
|
|
781
|
+
throw new Error("ai_generation_image_output_unsupported_type");
|
|
763
782
|
}
|
|
764
783
|
if (detectedMimeType === targetMimeType) {
|
|
765
|
-
if (targetMimeType ===
|
|
784
|
+
if (targetMimeType === "image/png" && buffer.length > GENERATED_PNG_OUTPUT_MAX_BYTES) {
|
|
766
785
|
return optimizeGeneratedPngOutputBuffer(buffer);
|
|
767
786
|
}
|
|
768
787
|
return buffer;
|
|
769
788
|
}
|
|
770
789
|
let sharp;
|
|
771
790
|
try {
|
|
772
|
-
const sharpModule = await Promise.resolve().then(() => __importStar(require(
|
|
791
|
+
const sharpModule = await Promise.resolve().then(() => __importStar(require("sharp")));
|
|
773
792
|
sharp = sharpModule.default ?? sharpModule;
|
|
774
793
|
}
|
|
775
794
|
catch {
|
|
776
|
-
throw new Error(
|
|
795
|
+
throw new Error("ai_generation_image_output_conversion_unavailable");
|
|
777
796
|
}
|
|
778
797
|
try {
|
|
779
|
-
if (targetMimeType ===
|
|
798
|
+
if (targetMimeType === "image/png") {
|
|
780
799
|
return await optimizeGeneratedPngOutputBuffer(buffer, sharp);
|
|
781
800
|
}
|
|
782
|
-
const pipeline = sharp(buffer, { failOn:
|
|
783
|
-
if (targetMimeType ===
|
|
801
|
+
const pipeline = sharp(buffer, { failOn: "error" });
|
|
802
|
+
if (targetMimeType === "image/jpeg") {
|
|
784
803
|
return await pipeline.jpeg({ quality: 92 }).toBuffer();
|
|
785
804
|
}
|
|
786
|
-
if (targetMimeType ===
|
|
805
|
+
if (targetMimeType === "image/webp") {
|
|
787
806
|
return await pipeline.webp({ quality: 92 }).toBuffer();
|
|
788
807
|
}
|
|
789
808
|
}
|
|
790
809
|
catch {
|
|
791
|
-
throw new Error(
|
|
810
|
+
throw new Error("ai_generation_image_output_conversion_failed");
|
|
792
811
|
}
|
|
793
812
|
return buffer;
|
|
794
813
|
}
|
|
@@ -796,16 +815,16 @@ async function optimizeGeneratedPngOutputBuffer(buffer, loadedSharp) {
|
|
|
796
815
|
let sharp = loadedSharp;
|
|
797
816
|
if (!sharp) {
|
|
798
817
|
try {
|
|
799
|
-
const sharpModule = await Promise.resolve().then(() => __importStar(require(
|
|
818
|
+
const sharpModule = await Promise.resolve().then(() => __importStar(require("sharp")));
|
|
800
819
|
sharp = sharpModule.default ?? sharpModule;
|
|
801
820
|
}
|
|
802
821
|
catch {
|
|
803
|
-
throw new Error(
|
|
822
|
+
throw new Error("ai_generation_image_output_conversion_unavailable");
|
|
804
823
|
}
|
|
805
824
|
}
|
|
806
|
-
const metadata = await sharp(buffer, { failOn:
|
|
807
|
-
const sourceWidth = typeof metadata.width ===
|
|
808
|
-
const sourceHeight = typeof metadata.height ===
|
|
825
|
+
const metadata = await sharp(buffer, { failOn: "error" }).metadata();
|
|
826
|
+
const sourceWidth = typeof metadata.width === "number" && metadata.width > 0 ? metadata.width : null;
|
|
827
|
+
const sourceHeight = typeof metadata.height === "number" && metadata.height > 0 ? metadata.height : null;
|
|
809
828
|
const attempts = [
|
|
810
829
|
{ scale: 1, palette: false, quality: 100 },
|
|
811
830
|
{ scale: 1, palette: true, quality: 92 },
|
|
@@ -817,20 +836,22 @@ async function optimizeGeneratedPngOutputBuffer(buffer, loadedSharp) {
|
|
|
817
836
|
];
|
|
818
837
|
let smallest = null;
|
|
819
838
|
for (const attempt of attempts) {
|
|
820
|
-
let pipeline = sharp(buffer, { failOn:
|
|
839
|
+
let pipeline = sharp(buffer, { failOn: "error" }).rotate();
|
|
821
840
|
if (attempt.scale < 1 && sourceWidth && sourceHeight) {
|
|
822
841
|
pipeline = pipeline.resize({
|
|
823
842
|
width: Math.max(1, Math.round(sourceWidth * attempt.scale)),
|
|
824
843
|
height: Math.max(1, Math.round(sourceHeight * attempt.scale)),
|
|
825
|
-
fit:
|
|
844
|
+
fit: "inside",
|
|
826
845
|
withoutEnlargement: true,
|
|
827
846
|
});
|
|
828
847
|
}
|
|
829
|
-
const output = await pipeline
|
|
848
|
+
const output = await pipeline
|
|
849
|
+
.png({
|
|
830
850
|
compressionLevel: 9,
|
|
831
851
|
adaptiveFiltering: true,
|
|
832
852
|
...(attempt.palette ? { palette: true, quality: attempt.quality } : {}),
|
|
833
|
-
})
|
|
853
|
+
})
|
|
854
|
+
.toBuffer();
|
|
834
855
|
if (!smallest || output.length < smallest.length) {
|
|
835
856
|
smallest = output;
|
|
836
857
|
}
|
|
@@ -841,12 +862,10 @@ async function optimizeGeneratedPngOutputBuffer(buffer, loadedSharp) {
|
|
|
841
862
|
throw new Error(`ai_generation_image_output_too_large:${smallest?.length ?? buffer.length}:${GENERATED_PNG_OUTPUT_MAX_BYTES}`);
|
|
842
863
|
}
|
|
843
864
|
function formatJobStatus(job) {
|
|
844
|
-
const progress = typeof job.progressPercent ===
|
|
865
|
+
const progress = typeof job.progressPercent === "number"
|
|
845
866
|
? ` progress=${Math.max(0, Math.min(100, Math.round(job.progressPercent)))}%`
|
|
846
|
-
:
|
|
847
|
-
const eta = typeof job.etaSecondsRemaining ===
|
|
848
|
-
? ` eta=${Math.max(0, Math.round(job.etaSecondsRemaining))}s`
|
|
849
|
-
: '';
|
|
867
|
+
: "";
|
|
868
|
+
const eta = typeof job.etaSecondsRemaining === "number" ? ` eta=${Math.max(0, Math.round(job.etaSecondsRemaining))}s` : "";
|
|
850
869
|
return `${job.status}${progress}${eta}`;
|
|
851
870
|
}
|
|
852
871
|
async function generate(typeInput, promptInput, options = {}) {
|
|
@@ -855,7 +874,7 @@ async function generate(typeInput, promptInput, options = {}) {
|
|
|
855
874
|
parsed = buildGenerateRequest(typeInput, promptInput, options);
|
|
856
875
|
}
|
|
857
876
|
catch (error) {
|
|
858
|
-
const message = typeof error?.message ===
|
|
877
|
+
const message = typeof error?.message === "string" ? error.message : "invalid_input";
|
|
859
878
|
if (handleGenerateBuildRequestError(message)) {
|
|
860
879
|
return;
|
|
861
880
|
}
|
|
@@ -863,35 +882,33 @@ async function generate(typeInput, promptInput, options = {}) {
|
|
|
863
882
|
return;
|
|
864
883
|
}
|
|
865
884
|
(0, messages_1.printErrorWithHelp)(`Invalid AI create input: ${message}.`, ['Run "playdrop help ai create" for valid options.'], {
|
|
866
|
-
command:
|
|
885
|
+
command: "ai create",
|
|
867
886
|
});
|
|
868
887
|
process.exitCode = 1;
|
|
869
888
|
return;
|
|
870
889
|
}
|
|
871
|
-
const outputPath = typeof options.output ===
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
(0, messages_1.printErrorWithHelp)('The --output option is only supported for image generation.', ['Use "playdrop ai create image ... --output <file>".'], {
|
|
876
|
-
command: 'ai create',
|
|
890
|
+
const outputPath = typeof options.output === "string" && options.output.trim().length > 0 ? options.output.trim() : null;
|
|
891
|
+
if (outputPath && parsed.modality !== "IMAGE") {
|
|
892
|
+
(0, messages_1.printErrorWithHelp)("The --output option is only supported for image generation.", ['Use "playdrop ai create image ... --output <file>".'], {
|
|
893
|
+
command: "ai create",
|
|
877
894
|
});
|
|
878
895
|
process.exitCode = 1;
|
|
879
896
|
return;
|
|
880
897
|
}
|
|
881
|
-
await (0, commandContext_1.withEnvironment)(
|
|
898
|
+
await (0, commandContext_1.withEnvironment)("ai create", "Generating AI assets", async ({ aiClient }) => {
|
|
882
899
|
try {
|
|
883
900
|
const created = await aiClient.createGenerationJob(parsed.request);
|
|
884
901
|
let job = created.job;
|
|
885
|
-
const jobId = String(job.id ||
|
|
902
|
+
const jobId = String(job.id || "").trim();
|
|
886
903
|
if (!jobId) {
|
|
887
|
-
throw new Error(
|
|
904
|
+
throw new Error("ai_generation_job_missing_id");
|
|
888
905
|
}
|
|
889
906
|
if (!options.json) {
|
|
890
907
|
console.log(`Job ID: ${jobId}`);
|
|
891
908
|
console.log(`Status: ${formatJobStatus(job)}`);
|
|
892
909
|
}
|
|
893
910
|
const deadlineMs = Date.now() + parsed.timeoutSeconds * 1000;
|
|
894
|
-
while (job.status ===
|
|
911
|
+
while (job.status === "PENDING" || job.status === "RUNNING") {
|
|
895
912
|
if (Date.now() >= deadlineMs) {
|
|
896
913
|
throw new Error(`ai_generation_job_timeout: Timed out waiting for job ${jobId}`);
|
|
897
914
|
}
|
|
@@ -902,14 +919,12 @@ async function generate(typeInput, promptInput, options = {}) {
|
|
|
902
919
|
console.log(`Status: ${formatJobStatus(job)}`);
|
|
903
920
|
}
|
|
904
921
|
}
|
|
905
|
-
if (job.status !==
|
|
906
|
-
const errorCode = typeof job.errorCode ===
|
|
907
|
-
const errorMessage = typeof job.errorMessage ===
|
|
908
|
-
? job.errorMessage
|
|
909
|
-
: 'Generation failed.';
|
|
922
|
+
if (job.status !== "SUCCESS") {
|
|
923
|
+
const errorCode = typeof job.errorCode === "string" && job.errorCode.length > 0 ? job.errorCode : "ai_generation_failed";
|
|
924
|
+
const errorMessage = typeof job.errorMessage === "string" && job.errorMessage.length > 0 ? job.errorMessage : "Generation failed.";
|
|
910
925
|
throw new Error(`${errorCode}: ${errorMessage}`);
|
|
911
926
|
}
|
|
912
|
-
const payload =
|
|
927
|
+
const payload = job.resultData && typeof job.resultData === "object" ? job.resultData : {};
|
|
913
928
|
if (outputPath) {
|
|
914
929
|
await writeGeneratedImageOutput(payload, outputPath, parsed.request.input);
|
|
915
930
|
}
|
|
@@ -920,21 +935,21 @@ async function generate(typeInput, promptInput, options = {}) {
|
|
|
920
935
|
printGenerateResult(parsed.modality, payload);
|
|
921
936
|
}
|
|
922
937
|
catch (error) {
|
|
923
|
-
if (!handleAiFailure(error,
|
|
938
|
+
if (!handleAiFailure(error, "ai create", "AI create")) {
|
|
924
939
|
throw error;
|
|
925
940
|
}
|
|
926
941
|
}
|
|
927
942
|
});
|
|
928
943
|
}
|
|
929
944
|
function parseJobModality(raw) {
|
|
930
|
-
if (!raw || raw.trim().length === 0 || raw.trim().toLowerCase() ===
|
|
945
|
+
if (!raw || raw.trim().length === 0 || raw.trim().toLowerCase() === "all") {
|
|
931
946
|
return undefined;
|
|
932
947
|
}
|
|
933
948
|
return normalizeModality(raw);
|
|
934
949
|
}
|
|
935
950
|
function handleAiFailure(error, command, context) {
|
|
936
951
|
const handled = (0, errors_1.handleCommandFailure)(error, command, context, {
|
|
937
|
-
networkMessage:
|
|
952
|
+
networkMessage: "Could not reach the Playdrop AI API.",
|
|
938
953
|
apiMessage: (apiError) => {
|
|
939
954
|
if (apiError.status === 401 || apiError.status === 403) {
|
|
940
955
|
return {
|
|
@@ -944,59 +959,61 @@ function handleAiFailure(error, command, context) {
|
|
|
944
959
|
}
|
|
945
960
|
return {
|
|
946
961
|
problem: `${context} failed with status ${apiError.status}.`,
|
|
947
|
-
suggestions: [
|
|
962
|
+
suggestions: ["Retry in a moment."],
|
|
948
963
|
};
|
|
949
964
|
},
|
|
950
965
|
});
|
|
951
966
|
if (handled) {
|
|
952
967
|
return true;
|
|
953
968
|
}
|
|
954
|
-
const status = typeof error?.status ===
|
|
969
|
+
const status = typeof error?.status === "number" ? Number(error.status) : null;
|
|
955
970
|
if (status !== null) {
|
|
956
971
|
if (status === 401 || status === 403) {
|
|
957
|
-
(0, messages_1.printErrorWithHelp)(`${context} requires you to be logged in.`, ['Run "playdrop auth login" and retry.'], {
|
|
972
|
+
(0, messages_1.printErrorWithHelp)(`${context} requires you to be logged in.`, ['Run "playdrop auth login" and retry.'], {
|
|
973
|
+
command,
|
|
974
|
+
});
|
|
958
975
|
}
|
|
959
976
|
else {
|
|
960
|
-
(0, messages_1.printErrorWithHelp)(`${context} failed with status ${status}.`, [
|
|
977
|
+
(0, messages_1.printErrorWithHelp)(`${context} failed with status ${status}.`, ["Retry in a moment."], { command });
|
|
961
978
|
}
|
|
962
979
|
process.exitCode = 1;
|
|
963
980
|
return true;
|
|
964
981
|
}
|
|
965
982
|
const message = error instanceof Error ? error.message : String(error);
|
|
966
|
-
if (message ===
|
|
967
|
-
(0, messages_1.printErrorWithHelp)(
|
|
983
|
+
if (message === "ai_generation_job_missing_id") {
|
|
984
|
+
(0, messages_1.printErrorWithHelp)("AI create failed because the server did not return a job id.", ["Retry the command. If the problem persists, contact Playdrop support."], { command });
|
|
968
985
|
process.exitCode = 1;
|
|
969
986
|
return true;
|
|
970
987
|
}
|
|
971
|
-
if (message ===
|
|
972
|
-
(0, messages_1.printErrorWithHelp)(
|
|
988
|
+
if (message === "ai_generation_image_output_unsupported_type") {
|
|
989
|
+
(0, messages_1.printErrorWithHelp)("AI create returned an image format that Playdrop CLI could not identify.", ["Retry the command. If the problem persists, contact Playdrop support."], { command });
|
|
973
990
|
process.exitCode = 1;
|
|
974
991
|
return true;
|
|
975
992
|
}
|
|
976
|
-
if (message ===
|
|
977
|
-
(0, messages_1.printErrorWithHelp)(
|
|
993
|
+
if (message === "ai_generation_image_output_conversion_unavailable") {
|
|
994
|
+
(0, messages_1.printErrorWithHelp)("AI create could not convert the generated image to the requested output file type.", ["Install the Playdrop CLI dependencies again, then retry."], { command });
|
|
978
995
|
process.exitCode = 1;
|
|
979
996
|
return true;
|
|
980
997
|
}
|
|
981
|
-
if (message ===
|
|
982
|
-
(0, messages_1.printErrorWithHelp)(
|
|
998
|
+
if (message === "ai_generation_image_output_conversion_failed") {
|
|
999
|
+
(0, messages_1.printErrorWithHelp)("AI create failed while converting the generated image to the requested output file type.", ["Retry with a matching output extension such as .jpg, or retry the generation."], { command });
|
|
983
1000
|
process.exitCode = 1;
|
|
984
1001
|
return true;
|
|
985
1002
|
}
|
|
986
|
-
if (message ===
|
|
987
|
-
(0, messages_1.printErrorWithHelp)(
|
|
1003
|
+
if (message === "ai_generation_image_output_metadata_failed") {
|
|
1004
|
+
(0, messages_1.printErrorWithHelp)("AI create failed while writing PlayDrop metadata to the generated image.", ["Retry the generation. The output image must keep prompt metadata for worker validation."], { command });
|
|
988
1005
|
process.exitCode = 1;
|
|
989
1006
|
return true;
|
|
990
1007
|
}
|
|
991
|
-
if (message.startsWith(
|
|
992
|
-
const detail = message.split(
|
|
993
|
-
(0, messages_1.printErrorWithHelp)(detail ||
|
|
1008
|
+
if (message.startsWith("ai_generation_job_timeout:")) {
|
|
1009
|
+
const detail = message.split(":").slice(1).join(":").trim();
|
|
1010
|
+
(0, messages_1.printErrorWithHelp)(detail || "AI create timed out while waiting for the job to finish.", ["Retry the command with a higher --timeout value if the job normally takes longer."], { command });
|
|
994
1011
|
process.exitCode = 1;
|
|
995
1012
|
return true;
|
|
996
1013
|
}
|
|
997
|
-
if (message.includes(
|
|
998
|
-
const [errorCode, ...rest] = message.split(
|
|
999
|
-
const detail = rest.join(
|
|
1014
|
+
if (message.includes(":")) {
|
|
1015
|
+
const [errorCode, ...rest] = message.split(":");
|
|
1016
|
+
const detail = rest.join(":").trim();
|
|
1000
1017
|
if (errorCode && detail) {
|
|
1001
1018
|
(0, messages_1.printErrorWithHelp)(`AI create failed: ${detail}`, [`Error code: ${errorCode.trim()}`], { command });
|
|
1002
1019
|
process.exitCode = 1;
|
|
@@ -1008,25 +1025,27 @@ function handleAiFailure(error, command, context) {
|
|
|
1008
1025
|
async function browseGenerationJobs(options = {}) {
|
|
1009
1026
|
const modality = parseJobModality(options.type);
|
|
1010
1027
|
if (options.type !== undefined && modality === null) {
|
|
1011
|
-
(0, messages_1.printErrorWithHelp)(
|
|
1028
|
+
(0, messages_1.printErrorWithHelp)("The --type value is invalid.", ["Use one of: image, music, sfx, video, model_3d, all."], {
|
|
1029
|
+
command: "ai jobs browse",
|
|
1030
|
+
});
|
|
1012
1031
|
process.exitCode = 1;
|
|
1013
1032
|
return;
|
|
1014
1033
|
}
|
|
1015
1034
|
let limit;
|
|
1016
1035
|
let offset;
|
|
1017
1036
|
try {
|
|
1018
|
-
limit = parseOptionalPositiveInt(options.limit,
|
|
1019
|
-
offset = parseOptionalNonNegativeInt(options.offset,
|
|
1037
|
+
limit = parseOptionalPositiveInt(options.limit, "limit");
|
|
1038
|
+
offset = parseOptionalNonNegativeInt(options.offset, "offset");
|
|
1020
1039
|
}
|
|
1021
1040
|
catch (error) {
|
|
1022
|
-
const message = typeof error?.message ===
|
|
1023
|
-
(0, messages_1.printErrorWithHelp)(`Invalid ai jobs input: ${message}.`, [
|
|
1024
|
-
command:
|
|
1041
|
+
const message = typeof error?.message === "string" ? error.message : "invalid_pagination";
|
|
1042
|
+
(0, messages_1.printErrorWithHelp)(`Invalid ai jobs input: ${message}.`, ["Use positive integers for --limit and --offset."], {
|
|
1043
|
+
command: "ai jobs browse",
|
|
1025
1044
|
});
|
|
1026
1045
|
process.exitCode = 1;
|
|
1027
1046
|
return;
|
|
1028
1047
|
}
|
|
1029
|
-
await (0, commandContext_1.withEnvironment)(
|
|
1048
|
+
await (0, commandContext_1.withEnvironment)("ai jobs browse", "Browsing AI jobs", async ({ aiClient }) => {
|
|
1030
1049
|
try {
|
|
1031
1050
|
const response = await aiClient.listGenerationJobs({
|
|
1032
1051
|
modality: modality ?? undefined,
|
|
@@ -1038,31 +1057,33 @@ async function browseGenerationJobs(options = {}) {
|
|
|
1038
1057
|
return;
|
|
1039
1058
|
}
|
|
1040
1059
|
if (!Array.isArray(response.jobs) || response.jobs.length === 0) {
|
|
1041
|
-
console.log(
|
|
1060
|
+
console.log("No AI jobs found.");
|
|
1042
1061
|
console.log('Next: run "playdrop ai create <type> <prompt>" to start a new job.');
|
|
1043
1062
|
return;
|
|
1044
1063
|
}
|
|
1045
|
-
console.log(
|
|
1064
|
+
console.log("AI jobs:\n");
|
|
1046
1065
|
for (const job of response.jobs) {
|
|
1047
1066
|
console.log(`${job.id} | ${job.modality.toLowerCase()} | ${formatJobStatus(job)} | ${job.createdAt}`);
|
|
1048
1067
|
}
|
|
1049
1068
|
console.log('\nNext: run "playdrop ai jobs detail <id>" to inspect one job.');
|
|
1050
1069
|
}
|
|
1051
1070
|
catch (error) {
|
|
1052
|
-
if (!handleAiFailure(error,
|
|
1071
|
+
if (!handleAiFailure(error, "ai jobs browse", "AI job lookup")) {
|
|
1053
1072
|
throw error;
|
|
1054
1073
|
}
|
|
1055
1074
|
}
|
|
1056
1075
|
});
|
|
1057
1076
|
}
|
|
1058
1077
|
async function showGenerationJob(id, options = {}) {
|
|
1059
|
-
const jobId = typeof id ===
|
|
1078
|
+
const jobId = typeof id === "string" ? id.trim() : "";
|
|
1060
1079
|
if (!jobId) {
|
|
1061
|
-
(0, messages_1.printErrorWithHelp)(
|
|
1080
|
+
(0, messages_1.printErrorWithHelp)("A job id is required.", ["Example: playdrop ai jobs detail job_123"], {
|
|
1081
|
+
command: "ai jobs detail",
|
|
1082
|
+
});
|
|
1062
1083
|
process.exitCode = 1;
|
|
1063
1084
|
return;
|
|
1064
1085
|
}
|
|
1065
|
-
await (0, commandContext_1.withEnvironment)(
|
|
1086
|
+
await (0, commandContext_1.withEnvironment)("ai jobs detail", "Inspecting an AI job", async ({ aiClient }) => {
|
|
1066
1087
|
try {
|
|
1067
1088
|
const response = await aiClient.getGenerationJob(jobId);
|
|
1068
1089
|
if (options.json) {
|
|
@@ -1084,7 +1105,7 @@ async function showGenerationJob(id, options = {}) {
|
|
|
1084
1105
|
console.log('\nNext: run "playdrop ai jobs browse" to review other jobs.');
|
|
1085
1106
|
}
|
|
1086
1107
|
catch (error) {
|
|
1087
|
-
if (!handleAiFailure(error,
|
|
1108
|
+
if (!handleAiFailure(error, "ai jobs detail", "AI job detail lookup")) {
|
|
1088
1109
|
throw error;
|
|
1089
1110
|
}
|
|
1090
1111
|
}
|
|
@@ -1093,50 +1114,47 @@ async function showGenerationJob(id, options = {}) {
|
|
|
1093
1114
|
async function generations(options = {}) {
|
|
1094
1115
|
const format = parseListFormat(options.format);
|
|
1095
1116
|
if (!format) {
|
|
1096
|
-
(0, messages_1.printErrorWithHelp)(
|
|
1117
|
+
(0, messages_1.printErrorWithHelp)("The --format value is invalid.", ["Use --format text or --format json."], {
|
|
1118
|
+
command: "generations",
|
|
1119
|
+
});
|
|
1097
1120
|
process.exitCode = 1;
|
|
1098
1121
|
return;
|
|
1099
1122
|
}
|
|
1100
1123
|
const type = parseListType(options.type);
|
|
1101
1124
|
if (type === null) {
|
|
1102
|
-
(0, messages_1.printErrorWithHelp)(
|
|
1125
|
+
(0, messages_1.printErrorWithHelp)("The --type value is invalid.", ["Use one of: text, json, image, music, sfx, video, model_3d."], { command: "generations" });
|
|
1103
1126
|
process.exitCode = 1;
|
|
1104
1127
|
return;
|
|
1105
1128
|
}
|
|
1106
1129
|
let limit;
|
|
1107
1130
|
let offset;
|
|
1108
1131
|
try {
|
|
1109
|
-
limit = parseOptionalPositiveInt(options.limit,
|
|
1110
|
-
offset = parseOptionalNonNegativeInt(options.offset,
|
|
1132
|
+
limit = parseOptionalPositiveInt(options.limit, "limit");
|
|
1133
|
+
offset = parseOptionalNonNegativeInt(options.offset, "offset");
|
|
1111
1134
|
}
|
|
1112
1135
|
catch (error) {
|
|
1113
|
-
const message = typeof error?.message ===
|
|
1114
|
-
(0, messages_1.printErrorWithHelp)(`Invalid generations input: ${message}.`, [
|
|
1115
|
-
command:
|
|
1136
|
+
const message = typeof error?.message === "string" ? error.message : "invalid_pagination";
|
|
1137
|
+
(0, messages_1.printErrorWithHelp)(`Invalid generations input: ${message}.`, ["Use positive integers for --limit and --offset."], {
|
|
1138
|
+
command: "generations",
|
|
1116
1139
|
});
|
|
1117
1140
|
process.exitCode = 1;
|
|
1118
1141
|
return;
|
|
1119
1142
|
}
|
|
1120
|
-
await (0, commandContext_1.withEnvironment)(
|
|
1143
|
+
await (0, commandContext_1.withEnvironment)("generations", "Listing AI generations", async ({ aiClient }) => {
|
|
1121
1144
|
const response = await aiClient.listGenerations({ type: type ?? undefined, limit, offset });
|
|
1122
|
-
if (format ===
|
|
1145
|
+
if (format === "json") {
|
|
1123
1146
|
console.log(JSON.stringify(response, null, 2));
|
|
1124
1147
|
return;
|
|
1125
1148
|
}
|
|
1126
1149
|
if (!Array.isArray(response.generations) || response.generations.length === 0) {
|
|
1127
|
-
console.log(
|
|
1150
|
+
console.log("No AI generations found.");
|
|
1128
1151
|
return;
|
|
1129
1152
|
}
|
|
1130
1153
|
for (const generation of response.generations) {
|
|
1131
1154
|
const prompt = generationPrompt(generation);
|
|
1132
1155
|
const ref = generationAssetRef(generation);
|
|
1133
1156
|
const subcategory = generationAssetSubcategory(generation);
|
|
1134
|
-
const parts = [
|
|
1135
|
-
generation.id,
|
|
1136
|
-
generation.type,
|
|
1137
|
-
generation.createdAt,
|
|
1138
|
-
`cost=${generation.cost}`,
|
|
1139
|
-
];
|
|
1157
|
+
const parts = [generation.id, generation.type, generation.createdAt, `cost=${generation.cost}`];
|
|
1140
1158
|
if (prompt.length > 0) {
|
|
1141
1159
|
parts.push(`prompt=${prompt}`);
|
|
1142
1160
|
}
|
|
@@ -1146,7 +1164,7 @@ async function generations(options = {}) {
|
|
|
1146
1164
|
if (subcategory) {
|
|
1147
1165
|
parts.push(`subcategory=${subcategory}`);
|
|
1148
1166
|
}
|
|
1149
|
-
console.log(parts.join(
|
|
1167
|
+
console.log(parts.join(" | "));
|
|
1150
1168
|
}
|
|
1151
1169
|
});
|
|
1152
1170
|
}
|