@playcraft/cli 0.1.54 → 0.1.56-beta
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/README.md +83 -15
- package/SKILLS_REGISTRY.md +149 -0
- package/dist/agent/local-backend.js +1 -1
- package/dist/assets/client.js +157 -0
- package/dist/assets/messages.js +48 -0
- package/dist/auth/account-activation.js +157 -0
- package/dist/auth/messages.js +30 -0
- package/dist/cli-root-help.js +4 -0
- package/dist/commands/assets.js +123 -0
- package/dist/commands/build-all.js +5 -19
- package/dist/commands/build-temp.js +26 -0
- package/dist/commands/build.js +53 -28
- package/dist/commands/create.js +26 -33
- package/dist/commands/image-layer-messages.js +37 -0
- package/dist/commands/image-layer-tools.js +185 -0
- package/dist/commands/image.js +2 -73
- package/dist/commands/library-messages.js +46 -0
- package/dist/commands/library.js +130 -0
- package/dist/commands/login.js +84 -42
- package/dist/commands/platform-skills.generated.js +19 -0
- package/dist/commands/playable.js +53 -0
- package/dist/commands/preview-runtime.js +21 -0
- package/dist/commands/skills.js +4 -0
- package/dist/commands/tools-3d.js +11 -0
- package/dist/commands/tools-batch.js +113 -0
- package/dist/commands/tools-generation.js +6 -0
- package/dist/commands/tools.js +2 -0
- package/dist/commands/video.js +122 -0
- package/dist/commands/workspace-runtime.js +54 -0
- package/dist/commands/workspace.js +40 -0
- package/dist/config.js +59 -4
- package/dist/index.js +47 -3
- package/dist/preview-runtime/distribution.js +77 -0
- package/dist/project-skills/builtin-import.js +225 -0
- package/dist/project-skills/commands.js +77 -0
- package/dist/project-skills/lifecycle.js +28 -0
- package/dist/project-skills/local-run.js +112 -0
- package/dist/project-skills/local-store.js +221 -0
- package/dist/project-skills/messages.js +80 -0
- package/dist/project-skills/reconcile.js +62 -0
- package/dist/project-skills/remote-cache.js +51 -0
- package/dist/project-skills/validation.js +19 -0
- package/dist/recording/messages.js +40 -0
- package/dist/recording/project-digest.js +85 -0
- package/dist/recording/recorder.js +293 -0
- package/dist/recording/scenario.js +50 -0
- package/dist/remix/clone.js +2 -0
- package/dist/remix/init-template.js +2 -0
- package/dist/remix/pull.js +2 -0
- package/dist/remix/push.js +21 -1
- package/dist/skill-registry/client.js +345 -0
- package/dist/skill-registry/commands.js +180 -0
- package/dist/skill-registry/evaluation-client.js +156 -0
- package/dist/skill-registry/evaluation-commands.js +174 -0
- package/dist/skill-registry/messages.js +177 -0
- package/dist/skill-registry/package.js +275 -0
- package/dist/skill-registry/platform-package.js +100 -0
- package/dist/utils/agent-api-client.js +245 -30
- package/dist/utils/environment-endpoints.js +17 -0
- package/dist/utils/error-diagnostics.js +20 -0
- package/dist/utils/playcraft-http-client.js +6 -4
- package/dist/utils/tool-operation-journal.js +124 -0
- package/dist/utils/video-evidence-git.js +81 -0
- package/dist/video-replication/client.js +234 -0
- package/dist/video-replication/comparison-evidence.js +149 -0
- package/dist/video-replication/comparison-files.js +57 -0
- package/dist/video-replication/comparison-log.js +72 -0
- package/dist/video-replication/comparison-messages.js +104 -0
- package/dist/video-replication/comparison-output.js +63 -0
- package/dist/video-replication/comparison-preflight.js +66 -0
- package/dist/video-replication/comparison.js +230 -0
- package/dist/video-replication/diagnostics.js +41 -0
- package/dist/video-replication/evidence.js +165 -0
- package/dist/video-replication/media.js +112 -0
- package/dist/video-replication/messages.js +97 -0
- package/dist/workspace/messages.js +67 -0
- package/dist/workspace/transfer-client.js +237 -0
- package/dist/workspace/transfer-errors.js +48 -0
- package/dist/workspace-runtime/batch/content-changes.js +30 -0
- package/dist/workspace-runtime/batch/control.js +86 -0
- package/dist/workspace-runtime/batch/deliver.js +173 -0
- package/dist/workspace-runtime/batch/freeze.js +101 -0
- package/dist/workspace-runtime/batch/generate.js +249 -0
- package/dist/workspace-runtime/batch/git.js +40 -0
- package/dist/workspace-runtime/batch/occupancy.js +8 -0
- package/dist/workspace-runtime/batch/policy.js +70 -0
- package/dist/workspace-runtime/batch/prepare.js +317 -0
- package/dist/workspace-runtime/batch/processes.js +72 -0
- package/dist/workspace-runtime/batch/records.js +113 -0
- package/dist/workspace-runtime/batch/routes.js +61 -0
- package/dist/workspace-runtime/batch/source-candidate.js +86 -0
- package/dist/workspace-runtime/batch/source-capture.js +146 -0
- package/dist/workspace-runtime/batch/source-failure.js +43 -0
- package/dist/workspace-runtime/batch/source-publish.js +130 -0
- package/dist/workspace-runtime/codex/app-server.js +1065 -0
- package/dist/workspace-runtime/codex/compact.js +46 -0
- package/dist/workspace-runtime/codex/config-toml.js +107 -0
- package/dist/workspace-runtime/codex/delivery-tools.js +144 -0
- package/dist/workspace-runtime/codex/jsonrpc-stdio.js +145 -0
- package/dist/workspace-runtime/codex/launcher-client.js +177 -0
- package/dist/workspace-runtime/codex/loopback.js +146 -0
- package/dist/workspace-runtime/codex/mcp-config.js +39 -0
- package/dist/workspace-runtime/codex/model-broker.js +263 -0
- package/dist/workspace-runtime/codex/native-adapter.js +9 -0
- package/dist/workspace-runtime/codex/permissions.js +79 -0
- package/dist/workspace-runtime/codex/thread-image.js +38 -0
- package/dist/workspace-runtime/codex/tool-response.js +10 -0
- package/dist/workspace-runtime/codex/ui-instructions.js +4 -0
- package/dist/workspace-runtime/codex/ui-tools.js +203 -0
- package/dist/workspace-runtime/codex/work-mode.js +15 -0
- package/dist/workspace-runtime/main.js +10 -0
- package/dist/workspace-runtime/persistence/journal.js +365 -0
- package/dist/workspace-runtime/persistence/native-subagents.js +162 -0
- package/dist/workspace-runtime/persistence/sqlite-client.js +77 -0
- package/dist/workspace-runtime/persistence/sqlite-worker.js +1161 -0
- package/dist/workspace-runtime/persistence/stopped-execution.js +77 -0
- package/dist/workspace-runtime/previews/diagnostics.js +44 -0
- package/dist/workspace-runtime/previews/finalize.js +64 -0
- package/dist/workspace-runtime/previews/output.js +36 -0
- package/dist/workspace-runtime/previews/publish.js +306 -0
- package/dist/workspace-runtime/previews/runtime-preview.js +251 -0
- package/dist/workspace-runtime/previews/single-file.js +43 -0
- package/dist/workspace-runtime/processes/managed-writes.js +69 -0
- package/dist/workspace-runtime/serve.js +441 -0
- package/dist/workspace-runtime/server/accept-operation.js +61 -0
- package/dist/workspace-runtime/server/asset-transfers.js +63 -0
- package/dist/workspace-runtime/server/auth.js +21 -0
- package/dist/workspace-runtime/server/connectivity.js +211 -0
- package/dist/workspace-runtime/server/desktop-host.js +429 -0
- package/dist/workspace-runtime/server/desktop-preview-config.js +81 -0
- package/dist/workspace-runtime/server/desktop-preview-service.js +157 -0
- package/dist/workspace-runtime/server/desktop-preview-static.js +53 -0
- package/dist/workspace-runtime/server/desktop-preview.js +189 -0
- package/dist/workspace-runtime/server/dispatch.js +1655 -0
- package/dist/workspace-runtime/server/endpoints.js +21 -0
- package/dist/workspace-runtime/server/execution-group.js +90 -0
- package/dist/workspace-runtime/server/http.js +1363 -0
- package/dist/workspace-runtime/server/lock.js +53 -0
- package/dist/workspace-runtime/server/operation-record.js +33 -0
- package/dist/workspace-runtime/server/rfb-watch-gate.js +168 -0
- package/dist/workspace-runtime/server/session-restore.js +84 -0
- package/dist/workspace-runtime/server/source-uploader.js +138 -0
- package/dist/workspace-runtime/server/submit-operation.js +41 -0
- package/dist/workspace-runtime/server/terminal-host.js +366 -0
- package/dist/workspace-runtime/server/types.js +1 -0
- package/dist/workspace-runtime/server/workspace-transfer.js +168 -0
- package/dist/workspace-runtime/verify-artifact.js +59 -0
- package/dist/workspace-runtime/workspaces/append-only-log.js +62 -0
- package/dist/workspace-runtime/workspaces/archive.js +207 -0
- package/dist/workspace-runtime/workspaces/artifact-events.js +168 -0
- package/dist/workspace-runtime/workspaces/artifact-files.js +201 -0
- package/dist/workspace-runtime/workspaces/artifact-receipts.js +112 -0
- package/dist/workspace-runtime/workspaces/artifacts.js +380 -0
- package/dist/workspace-runtime/workspaces/asset-library-import.js +387 -0
- package/dist/workspace-runtime/workspaces/asset-publication-access.js +29 -0
- package/dist/workspace-runtime/workspaces/asset-transfer-dependencies.js +81 -0
- package/dist/workspace-runtime/workspaces/asset-transfer-publish.js +438 -0
- package/dist/workspace-runtime/workspaces/asset-transfer-storage.js +389 -0
- package/dist/workspace-runtime/workspaces/attachment-content.js +73 -0
- package/dist/workspace-runtime/workspaces/attachments.js +185 -0
- package/dist/workspace-runtime/workspaces/batch-commit.js +142 -0
- package/dist/workspace-runtime/workspaces/binary-content.js +65 -0
- package/dist/workspace-runtime/workspaces/binary-write.js +117 -0
- package/dist/workspace-runtime/workspaces/cli-context.js +23 -0
- package/dist/workspace-runtime/workspaces/cli-credentials.js +115 -0
- package/dist/workspace-runtime/workspaces/composer-context.js +147 -0
- package/dist/workspace-runtime/workspaces/context-error.js +2 -0
- package/dist/workspace-runtime/workspaces/delivery-build.js +421 -0
- package/dist/workspace-runtime/workspaces/delivery-store.js +168 -0
- package/dist/workspace-runtime/workspaces/delivery.js +64 -0
- package/dist/workspace-runtime/workspaces/dependencies.js +279 -0
- package/dist/workspace-runtime/workspaces/developer-command.js +98 -0
- package/dist/workspace-runtime/workspaces/directories.js +135 -0
- package/dist/workspace-runtime/workspaces/directory-access.js +50 -0
- package/dist/workspace-runtime/workspaces/directory-attachments.js +245 -0
- package/dist/workspace-runtime/workspaces/directory-create.js +57 -0
- package/dist/workspace-runtime/workspaces/directory-maintenance.js +111 -0
- package/dist/workspace-runtime/workspaces/directory-mutations.js +238 -0
- package/dist/workspace-runtime/workspaces/directory-revisions.js +56 -0
- package/dist/workspace-runtime/workspaces/directory-stats.js +49 -0
- package/dist/workspace-runtime/workspaces/disk-snapshot.js +31 -0
- package/dist/workspace-runtime/workspaces/empty-template.js +43 -0
- package/dist/workspace-runtime/workspaces/file-content.js +48 -0
- package/dist/workspace-runtime/workspaces/files-search.js +116 -0
- package/dist/workspace-runtime/workspaces/files.js +150 -0
- package/dist/workspace-runtime/workspaces/git-credential-broker.js +312 -0
- package/dist/workspace-runtime/workspaces/git-credential-helper.js +68 -0
- package/dist/workspace-runtime/workspaces/git-direct-store.js +155 -0
- package/dist/workspace-runtime/workspaces/git.js +683 -0
- package/dist/workspace-runtime/workspaces/instructions.js +56 -0
- package/dist/workspace-runtime/workspaces/json5-edit.js +313 -0
- package/dist/workspace-runtime/workspaces/library-attachments.js +268 -0
- package/dist/workspace-runtime/workspaces/operation-log.js +23 -0
- package/dist/workspace-runtime/workspaces/optional-platform-skills.js +14 -0
- package/dist/workspace-runtime/workspaces/parameter-agent-inputs.js +97 -0
- package/dist/workspace-runtime/workspaces/parameter-agent-protocol.js +40 -0
- package/dist/workspace-runtime/workspaces/parameter-agent-store.js +58 -0
- package/dist/workspace-runtime/workspaces/parameter-agent.js +284 -0
- package/dist/workspace-runtime/workspaces/parameter-assets.js +212 -0
- package/dist/workspace-runtime/workspaces/parameters.js +369 -0
- package/dist/workspace-runtime/workspaces/prepare.js +284 -0
- package/dist/workspace-runtime/workspaces/registry.js +251 -0
- package/dist/workspace-runtime/workspaces/remix-references.js +301 -0
- package/dist/workspace-runtime/workspaces/revisions.js +31 -0
- package/dist/workspace-runtime/workspaces/session-image.js +104 -0
- package/dist/workspace-runtime/workspaces/shared-git.js +40 -0
- package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +95 -0
- package/dist/workspace-runtime/workspaces/skills.js +191 -0
- package/dist/workspace-runtime/workspaces/theme-asset-index.js +267 -0
- package/dist/workspace-runtime/workspaces/transfer-quota.js +69 -0
- package/dist/workspace-runtime/workspaces/transfer.js +471 -0
- package/dist/workspace-runtime/workspaces/turn-changes.js +75 -0
- package/dist/workspace-runtime/workspaces/video-attachments.js +49 -0
- package/dist/workspace-runtime/workspaces/worktree-attachments.js +74 -0
- package/dist/workspace-runtime/workspaces/worktree-checkout.js +67 -0
- package/dist/workspace-runtime/workspaces/worktrees.js +73 -0
- package/package.json +16 -5
- package/project-template/.claude/skills/playcraft-audio-generation/SKILL.md +31 -4
- package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +36 -5
- package/project-template/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +1 -1
- package/project-template/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +1 -1
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +1 -1
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +1 -1
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +1 -1
- package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +1 -1
- package/project-template/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
- package/project-template/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +1 -1
- package/project-template/.claude/skills/playcraft-image-processing/SKILL.md +50 -25
- package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +25 -0
- package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +79 -0
- package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +29 -0
- package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +37 -0
- package/project-template/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
- package/project-template/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
- package/project-template-v2/.claude/agents/artist.md +82 -0
- package/project-template-v2/.claude/agents/developer.md +153 -0
- package/project-template-v2/.claude/agents/game-designer.md +264 -0
- package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +533 -0
- package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +153 -0
- package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +27 -0
- package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +208 -0
- package/project-template-v2/.claude/agents/refs/atom-skill-library.md +81 -0
- package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +432 -0
- package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +252 -0
- package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +266 -0
- package/project-template-v2/.claude/agents/refs/framework-mda.md +147 -0
- package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
- package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +88 -0
- package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +67 -0
- package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
- package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +300 -0
- package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +495 -0
- package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +1141 -0
- package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +111 -0
- package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
- package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +412 -0
- package/project-template-v2/.claude/agents/reviewer.md +75 -0
- package/project-template-v2/.claude/agents/technical-artist.md +86 -0
- package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +243 -0
- package/project-template-v2/.claude/hooks/user-prompt.mjs +133 -0
- package/project-template-v2/.claude/settings.json +33 -0
- package/project-template-v2/.claude/skills/brainstorming/SKILL.md +161 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +177 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +354 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
- package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +309 -0
- package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
- package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
- package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +205 -0
- package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +307 -0
- package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
- package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +401 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +333 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +95 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +136 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
- package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
- package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +244 -0
- package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +373 -0
- package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
- package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +215 -0
- package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +382 -0
- package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
- package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
- package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
- package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +167 -0
- package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
- package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
- package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
- package/project-template-v2/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
- package/project-template-v2/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
- package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +390 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +23 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +240 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +226 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +308 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +275 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +134 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +142 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +153 -0
- package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +386 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +102 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
- package/project-template-v2/.claude/snapshot.mjs +263 -0
- package/project-template-v2/.playcraft/skills.lock.json +152 -0
- package/project-template-v2/CLAUDE.md +146 -0
- package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
- package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
- package/project-template-v2/assets/bundles/.gitkeep +0 -0
- package/project-template-v2/assets/images/bg/.gitkeep +0 -0
- package/project-template-v2/assets/images/reference/.gitkeep +0 -0
- package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
- package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
- package/project-template-v2/assets/images/ui/.gitkeep +0 -0
- package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
- package/project-template-v2/assets/models/.gitkeep +0 -0
- package/project-template-v2/docs/harness/iteration-1/context-flow.md +254 -0
- package/project-template-v2/docs/harness/iteration-1/generate-flow.md +91 -0
- package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +214 -0
- package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +75 -0
- package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +63 -0
- package/project-template-v2/docs/harness/iteration-2/context-flow.md +223 -0
- package/project-template-v2/docs/harness/iteration-2/generate-flow.md +129 -0
- package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +267 -0
- package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +164 -0
- package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +115 -0
- package/project-template-v2/docs/harness/orchestrator-flow.md +364 -0
- package/project-template-v2/docs/project-state.json +60 -0
- package/project-template-v2/docs/project-state.md +72 -0
- package/project-template-v2/docs/standards/README.md +225 -0
- package/project-template-v2/docs/standards/agent-behavior-standards.md +174 -0
- package/project-template-v2/docs/standards/artifacts/design-brief.md +19 -0
- package/project-template-v2/docs/standards/artifacts/design.md +22 -0
- package/project-template-v2/docs/standards/artifacts/game-code.md +41 -0
- package/project-template-v2/docs/standards/artifacts/todo-list.md +41 -0
- package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +343 -0
- package/project-template-v2/game/index.ts +18 -0
- package/project-template-v2/globals.d.ts +51 -0
- package/project-template-v2/index.css +34 -0
- package/project-template-v2/index.html +18 -0
- package/project-template-v2/main.ts +9 -0
- package/project-template-v2/package.json +46 -0
- package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +31 -0
- package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +86 -0
- package/project-template-v2/skills/_shared/scripts/dod-check.mjs +153 -0
- package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +70 -0
- package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +91 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +131 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +80 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +90 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +93 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +23 -0
- package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +230 -0
- package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +58 -0
- package/project-template-v2/skills/_shared/scripts/state-get.mjs +339 -0
- package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +39 -0
- package/project-template-v2/skills/_shared/scripts/state-set.mjs +94 -0
- package/project-template-v2/skills/_shared/scripts/state-store.mjs +783 -0
- package/project-template-v2/skills/_shared/scripts/todo-add.mjs +88 -0
- package/project-template-v2/skills/_shared/scripts/todo-get.mjs +130 -0
- package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +33 -0
- package/project-template-v2/skills/_shared/scripts/todo-set.mjs +47 -0
- package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +268 -0
- package/project-template-v2/skills/_shared/scripts/verify-env.mjs +285 -0
- package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +161 -0
- package/project-template-v2/skills/playable-autoplay/SKILL.md +176 -0
- package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +4 -0
- package/project-template-v2/skills/playable-debug/SKILL.md +116 -0
- package/project-template-v2/skills/playable-debug/agents/openai.yaml +4 -0
- package/project-template-v2/skills/playable-debug/references/debug-config.md +40 -0
- package/project-template-v2/skills/playable-record/SKILL.md +140 -0
- package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
- package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
- package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +425 -0
- package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +261 -0
- package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
- package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +322 -0
- package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +105 -0
- package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +230 -0
- package/project-template-v2/skills/playable-validate/SKILL.md +61 -0
- package/project-template-v2/skills/playable-validate/validation-rules.md +14 -0
- package/project-template-v2/skills/playable-verify-ui/SKILL.md +63 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +106 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
- package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
- package/project-template-v2/tsconfig.json +20 -0
- package/project-template-v2/vite.config.ts +27 -0
- package/project-templates/batch-locks/phaser.yaml +922 -0
- package/project-templates/batch-locks/threejs.yaml +978 -0
- package/project-templates/empty/AGENTS.md +53 -0
- package/project-templates/empty/gitignore +33 -0
- package/project-templates/phaser/.claude/skills/playcraft-audio-generation/SKILL.md +31 -4
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +36 -5
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +1 -1
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +1 -1
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +1 -1
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +1 -1
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +1 -1
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +1 -1
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +1 -1
- package/project-templates/phaser/.claude/skills/playcraft-image-processing/SKILL.md +50 -25
- package/project-templates/phaser/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
- package/project-templates/phaser/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
- package/project-templates/threejs/.claude/skills/playcraft-audio-generation/SKILL.md +31 -4
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +36 -5
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +1 -1
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +1 -1
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +1 -1
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +1 -1
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +1 -1
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +1 -1
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +1 -1
- package/project-templates/threejs/.claude/skills/playcraft-image-processing/SKILL.md +50 -25
- package/project-templates/threejs/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
- package/project-templates/threejs/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
- package/templates/preview-runtime/v1/README.md +79 -0
- package/templates/preview-runtime/v1/build-preview.mjs +1324 -0
- package/templates/preview-runtime/v1/manifest.json +17 -0
- package/templates/preview-runtime/v1/release-guard.mjs +87 -0
- package/templates/preview-runtime/v1/runtime.d.mts +3 -0
- package/templates/preview-runtime/v1/runtime.d.ts +3 -0
- package/templates/preview-runtime/v1/runtime.mjs +1312 -0
- package/templates/preview-runtime/v1/types/adapters.d.ts +28 -0
- package/templates/preview-runtime/v1/types/preview.d.ts +24 -0
- package/templates/preview-runtime/v1/types/protocol.d.ts +131 -0
- package/templates/preview-runtime/v1/types/runtime.d.ts +14 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { loadGlobalConfig } from '../config.js';
|
|
5
|
+
import { accountActivationMessage } from './messages.js';
|
|
6
|
+
export const ACCOUNT_PENDING_ACTIVATION = 'account_pending_activation';
|
|
7
|
+
export class AccountActivationError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
status;
|
|
10
|
+
retryable = false;
|
|
11
|
+
constructor(code, message, status) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.status = status;
|
|
15
|
+
this.name = 'AccountActivationError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function responseErrorCode(payload) {
|
|
19
|
+
if (!payload || typeof payload !== 'object')
|
|
20
|
+
return undefined;
|
|
21
|
+
const { error, code } = payload;
|
|
22
|
+
return typeof error?.code === 'string' ? error.code : typeof code === 'string' ? code : undefined;
|
|
23
|
+
}
|
|
24
|
+
export function pendingAccountActivationError(status, payload) {
|
|
25
|
+
return status === 403 && responseErrorCode(payload) === ACCOUNT_PENDING_ACTIVATION
|
|
26
|
+
? new AccountActivationError(ACCOUNT_PENDING_ACTIVATION, `${ACCOUNT_PENDING_ACTIVATION}: ${accountActivationMessage('pending')}`, status)
|
|
27
|
+
: undefined;
|
|
28
|
+
}
|
|
29
|
+
export function parseErrorPayload(text) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(text);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function localActivationConfig() {
|
|
38
|
+
for (const path of [
|
|
39
|
+
join(process.cwd(), '.playcraft.json'),
|
|
40
|
+
'/project/.playcraft.json',
|
|
41
|
+
join(homedir(), '.playcraft.json'),
|
|
42
|
+
]) {
|
|
43
|
+
if (!existsSync(path))
|
|
44
|
+
continue;
|
|
45
|
+
try {
|
|
46
|
+
const config = JSON.parse(readFileSync(path, 'utf8'));
|
|
47
|
+
if (config && typeof config === 'object' && !Array.isArray(config))
|
|
48
|
+
return config;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Follow the existing local credential lookup when a file is unreadable.
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
function stringValue(value) {
|
|
57
|
+
return typeof value === 'string' && value ? value : undefined;
|
|
58
|
+
}
|
|
59
|
+
function activationBaseUrl(raw) {
|
|
60
|
+
try {
|
|
61
|
+
const url = new URL(raw);
|
|
62
|
+
if (!['http:', 'https:'].includes(url.protocol) ||
|
|
63
|
+
url.username ||
|
|
64
|
+
url.password ||
|
|
65
|
+
url.search ||
|
|
66
|
+
url.hash)
|
|
67
|
+
throw new Error();
|
|
68
|
+
url.pathname = url.pathname.replace(/\/+$/, '').replace(/\/api$/, '');
|
|
69
|
+
return url.toString().replace(/\/+$/, '');
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
throw new AccountActivationError('INVALID_ACTIVATION_TARGET', accountActivationMessage('invalidTarget'));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function savedTokenForTarget(config, rawUrl, target, environment) {
|
|
76
|
+
if (!rawUrl || (stringValue(config.env)?.trim() || '') !== environment)
|
|
77
|
+
return undefined;
|
|
78
|
+
try {
|
|
79
|
+
return activationBaseUrl(rawUrl) === target ? stringValue(config.token) : undefined;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function normalizedSavedUrl(raw) {
|
|
86
|
+
try {
|
|
87
|
+
return raw ? activationBaseUrl(raw) : undefined;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export async function activateAccount(options, defaultBaseUrl) {
|
|
94
|
+
const local = localActivationConfig();
|
|
95
|
+
const global = loadGlobalConfig();
|
|
96
|
+
const localUrl = stringValue(local.apiUrl);
|
|
97
|
+
const globalUrl = stringValue(global.backendUrl) || stringValue(global.url);
|
|
98
|
+
const explicitUrl = options.url || process.env.PLAYCRAFT_API_URL || process.env.PLAYCRAFT_URL;
|
|
99
|
+
const target = activationBaseUrl(explicitUrl || localUrl || globalUrl || defaultBaseUrl);
|
|
100
|
+
const explicitToken = options.token || process.env.PLAYCRAFT_TOKEN || process.env.PLAYCRAFT_SANDBOX_TOKEN;
|
|
101
|
+
const savedUrls = [normalizedSavedUrl(localUrl), normalizedSavedUrl(globalUrl)].filter(Boolean);
|
|
102
|
+
const savedTokens = [stringValue(local.token), stringValue(global.token)].filter(Boolean);
|
|
103
|
+
const environmentsConflict = savedUrls.length === 2 &&
|
|
104
|
+
savedUrls[0] === savedUrls[1] &&
|
|
105
|
+
(stringValue(local.env)?.trim() || '') !== (stringValue(global.env)?.trim() || '');
|
|
106
|
+
const environmentTokensConflict = process.env.PLAYCRAFT_TOKEN &&
|
|
107
|
+
process.env.PLAYCRAFT_SANDBOX_TOKEN &&
|
|
108
|
+
process.env.PLAYCRAFT_TOKEN !== process.env.PLAYCRAFT_SANDBOX_TOKEN;
|
|
109
|
+
const environmentUrlsConflict = process.env.PLAYCRAFT_API_URL &&
|
|
110
|
+
process.env.PLAYCRAFT_URL &&
|
|
111
|
+
normalizedSavedUrl(process.env.PLAYCRAFT_API_URL) !==
|
|
112
|
+
normalizedSavedUrl(process.env.PLAYCRAFT_URL);
|
|
113
|
+
if ((!explicitUrl && new Set(savedUrls).size > 1) ||
|
|
114
|
+
(!explicitToken && new Set(savedTokens).size > 1) ||
|
|
115
|
+
(environmentsConflict && !process.env.PLAYCRAFT_ENV) ||
|
|
116
|
+
(environmentTokensConflict && !options.token) ||
|
|
117
|
+
(environmentUrlsConflict && !options.url)) {
|
|
118
|
+
throw new AccountActivationError('AMBIGUOUS_ACTIVATION_TARGET', accountActivationMessage('ambiguous'));
|
|
119
|
+
}
|
|
120
|
+
const environment = (process.env.PLAYCRAFT_ENV ||
|
|
121
|
+
(!explicitUrl ? (localUrl ? stringValue(local.env) : stringValue(global.env)) : '') ||
|
|
122
|
+
'').trim();
|
|
123
|
+
const token = explicitToken ||
|
|
124
|
+
savedTokenForTarget(local, localUrl, target, environment) ||
|
|
125
|
+
savedTokenForTarget(global, globalUrl, target, environment);
|
|
126
|
+
if (!token)
|
|
127
|
+
throw new AccountActivationError('AUTH_REQUIRED', accountActivationMessage('missingToken'));
|
|
128
|
+
if (!/^playcraft_pat_[A-Za-z0-9_-]{32}$/.test(token)) {
|
|
129
|
+
throw new AccountActivationError('INVALID_ACTIVATION_TOKEN', accountActivationMessage('invalidToken'));
|
|
130
|
+
}
|
|
131
|
+
let response;
|
|
132
|
+
try {
|
|
133
|
+
response = await fetch(`${target}/api/settings/personal-access-tokens/activate`, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
redirect: 'error',
|
|
136
|
+
signal: AbortSignal.timeout(30_000),
|
|
137
|
+
headers: {
|
|
138
|
+
Authorization: `Bearer ${token}`,
|
|
139
|
+
...(environment ? { 'playcraft-env': environment } : {}),
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
throw new AccountActivationError('ACTIVATION_UNCONFIRMED', accountActivationMessage('unavailable'));
|
|
145
|
+
}
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
await response.body?.cancel().catch(() => { });
|
|
148
|
+
throw new AccountActivationError('ACTIVATION_FAILED', accountActivationMessage('failed'), response.status);
|
|
149
|
+
}
|
|
150
|
+
const result = await response.json().catch(() => undefined);
|
|
151
|
+
if (!result ||
|
|
152
|
+
typeof result !== 'object' ||
|
|
153
|
+
result.accountStatus !== 'active') {
|
|
154
|
+
throw new AccountActivationError('ACTIVATION_UNCONFIRMED', accountActivationMessage('unavailable'), response.status);
|
|
155
|
+
}
|
|
156
|
+
console.log(accountActivationMessage('success'));
|
|
157
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const messages = {
|
|
2
|
+
en: {
|
|
3
|
+
activateOption: 'Explicitly activate the account using the current personal access token',
|
|
4
|
+
tokenOption: 'Personal access token for --activate (or use PLAYCRAFT_TOKEN)',
|
|
5
|
+
pending: 'Account activation is required. Run `playcraft login --activate` with the same token and target environment, then rerun your command.',
|
|
6
|
+
success: 'Account activated. Rerun your original command to continue.',
|
|
7
|
+
missingToken: 'No personal access token matches this target environment. Provide PLAYCRAFT_TOKEN or log in to this environment first.',
|
|
8
|
+
invalidToken: 'Account activation requires a personal access token. A sandbox token cannot activate an account.',
|
|
9
|
+
ambiguous: 'Activation credentials or target environments conflict. Specify --url, PLAYCRAFT_ENV when needed, and an explicit personal access token using --token or PLAYCRAFT_TOKEN.',
|
|
10
|
+
invalidTarget: 'Use a web service base address (http:// or https://) without credentials, a query, or a fragment.',
|
|
11
|
+
failed: 'Account activation failed. Check the target environment and token before trying again.',
|
|
12
|
+
unavailable: 'Account activation could not be confirmed. Check your account status before explicitly trying again.',
|
|
13
|
+
},
|
|
14
|
+
zh: {
|
|
15
|
+
activateOption: '明确使用当前个人访问令牌激活账号',
|
|
16
|
+
tokenOption: '用于 --activate 的个人访问令牌(也可使用 PLAYCRAFT_TOKEN)',
|
|
17
|
+
pending: '账号需要激活。请使用同一令牌和目标环境主动运行 `playcraft login --activate`,然后重新执行原命令。',
|
|
18
|
+
success: '账号已激活,请重新执行原命令继续。',
|
|
19
|
+
missingToken: '没有与目标环境匹配的个人访问令牌。请提供 PLAYCRAFT_TOKEN,或先登录此环境。',
|
|
20
|
+
invalidToken: '激活账号需要个人访问令牌,沙箱令牌不能用于激活账号。',
|
|
21
|
+
ambiguous: '激活凭据或目标环境存在冲突。请明确指定 --url、所需的 PLAYCRAFT_ENV,并通过 --token 或 PLAYCRAFT_TOKEN 提供个人访问令牌。',
|
|
22
|
+
invalidTarget: '激活目标必须是网页服务基址(http:// 或 https://),不能包含凭据、查询参数或片段。',
|
|
23
|
+
failed: '账号激活失败,请检查目标环境和令牌后再尝试。',
|
|
24
|
+
unavailable: '无法确认账号是否已激活。请先检查账号状态,再主动决定是否重试。',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export function accountActivationMessage(key) {
|
|
28
|
+
const locale = process.env.PLAYCRAFT_LANGUAGE || process.env.LANG || 'en';
|
|
29
|
+
return messages[locale.startsWith('zh') ? 'zh' : 'en'][key];
|
|
30
|
+
}
|
package/dist/cli-root-help.js
CHANGED
|
@@ -5,8 +5,12 @@ export function getCliTopicsHelpText() {
|
|
|
5
5
|
'',
|
|
6
6
|
' 本地开发 create, init, start, stop, status, logs, config, sync, fix-ids',
|
|
7
7
|
' 素材 tools generate-* | image <子命令> | audio <子命令> | prefab <子命令>',
|
|
8
|
+
' 素材库 library list/search/facets/get/files/download',
|
|
9
|
+
' 生成任务 assets estimate/generate/tasks/get/wait/cancel/download | assets animation',
|
|
10
|
+
' 视频理解 video models | video understand | video jobs get/cancel',
|
|
8
11
|
' 平台 build, build-base, build-playable, build-all, analyze, inspect, upgrade',
|
|
9
12
|
' tools 除 generate-* 外(Git / 沙箱构建 / 发布 / 列表 / Prefab 等,需后端 API)',
|
|
13
|
+
' 沙箱常驻 workspace-runtime serve(Cloud Workspace,由 Runtime 引导配置启动)',
|
|
10
14
|
'',
|
|
11
15
|
'也可运行: playcraft topics',
|
|
12
16
|
'',
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { assetGenerationRequestSchema, assetGenerationEstimateInput, assetGenerationEstimateInputSchema, assetGenerationEstimateSchema, assetGenerationTaskSavedSchema, assetLibrarySaveRequestSchema, assetLibrarySaveJobSchema, assetLibrarySaveListSchema, assetLibrarySaveTargetsSchema, animationEditorStateSchema, animationEditorDraftUpdateSchema, animationEditorFrameUploadSchema, animationEditorFrameUploadResultSchema, animationEditorVersionCreateSchema, animationEditorVersionResultSchema, workspaceAssetToolWriteSchema, } from '@playcraft/common/cloud-workspace/runtime';
|
|
2
|
+
import { AgentApiClient } from '../utils/agent-api-client.js';
|
|
3
|
+
import { resolveAssetScope, readAssetRequest, readAssetTask, readAssetTasks, scopedAssetTask, waitForAssetTask, downloadAssetTask } from '../assets/client.js';
|
|
4
|
+
import { validateAssetWait } from '../assets/client.js';
|
|
5
|
+
import { assetMessage as t } from '../assets/messages.js';
|
|
6
|
+
function shared(command) {
|
|
7
|
+
return command.option('--workspace <id>', t('workspace')).option('--directory <name>', t('directory')).option('--json', t('json'));
|
|
8
|
+
}
|
|
9
|
+
function polling(command) {
|
|
10
|
+
return command.option('--timeout <seconds>', t('timeout'), '1800').option('--interval <seconds>', t('interval'), '3');
|
|
11
|
+
}
|
|
12
|
+
function identifier(value) {
|
|
13
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value))
|
|
14
|
+
throw new Error(t('invalidRequest'));
|
|
15
|
+
return value.toLowerCase();
|
|
16
|
+
}
|
|
17
|
+
async function document(path) { if (!path)
|
|
18
|
+
throw new Error(t('invalidRequest')); return readAssetRequest(path); }
|
|
19
|
+
async function run(command, options, action) {
|
|
20
|
+
try {
|
|
21
|
+
const scope = await resolveAssetScope(options);
|
|
22
|
+
const result = await action({ scope, client: new AgentApiClient() });
|
|
23
|
+
const record = result && typeof result === 'object' ? result : {};
|
|
24
|
+
const failed = ['failed', 'interrupted', ...(command === 'assets cancel' ? [] : ['cancelled'])];
|
|
25
|
+
const ok = !failed.includes(record.status ?? '');
|
|
26
|
+
process.stdout.write(`${JSON.stringify({ schemaVersion: 'playcraft.assets-cli.v1', command, ok, result })}\n`);
|
|
27
|
+
if (!ok)
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32
|
+
const timeout = message === t('timeoutReached');
|
|
33
|
+
process.stderr.write(`${t('failed')}: ${message}\n`);
|
|
34
|
+
process.stdout.write(`${JSON.stringify({ schemaVersion: 'playcraft.assets-cli.v1', command, ok: false,
|
|
35
|
+
error: { code: timeout ? 'asset_generation_wait_timeout' : 'asset_operation_failed', message } })}\n`);
|
|
36
|
+
process.exitCode = timeout ? 75 : 1;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function write(client, body) {
|
|
40
|
+
return client.post(body.action === 'animation-draft' ? '/workspace-assets/animation-draft' : '/workspace-assets', workspaceAssetToolWriteSchema.parse(body));
|
|
41
|
+
}
|
|
42
|
+
export function registerWorkspaceAssetCommands(program) {
|
|
43
|
+
const assets = program.command('assets').description(t('topic'));
|
|
44
|
+
shared(assets.command('estimate').description(t('estimate')))
|
|
45
|
+
.requiredOption('--request <path>', t('request'))
|
|
46
|
+
.action((options) => run('assets estimate', options, async ({ client, scope }) => {
|
|
47
|
+
const input = await document(options.request), full = assetGenerationRequestSchema.safeParse(input);
|
|
48
|
+
const request = full.success ? assetGenerationEstimateInput(full.data) : assetGenerationEstimateInputSchema.parse(input);
|
|
49
|
+
return assetGenerationEstimateSchema.parse(await write(client, { ...scope, action: 'estimate', request }));
|
|
50
|
+
}));
|
|
51
|
+
polling(shared(assets.command('generate').description(t('generate'))))
|
|
52
|
+
.requiredOption('--request <path>', t('request')).requiredOption('--client-request-id <id>', t('clientRequest'))
|
|
53
|
+
.option('--wait', t('waitOption')).option('--output <path>', t('output'))
|
|
54
|
+
.action((options) => run('assets generate', options, async ({ client, scope }) => {
|
|
55
|
+
if (options.output && !options.wait)
|
|
56
|
+
throw new Error(t('invalidRequest'));
|
|
57
|
+
if (options.wait)
|
|
58
|
+
validateAssetWait(Number(options.timeout), Number(options.interval));
|
|
59
|
+
const clientRequestId = options.clientRequestId.trim();
|
|
60
|
+
if (!clientRequestId)
|
|
61
|
+
throw new Error(t('invalidRequest'));
|
|
62
|
+
const request = assetGenerationRequestSchema.parse(await document(options.request));
|
|
63
|
+
let task = scopedAssetTask(scope, await write(client, { ...scope, action: 'create', clientRequestId, request }));
|
|
64
|
+
if (task.clientRequestId !== clientRequestId)
|
|
65
|
+
throw new Error(t('scopeMismatch'));
|
|
66
|
+
// The identity is printed before polling so a disconnected caller can recover without creating a task.
|
|
67
|
+
if (options.wait) {
|
|
68
|
+
process.stderr.write(`${JSON.stringify({ taskId: task.taskId, clientRequestId: task.clientRequestId, status: task.status })}\n`);
|
|
69
|
+
task = await waitForAssetTask(client, scope, task.taskId, Number(options.timeout), Number(options.interval));
|
|
70
|
+
}
|
|
71
|
+
if (options.output && ['awaiting_adoption', 'saved'].includes(task.status))
|
|
72
|
+
return downloadAssetTask(client, scope, task.taskId, options.output);
|
|
73
|
+
return task;
|
|
74
|
+
}));
|
|
75
|
+
shared(assets.command('tasks').description(t('tasks')))
|
|
76
|
+
.action((options) => run('assets tasks', options, ({ client, scope }) => readAssetTasks(client, scope)));
|
|
77
|
+
shared(assets.command('get <task-id>').description(t('get')))
|
|
78
|
+
.action((taskId, options) => run('assets get', options, ({ client, scope }) => readAssetTask(client, scope, identifier(taskId))));
|
|
79
|
+
shared(assets.command('cancel <task-id>').description(t('cancel')))
|
|
80
|
+
.action((taskId, options) => run('assets cancel', options, async ({ client, scope }) => scopedAssetTask(scope, await write(client, { ...scope, action: 'cancel', taskId: identifier(taskId) }))));
|
|
81
|
+
polling(shared(assets.command('wait <task-id>').description(t('wait'))))
|
|
82
|
+
.action((taskId, options) => run('assets wait', options, ({ client, scope }) => waitForAssetTask(client, scope, identifier(taskId), Number(options.timeout), Number(options.interval))));
|
|
83
|
+
shared(assets.command('download <task-id>').description(t('download')))
|
|
84
|
+
.requiredOption('--output <path>', t('output')).option('--version <id>', t('version'))
|
|
85
|
+
.action((taskId, options) => run('assets download', options, ({ client, scope }) => downloadAssetTask(client, scope, identifier(taskId), options.output, options.version ? identifier(options.version) : undefined)));
|
|
86
|
+
shared(assets.command('saved <task-id>').description(t('saved')))
|
|
87
|
+
.requiredOption('--receipt <path>', t('receipt'))
|
|
88
|
+
.action((taskId, options) => run('assets saved', options, async ({ client, scope }) => scopedAssetTask(scope, await write(client, { ...scope, action: 'saved', taskId: identifier(taskId), proof: assetGenerationTaskSavedSchema.parse(await document(options.receipt)) }))));
|
|
89
|
+
shared(assets.command('library-targets').description(t('libraryTargets')))
|
|
90
|
+
.action((options) => run('assets library-targets', options, async ({ client, scope }) => assetLibrarySaveTargetsSchema.parse(await client.get('/workspace-assets', { ...scope, action: 'library-targets' }))));
|
|
91
|
+
shared(assets.command('library-saves <task-id>').description(t('librarySaves')))
|
|
92
|
+
.action((taskId, options) => run('assets library-saves', options, async ({ client, scope }) => assetLibrarySaveListSchema.parse(await client.get('/workspace-assets', { ...scope, action: 'library-saves', taskId: identifier(taskId) }))));
|
|
93
|
+
shared(assets.command('library-save <task-id>').description(t('librarySave')))
|
|
94
|
+
.requiredOption('--request <path>', t('request'))
|
|
95
|
+
.action((taskId, options) => run('assets library-save', options, async ({ client, scope }) => assetLibrarySaveJobSchema.parse(await write(client, { ...scope, action: 'library-save', taskId: identifier(taskId), request: assetLibrarySaveRequestSchema.parse(await document(options.request)) }))));
|
|
96
|
+
shared(assets.command('library-retry <task-id>').description(t('libraryRetry')))
|
|
97
|
+
.requiredOption('--save-id <id>', t('saveId')).option('--start-without-workspace', t('release'))
|
|
98
|
+
.action((taskId, options) => run('assets library-retry', options, async ({ client, scope }) => assetLibrarySaveJobSchema.parse(await write(client, { ...scope, action: 'library-retry', taskId: identifier(taskId), saveId: identifier(options.saveId),
|
|
99
|
+
...(options.startWithoutWorkspace ? { startWithoutWorkspace: true } : {}) }))));
|
|
100
|
+
const animation = assets.command('animation').description(t('animation'));
|
|
101
|
+
shared(animation.command('get <task-id>').description(t('animationGet')))
|
|
102
|
+
.action((taskId, options) => run('assets animation get', options, async ({ client, scope }) => {
|
|
103
|
+
const result = animationEditorStateSchema.parse(await client.get('/workspace-assets', { ...scope, action: 'animation', taskId: identifier(taskId) }));
|
|
104
|
+
if (result.taskId !== identifier(taskId))
|
|
105
|
+
throw new Error(t('scopeMismatch'));
|
|
106
|
+
return result;
|
|
107
|
+
}));
|
|
108
|
+
for (const [name, action, description, schema, response] of [
|
|
109
|
+
['draft', 'animation-draft', 'animationDraft', animationEditorDraftUpdateSchema, animationEditorStateSchema],
|
|
110
|
+
['upload-frame', 'animation-frame', 'animationFrame', animationEditorFrameUploadSchema, animationEditorFrameUploadResultSchema],
|
|
111
|
+
['version', 'animation-version', 'animationVersion', animationEditorVersionCreateSchema, animationEditorVersionResultSchema],
|
|
112
|
+
]) {
|
|
113
|
+
shared(animation.command(`${name} <task-id>`).description(t(description))).requiredOption('--request <path>', t('request'))
|
|
114
|
+
.action((taskId, options) => run(`assets animation ${name}`, options, async ({ client, scope }) => {
|
|
115
|
+
const body = workspaceAssetToolWriteSchema.parse({ ...scope, action, taskId: identifier(taskId), request: schema.parse(await document(options.request)) });
|
|
116
|
+
return response.parse(await write(client, body));
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
shared(animation.command('saved <task-id>').description(t('animationSaved')))
|
|
120
|
+
.requiredOption('--version <id>', t('version')).requiredOption('--receipt <path>', t('receipt'))
|
|
121
|
+
.action((taskId, options) => run('assets animation saved', options, async ({ client, scope }) => animationEditorVersionResultSchema.parse(await write(client, { ...scope, action: 'animation-saved', taskId: identifier(taskId), versionId: identifier(options.version),
|
|
122
|
+
proof: assetGenerationTaskSavedSchema.parse(await document(options.receipt)) }))));
|
|
123
|
+
}
|
|
@@ -4,6 +4,7 @@ import pc from 'picocolors';
|
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import { BaseBuilder, ViteBuilder, PlayableBuilder, EngineDetector, detectAmmoUsage, } from '@playcraft/build';
|
|
6
6
|
import { loadBuildConfig } from '../build-config.js';
|
|
7
|
+
import { cleanupBuildTempDirectory, createBuildTempDirectory } from './build-temp.js';
|
|
7
8
|
import inquirer from 'inquirer';
|
|
8
9
|
/**
|
|
9
10
|
* 所有可用的渠道平台
|
|
@@ -141,6 +142,7 @@ export async function buildAllCommand(projectPath, options) {
|
|
|
141
142
|
const spinner = ora(pc.cyan('🚀 批量打渠道包...')).start();
|
|
142
143
|
let isBaseBuild = false;
|
|
143
144
|
let baseBuildDir;
|
|
145
|
+
let tempBuildDir;
|
|
144
146
|
try {
|
|
145
147
|
// 1. 确定要构建的平台列表
|
|
146
148
|
let targetPlatforms;
|
|
@@ -415,9 +417,9 @@ export async function buildAllCommand(projectPath, options) {
|
|
|
415
417
|
}
|
|
416
418
|
else {
|
|
417
419
|
spinner.text = pc.cyan('执行阶段1: 基础构建(仅一次)...');
|
|
418
|
-
|
|
420
|
+
tempBuildDir = await createBuildTempDirectory(resolvedProjectPath);
|
|
419
421
|
const baseBuilder = new BaseBuilder(resolvedProjectPath, {
|
|
420
|
-
outputDir:
|
|
422
|
+
outputDir: tempBuildDir,
|
|
421
423
|
selectedScenes,
|
|
422
424
|
analyze: options.analyze,
|
|
423
425
|
});
|
|
@@ -593,6 +595,7 @@ export async function buildAllCommand(projectPath, options) {
|
|
|
593
595
|
if (failCount > 0) {
|
|
594
596
|
process.exit(1);
|
|
595
597
|
}
|
|
598
|
+
await cleanupBuildTempDirectory(tempBuildDir);
|
|
596
599
|
}
|
|
597
600
|
catch (error) {
|
|
598
601
|
spinner.fail(pc.red('批量构建失败'));
|
|
@@ -602,21 +605,4 @@ export async function buildAllCommand(projectPath, options) {
|
|
|
602
605
|
}
|
|
603
606
|
process.exit(1);
|
|
604
607
|
}
|
|
605
|
-
finally {
|
|
606
|
-
// 清理临时目录,避免磁盘空间浪费
|
|
607
|
-
if (!isBaseBuild && baseBuildDir && baseBuildDir.includes('.playcraft-temp')) {
|
|
608
|
-
try {
|
|
609
|
-
await fs.rm(baseBuildDir, { recursive: true, force: true });
|
|
610
|
-
// 如果 .playcraft-temp 父目录为空,也一并清理
|
|
611
|
-
const tempParent = path.dirname(baseBuildDir);
|
|
612
|
-
const remaining = await fs.readdir(tempParent);
|
|
613
|
-
if (remaining.length === 0) {
|
|
614
|
-
await fs.rm(tempParent, { recursive: true, force: true });
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
catch {
|
|
618
|
-
// 清理失败不影响构建结果
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
608
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, rm } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
export async function createBuildTempDirectory(projectPath) {
|
|
5
|
+
const parent = path.join(projectPath, '.playcraft-temp');
|
|
6
|
+
await mkdir(parent, { recursive: true });
|
|
7
|
+
const directory = path.join(parent, `base-build-${randomUUID()}`);
|
|
8
|
+
// mkdir 继承工程的共享组和权限掩码;mkdtemp 固定使用 0700。
|
|
9
|
+
await mkdir(directory);
|
|
10
|
+
return directory;
|
|
11
|
+
}
|
|
12
|
+
export async function cleanupBuildTempDirectory(directory) {
|
|
13
|
+
if (!directory)
|
|
14
|
+
return;
|
|
15
|
+
if (process.env.PLAYCRAFT_KEEP_BUILD_TEMP === '1') {
|
|
16
|
+
console.log(`构建临时目录保留在: ${directory}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
// 只删除本次创建的目录,保留并发构建与用户输入;父目录不做递归清理。
|
|
21
|
+
await rm(directory, { recursive: true, force: true });
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.warn(`清理构建临时目录失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
package/dist/commands/build.js
CHANGED
|
@@ -4,7 +4,12 @@ import pc from 'picocolors';
|
|
|
4
4
|
import ora from 'ora';
|
|
5
5
|
import { BaseBuilder, ViteBuilder, PlayableBuilder, PlayableAnalyzer, EngineDetector, detectAmmoUsage } from '@playcraft/build';
|
|
6
6
|
import { loadBuildConfig } from '../build-config.js';
|
|
7
|
+
import { cleanupBuildTempDirectory, createBuildTempDirectory } from './build-temp.js';
|
|
7
8
|
import inquirer from 'inquirer';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
import { generatedWorkspace } from '../workspace-runtime/workspaces/artifact-receipts.js';
|
|
11
|
+
import { isolateWorkspaceForBuild } from '../workspace-runtime/workspaces/delivery-build.js';
|
|
12
|
+
import { finalizeWorkspacePlayable, workspacePlayableSignature } from '../workspace-runtime/previews/finalize.js';
|
|
8
13
|
/**
|
|
9
14
|
* 类型守卫:检查对象是否符合 PlayableScriptsConfig 类型
|
|
10
15
|
*/
|
|
@@ -244,12 +249,45 @@ async function analyzeBaseBuild(baseBuildDir, ammoReplacement) {
|
|
|
244
249
|
export async function buildCommand(projectPath, options) {
|
|
245
250
|
// 解析项目路径 - 在 spinner 之前执行以便调试
|
|
246
251
|
const resolvedProjectPath = path.resolve(projectPath);
|
|
252
|
+
const workspace = options.workspaceArtifact !== false && process.env.PLAYCRAFT_BUILD_ISOLATED !== '1' && options.mode === 'full' && options.platform === 'playcraft'
|
|
253
|
+
&& (!options.format || options.format === 'html') ? await generatedWorkspace(resolvedProjectPath) : undefined;
|
|
254
|
+
const requestedOutput = options.output ? path.resolve(options.output) : path.join(resolvedProjectPath, 'dist');
|
|
255
|
+
const canonicalOutput = [path.join(resolvedProjectPath, 'dist'), path.join(resolvedProjectPath, 'dist/playable')].includes(requestedOutput);
|
|
256
|
+
if (workspace?.root === resolvedProjectPath) {
|
|
257
|
+
const prefix = requestedOutput.endsWith(path.sep) ? requestedOutput : `${requestedOutput}${path.sep}`;
|
|
258
|
+
if (requestedOutput === workspace.root || workspace.root.startsWith(prefix))
|
|
259
|
+
throw new Error('invalid_build_output');
|
|
260
|
+
const scratch = await fs.mkdtemp(path.join(tmpdir(), 'playcraft-workspace-build-'));
|
|
261
|
+
try {
|
|
262
|
+
const signature = canonicalOutput ? await workspacePlayableSignature(workspace.root) : undefined;
|
|
263
|
+
const project = path.join(scratch, 'project'), output = path.join(scratch, 'output');
|
|
264
|
+
await isolateWorkspaceForBuild(workspace.root, project);
|
|
265
|
+
await buildCommand(project, { ...options, workspaceArtifact: false, output });
|
|
266
|
+
if (canonicalOutput) {
|
|
267
|
+
const entries = await fs.readdir(output, { withFileTypes: true });
|
|
268
|
+
if (entries.length !== 1 || !entries[0].isFile() || !entries[0].name.endsWith('.html'))
|
|
269
|
+
throw new Error('preview_not_single_file');
|
|
270
|
+
await finalizeWorkspacePlayable(workspace.root, await fs.readFile(path.join(output, entries[0].name)), 'playcraft build', { expectedSignature: signature });
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
if (options.clean === true)
|
|
274
|
+
await fs.rm(requestedOutput, { recursive: true, force: true });
|
|
275
|
+
await fs.cp(output, requestedOutput, { recursive: true });
|
|
276
|
+
}
|
|
277
|
+
console.log(canonicalOutput ? path.join(workspace.root, 'dist/playable/index.html') : requestedOutput);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
finally {
|
|
281
|
+
await fs.rm(scratch, { recursive: true, force: true });
|
|
282
|
+
}
|
|
283
|
+
}
|
|
247
284
|
console.log(`[DEBUG] projectPath: ${projectPath}`);
|
|
248
285
|
console.log(`[DEBUG] resolvedProjectPath: ${resolvedProjectPath}`);
|
|
249
286
|
console.log(`[DEBUG] cwd: ${process.cwd()}`);
|
|
250
287
|
const spinner = ora(pc.cyan('🔨 开始打包 Playable Ad...')).start();
|
|
251
288
|
// 清理选项(默认为 false,使用覆盖模式)
|
|
252
289
|
const shouldClean = options.clean === true;
|
|
290
|
+
let tempBuildDir;
|
|
253
291
|
try {
|
|
254
292
|
// ====== 引擎 + 构建工具检测 ======
|
|
255
293
|
spinner.text = pc.cyan('检测项目引擎类型...');
|
|
@@ -450,6 +488,7 @@ export async function buildCommand(projectPath, options) {
|
|
|
450
488
|
const shouldRunPlayableOnly = options.mode === 'playable';
|
|
451
489
|
// 验证平台
|
|
452
490
|
const validPlatforms = [
|
|
491
|
+
'playcraft',
|
|
453
492
|
'facebook',
|
|
454
493
|
'snapchat',
|
|
455
494
|
'ironsource',
|
|
@@ -473,6 +512,7 @@ export async function buildCommand(projectPath, options) {
|
|
|
473
512
|
// 注:Facebook 在 Phaser(playable-scripts devkit)下的产物格式由其 devkit 输入配置决定(恒为 ZIP),
|
|
474
513
|
// 平台侧不在此处做引擎判断。
|
|
475
514
|
const platformFormatConfig = {
|
|
515
|
+
playcraft: { formats: ['html'], default: 'html' },
|
|
476
516
|
facebook: { formats: ['html', 'zip'], default: 'html' },
|
|
477
517
|
applovin: { formats: ['html'], default: 'html' },
|
|
478
518
|
ironsource: { formats: ['html'], default: 'html' },
|
|
@@ -584,8 +624,11 @@ export async function buildCommand(projectPath, options) {
|
|
|
584
624
|
console.log(pc.dim(' 无主题目录,跳过主题选择'));
|
|
585
625
|
}
|
|
586
626
|
}
|
|
587
|
-
// 输入商店跳转地址(CTA)-
|
|
588
|
-
if (!options.storeUrls) {
|
|
627
|
+
// 输入商店跳转地址(CTA)- 如果配置文件中没有则必填;通用预览(playcraft)不面向渠道,可不填
|
|
628
|
+
if (selectedPlatform === 'playcraft' && !options.storeUrls) {
|
|
629
|
+
console.log(pc.dim('\nℹ️ 通用预览不需要商店地址'));
|
|
630
|
+
}
|
|
631
|
+
else if (!options.storeUrls) {
|
|
589
632
|
console.log(pc.cyan('\n🔗 商店跳转地址(CTA 按钮目标)'));
|
|
590
633
|
console.log(pc.dim(' iOS 和 Android 地址均为必填'));
|
|
591
634
|
const storeUrlAnswer = await inquirer.prompt([
|
|
@@ -636,8 +679,8 @@ export async function buildCommand(projectPath, options) {
|
|
|
636
679
|
// 未指定格式,使用默认值
|
|
637
680
|
options.format = formatConfig.default;
|
|
638
681
|
}
|
|
639
|
-
// 如果命令行未传入 storeUrls
|
|
640
|
-
if (!options.storeUrls) {
|
|
682
|
+
// 如果命令行未传入 storeUrls,交互式输入(必填);通用预览(playcraft)不面向渠道,可不填
|
|
683
|
+
if (!options.storeUrls && options.platform !== 'playcraft') {
|
|
641
684
|
spinner.stop();
|
|
642
685
|
console.log(pc.cyan('\n🔗 商店跳转地址(CTA 按钮目标)'));
|
|
643
686
|
console.log(pc.dim(' iOS 和 Android 地址均为必填'));
|
|
@@ -742,7 +785,7 @@ export async function buildCommand(projectPath, options) {
|
|
|
742
785
|
// 输入是源代码或官方构建,先执行阶段1
|
|
743
786
|
spinner.text = pc.cyan('执行阶段1: 基础构建...');
|
|
744
787
|
// 将临时目录放在项目所在目录下,避免跨盘符路径问题(Windows 上 C:\Temp 和 D:\project 会导致 Vite 路径计算错误)
|
|
745
|
-
|
|
788
|
+
tempBuildDir = await createBuildTempDirectory(resolvedProjectPath);
|
|
746
789
|
// 构建 playableScriptsConfig,合并 CLI 选择的参数
|
|
747
790
|
const playableScriptsConfig = buildPlayableScriptsConfig(fileConfig?.playableScripts, {
|
|
748
791
|
platform: options.platform,
|
|
@@ -750,7 +793,7 @@ export async function buildCommand(projectPath, options) {
|
|
|
750
793
|
selectedThemes,
|
|
751
794
|
});
|
|
752
795
|
const baseBuilder = new BaseBuilder(resolvedProjectPath, {
|
|
753
|
-
outputDir:
|
|
796
|
+
outputDir: tempBuildDir,
|
|
754
797
|
selectedScenes,
|
|
755
798
|
analyze: buildOptions.analyze,
|
|
756
799
|
analyzeReportPath: buildOptions.analyze ? 'base-bundle-report.html' : undefined,
|
|
@@ -795,16 +838,7 @@ export async function buildCommand(projectPath, options) {
|
|
|
795
838
|
}
|
|
796
839
|
console.log('\n' + pc.green(`输出目录: ${finalOutputDir}`));
|
|
797
840
|
console.log(pc.dim('💡 产物已包含渠道适配、MRAID 注入、代码混淆和 fflate 压缩'));
|
|
798
|
-
|
|
799
|
-
try {
|
|
800
|
-
const tempBaseDir = path.join(resolvedProjectPath, '.playcraft-temp');
|
|
801
|
-
await fs.rm(tempBaseDir, { recursive: true, force: true });
|
|
802
|
-
console.log(pc.dim(`\n🗑️ 已清理临时目录`));
|
|
803
|
-
}
|
|
804
|
-
catch (error) {
|
|
805
|
-
// 记录清理错误信息
|
|
806
|
-
console.log(pc.dim(`\n⚠️ 清理临时目录失败: ${error instanceof Error ? error.message : String(error)}`));
|
|
807
|
-
}
|
|
841
|
+
await cleanupBuildTempDirectory(tempBuildDir);
|
|
808
842
|
return;
|
|
809
843
|
}
|
|
810
844
|
spinner.text = pc.cyan('✅ 阶段1完成,开始阶段2...');
|
|
@@ -976,18 +1010,7 @@ export async function buildCommand(projectPath, options) {
|
|
|
976
1010
|
console.log(pc.yellow(`\n⚠️ 检测到 Ammo.js,建议替换为 ${analysis.suggestedEngine}`));
|
|
977
1011
|
}
|
|
978
1012
|
}
|
|
979
|
-
|
|
980
|
-
if (!isBaseBuild && baseBuildDir.includes('.playcraft-temp')) {
|
|
981
|
-
// 调试:暂时保留临时目录
|
|
982
|
-
console.log(pc.yellow(`[DEBUG] 临时目录保留在: ${baseBuildDir}`));
|
|
983
|
-
// try {
|
|
984
|
-
// // 清理整个 .playcraft-temp 目录
|
|
985
|
-
// const tempBaseDir = path.join(resolvedProjectPath, '.playcraft-temp');
|
|
986
|
-
// await fs.rm(tempBaseDir, { recursive: true, force: true });
|
|
987
|
-
// } catch (error) {
|
|
988
|
-
// // 忽略清理错误
|
|
989
|
-
// }
|
|
990
|
-
}
|
|
1013
|
+
await cleanupBuildTempDirectory(tempBuildDir);
|
|
991
1014
|
}
|
|
992
1015
|
catch (error) {
|
|
993
1016
|
spinner.fail(pc.red('打包失败'));
|
|
@@ -995,6 +1018,8 @@ export async function buildCommand(projectPath, options) {
|
|
|
995
1018
|
if (error.stack) {
|
|
996
1019
|
console.error(pc.dim(error.stack));
|
|
997
1020
|
}
|
|
1021
|
+
if (options.workspaceArtifact === false)
|
|
1022
|
+
throw error;
|
|
998
1023
|
process.exit(1);
|
|
999
1024
|
}
|
|
1000
1025
|
}
|