@playcraft/cli 0.1.34 → 0.1.35-prod

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/README.md +3 -56
  2. package/dist/agent/local-backend.js +1 -1
  3. package/dist/cli-root-help.js +0 -2
  4. package/dist/commands/build.js +4 -9
  5. package/dist/commands/create.js +33 -26
  6. package/dist/commands/image.js +6 -2
  7. package/dist/commands/login.js +42 -84
  8. package/dist/commands/skills.js +0 -2
  9. package/dist/commands/tools-3d.js +0 -11
  10. package/dist/commands/tools-generation.js +109 -68
  11. package/dist/commands/tools-image-context.js +23 -0
  12. package/dist/commands/tools.js +2 -2
  13. package/dist/config.js +4 -59
  14. package/dist/index.js +3 -36
  15. package/dist/remix/clone.js +0 -2
  16. package/dist/remix/init-template.js +0 -2
  17. package/dist/remix/pull.js +0 -2
  18. package/dist/remix/push.js +1 -21
  19. package/dist/utils/agent-api-client.js +30 -185
  20. package/dist/utils/image-asset-context.js +105 -0
  21. package/dist/utils/playcraft-http-client.js +4 -6
  22. package/package.json +3 -12
  23. package/project-template/.claude/agents/refs/ta-image-generation-detail.md +67 -123
  24. package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +105 -44
  25. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  26. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  27. package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  28. package/project-template/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +36 -39
  29. package/project-templates/phaser/.claude/agents/refs/ta-image-generation-detail.md +59 -59
  30. package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +105 -44
  31. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  32. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  33. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  34. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +36 -39
  35. package/project-templates/threejs/.claude/agents/refs/ta-image-generation-detail.md +59 -59
  36. package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +105 -44
  37. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  38. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  39. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  40. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +36 -39
  41. package/dist/auth/account-activation.js +0 -157
  42. package/dist/auth/messages.js +0 -30
  43. package/dist/commands/platform-skills.generated.js +0 -19
  44. package/dist/commands/playable.js +0 -53
  45. package/dist/commands/tools-batch.js +0 -87
  46. package/dist/commands/video.js +0 -111
  47. package/dist/commands/workspace-runtime.js +0 -54
  48. package/dist/commands/workspace.js +0 -35
  49. package/dist/project-skills/builtin-import.js +0 -225
  50. package/dist/project-skills/commands.js +0 -77
  51. package/dist/project-skills/lifecycle.js +0 -28
  52. package/dist/project-skills/local-run.js +0 -112
  53. package/dist/project-skills/local-store.js +0 -221
  54. package/dist/project-skills/messages.js +0 -80
  55. package/dist/project-skills/reconcile.js +0 -62
  56. package/dist/project-skills/remote-cache.js +0 -51
  57. package/dist/project-skills/validation.js +0 -19
  58. package/dist/recording/messages.js +0 -40
  59. package/dist/recording/project-digest.js +0 -85
  60. package/dist/recording/recorder.js +0 -293
  61. package/dist/recording/scenario.js +0 -50
  62. package/dist/utils/environment-endpoints.js +0 -17
  63. package/dist/utils/tool-operation-journal.js +0 -124
  64. package/dist/utils/video-evidence-git.js +0 -81
  65. package/dist/video-replication/client.js +0 -222
  66. package/dist/video-replication/comparison-evidence.js +0 -149
  67. package/dist/video-replication/comparison-files.js +0 -57
  68. package/dist/video-replication/comparison-log.js +0 -72
  69. package/dist/video-replication/comparison-messages.js +0 -104
  70. package/dist/video-replication/comparison-output.js +0 -63
  71. package/dist/video-replication/comparison-preflight.js +0 -66
  72. package/dist/video-replication/comparison.js +0 -216
  73. package/dist/video-replication/evidence.js +0 -165
  74. package/dist/video-replication/media.js +0 -111
  75. package/dist/video-replication/messages.js +0 -89
  76. package/dist/workspace/messages.js +0 -35
  77. package/dist/workspace/transfer-client.js +0 -174
  78. package/dist/workspace-runtime/codex/app-server.js +0 -965
  79. package/dist/workspace-runtime/codex/compact.js +0 -46
  80. package/dist/workspace-runtime/codex/config-toml.js +0 -107
  81. package/dist/workspace-runtime/codex/jsonrpc-stdio.js +0 -145
  82. package/dist/workspace-runtime/codex/launcher-client.js +0 -177
  83. package/dist/workspace-runtime/codex/loopback.js +0 -146
  84. package/dist/workspace-runtime/codex/mcp-config.js +0 -39
  85. package/dist/workspace-runtime/codex/model-broker.js +0 -263
  86. package/dist/workspace-runtime/codex/native-adapter.js +0 -9
  87. package/dist/workspace-runtime/codex/permissions.js +0 -70
  88. package/dist/workspace-runtime/codex/work-mode.js +0 -15
  89. package/dist/workspace-runtime/main.js +0 -10
  90. package/dist/workspace-runtime/persistence/journal.js +0 -355
  91. package/dist/workspace-runtime/persistence/native-subagents.js +0 -162
  92. package/dist/workspace-runtime/persistence/sqlite-client.js +0 -77
  93. package/dist/workspace-runtime/persistence/sqlite-worker.js +0 -1096
  94. package/dist/workspace-runtime/previews/output.js +0 -36
  95. package/dist/workspace-runtime/previews/publish.js +0 -262
  96. package/dist/workspace-runtime/previews/single-file.js +0 -43
  97. package/dist/workspace-runtime/processes/managed-writes.js +0 -69
  98. package/dist/workspace-runtime/production/contracts.js +0 -17
  99. package/dist/workspace-runtime/production/controller.js +0 -207
  100. package/dist/workspace-runtime/production/dependencies.js +0 -60
  101. package/dist/workspace-runtime/production/native.js +0 -203
  102. package/dist/workspace-runtime/production/processes.js +0 -86
  103. package/dist/workspace-runtime/production/save-command.js +0 -35
  104. package/dist/workspace-runtime/production/source-copy.js +0 -91
  105. package/dist/workspace-runtime/production/stages.js +0 -205
  106. package/dist/workspace-runtime/production/storage.js +0 -60
  107. package/dist/workspace-runtime/serve.js +0 -207
  108. package/dist/workspace-runtime/server/auth.js +0 -21
  109. package/dist/workspace-runtime/server/connectivity.js +0 -201
  110. package/dist/workspace-runtime/server/desktop-host.js +0 -429
  111. package/dist/workspace-runtime/server/desktop-preview-config.js +0 -81
  112. package/dist/workspace-runtime/server/desktop-preview-service.js +0 -157
  113. package/dist/workspace-runtime/server/desktop-preview-static.js +0 -53
  114. package/dist/workspace-runtime/server/desktop-preview.js +0 -189
  115. package/dist/workspace-runtime/server/dispatch.js +0 -1183
  116. package/dist/workspace-runtime/server/endpoints.js +0 -19
  117. package/dist/workspace-runtime/server/execution-group.js +0 -85
  118. package/dist/workspace-runtime/server/http.js +0 -1127
  119. package/dist/workspace-runtime/server/lock.js +0 -53
  120. package/dist/workspace-runtime/server/rfb-watch-gate.js +0 -168
  121. package/dist/workspace-runtime/server/terminal-host.js +0 -366
  122. package/dist/workspace-runtime/server/types.js +0 -1
  123. package/dist/workspace-runtime/server/workspace-transfer.js +0 -99
  124. package/dist/workspace-runtime/workspaces/archive.js +0 -207
  125. package/dist/workspace-runtime/workspaces/artifact-events.js +0 -55
  126. package/dist/workspace-runtime/workspaces/artifact-files.js +0 -197
  127. package/dist/workspace-runtime/workspaces/artifact-receipts.js +0 -89
  128. package/dist/workspace-runtime/workspaces/artifacts.js +0 -282
  129. package/dist/workspace-runtime/workspaces/attachment-content.js +0 -123
  130. package/dist/workspace-runtime/workspaces/attachments.js +0 -181
  131. package/dist/workspace-runtime/workspaces/batch-commit.js +0 -142
  132. package/dist/workspace-runtime/workspaces/cli-context.js +0 -23
  133. package/dist/workspace-runtime/workspaces/cli-credentials.js +0 -111
  134. package/dist/workspace-runtime/workspaces/composer-context.js +0 -125
  135. package/dist/workspace-runtime/workspaces/context-error.js +0 -2
  136. package/dist/workspace-runtime/workspaces/dependencies.js +0 -264
  137. package/dist/workspace-runtime/workspaces/developer-command.js +0 -64
  138. package/dist/workspace-runtime/workspaces/directories.js +0 -123
  139. package/dist/workspace-runtime/workspaces/directory-access.js +0 -37
  140. package/dist/workspace-runtime/workspaces/directory-attachments.js +0 -245
  141. package/dist/workspace-runtime/workspaces/directory-maintenance.js +0 -111
  142. package/dist/workspace-runtime/workspaces/directory-stats.js +0 -49
  143. package/dist/workspace-runtime/workspaces/disk-snapshot.js +0 -31
  144. package/dist/workspace-runtime/workspaces/empty-template.js +0 -40
  145. package/dist/workspace-runtime/workspaces/files-search.js +0 -116
  146. package/dist/workspace-runtime/workspaces/files.js +0 -120
  147. package/dist/workspace-runtime/workspaces/git-credential-broker.js +0 -312
  148. package/dist/workspace-runtime/workspaces/git-credential-helper.js +0 -68
  149. package/dist/workspace-runtime/workspaces/git-direct-store.js +0 -155
  150. package/dist/workspace-runtime/workspaces/git.js +0 -670
  151. package/dist/workspace-runtime/workspaces/instructions.js +0 -56
  152. package/dist/workspace-runtime/workspaces/json5-edit.js +0 -170
  153. package/dist/workspace-runtime/workspaces/library-attachments.js +0 -268
  154. package/dist/workspace-runtime/workspaces/parameters.js +0 -272
  155. package/dist/workspace-runtime/workspaces/prepare.js +0 -264
  156. package/dist/workspace-runtime/workspaces/registry.js +0 -236
  157. package/dist/workspace-runtime/workspaces/revisions.js +0 -31
  158. package/dist/workspace-runtime/workspaces/shared-git.js +0 -40
  159. package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +0 -91
  160. package/dist/workspace-runtime/workspaces/skills.js +0 -189
  161. package/dist/workspace-runtime/workspaces/transfer.js +0 -288
  162. package/dist/workspace-runtime/workspaces/turn-changes.js +0 -75
  163. package/dist/workspace-runtime/workspaces/video-attachments.js +0 -49
  164. package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +0 -25
  165. package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +0 -79
  166. package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +0 -29
  167. package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +0 -37
  168. package/project-template-v2/.claude/agents/artist.md +0 -82
  169. package/project-template-v2/.claude/agents/developer.md +0 -153
  170. package/project-template-v2/.claude/agents/game-designer.md +0 -264
  171. package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +0 -533
  172. package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +0 -153
  173. package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +0 -27
  174. package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +0 -208
  175. package/project-template-v2/.claude/agents/refs/atom-skill-library.md +0 -81
  176. package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +0 -432
  177. package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +0 -252
  178. package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +0 -266
  179. package/project-template-v2/.claude/agents/refs/framework-mda.md +0 -147
  180. package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +0 -123
  181. package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +0 -88
  182. package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +0 -67
  183. package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +0 -120
  184. package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +0 -300
  185. package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +0 -495
  186. package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +0 -1141
  187. package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +0 -111
  188. package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +0 -365
  189. package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +0 -412
  190. package/project-template-v2/.claude/agents/reviewer.md +0 -75
  191. package/project-template-v2/.claude/agents/technical-artist.md +0 -86
  192. package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +0 -243
  193. package/project-template-v2/.claude/hooks/user-prompt.mjs +0 -133
  194. package/project-template-v2/.claude/settings.json +0 -33
  195. package/project-template-v2/.claude/skills/brainstorming/SKILL.md +0 -161
  196. package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +0 -270
  197. package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +0 -177
  198. package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +0 -354
  199. package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +0 -148
  200. package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +0 -56
  201. package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +0 -62
  202. package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
  203. package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +0 -309
  204. package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +0 -182
  205. package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +0 -123
  206. package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +0 -205
  207. package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +0 -280
  208. package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +0 -184
  209. package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +0 -306
  210. package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +0 -298
  211. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +0 -123
  212. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +0 -254
  213. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +0 -324
  214. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +0 -97
  215. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +0 -118
  216. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +0 -137
  217. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +0 -397
  218. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +0 -296
  219. package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +0 -122
  220. package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +0 -219
  221. package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +0 -373
  222. package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +0 -161
  223. package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +0 -215
  224. package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +0 -382
  225. package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +0 -423
  226. package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +0 -158
  227. package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +0 -100
  228. package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +0 -167
  229. package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +0 -270
  230. package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +0 -236
  231. package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +0 -130
  232. package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +0 -390
  233. package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +0 -23
  234. package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +0 -39
  235. package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +0 -87
  236. package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +0 -240
  237. package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +0 -226
  238. package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +0 -308
  239. package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +0 -275
  240. package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +0 -134
  241. package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +0 -142
  242. package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +0 -153
  243. package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +0 -386
  244. package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +0 -182
  245. package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +0 -72
  246. package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +0 -121
  247. package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +0 -102
  248. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +0 -127
  249. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +0 -106
  250. package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +0 -128
  251. package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +0 -67
  252. package/project-template-v2/.claude/snapshot.mjs +0 -263
  253. package/project-template-v2/.playcraft/skills.lock.json +0 -152
  254. package/project-template-v2/CLAUDE.md +0 -146
  255. package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
  256. package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
  257. package/project-template-v2/assets/bundles/.gitkeep +0 -0
  258. package/project-template-v2/assets/images/bg/.gitkeep +0 -0
  259. package/project-template-v2/assets/images/reference/.gitkeep +0 -0
  260. package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
  261. package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
  262. package/project-template-v2/assets/images/ui/.gitkeep +0 -0
  263. package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
  264. package/project-template-v2/assets/models/.gitkeep +0 -0
  265. package/project-template-v2/docs/harness/iteration-1/context-flow.md +0 -254
  266. package/project-template-v2/docs/harness/iteration-1/generate-flow.md +0 -91
  267. package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +0 -214
  268. package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +0 -75
  269. package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +0 -63
  270. package/project-template-v2/docs/harness/iteration-2/context-flow.md +0 -223
  271. package/project-template-v2/docs/harness/iteration-2/generate-flow.md +0 -129
  272. package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +0 -267
  273. package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +0 -164
  274. package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +0 -115
  275. package/project-template-v2/docs/harness/orchestrator-flow.md +0 -364
  276. package/project-template-v2/docs/project-state.json +0 -60
  277. package/project-template-v2/docs/project-state.md +0 -72
  278. package/project-template-v2/docs/standards/README.md +0 -225
  279. package/project-template-v2/docs/standards/agent-behavior-standards.md +0 -174
  280. package/project-template-v2/docs/standards/artifacts/design-brief.md +0 -19
  281. package/project-template-v2/docs/standards/artifacts/design.md +0 -22
  282. package/project-template-v2/docs/standards/artifacts/game-code.md +0 -41
  283. package/project-template-v2/docs/standards/artifacts/todo-list.md +0 -41
  284. package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +0 -343
  285. package/project-template-v2/game/index.ts +0 -18
  286. package/project-template-v2/globals.d.ts +0 -51
  287. package/project-template-v2/index.css +0 -34
  288. package/project-template-v2/index.html +0 -18
  289. package/project-template-v2/main.ts +0 -9
  290. package/project-template-v2/package.json +0 -46
  291. package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +0 -31
  292. package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +0 -86
  293. package/project-template-v2/skills/_shared/scripts/dod-check.mjs +0 -153
  294. package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +0 -70
  295. package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +0 -91
  296. package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +0 -131
  297. package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +0 -80
  298. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +0 -90
  299. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +0 -93
  300. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +0 -23
  301. package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +0 -230
  302. package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +0 -58
  303. package/project-template-v2/skills/_shared/scripts/state-get.mjs +0 -339
  304. package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +0 -39
  305. package/project-template-v2/skills/_shared/scripts/state-set.mjs +0 -94
  306. package/project-template-v2/skills/_shared/scripts/state-store.mjs +0 -783
  307. package/project-template-v2/skills/_shared/scripts/todo-add.mjs +0 -88
  308. package/project-template-v2/skills/_shared/scripts/todo-get.mjs +0 -130
  309. package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +0 -33
  310. package/project-template-v2/skills/_shared/scripts/todo-set.mjs +0 -47
  311. package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +0 -268
  312. package/project-template-v2/skills/_shared/scripts/verify-env.mjs +0 -285
  313. package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +0 -161
  314. package/project-template-v2/skills/playable-autoplay/SKILL.md +0 -176
  315. package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +0 -4
  316. package/project-template-v2/skills/playable-debug/SKILL.md +0 -116
  317. package/project-template-v2/skills/playable-debug/agents/openai.yaml +0 -4
  318. package/project-template-v2/skills/playable-debug/references/debug-config.md +0 -40
  319. package/project-template-v2/skills/playable-record/SKILL.md +0 -140
  320. package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +0 -104
  321. package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +0 -141
  322. package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +0 -425
  323. package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +0 -261
  324. package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +0 -398
  325. package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +0 -322
  326. package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +0 -105
  327. package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +0 -230
  328. package/project-template-v2/skills/playable-validate/SKILL.md +0 -61
  329. package/project-template-v2/skills/playable-validate/validation-rules.md +0 -14
  330. package/project-template-v2/skills/playable-verify-ui/SKILL.md +0 -63
  331. package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +0 -1
  332. package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +0 -218
  333. package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +0 -51
  334. package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +0 -59
  335. package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +0 -106
  336. package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +0 -116
  337. package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +0 -59
  338. package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +0 -64
  339. package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +0 -58
  340. package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +0 -333
  341. package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
  342. package/project-template-v2/tsconfig.json +0 -20
  343. package/project-template-v2/vite.config.ts +0 -27
  344. package/project-templates/batch-locks/phaser.yaml +0 -922
  345. package/project-templates/batch-locks/threejs.yaml +0 -978
  346. package/project-templates/empty/AGENTS.md +0 -39
  347. package/project-templates/empty/gitignore +0 -33
package/README.md CHANGED
@@ -7,29 +7,11 @@
7
7
 
8
8
  PlayCraft CLI(Command-Line Interface,命令行工具)支持本地代码与云端编辑器实时同步,以及将 PlayCanvas/PlayCraft 项目打包为多平台 Playable Ads。
9
9
 
10
- ## 云端工作台 Runtime
10
+ ## 云端工作台 Runtime(计划能力)
11
11
 
12
- `playcraft workspace-runtime serve --config <json>` 已注册。它前台常驻、跳过升级检查,读取 Runtime Server 下发的引导配置,只绑定回环并校验 control token。`runtime.ensure` 会执行到终态;设置 `PLAYCRAFT_NATIVE_ADAPTER=loopback` 或测试注入 loopback 适配器后,可跑会话 create/turn/interrupt/审批,以及本地 journal 检查点/恢复/销毁。工作空间相对路径的 `file.write` 与文件检查点不依赖 loopback。相同幂等键上的 `uncertain` 操作不会新开 turn。这不是 Codex App Server。现有 `playcraft start` 仍用于单项目本地开发,二者不要混用。
12
+ 云端工作台计划以 `@playcraft/cli` 承载自定义 AGS(Agent Sandbox,Agent 沙箱服务)内的常驻运行服务,新增 `playcraft workspace-runtime serve` 命令,管理多个 Workspace、一个 Codex App Server、文件/Git/终端/预览及持久恢复。该命令尚未实现,当前发布版本不可调用;现有 `playcraft start` 仍用于单项目本地开发。
13
13
 
14
- 实现与模块边界见 [Sandbox Agent Server](./src/workspace-runtime/README.md);契约见 [云端工作台后端架构方案](../../docs/architecture/backend/cloud-workspace/backend-architecture.md#cli-runtime)。
15
-
16
- ## 下载云工作区并推送本地修改
17
-
18
- 文件面板的下载弹窗可复制下列命令。需要发布包含 `workspace` 命令的新版 `@playcraft/cli`,并部署对应的工作区传输端点;旧版 Remix 命令保持兼容。
19
-
20
- ```bash
21
- npx @playcraft/cli@latest login --url 'https://playcraft.example.com/__env/test-a'
22
- npx @playcraft/cli@latest workspace clone --workspace-id '<workspace-id>' --directory root --url 'https://playcraft.example.com/__env/test-a' --dir './my-workspace'
23
- cd './my-workspace'
24
- # 完成本地编辑后提交,再同步回原工作区
25
- git add -A
26
- git commit -m 'Update workspace'
27
- npx @playcraft/cli@latest workspace push
28
- ```
29
-
30
- `--directory root` 下载整个工作区的工程目录;也可指定 `basic` 或已有工程目录。独立工作区无需关联平台项目。下载包含当前未提交文件、二进制素材和 `dist/` 产物,使用只有当前快照的新 Git 历史;排除 `.git`、`node_modules`、凭据文件和运行时路由信息。本地 `.playcraft-workspace.json` 保存目标工作区、目录、完整环境基址和快照摘要,不含访问令牌,默认不进入提交。服务基址的环境路径前缀会完整保留。
31
-
32
- `workspace push` 要求本地修改已经提交,将提交的文件同步回同一个云工作区;云端文件变化或有正在运行的任务时拒绝覆盖,需重新克隆并合并后再推送。云端现有 Git 仓库和分支元数据会保留,保存到远端项目仍使用工作区原有保存流程;针对项目分支的操作可继续使用 `remix clone` / `remix push`。传输限制为 20,000 个文件、256 MiB(Mebibyte,二进制兆字节)内容及压缩包,超限可使用弹窗中的直接下载。命令支持 `--token`、`--dir` 与 `--json`。
14
+ 新服务采用固定版本、前台非交互运行,由镜像监管器启动;独立 Runtime Server 在沙箱外部署。具体代码归属、进程权限、发布与恢复契约见 [云端工作台后端架构方案](../../docs/architecture/backend/cloud-workspace/backend-architecture.md#cli-runtime)。
33
15
 
34
16
  ## ✨ 特性
35
17
 
@@ -159,17 +141,6 @@ playcraft login --url https://your-playcraft.example.com
159
141
 
160
142
  登录成功后,`tools`、`recommend`、`fix-ids` 等所有需要后端 API 的命令均无需额外配置,直接使用。
161
143
 
162
- 账号提示待激活时,使用同一目标环境及已保存的个人访问令牌主动激活:
163
-
164
- ```bash
165
- playcraft login --activate
166
- playcraft login --activate --url https://your-playcraft.example.com
167
- ```
168
-
169
- 也可通过 `PLAYCRAFT_TOKEN` 提供个人访问令牌。激活只发送一次请求,成功后重新执行原业务命令;该动作不会打开浏览器或续签令牌。目标服务须已接入身份服务的激活入口;封禁、停用账号及沙箱执行令牌不能用于激活。
170
-
171
- 若本地、全局或环境变量配置冲突,激活会要求明确指定 `--url`、所需的 `PLAYCRAFT_ENV` 和对应的个人访问令牌。
172
-
173
144
  ### 沙箱环境(CI / Agent)
174
145
 
175
146
  在沙箱或 CI 中可通过 `.playcraft.json` 或环境变量配置:
@@ -217,30 +188,6 @@ echo '{"token":"<sandbox-jwt>","apiUrl":"https://..."}' > .playcraft.json
217
188
  | `recommend improvements` | Tag 改进建议 | `playcraft recommend improvements --channel Facebook` |
218
189
  | `recommend random` | 随机 Tag 组合推荐 | `playcraft recommend random --channel Google` |
219
190
 
220
- ### 业务工具请求恢复
221
-
222
- 业务工具写请求要求服务支持持久操作协议。命令行先保存请求编号、路径和输入摘要到 `~/.playcraft/tool-requests/`,再发送请求;记录不包含凭证或请求正文。可用绝对路径环境变量 `PLAYCRAFT_TOOL_REQUEST_DIR` 指定可持久保留的目录。
223
-
224
- 原样重跑同一条命令(路径与参数都相同)时,命令行按上一次的结果决定是否沿用原请求编号:
225
-
226
- | 上一次的结果 | 原样重跑时 |
227
- | -------------------------------------------------------------------- | -------------------------------------------------------- |
228
- | 成功(2xx) | 新操作 |
229
- | 请求被拒绝(4xx,下列 409 除外):请求没有被执行 | 新操作 |
230
- | 服务端错误(5xx)、超时或连接中断:结果未知 | 沿用原编号,不会另起一次操作;服务端按下文的恢复方式处理 |
231
- | 409 `business_operation_in_progress`:原操作仍在执行 | 沿用原编号,稍后重跑取得结果 |
232
- | 409 `business_operation_requires_reconciliation`:结果未知,需要核对 | 沿用原编号,不会再执行 |
233
-
234
- 沿用原编号时,服务端按原操作的状态处理:已完成则返回原结果;仍在执行则返回 409 `business_operation_in_progress`;没有拿到结果就结束时,按该工具声明的恢复方式决定,可以安全重做的工具(生图、构建、发布到 COS 等)用原编号再执行一次,其余返回 409 `business_operation_requires_reconciliation`。原调用的执行租约有效期间(执行中每 20 秒续期,60 秒未续即过期),同一编号不会被再次执行;续期因服务或数据库故障中断超过 60 秒时,重做可能与仍在运行的原调用重叠。
235
-
236
- 需要核对的操作,只有确认它没有生效后,才可设置 `PLAYCRAFT_TOOL_NEW_REQUEST=1` 强制发起新操作;不要删除记录来绕过。也可以显式指定编号,只查询原操作的确定结果(不会重新执行;声明了恢复方式的工具若上次报错,返回那次的错误)。只查询时即使是可以安全重做的工具,没有结果也返回需要核对;去掉 `PLAYCRAFT_TOOL_REQUEST_ID` 原样重跑即可续做:
237
-
238
- ```bash
239
- PLAYCRAFT_TOOL_REQUEST_ID=<错误中显示的请求编号> playcraft tools build-project --project-id <原项目编号>
240
- ```
241
-
242
- 能力检查失败时命令会明确说明尚未发送操作。服务不兼容时命令会在发送业务请求前停止;沙箱命令行与 Business 须排空旧调用后同步升级。
243
-
244
191
  ### 构建相关
245
192
 
246
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 '@playcraft/common/database/operators';
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';
@@ -5,10 +5,8 @@ export function getCliTopicsHelpText() {
5
5
  '',
6
6
  ' 本地开发 create, init, start, stop, status, logs, config, sync, fix-ids',
7
7
  ' 素材 tools generate-* | image <子命令> | audio <子命令> | prefab <子命令>',
8
- ' 视频理解 video models | video understand | video jobs get/cancel',
9
8
  ' 平台 build, build-base, build-playable, build-all, analyze, inspect, upgrade',
10
9
  ' tools 除 generate-* 外(Git / 沙箱构建 / 发布 / 列表 / Prefab 等,需后端 API)',
11
- ' 沙箱常驻 workspace-runtime serve(Cloud Workspace,由 Runtime 引导配置启动)',
12
10
  '',
13
11
  '也可运行: playcraft topics',
14
12
  '',
@@ -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)- 如果配置文件中没有则必填;通用预览(playcraft)不面向渠道,可不填
590
- if (selectedPlatform === 'playcraft' && !options.storeUrls) {
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,交互式输入(必填);通用预览(playcraft)不面向渠道,可不填
645
- if (!options.storeUrls && options.platform !== 'playcraft') {
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 地址均为必填'));
@@ -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
- export async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, configDir) {
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
- // Platform Skill 住在 playcraft-skills/,与 Atom Skill 的 skills/ 是两个目录。
876
- // 尝试从 CLI 安装包的位置定位它(monorepo 内或与 CLI 平级安装时可解析)。
871
+ // 尝试从 CLI 安装包的位置定位 @playcraft/skills/skills 目录
877
872
  const candidateDirs = [
878
- path.resolve(cliCommandsDir, '..', '..', '..', '..', 'skills', PLATFORM_SKILLS_DIRNAME),
879
- path.resolve(cliCommandsDir, '..', '..', '..', 'skills', PLATFORM_SKILLS_DIRNAME),
880
- path.resolve(cliCommandsDir, '..', '..', 'skills', PLATFORM_SKILLS_DIRNAME),
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', PLATFORM_SKILLS_DIRNAME);
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.isDirectory() || staticSkills.has(entry.name))
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.access(path.join(targetPath, 'SKILL.md'));
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
- // 无法立即解析 → 指向 node_modules 的相对路径软连接,npm install 后自动激活。
919
- // 清单由 scripts/generate-platform-skills.mjs 从真实目录生成并由 CI 校验,不要手写。
920
- for (const name of PLATFORM_SKILL_DIRS) {
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) {
@@ -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, { fit }), outputPath, inputPath);
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, { fit }), opts.output, opts.input);
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
  }
@@ -1,8 +1,7 @@
1
1
  import http from 'http';
2
- import { execFile } from 'child_process';
2
+ import { exec } from 'child_process';
3
3
  import crypto from 'crypto';
4
- import { loadGlobalConfig, normalizeEnvironmentBaseUrl, readEnvironmentProfile, saveEnvironmentProfile } from '../config.js';
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
- ? 'rundll32'
21
+ ? 'start'
23
22
  : 'xdg-open';
24
23
  try {
25
- const arguments_ = process.platform === 'win32' ? ['url.dll,FileProtocolHandler', url] : [url];
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
- const base = normalizeEnvironmentBaseUrl(raw);
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
- return normalizeEnvironmentBaseUrl(raw);
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 base = normalizeEnvironmentBaseUrl(options.backendUrl);
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
- let expiresAt;
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
- const previous = readEnvironmentProfile(globalConfig, backendUrl);
132
- saveEnvironmentProfile(backendUrl, { token: existingToken,
133
- ...(previous?.identity ? { identity: previous.identity } : {}),
134
- ...(expiresAt ? { expiresAt } : {}) });
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', new URL(backendUrl).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) => { body += chunk; if (body.length > 16_384)
163
- req.destroy(); });
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
- return;
174
- }
175
- if (exchanging) {
176
- res.writeHead(409);
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
- if (typeof data.code !== 'string' || !/^[A-Za-z0-9_-]{43}$/.test(data.code)) {
181
- throw new Error('Login callback did not include an authorization code');
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
- exchanging = true;
184
- const base = normalizeEnvironmentBaseUrl(backendUrl);
185
- if (!base)
186
- throw new Error('Invalid environment address');
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, '127.0.0.1', () => {
224
+ server.listen(callbackPort, () => {
266
225
  const address = server.address();
267
226
  const listeningPort = typeof address === 'object' && address ? address.port : callbackPort;
268
- callbackUrl = `http://127.0.0.1:${listeningPort}/callback`;
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`);
@@ -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 ──────────────────────────────────────────────────────────────────
@@ -2,7 +2,6 @@ import { writeFileSync, mkdirSync, readFileSync } from 'fs';
2
2
  import { dirname } from 'path';
3
3
  import { AgentApiClient } from '../utils/agent-api-client.js';
4
4
  import { mimeTypeForImagePath, handleError } from './tools-utils.js';
5
- import { captureGeneratedArtifact } from '../workspace-runtime/workspaces/artifact-receipts.js';
6
5
  const AVATAR_TEMPLATES = [
7
6
  'basketball', 'badminton', 'pingpong', 'gymnastics', 'pilidance',
8
7
  'tennis', 'athletics', 'footballboykicking1', 'footballboykicking2',
@@ -149,9 +148,6 @@ export function register3DCommands(tools) {
149
148
  writeFileSync(opts.savePreview, previewBuf);
150
149
  console.log(` Preview saved: ${opts.savePreview}`);
151
150
  }
152
- await captureGeneratedArtifact(opts.output, 'generate-3d', {
153
- ...(opts.savePreview && result.previewImageBase64 ? { thumbnailPath: opts.savePreview } : {}),
154
- });
155
151
  console.log(`\nNext steps:`);
156
152
  console.log(` Inspect: playcraft 3d info ${opts.output}`);
157
153
  console.log(` Apply texture: playcraft tools generate-texture --model-url <url> --reference-image <img> --output out.glb`);
@@ -213,7 +209,6 @@ export function register3DCommands(tools) {
213
209
  const outDir = dirname(opts.output);
214
210
  mkdirSync(outDir, { recursive: true });
215
211
  writeFileSync(opts.output, buf);
216
- await captureGeneratedArtifact(opts.output, 'generate-texture');
217
212
  const sizeMB = (buf.length / 1024 / 1024).toFixed(2);
218
213
  console.log(`\nTextured model saved: ${opts.output} (${sizeMB}MB, ${elapsed}s)`);
219
214
  if (result.resultUrl)
@@ -258,7 +253,6 @@ export function register3DCommands(tools) {
258
253
  const outDir = dirname(opts.output);
259
254
  mkdirSync(outDir, { recursive: true });
260
255
  writeFileSync(opts.output, buf);
261
- await captureGeneratedArtifact(opts.output, 'retopology');
262
256
  const sizeMB = (buf.length / 1024 / 1024).toFixed(2);
263
257
  console.log(`\nRetopologized model saved: ${opts.output} (${sizeMB}MB, ${elapsed}s)`);
264
258
  }
@@ -295,7 +289,6 @@ export function register3DCommands(tools) {
295
289
  const outDir = dirname(opts.output);
296
290
  mkdirSync(outDir, { recursive: true });
297
291
  writeFileSync(opts.output, buf);
298
- await captureGeneratedArtifact(opts.output, 'uv-unwrap');
299
292
  const sizeMB = (buf.length / 1024 / 1024).toFixed(2);
300
293
  console.log(`\nUV-unwrapped model saved: ${opts.output} (${sizeMB}MB, ${elapsed}s)`);
301
294
  }
@@ -331,7 +324,6 @@ export function register3DCommands(tools) {
331
324
  const outDir = dirname(opts.output);
332
325
  mkdirSync(outDir, { recursive: true });
333
326
  writeFileSync(opts.output, buf);
334
- await captureGeneratedArtifact(opts.output, 'convert-3d');
335
327
  const sizeMB = (buf.length / 1024 / 1024).toFixed(2);
336
328
  console.log(`\nConverted model saved: ${opts.output} (${sizeMB}MB, ${elapsed}s)`);
337
329
  console.log(` Format: ${result.format.toUpperCase()}`);
@@ -367,7 +359,6 @@ export function register3DCommands(tools) {
367
359
  const outDir = dirname(opts.output);
368
360
  mkdirSync(outDir, { recursive: true });
369
361
  writeFileSync(opts.output, buf);
370
- await captureGeneratedArtifact(opts.output, 'generate-3d-parts');
371
362
  const sizeMB = (buf.length / 1024 / 1024).toFixed(2);
372
363
  console.log(`\n3D parts model saved: ${opts.output} (${sizeMB}MB, ${elapsed}s)`);
373
364
  }
@@ -411,7 +402,6 @@ export function register3DCommands(tools) {
411
402
  const outDir = dirname(opts.output);
412
403
  mkdirSync(outDir, { recursive: true });
413
404
  writeFileSync(opts.output, buf);
414
- await captureGeneratedArtifact(opts.output, 'generate-motion');
415
405
  const sizeMB = (buf.length / 1024 / 1024).toFixed(2);
416
406
  console.log(`\nMotion FBX saved: ${opts.output} (${sizeMB}MB, ${elapsed}s)`);
417
407
  }
@@ -473,7 +463,6 @@ export function register3DCommands(tools) {
473
463
  const outDir = dirname(opts.output);
474
464
  mkdirSync(outDir, { recursive: true });
475
465
  writeFileSync(opts.output, buf);
476
- await captureGeneratedArtifact(opts.output, 'generate-avatar');
477
466
  const sizeMB = (buf.length / 1024 / 1024).toFixed(2);
478
467
  console.log(`\n3D avatar saved: ${opts.output} (${sizeMB}MB, ${elapsed}s)`);
479
468
  }