deepline 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cli/index.js +509 -353
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +513 -358
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +250 -305
- package/dist/index.d.ts +250 -305
- package/dist/index.js +174 -286
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -285
- package/dist/index.mjs.map +1 -1
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +23 -13
- package/dist/repo/apps/play-runner-workers/src/entry.ts +581 -1220
- package/dist/repo/sdk/src/cli/commands/play.ts +381 -247
- package/dist/repo/sdk/src/cli/commands/tools.ts +1 -1
- package/dist/repo/sdk/src/cli/dataset-stats.ts +86 -12
- package/dist/repo/sdk/src/client.ts +54 -51
- package/dist/repo/sdk/src/index.ts +7 -16
- package/dist/repo/sdk/src/play.ts +122 -135
- package/dist/repo/sdk/src/plays/bundle-play-file.ts +6 -3
- package/dist/repo/sdk/src/tool-output.ts +0 -111
- package/dist/repo/sdk/src/types.ts +2 -0
- package/dist/repo/sdk/src/version.ts +1 -1
- package/dist/repo/sdk/src/worker-play-entry.ts +3 -0
- package/dist/repo/shared_libs/play-runtime/context.ts +510 -267
- package/dist/repo/shared_libs/play-runtime/csv-rename.ts +180 -0
- package/dist/repo/shared_libs/play-runtime/ctx-types.ts +13 -1
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +139 -114
- package/dist/repo/shared_libs/plays/bundling/index.ts +68 -5
- package/dist/repo/shared_libs/plays/compiler-manifest.ts +1 -1
- package/dist/repo/shared_libs/plays/dataset.ts +1 -1
- package/dist/repo/shared_libs/plays/runtime-validation.ts +8 -28
- package/package.json +1 -1
- package/dist/repo/apps/play-runner-workers/src/runtime/tool-result.ts +0 -184
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
|
|
4
|
+
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/config.ts
|
|
7
7
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
|
|
@@ -169,7 +169,7 @@ function resolveConfig(options) {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// src/version.ts
|
|
172
|
-
var SDK_VERSION = "0.1.
|
|
172
|
+
var SDK_VERSION = "0.1.12";
|
|
173
173
|
var SDK_API_CONTRACT = "2026-04-plays-v1";
|
|
174
174
|
|
|
175
175
|
// ../shared_libs/play-runtime/coordinator-headers.ts
|
|
@@ -444,6 +444,9 @@ function sleep(ms) {
|
|
|
444
444
|
|
|
445
445
|
// src/client.ts
|
|
446
446
|
var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
447
|
+
function isRecord(value) {
|
|
448
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
449
|
+
}
|
|
447
450
|
function normalizePlayStatus(raw) {
|
|
448
451
|
const status = typeof raw.status === "string" ? raw.status : typeof raw.temporalStatus === "string" ? mapLegacyTemporalStatus(raw.temporalStatus) : "running";
|
|
449
452
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : "";
|
|
@@ -496,12 +499,27 @@ var DeeplineClient = class {
|
|
|
496
499
|
).filter((field) => Boolean(field?.name)) : [];
|
|
497
500
|
return fields.length > 0 ? { fields } : schema;
|
|
498
501
|
}
|
|
499
|
-
|
|
500
|
-
|
|
502
|
+
schemaMetadata(schema, key) {
|
|
503
|
+
if (!isRecord(schema)) return null;
|
|
504
|
+
const value = schema[key];
|
|
505
|
+
return isRecord(value) ? value : null;
|
|
506
|
+
}
|
|
507
|
+
playRunCommand(play, options) {
|
|
508
|
+
const target = play.reference || play.name;
|
|
509
|
+
if (options?.csvInput) {
|
|
510
|
+
const inputField = typeof options.csvInput.inputField === "string" && options.csvInput.inputField.trim() ? options.csvInput.inputField.trim() : "csv";
|
|
511
|
+
return `deepline plays run ${target} --${inputField} leads.csv --watch`;
|
|
512
|
+
}
|
|
513
|
+
return `deepline plays run ${target} --input '{...}' --watch`;
|
|
501
514
|
}
|
|
502
515
|
summarizePlayListItem(play, options) {
|
|
503
516
|
const aliases = play.aliases?.length ? play.aliases : [play.name];
|
|
504
|
-
const
|
|
517
|
+
const csvInput = this.schemaMetadata(play.inputSchema, "csvInput");
|
|
518
|
+
const rowOutputSchema = this.schemaMetadata(
|
|
519
|
+
play.outputSchema,
|
|
520
|
+
"rowOutputSchema"
|
|
521
|
+
);
|
|
522
|
+
const runCommand = this.playRunCommand(play, { csvInput });
|
|
505
523
|
return {
|
|
506
524
|
name: play.name,
|
|
507
525
|
...play.reference ? { reference: play.reference } : {},
|
|
@@ -513,6 +531,8 @@ var DeeplineClient = class {
|
|
|
513
531
|
aliases,
|
|
514
532
|
inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
|
|
515
533
|
outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
|
|
534
|
+
...csvInput ? { csvInput } : {},
|
|
535
|
+
...rowOutputSchema ? { rowOutputSchema } : {},
|
|
516
536
|
runCommand,
|
|
517
537
|
examples: [runCommand],
|
|
518
538
|
currentPublishedVersion: play.currentPublishedVersion ?? null,
|
|
@@ -579,50 +599,14 @@ var DeeplineClient = class {
|
|
|
579
599
|
);
|
|
580
600
|
}
|
|
581
601
|
/**
|
|
582
|
-
* Execute a tool and return the
|
|
602
|
+
* Execute a tool and return the standard execution envelope.
|
|
583
603
|
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
* @param toolId - Tool identifier (e.g. `"test_company_search"`)
|
|
589
|
-
* @param input - Tool-specific input parameters
|
|
590
|
-
* @returns The tool's output (shape varies by tool)
|
|
591
|
-
* @throws {@link DeeplineError} if the tool execution fails
|
|
592
|
-
*
|
|
593
|
-
* @example
|
|
594
|
-
* ```typescript
|
|
595
|
-
* const company = await client.executeTool('test_company_search', {
|
|
596
|
-
* domain: 'stripe.com',
|
|
597
|
-
* });
|
|
598
|
-
* console.log(company); // { name: "Stripe", industry: "Financial Services", ... }
|
|
599
|
-
* ```
|
|
604
|
+
* The `result.data` field contains the provider payload. `result.meta`
|
|
605
|
+
* contains provider/upstream metadata such as HTTP status or paging details.
|
|
606
|
+
* Top-level fields such as `status`, `job_id`, and `billing` describe the
|
|
607
|
+
* Deepline execution.
|
|
600
608
|
*/
|
|
601
609
|
async executeTool(toolId, input) {
|
|
602
|
-
const res = await this.http.post(
|
|
603
|
-
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
604
|
-
{ payload: input }
|
|
605
|
-
);
|
|
606
|
-
return res.result ?? res;
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Execute a tool and return the full response envelope.
|
|
610
|
-
*
|
|
611
|
-
* Unlike {@link executeTool}, this returns the complete API response including
|
|
612
|
-
* `job_id`, `status`, `credits`, and the raw `result` object.
|
|
613
|
-
*
|
|
614
|
-
* @param toolId - Tool identifier
|
|
615
|
-
* @param input - Tool-specific input parameters
|
|
616
|
-
* @returns Full response with job metadata and result
|
|
617
|
-
*
|
|
618
|
-
* @example
|
|
619
|
-
* ```typescript
|
|
620
|
-
* const raw = await client.executeToolRaw('test_company_search', { domain: 'stripe.com' });
|
|
621
|
-
* console.log(`Job: ${raw.job_id}, Credits: ${raw.credits}`);
|
|
622
|
-
* console.log(`Result:`, raw.result);
|
|
623
|
-
* ```
|
|
624
|
-
*/
|
|
625
|
-
async executeToolRaw(toolId, input) {
|
|
626
610
|
return this.http.post(
|
|
627
611
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
628
612
|
{ payload: input }
|
|
@@ -1953,18 +1937,61 @@ function registerBillingCommands(program) {
|
|
|
1953
1937
|
// src/cli/dataset-stats.ts
|
|
1954
1938
|
import { writeFileSync as writeFileSync3 } from "fs";
|
|
1955
1939
|
import { resolve as resolve3 } from "path";
|
|
1956
|
-
|
|
1940
|
+
var CSV_PROJECTED_FIELDS_KEY = "__deeplineCsvProjectedFields";
|
|
1941
|
+
function csvProjectedFields(row) {
|
|
1942
|
+
const serialized = row[CSV_PROJECTED_FIELDS_KEY];
|
|
1943
|
+
if (!Array.isArray(serialized)) {
|
|
1944
|
+
return /* @__PURE__ */ new Set();
|
|
1945
|
+
}
|
|
1946
|
+
return new Set(
|
|
1947
|
+
serialized.filter((field) => typeof field === "string")
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
function stripCsvProjectionFields(row) {
|
|
1951
|
+
const projectedFields = csvProjectedFields(row);
|
|
1952
|
+
if (projectedFields.size === 0 && !(CSV_PROJECTED_FIELDS_KEY in row)) {
|
|
1953
|
+
return row;
|
|
1954
|
+
}
|
|
1955
|
+
const stripped = { ...row };
|
|
1956
|
+
for (const field of projectedFields) {
|
|
1957
|
+
delete stripped[field];
|
|
1958
|
+
}
|
|
1959
|
+
delete stripped[CSV_PROJECTED_FIELDS_KEY];
|
|
1960
|
+
return stripped;
|
|
1961
|
+
}
|
|
1962
|
+
function stripCsvProjectionColumns(columns, rows) {
|
|
1963
|
+
const projectedFields = /* @__PURE__ */ new Set();
|
|
1964
|
+
let hasProjectionMetadata = false;
|
|
1965
|
+
for (const row of rows) {
|
|
1966
|
+
for (const field of csvProjectedFields(row)) {
|
|
1967
|
+
projectedFields.add(field);
|
|
1968
|
+
}
|
|
1969
|
+
hasProjectionMetadata ||= CSV_PROJECTED_FIELDS_KEY in row;
|
|
1970
|
+
}
|
|
1971
|
+
if (!hasProjectionMetadata && projectedFields.size === 0) {
|
|
1972
|
+
return columns;
|
|
1973
|
+
}
|
|
1974
|
+
return columns.filter(
|
|
1975
|
+
(column) => column !== CSV_PROJECTED_FIELDS_KEY && !projectedFields.has(column)
|
|
1976
|
+
);
|
|
1977
|
+
}
|
|
1978
|
+
function sanitizeCsvProjectionInfo(input) {
|
|
1979
|
+
const columns = stripCsvProjectionColumns(input.columns, input.rows);
|
|
1980
|
+
const rows = input.rows.map(stripCsvProjectionFields);
|
|
1981
|
+
return { rows, columns };
|
|
1982
|
+
}
|
|
1983
|
+
function isRecord2(value) {
|
|
1957
1984
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1958
1985
|
}
|
|
1959
1986
|
function isSerializedDataset(value) {
|
|
1960
|
-
return
|
|
1987
|
+
return isRecord2(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
|
|
1961
1988
|
}
|
|
1962
1989
|
function rowArray(value) {
|
|
1963
1990
|
if (!Array.isArray(value)) {
|
|
1964
1991
|
return null;
|
|
1965
1992
|
}
|
|
1966
1993
|
const rows = value.filter(
|
|
1967
|
-
(row) =>
|
|
1994
|
+
(row) => isRecord2(row)
|
|
1968
1995
|
);
|
|
1969
1996
|
return rows.length === value.length ? rows : null;
|
|
1970
1997
|
}
|
|
@@ -1988,12 +2015,12 @@ function inferColumns(rows) {
|
|
|
1988
2015
|
return columns;
|
|
1989
2016
|
}
|
|
1990
2017
|
function extractCanonicalRowsInfo(statusOrResult) {
|
|
1991
|
-
const root =
|
|
1992
|
-
const result =
|
|
2018
|
+
const root = isRecord2(statusOrResult) ? statusOrResult : null;
|
|
2019
|
+
const result = isRecord2(root?.result) ? root.result : root;
|
|
1993
2020
|
if (!result) {
|
|
1994
2021
|
return null;
|
|
1995
2022
|
}
|
|
1996
|
-
const metadata =
|
|
2023
|
+
const metadata = isRecord2(result._metadata) ? result._metadata : null;
|
|
1997
2024
|
const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
|
|
1998
2025
|
const candidates = [
|
|
1999
2026
|
{ source: "result.contacts", value: result.contacts, total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count },
|
|
@@ -2001,8 +2028,8 @@ function extractCanonicalRowsInfo(statusOrResult) {
|
|
|
2001
2028
|
{ source: "result.rows", value: result.rows, total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count },
|
|
2002
2029
|
{ source: "result.results", value: result.results, total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count }
|
|
2003
2030
|
];
|
|
2004
|
-
if (
|
|
2005
|
-
const outputMetadata =
|
|
2031
|
+
if (isRecord2(result.output)) {
|
|
2032
|
+
const outputMetadata = isRecord2(result.output._metadata) ? result.output._metadata : null;
|
|
2006
2033
|
const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
|
|
2007
2034
|
candidates.push(
|
|
2008
2035
|
{ source: "result.output.contacts", value: result.output.contacts, total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count },
|
|
@@ -2013,12 +2040,17 @@ function extractCanonicalRowsInfo(statusOrResult) {
|
|
|
2013
2040
|
}
|
|
2014
2041
|
for (const candidate of candidates) {
|
|
2015
2042
|
if (isSerializedDataset(candidate.value)) {
|
|
2016
|
-
const
|
|
2017
|
-
const totalRows2 = readNumber(candidate.value.count) ??
|
|
2043
|
+
const rawRows = rowArray(candidate.value.preview) ?? [];
|
|
2044
|
+
const totalRows2 = readNumber(candidate.value.count) ?? rawRows.length;
|
|
2045
|
+
const rawColumns = Array.isArray(candidate.value.columns) && candidate.value.columns.every((column) => typeof column === "string") ? candidate.value.columns : inferColumns(rawRows);
|
|
2046
|
+
const { rows: rows2, columns } = sanitizeCsvProjectionInfo({
|
|
2047
|
+
rows: rawRows,
|
|
2048
|
+
columns: rawColumns
|
|
2049
|
+
});
|
|
2018
2050
|
return {
|
|
2019
2051
|
rows: rows2,
|
|
2020
2052
|
totalRows: totalRows2,
|
|
2021
|
-
columns
|
|
2053
|
+
columns,
|
|
2022
2054
|
complete: rows2.length === totalRows2,
|
|
2023
2055
|
source: candidate.source
|
|
2024
2056
|
};
|
|
@@ -2028,10 +2060,14 @@ function extractCanonicalRowsInfo(statusOrResult) {
|
|
|
2028
2060
|
continue;
|
|
2029
2061
|
}
|
|
2030
2062
|
const totalRows = readNumber(candidate.total) ?? rows.length;
|
|
2031
|
-
|
|
2063
|
+
const sanitized = sanitizeCsvProjectionInfo({
|
|
2032
2064
|
rows,
|
|
2065
|
+
columns: inferColumns(rows)
|
|
2066
|
+
});
|
|
2067
|
+
return {
|
|
2068
|
+
rows: sanitized.rows,
|
|
2033
2069
|
totalRows,
|
|
2034
|
-
columns:
|
|
2070
|
+
columns: sanitized.columns,
|
|
2035
2071
|
complete: rows.length === totalRows,
|
|
2036
2072
|
source: candidate.source
|
|
2037
2073
|
};
|
|
@@ -2079,13 +2115,13 @@ function summarizeSampleValue(value, depth = 0) {
|
|
|
2079
2115
|
if (typeof parsed === "number" || typeof parsed === "boolean") return parsed;
|
|
2080
2116
|
if (depth >= 3) {
|
|
2081
2117
|
if (Array.isArray(parsed)) return [];
|
|
2082
|
-
if (
|
|
2118
|
+
if (isRecord2(parsed)) return {};
|
|
2083
2119
|
return compactScalar(parsed);
|
|
2084
2120
|
}
|
|
2085
2121
|
if (Array.isArray(parsed)) {
|
|
2086
2122
|
return parsed.slice(0, 3).map((item) => summarizeSampleValue(item, depth + 1));
|
|
2087
2123
|
}
|
|
2088
|
-
if (
|
|
2124
|
+
if (isRecord2(parsed)) {
|
|
2089
2125
|
const out = {};
|
|
2090
2126
|
for (const [key, nested] of Object.entries(parsed)) {
|
|
2091
2127
|
if (["__dl", "meta", "metadata"].includes(key)) {
|
|
@@ -2115,7 +2151,7 @@ function compactCell(value) {
|
|
|
2115
2151
|
}
|
|
2116
2152
|
return `[${parsed.length} items]`;
|
|
2117
2153
|
}
|
|
2118
|
-
if (
|
|
2154
|
+
if (isRecord2(parsed)) {
|
|
2119
2155
|
for (const key of ["matched_result", "output"]) {
|
|
2120
2156
|
if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
|
|
2121
2157
|
return compactCell(parsed[key]);
|
|
@@ -2134,14 +2170,15 @@ function compactCell(value) {
|
|
|
2134
2170
|
return compactScalar(parsed, 120);
|
|
2135
2171
|
}
|
|
2136
2172
|
function buildDatasetStats(rows, totalRows = rows.length, columns = inferColumns(rows)) {
|
|
2173
|
+
const sanitized = sanitizeCsvProjectionInfo({ rows, columns });
|
|
2137
2174
|
const columnStats = {};
|
|
2138
|
-
for (const column of columns) {
|
|
2175
|
+
for (const column of sanitized.columns) {
|
|
2139
2176
|
let nonEmpty = 0;
|
|
2140
2177
|
let empty = 0;
|
|
2141
2178
|
let sampleValue;
|
|
2142
2179
|
let sampleValueType = null;
|
|
2143
2180
|
const valueCounts = /* @__PURE__ */ new Map();
|
|
2144
|
-
for (const row of rows) {
|
|
2181
|
+
for (const row of sanitized.rows) {
|
|
2145
2182
|
const raw = row[column];
|
|
2146
2183
|
const value = compactCell(raw);
|
|
2147
2184
|
if (value) {
|
|
@@ -2193,10 +2230,14 @@ function writeCanonicalRowsCsv(rowsInfo, outPath) {
|
|
|
2193
2230
|
`Run output only includes ${rowsInfo.rows.length} preview row(s) of ${rowsInfo.totalRows}; cannot export a complete CSV from this status payload yet.`
|
|
2194
2231
|
);
|
|
2195
2232
|
}
|
|
2233
|
+
const sanitized = sanitizeCsvProjectionInfo({
|
|
2234
|
+
rows: rowsInfo.rows,
|
|
2235
|
+
columns: rowsInfo.columns
|
|
2236
|
+
});
|
|
2196
2237
|
const resolved = resolve3(outPath);
|
|
2197
2238
|
writeFileSync3(
|
|
2198
2239
|
resolved,
|
|
2199
|
-
csvStringFromRows(
|
|
2240
|
+
csvStringFromRows(sanitized.rows, sanitized.columns),
|
|
2200
2241
|
"utf-8"
|
|
2201
2242
|
);
|
|
2202
2243
|
return resolved;
|
|
@@ -2488,14 +2529,12 @@ function registerOrgCommands(program) {
|
|
|
2488
2529
|
import { createHash as createHash3 } from "crypto";
|
|
2489
2530
|
import {
|
|
2490
2531
|
existsSync as existsSync4,
|
|
2491
|
-
mkdirSync as mkdirSync3,
|
|
2492
2532
|
readFileSync as readFileSync3,
|
|
2493
2533
|
readdirSync,
|
|
2494
2534
|
realpathSync,
|
|
2495
2535
|
writeFileSync as writeFileSync4
|
|
2496
2536
|
} from "fs";
|
|
2497
2537
|
import { basename as basename3, dirname as dirname6, join as join6, resolve as resolve7 } from "path";
|
|
2498
|
-
import { Option } from "commander";
|
|
2499
2538
|
|
|
2500
2539
|
// src/plays/bundle-play-file.ts
|
|
2501
2540
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -2579,6 +2618,14 @@ var PLAY_SOURCE_FILE_PATTERN = /\.play\.(?:[cm]?[jt]sx?)$/i;
|
|
|
2579
2618
|
var NODE_BUILTIN_SET = new Set(
|
|
2580
2619
|
builtinModules.flatMap((name) => name.startsWith("node:") ? [name, name.slice(5)] : [name, `node:${name}`])
|
|
2581
2620
|
);
|
|
2621
|
+
function assertValidExportName(exportName) {
|
|
2622
|
+
if (exportName === "default") return;
|
|
2623
|
+
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(exportName)) {
|
|
2624
|
+
throw new Error(
|
|
2625
|
+
`Invalid play export name "${exportName}". Named prebuilt exports must be valid JavaScript identifiers.`
|
|
2626
|
+
);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2582
2629
|
function sha256(value) {
|
|
2583
2630
|
return createHash("sha256").update(value).digest("hex");
|
|
2584
2631
|
}
|
|
@@ -2773,6 +2820,29 @@ function workersPlayEntryAliasPlugin(playFilePath) {
|
|
|
2773
2820
|
}
|
|
2774
2821
|
};
|
|
2775
2822
|
}
|
|
2823
|
+
function workersNamedPlayEntryAliasPlugin(playFilePath, exportName) {
|
|
2824
|
+
return {
|
|
2825
|
+
name: "deepline-workers-named-play-entry-alias",
|
|
2826
|
+
setup(buildContext) {
|
|
2827
|
+
buildContext.onResolve(
|
|
2828
|
+
{ filter: new RegExp(`^${WORKERS_PLAY_ENTRY_VIRTUAL}$`) },
|
|
2829
|
+
() => ({
|
|
2830
|
+
path: `${playFilePath}.${exportName}.entry.ts`,
|
|
2831
|
+
namespace: "deepline-named-play-entry"
|
|
2832
|
+
})
|
|
2833
|
+
);
|
|
2834
|
+
buildContext.onLoad(
|
|
2835
|
+
{ filter: /.*/, namespace: "deepline-named-play-entry" },
|
|
2836
|
+
() => ({
|
|
2837
|
+
contents: `export { ${exportName} as default } from ${JSON.stringify(playFilePath)};
|
|
2838
|
+
`,
|
|
2839
|
+
loader: "ts",
|
|
2840
|
+
resolveDir: dirname3(playFilePath)
|
|
2841
|
+
})
|
|
2842
|
+
);
|
|
2843
|
+
}
|
|
2844
|
+
};
|
|
2845
|
+
}
|
|
2776
2846
|
function workersNodeBuiltinStubPlugin() {
|
|
2777
2847
|
const UNSUPPORTED = /* @__PURE__ */ new Set(["node:fs", "node:fs/promises", "node:os", "node:child_process"]);
|
|
2778
2848
|
return {
|
|
@@ -3204,11 +3274,20 @@ function getBundleSizeError(filePath, bundledCode, artifactKind) {
|
|
|
3204
3274
|
}
|
|
3205
3275
|
return null;
|
|
3206
3276
|
}
|
|
3207
|
-
async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter) {
|
|
3277
|
+
async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter, exportName) {
|
|
3208
3278
|
const sdkAliasPlugin = localSdkAliasPlugin(adapter);
|
|
3209
3279
|
const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
|
|
3280
|
+
const namedExportShim = exportName === "default" ? null : `export { ${exportName} as default } from ${JSON.stringify(entryFile)};
|
|
3281
|
+
`;
|
|
3210
3282
|
const result = await build({
|
|
3211
|
-
|
|
3283
|
+
...namedExportShim ? {
|
|
3284
|
+
stdin: {
|
|
3285
|
+
contents: namedExportShim,
|
|
3286
|
+
resolveDir: dirname3(entryFile),
|
|
3287
|
+
sourcefile: `${basename(entryFile)}.${exportName}.entry.ts`,
|
|
3288
|
+
loader: "ts"
|
|
3289
|
+
}
|
|
3290
|
+
} : { entryPoints: [entryFile] },
|
|
3212
3291
|
absWorkingDir: adapter.projectRoot,
|
|
3213
3292
|
bundle: true,
|
|
3214
3293
|
format: "cjs",
|
|
@@ -3236,10 +3315,10 @@ async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter
|
|
|
3236
3315
|
outputExtension: "cjs"
|
|
3237
3316
|
};
|
|
3238
3317
|
}
|
|
3239
|
-
async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies, adapter) {
|
|
3318
|
+
async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies, adapter, exportName) {
|
|
3240
3319
|
const sdkAliasPlugin = localSdkAliasPlugin(adapter, { workersRuntime: true });
|
|
3241
3320
|
const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
|
|
3242
|
-
const playEntryAlias = workersPlayEntryAliasPlugin(playEntryFile);
|
|
3321
|
+
const playEntryAlias = exportName === "default" ? workersPlayEntryAliasPlugin(playEntryFile) : workersNamedPlayEntryAliasPlugin(playEntryFile, exportName);
|
|
3243
3322
|
const result = await build({
|
|
3244
3323
|
// Entry is the Workers harness; it imports the play via the virtual
|
|
3245
3324
|
// `deepline-play-entry` alias resolved by workersPlayEntryAliasPlugin.
|
|
@@ -3310,10 +3389,16 @@ async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies,
|
|
|
3310
3389
|
async function bundlePlayFile(filePath, options) {
|
|
3311
3390
|
const adapter = options.adapter;
|
|
3312
3391
|
const target = options.target ?? PLAY_ARTIFACT_KINDS.cjsNode20;
|
|
3392
|
+
const exportName = options.exportName?.trim() || "default";
|
|
3393
|
+
assertValidExportName(exportName);
|
|
3313
3394
|
const absolutePath = await normalizeLocalPath(filePath);
|
|
3314
3395
|
adapter.warnAboutNonDevelopmentBundling?.(absolutePath);
|
|
3315
3396
|
try {
|
|
3316
3397
|
const analysis = await analyzeSourceGraph(absolutePath, adapter);
|
|
3398
|
+
analysis.graphHash = sha256(
|
|
3399
|
+
`${analysis.graphHash}
|
|
3400
|
+
entry-export:${exportName}`
|
|
3401
|
+
);
|
|
3317
3402
|
if (target === PLAY_ARTIFACT_KINDS.esmWorkers) {
|
|
3318
3403
|
const harnessFingerprint = await computeWorkersHarnessFingerprintWithAdapter(adapter);
|
|
3319
3404
|
analysis.graphHash = sha256(
|
|
@@ -3365,7 +3450,7 @@ workers-harness:${harnessFingerprint}`
|
|
|
3365
3450
|
errors: typecheckErrors
|
|
3366
3451
|
};
|
|
3367
3452
|
}
|
|
3368
|
-
const buildOutcome = target === PLAY_ARTIFACT_KINDS.esmWorkers ? await runEsbuildForEsmWorkers(absolutePath, analysis.importedPlayDependencies, adapter) : await runEsbuildForCjsNode(absolutePath, analysis.importedPlayDependencies, adapter);
|
|
3453
|
+
const buildOutcome = target === PLAY_ARTIFACT_KINDS.esmWorkers ? await runEsbuildForEsmWorkers(absolutePath, analysis.importedPlayDependencies, adapter, exportName) : await runEsbuildForCjsNode(absolutePath, analysis.importedPlayDependencies, adapter, exportName);
|
|
3369
3454
|
if (Array.isArray(buildOutcome)) {
|
|
3370
3455
|
return {
|
|
3371
3456
|
success: false,
|
|
@@ -3375,7 +3460,8 @@ workers-harness:${harnessFingerprint}`
|
|
|
3375
3460
|
}
|
|
3376
3461
|
const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
|
|
3377
3462
|
const normalizedSourceMap = normalizeSourceMapForRuntime(sourceMapText);
|
|
3378
|
-
const
|
|
3463
|
+
const virtualBaseName = exportName === "default" ? basename(absolutePath).replace(/\.[^.]+$/, "") : `${basename(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
|
|
3464
|
+
const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
|
|
3379
3465
|
const executableCode = `${bundledCode}
|
|
3380
3466
|
//# sourceMappingURL=${basename(virtualFilename)}.map
|
|
3381
3467
|
`;
|
|
@@ -3758,7 +3844,7 @@ function createSdkPlayBundlingAdapter() {
|
|
|
3758
3844
|
sdkSourceRoot: SDK_SOURCE_ROOT,
|
|
3759
3845
|
sdkPackageJson: SDK_PACKAGE_JSON,
|
|
3760
3846
|
sdkEntryFile: SDK_ENTRY_FILE,
|
|
3761
|
-
sdkTypesEntryFile: existsSync3(SDK_TYPES_ENTRY_FILE) ? SDK_TYPES_ENTRY_FILE : SDK_ENTRY_FILE,
|
|
3847
|
+
sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : existsSync3(SDK_TYPES_ENTRY_FILE) ? SDK_TYPES_ENTRY_FILE : SDK_ENTRY_FILE,
|
|
3762
3848
|
sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
|
|
3763
3849
|
workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
|
|
3764
3850
|
workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
|
|
@@ -3769,6 +3855,7 @@ function createSdkPlayBundlingAdapter() {
|
|
|
3769
3855
|
async function bundlePlayFile2(filePath, options = {}) {
|
|
3770
3856
|
return bundlePlayFile(filePath, {
|
|
3771
3857
|
target: options.target ?? defaultPlayBundleTarget(),
|
|
3858
|
+
exportName: options.exportName,
|
|
3772
3859
|
adapter: createSdkPlayBundlingAdapter()
|
|
3773
3860
|
});
|
|
3774
3861
|
}
|
|
@@ -3918,54 +4005,6 @@ function createCliProgress(enabled) {
|
|
|
3918
4005
|
return progress;
|
|
3919
4006
|
}
|
|
3920
4007
|
|
|
3921
|
-
// src/cli/trace.ts
|
|
3922
|
-
var cliTraceStartedAt = Date.now();
|
|
3923
|
-
function isTruthyEnv(value) {
|
|
3924
|
-
return value === "1" || value === "true" || value === "yes";
|
|
3925
|
-
}
|
|
3926
|
-
function isCliTraceEnabled() {
|
|
3927
|
-
return isTruthyEnv(process.env.DEEPLINE_CLI_TRACE);
|
|
3928
|
-
}
|
|
3929
|
-
function recordCliTrace(event) {
|
|
3930
|
-
if (!isCliTraceEnabled()) {
|
|
3931
|
-
return;
|
|
3932
|
-
}
|
|
3933
|
-
const now = Date.now();
|
|
3934
|
-
const payload = {
|
|
3935
|
-
ts: now,
|
|
3936
|
-
source: "cli",
|
|
3937
|
-
sinceStartMs: now - cliTraceStartedAt,
|
|
3938
|
-
...event
|
|
3939
|
-
};
|
|
3940
|
-
process.stderr.write(`[cli-trace] ${JSON.stringify(payload)}
|
|
3941
|
-
`);
|
|
3942
|
-
}
|
|
3943
|
-
async function traceCliSpan(phase, fields, run) {
|
|
3944
|
-
if (!isCliTraceEnabled()) {
|
|
3945
|
-
return run();
|
|
3946
|
-
}
|
|
3947
|
-
const startedAt = Date.now();
|
|
3948
|
-
try {
|
|
3949
|
-
const result = await run();
|
|
3950
|
-
recordCliTrace({
|
|
3951
|
-
phase,
|
|
3952
|
-
ms: Date.now() - startedAt,
|
|
3953
|
-
ok: true,
|
|
3954
|
-
...fields
|
|
3955
|
-
});
|
|
3956
|
-
return result;
|
|
3957
|
-
} catch (error) {
|
|
3958
|
-
recordCliTrace({
|
|
3959
|
-
phase,
|
|
3960
|
-
ms: Date.now() - startedAt,
|
|
3961
|
-
ok: false,
|
|
3962
|
-
error: error instanceof Error ? error.message : String(error),
|
|
3963
|
-
...fields
|
|
3964
|
-
});
|
|
3965
|
-
throw error;
|
|
3966
|
-
}
|
|
3967
|
-
}
|
|
3968
|
-
|
|
3969
4008
|
// src/cli/commands/play.ts
|
|
3970
4009
|
function parseReferencedPlayTarget(target) {
|
|
3971
4010
|
const trimmed = target.trim();
|
|
@@ -4013,67 +4052,6 @@ function defaultMaterializedPlayPath(reference) {
|
|
|
4013
4052
|
const safeName = playName.trim().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
4014
4053
|
return resolve7(`${safeName || "play"}.play.ts`);
|
|
4015
4054
|
}
|
|
4016
|
-
function sanitizeGeneratedPlayName(value) {
|
|
4017
|
-
return value.trim().toLowerCase().replace(/^prebuilt\//, "").replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "play";
|
|
4018
|
-
}
|
|
4019
|
-
function buildGeneratedCsvWrapperSource(input) {
|
|
4020
|
-
return `import { definePlay } from 'deepline';
|
|
4021
|
-
|
|
4022
|
-
export default definePlay(
|
|
4023
|
-
${JSON.stringify(input.wrapperName)},
|
|
4024
|
-
async (ctx, input: Record<string, unknown> & { file: string }) => {
|
|
4025
|
-
const rows = await ctx.csv<Record<string, unknown>>(input.file);
|
|
4026
|
-
const constants = Object.fromEntries(
|
|
4027
|
-
Object.entries(input).filter(([key]) => key !== 'file'),
|
|
4028
|
-
);
|
|
4029
|
-
|
|
4030
|
-
const mappedRows = await ctx
|
|
4031
|
-
.map('csv_rows', rows, {
|
|
4032
|
-
key: (row, index) =>
|
|
4033
|
-
String(
|
|
4034
|
-
row.id ??
|
|
4035
|
-
row.lead_id ??
|
|
4036
|
-
row.email ??
|
|
4037
|
-
row.linkedin_url ??
|
|
4038
|
-
row.domain ??
|
|
4039
|
-
index,
|
|
4040
|
-
),
|
|
4041
|
-
})
|
|
4042
|
-
.step('result', (row, rowCtx) =>
|
|
4043
|
-
rowCtx.runPlay(
|
|
4044
|
-
'row_play',
|
|
4045
|
-
${JSON.stringify(input.playRef)},
|
|
4046
|
-
{
|
|
4047
|
-
...constants,
|
|
4048
|
-
...row,
|
|
4049
|
-
},
|
|
4050
|
-
{
|
|
4051
|
-
description: 'Run the source play for this CSV row.',
|
|
4052
|
-
},
|
|
4053
|
-
),
|
|
4054
|
-
)
|
|
4055
|
-
.run({ description: 'Run the source play once per CSV row.' });
|
|
4056
|
-
|
|
4057
|
-
return { rows: mappedRows };
|
|
4058
|
-
},
|
|
4059
|
-
);
|
|
4060
|
-
`;
|
|
4061
|
-
}
|
|
4062
|
-
function writeGeneratedCsvWrapperPlay(playRef) {
|
|
4063
|
-
const baseName = sanitizeGeneratedPlayName(
|
|
4064
|
-
parseReferencedPlayTarget(playRef).unqualifiedPlayName
|
|
4065
|
-
);
|
|
4066
|
-
const wrapperName = `${baseName}-csv`;
|
|
4067
|
-
const outputDir = resolve7(".deepline", "generated");
|
|
4068
|
-
const outputPath = join6(outputDir, `${wrapperName}.play.ts`);
|
|
4069
|
-
mkdirSync3(outputDir, { recursive: true });
|
|
4070
|
-
writeFileSync4(
|
|
4071
|
-
outputPath,
|
|
4072
|
-
buildGeneratedCsvWrapperSource({ wrapperName, playRef }),
|
|
4073
|
-
"utf-8"
|
|
4074
|
-
);
|
|
4075
|
-
return outputPath;
|
|
4076
|
-
}
|
|
4077
4055
|
function materializeRemotePlaySource(input) {
|
|
4078
4056
|
if (isFileTarget(input.target)) {
|
|
4079
4057
|
return null;
|
|
@@ -4139,7 +4117,10 @@ function looksLikeFilePath(target) {
|
|
|
4139
4117
|
if (target.trim().toLowerCase().startsWith("prebuilt/")) {
|
|
4140
4118
|
return false;
|
|
4141
4119
|
}
|
|
4142
|
-
|
|
4120
|
+
if (target.startsWith("./") || target.startsWith("../") || target.startsWith("/") || target.startsWith("~/")) {
|
|
4121
|
+
return true;
|
|
4122
|
+
}
|
|
4123
|
+
return target.includes("\\") || /\.(ts|js|mjs|play\.ts)$/.test(target);
|
|
4143
4124
|
}
|
|
4144
4125
|
function parsePositiveInteger2(value, flagName) {
|
|
4145
4126
|
const parsed = Number.parseInt(value, 10);
|
|
@@ -4156,6 +4137,133 @@ function parseJsonInput(raw) {
|
|
|
4156
4137
|
}
|
|
4157
4138
|
return parsed;
|
|
4158
4139
|
}
|
|
4140
|
+
function parseInputFieldFlag(rawFlag, nextArg) {
|
|
4141
|
+
const flag = rawFlag.slice(2);
|
|
4142
|
+
const equalsIndex = flag.indexOf("=");
|
|
4143
|
+
if (equalsIndex > 0) {
|
|
4144
|
+
const path = flag.slice(0, equalsIndex).trim();
|
|
4145
|
+
const value = flag.slice(equalsIndex + 1);
|
|
4146
|
+
if (!path) {
|
|
4147
|
+
throw new Error(`Invalid play input flag: ${rawFlag}`);
|
|
4148
|
+
}
|
|
4149
|
+
return { path, value };
|
|
4150
|
+
}
|
|
4151
|
+
if (!nextArg || nextArg.startsWith("--")) {
|
|
4152
|
+
throw new Error(`Play input flag ${rawFlag} requires a value.`);
|
|
4153
|
+
}
|
|
4154
|
+
return { path: flag, value: nextArg };
|
|
4155
|
+
}
|
|
4156
|
+
function parseInputFlagValue(raw) {
|
|
4157
|
+
const trimmed = raw.trim();
|
|
4158
|
+
if (!trimmed) return "";
|
|
4159
|
+
if (trimmed === "true" || trimmed === "false" || trimmed === "null" || trimmed.startsWith("{") || trimmed.startsWith("[") || /^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
4160
|
+
try {
|
|
4161
|
+
return JSON.parse(trimmed);
|
|
4162
|
+
} catch {
|
|
4163
|
+
return raw;
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
return raw;
|
|
4167
|
+
}
|
|
4168
|
+
function getDottedInputValue(input, path) {
|
|
4169
|
+
const parts = path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
4170
|
+
let cursor = input;
|
|
4171
|
+
for (const part of parts) {
|
|
4172
|
+
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) {
|
|
4173
|
+
return void 0;
|
|
4174
|
+
}
|
|
4175
|
+
cursor = cursor[part];
|
|
4176
|
+
}
|
|
4177
|
+
return cursor;
|
|
4178
|
+
}
|
|
4179
|
+
function setDottedInputValue(input, path, value) {
|
|
4180
|
+
const parts = path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
4181
|
+
if (parts.length === 0) {
|
|
4182
|
+
throw new Error(`Invalid play input flag path: ${path}`);
|
|
4183
|
+
}
|
|
4184
|
+
let cursor = input;
|
|
4185
|
+
for (const part of parts.slice(0, -1)) {
|
|
4186
|
+
const existing = cursor[part];
|
|
4187
|
+
if (existing !== void 0 && (!existing || typeof existing !== "object" || Array.isArray(existing))) {
|
|
4188
|
+
throw new Error(
|
|
4189
|
+
`Cannot set --${path}; input.${part} is already a non-object value.`
|
|
4190
|
+
);
|
|
4191
|
+
}
|
|
4192
|
+
if (!existing) {
|
|
4193
|
+
cursor[part] = {};
|
|
4194
|
+
}
|
|
4195
|
+
cursor = cursor[part];
|
|
4196
|
+
}
|
|
4197
|
+
cursor[parts[parts.length - 1]] = value;
|
|
4198
|
+
}
|
|
4199
|
+
function schemaMetadata(schema, key) {
|
|
4200
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return null;
|
|
4201
|
+
const value = schema[key];
|
|
4202
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
4203
|
+
}
|
|
4204
|
+
function stringMetadata(metadata, key) {
|
|
4205
|
+
const value = metadata?.[key];
|
|
4206
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
4207
|
+
}
|
|
4208
|
+
function inputFieldFromCsvArg(csvArg) {
|
|
4209
|
+
if (typeof csvArg !== "string") return null;
|
|
4210
|
+
const match = /^input\.([A-Za-z_$][\w$]*)$/.exec(csvArg.trim());
|
|
4211
|
+
return match?.[1] ?? null;
|
|
4212
|
+
}
|
|
4213
|
+
function fileInputBindingsFromPlaySchema(inputSchema) {
|
|
4214
|
+
const csvInput = schemaMetadata(inputSchema, "csvInput");
|
|
4215
|
+
if (!csvInput) return [];
|
|
4216
|
+
return [
|
|
4217
|
+
{
|
|
4218
|
+
inputPath: stringMetadata(csvInput, "inputField") ?? "csv"
|
|
4219
|
+
}
|
|
4220
|
+
];
|
|
4221
|
+
}
|
|
4222
|
+
function fileInputBindingsFromStaticPipeline(staticPipeline) {
|
|
4223
|
+
if (!staticPipeline || typeof staticPipeline !== "object" || Array.isArray(staticPipeline)) {
|
|
4224
|
+
return [];
|
|
4225
|
+
}
|
|
4226
|
+
const inputField = inputFieldFromCsvArg(
|
|
4227
|
+
staticPipeline.csvArg
|
|
4228
|
+
);
|
|
4229
|
+
return inputField ? [{ inputPath: inputField }] : [];
|
|
4230
|
+
}
|
|
4231
|
+
function isLocalFilePathValue(value) {
|
|
4232
|
+
if (typeof value !== "string" || !value.trim()) return false;
|
|
4233
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
|
|
4234
|
+
return existsSync4(resolve7(value));
|
|
4235
|
+
}
|
|
4236
|
+
async function stageFileInputArgs(input) {
|
|
4237
|
+
const uniqueBindings = [
|
|
4238
|
+
...new Map(input.bindings.map((binding) => [binding.inputPath, binding])).values()
|
|
4239
|
+
];
|
|
4240
|
+
const localFiles = uniqueBindings.flatMap((binding) => {
|
|
4241
|
+
const value = getDottedInputValue(input.runtimeInput, binding.inputPath);
|
|
4242
|
+
if (!isLocalFilePathValue(value)) return [];
|
|
4243
|
+
const absolutePath = resolve7(value);
|
|
4244
|
+
return [{ binding, absolutePath, logicalPath: basename3(absolutePath) }];
|
|
4245
|
+
});
|
|
4246
|
+
if (localFiles.length === 0) {
|
|
4247
|
+
return { inputFile: null, packagedFiles: [] };
|
|
4248
|
+
}
|
|
4249
|
+
input.progress.phase(
|
|
4250
|
+
localFiles.length === 1 ? "staging input file" : "staging input files"
|
|
4251
|
+
);
|
|
4252
|
+
const staged = await input.client.stagePlayFiles(
|
|
4253
|
+
localFiles.map((file) => stageFile(file.logicalPath, file.absolutePath))
|
|
4254
|
+
);
|
|
4255
|
+
for (const [index, file] of localFiles.entries()) {
|
|
4256
|
+
setDottedInputValue(input.runtimeInput, file.binding.inputPath, file.logicalPath);
|
|
4257
|
+
const stagedFile = staged[index];
|
|
4258
|
+
if (stagedFile && stagedFile.logicalPath !== file.logicalPath) {
|
|
4259
|
+
setDottedInputValue(input.runtimeInput, file.binding.inputPath, stagedFile.logicalPath);
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
return {
|
|
4263
|
+
inputFile: staged[0] ?? null,
|
|
4264
|
+
packagedFiles: staged.slice(1)
|
|
4265
|
+
};
|
|
4266
|
+
}
|
|
4159
4267
|
function stageFile(logicalPath, absolutePath) {
|
|
4160
4268
|
const buffer = readFileSync3(absolutePath);
|
|
4161
4269
|
return {
|
|
@@ -4564,24 +4672,10 @@ async function startAndWaitForPlayCompletionByStream(input) {
|
|
|
4564
4672
|
},
|
|
4565
4673
|
Math.max(1, input.waitTimeoutMs)
|
|
4566
4674
|
);
|
|
4567
|
-
recordCliTrace({
|
|
4568
|
-
phase: "cli.start_stream_request",
|
|
4569
|
-
playName: input.playName
|
|
4570
|
-
});
|
|
4571
4675
|
try {
|
|
4572
|
-
let eventCount = 0;
|
|
4573
4676
|
for await (const event of input.client.startPlayRunStream(input.request, {
|
|
4574
4677
|
signal: controller.signal
|
|
4575
4678
|
})) {
|
|
4576
|
-
eventCount += 1;
|
|
4577
|
-
if (eventCount === 1) {
|
|
4578
|
-
recordCliTrace({
|
|
4579
|
-
phase: "cli.start_stream_first_event",
|
|
4580
|
-
ms: Date.now() - startedAt,
|
|
4581
|
-
playName: input.playName,
|
|
4582
|
-
eventType: event.type
|
|
4583
|
-
});
|
|
4584
|
-
}
|
|
4585
4679
|
const eventRunId = getEventPayload(event).runId;
|
|
4586
4680
|
if (typeof eventRunId === "string" && eventRunId && eventRunId !== "pending") {
|
|
4587
4681
|
lastKnownWorkflowId = eventRunId;
|
|
@@ -4622,14 +4716,6 @@ async function startAndWaitForPlayCompletionByStream(input) {
|
|
|
4622
4716
|
});
|
|
4623
4717
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
4624
4718
|
if (finalStatus) {
|
|
4625
|
-
recordCliTrace({
|
|
4626
|
-
phase: "cli.start_stream_final_event",
|
|
4627
|
-
ms: Date.now() - startedAt,
|
|
4628
|
-
playName: input.playName,
|
|
4629
|
-
runId: finalStatus.runId,
|
|
4630
|
-
status: finalStatus.status,
|
|
4631
|
-
eventCount
|
|
4632
|
-
});
|
|
4633
4719
|
return finalStatus;
|
|
4634
4720
|
}
|
|
4635
4721
|
}
|
|
@@ -4908,7 +4994,6 @@ function buildRunNextCommands(runId) {
|
|
|
4908
4994
|
return {
|
|
4909
4995
|
exportCsv: `deepline runs export ${runId} --out output.csv`,
|
|
4910
4996
|
status: `deepline runs status ${runId} --json`,
|
|
4911
|
-
fullStatus: `deepline runs status ${runId} --json --full`,
|
|
4912
4997
|
logs: `deepline runs logs ${runId}`
|
|
4913
4998
|
};
|
|
4914
4999
|
}
|
|
@@ -4932,12 +5017,26 @@ function compactPlayStatus(status, options) {
|
|
|
4932
5017
|
...result !== void 0 ? { result } : {},
|
|
4933
5018
|
...status.resultView ? { resultView: status.resultView } : {},
|
|
4934
5019
|
...datasetStats ? { dataset_stats: datasetStats } : {},
|
|
4935
|
-
...rowsInfo ? { previewRows: rowsInfo.rows.slice(0,
|
|
5020
|
+
...rowsInfo ? { previewRows: rowsInfo.rows.slice(0, 5) } : {},
|
|
4936
5021
|
...billing ? { billing } : {},
|
|
4937
5022
|
...status.run ? { run: status.run } : {},
|
|
4938
5023
|
next: buildRunNextCommands(status.runId)
|
|
4939
5024
|
};
|
|
4940
5025
|
}
|
|
5026
|
+
function enrichPlayStatusWithDatasetStats(status) {
|
|
5027
|
+
const rowsInfo = extractCanonicalRowsInfo(status);
|
|
5028
|
+
if (!rowsInfo?.complete) {
|
|
5029
|
+
return status;
|
|
5030
|
+
}
|
|
5031
|
+
return {
|
|
5032
|
+
...status,
|
|
5033
|
+
dataset_stats: buildDatasetStats(
|
|
5034
|
+
rowsInfo.rows,
|
|
5035
|
+
rowsInfo.totalRows,
|
|
5036
|
+
rowsInfo.columns
|
|
5037
|
+
)
|
|
5038
|
+
};
|
|
5039
|
+
}
|
|
4941
5040
|
function formatDatasetStatsLines(datasetStats) {
|
|
4942
5041
|
if (!datasetStats) {
|
|
4943
5042
|
return [];
|
|
@@ -4947,10 +5046,10 @@ function formatDatasetStatsLines(datasetStats) {
|
|
|
4947
5046
|
0,
|
|
4948
5047
|
12
|
|
4949
5048
|
)) {
|
|
4950
|
-
const topValues = stat3.top_values ? `,
|
|
4951
|
-
const sample = stat3.sample_value !== void 0 ? `,
|
|
5049
|
+
const topValues = stat3.top_values ? `, top_values=${Object.entries(stat3.top_values).slice(0, 3).map(([value, count]) => `${value}=${count}`).join(", ")}` : "";
|
|
5050
|
+
const sample = stat3.sample_value !== void 0 ? `, sample_value=${JSON.stringify(stat3.sample_value)}` : "";
|
|
4952
5051
|
lines.push(
|
|
4953
|
-
` ${column}:
|
|
5052
|
+
` ${column}: non_empty=${stat3.non_empty}, unique=${stat3.unique}${topValues}${sample}`
|
|
4954
5053
|
);
|
|
4955
5054
|
}
|
|
4956
5055
|
return lines;
|
|
@@ -4959,7 +5058,7 @@ function writePlayResult(status, jsonOutput, options) {
|
|
|
4959
5058
|
if (jsonOutput) {
|
|
4960
5059
|
process.stdout.write(
|
|
4961
5060
|
`${JSON.stringify(
|
|
4962
|
-
options?.fullJson ? status : compactPlayStatus(status, options)
|
|
5061
|
+
options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status, options)
|
|
4963
5062
|
)}
|
|
4964
5063
|
`
|
|
4965
5064
|
);
|
|
@@ -5108,10 +5207,9 @@ function writeStartedPlayRun(input) {
|
|
|
5108
5207
|
console.log(output);
|
|
5109
5208
|
}
|
|
5110
5209
|
function parsePlayRunOptions(args) {
|
|
5111
|
-
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--
|
|
5210
|
+
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--watch] [--out output.csv] [--tail-timeout-ms 30000] [--force] [--json] [--<input> value]";
|
|
5112
5211
|
let filePath = null;
|
|
5113
5212
|
let playName = null;
|
|
5114
|
-
let csvPath = null;
|
|
5115
5213
|
let input = null;
|
|
5116
5214
|
let revisionId = null;
|
|
5117
5215
|
let revisionSelector = null;
|
|
@@ -5132,10 +5230,6 @@ function parsePlayRunOptions(args) {
|
|
|
5132
5230
|
playName = parseReferencedPlayTarget(args[++index]).playName;
|
|
5133
5231
|
continue;
|
|
5134
5232
|
}
|
|
5135
|
-
if (arg === "--csv" && args[index + 1]) {
|
|
5136
|
-
csvPath = resolve7(args[++index]);
|
|
5137
|
-
continue;
|
|
5138
|
-
}
|
|
5139
5233
|
if ((arg === "--input" || arg === "-i") && args[index + 1]) {
|
|
5140
5234
|
input = parseJsonInput(args[++index]);
|
|
5141
5235
|
continue;
|
|
@@ -5185,8 +5279,13 @@ function parsePlayRunOptions(args) {
|
|
|
5185
5279
|
continue;
|
|
5186
5280
|
}
|
|
5187
5281
|
if (arg.startsWith("--")) {
|
|
5188
|
-
|
|
5189
|
-
|
|
5282
|
+
const { path, value } = parseInputFieldFlag(arg, args[index + 1]);
|
|
5283
|
+
input ??= {};
|
|
5284
|
+
setDottedInputValue(input, path, parseInputFlagValue(value));
|
|
5285
|
+
if (!arg.includes("=")) {
|
|
5286
|
+
index += 1;
|
|
5287
|
+
}
|
|
5288
|
+
continue;
|
|
5190
5289
|
}
|
|
5191
5290
|
if (!arg.startsWith("--") && !filePath && !playName) {
|
|
5192
5291
|
if (isFileTarget(arg) || looksLikeFilePath(arg)) {
|
|
@@ -5222,7 +5321,6 @@ ${usage}`);
|
|
|
5222
5321
|
}
|
|
5223
5322
|
return {
|
|
5224
5323
|
target: filePath ? { kind: "file", path: filePath } : { kind: "name", name: playName },
|
|
5225
|
-
csvPath,
|
|
5226
5324
|
input,
|
|
5227
5325
|
revisionId,
|
|
5228
5326
|
revisionSelector,
|
|
@@ -5297,34 +5395,12 @@ async function handleFileBackedRun(options) {
|
|
|
5297
5395
|
const client = new DeeplineClient();
|
|
5298
5396
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
5299
5397
|
const absolutePlayPath = resolve7(options.target.path);
|
|
5300
|
-
recordCliTrace({
|
|
5301
|
-
phase: "cli.play_run_file_start",
|
|
5302
|
-
playPath: absolutePlayPath,
|
|
5303
|
-
watch: options.watch,
|
|
5304
|
-
hasCsv: Boolean(options.csvPath),
|
|
5305
|
-
force: options.force
|
|
5306
|
-
});
|
|
5307
5398
|
progress.phase("compiling play");
|
|
5308
|
-
const readSourceStartedAt = Date.now();
|
|
5309
5399
|
const sourceCode = readFileSync3(absolutePlayPath, "utf-8");
|
|
5310
|
-
recordCliTrace({
|
|
5311
|
-
phase: "cli.read_play_source",
|
|
5312
|
-
ms: Date.now() - readSourceStartedAt,
|
|
5313
|
-
bytes: sourceCode.length,
|
|
5314
|
-
playPath: absolutePlayPath
|
|
5315
|
-
});
|
|
5316
5400
|
let graph;
|
|
5317
5401
|
try {
|
|
5318
|
-
graph = await
|
|
5319
|
-
|
|
5320
|
-
{ playPath: absolutePlayPath },
|
|
5321
|
-
() => collectBundledPlayGraph(absolutePlayPath)
|
|
5322
|
-
);
|
|
5323
|
-
await traceCliSpan(
|
|
5324
|
-
"cli.compile_play_manifest",
|
|
5325
|
-
{ playPath: absolutePlayPath, nodeCount: graph.nodes.size },
|
|
5326
|
-
() => compileBundledPlayGraphManifests(client, graph)
|
|
5327
|
-
);
|
|
5402
|
+
graph = await collectBundledPlayGraph(absolutePlayPath);
|
|
5403
|
+
await compileBundledPlayGraphManifests(client, graph);
|
|
5328
5404
|
progress.phase("compiled play");
|
|
5329
5405
|
} catch (error) {
|
|
5330
5406
|
progress.fail();
|
|
@@ -5335,87 +5411,58 @@ async function handleFileBackedRun(options) {
|
|
|
5335
5411
|
const playName = bundleResult.playName ?? extractPlayName(sourceCode, absolutePlayPath);
|
|
5336
5412
|
try {
|
|
5337
5413
|
progress.phase("publishing imported plays");
|
|
5338
|
-
await
|
|
5339
|
-
"cli.publish_imported_plays",
|
|
5340
|
-
{ playName, nodeCount: graph.nodes.size },
|
|
5341
|
-
() => publishImportedPlayDependencies(client, graph)
|
|
5342
|
-
);
|
|
5414
|
+
await publishImportedPlayDependencies(client, graph);
|
|
5343
5415
|
} catch (error) {
|
|
5344
5416
|
progress.fail();
|
|
5345
5417
|
console.error(error instanceof Error ? error.message : String(error));
|
|
5346
5418
|
return 1;
|
|
5347
5419
|
}
|
|
5348
5420
|
const runtimeInput = options.input ? { ...options.input } : {};
|
|
5349
|
-
const prepareFilesStartedAt = Date.now();
|
|
5350
5421
|
const packagedFileUploads = bundleResult.packagedFiles.map(
|
|
5351
5422
|
(file) => stageFile(file.logicalPath, file.absolutePath)
|
|
5352
5423
|
);
|
|
5353
|
-
const
|
|
5354
|
-
|
|
5355
|
-
runtimeInput
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
playName,
|
|
5361
|
-
packagedFileCount: packagedFileUploads.length,
|
|
5362
|
-
hasInputFile: Boolean(inputFileUpload)
|
|
5424
|
+
const stagedFileInputs = await stageFileInputArgs({
|
|
5425
|
+
client,
|
|
5426
|
+
runtimeInput,
|
|
5427
|
+
bindings: fileInputBindingsFromStaticPipeline(
|
|
5428
|
+
requireCompilerManifest(bundleResult).staticPipeline
|
|
5429
|
+
),
|
|
5430
|
+
progress
|
|
5363
5431
|
});
|
|
5364
5432
|
const startRequest = {
|
|
5365
5433
|
name: playName,
|
|
5366
5434
|
sourceCode: bundleResult.sourceCode,
|
|
5367
5435
|
runtimeArtifact: bundleResult.artifact,
|
|
5368
5436
|
compilerManifest: requireCompilerManifest(bundleResult),
|
|
5369
|
-
inputFileUpload,
|
|
5370
5437
|
packagedFileUploads,
|
|
5371
5438
|
...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
|
|
5439
|
+
...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
|
|
5440
|
+
...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
|
|
5372
5441
|
...options.force ? { force: true } : {}
|
|
5373
5442
|
};
|
|
5374
5443
|
if (options.watch) {
|
|
5375
5444
|
progress.phase("starting run");
|
|
5376
|
-
const finalStatus = await
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
() => startAndWaitForPlayCompletionByStream({
|
|
5380
|
-
client,
|
|
5381
|
-
request: startRequest,
|
|
5382
|
-
playName,
|
|
5383
|
-
jsonOutput: options.jsonOutput,
|
|
5384
|
-
emitLogs: options.emitLogs,
|
|
5385
|
-
waitTimeoutMs: options.waitTimeoutMs,
|
|
5386
|
-
progress
|
|
5387
|
-
})
|
|
5388
|
-
);
|
|
5389
|
-
const exportStartedAt = Date.now();
|
|
5390
|
-
const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
|
|
5391
|
-
recordCliTrace({
|
|
5392
|
-
phase: "cli.export_rows",
|
|
5393
|
-
ms: Date.now() - exportStartedAt,
|
|
5445
|
+
const finalStatus = await startAndWaitForPlayCompletionByStream({
|
|
5446
|
+
client,
|
|
5447
|
+
request: startRequest,
|
|
5394
5448
|
playName,
|
|
5395
|
-
|
|
5449
|
+
jsonOutput: options.jsonOutput,
|
|
5450
|
+
emitLogs: options.emitLogs,
|
|
5451
|
+
waitTimeoutMs: options.waitTimeoutMs,
|
|
5452
|
+
progress
|
|
5396
5453
|
});
|
|
5454
|
+
const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
|
|
5397
5455
|
if (finalStatus.status === "completed") {
|
|
5398
5456
|
progress.complete();
|
|
5399
5457
|
} else {
|
|
5400
5458
|
progress.fail();
|
|
5401
5459
|
}
|
|
5402
|
-
recordCliTrace({
|
|
5403
|
-
phase: "cli.write_play_result",
|
|
5404
|
-
playName,
|
|
5405
|
-
status: finalStatus.status,
|
|
5406
|
-
runId: finalStatus.runId
|
|
5407
|
-
});
|
|
5408
5460
|
writePlayResult(finalStatus, options.jsonOutput, { exportedPath });
|
|
5409
5461
|
return finalStatus.status === "completed" ? 0 : 1;
|
|
5410
5462
|
}
|
|
5411
5463
|
progress.phase("starting run");
|
|
5412
|
-
const started = await
|
|
5413
|
-
|
|
5414
|
-
{ playName },
|
|
5415
|
-
() => client.startPlayRun(startRequest)
|
|
5416
|
-
);
|
|
5417
|
-
const fallbackDashboardUrl = buildPlayDashboardUrl(client.baseUrl, playName);
|
|
5418
|
-
const dashboardUrl = started.dashboardUrl ?? fallbackDashboardUrl;
|
|
5464
|
+
const started = await client.startPlayRun(startRequest);
|
|
5465
|
+
const dashboardUrl = buildPlayDashboardUrl(client.baseUrl, playName);
|
|
5419
5466
|
progress.phase(`loading play on ${dashboardUrl}`);
|
|
5420
5467
|
progress.complete();
|
|
5421
5468
|
writeStartedPlayRun({
|
|
@@ -5423,7 +5470,7 @@ async function handleFileBackedRun(options) {
|
|
|
5423
5470
|
playName,
|
|
5424
5471
|
status: started.status,
|
|
5425
5472
|
statusUrl: started.statusUrl,
|
|
5426
|
-
dashboardUrl,
|
|
5473
|
+
dashboardUrl: started.dashboardUrl ?? dashboardUrl,
|
|
5427
5474
|
jsonOutput: options.jsonOutput,
|
|
5428
5475
|
progress
|
|
5429
5476
|
});
|
|
@@ -5449,9 +5496,8 @@ async function handleNamedRun(options) {
|
|
|
5449
5496
|
}
|
|
5450
5497
|
const client = new DeeplineClient();
|
|
5451
5498
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
5452
|
-
let stagedInputFile = null;
|
|
5453
5499
|
progress.phase("loading play definition");
|
|
5454
|
-
await assertCanonicalNamedPlayReference(client, options.target.name);
|
|
5500
|
+
const playDetail = await assertCanonicalNamedPlayReference(client, options.target.name);
|
|
5455
5501
|
progress.phase("selecting revision");
|
|
5456
5502
|
const selectedRevisionId = await resolveNamedRunRevisionId({
|
|
5457
5503
|
client,
|
|
@@ -5459,19 +5505,22 @@ async function handleNamedRun(options) {
|
|
|
5459
5505
|
revisionId: options.revisionId,
|
|
5460
5506
|
selector: options.revisionSelector
|
|
5461
5507
|
});
|
|
5462
|
-
if (options.csvPath) {
|
|
5463
|
-
progress.phase("staging input file");
|
|
5464
|
-
const [staged] = await client.stagePlayFiles([
|
|
5465
|
-
stageFile(basename3(options.csvPath), options.csvPath)
|
|
5466
|
-
]);
|
|
5467
|
-
stagedInputFile = staged ?? null;
|
|
5468
|
-
}
|
|
5469
5508
|
const runtimeInput = options.input ? { ...options.input } : {};
|
|
5509
|
+
const stagedFileInputs = await stageFileInputArgs({
|
|
5510
|
+
client,
|
|
5511
|
+
runtimeInput,
|
|
5512
|
+
bindings: [
|
|
5513
|
+
...fileInputBindingsFromPlaySchema(playDetail.play.inputSchema),
|
|
5514
|
+
...fileInputBindingsFromStaticPipeline(playDetail.play.staticPipeline)
|
|
5515
|
+
],
|
|
5516
|
+
progress
|
|
5517
|
+
});
|
|
5470
5518
|
const startRequest = {
|
|
5471
5519
|
name: options.target.name,
|
|
5472
5520
|
...selectedRevisionId ? { revisionId: selectedRevisionId } : {},
|
|
5473
5521
|
...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
|
|
5474
|
-
...
|
|
5522
|
+
...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
|
|
5523
|
+
...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
|
|
5475
5524
|
...options.force ? { force: true } : {}
|
|
5476
5525
|
};
|
|
5477
5526
|
if (options.watch) {
|
|
@@ -5485,22 +5534,6 @@ async function handleNamedRun(options) {
|
|
|
5485
5534
|
waitTimeoutMs: options.waitTimeoutMs,
|
|
5486
5535
|
progress
|
|
5487
5536
|
});
|
|
5488
|
-
if (finalStatus.status !== "completed" && options.csvPath) {
|
|
5489
|
-
progress.phase("generating csv wrapper play");
|
|
5490
|
-
const generatedPlayPath = writeGeneratedCsvWrapperPlay(
|
|
5491
|
-
options.target.name
|
|
5492
|
-
);
|
|
5493
|
-
progress.writeLogLine(
|
|
5494
|
-
`Generated CSV wrapper play: ${generatedPlayPath}`
|
|
5495
|
-
);
|
|
5496
|
-
progress.phase("running generated csv wrapper play");
|
|
5497
|
-
return handleFileBackedRun({
|
|
5498
|
-
...options,
|
|
5499
|
-
target: { kind: "file", path: generatedPlayPath },
|
|
5500
|
-
revisionId: null,
|
|
5501
|
-
revisionSelector: null
|
|
5502
|
-
});
|
|
5503
|
-
}
|
|
5504
5537
|
const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
|
|
5505
5538
|
if (finalStatus.status === "completed") {
|
|
5506
5539
|
progress.complete();
|
|
@@ -5512,11 +5545,10 @@ async function handleNamedRun(options) {
|
|
|
5512
5545
|
}
|
|
5513
5546
|
progress.phase("starting run");
|
|
5514
5547
|
const started = await client.startPlayRun(startRequest);
|
|
5515
|
-
const
|
|
5548
|
+
const dashboardUrl = buildPlayDashboardUrl(
|
|
5516
5549
|
client.baseUrl,
|
|
5517
5550
|
options.target.name
|
|
5518
5551
|
);
|
|
5519
|
-
const dashboardUrl = started.dashboardUrl ?? fallbackDashboardUrl;
|
|
5520
5552
|
progress.phase(`loading play on ${dashboardUrl}`);
|
|
5521
5553
|
progress.complete();
|
|
5522
5554
|
writeStartedPlayRun({
|
|
@@ -5524,7 +5556,7 @@ async function handleNamedRun(options) {
|
|
|
5524
5556
|
playName: started.name ?? options.target.name,
|
|
5525
5557
|
status: started.status,
|
|
5526
5558
|
statusUrl: started.statusUrl,
|
|
5527
|
-
dashboardUrl,
|
|
5559
|
+
dashboardUrl: started.dashboardUrl ?? dashboardUrl,
|
|
5528
5560
|
jsonOutput: options.jsonOutput,
|
|
5529
5561
|
progress
|
|
5530
5562
|
});
|
|
@@ -5743,8 +5775,9 @@ async function handlePlayGet(args) {
|
|
|
5743
5775
|
return 1;
|
|
5744
5776
|
}
|
|
5745
5777
|
const client = new DeeplineClient();
|
|
5746
|
-
const
|
|
5778
|
+
const explicitJson = args.includes("--json");
|
|
5747
5779
|
const sourceOutput = args.includes("--source");
|
|
5780
|
+
const jsonOutput = sourceOutput ? explicitJson : argsWantJson(args);
|
|
5748
5781
|
let outPath = null;
|
|
5749
5782
|
for (let index = 1; index < args.length; index += 1) {
|
|
5750
5783
|
const arg = args[index];
|
|
@@ -5755,7 +5788,7 @@ async function handlePlayGet(args) {
|
|
|
5755
5788
|
const playName = isFileTarget(target) ? extractPlayName(readFileSync3(resolve7(target), "utf-8"), resolve7(target)) : parseReferencedPlayTarget(target).playName;
|
|
5756
5789
|
const detail = isFileTarget(target) ? await client.getPlay(playName) : await assertCanonicalNamedPlayReference(client, target);
|
|
5757
5790
|
const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
|
|
5758
|
-
const materializedFile =
|
|
5791
|
+
const materializedFile = outPath ? materializeRemotePlaySource({
|
|
5759
5792
|
target,
|
|
5760
5793
|
playName,
|
|
5761
5794
|
sourceCode: resolvedSource,
|
|
@@ -5795,6 +5828,10 @@ async function handlePlayGet(args) {
|
|
|
5795
5828
|
}
|
|
5796
5829
|
return 0;
|
|
5797
5830
|
}
|
|
5831
|
+
if (outPath && loadedMessage) {
|
|
5832
|
+
console.log(loadedMessage);
|
|
5833
|
+
return 0;
|
|
5834
|
+
}
|
|
5798
5835
|
console.log(`Play: ${formatPlayReference(detail.play)}`);
|
|
5799
5836
|
console.log(
|
|
5800
5837
|
`Working version: ${detail.play.workingRevision?.version ?? "\u2014"}`
|
|
@@ -5961,6 +5998,20 @@ function printPlayDescription(play) {
|
|
|
5961
5998
|
console.log(` ${line}`);
|
|
5962
5999
|
}
|
|
5963
6000
|
}
|
|
6001
|
+
if (play.csvInput) {
|
|
6002
|
+
console.log(" CSV input:");
|
|
6003
|
+
const rendered = JSON.stringify(play.csvInput, null, 2);
|
|
6004
|
+
for (const line of rendered.split("\n")) {
|
|
6005
|
+
console.log(` ${line}`);
|
|
6006
|
+
}
|
|
6007
|
+
}
|
|
6008
|
+
if (play.rowOutputSchema) {
|
|
6009
|
+
console.log(" Row output schema:");
|
|
6010
|
+
const rendered = JSON.stringify(play.rowOutputSchema, null, 2);
|
|
6011
|
+
for (const line of rendered.split("\n")) {
|
|
6012
|
+
console.log(` ${line}`);
|
|
6013
|
+
}
|
|
6014
|
+
}
|
|
5964
6015
|
console.log(` Run: ${play.runCommand}`);
|
|
5965
6016
|
}
|
|
5966
6017
|
async function handlePlaySearch(args) {
|
|
@@ -6100,6 +6151,45 @@ async function handlePlayPublish(args) {
|
|
|
6100
6151
|
`);
|
|
6101
6152
|
return result.success ? 0 : 1;
|
|
6102
6153
|
}
|
|
6154
|
+
async function handlePlayDelete(args) {
|
|
6155
|
+
const playName = args[0];
|
|
6156
|
+
if (!playName) {
|
|
6157
|
+
console.error("Usage: deepline plays delete <play-name> --yes [--json]");
|
|
6158
|
+
return 1;
|
|
6159
|
+
}
|
|
6160
|
+
const confirmed = args.includes("--yes") || args.includes("-y") || args.includes("--force");
|
|
6161
|
+
if (!confirmed) {
|
|
6162
|
+
console.error(
|
|
6163
|
+
"Refusing to delete without --yes. This deletes the org-owned play, its revisions, trigger bindings, and local run records."
|
|
6164
|
+
);
|
|
6165
|
+
return 1;
|
|
6166
|
+
}
|
|
6167
|
+
const client = new DeeplineClient();
|
|
6168
|
+
let detail;
|
|
6169
|
+
try {
|
|
6170
|
+
detail = await client.getPlay(parseReferencedPlayTarget(playName).playName);
|
|
6171
|
+
} catch (error) {
|
|
6172
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
6173
|
+
return 1;
|
|
6174
|
+
}
|
|
6175
|
+
if (detail.play.ownerType === "deepline" || detail.play.origin === "prebuilt") {
|
|
6176
|
+
console.error(`Cannot delete prebuilt play: ${formatPlayReference(detail.play)}`);
|
|
6177
|
+
return 1;
|
|
6178
|
+
}
|
|
6179
|
+
const result = await client.deletePlay(
|
|
6180
|
+
parseReferencedPlayTarget(formatPlayReference(detail.play)).playName
|
|
6181
|
+
);
|
|
6182
|
+
if (argsWantJson(args)) {
|
|
6183
|
+
process.stdout.write(`${JSON.stringify(result)}
|
|
6184
|
+
`);
|
|
6185
|
+
return result.deleted ? 0 : 1;
|
|
6186
|
+
}
|
|
6187
|
+
process.stdout.write(
|
|
6188
|
+
`Deleted ${result.name}: revisions=${result.deletedRevisionCount}, bindings=${result.deletedBindingCount}, runs=${result.deletedRunCount}
|
|
6189
|
+
`
|
|
6190
|
+
);
|
|
6191
|
+
return result.deleted ? 0 : 1;
|
|
6192
|
+
}
|
|
6103
6193
|
function registerPlayCommands(program) {
|
|
6104
6194
|
const play = program.command("plays").alias("play").description("Search, validate, run, and manage cloud plays.").addHelpText(
|
|
6105
6195
|
"after",
|
|
@@ -6133,21 +6223,23 @@ Examples:
|
|
|
6133
6223
|
...options.json ? ["--json"] : []
|
|
6134
6224
|
]);
|
|
6135
6225
|
});
|
|
6136
|
-
play.command("run [target]").description("Run a play file or named play.").addHelpText(
|
|
6226
|
+
play.command("run [target]").description("Run a play file or named play.").allowUnknownOption(true).allowExcessArguments(true).addHelpText(
|
|
6137
6227
|
"after",
|
|
6138
6228
|
`
|
|
6139
6229
|
Notes:
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6230
|
+
Local play files are bundled locally, then validated and executed in Deepline cloud.
|
|
6231
|
+
Named plays run the stored live cloud revision.
|
|
6232
|
+
Unknown --foo and --foo.bar flags are treated as play input args.
|
|
6233
|
+
File-like input args accept local paths; the CLI stages those files before submit.
|
|
6234
|
+
Run performs server preflight automatically. Use \`deepline plays check <file>\`
|
|
6235
|
+
to validate without starting a run.
|
|
6144
6236
|
|
|
6145
6237
|
Examples:
|
|
6146
6238
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
|
|
6147
6239
|
deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}' --watch
|
|
6148
6240
|
deepline plays run enrich.play.ts --csv leads.csv --watch --out leads-enriched.csv
|
|
6149
6241
|
`
|
|
6150
|
-
).option("--file <path>", "Local play file to run").option("--name <name>", "Saved play name to run").option("
|
|
6242
|
+
).option("--file <path>", "Local play file to run").option("--name <name>", "Saved play name to run").option("-i, --input <json>", "Input JSON object or @file path").option("--live", "Run the current live revision explicitly").option("--latest", "Run the newest saved revision, even if it is not live").option(
|
|
6151
6243
|
"--revision-id <id>",
|
|
6152
6244
|
"Run a specific saved revision instead of the live revision"
|
|
6153
6245
|
).option(
|
|
@@ -6156,12 +6248,21 @@ Examples:
|
|
|
6156
6248
|
).option("--watch", "Stream logs until completion").option(
|
|
6157
6249
|
"--logs",
|
|
6158
6250
|
"When output is non-interactive, stream play logs to stderr while waiting"
|
|
6159
|
-
).option("--poll-interval-ms <ms>", "Polling interval while tailing").option("--tail-timeout-ms <ms>", "Timeout while tailing").option("--force", "Supersede any active runs for this play").option("--json", "Emit JSON output").action(async (target, options) => {
|
|
6251
|
+
).option("--poll-interval-ms <ms>", "Polling interval while tailing").option("--tail-timeout-ms <ms>", "Timeout while tailing").option("--force", "Supersede any active runs for this play").option("--json", "Emit JSON output").action(async (target, options, command) => {
|
|
6252
|
+
const passthroughArgs = [...command.args];
|
|
6253
|
+
const explicitTarget = options.file || options.name;
|
|
6254
|
+
const targetIsInputFlag = typeof target === "string" && target.startsWith("--");
|
|
6255
|
+
const effectiveTarget = explicitTarget || targetIsInputFlag ? null : target;
|
|
6256
|
+
if (explicitTarget && typeof target === "string" && !targetIsInputFlag && !passthroughArgs.includes(target)) {
|
|
6257
|
+
passthroughArgs.push(target);
|
|
6258
|
+
}
|
|
6259
|
+
if (effectiveTarget && passthroughArgs[0] === effectiveTarget) {
|
|
6260
|
+
passthroughArgs.shift();
|
|
6261
|
+
}
|
|
6160
6262
|
process.exitCode = await handlePlayRun([
|
|
6161
|
-
...
|
|
6263
|
+
...effectiveTarget ? [effectiveTarget] : [],
|
|
6162
6264
|
...options.file ? ["--file", options.file] : [],
|
|
6163
6265
|
...options.name ? ["--name", options.name] : [],
|
|
6164
|
-
...options.csv ? ["--csv", options.csv] : [],
|
|
6165
6266
|
...options.input ? ["--input", options.input] : [],
|
|
6166
6267
|
...options.live ? ["--live"] : [],
|
|
6167
6268
|
...options.latest ? ["--latest"] : [],
|
|
@@ -6172,7 +6273,8 @@ Examples:
|
|
|
6172
6273
|
...options.pollIntervalMs ? ["--poll-interval-ms", options.pollIntervalMs] : [],
|
|
6173
6274
|
...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
|
|
6174
6275
|
...options.force ? ["--force"] : [],
|
|
6175
|
-
...options.json ? ["--json"] : []
|
|
6276
|
+
...options.json ? ["--json"] : [],
|
|
6277
|
+
...passthroughArgs
|
|
6176
6278
|
]);
|
|
6177
6279
|
});
|
|
6178
6280
|
play.command("get <target>").description("Fetch full play details.").addHelpText(
|
|
@@ -6186,12 +6288,10 @@ Notes:
|
|
|
6186
6288
|
Examples:
|
|
6187
6289
|
deepline plays get person-linkedin-to-email
|
|
6188
6290
|
deepline plays get person-linkedin-to-email --json | jq '.play.liveRevision'
|
|
6291
|
+
deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source > email-waterfall.play.ts
|
|
6292
|
+
deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source --out ./email-waterfall.play.ts
|
|
6189
6293
|
`
|
|
6190
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").
|
|
6191
|
-
new Option("--source", "Materialize or print the source code").hideHelp()
|
|
6192
|
-
).addOption(
|
|
6193
|
-
new Option("--out <path>", "Write source to a specific path").hideHelp()
|
|
6194
|
-
).action(async (target, options) => {
|
|
6294
|
+
).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--source", "Print raw source code; combine with --out to write a file").option("--out <path>", "Write source to a specific path").action(async (target, options) => {
|
|
6195
6295
|
process.exitCode = await handlePlayGet([
|
|
6196
6296
|
target,
|
|
6197
6297
|
...options.json ? ["--json"] : [],
|
|
@@ -6251,7 +6351,7 @@ Examples:
|
|
|
6251
6351
|
...options.json ? ["--json"] : []
|
|
6252
6352
|
]);
|
|
6253
6353
|
});
|
|
6254
|
-
play.command("status").description("Show status for a play run.").option("--run-id <runId>", "Run id to inspect").option("--name <name>", "Inspect the latest run for a named play").option("--json", "Emit JSON output").option("--full", "
|
|
6354
|
+
play.command("status").description("Show status for a play run.").option("--run-id <runId>", "Run id to inspect").option("--name <name>", "Inspect the latest run for a named play").option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").action(async (options) => {
|
|
6255
6355
|
process.exitCode = await handlePlayStatus([
|
|
6256
6356
|
...options.runId ? ["--run-id", options.runId] : [],
|
|
6257
6357
|
...options.name ? ["--name", options.name] : [],
|
|
@@ -6282,6 +6382,13 @@ Examples:
|
|
|
6282
6382
|
...options.json ? ["--json"] : []
|
|
6283
6383
|
]);
|
|
6284
6384
|
});
|
|
6385
|
+
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) => {
|
|
6386
|
+
process.exitCode = await handlePlayDelete([
|
|
6387
|
+
target,
|
|
6388
|
+
...options.yes ? ["--yes"] : [],
|
|
6389
|
+
...options.json ? ["--json"] : []
|
|
6390
|
+
]);
|
|
6391
|
+
});
|
|
6285
6392
|
const runs = program.command("runs").description("Inspect and export play runs.").addHelpText(
|
|
6286
6393
|
"after",
|
|
6287
6394
|
`
|
|
@@ -6291,7 +6398,7 @@ Examples:
|
|
|
6291
6398
|
deepline runs logs play/my-play/run/20260501t000000-000
|
|
6292
6399
|
`
|
|
6293
6400
|
);
|
|
6294
|
-
runs.command("status <runId>").description("Show compact status for a play run.").option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--full", "
|
|
6401
|
+
runs.command("status <runId>").description("Show compact status 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) => {
|
|
6295
6402
|
process.exitCode = await handleRunStatus([
|
|
6296
6403
|
runId,
|
|
6297
6404
|
...options.json ? ["--json"] : [],
|
|
@@ -6315,7 +6422,7 @@ Examples:
|
|
|
6315
6422
|
}
|
|
6316
6423
|
|
|
6317
6424
|
// src/tool-output.ts
|
|
6318
|
-
import { mkdirSync as
|
|
6425
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
6319
6426
|
import { homedir as homedir3 } from "os";
|
|
6320
6427
|
import { join as join7 } from "path";
|
|
6321
6428
|
function isPlainObject(value) {
|
|
@@ -6393,7 +6500,7 @@ function tryConvertToList(payload, options) {
|
|
|
6393
6500
|
}
|
|
6394
6501
|
function ensureOutputDir() {
|
|
6395
6502
|
const outputDir = join7(homedir3(), ".local", "share", "deepline", "data");
|
|
6396
|
-
|
|
6503
|
+
mkdirSync3(outputDir, { recursive: true });
|
|
6397
6504
|
return outputDir;
|
|
6398
6505
|
}
|
|
6399
6506
|
function writeJsonOutputFile(payload, stem) {
|
|
@@ -6646,7 +6753,7 @@ function printToolDetails(tool, requestedToolId) {
|
|
|
6646
6753
|
const operation = typeof tool.operation === "string" ? tool.operation : "";
|
|
6647
6754
|
const displayBase = operation && operation.startsWith(`${tool.provider}_`) ? operation.slice(String(tool.provider).length + 1) : operation ? `${tool.provider} ${operation}`.trim() : toolId;
|
|
6648
6755
|
const displayName = titleCase(displayBase || String(tool.displayName || toolId));
|
|
6649
|
-
const cost =
|
|
6756
|
+
const cost = isRecord3(tool.cost) ? tool.cost : null;
|
|
6650
6757
|
const deeplineCredits = numberField(tool, "deeplineCreditsPerPricingUnit", "deepline_credits_per_pricing_unit");
|
|
6651
6758
|
const deeplineUsdPerPricingUnit = numberField(tool, "deeplineUsdPerPricingUnit", "deepline_usd_per_pricing_unit");
|
|
6652
6759
|
const deeplineUsdPerCredit = numberField(tool, "deeplineUsdPerCredit", "deepline_usd_per_credit");
|
|
@@ -6691,7 +6798,7 @@ function printToolDetails(tool, requestedToolId) {
|
|
|
6691
6798
|
if (stepContributions.length) {
|
|
6692
6799
|
console.log(" step contributions:");
|
|
6693
6800
|
for (const item of stepContributions) {
|
|
6694
|
-
if (!
|
|
6801
|
+
if (!isRecord3(item)) continue;
|
|
6695
6802
|
const stepTool = typeof item.tool === "string" ? item.tool.trim() : "";
|
|
6696
6803
|
const low = typeof item.lowCredits === "number" ? item.lowCredits : null;
|
|
6697
6804
|
const high = typeof item.highCredits === "number" ? item.highCredits : null;
|
|
@@ -6778,12 +6885,12 @@ function printToolCost(input) {
|
|
|
6778
6885
|
return false;
|
|
6779
6886
|
}
|
|
6780
6887
|
function toolInputFieldsForDisplay(inputSchema) {
|
|
6781
|
-
if (Array.isArray(inputSchema.fields)) return inputSchema.fields.filter(
|
|
6782
|
-
const jsonSchema =
|
|
6783
|
-
const properties =
|
|
6888
|
+
if (Array.isArray(inputSchema.fields)) return inputSchema.fields.filter(isRecord3);
|
|
6889
|
+
const jsonSchema = isRecord3(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
|
|
6890
|
+
const properties = isRecord3(jsonSchema.properties) ? jsonSchema.properties : {};
|
|
6784
6891
|
const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
|
|
6785
6892
|
return Object.entries(properties).map(([name, value]) => {
|
|
6786
|
-
const property =
|
|
6893
|
+
const property = isRecord3(value) ? value : {};
|
|
6787
6894
|
return {
|
|
6788
6895
|
name,
|
|
6789
6896
|
type: typeof property.type === "string" ? property.type : "unknown",
|
|
@@ -6810,7 +6917,7 @@ function printJsonPreview(label, payload) {
|
|
|
6810
6917
|
}
|
|
6811
6918
|
function samplePayload(samples, key) {
|
|
6812
6919
|
const entry = samples[key];
|
|
6813
|
-
if (!
|
|
6920
|
+
if (!isRecord3(entry)) return void 0;
|
|
6814
6921
|
return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
|
|
6815
6922
|
}
|
|
6816
6923
|
function isPlayTool(tool) {
|
|
@@ -6831,7 +6938,7 @@ function formatDecimal(value) {
|
|
|
6831
6938
|
function formatUsd(value) {
|
|
6832
6939
|
return `$${formatDecimal(value)}`;
|
|
6833
6940
|
}
|
|
6834
|
-
function
|
|
6941
|
+
function isRecord3(value) {
|
|
6835
6942
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
6836
6943
|
}
|
|
6837
6944
|
function stringField(source, ...keys) {
|
|
@@ -6858,7 +6965,7 @@ function arrayField(source, ...keys) {
|
|
|
6858
6965
|
function recordField(source, ...keys) {
|
|
6859
6966
|
for (const key of keys) {
|
|
6860
6967
|
const value = source[key];
|
|
6861
|
-
if (
|
|
6968
|
+
if (isRecord3(value)) return value;
|
|
6862
6969
|
}
|
|
6863
6970
|
return {};
|
|
6864
6971
|
}
|
|
@@ -6949,7 +7056,7 @@ async function executeTool(args) {
|
|
|
6949
7056
|
}
|
|
6950
7057
|
throw error;
|
|
6951
7058
|
}
|
|
6952
|
-
const rawResponse = await client.
|
|
7059
|
+
const rawResponse = await client.executeTool(parsed.toolId, parsed.params);
|
|
6953
7060
|
const listConversion = tryConvertToList(rawResponse, {
|
|
6954
7061
|
listExtractorPaths: metadata.listExtractorPaths ?? []
|
|
6955
7062
|
});
|
|
@@ -7005,7 +7112,7 @@ async function executeTool(args) {
|
|
|
7005
7112
|
|
|
7006
7113
|
// src/cli/skills-sync.ts
|
|
7007
7114
|
import { spawn } from "child_process";
|
|
7008
|
-
import { existsSync as existsSync5, mkdirSync as
|
|
7115
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
7009
7116
|
import { homedir as homedir4 } from "os";
|
|
7010
7117
|
import { dirname as dirname7, join as join8 } from "path";
|
|
7011
7118
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
@@ -7031,7 +7138,7 @@ function readLocalSkillsVersion(baseUrl) {
|
|
|
7031
7138
|
}
|
|
7032
7139
|
function writeLocalSkillsVersion(baseUrl, version) {
|
|
7033
7140
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
7034
|
-
|
|
7141
|
+
mkdirSync4(dirname7(path), { recursive: true });
|
|
7035
7142
|
writeFileSync6(path, `${version}
|
|
7036
7143
|
`, "utf-8");
|
|
7037
7144
|
}
|
|
@@ -7120,6 +7227,54 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
|
|
|
7120
7227
|
progress?.writeLine("SDK skills are up to date.") ?? process.stderr.write("SDK skills are up to date.\n");
|
|
7121
7228
|
}
|
|
7122
7229
|
|
|
7230
|
+
// src/cli/trace.ts
|
|
7231
|
+
var cliTraceStartedAt = Date.now();
|
|
7232
|
+
function isTruthyEnv(value) {
|
|
7233
|
+
return value === "1" || value === "true" || value === "yes";
|
|
7234
|
+
}
|
|
7235
|
+
function isCliTraceEnabled() {
|
|
7236
|
+
return isTruthyEnv(process.env.DEEPLINE_CLI_TRACE);
|
|
7237
|
+
}
|
|
7238
|
+
function recordCliTrace(event) {
|
|
7239
|
+
if (!isCliTraceEnabled()) {
|
|
7240
|
+
return;
|
|
7241
|
+
}
|
|
7242
|
+
const now = Date.now();
|
|
7243
|
+
const payload = {
|
|
7244
|
+
ts: now,
|
|
7245
|
+
source: "cli",
|
|
7246
|
+
sinceStartMs: now - cliTraceStartedAt,
|
|
7247
|
+
...event
|
|
7248
|
+
};
|
|
7249
|
+
process.stderr.write(`[cli-trace] ${JSON.stringify(payload)}
|
|
7250
|
+
`);
|
|
7251
|
+
}
|
|
7252
|
+
async function traceCliSpan(phase, fields, run) {
|
|
7253
|
+
if (!isCliTraceEnabled()) {
|
|
7254
|
+
return run();
|
|
7255
|
+
}
|
|
7256
|
+
const startedAt = Date.now();
|
|
7257
|
+
try {
|
|
7258
|
+
const result = await run();
|
|
7259
|
+
recordCliTrace({
|
|
7260
|
+
phase,
|
|
7261
|
+
ms: Date.now() - startedAt,
|
|
7262
|
+
ok: true,
|
|
7263
|
+
...fields
|
|
7264
|
+
});
|
|
7265
|
+
return result;
|
|
7266
|
+
} catch (error) {
|
|
7267
|
+
recordCliTrace({
|
|
7268
|
+
phase,
|
|
7269
|
+
ms: Date.now() - startedAt,
|
|
7270
|
+
ok: false,
|
|
7271
|
+
error: error instanceof Error ? error.message : String(error),
|
|
7272
|
+
...fields
|
|
7273
|
+
});
|
|
7274
|
+
throw error;
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
|
|
7123
7278
|
// src/cli/index.ts
|
|
7124
7279
|
function shouldPrintStartupPhase() {
|
|
7125
7280
|
if (process.argv.includes("--json")) {
|
|
@@ -7141,7 +7296,7 @@ async function main() {
|
|
|
7141
7296
|
if (printStartupPhase) {
|
|
7142
7297
|
progress?.phase("loading deepline cli");
|
|
7143
7298
|
}
|
|
7144
|
-
const program = new
|
|
7299
|
+
const program = new Command();
|
|
7145
7300
|
program.name("deepline").description("Deepline CLI (TypeScript SDK)").version(SDK_VERSION, "-v, --version", "Show version").showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
7146
7301
|
"after",
|
|
7147
7302
|
`
|