@playcraft/cli 0.0.56 → 0.0.58

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 (228) hide show
  1. package/README.md +41 -26
  2. package/REMIX.md +17 -5
  3. package/dist/cli-root-help.js +1 -0
  4. package/dist/commands/build-all.js +10 -9
  5. package/dist/commands/build.js +13 -12
  6. package/dist/commands/create.js +26 -33
  7. package/dist/commands/platform-skills.generated.js +19 -0
  8. package/dist/commands/remix.js +48 -2
  9. package/dist/commands/skills.js +2 -0
  10. package/dist/commands/tools-generation.js +1 -1
  11. package/dist/commands/workspace-runtime.js +54 -0
  12. package/dist/index.js +3 -1
  13. package/dist/project-skills/commands.js +72 -0
  14. package/dist/project-skills/lifecycle.js +28 -0
  15. package/dist/project-skills/local-run.js +112 -0
  16. package/dist/project-skills/local-store.js +149 -0
  17. package/dist/project-skills/messages.js +72 -0
  18. package/dist/project-skills/reconcile.js +62 -0
  19. package/dist/project-skills/remote-cache.js +51 -0
  20. package/dist/project-skills/validation.js +19 -0
  21. package/dist/remix/clone.js +4 -1
  22. package/dist/remix/init-template.js +2 -0
  23. package/dist/remix/local-git.js +56 -0
  24. package/dist/remix/pull.js +66 -0
  25. package/dist/remix/push.js +90 -0
  26. package/dist/utils/agent-api-client.js +54 -17
  27. package/dist/utils/tool-operation-journal.js +54 -0
  28. package/dist/workspace-runtime/codex/app-server.js +395 -0
  29. package/dist/workspace-runtime/codex/config-toml.js +25 -0
  30. package/dist/workspace-runtime/codex/jsonrpc-stdio.js +106 -0
  31. package/dist/workspace-runtime/codex/loopback.js +59 -0
  32. package/dist/workspace-runtime/codex/native-adapter.js +3 -0
  33. package/dist/workspace-runtime/main.js +10 -0
  34. package/dist/workspace-runtime/persistence/journal.js +350 -0
  35. package/dist/workspace-runtime/processes/managed-writes.js +69 -0
  36. package/dist/workspace-runtime/serve.js +111 -0
  37. package/dist/workspace-runtime/server/auth.js +21 -0
  38. package/dist/workspace-runtime/server/dispatch.js +861 -0
  39. package/dist/workspace-runtime/server/execution-group.js +88 -0
  40. package/dist/workspace-runtime/server/http.js +561 -0
  41. package/dist/workspace-runtime/server/lock.js +53 -0
  42. package/dist/workspace-runtime/server/types.js +1 -0
  43. package/dist/workspace-runtime/workspaces/context-error.js +2 -0
  44. package/dist/workspace-runtime/workspaces/file-snapshot.js +213 -0
  45. package/dist/workspace-runtime/workspaces/files.js +143 -0
  46. package/dist/workspace-runtime/workspaces/git.js +242 -0
  47. package/dist/workspace-runtime/workspaces/json5-edit.js +170 -0
  48. package/dist/workspace-runtime/workspaces/parameters.js +272 -0
  49. package/dist/workspace-runtime/workspaces/prepare.js +364 -0
  50. package/dist/workspace-runtime/workspaces/registry.js +107 -0
  51. package/dist/workspace-runtime/workspaces/revisions.js +31 -0
  52. package/package.json +6 -3
  53. package/project-template-v2/.claude/agents/artist.md +82 -0
  54. package/project-template-v2/.claude/agents/developer.md +153 -0
  55. package/project-template-v2/.claude/agents/game-designer.md +264 -0
  56. package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +533 -0
  57. package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +153 -0
  58. package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +27 -0
  59. package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +208 -0
  60. package/project-template-v2/.claude/agents/refs/atom-skill-library.md +81 -0
  61. package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +432 -0
  62. package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +252 -0
  63. package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +266 -0
  64. package/project-template-v2/.claude/agents/refs/framework-mda.md +147 -0
  65. package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
  66. package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +88 -0
  67. package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +67 -0
  68. package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
  69. package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +300 -0
  70. package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +495 -0
  71. package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +1141 -0
  72. package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +111 -0
  73. package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
  74. package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +412 -0
  75. package/project-template-v2/.claude/agents/reviewer.md +75 -0
  76. package/project-template-v2/.claude/agents/technical-artist.md +86 -0
  77. package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +243 -0
  78. package/project-template-v2/.claude/hooks/user-prompt.mjs +133 -0
  79. package/project-template-v2/.claude/settings.json +33 -0
  80. package/project-template-v2/.claude/skills/brainstorming/SKILL.md +161 -0
  81. package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
  82. package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +177 -0
  83. package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +354 -0
  84. package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
  85. package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
  86. package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
  87. package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  88. package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +309 -0
  89. package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
  90. package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
  91. package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +205 -0
  92. package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +280 -0
  93. package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
  94. package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
  95. package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +298 -0
  96. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
  97. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
  98. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +324 -0
  99. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +97 -0
  100. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
  101. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +137 -0
  102. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
  103. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
  104. package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
  105. package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +219 -0
  106. package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +373 -0
  107. package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
  108. package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +215 -0
  109. package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +382 -0
  110. package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
  111. package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
  112. package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
  113. package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +167 -0
  114. package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
  115. package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
  116. package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
  117. package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +390 -0
  118. package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +23 -0
  119. package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +39 -0
  120. package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
  121. package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +240 -0
  122. package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +226 -0
  123. package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +308 -0
  124. package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +275 -0
  125. package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +134 -0
  126. package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +142 -0
  127. package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +153 -0
  128. package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +386 -0
  129. package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
  130. package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
  131. package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
  132. package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +102 -0
  133. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
  134. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
  135. package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
  136. package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
  137. package/project-template-v2/.claude/snapshot.mjs +263 -0
  138. package/project-template-v2/.playcraft/skills.lock.json +152 -0
  139. package/project-template-v2/CLAUDE.md +146 -0
  140. package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
  141. package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
  142. package/project-template-v2/assets/bundles/.gitkeep +0 -0
  143. package/project-template-v2/assets/images/bg/.gitkeep +0 -0
  144. package/project-template-v2/assets/images/reference/.gitkeep +0 -0
  145. package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
  146. package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
  147. package/project-template-v2/assets/images/ui/.gitkeep +0 -0
  148. package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
  149. package/project-template-v2/assets/models/.gitkeep +0 -0
  150. package/project-template-v2/docs/harness/iteration-1/context-flow.md +254 -0
  151. package/project-template-v2/docs/harness/iteration-1/generate-flow.md +91 -0
  152. package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +214 -0
  153. package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +75 -0
  154. package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +63 -0
  155. package/project-template-v2/docs/harness/iteration-2/context-flow.md +223 -0
  156. package/project-template-v2/docs/harness/iteration-2/generate-flow.md +129 -0
  157. package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +267 -0
  158. package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +164 -0
  159. package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +115 -0
  160. package/project-template-v2/docs/harness/orchestrator-flow.md +364 -0
  161. package/project-template-v2/docs/project-state.json +60 -0
  162. package/project-template-v2/docs/project-state.md +72 -0
  163. package/project-template-v2/docs/standards/README.md +225 -0
  164. package/project-template-v2/docs/standards/agent-behavior-standards.md +174 -0
  165. package/project-template-v2/docs/standards/artifacts/design-brief.md +19 -0
  166. package/project-template-v2/docs/standards/artifacts/design.md +22 -0
  167. package/project-template-v2/docs/standards/artifacts/game-code.md +41 -0
  168. package/project-template-v2/docs/standards/artifacts/todo-list.md +41 -0
  169. package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +343 -0
  170. package/project-template-v2/game/index.ts +18 -0
  171. package/project-template-v2/globals.d.ts +51 -0
  172. package/project-template-v2/index.css +34 -0
  173. package/project-template-v2/index.html +18 -0
  174. package/project-template-v2/main.ts +9 -0
  175. package/project-template-v2/package.json +46 -0
  176. package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +31 -0
  177. package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +86 -0
  178. package/project-template-v2/skills/_shared/scripts/dod-check.mjs +153 -0
  179. package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +70 -0
  180. package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +91 -0
  181. package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +131 -0
  182. package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +80 -0
  183. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +90 -0
  184. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +93 -0
  185. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +23 -0
  186. package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +230 -0
  187. package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +58 -0
  188. package/project-template-v2/skills/_shared/scripts/state-get.mjs +339 -0
  189. package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +39 -0
  190. package/project-template-v2/skills/_shared/scripts/state-set.mjs +94 -0
  191. package/project-template-v2/skills/_shared/scripts/state-store.mjs +783 -0
  192. package/project-template-v2/skills/_shared/scripts/todo-add.mjs +88 -0
  193. package/project-template-v2/skills/_shared/scripts/todo-get.mjs +130 -0
  194. package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +33 -0
  195. package/project-template-v2/skills/_shared/scripts/todo-set.mjs +47 -0
  196. package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +268 -0
  197. package/project-template-v2/skills/_shared/scripts/verify-env.mjs +285 -0
  198. package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +161 -0
  199. package/project-template-v2/skills/playable-autoplay/SKILL.md +176 -0
  200. package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +4 -0
  201. package/project-template-v2/skills/playable-debug/SKILL.md +116 -0
  202. package/project-template-v2/skills/playable-debug/agents/openai.yaml +4 -0
  203. package/project-template-v2/skills/playable-debug/references/debug-config.md +40 -0
  204. package/project-template-v2/skills/playable-record/SKILL.md +140 -0
  205. package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
  206. package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
  207. package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +425 -0
  208. package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +261 -0
  209. package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
  210. package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +322 -0
  211. package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +105 -0
  212. package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +230 -0
  213. package/project-template-v2/skills/playable-validate/SKILL.md +61 -0
  214. package/project-template-v2/skills/playable-validate/validation-rules.md +14 -0
  215. package/project-template-v2/skills/playable-verify-ui/SKILL.md +63 -0
  216. package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
  217. package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
  218. package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
  219. package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
  220. package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +106 -0
  221. package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
  222. package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
  223. package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
  224. package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
  225. package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
  226. package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
  227. package/project-template-v2/tsconfig.json +20 -0
  228. package/project-template-v2/vite.config.ts +27 -0
package/README.md CHANGED
@@ -5,7 +5,13 @@
5
5
  [![npm version](https://img.shields.io/npm/v/@playcraft/cli.svg)](https://www.npmjs.com/package/@playcraft/cli)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@playcraft/cli.svg)](https://www.npmjs.com/package/@playcraft/cli)
7
7
 
8
- PlayCraft CLI 是一个功能强大的命令行工具,支持本地代码与云端编辑器实时同步,以及将 PlayCanvas/PlayCraft 项目打包为多平台 Playable Ads。
8
+ PlayCraft CLI(Command-Line Interface,命令行工具)支持本地代码与云端编辑器实时同步,以及将 PlayCanvas/PlayCraft 项目打包为多平台 Playable Ads。
9
+
10
+ ## 云端工作台 Runtime
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` 仍用于单项目本地开发,二者不要混用。
13
+
14
+ 实现与模块边界见 [Sandbox Agent Server](./src/workspace-runtime/README.md);契约见 [云端工作台后端架构方案](../../docs/architecture/backend/cloud-workspace/backend-architecture.md#cli-runtime)。
9
15
 
10
16
  ## ✨ 特性
11
17
 
@@ -75,7 +81,7 @@ npx @playcraft/cli start --project <project-id> --daemon
75
81
  npx @playcraft/cli build
76
82
 
77
83
  # 命令行打包
78
- npx @playcraft/cli build --platform facebook --format html --output ./dist
84
+ npx @playcraft/cli build --platform facebook --format zip --output ./dist
79
85
  ```
80
86
 
81
87
  ### 5. 创建并继续编辑 Remix
@@ -93,23 +99,20 @@ playcraft remix start \
93
99
 
94
100
  ### 6. 将 Remix 源码 clone 到本地
95
101
 
102
+ 完整步骤(登录 → clone → commit → push)见:
103
+
104
+ - [Remix 本地 Clone / Commit / Push](../../docs/cli/remix-local-clone-push.md)
105
+
96
106
  ```bash
97
107
  playcraft login
98
- # 本地开发建议直连 backend,避免经前端代理缓冲 Git pack
99
- export PLAYCRAFT_API_URL=http://localhost:3001
100
-
101
108
  # 推荐:粘贴 Remix 详情页 / Editor / 工蜂分支页 URL
102
109
  playcraft remix clone '<remix-detail-or-editor-or-gongfeng-url>' --install
103
110
 
104
- # 兼容:显式 project + branch
105
- playcraft remix clone \
106
- --project-id <project-id> \
107
- --branch remix/your-branch \
108
- --install
109
-
110
111
  cd <cloned-dir>
111
112
  npm run dev # external 引擎
112
- git push # 经 PlayCraft Git 代理写回 Remix 分支(禁止推 main)
113
+ git add -A && git commit -m "…"
114
+ playcraft remix pull # 需要同步远端时
115
+ playcraft remix push # 不要裸 git push/pull(尤其 Windows)
113
116
  ```
114
117
 
115
118
  完整的 Remix 子命令、参数、图片传输、自动化输出及故障处理说明见:
@@ -185,6 +188,18 @@ echo '{"token":"<sandbox-jwt>","apiUrl":"https://..."}' > .playcraft.json
185
188
  | `recommend improvements` | Tag 改进建议 | `playcraft recommend improvements --channel Facebook` |
186
189
  | `recommend random` | 随机 Tag 组合推荐 | `playcraft recommend random --channel Google` |
187
190
 
191
+ ### 业务工具请求恢复
192
+
193
+ 业务工具写请求要求服务支持持久操作协议。命令行先保存请求编号、路径和输入摘要到 `~/.playcraft/tool-requests/`,再发送请求;记录不包含凭证或请求正文。可用绝对路径环境变量 `PLAYCRAFT_TOOL_REQUEST_DIR` 指定可持久保留的目录。
194
+
195
+ 如果请求超时或连接中断,错误会显示请求编号。使用相同参数重跑命令,并设置该编号,只查询原操作的确定结果:
196
+
197
+ ```bash
198
+ PLAYCRAFT_TOOL_REQUEST_ID=<错误中显示的请求编号> playcraft tools build-project --project-id <原项目编号>
199
+ ```
200
+
201
+ 恢复不会重新构建。操作尚未完成、结果未知或没有回执时会明确失败;不要换编号或删除记录来强行重试。只有错误明确说明能力检查失败且尚未发送操作时,才可在服务恢复后发起新的正常命令。服务不兼容时命令会在发送业务请求前停止;沙箱命令行与 Business 须排空旧调用后同步升级。
202
+
188
203
  ### 构建相关
189
204
 
190
205
  | 命令 | 说明 | 示例 |
@@ -198,18 +213,18 @@ echo '{"token":"<sandbox-jwt>","apiUrl":"https://..."}' > .playcraft.json
198
213
 
199
214
  现已支持 **10 个主流广告平台**:
200
215
 
201
- | 平台 | 格式 | 大小限制 | SDK/API |
202
- | ----------------- | -------- | ---------------------------------- | ------------ |
203
- | **Facebook** | HTML/ZIP | HTML: 5MB / ZIP: 5MB(HTML < 2MB) | FbPlayableAd |
204
- | **Snapchat** | ZIP | 5MB | MRAID 2.0 |
205
- | **ironSource** | HTML | 5MB | MRAID + dapi |
206
- | **AppLovin** | HTML | 5MB | MRAID 2.0 |
207
- | **Google Ads** | ZIP | 5MB | ExitApi |
208
- | **TikTok/Pangle** | ZIP | 5MB | Pangle SDK |
209
- | **Unity Ads** | HTML | 5MB | MRAID 2.0 |
210
- | **Liftoff** | ZIP | 5MB | MRAID |
211
- | **Moloco** | HTML | 5MB | FbPlayableAd |
212
- | **BIGO Ads** | ZIP | 5MB | BIGO SDK |
216
+ | 平台 | 格式 | 大小限制 | SDK/API |
217
+ | ----------------- | -------- | -------------------- | ------------ |
218
+ | **Facebook** | HTML/ZIP | HTML: 5MB / ZIP: 5MB | FbPlayableAd |
219
+ | **Snapchat** | ZIP | 5MB | MRAID 2.0 |
220
+ | **ironSource** | HTML | 5MB | MRAID + dapi |
221
+ | **AppLovin** | HTML | 5MB | MRAID 2.0 |
222
+ | **Google Ads** | ZIP | 5MB | ExitApi |
223
+ | **TikTok/Pangle** | ZIP | 5MB | Pangle SDK |
224
+ | **Unity Ads** | HTML | 5MB | MRAID 2.0 |
225
+ | **Liftoff** | ZIP | 5MB | MRAID |
226
+ | **Moloco** | HTML | 5MB | FbPlayableAd |
227
+ | **BIGO Ads** | ZIP | 5MB | BIGO SDK |
213
228
 
214
229
  ## 💡 使用示例
215
230
 
@@ -228,8 +243,8 @@ playcraft start --project your-project-id
228
243
  ### 打包 Playable Ads
229
244
 
230
245
  ```bash
231
- # Facebook 平台(单 HTML)
232
- playcraft build --platform facebook --format html --output ./dist/facebook
246
+ # Facebook 平台(ZIP,Phaser 产物格式)
247
+ playcraft build --platform facebook --format zip --output ./dist/facebook
233
248
 
234
249
  # Snapchat 平台(ZIP)
235
250
  playcraft build --platform snapchat --format zip --output ./dist/snapchat
package/REMIX.md CHANGED
@@ -24,6 +24,8 @@ playcraft remix start
24
24
  playcraft remix prompt
25
25
  playcraft remix run
26
26
  playcraft remix clone
27
+ playcraft remix pull
28
+ playcraft remix push
27
29
  playcraft git-credential
28
30
  ```
29
31
 
@@ -36,6 +38,8 @@ playcraft git-credential
36
38
  | 向已有 Remix 发送需求 | `playcraft remix prompt` |
37
39
  | 创建 Remix 并立即运行 Agent | `playcraft remix run` |
38
40
  | **Clone Remix 源码到本地** | `playcraft remix clone <详情页/Editor/工蜂 URL>` 或 `--project-id` + `--branch` |
41
+ | **Pull 远端 Remix** | `playcraft remix pull`(推荐;Windows 勿直接 `git pull`) |
42
+ | **Push 回 Remix 分支** | `playcraft remix push`(推荐;Windows 勿直接 `git push`) |
39
43
  | 查询已有 Remix 列表 | `playcraft tools list-remixes`;当前没有 `playcraft remix list` |
40
44
  | 给本地项目应用引擎模板 | `playcraft remix init-template` |
41
45
 
@@ -725,6 +729,8 @@ playcraft remix start --project-id <project-id> --branch <remix-branch> --open
725
729
 
726
730
  登录后可将 Remix 源码经 **PlayCraft Backend Git Smart HTTP 代理**克隆到本机,无需工蜂凭据。平台服务账号 Token 不会下发到 CLI。
727
731
 
732
+ > **上手文档(推荐先读)**:[Remix 本地 Clone / Commit / Push](../../docs/cli/remix-local-clone-push.md)
733
+
728
734
  ### 14.1 Clone
729
735
 
730
736
  ```bash
@@ -772,17 +778,23 @@ playcraft remix clone \
772
778
  - **external(Phaser / Three.js)**:`npm install && npm run dev`(可用 `--install` / `--dev`)
773
779
  - **PlayCanvas**:使用 `playcraft start --project <id>`,不是 Vite
774
780
 
775
- ### 14.3 Push 回 Remix
781
+ ### 14.3 Pull / Push
776
782
 
777
783
  在克隆目录内:
778
784
 
779
785
  ```bash
786
+ # 同步远端(例如沙箱 Save 之后)
787
+ playcraft remix pull
788
+
789
+ # 本地改完并 commit 后写回
780
790
  git add -A
781
791
  git commit -m "local changes"
782
- git push
792
+ playcraft remix push
783
793
  ```
784
794
 
785
- 服务端强制:
795
+ **不要**依赖裸 `git pull` / `git push`(尤其 Windows + Git Credential Manager 会弹窗)。二者与 clone 一样注入 `Authorization: Bearer`,并禁用本命令的 credential helper。
796
+
797
+ 服务端强制(push):
786
798
 
787
799
  - 只能 push 到 URL 对应的 Remix 分支
788
800
  - 禁止 push `main` / `master` / 项目默认分支
@@ -791,11 +803,11 @@ git push
791
803
 
792
804
  ### 14.4 与云端沙箱同时写
793
805
 
794
- 同一 Remix 分支若已在沙箱打开并 Save,本机 `git push` 与沙箱 push 会互相覆盖。请避免两边同时写同一分支;push 成功后 backend 会 `BareRepoCache.invalidate`。
806
+ 同一 Remix 分支若已在沙箱打开并 Save,本机 `playcraft remix push` 与沙箱 push 会互相覆盖。请避免两边同时写同一分支;需要合并远端时先 `playcraft remix pull`。push 成功后 backend 会 `BareRepoCache.invalidate`。
795
807
 
796
808
  ### 14.5 `playcraft git-credential`
797
809
 
798
- 供本机 `git pull` / `git push` 使用的 credential helper,从 `~/.playcraft/config.json` 读取 PAT。clone 后会自动写入仓库 `credential.helper`。
810
+ clone 后仍可能写入仓库 `credential.helper`(兼容)。**日常请用 `playcraft remix pull` / `push`**,不要手动跑 `git-credential`。
799
811
 
800
812
  ---
801
813
 
@@ -7,6 +7,7 @@ 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 引导配置启动)',
10
11
  '',
11
12
  '也可运行: playcraft topics',
12
13
  '',
@@ -33,12 +33,12 @@ const PLATFORM_GROUPS = {
33
33
  platforms: [...ALL_PLATFORMS],
34
34
  },
35
35
  html: {
36
- name: '仅 HTML 渠道 (applovin, ironsource, unity, moloco, remerge, adikteev)',
37
- platforms: ['applovin', 'ironsource', 'unity', 'moloco', 'remerge', 'adikteev'],
36
+ name: '仅 HTML 渠道 (applovin, ironsource, unity, moloco, adikteev)',
37
+ platforms: ['applovin', 'ironsource', 'unity', 'moloco', 'adikteev'],
38
38
  },
39
39
  zip: {
40
- name: '仅 ZIP 渠道 (google, tiktok, liftoff, bigo, snapchat, inmobi, mintegral)',
41
- platforms: ['google', 'tiktok', 'liftoff', 'bigo', 'snapchat', 'inmobi', 'mintegral'],
40
+ name: '仅 ZIP 渠道 (google, tiktok, liftoff, bigo, snapchat, inmobi, mintegral, remerge)',
41
+ platforms: ['google', 'tiktok', 'liftoff', 'bigo', 'snapchat', 'inmobi', 'mintegral', 'remerge'],
42
42
  },
43
43
  mainstream: {
44
44
  name: '主流渠道 (facebook, google, tiktok, applovin, ironsource, unity)',
@@ -55,7 +55,7 @@ const platformFormatConfig = {
55
55
  unity: { formats: ['html'], default: 'html' },
56
56
  moloco: { formats: ['html'], default: 'html' },
57
57
  adikteev: { formats: ['html', 'zip'], default: 'html', description: 'PlayCanvas/PlayCraft uses HTML, others use ZIP' },
58
- remerge: { formats: ['html'], default: 'html' },
58
+ remerge: { formats: ['zip'], default: 'zip' },
59
59
  google: { formats: ['html', 'zip'], default: 'html' },
60
60
  tiktok: { formats: ['zip'], default: 'zip' },
61
61
  liftoff: { formats: ['zip'], default: 'zip' },
@@ -164,10 +164,11 @@ export async function buildAllCommand(projectPath, options) {
164
164
  name: 'selection',
165
165
  message: '选择要批量构建的渠道:',
166
166
  choices: [
167
- { name: '🌐 全部渠道(13个)', value: 'all' },
168
- { name: '⭐ 主流渠道(facebook, google, tiktok, applovin, ironsource, unity)', value: 'mainstream' },
169
- { name: '📄 仅 HTML 渠道(applovin, ironsource, unity, moloco, remerge)', value: 'html' },
170
- { name: '📦 仅 ZIP 渠道(tiktok, liftoff, bigo, snapchat, inmobi)', value: 'zip' },
167
+ { name: `🌐 全部渠道(${ALL_PLATFORMS.length}个)`, value: 'all' },
168
+ // 分组文案直接取自 PLATFORM_GROUPS,避免两处渠道清单各写一份导致漂移
169
+ { name: `⭐ ${PLATFORM_GROUPS.mainstream.name}`, value: 'mainstream' },
170
+ { name: `📄 ${PLATFORM_GROUPS.html.name}`, value: 'html' },
171
+ { name: `📦 ${PLATFORM_GROUPS.zip.name}`, value: 'zip' },
171
172
  { name: '🔧 自定义选择', value: 'custom' },
172
173
  ],
173
174
  },
@@ -466,21 +466,20 @@ export async function buildCommand(projectPath, options) {
466
466
  'mintegral',
467
467
  ];
468
468
  // 渠道输出格式配置(根据各渠道Playable规格对照表)
469
- // 只支持 HTML: applovin, ironsource, unity, moloco, adikteev, remerge
470
- // 只支持 ZIP: bigo, snapchat
471
- // 支持两种: facebook, google, tiktok, liftoff, inmobi, mintegral
469
+ // 单格式(ZIP): bigo, snapchat, remerge
470
+ // 单格式(HTML): applovin, ironsource, unity, moloco
471
+ // 双格式: facebook, google, tiktok, liftoff, inmobi, mintegral
472
+ // adikteev: 由引擎决定(PlayCanvas/PlayCraft 用 HTML,其他引擎用 ZIP)
473
+ // 注:Facebook 在 Phaser(playable-scripts devkit)下的产物格式由其 devkit 输入配置决定(恒为 ZIP),
474
+ // 平台侧不在此处做引擎判断。
472
475
  const platformFormatConfig = {
473
- facebook: {
474
- formats: ['html', 'zip'],
475
- default: 'html',
476
- description: 'Facebook 支持两种格式'
477
- },
476
+ facebook: { formats: ['html', 'zip'], default: 'html' },
478
477
  applovin: { formats: ['html'], default: 'html' },
479
478
  ironsource: { formats: ['html'], default: 'html' },
480
479
  unity: { formats: ['html'], default: 'html' },
481
480
  moloco: { formats: ['html'], default: 'html' },
482
481
  adikteev: { formats: ['html', 'zip'], default: 'html', description: 'PlayCanvas/PlayCraft uses HTML, others use ZIP' },
483
- remerge: { formats: ['html'], default: 'html' },
482
+ remerge: { formats: ['zip'], default: 'zip' },
484
483
  google: {
485
484
  formats: ['html', 'zip'],
486
485
  default: 'html',
@@ -532,9 +531,11 @@ export async function buildCommand(projectPath, options) {
532
531
  ? (selectedPlatform === 'facebook' || selectedPlatform === 'google'
533
532
  ? 'HTML(单文件,最大 5MB,所有资源内联)'
534
533
  : 'HTML(单文件)')
535
- : (selectedPlatform === 'facebook' || selectedPlatform === 'google'
536
- ? 'ZIP(多文件,最大 5MB,HTML 文件需 < 2MB)'
537
- : 'ZIP(多文件)'),
534
+ : (selectedPlatform === 'google'
535
+ ? 'ZIP(多文件,最大 5MB,ZIP 内文件数 ≤ 512)'
536
+ : selectedPlatform === 'facebook'
537
+ ? 'ZIP(多文件,最大 5MB)'
538
+ : 'ZIP(多文件)'),
538
539
  value: f,
539
540
  })),
540
541
  default: formatConfig.default,
@@ -1,3 +1,4 @@
1
+ import { prepareLocalSkillLifecycle } from '../project-skills/lifecycle.js';
1
2
  import { execFileSync, execSync } from 'child_process';
2
3
  import inquirer from 'inquirer';
3
4
  import fs from 'fs/promises';
@@ -6,8 +7,11 @@ import { fileURLToPath } from 'url';
6
7
  import pc from 'picocolors';
7
8
  import ora from 'ora';
8
9
  import { resolveCreateTemplate, resolveCreateTemplateDir, } from '../scaffold/templates.js';
10
+ import { PLATFORM_SKILL_DIRS } from './platform-skills.generated.js';
9
11
  const __filename = fileURLToPath(import.meta.url);
10
12
  const __dirname = path.dirname(__filename);
13
+ /** `@playcraft/skills` 包内 Platform Skill 的目录名(与 Atom Skill 的 `skills/` 区分)。 */
14
+ const PLATFORM_SKILLS_DIRNAME = 'playcraft-skills';
11
15
  /** 生成一个本地占位 Project ID(99xxxxxx),后续可通过 playcraft config set 更新为真实 ID */
12
16
  function generateMockProjectId() {
13
17
  const suffix = Math.floor(Math.random() * 90_000_000) + 10_000_000;
@@ -849,7 +853,7 @@ function extractSkillBodyForCursor(content) {
849
853
  * @param cliCommandsDir CLI 命令所在目录(用于解析 skills 包位置)
850
854
  * @param configDir 配置目录名(如 '.claude' 或 '.codebuddy')
851
855
  */
852
- async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, configDir) {
856
+ export async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, configDir) {
853
857
  const skillsLinkDir = path.join(targetDir, configDir, 'skills');
854
858
  await fs.mkdir(skillsLinkDir, { recursive: true });
855
859
  // 以下 Skill 在项目模板中以静态目录形式存在,不创建软连接覆盖它们。
@@ -868,11 +872,12 @@ async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, configDir
868
872
  'playcraft-image-generation',
869
873
  'playcraft-audio-generation',
870
874
  ]);
871
- // 尝试从 CLI 安装包的位置定位 @playcraft/skills/skills 目录
875
+ // Platform Skill 住在 playcraft-skills/,与 Atom Skill 的 skills/ 是两个目录。
876
+ // 尝试从 CLI 安装包的位置定位它(monorepo 内或与 CLI 平级安装时可解析)。
872
877
  const candidateDirs = [
873
- path.resolve(cliCommandsDir, '..', '..', '..', '..', 'skills', 'skills'),
874
- path.resolve(cliCommandsDir, '..', '..', '..', 'skills', 'skills'),
875
- path.resolve(cliCommandsDir, '..', '..', 'skills', 'skills'),
878
+ path.resolve(cliCommandsDir, '..', '..', '..', '..', 'skills', PLATFORM_SKILLS_DIRNAME),
879
+ path.resolve(cliCommandsDir, '..', '..', '..', 'skills', PLATFORM_SKILLS_DIRNAME),
880
+ path.resolve(cliCommandsDir, '..', '..', 'skills', PLATFORM_SKILLS_DIRNAME),
876
881
  ];
877
882
  let resolvedSkillsDir = null;
878
883
  for (const dir of candidateDirs) {
@@ -885,18 +890,24 @@ async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, configDir
885
890
  // 继续下一个候选
886
891
  }
887
892
  }
888
- // 相对路径(指向 npm install 后的 node_modules)始终创建,作为安装后激活的备用
889
- const relativeSkillsBase = path.join('..', '..', 'node_modules', '@playcraft', 'skills', 'skills');
893
+ // 相对路径(指向 npm install 后的 node_modules)作为安装后激活的备用
894
+ const relativeSkillsBase = path.join('..', '..', 'node_modules', '@playcraft', 'skills', PLATFORM_SKILLS_DIRNAME);
890
895
  if (resolvedSkillsDir) {
891
- // 能立即解析 → 创建指向绝对路径的软连接,当下即可使用
896
+ // 能立即解析 → 以真实目录为准创建绝对路径软连接,当下即可使用。
897
+ // 按「是否含 SKILL.md」判定而非 playcraft- 前缀:sound-effects 无前缀但同样是平台技能。
892
898
  const entries = await fs.readdir(resolvedSkillsDir, { withFileTypes: true });
893
899
  for (const entry of entries) {
894
- if (!entry.name.startsWith('playcraft-') || staticSkills.has(entry.name))
900
+ if (!entry.isDirectory() || staticSkills.has(entry.name))
895
901
  continue;
896
- const linkPath = path.join(skillsLinkDir, entry.name);
897
902
  const targetPath = path.join(resolvedSkillsDir, entry.name);
898
903
  try {
899
- await fs.symlink(targetPath, linkPath, 'dir');
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');
900
911
  }
901
912
  catch {
902
913
  // 已存在则跳过
@@ -904,28 +915,9 @@ async function setupPlatformSkillLinksInner(targetDir, cliCommandsDir, configDir
904
915
  }
905
916
  }
906
917
  else {
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) {
918
+ // 无法立即解析 → 指向 node_modules 的相对路径软连接,npm install 后自动激活。
919
+ // 清单由 scripts/generate-platform-skills.mjs 从真实目录生成并由 CI 校验,不要手写。
920
+ for (const name of PLATFORM_SKILL_DIRS) {
929
921
  if (staticSkills.has(name))
930
922
  continue;
931
923
  const linkPath = path.join(skillsLinkDir, name);
@@ -1289,6 +1281,7 @@ export async function createCommand(projectName, options) {
1289
1281
  smokeSpinner.warn(`Harness 自检跳过: ${message}`);
1290
1282
  }
1291
1283
  }
1284
+ await prepareLocalSkillLifecycle(targetDir, 'create');
1292
1285
  const gitSpinner = ora(isWorktreeMode ? '提交项目分支...' : '初始化 Git 仓库...').start();
1293
1286
  try {
1294
1287
  if (isWorktreeMode) {
@@ -0,0 +1,19 @@
1
+ // 此文件由 scripts/generate-platform-skills.mjs 生成,请勿手改。
2
+ // 重新生成:pnpm --filter @playcraft/cli generate:platform-skills
3
+ /** `@playcraft/skills/playcraft-skills/` 下的 Platform Skill 目录名。 */
4
+ export const PLATFORM_SKILL_DIRS = [
5
+ 'playcraft-3d-flip-sprite',
6
+ 'playcraft-asset-management',
7
+ 'playcraft-build',
8
+ 'playcraft-code-editor',
9
+ 'playcraft-create-remix',
10
+ 'playcraft-deploy',
11
+ 'playcraft-iteration-methodology',
12
+ 'playcraft-platform-intro',
13
+ 'playcraft-prefab',
14
+ 'playcraft-project-management',
15
+ 'playcraft-remix-workflow',
16
+ 'playcraft-save',
17
+ 'playcraft-template-upgrade-merge',
18
+ 'sound-effects',
19
+ ];
@@ -6,6 +6,8 @@ import { PlayCraftApiError, PlayCraftHttpClient, isPlayCraftApiError } from '../
6
6
  import { IMAGE_OPTION_HELP, buildReferenceImagesPrompt, readImageAttachments, uploadImageAttachments, } from '../utils/remix-image-attachments.js';
7
7
  import { initTemplateCommand } from '../remix/init-template.js';
8
8
  import { remixClone, gitCredentialCommand, isRemoteCloneSource } from '../remix/clone.js';
9
+ import { remixPush } from '../remix/push.js';
10
+ import { remixPull } from '../remix/pull.js';
9
11
  // Register autocomplete prompt
10
12
  inquirer.registerPrompt('autocomplete', autocomplete);
11
13
  const JSON_OUTPUT_HELP = '输出一条 JSON (JavaScript Object Notation, JavaScript 对象表示法) 结果';
@@ -1303,12 +1305,56 @@ export function registerRemixCommands(program) {
1303
1305
  handleCommandError('remix.clone', opts, undefined, error);
1304
1306
  }
1305
1307
  });
1308
+ remix
1309
+ .command('push')
1310
+ .description('经 PlayCraft Git 代理推送当前 Remix(注入已登录 PAT,避免 Windows Git Credential Manager 弹窗)')
1311
+ .argument('[git-args...]', '透传给 git push 的参数(可选)')
1312
+ .option('--dir <path>', '仓库目录(默认当前目录)')
1313
+ .option('--url <url>', SERVICE_ADDRESS_HELP)
1314
+ .option('--token <token>', PAT_HELP)
1315
+ .option('--json', JSON_OUTPUT_HELP)
1316
+ .action(async (gitArgs, opts) => {
1317
+ try {
1318
+ await remixPush({
1319
+ dir: opts.dir ? String(opts.dir) : undefined,
1320
+ url: opts.url,
1321
+ token: opts.token,
1322
+ json: Boolean(opts.json),
1323
+ gitArgs: Array.isArray(gitArgs) ? gitArgs.map(String) : [],
1324
+ });
1325
+ }
1326
+ catch (error) {
1327
+ handleCommandError('remix.push', opts, undefined, error);
1328
+ }
1329
+ });
1330
+ remix
1331
+ .command('pull')
1332
+ .description('经 PlayCraft Git 代理拉取当前 Remix(注入已登录 PAT,避免 Windows Git Credential Manager 弹窗)')
1333
+ .argument('[git-args...]', '透传给 git pull 的参数(可选)')
1334
+ .option('--dir <path>', '仓库目录(默认当前目录)')
1335
+ .option('--url <url>', SERVICE_ADDRESS_HELP)
1336
+ .option('--token <token>', PAT_HELP)
1337
+ .option('--json', JSON_OUTPUT_HELP)
1338
+ .action(async (gitArgs, opts) => {
1339
+ try {
1340
+ await remixPull({
1341
+ dir: opts.dir ? String(opts.dir) : undefined,
1342
+ url: opts.url,
1343
+ token: opts.token,
1344
+ json: Boolean(opts.json),
1345
+ gitArgs: Array.isArray(gitArgs) ? gitArgs.map(String) : [],
1346
+ });
1347
+ }
1348
+ catch (error) {
1349
+ handleCommandError('remix.pull', opts, undefined, error);
1350
+ }
1351
+ });
1306
1352
  }
1307
- /** Register `playcraft git-credential` for local git pull/push after remix clone. */
1353
+ /** Register `playcraft git-credential`(clone 写入的 helper;拉/推请用 remix pull / push). */
1308
1354
  export function registerGitCredentialCommand(program) {
1309
1355
  program
1310
1356
  .command('git-credential')
1311
- .description('Git credential helper:从登录配置提供 PlayCraft PAT')
1357
+ .description('Git credential helper(一般勿手动调用;请用 playcraft remix pull / push)')
1312
1358
  .argument('[action]', 'get | store | erase', 'get')
1313
1359
  .action((action) => {
1314
1360
  gitCredentialCommand(action);
@@ -18,6 +18,7 @@
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';
21
22
  import * as fs from 'node:fs';
22
23
  import * as path from 'node:path';
23
24
  import { getFusionHintsForGameplayAtoms, } from '../atom-tree/fusion-hints.js';
@@ -1430,6 +1431,7 @@ export function registerSkillsCommands(program) {
1430
1431
  const skills = program
1431
1432
  .command('skills')
1432
1433
  .description('开发时 Skill 发现与脚手架工具(按 engine/intent 推荐 skill 集合,或将 ref 文件复制到项目)');
1434
+ registerProjectSkillsCommands(skills);
1433
1435
  // 公共选项:skills 目录
1434
1436
  const addSkillsDirOption = (cmd) => cmd.option('--skills-dir <path>', '指定 skills 目录路径(默认自动发现)');
1435
1437
  // ── list ──────────────────────────────────────────────────────────────────
@@ -125,7 +125,7 @@ export function registerGenerationCommands(tools) {
125
125
  }
126
126
  console.log('');
127
127
  console.log('提示:传入模型名(如 gpt-image-2),后端按优先级依次 fallback 各 provider(gpt-image-2:iegg-litellm → mulerouter → 302)。');
128
- console.log(' 也可传入 provider/model(如 mulerouter/gpt-image-2)直连指定 provider。');
128
+ console.log(' 也可传入 provider/model(如 mulerouter/gpt-image-2、gamepilot/dreamina/dola-seedream-5-0-pro-260628)直连指定 provider。');
129
129
  console.log('');
130
130
  console.log('CAPABILITY 说明:');
131
131
  console.log(' text→image 仅支持文生图(不可传 --reference-image)');
@@ -0,0 +1,54 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { INCOMPATIBLE_EXIT_CODE, parseSandboxRuntimeConfig, } from '@playcraft/common/cloud-workspace/runtime';
3
+ import { startWorkspaceRuntime } from '../workspace-runtime/serve.js';
4
+ export async function runWorkspaceRuntimeServe(configPath) {
5
+ process.env.PLAYCRAFT_SKIP_UPDATE_CHECK = '1';
6
+ let config;
7
+ try {
8
+ config = parseSandboxRuntimeConfig(JSON.parse(await readFile(configPath, 'utf8')));
9
+ }
10
+ catch (error) {
11
+ const message = error instanceof Error ? error.message : String(error);
12
+ console.error(`workspace-runtime config invalid: ${message}`);
13
+ process.exitCode = INCOMPATIBLE_EXIT_CODE;
14
+ return;
15
+ }
16
+ try {
17
+ const runtime = await startWorkspaceRuntime(config);
18
+ console.log(JSON.stringify({
19
+ status: 'listening',
20
+ url: runtime.url,
21
+ phase: 'awaiting_native',
22
+ protocolMajor: runtime.config.protocolMajor,
23
+ protocolMinor: runtime.config.protocolMinor,
24
+ }));
25
+ await new Promise((resolve) => {
26
+ const stop = () => {
27
+ void runtime.close().finally(resolve);
28
+ };
29
+ process.once('SIGINT', stop);
30
+ process.once('SIGTERM', stop);
31
+ });
32
+ }
33
+ catch (error) {
34
+ const code = error.code;
35
+ if (code === 'protocol_incompatible' || code === 'duplicate_instance') {
36
+ console.error(error instanceof Error ? error.message : code);
37
+ process.exitCode = INCOMPATIBLE_EXIT_CODE;
38
+ return;
39
+ }
40
+ throw error;
41
+ }
42
+ }
43
+ export function registerWorkspaceRuntimeCommands(program) {
44
+ const workspaceRuntime = program
45
+ .command('workspace-runtime')
46
+ .description('沙箱内 Sandbox Agent Server(Cloud Workspace 常驻运行入口)');
47
+ workspaceRuntime
48
+ .command('serve')
49
+ .description('前台常驻:读取 Runtime Server 下发的配置,不启动本地 backend 或旧同步')
50
+ .requiredOption('--config <path>', 'Runtime 引导配置 JSON')
51
+ .action(async (options) => {
52
+ await runWorkspaceRuntimeServe(options.config);
53
+ });
54
+ }
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ import { registerLevelsCommands } from './commands/levels.js';
27
27
  import { registerPatternsCommands } from './commands/patterns.js';
28
28
  import { registerPradCommands } from './commands/prad.js';
29
29
  import { register3DCommands } from './commands/3d.js';
30
+ import { registerWorkspaceRuntimeCommands } from './commands/workspace-runtime.js';
30
31
  import { CLI_ROOT_DESCRIPTION, getCliTopicsHelpText, registerRootProgramHelp, } from './cli-root-help.js';
31
32
  const __filename = fileURLToPath(import.meta.url);
32
33
  const __dirname = dirname(__filename);
@@ -36,7 +37,7 @@ program.name('playcraft').description(CLI_ROOT_DESCRIPTION).version(packageJson.
36
37
  registerRootProgramHelp(program);
37
38
  // 版本检查(非阻塞,后台执行)
38
39
  // 只在非 upgrade 命令时检查,避免重复提示
39
- if (!process.argv.includes('upgrade')) {
40
+ if (!process.argv.includes('upgrade') && !process.argv.includes('workspace-runtime')) {
40
41
  checkForUpdates(packageJson);
41
42
  }
42
43
  // create 命令
@@ -368,4 +369,5 @@ registerPatternsCommands(program);
368
369
  registerPradCommands(program);
369
370
  // 3D model utilities (playcraft 3d <command>)
370
371
  register3DCommands(program);
372
+ registerWorkspaceRuntimeCommands(program);
371
373
  program.parse(process.argv);