deepline 0.1.23 → 0.1.25

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
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/cli/index.ts
27
- var import_commander = require("commander");
27
+ var import_commander2 = require("commander");
28
28
 
29
29
  // src/config.ts
30
30
  var import_node_fs = require("fs");
@@ -266,7 +266,7 @@ function saveProjectDeeplineEnvValues(baseUrl, values, startDir = projectEnvStar
266
266
  }
267
267
 
268
268
  // src/version.ts
269
- var SDK_VERSION = "0.1.23";
269
+ var SDK_VERSION = "0.1.25";
270
270
  var SDK_API_CONTRACT = "2026-05-runs-v2";
271
271
 
272
272
  // ../shared_libs/play-runtime/coordinator-headers.ts
@@ -548,7 +548,7 @@ function decodeSseFrame(frame) {
548
548
  return parsed;
549
549
  }
550
550
  function sleep(ms) {
551
- return new Promise((resolve8) => setTimeout(resolve8, ms));
551
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
552
552
  }
553
553
 
554
554
  // src/client.ts
@@ -556,7 +556,7 @@ var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "ca
556
556
  var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
557
557
  var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
558
558
  function sleep2(ms) {
559
- return new Promise((resolve8) => setTimeout(resolve8, ms));
559
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
560
560
  }
561
561
  function isTransientCompileManifestError(error) {
562
562
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -2041,7 +2041,7 @@ function buildCandidateUrls2(url) {
2041
2041
  }
2042
2042
  }
2043
2043
  function sleep3(ms) {
2044
- return new Promise((resolve8) => setTimeout(resolve8, ms));
2044
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
2045
2045
  }
2046
2046
  function printDeeplineLogo() {
2047
2047
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -2348,18 +2348,48 @@ function registerAuthCommands(program) {
2348
2348
  `
2349
2349
  Common commands:
2350
2350
  deepline auth register
2351
+ deepline auth register --no-wait
2352
+ deepline auth wait --timeout 300
2351
2353
  deepline auth status
2352
2354
  deepline auth status --json
2355
+
2356
+ Notes:
2357
+ Registration opens a browser approval page by default. Use --no-wait in CI
2358
+ or agent runs, then finish with deepline auth wait.
2359
+ Auth status shows the target host and active workspace without printing secrets.
2353
2360
  `
2354
2361
  );
2355
- auth.command("register").description("Register this device and open the approval page in your browser.").option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--no-wait", "Return immediately after opening the approval page").action(async (options) => {
2362
+ auth.command("register").description("Register this device and open the approval page in your browser.").addHelpText(
2363
+ "after",
2364
+ `
2365
+ Notes:
2366
+ Opens a browser approval page and waits for approval unless --no-wait is set.
2367
+ The saved API key is scoped to the selected workspace and host.
2368
+
2369
+ Examples:
2370
+ deepline auth register
2371
+ deepline auth register --org-name Acme --agent-name local-cli
2372
+ deepline auth register --no-wait
2373
+ `
2374
+ ).option("--org-name <name>", "Workspace name to prefill").option("--agent-name <name>", "Agent name to register").option("--no-wait", "Return immediately after opening the approval page").action(async (options) => {
2356
2375
  process.exitCode = await handleRegister([
2357
2376
  ...options.orgName ? ["--org-name", options.orgName] : [],
2358
2377
  ...options.agentName ? ["--agent-name", options.agentName] : [],
2359
2378
  ...options.noWait || options.wait === false ? ["--no-wait"] : []
2360
2379
  ]);
2361
2380
  });
2362
- auth.command("wait").description("Wait for a pending browser approval and save the API key.").option("--timeout <seconds>", "Maximum seconds to wait", "300").action(async (options) => {
2381
+ auth.command("wait").description("Wait for a pending browser approval and save the API key.").addHelpText(
2382
+ "after",
2383
+ `
2384
+ Notes:
2385
+ Completes a previous deepline auth register --no-wait flow.
2386
+ Saves the approved API key into the host auth file.
2387
+
2388
+ Examples:
2389
+ deepline auth wait
2390
+ deepline auth wait --timeout 120
2391
+ `
2392
+ ).option("--timeout <seconds>", "Maximum seconds to wait", "300").action(async (options) => {
2363
2393
  process.exitCode = await handleWait([
2364
2394
  ...options.timeout ? ["--timeout", options.timeout] : []
2365
2395
  ]);
@@ -2385,6 +2415,10 @@ Examples:
2385
2415
  }
2386
2416
 
2387
2417
  // src/cli/commands/billing.ts
2418
+ var import_commander = require("commander");
2419
+ var import_promises2 = require("fs/promises");
2420
+ var import_node_path4 = require("path");
2421
+ var import_sync3 = require("csv-stringify/sync");
2388
2422
  function humanize(value) {
2389
2423
  return String(value || "").split("_").filter(Boolean).map((token) => token[0]?.toUpperCase() + token.slice(1)).join(" ") || "Unknown";
2390
2424
  }
@@ -2402,6 +2436,54 @@ function printRecentUsage(entries) {
2402
2436
  `);
2403
2437
  }
2404
2438
  }
2439
+ function summarizeLedgerRows(summary, rows) {
2440
+ const netDelta = rows.reduce((sum, row) => {
2441
+ const value = Number.parseFloat(String(row.delta_credits ?? "").trim());
2442
+ return Number.isFinite(value) ? sum + value : sum;
2443
+ }, summary.net_delta_credits);
2444
+ return {
2445
+ row_count: summary.row_count + rows.length,
2446
+ net_delta_credits: Math.round((netDelta + Number.EPSILON) * 100) / 100
2447
+ };
2448
+ }
2449
+ function ledgerApiEntryToRow(entry) {
2450
+ const metadata = typeof entry.metadata === "object" && entry.metadata !== null ? entry.metadata : {};
2451
+ return {
2452
+ created_at: entry.created_at ?? "",
2453
+ delta_credits: entry.delta ?? "",
2454
+ reason: entry.reason ?? "",
2455
+ provider: metadata.provider ?? "",
2456
+ operation: metadata.operation ?? "",
2457
+ request_id: metadata.requestId ?? metadata.request_id ?? "",
2458
+ run_id: metadata.runId ?? metadata.run_id ?? "",
2459
+ api_key_id: entry.api_key_id ?? "",
2460
+ stripe_session_id: entry.stripe_session_id ?? ""
2461
+ };
2462
+ }
2463
+ function ledgerRowsToCsv(rows, header) {
2464
+ return (0, import_sync3.stringify)(rows, {
2465
+ header,
2466
+ columns: [
2467
+ "created_at",
2468
+ "delta_credits",
2469
+ "reason",
2470
+ "provider",
2471
+ "operation",
2472
+ "request_id",
2473
+ "run_id",
2474
+ "api_key_id",
2475
+ "stripe_session_id"
2476
+ ]
2477
+ });
2478
+ }
2479
+ function defaultLedgerExportPath() {
2480
+ return (0, import_node_path4.resolve)(
2481
+ process.cwd(),
2482
+ "deepline",
2483
+ "data",
2484
+ `billing-ledger-all-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.csv`
2485
+ );
2486
+ }
2405
2487
  async function handleBalance(options) {
2406
2488
  const { http } = getAuthedHttpClient();
2407
2489
  const payload = await http.get("/api/v2/billing/balance");
@@ -2490,6 +2572,51 @@ async function handleHistory(options) {
2490
2572
  process.stdout.write(`${rows.length} row(s) exported.
2491
2573
  `);
2492
2574
  }
2575
+ async function handleLedgerExportAll(options) {
2576
+ const { http } = getAuthedHttpClient();
2577
+ const outputPath = options.output ? (0, import_node_path4.resolve)(String(options.output)) : defaultLedgerExportPath();
2578
+ let summary = { row_count: 0, net_delta_credits: 0 };
2579
+ let cursor = null;
2580
+ let initializedOutput = false;
2581
+ for (; ; ) {
2582
+ const params = new URLSearchParams({ limit: "5000" });
2583
+ if (cursor !== null) params.set("cursor", cursor);
2584
+ const payload = await http.get(
2585
+ `/api/v2/billing/ledger?${params.toString()}`
2586
+ );
2587
+ const entries = Array.isArray(payload.entries) ? payload.entries : [];
2588
+ const rows = entries.map(ledgerApiEntryToRow);
2589
+ if (!initializedOutput) {
2590
+ await (0, import_promises2.mkdir)((0, import_node_path4.dirname)(outputPath), { recursive: true });
2591
+ await (0, import_promises2.writeFile)(outputPath, ledgerRowsToCsv([], true), "utf-8");
2592
+ initializedOutput = true;
2593
+ }
2594
+ if (rows.length > 0) {
2595
+ await (0, import_promises2.appendFile)(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
2596
+ summary = summarizeLedgerRows(summary, rows);
2597
+ }
2598
+ const nextCursor = typeof payload.next_cursor === "string" && payload.next_cursor.length > 0 ? payload.next_cursor : null;
2599
+ if (rows.length === 0 || payload.has_more !== true || nextCursor === null) {
2600
+ break;
2601
+ }
2602
+ if (nextCursor === cursor) break;
2603
+ cursor = nextCursor;
2604
+ }
2605
+ if (shouldEmitJson(options.json)) {
2606
+ return printJson({
2607
+ output_path: outputPath,
2608
+ row_count: summary.row_count,
2609
+ net_delta_credits: summary.net_delta_credits,
2610
+ scope: "current_auth_context"
2611
+ });
2612
+ }
2613
+ process.stdout.write(`Billing ledger written to ${outputPath}
2614
+ `);
2615
+ process.stdout.write(`${summary.row_count} row(s) exported for the current auth context.
2616
+ `);
2617
+ process.stdout.write(`Net ledger delta: ${summary.net_delta_credits} Deepline Credits
2618
+ `);
2619
+ }
2493
2620
  async function handleCheckout(options) {
2494
2621
  const { http } = getAuthedHttpClient();
2495
2622
  const payload = await http.post("/api/v2/billing/checkout", {
@@ -2513,20 +2640,156 @@ async function handleRedeemCode(code, options) {
2513
2640
  `);
2514
2641
  }
2515
2642
  function registerBillingCommands(program) {
2516
- const billing = program.command("billing").description("Inspect balance, usage, limits, and checkout flows.");
2517
- billing.command("balance").description("Show current billing balance.").option("--json", "Emit JSON output").action(handleBalance);
2518
- billing.command("usage").description("Show current usage plus recent calls.").option("--limit <n>", "Recent-call page size").option("--offset <n>", "Recent-call offset").option("--json", "Emit JSON output").action(handleUsage);
2519
- billing.command("limit").description("Show configured monthly limit state.").option("--json", "Emit JSON output").action(handleLimit);
2520
- billing.command("set-limit").description("Set monthly credit cap.").argument("<credits>", "Monthly credits limit").option("--json", "Emit JSON output").action(handleSetLimit);
2521
- billing.command("off").description("Disable monthly credit cap.").option("--json", "Emit JSON output").action(handleLimitOff);
2522
- billing.command("history").description("Export billing ledger history to CSV.").requiredOption("--time <window>", "Rolling time window: 1d, 1w, 1m, or 1y").option("--json", "Emit JSON output").action(handleHistory);
2523
- billing.command("checkout").description("Create a checkout session and optionally open it in your browser.").option("--tier <tierId>", "Named pricing tier").option("--credits <credits>", "Custom credit amount").option("--discount-code <code>", "Apply a discount code").option("--no-open", "Print the checkout URL without opening a browser").option("--json", "Emit JSON output").action(handleCheckout);
2524
- billing.command("redeem-code").description("Redeem a billing code.").requiredOption("--code <code>", "Code to redeem").option("--no-open", "Do not open a browser").option("--json", "Emit JSON output").action(({ code, ...options }) => handleRedeemCode(code, options));
2643
+ const billing = program.command("billing").description("Inspect balance, usage, limits, and checkout flows.").addHelpText(
2644
+ "after",
2645
+ `
2646
+ Concepts:
2647
+ Billing commands show Deepline credits, not raw provider spend.
2648
+ set-limit/off mutate the monthly workspace cap. checkout/redeem-code can open
2649
+ a browser unless --no-open is set.
2650
+
2651
+ Examples:
2652
+ deepline billing balance --json
2653
+ deepline billing usage --limit 20 --json
2654
+ deepline billing set-limit 500 --json
2655
+ deepline billing checkout --credits 1000 --no-open --json
2656
+ `
2657
+ );
2658
+ billing.command("balance").description("Show current billing balance.").addHelpText(
2659
+ "after",
2660
+ `
2661
+ Notes:
2662
+ Read-only. Shows the current Deepline credit balance for the active workspace.
2663
+
2664
+ Examples:
2665
+ deepline billing balance
2666
+ deepline billing balance --json
2667
+ `
2668
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleBalance);
2669
+ billing.command("usage").description("Show current usage plus recent calls.").addHelpText(
2670
+ "after",
2671
+ `
2672
+ Notes:
2673
+ Read-only. Shows last-30-day Deepline credit usage plus a bounded recent-call
2674
+ page. Use --limit/--offset to paginate the recent-call section.
2675
+
2676
+ Examples:
2677
+ deepline billing usage
2678
+ deepline billing usage --limit 50 --offset 50 --json
2679
+ `
2680
+ ).option("--limit <n>", "Recent-call page size").option("--offset <n>", "Recent-call offset").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleUsage);
2681
+ billing.command("limit").description("Show configured monthly limit state.").addHelpText(
2682
+ "after",
2683
+ `
2684
+ Notes:
2685
+ Read-only. Shows whether the monthly workspace cap is enabled and how many
2686
+ Deepline credits remain before the cap.
2687
+
2688
+ Examples:
2689
+ deepline billing limit
2690
+ deepline billing limit --json
2691
+ `
2692
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLimit);
2693
+ billing.command("set-limit").description("Set monthly credit cap.").addHelpText(
2694
+ "after",
2695
+ `
2696
+ Notes:
2697
+ Mutates workspace billing settings. The argument is a Deepline credit amount,
2698
+ not dollars and not provider credits.
2699
+
2700
+ Examples:
2701
+ deepline billing set-limit 500
2702
+ deepline billing set-limit 500 --json
2703
+ `
2704
+ ).argument("<credits>", "Monthly credits limit").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSetLimit);
2705
+ billing.command("off").description("Disable monthly credit cap.").addHelpText(
2706
+ "after",
2707
+ `
2708
+ Notes:
2709
+ Mutates workspace billing settings by removing the monthly Deepline credit cap.
2710
+
2711
+ Examples:
2712
+ deepline billing off
2713
+ deepline billing off --json
2714
+ `
2715
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLimitOff);
2716
+ billing.command("ledger").description("Inspect and export billing ledger rows.").addHelpText(
2717
+ "after",
2718
+ `
2719
+ Notes:
2720
+ Read-only. Exports ledger rows for the current auth context. API-key auth is
2721
+ scoped by the server to that API key; session auth is scoped to the active
2722
+ workspace.
2723
+
2724
+ Examples:
2725
+ deepline billing ledger export all
2726
+ deepline billing ledger export all --output ./ledger.csv
2727
+ deepline billing ledger export all --json
2728
+ `
2729
+ ).addCommand(
2730
+ new import_commander.Command("export").description("Export billing ledger rows.").addHelpText(
2731
+ "after",
2732
+ `
2733
+ Examples:
2734
+ deepline billing ledger export all
2735
+ `
2736
+ ).addCommand(
2737
+ new import_commander.Command("all").description("Export all available billing ledger rows to CSV.").addHelpText(
2738
+ "after",
2739
+ `
2740
+ Notes:
2741
+ Pages through the ledger for the current auth context, writes CSV locally,
2742
+ then reports the row count and the net delta computed from delta_credits.
2743
+
2744
+ Examples:
2745
+ deepline billing ledger export all
2746
+ deepline billing ledger export all --json
2747
+ `
2748
+ ).option("--output <path>", "Write CSV to an explicit path").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLedgerExportAll)
2749
+ )
2750
+ );
2751
+ billing.command("history").description("Export billing ledger history to CSV.").addHelpText(
2752
+ "after",
2753
+ `
2754
+ Notes:
2755
+ Read-only server query that writes a local CSV file. With --json, stdout is a
2756
+ summary containing the output path and row count.
2757
+
2758
+ Examples:
2759
+ deepline billing history --time 1m
2760
+ deepline billing history --time 1y --json
2761
+ `
2762
+ ).requiredOption("--time <window>", "Rolling time window: 1d, 1w, 1m, or 1y").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleHistory);
2763
+ billing.command("checkout").description("Create a checkout session and optionally open it in your browser.").addHelpText(
2764
+ "after",
2765
+ `
2766
+ Notes:
2767
+ Creates a payment checkout session. Opens the checkout URL in a browser unless
2768
+ --no-open is set. Use --json for automation.
2769
+
2770
+ Examples:
2771
+ deepline billing checkout --tier pro
2772
+ deepline billing checkout --credits 1000 --no-open --json
2773
+ deepline billing checkout --credits 1000 --discount-code LAUNCH --no-open
2774
+ `
2775
+ ).option("--tier <tierId>", "Named pricing tier").option("--credits <credits>", "Custom credit amount").option("--discount-code <code>", "Apply a discount code").option("--no-open", "Print the checkout URL without opening a browser").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleCheckout);
2776
+ billing.command("redeem-code").description("Redeem a billing code.").addHelpText(
2777
+ "after",
2778
+ `
2779
+ Notes:
2780
+ Redeems a workspace billing code and may open a browser for completion unless
2781
+ --no-open is set.
2782
+
2783
+ Examples:
2784
+ deepline billing redeem-code --code ABC123
2785
+ deepline billing redeem-code --code ABC123 --no-open --json
2786
+ `
2787
+ ).requiredOption("--code <code>", "Code to redeem").option("--no-open", "Do not open a browser").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(({ code, ...options }) => handleRedeemCode(code, options));
2525
2788
  }
2526
2789
 
2527
2790
  // src/cli/dataset-stats.ts
2528
2791
  var import_node_fs4 = require("fs");
2529
- var import_node_path4 = require("path");
2792
+ var import_node_path5 = require("path");
2530
2793
  var CSV_PROJECTED_FIELDS_KEY = "__deeplineCsvProjectedFields";
2531
2794
  function csvProjectedFields(row) {
2532
2795
  const serialized = row[CSV_PROJECTED_FIELDS_KEY];
@@ -2856,7 +3119,7 @@ function writeCanonicalRowsCsv(rowsInfo, outPath) {
2856
3119
  rows: rowsInfo.rows,
2857
3120
  columns: rowsInfo.columns
2858
3121
  });
2859
- const resolved = (0, import_node_path4.resolve)(outPath);
3122
+ const resolved = (0, import_node_path5.resolve)(outPath);
2860
3123
  (0, import_node_fs4.writeFileSync)(
2861
3124
  resolved,
2862
3125
  csvStringFromRows(sanitized.rows, sanitized.columns),
@@ -2952,8 +3215,31 @@ async function handleCsvShow(options) {
2952
3215
  `);
2953
3216
  }
2954
3217
  function registerCsvCommands(program) {
2955
- const csv = program.command("csv").description("Inspect local CSV files.");
2956
- csv.command("show").description("Display rows from a CSV file in json, csv, or table form.").requiredOption("--csv <path>", "Input CSV path").option("--format <format>", "Output format: json, csv, or table", "json").option("--rows <range>", "Row range start:end", "0:19").option("--columns <names>", "Comma-separated column names to include").option("--summary", "Print a summary payload instead of row output").option("--verbose", "Do not truncate long values in table output").action(handleCsvShow);
3218
+ const csv = program.command("csv").description("Inspect local CSV files.").addHelpText(
3219
+ "after",
3220
+ `
3221
+ Notes:
3222
+ Local-only inspection helpers. These commands do not upload CSV files or call
3223
+ Deepline APIs.
3224
+
3225
+ Examples:
3226
+ deepline csv show --csv leads.csv --rows 0:10 --format table
3227
+ deepline csv show --csv leads.csv --summary
3228
+ `
3229
+ );
3230
+ csv.command("show").description("Display rows from a CSV file in json, csv, or table form.").addHelpText(
3231
+ "after",
3232
+ `
3233
+ Notes:
3234
+ Reads a local CSV path and prints a bounded row range. --rows uses inclusive
3235
+ start:end indexes, so 0:19 prints the first 20 rows. JSON is the default format.
3236
+
3237
+ Examples:
3238
+ deepline csv show --csv leads.csv
3239
+ deepline csv show --csv leads.csv --rows 20:39 --columns name,email --format table
3240
+ deepline csv show --csv leads.csv --summary
3241
+ `
3242
+ ).requiredOption("--csv <path>", "Input CSV path").option("--format <format>", "Output format: json, csv, or table", "json").option("--rows <range>", "Row range start:end", "0:19").option("--columns <names>", "Comma-separated column names to include").option("--summary", "Print a summary payload instead of row output").option("--verbose", "Do not truncate long values in table output").action(handleCsvShow);
2957
3243
  }
2958
3244
 
2959
3245
  // src/cli/commands/db.ts
@@ -3033,8 +3319,32 @@ async function handleDbQuery(args) {
3033
3319
  return 0;
3034
3320
  }
3035
3321
  function registerDbCommands(program) {
3036
- const db = program.command("db").alias("customer-db").description("Query the tenant customer database.");
3037
- db.command("query").alias("psql").description("Run SQL against the tenant customer database.").requiredOption("--sql <sql>", "SQL statement").option("--max-rows <n>", "Maximum returned rows").option("--json", "Emit raw JSON response").action(async (options) => {
3322
+ const db = program.command("db").alias("customer-db").description("Query the tenant customer database.").addHelpText(
3323
+ "after",
3324
+ `
3325
+ Notes:
3326
+ Runs SQL against the active workspace customer database through Deepline APIs.
3327
+ Results are bounded by the server and --max-rows. Use --json for stable output.
3328
+
3329
+ Examples:
3330
+ deepline db query --sql "select * from companies limit 20"
3331
+ deepline db query --sql "select domain, name from companies limit 20" --json
3332
+ deepline db query --sql "select * from contacts" --max-rows 100 --json
3333
+ `
3334
+ );
3335
+ db.command("query").alias("psql").description("Run SQL against the tenant customer database.").addHelpText(
3336
+ "after",
3337
+ `
3338
+ Notes:
3339
+ Requires --sql. Output is a compact table in a terminal and raw JSON with
3340
+ --json or when stdout is piped. The active auth workspace determines scope.
3341
+
3342
+ Examples:
3343
+ deepline db query --sql "select * from companies limit 20"
3344
+ deepline db query --sql "select domain, name from companies limit 20" --json
3345
+ deepline db psql --sql "select count(*) from contacts" --json
3346
+ `
3347
+ ).requiredOption("--sql <sql>", "SQL statement").option("--max-rows <n>", "Maximum returned rows").option("--json", "Emit raw JSON response. Also automatic when stdout is piped").action(async (options) => {
3038
3348
  process.exitCode = await handleDbQuery([
3039
3349
  "--sql",
3040
3350
  options.sql,
@@ -3060,9 +3370,29 @@ async function handleFeedback(text, options) {
3060
3370
  process.stdout.write("Feedback submitted. Thank you.\n");
3061
3371
  }
3062
3372
  function registerFeedbackCommands(program) {
3063
- const feedback = program.command("feedback").description("Submit CLI feedback to Deepline.");
3373
+ const feedback = program.command("feedback").description("Submit CLI feedback to Deepline.").addHelpText(
3374
+ "after",
3375
+ `
3376
+ Notes:
3377
+ Sends the feedback text plus local CLI environment info to Deepline support.
3378
+ Use --command and --payload to attach a reproducible command shape.
3379
+
3380
+ Examples:
3381
+ deepline feedback "plays run failed after upload" --command "deepline plays run my.play.ts --watch"
3382
+ deepline feedback "unexpected billing output" --payload '{"command":"billing usage"}' --json
3383
+ `
3384
+ );
3064
3385
  feedback.argument("<text>", "Feedback text").option("--command <command>", "Command that reproduced the issue").option("--payload <payload>", "JSON or plain-text payload for the repro").option("--json", "Emit JSON output").action(handleFeedback);
3065
- program.command("provide-feedback").description("Legacy alias for `deepline feedback`.").argument("<text>", "Feedback text").option("--command <command>", "Command that reproduced the issue").option("--payload <payload>", "JSON or plain-text payload for the repro").option("--json", "Emit JSON output").action(handleFeedback);
3386
+ program.command("provide-feedback").description("Legacy alias for `deepline feedback`.").addHelpText(
3387
+ "after",
3388
+ `
3389
+ Notes:
3390
+ Compatibility alias. Prefer deepline feedback in new scripts and docs.
3391
+
3392
+ Examples:
3393
+ deepline feedback "tools search returned stale results" --json
3394
+ `
3395
+ ).argument("<text>", "Feedback text").option("--command <command>", "Command that reproduced the issue").option("--payload <payload>", "JSON or plain-text payload for the repro").option("--json", "Emit JSON output").action(handleFeedback);
3066
3396
  }
3067
3397
 
3068
3398
  // src/cli/commands/org.ts
@@ -3142,27 +3472,61 @@ async function handleOrgSwitch(selection, options) {
3142
3472
  `);
3143
3473
  }
3144
3474
  function registerOrgCommands(program) {
3145
- const org = program.command("org").description("List and switch organizations.");
3146
- org.command("list").description("List your organizations.").option("--json", "Emit JSON output").action(handleOrgList);
3147
- org.command("switch [selection]").description("Switch to another organization and save the new API key in the host auth file.").option("--org-id <id>", "Switch using an explicit organization id").option("--json", "Emit JSON output").action(handleOrgSwitch);
3475
+ const org = program.command("org").description("List and switch organizations.").addHelpText(
3476
+ "after",
3477
+ `
3478
+ Notes:
3479
+ Organizations are workspaces. Switching organizations mutates the saved host
3480
+ auth file so later CLI commands target the selected workspace.
3481
+
3482
+ Examples:
3483
+ deepline org list --json
3484
+ deepline org switch 2
3485
+ deepline org switch --org-id org_123 --json
3486
+ `
3487
+ );
3488
+ org.command("list").description("List your organizations.").addHelpText(
3489
+ "after",
3490
+ `
3491
+ Notes:
3492
+ Read-only. Marks the active organization when the server returns that metadata.
3493
+
3494
+ Examples:
3495
+ deepline org list
3496
+ deepline org list --json
3497
+ `
3498
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgList);
3499
+ org.command("switch [selection]").description("Switch to another organization and save the new API key in the host auth file.").addHelpText(
3500
+ "after",
3501
+ `
3502
+ Notes:
3503
+ Mutates the saved host auth file. Selection can be a list number, exact
3504
+ organization name, or organization id. Without a selection, prints choices.
3505
+
3506
+ Examples:
3507
+ deepline org switch
3508
+ deepline org switch 2
3509
+ deepline org switch --org-id org_123 --json
3510
+ `
3511
+ ).option("--org-id <id>", "Switch using an explicit organization id").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgSwitch);
3148
3512
  }
3149
3513
 
3150
3514
  // src/cli/commands/play.ts
3151
3515
  var import_node_crypto3 = require("crypto");
3152
3516
  var import_node_fs6 = require("fs");
3153
- var import_node_path8 = require("path");
3517
+ var import_node_path9 = require("path");
3154
3518
 
3155
3519
  // src/plays/bundle-play-file.ts
3156
3520
  var import_node_os5 = require("os");
3157
- var import_node_path7 = require("path");
3521
+ var import_node_path8 = require("path");
3158
3522
  var import_node_url = require("url");
3159
3523
  var import_node_fs5 = require("fs");
3160
3524
 
3161
3525
  // ../shared_libs/plays/bundling/index.ts
3162
3526
  var import_node_crypto = require("crypto");
3163
- var import_promises2 = require("fs/promises");
3527
+ var import_promises3 = require("fs/promises");
3164
3528
  var import_node_os4 = require("os");
3165
- var import_node_path5 = require("path");
3529
+ var import_node_path6 = require("path");
3166
3530
  var import_node_module = require("module");
3167
3531
  var import_esbuild = require("esbuild");
3168
3532
 
@@ -3223,7 +3587,7 @@ var playArtifactRequire = (0, import_node_module.createRequire)(import_meta.url)
3223
3587
  var PLAY_BUNDLE_CACHE_VERSION = 24;
3224
3588
  var MAX_PLAY_BUNDLE_BYTES = 30 * 1024 * 1024;
3225
3589
  var MAX_ESM_WORKERS_BUNDLE_BYTES = 115e4;
3226
- var PLAY_ARTIFACT_CACHE_DIR = (0, import_node_path5.join)(
3590
+ var PLAY_ARTIFACT_CACHE_DIR = (0, import_node_path6.join)(
3227
3591
  (0, import_node_os4.tmpdir)(),
3228
3592
  `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION}`
3229
3593
  );
@@ -3254,15 +3618,15 @@ function isLocalSpecifier(specifier) {
3254
3618
  }
3255
3619
  async function normalizeLocalPath(filePath) {
3256
3620
  try {
3257
- return await (0, import_promises2.realpath)(filePath);
3621
+ return await (0, import_promises3.realpath)(filePath);
3258
3622
  } catch {
3259
- return (0, import_node_path5.resolve)(filePath);
3623
+ return (0, import_node_path6.resolve)(filePath);
3260
3624
  }
3261
3625
  }
3262
3626
  function createPlayWorkspace(entryFile) {
3263
3627
  return {
3264
3628
  entryFile,
3265
- rootDir: (0, import_node_path5.dirname)(entryFile)
3629
+ rootDir: (0, import_node_path6.dirname)(entryFile)
3266
3630
  };
3267
3631
  }
3268
3632
  function isPathInsideDirectory(filePath, directory) {
@@ -3416,7 +3780,7 @@ function extractDefinedPlayName(sourceCode, _filePath) {
3416
3780
  function getPackageRequireCandidates(fromFile) {
3417
3781
  const candidates = [
3418
3782
  (0, import_node_module.createRequire)(fromFile),
3419
- (0, import_node_module.createRequire)((0, import_node_path5.join)(process.cwd(), "package.json")),
3783
+ (0, import_node_module.createRequire)((0, import_node_path6.join)(process.cwd(), "package.json")),
3420
3784
  playArtifactRequire
3421
3785
  ];
3422
3786
  return candidates;
@@ -3463,7 +3827,7 @@ function workersNamedPlayEntryAliasPlugin(playFilePath, exportName) {
3463
3827
  contents: `export { ${exportName} as default } from ${JSON.stringify(playFilePath)};
3464
3828
  `,
3465
3829
  loader: "ts",
3466
- resolveDir: (0, import_node_path5.dirname)(playFilePath)
3830
+ resolveDir: (0, import_node_path6.dirname)(playFilePath)
3467
3831
  })
3468
3832
  );
3469
3833
  }
@@ -3627,7 +3991,7 @@ function importedPlayProxyPlugin(importedPlayDependencies) {
3627
3991
  return {
3628
3992
  contents: buildImportedPlayProxyModule(dependency.playName),
3629
3993
  loader: "ts",
3630
- resolveDir: (0, import_node_path5.dirname)(args.path)
3994
+ resolveDir: (0, import_node_path6.dirname)(args.path)
3631
3995
  };
3632
3996
  });
3633
3997
  }
@@ -3635,7 +3999,7 @@ function importedPlayProxyPlugin(importedPlayDependencies) {
3635
3999
  }
3636
4000
  async function fileExists(filePath) {
3637
4001
  try {
3638
- await (0, import_promises2.stat)(filePath);
4002
+ await (0, import_promises3.stat)(filePath);
3639
4003
  return true;
3640
4004
  } catch {
3641
4005
  return false;
@@ -3645,12 +4009,12 @@ async function resolveLocalImport(fromFile, specifier) {
3645
4009
  if (specifier.startsWith("file:")) {
3646
4010
  return normalizeLocalPath(new URL(specifier).pathname);
3647
4011
  }
3648
- const base = (0, import_node_path5.isAbsolute)(specifier) ? (0, import_node_path5.resolve)(specifier) : (0, import_node_path5.resolve)((0, import_node_path5.dirname)(fromFile), specifier);
4012
+ const base = (0, import_node_path6.isAbsolute)(specifier) ? (0, import_node_path6.resolve)(specifier) : (0, import_node_path6.resolve)((0, import_node_path6.dirname)(fromFile), specifier);
3649
4013
  const candidates = [base];
3650
- const explicitExtension = (0, import_node_path5.extname)(base).toLowerCase();
4014
+ const explicitExtension = (0, import_node_path6.extname)(base).toLowerCase();
3651
4015
  if (!explicitExtension) {
3652
4016
  candidates.push(...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`));
3653
- candidates.push(...SOURCE_EXTENSIONS.map((extension) => (0, import_node_path5.join)(base, `index${extension}`)));
4017
+ candidates.push(...SOURCE_EXTENSIONS.map((extension) => (0, import_node_path6.join)(base, `index${extension}`)));
3654
4018
  } else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
3655
4019
  const stem = base.slice(0, -explicitExtension.length);
3656
4020
  candidates.push(...SOURCE_EXTENSIONS.map((extension) => `${stem}${extension}`));
@@ -3716,9 +4080,9 @@ async function analyzeSourceGraph(entryFile, adapter) {
3716
4080
  return;
3717
4081
  }
3718
4082
  visited.add(absolutePath);
3719
- const sourceCode2 = await (0, import_promises2.readFile)(absolutePath, "utf-8");
4083
+ const sourceCode2 = await (0, import_promises3.readFile)(absolutePath, "utf-8");
3720
4084
  localFiles.set(absolutePath, sourceCode2);
3721
- if ((0, import_node_path5.extname)(absolutePath).toLowerCase() === ".json") {
4085
+ if ((0, import_node_path6.extname)(absolutePath).toLowerCase() === ".json") {
3722
4086
  return;
3723
4087
  }
3724
4088
  const handleSpecifier = async (specifier, line, column, kind) => {
@@ -3742,7 +4106,7 @@ async function analyzeSourceGraph(entryFile, adapter) {
3742
4106
  column
3743
4107
  });
3744
4108
  if (resolved !== absoluteEntryFile && isPlaySourceFile(resolved)) {
3745
- const importedSource = await (0, import_promises2.readFile)(resolved, "utf-8");
4109
+ const importedSource = await (0, import_promises3.readFile)(resolved, "utf-8");
3746
4110
  const importedPlayName = extractDefinedPlayName(importedSource, resolved);
3747
4111
  if (!importedPlayName) {
3748
4112
  throw new Error(
@@ -3822,20 +4186,20 @@ async function computeWorkersHarnessFingerprintWithAdapter(adapter) {
3822
4186
  const tsFiles = entries.filter((e) => e.isFile() && /\.[cm]?ts$/.test(e.name)).map((e) => e.name).sort();
3823
4187
  const parts = [];
3824
4188
  for (const name of tsFiles) {
3825
- const contents = await (0, import_promises2.readFile)((0, import_node_path5.join)(adapter.workersHarnessFilesDir, name), "utf-8");
4189
+ const contents = await (0, import_promises3.readFile)((0, import_node_path6.join)(adapter.workersHarnessFilesDir, name), "utf-8");
3826
4190
  parts.push({ name, hash: sha256(contents) });
3827
4191
  }
3828
4192
  return sha256(JSON.stringify(parts));
3829
4193
  }
3830
4194
  function artifactCachePath(graphHash, artifactKind, adapter) {
3831
- return (0, import_node_path5.join)(
4195
+ return (0, import_node_path6.join)(
3832
4196
  adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR,
3833
4197
  `${graphHash}.${artifactKind}.json`
3834
4198
  );
3835
4199
  }
3836
4200
  async function readArtifactCache(graphHash, artifactKind, adapter) {
3837
4201
  try {
3838
- const serialized = await (0, import_promises2.readFile)(
4202
+ const serialized = await (0, import_promises3.readFile)(
3839
4203
  artifactCachePath(graphHash, artifactKind, adapter),
3840
4204
  "utf-8"
3841
4205
  );
@@ -3846,8 +4210,8 @@ async function readArtifactCache(graphHash, artifactKind, adapter) {
3846
4210
  }
3847
4211
  async function writeArtifactCache(artifact, adapter) {
3848
4212
  const cacheDir = adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR;
3849
- await (0, import_promises2.mkdir)(cacheDir, { recursive: true });
3850
- await (0, import_promises2.writeFile)(
4213
+ await (0, import_promises3.mkdir)(cacheDir, { recursive: true });
4214
+ await (0, import_promises3.writeFile)(
3851
4215
  artifactCachePath(
3852
4216
  artifact.graphHash,
3853
4217
  artifact.artifactKind ?? PLAY_ARTIFACT_KINDS.cjsNode20,
@@ -3863,7 +4227,7 @@ function normalizeSourceMapForRuntime(sourceMapText) {
3863
4227
  if (sourcePath.startsWith("data:") || sourcePath.startsWith("node:") || sourcePath.startsWith("/") || /^[a-zA-Z]+:\/\//.test(sourcePath)) {
3864
4228
  return sourcePath;
3865
4229
  }
3866
- return (0, import_node_path5.resolve)(process.cwd(), sourcePath);
4230
+ return (0, import_node_path6.resolve)(process.cwd(), sourcePath);
3867
4231
  });
3868
4232
  parsed.sourceRoot = void 0;
3869
4233
  return JSON.stringify(parsed);
@@ -3895,8 +4259,8 @@ async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter
3895
4259
  ...namedExportShim ? {
3896
4260
  stdin: {
3897
4261
  contents: namedExportShim,
3898
- resolveDir: (0, import_node_path5.dirname)(entryFile),
3899
- sourcefile: `${(0, import_node_path5.basename)(entryFile)}.${exportName}.entry.ts`,
4262
+ resolveDir: (0, import_node_path6.dirname)(entryFile),
4263
+ sourcefile: `${(0, import_node_path6.basename)(entryFile)}.${exportName}.entry.ts`,
3900
4264
  loader: "ts"
3901
4265
  }
3902
4266
  } : { entryPoints: [entryFile] },
@@ -4072,10 +4436,10 @@ workers-harness:${harnessFingerprint}`
4072
4436
  }
4073
4437
  const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
4074
4438
  const normalizedSourceMap = normalizeSourceMapForRuntime(sourceMapText);
4075
- const virtualBaseName = exportName === "default" ? (0, import_node_path5.basename)(absolutePath).replace(/\.[^.]+$/, "") : `${(0, import_node_path5.basename)(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
4439
+ const virtualBaseName = exportName === "default" ? (0, import_node_path6.basename)(absolutePath).replace(/\.[^.]+$/, "") : `${(0, import_node_path6.basename)(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
4076
4440
  const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
4077
4441
  const executableCode = `${bundledCode}
4078
- //# sourceMappingURL=${(0, import_node_path5.basename)(virtualFilename)}.map
4442
+ //# sourceMappingURL=${(0, import_node_path6.basename)(virtualFilename)}.map
4079
4443
  `;
4080
4444
  const bundleSizeError = getBundleSizeError(
4081
4445
  absolutePath,
@@ -4184,14 +4548,14 @@ function resolveExecutionProfile(override) {
4184
4548
 
4185
4549
  // src/plays/local-file-discovery.ts
4186
4550
  var import_node_crypto2 = require("crypto");
4187
- var import_promises3 = require("fs/promises");
4188
- var import_node_path6 = require("path");
4551
+ var import_promises4 = require("fs/promises");
4552
+ var import_node_path7 = require("path");
4189
4553
  var SOURCE_EXTENSIONS2 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".json"];
4190
4554
  function sha2562(buffer) {
4191
4555
  return (0, import_node_crypto2.createHash)("sha256").update(buffer).digest("hex");
4192
4556
  }
4193
4557
  function contentTypeForFile(filePath) {
4194
- const extension = (0, import_node_path6.extname)(filePath).toLowerCase();
4558
+ const extension = (0, import_node_path7.extname)(filePath).toLowerCase();
4195
4559
  if (extension === ".csv") return "text/csv";
4196
4560
  if (extension === ".json") return "application/json";
4197
4561
  if (extension === ".txt") return "text/plain";
@@ -4375,23 +4739,23 @@ function localImportSpecifiers(sourceCode) {
4375
4739
  }
4376
4740
  async function fileExists2(filePath) {
4377
4741
  try {
4378
- await (0, import_promises3.stat)(filePath);
4742
+ await (0, import_promises4.stat)(filePath);
4379
4743
  return true;
4380
4744
  } catch {
4381
4745
  return false;
4382
4746
  }
4383
4747
  }
4384
4748
  function isPathInsideDirectory2(filePath, directory) {
4385
- const relativePath = (0, import_node_path6.relative)(directory, filePath);
4386
- return relativePath === "" || !relativePath.startsWith("..") && !(0, import_node_path6.isAbsolute)(relativePath);
4749
+ const relativePath = (0, import_node_path7.relative)(directory, filePath);
4750
+ return relativePath === "" || !relativePath.startsWith("..") && !(0, import_node_path7.isAbsolute)(relativePath);
4387
4751
  }
4388
4752
  async function resolveLocalImport2(fromFile, specifier) {
4389
- const base = (0, import_node_path6.isAbsolute)(specifier) ? (0, import_node_path6.resolve)(specifier) : (0, import_node_path6.resolve)((0, import_node_path6.dirname)(fromFile), specifier);
4753
+ const base = (0, import_node_path7.isAbsolute)(specifier) ? (0, import_node_path7.resolve)(specifier) : (0, import_node_path7.resolve)((0, import_node_path7.dirname)(fromFile), specifier);
4390
4754
  const candidates = [base];
4391
- const explicitExtension = (0, import_node_path6.extname)(base).toLowerCase();
4755
+ const explicitExtension = (0, import_node_path7.extname)(base).toLowerCase();
4392
4756
  if (!explicitExtension) {
4393
4757
  candidates.push(...SOURCE_EXTENSIONS2.map((extension) => `${base}${extension}`));
4394
- candidates.push(...SOURCE_EXTENSIONS2.map((extension) => (0, import_node_path6.join)(base, `index${extension}`)));
4758
+ candidates.push(...SOURCE_EXTENSIONS2.map((extension) => (0, import_node_path7.join)(base, `index${extension}`)));
4395
4759
  } else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
4396
4760
  const stem = base.slice(0, -explicitExtension.length);
4397
4761
  candidates.push(...SOURCE_EXTENSIONS2.map((extension) => `${stem}${extension}`));
@@ -4404,18 +4768,18 @@ async function resolveLocalImport2(fromFile, specifier) {
4404
4768
  throw new Error(`Could not resolve local import "${specifier}" from ${fromFile}`);
4405
4769
  }
4406
4770
  async function discoverPackagedLocalFiles(entryFile) {
4407
- const absoluteEntryFile = (0, import_node_path6.resolve)(entryFile);
4408
- const packagingRoot = (0, import_node_path6.dirname)(absoluteEntryFile);
4771
+ const absoluteEntryFile = (0, import_node_path7.resolve)(entryFile);
4772
+ const packagingRoot = (0, import_node_path7.dirname)(absoluteEntryFile);
4409
4773
  const files = /* @__PURE__ */ new Map();
4410
4774
  const unresolved = [];
4411
4775
  const visitedFiles = /* @__PURE__ */ new Set();
4412
4776
  const visitSourceFile = async (filePath) => {
4413
- const absolutePath = (0, import_node_path6.resolve)(filePath);
4777
+ const absolutePath = (0, import_node_path7.resolve)(filePath);
4414
4778
  if (visitedFiles.has(absolutePath)) {
4415
4779
  return;
4416
4780
  }
4417
4781
  visitedFiles.add(absolutePath);
4418
- const sourceCode = await (0, import_promises3.readFile)(absolutePath, "utf-8");
4782
+ const sourceCode = await (0, import_promises4.readFile)(absolutePath, "utf-8");
4419
4783
  const scanSource = stripCommentsToSpaces2(sourceCode);
4420
4784
  const constants = collectTopLevelStringConstants(sourceCode);
4421
4785
  const childVisits = [];
@@ -4442,16 +4806,16 @@ async function discoverPackagedLocalFiles(entryFile) {
4442
4806
  message: "Could not resolve this ctx.csv(...) path at submit time. Use a string literal, a top-level const string, or pass a runtime input like input.file."
4443
4807
  });
4444
4808
  } else {
4445
- const absoluteCsvPath = (0, import_node_path6.resolve)((0, import_node_path6.dirname)(absolutePath), resolvedPath);
4446
- if ((0, import_node_path6.isAbsolute)(resolvedPath) || !isPathInsideDirectory2(absoluteCsvPath, packagingRoot)) {
4809
+ const absoluteCsvPath = (0, import_node_path7.resolve)((0, import_node_path7.dirname)(absolutePath), resolvedPath);
4810
+ if ((0, import_node_path7.isAbsolute)(resolvedPath) || !isPathInsideDirectory2(absoluteCsvPath, packagingRoot)) {
4447
4811
  unresolved.push({
4448
4812
  sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
4449
4813
  message: "ctx.csv(...) packaged file paths must be relative paths inside the play directory. Pass external files at runtime with input.file instead."
4450
4814
  });
4451
4815
  continue;
4452
4816
  }
4453
- const buffer = await (0, import_promises3.readFile)(absoluteCsvPath);
4454
- const stats = await (0, import_promises3.stat)(absoluteCsvPath);
4817
+ const buffer = await (0, import_promises4.readFile)(absoluteCsvPath);
4818
+ const stats = await (0, import_promises4.stat)(absoluteCsvPath);
4455
4819
  files.set(absoluteCsvPath, {
4456
4820
  sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
4457
4821
  logicalPath: resolvedPath,
@@ -4482,24 +4846,24 @@ async function discoverPackagedLocalFiles(entryFile) {
4482
4846
  // src/plays/bundle-play-file.ts
4483
4847
  var import_meta2 = {};
4484
4848
  var PLAY_BUNDLE_CACHE_VERSION2 = 26;
4485
- var MODULE_DIR = (0, import_node_path7.dirname)((0, import_node_url.fileURLToPath)(import_meta2.url));
4486
- var SDK_PACKAGE_ROOT = (0, import_node_path7.resolve)(MODULE_DIR, "..", "..");
4487
- var SOURCE_REPO_ROOT = (0, import_node_path7.resolve)(SDK_PACKAGE_ROOT, "..");
4849
+ var MODULE_DIR = (0, import_node_path8.dirname)((0, import_node_url.fileURLToPath)(import_meta2.url));
4850
+ var SDK_PACKAGE_ROOT = (0, import_node_path8.resolve)(MODULE_DIR, "..", "..");
4851
+ var SOURCE_REPO_ROOT = (0, import_node_path8.resolve)(SDK_PACKAGE_ROOT, "..");
4488
4852
  var HAS_SOURCE_BUNDLING_SOURCES = (0, import_node_fs5.existsSync)(
4489
- (0, import_node_path7.resolve)(SOURCE_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
4853
+ (0, import_node_path8.resolve)(SOURCE_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
4490
4854
  );
4491
- var PACKAGED_REPO_ROOT = (0, import_node_path7.resolve)(SDK_PACKAGE_ROOT, "dist", "repo");
4855
+ var PACKAGED_REPO_ROOT = (0, import_node_path8.resolve)(SDK_PACKAGE_ROOT, "dist", "repo");
4492
4856
  var HAS_PACKAGED_BUNDLING_SOURCES = (0, import_node_fs5.existsSync)(
4493
- (0, import_node_path7.resolve)(PACKAGED_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
4857
+ (0, import_node_path8.resolve)(PACKAGED_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
4494
4858
  );
4495
- var PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? SOURCE_REPO_ROOT : HAS_PACKAGED_BUNDLING_SOURCES ? PACKAGED_REPO_ROOT : (0, import_node_path7.resolve)(SDK_PACKAGE_ROOT, "..");
4496
- var SDK_SOURCE_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? (0, import_node_path7.resolve)(SOURCE_REPO_ROOT, "sdk", "src") : HAS_PACKAGED_BUNDLING_SOURCES ? (0, import_node_path7.resolve)(PACKAGED_REPO_ROOT, "sdk", "src") : (0, import_node_path7.resolve)(SDK_PACKAGE_ROOT, "src");
4497
- var SDK_PACKAGE_JSON = (0, import_node_path7.resolve)(SDK_PACKAGE_ROOT, "package.json");
4498
- var SDK_ENTRY_FILE = (0, import_node_path7.resolve)(SDK_SOURCE_ROOT, "index.ts");
4499
- var SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : (0, import_node_path7.resolve)(SDK_PACKAGE_ROOT, "dist", "index.d.ts");
4500
- var SDK_WORKERS_ENTRY_FILE = (0, import_node_path7.resolve)(SDK_SOURCE_ROOT, "worker-play-entry.ts");
4501
- var WORKERS_HARNESS_ENTRY_FILE = (0, import_node_path7.resolve)(PROJECT_ROOT, "apps", "play-runner-workers", "src", "entry.ts");
4502
- var WORKERS_HARNESS_FILES_DIR = (0, import_node_path7.resolve)(PROJECT_ROOT, "apps", "play-runner-workers", "src");
4859
+ var PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? SOURCE_REPO_ROOT : HAS_PACKAGED_BUNDLING_SOURCES ? PACKAGED_REPO_ROOT : (0, import_node_path8.resolve)(SDK_PACKAGE_ROOT, "..");
4860
+ var SDK_SOURCE_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? (0, import_node_path8.resolve)(SOURCE_REPO_ROOT, "sdk", "src") : HAS_PACKAGED_BUNDLING_SOURCES ? (0, import_node_path8.resolve)(PACKAGED_REPO_ROOT, "sdk", "src") : (0, import_node_path8.resolve)(SDK_PACKAGE_ROOT, "src");
4861
+ var SDK_PACKAGE_JSON = (0, import_node_path8.resolve)(SDK_PACKAGE_ROOT, "package.json");
4862
+ var SDK_ENTRY_FILE = (0, import_node_path8.resolve)(SDK_SOURCE_ROOT, "index.ts");
4863
+ var SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : (0, import_node_path8.resolve)(SDK_PACKAGE_ROOT, "dist", "index.d.ts");
4864
+ var SDK_WORKERS_ENTRY_FILE = (0, import_node_path8.resolve)(SDK_SOURCE_ROOT, "worker-play-entry.ts");
4865
+ var WORKERS_HARNESS_ENTRY_FILE = (0, import_node_path8.resolve)(PROJECT_ROOT, "apps", "play-runner-workers", "src", "entry.ts");
4866
+ var WORKERS_HARNESS_FILES_DIR = (0, import_node_path8.resolve)(PROJECT_ROOT, "apps", "play-runner-workers", "src");
4503
4867
  var hasWarnedAboutNonDevelopmentBundling = false;
4504
4868
  function warnAboutNonDevelopmentBundling(filePath) {
4505
4869
  if (hasWarnedAboutNonDevelopmentBundling) {
@@ -4523,8 +4887,8 @@ function defaultPlayBundleTarget() {
4523
4887
  function createSdkPlayBundlingAdapter() {
4524
4888
  return {
4525
4889
  projectRoot: PROJECT_ROOT,
4526
- nodeModulesDir: (0, import_node_path7.resolve)(PROJECT_ROOT, "node_modules"),
4527
- cacheDir: (0, import_node_path7.join)((0, import_node_os5.tmpdir)(), `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`),
4890
+ nodeModulesDir: (0, import_node_path8.resolve)(PROJECT_ROOT, "node_modules"),
4891
+ cacheDir: (0, import_node_path8.join)((0, import_node_os5.tmpdir)(), `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`),
4528
4892
  sdkSourceRoot: SDK_SOURCE_ROOT,
4529
4893
  sdkPackageJson: SDK_PACKAGE_JSON,
4530
4894
  sdkEntryFile: SDK_ENTRY_FILE,
@@ -4804,7 +5168,7 @@ function formatPlayListReference(play) {
4804
5168
  function defaultMaterializedPlayPath(reference) {
4805
5169
  const playName = parseReferencedPlayTarget(reference).unqualifiedPlayName;
4806
5170
  const safeName = playName.trim().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
4807
- return (0, import_node_path8.resolve)(`${safeName || "play"}.play.ts`);
5171
+ return (0, import_node_path9.resolve)(`${safeName || "play"}.play.ts`);
4808
5172
  }
4809
5173
  function materializeRemotePlaySource(input) {
4810
5174
  if (isFileTarget(input.target)) {
@@ -4867,7 +5231,7 @@ function extractPlayName(code, filePath) {
4867
5231
  throw buildMissingDefinePlayError(filePath);
4868
5232
  }
4869
5233
  function isFileTarget(target) {
4870
- return (0, import_node_fs6.existsSync)((0, import_node_path8.resolve)(target));
5234
+ return (0, import_node_fs6.existsSync)((0, import_node_path9.resolve)(target));
4871
5235
  }
4872
5236
  function looksLikeFilePath(target) {
4873
5237
  if (target.trim().toLowerCase().startsWith("prebuilt/")) {
@@ -4886,7 +5250,7 @@ function parsePositiveInteger2(value, flagName) {
4886
5250
  return parsed;
4887
5251
  }
4888
5252
  function parseJsonInput(raw) {
4889
- const source = raw.startsWith("@") ? (0, import_node_fs6.readFileSync)((0, import_node_path8.resolve)(raw.slice(1)), "utf-8") : raw;
5253
+ const source = raw.startsWith("@") ? (0, import_node_fs6.readFileSync)((0, import_node_path9.resolve)(raw.slice(1)), "utf-8") : raw;
4890
5254
  const parsed = JSON.parse(source);
4891
5255
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
4892
5256
  throw new Error("--input must be a JSON object.");
@@ -4996,7 +5360,7 @@ function applyCsvShortcutInput(input) {
4996
5360
  function isLocalFilePathValue(value) {
4997
5361
  if (typeof value !== "string" || !value.trim()) return false;
4998
5362
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
4999
- return (0, import_node_fs6.existsSync)((0, import_node_path8.resolve)(value));
5363
+ return (0, import_node_fs6.existsSync)((0, import_node_path9.resolve)(value));
5000
5364
  }
5001
5365
  function inputContainsLocalFilePath(value) {
5002
5366
  if (isLocalFilePathValue(value)) {
@@ -5022,8 +5386,8 @@ async function stageFileInputArgs(input) {
5022
5386
  const localFiles = uniqueBindings.flatMap((binding) => {
5023
5387
  const value = getDottedInputValue(input.runtimeInput, binding.inputPath);
5024
5388
  if (!isLocalFilePathValue(value)) return [];
5025
- const absolutePath = (0, import_node_path8.resolve)(value);
5026
- return [{ binding, absolutePath, logicalPath: (0, import_node_path8.basename)(absolutePath) }];
5389
+ const absolutePath = (0, import_node_path9.resolve)(value);
5390
+ return [{ binding, absolutePath, logicalPath: (0, import_node_path9.basename)(absolutePath) }];
5027
5391
  });
5028
5392
  if (localFiles.length === 0) {
5029
5393
  return { inputFile: null, packagedFiles: [] };
@@ -5058,9 +5422,9 @@ function stageFile(logicalPath, absolutePath) {
5058
5422
  }
5059
5423
  function normalizePlayPath(filePath) {
5060
5424
  try {
5061
- return import_node_fs6.realpathSync.native((0, import_node_path8.resolve)(filePath));
5425
+ return import_node_fs6.realpathSync.native((0, import_node_path9.resolve)(filePath));
5062
5426
  } catch {
5063
- return (0, import_node_path8.resolve)(filePath);
5427
+ return (0, import_node_path9.resolve)(filePath);
5064
5428
  }
5065
5429
  }
5066
5430
  function formatBundlingErrors(filePath, errors) {
@@ -6086,7 +6450,7 @@ function parsePlayRunOptions(args) {
6086
6450
  let input = null;
6087
6451
  let revisionId = null;
6088
6452
  let revisionSelector = null;
6089
- const watch = args.includes("--watch");
6453
+ const watch = args.includes("--watch") || args.includes("--wait");
6090
6454
  let jsonOutput = watch ? args.includes("--json") : argsWantJson(args);
6091
6455
  const emitLogs = !jsonOutput || args.includes("--logs");
6092
6456
  const force = args.includes("--force");
@@ -6120,7 +6484,7 @@ function parsePlayRunOptions(args) {
6120
6484
  continue;
6121
6485
  }
6122
6486
  if (arg === "--out" && args[index + 1]) {
6123
- outPath = (0, import_node_path8.resolve)(args[++index]);
6487
+ outPath = (0, import_node_path9.resolve)(args[++index]);
6124
6488
  continue;
6125
6489
  }
6126
6490
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
@@ -6136,15 +6500,13 @@ function parsePlayRunOptions(args) {
6136
6500
  if (arg === "--watch") {
6137
6501
  continue;
6138
6502
  }
6503
+ if (arg === "--wait") {
6504
+ continue;
6505
+ }
6139
6506
  if (arg === "--json") {
6140
6507
  jsonOutput = true;
6141
6508
  continue;
6142
6509
  }
6143
- if (arg === "--wait") {
6144
- throw new Error(
6145
- "--wait is removed for `plays run`; use `--watch` to stream completion output."
6146
- );
6147
- }
6148
6510
  if (arg === "--tail") {
6149
6511
  throw new Error(
6150
6512
  "--tail is removed for `plays run`; use `--watch` to stream completion output."
@@ -6222,11 +6584,11 @@ function shouldUseLocalOnlyPlayCheck() {
6222
6584
  async function handlePlayCheck(args) {
6223
6585
  const options = parsePlayCheckOptions(args);
6224
6586
  if (!isFileTarget(options.target)) {
6225
- const resolved = (0, import_node_path8.resolve)(options.target);
6587
+ const resolved = (0, import_node_path9.resolve)(options.target);
6226
6588
  console.error(`File not found: ${resolved}`);
6227
6589
  return 1;
6228
6590
  }
6229
- const absolutePlayPath = (0, import_node_path8.resolve)(options.target);
6591
+ const absolutePlayPath = (0, import_node_path9.resolve)(options.target);
6230
6592
  const sourceCode = (0, import_node_fs6.readFileSync)(absolutePlayPath, "utf-8");
6231
6593
  let graph;
6232
6594
  try {
@@ -6290,7 +6652,7 @@ async function handleFileBackedRun(options) {
6290
6652
  }
6291
6653
  const client = new DeeplineClient();
6292
6654
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
6293
- const absolutePlayPath = (0, import_node_path8.resolve)(options.target.path);
6655
+ const absolutePlayPath = (0, import_node_path9.resolve)(options.target.path);
6294
6656
  progress.phase("compiling play");
6295
6657
  const sourceCode = traceCliSync(
6296
6658
  "cli.play_file_read_source",
@@ -6579,11 +6941,11 @@ async function handlePlayRun(args) {
6579
6941
  if (isFileTarget(options.target.path)) {
6580
6942
  return handleFileBackedRun(options);
6581
6943
  }
6582
- const resolved = (0, import_node_path8.resolve)(options.target.path);
6944
+ const resolved = (0, import_node_path9.resolve)(options.target.path);
6583
6945
  console.error(`File not found: ${resolved}`);
6584
- const dir = (0, import_node_path8.dirname)(resolved);
6946
+ const dir = (0, import_node_path9.dirname)(resolved);
6585
6947
  if ((0, import_node_fs6.existsSync)(dir)) {
6586
- const base = (0, import_node_path8.basename)(resolved);
6948
+ const base = (0, import_node_path9.basename)(resolved);
6587
6949
  try {
6588
6950
  const siblings = (0, import_node_fs6.readdirSync)(dir).filter(
6589
6951
  (f) => f.includes(base.replace(/\.(play\.)?ts$/, "")) || f.endsWith(".play.ts")
@@ -6591,7 +6953,7 @@ async function handlePlayRun(args) {
6591
6953
  if (siblings.length > 0) {
6592
6954
  console.error(`Did you mean one of these?`);
6593
6955
  for (const s of siblings.slice(0, 5)) {
6594
- console.error(` ${(0, import_node_path8.join)(dir, s)}`);
6956
+ console.error(` ${(0, import_node_path9.join)(dir, s)}`);
6595
6957
  }
6596
6958
  }
6597
6959
  } catch {
@@ -6737,7 +7099,7 @@ async function handleRunLogs(args) {
6737
7099
  continue;
6738
7100
  }
6739
7101
  if (arg === "--out" && args[index + 1]) {
6740
- outPath = (0, import_node_path8.resolve)(args[++index]);
7102
+ outPath = (0, import_node_path9.resolve)(args[++index]);
6741
7103
  }
6742
7104
  }
6743
7105
  const client = new DeeplineClient();
@@ -6824,7 +7186,7 @@ async function handleRunExport(args) {
6824
7186
  for (let index = 0; index < args.length; index += 1) {
6825
7187
  const arg = args[index];
6826
7188
  if (arg === "--out" && args[index + 1]) {
6827
- outPath = (0, import_node_path8.resolve)(args[++index]);
7189
+ outPath = (0, import_node_path9.resolve)(args[++index]);
6828
7190
  }
6829
7191
  }
6830
7192
  if (!outPath) {
@@ -6864,10 +7226,10 @@ async function handlePlayGet(args) {
6864
7226
  for (let index = 1; index < args.length; index += 1) {
6865
7227
  const arg = args[index];
6866
7228
  if (arg === "--out" && args[index + 1]) {
6867
- outPath = (0, import_node_path8.resolve)(args[++index]);
7229
+ outPath = (0, import_node_path9.resolve)(args[++index]);
6868
7230
  }
6869
7231
  }
6870
- const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs6.readFileSync)((0, import_node_path8.resolve)(target), "utf-8"), (0, import_node_path8.resolve)(target)) : parseReferencedPlayTarget(target).playName;
7232
+ const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs6.readFileSync)((0, import_node_path9.resolve)(target), "utf-8"), (0, import_node_path9.resolve)(target)) : parseReferencedPlayTarget(target).playName;
6871
7233
  const detail = isFileTarget(target) ? await client.getPlay(playName) : await assertCanonicalNamedPlayReference(client, target);
6872
7234
  const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
6873
7235
  const materializedFile = outPath ? materializeRemotePlaySource({
@@ -7159,7 +7521,7 @@ async function handlePlayPublish(args) {
7159
7521
  }
7160
7522
  let graph;
7161
7523
  try {
7162
- graph = await collectBundledPlayGraph((0, import_node_path8.resolve)(playName));
7524
+ graph = await collectBundledPlayGraph((0, import_node_path9.resolve)(playName));
7163
7525
  await compileBundledPlayGraphManifests(client, graph);
7164
7526
  await publishImportedPlayDependencies(client, graph);
7165
7527
  } catch (error) {
@@ -7259,12 +7621,15 @@ Concepts:
7259
7621
  Plays are durable cloud workflows.
7260
7622
  Stable ctx.tools.execute({ id, tool, input }) calls are replay-safe.
7261
7623
  ctx.map adds row keys and row progress.
7624
+ Named play runs use the live revision unless --latest or --revision-id is set.
7625
+ Running a local file does not make it live; use set-live/publish explicitly.
7262
7626
 
7263
7627
  Common commands:
7264
7628
  deepline plays search email --json
7265
7629
  deepline plays describe person-linkedin-to-email --json
7266
7630
  deepline plays check my.play.ts
7267
7631
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
7632
+ deepline plays set-live my.play.ts --json
7268
7633
  deepline plays get person-linkedin-to-email --json
7269
7634
  `
7270
7635
  );
@@ -7294,9 +7659,11 @@ Notes:
7294
7659
  Unknown --foo and --foo.bar flags are treated as play input args.
7295
7660
  File args accept local paths; the CLI stages files before submit.
7296
7661
  --watch prints logs, previews, stats, and next commands.
7662
+ --wait is accepted as a compatibility alias for --watch.
7297
7663
  The play page opens in your browser as soon as the run starts; use --no-open
7298
7664
  to only print the URL.
7299
7665
  --force supersedes active runs; it does not bypass completed reuse.
7666
+ This command starts cloud work and may spend Deepline credits through tool calls.
7300
7667
 
7301
7668
  Idempotent execution:
7302
7669
  Stable tool call ids are the reuse key:
@@ -7321,6 +7688,7 @@ Idempotent execution:
7321
7688
 
7322
7689
  Examples:
7323
7690
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
7691
+ deepline plays run my.play.ts --input @input.json --wait --json
7324
7692
  deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}' --watch
7325
7693
  deepline plays run enrich.play.ts --csv leads.csv --watch --out leads-enriched.csv
7326
7694
  deepline plays run cto-search.play.ts --limit 5 --watch
@@ -7332,7 +7700,7 @@ Examples:
7332
7700
  ).option(
7333
7701
  "--out <path>",
7334
7702
  "Write the completed row output to CSV; requires --watch"
7335
- ).option("--watch", "Stream logs until completion").option(
7703
+ ).option("--watch", "Stream logs until completion").option("--wait", "Alias for --watch; stream logs until completion").option(
7336
7704
  "--logs",
7337
7705
  "When output is non-interactive, stream play logs to stderr while waiting"
7338
7706
  ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Supersede any active runs for this play").option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").action(async (target, options, command) => {
@@ -7355,7 +7723,7 @@ Examples:
7355
7723
  ...options.latest ? ["--latest"] : [],
7356
7724
  ...options.revisionId ? ["--revision-id", options.revisionId] : [],
7357
7725
  ...options.out ? ["--out", options.out] : [],
7358
- ...options.watch ? ["--watch"] : [],
7726
+ ...options.watch || options.wait ? ["--watch"] : [],
7359
7727
  ...options.logs ? ["--logs"] : [],
7360
7728
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
7361
7729
  ...options.force ? ["--force"] : [],
@@ -7386,12 +7754,36 @@ Examples:
7386
7754
  ...options.out ? ["--out", options.out] : []
7387
7755
  ]);
7388
7756
  });
7389
- play.command("list").description("List saved and prebuilt plays.").option("--json", "Emit JSON output").action(async (options) => {
7757
+ play.command("list").description("List saved and prebuilt plays.").addHelpText(
7758
+ "after",
7759
+ `
7760
+ Notes:
7761
+ Inventory command for saved org plays and prebuilt plays. Use search for
7762
+ ranked discovery by task or schema.
7763
+
7764
+ Examples:
7765
+ deepline plays list
7766
+ deepline plays list --json
7767
+ deepline plays search email --origin prebuilt --json
7768
+ `
7769
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
7390
7770
  process.exitCode = await handlePlayList([
7391
7771
  ...options.json ? ["--json"] : []
7392
7772
  ]);
7393
7773
  });
7394
- play.command("search <query>").description("Search saved and prebuilt plays.").option("--origin <origin>", "Filter to prebuilt or owned plays").option("--compact", "Emit compact schemas").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
7774
+ play.command("search <query>").description("Search saved and prebuilt plays.").addHelpText(
7775
+ "after",
7776
+ `
7777
+ Notes:
7778
+ Ranked discovery for workflows. Use --origin prebuilt or --origin owned when
7779
+ you need to narrow results. Use describe on a result before running it.
7780
+
7781
+ Examples:
7782
+ deepline plays search email
7783
+ deepline plays search "linkedin to email" --origin prebuilt --compact --json
7784
+ deepline plays describe person-linkedin-to-email --json
7785
+ `
7786
+ ).option("--origin <origin>", "Filter to prebuilt or owned plays").option("--compact", "Emit compact schemas").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
7395
7787
  process.exitCode = await handlePlaySearch([
7396
7788
  query,
7397
7789
  ...options.origin ? ["--origin", options.origin] : [],
@@ -7417,13 +7809,43 @@ Examples:
7417
7809
  ...options.json ? ["--json"] : []
7418
7810
  ]);
7419
7811
  });
7420
- play.command("versions").description("List revisions for a named play.").option("--name <name>", "Saved play name").option("--json", "Emit JSON output").action(async (options) => {
7812
+ play.command("versions").description("List revisions for a named play.").addHelpText(
7813
+ "after",
7814
+ `
7815
+ Notes:
7816
+ Shows saved revisions for an org-owned play, including which revision is live
7817
+ when that metadata is available. Named runs use the live revision by default.
7818
+
7819
+ Examples:
7820
+ deepline plays versions --name my-play
7821
+ deepline plays versions --name my-play --json
7822
+ deepline plays run my-play --revision-id <revision-id> --watch
7823
+ `
7824
+ ).option("--name <name>", "Saved play name").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
7421
7825
  process.exitCode = await handlePlayVersions([
7422
7826
  ...options.name ? ["--name", options.name] : [],
7423
7827
  ...options.json ? ["--json"] : []
7424
7828
  ]);
7425
7829
  });
7426
- play.command("publish <target>").description("Bundle, validate, save, and publish a play.").option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output").action(async (target, options) => {
7830
+ const addPublishHelp = (command) => command.addHelpText(
7831
+ "after",
7832
+ `
7833
+ Notes:
7834
+ Mutates cloud state. For a local file, this bundles, validates, saves a new
7835
+ revision, and promotes that revision live. For a saved play, --latest or
7836
+ --revision-id promotes an existing saved revision live.
7837
+ Running a local file with plays run does not publish it.
7838
+
7839
+ Examples:
7840
+ deepline plays set-live my.play.ts --json
7841
+ deepline plays set-live my-play --latest --json
7842
+ deepline plays set-live my-play --revision-id <revision-id> --json
7843
+ deepline plays publish my.play.ts --json
7844
+ `
7845
+ );
7846
+ addPublishHelp(
7847
+ play.command("publish <target>").description("Bundle, validate, save, and promote a play revision live.")
7848
+ ).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
7427
7849
  process.exitCode = await handlePlayPublish([
7428
7850
  target,
7429
7851
  ...options.latest ? ["--latest"] : [],
@@ -7431,7 +7853,28 @@ Examples:
7431
7853
  ...options.json ? ["--json"] : []
7432
7854
  ]);
7433
7855
  });
7434
- play.command("delete <target>").description("Delete an org-owned play and its saved revisions/runs.").option("-y, --yes", "Confirm deletion").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
7856
+ addPublishHelp(
7857
+ play.command("set-live <target>").description("Promote a local file or saved revision as the live play revision.")
7858
+ ).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
7859
+ process.exitCode = await handlePlayPublish([
7860
+ target,
7861
+ ...options.latest ? ["--latest"] : [],
7862
+ ...options.revisionId ? ["--revision-id", options.revisionId] : [],
7863
+ ...options.json ? ["--json"] : []
7864
+ ]);
7865
+ });
7866
+ play.command("delete <target>").description("Delete an org-owned play and its saved revisions/runs.").addHelpText(
7867
+ "after",
7868
+ `
7869
+ Notes:
7870
+ Destructive mutation. Deletes an org-owned play plus saved revisions and run
7871
+ records. Prebuilt/read-only plays are refused. Use --yes for noninteractive runs.
7872
+
7873
+ Examples:
7874
+ deepline plays delete my-play
7875
+ deepline plays delete my-play --yes --json
7876
+ `
7877
+ ).option("-y, --yes", "Confirm deletion").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
7435
7878
  process.exitCode = await handlePlayDelete([
7436
7879
  target,
7437
7880
  ...options.yes ? ["--yes"] : [],
@@ -7441,6 +7884,12 @@ Examples:
7441
7884
  const runs = program.command("runs").description("Inspect, tail, stop, and export play runs.").addHelpText(
7442
7885
  "after",
7443
7886
  `
7887
+ Concepts:
7888
+ A run is one execution instance of a play. It has status, progress, logs,
7889
+ preview output, recovery metadata, and optional full row export.
7890
+ tail reads the live stream. logs fetches persisted logs after the fact.
7891
+ stop mutates cloud state by requesting cancellation.
7892
+
7444
7893
  Examples:
7445
7894
  deepline runs get play/my-play/run/20260501t000000-000 --json
7446
7895
  deepline runs tail play/my-play/run/20260501t000000-000
@@ -7450,14 +7899,36 @@ Examples:
7450
7899
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv
7451
7900
  `
7452
7901
  );
7453
- runs.command("get <runId>").description("Get status, progress, outputs, errors, and recovery metadata for a play run.").option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--full", "Debug only: with --json, emit the raw status payload").action(async (runId, options) => {
7902
+ runs.command("get <runId>").description("Get status, progress, outputs, errors, and recovery metadata for a play run.").addHelpText(
7903
+ "after",
7904
+ `
7905
+ Notes:
7906
+ Full run status read. Use --full --json when debugging raw stream/status fields.
7907
+
7908
+ Examples:
7909
+ deepline runs get play/my-play/run/20260501t000000-000
7910
+ deepline runs get play/my-play/run/20260501t000000-000 --json
7911
+ deepline runs get play/my-play/run/20260501t000000-000 --full --json
7912
+ `
7913
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--full", "Debug only: with --json, emit the raw status payload").action(async (runId, options) => {
7454
7914
  process.exitCode = await handleRunGet([
7455
7915
  runId,
7456
7916
  ...options.json ? ["--json"] : [],
7457
7917
  ...options.full ? ["--full"] : []
7458
7918
  ]);
7459
7919
  });
7460
- runs.command("list").description("List play runs.").requiredOption("--play <name>", "Play name to filter runs").option("--status <status>", "Filter by run status").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
7920
+ runs.command("list").description("List play runs.").addHelpText(
7921
+ "after",
7922
+ `
7923
+ Notes:
7924
+ Bounded inventory for a play's recent runs. Use --compact for agent loops.
7925
+ Common statuses include running, completed, failed, and stopped.
7926
+
7927
+ Examples:
7928
+ deepline runs list --play my-play
7929
+ deepline runs list --play my-play --status failed --compact --json
7930
+ `
7931
+ ).requiredOption("--play <name>", "Play name to filter runs").option("--status <status>", "Filter by run status").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
7461
7932
  process.exitCode = await handleRunsList([
7462
7933
  "--play",
7463
7934
  options.play,
@@ -7466,14 +7937,37 @@ Examples:
7466
7937
  ...options.json ? ["--json"] : []
7467
7938
  ]);
7468
7939
  });
7469
- runs.command("tail <runId>").description("Read the canonical live stream for a play run.").option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--compact", "Drop verbose fields from JSON output").action(async (runId, options) => {
7940
+ runs.command("tail <runId>").description("Read the canonical live stream for a play run.").addHelpText(
7941
+ "after",
7942
+ `
7943
+ Notes:
7944
+ Streams live run events until the stream ends. Use get for current status and
7945
+ logs for persisted log history.
7946
+
7947
+ Examples:
7948
+ deepline runs tail play/my-play/run/20260501t000000-000
7949
+ deepline runs tail play/my-play/run/20260501t000000-000 --compact --json
7950
+ `
7951
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--compact", "Drop verbose fields from JSON output").action(async (runId, options) => {
7470
7952
  process.exitCode = await handleRunTail([
7471
7953
  runId,
7472
7954
  ...options.json ? ["--json"] : [],
7473
7955
  ...options.compact ? ["--compact"] : []
7474
7956
  ]);
7475
7957
  });
7476
- runs.command("logs <runId>").description("Fetch persisted logs for a play run.").option("--limit <count>", "Maximum recent log lines to print without --out", "200").option("--out <path>", "Write the full persisted log stream to a file").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
7958
+ runs.command("logs <runId>").description("Fetch persisted logs for a play run.").addHelpText(
7959
+ "after",
7960
+ `
7961
+ Notes:
7962
+ Prints a bounded recent log preview by default. Use --out to write the full
7963
+ persisted log stream to a local file.
7964
+
7965
+ Examples:
7966
+ deepline runs logs play/my-play/run/20260501t000000-000
7967
+ deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
7968
+ deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
7969
+ `
7970
+ ).option("--limit <count>", "Maximum recent log lines to print without --out", "200").option("--out <path>", "Write the full persisted log stream to a file").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
7477
7971
  process.exitCode = await handleRunLogs([
7478
7972
  runId,
7479
7973
  ...options.limit ? ["--limit", options.limit] : [],
@@ -7481,14 +7975,36 @@ Examples:
7481
7975
  ...options.json ? ["--json"] : []
7482
7976
  ]);
7483
7977
  });
7484
- runs.command("stop <runId>").description("Stop a play run.").option("--reason <text>", "Reason to include with the stop request").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
7978
+ runs.command("stop <runId>").description("Stop a play run.").addHelpText(
7979
+ "after",
7980
+ `
7981
+ Notes:
7982
+ Mutates cloud state by requesting cancellation for an active run. Already
7983
+ terminal runs are returned as no-ops by the server when applicable.
7984
+
7985
+ Examples:
7986
+ deepline runs stop play/my-play/run/20260501t000000-000 --reason "stale lock"
7987
+ deepline runs stop play/my-play/run/20260501t000000-000 --json
7988
+ `
7989
+ ).option("--reason <text>", "Reason to include with the stop request").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
7485
7990
  process.exitCode = await handleRunStop([
7486
7991
  runId,
7487
7992
  ...options.reason ? ["--reason", options.reason] : [],
7488
7993
  ...options.json ? ["--json"] : []
7489
7994
  ]);
7490
7995
  });
7491
- runs.command("export <runId>").description("Export the completed row output for a play run to CSV.").requiredOption("--out <path>", "Output CSV path").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
7996
+ runs.command("export <runId>").description("Export the completed row output for a play run to CSV.").addHelpText(
7997
+ "after",
7998
+ `
7999
+ Notes:
8000
+ Writes the completed row output to the requested local CSV path. Use runs get
8001
+ first when you need to confirm the run is complete or inspect preview output.
8002
+
8003
+ Examples:
8004
+ deepline runs export play/my-play/run/20260501t000000-000 --out output.csv
8005
+ deepline runs export play/my-play/run/20260501t000000-000 --out output.csv --json
8006
+ `
8007
+ ).requiredOption("--out <path>", "Output CSV path").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
7492
8008
  process.exitCode = await handleRunExport([
7493
8009
  runId,
7494
8010
  "--out",
@@ -7501,12 +8017,12 @@ Examples:
7501
8017
  // src/cli/commands/tools.ts
7502
8018
  var import_node_fs8 = require("fs");
7503
8019
  var import_node_os7 = require("os");
7504
- var import_node_path10 = require("path");
8020
+ var import_node_path11 = require("path");
7505
8021
 
7506
8022
  // src/tool-output.ts
7507
8023
  var import_node_fs7 = require("fs");
7508
8024
  var import_node_os6 = require("os");
7509
- var import_node_path9 = require("path");
8025
+ var import_node_path10 = require("path");
7510
8026
  function isPlainObject(value) {
7511
8027
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7512
8028
  }
@@ -7581,19 +8097,19 @@ function tryConvertToList(payload, options) {
7581
8097
  return null;
7582
8098
  }
7583
8099
  function ensureOutputDir() {
7584
- const outputDir = (0, import_node_path9.join)((0, import_node_os6.homedir)(), ".local", "share", "deepline", "data");
8100
+ const outputDir = (0, import_node_path10.join)((0, import_node_os6.homedir)(), ".local", "share", "deepline", "data");
7585
8101
  (0, import_node_fs7.mkdirSync)(outputDir, { recursive: true });
7586
8102
  return outputDir;
7587
8103
  }
7588
8104
  function writeJsonOutputFile(payload, stem) {
7589
8105
  const outputDir = ensureOutputDir();
7590
- const outputPath = (0, import_node_path9.join)(outputDir, `${stem}_${Date.now()}.json`);
8106
+ const outputPath = (0, import_node_path10.join)(outputDir, `${stem}_${Date.now()}.json`);
7591
8107
  (0, import_node_fs7.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
7592
8108
  return outputPath;
7593
8109
  }
7594
8110
  function writeCsvOutputFile(rows, stem) {
7595
8111
  const outputDir = ensureOutputDir();
7596
- const outputPath = (0, import_node_path9.join)(outputDir, `${stem}_${Date.now()}.csv`);
8112
+ const outputPath = (0, import_node_path10.join)(outputDir, `${stem}_${Date.now()}.csv`);
7597
8113
  const seen = /* @__PURE__ */ new Set();
7598
8114
  const columns = [];
7599
8115
  for (const row of rows) {
@@ -7732,16 +8248,44 @@ Concepts:
7732
8248
 
7733
8249
  Common commands:
7734
8250
  deepline tools search email --json
7735
- deepline tools get hunter_email_verifier --json
8251
+ deepline tools describe hunter_email_verifier --json
7736
8252
  deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
8253
+
8254
+ Output:
8255
+ Search/list output is bounded. Use describe for a compact contract and get for
8256
+ the full machine-readable metadata available for the tool.
7737
8257
  `
7738
8258
  );
7739
- tools.command("list").description("List available tools.").option("--json", "Emit JSON output").action(async (options) => {
8259
+ tools.command("list").description("List available tools.").addHelpText(
8260
+ "after",
8261
+ `
8262
+ Notes:
8263
+ Inventory command for known tool ids. Use search for ranked discovery by
8264
+ intent, aliases, descriptions, and schema fields.
8265
+
8266
+ Examples:
8267
+ deepline tools list
8268
+ deepline tools list --json
8269
+ deepline tools search email --json
8270
+ `
8271
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
7740
8272
  process.exitCode = await listTools([
7741
8273
  ...options.json ? ["--json"] : []
7742
8274
  ]);
7743
8275
  });
7744
- tools.command("search <query>").description("Search available tools.").option("--categories <categories>", "Comma-separated categories to filter ranked search").option("--search_terms <terms>", "Structured search terms for ranked search").option("--search-terms <terms>", "Structured search terms for ranked search").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
8276
+ tools.command("search <query>").description("Search available tools.").addHelpText(
8277
+ "after",
8278
+ `
8279
+ Notes:
8280
+ Ranked discovery for atomic provider/API operations. Results include tool ids
8281
+ that can be passed to deepline tools describe or deepline tools call.
8282
+
8283
+ Examples:
8284
+ deepline tools search email
8285
+ deepline tools search "company enrichment" --categories enrichment --json
8286
+ deepline tools search verifier --search-mode v2 --json
8287
+ `
8288
+ ).option("--categories <categories>", "Comma-separated categories to filter ranked search").option("--search_terms <terms>", "Structured search terms for ranked search").option("--search-terms <terms>", "Structured search terms for ranked search").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
7745
8289
  process.exitCode = await searchTools(query, {
7746
8290
  json: options.json,
7747
8291
  categories: options.categories,
@@ -7750,15 +8294,18 @@ Common commands:
7750
8294
  includeSearchDebug: Boolean(options.includeSearchDebug)
7751
8295
  });
7752
8296
  });
7753
- tools.command("get <toolId>").alias("describe").description("Show metadata for a tool.").addHelpText(
8297
+ const addToolMetadataCommand = (command, preferredExample) => command.description("Show metadata for a tool.").addHelpText(
7754
8298
  "after",
7755
8299
  `
7756
8300
  Notes:
7757
- Shows the tool contract, input schema, output schema, costs, aliases, and metadata.
8301
+ Shows the tool contract, input schema, output schema, Deepline cost, aliases,
8302
+ and metadata. describe is the preferred discovery verb; get is kept as a
8303
+ compatibility command for the same metadata surface.
7758
8304
 
7759
8305
  Examples:
7760
- deepline tools get hunter_email_verifier
7761
- deepline tools get hunter_email_verifier --json | jq '.inputSchema'
8306
+ deepline tools ${preferredExample} hunter_email_verifier
8307
+ deepline tools ${preferredExample} hunter_email_verifier --json | jq '.inputSchema'
8308
+ deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
7762
8309
  `
7763
8310
  ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (toolId, options) => {
7764
8311
  process.exitCode = await getTool([
@@ -7766,12 +8313,16 @@ Examples:
7766
8313
  ...options.json ? ["--json"] : []
7767
8314
  ]);
7768
8315
  });
8316
+ addToolMetadataCommand(tools.command("describe <toolId>"), "describe");
8317
+ addToolMetadataCommand(tools.command("get <toolId>"), "get");
7769
8318
  tools.command("call <toolId>").alias("execute").alias("run").description("Execute a tool by id.").addHelpText(
7770
8319
  "after",
7771
8320
  `
7772
8321
  Notes:
7773
8322
  Use tools for one atomic provider/API operation. Use plays for composed workflows,
7774
8323
  waterfalls, row maps, checkpoints, and retries.
8324
+ Calling a provider-backed tool can spend Deepline credits. Use --json for the
8325
+ stable result payload and --full-output when debugging response metadata.
7775
8326
 
7776
8327
  Examples:
7777
8328
  deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
@@ -8118,9 +8669,9 @@ function powerShellQuote(value) {
8118
8669
  function seedToolListScript(input) {
8119
8670
  const stem = safeFileStem(input.toolId);
8120
8671
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
8121
- const scriptDir = (0, import_node_fs8.mkdtempSync)((0, import_node_path10.join)((0, import_node_os7.tmpdir)(), "deepline-workflow-seed-"));
8672
+ const scriptDir = (0, import_node_fs8.mkdtempSync)((0, import_node_path11.join)((0, import_node_os7.tmpdir)(), "deepline-workflow-seed-"));
8122
8673
  (0, import_node_fs8.chmodSync)(scriptDir, 448);
8123
- const scriptPath = (0, import_node_path10.join)(scriptDir, fileName);
8674
+ const scriptPath = (0, import_node_path11.join)(scriptDir, fileName);
8124
8675
  const projectDir = `deepline/projects/${stem}-workflow`;
8125
8676
  const playName = `${stem}-workflow`;
8126
8677
  const sampleRows = input.rows.length > 0 ? `${JSON.stringify(input.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
@@ -8263,7 +8814,7 @@ async function executeTool(args) {
8263
8814
  var import_node_child_process2 = require("child_process");
8264
8815
  var import_node_fs9 = require("fs");
8265
8816
  var import_node_os8 = require("os");
8266
- var import_node_path11 = require("path");
8817
+ var import_node_path12 = require("path");
8267
8818
  var CHECK_TIMEOUT_MS2 = 3e3;
8268
8819
  var SDK_SKILL_NAME = "deepline-sdk";
8269
8820
  var SKILL_AGENTS = ["codex", "claude-code", "cursor"];
@@ -8274,7 +8825,7 @@ function shouldSkipSkillsSync() {
8274
8825
  }
8275
8826
  function sdkSkillsVersionPath(baseUrl) {
8276
8827
  const home = process.env.HOME?.trim() || (0, import_node_os8.homedir)();
8277
- return (0, import_node_path11.join)(home, ".local", "deepline", baseUrlSlug(baseUrl), "sdk-skills", ".version");
8828
+ return (0, import_node_path12.join)(home, ".local", "deepline", baseUrlSlug(baseUrl), "sdk-skills", ".version");
8278
8829
  }
8279
8830
  function readLocalSkillsVersion(baseUrl) {
8280
8831
  const path = sdkSkillsVersionPath(baseUrl);
@@ -8287,7 +8838,7 @@ function readLocalSkillsVersion(baseUrl) {
8287
8838
  }
8288
8839
  function writeLocalSkillsVersion(baseUrl, version) {
8289
8840
  const path = sdkSkillsVersionPath(baseUrl);
8290
- (0, import_node_fs9.mkdirSync)((0, import_node_path11.dirname)(path), { recursive: true });
8841
+ (0, import_node_fs9.mkdirSync)((0, import_node_path12.dirname)(path), { recursive: true });
8291
8842
  (0, import_node_fs9.writeFileSync)(path, `${version}
8292
8843
  `, "utf-8");
8293
8844
  }
@@ -8382,7 +8933,7 @@ function resolveSkillsInstallCommands(baseUrl) {
8382
8933
  return [npxInstall];
8383
8934
  }
8384
8935
  function runOneSkillsInstall(install) {
8385
- return new Promise((resolve8) => {
8936
+ return new Promise((resolve9) => {
8386
8937
  const child = (0, import_node_child_process2.spawn)(install.command, install.args, {
8387
8938
  stdio: ["ignore", "ignore", "pipe"],
8388
8939
  env: process.env
@@ -8392,7 +8943,7 @@ function runOneSkillsInstall(install) {
8392
8943
  stderr += chunk.toString("utf-8");
8393
8944
  });
8394
8945
  child.on("error", (error) => {
8395
- resolve8({
8946
+ resolve9({
8396
8947
  ok: false,
8397
8948
  detail: `failed to start ${install.command}: ${error.message}`,
8398
8949
  manualCommand: install.manualCommand
@@ -8400,11 +8951,11 @@ function runOneSkillsInstall(install) {
8400
8951
  });
8401
8952
  child.on("close", (code) => {
8402
8953
  if (code === 0) {
8403
- resolve8({ ok: true, detail: "", manualCommand: install.manualCommand });
8954
+ resolve9({ ok: true, detail: "", manualCommand: install.manualCommand });
8404
8955
  return;
8405
8956
  }
8406
8957
  const detail = stderr.trim();
8407
- resolve8({
8958
+ resolve9({
8408
8959
  ok: false,
8409
8960
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
8410
8961
  manualCommand: install.manualCommand
@@ -8457,6 +9008,9 @@ function shouldPrintStartupPhase() {
8457
9008
  return false;
8458
9009
  }
8459
9010
  const args = process.argv.slice(2);
9011
+ if (args.includes("-h") || args.includes("--help")) {
9012
+ return false;
9013
+ }
8460
9014
  const command = args[0];
8461
9015
  const subcommand = args[1];
8462
9016
  return (command === "play" || command === "plays") && subcommand === "run";
@@ -8478,7 +9032,7 @@ async function main() {
8478
9032
  if (printStartupPhase) {
8479
9033
  progress?.phase("loading deepline cli");
8480
9034
  }
8481
- const program = new import_commander.Command();
9035
+ const program = new import_commander2.Command();
8482
9036
  program.name("deepline").description("Deepline CLI (TypeScript SDK)").version(SDK_VERSION, "-v, --version", "Show version").showHelpAfterError().showSuggestionAfterError(true).addHelpText(
8483
9037
  "after",
8484
9038
  `
@@ -8490,9 +9044,23 @@ Common commands:
8490
9044
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
8491
9045
  deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
8492
9046
 
9047
+ Product model:
9048
+ Tools are atomic provider/API operations that may spend credits.
9049
+ Plays are durable workflows backed by source code or saved cloud revisions.
9050
+ Runs are execution instances with logs, status, outputs, and cancellation.
9051
+ Live plays are promoted revisions used by named play runs.
9052
+
8493
9053
  Output:
8494
9054
  Structured commands print human-readable output in a terminal and JSON when stdout is piped.
8495
9055
  Use --json to force JSON in an interactive terminal.
9056
+
9057
+ Safety:
9058
+ Commands that mutate state, open a browser, write files, stop work, or spend credits say so in their help.
9059
+ Use --no-open where available for CI and agent runs.
9060
+
9061
+ Exit codes:
9062
+ 0 success; 2 usage/local input error; 3 auth/permission error; 4 not found;
9063
+ 5 server/runtime/provider failure; 7 validation/check failed.
8496
9064
  `
8497
9065
  );
8498
9066
  program.hook("preAction", async (_thisCommand, actionCommand) => {
@@ -8527,7 +9095,17 @@ Output:
8527
9095
  registerCsvCommands(program);
8528
9096
  registerDbCommands(program);
8529
9097
  registerFeedbackCommands(program);
8530
- program.command("health").description("Check server health.").action(async () => {
9098
+ program.command("health").description("Check server health.").addHelpText(
9099
+ "after",
9100
+ `
9101
+ Notes:
9102
+ Read-only connectivity check for the configured Deepline host. Prints the raw
9103
+ server health payload as JSON.
9104
+
9105
+ Examples:
9106
+ deepline health
9107
+ `
9108
+ ).action(async () => {
8531
9109
  try {
8532
9110
  const client = new DeeplineClient();
8533
9111
  const data = await client.health();
@@ -8539,7 +9117,18 @@ Output:
8539
9117
  );
8540
9118
  }
8541
9119
  });
8542
- program.command("version").description("Show version.").action(() => {
9120
+ program.command("version").description("Show version.").addHelpText(
9121
+ "after",
9122
+ `
9123
+ Notes:
9124
+ Prints the SDK CLI package version. The top-level -v/--version flag returns
9125
+ the same version.
9126
+
9127
+ Examples:
9128
+ deepline version
9129
+ deepline --version
9130
+ `
9131
+ ).action(() => {
8543
9132
  process.stdout.write(`deepline ${SDK_VERSION}
8544
9133
  `);
8545
9134
  });