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.js
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/cli/index.ts
|
|
27
|
-
var
|
|
27
|
+
var import_commander = require("commander");
|
|
28
28
|
|
|
29
29
|
// src/config.ts
|
|
30
30
|
var import_node_fs = require("fs");
|
|
@@ -192,7 +192,7 @@ function resolveConfig(options) {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
// src/version.ts
|
|
195
|
-
var SDK_VERSION = "0.1.
|
|
195
|
+
var SDK_VERSION = "0.1.12";
|
|
196
196
|
var SDK_API_CONTRACT = "2026-04-plays-v1";
|
|
197
197
|
|
|
198
198
|
// ../shared_libs/play-runtime/coordinator-headers.ts
|
|
@@ -467,6 +467,9 @@ function sleep(ms) {
|
|
|
467
467
|
|
|
468
468
|
// src/client.ts
|
|
469
469
|
var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
470
|
+
function isRecord(value) {
|
|
471
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
472
|
+
}
|
|
470
473
|
function normalizePlayStatus(raw) {
|
|
471
474
|
const status = typeof raw.status === "string" ? raw.status : typeof raw.temporalStatus === "string" ? mapLegacyTemporalStatus(raw.temporalStatus) : "running";
|
|
472
475
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : "";
|
|
@@ -519,12 +522,27 @@ var DeeplineClient = class {
|
|
|
519
522
|
).filter((field) => Boolean(field?.name)) : [];
|
|
520
523
|
return fields.length > 0 ? { fields } : schema;
|
|
521
524
|
}
|
|
522
|
-
|
|
523
|
-
|
|
525
|
+
schemaMetadata(schema, key) {
|
|
526
|
+
if (!isRecord(schema)) return null;
|
|
527
|
+
const value = schema[key];
|
|
528
|
+
return isRecord(value) ? value : null;
|
|
529
|
+
}
|
|
530
|
+
playRunCommand(play, options) {
|
|
531
|
+
const target = play.reference || play.name;
|
|
532
|
+
if (options?.csvInput) {
|
|
533
|
+
const inputField = typeof options.csvInput.inputField === "string" && options.csvInput.inputField.trim() ? options.csvInput.inputField.trim() : "csv";
|
|
534
|
+
return `deepline plays run ${target} --${inputField} leads.csv --watch`;
|
|
535
|
+
}
|
|
536
|
+
return `deepline plays run ${target} --input '{...}' --watch`;
|
|
524
537
|
}
|
|
525
538
|
summarizePlayListItem(play, options) {
|
|
526
539
|
const aliases = play.aliases?.length ? play.aliases : [play.name];
|
|
527
|
-
const
|
|
540
|
+
const csvInput = this.schemaMetadata(play.inputSchema, "csvInput");
|
|
541
|
+
const rowOutputSchema = this.schemaMetadata(
|
|
542
|
+
play.outputSchema,
|
|
543
|
+
"rowOutputSchema"
|
|
544
|
+
);
|
|
545
|
+
const runCommand = this.playRunCommand(play, { csvInput });
|
|
528
546
|
return {
|
|
529
547
|
name: play.name,
|
|
530
548
|
...play.reference ? { reference: play.reference } : {},
|
|
@@ -536,6 +554,8 @@ var DeeplineClient = class {
|
|
|
536
554
|
aliases,
|
|
537
555
|
inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
|
|
538
556
|
outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
|
|
557
|
+
...csvInput ? { csvInput } : {},
|
|
558
|
+
...rowOutputSchema ? { rowOutputSchema } : {},
|
|
539
559
|
runCommand,
|
|
540
560
|
examples: [runCommand],
|
|
541
561
|
currentPublishedVersion: play.currentPublishedVersion ?? null,
|
|
@@ -602,50 +622,14 @@ var DeeplineClient = class {
|
|
|
602
622
|
);
|
|
603
623
|
}
|
|
604
624
|
/**
|
|
605
|
-
* Execute a tool and return the
|
|
606
|
-
*
|
|
607
|
-
* Sends the input payload to the tool and returns the `.result` field from the
|
|
608
|
-
* response. For the full response envelope (including job_id, credits, etc.),
|
|
609
|
-
* use {@link executeToolRaw}.
|
|
610
|
-
*
|
|
611
|
-
* @param toolId - Tool identifier (e.g. `"test_company_search"`)
|
|
612
|
-
* @param input - Tool-specific input parameters
|
|
613
|
-
* @returns The tool's output (shape varies by tool)
|
|
614
|
-
* @throws {@link DeeplineError} if the tool execution fails
|
|
625
|
+
* Execute a tool and return the standard execution envelope.
|
|
615
626
|
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
* });
|
|
621
|
-
* console.log(company); // { name: "Stripe", industry: "Financial Services", ... }
|
|
622
|
-
* ```
|
|
627
|
+
* The `result.data` field contains the provider payload. `result.meta`
|
|
628
|
+
* contains provider/upstream metadata such as HTTP status or paging details.
|
|
629
|
+
* Top-level fields such as `status`, `job_id`, and `billing` describe the
|
|
630
|
+
* Deepline execution.
|
|
623
631
|
*/
|
|
624
632
|
async executeTool(toolId, input) {
|
|
625
|
-
const res = await this.http.post(
|
|
626
|
-
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
627
|
-
{ payload: input }
|
|
628
|
-
);
|
|
629
|
-
return res.result ?? res;
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Execute a tool and return the full response envelope.
|
|
633
|
-
*
|
|
634
|
-
* Unlike {@link executeTool}, this returns the complete API response including
|
|
635
|
-
* `job_id`, `status`, `credits`, and the raw `result` object.
|
|
636
|
-
*
|
|
637
|
-
* @param toolId - Tool identifier
|
|
638
|
-
* @param input - Tool-specific input parameters
|
|
639
|
-
* @returns Full response with job metadata and result
|
|
640
|
-
*
|
|
641
|
-
* @example
|
|
642
|
-
* ```typescript
|
|
643
|
-
* const raw = await client.executeToolRaw('test_company_search', { domain: 'stripe.com' });
|
|
644
|
-
* console.log(`Job: ${raw.job_id}, Credits: ${raw.credits}`);
|
|
645
|
-
* console.log(`Result:`, raw.result);
|
|
646
|
-
* ```
|
|
647
|
-
*/
|
|
648
|
-
async executeToolRaw(toolId, input) {
|
|
649
633
|
return this.http.post(
|
|
650
634
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
651
635
|
{ payload: input }
|
|
@@ -1976,18 +1960,61 @@ function registerBillingCommands(program) {
|
|
|
1976
1960
|
// src/cli/dataset-stats.ts
|
|
1977
1961
|
var import_node_fs4 = require("fs");
|
|
1978
1962
|
var import_node_path4 = require("path");
|
|
1979
|
-
|
|
1963
|
+
var CSV_PROJECTED_FIELDS_KEY = "__deeplineCsvProjectedFields";
|
|
1964
|
+
function csvProjectedFields(row) {
|
|
1965
|
+
const serialized = row[CSV_PROJECTED_FIELDS_KEY];
|
|
1966
|
+
if (!Array.isArray(serialized)) {
|
|
1967
|
+
return /* @__PURE__ */ new Set();
|
|
1968
|
+
}
|
|
1969
|
+
return new Set(
|
|
1970
|
+
serialized.filter((field) => typeof field === "string")
|
|
1971
|
+
);
|
|
1972
|
+
}
|
|
1973
|
+
function stripCsvProjectionFields(row) {
|
|
1974
|
+
const projectedFields = csvProjectedFields(row);
|
|
1975
|
+
if (projectedFields.size === 0 && !(CSV_PROJECTED_FIELDS_KEY in row)) {
|
|
1976
|
+
return row;
|
|
1977
|
+
}
|
|
1978
|
+
const stripped = { ...row };
|
|
1979
|
+
for (const field of projectedFields) {
|
|
1980
|
+
delete stripped[field];
|
|
1981
|
+
}
|
|
1982
|
+
delete stripped[CSV_PROJECTED_FIELDS_KEY];
|
|
1983
|
+
return stripped;
|
|
1984
|
+
}
|
|
1985
|
+
function stripCsvProjectionColumns(columns, rows) {
|
|
1986
|
+
const projectedFields = /* @__PURE__ */ new Set();
|
|
1987
|
+
let hasProjectionMetadata = false;
|
|
1988
|
+
for (const row of rows) {
|
|
1989
|
+
for (const field of csvProjectedFields(row)) {
|
|
1990
|
+
projectedFields.add(field);
|
|
1991
|
+
}
|
|
1992
|
+
hasProjectionMetadata ||= CSV_PROJECTED_FIELDS_KEY in row;
|
|
1993
|
+
}
|
|
1994
|
+
if (!hasProjectionMetadata && projectedFields.size === 0) {
|
|
1995
|
+
return columns;
|
|
1996
|
+
}
|
|
1997
|
+
return columns.filter(
|
|
1998
|
+
(column) => column !== CSV_PROJECTED_FIELDS_KEY && !projectedFields.has(column)
|
|
1999
|
+
);
|
|
2000
|
+
}
|
|
2001
|
+
function sanitizeCsvProjectionInfo(input) {
|
|
2002
|
+
const columns = stripCsvProjectionColumns(input.columns, input.rows);
|
|
2003
|
+
const rows = input.rows.map(stripCsvProjectionFields);
|
|
2004
|
+
return { rows, columns };
|
|
2005
|
+
}
|
|
2006
|
+
function isRecord2(value) {
|
|
1980
2007
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1981
2008
|
}
|
|
1982
2009
|
function isSerializedDataset(value) {
|
|
1983
|
-
return
|
|
2010
|
+
return isRecord2(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
|
|
1984
2011
|
}
|
|
1985
2012
|
function rowArray(value) {
|
|
1986
2013
|
if (!Array.isArray(value)) {
|
|
1987
2014
|
return null;
|
|
1988
2015
|
}
|
|
1989
2016
|
const rows = value.filter(
|
|
1990
|
-
(row) =>
|
|
2017
|
+
(row) => isRecord2(row)
|
|
1991
2018
|
);
|
|
1992
2019
|
return rows.length === value.length ? rows : null;
|
|
1993
2020
|
}
|
|
@@ -2011,12 +2038,12 @@ function inferColumns(rows) {
|
|
|
2011
2038
|
return columns;
|
|
2012
2039
|
}
|
|
2013
2040
|
function extractCanonicalRowsInfo(statusOrResult) {
|
|
2014
|
-
const root =
|
|
2015
|
-
const result =
|
|
2041
|
+
const root = isRecord2(statusOrResult) ? statusOrResult : null;
|
|
2042
|
+
const result = isRecord2(root?.result) ? root.result : root;
|
|
2016
2043
|
if (!result) {
|
|
2017
2044
|
return null;
|
|
2018
2045
|
}
|
|
2019
|
-
const metadata =
|
|
2046
|
+
const metadata = isRecord2(result._metadata) ? result._metadata : null;
|
|
2020
2047
|
const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
|
|
2021
2048
|
const candidates = [
|
|
2022
2049
|
{ source: "result.contacts", value: result.contacts, total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count },
|
|
@@ -2024,8 +2051,8 @@ function extractCanonicalRowsInfo(statusOrResult) {
|
|
|
2024
2051
|
{ source: "result.rows", value: result.rows, total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count },
|
|
2025
2052
|
{ source: "result.results", value: result.results, total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count }
|
|
2026
2053
|
];
|
|
2027
|
-
if (
|
|
2028
|
-
const outputMetadata =
|
|
2054
|
+
if (isRecord2(result.output)) {
|
|
2055
|
+
const outputMetadata = isRecord2(result.output._metadata) ? result.output._metadata : null;
|
|
2029
2056
|
const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
|
|
2030
2057
|
candidates.push(
|
|
2031
2058
|
{ source: "result.output.contacts", value: result.output.contacts, total: outputTotalFromMetadata ?? result.output.totalRows ?? result.output.rowCount ?? result.output.count },
|
|
@@ -2036,12 +2063,17 @@ function extractCanonicalRowsInfo(statusOrResult) {
|
|
|
2036
2063
|
}
|
|
2037
2064
|
for (const candidate of candidates) {
|
|
2038
2065
|
if (isSerializedDataset(candidate.value)) {
|
|
2039
|
-
const
|
|
2040
|
-
const totalRows2 = readNumber(candidate.value.count) ??
|
|
2066
|
+
const rawRows = rowArray(candidate.value.preview) ?? [];
|
|
2067
|
+
const totalRows2 = readNumber(candidate.value.count) ?? rawRows.length;
|
|
2068
|
+
const rawColumns = Array.isArray(candidate.value.columns) && candidate.value.columns.every((column) => typeof column === "string") ? candidate.value.columns : inferColumns(rawRows);
|
|
2069
|
+
const { rows: rows2, columns } = sanitizeCsvProjectionInfo({
|
|
2070
|
+
rows: rawRows,
|
|
2071
|
+
columns: rawColumns
|
|
2072
|
+
});
|
|
2041
2073
|
return {
|
|
2042
2074
|
rows: rows2,
|
|
2043
2075
|
totalRows: totalRows2,
|
|
2044
|
-
columns
|
|
2076
|
+
columns,
|
|
2045
2077
|
complete: rows2.length === totalRows2,
|
|
2046
2078
|
source: candidate.source
|
|
2047
2079
|
};
|
|
@@ -2051,10 +2083,14 @@ function extractCanonicalRowsInfo(statusOrResult) {
|
|
|
2051
2083
|
continue;
|
|
2052
2084
|
}
|
|
2053
2085
|
const totalRows = readNumber(candidate.total) ?? rows.length;
|
|
2054
|
-
|
|
2086
|
+
const sanitized = sanitizeCsvProjectionInfo({
|
|
2055
2087
|
rows,
|
|
2088
|
+
columns: inferColumns(rows)
|
|
2089
|
+
});
|
|
2090
|
+
return {
|
|
2091
|
+
rows: sanitized.rows,
|
|
2056
2092
|
totalRows,
|
|
2057
|
-
columns:
|
|
2093
|
+
columns: sanitized.columns,
|
|
2058
2094
|
complete: rows.length === totalRows,
|
|
2059
2095
|
source: candidate.source
|
|
2060
2096
|
};
|
|
@@ -2102,13 +2138,13 @@ function summarizeSampleValue(value, depth = 0) {
|
|
|
2102
2138
|
if (typeof parsed === "number" || typeof parsed === "boolean") return parsed;
|
|
2103
2139
|
if (depth >= 3) {
|
|
2104
2140
|
if (Array.isArray(parsed)) return [];
|
|
2105
|
-
if (
|
|
2141
|
+
if (isRecord2(parsed)) return {};
|
|
2106
2142
|
return compactScalar(parsed);
|
|
2107
2143
|
}
|
|
2108
2144
|
if (Array.isArray(parsed)) {
|
|
2109
2145
|
return parsed.slice(0, 3).map((item) => summarizeSampleValue(item, depth + 1));
|
|
2110
2146
|
}
|
|
2111
|
-
if (
|
|
2147
|
+
if (isRecord2(parsed)) {
|
|
2112
2148
|
const out = {};
|
|
2113
2149
|
for (const [key, nested] of Object.entries(parsed)) {
|
|
2114
2150
|
if (["__dl", "meta", "metadata"].includes(key)) {
|
|
@@ -2138,7 +2174,7 @@ function compactCell(value) {
|
|
|
2138
2174
|
}
|
|
2139
2175
|
return `[${parsed.length} items]`;
|
|
2140
2176
|
}
|
|
2141
|
-
if (
|
|
2177
|
+
if (isRecord2(parsed)) {
|
|
2142
2178
|
for (const key of ["matched_result", "output"]) {
|
|
2143
2179
|
if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
|
|
2144
2180
|
return compactCell(parsed[key]);
|
|
@@ -2157,14 +2193,15 @@ function compactCell(value) {
|
|
|
2157
2193
|
return compactScalar(parsed, 120);
|
|
2158
2194
|
}
|
|
2159
2195
|
function buildDatasetStats(rows, totalRows = rows.length, columns = inferColumns(rows)) {
|
|
2196
|
+
const sanitized = sanitizeCsvProjectionInfo({ rows, columns });
|
|
2160
2197
|
const columnStats = {};
|
|
2161
|
-
for (const column of columns) {
|
|
2198
|
+
for (const column of sanitized.columns) {
|
|
2162
2199
|
let nonEmpty = 0;
|
|
2163
2200
|
let empty = 0;
|
|
2164
2201
|
let sampleValue;
|
|
2165
2202
|
let sampleValueType = null;
|
|
2166
2203
|
const valueCounts = /* @__PURE__ */ new Map();
|
|
2167
|
-
for (const row of rows) {
|
|
2204
|
+
for (const row of sanitized.rows) {
|
|
2168
2205
|
const raw = row[column];
|
|
2169
2206
|
const value = compactCell(raw);
|
|
2170
2207
|
if (value) {
|
|
@@ -2216,10 +2253,14 @@ function writeCanonicalRowsCsv(rowsInfo, outPath) {
|
|
|
2216
2253
|
`Run output only includes ${rowsInfo.rows.length} preview row(s) of ${rowsInfo.totalRows}; cannot export a complete CSV from this status payload yet.`
|
|
2217
2254
|
);
|
|
2218
2255
|
}
|
|
2256
|
+
const sanitized = sanitizeCsvProjectionInfo({
|
|
2257
|
+
rows: rowsInfo.rows,
|
|
2258
|
+
columns: rowsInfo.columns
|
|
2259
|
+
});
|
|
2219
2260
|
const resolved = (0, import_node_path4.resolve)(outPath);
|
|
2220
2261
|
(0, import_node_fs4.writeFileSync)(
|
|
2221
2262
|
resolved,
|
|
2222
|
-
csvStringFromRows(
|
|
2263
|
+
csvStringFromRows(sanitized.rows, sanitized.columns),
|
|
2223
2264
|
"utf-8"
|
|
2224
2265
|
);
|
|
2225
2266
|
return resolved;
|
|
@@ -2511,7 +2552,6 @@ function registerOrgCommands(program) {
|
|
|
2511
2552
|
var import_node_crypto3 = require("crypto");
|
|
2512
2553
|
var import_node_fs6 = require("fs");
|
|
2513
2554
|
var import_node_path8 = require("path");
|
|
2514
|
-
var import_commander = require("commander");
|
|
2515
2555
|
|
|
2516
2556
|
// src/plays/bundle-play-file.ts
|
|
2517
2557
|
var import_node_os5 = require("os");
|
|
@@ -2596,6 +2636,14 @@ var PLAY_SOURCE_FILE_PATTERN = /\.play\.(?:[cm]?[jt]sx?)$/i;
|
|
|
2596
2636
|
var NODE_BUILTIN_SET = new Set(
|
|
2597
2637
|
import_node_module.builtinModules.flatMap((name) => name.startsWith("node:") ? [name, name.slice(5)] : [name, `node:${name}`])
|
|
2598
2638
|
);
|
|
2639
|
+
function assertValidExportName(exportName) {
|
|
2640
|
+
if (exportName === "default") return;
|
|
2641
|
+
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(exportName)) {
|
|
2642
|
+
throw new Error(
|
|
2643
|
+
`Invalid play export name "${exportName}". Named prebuilt exports must be valid JavaScript identifiers.`
|
|
2644
|
+
);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2599
2647
|
function sha256(value) {
|
|
2600
2648
|
return (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
2601
2649
|
}
|
|
@@ -2790,6 +2838,29 @@ function workersPlayEntryAliasPlugin(playFilePath) {
|
|
|
2790
2838
|
}
|
|
2791
2839
|
};
|
|
2792
2840
|
}
|
|
2841
|
+
function workersNamedPlayEntryAliasPlugin(playFilePath, exportName) {
|
|
2842
|
+
return {
|
|
2843
|
+
name: "deepline-workers-named-play-entry-alias",
|
|
2844
|
+
setup(buildContext) {
|
|
2845
|
+
buildContext.onResolve(
|
|
2846
|
+
{ filter: new RegExp(`^${WORKERS_PLAY_ENTRY_VIRTUAL}$`) },
|
|
2847
|
+
() => ({
|
|
2848
|
+
path: `${playFilePath}.${exportName}.entry.ts`,
|
|
2849
|
+
namespace: "deepline-named-play-entry"
|
|
2850
|
+
})
|
|
2851
|
+
);
|
|
2852
|
+
buildContext.onLoad(
|
|
2853
|
+
{ filter: /.*/, namespace: "deepline-named-play-entry" },
|
|
2854
|
+
() => ({
|
|
2855
|
+
contents: `export { ${exportName} as default } from ${JSON.stringify(playFilePath)};
|
|
2856
|
+
`,
|
|
2857
|
+
loader: "ts",
|
|
2858
|
+
resolveDir: (0, import_node_path5.dirname)(playFilePath)
|
|
2859
|
+
})
|
|
2860
|
+
);
|
|
2861
|
+
}
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2793
2864
|
function workersNodeBuiltinStubPlugin() {
|
|
2794
2865
|
const UNSUPPORTED = /* @__PURE__ */ new Set(["node:fs", "node:fs/promises", "node:os", "node:child_process"]);
|
|
2795
2866
|
return {
|
|
@@ -3221,11 +3292,20 @@ function getBundleSizeError(filePath, bundledCode, artifactKind) {
|
|
|
3221
3292
|
}
|
|
3222
3293
|
return null;
|
|
3223
3294
|
}
|
|
3224
|
-
async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter) {
|
|
3295
|
+
async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter, exportName) {
|
|
3225
3296
|
const sdkAliasPlugin = localSdkAliasPlugin(adapter);
|
|
3226
3297
|
const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
|
|
3298
|
+
const namedExportShim = exportName === "default" ? null : `export { ${exportName} as default } from ${JSON.stringify(entryFile)};
|
|
3299
|
+
`;
|
|
3227
3300
|
const result = await (0, import_esbuild.build)({
|
|
3228
|
-
|
|
3301
|
+
...namedExportShim ? {
|
|
3302
|
+
stdin: {
|
|
3303
|
+
contents: namedExportShim,
|
|
3304
|
+
resolveDir: (0, import_node_path5.dirname)(entryFile),
|
|
3305
|
+
sourcefile: `${(0, import_node_path5.basename)(entryFile)}.${exportName}.entry.ts`,
|
|
3306
|
+
loader: "ts"
|
|
3307
|
+
}
|
|
3308
|
+
} : { entryPoints: [entryFile] },
|
|
3229
3309
|
absWorkingDir: adapter.projectRoot,
|
|
3230
3310
|
bundle: true,
|
|
3231
3311
|
format: "cjs",
|
|
@@ -3253,10 +3333,10 @@ async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter
|
|
|
3253
3333
|
outputExtension: "cjs"
|
|
3254
3334
|
};
|
|
3255
3335
|
}
|
|
3256
|
-
async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies, adapter) {
|
|
3336
|
+
async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies, adapter, exportName) {
|
|
3257
3337
|
const sdkAliasPlugin = localSdkAliasPlugin(adapter, { workersRuntime: true });
|
|
3258
3338
|
const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
|
|
3259
|
-
const playEntryAlias = workersPlayEntryAliasPlugin(playEntryFile);
|
|
3339
|
+
const playEntryAlias = exportName === "default" ? workersPlayEntryAliasPlugin(playEntryFile) : workersNamedPlayEntryAliasPlugin(playEntryFile, exportName);
|
|
3260
3340
|
const result = await (0, import_esbuild.build)({
|
|
3261
3341
|
// Entry is the Workers harness; it imports the play via the virtual
|
|
3262
3342
|
// `deepline-play-entry` alias resolved by workersPlayEntryAliasPlugin.
|
|
@@ -3327,10 +3407,16 @@ async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies,
|
|
|
3327
3407
|
async function bundlePlayFile(filePath, options) {
|
|
3328
3408
|
const adapter = options.adapter;
|
|
3329
3409
|
const target = options.target ?? PLAY_ARTIFACT_KINDS.cjsNode20;
|
|
3410
|
+
const exportName = options.exportName?.trim() || "default";
|
|
3411
|
+
assertValidExportName(exportName);
|
|
3330
3412
|
const absolutePath = await normalizeLocalPath(filePath);
|
|
3331
3413
|
adapter.warnAboutNonDevelopmentBundling?.(absolutePath);
|
|
3332
3414
|
try {
|
|
3333
3415
|
const analysis = await analyzeSourceGraph(absolutePath, adapter);
|
|
3416
|
+
analysis.graphHash = sha256(
|
|
3417
|
+
`${analysis.graphHash}
|
|
3418
|
+
entry-export:${exportName}`
|
|
3419
|
+
);
|
|
3334
3420
|
if (target === PLAY_ARTIFACT_KINDS.esmWorkers) {
|
|
3335
3421
|
const harnessFingerprint = await computeWorkersHarnessFingerprintWithAdapter(adapter);
|
|
3336
3422
|
analysis.graphHash = sha256(
|
|
@@ -3382,7 +3468,7 @@ workers-harness:${harnessFingerprint}`
|
|
|
3382
3468
|
errors: typecheckErrors
|
|
3383
3469
|
};
|
|
3384
3470
|
}
|
|
3385
|
-
const buildOutcome = target === PLAY_ARTIFACT_KINDS.esmWorkers ? await runEsbuildForEsmWorkers(absolutePath, analysis.importedPlayDependencies, adapter) : await runEsbuildForCjsNode(absolutePath, analysis.importedPlayDependencies, adapter);
|
|
3471
|
+
const buildOutcome = target === PLAY_ARTIFACT_KINDS.esmWorkers ? await runEsbuildForEsmWorkers(absolutePath, analysis.importedPlayDependencies, adapter, exportName) : await runEsbuildForCjsNode(absolutePath, analysis.importedPlayDependencies, adapter, exportName);
|
|
3386
3472
|
if (Array.isArray(buildOutcome)) {
|
|
3387
3473
|
return {
|
|
3388
3474
|
success: false,
|
|
@@ -3392,7 +3478,8 @@ workers-harness:${harnessFingerprint}`
|
|
|
3392
3478
|
}
|
|
3393
3479
|
const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
|
|
3394
3480
|
const normalizedSourceMap = normalizeSourceMapForRuntime(sourceMapText);
|
|
3395
|
-
const
|
|
3481
|
+
const virtualBaseName = exportName === "default" ? (0, import_node_path5.basename)(absolutePath).replace(/\.[^.]+$/, "") : `${(0, import_node_path5.basename)(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
|
|
3482
|
+
const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
|
|
3396
3483
|
const executableCode = `${bundledCode}
|
|
3397
3484
|
//# sourceMappingURL=${(0, import_node_path5.basename)(virtualFilename)}.map
|
|
3398
3485
|
`;
|
|
@@ -3776,7 +3863,7 @@ function createSdkPlayBundlingAdapter() {
|
|
|
3776
3863
|
sdkSourceRoot: SDK_SOURCE_ROOT,
|
|
3777
3864
|
sdkPackageJson: SDK_PACKAGE_JSON,
|
|
3778
3865
|
sdkEntryFile: SDK_ENTRY_FILE,
|
|
3779
|
-
sdkTypesEntryFile: (0, import_node_fs5.existsSync)(SDK_TYPES_ENTRY_FILE) ? SDK_TYPES_ENTRY_FILE : SDK_ENTRY_FILE,
|
|
3866
|
+
sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : (0, import_node_fs5.existsSync)(SDK_TYPES_ENTRY_FILE) ? SDK_TYPES_ENTRY_FILE : SDK_ENTRY_FILE,
|
|
3780
3867
|
sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
|
|
3781
3868
|
workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
|
|
3782
3869
|
workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
|
|
@@ -3787,6 +3874,7 @@ function createSdkPlayBundlingAdapter() {
|
|
|
3787
3874
|
async function bundlePlayFile2(filePath, options = {}) {
|
|
3788
3875
|
return bundlePlayFile(filePath, {
|
|
3789
3876
|
target: options.target ?? defaultPlayBundleTarget(),
|
|
3877
|
+
exportName: options.exportName,
|
|
3790
3878
|
adapter: createSdkPlayBundlingAdapter()
|
|
3791
3879
|
});
|
|
3792
3880
|
}
|
|
@@ -3936,54 +4024,6 @@ function createCliProgress(enabled) {
|
|
|
3936
4024
|
return progress;
|
|
3937
4025
|
}
|
|
3938
4026
|
|
|
3939
|
-
// src/cli/trace.ts
|
|
3940
|
-
var cliTraceStartedAt = Date.now();
|
|
3941
|
-
function isTruthyEnv(value) {
|
|
3942
|
-
return value === "1" || value === "true" || value === "yes";
|
|
3943
|
-
}
|
|
3944
|
-
function isCliTraceEnabled() {
|
|
3945
|
-
return isTruthyEnv(process.env.DEEPLINE_CLI_TRACE);
|
|
3946
|
-
}
|
|
3947
|
-
function recordCliTrace(event) {
|
|
3948
|
-
if (!isCliTraceEnabled()) {
|
|
3949
|
-
return;
|
|
3950
|
-
}
|
|
3951
|
-
const now = Date.now();
|
|
3952
|
-
const payload = {
|
|
3953
|
-
ts: now,
|
|
3954
|
-
source: "cli",
|
|
3955
|
-
sinceStartMs: now - cliTraceStartedAt,
|
|
3956
|
-
...event
|
|
3957
|
-
};
|
|
3958
|
-
process.stderr.write(`[cli-trace] ${JSON.stringify(payload)}
|
|
3959
|
-
`);
|
|
3960
|
-
}
|
|
3961
|
-
async function traceCliSpan(phase, fields, run) {
|
|
3962
|
-
if (!isCliTraceEnabled()) {
|
|
3963
|
-
return run();
|
|
3964
|
-
}
|
|
3965
|
-
const startedAt = Date.now();
|
|
3966
|
-
try {
|
|
3967
|
-
const result = await run();
|
|
3968
|
-
recordCliTrace({
|
|
3969
|
-
phase,
|
|
3970
|
-
ms: Date.now() - startedAt,
|
|
3971
|
-
ok: true,
|
|
3972
|
-
...fields
|
|
3973
|
-
});
|
|
3974
|
-
return result;
|
|
3975
|
-
} catch (error) {
|
|
3976
|
-
recordCliTrace({
|
|
3977
|
-
phase,
|
|
3978
|
-
ms: Date.now() - startedAt,
|
|
3979
|
-
ok: false,
|
|
3980
|
-
error: error instanceof Error ? error.message : String(error),
|
|
3981
|
-
...fields
|
|
3982
|
-
});
|
|
3983
|
-
throw error;
|
|
3984
|
-
}
|
|
3985
|
-
}
|
|
3986
|
-
|
|
3987
4027
|
// src/cli/commands/play.ts
|
|
3988
4028
|
function parseReferencedPlayTarget(target) {
|
|
3989
4029
|
const trimmed = target.trim();
|
|
@@ -4031,67 +4071,6 @@ function defaultMaterializedPlayPath(reference) {
|
|
|
4031
4071
|
const safeName = playName.trim().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
4032
4072
|
return (0, import_node_path8.resolve)(`${safeName || "play"}.play.ts`);
|
|
4033
4073
|
}
|
|
4034
|
-
function sanitizeGeneratedPlayName(value) {
|
|
4035
|
-
return value.trim().toLowerCase().replace(/^prebuilt\//, "").replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "play";
|
|
4036
|
-
}
|
|
4037
|
-
function buildGeneratedCsvWrapperSource(input) {
|
|
4038
|
-
return `import { definePlay } from 'deepline';
|
|
4039
|
-
|
|
4040
|
-
export default definePlay(
|
|
4041
|
-
${JSON.stringify(input.wrapperName)},
|
|
4042
|
-
async (ctx, input: Record<string, unknown> & { file: string }) => {
|
|
4043
|
-
const rows = await ctx.csv<Record<string, unknown>>(input.file);
|
|
4044
|
-
const constants = Object.fromEntries(
|
|
4045
|
-
Object.entries(input).filter(([key]) => key !== 'file'),
|
|
4046
|
-
);
|
|
4047
|
-
|
|
4048
|
-
const mappedRows = await ctx
|
|
4049
|
-
.map('csv_rows', rows, {
|
|
4050
|
-
key: (row, index) =>
|
|
4051
|
-
String(
|
|
4052
|
-
row.id ??
|
|
4053
|
-
row.lead_id ??
|
|
4054
|
-
row.email ??
|
|
4055
|
-
row.linkedin_url ??
|
|
4056
|
-
row.domain ??
|
|
4057
|
-
index,
|
|
4058
|
-
),
|
|
4059
|
-
})
|
|
4060
|
-
.step('result', (row, rowCtx) =>
|
|
4061
|
-
rowCtx.runPlay(
|
|
4062
|
-
'row_play',
|
|
4063
|
-
${JSON.stringify(input.playRef)},
|
|
4064
|
-
{
|
|
4065
|
-
...constants,
|
|
4066
|
-
...row,
|
|
4067
|
-
},
|
|
4068
|
-
{
|
|
4069
|
-
description: 'Run the source play for this CSV row.',
|
|
4070
|
-
},
|
|
4071
|
-
),
|
|
4072
|
-
)
|
|
4073
|
-
.run({ description: 'Run the source play once per CSV row.' });
|
|
4074
|
-
|
|
4075
|
-
return { rows: mappedRows };
|
|
4076
|
-
},
|
|
4077
|
-
);
|
|
4078
|
-
`;
|
|
4079
|
-
}
|
|
4080
|
-
function writeGeneratedCsvWrapperPlay(playRef) {
|
|
4081
|
-
const baseName = sanitizeGeneratedPlayName(
|
|
4082
|
-
parseReferencedPlayTarget(playRef).unqualifiedPlayName
|
|
4083
|
-
);
|
|
4084
|
-
const wrapperName = `${baseName}-csv`;
|
|
4085
|
-
const outputDir = (0, import_node_path8.resolve)(".deepline", "generated");
|
|
4086
|
-
const outputPath = (0, import_node_path8.join)(outputDir, `${wrapperName}.play.ts`);
|
|
4087
|
-
(0, import_node_fs6.mkdirSync)(outputDir, { recursive: true });
|
|
4088
|
-
(0, import_node_fs6.writeFileSync)(
|
|
4089
|
-
outputPath,
|
|
4090
|
-
buildGeneratedCsvWrapperSource({ wrapperName, playRef }),
|
|
4091
|
-
"utf-8"
|
|
4092
|
-
);
|
|
4093
|
-
return outputPath;
|
|
4094
|
-
}
|
|
4095
4074
|
function materializeRemotePlaySource(input) {
|
|
4096
4075
|
if (isFileTarget(input.target)) {
|
|
4097
4076
|
return null;
|
|
@@ -4157,7 +4136,10 @@ function looksLikeFilePath(target) {
|
|
|
4157
4136
|
if (target.trim().toLowerCase().startsWith("prebuilt/")) {
|
|
4158
4137
|
return false;
|
|
4159
4138
|
}
|
|
4160
|
-
|
|
4139
|
+
if (target.startsWith("./") || target.startsWith("../") || target.startsWith("/") || target.startsWith("~/")) {
|
|
4140
|
+
return true;
|
|
4141
|
+
}
|
|
4142
|
+
return target.includes("\\") || /\.(ts|js|mjs|play\.ts)$/.test(target);
|
|
4161
4143
|
}
|
|
4162
4144
|
function parsePositiveInteger2(value, flagName) {
|
|
4163
4145
|
const parsed = Number.parseInt(value, 10);
|
|
@@ -4174,6 +4156,133 @@ function parseJsonInput(raw) {
|
|
|
4174
4156
|
}
|
|
4175
4157
|
return parsed;
|
|
4176
4158
|
}
|
|
4159
|
+
function parseInputFieldFlag(rawFlag, nextArg) {
|
|
4160
|
+
const flag = rawFlag.slice(2);
|
|
4161
|
+
const equalsIndex = flag.indexOf("=");
|
|
4162
|
+
if (equalsIndex > 0) {
|
|
4163
|
+
const path = flag.slice(0, equalsIndex).trim();
|
|
4164
|
+
const value = flag.slice(equalsIndex + 1);
|
|
4165
|
+
if (!path) {
|
|
4166
|
+
throw new Error(`Invalid play input flag: ${rawFlag}`);
|
|
4167
|
+
}
|
|
4168
|
+
return { path, value };
|
|
4169
|
+
}
|
|
4170
|
+
if (!nextArg || nextArg.startsWith("--")) {
|
|
4171
|
+
throw new Error(`Play input flag ${rawFlag} requires a value.`);
|
|
4172
|
+
}
|
|
4173
|
+
return { path: flag, value: nextArg };
|
|
4174
|
+
}
|
|
4175
|
+
function parseInputFlagValue(raw) {
|
|
4176
|
+
const trimmed = raw.trim();
|
|
4177
|
+
if (!trimmed) return "";
|
|
4178
|
+
if (trimmed === "true" || trimmed === "false" || trimmed === "null" || trimmed.startsWith("{") || trimmed.startsWith("[") || /^-?\d+(\.\d+)?$/.test(trimmed)) {
|
|
4179
|
+
try {
|
|
4180
|
+
return JSON.parse(trimmed);
|
|
4181
|
+
} catch {
|
|
4182
|
+
return raw;
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
return raw;
|
|
4186
|
+
}
|
|
4187
|
+
function getDottedInputValue(input, path) {
|
|
4188
|
+
const parts = path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
4189
|
+
let cursor = input;
|
|
4190
|
+
for (const part of parts) {
|
|
4191
|
+
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) {
|
|
4192
|
+
return void 0;
|
|
4193
|
+
}
|
|
4194
|
+
cursor = cursor[part];
|
|
4195
|
+
}
|
|
4196
|
+
return cursor;
|
|
4197
|
+
}
|
|
4198
|
+
function setDottedInputValue(input, path, value) {
|
|
4199
|
+
const parts = path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
4200
|
+
if (parts.length === 0) {
|
|
4201
|
+
throw new Error(`Invalid play input flag path: ${path}`);
|
|
4202
|
+
}
|
|
4203
|
+
let cursor = input;
|
|
4204
|
+
for (const part of parts.slice(0, -1)) {
|
|
4205
|
+
const existing = cursor[part];
|
|
4206
|
+
if (existing !== void 0 && (!existing || typeof existing !== "object" || Array.isArray(existing))) {
|
|
4207
|
+
throw new Error(
|
|
4208
|
+
`Cannot set --${path}; input.${part} is already a non-object value.`
|
|
4209
|
+
);
|
|
4210
|
+
}
|
|
4211
|
+
if (!existing) {
|
|
4212
|
+
cursor[part] = {};
|
|
4213
|
+
}
|
|
4214
|
+
cursor = cursor[part];
|
|
4215
|
+
}
|
|
4216
|
+
cursor[parts[parts.length - 1]] = value;
|
|
4217
|
+
}
|
|
4218
|
+
function schemaMetadata(schema, key) {
|
|
4219
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return null;
|
|
4220
|
+
const value = schema[key];
|
|
4221
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
4222
|
+
}
|
|
4223
|
+
function stringMetadata(metadata, key) {
|
|
4224
|
+
const value = metadata?.[key];
|
|
4225
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
4226
|
+
}
|
|
4227
|
+
function inputFieldFromCsvArg(csvArg) {
|
|
4228
|
+
if (typeof csvArg !== "string") return null;
|
|
4229
|
+
const match = /^input\.([A-Za-z_$][\w$]*)$/.exec(csvArg.trim());
|
|
4230
|
+
return match?.[1] ?? null;
|
|
4231
|
+
}
|
|
4232
|
+
function fileInputBindingsFromPlaySchema(inputSchema) {
|
|
4233
|
+
const csvInput = schemaMetadata(inputSchema, "csvInput");
|
|
4234
|
+
if (!csvInput) return [];
|
|
4235
|
+
return [
|
|
4236
|
+
{
|
|
4237
|
+
inputPath: stringMetadata(csvInput, "inputField") ?? "csv"
|
|
4238
|
+
}
|
|
4239
|
+
];
|
|
4240
|
+
}
|
|
4241
|
+
function fileInputBindingsFromStaticPipeline(staticPipeline) {
|
|
4242
|
+
if (!staticPipeline || typeof staticPipeline !== "object" || Array.isArray(staticPipeline)) {
|
|
4243
|
+
return [];
|
|
4244
|
+
}
|
|
4245
|
+
const inputField = inputFieldFromCsvArg(
|
|
4246
|
+
staticPipeline.csvArg
|
|
4247
|
+
);
|
|
4248
|
+
return inputField ? [{ inputPath: inputField }] : [];
|
|
4249
|
+
}
|
|
4250
|
+
function isLocalFilePathValue(value) {
|
|
4251
|
+
if (typeof value !== "string" || !value.trim()) return false;
|
|
4252
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
|
|
4253
|
+
return (0, import_node_fs6.existsSync)((0, import_node_path8.resolve)(value));
|
|
4254
|
+
}
|
|
4255
|
+
async function stageFileInputArgs(input) {
|
|
4256
|
+
const uniqueBindings = [
|
|
4257
|
+
...new Map(input.bindings.map((binding) => [binding.inputPath, binding])).values()
|
|
4258
|
+
];
|
|
4259
|
+
const localFiles = uniqueBindings.flatMap((binding) => {
|
|
4260
|
+
const value = getDottedInputValue(input.runtimeInput, binding.inputPath);
|
|
4261
|
+
if (!isLocalFilePathValue(value)) return [];
|
|
4262
|
+
const absolutePath = (0, import_node_path8.resolve)(value);
|
|
4263
|
+
return [{ binding, absolutePath, logicalPath: (0, import_node_path8.basename)(absolutePath) }];
|
|
4264
|
+
});
|
|
4265
|
+
if (localFiles.length === 0) {
|
|
4266
|
+
return { inputFile: null, packagedFiles: [] };
|
|
4267
|
+
}
|
|
4268
|
+
input.progress.phase(
|
|
4269
|
+
localFiles.length === 1 ? "staging input file" : "staging input files"
|
|
4270
|
+
);
|
|
4271
|
+
const staged = await input.client.stagePlayFiles(
|
|
4272
|
+
localFiles.map((file) => stageFile(file.logicalPath, file.absolutePath))
|
|
4273
|
+
);
|
|
4274
|
+
for (const [index, file] of localFiles.entries()) {
|
|
4275
|
+
setDottedInputValue(input.runtimeInput, file.binding.inputPath, file.logicalPath);
|
|
4276
|
+
const stagedFile = staged[index];
|
|
4277
|
+
if (stagedFile && stagedFile.logicalPath !== file.logicalPath) {
|
|
4278
|
+
setDottedInputValue(input.runtimeInput, file.binding.inputPath, stagedFile.logicalPath);
|
|
4279
|
+
}
|
|
4280
|
+
}
|
|
4281
|
+
return {
|
|
4282
|
+
inputFile: staged[0] ?? null,
|
|
4283
|
+
packagedFiles: staged.slice(1)
|
|
4284
|
+
};
|
|
4285
|
+
}
|
|
4177
4286
|
function stageFile(logicalPath, absolutePath) {
|
|
4178
4287
|
const buffer = (0, import_node_fs6.readFileSync)(absolutePath);
|
|
4179
4288
|
return {
|
|
@@ -4582,24 +4691,10 @@ async function startAndWaitForPlayCompletionByStream(input) {
|
|
|
4582
4691
|
},
|
|
4583
4692
|
Math.max(1, input.waitTimeoutMs)
|
|
4584
4693
|
);
|
|
4585
|
-
recordCliTrace({
|
|
4586
|
-
phase: "cli.start_stream_request",
|
|
4587
|
-
playName: input.playName
|
|
4588
|
-
});
|
|
4589
4694
|
try {
|
|
4590
|
-
let eventCount = 0;
|
|
4591
4695
|
for await (const event of input.client.startPlayRunStream(input.request, {
|
|
4592
4696
|
signal: controller.signal
|
|
4593
4697
|
})) {
|
|
4594
|
-
eventCount += 1;
|
|
4595
|
-
if (eventCount === 1) {
|
|
4596
|
-
recordCliTrace({
|
|
4597
|
-
phase: "cli.start_stream_first_event",
|
|
4598
|
-
ms: Date.now() - startedAt,
|
|
4599
|
-
playName: input.playName,
|
|
4600
|
-
eventType: event.type
|
|
4601
|
-
});
|
|
4602
|
-
}
|
|
4603
4698
|
const eventRunId = getEventPayload(event).runId;
|
|
4604
4699
|
if (typeof eventRunId === "string" && eventRunId && eventRunId !== "pending") {
|
|
4605
4700
|
lastKnownWorkflowId = eventRunId;
|
|
@@ -4640,14 +4735,6 @@ async function startAndWaitForPlayCompletionByStream(input) {
|
|
|
4640
4735
|
});
|
|
4641
4736
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
4642
4737
|
if (finalStatus) {
|
|
4643
|
-
recordCliTrace({
|
|
4644
|
-
phase: "cli.start_stream_final_event",
|
|
4645
|
-
ms: Date.now() - startedAt,
|
|
4646
|
-
playName: input.playName,
|
|
4647
|
-
runId: finalStatus.runId,
|
|
4648
|
-
status: finalStatus.status,
|
|
4649
|
-
eventCount
|
|
4650
|
-
});
|
|
4651
4738
|
return finalStatus;
|
|
4652
4739
|
}
|
|
4653
4740
|
}
|
|
@@ -4926,7 +5013,6 @@ function buildRunNextCommands(runId) {
|
|
|
4926
5013
|
return {
|
|
4927
5014
|
exportCsv: `deepline runs export ${runId} --out output.csv`,
|
|
4928
5015
|
status: `deepline runs status ${runId} --json`,
|
|
4929
|
-
fullStatus: `deepline runs status ${runId} --json --full`,
|
|
4930
5016
|
logs: `deepline runs logs ${runId}`
|
|
4931
5017
|
};
|
|
4932
5018
|
}
|
|
@@ -4950,12 +5036,26 @@ function compactPlayStatus(status, options) {
|
|
|
4950
5036
|
...result !== void 0 ? { result } : {},
|
|
4951
5037
|
...status.resultView ? { resultView: status.resultView } : {},
|
|
4952
5038
|
...datasetStats ? { dataset_stats: datasetStats } : {},
|
|
4953
|
-
...rowsInfo ? { previewRows: rowsInfo.rows.slice(0,
|
|
5039
|
+
...rowsInfo ? { previewRows: rowsInfo.rows.slice(0, 5) } : {},
|
|
4954
5040
|
...billing ? { billing } : {},
|
|
4955
5041
|
...status.run ? { run: status.run } : {},
|
|
4956
5042
|
next: buildRunNextCommands(status.runId)
|
|
4957
5043
|
};
|
|
4958
5044
|
}
|
|
5045
|
+
function enrichPlayStatusWithDatasetStats(status) {
|
|
5046
|
+
const rowsInfo = extractCanonicalRowsInfo(status);
|
|
5047
|
+
if (!rowsInfo?.complete) {
|
|
5048
|
+
return status;
|
|
5049
|
+
}
|
|
5050
|
+
return {
|
|
5051
|
+
...status,
|
|
5052
|
+
dataset_stats: buildDatasetStats(
|
|
5053
|
+
rowsInfo.rows,
|
|
5054
|
+
rowsInfo.totalRows,
|
|
5055
|
+
rowsInfo.columns
|
|
5056
|
+
)
|
|
5057
|
+
};
|
|
5058
|
+
}
|
|
4959
5059
|
function formatDatasetStatsLines(datasetStats) {
|
|
4960
5060
|
if (!datasetStats) {
|
|
4961
5061
|
return [];
|
|
@@ -4965,10 +5065,10 @@ function formatDatasetStatsLines(datasetStats) {
|
|
|
4965
5065
|
0,
|
|
4966
5066
|
12
|
|
4967
5067
|
)) {
|
|
4968
|
-
const topValues = stat3.top_values ? `,
|
|
4969
|
-
const sample = stat3.sample_value !== void 0 ? `,
|
|
5068
|
+
const topValues = stat3.top_values ? `, top_values=${Object.entries(stat3.top_values).slice(0, 3).map(([value, count]) => `${value}=${count}`).join(", ")}` : "";
|
|
5069
|
+
const sample = stat3.sample_value !== void 0 ? `, sample_value=${JSON.stringify(stat3.sample_value)}` : "";
|
|
4970
5070
|
lines.push(
|
|
4971
|
-
` ${column}:
|
|
5071
|
+
` ${column}: non_empty=${stat3.non_empty}, unique=${stat3.unique}${topValues}${sample}`
|
|
4972
5072
|
);
|
|
4973
5073
|
}
|
|
4974
5074
|
return lines;
|
|
@@ -4977,7 +5077,7 @@ function writePlayResult(status, jsonOutput, options) {
|
|
|
4977
5077
|
if (jsonOutput) {
|
|
4978
5078
|
process.stdout.write(
|
|
4979
5079
|
`${JSON.stringify(
|
|
4980
|
-
options?.fullJson ? status : compactPlayStatus(status, options)
|
|
5080
|
+
options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status, options)
|
|
4981
5081
|
)}
|
|
4982
5082
|
`
|
|
4983
5083
|
);
|
|
@@ -5126,10 +5226,9 @@ function writeStartedPlayRun(input) {
|
|
|
5126
5226
|
console.log(output);
|
|
5127
5227
|
}
|
|
5128
5228
|
function parsePlayRunOptions(args) {
|
|
5129
|
-
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--
|
|
5229
|
+
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]";
|
|
5130
5230
|
let filePath = null;
|
|
5131
5231
|
let playName = null;
|
|
5132
|
-
let csvPath = null;
|
|
5133
5232
|
let input = null;
|
|
5134
5233
|
let revisionId = null;
|
|
5135
5234
|
let revisionSelector = null;
|
|
@@ -5150,10 +5249,6 @@ function parsePlayRunOptions(args) {
|
|
|
5150
5249
|
playName = parseReferencedPlayTarget(args[++index]).playName;
|
|
5151
5250
|
continue;
|
|
5152
5251
|
}
|
|
5153
|
-
if (arg === "--csv" && args[index + 1]) {
|
|
5154
|
-
csvPath = (0, import_node_path8.resolve)(args[++index]);
|
|
5155
|
-
continue;
|
|
5156
|
-
}
|
|
5157
5252
|
if ((arg === "--input" || arg === "-i") && args[index + 1]) {
|
|
5158
5253
|
input = parseJsonInput(args[++index]);
|
|
5159
5254
|
continue;
|
|
@@ -5203,8 +5298,13 @@ function parsePlayRunOptions(args) {
|
|
|
5203
5298
|
continue;
|
|
5204
5299
|
}
|
|
5205
5300
|
if (arg.startsWith("--")) {
|
|
5206
|
-
|
|
5207
|
-
|
|
5301
|
+
const { path, value } = parseInputFieldFlag(arg, args[index + 1]);
|
|
5302
|
+
input ??= {};
|
|
5303
|
+
setDottedInputValue(input, path, parseInputFlagValue(value));
|
|
5304
|
+
if (!arg.includes("=")) {
|
|
5305
|
+
index += 1;
|
|
5306
|
+
}
|
|
5307
|
+
continue;
|
|
5208
5308
|
}
|
|
5209
5309
|
if (!arg.startsWith("--") && !filePath && !playName) {
|
|
5210
5310
|
if (isFileTarget(arg) || looksLikeFilePath(arg)) {
|
|
@@ -5240,7 +5340,6 @@ ${usage}`);
|
|
|
5240
5340
|
}
|
|
5241
5341
|
return {
|
|
5242
5342
|
target: filePath ? { kind: "file", path: filePath } : { kind: "name", name: playName },
|
|
5243
|
-
csvPath,
|
|
5244
5343
|
input,
|
|
5245
5344
|
revisionId,
|
|
5246
5345
|
revisionSelector,
|
|
@@ -5315,34 +5414,12 @@ async function handleFileBackedRun(options) {
|
|
|
5315
5414
|
const client = new DeeplineClient();
|
|
5316
5415
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
5317
5416
|
const absolutePlayPath = (0, import_node_path8.resolve)(options.target.path);
|
|
5318
|
-
recordCliTrace({
|
|
5319
|
-
phase: "cli.play_run_file_start",
|
|
5320
|
-
playPath: absolutePlayPath,
|
|
5321
|
-
watch: options.watch,
|
|
5322
|
-
hasCsv: Boolean(options.csvPath),
|
|
5323
|
-
force: options.force
|
|
5324
|
-
});
|
|
5325
5417
|
progress.phase("compiling play");
|
|
5326
|
-
const readSourceStartedAt = Date.now();
|
|
5327
5418
|
const sourceCode = (0, import_node_fs6.readFileSync)(absolutePlayPath, "utf-8");
|
|
5328
|
-
recordCliTrace({
|
|
5329
|
-
phase: "cli.read_play_source",
|
|
5330
|
-
ms: Date.now() - readSourceStartedAt,
|
|
5331
|
-
bytes: sourceCode.length,
|
|
5332
|
-
playPath: absolutePlayPath
|
|
5333
|
-
});
|
|
5334
5419
|
let graph;
|
|
5335
5420
|
try {
|
|
5336
|
-
graph = await
|
|
5337
|
-
|
|
5338
|
-
{ playPath: absolutePlayPath },
|
|
5339
|
-
() => collectBundledPlayGraph(absolutePlayPath)
|
|
5340
|
-
);
|
|
5341
|
-
await traceCliSpan(
|
|
5342
|
-
"cli.compile_play_manifest",
|
|
5343
|
-
{ playPath: absolutePlayPath, nodeCount: graph.nodes.size },
|
|
5344
|
-
() => compileBundledPlayGraphManifests(client, graph)
|
|
5345
|
-
);
|
|
5421
|
+
graph = await collectBundledPlayGraph(absolutePlayPath);
|
|
5422
|
+
await compileBundledPlayGraphManifests(client, graph);
|
|
5346
5423
|
progress.phase("compiled play");
|
|
5347
5424
|
} catch (error) {
|
|
5348
5425
|
progress.fail();
|
|
@@ -5353,87 +5430,58 @@ async function handleFileBackedRun(options) {
|
|
|
5353
5430
|
const playName = bundleResult.playName ?? extractPlayName(sourceCode, absolutePlayPath);
|
|
5354
5431
|
try {
|
|
5355
5432
|
progress.phase("publishing imported plays");
|
|
5356
|
-
await
|
|
5357
|
-
"cli.publish_imported_plays",
|
|
5358
|
-
{ playName, nodeCount: graph.nodes.size },
|
|
5359
|
-
() => publishImportedPlayDependencies(client, graph)
|
|
5360
|
-
);
|
|
5433
|
+
await publishImportedPlayDependencies(client, graph);
|
|
5361
5434
|
} catch (error) {
|
|
5362
5435
|
progress.fail();
|
|
5363
5436
|
console.error(error instanceof Error ? error.message : String(error));
|
|
5364
5437
|
return 1;
|
|
5365
5438
|
}
|
|
5366
5439
|
const runtimeInput = options.input ? { ...options.input } : {};
|
|
5367
|
-
const prepareFilesStartedAt = Date.now();
|
|
5368
5440
|
const packagedFileUploads = bundleResult.packagedFiles.map(
|
|
5369
5441
|
(file) => stageFile(file.logicalPath, file.absolutePath)
|
|
5370
5442
|
);
|
|
5371
|
-
const
|
|
5372
|
-
|
|
5373
|
-
runtimeInput
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
playName,
|
|
5379
|
-
packagedFileCount: packagedFileUploads.length,
|
|
5380
|
-
hasInputFile: Boolean(inputFileUpload)
|
|
5443
|
+
const stagedFileInputs = await stageFileInputArgs({
|
|
5444
|
+
client,
|
|
5445
|
+
runtimeInput,
|
|
5446
|
+
bindings: fileInputBindingsFromStaticPipeline(
|
|
5447
|
+
requireCompilerManifest(bundleResult).staticPipeline
|
|
5448
|
+
),
|
|
5449
|
+
progress
|
|
5381
5450
|
});
|
|
5382
5451
|
const startRequest = {
|
|
5383
5452
|
name: playName,
|
|
5384
5453
|
sourceCode: bundleResult.sourceCode,
|
|
5385
5454
|
runtimeArtifact: bundleResult.artifact,
|
|
5386
5455
|
compilerManifest: requireCompilerManifest(bundleResult),
|
|
5387
|
-
inputFileUpload,
|
|
5388
5456
|
packagedFileUploads,
|
|
5389
5457
|
...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
|
|
5458
|
+
...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
|
|
5459
|
+
...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
|
|
5390
5460
|
...options.force ? { force: true } : {}
|
|
5391
5461
|
};
|
|
5392
5462
|
if (options.watch) {
|
|
5393
5463
|
progress.phase("starting run");
|
|
5394
|
-
const finalStatus = await
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
() => startAndWaitForPlayCompletionByStream({
|
|
5398
|
-
client,
|
|
5399
|
-
request: startRequest,
|
|
5400
|
-
playName,
|
|
5401
|
-
jsonOutput: options.jsonOutput,
|
|
5402
|
-
emitLogs: options.emitLogs,
|
|
5403
|
-
waitTimeoutMs: options.waitTimeoutMs,
|
|
5404
|
-
progress
|
|
5405
|
-
})
|
|
5406
|
-
);
|
|
5407
|
-
const exportStartedAt = Date.now();
|
|
5408
|
-
const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
|
|
5409
|
-
recordCliTrace({
|
|
5410
|
-
phase: "cli.export_rows",
|
|
5411
|
-
ms: Date.now() - exportStartedAt,
|
|
5464
|
+
const finalStatus = await startAndWaitForPlayCompletionByStream({
|
|
5465
|
+
client,
|
|
5466
|
+
request: startRequest,
|
|
5412
5467
|
playName,
|
|
5413
|
-
|
|
5468
|
+
jsonOutput: options.jsonOutput,
|
|
5469
|
+
emitLogs: options.emitLogs,
|
|
5470
|
+
waitTimeoutMs: options.waitTimeoutMs,
|
|
5471
|
+
progress
|
|
5414
5472
|
});
|
|
5473
|
+
const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
|
|
5415
5474
|
if (finalStatus.status === "completed") {
|
|
5416
5475
|
progress.complete();
|
|
5417
5476
|
} else {
|
|
5418
5477
|
progress.fail();
|
|
5419
5478
|
}
|
|
5420
|
-
recordCliTrace({
|
|
5421
|
-
phase: "cli.write_play_result",
|
|
5422
|
-
playName,
|
|
5423
|
-
status: finalStatus.status,
|
|
5424
|
-
runId: finalStatus.runId
|
|
5425
|
-
});
|
|
5426
5479
|
writePlayResult(finalStatus, options.jsonOutput, { exportedPath });
|
|
5427
5480
|
return finalStatus.status === "completed" ? 0 : 1;
|
|
5428
5481
|
}
|
|
5429
5482
|
progress.phase("starting run");
|
|
5430
|
-
const started = await
|
|
5431
|
-
|
|
5432
|
-
{ playName },
|
|
5433
|
-
() => client.startPlayRun(startRequest)
|
|
5434
|
-
);
|
|
5435
|
-
const fallbackDashboardUrl = buildPlayDashboardUrl(client.baseUrl, playName);
|
|
5436
|
-
const dashboardUrl = started.dashboardUrl ?? fallbackDashboardUrl;
|
|
5483
|
+
const started = await client.startPlayRun(startRequest);
|
|
5484
|
+
const dashboardUrl = buildPlayDashboardUrl(client.baseUrl, playName);
|
|
5437
5485
|
progress.phase(`loading play on ${dashboardUrl}`);
|
|
5438
5486
|
progress.complete();
|
|
5439
5487
|
writeStartedPlayRun({
|
|
@@ -5441,7 +5489,7 @@ async function handleFileBackedRun(options) {
|
|
|
5441
5489
|
playName,
|
|
5442
5490
|
status: started.status,
|
|
5443
5491
|
statusUrl: started.statusUrl,
|
|
5444
|
-
dashboardUrl,
|
|
5492
|
+
dashboardUrl: started.dashboardUrl ?? dashboardUrl,
|
|
5445
5493
|
jsonOutput: options.jsonOutput,
|
|
5446
5494
|
progress
|
|
5447
5495
|
});
|
|
@@ -5467,9 +5515,8 @@ async function handleNamedRun(options) {
|
|
|
5467
5515
|
}
|
|
5468
5516
|
const client = new DeeplineClient();
|
|
5469
5517
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
5470
|
-
let stagedInputFile = null;
|
|
5471
5518
|
progress.phase("loading play definition");
|
|
5472
|
-
await assertCanonicalNamedPlayReference(client, options.target.name);
|
|
5519
|
+
const playDetail = await assertCanonicalNamedPlayReference(client, options.target.name);
|
|
5473
5520
|
progress.phase("selecting revision");
|
|
5474
5521
|
const selectedRevisionId = await resolveNamedRunRevisionId({
|
|
5475
5522
|
client,
|
|
@@ -5477,19 +5524,22 @@ async function handleNamedRun(options) {
|
|
|
5477
5524
|
revisionId: options.revisionId,
|
|
5478
5525
|
selector: options.revisionSelector
|
|
5479
5526
|
});
|
|
5480
|
-
if (options.csvPath) {
|
|
5481
|
-
progress.phase("staging input file");
|
|
5482
|
-
const [staged] = await client.stagePlayFiles([
|
|
5483
|
-
stageFile((0, import_node_path8.basename)(options.csvPath), options.csvPath)
|
|
5484
|
-
]);
|
|
5485
|
-
stagedInputFile = staged ?? null;
|
|
5486
|
-
}
|
|
5487
5527
|
const runtimeInput = options.input ? { ...options.input } : {};
|
|
5528
|
+
const stagedFileInputs = await stageFileInputArgs({
|
|
5529
|
+
client,
|
|
5530
|
+
runtimeInput,
|
|
5531
|
+
bindings: [
|
|
5532
|
+
...fileInputBindingsFromPlaySchema(playDetail.play.inputSchema),
|
|
5533
|
+
...fileInputBindingsFromStaticPipeline(playDetail.play.staticPipeline)
|
|
5534
|
+
],
|
|
5535
|
+
progress
|
|
5536
|
+
});
|
|
5488
5537
|
const startRequest = {
|
|
5489
5538
|
name: options.target.name,
|
|
5490
5539
|
...selectedRevisionId ? { revisionId: selectedRevisionId } : {},
|
|
5491
5540
|
...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
|
|
5492
|
-
...
|
|
5541
|
+
...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
|
|
5542
|
+
...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
|
|
5493
5543
|
...options.force ? { force: true } : {}
|
|
5494
5544
|
};
|
|
5495
5545
|
if (options.watch) {
|
|
@@ -5503,22 +5553,6 @@ async function handleNamedRun(options) {
|
|
|
5503
5553
|
waitTimeoutMs: options.waitTimeoutMs,
|
|
5504
5554
|
progress
|
|
5505
5555
|
});
|
|
5506
|
-
if (finalStatus.status !== "completed" && options.csvPath) {
|
|
5507
|
-
progress.phase("generating csv wrapper play");
|
|
5508
|
-
const generatedPlayPath = writeGeneratedCsvWrapperPlay(
|
|
5509
|
-
options.target.name
|
|
5510
|
-
);
|
|
5511
|
-
progress.writeLogLine(
|
|
5512
|
-
`Generated CSV wrapper play: ${generatedPlayPath}`
|
|
5513
|
-
);
|
|
5514
|
-
progress.phase("running generated csv wrapper play");
|
|
5515
|
-
return handleFileBackedRun({
|
|
5516
|
-
...options,
|
|
5517
|
-
target: { kind: "file", path: generatedPlayPath },
|
|
5518
|
-
revisionId: null,
|
|
5519
|
-
revisionSelector: null
|
|
5520
|
-
});
|
|
5521
|
-
}
|
|
5522
5556
|
const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
|
|
5523
5557
|
if (finalStatus.status === "completed") {
|
|
5524
5558
|
progress.complete();
|
|
@@ -5530,11 +5564,10 @@ async function handleNamedRun(options) {
|
|
|
5530
5564
|
}
|
|
5531
5565
|
progress.phase("starting run");
|
|
5532
5566
|
const started = await client.startPlayRun(startRequest);
|
|
5533
|
-
const
|
|
5567
|
+
const dashboardUrl = buildPlayDashboardUrl(
|
|
5534
5568
|
client.baseUrl,
|
|
5535
5569
|
options.target.name
|
|
5536
5570
|
);
|
|
5537
|
-
const dashboardUrl = started.dashboardUrl ?? fallbackDashboardUrl;
|
|
5538
5571
|
progress.phase(`loading play on ${dashboardUrl}`);
|
|
5539
5572
|
progress.complete();
|
|
5540
5573
|
writeStartedPlayRun({
|
|
@@ -5542,7 +5575,7 @@ async function handleNamedRun(options) {
|
|
|
5542
5575
|
playName: started.name ?? options.target.name,
|
|
5543
5576
|
status: started.status,
|
|
5544
5577
|
statusUrl: started.statusUrl,
|
|
5545
|
-
dashboardUrl,
|
|
5578
|
+
dashboardUrl: started.dashboardUrl ?? dashboardUrl,
|
|
5546
5579
|
jsonOutput: options.jsonOutput,
|
|
5547
5580
|
progress
|
|
5548
5581
|
});
|
|
@@ -5761,8 +5794,9 @@ async function handlePlayGet(args) {
|
|
|
5761
5794
|
return 1;
|
|
5762
5795
|
}
|
|
5763
5796
|
const client = new DeeplineClient();
|
|
5764
|
-
const
|
|
5797
|
+
const explicitJson = args.includes("--json");
|
|
5765
5798
|
const sourceOutput = args.includes("--source");
|
|
5799
|
+
const jsonOutput = sourceOutput ? explicitJson : argsWantJson(args);
|
|
5766
5800
|
let outPath = null;
|
|
5767
5801
|
for (let index = 1; index < args.length; index += 1) {
|
|
5768
5802
|
const arg = args[index];
|
|
@@ -5773,7 +5807,7 @@ async function handlePlayGet(args) {
|
|
|
5773
5807
|
const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs6.readFileSync)((0, import_node_path8.resolve)(target), "utf-8"), (0, import_node_path8.resolve)(target)) : parseReferencedPlayTarget(target).playName;
|
|
5774
5808
|
const detail = isFileTarget(target) ? await client.getPlay(playName) : await assertCanonicalNamedPlayReference(client, target);
|
|
5775
5809
|
const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
|
|
5776
|
-
const materializedFile =
|
|
5810
|
+
const materializedFile = outPath ? materializeRemotePlaySource({
|
|
5777
5811
|
target,
|
|
5778
5812
|
playName,
|
|
5779
5813
|
sourceCode: resolvedSource,
|
|
@@ -5813,6 +5847,10 @@ async function handlePlayGet(args) {
|
|
|
5813
5847
|
}
|
|
5814
5848
|
return 0;
|
|
5815
5849
|
}
|
|
5850
|
+
if (outPath && loadedMessage) {
|
|
5851
|
+
console.log(loadedMessage);
|
|
5852
|
+
return 0;
|
|
5853
|
+
}
|
|
5816
5854
|
console.log(`Play: ${formatPlayReference(detail.play)}`);
|
|
5817
5855
|
console.log(
|
|
5818
5856
|
`Working version: ${detail.play.workingRevision?.version ?? "\u2014"}`
|
|
@@ -5979,6 +6017,20 @@ function printPlayDescription(play) {
|
|
|
5979
6017
|
console.log(` ${line}`);
|
|
5980
6018
|
}
|
|
5981
6019
|
}
|
|
6020
|
+
if (play.csvInput) {
|
|
6021
|
+
console.log(" CSV input:");
|
|
6022
|
+
const rendered = JSON.stringify(play.csvInput, null, 2);
|
|
6023
|
+
for (const line of rendered.split("\n")) {
|
|
6024
|
+
console.log(` ${line}`);
|
|
6025
|
+
}
|
|
6026
|
+
}
|
|
6027
|
+
if (play.rowOutputSchema) {
|
|
6028
|
+
console.log(" Row output schema:");
|
|
6029
|
+
const rendered = JSON.stringify(play.rowOutputSchema, null, 2);
|
|
6030
|
+
for (const line of rendered.split("\n")) {
|
|
6031
|
+
console.log(` ${line}`);
|
|
6032
|
+
}
|
|
6033
|
+
}
|
|
5982
6034
|
console.log(` Run: ${play.runCommand}`);
|
|
5983
6035
|
}
|
|
5984
6036
|
async function handlePlaySearch(args) {
|
|
@@ -6118,6 +6170,45 @@ async function handlePlayPublish(args) {
|
|
|
6118
6170
|
`);
|
|
6119
6171
|
return result.success ? 0 : 1;
|
|
6120
6172
|
}
|
|
6173
|
+
async function handlePlayDelete(args) {
|
|
6174
|
+
const playName = args[0];
|
|
6175
|
+
if (!playName) {
|
|
6176
|
+
console.error("Usage: deepline plays delete <play-name> --yes [--json]");
|
|
6177
|
+
return 1;
|
|
6178
|
+
}
|
|
6179
|
+
const confirmed = args.includes("--yes") || args.includes("-y") || args.includes("--force");
|
|
6180
|
+
if (!confirmed) {
|
|
6181
|
+
console.error(
|
|
6182
|
+
"Refusing to delete without --yes. This deletes the org-owned play, its revisions, trigger bindings, and local run records."
|
|
6183
|
+
);
|
|
6184
|
+
return 1;
|
|
6185
|
+
}
|
|
6186
|
+
const client = new DeeplineClient();
|
|
6187
|
+
let detail;
|
|
6188
|
+
try {
|
|
6189
|
+
detail = await client.getPlay(parseReferencedPlayTarget(playName).playName);
|
|
6190
|
+
} catch (error) {
|
|
6191
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
6192
|
+
return 1;
|
|
6193
|
+
}
|
|
6194
|
+
if (detail.play.ownerType === "deepline" || detail.play.origin === "prebuilt") {
|
|
6195
|
+
console.error(`Cannot delete prebuilt play: ${formatPlayReference(detail.play)}`);
|
|
6196
|
+
return 1;
|
|
6197
|
+
}
|
|
6198
|
+
const result = await client.deletePlay(
|
|
6199
|
+
parseReferencedPlayTarget(formatPlayReference(detail.play)).playName
|
|
6200
|
+
);
|
|
6201
|
+
if (argsWantJson(args)) {
|
|
6202
|
+
process.stdout.write(`${JSON.stringify(result)}
|
|
6203
|
+
`);
|
|
6204
|
+
return result.deleted ? 0 : 1;
|
|
6205
|
+
}
|
|
6206
|
+
process.stdout.write(
|
|
6207
|
+
`Deleted ${result.name}: revisions=${result.deletedRevisionCount}, bindings=${result.deletedBindingCount}, runs=${result.deletedRunCount}
|
|
6208
|
+
`
|
|
6209
|
+
);
|
|
6210
|
+
return result.deleted ? 0 : 1;
|
|
6211
|
+
}
|
|
6121
6212
|
function registerPlayCommands(program) {
|
|
6122
6213
|
const play = program.command("plays").alias("play").description("Search, validate, run, and manage cloud plays.").addHelpText(
|
|
6123
6214
|
"after",
|
|
@@ -6151,21 +6242,23 @@ Examples:
|
|
|
6151
6242
|
...options.json ? ["--json"] : []
|
|
6152
6243
|
]);
|
|
6153
6244
|
});
|
|
6154
|
-
play.command("run [target]").description("Run a play file or named play.").addHelpText(
|
|
6245
|
+
play.command("run [target]").description("Run a play file or named play.").allowUnknownOption(true).allowExcessArguments(true).addHelpText(
|
|
6155
6246
|
"after",
|
|
6156
6247
|
`
|
|
6157
6248
|
Notes:
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6249
|
+
Local play files are bundled locally, then validated and executed in Deepline cloud.
|
|
6250
|
+
Named plays run the stored live cloud revision.
|
|
6251
|
+
Unknown --foo and --foo.bar flags are treated as play input args.
|
|
6252
|
+
File-like input args accept local paths; the CLI stages those files before submit.
|
|
6253
|
+
Run performs server preflight automatically. Use \`deepline plays check <file>\`
|
|
6254
|
+
to validate without starting a run.
|
|
6162
6255
|
|
|
6163
6256
|
Examples:
|
|
6164
6257
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}' --watch
|
|
6165
6258
|
deepline plays run person-linkedin-to-email --input '{"linkedin_url":"..."}' --watch
|
|
6166
6259
|
deepline plays run enrich.play.ts --csv leads.csv --watch --out leads-enriched.csv
|
|
6167
6260
|
`
|
|
6168
|
-
).option("--file <path>", "Local play file to run").option("--name <name>", "Saved play name to run").option("
|
|
6261
|
+
).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(
|
|
6169
6262
|
"--revision-id <id>",
|
|
6170
6263
|
"Run a specific saved revision instead of the live revision"
|
|
6171
6264
|
).option(
|
|
@@ -6174,12 +6267,21 @@ Examples:
|
|
|
6174
6267
|
).option("--watch", "Stream logs until completion").option(
|
|
6175
6268
|
"--logs",
|
|
6176
6269
|
"When output is non-interactive, stream play logs to stderr while waiting"
|
|
6177
|
-
).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) => {
|
|
6270
|
+
).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) => {
|
|
6271
|
+
const passthroughArgs = [...command.args];
|
|
6272
|
+
const explicitTarget = options.file || options.name;
|
|
6273
|
+
const targetIsInputFlag = typeof target === "string" && target.startsWith("--");
|
|
6274
|
+
const effectiveTarget = explicitTarget || targetIsInputFlag ? null : target;
|
|
6275
|
+
if (explicitTarget && typeof target === "string" && !targetIsInputFlag && !passthroughArgs.includes(target)) {
|
|
6276
|
+
passthroughArgs.push(target);
|
|
6277
|
+
}
|
|
6278
|
+
if (effectiveTarget && passthroughArgs[0] === effectiveTarget) {
|
|
6279
|
+
passthroughArgs.shift();
|
|
6280
|
+
}
|
|
6178
6281
|
process.exitCode = await handlePlayRun([
|
|
6179
|
-
...
|
|
6282
|
+
...effectiveTarget ? [effectiveTarget] : [],
|
|
6180
6283
|
...options.file ? ["--file", options.file] : [],
|
|
6181
6284
|
...options.name ? ["--name", options.name] : [],
|
|
6182
|
-
...options.csv ? ["--csv", options.csv] : [],
|
|
6183
6285
|
...options.input ? ["--input", options.input] : [],
|
|
6184
6286
|
...options.live ? ["--live"] : [],
|
|
6185
6287
|
...options.latest ? ["--latest"] : [],
|
|
@@ -6190,7 +6292,8 @@ Examples:
|
|
|
6190
6292
|
...options.pollIntervalMs ? ["--poll-interval-ms", options.pollIntervalMs] : [],
|
|
6191
6293
|
...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
|
|
6192
6294
|
...options.force ? ["--force"] : [],
|
|
6193
|
-
...options.json ? ["--json"] : []
|
|
6295
|
+
...options.json ? ["--json"] : [],
|
|
6296
|
+
...passthroughArgs
|
|
6194
6297
|
]);
|
|
6195
6298
|
});
|
|
6196
6299
|
play.command("get <target>").description("Fetch full play details.").addHelpText(
|
|
@@ -6204,12 +6307,10 @@ Notes:
|
|
|
6204
6307
|
Examples:
|
|
6205
6308
|
deepline plays get person-linkedin-to-email
|
|
6206
6309
|
deepline plays get person-linkedin-to-email --json | jq '.play.liveRevision'
|
|
6310
|
+
deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source > email-waterfall.play.ts
|
|
6311
|
+
deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source --out ./email-waterfall.play.ts
|
|
6207
6312
|
`
|
|
6208
|
-
).option("--json", "Emit JSON output. Also automatic when stdout is piped").
|
|
6209
|
-
new import_commander.Option("--source", "Materialize or print the source code").hideHelp()
|
|
6210
|
-
).addOption(
|
|
6211
|
-
new import_commander.Option("--out <path>", "Write source to a specific path").hideHelp()
|
|
6212
|
-
).action(async (target, options) => {
|
|
6313
|
+
).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) => {
|
|
6213
6314
|
process.exitCode = await handlePlayGet([
|
|
6214
6315
|
target,
|
|
6215
6316
|
...options.json ? ["--json"] : [],
|
|
@@ -6269,7 +6370,7 @@ Examples:
|
|
|
6269
6370
|
...options.json ? ["--json"] : []
|
|
6270
6371
|
]);
|
|
6271
6372
|
});
|
|
6272
|
-
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", "
|
|
6373
|
+
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) => {
|
|
6273
6374
|
process.exitCode = await handlePlayStatus([
|
|
6274
6375
|
...options.runId ? ["--run-id", options.runId] : [],
|
|
6275
6376
|
...options.name ? ["--name", options.name] : [],
|
|
@@ -6300,6 +6401,13 @@ Examples:
|
|
|
6300
6401
|
...options.json ? ["--json"] : []
|
|
6301
6402
|
]);
|
|
6302
6403
|
});
|
|
6404
|
+
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) => {
|
|
6405
|
+
process.exitCode = await handlePlayDelete([
|
|
6406
|
+
target,
|
|
6407
|
+
...options.yes ? ["--yes"] : [],
|
|
6408
|
+
...options.json ? ["--json"] : []
|
|
6409
|
+
]);
|
|
6410
|
+
});
|
|
6303
6411
|
const runs = program.command("runs").description("Inspect and export play runs.").addHelpText(
|
|
6304
6412
|
"after",
|
|
6305
6413
|
`
|
|
@@ -6309,7 +6417,7 @@ Examples:
|
|
|
6309
6417
|
deepline runs logs play/my-play/run/20260501t000000-000
|
|
6310
6418
|
`
|
|
6311
6419
|
);
|
|
6312
|
-
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", "
|
|
6420
|
+
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) => {
|
|
6313
6421
|
process.exitCode = await handleRunStatus([
|
|
6314
6422
|
runId,
|
|
6315
6423
|
...options.json ? ["--json"] : [],
|
|
@@ -6664,7 +6772,7 @@ function printToolDetails(tool, requestedToolId) {
|
|
|
6664
6772
|
const operation = typeof tool.operation === "string" ? tool.operation : "";
|
|
6665
6773
|
const displayBase = operation && operation.startsWith(`${tool.provider}_`) ? operation.slice(String(tool.provider).length + 1) : operation ? `${tool.provider} ${operation}`.trim() : toolId;
|
|
6666
6774
|
const displayName = titleCase(displayBase || String(tool.displayName || toolId));
|
|
6667
|
-
const cost =
|
|
6775
|
+
const cost = isRecord3(tool.cost) ? tool.cost : null;
|
|
6668
6776
|
const deeplineCredits = numberField(tool, "deeplineCreditsPerPricingUnit", "deepline_credits_per_pricing_unit");
|
|
6669
6777
|
const deeplineUsdPerPricingUnit = numberField(tool, "deeplineUsdPerPricingUnit", "deepline_usd_per_pricing_unit");
|
|
6670
6778
|
const deeplineUsdPerCredit = numberField(tool, "deeplineUsdPerCredit", "deepline_usd_per_credit");
|
|
@@ -6709,7 +6817,7 @@ function printToolDetails(tool, requestedToolId) {
|
|
|
6709
6817
|
if (stepContributions.length) {
|
|
6710
6818
|
console.log(" step contributions:");
|
|
6711
6819
|
for (const item of stepContributions) {
|
|
6712
|
-
if (!
|
|
6820
|
+
if (!isRecord3(item)) continue;
|
|
6713
6821
|
const stepTool = typeof item.tool === "string" ? item.tool.trim() : "";
|
|
6714
6822
|
const low = typeof item.lowCredits === "number" ? item.lowCredits : null;
|
|
6715
6823
|
const high = typeof item.highCredits === "number" ? item.highCredits : null;
|
|
@@ -6796,12 +6904,12 @@ function printToolCost(input) {
|
|
|
6796
6904
|
return false;
|
|
6797
6905
|
}
|
|
6798
6906
|
function toolInputFieldsForDisplay(inputSchema) {
|
|
6799
|
-
if (Array.isArray(inputSchema.fields)) return inputSchema.fields.filter(
|
|
6800
|
-
const jsonSchema =
|
|
6801
|
-
const properties =
|
|
6907
|
+
if (Array.isArray(inputSchema.fields)) return inputSchema.fields.filter(isRecord3);
|
|
6908
|
+
const jsonSchema = isRecord3(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
|
|
6909
|
+
const properties = isRecord3(jsonSchema.properties) ? jsonSchema.properties : {};
|
|
6802
6910
|
const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
|
|
6803
6911
|
return Object.entries(properties).map(([name, value]) => {
|
|
6804
|
-
const property =
|
|
6912
|
+
const property = isRecord3(value) ? value : {};
|
|
6805
6913
|
return {
|
|
6806
6914
|
name,
|
|
6807
6915
|
type: typeof property.type === "string" ? property.type : "unknown",
|
|
@@ -6828,7 +6936,7 @@ function printJsonPreview(label, payload) {
|
|
|
6828
6936
|
}
|
|
6829
6937
|
function samplePayload(samples, key) {
|
|
6830
6938
|
const entry = samples[key];
|
|
6831
|
-
if (!
|
|
6939
|
+
if (!isRecord3(entry)) return void 0;
|
|
6832
6940
|
return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
|
|
6833
6941
|
}
|
|
6834
6942
|
function isPlayTool(tool) {
|
|
@@ -6849,7 +6957,7 @@ function formatDecimal(value) {
|
|
|
6849
6957
|
function formatUsd(value) {
|
|
6850
6958
|
return `$${formatDecimal(value)}`;
|
|
6851
6959
|
}
|
|
6852
|
-
function
|
|
6960
|
+
function isRecord3(value) {
|
|
6853
6961
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
6854
6962
|
}
|
|
6855
6963
|
function stringField(source, ...keys) {
|
|
@@ -6876,7 +6984,7 @@ function arrayField(source, ...keys) {
|
|
|
6876
6984
|
function recordField(source, ...keys) {
|
|
6877
6985
|
for (const key of keys) {
|
|
6878
6986
|
const value = source[key];
|
|
6879
|
-
if (
|
|
6987
|
+
if (isRecord3(value)) return value;
|
|
6880
6988
|
}
|
|
6881
6989
|
return {};
|
|
6882
6990
|
}
|
|
@@ -6967,7 +7075,7 @@ async function executeTool(args) {
|
|
|
6967
7075
|
}
|
|
6968
7076
|
throw error;
|
|
6969
7077
|
}
|
|
6970
|
-
const rawResponse = await client.
|
|
7078
|
+
const rawResponse = await client.executeTool(parsed.toolId, parsed.params);
|
|
6971
7079
|
const listConversion = tryConvertToList(rawResponse, {
|
|
6972
7080
|
listExtractorPaths: metadata.listExtractorPaths ?? []
|
|
6973
7081
|
});
|
|
@@ -7138,6 +7246,54 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
|
|
|
7138
7246
|
progress?.writeLine("SDK skills are up to date.") ?? process.stderr.write("SDK skills are up to date.\n");
|
|
7139
7247
|
}
|
|
7140
7248
|
|
|
7249
|
+
// src/cli/trace.ts
|
|
7250
|
+
var cliTraceStartedAt = Date.now();
|
|
7251
|
+
function isTruthyEnv(value) {
|
|
7252
|
+
return value === "1" || value === "true" || value === "yes";
|
|
7253
|
+
}
|
|
7254
|
+
function isCliTraceEnabled() {
|
|
7255
|
+
return isTruthyEnv(process.env.DEEPLINE_CLI_TRACE);
|
|
7256
|
+
}
|
|
7257
|
+
function recordCliTrace(event) {
|
|
7258
|
+
if (!isCliTraceEnabled()) {
|
|
7259
|
+
return;
|
|
7260
|
+
}
|
|
7261
|
+
const now = Date.now();
|
|
7262
|
+
const payload = {
|
|
7263
|
+
ts: now,
|
|
7264
|
+
source: "cli",
|
|
7265
|
+
sinceStartMs: now - cliTraceStartedAt,
|
|
7266
|
+
...event
|
|
7267
|
+
};
|
|
7268
|
+
process.stderr.write(`[cli-trace] ${JSON.stringify(payload)}
|
|
7269
|
+
`);
|
|
7270
|
+
}
|
|
7271
|
+
async function traceCliSpan(phase, fields, run) {
|
|
7272
|
+
if (!isCliTraceEnabled()) {
|
|
7273
|
+
return run();
|
|
7274
|
+
}
|
|
7275
|
+
const startedAt = Date.now();
|
|
7276
|
+
try {
|
|
7277
|
+
const result = await run();
|
|
7278
|
+
recordCliTrace({
|
|
7279
|
+
phase,
|
|
7280
|
+
ms: Date.now() - startedAt,
|
|
7281
|
+
ok: true,
|
|
7282
|
+
...fields
|
|
7283
|
+
});
|
|
7284
|
+
return result;
|
|
7285
|
+
} catch (error) {
|
|
7286
|
+
recordCliTrace({
|
|
7287
|
+
phase,
|
|
7288
|
+
ms: Date.now() - startedAt,
|
|
7289
|
+
ok: false,
|
|
7290
|
+
error: error instanceof Error ? error.message : String(error),
|
|
7291
|
+
...fields
|
|
7292
|
+
});
|
|
7293
|
+
throw error;
|
|
7294
|
+
}
|
|
7295
|
+
}
|
|
7296
|
+
|
|
7141
7297
|
// src/cli/index.ts
|
|
7142
7298
|
function shouldPrintStartupPhase() {
|
|
7143
7299
|
if (process.argv.includes("--json")) {
|
|
@@ -7159,7 +7315,7 @@ async function main() {
|
|
|
7159
7315
|
if (printStartupPhase) {
|
|
7160
7316
|
progress?.phase("loading deepline cli");
|
|
7161
7317
|
}
|
|
7162
|
-
const program = new
|
|
7318
|
+
const program = new import_commander.Command();
|
|
7163
7319
|
program.name("deepline").description("Deepline CLI (TypeScript SDK)").version(SDK_VERSION, "-v, --version", "Show version").showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
7164
7320
|
"after",
|
|
7165
7321
|
`
|