deepline 0.1.67 → 0.1.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1033 -577
- package/dist/cli/index.mjs +1033 -577
- package/dist/index.d.mts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +19 -2
- package/dist/index.mjs +19 -2
- package/dist/repo/apps/play-runner-workers/src/entry.ts +122 -29
- package/dist/repo/sdk/src/client.ts +40 -0
- package/dist/repo/sdk/src/play.ts +33 -1
- package/dist/repo/sdk/src/plays/bundle-play-file.ts +4 -1
- package/dist/repo/sdk/src/release.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/secret-capability.ts +103 -0
- package/dist/repo/shared_libs/play-runtime/secret-redaction.ts +90 -0
- package/dist/repo/shared_libs/plays/bundling/index.ts +10 -0
- package/dist/repo/shared_libs/plays/secret-guardrails.ts +57 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -229,10 +229,10 @@ var import_node_path2 = require("path");
|
|
|
229
229
|
|
|
230
230
|
// src/release.ts
|
|
231
231
|
var SDK_RELEASE = {
|
|
232
|
-
version: "0.1.
|
|
232
|
+
version: "0.1.70",
|
|
233
233
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
234
234
|
supportPolicy: {
|
|
235
|
-
latest: "0.1.
|
|
235
|
+
latest: "0.1.70",
|
|
236
236
|
minimumSupported: "0.1.53",
|
|
237
237
|
deprecatedBelow: "0.1.53"
|
|
238
238
|
}
|
|
@@ -739,7 +739,7 @@ var DeeplineClient = class {
|
|
|
739
739
|
list: (options2) => this.listRuns(options2),
|
|
740
740
|
tail: (runId, options2) => this.tailRun(runId, options2),
|
|
741
741
|
logs: (runId, options2) => this.getRunLogs(runId, options2),
|
|
742
|
-
exportDatasetRows: (
|
|
742
|
+
exportDatasetRows: (input2) => this.getPlaySheetRows(input2),
|
|
743
743
|
stop: (runId, options2) => this.stopRun(runId, options2)
|
|
744
744
|
};
|
|
745
745
|
}
|
|
@@ -826,6 +826,22 @@ var DeeplineClient = class {
|
|
|
826
826
|
};
|
|
827
827
|
}
|
|
828
828
|
// ——————————————————————————————————————————————————————————
|
|
829
|
+
// Secrets
|
|
830
|
+
// ——————————————————————————————————————————————————————————
|
|
831
|
+
async listSecrets() {
|
|
832
|
+
const response = await this.http.get(
|
|
833
|
+
"/api/v2/secrets"
|
|
834
|
+
);
|
|
835
|
+
return Array.isArray(response.secrets) ? response.secrets : [];
|
|
836
|
+
}
|
|
837
|
+
async checkSecret(name) {
|
|
838
|
+
const normalized = name.trim().toUpperCase();
|
|
839
|
+
const secrets = await this.listSecrets();
|
|
840
|
+
return secrets.find(
|
|
841
|
+
(secret) => secret.name === normalized && secret.status === "active" && secret.hasValue
|
|
842
|
+
) ?? null;
|
|
843
|
+
}
|
|
844
|
+
// ——————————————————————————————————————————————————————————
|
|
829
845
|
// Tools
|
|
830
846
|
// ——————————————————————————————————————————————————————————
|
|
831
847
|
/**
|
|
@@ -918,24 +934,24 @@ var DeeplineClient = class {
|
|
|
918
934
|
* Top-level fields such as `status`, `job_id`, and `billing` describe the
|
|
919
935
|
* Deepline execution envelope.
|
|
920
936
|
*/
|
|
921
|
-
async executeTool(toolId,
|
|
937
|
+
async executeTool(toolId, input2, options) {
|
|
922
938
|
const headers = {
|
|
923
939
|
[EXECUTE_RESPONSE_CONTRACT_HEADER]: V2_EXECUTE_RESPONSE_CONTRACT,
|
|
924
940
|
...options?.includeToolMetadata ? { [INCLUDE_TOOL_METADATA_HEADER]: "true" } : {}
|
|
925
941
|
};
|
|
926
942
|
return this.http.post(
|
|
927
943
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
928
|
-
{ payload:
|
|
944
|
+
{ payload: input2 },
|
|
929
945
|
headers
|
|
930
946
|
);
|
|
931
947
|
}
|
|
932
|
-
async executeToolRaw(toolId,
|
|
933
|
-
return this.executeTool(toolId,
|
|
948
|
+
async executeToolRaw(toolId, input2, options) {
|
|
949
|
+
return this.executeTool(toolId, input2, options);
|
|
934
950
|
}
|
|
935
|
-
async queryCustomerDb(
|
|
951
|
+
async queryCustomerDb(input2) {
|
|
936
952
|
return this.http.post("/api/v2/db/query", {
|
|
937
|
-
sql:
|
|
938
|
-
...
|
|
953
|
+
sql: input2.sql,
|
|
954
|
+
...input2.maxRows ? { max_rows: input2.maxRows } : {}
|
|
939
955
|
});
|
|
940
956
|
}
|
|
941
957
|
// ——————————————————————————————————————————————————————————
|
|
@@ -1021,6 +1037,7 @@ var DeeplineClient = class {
|
|
|
1021
1037
|
...request.inputFile ? { inputFile: request.inputFile } : {},
|
|
1022
1038
|
...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
|
|
1023
1039
|
...request.force ? { force: true } : {},
|
|
1040
|
+
...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
|
|
1024
1041
|
...request.profile ? { profile: request.profile } : {}
|
|
1025
1042
|
};
|
|
1026
1043
|
for await (const event of this.http.streamSse(
|
|
@@ -1042,15 +1059,15 @@ var DeeplineClient = class {
|
|
|
1042
1059
|
* Internal/advanced primitive used by packaging flows. Public callers should
|
|
1043
1060
|
* prefer the CLI, {@link submitPlay}, or {@link runPlay}.
|
|
1044
1061
|
*/
|
|
1045
|
-
async registerPlayArtifact(
|
|
1046
|
-
const compilerManifest =
|
|
1047
|
-
name:
|
|
1048
|
-
sourceCode:
|
|
1049
|
-
sourceFiles:
|
|
1050
|
-
artifact:
|
|
1062
|
+
async registerPlayArtifact(input2) {
|
|
1063
|
+
const compilerManifest = input2.compilerManifest ?? await this.compilePlayManifest({
|
|
1064
|
+
name: input2.name,
|
|
1065
|
+
sourceCode: input2.sourceCode,
|
|
1066
|
+
sourceFiles: input2.sourceFiles,
|
|
1067
|
+
artifact: input2.artifact
|
|
1051
1068
|
});
|
|
1052
1069
|
return this.http.post("/api/v2/plays/artifacts", {
|
|
1053
|
-
...
|
|
1070
|
+
...input2,
|
|
1054
1071
|
compilerManifest
|
|
1055
1072
|
});
|
|
1056
1073
|
}
|
|
@@ -1070,14 +1087,14 @@ var DeeplineClient = class {
|
|
|
1070
1087
|
artifacts: compiledArtifacts
|
|
1071
1088
|
});
|
|
1072
1089
|
}
|
|
1073
|
-
async compilePlayManifest(
|
|
1090
|
+
async compilePlayManifest(input2) {
|
|
1074
1091
|
const retryDelays = COMPILE_MANIFEST_RETRY_DELAYS_MS.slice(
|
|
1075
1092
|
0,
|
|
1076
1093
|
Math.max(0, this.config.maxRetries)
|
|
1077
1094
|
);
|
|
1078
1095
|
for (let attempt = 0; ; attempt += 1) {
|
|
1079
1096
|
try {
|
|
1080
|
-
const response = await this.http.post("/api/v2/plays/compile-manifest",
|
|
1097
|
+
const response = await this.http.post("/api/v2/plays/compile-manifest", input2);
|
|
1081
1098
|
return response.compilerManifest;
|
|
1082
1099
|
} catch (error) {
|
|
1083
1100
|
const delayMs = retryDelays[attempt];
|
|
@@ -1095,21 +1112,21 @@ var DeeplineClient = class {
|
|
|
1095
1112
|
* publish a revision, or start a run. It is the authoritative cloud validation
|
|
1096
1113
|
* path used by `deepline play check`.
|
|
1097
1114
|
*/
|
|
1098
|
-
async checkPlayArtifact(
|
|
1099
|
-
return this.http.post("/api/v2/plays/check",
|
|
1100
|
-
}
|
|
1101
|
-
async startPlayRunFromBundle(
|
|
1102
|
-
const compilerManifest =
|
|
1103
|
-
name:
|
|
1104
|
-
sourceCode:
|
|
1105
|
-
sourceFiles:
|
|
1106
|
-
artifact:
|
|
1115
|
+
async checkPlayArtifact(input2) {
|
|
1116
|
+
return this.http.post("/api/v2/plays/check", input2);
|
|
1117
|
+
}
|
|
1118
|
+
async startPlayRunFromBundle(input2) {
|
|
1119
|
+
const compilerManifest = input2.compilerManifest ?? await this.compilePlayManifest({
|
|
1120
|
+
name: input2.name,
|
|
1121
|
+
sourceCode: input2.sourceCode,
|
|
1122
|
+
sourceFiles: input2.sourceFiles,
|
|
1123
|
+
artifact: input2.artifact
|
|
1107
1124
|
});
|
|
1108
1125
|
const registeredArtifact = await this.registerPlayArtifact({
|
|
1109
|
-
name:
|
|
1110
|
-
sourceCode:
|
|
1111
|
-
sourceFiles:
|
|
1112
|
-
artifact:
|
|
1126
|
+
name: input2.name,
|
|
1127
|
+
sourceCode: input2.sourceCode,
|
|
1128
|
+
sourceFiles: input2.sourceFiles,
|
|
1129
|
+
artifact: input2.artifact,
|
|
1113
1130
|
compilerManifest,
|
|
1114
1131
|
publish: false
|
|
1115
1132
|
});
|
|
@@ -1119,13 +1136,13 @@ var DeeplineClient = class {
|
|
|
1119
1136
|
);
|
|
1120
1137
|
}
|
|
1121
1138
|
return this.startPlayRun({
|
|
1122
|
-
name:
|
|
1139
|
+
name: input2.name,
|
|
1123
1140
|
artifactStorageKey: registeredArtifact.artifactStorageKey,
|
|
1124
1141
|
compilerManifest,
|
|
1125
|
-
...
|
|
1126
|
-
...
|
|
1127
|
-
...
|
|
1128
|
-
...
|
|
1142
|
+
...input2.input ? { input: input2.input } : {},
|
|
1143
|
+
...input2.inputFile ? { inputFile: input2.inputFile } : {},
|
|
1144
|
+
...input2.packagedFiles?.length ? { packagedFiles: input2.packagedFiles } : {},
|
|
1145
|
+
...input2.force ? { force: true } : {}
|
|
1129
1146
|
});
|
|
1130
1147
|
}
|
|
1131
1148
|
/**
|
|
@@ -1470,17 +1487,17 @@ var DeeplineClient = class {
|
|
|
1470
1487
|
entries
|
|
1471
1488
|
};
|
|
1472
1489
|
}
|
|
1473
|
-
async getPlaySheetRows(
|
|
1490
|
+
async getPlaySheetRows(input2) {
|
|
1474
1491
|
const params = new URLSearchParams({
|
|
1475
|
-
tableNamespace:
|
|
1476
|
-
limit: String(
|
|
1477
|
-
offset: String(
|
|
1492
|
+
tableNamespace: input2.tableNamespace,
|
|
1493
|
+
limit: String(input2.limit ?? 5e3),
|
|
1494
|
+
offset: String(input2.offset ?? 0)
|
|
1478
1495
|
});
|
|
1479
|
-
if (
|
|
1480
|
-
params.set("runId",
|
|
1496
|
+
if (input2.runId?.trim()) {
|
|
1497
|
+
params.set("runId", input2.runId.trim());
|
|
1481
1498
|
}
|
|
1482
1499
|
return await this.http.get(
|
|
1483
|
-
`/api/v2/plays/${encodeURIComponent(
|
|
1500
|
+
`/api/v2/plays/${encodeURIComponent(input2.playName)}/sheet?${params.toString()}`
|
|
1484
1501
|
);
|
|
1485
1502
|
}
|
|
1486
1503
|
/**
|
|
@@ -1923,7 +1940,7 @@ function browserAppNameFromBundleId(bundleId) {
|
|
|
1923
1940
|
}
|
|
1924
1941
|
function readDefaultMacBrowserBundleId(runner = defaultBrowserCommandRunner) {
|
|
1925
1942
|
try {
|
|
1926
|
-
const
|
|
1943
|
+
const output2 = runner.execFileSync(
|
|
1927
1944
|
"/usr/bin/defaults",
|
|
1928
1945
|
[
|
|
1929
1946
|
"read",
|
|
@@ -1932,10 +1949,10 @@ function readDefaultMacBrowserBundleId(runner = defaultBrowserCommandRunner) {
|
|
|
1932
1949
|
],
|
|
1933
1950
|
{ encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
|
|
1934
1951
|
);
|
|
1935
|
-
const httpsMatch =
|
|
1952
|
+
const httpsMatch = output2.match(
|
|
1936
1953
|
/LSHandlerURLScheme\s*=\s*https;[\s\S]*?LSHandlerRole(?:All|Viewer|Editor)\s*=\s*"([^"]+)"/
|
|
1937
1954
|
);
|
|
1938
|
-
const httpMatch =
|
|
1955
|
+
const httpMatch = output2.match(
|
|
1939
1956
|
/LSHandlerURLScheme\s*=\s*http;[\s\S]*?LSHandlerRole(?:All|Viewer|Editor)\s*=\s*"([^"]+)"/
|
|
1940
1957
|
);
|
|
1941
1958
|
return (httpsMatch?.[1] ?? httpMatch?.[1] ?? "").trim();
|
|
@@ -3380,9 +3397,9 @@ function stripCsvProjectionColumns(columns, rows) {
|
|
|
3380
3397
|
(column) => column !== CSV_PROJECTED_FIELDS_KEY && !projectedFields.has(column)
|
|
3381
3398
|
);
|
|
3382
3399
|
}
|
|
3383
|
-
function sanitizeCsvProjectionInfo(
|
|
3384
|
-
const columns = stripCsvProjectionColumns(
|
|
3385
|
-
const rows =
|
|
3400
|
+
function sanitizeCsvProjectionInfo(input2) {
|
|
3401
|
+
const columns = stripCsvProjectionColumns(input2.columns, input2.rows);
|
|
3402
|
+
const rows = input2.rows.map(stripCsvProjectionFields);
|
|
3386
3403
|
return { rows, columns };
|
|
3387
3404
|
}
|
|
3388
3405
|
function isRecord2(value) {
|
|
@@ -3438,8 +3455,8 @@ function inferColumns(rows) {
|
|
|
3438
3455
|
}
|
|
3439
3456
|
return columns;
|
|
3440
3457
|
}
|
|
3441
|
-
function canonicalRowsInfoFromCandidate(
|
|
3442
|
-
const candidate =
|
|
3458
|
+
function canonicalRowsInfoFromCandidate(input2) {
|
|
3459
|
+
const candidate = input2;
|
|
3443
3460
|
if (isSerializedDataset(candidate.value)) {
|
|
3444
3461
|
const rawRows = rowArray(candidate.value.preview) ?? [];
|
|
3445
3462
|
const totalRows2 = readNumber(candidate.value.count) ?? rawRows.length;
|
|
@@ -3480,31 +3497,31 @@ function canonicalRowsInfoFromCandidate(input) {
|
|
|
3480
3497
|
source: candidate.source
|
|
3481
3498
|
};
|
|
3482
3499
|
}
|
|
3483
|
-
function collectDatasetCandidates(
|
|
3484
|
-
if (
|
|
3500
|
+
function collectDatasetCandidates(input2) {
|
|
3501
|
+
if (input2.depth && input2.depth > 16) {
|
|
3485
3502
|
return;
|
|
3486
3503
|
}
|
|
3487
|
-
if (isSerializedDataset(
|
|
3488
|
-
|
|
3489
|
-
source:
|
|
3490
|
-
value:
|
|
3491
|
-
total:
|
|
3504
|
+
if (isSerializedDataset(input2.value)) {
|
|
3505
|
+
input2.output.push({
|
|
3506
|
+
source: input2.path,
|
|
3507
|
+
value: input2.value,
|
|
3508
|
+
total: input2.total
|
|
3492
3509
|
});
|
|
3493
3510
|
return;
|
|
3494
3511
|
}
|
|
3495
|
-
if (!isRecord2(
|
|
3512
|
+
if (!isRecord2(input2.value)) {
|
|
3496
3513
|
return;
|
|
3497
3514
|
}
|
|
3498
|
-
for (const [key, child] of Object.entries(
|
|
3515
|
+
for (const [key, child] of Object.entries(input2.value)) {
|
|
3499
3516
|
if (key === "preview" || key === "access") {
|
|
3500
3517
|
continue;
|
|
3501
3518
|
}
|
|
3502
3519
|
collectDatasetCandidates({
|
|
3503
3520
|
value: child,
|
|
3504
|
-
path: `${
|
|
3505
|
-
total: totalRowsForDataset(
|
|
3506
|
-
output:
|
|
3507
|
-
depth: (
|
|
3521
|
+
path: `${input2.path}.${key}`,
|
|
3522
|
+
total: totalRowsForDataset(input2.value, `${input2.path}.${key}`),
|
|
3523
|
+
output: input2.output,
|
|
3524
|
+
depth: (input2.depth ?? 0) + 1
|
|
3508
3525
|
});
|
|
3509
3526
|
}
|
|
3510
3527
|
}
|
|
@@ -4022,26 +4039,26 @@ function writeCustomerDbCsv(result, outPath) {
|
|
|
4022
4039
|
);
|
|
4023
4040
|
return resolved;
|
|
4024
4041
|
}
|
|
4025
|
-
function dbQueryExportEnvelope(
|
|
4026
|
-
const destination =
|
|
4042
|
+
function dbQueryExportEnvelope(input2) {
|
|
4043
|
+
const destination = input2.outPath ?? "stdout";
|
|
4027
4044
|
return {
|
|
4028
|
-
command:
|
|
4029
|
-
format:
|
|
4030
|
-
row_count:
|
|
4031
|
-
row_count_returned:
|
|
4032
|
-
truncated:
|
|
4033
|
-
...
|
|
4034
|
-
next: { toolEquivalent:
|
|
4045
|
+
command: input2.result.command,
|
|
4046
|
+
format: input2.format,
|
|
4047
|
+
row_count: input2.result.row_count,
|
|
4048
|
+
row_count_returned: input2.result.row_count_returned,
|
|
4049
|
+
truncated: input2.result.truncated,
|
|
4050
|
+
...input2.outPath ? { file: input2.outPath, local: { file: input2.outPath } } : {},
|
|
4051
|
+
next: { toolEquivalent: input2.toolCommand },
|
|
4035
4052
|
render: {
|
|
4036
4053
|
sections: [
|
|
4037
4054
|
{
|
|
4038
4055
|
title: "customer db export",
|
|
4039
4056
|
lines: [
|
|
4040
|
-
`Rendered ${
|
|
4057
|
+
`Rendered ${input2.result.row_count_returned} row(s) as ${input2.format} to ${destination}`
|
|
4041
4058
|
]
|
|
4042
4059
|
}
|
|
4043
4060
|
],
|
|
4044
|
-
actions: [{ label: "Tool equivalent", command:
|
|
4061
|
+
actions: [{ label: "Tool equivalent", command: input2.toolCommand }]
|
|
4045
4062
|
}
|
|
4046
4063
|
};
|
|
4047
4064
|
}
|
|
@@ -4479,16 +4496,63 @@ var PLAY_RUNTIME_FEATURES = [
|
|
|
4479
4496
|
"durable_sleep",
|
|
4480
4497
|
"packaged_files"
|
|
4481
4498
|
];
|
|
4482
|
-
function buildPlayContractCompatibility(
|
|
4499
|
+
function buildPlayContractCompatibility(input2) {
|
|
4483
4500
|
return {
|
|
4484
4501
|
apiVersion: PLAY_PUBLIC_API_VERSION,
|
|
4485
4502
|
artifactVersion: PLAY_ARTIFACT_VERSION,
|
|
4486
4503
|
minRunnerVersion: PLAY_MIN_RUNNER_VERSION,
|
|
4487
4504
|
runtimeFeatures: [...PLAY_RUNTIME_FEATURES],
|
|
4488
|
-
runtimeBackend:
|
|
4505
|
+
runtimeBackend: input2?.runtimeBackend ?? null
|
|
4489
4506
|
};
|
|
4490
4507
|
}
|
|
4491
4508
|
|
|
4509
|
+
// ../shared_libs/plays/secret-guardrails.ts
|
|
4510
|
+
var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
|
|
4511
|
+
var PRIVATE_KEY_PATTERN = /-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/;
|
|
4512
|
+
var BEARER_LITERAL_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/i;
|
|
4513
|
+
var ASSIGNMENT_SECRET_LITERAL_PATTERN = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*['"][^'"]{12,}['"]/i;
|
|
4514
|
+
var HIGH_ENTROPY_LITERAL_PATTERN = /['"]([A-Za-z0-9+/=_-]{32,})['"]/g;
|
|
4515
|
+
function shannonEntropy(value) {
|
|
4516
|
+
const counts = /* @__PURE__ */ new Map();
|
|
4517
|
+
for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
|
|
4518
|
+
return [...counts.values()].reduce((entropy, count) => {
|
|
4519
|
+
const p = count / value.length;
|
|
4520
|
+
return entropy - p * Math.log2(p);
|
|
4521
|
+
}, 0);
|
|
4522
|
+
}
|
|
4523
|
+
function validatePlaySourceHasNoInlineSecrets(input2) {
|
|
4524
|
+
const findings = [];
|
|
4525
|
+
for (const match of input2.sourceCode.matchAll(SECRET_ENV_PATTERN)) {
|
|
4526
|
+
findings.push(`process.env.${match[1]}`);
|
|
4527
|
+
}
|
|
4528
|
+
if (PRIVATE_KEY_PATTERN.test(input2.sourceCode)) findings.push("private key block");
|
|
4529
|
+
if (BEARER_LITERAL_PATTERN.test(input2.sourceCode)) findings.push("bearer token literal");
|
|
4530
|
+
if (ASSIGNMENT_SECRET_LITERAL_PATTERN.test(input2.sourceCode)) {
|
|
4531
|
+
findings.push("secret-looking assignment literal");
|
|
4532
|
+
}
|
|
4533
|
+
for (const match of input2.sourceCode.matchAll(HIGH_ENTROPY_LITERAL_PATTERN)) {
|
|
4534
|
+
const literal = match[1] ?? "";
|
|
4535
|
+
if (literal.length >= 40 && shannonEntropy(literal) >= 4.2) {
|
|
4536
|
+
findings.push("high-entropy string literal");
|
|
4537
|
+
break;
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4540
|
+
if (!findings.length) return;
|
|
4541
|
+
throw new Error(
|
|
4542
|
+
[
|
|
4543
|
+
`Play source ${input2.filePath} appears to contain inline secret material: ${[
|
|
4544
|
+
...new Set(findings)
|
|
4545
|
+
].join(", ")}.`,
|
|
4546
|
+
'Author secrets in the dashboard and use ctx.secrets.get("NAME") with an approved helper such as ctx.secrets.bearer(handle).'
|
|
4547
|
+
].join(" ")
|
|
4548
|
+
);
|
|
4549
|
+
}
|
|
4550
|
+
function validatePlaySourceFilesHaveNoInlineSecrets(sourceFiles) {
|
|
4551
|
+
for (const [filePath, sourceCode] of Object.entries(sourceFiles)) {
|
|
4552
|
+
validatePlaySourceHasNoInlineSecrets({ filePath, sourceCode });
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
|
|
4492
4556
|
// ../shared_libs/plays/bundling/index.ts
|
|
4493
4557
|
var PLAY_BUNDLE_CACHE_VERSION = 24;
|
|
4494
4558
|
var MAX_PLAY_BUNDLE_BYTES = 30 * 1024 * 1024;
|
|
@@ -4550,12 +4614,12 @@ function createPlayWorkspace(entryFile) {
|
|
|
4550
4614
|
function isPathInsideDirectory(filePath, directory) {
|
|
4551
4615
|
return filePath === directory || filePath.startsWith(`${directory}/`);
|
|
4552
4616
|
}
|
|
4553
|
-
function assertWithinPlayWorkspace(
|
|
4554
|
-
if (isPathInsideDirectory(
|
|
4617
|
+
function assertWithinPlayWorkspace(input2) {
|
|
4618
|
+
if (isPathInsideDirectory(input2.resolvedPath, input2.workspace.rootDir)) {
|
|
4555
4619
|
return;
|
|
4556
4620
|
}
|
|
4557
4621
|
throw new Error(
|
|
4558
|
-
`${
|
|
4622
|
+
`${input2.importer}:${input2.line}:${input2.column} Local play imports must stay inside the play workspace (${input2.workspace.rootDir}). Import "${input2.specifier}" resolved to ${input2.resolvedPath}, which crosses into app/backend code. Use the public SDK/API surface or move shared helpers into the play workspace.`
|
|
4559
4623
|
);
|
|
4560
4624
|
}
|
|
4561
4625
|
function getPackageName(specifier) {
|
|
@@ -5410,6 +5474,15 @@ entry-export:${exportName}`
|
|
|
5410
5474
|
workers-harness:${harnessFingerprint}`
|
|
5411
5475
|
);
|
|
5412
5476
|
}
|
|
5477
|
+
try {
|
|
5478
|
+
validatePlaySourceFilesHaveNoInlineSecrets(analysis.sourceFiles);
|
|
5479
|
+
} catch (error) {
|
|
5480
|
+
return {
|
|
5481
|
+
success: false,
|
|
5482
|
+
filePath: absolutePath,
|
|
5483
|
+
errors: [error instanceof Error ? error.message : String(error)]
|
|
5484
|
+
};
|
|
5485
|
+
}
|
|
5413
5486
|
const typecheckErrors = [
|
|
5414
5487
|
...await adapter.typecheckPlaySource?.({
|
|
5415
5488
|
sourceCode: analysis.sourceCode,
|
|
@@ -6012,11 +6085,13 @@ function createSdkPlayBundlingAdapter() {
|
|
|
6012
6085
|
};
|
|
6013
6086
|
}
|
|
6014
6087
|
async function bundlePlayFile2(filePath, options = {}) {
|
|
6015
|
-
|
|
6088
|
+
const result = await bundlePlayFile(filePath, {
|
|
6016
6089
|
target: options.target ?? defaultPlayBundleTarget(),
|
|
6017
6090
|
exportName: options.exportName,
|
|
6018
6091
|
adapter: createSdkPlayBundlingAdapter()
|
|
6019
6092
|
});
|
|
6093
|
+
if (result.success) validatePlaySourceFilesHaveNoInlineSecrets(result.sourceFiles);
|
|
6094
|
+
return result;
|
|
6020
6095
|
}
|
|
6021
6096
|
|
|
6022
6097
|
// src/cli/commands/plays/bootstrap.ts
|
|
@@ -6610,28 +6685,28 @@ function objectPropertySchema(schema, property) {
|
|
|
6610
6685
|
function finderResultTypeName(finder) {
|
|
6611
6686
|
return finder === "email_finder" ? "EmailFinderPlayResult" : "PhoneFinderPlayResult";
|
|
6612
6687
|
}
|
|
6613
|
-
function renderFinderPlayResultType(
|
|
6614
|
-
if (!
|
|
6615
|
-
const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[
|
|
6688
|
+
function renderFinderPlayResultType(input2) {
|
|
6689
|
+
if (!input2.play) return null;
|
|
6690
|
+
const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input2.finder];
|
|
6616
6691
|
const fieldSchema = objectPropertySchema(
|
|
6617
|
-
|
|
6692
|
+
input2.play.outputSchema,
|
|
6618
6693
|
outputField
|
|
6619
6694
|
);
|
|
6620
6695
|
const fieldType = fieldSchema ? jsonSchemaTypeExpression(fieldSchema) : "string | null";
|
|
6621
|
-
return `type ${finderResultTypeName(
|
|
6696
|
+
return `type ${finderResultTypeName(input2.finder)} =
|
|
6622
6697
|
| string
|
|
6623
6698
|
| null
|
|
6624
6699
|
| {
|
|
6625
6700
|
${outputField}?: ${fieldType};
|
|
6626
6701
|
};`;
|
|
6627
6702
|
}
|
|
6628
|
-
function generatedFinderPlayResultTypes(
|
|
6703
|
+
function generatedFinderPlayResultTypes(input2) {
|
|
6629
6704
|
return ["email_finder", "phone_finder"].flatMap((finder) => {
|
|
6630
|
-
const stage = finderStage(
|
|
6705
|
+
const stage = finderStage(input2.options, finder);
|
|
6631
6706
|
if (stage?.kind !== "play") return [];
|
|
6632
6707
|
const typeDefinition = renderFinderPlayResultType({
|
|
6633
6708
|
finder,
|
|
6634
|
-
play:
|
|
6709
|
+
play: input2.finderPlays[finder]
|
|
6635
6710
|
});
|
|
6636
6711
|
return typeDefinition ? [typeDefinition] : [];
|
|
6637
6712
|
}).join("\n\n");
|
|
@@ -6689,8 +6764,8 @@ function generateCompanyInputObjectFromSchema(schema, indent, label, fallbackFie
|
|
|
6689
6764
|
${lines.join("\n")}
|
|
6690
6765
|
${indent.slice(2)}}`;
|
|
6691
6766
|
}
|
|
6692
|
-
function generateSourceProviderInputObject(
|
|
6693
|
-
const { tool, indent, label, entity } =
|
|
6767
|
+
function generateSourceProviderInputObject(input2) {
|
|
6768
|
+
const { tool, indent, label, entity } = input2;
|
|
6694
6769
|
const properties = inputPropertyNames(tool?.inputSchema);
|
|
6695
6770
|
const details = schemaFieldDetails(tool?.inputSchema);
|
|
6696
6771
|
const required = details.required;
|
|
@@ -6748,8 +6823,8 @@ function generateSourceProviderInputObject(input) {
|
|
|
6748
6823
|
${lines.join("\n")}
|
|
6749
6824
|
${indent.slice(2)}}`;
|
|
6750
6825
|
}
|
|
6751
|
-
function generatePlayInputObject(
|
|
6752
|
-
const { schema, indent, label, entity } =
|
|
6826
|
+
function generatePlayInputObject(input2) {
|
|
6827
|
+
const { schema, indent, label, entity } = input2;
|
|
6753
6828
|
const details = schemaFieldDetails(schema);
|
|
6754
6829
|
const fallback = entity === "company" ? ["domain", "company_name"] : ["first_name", "last_name", "domain"];
|
|
6755
6830
|
const required = details.required.length ? details.required : fallback;
|
|
@@ -6816,80 +6891,80 @@ function needsWhenImport(options) {
|
|
|
6816
6891
|
function sourceCollectionTypeName(entity) {
|
|
6817
6892
|
return entity === "company" ? "CompanySourceRow" : "ContactSourceRow";
|
|
6818
6893
|
}
|
|
6819
|
-
function renderPartialRowType(
|
|
6820
|
-
if (
|
|
6821
|
-
return `type ${
|
|
6894
|
+
function renderPartialRowType(input2) {
|
|
6895
|
+
if (input2.fields.length === 0) {
|
|
6896
|
+
return `type ${input2.typeName} = Record<string, unknown>;`;
|
|
6822
6897
|
}
|
|
6823
|
-
const properties =
|
|
6824
|
-
return `type ${
|
|
6825
|
-
// ${
|
|
6898
|
+
const properties = input2.fields.map((field) => ` ${jsString(field)}?: unknown;`).join("\n");
|
|
6899
|
+
return `type ${input2.typeName} = Record<string, unknown> & Partial<{
|
|
6900
|
+
// ${input2.comment}
|
|
6826
6901
|
${properties}
|
|
6827
6902
|
}>;`;
|
|
6828
6903
|
}
|
|
6829
|
-
function fieldsFromSchemaDetails(
|
|
6904
|
+
function fieldsFromSchemaDetails(input2) {
|
|
6830
6905
|
return [
|
|
6831
|
-
...
|
|
6832
|
-
...
|
|
6906
|
+
...input2.details.required.length ? input2.details.required : input2.fallbackFields,
|
|
6907
|
+
...input2.details.optional
|
|
6833
6908
|
];
|
|
6834
6909
|
}
|
|
6835
|
-
function schemaFieldsForStage(stage,
|
|
6910
|
+
function schemaFieldsForStage(stage, input2) {
|
|
6836
6911
|
switch (stage?.kind) {
|
|
6837
6912
|
case void 0:
|
|
6838
6913
|
return [];
|
|
6839
6914
|
case "play":
|
|
6840
6915
|
return fieldsFromSchemaDetails({
|
|
6841
|
-
details: schemaFieldDetails(
|
|
6842
|
-
fallbackFields:
|
|
6916
|
+
details: schemaFieldDetails(input2.play?.inputSchema),
|
|
6917
|
+
fallbackFields: input2.fallbackFields
|
|
6843
6918
|
});
|
|
6844
6919
|
case "providers":
|
|
6845
|
-
return
|
|
6920
|
+
return input2.tools.flatMap(
|
|
6846
6921
|
(tool) => fieldsFromSchemaDetails({
|
|
6847
6922
|
details: schemaFieldDetails(tool.inputSchema),
|
|
6848
|
-
fallbackFields:
|
|
6923
|
+
fallbackFields: input2.fallbackFields
|
|
6849
6924
|
})
|
|
6850
6925
|
);
|
|
6851
6926
|
}
|
|
6852
6927
|
}
|
|
6853
|
-
function sourceRowTypeDefinition(
|
|
6854
|
-
switch (
|
|
6928
|
+
function sourceRowTypeDefinition(input2) {
|
|
6929
|
+
switch (input2.options.from.kind) {
|
|
6855
6930
|
case "csv":
|
|
6856
|
-
return `type ${
|
|
6931
|
+
return `type ${input2.sourceTypeName} = SourceCsvRow;`;
|
|
6857
6932
|
case "providers":
|
|
6858
6933
|
return renderPartialRowType({
|
|
6859
|
-
typeName:
|
|
6934
|
+
typeName: input2.sourceTypeName,
|
|
6860
6935
|
fields: [
|
|
6861
|
-
...new Set(
|
|
6936
|
+
...new Set(input2.sourceTools.flatMap(listRowCandidateKeysFromTool))
|
|
6862
6937
|
].sort(),
|
|
6863
6938
|
comment: "Candidate source row keys from described list getters; confirm the actual provider keys with source_*.extractedLists.*.keys before mapping."
|
|
6864
6939
|
});
|
|
6865
6940
|
case "play": {
|
|
6866
|
-
const details = schemaFieldDetails(
|
|
6941
|
+
const details = schemaFieldDetails(input2.sourcePlay?.outputSchema);
|
|
6867
6942
|
return renderPartialRowType({
|
|
6868
|
-
typeName:
|
|
6943
|
+
typeName: input2.sourceTypeName,
|
|
6869
6944
|
fields: [...details.required, ...details.optional].sort(),
|
|
6870
6945
|
comment: "Candidate source play output fields; confirm the selected rows field before mapping."
|
|
6871
6946
|
});
|
|
6872
6947
|
}
|
|
6873
6948
|
}
|
|
6874
6949
|
}
|
|
6875
|
-
function contactBridgeRowTypeDefinition(
|
|
6876
|
-
const config = playBootstrapTemplateConfig(
|
|
6877
|
-
if (config.sourceEntity !== "company" || !
|
|
6878
|
-
const emailFields = schemaFieldsForStage(
|
|
6879
|
-
tools:
|
|
6880
|
-
play:
|
|
6950
|
+
function contactBridgeRowTypeDefinition(input2) {
|
|
6951
|
+
const config = playBootstrapTemplateConfig(input2.options.template);
|
|
6952
|
+
if (config.sourceEntity !== "company" || !input2.options.people) return null;
|
|
6953
|
+
const emailFields = schemaFieldsForStage(input2.options.email, {
|
|
6954
|
+
tools: input2.finderTools.email_finder ?? [],
|
|
6955
|
+
play: input2.finderPlays.email_finder,
|
|
6881
6956
|
fallbackFields: ["first_name", "last_name", "domain"]
|
|
6882
6957
|
});
|
|
6883
|
-
const phoneFields = schemaFieldsForStage(
|
|
6884
|
-
tools:
|
|
6885
|
-
play:
|
|
6958
|
+
const phoneFields = schemaFieldsForStage(input2.options.phone, {
|
|
6959
|
+
tools: input2.finderTools.phone_finder ?? [],
|
|
6960
|
+
play: input2.finderPlays.phone_finder,
|
|
6886
6961
|
fallbackFields: ["first_name", "last_name", "domain"]
|
|
6887
6962
|
});
|
|
6888
6963
|
return renderPartialRowType({
|
|
6889
6964
|
typeName: "ContactSourceRow",
|
|
6890
6965
|
fields: [
|
|
6891
6966
|
.../* @__PURE__ */ new Set([
|
|
6892
|
-
...inputPropertyNames(
|
|
6967
|
+
...inputPropertyNames(input2.peoplePlay?.outputSchema),
|
|
6893
6968
|
...emailFields,
|
|
6894
6969
|
...phoneFields
|
|
6895
6970
|
])
|
|
@@ -6897,27 +6972,27 @@ function contactBridgeRowTypeDefinition(input) {
|
|
|
6897
6972
|
comment: "Fields the people play or later finder stages may need; the generated code still requires explicit mapping."
|
|
6898
6973
|
});
|
|
6899
6974
|
}
|
|
6900
|
-
function generateRowTypeDefinitions(
|
|
6901
|
-
const config = playBootstrapTemplateConfig(
|
|
6975
|
+
function generateRowTypeDefinitions(input2) {
|
|
6976
|
+
const config = playBootstrapTemplateConfig(input2.options.template);
|
|
6902
6977
|
const sourceTypeName = sourceCollectionTypeName(config.sourceEntity);
|
|
6903
6978
|
const definitions = [
|
|
6904
6979
|
sourceRowTypeDefinition({
|
|
6905
|
-
options:
|
|
6980
|
+
options: input2.options,
|
|
6906
6981
|
sourceTypeName,
|
|
6907
|
-
sourceTools:
|
|
6908
|
-
sourcePlay:
|
|
6982
|
+
sourceTools: input2.sourceTools,
|
|
6983
|
+
sourcePlay: input2.sourcePlay
|
|
6909
6984
|
}),
|
|
6910
|
-
contactBridgeRowTypeDefinition(
|
|
6985
|
+
contactBridgeRowTypeDefinition(input2)
|
|
6911
6986
|
];
|
|
6912
6987
|
return definitions.filter(Boolean).join("\n\n");
|
|
6913
6988
|
}
|
|
6914
|
-
function validateBootstrapRoutes(
|
|
6915
|
-
const config = playBootstrapTemplateConfig(
|
|
6989
|
+
function validateBootstrapRoutes(input2) {
|
|
6990
|
+
const config = playBootstrapTemplateConfig(input2.options.template);
|
|
6916
6991
|
const sourceCategory = config.sourceEntity === "company" ? PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY : PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY;
|
|
6917
|
-
for (const tool of
|
|
6992
|
+
for (const tool of input2.sourceTools) {
|
|
6918
6993
|
if (!tool.categories.includes(sourceCategory)) {
|
|
6919
6994
|
throw new PlayBootstrapValidationError(
|
|
6920
|
-
`Cannot use ${tool.toolId} as a ${config.sourceEntity} source for ${
|
|
6995
|
+
`Cannot use ${tool.toolId} as a ${config.sourceEntity} source for ${input2.options.template}: expected category ${sourceCategory}, got ${tool.categories.join(", ") || "none"}. Run: deepline tools grep ${sourceCategory} --categories ${sourceCategory} --json`
|
|
6921
6996
|
);
|
|
6922
6997
|
}
|
|
6923
6998
|
if (getterNamesFromTool(tool, "list").length === 0) {
|
|
@@ -6926,14 +7001,14 @@ function validateBootstrapRoutes(input) {
|
|
|
6926
7001
|
);
|
|
6927
7002
|
}
|
|
6928
7003
|
}
|
|
6929
|
-
if (
|
|
7004
|
+
if (input2.options.people?.kind === "providers") {
|
|
6930
7005
|
throw new PlayBootstrapValidationError(
|
|
6931
7006
|
"Company-to-people bootstrap only accepts --people play:<play-ref> for now. Providers are too task-specific; choose or create a people play so the generated file can show the mapping contract."
|
|
6932
7007
|
);
|
|
6933
7008
|
}
|
|
6934
7009
|
for (const finder of ["email_finder", "phone_finder"]) {
|
|
6935
7010
|
const requiredCategory = PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER[finder];
|
|
6936
|
-
for (const tool of
|
|
7011
|
+
for (const tool of input2.finderTools[finder] ?? []) {
|
|
6937
7012
|
if (!tool.categories.includes(requiredCategory)) {
|
|
6938
7013
|
throw new PlayBootstrapValidationError(
|
|
6939
7014
|
`Cannot use ${tool.toolId} for ${finder}: expected category ${requiredCategory}, got ${tool.categories.join(", ") || "none"}. Run: deepline tools grep ${requiredCategory} --categories ${requiredCategory} --json`
|
|
@@ -6955,118 +7030,118 @@ function sourceCollectionName(entity) {
|
|
|
6955
7030
|
return "contacts";
|
|
6956
7031
|
}
|
|
6957
7032
|
}
|
|
6958
|
-
function requiredGetterName(
|
|
6959
|
-
const getter = getterNamesFromTool(
|
|
7033
|
+
function requiredGetterName(input2) {
|
|
7034
|
+
const getter = getterNamesFromTool(input2.tool, input2.kind)[0];
|
|
6960
7035
|
if (!getter) {
|
|
6961
|
-
switch (
|
|
7036
|
+
switch (input2.kind) {
|
|
6962
7037
|
case "list":
|
|
6963
7038
|
throw new PlayBootstrapValidationError(
|
|
6964
|
-
`Cannot use ${
|
|
7039
|
+
`Cannot use ${input2.label} as a source: it exposes no extracted list getters.`
|
|
6965
7040
|
);
|
|
6966
7041
|
case "value":
|
|
6967
7042
|
throw new PlayBootstrapValidationError(
|
|
6968
|
-
`Cannot use ${
|
|
7043
|
+
`Cannot use ${input2.label} as a finder: it exposes no extracted value getters.`
|
|
6969
7044
|
);
|
|
6970
7045
|
}
|
|
6971
7046
|
}
|
|
6972
7047
|
return getter;
|
|
6973
7048
|
}
|
|
6974
|
-
function generateCsvSourceRowsBlock(
|
|
6975
|
-
return `const sourceDataset = await ctx.csv<SourceCsvRow>(${jsString(
|
|
6976
|
-
const ${
|
|
7049
|
+
function generateCsvSourceRowsBlock(input2) {
|
|
7050
|
+
return `const sourceDataset = await ctx.csv<SourceCsvRow>(${jsString(input2.packagedSourceCsvPath ?? input2.source.value)});
|
|
7051
|
+
const ${input2.collection}: ${input2.collectionType}[] = await sourceDataset.peek(limit);`;
|
|
6977
7052
|
}
|
|
6978
|
-
function generatePlaySourceRowsBlock(
|
|
7053
|
+
function generatePlaySourceRowsBlock(input2) {
|
|
6979
7054
|
const playInput = generatePlayInputObject({
|
|
6980
|
-
schema:
|
|
7055
|
+
schema: input2.sourcePlay?.inputSchema,
|
|
6981
7056
|
indent: " ",
|
|
6982
|
-
label:
|
|
6983
|
-
entity:
|
|
7057
|
+
label: input2.source.value,
|
|
7058
|
+
entity: input2.entity
|
|
6984
7059
|
});
|
|
6985
7060
|
return `const sourceInput = ${playInput};
|
|
6986
|
-
throw new Error(${jsString(`TODO: map sourceInput for ${
|
|
6987
|
-
const sourceResult = await ctx.runPlay('source_play', ${jsString(
|
|
6988
|
-
description: ${jsString(`Seed ${
|
|
7061
|
+
throw new Error(${jsString(`TODO: map sourceInput for ${input2.source.value}, choose the play output rows field, then delete this throw.`)});
|
|
7062
|
+
const sourceResult = await ctx.runPlay('source_play', ${jsString(input2.source.value)}, sourceInput, {
|
|
7063
|
+
description: ${jsString(`Seed ${input2.entity} rows from the selected play.`)},
|
|
6989
7064
|
});
|
|
6990
7065
|
// TODO: Replace sourceResult.rows with the selected play's actual row output field.
|
|
6991
|
-
const ${
|
|
7066
|
+
const ${input2.collection}: ${input2.collectionType}[] = (sourceResult.rows ?? []) as ${input2.collectionType}[];`;
|
|
6992
7067
|
}
|
|
6993
|
-
function generateProviderSourceBlock(
|
|
7068
|
+
function generateProviderSourceBlock(input2) {
|
|
6994
7069
|
const getter = requiredGetterName({
|
|
6995
|
-
tool:
|
|
7070
|
+
tool: input2.tool,
|
|
6996
7071
|
kind: "list",
|
|
6997
|
-
label:
|
|
7072
|
+
label: input2.provider
|
|
6998
7073
|
});
|
|
6999
|
-
const inputName = `${
|
|
7000
|
-
return `// ${
|
|
7074
|
+
const inputName = `${input2.entity}Input_${input2.index}`;
|
|
7075
|
+
return `// ${input2.entity === "company" ? "Company" : "People"} source provider: ${input2.provider}
|
|
7001
7076
|
const ${inputName}: Record<string, unknown> = ${generateSourceProviderInputObject(
|
|
7002
7077
|
{
|
|
7003
|
-
tool:
|
|
7078
|
+
tool: input2.tool,
|
|
7004
7079
|
indent: " ",
|
|
7005
|
-
label:
|
|
7006
|
-
entity:
|
|
7080
|
+
label: input2.provider,
|
|
7081
|
+
entity: input2.entity
|
|
7007
7082
|
}
|
|
7008
7083
|
)};
|
|
7009
|
-
throw new Error(${jsString(`TODO: fill ${inputName} for ${
|
|
7010
|
-
const source_${
|
|
7011
|
-
id: ${jsString(`${
|
|
7012
|
-
tool: ${jsString(
|
|
7084
|
+
throw new Error(${jsString(`TODO: fill ${inputName} for ${input2.provider}, then delete this throw.`)});
|
|
7085
|
+
const source_${input2.index} = await ctx.tools.execute({
|
|
7086
|
+
id: ${jsString(`${input2.entity}_source_${input2.index}`)},
|
|
7087
|
+
tool: ${jsString(input2.provider)},
|
|
7013
7088
|
input: ${inputName},
|
|
7014
|
-
description: ${jsString(`Seed ${
|
|
7089
|
+
description: ${jsString(`Seed ${input2.entity} rows from ${input2.provider}.`)},
|
|
7015
7090
|
});
|
|
7016
7091
|
// extractedLists.${getter}.get() returns provider-shaped rows. Do not assume canonical fields;
|
|
7017
|
-
// inspect source_${
|
|
7018
|
-
const sourceRows_${
|
|
7092
|
+
// inspect source_${input2.index}.extractedLists.${getter}.keys or the provider output schema, then map explicitly below.
|
|
7093
|
+
const sourceRows_${input2.index} = ${accessorExpression(`source_${input2.index}.extractedLists`, getter)}.get() as ${input2.collectionType}[];`;
|
|
7019
7094
|
}
|
|
7020
|
-
function generateProviderSourceRowsBlock(
|
|
7021
|
-
const blocks =
|
|
7095
|
+
function generateProviderSourceRowsBlock(input2) {
|
|
7096
|
+
const blocks = input2.source.values.map(
|
|
7022
7097
|
(provider, index) => generateProviderSourceBlock({
|
|
7023
7098
|
provider,
|
|
7024
7099
|
index,
|
|
7025
|
-
tool:
|
|
7026
|
-
entity:
|
|
7027
|
-
collectionType:
|
|
7100
|
+
tool: input2.sourceTools[index] ?? null,
|
|
7101
|
+
entity: input2.entity,
|
|
7102
|
+
collectionType: input2.collectionType
|
|
7028
7103
|
})
|
|
7029
7104
|
);
|
|
7030
7105
|
return `${blocks.join("\n\n ")}
|
|
7031
|
-
const ${
|
|
7106
|
+
const ${input2.collection}: ${input2.collectionType}[] = [${input2.source.values.map((_, index) => `...sourceRows_${index}`).join(", ")}];`;
|
|
7032
7107
|
}
|
|
7033
|
-
function generateSourceRowsBlock(
|
|
7034
|
-
const config = playBootstrapTemplateConfig(
|
|
7108
|
+
function generateSourceRowsBlock(input2) {
|
|
7109
|
+
const config = playBootstrapTemplateConfig(input2.options.template);
|
|
7035
7110
|
const entity = config.sourceEntity;
|
|
7036
7111
|
const collection = sourceCollectionName(entity);
|
|
7037
7112
|
const collectionType = sourceCollectionTypeName(entity);
|
|
7038
|
-
switch (
|
|
7113
|
+
switch (input2.options.from.kind) {
|
|
7039
7114
|
case "csv":
|
|
7040
7115
|
return generateCsvSourceRowsBlock({
|
|
7041
|
-
source:
|
|
7116
|
+
source: input2.options.from,
|
|
7042
7117
|
collection,
|
|
7043
7118
|
collectionType,
|
|
7044
|
-
packagedSourceCsvPath:
|
|
7119
|
+
packagedSourceCsvPath: input2.packagedSourceCsvPath
|
|
7045
7120
|
});
|
|
7046
7121
|
case "play":
|
|
7047
7122
|
return generatePlaySourceRowsBlock({
|
|
7048
|
-
source:
|
|
7049
|
-
sourcePlay:
|
|
7123
|
+
source: input2.options.from,
|
|
7124
|
+
sourcePlay: input2.sourcePlay,
|
|
7050
7125
|
entity,
|
|
7051
7126
|
collection,
|
|
7052
7127
|
collectionType
|
|
7053
7128
|
});
|
|
7054
7129
|
case "providers":
|
|
7055
7130
|
return generateProviderSourceRowsBlock({
|
|
7056
|
-
source:
|
|
7057
|
-
sourceTools:
|
|
7131
|
+
source: input2.options.from,
|
|
7132
|
+
sourceTools: input2.sourceTools,
|
|
7058
7133
|
entity,
|
|
7059
7134
|
collection,
|
|
7060
7135
|
collectionType
|
|
7061
7136
|
});
|
|
7062
7137
|
}
|
|
7063
7138
|
}
|
|
7064
|
-
function generateSourceSeedBlock(
|
|
7065
|
-
const sourceRows = generateSourceRowsBlock(
|
|
7066
|
-
const peoplePlayRef = stagePlayRef(
|
|
7139
|
+
function generateSourceSeedBlock(input2) {
|
|
7140
|
+
const sourceRows = generateSourceRowsBlock(input2);
|
|
7141
|
+
const peoplePlayRef = stagePlayRef(input2.options.people);
|
|
7067
7142
|
if (!peoplePlayRef) return sourceRows;
|
|
7068
7143
|
const peopleInput = generateCompanyInputObjectFromSchema(
|
|
7069
|
-
|
|
7144
|
+
input2.peoplePlay?.inputSchema,
|
|
7070
7145
|
" ",
|
|
7071
7146
|
peoplePlayRef,
|
|
7072
7147
|
["domain", "company_name"]
|
|
@@ -7088,15 +7163,15 @@ function generateSourceSeedBlock(input) {
|
|
|
7088
7163
|
contacts.push(...((peopleResult.rows ?? []) as ContactSourceRow[]));
|
|
7089
7164
|
}`;
|
|
7090
7165
|
}
|
|
7091
|
-
function finderProviderStepName(
|
|
7092
|
-
return `${
|
|
7166
|
+
function finderProviderStepName(input2) {
|
|
7167
|
+
return `${input2.aggregateStepName}${input2.index}_${safeIdentifier(input2.provider)}`;
|
|
7093
7168
|
}
|
|
7094
|
-
function finderValueGetter(
|
|
7095
|
-
const getters = getterNamesFromTool(
|
|
7096
|
-
const getter = getters.find((name) => name ===
|
|
7097
|
-
tool:
|
|
7169
|
+
function finderValueGetter(input2) {
|
|
7170
|
+
const getters = getterNamesFromTool(input2.tool, "value");
|
|
7171
|
+
const getter = getters.find((name) => name === input2.outputField) ?? requiredGetterName({
|
|
7172
|
+
tool: input2.tool,
|
|
7098
7173
|
kind: "value",
|
|
7099
|
-
label:
|
|
7174
|
+
label: input2.provider
|
|
7100
7175
|
});
|
|
7101
7176
|
return getter;
|
|
7102
7177
|
}
|
|
@@ -7104,157 +7179,157 @@ function optionalFinderValueExpression(candidateExpression, outputField) {
|
|
|
7104
7179
|
const valueExpression = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(outputField) ? `${candidateExpression}?.${outputField}` : `${candidateExpression}?.[${jsString(outputField)}]`;
|
|
7105
7180
|
return `${valueExpression}?.trim()`;
|
|
7106
7181
|
}
|
|
7107
|
-
function generateFinderPlayStep(
|
|
7108
|
-
const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[
|
|
7109
|
-
const resultTypeName = finderResultTypeName(
|
|
7182
|
+
function generateFinderPlayStep(input2) {
|
|
7183
|
+
const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input2.finder];
|
|
7184
|
+
const resultTypeName = finderResultTypeName(input2.finder);
|
|
7110
7185
|
const payload = generateContactInputObjectFromSchema(
|
|
7111
|
-
|
|
7186
|
+
input2.play?.inputSchema,
|
|
7112
7187
|
" ",
|
|
7113
|
-
|
|
7188
|
+
input2.stage.value
|
|
7114
7189
|
);
|
|
7115
7190
|
return `.step(${jsString(outputField)}, async (row, rowCtx) => {
|
|
7116
|
-
const ${
|
|
7117
|
-
throw new Error(${jsString(`TODO: map ${
|
|
7118
|
-
const ${
|
|
7119
|
-
${jsString(`${
|
|
7120
|
-
${jsString(
|
|
7121
|
-
${
|
|
7191
|
+
const ${input2.aggregateStepName}Input = ${payload};
|
|
7192
|
+
throw new Error(${jsString(`TODO: map ${input2.aggregateStepName}Input for ${input2.stage.value}, then delete this throw.`)});
|
|
7193
|
+
const ${input2.aggregateStepName}Result = await rowCtx.runPlay<${resultTypeName}>(
|
|
7194
|
+
${jsString(`${input2.aggregateStepName}Play`)},
|
|
7195
|
+
${jsString(input2.stage.value)},
|
|
7196
|
+
${input2.aggregateStepName}Input,
|
|
7122
7197
|
{
|
|
7123
|
-
description: ${jsString(`Run ${
|
|
7198
|
+
description: ${jsString(`Run ${input2.finder} play.`)},
|
|
7124
7199
|
},
|
|
7125
7200
|
);
|
|
7126
|
-
return typeof ${
|
|
7127
|
-
? ${
|
|
7128
|
-
: ${
|
|
7201
|
+
return typeof ${input2.aggregateStepName}Result === 'string'
|
|
7202
|
+
? ${input2.aggregateStepName}Result.trim() || null
|
|
7203
|
+
: ${input2.aggregateStepName}Result?.${outputField} ?? null;
|
|
7129
7204
|
})`;
|
|
7130
7205
|
}
|
|
7131
|
-
function generateFinderProviderResolver(
|
|
7206
|
+
function generateFinderProviderResolver(input2) {
|
|
7132
7207
|
const payload = generateContactInputObjectFromSchema(
|
|
7133
|
-
|
|
7208
|
+
input2.tool?.inputSchema,
|
|
7134
7209
|
" ",
|
|
7135
|
-
|
|
7210
|
+
input2.provider
|
|
7136
7211
|
);
|
|
7137
7212
|
const getter = finderValueGetter({
|
|
7138
|
-
tool:
|
|
7139
|
-
provider:
|
|
7140
|
-
outputField:
|
|
7213
|
+
tool: input2.tool,
|
|
7214
|
+
provider: input2.provider,
|
|
7215
|
+
outputField: input2.outputField
|
|
7141
7216
|
});
|
|
7142
7217
|
return `async (row, rowCtx) => {
|
|
7143
7218
|
const providerInput = ${payload};
|
|
7144
|
-
throw new Error(${jsString(`TODO: map providerInput for ${
|
|
7219
|
+
throw new Error(${jsString(`TODO: map providerInput for ${input2.provider}, then delete this throw.`)});
|
|
7145
7220
|
const result = await rowCtx.tools.execute({
|
|
7146
|
-
id: ${jsString(`${
|
|
7147
|
-
tool: ${jsString(
|
|
7221
|
+
id: ${jsString(`${input2.aggregateStepName}_${input2.providerIndex}`)},
|
|
7222
|
+
tool: ${jsString(input2.provider)},
|
|
7148
7223
|
input: providerInput,
|
|
7149
|
-
description: ${jsString(`Try ${
|
|
7224
|
+
description: ${jsString(`Try ${input2.provider} as a ${input2.finder}.`)},
|
|
7150
7225
|
});
|
|
7151
7226
|
return {
|
|
7152
|
-
${
|
|
7227
|
+
${input2.outputField}: (${accessorExpression("result.extractedValues", getter)}.get() as string | null) ?? null,
|
|
7153
7228
|
result,
|
|
7154
7229
|
};
|
|
7155
7230
|
}`;
|
|
7156
7231
|
}
|
|
7157
|
-
function generateFinderProviderStep(
|
|
7158
|
-
const stepName =
|
|
7159
|
-
switch (
|
|
7232
|
+
function generateFinderProviderStep(input2) {
|
|
7233
|
+
const stepName = input2.stepNames[input2.index];
|
|
7234
|
+
switch (input2.index) {
|
|
7160
7235
|
case 0:
|
|
7161
|
-
return `.step(${jsString(stepName)}, ${
|
|
7236
|
+
return `.step(${jsString(stepName)}, ${input2.resolver})`;
|
|
7162
7237
|
default: {
|
|
7163
|
-
const priorCandidates =
|
|
7238
|
+
const priorCandidates = input2.stepNames.slice(0, input2.index).map((name) => `row.${name}`).join(", ");
|
|
7164
7239
|
return `.step(
|
|
7165
7240
|
${jsString(stepName)},
|
|
7166
7241
|
when(
|
|
7167
|
-
(row) => ![${priorCandidates}].some((candidate) => ${optionalFinderValueExpression("candidate",
|
|
7168
|
-
${
|
|
7242
|
+
(row) => ![${priorCandidates}].some((candidate) => ${optionalFinderValueExpression("candidate", input2.outputField)}),
|
|
7243
|
+
${input2.resolver},
|
|
7169
7244
|
),
|
|
7170
7245
|
)`;
|
|
7171
7246
|
}
|
|
7172
7247
|
}
|
|
7173
7248
|
}
|
|
7174
|
-
function generateFinderProviderWaterfall(
|
|
7175
|
-
const legPrefix = finderProviderStepPrefix(
|
|
7176
|
-
const stepNames =
|
|
7249
|
+
function generateFinderProviderWaterfall(input2) {
|
|
7250
|
+
const legPrefix = finderProviderStepPrefix(input2.finder);
|
|
7251
|
+
const stepNames = input2.stage.values.map(
|
|
7177
7252
|
(provider, index) => finderProviderStepName({
|
|
7178
7253
|
aggregateStepName: legPrefix,
|
|
7179
7254
|
provider,
|
|
7180
7255
|
index
|
|
7181
7256
|
})
|
|
7182
7257
|
);
|
|
7183
|
-
const providerSteps =
|
|
7258
|
+
const providerSteps = input2.stage.values.map(
|
|
7184
7259
|
(provider, index) => generateFinderProviderStep({
|
|
7185
7260
|
index,
|
|
7186
7261
|
stepNames,
|
|
7187
|
-
outputField:
|
|
7262
|
+
outputField: input2.outputField,
|
|
7188
7263
|
resolver: generateFinderProviderResolver({
|
|
7189
|
-
finder:
|
|
7264
|
+
finder: input2.finder,
|
|
7190
7265
|
provider,
|
|
7191
7266
|
providerIndex: index,
|
|
7192
|
-
tool:
|
|
7193
|
-
aggregateStepName:
|
|
7194
|
-
outputField:
|
|
7267
|
+
tool: input2.tools[index] ?? null,
|
|
7268
|
+
aggregateStepName: input2.aggregateStepName,
|
|
7269
|
+
outputField: input2.outputField
|
|
7195
7270
|
})
|
|
7196
7271
|
})
|
|
7197
7272
|
);
|
|
7198
7273
|
const candidateNames = stepNames.map((name) => `row.${name}`).join(", ");
|
|
7199
|
-
return `// ${
|
|
7274
|
+
return `// ${input2.aggregateStepName} provider waterfall. Each provider leg is active once its TODO throw is removed;
|
|
7200
7275
|
// delete or comment out legs you do not want before running. Later legs are gated with when(...).
|
|
7201
7276
|
${providerSteps.join("\n ")}
|
|
7202
|
-
.step(${jsString(
|
|
7277
|
+
.step(${jsString(input2.aggregateStepName)}, (row) => {
|
|
7203
7278
|
const candidates = [${candidateNames}];
|
|
7204
|
-
const match = candidates.find((candidate) => ${optionalFinderValueExpression("candidate",
|
|
7205
|
-
return ${optionalFinderValueExpression("match",
|
|
7279
|
+
const match = candidates.find((candidate) => ${optionalFinderValueExpression("candidate", input2.outputField)});
|
|
7280
|
+
return ${optionalFinderValueExpression("match", input2.outputField)} ?? null;
|
|
7206
7281
|
})`;
|
|
7207
7282
|
}
|
|
7208
|
-
function generateFinderStageSteps(
|
|
7209
|
-
const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[
|
|
7210
|
-
const aggregateStepName = stepFieldName(
|
|
7211
|
-
switch (
|
|
7283
|
+
function generateFinderStageSteps(input2) {
|
|
7284
|
+
const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input2.finder];
|
|
7285
|
+
const aggregateStepName = stepFieldName(input2.finder);
|
|
7286
|
+
switch (input2.stage.kind) {
|
|
7212
7287
|
case "play":
|
|
7213
7288
|
return generateFinderPlayStep({
|
|
7214
|
-
finder:
|
|
7215
|
-
stage:
|
|
7216
|
-
play:
|
|
7289
|
+
finder: input2.finder,
|
|
7290
|
+
stage: input2.stage,
|
|
7291
|
+
play: input2.finderPlays[input2.finder],
|
|
7217
7292
|
aggregateStepName
|
|
7218
7293
|
});
|
|
7219
7294
|
case "providers":
|
|
7220
7295
|
return generateFinderProviderWaterfall({
|
|
7221
|
-
finder:
|
|
7222
|
-
stage:
|
|
7223
|
-
tools:
|
|
7296
|
+
finder: input2.finder,
|
|
7297
|
+
stage: input2.stage,
|
|
7298
|
+
tools: input2.finderTools[input2.finder] ?? [],
|
|
7224
7299
|
aggregateStepName,
|
|
7225
7300
|
outputField
|
|
7226
7301
|
});
|
|
7227
7302
|
}
|
|
7228
7303
|
}
|
|
7229
|
-
function generateFinderSteps(
|
|
7304
|
+
function generateFinderSteps(input2) {
|
|
7230
7305
|
return ["email_finder", "phone_finder"].flatMap((finder) => {
|
|
7231
|
-
const stage = finderStage(
|
|
7306
|
+
const stage = finderStage(input2.options, finder);
|
|
7232
7307
|
return stage ? [
|
|
7233
7308
|
generateFinderStageSteps({
|
|
7234
|
-
...
|
|
7309
|
+
...input2,
|
|
7235
7310
|
finder,
|
|
7236
7311
|
stage
|
|
7237
7312
|
})
|
|
7238
7313
|
] : [];
|
|
7239
7314
|
}).join("\n ");
|
|
7240
7315
|
}
|
|
7241
|
-
function generateBootstrapPlaySource(
|
|
7242
|
-
const config = playBootstrapTemplateConfig(
|
|
7243
|
-
const sourceSeedBlock = generateSourceSeedBlock(
|
|
7244
|
-
const finderSteps = generateFinderSteps(
|
|
7245
|
-
const hasPeople = config.sourceEntity === "people" || Boolean(
|
|
7316
|
+
function generateBootstrapPlaySource(input2) {
|
|
7317
|
+
const config = playBootstrapTemplateConfig(input2.options.template);
|
|
7318
|
+
const sourceSeedBlock = generateSourceSeedBlock(input2);
|
|
7319
|
+
const finderSteps = generateFinderSteps(input2);
|
|
7320
|
+
const hasPeople = config.sourceEntity === "people" || Boolean(input2.options.people);
|
|
7246
7321
|
const sourceCollection = hasPeople ? "contacts" : "companies";
|
|
7247
7322
|
const mapSteps = finderSteps ? `
|
|
7248
7323
|
${finderSteps}` : "";
|
|
7249
|
-
const sourceCsvRowType =
|
|
7250
|
-
const rowTypeDefinitions = generateRowTypeDefinitions(
|
|
7251
|
-
const finderPlayResultTypes = generatedFinderPlayResultTypes(
|
|
7324
|
+
const sourceCsvRowType = input2.options.from.kind === "csv" ? renderSourceCsvRowType(input2.sourceCsvColumns) : "";
|
|
7325
|
+
const rowTypeDefinitions = generateRowTypeDefinitions(input2);
|
|
7326
|
+
const finderPlayResultTypes = generatedFinderPlayResultTypes(input2);
|
|
7252
7327
|
const typeDefinitions = [
|
|
7253
7328
|
sourceCsvRowType.trimEnd(),
|
|
7254
7329
|
rowTypeDefinitions,
|
|
7255
7330
|
finderPlayResultTypes
|
|
7256
7331
|
].filter((definition) => definition.trim().length > 0).join("\n\n");
|
|
7257
|
-
const importNames = needsWhenImport(
|
|
7332
|
+
const importNames = needsWhenImport(input2.options) ? "definePlay, when" : "definePlay";
|
|
7258
7333
|
return `import { ${importNames} } from 'deepline';
|
|
7259
7334
|
|
|
7260
7335
|
${typeDefinitions}
|
|
@@ -7263,8 +7338,8 @@ type Input = {
|
|
|
7263
7338
|
limit?: number;
|
|
7264
7339
|
};
|
|
7265
7340
|
|
|
7266
|
-
export default definePlay(${jsString(
|
|
7267
|
-
const limit = Math.max(1, Math.min(Number(input.limit ?? ${
|
|
7341
|
+
export default definePlay(${jsString(input2.options.name)}, async (ctx, input: Input = {}) => {
|
|
7342
|
+
const limit = Math.max(1, Math.min(Number(input.limit ?? ${input2.options.limit}), ${input2.options.limit}));
|
|
7268
7343
|
${sourceSeedBlock}
|
|
7269
7344
|
|
|
7270
7345
|
const rowsToProcess = ${sourceCollection}.slice(0, limit);
|
|
@@ -7276,7 +7351,7 @@ export default definePlay(${jsString(input.options.name)}, async (ctx, input: In
|
|
|
7276
7351
|
.map('bootstrap_rows', rowsToProcess)${mapSteps}
|
|
7277
7352
|
.run({
|
|
7278
7353
|
key: (_row, index) => index,
|
|
7279
|
-
description: ${jsString(`Bootstrap ${
|
|
7354
|
+
description: ${jsString(`Bootstrap ${input2.options.template}: seed source rows, run requested stages, then return the mapped rows.`)},
|
|
7280
7355
|
});
|
|
7281
7356
|
|
|
7282
7357
|
return {
|
|
@@ -7684,8 +7759,8 @@ var SHA256_ROUND_CONSTANTS = [
|
|
|
7684
7759
|
function rightRotate32(value, bits) {
|
|
7685
7760
|
return value >>> bits | value << 32 - bits;
|
|
7686
7761
|
}
|
|
7687
|
-
function sha256Hex(
|
|
7688
|
-
const bytes = Array.from(new TextEncoder().encode(
|
|
7762
|
+
function sha256Hex(input2) {
|
|
7763
|
+
const bytes = Array.from(new TextEncoder().encode(input2));
|
|
7689
7764
|
const bitLength = bytes.length * 8;
|
|
7690
7765
|
bytes.push(128);
|
|
7691
7766
|
while (bytes.length % 64 !== 56) {
|
|
@@ -7859,10 +7934,10 @@ function looksLikeInvalidExtractedGetter(error, sourceLine) {
|
|
|
7859
7934
|
if (!/Property '[^']+' does not exist on type/.test(error)) return false;
|
|
7860
7935
|
return /\bextracted(?:Values|Lists)\s*\./.test(sourceLine);
|
|
7861
7936
|
}
|
|
7862
|
-
function addPlayCheckRepairHints(
|
|
7937
|
+
function addPlayCheckRepairHints(input2) {
|
|
7863
7938
|
let addedHint = false;
|
|
7864
|
-
return
|
|
7865
|
-
const line = sourceLineForError(
|
|
7939
|
+
return input2.errors.map((error) => {
|
|
7940
|
+
const line = sourceLineForError(input2.sourceCode, error);
|
|
7866
7941
|
if (addedHint || !looksLikeInvalidExtractedGetter(error, line) || error.includes(EXTRACTED_GETTER_ERROR_HINT)) {
|
|
7867
7942
|
return error;
|
|
7868
7943
|
}
|
|
@@ -7873,6 +7948,7 @@ ${EXTRACTED_GETTER_ERROR_HINT}`;
|
|
|
7873
7948
|
}
|
|
7874
7949
|
|
|
7875
7950
|
// src/cli/commands/play.ts
|
|
7951
|
+
var PLAY_START_STREAM_FAST_COMPLETION_WAIT_MS = 2500;
|
|
7876
7952
|
var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
7877
7953
|
"--json",
|
|
7878
7954
|
"--wait",
|
|
@@ -7924,9 +8000,9 @@ function parseReferencedPlayTarget2(target) {
|
|
|
7924
8000
|
function isPrebuiltReferenceTarget(target) {
|
|
7925
8001
|
return target.trim().toLowerCase().startsWith("prebuilt/");
|
|
7926
8002
|
}
|
|
7927
|
-
function buildBarePrebuiltReferenceError(
|
|
8003
|
+
function buildBarePrebuiltReferenceError(input2) {
|
|
7928
8004
|
return new Error(
|
|
7929
|
-
`Prebuilt play "${
|
|
8005
|
+
`Prebuilt play "${input2.requested}" must be referenced as "${input2.reference}". Use the prebuilt/ namespace anywhere you run, describe, get, or link to Deepline-managed plays.`
|
|
7930
8006
|
);
|
|
7931
8007
|
}
|
|
7932
8008
|
async function assertCanonicalNamedPlayReference(client, target) {
|
|
@@ -7969,23 +8045,23 @@ function buildCloneEditStarter(play) {
|
|
|
7969
8045
|
checkCommand: `deepline plays check ${path}`
|
|
7970
8046
|
};
|
|
7971
8047
|
}
|
|
7972
|
-
function materializeRemotePlaySource(
|
|
7973
|
-
if (isFileTarget(
|
|
8048
|
+
function materializeRemotePlaySource(input2) {
|
|
8049
|
+
if (isFileTarget(input2.target)) {
|
|
7974
8050
|
return null;
|
|
7975
8051
|
}
|
|
7976
|
-
if (!
|
|
8052
|
+
if (!input2.sourceCode.trim()) {
|
|
7977
8053
|
return null;
|
|
7978
8054
|
}
|
|
7979
|
-
const outputPath =
|
|
8055
|
+
const outputPath = input2.outPath ?? defaultMaterializedPlayPath(input2.playName);
|
|
7980
8056
|
if ((0, import_node_fs10.existsSync)(outputPath)) {
|
|
7981
8057
|
const existingSource = (0, import_node_fs10.readFileSync)(outputPath, "utf-8");
|
|
7982
|
-
if (existingSource ===
|
|
8058
|
+
if (existingSource === input2.sourceCode) {
|
|
7983
8059
|
return { path: outputPath, status: "unchanged", created: false };
|
|
7984
8060
|
}
|
|
7985
|
-
(0, import_node_fs10.writeFileSync)(outputPath,
|
|
8061
|
+
(0, import_node_fs10.writeFileSync)(outputPath, input2.sourceCode, "utf-8");
|
|
7986
8062
|
return { path: outputPath, status: "updated", created: false };
|
|
7987
8063
|
}
|
|
7988
|
-
(0, import_node_fs10.writeFileSync)(outputPath,
|
|
8064
|
+
(0, import_node_fs10.writeFileSync)(outputPath, input2.sourceCode, "utf-8");
|
|
7989
8065
|
return { path: outputPath, status: "created", created: true };
|
|
7990
8066
|
}
|
|
7991
8067
|
function formatLoadedPlayMessage(materializedFile) {
|
|
@@ -8035,12 +8111,12 @@ function isFileTarget(target) {
|
|
|
8035
8111
|
function looksLikeRunId(target) {
|
|
8036
8112
|
return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
|
|
8037
8113
|
}
|
|
8038
|
-
function formatPlayCommandReceivedRunIdError(
|
|
8039
|
-
return `\`deepline plays ${
|
|
8114
|
+
function formatPlayCommandReceivedRunIdError(input2) {
|
|
8115
|
+
return `\`deepline plays ${input2.command} <run-id>\` expects a play name, but this looks like a run id.
|
|
8040
8116
|
Use:
|
|
8041
|
-
deepline runs get ${
|
|
8042
|
-
deepline runs logs ${
|
|
8043
|
-
deepline runs export ${
|
|
8117
|
+
deepline runs get ${input2.runId} --json
|
|
8118
|
+
deepline runs logs ${input2.runId} --json
|
|
8119
|
+
deepline runs export ${input2.runId} --out output.csv`;
|
|
8044
8120
|
}
|
|
8045
8121
|
function looksLikeFilePath(target) {
|
|
8046
8122
|
if (target.trim().toLowerCase().startsWith("prebuilt/")) {
|
|
@@ -8094,9 +8170,9 @@ function parseInputFlagValue(raw) {
|
|
|
8094
8170
|
}
|
|
8095
8171
|
return raw;
|
|
8096
8172
|
}
|
|
8097
|
-
function getDottedInputValue(
|
|
8173
|
+
function getDottedInputValue(input2, path) {
|
|
8098
8174
|
const parts = path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
8099
|
-
let cursor =
|
|
8175
|
+
let cursor = input2;
|
|
8100
8176
|
for (const part of parts) {
|
|
8101
8177
|
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) {
|
|
8102
8178
|
return void 0;
|
|
@@ -8105,12 +8181,12 @@ function getDottedInputValue(input, path) {
|
|
|
8105
8181
|
}
|
|
8106
8182
|
return cursor;
|
|
8107
8183
|
}
|
|
8108
|
-
function setDottedInputValue(
|
|
8184
|
+
function setDottedInputValue(input2, path, value) {
|
|
8109
8185
|
const parts = path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
8110
8186
|
if (parts.length === 0) {
|
|
8111
8187
|
throw new Error(`Invalid play input flag path: ${path}`);
|
|
8112
8188
|
}
|
|
8113
|
-
let cursor =
|
|
8189
|
+
let cursor = input2;
|
|
8114
8190
|
for (const part of parts.slice(0, -1)) {
|
|
8115
8191
|
const existing = cursor[part];
|
|
8116
8192
|
if (existing !== void 0 && (!existing || typeof existing !== "object" || Array.isArray(existing))) {
|
|
@@ -8177,17 +8253,17 @@ function inputContainsLocalFilePath(value) {
|
|
|
8177
8253
|
}
|
|
8178
8254
|
return false;
|
|
8179
8255
|
}
|
|
8180
|
-
function namedRunNeedsPlayDefinition(
|
|
8181
|
-
return
|
|
8256
|
+
function namedRunNeedsPlayDefinition(input2) {
|
|
8257
|
+
return input2.revisionSelector === "latest" || inputContainsLocalFilePath(input2.runtimeInput);
|
|
8182
8258
|
}
|
|
8183
|
-
async function stageFileInputArgs(
|
|
8259
|
+
async function stageFileInputArgs(input2) {
|
|
8184
8260
|
const uniqueBindings = [
|
|
8185
8261
|
...new Map(
|
|
8186
|
-
|
|
8262
|
+
input2.bindings.map((binding) => [binding.inputPath, binding])
|
|
8187
8263
|
).values()
|
|
8188
8264
|
];
|
|
8189
8265
|
const localFiles = uniqueBindings.flatMap((binding) => {
|
|
8190
|
-
const value = getDottedInputValue(
|
|
8266
|
+
const value = getDottedInputValue(input2.runtimeInput, binding.inputPath);
|
|
8191
8267
|
if (!isLocalFilePathValue(value)) return [];
|
|
8192
8268
|
const absolutePath = (0, import_node_path12.resolve)(value);
|
|
8193
8269
|
return [{ binding, absolutePath, logicalPath: (0, import_node_path12.basename)(absolutePath) }];
|
|
@@ -8195,22 +8271,22 @@ async function stageFileInputArgs(input) {
|
|
|
8195
8271
|
if (localFiles.length === 0) {
|
|
8196
8272
|
return { inputFile: null, packagedFiles: [] };
|
|
8197
8273
|
}
|
|
8198
|
-
|
|
8274
|
+
input2.progress.phase(
|
|
8199
8275
|
localFiles.length === 1 ? "staging input file" : "staging input files"
|
|
8200
8276
|
);
|
|
8201
|
-
const staged = await
|
|
8277
|
+
const staged = await input2.client.stagePlayFiles(
|
|
8202
8278
|
localFiles.map((file) => stageFile(file.logicalPath, file.absolutePath))
|
|
8203
8279
|
);
|
|
8204
8280
|
for (const [index, file] of localFiles.entries()) {
|
|
8205
8281
|
setDottedInputValue(
|
|
8206
|
-
|
|
8282
|
+
input2.runtimeInput,
|
|
8207
8283
|
file.binding.inputPath,
|
|
8208
8284
|
file.logicalPath
|
|
8209
8285
|
);
|
|
8210
8286
|
const stagedFile = staged[index];
|
|
8211
8287
|
if (stagedFile && stagedFile.logicalPath !== file.logicalPath) {
|
|
8212
8288
|
setDottedInputValue(
|
|
8213
|
-
|
|
8289
|
+
input2.runtimeInput,
|
|
8214
8290
|
file.binding.inputPath,
|
|
8215
8291
|
stagedFile.logicalPath
|
|
8216
8292
|
);
|
|
@@ -8495,16 +8571,16 @@ function buildStepReceiptsDebugCommand(runId) {
|
|
|
8495
8571
|
const sql = `select convert_from(k, 'UTF8') as receipt_key, case status when 0 then 'pending' when 1 then 'running' when 2 then 'completed' when 3 then 'failed' when 4 then 'skipped' else status::text end as status, output, error, updated_at from ${table} where run_id = ${quoteSqlLiteral(runId)} order by updated_at asc, receipt_key asc limit 20`;
|
|
8496
8572
|
return buildDebugDbQueryCommand(sql);
|
|
8497
8573
|
}
|
|
8498
|
-
function buildMapTableDebugCommand(
|
|
8574
|
+
function buildMapTableDebugCommand(input2) {
|
|
8499
8575
|
try {
|
|
8500
8576
|
const tableName = validatePlaySheetTableName(
|
|
8501
|
-
|
|
8502
|
-
|
|
8577
|
+
input2.playName,
|
|
8578
|
+
input2.tableNamespace
|
|
8503
8579
|
);
|
|
8504
8580
|
const table = `${quoteSqlIdentifier(
|
|
8505
8581
|
PLAY_CUSTOMER_STORAGE_SCHEMA_NAME
|
|
8506
8582
|
)}.${quoteSqlIdentifier(tableName)}`;
|
|
8507
|
-
const sql = `select * from ${table} where _run_id = ${quoteSqlLiteral(
|
|
8583
|
+
const sql = `select * from ${table} where _run_id = ${quoteSqlLiteral(input2.runId)} limit 20`;
|
|
8508
8584
|
return buildDebugDbQueryCommand(sql);
|
|
8509
8585
|
} catch {
|
|
8510
8586
|
return null;
|
|
@@ -8524,37 +8600,37 @@ function extractTableNamespaceFromLiveEvent(event) {
|
|
|
8524
8600
|
}
|
|
8525
8601
|
return null;
|
|
8526
8602
|
}
|
|
8527
|
-
function emitLiveDebugTableHints(
|
|
8528
|
-
if (
|
|
8603
|
+
function emitLiveDebugTableHints(input2) {
|
|
8604
|
+
if (input2.jsonOutput || !input2.runId || input2.runId === "pending") {
|
|
8529
8605
|
return;
|
|
8530
8606
|
}
|
|
8531
|
-
|
|
8532
|
-
const receiptsKey = `receipts:${
|
|
8533
|
-
if (!
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
`Debug top-level outputs: ${buildStepReceiptsDebugCommand(
|
|
8607
|
+
input2.state.emittedDebugKeys ??= /* @__PURE__ */ new Set();
|
|
8608
|
+
const receiptsKey = `receipts:${input2.runId}`;
|
|
8609
|
+
if (!input2.state.emittedDebugKeys.has(receiptsKey)) {
|
|
8610
|
+
input2.state.emittedDebugKeys.add(receiptsKey);
|
|
8611
|
+
input2.progress.writeLine(
|
|
8612
|
+
`Debug top-level outputs: ${buildStepReceiptsDebugCommand(input2.runId)}`,
|
|
8537
8613
|
process.stdout
|
|
8538
8614
|
);
|
|
8539
8615
|
}
|
|
8540
|
-
const tableNamespace = extractTableNamespaceFromLiveEvent(
|
|
8616
|
+
const tableNamespace = extractTableNamespaceFromLiveEvent(input2.event);
|
|
8541
8617
|
if (!tableNamespace) {
|
|
8542
8618
|
return;
|
|
8543
8619
|
}
|
|
8544
|
-
const tableKey = `table:${
|
|
8545
|
-
if (
|
|
8620
|
+
const tableKey = `table:${input2.runId}:${tableNamespace}`;
|
|
8621
|
+
if (input2.state.emittedDebugKeys.has(tableKey)) {
|
|
8546
8622
|
return;
|
|
8547
8623
|
}
|
|
8548
8624
|
const command = buildMapTableDebugCommand({
|
|
8549
|
-
playName:
|
|
8550
|
-
runId:
|
|
8625
|
+
playName: input2.playName,
|
|
8626
|
+
runId: input2.runId,
|
|
8551
8627
|
tableNamespace
|
|
8552
8628
|
});
|
|
8553
8629
|
if (!command) {
|
|
8554
8630
|
return;
|
|
8555
8631
|
}
|
|
8556
|
-
|
|
8557
|
-
|
|
8632
|
+
input2.state.emittedDebugKeys.add(tableKey);
|
|
8633
|
+
input2.progress.writeLine(
|
|
8558
8634
|
`Debug rows for ${tableNamespace}: ${command}`,
|
|
8559
8635
|
process.stdout
|
|
8560
8636
|
);
|
|
@@ -8587,9 +8663,9 @@ function formatProgressLabel(raw) {
|
|
|
8587
8663
|
const value = typeof raw === "string" && raw.trim() ? raw.trim() : "step";
|
|
8588
8664
|
return value.replace(/^map:/, "").replace(/^tool:/, "");
|
|
8589
8665
|
}
|
|
8590
|
-
function formatProgressCounts(
|
|
8591
|
-
const completed = typeof
|
|
8592
|
-
const total = typeof
|
|
8666
|
+
function formatProgressCounts(input2) {
|
|
8667
|
+
const completed = typeof input2.completed === "number" && Number.isFinite(input2.completed) ? input2.completed : null;
|
|
8668
|
+
const total = typeof input2.total === "number" && Number.isFinite(input2.total) ? input2.total : null;
|
|
8593
8669
|
if (completed === null || total === null || total <= 0) {
|
|
8594
8670
|
return null;
|
|
8595
8671
|
}
|
|
@@ -8597,7 +8673,7 @@ function formatProgressCounts(input) {
|
|
|
8597
8673
|
0,
|
|
8598
8674
|
Math.min(100, Math.round(completed / total * 100))
|
|
8599
8675
|
);
|
|
8600
|
-
const failed = typeof
|
|
8676
|
+
const failed = typeof input2.failed === "number" && Number.isFinite(input2.failed) && input2.failed > 0 ? `, failed ${formatInteger(input2.failed)}` : "";
|
|
8601
8677
|
return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
|
|
8602
8678
|
}
|
|
8603
8679
|
function getProgressLinesFromLiveEvent(event) {
|
|
@@ -8639,14 +8715,14 @@ function getProgressLinesFromLiveEvent(event) {
|
|
|
8639
8715
|
}
|
|
8640
8716
|
return lines;
|
|
8641
8717
|
}
|
|
8642
|
-
function printPlayProgressLines(
|
|
8643
|
-
for (const line of
|
|
8718
|
+
function printPlayProgressLines(input2) {
|
|
8719
|
+
for (const line of input2.lines) {
|
|
8644
8720
|
const signature = line.trim();
|
|
8645
|
-
if (!signature ||
|
|
8721
|
+
if (!signature || input2.state.lastProgressSignature === signature) {
|
|
8646
8722
|
continue;
|
|
8647
8723
|
}
|
|
8648
|
-
|
|
8649
|
-
|
|
8724
|
+
input2.state.lastProgressSignature = signature;
|
|
8725
|
+
input2.progress.writeLine(line);
|
|
8650
8726
|
}
|
|
8651
8727
|
}
|
|
8652
8728
|
function buildPlayDashboardUrl(baseUrl, playName) {
|
|
@@ -8654,102 +8730,102 @@ function buildPlayDashboardUrl(baseUrl, playName) {
|
|
|
8654
8730
|
const encodedPlayName = encodeURIComponent(playName);
|
|
8655
8731
|
return `${trimmedBase}/dashboard/plays/${encodedPlayName}`;
|
|
8656
8732
|
}
|
|
8657
|
-
function openPlayDashboard(
|
|
8658
|
-
if (
|
|
8733
|
+
function openPlayDashboard(input2) {
|
|
8734
|
+
if (input2.jsonOutput || input2.noOpen || !input2.dashboardUrl) {
|
|
8659
8735
|
return;
|
|
8660
8736
|
}
|
|
8661
|
-
openInBrowser(
|
|
8737
|
+
openInBrowser(input2.dashboardUrl);
|
|
8662
8738
|
}
|
|
8663
|
-
function printPlayLogLines(
|
|
8664
|
-
for (const line of
|
|
8665
|
-
if (
|
|
8739
|
+
function printPlayLogLines(input2) {
|
|
8740
|
+
for (const line of input2.lines) {
|
|
8741
|
+
if (input2.emitLogs) {
|
|
8666
8742
|
const formatted = formatPlayLogLine(
|
|
8667
8743
|
line,
|
|
8668
|
-
|
|
8669
|
-
|
|
8744
|
+
input2.status ?? void 0,
|
|
8745
|
+
input2.state
|
|
8670
8746
|
);
|
|
8671
8747
|
if (formatted) {
|
|
8672
|
-
|
|
8748
|
+
input2.progress.writeLogLine(formatted);
|
|
8673
8749
|
}
|
|
8674
8750
|
}
|
|
8675
|
-
|
|
8751
|
+
input2.state.lastLogIndex += 1;
|
|
8676
8752
|
}
|
|
8677
8753
|
}
|
|
8678
|
-
function assertPlayWaitNotTimedOut(
|
|
8679
|
-
if (
|
|
8680
|
-
const hasRealRunId =
|
|
8681
|
-
const phaseSuffix =
|
|
8682
|
-
const tailHint = hasRealRunId ? ` Run 'deepline runs tail ${
|
|
8754
|
+
function assertPlayWaitNotTimedOut(input2) {
|
|
8755
|
+
if (input2.waitTimeoutMs !== null && Date.now() - input2.startedAt >= input2.waitTimeoutMs) {
|
|
8756
|
+
const hasRealRunId = input2.workflowId.length > 0 && input2.workflowId !== "pending";
|
|
8757
|
+
const phaseSuffix = input2.lastPhase && input2.lastPhase.trim() ? ` (last observed phase: ${input2.lastPhase.trim()})` : "";
|
|
8758
|
+
const tailHint = hasRealRunId ? ` Run 'deepline runs tail ${input2.workflowId} --json' to inspect it, or rerun with a larger --tail-timeout-ms.` : ` The run never reported a workflow id \u2014 the start request likely failed before reaching the scheduler. Check server logs and rerun with a larger --tail-timeout-ms.`;
|
|
8683
8759
|
throw new DeeplineError(
|
|
8684
|
-
`Timed out waiting for play ${hasRealRunId ?
|
|
8760
|
+
`Timed out waiting for play ${hasRealRunId ? input2.workflowId : "<no run id>"} after ${Math.ceil(input2.waitTimeoutMs / 1e3)}s${phaseSuffix}.${tailHint}`,
|
|
8685
8761
|
void 0,
|
|
8686
8762
|
"PLAY_WAIT_TIMEOUT",
|
|
8687
8763
|
{
|
|
8688
|
-
...hasRealRunId ? { runId:
|
|
8689
|
-
...
|
|
8690
|
-
timeoutMs:
|
|
8764
|
+
...hasRealRunId ? { runId: input2.workflowId, workflowId: input2.workflowId } : {},
|
|
8765
|
+
...input2.lastPhase ? { phase: input2.lastPhase } : {},
|
|
8766
|
+
timeoutMs: input2.waitTimeoutMs
|
|
8691
8767
|
}
|
|
8692
8768
|
);
|
|
8693
8769
|
}
|
|
8694
8770
|
}
|
|
8695
|
-
async function waitForPlayCompletionByStream(
|
|
8771
|
+
async function waitForPlayCompletionByStream(input2) {
|
|
8696
8772
|
const controller = new AbortController();
|
|
8697
8773
|
let timedOut = false;
|
|
8698
8774
|
let lastPhase = null;
|
|
8699
|
-
const timeout =
|
|
8775
|
+
const timeout = input2.waitTimeoutMs === null ? null : setTimeout(
|
|
8700
8776
|
() => {
|
|
8701
8777
|
timedOut = true;
|
|
8702
8778
|
controller.abort();
|
|
8703
8779
|
},
|
|
8704
|
-
Math.max(1,
|
|
8780
|
+
Math.max(1, input2.waitTimeoutMs - (Date.now() - input2.startedAt))
|
|
8705
8781
|
);
|
|
8706
8782
|
try {
|
|
8707
|
-
for await (const event of
|
|
8708
|
-
|
|
8783
|
+
for await (const event of input2.client.streamPlayRunEvents(
|
|
8784
|
+
input2.workflowId,
|
|
8709
8785
|
{ signal: controller.signal }
|
|
8710
8786
|
)) {
|
|
8711
|
-
assertPlayWaitNotTimedOut({ ...
|
|
8787
|
+
assertPlayWaitNotTimedOut({ ...input2, lastPhase });
|
|
8712
8788
|
const phase = describeLiveEventPhase(event);
|
|
8713
8789
|
if (phase) {
|
|
8714
8790
|
lastPhase = phase;
|
|
8715
|
-
|
|
8791
|
+
input2.progress.phase(phase);
|
|
8716
8792
|
}
|
|
8717
8793
|
emitLiveDebugTableHints({
|
|
8718
8794
|
event,
|
|
8719
|
-
playName:
|
|
8720
|
-
runId:
|
|
8721
|
-
jsonOutput:
|
|
8722
|
-
state:
|
|
8723
|
-
progress:
|
|
8795
|
+
playName: input2.playName,
|
|
8796
|
+
runId: input2.workflowId,
|
|
8797
|
+
jsonOutput: input2.jsonOutput,
|
|
8798
|
+
state: input2.state,
|
|
8799
|
+
progress: input2.progress
|
|
8724
8800
|
});
|
|
8725
8801
|
printPlayLogLines({
|
|
8726
8802
|
lines: getLogLinesFromLiveEvent(event),
|
|
8727
8803
|
status: null,
|
|
8728
|
-
jsonOutput:
|
|
8729
|
-
emitLogs:
|
|
8730
|
-
state:
|
|
8731
|
-
progress:
|
|
8804
|
+
jsonOutput: input2.jsonOutput,
|
|
8805
|
+
emitLogs: input2.emitLogs,
|
|
8806
|
+
state: input2.state,
|
|
8807
|
+
progress: input2.progress
|
|
8732
8808
|
});
|
|
8733
|
-
if (!
|
|
8809
|
+
if (!input2.jsonOutput) {
|
|
8734
8810
|
printPlayProgressLines({
|
|
8735
8811
|
lines: getProgressLinesFromLiveEvent(event),
|
|
8736
|
-
state:
|
|
8737
|
-
progress:
|
|
8812
|
+
state: input2.state,
|
|
8813
|
+
progress: input2.progress
|
|
8738
8814
|
});
|
|
8739
8815
|
}
|
|
8740
8816
|
const status = getStatusFromLiveEvent(event);
|
|
8741
8817
|
if (status && TERMINAL_PLAY_STATUSES2.has(status)) {
|
|
8742
|
-
const finalStatus = await
|
|
8818
|
+
const finalStatus = await input2.client.getPlayStatus(input2.workflowId, {
|
|
8743
8819
|
billing: false
|
|
8744
8820
|
});
|
|
8745
8821
|
if (TERMINAL_PLAY_STATUSES2.has(finalStatus.status)) {
|
|
8746
|
-
return
|
|
8822
|
+
return input2.dashboardUrl ? { ...finalStatus, dashboardUrl: input2.dashboardUrl } : finalStatus;
|
|
8747
8823
|
}
|
|
8748
8824
|
}
|
|
8749
8825
|
}
|
|
8750
8826
|
} catch (error) {
|
|
8751
8827
|
if (timedOut) {
|
|
8752
|
-
assertPlayWaitNotTimedOut({ ...
|
|
8828
|
+
assertPlayWaitNotTimedOut({ ...input2, lastPhase });
|
|
8753
8829
|
}
|
|
8754
8830
|
throw error;
|
|
8755
8831
|
} finally {
|
|
@@ -8759,25 +8835,25 @@ async function waitForPlayCompletionByStream(input) {
|
|
|
8759
8835
|
}
|
|
8760
8836
|
const phaseSuffix = lastPhase && lastPhase.trim() ? ` (last observed phase: ${lastPhase.trim()})` : "";
|
|
8761
8837
|
throw new DeeplineError(
|
|
8762
|
-
`Play live stream ended before the run reached a terminal state runId=${
|
|
8838
|
+
`Play live stream ended before the run reached a terminal state runId=${input2.workflowId}${phaseSuffix}.`,
|
|
8763
8839
|
void 0,
|
|
8764
8840
|
"PLAY_LIVE_STREAM_ENDED",
|
|
8765
8841
|
{
|
|
8766
|
-
runId:
|
|
8767
|
-
workflowId:
|
|
8842
|
+
runId: input2.workflowId,
|
|
8843
|
+
workflowId: input2.workflowId,
|
|
8768
8844
|
...lastPhase ? { phase: lastPhase } : {}
|
|
8769
8845
|
}
|
|
8770
8846
|
);
|
|
8771
8847
|
}
|
|
8772
|
-
async function startAndWaitForPlayCompletionByStream(
|
|
8848
|
+
async function startAndWaitForPlayCompletionByStream(input2) {
|
|
8773
8849
|
for (let attempt = 0; attempt <= PLAY_START_TRANSIENT_RETRY_DELAYS_MS.length; attempt += 1) {
|
|
8774
|
-
const status = await startAndWaitForPlayCompletionByStreamOnce(
|
|
8850
|
+
const status = await startAndWaitForPlayCompletionByStreamOnce(input2);
|
|
8775
8851
|
const retryDelayMs = PLAY_START_TRANSIENT_RETRY_DELAYS_MS[attempt];
|
|
8776
8852
|
if (retryDelayMs === void 0 || !isRetryablePendingStartFailure(status)) {
|
|
8777
8853
|
return status;
|
|
8778
8854
|
}
|
|
8779
|
-
if (!
|
|
8780
|
-
|
|
8855
|
+
if (!input2.jsonOutput) {
|
|
8856
|
+
input2.progress.writeLine(
|
|
8781
8857
|
`[play watch] start failed before run id with a transient error; retrying (${playStatusErrorText(status)})`
|
|
8782
8858
|
);
|
|
8783
8859
|
}
|
|
@@ -8785,23 +8861,23 @@ async function startAndWaitForPlayCompletionByStream(input) {
|
|
|
8785
8861
|
phase: "cli.play_start_stream_retry",
|
|
8786
8862
|
ms: 0,
|
|
8787
8863
|
ok: true,
|
|
8788
|
-
playName:
|
|
8864
|
+
playName: input2.playName,
|
|
8789
8865
|
attempt: attempt + 1,
|
|
8790
8866
|
reason: playStatusErrorText(status)
|
|
8791
8867
|
});
|
|
8792
8868
|
await sleep4(retryDelayMs);
|
|
8793
8869
|
}
|
|
8794
8870
|
throw new DeeplineError(
|
|
8795
|
-
`Play ${
|
|
8871
|
+
`Play ${input2.playName} did not start after retrying transient start failures.`,
|
|
8796
8872
|
void 0,
|
|
8797
8873
|
"PLAY_START_RETRY_EXHAUSTED"
|
|
8798
8874
|
);
|
|
8799
8875
|
}
|
|
8800
|
-
async function startAndWaitForPlayCompletionByStreamOnce(
|
|
8876
|
+
async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
8801
8877
|
const startedAt = Date.now();
|
|
8802
8878
|
const dashboardUrl = buildPlayDashboardUrl(
|
|
8803
|
-
|
|
8804
|
-
|
|
8879
|
+
input2.client.baseUrl,
|
|
8880
|
+
input2.playName
|
|
8805
8881
|
);
|
|
8806
8882
|
const state = {
|
|
8807
8883
|
lastLogIndex: 0,
|
|
@@ -8815,15 +8891,19 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8815
8891
|
let eventCount = 0;
|
|
8816
8892
|
let firstRunIdMs = null;
|
|
8817
8893
|
let lastPhase = null;
|
|
8818
|
-
const
|
|
8894
|
+
const startRequest = {
|
|
8895
|
+
...input2.request,
|
|
8896
|
+
waitForCompletionMs: typeof input2.request.waitForCompletionMs === "number" ? input2.request.waitForCompletionMs : PLAY_START_STREAM_FAST_COMPLETION_WAIT_MS
|
|
8897
|
+
};
|
|
8898
|
+
const timeout = input2.waitTimeoutMs === null ? null : setTimeout(
|
|
8819
8899
|
() => {
|
|
8820
8900
|
timedOut = true;
|
|
8821
8901
|
controller.abort();
|
|
8822
8902
|
},
|
|
8823
|
-
Math.max(1,
|
|
8903
|
+
Math.max(1, input2.waitTimeoutMs)
|
|
8824
8904
|
);
|
|
8825
8905
|
try {
|
|
8826
|
-
for await (const event of
|
|
8906
|
+
for await (const event of input2.client.startPlayRunStream(startRequest, {
|
|
8827
8907
|
signal: controller.signal
|
|
8828
8908
|
})) {
|
|
8829
8909
|
eventCount += 1;
|
|
@@ -8834,55 +8914,55 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8834
8914
|
}
|
|
8835
8915
|
const workflowId = lastKnownWorkflowId || "pending";
|
|
8836
8916
|
if (workflowId !== "pending" && !emittedDashboardUrl) {
|
|
8837
|
-
if (!
|
|
8917
|
+
if (!input2.jsonOutput) {
|
|
8838
8918
|
writeStartedPlayRun({
|
|
8839
8919
|
runId: workflowId,
|
|
8840
|
-
playName:
|
|
8920
|
+
playName: input2.playName,
|
|
8841
8921
|
dashboardUrl,
|
|
8842
8922
|
jsonOutput: false,
|
|
8843
|
-
progress:
|
|
8923
|
+
progress: input2.progress
|
|
8844
8924
|
});
|
|
8845
8925
|
}
|
|
8846
8926
|
openPlayDashboard({
|
|
8847
8927
|
dashboardUrl,
|
|
8848
|
-
jsonOutput:
|
|
8849
|
-
noOpen:
|
|
8928
|
+
jsonOutput: input2.jsonOutput,
|
|
8929
|
+
noOpen: input2.noOpen
|
|
8850
8930
|
});
|
|
8851
|
-
|
|
8931
|
+
input2.progress.phase(`loading play on ${dashboardUrl}`);
|
|
8852
8932
|
emittedDashboardUrl = true;
|
|
8853
8933
|
}
|
|
8854
8934
|
assertPlayWaitNotTimedOut({
|
|
8855
8935
|
workflowId,
|
|
8856
8936
|
startedAt,
|
|
8857
|
-
waitTimeoutMs:
|
|
8937
|
+
waitTimeoutMs: input2.waitTimeoutMs,
|
|
8858
8938
|
lastPhase
|
|
8859
8939
|
});
|
|
8860
8940
|
const phase = describeLiveEventPhase(event);
|
|
8861
8941
|
if (phase) {
|
|
8862
8942
|
lastPhase = phase;
|
|
8863
|
-
|
|
8943
|
+
input2.progress.phase(phase);
|
|
8864
8944
|
}
|
|
8865
8945
|
printPlayLogLines({
|
|
8866
8946
|
lines: getLogLinesFromLiveEvent(event),
|
|
8867
8947
|
status: null,
|
|
8868
|
-
jsonOutput:
|
|
8869
|
-
emitLogs:
|
|
8948
|
+
jsonOutput: input2.jsonOutput,
|
|
8949
|
+
emitLogs: input2.emitLogs,
|
|
8870
8950
|
state,
|
|
8871
|
-
progress:
|
|
8951
|
+
progress: input2.progress
|
|
8872
8952
|
});
|
|
8873
8953
|
emitLiveDebugTableHints({
|
|
8874
8954
|
event,
|
|
8875
|
-
playName:
|
|
8955
|
+
playName: input2.playName,
|
|
8876
8956
|
runId: workflowId,
|
|
8877
|
-
jsonOutput:
|
|
8957
|
+
jsonOutput: input2.jsonOutput,
|
|
8878
8958
|
state,
|
|
8879
|
-
progress:
|
|
8959
|
+
progress: input2.progress
|
|
8880
8960
|
});
|
|
8881
|
-
if (!
|
|
8961
|
+
if (!input2.jsonOutput) {
|
|
8882
8962
|
printPlayProgressLines({
|
|
8883
8963
|
lines: getProgressLinesFromLiveEvent(event),
|
|
8884
8964
|
state,
|
|
8885
|
-
progress:
|
|
8965
|
+
progress: input2.progress
|
|
8886
8966
|
});
|
|
8887
8967
|
}
|
|
8888
8968
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
@@ -8891,7 +8971,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8891
8971
|
phase: "cli.play_start_stream_terminal",
|
|
8892
8972
|
ms: Date.now() - startedAt,
|
|
8893
8973
|
ok: true,
|
|
8894
|
-
playName:
|
|
8974
|
+
playName: input2.playName,
|
|
8895
8975
|
workflowId: finalStatus.runId || lastKnownWorkflowId || null,
|
|
8896
8976
|
eventCount,
|
|
8897
8977
|
firstRunIdMs,
|
|
@@ -8905,7 +8985,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8905
8985
|
assertPlayWaitNotTimedOut({
|
|
8906
8986
|
workflowId: lastKnownWorkflowId,
|
|
8907
8987
|
startedAt,
|
|
8908
|
-
waitTimeoutMs:
|
|
8988
|
+
waitTimeoutMs: input2.waitTimeoutMs,
|
|
8909
8989
|
lastPhase
|
|
8910
8990
|
});
|
|
8911
8991
|
}
|
|
@@ -8914,7 +8994,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8914
8994
|
clearTimeout(timeout);
|
|
8915
8995
|
}
|
|
8916
8996
|
const reason = error instanceof Error ? error.message : String(error);
|
|
8917
|
-
if (!
|
|
8997
|
+
if (!input2.jsonOutput) {
|
|
8918
8998
|
process.stderr.write(
|
|
8919
8999
|
`[play watch] start stream failed after run ${lastKnownWorkflowId}; reconnecting to run stream (${reason})
|
|
8920
9000
|
`
|
|
@@ -8924,7 +9004,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8924
9004
|
phase: "cli.play_start_stream_reconnect",
|
|
8925
9005
|
ms: Date.now() - startedAt,
|
|
8926
9006
|
ok: true,
|
|
8927
|
-
playName:
|
|
9007
|
+
playName: input2.playName,
|
|
8928
9008
|
workflowId: lastKnownWorkflowId,
|
|
8929
9009
|
eventCount,
|
|
8930
9010
|
firstRunIdMs,
|
|
@@ -8932,16 +9012,16 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8932
9012
|
reason
|
|
8933
9013
|
});
|
|
8934
9014
|
return waitForPlayCompletionByStream({
|
|
8935
|
-
client:
|
|
8936
|
-
playName:
|
|
9015
|
+
client: input2.client,
|
|
9016
|
+
playName: input2.playName,
|
|
8937
9017
|
workflowId: lastKnownWorkflowId,
|
|
8938
9018
|
dashboardUrl,
|
|
8939
|
-
jsonOutput:
|
|
8940
|
-
emitLogs:
|
|
8941
|
-
waitTimeoutMs:
|
|
9019
|
+
jsonOutput: input2.jsonOutput,
|
|
9020
|
+
emitLogs: input2.emitLogs,
|
|
9021
|
+
waitTimeoutMs: input2.waitTimeoutMs,
|
|
8942
9022
|
startedAt,
|
|
8943
9023
|
state,
|
|
8944
|
-
progress:
|
|
9024
|
+
progress: input2.progress
|
|
8945
9025
|
});
|
|
8946
9026
|
}
|
|
8947
9027
|
throw error;
|
|
@@ -8951,8 +9031,8 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8951
9031
|
}
|
|
8952
9032
|
}
|
|
8953
9033
|
if (lastKnownWorkflowId) {
|
|
8954
|
-
if (!
|
|
8955
|
-
|
|
9034
|
+
if (!input2.jsonOutput) {
|
|
9035
|
+
input2.progress.writeLine(
|
|
8956
9036
|
`[play watch] start stream ended after run ${lastKnownWorkflowId}; reconnecting to run stream`
|
|
8957
9037
|
);
|
|
8958
9038
|
}
|
|
@@ -8960,7 +9040,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8960
9040
|
phase: "cli.play_start_stream_reconnect",
|
|
8961
9041
|
ms: Date.now() - startedAt,
|
|
8962
9042
|
ok: true,
|
|
8963
|
-
playName:
|
|
9043
|
+
playName: input2.playName,
|
|
8964
9044
|
workflowId: lastKnownWorkflowId,
|
|
8965
9045
|
eventCount,
|
|
8966
9046
|
firstRunIdMs,
|
|
@@ -8968,16 +9048,16 @@ async function startAndWaitForPlayCompletionByStreamOnce(input) {
|
|
|
8968
9048
|
reason: "stream ended before terminal event"
|
|
8969
9049
|
});
|
|
8970
9050
|
return waitForPlayCompletionByStream({
|
|
8971
|
-
client:
|
|
8972
|
-
playName:
|
|
9051
|
+
client: input2.client,
|
|
9052
|
+
playName: input2.playName,
|
|
8973
9053
|
workflowId: lastKnownWorkflowId,
|
|
8974
9054
|
dashboardUrl,
|
|
8975
|
-
jsonOutput:
|
|
8976
|
-
emitLogs:
|
|
8977
|
-
waitTimeoutMs:
|
|
9055
|
+
jsonOutput: input2.jsonOutput,
|
|
9056
|
+
emitLogs: input2.emitLogs,
|
|
9057
|
+
waitTimeoutMs: input2.waitTimeoutMs,
|
|
8978
9058
|
startedAt,
|
|
8979
9059
|
state,
|
|
8980
|
-
progress:
|
|
9060
|
+
progress: input2.progress
|
|
8981
9061
|
});
|
|
8982
9062
|
}
|
|
8983
9063
|
const phaseSuffix = lastPhase && lastPhase.trim() ? ` (last observed phase: ${lastPhase.trim()})` : "";
|
|
@@ -9058,7 +9138,7 @@ function compactReturnValue(value, depth = 0) {
|
|
|
9058
9138
|
if (!value || typeof value !== "object") {
|
|
9059
9139
|
return value;
|
|
9060
9140
|
}
|
|
9061
|
-
const
|
|
9141
|
+
const output2 = {};
|
|
9062
9142
|
for (const [key, entry] of Object.entries(value)) {
|
|
9063
9143
|
if (depth === 0 && key === "_metadata") {
|
|
9064
9144
|
continue;
|
|
@@ -9069,9 +9149,9 @@ function compactReturnValue(value, depth = 0) {
|
|
|
9069
9149
|
if (key === "access") {
|
|
9070
9150
|
continue;
|
|
9071
9151
|
}
|
|
9072
|
-
|
|
9152
|
+
output2[key] = compactReturnValue(entry, depth + 1);
|
|
9073
9153
|
}
|
|
9074
|
-
return
|
|
9154
|
+
return output2;
|
|
9075
9155
|
}
|
|
9076
9156
|
function formatJsonPreview(value) {
|
|
9077
9157
|
const json = JSON.stringify(value, null, 2);
|
|
@@ -9280,22 +9360,22 @@ function extractBillingForStatus(status, error) {
|
|
|
9280
9360
|
const progressError = getStringField(status.progress, "error");
|
|
9281
9361
|
return extractBillingFromText(error) ?? extractBillingFromText(progressError) ?? getObjectField(status, "billing");
|
|
9282
9362
|
}
|
|
9283
|
-
function formatInsufficientCreditsMessage(
|
|
9284
|
-
const operation = getStringField(
|
|
9285
|
-
const balance = formatCreditAmount(
|
|
9286
|
-
const required = formatCreditAmount(
|
|
9363
|
+
function formatInsufficientCreditsMessage(input2) {
|
|
9364
|
+
const operation = getStringField(input2.billing, "operation_id") ?? getStringField(input2.billing, "operation") ?? extractToolIdFromErrorText(input2.error) ?? getStringField(input2.billing, "provider") ?? "tool call";
|
|
9365
|
+
const balance = formatCreditAmount(input2.billing.balance_credits);
|
|
9366
|
+
const required = formatCreditAmount(input2.billing.required_credits);
|
|
9287
9367
|
const recommended = formatCreditAmount(
|
|
9288
|
-
|
|
9368
|
+
input2.billing.recommended_add_credits ?? input2.billing.needed_credits
|
|
9289
9369
|
);
|
|
9290
|
-
const billingUrl = getStringField(
|
|
9291
|
-
const workspace = getStringField(
|
|
9370
|
+
const billingUrl = getStringField(input2.billing, "billing_url");
|
|
9371
|
+
const workspace = getStringField(input2.billing, "workspace_id") ?? getStringField(input2.billing, "workspaceId");
|
|
9292
9372
|
const workspaceSuffix = workspace ? ` (workspace=${workspace})` : "";
|
|
9293
9373
|
const addSuffix = billingUrl && recommended !== "-" ? ` Add >=${recommended} at ${billingUrl}.` : billingUrl ? ` Add credits at ${billingUrl}.` : "";
|
|
9294
9374
|
return `Workspace balance ${balance} < required ${required} for ${operation}${workspaceSuffix}.${addSuffix}`;
|
|
9295
9375
|
}
|
|
9296
|
-
function buildInsufficientCreditsSummaryLines(
|
|
9297
|
-
const progress =
|
|
9298
|
-
const rowsInfo = extractCanonicalRowsInfo(
|
|
9376
|
+
function buildInsufficientCreditsSummaryLines(input2) {
|
|
9377
|
+
const progress = input2.status.progress;
|
|
9378
|
+
const rowsInfo = extractCanonicalRowsInfo(input2.status);
|
|
9299
9379
|
const completed = getNumericField(progress, "completed") ?? getNumericField(progress, "completedRows") ?? rowsInfo?.rows.length ?? null;
|
|
9300
9380
|
const total = getNumericField(progress, "total") ?? getNumericField(progress, "totalRows") ?? rowsInfo?.totalRows ?? null;
|
|
9301
9381
|
const lines = [
|
|
@@ -9303,16 +9383,16 @@ function buildInsufficientCreditsSummaryLines(input) {
|
|
|
9303
9383
|
completed === null ? " completed rows: unknown" : ` completed rows: ${formatInteger(completed)}${total !== null ? ` of ${formatInteger(total)}` : ""}`,
|
|
9304
9384
|
" reusable receipts: yes; rerun after adding credits to continue from completed provider work"
|
|
9305
9385
|
];
|
|
9306
|
-
const billingUrl = getStringField(
|
|
9386
|
+
const billingUrl = getStringField(input2.billing, "billing_url");
|
|
9307
9387
|
const recommended = formatCreditAmount(
|
|
9308
|
-
|
|
9388
|
+
input2.billing.recommended_add_credits ?? input2.billing.needed_credits
|
|
9309
9389
|
);
|
|
9310
9390
|
if (billingUrl) {
|
|
9311
9391
|
lines.push(
|
|
9312
9392
|
recommended !== "-" ? ` add credits: add >=${recommended} at ${billingUrl}` : ` add credits: ${billingUrl}`
|
|
9313
9393
|
);
|
|
9314
9394
|
}
|
|
9315
|
-
const runId =
|
|
9395
|
+
const runId = input2.status.runId?.trim();
|
|
9316
9396
|
if (runId) {
|
|
9317
9397
|
lines.push(` inspect: deepline runs get ${runId} --json`);
|
|
9318
9398
|
lines.push(
|
|
@@ -9647,8 +9727,8 @@ function actionToCommand(action) {
|
|
|
9647
9727
|
}
|
|
9648
9728
|
function readFirstDatasetActions(packaged) {
|
|
9649
9729
|
for (const step of readRecordArray(packaged.steps)) {
|
|
9650
|
-
const
|
|
9651
|
-
const actions =
|
|
9730
|
+
const output2 = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
|
|
9731
|
+
const actions = output2?.actions && typeof output2.actions === "object" && !Array.isArray(output2.actions) ? output2.actions : null;
|
|
9652
9732
|
if (actions) {
|
|
9653
9733
|
return actions;
|
|
9654
9734
|
}
|
|
@@ -9670,12 +9750,12 @@ function buildRunPackageTextLines(packaged) {
|
|
|
9670
9750
|
const id = typeof step.id === "string" ? step.id : "step";
|
|
9671
9751
|
const kind = typeof step.kind === "string" ? step.kind : "step";
|
|
9672
9752
|
const stepStatus = typeof step.status === "string" ? step.status : status;
|
|
9673
|
-
const
|
|
9674
|
-
const rowCount =
|
|
9675
|
-
const preview =
|
|
9753
|
+
const output2 = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
|
|
9754
|
+
const rowCount = output2 && typeof output2.rowCount === "number" ? ` rows=${formatInteger(output2.rowCount)}` : "";
|
|
9755
|
+
const preview = output2?.preview && typeof output2.preview === "object" && !Array.isArray(output2.preview) ? output2.preview : null;
|
|
9676
9756
|
const previewRows = Array.isArray(preview?.rows) ? preview.rows.length : null;
|
|
9677
9757
|
lines.push(` ${kind} ${id}: ${stepStatus}${rowCount}`);
|
|
9678
|
-
lines.push(...formatPackageDatasetSummaryLines(
|
|
9758
|
+
lines.push(...formatPackageDatasetSummaryLines(output2?.summary));
|
|
9679
9759
|
if (previewRows !== null) {
|
|
9680
9760
|
lines.push(
|
|
9681
9761
|
` preview=${previewRows}${preview?.truncated ? " truncated" : ""}`
|
|
@@ -9758,19 +9838,19 @@ function writePlayResult(status, jsonOutput, options) {
|
|
|
9758
9838
|
` }
|
|
9759
9839
|
);
|
|
9760
9840
|
}
|
|
9761
|
-
async function resolvePlayRunOutputStatus(
|
|
9762
|
-
if (!getPlayRunPackage(
|
|
9763
|
-
return
|
|
9841
|
+
async function resolvePlayRunOutputStatus(input2) {
|
|
9842
|
+
if (!getPlayRunPackage(input2.status)) {
|
|
9843
|
+
return input2.status;
|
|
9764
9844
|
}
|
|
9765
|
-
const runId =
|
|
9845
|
+
const runId = input2.status.runId;
|
|
9766
9846
|
if (!runId) {
|
|
9767
|
-
return
|
|
9847
|
+
return input2.status;
|
|
9768
9848
|
}
|
|
9769
|
-
const refreshedStatus = await
|
|
9849
|
+
const refreshedStatus = await input2.client.getPlayStatus(runId, {
|
|
9770
9850
|
billing: false,
|
|
9771
|
-
full:
|
|
9851
|
+
full: input2.fullJson
|
|
9772
9852
|
});
|
|
9773
|
-
const dashboardUrl =
|
|
9853
|
+
const dashboardUrl = input2.status.dashboardUrl;
|
|
9774
9854
|
return typeof dashboardUrl === "string" ? { ...refreshedStatus, dashboardUrl } : refreshedStatus;
|
|
9775
9855
|
}
|
|
9776
9856
|
var RUN_EXPORT_PAGE_SIZE = 5e3;
|
|
@@ -9801,21 +9881,21 @@ function extractRunPlayName(status) {
|
|
|
9801
9881
|
function normalizeCustomerDbIdentifier(value) {
|
|
9802
9882
|
return value.split("/").pop().replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
|
|
9803
9883
|
}
|
|
9804
|
-
function buildCustomerDbQueryPlan(
|
|
9805
|
-
const playName = extractRunPlayName(
|
|
9806
|
-
const tableNamespace =
|
|
9807
|
-
if (!playName || !tableNamespace ||
|
|
9884
|
+
function buildCustomerDbQueryPlan(input2) {
|
|
9885
|
+
const playName = extractRunPlayName(input2.status);
|
|
9886
|
+
const tableNamespace = input2.rowsInfo.tableNamespace?.trim();
|
|
9887
|
+
if (!playName || !tableNamespace || input2.rowsInfo.totalRows <= 0) {
|
|
9808
9888
|
return null;
|
|
9809
9889
|
}
|
|
9810
9890
|
const tableName = `${normalizeCustomerDbIdentifier(playName)}_${normalizeCustomerDbIdentifier(
|
|
9811
9891
|
tableNamespace
|
|
9812
9892
|
)}`;
|
|
9813
|
-
const sql = `select * from "storage"."${tableName}" where _run_id = ${sqlStringLiteral(
|
|
9814
|
-
const base = `deepline customer-db query --sql ${shellSingleQuote(sql)} --max-rows ${
|
|
9893
|
+
const sql = `select * from "storage"."${tableName}" where _run_id = ${sqlStringLiteral(input2.status.runId)} limit ${input2.rowsInfo.totalRows}`;
|
|
9894
|
+
const base = `deepline customer-db query --sql ${shellSingleQuote(sql)} --max-rows ${input2.rowsInfo.totalRows}`;
|
|
9815
9895
|
return {
|
|
9816
9896
|
sql,
|
|
9817
9897
|
json: `${base} --json`,
|
|
9818
|
-
csv: `${base} --format csv --out ${shellSingleQuote((0, import_node_path12.resolve)(
|
|
9898
|
+
csv: `${base} --format csv --out ${shellSingleQuote((0, import_node_path12.resolve)(input2.outPath))}`
|
|
9819
9899
|
};
|
|
9820
9900
|
}
|
|
9821
9901
|
function exportableSheetRow(row) {
|
|
@@ -9866,20 +9946,20 @@ function mergeExportColumns(preferredColumns, rows) {
|
|
|
9866
9946
|
}
|
|
9867
9947
|
return columns;
|
|
9868
9948
|
}
|
|
9869
|
-
async function fetchBackingDatasetRows(
|
|
9870
|
-
const playName = extractRunPlayName(
|
|
9871
|
-
const tableNamespace =
|
|
9949
|
+
async function fetchBackingDatasetRows(input2) {
|
|
9950
|
+
const playName = extractRunPlayName(input2.status);
|
|
9951
|
+
const tableNamespace = input2.rowsInfo.tableNamespace?.trim();
|
|
9872
9952
|
if (!playName || !tableNamespace) {
|
|
9873
9953
|
return null;
|
|
9874
9954
|
}
|
|
9875
9955
|
const sheetRows = [];
|
|
9876
9956
|
let offset = 0;
|
|
9877
|
-
let expectedTotal =
|
|
9957
|
+
let expectedTotal = input2.rowsInfo.totalRows;
|
|
9878
9958
|
while (true) {
|
|
9879
|
-
const page = await
|
|
9959
|
+
const page = await input2.client.runs.exportDatasetRows({
|
|
9880
9960
|
playName,
|
|
9881
9961
|
tableNamespace,
|
|
9882
|
-
runId:
|
|
9962
|
+
runId: input2.status.runId,
|
|
9883
9963
|
limit: RUN_EXPORT_PAGE_SIZE,
|
|
9884
9964
|
offset
|
|
9885
9965
|
});
|
|
@@ -9894,20 +9974,20 @@ async function fetchBackingDatasetRows(input) {
|
|
|
9894
9974
|
offset += page.rows.length;
|
|
9895
9975
|
}
|
|
9896
9976
|
const rows = sheetRows.map(exportableSheetRow).filter((row) => Boolean(row));
|
|
9897
|
-
if (rows.length <
|
|
9977
|
+
if (rows.length < input2.rowsInfo.totalRows) {
|
|
9898
9978
|
return null;
|
|
9899
9979
|
}
|
|
9900
9980
|
const columns = mergeExportColumns(
|
|
9901
|
-
|
|
9981
|
+
input2.rowsInfo.columnsExplicit ? input2.rowsInfo.columns : [],
|
|
9902
9982
|
rows
|
|
9903
9983
|
);
|
|
9904
9984
|
return {
|
|
9905
|
-
...
|
|
9985
|
+
...input2.rowsInfo,
|
|
9906
9986
|
rows,
|
|
9907
9987
|
columns,
|
|
9908
9988
|
totalRows: rows.length,
|
|
9909
9989
|
complete: true,
|
|
9910
|
-
source: `${
|
|
9990
|
+
source: `${input2.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
|
|
9911
9991
|
};
|
|
9912
9992
|
}
|
|
9913
9993
|
async function exportPlayStatusRows(client, status, outPath, options = {}) {
|
|
@@ -10009,11 +10089,11 @@ function extractActiveRunsFromError(error) {
|
|
|
10009
10089
|
function activeRunId(run) {
|
|
10010
10090
|
return getStringField(run, "workflowId") ?? getStringField(run, "runId");
|
|
10011
10091
|
}
|
|
10012
|
-
function formatActiveRunConflictError(
|
|
10092
|
+
function formatActiveRunConflictError(input2) {
|
|
10013
10093
|
const lines = [
|
|
10014
|
-
`Active run exists for ${
|
|
10094
|
+
`Active run exists for ${input2.playName}. Use --force to supersede, or inspect/stop the active run first.`
|
|
10015
10095
|
];
|
|
10016
|
-
for (const run of
|
|
10096
|
+
for (const run of input2.activeRuns.slice(0, 3)) {
|
|
10017
10097
|
const runId = activeRunId(run);
|
|
10018
10098
|
if (!runId) {
|
|
10019
10099
|
continue;
|
|
@@ -10127,49 +10207,49 @@ function renderServerResultView(value) {
|
|
|
10127
10207
|
}
|
|
10128
10208
|
return { lines: lines.length > 1 ? lines : [], actions: [] };
|
|
10129
10209
|
}
|
|
10130
|
-
function writeStartedPlayRun(
|
|
10131
|
-
if (
|
|
10132
|
-
if (
|
|
10133
|
-
printCommandEnvelope(
|
|
10210
|
+
function writeStartedPlayRun(input2) {
|
|
10211
|
+
if (input2.package && isPlayRunPackageValue(input2.package)) {
|
|
10212
|
+
if (input2.jsonOutput) {
|
|
10213
|
+
printCommandEnvelope(input2.package, { json: true });
|
|
10134
10214
|
return;
|
|
10135
10215
|
}
|
|
10136
|
-
const lines2 = buildRunPackageTextLines(
|
|
10137
|
-
const
|
|
10138
|
-
if (
|
|
10139
|
-
|
|
10216
|
+
const lines2 = buildRunPackageTextLines(input2.package);
|
|
10217
|
+
const output3 = lines2.join("\n");
|
|
10218
|
+
if (input2.progress) {
|
|
10219
|
+
input2.progress.writeLine(output3, process.stdout);
|
|
10140
10220
|
return;
|
|
10141
10221
|
}
|
|
10142
|
-
printCommandEnvelope(
|
|
10222
|
+
printCommandEnvelope(input2.package, {
|
|
10143
10223
|
json: false,
|
|
10144
|
-
text: `${
|
|
10224
|
+
text: `${output3}
|
|
10145
10225
|
`
|
|
10146
10226
|
});
|
|
10147
10227
|
return;
|
|
10148
10228
|
}
|
|
10149
10229
|
const payload = {
|
|
10150
|
-
runId:
|
|
10151
|
-
workflowId:
|
|
10152
|
-
name:
|
|
10153
|
-
status:
|
|
10154
|
-
dashboardUrl:
|
|
10230
|
+
runId: input2.runId,
|
|
10231
|
+
workflowId: input2.runId,
|
|
10232
|
+
name: input2.playName,
|
|
10233
|
+
status: input2.status ?? "started",
|
|
10234
|
+
dashboardUrl: input2.dashboardUrl,
|
|
10155
10235
|
next: {
|
|
10156
|
-
inspect: `deepline runs get ${
|
|
10157
|
-
full: `deepline runs get ${
|
|
10158
|
-
logs: `deepline runs logs ${
|
|
10159
|
-
export: `deepline runs export ${
|
|
10160
|
-
stop: `deepline runs stop ${
|
|
10236
|
+
inspect: `deepline runs get ${input2.runId} --json`,
|
|
10237
|
+
full: `deepline runs get ${input2.runId} --full --json`,
|
|
10238
|
+
logs: `deepline runs logs ${input2.runId} --json`,
|
|
10239
|
+
export: `deepline runs export ${input2.runId} --out output.csv`,
|
|
10240
|
+
stop: `deepline runs stop ${input2.runId} --reason "stale lock" --json`
|
|
10161
10241
|
}
|
|
10162
10242
|
};
|
|
10163
10243
|
const lines = [
|
|
10164
|
-
`Started ${
|
|
10165
|
-
` run id: ${
|
|
10166
|
-
` inspect: deepline runs get ${
|
|
10167
|
-
` full debug: deepline runs get ${
|
|
10168
|
-
` logs: deepline runs logs ${
|
|
10169
|
-
` export after completion: deepline runs export ${
|
|
10170
|
-
` stop run: deepline runs stop ${
|
|
10244
|
+
`Started ${input2.playName}`,
|
|
10245
|
+
` run id: ${input2.runId}`,
|
|
10246
|
+
` inspect: deepline runs get ${input2.runId} --json`,
|
|
10247
|
+
` full debug: deepline runs get ${input2.runId} --full --json`,
|
|
10248
|
+
` logs: deepline runs logs ${input2.runId} --json`,
|
|
10249
|
+
` export after completion: deepline runs export ${input2.runId} --out output.csv`,
|
|
10250
|
+
` stop run: deepline runs stop ${input2.runId} --reason "stale lock" --json`
|
|
10171
10251
|
];
|
|
10172
|
-
if (
|
|
10252
|
+
if (input2.jsonOutput) {
|
|
10173
10253
|
printCommandEnvelope(
|
|
10174
10254
|
{
|
|
10175
10255
|
...payload,
|
|
@@ -10179,12 +10259,12 @@ function writeStartedPlayRun(input) {
|
|
|
10179
10259
|
);
|
|
10180
10260
|
return;
|
|
10181
10261
|
}
|
|
10182
|
-
if (
|
|
10183
|
-
lines.push(` play page: ${
|
|
10262
|
+
if (input2.dashboardUrl) {
|
|
10263
|
+
lines.push(` play page: ${input2.dashboardUrl}`);
|
|
10184
10264
|
}
|
|
10185
|
-
const
|
|
10186
|
-
if (
|
|
10187
|
-
|
|
10265
|
+
const output2 = lines.join("\n");
|
|
10266
|
+
if (input2.progress) {
|
|
10267
|
+
input2.progress.writeLine(output2, process.stdout);
|
|
10188
10268
|
return;
|
|
10189
10269
|
}
|
|
10190
10270
|
printCommandEnvelope(
|
|
@@ -10192,7 +10272,7 @@ function writeStartedPlayRun(input) {
|
|
|
10192
10272
|
...payload,
|
|
10193
10273
|
render: { sections: [{ title: "play run", lines }] }
|
|
10194
10274
|
},
|
|
10195
|
-
{ json: false, text: `${
|
|
10275
|
+
{ json: false, text: `${output2}
|
|
10196
10276
|
` }
|
|
10197
10277
|
);
|
|
10198
10278
|
}
|
|
@@ -10200,7 +10280,7 @@ function parsePlayRunOptions(args) {
|
|
|
10200
10280
|
const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.map guidance.";
|
|
10201
10281
|
let filePath = null;
|
|
10202
10282
|
let playName = null;
|
|
10203
|
-
let
|
|
10283
|
+
let input2 = null;
|
|
10204
10284
|
let revisionId = null;
|
|
10205
10285
|
let revisionSelector = null;
|
|
10206
10286
|
const watch = !args.includes("--no-wait");
|
|
@@ -10221,7 +10301,7 @@ function parsePlayRunOptions(args) {
|
|
|
10221
10301
|
continue;
|
|
10222
10302
|
}
|
|
10223
10303
|
if ((arg === "--input" || arg === "-i") && args[index + 1]) {
|
|
10224
|
-
|
|
10304
|
+
input2 = parseJsonInput(args[++index]);
|
|
10225
10305
|
continue;
|
|
10226
10306
|
}
|
|
10227
10307
|
if (arg === "--revision-id" && args[index + 1]) {
|
|
@@ -10270,8 +10350,8 @@ function parsePlayRunOptions(args) {
|
|
|
10270
10350
|
}
|
|
10271
10351
|
if (arg.startsWith("--")) {
|
|
10272
10352
|
const { path, value } = parseInputFieldFlag(arg, args[index + 1]);
|
|
10273
|
-
|
|
10274
|
-
setDottedInputValue(
|
|
10353
|
+
input2 ??= {};
|
|
10354
|
+
setDottedInputValue(input2, path, parseInputFlagValue(value));
|
|
10275
10355
|
if (!arg.includes("=")) {
|
|
10276
10356
|
index += 1;
|
|
10277
10357
|
}
|
|
@@ -10306,7 +10386,7 @@ function parsePlayRunOptions(args) {
|
|
|
10306
10386
|
}
|
|
10307
10387
|
return {
|
|
10308
10388
|
target: filePath ? { kind: "file", path: filePath } : { kind: "name", name: playName },
|
|
10309
|
-
input,
|
|
10389
|
+
input: input2,
|
|
10310
10390
|
revisionId,
|
|
10311
10391
|
revisionSelector,
|
|
10312
10392
|
watch,
|
|
@@ -10673,15 +10753,15 @@ async function handleFileBackedRun(options) {
|
|
|
10673
10753
|
});
|
|
10674
10754
|
return 0;
|
|
10675
10755
|
}
|
|
10676
|
-
async function resolveNamedRunRevisionId(
|
|
10677
|
-
if (
|
|
10678
|
-
return
|
|
10756
|
+
async function resolveNamedRunRevisionId(input2) {
|
|
10757
|
+
if (input2.revisionId) {
|
|
10758
|
+
return input2.revisionId;
|
|
10679
10759
|
}
|
|
10680
|
-
if (
|
|
10681
|
-
const versions = await
|
|
10760
|
+
if (input2.selector === "latest") {
|
|
10761
|
+
const versions = await input2.client.listPlayVersions(input2.playName);
|
|
10682
10762
|
const latest = versions[0];
|
|
10683
10763
|
if (!latest?._id) {
|
|
10684
|
-
throw new Error(`No saved revisions found for ${
|
|
10764
|
+
throw new Error(`No saved revisions found for ${input2.playName}.`);
|
|
10685
10765
|
}
|
|
10686
10766
|
return latest._id;
|
|
10687
10767
|
}
|
|
@@ -12481,6 +12561,218 @@ async function handlePlayShareUnpublish(args) {
|
|
|
12481
12561
|
return 0;
|
|
12482
12562
|
}
|
|
12483
12563
|
|
|
12564
|
+
// src/cli/commands/secrets.ts
|
|
12565
|
+
var import_node_process = require("process");
|
|
12566
|
+
var hiddenInputBuffer = "";
|
|
12567
|
+
function normalizeSecretName(value) {
|
|
12568
|
+
const normalized = value.trim().toUpperCase();
|
|
12569
|
+
if (!/^[A-Z][A-Z0-9_]{1,63}$/.test(normalized)) {
|
|
12570
|
+
throw new Error(
|
|
12571
|
+
"Secret names must be 2-64 characters and use uppercase letters, numbers, and underscores."
|
|
12572
|
+
);
|
|
12573
|
+
}
|
|
12574
|
+
return normalized;
|
|
12575
|
+
}
|
|
12576
|
+
function renderSecret(secret) {
|
|
12577
|
+
const scope = secret.scope === "play" && secret.playName ? `play:${secret.playName}` : secret.scope;
|
|
12578
|
+
return `${secret.name} (${scope}) - ${secret.status}${secret.hasValue ? ", set" : ", empty"}`;
|
|
12579
|
+
}
|
|
12580
|
+
async function readHiddenLine(prompt) {
|
|
12581
|
+
if (!import_node_process.stdin.isTTY || !import_node_process.stdout.isTTY) {
|
|
12582
|
+
throw new Error(
|
|
12583
|
+
"Secret values must be entered from an interactive TTY. Do not pipe, pass, or script secret values."
|
|
12584
|
+
);
|
|
12585
|
+
}
|
|
12586
|
+
import_node_process.stdout.write(prompt);
|
|
12587
|
+
const previousRawMode = import_node_process.stdin.isRaw;
|
|
12588
|
+
if (typeof import_node_process.stdin.setRawMode === "function") import_node_process.stdin.setRawMode(true);
|
|
12589
|
+
let value = "";
|
|
12590
|
+
import_node_process.stdin.resume();
|
|
12591
|
+
return await new Promise((resolve12, reject) => {
|
|
12592
|
+
let settled = false;
|
|
12593
|
+
const cleanup = () => {
|
|
12594
|
+
import_node_process.stdin.off("data", onData);
|
|
12595
|
+
import_node_process.stdin.off("end", onEnd);
|
|
12596
|
+
import_node_process.stdin.off("error", onError);
|
|
12597
|
+
if (typeof import_node_process.stdin.setRawMode === "function") {
|
|
12598
|
+
import_node_process.stdin.setRawMode(previousRawMode);
|
|
12599
|
+
}
|
|
12600
|
+
};
|
|
12601
|
+
const finish = (line) => {
|
|
12602
|
+
if (settled) return;
|
|
12603
|
+
settled = true;
|
|
12604
|
+
import_node_process.stdout.write("\n");
|
|
12605
|
+
cleanup();
|
|
12606
|
+
resolve12(line);
|
|
12607
|
+
};
|
|
12608
|
+
const fail = (error) => {
|
|
12609
|
+
if (settled) return;
|
|
12610
|
+
settled = true;
|
|
12611
|
+
import_node_process.stdout.write("\n");
|
|
12612
|
+
cleanup();
|
|
12613
|
+
reject(error);
|
|
12614
|
+
};
|
|
12615
|
+
const processText = (text) => {
|
|
12616
|
+
for (let index = 0; index < text.length; index++) {
|
|
12617
|
+
const char = text[index];
|
|
12618
|
+
const code = char.charCodeAt(0);
|
|
12619
|
+
if (char === "\r" || char === "\n") {
|
|
12620
|
+
hiddenInputBuffer = text.slice(index + 1);
|
|
12621
|
+
finish(value);
|
|
12622
|
+
return;
|
|
12623
|
+
}
|
|
12624
|
+
if (code === 3) {
|
|
12625
|
+
fail(new Error("Secret input cancelled."));
|
|
12626
|
+
return;
|
|
12627
|
+
}
|
|
12628
|
+
if (code === 8 || code === 127) {
|
|
12629
|
+
value = value.slice(0, -1);
|
|
12630
|
+
continue;
|
|
12631
|
+
}
|
|
12632
|
+
if (code >= 32) {
|
|
12633
|
+
value += char;
|
|
12634
|
+
}
|
|
12635
|
+
}
|
|
12636
|
+
hiddenInputBuffer = "";
|
|
12637
|
+
};
|
|
12638
|
+
const onData = (chunk) => {
|
|
12639
|
+
processText(chunk.toString());
|
|
12640
|
+
};
|
|
12641
|
+
const onEnd = () => fail(new Error("Secret input ended before a value was entered."));
|
|
12642
|
+
const onError = (error) => fail(error);
|
|
12643
|
+
import_node_process.stdin.on("data", onData);
|
|
12644
|
+
import_node_process.stdin.once("end", onEnd);
|
|
12645
|
+
import_node_process.stdin.once("error", onError);
|
|
12646
|
+
if (hiddenInputBuffer) {
|
|
12647
|
+
const buffered = hiddenInputBuffer;
|
|
12648
|
+
hiddenInputBuffer = "";
|
|
12649
|
+
processText(buffered);
|
|
12650
|
+
}
|
|
12651
|
+
});
|
|
12652
|
+
}
|
|
12653
|
+
async function readSecretValue() {
|
|
12654
|
+
const first = await readHiddenLine("Secret value: ");
|
|
12655
|
+
if (!first) throw new Error("Secret value is required.");
|
|
12656
|
+
const second = await readHiddenLine("Confirm secret value: ");
|
|
12657
|
+
if (first !== second) {
|
|
12658
|
+
throw new Error("Secret values did not match.");
|
|
12659
|
+
}
|
|
12660
|
+
return first;
|
|
12661
|
+
}
|
|
12662
|
+
function preventShellHistoryLeak(forbidden) {
|
|
12663
|
+
if (forbidden.length > 0) {
|
|
12664
|
+
throw new Error(
|
|
12665
|
+
"Do not pass secret values as command arguments. Run `deepline secrets set NAME` and enter the value at the hidden prompt."
|
|
12666
|
+
);
|
|
12667
|
+
}
|
|
12668
|
+
}
|
|
12669
|
+
async function handleList(options) {
|
|
12670
|
+
const client = new DeeplineClient();
|
|
12671
|
+
const secrets = await client.listSecrets();
|
|
12672
|
+
printCommandEnvelope(
|
|
12673
|
+
{
|
|
12674
|
+
secrets,
|
|
12675
|
+
count: secrets.length,
|
|
12676
|
+
render: {
|
|
12677
|
+
sections: [
|
|
12678
|
+
{
|
|
12679
|
+
title: "secrets",
|
|
12680
|
+
lines: secrets.length ? secrets.map(renderSecret) : ["No play secrets are configured."]
|
|
12681
|
+
}
|
|
12682
|
+
]
|
|
12683
|
+
}
|
|
12684
|
+
},
|
|
12685
|
+
{ json: options.json }
|
|
12686
|
+
);
|
|
12687
|
+
}
|
|
12688
|
+
async function handleCheck(nameInput, options) {
|
|
12689
|
+
const name = normalizeSecretName(nameInput);
|
|
12690
|
+
const client = new DeeplineClient();
|
|
12691
|
+
const secret = await client.checkSecret(name);
|
|
12692
|
+
printCommandEnvelope(
|
|
12693
|
+
{
|
|
12694
|
+
ok: Boolean(secret),
|
|
12695
|
+
name,
|
|
12696
|
+
secret: secret ?? null,
|
|
12697
|
+
render: {
|
|
12698
|
+
sections: [
|
|
12699
|
+
{
|
|
12700
|
+
title: "secret check",
|
|
12701
|
+
lines: [
|
|
12702
|
+
secret ? `${name}: active` : `${name}: missing, disabled, or empty`
|
|
12703
|
+
]
|
|
12704
|
+
}
|
|
12705
|
+
]
|
|
12706
|
+
}
|
|
12707
|
+
},
|
|
12708
|
+
{ json: options.json }
|
|
12709
|
+
);
|
|
12710
|
+
if (!secret) process.exitCode = 4;
|
|
12711
|
+
}
|
|
12712
|
+
async function handleSet(nameInput, forbidden, options) {
|
|
12713
|
+
preventShellHistoryLeak(forbidden);
|
|
12714
|
+
const name = normalizeSecretName(nameInput);
|
|
12715
|
+
const scope = options.scope === "play" ? "play" : "org";
|
|
12716
|
+
const playName = options.play?.trim();
|
|
12717
|
+
if (scope === "play" && !playName) {
|
|
12718
|
+
throw new Error("--play <name> is required when --scope play is used.");
|
|
12719
|
+
}
|
|
12720
|
+
const value = await readSecretValue();
|
|
12721
|
+
const { http } = getAuthedHttpClient();
|
|
12722
|
+
const response = await http.post(
|
|
12723
|
+
"/api/v2/secrets",
|
|
12724
|
+
{
|
|
12725
|
+
name,
|
|
12726
|
+
value,
|
|
12727
|
+
scope,
|
|
12728
|
+
...playName ? { playName } : {}
|
|
12729
|
+
}
|
|
12730
|
+
);
|
|
12731
|
+
const secret = response.secret;
|
|
12732
|
+
printCommandEnvelope(
|
|
12733
|
+
{
|
|
12734
|
+
ok: true,
|
|
12735
|
+
secret,
|
|
12736
|
+
render: {
|
|
12737
|
+
sections: [
|
|
12738
|
+
{
|
|
12739
|
+
title: "secret saved",
|
|
12740
|
+
lines: [`${secret.name}: saved (${secret.scope})`]
|
|
12741
|
+
}
|
|
12742
|
+
]
|
|
12743
|
+
}
|
|
12744
|
+
},
|
|
12745
|
+
{ json: options.json }
|
|
12746
|
+
);
|
|
12747
|
+
}
|
|
12748
|
+
function registerSecretsCommands(program) {
|
|
12749
|
+
const secrets = program.command("secrets").description("Manage play secrets without revealing values.").addHelpText(
|
|
12750
|
+
"after",
|
|
12751
|
+
`
|
|
12752
|
+
Notes:
|
|
12753
|
+
Secret values are never accepted as command arguments, stdin pipes, env vars,
|
|
12754
|
+
or files. Use deepline secrets set NAME and type the value at the hidden TTY
|
|
12755
|
+
prompt. Agents can list/check metadata but should not enter secret values.
|
|
12756
|
+
|
|
12757
|
+
Examples:
|
|
12758
|
+
deepline secrets list
|
|
12759
|
+
deepline secrets check HUBSPOT_TOKEN
|
|
12760
|
+
deepline secrets set HUBSPOT_TOKEN
|
|
12761
|
+
`
|
|
12762
|
+
);
|
|
12763
|
+
secrets.command("list").description("List secret metadata only.").option("--json", "Emit JSON output").action(async (options) => {
|
|
12764
|
+
await handleList(options);
|
|
12765
|
+
});
|
|
12766
|
+
secrets.command("check").description("Check whether a secret exists and is active.").argument("<name>", "Secret name").option("--json", "Emit JSON output").action(async (name, options) => {
|
|
12767
|
+
await handleCheck(name, options);
|
|
12768
|
+
});
|
|
12769
|
+
secrets.command("set").description("Set or rotate a secret through a hidden interactive prompt.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play", "org").option("--play <name>", "Play name for play-scoped secrets").action(
|
|
12770
|
+
async (name, forbidden, options) => {
|
|
12771
|
+
await handleSet(name, forbidden ?? [], options);
|
|
12772
|
+
}
|
|
12773
|
+
);
|
|
12774
|
+
}
|
|
12775
|
+
|
|
12484
12776
|
// src/cli/commands/tools.ts
|
|
12485
12777
|
var import_commander2 = require("commander");
|
|
12486
12778
|
var import_node_fs12 = require("fs");
|
|
@@ -13686,25 +13978,25 @@ function shellQuote(value) {
|
|
|
13686
13978
|
function powerShellQuote(value) {
|
|
13687
13979
|
return `'${value.replace(/'/g, "''")}'`;
|
|
13688
13980
|
}
|
|
13689
|
-
function seedToolListScript(
|
|
13690
|
-
const stem = safeFileStem(
|
|
13981
|
+
function seedToolListScript(input2) {
|
|
13982
|
+
const stem = safeFileStem(input2.toolId);
|
|
13691
13983
|
const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
|
|
13692
13984
|
const scriptDir = (0, import_node_fs12.mkdtempSync)((0, import_node_path14.join)((0, import_node_os8.tmpdir)(), "deepline-workflow-seed-"));
|
|
13693
13985
|
(0, import_node_fs12.chmodSync)(scriptDir, 448);
|
|
13694
13986
|
const scriptPath = (0, import_node_path14.join)(scriptDir, fileName);
|
|
13695
13987
|
const projectDir = `deepline/projects/${stem}-workflow`;
|
|
13696
13988
|
const playName = `${stem}-workflow`;
|
|
13697
|
-
const sampleRows =
|
|
13698
|
-
const columns = Object.keys(
|
|
13699
|
-
const rowKey = Object.prototype.hasOwnProperty.call(
|
|
13989
|
+
const sampleRows = input2.rows.length > 0 ? `${JSON.stringify(input2.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
|
|
13990
|
+
const columns = Object.keys(input2.rows[0] ?? {}).join(", ");
|
|
13991
|
+
const rowKey = Object.prototype.hasOwnProperty.call(input2.rows[0] ?? {}, "id") ? '"id"' : "(row) => JSON.stringify(row)";
|
|
13700
13992
|
const script = `import { definePlay } from 'deepline';
|
|
13701
13993
|
|
|
13702
13994
|
export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
13703
13995
|
const result = await ctx.tools.execute({
|
|
13704
|
-
id: ${JSON.stringify(
|
|
13705
|
-
tool: ${JSON.stringify(
|
|
13706
|
-
input: ${JSON.stringify(
|
|
13707
|
-
description: ${JSON.stringify(`Seed ${
|
|
13996
|
+
id: ${JSON.stringify(input2.toolId)},
|
|
13997
|
+
tool: ${JSON.stringify(input2.toolId)},
|
|
13998
|
+
input: ${JSON.stringify(input2.payload)},
|
|
13999
|
+
description: ${JSON.stringify(`Seed ${input2.toolId} rows for workflow expansion.`)},
|
|
13708
14000
|
});
|
|
13709
14001
|
|
|
13710
14002
|
const list = Object.values(result.extractedLists)[0];
|
|
@@ -13736,23 +14028,23 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
|
13736
14028
|
windowsCopyCommand: `New-Item -ItemType Directory -Force -Path ${powerShellQuote(projectDir.replace(/\//g, "\\"))} | Out-Null; Copy-Item -LiteralPath ${powerShellQuote(scriptPath)} -Destination ${powerShellQuote(`${projectDir.replace(/\//g, "\\")}\\${fileName}`)}`
|
|
13737
14029
|
};
|
|
13738
14030
|
}
|
|
13739
|
-
function buildToolExecuteBaseEnvelope(
|
|
13740
|
-
const envelope = commandEnvelopeFromRawResponse(
|
|
13741
|
-
const summaryEntries = Object.entries(
|
|
13742
|
-
const outputPreview =
|
|
14031
|
+
function buildToolExecuteBaseEnvelope(input2) {
|
|
14032
|
+
const envelope = commandEnvelopeFromRawResponse(input2.rawResponse);
|
|
14033
|
+
const summaryEntries = Object.entries(input2.summary);
|
|
14034
|
+
const outputPreview = input2.listConversion ? {
|
|
13743
14035
|
kind: "list",
|
|
13744
|
-
rowCount:
|
|
13745
|
-
columns: Object.keys(
|
|
13746
|
-
preview:
|
|
13747
|
-
listStrategy:
|
|
13748
|
-
listSourcePath:
|
|
14036
|
+
rowCount: input2.listConversion.rows.length,
|
|
14037
|
+
columns: Object.keys(input2.listConversion.rows[0] ?? {}),
|
|
14038
|
+
preview: input2.listConversion.rows.slice(0, 5),
|
|
14039
|
+
listStrategy: input2.listConversion.strategy,
|
|
14040
|
+
listSourcePath: input2.listConversion.sourcePath
|
|
13749
14041
|
} : {
|
|
13750
14042
|
kind: summaryEntries.length > 0 ? "object" : "raw",
|
|
13751
|
-
summary:
|
|
14043
|
+
summary: input2.summary
|
|
13752
14044
|
};
|
|
13753
14045
|
const envelopeHasCanonicalOutput = isRecord5(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
|
|
13754
|
-
const inspectCommand = `deepline tools execute ${
|
|
13755
|
-
const actions =
|
|
14046
|
+
const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote(JSON.stringify(input2.params))} --json`;
|
|
14047
|
+
const actions = input2.listConversion ? [
|
|
13756
14048
|
{
|
|
13757
14049
|
label: "next",
|
|
13758
14050
|
command: "move starter script into a project folder and expand it into a Deepline play"
|
|
@@ -13761,24 +14053,24 @@ function buildToolExecuteBaseEnvelope(input) {
|
|
|
13761
14053
|
return {
|
|
13762
14054
|
...envelope,
|
|
13763
14055
|
...envelopeHasCanonicalOutput ? { output_preview: outputPreview } : { output: outputPreview },
|
|
13764
|
-
...summaryEntries.length > 0 ? { summary:
|
|
14056
|
+
...summaryEntries.length > 0 ? { summary: input2.summary } : {},
|
|
13765
14057
|
next: {
|
|
13766
14058
|
inspect: inspectCommand,
|
|
13767
14059
|
playDebugging: "When fixing a play getter, inspect the actual play run table with runs get / inspect rows; do not copy CLI preview paths blindly.",
|
|
13768
|
-
...
|
|
14060
|
+
...input2.listConversion ? {
|
|
13769
14061
|
expandToPlay: "Use stable map and step keys so reruns are idempotent: completed rows are reused, and only missing or stale work runs again.",
|
|
13770
|
-
listSourcePath:
|
|
14062
|
+
listSourcePath: input2.listConversion.sourcePath ?? "auto-detected list in the CLI response preview"
|
|
13771
14063
|
} : {}
|
|
13772
14064
|
},
|
|
13773
14065
|
render: {
|
|
13774
|
-
sections:
|
|
14066
|
+
sections: input2.listConversion ? [
|
|
13775
14067
|
{
|
|
13776
14068
|
title: "output",
|
|
13777
14069
|
lines: [
|
|
13778
|
-
`${
|
|
14070
|
+
`${input2.listConversion.rows.length} row(s) extracted from ${input2.listConversion.sourcePath ?? "auto-detected list"}`,
|
|
13779
14071
|
"paths above are observed from this execute response; use run table rows to debug play getters",
|
|
13780
|
-
`columns: ${JSON.stringify(Object.keys(
|
|
13781
|
-
`preview: ${JSON.stringify(
|
|
14072
|
+
`columns: ${JSON.stringify(Object.keys(input2.listConversion.rows[0] ?? {}))}`,
|
|
14073
|
+
`preview: ${JSON.stringify(input2.listConversion.rows.slice(0, 5))}`
|
|
13782
14074
|
]
|
|
13783
14075
|
}
|
|
13784
14076
|
] : [
|
|
@@ -13786,7 +14078,7 @@ function buildToolExecuteBaseEnvelope(input) {
|
|
|
13786
14078
|
title: "result",
|
|
13787
14079
|
lines: summaryEntries.length > 0 ? summaryEntries.map(
|
|
13788
14080
|
([key, value]) => `${key}=${String(value)}`
|
|
13789
|
-
) : [JSON.stringify(
|
|
14081
|
+
) : [JSON.stringify(input2.rawResponse, null, 2)]
|
|
13790
14082
|
}
|
|
13791
14083
|
],
|
|
13792
14084
|
actions
|
|
@@ -14107,6 +14399,174 @@ Examples:
|
|
|
14107
14399
|
});
|
|
14108
14400
|
}
|
|
14109
14401
|
|
|
14402
|
+
// ../shared_libs/cli/command-compatibility.json
|
|
14403
|
+
var command_compatibility_default = {
|
|
14404
|
+
enrich: {
|
|
14405
|
+
family: "python",
|
|
14406
|
+
label: "a legacy Python CLI enrichment command",
|
|
14407
|
+
sdk_alternative: "Use `deepline plays ...` for durable workflows or `deepline tools execute ...` for one tool call."
|
|
14408
|
+
},
|
|
14409
|
+
session: {
|
|
14410
|
+
family: "python",
|
|
14411
|
+
label: "a legacy Python CLI session/playground command",
|
|
14412
|
+
sdk_alternative: "Use SDK play run output and run commands such as `deepline plays run ...`."
|
|
14413
|
+
},
|
|
14414
|
+
workflows: {
|
|
14415
|
+
family: "python",
|
|
14416
|
+
label: "a legacy Python CLI workflow command",
|
|
14417
|
+
sdk_alternative: "Use `deepline plays ...` in the SDK CLI."
|
|
14418
|
+
},
|
|
14419
|
+
backend: {
|
|
14420
|
+
family: "python",
|
|
14421
|
+
label: "a legacy Python CLI playground backend command"
|
|
14422
|
+
},
|
|
14423
|
+
events: {
|
|
14424
|
+
family: "python",
|
|
14425
|
+
label: "a legacy Python CLI event command"
|
|
14426
|
+
},
|
|
14427
|
+
plays: {
|
|
14428
|
+
family: "sdk",
|
|
14429
|
+
label: "an SDK CLI play command",
|
|
14430
|
+
python_alternative: "Use `deepline workflows ...` only for legacy workflows."
|
|
14431
|
+
},
|
|
14432
|
+
play: {
|
|
14433
|
+
family: "sdk",
|
|
14434
|
+
label: "an SDK CLI play command",
|
|
14435
|
+
python_alternative: "Use `deepline workflows ...` only for legacy workflows."
|
|
14436
|
+
},
|
|
14437
|
+
runs: {
|
|
14438
|
+
family: "sdk",
|
|
14439
|
+
label: "an SDK CLI run inspection command"
|
|
14440
|
+
},
|
|
14441
|
+
health: {
|
|
14442
|
+
family: "sdk",
|
|
14443
|
+
label: "an SDK CLI health command"
|
|
14444
|
+
}
|
|
14445
|
+
};
|
|
14446
|
+
|
|
14447
|
+
// ../shared_libs/cli/install-commands.json
|
|
14448
|
+
var install_commands_default = {
|
|
14449
|
+
skills: {
|
|
14450
|
+
index_path: "/.well-known/skills/index.json",
|
|
14451
|
+
default_agents: ["codex", "claude-code", "cursor"],
|
|
14452
|
+
npx_binary: "npx",
|
|
14453
|
+
npx_add_args_template: [
|
|
14454
|
+
"--yes",
|
|
14455
|
+
"skills",
|
|
14456
|
+
"add",
|
|
14457
|
+
"{skills_index_url}",
|
|
14458
|
+
"--agent",
|
|
14459
|
+
"{agents}",
|
|
14460
|
+
"--global",
|
|
14461
|
+
"--yes",
|
|
14462
|
+
"--skill",
|
|
14463
|
+
"{skill_name}",
|
|
14464
|
+
"--full-depth"
|
|
14465
|
+
]
|
|
14466
|
+
},
|
|
14467
|
+
cli: {
|
|
14468
|
+
legacy_python_shell_template: "curl -s {base_url}/api/v2/cli/install | bash",
|
|
14469
|
+
sdk_npm_global: "npm install -g deepline@latest"
|
|
14470
|
+
}
|
|
14471
|
+
};
|
|
14472
|
+
|
|
14473
|
+
// src/cli/install-commands.ts
|
|
14474
|
+
var INSTALL_COMMANDS = install_commands_default;
|
|
14475
|
+
function normalizeBaseUrl2(baseUrl) {
|
|
14476
|
+
return baseUrl.replace(/\/$/, "");
|
|
14477
|
+
}
|
|
14478
|
+
function renderTemplate(template, values) {
|
|
14479
|
+
return template.replace(/\{([a-z_]+)\}/g, (match, key) => {
|
|
14480
|
+
return values[key] ?? match;
|
|
14481
|
+
});
|
|
14482
|
+
}
|
|
14483
|
+
function shellJoin(args) {
|
|
14484
|
+
return args.join(" ");
|
|
14485
|
+
}
|
|
14486
|
+
function skillsIndexUrl(baseUrl) {
|
|
14487
|
+
return `${normalizeBaseUrl2(baseUrl)}${INSTALL_COMMANDS.skills.index_path}`;
|
|
14488
|
+
}
|
|
14489
|
+
function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
|
|
14490
|
+
const values = {
|
|
14491
|
+
skills_index_url: skillsIndexUrl(baseUrl),
|
|
14492
|
+
agents: INSTALL_COMMANDS.skills.default_agents.join(" "),
|
|
14493
|
+
skill_name: skillName
|
|
14494
|
+
};
|
|
14495
|
+
const rendered = INSTALL_COMMANDS.skills.npx_add_args_template.flatMap(
|
|
14496
|
+
(arg, index) => {
|
|
14497
|
+
const next = index === 0 && options.firstArg ? options.firstArg : arg;
|
|
14498
|
+
const value = renderTemplate(next, values);
|
|
14499
|
+
return arg === "{agents}" ? INSTALL_COMMANDS.skills.default_agents : value;
|
|
14500
|
+
}
|
|
14501
|
+
);
|
|
14502
|
+
return rendered;
|
|
14503
|
+
}
|
|
14504
|
+
function skillsInstallCommand(baseUrl, skillName) {
|
|
14505
|
+
return `${INSTALL_COMMANDS.skills.npx_binary} ${shellJoin(
|
|
14506
|
+
buildSkillsAddArgs(baseUrl, skillName)
|
|
14507
|
+
)}`;
|
|
14508
|
+
}
|
|
14509
|
+
function legacyPythonInstallCommand(baseUrl) {
|
|
14510
|
+
return renderTemplate(INSTALL_COMMANDS.cli.legacy_python_shell_template, {
|
|
14511
|
+
base_url: normalizeBaseUrl2(baseUrl)
|
|
14512
|
+
});
|
|
14513
|
+
}
|
|
14514
|
+
function sdkNpmGlobalInstallCommand() {
|
|
14515
|
+
return INSTALL_COMMANDS.cli.sdk_npm_global;
|
|
14516
|
+
}
|
|
14517
|
+
|
|
14518
|
+
// src/cli/command-compatibility.ts
|
|
14519
|
+
var COMMAND_COMPATIBILITY = command_compatibility_default;
|
|
14520
|
+
function cliFamilyLabel(family) {
|
|
14521
|
+
return family === "sdk" ? "SDK CLI" : "legacy Python CLI";
|
|
14522
|
+
}
|
|
14523
|
+
function commandCompatibilityHint(currentFamily, commandName, baseUrl) {
|
|
14524
|
+
const compatibility = COMMAND_COMPATIBILITY[commandName];
|
|
14525
|
+
if (!compatibility || compatibility.family === currentFamily) {
|
|
14526
|
+
return null;
|
|
14527
|
+
}
|
|
14528
|
+
const expectedFamily = compatibility.family;
|
|
14529
|
+
const currentLabel = cliFamilyLabel(currentFamily);
|
|
14530
|
+
const expectedLabel = cliFamilyLabel(expectedFamily);
|
|
14531
|
+
const lines = [
|
|
14532
|
+
"",
|
|
14533
|
+
"Command compatibility:",
|
|
14534
|
+
` \`deepline ${commandName}\` is ${compatibility.label}.`,
|
|
14535
|
+
` Current binary: ${currentLabel}. Required binary: ${expectedLabel}.`,
|
|
14536
|
+
" If this came from an agent skill, the installed skill likely targets the other Deepline CLI."
|
|
14537
|
+
];
|
|
14538
|
+
if (currentFamily === "sdk") {
|
|
14539
|
+
lines.push(
|
|
14540
|
+
"",
|
|
14541
|
+
" To stay on the SDK CLI, install the SDK agent skill:",
|
|
14542
|
+
` ${skillsInstallCommand(baseUrl, "deepline-sdk")}`,
|
|
14543
|
+
" To use the legacy Python CLI instead:",
|
|
14544
|
+
` ${legacyPythonInstallCommand(baseUrl)}`,
|
|
14545
|
+
" `deepline update` updates this SDK CLI, but it will not switch CLI families."
|
|
14546
|
+
);
|
|
14547
|
+
if (compatibility.sdk_alternative) {
|
|
14548
|
+
lines.push(` SDK alternative: ${compatibility.sdk_alternative}`);
|
|
14549
|
+
}
|
|
14550
|
+
} else {
|
|
14551
|
+
lines.push(
|
|
14552
|
+
"",
|
|
14553
|
+
" To use SDK commands, install the SDK CLI and SDK agent skill:",
|
|
14554
|
+
` ${sdkNpmGlobalInstallCommand()}`,
|
|
14555
|
+
` ${skillsInstallCommand(baseUrl, "deepline-sdk")}`,
|
|
14556
|
+
" `deepline update` updates this Python CLI and its skills, but it will not switch CLI families."
|
|
14557
|
+
);
|
|
14558
|
+
if (compatibility.python_alternative) {
|
|
14559
|
+
lines.push(` Python alternative: ${compatibility.python_alternative}`);
|
|
14560
|
+
}
|
|
14561
|
+
}
|
|
14562
|
+
return lines.join("\n");
|
|
14563
|
+
}
|
|
14564
|
+
function unknownCommandNameFromMessage(message) {
|
|
14565
|
+
const match = message.match(/unknown command ['"]([^'"]+)['"]/i);
|
|
14566
|
+
const command = match?.[1]?.trim();
|
|
14567
|
+
return command ? command : null;
|
|
14568
|
+
}
|
|
14569
|
+
|
|
14110
14570
|
// src/cli/skills-sync.ts
|
|
14111
14571
|
var import_node_child_process2 = require("child_process");
|
|
14112
14572
|
var import_node_fs14 = require("fs");
|
|
@@ -14114,7 +14574,6 @@ var import_node_os9 = require("os");
|
|
|
14114
14574
|
var import_node_path16 = require("path");
|
|
14115
14575
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
14116
14576
|
var SDK_SKILL_NAME = "deepline-sdk";
|
|
14117
|
-
var SKILL_AGENTS = ["codex", "claude-code", "cursor"];
|
|
14118
14577
|
var attemptedSync = false;
|
|
14119
14578
|
function shouldSkipSkillsSync() {
|
|
14120
14579
|
const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
|
|
@@ -14211,42 +14670,10 @@ async function fetchSkillsUpdate(baseUrl, localVersion) {
|
|
|
14211
14670
|
}
|
|
14212
14671
|
}
|
|
14213
14672
|
function buildSkillsInstallArgs(baseUrl) {
|
|
14214
|
-
|
|
14215
|
-
"/.well-known/skills/index.json",
|
|
14216
|
-
baseUrl
|
|
14217
|
-
).toString();
|
|
14218
|
-
return [
|
|
14219
|
-
"--yes",
|
|
14220
|
-
"skills",
|
|
14221
|
-
"add",
|
|
14222
|
-
packageUrl,
|
|
14223
|
-
"--agent",
|
|
14224
|
-
...SKILL_AGENTS,
|
|
14225
|
-
"--global",
|
|
14226
|
-
"--yes",
|
|
14227
|
-
"--skill",
|
|
14228
|
-
SDK_SKILL_NAME,
|
|
14229
|
-
"--full-depth"
|
|
14230
|
-
];
|
|
14673
|
+
return buildSkillsAddArgs(baseUrl, SDK_SKILL_NAME);
|
|
14231
14674
|
}
|
|
14232
14675
|
function buildBunxSkillsInstallArgs(baseUrl) {
|
|
14233
|
-
|
|
14234
|
-
"/.well-known/skills/index.json",
|
|
14235
|
-
baseUrl
|
|
14236
|
-
).toString();
|
|
14237
|
-
return [
|
|
14238
|
-
"--bun",
|
|
14239
|
-
"skills",
|
|
14240
|
-
"add",
|
|
14241
|
-
packageUrl,
|
|
14242
|
-
"--agent",
|
|
14243
|
-
...SKILL_AGENTS,
|
|
14244
|
-
"--global",
|
|
14245
|
-
"--yes",
|
|
14246
|
-
"--skill",
|
|
14247
|
-
SDK_SKILL_NAME,
|
|
14248
|
-
"--full-depth"
|
|
14249
|
-
];
|
|
14676
|
+
return buildSkillsAddArgs(baseUrl, SDK_SKILL_NAME, { firstArg: "--bun" });
|
|
14250
14677
|
}
|
|
14251
14678
|
function hasCommand(command) {
|
|
14252
14679
|
const result = (0, import_node_child_process2.spawnSync)(command, ["--version"], {
|
|
@@ -14358,6 +14785,13 @@ async function syncSdkSkillsIfNeeded(baseUrl) {
|
|
|
14358
14785
|
}
|
|
14359
14786
|
|
|
14360
14787
|
// src/cli/index.ts
|
|
14788
|
+
function asCommanderError(error) {
|
|
14789
|
+
if (!(error instanceof Error) || !("code" in error)) {
|
|
14790
|
+
return null;
|
|
14791
|
+
}
|
|
14792
|
+
const code = error.code;
|
|
14793
|
+
return typeof code === "string" && code.startsWith("commander.") ? error : null;
|
|
14794
|
+
}
|
|
14361
14795
|
function shouldPrintStartupPhase() {
|
|
14362
14796
|
if (process.argv.includes("--json")) {
|
|
14363
14797
|
return false;
|
|
@@ -14443,7 +14877,7 @@ async function main() {
|
|
|
14443
14877
|
progress?.phase("loading deepline cli");
|
|
14444
14878
|
}
|
|
14445
14879
|
const program = new import_commander3.Command();
|
|
14446
|
-
program.name("deepline").description("Deepline CLI (TypeScript SDK)").version(SDK_VERSION, "-v, --version", "Show version").showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
14880
|
+
program.name("deepline").description("Deepline CLI (TypeScript SDK)").version(SDK_VERSION, "-v, --version", "Show version").exitOverride().showHelpAfterError().showSuggestionAfterError(true).addHelpText(
|
|
14447
14881
|
"after",
|
|
14448
14882
|
`
|
|
14449
14883
|
Common commands:
|
|
@@ -14452,6 +14886,7 @@ Common commands:
|
|
|
14452
14886
|
deepline plays search email --json
|
|
14453
14887
|
deepline plays describe person-linkedin-to-email --json
|
|
14454
14888
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
14889
|
+
deepline secrets check HUBSPOT_TOKEN
|
|
14455
14890
|
deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
|
|
14456
14891
|
deepline update
|
|
14457
14892
|
|
|
@@ -14501,6 +14936,7 @@ Exit codes:
|
|
|
14501
14936
|
registerAuthCommands(program);
|
|
14502
14937
|
registerToolsCommands(program);
|
|
14503
14938
|
registerPlayCommands(program);
|
|
14939
|
+
registerSecretsCommands(program);
|
|
14504
14940
|
registerBillingCommands(program);
|
|
14505
14941
|
registerOrgCommands(program);
|
|
14506
14942
|
registerCsvCommands(program);
|
|
@@ -14570,6 +15006,7 @@ Examples:
|
|
|
14570
15006
|
ok: true
|
|
14571
15007
|
});
|
|
14572
15008
|
} catch (error) {
|
|
15009
|
+
const commanderError = asCommanderError(error);
|
|
14573
15010
|
recordCliTrace({
|
|
14574
15011
|
phase: "cli.main_total",
|
|
14575
15012
|
ms: Date.now() - mainStartedAt,
|
|
@@ -14577,7 +15014,26 @@ Examples:
|
|
|
14577
15014
|
error: error instanceof Error ? error.message : String(error)
|
|
14578
15015
|
});
|
|
14579
15016
|
progress?.fail();
|
|
14580
|
-
|
|
15017
|
+
const wantsJson = process.argv.includes("--json");
|
|
15018
|
+
if (commanderError) {
|
|
15019
|
+
if (commanderError.code === "commander.unknownCommand") {
|
|
15020
|
+
const commandName = unknownCommandNameFromMessage(
|
|
15021
|
+
commanderError.message
|
|
15022
|
+
);
|
|
15023
|
+
if (commandName && !wantsJson) {
|
|
15024
|
+
const hint = commandCompatibilityHint(
|
|
15025
|
+
"sdk",
|
|
15026
|
+
commandName,
|
|
15027
|
+
autoDetectBaseUrl()
|
|
15028
|
+
);
|
|
15029
|
+
if (hint) {
|
|
15030
|
+
console.error(hint);
|
|
15031
|
+
}
|
|
15032
|
+
}
|
|
15033
|
+
}
|
|
15034
|
+
process.exitCode = commanderError.code === "commander.unknownCommand" && !wantsJson ? 2 : commanderError.exitCode ?? 1;
|
|
15035
|
+
return;
|
|
15036
|
+
} else if (wantsJson) {
|
|
14581
15037
|
printJsonError(error);
|
|
14582
15038
|
} else if (error instanceof Error) {
|
|
14583
15039
|
console.error(`Error: ${error.message}`);
|