deepline 0.1.41 → 0.1.45

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.
@@ -52,7 +52,10 @@ import {
52
52
  import {
53
53
  adaptV2ExecuteResponseToToolResult,
54
54
  createToolExecuteResult,
55
+ deserializeToolExecuteResult,
56
+ isSerializedToolExecuteResult,
55
57
  isToolExecuteResult,
58
+ serializeToolExecuteResult,
56
59
  type ToolExecuteResult,
57
60
  type ToolResultMetadataInput,
58
61
  } from '../../../shared_libs/play-runtime/tool-result';
@@ -448,7 +451,7 @@ async function probeHarnessOnce(
448
451
  */
449
452
  const RUNTIME_API_TIMEOUT_MS = 30_000;
450
453
  const RUNTIME_API_PLAY_RUN_TIMEOUT_MS = 75_000;
451
- const RUNTIME_API_RETRY_DELAYS_MS = [250, 750, 1500] as const;
454
+ const RUNTIME_API_RETRY_DELAYS_MS = [250, 750, 1500, 3000, 5000, 10000] as const;
452
455
  let loggedMissingRuntimeApiBinding = false;
453
456
 
454
457
  async function fetchRuntimeApi(
@@ -461,7 +464,17 @@ async function fetchRuntimeApi(
461
464
  ? RUNTIME_API_PLAY_RUN_TIMEOUT_MS
462
465
  : RUNTIME_API_TIMEOUT_MS;
463
466
  const controller = new AbortController();
464
- const timer = setTimeout(() => controller.abort(), timeoutMs);
467
+ let timeout: ReturnType<typeof setTimeout> | null = null;
468
+ const timeoutPromise = new Promise<never>((_, reject) => {
469
+ timeout = setTimeout(() => {
470
+ controller.abort();
471
+ reject(
472
+ new Error(
473
+ `[play-harness] runtime API call timed out after ${timeoutMs}ms. path=${path} baseUrl=${baseUrl}`,
474
+ ),
475
+ );
476
+ }, timeoutMs);
477
+ });
465
478
  try {
466
479
  const mergedInit: RequestInit = {
467
480
  ...init,
@@ -475,11 +488,15 @@ async function fetchRuntimeApi(
475
488
  `[play-harness] RUNTIME_API binding missing; using public runtime API transport. path=${path}`,
476
489
  );
477
490
  }
478
- return await fetch(`${baseUrl.replace(/\/$/, '')}${path}`, mergedInit);
491
+ return await Promise.race([
492
+ fetch(`${baseUrl.replace(/\/$/, '')}${path}`, mergedInit),
493
+ timeoutPromise,
494
+ ]);
479
495
  }
480
- return await cachedRuntimeApiBinding.fetch(
496
+ const responsePromise = cachedRuntimeApiBinding.fetch(
481
497
  new Request(`${baseUrl.replace(/\/$/, '')}${path}`, mergedInit),
482
498
  );
499
+ return await Promise.race([responsePromise, timeoutPromise]);
483
500
  } catch (err) {
484
501
  if (err instanceof Error && err.name === 'AbortError') {
485
502
  throw new Error(
@@ -488,7 +505,7 @@ async function fetchRuntimeApi(
488
505
  }
489
506
  throw err;
490
507
  } finally {
491
- clearTimeout(timer);
508
+ if (timeout) clearTimeout(timeout);
492
509
  }
493
510
  }
494
511
 
@@ -724,7 +741,8 @@ function isRetryableRuntimeApiResponse(status: number, body: string): boolean {
724
741
  status === 429 ||
725
742
  status === 502 ||
726
743
  status === 503 ||
727
- status === 504
744
+ status === 504 ||
745
+ status === 530
728
746
  ) {
729
747
  return true;
730
748
  }
@@ -1296,12 +1314,44 @@ function parseExecuteToolMetadata(
1296
1314
  : toolId;
1297
1315
  return {
1298
1316
  toolId: metadataToolId,
1299
- resultIdentityGetters: parseGetterMetadata(record.resultIdentityGetters),
1317
+ extractors: parseExtractorMetadata(record.extractors),
1318
+ targetGetters: parseGetterMetadata(record.targetGetters),
1300
1319
  listExtractorPaths: parseStringArray(record.listExtractorPaths),
1301
1320
  listIdentityGetters: parseGetterMetadata(record.listIdentityGetters),
1302
1321
  };
1303
1322
  }
1304
1323
 
1324
+ function parseExtractorMetadata(
1325
+ value: unknown,
1326
+ ): ToolResultMetadataInput['extractors'] {
1327
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
1328
+ return undefined;
1329
+ }
1330
+ const entries = Object.entries(value as Record<string, unknown>).flatMap(
1331
+ ([key, descriptor]) => {
1332
+ if (!descriptor || typeof descriptor !== 'object' || Array.isArray(descriptor)) {
1333
+ return [];
1334
+ }
1335
+ const record = descriptor as Record<string, unknown>;
1336
+ const paths = parseStringArray(record.paths);
1337
+ if (paths.length === 0) return [];
1338
+ const transforms = parseStringArray(record.transforms);
1339
+ const enumValues = parseStringArray(record.enum);
1340
+ return [
1341
+ [
1342
+ key,
1343
+ {
1344
+ paths,
1345
+ ...(transforms.length > 0 ? { transforms } : {}),
1346
+ ...(enumValues.length > 0 ? { enum: enumValues } : {}),
1347
+ },
1348
+ ],
1349
+ ] as const;
1350
+ },
1351
+ );
1352
+ return entries.length > 0 ? Object.fromEntries(entries) : undefined;
1353
+ }
1354
+
1305
1355
  function parseGetterMetadata(
1306
1356
  value: unknown,
1307
1357
  ): Record<string, readonly string[]> | undefined {
@@ -1327,7 +1377,7 @@ function syntheticToolMetadata(toolId: string): ToolResultMetadataInput {
1327
1377
  if (toolId === 'test_rate_limit') {
1328
1378
  return {
1329
1379
  toolId,
1330
- resultIdentityGetters: {
1380
+ targetGetters: {
1331
1381
  email: ['email', 'value'],
1332
1382
  },
1333
1383
  };
@@ -1463,6 +1513,21 @@ function executeSyntheticTransientRetry(
1463
1513
  function executeSyntheticTestRateLimit(
1464
1514
  input: Record<string, unknown>,
1465
1515
  ): Record<string, unknown> {
1516
+ if (
1517
+ typeof input.key === 'string' &&
1518
+ input.key.startsWith('public-error-message-regression')
1519
+ ) {
1520
+ throw new ToolHttpError(
1521
+ [
1522
+ 'tool test_rate_limit 422 attempt 1/1:',
1523
+ 'Synthetic public test error with a redacted token=[REDACTED].',
1524
+ 'code=TEST_PUBLIC_ERROR.',
1525
+ 'failure_description=The fake test provider intentionally raised a typed public error so V2 runner output preserves actionable details.',
1526
+ 'operator_hint=Use this no-bill test provider fixture when verifying play runner error rendering.',
1527
+ ].join(' '),
1528
+ null,
1529
+ );
1530
+ }
1466
1531
  const rowNumber =
1467
1532
  typeof input.row_number === 'number' && Number.isInteger(input.row_number)
1468
1533
  ? input.row_number
@@ -1859,8 +1924,39 @@ type WorkerMapChunkSummary<T extends Record<string, unknown>> = {
1859
1924
  cachedRows?: T[];
1860
1925
  };
1861
1926
 
1862
- function toWorkflowSerializableValue<T>(value: T): T {
1863
- return JSON.parse(JSON.stringify(serializeValue(value, 0))) as T;
1927
+ function serializeDurableStepValue<T>(value: T, depth = 0): T {
1928
+ if (depth > 20 || value == null) return value;
1929
+ if (isToolExecuteResult(value)) return serializeToolExecuteResult(value) as T;
1930
+ if (isDatasetHandle(value)) return serializeValue(value, depth) as T;
1931
+ if (Array.isArray(value)) {
1932
+ return value.map((entry) => serializeDurableStepValue(entry, depth + 1)) as T;
1933
+ }
1934
+ if (typeof value !== 'object') return value;
1935
+ return Object.fromEntries(
1936
+ Object.entries(value as Record<string, unknown>).map(([key, child]) => [
1937
+ key,
1938
+ serializeDurableStepValue(child, depth + 1),
1939
+ ]),
1940
+ ) as T;
1941
+ }
1942
+
1943
+ function deserializeDurableStepValue<T>(value: T, depth = 0): T {
1944
+ if (depth > 20 || value == null) return value;
1945
+ if (isSerializedToolExecuteResult(value)) {
1946
+ return deserializeToolExecuteResult(value) as T;
1947
+ }
1948
+ if (Array.isArray(value)) {
1949
+ return value.map((entry) =>
1950
+ deserializeDurableStepValue(entry, depth + 1),
1951
+ ) as T;
1952
+ }
1953
+ if (typeof value !== 'object') return value;
1954
+ return Object.fromEntries(
1955
+ Object.entries(value as Record<string, unknown>).map(([key, child]) => [
1956
+ key,
1957
+ deserializeDurableStepValue(child, depth + 1),
1958
+ ]),
1959
+ ) as T;
1864
1960
  }
1865
1961
 
1866
1962
  type WorkerStepResolver = (
@@ -1982,8 +2078,8 @@ async function executeWorkerStepProgram(
1982
2078
  let currentRow: Record<string, unknown> = cloneCsvAliasedRow(inputRow);
1983
2079
  for (const step of program.steps) {
1984
2080
  const stepPath = [...(recorder?.path ?? []), step.name];
1985
- const runStep = async () =>
1986
- await executeWorkerStepResolver(
2081
+ const runStep = async (): Promise<WorkerStepResolution> => {
2082
+ const resolution = await executeWorkerStepResolver(
1987
2083
  step.resolver,
1988
2084
  currentRow,
1989
2085
  ctx,
@@ -1991,10 +2087,15 @@ async function executeWorkerStepProgram(
1991
2087
  recorder
1992
2088
  ? {
1993
2089
  ...recorder,
1994
- path: stepPath,
1995
- }
1996
- : undefined,
2090
+ path: stepPath,
2091
+ }
2092
+ : undefined,
1997
2093
  );
2094
+ return {
2095
+ value: serializeDurableStepValue(resolution.value),
2096
+ ...(resolution.status ? { status: resolution.status } : {}),
2097
+ };
2098
+ };
1998
2099
  const resolution = workflowStep
1999
2100
  ? await (
2000
2101
  workflowStep.do as unknown as (
@@ -2003,7 +2104,7 @@ async function executeWorkerStepProgram(
2003
2104
  ) => Promise<WorkerStepResolution>
2004
2105
  )(stepPath.join('.'), runStep)
2005
2106
  : await runStep();
2006
- const value = resolution.value;
2107
+ const value = deserializeDurableStepValue(resolution.value);
2007
2108
  currentRow = cloneCsvAliasedRow(currentRow, { [step.name]: value });
2008
2109
  if (recorder) {
2009
2110
  const stepId = stepPath.join('.');
@@ -3562,10 +3663,10 @@ function createMinimalWorkerCtx(
3562
3663
  rowsSkipped,
3563
3664
  outputDatasetId: `map:${name}`,
3564
3665
  hash,
3565
- preview: toWorkflowSerializableValue(out.slice(0, 5)),
3666
+ preview: serializeDurableStepValue(out.slice(0, 5)),
3566
3667
  cachedRows:
3567
3668
  out.length <= WORKER_DATASET_IN_MEMORY_ROWS
3568
- ? toWorkflowSerializableValue(out)
3669
+ ? serializeDurableStepValue(out)
3569
3670
  : undefined,
3570
3671
  };
3571
3672
  };
@@ -3793,13 +3894,16 @@ function createMinimalWorkerCtx(
3793
3894
  ts: nowMs(),
3794
3895
  });
3795
3896
  }
3897
+ // Static pipeline JS blocks already execute inside a Workflow step.
3898
+ // Wrapping each generated waterfall step in another step.do can leave
3899
+ // Workers preview runs parked after the last provider callback.
3796
3900
  return (await executeWorkerStepProgram(
3797
3901
  program,
3798
3902
  input,
3799
3903
  ctx,
3800
3904
  0,
3801
3905
  undefined,
3802
- workflowStep,
3906
+ undefined,
3803
3907
  )) as T;
3804
3908
  },
3805
3909
  async csv<T extends Record<string, unknown> = Record<string, unknown>>(
@@ -522,7 +522,7 @@ export class DeeplineClient {
522
522
  params.set('search_terms', options.searchTerms.trim());
523
523
  }
524
524
  return this.http.get<ToolSearchResult>(
525
- `/api/v2/integrations/list?${params.toString()}`,
525
+ `/api/v2/tools/search?${params.toString()}`,
526
526
  );
527
527
  }
528
528
 
@@ -77,7 +77,10 @@ import type {
77
77
  PlayDataset,
78
78
  PlayDatasetInput,
79
79
  } from '../../shared_libs/plays/dataset.js';
80
- import type { ToolExecuteResult } from '../../shared_libs/play-runtime/tool-result-types.js';
80
+ import type {
81
+ ToolExecuteResult,
82
+ ToolResultMetadataInput,
83
+ } from '../../shared_libs/play-runtime/tool-result-types.js';
81
84
  import type {
82
85
  DeeplineClientOptions,
83
86
  PlayDetail,
@@ -1092,6 +1095,37 @@ function stringArray(value: unknown): string[] {
1092
1095
  return Array.isArray(value) ? value.map(String) : [];
1093
1096
  }
1094
1097
 
1098
+ function extractorDescriptorRecord(
1099
+ value: unknown,
1100
+ ): ToolResultMetadataInput['extractors'] {
1101
+ if (!isRecord(value)) return {};
1102
+ return Object.fromEntries(
1103
+ Object.entries(value).flatMap(([key, descriptor]) => {
1104
+ if (!isRecord(descriptor)) return [];
1105
+ const paths = stringArray(descriptor.paths)
1106
+ .map((path) => path.trim())
1107
+ .filter(Boolean);
1108
+ if (paths.length === 0) return [];
1109
+ const transforms = stringArray(descriptor.transforms)
1110
+ .map((transform) => transform.trim())
1111
+ .filter(Boolean);
1112
+ const enumValues = stringArray(descriptor.enum)
1113
+ .map((entry) => entry.trim())
1114
+ .filter(Boolean);
1115
+ return [
1116
+ [
1117
+ key,
1118
+ {
1119
+ paths,
1120
+ ...(transforms.length > 0 ? { transforms } : {}),
1121
+ ...(enumValues.length > 0 ? { enum: enumValues } : {}),
1122
+ },
1123
+ ],
1124
+ ];
1125
+ }),
1126
+ );
1127
+ }
1128
+
1095
1129
  function toolExecutionEnvelopeToResult(
1096
1130
  fallbackToolId: string,
1097
1131
  response: ToolExecution,
@@ -1115,8 +1149,9 @@ function toolExecutionEnvelopeToResult(
1115
1149
  typeof toolMetadata.toolId === 'string'
1116
1150
  ? toolMetadata.toolId
1117
1151
  : fallbackToolId,
1118
- resultIdentityGetters: stringArrayRecord(
1119
- toolMetadata.resultIdentityGetters,
1152
+ extractors: extractorDescriptorRecord(toolMetadata.extractors),
1153
+ targetGetters: stringArrayRecord(
1154
+ toolMetadata.targetGetters,
1120
1155
  ),
1121
1156
  listExtractorPaths: stringArray(toolMetadata.listExtractorPaths),
1122
1157
  listIdentityGetters: stringArrayRecord(toolMetadata.listIdentityGetters),
@@ -168,7 +168,25 @@ export interface ToolSearchOptions {
168
168
 
169
169
  export interface ToolSearchResult {
170
170
  tools: ToolDefinition[];
171
+ count?: number;
172
+ total?: number;
173
+ truncated?: boolean;
174
+ query?: string;
175
+ categories?: string[];
176
+ search_terms?: string[];
177
+ search_mode?: 'v1' | 'v2';
171
178
  search_fallback_to_category?: boolean;
179
+ omitted_plays_hint?: string;
180
+ render?: {
181
+ sections?: Array<{
182
+ title: string;
183
+ lines: string[];
184
+ }>;
185
+ actions?: Array<{
186
+ label: string;
187
+ command: string;
188
+ }>;
189
+ };
172
190
  }
173
191
 
174
192
  /**
@@ -626,10 +644,27 @@ export interface PlayCheckResult {
626
644
  valid: boolean;
627
645
  errors: string[];
628
646
  staticPipeline?: Record<string, unknown> | null;
647
+ toolGetterHints?: PlayCheckToolGetterHint[];
629
648
  artifactHash?: string | null;
630
649
  graphHash?: string | null;
631
650
  }
632
651
 
652
+ export interface PlayCheckToolGetterHint {
653
+ toolId: string;
654
+ lists: Array<{
655
+ name: string;
656
+ expression: string;
657
+ raw?: string;
658
+ }>;
659
+ values: Array<{
660
+ name: string;
661
+ expression: string;
662
+ raw?: string;
663
+ }>;
664
+ raw?: string;
665
+ unavailable?: string;
666
+ }
667
+
633
668
  /**
634
669
  * Request body for starting a play run via {@link DeeplineClient.startPlayRun}.
635
670
  *
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.41";
2
- export const SDK_API_CONTRACT = "2026-05-cloud-play-search";
1
+ export const SDK_VERSION = "0.1.45";
2
+ export const SDK_API_CONTRACT = "2026-05-promo-redemption-policy";