deepline 0.1.62 → 0.1.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/cli/index.js +702 -339
  2. package/dist/cli/index.mjs +727 -348
  3. package/dist/index.d.mts +7 -1
  4. package/dist/index.d.ts +7 -1
  5. package/dist/index.js +77 -51
  6. package/dist/index.mjs +77 -51
  7. package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +9 -10
  8. package/dist/repo/apps/play-runner-workers/src/entry.ts +55 -0
  9. package/dist/repo/apps/play-runner-workers/src/runtime/dataset-handles.ts +36 -27
  10. package/dist/repo/apps/play-runner-workers/src/runtime/tool-http-errors.ts +5 -2
  11. package/dist/repo/sdk/src/client.ts +71 -63
  12. package/dist/repo/sdk/src/errors.ts +5 -1
  13. package/dist/repo/sdk/src/http.ts +25 -17
  14. package/dist/repo/sdk/src/plays/local-file-discovery.ts +93 -24
  15. package/dist/repo/sdk/src/release.ts +2 -2
  16. package/dist/repo/sdk/src/tool-output.ts +40 -20
  17. package/dist/repo/shared_libs/play-runtime/batch-runtime.ts +10 -3
  18. package/dist/repo/shared_libs/play-runtime/batching-types.ts +15 -4
  19. package/dist/repo/shared_libs/play-runtime/coordinator-headers.ts +2 -1
  20. package/dist/repo/shared_libs/play-runtime/dedup-backend.ts +0 -0
  21. package/dist/repo/shared_libs/play-runtime/default-batch-strategies.ts +3 -4
  22. package/dist/repo/shared_libs/play-runtime/run-failure.ts +1 -3
  23. package/dist/repo/shared_libs/play-runtime/step-lifecycle-tracker.ts +4 -1
  24. package/dist/repo/shared_libs/play-runtime/tool-batch-executor.ts +4 -1
  25. package/dist/repo/shared_libs/play-runtime/tool-result.ts +28 -15
  26. package/dist/repo/shared_libs/plays/dataset.ts +10 -11
  27. package/package.json +1 -1
@@ -50,10 +50,10 @@ export type SdkRelease = {
50
50
  };
51
51
 
52
52
  export const SDK_RELEASE = {
53
- version: '0.1.62',
53
+ version: '0.1.64',
54
54
  apiContract: '2026-05-play-bootstrap-dataset-summary',
55
55
  supportPolicy: {
56
- latest: '0.1.62',
56
+ latest: '0.1.64',
57
57
  minimumSupported: '0.1.53',
58
58
  deprecatedBelow: '0.1.53',
59
59
  },
@@ -86,7 +86,9 @@ function normalizeScalarString(value: unknown): string | null {
86
86
  */
87
87
  function getByDottedPath(root: unknown, dottedPath: string): unknown {
88
88
  let current = root;
89
- for (const segment of String(dottedPath || '').split('.').filter(Boolean)) {
89
+ for (const segment of String(dottedPath || '')
90
+ .split('.')
91
+ .filter(Boolean)) {
90
92
  if (!isPlainObject(current) || !(segment in current)) {
91
93
  return null;
92
94
  }
@@ -111,8 +113,12 @@ function normalizeRows(value: unknown): Array<Record<string, unknown>> | null {
111
113
  * Generate candidate root objects to search for lists.
112
114
  * Tries: raw payload → V2 toolResponse.raw → legacy payload.output.body → legacy payload.result → legacy payload.result.data.
113
115
  */
114
- function candidateRoots(payload: unknown): Array<{ path: string | null; value: unknown }> {
115
- const roots: Array<{ path: string | null; value: unknown }> = [{ path: null, value: payload }];
116
+ function candidateRoots(
117
+ payload: unknown,
118
+ ): Array<{ path: string | null; value: unknown }> {
119
+ const roots: Array<{ path: string | null; value: unknown }> = [
120
+ { path: null, value: payload },
121
+ ];
116
122
  if (isPlainObject(payload) && isPlainObject(payload.toolResponse)) {
117
123
  roots.push({ path: 'toolResponse', value: payload.toolResponse });
118
124
  if (Object.prototype.hasOwnProperty.call(payload.toolResponse, 'raw')) {
@@ -150,7 +156,10 @@ function findBestArrayCandidate(
150
156
  if (depth > 5) return null;
151
157
 
152
158
  const directRows = normalizeRows(value);
153
- const hasObjectRow = directRows?.some((row) => Object.keys(row).some((key) => key !== 'value')) ?? false;
159
+ const hasObjectRow =
160
+ directRows?.some((row) =>
161
+ Object.keys(row).some((key) => key !== 'value'),
162
+ ) ?? false;
154
163
  let best: { path: string; rows: Array<Record<string, unknown>> } | null =
155
164
  directRows && directRows.length > 0 && hasObjectRow
156
165
  ? { path: pathPrefix, rows: directRows }
@@ -220,7 +229,10 @@ export function tryConvertToList(
220
229
  options?: { listExtractorPaths?: string[] },
221
230
  ): ListConversionResult | null {
222
231
  const listExtractorPaths = Array.isArray(options?.listExtractorPaths)
223
- ? options?.listExtractorPaths.filter((entry): entry is string => typeof entry === 'string' && entry.trim().length > 0)
232
+ ? options?.listExtractorPaths.filter(
233
+ (entry): entry is string =>
234
+ typeof entry === 'string' && entry.trim().length > 0,
235
+ )
224
236
  : [];
225
237
 
226
238
  if (listExtractorPaths.length > 0) {
@@ -229,7 +241,9 @@ export function tryConvertToList(
229
241
  const resolved = getByDottedPath(root.value, extractorPath);
230
242
  const rows = normalizeRows(resolved);
231
243
  if (rows && rows.length > 0) {
232
- const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
244
+ const sourcePath = root.path
245
+ ? `${root.path}.${extractorPath}`
246
+ : extractorPath;
233
247
  return { rows, strategy: 'configured_paths', sourcePath };
234
248
  }
235
249
  }
@@ -322,11 +336,14 @@ export function writeCsvOutputFile(
322
336
  }
323
337
 
324
338
  const escapeCell = (value: unknown): string => {
325
- const normalized = value == null
326
- ? ''
327
- : typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'
328
- ? String(value)
329
- : JSON.stringify(value);
339
+ const normalized =
340
+ value == null
341
+ ? ''
342
+ : typeof value === 'string' ||
343
+ typeof value === 'number' ||
344
+ typeof value === 'boolean'
345
+ ? String(value)
346
+ : JSON.stringify(value);
330
347
  if (/[",\n]/.test(normalized)) {
331
348
  return `"${normalized.replace(/"/g, '""')}"`;
332
349
  }
@@ -345,7 +362,8 @@ export function writeCsvOutputFile(
345
362
  const preview = [
346
363
  previewColumns.join(','),
347
364
  ...previewRows.map((row) =>
348
- previewColumns.map((column) => escapeCell(row[column])).join(',')),
365
+ previewColumns.map((column) => escapeCell(row[column])).join(','),
366
+ ),
349
367
  ].join('\n');
350
368
 
351
369
  return {
@@ -378,14 +396,16 @@ export function extractSummaryFields(payload: unknown): Record<string, Scalar> {
378
396
  const candidates = candidateRoots(payload);
379
397
  for (const candidate of candidates) {
380
398
  if (!isPlainObject(candidate.value)) continue;
381
- const summaryEntries = Object.entries(candidate.value).filter(([, value]) => {
382
- return (
383
- value == null ||
384
- typeof value === 'string' ||
385
- typeof value === 'number' ||
386
- typeof value === 'boolean'
387
- );
388
- });
399
+ const summaryEntries = Object.entries(candidate.value).filter(
400
+ ([, value]) => {
401
+ return (
402
+ value == null ||
403
+ typeof value === 'string' ||
404
+ typeof value === 'number' ||
405
+ typeof value === 'boolean'
406
+ );
407
+ },
408
+ );
389
409
  if (summaryEntries.length === 0) continue;
390
410
  return Object.fromEntries(summaryEntries) as Record<string, Scalar>;
391
411
  }
@@ -132,7 +132,9 @@ export function compileRequestsWithStrategy<TRequest>(input: {
132
132
  export async function executeWaterfallProviders<TRequest, TResult>(input: {
133
133
  providers: string[];
134
134
  getPendingRequests: () => TRequest[];
135
- getCachedResults: (provider: string) => Array<ChunkExecutionResult<TRequest, TResult>> | null;
135
+ getCachedResults: (
136
+ provider: string,
137
+ ) => Array<ChunkExecutionResult<TRequest, TResult>> | null;
136
138
  storeCachedResults: (
137
139
  provider: string,
138
140
  results: Array<ChunkExecutionResult<TRequest, TResult>>,
@@ -177,6 +179,11 @@ export async function executeWaterfallProviders<TRequest, TResult>(input: {
177
179
  }
178
180
  }
179
181
 
180
- export function resolveWaterfallToolId(provider: string, toolName: string): string {
181
- return toolName.startsWith(`${provider}_`) ? toolName : `${provider}_${toolName}`;
182
+ export function resolveWaterfallToolId(
183
+ provider: string,
184
+ toolName: string,
185
+ ): string {
186
+ return toolName.startsWith(`${provider}_`)
187
+ ? toolName
188
+ : `${provider}_${toolName}`;
182
189
  }
@@ -10,7 +10,10 @@ export type BatchCompileItem<TSingle extends object> = {
10
10
  payload: TSingle;
11
11
  };
12
12
 
13
- export type BatchCompileResult<TBatch extends object, TSingle extends object> = {
13
+ export type BatchCompileResult<
14
+ TBatch extends object,
15
+ TSingle extends object,
16
+ > = {
14
17
  batchOperation: string;
15
18
  batchPayload: TBatch;
16
19
  items: Array<BatchCompileItem<TSingle>>;
@@ -58,7 +61,10 @@ export type AnyBatchOperationStrategy = {
58
61
  batchOperation: string;
59
62
  kind: BatchStrategyKind;
60
63
  maxBatchSize: number;
61
- canBatchWith(left: Record<string, unknown>, right: Record<string, unknown>): boolean;
64
+ canBatchWith(
65
+ left: Record<string, unknown>,
66
+ right: Record<string, unknown>,
67
+ ): boolean;
62
68
  toBucketKey(payload: Record<string, unknown>): string;
63
69
  toItemKey(payload: Record<string, unknown>): string;
64
70
  compile(payloads: Record<string, unknown>[]): {
@@ -81,8 +87,13 @@ export type AnyBatchOperationStrategy = {
81
87
 
82
88
  export type BatchStrategyMap = Record<string, AnyBatchOperationStrategy>;
83
89
 
84
- type StrictBatchOperationStrategy =
85
- BatchOperationStrategy<Record<string, unknown>, Record<string, unknown>, object, unknown, unknown>;
90
+ type StrictBatchOperationStrategy = BatchOperationStrategy<
91
+ Record<string, unknown>,
92
+ Record<string, unknown>,
93
+ object,
94
+ unknown,
95
+ unknown
96
+ >;
86
97
 
87
98
  export function defineBatchStrategyMap<
88
99
  TStrategies extends Record<string, StrictBatchOperationStrategy>,
@@ -31,7 +31,8 @@ function resolveInternalCoordinatorToken(): string | null {
31
31
  // Read lazily so the helper is safe to import in environments without
32
32
  // env access (e.g. workerd build-time bundling).
33
33
  const fromEnv =
34
- (typeof process !== 'undefined' && process?.env?.DEEPLINE_INTERNAL_TOKEN?.trim()) ||
34
+ (typeof process !== 'undefined' &&
35
+ process?.env?.DEEPLINE_INTERNAL_TOKEN?.trim()) ||
35
36
  null;
36
37
  if (fromEnv) return fromEnv;
37
38
  if (!warnedAboutMissingInternalToken) {
@@ -109,10 +109,9 @@ const testRateLimitBatchStrategy: BatchOperationStrategy<
109
109
  },
110
110
  };
111
111
 
112
- export const DEFAULT_PLAY_RUNTIME_BATCH_STRATEGIES =
113
- defineBatchStrategyMap({
114
- test_rate_limit: testRateLimitBatchStrategy,
115
- });
112
+ export const DEFAULT_PLAY_RUNTIME_BATCH_STRATEGIES = defineBatchStrategyMap({
113
+ test_rate_limit: testRateLimitBatchStrategy,
114
+ });
116
115
 
117
116
  export function getDefaultPlayRuntimeBatchStrategy(
118
117
  operation: string | null | undefined,
@@ -27,9 +27,7 @@ export function isCloudflareDurableObjectCodeUpdatedError(
27
27
  );
28
28
  }
29
29
 
30
- export function normalizePlayRunFailure(
31
- error: unknown,
32
- ): PlayRunFailureDetails {
30
+ export function normalizePlayRunFailure(error: unknown): PlayRunFailureDetails {
33
31
  const cause = toErrorText(error);
34
32
  if (isCloudflareDurableObjectCodeUpdatedError(cause)) {
35
33
  return {
@@ -24,7 +24,10 @@ export class PlayStepLifecycleTracker {
24
24
 
25
25
  constructor(
26
26
  private readonly nodes: readonly PlayStepLifecycleNode[],
27
- private readonly getProgress: () => Record<string, PlayStepLifecycleProgress>,
27
+ private readonly getProgress: () => Record<
28
+ string,
29
+ PlayStepLifecycleProgress
30
+ >,
28
31
  private readonly emit: (event: PlayStepLifecycleEvent) => void,
29
32
  private readonly now: () => number = Date.now,
30
33
  ) {}
@@ -55,7 +55,10 @@ export function createToolBatchExecutor(
55
55
  ): ToolBatchExecutor {
56
56
  return {
57
57
  async executeToolBatch(request) {
58
- const providerBatchSize = Math.max(1, Math.floor(request.providerBatchSize));
58
+ const providerBatchSize = Math.max(
59
+ 1,
60
+ Math.floor(request.providerBatchSize),
61
+ );
59
62
  const batches = chunkToolBatchItems(request.items, providerBatchSize);
60
63
  const results: ToolBatchItemResult[] = [];
61
64
  for (let batchIndex = 0; batchIndex < batches.length; batchIndex += 1) {
@@ -454,19 +454,14 @@ function deriveListKeys(input: {
454
454
  }
455
455
 
456
456
  const listPrefix = input.listPath.replace(/\[\d+\]$/, '');
457
- for (const [target, paths] of Object.entries(
458
- input.targetGetters ?? {},
459
- )) {
457
+ for (const [target, paths] of Object.entries(input.targetGetters ?? {})) {
460
458
  for (const rawPath of paths) {
461
459
  const path = String(rawPath || '')
462
460
  .trim()
463
461
  .replace(/^\./, '');
464
462
  if (!path) continue;
465
463
  const firstRow = input.rows[0];
466
- if (
467
- firstRow &&
468
- Object.prototype.hasOwnProperty.call(firstRow, path)
469
- ) {
464
+ if (firstRow && Object.prototype.hasOwnProperty.call(firstRow, path)) {
470
465
  keys[target] = path;
471
466
  break;
472
467
  }
@@ -514,21 +509,20 @@ function buildTargets(
514
509
  for (const [target, descriptor] of Object.entries(extractors ?? {})) {
515
510
  const fromExtractor = findFirstTargetByPath(result, descriptor.paths);
516
511
  if (!fromExtractor) continue;
512
+ const transformed = coerceToEnum(
513
+ applyExtractorTransforms(fromExtractor.value, descriptor),
514
+ descriptor,
515
+ );
516
+ const override = findExtractorOverride(result, descriptor);
517
517
  targets[target] = {
518
518
  path: fromExtractor.path,
519
- value: coerceToEnum(
520
- applyExtractorTransforms(fromExtractor.value, descriptor),
521
- descriptor,
522
- ),
519
+ value: override?.value ?? transformed,
523
520
  };
524
521
  }
525
522
  const metadataTargets = new Set(Object.keys(targetGetters ?? {}));
526
523
  for (const target of metadataTargets) {
527
524
  if (targets[target]) continue;
528
- const fromMetadata = findFirstTargetByPath(
529
- result,
530
- targetGetters?.[target],
531
- );
525
+ const fromMetadata = findFirstTargetByPath(result, targetGetters?.[target]);
532
526
  if (fromMetadata) {
533
527
  targets[target] = fromMetadata;
534
528
  continue;
@@ -547,6 +541,25 @@ function buildTargets(
547
541
  return targets;
548
542
  }
549
543
 
544
+ function findExtractorOverride(
545
+ result: unknown,
546
+ descriptor: ToolResultExtractorDescriptor,
547
+ ): { value: string | number | boolean | null } | null {
548
+ for (const override of descriptor.overrides ?? []) {
549
+ const expected = Object.prototype.hasOwnProperty.call(override, 'equals')
550
+ ? override.equals
551
+ : true;
552
+ for (const path of override.paths) {
553
+ const match = findFirstTargetByPath(result, [path]);
554
+ if (!match) continue;
555
+ if (match.value === expected) {
556
+ return { value: override.value };
557
+ }
558
+ }
559
+ }
560
+ return null;
561
+ }
562
+
550
563
  function buildLists(
551
564
  resolved: Record<string, { path: string; rows: Record<string, unknown>[] }>,
552
565
  metadata: ToolResultMetadataInput,
@@ -172,8 +172,8 @@ function inferPreviewColumns<T>(rows: readonly T[]): string[] | undefined {
172
172
  export function isPlayDataset<T>(value: unknown): value is PlayDataset<T> {
173
173
  return Boolean(
174
174
  value &&
175
- typeof value === 'object' &&
176
- (value as Record<PropertyKey, unknown>)[PLAY_DATASET_BRAND] === true,
175
+ typeof value === 'object' &&
176
+ (value as Record<PropertyKey, unknown>)[PLAY_DATASET_BRAND] === true,
177
177
  );
178
178
  }
179
179
 
@@ -182,13 +182,13 @@ export function isSerializedPlayDataset<T>(
182
182
  ): value is SerializedPlayDataset<T> {
183
183
  return Boolean(
184
184
  value &&
185
- typeof value === 'object' &&
186
- !Array.isArray(value) &&
187
- (value as Record<string, unknown>).kind === 'dataset' &&
188
- typeof (value as Record<string, unknown>).datasetKind === 'string' &&
189
- typeof (value as Record<string, unknown>).datasetId === 'string' &&
190
- typeof (value as Record<string, unknown>).count === 'number' &&
191
- Array.isArray((value as Record<string, unknown>).preview),
185
+ typeof value === 'object' &&
186
+ !Array.isArray(value) &&
187
+ (value as Record<string, unknown>).kind === 'dataset' &&
188
+ typeof (value as Record<string, unknown>).datasetKind === 'string' &&
189
+ typeof (value as Record<string, unknown>).datasetId === 'string' &&
190
+ typeof (value as Record<string, unknown>).count === 'number' &&
191
+ Array.isArray((value as Record<string, unknown>).preview),
192
192
  );
193
193
  }
194
194
 
@@ -506,8 +506,7 @@ export function createPlayDataset<T>(
506
506
  tableNamespace: metadata?.tableNamespace ?? null,
507
507
  resolvers: {
508
508
  count: async () => materializedRows.length,
509
- peek: async (limit) =>
510
- materializedRows.slice(0, Math.max(0, limit)),
509
+ peek: async (limit) => materializedRows.slice(0, Math.max(0, limit)),
511
510
  materialize: async (limit) =>
512
511
  limit === undefined
513
512
  ? [...materializedRows]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.62",
3
+ "version": "0.1.64",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {