@playdrop/playdrop-cli 0.12.27 → 0.12.28

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.
@@ -1,38 +1,7 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveUploadOwner = resolveUploadOwner;
4
+ exports.resolveDefaultUploadCreator = resolveDefaultUploadCreator;
36
5
  exports.upload = upload;
37
6
  exports.assertTaskPlaytestEvidenceManifest = assertTaskPlaytestEvidenceManifest;
38
7
  exports.publishWorkerAppProject = publishWorkerAppProject;
@@ -53,6 +22,7 @@ const uploadLog_1 = require("../uploadLog");
53
22
  const upload_content_1 = require("./upload-content");
54
23
  const appUrls_1 = require("../appUrls");
55
24
  const devRuntimeAssets_1 = require("./devRuntimeAssets");
25
+ const ownedRuntimeImageValidation_1 = require("./ownedRuntimeImageValidation");
56
26
  const listingPreflight_1 = require("../listingPreflight");
57
27
  const upload_graph_1 = require("./upload-graph");
58
28
  function normalizeSavedItemKinds(kinds) {
@@ -222,6 +192,19 @@ function normalizeCreatorUsername(username) {
222
192
  }
223
193
  return trimmed;
224
194
  }
195
+ function resolveUploadOwner(actorUsername, workspaceOwnerUsername) {
196
+ const workspaceOwner = workspaceOwnerUsername?.trim() ?? '';
197
+ if (workspaceOwner) {
198
+ return workspaceOwner;
199
+ }
200
+ const actor = actorUsername?.trim() ?? '';
201
+ return actor || 'unknown';
202
+ }
203
+ function resolveDefaultUploadCreator(owner, actorUsername) {
204
+ return normalizeCreatorUsername(owner ?? null)
205
+ ?? normalizeCreatorUsername(actorUsername ?? null)
206
+ ?? 'unknown';
207
+ }
225
208
  function isNotFoundApiError(error) {
226
209
  return error instanceof types_1.ApiError && error.status === 404;
227
210
  }
@@ -1059,7 +1042,7 @@ async function flushGraphState(client, graphState, results) {
1059
1042
  }
1060
1043
  async function processUploadTasks(client, tasks, owner, ownerUsername, currentUserRole, localTagGroups, currentUser, token, warnings, apiBase, webBase, options) {
1061
1044
  const portalBase = normalizePortalBase(webBase);
1062
- const defaultCreator = normalizeCreatorUsername(ownerUsername) ?? owner;
1045
+ const defaultCreator = resolveDefaultUploadCreator(owner, ownerUsername);
1063
1046
  const results = [];
1064
1047
  const preflight = await buildUploadPreflight(client, tasks, defaultCreator, currentUserRole, localTagGroups);
1065
1048
  const sortedTasks = preflight.nodes.map((node) => node.task);
@@ -1177,9 +1160,7 @@ async function upload(pathOrName, options) {
1177
1160
  }
1178
1161
  throw error;
1179
1162
  }
1180
- const owner = typeof userInfo.username === 'string' && userInfo.username.trim().length > 0
1181
- ? userInfo.username.trim()
1182
- : 'unknown';
1163
+ const owner = resolveUploadOwner(userInfo.username, ctx.workspaceAuth?.config.ownerUsername);
1183
1164
  const tagGroupLoad = (0, catalogue_1.resolveCatalogueTagGroups)(workspaceRoot);
1184
1165
  if (tagGroupLoad.errors.length > 0) {
1185
1166
  (0, taskSelection_1.reportTaskErrors)(tagGroupLoad.errors.map((message) => ({
@@ -1234,8 +1215,6 @@ const WORKER_SUPERVISOR_BUNDLE_EXCLUDES = [
1234
1215
  'assets/marketing/',
1235
1216
  'listing/',
1236
1217
  ];
1237
- const OWNED_RUNTIME_IMAGE_CHECK_SIZE = 96;
1238
- const OWNED_RUNTIME_IMAGE_GRID_CHECK_SIZE = 512;
1239
1218
  function appTaskSatisfiesPlaydropAssetRequirement(task, requirement) {
1240
1219
  if (!requirement) {
1241
1220
  return true;
@@ -1253,361 +1232,6 @@ function appTaskSatisfiesPlaydropAssetRequirement(task, requirement) {
1253
1232
  });
1254
1233
  return hasFirstPartyPack || hasFirstPartyAsset || task.ownedAssets.length > 0;
1255
1234
  }
1256
- function isUnsafeDirectPlaydropAiImageAsset(detail, parsedRevision) {
1257
- const asset = detail?.asset;
1258
- if (!asset || asset.category !== 'IMAGE') {
1259
- return false;
1260
- }
1261
- const currentVersion = asset.currentVersion;
1262
- if (!currentVersion || Number(currentVersion.revision) !== parsedRevision) {
1263
- return false;
1264
- }
1265
- const sourceKind = typeof currentVersion.sourceKind === 'string' ? currentVersion.sourceKind.toUpperCase() : '';
1266
- if (sourceKind !== 'AI') {
1267
- return false;
1268
- }
1269
- const format = typeof currentVersion.format === 'string' ? currentVersion.format.toUpperCase() : '';
1270
- const files = Array.isArray(currentVersion.fileManifest?.files) ? currentVersion.fileManifest.files : [];
1271
- const primary = files.find((file) => file?.role === 'primary');
1272
- const primaryContentType = typeof primary?.contentType === 'string' ? primary.contentType.toLowerCase() : '';
1273
- return format === 'JPEG' || primaryContentType === 'image/jpeg' || primaryContentType === 'image/jpg';
1274
- }
1275
- async function assertNewGameDirectPlaydropAssetsAreRuntimeSafe(input) {
1276
- const unsafeRefs = [];
1277
- for (const dependency of input.task.uses.assets) {
1278
- const parsed = (0, types_1.parseContentVersionRef)(dependency.ref);
1279
- if (!parsed || parsed.kind !== 'asset' || parsed.creatorUsername.toLowerCase() !== 'playdrop') {
1280
- continue;
1281
- }
1282
- const detail = await input.client.fetchAssetBySlug(parsed.creatorUsername, parsed.name);
1283
- if (isUnsafeDirectPlaydropAiImageAsset(detail, parsed.revision)) {
1284
- unsafeRefs.push((0, types_1.formatContentVersionRef)(parsed));
1285
- }
1286
- }
1287
- if (unsafeRefs.length > 0) {
1288
- throw new Error(`agent_task_playdrop_direct_ai_image_asset_unsafe: direct PlayDrop AI JPEG image assets cannot be used as new-game runtime sprites because their backgrounds are baked into the image. Use a PlayDrop asset pack or create clean owned PNG assets through the PlayDrop make-assets workflow instead. Unsafe refs: ${unsafeRefs.join(', ')}`);
1289
- }
1290
- }
1291
- function isOwnedRuntimeImageAsset(task, ownedAsset) {
1292
- if (!ownedAsset.runtimeKey || ownedAsset.category !== 'IMAGE') {
1293
- return false;
1294
- }
1295
- const primaryPath = ownedAsset.filePaths?.primary;
1296
- if (!primaryPath) {
1297
- return false;
1298
- }
1299
- const relativePath = primaryPath.slice((0, node_path_1.resolve)(task.projectDir).length + 1).replace(/\\/g, '/');
1300
- return !relativePath.startsWith('assets/marketing/') && !relativePath.startsWith('listing/');
1301
- }
1302
- function isBackgroundLikeOwnedRuntimeImageAsset(ownedAsset) {
1303
- const value = `${ownedAsset.name ?? ''} ${ownedAsset.runtimeKey ?? ''}`.toLowerCase();
1304
- return /\b(background|backdrop|scene|sky|floor|ground|wall|terrain|landscape|level|arena)\b/i.test(value);
1305
- }
1306
- function looksLikeBakedCheckerboardPreview(input) {
1307
- const { data, width, height, channels } = input;
1308
- if (width < 24 || height < 24 || channels < 4) {
1309
- return false;
1310
- }
1311
- const border = Math.max(8, Math.floor(Math.min(width, height) * 0.16));
1312
- let sampled = 0;
1313
- let transparent = 0;
1314
- let opaqueGray = 0;
1315
- let lowGray = 0;
1316
- let highGray = 0;
1317
- for (let y = 0; y < height; y += 1) {
1318
- for (let x = 0; x < width; x += 1) {
1319
- const inBorder = x < border || y < border || x >= width - border || y >= height - border;
1320
- if (!inBorder) {
1321
- continue;
1322
- }
1323
- sampled += 1;
1324
- const offset = (y * width + x) * channels;
1325
- const red = data[offset] ?? 0;
1326
- const green = data[offset + 1] ?? 0;
1327
- const blue = data[offset + 2] ?? 0;
1328
- const alpha = data[offset + 3] ?? 255;
1329
- if (alpha < 32) {
1330
- transparent += 1;
1331
- continue;
1332
- }
1333
- const brightness = (red + green + blue) / 3;
1334
- const grayish = Math.max(Math.abs(red - green), Math.abs(red - blue), Math.abs(green - blue)) <= 10;
1335
- if (alpha > 240 && grayish && brightness >= 70 && brightness <= 210) {
1336
- opaqueGray += 1;
1337
- if (brightness < 125) {
1338
- lowGray += 1;
1339
- }
1340
- else if (brightness > 145) {
1341
- highGray += 1;
1342
- }
1343
- }
1344
- }
1345
- }
1346
- if (sampled === 0 || transparent / sampled > 0.18) {
1347
- return false;
1348
- }
1349
- return opaqueGray / sampled > 0.58
1350
- && lowGray / sampled > 0.08
1351
- && highGray / sampled > 0.18;
1352
- }
1353
- function looksLikeBakedSolidMattePreview(input) {
1354
- const { data, width, height, channels } = input;
1355
- if (width < 24 || height < 24 || channels < 4) {
1356
- return false;
1357
- }
1358
- const border = Math.max(8, Math.floor(Math.min(width, height) * 0.18));
1359
- let sampled = 0;
1360
- let transparent = 0;
1361
- let matteLike = 0;
1362
- for (let y = 0; y < height; y += 1) {
1363
- for (let x = 0; x < width; x += 1) {
1364
- const inBorder = x < border || y < border || x >= width - border || y >= height - border;
1365
- if (!inBorder) {
1366
- continue;
1367
- }
1368
- sampled += 1;
1369
- const offset = (y * width + x) * channels;
1370
- const red = data[offset] ?? 0;
1371
- const green = data[offset + 1] ?? 0;
1372
- const blue = data[offset + 2] ?? 0;
1373
- const alpha = data[offset + 3] ?? 255;
1374
- if (alpha < 32) {
1375
- transparent += 1;
1376
- continue;
1377
- }
1378
- const dominant = Math.max(red, green, blue);
1379
- const weakest = Math.min(red, green, blue);
1380
- const chroma = dominant - weakest;
1381
- const brightGreenMatte = green >= 220 && green - Math.max(red, blue) >= 65 && Math.max(red, blue) >= 70;
1382
- const brightRedMatte = red >= 220 && red - Math.max(green, blue) >= 65;
1383
- const brightBlueMatte = blue >= 220 && blue - Math.max(red, green) >= 65;
1384
- const brightTwoChannelMatte = dominant >= 220
1385
- && chroma >= 65
1386
- && ((red >= 220 && green >= 220) || (red >= 220 && blue >= 220) || (green >= 220 && blue >= 220));
1387
- if (brightGreenMatte || brightRedMatte || brightBlueMatte || brightTwoChannelMatte) {
1388
- matteLike += 1;
1389
- }
1390
- }
1391
- }
1392
- if (sampled === 0 || transparent / sampled > 0.18) {
1393
- return false;
1394
- }
1395
- return matteLike / sampled > 0.58;
1396
- }
1397
- function looksLikeBakedNeutralSolidMattePreview(input) {
1398
- const { data, width, height, channels } = input;
1399
- if (width < 24 || height < 24 || channels < 4) {
1400
- return false;
1401
- }
1402
- const border = Math.max(8, Math.floor(Math.min(width, height) * 0.18));
1403
- let sampled = 0;
1404
- let transparent = 0;
1405
- let neutralMatteLike = 0;
1406
- for (let y = 0; y < height; y += 1) {
1407
- for (let x = 0; x < width; x += 1) {
1408
- const inBorder = x < border || y < border || x >= width - border || y >= height - border;
1409
- if (!inBorder) {
1410
- continue;
1411
- }
1412
- sampled += 1;
1413
- const offset = (y * width + x) * channels;
1414
- const red = data[offset] ?? 0;
1415
- const green = data[offset + 1] ?? 0;
1416
- const blue = data[offset + 2] ?? 0;
1417
- const alpha = data[offset + 3] ?? 255;
1418
- if (alpha < 32) {
1419
- transparent += 1;
1420
- continue;
1421
- }
1422
- const brightness = (red + green + blue) / 3;
1423
- const grayish = Math.max(Math.abs(red - green), Math.abs(red - blue), Math.abs(green - blue)) <= 12;
1424
- if (alpha > 240 && grayish && (brightness >= 235 || brightness <= 20)) {
1425
- neutralMatteLike += 1;
1426
- }
1427
- }
1428
- }
1429
- if (sampled === 0 || transparent / sampled > 0.18) {
1430
- return false;
1431
- }
1432
- return neutralMatteLike / sampled > 0.58;
1433
- }
1434
- function looksLikeResidualMatteGridArtifact(input) {
1435
- const { data, width, height, channels } = input;
1436
- if (width < 48 || height < 48 || channels < 4) {
1437
- return false;
1438
- }
1439
- const rowCounts = new Uint32Array(height);
1440
- const columnCounts = new Uint32Array(width);
1441
- let matteLike = 0;
1442
- for (let y = 0; y < height; y += 1) {
1443
- for (let x = 0; x < width; x += 1) {
1444
- const offset = (y * width + x) * channels;
1445
- const red = data[offset] ?? 0;
1446
- const green = data[offset + 1] ?? 0;
1447
- const blue = data[offset + 2] ?? 0;
1448
- const alpha = data[offset + 3] ?? 255;
1449
- if (alpha < 24 || alpha > 190) {
1450
- continue;
1451
- }
1452
- const greenMatte = green >= 35 && green - Math.max(red, blue) >= 25 && red <= 110 && blue <= 110;
1453
- const redMatte = red >= 35 && red - Math.max(green, blue) >= 25 && green <= 120 && blue <= 120;
1454
- const blueMatte = blue >= 35 && blue - Math.max(red, green) >= 25 && red <= 120 && green <= 120;
1455
- const purpleMatte = red >= 35 && blue >= 35 && Math.min(red, blue) - green >= 25 && green <= 120;
1456
- if (!greenMatte && !redMatte && !blueMatte && !purpleMatte) {
1457
- continue;
1458
- }
1459
- matteLike += 1;
1460
- rowCounts[y] += 1;
1461
- columnCounts[x] += 1;
1462
- }
1463
- }
1464
- const matteRatio = matteLike / (width * height);
1465
- if (matteRatio < 0.0015) {
1466
- return false;
1467
- }
1468
- let rowsWithLines = 0;
1469
- for (const count of rowCounts) {
1470
- if (count / width >= 0.12) {
1471
- rowsWithLines += 1;
1472
- }
1473
- }
1474
- let columnsWithLines = 0;
1475
- for (const count of columnCounts) {
1476
- if (count / height >= 0.12) {
1477
- columnsWithLines += 1;
1478
- }
1479
- }
1480
- return rowsWithLines + columnsWithLines >= 3
1481
- && (rowsWithLines >= 2 || columnsWithLines >= 2);
1482
- }
1483
- function looksLikeResidualTransparentGridLineArtifact(input) {
1484
- const { data, width, height, channels } = input;
1485
- if (width < 48 || height < 48 || channels < 4) {
1486
- return false;
1487
- }
1488
- const rowVisibleCounts = new Uint32Array(height);
1489
- const rowSemiCounts = new Uint32Array(height);
1490
- const columnVisibleCounts = new Uint32Array(width);
1491
- const columnSemiCounts = new Uint32Array(width);
1492
- for (let y = 0; y < height; y += 1) {
1493
- for (let x = 0; x < width; x += 1) {
1494
- const offset = (y * width + x) * channels;
1495
- const alpha = data[offset + 3] ?? 255;
1496
- if (alpha <= 0) {
1497
- continue;
1498
- }
1499
- rowVisibleCounts[y] += 1;
1500
- columnVisibleCounts[x] += 1;
1501
- if (alpha < 255) {
1502
- rowSemiCounts[y] += 1;
1503
- columnSemiCounts[x] += 1;
1504
- }
1505
- }
1506
- }
1507
- let rowsWithLines = 0;
1508
- for (let row = 0; row < height; row += 1) {
1509
- const visibleRatio = rowVisibleCounts[row] / width;
1510
- const semiRatio = rowSemiCounts[row] / width;
1511
- if (visibleRatio >= 0.94 && semiRatio >= 0.72) {
1512
- rowsWithLines += 1;
1513
- }
1514
- }
1515
- let columnsWithLines = 0;
1516
- for (let column = 0; column < width; column += 1) {
1517
- const visibleRatio = columnVisibleCounts[column] / height;
1518
- const semiRatio = columnSemiCounts[column] / height;
1519
- if (visibleRatio >= 0.94 && semiRatio >= 0.72) {
1520
- columnsWithLines += 1;
1521
- }
1522
- }
1523
- return rowsWithLines + columnsWithLines >= 3
1524
- && (rowsWithLines >= 2 || columnsWithLines >= 2);
1525
- }
1526
- async function imageHasBakedPreviewBackground(filePath, options = {}) {
1527
- let sharp;
1528
- try {
1529
- const sharpModule = await Promise.resolve().then(() => __importStar(require('sharp')));
1530
- sharp = sharpModule.default ?? sharpModule;
1531
- }
1532
- catch {
1533
- return false;
1534
- }
1535
- try {
1536
- const { data, info } = await sharp(filePath, { failOn: 'error' })
1537
- .rotate()
1538
- .resize(OWNED_RUNTIME_IMAGE_CHECK_SIZE, OWNED_RUNTIME_IMAGE_CHECK_SIZE, { fit: 'fill' })
1539
- .ensureAlpha()
1540
- .raw()
1541
- .toBuffer({ resolveWithObject: true });
1542
- const hasPreviewBackground = looksLikeBakedCheckerboardPreview({
1543
- data,
1544
- width: info.width,
1545
- height: info.height,
1546
- channels: info.channels,
1547
- }) || looksLikeBakedSolidMattePreview({
1548
- data,
1549
- width: info.width,
1550
- height: info.height,
1551
- channels: info.channels,
1552
- }) || (!options.allowNeutralSolidMatte && looksLikeBakedNeutralSolidMattePreview({
1553
- data,
1554
- width: info.width,
1555
- height: info.height,
1556
- channels: info.channels,
1557
- }));
1558
- if (hasPreviewBackground) {
1559
- return true;
1560
- }
1561
- }
1562
- catch {
1563
- return false;
1564
- }
1565
- try {
1566
- const { data, info } = await sharp(filePath, { failOn: 'error' })
1567
- .rotate()
1568
- .resize(OWNED_RUNTIME_IMAGE_GRID_CHECK_SIZE, OWNED_RUNTIME_IMAGE_GRID_CHECK_SIZE, { fit: 'inside', withoutEnlargement: true })
1569
- .ensureAlpha()
1570
- .raw()
1571
- .toBuffer({ resolveWithObject: true });
1572
- if (looksLikeResidualMatteGridArtifact({
1573
- data,
1574
- width: info.width,
1575
- height: info.height,
1576
- channels: info.channels,
1577
- }) || looksLikeResidualTransparentGridLineArtifact({
1578
- data,
1579
- width: info.width,
1580
- height: info.height,
1581
- channels: info.channels,
1582
- })) {
1583
- return true;
1584
- }
1585
- }
1586
- catch {
1587
- return false;
1588
- }
1589
- return false;
1590
- }
1591
- async function assertNewGameOwnedRuntimeImageAssetsAreClean(task) {
1592
- const unsafeAssets = [];
1593
- for (const ownedAsset of task.ownedAssets) {
1594
- if (!isOwnedRuntimeImageAsset(task, ownedAsset)) {
1595
- continue;
1596
- }
1597
- const primaryPath = ownedAsset.filePaths?.primary;
1598
- if (!primaryPath) {
1599
- continue;
1600
- }
1601
- if (await imageHasBakedPreviewBackground(primaryPath, {
1602
- allowNeutralSolidMatte: isBackgroundLikeOwnedRuntimeImageAsset(ownedAsset),
1603
- })) {
1604
- unsafeAssets.push(`${ownedAsset.name}:${ownedAsset.runtimeKey}`);
1605
- }
1606
- }
1607
- if (unsafeAssets.length > 0) {
1608
- throw new Error(`agent_task_owned_image_asset_checkerboard_background: owned runtime image assets must not contain baked transparency checkerboard, matte-color, or preview backgrounds. Recreate the asset through the PlayDrop make-assets workflow, use a cleaner PlayDrop asset, or use the image as non-runtime listing art only. Unsafe owned assets: ${unsafeAssets.join(', ')}`);
1609
- }
1610
- }
1611
1235
  const RUNTIME_SOURCE_EXTENSIONS = new Set([
1612
1236
  '.html',
1613
1237
  '.js',
@@ -2242,11 +1866,7 @@ async function publishWorkerAppProject(input) {
2242
1866
  throw new Error('agent_task_playdrop_asset_dependency_missing: the creator asked for PlayDrop assets, but catalogue.json does not declare a matching uses.assets, uses.packs, or ownedAssets dependency.');
2243
1867
  }
2244
1868
  if (input.kind === 'NEW_GAME' || input.kind === 'REMIX_GAME') {
2245
- await assertNewGameDirectPlaydropAssetsAreRuntimeSafe({
2246
- client: input.client,
2247
- task,
2248
- });
2249
- await assertNewGameOwnedRuntimeImageAssetsAreClean(task);
1869
+ await (0, ownedRuntimeImageValidation_1.assertOwnedRuntimeImagesAreValid)(task);
2250
1870
  }
2251
1871
  assertRequestedPlaydropAssetsAreUsedAtRuntime({
2252
1872
  task,
@@ -310,6 +310,22 @@ export declare function acquireWorkerSupervisorLock(input: {
310
310
  file?: string;
311
311
  }): WorkerSupervisorLock;
312
312
  export declare function releaseWorkerSupervisorLock(lock: WorkerSupervisorLock): void;
313
+ export type TaskUploadLockOwner = {
314
+ schemaVersion: 1;
315
+ command: 'task upload';
316
+ pid: number;
317
+ processStartIdentity: string;
318
+ createdAt: string;
319
+ };
320
+ export type TaskUploadLock = {
321
+ file: string;
322
+ owner: TaskUploadLockOwner;
323
+ };
324
+ export declare function resolveTaskUploadLockFile(workspaceDir: string): string;
325
+ export declare function removeStaleTaskUploadLockIfUnchanged(file: string, observedHolder: TaskUploadLockOwner): boolean;
326
+ export declare function acquireTaskUploadLock(workspaceDir: string): TaskUploadLock;
327
+ export declare function releaseTaskUploadLock(lock: TaskUploadLock): void;
328
+ export declare function withTaskUploadLock<T>(workspaceDir: string, work: () => Promise<T>): Promise<T>;
313
329
  export declare function readActivePersonalWorkerRuntimeState(): WorkerRuntimeState | null;
314
330
  export declare function parseLaunchAgentProgramArguments(plist: string): string[];
315
331
  export declare function assertLaunchAgentPlistCompatible(input: {