deepline 0.1.54 → 0.1.56
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 +673 -127
- package/dist/cli/index.mjs +681 -128
- 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 +36 -12
- package/dist/repo/apps/play-runner-workers/src/runtime/dataset-handles.ts +35 -7
- package/dist/repo/sdk/src/client.ts +33 -2
- package/dist/repo/sdk/src/play.ts +167 -33
- package/dist/repo/sdk/src/plays/bundle-play-file.ts +27 -18
- 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/play-runtime/profiles.ts +26 -54
- package/dist/repo/shared_libs/play-runtime/providers.ts +71 -0
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +9 -1
- package/dist/repo/shared_libs/plays/bundling/index.ts +225 -69
- package/dist/repo/shared_libs/plays/dataset.ts +25 -1
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyCsvRenameProjection,
|
|
3
|
+
stripCsvProjectedFields,
|
|
4
|
+
stripCsvProjectionMetadata,
|
|
3
5
|
type CsvRenameOptions,
|
|
4
6
|
} from '../../../../shared_libs/play-runtime/csv-rename';
|
|
5
7
|
import {
|
|
@@ -38,7 +40,32 @@ const datasetCountHints = new WeakMap<object, number | null>();
|
|
|
38
40
|
const datasetCapabilities = new WeakMap<object, WorkerDatasetCapabilities>();
|
|
39
41
|
|
|
40
42
|
function cloneRow<T extends DatasetRow>(row: T): T {
|
|
41
|
-
|
|
43
|
+
const cloned: DatasetRow = {};
|
|
44
|
+
for (const key of Reflect.ownKeys(row)) {
|
|
45
|
+
const descriptor = Object.getOwnPropertyDescriptor(row, key);
|
|
46
|
+
if (!descriptor) continue;
|
|
47
|
+
Object.defineProperty(cloned, key, descriptor);
|
|
48
|
+
}
|
|
49
|
+
return cloned as T;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function internalDatasetRow<T extends DatasetRow>(row: T): T {
|
|
53
|
+
const stripped = stripCsvProjectionMetadata(row) as DatasetRow;
|
|
54
|
+
const publicRow: DatasetRow = {};
|
|
55
|
+
for (const key of Reflect.ownKeys(stripped)) {
|
|
56
|
+
if (typeof key === 'string' && key.startsWith('__deepline')) continue;
|
|
57
|
+
const descriptor = Object.getOwnPropertyDescriptor(stripped, key);
|
|
58
|
+
if (!descriptor) continue;
|
|
59
|
+
Object.defineProperty(publicRow, key, descriptor);
|
|
60
|
+
}
|
|
61
|
+
return publicRow as T;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function materializedDatasetRow<T extends DatasetRow>(row: T): T {
|
|
65
|
+
const stripped = stripCsvProjectedFields(row) as DatasetRow;
|
|
66
|
+
return Object.fromEntries(
|
|
67
|
+
Object.entries(stripped).filter(([key]) => !key.startsWith('__deepline')),
|
|
68
|
+
) as T;
|
|
42
69
|
}
|
|
43
70
|
|
|
44
71
|
function registerChunkReader<T extends DatasetRow>(
|
|
@@ -138,10 +165,10 @@ export function createPersistedDatasetHandle<T extends DatasetRow>(input: {
|
|
|
138
165
|
const count = Math.max(0, Math.floor(input.count));
|
|
139
166
|
const previewRows = (input.previewRows ?? [])
|
|
140
167
|
.slice(0, WORKER_DATASET_PREVIEW_ROWS)
|
|
141
|
-
.map(
|
|
168
|
+
.map(materializedDatasetRow);
|
|
142
169
|
const cachedRows =
|
|
143
170
|
input.cachedRows && input.cachedRows.length <= WORKER_DATASET_IN_MEMORY_ROWS
|
|
144
|
-
? input.cachedRows.map(
|
|
171
|
+
? input.cachedRows.map(internalDatasetRow)
|
|
145
172
|
: null;
|
|
146
173
|
|
|
147
174
|
async function loadRows(limit: number, offset: number): Promise<T[]> {
|
|
@@ -157,7 +184,7 @@ export function createPersistedDatasetHandle<T extends DatasetRow>(input: {
|
|
|
157
184
|
) {
|
|
158
185
|
return cachedRows
|
|
159
186
|
.slice(normalizedOffset, normalizedOffset + normalizedLimit)
|
|
160
|
-
.map(
|
|
187
|
+
.map(internalDatasetRow);
|
|
161
188
|
}
|
|
162
189
|
const startedAt = input.nowMs();
|
|
163
190
|
const rows = await input.readRows({
|
|
@@ -172,7 +199,7 @@ export function createPersistedDatasetHandle<T extends DatasetRow>(input: {
|
|
|
172
199
|
offset: normalizedOffset,
|
|
173
200
|
rows: rows.length,
|
|
174
201
|
});
|
|
175
|
-
return rows.map(
|
|
202
|
+
return rows.map(internalDatasetRow);
|
|
176
203
|
}
|
|
177
204
|
|
|
178
205
|
async function* readChunks(chunkSize: number): AsyncGenerator<T[], void, void> {
|
|
@@ -205,14 +232,15 @@ export function createPersistedDatasetHandle<T extends DatasetRow>(input: {
|
|
|
205
232
|
workProgress: input.workProgress,
|
|
206
233
|
resolvers: {
|
|
207
234
|
count: async () => count,
|
|
208
|
-
peek: async (limit) =>
|
|
235
|
+
peek: async (limit) =>
|
|
236
|
+
(await loadRows(Math.max(0, limit), 0)).map(materializedDatasetRow),
|
|
209
237
|
materialize: async (limit) => {
|
|
210
238
|
const rows: T[] = [];
|
|
211
239
|
const maxRows = limit ?? count;
|
|
212
240
|
for await (const chunk of readChunks(STREAM_MATERIALIZE_CHUNK_ROWS)) {
|
|
213
241
|
for (const row of chunk) {
|
|
214
242
|
if (rows.length >= maxRows) return rows;
|
|
215
|
-
rows.push(row);
|
|
243
|
+
rows.push(materializedDatasetRow(row));
|
|
216
244
|
}
|
|
217
245
|
}
|
|
218
246
|
return rows;
|
|
@@ -485,6 +485,37 @@ export class DeeplineClient {
|
|
|
485
485
|
return `deepline plays run ${target} --input '{...}' --watch`;
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
+
private starterPlayPath(play: Pick<PlayListItem, 'name' | 'reference'>): string {
|
|
489
|
+
const target = play.reference || play.name;
|
|
490
|
+
const unqualifiedName = target.split('/').pop() || play.name;
|
|
491
|
+
const safeName = unqualifiedName
|
|
492
|
+
.trim()
|
|
493
|
+
.toLowerCase()
|
|
494
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
495
|
+
.replace(/-+/g, '-')
|
|
496
|
+
.replace(/^-|-$/g, '');
|
|
497
|
+
return `./${safeName || 'play'}.play.ts`;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
private playCloneEditStarter(
|
|
501
|
+
play: Pick<
|
|
502
|
+
PlayListItem,
|
|
503
|
+
'name' | 'reference' | 'canClone' | 'canEdit' | 'origin' | 'ownerType'
|
|
504
|
+
>,
|
|
505
|
+
): PlayDescription['cloneEditStarter'] | undefined {
|
|
506
|
+
const readonlyPrebuilt =
|
|
507
|
+
(play.origin === 'prebuilt' || play.ownerType === 'deepline') &&
|
|
508
|
+
!play.canEdit;
|
|
509
|
+
if (!play.canClone && !readonlyPrebuilt) return undefined;
|
|
510
|
+
const target = play.reference || play.name;
|
|
511
|
+
const path = this.starterPlayPath(play);
|
|
512
|
+
return {
|
|
513
|
+
path,
|
|
514
|
+
command: `deepline plays get ${target} --source --out ${path}`,
|
|
515
|
+
checkCommand: `deepline plays check ${path}`,
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
|
|
488
519
|
private summarizePlayListItem(
|
|
489
520
|
play: PlayListItem,
|
|
490
521
|
options?: { compact?: boolean },
|
|
@@ -496,6 +527,7 @@ export class DeeplineClient {
|
|
|
496
527
|
'rowOutputSchema',
|
|
497
528
|
);
|
|
498
529
|
const runCommand = this.playRunCommand(play, { csvInput });
|
|
530
|
+
const cloneEditStarter = this.playCloneEditStarter(play);
|
|
499
531
|
return {
|
|
500
532
|
name: play.name,
|
|
501
533
|
...(play.reference ? { reference: play.reference } : {}),
|
|
@@ -515,6 +547,7 @@ export class DeeplineClient {
|
|
|
515
547
|
...(rowOutputSchema ? { rowOutputSchema } : {}),
|
|
516
548
|
runCommand,
|
|
517
549
|
examples: [runCommand],
|
|
550
|
+
...(cloneEditStarter ? { cloneEditStarter } : {}),
|
|
518
551
|
currentPublishedVersion: play.currentPublishedVersion ?? null,
|
|
519
552
|
isDraftDirty: play.isDraftDirty,
|
|
520
553
|
};
|
|
@@ -1472,12 +1505,10 @@ export class DeeplineClient {
|
|
|
1472
1505
|
|
|
1473
1506
|
async searchPlays(options: {
|
|
1474
1507
|
query: string;
|
|
1475
|
-
origin?: 'prebuilt' | 'owned';
|
|
1476
1508
|
compact?: boolean;
|
|
1477
1509
|
}): Promise<PlayDescription[]> {
|
|
1478
1510
|
const params = new URLSearchParams();
|
|
1479
1511
|
params.set('search', options.query.trim());
|
|
1480
|
-
if (options.origin) params.set('origin', options.origin);
|
|
1481
1512
|
const response = await this.http.get<{ plays: PlayListItem[] }>(
|
|
1482
1513
|
`/api/v2/plays?${params.toString()}`,
|
|
1483
1514
|
);
|
|
@@ -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>,
|
|
@@ -14,13 +14,10 @@ import {
|
|
|
14
14
|
} from '../../../shared_libs/plays/bundling/index.js';
|
|
15
15
|
import {
|
|
16
16
|
PLAY_ARTIFACT_KINDS,
|
|
17
|
-
PLAY_BACKEND_DESCRIPTORS,
|
|
18
17
|
type PlayArtifactKind,
|
|
19
18
|
} from '../../../shared_libs/play-runtime/backend.js';
|
|
20
19
|
import { resolveExecutionProfile } from '../../../shared_libs/play-runtime/profiles.js';
|
|
21
|
-
import {
|
|
22
|
-
discoverPackagedLocalFiles,
|
|
23
|
-
} from './local-file-discovery.js';
|
|
20
|
+
import { discoverPackagedLocalFiles } from './local-file-discovery.js';
|
|
24
21
|
|
|
25
22
|
export type {
|
|
26
23
|
BundlePlayFileOptions,
|
|
@@ -39,9 +36,7 @@ export type {
|
|
|
39
36
|
PlayRuntimeFeature,
|
|
40
37
|
} from '../../../shared_libs/plays/bundling/index.js';
|
|
41
38
|
|
|
42
|
-
export {
|
|
43
|
-
extractDefinedPlayName,
|
|
44
|
-
} from '../../../shared_libs/plays/bundling/index.js';
|
|
39
|
+
export { extractDefinedPlayName } from '../../../shared_libs/plays/bundling/index.js';
|
|
45
40
|
|
|
46
41
|
const PLAY_BUNDLE_CACHE_VERSION = 30;
|
|
47
42
|
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
@@ -57,21 +52,32 @@ const HAS_PACKAGED_BUNDLING_SOURCES = existsSync(
|
|
|
57
52
|
const PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES
|
|
58
53
|
? SOURCE_REPO_ROOT
|
|
59
54
|
: HAS_PACKAGED_BUNDLING_SOURCES
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
? PACKAGED_REPO_ROOT
|
|
56
|
+
: resolve(SDK_PACKAGE_ROOT, '..');
|
|
62
57
|
const SDK_SOURCE_ROOT = HAS_SOURCE_BUNDLING_SOURCES
|
|
63
58
|
? resolve(SOURCE_REPO_ROOT, 'sdk', 'src')
|
|
64
59
|
: HAS_PACKAGED_BUNDLING_SOURCES
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
? resolve(PACKAGED_REPO_ROOT, 'sdk', 'src')
|
|
61
|
+
: resolve(SDK_PACKAGE_ROOT, 'src');
|
|
67
62
|
const SDK_PACKAGE_JSON = resolve(SDK_PACKAGE_ROOT, 'package.json');
|
|
68
63
|
const SDK_ENTRY_FILE = resolve(SDK_SOURCE_ROOT, 'index.ts');
|
|
69
64
|
const SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES
|
|
70
65
|
? SDK_ENTRY_FILE
|
|
71
66
|
: resolve(SDK_PACKAGE_ROOT, 'dist', 'index.d.ts');
|
|
72
67
|
const SDK_WORKERS_ENTRY_FILE = resolve(SDK_SOURCE_ROOT, 'worker-play-entry.ts');
|
|
73
|
-
const WORKERS_HARNESS_ENTRY_FILE = resolve(
|
|
74
|
-
|
|
68
|
+
const WORKERS_HARNESS_ENTRY_FILE = resolve(
|
|
69
|
+
PROJECT_ROOT,
|
|
70
|
+
'apps',
|
|
71
|
+
'play-runner-workers',
|
|
72
|
+
'src',
|
|
73
|
+
'entry.ts',
|
|
74
|
+
);
|
|
75
|
+
const WORKERS_HARNESS_FILES_DIR = resolve(
|
|
76
|
+
PROJECT_ROOT,
|
|
77
|
+
'apps',
|
|
78
|
+
'play-runner-workers',
|
|
79
|
+
'src',
|
|
80
|
+
);
|
|
75
81
|
let hasWarnedAboutNonDevelopmentBundling = false;
|
|
76
82
|
|
|
77
83
|
/**
|
|
@@ -93,7 +99,9 @@ function warnAboutNonDevelopmentBundling(filePath: string): void {
|
|
|
93
99
|
return;
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
const nodeEnv = String(process.env.NODE_ENV ?? '')
|
|
102
|
+
const nodeEnv = String(process.env.NODE_ENV ?? '')
|
|
103
|
+
.trim()
|
|
104
|
+
.toLowerCase();
|
|
97
105
|
if (!nodeEnv || nodeEnv === 'development' || nodeEnv === 'test') {
|
|
98
106
|
return;
|
|
99
107
|
}
|
|
@@ -111,16 +119,17 @@ function warnAboutNonDevelopmentBundling(filePath: string): void {
|
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
function defaultPlayBundleTarget(): PlayArtifactKind {
|
|
114
|
-
return
|
|
115
|
-
resolveExecutionProfile(null).runner
|
|
116
|
-
].artifactKind;
|
|
122
|
+
return resolveExecutionProfile(null).artifactKind;
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
export function createSdkPlayBundlingAdapter(): PlayBundlingAdapter {
|
|
120
126
|
return {
|
|
121
127
|
projectRoot: PROJECT_ROOT,
|
|
122
128
|
nodeModulesDir: resolve(PROJECT_ROOT, 'node_modules'),
|
|
123
|
-
cacheDir: join(
|
|
129
|
+
cacheDir: join(
|
|
130
|
+
tmpdir(),
|
|
131
|
+
`deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION}`,
|
|
132
|
+
),
|
|
124
133
|
sdkSourceRoot: SDK_SOURCE_ROOT,
|
|
125
134
|
sdkPackageJson: SDK_PACKAGE_JSON,
|
|
126
135
|
sdkEntryFile: SDK_ENTRY_FILE,
|
|
@@ -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.56',
|
|
54
|
+
apiContract: '2026-05-play-tool-describe-starters',
|
|
55
55
|
supportPolicy: {
|
|
56
|
-
latest: '0.1.
|
|
56
|
+
latest: '0.1.56',
|
|
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;
|