@playcraft/cli 0.1.23 → 0.1.24
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 -1
- 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-generation.js +4 -2
- package/dist/commands/tools.js +0 -2
- package/dist/config.js +4 -59
- package/dist/index.js +1 -6
- 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 +29 -148
- package/dist/utils/playcraft-http-client.js +4 -6
- package/package.json +2 -8
- package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +61 -23
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +61 -23
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +61 -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/tools-batch.js +0 -59
- package/dist/commands/workspace-runtime.js +0 -54
- package/dist/project-skills/commands.js +0 -72
- 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 -149
- package/dist/project-skills/messages.js +0 -72
- 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/utils/environment-endpoints.js +0 -17
- package/dist/utils/tool-operation-journal.js +0 -124
- package/dist/workspace-runtime/codex/app-server.js +0 -574
- package/dist/workspace-runtime/codex/config-toml.js +0 -108
- 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 -239
- 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/sqlite-client.js +0 -61
- package/dist/workspace-runtime/persistence/sqlite-worker.js +0 -1015
- 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 -70
- package/dist/workspace-runtime/production/processes.js +0 -86
- package/dist/workspace-runtime/production/save-command.js +0 -20
- package/dist/workspace-runtime/production/stages.js +0 -175
- package/dist/workspace-runtime/production/storage.js +0 -32
- package/dist/workspace-runtime/serve.js +0 -199
- 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 -848
- 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 -919
- 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/attachments.js +0 -109
- package/dist/workspace-runtime/workspaces/batch-commit.js +0 -142
- 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 -106
- package/dist/workspace-runtime/workspaces/directory-access.js +0 -20
- 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/empty-template.js +0 -32
- package/dist/workspace-runtime/workspaces/files.js +0 -113
- 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 -471
- 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 -263
- package/dist/workspace-runtime/workspaces/registry.js +0 -192
- package/dist/workspace-runtime/workspaces/revisions.js +0 -31
- package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +0 -46
- package/dist/workspace-runtime/workspaces/skills.js +0 -179
- 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 -23
- package/project-templates/empty/gitignore +0 -31
package/README.md
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
PlayCraft CLI(Command-Line Interface,命令行工具)支持本地代码与云端编辑器实时同步,以及将 PlayCanvas/PlayCraft 项目打包为多平台 Playable Ads。
|
|
9
9
|
|
|
10
|
-
## 云端工作台 Runtime
|
|
10
|
+
## 云端工作台 Runtime(计划能力)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
云端工作台计划以 `@playcraft/cli` 承载自定义 AGS(Agent Sandbox,Agent 沙箱服务)内的常驻运行服务,新增 `playcraft workspace-runtime serve` 命令,管理多个 Workspace、一个 Codex App Server、文件/Git/终端/预览及持久恢复。该命令尚未实现,当前发布版本不可调用;现有 `playcraft start` 仍用于单项目本地开发。
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
新服务采用固定版本、前台非交互运行,由镜像监管器启动;独立 Runtime Server 在沙箱外部署。具体代码归属、进程权限、发布与恢复契约见 [云端工作台后端架构方案](../../docs/architecture/backend/cloud-workspace/backend-architecture.md#cli-runtime)。
|
|
15
15
|
|
|
16
16
|
## ✨ 特性
|
|
17
17
|
|
|
@@ -141,17 +141,6 @@ playcraft login --url https://your-playcraft.example.com
|
|
|
141
141
|
|
|
142
142
|
登录成功后,`tools`、`recommend`、`fix-ids` 等所有需要后端 API 的命令均无需额外配置,直接使用。
|
|
143
143
|
|
|
144
|
-
账号提示待激活时,使用同一目标环境及已保存的个人访问令牌主动激活:
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
playcraft login --activate
|
|
148
|
-
playcraft login --activate --url https://your-playcraft.example.com
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
也可通过 `PLAYCRAFT_TOKEN` 提供个人访问令牌。激活只发送一次请求,成功后重新执行原业务命令;该动作不会打开浏览器或续签令牌。目标服务须已接入身份服务的激活入口;封禁、停用账号及沙箱执行令牌不能用于激活。
|
|
152
|
-
|
|
153
|
-
若本地、全局或环境变量配置冲突,激活会要求明确指定 `--url`、所需的 `PLAYCRAFT_ENV` 和对应的个人访问令牌。
|
|
154
|
-
|
|
155
144
|
### 沙箱环境(CI / Agent)
|
|
156
145
|
|
|
157
146
|
在沙箱或 CI 中可通过 `.playcraft.json` 或环境变量配置:
|
|
@@ -199,30 +188,6 @@ echo '{"token":"<sandbox-jwt>","apiUrl":"https://..."}' > .playcraft.json
|
|
|
199
188
|
| `recommend improvements` | Tag 改进建议 | `playcraft recommend improvements --channel Facebook` |
|
|
200
189
|
| `recommend random` | 随机 Tag 组合推荐 | `playcraft recommend random --channel Google` |
|
|
201
190
|
|
|
202
|
-
### 业务工具请求恢复
|
|
203
|
-
|
|
204
|
-
业务工具写请求要求服务支持持久操作协议。命令行先保存请求编号、路径和输入摘要到 `~/.playcraft/tool-requests/`,再发送请求;记录不包含凭证或请求正文。可用绝对路径环境变量 `PLAYCRAFT_TOOL_REQUEST_DIR` 指定可持久保留的目录。
|
|
205
|
-
|
|
206
|
-
原样重跑同一条命令(路径与参数都相同)时,命令行按上一次的结果决定是否沿用原请求编号:
|
|
207
|
-
|
|
208
|
-
| 上一次的结果 | 原样重跑时 |
|
|
209
|
-
| -------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
210
|
-
| 成功(2xx) | 新操作 |
|
|
211
|
-
| 请求被拒绝(4xx,下列 409 除外):请求没有被执行 | 新操作 |
|
|
212
|
-
| 服务端错误(5xx)、超时或连接中断:结果未知 | 沿用原编号,不会另起一次操作;服务端按下文的恢复方式处理 |
|
|
213
|
-
| 409 `business_operation_in_progress`:原操作仍在执行 | 沿用原编号,稍后重跑取得结果 |
|
|
214
|
-
| 409 `business_operation_requires_reconciliation`:结果未知,需要核对 | 沿用原编号,不会再执行 |
|
|
215
|
-
|
|
216
|
-
沿用原编号时,服务端按原操作的状态处理:已完成则返回原结果;仍在执行则返回 409 `business_operation_in_progress`;没有拿到结果就结束时,按该工具声明的恢复方式决定,可以安全重做的工具(生图、构建、发布到 COS 等)用原编号再执行一次,其余返回 409 `business_operation_requires_reconciliation`。原调用的执行租约有效期间(执行中每 20 秒续期,60 秒未续即过期),同一编号不会被再次执行;续期因服务或数据库故障中断超过 60 秒时,重做可能与仍在运行的原调用重叠。
|
|
217
|
-
|
|
218
|
-
需要核对的操作,只有确认它没有生效后,才可设置 `PLAYCRAFT_TOOL_NEW_REQUEST=1` 强制发起新操作;不要删除记录来绕过。也可以显式指定编号,只查询原操作的确定结果(不会重新执行;声明了恢复方式的工具若上次报错,返回那次的错误)。只查询时即使是可以安全重做的工具,没有结果也返回需要核对;去掉 `PLAYCRAFT_TOOL_REQUEST_ID` 原样重跑即可续做:
|
|
219
|
-
|
|
220
|
-
```bash
|
|
221
|
-
PLAYCRAFT_TOOL_REQUEST_ID=<错误中显示的请求编号> playcraft tools build-project --project-id <原项目编号>
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
能力检查失败时命令会明确说明尚未发送操作。服务不兼容时命令会在发送业务请求前停止;沙箱命令行与 Business 须排空旧调用后同步升级。
|
|
225
|
-
|
|
226
191
|
### 构建相关
|
|
227
192
|
|
|
228
193
|
| 命令 | 说明 | 示例 |
|
|
@@ -2,7 +2,7 @@ import express from 'express';
|
|
|
2
2
|
import crypto from 'node:crypto';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import fs from 'node:fs/promises';
|
|
5
|
-
import { eq, inArray } from '
|
|
5
|
+
import { eq, inArray } from 'drizzle-orm';
|
|
6
6
|
import pc from 'picocolors';
|
|
7
7
|
import { createSqliteAdapter } from '@playcraft/common/database';
|
|
8
8
|
import { AssetModel, ProjectModel, SceneModel } from '@playcraft/common/models';
|
package/dist/cli-root-help.js
CHANGED
|
@@ -7,7 +7,6 @@ export function getCliTopicsHelpText() {
|
|
|
7
7
|
' 素材 tools generate-* | image <子命令> | audio <子命令> | prefab <子命令>',
|
|
8
8
|
' 平台 build, build-base, build-playable, build-all, analyze, inspect, upgrade',
|
|
9
9
|
' tools 除 generate-* 外(Git / 沙箱构建 / 发布 / 列表 / Prefab 等,需后端 API)',
|
|
10
|
-
' 沙箱常驻 workspace-runtime serve(Cloud Workspace,由 Runtime 引导配置启动)',
|
|
11
10
|
'',
|
|
12
11
|
'也可运行: playcraft topics',
|
|
13
12
|
'',
|
package/dist/commands/build.js
CHANGED
|
@@ -450,7 +450,6 @@ export async function buildCommand(projectPath, options) {
|
|
|
450
450
|
const shouldRunPlayableOnly = options.mode === 'playable';
|
|
451
451
|
// 验证平台
|
|
452
452
|
const validPlatforms = [
|
|
453
|
-
'playcraft',
|
|
454
453
|
'facebook',
|
|
455
454
|
'snapchat',
|
|
456
455
|
'ironsource',
|
|
@@ -474,7 +473,6 @@ export async function buildCommand(projectPath, options) {
|
|
|
474
473
|
// 注:Facebook 在 Phaser(playable-scripts devkit)下的产物格式由其 devkit 输入配置决定(恒为 ZIP),
|
|
475
474
|
// 平台侧不在此处做引擎判断。
|
|
476
475
|
const platformFormatConfig = {
|
|
477
|
-
playcraft: { formats: ['html'], default: 'html' },
|
|
478
476
|
facebook: { formats: ['html', 'zip'], default: 'html' },
|
|
479
477
|
applovin: { formats: ['html'], default: 'html' },
|
|
480
478
|
ironsource: { formats: ['html'], default: 'html' },
|
|
@@ -586,11 +584,8 @@ export async function buildCommand(projectPath, options) {
|
|
|
586
584
|
console.log(pc.dim(' 无主题目录,跳过主题选择'));
|
|
587
585
|
}
|
|
588
586
|
}
|
|
589
|
-
// 输入商店跳转地址(CTA)-
|
|
590
|
-
if (
|
|
591
|
-
console.log(pc.dim('\nℹ️ 通用预览不需要商店地址'));
|
|
592
|
-
}
|
|
593
|
-
else if (!options.storeUrls) {
|
|
587
|
+
// 输入商店跳转地址(CTA)- 如果配置文件中没有则必填
|
|
588
|
+
if (!options.storeUrls) {
|
|
594
589
|
console.log(pc.cyan('\n🔗 商店跳转地址(CTA 按钮目标)'));
|
|
595
590
|
console.log(pc.dim(' iOS 和 Android 地址均为必填'));
|
|
596
591
|
const storeUrlAnswer = await inquirer.prompt([
|
|
@@ -641,8 +636,8 @@ export async function buildCommand(projectPath, options) {
|
|
|
641
636
|
// 未指定格式,使用默认值
|
|
642
637
|
options.format = formatConfig.default;
|
|
643
638
|
}
|
|
644
|
-
// 如果命令行未传入 storeUrls
|
|
645
|
-
if (!options.storeUrls
|
|
639
|
+
// 如果命令行未传入 storeUrls,交互式输入(必填)
|
|
640
|
+
if (!options.storeUrls) {
|
|
646
641
|
spinner.stop();
|
|
647
642
|
console.log(pc.cyan('\n🔗 商店跳转地址(CTA 按钮目标)'));
|
|
648
643
|
console.log(pc.dim(' iOS 和 Android 地址均为必填'));
|
package/dist/commands/create.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { prepareLocalSkillLifecycle } from '../project-skills/lifecycle.js';
|
|
2
1
|
import { execFileSync, execSync } from 'child_process';
|
|
3
2
|
import inquirer from 'inquirer';
|
|
4
3
|
import fs from 'fs/promises';
|
|
@@ -7,11 +6,8 @@ import { fileURLToPath } from 'url';
|
|
|
7
6
|
import pc from 'picocolors';
|
|
8
7
|
import ora from 'ora';
|
|
9
8
|
import { resolveCreateTemplate, resolveCreateTemplateDir, } from '../scaffold/templates.js';
|
|
10
|
-
import { PLATFORM_SKILL_DIRS } from './platform-skills.generated.js';
|
|
11
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
10
|
const __dirname = path.dirname(__filename);
|
|
13
|
-
/** `@playcraft/skills` 包内 Platform Skill 的目录名(与 Atom Skill 的 `skills/` 区分)。 */
|
|
14
|
-
const PLATFORM_SKILLS_DIRNAME = 'playcraft-skills';
|
|
15
11
|
/** 生成一个本地占位 Project ID(99xxxxxx),后续可通过 playcraft config set 更新为真实 ID */
|
|
16
12
|
function generateMockProjectId() {
|
|
17
13
|
const suffix = Math.floor(Math.random() * 90_000_000) + 10_000_000;
|
|
@@ -853,7 +849,7 @@ function extractSkillBodyForCursor(content) {
|
|
|
853
849
|
* @param cliCommandsDir CLI 命令所在目录(用于解析 skills 包位置)
|
|
854
850
|
* @param configDir 配置目录名(如 '.claude' 或 '.codebuddy')
|
|
855
851
|
*/
|
|
856
|
-
|
|
852
|
+
async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, configDir) {
|
|
857
853
|
const skillsLinkDir = path.join(targetDir, configDir, 'skills');
|
|
858
854
|
await fs.mkdir(skillsLinkDir, { recursive: true });
|
|
859
855
|
// 以下 Skill 在项目模板中以静态目录形式存在,不创建软连接覆盖它们。
|
|
@@ -872,12 +868,11 @@ export async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, co
|
|
|
872
868
|
'playcraft-image-generation',
|
|
873
869
|
'playcraft-audio-generation',
|
|
874
870
|
]);
|
|
875
|
-
//
|
|
876
|
-
// 尝试从 CLI 安装包的位置定位它(monorepo 内或与 CLI 平级安装时可解析)。
|
|
871
|
+
// 尝试从 CLI 安装包的位置定位 @playcraft/skills/skills 目录
|
|
877
872
|
const candidateDirs = [
|
|
878
|
-
path.resolve(cliCommandsDir, '..', '..', '..', '..', 'skills',
|
|
879
|
-
path.resolve(cliCommandsDir, '..', '..', '..', 'skills',
|
|
880
|
-
path.resolve(cliCommandsDir, '..', '..', 'skills',
|
|
873
|
+
path.resolve(cliCommandsDir, '..', '..', '..', '..', 'skills', 'skills'),
|
|
874
|
+
path.resolve(cliCommandsDir, '..', '..', '..', 'skills', 'skills'),
|
|
875
|
+
path.resolve(cliCommandsDir, '..', '..', 'skills', 'skills'),
|
|
881
876
|
];
|
|
882
877
|
let resolvedSkillsDir = null;
|
|
883
878
|
for (const dir of candidateDirs) {
|
|
@@ -890,24 +885,18 @@ export async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, co
|
|
|
890
885
|
// 继续下一个候选
|
|
891
886
|
}
|
|
892
887
|
}
|
|
893
|
-
// 相对路径(指向 npm install 后的 node_modules
|
|
894
|
-
const relativeSkillsBase = path.join('..', '..', 'node_modules', '@playcraft', 'skills',
|
|
888
|
+
// 相对路径(指向 npm install 后的 node_modules)始终创建,作为安装后激活的备用
|
|
889
|
+
const relativeSkillsBase = path.join('..', '..', 'node_modules', '@playcraft', 'skills', 'skills');
|
|
895
890
|
if (resolvedSkillsDir) {
|
|
896
|
-
// 能立即解析 →
|
|
897
|
-
// 按「是否含 SKILL.md」判定而非 playcraft- 前缀:sound-effects 无前缀但同样是平台技能。
|
|
891
|
+
// 能立即解析 → 创建指向绝对路径的软连接,当下即可使用
|
|
898
892
|
const entries = await fs.readdir(resolvedSkillsDir, { withFileTypes: true });
|
|
899
893
|
for (const entry of entries) {
|
|
900
|
-
if (!entry.
|
|
894
|
+
if (!entry.name.startsWith('playcraft-') || staticSkills.has(entry.name))
|
|
901
895
|
continue;
|
|
896
|
+
const linkPath = path.join(skillsLinkDir, entry.name);
|
|
902
897
|
const targetPath = path.join(resolvedSkillsDir, entry.name);
|
|
903
898
|
try {
|
|
904
|
-
await fs.
|
|
905
|
-
}
|
|
906
|
-
catch {
|
|
907
|
-
continue;
|
|
908
|
-
}
|
|
909
|
-
try {
|
|
910
|
-
await fs.symlink(targetPath, path.join(skillsLinkDir, entry.name), 'dir');
|
|
899
|
+
await fs.symlink(targetPath, linkPath, 'dir');
|
|
911
900
|
}
|
|
912
901
|
catch {
|
|
913
902
|
// 已存在则跳过
|
|
@@ -915,9 +904,28 @@ export async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, co
|
|
|
915
904
|
}
|
|
916
905
|
}
|
|
917
906
|
else {
|
|
918
|
-
// 无法立即解析 →
|
|
919
|
-
|
|
920
|
-
|
|
907
|
+
// 无法立即解析 → 创建指向 node_modules 的相对路径软连接,npm install 后自动激活
|
|
908
|
+
const knownPlatformTools = [
|
|
909
|
+
'playcraft-asset-management',
|
|
910
|
+
'playcraft-audio-generation',
|
|
911
|
+
'playcraft-build',
|
|
912
|
+
'playcraft-code-editor',
|
|
913
|
+
'playcraft-create-remix',
|
|
914
|
+
'playcraft-deploy',
|
|
915
|
+
'playcraft-image-generation',
|
|
916
|
+
'playcraft-image-processing',
|
|
917
|
+
'playcraft-platform-intro',
|
|
918
|
+
'playcraft-prefab',
|
|
919
|
+
'playcraft-project-management',
|
|
920
|
+
'playcraft-remix-workflow',
|
|
921
|
+
'playcraft-save',
|
|
922
|
+
'playcraft-skill-recommender',
|
|
923
|
+
'playcraft-sprite-generation',
|
|
924
|
+
'playcraft-sprite-remix',
|
|
925
|
+
'playcraft-sprite-sheet',
|
|
926
|
+
'playcraft-3d-flip-sprite',
|
|
927
|
+
];
|
|
928
|
+
for (const name of knownPlatformTools) {
|
|
921
929
|
if (staticSkills.has(name))
|
|
922
930
|
continue;
|
|
923
931
|
const linkPath = path.join(skillsLinkDir, name);
|
|
@@ -1281,7 +1289,6 @@ export async function createCommand(projectName, options) {
|
|
|
1281
1289
|
smokeSpinner.warn(`Harness 自检跳过: ${message}`);
|
|
1282
1290
|
}
|
|
1283
1291
|
}
|
|
1284
|
-
await prepareLocalSkillLifecycle(targetDir, 'create');
|
|
1285
1292
|
const gitSpinner = ora(isWorktreeMode ? '提交项目分支...' : '初始化 Git 仓库...').start();
|
|
1286
1293
|
try {
|
|
1287
1294
|
if (isWorktreeMode) {
|
package/dist/commands/image.js
CHANGED
|
@@ -677,7 +677,9 @@ async function runBatchStep(cmd, args, inputPath, outputPath) {
|
|
|
677
677
|
const meta = await sharp(inputPath).metadata();
|
|
678
678
|
const targetW = scale ? Math.round((meta.width ?? 64) * scale) : w;
|
|
679
679
|
const targetH = scale ? Math.round((meta.height ?? 64) * scale) : h;
|
|
680
|
-
await safeToFile(sharp(inputPath).resize(targetW, targetH, {
|
|
680
|
+
await safeToFile(sharp(inputPath).resize(targetW, targetH, {
|
|
681
|
+
fit, background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
682
|
+
}), outputPath, inputPath);
|
|
681
683
|
break;
|
|
682
684
|
}
|
|
683
685
|
case 'crop': {
|
|
@@ -836,7 +838,9 @@ export function registerImageCommands(program) {
|
|
|
836
838
|
process.exit(1);
|
|
837
839
|
}
|
|
838
840
|
const fit = parseResizeFitOption(opts.fit);
|
|
839
|
-
await safeToFile(sharp(opts.input).resize(targetW, targetH, {
|
|
841
|
+
await safeToFile(sharp(opts.input).resize(targetW, targetH, {
|
|
842
|
+
fit, background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
843
|
+
}), opts.output, opts.input);
|
|
840
844
|
const outSz = statSync(resolveSandboxPath(opts.output)).size;
|
|
841
845
|
console.log(`Resized ${w}x${h} → ${targetW ?? '?'}x${targetH ?? '?'} — ${opts.output} (${sizeLabelBytes(outSz)})`);
|
|
842
846
|
}
|
package/dist/commands/login.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
|
-
import {
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
3
|
import crypto from 'crypto';
|
|
4
|
-
import {
|
|
5
|
-
import { activateAccount } from '../auth/account-activation.js';
|
|
4
|
+
import { saveGlobalConfig, loadGlobalConfig } from '../config.js';
|
|
6
5
|
/** 默认云端 Portal(Next.js `/cli-auth` 与 API 同源时的基址;可通过 --url 或 PLAYCRAFT_URL 覆盖) */
|
|
7
6
|
export const DEFAULT_PLAYCRAFT_CLOUD_BASE = 'https://playcraft.aix.intlgame.com';
|
|
8
7
|
const CALLBACK_PORT = 3456;
|
|
@@ -19,11 +18,10 @@ function openBrowser(url) {
|
|
|
19
18
|
const cmd = process.platform === 'darwin'
|
|
20
19
|
? 'open'
|
|
21
20
|
: process.platform === 'win32'
|
|
22
|
-
? '
|
|
21
|
+
? 'start'
|
|
23
22
|
: 'xdg-open';
|
|
24
23
|
try {
|
|
25
|
-
|
|
26
|
-
execFile(cmd, arguments_, (err, _stdout, stderr) => {
|
|
24
|
+
exec(`${cmd} "${url}"`, (err, _stdout, stderr) => {
|
|
27
25
|
if (err) {
|
|
28
26
|
console.error('Failed to open browser automatically:', err.message);
|
|
29
27
|
if (stderr?.trim()) {
|
|
@@ -46,18 +44,21 @@ function resolveLoginBaseUrl(options) {
|
|
|
46
44
|
globalConfig.url ||
|
|
47
45
|
globalConfig.backendUrl ||
|
|
48
46
|
DEFAULT_PLAYCRAFT_CLOUD_BASE;
|
|
49
|
-
|
|
50
|
-
if (!base)
|
|
51
|
-
throw new Error('Invalid environment address');
|
|
52
|
-
return base;
|
|
47
|
+
return raw.replace(/\/+$/, '');
|
|
53
48
|
}
|
|
54
49
|
function normalizeLoginEnvironmentUrl(raw) {
|
|
55
|
-
|
|
50
|
+
try {
|
|
51
|
+
const url = new URL(raw);
|
|
52
|
+
url.hash = '';
|
|
53
|
+
url.search = '';
|
|
54
|
+
url.pathname = url.pathname.replace(/\/+$/, '');
|
|
55
|
+
return url.toString().replace(/\/+$/, '');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
56
60
|
}
|
|
57
61
|
export function resolveExistingTokenForLoginTarget(globalConfig, backendUrl) {
|
|
58
|
-
const profile = readEnvironmentProfile(globalConfig, backendUrl);
|
|
59
|
-
if (profile)
|
|
60
|
-
return profile.token;
|
|
61
62
|
const token = typeof globalConfig.token === 'string' ? globalConfig.token : undefined;
|
|
62
63
|
const storedBackendUrl = typeof globalConfig.backendUrl === 'string'
|
|
63
64
|
? globalConfig.backendUrl
|
|
@@ -73,17 +74,9 @@ export function resolveExistingTokenForLoginTarget(globalConfig, backendUrl) {
|
|
|
73
74
|
: undefined;
|
|
74
75
|
}
|
|
75
76
|
export function buildCliAuthUrl(options) {
|
|
76
|
-
const
|
|
77
|
-
if (!base)
|
|
78
|
-
throw new Error('Invalid environment address');
|
|
79
|
-
const url = new URL(`${base}/cli-auth`);
|
|
80
|
-
url.searchParams.set('callbackUrl', options.callbackUrl);
|
|
77
|
+
const url = new URL('/cli-auth', options.backendUrl);
|
|
81
78
|
url.searchParams.set('callback', options.callbackUrl);
|
|
82
79
|
url.searchParams.set('state', options.state);
|
|
83
|
-
if (options.codeChallenge) {
|
|
84
|
-
url.searchParams.set('codeChallenge', options.codeChallenge);
|
|
85
|
-
url.searchParams.set('codeChallengeMethod', 'S256');
|
|
86
|
-
}
|
|
87
80
|
return url.toString();
|
|
88
81
|
}
|
|
89
82
|
export async function renewExistingToken(options) {
|
|
@@ -94,20 +87,12 @@ export async function renewExistingToken(options) {
|
|
|
94
87
|
try {
|
|
95
88
|
const res = await fetchFn(`${options.backendUrl}/api/settings/personal-access-tokens/current/renew`, {
|
|
96
89
|
method: 'PATCH',
|
|
97
|
-
redirect: 'error',
|
|
98
|
-
signal: AbortSignal.timeout(10_000),
|
|
99
90
|
headers: {
|
|
100
91
|
Authorization: `Bearer ${options.token}`,
|
|
101
92
|
'Content-Type': 'application/json',
|
|
102
93
|
},
|
|
103
94
|
body: JSON.stringify({ expiresIn: '365d' }),
|
|
104
95
|
});
|
|
105
|
-
if (res.ok && res.json && options.onRenewed) {
|
|
106
|
-
const result = await res.json();
|
|
107
|
-
if (typeof result.expiresAt === 'string' && Date.parse(result.expiresAt) > Date.now()) {
|
|
108
|
-
options.onRenewed(result.expiresAt);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
96
|
return res.ok;
|
|
112
97
|
}
|
|
113
98
|
catch {
|
|
@@ -115,43 +100,29 @@ export async function renewExistingToken(options) {
|
|
|
115
100
|
}
|
|
116
101
|
}
|
|
117
102
|
export async function loginCommand(options) {
|
|
118
|
-
if (options.activate) {
|
|
119
|
-
await activateAccount(options, DEFAULT_PLAYCRAFT_CLOUD_BASE);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
103
|
const backendUrl = resolveLoginBaseUrl(options);
|
|
123
104
|
const callbackPort = options.callbackPort ?? CALLBACK_PORT;
|
|
124
105
|
const globalConfig = loadGlobalConfig();
|
|
125
106
|
const existingToken = resolveExistingTokenForLoginTarget(globalConfig, backendUrl);
|
|
126
107
|
if (existingToken) {
|
|
127
|
-
|
|
128
|
-
const renewed = await renewExistingToken({ backendUrl, token: existingToken,
|
|
129
|
-
onRenewed: (value) => { expiresAt = value; } });
|
|
108
|
+
const renewed = await renewExistingToken({ backendUrl, token: existingToken });
|
|
130
109
|
if (renewed) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
110
|
+
saveGlobalConfig({
|
|
111
|
+
token: existingToken,
|
|
112
|
+
url: backendUrl,
|
|
113
|
+
backendUrl,
|
|
114
|
+
});
|
|
135
115
|
console.log('Existing CLI token renewed. Token saved to ~/.playcraft/config.json');
|
|
136
116
|
return;
|
|
137
117
|
}
|
|
138
118
|
}
|
|
139
119
|
const state = crypto.randomBytes(16).toString('hex');
|
|
140
|
-
const codeVerifier = crypto.randomBytes(32).toString('base64url');
|
|
141
|
-
const codeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('base64url');
|
|
142
|
-
let callbackUrl = '';
|
|
143
|
-
let exchanging = false;
|
|
144
120
|
return new Promise((resolve, reject) => {
|
|
145
121
|
let timeout;
|
|
146
122
|
const server = http.createServer((req, res) => {
|
|
147
|
-
res.setHeader('Access-Control-Allow-Origin',
|
|
123
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
148
124
|
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
149
125
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
150
|
-
if (req.headers.origin && req.headers.origin !== new URL(backendUrl).origin) {
|
|
151
|
-
res.writeHead(403);
|
|
152
|
-
res.end();
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
126
|
if (req.method === 'OPTIONS') {
|
|
156
127
|
res.writeHead(204);
|
|
157
128
|
res.end();
|
|
@@ -159,9 +130,8 @@ export async function loginCommand(options) {
|
|
|
159
130
|
}
|
|
160
131
|
if (req.url === '/callback' && req.method === 'POST') {
|
|
161
132
|
let body = '';
|
|
162
|
-
req.on('data', (chunk) =>
|
|
163
|
-
|
|
164
|
-
req.on('end', async () => {
|
|
133
|
+
req.on('data', (chunk) => (body += chunk));
|
|
134
|
+
req.on('end', () => {
|
|
165
135
|
try {
|
|
166
136
|
const data = JSON.parse(body);
|
|
167
137
|
if (data.state !== state) {
|
|
@@ -169,36 +139,22 @@ export async function loginCommand(options) {
|
|
|
169
139
|
'Content-Type': 'text/html',
|
|
170
140
|
Connection: 'close',
|
|
171
141
|
});
|
|
172
|
-
res.end('<html><body><h1>Invalid state</h1></body></html>')
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
res.end();
|
|
142
|
+
res.end('<html><body><h1>Invalid state</h1></body></html>', () => {
|
|
143
|
+
closeServer(() => {
|
|
144
|
+
reject(new Error('State mismatch - possible CSRF attack'));
|
|
145
|
+
});
|
|
146
|
+
});
|
|
178
147
|
return;
|
|
179
148
|
}
|
|
180
|
-
|
|
181
|
-
|
|
149
|
+
const callbackToken = typeof data.token === 'string' ? data.token : undefined;
|
|
150
|
+
if (!callbackToken) {
|
|
151
|
+
throw new Error('Login callback did not include a token');
|
|
182
152
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const exchange = await fetch(`${base}/api/cloud-environments/exchange`, {
|
|
188
|
-
method: 'POST', redirect: 'error', signal: AbortSignal.timeout(10_000),
|
|
189
|
-
headers: { 'Content-Type': 'application/json' },
|
|
190
|
-
body: JSON.stringify({ code: data.code, state, callbackUrl, codeVerifier }),
|
|
153
|
+
saveGlobalConfig({
|
|
154
|
+
token: callbackToken,
|
|
155
|
+
url: backendUrl,
|
|
156
|
+
backendUrl,
|
|
191
157
|
});
|
|
192
|
-
if (!exchange.ok)
|
|
193
|
-
throw new Error('Authorization code exchange failed');
|
|
194
|
-
const credential = await exchange.json();
|
|
195
|
-
if (!credential.token || !/^playcraft_pat_[A-Za-z0-9_-]{32}$/.test(credential.token)
|
|
196
|
-
|| !credential.identity?.userId || !Array.isArray(credential.identity.identities)
|
|
197
|
-
|| !credential.expiresAt || Date.parse(credential.expiresAt) <= Date.now()) {
|
|
198
|
-
throw new Error('Invalid environment credential response');
|
|
199
|
-
}
|
|
200
|
-
saveEnvironmentProfile(base, { token: credential.token,
|
|
201
|
-
identity: credential.identity, expiresAt: credential.expiresAt });
|
|
202
158
|
res.writeHead(200, {
|
|
203
159
|
'Content-Type': 'text/html',
|
|
204
160
|
Connection: 'close',
|
|
@@ -218,6 +174,9 @@ export async function loginCommand(options) {
|
|
|
218
174
|
catch (err) {
|
|
219
175
|
const cause = err instanceof Error ? err : new Error(String(err));
|
|
220
176
|
console.error('[playcraft login] Callback handling failed:', cause.message);
|
|
177
|
+
if (cause.stack) {
|
|
178
|
+
console.error(cause.stack);
|
|
179
|
+
}
|
|
221
180
|
const userFacing = cause instanceof SyntaxError
|
|
222
181
|
? 'Invalid JSON in login callback.'
|
|
223
182
|
: `Login callback failed: ${cause.message}`;
|
|
@@ -262,15 +221,14 @@ export async function loginCommand(options) {
|
|
|
262
221
|
});
|
|
263
222
|
});
|
|
264
223
|
try {
|
|
265
|
-
server.listen(callbackPort,
|
|
224
|
+
server.listen(callbackPort, () => {
|
|
266
225
|
const address = server.address();
|
|
267
226
|
const listeningPort = typeof address === 'object' && address ? address.port : callbackPort;
|
|
268
|
-
callbackUrl = `http://
|
|
227
|
+
const callbackUrl = `http://localhost:${listeningPort}/callback`;
|
|
269
228
|
const authUrl = buildCliAuthUrl({
|
|
270
229
|
backendUrl,
|
|
271
230
|
callbackUrl,
|
|
272
231
|
state,
|
|
273
|
-
codeChallenge,
|
|
274
232
|
});
|
|
275
233
|
console.log('Opening browser for login...');
|
|
276
234
|
console.log(`If the browser does not open, visit this URL manually:\n ${authUrl}\n`);
|
package/dist/commands/skills.js
CHANGED
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
* 3. <cwd>/node_modules/@playcraft/skills/playcraft-skills(兼容旧路径 skills)
|
|
19
19
|
* 4. <CLI 自身>/../../skills/playcraft-skills(monorepo 开发时,兼容旧路径 skills)
|
|
20
20
|
*/
|
|
21
|
-
import { registerProjectSkillsCommands } from '../project-skills/commands.js';
|
|
22
21
|
import * as fs from 'node:fs';
|
|
23
22
|
import * as path from 'node:path';
|
|
24
23
|
import { getFusionHintsForGameplayAtoms, } from '../atom-tree/fusion-hints.js';
|
|
@@ -1431,7 +1430,6 @@ export function registerSkillsCommands(program) {
|
|
|
1431
1430
|
const skills = program
|
|
1432
1431
|
.command('skills')
|
|
1433
1432
|
.description('开发时 Skill 发现与脚手架工具(按 engine/intent 推荐 skill 集合,或将 ref 文件复制到项目)');
|
|
1434
|
-
registerProjectSkillsCommands(skills);
|
|
1435
1433
|
// 公共选项:skills 目录
|
|
1436
1434
|
const addSkillsDirOption = (cmd) => cmd.option('--skills-dir <path>', '指定 skills 目录路径(默认自动发现)');
|
|
1437
1435
|
// ── list ──────────────────────────────────────────────────────────────────
|
|
@@ -258,7 +258,7 @@ export function registerGenerationCommands(tools) {
|
|
|
258
258
|
...(result.additionalImages ?? []),
|
|
259
259
|
];
|
|
260
260
|
const isBatch = allImages.length > 1;
|
|
261
|
-
const modelPart =
|
|
261
|
+
const modelPart = result.model ? `model: ${result.model}` : '';
|
|
262
262
|
const providerPart = result.provider ? `provider: ${result.provider}` : '';
|
|
263
263
|
const labelParts = [modelPart, providerPart].filter(Boolean);
|
|
264
264
|
const modelLabel = labelParts.length > 0 ? ` (${labelParts.join(', ')})` : '';
|
|
@@ -311,8 +311,10 @@ export function registerGenerationCommands(tools) {
|
|
|
311
311
|
savedPaths.push(resolvedPath);
|
|
312
312
|
const sidecar = {
|
|
313
313
|
prompt: opts.prompt,
|
|
314
|
-
model:
|
|
314
|
+
model: result.model ?? null,
|
|
315
|
+
requestedModel: opts.imageModel ?? null,
|
|
315
316
|
provider: result.provider ?? null,
|
|
317
|
+
transparentBackground: result.transparentBackground ?? null,
|
|
316
318
|
aspectRatio: opts.aspectRatio,
|
|
317
319
|
imageSize: opts.imageSize ?? null,
|
|
318
320
|
requestedWidth: opts.width ?? stripTarget?.width ?? null,
|
package/dist/commands/tools.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
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';
|
|
@@ -10,7 +9,6 @@ export function registerToolsCommands(program) {
|
|
|
10
9
|
.description('后端 /api/agent/tools;运行 playcraft login 后即可直接使用,也支持 .playcraft.json 或 PLAYCRAFT_SANDBOX_TOKEN 环境变量');
|
|
11
10
|
registerGenerationCommands(tools);
|
|
12
11
|
registerProjectCommands(tools);
|
|
13
|
-
registerBatchCommands(tools);
|
|
14
12
|
register3DCommands(tools);
|
|
15
13
|
registerDetectCommand(tools);
|
|
16
14
|
registerVideoReviewCommand(tools);
|