@playdrop/playdrop-cli 0.13.16 → 0.14.0
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/config/client-meta.json +2 -2
- package/dist/apps/staticHtml.js +1 -0
- package/dist/commandContext.js +1 -1
- package/dist/commands/captureListing.d.ts +52 -0
- package/dist/commands/captureListing.js +213 -12
- package/dist/commands/upload.d.ts +12 -1
- package/dist/commands/upload.js +97 -88
- package/dist/commands/whoami.js +10 -1
- package/dist/commands/worker/runtime.js +2 -0
- package/dist/commands/worker.d.ts +28 -1
- package/dist/commands/worker.js +381 -29
- package/dist/index.js +17 -2
- package/dist/listingPreflight.d.ts +2 -1
- package/dist/listingPreflight.js +63 -35
- package/dist/workerAppProject.d.ts +2 -0
- package/dist/workerAppProject.js +33 -0
- package/node_modules/@playdrop/api-client/dist/client.d.ts +5 -2
- package/node_modules/@playdrop/api-client/dist/client.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts +27 -1
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/domains/agent-tasks.js +103 -0
- package/node_modules/@playdrop/api-client/dist/index.d.ts +4 -2
- package/node_modules/@playdrop/api-client/dist/index.d.ts.map +1 -1
- package/node_modules/@playdrop/api-client/dist/index.js +10 -0
- package/node_modules/@playdrop/config/client-meta.json +2 -2
- package/node_modules/@playdrop/types/dist/api.d.ts +150 -2
- package/node_modules/@playdrop/types/dist/api.d.ts.map +1 -1
- package/node_modules/@playdrop/types/dist/api.js +3 -1
- package/package.json +1 -1
package/dist/commands/upload.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.upload = upload;
|
|
|
6
6
|
exports.resolveWorkerPlaydropAssetRequirement = resolveWorkerPlaydropAssetRequirement;
|
|
7
7
|
exports.assertAgentNewGamePlaytestContract = assertAgentNewGamePlaytestContract;
|
|
8
8
|
exports.assertWorkerAppLocalUploadPreflight = assertWorkerAppLocalUploadPreflight;
|
|
9
|
+
exports.preflightWorkerAppProject = preflightWorkerAppProject;
|
|
9
10
|
exports.publishWorkerAppProject = publishWorkerAppProject;
|
|
10
11
|
exports.publishStaticHtmlProject = publishStaticHtmlProject;
|
|
11
12
|
const node_fs_1 = require("node:fs");
|
|
@@ -23,6 +24,7 @@ const output_1 = require("../output");
|
|
|
23
24
|
const taskSelection_1 = require("../taskSelection");
|
|
24
25
|
const taskUtils_1 = require("../taskUtils");
|
|
25
26
|
const uploadLog_1 = require("../uploadLog");
|
|
27
|
+
const workerAppProject_1 = require("../workerAppProject");
|
|
26
28
|
const upload_content_1 = require("./upload-content");
|
|
27
29
|
const appUrls_1 = require("../appUrls");
|
|
28
30
|
const devRuntimeAssets_1 = require("./devRuntimeAssets");
|
|
@@ -1275,19 +1277,6 @@ function assertAgentNewGamePlaytestContract(task) {
|
|
|
1275
1277
|
}
|
|
1276
1278
|
}
|
|
1277
1279
|
}
|
|
1278
|
-
const WORKER_SUPERVISOR_SOURCE_EXCLUDES = [
|
|
1279
|
-
'PLAYDROP_TASK.md',
|
|
1280
|
-
'AGENTS.md',
|
|
1281
|
-
'CLAUDE.md',
|
|
1282
|
-
'.playdrop/',
|
|
1283
|
-
'.playdrop-task-events/',
|
|
1284
|
-
'bin/playdrop',
|
|
1285
|
-
];
|
|
1286
|
-
const WORKER_SUPERVISOR_BUNDLE_EXCLUDES = [
|
|
1287
|
-
...WORKER_SUPERVISOR_SOURCE_EXCLUDES,
|
|
1288
|
-
'assets/marketing/',
|
|
1289
|
-
'listing/',
|
|
1290
|
-
];
|
|
1291
1280
|
function appTaskSatisfiesPlaydropAssetRequirement(task, requirement) {
|
|
1292
1281
|
if (!requirement) {
|
|
1293
1282
|
return true;
|
|
@@ -1706,58 +1695,6 @@ async function assertNewGameDeclaredAssetsAreUsedAtRuntime(input) {
|
|
|
1706
1695
|
throw new Error('agent_task_game_asset_fallback_disallowed: new game tasks must fail clearly when declared gameplay assets cannot load instead of rendering placeholder or fallback visuals.');
|
|
1707
1696
|
}
|
|
1708
1697
|
}
|
|
1709
|
-
function assertGreyboxReport(task) {
|
|
1710
|
-
const reportPath = (0, node_path_1.join)(task.projectDir, 'greybox-report.json');
|
|
1711
|
-
if (!(0, node_fs_1.existsSync)(reportPath)) {
|
|
1712
|
-
throw new Error('agent_task_greybox_report_missing: greybox-report.json must prove the prototype and final start, agency, and restart checks.');
|
|
1713
|
-
}
|
|
1714
|
-
let report;
|
|
1715
|
-
try {
|
|
1716
|
-
const parsed = JSON.parse((0, node_fs_1.readFileSync)(reportPath, 'utf8'));
|
|
1717
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
1718
|
-
throw new Error('report must be a JSON object');
|
|
1719
|
-
}
|
|
1720
|
-
report = parsed;
|
|
1721
|
-
}
|
|
1722
|
-
catch (error) {
|
|
1723
|
-
throw new Error(`agent_task_greybox_report_invalid: ${error instanceof Error ? error.message : String(error)}`);
|
|
1724
|
-
}
|
|
1725
|
-
if (report.schemaVersion !== 1 || Object.keys(report).some((key) => !['schemaVersion', 'prototype', 'final'].includes(key))) {
|
|
1726
|
-
throw new Error('agent_task_greybox_report_invalid: expected schemaVersion 1 with only prototype and final sections.');
|
|
1727
|
-
}
|
|
1728
|
-
for (const sectionName of ['prototype', 'final']) {
|
|
1729
|
-
const rawSection = report[sectionName];
|
|
1730
|
-
if (!rawSection || typeof rawSection !== 'object' || Array.isArray(rawSection)) {
|
|
1731
|
-
throw new Error(`agent_task_greybox_report_invalid: ${sectionName} must contain start, agency, and restart.`);
|
|
1732
|
-
}
|
|
1733
|
-
const section = rawSection;
|
|
1734
|
-
if (Object.keys(section).length !== 3
|
|
1735
|
-
|| Object.keys(section).some((key) => !['start', 'agency', 'restart'].includes(key))) {
|
|
1736
|
-
throw new Error(`agent_task_greybox_report_invalid: ${sectionName} must contain exactly start, agency, and restart.`);
|
|
1737
|
-
}
|
|
1738
|
-
for (const checkName of ['start', 'agency', 'restart']) {
|
|
1739
|
-
const rawCheck = section[checkName];
|
|
1740
|
-
if (!rawCheck || typeof rawCheck !== 'object' || Array.isArray(rawCheck)) {
|
|
1741
|
-
throw new Error(`agent_task_greybox_report_invalid: ${sectionName}.${checkName} must be an object.`);
|
|
1742
|
-
}
|
|
1743
|
-
const check = rawCheck;
|
|
1744
|
-
const expectedKeys = checkName === 'agency'
|
|
1745
|
-
? ['passed', 'normalInput', 'controlCondition', 'observation']
|
|
1746
|
-
: ['passed', 'observation'];
|
|
1747
|
-
if (Object.keys(check).length !== expectedKeys.length
|
|
1748
|
-
|| Object.keys(check).some((key) => !expectedKeys.includes(key))
|
|
1749
|
-
|| check.passed !== true
|
|
1750
|
-
|| typeof check.observation !== 'string'
|
|
1751
|
-
|| !check.observation.trim()
|
|
1752
|
-
|| (checkName === 'agency' && (typeof check.normalInput !== 'string'
|
|
1753
|
-
|| !check.normalInput.trim()
|
|
1754
|
-
|| typeof check.controlCondition !== 'string'
|
|
1755
|
-
|| !check.controlCondition.trim()))) {
|
|
1756
|
-
throw new Error(`agent_task_greybox_report_invalid: ${sectionName}.${checkName} must be complete and passing.`);
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1760
|
-
}
|
|
1761
1698
|
async function collectUploadPreflightErrors(checks) {
|
|
1762
1699
|
const errors = [];
|
|
1763
1700
|
for (const check of checks) {
|
|
@@ -1770,14 +1707,27 @@ async function collectUploadPreflightErrors(checks) {
|
|
|
1770
1707
|
}
|
|
1771
1708
|
return errors;
|
|
1772
1709
|
}
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1710
|
+
function assertAgentTaskReleaseNotes(task) {
|
|
1711
|
+
const releaseNotes = task.releaseNotes?.trim() ?? '';
|
|
1712
|
+
if (!releaseNotes) {
|
|
1713
|
+
throw new Error('agent_task_release_notes_missing');
|
|
1714
|
+
}
|
|
1715
|
+
if (/[\r\n]/.test(releaseNotes)) {
|
|
1716
|
+
throw new Error('agent_task_release_notes_multiline');
|
|
1776
1717
|
}
|
|
1718
|
+
if (releaseNotes.length > 240) {
|
|
1719
|
+
throw new Error('agent_task_release_notes_too_long');
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
async function assertWorkerAppLocalUploadPreflight(input) {
|
|
1723
|
+
const complete = input.stage !== 'PRE_CAPTURE';
|
|
1724
|
+
const existingCaptureReport = input.task.listing?.captureReportPath;
|
|
1725
|
+
const shouldCheckExistingCapture = !complete
|
|
1726
|
+
&& Boolean(existingCaptureReport)
|
|
1727
|
+
&& (0, node_fs_1.existsSync)(existingCaptureReport);
|
|
1777
1728
|
const errors = await collectUploadPreflightErrors([
|
|
1778
|
-
() =>
|
|
1779
|
-
() => (0, listingPreflight_1.assertAgentGameHeroListingPreflight)(input.task),
|
|
1780
|
-
...(input.kind === 'NEW_GAME' ? [() => (0, listingPreflight_1.assertAgentNewGameArtDirectionPreflight)(input.task)] : []),
|
|
1729
|
+
() => assertAgentTaskReleaseNotes(input.task),
|
|
1730
|
+
...(complete ? [() => (0, listingPreflight_1.assertAgentGameHeroListingPreflight)(input.task)] : []),
|
|
1781
1731
|
...(input.kind === 'NEW_GAME' ? [() => assertAgentNewGamePlaytestContract(input.task)] : []),
|
|
1782
1732
|
() => {
|
|
1783
1733
|
if (!appTaskSatisfiesPlaydropAssetRequirement(input.task, input.playdropAssetRequirement)) {
|
|
@@ -1794,10 +1744,23 @@ async function assertWorkerAppLocalUploadPreflight(input) {
|
|
|
1794
1744
|
creatorUsername: input.creatorUsername?.trim() ?? '',
|
|
1795
1745
|
task: input.task,
|
|
1796
1746
|
}),
|
|
1797
|
-
(
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1747
|
+
...(complete
|
|
1748
|
+
? [
|
|
1749
|
+
() => (0, listingPreflight_1.assertAgentGameScreenshotListingPreflight)(input.task),
|
|
1750
|
+
() => (0, listingPreflight_1.assertAgentGameCaptureReportPreflight)(input.task, {
|
|
1751
|
+
requireCaptureReport: input.executionTarget === 'FIRST_PARTY',
|
|
1752
|
+
expectedRuntimeBundleHash: input.expectedRuntimeBundleHash,
|
|
1753
|
+
}),
|
|
1754
|
+
]
|
|
1755
|
+
: []),
|
|
1756
|
+
...(shouldCheckExistingCapture
|
|
1757
|
+
? [
|
|
1758
|
+
() => (0, listingPreflight_1.assertAgentGameCaptureReportPreflight)(input.task, {
|
|
1759
|
+
requireCaptureReport: false,
|
|
1760
|
+
expectedRuntimeBundleHash: input.expectedRuntimeBundleHash,
|
|
1761
|
+
}),
|
|
1762
|
+
]
|
|
1763
|
+
: []),
|
|
1801
1764
|
]);
|
|
1802
1765
|
if (errors.length === 1) {
|
|
1803
1766
|
throw new Error(errors[0]);
|
|
@@ -1806,10 +1769,7 @@ async function assertWorkerAppLocalUploadPreflight(input) {
|
|
|
1806
1769
|
throw new Error(`agent_task_upload_preflight_failed:\n${errors.map((error, index) => `${index + 1}. ${error}`).join('\n')}`);
|
|
1807
1770
|
}
|
|
1808
1771
|
}
|
|
1809
|
-
|
|
1810
|
-
// "playdrop project publish", but always as one PRIVATE draft version for the
|
|
1811
|
-
// task's creator, with browser launch checks on before the version is created.
|
|
1812
|
-
async function publishWorkerAppProject(input) {
|
|
1772
|
+
async function prepareWorkerAppProject(input, stage) {
|
|
1813
1773
|
const creatorUsername = input.creatorUsername.trim();
|
|
1814
1774
|
if (!creatorUsername) {
|
|
1815
1775
|
throw new Error('agent_task_creator_username_missing');
|
|
@@ -1830,15 +1790,21 @@ async function publishWorkerAppProject(input) {
|
|
|
1830
1790
|
if (expectedAppName && appTask.name !== expectedAppName) {
|
|
1831
1791
|
throw new Error(`agent_task_output_app_name_mismatch: expected catalogue app "${expectedAppName}", found "${appTask.name}".`);
|
|
1832
1792
|
}
|
|
1793
|
+
const expectedDisplayName = input.expectedDisplayName?.trim() ?? '';
|
|
1794
|
+
if (expectedDisplayName && appTask.displayName !== expectedDisplayName) {
|
|
1795
|
+
throw new Error(`agent_task_output_display_name_mismatch: expected "${expectedDisplayName}", found "${appTask.displayName ?? ''}".`);
|
|
1796
|
+
}
|
|
1797
|
+
const expectedSubtitle = input.expectedSubtitle?.trim() ?? '';
|
|
1798
|
+
if (expectedSubtitle && appTask.subtitle !== expectedSubtitle) {
|
|
1799
|
+
throw new Error(`agent_task_output_subtitle_mismatch: expected "${expectedSubtitle}", found "${appTask.subtitle ?? ''}".`);
|
|
1800
|
+
}
|
|
1801
|
+
if (input.expectedPrimarySurface && appTask.primarySurface !== input.expectedPrimarySurface) {
|
|
1802
|
+
throw new Error(`agent_task_output_primary_surface_mismatch: expected "${input.expectedPrimarySurface}", found "${appTask.primarySurface ?? ''}".`);
|
|
1803
|
+
}
|
|
1833
1804
|
if ((input.kind === 'NEW_GAME' || input.kind === 'REMIX_GAME') && (appTask.type ?? 'GAME') !== 'GAME') {
|
|
1834
1805
|
throw new Error(`agent_task_game_type_invalid:${appTask.type ?? 'missing'}`);
|
|
1835
1806
|
}
|
|
1836
|
-
const task =
|
|
1837
|
-
...appTask,
|
|
1838
|
-
versionVisibility: 'PRIVATE',
|
|
1839
|
-
sourceArchiveExcludeRelativeFiles: WORKER_SUPERVISOR_SOURCE_EXCLUDES,
|
|
1840
|
-
bundleArchiveExcludeRelativeFiles: WORKER_SUPERVISOR_BUNDLE_EXCLUDES,
|
|
1841
|
-
};
|
|
1807
|
+
const task = (0, workerAppProject_1.prepareWorkerAppTask)(appTask);
|
|
1842
1808
|
if (input.kind === 'REMIX_GAME') {
|
|
1843
1809
|
const expectedRemixRef = input.remixSourceRef?.trim() ?? '';
|
|
1844
1810
|
if (!expectedRemixRef) {
|
|
@@ -1852,6 +1818,9 @@ async function publishWorkerAppProject(input) {
|
|
|
1852
1818
|
throw new Error(`agent_task_remix_ref_mismatch:${catalogueRemixRef}:${expectedRemixRef}`);
|
|
1853
1819
|
}
|
|
1854
1820
|
}
|
|
1821
|
+
await (0, apps_1.validateAppTask)(task);
|
|
1822
|
+
const isExternal = task.hostingMode === 'EXTERNAL' || Boolean(task.externalUrl);
|
|
1823
|
+
const artifacts = isExternal ? null : await (0, apps_1.buildApp)(task);
|
|
1855
1824
|
await assertWorkerAppLocalUploadPreflight({
|
|
1856
1825
|
task,
|
|
1857
1826
|
kind: input.kind,
|
|
@@ -1859,12 +1828,38 @@ async function publishWorkerAppProject(input) {
|
|
|
1859
1828
|
creatorUsername,
|
|
1860
1829
|
playdropAssetRequirement: input.playdropAssetRequirement,
|
|
1861
1830
|
creatorRequest: input.creatorRequest,
|
|
1831
|
+
stage,
|
|
1832
|
+
expectedRuntimeBundleHash: artifacts?.bundleHash,
|
|
1862
1833
|
});
|
|
1863
1834
|
await assertDeclared3dPlaydropPacksContainRuntimeModels({
|
|
1864
1835
|
client: input.client,
|
|
1865
1836
|
task,
|
|
1866
1837
|
creatorRequest: input.creatorRequest,
|
|
1867
1838
|
});
|
|
1839
|
+
return {
|
|
1840
|
+
task,
|
|
1841
|
+
artifacts,
|
|
1842
|
+
warnings: [...selection.warnings],
|
|
1843
|
+
creatorUsername,
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
// Runs every worker upload check that can be proven before final recorder
|
|
1847
|
+
// output exists. It intentionally performs no app registration, metadata
|
|
1848
|
+
// update, upload-session creation, file upload, or version creation.
|
|
1849
|
+
async function preflightWorkerAppProject(input) {
|
|
1850
|
+
const prepared = await prepareWorkerAppProject(input, 'PRE_CAPTURE');
|
|
1851
|
+
return {
|
|
1852
|
+
appName: prepared.task.name,
|
|
1853
|
+
creatorUsername: prepared.creatorUsername,
|
|
1854
|
+
warnings: prepared.warnings,
|
|
1855
|
+
};
|
|
1856
|
+
}
|
|
1857
|
+
// Task upload path used by "playdrop task upload": same internal pipeline as
|
|
1858
|
+
// "playdrop project publish", but always as one PRIVATE draft version for the
|
|
1859
|
+
// task's creator, with browser launch checks on before the version is created.
|
|
1860
|
+
async function publishWorkerAppProject(input) {
|
|
1861
|
+
const prepared = await prepareWorkerAppProject(input, 'COMPLETE');
|
|
1862
|
+
const { task, artifacts, creatorUsername } = prepared;
|
|
1868
1863
|
const { app } = await (0, registration_1.ensureRegisteredHostedAppShell)({
|
|
1869
1864
|
client: input.client,
|
|
1870
1865
|
creatorUsername,
|
|
@@ -1896,6 +1891,7 @@ async function publishWorkerAppProject(input) {
|
|
|
1896
1891
|
mediaCaptureRequired: input.executionTarget === 'FIRST_PARTY',
|
|
1897
1892
|
playtestSmokeCheckRequired: input.kind === 'NEW_GAME',
|
|
1898
1893
|
captureSession,
|
|
1894
|
+
...(artifacts ? { artifacts } : {}),
|
|
1899
1895
|
});
|
|
1900
1896
|
if (!uploadResult.versionCreated || !uploadResult.version) {
|
|
1901
1897
|
throw new Error(`App "${task.name}" upload did not return a created version.`);
|
|
@@ -1913,7 +1909,7 @@ async function publishWorkerAppProject(input) {
|
|
|
1913
1909
|
version: uploadResult.version,
|
|
1914
1910
|
appName: task.name,
|
|
1915
1911
|
creatorUsername,
|
|
1916
|
-
warnings: [...
|
|
1912
|
+
warnings: [...prepared.warnings, ...warnings],
|
|
1917
1913
|
};
|
|
1918
1914
|
}
|
|
1919
1915
|
async function publishStaticHtmlProject(input) {
|
|
@@ -1933,6 +1929,14 @@ async function publishStaticHtmlProject(input) {
|
|
|
1933
1929
|
});
|
|
1934
1930
|
try {
|
|
1935
1931
|
if (input.taskId !== undefined && !input.claimedAppName?.trim()) {
|
|
1932
|
+
const subtitle = prepared.metadata.description?.trim() ?? '';
|
|
1933
|
+
if (!subtitle) {
|
|
1934
|
+
throw new Error('static_game_subtitle_required');
|
|
1935
|
+
}
|
|
1936
|
+
const primarySurface = prepared.runtimeTask.primarySurface;
|
|
1937
|
+
if (!primarySurface) {
|
|
1938
|
+
throw new Error('static_game_primary_surface_required');
|
|
1939
|
+
}
|
|
1936
1940
|
const taskToken = input.taskToken?.trim() ?? '';
|
|
1937
1941
|
if (!taskToken) {
|
|
1938
1942
|
throw new Error('static_game_publish_task_token_missing');
|
|
@@ -1940,9 +1944,14 @@ async function publishStaticHtmlProject(input) {
|
|
|
1940
1944
|
const claimed = await input.client.workerClaimAgentTaskSlug(input.taskId, {
|
|
1941
1945
|
appName: prepared.runtimeTask.name,
|
|
1942
1946
|
displayName: prepared.metadata.title,
|
|
1947
|
+
subtitle,
|
|
1948
|
+
primarySurface,
|
|
1943
1949
|
});
|
|
1944
|
-
if (claimed.appName !== prepared.runtimeTask.name
|
|
1945
|
-
|
|
1950
|
+
if (claimed.appName !== prepared.runtimeTask.name
|
|
1951
|
+
|| claimed.displayName !== prepared.metadata.title
|
|
1952
|
+
|| claimed.subtitle !== subtitle
|
|
1953
|
+
|| claimed.primarySurface !== primarySurface) {
|
|
1954
|
+
throw new Error(`static_game_publish_identity_claim_mismatch:${claimed.appName}:${prepared.runtimeTask.name}`);
|
|
1946
1955
|
}
|
|
1947
1956
|
}
|
|
1948
1957
|
const { app } = await (0, registration_1.ensureRegisteredHostedAppShell)({
|
package/dist/commands/whoami.js
CHANGED
|
@@ -67,7 +67,16 @@ async function whoami(options = {}) {
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
if (resolvedCtx.workspaceAuth) {
|
|
70
|
-
|
|
70
|
+
const workspaceOwner = resolvedCtx.workspaceAuth.config.ownerUsername;
|
|
71
|
+
if (username === workspaceOwner) {
|
|
72
|
+
console.log(`Workspace account: ${username} (${resolvedCtx.env})`);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const role = data.user?.role?.trim();
|
|
76
|
+
console.log(`Authenticated actor: ${username} (${resolvedCtx.env}${role ? `, ${role}` : ''})`);
|
|
77
|
+
console.log(`Workspace owner: ${workspaceOwner}`);
|
|
78
|
+
console.log('Authorization: delegated account access is enforced by the PlayDrop API');
|
|
79
|
+
}
|
|
71
80
|
const resolutionSources = ['.playdrop.json'];
|
|
72
81
|
if (options.env) {
|
|
73
82
|
resolutionSources.push(`--env ${options.env}`);
|
|
@@ -804,10 +804,12 @@ function buildClaudeAllowedPermissionRules(workspaceDir, playdropCliEnabled = tr
|
|
|
804
804
|
throw new Error('worker_claude_workspace_missing');
|
|
805
805
|
}
|
|
806
806
|
const absoluteWorkspacePattern = `//${workspaceRoot.replace(/^\/+/, '')}/**`;
|
|
807
|
+
const managedImagePython = node_path_1.default.join(node_os_1.default.homedir(), '.cache', 'playdrop', 'make-2d-asset-pack', 'venv-v1', 'bin', 'python');
|
|
807
808
|
return [
|
|
808
809
|
`Read(${absoluteWorkspacePattern})`,
|
|
809
810
|
`Edit(${absoluteWorkspacePattern})`,
|
|
810
811
|
`Write(${absoluteWorkspacePattern})`,
|
|
812
|
+
`Bash(${managedImagePython} *)`,
|
|
811
813
|
...(playdropCliEnabled ? [`Bash(${workspaceRoot}/bin/playdrop *)`] : []),
|
|
812
814
|
...CLAUDE_BUILD_PERMISSION_RULES.filter((rule) => (playdropCliEnabled || !rule.toLowerCase().includes('playdrop'))),
|
|
813
815
|
];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ApiClient } from '@playdrop/api-client';
|
|
2
|
-
import { type AgentExecutionTarget, type AgentRuntime, type AgentTaskKind, type AgentTaskNextStepSuggestion, type AgentTaskResponse, type AgentWorkerCapabilities, type AgentWorkerResponse, type AgentWorkerUpdatePolicyResponse, type JsonValue, type WorkerTaskAssignmentV2, type WorkerTaskPluginV2, type WorkerClaimAgentTaskResponse } from '@playdrop/types';
|
|
2
|
+
import { type AgentAvailabilityFailureReason, type AgentExecutionTarget, type AgentRuntime, type AgentTaskKind, type AgentTaskNextStepSuggestion, type AgentTaskResponse, type AppSurface, type AgentWorkerCapabilities, type AgentWorkerResponse, type AgentWorkerUpdatePolicyResponse, type JsonValue, type WorkerTaskAssignmentV2, type WorkerTaskPluginV2, type WorkerClaimAgentTaskResponse } from '@playdrop/types';
|
|
3
3
|
import { loadConfig } from '../config';
|
|
4
4
|
import { runShell } from '../shellProbe';
|
|
5
5
|
import { type WorkerPlaydropAssetRequirement } from './upload';
|
|
@@ -79,6 +79,14 @@ type TaskCatalogueReportOptions = {
|
|
|
79
79
|
file?: string;
|
|
80
80
|
message?: string;
|
|
81
81
|
};
|
|
82
|
+
type TaskMaterialOptions = {
|
|
83
|
+
env?: string;
|
|
84
|
+
file?: string;
|
|
85
|
+
title?: string;
|
|
86
|
+
phase?: string;
|
|
87
|
+
poster?: string;
|
|
88
|
+
asset?: boolean;
|
|
89
|
+
};
|
|
82
90
|
type TaskCompleteOptions = {
|
|
83
91
|
env?: string;
|
|
84
92
|
nextSteps?: string;
|
|
@@ -88,10 +96,13 @@ type TaskCompleteOptions = {
|
|
|
88
96
|
type TaskClaimSlugOptions = {
|
|
89
97
|
appName?: string;
|
|
90
98
|
displayName?: string;
|
|
99
|
+
subtitle?: string;
|
|
100
|
+
primarySurface?: string;
|
|
91
101
|
env?: string;
|
|
92
102
|
};
|
|
93
103
|
type TaskUploadOptions = {
|
|
94
104
|
env?: string;
|
|
105
|
+
preflightOnly?: boolean;
|
|
95
106
|
};
|
|
96
107
|
type TaskFailOptions = {
|
|
97
108
|
env?: string;
|
|
@@ -147,6 +158,9 @@ type WorkerTaskContextFile = {
|
|
|
147
158
|
creatorRequest: string;
|
|
148
159
|
target: AgentExecutionTarget;
|
|
149
160
|
outputAppName: string | null;
|
|
161
|
+
outputDisplayName: string | null;
|
|
162
|
+
outputSubtitle: string | null;
|
|
163
|
+
outputPrimarySurface: AppSurface | null;
|
|
150
164
|
outputVersion: string;
|
|
151
165
|
remixSourceRef?: string | null;
|
|
152
166
|
allowedTemplateKeys?: string[];
|
|
@@ -154,6 +168,16 @@ type WorkerTaskContextFile = {
|
|
|
154
168
|
devPort: number;
|
|
155
169
|
env: string;
|
|
156
170
|
};
|
|
171
|
+
type WorkerQueuedEvent = {
|
|
172
|
+
kind: 'progress' | 'catalogue_preview';
|
|
173
|
+
phase: string | null;
|
|
174
|
+
message?: string | null;
|
|
175
|
+
done?: string | null;
|
|
176
|
+
current?: string | null;
|
|
177
|
+
pct?: number | null;
|
|
178
|
+
payload?: Record<string, unknown>;
|
|
179
|
+
};
|
|
180
|
+
export declare function resolveInitialCreatorProgress(kind: AgentTaskKind, creationRecovery?: boolean): WorkerQueuedEvent | null;
|
|
157
181
|
type WorkerCodexModel = {
|
|
158
182
|
model: string;
|
|
159
183
|
reasoningEffort: string;
|
|
@@ -293,6 +317,7 @@ export declare function buildAgentFailureCode(agent: AgentRuntime, result: Logge
|
|
|
293
317
|
model: string;
|
|
294
318
|
reasoningEffort?: string | null;
|
|
295
319
|
}): string;
|
|
320
|
+
export declare function classifyAgentAvailabilityFailureReason(errorCode: string): AgentAvailabilityFailureReason | null;
|
|
296
321
|
export declare function describeAgentFailureForEvent(errorCode: string): string;
|
|
297
322
|
export declare function createLocalPlaydropShim(input: {
|
|
298
323
|
workspaceDir: string;
|
|
@@ -385,6 +410,8 @@ export declare function assignmentRequiresRegisteredBundle(assignment: WorkerTas
|
|
|
385
410
|
export declare function startWorker(options?: WorkerStartOptions): Promise<void>;
|
|
386
411
|
export declare function reportTask(options: TaskReportOptions): Promise<void>;
|
|
387
412
|
export declare function showTaskContext(): void;
|
|
413
|
+
export declare function assertTaskAssetMaterialIsTransparentPng(filePath: string): Promise<void>;
|
|
414
|
+
export declare function materialTask(options: TaskMaterialOptions): Promise<void>;
|
|
388
415
|
export declare function reportCatalogueTask(options: TaskCatalogueReportOptions): Promise<void>;
|
|
389
416
|
export declare function uploadTask(options?: TaskUploadOptions): Promise<void>;
|
|
390
417
|
export declare function claimSlugTask(options: TaskClaimSlugOptions): Promise<void>;
|