deepline 0.1.30 → 0.1.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -266,8 +266,8 @@ function saveProjectDeeplineEnvValues(baseUrl, values, startDir = projectEnvStar
266
266
  }
267
267
 
268
268
  // src/version.ts
269
- var SDK_VERSION = "0.1.30";
270
- var SDK_API_CONTRACT = "2026-05-runs-v2-datasets";
269
+ var SDK_VERSION = "0.1.32";
270
+ var SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
271
271
 
272
272
  // ../shared_libs/play-runtime/coordinator-headers.ts
273
273
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
@@ -5572,7 +5572,7 @@ function inputContainsLocalFilePath(value) {
5572
5572
  return false;
5573
5573
  }
5574
5574
  function namedRunNeedsPlayDefinition(input) {
5575
- return input.revisionSelector === "latest" || getDottedInputValue(input.runtimeInput, "csv") != null || inputContainsLocalFilePath(input.runtimeInput);
5575
+ return input.revisionSelector === "latest" || inputContainsLocalFilePath(input.runtimeInput);
5576
5576
  }
5577
5577
  async function stageFileInputArgs(input) {
5578
5578
  const uniqueBindings = [
@@ -6384,7 +6384,7 @@ function stripProviderSpendFromBilling(value) {
6384
6384
  }
6385
6385
  return next;
6386
6386
  }
6387
- function compactPlayStatus(status, options) {
6387
+ function compactPlayStatus(status) {
6388
6388
  const rowsInfo = extractCanonicalRowsInfo(status);
6389
6389
  const result = status && typeof status === "object" ? status.result : null;
6390
6390
  const warnings = buildRunWarnings(status, rowsInfo);
@@ -6413,7 +6413,6 @@ function compactPlayStatus(status, options) {
6413
6413
  ...error ? { error } : {},
6414
6414
  ...warnings.length > 0 ? { warnings } : {},
6415
6415
  ...result !== void 0 ? { result } : {},
6416
- ...options?.exportedPath ? { local: { csv_path: options.exportedPath } } : {},
6417
6416
  ...status.resultView ? { resultView: status.resultView } : {},
6418
6417
  ...datasetStats ? { dataset_stats: datasetStats } : {},
6419
6418
  ...billing ? { billing } : {},
@@ -6455,7 +6454,7 @@ function formatDatasetStatsLines(datasetStats) {
6455
6454
  }
6456
6455
  function writePlayResult(status, jsonOutput, options) {
6457
6456
  if (jsonOutput) {
6458
- const payload2 = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status, options);
6457
+ const payload2 = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status);
6459
6458
  printCommandEnvelope({
6460
6459
  ...payload2,
6461
6460
  render: {
@@ -6485,9 +6484,6 @@ function writePlayResult(status, jsonOutput, options) {
6485
6484
  rowsInfo.columns,
6486
6485
  extractDatasetExecutionStats(status)
6487
6486
  ) : null;
6488
- if (options?.exportedPath) {
6489
- lines.push(` exported CSV: file=${options.exportedPath}`);
6490
- }
6491
6487
  for (const warning of warnings) {
6492
6488
  lines.push(` warning: ${warning}`);
6493
6489
  }
@@ -6505,7 +6501,7 @@ function writePlayResult(status, jsonOutput, options) {
6505
6501
  lines.push(...renderedServerView.lines);
6506
6502
  }
6507
6503
  lines.push(...renderedServerView.actions);
6508
- const payload = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status, options);
6504
+ const payload = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status);
6509
6505
  printCommandEnvelope({
6510
6506
  ...payload,
6511
6507
  render: {
@@ -6515,8 +6511,6 @@ function writePlayResult(status, jsonOutput, options) {
6515
6511
  ` });
6516
6512
  }
6517
6513
  var RUN_EXPORT_PAGE_SIZE = 5e3;
6518
- var PLAY_RUN_OUT_EXPORT_ATTEMPTS = 8;
6519
- var PLAY_RUN_OUT_EXPORT_RETRY_DELAY_MS = 1e3;
6520
6514
  function shellSingleQuote(value) {
6521
6515
  return `'${value.replace(/'/g, `'\\''`)}'`;
6522
6516
  }
@@ -6565,6 +6559,27 @@ function exportableSheetRow(row) {
6565
6559
  }
6566
6560
  return fallback;
6567
6561
  }
6562
+ function mergeExportColumns(preferredColumns, rows) {
6563
+ const columns = [];
6564
+ const seen = /* @__PURE__ */ new Set();
6565
+ for (const column of preferredColumns) {
6566
+ if (!column || seen.has(column)) {
6567
+ continue;
6568
+ }
6569
+ seen.add(column);
6570
+ columns.push(column);
6571
+ }
6572
+ for (const row of rows) {
6573
+ for (const column of Object.keys(row)) {
6574
+ if (seen.has(column)) {
6575
+ continue;
6576
+ }
6577
+ seen.add(column);
6578
+ columns.push(column);
6579
+ }
6580
+ }
6581
+ return columns;
6582
+ }
6568
6583
  async function fetchBackingDatasetRows(input) {
6569
6584
  const playName = extractRunPlayName(input.status);
6570
6585
  const tableNamespace = input.rowsInfo.tableNamespace?.trim();
@@ -6596,7 +6611,10 @@ async function fetchBackingDatasetRows(input) {
6596
6611
  if (rows.length < input.rowsInfo.totalRows) {
6597
6612
  return null;
6598
6613
  }
6599
- const columns = input.rowsInfo.columnsExplicit && input.rowsInfo.columns.length ? input.rowsInfo.columns : [...new Set(rows.flatMap((row) => Object.keys(row)))];
6614
+ const columns = mergeExportColumns(
6615
+ input.rowsInfo.columnsExplicit ? input.rowsInfo.columns : [],
6616
+ rows
6617
+ );
6600
6618
  return {
6601
6619
  ...input.rowsInfo,
6602
6620
  rows,
@@ -6638,20 +6656,27 @@ async function exportPlayStatusRows(client, status, outPath, options = {}) {
6638
6656
  const attempts = Math.max(1, Math.trunc(options.attempts ?? 1));
6639
6657
  const retryDelayMs = Math.max(0, Math.trunc(options.retryDelayMs ?? 0));
6640
6658
  for (let attempt = 1; attempt <= attempts; attempt += 1) {
6641
- if (rowsInfo.complete) {
6642
- return { path: writeCanonicalRowsCsv(rowsInfo, outPath), rowsInfo };
6659
+ let fetchedRowsInfo = null;
6660
+ try {
6661
+ fetchedRowsInfo = await fetchBackingDatasetRows({
6662
+ client,
6663
+ status,
6664
+ rowsInfo
6665
+ });
6666
+ } catch (error) {
6667
+ if (!rowsInfo.complete) {
6668
+ throw error;
6669
+ }
6643
6670
  }
6644
- const fetchedRowsInfo = await fetchBackingDatasetRows({
6645
- client,
6646
- status,
6647
- rowsInfo
6648
- });
6649
6671
  if (fetchedRowsInfo?.complete) {
6650
6672
  return {
6651
6673
  path: writeCanonicalRowsCsv(fetchedRowsInfo, outPath),
6652
6674
  rowsInfo: fetchedRowsInfo
6653
6675
  };
6654
6676
  }
6677
+ if (rowsInfo.complete) {
6678
+ return { path: writeCanonicalRowsCsv(rowsInfo, outPath), rowsInfo };
6679
+ }
6655
6680
  if (attempt < attempts && retryDelayMs > 0) {
6656
6681
  await sleep4(retryDelayMs);
6657
6682
  }
@@ -6779,7 +6804,7 @@ function writeStartedPlayRun(input) {
6779
6804
  ` });
6780
6805
  }
6781
6806
  function parsePlayRunOptions(args) {
6782
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.map guidance.";
6807
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--watch] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--watch] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--watch] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--watch] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.map guidance.";
6783
6808
  let filePath = null;
6784
6809
  let playName = null;
6785
6810
  let input = null;
@@ -6790,7 +6815,6 @@ function parsePlayRunOptions(args) {
6790
6815
  const emitLogs = !jsonOutput || args.includes("--logs");
6791
6816
  const force = args.includes("--force");
6792
6817
  const noOpen = args.includes("--no-open");
6793
- let outPath = null;
6794
6818
  let waitTimeoutMs = null;
6795
6819
  for (let index = 0; index < args.length; index += 1) {
6796
6820
  const arg = args[index];
@@ -6818,9 +6842,10 @@ function parsePlayRunOptions(args) {
6818
6842
  revisionSelector = "latest";
6819
6843
  continue;
6820
6844
  }
6821
- if (arg === "--out" && args[index + 1]) {
6822
- outPath = (0, import_node_path9.resolve)(args[++index]);
6823
- continue;
6845
+ if (arg === "--out" || arg.startsWith("--out=")) {
6846
+ throw new Error(
6847
+ "--out is not a plays run flag. Run the play first, then export rows with: deepline runs export <run-id> --out output.csv"
6848
+ );
6824
6849
  }
6825
6850
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
6826
6851
  throw new Error(
@@ -6849,11 +6874,6 @@ function parsePlayRunOptions(args) {
6849
6874
  }
6850
6875
  continue;
6851
6876
  }
6852
- if (arg === "--csv" || arg.startsWith("--csv=")) {
6853
- throw new Error(
6854
- `--csv is not a plays run flag. Pass CSV paths through --input, for example: deepline plays run my.play.ts --input '{"file":"leads.csv"}' --watch`
6855
- );
6856
- }
6857
6877
  if (arg.startsWith("--")) {
6858
6878
  const { path, value } = parseInputFieldFlag(arg, args[index + 1]);
6859
6879
  input ??= {};
@@ -6890,11 +6910,6 @@ function parsePlayRunOptions(args) {
6890
6910
  "--live, --latest, and --revision-id only apply to named plays."
6891
6911
  );
6892
6912
  }
6893
- if (outPath && !watch) {
6894
- throw new Error(
6895
- "--out requires --watch so the CLI can export the completed run output."
6896
- );
6897
- }
6898
6913
  return {
6899
6914
  target: filePath ? { kind: "file", path: filePath } : { kind: "name", name: playName },
6900
6915
  input,
@@ -6905,7 +6920,6 @@ function parsePlayRunOptions(args) {
6905
6920
  jsonOutput,
6906
6921
  waitTimeoutMs,
6907
6922
  force,
6908
- outPath,
6909
6923
  noOpen
6910
6924
  };
6911
6925
  }
@@ -7080,14 +7094,6 @@ async function handleFileBackedRun(options) {
7080
7094
  progress
7081
7095
  })
7082
7096
  );
7083
- const exportResult = await traceCliSpan(
7084
- "cli.play_export_rows",
7085
- { targetKind: "file", playName },
7086
- () => exportPlayStatusRows(client, finalStatus, options.outPath, {
7087
- attempts: PLAY_RUN_OUT_EXPORT_ATTEMPTS,
7088
- retryDelayMs: PLAY_RUN_OUT_EXPORT_RETRY_DELAY_MS
7089
- })
7090
- );
7091
7097
  if (finalStatus.status === "completed") {
7092
7098
  progress.complete();
7093
7099
  } else {
@@ -7096,7 +7102,7 @@ async function handleFileBackedRun(options) {
7096
7102
  traceCliSync(
7097
7103
  "cli.play_write_result",
7098
7104
  { targetKind: "file", playName },
7099
- () => writePlayResult(finalStatus, options.jsonOutput, { exportedPath: exportResult?.path ?? null })
7105
+ () => writePlayResult(finalStatus, options.jsonOutput)
7100
7106
  );
7101
7107
  return finalStatus.status === "completed" ? 0 : 1;
7102
7108
  }
@@ -7224,14 +7230,6 @@ async function handleNamedRun(options) {
7224
7230
  progress
7225
7231
  })
7226
7232
  );
7227
- const exportResult = await traceCliSpan(
7228
- "cli.play_export_rows",
7229
- { targetKind: "name", playName },
7230
- () => exportPlayStatusRows(client, finalStatus, options.outPath, {
7231
- attempts: PLAY_RUN_OUT_EXPORT_ATTEMPTS,
7232
- retryDelayMs: PLAY_RUN_OUT_EXPORT_RETRY_DELAY_MS
7233
- })
7234
- );
7235
7233
  if (finalStatus.status === "completed") {
7236
7234
  progress.complete();
7237
7235
  } else {
@@ -7240,7 +7238,7 @@ async function handleNamedRun(options) {
7240
7238
  traceCliSync(
7241
7239
  "cli.play_write_result",
7242
7240
  { targetKind: "name", playName },
7243
- () => writePlayResult(finalStatus, options.jsonOutput, { exportedPath: exportResult?.path ?? null })
7241
+ () => writePlayResult(finalStatus, options.jsonOutput)
7244
7242
  );
7245
7243
  return finalStatus.status === "completed" ? 0 : 1;
7246
7244
  }
@@ -8006,17 +8004,14 @@ Idempotent execution:
8006
8004
  Examples:
8007
8005
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
8008
8006
  deepline plays run my.play.ts --input @input.json --wait --json
8009
- deepline plays run enrich.play.ts --input '{"file":"leads.csv"}' --watch --out leads-enriched.csv
8010
8007
  deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}' --watch
8011
8008
  deepline plays run cto-search.play.ts --limit 5 --watch
8009
+ deepline runs export <run-id> --out output.csv
8012
8010
  deepline runs get <run-id>
8013
8011
  `
8014
8012
  ).option("--file <path>", "Local play file to run").option("--name <name>", "Saved play name to run").option("-i, --input <json>", "Input JSON object or @file path").option("--live", "Run the current live revision explicitly").option("--latest", "Run the newest saved revision, even if it is not live").option(
8015
8013
  "--revision-id <id>",
8016
8014
  "Run a specific saved revision instead of the live revision"
8017
- ).option(
8018
- "--out <path>",
8019
- "Write the completed row output to CSV; requires --watch"
8020
8015
  ).option("--watch", "Stream logs until completion").option("--wait", "Alias for --watch; stream logs until completion").option(
8021
8016
  "--logs",
8022
8017
  "When output is non-interactive, stream play logs to stderr while waiting"
@@ -8026,8 +8021,10 @@ Examples:
8026
8021
  Pass-through input flags:
8027
8022
  Unknown flags are accepted intentionally and become play input fields. Use
8028
8023
  this for play-specific inputs like --limit 5 or --filters.title "GTM Engineer".
8029
- For CSV file inputs, prefer --input '{"file":"leads.csv"}' so the field name
8030
- matches the play's ctx.csv(input.file) contract.
8024
+ For CSV file inputs, the play owns the field name: --csv leads.csv becomes
8025
+ input.csv, and --columns.email "Email" becomes input.columns.email. Reserved
8026
+ run flags like --file and --name keep their command meaning; pass fields with
8027
+ those names through --input '{"file":"leads.csv"}'.
8031
8028
  `
8032
8029
  ).action(async (target, options, command) => {
8033
8030
  const passthroughArgs = [...command.args];
@@ -8048,7 +8045,6 @@ Pass-through input flags:
8048
8045
  ...options.live ? ["--live"] : [],
8049
8046
  ...options.latest ? ["--latest"] : [],
8050
8047
  ...options.revisionId ? ["--revision-id", options.revisionId] : [],
8051
- ...options.out ? ["--out", options.out] : [],
8052
8048
  ...options.watch || options.wait ? ["--watch"] : [],
8053
8049
  ...options.logs ? ["--logs"] : [],
8054
8050
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
@@ -243,8 +243,8 @@ function saveProjectDeeplineEnvValues(baseUrl, values, startDir = projectEnvStar
243
243
  }
244
244
 
245
245
  // src/version.ts
246
- var SDK_VERSION = "0.1.30";
247
- var SDK_API_CONTRACT = "2026-05-runs-v2-datasets";
246
+ var SDK_VERSION = "0.1.32";
247
+ var SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
248
248
 
249
249
  // ../shared_libs/play-runtime/coordinator-headers.ts
250
250
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
@@ -5559,7 +5559,7 @@ function inputContainsLocalFilePath(value) {
5559
5559
  return false;
5560
5560
  }
5561
5561
  function namedRunNeedsPlayDefinition(input) {
5562
- return input.revisionSelector === "latest" || getDottedInputValue(input.runtimeInput, "csv") != null || inputContainsLocalFilePath(input.runtimeInput);
5562
+ return input.revisionSelector === "latest" || inputContainsLocalFilePath(input.runtimeInput);
5563
5563
  }
5564
5564
  async function stageFileInputArgs(input) {
5565
5565
  const uniqueBindings = [
@@ -6371,7 +6371,7 @@ function stripProviderSpendFromBilling(value) {
6371
6371
  }
6372
6372
  return next;
6373
6373
  }
6374
- function compactPlayStatus(status, options) {
6374
+ function compactPlayStatus(status) {
6375
6375
  const rowsInfo = extractCanonicalRowsInfo(status);
6376
6376
  const result = status && typeof status === "object" ? status.result : null;
6377
6377
  const warnings = buildRunWarnings(status, rowsInfo);
@@ -6400,7 +6400,6 @@ function compactPlayStatus(status, options) {
6400
6400
  ...error ? { error } : {},
6401
6401
  ...warnings.length > 0 ? { warnings } : {},
6402
6402
  ...result !== void 0 ? { result } : {},
6403
- ...options?.exportedPath ? { local: { csv_path: options.exportedPath } } : {},
6404
6403
  ...status.resultView ? { resultView: status.resultView } : {},
6405
6404
  ...datasetStats ? { dataset_stats: datasetStats } : {},
6406
6405
  ...billing ? { billing } : {},
@@ -6442,7 +6441,7 @@ function formatDatasetStatsLines(datasetStats) {
6442
6441
  }
6443
6442
  function writePlayResult(status, jsonOutput, options) {
6444
6443
  if (jsonOutput) {
6445
- const payload2 = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status, options);
6444
+ const payload2 = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status);
6446
6445
  printCommandEnvelope({
6447
6446
  ...payload2,
6448
6447
  render: {
@@ -6472,9 +6471,6 @@ function writePlayResult(status, jsonOutput, options) {
6472
6471
  rowsInfo.columns,
6473
6472
  extractDatasetExecutionStats(status)
6474
6473
  ) : null;
6475
- if (options?.exportedPath) {
6476
- lines.push(` exported CSV: file=${options.exportedPath}`);
6477
- }
6478
6474
  for (const warning of warnings) {
6479
6475
  lines.push(` warning: ${warning}`);
6480
6476
  }
@@ -6492,7 +6488,7 @@ function writePlayResult(status, jsonOutput, options) {
6492
6488
  lines.push(...renderedServerView.lines);
6493
6489
  }
6494
6490
  lines.push(...renderedServerView.actions);
6495
- const payload = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status, options);
6491
+ const payload = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status);
6496
6492
  printCommandEnvelope({
6497
6493
  ...payload,
6498
6494
  render: {
@@ -6502,8 +6498,6 @@ function writePlayResult(status, jsonOutput, options) {
6502
6498
  ` });
6503
6499
  }
6504
6500
  var RUN_EXPORT_PAGE_SIZE = 5e3;
6505
- var PLAY_RUN_OUT_EXPORT_ATTEMPTS = 8;
6506
- var PLAY_RUN_OUT_EXPORT_RETRY_DELAY_MS = 1e3;
6507
6501
  function shellSingleQuote(value) {
6508
6502
  return `'${value.replace(/'/g, `'\\''`)}'`;
6509
6503
  }
@@ -6552,6 +6546,27 @@ function exportableSheetRow(row) {
6552
6546
  }
6553
6547
  return fallback;
6554
6548
  }
6549
+ function mergeExportColumns(preferredColumns, rows) {
6550
+ const columns = [];
6551
+ const seen = /* @__PURE__ */ new Set();
6552
+ for (const column of preferredColumns) {
6553
+ if (!column || seen.has(column)) {
6554
+ continue;
6555
+ }
6556
+ seen.add(column);
6557
+ columns.push(column);
6558
+ }
6559
+ for (const row of rows) {
6560
+ for (const column of Object.keys(row)) {
6561
+ if (seen.has(column)) {
6562
+ continue;
6563
+ }
6564
+ seen.add(column);
6565
+ columns.push(column);
6566
+ }
6567
+ }
6568
+ return columns;
6569
+ }
6555
6570
  async function fetchBackingDatasetRows(input) {
6556
6571
  const playName = extractRunPlayName(input.status);
6557
6572
  const tableNamespace = input.rowsInfo.tableNamespace?.trim();
@@ -6583,7 +6598,10 @@ async function fetchBackingDatasetRows(input) {
6583
6598
  if (rows.length < input.rowsInfo.totalRows) {
6584
6599
  return null;
6585
6600
  }
6586
- const columns = input.rowsInfo.columnsExplicit && input.rowsInfo.columns.length ? input.rowsInfo.columns : [...new Set(rows.flatMap((row) => Object.keys(row)))];
6601
+ const columns = mergeExportColumns(
6602
+ input.rowsInfo.columnsExplicit ? input.rowsInfo.columns : [],
6603
+ rows
6604
+ );
6587
6605
  return {
6588
6606
  ...input.rowsInfo,
6589
6607
  rows,
@@ -6625,20 +6643,27 @@ async function exportPlayStatusRows(client, status, outPath, options = {}) {
6625
6643
  const attempts = Math.max(1, Math.trunc(options.attempts ?? 1));
6626
6644
  const retryDelayMs = Math.max(0, Math.trunc(options.retryDelayMs ?? 0));
6627
6645
  for (let attempt = 1; attempt <= attempts; attempt += 1) {
6628
- if (rowsInfo.complete) {
6629
- return { path: writeCanonicalRowsCsv(rowsInfo, outPath), rowsInfo };
6646
+ let fetchedRowsInfo = null;
6647
+ try {
6648
+ fetchedRowsInfo = await fetchBackingDatasetRows({
6649
+ client,
6650
+ status,
6651
+ rowsInfo
6652
+ });
6653
+ } catch (error) {
6654
+ if (!rowsInfo.complete) {
6655
+ throw error;
6656
+ }
6630
6657
  }
6631
- const fetchedRowsInfo = await fetchBackingDatasetRows({
6632
- client,
6633
- status,
6634
- rowsInfo
6635
- });
6636
6658
  if (fetchedRowsInfo?.complete) {
6637
6659
  return {
6638
6660
  path: writeCanonicalRowsCsv(fetchedRowsInfo, outPath),
6639
6661
  rowsInfo: fetchedRowsInfo
6640
6662
  };
6641
6663
  }
6664
+ if (rowsInfo.complete) {
6665
+ return { path: writeCanonicalRowsCsv(rowsInfo, outPath), rowsInfo };
6666
+ }
6642
6667
  if (attempt < attempts && retryDelayMs > 0) {
6643
6668
  await sleep4(retryDelayMs);
6644
6669
  }
@@ -6766,7 +6791,7 @@ function writeStartedPlayRun(input) {
6766
6791
  ` });
6767
6792
  }
6768
6793
  function parsePlayRunOptions(args) {
6769
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.map guidance.";
6794
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--watch] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--watch] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--watch] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--watch] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.map guidance.";
6770
6795
  let filePath = null;
6771
6796
  let playName = null;
6772
6797
  let input = null;
@@ -6777,7 +6802,6 @@ function parsePlayRunOptions(args) {
6777
6802
  const emitLogs = !jsonOutput || args.includes("--logs");
6778
6803
  const force = args.includes("--force");
6779
6804
  const noOpen = args.includes("--no-open");
6780
- let outPath = null;
6781
6805
  let waitTimeoutMs = null;
6782
6806
  for (let index = 0; index < args.length; index += 1) {
6783
6807
  const arg = args[index];
@@ -6805,9 +6829,10 @@ function parsePlayRunOptions(args) {
6805
6829
  revisionSelector = "latest";
6806
6830
  continue;
6807
6831
  }
6808
- if (arg === "--out" && args[index + 1]) {
6809
- outPath = resolve8(args[++index]);
6810
- continue;
6832
+ if (arg === "--out" || arg.startsWith("--out=")) {
6833
+ throw new Error(
6834
+ "--out is not a plays run flag. Run the play first, then export rows with: deepline runs export <run-id> --out output.csv"
6835
+ );
6811
6836
  }
6812
6837
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
6813
6838
  throw new Error(
@@ -6836,11 +6861,6 @@ function parsePlayRunOptions(args) {
6836
6861
  }
6837
6862
  continue;
6838
6863
  }
6839
- if (arg === "--csv" || arg.startsWith("--csv=")) {
6840
- throw new Error(
6841
- `--csv is not a plays run flag. Pass CSV paths through --input, for example: deepline plays run my.play.ts --input '{"file":"leads.csv"}' --watch`
6842
- );
6843
- }
6844
6864
  if (arg.startsWith("--")) {
6845
6865
  const { path, value } = parseInputFieldFlag(arg, args[index + 1]);
6846
6866
  input ??= {};
@@ -6877,11 +6897,6 @@ function parsePlayRunOptions(args) {
6877
6897
  "--live, --latest, and --revision-id only apply to named plays."
6878
6898
  );
6879
6899
  }
6880
- if (outPath && !watch) {
6881
- throw new Error(
6882
- "--out requires --watch so the CLI can export the completed run output."
6883
- );
6884
- }
6885
6900
  return {
6886
6901
  target: filePath ? { kind: "file", path: filePath } : { kind: "name", name: playName },
6887
6902
  input,
@@ -6892,7 +6907,6 @@ function parsePlayRunOptions(args) {
6892
6907
  jsonOutput,
6893
6908
  waitTimeoutMs,
6894
6909
  force,
6895
- outPath,
6896
6910
  noOpen
6897
6911
  };
6898
6912
  }
@@ -7067,14 +7081,6 @@ async function handleFileBackedRun(options) {
7067
7081
  progress
7068
7082
  })
7069
7083
  );
7070
- const exportResult = await traceCliSpan(
7071
- "cli.play_export_rows",
7072
- { targetKind: "file", playName },
7073
- () => exportPlayStatusRows(client, finalStatus, options.outPath, {
7074
- attempts: PLAY_RUN_OUT_EXPORT_ATTEMPTS,
7075
- retryDelayMs: PLAY_RUN_OUT_EXPORT_RETRY_DELAY_MS
7076
- })
7077
- );
7078
7084
  if (finalStatus.status === "completed") {
7079
7085
  progress.complete();
7080
7086
  } else {
@@ -7083,7 +7089,7 @@ async function handleFileBackedRun(options) {
7083
7089
  traceCliSync(
7084
7090
  "cli.play_write_result",
7085
7091
  { targetKind: "file", playName },
7086
- () => writePlayResult(finalStatus, options.jsonOutput, { exportedPath: exportResult?.path ?? null })
7092
+ () => writePlayResult(finalStatus, options.jsonOutput)
7087
7093
  );
7088
7094
  return finalStatus.status === "completed" ? 0 : 1;
7089
7095
  }
@@ -7211,14 +7217,6 @@ async function handleNamedRun(options) {
7211
7217
  progress
7212
7218
  })
7213
7219
  );
7214
- const exportResult = await traceCliSpan(
7215
- "cli.play_export_rows",
7216
- { targetKind: "name", playName },
7217
- () => exportPlayStatusRows(client, finalStatus, options.outPath, {
7218
- attempts: PLAY_RUN_OUT_EXPORT_ATTEMPTS,
7219
- retryDelayMs: PLAY_RUN_OUT_EXPORT_RETRY_DELAY_MS
7220
- })
7221
- );
7222
7220
  if (finalStatus.status === "completed") {
7223
7221
  progress.complete();
7224
7222
  } else {
@@ -7227,7 +7225,7 @@ async function handleNamedRun(options) {
7227
7225
  traceCliSync(
7228
7226
  "cli.play_write_result",
7229
7227
  { targetKind: "name", playName },
7230
- () => writePlayResult(finalStatus, options.jsonOutput, { exportedPath: exportResult?.path ?? null })
7228
+ () => writePlayResult(finalStatus, options.jsonOutput)
7231
7229
  );
7232
7230
  return finalStatus.status === "completed" ? 0 : 1;
7233
7231
  }
@@ -7993,17 +7991,14 @@ Idempotent execution:
7993
7991
  Examples:
7994
7992
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
7995
7993
  deepline plays run my.play.ts --input @input.json --wait --json
7996
- deepline plays run enrich.play.ts --input '{"file":"leads.csv"}' --watch --out leads-enriched.csv
7997
7994
  deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}' --watch
7998
7995
  deepline plays run cto-search.play.ts --limit 5 --watch
7996
+ deepline runs export <run-id> --out output.csv
7999
7997
  deepline runs get <run-id>
8000
7998
  `
8001
7999
  ).option("--file <path>", "Local play file to run").option("--name <name>", "Saved play name to run").option("-i, --input <json>", "Input JSON object or @file path").option("--live", "Run the current live revision explicitly").option("--latest", "Run the newest saved revision, even if it is not live").option(
8002
8000
  "--revision-id <id>",
8003
8001
  "Run a specific saved revision instead of the live revision"
8004
- ).option(
8005
- "--out <path>",
8006
- "Write the completed row output to CSV; requires --watch"
8007
8002
  ).option("--watch", "Stream logs until completion").option("--wait", "Alias for --watch; stream logs until completion").option(
8008
8003
  "--logs",
8009
8004
  "When output is non-interactive, stream play logs to stderr while waiting"
@@ -8013,8 +8008,10 @@ Examples:
8013
8008
  Pass-through input flags:
8014
8009
  Unknown flags are accepted intentionally and become play input fields. Use
8015
8010
  this for play-specific inputs like --limit 5 or --filters.title "GTM Engineer".
8016
- For CSV file inputs, prefer --input '{"file":"leads.csv"}' so the field name
8017
- matches the play's ctx.csv(input.file) contract.
8011
+ For CSV file inputs, the play owns the field name: --csv leads.csv becomes
8012
+ input.csv, and --columns.email "Email" becomes input.columns.email. Reserved
8013
+ run flags like --file and --name keep their command meaning; pass fields with
8014
+ those names through --input '{"file":"leads.csv"}'.
8018
8015
  `
8019
8016
  ).action(async (target, options, command) => {
8020
8017
  const passthroughArgs = [...command.args];
@@ -8035,7 +8032,6 @@ Pass-through input flags:
8035
8032
  ...options.live ? ["--live"] : [],
8036
8033
  ...options.latest ? ["--latest"] : [],
8037
8034
  ...options.revisionId ? ["--revision-id", options.revisionId] : [],
8038
- ...options.out ? ["--out", options.out] : [],
8039
8035
  ...options.watch || options.wait ? ["--watch"] : [],
8040
8036
  ...options.logs ? ["--logs"] : [],
8041
8037
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
package/dist/index.d.mts CHANGED
@@ -1438,8 +1438,8 @@ declare class DeeplineClient {
1438
1438
  }>;
1439
1439
  }
1440
1440
 
1441
- declare const SDK_VERSION = "0.1.30";
1442
- declare const SDK_API_CONTRACT = "2026-05-runs-v2-datasets";
1441
+ declare const SDK_VERSION = "0.1.32";
1442
+ declare const SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
1443
1443
 
1444
1444
  /**
1445
1445
  * Base error class for all Deepline SDK errors.
package/dist/index.d.ts CHANGED
@@ -1438,8 +1438,8 @@ declare class DeeplineClient {
1438
1438
  }>;
1439
1439
  }
1440
1440
 
1441
- declare const SDK_VERSION = "0.1.30";
1442
- declare const SDK_API_CONTRACT = "2026-05-runs-v2-datasets";
1441
+ declare const SDK_VERSION = "0.1.32";
1442
+ declare const SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
1443
1443
 
1444
1444
  /**
1445
1445
  * Base error class for all Deepline SDK errors.
package/dist/index.js CHANGED
@@ -241,8 +241,8 @@ function resolveConfig(options) {
241
241
  }
242
242
 
243
243
  // src/version.ts
244
- var SDK_VERSION = "0.1.30";
245
- var SDK_API_CONTRACT = "2026-05-runs-v2-datasets";
244
+ var SDK_VERSION = "0.1.32";
245
+ var SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
246
246
 
247
247
  // ../shared_libs/play-runtime/coordinator-headers.ts
248
248
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
package/dist/index.mjs CHANGED
@@ -195,8 +195,8 @@ function resolveConfig(options) {
195
195
  }
196
196
 
197
197
  // src/version.ts
198
- var SDK_VERSION = "0.1.30";
199
- var SDK_API_CONTRACT = "2026-05-runs-v2-datasets";
198
+ var SDK_VERSION = "0.1.32";
199
+ var SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
200
200
 
201
201
  // ../shared_libs/play-runtime/coordinator-headers.ts
202
202
  var COORDINATOR_INTERNAL_TOKEN_HEADER = "x-deepline-internal-token";
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.30";
2
- export const SDK_API_CONTRACT = "2026-05-runs-v2-datasets";
1
+ export const SDK_VERSION = "0.1.32";
2
+ export const SDK_API_CONTRACT = "2026-05-generic-play-input-flags";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {