deepline 0.1.304 → 0.1.306

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.
@@ -157,7 +157,7 @@ export const SDK_RELEASE = {
157
157
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
158
158
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
159
159
  // Operators use the checkout-local deepline-admin binary instead.
160
- version: '0.1.304',
160
+ version: '0.1.306',
161
161
  contracts: {
162
162
  api: {
163
163
  name: 'sdk-http-api',
@@ -15,10 +15,15 @@
15
15
  import { AsyncLocalStorage } from 'async_hooks';
16
16
  import {
17
17
  createDeferredPlayDataset,
18
+ deserializeLegacyPlayDataset,
19
+ deserializePlayDatasetCell,
18
20
  isPlayDataset,
21
+ isSerializedPlayDataset,
22
+ isSerializedPlayDatasetCell,
19
23
  iteratePlayDatasetInputPages,
20
24
  materializePlayDatasetInput,
21
25
  resolveMaterializeLimitCap,
26
+ serializePlayDatasetCell,
22
27
  } from '@shared_libs/plays/dataset';
23
28
  import type { PlayDataset, PlayDatasetInput } from '@shared_libs/plays/dataset';
24
29
  import {
@@ -733,6 +738,14 @@ function runtimeSheetPatchFieldName(fieldName: string): string {
733
738
  return fieldName.includes('.') ? sqlSafePlayColumnName(fieldName) : fieldName;
734
739
  }
735
740
 
741
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
742
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
743
+ return false;
744
+ }
745
+ const prototype = Object.getPrototypeOf(value);
746
+ return prototype === Object.prototype || prototype === null;
747
+ }
748
+
736
749
  type PersistableMapRow = MapRowOutcome;
737
750
 
738
751
  function comparePersistableMapRowsByInputIndex(
@@ -3088,18 +3101,15 @@ export class PlayContextImpl {
3088
3101
  );
3089
3102
  }
3090
3103
 
3091
- // --- Tool-result cells survive the dataset persist/resume boundary ---
3092
- // A ToolExecuteResult carries live getter methods that cannot be serialized
3093
- // to durable storage. We store its serialized form on write and rehydrate it
3094
- // when a cell value is handed back to play code (later column resolvers,
3095
- // staleAfterSeconds, previousCell), so `row.<col>.extractedValues.x.get()`
3096
- // works the same on a fresh pass and on a cached/resumed re-run. Both guards
3097
- // are no-ops for any value that is not a tool result.
3104
+ // --- Runtime values survive the dataset persist/resume boundary ---
3105
+ // Tool results and PlayDatasets carry live methods. Cells store JSON, so
3106
+ // encode them before persistence and revive them before authored play code
3107
+ // receives a row again.
3098
3108
 
3099
- private serializeCellValue(value: unknown): unknown {
3109
+ private async serializeCellValue(value: unknown): Promise<unknown> {
3100
3110
  const serialized = isToolExecuteResult(value)
3101
3111
  ? serializeToolExecuteResult(value)
3102
- : value;
3112
+ : await this.serializeDatasetCells(value);
3103
3113
  try {
3104
3114
  stringifyPostgresJson(serialized);
3105
3115
  } catch (error) {
@@ -3112,10 +3122,86 @@ export class PlayContextImpl {
3112
3122
  return serialized;
3113
3123
  }
3114
3124
 
3125
+ private async serializeDatasetCells(value: unknown): Promise<unknown> {
3126
+ // Keep cycles intact for stringifyPostgresJson to reject. This pass only
3127
+ // encodes runtime values; it must not turn an invalid cyclic cell into a
3128
+ // different graph or recurse forever before the JSON boundary can report it.
3129
+ const visiting = new WeakSet<object>();
3130
+ const visit = async (current: unknown): Promise<unknown> => {
3131
+ if (isToolExecuteResult(current)) {
3132
+ return serializeToolExecuteResult(current);
3133
+ }
3134
+ if (isPlayDataset(current)) {
3135
+ return await serializePlayDatasetCell(current, visit);
3136
+ }
3137
+ if (!current || typeof current !== 'object') return current;
3138
+ if (visiting.has(current)) return current;
3139
+ visiting.add(current);
3140
+ try {
3141
+ if (Array.isArray(current)) {
3142
+ let copy: unknown[] | null = null;
3143
+ for (const [index, entry] of current.entries()) {
3144
+ const serialized = await visit(entry);
3145
+ if (serialized !== entry) {
3146
+ copy ??= [...current];
3147
+ copy[index] = serialized;
3148
+ }
3149
+ }
3150
+ return copy ?? current;
3151
+ }
3152
+ if (!isPlainRecord(current)) return current;
3153
+ let copy: Record<string, unknown> | null = null;
3154
+ for (const [key, entry] of Object.entries(current)) {
3155
+ const serialized = await visit(entry);
3156
+ if (serialized !== entry) {
3157
+ copy ??= { ...current };
3158
+ copy[key] = serialized;
3159
+ }
3160
+ }
3161
+ return copy ?? current;
3162
+ } finally {
3163
+ visiting.delete(current);
3164
+ }
3165
+ };
3166
+ return await visit(value);
3167
+ }
3168
+
3115
3169
  private rehydrateCellValue(value: unknown): unknown {
3116
- return isSerializedToolExecuteResult(value)
3117
- ? deserializeToolExecuteResult(value)
3118
- : value;
3170
+ const seen = new WeakMap<object, unknown>();
3171
+ const visit = (current: unknown): unknown => {
3172
+ if (isToolExecuteResult(current)) {
3173
+ return current;
3174
+ }
3175
+ if (isSerializedToolExecuteResult(current)) {
3176
+ return deserializeToolExecuteResult(current);
3177
+ }
3178
+ if (isSerializedPlayDatasetCell(current)) {
3179
+ return deserializePlayDatasetCell(current, visit);
3180
+ }
3181
+ if (
3182
+ isSerializedPlayDataset(current) &&
3183
+ current.datasetId.startsWith('tool-list:')
3184
+ ) {
3185
+ return deserializeLegacyPlayDataset(current);
3186
+ }
3187
+ if (!current || typeof current !== 'object') return current;
3188
+ const existing = seen.get(current);
3189
+ if (existing !== undefined) return existing;
3190
+ if (Array.isArray(current)) {
3191
+ const copy: unknown[] = [];
3192
+ seen.set(current, copy);
3193
+ for (const entry of current) copy.push(visit(entry));
3194
+ return copy;
3195
+ }
3196
+ if (!isPlainRecord(current)) return current;
3197
+ const copy: Record<string, unknown> = {};
3198
+ seen.set(current, copy);
3199
+ for (const [key, entry] of Object.entries(current)) {
3200
+ copy[key] = visit(entry);
3201
+ }
3202
+ return copy;
3203
+ };
3204
+ return visit(value);
3119
3205
  }
3120
3206
 
3121
3207
  /**
@@ -3128,10 +3214,7 @@ export class PlayContextImpl {
3128
3214
  row: Record<string, unknown>,
3129
3215
  ): Record<string, unknown> {
3130
3216
  for (const key of Object.keys(row)) {
3131
- const value = row[key];
3132
- if (isSerializedToolExecuteResult(value)) {
3133
- row[key] = deserializeToolExecuteResult(value);
3134
- }
3217
+ row[key] = this.rehydrateCellValue(row[key]);
3135
3218
  }
3136
3219
  return row;
3137
3220
  }
@@ -5536,7 +5619,7 @@ export class PlayContextImpl {
5536
5619
  this.previousCellForField(baseRow, fieldName),
5537
5620
  ),
5538
5621
  );
5539
- cellValue = this.serializeCellValue(value);
5622
+ cellValue = await this.serializeCellValue(value);
5540
5623
  } catch (error) {
5541
5624
  if (
5542
5625
  isPlayRowExecutionSuspendedError(error) ||
@@ -6010,7 +6093,7 @@ export class PlayContextImpl {
6010
6093
  const fieldName = stepPath.join('.');
6011
6094
  const patchFieldName = runtimeSheetPatchFieldName(fieldName);
6012
6095
  if (rowStore && shouldPersistMapCellField(patchFieldName)) {
6013
- const cellValue = this.serializeCellValue(value);
6096
+ const cellValue = await this.serializeCellValue(value);
6014
6097
  this.emitScopedFieldMetaUpdate({
6015
6098
  rowId: rowStore.rowId,
6016
6099
  key: rowStore.rowKey ?? null,
@@ -6158,7 +6241,7 @@ export class PlayContextImpl {
6158
6241
  index,
6159
6242
  this.previousCellForField(baseRow, fieldName),
6160
6243
  );
6161
- computedFields[fieldName] = this.serializeCellValue(value);
6244
+ computedFields[fieldName] = await this.serializeCellValue(value);
6162
6245
  if (shouldPersistMapCellField(fieldName)) {
6163
6246
  rowDataPatch[fieldName] = computedFields[fieldName];
6164
6247
  }
@@ -6536,11 +6619,16 @@ export class PlayContextImpl {
6536
6619
  ): Record<string, unknown> {
6537
6620
  const stripped = stripCsvProjectedFields(row);
6538
6621
  return Object.fromEntries(
6539
- Object.entries(stripped).filter(
6540
- ([fieldName]) =>
6541
- shouldPersistMapCellField(fieldName) &&
6542
- !fieldName.startsWith('__deepline'),
6543
- ),
6622
+ Object.entries(stripped)
6623
+ .filter(
6624
+ ([fieldName]) =>
6625
+ shouldPersistMapCellField(fieldName) &&
6626
+ !fieldName.startsWith('__deepline'),
6627
+ )
6628
+ .map(([fieldName, value]) => [
6629
+ fieldName,
6630
+ this.rehydrateCellValue(value),
6631
+ ]),
6544
6632
  );
6545
6633
  }
6546
6634
 
@@ -6549,11 +6637,16 @@ export class PlayContextImpl {
6549
6637
  ): Record<string, unknown> {
6550
6638
  const stripped = stripCsvProjectedFields(row);
6551
6639
  return Object.fromEntries(
6552
- Object.entries(stripped).filter(
6553
- ([fieldName]) =>
6554
- shouldPersistMapCellField(fieldName) &&
6555
- !fieldName.startsWith('__deepline'),
6556
- ),
6640
+ Object.entries(stripped)
6641
+ .filter(
6642
+ ([fieldName]) =>
6643
+ shouldPersistMapCellField(fieldName) &&
6644
+ !fieldName.startsWith('__deepline'),
6645
+ )
6646
+ .map(([fieldName, value]) => [
6647
+ fieldName,
6648
+ this.rehydrateCellValue(value),
6649
+ ]),
6557
6650
  );
6558
6651
  }
6559
6652
 
@@ -69,6 +69,12 @@ function isInFlightRuntimeReceipt(
69
69
  export function runtimeReceiptFailureKindForError(
70
70
  error: unknown,
71
71
  ): WorkReceiptFailureKind {
72
+ // A failed ownership check means the runner cannot prove whether the
73
+ // invocation gateway or a newer attempt owns/completed the side effect. It
74
+ // must never stamp that receipt terminal: a later fenced Play Run attempt
75
+ // first reconciles the invocation receipt, then replays or reclaims safely.
76
+ if (error instanceof RuntimeReceiptLeaseLostError) return 'repairable';
77
+
72
78
  const toolFailureKind = getToolHttpErrorReceiptFailureKind(error);
73
79
  if (toolFailureKind) return toolFailureKind;
74
80
 
@@ -832,6 +838,13 @@ export async function executeWithDurableRuntimeReceipt<T>(input: {
832
838
  if (input.shouldPersistFailure?.(error) === false) {
833
839
  throw error;
834
840
  }
841
+ // The ownership is uncertain, so neither `fail` nor `release` is safe.
842
+ // Let the attempt-level cleanup and the receipt lease fence reconcile this
843
+ // on the next Play Run attempt. In particular, never replace a possibly
844
+ // completed invocation with a terminal error from the old owner.
845
+ if (error instanceof RuntimeReceiptLeaseLostError) {
846
+ throw error;
847
+ }
835
848
  if (
836
849
  isPlayExecutionSuspendedError(error) ||
837
850
  isPlayRowExecutionSuspendedError(error)
@@ -100,7 +100,24 @@ export type PlayRunnerBudgetChargeResult = {
100
100
  export interface PlayRunnerContextConfig {
101
101
  executorToken?: string;
102
102
  baseUrl?: string;
103
+ /**
104
+ * Runtime API origin reachable from a customer-code sandbox. Production sends
105
+ * execution traffic directly to the app; preview may use the combined gateway
106
+ * because the preview app requires a protection-bypass credential.
107
+ */
108
+ executionGatewayBaseUrl?: string | null;
103
109
  receiptGatewayBaseUrl?: string | null;
110
+ /**
111
+ * Request execution through the relay's durable invocation fence. This is
112
+ * required when the execution relay and receipt gateway have different
113
+ * origins, where the legacy same-origin inference cannot apply.
114
+ */
115
+ requestDurableInvocationFence?: boolean;
116
+ /**
117
+ * Preserves the explicit fence capability for callers that validate an
118
+ * ambiguous dispatched provider request before allowing a retry.
119
+ */
120
+ durableInvocationFence?: boolean;
104
121
  runtimeTestFaultHeader?: string | null;
105
122
  vercelProtectionBypassToken?: string | null;
106
123
  integrationMode?: 'live' | 'eval_stub' | 'fixture';
@@ -1,4 +1,5 @@
1
1
  import { isHardBillingToolHttpError, ToolHttpError } from './tool-http-errors';
2
+ import { RuntimeReceiptLeaseLostError } from './durable-receipt-execution';
2
3
  import { isRuntimePersistenceCircuitOpenError } from './persistence-latch';
3
4
  import { isWorkspaceStorageNotReadyFailure } from './run-failure';
4
5
 
@@ -33,6 +34,10 @@ export function isAbortLikeError(error: unknown): boolean {
33
34
  */
34
35
  export function isRowIsolationExemptError(error: unknown): boolean {
35
36
  if (isAbortLikeError(error)) return true;
37
+ // Receipt ownership loss is a control-plane uncertainty, not a provider row
38
+ // result. Propagate it to the one fenced Play Run task so its normal retry
39
+ // path can reconcile/replay the durable invocation before any redelivery.
40
+ if (error instanceof RuntimeReceiptLeaseLostError) return true;
36
41
  // A remote tool can return arbitrary provider/database wording. Its message
37
42
  // must never be mistaken for a failure of the runner's own receipt or sheet
38
43
  // persistence plane. Hard Deepline billing denials are the sole typed tool
@@ -362,10 +362,22 @@ function remoteRuntimeContextForDaytona(
362
362
  'Daytona execution requires DEEPLINE_RUNTIME_RECEIPT_GATEWAY_URL. Refusing to put app credentials or database sessions in the customer-code sandbox.',
363
363
  );
364
364
  }
365
+ const executionGatewayBaseUrl =
366
+ context.executionGatewayBaseUrl?.trim() || gatewayBaseUrl;
365
367
  return {
366
368
  ...context,
367
- baseUrl: gatewayBaseUrl,
369
+ // Receipt ownership and runner terminal publication must stay on the Fly
370
+ // receipt gateway. Production execution calls go to the separate relay,
371
+ // keeping a blue/green receipt-gateway deploy out of long provider calls.
372
+ // Protected preview apps intentionally fall back to the combined gateway.
373
+ baseUrl: executionGatewayBaseUrl,
374
+ executionGatewayBaseUrl,
368
375
  receiptGatewayBaseUrl: gatewayBaseUrl,
376
+ // The execution relay owns the Postgres-backed invocation fence even though
377
+ // receipt control traffic has a different origin. This must stay explicit:
378
+ // origin equality was only a legacy shortcut for the combined gateway.
379
+ requestDurableInvocationFence: true,
380
+ durableInvocationFence: true,
369
381
  vercelProtectionBypassToken: null,
370
382
  dbSessionStrategy: 'gateway_only',
371
383
  preloadedDbSessions: undefined,
@@ -51,6 +51,25 @@ export interface SerializedPlayDataset<T> {
51
51
  preview: T[];
52
52
  }
53
53
 
54
+ /**
55
+ * Durable cell representation for a PlayDataset returned from a map column.
56
+ *
57
+ * `PlayDataset.toJSON()` intentionally exposes only a bounded preview for
58
+ * normal output rendering. A runtime-sheet cell needs the complete rows so it
59
+ * can revive a live handle after a persistence or resume boundary.
60
+ */
61
+ export interface SerializedPlayDatasetCell<T> {
62
+ __kind: 'deepline.play_dataset_cell.v1';
63
+ dataset: SerializedPlayDataset<T>;
64
+ rows: T[];
65
+ }
66
+
67
+ const PLAY_DATASET_CELL_KIND = 'deepline.play_dataset_cell.v1';
68
+ const PLAY_DATASET_CELL_MAX_BYTES = 5 * 1024 * 1024;
69
+ const DATASET_CELL_REHYDRATION_INCOMPLETE =
70
+ 'DATASET_CELL_REHYDRATION_INCOMPLETE';
71
+ const DATASET_CELL_CORRUPT = 'DATASET_CELL_CORRUPT';
72
+
54
73
  export type PlayDatasetInput<T> =
55
74
  | ReadonlyArray<T>
56
75
  | Iterable<T>
@@ -219,6 +238,151 @@ export function isSerializedPlayDataset<T>(
219
238
  );
220
239
  }
221
240
 
241
+ export function isSerializedPlayDatasetCell<T>(
242
+ value: unknown,
243
+ ): value is SerializedPlayDatasetCell<T> {
244
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
245
+ return false;
246
+ }
247
+ const record = value as Record<string, unknown>;
248
+ return (
249
+ record.__kind === PLAY_DATASET_CELL_KIND &&
250
+ isSerializedPlayDataset<T>(record.dataset) &&
251
+ Array.isArray(record.rows)
252
+ );
253
+ }
254
+
255
+ /** Serialize every row because a Dataset cell must survive a new worker. */
256
+ export async function serializePlayDatasetCell<T>(
257
+ dataset: PlayDataset<T>,
258
+ serializeRow: (row: T) => Promise<T> = async (row) => row,
259
+ ): Promise<SerializedPlayDatasetCell<T>> {
260
+ const source = dataset.toJSON();
261
+ const datasetMetadata = {
262
+ ...source,
263
+ count: 0,
264
+ preview: [] as T[],
265
+ };
266
+ // The persisted envelope does not repeat the preview rows. That keeps the
267
+ // byte budget honest; deserialize derives its preview from `rows`.
268
+ let encodedBytes = new TextEncoder().encode(
269
+ JSON.stringify({
270
+ __kind: PLAY_DATASET_CELL_KIND,
271
+ dataset: datasetMetadata,
272
+ rows: [],
273
+ }),
274
+ ).length;
275
+ const rows: T[] = [];
276
+ for await (const row of dataset) {
277
+ const serializedRow = await serializeRow(row);
278
+ // Array serialization gives the exact JSON representation even for an
279
+ // undefined row, which JSON encodes as null inside `rows`.
280
+ const rowJson = JSON.stringify([serializedRow]).slice(1, -1);
281
+ encodedBytes +=
282
+ new TextEncoder().encode(rowJson).length + (rows.length > 0 ? 1 : 0);
283
+ if (encodedBytes > PLAY_DATASET_CELL_MAX_BYTES) {
284
+ throw new Error(
285
+ `OUTPUT_TOO_LARGE: Dataset cell ${dataset.datasetId} exceeds the 5 MiB customer-output limit. ` +
286
+ 'Keep large datasets as a top-level pipeline or return a bounded dataset from the column.',
287
+ );
288
+ }
289
+ rows.push(serializedRow);
290
+ }
291
+ return {
292
+ __kind: PLAY_DATASET_CELL_KIND,
293
+ dataset: {
294
+ ...source,
295
+ count: rows.length,
296
+ preview: [],
297
+ },
298
+ rows,
299
+ };
300
+ }
301
+
302
+ /** Restore the public lazy-handle contract from a persisted Dataset cell. */
303
+ export function deserializePlayDatasetCell<T>(
304
+ value: SerializedPlayDatasetCell<T>,
305
+ deserializeRow: (row: T) => T = (row) => row,
306
+ ): PlayDataset<T> {
307
+ const { dataset } = value;
308
+ const rows = value.rows.map(deserializeRow);
309
+ if (dataset.count !== rows.length) {
310
+ throw new Error(
311
+ `${DATASET_CELL_CORRUPT}: Dataset cell ${dataset.datasetId} declares ${dataset.count} rows but stores ${rows.length}.`,
312
+ );
313
+ }
314
+ return createDeferredPlayDataset({
315
+ datasetKind: dataset.datasetKind,
316
+ datasetId: dataset.datasetId,
317
+ count: rows.length,
318
+ backing: dataset.backing,
319
+ previewRows: rows.slice(0, 10),
320
+ sourceLabel: dataset.sourceLabel ?? null,
321
+ tableNamespace: dataset.tableNamespace ?? null,
322
+ workProgress: dataset._metadata?.workProgress,
323
+ resolvers: {
324
+ count: async () => rows.length,
325
+ peek: async (limit) => rows.slice(0, Math.max(0, limit)),
326
+ materialize: async (limit) =>
327
+ limit === undefined ? [...rows] : rows.slice(0, Math.max(0, limit)),
328
+ iterate: () =>
329
+ ({
330
+ async *[Symbol.asyncIterator]() {
331
+ yield* rows;
332
+ },
333
+ }) as AsyncIterable<T>,
334
+ },
335
+ });
336
+ }
337
+
338
+ /**
339
+ * Compatibility reader for cells persisted before Dataset cells carried their
340
+ * full rows. Small legacy lists remain usable; incomplete previews fail with a
341
+ * clear migration error instead of masquerading as a live handle.
342
+ */
343
+ export function deserializeLegacyPlayDataset<T>(
344
+ dataset: SerializedPlayDataset<T>,
345
+ ): PlayDataset<T> {
346
+ const complete = dataset.count === dataset.preview.length;
347
+ const incomplete = (): Error =>
348
+ new Error(
349
+ `${DATASET_CELL_REHYDRATION_INCOMPLETE}: Dataset cell ${dataset.datasetId} only stored ${dataset.preview.length} preview row(s) for ${dataset.count} total row(s). Re-run the producing column to persist the complete Dataset Handle.`,
350
+ );
351
+ const rows = dataset.preview;
352
+ return createDeferredPlayDataset({
353
+ datasetKind: dataset.datasetKind,
354
+ datasetId: dataset.datasetId,
355
+ count: dataset.count,
356
+ backing: dataset.backing,
357
+ previewRows: rows,
358
+ sourceLabel: dataset.sourceLabel ?? null,
359
+ tableNamespace: dataset.tableNamespace ?? null,
360
+ workProgress: dataset._metadata?.workProgress,
361
+ resolvers: {
362
+ count: async () => dataset.count,
363
+ peek: async (limit) => {
364
+ if (limit > rows.length && !complete) throw incomplete();
365
+ return rows.slice(0, Math.max(0, limit));
366
+ },
367
+ materialize: async (limit) => {
368
+ if (!complete && (limit === undefined || limit > rows.length)) {
369
+ throw incomplete();
370
+ }
371
+ return limit === undefined
372
+ ? [...rows]
373
+ : rows.slice(0, Math.max(0, limit));
374
+ },
375
+ iterate: () =>
376
+ ({
377
+ async *[Symbol.asyncIterator]() {
378
+ if (!complete) throw incomplete();
379
+ yield* rows;
380
+ },
381
+ }) as AsyncIterable<T>,
382
+ },
383
+ });
384
+ }
385
+
222
386
  export function trimSerializedPlayDatasetPreview<T>(
223
387
  dataset: SerializedPlayDataset<T>,
224
388
  limit: number,
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.304",
1040
+ version: "0.1.306",
1041
1041
  contracts: {
1042
1042
  api: {
1043
1043
  name: "sdk-http-api",
@@ -1022,7 +1022,7 @@ 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.304",
1025
+ version: "0.1.306",
1026
1026
  contracts: {
1027
1027
  api: {
1028
1028
  name: "sdk-http-api",
package/dist/index.js CHANGED
@@ -760,7 +760,7 @@ var SDK_RELEASE = {
760
760
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
761
761
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
762
762
  // Operators use the checkout-local deepline-admin binary instead.
763
- version: "0.1.304",
763
+ version: "0.1.306",
764
764
  contracts: {
765
765
  api: {
766
766
  name: "sdk-http-api",
@@ -5780,6 +5780,7 @@ var PLAY_DATASET_BRAND = /* @__PURE__ */ Symbol.for("deepline.play.dataset");
5780
5780
  var NODE_INSPECT_CUSTOM = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
5781
5781
  var DEFAULT_MATERIALIZE_LIMIT = 1e4;
5782
5782
  var PLAY_DATASET_EXECUTION_PAGE_BYTES = 64 * 1024 * 1024;
5783
+ var PLAY_DATASET_CELL_MAX_BYTES = 5 * 1024 * 1024;
5783
5784
  function resolveMaterializeLimitCap() {
5784
5785
  const raw = process.env.DEEPLINE_PLAY_DATASET_MATERIALIZE_LIMIT;
5785
5786
  const parsed = raw ? Number(raw) : NaN;
package/dist/index.mjs CHANGED
@@ -686,7 +686,7 @@ var SDK_RELEASE = {
686
686
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
687
687
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
688
688
  // Operators use the checkout-local deepline-admin binary instead.
689
- version: "0.1.304",
689
+ version: "0.1.306",
690
690
  contracts: {
691
691
  api: {
692
692
  name: "sdk-http-api",
@@ -5706,6 +5706,7 @@ var PLAY_DATASET_BRAND = /* @__PURE__ */ Symbol.for("deepline.play.dataset");
5706
5706
  var NODE_INSPECT_CUSTOM = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
5707
5707
  var DEFAULT_MATERIALIZE_LIMIT = 1e4;
5708
5708
  var PLAY_DATASET_EXECUTION_PAGE_BYTES = 64 * 1024 * 1024;
5709
+ var PLAY_DATASET_CELL_MAX_BYTES = 5 * 1024 * 1024;
5709
5710
  function resolveMaterializeLimitCap() {
5710
5711
  const raw = process.env.DEEPLINE_PLAY_DATASET_MATERIALIZE_LIMIT;
5711
5712
  const parsed = raw ? Number(raw) : NaN;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.304",
3
+ "version": "0.1.306",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {