@playcraft/cli 0.1.41-prod → 0.1.43-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -3
- package/SKILLS_REGISTRY.md +149 -0
- package/dist/agent/local-backend.js +1 -1
- package/dist/auth/account-activation.js +157 -0
- package/dist/auth/messages.js +30 -0
- package/dist/cli-root-help.js +2 -0
- package/dist/commands/build-all.js +5 -19
- package/dist/commands/build-temp.js +26 -0
- package/dist/commands/build.js +15 -28
- package/dist/commands/create.js +26 -33
- package/dist/commands/image.js +2 -6
- package/dist/commands/login.js +84 -42
- package/dist/commands/platform-skills.generated.js +19 -0
- package/dist/commands/playable.js +53 -0
- package/dist/commands/skills.js +4 -0
- package/dist/commands/tools-3d.js +11 -0
- package/dist/commands/tools-batch.js +87 -0
- package/dist/commands/tools-generation.js +69 -137
- package/dist/commands/tools-utils.js +0 -12
- package/dist/commands/tools.js +2 -2
- package/dist/commands/video.js +122 -0
- package/dist/commands/workspace-runtime.js +54 -0
- package/dist/commands/workspace.js +40 -0
- package/dist/config.js +59 -4
- package/dist/index.js +40 -3
- package/dist/project-skills/builtin-import.js +225 -0
- package/dist/project-skills/commands.js +77 -0
- package/dist/project-skills/lifecycle.js +28 -0
- package/dist/project-skills/local-run.js +112 -0
- package/dist/project-skills/local-store.js +221 -0
- package/dist/project-skills/messages.js +80 -0
- package/dist/project-skills/reconcile.js +62 -0
- package/dist/project-skills/remote-cache.js +51 -0
- package/dist/project-skills/validation.js +19 -0
- package/dist/recording/messages.js +40 -0
- package/dist/recording/project-digest.js +85 -0
- package/dist/recording/recorder.js +293 -0
- package/dist/recording/scenario.js +50 -0
- package/dist/remix/clone.js +2 -0
- package/dist/remix/init-template.js +2 -0
- package/dist/remix/pull.js +2 -0
- package/dist/remix/push.js +21 -1
- package/dist/skill-registry/client.js +345 -0
- package/dist/skill-registry/commands.js +180 -0
- package/dist/skill-registry/evaluation-client.js +156 -0
- package/dist/skill-registry/evaluation-commands.js +174 -0
- package/dist/skill-registry/messages.js +177 -0
- package/dist/skill-registry/package.js +275 -0
- package/dist/skill-registry/platform-package.js +100 -0
- package/dist/utils/agent-api-client.js +210 -30
- package/dist/utils/environment-endpoints.js +17 -0
- package/dist/utils/error-diagnostics.js +20 -0
- package/dist/utils/playcraft-http-client.js +6 -4
- package/dist/utils/tool-operation-journal.js +124 -0
- package/dist/utils/video-evidence-git.js +81 -0
- package/dist/video-replication/client.js +234 -0
- package/dist/video-replication/comparison-evidence.js +149 -0
- package/dist/video-replication/comparison-files.js +57 -0
- package/dist/video-replication/comparison-log.js +72 -0
- package/dist/video-replication/comparison-messages.js +104 -0
- package/dist/video-replication/comparison-output.js +63 -0
- package/dist/video-replication/comparison-preflight.js +66 -0
- package/dist/video-replication/comparison.js +230 -0
- package/dist/video-replication/diagnostics.js +41 -0
- package/dist/video-replication/evidence.js +165 -0
- package/dist/video-replication/media.js +112 -0
- package/dist/video-replication/messages.js +97 -0
- package/dist/workspace/messages.js +67 -0
- package/dist/workspace/transfer-client.js +233 -0
- package/dist/workspace/transfer-errors.js +48 -0
- package/dist/workspace-runtime/codex/app-server.js +1040 -0
- package/dist/workspace-runtime/codex/compact.js +46 -0
- package/dist/workspace-runtime/codex/config-toml.js +107 -0
- package/dist/workspace-runtime/codex/jsonrpc-stdio.js +145 -0
- package/dist/workspace-runtime/codex/launcher-client.js +177 -0
- package/dist/workspace-runtime/codex/loopback.js +146 -0
- package/dist/workspace-runtime/codex/mcp-config.js +39 -0
- package/dist/workspace-runtime/codex/model-broker.js +263 -0
- package/dist/workspace-runtime/codex/native-adapter.js +9 -0
- package/dist/workspace-runtime/codex/permissions.js +70 -0
- package/dist/workspace-runtime/codex/thread-image.js +38 -0
- package/dist/workspace-runtime/codex/ui-instructions.js +4 -0
- package/dist/workspace-runtime/codex/ui-tools.js +186 -0
- package/dist/workspace-runtime/codex/work-mode.js +15 -0
- package/dist/workspace-runtime/main.js +10 -0
- package/dist/workspace-runtime/persistence/journal.js +365 -0
- package/dist/workspace-runtime/persistence/native-subagents.js +162 -0
- package/dist/workspace-runtime/persistence/sqlite-client.js +77 -0
- package/dist/workspace-runtime/persistence/sqlite-worker.js +1161 -0
- package/dist/workspace-runtime/persistence/stopped-execution.js +77 -0
- package/dist/workspace-runtime/previews/output.js +36 -0
- package/dist/workspace-runtime/previews/publish.js +262 -0
- package/dist/workspace-runtime/previews/single-file.js +43 -0
- package/dist/workspace-runtime/processes/managed-writes.js +69 -0
- package/dist/workspace-runtime/production/content-changes.js +36 -0
- package/dist/workspace-runtime/production/contracts.js +19 -0
- package/dist/workspace-runtime/production/controller.js +225 -0
- package/dist/workspace-runtime/production/dependencies.js +60 -0
- package/dist/workspace-runtime/production/native.js +239 -0
- package/dist/workspace-runtime/production/processes.js +102 -0
- package/dist/workspace-runtime/production/save-command.js +35 -0
- package/dist/workspace-runtime/production/source-archive.js +137 -0
- package/dist/workspace-runtime/production/source-copy.js +92 -0
- package/dist/workspace-runtime/production/stages.js +354 -0
- package/dist/workspace-runtime/production/storage.js +75 -0
- package/dist/workspace-runtime/serve.js +281 -0
- package/dist/workspace-runtime/server/auth.js +21 -0
- package/dist/workspace-runtime/server/connectivity.js +201 -0
- package/dist/workspace-runtime/server/desktop-host.js +429 -0
- package/dist/workspace-runtime/server/desktop-preview-config.js +81 -0
- package/dist/workspace-runtime/server/desktop-preview-service.js +157 -0
- package/dist/workspace-runtime/server/desktop-preview-static.js +53 -0
- package/dist/workspace-runtime/server/desktop-preview.js +189 -0
- package/dist/workspace-runtime/server/dispatch.js +1335 -0
- package/dist/workspace-runtime/server/endpoints.js +21 -0
- package/dist/workspace-runtime/server/execution-group.js +90 -0
- package/dist/workspace-runtime/server/http.js +1291 -0
- package/dist/workspace-runtime/server/lock.js +53 -0
- package/dist/workspace-runtime/server/rfb-watch-gate.js +168 -0
- package/dist/workspace-runtime/server/session-restore.js +84 -0
- package/dist/workspace-runtime/server/source-uploader.js +138 -0
- package/dist/workspace-runtime/server/terminal-host.js +366 -0
- package/dist/workspace-runtime/server/types.js +1 -0
- package/dist/workspace-runtime/server/workspace-transfer.js +168 -0
- package/dist/workspace-runtime/workspaces/archive.js +207 -0
- package/dist/workspace-runtime/workspaces/artifact-events.js +55 -0
- package/dist/workspace-runtime/workspaces/artifact-files.js +199 -0
- package/dist/workspace-runtime/workspaces/artifact-receipts.js +89 -0
- package/dist/workspace-runtime/workspaces/artifacts.js +282 -0
- package/dist/workspace-runtime/workspaces/asset-library-import.js +366 -0
- package/dist/workspace-runtime/workspaces/attachment-content.js +73 -0
- package/dist/workspace-runtime/workspaces/attachments.js +185 -0
- package/dist/workspace-runtime/workspaces/batch-commit.js +142 -0
- package/dist/workspace-runtime/workspaces/binary-content.js +65 -0
- package/dist/workspace-runtime/workspaces/binary-write.js +112 -0
- package/dist/workspace-runtime/workspaces/cli-context.js +23 -0
- package/dist/workspace-runtime/workspaces/cli-credentials.js +111 -0
- package/dist/workspace-runtime/workspaces/composer-context.js +147 -0
- package/dist/workspace-runtime/workspaces/context-error.js +2 -0
- package/dist/workspace-runtime/workspaces/dependencies.js +264 -0
- package/dist/workspace-runtime/workspaces/developer-command.js +64 -0
- package/dist/workspace-runtime/workspaces/directories.js +137 -0
- package/dist/workspace-runtime/workspaces/directory-access.js +37 -0
- package/dist/workspace-runtime/workspaces/directory-attachments.js +245 -0
- package/dist/workspace-runtime/workspaces/directory-create.js +57 -0
- package/dist/workspace-runtime/workspaces/directory-maintenance.js +111 -0
- package/dist/workspace-runtime/workspaces/directory-stats.js +49 -0
- package/dist/workspace-runtime/workspaces/disk-snapshot.js +31 -0
- package/dist/workspace-runtime/workspaces/empty-template.js +42 -0
- package/dist/workspace-runtime/workspaces/file-content.js +48 -0
- package/dist/workspace-runtime/workspaces/files-search.js +116 -0
- package/dist/workspace-runtime/workspaces/files.js +150 -0
- package/dist/workspace-runtime/workspaces/git-credential-broker.js +312 -0
- package/dist/workspace-runtime/workspaces/git-credential-helper.js +68 -0
- package/dist/workspace-runtime/workspaces/git-direct-store.js +155 -0
- package/dist/workspace-runtime/workspaces/git.js +670 -0
- package/dist/workspace-runtime/workspaces/instructions.js +56 -0
- package/dist/workspace-runtime/workspaces/json5-edit.js +170 -0
- package/dist/workspace-runtime/workspaces/library-attachments.js +268 -0
- package/dist/workspace-runtime/workspaces/optional-platform-skills.js +14 -0
- package/dist/workspace-runtime/workspaces/parameters.js +272 -0
- package/dist/workspace-runtime/workspaces/prepare.js +278 -0
- package/dist/workspace-runtime/workspaces/registry.js +251 -0
- package/dist/workspace-runtime/workspaces/remix-references.js +301 -0
- package/dist/workspace-runtime/workspaces/revisions.js +31 -0
- package/dist/workspace-runtime/workspaces/session-image.js +104 -0
- package/dist/workspace-runtime/workspaces/shared-git.js +40 -0
- package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +95 -0
- package/dist/workspace-runtime/workspaces/skills.js +191 -0
- package/dist/workspace-runtime/workspaces/transfer-quota.js +69 -0
- package/dist/workspace-runtime/workspaces/transfer.js +471 -0
- package/dist/workspace-runtime/workspaces/turn-changes.js +75 -0
- package/dist/workspace-runtime/workspaces/video-attachments.js +49 -0
- package/package.json +15 -5
- package/project-template/.claude/agents/refs/ta-image-generation-detail.md +123 -67
- package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +63 -135
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +33 -42
- package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +20 -18
- package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +7 -6
- package/project-template/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +39 -39
- package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +25 -0
- package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +79 -0
- package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +29 -0
- package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +37 -0
- package/project-template-v2/.claude/agents/artist.md +82 -0
- package/project-template-v2/.claude/agents/developer.md +153 -0
- package/project-template-v2/.claude/agents/game-designer.md +264 -0
- package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +533 -0
- package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +153 -0
- package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +27 -0
- package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +208 -0
- package/project-template-v2/.claude/agents/refs/atom-skill-library.md +81 -0
- package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +432 -0
- package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +252 -0
- package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +266 -0
- package/project-template-v2/.claude/agents/refs/framework-mda.md +147 -0
- package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
- package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +88 -0
- package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +67 -0
- package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
- package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +300 -0
- package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +495 -0
- package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +1141 -0
- package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +111 -0
- package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
- package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +412 -0
- package/project-template-v2/.claude/agents/reviewer.md +75 -0
- package/project-template-v2/.claude/agents/technical-artist.md +86 -0
- package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +243 -0
- package/project-template-v2/.claude/hooks/user-prompt.mjs +133 -0
- package/project-template-v2/.claude/settings.json +33 -0
- package/project-template-v2/.claude/skills/brainstorming/SKILL.md +161 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +177 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +354 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
- package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +309 -0
- package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
- package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
- package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +205 -0
- package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +280 -0
- package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
- package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +298 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +324 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +97 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +137 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
- package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
- package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +219 -0
- package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +373 -0
- package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
- package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +215 -0
- package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +382 -0
- package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
- package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
- package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
- package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +167 -0
- package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
- package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
- package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
- package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +390 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +23 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +39 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +240 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +226 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +308 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +275 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +134 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +142 -0
- package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +153 -0
- package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +386 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +102 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
- package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
- package/project-template-v2/.claude/snapshot.mjs +263 -0
- package/project-template-v2/.playcraft/skills.lock.json +152 -0
- package/project-template-v2/CLAUDE.md +146 -0
- package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
- package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
- package/project-template-v2/assets/bundles/.gitkeep +0 -0
- package/project-template-v2/assets/images/bg/.gitkeep +0 -0
- package/project-template-v2/assets/images/reference/.gitkeep +0 -0
- package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
- package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
- package/project-template-v2/assets/images/ui/.gitkeep +0 -0
- package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
- package/project-template-v2/assets/models/.gitkeep +0 -0
- package/project-template-v2/docs/harness/iteration-1/context-flow.md +254 -0
- package/project-template-v2/docs/harness/iteration-1/generate-flow.md +91 -0
- package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +214 -0
- package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +75 -0
- package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +63 -0
- package/project-template-v2/docs/harness/iteration-2/context-flow.md +223 -0
- package/project-template-v2/docs/harness/iteration-2/generate-flow.md +129 -0
- package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +267 -0
- package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +164 -0
- package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +115 -0
- package/project-template-v2/docs/harness/orchestrator-flow.md +364 -0
- package/project-template-v2/docs/project-state.json +60 -0
- package/project-template-v2/docs/project-state.md +72 -0
- package/project-template-v2/docs/standards/README.md +225 -0
- package/project-template-v2/docs/standards/agent-behavior-standards.md +174 -0
- package/project-template-v2/docs/standards/artifacts/design-brief.md +19 -0
- package/project-template-v2/docs/standards/artifacts/design.md +22 -0
- package/project-template-v2/docs/standards/artifacts/game-code.md +41 -0
- package/project-template-v2/docs/standards/artifacts/todo-list.md +41 -0
- package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +343 -0
- package/project-template-v2/game/index.ts +18 -0
- package/project-template-v2/globals.d.ts +51 -0
- package/project-template-v2/index.css +34 -0
- package/project-template-v2/index.html +18 -0
- package/project-template-v2/main.ts +9 -0
- package/project-template-v2/package.json +46 -0
- package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +31 -0
- package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +86 -0
- package/project-template-v2/skills/_shared/scripts/dod-check.mjs +153 -0
- package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +70 -0
- package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +91 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +131 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +80 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +90 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +93 -0
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +23 -0
- package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +230 -0
- package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +58 -0
- package/project-template-v2/skills/_shared/scripts/state-get.mjs +339 -0
- package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +39 -0
- package/project-template-v2/skills/_shared/scripts/state-set.mjs +94 -0
- package/project-template-v2/skills/_shared/scripts/state-store.mjs +783 -0
- package/project-template-v2/skills/_shared/scripts/todo-add.mjs +88 -0
- package/project-template-v2/skills/_shared/scripts/todo-get.mjs +130 -0
- package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +33 -0
- package/project-template-v2/skills/_shared/scripts/todo-set.mjs +47 -0
- package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +268 -0
- package/project-template-v2/skills/_shared/scripts/verify-env.mjs +285 -0
- package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +161 -0
- package/project-template-v2/skills/playable-autoplay/SKILL.md +176 -0
- package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +4 -0
- package/project-template-v2/skills/playable-debug/SKILL.md +116 -0
- package/project-template-v2/skills/playable-debug/agents/openai.yaml +4 -0
- package/project-template-v2/skills/playable-debug/references/debug-config.md +40 -0
- package/project-template-v2/skills/playable-record/SKILL.md +140 -0
- package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
- package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
- package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +425 -0
- package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +261 -0
- package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
- package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +322 -0
- package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +105 -0
- package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +230 -0
- package/project-template-v2/skills/playable-validate/SKILL.md +61 -0
- package/project-template-v2/skills/playable-validate/validation-rules.md +14 -0
- package/project-template-v2/skills/playable-verify-ui/SKILL.md +63 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +106 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
- package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
- package/project-template-v2/tsconfig.json +20 -0
- package/project-template-v2/vite.config.ts +27 -0
- package/project-templates/batch-locks/phaser.yaml +922 -0
- package/project-templates/batch-locks/threejs.yaml +978 -0
- package/project-templates/empty/AGENTS.md +41 -0
- package/project-templates/empty/gitignore +33 -0
- package/project-templates/phaser/.claude/agents/refs/ta-image-generation-detail.md +59 -59
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +63 -135
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +33 -42
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +20 -18
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +7 -6
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +39 -39
- package/project-templates/threejs/.claude/agents/refs/ta-image-generation-detail.md +59 -59
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +63 -135
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +33 -42
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +20 -18
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +7 -6
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +39 -39
- package/dist/commands/tools-image-context.js +0 -29
- package/dist/utils/image-asset-context.js +0 -228
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { batchCreateSchema, batchPromptCreateSchema } from '@playcraft/common/cloud-workspace/runtime';
|
|
3
|
+
import { AgentApiClient } from '../utils/agent-api-client.js';
|
|
4
|
+
import { handleError } from './tools-utils.js';
|
|
5
|
+
const messages = {
|
|
6
|
+
en: {
|
|
7
|
+
create: 'Create and automatically run independent Remix variants from one prompt',
|
|
8
|
+
input: 'Path to the batch draft JSON (JavaScript Object Notation, 数据交换格式) file',
|
|
9
|
+
status: 'Read a batch and its generation status',
|
|
10
|
+
id: 'Batch identifier',
|
|
11
|
+
created: 'Batch created',
|
|
12
|
+
prompt: 'The complete batch generation request', workspace: 'Source workspace identifier',
|
|
13
|
+
directory: 'Source engineering directory; defaults to basic', request: 'Stable batch creation identity for retries',
|
|
14
|
+
team: 'Team identifier for a standalone workspace', invalidMode: 'Provide either --prompt with --workspace-id or --input, exclusively.',
|
|
15
|
+
requestRequired: 'Prompt creation requires a stable --client-request-id; reuse it when retrying the same request.',
|
|
16
|
+
help: '\nUse --prompt with --workspace-id and a stable --client-request-id. The platform plans and generates independent Remix directories while preserving the source. An omitted count defaults to 3; maximum 10. --input also accepts existing structured drafts.\n',
|
|
17
|
+
confirmation: 'Generation is queued. Read the batch status to track its results.',
|
|
18
|
+
review: 'This existing draft requires baseline approval in the browser.',
|
|
19
|
+
},
|
|
20
|
+
zh: {
|
|
21
|
+
create: '用一个 prompt 创建并自动生成独立 Remix 变体',
|
|
22
|
+
input: '批次草案 JSON (JavaScript Object Notation, 数据交换格式) 文件路径',
|
|
23
|
+
status: '查询批次及生成状态',
|
|
24
|
+
id: '批次标识',
|
|
25
|
+
created: '批次已创建',
|
|
26
|
+
prompt: '完整的批量生成需求', workspace: '来源 workspace 标识',
|
|
27
|
+
directory: '来源工程目录,默认 basic', request: '用于重试的稳定批次创建标识',
|
|
28
|
+
team: '独立工作区所属团队标识', invalidMode: '请选择 --prompt 配合 --workspace-id,或 --input,两种方式不能同时使用。',
|
|
29
|
+
requestRequired: '使用 prompt 创建时必须提供稳定的 --client-request-id,重试同一请求时复用该标识。',
|
|
30
|
+
help: '\n使用 --prompt、--workspace-id 和稳定的 --client-request-id。平台自动规划,在副本中生成独立 Remix,保持来源不变。未指定数量默认 3 个,最多 10 个。--input 也兼容现有结构化草案。\n',
|
|
31
|
+
confirmation: '生成已排队,可查询批次状态追踪各项成果。',
|
|
32
|
+
review: '此历史草案需要在浏览器确认基准。',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
const language = () => /^zh/i.test(process.env.PLAYCRAFT_LANG ?? process.env.LANG ?? '') ? messages.zh : messages.en;
|
|
36
|
+
export async function createBatchDraft(path, client = new AgentApiClient()) {
|
|
37
|
+
const draft = batchCreateSchema.parse(JSON.parse(await readFile(path, 'utf8')));
|
|
38
|
+
return client.post('/create-batch', draft);
|
|
39
|
+
}
|
|
40
|
+
export async function createPromptBatch(input, client = new AgentApiClient()) {
|
|
41
|
+
return client.post('/create-batch', batchPromptCreateSchema.parse(input));
|
|
42
|
+
}
|
|
43
|
+
export function registerBatchCommands(tools) {
|
|
44
|
+
const t = language();
|
|
45
|
+
tools.command('create-batch')
|
|
46
|
+
.description(t.create)
|
|
47
|
+
.option('--input <path>', t.input)
|
|
48
|
+
.option('--prompt <text>', t.prompt)
|
|
49
|
+
.option('--workspace-id <id>', t.workspace)
|
|
50
|
+
.option('--source-directory <name>', t.directory, 'basic')
|
|
51
|
+
.option('--client-request-id <id>', t.request)
|
|
52
|
+
.option('--team-id <id>', t.team)
|
|
53
|
+
.option('--json', 'JSON (JavaScript Object Notation, 数据交换格式)')
|
|
54
|
+
.addHelpText('after', t.help)
|
|
55
|
+
.action(async (opts) => {
|
|
56
|
+
try {
|
|
57
|
+
if (Boolean(opts.input) === Boolean(opts.prompt))
|
|
58
|
+
throw new Error(t.invalidMode);
|
|
59
|
+
if (opts.prompt && !opts.workspaceId)
|
|
60
|
+
throw new Error(t.invalidMode);
|
|
61
|
+
if (opts.prompt && !opts.clientRequestId)
|
|
62
|
+
throw new Error(t.requestRequired);
|
|
63
|
+
const result = opts.input ? await createBatchDraft(opts.input) : await createPromptBatch({
|
|
64
|
+
clientRequestId: opts.clientRequestId, prompt: opts.prompt,
|
|
65
|
+
sourceWorkspaceId: opts.workspaceId, sourceDirectoryName: opts.sourceDirectory,
|
|
66
|
+
...(opts.teamId ? { teamId: opts.teamId } : {}),
|
|
67
|
+
});
|
|
68
|
+
console.log(opts.json ? JSON.stringify(result, null, 2) : `${t.created}: ${result.batchId}\n${result.manifest.autoStart ? t.confirmation : t.review}`);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
handleError(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
tools.command('get-batch')
|
|
75
|
+
.description(t.status)
|
|
76
|
+
.requiredOption('--batch-id <id>', t.id)
|
|
77
|
+
.action(async (opts) => {
|
|
78
|
+
try {
|
|
79
|
+
const client = new AgentApiClient();
|
|
80
|
+
const result = await client.get('/get-batch', { batchId: opts.batchId });
|
|
81
|
+
console.log(JSON.stringify(result, null, 2));
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
handleError(error);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { Option } from 'commander';
|
|
2
1
|
import { writeFileSync, mkdirSync } from 'fs';
|
|
3
2
|
import { dirname, parse, join } from 'path';
|
|
4
3
|
import sharp from 'sharp';
|
|
5
|
-
import {
|
|
6
|
-
import { assertImageAssetOutputPaths, readImageAssetContext } from '../utils/image-asset-context.js';
|
|
4
|
+
import { captureGeneratedArtifact } from '../workspace-runtime/workspaces/artifact-receipts.js';
|
|
7
5
|
import { AgentApiClient } from '../utils/agent-api-client.js';
|
|
8
|
-
import { MAX_REFERENCE_IMAGES, collectReferenceImagePaths,
|
|
6
|
+
import { MAX_REFERENCE_IMAGES, collectReferenceImagePaths, collectReferenceImagePayloads, sniffImageExtension, extensionForImageMime, resolveImageOutputPath, handleError, raceWithTimeout, } from './tools-utils.js';
|
|
9
7
|
function isMasterCompositeStripRequest(opts) {
|
|
10
8
|
if (opts.aspectRatio === '45:16')
|
|
11
9
|
return true;
|
|
@@ -153,140 +151,86 @@ export function registerGenerationCommands(tools) {
|
|
|
153
151
|
.requiredOption('--prompt <text>', '图片描述')
|
|
154
152
|
.option('--aspect-ratio <ratio>', '宽高比 (1:1|45:16|16:9|9:16|3:4|4:3|2:3|3:2|21:9)', '1:1')
|
|
155
153
|
.requiredOption('--output <path>', '保存路径(--count>1 时自动追加 _1/_2 等后缀)')
|
|
156
|
-
.option('--target-asset <path>', 'Existing asset to replace; read its schema references and delivery constraints')
|
|
157
|
-
.option('--target-field-path <path>', 'Target image field as an array of keys, e.g. ["endUI","playButton"]', parseImageTargetFieldPath)
|
|
158
|
-
.option('--no-target-reference', 'Generate without the existing asset reference only when explicitly requested')
|
|
159
|
-
.option('--output-format <format>', 'Final format: png, webp or jpeg')
|
|
160
|
-
.option('--fit-mode <mode>', 'Canvas fitting: contain, cover or fill')
|
|
161
|
-
.option('--padding-color <color>', 'Canvas padding color (transparent by default)')
|
|
162
|
-
.addOption(new Option('--background <mode>', 'Agent background decision from conversation context').choices(['transparent', 'opaque']))
|
|
163
|
-
.option('--remove-background', 'Require a verified transparent image')
|
|
164
|
-
.option('--no-remove-background', 'Keep the generated background')
|
|
165
154
|
.option('--image-size <size>', '图片尺寸 (1K|2K|4K)')
|
|
166
155
|
.option('--width <n>', '精确宽度(像素;MC 横排 5×9:16 推荐 3600 或 4096)', (v) => parseInt(v, 10))
|
|
167
156
|
.option('--height <n>', '精确高度(像素;MC 推荐 1280 或 1455)', (v) => parseInt(v, 10))
|
|
168
157
|
.option('--reference-image <path>', '参考图路径(可重复多次,最多 8 张),支持 PNG/JPG/WEBP', collectReferenceImagePaths, [])
|
|
169
158
|
.option('--image-model <model>', '模型名(如 gpt-image-2)或 provider/model(如 mulerouter/gpt-image-2)。传模型名时后端按优先级自动 fallback;传 provider/model 则直连指定 provider')
|
|
170
|
-
.option('--retry <n>', '
|
|
159
|
+
.option('--retry <n>', '全部 provider 都失败时的重试轮数(默认 1;超时不计为可重试错误)', (v) => parseInt(v, 10), 1)
|
|
171
160
|
.option('--timeout <seconds>', '请求超时秒数(默认 1800,即 30 分钟;异步生图模型耗时较长,仅在后端明确报错时提前终止)', (v) => parseInt(v, 10), 1800)
|
|
172
161
|
.option('--count <n>', '一次 API 调用生成多少张图片(默认 1,最多 10;仅 gpt-image-2 实际支持批量)', (v) => parseInt(v, 10), 1)
|
|
173
162
|
.action(async (opts) => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
163
|
+
const paths = opts.referenceImage ?? [];
|
|
164
|
+
if (paths.length > MAX_REFERENCE_IMAGES) {
|
|
165
|
+
console.error(`Error: Too many reference images: ${paths.length} paths given; maximum is ${MAX_REFERENCE_IMAGES}.`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const hasReferenceImages = paths.length > 0;
|
|
170
|
+
const attemptGenerate = async (modelRef, attempt) => {
|
|
171
|
+
const label = modelRef ? `[${modelRef}]` : '[default model]';
|
|
172
|
+
if (attempt > 0) {
|
|
173
|
+
console.log(`Retry ${attempt}/${opts.retry} ${label}...`);
|
|
182
174
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const outputCandidates = [opts.output, ...Array.from({ length: opts.count > 1 ? Math.min(opts.count, 10) : 0 }, (_, i) => join(outputDir, `${outputName}_${i + 1}${outputExt}`))];
|
|
186
|
-
const assetContext = opts.targetAsset ? await readImageAssetContext(opts.targetAsset, process.cwd(), {
|
|
187
|
-
referenceImagePaths: opts.referenceImage, useTargetReference: opts.targetReference,
|
|
188
|
-
...(opts.targetFieldPath ? { targetFieldPath: opts.targetFieldPath } : {}),
|
|
189
|
-
outputPaths: outputCandidates,
|
|
190
|
-
prompt: opts.prompt, removeBackground: opts.removeBackground,
|
|
191
|
-
}) : undefined;
|
|
192
|
-
opts = { ...opts,
|
|
193
|
-
aspectRatio: assetContext?.aspectRatio ?? opts.aspectRatio,
|
|
194
|
-
width: assetContext?.width ?? opts.width, height: assetContext?.height ?? opts.height,
|
|
195
|
-
outputFormat: assetContext?.outputFormatFromSchema ? assetContext.outputFormat : opts.outputFormat ?? assetContext?.outputFormat,
|
|
196
|
-
fitMode: assetContext?.fitMode ?? opts.fitMode,
|
|
197
|
-
removeBackground: resolveImageBackgroundRequirement({ prompt: opts.prompt,
|
|
198
|
-
schemaRemoveBackground: assetContext?.removeBackgroundFromSchema ? assetContext.removeBackground : undefined,
|
|
199
|
-
removeBackground: opts.removeBackground, fallbackRemoveBackground: assetContext?.removeBackground }),
|
|
200
|
-
paddingColor: assetContext?.paddingColor ?? opts.paddingColor,
|
|
201
|
-
imageModel: opts.imageModel || assetContext?.imageModelRef,
|
|
202
|
-
};
|
|
203
|
-
const invalidDelivery = validateImageDeliveryOptions(opts);
|
|
204
|
-
if (invalidDelivery)
|
|
205
|
-
throw new Error(invalidDelivery);
|
|
206
|
-
const paths = opts.referenceImage?.length ? opts.referenceImage : assetContext?.referenceImagePaths ?? [];
|
|
207
|
-
if (paths.length > MAX_REFERENCE_IMAGES) {
|
|
208
|
-
console.error(`Error: Too many reference images: ${paths.length} paths given; maximum is ${MAX_REFERENCE_IMAGES}.`);
|
|
209
|
-
process.exit(1);
|
|
210
|
-
return;
|
|
175
|
+
else {
|
|
176
|
+
console.log(`Generating image ${label}...`);
|
|
211
177
|
}
|
|
212
|
-
const
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
background: opts.background === undefined ? undefined : opts.removeBackground ? 'transparent' : 'opaque',
|
|
236
|
-
removeBackground: opts.removeBackground,
|
|
237
|
-
backgroundRequirementSource: assetContext?.removeBackgroundFromSchema ? 'schema'
|
|
238
|
-
: explicitBackground !== undefined ? 'explicit' : 'inferred',
|
|
239
|
-
referenceImages,
|
|
240
|
-
...(modelRef ? { imageModelRef: modelRef } : {}),
|
|
241
|
-
...(imageCount > 1 ? { imageCount } : {}),
|
|
242
|
-
});
|
|
243
|
-
return raceWithTimeout(requestPromise, opts.timeout * 1000, `Request timed out after ${opts.timeout}s. The backend task may still be running — check admin panel before re-running.`);
|
|
244
|
-
};
|
|
245
|
-
const enrichError = (err, modelRef) => {
|
|
246
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
247
|
-
const lines = [`Error: ${msg}`];
|
|
248
|
-
if (/source_transparency_invalid|output_transparency_invalid|transparency_unsupported/.test(msg)) {
|
|
249
|
-
lines.push('Hint: Transparent output was not delivered. Preserve the requested transparency, references and model; use the request id and stage to investigate.');
|
|
250
|
-
}
|
|
251
|
-
else if (/API 500\b|Internal server error/.test(msg)) {
|
|
252
|
-
lines.push('');
|
|
253
|
-
lines.push('Hint: API 500 error — the model may be temporarily unavailable.');
|
|
254
|
-
lines.push(' → Inspect the request id and backend diagnostics before another generation attempt.');
|
|
255
|
-
if (modelRef?.includes('/') && opts.removeBackground !== true) {
|
|
256
|
-
lines.push(' → Or try without provider prefix to auto-fallback providers: --image-model gpt-image-2');
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
else if (msg.includes('timed out')) {
|
|
260
|
-
lines.push('');
|
|
261
|
-
lines.push('Hint: Request timed out. The backend task may still be running — retries were skipped to avoid creating duplicate tasks.');
|
|
262
|
-
lines.push(' → Check the backend/admin panel for task status before re-running');
|
|
263
|
-
lines.push(' → Try --image-size 1K to reduce generation time');
|
|
264
|
-
lines.push(' → Or increase timeout with --timeout <seconds> (current default: 1800s)');
|
|
265
|
-
}
|
|
266
|
-
else if (hasReferenceImages && (msg.includes('reference') || msg.includes('image input'))) {
|
|
267
|
-
lines.push('');
|
|
268
|
-
lines.push('Hint: Reference image error — the selected model may not support --reference-image.');
|
|
269
|
-
lines.push(' → Run: playcraft tools list-image-models');
|
|
270
|
-
lines.push(' → Models with CAPABILITY=text+image support --reference-image');
|
|
178
|
+
const referenceImages = await collectReferenceImagePayloads(paths);
|
|
179
|
+
const client = new AgentApiClient();
|
|
180
|
+
const imageCount = Math.min(Math.max(1, opts.count ?? 1), 10);
|
|
181
|
+
const requestPromise = client.post('/generate-image', {
|
|
182
|
+
prompt: opts.prompt,
|
|
183
|
+
aspectRatio: opts.aspectRatio,
|
|
184
|
+
imageSize: opts.imageSize,
|
|
185
|
+
...(opts.width && opts.height ? { width: opts.width, height: opts.height } : {}),
|
|
186
|
+
referenceImages,
|
|
187
|
+
...(modelRef ? { imageModelRef: modelRef } : {}),
|
|
188
|
+
...(imageCount > 1 ? { imageCount } : {}),
|
|
189
|
+
});
|
|
190
|
+
return raceWithTimeout(requestPromise, opts.timeout * 1000, `Request timed out after ${opts.timeout}s. The backend task may still be running — check admin panel before re-running.`);
|
|
191
|
+
};
|
|
192
|
+
const enrichError = (err, modelRef) => {
|
|
193
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
194
|
+
const lines = [`Error: ${msg}`];
|
|
195
|
+
if (msg.includes('500') || msg.includes('Internal server error')) {
|
|
196
|
+
lines.push('');
|
|
197
|
+
lines.push('Hint: API 500 error — the model may be temporarily unavailable.');
|
|
198
|
+
lines.push(' → If using a bare model name (e.g. gpt-image-2), all providers failed — try a different model');
|
|
199
|
+
if (modelRef?.includes('/')) {
|
|
200
|
+
lines.push(' → Or try without provider prefix to auto-fallback providers: --image-model gpt-image-2');
|
|
271
201
|
}
|
|
272
|
-
|
|
273
|
-
|
|
202
|
+
}
|
|
203
|
+
else if (msg.includes('timed out')) {
|
|
204
|
+
lines.push('');
|
|
205
|
+
lines.push('Hint: Request timed out. The backend task may still be running — retries were skipped to avoid creating duplicate tasks.');
|
|
206
|
+
lines.push(' → Check the backend/admin panel for task status before re-running');
|
|
207
|
+
lines.push(' → Try --image-size 1K to reduce generation time');
|
|
208
|
+
lines.push(' → Or increase timeout with --timeout <seconds> (current default: 1800s)');
|
|
209
|
+
}
|
|
210
|
+
else if (hasReferenceImages && (msg.includes('reference') || msg.includes('image input'))) {
|
|
211
|
+
lines.push('');
|
|
212
|
+
lines.push('Hint: Reference image error — the selected model may not support --reference-image.');
|
|
213
|
+
lines.push(' → Run: playcraft tools list-image-models');
|
|
214
|
+
lines.push(' → Models with CAPABILITY=text+image support --reference-image');
|
|
215
|
+
}
|
|
216
|
+
return lines.join('\n');
|
|
217
|
+
};
|
|
218
|
+
try {
|
|
274
219
|
let result = null;
|
|
275
220
|
let lastError = null;
|
|
276
221
|
// 重试逻辑:超时不重试(后端任务可能仍在运行,重试会导致重复提交)
|
|
277
|
-
const maxAttempts = 1 + (opts.retry ??
|
|
222
|
+
const maxAttempts = 1 + (opts.retry ?? 1);
|
|
278
223
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
279
224
|
try {
|
|
280
|
-
result = await attemptGenerate(opts.imageModel
|
|
225
|
+
result = await attemptGenerate(opts.imageModel, attempt);
|
|
281
226
|
break;
|
|
282
227
|
}
|
|
283
228
|
catch (e) {
|
|
284
229
|
lastError = e;
|
|
285
230
|
const msg = e instanceof Error ? e.message : String(e);
|
|
286
231
|
const isTimeout = msg.includes('timed out');
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
console.error(`Attempt ${attempt + 1} stopped: ${msg}`);
|
|
232
|
+
if (isTimeout) {
|
|
233
|
+
console.error(`Attempt ${attempt + 1} timed out — not retrying (backend task may still be running).`);
|
|
290
234
|
break;
|
|
291
235
|
}
|
|
292
236
|
if (attempt < maxAttempts - 1) {
|
|
@@ -311,18 +255,16 @@ export function registerGenerationCommands(tools) {
|
|
|
311
255
|
}
|
|
312
256
|
// 收集所有待保存图片(第 1 张 + 批量额外图)
|
|
313
257
|
const allImages = [
|
|
314
|
-
{ imageBase64: result.imageBase64, mimeType: result.mimeType
|
|
258
|
+
{ imageBase64: result.imageBase64, mimeType: result.mimeType },
|
|
315
259
|
...(result.additionalImages ?? []),
|
|
316
260
|
];
|
|
317
261
|
const isBatch = allImages.length > 1;
|
|
318
|
-
const modelPart =
|
|
262
|
+
const modelPart = opts.imageModel ? `model: ${opts.imageModel}` : '';
|
|
319
263
|
const providerPart = result.provider ? `provider: ${result.provider}` : '';
|
|
320
264
|
const labelParts = [modelPart, providerPart].filter(Boolean);
|
|
321
265
|
const modelLabel = labelParts.length > 0 ? ` (${labelParts.join(', ')})` : '';
|
|
322
266
|
const savedPaths = [];
|
|
323
|
-
|
|
324
|
-
console.log(`Transparency source: ${result.transparencySource}`);
|
|
325
|
-
const stripTarget = opts.targetAsset || result.transparentBackground ? null : resolveStripTargetDimensions({
|
|
267
|
+
const stripTarget = resolveStripTargetDimensions({
|
|
326
268
|
aspectRatio: opts.aspectRatio,
|
|
327
269
|
width: opts.width,
|
|
328
270
|
height: opts.height,
|
|
@@ -351,8 +293,6 @@ export function registerGenerationCommands(tools) {
|
|
|
351
293
|
console.log(`↑ Letterbox ${generatedWidth}×${generatedHeight} → ${stripTarget.width}×${stripTarget.height}(等比 + 白边,不拉伸)`);
|
|
352
294
|
}
|
|
353
295
|
}
|
|
354
|
-
if (assetContext)
|
|
355
|
-
assertImageAssetOutputPaths(assetContext, [resolvedPath]);
|
|
356
296
|
mkdirSync(dirname(resolvedPath), { recursive: true });
|
|
357
297
|
writeFileSync(resolvedPath, imgBuf);
|
|
358
298
|
let actualWidth = null;
|
|
@@ -369,23 +309,11 @@ export function registerGenerationCommands(tools) {
|
|
|
369
309
|
}
|
|
370
310
|
const sizeKB = Math.round(imgBuf.length / 1024);
|
|
371
311
|
console.log(`[${i + 1}/${allImages.length}] Image saved to ${resolvedPath} (${sizeKB}KB)${modelLabel}`);
|
|
372
|
-
if (img.previewUrl)
|
|
373
|
-
console.log(`Image preview: ${img.previewUrl}`);
|
|
374
312
|
savedPaths.push(resolvedPath);
|
|
375
313
|
const sidecar = {
|
|
376
314
|
prompt: opts.prompt,
|
|
377
|
-
model:
|
|
378
|
-
requestedModel: opts.imageModel ?? null,
|
|
315
|
+
model: opts.imageModel ?? 'default',
|
|
379
316
|
provider: result.provider ?? null,
|
|
380
|
-
transparentBackground: result.transparentBackground ?? null,
|
|
381
|
-
requestedBackground: opts.background ?? null,
|
|
382
|
-
transparencySource: result.transparencySource ?? null,
|
|
383
|
-
requestId: result.requestId ?? null,
|
|
384
|
-
attempts: result.attempts ?? null,
|
|
385
|
-
targetAssetPath: assetContext?.targetAssetPath ?? null,
|
|
386
|
-
outputFormat: opts.outputFormat ?? null,
|
|
387
|
-
fitMode: opts.fitMode ?? null,
|
|
388
|
-
paddingColor: opts.paddingColor ?? null,
|
|
389
317
|
aspectRatio: opts.aspectRatio,
|
|
390
318
|
imageSize: opts.imageSize ?? null,
|
|
391
319
|
requestedWidth: opts.width ?? stripTarget?.width ?? null,
|
|
@@ -398,12 +326,14 @@ export function registerGenerationCommands(tools) {
|
|
|
398
326
|
count: opts.count ?? 1,
|
|
399
327
|
batchIndex: isBatch ? i + 1 : null,
|
|
400
328
|
output: resolvedPath,
|
|
401
|
-
previewUrl: img.previewUrl ?? null,
|
|
402
329
|
referenceImageStatus: result.referenceImageStatus ?? null,
|
|
403
330
|
generatedAt: new Date().toISOString(),
|
|
404
331
|
};
|
|
405
332
|
const sidecarPath = resolvedPath.replace(/\.[^.]+$/, '.json');
|
|
406
333
|
writeFileSync(sidecarPath, JSON.stringify(sidecar, null, 2));
|
|
334
|
+
await captureGeneratedArtifact(resolvedPath, 'generate-image', {
|
|
335
|
+
...(actualWidth ? { width: actualWidth } : {}), ...(actualHeight ? { height: actualHeight } : {}),
|
|
336
|
+
});
|
|
407
337
|
console.log(` └─ Generation metadata: ${sidecarPath}`);
|
|
408
338
|
}
|
|
409
339
|
if (!isBatch && opts.output !== savedPaths[0] && savedPaths[0]) {
|
|
@@ -451,6 +381,7 @@ export function registerGenerationCommands(tools) {
|
|
|
451
381
|
output: opts.output, generatedAt: new Date().toISOString(),
|
|
452
382
|
};
|
|
453
383
|
writeFileSync(opts.output.replace(/\.[^.]+$/, '.json'), JSON.stringify(sfxSidecar, null, 2));
|
|
384
|
+
await captureGeneratedArtifact(opts.output, 'generate-sfx', { duration: result.duration });
|
|
454
385
|
console.log(` └─ Generation metadata: ${opts.output.replace(/\.[^.]+$/, '.json')}`);
|
|
455
386
|
}
|
|
456
387
|
catch (e) {
|
|
@@ -483,6 +414,7 @@ export function registerGenerationCommands(tools) {
|
|
|
483
414
|
output: opts.output, generatedAt: new Date().toISOString(),
|
|
484
415
|
};
|
|
485
416
|
writeFileSync(opts.output.replace(/\.[^.]+$/, '.json'), JSON.stringify(bgmSidecar, null, 2));
|
|
417
|
+
await captureGeneratedArtifact(opts.output, 'generate-bgm', { duration: result.duration });
|
|
486
418
|
console.log(` └─ Generation metadata: ${opts.output.replace(/\.[^.]+$/, '.json')}`);
|
|
487
419
|
}
|
|
488
420
|
catch (e) {
|
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
import { writeFileSync, mkdirSync, readFileSync } from 'fs';
|
|
2
2
|
import { join, parse } from 'path';
|
|
3
3
|
import { tmpdir } from 'os';
|
|
4
|
-
import { InvalidArgumentError } from 'commander';
|
|
5
4
|
export const TMP_DIR = join(tmpdir(), 'playcraft');
|
|
6
5
|
export const MAX_REFERENCE_IMAGES = 8;
|
|
7
|
-
export function parseImageTargetFieldPath(value) {
|
|
8
|
-
let parsed;
|
|
9
|
-
try {
|
|
10
|
-
parsed = JSON.parse(value);
|
|
11
|
-
}
|
|
12
|
-
catch { /* Report the expected shape below. */ }
|
|
13
|
-
if (!Array.isArray(parsed) || !parsed.length || parsed.some(key => typeof key !== 'string' || !key.length)) {
|
|
14
|
-
throw new InvalidArgumentError('Expected an array of field names, e.g. ["endUI","playButton"].');
|
|
15
|
-
}
|
|
16
|
-
return parsed;
|
|
17
|
-
}
|
|
18
6
|
export function ensureTmpDir() {
|
|
19
7
|
mkdirSync(TMP_DIR, { recursive: true });
|
|
20
8
|
}
|
package/dist/commands/tools.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { registerGenerationCommands } from './tools-generation.js';
|
|
2
|
+
import { registerBatchCommands } from './tools-batch.js';
|
|
2
3
|
import { registerProjectCommands } from './tools-project.js';
|
|
3
4
|
import { register3DCommands } from './tools-3d.js';
|
|
4
5
|
import { registerDetectCommand } from './tools-detect.js';
|
|
5
6
|
import { registerVideoReviewCommand } from './tools-video-review.js';
|
|
6
|
-
import { registerImageContextCommand } from './tools-image-context.js';
|
|
7
7
|
export function registerToolsCommands(program) {
|
|
8
8
|
const tools = program
|
|
9
9
|
.command('tools')
|
|
10
10
|
.description('后端 /api/agent/tools;运行 playcraft login 后即可直接使用,也支持 .playcraft.json 或 PLAYCRAFT_SANDBOX_TOKEN 环境变量');
|
|
11
11
|
registerGenerationCommands(tools);
|
|
12
|
-
registerImageContextCommand(tools);
|
|
13
12
|
registerProjectCommands(tools);
|
|
13
|
+
registerBatchCommands(tools);
|
|
14
14
|
register3DCommands(tools);
|
|
15
15
|
registerDetectCommand(tools);
|
|
16
16
|
registerVideoReviewCommand(tools);
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { videoAnalysisRunSchema, videoModelCatalogSchema } from '@playcraft/common/agent-tools';
|
|
2
|
+
import { AgentApiClient } from '../utils/agent-api-client.js';
|
|
3
|
+
import { executeVideoUnderstanding, readVideoRun, requireVideoId, resolveVideoWorkspace, videoTimeout, } from '../video-replication/client.js';
|
|
4
|
+
import { materializeVideoEvidence } from '../video-replication/evidence.js';
|
|
5
|
+
import { probeVideo } from '../video-replication/media.js';
|
|
6
|
+
import { VideoCliError, videoMessage as t } from '../video-replication/messages.js';
|
|
7
|
+
import { comparisonMessage as c, ComparisonCliError } from '../video-replication/comparison-messages.js';
|
|
8
|
+
import { describeVideoFailure, remoteVideoFailure } from '../video-replication/diagnostics.js';
|
|
9
|
+
import { executeVideoComparison, readComparisonRun, comparisonRunResult } from '../video-replication/comparison.js';
|
|
10
|
+
import { materializeComparisonEvidence } from '../video-replication/comparison-evidence.js';
|
|
11
|
+
/** One final structured stdout record; progress and diagnostics stay on stderr. */
|
|
12
|
+
export async function runVideoCliAction(command, options, action) {
|
|
13
|
+
const interrupt = new AbortController();
|
|
14
|
+
const onInterrupt = () => interrupt.abort(new DOMException('Interrupted', 'AbortError'));
|
|
15
|
+
process.once('SIGINT', onInterrupt);
|
|
16
|
+
let timer;
|
|
17
|
+
const deadline = new AbortController();
|
|
18
|
+
try {
|
|
19
|
+
timer = setTimeout(() => deadline.abort(new DOMException('Timed out', 'TimeoutError')), videoTimeout(options));
|
|
20
|
+
const result = await action(AbortSignal.any([interrupt.signal, deadline.signal]));
|
|
21
|
+
if (result.envelope.error)
|
|
22
|
+
process.stderr.write(`[video] ${result.envelope.error.message}\n`);
|
|
23
|
+
process.stdout.write(`${JSON.stringify(result.envelope)}\n`);
|
|
24
|
+
process.exitCode = result.exitCode;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
const known = error instanceof VideoCliError || error instanceof ComparisonCliError;
|
|
28
|
+
const key = known ? error.code : interrupt.signal.aborted ? 'interrupted' : deadline.signal.aborted ? 'timeoutReached' : 'failed';
|
|
29
|
+
const summary = error instanceof ComparisonCliError ? c(error.code) : error instanceof VideoCliError ? t(error.code)
|
|
30
|
+
: interrupt.signal.aborted ? t('interrupted') : deadline.signal.aborted ? t('timeoutReached') : command === 'video compare' ? c('comparisonFailed') : t('failed');
|
|
31
|
+
const envelope = {
|
|
32
|
+
schemaVersion: 'playcraft.video-cli.v1', command, state: interrupt.signal.aborted || deadline.signal.aborted ? 'uncertain' : 'failed', ok: false,
|
|
33
|
+
error: { code: key, ...describeVideoFailure(summary, error, command === 'video models' ? 'models' : command === 'video jobs get' ? 'poll' : command === 'video jobs cancel' ? 'cancel' : 'prepare') },
|
|
34
|
+
};
|
|
35
|
+
process.stderr.write(`[video] ${envelope.error.message}\n`);
|
|
36
|
+
process.stdout.write(`${JSON.stringify(envelope)}\n`);
|
|
37
|
+
process.exitCode = known ? error.exitCode : interrupt.signal.aborted ? 130 : deadline.signal.aborted ? 75 : 4;
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
if (timer)
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
process.removeListener('SIGINT', onInterrupt);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function shared(command) {
|
|
46
|
+
return command.option('--workspace <id>', t('workspace')).option('--timeout <seconds>', t('timeout'));
|
|
47
|
+
}
|
|
48
|
+
export function registerVideoCommands(program) {
|
|
49
|
+
const video = program.command('video').description(t('topic'));
|
|
50
|
+
shared(video.command('models').description(t('models')))
|
|
51
|
+
.option('--json', t('json'))
|
|
52
|
+
.action((options) => runVideoCliAction('video models', options, async (signal) => {
|
|
53
|
+
const workspaceId = await resolveVideoWorkspace(options.workspace);
|
|
54
|
+
const catalog = videoModelCatalogSchema.parse(await new AgentApiClient().get('/video-models', { workspaceId }, { signal }));
|
|
55
|
+
return { exitCode: 0, envelope: { schemaVersion: 'playcraft.video-cli.v1', command: 'video models', state: 'completed', ok: true, result: catalog } };
|
|
56
|
+
}));
|
|
57
|
+
shared(video.command('understand').description(t('understand')))
|
|
58
|
+
.option('--video <path>', t('video')).option('--question <text>', t('question'))
|
|
59
|
+
.option('--context <path>', t('context')).option('--processing <mode>', t('processing'))
|
|
60
|
+
.option('--fps <number>', t('fps')).option('--clip <start:end>', t('clip'))
|
|
61
|
+
.option('--model-config <id>', t('model')).option('--out <directory>', t('out'))
|
|
62
|
+
.option('--resume <runId>', t('resume'))
|
|
63
|
+
.action((options) => runVideoCliAction('video understand', options, signal => executeVideoUnderstanding(options, signal, {
|
|
64
|
+
client: new AgentApiClient(), probe: probeVideo, materialize: materializeVideoEvidence,
|
|
65
|
+
progress: key => process.stderr.write(`[video] ${t(key)}\n`),
|
|
66
|
+
})));
|
|
67
|
+
shared(video.command('compare').description(c('compare')))
|
|
68
|
+
.option('--reference <path>', c('reference')).option('--analysis <path>', c('analysis'))
|
|
69
|
+
.option('--candidate <path>', c('candidate')).option('--recording <path>', c('recording'))
|
|
70
|
+
.option('--policy <path>', c('policy')).option('--processing <mode>', c('processing'))
|
|
71
|
+
.option('--fps <number>', t('fps')).option('--model-config <id>', t('model'))
|
|
72
|
+
.option('--out <directory>', t('out')).option('--resume <runId>', t('resume'))
|
|
73
|
+
.action((options) => runVideoCliAction('video compare', options, signal => executeVideoComparison(options, signal, {
|
|
74
|
+
client: new AgentApiClient(), probe: probeVideo, materialize: materializeComparisonEvidence,
|
|
75
|
+
progress: key => process.stderr.write(`[video] ${t(key)}\n`),
|
|
76
|
+
})));
|
|
77
|
+
const jobs = video.command('jobs').description(t('jobs'));
|
|
78
|
+
shared(jobs.command('get <runId>').description(t('get')))
|
|
79
|
+
.option('--kind <kind>', c('kind'))
|
|
80
|
+
.action((runId, options) => runVideoCliAction('video jobs get', options, async (signal) => {
|
|
81
|
+
const workspaceId = await resolveVideoWorkspace(options.workspace);
|
|
82
|
+
if (options.kind !== undefined && !['understanding', 'comparison'].includes(options.kind))
|
|
83
|
+
throw new VideoCliError('invalidArguments', 64);
|
|
84
|
+
if (options.kind === 'comparison') {
|
|
85
|
+
const run = await readComparisonRun(new AgentApiClient(), requireVideoId(runId), workspaceId, signal);
|
|
86
|
+
return comparisonRunResult('video jobs get', run);
|
|
87
|
+
}
|
|
88
|
+
const run = await readVideoRun(new AgentApiClient(), requireVideoId(runId), workspaceId, signal);
|
|
89
|
+
const error = remoteVideoFailure(run.state, run.error);
|
|
90
|
+
return { exitCode: run.state === 'uncertain' ? 75 : run.state === 'failed' || run.state === 'cancelled' ? 4 : 0, envelope: {
|
|
91
|
+
schemaVersion: 'playcraft.video-cli.v1', command: 'video jobs get', runId: run.runId, state: run.state,
|
|
92
|
+
ok: !['failed', 'uncertain', 'cancelled'].includes(run.state), result: run,
|
|
93
|
+
...(error && { error }),
|
|
94
|
+
} };
|
|
95
|
+
}));
|
|
96
|
+
shared(jobs.command('cancel <runId>').description(t('cancel')))
|
|
97
|
+
.option('--kind <kind>', c('kind'))
|
|
98
|
+
.action((identifier, options) => runVideoCliAction('video jobs cancel', options, async (signal) => {
|
|
99
|
+
const workspaceId = await resolveVideoWorkspace(options.workspace);
|
|
100
|
+
const runId = requireVideoId(identifier);
|
|
101
|
+
if (options.kind !== undefined && !['understanding', 'comparison'].includes(options.kind))
|
|
102
|
+
throw new VideoCliError('invalidArguments', 64);
|
|
103
|
+
if (options.kind === 'comparison') {
|
|
104
|
+
const run = await readComparisonRun(new AgentApiClient(), runId, workspaceId, signal, true);
|
|
105
|
+
const confirmed = run.state === 'cancelled';
|
|
106
|
+
return { exitCode: confirmed ? 0 : 75, envelope: {
|
|
107
|
+
schemaVersion: 'playcraft.video-cli.v1', command: 'video jobs cancel', runId, state: run.state,
|
|
108
|
+
ok: confirmed, result: { ...run, cancellationConfirmed: confirmed },
|
|
109
|
+
...(!confirmed && { error: { code: 'uncertain', ...describeVideoFailure(t('uncertain'), run.error?.code, 'cancel') } }),
|
|
110
|
+
} };
|
|
111
|
+
}
|
|
112
|
+
const run = videoAnalysisRunSchema.parse(await new AgentApiClient().post(`/video-analysis/${runId}/cancel`, { workspaceId, runId }, { signal }));
|
|
113
|
+
if (run.runId !== runId || run.workspaceId !== workspaceId)
|
|
114
|
+
throw new VideoCliError('invalidResult');
|
|
115
|
+
const confirmed = run.state === 'cancelled';
|
|
116
|
+
return { exitCode: confirmed ? 0 : 75, envelope: {
|
|
117
|
+
schemaVersion: 'playcraft.video-cli.v1', command: 'video jobs cancel', runId, state: run.state,
|
|
118
|
+
ok: confirmed, result: { ...run, cancellationConfirmed: confirmed },
|
|
119
|
+
...(!confirmed && { error: { code: 'uncertain', ...describeVideoFailure(t('uncertain'), run.error?.code, 'cancel') } }),
|
|
120
|
+
} };
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
@@ -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, { configPath });
|
|
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
|
+
}
|