deepline 0.1.320 → 0.2.1

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 (32) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +13 -2
  2. package/dist/bundling-sources/sdk/src/release.ts +4 -1
  3. package/dist/bundling-sources/shared_libs/play-runtime/backend.ts +19 -0
  4. package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +104 -0
  5. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +4 -1
  6. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +106 -3
  7. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-modal-fallback.ts +218 -0
  8. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +26 -7
  9. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +33 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +380 -0
  11. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/index.ts +28 -3
  12. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +240 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +5 -1
  14. package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +17 -2
  15. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-placement-policy.ts +188 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +77 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +7 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +10 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +39 -0
  20. package/dist/bundling-sources/shared_libs/plays/dataset.ts +43 -47
  21. package/dist/cli/index.js +55 -28
  22. package/dist/cli/index.mjs +55 -28
  23. package/dist/index.d.mts +8 -9
  24. package/dist/index.d.ts +8 -9
  25. package/dist/index.js +86 -38
  26. package/dist/index.mjs +86 -38
  27. package/dist/plays/bundle-play-file.d.mts +2 -2
  28. package/dist/plays/bundle-play-file.d.ts +2 -2
  29. package/dist/plays/bundle-play-file.mjs +7 -1
  30. package/dist/{tool-execution-error-YDz7UMl-.d.mts → tool-execution-error-4-rhemLQ.d.mts} +7 -1
  31. package/dist/{tool-execution-error-YDz7UMl-.d.ts → tool-execution-error-4-rhemLQ.d.ts} +7 -1
  32. package/package.json +1 -1
@@ -105,17 +105,14 @@ export type PlayDatasetTransformOptions = {
105
105
  * runtime control. Use `count()` and `peek()` for bounded inspection. Use
106
106
  * `materialize(limit)` or async iteration only when the dataset is intentionally
107
107
  * small and bounded. `PlayDataset` intentionally does not expose `.rows`,
108
- * `.toArray()`, or other array aliases; those hide the runtime cost of loading
109
- * persisted rows into memory.
108
+ * `.toArray()`, `.length`, numeric indexing, spread, or synchronous iteration;
109
+ * those hide the runtime cost of loading persisted rows into memory or make
110
+ * behavior depend on whether rows happen to be resident.
110
111
  *
111
112
  * @sdkReference runtime 190
112
113
  */
113
- export interface PlayDataset<T> extends AsyncIterable<T>, Iterable<T> {
114
+ export interface PlayDataset<T> extends AsyncIterable<T> {
114
115
  readonly [PLAY_DATASET_BRAND]: true;
115
- /** Authoritative row count when known without I/O. */
116
- readonly length: number;
117
- /** Resident row access. Throws when the requested row requires I/O. */
118
- readonly [index: number]: T;
119
116
  /** Dataset kind. */
120
117
  readonly datasetKind: PlayDatasetKind;
121
118
  /** Dataset id. */
@@ -413,7 +410,6 @@ export function trimSerializedPlayDatasetPreview<T>(
413
410
  }
414
411
 
415
412
  class DeferredPlayDataset<T> implements PlayDataset<T> {
416
- readonly [index: number]: T;
417
413
  readonly [PLAY_DATASET_BRAND] = true as const;
418
414
  readonly datasetKind: PlayDatasetKind;
419
415
  readonly datasetId: string;
@@ -456,15 +452,6 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
456
452
  this.resolvers = input.resolvers;
457
453
  }
458
454
 
459
- get length(): number {
460
- if (this.knownCount === null) {
461
- throw this.requiresAsyncAccess(
462
- 'The row count is not known until this lazy transform executes.',
463
- );
464
- }
465
- return this.knownCount;
466
- }
467
-
468
455
  async count(): Promise<number> {
469
456
  this.cachedCount = await this.resolvers.count();
470
457
  this.knownCount = this.cachedCount;
@@ -492,6 +479,9 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
492
479
  return undefined;
493
480
  }
494
481
  if (this.residentRows) return this.residentRows[normalized];
482
+ if (normalized < this.previewRows.length) {
483
+ return this.previewRows[normalized];
484
+ }
495
485
  if (this.resolvers.at) return await this.resolvers.at(normalized);
496
486
  let current = 0;
497
487
  for await (const row of this.resolvers.iterate()) {
@@ -591,33 +581,6 @@ class DeferredPlayDataset<T> implements PlayDataset<T> {
591
581
  }
592
582
  }
593
583
 
594
- [Symbol.iterator](): Iterator<T> {
595
- if (!this.residentRows) {
596
- throw this.requiresAsyncAccess(
597
- 'Synchronous iteration is available only when every row is resident.',
598
- );
599
- }
600
- return this.residentRows[Symbol.iterator]();
601
- }
602
-
603
- residentAt(index: number): T | undefined {
604
- if (this.knownCount !== null && index >= this.knownCount) return undefined;
605
- if (!this.residentRows) {
606
- throw this.requiresAsyncAccess(
607
- `Row ${index} is not resident and may require dataset paging.`,
608
- );
609
- }
610
- return this.residentRows[index];
611
- }
612
-
613
- private requiresAsyncAccess(detail: string): Error {
614
- return new Error(
615
- `PLAY_DATASET_REQUIRES_ASYNC_ACCESS: ${detail} ` +
616
- `Dataset Handle ${this.sourceLabel ?? this.datasetId}. ` +
617
- 'Use await dataset.first(), await dataset.at(index), await dataset.materialize(limit), or for await...of.',
618
- );
619
- }
620
-
621
584
  toJSON() {
622
585
  return {
623
586
  kind: 'dataset' as const,
@@ -802,8 +765,28 @@ export function createDeferredPlayDataset<T>(input: {
802
765
  const boundMethods = new Map<PropertyKey, unknown>();
803
766
  const dataset = new Proxy(target, {
804
767
  get(dataset, property) {
768
+ if (property === 'length') {
769
+ throw datasetAsyncOnlyError(
770
+ dataset,
771
+ 'Dataset Handles do not expose synchronous .length.',
772
+ 'Use await dataset.count().',
773
+ );
774
+ }
805
775
  if (typeof property === 'string' && /^(0|[1-9]\d*)$/.test(property)) {
806
- return dataset.residentAt(Number(property));
776
+ throw datasetAsyncOnlyError(
777
+ dataset,
778
+ `Dataset Handles do not expose synchronous row indexing (${property}).`,
779
+ `Use await dataset.at(${property}) or await dataset.first().`,
780
+ );
781
+ }
782
+ if (property === Symbol.iterator) {
783
+ return () => {
784
+ throw datasetAsyncOnlyError(
785
+ dataset,
786
+ 'Dataset Handles do not support synchronous iteration.',
787
+ 'Use for await...of or await dataset.materialize(limit).',
788
+ );
789
+ };
807
790
  }
808
791
  const value = Reflect.get(dataset, property, dataset);
809
792
  if (typeof value !== 'function') return value;
@@ -817,8 +800,10 @@ export function createDeferredPlayDataset<T>(input: {
817
800
  property === 'length' ||
818
801
  (typeof property === 'string' && /^(0|[1-9]\d*)$/.test(property))
819
802
  ) {
820
- throw new Error(
821
- 'PLAY_DATASET_READ_ONLY: Dataset Handle rows cannot be assigned directly.',
803
+ throw datasetAsyncOnlyError(
804
+ target,
805
+ 'Dataset Handles do not support synchronous array assignment.',
806
+ 'Transform rows with dataset.map(...) or explicitly materialize a bounded array.',
822
807
  );
823
808
  }
824
809
  return false;
@@ -831,6 +816,17 @@ export function createDeferredPlayDataset<T>(input: {
831
816
  return dataset;
832
817
  }
833
818
 
819
+ function datasetAsyncOnlyError(
820
+ dataset: Pick<PlayDataset<unknown>, 'datasetId' | 'sourceLabel'>,
821
+ detail: string,
822
+ guidance: string,
823
+ ): Error {
824
+ return new Error(
825
+ `PLAY_DATASET_ASYNC_ONLY: ${detail} ` +
826
+ `Dataset Handle ${dataset.sourceLabel ?? dataset.datasetId}. ${guidance}`,
827
+ );
828
+ }
829
+
834
830
  export function createPlayDataset<T>(
835
831
  rows: readonly T[],
836
832
  metadata?: {
package/dist/cli/index.js CHANGED
@@ -1037,7 +1037,10 @@ 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.320",
1040
+ // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
1041
+ // exposed storage-dependent synchronous access. This deliberate minor
1042
+ // release keeps lazy paging semantics independent of row residency.
1043
+ version: "0.2.1",
1041
1044
  contracts: {
1042
1045
  api: {
1043
1046
  name: "sdk-http-api",
@@ -3244,6 +3247,33 @@ function usesExtendedTheirstackJobSearchBudget(endpointId, payload) {
3244
3247
  return maxAgeDays !== null && maxAgeDays >= 365 ? true : usesLongExplicitDateWindow(payload);
3245
3248
  }
3246
3249
 
3250
+ // ../shared_libs/play-runtime/backend.ts
3251
+ var PLAY_RUNTIME_BACKENDS = {
3252
+ localProcess: "local_process",
3253
+ daytona: "daytona",
3254
+ modal: "modal"
3255
+ };
3256
+ var PLAY_ARTIFACT_KINDS = {
3257
+ cjsNode20: "cjs_node20"
3258
+ };
3259
+ var PLAY_BACKEND_DESCRIPTORS = {
3260
+ [PLAY_RUNTIME_BACKENDS.localProcess]: {
3261
+ id: PLAY_RUNTIME_BACKENDS.localProcess,
3262
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
3263
+ label: "Local node subprocess"
3264
+ },
3265
+ [PLAY_RUNTIME_BACKENDS.daytona]: {
3266
+ id: PLAY_RUNTIME_BACKENDS.daytona,
3267
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
3268
+ label: "Daytona sandbox"
3269
+ },
3270
+ [PLAY_RUNTIME_BACKENDS.modal]: {
3271
+ id: PLAY_RUNTIME_BACKENDS.modal,
3272
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
3273
+ label: "Modal sandbox"
3274
+ }
3275
+ };
3276
+
3247
3277
  // ../shared_libs/play-runtime/runtime-environment.ts
3248
3278
  var PLAY_RUNTIME_ENVIRONMENTS = ["preview"];
3249
3279
  var PLAY_RUNTIME_NAMESPACE_PATTERN = /^[a-z][a-z0-9-]{0,30}$/;
@@ -3256,12 +3286,19 @@ function normalizePlayRuntimeSelection(value) {
3256
3286
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
3257
3287
  const record = value;
3258
3288
  if (Object.keys(record).some(
3259
- (key) => key !== "environment" && key !== "namespace"
3289
+ (key) => key !== "environment" && key !== "namespace" && key !== "backend"
3260
3290
  ) || record.environment !== "preview") {
3261
3291
  return null;
3262
3292
  }
3263
3293
  const namespace = normalizePlayRuntimeNamespace(record.namespace);
3264
- return namespace ? { environment: "preview", namespace } : null;
3294
+ if (!namespace) return null;
3295
+ if (record.backend === void 0) {
3296
+ return { environment: "preview", namespace };
3297
+ }
3298
+ if (record.backend !== PLAY_RUNTIME_BACKENDS.daytona && record.backend !== PLAY_RUNTIME_BACKENDS.modal) {
3299
+ return null;
3300
+ }
3301
+ return { environment: "preview", namespace, backend: record.backend };
3265
3302
  }
3266
3303
  function normalizePlayRuntimeEnvironment(value) {
3267
3304
  return typeof value === "string" && PLAY_RUNTIME_ENVIRONMENTS.includes(value) ? value : null;
@@ -3294,7 +3331,7 @@ function resolvePlayRunRuntimeSelection(request) {
3294
3331
  const runtime = normalizePlayRuntimeSelection(request.runtime);
3295
3332
  if (!runtime) {
3296
3333
  throw new DeeplineError(
3297
- 'runtime must be exactly { environment: "preview", namespace } with namespace matching ^[a-z][a-z0-9-]{0,30}$.',
3334
+ 'runtime must be { environment: "preview", namespace, backend?: "daytona" | "modal" } with namespace matching ^[a-z][a-z0-9-]{0,30}$.',
3298
3335
  void 0,
3299
3336
  "INVALID_RUNTIME_SELECTION"
3300
3337
  );
@@ -3330,7 +3367,18 @@ function resolvePlayRunRuntimeSelection(request) {
3330
3367
  "INVALID_RUNTIME_NAMESPACE"
3331
3368
  );
3332
3369
  }
3333
- return { environment, namespace };
3370
+ const configuredBackend = process.env.DEEPLINE_PLAY_RUNNER_BACKEND?.trim();
3371
+ if (!configuredBackend) {
3372
+ return { environment, namespace };
3373
+ }
3374
+ if (configuredBackend !== "daytona" && configuredBackend !== "modal") {
3375
+ throw new DeeplineError(
3376
+ `DEEPLINE_PLAY_RUNNER_BACKEND must be daytona or modal for preview runtime selection. Received "${configuredBackend}".`,
3377
+ void 0,
3378
+ "INVALID_RUNTIME_BACKEND"
3379
+ );
3380
+ }
3381
+ return { environment, namespace, backend: configuredBackend };
3334
3382
  }
3335
3383
  function runtimeSelectionHeaders(runtime) {
3336
3384
  if (!runtime) return void 0;
@@ -11991,7 +12039,7 @@ async function traceCliSpan(phase, fields, run) {
11991
12039
 
11992
12040
  // src/cli/play-check-hints.ts
11993
12041
  var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists .get() only works for declared Deepline getters listed by `deepline tools describe <tool> --json`. Use `toolExecutionResult.toolResponse.raw` for provider/tool-specific scalar fields, and `toolExecutionResult.extractedLists.<name>.get()` for declared row/list outputs.";
11994
- var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Complete resident handles support read-only length/index/iteration. For paged rows use `.first()`, `.at(index)`, `.peek(n)`, `.materialize(limit)`, or async iteration; do not use `.rows` or `.toArray()`.";
12042
+ var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy, durable, and async-only. Use `.count()`, `.first()`, `.at(index)`, `.peek(n)`, `.materialize(limit)`, or async iteration; do not use `.length`, numeric indexing, spread, synchronous iteration, `.rows`, or `.toArray()`.";
11995
12043
  var ROW_PROPERTY_HINT = "Deepline hint: this row type only contains fields produced by the CSV/schema and previous map steps. Check source column casing and the exact output field names from earlier steps before scaling.";
11996
12044
  var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for logs, metadata, and receipt attachment; provider-call reuse is based on play, tool, semantic input, auth scope, provider action version, and cache policy.";
11997
12045
  var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or dataset-backed batch plays must be run directly, exported, then consumed by a separate play.";
@@ -12009,7 +12057,7 @@ function looksLikeInvalidExtractedGetter(error, sourceLine) {
12009
12057
  function looksLikeDatasetApiMisuse(error, sourceLine) {
12010
12058
  return /Property '(?:rows|toArray|forEach|map|filter|reduce)' does not exist on type '[^']*PlayDataset/.test(
12011
12059
  error
12012
- ) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
12060
+ ) || /PlayDataset/.test(error) && (/Property 'length' does not exist/.test(error) || /can't be used to index type/.test(error) || /\[Symbol\.iterator\]/.test(error) || /not iterable/.test(error)) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
12013
12061
  sourceLine
12014
12062
  );
12015
12063
  }
@@ -12064,27 +12112,6 @@ ${hint}`;
12064
12112
  });
12065
12113
  }
12066
12114
 
12067
- // ../shared_libs/play-runtime/backend.ts
12068
- var PLAY_RUNTIME_BACKENDS = {
12069
- localProcess: "local_process",
12070
- daytona: "daytona"
12071
- };
12072
- var PLAY_ARTIFACT_KINDS = {
12073
- cjsNode20: "cjs_node20"
12074
- };
12075
- var PLAY_BACKEND_DESCRIPTORS = {
12076
- [PLAY_RUNTIME_BACKENDS.localProcess]: {
12077
- id: PLAY_RUNTIME_BACKENDS.localProcess,
12078
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
12079
- label: "Local node subprocess"
12080
- },
12081
- [PLAY_RUNTIME_BACKENDS.daytona]: {
12082
- id: PLAY_RUNTIME_BACKENDS.daytona,
12083
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
12084
- label: "Daytona sandbox"
12085
- }
12086
- };
12087
-
12088
12115
  // ../shared_libs/play-runtime/dedup-backend.ts
12089
12116
  var PLAY_DEDUP_BACKENDS = {
12090
12117
  inMemory: "in_memory",
@@ -1022,7 +1022,10 @@ var SDK_RELEASE = {
1022
1022
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
1023
1023
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
1024
1024
  // Operators use the checkout-local deepline-admin binary instead.
1025
- version: "0.1.320",
1025
+ // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
1026
+ // exposed storage-dependent synchronous access. This deliberate minor
1027
+ // release keeps lazy paging semantics independent of row residency.
1028
+ version: "0.2.1",
1026
1029
  contracts: {
1027
1030
  api: {
1028
1031
  name: "sdk-http-api",
@@ -3229,6 +3232,33 @@ function usesExtendedTheirstackJobSearchBudget(endpointId, payload) {
3229
3232
  return maxAgeDays !== null && maxAgeDays >= 365 ? true : usesLongExplicitDateWindow(payload);
3230
3233
  }
3231
3234
 
3235
+ // ../shared_libs/play-runtime/backend.ts
3236
+ var PLAY_RUNTIME_BACKENDS = {
3237
+ localProcess: "local_process",
3238
+ daytona: "daytona",
3239
+ modal: "modal"
3240
+ };
3241
+ var PLAY_ARTIFACT_KINDS = {
3242
+ cjsNode20: "cjs_node20"
3243
+ };
3244
+ var PLAY_BACKEND_DESCRIPTORS = {
3245
+ [PLAY_RUNTIME_BACKENDS.localProcess]: {
3246
+ id: PLAY_RUNTIME_BACKENDS.localProcess,
3247
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
3248
+ label: "Local node subprocess"
3249
+ },
3250
+ [PLAY_RUNTIME_BACKENDS.daytona]: {
3251
+ id: PLAY_RUNTIME_BACKENDS.daytona,
3252
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
3253
+ label: "Daytona sandbox"
3254
+ },
3255
+ [PLAY_RUNTIME_BACKENDS.modal]: {
3256
+ id: PLAY_RUNTIME_BACKENDS.modal,
3257
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
3258
+ label: "Modal sandbox"
3259
+ }
3260
+ };
3261
+
3232
3262
  // ../shared_libs/play-runtime/runtime-environment.ts
3233
3263
  var PLAY_RUNTIME_ENVIRONMENTS = ["preview"];
3234
3264
  var PLAY_RUNTIME_NAMESPACE_PATTERN = /^[a-z][a-z0-9-]{0,30}$/;
@@ -3241,12 +3271,19 @@ function normalizePlayRuntimeSelection(value) {
3241
3271
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
3242
3272
  const record = value;
3243
3273
  if (Object.keys(record).some(
3244
- (key) => key !== "environment" && key !== "namespace"
3274
+ (key) => key !== "environment" && key !== "namespace" && key !== "backend"
3245
3275
  ) || record.environment !== "preview") {
3246
3276
  return null;
3247
3277
  }
3248
3278
  const namespace = normalizePlayRuntimeNamespace(record.namespace);
3249
- return namespace ? { environment: "preview", namespace } : null;
3279
+ if (!namespace) return null;
3280
+ if (record.backend === void 0) {
3281
+ return { environment: "preview", namespace };
3282
+ }
3283
+ if (record.backend !== PLAY_RUNTIME_BACKENDS.daytona && record.backend !== PLAY_RUNTIME_BACKENDS.modal) {
3284
+ return null;
3285
+ }
3286
+ return { environment: "preview", namespace, backend: record.backend };
3250
3287
  }
3251
3288
  function normalizePlayRuntimeEnvironment(value) {
3252
3289
  return typeof value === "string" && PLAY_RUNTIME_ENVIRONMENTS.includes(value) ? value : null;
@@ -3279,7 +3316,7 @@ function resolvePlayRunRuntimeSelection(request) {
3279
3316
  const runtime = normalizePlayRuntimeSelection(request.runtime);
3280
3317
  if (!runtime) {
3281
3318
  throw new DeeplineError(
3282
- 'runtime must be exactly { environment: "preview", namespace } with namespace matching ^[a-z][a-z0-9-]{0,30}$.',
3319
+ 'runtime must be { environment: "preview", namespace, backend?: "daytona" | "modal" } with namespace matching ^[a-z][a-z0-9-]{0,30}$.',
3283
3320
  void 0,
3284
3321
  "INVALID_RUNTIME_SELECTION"
3285
3322
  );
@@ -3315,7 +3352,18 @@ function resolvePlayRunRuntimeSelection(request) {
3315
3352
  "INVALID_RUNTIME_NAMESPACE"
3316
3353
  );
3317
3354
  }
3318
- return { environment, namespace };
3355
+ const configuredBackend = process.env.DEEPLINE_PLAY_RUNNER_BACKEND?.trim();
3356
+ if (!configuredBackend) {
3357
+ return { environment, namespace };
3358
+ }
3359
+ if (configuredBackend !== "daytona" && configuredBackend !== "modal") {
3360
+ throw new DeeplineError(
3361
+ `DEEPLINE_PLAY_RUNNER_BACKEND must be daytona or modal for preview runtime selection. Received "${configuredBackend}".`,
3362
+ void 0,
3363
+ "INVALID_RUNTIME_BACKEND"
3364
+ );
3365
+ }
3366
+ return { environment, namespace, backend: configuredBackend };
3319
3367
  }
3320
3368
  function runtimeSelectionHeaders(runtime) {
3321
3369
  if (!runtime) return void 0;
@@ -12020,7 +12068,7 @@ async function traceCliSpan(phase, fields, run) {
12020
12068
 
12021
12069
  // src/cli/play-check-hints.ts
12022
12070
  var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists .get() only works for declared Deepline getters listed by `deepline tools describe <tool> --json`. Use `toolExecutionResult.toolResponse.raw` for provider/tool-specific scalar fields, and `toolExecutionResult.extractedLists.<name>.get()` for declared row/list outputs.";
12023
- var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Complete resident handles support read-only length/index/iteration. For paged rows use `.first()`, `.at(index)`, `.peek(n)`, `.materialize(limit)`, or async iteration; do not use `.rows` or `.toArray()`.";
12071
+ var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy, durable, and async-only. Use `.count()`, `.first()`, `.at(index)`, `.peek(n)`, `.materialize(limit)`, or async iteration; do not use `.length`, numeric indexing, spread, synchronous iteration, `.rows`, or `.toArray()`.";
12024
12072
  var ROW_PROPERTY_HINT = "Deepline hint: this row type only contains fields produced by the CSV/schema and previous map steps. Check source column casing and the exact output field names from earlier steps before scaling.";
12025
12073
  var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for logs, metadata, and receipt attachment; provider-call reuse is based on play, tool, semantic input, auth scope, provider action version, and cache policy.";
12026
12074
  var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or dataset-backed batch plays must be run directly, exported, then consumed by a separate play.";
@@ -12038,7 +12086,7 @@ function looksLikeInvalidExtractedGetter(error, sourceLine) {
12038
12086
  function looksLikeDatasetApiMisuse(error, sourceLine) {
12039
12087
  return /Property '(?:rows|toArray|forEach|map|filter|reduce)' does not exist on type '[^']*PlayDataset/.test(
12040
12088
  error
12041
- ) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
12089
+ ) || /PlayDataset/.test(error) && (/Property 'length' does not exist/.test(error) || /can't be used to index type/.test(error) || /\[Symbol\.iterator\]/.test(error) || /not iterable/.test(error)) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
12042
12090
  sourceLine
12043
12091
  );
12044
12092
  }
@@ -12093,27 +12141,6 @@ ${hint}`;
12093
12141
  });
12094
12142
  }
12095
12143
 
12096
- // ../shared_libs/play-runtime/backend.ts
12097
- var PLAY_RUNTIME_BACKENDS = {
12098
- localProcess: "local_process",
12099
- daytona: "daytona"
12100
- };
12101
- var PLAY_ARTIFACT_KINDS = {
12102
- cjsNode20: "cjs_node20"
12103
- };
12104
- var PLAY_BACKEND_DESCRIPTORS = {
12105
- [PLAY_RUNTIME_BACKENDS.localProcess]: {
12106
- id: PLAY_RUNTIME_BACKENDS.localProcess,
12107
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
12108
- label: "Local node subprocess"
12109
- },
12110
- [PLAY_RUNTIME_BACKENDS.daytona]: {
12111
- id: PLAY_RUNTIME_BACKENDS.daytona,
12112
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
12113
- label: "Daytona sandbox"
12114
- }
12115
- };
12116
-
12117
12144
  // ../shared_libs/play-runtime/dedup-backend.ts
12118
12145
  var PLAY_DEDUP_BACKENDS = {
12119
12146
  inMemory: "in_memory",
package/dist/index.d.mts CHANGED
@@ -1,10 +1,12 @@
1
- import { a as PlayCompilerManifest, D as DeeplineError, c as ToolExecutionError, d as ToolExecutionErrorOptions, T as ToolExecutionErrorSchemaVersion } from './tool-execution-error-YDz7UMl-.mjs';
2
- export { e as ProviderTransientError, f as ProviderTransientErrorCategory, g as ToolExecutionErrorCategory, h as ToolExecutionErrorOrigin, i as ToolExecutionFailureV1, j as ToolExecutionNetworkKind, k as ToolExecutionNetworkScope } from './tool-execution-error-YDz7UMl-.mjs';
1
+ import { c as PlayRuntimeBackendId, a as PlayCompilerManifest, D as DeeplineError, d as ToolExecutionError, e as ToolExecutionErrorOptions, T as ToolExecutionErrorSchemaVersion } from './tool-execution-error-4-rhemLQ.mjs';
2
+ export { f as ProviderTransientError, g as ProviderTransientErrorCategory, h as ToolExecutionErrorCategory, i as ToolExecutionErrorOrigin, j as ToolExecutionFailureV1, k as ToolExecutionNetworkKind, l as ToolExecutionNetworkScope } from './tool-execution-error-4-rhemLQ.mjs';
3
3
 
4
4
  type PlayRuntimeSelection = {
5
5
  environment: 'preview';
6
6
  /** Caller-named isolation scope inside a remote runtime environment. */
7
7
  namespace: string;
8
+ /** Explicit managed-sandbox executor. Omission preserves Daytona compatibility. */
9
+ backend?: Extract<PlayRuntimeBackendId, 'daytona' | 'modal'>;
8
10
  };
9
11
 
10
12
  /**
@@ -3605,17 +3607,14 @@ type PlayDatasetTransformOptions = {
3605
3607
  * runtime control. Use `count()` and `peek()` for bounded inspection. Use
3606
3608
  * `materialize(limit)` or async iteration only when the dataset is intentionally
3607
3609
  * small and bounded. `PlayDataset` intentionally does not expose `.rows`,
3608
- * `.toArray()`, or other array aliases; those hide the runtime cost of loading
3609
- * persisted rows into memory.
3610
+ * `.toArray()`, `.length`, numeric indexing, spread, or synchronous iteration;
3611
+ * those hide the runtime cost of loading persisted rows into memory or make
3612
+ * behavior depend on whether rows happen to be resident.
3610
3613
  *
3611
3614
  * @sdkReference runtime 190
3612
3615
  */
3613
- interface PlayDataset<T> extends AsyncIterable<T>, Iterable<T> {
3616
+ interface PlayDataset<T> extends AsyncIterable<T> {
3614
3617
  readonly [PLAY_DATASET_BRAND]: true;
3615
- /** Authoritative row count when known without I/O. */
3616
- readonly length: number;
3617
- /** Resident row access. Throws when the requested row requires I/O. */
3618
- readonly [index: number]: T;
3619
3618
  /** Dataset kind. */
3620
3619
  readonly datasetKind: PlayDatasetKind;
3621
3620
  /** Dataset id. */
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { a as PlayCompilerManifest, D as DeeplineError, c as ToolExecutionError, d as ToolExecutionErrorOptions, T as ToolExecutionErrorSchemaVersion } from './tool-execution-error-YDz7UMl-.js';
2
- export { e as ProviderTransientError, f as ProviderTransientErrorCategory, g as ToolExecutionErrorCategory, h as ToolExecutionErrorOrigin, i as ToolExecutionFailureV1, j as ToolExecutionNetworkKind, k as ToolExecutionNetworkScope } from './tool-execution-error-YDz7UMl-.js';
1
+ import { c as PlayRuntimeBackendId, a as PlayCompilerManifest, D as DeeplineError, d as ToolExecutionError, e as ToolExecutionErrorOptions, T as ToolExecutionErrorSchemaVersion } from './tool-execution-error-4-rhemLQ.js';
2
+ export { f as ProviderTransientError, g as ProviderTransientErrorCategory, h as ToolExecutionErrorCategory, i as ToolExecutionErrorOrigin, j as ToolExecutionFailureV1, k as ToolExecutionNetworkKind, l as ToolExecutionNetworkScope } from './tool-execution-error-4-rhemLQ.js';
3
3
 
4
4
  type PlayRuntimeSelection = {
5
5
  environment: 'preview';
6
6
  /** Caller-named isolation scope inside a remote runtime environment. */
7
7
  namespace: string;
8
+ /** Explicit managed-sandbox executor. Omission preserves Daytona compatibility. */
9
+ backend?: Extract<PlayRuntimeBackendId, 'daytona' | 'modal'>;
8
10
  };
9
11
 
10
12
  /**
@@ -3605,17 +3607,14 @@ type PlayDatasetTransformOptions = {
3605
3607
  * runtime control. Use `count()` and `peek()` for bounded inspection. Use
3606
3608
  * `materialize(limit)` or async iteration only when the dataset is intentionally
3607
3609
  * small and bounded. `PlayDataset` intentionally does not expose `.rows`,
3608
- * `.toArray()`, or other array aliases; those hide the runtime cost of loading
3609
- * persisted rows into memory.
3610
+ * `.toArray()`, `.length`, numeric indexing, spread, or synchronous iteration;
3611
+ * those hide the runtime cost of loading persisted rows into memory or make
3612
+ * behavior depend on whether rows happen to be resident.
3610
3613
  *
3611
3614
  * @sdkReference runtime 190
3612
3615
  */
3613
- interface PlayDataset<T> extends AsyncIterable<T>, Iterable<T> {
3616
+ interface PlayDataset<T> extends AsyncIterable<T> {
3614
3617
  readonly [PLAY_DATASET_BRAND]: true;
3615
- /** Authoritative row count when known without I/O. */
3616
- readonly length: number;
3617
- /** Resident row access. Throws when the requested row requires I/O. */
3618
- readonly [index: number]: T;
3619
3618
  /** Dataset kind. */
3620
3619
  readonly datasetKind: PlayDatasetKind;
3621
3620
  /** Dataset id. */