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 +741 -152
- package/dist/cli/index.mjs +703 -114
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +95 -81
- package/dist/repo/apps/play-runner-workers/src/dedup-do.ts +18 -5
- package/dist/repo/apps/play-runner-workers/src/entry.ts +37 -32
- package/dist/repo/apps/play-runner-workers/src/runtime/live-progress.ts +18 -0
- package/dist/repo/sdk/src/plays/harness-stub.ts +2 -0
- package/dist/repo/sdk/src/version.ts +1 -1
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
|
-
import { Command } from "commander";
|
|
4
|
+
import { Command as Command2 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
7
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
|
|
@@ -243,7 +243,7 @@ function saveProjectDeeplineEnvValues(baseUrl, values, startDir = projectEnvStar
|
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
// src/version.ts
|
|
246
|
-
var SDK_VERSION = "0.1.
|
|
246
|
+
var SDK_VERSION = "0.1.25";
|
|
247
247
|
var SDK_API_CONTRACT = "2026-05-runs-v2";
|
|
248
248
|
|
|
249
249
|
// ../shared_libs/play-runtime/coordinator-headers.ts
|
|
@@ -525,7 +525,7 @@ function decodeSseFrame(frame) {
|
|
|
525
525
|
return parsed;
|
|
526
526
|
}
|
|
527
527
|
function sleep(ms) {
|
|
528
|
-
return new Promise((
|
|
528
|
+
return new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
529
529
|
}
|
|
530
530
|
|
|
531
531
|
// src/client.ts
|
|
@@ -533,7 +533,7 @@ var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "ca
|
|
|
533
533
|
var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
|
|
534
534
|
var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
|
|
535
535
|
function sleep2(ms) {
|
|
536
|
-
return new Promise((
|
|
536
|
+
return new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
537
537
|
}
|
|
538
538
|
function isTransientCompileManifestError(error) {
|
|
539
539
|
if (error instanceof DeeplineError && typeof error.statusCode === "number") {
|
|
@@ -2023,7 +2023,7 @@ function buildCandidateUrls2(url) {
|
|
|
2023
2023
|
}
|
|
2024
2024
|
}
|
|
2025
2025
|
function sleep3(ms) {
|
|
2026
|
-
return new Promise((
|
|
2026
|
+
return new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
2027
2027
|
}
|
|
2028
2028
|
function printDeeplineLogo() {
|
|
2029
2029
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
@@ -2330,18 +2330,48 @@ function registerAuthCommands(program) {
|
|
|
2330
2330
|
`
|
|
2331
2331
|
Common commands:
|
|
2332
2332
|
deepline auth register
|
|
2333
|
+
deepline auth register --no-wait
|
|
2334
|
+
deepline auth wait --timeout 300
|
|
2333
2335
|
deepline auth status
|
|
2334
2336
|
deepline auth status --json
|
|
2337
|
+
|
|
2338
|
+
Notes:
|
|
2339
|
+
Registration opens a browser approval page by default. Use --no-wait in CI
|
|
2340
|
+
or agent runs, then finish with deepline auth wait.
|
|
2341
|
+
Auth status shows the target host and active workspace without printing secrets.
|
|
2335
2342
|
`
|
|
2336
2343
|
);
|
|
2337
|
-
auth.command("register").description("Register this device and open the approval page in your browser.").
|
|
2344
|
+
auth.command("register").description("Register this device and open the approval page in your browser.").addHelpText(
|
|
2345
|
+
"after",
|
|
2346
|
+
`
|
|
2347
|
+
Notes:
|
|
2348
|
+
Opens a browser approval page and waits for approval unless --no-wait is set.
|
|
2349
|
+
The saved API key is scoped to the selected workspace and host.
|
|
2350
|
+
|
|
2351
|
+
Examples:
|
|
2352
|
+
deepline auth register
|
|
2353
|
+
deepline auth register --org-name Acme --agent-name local-cli
|
|
2354
|
+
deepline auth register --no-wait
|
|
2355
|
+
`
|
|
2356
|
+
).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) => {
|
|
2338
2357
|
process.exitCode = await handleRegister([
|
|
2339
2358
|
...options.orgName ? ["--org-name", options.orgName] : [],
|
|
2340
2359
|
...options.agentName ? ["--agent-name", options.agentName] : [],
|
|
2341
2360
|
...options.noWait || options.wait === false ? ["--no-wait"] : []
|
|
2342
2361
|
]);
|
|
2343
2362
|
});
|
|
2344
|
-
auth.command("wait").description("Wait for a pending browser approval and save the API key.").
|
|
2363
|
+
auth.command("wait").description("Wait for a pending browser approval and save the API key.").addHelpText(
|
|
2364
|
+
"after",
|
|
2365
|
+
`
|
|
2366
|
+
Notes:
|
|
2367
|
+
Completes a previous deepline auth register --no-wait flow.
|
|
2368
|
+
Saves the approved API key into the host auth file.
|
|
2369
|
+
|
|
2370
|
+
Examples:
|
|
2371
|
+
deepline auth wait
|
|
2372
|
+
deepline auth wait --timeout 120
|
|
2373
|
+
`
|
|
2374
|
+
).option("--timeout <seconds>", "Maximum seconds to wait", "300").action(async (options) => {
|
|
2345
2375
|
process.exitCode = await handleWait([
|
|
2346
2376
|
...options.timeout ? ["--timeout", options.timeout] : []
|
|
2347
2377
|
]);
|
|
@@ -2367,6 +2397,10 @@ Examples:
|
|
|
2367
2397
|
}
|
|
2368
2398
|
|
|
2369
2399
|
// src/cli/commands/billing.ts
|
|
2400
|
+
import { Command } from "commander";
|
|
2401
|
+
import { appendFile, mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
2402
|
+
import { dirname as dirname4, resolve as resolve3 } from "path";
|
|
2403
|
+
import { stringify as stringify2 } from "csv-stringify/sync";
|
|
2370
2404
|
function humanize(value) {
|
|
2371
2405
|
return String(value || "").split("_").filter(Boolean).map((token) => token[0]?.toUpperCase() + token.slice(1)).join(" ") || "Unknown";
|
|
2372
2406
|
}
|
|
@@ -2384,6 +2418,54 @@ function printRecentUsage(entries) {
|
|
|
2384
2418
|
`);
|
|
2385
2419
|
}
|
|
2386
2420
|
}
|
|
2421
|
+
function summarizeLedgerRows(summary, rows) {
|
|
2422
|
+
const netDelta = rows.reduce((sum, row) => {
|
|
2423
|
+
const value = Number.parseFloat(String(row.delta_credits ?? "").trim());
|
|
2424
|
+
return Number.isFinite(value) ? sum + value : sum;
|
|
2425
|
+
}, summary.net_delta_credits);
|
|
2426
|
+
return {
|
|
2427
|
+
row_count: summary.row_count + rows.length,
|
|
2428
|
+
net_delta_credits: Math.round((netDelta + Number.EPSILON) * 100) / 100
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
function ledgerApiEntryToRow(entry) {
|
|
2432
|
+
const metadata = typeof entry.metadata === "object" && entry.metadata !== null ? entry.metadata : {};
|
|
2433
|
+
return {
|
|
2434
|
+
created_at: entry.created_at ?? "",
|
|
2435
|
+
delta_credits: entry.delta ?? "",
|
|
2436
|
+
reason: entry.reason ?? "",
|
|
2437
|
+
provider: metadata.provider ?? "",
|
|
2438
|
+
operation: metadata.operation ?? "",
|
|
2439
|
+
request_id: metadata.requestId ?? metadata.request_id ?? "",
|
|
2440
|
+
run_id: metadata.runId ?? metadata.run_id ?? "",
|
|
2441
|
+
api_key_id: entry.api_key_id ?? "",
|
|
2442
|
+
stripe_session_id: entry.stripe_session_id ?? ""
|
|
2443
|
+
};
|
|
2444
|
+
}
|
|
2445
|
+
function ledgerRowsToCsv(rows, header) {
|
|
2446
|
+
return stringify2(rows, {
|
|
2447
|
+
header,
|
|
2448
|
+
columns: [
|
|
2449
|
+
"created_at",
|
|
2450
|
+
"delta_credits",
|
|
2451
|
+
"reason",
|
|
2452
|
+
"provider",
|
|
2453
|
+
"operation",
|
|
2454
|
+
"request_id",
|
|
2455
|
+
"run_id",
|
|
2456
|
+
"api_key_id",
|
|
2457
|
+
"stripe_session_id"
|
|
2458
|
+
]
|
|
2459
|
+
});
|
|
2460
|
+
}
|
|
2461
|
+
function defaultLedgerExportPath() {
|
|
2462
|
+
return resolve3(
|
|
2463
|
+
process.cwd(),
|
|
2464
|
+
"deepline",
|
|
2465
|
+
"data",
|
|
2466
|
+
`billing-ledger-all-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.csv`
|
|
2467
|
+
);
|
|
2468
|
+
}
|
|
2387
2469
|
async function handleBalance(options) {
|
|
2388
2470
|
const { http } = getAuthedHttpClient();
|
|
2389
2471
|
const payload = await http.get("/api/v2/billing/balance");
|
|
@@ -2472,6 +2554,51 @@ async function handleHistory(options) {
|
|
|
2472
2554
|
process.stdout.write(`${rows.length} row(s) exported.
|
|
2473
2555
|
`);
|
|
2474
2556
|
}
|
|
2557
|
+
async function handleLedgerExportAll(options) {
|
|
2558
|
+
const { http } = getAuthedHttpClient();
|
|
2559
|
+
const outputPath = options.output ? resolve3(String(options.output)) : defaultLedgerExportPath();
|
|
2560
|
+
let summary = { row_count: 0, net_delta_credits: 0 };
|
|
2561
|
+
let cursor = null;
|
|
2562
|
+
let initializedOutput = false;
|
|
2563
|
+
for (; ; ) {
|
|
2564
|
+
const params = new URLSearchParams({ limit: "5000" });
|
|
2565
|
+
if (cursor !== null) params.set("cursor", cursor);
|
|
2566
|
+
const payload = await http.get(
|
|
2567
|
+
`/api/v2/billing/ledger?${params.toString()}`
|
|
2568
|
+
);
|
|
2569
|
+
const entries = Array.isArray(payload.entries) ? payload.entries : [];
|
|
2570
|
+
const rows = entries.map(ledgerApiEntryToRow);
|
|
2571
|
+
if (!initializedOutput) {
|
|
2572
|
+
await mkdir2(dirname4(outputPath), { recursive: true });
|
|
2573
|
+
await writeFile2(outputPath, ledgerRowsToCsv([], true), "utf-8");
|
|
2574
|
+
initializedOutput = true;
|
|
2575
|
+
}
|
|
2576
|
+
if (rows.length > 0) {
|
|
2577
|
+
await appendFile(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
|
|
2578
|
+
summary = summarizeLedgerRows(summary, rows);
|
|
2579
|
+
}
|
|
2580
|
+
const nextCursor = typeof payload.next_cursor === "string" && payload.next_cursor.length > 0 ? payload.next_cursor : null;
|
|
2581
|
+
if (rows.length === 0 || payload.has_more !== true || nextCursor === null) {
|
|
2582
|
+
break;
|
|
2583
|
+
}
|
|
2584
|
+
if (nextCursor === cursor) break;
|
|
2585
|
+
cursor = nextCursor;
|
|
2586
|
+
}
|
|
2587
|
+
if (shouldEmitJson(options.json)) {
|
|
2588
|
+
return printJson({
|
|
2589
|
+
output_path: outputPath,
|
|
2590
|
+
row_count: summary.row_count,
|
|
2591
|
+
net_delta_credits: summary.net_delta_credits,
|
|
2592
|
+
scope: "current_auth_context"
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
process.stdout.write(`Billing ledger written to ${outputPath}
|
|
2596
|
+
`);
|
|
2597
|
+
process.stdout.write(`${summary.row_count} row(s) exported for the current auth context.
|
|
2598
|
+
`);
|
|
2599
|
+
process.stdout.write(`Net ledger delta: ${summary.net_delta_credits} Deepline Credits
|
|
2600
|
+
`);
|
|
2601
|
+
}
|
|
2475
2602
|
async function handleCheckout(options) {
|
|
2476
2603
|
const { http } = getAuthedHttpClient();
|
|
2477
2604
|
const payload = await http.post("/api/v2/billing/checkout", {
|
|
@@ -2495,20 +2622,156 @@ async function handleRedeemCode(code, options) {
|
|
|
2495
2622
|
`);
|
|
2496
2623
|
}
|
|
2497
2624
|
function registerBillingCommands(program) {
|
|
2498
|
-
const billing = program.command("billing").description("Inspect balance, usage, limits, and checkout flows.")
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2625
|
+
const billing = program.command("billing").description("Inspect balance, usage, limits, and checkout flows.").addHelpText(
|
|
2626
|
+
"after",
|
|
2627
|
+
`
|
|
2628
|
+
Concepts:
|
|
2629
|
+
Billing commands show Deepline credits, not raw provider spend.
|
|
2630
|
+
set-limit/off mutate the monthly workspace cap. checkout/redeem-code can open
|
|
2631
|
+
a browser unless --no-open is set.
|
|
2632
|
+
|
|
2633
|
+
Examples:
|
|
2634
|
+
deepline billing balance --json
|
|
2635
|
+
deepline billing usage --limit 20 --json
|
|
2636
|
+
deepline billing set-limit 500 --json
|
|
2637
|
+
deepline billing checkout --credits 1000 --no-open --json
|
|
2638
|
+
`
|
|
2639
|
+
);
|
|
2640
|
+
billing.command("balance").description("Show current billing balance.").addHelpText(
|
|
2641
|
+
"after",
|
|
2642
|
+
`
|
|
2643
|
+
Notes:
|
|
2644
|
+
Read-only. Shows the current Deepline credit balance for the active workspace.
|
|
2645
|
+
|
|
2646
|
+
Examples:
|
|
2647
|
+
deepline billing balance
|
|
2648
|
+
deepline billing balance --json
|
|
2649
|
+
`
|
|
2650
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleBalance);
|
|
2651
|
+
billing.command("usage").description("Show current usage plus recent calls.").addHelpText(
|
|
2652
|
+
"after",
|
|
2653
|
+
`
|
|
2654
|
+
Notes:
|
|
2655
|
+
Read-only. Shows last-30-day Deepline credit usage plus a bounded recent-call
|
|
2656
|
+
page. Use --limit/--offset to paginate the recent-call section.
|
|
2657
|
+
|
|
2658
|
+
Examples:
|
|
2659
|
+
deepline billing usage
|
|
2660
|
+
deepline billing usage --limit 50 --offset 50 --json
|
|
2661
|
+
`
|
|
2662
|
+
).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);
|
|
2663
|
+
billing.command("limit").description("Show configured monthly limit state.").addHelpText(
|
|
2664
|
+
"after",
|
|
2665
|
+
`
|
|
2666
|
+
Notes:
|
|
2667
|
+
Read-only. Shows whether the monthly workspace cap is enabled and how many
|
|
2668
|
+
Deepline credits remain before the cap.
|
|
2669
|
+
|
|
2670
|
+
Examples:
|
|
2671
|
+
deepline billing limit
|
|
2672
|
+
deepline billing limit --json
|
|
2673
|
+
`
|
|
2674
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLimit);
|
|
2675
|
+
billing.command("set-limit").description("Set monthly credit cap.").addHelpText(
|
|
2676
|
+
"after",
|
|
2677
|
+
`
|
|
2678
|
+
Notes:
|
|
2679
|
+
Mutates workspace billing settings. The argument is a Deepline credit amount,
|
|
2680
|
+
not dollars and not provider credits.
|
|
2681
|
+
|
|
2682
|
+
Examples:
|
|
2683
|
+
deepline billing set-limit 500
|
|
2684
|
+
deepline billing set-limit 500 --json
|
|
2685
|
+
`
|
|
2686
|
+
).argument("<credits>", "Monthly credits limit").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleSetLimit);
|
|
2687
|
+
billing.command("off").description("Disable monthly credit cap.").addHelpText(
|
|
2688
|
+
"after",
|
|
2689
|
+
`
|
|
2690
|
+
Notes:
|
|
2691
|
+
Mutates workspace billing settings by removing the monthly Deepline credit cap.
|
|
2692
|
+
|
|
2693
|
+
Examples:
|
|
2694
|
+
deepline billing off
|
|
2695
|
+
deepline billing off --json
|
|
2696
|
+
`
|
|
2697
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLimitOff);
|
|
2698
|
+
billing.command("ledger").description("Inspect and export billing ledger rows.").addHelpText(
|
|
2699
|
+
"after",
|
|
2700
|
+
`
|
|
2701
|
+
Notes:
|
|
2702
|
+
Read-only. Exports ledger rows for the current auth context. API-key auth is
|
|
2703
|
+
scoped by the server to that API key; session auth is scoped to the active
|
|
2704
|
+
workspace.
|
|
2705
|
+
|
|
2706
|
+
Examples:
|
|
2707
|
+
deepline billing ledger export all
|
|
2708
|
+
deepline billing ledger export all --output ./ledger.csv
|
|
2709
|
+
deepline billing ledger export all --json
|
|
2710
|
+
`
|
|
2711
|
+
).addCommand(
|
|
2712
|
+
new Command("export").description("Export billing ledger rows.").addHelpText(
|
|
2713
|
+
"after",
|
|
2714
|
+
`
|
|
2715
|
+
Examples:
|
|
2716
|
+
deepline billing ledger export all
|
|
2717
|
+
`
|
|
2718
|
+
).addCommand(
|
|
2719
|
+
new Command("all").description("Export all available billing ledger rows to CSV.").addHelpText(
|
|
2720
|
+
"after",
|
|
2721
|
+
`
|
|
2722
|
+
Notes:
|
|
2723
|
+
Pages through the ledger for the current auth context, writes CSV locally,
|
|
2724
|
+
then reports the row count and the net delta computed from delta_credits.
|
|
2725
|
+
|
|
2726
|
+
Examples:
|
|
2727
|
+
deepline billing ledger export all
|
|
2728
|
+
deepline billing ledger export all --json
|
|
2729
|
+
`
|
|
2730
|
+
).option("--output <path>", "Write CSV to an explicit path").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleLedgerExportAll)
|
|
2731
|
+
)
|
|
2732
|
+
);
|
|
2733
|
+
billing.command("history").description("Export billing ledger history to CSV.").addHelpText(
|
|
2734
|
+
"after",
|
|
2735
|
+
`
|
|
2736
|
+
Notes:
|
|
2737
|
+
Read-only server query that writes a local CSV file. With --json, stdout is a
|
|
2738
|
+
summary containing the output path and row count.
|
|
2739
|
+
|
|
2740
|
+
Examples:
|
|
2741
|
+
deepline billing history --time 1m
|
|
2742
|
+
deepline billing history --time 1y --json
|
|
2743
|
+
`
|
|
2744
|
+
).requiredOption("--time <window>", "Rolling time window: 1d, 1w, 1m, or 1y").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleHistory);
|
|
2745
|
+
billing.command("checkout").description("Create a checkout session and optionally open it in your browser.").addHelpText(
|
|
2746
|
+
"after",
|
|
2747
|
+
`
|
|
2748
|
+
Notes:
|
|
2749
|
+
Creates a payment checkout session. Opens the checkout URL in a browser unless
|
|
2750
|
+
--no-open is set. Use --json for automation.
|
|
2751
|
+
|
|
2752
|
+
Examples:
|
|
2753
|
+
deepline billing checkout --tier pro
|
|
2754
|
+
deepline billing checkout --credits 1000 --no-open --json
|
|
2755
|
+
deepline billing checkout --credits 1000 --discount-code LAUNCH --no-open
|
|
2756
|
+
`
|
|
2757
|
+
).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);
|
|
2758
|
+
billing.command("redeem-code").description("Redeem a billing code.").addHelpText(
|
|
2759
|
+
"after",
|
|
2760
|
+
`
|
|
2761
|
+
Notes:
|
|
2762
|
+
Redeems a workspace billing code and may open a browser for completion unless
|
|
2763
|
+
--no-open is set.
|
|
2764
|
+
|
|
2765
|
+
Examples:
|
|
2766
|
+
deepline billing redeem-code --code ABC123
|
|
2767
|
+
deepline billing redeem-code --code ABC123 --no-open --json
|
|
2768
|
+
`
|
|
2769
|
+
).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));
|
|
2507
2770
|
}
|
|
2508
2771
|
|
|
2509
2772
|
// src/cli/dataset-stats.ts
|
|
2510
2773
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
2511
|
-
import { resolve as
|
|
2774
|
+
import { resolve as resolve4 } from "path";
|
|
2512
2775
|
var CSV_PROJECTED_FIELDS_KEY = "__deeplineCsvProjectedFields";
|
|
2513
2776
|
function csvProjectedFields(row) {
|
|
2514
2777
|
const serialized = row[CSV_PROJECTED_FIELDS_KEY];
|
|
@@ -2838,7 +3101,7 @@ function writeCanonicalRowsCsv(rowsInfo, outPath) {
|
|
|
2838
3101
|
rows: rowsInfo.rows,
|
|
2839
3102
|
columns: rowsInfo.columns
|
|
2840
3103
|
});
|
|
2841
|
-
const resolved =
|
|
3104
|
+
const resolved = resolve4(outPath);
|
|
2842
3105
|
writeFileSync4(
|
|
2843
3106
|
resolved,
|
|
2844
3107
|
csvStringFromRows(sanitized.rows, sanitized.columns),
|
|
@@ -2934,8 +3197,31 @@ async function handleCsvShow(options) {
|
|
|
2934
3197
|
`);
|
|
2935
3198
|
}
|
|
2936
3199
|
function registerCsvCommands(program) {
|
|
2937
|
-
const csv = program.command("csv").description("Inspect local CSV files.")
|
|
2938
|
-
|
|
3200
|
+
const csv = program.command("csv").description("Inspect local CSV files.").addHelpText(
|
|
3201
|
+
"after",
|
|
3202
|
+
`
|
|
3203
|
+
Notes:
|
|
3204
|
+
Local-only inspection helpers. These commands do not upload CSV files or call
|
|
3205
|
+
Deepline APIs.
|
|
3206
|
+
|
|
3207
|
+
Examples:
|
|
3208
|
+
deepline csv show --csv leads.csv --rows 0:10 --format table
|
|
3209
|
+
deepline csv show --csv leads.csv --summary
|
|
3210
|
+
`
|
|
3211
|
+
);
|
|
3212
|
+
csv.command("show").description("Display rows from a CSV file in json, csv, or table form.").addHelpText(
|
|
3213
|
+
"after",
|
|
3214
|
+
`
|
|
3215
|
+
Notes:
|
|
3216
|
+
Reads a local CSV path and prints a bounded row range. --rows uses inclusive
|
|
3217
|
+
start:end indexes, so 0:19 prints the first 20 rows. JSON is the default format.
|
|
3218
|
+
|
|
3219
|
+
Examples:
|
|
3220
|
+
deepline csv show --csv leads.csv
|
|
3221
|
+
deepline csv show --csv leads.csv --rows 20:39 --columns name,email --format table
|
|
3222
|
+
deepline csv show --csv leads.csv --summary
|
|
3223
|
+
`
|
|
3224
|
+
).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);
|
|
2939
3225
|
}
|
|
2940
3226
|
|
|
2941
3227
|
// src/cli/commands/db.ts
|
|
@@ -3015,8 +3301,32 @@ async function handleDbQuery(args) {
|
|
|
3015
3301
|
return 0;
|
|
3016
3302
|
}
|
|
3017
3303
|
function registerDbCommands(program) {
|
|
3018
|
-
const db = program.command("db").alias("customer-db").description("Query the tenant customer database.")
|
|
3019
|
-
|
|
3304
|
+
const db = program.command("db").alias("customer-db").description("Query the tenant customer database.").addHelpText(
|
|
3305
|
+
"after",
|
|
3306
|
+
`
|
|
3307
|
+
Notes:
|
|
3308
|
+
Runs SQL against the active workspace customer database through Deepline APIs.
|
|
3309
|
+
Results are bounded by the server and --max-rows. Use --json for stable output.
|
|
3310
|
+
|
|
3311
|
+
Examples:
|
|
3312
|
+
deepline db query --sql "select * from companies limit 20"
|
|
3313
|
+
deepline db query --sql "select domain, name from companies limit 20" --json
|
|
3314
|
+
deepline db query --sql "select * from contacts" --max-rows 100 --json
|
|
3315
|
+
`
|
|
3316
|
+
);
|
|
3317
|
+
db.command("query").alias("psql").description("Run SQL against the tenant customer database.").addHelpText(
|
|
3318
|
+
"after",
|
|
3319
|
+
`
|
|
3320
|
+
Notes:
|
|
3321
|
+
Requires --sql. Output is a compact table in a terminal and raw JSON with
|
|
3322
|
+
--json or when stdout is piped. The active auth workspace determines scope.
|
|
3323
|
+
|
|
3324
|
+
Examples:
|
|
3325
|
+
deepline db query --sql "select * from companies limit 20"
|
|
3326
|
+
deepline db query --sql "select domain, name from companies limit 20" --json
|
|
3327
|
+
deepline db psql --sql "select count(*) from contacts" --json
|
|
3328
|
+
`
|
|
3329
|
+
).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) => {
|
|
3020
3330
|
process.exitCode = await handleDbQuery([
|
|
3021
3331
|
"--sql",
|
|
3022
3332
|
options.sql,
|
|
@@ -3042,9 +3352,29 @@ async function handleFeedback(text, options) {
|
|
|
3042
3352
|
process.stdout.write("Feedback submitted. Thank you.\n");
|
|
3043
3353
|
}
|
|
3044
3354
|
function registerFeedbackCommands(program) {
|
|
3045
|
-
const feedback = program.command("feedback").description("Submit CLI feedback to Deepline.")
|
|
3355
|
+
const feedback = program.command("feedback").description("Submit CLI feedback to Deepline.").addHelpText(
|
|
3356
|
+
"after",
|
|
3357
|
+
`
|
|
3358
|
+
Notes:
|
|
3359
|
+
Sends the feedback text plus local CLI environment info to Deepline support.
|
|
3360
|
+
Use --command and --payload to attach a reproducible command shape.
|
|
3361
|
+
|
|
3362
|
+
Examples:
|
|
3363
|
+
deepline feedback "plays run failed after upload" --command "deepline plays run my.play.ts --watch"
|
|
3364
|
+
deepline feedback "unexpected billing output" --payload '{"command":"billing usage"}' --json
|
|
3365
|
+
`
|
|
3366
|
+
);
|
|
3046
3367
|
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);
|
|
3047
|
-
program.command("provide-feedback").description("Legacy alias for `deepline feedback`.").
|
|
3368
|
+
program.command("provide-feedback").description("Legacy alias for `deepline feedback`.").addHelpText(
|
|
3369
|
+
"after",
|
|
3370
|
+
`
|
|
3371
|
+
Notes:
|
|
3372
|
+
Compatibility alias. Prefer deepline feedback in new scripts and docs.
|
|
3373
|
+
|
|
3374
|
+
Examples:
|
|
3375
|
+
deepline feedback "tools search returned stale results" --json
|
|
3376
|
+
`
|
|
3377
|
+
).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);
|
|
3048
3378
|
}
|
|
3049
3379
|
|
|
3050
3380
|
// src/cli/commands/org.ts
|
|
@@ -3124,9 +3454,43 @@ async function handleOrgSwitch(selection, options) {
|
|
|
3124
3454
|
`);
|
|
3125
3455
|
}
|
|
3126
3456
|
function registerOrgCommands(program) {
|
|
3127
|
-
const org = program.command("org").description("List and switch organizations.")
|
|
3128
|
-
|
|
3129
|
-
|
|
3457
|
+
const org = program.command("org").description("List and switch organizations.").addHelpText(
|
|
3458
|
+
"after",
|
|
3459
|
+
`
|
|
3460
|
+
Notes:
|
|
3461
|
+
Organizations are workspaces. Switching organizations mutates the saved host
|
|
3462
|
+
auth file so later CLI commands target the selected workspace.
|
|
3463
|
+
|
|
3464
|
+
Examples:
|
|
3465
|
+
deepline org list --json
|
|
3466
|
+
deepline org switch 2
|
|
3467
|
+
deepline org switch --org-id org_123 --json
|
|
3468
|
+
`
|
|
3469
|
+
);
|
|
3470
|
+
org.command("list").description("List your organizations.").addHelpText(
|
|
3471
|
+
"after",
|
|
3472
|
+
`
|
|
3473
|
+
Notes:
|
|
3474
|
+
Read-only. Marks the active organization when the server returns that metadata.
|
|
3475
|
+
|
|
3476
|
+
Examples:
|
|
3477
|
+
deepline org list
|
|
3478
|
+
deepline org list --json
|
|
3479
|
+
`
|
|
3480
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgList);
|
|
3481
|
+
org.command("switch [selection]").description("Switch to another organization and save the new API key in the host auth file.").addHelpText(
|
|
3482
|
+
"after",
|
|
3483
|
+
`
|
|
3484
|
+
Notes:
|
|
3485
|
+
Mutates the saved host auth file. Selection can be a list number, exact
|
|
3486
|
+
organization name, or organization id. Without a selection, prints choices.
|
|
3487
|
+
|
|
3488
|
+
Examples:
|
|
3489
|
+
deepline org switch
|
|
3490
|
+
deepline org switch 2
|
|
3491
|
+
deepline org switch --org-id org_123 --json
|
|
3492
|
+
`
|
|
3493
|
+
).option("--org-id <id>", "Switch using an explicit organization id").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleOrgSwitch);
|
|
3130
3494
|
}
|
|
3131
3495
|
|
|
3132
3496
|
// src/cli/commands/play.ts
|
|
@@ -3138,19 +3502,19 @@ import {
|
|
|
3138
3502
|
realpathSync,
|
|
3139
3503
|
writeFileSync as writeFileSync5
|
|
3140
3504
|
} from "fs";
|
|
3141
|
-
import { basename as basename3, dirname as
|
|
3505
|
+
import { basename as basename3, dirname as dirname8, join as join6, resolve as resolve8 } from "path";
|
|
3142
3506
|
|
|
3143
3507
|
// src/plays/bundle-play-file.ts
|
|
3144
3508
|
import { tmpdir as tmpdir2 } from "os";
|
|
3145
|
-
import { dirname as
|
|
3509
|
+
import { dirname as dirname7, join as join5, resolve as resolve7 } from "path";
|
|
3146
3510
|
import { fileURLToPath } from "url";
|
|
3147
3511
|
import { existsSync as existsSync4 } from "fs";
|
|
3148
3512
|
|
|
3149
3513
|
// ../shared_libs/plays/bundling/index.ts
|
|
3150
3514
|
import { createHash } from "crypto";
|
|
3151
|
-
import { mkdir as
|
|
3515
|
+
import { mkdir as mkdir3, readFile, realpath, stat, writeFile as writeFile3 } from "fs/promises";
|
|
3152
3516
|
import { tmpdir } from "os";
|
|
3153
|
-
import { basename, dirname as
|
|
3517
|
+
import { basename, dirname as dirname5, extname, isAbsolute, join as join3, resolve as resolve5 } from "path";
|
|
3154
3518
|
import { builtinModules, createRequire } from "module";
|
|
3155
3519
|
import { build } from "esbuild";
|
|
3156
3520
|
|
|
@@ -3243,13 +3607,13 @@ async function normalizeLocalPath(filePath) {
|
|
|
3243
3607
|
try {
|
|
3244
3608
|
return await realpath(filePath);
|
|
3245
3609
|
} catch {
|
|
3246
|
-
return
|
|
3610
|
+
return resolve5(filePath);
|
|
3247
3611
|
}
|
|
3248
3612
|
}
|
|
3249
3613
|
function createPlayWorkspace(entryFile) {
|
|
3250
3614
|
return {
|
|
3251
3615
|
entryFile,
|
|
3252
|
-
rootDir:
|
|
3616
|
+
rootDir: dirname5(entryFile)
|
|
3253
3617
|
};
|
|
3254
3618
|
}
|
|
3255
3619
|
function isPathInsideDirectory(filePath, directory) {
|
|
@@ -3450,7 +3814,7 @@ function workersNamedPlayEntryAliasPlugin(playFilePath, exportName) {
|
|
|
3450
3814
|
contents: `export { ${exportName} as default } from ${JSON.stringify(playFilePath)};
|
|
3451
3815
|
`,
|
|
3452
3816
|
loader: "ts",
|
|
3453
|
-
resolveDir:
|
|
3817
|
+
resolveDir: dirname5(playFilePath)
|
|
3454
3818
|
})
|
|
3455
3819
|
);
|
|
3456
3820
|
}
|
|
@@ -3614,7 +3978,7 @@ function importedPlayProxyPlugin(importedPlayDependencies) {
|
|
|
3614
3978
|
return {
|
|
3615
3979
|
contents: buildImportedPlayProxyModule(dependency.playName),
|
|
3616
3980
|
loader: "ts",
|
|
3617
|
-
resolveDir:
|
|
3981
|
+
resolveDir: dirname5(args.path)
|
|
3618
3982
|
};
|
|
3619
3983
|
});
|
|
3620
3984
|
}
|
|
@@ -3632,7 +3996,7 @@ async function resolveLocalImport(fromFile, specifier) {
|
|
|
3632
3996
|
if (specifier.startsWith("file:")) {
|
|
3633
3997
|
return normalizeLocalPath(new URL(specifier).pathname);
|
|
3634
3998
|
}
|
|
3635
|
-
const base = isAbsolute(specifier) ?
|
|
3999
|
+
const base = isAbsolute(specifier) ? resolve5(specifier) : resolve5(dirname5(fromFile), specifier);
|
|
3636
4000
|
const candidates = [base];
|
|
3637
4001
|
const explicitExtension = extname(base).toLowerCase();
|
|
3638
4002
|
if (!explicitExtension) {
|
|
@@ -3833,8 +4197,8 @@ async function readArtifactCache(graphHash, artifactKind, adapter) {
|
|
|
3833
4197
|
}
|
|
3834
4198
|
async function writeArtifactCache(artifact, adapter) {
|
|
3835
4199
|
const cacheDir = adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR;
|
|
3836
|
-
await
|
|
3837
|
-
await
|
|
4200
|
+
await mkdir3(cacheDir, { recursive: true });
|
|
4201
|
+
await writeFile3(
|
|
3838
4202
|
artifactCachePath(
|
|
3839
4203
|
artifact.graphHash,
|
|
3840
4204
|
artifact.artifactKind ?? PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
@@ -3850,7 +4214,7 @@ function normalizeSourceMapForRuntime(sourceMapText) {
|
|
|
3850
4214
|
if (sourcePath.startsWith("data:") || sourcePath.startsWith("node:") || sourcePath.startsWith("/") || /^[a-zA-Z]+:\/\//.test(sourcePath)) {
|
|
3851
4215
|
return sourcePath;
|
|
3852
4216
|
}
|
|
3853
|
-
return
|
|
4217
|
+
return resolve5(process.cwd(), sourcePath);
|
|
3854
4218
|
});
|
|
3855
4219
|
parsed.sourceRoot = void 0;
|
|
3856
4220
|
return JSON.stringify(parsed);
|
|
@@ -3882,7 +4246,7 @@ async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter
|
|
|
3882
4246
|
...namedExportShim ? {
|
|
3883
4247
|
stdin: {
|
|
3884
4248
|
contents: namedExportShim,
|
|
3885
|
-
resolveDir:
|
|
4249
|
+
resolveDir: dirname5(entryFile),
|
|
3886
4250
|
sourcefile: `${basename(entryFile)}.${exportName}.entry.ts`,
|
|
3887
4251
|
loader: "ts"
|
|
3888
4252
|
}
|
|
@@ -4172,7 +4536,7 @@ function resolveExecutionProfile(override) {
|
|
|
4172
4536
|
// src/plays/local-file-discovery.ts
|
|
4173
4537
|
import { createHash as createHash2 } from "crypto";
|
|
4174
4538
|
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
4175
|
-
import { basename as basename2, dirname as
|
|
4539
|
+
import { basename as basename2, dirname as dirname6, extname as extname2, isAbsolute as isAbsolute2, join as join4, relative, resolve as resolve6 } from "path";
|
|
4176
4540
|
var SOURCE_EXTENSIONS2 = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs", ".json"];
|
|
4177
4541
|
function sha2562(buffer) {
|
|
4178
4542
|
return createHash2("sha256").update(buffer).digest("hex");
|
|
@@ -4373,7 +4737,7 @@ function isPathInsideDirectory2(filePath, directory) {
|
|
|
4373
4737
|
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute2(relativePath);
|
|
4374
4738
|
}
|
|
4375
4739
|
async function resolveLocalImport2(fromFile, specifier) {
|
|
4376
|
-
const base = isAbsolute2(specifier) ?
|
|
4740
|
+
const base = isAbsolute2(specifier) ? resolve6(specifier) : resolve6(dirname6(fromFile), specifier);
|
|
4377
4741
|
const candidates = [base];
|
|
4378
4742
|
const explicitExtension = extname2(base).toLowerCase();
|
|
4379
4743
|
if (!explicitExtension) {
|
|
@@ -4391,13 +4755,13 @@ async function resolveLocalImport2(fromFile, specifier) {
|
|
|
4391
4755
|
throw new Error(`Could not resolve local import "${specifier}" from ${fromFile}`);
|
|
4392
4756
|
}
|
|
4393
4757
|
async function discoverPackagedLocalFiles(entryFile) {
|
|
4394
|
-
const absoluteEntryFile =
|
|
4395
|
-
const packagingRoot =
|
|
4758
|
+
const absoluteEntryFile = resolve6(entryFile);
|
|
4759
|
+
const packagingRoot = dirname6(absoluteEntryFile);
|
|
4396
4760
|
const files = /* @__PURE__ */ new Map();
|
|
4397
4761
|
const unresolved = [];
|
|
4398
4762
|
const visitedFiles = /* @__PURE__ */ new Set();
|
|
4399
4763
|
const visitSourceFile = async (filePath) => {
|
|
4400
|
-
const absolutePath =
|
|
4764
|
+
const absolutePath = resolve6(filePath);
|
|
4401
4765
|
if (visitedFiles.has(absolutePath)) {
|
|
4402
4766
|
return;
|
|
4403
4767
|
}
|
|
@@ -4429,7 +4793,7 @@ async function discoverPackagedLocalFiles(entryFile) {
|
|
|
4429
4793
|
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."
|
|
4430
4794
|
});
|
|
4431
4795
|
} else {
|
|
4432
|
-
const absoluteCsvPath =
|
|
4796
|
+
const absoluteCsvPath = resolve6(dirname6(absolutePath), resolvedPath);
|
|
4433
4797
|
if (isAbsolute2(resolvedPath) || !isPathInsideDirectory2(absoluteCsvPath, packagingRoot)) {
|
|
4434
4798
|
unresolved.push({
|
|
4435
4799
|
sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
|
|
@@ -4468,24 +4832,24 @@ async function discoverPackagedLocalFiles(entryFile) {
|
|
|
4468
4832
|
|
|
4469
4833
|
// src/plays/bundle-play-file.ts
|
|
4470
4834
|
var PLAY_BUNDLE_CACHE_VERSION2 = 26;
|
|
4471
|
-
var MODULE_DIR =
|
|
4472
|
-
var SDK_PACKAGE_ROOT =
|
|
4473
|
-
var SOURCE_REPO_ROOT =
|
|
4835
|
+
var MODULE_DIR = dirname7(fileURLToPath(import.meta.url));
|
|
4836
|
+
var SDK_PACKAGE_ROOT = resolve7(MODULE_DIR, "..", "..");
|
|
4837
|
+
var SOURCE_REPO_ROOT = resolve7(SDK_PACKAGE_ROOT, "..");
|
|
4474
4838
|
var HAS_SOURCE_BUNDLING_SOURCES = existsSync4(
|
|
4475
|
-
|
|
4839
|
+
resolve7(SOURCE_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
|
|
4476
4840
|
);
|
|
4477
|
-
var PACKAGED_REPO_ROOT =
|
|
4841
|
+
var PACKAGED_REPO_ROOT = resolve7(SDK_PACKAGE_ROOT, "dist", "repo");
|
|
4478
4842
|
var HAS_PACKAGED_BUNDLING_SOURCES = existsSync4(
|
|
4479
|
-
|
|
4843
|
+
resolve7(PACKAGED_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
|
|
4480
4844
|
);
|
|
4481
|
-
var PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? SOURCE_REPO_ROOT : HAS_PACKAGED_BUNDLING_SOURCES ? PACKAGED_REPO_ROOT :
|
|
4482
|
-
var SDK_SOURCE_ROOT = HAS_SOURCE_BUNDLING_SOURCES ?
|
|
4483
|
-
var SDK_PACKAGE_JSON =
|
|
4484
|
-
var SDK_ENTRY_FILE =
|
|
4485
|
-
var SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE :
|
|
4486
|
-
var SDK_WORKERS_ENTRY_FILE =
|
|
4487
|
-
var WORKERS_HARNESS_ENTRY_FILE =
|
|
4488
|
-
var WORKERS_HARNESS_FILES_DIR =
|
|
4845
|
+
var PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? SOURCE_REPO_ROOT : HAS_PACKAGED_BUNDLING_SOURCES ? PACKAGED_REPO_ROOT : resolve7(SDK_PACKAGE_ROOT, "..");
|
|
4846
|
+
var SDK_SOURCE_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? resolve7(SOURCE_REPO_ROOT, "sdk", "src") : HAS_PACKAGED_BUNDLING_SOURCES ? resolve7(PACKAGED_REPO_ROOT, "sdk", "src") : resolve7(SDK_PACKAGE_ROOT, "src");
|
|
4847
|
+
var SDK_PACKAGE_JSON = resolve7(SDK_PACKAGE_ROOT, "package.json");
|
|
4848
|
+
var SDK_ENTRY_FILE = resolve7(SDK_SOURCE_ROOT, "index.ts");
|
|
4849
|
+
var SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : resolve7(SDK_PACKAGE_ROOT, "dist", "index.d.ts");
|
|
4850
|
+
var SDK_WORKERS_ENTRY_FILE = resolve7(SDK_SOURCE_ROOT, "worker-play-entry.ts");
|
|
4851
|
+
var WORKERS_HARNESS_ENTRY_FILE = resolve7(PROJECT_ROOT, "apps", "play-runner-workers", "src", "entry.ts");
|
|
4852
|
+
var WORKERS_HARNESS_FILES_DIR = resolve7(PROJECT_ROOT, "apps", "play-runner-workers", "src");
|
|
4489
4853
|
var hasWarnedAboutNonDevelopmentBundling = false;
|
|
4490
4854
|
function warnAboutNonDevelopmentBundling(filePath) {
|
|
4491
4855
|
if (hasWarnedAboutNonDevelopmentBundling) {
|
|
@@ -4509,7 +4873,7 @@ function defaultPlayBundleTarget() {
|
|
|
4509
4873
|
function createSdkPlayBundlingAdapter() {
|
|
4510
4874
|
return {
|
|
4511
4875
|
projectRoot: PROJECT_ROOT,
|
|
4512
|
-
nodeModulesDir:
|
|
4876
|
+
nodeModulesDir: resolve7(PROJECT_ROOT, "node_modules"),
|
|
4513
4877
|
cacheDir: join5(tmpdir2(), `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`),
|
|
4514
4878
|
sdkSourceRoot: SDK_SOURCE_ROOT,
|
|
4515
4879
|
sdkPackageJson: SDK_PACKAGE_JSON,
|
|
@@ -4790,7 +5154,7 @@ function formatPlayListReference(play) {
|
|
|
4790
5154
|
function defaultMaterializedPlayPath(reference) {
|
|
4791
5155
|
const playName = parseReferencedPlayTarget(reference).unqualifiedPlayName;
|
|
4792
5156
|
const safeName = playName.trim().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
4793
|
-
return
|
|
5157
|
+
return resolve8(`${safeName || "play"}.play.ts`);
|
|
4794
5158
|
}
|
|
4795
5159
|
function materializeRemotePlaySource(input) {
|
|
4796
5160
|
if (isFileTarget(input.target)) {
|
|
@@ -4853,7 +5217,7 @@ function extractPlayName(code, filePath) {
|
|
|
4853
5217
|
throw buildMissingDefinePlayError(filePath);
|
|
4854
5218
|
}
|
|
4855
5219
|
function isFileTarget(target) {
|
|
4856
|
-
return existsSync5(
|
|
5220
|
+
return existsSync5(resolve8(target));
|
|
4857
5221
|
}
|
|
4858
5222
|
function looksLikeFilePath(target) {
|
|
4859
5223
|
if (target.trim().toLowerCase().startsWith("prebuilt/")) {
|
|
@@ -4872,7 +5236,7 @@ function parsePositiveInteger2(value, flagName) {
|
|
|
4872
5236
|
return parsed;
|
|
4873
5237
|
}
|
|
4874
5238
|
function parseJsonInput(raw) {
|
|
4875
|
-
const source = raw.startsWith("@") ? readFileSync3(
|
|
5239
|
+
const source = raw.startsWith("@") ? readFileSync3(resolve8(raw.slice(1)), "utf-8") : raw;
|
|
4876
5240
|
const parsed = JSON.parse(source);
|
|
4877
5241
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4878
5242
|
throw new Error("--input must be a JSON object.");
|
|
@@ -4982,7 +5346,7 @@ function applyCsvShortcutInput(input) {
|
|
|
4982
5346
|
function isLocalFilePathValue(value) {
|
|
4983
5347
|
if (typeof value !== "string" || !value.trim()) return false;
|
|
4984
5348
|
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
|
|
4985
|
-
return existsSync5(
|
|
5349
|
+
return existsSync5(resolve8(value));
|
|
4986
5350
|
}
|
|
4987
5351
|
function inputContainsLocalFilePath(value) {
|
|
4988
5352
|
if (isLocalFilePathValue(value)) {
|
|
@@ -5008,7 +5372,7 @@ async function stageFileInputArgs(input) {
|
|
|
5008
5372
|
const localFiles = uniqueBindings.flatMap((binding) => {
|
|
5009
5373
|
const value = getDottedInputValue(input.runtimeInput, binding.inputPath);
|
|
5010
5374
|
if (!isLocalFilePathValue(value)) return [];
|
|
5011
|
-
const absolutePath =
|
|
5375
|
+
const absolutePath = resolve8(value);
|
|
5012
5376
|
return [{ binding, absolutePath, logicalPath: basename3(absolutePath) }];
|
|
5013
5377
|
});
|
|
5014
5378
|
if (localFiles.length === 0) {
|
|
@@ -5044,9 +5408,9 @@ function stageFile(logicalPath, absolutePath) {
|
|
|
5044
5408
|
}
|
|
5045
5409
|
function normalizePlayPath(filePath) {
|
|
5046
5410
|
try {
|
|
5047
|
-
return realpathSync.native(
|
|
5411
|
+
return realpathSync.native(resolve8(filePath));
|
|
5048
5412
|
} catch {
|
|
5049
|
-
return
|
|
5413
|
+
return resolve8(filePath);
|
|
5050
5414
|
}
|
|
5051
5415
|
}
|
|
5052
5416
|
function formatBundlingErrors(filePath, errors) {
|
|
@@ -6072,7 +6436,7 @@ function parsePlayRunOptions(args) {
|
|
|
6072
6436
|
let input = null;
|
|
6073
6437
|
let revisionId = null;
|
|
6074
6438
|
let revisionSelector = null;
|
|
6075
|
-
const watch = args.includes("--watch");
|
|
6439
|
+
const watch = args.includes("--watch") || args.includes("--wait");
|
|
6076
6440
|
let jsonOutput = watch ? args.includes("--json") : argsWantJson(args);
|
|
6077
6441
|
const emitLogs = !jsonOutput || args.includes("--logs");
|
|
6078
6442
|
const force = args.includes("--force");
|
|
@@ -6106,7 +6470,7 @@ function parsePlayRunOptions(args) {
|
|
|
6106
6470
|
continue;
|
|
6107
6471
|
}
|
|
6108
6472
|
if (arg === "--out" && args[index + 1]) {
|
|
6109
|
-
outPath =
|
|
6473
|
+
outPath = resolve8(args[++index]);
|
|
6110
6474
|
continue;
|
|
6111
6475
|
}
|
|
6112
6476
|
if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
|
|
@@ -6122,15 +6486,13 @@ function parsePlayRunOptions(args) {
|
|
|
6122
6486
|
if (arg === "--watch") {
|
|
6123
6487
|
continue;
|
|
6124
6488
|
}
|
|
6489
|
+
if (arg === "--wait") {
|
|
6490
|
+
continue;
|
|
6491
|
+
}
|
|
6125
6492
|
if (arg === "--json") {
|
|
6126
6493
|
jsonOutput = true;
|
|
6127
6494
|
continue;
|
|
6128
6495
|
}
|
|
6129
|
-
if (arg === "--wait") {
|
|
6130
|
-
throw new Error(
|
|
6131
|
-
"--wait is removed for `plays run`; use `--watch` to stream completion output."
|
|
6132
|
-
);
|
|
6133
|
-
}
|
|
6134
6496
|
if (arg === "--tail") {
|
|
6135
6497
|
throw new Error(
|
|
6136
6498
|
"--tail is removed for `plays run`; use `--watch` to stream completion output."
|
|
@@ -6208,11 +6570,11 @@ function shouldUseLocalOnlyPlayCheck() {
|
|
|
6208
6570
|
async function handlePlayCheck(args) {
|
|
6209
6571
|
const options = parsePlayCheckOptions(args);
|
|
6210
6572
|
if (!isFileTarget(options.target)) {
|
|
6211
|
-
const resolved =
|
|
6573
|
+
const resolved = resolve8(options.target);
|
|
6212
6574
|
console.error(`File not found: ${resolved}`);
|
|
6213
6575
|
return 1;
|
|
6214
6576
|
}
|
|
6215
|
-
const absolutePlayPath =
|
|
6577
|
+
const absolutePlayPath = resolve8(options.target);
|
|
6216
6578
|
const sourceCode = readFileSync3(absolutePlayPath, "utf-8");
|
|
6217
6579
|
let graph;
|
|
6218
6580
|
try {
|
|
@@ -6276,7 +6638,7 @@ async function handleFileBackedRun(options) {
|
|
|
6276
6638
|
}
|
|
6277
6639
|
const client = new DeeplineClient();
|
|
6278
6640
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
6279
|
-
const absolutePlayPath =
|
|
6641
|
+
const absolutePlayPath = resolve8(options.target.path);
|
|
6280
6642
|
progress.phase("compiling play");
|
|
6281
6643
|
const sourceCode = traceCliSync(
|
|
6282
6644
|
"cli.play_file_read_source",
|
|
@@ -6565,9 +6927,9 @@ async function handlePlayRun(args) {
|
|
|
6565
6927
|
if (isFileTarget(options.target.path)) {
|
|
6566
6928
|
return handleFileBackedRun(options);
|
|
6567
6929
|
}
|
|
6568
|
-
const resolved =
|
|
6930
|
+
const resolved = resolve8(options.target.path);
|
|
6569
6931
|
console.error(`File not found: ${resolved}`);
|
|
6570
|
-
const dir =
|
|
6932
|
+
const dir = dirname8(resolved);
|
|
6571
6933
|
if (existsSync5(dir)) {
|
|
6572
6934
|
const base = basename3(resolved);
|
|
6573
6935
|
try {
|
|
@@ -6723,7 +7085,7 @@ async function handleRunLogs(args) {
|
|
|
6723
7085
|
continue;
|
|
6724
7086
|
}
|
|
6725
7087
|
if (arg === "--out" && args[index + 1]) {
|
|
6726
|
-
outPath =
|
|
7088
|
+
outPath = resolve8(args[++index]);
|
|
6727
7089
|
}
|
|
6728
7090
|
}
|
|
6729
7091
|
const client = new DeeplineClient();
|
|
@@ -6810,7 +7172,7 @@ async function handleRunExport(args) {
|
|
|
6810
7172
|
for (let index = 0; index < args.length; index += 1) {
|
|
6811
7173
|
const arg = args[index];
|
|
6812
7174
|
if (arg === "--out" && args[index + 1]) {
|
|
6813
|
-
outPath =
|
|
7175
|
+
outPath = resolve8(args[++index]);
|
|
6814
7176
|
}
|
|
6815
7177
|
}
|
|
6816
7178
|
if (!outPath) {
|
|
@@ -6850,10 +7212,10 @@ async function handlePlayGet(args) {
|
|
|
6850
7212
|
for (let index = 1; index < args.length; index += 1) {
|
|
6851
7213
|
const arg = args[index];
|
|
6852
7214
|
if (arg === "--out" && args[index + 1]) {
|
|
6853
|
-
outPath =
|
|
7215
|
+
outPath = resolve8(args[++index]);
|
|
6854
7216
|
}
|
|
6855
7217
|
}
|
|
6856
|
-
const playName = isFileTarget(target) ? extractPlayName(readFileSync3(
|
|
7218
|
+
const playName = isFileTarget(target) ? extractPlayName(readFileSync3(resolve8(target), "utf-8"), resolve8(target)) : parseReferencedPlayTarget(target).playName;
|
|
6857
7219
|
const detail = isFileTarget(target) ? await client.getPlay(playName) : await assertCanonicalNamedPlayReference(client, target);
|
|
6858
7220
|
const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
|
|
6859
7221
|
const materializedFile = outPath ? materializeRemotePlaySource({
|
|
@@ -7145,7 +7507,7 @@ async function handlePlayPublish(args) {
|
|
|
7145
7507
|
}
|
|
7146
7508
|
let graph;
|
|
7147
7509
|
try {
|
|
7148
|
-
graph = await collectBundledPlayGraph(
|
|
7510
|
+
graph = await collectBundledPlayGraph(resolve8(playName));
|
|
7149
7511
|
await compileBundledPlayGraphManifests(client, graph);
|
|
7150
7512
|
await publishImportedPlayDependencies(client, graph);
|
|
7151
7513
|
} catch (error) {
|
|
@@ -7245,12 +7607,15 @@ Concepts:
|
|
|
7245
7607
|
Plays are durable cloud workflows.
|
|
7246
7608
|
Stable ctx.tools.execute({ id, tool, input }) calls are replay-safe.
|
|
7247
7609
|
ctx.map adds row keys and row progress.
|
|
7610
|
+
Named play runs use the live revision unless --latest or --revision-id is set.
|
|
7611
|
+
Running a local file does not make it live; use set-live/publish explicitly.
|
|
7248
7612
|
|
|
7249
7613
|
Common commands:
|
|
7250
7614
|
deepline plays search email --json
|
|
7251
7615
|
deepline plays describe person-linkedin-to-email --json
|
|
7252
7616
|
deepline plays check my.play.ts
|
|
7253
7617
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
|
|
7618
|
+
deepline plays set-live my.play.ts --json
|
|
7254
7619
|
deepline plays get person-linkedin-to-email --json
|
|
7255
7620
|
`
|
|
7256
7621
|
);
|
|
@@ -7280,9 +7645,11 @@ Notes:
|
|
|
7280
7645
|
Unknown --foo and --foo.bar flags are treated as play input args.
|
|
7281
7646
|
File args accept local paths; the CLI stages files before submit.
|
|
7282
7647
|
--watch prints logs, previews, stats, and next commands.
|
|
7648
|
+
--wait is accepted as a compatibility alias for --watch.
|
|
7283
7649
|
The play page opens in your browser as soon as the run starts; use --no-open
|
|
7284
7650
|
to only print the URL.
|
|
7285
7651
|
--force supersedes active runs; it does not bypass completed reuse.
|
|
7652
|
+
This command starts cloud work and may spend Deepline credits through tool calls.
|
|
7286
7653
|
|
|
7287
7654
|
Idempotent execution:
|
|
7288
7655
|
Stable tool call ids are the reuse key:
|
|
@@ -7307,6 +7674,7 @@ Idempotent execution:
|
|
|
7307
7674
|
|
|
7308
7675
|
Examples:
|
|
7309
7676
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
|
|
7677
|
+
deepline plays run my.play.ts --input @input.json --wait --json
|
|
7310
7678
|
deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}' --watch
|
|
7311
7679
|
deepline plays run enrich.play.ts --csv leads.csv --watch --out leads-enriched.csv
|
|
7312
7680
|
deepline plays run cto-search.play.ts --limit 5 --watch
|
|
@@ -7318,7 +7686,7 @@ Examples:
|
|
|
7318
7686
|
).option(
|
|
7319
7687
|
"--out <path>",
|
|
7320
7688
|
"Write the completed row output to CSV; requires --watch"
|
|
7321
|
-
).option("--watch", "Stream logs until completion").option(
|
|
7689
|
+
).option("--watch", "Stream logs until completion").option("--wait", "Alias for --watch; stream logs until completion").option(
|
|
7322
7690
|
"--logs",
|
|
7323
7691
|
"When output is non-interactive, stream play logs to stderr while waiting"
|
|
7324
7692
|
).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) => {
|
|
@@ -7341,7 +7709,7 @@ Examples:
|
|
|
7341
7709
|
...options.latest ? ["--latest"] : [],
|
|
7342
7710
|
...options.revisionId ? ["--revision-id", options.revisionId] : [],
|
|
7343
7711
|
...options.out ? ["--out", options.out] : [],
|
|
7344
|
-
...options.watch ? ["--watch"] : [],
|
|
7712
|
+
...options.watch || options.wait ? ["--watch"] : [],
|
|
7345
7713
|
...options.logs ? ["--logs"] : [],
|
|
7346
7714
|
...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
|
|
7347
7715
|
...options.force ? ["--force"] : [],
|
|
@@ -7372,12 +7740,36 @@ Examples:
|
|
|
7372
7740
|
...options.out ? ["--out", options.out] : []
|
|
7373
7741
|
]);
|
|
7374
7742
|
});
|
|
7375
|
-
play.command("list").description("List saved and prebuilt plays.").
|
|
7743
|
+
play.command("list").description("List saved and prebuilt plays.").addHelpText(
|
|
7744
|
+
"after",
|
|
7745
|
+
`
|
|
7746
|
+
Notes:
|
|
7747
|
+
Inventory command for saved org plays and prebuilt plays. Use search for
|
|
7748
|
+
ranked discovery by task or schema.
|
|
7749
|
+
|
|
7750
|
+
Examples:
|
|
7751
|
+
deepline plays list
|
|
7752
|
+
deepline plays list --json
|
|
7753
|
+
deepline plays search email --origin prebuilt --json
|
|
7754
|
+
`
|
|
7755
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
7376
7756
|
process.exitCode = await handlePlayList([
|
|
7377
7757
|
...options.json ? ["--json"] : []
|
|
7378
7758
|
]);
|
|
7379
7759
|
});
|
|
7380
|
-
play.command("search <query>").description("Search saved and prebuilt plays.").
|
|
7760
|
+
play.command("search <query>").description("Search saved and prebuilt plays.").addHelpText(
|
|
7761
|
+
"after",
|
|
7762
|
+
`
|
|
7763
|
+
Notes:
|
|
7764
|
+
Ranked discovery for workflows. Use --origin prebuilt or --origin owned when
|
|
7765
|
+
you need to narrow results. Use describe on a result before running it.
|
|
7766
|
+
|
|
7767
|
+
Examples:
|
|
7768
|
+
deepline plays search email
|
|
7769
|
+
deepline plays search "linkedin to email" --origin prebuilt --compact --json
|
|
7770
|
+
deepline plays describe person-linkedin-to-email --json
|
|
7771
|
+
`
|
|
7772
|
+
).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) => {
|
|
7381
7773
|
process.exitCode = await handlePlaySearch([
|
|
7382
7774
|
query,
|
|
7383
7775
|
...options.origin ? ["--origin", options.origin] : [],
|
|
@@ -7403,13 +7795,53 @@ Examples:
|
|
|
7403
7795
|
...options.json ? ["--json"] : []
|
|
7404
7796
|
]);
|
|
7405
7797
|
});
|
|
7406
|
-
play.command("versions").description("List revisions for a named play.").
|
|
7798
|
+
play.command("versions").description("List revisions for a named play.").addHelpText(
|
|
7799
|
+
"after",
|
|
7800
|
+
`
|
|
7801
|
+
Notes:
|
|
7802
|
+
Shows saved revisions for an org-owned play, including which revision is live
|
|
7803
|
+
when that metadata is available. Named runs use the live revision by default.
|
|
7804
|
+
|
|
7805
|
+
Examples:
|
|
7806
|
+
deepline plays versions --name my-play
|
|
7807
|
+
deepline plays versions --name my-play --json
|
|
7808
|
+
deepline plays run my-play --revision-id <revision-id> --watch
|
|
7809
|
+
`
|
|
7810
|
+
).option("--name <name>", "Saved play name").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
7407
7811
|
process.exitCode = await handlePlayVersions([
|
|
7408
7812
|
...options.name ? ["--name", options.name] : [],
|
|
7409
7813
|
...options.json ? ["--json"] : []
|
|
7410
7814
|
]);
|
|
7411
7815
|
});
|
|
7412
|
-
|
|
7816
|
+
const addPublishHelp = (command) => command.addHelpText(
|
|
7817
|
+
"after",
|
|
7818
|
+
`
|
|
7819
|
+
Notes:
|
|
7820
|
+
Mutates cloud state. For a local file, this bundles, validates, saves a new
|
|
7821
|
+
revision, and promotes that revision live. For a saved play, --latest or
|
|
7822
|
+
--revision-id promotes an existing saved revision live.
|
|
7823
|
+
Running a local file with plays run does not publish it.
|
|
7824
|
+
|
|
7825
|
+
Examples:
|
|
7826
|
+
deepline plays set-live my.play.ts --json
|
|
7827
|
+
deepline plays set-live my-play --latest --json
|
|
7828
|
+
deepline plays set-live my-play --revision-id <revision-id> --json
|
|
7829
|
+
deepline plays publish my.play.ts --json
|
|
7830
|
+
`
|
|
7831
|
+
);
|
|
7832
|
+
addPublishHelp(
|
|
7833
|
+
play.command("publish <target>").description("Bundle, validate, save, and promote a play revision live.")
|
|
7834
|
+
).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) => {
|
|
7835
|
+
process.exitCode = await handlePlayPublish([
|
|
7836
|
+
target,
|
|
7837
|
+
...options.latest ? ["--latest"] : [],
|
|
7838
|
+
...options.revisionId ? ["--revision-id", options.revisionId] : [],
|
|
7839
|
+
...options.json ? ["--json"] : []
|
|
7840
|
+
]);
|
|
7841
|
+
});
|
|
7842
|
+
addPublishHelp(
|
|
7843
|
+
play.command("set-live <target>").description("Promote a local file or saved revision as the live play revision.")
|
|
7844
|
+
).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) => {
|
|
7413
7845
|
process.exitCode = await handlePlayPublish([
|
|
7414
7846
|
target,
|
|
7415
7847
|
...options.latest ? ["--latest"] : [],
|
|
@@ -7417,7 +7849,18 @@ Examples:
|
|
|
7417
7849
|
...options.json ? ["--json"] : []
|
|
7418
7850
|
]);
|
|
7419
7851
|
});
|
|
7420
|
-
play.command("delete <target>").description("Delete an org-owned play and its saved revisions/runs.").
|
|
7852
|
+
play.command("delete <target>").description("Delete an org-owned play and its saved revisions/runs.").addHelpText(
|
|
7853
|
+
"after",
|
|
7854
|
+
`
|
|
7855
|
+
Notes:
|
|
7856
|
+
Destructive mutation. Deletes an org-owned play plus saved revisions and run
|
|
7857
|
+
records. Prebuilt/read-only plays are refused. Use --yes for noninteractive runs.
|
|
7858
|
+
|
|
7859
|
+
Examples:
|
|
7860
|
+
deepline plays delete my-play
|
|
7861
|
+
deepline plays delete my-play --yes --json
|
|
7862
|
+
`
|
|
7863
|
+
).option("-y, --yes", "Confirm deletion").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
7421
7864
|
process.exitCode = await handlePlayDelete([
|
|
7422
7865
|
target,
|
|
7423
7866
|
...options.yes ? ["--yes"] : [],
|
|
@@ -7427,6 +7870,12 @@ Examples:
|
|
|
7427
7870
|
const runs = program.command("runs").description("Inspect, tail, stop, and export play runs.").addHelpText(
|
|
7428
7871
|
"after",
|
|
7429
7872
|
`
|
|
7873
|
+
Concepts:
|
|
7874
|
+
A run is one execution instance of a play. It has status, progress, logs,
|
|
7875
|
+
preview output, recovery metadata, and optional full row export.
|
|
7876
|
+
tail reads the live stream. logs fetches persisted logs after the fact.
|
|
7877
|
+
stop mutates cloud state by requesting cancellation.
|
|
7878
|
+
|
|
7430
7879
|
Examples:
|
|
7431
7880
|
deepline runs get play/my-play/run/20260501t000000-000 --json
|
|
7432
7881
|
deepline runs tail play/my-play/run/20260501t000000-000
|
|
@@ -7436,14 +7885,36 @@ Examples:
|
|
|
7436
7885
|
deepline runs export play/my-play/run/20260501t000000-000 --out output.csv
|
|
7437
7886
|
`
|
|
7438
7887
|
);
|
|
7439
|
-
runs.command("get <runId>").description("Get status, progress, outputs, errors, and recovery metadata for a play run.").
|
|
7888
|
+
runs.command("get <runId>").description("Get status, progress, outputs, errors, and recovery metadata for a play run.").addHelpText(
|
|
7889
|
+
"after",
|
|
7890
|
+
`
|
|
7891
|
+
Notes:
|
|
7892
|
+
Full run status read. Use --full --json when debugging raw stream/status fields.
|
|
7893
|
+
|
|
7894
|
+
Examples:
|
|
7895
|
+
deepline runs get play/my-play/run/20260501t000000-000
|
|
7896
|
+
deepline runs get play/my-play/run/20260501t000000-000 --json
|
|
7897
|
+
deepline runs get play/my-play/run/20260501t000000-000 --full --json
|
|
7898
|
+
`
|
|
7899
|
+
).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) => {
|
|
7440
7900
|
process.exitCode = await handleRunGet([
|
|
7441
7901
|
runId,
|
|
7442
7902
|
...options.json ? ["--json"] : [],
|
|
7443
7903
|
...options.full ? ["--full"] : []
|
|
7444
7904
|
]);
|
|
7445
7905
|
});
|
|
7446
|
-
runs.command("list").description("List play runs.").
|
|
7906
|
+
runs.command("list").description("List play runs.").addHelpText(
|
|
7907
|
+
"after",
|
|
7908
|
+
`
|
|
7909
|
+
Notes:
|
|
7910
|
+
Bounded inventory for a play's recent runs. Use --compact for agent loops.
|
|
7911
|
+
Common statuses include running, completed, failed, and stopped.
|
|
7912
|
+
|
|
7913
|
+
Examples:
|
|
7914
|
+
deepline runs list --play my-play
|
|
7915
|
+
deepline runs list --play my-play --status failed --compact --json
|
|
7916
|
+
`
|
|
7917
|
+
).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) => {
|
|
7447
7918
|
process.exitCode = await handleRunsList([
|
|
7448
7919
|
"--play",
|
|
7449
7920
|
options.play,
|
|
@@ -7452,14 +7923,37 @@ Examples:
|
|
|
7452
7923
|
...options.json ? ["--json"] : []
|
|
7453
7924
|
]);
|
|
7454
7925
|
});
|
|
7455
|
-
runs.command("tail <runId>").description("Read the canonical live stream for a play run.").
|
|
7926
|
+
runs.command("tail <runId>").description("Read the canonical live stream for a play run.").addHelpText(
|
|
7927
|
+
"after",
|
|
7928
|
+
`
|
|
7929
|
+
Notes:
|
|
7930
|
+
Streams live run events until the stream ends. Use get for current status and
|
|
7931
|
+
logs for persisted log history.
|
|
7932
|
+
|
|
7933
|
+
Examples:
|
|
7934
|
+
deepline runs tail play/my-play/run/20260501t000000-000
|
|
7935
|
+
deepline runs tail play/my-play/run/20260501t000000-000 --compact --json
|
|
7936
|
+
`
|
|
7937
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--compact", "Drop verbose fields from JSON output").action(async (runId, options) => {
|
|
7456
7938
|
process.exitCode = await handleRunTail([
|
|
7457
7939
|
runId,
|
|
7458
7940
|
...options.json ? ["--json"] : [],
|
|
7459
7941
|
...options.compact ? ["--compact"] : []
|
|
7460
7942
|
]);
|
|
7461
7943
|
});
|
|
7462
|
-
runs.command("logs <runId>").description("Fetch persisted logs for a play run.").
|
|
7944
|
+
runs.command("logs <runId>").description("Fetch persisted logs for a play run.").addHelpText(
|
|
7945
|
+
"after",
|
|
7946
|
+
`
|
|
7947
|
+
Notes:
|
|
7948
|
+
Prints a bounded recent log preview by default. Use --out to write the full
|
|
7949
|
+
persisted log stream to a local file.
|
|
7950
|
+
|
|
7951
|
+
Examples:
|
|
7952
|
+
deepline runs logs play/my-play/run/20260501t000000-000
|
|
7953
|
+
deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
|
|
7954
|
+
deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
|
|
7955
|
+
`
|
|
7956
|
+
).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) => {
|
|
7463
7957
|
process.exitCode = await handleRunLogs([
|
|
7464
7958
|
runId,
|
|
7465
7959
|
...options.limit ? ["--limit", options.limit] : [],
|
|
@@ -7467,14 +7961,36 @@ Examples:
|
|
|
7467
7961
|
...options.json ? ["--json"] : []
|
|
7468
7962
|
]);
|
|
7469
7963
|
});
|
|
7470
|
-
runs.command("stop <runId>").description("Stop a play run.").
|
|
7964
|
+
runs.command("stop <runId>").description("Stop a play run.").addHelpText(
|
|
7965
|
+
"after",
|
|
7966
|
+
`
|
|
7967
|
+
Notes:
|
|
7968
|
+
Mutates cloud state by requesting cancellation for an active run. Already
|
|
7969
|
+
terminal runs are returned as no-ops by the server when applicable.
|
|
7970
|
+
|
|
7971
|
+
Examples:
|
|
7972
|
+
deepline runs stop play/my-play/run/20260501t000000-000 --reason "stale lock"
|
|
7973
|
+
deepline runs stop play/my-play/run/20260501t000000-000 --json
|
|
7974
|
+
`
|
|
7975
|
+
).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) => {
|
|
7471
7976
|
process.exitCode = await handleRunStop([
|
|
7472
7977
|
runId,
|
|
7473
7978
|
...options.reason ? ["--reason", options.reason] : [],
|
|
7474
7979
|
...options.json ? ["--json"] : []
|
|
7475
7980
|
]);
|
|
7476
7981
|
});
|
|
7477
|
-
runs.command("export <runId>").description("Export the completed row output for a play run to CSV.").
|
|
7982
|
+
runs.command("export <runId>").description("Export the completed row output for a play run to CSV.").addHelpText(
|
|
7983
|
+
"after",
|
|
7984
|
+
`
|
|
7985
|
+
Notes:
|
|
7986
|
+
Writes the completed row output to the requested local CSV path. Use runs get
|
|
7987
|
+
first when you need to confirm the run is complete or inspect preview output.
|
|
7988
|
+
|
|
7989
|
+
Examples:
|
|
7990
|
+
deepline runs export play/my-play/run/20260501t000000-000 --out output.csv
|
|
7991
|
+
deepline runs export play/my-play/run/20260501t000000-000 --out output.csv --json
|
|
7992
|
+
`
|
|
7993
|
+
).requiredOption("--out <path>", "Output CSV path").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
|
|
7478
7994
|
process.exitCode = await handleRunExport([
|
|
7479
7995
|
runId,
|
|
7480
7996
|
"--out",
|
|
@@ -7718,16 +8234,44 @@ Concepts:
|
|
|
7718
8234
|
|
|
7719
8235
|
Common commands:
|
|
7720
8236
|
deepline tools search email --json
|
|
7721
|
-
deepline tools
|
|
8237
|
+
deepline tools describe hunter_email_verifier --json
|
|
7722
8238
|
deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
8239
|
+
|
|
8240
|
+
Output:
|
|
8241
|
+
Search/list output is bounded. Use describe for a compact contract and get for
|
|
8242
|
+
the full machine-readable metadata available for the tool.
|
|
7723
8243
|
`
|
|
7724
8244
|
);
|
|
7725
|
-
tools.command("list").description("List available tools.").
|
|
8245
|
+
tools.command("list").description("List available tools.").addHelpText(
|
|
8246
|
+
"after",
|
|
8247
|
+
`
|
|
8248
|
+
Notes:
|
|
8249
|
+
Inventory command for known tool ids. Use search for ranked discovery by
|
|
8250
|
+
intent, aliases, descriptions, and schema fields.
|
|
8251
|
+
|
|
8252
|
+
Examples:
|
|
8253
|
+
deepline tools list
|
|
8254
|
+
deepline tools list --json
|
|
8255
|
+
deepline tools search email --json
|
|
8256
|
+
`
|
|
8257
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
|
|
7726
8258
|
process.exitCode = await listTools([
|
|
7727
8259
|
...options.json ? ["--json"] : []
|
|
7728
8260
|
]);
|
|
7729
8261
|
});
|
|
7730
|
-
tools.command("search <query>").description("Search available tools.").
|
|
8262
|
+
tools.command("search <query>").description("Search available tools.").addHelpText(
|
|
8263
|
+
"after",
|
|
8264
|
+
`
|
|
8265
|
+
Notes:
|
|
8266
|
+
Ranked discovery for atomic provider/API operations. Results include tool ids
|
|
8267
|
+
that can be passed to deepline tools describe or deepline tools call.
|
|
8268
|
+
|
|
8269
|
+
Examples:
|
|
8270
|
+
deepline tools search email
|
|
8271
|
+
deepline tools search "company enrichment" --categories enrichment --json
|
|
8272
|
+
deepline tools search verifier --search-mode v2 --json
|
|
8273
|
+
`
|
|
8274
|
+
).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) => {
|
|
7731
8275
|
process.exitCode = await searchTools(query, {
|
|
7732
8276
|
json: options.json,
|
|
7733
8277
|
categories: options.categories,
|
|
@@ -7736,15 +8280,18 @@ Common commands:
|
|
|
7736
8280
|
includeSearchDebug: Boolean(options.includeSearchDebug)
|
|
7737
8281
|
});
|
|
7738
8282
|
});
|
|
7739
|
-
|
|
8283
|
+
const addToolMetadataCommand = (command, preferredExample) => command.description("Show metadata for a tool.").addHelpText(
|
|
7740
8284
|
"after",
|
|
7741
8285
|
`
|
|
7742
8286
|
Notes:
|
|
7743
|
-
Shows the tool contract, input schema, output schema,
|
|
8287
|
+
Shows the tool contract, input schema, output schema, Deepline cost, aliases,
|
|
8288
|
+
and metadata. describe is the preferred discovery verb; get is kept as a
|
|
8289
|
+
compatibility command for the same metadata surface.
|
|
7744
8290
|
|
|
7745
8291
|
Examples:
|
|
7746
|
-
deepline tools
|
|
7747
|
-
deepline tools
|
|
8292
|
+
deepline tools ${preferredExample} hunter_email_verifier
|
|
8293
|
+
deepline tools ${preferredExample} hunter_email_verifier --json | jq '.inputSchema'
|
|
8294
|
+
deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
7748
8295
|
`
|
|
7749
8296
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (toolId, options) => {
|
|
7750
8297
|
process.exitCode = await getTool([
|
|
@@ -7752,12 +8299,16 @@ Examples:
|
|
|
7752
8299
|
...options.json ? ["--json"] : []
|
|
7753
8300
|
]);
|
|
7754
8301
|
});
|
|
8302
|
+
addToolMetadataCommand(tools.command("describe <toolId>"), "describe");
|
|
8303
|
+
addToolMetadataCommand(tools.command("get <toolId>"), "get");
|
|
7755
8304
|
tools.command("call <toolId>").alias("execute").alias("run").description("Execute a tool by id.").addHelpText(
|
|
7756
8305
|
"after",
|
|
7757
8306
|
`
|
|
7758
8307
|
Notes:
|
|
7759
8308
|
Use tools for one atomic provider/API operation. Use plays for composed workflows,
|
|
7760
8309
|
waterfalls, row maps, checkpoints, and retries.
|
|
8310
|
+
Calling a provider-backed tool can spend Deepline credits. Use --json for the
|
|
8311
|
+
stable result payload and --full-output when debugging response metadata.
|
|
7761
8312
|
|
|
7762
8313
|
Examples:
|
|
7763
8314
|
deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
@@ -8249,7 +8800,7 @@ async function executeTool(args) {
|
|
|
8249
8800
|
import { spawn, spawnSync as spawnSync2 } from "child_process";
|
|
8250
8801
|
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync8 } from "fs";
|
|
8251
8802
|
import { homedir as homedir4 } from "os";
|
|
8252
|
-
import { dirname as
|
|
8803
|
+
import { dirname as dirname9, join as join9 } from "path";
|
|
8253
8804
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
8254
8805
|
var SDK_SKILL_NAME = "deepline-sdk";
|
|
8255
8806
|
var SKILL_AGENTS = ["codex", "claude-code", "cursor"];
|
|
@@ -8273,7 +8824,7 @@ function readLocalSkillsVersion(baseUrl) {
|
|
|
8273
8824
|
}
|
|
8274
8825
|
function writeLocalSkillsVersion(baseUrl, version) {
|
|
8275
8826
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
8276
|
-
mkdirSync5(
|
|
8827
|
+
mkdirSync5(dirname9(path), { recursive: true });
|
|
8277
8828
|
writeFileSync8(path, `${version}
|
|
8278
8829
|
`, "utf-8");
|
|
8279
8830
|
}
|
|
@@ -8368,7 +8919,7 @@ function resolveSkillsInstallCommands(baseUrl) {
|
|
|
8368
8919
|
return [npxInstall];
|
|
8369
8920
|
}
|
|
8370
8921
|
function runOneSkillsInstall(install) {
|
|
8371
|
-
return new Promise((
|
|
8922
|
+
return new Promise((resolve9) => {
|
|
8372
8923
|
const child = spawn(install.command, install.args, {
|
|
8373
8924
|
stdio: ["ignore", "ignore", "pipe"],
|
|
8374
8925
|
env: process.env
|
|
@@ -8378,7 +8929,7 @@ function runOneSkillsInstall(install) {
|
|
|
8378
8929
|
stderr += chunk.toString("utf-8");
|
|
8379
8930
|
});
|
|
8380
8931
|
child.on("error", (error) => {
|
|
8381
|
-
|
|
8932
|
+
resolve9({
|
|
8382
8933
|
ok: false,
|
|
8383
8934
|
detail: `failed to start ${install.command}: ${error.message}`,
|
|
8384
8935
|
manualCommand: install.manualCommand
|
|
@@ -8386,11 +8937,11 @@ function runOneSkillsInstall(install) {
|
|
|
8386
8937
|
});
|
|
8387
8938
|
child.on("close", (code) => {
|
|
8388
8939
|
if (code === 0) {
|
|
8389
|
-
|
|
8940
|
+
resolve9({ ok: true, detail: "", manualCommand: install.manualCommand });
|
|
8390
8941
|
return;
|
|
8391
8942
|
}
|
|
8392
8943
|
const detail = stderr.trim();
|
|
8393
|
-
|
|
8944
|
+
resolve9({
|
|
8394
8945
|
ok: false,
|
|
8395
8946
|
detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
|
|
8396
8947
|
manualCommand: install.manualCommand
|
|
@@ -8443,6 +8994,9 @@ function shouldPrintStartupPhase() {
|
|
|
8443
8994
|
return false;
|
|
8444
8995
|
}
|
|
8445
8996
|
const args = process.argv.slice(2);
|
|
8997
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
8998
|
+
return false;
|
|
8999
|
+
}
|
|
8446
9000
|
const command = args[0];
|
|
8447
9001
|
const subcommand = args[1];
|
|
8448
9002
|
return (command === "play" || command === "plays") && subcommand === "run";
|
|
@@ -8464,7 +9018,7 @@ async function main() {
|
|
|
8464
9018
|
if (printStartupPhase) {
|
|
8465
9019
|
progress?.phase("loading deepline cli");
|
|
8466
9020
|
}
|
|
8467
|
-
const program = new
|
|
9021
|
+
const program = new Command2();
|
|
8468
9022
|
program.name("deepline").description("Deepline CLI (TypeScript SDK)").version(SDK_VERSION, "-v, --version", "Show version").showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
8469
9023
|
"after",
|
|
8470
9024
|
`
|
|
@@ -8476,9 +9030,23 @@ Common commands:
|
|
|
8476
9030
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
|
|
8477
9031
|
deepline tools call hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
8478
9032
|
|
|
9033
|
+
Product model:
|
|
9034
|
+
Tools are atomic provider/API operations that may spend credits.
|
|
9035
|
+
Plays are durable workflows backed by source code or saved cloud revisions.
|
|
9036
|
+
Runs are execution instances with logs, status, outputs, and cancellation.
|
|
9037
|
+
Live plays are promoted revisions used by named play runs.
|
|
9038
|
+
|
|
8479
9039
|
Output:
|
|
8480
9040
|
Structured commands print human-readable output in a terminal and JSON when stdout is piped.
|
|
8481
9041
|
Use --json to force JSON in an interactive terminal.
|
|
9042
|
+
|
|
9043
|
+
Safety:
|
|
9044
|
+
Commands that mutate state, open a browser, write files, stop work, or spend credits say so in their help.
|
|
9045
|
+
Use --no-open where available for CI and agent runs.
|
|
9046
|
+
|
|
9047
|
+
Exit codes:
|
|
9048
|
+
0 success; 2 usage/local input error; 3 auth/permission error; 4 not found;
|
|
9049
|
+
5 server/runtime/provider failure; 7 validation/check failed.
|
|
8482
9050
|
`
|
|
8483
9051
|
);
|
|
8484
9052
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
@@ -8513,7 +9081,17 @@ Output:
|
|
|
8513
9081
|
registerCsvCommands(program);
|
|
8514
9082
|
registerDbCommands(program);
|
|
8515
9083
|
registerFeedbackCommands(program);
|
|
8516
|
-
program.command("health").description("Check server health.").
|
|
9084
|
+
program.command("health").description("Check server health.").addHelpText(
|
|
9085
|
+
"after",
|
|
9086
|
+
`
|
|
9087
|
+
Notes:
|
|
9088
|
+
Read-only connectivity check for the configured Deepline host. Prints the raw
|
|
9089
|
+
server health payload as JSON.
|
|
9090
|
+
|
|
9091
|
+
Examples:
|
|
9092
|
+
deepline health
|
|
9093
|
+
`
|
|
9094
|
+
).action(async () => {
|
|
8517
9095
|
try {
|
|
8518
9096
|
const client = new DeeplineClient();
|
|
8519
9097
|
const data = await client.health();
|
|
@@ -8525,7 +9103,18 @@ Output:
|
|
|
8525
9103
|
);
|
|
8526
9104
|
}
|
|
8527
9105
|
});
|
|
8528
|
-
program.command("version").description("Show version.").
|
|
9106
|
+
program.command("version").description("Show version.").addHelpText(
|
|
9107
|
+
"after",
|
|
9108
|
+
`
|
|
9109
|
+
Notes:
|
|
9110
|
+
Prints the SDK CLI package version. The top-level -v/--version flag returns
|
|
9111
|
+
the same version.
|
|
9112
|
+
|
|
9113
|
+
Examples:
|
|
9114
|
+
deepline version
|
|
9115
|
+
deepline --version
|
|
9116
|
+
`
|
|
9117
|
+
).action(() => {
|
|
8529
9118
|
process.stdout.write(`deepline ${SDK_VERSION}
|
|
8530
9119
|
`);
|
|
8531
9120
|
});
|