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.
@@ -1,4 +1,5 @@
1
1
  export type {
2
+ SerializedToolExecuteResult,
2
3
  ToolExecuteResult,
3
4
  ToolResultExecutionMetadata,
4
5
  ToolResultMetadata,
@@ -10,8 +11,10 @@ export type {
10
11
  } from './tool-result-types';
11
12
 
12
13
  import type {
14
+ SerializedToolExecuteResult,
13
15
  ToolExecuteResult,
14
16
  ToolResultExecutionMetadata,
17
+ ToolResultExtractorDescriptor,
15
18
  ToolResultListAccessor,
16
19
  ToolResultListMetadata,
17
20
  ToolResultEnvelope,
@@ -22,6 +25,8 @@ import type {
22
25
 
23
26
  type PathSegment = string | number | '*';
24
27
 
28
+ const SERIALIZED_TOOL_EXECUTE_RESULT_KIND = 'deepline.tool_execute_result.v1';
29
+
25
30
  const TARGET_FALLBACK_KEYS: Record<string, readonly RegExp[]> = {
26
31
  email: [/^email$/i, /^address$/i, /email/i],
27
32
  phone: [/^phone$/i, /mobile/i, /phone/i, /telephone/i],
@@ -91,9 +96,7 @@ export function toV2RawToolOutputPath(path: string): string {
91
96
  .replace(/^result\.?/, '')
92
97
  .replace(/^data\.?/, '')
93
98
  .replace(/^\./, '');
94
- return rawPath
95
- ? `toolResponse.raw.${rawPath}`
96
- : 'toolResponse.raw';
99
+ return rawPath ? `toolResponse.raw.${rawPath}` : 'toolResponse.raw';
97
100
  }
98
101
 
99
102
  function isMeaningfulValue(value: unknown): boolean {
@@ -195,12 +198,8 @@ function toV2RawToolOutputPathPreservingProviderData(path: string): string {
195
198
  ) {
196
199
  return normalized;
197
200
  }
198
- const rawPath = normalized
199
- .replace(/^result\.?/, '')
200
- .replace(/^\./, '');
201
- return rawPath
202
- ? `toolResponse.raw.${rawPath}`
203
- : 'toolResponse.raw';
201
+ const rawPath = normalized.replace(/^result\.?/, '').replace(/^\./, '');
202
+ return rawPath ? `toolResponse.raw.${rawPath}` : 'toolResponse.raw';
204
203
  }
205
204
 
206
205
  function candidateResultPaths(path: string): string[] {
@@ -320,6 +319,61 @@ function findFirstTargetByKey(
320
319
  return null;
321
320
  }
322
321
 
322
+ function normalizeEmailStatus(value: unknown): unknown {
323
+ const normalized = normalizeString(value)
324
+ ?.toLowerCase()
325
+ .replace(/[\s-]+/g, '_');
326
+ if (!normalized) return 'unknown';
327
+ if (['deliverable', 'verified', 'ok', 'true'].includes(normalized))
328
+ return 'valid';
329
+ if (['undeliverable', 'bad', 'false', 'failed'].includes(normalized))
330
+ return 'invalid';
331
+ if (
332
+ ['accept_all', 'acceptall', 'catchall', 'valid_catch_all'].includes(
333
+ normalized,
334
+ )
335
+ ) {
336
+ return 'catch_all';
337
+ }
338
+ return normalized;
339
+ }
340
+
341
+ function normalizePhoneStatus(value: unknown): unknown {
342
+ if (typeof value === 'boolean') return value ? 'valid' : 'invalid';
343
+ const normalized = normalizeString(value)
344
+ ?.toLowerCase()
345
+ .replace(/[\s-]+/g, '_');
346
+ if (!normalized) return 'unknown';
347
+ if (['verified', 'ok', 'true', 'active'].includes(normalized)) return 'valid';
348
+ if (
349
+ ['bad', 'false', 'failed', 'inactive', 'disconnected'].includes(normalized)
350
+ ) {
351
+ return 'invalid';
352
+ }
353
+ return normalized;
354
+ }
355
+
356
+ function applyExtractorTransforms(
357
+ value: unknown,
358
+ descriptor: ToolResultExtractorDescriptor,
359
+ ): unknown {
360
+ return (descriptor.transforms ?? []).reduce((current, transform) => {
361
+ if (transform.endsWith('emailStatus')) return normalizeEmailStatus(current);
362
+ if (transform.endsWith('phoneStatus')) return normalizePhoneStatus(current);
363
+ return current;
364
+ }, value);
365
+ }
366
+
367
+ function coerceToEnum(
368
+ value: unknown,
369
+ descriptor: ToolResultExtractorDescriptor,
370
+ ): unknown {
371
+ if (!descriptor.enum?.length) return value;
372
+ const normalized = normalizeString(value);
373
+ if (!normalized) return value;
374
+ return descriptor.enum.includes(normalized) ? normalized : value;
375
+ }
376
+
323
377
  function resolveListRows(
324
378
  result: unknown,
325
379
  listExtractorPaths: readonly string[] | undefined,
@@ -331,11 +385,8 @@ function resolveListRows(
331
385
  for (const rawPath of listExtractorPaths ?? []) {
332
386
  const path = normalizeResultPath(rawPath);
333
387
  if (!path) continue;
334
- const candidates = [
335
- ...candidateResultPaths(rawPath),
336
- ].filter(
337
- (candidate, index, all) =>
338
- candidate && all.indexOf(candidate) === index,
388
+ const candidates = [...candidateResultPaths(rawPath)].filter(
389
+ (candidate, index, all) => candidate && all.indexOf(candidate) === index,
339
390
  );
340
391
  let resolvedPath: string | null = null;
341
392
  let rows: Record<string, unknown>[] | null = null;
@@ -361,7 +412,7 @@ function resolveListRows(
361
412
  function deriveListKeys(input: {
362
413
  listPath: string;
363
414
  rows: readonly Record<string, unknown>[];
364
- resultIdentityGetters?: Record<string, readonly string[]>;
415
+ targetGetters?: Record<string, readonly string[]>;
365
416
  listIdentityGetters?: Record<string, readonly string[]>;
366
417
  }): Record<string, string> {
367
418
  const keys: Record<string, string> = {};
@@ -369,9 +420,7 @@ function deriveListKeys(input: {
369
420
  input.listIdentityGetters ?? {},
370
421
  )) {
371
422
  const firstPath = paths
372
- .map((rawPath) =>
373
- normalizeRelativePath(rawPath),
374
- )
423
+ .map((rawPath) => normalizeRelativePath(rawPath))
375
424
  .find(Boolean);
376
425
  if (firstPath) {
377
426
  keys[target] = firstPath;
@@ -383,7 +432,7 @@ function deriveListKeys(input: {
383
432
 
384
433
  const listPrefix = input.listPath.replace(/\[\d+\]$/, '');
385
434
  for (const [target, paths] of Object.entries(
386
- input.resultIdentityGetters ?? {},
435
+ input.targetGetters ?? {},
387
436
  )) {
388
437
  for (const rawPath of paths) {
389
438
  const path = String(rawPath || '')
@@ -427,14 +476,27 @@ function deriveListKeys(input: {
427
476
 
428
477
  function buildTargets(
429
478
  result: unknown,
430
- resultIdentityGetters?: Record<string, readonly string[]>,
479
+ extractors?: Record<string, ToolResultExtractorDescriptor>,
480
+ targetGetters?: Record<string, readonly string[]>,
431
481
  ): Record<string, ToolResultTargetMetadata> {
432
482
  const targets: Record<string, ToolResultTargetMetadata> = {};
433
- const metadataTargets = new Set(Object.keys(resultIdentityGetters ?? {}));
483
+ for (const [target, descriptor] of Object.entries(extractors ?? {})) {
484
+ const fromExtractor = findFirstTargetByPath(result, descriptor.paths);
485
+ if (!fromExtractor) continue;
486
+ targets[target] = {
487
+ path: fromExtractor.path,
488
+ value: coerceToEnum(
489
+ applyExtractorTransforms(fromExtractor.value, descriptor),
490
+ descriptor,
491
+ ),
492
+ };
493
+ }
494
+ const metadataTargets = new Set(Object.keys(targetGetters ?? {}));
434
495
  for (const target of metadataTargets) {
496
+ if (targets[target]) continue;
435
497
  const fromMetadata = findFirstTargetByPath(
436
498
  result,
437
- resultIdentityGetters?.[target],
499
+ targetGetters?.[target],
438
500
  );
439
501
  if (fromMetadata) {
440
502
  targets[target] = fromMetadata;
@@ -455,11 +517,10 @@ function buildTargets(
455
517
  }
456
518
 
457
519
  function buildLists(
458
- result: unknown,
520
+ resolved: Record<string, { path: string; rows: Record<string, unknown>[] }>,
459
521
  metadata: ToolResultMetadataInput,
460
522
  ): Record<string, ToolResultListMetadata> {
461
523
  const lists: Record<string, ToolResultListMetadata> = {};
462
- const resolved = resolveListRows(result, metadata.listExtractorPaths);
463
524
  for (const [name, list] of Object.entries(resolved)) {
464
525
  lists[name] = {
465
526
  path: list.path,
@@ -467,7 +528,7 @@ function buildLists(
467
528
  keys: deriveListKeys({
468
529
  listPath: list.path,
469
530
  rows: list.rows,
470
- resultIdentityGetters: metadata.resultIdentityGetters,
531
+ targetGetters: metadata.targetGetters,
471
532
  listIdentityGetters: metadata.listIdentityGetters,
472
533
  }),
473
534
  };
@@ -499,11 +560,12 @@ function buildExtractedAccessors(
499
560
  }
500
561
 
501
562
  function buildListAccessors(
502
- result: unknown,
563
+ resolved: Record<string, { path: string; rows: Record<string, unknown>[] }>,
503
564
  lists: Record<string, ToolResultListMetadata>,
504
565
  ): Record<string, ToolResultListAccessor> {
505
566
  return Object.fromEntries(
506
567
  Object.entries(lists).map(([name, metadata]) => {
568
+ const rows = resolved[name]?.rows ?? [];
507
569
  const accessor = {
508
570
  path: metadata.path,
509
571
  count: metadata.count,
@@ -511,7 +573,7 @@ function buildListAccessors(
511
573
  } as ToolResultListAccessor;
512
574
  Object.defineProperty(accessor, 'get', {
513
575
  value() {
514
- return normalizeRows(getAtPath(result, metadata.path)) ?? [];
576
+ return rows;
515
577
  },
516
578
  enumerable: false,
517
579
  });
@@ -537,13 +599,21 @@ export function createToolExecuteResult<TResult = unknown>(input: {
537
599
  };
538
600
  const targets = buildTargets(
539
601
  resultRoot,
540
- input.metadata.resultIdentityGetters,
602
+ input.metadata.extractors,
603
+ input.metadata.targetGetters,
541
604
  );
542
- const lists = buildLists(resultRoot, input.metadata);
605
+ const resolvedLists = resolveListRows(
606
+ resultRoot,
607
+ input.metadata.listExtractorPaths,
608
+ );
609
+ const lists = buildLists(resolvedLists, input.metadata);
543
610
  const metadata = {
544
611
  toolId: input.metadata.toolId,
545
612
  execution: input.execution,
546
613
  targets,
614
+ ...(input.metadata.extractors
615
+ ? { extractors: input.metadata.extractors }
616
+ : {}),
547
617
  lists,
548
618
  };
549
619
  const toolResponse = {
@@ -551,7 +621,7 @@ export function createToolExecuteResult<TResult = unknown>(input: {
551
621
  ...(result.meta ? { meta: result.meta } : {}),
552
622
  };
553
623
  const extractedValues = buildExtractedAccessors(targets);
554
- const extractedLists = buildListAccessors(resultRoot, lists);
624
+ const extractedLists = buildListAccessors(resolvedLists, lists);
555
625
  const wrapper = {
556
626
  status: input.status,
557
627
  ...(input.jobId ? { job_id: input.jobId } : {}),
@@ -586,6 +656,73 @@ export function isToolExecuteResult(
586
656
  );
587
657
  }
588
658
 
659
+ function metadataInputFromToolExecuteResult(
660
+ value: ToolExecuteResult,
661
+ ): ToolResultMetadataInput {
662
+ return {
663
+ toolId: value._metadata.toolId,
664
+ ...(value._metadata.extractors
665
+ ? { extractors: value._metadata.extractors }
666
+ : {}),
667
+ targetGetters: Object.fromEntries(
668
+ Object.entries(value._metadata.targets).map(([target, info]) => [
669
+ target,
670
+ [info.path],
671
+ ]),
672
+ ),
673
+ listExtractorPaths: Object.values(value._metadata.lists).map(
674
+ (list) => list.path,
675
+ ),
676
+ listIdentityGetters: Object.fromEntries(
677
+ Object.values(value._metadata.lists)
678
+ .flatMap((list) => Object.entries(list.keys))
679
+ .map(([target, path]) => [target, [path]]),
680
+ ),
681
+ };
682
+ }
683
+
684
+ export function serializeToolExecuteResult(
685
+ value: ToolExecuteResult,
686
+ ): SerializedToolExecuteResult {
687
+ return {
688
+ __kind: SERIALIZED_TOOL_EXECUTE_RESULT_KIND,
689
+ status: value.status,
690
+ toolResponse: {
691
+ raw: value.toolResponse.raw,
692
+ ...(value.toolResponse.meta ? { meta: value.toolResponse.meta } : {}),
693
+ },
694
+ metadata: metadataInputFromToolExecuteResult(value),
695
+ execution: value._metadata.execution,
696
+ };
697
+ }
698
+
699
+ export function isSerializedToolExecuteResult(
700
+ value: unknown,
701
+ ): value is SerializedToolExecuteResult {
702
+ return (
703
+ isRecord(value) &&
704
+ value.__kind === SERIALIZED_TOOL_EXECUTE_RESULT_KIND &&
705
+ typeof value.status === 'string' &&
706
+ isRecord(value.toolResponse) &&
707
+ isRecord(value.metadata) &&
708
+ isRecord(value.execution)
709
+ );
710
+ }
711
+
712
+ export function deserializeToolExecuteResult(
713
+ value: SerializedToolExecuteResult,
714
+ ): ToolExecuteResult {
715
+ return createToolExecuteResult({
716
+ status: value.status,
717
+ result: {
718
+ data: value.toolResponse.raw,
719
+ ...(value.toolResponse.meta ? { meta: value.toolResponse.meta } : {}),
720
+ },
721
+ metadata: value.metadata,
722
+ execution: value.execution,
723
+ });
724
+ }
725
+
589
726
  export function cloneToolExecuteResultWithExecution<TResult>(
590
727
  value: ToolExecuteResult<TResult>,
591
728
  execution: ToolResultExecutionMetadata,
@@ -600,23 +737,7 @@ export function cloneToolExecuteResultWithExecution<TResult>(
600
737
  data: value.toolResponse.raw,
601
738
  ...(value.toolResponse.meta ? { meta: value.toolResponse.meta } : {}),
602
739
  } as TResult,
603
- metadata: {
604
- toolId: value._metadata.toolId,
605
- resultIdentityGetters: Object.fromEntries(
606
- Object.entries(value._metadata.targets).map(([target, info]) => [
607
- target,
608
- [info.path],
609
- ]),
610
- ),
611
- listExtractorPaths: Object.values(value._metadata.lists).map(
612
- (list) => list.path,
613
- ),
614
- listIdentityGetters: Object.fromEntries(
615
- Object.values(value._metadata.lists)
616
- .flatMap((list) => Object.entries(list.keys))
617
- .map(([target, path]) => [target, [path]]),
618
- ),
619
- },
740
+ metadata: metadataInputFromToolExecuteResult(value),
620
741
  execution,
621
742
  meta: isRecord(value.meta) ? value.meta : undefined,
622
743
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.41",
3
+ "version": "0.1.45",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {