deepline 0.1.11 → 0.1.12
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 +4 -4
- package/dist/cli/index.js +509 -353
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +513 -358
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +250 -307
- package/dist/index.d.ts +250 -307
- package/dist/index.js +174 -315
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -314
- package/dist/index.mjs.map +1 -1
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +23 -13
- package/dist/repo/apps/play-runner-workers/src/entry.ts +581 -1220
- package/dist/repo/sdk/src/cli/commands/play.ts +381 -247
- package/dist/repo/sdk/src/cli/commands/tools.ts +1 -1
- package/dist/repo/sdk/src/cli/dataset-stats.ts +86 -12
- package/dist/repo/sdk/src/client.ts +54 -51
- package/dist/repo/sdk/src/index.ts +7 -16
- package/dist/repo/sdk/src/play.ts +122 -140
- package/dist/repo/sdk/src/plays/bundle-play-file.ts +6 -3
- package/dist/repo/sdk/src/tool-output.ts +0 -146
- package/dist/repo/sdk/src/types.ts +2 -0
- package/dist/repo/sdk/src/version.ts +1 -1
- package/dist/repo/sdk/src/worker-play-entry.ts +3 -0
- package/dist/repo/shared_libs/play-runtime/context.ts +510 -267
- package/dist/repo/shared_libs/play-runtime/csv-rename.ts +180 -0
- package/dist/repo/shared_libs/play-runtime/ctx-types.ts +13 -1
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +139 -114
- package/dist/repo/shared_libs/plays/bundling/index.ts +68 -5
- package/dist/repo/shared_libs/plays/compiler-manifest.ts +1 -1
- package/dist/repo/shared_libs/plays/dataset.ts +1 -1
- package/dist/repo/shared_libs/plays/runtime-validation.ts +8 -28
- package/package.json +1 -1
- package/dist/repo/apps/play-runner-workers/src/runtime/tool-result.ts +0 -184
package/dist/index.js
CHANGED
|
@@ -30,7 +30,6 @@ __export(src_exports, {
|
|
|
30
30
|
RateLimitError: () => RateLimitError,
|
|
31
31
|
SDK_API_CONTRACT: () => SDK_API_CONTRACT,
|
|
32
32
|
SDK_VERSION: () => SDK_VERSION,
|
|
33
|
-
createToolCallResult: () => createToolCallResult,
|
|
34
33
|
defineInput: () => defineInput,
|
|
35
34
|
definePlay: () => definePlay,
|
|
36
35
|
defineWorkflow: () => defineWorkflow,
|
|
@@ -196,7 +195,7 @@ function resolveConfig(options) {
|
|
|
196
195
|
}
|
|
197
196
|
|
|
198
197
|
// src/version.ts
|
|
199
|
-
var SDK_VERSION = "0.1.
|
|
198
|
+
var SDK_VERSION = "0.1.12";
|
|
200
199
|
var SDK_API_CONTRACT = "2026-04-plays-v1";
|
|
201
200
|
|
|
202
201
|
// ../shared_libs/play-runtime/coordinator-headers.ts
|
|
@@ -471,6 +470,9 @@ function sleep(ms) {
|
|
|
471
470
|
|
|
472
471
|
// src/client.ts
|
|
473
472
|
var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
473
|
+
function isRecord(value) {
|
|
474
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
475
|
+
}
|
|
474
476
|
function normalizePlayStatus(raw) {
|
|
475
477
|
const status = typeof raw.status === "string" ? raw.status : typeof raw.temporalStatus === "string" ? mapLegacyTemporalStatus(raw.temporalStatus) : "running";
|
|
476
478
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : "";
|
|
@@ -523,12 +525,27 @@ var DeeplineClient = class {
|
|
|
523
525
|
).filter((field) => Boolean(field?.name)) : [];
|
|
524
526
|
return fields.length > 0 ? { fields } : schema;
|
|
525
527
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
+
schemaMetadata(schema, key) {
|
|
529
|
+
if (!isRecord(schema)) return null;
|
|
530
|
+
const value = schema[key];
|
|
531
|
+
return isRecord(value) ? value : null;
|
|
532
|
+
}
|
|
533
|
+
playRunCommand(play, options) {
|
|
534
|
+
const target = play.reference || play.name;
|
|
535
|
+
if (options?.csvInput) {
|
|
536
|
+
const inputField = typeof options.csvInput.inputField === "string" && options.csvInput.inputField.trim() ? options.csvInput.inputField.trim() : "csv";
|
|
537
|
+
return `deepline plays run ${target} --${inputField} leads.csv --watch`;
|
|
538
|
+
}
|
|
539
|
+
return `deepline plays run ${target} --input '{...}' --watch`;
|
|
528
540
|
}
|
|
529
541
|
summarizePlayListItem(play, options) {
|
|
530
542
|
const aliases = play.aliases?.length ? play.aliases : [play.name];
|
|
531
|
-
const
|
|
543
|
+
const csvInput = this.schemaMetadata(play.inputSchema, "csvInput");
|
|
544
|
+
const rowOutputSchema = this.schemaMetadata(
|
|
545
|
+
play.outputSchema,
|
|
546
|
+
"rowOutputSchema"
|
|
547
|
+
);
|
|
548
|
+
const runCommand = this.playRunCommand(play, { csvInput });
|
|
532
549
|
return {
|
|
533
550
|
name: play.name,
|
|
534
551
|
...play.reference ? { reference: play.reference } : {},
|
|
@@ -540,6 +557,8 @@ var DeeplineClient = class {
|
|
|
540
557
|
aliases,
|
|
541
558
|
inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
|
|
542
559
|
outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
|
|
560
|
+
...csvInput ? { csvInput } : {},
|
|
561
|
+
...rowOutputSchema ? { rowOutputSchema } : {},
|
|
543
562
|
runCommand,
|
|
544
563
|
examples: [runCommand],
|
|
545
564
|
currentPublishedVersion: play.currentPublishedVersion ?? null,
|
|
@@ -606,50 +625,14 @@ var DeeplineClient = class {
|
|
|
606
625
|
);
|
|
607
626
|
}
|
|
608
627
|
/**
|
|
609
|
-
* Execute a tool and return the
|
|
610
|
-
*
|
|
611
|
-
* Sends the input payload to the tool and returns the `.result` field from the
|
|
612
|
-
* response. For the full response envelope (including job_id, credits, etc.),
|
|
613
|
-
* use {@link executeToolRaw}.
|
|
614
|
-
*
|
|
615
|
-
* @param toolId - Tool identifier (e.g. `"test_company_search"`)
|
|
616
|
-
* @param input - Tool-specific input parameters
|
|
617
|
-
* @returns The tool's output (shape varies by tool)
|
|
618
|
-
* @throws {@link DeeplineError} if the tool execution fails
|
|
628
|
+
* Execute a tool and return the standard execution envelope.
|
|
619
629
|
*
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
* });
|
|
625
|
-
* console.log(company); // { name: "Stripe", industry: "Financial Services", ... }
|
|
626
|
-
* ```
|
|
630
|
+
* The `result.data` field contains the provider payload. `result.meta`
|
|
631
|
+
* contains provider/upstream metadata such as HTTP status or paging details.
|
|
632
|
+
* Top-level fields such as `status`, `job_id`, and `billing` describe the
|
|
633
|
+
* Deepline execution.
|
|
627
634
|
*/
|
|
628
635
|
async executeTool(toolId, input) {
|
|
629
|
-
const res = await this.http.post(
|
|
630
|
-
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
631
|
-
{ payload: input }
|
|
632
|
-
);
|
|
633
|
-
return res.result ?? res;
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Execute a tool and return the full response envelope.
|
|
637
|
-
*
|
|
638
|
-
* Unlike {@link executeTool}, this returns the complete API response including
|
|
639
|
-
* `job_id`, `status`, `credits`, and the raw `result` object.
|
|
640
|
-
*
|
|
641
|
-
* @param toolId - Tool identifier
|
|
642
|
-
* @param input - Tool-specific input parameters
|
|
643
|
-
* @returns Full response with job metadata and result
|
|
644
|
-
*
|
|
645
|
-
* @example
|
|
646
|
-
* ```typescript
|
|
647
|
-
* const raw = await client.executeToolRaw('test_company_search', { domain: 'stripe.com' });
|
|
648
|
-
* console.log(`Job: ${raw.job_id}, Credits: ${raw.credits}`);
|
|
649
|
-
* console.log(`Result:`, raw.result);
|
|
650
|
-
* ```
|
|
651
|
-
*/
|
|
652
|
-
async executeToolRaw(toolId, input) {
|
|
653
636
|
return this.http.post(
|
|
654
637
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
655
638
|
{ payload: input }
|
|
@@ -1271,258 +1254,6 @@ var DeeplineClient = class {
|
|
|
1271
1254
|
}
|
|
1272
1255
|
};
|
|
1273
1256
|
|
|
1274
|
-
// src/tool-output.ts
|
|
1275
|
-
var import_node_fs2 = require("fs");
|
|
1276
|
-
var import_node_os2 = require("os");
|
|
1277
|
-
var import_node_path2 = require("path");
|
|
1278
|
-
function isPlainObject(value) {
|
|
1279
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1280
|
-
}
|
|
1281
|
-
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1282
|
-
var PHONE_KEY_PATTERN = /(^|[_-])(phone|mobile|cell|telephone|tel)([_-]|$)|phone|mobile|telephone/i;
|
|
1283
|
-
function normalizeScalarString(value) {
|
|
1284
|
-
if (typeof value === "string") {
|
|
1285
|
-
const trimmed = value.trim();
|
|
1286
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
1287
|
-
}
|
|
1288
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1289
|
-
return String(value);
|
|
1290
|
-
}
|
|
1291
|
-
return null;
|
|
1292
|
-
}
|
|
1293
|
-
function looksLikeEmail(value) {
|
|
1294
|
-
const candidate = normalizeScalarString(value);
|
|
1295
|
-
if (!candidate || !EMAIL_PATTERN.test(candidate)) return null;
|
|
1296
|
-
return candidate;
|
|
1297
|
-
}
|
|
1298
|
-
function looksLikePhone(value) {
|
|
1299
|
-
const candidate = normalizeScalarString(value);
|
|
1300
|
-
if (!candidate) return null;
|
|
1301
|
-
const digits = candidate.replace(/\D/g, "");
|
|
1302
|
-
if (digits.length < 7 || digits.length > 16) return null;
|
|
1303
|
-
return candidate;
|
|
1304
|
-
}
|
|
1305
|
-
function findEmail(value, depth = 0) {
|
|
1306
|
-
if (depth > 6) return null;
|
|
1307
|
-
const direct = looksLikeEmail(value);
|
|
1308
|
-
if (direct) return direct;
|
|
1309
|
-
if (Array.isArray(value)) {
|
|
1310
|
-
for (const entry of value) {
|
|
1311
|
-
const nested = findEmail(entry, depth + 1);
|
|
1312
|
-
if (nested) return nested;
|
|
1313
|
-
}
|
|
1314
|
-
return null;
|
|
1315
|
-
}
|
|
1316
|
-
if (!isPlainObject(value)) return null;
|
|
1317
|
-
for (const [key, child] of Object.entries(value)) {
|
|
1318
|
-
if (/email/i.test(key)) {
|
|
1319
|
-
const keyed = looksLikeEmail(child);
|
|
1320
|
-
if (keyed) return keyed;
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
for (const child of Object.values(value)) {
|
|
1324
|
-
const nested = findEmail(child, depth + 1);
|
|
1325
|
-
if (nested) return nested;
|
|
1326
|
-
}
|
|
1327
|
-
return null;
|
|
1328
|
-
}
|
|
1329
|
-
function findPhone(value, depth = 0) {
|
|
1330
|
-
if (depth > 6) return null;
|
|
1331
|
-
if (Array.isArray(value)) {
|
|
1332
|
-
for (const entry of value) {
|
|
1333
|
-
const nested = findPhone(entry, depth + 1);
|
|
1334
|
-
if (nested) return nested;
|
|
1335
|
-
}
|
|
1336
|
-
return null;
|
|
1337
|
-
}
|
|
1338
|
-
if (!isPlainObject(value)) return null;
|
|
1339
|
-
for (const [key, child] of Object.entries(value)) {
|
|
1340
|
-
if (PHONE_KEY_PATTERN.test(key)) {
|
|
1341
|
-
const keyed = looksLikePhone(child);
|
|
1342
|
-
if (keyed) return keyed;
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
for (const child of Object.values(value)) {
|
|
1346
|
-
const nested = findPhone(child, depth + 1);
|
|
1347
|
-
if (nested) return nested;
|
|
1348
|
-
}
|
|
1349
|
-
return null;
|
|
1350
|
-
}
|
|
1351
|
-
function normalizeListExtractorPaths(paths) {
|
|
1352
|
-
if (!Array.isArray(paths)) return [];
|
|
1353
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1354
|
-
const normalized = [];
|
|
1355
|
-
for (const rawPath of paths) {
|
|
1356
|
-
if (typeof rawPath !== "string") continue;
|
|
1357
|
-
const path = rawPath.trim();
|
|
1358
|
-
if (!path) continue;
|
|
1359
|
-
for (const candidate of [path, path.replace(/^result\./, "")]) {
|
|
1360
|
-
if (!candidate || seen.has(candidate)) continue;
|
|
1361
|
-
seen.add(candidate);
|
|
1362
|
-
normalized.push(candidate);
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
return normalized;
|
|
1366
|
-
}
|
|
1367
|
-
var DeeplineToolCallResult = class {
|
|
1368
|
-
constructor(value, options) {
|
|
1369
|
-
this.value = value;
|
|
1370
|
-
this.listExtractorPaths = normalizeListExtractorPaths(
|
|
1371
|
-
options?.listExtractorPaths
|
|
1372
|
-
);
|
|
1373
|
-
}
|
|
1374
|
-
value;
|
|
1375
|
-
listExtractorPaths;
|
|
1376
|
-
getEmail() {
|
|
1377
|
-
return findEmail(this.value);
|
|
1378
|
-
}
|
|
1379
|
-
getPhone() {
|
|
1380
|
-
return findPhone(this.value);
|
|
1381
|
-
}
|
|
1382
|
-
tryList(options) {
|
|
1383
|
-
const explicitPaths = normalizeListExtractorPaths(options?.listExtractorPaths);
|
|
1384
|
-
return tryConvertToList(this.value, {
|
|
1385
|
-
listExtractorPaths: explicitPaths.length > 0 ? explicitPaths : this.listExtractorPaths
|
|
1386
|
-
})?.rows ?? null;
|
|
1387
|
-
}
|
|
1388
|
-
};
|
|
1389
|
-
function createToolCallResult(value, options) {
|
|
1390
|
-
return new DeeplineToolCallResult(value, options);
|
|
1391
|
-
}
|
|
1392
|
-
function getByDottedPath(root, dottedPath) {
|
|
1393
|
-
let current = root;
|
|
1394
|
-
for (const segment of String(dottedPath || "").split(".").filter(Boolean)) {
|
|
1395
|
-
if (!isPlainObject(current) || !(segment in current)) {
|
|
1396
|
-
return null;
|
|
1397
|
-
}
|
|
1398
|
-
current = current[segment];
|
|
1399
|
-
}
|
|
1400
|
-
return current;
|
|
1401
|
-
}
|
|
1402
|
-
function normalizeRows(value) {
|
|
1403
|
-
if (!Array.isArray(value)) return null;
|
|
1404
|
-
return value.map((entry) => {
|
|
1405
|
-
if (isPlainObject(entry)) return entry;
|
|
1406
|
-
return { value: entry };
|
|
1407
|
-
});
|
|
1408
|
-
}
|
|
1409
|
-
function candidateRoots(payload) {
|
|
1410
|
-
const roots = [{ path: null, value: payload }];
|
|
1411
|
-
if (isPlainObject(payload) && isPlainObject(payload.result)) {
|
|
1412
|
-
roots.push({ path: "result", value: payload.result });
|
|
1413
|
-
if (isPlainObject(payload.result.data)) {
|
|
1414
|
-
roots.push({ path: "result.data", value: payload.result.data });
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
return roots;
|
|
1418
|
-
}
|
|
1419
|
-
function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
1420
|
-
if (depth > 5) return null;
|
|
1421
|
-
const directRows = normalizeRows(value);
|
|
1422
|
-
const hasObjectRow = directRows?.some((row) => Object.keys(row).some((key) => key !== "value")) ?? false;
|
|
1423
|
-
let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
|
|
1424
|
-
if (!isPlainObject(value)) {
|
|
1425
|
-
return best;
|
|
1426
|
-
}
|
|
1427
|
-
for (const [key, child] of Object.entries(value)) {
|
|
1428
|
-
const childPath = pathPrefix ? `${pathPrefix}.${key}` : key;
|
|
1429
|
-
const candidate = findBestArrayCandidate(child, childPath, depth + 1);
|
|
1430
|
-
if (!candidate) continue;
|
|
1431
|
-
if (!best || candidate.rows.length > best.rows.length) {
|
|
1432
|
-
best = candidate;
|
|
1433
|
-
}
|
|
1434
|
-
}
|
|
1435
|
-
return best;
|
|
1436
|
-
}
|
|
1437
|
-
function tryConvertToList(payload, options) {
|
|
1438
|
-
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
|
|
1439
|
-
if (listExtractorPaths.length > 0) {
|
|
1440
|
-
for (const root of candidateRoots(payload)) {
|
|
1441
|
-
for (const extractorPath of listExtractorPaths) {
|
|
1442
|
-
const resolved = getByDottedPath(root.value, extractorPath);
|
|
1443
|
-
const rows = normalizeRows(resolved);
|
|
1444
|
-
if (rows && rows.length > 0) {
|
|
1445
|
-
const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
|
|
1446
|
-
return { rows, strategy: "configured_paths", sourcePath };
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
for (const root of candidateRoots(payload)) {
|
|
1452
|
-
const candidate = findBestArrayCandidate(root.value, root.path ?? "");
|
|
1453
|
-
if (!candidate || candidate.rows.length === 0) continue;
|
|
1454
|
-
return {
|
|
1455
|
-
rows: candidate.rows,
|
|
1456
|
-
strategy: "auto_detected",
|
|
1457
|
-
sourcePath: candidate.path || root.path
|
|
1458
|
-
};
|
|
1459
|
-
}
|
|
1460
|
-
return null;
|
|
1461
|
-
}
|
|
1462
|
-
function ensureOutputDir() {
|
|
1463
|
-
const outputDir = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".local", "share", "deepline", "data");
|
|
1464
|
-
(0, import_node_fs2.mkdirSync)(outputDir, { recursive: true });
|
|
1465
|
-
return outputDir;
|
|
1466
|
-
}
|
|
1467
|
-
function writeJsonOutputFile(payload, stem) {
|
|
1468
|
-
const outputDir = ensureOutputDir();
|
|
1469
|
-
const outputPath = (0, import_node_path2.join)(outputDir, `${stem}_${Date.now()}.json`);
|
|
1470
|
-
(0, import_node_fs2.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
1471
|
-
return outputPath;
|
|
1472
|
-
}
|
|
1473
|
-
function writeCsvOutputFile(rows, stem) {
|
|
1474
|
-
const outputDir = ensureOutputDir();
|
|
1475
|
-
const outputPath = (0, import_node_path2.join)(outputDir, `${stem}_${Date.now()}.csv`);
|
|
1476
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1477
|
-
const columns = [];
|
|
1478
|
-
for (const row of rows) {
|
|
1479
|
-
for (const key of Object.keys(row)) {
|
|
1480
|
-
if (!seen.has(key)) {
|
|
1481
|
-
seen.add(key);
|
|
1482
|
-
columns.push(key);
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
}
|
|
1486
|
-
const escapeCell = (value) => {
|
|
1487
|
-
const normalized = value == null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
|
|
1488
|
-
if (/[",\n]/.test(normalized)) {
|
|
1489
|
-
return `"${normalized.replace(/"/g, '""')}"`;
|
|
1490
|
-
}
|
|
1491
|
-
return normalized;
|
|
1492
|
-
};
|
|
1493
|
-
const lines = [];
|
|
1494
|
-
lines.push(columns.map(escapeCell).join(","));
|
|
1495
|
-
for (const row of rows) {
|
|
1496
|
-
lines.push(columns.map((column) => escapeCell(row[column])).join(","));
|
|
1497
|
-
}
|
|
1498
|
-
(0, import_node_fs2.writeFileSync)(outputPath, `${lines.join("\n")}
|
|
1499
|
-
`, "utf-8");
|
|
1500
|
-
const previewRows = rows.slice(0, 5);
|
|
1501
|
-
const previewColumns = columns.slice(0, 5);
|
|
1502
|
-
const preview = [
|
|
1503
|
-
previewColumns.join(","),
|
|
1504
|
-
...previewRows.map((row) => previewColumns.map((column) => escapeCell(row[column])).join(","))
|
|
1505
|
-
].join("\n");
|
|
1506
|
-
return {
|
|
1507
|
-
path: outputPath,
|
|
1508
|
-
rowCount: rows.length,
|
|
1509
|
-
columns,
|
|
1510
|
-
preview
|
|
1511
|
-
};
|
|
1512
|
-
}
|
|
1513
|
-
function extractSummaryFields(payload) {
|
|
1514
|
-
const candidates = candidateRoots(payload);
|
|
1515
|
-
for (const candidate of candidates) {
|
|
1516
|
-
if (!isPlainObject(candidate.value)) continue;
|
|
1517
|
-
const summaryEntries = Object.entries(candidate.value).filter(([, value]) => {
|
|
1518
|
-
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
1519
|
-
});
|
|
1520
|
-
if (summaryEntries.length === 0) continue;
|
|
1521
|
-
return Object.fromEntries(summaryEntries);
|
|
1522
|
-
}
|
|
1523
|
-
return {};
|
|
1524
|
-
}
|
|
1525
|
-
|
|
1526
1257
|
// src/play.ts
|
|
1527
1258
|
var DeeplineConditionalStepResolver = class _DeeplineConditionalStepResolver {
|
|
1528
1259
|
constructor(when2, run, elseValue) {
|
|
@@ -1661,12 +1392,8 @@ var DeeplineContext = class {
|
|
|
1661
1392
|
* ```typescript
|
|
1662
1393
|
* const tools = await ctx.tools.list();
|
|
1663
1394
|
* const meta = await ctx.tools.get('apollo_people_search');
|
|
1664
|
-
* const
|
|
1665
|
-
*
|
|
1666
|
-
* input: { domain: 'stripe.com' },
|
|
1667
|
-
* });
|
|
1668
|
-
* const rows = result.tryList({ listExtractorPaths: ['people'] });
|
|
1669
|
-
* const email = result.getEmail();
|
|
1395
|
+
* const companyLookup = await ctx.tools.execute('test_company_search', { domain: 'stripe.com' });
|
|
1396
|
+
* const company = companyLookup.result.data;
|
|
1670
1397
|
* ```
|
|
1671
1398
|
*/
|
|
1672
1399
|
get tools() {
|
|
@@ -1675,16 +1402,8 @@ var DeeplineContext = class {
|
|
|
1675
1402
|
list: () => this.client.listTools(),
|
|
1676
1403
|
/** Get detailed metadata for a tool. */
|
|
1677
1404
|
get: (toolId) => this.client.getTool(toolId),
|
|
1678
|
-
/** Execute a tool and return
|
|
1679
|
-
execute: async (
|
|
1680
|
-
const [metadata, value] = await Promise.all([
|
|
1681
|
-
this.client.getTool(request.tool),
|
|
1682
|
-
this.client.executeTool(request.tool, request.input)
|
|
1683
|
-
]);
|
|
1684
|
-
return createToolCallResult(value, {
|
|
1685
|
-
listExtractorPaths: metadata.listExtractorPaths ?? []
|
|
1686
|
-
});
|
|
1687
|
-
}
|
|
1405
|
+
/** Execute a tool and return the standard execution envelope. */
|
|
1406
|
+
execute: async (toolId, input) => this.client.executeTool(toolId, input)
|
|
1688
1407
|
};
|
|
1689
1408
|
}
|
|
1690
1409
|
get plays() {
|
|
@@ -1887,6 +1606,147 @@ function getDefinedPlayMetadata(value) {
|
|
|
1887
1606
|
}
|
|
1888
1607
|
return candidate;
|
|
1889
1608
|
}
|
|
1609
|
+
|
|
1610
|
+
// src/tool-output.ts
|
|
1611
|
+
var import_node_fs2 = require("fs");
|
|
1612
|
+
var import_node_os2 = require("os");
|
|
1613
|
+
var import_node_path2 = require("path");
|
|
1614
|
+
function isPlainObject(value) {
|
|
1615
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1616
|
+
}
|
|
1617
|
+
function getByDottedPath(root, dottedPath) {
|
|
1618
|
+
let current = root;
|
|
1619
|
+
for (const segment of String(dottedPath || "").split(".").filter(Boolean)) {
|
|
1620
|
+
if (!isPlainObject(current) || !(segment in current)) {
|
|
1621
|
+
return null;
|
|
1622
|
+
}
|
|
1623
|
+
current = current[segment];
|
|
1624
|
+
}
|
|
1625
|
+
return current;
|
|
1626
|
+
}
|
|
1627
|
+
function normalizeRows(value) {
|
|
1628
|
+
if (!Array.isArray(value)) return null;
|
|
1629
|
+
return value.map((entry) => {
|
|
1630
|
+
if (isPlainObject(entry)) return entry;
|
|
1631
|
+
return { value: entry };
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
function candidateRoots(payload) {
|
|
1635
|
+
const roots = [{ path: null, value: payload }];
|
|
1636
|
+
if (isPlainObject(payload) && isPlainObject(payload.result)) {
|
|
1637
|
+
roots.push({ path: "result", value: payload.result });
|
|
1638
|
+
if (isPlainObject(payload.result.data)) {
|
|
1639
|
+
roots.push({ path: "result.data", value: payload.result.data });
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
return roots;
|
|
1643
|
+
}
|
|
1644
|
+
function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
1645
|
+
if (depth > 5) return null;
|
|
1646
|
+
const directRows = normalizeRows(value);
|
|
1647
|
+
const hasObjectRow = directRows?.some((row) => Object.keys(row).some((key) => key !== "value")) ?? false;
|
|
1648
|
+
let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
|
|
1649
|
+
if (!isPlainObject(value)) {
|
|
1650
|
+
return best;
|
|
1651
|
+
}
|
|
1652
|
+
for (const [key, child] of Object.entries(value)) {
|
|
1653
|
+
const childPath = pathPrefix ? `${pathPrefix}.${key}` : key;
|
|
1654
|
+
const candidate = findBestArrayCandidate(child, childPath, depth + 1);
|
|
1655
|
+
if (!candidate) continue;
|
|
1656
|
+
if (!best || candidate.rows.length > best.rows.length) {
|
|
1657
|
+
best = candidate;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return best;
|
|
1661
|
+
}
|
|
1662
|
+
function tryConvertToList(payload, options) {
|
|
1663
|
+
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
|
|
1664
|
+
if (listExtractorPaths.length > 0) {
|
|
1665
|
+
for (const root of candidateRoots(payload)) {
|
|
1666
|
+
for (const extractorPath of listExtractorPaths) {
|
|
1667
|
+
const resolved = getByDottedPath(root.value, extractorPath);
|
|
1668
|
+
const rows = normalizeRows(resolved);
|
|
1669
|
+
if (rows && rows.length > 0) {
|
|
1670
|
+
const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
|
|
1671
|
+
return { rows, strategy: "configured_paths", sourcePath };
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
for (const root of candidateRoots(payload)) {
|
|
1677
|
+
const candidate = findBestArrayCandidate(root.value, root.path ?? "");
|
|
1678
|
+
if (!candidate || candidate.rows.length === 0) continue;
|
|
1679
|
+
return {
|
|
1680
|
+
rows: candidate.rows,
|
|
1681
|
+
strategy: "auto_detected",
|
|
1682
|
+
sourcePath: candidate.path || root.path
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
return null;
|
|
1686
|
+
}
|
|
1687
|
+
function ensureOutputDir() {
|
|
1688
|
+
const outputDir = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".local", "share", "deepline", "data");
|
|
1689
|
+
(0, import_node_fs2.mkdirSync)(outputDir, { recursive: true });
|
|
1690
|
+
return outputDir;
|
|
1691
|
+
}
|
|
1692
|
+
function writeJsonOutputFile(payload, stem) {
|
|
1693
|
+
const outputDir = ensureOutputDir();
|
|
1694
|
+
const outputPath = (0, import_node_path2.join)(outputDir, `${stem}_${Date.now()}.json`);
|
|
1695
|
+
(0, import_node_fs2.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
1696
|
+
return outputPath;
|
|
1697
|
+
}
|
|
1698
|
+
function writeCsvOutputFile(rows, stem) {
|
|
1699
|
+
const outputDir = ensureOutputDir();
|
|
1700
|
+
const outputPath = (0, import_node_path2.join)(outputDir, `${stem}_${Date.now()}.csv`);
|
|
1701
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1702
|
+
const columns = [];
|
|
1703
|
+
for (const row of rows) {
|
|
1704
|
+
for (const key of Object.keys(row)) {
|
|
1705
|
+
if (!seen.has(key)) {
|
|
1706
|
+
seen.add(key);
|
|
1707
|
+
columns.push(key);
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
const escapeCell = (value) => {
|
|
1712
|
+
const normalized = value == null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
|
|
1713
|
+
if (/[",\n]/.test(normalized)) {
|
|
1714
|
+
return `"${normalized.replace(/"/g, '""')}"`;
|
|
1715
|
+
}
|
|
1716
|
+
return normalized;
|
|
1717
|
+
};
|
|
1718
|
+
const lines = [];
|
|
1719
|
+
lines.push(columns.map(escapeCell).join(","));
|
|
1720
|
+
for (const row of rows) {
|
|
1721
|
+
lines.push(columns.map((column) => escapeCell(row[column])).join(","));
|
|
1722
|
+
}
|
|
1723
|
+
(0, import_node_fs2.writeFileSync)(outputPath, `${lines.join("\n")}
|
|
1724
|
+
`, "utf-8");
|
|
1725
|
+
const previewRows = rows.slice(0, 5);
|
|
1726
|
+
const previewColumns = columns.slice(0, 5);
|
|
1727
|
+
const preview = [
|
|
1728
|
+
previewColumns.join(","),
|
|
1729
|
+
...previewRows.map((row) => previewColumns.map((column) => escapeCell(row[column])).join(","))
|
|
1730
|
+
].join("\n");
|
|
1731
|
+
return {
|
|
1732
|
+
path: outputPath,
|
|
1733
|
+
rowCount: rows.length,
|
|
1734
|
+
columns,
|
|
1735
|
+
preview
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
function extractSummaryFields(payload) {
|
|
1739
|
+
const candidates = candidateRoots(payload);
|
|
1740
|
+
for (const candidate of candidates) {
|
|
1741
|
+
if (!isPlainObject(candidate.value)) continue;
|
|
1742
|
+
const summaryEntries = Object.entries(candidate.value).filter(([, value]) => {
|
|
1743
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
1744
|
+
});
|
|
1745
|
+
if (summaryEntries.length === 0) continue;
|
|
1746
|
+
return Object.fromEntries(summaryEntries);
|
|
1747
|
+
}
|
|
1748
|
+
return {};
|
|
1749
|
+
}
|
|
1890
1750
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1891
1751
|
0 && (module.exports = {
|
|
1892
1752
|
AuthError,
|
|
@@ -1899,7 +1759,6 @@ function getDefinedPlayMetadata(value) {
|
|
|
1899
1759
|
RateLimitError,
|
|
1900
1760
|
SDK_API_CONTRACT,
|
|
1901
1761
|
SDK_VERSION,
|
|
1902
|
-
createToolCallResult,
|
|
1903
1762
|
defineInput,
|
|
1904
1763
|
definePlay,
|
|
1905
1764
|
defineWorkflow,
|