@playcraft/cli 0.1.27 → 0.1.29
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 +3 -38
- package/dist/agent/local-backend.js +1 -1
- package/dist/cli-root-help.js +0 -2
- package/dist/commands/build.js +4 -9
- package/dist/commands/create.js +33 -26
- package/dist/commands/image.js +6 -2
- package/dist/commands/login.js +42 -84
- package/dist/commands/skills.js +0 -2
- package/dist/commands/tools-3d.js +0 -11
- package/dist/commands/tools-generation.js +109 -68
- package/dist/commands/tools-image-context.js +23 -0
- package/dist/commands/tools.js +2 -2
- package/dist/config.js +4 -59
- package/dist/index.js +3 -34
- package/dist/remix/clone.js +0 -2
- package/dist/remix/init-template.js +0 -2
- package/dist/remix/pull.js +0 -2
- package/dist/remix/push.js +1 -21
- package/dist/utils/agent-api-client.js +30 -185
- package/dist/utils/image-asset-context.js +105 -0
- package/dist/utils/playcraft-http-client.js +4 -6
- package/package.json +5 -14
- package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +81 -23
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +81 -23
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +81 -23
- package/dist/auth/account-activation.js +0 -157
- package/dist/auth/messages.js +0 -30
- package/dist/commands/platform-skills.generated.js +0 -19
- package/dist/commands/playable.js +0 -53
- package/dist/commands/tools-batch.js +0 -87
- package/dist/commands/video.js +0 -111
- package/dist/commands/workspace-runtime.js +0 -54
- package/dist/project-skills/builtin-import.js +0 -225
- package/dist/project-skills/commands.js +0 -77
- package/dist/project-skills/lifecycle.js +0 -28
- package/dist/project-skills/local-run.js +0 -112
- package/dist/project-skills/local-store.js +0 -221
- package/dist/project-skills/messages.js +0 -80
- package/dist/project-skills/reconcile.js +0 -62
- package/dist/project-skills/remote-cache.js +0 -51
- package/dist/project-skills/validation.js +0 -19
- package/dist/recording/messages.js +0 -40
- package/dist/recording/project-digest.js +0 -85
- package/dist/recording/recorder.js +0 -293
- package/dist/recording/scenario.js +0 -50
- package/dist/utils/environment-endpoints.js +0 -17
- package/dist/utils/tool-operation-journal.js +0 -124
- package/dist/utils/video-evidence-git.js +0 -81
- package/dist/video-replication/client.js +0 -222
- package/dist/video-replication/comparison-evidence.js +0 -149
- package/dist/video-replication/comparison-files.js +0 -57
- package/dist/video-replication/comparison-log.js +0 -72
- package/dist/video-replication/comparison-messages.js +0 -104
- package/dist/video-replication/comparison-output.js +0 -63
- package/dist/video-replication/comparison-preflight.js +0 -66
- package/dist/video-replication/comparison.js +0 -216
- package/dist/video-replication/evidence.js +0 -165
- package/dist/video-replication/media.js +0 -111
- package/dist/video-replication/messages.js +0 -89
- package/dist/workspace-runtime/codex/app-server.js +0 -636
- package/dist/workspace-runtime/codex/config-toml.js +0 -107
- package/dist/workspace-runtime/codex/jsonrpc-stdio.js +0 -123
- package/dist/workspace-runtime/codex/launcher-client.js +0 -163
- package/dist/workspace-runtime/codex/loopback.js +0 -143
- package/dist/workspace-runtime/codex/model-broker.js +0 -258
- package/dist/workspace-runtime/codex/native-adapter.js +0 -9
- package/dist/workspace-runtime/main.js +0 -10
- package/dist/workspace-runtime/persistence/journal.js +0 -355
- package/dist/workspace-runtime/persistence/native-subagents.js +0 -162
- package/dist/workspace-runtime/persistence/sqlite-client.js +0 -77
- package/dist/workspace-runtime/persistence/sqlite-worker.js +0 -1057
- package/dist/workspace-runtime/previews/publish.js +0 -259
- package/dist/workspace-runtime/previews/single-file.js +0 -43
- package/dist/workspace-runtime/processes/managed-writes.js +0 -69
- package/dist/workspace-runtime/production/contracts.js +0 -17
- package/dist/workspace-runtime/production/controller.js +0 -207
- package/dist/workspace-runtime/production/dependencies.js +0 -60
- package/dist/workspace-runtime/production/native.js +0 -90
- package/dist/workspace-runtime/production/processes.js +0 -86
- package/dist/workspace-runtime/production/save-command.js +0 -24
- package/dist/workspace-runtime/production/source-copy.js +0 -91
- package/dist/workspace-runtime/production/stages.js +0 -202
- package/dist/workspace-runtime/production/storage.js +0 -32
- package/dist/workspace-runtime/serve.js +0 -202
- package/dist/workspace-runtime/server/auth.js +0 -21
- package/dist/workspace-runtime/server/connectivity.js +0 -201
- package/dist/workspace-runtime/server/desktop-host.js +0 -429
- package/dist/workspace-runtime/server/desktop-preview-config.js +0 -81
- package/dist/workspace-runtime/server/desktop-preview-service.js +0 -157
- package/dist/workspace-runtime/server/desktop-preview-static.js +0 -53
- package/dist/workspace-runtime/server/desktop-preview.js +0 -189
- package/dist/workspace-runtime/server/dispatch.js +0 -903
- package/dist/workspace-runtime/server/endpoints.js +0 -19
- package/dist/workspace-runtime/server/execution-group.js +0 -85
- package/dist/workspace-runtime/server/http.js +0 -984
- package/dist/workspace-runtime/server/lock.js +0 -53
- package/dist/workspace-runtime/server/rfb-watch-gate.js +0 -168
- package/dist/workspace-runtime/server/terminal-host.js +0 -294
- package/dist/workspace-runtime/server/types.js +0 -1
- package/dist/workspace-runtime/workspaces/artifact-events.js +0 -55
- package/dist/workspace-runtime/workspaces/artifact-files.js +0 -195
- package/dist/workspace-runtime/workspaces/artifact-receipts.js +0 -89
- package/dist/workspace-runtime/workspaces/artifacts.js +0 -260
- package/dist/workspace-runtime/workspaces/attachment-content.js +0 -111
- package/dist/workspace-runtime/workspaces/attachments.js +0 -175
- package/dist/workspace-runtime/workspaces/batch-commit.js +0 -142
- package/dist/workspace-runtime/workspaces/cli-context.js +0 -23
- package/dist/workspace-runtime/workspaces/cli-credentials.js +0 -111
- package/dist/workspace-runtime/workspaces/context-error.js +0 -2
- package/dist/workspace-runtime/workspaces/dependencies.js +0 -264
- package/dist/workspace-runtime/workspaces/developer-command.js +0 -64
- package/dist/workspace-runtime/workspaces/directories.js +0 -113
- package/dist/workspace-runtime/workspaces/directory-access.js +0 -29
- package/dist/workspace-runtime/workspaces/directory-maintenance.js +0 -111
- package/dist/workspace-runtime/workspaces/directory-stats.js +0 -49
- package/dist/workspace-runtime/workspaces/disk-snapshot.js +0 -31
- package/dist/workspace-runtime/workspaces/empty-template.js +0 -40
- package/dist/workspace-runtime/workspaces/files.js +0 -120
- package/dist/workspace-runtime/workspaces/git-credential-broker.js +0 -312
- package/dist/workspace-runtime/workspaces/git-credential-helper.js +0 -68
- package/dist/workspace-runtime/workspaces/git-direct-store.js +0 -155
- package/dist/workspace-runtime/workspaces/git.js +0 -517
- package/dist/workspace-runtime/workspaces/json5-edit.js +0 -170
- package/dist/workspace-runtime/workspaces/parameters.js +0 -272
- package/dist/workspace-runtime/workspaces/prepare.js +0 -264
- package/dist/workspace-runtime/workspaces/registry.js +0 -226
- package/dist/workspace-runtime/workspaces/revisions.js +0 -31
- package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +0 -91
- package/dist/workspace-runtime/workspaces/skills.js +0 -189
- package/dist/workspace-runtime/workspaces/video-attachments.js +0 -49
- package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +0 -25
- package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +0 -79
- package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +0 -29
- package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +0 -37
- package/project-template-v2/.claude/agents/artist.md +0 -82
- package/project-template-v2/.claude/agents/developer.md +0 -153
- package/project-template-v2/.claude/agents/game-designer.md +0 -264
- package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +0 -533
- package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +0 -153
- package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +0 -27
- package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +0 -208
- package/project-template-v2/.claude/agents/refs/atom-skill-library.md +0 -81
- package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +0 -432
- package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +0 -252
- package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +0 -266
- package/project-template-v2/.claude/agents/refs/framework-mda.md +0 -147
- package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +0 -123
- package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +0 -88
- package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +0 -67
- package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +0 -120
- package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +0 -300
- package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +0 -495
- package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +0 -1141
- package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +0 -111
- package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +0 -365
- package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +0 -412
- package/project-template-v2/.claude/agents/reviewer.md +0 -75
- package/project-template-v2/.claude/agents/technical-artist.md +0 -86
- package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +0 -243
- package/project-template-v2/.claude/hooks/user-prompt.mjs +0 -133
- package/project-template-v2/.claude/settings.json +0 -33
- package/project-template-v2/.claude/skills/brainstorming/SKILL.md +0 -161
- package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +0 -270
- package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +0 -177
- package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +0 -354
- package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +0 -148
- package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +0 -56
- package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +0 -62
- package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
- package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +0 -309
- package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +0 -182
- package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +0 -123
- package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +0 -205
- package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +0 -280
- package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +0 -184
- package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +0 -306
- package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +0 -298
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +0 -123
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +0 -254
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +0 -324
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +0 -97
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +0 -118
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +0 -137
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +0 -397
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +0 -296
- package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +0 -122
- package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +0 -219
- package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +0 -373
- package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +0 -161
- package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +0 -215
- package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +0 -382
- package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +0 -423
- package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +0 -158
- package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +0 -100
- package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +0 -167
- package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +0 -270
- package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +0 -236
- package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +0 -130
- package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +0 -390
- package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +0 -23
- package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +0 -39
- package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +0 -87
- package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +0 -240
- package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +0 -226
- package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +0 -308
- package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +0 -275
- package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +0 -134
- package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +0 -142
- package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +0 -153
- package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +0 -386
- package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +0 -182
- package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +0 -72
- package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +0 -121
- package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +0 -102
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +0 -127
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +0 -106
- package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +0 -128
- package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +0 -67
- package/project-template-v2/.claude/snapshot.mjs +0 -263
- package/project-template-v2/.playcraft/skills.lock.json +0 -152
- package/project-template-v2/CLAUDE.md +0 -146
- 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 +0 -254
- package/project-template-v2/docs/harness/iteration-1/generate-flow.md +0 -91
- package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +0 -214
- package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +0 -75
- package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +0 -63
- package/project-template-v2/docs/harness/iteration-2/context-flow.md +0 -223
- package/project-template-v2/docs/harness/iteration-2/generate-flow.md +0 -129
- package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +0 -267
- package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +0 -164
- package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +0 -115
- package/project-template-v2/docs/harness/orchestrator-flow.md +0 -364
- package/project-template-v2/docs/project-state.json +0 -60
- package/project-template-v2/docs/project-state.md +0 -72
- package/project-template-v2/docs/standards/README.md +0 -225
- package/project-template-v2/docs/standards/agent-behavior-standards.md +0 -174
- package/project-template-v2/docs/standards/artifacts/design-brief.md +0 -19
- package/project-template-v2/docs/standards/artifacts/design.md +0 -22
- package/project-template-v2/docs/standards/artifacts/game-code.md +0 -41
- package/project-template-v2/docs/standards/artifacts/todo-list.md +0 -41
- package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +0 -343
- package/project-template-v2/game/index.ts +0 -18
- package/project-template-v2/globals.d.ts +0 -51
- package/project-template-v2/index.css +0 -34
- package/project-template-v2/index.html +0 -18
- package/project-template-v2/main.ts +0 -9
- package/project-template-v2/package.json +0 -46
- package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +0 -31
- package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +0 -86
- package/project-template-v2/skills/_shared/scripts/dod-check.mjs +0 -153
- package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +0 -70
- package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +0 -91
- package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +0 -131
- package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +0 -80
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +0 -90
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +0 -93
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +0 -23
- package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +0 -230
- package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +0 -58
- package/project-template-v2/skills/_shared/scripts/state-get.mjs +0 -339
- package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +0 -39
- package/project-template-v2/skills/_shared/scripts/state-set.mjs +0 -94
- package/project-template-v2/skills/_shared/scripts/state-store.mjs +0 -783
- package/project-template-v2/skills/_shared/scripts/todo-add.mjs +0 -88
- package/project-template-v2/skills/_shared/scripts/todo-get.mjs +0 -130
- package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +0 -33
- package/project-template-v2/skills/_shared/scripts/todo-set.mjs +0 -47
- package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +0 -268
- package/project-template-v2/skills/_shared/scripts/verify-env.mjs +0 -285
- package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +0 -161
- package/project-template-v2/skills/playable-autoplay/SKILL.md +0 -176
- package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +0 -4
- package/project-template-v2/skills/playable-debug/SKILL.md +0 -116
- package/project-template-v2/skills/playable-debug/agents/openai.yaml +0 -4
- package/project-template-v2/skills/playable-debug/references/debug-config.md +0 -40
- package/project-template-v2/skills/playable-record/SKILL.md +0 -140
- package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +0 -104
- package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +0 -141
- package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +0 -425
- package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +0 -261
- package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +0 -398
- package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +0 -322
- package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +0 -105
- package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +0 -230
- package/project-template-v2/skills/playable-validate/SKILL.md +0 -61
- package/project-template-v2/skills/playable-validate/validation-rules.md +0 -14
- package/project-template-v2/skills/playable-verify-ui/SKILL.md +0 -63
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +0 -1
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +0 -218
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +0 -51
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +0 -59
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +0 -106
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +0 -116
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +0 -59
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +0 -64
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +0 -58
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +0 -333
- package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
- package/project-template-v2/tsconfig.json +0 -20
- package/project-template-v2/vite.config.ts +0 -27
- package/project-templates/batch-locks/phaser.yaml +0 -922
- package/project-templates/batch-locks/threejs.yaml +0 -978
- package/project-templates/empty/AGENTS.md +0 -25
- package/project-templates/empty/gitignore +0 -33
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { writeFileSync, mkdirSync } from 'fs';
|
|
2
2
|
import { dirname, parse, join } from 'path';
|
|
3
3
|
import sharp from 'sharp';
|
|
4
|
-
import {
|
|
4
|
+
import { resolveImageBackgroundRequirement, validateImageDeliveryOptions } from '@playcraft/common/prefab';
|
|
5
|
+
import { readImageAssetContext } from '../utils/image-asset-context.js';
|
|
5
6
|
import { AgentApiClient } from '../utils/agent-api-client.js';
|
|
6
7
|
import { MAX_REFERENCE_IMAGES, collectReferenceImagePaths, collectReferenceImagePayloads, sniffImageExtension, extensionForImageMime, resolveImageOutputPath, handleError, raceWithTimeout, } from './tools-utils.js';
|
|
7
8
|
function isMasterCompositeStripRequest(opts) {
|
|
@@ -151,86 +152,120 @@ export function registerGenerationCommands(tools) {
|
|
|
151
152
|
.requiredOption('--prompt <text>', '图片描述')
|
|
152
153
|
.option('--aspect-ratio <ratio>', '宽高比 (1:1|45:16|16:9|9:16|3:4|4:3|2:3|3:2|21:9)', '1:1')
|
|
153
154
|
.requiredOption('--output <path>', '保存路径(--count>1 时自动追加 _1/_2 等后缀)')
|
|
155
|
+
.option('--target-asset <path>', 'Existing asset to replace; read its schema references and delivery constraints')
|
|
156
|
+
.option('--no-target-reference', 'Generate without the existing asset reference only when explicitly requested')
|
|
157
|
+
.option('--output-format <format>', 'Final format: png, webp or jpeg')
|
|
158
|
+
.option('--fit-mode <mode>', 'Canvas fitting: contain, cover or fill')
|
|
159
|
+
.option('--padding-color <color>', 'Canvas padding color (transparent by default)')
|
|
160
|
+
.option('--remove-background', 'Require a verified transparent image')
|
|
161
|
+
.option('--no-remove-background', 'Keep the generated background')
|
|
154
162
|
.option('--image-size <size>', '图片尺寸 (1K|2K|4K)')
|
|
155
163
|
.option('--width <n>', '精确宽度(像素;MC 横排 5×9:16 推荐 3600 或 4096)', (v) => parseInt(v, 10))
|
|
156
164
|
.option('--height <n>', '精确高度(像素;MC 推荐 1280 或 1455)', (v) => parseInt(v, 10))
|
|
157
165
|
.option('--reference-image <path>', '参考图路径(可重复多次,最多 8 张),支持 PNG/JPG/WEBP', collectReferenceImagePaths, [])
|
|
158
166
|
.option('--image-model <model>', '模型名(如 gpt-image-2)或 provider/model(如 mulerouter/gpt-image-2)。传模型名时后端按优先级自动 fallback;传 provider/model 则直连指定 provider')
|
|
159
|
-
.option('--retry <n>', '
|
|
167
|
+
.option('--retry <n>', '额外重试轮数(默认 0;后端统一限制尝试,透明验证失败和超时不重试)', (v) => parseInt(v, 10), 0)
|
|
160
168
|
.option('--timeout <seconds>', '请求超时秒数(默认 1800,即 30 分钟;异步生图模型耗时较长,仅在后端明确报错时提前终止)', (v) => parseInt(v, 10), 1800)
|
|
161
169
|
.option('--count <n>', '一次 API 调用生成多少张图片(默认 1,最多 10;仅 gpt-image-2 实际支持批量)', (v) => parseInt(v, 10), 1)
|
|
162
170
|
.action(async (opts) => {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
171
|
+
try {
|
|
172
|
+
const assetContext = opts.targetAsset ? await readImageAssetContext(opts.targetAsset, process.cwd(), {
|
|
173
|
+
referenceImagePaths: opts.referenceImage, useTargetReference: opts.targetReference,
|
|
174
|
+
prompt: opts.prompt, removeBackground: opts.removeBackground,
|
|
175
|
+
}) : undefined;
|
|
176
|
+
opts = { ...opts,
|
|
177
|
+
aspectRatio: assetContext?.aspectRatio ?? opts.aspectRatio,
|
|
178
|
+
width: assetContext?.width ?? opts.width, height: assetContext?.height ?? opts.height,
|
|
179
|
+
outputFormat: assetContext?.outputFormat ?? opts.outputFormat,
|
|
180
|
+
fitMode: assetContext?.fitMode ?? opts.fitMode,
|
|
181
|
+
removeBackground: resolveImageBackgroundRequirement({ prompt: opts.prompt,
|
|
182
|
+
schemaRemoveBackground: assetContext?.removeBackgroundFromSchema ? assetContext.removeBackground : undefined,
|
|
183
|
+
removeBackground: opts.removeBackground, fallbackRemoveBackground: assetContext?.removeBackground }),
|
|
184
|
+
paddingColor: assetContext?.paddingColor ?? opts.paddingColor,
|
|
185
|
+
imageModel: opts.imageModel || assetContext?.imageModelRef,
|
|
186
|
+
};
|
|
187
|
+
const invalidDelivery = validateImageDeliveryOptions(opts);
|
|
188
|
+
if (invalidDelivery)
|
|
189
|
+
throw new Error(invalidDelivery);
|
|
190
|
+
const paths = opts.referenceImage?.length ? opts.referenceImage : assetContext?.referenceImagePaths ?? [];
|
|
191
|
+
if (paths.length > MAX_REFERENCE_IMAGES) {
|
|
192
|
+
console.error(`Error: Too many reference images: ${paths.length} paths given; maximum is ${MAX_REFERENCE_IMAGES}.`);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
return;
|
|
177
195
|
}
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
aspectRatio: opts.aspectRatio,
|
|
184
|
-
imageSize: opts.imageSize,
|
|
185
|
-
...(opts.width && opts.height ? { width: opts.width, height: opts.height } : {}),
|
|
186
|
-
referenceImages,
|
|
187
|
-
...(modelRef ? { imageModelRef: modelRef } : {}),
|
|
188
|
-
...(imageCount > 1 ? { imageCount } : {}),
|
|
189
|
-
});
|
|
190
|
-
return raceWithTimeout(requestPromise, opts.timeout * 1000, `Request timed out after ${opts.timeout}s. The backend task may still be running — check admin panel before re-running.`);
|
|
191
|
-
};
|
|
192
|
-
const enrichError = (err, modelRef) => {
|
|
193
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
194
|
-
const lines = [`Error: ${msg}`];
|
|
195
|
-
if (msg.includes('500') || msg.includes('Internal server error')) {
|
|
196
|
-
lines.push('');
|
|
197
|
-
lines.push('Hint: API 500 error — the model may be temporarily unavailable.');
|
|
198
|
-
lines.push(' → If using a bare model name (e.g. gpt-image-2), all providers failed — try a different model');
|
|
199
|
-
if (modelRef?.includes('/')) {
|
|
200
|
-
lines.push(' → Or try without provider prefix to auto-fallback providers: --image-model gpt-image-2');
|
|
196
|
+
const hasReferenceImages = paths.length > 0;
|
|
197
|
+
const attemptGenerate = async (modelRef, attempt) => {
|
|
198
|
+
const label = modelRef ? `[${modelRef}]` : '[default model]';
|
|
199
|
+
if (attempt > 0) {
|
|
200
|
+
console.log(`Retry ${attempt}/${opts.retry} ${label}...`);
|
|
201
201
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
202
|
+
else {
|
|
203
|
+
console.log(`Generating image ${label}...`);
|
|
204
|
+
}
|
|
205
|
+
const referenceImages = await collectReferenceImagePayloads(paths);
|
|
206
|
+
const client = new AgentApiClient();
|
|
207
|
+
const imageCount = Math.min(Math.max(1, opts.count ?? 1), 10);
|
|
208
|
+
const requestPromise = client.post('/generate-image', {
|
|
209
|
+
prompt: opts.prompt,
|
|
210
|
+
aspectRatio: assetContext?.aspectRatio ?? opts.aspectRatio,
|
|
211
|
+
imageSize: opts.imageSize,
|
|
212
|
+
width: assetContext?.width ?? opts.width,
|
|
213
|
+
height: assetContext?.height ?? opts.height,
|
|
214
|
+
outputFormat: assetContext?.outputFormat ?? opts.outputFormat,
|
|
215
|
+
fitMode: assetContext?.fitMode ?? opts.fitMode,
|
|
216
|
+
paddingColor: assetContext?.paddingColor ?? opts.paddingColor,
|
|
217
|
+
removeBackground: opts.removeBackground,
|
|
218
|
+
referenceImages,
|
|
219
|
+
...(modelRef ? { imageModelRef: modelRef } : {}),
|
|
220
|
+
...(imageCount > 1 ? { imageCount } : {}),
|
|
221
|
+
});
|
|
222
|
+
return raceWithTimeout(requestPromise, opts.timeout * 1000, `Request timed out after ${opts.timeout}s. The backend task may still be running — check admin panel before re-running.`);
|
|
223
|
+
};
|
|
224
|
+
const enrichError = (err, modelRef) => {
|
|
225
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
226
|
+
const lines = [`Error: ${msg}`];
|
|
227
|
+
if (/source_transparency_invalid|output_transparency_invalid|transparency_unsupported/.test(msg)) {
|
|
228
|
+
lines.push('Hint: Transparent output was not delivered. Preserve the requested transparency, references and model; use the request id and stage to investigate.');
|
|
229
|
+
}
|
|
230
|
+
else if (/API 500\b|Internal server error/.test(msg)) {
|
|
231
|
+
lines.push('');
|
|
232
|
+
lines.push('Hint: API 500 error — the model may be temporarily unavailable.');
|
|
233
|
+
lines.push(' → Inspect the request id and backend diagnostics before another generation attempt.');
|
|
234
|
+
if (modelRef?.includes('/') && opts.removeBackground !== true) {
|
|
235
|
+
lines.push(' → Or try without provider prefix to auto-fallback providers: --image-model gpt-image-2');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else if (msg.includes('timed out')) {
|
|
239
|
+
lines.push('');
|
|
240
|
+
lines.push('Hint: Request timed out. The backend task may still be running — retries were skipped to avoid creating duplicate tasks.');
|
|
241
|
+
lines.push(' → Check the backend/admin panel for task status before re-running');
|
|
242
|
+
lines.push(' → Try --image-size 1K to reduce generation time');
|
|
243
|
+
lines.push(' → Or increase timeout with --timeout <seconds> (current default: 1800s)');
|
|
244
|
+
}
|
|
245
|
+
else if (hasReferenceImages && (msg.includes('reference') || msg.includes('image input'))) {
|
|
246
|
+
lines.push('');
|
|
247
|
+
lines.push('Hint: Reference image error — the selected model may not support --reference-image.');
|
|
248
|
+
lines.push(' → Run: playcraft tools list-image-models');
|
|
249
|
+
lines.push(' → Models with CAPABILITY=text+image support --reference-image');
|
|
250
|
+
}
|
|
251
|
+
return lines.join('\n');
|
|
252
|
+
};
|
|
219
253
|
let result = null;
|
|
220
254
|
let lastError = null;
|
|
221
255
|
// 重试逻辑:超时不重试(后端任务可能仍在运行,重试会导致重复提交)
|
|
222
|
-
const maxAttempts = 1 + (opts.retry ??
|
|
256
|
+
const maxAttempts = 1 + (opts.retry ?? 0);
|
|
223
257
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
224
258
|
try {
|
|
225
|
-
result = await attemptGenerate(opts.imageModel, attempt);
|
|
259
|
+
result = await attemptGenerate(opts.imageModel || assetContext?.imageModelRef, attempt);
|
|
226
260
|
break;
|
|
227
261
|
}
|
|
228
262
|
catch (e) {
|
|
229
263
|
lastError = e;
|
|
230
264
|
const msg = e instanceof Error ? e.message : String(e);
|
|
231
265
|
const isTimeout = msg.includes('timed out');
|
|
232
|
-
|
|
233
|
-
|
|
266
|
+
const cannotRetry = /source_transparency_invalid|output_transparency_invalid|transparency_unsupported|"retryable"\s*:\s*false/.test(msg);
|
|
267
|
+
if (isTimeout || cannotRetry) {
|
|
268
|
+
console.error(`Attempt ${attempt + 1} stopped: ${msg}`);
|
|
234
269
|
break;
|
|
235
270
|
}
|
|
236
271
|
if (attempt < maxAttempts - 1) {
|
|
@@ -259,12 +294,14 @@ export function registerGenerationCommands(tools) {
|
|
|
259
294
|
...(result.additionalImages ?? []),
|
|
260
295
|
];
|
|
261
296
|
const isBatch = allImages.length > 1;
|
|
262
|
-
const modelPart =
|
|
297
|
+
const modelPart = result.model ? `model: ${result.model}` : '';
|
|
263
298
|
const providerPart = result.provider ? `provider: ${result.provider}` : '';
|
|
264
299
|
const labelParts = [modelPart, providerPart].filter(Boolean);
|
|
265
300
|
const modelLabel = labelParts.length > 0 ? ` (${labelParts.join(', ')})` : '';
|
|
266
301
|
const savedPaths = [];
|
|
267
|
-
|
|
302
|
+
if (result.transparencySource)
|
|
303
|
+
console.log(`Transparency source: ${result.transparencySource}`);
|
|
304
|
+
const stripTarget = opts.targetAsset || result.transparentBackground ? null : resolveStripTargetDimensions({
|
|
268
305
|
aspectRatio: opts.aspectRatio,
|
|
269
306
|
width: opts.width,
|
|
270
307
|
height: opts.height,
|
|
@@ -312,8 +349,17 @@ export function registerGenerationCommands(tools) {
|
|
|
312
349
|
savedPaths.push(resolvedPath);
|
|
313
350
|
const sidecar = {
|
|
314
351
|
prompt: opts.prompt,
|
|
315
|
-
model:
|
|
352
|
+
model: result.model ?? null,
|
|
353
|
+
requestedModel: opts.imageModel ?? null,
|
|
316
354
|
provider: result.provider ?? null,
|
|
355
|
+
transparentBackground: result.transparentBackground ?? null,
|
|
356
|
+
transparencySource: result.transparencySource ?? null,
|
|
357
|
+
requestId: result.requestId ?? null,
|
|
358
|
+
attempts: result.attempts ?? null,
|
|
359
|
+
targetAssetPath: assetContext?.targetAssetPath ?? null,
|
|
360
|
+
outputFormat: opts.outputFormat ?? null,
|
|
361
|
+
fitMode: opts.fitMode ?? null,
|
|
362
|
+
paddingColor: opts.paddingColor ?? null,
|
|
317
363
|
aspectRatio: opts.aspectRatio,
|
|
318
364
|
imageSize: opts.imageSize ?? null,
|
|
319
365
|
requestedWidth: opts.width ?? stripTarget?.width ?? null,
|
|
@@ -331,9 +377,6 @@ export function registerGenerationCommands(tools) {
|
|
|
331
377
|
};
|
|
332
378
|
const sidecarPath = resolvedPath.replace(/\.[^.]+$/, '.json');
|
|
333
379
|
writeFileSync(sidecarPath, JSON.stringify(sidecar, null, 2));
|
|
334
|
-
await captureGeneratedArtifact(resolvedPath, 'generate-image', {
|
|
335
|
-
...(actualWidth ? { width: actualWidth } : {}), ...(actualHeight ? { height: actualHeight } : {}),
|
|
336
|
-
});
|
|
337
380
|
console.log(` └─ Generation metadata: ${sidecarPath}`);
|
|
338
381
|
}
|
|
339
382
|
if (!isBatch && opts.output !== savedPaths[0] && savedPaths[0]) {
|
|
@@ -381,7 +424,6 @@ export function registerGenerationCommands(tools) {
|
|
|
381
424
|
output: opts.output, generatedAt: new Date().toISOString(),
|
|
382
425
|
};
|
|
383
426
|
writeFileSync(opts.output.replace(/\.[^.]+$/, '.json'), JSON.stringify(sfxSidecar, null, 2));
|
|
384
|
-
await captureGeneratedArtifact(opts.output, 'generate-sfx', { duration: result.duration });
|
|
385
427
|
console.log(` └─ Generation metadata: ${opts.output.replace(/\.[^.]+$/, '.json')}`);
|
|
386
428
|
}
|
|
387
429
|
catch (e) {
|
|
@@ -414,7 +456,6 @@ export function registerGenerationCommands(tools) {
|
|
|
414
456
|
output: opts.output, generatedAt: new Date().toISOString(),
|
|
415
457
|
};
|
|
416
458
|
writeFileSync(opts.output.replace(/\.[^.]+$/, '.json'), JSON.stringify(bgmSidecar, null, 2));
|
|
417
|
-
await captureGeneratedArtifact(opts.output, 'generate-bgm', { duration: result.duration });
|
|
418
459
|
console.log(` └─ Generation metadata: ${opts.output.replace(/\.[^.]+$/, '.json')}`);
|
|
419
460
|
}
|
|
420
461
|
catch (e) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { readImageAssetContext } from '../utils/image-asset-context.js';
|
|
2
|
+
import { collectReferenceImagePaths, handleError } from './tools-utils.js';
|
|
3
|
+
export function registerImageContextCommand(tools) {
|
|
4
|
+
tools.command('image-context')
|
|
5
|
+
.description('Read image asset reference and delivery constraints locally; does not generate an image')
|
|
6
|
+
.requiredOption('--asset-path <path>', 'Existing image asset path relative to the project')
|
|
7
|
+
.option('--reference-image <path>', 'Explicit local reference; may be repeated', collectReferenceImagePaths, [])
|
|
8
|
+
.option('--no-target-reference', 'Do not use the target schema or current asset as a reference')
|
|
9
|
+
.option('--prompt <text>', 'Generation request used to resolve background intent')
|
|
10
|
+
.option('--remove-background', 'Explicitly request verified transparency')
|
|
11
|
+
.option('--no-remove-background', 'Explicitly keep an opaque background')
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
try {
|
|
14
|
+
console.log(JSON.stringify(await readImageAssetContext(opts.assetPath, process.cwd(), {
|
|
15
|
+
referenceImagePaths: opts.referenceImage, useTargetReference: opts.targetReference,
|
|
16
|
+
prompt: opts.prompt, removeBackground: opts.removeBackground,
|
|
17
|
+
})));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
handleError(error);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
package/dist/commands/tools.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { registerGenerationCommands } from './tools-generation.js';
|
|
2
|
-
import { registerBatchCommands } from './tools-batch.js';
|
|
3
2
|
import { registerProjectCommands } from './tools-project.js';
|
|
4
3
|
import { register3DCommands } from './tools-3d.js';
|
|
5
4
|
import { registerDetectCommand } from './tools-detect.js';
|
|
6
5
|
import { registerVideoReviewCommand } from './tools-video-review.js';
|
|
6
|
+
import { registerImageContextCommand } from './tools-image-context.js';
|
|
7
7
|
export function registerToolsCommands(program) {
|
|
8
8
|
const tools = program
|
|
9
9
|
.command('tools')
|
|
10
10
|
.description('后端 /api/agent/tools;运行 playcraft login 后即可直接使用,也支持 .playcraft.json 或 PLAYCRAFT_SANDBOX_TOKEN 环境变量');
|
|
11
11
|
registerGenerationCommands(tools);
|
|
12
|
+
registerImageContextCommand(tools);
|
|
12
13
|
registerProjectCommands(tools);
|
|
13
|
-
registerBatchCommands(tools);
|
|
14
14
|
register3DCommands(tools);
|
|
15
15
|
registerDetectCommand(tools);
|
|
16
16
|
registerVideoReviewCommand(tools);
|
package/dist/config.js
CHANGED
|
@@ -2,8 +2,7 @@ import { cosmiconfig } from 'cosmiconfig';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { homedir } from 'os';
|
|
5
|
-
import {
|
|
6
|
-
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
7
6
|
import 'dotenv/config';
|
|
8
7
|
export const ConfigSchema = z.object({
|
|
9
8
|
projectId: z.string().optional(),
|
|
@@ -19,33 +18,6 @@ const explorer = cosmiconfig('playcraft', {
|
|
|
19
18
|
});
|
|
20
19
|
const GLOBAL_CONFIG_DIR = path.join(homedir(), '.playcraft');
|
|
21
20
|
const GLOBAL_CONFIG_FILE = path.join(GLOBAL_CONFIG_DIR, 'config.json');
|
|
22
|
-
export function normalizeEnvironmentBaseUrl(raw) {
|
|
23
|
-
try {
|
|
24
|
-
const url = new URL(raw);
|
|
25
|
-
if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password)
|
|
26
|
-
return undefined;
|
|
27
|
-
url.hash = '';
|
|
28
|
-
url.search = '';
|
|
29
|
-
url.pathname = url.pathname.replace(/\/+$/, '').replace(/\/api$/, '');
|
|
30
|
-
return url.toString().replace(/\/+$/, '');
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export function readEnvironmentProfile(config, baseUrl) {
|
|
37
|
-
const key = normalizeEnvironmentBaseUrl(baseUrl);
|
|
38
|
-
const profiles = config.environmentProfiles;
|
|
39
|
-
if (!key || !profiles || typeof profiles !== 'object' || Array.isArray(profiles))
|
|
40
|
-
return undefined;
|
|
41
|
-
const profile = profiles[key];
|
|
42
|
-
if (!profile || typeof profile !== 'object' || Array.isArray(profile))
|
|
43
|
-
return undefined;
|
|
44
|
-
const value = profile;
|
|
45
|
-
if (typeof value.token !== 'string' || !value.token || normalizeEnvironmentBaseUrl(value.backendUrl) !== key)
|
|
46
|
-
return undefined;
|
|
47
|
-
return value;
|
|
48
|
-
}
|
|
49
21
|
export function loadGlobalConfig() {
|
|
50
22
|
try {
|
|
51
23
|
const content = readFileSync(GLOBAL_CONFIG_FILE, 'utf-8');
|
|
@@ -56,8 +28,7 @@ export function loadGlobalConfig() {
|
|
|
56
28
|
}
|
|
57
29
|
}
|
|
58
30
|
export function saveGlobalConfig(partial) {
|
|
59
|
-
mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true
|
|
60
|
-
chmodSync(GLOBAL_CONFIG_DIR, 0o700);
|
|
31
|
+
mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
|
|
61
32
|
let existing = {};
|
|
62
33
|
try {
|
|
63
34
|
existing = JSON.parse(readFileSync(GLOBAL_CONFIG_FILE, 'utf-8'));
|
|
@@ -66,25 +37,7 @@ export function saveGlobalConfig(partial) {
|
|
|
66
37
|
// ignore
|
|
67
38
|
}
|
|
68
39
|
const merged = { ...existing, ...partial };
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
writeFileSync(temporary, JSON.stringify(merged, null, 2), { encoding: 'utf-8', flag: 'wx', mode: 0o600 });
|
|
72
|
-
renameSync(temporary, GLOBAL_CONFIG_FILE);
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
rmSync(temporary, { force: true });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export function saveEnvironmentProfile(baseUrl, profile) {
|
|
79
|
-
const key = normalizeEnvironmentBaseUrl(baseUrl);
|
|
80
|
-
if (!key)
|
|
81
|
-
throw new Error('Invalid environment address');
|
|
82
|
-
const current = loadGlobalConfig();
|
|
83
|
-
const profiles = current.environmentProfiles && typeof current.environmentProfiles === 'object'
|
|
84
|
-
&& !Array.isArray(current.environmentProfiles) ? current.environmentProfiles : {};
|
|
85
|
-
saveGlobalConfig({ environmentProfiles: { ...profiles,
|
|
86
|
-
[key]: { ...profile, backendUrl: key, updatedAt: new Date().toISOString() } },
|
|
87
|
-
token: profile.token, url: key, backendUrl: key });
|
|
40
|
+
writeFileSync(GLOBAL_CONFIG_FILE, JSON.stringify(merged, null, 2), 'utf-8');
|
|
88
41
|
}
|
|
89
42
|
export async function loadConfig(cliOptions) {
|
|
90
43
|
const result = await explorer.search(cliOptions.dir || process.cwd());
|
|
@@ -93,20 +46,12 @@ export async function loadConfig(cliOptions) {
|
|
|
93
46
|
? (fileConfig.agent || {})
|
|
94
47
|
: fileConfig;
|
|
95
48
|
const globalConfig = loadGlobalConfig();
|
|
96
|
-
const explicitTarget = cliOptions.url || process.env.PLAYCRAFT_URL || agentConfig.url;
|
|
97
|
-
const targetUrl = explicitTarget || globalConfig.url;
|
|
98
|
-
const profile = typeof targetUrl === 'string' ? readEnvironmentProfile(globalConfig, targetUrl) : undefined;
|
|
99
|
-
const legacyTarget = typeof globalConfig.backendUrl === 'string' ? globalConfig.backendUrl
|
|
100
|
-
: typeof globalConfig.url === 'string' ? globalConfig.url : undefined;
|
|
101
|
-
const legacyToken = !explicitTarget || (legacyTarget && normalizeEnvironmentBaseUrl(String(targetUrl)) === normalizeEnvironmentBaseUrl(legacyTarget))
|
|
102
|
-
? globalConfig.token : undefined;
|
|
103
49
|
const config = ConfigSchema.parse({
|
|
104
50
|
...globalConfig,
|
|
105
51
|
...agentConfig,
|
|
106
52
|
...cliOptions,
|
|
107
53
|
projectId: cliOptions.projectId || process.env.PLAYCRAFT_PROJECT_ID || agentConfig.projectId || globalConfig.projectId,
|
|
108
|
-
|
|
109
|
-
token: cliOptions.token || process.env.PLAYCRAFT_TOKEN || agentConfig.token || profile?.token || legacyToken,
|
|
54
|
+
token: cliOptions.token || process.env.PLAYCRAFT_TOKEN || agentConfig.token || globalConfig.token,
|
|
110
55
|
port: cliOptions.port || (process.env.PLAYCRAFT_PORT ? parseInt(process.env.PLAYCRAFT_PORT) : undefined) || agentConfig.port || globalConfig.port,
|
|
111
56
|
mode: cliOptions.mode || process.env.PLAYCRAFT_MODE || agentConfig.mode || globalConfig.mode,
|
|
112
57
|
skillsDir: cliOptions.skillsDir || process.env.AGENT_SKILLS_DIR || agentConfig.skillsDir || globalConfig.skillsDir,
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command
|
|
3
|
-
import { accountActivationMessage } from './auth/messages.js';
|
|
2
|
+
import { Command } from 'commander';
|
|
4
3
|
import { readFileSync } from 'fs';
|
|
5
4
|
import { fileURLToPath } from 'url';
|
|
6
5
|
import { dirname, join } from 'path';
|
|
@@ -28,23 +27,16 @@ import { registerLevelsCommands } from './commands/levels.js';
|
|
|
28
27
|
import { registerPatternsCommands } from './commands/patterns.js';
|
|
29
28
|
import { registerPradCommands } from './commands/prad.js';
|
|
30
29
|
import { register3DCommands } from './commands/3d.js';
|
|
31
|
-
import { registerWorkspaceRuntimeCommands } from './commands/workspace-runtime.js';
|
|
32
|
-
import { registerVideoCommands } from './commands/video.js';
|
|
33
|
-
import { registerPlayableCommands } from './commands/playable.js';
|
|
34
|
-
import { videoMessage } from './video-replication/messages.js';
|
|
35
30
|
import { CLI_ROOT_DESCRIPTION, getCliTopicsHelpText, registerRootProgramHelp, } from './cli-root-help.js';
|
|
36
31
|
const __filename = fileURLToPath(import.meta.url);
|
|
37
32
|
const __dirname = dirname(__filename);
|
|
38
33
|
const packageJson = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
39
34
|
const program = new Command();
|
|
40
|
-
const structuredVideoTopic = ['video', 'playable'].includes(process.argv[2] ?? '');
|
|
41
|
-
if (structuredVideoTopic)
|
|
42
|
-
program.exitOverride();
|
|
43
35
|
program.name('playcraft').description(CLI_ROOT_DESCRIPTION).version(packageJson.version);
|
|
44
36
|
registerRootProgramHelp(program);
|
|
45
37
|
// 版本检查(非阻塞,后台执行)
|
|
46
38
|
// 只在非 upgrade 命令时检查,避免重复提示
|
|
47
|
-
if (!
|
|
39
|
+
if (!process.argv.includes('upgrade')) {
|
|
48
40
|
checkForUpdates(packageJson);
|
|
49
41
|
}
|
|
50
42
|
// create 命令
|
|
@@ -73,8 +65,6 @@ program
|
|
|
73
65
|
.command('login')
|
|
74
66
|
.description('登录 PlayCraft 账号并获取 CLI token')
|
|
75
67
|
.option('--url <url>', 'Portal / API 基址(默认 https://playcraft.aix.intlgame.com,可用环境变量 PLAYCRAFT_URL 覆盖)')
|
|
76
|
-
.option('--activate', accountActivationMessage('activateOption'))
|
|
77
|
-
.option('--token <token>', accountActivationMessage('tokenOption'))
|
|
78
68
|
.action(async (options) => {
|
|
79
69
|
const { loginCommand } = await import('./commands/login.js');
|
|
80
70
|
await loginCommand(options);
|
|
@@ -378,25 +368,4 @@ registerPatternsCommands(program);
|
|
|
378
368
|
registerPradCommands(program);
|
|
379
369
|
// 3D model utilities (playcraft 3d <command>)
|
|
380
370
|
register3DCommands(program);
|
|
381
|
-
|
|
382
|
-
registerVideoCommands(program);
|
|
383
|
-
registerPlayableCommands(program);
|
|
384
|
-
if (structuredVideoTopic) {
|
|
385
|
-
try {
|
|
386
|
-
await program.parseAsync(process.argv);
|
|
387
|
-
}
|
|
388
|
-
catch (error) {
|
|
389
|
-
if (!(error instanceof CommanderError))
|
|
390
|
-
throw error;
|
|
391
|
-
if (error.exitCode === 0)
|
|
392
|
-
process.exitCode = 0;
|
|
393
|
-
else {
|
|
394
|
-
const command = [process.argv[2], process.argv[3]?.startsWith('-') ? undefined : process.argv[3]].filter(Boolean).join(' ');
|
|
395
|
-
process.stdout.write(`${JSON.stringify({ schemaVersion: 'playcraft.video-cli.v1', command, state: 'failed', ok: false,
|
|
396
|
-
error: { code: 'invalidArguments', message: videoMessage('invalidArguments') } })}\n`);
|
|
397
|
-
process.exitCode = 64;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
else
|
|
402
|
-
program.parse(process.argv);
|
|
371
|
+
program.parse(process.argv);
|
package/dist/remix/clone.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { prepareLocalSkillLifecycle } from '../project-skills/lifecycle.js';
|
|
2
1
|
import { spawnSync } from 'node:child_process';
|
|
3
2
|
import { mkdirSync, writeFileSync, readFileSync, existsSync } from 'node:fs';
|
|
4
3
|
import path from 'node:path';
|
|
@@ -152,7 +151,6 @@ export async function remixClone(options) {
|
|
|
152
151
|
};
|
|
153
152
|
writePlaycraftMeta(targetDir, meta);
|
|
154
153
|
configureRepoCredentialHelper(targetDir);
|
|
155
|
-
await prepareLocalSkillLifecycle(targetDir, 'checkout');
|
|
156
154
|
let projectType;
|
|
157
155
|
try {
|
|
158
156
|
const project = await client.get(`/projects/${encodeURIComponent(projectId)}`);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { prepareLocalSkillLifecycle } from '../project-skills/lifecycle.js';
|
|
2
1
|
import * as path from 'node:path';
|
|
3
2
|
import { applyEnginePackToProject, bakeFullTemplate, KNOWN_ADAPTERS, readAdapterFromAtomTree, readEngineMarker, resolveCliPackageRoot, } from '../scaffold/compose.js';
|
|
4
3
|
import { autoLinkSkillsFromAtomTree } from '../commands/skills.js';
|
|
@@ -69,7 +68,6 @@ export async function initTemplateCommand(opts) {
|
|
|
69
68
|
console.log(` ⚠ auto-link skipped: ${err.message}`);
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
|
-
await prepareLocalSkillLifecycle(projectDir, 'create');
|
|
73
71
|
console.log('\n下一步:');
|
|
74
72
|
console.log(' npm install');
|
|
75
73
|
console.log(' 阅读 .claude/skills/<atom>/SKILL.md(已自动 link)并填 logs/developer-log.md § Skill Preflight');
|
package/dist/remix/pull.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { prepareLocalSkillLifecycle } from '../project-skills/lifecycle.js';
|
|
2
1
|
import { spawnSync } from 'node:child_process';
|
|
3
2
|
import { existsSync } from 'node:fs';
|
|
4
3
|
import path from 'node:path';
|
|
@@ -45,7 +44,6 @@ export async function remixPull(options = {}) {
|
|
|
45
44
|
const detail = [result.stderr, result.stdout].filter(Boolean).join('\n').trim();
|
|
46
45
|
throw new Error(detail || `git pull 失败(exit ${result.status})`);
|
|
47
46
|
}
|
|
48
|
-
await prepareLocalSkillLifecycle(repoDir, 'checkout');
|
|
49
47
|
if (options.json) {
|
|
50
48
|
console.log(JSON.stringify({
|
|
51
49
|
schemaVersion: '1.0',
|
package/dist/remix/push.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { prepareLocalSkillLifecycle } from '../project-skills/lifecycle.js';
|
|
2
|
-
import { reconcileLocalProjectSkills } from '../project-skills/reconcile.js';
|
|
3
|
-
import { projectSkillsMessage as skillMessage } from '../project-skills/messages.js';
|
|
4
1
|
import { spawnSync } from 'node:child_process';
|
|
5
2
|
import { existsSync } from 'node:fs';
|
|
6
3
|
import path from 'node:path';
|
|
@@ -44,7 +41,6 @@ export async function remixPush(options = {}) {
|
|
|
44
41
|
process.stderr.write(`[push] ${meta.cloneUrl}\n`);
|
|
45
42
|
process.stderr.write(`[push] branch=${meta.branch} dir=${repoDir}\n`);
|
|
46
43
|
}
|
|
47
|
-
const skills = await prepareLocalSkillLifecycle(repoDir, 'push');
|
|
48
44
|
const result = runAuthenticatedGit(['push', ...effectiveArgs], {
|
|
49
45
|
cwd: repoDir,
|
|
50
46
|
token: client.token,
|
|
@@ -54,24 +50,10 @@ export async function remixPush(options = {}) {
|
|
|
54
50
|
const detail = [result.stderr, result.stdout].filter(Boolean).join('\n').trim();
|
|
55
51
|
throw new Error(detail || `git push 失败(exit ${result.status})`);
|
|
56
52
|
}
|
|
57
|
-
let skillIndex;
|
|
58
|
-
let skillIndexFailed = false;
|
|
59
|
-
if (skills.managed) {
|
|
60
|
-
try {
|
|
61
|
-
skillIndex = await reconcileLocalProjectSkills(repoDir, { url: options.url, token: options.token });
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
skillIndexFailed = true;
|
|
65
|
-
skillIndex = { indexed: false, message: skillMessage('pushIndexFailed'), detail: error instanceof Error ? error.message : String(error) };
|
|
66
|
-
process.exitCode = 1;
|
|
67
|
-
}
|
|
68
|
-
if (!options.json)
|
|
69
|
-
process.stderr.write(`${JSON.stringify(skillIndex)}\n`);
|
|
70
|
-
}
|
|
71
53
|
if (options.json) {
|
|
72
54
|
console.log(JSON.stringify({
|
|
73
55
|
schemaVersion: '1.0',
|
|
74
|
-
ok:
|
|
56
|
+
ok: true,
|
|
75
57
|
command: 'remix.push',
|
|
76
58
|
requestId: client.requestId,
|
|
77
59
|
data: {
|
|
@@ -80,8 +62,6 @@ export async function remixPush(options = {}) {
|
|
|
80
62
|
cloneUrl: meta.cloneUrl,
|
|
81
63
|
dir: repoDir,
|
|
82
64
|
gitArgs: effectiveArgs,
|
|
83
|
-
gitPushed: true,
|
|
84
|
-
skills: skillIndex,
|
|
85
65
|
},
|
|
86
66
|
}));
|
|
87
67
|
return;
|