deepline 0.1.145 → 0.1.147

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.
@@ -604,10 +604,11 @@ var SDK_RELEASE = {
604
604
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
605
605
  // the SDK enrich generator's one-second stale policy.
606
606
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
607
- version: "0.1.145",
608
- apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
607
+ // 0.1.111 ships dataset-native tool list getters and result row datasets.
608
+ version: "0.1.147",
609
+ apiContract: "2026-06-dataset-handle-results-hard-cutover",
609
610
  supportPolicy: {
610
- latest: "0.1.145",
611
+ latest: "0.1.147",
611
612
  minimumSupported: "0.1.53",
612
613
  deprecatedBelow: "0.1.53",
613
614
  commandMinimumSupported: [
@@ -618,52 +619,79 @@ var SDK_RELEASE = {
618
619
  },
619
620
  {
620
621
  command: "plays",
621
- minimumSupported: "0.1.110",
622
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
622
+ minimumSupported: "0.1.111",
623
+ reason: "Play file commands now use dataset-native list getters and result row datasets."
623
624
  },
624
625
  {
625
626
  command: "plays run",
626
- minimumSupported: "0.1.110",
627
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
627
+ minimumSupported: "0.1.111",
628
+ reason: "Play run results now promote row-shaped outputs into dataset handles for safe export."
628
629
  },
629
630
  {
630
631
  command: "run",
631
632
  displayCommand: "plays run",
632
- minimumSupported: "0.1.110",
633
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
633
+ minimumSupported: "0.1.111",
634
+ reason: "Play run results now promote row-shaped outputs into dataset handles for safe export."
634
635
  },
635
636
  {
636
637
  command: "plays check",
637
- minimumSupported: "0.1.110",
638
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
638
+ minimumSupported: "0.1.111",
639
+ reason: "Play file checks now validate dataset-native list getter authoring."
639
640
  },
640
641
  {
641
642
  command: "check",
642
643
  displayCommand: "plays check",
643
- minimumSupported: "0.1.110",
644
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
644
+ minimumSupported: "0.1.111",
645
+ reason: "Play file checks now validate dataset-native list getter authoring."
645
646
  },
646
647
  {
647
648
  command: "plays publish",
648
- minimumSupported: "0.1.110",
649
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
649
+ minimumSupported: "0.1.111",
650
+ reason: "Published play artifacts now target dataset-native list getters and result row datasets."
650
651
  },
651
652
  {
652
653
  command: "publish",
653
654
  displayCommand: "plays publish",
654
- minimumSupported: "0.1.110",
655
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
655
+ minimumSupported: "0.1.111",
656
+ reason: "Published play artifacts now target dataset-native list getters and result row datasets."
656
657
  },
657
658
  {
658
659
  command: "plays set-live",
659
- minimumSupported: "0.1.110",
660
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
660
+ minimumSupported: "0.1.111",
661
+ reason: "Published play artifacts now target dataset-native list getters and result row datasets."
661
662
  },
662
663
  {
663
664
  command: "set-live",
664
665
  displayCommand: "plays set-live",
665
- minimumSupported: "0.1.110",
666
- reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
666
+ minimumSupported: "0.1.111",
667
+ reason: "Published play artifacts now target dataset-native list getters and result row datasets."
668
+ },
669
+ {
670
+ command: "runs",
671
+ minimumSupported: "0.1.111",
672
+ reason: "Run result rows now render as dataset handles with explicit export commands."
673
+ },
674
+ {
675
+ command: "runs get",
676
+ minimumSupported: "0.1.111",
677
+ reason: "Run result rows now render as dataset handles with explicit export commands."
678
+ },
679
+ {
680
+ command: "get",
681
+ displayCommand: "runs get",
682
+ minimumSupported: "0.1.111",
683
+ reason: "Run result rows now render as dataset handles with explicit export commands."
684
+ },
685
+ {
686
+ command: "runs export",
687
+ minimumSupported: "0.1.111",
688
+ reason: "Run result row datasets now use the dataset-handle export contract."
689
+ },
690
+ {
691
+ command: "export",
692
+ displayCommand: "runs export",
693
+ minimumSupported: "0.1.111",
694
+ reason: "Run result row datasets now use the dataset-handle export contract."
667
695
  }
668
696
  ],
669
697
  autoUpdatePatchLag: 2
@@ -8319,9 +8347,10 @@ function generateProviderSourceBlock(input2) {
8319
8347
  input: ${inputName},
8320
8348
  description: ${jsString(`Seed ${input2.entity} rows from ${input2.provider}.`)},
8321
8349
  });
8322
- // extractedLists.${getter}.get() returns provider-shaped rows. Do not assume canonical fields;
8350
+ // extractedLists.${getter}.get() returns a dataset handle of provider-shaped rows. Do not assume canonical fields;
8323
8351
  // inspect source_${input2.index}.extractedLists.${getter}.keys or the provider output schema, then map explicitly below.
8324
- const sourceRows_${input2.index} = ${accessorExpression(`source_${input2.index}.extractedLists`, getter)}.get() as ${input2.collectionType}[];`;
8352
+ const sourceRowsDataset_${input2.index} = ${accessorExpression(`source_${input2.index}.extractedLists`, getter)}.get();
8353
+ const sourceRows_${input2.index} = (await sourceRowsDataset_${input2.index}.peek(limit)) as ${input2.collectionType}[];`;
8325
8354
  }
8326
8355
  function generateProviderSourceRowsBlock(input2) {
8327
8356
  const blocks = input2.source.values.map(
@@ -11007,6 +11036,9 @@ function formatPlayLogLine(line, status, state) {
11007
11036
  }
11008
11037
  return `${prefix}${message}`;
11009
11038
  }
11039
+ function isDatasetResultEnvelope(value) {
11040
+ return value !== null && typeof value === "object" && !Array.isArray(value) && value.kind === "dataset";
11041
+ }
11010
11042
  function compactReturnValue(value, depth = 0) {
11011
11043
  if (depth >= 4) {
11012
11044
  return value && typeof value === "object" ? "[Object]" : value;
@@ -11018,6 +11050,7 @@ function compactReturnValue(value, depth = 0) {
11018
11050
  if (!value || typeof value !== "object") {
11019
11051
  return value;
11020
11052
  }
11053
+ const isDatasetEnvelope = isDatasetResultEnvelope(value);
11021
11054
  const output2 = {};
11022
11055
  for (const [key, entry] of Object.entries(value)) {
11023
11056
  if (depth === 0 && key === "_metadata") {
@@ -11026,13 +11059,41 @@ function compactReturnValue(value, depth = 0) {
11026
11059
  if (BULKY_RETURN_KEYS.has(key)) {
11027
11060
  continue;
11028
11061
  }
11029
- if (key === "access") {
11062
+ if (isDatasetEnvelope && key === "access") {
11063
+ continue;
11064
+ }
11065
+ if (isDatasetEnvelope && (key === "queryDatasetCommand" || key === "cliCommand")) {
11066
+ continue;
11067
+ }
11068
+ if (isDatasetEnvelope && key === "slowExportAsCsvCommand") {
11069
+ output2.fullExportCommand = entry;
11030
11070
  continue;
11031
11071
  }
11032
11072
  output2[key] = compactReturnValue(entry, depth + 1);
11033
11073
  }
11034
11074
  return output2;
11035
11075
  }
11076
+ function defaultResultForEnvelope(value, depth = 0) {
11077
+ if (depth > 20 || value == null || typeof value !== "object") {
11078
+ return value;
11079
+ }
11080
+ if (Array.isArray(value)) {
11081
+ return value.map((entry) => defaultResultForEnvelope(entry, depth + 1));
11082
+ }
11083
+ const isDatasetEnvelope = isDatasetResultEnvelope(value);
11084
+ const output2 = {};
11085
+ for (const [key, entry] of Object.entries(value)) {
11086
+ if (isDatasetEnvelope && (key === "queryDatasetCommand" || key === "cliCommand")) {
11087
+ continue;
11088
+ }
11089
+ if (isDatasetEnvelope && key === "slowExportAsCsvCommand") {
11090
+ output2.fullExportCommand = entry;
11091
+ continue;
11092
+ }
11093
+ output2[key] = defaultResultForEnvelope(entry, depth + 1);
11094
+ }
11095
+ return output2;
11096
+ }
11036
11097
  function formatJsonPreview(value) {
11037
11098
  const json = JSON.stringify(value, null, 2);
11038
11099
  if (!json || json === "{}") {
@@ -11076,9 +11137,6 @@ function collectDatasetHandleLines(value, path = "result", datasetStats) {
11076
11137
  if (datasetStats && (datasetStats.source === path || datasetStats.source === record.path)) {
11077
11138
  lines2.push(...formatDatasetStatsLines(datasetStats.stats, " "));
11078
11139
  }
11079
- if (typeof record.queryDatasetCommand === "string") {
11080
- lines2.push(` query dataset: ${record.queryDatasetCommand}`);
11081
- }
11082
11140
  if (typeof record.slowExportAsCsvCommand === "string") {
11083
11141
  lines2.push(` export CSV: ${record.slowExportAsCsvCommand}`);
11084
11142
  }
@@ -11489,7 +11547,7 @@ function compactPlayStatus(status) {
11489
11547
  logs: normalizeLogsForEnvelope(status),
11490
11548
  ...displayError ? { error: displayError } : {},
11491
11549
  ...warnings.length > 0 ? { warnings } : {},
11492
- ...result !== void 0 ? { result } : {},
11550
+ ...result !== void 0 ? { result: defaultResultForEnvelope(result) } : {},
11493
11551
  ...billing ? { billing } : {},
11494
11552
  next: buildRunNextCommands(status)
11495
11553
  };
@@ -18970,6 +19028,221 @@ Examples:
18970
19028
  }
18971
19029
  }
18972
19030
 
19031
+ // src/cli/commands/monitors.ts
19032
+ var FORBIDDEN_AS_API_ERROR = { forbiddenAsApiError: true };
19033
+ function buildHttpClient() {
19034
+ return new HttpClient(resolveConfig());
19035
+ }
19036
+ function parseJsonObjectArg(raw, flag) {
19037
+ let parsed;
19038
+ try {
19039
+ parsed = JSON.parse(raw);
19040
+ } catch (error) {
19041
+ throw new Error(
19042
+ `${flag} must be a JSON object. ${error instanceof Error ? error.message : String(error)}`
19043
+ );
19044
+ }
19045
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
19046
+ throw new Error(`${flag} must be a JSON object.`);
19047
+ }
19048
+ return parsed;
19049
+ }
19050
+ function encodeKey(key) {
19051
+ return encodeURIComponent(key);
19052
+ }
19053
+ async function handleMonitorsTools(options) {
19054
+ const http = buildHttpClient();
19055
+ const params = new URLSearchParams();
19056
+ if (options.provider) params.set("provider", options.provider);
19057
+ if (options.tool) params.set("tool", options.tool);
19058
+ if (options.search) params.set("search", options.search);
19059
+ if (options.limit) params.set("limit", options.limit);
19060
+ const query = params.toString();
19061
+ const payload = await http.request(
19062
+ `/api/v2/monitors/tools${query ? `?${query}` : ""}`,
19063
+ { method: "GET", ...FORBIDDEN_AS_API_ERROR }
19064
+ );
19065
+ printCommandEnvelope(payload, { json: options.json });
19066
+ }
19067
+ async function handleMonitorsCheck(definition, options) {
19068
+ const http = buildHttpClient();
19069
+ const body = parseJsonObjectArg(definition, "--definition");
19070
+ const payload = await http.request(
19071
+ "/api/v2/monitors/check",
19072
+ { method: "POST", body, ...FORBIDDEN_AS_API_ERROR }
19073
+ );
19074
+ printCommandEnvelope(payload, { json: options.json });
19075
+ }
19076
+ async function handleMonitorsDeploy(definition, options) {
19077
+ const http = buildHttpClient();
19078
+ const body = parseJsonObjectArg(definition, "--definition");
19079
+ const payload = await http.request(
19080
+ "/api/v2/monitors/deploy",
19081
+ { method: "POST", body, ...FORBIDDEN_AS_API_ERROR }
19082
+ );
19083
+ printCommandEnvelope(payload, { json: options.json });
19084
+ }
19085
+ async function handleDeployedList(options) {
19086
+ const http = buildHttpClient();
19087
+ const params = new URLSearchParams();
19088
+ if (options.status) params.set("status", options.status);
19089
+ if (options.limit) params.set("limit", options.limit);
19090
+ const query = params.toString();
19091
+ const payload = await http.request(
19092
+ `/api/v2/monitors/deployed${query ? `?${query}` : ""}`,
19093
+ { method: "GET", ...FORBIDDEN_AS_API_ERROR }
19094
+ );
19095
+ printCommandEnvelope(payload, { json: options.json });
19096
+ }
19097
+ async function handleDeployedGet(key, options) {
19098
+ const http = buildHttpClient();
19099
+ const payload = await http.request(
19100
+ `/api/v2/monitors/deployed/${encodeKey(key)}`,
19101
+ { method: "GET", ...FORBIDDEN_AS_API_ERROR }
19102
+ );
19103
+ printCommandEnvelope(payload, { json: options.json });
19104
+ }
19105
+ async function handleDeployedDelete(key, options) {
19106
+ const http = buildHttpClient();
19107
+ const params = new URLSearchParams();
19108
+ if (options.localOnly) params.set("local_only", "true");
19109
+ const query = params.toString();
19110
+ const payload = await http.request(
19111
+ `/api/v2/monitors/deployed/${encodeKey(key)}${query ? `?${query}` : ""}`,
19112
+ { method: "DELETE", ...FORBIDDEN_AS_API_ERROR }
19113
+ );
19114
+ printCommandEnvelope(payload, { json: options.json });
19115
+ }
19116
+ async function handleDeployedUpdate(key, patch, options) {
19117
+ const http = buildHttpClient();
19118
+ const body = parseJsonObjectArg(patch, "<patch>");
19119
+ const payload = await http.request(
19120
+ `/api/v2/monitors/deployed/${encodeKey(key)}`,
19121
+ { method: "PATCH", body, ...FORBIDDEN_AS_API_ERROR }
19122
+ );
19123
+ printCommandEnvelope(payload, { json: options.json });
19124
+ }
19125
+ async function handleReactivate(key, options) {
19126
+ const http = buildHttpClient();
19127
+ const payload = await http.request(
19128
+ `/api/v2/monitors/deployed/${encodeKey(key)}/reactivate`,
19129
+ { method: "POST", body: {}, ...FORBIDDEN_AS_API_ERROR }
19130
+ );
19131
+ printCommandEnvelope(payload, { json: options.json });
19132
+ }
19133
+ function registerMonitorsCommands(program) {
19134
+ const monitors = program.command("monitors").description("Discover, deploy, and manage Deepline monitors.").addHelpText(
19135
+ "after",
19136
+ `
19137
+ Notes:
19138
+ Monitors are provider-backed signal feeds that deliver events into your
19139
+ workspace. Access is granted by a Deepline admin via Admin -> Rollouts; until
19140
+ then these commands return a clear monitor_access_required error.
19141
+
19142
+ Examples:
19143
+ deepline monitors tools --json
19144
+ deepline monitors check '{"key":"my-monitor","tool":"...","payload":{}}'
19145
+ deepline monitors deploy '{"key":"my-monitor","tool":"...","payload":{}}'
19146
+ deepline monitors deployed --json
19147
+ deepline monitors deployed get my-monitor --json
19148
+ deepline monitors reactivate my-monitor --json
19149
+ `
19150
+ );
19151
+ monitors.command("tools").description("List or describe the monitor tools available to your org.").addHelpText(
19152
+ "after",
19153
+ `
19154
+ Notes:
19155
+ Read-only. Filter the catalog with --provider, --tool, --search, or --limit.
19156
+ Pass --tool to describe a single monitor tool.
19157
+
19158
+ Examples:
19159
+ deepline monitors tools
19160
+ deepline monitors tools --provider theirstack --json
19161
+ deepline monitors tools --tool theirstack_jobs --json
19162
+ `
19163
+ ).option("--provider <provider>", "Filter by provider").option("--tool <tool>", "Describe a single monitor tool by id").option("--search <query>", "Search monitor tools by text").option("--limit <n>", "Limit the number of monitor tools returned").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleMonitorsTools);
19164
+ monitors.command("check <definition>").description("Validate a monitor definition without deploying it.").addHelpText(
19165
+ "after",
19166
+ `
19167
+ Notes:
19168
+ Read-only validation. <definition> is a JSON object with key, tool, payload,
19169
+ and optional controls. Does not deploy or spend credits.
19170
+
19171
+ Examples:
19172
+ deepline monitors check '{"key":"my-monitor","tool":"theirstack_jobs","payload":{}}'
19173
+ `
19174
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleMonitorsCheck);
19175
+ monitors.command("deploy <definition>").description("Deploy a monitor from a definition.").addHelpText(
19176
+ "after",
19177
+ `
19178
+ Notes:
19179
+ Mutates workspace state and may spend Deepline credits. <definition> is a JSON
19180
+ object with key, tool, payload, and optional controls.
19181
+
19182
+ Examples:
19183
+ deepline monitors deploy '{"key":"my-monitor","tool":"theirstack_jobs","payload":{}}'
19184
+ `
19185
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleMonitorsDeploy);
19186
+ monitors.command("reactivate <key>").description("Reactivate a previously disabled deployed monitor.").addHelpText(
19187
+ "after",
19188
+ `
19189
+ Notes:
19190
+ Mutates workspace state and may spend Deepline credits.
19191
+
19192
+ Examples:
19193
+ deepline monitors reactivate my-monitor --json
19194
+ `
19195
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleReactivate);
19196
+ const deployed = monitors.command("deployed").description("List and manage your deployed monitors.").addHelpText(
19197
+ "after",
19198
+ `
19199
+ Notes:
19200
+ With no subcommand, lists deployed monitors. Use get/update/delete to manage a
19201
+ single monitor by its public key.
19202
+
19203
+ Examples:
19204
+ deepline monitors deployed --json
19205
+ deepline monitors deployed --status all --json
19206
+ deepline monitors deployed get my-monitor --json
19207
+ `
19208
+ ).option("--status <status>", 'Filter by monitor status (or "all")').option("--limit <n>", "Limit the number of deployed monitors returned").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleDeployedList);
19209
+ deployed.command("get <key>").description("Show a single deployed monitor by its public key.").addHelpText(
19210
+ "after",
19211
+ `
19212
+ Notes:
19213
+ Read-only.
19214
+
19215
+ Examples:
19216
+ deepline monitors deployed get my-monitor --json
19217
+ `
19218
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleDeployedGet);
19219
+ deployed.command("update <key> <patch>").description("Update a deployed monitor by its public key.").addHelpText(
19220
+ "after",
19221
+ `
19222
+ Notes:
19223
+ Mutates workspace state. <patch> is a JSON object of fields to update.
19224
+
19225
+ Examples:
19226
+ deepline monitors deployed update my-monitor '{"controls":{"enabled":false}}' --json
19227
+ `
19228
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleDeployedUpdate);
19229
+ deployed.command("delete <key>").description("Delete a deployed monitor by its public key.").addHelpText(
19230
+ "after",
19231
+ `
19232
+ Notes:
19233
+ Mutates workspace state. By default deprovisions the upstream provider
19234
+ resource; pass --local-only to remove only the Deepline-managed record.
19235
+
19236
+ Examples:
19237
+ deepline monitors deployed delete my-monitor --json
19238
+ deepline monitors deployed delete my-monitor --local-only --json
19239
+ `
19240
+ ).option(
19241
+ "--local-only",
19242
+ "Remove only the Deepline-managed record, leaving the upstream resource"
19243
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleDeployedDelete);
19244
+ }
19245
+
18973
19246
  // src/cli/commands/org.ts
18974
19247
  async function fetchOrganizations(http, apiKey) {
18975
19248
  return http.post("/api/v2/auth/cli/organizations", { api_key: apiKey });
@@ -20157,7 +20430,7 @@ import { join as join10, resolve as resolve10 } from "path";
20157
20430
  // src/tool-output.ts
20158
20431
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync11 } from "fs";
20159
20432
  import { homedir as homedir9 } from "os";
20160
- import { join as join9 } from "path";
20433
+ import { dirname as dirname9, join as join9 } from "path";
20161
20434
  function isPlainObject(value) {
20162
20435
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
20163
20436
  }
@@ -20230,16 +20503,24 @@ function tryConvertToList(payload, options) {
20230
20503
  (entry) => typeof entry === "string" && entry.trim().length > 0
20231
20504
  ) : [];
20232
20505
  if (listExtractorPaths.length > 0) {
20506
+ let emptyMatch = null;
20233
20507
  for (const root of candidateRoots(payload)) {
20234
20508
  for (const extractorPath of listExtractorPaths) {
20235
20509
  const resolved = getByDottedPath(root.value, extractorPath);
20236
20510
  const rows = normalizeRows(resolved);
20237
- if (rows && rows.length > 0) {
20238
- const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
20511
+ if (!rows) {
20512
+ continue;
20513
+ }
20514
+ const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
20515
+ if (rows.length > 0) {
20239
20516
  return { rows, strategy: "configured_paths", sourcePath };
20240
20517
  }
20518
+ emptyMatch ??= { rows, strategy: "configured_paths", sourcePath };
20241
20519
  }
20242
20520
  }
20521
+ if (emptyMatch) {
20522
+ return emptyMatch;
20523
+ }
20243
20524
  }
20244
20525
  for (const root of candidateRoots(payload)) {
20245
20526
  const candidate = findBestArrayCandidate(root.value, root.path ?? "");
@@ -20263,9 +20544,9 @@ function writeJsonOutputFile(payload, stem) {
20263
20544
  writeFileSync11(outputPath, JSON.stringify(payload, null, 2), "utf-8");
20264
20545
  return outputPath;
20265
20546
  }
20266
- function writeCsvOutputFile(rows, stem) {
20267
- const outputDir = ensureOutputDir();
20268
- const outputPath = join9(outputDir, `${stem}_${Date.now()}.csv`);
20547
+ function writeCsvOutputFile(rows, stem, options) {
20548
+ const outputPath = options?.outPath ? options.outPath : join9(ensureOutputDir(), `${stem}_${Date.now()}.csv`);
20549
+ mkdirSync7(dirname9(outputPath), { recursive: true });
20269
20550
  const seen = /* @__PURE__ */ new Set();
20270
20551
  const columns = [];
20271
20552
  for (const row of rows) {
@@ -20794,6 +21075,7 @@ Examples:
20794
21075
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
20795
21076
  deepline tools execute hunter_email_verifier -p email=a@b.com
20796
21077
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --json | jq '.status'
21078
+ deepline tools execute free_simple_company_search --input '{"sql":"SELECT company_name FROM companies LIMIT 10"}' --out companies.csv
20797
21079
  `
20798
21080
  ).option(
20799
21081
  "-p, --param <key=value>",
@@ -20815,6 +21097,9 @@ Examples:
20815
21097
  ).option(
20816
21098
  "--output-format <format>",
20817
21099
  "Output format: auto, csv, csv_file, json, or json_file"
21100
+ ).option(
21101
+ "-o, --out <path>",
21102
+ "Write row-shaped tool output to this CSV path"
20818
21103
  ).option(
20819
21104
  "--no-preview",
20820
21105
  "Only print the extracted output path when applicable"
@@ -20827,6 +21112,7 @@ Examples:
20827
21112
  ...options.input ? ["--input", options.input] : [],
20828
21113
  ...options.payload ? ["--payload", options.payload] : [],
20829
21114
  ...options.outputFormat ? ["--output-format", options.outputFormat] : [],
21115
+ ...options.out ? ["--out", options.out] : [],
20830
21116
  ...options.preview === false ? ["--no-preview"] : []
20831
21117
  ];
20832
21118
  process.exitCode = await executeTool(args);
@@ -21277,7 +21563,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
21277
21563
  invalidGetterHint: "If TypeScript says an extractedValues/extractedLists property does not exist, that field is not a declared Deepline getter.",
21278
21564
  observeActualShape: observedOutputCommand,
21279
21565
  observedOutput: observedOutputCommand,
21280
- forPlayGetterBugs: "Run a tiny play, inspect `deepline runs get <run-id> --full --json`, and export returned dataset handles with `deepline runs export`. Backing tables exist only for ctx.map(...).run(...) stages that actually executed.",
21566
+ forPlayGetterBugs: "Run a tiny play, inspect returned handles with `deepline runs get <run-id> --full --json`, then export row datasets with `deepline runs export`.",
21281
21567
  executeOutputFields: "tools execute JSON may include output_preview for this direct probe only; play debugging uses run output and returned dataset handles."
21282
21568
  },
21283
21569
  ...starterScript ? { starterScript } : {}
@@ -21484,12 +21770,13 @@ function parseExecuteOptions(args) {
21484
21770
  const toolId = args[0];
21485
21771
  if (!toolId) {
21486
21772
  throw new Error(
21487
- `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
21773
+ `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--out rows.csv] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
21488
21774
  );
21489
21775
  }
21490
21776
  const params = {};
21491
21777
  let outputFormat = "auto";
21492
21778
  let noPreview = false;
21779
+ let outPath = null;
21493
21780
  for (let index = 1; index < args.length; index += 1) {
21494
21781
  const arg = args[index];
21495
21782
  if ((arg === "--param" || arg === "-p") && args[index + 1]) {
@@ -21521,9 +21808,13 @@ function parseExecuteOptions(args) {
21521
21808
  noPreview = true;
21522
21809
  continue;
21523
21810
  }
21811
+ if ((arg === "--out" || arg === "-o") && args[index + 1]) {
21812
+ outPath = resolve10(args[++index]);
21813
+ continue;
21814
+ }
21524
21815
  throw new Error(`Unknown option: ${arg}`);
21525
21816
  }
21526
- return { toolId, params, outputFormat, noPreview };
21817
+ return { toolId, params, outputFormat, noPreview, outPath };
21527
21818
  }
21528
21819
  function safeFileStem(value) {
21529
21820
  return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
@@ -21567,9 +21858,14 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
21567
21858
  });
21568
21859
 
21569
21860
  const list = Object.values(result.extractedLists)[0];
21570
- const rows = (list?.get() ?? []).slice(0, 100);
21861
+ if (!list) {
21862
+ throw new Error('Expected ${input2.toolId} to expose an extracted list getter.');
21863
+ }
21864
+ const rows = list.get();
21571
21865
  // ${sampleRows}
21572
21866
  // columns: ${columns}
21867
+ // extractedLists.<name>.get() returns a dataset handle for row-shaped list outputs.
21868
+ // Pass it to ctx.dataset; use rows.peek/count/materialize only for deliberate bounded inspection.
21573
21869
  // .withColumn('email_waterfall', (row, rowCtx) => rowCtx.runPlay('name_domain_email', 'name-and-domain-to-email', { first_name: String(row.first_name ?? ''), last_name: String(row.last_name ?? ''), domain: String(row.domain ?? '') }, { description: 'Resolve email.' }))
21574
21870
  // .withColumn('phone_waterfall', (row, rowCtx) => rowCtx.runPlay('contact_phone', 'contact-to-phone', { first_name: String(row.first_name ?? ''), last_name: String(row.last_name ?? ''), email: String(row.email ?? '') }, { description: 'Resolve phone.' }))
21575
21871
  // ctx.dataset is idempotent by dataset key + row key; reruns reuse completed rows.
@@ -21629,7 +21925,7 @@ function buildToolExecuteBaseEnvelope(input2) {
21629
21925
  ...summaryEntries.length > 0 ? { summary: input2.summary } : {},
21630
21926
  next: {
21631
21927
  inspect: inspectCommand,
21632
- playDebugging: "When fixing a play getter, inspect the actual play run table with runs get / inspect rows; do not copy CLI preview paths blindly.",
21928
+ playDebugging: "When fixing a play getter, inspect returned dataset handles with runs get and export rows with runs export; do not copy CLI preview paths blindly.",
21633
21929
  ...input2.listConversion ? {
21634
21930
  expandToPlay: "Use stable map and step keys so reruns are idempotent: completed rows are reused, and only missing or stale work runs again.",
21635
21931
  listSourcePath: input2.listConversion.sourcePath ?? "auto-detected list in the CLI response preview"
@@ -21641,7 +21937,7 @@ function buildToolExecuteBaseEnvelope(input2) {
21641
21937
  title: "output",
21642
21938
  lines: [
21643
21939
  `${input2.listConversion.rows.length} row(s) extracted from ${input2.listConversion.sourcePath ?? "auto-detected list"}`,
21644
- "paths above are observed from this execute response; use run table rows to debug play getters",
21940
+ "paths above are observed from this execute response; use runs get and runs export to validate play output",
21645
21941
  `columns: ${JSON.stringify(Object.keys(input2.listConversion.rows[0] ?? {}))}`,
21646
21942
  `preview: ${JSON.stringify(input2.listConversion.rows.slice(0, 5))}`
21647
21943
  ]
@@ -21721,7 +22017,7 @@ async function executeTool(args) {
21721
22017
  listConversion,
21722
22018
  summary
21723
22019
  });
21724
- if (parsed.outputFormat === "json" || parsed.outputFormat === "auto" && shouldEmitJson()) {
22020
+ if (!parsed.outPath && (parsed.outputFormat === "json" || parsed.outputFormat === "auto" && shouldEmitJson())) {
21725
22021
  printCommandEnvelope(baseEnvelope, { json: true });
21726
22022
  return 0;
21727
22023
  }
@@ -21743,6 +22039,17 @@ async function executeTool(args) {
21743
22039
  return 0;
21744
22040
  }
21745
22041
  if (!listConversion) {
22042
+ if (parsed.outPath) {
22043
+ const error = new Error(
22044
+ `${parsed.toolId} did not expose row-shaped output to write as CSV. Re-run with --json to inspect the raw tool response.`
22045
+ );
22046
+ if (argsWantJson(args)) {
22047
+ printJsonError(error);
22048
+ } else {
22049
+ console.error(error.message);
22050
+ }
22051
+ return 1;
22052
+ }
21746
22053
  if (parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file") {
21747
22054
  const jsonPath = writeJsonOutputFile(
21748
22055
  rawResponse,
@@ -21764,7 +22071,8 @@ async function executeTool(args) {
21764
22071
  }
21765
22072
  const csv = writeCsvOutputFile(
21766
22073
  listConversion.rows,
21767
- `${parsed.toolId}_output`
22074
+ `${parsed.toolId}_output`,
22075
+ parsed.outPath ? { outPath: parsed.outPath } : void 0
21768
22076
  );
21769
22077
  const seededScript = seedToolListScript({
21770
22078
  toolId: parsed.toolId,
@@ -21837,6 +22145,27 @@ async function executeTool(args) {
21837
22145
  );
21838
22146
  return 0;
21839
22147
  }
22148
+ if (parsed.outPath) {
22149
+ printCommandEnvelope(
22150
+ {
22151
+ ...materializedEnvelope,
22152
+ csv_path: csv.path,
22153
+ row_count: csv.rowCount,
22154
+ row_count_returned: csv.rowCount,
22155
+ columns: csv.columns,
22156
+ preview: csv.preview,
22157
+ list_strategy: listConversion.strategy,
22158
+ list_source_path: listConversion.sourcePath,
22159
+ summary
22160
+ },
22161
+ {
22162
+ json: argsWantJson(args) || shouldEmitJson(),
22163
+ text: `Wrote ${csv.rowCount} row(s) to ${csv.path}
22164
+ `
22165
+ }
22166
+ );
22167
+ return 0;
22168
+ }
21840
22169
  if (parsed.noPreview) {
21841
22170
  printCommandEnvelope(
21842
22171
  {
@@ -21857,7 +22186,7 @@ async function executeTool(args) {
21857
22186
 
21858
22187
  // src/cli/commands/workflow.ts
21859
22188
  import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile4 } from "fs/promises";
21860
- import { dirname as dirname9, join as join11, resolve as resolve11 } from "path";
22189
+ import { dirname as dirname10, join as join11, resolve as resolve11 } from "path";
21861
22190
 
21862
22191
  // src/cli/workflow-to-play.ts
21863
22192
  import { createHash as createHash3 } from "crypto";
@@ -22136,7 +22465,7 @@ async function transformOne(api, workflowId, outDir, publish) {
22136
22465
  { workflowName: workflow.name, version: revision.version }
22137
22466
  );
22138
22467
  const file = join11(resolve11(outDir), `${compiled.playName}.play.ts`);
22139
- await mkdir4(dirname9(file), { recursive: true });
22468
+ await mkdir4(dirname10(file), { recursive: true });
22140
22469
  await writeFile4(file, compiled.sourceCode, "utf8");
22141
22470
  let published = false;
22142
22471
  if (publish) {
@@ -22394,12 +22723,12 @@ import {
22394
22723
  writeFileSync as writeFileSync14
22395
22724
  } from "fs";
22396
22725
  import { homedir as homedir10 } from "os";
22397
- import { dirname as dirname11, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve as resolve12 } from "path";
22726
+ import { dirname as dirname12, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve as resolve12 } from "path";
22398
22727
 
22399
22728
  // src/cli/skills-sync.ts
22400
22729
  import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
22401
22730
  import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync13 } from "fs";
22402
- import { dirname as dirname10, join as join12 } from "path";
22731
+ import { dirname as dirname11, join as join12 } from "path";
22403
22732
 
22404
22733
  // ../shared_libs/cli/install-commands.json
22405
22734
  var install_commands_default = {
@@ -22533,7 +22862,7 @@ function sdkSkillsVersionPath(baseUrl) {
22533
22862
  return join12(sdkCliStateDirPath(baseUrl), "skills-version");
22534
22863
  }
22535
22864
  function legacySdkSkillsVersionPath(baseUrl) {
22536
- return join12(dirname10(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
22865
+ return join12(dirname11(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
22537
22866
  }
22538
22867
  function readSdkSkillsLocalVersion(baseUrl) {
22539
22868
  const pluginVersion = readPluginSkillsVersion();
@@ -22548,7 +22877,7 @@ function readSdkSkillsLocalVersion(baseUrl) {
22548
22877
  }
22549
22878
  function writeLocalSkillsVersion(baseUrl, version) {
22550
22879
  const path = sdkSkillsVersionPath(baseUrl);
22551
- mkdirSync8(dirname10(path), { recursive: true });
22880
+ mkdirSync8(dirname11(path), { recursive: true });
22552
22881
  writeFileSync13(path, `${version}
22553
22882
  `, "utf-8");
22554
22883
  }
@@ -22877,7 +23206,7 @@ function findRepoBackedSdkRoot(startPath) {
22877
23206
  if (existsSync11(join13(current, "sdk", "package.json")) && existsSync11(join13(current, "sdk", "bin", "deepline-dev.ts"))) {
22878
23207
  return current;
22879
23208
  }
22880
- const parent = dirname11(current);
23209
+ const parent = dirname12(current);
22881
23210
  if (parent === current) return null;
22882
23211
  current = parent;
22883
23212
  }
@@ -22907,7 +23236,7 @@ function resolveUpdatePlan(options = {}) {
22907
23236
  const env = options.env ?? process.env;
22908
23237
  const homeDir2 = options.homeDir ?? homedir10();
22909
23238
  const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve12(process.argv[1]) : "");
22910
- const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname11(entrypoint)) : null;
23239
+ const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname12(entrypoint)) : null;
22911
23240
  if (sourceRoot) {
22912
23241
  return {
22913
23242
  kind: "source",
@@ -22986,7 +23315,7 @@ function writeAutoUpdateFailure(plan, exitCode) {
22986
23315
  manualCommand: plan.manualCommand
22987
23316
  };
22988
23317
  try {
22989
- mkdirSync9(dirname11(path), { recursive: true });
23318
+ mkdirSync9(dirname12(path), { recursive: true });
22990
23319
  writeFileSync14(path, `${JSON.stringify(marker, null, 2)}
22991
23320
  `, "utf8");
22992
23321
  } catch {
@@ -23073,7 +23402,7 @@ function runCommand(command, args, env = process.env) {
23073
23402
  });
23074
23403
  }
23075
23404
  function writeSidecarLauncher(input2) {
23076
- mkdirSync9(dirname11(input2.path), { recursive: true });
23405
+ mkdirSync9(dirname12(input2.path), { recursive: true });
23077
23406
  if (process.platform === "win32") {
23078
23407
  writeFileSync14(
23079
23408
  input2.path,
@@ -23110,7 +23439,7 @@ async function runPythonSidecarUpdatePlan(plan) {
23110
23439
  writeFileSync14(join13(tempDir, "package.json"), NPM_SDK_SIDECAR_PACKAGE_JSON);
23111
23440
  const env = {
23112
23441
  ...process.env,
23113
- PATH: `${dirname11(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
23442
+ PATH: `${dirname12(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
23114
23443
  };
23115
23444
  const installExitCode = await runCommand(
23116
23445
  plan.npmCommand,
@@ -24030,6 +24359,7 @@ Exit codes:
24030
24359
  registerWorkflowCommands(program);
24031
24360
  registerSecretsCommands(program);
24032
24361
  registerBillingCommands(program);
24362
+ registerMonitorsCommands(program);
24033
24363
  registerOrgCommands(program);
24034
24364
  registerEnrichCommand(program);
24035
24365
  registerCsvCommands(program);