deepline 0.1.307 → 0.1.308

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.
Files changed (24) hide show
  1. package/dist/bundling-sources/sdk/src/play.ts +26 -0
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
  4. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +66 -11
  5. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +13 -5
  6. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +12 -3
  7. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +21 -9
  8. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +2 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +5 -1
  10. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +17 -2
  11. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runtime-limits.ts +102 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +56 -9
  13. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +56 -0
  14. package/dist/bundling-sources/shared_libs/plays/contracts.ts +6 -0
  15. package/dist/cli/index.js +174 -11
  16. package/dist/cli/index.mjs +174 -11
  17. package/dist/index.d.mts +16 -0
  18. package/dist/index.d.ts +16 -0
  19. package/dist/index.js +11 -1
  20. package/dist/index.mjs +11 -1
  21. package/dist/plays/bundle-play-file.d.mts +8 -0
  22. package/dist/plays/bundle-play-file.d.ts +8 -0
  23. package/dist/plays/bundle-play-file.mjs +42 -0
  24. package/package.json +1 -1
@@ -229,6 +229,29 @@ function isHardBillingFailurePayload(
229
229
  );
230
230
  }
231
231
 
232
+ /**
233
+ * A normalized provider 402 is fatal only when the integration boundary has
234
+ * declared it account-level capacity. A raw 402 never reaches this function as
235
+ * proof by itself: providers use that status inconsistently.
236
+ */
237
+ function isProviderAccountCapacityFailurePayload(
238
+ payload: Record<string, unknown> | null,
239
+ ): payload is Record<string, unknown> {
240
+ if (!payload) return false;
241
+ const code = String(payload.code ?? payload.error_code ?? '').toUpperCase();
242
+ const category = String(
243
+ payload.error_category ?? payload.errorCategory ?? '',
244
+ ).toLowerCase();
245
+ const origin = String(
246
+ payload.failure_origin ?? payload.failureOrigin ?? '',
247
+ ).toLowerCase();
248
+ return (
249
+ code === 'PROVIDER_ACCOUNT_CAPACITY' &&
250
+ category === 'provider_account' &&
251
+ (origin === 'provider' || origin === 'provider_account')
252
+ );
253
+ }
254
+
232
255
  function normalizeHardBillingPayload(
233
256
  payload: Record<string, unknown>,
234
257
  ): Record<string, unknown> {
@@ -268,11 +291,19 @@ function formatHardBillingFailureMessage(input: {
268
291
  maxAttempts: number;
269
292
  }): string {
270
293
  const code = getStringField(input.billing, 'code');
294
+ const providerCapacity = isProviderAccountCapacityFailurePayload(
295
+ input.billing,
296
+ );
271
297
  const message =
272
298
  getStringField(input.billing, 'message') ??
273
299
  getStringField(input.billing, 'error') ??
274
- 'Deepline billing cap exceeded.';
275
- return `tool ${input.toolId} ${input.status} attempt ${input.attempt}/${input.maxAttempts}: Deepline billing cap exceeded. Run halted before marking remaining rows processed. ${code ? `code=${code}. ` : ''}${message}`;
300
+ (providerCapacity
301
+ ? 'Provider account capacity blocked execution.'
302
+ : 'Deepline billing cap exceeded.');
303
+ const headline = providerCapacity
304
+ ? 'Provider account capacity blocked execution.'
305
+ : 'Deepline billing cap exceeded.';
306
+ return `tool ${input.toolId} ${input.status} attempt ${input.attempt}/${input.maxAttempts}: ${headline} Run halted before marking remaining rows processed. ${code ? `code=${code}. ` : ''}${message}`;
276
307
  }
277
308
 
278
309
  function formatInsufficientCreditsMessage(input: {
@@ -434,8 +465,13 @@ export function normalizeToolHttpErrorMessage(input: {
434
465
  ? normalizeHardBillingPayload(billing)
435
466
  : isHardBillingFailurePayload(parsed)
436
467
  ? normalizeHardBillingPayload(parsed)
437
- : null;
468
+ : isProviderAccountCapacityFailurePayload(parsed)
469
+ ? parsed
470
+ : null;
438
471
  if (hardBillingPayload) {
472
+ const providerCapacity = isProviderAccountCapacityFailurePayload(
473
+ hardBillingPayload,
474
+ );
439
475
  return createToolHttpError(
440
476
  schemaVersion,
441
477
  formatHardBillingFailureMessage({
@@ -450,8 +486,15 @@ export function normalizeToolHttpErrorMessage(input: {
450
486
  'terminal',
451
487
  {
452
488
  ...publicOptions,
453
- origin: 'deepline',
454
- category: 'billing',
489
+ origin: providerCapacity ? 'provider' : 'deepline',
490
+ // `provider_account` is the integration-boundary category. The
491
+ // portable ToolExecutionError taxonomy canonically represents it as
492
+ // provider-owned authentication; the code retains the precise
493
+ // account-capacity reason.
494
+ category: providerCapacity ? 'authentication' : 'billing',
495
+ code: providerCapacity
496
+ ? 'PROVIDER_ACCOUNT_CAPACITY'
497
+ : publicOptions.code,
455
498
  retryable: false,
456
499
  },
457
500
  );
@@ -481,15 +524,19 @@ export function isHardBillingToolHttpError(error: unknown): boolean {
481
524
  if (
482
525
  error instanceof ToolHttpError &&
483
526
  (isInsufficientCreditsBilling(error.billing) ||
484
- isHardBillingFailurePayload(error.billing))
527
+ isHardBillingFailurePayload(error.billing) ||
528
+ isProviderAccountCapacityFailurePayload(error.billing))
485
529
  ) {
486
530
  return true;
487
531
  }
488
532
  return (
489
533
  error instanceof ToolExecutionError &&
490
- error.origin === 'deepline' &&
491
- error.category === 'billing' &&
492
- error.code !== 'BILLING_UNAVAILABLE'
534
+ ((error.origin === 'deepline' &&
535
+ error.category === 'billing' &&
536
+ error.code !== 'BILLING_UNAVAILABLE') ||
537
+ (error.origin === 'provider' &&
538
+ error.category === 'authentication' &&
539
+ error.code === 'PROVIDER_ACCOUNT_CAPACITY'))
493
540
  );
494
541
  }
495
542
 
@@ -29,6 +29,7 @@ import type {
29
29
  } from '../artifact-types';
30
30
  import { buildPlayContractCompatibility } from '../contracts';
31
31
  import type { ToolExecutionErrorSchemaVersion } from '../../tool-execution-error';
32
+ import type { PlaySandboxRuntimeDeclaration } from '../../play-runtime/sandbox-runtime-limits';
32
33
  import { validatePlaySourceFilesHaveNoInlineSecrets } from '../secret-guardrails';
33
34
  import { MAX_PLAY_BUNDLE_BYTES } from './limits';
34
35
 
@@ -126,6 +127,7 @@ export type BundledPlayFileSuccess = {
126
127
  filePath: string;
127
128
  playName: string | null;
128
129
  playDescription: string | null;
130
+ sandboxRuntimeDeclaration: PlaySandboxRuntimeDeclaration | null;
129
131
  compilerManifest?: PlayCompilerManifest;
130
132
  packagedFiles: PlayLocalFileReference[];
131
133
  unresolvedFileReferences: PlayLocalFileDiscoveryError[];
@@ -155,6 +157,7 @@ type SourceGraphAnalysis = {
155
157
  importPolicy: PlayImportPolicy;
156
158
  playName: string | null;
157
159
  playDescription: string | null;
160
+ sandboxRuntimeDeclaration: PlaySandboxRuntimeDeclaration | null;
158
161
  toolErrorSchemaVersion: ToolExecutionErrorSchemaVersion | null;
159
162
  importedPlayDependencies: ImportedPlayDependency[];
160
163
  };
@@ -505,6 +508,7 @@ type PlayMetadataExtractionContext = {
505
508
  type ExtractedPlayMetadata = {
506
509
  name: string | null;
507
510
  description: string | null;
511
+ sandboxRuntimeDeclaration: PlaySandboxRuntimeDeclaration | null;
508
512
  toolErrorSchemaVersion: ToolExecutionErrorSchemaVersion | null;
509
513
  toolErrorSchemaVersionUnknown: boolean;
510
514
  };
@@ -939,6 +943,48 @@ function toolErrorSchemaVersionFromOptions(
939
943
  return null;
940
944
  }
941
945
 
946
+ function sandboxRuntimeDeclarationFromOptions(
947
+ node: AstNode | null | undefined,
948
+ context: PlayMetadataExtractionContext,
949
+ ): PlaySandboxRuntimeDeclaration | null {
950
+ const directRuntime = resolveStaticProperty(node, 'runtime', context);
951
+ const bindings = resolveStaticProperty(node, 'bindings', context);
952
+ const bindingRuntime =
953
+ bindings.kind === 'found'
954
+ ? resolveStaticProperty(bindings.value, 'runtime', context)
955
+ : ({ kind: 'absent' } satisfies StaticPropertyResolution);
956
+ const runtime =
957
+ directRuntime.kind === 'found' ? directRuntime : bindingRuntime;
958
+ if (runtime.kind !== 'found') return null;
959
+
960
+ const timeout = resolveStaticProperty(runtime.value, 'timeout', context);
961
+ const memory = resolveStaticProperty(runtime.value, 'memory', context);
962
+ const cpu = resolveStaticProperty(runtime.value, 'cpu', context);
963
+ const disk = resolveStaticProperty(runtime.value, 'disk', context);
964
+ const declaration: PlaySandboxRuntimeDeclaration = {};
965
+ if (timeout.kind === 'found') {
966
+ const value = staticStringFromExpression(timeout.value, context);
967
+ if (value === null) return null;
968
+ declaration.timeout = value;
969
+ }
970
+ if (memory.kind === 'found') {
971
+ const value = staticStringFromExpression(memory.value, context);
972
+ if (value === null) return null;
973
+ declaration.memory = value;
974
+ }
975
+ if (cpu.kind === 'found') {
976
+ const value = staticNumberFromExpression(cpu.value, context);
977
+ if (value === null) return null;
978
+ declaration.cpu = value;
979
+ }
980
+ if (disk.kind === 'found') {
981
+ const value = staticStringFromExpression(disk.value, context);
982
+ if (value === null) return null;
983
+ declaration.disk = value;
984
+ }
985
+ return declaration;
986
+ }
987
+
942
988
  function stringPropertyFromObjectExpression(
943
989
  node: AstNode | null | undefined,
944
990
  propertyName: string,
@@ -1031,6 +1077,10 @@ function playMetadataFromDefinePlayCall(
1031
1077
  }
1032
1078
 
1033
1079
  const options = isObjectForm ? firstArg : (args[2] ?? null);
1080
+ const sandboxRuntimeDeclaration = sandboxRuntimeDeclarationFromOptions(
1081
+ options,
1082
+ context,
1083
+ );
1034
1084
  const toolErrorSchemaVersion = toolErrorSchemaVersionFromOptions(
1035
1085
  options,
1036
1086
  context,
@@ -1048,6 +1098,7 @@ function playMetadataFromDefinePlayCall(
1048
1098
  return {
1049
1099
  name,
1050
1100
  description,
1101
+ sandboxRuntimeDeclaration,
1051
1102
  toolErrorSchemaVersion: toolErrorSchemaVersion ?? null,
1052
1103
  toolErrorSchemaVersionUnknown,
1053
1104
  };
@@ -1545,6 +1596,8 @@ async function analyzeSourceGraph(
1545
1596
  }
1546
1597
  const playName = metadata?.name ?? null;
1547
1598
  const playDescription = metadata?.description ?? null;
1599
+ const sandboxRuntimeDeclaration =
1600
+ metadata?.sandboxRuntimeDeclaration ?? null;
1548
1601
 
1549
1602
  return {
1550
1603
  sourceCode,
@@ -1564,6 +1617,7 @@ async function analyzeSourceGraph(
1564
1617
  },
1565
1618
  playName,
1566
1619
  playDescription,
1620
+ sandboxRuntimeDeclaration,
1567
1621
  toolErrorSchemaVersion: metadata?.toolErrorSchemaVersion ?? null,
1568
1622
  importedPlayDependencies: [...importedPlayDependencies.values()].sort(
1569
1623
  (left, right) => left.filePath.localeCompare(right.filePath),
@@ -1824,6 +1878,7 @@ export async function bundlePlayFile(
1824
1878
  filePath: absolutePath,
1825
1879
  playName: analysis.playName,
1826
1880
  playDescription: analysis.playDescription,
1881
+ sandboxRuntimeDeclaration: analysis.sandboxRuntimeDeclaration,
1827
1882
  packagedFiles: discoveredFiles.files,
1828
1883
  unresolvedFileReferences: discoveredFiles.unresolved,
1829
1884
  importedPlayDependencies: analysis.importedPlayDependencies,
@@ -1898,6 +1953,7 @@ export async function bundlePlayFile(
1898
1953
  filePath: absolutePath,
1899
1954
  playName: analysis.playName,
1900
1955
  playDescription: analysis.playDescription,
1956
+ sandboxRuntimeDeclaration: analysis.sandboxRuntimeDeclaration,
1901
1957
  packagedFiles: discoveredFiles.files,
1902
1958
  unresolvedFileReferences: discoveredFiles.unresolved,
1903
1959
  importedPlayDependencies: analysis.importedPlayDependencies,
@@ -111,6 +111,12 @@ export type PlayRunContractSnapshot = {
111
111
  billingLimit?: {
112
112
  maxCreditsPerRun?: number | null;
113
113
  } | null;
114
+ runtimeLimit?: {
115
+ timeoutSeconds: number;
116
+ memoryGiB: number;
117
+ cpu: number;
118
+ diskGiB: number;
119
+ } | null;
114
120
  structuredDefinition?: unknown;
115
121
  artifactMetadata?: Record<string, unknown> | null;
116
122
  codeFormat?: 'function' | 'cjs_module' | 'esm_module' | null;
package/dist/cli/index.js CHANGED
@@ -1037,7 +1037,7 @@ var SDK_RELEASE = {
1037
1037
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
1038
1038
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
1039
1039
  // Operators use the checkout-local deepline-admin binary instead.
1040
- version: "0.1.307",
1040
+ version: "0.1.308",
1041
1041
  contracts: {
1042
1042
  api: {
1043
1043
  name: "sdk-http-api",
@@ -12142,6 +12142,134 @@ function resolveEnabledExecutionProfile(override) {
12142
12142
  }
12143
12143
  }
12144
12144
 
12145
+ // ../shared_libs/play-runtime/sandbox-runtime-limits.ts
12146
+ var STANDARD_PLAY_SANDBOX_RUNTIME_LIMITS = {
12147
+ timeoutSeconds: 30 * 60,
12148
+ memoryGiB: 1,
12149
+ cpu: 1,
12150
+ diskGiB: 3
12151
+ };
12152
+ var MAX_PLAY_SANDBOX_RUNTIME_LIMITS = {
12153
+ timeoutSeconds: 4 * 60 * 60,
12154
+ memoryGiB: 16,
12155
+ cpu: 4,
12156
+ diskGiB: 50
12157
+ };
12158
+ function parsePositiveInteger3(value, unit) {
12159
+ const match = new RegExp(`^(\\d+)\\s*${unit}$`, "i").exec(value.trim());
12160
+ if (!match) return null;
12161
+ const parsed = Number(match[1]);
12162
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
12163
+ }
12164
+ function parseTimeout(value) {
12165
+ const match = /^(\d+)\s*([mh])$/i.exec(value.trim());
12166
+ if (!match) return null;
12167
+ const amount = Number(match[1]);
12168
+ if (!Number.isSafeInteger(amount) || amount <= 0) return null;
12169
+ return amount * (match[2].toLowerCase() === "h" ? 3600 : 60);
12170
+ }
12171
+ function resolvePlaySandboxRuntimeLimits(declaration) {
12172
+ const base = STANDARD_PLAY_SANDBOX_RUNTIME_LIMITS;
12173
+ if (!declaration) return { ...base };
12174
+ const timeoutSeconds = declaration.timeout ? parseTimeout(declaration.timeout) : base.timeoutSeconds;
12175
+ const memoryGiB = declaration.memory ? parsePositiveInteger3(declaration.memory, "GiB") : base.memoryGiB;
12176
+ const diskGiB = declaration.disk ? parsePositiveInteger3(declaration.disk, "GiB") : base.diskGiB;
12177
+ const cpu = declaration.cpu ?? base.cpu;
12178
+ if (timeoutSeconds === null || memoryGiB === null || diskGiB === null || !Number.isSafeInteger(cpu) || cpu <= 0) {
12179
+ throw new Error(
12180
+ 'Invalid runtime sandbox declaration. Use timeout like "90m" or "2h", memory/disk like "4GiB", and a positive integer cpu.'
12181
+ );
12182
+ }
12183
+ const resolved = { timeoutSeconds, memoryGiB, cpu, diskGiB };
12184
+ for (const key of ["memoryGiB", "cpu", "diskGiB"]) {
12185
+ if (resolved[key] < base[key]) {
12186
+ throw new Error(
12187
+ `Requested runtime ${key}=${resolved[key]} is below the supported minimum ${base[key]}.`
12188
+ );
12189
+ }
12190
+ }
12191
+ for (const key of Object.keys(
12192
+ resolved
12193
+ )) {
12194
+ if (resolved[key] > MAX_PLAY_SANDBOX_RUNTIME_LIMITS[key]) {
12195
+ throw new Error(
12196
+ `Requested runtime ${key}=${resolved[key]} exceeds this organisation's maximum ${MAX_PLAY_SANDBOX_RUNTIME_LIMITS[key]}.`
12197
+ );
12198
+ }
12199
+ }
12200
+ return resolved;
12201
+ }
12202
+ function hasNonStandardPlaySandboxRuntimeLimits(value) {
12203
+ return Object.keys(value).some(
12204
+ (key) => value[key] !== STANDARD_PLAY_SANDBOX_RUNTIME_LIMITS[key]
12205
+ );
12206
+ }
12207
+
12208
+ // ../shared_libs/play-runtime/worker-api-types.ts
12209
+ var DAYTONA_COMPUTE_PRICING_USD = {
12210
+ vcpuSecond: 14e-6,
12211
+ memoryGiBSecond: 45e-7,
12212
+ storageGiBSecond: 3e-8,
12213
+ includedStorageGiB: 5
12214
+ };
12215
+ function roundUsd(amount) {
12216
+ return Number(Math.max(0, amount).toFixed(12));
12217
+ }
12218
+ function resolveDaytonaSandboxComputeItem(input2) {
12219
+ const billableSeconds = Math.max(1, Math.ceil(input2.wallTimeSeconds));
12220
+ const cpu = Math.max(0, input2.cpu);
12221
+ const memoryGiB = Math.max(0, input2.memoryGiB);
12222
+ const billableDiskGiB = Math.max(
12223
+ 0,
12224
+ input2.diskGiB - DAYTONA_COMPUTE_PRICING_USD.includedStorageGiB
12225
+ );
12226
+ const providerCostUsd = roundUsd(
12227
+ billableSeconds * (cpu * DAYTONA_COMPUTE_PRICING_USD.vcpuSecond + memoryGiB * DAYTONA_COMPUTE_PRICING_USD.memoryGiBSecond + billableDiskGiB * DAYTONA_COMPUTE_PRICING_USD.storageGiBSecond)
12228
+ );
12229
+ return {
12230
+ itemId: input2.itemId,
12231
+ source: input2.source ?? "daytona",
12232
+ unit: "sandbox_second",
12233
+ units: billableSeconds,
12234
+ providerCostUsd,
12235
+ metadata: {
12236
+ sandboxId: input2.sandboxId ?? null,
12237
+ cpu,
12238
+ memoryGiB,
12239
+ diskGiB: Math.max(0, input2.diskGiB),
12240
+ billableDiskGiB,
12241
+ startedAt: input2.startedAt,
12242
+ endedAt: input2.endedAt
12243
+ }
12244
+ };
12245
+ }
12246
+
12247
+ // ../shared_libs/billing/compute-pricing.ts
12248
+ var COMPUTE_BILLING_MARKUP_MULTIPLIER = 5;
12249
+ var DEFAULT_USD_PER_CUSTOMER_CREDIT = 0.1;
12250
+ var DEFAULT_PROVIDER_MARKUP_MULTIPLIER = 1.4;
12251
+ function roundUpCredits(value) {
12252
+ if (!Number.isFinite(value) || value <= 0) return 0;
12253
+ return Math.ceil(value * 100) / 100;
12254
+ }
12255
+ function estimateDaytonaMaximumComputeCredits(limits) {
12256
+ const item = resolveDaytonaSandboxComputeItem({
12257
+ itemId: "estimate",
12258
+ wallTimeSeconds: limits.timeoutSeconds,
12259
+ cpu: limits.cpu,
12260
+ memoryGiB: limits.memoryGiB,
12261
+ diskGiB: limits.diskGiB
12262
+ });
12263
+ return roundUpCredits(
12264
+ item.providerCostUsd * COMPUTE_BILLING_MARKUP_MULTIPLIER * DEFAULT_PROVIDER_MARKUP_MULTIPLIER / DEFAULT_USD_PER_CUSTOMER_CREDIT
12265
+ );
12266
+ }
12267
+ function formatNonStandardSandboxRuntimeWarning(limits) {
12268
+ if (!hasNonStandardPlaySandboxRuntimeLimits(limits)) return null;
12269
+ const maximumComputeCredits = estimateDaytonaMaximumComputeCredits(limits);
12270
+ return `This Play requests a non-standard sandbox (${limits.timeoutSeconds}s, ${limits.memoryGiB}GiB memory, ${limits.cpu} CPU, ${limits.diskGiB}GiB disk). Maximum compute estimate: ${maximumComputeCredits.toFixed(2)} Deepline credits. It may queue longer.`;
12271
+ }
12272
+
12145
12273
  // ../shared_libs/play-runtime/internal-step-ids.ts
12146
12274
  var INTERNAL_GLUE_NODE_ID_PREFIX = "run_javascript:";
12147
12275
  function isInternalGlueStepId(stepId) {
@@ -12701,7 +12829,7 @@ function looksLikeFilePath(target) {
12701
12829
  }
12702
12830
  return target.includes("\\") || /\.(ts|js|mjs|play\.ts)$/.test(target);
12703
12831
  }
12704
- function parsePositiveInteger3(value, flagName) {
12832
+ function parsePositiveInteger4(value, flagName) {
12705
12833
  const parsed = Number.parseInt(value, 10);
12706
12834
  if (!Number.isFinite(parsed) || parsed <= 0) {
12707
12835
  throw new Error(`${flagName} must be a positive integer.`);
@@ -16221,7 +16349,7 @@ function parsePlayRunOptions(args) {
16221
16349
  );
16222
16350
  }
16223
16351
  if ((arg === "--tail-timeout-ms" || arg === "--timeout-ms") && args[index + 1]) {
16224
- waitTimeoutMs = parsePositiveInteger3(args[++index], arg);
16352
+ waitTimeoutMs = parsePositiveInteger4(args[++index], arg);
16225
16353
  continue;
16226
16354
  }
16227
16355
  if (PLAY_RUN_RESERVED_BOOLEAN_FLAGS.has(arg)) {
@@ -16544,23 +16672,49 @@ function formatPlayCheckIssueLines(issue) {
16544
16672
  }
16545
16673
  return lines;
16546
16674
  }
16547
- function printPlayCheckIssues(issues, writer) {
16548
- if (!issues?.length) return;
16549
- const errorIssues = issues.filter((issue) => issue.severity === "error");
16550
- const warningIssues = issues.filter((issue) => issue.severity === "warning");
16675
+ function printPlayCheckIssues(issues, writer, warnings = void 0) {
16676
+ const errorIssues = (issues ?? []).filter(
16677
+ (issue) => issue.severity === "error"
16678
+ );
16679
+ const warningIssues = (issues ?? []).filter(
16680
+ (issue) => issue.severity === "warning"
16681
+ );
16682
+ const structuredWarningMessages = warningIssues.map(
16683
+ (issue) => issue.message.trim()
16684
+ );
16685
+ const stringWarnings = [...new Set(warnings ?? [])].filter((warning) => {
16686
+ const trimmed = warning.trim();
16687
+ return trimmed.length > 0 && !structuredWarningMessages.some(
16688
+ (message) => trimmed === message || trimmed.startsWith(message)
16689
+ );
16690
+ });
16551
16691
  if (errorIssues.length) {
16552
16692
  writer(" issues:");
16553
16693
  for (const issue of errorIssues) {
16554
16694
  for (const line of formatPlayCheckIssueLines(issue)) writer(line);
16555
16695
  }
16556
16696
  }
16557
- if (warningIssues.length) {
16697
+ if (warningIssues.length || stringWarnings.length) {
16558
16698
  writer(" warnings:");
16559
16699
  for (const issue of warningIssues) {
16560
16700
  for (const line of formatPlayCheckIssueLines(issue)) writer(line);
16561
16701
  }
16702
+ for (const warning of stringWarnings) writer(` - ${warning.trim()}`);
16562
16703
  }
16563
16704
  }
16705
+ function formatPlaySandboxRuntimeWarning(declaration) {
16706
+ if (!declaration) return null;
16707
+ const warning = formatNonStandardSandboxRuntimeWarning(
16708
+ resolvePlaySandboxRuntimeLimits(declaration)
16709
+ );
16710
+ return warning ? `Warning: ${warning}` : null;
16711
+ }
16712
+ function printBundledRuntimeWarning(bundle) {
16713
+ const warning = formatPlaySandboxRuntimeWarning(
16714
+ bundle.sandboxRuntimeDeclaration
16715
+ );
16716
+ if (warning) console.warn(warning);
16717
+ }
16564
16718
  function partitionMirroredErrors(errors, issues) {
16565
16719
  const errorMessages = (issues ?? []).filter((issue) => issue.severity === "error").map((issue) => issue.message.trim()).filter((message) => message.length > 0);
16566
16720
  if (errorMessages.length === 0) {
@@ -16738,7 +16892,11 @@ async function handlePlayCheck(args) {
16738
16892
  }
16739
16893
  printPlayTriggers(enrichedResult.triggers);
16740
16894
  printRecognizedSummary(enrichedResult.recognized);
16741
- printPlayCheckIssues(enrichedResult.issues, (line) => console.log(line));
16895
+ printPlayCheckIssues(
16896
+ enrichedResult.issues,
16897
+ (line) => console.log(line),
16898
+ enrichedResult.warnings
16899
+ );
16742
16900
  printToolGetterHints(enrichedResult.toolGetterHints);
16743
16901
  } else {
16744
16902
  console.error(`\u2717 ${playName} failed cloud play check`);
@@ -16749,7 +16907,11 @@ async function handlePlayCheck(args) {
16749
16907
  for (const error of unstructuredErrors) {
16750
16908
  console.error(` ${error}`);
16751
16909
  }
16752
- printPlayCheckIssues(enrichedResult.issues, (line) => console.error(line));
16910
+ printPlayCheckIssues(
16911
+ enrichedResult.issues,
16912
+ (line) => console.error(line),
16913
+ enrichedResult.warnings
16914
+ );
16753
16915
  printToolGetterHints(enrichedResult.toolGetterHints);
16754
16916
  }
16755
16917
  return enrichedResult.valid ? 0 : 1;
@@ -16810,6 +16972,7 @@ async function handleFileBackedRun(options, hooks) {
16810
16972
  }
16811
16973
  const bundleResult = graph.root;
16812
16974
  const playName = bundleResult.playName ?? extractPlayName(sourceCode, absolutePlayPath);
16975
+ printBundledRuntimeWarning(bundleResult);
16813
16976
  try {
16814
16977
  progress.phase("publishing imported plays");
16815
16978
  await traceCliSpan(
@@ -17347,7 +17510,7 @@ async function handleRunLogs(args) {
17347
17510
  for (let index = 0; index < args.length; index += 1) {
17348
17511
  const arg = args[index];
17349
17512
  if (arg === "--limit" && args[index + 1]) {
17350
- limit = parsePositiveInteger3(args[++index], "--limit");
17513
+ limit = parsePositiveInteger4(args[++index], "--limit");
17351
17514
  continue;
17352
17515
  }
17353
17516
  if (arg === "--out" && args[index + 1]) {