deepline 0.1.42 → 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.
package/dist/cli/index.js CHANGED
@@ -216,8 +216,8 @@ function resolveConfig(options) {
216
216
  }
217
217
 
218
218
  // src/version.ts
219
- var SDK_VERSION = "0.1.42";
220
- var SDK_API_CONTRACT = "2026-05-play-tool-result-errors";
219
+ var SDK_VERSION = "0.1.45";
220
+ var SDK_API_CONTRACT = "2026-05-promo-redemption-policy";
221
221
 
222
222
  // ../shared_libs/play-runtime/coordinator-headers.ts
223
223
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
@@ -764,7 +764,7 @@ var DeeplineClient = class {
764
764
  params.set("search_terms", options.searchTerms.trim());
765
765
  }
766
766
  return this.http.get(
767
- `/api/v2/integrations/list?${params.toString()}`
767
+ `/api/v2/tools/search?${params.toString()}`
768
768
  );
769
769
  }
770
770
  /**
@@ -9280,33 +9280,9 @@ async function searchTools(queryInput, options = {}) {
9280
9280
  searchMode: options.searchMode,
9281
9281
  includeSearchDebug: options.includeSearchDebug
9282
9282
  });
9283
- const items = result.tools.filter((tool) => !isPlayLikeTool(tool)).map(toListedTool);
9284
- const envelope = {
9285
- ...result,
9286
- tools: items,
9287
- count: items.length,
9288
- omitted_plays_hint: "Use `deepline plays search <query> --json` for prebuilt and org-owned plays.",
9289
- render: {
9290
- sections: [
9291
- {
9292
- title: `${items.length} tools found:`,
9293
- lines: items.flatMap((item) => {
9294
- const cats = item.categories.length ? ` [${item.categories.join(", ")}]` : "";
9295
- return [
9296
- `${item.toolId}${cats}`,
9297
- ` ${item.description}`,
9298
- ...item.inputSchema ? [" inputSchema: yes"] : []
9299
- ];
9300
- })
9301
- },
9302
- {
9303
- title: "plays",
9304
- lines: ["For prebuilt or org-owned workflows, run: deepline plays search <query>"]
9305
- }
9306
- ]
9307
- }
9308
- };
9309
- printCommandEnvelope(envelope, { json: options.json || shouldEmitJson() });
9283
+ printCommandEnvelope(result, {
9284
+ json: options.json || shouldEmitJson()
9285
+ });
9310
9286
  return 0;
9311
9287
  }
9312
9288
  function playIdentifiers(play) {
@@ -193,8 +193,8 @@ function resolveConfig(options) {
193
193
  }
194
194
 
195
195
  // src/version.ts
196
- var SDK_VERSION = "0.1.42";
197
- var SDK_API_CONTRACT = "2026-05-play-tool-result-errors";
196
+ var SDK_VERSION = "0.1.45";
197
+ var SDK_API_CONTRACT = "2026-05-promo-redemption-policy";
198
198
 
199
199
  // ../shared_libs/play-runtime/coordinator-headers.ts
200
200
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
@@ -741,7 +741,7 @@ var DeeplineClient = class {
741
741
  params.set("search_terms", options.searchTerms.trim());
742
742
  }
743
743
  return this.http.get(
744
- `/api/v2/integrations/list?${params.toString()}`
744
+ `/api/v2/tools/search?${params.toString()}`
745
745
  );
746
746
  }
747
747
  /**
@@ -9267,33 +9267,9 @@ async function searchTools(queryInput, options = {}) {
9267
9267
  searchMode: options.searchMode,
9268
9268
  includeSearchDebug: options.includeSearchDebug
9269
9269
  });
9270
- const items = result.tools.filter((tool) => !isPlayLikeTool(tool)).map(toListedTool);
9271
- const envelope = {
9272
- ...result,
9273
- tools: items,
9274
- count: items.length,
9275
- omitted_plays_hint: "Use `deepline plays search <query> --json` for prebuilt and org-owned plays.",
9276
- render: {
9277
- sections: [
9278
- {
9279
- title: `${items.length} tools found:`,
9280
- lines: items.flatMap((item) => {
9281
- const cats = item.categories.length ? ` [${item.categories.join(", ")}]` : "";
9282
- return [
9283
- `${item.toolId}${cats}`,
9284
- ` ${item.description}`,
9285
- ...item.inputSchema ? [" inputSchema: yes"] : []
9286
- ];
9287
- })
9288
- },
9289
- {
9290
- title: "plays",
9291
- lines: ["For prebuilt or org-owned workflows, run: deepline plays search <query>"]
9292
- }
9293
- ]
9294
- }
9295
- };
9296
- printCommandEnvelope(envelope, { json: options.json || shouldEmitJson() });
9270
+ printCommandEnvelope(result, {
9271
+ json: options.json || shouldEmitJson()
9272
+ });
9297
9273
  return 0;
9298
9274
  }
9299
9275
  function playIdentifiers(play) {
package/dist/index.d.mts CHANGED
@@ -318,7 +318,25 @@ interface ToolSearchOptions {
318
318
  }
319
319
  interface ToolSearchResult {
320
320
  tools: ToolDefinition[];
321
+ count?: number;
322
+ total?: number;
323
+ truncated?: boolean;
324
+ query?: string;
325
+ categories?: string[];
326
+ search_terms?: string[];
327
+ search_mode?: 'v1' | 'v2';
321
328
  search_fallback_to_category?: boolean;
329
+ omitted_plays_hint?: string;
330
+ render?: {
331
+ sections?: Array<{
332
+ title: string;
333
+ lines: string[];
334
+ }>;
335
+ actions?: Array<{
336
+ label: string;
337
+ command: string;
338
+ }>;
339
+ };
322
340
  }
323
341
  /**
324
342
  * Extended tool metadata including pricing, samples, and failure modes.
@@ -1493,8 +1511,8 @@ declare class DeeplineClient {
1493
1511
  }>;
1494
1512
  }
1495
1513
 
1496
- declare const SDK_VERSION = "0.1.42";
1497
- declare const SDK_API_CONTRACT = "2026-05-play-tool-result-errors";
1514
+ declare const SDK_VERSION = "0.1.45";
1515
+ declare const SDK_API_CONTRACT = "2026-05-promo-redemption-policy";
1498
1516
 
1499
1517
  /**
1500
1518
  * Base error class for all Deepline SDK errors.
@@ -1700,6 +1718,11 @@ type ToolResultListMetadata = {
1700
1718
  count: number | null;
1701
1719
  keys: Record<string, string>;
1702
1720
  };
1721
+ type ToolResultExtractorDescriptor = {
1722
+ paths: readonly string[];
1723
+ transforms?: readonly string[];
1724
+ enum?: readonly string[];
1725
+ };
1703
1726
  type ToolResultTargetAccessor<T = unknown> = ToolResultTargetMetadata & {
1704
1727
  get(): T | null;
1705
1728
  };
@@ -1727,6 +1750,7 @@ type ToolExecuteResultBase<TResult = unknown, TMeta = Record<string, unknown>> =
1727
1750
  value: unknown;
1728
1751
  path: string;
1729
1752
  }>;
1753
+ extractors?: Record<string, ToolResultExtractorDescriptor>;
1730
1754
  lists: Record<string, {
1731
1755
  path: string;
1732
1756
  count: number | null;
package/dist/index.d.ts CHANGED
@@ -318,7 +318,25 @@ interface ToolSearchOptions {
318
318
  }
319
319
  interface ToolSearchResult {
320
320
  tools: ToolDefinition[];
321
+ count?: number;
322
+ total?: number;
323
+ truncated?: boolean;
324
+ query?: string;
325
+ categories?: string[];
326
+ search_terms?: string[];
327
+ search_mode?: 'v1' | 'v2';
321
328
  search_fallback_to_category?: boolean;
329
+ omitted_plays_hint?: string;
330
+ render?: {
331
+ sections?: Array<{
332
+ title: string;
333
+ lines: string[];
334
+ }>;
335
+ actions?: Array<{
336
+ label: string;
337
+ command: string;
338
+ }>;
339
+ };
322
340
  }
323
341
  /**
324
342
  * Extended tool metadata including pricing, samples, and failure modes.
@@ -1493,8 +1511,8 @@ declare class DeeplineClient {
1493
1511
  }>;
1494
1512
  }
1495
1513
 
1496
- declare const SDK_VERSION = "0.1.42";
1497
- declare const SDK_API_CONTRACT = "2026-05-play-tool-result-errors";
1514
+ declare const SDK_VERSION = "0.1.45";
1515
+ declare const SDK_API_CONTRACT = "2026-05-promo-redemption-policy";
1498
1516
 
1499
1517
  /**
1500
1518
  * Base error class for all Deepline SDK errors.
@@ -1700,6 +1718,11 @@ type ToolResultListMetadata = {
1700
1718
  count: number | null;
1701
1719
  keys: Record<string, string>;
1702
1720
  };
1721
+ type ToolResultExtractorDescriptor = {
1722
+ paths: readonly string[];
1723
+ transforms?: readonly string[];
1724
+ enum?: readonly string[];
1725
+ };
1703
1726
  type ToolResultTargetAccessor<T = unknown> = ToolResultTargetMetadata & {
1704
1727
  get(): T | null;
1705
1728
  };
@@ -1727,6 +1750,7 @@ type ToolExecuteResultBase<TResult = unknown, TMeta = Record<string, unknown>> =
1727
1750
  value: unknown;
1728
1751
  path: string;
1729
1752
  }>;
1753
+ extractors?: Record<string, ToolResultExtractorDescriptor>;
1730
1754
  lists: Record<string, {
1731
1755
  path: string;
1732
1756
  count: number | null;
package/dist/index.js CHANGED
@@ -215,8 +215,8 @@ function resolveConfig(options) {
215
215
  }
216
216
 
217
217
  // src/version.ts
218
- var SDK_VERSION = "0.1.42";
219
- var SDK_API_CONTRACT = "2026-05-play-tool-result-errors";
218
+ var SDK_VERSION = "0.1.45";
219
+ var SDK_API_CONTRACT = "2026-05-promo-redemption-policy";
220
220
 
221
221
  // ../shared_libs/play-runtime/coordinator-headers.ts
222
222
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
@@ -763,7 +763,7 @@ var DeeplineClient = class {
763
763
  params.set("search_terms", options.searchTerms.trim());
764
764
  }
765
765
  return this.http.get(
766
- `/api/v2/integrations/list?${params.toString()}`
766
+ `/api/v2/tools/search?${params.toString()}`
767
767
  );
768
768
  }
769
769
  /**
@@ -1736,6 +1736,16 @@ function getAtPath(root, path) {
1736
1736
  }
1737
1737
  return current;
1738
1738
  }
1739
+ function normalizeString(value) {
1740
+ if (typeof value === "string") {
1741
+ const trimmed = value.trim();
1742
+ return trimmed ? trimmed : null;
1743
+ }
1744
+ if (typeof value === "number" && Number.isFinite(value)) {
1745
+ return String(value);
1746
+ }
1747
+ return null;
1748
+ }
1739
1749
  function normalizeRows(value) {
1740
1750
  if (!Array.isArray(value)) return null;
1741
1751
  return value.map((entry) => isRecord2(entry) ? entry : { value: entry });
@@ -1779,14 +1789,49 @@ function findFirstTargetByKey(result, target, depth = 0, path = []) {
1779
1789
  }
1780
1790
  return null;
1781
1791
  }
1792
+ function normalizeEmailStatus(value) {
1793
+ const normalized = normalizeString(value)?.toLowerCase().replace(/[\s-]+/g, "_");
1794
+ if (!normalized) return "unknown";
1795
+ if (["deliverable", "verified", "ok", "true"].includes(normalized))
1796
+ return "valid";
1797
+ if (["undeliverable", "bad", "false", "failed"].includes(normalized))
1798
+ return "invalid";
1799
+ if (["accept_all", "acceptall", "catchall", "valid_catch_all"].includes(
1800
+ normalized
1801
+ )) {
1802
+ return "catch_all";
1803
+ }
1804
+ return normalized;
1805
+ }
1806
+ function normalizePhoneStatus(value) {
1807
+ if (typeof value === "boolean") return value ? "valid" : "invalid";
1808
+ const normalized = normalizeString(value)?.toLowerCase().replace(/[\s-]+/g, "_");
1809
+ if (!normalized) return "unknown";
1810
+ if (["verified", "ok", "true", "active"].includes(normalized)) return "valid";
1811
+ if (["bad", "false", "failed", "inactive", "disconnected"].includes(normalized)) {
1812
+ return "invalid";
1813
+ }
1814
+ return normalized;
1815
+ }
1816
+ function applyExtractorTransforms(value, descriptor) {
1817
+ return (descriptor.transforms ?? []).reduce((current, transform) => {
1818
+ if (transform.endsWith("emailStatus")) return normalizeEmailStatus(current);
1819
+ if (transform.endsWith("phoneStatus")) return normalizePhoneStatus(current);
1820
+ return current;
1821
+ }, value);
1822
+ }
1823
+ function coerceToEnum(value, descriptor) {
1824
+ if (!descriptor.enum?.length) return value;
1825
+ const normalized = normalizeString(value);
1826
+ if (!normalized) return value;
1827
+ return descriptor.enum.includes(normalized) ? normalized : value;
1828
+ }
1782
1829
  function resolveListRows(result, listExtractorPaths) {
1783
1830
  const lists = {};
1784
1831
  for (const rawPath of listExtractorPaths ?? []) {
1785
1832
  const path = normalizeResultPath(rawPath);
1786
1833
  if (!path) continue;
1787
- const candidates = [
1788
- ...candidateResultPaths(rawPath)
1789
- ].filter(
1834
+ const candidates = [...candidateResultPaths(rawPath)].filter(
1790
1835
  (candidate, index, all) => candidate && all.indexOf(candidate) === index
1791
1836
  );
1792
1837
  let resolvedPath = null;
@@ -1810,9 +1855,7 @@ function deriveListKeys(input) {
1810
1855
  for (const [target, paths] of Object.entries(
1811
1856
  input.listIdentityGetters ?? {}
1812
1857
  )) {
1813
- const firstPath = paths.map(
1814
- (rawPath) => normalizeRelativePath(rawPath)
1815
- ).find(Boolean);
1858
+ const firstPath = paths.map((rawPath) => normalizeRelativePath(rawPath)).find(Boolean);
1816
1859
  if (firstPath) {
1817
1860
  keys[target] = firstPath;
1818
1861
  }
@@ -1822,7 +1865,7 @@ function deriveListKeys(input) {
1822
1865
  }
1823
1866
  const listPrefix = input.listPath.replace(/\[\d+\]$/, "");
1824
1867
  for (const [target, paths] of Object.entries(
1825
- input.resultIdentityGetters ?? {}
1868
+ input.targetGetters ?? {}
1826
1869
  )) {
1827
1870
  for (const rawPath of paths) {
1828
1871
  const path = String(rawPath || "").trim().replace(/^\./, "");
@@ -1859,13 +1902,25 @@ function deriveListKeys(input) {
1859
1902
  }
1860
1903
  return keys;
1861
1904
  }
1862
- function buildTargets(result, resultIdentityGetters) {
1905
+ function buildTargets(result, extractors, targetGetters) {
1863
1906
  const targets = {};
1864
- const metadataTargets = new Set(Object.keys(resultIdentityGetters ?? {}));
1907
+ for (const [target, descriptor] of Object.entries(extractors ?? {})) {
1908
+ const fromExtractor = findFirstTargetByPath(result, descriptor.paths);
1909
+ if (!fromExtractor) continue;
1910
+ targets[target] = {
1911
+ path: fromExtractor.path,
1912
+ value: coerceToEnum(
1913
+ applyExtractorTransforms(fromExtractor.value, descriptor),
1914
+ descriptor
1915
+ )
1916
+ };
1917
+ }
1918
+ const metadataTargets = new Set(Object.keys(targetGetters ?? {}));
1865
1919
  for (const target of metadataTargets) {
1920
+ if (targets[target]) continue;
1866
1921
  const fromMetadata = findFirstTargetByPath(
1867
1922
  result,
1868
- resultIdentityGetters?.[target]
1923
+ targetGetters?.[target]
1869
1924
  );
1870
1925
  if (fromMetadata) {
1871
1926
  targets[target] = fromMetadata;
@@ -1892,7 +1947,7 @@ function buildLists(resolved, metadata) {
1892
1947
  keys: deriveListKeys({
1893
1948
  listPath: list.path,
1894
1949
  rows: list.rows,
1895
- resultIdentityGetters: metadata.resultIdentityGetters,
1950
+ targetGetters: metadata.targetGetters,
1896
1951
  listIdentityGetters: metadata.listIdentityGetters
1897
1952
  })
1898
1953
  };
@@ -1948,7 +2003,8 @@ function createToolExecuteResult(input) {
1948
2003
  };
1949
2004
  const targets = buildTargets(
1950
2005
  resultRoot,
1951
- input.metadata.resultIdentityGetters
2006
+ input.metadata.extractors,
2007
+ input.metadata.targetGetters
1952
2008
  );
1953
2009
  const resolvedLists = resolveListRows(
1954
2010
  resultRoot,
@@ -1959,6 +2015,7 @@ function createToolExecuteResult(input) {
1959
2015
  toolId: input.metadata.toolId,
1960
2016
  execution: input.execution,
1961
2017
  targets,
2018
+ ...input.metadata.extractors ? { extractors: input.metadata.extractors } : {},
1962
2019
  lists
1963
2020
  };
1964
2021
  const toolResponse = {
@@ -2254,6 +2311,28 @@ function stringArrayRecord(value) {
2254
2311
  function stringArray(value) {
2255
2312
  return Array.isArray(value) ? value.map(String) : [];
2256
2313
  }
2314
+ function extractorDescriptorRecord(value) {
2315
+ if (!isRecord3(value)) return {};
2316
+ return Object.fromEntries(
2317
+ Object.entries(value).flatMap(([key, descriptor]) => {
2318
+ if (!isRecord3(descriptor)) return [];
2319
+ const paths = stringArray(descriptor.paths).map((path) => path.trim()).filter(Boolean);
2320
+ if (paths.length === 0) return [];
2321
+ const transforms = stringArray(descriptor.transforms).map((transform) => transform.trim()).filter(Boolean);
2322
+ const enumValues = stringArray(descriptor.enum).map((entry) => entry.trim()).filter(Boolean);
2323
+ return [
2324
+ [
2325
+ key,
2326
+ {
2327
+ paths,
2328
+ ...transforms.length > 0 ? { transforms } : {},
2329
+ ...enumValues.length > 0 ? { enum: enumValues } : {}
2330
+ }
2331
+ ]
2332
+ ];
2333
+ })
2334
+ );
2335
+ }
2257
2336
  function toolExecutionEnvelopeToResult(fallbackToolId, response) {
2258
2337
  const raw = response.toolResponse?.raw ?? null;
2259
2338
  const meta = response.toolResponse?.meta;
@@ -2268,8 +2347,9 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response) {
2268
2347
  },
2269
2348
  metadata: {
2270
2349
  toolId: typeof toolMetadata.toolId === "string" ? toolMetadata.toolId : fallbackToolId,
2271
- resultIdentityGetters: stringArrayRecord(
2272
- toolMetadata.resultIdentityGetters
2350
+ extractors: extractorDescriptorRecord(toolMetadata.extractors),
2351
+ targetGetters: stringArrayRecord(
2352
+ toolMetadata.targetGetters
2273
2353
  ),
2274
2354
  listExtractorPaths: stringArray(toolMetadata.listExtractorPaths),
2275
2355
  listIdentityGetters: stringArrayRecord(toolMetadata.listIdentityGetters)
package/dist/index.mjs CHANGED
@@ -169,8 +169,8 @@ function resolveConfig(options) {
169
169
  }
170
170
 
171
171
  // src/version.ts
172
- var SDK_VERSION = "0.1.42";
173
- var SDK_API_CONTRACT = "2026-05-play-tool-result-errors";
172
+ var SDK_VERSION = "0.1.45";
173
+ var SDK_API_CONTRACT = "2026-05-promo-redemption-policy";
174
174
 
175
175
  // ../shared_libs/play-runtime/coordinator-headers.ts
176
176
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
@@ -717,7 +717,7 @@ var DeeplineClient = class {
717
717
  params.set("search_terms", options.searchTerms.trim());
718
718
  }
719
719
  return this.http.get(
720
- `/api/v2/integrations/list?${params.toString()}`
720
+ `/api/v2/tools/search?${params.toString()}`
721
721
  );
722
722
  }
723
723
  /**
@@ -1690,6 +1690,16 @@ function getAtPath(root, path) {
1690
1690
  }
1691
1691
  return current;
1692
1692
  }
1693
+ function normalizeString(value) {
1694
+ if (typeof value === "string") {
1695
+ const trimmed = value.trim();
1696
+ return trimmed ? trimmed : null;
1697
+ }
1698
+ if (typeof value === "number" && Number.isFinite(value)) {
1699
+ return String(value);
1700
+ }
1701
+ return null;
1702
+ }
1693
1703
  function normalizeRows(value) {
1694
1704
  if (!Array.isArray(value)) return null;
1695
1705
  return value.map((entry) => isRecord2(entry) ? entry : { value: entry });
@@ -1733,14 +1743,49 @@ function findFirstTargetByKey(result, target, depth = 0, path = []) {
1733
1743
  }
1734
1744
  return null;
1735
1745
  }
1746
+ function normalizeEmailStatus(value) {
1747
+ const normalized = normalizeString(value)?.toLowerCase().replace(/[\s-]+/g, "_");
1748
+ if (!normalized) return "unknown";
1749
+ if (["deliverable", "verified", "ok", "true"].includes(normalized))
1750
+ return "valid";
1751
+ if (["undeliverable", "bad", "false", "failed"].includes(normalized))
1752
+ return "invalid";
1753
+ if (["accept_all", "acceptall", "catchall", "valid_catch_all"].includes(
1754
+ normalized
1755
+ )) {
1756
+ return "catch_all";
1757
+ }
1758
+ return normalized;
1759
+ }
1760
+ function normalizePhoneStatus(value) {
1761
+ if (typeof value === "boolean") return value ? "valid" : "invalid";
1762
+ const normalized = normalizeString(value)?.toLowerCase().replace(/[\s-]+/g, "_");
1763
+ if (!normalized) return "unknown";
1764
+ if (["verified", "ok", "true", "active"].includes(normalized)) return "valid";
1765
+ if (["bad", "false", "failed", "inactive", "disconnected"].includes(normalized)) {
1766
+ return "invalid";
1767
+ }
1768
+ return normalized;
1769
+ }
1770
+ function applyExtractorTransforms(value, descriptor) {
1771
+ return (descriptor.transforms ?? []).reduce((current, transform) => {
1772
+ if (transform.endsWith("emailStatus")) return normalizeEmailStatus(current);
1773
+ if (transform.endsWith("phoneStatus")) return normalizePhoneStatus(current);
1774
+ return current;
1775
+ }, value);
1776
+ }
1777
+ function coerceToEnum(value, descriptor) {
1778
+ if (!descriptor.enum?.length) return value;
1779
+ const normalized = normalizeString(value);
1780
+ if (!normalized) return value;
1781
+ return descriptor.enum.includes(normalized) ? normalized : value;
1782
+ }
1736
1783
  function resolveListRows(result, listExtractorPaths) {
1737
1784
  const lists = {};
1738
1785
  for (const rawPath of listExtractorPaths ?? []) {
1739
1786
  const path = normalizeResultPath(rawPath);
1740
1787
  if (!path) continue;
1741
- const candidates = [
1742
- ...candidateResultPaths(rawPath)
1743
- ].filter(
1788
+ const candidates = [...candidateResultPaths(rawPath)].filter(
1744
1789
  (candidate, index, all) => candidate && all.indexOf(candidate) === index
1745
1790
  );
1746
1791
  let resolvedPath = null;
@@ -1764,9 +1809,7 @@ function deriveListKeys(input) {
1764
1809
  for (const [target, paths] of Object.entries(
1765
1810
  input.listIdentityGetters ?? {}
1766
1811
  )) {
1767
- const firstPath = paths.map(
1768
- (rawPath) => normalizeRelativePath(rawPath)
1769
- ).find(Boolean);
1812
+ const firstPath = paths.map((rawPath) => normalizeRelativePath(rawPath)).find(Boolean);
1770
1813
  if (firstPath) {
1771
1814
  keys[target] = firstPath;
1772
1815
  }
@@ -1776,7 +1819,7 @@ function deriveListKeys(input) {
1776
1819
  }
1777
1820
  const listPrefix = input.listPath.replace(/\[\d+\]$/, "");
1778
1821
  for (const [target, paths] of Object.entries(
1779
- input.resultIdentityGetters ?? {}
1822
+ input.targetGetters ?? {}
1780
1823
  )) {
1781
1824
  for (const rawPath of paths) {
1782
1825
  const path = String(rawPath || "").trim().replace(/^\./, "");
@@ -1813,13 +1856,25 @@ function deriveListKeys(input) {
1813
1856
  }
1814
1857
  return keys;
1815
1858
  }
1816
- function buildTargets(result, resultIdentityGetters) {
1859
+ function buildTargets(result, extractors, targetGetters) {
1817
1860
  const targets = {};
1818
- const metadataTargets = new Set(Object.keys(resultIdentityGetters ?? {}));
1861
+ for (const [target, descriptor] of Object.entries(extractors ?? {})) {
1862
+ const fromExtractor = findFirstTargetByPath(result, descriptor.paths);
1863
+ if (!fromExtractor) continue;
1864
+ targets[target] = {
1865
+ path: fromExtractor.path,
1866
+ value: coerceToEnum(
1867
+ applyExtractorTransforms(fromExtractor.value, descriptor),
1868
+ descriptor
1869
+ )
1870
+ };
1871
+ }
1872
+ const metadataTargets = new Set(Object.keys(targetGetters ?? {}));
1819
1873
  for (const target of metadataTargets) {
1874
+ if (targets[target]) continue;
1820
1875
  const fromMetadata = findFirstTargetByPath(
1821
1876
  result,
1822
- resultIdentityGetters?.[target]
1877
+ targetGetters?.[target]
1823
1878
  );
1824
1879
  if (fromMetadata) {
1825
1880
  targets[target] = fromMetadata;
@@ -1846,7 +1901,7 @@ function buildLists(resolved, metadata) {
1846
1901
  keys: deriveListKeys({
1847
1902
  listPath: list.path,
1848
1903
  rows: list.rows,
1849
- resultIdentityGetters: metadata.resultIdentityGetters,
1904
+ targetGetters: metadata.targetGetters,
1850
1905
  listIdentityGetters: metadata.listIdentityGetters
1851
1906
  })
1852
1907
  };
@@ -1902,7 +1957,8 @@ function createToolExecuteResult(input) {
1902
1957
  };
1903
1958
  const targets = buildTargets(
1904
1959
  resultRoot,
1905
- input.metadata.resultIdentityGetters
1960
+ input.metadata.extractors,
1961
+ input.metadata.targetGetters
1906
1962
  );
1907
1963
  const resolvedLists = resolveListRows(
1908
1964
  resultRoot,
@@ -1913,6 +1969,7 @@ function createToolExecuteResult(input) {
1913
1969
  toolId: input.metadata.toolId,
1914
1970
  execution: input.execution,
1915
1971
  targets,
1972
+ ...input.metadata.extractors ? { extractors: input.metadata.extractors } : {},
1916
1973
  lists
1917
1974
  };
1918
1975
  const toolResponse = {
@@ -2208,6 +2265,28 @@ function stringArrayRecord(value) {
2208
2265
  function stringArray(value) {
2209
2266
  return Array.isArray(value) ? value.map(String) : [];
2210
2267
  }
2268
+ function extractorDescriptorRecord(value) {
2269
+ if (!isRecord3(value)) return {};
2270
+ return Object.fromEntries(
2271
+ Object.entries(value).flatMap(([key, descriptor]) => {
2272
+ if (!isRecord3(descriptor)) return [];
2273
+ const paths = stringArray(descriptor.paths).map((path) => path.trim()).filter(Boolean);
2274
+ if (paths.length === 0) return [];
2275
+ const transforms = stringArray(descriptor.transforms).map((transform) => transform.trim()).filter(Boolean);
2276
+ const enumValues = stringArray(descriptor.enum).map((entry) => entry.trim()).filter(Boolean);
2277
+ return [
2278
+ [
2279
+ key,
2280
+ {
2281
+ paths,
2282
+ ...transforms.length > 0 ? { transforms } : {},
2283
+ ...enumValues.length > 0 ? { enum: enumValues } : {}
2284
+ }
2285
+ ]
2286
+ ];
2287
+ })
2288
+ );
2289
+ }
2211
2290
  function toolExecutionEnvelopeToResult(fallbackToolId, response) {
2212
2291
  const raw = response.toolResponse?.raw ?? null;
2213
2292
  const meta = response.toolResponse?.meta;
@@ -2222,8 +2301,9 @@ function toolExecutionEnvelopeToResult(fallbackToolId, response) {
2222
2301
  },
2223
2302
  metadata: {
2224
2303
  toolId: typeof toolMetadata.toolId === "string" ? toolMetadata.toolId : fallbackToolId,
2225
- resultIdentityGetters: stringArrayRecord(
2226
- toolMetadata.resultIdentityGetters
2304
+ extractors: extractorDescriptorRecord(toolMetadata.extractors),
2305
+ targetGetters: stringArrayRecord(
2306
+ toolMetadata.targetGetters
2227
2307
  ),
2228
2308
  listExtractorPaths: stringArray(toolMetadata.listExtractorPaths),
2229
2309
  listIdentityGetters: stringArrayRecord(toolMetadata.listIdentityGetters)
@@ -1314,12 +1314,44 @@ function parseExecuteToolMetadata(
1314
1314
  : toolId;
1315
1315
  return {
1316
1316
  toolId: metadataToolId,
1317
- resultIdentityGetters: parseGetterMetadata(record.resultIdentityGetters),
1317
+ extractors: parseExtractorMetadata(record.extractors),
1318
+ targetGetters: parseGetterMetadata(record.targetGetters),
1318
1319
  listExtractorPaths: parseStringArray(record.listExtractorPaths),
1319
1320
  listIdentityGetters: parseGetterMetadata(record.listIdentityGetters),
1320
1321
  };
1321
1322
  }
1322
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
+
1323
1355
  function parseGetterMetadata(
1324
1356
  value: unknown,
1325
1357
  ): Record<string, readonly string[]> | undefined {
@@ -1345,7 +1377,7 @@ function syntheticToolMetadata(toolId: string): ToolResultMetadataInput {
1345
1377
  if (toolId === 'test_rate_limit') {
1346
1378
  return {
1347
1379
  toolId,
1348
- resultIdentityGetters: {
1380
+ targetGetters: {
1349
1381
  email: ['email', 'value'],
1350
1382
  },
1351
1383
  };
@@ -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
  /**
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.42";
2
- export const SDK_API_CONTRACT = "2026-05-play-tool-result-errors";
1
+ export const SDK_VERSION = "0.1.45";
2
+ export const SDK_API_CONTRACT = "2026-05-promo-redemption-policy";
@@ -14,6 +14,7 @@ import type {
14
14
  SerializedToolExecuteResult,
15
15
  ToolExecuteResult,
16
16
  ToolResultExecutionMetadata,
17
+ ToolResultExtractorDescriptor,
17
18
  ToolResultListAccessor,
18
19
  ToolResultListMetadata,
19
20
  ToolResultEnvelope,
@@ -95,9 +96,7 @@ export function toV2RawToolOutputPath(path: string): string {
95
96
  .replace(/^result\.?/, '')
96
97
  .replace(/^data\.?/, '')
97
98
  .replace(/^\./, '');
98
- return rawPath
99
- ? `toolResponse.raw.${rawPath}`
100
- : 'toolResponse.raw';
99
+ return rawPath ? `toolResponse.raw.${rawPath}` : 'toolResponse.raw';
101
100
  }
102
101
 
103
102
  function isMeaningfulValue(value: unknown): boolean {
@@ -199,12 +198,8 @@ function toV2RawToolOutputPathPreservingProviderData(path: string): string {
199
198
  ) {
200
199
  return normalized;
201
200
  }
202
- const rawPath = normalized
203
- .replace(/^result\.?/, '')
204
- .replace(/^\./, '');
205
- return rawPath
206
- ? `toolResponse.raw.${rawPath}`
207
- : 'toolResponse.raw';
201
+ const rawPath = normalized.replace(/^result\.?/, '').replace(/^\./, '');
202
+ return rawPath ? `toolResponse.raw.${rawPath}` : 'toolResponse.raw';
208
203
  }
209
204
 
210
205
  function candidateResultPaths(path: string): string[] {
@@ -324,6 +319,61 @@ function findFirstTargetByKey(
324
319
  return null;
325
320
  }
326
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
+
327
377
  function resolveListRows(
328
378
  result: unknown,
329
379
  listExtractorPaths: readonly string[] | undefined,
@@ -335,11 +385,8 @@ function resolveListRows(
335
385
  for (const rawPath of listExtractorPaths ?? []) {
336
386
  const path = normalizeResultPath(rawPath);
337
387
  if (!path) continue;
338
- const candidates = [
339
- ...candidateResultPaths(rawPath),
340
- ].filter(
341
- (candidate, index, all) =>
342
- candidate && all.indexOf(candidate) === index,
388
+ const candidates = [...candidateResultPaths(rawPath)].filter(
389
+ (candidate, index, all) => candidate && all.indexOf(candidate) === index,
343
390
  );
344
391
  let resolvedPath: string | null = null;
345
392
  let rows: Record<string, unknown>[] | null = null;
@@ -365,7 +412,7 @@ function resolveListRows(
365
412
  function deriveListKeys(input: {
366
413
  listPath: string;
367
414
  rows: readonly Record<string, unknown>[];
368
- resultIdentityGetters?: Record<string, readonly string[]>;
415
+ targetGetters?: Record<string, readonly string[]>;
369
416
  listIdentityGetters?: Record<string, readonly string[]>;
370
417
  }): Record<string, string> {
371
418
  const keys: Record<string, string> = {};
@@ -373,9 +420,7 @@ function deriveListKeys(input: {
373
420
  input.listIdentityGetters ?? {},
374
421
  )) {
375
422
  const firstPath = paths
376
- .map((rawPath) =>
377
- normalizeRelativePath(rawPath),
378
- )
423
+ .map((rawPath) => normalizeRelativePath(rawPath))
379
424
  .find(Boolean);
380
425
  if (firstPath) {
381
426
  keys[target] = firstPath;
@@ -387,7 +432,7 @@ function deriveListKeys(input: {
387
432
 
388
433
  const listPrefix = input.listPath.replace(/\[\d+\]$/, '');
389
434
  for (const [target, paths] of Object.entries(
390
- input.resultIdentityGetters ?? {},
435
+ input.targetGetters ?? {},
391
436
  )) {
392
437
  for (const rawPath of paths) {
393
438
  const path = String(rawPath || '')
@@ -431,14 +476,27 @@ function deriveListKeys(input: {
431
476
 
432
477
  function buildTargets(
433
478
  result: unknown,
434
- resultIdentityGetters?: Record<string, readonly string[]>,
479
+ extractors?: Record<string, ToolResultExtractorDescriptor>,
480
+ targetGetters?: Record<string, readonly string[]>,
435
481
  ): Record<string, ToolResultTargetMetadata> {
436
482
  const targets: Record<string, ToolResultTargetMetadata> = {};
437
- 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 ?? {}));
438
495
  for (const target of metadataTargets) {
496
+ if (targets[target]) continue;
439
497
  const fromMetadata = findFirstTargetByPath(
440
498
  result,
441
- resultIdentityGetters?.[target],
499
+ targetGetters?.[target],
442
500
  );
443
501
  if (fromMetadata) {
444
502
  targets[target] = fromMetadata;
@@ -470,7 +528,7 @@ function buildLists(
470
528
  keys: deriveListKeys({
471
529
  listPath: list.path,
472
530
  rows: list.rows,
473
- resultIdentityGetters: metadata.resultIdentityGetters,
531
+ targetGetters: metadata.targetGetters,
474
532
  listIdentityGetters: metadata.listIdentityGetters,
475
533
  }),
476
534
  };
@@ -541,7 +599,8 @@ export function createToolExecuteResult<TResult = unknown>(input: {
541
599
  };
542
600
  const targets = buildTargets(
543
601
  resultRoot,
544
- input.metadata.resultIdentityGetters,
602
+ input.metadata.extractors,
603
+ input.metadata.targetGetters,
545
604
  );
546
605
  const resolvedLists = resolveListRows(
547
606
  resultRoot,
@@ -552,6 +611,9 @@ export function createToolExecuteResult<TResult = unknown>(input: {
552
611
  toolId: input.metadata.toolId,
553
612
  execution: input.execution,
554
613
  targets,
614
+ ...(input.metadata.extractors
615
+ ? { extractors: input.metadata.extractors }
616
+ : {}),
555
617
  lists,
556
618
  };
557
619
  const toolResponse = {
@@ -599,7 +661,10 @@ function metadataInputFromToolExecuteResult(
599
661
  ): ToolResultMetadataInput {
600
662
  return {
601
663
  toolId: value._metadata.toolId,
602
- resultIdentityGetters: Object.fromEntries(
664
+ ...(value._metadata.extractors
665
+ ? { extractors: value._metadata.extractors }
666
+ : {}),
667
+ targetGetters: Object.fromEntries(
603
668
  Object.entries(value._metadata.targets).map(([target, info]) => [
604
669
  target,
605
670
  [info.path],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.42",
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": {