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 +6 -30
- package/dist/cli/index.mjs +6 -30
- package/dist/index.d.mts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +97 -17
- package/dist/index.mjs +97 -17
- package/dist/repo/apps/play-runner-workers/src/entry.ts +34 -2
- package/dist/repo/sdk/src/client.ts +1 -1
- package/dist/repo/sdk/src/play.ts +38 -3
- package/dist/repo/sdk/src/types.ts +18 -0
- package/dist/repo/sdk/src/version.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +90 -25
- package/package.json +1 -1
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.
|
|
220
|
-
var SDK_API_CONTRACT = "2026-05-
|
|
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/
|
|
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
|
-
|
|
9284
|
-
|
|
9285
|
-
|
|
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) {
|
package/dist/cli/index.mjs
CHANGED
|
@@ -193,8 +193,8 @@ function resolveConfig(options) {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// src/version.ts
|
|
196
|
-
var SDK_VERSION = "0.1.
|
|
197
|
-
var SDK_API_CONTRACT = "2026-05-
|
|
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/
|
|
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
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
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.
|
|
1497
|
-
declare const SDK_API_CONTRACT = "2026-05-
|
|
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.
|
|
1497
|
-
declare const SDK_API_CONTRACT = "2026-05-
|
|
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.
|
|
219
|
-
var SDK_API_CONTRACT = "2026-05-
|
|
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/
|
|
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.
|
|
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,
|
|
1905
|
+
function buildTargets(result, extractors, targetGetters) {
|
|
1863
1906
|
const targets = {};
|
|
1864
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
2272
|
-
|
|
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.
|
|
173
|
-
var SDK_API_CONTRACT = "2026-05-
|
|
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/
|
|
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.
|
|
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,
|
|
1859
|
+
function buildTargets(result, extractors, targetGetters) {
|
|
1817
1860
|
const targets = {};
|
|
1818
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
2226
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/
|
|
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 {
|
|
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
|
-
|
|
1119
|
-
|
|
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.
|
|
2
|
-
export const SDK_API_CONTRACT = "2026-05-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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],
|