@playdrop/playdrop-cli 0.10.21 → 0.11.4

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.
@@ -18,6 +18,7 @@ exports.assertTaskUploadResultMatchesContext = assertTaskUploadResultMatchesCont
18
18
  exports.stageAssignmentWorkspaceFiles = stageAssignmentWorkspaceFiles;
19
19
  exports.resolvePlaydropPluginRoot = resolvePlaydropPluginRoot;
20
20
  exports.stagePlaydropPluginReferences = stagePlaydropPluginReferences;
21
+ exports.stageAssignmentPluginBundle = stageAssignmentPluginBundle;
21
22
  exports.discoverWorkerProjectRoot = discoverWorkerProjectRoot;
22
23
  exports.readWorkerTaskState = readWorkerTaskState;
23
24
  exports.buildWorkerHealthAlertText = buildWorkerHealthAlertText;
@@ -52,6 +53,7 @@ exports.claimSlugTask = claimSlugTask;
52
53
  exports.completeTask = completeTask;
53
54
  exports.readReviewEvidenceFiles = readReviewEvidenceFiles;
54
55
  exports.submitReviewTask = submitReviewTask;
56
+ exports.submitEvalTask = submitEvalTask;
55
57
  exports.failTask = failTask;
56
58
  const promises_1 = require("node:fs/promises");
57
59
  const node_fs_1 = require("node:fs");
@@ -59,6 +61,7 @@ const node_os_1 = __importDefault(require("node:os"));
59
61
  const node_path_1 = __importDefault(require("node:path"));
60
62
  const node_process_1 = __importDefault(require("node:process"));
61
63
  const node_module_1 = require("node:module");
64
+ const node_crypto_1 = require("node:crypto");
62
65
  const fflate_1 = require("fflate");
63
66
  const types_1 = require("@playdrop/types");
64
67
  const commandContext_1 = require("../commandContext");
@@ -99,10 +102,13 @@ const FAIL_REPORT_RETRY_DELAY_MS = 2000;
99
102
  const WORKER_TRANSCRIPT_CHUNK_BATCH_SIZE = 100;
100
103
  const SLACK_API_BASE_URL = 'https://slack.com/api';
101
104
  const WORKER_WRAPPER_CONTRACT_VERSION = 1;
102
- const WORKER_SUPPORTED_KINDS = ['NEW_GAME', 'REMIX_GAME', 'GAME_UPDATE', 'GAME_REVIEW'];
105
+ const WORKER_SUPPORTED_KINDS = ['NEW_GAME', 'REMIX_GAME', 'GAME_UPDATE', 'GAME_REVIEW', 'GAME_EVAL'];
106
+ const PLAYDROP_PLUGIN_MANIFEST_REQUIRED_STARTUP_KINDS = WORKER_SUPPORTED_KINDS;
103
107
  const requireFromWorker = (0, node_module_1.createRequire)(__filename);
104
108
  const STAGED_PLAYDROP_PLUGIN_ROOT = '.playdrop/plugin';
105
109
  const PLAYDROP_PLUGIN_STAGING_MANIFEST_PATH = 'playdrop-worker-staging.json';
110
+ const ASSIGNMENT_PLUGIN_BUNDLE_MAX_FILES = 1000;
111
+ const ASSIGNMENT_PLUGIN_BUNDLE_MAX_UNCOMPRESSED_BYTES = 20 * 1024 * 1024;
106
112
  exports.WORKER_SESSION_EXPIRED_MESSAGE = 'worker session expired: run "playdrop auth login" and start the worker again';
107
113
  const WORKER_CONTEXT_ALLOWED_COMMANDS = [
108
114
  ['task', 'report'],
@@ -111,6 +117,7 @@ const WORKER_CONTEXT_ALLOWED_COMMANDS = [
111
117
  ['task', 'upload'],
112
118
  ['task', 'done'],
113
119
  ['task', 'submit-review'],
120
+ ['task', 'submit-eval'],
114
121
  ['task', 'fail'],
115
122
  ['review', 'validate-result'],
116
123
  ['review', 'compose-evidence'],
@@ -125,12 +132,13 @@ const WORKER_CONTEXT_ALLOWED_COMMANDS = [
125
132
  ['versions', 'browse'],
126
133
  ['documentation', 'browse'],
127
134
  ['documentation', 'read'],
135
+ ['help'],
128
136
  ['ai', 'create'],
129
137
  ['ai', 'jobs', 'browse'],
130
138
  ['ai', 'jobs', 'detail'],
131
139
  ['ai', 'generations'],
132
140
  ];
133
- exports.WORKER_CONTEXT_COMMAND_NOT_ALLOWED_MESSAGE = 'worker_context_command_not_allowed: inside a PlayDrop worker task only task progress, task claim-slug, task upload/done/fail, assigned app scaffolding, project validation/build/dev/capture, read-only catalogue/documentation lookup, and PlayDrop AI generation are permitted.';
141
+ exports.WORKER_CONTEXT_COMMAND_NOT_ALLOWED_MESSAGE = 'worker_context_command_not_allowed: inside a PlayDrop worker task only task progress, task claim-slug, task upload/done/fail, assigned app scaffolding, project validation/build/dev/capture, read-only help/catalogue/documentation lookup, and PlayDrop AI generation are permitted.';
134
142
  function allocateWorkerDevPort(input) {
135
143
  const basePort = input.basePort ?? DEFAULT_WORKER_DEV_PORT_BASE;
136
144
  const maxParallelTasks = input.maxParallelTasks ?? DEFAULT_WORKER_MAX_PARALLEL_TASKS;
@@ -182,6 +190,28 @@ function normalizeRemixFlagValue(argv) {
182
190
  }
183
191
  return null;
184
192
  }
193
+ function normalizeTemplateKeyRef(value) {
194
+ const trimmed = value.trim();
195
+ const match = /^([^/]+)\/(?:template|app)\/([^/]+)$/.exec(trimmed);
196
+ if (!match) {
197
+ return trimmed || null;
198
+ }
199
+ return `${match[1]}/template/${match[2]}`;
200
+ }
201
+ function normalizeTemplateFlagValue(argv) {
202
+ for (let index = 0; index < argv.length; index += 1) {
203
+ const arg = argv[index];
204
+ if (arg === '--template') {
205
+ const value = argv[index + 1]?.trim() ?? '';
206
+ return value ? normalizeTemplateKeyRef(value) : null;
207
+ }
208
+ if (arg.startsWith('--template=')) {
209
+ const value = arg.slice('--template='.length).trim();
210
+ return value ? normalizeTemplateKeyRef(value) : null;
211
+ }
212
+ }
213
+ return null;
214
+ }
185
215
  function isAssignedAppScaffoldCommandAllowed(argv) {
186
216
  if (argv[0] !== 'project' || argv[1] !== 'create' || argv[2] !== 'app') {
187
217
  return false;
@@ -199,7 +229,11 @@ function isAssignedAppScaffoldCommandAllowed(argv) {
199
229
  || requestedAppName !== context.outputAppName) {
200
230
  return false;
201
231
  }
202
- return normalizeRemixFlagValue(argv) === null;
232
+ const templateKey = normalizeTemplateFlagValue(argv);
233
+ const allowedTemplateKeys = new Set((context.allowedTemplateKeys ?? []).map((key) => normalizeTemplateKeyRef(key)).filter(Boolean));
234
+ return normalizeRemixFlagValue(argv) === null
235
+ && templateKey !== null
236
+ && allowedTemplateKeys.has(templateKey);
203
237
  }
204
238
  return normalizeRemixFlagValue(argv) === context.remixSourceRef;
205
239
  }
@@ -223,7 +257,7 @@ function normalizeAssignmentAgent(value) {
223
257
  return value;
224
258
  }
225
259
  function normalizeAssignmentKind(value, task) {
226
- if (value !== 'NEW_GAME' && value !== 'REMIX_GAME' && value !== 'GAME_UPDATE' && value !== 'GAME_REVIEW') {
260
+ if (value !== 'NEW_GAME' && value !== 'REMIX_GAME' && value !== 'GAME_UPDATE' && value !== 'GAME_REVIEW' && value !== 'GAME_EVAL') {
227
261
  throw new Error('agent_task_assignment_kind_missing');
228
262
  }
229
263
  if (value !== task.kind) {
@@ -283,6 +317,9 @@ function resolveWorkerClaimTaskAssignment(claim) {
283
317
  if (!version) {
284
318
  throw new Error('agent_task_assignment_output_version_missing');
285
319
  }
320
+ const pluginBundle = assignment.pluginBundle && typeof assignment.pluginBundle === 'object' && !Array.isArray(assignment.pluginBundle)
321
+ ? assignment.pluginBundle
322
+ : null;
286
323
  return {
287
324
  taskId,
288
325
  taskToken,
@@ -302,7 +339,12 @@ function resolveWorkerClaimTaskAssignment(claim) {
302
339
  baseSource: inputs.baseSource ?? null,
303
340
  remixSource: inputs.remixSource ?? null,
304
341
  reviewTarget: inputs.reviewTarget ?? null,
342
+ evalTarget: inputs.evalTarget ?? null,
343
+ allowedTemplateKeys: Array.isArray(inputs.allowedTemplateKeys)
344
+ ? Array.from(new Set(inputs.allowedTemplateKeys.map((value) => (typeof value === 'string' ? value.trim() : '')).filter(Boolean)))
345
+ : [],
305
346
  },
347
+ pluginBundle,
306
348
  output: {
307
349
  appId: typeof output.appId === 'number' && Number.isInteger(output.appId) && output.appId > 0 ? output.appId : null,
308
350
  appName: typeof output.appName === 'string' && output.appName.trim() ? output.appName.trim() : null,
@@ -383,6 +425,9 @@ function buildWorkerTaskContext(claim, assignment) {
383
425
  }
384
426
  remixSourceRef = parsedRemixSourceRef;
385
427
  }
428
+ const allowedTemplateKeys = Array.isArray(assignment.inputs.allowedTemplateKeys)
429
+ ? Array.from(new Set(assignment.inputs.allowedTemplateKeys.map((value) => (typeof value === 'string' ? value.trim() : '')).filter(Boolean)))
430
+ : [];
386
431
  const creatorRequest = assignment.inputs.request.prompt.trim();
387
432
  if (!creatorRequest) {
388
433
  throw new Error('agent_task_context_creator_request_missing');
@@ -398,6 +443,7 @@ function buildWorkerTaskContext(claim, assignment) {
398
443
  outputAppName,
399
444
  outputVersion,
400
445
  remixSourceRef,
446
+ allowedTemplateKeys,
401
447
  reviewAppVersionId,
402
448
  };
403
449
  }
@@ -455,6 +501,9 @@ function readTaskContextFile(startDir = node_process_1.default.cwd()) {
455
501
  const remixSourceRef = typeof parsed.remixSourceRef === 'string' && parsed.remixSourceRef.trim()
456
502
  ? parsed.remixSourceRef.trim()
457
503
  : null;
504
+ const allowedTemplateKeys = Array.isArray(parsed.allowedTemplateKeys)
505
+ ? Array.from(new Set(parsed.allowedTemplateKeys.map((value) => (typeof value === 'string' ? value.trim() : '')).filter(Boolean)))
506
+ : [];
458
507
  let reviewAppVersionId = null;
459
508
  if (parsed.reviewAppVersionId !== null && parsed.reviewAppVersionId !== undefined) {
460
509
  const parsedReviewAppVersionId = Number(parsed.reviewAppVersionId);
@@ -466,7 +515,7 @@ function readTaskContextFile(startDir = node_process_1.default.cwd()) {
466
515
  if (!Number.isInteger(taskId) || taskId <= 0
467
516
  || !Number.isInteger(attempt) || attempt <= 0
468
517
  || !taskToken
469
- || (parsed.kind !== 'NEW_GAME' && parsed.kind !== 'REMIX_GAME' && parsed.kind !== 'GAME_UPDATE' && parsed.kind !== 'GAME_REVIEW')
518
+ || (parsed.kind !== 'NEW_GAME' && parsed.kind !== 'REMIX_GAME' && parsed.kind !== 'GAME_UPDATE' && parsed.kind !== 'GAME_REVIEW' && parsed.kind !== 'GAME_EVAL')
470
519
  || (parsed.target !== 'FIRST_PARTY' && parsed.target !== 'PERSONAL')
471
520
  || !creatorUsername
472
521
  || !creatorRequest
@@ -488,6 +537,7 @@ function readTaskContextFile(startDir = node_process_1.default.cwd()) {
488
537
  outputAppName: typeof parsed.outputAppName === 'string' && parsed.outputAppName.trim() ? parsed.outputAppName.trim() : null,
489
538
  outputVersion,
490
539
  remixSourceRef,
540
+ allowedTemplateKeys,
491
541
  reviewAppVersionId,
492
542
  devPort,
493
543
  env,
@@ -677,6 +727,15 @@ async function readTaskNextStepsFileForCommand(input) {
677
727
  return NEXT_STEPS_READ_FAILED;
678
728
  }
679
729
  }
730
+ function isFinalOwnerRouteLaunchCheckFailure(error) {
731
+ const message = error instanceof Error ? error.message : String(error);
732
+ return message.startsWith('hosted_launch_check_failed:')
733
+ && message.includes('final owner play route');
734
+ }
735
+ function formatTerminalFinalOwnerRouteFailure(error) {
736
+ const message = error instanceof Error ? error.message : String(error);
737
+ return `agent_task_final_owner_route_failed: final owner play route validation failed after the task version was created. Task uploads have a fixed outputVersion and cannot be retried by bumping catalogue.json. ${message}`;
738
+ }
680
739
  function assertTaskUploadResultMatchesContext(input) {
681
740
  if (input.uploadResult.taskId !== input.taskContext.taskId) {
682
741
  throw new Error('task_upload_result_task_mismatch');
@@ -836,8 +895,37 @@ function readPlaydropPluginStagingManifest(pluginRoot) {
836
895
  }
837
896
  const taskFiles = {};
838
897
  const rawTaskFiles = rawManifest.taskFiles;
898
+ for (const kind of PLAYDROP_PLUGIN_MANIFEST_REQUIRED_STARTUP_KINDS) {
899
+ const rawFiles = rawTaskFiles[kind];
900
+ if (!Array.isArray(rawFiles) || rawFiles.length <= 0) {
901
+ throw new Error(`playdrop_plugin_staging_manifest_incomplete:${kind}: non-empty taskFiles entry required in ${manifestPath}`);
902
+ }
903
+ const seen = new Set();
904
+ const files = rawFiles.map((value) => normalizePlaydropPluginManifestPath({ manifestPath, kind, value }));
905
+ for (const relativePath of files) {
906
+ if (seen.has(relativePath)) {
907
+ throw new Error(`playdrop_plugin_staging_manifest_duplicate_file:${kind}:${relativePath}`);
908
+ }
909
+ seen.add(relativePath);
910
+ const source = node_path_1.default.resolve(resolvedRoot, ...relativePath.split('/'));
911
+ const relativeToRoot = node_path_1.default.relative(resolvedRoot, source);
912
+ if (relativeToRoot.startsWith('..') || node_path_1.default.isAbsolute(relativeToRoot)) {
913
+ throw new Error(`playdrop_plugin_staging_manifest_invalid_path:${kind}:${relativePath}`);
914
+ }
915
+ if (!isFile(source)) {
916
+ throw new Error(`playdrop_plugin_staging_manifest_file_missing:${kind}:${relativePath}`);
917
+ }
918
+ }
919
+ taskFiles[kind] = files;
920
+ }
839
921
  for (const kind of WORKER_SUPPORTED_KINDS) {
922
+ if (taskFiles[kind]) {
923
+ continue;
924
+ }
840
925
  const rawFiles = rawTaskFiles[kind];
926
+ if (rawFiles === undefined) {
927
+ continue;
928
+ }
841
929
  if (!Array.isArray(rawFiles) || rawFiles.length <= 0) {
842
930
  throw new Error(`playdrop_plugin_staging_manifest_incomplete:${kind}: non-empty taskFiles entry required in ${manifestPath}`);
843
931
  }
@@ -861,7 +949,7 @@ function readPlaydropPluginStagingManifest(pluginRoot) {
861
949
  }
862
950
  return {
863
951
  version: 1,
864
- taskFiles,
952
+ taskFiles: taskFiles,
865
953
  };
866
954
  }
867
955
  function resolvePlaydropPluginRoot(input = {}) {
@@ -898,6 +986,9 @@ async function stagePlaydropPluginReferences(input) {
898
986
  }
899
987
  const manifest = readPlaydropPluginStagingManifest(pluginRoot);
900
988
  const referenceFiles = manifest.taskFiles[input.kind];
989
+ if (!Array.isArray(referenceFiles) || referenceFiles.length <= 0) {
990
+ throw new Error(`playdrop_plugin_staging_manifest_incomplete:${input.kind}: non-empty taskFiles entry required`);
991
+ }
901
992
  const staged = [];
902
993
  for (const relativePath of referenceFiles) {
903
994
  const destinationRelativePath = node_path_1.default.join(STAGED_PLAYDROP_PLUGIN_ROOT, relativePath);
@@ -908,6 +999,54 @@ async function stagePlaydropPluginReferences(input) {
908
999
  }
909
1000
  return staged;
910
1001
  }
1002
+ async function stageAssignmentPluginBundle(input) {
1003
+ const sha256 = typeof input.pluginBundle.sha256 === 'string' ? input.pluginBundle.sha256.trim() : '';
1004
+ const contentBase64 = typeof input.pluginBundle.contentBase64 === 'string' ? input.pluginBundle.contentBase64.trim() : '';
1005
+ if (!/^[a-f0-9]{64}$/.test(sha256) || !contentBase64) {
1006
+ throw new Error('agent_task_plugin_bundle_invalid');
1007
+ }
1008
+ const buffer = Buffer.from(contentBase64, 'base64');
1009
+ if (buffer.length <= 0) {
1010
+ throw new Error('agent_task_plugin_bundle_empty');
1011
+ }
1012
+ const actualSha = (0, node_crypto_1.createHash)('sha256').update(buffer).digest('hex');
1013
+ if (actualSha !== sha256) {
1014
+ throw new Error('agent_task_plugin_bundle_sha_mismatch');
1015
+ }
1016
+ const pluginRoot = node_path_1.default.join(input.workspaceDir, '.playdrop', 'task-plugin');
1017
+ await (0, promises_1.rm)(pluginRoot, { recursive: true, force: true });
1018
+ await (0, promises_1.mkdir)(pluginRoot, { recursive: true });
1019
+ const entries = (0, fflate_1.unzipSync)(new Uint8Array(buffer));
1020
+ const entryPairs = Object.entries(entries);
1021
+ const fileEntries = entryPairs.filter(([entryName]) => !entryName.replace(/\\/g, '/').endsWith('/'));
1022
+ if (fileEntries.length > ASSIGNMENT_PLUGIN_BUNDLE_MAX_FILES) {
1023
+ throw new Error(`agent_task_plugin_bundle_too_many_files:${fileEntries.length}>${ASSIGNMENT_PLUGIN_BUNDLE_MAX_FILES}`);
1024
+ }
1025
+ let uncompressedBytes = 0;
1026
+ for (const [entryName, content] of Object.entries(entries)) {
1027
+ const normalizedName = entryName.replace(/\\/g, '/');
1028
+ if (!normalizedName || normalizedName.startsWith('/') || normalizedName.split('/').includes('..')) {
1029
+ throw new Error(`agent_task_plugin_bundle_invalid_path:${entryName}`);
1030
+ }
1031
+ if (normalizedName.endsWith('/')) {
1032
+ await (0, promises_1.mkdir)(node_path_1.default.join(pluginRoot, normalizedName), { recursive: true });
1033
+ continue;
1034
+ }
1035
+ const destination = node_path_1.default.join(pluginRoot, normalizedName);
1036
+ const relative = node_path_1.default.relative(pluginRoot, destination);
1037
+ if (relative.startsWith('..') || node_path_1.default.isAbsolute(relative)) {
1038
+ throw new Error(`agent_task_plugin_bundle_invalid_path:${entryName}`);
1039
+ }
1040
+ uncompressedBytes += content.byteLength;
1041
+ if (uncompressedBytes > ASSIGNMENT_PLUGIN_BUNDLE_MAX_UNCOMPRESSED_BYTES) {
1042
+ throw new Error(`agent_task_plugin_bundle_too_large:${uncompressedBytes}>${ASSIGNMENT_PLUGIN_BUNDLE_MAX_UNCOMPRESSED_BYTES}`);
1043
+ }
1044
+ await (0, promises_1.mkdir)(node_path_1.default.dirname(destination), { recursive: true });
1045
+ await (0, promises_1.writeFile)(destination, Buffer.from(content));
1046
+ }
1047
+ readPlaydropPluginStagingManifest(pluginRoot);
1048
+ return pluginRoot;
1049
+ }
911
1050
  // A PlayDrop project root is the topmost directory holding a catalogue.json,
912
1051
  // the same marker "playdrop project publish" resolves its target from. Nested
913
1052
  // catalogue.json files belong to the root above them, so the walk stops at the
@@ -1269,6 +1408,7 @@ function buildWorkerCapabilities(input) {
1269
1408
  ? DEFAULT_WORKER_MAX_PARALLEL_TASKS
1270
1409
  : input.maxParallelTasks ?? DEFAULT_WORKER_MAX_PARALLEL_TASKS;
1271
1410
  const runningTaskCount = typeof input === 'string' ? 0 : input.runningTaskCount ?? 0;
1411
+ const providerAccountLabel = typeof input === 'string' ? null : input.providerAccountLabel?.trim() || null;
1272
1412
  const degradedReasons = [];
1273
1413
  const agents = [];
1274
1414
  if (codexVersion) {
@@ -1321,6 +1461,7 @@ function buildWorkerCapabilities(input) {
1321
1461
  agents,
1322
1462
  ready: agents.some((agent) => agent.ready === true),
1323
1463
  degradedReasons,
1464
+ ...(providerAccountLabel ? { providerAccountLabel } : {}),
1324
1465
  wrapperContractVersion: (0, runtime_1.readPositiveEnvInt)('PLAYDROP_WORKER_WRAPPER_CONTRACT_VERSION', WORKER_WRAPPER_CONTRACT_VERSION),
1325
1466
  ...(npmVersion ? { npmVersion } : {}),
1326
1467
  ...(playwright ? { playwright } : {}),
@@ -2123,6 +2264,7 @@ function collectWorkerLocalStatus() {
2123
2264
  playwright,
2124
2265
  runningTaskCount: 0,
2125
2266
  maxParallelTasks: (0, runtime_1.readPositiveEnvInt)('PLAYDROP_WORKER_MAX_PARALLEL_TASKS', DEFAULT_WORKER_MAX_PARALLEL_TASKS),
2267
+ providerAccountLabel: node_process_1.default.env.PLAYDROP_WORKER_AGENT_ACCOUNT_LABEL?.trim() || null,
2126
2268
  });
2127
2269
  if (pluginVersion) {
2128
2270
  capabilities.pluginVersion = pluginVersion;
@@ -2984,6 +3126,7 @@ async function startWorker(options = {}) {
2984
3126
  throw new Error('worker_session_invalid: the stored session did not resolve to a user. Run "playdrop auth login" and retry.');
2985
3127
  }
2986
3128
  const target = resolveWorkerExecutionTargetFromRole(me.user.role);
3129
+ const providerAccountLabel = readProviderAccountLabel(target);
2987
3130
  const codexVersion = probeCodexInstallation()?.codexVersion ?? null;
2988
3131
  const claudeVersion = probeClaudeInstallation()?.claudeVersion ?? null;
2989
3132
  const cursorVersion = probeCursorInstallation()?.cursorVersion ?? null;
@@ -3008,6 +3151,7 @@ async function startWorker(options = {}) {
3008
3151
  playwright,
3009
3152
  maxParallelTasks,
3010
3153
  runningTaskCount: 0,
3154
+ providerAccountLabel,
3011
3155
  });
3012
3156
  if (playdropPluginVersion) {
3013
3157
  capabilities.pluginVersion = playdropPluginVersion;
@@ -3259,7 +3403,10 @@ async function startWorker(options = {}) {
3259
3403
  message: 'Preparing worker workspace',
3260
3404
  pct: 2,
3261
3405
  });
3262
- availableSkillPaths = normalizeTelemetrySkillPaths(await stagePlaydropPluginReferences({ workspaceDir, pluginRoot: playdropPluginRoot, kind: task.kind }));
3406
+ const assignmentPluginRoot = assignment.pluginBundle
3407
+ ? await stageAssignmentPluginBundle({ workspaceDir, pluginBundle: assignment.pluginBundle })
3408
+ : playdropPluginRoot;
3409
+ availableSkillPaths = normalizeTelemetrySkillPaths(await stagePlaydropPluginReferences({ workspaceDir, pluginRoot: assignmentPluginRoot, kind: task.kind }));
3263
3410
  await client.workerCreateAgentTaskEvent(task.id, {
3264
3411
  workerKey,
3265
3412
  leaseToken,
@@ -3370,6 +3517,14 @@ async function startWorker(options = {}) {
3370
3517
  throw new Error('agent_task_assignment_review_target_missing');
3371
3518
  }
3372
3519
  }
3520
+ else if (task.kind === 'GAME_EVAL') {
3521
+ if (assignment.inputs.baseSource !== null) {
3522
+ throw new Error('agent_task_assignment_unexpected_base_source');
3523
+ }
3524
+ if (!assignment.inputs.evalTarget) {
3525
+ throw new Error('agent_task_assignment_eval_target_missing');
3526
+ }
3527
+ }
3373
3528
  else {
3374
3529
  throw new Error(`unsupported_agent_task_kind:${task.kind}`);
3375
3530
  }
@@ -3407,7 +3562,7 @@ async function startWorker(options = {}) {
3407
3562
  attempt: taskContext.attempt,
3408
3563
  devPort,
3409
3564
  claudeModel: claudeModel ?? resolveClaudeModel(assignment.model),
3410
- playdropPluginRoot,
3565
+ playdropPluginRoot: assignmentPluginRoot,
3411
3566
  onTranscriptChunks: async (chunks) => {
3412
3567
  await appendTranscriptChunks(chunks);
3413
3568
  },
@@ -3821,7 +3976,7 @@ async function resolveTaskCommandContext(command, optionsEnv, taskContext) {
3821
3976
  }
3822
3977
  async function uploadTask(options = {}) {
3823
3978
  const taskContext = readTaskContextFile();
3824
- if (taskContext.kind === 'GAME_REVIEW') {
3979
+ if (taskContext.kind === 'GAME_REVIEW' || taskContext.kind === 'GAME_EVAL') {
3825
3980
  throw new Error('task_upload_not_allowed_for_game_review');
3826
3981
  }
3827
3982
  const workspaceDir = resolveTaskWorkspaceDir();
@@ -3839,21 +3994,40 @@ async function uploadTask(options = {}) {
3839
3994
  return;
3840
3995
  }
3841
3996
  const projectDir = discoverWorkerProjectRoot(node_process_1.default.cwd());
3842
- const published = await (0, upload_1.publishWorkerAppProject)({
3843
- client: ctx.client,
3844
- taskId: taskContext.taskId,
3845
- kind: taskContext.kind,
3846
- expectedAppName: taskContext.outputAppName ?? undefined,
3847
- remixSourceRef: taskContext.remixSourceRef ?? null,
3848
- playdropAssetRequirement: resolvePlaydropAssetRequirementFromTaskRequest(taskContext.creatorRequest),
3849
- creatorRequest: taskContext.creatorRequest,
3850
- projectDir,
3851
- creatorUsername: taskContext.creatorUsername,
3852
- apiBase: ctx.envConfig.apiBase,
3853
- webBase: ctx.envConfig.webBase ?? null,
3854
- token: ctx.token,
3855
- user: ctx.user,
3856
- });
3997
+ let published;
3998
+ try {
3999
+ published = await (0, upload_1.publishWorkerAppProject)({
4000
+ client: ctx.client,
4001
+ taskId: taskContext.taskId,
4002
+ kind: taskContext.kind,
4003
+ expectedAppName: taskContext.outputAppName ?? undefined,
4004
+ remixSourceRef: taskContext.remixSourceRef ?? null,
4005
+ playdropAssetRequirement: resolvePlaydropAssetRequirementFromTaskRequest(taskContext.creatorRequest),
4006
+ creatorRequest: taskContext.creatorRequest,
4007
+ projectDir,
4008
+ creatorUsername: taskContext.creatorUsername,
4009
+ apiBase: ctx.envConfig.apiBase,
4010
+ webBase: ctx.envConfig.webBase ?? null,
4011
+ token: ctx.token,
4012
+ user: ctx.user,
4013
+ });
4014
+ }
4015
+ catch (error) {
4016
+ if (isFinalOwnerRouteLaunchCheckFailure(error)) {
4017
+ const terminalError = formatTerminalFinalOwnerRouteFailure(error);
4018
+ await ctx.client.workerFailAgentTask(taskContext.taskId, {
4019
+ taskToken: taskContext.taskToken,
4020
+ error: terminalError,
4021
+ result: {
4022
+ failedBy: 'worker_upload_final_owner_route',
4023
+ finalOwnerRouteFailure: true,
4024
+ originalError: error instanceof Error ? error.message : String(error),
4025
+ },
4026
+ });
4027
+ throw new Error(terminalError);
4028
+ }
4029
+ throw error;
4030
+ }
3857
4031
  const result = {
3858
4032
  taskId: taskContext.taskId,
3859
4033
  appId: published.appId,
@@ -3899,9 +4073,13 @@ async function claimSlugTask(options) {
3899
4073
  }
3900
4074
  async function completeTask(options) {
3901
4075
  const taskContext = readTaskContextFile();
3902
- if (taskContext.kind === 'GAME_REVIEW') {
4076
+ if (taskContext.kind === 'GAME_REVIEW' || taskContext.kind === 'GAME_EVAL') {
3903
4077
  throw new Error('task_done_not_allowed_for_game_review');
3904
4078
  }
4079
+ const summary = typeof options.summary === 'string' ? options.summary.trim() : '';
4080
+ if (!summary || summary.length > 200 || /[\r\n]/.test(summary)) {
4081
+ throw new Error('task_done_summary_required');
4082
+ }
3905
4083
  const ctx = await resolveTaskCommandContext('task done', options.env, taskContext);
3906
4084
  if (!ctx) {
3907
4085
  return;
@@ -3938,6 +4116,7 @@ async function completeTask(options) {
3938
4116
  creatorUsername: uploadResult.creatorUsername,
3939
4117
  completedBy: 'agent',
3940
4118
  },
4119
+ summary,
3941
4120
  ...(nextSteps !== undefined ? { nextSteps } : {}),
3942
4121
  });
3943
4122
  }
@@ -3956,7 +4135,7 @@ async function completeTask(options) {
3956
4135
  }
3957
4136
  throw error;
3958
4137
  }
3959
- (0, output_1.printSuccess)('Task marked done. Send one short final status sentence now, then stop.');
4138
+ (0, output_1.printSuccess)('Task marked done.');
3960
4139
  }
3961
4140
  function normalizeReviewSubmitState(value) {
3962
4141
  const normalized = typeof value === 'string' ? value.trim().toUpperCase() : '';
@@ -4105,6 +4284,29 @@ async function submitReviewTask(options) {
4105
4284
  });
4106
4285
  (0, output_1.printSuccess)('Review submitted. Send one short final status sentence now, then stop.');
4107
4286
  }
4287
+ async function submitEvalTask(options) {
4288
+ const taskContext = readTaskContextFile();
4289
+ if (taskContext.kind !== 'GAME_EVAL') {
4290
+ throw new Error('task_submit_eval_requires_game_eval');
4291
+ }
4292
+ const resultFile = resolveReviewFilePath(options.resultFile, 'invalid_eval_result_file');
4293
+ let result;
4294
+ try {
4295
+ result = JSON.parse((0, node_fs_1.readFileSync)(resultFile, 'utf8'));
4296
+ }
4297
+ catch (error) {
4298
+ throw new Error(`invalid_eval_result_json:${error instanceof Error ? error.message : String(error)}`);
4299
+ }
4300
+ const ctx = await resolveTaskCommandContext('task submit-eval', options.env, taskContext);
4301
+ if (!ctx) {
4302
+ throw new Error('task_submit_eval_auth_required');
4303
+ }
4304
+ await ctx.client.workerSubmitAgentTaskEval(taskContext.taskId, {
4305
+ taskToken: taskContext.taskToken,
4306
+ result: result,
4307
+ });
4308
+ (0, output_1.printSuccess)('Eval submitted. Send one short final status sentence now, then stop.');
4309
+ }
4108
4310
  async function failTask(options) {
4109
4311
  const message = options.message?.trim();
4110
4312
  if (!message) {
package/dist/index.js CHANGED
@@ -255,6 +255,7 @@ task
255
255
  task
256
256
  .command('done')
257
257
  .description('Mark the active agent task done after upload')
258
+ .requiredOption('--summary <summary>', 'One-sentence creator-facing recap of what was built')
258
259
  .option('--next-steps <path>', 'JSON file with up to three next-step suggestions')
259
260
  .option('--env <env>', 'Environment override')
260
261
  .action(async (opts) => {
@@ -272,6 +273,14 @@ task
272
273
  .action(async (opts) => {
273
274
  await (0, worker_1.submitReviewTask)(opts);
274
275
  });
276
+ task
277
+ .command('submit-eval')
278
+ .description('Submit the active game eval task result')
279
+ .requiredOption('--result-file <path>', 'Strict GAME_EVAL JSON result file')
280
+ .option('--env <env>', 'Environment override')
281
+ .action(async (opts) => {
282
+ await (0, worker_1.submitEvalTask)(opts);
283
+ });
275
284
  task
276
285
  .command('fail')
277
286
  .description('Fail the active agent task')
@@ -1040,6 +1049,7 @@ projectCapture
1040
1049
  .option('--expected-url <url>', 'Expected final URL after redirects')
1041
1050
  .option('--actions <path>', 'JSON action file with click, press, and wait steps before screenshot')
1042
1051
  .option('--viewport <size>', 'Viewport size as WIDTHxHEIGHT')
1052
+ .option('--surface <surface>', 'Browser surface preset: desktop, mobile-landscape, or mobile-portrait')
1043
1053
  .option('--fps-sample-ms <milliseconds>', 'Sample frame rate for this many milliseconds after capture')
1044
1054
  .option('--username <username>', 'Login username')
1045
1055
  .option('--password <password>', 'Login password')
@@ -1,4 +1,4 @@
1
- import type { AppleOAuthHandoffExchangeRequest, AppleOAuthHandoffExchangeResponse, AppleOAuthLinkStartRequest, AppleOAuthLinkStartResponse, ApplePushDeviceRequest, ApplePushDeviceStatusResponse, FirebasePushDeviceRequest, FirebasePushDeviceStatusResponse, ApiKeyLoginRequest, CliApiKeyStatusResponse, CliLoginApproveRequest, CliLoginApproveResponse, CliLoginPollRequest, CliLoginPollResponse, CliLoginStartResponse, CliLoginStatusResponse, CliWebLaunchStartRequest, CliWebLaunchStartResponse, CompleteXSignupRequest, CompleteXSignupResponse, DeleteMyAccountRequest, DeleteMyAccountResponse, LoginRequest, LoginResponse, LogoutResponse, PrivacyExportResponse, RegisterRequest, RegisterResponse, StarterProfileAssetsResponse, CreateAppRequest, CreateAppResponse, UpdateAppRequest, AdminUpdateAppRequest, UpdateAppResponse, AppsListResponse, AppBrowseRequest, AppDetailRequest, AppDetailResponse, AppMoreCollectionKey, AppMoreCollectionPage, AppMoreCollectionRequest, AppMoreCollectionsRequest, AppMoreCollectionsResponse, CreatorAppsBrowseRequest, AppRuntimeAssetsResponse, ContentLicense, InitializeAppUploadRequest, InitializeAppUploadResponse, UploadAppSessionFileResponse, UploadAppSessionOwnedAssetResponse, FinalizeAppUploadResponse, AppUploadLaunchCheckPreviewResponse, AbortAppUploadResponse, RecordAppUploadLaunchCheckRequest, RecordAppUploadLaunchCheckResponse, MyAppsResponse, BootstrapResponse, SetProfileAssetRequest, SetProfileAssetResponse, MeResponse, UserDetailResponse, UsersListResponse, CreateUserRequest, CreateUserResponse, UpdateAdminUserRequest, RemixScaffoldResponse, TemplateScaffoldResponse, HomeResponse, HomeCollectionPageResponse, FetchHomeOptions, DeleteAppResponse, AppType, AppAccessTokenResponse, DevAppAccessTokenResponse, DevPlayerResetResponse, AppLogEntryRequest, AppLogEntryResponse, ClaimFreeCreditRewardResponse, SubmitFeedbackRequest, SubmitFeedbackResponse, FeedbackListResponse, AdminFeedbackListResponse, AdminFeedbackResponse, UpdateAdminFeedbackRequest, UpdateAdminFeedbackResponse, DeleteFeedbackResponse, FeedbackCategory, FeedbackClient, FeedbackStatus, ShopResponse, AppleCreditPackFulfillmentRequest, AdInterstitialShowResponse, AdLoadResponse, AdShowRequest, AdRewardedShowResponse, AssetPurchaseRequest, BoostActivationRequest, BoostBalanceResponse, BoostHistoryResponse, BoostPurchaseRequest, BoostPurchaseResponse, BoostReportQuery, BoostReportResponse, BoostStatusResponse, AdLoadRequest, CreditPackCheckoutSessionRequest, PurchaseResponse, CreditPackCheckoutSessionResponse, CreditPackCheckoutStatusResponse, CreatorEarningsResponse, GoogleCreditPackFulfillmentRequest, MobileCreditPackFulfillmentResponse, TransactionsResponse, CreditPacksResponse, CreditPackResponse, PaymentProvider, PaymentStatus, AdminPaymentsListResponse, AdminPaymentDetailResponse, AdminPlatformAnalyticsRequest, AdminPlatformAnalyticsResponse, AdminRefundPaymentRequest, IapPurchaseRequest, IapPurchaseResponse, IapReceiptsResponse, IapReceiptListParams, IapReceiptResponse, AdminCreditTransactionsResponse, AiGenerationsResponse, AiGenerationDetailResponse, OwnedProfileAssetsResponse, SavedItemKind, CreateContentReportRequest, CreateCreatorReportRequest, CreateCommentReportRequest, CreatorBlockMutationResponse, LikedItemMutationResponse, DislikedItemMutationResponse, ModerationReportResponse, SavedItemMutationResponse, LibraryCategory, LibrarySort, LibraryResponse, TrackEngagementEventRequest, TrackEngagementEventResponse, CreatorFollowMutationResponse, ContentCommentsResponse, CreateContentCommentRequest, CreateContentCommentResponse, FollowingSort, FollowingCreatorsResponse, FollowingFeedSection, FollowingFeedResponse, DeleteContentCommentResponse, NotificationStatus, NotificationsResponse, NotificationReadResponse, EmailPreferencesResponse, UpdateUserCommunicationPreferencesRequest, PublicEmailPreferencesResponse, PublicEmailPreferencesUpdateRequest, EmailUnsubscribeResponse, AdminCreatorEngagementRulesResponse, AdminCreatorEngagementExecutionsResponse, AdminCreatorEngagementUserResponse, AdminCreatorEngagementRulePreviewRequest, AdminCreatorEngagementRulePreviewResponse, CreatorEngagementRuleExecutionStatus, PushSubscriptionMutationResponse, AdminUserResponse, DeleteAdminUserResponse, BatchCreateUsersResponse, UpsertWebPushSubscriptionRequest, UpdateProfileRequest, UpdateProfileResponse, WebPushConfigResponse, WebPushSubscriptionStatusResponse, ChangePasswordRequest, ChangePasswordResponse, UpgradeToCreatorResponse, AppleLinkRequest, AppleLinkResponse, AppleNativeChallengeResponse, ApplePendingSignupResponse, AppleSignInRequest, AppleSignInResponse, UnlinkXResponse, UnlinkGoogleResponse, GooglePendingSignupResponse, XPendingSignupResponse, GoogleOneTapExchangeRequest, GoogleOneTapExchangeResponse, UsernameAvailableResponse, CompleteAppleSignupRequest, CompleteAppleSignupResponse, CompleteGoogleSignupRequest, CompleteGoogleSignupResponse, GoogleAppleLinkRequest, GoogleAppleLinkResponse, GoogleAppleSignInRequest, GoogleAppleSignInResponse, AdminAppPlayerMetaResponse, AdminAppPlayerMetaUserResponse, AdminAppVersionReviewsListResponse, AdminEnqueueNextAppVersionReviewTaskResponse, AdminMutateAchievementStateRequest, AdminMutateAchievementStateResponse, AdminMutateLeaderboardScoreRequest, AdminMutateLeaderboardScoreResponse, AdminRetirePlayerMetaDefinitionResponse, AdminUpdateAppVersionReviewRequest, AdminUpdateAppVersionReviewResponse, CreateCliApiKeyResponse, GetAchievementResponse, GetLeaderboardResponse, ListAchievementsResponse, ListLeaderboardsResponse, MyAchievementsResponse, MyLeaderboardsResponse, SetAchievementProgressRequest, SetAchievementProgressResponse, SubmitLeaderboardScoreRequest, SubmitLeaderboardScoreResponse, UnlockAchievementResponse, ReviewState, AppVersionVisibility, AppVersionsListResponse, AppVersionDetailResponse, AppSourceBundleResponse, UpdateVersionResponse, DeleteVersionResponse, AdminAppsListResponse, AdminGameCollectionCandidatesResponse, AdminGameCollectionResponse, AdminGameCollectionsResponse, AdminUpdateAppResponse, CreateAdminGameCollectionRequest, DeleteAdminGameCollectionResponse, UpdateAdminGameCollectionGamesRequest, UpdateAdminGameCollectionRequest, AssetBrowseKind, AssetCategory, AssetFormat, AssetVisibility, AssetSourceKind, AssetListSort, AssetListResponse, AssetCategoriesResponse, AssetDetailResponse, AssetVersionsListResponse, CreateAssetVersionResponse, DeleteOwnedCustomAssetResponse, CreateAssetSpecVersionResponse, ListOwnedCustomAssetsResponse, LoadOwnedCustomAssetResponse, MutateOwnedCustomAssetRequest, MutateOwnedCustomAssetResponse, UpdateAssetRequest, UpdateAssetResponse, UpdateAssetVersionRequest, UpdateAssetVersionResponse, UpdateAssetSpecVersionResponse, DeleteAssetVersionResponse, DeleteAssetResponse, DeleteAssetSpecVersionResponse, DeleteAssetSpecResponse, AssetSourceBundleResponse, AssetPackListSort, AssetSpecAssetsListResponse, AssetSpecAppsListResponse, AssetSpecDetailResponse, AssetSpecListSort, AssetSpecListResponse, AssetSpecVersionResponseEnvelope, AssetSpecVersionsListResponse, AssetPackSourceBundleResponse, AssetPackListResponse, AssetPackDetailResponse, AssetPackVersionsListResponse, InitializeAssetPackUploadRequest, InitializeAssetPackUploadResponse, UploadAssetPackSessionAssetResponse, UploadAssetPackSessionMediaResponse, FinalizeAssetPackUploadResponse, AbortAssetPackUploadResponse, UpdateAssetPackRequest, UpdateAssetPackResponse, UpdateAssetPackVersionRequest, UpdateAssetPackVersionResponse, DeleteAssetPackVersionResponse, DeleteAssetPackResponse, BatchUpsertNodeRelationsRequest, BatchUpsertNodeRelationsResponse, ContentRemixRelationsResponse, SearchRequest, SearchResponse, SearchSuggestRequest, SearchSuggestResponse, AdminTagGroupResponse, AdminTagGroupsResponse, AdminTagResponse, CreateTagGroupRequest, CreateTagRequest, TagDirectoryResponse, TagDetailResponse, TagGroupDetailResponse, TagGroupSort, TagListResponse, UpdateTagGroupRequest, UpdateTagRequest, AdminAgentTaskDetailResponse, AdminAgentTaskTranscriptResponse, AdminAgentTasksResponse, AdminAgentWorkersStatusResponse, AgentTaskAvailabilityResponse, AgentTaskAttachmentUploadResponse, AgentTaskCreatorFeedbackStatus, AgentTaskDetailResponse, AgentTaskEventsResponse, AgentTaskKind, AgentTaskNewGameSuggestionsResponse, AgentTasksResponse, AppAgentTaskResponse, CancelAgentTaskResponse, ClearAgentTaskResponse, CreateAppAgentTaskRequest, CreateAppAgentTaskResponse, CreateNewGameAgentTaskRequest, CreateNewGameAgentTaskResponse, CreateRemixGameAgentTaskRequest, CreateRemixGameAgentTaskResponse, CreatorGameCreatorFeedbackStatusResponse, CreatorGamesListResponse, CreatorGameShareResponse, CreatorGameStatusResponse, CreatorGameVersionsResponse, MeAgentWorkersResponse, RetryAgentTaskResponse, WorkerClaimAgentTaskRequest, WorkerClaimAgentTaskResponse, WorkerClaimAgentTaskSlugRequest, WorkerClaimAgentTaskSlugResponse, WorkerCompleteAgentTaskRequest, WorkerCreateAgentTaskEventRequest, WorkerCreateAgentTaskEventResponse, WorkerCreateAgentTaskTranscriptChunkRequest, WorkerCreateAgentTaskTranscriptChunkResponse, WorkerAgentTaskAttemptUnavailableRequest, WorkerAgentTaskAttemptUnavailableResponse, WorkerFailAgentTaskRequest, WorkerHeartbeatAgentTaskRequest, WorkerHeartbeatAgentTaskResponse, WorkerRecordAgentTaskRunTelemetryRequest, WorkerRecordAgentTaskRunTelemetryResponse, WorkerPresenceRequest, WorkerPresenceResponse, WorkerSubmitAgentTaskReviewRequest, WorkerSubmitAgentTaskReviewResponse, WorkerUpdateIntentRequest, WorkerUpdateIntentResponse, FreeCreditsResponse, InvitePreviewResponse, MyInviteCodeResponse } from '@playdrop/types';
1
+ import type { AppleOAuthHandoffExchangeRequest, AppleOAuthHandoffExchangeResponse, AppleOAuthLinkStartRequest, AppleOAuthLinkStartResponse, ApplePushDeviceRequest, ApplePushDeviceStatusResponse, FirebasePushDeviceRequest, FirebasePushDeviceStatusResponse, ApiKeyLoginRequest, CliApiKeyStatusResponse, CliLoginApproveRequest, CliLoginApproveResponse, CliLoginPollRequest, CliLoginPollResponse, CliLoginStartResponse, CliLoginStatusResponse, CliWebLaunchStartRequest, CliWebLaunchStartResponse, CompleteXSignupRequest, CompleteXSignupResponse, DeleteMyAccountRequest, DeleteMyAccountResponse, LoginRequest, LoginResponse, LogoutResponse, PrivacyExportResponse, RegisterRequest, RegisterResponse, StarterProfileAssetsResponse, CreateAppRequest, CreateAppResponse, UpdateAppRequest, AdminUpdateAppRequest, UpdateAppResponse, AppsListResponse, AppBrowseRequest, AppDetailRequest, AppDetailResponse, AppMoreCollectionKey, AppMoreCollectionPage, AppMoreCollectionRequest, AppMoreCollectionsRequest, AppMoreCollectionsResponse, CreatorAppsBrowseRequest, AppRuntimeAssetsResponse, ContentLicense, InitializeAppUploadRequest, InitializeAppUploadResponse, UploadAppSessionFileResponse, UploadAppSessionOwnedAssetResponse, FinalizeAppUploadResponse, AppUploadLaunchCheckPreviewResponse, AbortAppUploadResponse, RecordAppUploadLaunchCheckRequest, RecordAppUploadLaunchCheckResponse, MyAppsResponse, BootstrapResponse, SetProfileAssetRequest, SetProfileAssetResponse, MeResponse, UserDetailResponse, UsersListResponse, CreateUserRequest, CreateUserResponse, UpdateAdminUserRequest, RemixScaffoldResponse, TemplateScaffoldResponse, HomeResponse, HomeCollectionPageResponse, FetchHomeOptions, DeleteAppResponse, AppType, AppAccessTokenResponse, DevAppAccessTokenResponse, DevPlayerResetResponse, AppLogEntryRequest, AppLogEntryResponse, ClaimFreeCreditRewardResponse, SubmitFeedbackRequest, SubmitFeedbackResponse, FeedbackListResponse, AdminFeedbackListResponse, AdminFeedbackResponse, UpdateAdminFeedbackRequest, UpdateAdminFeedbackResponse, DeleteFeedbackResponse, FeedbackCategory, FeedbackClient, FeedbackStatus, ShopResponse, AppleCreditPackFulfillmentRequest, AdInterstitialShowResponse, AdLoadResponse, AdShowRequest, AdRewardedShowResponse, AssetPurchaseRequest, BoostActivationRequest, BoostBalanceResponse, BoostHistoryResponse, BoostPurchaseRequest, BoostPurchaseResponse, BoostReportQuery, BoostReportResponse, BoostStatusResponse, AdLoadRequest, CreditPackCheckoutSessionRequest, PurchaseResponse, CreditPackCheckoutSessionResponse, CreditPackCheckoutStatusResponse, CreatorEarningsResponse, GoogleCreditPackFulfillmentRequest, MobileCreditPackFulfillmentResponse, TransactionsResponse, CreditPacksResponse, CreditPackResponse, PaymentProvider, PaymentStatus, AdminPaymentsListResponse, AdminPaymentDetailResponse, AdminPlatformAnalyticsRequest, AdminPlatformAnalyticsResponse, AdminRefundPaymentRequest, IapPurchaseRequest, IapPurchaseResponse, IapReceiptsResponse, IapReceiptListParams, IapReceiptResponse, AdminCreditTransactionsResponse, AiGenerationsResponse, AiGenerationDetailResponse, OwnedProfileAssetsResponse, SavedItemKind, CreateContentReportRequest, CreateCreatorReportRequest, CreateCommentReportRequest, CreatorBlockMutationResponse, LikedItemMutationResponse, DislikedItemMutationResponse, ModerationReportResponse, SavedItemMutationResponse, LibraryCategory, LibrarySort, LibraryResponse, TrackEngagementEventRequest, TrackEngagementEventResponse, CreatorFollowMutationResponse, ContentCommentsResponse, CreateContentCommentRequest, CreateContentCommentResponse, FollowingSort, FollowingCreatorsResponse, FollowingFeedSection, FollowingFeedResponse, DeleteContentCommentResponse, NotificationStatus, NotificationsResponse, NotificationReadResponse, EmailPreferencesResponse, UpdateUserCommunicationPreferencesRequest, PublicEmailPreferencesResponse, PublicEmailPreferencesUpdateRequest, EmailUnsubscribeResponse, AdminCreatorEngagementRulesResponse, AdminCreatorEngagementExecutionsResponse, AdminCreatorEngagementUserResponse, AdminCreatorEngagementRulePreviewRequest, AdminCreatorEngagementRulePreviewResponse, CreatorEngagementRuleExecutionStatus, PushSubscriptionMutationResponse, AdminUserResponse, DeleteAdminUserResponse, BatchCreateUsersResponse, UpsertWebPushSubscriptionRequest, UpdateProfileRequest, UpdateProfileResponse, WebPushConfigResponse, WebPushSubscriptionStatusResponse, ChangePasswordRequest, ChangePasswordResponse, UpgradeToCreatorResponse, AppleLinkRequest, AppleLinkResponse, AppleNativeChallengeResponse, ApplePendingSignupResponse, AppleSignInRequest, AppleSignInResponse, UnlinkXResponse, UnlinkGoogleResponse, GooglePendingSignupResponse, XPendingSignupResponse, GoogleOneTapExchangeRequest, GoogleOneTapExchangeResponse, UsernameAvailableResponse, CompleteAppleSignupRequest, CompleteAppleSignupResponse, CompleteGoogleSignupRequest, CompleteGoogleSignupResponse, GoogleAppleLinkRequest, GoogleAppleLinkResponse, GoogleAppleSignInRequest, GoogleAppleSignInResponse, AdminAppPlayerMetaResponse, AdminAppPlayerMetaUserResponse, AdminAppVersionReviewsListResponse, AdminEnqueueNextAppVersionReviewTaskResponse, AdminMutateAchievementStateRequest, AdminMutateAchievementStateResponse, AdminMutateLeaderboardScoreRequest, AdminMutateLeaderboardScoreResponse, AdminRetirePlayerMetaDefinitionResponse, AdminUpdateAppVersionReviewRequest, AdminUpdateAppVersionReviewResponse, CreateCliApiKeyResponse, GetAchievementResponse, GetLeaderboardResponse, ListAchievementsResponse, ListLeaderboardsResponse, MyAchievementsResponse, MyLeaderboardsResponse, SetAchievementProgressRequest, SetAchievementProgressResponse, SubmitLeaderboardScoreRequest, SubmitLeaderboardScoreResponse, UnlockAchievementResponse, ReviewState, AppVersionVisibility, AppVersionsListResponse, AppVersionDetailResponse, AppSourceBundleResponse, UpdateVersionResponse, DeleteVersionResponse, AdminAppsListResponse, AdminGameCollectionCandidatesResponse, AdminGameCollectionResponse, AdminGameCollectionsResponse, AdminUpdateAppResponse, CreateAdminGameCollectionRequest, DeleteAdminGameCollectionResponse, UpdateAdminGameCollectionGamesRequest, UpdateAdminGameCollectionRequest, AssetBrowseKind, AssetCategory, AssetFormat, AssetVisibility, AssetSourceKind, AssetListSort, AssetListResponse, AssetCategoriesResponse, AssetDetailResponse, AssetVersionsListResponse, CreateAssetVersionResponse, DeleteOwnedCustomAssetResponse, CreateAssetSpecVersionResponse, ListOwnedCustomAssetsResponse, LoadOwnedCustomAssetResponse, MutateOwnedCustomAssetRequest, MutateOwnedCustomAssetResponse, UpdateAssetRequest, UpdateAssetResponse, UpdateAssetVersionRequest, UpdateAssetVersionResponse, UpdateAssetSpecVersionResponse, DeleteAssetVersionResponse, DeleteAssetResponse, DeleteAssetSpecVersionResponse, DeleteAssetSpecResponse, AssetSourceBundleResponse, AssetPackListSort, AssetSpecAssetsListResponse, AssetSpecAppsListResponse, AssetSpecDetailResponse, AssetSpecListSort, AssetSpecListResponse, AssetSpecVersionResponseEnvelope, AssetSpecVersionsListResponse, AssetPackSourceBundleResponse, AssetPackListResponse, AssetPackDetailResponse, AssetPackVersionsListResponse, InitializeAssetPackUploadRequest, InitializeAssetPackUploadResponse, UploadAssetPackSessionAssetResponse, UploadAssetPackSessionMediaResponse, FinalizeAssetPackUploadResponse, AbortAssetPackUploadResponse, UpdateAssetPackRequest, UpdateAssetPackResponse, UpdateAssetPackVersionRequest, UpdateAssetPackVersionResponse, DeleteAssetPackVersionResponse, DeleteAssetPackResponse, BatchUpsertNodeRelationsRequest, BatchUpsertNodeRelationsResponse, ContentRemixRelationsResponse, SearchRequest, SearchResponse, SearchSuggestRequest, SearchSuggestResponse, AdminTagGroupResponse, AdminTagGroupsResponse, AdminTagResponse, CreateTagGroupRequest, CreateTagRequest, TagDirectoryResponse, TagDetailResponse, TagGroupDetailResponse, TagGroupSort, TagListResponse, UpdateTagGroupRequest, UpdateTagRequest, AdminAgentTaskDetailResponse, AdminAgentTaskTranscriptResponse, AdminAgentTasksResponse, AdminAgentWorkersStatusResponse, AgentTaskAvailabilityResponse, AgentTaskAttachmentUploadResponse, AgentTaskCreatorFeedbackStatus, AgentTaskDetailResponse, AgentTaskEventsResponse, AgentTaskKind, AgentTaskNewGameSuggestionsResponse, AgentTasksResponse, AppAgentTaskResponse, CancelAgentTaskResponse, ClearAgentTaskResponse, CreateAppAgentTaskRequest, CreateAppAgentTaskResponse, CreateGameEvalAgentTaskRequest, CreateGameEvalAgentTaskResponse, CreateNewGameAgentTaskRequest, CreateNewGameAgentTaskResponse, CreateRemixGameAgentTaskRequest, CreateRemixGameAgentTaskResponse, CreatorGameCreatorFeedbackStatusResponse, CreatorGamesListResponse, CreatorGameShareResponse, CreatorGameStatusResponse, CreatorGameVersionsResponse, MeAgentWorkersResponse, RetryAgentTaskResponse, WorkerClaimAgentTaskRequest, WorkerClaimAgentTaskResponse, WorkerClaimAgentTaskSlugRequest, WorkerClaimAgentTaskSlugResponse, WorkerCompleteAgentTaskRequest, WorkerCreateAgentTaskEventRequest, WorkerCreateAgentTaskEventResponse, WorkerCreateAgentTaskTranscriptChunkRequest, WorkerCreateAgentTaskTranscriptChunkResponse, WorkerAgentTaskAttemptUnavailableRequest, WorkerAgentTaskAttemptUnavailableResponse, WorkerFailAgentTaskRequest, WorkerHeartbeatAgentTaskRequest, WorkerHeartbeatAgentTaskResponse, WorkerRecordAgentTaskRunTelemetryRequest, WorkerRecordAgentTaskRunTelemetryResponse, WorkerPresenceRequest, WorkerPresenceResponse, WorkerSubmitAgentTaskEvalRequest, WorkerSubmitAgentTaskEvalResponse, WorkerSubmitAgentTaskReviewRequest, WorkerSubmitAgentTaskReviewResponse, WorkerUpdateIntentRequest, WorkerUpdateIntentResponse, FreeCreditsResponse, InvitePreviewResponse, MyInviteCodeResponse } from '@playdrop/types';
2
2
  import { type AdminAgentTaskTranscriptOptions, type ListCreatorGamesOptions, type ListAgentTasksOptions } from './domains/agent-tasks.js';
3
3
  export interface HttpMethod {
4
4
  GET: 'GET';
@@ -135,6 +135,7 @@ export interface ApiClient {
135
135
  uploadAgentTaskAttachment(file: Blob, description?: string, filename?: string): Promise<AgentTaskAttachmentUploadResponse>;
136
136
  createNewGameAgentTask(body: CreateNewGameAgentTaskRequest): Promise<CreateNewGameAgentTaskResponse>;
137
137
  createRemixGameAgentTask(body: CreateRemixGameAgentTaskRequest): Promise<CreateRemixGameAgentTaskResponse>;
138
+ createGameEvalAgentTask(body: CreateGameEvalAgentTaskRequest): Promise<CreateGameEvalAgentTaskResponse>;
138
139
  createAppAgentTask(appName: string, body: CreateAppAgentTaskRequest): Promise<CreateAppAgentTaskResponse>;
139
140
  getAppAgentTask(appName: string): Promise<AppAgentTaskResponse>;
140
141
  getAppAgentTaskAvailability(appName: string): Promise<AgentTaskAvailabilityResponse>;
@@ -163,6 +164,7 @@ export interface ApiClient {
163
164
  workerRecordAgentTaskRunTelemetry(taskId: number, body: WorkerRecordAgentTaskRunTelemetryRequest): Promise<WorkerRecordAgentTaskRunTelemetryResponse>;
164
165
  workerCompleteAgentTask(taskId: number, body: WorkerCompleteAgentTaskRequest): Promise<AgentTaskDetailResponse>;
165
166
  workerSubmitAgentTaskReview(taskId: number, body: WorkerSubmitAgentTaskReviewRequest): Promise<WorkerSubmitAgentTaskReviewResponse>;
167
+ workerSubmitAgentTaskEval(taskId: number, body: WorkerSubmitAgentTaskEvalRequest): Promise<WorkerSubmitAgentTaskEvalResponse>;
166
168
  workerFailAgentTask(taskId: number, body: WorkerFailAgentTaskRequest): Promise<AgentTaskDetailResponse>;
167
169
  adminListAgentTasks(options?: ListAgentTasksOptions): Promise<AdminAgentTasksResponse>;
168
170
  adminGetAgentTask(taskId: number): Promise<AdminAgentTaskDetailResponse>;