deepline 0.1.32 → 0.1.35
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/README.md +33 -20
- package/dist/cli/index.js +1117 -381
- package/dist/cli/index.mjs +1058 -322
- package/dist/index.d.mts +131 -85
- package/dist/index.d.ts +131 -85
- package/dist/index.js +569 -124
- package/dist/index.mjs +570 -125
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +212 -1
- package/dist/repo/apps/play-runner-workers/src/dedup-do.ts +129 -2
- package/dist/repo/apps/play-runner-workers/src/entry.ts +147 -64
- package/dist/repo/apps/play-runner-workers/src/workflow-retry.ts +50 -0
- package/dist/repo/sdk/src/client.ts +46 -33
- package/dist/repo/sdk/src/config.ts +109 -233
- package/dist/repo/sdk/src/http.ts +44 -4
- package/dist/repo/sdk/src/index.ts +8 -5
- package/dist/repo/sdk/src/play.ts +124 -45
- package/dist/repo/sdk/src/plays/harness-stub.ts +2 -2
- package/dist/repo/sdk/src/tool-output.ts +26 -7
- package/dist/repo/sdk/src/types.ts +48 -12
- package/dist/repo/sdk/src/version.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/run-failure.ts +49 -0
- package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +1 -1
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +138 -35
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -85,13 +85,12 @@ var ConfigError = class extends DeeplineError {
|
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
// src/config.ts
|
|
88
|
+
var HOST_URL_ENV = "DEEPLINE_HOST_URL";
|
|
89
|
+
var API_KEY_ENV = "DEEPLINE_API_KEY";
|
|
88
90
|
var PROD_URL = "https://code.deepline.com";
|
|
89
91
|
var DEFAULT_TIMEOUT = 6e4;
|
|
90
92
|
var DEFAULT_MAX_RETRIES = 3;
|
|
91
|
-
var
|
|
92
|
-
function projectEnvStartDir() {
|
|
93
|
-
return process.env.DEEPLINE_PROJECT_ENV_DIR?.trim() || process.cwd();
|
|
94
|
-
}
|
|
93
|
+
var PROJECT_DEEPLINE_ENV_FILE = ".env.deepline";
|
|
95
94
|
function baseUrlSlug(baseUrl) {
|
|
96
95
|
let url;
|
|
97
96
|
try {
|
|
@@ -100,7 +99,7 @@ function baseUrlSlug(baseUrl) {
|
|
|
100
99
|
return "unknown";
|
|
101
100
|
}
|
|
102
101
|
const host = url.hostname || "unknown";
|
|
103
|
-
const port = url.port ? parseInt(url.port, 10) : null;
|
|
102
|
+
const port = url.port ? Number.parseInt(url.port, 10) : null;
|
|
104
103
|
let slug = host.replace(/[^a-zA-Z0-9]/g, "-");
|
|
105
104
|
if (port && port !== 80 && port !== 443) {
|
|
106
105
|
slug = `${slug}-${port}`;
|
|
@@ -127,109 +126,84 @@ function parseEnvFile(filePath) {
|
|
|
127
126
|
}
|
|
128
127
|
return env;
|
|
129
128
|
}
|
|
130
|
-
function findNearestEnvFile(
|
|
129
|
+
function findNearestEnvFile(name, startDir = process.cwd()) {
|
|
131
130
|
let current = (0, import_node_path.resolve)(startDir);
|
|
132
131
|
while (true) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if ((0, import_node_fs.existsSync)(filePath)) return filePath;
|
|
136
|
-
}
|
|
132
|
+
const filePath = (0, import_node_path.join)(current, name);
|
|
133
|
+
if ((0, import_node_fs.existsSync)(filePath)) return filePath;
|
|
137
134
|
const parent = (0, import_node_path.dirname)(current);
|
|
138
135
|
if (parent === current) return null;
|
|
139
136
|
current = parent;
|
|
140
137
|
}
|
|
141
138
|
}
|
|
142
|
-
function
|
|
143
|
-
const filePath = findNearestEnvFile(
|
|
139
|
+
function loadProjectDeeplineEnv(startDir = process.cwd()) {
|
|
140
|
+
const filePath = findNearestEnvFile(PROJECT_DEEPLINE_ENV_FILE, startDir);
|
|
144
141
|
return filePath ? parseEnvFile(filePath) : {};
|
|
145
142
|
}
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
function resolveProfileEnvFileNames() {
|
|
150
|
-
const explicitProfile = process.env.DEEPLINE_ENV_PROFILE?.trim() || process.env.DEEPLINE_PROFILE?.trim() || "";
|
|
151
|
-
const names = [];
|
|
152
|
-
if (explicitProfile) names.push(`.env.deepline.${explicitProfile}`);
|
|
153
|
-
const nodeEnv = process.env.NODE_ENV?.trim();
|
|
154
|
-
if (nodeEnv === "production") names.push(".env.deepline.prod");
|
|
155
|
-
else if (nodeEnv === "staging") names.push(".env.deepline.staging");
|
|
156
|
-
names.push(ACTIVE_DEEPLINE_ENV_FILE);
|
|
157
|
-
return names;
|
|
158
|
-
}
|
|
159
|
-
function resolveProjectAppEnvFileNames() {
|
|
160
|
-
const nodeEnv = process.env.NODE_ENV?.trim();
|
|
161
|
-
const names = [];
|
|
162
|
-
if (nodeEnv === "production") names.push(".env.prod");
|
|
163
|
-
if (nodeEnv === "staging") names.push(".env.staging");
|
|
164
|
-
names.push(".env.local", ".env");
|
|
165
|
-
return names;
|
|
166
|
-
}
|
|
167
|
-
function resolveBaseUrlFromEnvValues(env) {
|
|
168
|
-
return env.DEEPLINE_ORIGIN_URL?.trim() || env.DEEPLINE_API_BASE_URL?.trim() || "";
|
|
169
|
-
}
|
|
170
|
-
function loadProjectDeeplineEnv() {
|
|
171
|
-
return findNearestEnv(resolveProfileEnvFileNames(), projectEnvStartDir());
|
|
172
|
-
}
|
|
173
|
-
function loadProjectAppEnv() {
|
|
174
|
-
return findNearestEnv(resolveProjectAppEnvFileNames(), projectEnvStartDir());
|
|
175
|
-
}
|
|
176
|
-
function normalizeWorktreeBaseUrl(baseUrl, worktreeEnv = findNearestWorktreeEnv()) {
|
|
177
|
-
const trimmed = baseUrl.trim().replace(/\/$/, "");
|
|
178
|
-
if (!trimmed) return trimmed;
|
|
143
|
+
function normalizeBaseUrl(baseUrl) {
|
|
144
|
+
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
145
|
+
if (!trimmed) return "";
|
|
179
146
|
try {
|
|
180
147
|
const parsed = new URL(trimmed);
|
|
181
|
-
if (parsed.
|
|
182
|
-
|
|
183
|
-
if (port) return `${parsed.protocol}//localhost:${port}`;
|
|
148
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
149
|
+
return "";
|
|
184
150
|
}
|
|
151
|
+
return parsed.toString().replace(/\/+$/, "");
|
|
185
152
|
} catch {
|
|
153
|
+
return "";
|
|
186
154
|
}
|
|
187
|
-
return trimmed;
|
|
188
155
|
}
|
|
189
|
-
function
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return
|
|
156
|
+
function firstNonEmpty(...values) {
|
|
157
|
+
for (const value of values) {
|
|
158
|
+
const trimmed = value?.trim();
|
|
159
|
+
if (trimmed) return trimmed;
|
|
160
|
+
}
|
|
161
|
+
return "";
|
|
195
162
|
}
|
|
196
|
-
function
|
|
163
|
+
function sdkCliConfigDir(baseUrl) {
|
|
197
164
|
const home = process.env.HOME?.trim() || (0, import_node_os.homedir)();
|
|
198
|
-
return (0, import_node_path.join)(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL)
|
|
165
|
+
return (0, import_node_path.join)(home, ".local", "deepline", baseUrlSlug(baseUrl || PROD_URL));
|
|
166
|
+
}
|
|
167
|
+
function sdkCliEnvFilePath(baseUrl) {
|
|
168
|
+
return (0, import_node_path.join)(sdkCliConfigDir(baseUrl), ".env");
|
|
199
169
|
}
|
|
200
170
|
function loadCliEnv(baseUrl = PROD_URL) {
|
|
201
|
-
|
|
202
|
-
return parseEnvFile(envPath);
|
|
171
|
+
return parseEnvFile(sdkCliEnvFilePath(baseUrl));
|
|
203
172
|
}
|
|
204
173
|
function loadGlobalCliEnv() {
|
|
205
174
|
return loadCliEnv(PROD_URL);
|
|
206
175
|
}
|
|
207
176
|
function autoDetectBaseUrl() {
|
|
208
|
-
const
|
|
209
|
-
if (envOrigin) return normalizeWorktreeBaseUrl(envOrigin);
|
|
210
|
-
const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();
|
|
211
|
-
if (envBase) return normalizeWorktreeBaseUrl(envBase);
|
|
212
|
-
const projectDeeplineBaseUrl = resolveBaseUrlFromEnvValues(loadProjectDeeplineEnv());
|
|
213
|
-
if (projectDeeplineBaseUrl) return normalizeWorktreeBaseUrl(projectDeeplineBaseUrl);
|
|
214
|
-
const projectAppBaseUrl = resolveBaseUrlFromEnvValues(loadProjectAppEnv());
|
|
215
|
-
if (projectAppBaseUrl) return normalizeWorktreeBaseUrl(projectAppBaseUrl);
|
|
216
|
-
const worktreeBaseUrl = resolveWorktreeBaseUrl();
|
|
217
|
-
if (worktreeBaseUrl) return worktreeBaseUrl;
|
|
177
|
+
const projectEnv = loadProjectDeeplineEnv();
|
|
218
178
|
const globalEnv = loadGlobalCliEnv();
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
179
|
+
return normalizeBaseUrl(process.env[HOST_URL_ENV] ?? "") || normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "") || normalizeBaseUrl(globalEnv[HOST_URL_ENV] ?? "") || PROD_URL;
|
|
180
|
+
}
|
|
181
|
+
function resolveApiKeyForBaseUrl(baseUrl, explicitApiKey) {
|
|
182
|
+
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
183
|
+
const projectEnv = loadProjectDeeplineEnv();
|
|
184
|
+
const cliEnv = loadCliEnv(normalizedBaseUrl || baseUrl);
|
|
185
|
+
const projectBaseUrl = normalizeBaseUrl(projectEnv[HOST_URL_ENV] ?? "");
|
|
186
|
+
const projectKeyApplies = projectBaseUrl === normalizedBaseUrl;
|
|
187
|
+
return firstNonEmpty(
|
|
188
|
+
explicitApiKey,
|
|
189
|
+
process.env[API_KEY_ENV],
|
|
190
|
+
projectKeyApplies ? projectEnv[API_KEY_ENV] : "",
|
|
191
|
+
cliEnv[API_KEY_ENV]
|
|
192
|
+
);
|
|
222
193
|
}
|
|
223
194
|
function resolveConfig(options) {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
195
|
+
const baseUrl = normalizeBaseUrl(
|
|
196
|
+
options?.baseUrl?.trim() || autoDetectBaseUrl()
|
|
197
|
+
);
|
|
198
|
+
if (!baseUrl) {
|
|
199
|
+
throw new ConfigError(
|
|
200
|
+
`Invalid ${HOST_URL_ENV}. Expected an http(s) URL such as https://code.deepline.com.`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
const apiKey = resolveApiKeyForBaseUrl(baseUrl, options?.apiKey);
|
|
230
204
|
if (!apiKey) {
|
|
231
205
|
throw new ConfigError(
|
|
232
|
-
`No API key found. Set
|
|
206
|
+
`No API key found. Set ${API_KEY_ENV}, add it to .env.deepline, or run: deepline auth register`
|
|
233
207
|
);
|
|
234
208
|
}
|
|
235
209
|
return {
|
|
@@ -241,8 +215,8 @@ function resolveConfig(options) {
|
|
|
241
215
|
}
|
|
242
216
|
|
|
243
217
|
// src/version.ts
|
|
244
|
-
var SDK_VERSION = "0.1.
|
|
245
|
-
var SDK_API_CONTRACT = "2026-05-
|
|
218
|
+
var SDK_VERSION = "0.1.35";
|
|
219
|
+
var SDK_API_CONTRACT = "2026-05-v2-tool-result-contract";
|
|
246
220
|
|
|
247
221
|
// ../shared_libs/play-runtime/coordinator-headers.ts
|
|
248
222
|
var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
|
|
@@ -324,7 +298,7 @@ var HttpClient = class {
|
|
|
324
298
|
const response = await fetch(candidateUrl, {
|
|
325
299
|
method,
|
|
326
300
|
headers,
|
|
327
|
-
body: options?.formData !== void 0 ? options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
301
|
+
body: options?.formData !== void 0 ? typeof options.formData === "function" ? options.formData() : options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
328
302
|
signal: controller.signal
|
|
329
303
|
});
|
|
330
304
|
clearTimeout(timeoutId);
|
|
@@ -407,10 +381,13 @@ var HttpClient = class {
|
|
|
407
381
|
throw new AuthError();
|
|
408
382
|
}
|
|
409
383
|
if (!response.ok) {
|
|
384
|
+
const body = await response.text();
|
|
385
|
+
const parsed = parseResponseBody(body);
|
|
410
386
|
throw new DeeplineError(
|
|
411
|
-
|
|
387
|
+
apiErrorMessage(parsed, response.status),
|
|
412
388
|
response.status,
|
|
413
|
-
"API_ERROR"
|
|
389
|
+
"API_ERROR",
|
|
390
|
+
{ response: parsed }
|
|
414
391
|
);
|
|
415
392
|
}
|
|
416
393
|
if (!response.body) {
|
|
@@ -460,6 +437,26 @@ var HttpClient = class {
|
|
|
460
437
|
return this.request(path, { method: "DELETE" });
|
|
461
438
|
}
|
|
462
439
|
};
|
|
440
|
+
function parseResponseBody(body) {
|
|
441
|
+
try {
|
|
442
|
+
return JSON.parse(body);
|
|
443
|
+
} catch {
|
|
444
|
+
return body;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function apiErrorMessage(parsed, status) {
|
|
448
|
+
const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
|
|
449
|
+
if (typeof errorValue === "string") {
|
|
450
|
+
return errorValue;
|
|
451
|
+
}
|
|
452
|
+
if (errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string") {
|
|
453
|
+
return errorValue.message;
|
|
454
|
+
}
|
|
455
|
+
if (typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string") {
|
|
456
|
+
return parsed.message;
|
|
457
|
+
}
|
|
458
|
+
return `HTTP ${status}`;
|
|
459
|
+
}
|
|
463
460
|
function parseRetryAfter(response) {
|
|
464
461
|
const header = response.headers.get("retry-after");
|
|
465
462
|
if (header) {
|
|
@@ -529,6 +526,8 @@ function sleep(ms) {
|
|
|
529
526
|
// src/client.ts
|
|
530
527
|
var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
531
528
|
var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
|
|
529
|
+
var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
|
|
530
|
+
var V2_EXECUTE_RESPONSE_CONTRACT = "v2-tool-execution-result";
|
|
532
531
|
var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
|
|
533
532
|
function sleep2(ms) {
|
|
534
533
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
@@ -797,13 +796,16 @@ var DeeplineClient = class {
|
|
|
797
796
|
/**
|
|
798
797
|
* Execute a tool and return the standard execution envelope.
|
|
799
798
|
*
|
|
800
|
-
* The `
|
|
801
|
-
* contains provider
|
|
799
|
+
* The `toolExecutionResult.toolOutput.raw` field contains the raw tool output.
|
|
800
|
+
* `toolExecutionResult.toolOutput.meta` contains tool/provider metadata.
|
|
802
801
|
* Top-level fields such as `status`, `job_id`, and `billing` describe the
|
|
803
|
-
* Deepline execution.
|
|
802
|
+
* Deepline execution envelope.
|
|
804
803
|
*/
|
|
805
804
|
async executeTool(toolId, input, options) {
|
|
806
|
-
const headers =
|
|
805
|
+
const headers = {
|
|
806
|
+
[EXECUTE_RESPONSE_CONTRACT_HEADER]: V2_EXECUTE_RESPONSE_CONTRACT,
|
|
807
|
+
...options?.includeToolMetadata ? { [INCLUDE_TOOL_METADATA_HEADER]: "true" } : {}
|
|
808
|
+
};
|
|
807
809
|
return this.http.post(
|
|
808
810
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
809
811
|
{ payload: input },
|
|
@@ -1101,34 +1103,37 @@ var DeeplineClient = class {
|
|
|
1101
1103
|
* ```
|
|
1102
1104
|
*/
|
|
1103
1105
|
async stagePlayFiles(files) {
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
"metadata",
|
|
1107
|
-
JSON.stringify({
|
|
1108
|
-
files: files.map((file, index) => ({
|
|
1109
|
-
index,
|
|
1110
|
-
logicalPath: file.logicalPath,
|
|
1111
|
-
contentHash: file.contentHash,
|
|
1112
|
-
contentType: file.contentType,
|
|
1113
|
-
bytes: file.bytes
|
|
1114
|
-
}))
|
|
1115
|
-
})
|
|
1116
|
-
);
|
|
1117
|
-
for (const [index, file] of files.entries()) {
|
|
1118
|
-
const bytes = decodeBase64Bytes(file.contentBase64);
|
|
1119
|
-
const body = bytes.buffer.slice(
|
|
1120
|
-
bytes.byteOffset,
|
|
1121
|
-
bytes.byteOffset + bytes.byteLength
|
|
1122
|
-
);
|
|
1106
|
+
const buildFormData = () => {
|
|
1107
|
+
const formData = new FormData();
|
|
1123
1108
|
formData.set(
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1109
|
+
"metadata",
|
|
1110
|
+
JSON.stringify({
|
|
1111
|
+
files: files.map((file, index) => ({
|
|
1112
|
+
index,
|
|
1113
|
+
logicalPath: file.logicalPath,
|
|
1114
|
+
contentHash: file.contentHash,
|
|
1115
|
+
contentType: file.contentType,
|
|
1116
|
+
bytes: file.bytes
|
|
1117
|
+
}))
|
|
1118
|
+
})
|
|
1127
1119
|
);
|
|
1128
|
-
|
|
1120
|
+
for (const [index, file] of files.entries()) {
|
|
1121
|
+
const bytes = decodeBase64Bytes(file.contentBase64);
|
|
1122
|
+
const body = bytes.buffer.slice(
|
|
1123
|
+
bytes.byteOffset,
|
|
1124
|
+
bytes.byteOffset + bytes.byteLength
|
|
1125
|
+
);
|
|
1126
|
+
formData.set(
|
|
1127
|
+
`file:${index}`,
|
|
1128
|
+
new Blob([body], { type: file.contentType }),
|
|
1129
|
+
file.logicalPath
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
return formData;
|
|
1133
|
+
};
|
|
1129
1134
|
const response = await this.http.postFormData(
|
|
1130
1135
|
"/api/v2/plays/files/stage",
|
|
1131
|
-
|
|
1136
|
+
buildFormData
|
|
1132
1137
|
);
|
|
1133
1138
|
return response.files;
|
|
1134
1139
|
}
|
|
@@ -1602,6 +1607,383 @@ var DeeplineClient = class {
|
|
|
1602
1607
|
}
|
|
1603
1608
|
};
|
|
1604
1609
|
|
|
1610
|
+
// ../shared_libs/play-runtime/tool-result.ts
|
|
1611
|
+
var TARGET_FALLBACK_KEYS = {
|
|
1612
|
+
email: [/^email$/i, /^address$/i, /email/i],
|
|
1613
|
+
phone: [/^phone$/i, /mobile/i, /phone/i, /telephone/i],
|
|
1614
|
+
linkedin: [/^linkedin_url$/i, /^linkedin$/i, /linkedin/i],
|
|
1615
|
+
company_linkedin_url: [/company.*linkedin/i, /linkedin.*company/i],
|
|
1616
|
+
company_domain: [/^company_domain$/i, /company.*domain/i],
|
|
1617
|
+
company_name: [/^company_name$/i, /company.*name/i],
|
|
1618
|
+
domain: [/^domain$/i, /company_domain/i, /domain/i],
|
|
1619
|
+
status: [/^email_status$/i, /^status$/i],
|
|
1620
|
+
email_status: [/^email_status$/i, /^status$/i]
|
|
1621
|
+
};
|
|
1622
|
+
function isRecord2(value) {
|
|
1623
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1624
|
+
}
|
|
1625
|
+
function toV2RawToolOutputPath(path) {
|
|
1626
|
+
const normalized = String(path || "").trim().replace(/^\./, "");
|
|
1627
|
+
if (!normalized) return "toolExecutionResult.toolOutput.raw";
|
|
1628
|
+
if (normalized === "toolExecutionResult.toolOutput.raw" || normalized.startsWith("toolExecutionResult.toolOutput.raw.")) {
|
|
1629
|
+
return normalized;
|
|
1630
|
+
}
|
|
1631
|
+
const rawPath = normalized.replace(/^result\.data\.?/, "").replace(/^result\.?/, "").replace(/^data\.?/, "").replace(/^\./, "");
|
|
1632
|
+
return rawPath ? `toolExecutionResult.toolOutput.raw.${rawPath}` : "toolExecutionResult.toolOutput.raw";
|
|
1633
|
+
}
|
|
1634
|
+
function isMeaningfulValue(value) {
|
|
1635
|
+
if (value == null) return false;
|
|
1636
|
+
if (typeof value === "string") return value.trim().length > 0;
|
|
1637
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
1638
|
+
if (typeof value === "object") return Object.keys(value).length > 0;
|
|
1639
|
+
return true;
|
|
1640
|
+
}
|
|
1641
|
+
function parsePath(path) {
|
|
1642
|
+
const segments = [];
|
|
1643
|
+
for (const rawPart of path.split(".").filter(Boolean)) {
|
|
1644
|
+
const bracketPattern = /([^\[\]]+)|\[(\d+|\*)\]/g;
|
|
1645
|
+
let matched = false;
|
|
1646
|
+
for (const match of rawPart.matchAll(bracketPattern)) {
|
|
1647
|
+
matched = true;
|
|
1648
|
+
if (match[1]) {
|
|
1649
|
+
segments.push(match[1]);
|
|
1650
|
+
} else if (match[2] === "*") {
|
|
1651
|
+
segments.push("*");
|
|
1652
|
+
} else if (match[2]) {
|
|
1653
|
+
segments.push(Number(match[2]));
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
if (!matched) {
|
|
1657
|
+
segments.push(rawPart);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return segments;
|
|
1661
|
+
}
|
|
1662
|
+
function pathToString(segments) {
|
|
1663
|
+
return segments.map(
|
|
1664
|
+
(segment, index) => typeof segment === "number" ? `[${segment}]` : segment === "*" ? "[*]" : index === 0 ? segment : `.${segment}`
|
|
1665
|
+
).join("");
|
|
1666
|
+
}
|
|
1667
|
+
function valuesAtSegments(current, segments, path = []) {
|
|
1668
|
+
if (segments.length === 0) {
|
|
1669
|
+
return [{ value: current, path: pathToString(path) }];
|
|
1670
|
+
}
|
|
1671
|
+
const [segment, ...rest] = segments;
|
|
1672
|
+
if (segment === "*") {
|
|
1673
|
+
if (!Array.isArray(current)) return [];
|
|
1674
|
+
return current.flatMap(
|
|
1675
|
+
(entry, index) => valuesAtSegments(entry, rest, [...path, index])
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
if (typeof segment === "number") {
|
|
1679
|
+
if (!Array.isArray(current)) return [];
|
|
1680
|
+
return valuesAtSegments(current[segment], rest, [...path, segment]);
|
|
1681
|
+
}
|
|
1682
|
+
if (!isRecord2(current)) return [];
|
|
1683
|
+
return valuesAtSegments(current[segment], rest, [...path, segment]);
|
|
1684
|
+
}
|
|
1685
|
+
function getValuesAtPath(root, path) {
|
|
1686
|
+
return valuesAtSegments(root, parsePath(path)).map((entry) => entry.value);
|
|
1687
|
+
}
|
|
1688
|
+
function toResultEnvelope(value) {
|
|
1689
|
+
if (isRecord2(value) && "data" in value) {
|
|
1690
|
+
const envelope = { data: value.data };
|
|
1691
|
+
if ("meta" in value) envelope.meta = value.meta;
|
|
1692
|
+
return envelope;
|
|
1693
|
+
}
|
|
1694
|
+
return { data: value };
|
|
1695
|
+
}
|
|
1696
|
+
function normalizeResultPath(path) {
|
|
1697
|
+
const trimmed = String(path || "").trim().replace(/^\./, "");
|
|
1698
|
+
if (!trimmed) return "";
|
|
1699
|
+
return toV2RawToolOutputPath(trimmed);
|
|
1700
|
+
}
|
|
1701
|
+
function toV2RawToolOutputPathPreservingProviderData(path) {
|
|
1702
|
+
const normalized = String(path || "").trim().replace(/^\./, "");
|
|
1703
|
+
if (!normalized) return "toolExecutionResult.toolOutput.raw";
|
|
1704
|
+
if (normalized === "toolExecutionResult.toolOutput.raw" || normalized.startsWith("toolExecutionResult.toolOutput.raw.")) {
|
|
1705
|
+
return normalized;
|
|
1706
|
+
}
|
|
1707
|
+
const rawPath = normalized.replace(/^result\.?/, "").replace(/^\./, "");
|
|
1708
|
+
return rawPath ? `toolExecutionResult.toolOutput.raw.${rawPath}` : "toolExecutionResult.toolOutput.raw";
|
|
1709
|
+
}
|
|
1710
|
+
function candidateResultPaths(path) {
|
|
1711
|
+
const candidates = [
|
|
1712
|
+
normalizeResultPath(path),
|
|
1713
|
+
toV2RawToolOutputPathPreservingProviderData(path)
|
|
1714
|
+
];
|
|
1715
|
+
return candidates.filter(
|
|
1716
|
+
(candidate, index, all) => candidate.length > 0 && all.indexOf(candidate) === index
|
|
1717
|
+
);
|
|
1718
|
+
}
|
|
1719
|
+
function normalizeRelativePath(path) {
|
|
1720
|
+
return String(path || "").trim().replace(/^result\./, "").replace(/^\./, "");
|
|
1721
|
+
}
|
|
1722
|
+
function getFirstMeaningfulValueAtPath(root, path) {
|
|
1723
|
+
for (const entry of valuesAtSegments(root, parsePath(path))) {
|
|
1724
|
+
if (isMeaningfulValue(entry.value)) {
|
|
1725
|
+
return { value: entry.value, path: entry.path };
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
return null;
|
|
1729
|
+
}
|
|
1730
|
+
function getAtPath(root, path) {
|
|
1731
|
+
const segments = parsePath(path);
|
|
1732
|
+
if (segments.includes("*")) {
|
|
1733
|
+
return getValuesAtPath(root, path).filter(isMeaningfulValue);
|
|
1734
|
+
}
|
|
1735
|
+
let current = root;
|
|
1736
|
+
for (const segment of segments) {
|
|
1737
|
+
if (typeof segment === "number") {
|
|
1738
|
+
if (!Array.isArray(current)) return void 0;
|
|
1739
|
+
current = current[segment];
|
|
1740
|
+
continue;
|
|
1741
|
+
}
|
|
1742
|
+
if (!isRecord2(current)) return void 0;
|
|
1743
|
+
current = current[segment];
|
|
1744
|
+
}
|
|
1745
|
+
return current;
|
|
1746
|
+
}
|
|
1747
|
+
function normalizeRows(value) {
|
|
1748
|
+
if (!Array.isArray(value)) return null;
|
|
1749
|
+
return value.map((entry) => isRecord2(entry) ? entry : { value: entry });
|
|
1750
|
+
}
|
|
1751
|
+
function findFirstTargetByPath(result, paths) {
|
|
1752
|
+
for (const path of paths ?? []) {
|
|
1753
|
+
for (const candidate of candidateResultPaths(path)) {
|
|
1754
|
+
const match = getFirstMeaningfulValueAtPath(result, candidate);
|
|
1755
|
+
if (match) return match;
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
return null;
|
|
1759
|
+
}
|
|
1760
|
+
function findFirstTargetByKey(result, target, depth = 0, path = []) {
|
|
1761
|
+
if (depth > 6) return null;
|
|
1762
|
+
if (Array.isArray(result)) {
|
|
1763
|
+
for (let index = 0; index < result.length; index += 1) {
|
|
1764
|
+
const found = findFirstTargetByKey(result[index], target, depth + 1, [
|
|
1765
|
+
...path,
|
|
1766
|
+
index
|
|
1767
|
+
]);
|
|
1768
|
+
if (found) return found;
|
|
1769
|
+
}
|
|
1770
|
+
return null;
|
|
1771
|
+
}
|
|
1772
|
+
if (!isRecord2(result)) return null;
|
|
1773
|
+
const patterns = TARGET_FALLBACK_KEYS[target] ?? [
|
|
1774
|
+
new RegExp(`^${target}$`, "i")
|
|
1775
|
+
];
|
|
1776
|
+
for (const [key, value] of Object.entries(result)) {
|
|
1777
|
+
if (patterns.some((pattern) => pattern.test(key)) && isMeaningfulValue(value)) {
|
|
1778
|
+
return { value, path: pathToString([...path, key]) };
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
for (const [key, value] of Object.entries(result)) {
|
|
1782
|
+
const found = findFirstTargetByKey(value, target, depth + 1, [
|
|
1783
|
+
...path,
|
|
1784
|
+
key
|
|
1785
|
+
]);
|
|
1786
|
+
if (found) return found;
|
|
1787
|
+
}
|
|
1788
|
+
return null;
|
|
1789
|
+
}
|
|
1790
|
+
function resolveListRows(result, listExtractorPaths) {
|
|
1791
|
+
const lists = {};
|
|
1792
|
+
for (const rawPath of listExtractorPaths ?? []) {
|
|
1793
|
+
const path = normalizeResultPath(rawPath);
|
|
1794
|
+
if (!path) continue;
|
|
1795
|
+
const candidates = [
|
|
1796
|
+
...candidateResultPaths(rawPath)
|
|
1797
|
+
].filter(
|
|
1798
|
+
(candidate, index, all) => candidate && all.indexOf(candidate) === index
|
|
1799
|
+
);
|
|
1800
|
+
let resolvedPath = null;
|
|
1801
|
+
let rows = null;
|
|
1802
|
+
for (const candidate of candidates) {
|
|
1803
|
+
rows = normalizeRows(getAtPath(result, candidate));
|
|
1804
|
+
if (rows) {
|
|
1805
|
+
resolvedPath = candidate;
|
|
1806
|
+
break;
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
if (!rows) continue;
|
|
1810
|
+
const storedPath = resolvedPath ?? path;
|
|
1811
|
+
const name = storedPath.split(".").filter(Boolean).at(-1)?.replace(/\[\d+\]$/, "");
|
|
1812
|
+
lists[name || storedPath] = { path: storedPath, rows };
|
|
1813
|
+
}
|
|
1814
|
+
return lists;
|
|
1815
|
+
}
|
|
1816
|
+
function deriveListKeys(input) {
|
|
1817
|
+
const keys = {};
|
|
1818
|
+
for (const [target, paths] of Object.entries(
|
|
1819
|
+
input.listIdentityGetters ?? {}
|
|
1820
|
+
)) {
|
|
1821
|
+
const firstPath = paths.map(
|
|
1822
|
+
(rawPath) => normalizeRelativePath(rawPath)
|
|
1823
|
+
).find(Boolean);
|
|
1824
|
+
if (firstPath) {
|
|
1825
|
+
keys[target] = firstPath;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
if (Object.keys(keys).length > 0) {
|
|
1829
|
+
return keys;
|
|
1830
|
+
}
|
|
1831
|
+
const listPrefix = input.listPath.replace(/\[\d+\]$/, "");
|
|
1832
|
+
for (const [target, paths] of Object.entries(
|
|
1833
|
+
input.resultIdentityGetters ?? {}
|
|
1834
|
+
)) {
|
|
1835
|
+
for (const rawPath of paths) {
|
|
1836
|
+
const path = String(rawPath || "").trim().replace(/^\./, "");
|
|
1837
|
+
if (!path) continue;
|
|
1838
|
+
for (const resultPath of candidateResultPaths(path)) {
|
|
1839
|
+
const directPrefix = `${listPrefix}.`;
|
|
1840
|
+
if (resultPath.startsWith(directPrefix)) {
|
|
1841
|
+
keys[target] = resultPath.slice(directPrefix.length).replace(/^\[\d+\]\.?/, "");
|
|
1842
|
+
break;
|
|
1843
|
+
}
|
|
1844
|
+
const indexedPrefix = `${listPrefix}[0].`;
|
|
1845
|
+
if (resultPath.startsWith(indexedPrefix)) {
|
|
1846
|
+
keys[target] = resultPath.slice(indexedPrefix.length);
|
|
1847
|
+
break;
|
|
1848
|
+
}
|
|
1849
|
+
const wildcardPrefix = `${listPrefix}[*].`;
|
|
1850
|
+
if (resultPath.startsWith(wildcardPrefix)) {
|
|
1851
|
+
keys[target] = resultPath.slice(wildcardPrefix.length);
|
|
1852
|
+
break;
|
|
1853
|
+
}
|
|
1854
|
+
const dottedIndexPrefix = `${listPrefix}.0.`;
|
|
1855
|
+
if (resultPath.startsWith(dottedIndexPrefix)) {
|
|
1856
|
+
keys[target] = resultPath.slice(dottedIndexPrefix.length);
|
|
1857
|
+
break;
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
if (keys[target]) break;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
if (Object.keys(keys).length === 0 && input.rows[0]) {
|
|
1864
|
+
for (const key of Object.keys(input.rows[0])) {
|
|
1865
|
+
keys[key] = key;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
return keys;
|
|
1869
|
+
}
|
|
1870
|
+
function buildTargets(result, resultIdentityGetters) {
|
|
1871
|
+
const targets = {};
|
|
1872
|
+
const metadataTargets = new Set(Object.keys(resultIdentityGetters ?? {}));
|
|
1873
|
+
for (const target of metadataTargets) {
|
|
1874
|
+
const fromMetadata = findFirstTargetByPath(
|
|
1875
|
+
result,
|
|
1876
|
+
resultIdentityGetters?.[target]
|
|
1877
|
+
);
|
|
1878
|
+
if (fromMetadata) {
|
|
1879
|
+
targets[target] = fromMetadata;
|
|
1880
|
+
continue;
|
|
1881
|
+
}
|
|
1882
|
+
const fallback = findFirstTargetByKey(result, target);
|
|
1883
|
+
if (fallback) {
|
|
1884
|
+
targets[target] = fallback;
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
if (metadataTargets.size > 0) return targets;
|
|
1888
|
+
for (const target of ["email", "phone", "linkedin", "domain", "status"]) {
|
|
1889
|
+
const found = findFirstTargetByKey(result, target);
|
|
1890
|
+
if (found) targets[target] = found;
|
|
1891
|
+
}
|
|
1892
|
+
return targets;
|
|
1893
|
+
}
|
|
1894
|
+
function buildLists(result, metadata) {
|
|
1895
|
+
const lists = {};
|
|
1896
|
+
const resolved = resolveListRows(result, metadata.listExtractorPaths);
|
|
1897
|
+
for (const [name, list] of Object.entries(resolved)) {
|
|
1898
|
+
lists[name] = {
|
|
1899
|
+
path: list.path,
|
|
1900
|
+
count: list.rows.length,
|
|
1901
|
+
keys: deriveListKeys({
|
|
1902
|
+
listPath: list.path,
|
|
1903
|
+
rows: list.rows,
|
|
1904
|
+
resultIdentityGetters: metadata.resultIdentityGetters,
|
|
1905
|
+
listIdentityGetters: metadata.listIdentityGetters
|
|
1906
|
+
})
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
return lists;
|
|
1910
|
+
}
|
|
1911
|
+
function buildExtractedAccessors(targets) {
|
|
1912
|
+
return Object.fromEntries(
|
|
1913
|
+
Object.entries(targets).map(([target, metadata]) => {
|
|
1914
|
+
const accessor = { path: metadata.path };
|
|
1915
|
+
Object.defineProperties(accessor, {
|
|
1916
|
+
value: {
|
|
1917
|
+
value: metadata.value,
|
|
1918
|
+
enumerable: false
|
|
1919
|
+
},
|
|
1920
|
+
get: {
|
|
1921
|
+
value() {
|
|
1922
|
+
return metadata.value ?? null;
|
|
1923
|
+
},
|
|
1924
|
+
enumerable: false
|
|
1925
|
+
}
|
|
1926
|
+
});
|
|
1927
|
+
return [target, accessor];
|
|
1928
|
+
})
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
function buildListAccessors(result, lists) {
|
|
1932
|
+
return Object.fromEntries(
|
|
1933
|
+
Object.entries(lists).map(([name, metadata]) => {
|
|
1934
|
+
const accessor = {
|
|
1935
|
+
path: metadata.path,
|
|
1936
|
+
count: metadata.count,
|
|
1937
|
+
keys: metadata.keys
|
|
1938
|
+
};
|
|
1939
|
+
Object.defineProperty(accessor, "get", {
|
|
1940
|
+
value() {
|
|
1941
|
+
return normalizeRows(getAtPath(result, metadata.path)) ?? [];
|
|
1942
|
+
},
|
|
1943
|
+
enumerable: false
|
|
1944
|
+
});
|
|
1945
|
+
return [name, accessor];
|
|
1946
|
+
})
|
|
1947
|
+
);
|
|
1948
|
+
}
|
|
1949
|
+
function createToolExecuteResult(input) {
|
|
1950
|
+
const result = toResultEnvelope(input.result);
|
|
1951
|
+
const resultRoot = {
|
|
1952
|
+
toolExecutionResult: {
|
|
1953
|
+
toolOutput: {
|
|
1954
|
+
raw: result.data,
|
|
1955
|
+
...result.meta ? { meta: result.meta } : {}
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
};
|
|
1959
|
+
const targets = buildTargets(
|
|
1960
|
+
resultRoot,
|
|
1961
|
+
input.metadata.resultIdentityGetters
|
|
1962
|
+
);
|
|
1963
|
+
const lists = buildLists(resultRoot, input.metadata);
|
|
1964
|
+
const metadata = {
|
|
1965
|
+
toolId: input.metadata.toolId,
|
|
1966
|
+
execution: input.execution,
|
|
1967
|
+
targets,
|
|
1968
|
+
lists
|
|
1969
|
+
};
|
|
1970
|
+
const wrapper = {
|
|
1971
|
+
status: input.status,
|
|
1972
|
+
toolOutput: {
|
|
1973
|
+
raw: result.data,
|
|
1974
|
+
...result.meta ? { meta: result.meta } : {}
|
|
1975
|
+
},
|
|
1976
|
+
meta: input.execution,
|
|
1977
|
+
extractedValues: buildExtractedAccessors(targets),
|
|
1978
|
+
extractedLists: buildListAccessors(resultRoot, lists)
|
|
1979
|
+
};
|
|
1980
|
+
Object.defineProperty(wrapper, "_metadata", {
|
|
1981
|
+
value: metadata,
|
|
1982
|
+
enumerable: false
|
|
1983
|
+
});
|
|
1984
|
+
return wrapper;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1605
1987
|
// src/play.ts
|
|
1606
1988
|
var DeeplineConditionalStepResolver = class _DeeplineConditionalStepResolver {
|
|
1607
1989
|
constructor(when2, run, elseValue) {
|
|
@@ -1738,10 +2120,10 @@ var DeeplineContext = class {
|
|
|
1738
2120
|
*
|
|
1739
2121
|
* @example
|
|
1740
2122
|
* ```typescript
|
|
1741
|
-
* const tools = await
|
|
1742
|
-
* const meta = await
|
|
1743
|
-
* const companyLookup = await
|
|
1744
|
-
* const company = companyLookup.
|
|
2123
|
+
* const tools = await deepline.tools.list();
|
|
2124
|
+
* const meta = await deepline.tools.get('apollo_people_search');
|
|
2125
|
+
* const companyLookup = await deepline.tools.execute('test_company_search', { domain: 'stripe.com' });
|
|
2126
|
+
* const company = companyLookup.toolOutput.raw;
|
|
1745
2127
|
* ```
|
|
1746
2128
|
*/
|
|
1747
2129
|
get tools() {
|
|
@@ -1751,11 +2133,14 @@ var DeeplineContext = class {
|
|
|
1751
2133
|
/** Get detailed metadata for a tool. */
|
|
1752
2134
|
get: (toolId) => this.client.getTool(toolId),
|
|
1753
2135
|
/** Execute a tool and return the standard execution envelope. */
|
|
1754
|
-
execute: async (toolId, input) =>
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
2136
|
+
execute: async (toolId, input) => {
|
|
2137
|
+
const response = await this.client.executeTool(
|
|
2138
|
+
toolId,
|
|
2139
|
+
input,
|
|
2140
|
+
{ includeToolMetadata: true }
|
|
2141
|
+
);
|
|
2142
|
+
return toolExecutionEnvelopeToResult(toolId, response);
|
|
2143
|
+
}
|
|
1759
2144
|
};
|
|
1760
2145
|
}
|
|
1761
2146
|
get plays() {
|
|
@@ -1850,6 +2235,47 @@ var Deepline = class {
|
|
|
1850
2235
|
return new DeeplineContext(options);
|
|
1851
2236
|
}
|
|
1852
2237
|
};
|
|
2238
|
+
function isRecord3(value) {
|
|
2239
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2240
|
+
}
|
|
2241
|
+
function stringArrayRecord(value) {
|
|
2242
|
+
if (!isRecord3(value)) return {};
|
|
2243
|
+
return Object.fromEntries(
|
|
2244
|
+
Object.entries(value).map(([key, paths]) => [
|
|
2245
|
+
key,
|
|
2246
|
+
Array.isArray(paths) ? paths.map(String) : []
|
|
2247
|
+
])
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
function stringArray(value) {
|
|
2251
|
+
return Array.isArray(value) ? value.map(String) : [];
|
|
2252
|
+
}
|
|
2253
|
+
function toolExecutionEnvelopeToResult(fallbackToolId, response) {
|
|
2254
|
+
const raw = response.toolExecutionResult?.toolOutput?.raw ?? null;
|
|
2255
|
+
const meta = response.toolExecutionResult?.toolOutput?.meta;
|
|
2256
|
+
const metadata = isRecord3(response._metadata) ? response._metadata.tool : null;
|
|
2257
|
+
const toolMetadata = isRecord3(metadata) ? metadata : {};
|
|
2258
|
+
return createToolExecuteResult({
|
|
2259
|
+
status: typeof response.status === "string" ? response.status : "completed",
|
|
2260
|
+
result: {
|
|
2261
|
+
data: raw,
|
|
2262
|
+
...isRecord3(meta) ? { meta } : {}
|
|
2263
|
+
},
|
|
2264
|
+
metadata: {
|
|
2265
|
+
toolId: typeof toolMetadata.toolId === "string" ? toolMetadata.toolId : fallbackToolId,
|
|
2266
|
+
resultIdentityGetters: stringArrayRecord(
|
|
2267
|
+
toolMetadata.resultIdentityGetters
|
|
2268
|
+
),
|
|
2269
|
+
listExtractorPaths: stringArray(toolMetadata.listExtractorPaths),
|
|
2270
|
+
listIdentityGetters: stringArrayRecord(toolMetadata.listIdentityGetters)
|
|
2271
|
+
},
|
|
2272
|
+
execution: {
|
|
2273
|
+
idempotent: true,
|
|
2274
|
+
cached: false,
|
|
2275
|
+
source: "live"
|
|
2276
|
+
}
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
1853
2279
|
function defineInput(schema) {
|
|
1854
2280
|
if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
|
|
1855
2281
|
throw new Error(
|
|
@@ -1976,7 +2402,7 @@ function getByDottedPath(root, dottedPath) {
|
|
|
1976
2402
|
}
|
|
1977
2403
|
return current;
|
|
1978
2404
|
}
|
|
1979
|
-
function
|
|
2405
|
+
function normalizeRows2(value) {
|
|
1980
2406
|
if (!Array.isArray(value)) return null;
|
|
1981
2407
|
return value.map((entry) => {
|
|
1982
2408
|
if (isPlainObject(entry)) return entry;
|
|
@@ -1985,6 +2411,25 @@ function normalizeRows(value) {
|
|
|
1985
2411
|
}
|
|
1986
2412
|
function candidateRoots(payload) {
|
|
1987
2413
|
const roots = [{ path: null, value: payload }];
|
|
2414
|
+
if (isPlainObject(payload) && isPlainObject(payload.toolExecutionResult)) {
|
|
2415
|
+
roots.push({ path: "toolExecutionResult", value: payload.toolExecutionResult });
|
|
2416
|
+
const toolOutput = payload.toolExecutionResult.toolOutput;
|
|
2417
|
+
if (isPlainObject(toolOutput)) {
|
|
2418
|
+
roots.push({ path: "toolExecutionResult.toolOutput", value: toolOutput });
|
|
2419
|
+
if (Object.prototype.hasOwnProperty.call(toolOutput, "raw")) {
|
|
2420
|
+
roots.push({
|
|
2421
|
+
path: "toolExecutionResult.toolOutput.raw",
|
|
2422
|
+
value: toolOutput.raw
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
if (isPlainObject(payload) && isPlainObject(payload.output)) {
|
|
2428
|
+
roots.push({ path: "output", value: payload.output });
|
|
2429
|
+
if (Object.prototype.hasOwnProperty.call(payload.output, "body")) {
|
|
2430
|
+
roots.push({ path: "output.body", value: payload.output.body });
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
1988
2433
|
if (isPlainObject(payload) && isPlainObject(payload.result)) {
|
|
1989
2434
|
roots.push({ path: "result", value: payload.result });
|
|
1990
2435
|
if (isPlainObject(payload.result.data)) {
|
|
@@ -1995,7 +2440,7 @@ function candidateRoots(payload) {
|
|
|
1995
2440
|
}
|
|
1996
2441
|
function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
1997
2442
|
if (depth > 5) return null;
|
|
1998
|
-
const directRows =
|
|
2443
|
+
const directRows = normalizeRows2(value);
|
|
1999
2444
|
const hasObjectRow = directRows?.some((row) => Object.keys(row).some((key) => key !== "value")) ?? false;
|
|
2000
2445
|
let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
|
|
2001
2446
|
if (!isPlainObject(value)) {
|
|
@@ -2017,7 +2462,7 @@ function tryConvertToList(payload, options) {
|
|
|
2017
2462
|
for (const root of candidateRoots(payload)) {
|
|
2018
2463
|
for (const extractorPath of listExtractorPaths) {
|
|
2019
2464
|
const resolved = getByDottedPath(root.value, extractorPath);
|
|
2020
|
-
const rows =
|
|
2465
|
+
const rows = normalizeRows2(resolved);
|
|
2021
2466
|
if (rows && rows.length > 0) {
|
|
2022
2467
|
const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
|
|
2023
2468
|
return { rows, strategy: "configured_paths", sourcePath };
|