deepline 0.1.55 → 0.1.57
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/cli/index.js +461 -62
- package/dist/cli/index.mjs +461 -62
- package/dist/index.d.mts +220 -34
- package/dist/index.d.ts +220 -34
- package/dist/index.js +22 -4
- package/dist/index.mjs +22 -4
- package/dist/repo/apps/play-runner-workers/src/entry.ts +43 -95
- package/dist/repo/apps/play-runner-workers/src/runtime/dataset-handles.ts +35 -7
- package/dist/repo/apps/play-runner-workers/src/runtime/tool-http-errors.ts +198 -0
- package/dist/repo/sdk/src/client.ts +33 -2
- package/dist/repo/sdk/src/play.ts +167 -33
- package/dist/repo/sdk/src/release.ts +3 -3
- package/dist/repo/sdk/src/types.ts +21 -0
- package/dist/repo/shared_libs/play-runtime/csv-rename.ts +55 -3
- package/dist/repo/shared_libs/plays/dataset.ts +25 -1
- package/package.json +1 -1
|
@@ -161,10 +161,20 @@ export type {
|
|
|
161
161
|
ToolResultTargetAccessor as ToolExtractedValue,
|
|
162
162
|
} from '../../shared_libs/play-runtime/tool-result-types.js';
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Keyword-style request object for `ctx.tools.execute(...)`.
|
|
166
|
+
*
|
|
167
|
+
* The `tool` value comes from live tool discovery. The `id` is the stable
|
|
168
|
+
* logical call name inside this play and participates in replay/idempotency.
|
|
169
|
+
*/
|
|
164
170
|
export type ToolExecutionRequest = {
|
|
171
|
+
/** Stable logical id for this tool call within the play. */
|
|
165
172
|
id: string;
|
|
173
|
+
/** Current tool id from `deepline tools search` / `deepline tools describe`. */
|
|
166
174
|
tool: string;
|
|
175
|
+
/** JSON-serializable provider/tool input object. */
|
|
167
176
|
input: Record<string, unknown>;
|
|
177
|
+
/** Human-readable description for logs and run inspection. */
|
|
168
178
|
description?: string;
|
|
169
179
|
staleAfterSeconds?: number;
|
|
170
180
|
};
|
|
@@ -226,10 +236,32 @@ export type MapStepBuilder<
|
|
|
226
236
|
InputRow extends object,
|
|
227
237
|
OutputRow extends object,
|
|
228
238
|
> = {
|
|
239
|
+
/**
|
|
240
|
+
* Define one output column for every row in this map dataset.
|
|
241
|
+
*
|
|
242
|
+
* The `name` becomes a field on each output row. For example,
|
|
243
|
+
* `.step('contact', ...)` creates `row.contact` in later map stages; it does
|
|
244
|
+
* not spread returned object fields such as `contact.email` into `row.email`.
|
|
245
|
+
* Add a later column resolver when you want a top-level export field:
|
|
246
|
+
* `.step('email', row => row.contact?.email ?? null)`.
|
|
247
|
+
*
|
|
248
|
+
* @param name - Output column name.
|
|
249
|
+
* @param resolver - Computes the value for one row.
|
|
250
|
+
* @returns The same map builder with the new column type.
|
|
251
|
+
*/
|
|
229
252
|
step<Name extends string, Value>(
|
|
230
253
|
name: Name,
|
|
231
254
|
resolver: MapStepResolver<OutputRow, Value>,
|
|
232
255
|
): MapStepBuilder<InputRow, OutputRow & Record<Name, Value>>;
|
|
256
|
+
/**
|
|
257
|
+
* Execute the row-column program and return a durable dataset handle.
|
|
258
|
+
*
|
|
259
|
+
* The returned {@link PlayDataset} preserves one output row per input row,
|
|
260
|
+
* with original fields merged with the columns produced by `.step(...)`.
|
|
261
|
+
*
|
|
262
|
+
* @param options - Run options.
|
|
263
|
+
* @returns Output rows as a dataset handle.
|
|
264
|
+
*/
|
|
233
265
|
run(options?: {
|
|
234
266
|
description?: string;
|
|
235
267
|
staleAfterSeconds?: number;
|
|
@@ -270,10 +302,15 @@ export type ColumnMap<TRow extends object> = Partial<
|
|
|
270
302
|
Record<Extract<keyof TRow, string>, string | readonly string[]>
|
|
271
303
|
>;
|
|
272
304
|
|
|
305
|
+
/** Options for loading a staged CSV with `ctx.csv(...)`. */
|
|
273
306
|
export type CsvOptions = {
|
|
307
|
+
/** Human-readable description for runtime logs and inspection. */
|
|
274
308
|
description?: string;
|
|
309
|
+
/** Canonical field-to-header aliases, e.g. `{ domain: ['domain', 'Company Domain'] }`. */
|
|
275
310
|
columns?: CsvRenameMap;
|
|
311
|
+
/** Header rename map; use `columns` for new code. */
|
|
276
312
|
rename?: CsvRenameMap;
|
|
313
|
+
/** Canonical fields that must be present after header normalization. */
|
|
277
314
|
required?: readonly string[];
|
|
278
315
|
};
|
|
279
316
|
|
|
@@ -324,17 +361,22 @@ export type CsvOptions = {
|
|
|
324
361
|
*/
|
|
325
362
|
export interface DeeplinePlayRuntimeContext {
|
|
326
363
|
/**
|
|
327
|
-
* Load a CSV file as a dataset handle.
|
|
364
|
+
* Load a staged CSV file as a durable dataset handle.
|
|
328
365
|
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
366
|
+
* Use this when a play receives a CSV path from the CLI or API and row work
|
|
367
|
+
* should continue through {@link DeeplinePlayRuntimeContext.map}. The path is
|
|
368
|
+
* normally an input field such as `input.csv`, populated by
|
|
369
|
+
* `deepline plays run my.play.ts --csv rows.csv`.
|
|
370
|
+
*
|
|
371
|
+
* Each CSV row becomes an object keyed by canonical column names. Use
|
|
372
|
+
* `options.columns` / `options.rename` to map user headers such as
|
|
373
|
+
* `"Company Domain"` to stable code fields such as `domain`.
|
|
331
374
|
*
|
|
332
375
|
* @typeParam T - Row type (defaults to `Record<string, unknown>`)
|
|
333
|
-
* @param path -
|
|
334
|
-
*
|
|
335
|
-
* explicit `materialize()` for small result sets.
|
|
376
|
+
* @param path - Staged CSV path.
|
|
377
|
+
* @param options - CSV load options.
|
|
336
378
|
*
|
|
337
|
-
* @returns
|
|
379
|
+
* @returns A {@link PlayDataset} whose rows should usually flow directly into `ctx.map(...)`.
|
|
338
380
|
*/
|
|
339
381
|
csv<T = Record<string, unknown>>(
|
|
340
382
|
path: string,
|
|
@@ -342,27 +384,28 @@ export interface DeeplinePlayRuntimeContext {
|
|
|
342
384
|
): Promise<PlayDataset<T>>;
|
|
343
385
|
|
|
344
386
|
/**
|
|
345
|
-
*
|
|
387
|
+
* Create a persisted row dataset/table from input rows.
|
|
346
388
|
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
389
|
+
* `ctx.map` is Deepline's row-work primitive. It records row identity,
|
|
390
|
+
* progress, retries, table output, and idempotency for a collection of rows.
|
|
391
|
+
* Use `.step(name, resolver)` on the returned builder to define output
|
|
392
|
+
* columns, then `.run(...)` to execute the row program.
|
|
350
393
|
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
* automatically from
|
|
354
|
-
*
|
|
355
|
-
* relative time window. Use `86400` for daily reruns; retries inside the same
|
|
356
|
-
* window still replay safely.
|
|
394
|
+
* The `key` identifies the logical dataset/table. Renaming it is a persistence
|
|
395
|
+
* migration: existing rows may no longer be reused. Row identity is derived
|
|
396
|
+
* automatically from input row content unless `.run({ key: ... })` overrides
|
|
397
|
+
* it with stable business fields such as `domain`, `email`, or `linkedin_url`.
|
|
357
398
|
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
399
|
+
* By default, `ctx.map` is row-preserving: one input row produces one output
|
|
400
|
+
* row, with original fields merged with the columns produced by
|
|
401
|
+
* `.step(...)`. If one input entity must become many output rows, use the
|
|
402
|
+
* documented expand/flatten recipe instead of assuming `ctx.map` changes
|
|
403
|
+
* row cardinality.
|
|
361
404
|
*
|
|
362
405
|
* @typeParam T - Row type
|
|
363
|
-
* @param key -
|
|
364
|
-
* @param items - Input rows
|
|
365
|
-
* @returns
|
|
406
|
+
* @param key - Dataset/table name.
|
|
407
|
+
* @param items - Input rows.
|
|
408
|
+
* @returns A builder. Calling `.run()` returns a `PlayDataset` of rows plus computed columns.
|
|
366
409
|
*
|
|
367
410
|
* @example Single tool per row
|
|
368
411
|
* ```typescript
|
|
@@ -405,25 +448,78 @@ export interface DeeplinePlayRuntimeContext {
|
|
|
405
448
|
/**
|
|
406
449
|
* Execute a single tool with a keyword-style request object.
|
|
407
450
|
*
|
|
408
|
-
* @param request
|
|
409
|
-
* @
|
|
410
|
-
* @param request.input - Tool-specific input parameters
|
|
411
|
-
* @returns The tool's output
|
|
451
|
+
* @param request - Tool call request.
|
|
452
|
+
* @returns Tool execution result.
|
|
412
453
|
*/
|
|
413
454
|
execute<TOutput = LoosePlayObject>(
|
|
414
455
|
request: ToolExecutionRequest & { staleAfterSeconds?: number },
|
|
415
456
|
): Promise<ToolExecuteResult<TOutput>>;
|
|
416
457
|
};
|
|
458
|
+
/**
|
|
459
|
+
* Execute a single tool by stable step key and tool ID.
|
|
460
|
+
*
|
|
461
|
+
* Shorthand for `ctx.tools.execute(...)`; this is the preferred spelling in
|
|
462
|
+
* row-level step programs.
|
|
463
|
+
*/
|
|
464
|
+
tool<TOutput = LoosePlayObject>(
|
|
465
|
+
key: string,
|
|
466
|
+
toolId: string,
|
|
467
|
+
input: Record<string, unknown>,
|
|
468
|
+
options?: { description?: string },
|
|
469
|
+
): Promise<ToolExecuteResult<TOutput>>;
|
|
470
|
+
/**
|
|
471
|
+
* Run a reusable step program against one scalar input object.
|
|
472
|
+
*
|
|
473
|
+
* `steps().step(...)` is a composable mini-pipeline. Use `ctx.runSteps(...)`
|
|
474
|
+
* when that mini-pipeline should execute outside a row dataset. Inside a
|
|
475
|
+
* `ctx.map` column resolver, pass the step program directly to
|
|
476
|
+
* `.step(name, program)` instead.
|
|
477
|
+
*
|
|
478
|
+
* @param program - Step program.
|
|
479
|
+
* @param input - Program input.
|
|
480
|
+
* @param options - Run options.
|
|
481
|
+
* @returns Program output.
|
|
482
|
+
*/
|
|
417
483
|
runSteps<TInput extends Record<string, unknown>, TOutput>(
|
|
418
484
|
program: StepProgram<TInput, unknown, TOutput>,
|
|
419
485
|
input: TInput,
|
|
420
486
|
options?: { description?: string },
|
|
421
487
|
): Promise<TOutput>;
|
|
488
|
+
/**
|
|
489
|
+
* Create one scalar checkpoint for the whole play run.
|
|
490
|
+
*
|
|
491
|
+
* Use `ctx.step` when a value is nondeterministic, expensive, external, or
|
|
492
|
+
* useful to inspect as a named boundary. The first execution stores the
|
|
493
|
+
* JSON-serializable output under `id`; replay and retries return the stored
|
|
494
|
+
* value instead of running `run` again.
|
|
495
|
+
*
|
|
496
|
+
* Plain deterministic assignment does not need `ctx.step`. Use
|
|
497
|
+
* `ctx.map(...).step(...)`, not `ctx.step`, when the value should become a
|
|
498
|
+
* field on each exported row.
|
|
499
|
+
*
|
|
500
|
+
* @param id - Checkpoint id.
|
|
501
|
+
* @param run - Computes the value once.
|
|
502
|
+
* @param options - Checkpoint options.
|
|
503
|
+
* @returns Checkpoint value.
|
|
504
|
+
*/
|
|
422
505
|
step<T>(
|
|
423
506
|
id: string,
|
|
424
507
|
run: () => T | Promise<T>,
|
|
425
508
|
options?: { staleAfterSeconds?: number },
|
|
426
509
|
): Promise<T>;
|
|
510
|
+
/**
|
|
511
|
+
* Durable HTTP fetch.
|
|
512
|
+
*
|
|
513
|
+
* Use this for non-provider HTTP calls that must replay safely. The response
|
|
514
|
+
* is recorded under `key` so workflow replay sees the same value. Prefer
|
|
515
|
+
* `ctx.tools.execute(...)` for Deepline-managed provider APIs because tools
|
|
516
|
+
* handle auth, retries, rate limits, extraction metadata, and spend tracking.
|
|
517
|
+
*
|
|
518
|
+
* @param key - Checkpoint id.
|
|
519
|
+
* @param url - URL to fetch.
|
|
520
|
+
* @param init - Fetch options.
|
|
521
|
+
* @returns Recorded response.
|
|
522
|
+
*/
|
|
427
523
|
fetch(
|
|
428
524
|
key: string,
|
|
429
525
|
url: string | URL,
|
|
@@ -438,6 +534,22 @@ export interface DeeplinePlayRuntimeContext {
|
|
|
438
534
|
bodyText: string;
|
|
439
535
|
json: unknown | null;
|
|
440
536
|
}>;
|
|
537
|
+
/**
|
|
538
|
+
* Invoke another registered or file-backed play as a child workflow.
|
|
539
|
+
*
|
|
540
|
+
* Use this for real composition boundaries, especially when a fitting
|
|
541
|
+
* scalar prebuilt play already encodes provider order, fallbacks,
|
|
542
|
+
* normalization, and no-result behavior. Do not invoke plays through
|
|
543
|
+
* `ctx.tools.execute`; tools and plays are separate namespaces.
|
|
544
|
+
*
|
|
545
|
+
* `key` is the stable child-call identity for idempotency and traceability.
|
|
546
|
+
*
|
|
547
|
+
* @param key - Child call id.
|
|
548
|
+
* @param playRef - Play name or handle.
|
|
549
|
+
* @param input - Child input.
|
|
550
|
+
* @param options - Run options.
|
|
551
|
+
* @returns Child play output.
|
|
552
|
+
*/
|
|
441
553
|
runPlay(
|
|
442
554
|
key: string,
|
|
443
555
|
playRef: string | PlayReferenceLike,
|
|
@@ -646,11 +758,24 @@ export type PlayInputContract<TInput> = {
|
|
|
646
758
|
readonly __inputType?: TInput;
|
|
647
759
|
};
|
|
648
760
|
|
|
761
|
+
/**
|
|
762
|
+
* Object-form play definition accepted by `definePlay(config)`.
|
|
763
|
+
*
|
|
764
|
+
* Use this form when the input contract should be explicit at definition time
|
|
765
|
+
* through `defineInput<T>(schema)`, or when configuration reads clearer as one
|
|
766
|
+
* object. The shorthand `definePlay(name, fn, bindings?)` is equivalent for
|
|
767
|
+
* simple file-backed plays.
|
|
768
|
+
*/
|
|
649
769
|
export type DefinePlayConfig<TInput, TOutput extends PlayReturnObject> = {
|
|
770
|
+
/** Play id/name. */
|
|
650
771
|
id: string;
|
|
772
|
+
/** Input schema. */
|
|
651
773
|
input: PlayInputContract<TInput>;
|
|
774
|
+
/** Play function. */
|
|
652
775
|
run: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>;
|
|
776
|
+
/** Trigger bindings. */
|
|
653
777
|
bindings?: PlayBindings;
|
|
778
|
+
/** Billing options. */
|
|
654
779
|
billing?: PlayBindings['billing'];
|
|
655
780
|
};
|
|
656
781
|
|
|
@@ -1184,9 +1309,10 @@ export function defineInput<TInput>(
|
|
|
1184
1309
|
*
|
|
1185
1310
|
* @typeParam TInput - The input type accepted by the play
|
|
1186
1311
|
* @typeParam TOutput - The return type of the play
|
|
1187
|
-
* @param
|
|
1188
|
-
* @param
|
|
1189
|
-
* @param
|
|
1312
|
+
* @param config - Object-form play config.
|
|
1313
|
+
* @param name - Play name.
|
|
1314
|
+
* @param fn - Play function.
|
|
1315
|
+
* @param bindings - Trigger bindings.
|
|
1190
1316
|
* @returns A {@link DefinedPlay} that is both callable and has lifecycle methods
|
|
1191
1317
|
*
|
|
1192
1318
|
* @example Basic play
|
|
@@ -1207,9 +1333,9 @@ export function defineInput<TInput>(
|
|
|
1207
1333
|
*
|
|
1208
1334
|
* @example CSV processing play
|
|
1209
1335
|
* ```typescript
|
|
1210
|
-
* export default definePlay('bulk-enrich', async (ctx) => {
|
|
1211
|
-
* const leads = await ctx.csv(
|
|
1212
|
-
* ctx.log(`Processing ${leads.
|
|
1336
|
+
* export default definePlay('bulk-enrich', async (ctx, input: { csv: string }) => {
|
|
1337
|
+
* const leads = await ctx.csv(input.csv);
|
|
1338
|
+
* ctx.log(`Processing ${await leads.count()} rows`);
|
|
1213
1339
|
* const results = await ctx
|
|
1214
1340
|
* .map('companies', leads)
|
|
1215
1341
|
* .step('company', (row, ctx) =>
|
|
@@ -1256,6 +1382,14 @@ export function defineInput<TInput>(
|
|
|
1256
1382
|
export function definePlay<TInput, TOutput extends PlayReturnObject>(
|
|
1257
1383
|
config: DefinePlayConfig<TInput, TOutput>,
|
|
1258
1384
|
): DefinedPlay<TInput, TOutput>;
|
|
1385
|
+
/**
|
|
1386
|
+
* Define a play with a name and function.
|
|
1387
|
+
*
|
|
1388
|
+
* @param name - Play name.
|
|
1389
|
+
* @param fn - Play function.
|
|
1390
|
+
* @param bindings - Trigger bindings.
|
|
1391
|
+
* @returns Play handle.
|
|
1392
|
+
*/
|
|
1259
1393
|
export function definePlay<TInput, TOutput extends PlayReturnObject>(
|
|
1260
1394
|
name: string,
|
|
1261
1395
|
fn: (ctx: DeeplinePlayRuntimeContext, input: TInput) => Promise<TOutput>,
|
|
@@ -50,10 +50,10 @@ export type SdkRelease = {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
export const SDK_RELEASE = {
|
|
53
|
-
version: '0.1.
|
|
54
|
-
apiContract: '2026-05-
|
|
53
|
+
version: '0.1.57',
|
|
54
|
+
apiContract: '2026-05-play-tool-describe-starters',
|
|
55
55
|
supportPolicy: {
|
|
56
|
-
latest: '0.1.
|
|
56
|
+
latest: '0.1.57',
|
|
57
57
|
minimumSupported: '0.1.53',
|
|
58
58
|
deprecatedBelow: '0.1.53',
|
|
59
59
|
},
|
|
@@ -125,6 +125,22 @@ export interface ToolDefinition {
|
|
|
125
125
|
/** Copyable play-runtime guidance for V2 tool execution results. */
|
|
126
126
|
usageGuidance?: {
|
|
127
127
|
execute?: string;
|
|
128
|
+
prefer?: string[];
|
|
129
|
+
access?: {
|
|
130
|
+
extractedLists?: {
|
|
131
|
+
expression?: string;
|
|
132
|
+
meaning?: string;
|
|
133
|
+
};
|
|
134
|
+
extractedValues?: {
|
|
135
|
+
expression?: string;
|
|
136
|
+
meaning?: string;
|
|
137
|
+
};
|
|
138
|
+
rawToolResponse?: {
|
|
139
|
+
expression?: string;
|
|
140
|
+
meaning?: string;
|
|
141
|
+
};
|
|
142
|
+
invalidGetterHint?: string;
|
|
143
|
+
};
|
|
128
144
|
toolExecutionResult?: {
|
|
129
145
|
type?: 'ToolExecutionResult';
|
|
130
146
|
toolResponse?: {
|
|
@@ -637,6 +653,11 @@ export interface PlayDescription {
|
|
|
637
653
|
rowOutputSchema?: Record<string, unknown> | null;
|
|
638
654
|
runCommand: string;
|
|
639
655
|
examples: string[];
|
|
656
|
+
cloneEditStarter?: {
|
|
657
|
+
path: string;
|
|
658
|
+
command: string;
|
|
659
|
+
checkCommand: string;
|
|
660
|
+
};
|
|
640
661
|
currentPublishedVersion?: number | null;
|
|
641
662
|
isDraftDirty?: boolean;
|
|
642
663
|
latestRunId?: string | null;
|
|
@@ -8,10 +8,12 @@ export type CsvRenameOptions = {
|
|
|
8
8
|
|
|
9
9
|
const CSV_PROJECTED_FIELDS = Symbol.for('deepline.play.csv.projected_fields');
|
|
10
10
|
const CSV_PROJECTED_FIELDS_KEY = '__deeplineCsvProjectedFields';
|
|
11
|
+
const CSV_PROJECTED_VALUES_KEY = '__deeplineCsvProjectedValues';
|
|
11
12
|
|
|
12
13
|
type ProjectedRow = Record<string, unknown> & {
|
|
13
14
|
[CSV_PROJECTED_FIELDS]?: ReadonlySet<string>;
|
|
14
15
|
[CSV_PROJECTED_FIELDS_KEY]?: readonly string[];
|
|
16
|
+
[CSV_PROJECTED_VALUES_KEY]?: Record<string, unknown>;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
function normalizeCsvHeader(header: string): string {
|
|
@@ -58,6 +60,7 @@ export function applyCsvRenameProjection<T extends Record<string, unknown>>(
|
|
|
58
60
|
return rows.map((row, index) => {
|
|
59
61
|
const lookup = buildRowLookup(row);
|
|
60
62
|
const projectedFields = new Set<string>();
|
|
63
|
+
const projectedValues: Record<string, unknown> = {};
|
|
61
64
|
const projected: Record<string, unknown> = { ...row };
|
|
62
65
|
|
|
63
66
|
for (const [target, sourceNames] of Object.entries(aliases)) {
|
|
@@ -81,6 +84,7 @@ export function applyCsvRenameProjection<T extends Record<string, unknown>>(
|
|
|
81
84
|
writable: true,
|
|
82
85
|
});
|
|
83
86
|
projectedFields.add(target);
|
|
87
|
+
projectedValues[target] = selected;
|
|
84
88
|
} else {
|
|
85
89
|
projected[target] = selected;
|
|
86
90
|
}
|
|
@@ -96,6 +100,20 @@ export function applyCsvRenameProjection<T extends Record<string, unknown>>(
|
|
|
96
100
|
enumerable: false,
|
|
97
101
|
configurable: true,
|
|
98
102
|
});
|
|
103
|
+
if (projectedFields.size > 0) {
|
|
104
|
+
Object.defineProperty(projected, CSV_PROJECTED_FIELDS_KEY, {
|
|
105
|
+
value: [...projectedFields],
|
|
106
|
+
enumerable: true,
|
|
107
|
+
configurable: true,
|
|
108
|
+
writable: true,
|
|
109
|
+
});
|
|
110
|
+
Object.defineProperty(projected, CSV_PROJECTED_VALUES_KEY, {
|
|
111
|
+
value: projectedValues,
|
|
112
|
+
enumerable: true,
|
|
113
|
+
configurable: true,
|
|
114
|
+
writable: true,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
99
117
|
return projected as T & Record<string, unknown>;
|
|
100
118
|
});
|
|
101
119
|
}
|
|
@@ -111,6 +129,7 @@ export function cloneCsvAliasedRow<T extends Record<string, unknown>>(
|
|
|
111
129
|
}
|
|
112
130
|
|
|
113
131
|
const clonedProjectedFields = new Set<string>();
|
|
132
|
+
const serializedValues = getCsvProjectedValues(row);
|
|
114
133
|
for (const field of projectedFields) {
|
|
115
134
|
if (Object.prototype.hasOwnProperty.call(cloned, field)) {
|
|
116
135
|
continue;
|
|
@@ -124,7 +143,7 @@ export function cloneCsvAliasedRow<T extends Record<string, unknown>>(
|
|
|
124
143
|
});
|
|
125
144
|
} else {
|
|
126
145
|
Object.defineProperty(cloned, field, {
|
|
127
|
-
value: row[field],
|
|
146
|
+
value: serializedValues?.[field] ?? row[field],
|
|
128
147
|
enumerable: false,
|
|
129
148
|
configurable: true,
|
|
130
149
|
writable: true,
|
|
@@ -139,6 +158,20 @@ export function cloneCsvAliasedRow<T extends Record<string, unknown>>(
|
|
|
139
158
|
enumerable: false,
|
|
140
159
|
configurable: true,
|
|
141
160
|
});
|
|
161
|
+
Object.defineProperty(cloned, CSV_PROJECTED_FIELDS_KEY, {
|
|
162
|
+
value: [...clonedProjectedFields],
|
|
163
|
+
enumerable: true,
|
|
164
|
+
configurable: true,
|
|
165
|
+
writable: true,
|
|
166
|
+
});
|
|
167
|
+
Object.defineProperty(cloned, CSV_PROJECTED_VALUES_KEY, {
|
|
168
|
+
value: Object.fromEntries(
|
|
169
|
+
[...clonedProjectedFields].map((field) => [field, cloned[field]]),
|
|
170
|
+
),
|
|
171
|
+
enumerable: true,
|
|
172
|
+
configurable: true,
|
|
173
|
+
writable: true,
|
|
174
|
+
});
|
|
142
175
|
}
|
|
143
176
|
return cloned;
|
|
144
177
|
}
|
|
@@ -153,6 +186,7 @@ export function stripCsvProjectedFields<T extends Record<string, unknown>>(
|
|
|
153
186
|
delete stripped[field];
|
|
154
187
|
}
|
|
155
188
|
delete stripped[CSV_PROJECTED_FIELDS_KEY];
|
|
189
|
+
delete stripped[CSV_PROJECTED_VALUES_KEY];
|
|
156
190
|
return stripped as T;
|
|
157
191
|
}
|
|
158
192
|
|
|
@@ -168,13 +202,31 @@ export function getCsvProjectedFields(
|
|
|
168
202
|
return new Set(serializedFields.filter((field) => typeof field === 'string'));
|
|
169
203
|
}
|
|
170
204
|
|
|
205
|
+
function getCsvProjectedValues(
|
|
206
|
+
row: Record<string, unknown>,
|
|
207
|
+
): Record<string, unknown> | null {
|
|
208
|
+
const serializedValues = (row as ProjectedRow)[CSV_PROJECTED_VALUES_KEY];
|
|
209
|
+
if (
|
|
210
|
+
!serializedValues ||
|
|
211
|
+
typeof serializedValues !== 'object' ||
|
|
212
|
+
Array.isArray(serializedValues)
|
|
213
|
+
) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
return serializedValues;
|
|
217
|
+
}
|
|
218
|
+
|
|
171
219
|
export function stripCsvProjectionMetadata<T extends Record<string, unknown>>(
|
|
172
220
|
row: T,
|
|
173
221
|
): T {
|
|
174
|
-
if (
|
|
222
|
+
if (
|
|
223
|
+
!Object.prototype.hasOwnProperty.call(row, CSV_PROJECTED_FIELDS_KEY) &&
|
|
224
|
+
!Object.prototype.hasOwnProperty.call(row, CSV_PROJECTED_VALUES_KEY)
|
|
225
|
+
) {
|
|
175
226
|
return row;
|
|
176
227
|
}
|
|
177
|
-
const stripped =
|
|
228
|
+
const stripped = cloneCsvAliasedRow(row) as T;
|
|
178
229
|
delete stripped[CSV_PROJECTED_FIELDS_KEY];
|
|
230
|
+
delete stripped[CSV_PROJECTED_VALUES_KEY];
|
|
179
231
|
return stripped as T;
|
|
180
232
|
}
|
|
@@ -55,14 +55,34 @@ export type PlayDatasetInput<T> =
|
|
|
55
55
|
| AsyncIterable<T>
|
|
56
56
|
| PlayDataset<T>;
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Durable handle for rows produced by `ctx.csv(...)` or `ctx.map(...).run()`.
|
|
60
|
+
*
|
|
61
|
+
* A `PlayDataset` is not a normal in-memory array. It points at runtime-managed
|
|
62
|
+
* rows, usually backed by persisted sheet storage, and carries metadata such as
|
|
63
|
+
* dataset kind, dataset id, table namespace, count, and preview rows.
|
|
64
|
+
*
|
|
65
|
+
* Pass dataset handles directly into later `ctx.map(...)` stages by default so
|
|
66
|
+
* Deepline keeps row progress, retries, memory use, and table output under
|
|
67
|
+
* runtime control. Use `count()` and `peek()` for bounded inspection. Use
|
|
68
|
+
* `materialize(limit)` or async iteration only when the dataset is intentionally
|
|
69
|
+
* small and bounded.
|
|
70
|
+
*/
|
|
58
71
|
export interface PlayDataset<T> extends AsyncIterable<T> {
|
|
59
72
|
readonly [PLAY_DATASET_BRAND]: true;
|
|
73
|
+
/** Dataset kind. */
|
|
60
74
|
readonly datasetKind: PlayDatasetKind;
|
|
75
|
+
/** Dataset id. */
|
|
61
76
|
readonly datasetId: string;
|
|
77
|
+
/** Backing store info. */
|
|
62
78
|
readonly backing?: PlayDatasetBacking;
|
|
79
|
+
/** Display label. */
|
|
63
80
|
readonly sourceLabel?: string | null;
|
|
81
|
+
/** Runtime table name. */
|
|
64
82
|
readonly tableNamespace?: string | null;
|
|
83
|
+
/** Row count. */
|
|
65
84
|
count(): Promise<number>;
|
|
85
|
+
/** Preview rows. */
|
|
66
86
|
peek(limit?: number): Promise<T[]>;
|
|
67
87
|
/**
|
|
68
88
|
* Explicit escape hatch for bounded result sets.
|
|
@@ -310,7 +330,11 @@ export async function materializePlayDatasetInput<T>(
|
|
|
310
330
|
input: PlayDatasetInput<T>,
|
|
311
331
|
): Promise<T[]> {
|
|
312
332
|
if (isPlayDataset(input)) {
|
|
313
|
-
|
|
333
|
+
const rows: T[] = [];
|
|
334
|
+
for await (const row of input) {
|
|
335
|
+
rows.push(row);
|
|
336
|
+
}
|
|
337
|
+
return rows;
|
|
314
338
|
}
|
|
315
339
|
|
|
316
340
|
if (Array.isArray(input)) {
|