deepline 0.1.10 → 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.
Files changed (34) hide show
  1. package/README.md +4 -4
  2. package/dist/cli/index.js +509 -353
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/cli/index.mjs +513 -358
  5. package/dist/cli/index.mjs.map +1 -1
  6. package/dist/index.d.mts +250 -305
  7. package/dist/index.d.ts +250 -305
  8. package/dist/index.js +174 -286
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +174 -285
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +23 -13
  13. package/dist/repo/apps/play-runner-workers/src/entry.ts +581 -1220
  14. package/dist/repo/sdk/src/cli/commands/play.ts +381 -247
  15. package/dist/repo/sdk/src/cli/commands/tools.ts +1 -1
  16. package/dist/repo/sdk/src/cli/dataset-stats.ts +86 -12
  17. package/dist/repo/sdk/src/client.ts +54 -51
  18. package/dist/repo/sdk/src/index.ts +7 -16
  19. package/dist/repo/sdk/src/play.ts +122 -135
  20. package/dist/repo/sdk/src/plays/bundle-play-file.ts +6 -3
  21. package/dist/repo/sdk/src/tool-output.ts +0 -111
  22. package/dist/repo/sdk/src/types.ts +2 -0
  23. package/dist/repo/sdk/src/version.ts +1 -1
  24. package/dist/repo/sdk/src/worker-play-entry.ts +3 -0
  25. package/dist/repo/shared_libs/play-runtime/context.ts +510 -267
  26. package/dist/repo/shared_libs/play-runtime/csv-rename.ts +180 -0
  27. package/dist/repo/shared_libs/play-runtime/ctx-types.ts +13 -1
  28. package/dist/repo/shared_libs/play-runtime/tool-result.ts +139 -114
  29. package/dist/repo/shared_libs/plays/bundling/index.ts +68 -5
  30. package/dist/repo/shared_libs/plays/compiler-manifest.ts +1 -1
  31. package/dist/repo/shared_libs/plays/dataset.ts +1 -1
  32. package/dist/repo/shared_libs/plays/runtime-validation.ts +8 -28
  33. package/package.json +1 -1
  34. package/dist/repo/apps/play-runner-workers/src/runtime/tool-result.ts +0 -184
package/dist/index.mjs CHANGED
@@ -149,7 +149,7 @@ function resolveConfig(options) {
149
149
  }
150
150
 
151
151
  // src/version.ts
152
- var SDK_VERSION = "0.1.10";
152
+ var SDK_VERSION = "0.1.12";
153
153
  var SDK_API_CONTRACT = "2026-04-plays-v1";
154
154
 
155
155
  // ../shared_libs/play-runtime/coordinator-headers.ts
@@ -424,6 +424,9 @@ function sleep(ms) {
424
424
 
425
425
  // src/client.ts
426
426
  var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
427
+ function isRecord(value) {
428
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
429
+ }
427
430
  function normalizePlayStatus(raw) {
428
431
  const status = typeof raw.status === "string" ? raw.status : typeof raw.temporalStatus === "string" ? mapLegacyTemporalStatus(raw.temporalStatus) : "running";
429
432
  const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : "";
@@ -476,12 +479,27 @@ var DeeplineClient = class {
476
479
  ).filter((field) => Boolean(field?.name)) : [];
477
480
  return fields.length > 0 ? { fields } : schema;
478
481
  }
479
- playRunCommand(name) {
480
- return `deepline plays run ${name} --input '{...}' --watch`;
482
+ schemaMetadata(schema, key) {
483
+ if (!isRecord(schema)) return null;
484
+ const value = schema[key];
485
+ return isRecord(value) ? value : null;
486
+ }
487
+ playRunCommand(play, options) {
488
+ const target = play.reference || play.name;
489
+ if (options?.csvInput) {
490
+ const inputField = typeof options.csvInput.inputField === "string" && options.csvInput.inputField.trim() ? options.csvInput.inputField.trim() : "csv";
491
+ return `deepline plays run ${target} --${inputField} leads.csv --watch`;
492
+ }
493
+ return `deepline plays run ${target} --input '{...}' --watch`;
481
494
  }
482
495
  summarizePlayListItem(play, options) {
483
496
  const aliases = play.aliases?.length ? play.aliases : [play.name];
484
- const runCommand = this.playRunCommand(play.name);
497
+ const csvInput = this.schemaMetadata(play.inputSchema, "csvInput");
498
+ const rowOutputSchema = this.schemaMetadata(
499
+ play.outputSchema,
500
+ "rowOutputSchema"
501
+ );
502
+ const runCommand = this.playRunCommand(play, { csvInput });
485
503
  return {
486
504
  name: play.name,
487
505
  ...play.reference ? { reference: play.reference } : {},
@@ -493,6 +511,8 @@ var DeeplineClient = class {
493
511
  aliases,
494
512
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
495
513
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
514
+ ...csvInput ? { csvInput } : {},
515
+ ...rowOutputSchema ? { rowOutputSchema } : {},
496
516
  runCommand,
497
517
  examples: [runCommand],
498
518
  currentPublishedVersion: play.currentPublishedVersion ?? null,
@@ -559,50 +579,14 @@ var DeeplineClient = class {
559
579
  );
560
580
  }
561
581
  /**
562
- * Execute a tool and return the extracted result.
563
- *
564
- * Sends the input payload to the tool and returns the `.result` field from the
565
- * response. For the full response envelope (including job_id, credits, etc.),
566
- * use {@link executeToolRaw}.
567
- *
568
- * @param toolId - Tool identifier (e.g. `"test_company_search"`)
569
- * @param input - Tool-specific input parameters
570
- * @returns The tool's output (shape varies by tool)
571
- * @throws {@link DeeplineError} if the tool execution fails
582
+ * Execute a tool and return the standard execution envelope.
572
583
  *
573
- * @example
574
- * ```typescript
575
- * const company = await client.executeTool('test_company_search', {
576
- * domain: 'stripe.com',
577
- * });
578
- * console.log(company); // { name: "Stripe", industry: "Financial Services", ... }
579
- * ```
584
+ * The `result.data` field contains the provider payload. `result.meta`
585
+ * contains provider/upstream metadata such as HTTP status or paging details.
586
+ * Top-level fields such as `status`, `job_id`, and `billing` describe the
587
+ * Deepline execution.
580
588
  */
581
589
  async executeTool(toolId, input) {
582
- const res = await this.http.post(
583
- `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
584
- { payload: input }
585
- );
586
- return res.result ?? res;
587
- }
588
- /**
589
- * Execute a tool and return the full response envelope.
590
- *
591
- * Unlike {@link executeTool}, this returns the complete API response including
592
- * `job_id`, `status`, `credits`, and the raw `result` object.
593
- *
594
- * @param toolId - Tool identifier
595
- * @param input - Tool-specific input parameters
596
- * @returns Full response with job metadata and result
597
- *
598
- * @example
599
- * ```typescript
600
- * const raw = await client.executeToolRaw('test_company_search', { domain: 'stripe.com' });
601
- * console.log(`Job: ${raw.job_id}, Credits: ${raw.credits}`);
602
- * console.log(`Result:`, raw.result);
603
- * ```
604
- */
605
- async executeToolRaw(toolId, input) {
606
590
  return this.http.post(
607
591
  `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
608
592
  { payload: input }
@@ -1224,235 +1208,6 @@ var DeeplineClient = class {
1224
1208
  }
1225
1209
  };
1226
1210
 
1227
- // src/tool-output.ts
1228
- import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
1229
- import { homedir as homedir2 } from "os";
1230
- import { join as join2 } from "path";
1231
- function isPlainObject(value) {
1232
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1233
- }
1234
- var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1235
- var PHONE_KEY_PATTERN = /(^|[_-])(phone|mobile|cell|telephone|tel)([_-]|$)|phone|mobile|telephone/i;
1236
- function normalizeScalarString(value) {
1237
- if (typeof value === "string") {
1238
- const trimmed = value.trim();
1239
- return trimmed.length > 0 ? trimmed : null;
1240
- }
1241
- if (typeof value === "number" && Number.isFinite(value)) {
1242
- return String(value);
1243
- }
1244
- return null;
1245
- }
1246
- function looksLikeEmail(value) {
1247
- const candidate = normalizeScalarString(value);
1248
- if (!candidate || !EMAIL_PATTERN.test(candidate)) return null;
1249
- return candidate;
1250
- }
1251
- function looksLikePhone(value) {
1252
- const candidate = normalizeScalarString(value);
1253
- if (!candidate) return null;
1254
- const digits = candidate.replace(/\D/g, "");
1255
- if (digits.length < 7 || digits.length > 16) return null;
1256
- return candidate;
1257
- }
1258
- function findEmail(value, depth = 0) {
1259
- if (depth > 6) return null;
1260
- const direct = looksLikeEmail(value);
1261
- if (direct) return direct;
1262
- if (Array.isArray(value)) {
1263
- for (const entry of value) {
1264
- const nested = findEmail(entry, depth + 1);
1265
- if (nested) return nested;
1266
- }
1267
- return null;
1268
- }
1269
- if (!isPlainObject(value)) return null;
1270
- for (const [key, child] of Object.entries(value)) {
1271
- if (/email/i.test(key)) {
1272
- const keyed = looksLikeEmail(child);
1273
- if (keyed) return keyed;
1274
- }
1275
- }
1276
- for (const child of Object.values(value)) {
1277
- const nested = findEmail(child, depth + 1);
1278
- if (nested) return nested;
1279
- }
1280
- return null;
1281
- }
1282
- function findPhone(value, depth = 0) {
1283
- if (depth > 6) return null;
1284
- if (Array.isArray(value)) {
1285
- for (const entry of value) {
1286
- const nested = findPhone(entry, depth + 1);
1287
- if (nested) return nested;
1288
- }
1289
- return null;
1290
- }
1291
- if (!isPlainObject(value)) return null;
1292
- for (const [key, child] of Object.entries(value)) {
1293
- if (PHONE_KEY_PATTERN.test(key)) {
1294
- const keyed = looksLikePhone(child);
1295
- if (keyed) return keyed;
1296
- }
1297
- }
1298
- for (const child of Object.values(value)) {
1299
- const nested = findPhone(child, depth + 1);
1300
- if (nested) return nested;
1301
- }
1302
- return null;
1303
- }
1304
- var DeeplineToolCallResult = class {
1305
- constructor(value) {
1306
- this.value = value;
1307
- }
1308
- value;
1309
- getEmail() {
1310
- return findEmail(this.value);
1311
- }
1312
- getPhone() {
1313
- return findPhone(this.value);
1314
- }
1315
- tryList(options) {
1316
- return tryConvertToList(this.value, options)?.rows ?? null;
1317
- }
1318
- };
1319
- function createToolCallResult(value) {
1320
- return new DeeplineToolCallResult(value);
1321
- }
1322
- function getByDottedPath(root, dottedPath) {
1323
- let current = root;
1324
- for (const segment of String(dottedPath || "").split(".").filter(Boolean)) {
1325
- if (!isPlainObject(current) || !(segment in current)) {
1326
- return null;
1327
- }
1328
- current = current[segment];
1329
- }
1330
- return current;
1331
- }
1332
- function normalizeRows(value) {
1333
- if (!Array.isArray(value)) return null;
1334
- return value.map((entry) => {
1335
- if (isPlainObject(entry)) return entry;
1336
- return { value: entry };
1337
- });
1338
- }
1339
- function candidateRoots(payload) {
1340
- const roots = [{ path: null, value: payload }];
1341
- if (isPlainObject(payload) && isPlainObject(payload.result)) {
1342
- roots.push({ path: "result", value: payload.result });
1343
- if (isPlainObject(payload.result.data)) {
1344
- roots.push({ path: "result.data", value: payload.result.data });
1345
- }
1346
- }
1347
- return roots;
1348
- }
1349
- function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
1350
- if (depth > 5) return null;
1351
- const directRows = normalizeRows(value);
1352
- const hasObjectRow = directRows?.some((row) => Object.keys(row).some((key) => key !== "value")) ?? false;
1353
- let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
1354
- if (!isPlainObject(value)) {
1355
- return best;
1356
- }
1357
- for (const [key, child] of Object.entries(value)) {
1358
- const childPath = pathPrefix ? `${pathPrefix}.${key}` : key;
1359
- const candidate = findBestArrayCandidate(child, childPath, depth + 1);
1360
- if (!candidate) continue;
1361
- if (!best || candidate.rows.length > best.rows.length) {
1362
- best = candidate;
1363
- }
1364
- }
1365
- return best;
1366
- }
1367
- function tryConvertToList(payload, options) {
1368
- const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
1369
- if (listExtractorPaths.length > 0) {
1370
- for (const root of candidateRoots(payload)) {
1371
- for (const extractorPath of listExtractorPaths) {
1372
- const resolved = getByDottedPath(root.value, extractorPath);
1373
- const rows = normalizeRows(resolved);
1374
- if (rows && rows.length > 0) {
1375
- const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
1376
- return { rows, strategy: "configured_paths", sourcePath };
1377
- }
1378
- }
1379
- }
1380
- }
1381
- for (const root of candidateRoots(payload)) {
1382
- const candidate = findBestArrayCandidate(root.value, root.path ?? "");
1383
- if (!candidate || candidate.rows.length === 0) continue;
1384
- return {
1385
- rows: candidate.rows,
1386
- strategy: "auto_detected",
1387
- sourcePath: candidate.path || root.path
1388
- };
1389
- }
1390
- return null;
1391
- }
1392
- function ensureOutputDir() {
1393
- const outputDir = join2(homedir2(), ".local", "share", "deepline", "data");
1394
- mkdirSync2(outputDir, { recursive: true });
1395
- return outputDir;
1396
- }
1397
- function writeJsonOutputFile(payload, stem) {
1398
- const outputDir = ensureOutputDir();
1399
- const outputPath = join2(outputDir, `${stem}_${Date.now()}.json`);
1400
- writeFileSync2(outputPath, JSON.stringify(payload, null, 2), "utf-8");
1401
- return outputPath;
1402
- }
1403
- function writeCsvOutputFile(rows, stem) {
1404
- const outputDir = ensureOutputDir();
1405
- const outputPath = join2(outputDir, `${stem}_${Date.now()}.csv`);
1406
- const seen = /* @__PURE__ */ new Set();
1407
- const columns = [];
1408
- for (const row of rows) {
1409
- for (const key of Object.keys(row)) {
1410
- if (!seen.has(key)) {
1411
- seen.add(key);
1412
- columns.push(key);
1413
- }
1414
- }
1415
- }
1416
- const escapeCell = (value) => {
1417
- const normalized = value == null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
1418
- if (/[",\n]/.test(normalized)) {
1419
- return `"${normalized.replace(/"/g, '""')}"`;
1420
- }
1421
- return normalized;
1422
- };
1423
- const lines = [];
1424
- lines.push(columns.map(escapeCell).join(","));
1425
- for (const row of rows) {
1426
- lines.push(columns.map((column) => escapeCell(row[column])).join(","));
1427
- }
1428
- writeFileSync2(outputPath, `${lines.join("\n")}
1429
- `, "utf-8");
1430
- const previewRows = rows.slice(0, 5);
1431
- const previewColumns = columns.slice(0, 5);
1432
- const preview = [
1433
- previewColumns.join(","),
1434
- ...previewRows.map((row) => previewColumns.map((column) => escapeCell(row[column])).join(","))
1435
- ].join("\n");
1436
- return {
1437
- path: outputPath,
1438
- rowCount: rows.length,
1439
- columns,
1440
- preview
1441
- };
1442
- }
1443
- function extractSummaryFields(payload) {
1444
- const candidates = candidateRoots(payload);
1445
- for (const candidate of candidates) {
1446
- if (!isPlainObject(candidate.value)) continue;
1447
- const summaryEntries = Object.entries(candidate.value).filter(([, value]) => {
1448
- return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
1449
- });
1450
- if (summaryEntries.length === 0) continue;
1451
- return Object.fromEntries(summaryEntries);
1452
- }
1453
- return {};
1454
- }
1455
-
1456
1211
  // src/play.ts
1457
1212
  var DeeplineConditionalStepResolver = class _DeeplineConditionalStepResolver {
1458
1213
  constructor(when2, run, elseValue) {
@@ -1591,12 +1346,8 @@ var DeeplineContext = class {
1591
1346
  * ```typescript
1592
1347
  * const tools = await ctx.tools.list();
1593
1348
  * const meta = await ctx.tools.get('apollo_people_search');
1594
- * const result = await ctx.tools.execute({
1595
- * tool: 'test_company_search',
1596
- * input: { domain: 'stripe.com' },
1597
- * });
1598
- * const rows = result.tryList({ listExtractorPaths: ['people'] });
1599
- * const email = result.getEmail();
1349
+ * const companyLookup = await ctx.tools.execute('test_company_search', { domain: 'stripe.com' });
1350
+ * const company = companyLookup.result.data;
1600
1351
  * ```
1601
1352
  */
1602
1353
  get tools() {
@@ -1605,10 +1356,8 @@ var DeeplineContext = class {
1605
1356
  list: () => this.client.listTools(),
1606
1357
  /** Get detailed metadata for a tool. */
1607
1358
  get: (toolId) => this.client.getTool(toolId),
1608
- /** Execute a tool and return an ergonomic result wrapper. */
1609
- execute: async (request) => createToolCallResult(
1610
- await this.client.executeTool(request.tool, request.input)
1611
- )
1359
+ /** Execute a tool and return the standard execution envelope. */
1360
+ execute: async (toolId, input) => this.client.executeTool(toolId, input)
1612
1361
  };
1613
1362
  }
1614
1363
  get plays() {
@@ -1811,6 +1560,147 @@ function getDefinedPlayMetadata(value) {
1811
1560
  }
1812
1561
  return candidate;
1813
1562
  }
1563
+
1564
+ // src/tool-output.ts
1565
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
1566
+ import { homedir as homedir2 } from "os";
1567
+ import { join as join2 } from "path";
1568
+ function isPlainObject(value) {
1569
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1570
+ }
1571
+ function getByDottedPath(root, dottedPath) {
1572
+ let current = root;
1573
+ for (const segment of String(dottedPath || "").split(".").filter(Boolean)) {
1574
+ if (!isPlainObject(current) || !(segment in current)) {
1575
+ return null;
1576
+ }
1577
+ current = current[segment];
1578
+ }
1579
+ return current;
1580
+ }
1581
+ function normalizeRows(value) {
1582
+ if (!Array.isArray(value)) return null;
1583
+ return value.map((entry) => {
1584
+ if (isPlainObject(entry)) return entry;
1585
+ return { value: entry };
1586
+ });
1587
+ }
1588
+ function candidateRoots(payload) {
1589
+ const roots = [{ path: null, value: payload }];
1590
+ if (isPlainObject(payload) && isPlainObject(payload.result)) {
1591
+ roots.push({ path: "result", value: payload.result });
1592
+ if (isPlainObject(payload.result.data)) {
1593
+ roots.push({ path: "result.data", value: payload.result.data });
1594
+ }
1595
+ }
1596
+ return roots;
1597
+ }
1598
+ function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
1599
+ if (depth > 5) return null;
1600
+ const directRows = normalizeRows(value);
1601
+ const hasObjectRow = directRows?.some((row) => Object.keys(row).some((key) => key !== "value")) ?? false;
1602
+ let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
1603
+ if (!isPlainObject(value)) {
1604
+ return best;
1605
+ }
1606
+ for (const [key, child] of Object.entries(value)) {
1607
+ const childPath = pathPrefix ? `${pathPrefix}.${key}` : key;
1608
+ const candidate = findBestArrayCandidate(child, childPath, depth + 1);
1609
+ if (!candidate) continue;
1610
+ if (!best || candidate.rows.length > best.rows.length) {
1611
+ best = candidate;
1612
+ }
1613
+ }
1614
+ return best;
1615
+ }
1616
+ function tryConvertToList(payload, options) {
1617
+ const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
1618
+ if (listExtractorPaths.length > 0) {
1619
+ for (const root of candidateRoots(payload)) {
1620
+ for (const extractorPath of listExtractorPaths) {
1621
+ const resolved = getByDottedPath(root.value, extractorPath);
1622
+ const rows = normalizeRows(resolved);
1623
+ if (rows && rows.length > 0) {
1624
+ const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
1625
+ return { rows, strategy: "configured_paths", sourcePath };
1626
+ }
1627
+ }
1628
+ }
1629
+ }
1630
+ for (const root of candidateRoots(payload)) {
1631
+ const candidate = findBestArrayCandidate(root.value, root.path ?? "");
1632
+ if (!candidate || candidate.rows.length === 0) continue;
1633
+ return {
1634
+ rows: candidate.rows,
1635
+ strategy: "auto_detected",
1636
+ sourcePath: candidate.path || root.path
1637
+ };
1638
+ }
1639
+ return null;
1640
+ }
1641
+ function ensureOutputDir() {
1642
+ const outputDir = join2(homedir2(), ".local", "share", "deepline", "data");
1643
+ mkdirSync2(outputDir, { recursive: true });
1644
+ return outputDir;
1645
+ }
1646
+ function writeJsonOutputFile(payload, stem) {
1647
+ const outputDir = ensureOutputDir();
1648
+ const outputPath = join2(outputDir, `${stem}_${Date.now()}.json`);
1649
+ writeFileSync2(outputPath, JSON.stringify(payload, null, 2), "utf-8");
1650
+ return outputPath;
1651
+ }
1652
+ function writeCsvOutputFile(rows, stem) {
1653
+ const outputDir = ensureOutputDir();
1654
+ const outputPath = join2(outputDir, `${stem}_${Date.now()}.csv`);
1655
+ const seen = /* @__PURE__ */ new Set();
1656
+ const columns = [];
1657
+ for (const row of rows) {
1658
+ for (const key of Object.keys(row)) {
1659
+ if (!seen.has(key)) {
1660
+ seen.add(key);
1661
+ columns.push(key);
1662
+ }
1663
+ }
1664
+ }
1665
+ const escapeCell = (value) => {
1666
+ const normalized = value == null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
1667
+ if (/[",\n]/.test(normalized)) {
1668
+ return `"${normalized.replace(/"/g, '""')}"`;
1669
+ }
1670
+ return normalized;
1671
+ };
1672
+ const lines = [];
1673
+ lines.push(columns.map(escapeCell).join(","));
1674
+ for (const row of rows) {
1675
+ lines.push(columns.map((column) => escapeCell(row[column])).join(","));
1676
+ }
1677
+ writeFileSync2(outputPath, `${lines.join("\n")}
1678
+ `, "utf-8");
1679
+ const previewRows = rows.slice(0, 5);
1680
+ const previewColumns = columns.slice(0, 5);
1681
+ const preview = [
1682
+ previewColumns.join(","),
1683
+ ...previewRows.map((row) => previewColumns.map((column) => escapeCell(row[column])).join(","))
1684
+ ].join("\n");
1685
+ return {
1686
+ path: outputPath,
1687
+ rowCount: rows.length,
1688
+ columns,
1689
+ preview
1690
+ };
1691
+ }
1692
+ function extractSummaryFields(payload) {
1693
+ const candidates = candidateRoots(payload);
1694
+ for (const candidate of candidates) {
1695
+ if (!isPlainObject(candidate.value)) continue;
1696
+ const summaryEntries = Object.entries(candidate.value).filter(([, value]) => {
1697
+ return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
1698
+ });
1699
+ if (summaryEntries.length === 0) continue;
1700
+ return Object.fromEntries(summaryEntries);
1701
+ }
1702
+ return {};
1703
+ }
1814
1704
  export {
1815
1705
  AuthError,
1816
1706
  ConfigError,
@@ -1822,7 +1712,6 @@ export {
1822
1712
  RateLimitError,
1823
1713
  SDK_API_CONTRACT,
1824
1714
  SDK_VERSION,
1825
- createToolCallResult,
1826
1715
  defineInput,
1827
1716
  definePlay,
1828
1717
  defineWorkflow,