@playcraft/cli 0.1.23 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -38
- package/dist/agent/local-backend.js +1 -1
- package/dist/cli-root-help.js +0 -1
- package/dist/commands/build.js +4 -9
- package/dist/commands/create.js +33 -26
- package/dist/commands/image.js +6 -2
- package/dist/commands/login.js +42 -84
- package/dist/commands/skills.js +0 -2
- package/dist/commands/tools-generation.js +4 -2
- package/dist/commands/tools.js +0 -2
- package/dist/config.js +4 -59
- package/dist/index.js +1 -6
- package/dist/remix/clone.js +0 -2
- package/dist/remix/init-template.js +0 -2
- package/dist/remix/pull.js +0 -2
- package/dist/remix/push.js +1 -21
- package/dist/utils/agent-api-client.js +29 -148
- package/dist/utils/playcraft-http-client.js +4 -6
- package/package.json +2 -8
- package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +61 -23
- package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +61 -23
- package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +61 -23
- package/dist/auth/account-activation.js +0 -157
- package/dist/auth/messages.js +0 -30
- package/dist/commands/platform-skills.generated.js +0 -19
- package/dist/commands/tools-batch.js +0 -59
- package/dist/commands/workspace-runtime.js +0 -54
- package/dist/project-skills/commands.js +0 -72
- package/dist/project-skills/lifecycle.js +0 -28
- package/dist/project-skills/local-run.js +0 -112
- package/dist/project-skills/local-store.js +0 -149
- package/dist/project-skills/messages.js +0 -72
- package/dist/project-skills/reconcile.js +0 -62
- package/dist/project-skills/remote-cache.js +0 -51
- package/dist/project-skills/validation.js +0 -19
- package/dist/utils/environment-endpoints.js +0 -17
- package/dist/utils/tool-operation-journal.js +0 -124
- package/dist/workspace-runtime/codex/app-server.js +0 -574
- package/dist/workspace-runtime/codex/config-toml.js +0 -108
- package/dist/workspace-runtime/codex/jsonrpc-stdio.js +0 -123
- package/dist/workspace-runtime/codex/launcher-client.js +0 -163
- package/dist/workspace-runtime/codex/loopback.js +0 -143
- package/dist/workspace-runtime/codex/model-broker.js +0 -239
- package/dist/workspace-runtime/codex/native-adapter.js +0 -9
- package/dist/workspace-runtime/main.js +0 -10
- package/dist/workspace-runtime/persistence/journal.js +0 -355
- package/dist/workspace-runtime/persistence/sqlite-client.js +0 -61
- package/dist/workspace-runtime/persistence/sqlite-worker.js +0 -1015
- package/dist/workspace-runtime/previews/publish.js +0 -259
- package/dist/workspace-runtime/previews/single-file.js +0 -43
- package/dist/workspace-runtime/processes/managed-writes.js +0 -69
- package/dist/workspace-runtime/production/contracts.js +0 -17
- package/dist/workspace-runtime/production/controller.js +0 -207
- package/dist/workspace-runtime/production/dependencies.js +0 -60
- package/dist/workspace-runtime/production/native.js +0 -70
- package/dist/workspace-runtime/production/processes.js +0 -86
- package/dist/workspace-runtime/production/save-command.js +0 -20
- package/dist/workspace-runtime/production/stages.js +0 -175
- package/dist/workspace-runtime/production/storage.js +0 -32
- package/dist/workspace-runtime/serve.js +0 -199
- package/dist/workspace-runtime/server/auth.js +0 -21
- package/dist/workspace-runtime/server/connectivity.js +0 -201
- package/dist/workspace-runtime/server/desktop-host.js +0 -429
- package/dist/workspace-runtime/server/desktop-preview-config.js +0 -81
- package/dist/workspace-runtime/server/desktop-preview-service.js +0 -157
- package/dist/workspace-runtime/server/desktop-preview-static.js +0 -53
- package/dist/workspace-runtime/server/desktop-preview.js +0 -189
- package/dist/workspace-runtime/server/dispatch.js +0 -848
- package/dist/workspace-runtime/server/endpoints.js +0 -19
- package/dist/workspace-runtime/server/execution-group.js +0 -85
- package/dist/workspace-runtime/server/http.js +0 -919
- package/dist/workspace-runtime/server/lock.js +0 -53
- package/dist/workspace-runtime/server/rfb-watch-gate.js +0 -168
- package/dist/workspace-runtime/server/terminal-host.js +0 -294
- package/dist/workspace-runtime/server/types.js +0 -1
- package/dist/workspace-runtime/workspaces/attachments.js +0 -109
- package/dist/workspace-runtime/workspaces/batch-commit.js +0 -142
- package/dist/workspace-runtime/workspaces/cli-credentials.js +0 -111
- package/dist/workspace-runtime/workspaces/context-error.js +0 -2
- package/dist/workspace-runtime/workspaces/dependencies.js +0 -264
- package/dist/workspace-runtime/workspaces/developer-command.js +0 -64
- package/dist/workspace-runtime/workspaces/directories.js +0 -106
- package/dist/workspace-runtime/workspaces/directory-access.js +0 -20
- package/dist/workspace-runtime/workspaces/directory-maintenance.js +0 -111
- package/dist/workspace-runtime/workspaces/directory-stats.js +0 -49
- package/dist/workspace-runtime/workspaces/empty-template.js +0 -32
- package/dist/workspace-runtime/workspaces/files.js +0 -113
- package/dist/workspace-runtime/workspaces/git-credential-broker.js +0 -312
- package/dist/workspace-runtime/workspaces/git-credential-helper.js +0 -68
- package/dist/workspace-runtime/workspaces/git-direct-store.js +0 -155
- package/dist/workspace-runtime/workspaces/git.js +0 -471
- package/dist/workspace-runtime/workspaces/json5-edit.js +0 -170
- package/dist/workspace-runtime/workspaces/parameters.js +0 -272
- package/dist/workspace-runtime/workspaces/prepare.js +0 -263
- package/dist/workspace-runtime/workspaces/registry.js +0 -192
- package/dist/workspace-runtime/workspaces/revisions.js +0 -31
- package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +0 -46
- package/dist/workspace-runtime/workspaces/skills.js +0 -179
- package/project-template-v2/.claude/agents/artist.md +0 -82
- package/project-template-v2/.claude/agents/developer.md +0 -153
- package/project-template-v2/.claude/agents/game-designer.md +0 -264
- package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +0 -533
- package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +0 -153
- package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +0 -27
- package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +0 -208
- package/project-template-v2/.claude/agents/refs/atom-skill-library.md +0 -81
- package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +0 -432
- package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +0 -252
- package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +0 -266
- package/project-template-v2/.claude/agents/refs/framework-mda.md +0 -147
- package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +0 -123
- package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +0 -88
- package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +0 -67
- package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +0 -120
- package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +0 -300
- package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +0 -495
- package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +0 -1141
- package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +0 -111
- package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +0 -365
- package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +0 -412
- package/project-template-v2/.claude/agents/reviewer.md +0 -75
- package/project-template-v2/.claude/agents/technical-artist.md +0 -86
- package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +0 -243
- package/project-template-v2/.claude/hooks/user-prompt.mjs +0 -133
- package/project-template-v2/.claude/settings.json +0 -33
- package/project-template-v2/.claude/skills/brainstorming/SKILL.md +0 -161
- package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +0 -270
- package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +0 -177
- package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +0 -354
- package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +0 -148
- package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +0 -56
- package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +0 -62
- package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
- package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +0 -309
- package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +0 -182
- package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +0 -123
- package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +0 -205
- package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +0 -280
- package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +0 -184
- package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +0 -306
- package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +0 -298
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +0 -123
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +0 -254
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +0 -324
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +0 -97
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +0 -118
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +0 -137
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +0 -397
- package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +0 -296
- package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +0 -122
- package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +0 -219
- package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +0 -373
- package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +0 -161
- package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +0 -215
- package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +0 -382
- package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +0 -423
- package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +0 -158
- package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +0 -100
- package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +0 -167
- package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +0 -270
- package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +0 -236
- package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +0 -130
- package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +0 -390
- package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +0 -23
- package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +0 -39
- package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +0 -87
- package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +0 -240
- package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +0 -226
- package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +0 -308
- package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +0 -275
- package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +0 -134
- package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +0 -142
- package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +0 -153
- package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +0 -386
- package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +0 -182
- package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +0 -72
- package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +0 -121
- package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +0 -102
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +0 -127
- package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +0 -106
- package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +0 -128
- package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +0 -67
- package/project-template-v2/.claude/snapshot.mjs +0 -263
- package/project-template-v2/.playcraft/skills.lock.json +0 -152
- package/project-template-v2/CLAUDE.md +0 -146
- package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
- package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
- package/project-template-v2/assets/bundles/.gitkeep +0 -0
- package/project-template-v2/assets/images/bg/.gitkeep +0 -0
- package/project-template-v2/assets/images/reference/.gitkeep +0 -0
- package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
- package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
- package/project-template-v2/assets/images/ui/.gitkeep +0 -0
- package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
- package/project-template-v2/assets/models/.gitkeep +0 -0
- package/project-template-v2/docs/harness/iteration-1/context-flow.md +0 -254
- package/project-template-v2/docs/harness/iteration-1/generate-flow.md +0 -91
- package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +0 -214
- package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +0 -75
- package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +0 -63
- package/project-template-v2/docs/harness/iteration-2/context-flow.md +0 -223
- package/project-template-v2/docs/harness/iteration-2/generate-flow.md +0 -129
- package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +0 -267
- package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +0 -164
- package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +0 -115
- package/project-template-v2/docs/harness/orchestrator-flow.md +0 -364
- package/project-template-v2/docs/project-state.json +0 -60
- package/project-template-v2/docs/project-state.md +0 -72
- package/project-template-v2/docs/standards/README.md +0 -225
- package/project-template-v2/docs/standards/agent-behavior-standards.md +0 -174
- package/project-template-v2/docs/standards/artifacts/design-brief.md +0 -19
- package/project-template-v2/docs/standards/artifacts/design.md +0 -22
- package/project-template-v2/docs/standards/artifacts/game-code.md +0 -41
- package/project-template-v2/docs/standards/artifacts/todo-list.md +0 -41
- package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +0 -343
- package/project-template-v2/game/index.ts +0 -18
- package/project-template-v2/globals.d.ts +0 -51
- package/project-template-v2/index.css +0 -34
- package/project-template-v2/index.html +0 -18
- package/project-template-v2/main.ts +0 -9
- package/project-template-v2/package.json +0 -46
- package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +0 -31
- package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +0 -86
- package/project-template-v2/skills/_shared/scripts/dod-check.mjs +0 -153
- package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +0 -70
- package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +0 -91
- package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +0 -131
- package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +0 -80
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +0 -90
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +0 -93
- package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +0 -23
- package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +0 -230
- package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +0 -58
- package/project-template-v2/skills/_shared/scripts/state-get.mjs +0 -339
- package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +0 -39
- package/project-template-v2/skills/_shared/scripts/state-set.mjs +0 -94
- package/project-template-v2/skills/_shared/scripts/state-store.mjs +0 -783
- package/project-template-v2/skills/_shared/scripts/todo-add.mjs +0 -88
- package/project-template-v2/skills/_shared/scripts/todo-get.mjs +0 -130
- package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +0 -33
- package/project-template-v2/skills/_shared/scripts/todo-set.mjs +0 -47
- package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +0 -268
- package/project-template-v2/skills/_shared/scripts/verify-env.mjs +0 -285
- package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +0 -161
- package/project-template-v2/skills/playable-autoplay/SKILL.md +0 -176
- package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +0 -4
- package/project-template-v2/skills/playable-debug/SKILL.md +0 -116
- package/project-template-v2/skills/playable-debug/agents/openai.yaml +0 -4
- package/project-template-v2/skills/playable-debug/references/debug-config.md +0 -40
- package/project-template-v2/skills/playable-record/SKILL.md +0 -140
- package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +0 -104
- package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +0 -141
- package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +0 -425
- package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +0 -261
- package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +0 -398
- package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +0 -322
- package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +0 -105
- package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +0 -230
- package/project-template-v2/skills/playable-validate/SKILL.md +0 -61
- package/project-template-v2/skills/playable-validate/validation-rules.md +0 -14
- package/project-template-v2/skills/playable-verify-ui/SKILL.md +0 -63
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +0 -1
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +0 -218
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +0 -51
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +0 -59
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +0 -106
- package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +0 -116
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +0 -59
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +0 -64
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +0 -58
- package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +0 -333
- package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
- package/project-template-v2/tsconfig.json +0 -20
- package/project-template-v2/vite.config.ts +0 -27
- package/project-templates/batch-locks/phaser.yaml +0 -922
- package/project-templates/batch-locks/threejs.yaml +0 -978
- package/project-templates/empty/AGENTS.md +0 -23
- package/project-templates/empty/gitignore +0 -31
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { loadGlobalConfig } from '../config.js';
|
|
5
|
-
import { accountActivationMessage } from './messages.js';
|
|
6
|
-
export const ACCOUNT_PENDING_ACTIVATION = 'account_pending_activation';
|
|
7
|
-
export class AccountActivationError extends Error {
|
|
8
|
-
code;
|
|
9
|
-
status;
|
|
10
|
-
retryable = false;
|
|
11
|
-
constructor(code, message, status) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.code = code;
|
|
14
|
-
this.status = status;
|
|
15
|
-
this.name = 'AccountActivationError';
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
export function responseErrorCode(payload) {
|
|
19
|
-
if (!payload || typeof payload !== 'object')
|
|
20
|
-
return undefined;
|
|
21
|
-
const { error, code } = payload;
|
|
22
|
-
return typeof error?.code === 'string' ? error.code : typeof code === 'string' ? code : undefined;
|
|
23
|
-
}
|
|
24
|
-
export function pendingAccountActivationError(status, payload) {
|
|
25
|
-
return status === 403 && responseErrorCode(payload) === ACCOUNT_PENDING_ACTIVATION
|
|
26
|
-
? new AccountActivationError(ACCOUNT_PENDING_ACTIVATION, `${ACCOUNT_PENDING_ACTIVATION}: ${accountActivationMessage('pending')}`, status)
|
|
27
|
-
: undefined;
|
|
28
|
-
}
|
|
29
|
-
export function parseErrorPayload(text) {
|
|
30
|
-
try {
|
|
31
|
-
return JSON.parse(text);
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function localActivationConfig() {
|
|
38
|
-
for (const path of [
|
|
39
|
-
join(process.cwd(), '.playcraft.json'),
|
|
40
|
-
'/project/.playcraft.json',
|
|
41
|
-
join(homedir(), '.playcraft.json'),
|
|
42
|
-
]) {
|
|
43
|
-
if (!existsSync(path))
|
|
44
|
-
continue;
|
|
45
|
-
try {
|
|
46
|
-
const config = JSON.parse(readFileSync(path, 'utf8'));
|
|
47
|
-
if (config && typeof config === 'object' && !Array.isArray(config))
|
|
48
|
-
return config;
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// Follow the existing local credential lookup when a file is unreadable.
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return {};
|
|
55
|
-
}
|
|
56
|
-
function stringValue(value) {
|
|
57
|
-
return typeof value === 'string' && value ? value : undefined;
|
|
58
|
-
}
|
|
59
|
-
function activationBaseUrl(raw) {
|
|
60
|
-
try {
|
|
61
|
-
const url = new URL(raw);
|
|
62
|
-
if (!['http:', 'https:'].includes(url.protocol) ||
|
|
63
|
-
url.username ||
|
|
64
|
-
url.password ||
|
|
65
|
-
url.search ||
|
|
66
|
-
url.hash)
|
|
67
|
-
throw new Error();
|
|
68
|
-
url.pathname = url.pathname.replace(/\/+$/, '').replace(/\/api$/, '');
|
|
69
|
-
return url.toString().replace(/\/+$/, '');
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
throw new AccountActivationError('INVALID_ACTIVATION_TARGET', accountActivationMessage('invalidTarget'));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function savedTokenForTarget(config, rawUrl, target, environment) {
|
|
76
|
-
if (!rawUrl || (stringValue(config.env)?.trim() || '') !== environment)
|
|
77
|
-
return undefined;
|
|
78
|
-
try {
|
|
79
|
-
return activationBaseUrl(rawUrl) === target ? stringValue(config.token) : undefined;
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function normalizedSavedUrl(raw) {
|
|
86
|
-
try {
|
|
87
|
-
return raw ? activationBaseUrl(raw) : undefined;
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return undefined;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
export async function activateAccount(options, defaultBaseUrl) {
|
|
94
|
-
const local = localActivationConfig();
|
|
95
|
-
const global = loadGlobalConfig();
|
|
96
|
-
const localUrl = stringValue(local.apiUrl);
|
|
97
|
-
const globalUrl = stringValue(global.backendUrl) || stringValue(global.url);
|
|
98
|
-
const explicitUrl = options.url || process.env.PLAYCRAFT_API_URL || process.env.PLAYCRAFT_URL;
|
|
99
|
-
const target = activationBaseUrl(explicitUrl || localUrl || globalUrl || defaultBaseUrl);
|
|
100
|
-
const explicitToken = options.token || process.env.PLAYCRAFT_TOKEN || process.env.PLAYCRAFT_SANDBOX_TOKEN;
|
|
101
|
-
const savedUrls = [normalizedSavedUrl(localUrl), normalizedSavedUrl(globalUrl)].filter(Boolean);
|
|
102
|
-
const savedTokens = [stringValue(local.token), stringValue(global.token)].filter(Boolean);
|
|
103
|
-
const environmentsConflict = savedUrls.length === 2 &&
|
|
104
|
-
savedUrls[0] === savedUrls[1] &&
|
|
105
|
-
(stringValue(local.env)?.trim() || '') !== (stringValue(global.env)?.trim() || '');
|
|
106
|
-
const environmentTokensConflict = process.env.PLAYCRAFT_TOKEN &&
|
|
107
|
-
process.env.PLAYCRAFT_SANDBOX_TOKEN &&
|
|
108
|
-
process.env.PLAYCRAFT_TOKEN !== process.env.PLAYCRAFT_SANDBOX_TOKEN;
|
|
109
|
-
const environmentUrlsConflict = process.env.PLAYCRAFT_API_URL &&
|
|
110
|
-
process.env.PLAYCRAFT_URL &&
|
|
111
|
-
normalizedSavedUrl(process.env.PLAYCRAFT_API_URL) !==
|
|
112
|
-
normalizedSavedUrl(process.env.PLAYCRAFT_URL);
|
|
113
|
-
if ((!explicitUrl && new Set(savedUrls).size > 1) ||
|
|
114
|
-
(!explicitToken && new Set(savedTokens).size > 1) ||
|
|
115
|
-
(environmentsConflict && !process.env.PLAYCRAFT_ENV) ||
|
|
116
|
-
(environmentTokensConflict && !options.token) ||
|
|
117
|
-
(environmentUrlsConflict && !options.url)) {
|
|
118
|
-
throw new AccountActivationError('AMBIGUOUS_ACTIVATION_TARGET', accountActivationMessage('ambiguous'));
|
|
119
|
-
}
|
|
120
|
-
const environment = (process.env.PLAYCRAFT_ENV ||
|
|
121
|
-
(!explicitUrl ? (localUrl ? stringValue(local.env) : stringValue(global.env)) : '') ||
|
|
122
|
-
'').trim();
|
|
123
|
-
const token = explicitToken ||
|
|
124
|
-
savedTokenForTarget(local, localUrl, target, environment) ||
|
|
125
|
-
savedTokenForTarget(global, globalUrl, target, environment);
|
|
126
|
-
if (!token)
|
|
127
|
-
throw new AccountActivationError('AUTH_REQUIRED', accountActivationMessage('missingToken'));
|
|
128
|
-
if (!/^playcraft_pat_[A-Za-z0-9_-]{32}$/.test(token)) {
|
|
129
|
-
throw new AccountActivationError('INVALID_ACTIVATION_TOKEN', accountActivationMessage('invalidToken'));
|
|
130
|
-
}
|
|
131
|
-
let response;
|
|
132
|
-
try {
|
|
133
|
-
response = await fetch(`${target}/api/settings/personal-access-tokens/activate`, {
|
|
134
|
-
method: 'POST',
|
|
135
|
-
redirect: 'error',
|
|
136
|
-
signal: AbortSignal.timeout(30_000),
|
|
137
|
-
headers: {
|
|
138
|
-
Authorization: `Bearer ${token}`,
|
|
139
|
-
...(environment ? { 'playcraft-env': environment } : {}),
|
|
140
|
-
},
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
throw new AccountActivationError('ACTIVATION_UNCONFIRMED', accountActivationMessage('unavailable'));
|
|
145
|
-
}
|
|
146
|
-
if (!response.ok) {
|
|
147
|
-
await response.body?.cancel().catch(() => { });
|
|
148
|
-
throw new AccountActivationError('ACTIVATION_FAILED', accountActivationMessage('failed'), response.status);
|
|
149
|
-
}
|
|
150
|
-
const result = await response.json().catch(() => undefined);
|
|
151
|
-
if (!result ||
|
|
152
|
-
typeof result !== 'object' ||
|
|
153
|
-
result.accountStatus !== 'active') {
|
|
154
|
-
throw new AccountActivationError('ACTIVATION_UNCONFIRMED', accountActivationMessage('unavailable'), response.status);
|
|
155
|
-
}
|
|
156
|
-
console.log(accountActivationMessage('success'));
|
|
157
|
-
}
|
package/dist/auth/messages.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const messages = {
|
|
2
|
-
en: {
|
|
3
|
-
activateOption: 'Explicitly activate the account using the current personal access token',
|
|
4
|
-
tokenOption: 'Personal access token for --activate (or use PLAYCRAFT_TOKEN)',
|
|
5
|
-
pending: 'Account activation is required. Run `playcraft login --activate` with the same token and target environment, then rerun your command.',
|
|
6
|
-
success: 'Account activated. Rerun your original command to continue.',
|
|
7
|
-
missingToken: 'No personal access token matches this target environment. Provide PLAYCRAFT_TOKEN or log in to this environment first.',
|
|
8
|
-
invalidToken: 'Account activation requires a personal access token. A sandbox token cannot activate an account.',
|
|
9
|
-
ambiguous: 'Activation credentials or target environments conflict. Specify --url, PLAYCRAFT_ENV when needed, and an explicit personal access token using --token or PLAYCRAFT_TOKEN.',
|
|
10
|
-
invalidTarget: 'Use a web service base address (http:// or https://) without credentials, a query, or a fragment.',
|
|
11
|
-
failed: 'Account activation failed. Check the target environment and token before trying again.',
|
|
12
|
-
unavailable: 'Account activation could not be confirmed. Check your account status before explicitly trying again.',
|
|
13
|
-
},
|
|
14
|
-
zh: {
|
|
15
|
-
activateOption: '明确使用当前个人访问令牌激活账号',
|
|
16
|
-
tokenOption: '用于 --activate 的个人访问令牌(也可使用 PLAYCRAFT_TOKEN)',
|
|
17
|
-
pending: '账号需要激活。请使用同一令牌和目标环境主动运行 `playcraft login --activate`,然后重新执行原命令。',
|
|
18
|
-
success: '账号已激活,请重新执行原命令继续。',
|
|
19
|
-
missingToken: '没有与目标环境匹配的个人访问令牌。请提供 PLAYCRAFT_TOKEN,或先登录此环境。',
|
|
20
|
-
invalidToken: '激活账号需要个人访问令牌,沙箱令牌不能用于激活账号。',
|
|
21
|
-
ambiguous: '激活凭据或目标环境存在冲突。请明确指定 --url、所需的 PLAYCRAFT_ENV,并通过 --token 或 PLAYCRAFT_TOKEN 提供个人访问令牌。',
|
|
22
|
-
invalidTarget: '激活目标必须是网页服务基址(http:// 或 https://),不能包含凭据、查询参数或片段。',
|
|
23
|
-
failed: '账号激活失败,请检查目标环境和令牌后再尝试。',
|
|
24
|
-
unavailable: '无法确认账号是否已激活。请先检查账号状态,再主动决定是否重试。',
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
export function accountActivationMessage(key) {
|
|
28
|
-
const locale = process.env.PLAYCRAFT_LANGUAGE || process.env.LANG || 'en';
|
|
29
|
-
return messages[locale.startsWith('zh') ? 'zh' : 'en'][key];
|
|
30
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
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
|
-
];
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { batchCreateSchema } 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 a batch draft; confirm the whole batch in the browser',
|
|
8
|
-
input: 'Path to the batch draft JSON (JavaScript Object Notation, 数据交换格式) file',
|
|
9
|
-
status: 'Read a batch draft and its generation status',
|
|
10
|
-
id: 'Batch identifier',
|
|
11
|
-
created: 'Batch draft created',
|
|
12
|
-
help: '\nDraft shape: { clientRequestId, title, commonGoal, sourceWorkspaceId, engine, variants: [{ variantId, name, changes, preserves }] }\nUse the current workspace identifier as sourceWorkspaceId and a stable clientRequestId for retries. Maximum 10 variants. Confirm the batch in the browser.\n',
|
|
13
|
-
confirmation: 'Review the baseline and differences, then approve the whole batch in the browser.',
|
|
14
|
-
},
|
|
15
|
-
zh: {
|
|
16
|
-
create: '创建批次草案;整批确认须在浏览器完成',
|
|
17
|
-
input: '批次草案 JSON (JavaScript Object Notation, 数据交换格式) 文件路径',
|
|
18
|
-
status: '查询批次草案及生成状态',
|
|
19
|
-
id: '批次标识',
|
|
20
|
-
created: '批次草案已创建',
|
|
21
|
-
help: '\n草案格式:{ clientRequestId, title, commonGoal, sourceWorkspaceId, engine, variants: [{ variantId, name, changes, preserves }] }\nsourceWorkspaceId 填当前 workspace 标识,重试使用稳定的 clientRequestId。最多 10 个变体,整批在浏览器确认。\n',
|
|
22
|
-
confirmation: '请在浏览器查看基准和差异清单,然后确认整批。',
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
const language = () => /^zh/i.test(process.env.PLAYCRAFT_LANG ?? process.env.LANG ?? '') ? messages.zh : messages.en;
|
|
26
|
-
export async function createBatchDraft(path, client = new AgentApiClient()) {
|
|
27
|
-
const draft = batchCreateSchema.parse(JSON.parse(await readFile(path, 'utf8')));
|
|
28
|
-
return client.post('/create-batch', draft);
|
|
29
|
-
}
|
|
30
|
-
export function registerBatchCommands(tools) {
|
|
31
|
-
const t = language();
|
|
32
|
-
tools.command('create-batch')
|
|
33
|
-
.description(t.create)
|
|
34
|
-
.requiredOption('--input <path>', t.input)
|
|
35
|
-
.option('--json', 'JSON (JavaScript Object Notation, 数据交换格式)')
|
|
36
|
-
.addHelpText('after', t.help)
|
|
37
|
-
.action(async (opts) => {
|
|
38
|
-
try {
|
|
39
|
-
const result = await createBatchDraft(opts.input);
|
|
40
|
-
console.log(opts.json ? JSON.stringify(result, null, 2) : `${t.created}: ${result.batchId}\n${t.confirmation}`);
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
handleError(error);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
tools.command('get-batch')
|
|
47
|
-
.description(t.status)
|
|
48
|
-
.requiredOption('--batch-id <id>', t.id)
|
|
49
|
-
.action(async (opts) => {
|
|
50
|
-
try {
|
|
51
|
-
const client = new AgentApiClient();
|
|
52
|
-
const result = await client.get('/get-batch', { batchId: opts.batchId });
|
|
53
|
-
console.log(JSON.stringify(result, null, 2));
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
handleError(error);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { verifyLocalProjectSkills } from './validation.js';
|
|
2
|
-
export { verifyLocalProjectSkills } from './validation.js';
|
|
3
|
-
import { downloadLocalProjectSkillArtifacts } from './remote-cache.js';
|
|
4
|
-
import { resolve } from 'node:path';
|
|
5
|
-
import { inspectProjectSkills, } from '@playcraft/common/project-skills';
|
|
6
|
-
import { syncLocalProjectSkills, enableLocalProjectSkill, installFrozenProjectSkills, explainLocalProjectSkills } from './local-store.js';
|
|
7
|
-
import { runLocalProjectSkills, localProjectSkillUsage } from './local-run.js';
|
|
8
|
-
import { projectSkillsMessage as t } from './messages.js';
|
|
9
|
-
import { reconcileLocalProjectSkills } from './reconcile.js';
|
|
10
|
-
export async function inspectLocalProjectSkills(directory) {
|
|
11
|
-
const inventory = await inspectProjectSkills(directory);
|
|
12
|
-
// Report metadata only; never print complete skill bytes or project test data.
|
|
13
|
-
return { declaration: inventory.declaration, discovered: inventory.discovered, issues: inventory.issues,
|
|
14
|
-
sources: inventory.sources.map((source) => ({ entryKey: source.entryKey, root: source.root,
|
|
15
|
-
sourceTreeHash: source.sourceTreeHash, files: source.files.map((file) => file.path) })) };
|
|
16
|
-
}
|
|
17
|
-
export function registerProjectSkillsCommands(skills) {
|
|
18
|
-
const project = skills.command('project').description(t('description'));
|
|
19
|
-
const output = async (action) => {
|
|
20
|
-
try {
|
|
21
|
-
process.stdout.write(`${JSON.stringify(await action(), null, 2)}\n`);
|
|
22
|
-
}
|
|
23
|
-
catch (error) {
|
|
24
|
-
process.stderr.write(`${t('failed')}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
25
|
-
process.exitCode = 1;
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
project.command('run <prompt>').description(t('run')).requiredOption('--model <provider/model>', t('model'))
|
|
29
|
-
.option('--dir <path>', t('directory'), '.').action((prompt, options) => output(async () => {
|
|
30
|
-
const result = await runLocalProjectSkills(resolve(options.dir), { prompt, model: options.model });
|
|
31
|
-
if (result.exitCode !== 0)
|
|
32
|
-
process.exitCode = result.exitCode;
|
|
33
|
-
return result;
|
|
34
|
-
}));
|
|
35
|
-
project.command('usage').description(t('usage')).option('--dir <path>', t('directory'), '.')
|
|
36
|
-
.action((options) => output(() => localProjectSkillUsage(resolve(options.dir))));
|
|
37
|
-
project.command('sync').description(t('sync')).option('--dir <path>', t('directory'), '.')
|
|
38
|
-
.action((options) => output(() => syncLocalProjectSkills(resolve(options.dir))));
|
|
39
|
-
project.command('reconcile').description(t('reconcile')).option('--dir <path>', t('directory'), '.')
|
|
40
|
-
.action((options) => output(() => reconcileLocalProjectSkills(resolve(options.dir), { write: true })));
|
|
41
|
-
project.command('install').description(t('install')).requiredOption('--frozen', t('frozen')).option('--dir <path>', t('directory'), '.')
|
|
42
|
-
.option('--online', t('online')).action((options) => output(async () => {
|
|
43
|
-
const directory = resolve(options.dir);
|
|
44
|
-
if (options.online)
|
|
45
|
-
await downloadLocalProjectSkillArtifacts(directory);
|
|
46
|
-
return installFrozenProjectSkills(directory);
|
|
47
|
-
}));
|
|
48
|
-
for (const enabled of [true, false])
|
|
49
|
-
project.command(enabled ? 'enable <entryKey>' : 'disable <entryKey>')
|
|
50
|
-
.description(t(enabled ? 'enable' : 'disable')).option('--dir <path>', t('directory'), '.')
|
|
51
|
-
.action((entryKey, options) => output(() => enableLocalProjectSkill(resolve(options.dir), entryKey, enabled)));
|
|
52
|
-
project.command('explain').description(t('explain')).option('--dir <path>', t('directory'), '.')
|
|
53
|
-
.action((options) => output(() => explainLocalProjectSkills(resolve(options.dir))));
|
|
54
|
-
project.command('inspect').description(t('inspect')).option('--dir <path>', t('directory'), '.')
|
|
55
|
-
.action(async (options) => {
|
|
56
|
-
const result = await inspectLocalProjectSkills(resolve(options.dir));
|
|
57
|
-
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
58
|
-
if (result.issues.length)
|
|
59
|
-
process.exitCode = 1;
|
|
60
|
-
});
|
|
61
|
-
project.command('verify').description(t('verify')).option('--dir <path>', t('directory'), '.')
|
|
62
|
-
.option('--json', t('json')).action(async (options) => {
|
|
63
|
-
try {
|
|
64
|
-
const result = await verifyLocalProjectSkills(resolve(options.dir));
|
|
65
|
-
process.stdout.write(`${options.json ? JSON.stringify(result) : t('verified')}\n`);
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
process.stderr.write(`${t('failed')}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
69
|
-
process.exitCode = 1;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { readProjectSkillsLockFile } from '@playcraft/common/project-skills';
|
|
3
|
-
import { syncLocalProjectSkills, readLocalProjectSkillSnapshot, installFrozenProjectSkills } from './local-store.js';
|
|
4
|
-
import { verifyLocalProjectSkills } from './validation.js';
|
|
5
|
-
import { projectSkillsMessage as t } from './messages.js';
|
|
6
|
-
/** Existing formats keep their legacy consumer; format 3 never silently downgrades. */
|
|
7
|
-
export async function prepareLocalSkillLifecycle(directory, action, cache) {
|
|
8
|
-
const raw = await readProjectSkillsLockFile(directory);
|
|
9
|
-
const managed = raw !== null && JSON.parse(raw).lockVersion === 3;
|
|
10
|
-
if (!managed && process.env.PROJECT_SKILLS_ADOPTION_ENABLED !== 'true')
|
|
11
|
-
return { managed: false };
|
|
12
|
-
if (raw !== null && !managed)
|
|
13
|
-
return { managed: false, legacy: true };
|
|
14
|
-
if (action === 'create' || action === 'push' || !managed)
|
|
15
|
-
await syncLocalProjectSkills(directory, cache);
|
|
16
|
-
await verifyLocalProjectSkills(directory);
|
|
17
|
-
const snapshot = await readLocalProjectSkillSnapshot(directory);
|
|
18
|
-
if (action === 'push') {
|
|
19
|
-
const paths = ['.playcraft/skills.json', '.playcraft/skills.lock.json', ...snapshot.declaration.entries.flatMap(entry => entry.source.kind === 'repository' ? [entry.source.root, ...(entry.projectFiles ?? [])] : [])];
|
|
20
|
-
const status = spawnSync('git', ['status', '--porcelain', '--', ...paths], { cwd: directory, encoding: 'utf8' });
|
|
21
|
-
if (status.status !== 0 || status.stdout.trim())
|
|
22
|
-
throw new Error(t('commitRequired'));
|
|
23
|
-
}
|
|
24
|
-
// Source-only checkouts work offline. Registry packages remain exact and require an authorized cache fill.
|
|
25
|
-
if (!snapshot.lock.entries.some(entry => entry.revision.kind === 'release'))
|
|
26
|
-
await installFrozenProjectSkills(directory, cache);
|
|
27
|
-
return { managed: true, declarationHash: snapshot.lock.declarationHash };
|
|
28
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { spawn, execFileSync } from 'node:child_process';
|
|
2
|
-
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
-
import { createRequire } from 'node:module';
|
|
4
|
-
import { readFile, writeFile, mkdir, readdir, realpath } from 'node:fs/promises';
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import { pathToFileURL } from 'node:url';
|
|
7
|
-
import { createInterface } from 'node:readline';
|
|
8
|
-
import { effectiveProjectSkills, readManagedSkillEvidence } from '@playcraft/common/project-skills';
|
|
9
|
-
import { installFrozenProjectSkills, readLocalProjectSkillSnapshot, projectSkillsCache } from './local-store.js';
|
|
10
|
-
import { verifyLocalProjectSkills } from './validation.js';
|
|
11
|
-
import { projectSkillsMessage as t } from './messages.js';
|
|
12
|
-
const require = createRequire(import.meta.url);
|
|
13
|
-
export async function localProjectSkillUsage(directory, cache = projectSkillsCache()) {
|
|
14
|
-
const root = join(cache, 'usage', createHash('sha256').update(await realpath(directory)).digest('hex'));
|
|
15
|
-
let files;
|
|
16
|
-
try {
|
|
17
|
-
files = await readdir(root);
|
|
18
|
-
}
|
|
19
|
-
catch (error) {
|
|
20
|
-
if (error.code === 'ENOENT')
|
|
21
|
-
return [];
|
|
22
|
-
throw error;
|
|
23
|
-
}
|
|
24
|
-
return Promise.all(files.filter(file => /^[a-f0-9-]+\.json$/.test(file)).sort().map(async (file) => JSON.parse(await readFile(join(root, file), 'utf8'))));
|
|
25
|
-
}
|
|
26
|
-
/** Local evidence is explicitly client-reported; it never acts as a server evaluation or access grant. */
|
|
27
|
-
export async function runLocalProjectSkills(directory, options, cache = projectSkillsCache()) {
|
|
28
|
-
if (execFileSync('opencode', ['--version'], { encoding: 'utf8', timeout: 10000 }).trim() !== '1.18.31')
|
|
29
|
-
throw new Error(t('runner'));
|
|
30
|
-
const cwd = await realpath(directory);
|
|
31
|
-
await verifyLocalProjectSkills(cwd);
|
|
32
|
-
const snapshot = await readLocalProjectSkillSnapshot(cwd);
|
|
33
|
-
const installed = await installFrozenProjectSkills(cwd, cache);
|
|
34
|
-
const runId = randomUUID(), runtimeRoot = join(installed.generation, '.runtime');
|
|
35
|
-
const home = join(runtimeRoot, 'home');
|
|
36
|
-
await mkdir(home, { recursive: true, mode: 0o700 });
|
|
37
|
-
const entries = await Promise.all(effectiveProjectSkills(snapshot.declaration, snapshot.lock, 'sandbox-agent').map(async (entry) => {
|
|
38
|
-
const bodyFile = join(installed.generation, entry.entryKey, 'SKILL.md');
|
|
39
|
-
return { name: entry.entryKey, skillRef: entry.revision.skillRef, revisionId: entry.revision.kind === 'source' ? entry.revision.sourceRevision : entry.revision.version,
|
|
40
|
-
artifactHash: entry.revision.artifactHash, bodyFile, bodyHash: createHash('sha256').update(await readFile(bodyFile)).digest('hex'), description: entry.revision.skillRef };
|
|
41
|
-
}));
|
|
42
|
-
await writeFile(join(runtimeRoot, 'manifest.json'), JSON.stringify({ schemaVersion: 1, runtimeId: runId, lockId: snapshot.lock.declarationHash, entries }), { mode: 0o400 });
|
|
43
|
-
await writeFile(join(runtimeRoot, 'opencode.json'), JSON.stringify({ model: options.model,
|
|
44
|
-
plugin: [pathToFileURL(require.resolve('@playcraft/common/project-skills/runtime-plugin')).href] }), { mode: 0o400 });
|
|
45
|
-
const usageRoot = join(cache, 'usage', createHash('sha256').update(cwd).digest('hex'));
|
|
46
|
-
await mkdir(usageRoot, { recursive: true, mode: 0o700 });
|
|
47
|
-
const evidence = new Map();
|
|
48
|
-
const report = { schemaVersion: 1, runId, declarationHash: snapshot.lock.declarationHash, provenance: 'local-client-reported',
|
|
49
|
-
runnerVersion: '1.18.31', model: options.model, startedAt: new Date().toISOString(), status: 'running', collectionStatus: 'collecting', loaded: [] };
|
|
50
|
-
const reportPath = join(usageRoot, `${runId}.json`);
|
|
51
|
-
await writeFile(reportPath, JSON.stringify(report), { mode: 0o600 });
|
|
52
|
-
const environment = { ...process.env, HOME: home, XDG_CONFIG_HOME: join(home, '.config'), XDG_DATA_HOME: join(home, '.local/share'), XDG_STATE_HOME: join(home, '.local/state'), XDG_CACHE_HOME: join(home, '.cache'),
|
|
53
|
-
OPENCODE_CONFIG: join(runtimeRoot, 'opencode.json'), OPENCODE_CONFIG_DIR: join(runtimeRoot, 'config'),
|
|
54
|
-
OPENCODE_DISABLE_PROJECT_CONFIG: 'true', OPENCODE_DISABLE_CLAUDE_CODE: 'true', OPENCODE_DISABLE_DEFAULT_PLUGINS: 'true', OPENCODE_DISABLE_AUTOUPDATE: 'true',
|
|
55
|
-
PLAYCRAFT_SKILL_RUNTIME_FILE: join(runtimeRoot, 'manifest.json') };
|
|
56
|
-
delete environment.PLAYCRAFT_SKILL_RUNTIME_ROOT;
|
|
57
|
-
delete environment.OPENCODE_CONFIG_CONTENT;
|
|
58
|
-
let child;
|
|
59
|
-
let cancelled = false, killTimer;
|
|
60
|
-
const cancel = () => {
|
|
61
|
-
cancelled = true;
|
|
62
|
-
child?.kill('SIGTERM');
|
|
63
|
-
killTimer ??= setTimeout(() => child?.kill('SIGKILL'), 5000);
|
|
64
|
-
killTimer.unref();
|
|
65
|
-
};
|
|
66
|
-
process.once('SIGINT', cancel);
|
|
67
|
-
process.once('SIGTERM', cancel);
|
|
68
|
-
try {
|
|
69
|
-
child = spawn('opencode', ['run', '--format', 'json', '--model', options.model, '--', options.prompt], { cwd, env: environment, stdio: ['ignore', 'pipe', 'inherit'] });
|
|
70
|
-
// Resolve spawn failures so an early error cannot become an unhandled rejection while reading stdout.
|
|
71
|
-
const finished = new Promise(resolve => {
|
|
72
|
-
child.once('error', error => resolve({ code: 1, error }));
|
|
73
|
-
child.once('close', code => resolve({ code: code ?? 1 }));
|
|
74
|
-
});
|
|
75
|
-
const lines = createInterface({ input: child.stdout });
|
|
76
|
-
let partial = false;
|
|
77
|
-
for await (const line of lines) {
|
|
78
|
-
try {
|
|
79
|
-
const event = JSON.parse(line);
|
|
80
|
-
const parsed = readManagedSkillEvidence(event);
|
|
81
|
-
if (parsed?.runtimeId === runId && parsed.lockId === report.declarationHash && entries.some(entry => entry.revisionId === parsed.skillVersionId && entry.artifactHash === parsed.artifactHash && entry.bodyHash === parsed.bodyHash)) {
|
|
82
|
-
evidence.set(parsed.dedupeKey, parsed);
|
|
83
|
-
report.loaded = [...evidence.values()];
|
|
84
|
-
await writeFile(reportPath, JSON.stringify(report), { mode: 0o600 });
|
|
85
|
-
}
|
|
86
|
-
if (event.type === 'text' && typeof event.part?.text === 'string')
|
|
87
|
-
process.stderr.write(event.part.text);
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
partial = true;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const result = await finished;
|
|
94
|
-
if (result.error)
|
|
95
|
-
throw result.error;
|
|
96
|
-
const code = cancelled ? 130 : result.code;
|
|
97
|
-
report.status = cancelled ? 'cancelled' : code === 0 ? 'completed' : 'failed';
|
|
98
|
-
report.collectionStatus = code === 0 && !partial ? 'complete' : 'partial';
|
|
99
|
-
return { ...report, reportPath, exitCode: code };
|
|
100
|
-
}
|
|
101
|
-
finally {
|
|
102
|
-
if (killTimer)
|
|
103
|
-
clearTimeout(killTimer);
|
|
104
|
-
process.removeListener('SIGINT', cancel);
|
|
105
|
-
process.removeListener('SIGTERM', cancel);
|
|
106
|
-
if (report.status === 'running') {
|
|
107
|
-
report.status = 'failed';
|
|
108
|
-
report.collectionStatus = 'partial';
|
|
109
|
-
}
|
|
110
|
-
await writeFile(reportPath, JSON.stringify(report), { mode: 0o600 });
|
|
111
|
-
}
|
|
112
|
-
}
|