deepline 0.1.303 → 0.1.305
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.
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +123 -30
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +164 -0
- package/dist/cli/index.js +9 -9
- package/dist/cli/index.mjs +9 -9
- package/dist/index.js +2 -1
- package/dist/index.mjs +2 -1
- package/package.json +1 -1
|
@@ -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.
|
|
160
|
+
version: '0.1.305',
|
|
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(
|
|
@@ -1644,7 +1657,7 @@ export class PlayContextImpl {
|
|
|
1644
1657
|
tableNamespace: string | null,
|
|
1645
1658
|
update: Omit<PlayRowUpdate, 'key'>,
|
|
1646
1659
|
): void {
|
|
1647
|
-
assertNoSecretTaint(update, 'ctx.
|
|
1660
|
+
assertNoSecretTaint(update, 'ctx.dataset row update');
|
|
1648
1661
|
const rowScope = rowContext.getStore()?.mapScope;
|
|
1649
1662
|
if (rowScope && key) {
|
|
1650
1663
|
this.emitExecutionEvent({
|
|
@@ -3088,18 +3101,15 @@ export class PlayContextImpl {
|
|
|
3088
3101
|
);
|
|
3089
3102
|
}
|
|
3090
3103
|
|
|
3091
|
-
// ---
|
|
3092
|
-
//
|
|
3093
|
-
//
|
|
3094
|
-
//
|
|
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
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
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
|
-
|
|
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)
|
|
6540
|
-
(
|
|
6541
|
-
|
|
6542
|
-
|
|
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)
|
|
6553
|
-
(
|
|
6554
|
-
|
|
6555
|
-
|
|
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
|
|
|
@@ -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.
|
|
1040
|
+
version: "0.1.305",
|
|
1041
1041
|
contracts: {
|
|
1042
1042
|
api: {
|
|
1043
1043
|
name: "sdk-http-api",
|
|
@@ -9750,14 +9750,14 @@ function formatDbQueryError(sql, error) {
|
|
|
9750
9750
|
if (referencesStorage && relationMissing) {
|
|
9751
9751
|
return [
|
|
9752
9752
|
"Customer DB query failed: the referenced storage table does not exist.",
|
|
9753
|
-
"Play
|
|
9753
|
+
"Play dataset tables are created only when the corresponding ctx.dataset(...).run(...) call executes. Pilot branches, early returns, and runs that fail before the dataset do not create that table.",
|
|
9754
9754
|
"Use `deepline runs get <run-id> --full --json` to inspect returned dataset handles, then export them with `deepline runs export <run-id> --dataset result.rows --out rows.csv`.",
|
|
9755
9755
|
`Original error: ${errorMessage(error)}`
|
|
9756
9756
|
].join("\n");
|
|
9757
9757
|
}
|
|
9758
9758
|
if (referencesStorage && runIdColumnMissing) {
|
|
9759
9759
|
return [
|
|
9760
|
-
"Customer DB query failed: storage
|
|
9760
|
+
"Customer DB query failed: storage dataset tables use `_run_id`, not `run_id`.",
|
|
9761
9761
|
"Prefer `deepline runs export <run-id> --dataset result.rows --out rows.csv` unless you are doing deep table debugging.",
|
|
9762
9762
|
`Original error: ${errorMessage(error)}`
|
|
9763
9763
|
].join("\n");
|
|
@@ -11211,7 +11211,7 @@ function assertComposablePlayRoute(input2) {
|
|
|
11211
11211
|
if (!input2.playRef || !playUsesMapBackedRuntime(input2.play)) return;
|
|
11212
11212
|
const runCommand2 = input2.play?.runCommand?.trim() || `deepline plays run ${input2.playRef} --input '{...}' --watch`;
|
|
11213
11213
|
throw new PlayBootstrapValidationError(
|
|
11214
|
-
`Cannot use ${input2.stageLabel} play:${input2.playRef} in plays bootstrap composition: the selected play is
|
|
11214
|
+
`Cannot use ${input2.stageLabel} play:${input2.playRef} in plays bootstrap composition: the selected play is dataset-backed/direct-run-only. Child plays that use ctx.dataset() own durable table state and must be run directly, exported, or validated as their own play instead of wrapped with ctx.runPlay. Run it directly first: ${runCommand2}`
|
|
11215
11215
|
);
|
|
11216
11216
|
}
|
|
11217
11217
|
function sourcePlayNeedsExportFirst(input2) {
|
|
@@ -11252,7 +11252,7 @@ function generatePlaySourceRowsBlock(input2) {
|
|
|
11252
11252
|
})) {
|
|
11253
11253
|
const sourcePlay = input2.sourcePlay;
|
|
11254
11254
|
const runCommand2 = sourcePlay?.runCommand?.trim() || `deepline plays run ${input2.source.value} --input '{...}' --watch`;
|
|
11255
|
-
return `// Source play ${input2.source.value} is
|
|
11255
|
+
return `// Source play ${input2.source.value} is dataset-backed/direct-run-only, so this generated play is stage 2.
|
|
11256
11256
|
// Stage 1:
|
|
11257
11257
|
// ${runCommand2}
|
|
11258
11258
|
// Stage 2:
|
|
@@ -11983,8 +11983,8 @@ var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists
|
|
|
11983
11983
|
var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Use `.peek(n)` for a small preview or `.materialize()` when you intentionally need rows in memory; do not use `.rows`, `.toArray()`, or array methods directly on the dataset handle.";
|
|
11984
11984
|
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.";
|
|
11985
11985
|
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.";
|
|
11986
|
-
var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or
|
|
11987
|
-
var MAP_BACKED_CHILD_HINT = "Deepline hint:
|
|
11986
|
+
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.";
|
|
11987
|
+
var MAP_BACKED_CHILD_HINT = "Deepline hint: dataset-backed child plays own durable table state and cannot be called from another play. Run that play directly, export its dataset, then pass the CSV to the next play.";
|
|
11988
11988
|
function sourceLineForError(sourceCode, error) {
|
|
11989
11989
|
const match = error.match(/:(\d+):(\d+)\s/);
|
|
11990
11990
|
const lineNumber = match?.[1] ? Number(match[1]) : NaN;
|
|
@@ -12014,7 +12014,7 @@ function looksLikeRunPlaySignature(error, sourceLine) {
|
|
|
12014
12014
|
return /ctx\.runPlay/i.test(error) || /(?:Expected|Argument of type|No overload matches)/.test(error) && /\brunPlay\(/.test(sourceLine);
|
|
12015
12015
|
}
|
|
12016
12016
|
function looksLikeMapBackedChild(error) {
|
|
12017
|
-
return /map-backed child play|direct-run-only|cannot call a map-backed|own durable table/i.test(
|
|
12017
|
+
return /(?:map|dataset)-backed child play|direct-run-only|cannot call a (?:map|dataset)-backed|own durable table/i.test(
|
|
12018
12018
|
error
|
|
12019
12019
|
);
|
|
12020
12020
|
}
|
|
@@ -13484,7 +13484,7 @@ function emitLiveDebugTableHints(input2) {
|
|
|
13484
13484
|
}
|
|
13485
13485
|
input2.state.emittedDebugKeys.add(tableKey);
|
|
13486
13486
|
input2.progress.writeLine(
|
|
13487
|
-
`Possible
|
|
13487
|
+
`Possible dataset table ${tableNamespace}: created only after this ctx.dataset(...).run(...) executes. Inspect returned datasets with ${buildRunInspectCommand(input2.runId)}`,
|
|
13488
13488
|
process.stdout
|
|
13489
13489
|
);
|
|
13490
13490
|
}
|
package/dist/cli/index.mjs
CHANGED
|
@@ -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.
|
|
1025
|
+
version: "0.1.305",
|
|
1026
1026
|
contracts: {
|
|
1027
1027
|
api: {
|
|
1028
1028
|
name: "sdk-http-api",
|
|
@@ -9755,14 +9755,14 @@ function formatDbQueryError(sql, error) {
|
|
|
9755
9755
|
if (referencesStorage && relationMissing) {
|
|
9756
9756
|
return [
|
|
9757
9757
|
"Customer DB query failed: the referenced storage table does not exist.",
|
|
9758
|
-
"Play
|
|
9758
|
+
"Play dataset tables are created only when the corresponding ctx.dataset(...).run(...) call executes. Pilot branches, early returns, and runs that fail before the dataset do not create that table.",
|
|
9759
9759
|
"Use `deepline runs get <run-id> --full --json` to inspect returned dataset handles, then export them with `deepline runs export <run-id> --dataset result.rows --out rows.csv`.",
|
|
9760
9760
|
`Original error: ${errorMessage(error)}`
|
|
9761
9761
|
].join("\n");
|
|
9762
9762
|
}
|
|
9763
9763
|
if (referencesStorage && runIdColumnMissing) {
|
|
9764
9764
|
return [
|
|
9765
|
-
"Customer DB query failed: storage
|
|
9765
|
+
"Customer DB query failed: storage dataset tables use `_run_id`, not `run_id`.",
|
|
9766
9766
|
"Prefer `deepline runs export <run-id> --dataset result.rows --out rows.csv` unless you are doing deep table debugging.",
|
|
9767
9767
|
`Original error: ${errorMessage(error)}`
|
|
9768
9768
|
].join("\n");
|
|
@@ -11240,7 +11240,7 @@ function assertComposablePlayRoute(input2) {
|
|
|
11240
11240
|
if (!input2.playRef || !playUsesMapBackedRuntime(input2.play)) return;
|
|
11241
11241
|
const runCommand2 = input2.play?.runCommand?.trim() || `deepline plays run ${input2.playRef} --input '{...}' --watch`;
|
|
11242
11242
|
throw new PlayBootstrapValidationError(
|
|
11243
|
-
`Cannot use ${input2.stageLabel} play:${input2.playRef} in plays bootstrap composition: the selected play is
|
|
11243
|
+
`Cannot use ${input2.stageLabel} play:${input2.playRef} in plays bootstrap composition: the selected play is dataset-backed/direct-run-only. Child plays that use ctx.dataset() own durable table state and must be run directly, exported, or validated as their own play instead of wrapped with ctx.runPlay. Run it directly first: ${runCommand2}`
|
|
11244
11244
|
);
|
|
11245
11245
|
}
|
|
11246
11246
|
function sourcePlayNeedsExportFirst(input2) {
|
|
@@ -11281,7 +11281,7 @@ function generatePlaySourceRowsBlock(input2) {
|
|
|
11281
11281
|
})) {
|
|
11282
11282
|
const sourcePlay = input2.sourcePlay;
|
|
11283
11283
|
const runCommand2 = sourcePlay?.runCommand?.trim() || `deepline plays run ${input2.source.value} --input '{...}' --watch`;
|
|
11284
|
-
return `// Source play ${input2.source.value} is
|
|
11284
|
+
return `// Source play ${input2.source.value} is dataset-backed/direct-run-only, so this generated play is stage 2.
|
|
11285
11285
|
// Stage 1:
|
|
11286
11286
|
// ${runCommand2}
|
|
11287
11287
|
// Stage 2:
|
|
@@ -12012,8 +12012,8 @@ var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists
|
|
|
12012
12012
|
var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Use `.peek(n)` for a small preview or `.materialize()` when you intentionally need rows in memory; do not use `.rows`, `.toArray()`, or array methods directly on the dataset handle.";
|
|
12013
12013
|
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.";
|
|
12014
12014
|
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.";
|
|
12015
|
-
var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or
|
|
12016
|
-
var MAP_BACKED_CHILD_HINT = "Deepline hint:
|
|
12015
|
+
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.";
|
|
12016
|
+
var MAP_BACKED_CHILD_HINT = "Deepline hint: dataset-backed child plays own durable table state and cannot be called from another play. Run that play directly, export its dataset, then pass the CSV to the next play.";
|
|
12017
12017
|
function sourceLineForError(sourceCode, error) {
|
|
12018
12018
|
const match = error.match(/:(\d+):(\d+)\s/);
|
|
12019
12019
|
const lineNumber = match?.[1] ? Number(match[1]) : NaN;
|
|
@@ -12043,7 +12043,7 @@ function looksLikeRunPlaySignature(error, sourceLine) {
|
|
|
12043
12043
|
return /ctx\.runPlay/i.test(error) || /(?:Expected|Argument of type|No overload matches)/.test(error) && /\brunPlay\(/.test(sourceLine);
|
|
12044
12044
|
}
|
|
12045
12045
|
function looksLikeMapBackedChild(error) {
|
|
12046
|
-
return /map-backed child play|direct-run-only|cannot call a map-backed|own durable table/i.test(
|
|
12046
|
+
return /(?:map|dataset)-backed child play|direct-run-only|cannot call a (?:map|dataset)-backed|own durable table/i.test(
|
|
12047
12047
|
error
|
|
12048
12048
|
);
|
|
12049
12049
|
}
|
|
@@ -13513,7 +13513,7 @@ function emitLiveDebugTableHints(input2) {
|
|
|
13513
13513
|
}
|
|
13514
13514
|
input2.state.emittedDebugKeys.add(tableKey);
|
|
13515
13515
|
input2.progress.writeLine(
|
|
13516
|
-
`Possible
|
|
13516
|
+
`Possible dataset table ${tableNamespace}: created only after this ctx.dataset(...).run(...) executes. Inspect returned datasets with ${buildRunInspectCommand(input2.runId)}`,
|
|
13517
13517
|
process.stdout
|
|
13518
13518
|
);
|
|
13519
13519
|
}
|
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.
|
|
763
|
+
version: "0.1.305",
|
|
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.
|
|
689
|
+
version: "0.1.305",
|
|
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;
|