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 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.67",
232
+ version: "0.1.70",
233
233
  apiContract: "2026-05-play-bootstrap-dataset-summary",
234
234
  supportPolicy: {
235
- latest: "0.1.67",
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: (input) => this.getPlaySheetRows(input),
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, input, options) {
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: input },
944
+ { payload: input2 },
929
945
  headers
930
946
  );
931
947
  }
932
- async executeToolRaw(toolId, input, options) {
933
- return this.executeTool(toolId, input, options);
948
+ async executeToolRaw(toolId, input2, options) {
949
+ return this.executeTool(toolId, input2, options);
934
950
  }
935
- async queryCustomerDb(input) {
951
+ async queryCustomerDb(input2) {
936
952
  return this.http.post("/api/v2/db/query", {
937
- sql: input.sql,
938
- ...input.maxRows ? { max_rows: input.maxRows } : {}
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(input) {
1046
- const compilerManifest = input.compilerManifest ?? await this.compilePlayManifest({
1047
- name: input.name,
1048
- sourceCode: input.sourceCode,
1049
- sourceFiles: input.sourceFiles,
1050
- artifact: input.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
- ...input,
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(input) {
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", input);
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(input) {
1099
- return this.http.post("/api/v2/plays/check", input);
1100
- }
1101
- async startPlayRunFromBundle(input) {
1102
- const compilerManifest = input.compilerManifest ?? await this.compilePlayManifest({
1103
- name: input.name,
1104
- sourceCode: input.sourceCode,
1105
- sourceFiles: input.sourceFiles,
1106
- artifact: input.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: input.name,
1110
- sourceCode: input.sourceCode,
1111
- sourceFiles: input.sourceFiles,
1112
- artifact: input.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: input.name,
1139
+ name: input2.name,
1123
1140
  artifactStorageKey: registeredArtifact.artifactStorageKey,
1124
1141
  compilerManifest,
1125
- ...input.input ? { input: input.input } : {},
1126
- ...input.inputFile ? { inputFile: input.inputFile } : {},
1127
- ...input.packagedFiles?.length ? { packagedFiles: input.packagedFiles } : {},
1128
- ...input.force ? { force: true } : {}
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(input) {
1490
+ async getPlaySheetRows(input2) {
1474
1491
  const params = new URLSearchParams({
1475
- tableNamespace: input.tableNamespace,
1476
- limit: String(input.limit ?? 5e3),
1477
- offset: String(input.offset ?? 0)
1492
+ tableNamespace: input2.tableNamespace,
1493
+ limit: String(input2.limit ?? 5e3),
1494
+ offset: String(input2.offset ?? 0)
1478
1495
  });
1479
- if (input.runId?.trim()) {
1480
- params.set("runId", input.runId.trim());
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(input.playName)}/sheet?${params.toString()}`
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 output = runner.execFileSync(
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 = output.match(
1952
+ const httpsMatch = output2.match(
1936
1953
  /LSHandlerURLScheme\s*=\s*https;[\s\S]*?LSHandlerRole(?:All|Viewer|Editor)\s*=\s*"([^"]+)"/
1937
1954
  );
1938
- const httpMatch = output.match(
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(input) {
3384
- const columns = stripCsvProjectionColumns(input.columns, input.rows);
3385
- const rows = input.rows.map(stripCsvProjectionFields);
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(input) {
3442
- const candidate = input;
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(input) {
3484
- if (input.depth && input.depth > 16) {
3500
+ function collectDatasetCandidates(input2) {
3501
+ if (input2.depth && input2.depth > 16) {
3485
3502
  return;
3486
3503
  }
3487
- if (isSerializedDataset(input.value)) {
3488
- input.output.push({
3489
- source: input.path,
3490
- value: input.value,
3491
- total: input.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(input.value)) {
3512
+ if (!isRecord2(input2.value)) {
3496
3513
  return;
3497
3514
  }
3498
- for (const [key, child] of Object.entries(input.value)) {
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: `${input.path}.${key}`,
3505
- total: totalRowsForDataset(input.value, `${input.path}.${key}`),
3506
- output: input.output,
3507
- depth: (input.depth ?? 0) + 1
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(input) {
4026
- const destination = input.outPath ?? "stdout";
4042
+ function dbQueryExportEnvelope(input2) {
4043
+ const destination = input2.outPath ?? "stdout";
4027
4044
  return {
4028
- command: input.result.command,
4029
- format: input.format,
4030
- row_count: input.result.row_count,
4031
- row_count_returned: input.result.row_count_returned,
4032
- truncated: input.result.truncated,
4033
- ...input.outPath ? { file: input.outPath, local: { file: input.outPath } } : {},
4034
- next: { toolEquivalent: input.toolCommand },
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 ${input.result.row_count_returned} row(s) as ${input.format} to ${destination}`
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: input.toolCommand }]
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(input) {
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: input?.runtimeBackend ?? null
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(input) {
4554
- if (isPathInsideDirectory(input.resolvedPath, input.workspace.rootDir)) {
4617
+ function assertWithinPlayWorkspace(input2) {
4618
+ if (isPathInsideDirectory(input2.resolvedPath, input2.workspace.rootDir)) {
4555
4619
  return;
4556
4620
  }
4557
4621
  throw new Error(
4558
- `${input.importer}:${input.line}:${input.column} Local play imports must stay inside the play workspace (${input.workspace.rootDir}). Import "${input.specifier}" resolved to ${input.resolvedPath}, which crosses into app/backend code. Use the public SDK/API surface or move shared helpers into the play workspace.`
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
- return bundlePlayFile(filePath, {
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(input) {
6614
- if (!input.play) return null;
6615
- const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.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
- input.play.outputSchema,
6692
+ input2.play.outputSchema,
6618
6693
  outputField
6619
6694
  );
6620
6695
  const fieldType = fieldSchema ? jsonSchemaTypeExpression(fieldSchema) : "string | null";
6621
- return `type ${finderResultTypeName(input.finder)} =
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(input) {
6703
+ function generatedFinderPlayResultTypes(input2) {
6629
6704
  return ["email_finder", "phone_finder"].flatMap((finder) => {
6630
- const stage = finderStage(input.options, finder);
6705
+ const stage = finderStage(input2.options, finder);
6631
6706
  if (stage?.kind !== "play") return [];
6632
6707
  const typeDefinition = renderFinderPlayResultType({
6633
6708
  finder,
6634
- play: input.finderPlays[finder]
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(input) {
6693
- const { tool, indent, label, entity } = input;
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(input) {
6752
- const { schema, indent, label, entity } = input;
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(input) {
6820
- if (input.fields.length === 0) {
6821
- return `type ${input.typeName} = Record<string, unknown>;`;
6894
+ function renderPartialRowType(input2) {
6895
+ if (input2.fields.length === 0) {
6896
+ return `type ${input2.typeName} = Record<string, unknown>;`;
6822
6897
  }
6823
- const properties = input.fields.map((field) => ` ${jsString(field)}?: unknown;`).join("\n");
6824
- return `type ${input.typeName} = Record<string, unknown> & Partial<{
6825
- // ${input.comment}
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(input) {
6904
+ function fieldsFromSchemaDetails(input2) {
6830
6905
  return [
6831
- ...input.details.required.length ? input.details.required : input.fallbackFields,
6832
- ...input.details.optional
6906
+ ...input2.details.required.length ? input2.details.required : input2.fallbackFields,
6907
+ ...input2.details.optional
6833
6908
  ];
6834
6909
  }
6835
- function schemaFieldsForStage(stage, input) {
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(input.play?.inputSchema),
6842
- fallbackFields: input.fallbackFields
6916
+ details: schemaFieldDetails(input2.play?.inputSchema),
6917
+ fallbackFields: input2.fallbackFields
6843
6918
  });
6844
6919
  case "providers":
6845
- return input.tools.flatMap(
6920
+ return input2.tools.flatMap(
6846
6921
  (tool) => fieldsFromSchemaDetails({
6847
6922
  details: schemaFieldDetails(tool.inputSchema),
6848
- fallbackFields: input.fallbackFields
6923
+ fallbackFields: input2.fallbackFields
6849
6924
  })
6850
6925
  );
6851
6926
  }
6852
6927
  }
6853
- function sourceRowTypeDefinition(input) {
6854
- switch (input.options.from.kind) {
6928
+ function sourceRowTypeDefinition(input2) {
6929
+ switch (input2.options.from.kind) {
6855
6930
  case "csv":
6856
- return `type ${input.sourceTypeName} = SourceCsvRow;`;
6931
+ return `type ${input2.sourceTypeName} = SourceCsvRow;`;
6857
6932
  case "providers":
6858
6933
  return renderPartialRowType({
6859
- typeName: input.sourceTypeName,
6934
+ typeName: input2.sourceTypeName,
6860
6935
  fields: [
6861
- ...new Set(input.sourceTools.flatMap(listRowCandidateKeysFromTool))
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(input.sourcePlay?.outputSchema);
6941
+ const details = schemaFieldDetails(input2.sourcePlay?.outputSchema);
6867
6942
  return renderPartialRowType({
6868
- typeName: input.sourceTypeName,
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(input) {
6876
- const config = playBootstrapTemplateConfig(input.options.template);
6877
- if (config.sourceEntity !== "company" || !input.options.people) return null;
6878
- const emailFields = schemaFieldsForStage(input.options.email, {
6879
- tools: input.finderTools.email_finder ?? [],
6880
- play: input.finderPlays.email_finder,
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(input.options.phone, {
6884
- tools: input.finderTools.phone_finder ?? [],
6885
- play: input.finderPlays.phone_finder,
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(input.peoplePlay?.outputSchema),
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(input) {
6901
- const config = playBootstrapTemplateConfig(input.options.template);
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: input.options,
6980
+ options: input2.options,
6906
6981
  sourceTypeName,
6907
- sourceTools: input.sourceTools,
6908
- sourcePlay: input.sourcePlay
6982
+ sourceTools: input2.sourceTools,
6983
+ sourcePlay: input2.sourcePlay
6909
6984
  }),
6910
- contactBridgeRowTypeDefinition(input)
6985
+ contactBridgeRowTypeDefinition(input2)
6911
6986
  ];
6912
6987
  return definitions.filter(Boolean).join("\n\n");
6913
6988
  }
6914
- function validateBootstrapRoutes(input) {
6915
- const config = playBootstrapTemplateConfig(input.options.template);
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 input.sourceTools) {
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 ${input.options.template}: expected category ${sourceCategory}, got ${tool.categories.join(", ") || "none"}. Run: deepline tools grep ${sourceCategory} --categories ${sourceCategory} --json`
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 (input.options.people?.kind === "providers") {
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 input.finderTools[finder] ?? []) {
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(input) {
6959
- const getter = getterNamesFromTool(input.tool, input.kind)[0];
7033
+ function requiredGetterName(input2) {
7034
+ const getter = getterNamesFromTool(input2.tool, input2.kind)[0];
6960
7035
  if (!getter) {
6961
- switch (input.kind) {
7036
+ switch (input2.kind) {
6962
7037
  case "list":
6963
7038
  throw new PlayBootstrapValidationError(
6964
- `Cannot use ${input.label} as a source: it exposes no extracted list getters.`
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 ${input.label} as a finder: it exposes no extracted value getters.`
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(input) {
6975
- return `const sourceDataset = await ctx.csv<SourceCsvRow>(${jsString(input.packagedSourceCsvPath ?? input.source.value)});
6976
- const ${input.collection}: ${input.collectionType}[] = await sourceDataset.peek(limit);`;
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(input) {
7053
+ function generatePlaySourceRowsBlock(input2) {
6979
7054
  const playInput = generatePlayInputObject({
6980
- schema: input.sourcePlay?.inputSchema,
7055
+ schema: input2.sourcePlay?.inputSchema,
6981
7056
  indent: " ",
6982
- label: input.source.value,
6983
- entity: input.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 ${input.source.value}, choose the play output rows field, then delete this throw.`)});
6987
- const sourceResult = await ctx.runPlay('source_play', ${jsString(input.source.value)}, sourceInput, {
6988
- description: ${jsString(`Seed ${input.entity} rows from the selected play.`)},
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 ${input.collection}: ${input.collectionType}[] = (sourceResult.rows ?? []) as ${input.collectionType}[];`;
7066
+ const ${input2.collection}: ${input2.collectionType}[] = (sourceResult.rows ?? []) as ${input2.collectionType}[];`;
6992
7067
  }
6993
- function generateProviderSourceBlock(input) {
7068
+ function generateProviderSourceBlock(input2) {
6994
7069
  const getter = requiredGetterName({
6995
- tool: input.tool,
7070
+ tool: input2.tool,
6996
7071
  kind: "list",
6997
- label: input.provider
7072
+ label: input2.provider
6998
7073
  });
6999
- const inputName = `${input.entity}Input_${input.index}`;
7000
- return `// ${input.entity === "company" ? "Company" : "People"} source provider: ${input.provider}
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: input.tool,
7078
+ tool: input2.tool,
7004
7079
  indent: " ",
7005
- label: input.provider,
7006
- entity: input.entity
7080
+ label: input2.provider,
7081
+ entity: input2.entity
7007
7082
  }
7008
7083
  )};
7009
- throw new Error(${jsString(`TODO: fill ${inputName} for ${input.provider}, then delete this throw.`)});
7010
- const source_${input.index} = await ctx.tools.execute({
7011
- id: ${jsString(`${input.entity}_source_${input.index}`)},
7012
- tool: ${jsString(input.provider)},
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 ${input.entity} rows from ${input.provider}.`)},
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_${input.index}.extractedLists.${getter}.keys or the provider output schema, then map explicitly below.
7018
- const sourceRows_${input.index} = ${accessorExpression(`source_${input.index}.extractedLists`, getter)}.get() as ${input.collectionType}[];`;
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(input) {
7021
- const blocks = input.source.values.map(
7095
+ function generateProviderSourceRowsBlock(input2) {
7096
+ const blocks = input2.source.values.map(
7022
7097
  (provider, index) => generateProviderSourceBlock({
7023
7098
  provider,
7024
7099
  index,
7025
- tool: input.sourceTools[index] ?? null,
7026
- entity: input.entity,
7027
- collectionType: input.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 ${input.collection}: ${input.collectionType}[] = [${input.source.values.map((_, index) => `...sourceRows_${index}`).join(", ")}];`;
7106
+ const ${input2.collection}: ${input2.collectionType}[] = [${input2.source.values.map((_, index) => `...sourceRows_${index}`).join(", ")}];`;
7032
7107
  }
7033
- function generateSourceRowsBlock(input) {
7034
- const config = playBootstrapTemplateConfig(input.options.template);
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 (input.options.from.kind) {
7113
+ switch (input2.options.from.kind) {
7039
7114
  case "csv":
7040
7115
  return generateCsvSourceRowsBlock({
7041
- source: input.options.from,
7116
+ source: input2.options.from,
7042
7117
  collection,
7043
7118
  collectionType,
7044
- packagedSourceCsvPath: input.packagedSourceCsvPath
7119
+ packagedSourceCsvPath: input2.packagedSourceCsvPath
7045
7120
  });
7046
7121
  case "play":
7047
7122
  return generatePlaySourceRowsBlock({
7048
- source: input.options.from,
7049
- sourcePlay: input.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: input.options.from,
7057
- sourceTools: input.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(input) {
7065
- const sourceRows = generateSourceRowsBlock(input);
7066
- const peoplePlayRef = stagePlayRef(input.options.people);
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
- input.peoplePlay?.inputSchema,
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(input) {
7092
- return `${input.aggregateStepName}${input.index}_${safeIdentifier(input.provider)}`;
7166
+ function finderProviderStepName(input2) {
7167
+ return `${input2.aggregateStepName}${input2.index}_${safeIdentifier(input2.provider)}`;
7093
7168
  }
7094
- function finderValueGetter(input) {
7095
- const getters = getterNamesFromTool(input.tool, "value");
7096
- const getter = getters.find((name) => name === input.outputField) ?? requiredGetterName({
7097
- tool: input.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: input.provider
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(input) {
7108
- const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
7109
- const resultTypeName = finderResultTypeName(input.finder);
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
- input.play?.inputSchema,
7186
+ input2.play?.inputSchema,
7112
7187
  " ",
7113
- input.stage.value
7188
+ input2.stage.value
7114
7189
  );
7115
7190
  return `.step(${jsString(outputField)}, async (row, rowCtx) => {
7116
- const ${input.aggregateStepName}Input = ${payload};
7117
- throw new Error(${jsString(`TODO: map ${input.aggregateStepName}Input for ${input.stage.value}, then delete this throw.`)});
7118
- const ${input.aggregateStepName}Result = await rowCtx.runPlay<${resultTypeName}>(
7119
- ${jsString(`${input.aggregateStepName}Play`)},
7120
- ${jsString(input.stage.value)},
7121
- ${input.aggregateStepName}Input,
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 ${input.finder} play.`)},
7198
+ description: ${jsString(`Run ${input2.finder} play.`)},
7124
7199
  },
7125
7200
  );
7126
- return typeof ${input.aggregateStepName}Result === 'string'
7127
- ? ${input.aggregateStepName}Result.trim() || null
7128
- : ${input.aggregateStepName}Result?.${outputField} ?? null;
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(input) {
7206
+ function generateFinderProviderResolver(input2) {
7132
7207
  const payload = generateContactInputObjectFromSchema(
7133
- input.tool?.inputSchema,
7208
+ input2.tool?.inputSchema,
7134
7209
  " ",
7135
- input.provider
7210
+ input2.provider
7136
7211
  );
7137
7212
  const getter = finderValueGetter({
7138
- tool: input.tool,
7139
- provider: input.provider,
7140
- outputField: input.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 ${input.provider}, then delete this throw.`)});
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(`${input.aggregateStepName}_${input.providerIndex}`)},
7147
- tool: ${jsString(input.provider)},
7221
+ id: ${jsString(`${input2.aggregateStepName}_${input2.providerIndex}`)},
7222
+ tool: ${jsString(input2.provider)},
7148
7223
  input: providerInput,
7149
- description: ${jsString(`Try ${input.provider} as a ${input.finder}.`)},
7224
+ description: ${jsString(`Try ${input2.provider} as a ${input2.finder}.`)},
7150
7225
  });
7151
7226
  return {
7152
- ${input.outputField}: (${accessorExpression("result.extractedValues", getter)}.get() as string | null) ?? null,
7227
+ ${input2.outputField}: (${accessorExpression("result.extractedValues", getter)}.get() as string | null) ?? null,
7153
7228
  result,
7154
7229
  };
7155
7230
  }`;
7156
7231
  }
7157
- function generateFinderProviderStep(input) {
7158
- const stepName = input.stepNames[input.index];
7159
- switch (input.index) {
7232
+ function generateFinderProviderStep(input2) {
7233
+ const stepName = input2.stepNames[input2.index];
7234
+ switch (input2.index) {
7160
7235
  case 0:
7161
- return `.step(${jsString(stepName)}, ${input.resolver})`;
7236
+ return `.step(${jsString(stepName)}, ${input2.resolver})`;
7162
7237
  default: {
7163
- const priorCandidates = input.stepNames.slice(0, input.index).map((name) => `row.${name}`).join(", ");
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", input.outputField)}),
7168
- ${input.resolver},
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(input) {
7175
- const legPrefix = finderProviderStepPrefix(input.finder);
7176
- const stepNames = input.stage.values.map(
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 = input.stage.values.map(
7258
+ const providerSteps = input2.stage.values.map(
7184
7259
  (provider, index) => generateFinderProviderStep({
7185
7260
  index,
7186
7261
  stepNames,
7187
- outputField: input.outputField,
7262
+ outputField: input2.outputField,
7188
7263
  resolver: generateFinderProviderResolver({
7189
- finder: input.finder,
7264
+ finder: input2.finder,
7190
7265
  provider,
7191
7266
  providerIndex: index,
7192
- tool: input.tools[index] ?? null,
7193
- aggregateStepName: input.aggregateStepName,
7194
- outputField: input.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 `// ${input.aggregateStepName} provider waterfall. Each provider leg is active once its TODO throw is removed;
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(input.aggregateStepName)}, (row) => {
7277
+ .step(${jsString(input2.aggregateStepName)}, (row) => {
7203
7278
  const candidates = [${candidateNames}];
7204
- const match = candidates.find((candidate) => ${optionalFinderValueExpression("candidate", input.outputField)});
7205
- return ${optionalFinderValueExpression("match", input.outputField)} ?? null;
7279
+ const match = candidates.find((candidate) => ${optionalFinderValueExpression("candidate", input2.outputField)});
7280
+ return ${optionalFinderValueExpression("match", input2.outputField)} ?? null;
7206
7281
  })`;
7207
7282
  }
7208
- function generateFinderStageSteps(input) {
7209
- const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
7210
- const aggregateStepName = stepFieldName(input.finder);
7211
- switch (input.stage.kind) {
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: input.finder,
7215
- stage: input.stage,
7216
- play: input.finderPlays[input.finder],
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: input.finder,
7222
- stage: input.stage,
7223
- tools: input.finderTools[input.finder] ?? [],
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(input) {
7304
+ function generateFinderSteps(input2) {
7230
7305
  return ["email_finder", "phone_finder"].flatMap((finder) => {
7231
- const stage = finderStage(input.options, finder);
7306
+ const stage = finderStage(input2.options, finder);
7232
7307
  return stage ? [
7233
7308
  generateFinderStageSteps({
7234
- ...input,
7309
+ ...input2,
7235
7310
  finder,
7236
7311
  stage
7237
7312
  })
7238
7313
  ] : [];
7239
7314
  }).join("\n ");
7240
7315
  }
7241
- function generateBootstrapPlaySource(input) {
7242
- const config = playBootstrapTemplateConfig(input.options.template);
7243
- const sourceSeedBlock = generateSourceSeedBlock(input);
7244
- const finderSteps = generateFinderSteps(input);
7245
- const hasPeople = config.sourceEntity === "people" || Boolean(input.options.people);
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 = input.options.from.kind === "csv" ? renderSourceCsvRowType(input.sourceCsvColumns) : "";
7250
- const rowTypeDefinitions = generateRowTypeDefinitions(input);
7251
- const finderPlayResultTypes = generatedFinderPlayResultTypes(input);
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(input.options) ? "definePlay, when" : "definePlay";
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(input.options.name)}, async (ctx, input: Input = {}) => {
7267
- const limit = Math.max(1, Math.min(Number(input.limit ?? ${input.options.limit}), ${input.options.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 ${input.options.template}: seed source rows, run requested stages, then return the mapped rows.`)},
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(input) {
7688
- const bytes = Array.from(new TextEncoder().encode(input));
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(input) {
7937
+ function addPlayCheckRepairHints(input2) {
7863
7938
  let addedHint = false;
7864
- return input.errors.map((error) => {
7865
- const line = sourceLineForError(input.sourceCode, error);
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(input) {
8003
+ function buildBarePrebuiltReferenceError(input2) {
7928
8004
  return new Error(
7929
- `Prebuilt play "${input.requested}" must be referenced as "${input.reference}". Use the prebuilt/ namespace anywhere you run, describe, get, or link to Deepline-managed plays.`
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(input) {
7973
- if (isFileTarget(input.target)) {
8048
+ function materializeRemotePlaySource(input2) {
8049
+ if (isFileTarget(input2.target)) {
7974
8050
  return null;
7975
8051
  }
7976
- if (!input.sourceCode.trim()) {
8052
+ if (!input2.sourceCode.trim()) {
7977
8053
  return null;
7978
8054
  }
7979
- const outputPath = input.outPath ?? defaultMaterializedPlayPath(input.playName);
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 === input.sourceCode) {
8058
+ if (existingSource === input2.sourceCode) {
7983
8059
  return { path: outputPath, status: "unchanged", created: false };
7984
8060
  }
7985
- (0, import_node_fs10.writeFileSync)(outputPath, input.sourceCode, "utf-8");
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, input.sourceCode, "utf-8");
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(input) {
8039
- return `\`deepline plays ${input.command} <run-id>\` expects a play name, but this looks like a run id.
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 ${input.runId} --json
8042
- deepline runs logs ${input.runId} --json
8043
- deepline runs export ${input.runId} --out output.csv`;
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(input, path) {
8173
+ function getDottedInputValue(input2, path) {
8098
8174
  const parts = path.split(".").map((part) => part.trim()).filter(Boolean);
8099
- let cursor = input;
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(input, path, value) {
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 = input;
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(input) {
8181
- return input.revisionSelector === "latest" || inputContainsLocalFilePath(input.runtimeInput);
8256
+ function namedRunNeedsPlayDefinition(input2) {
8257
+ return input2.revisionSelector === "latest" || inputContainsLocalFilePath(input2.runtimeInput);
8182
8258
  }
8183
- async function stageFileInputArgs(input) {
8259
+ async function stageFileInputArgs(input2) {
8184
8260
  const uniqueBindings = [
8185
8261
  ...new Map(
8186
- input.bindings.map((binding) => [binding.inputPath, binding])
8262
+ input2.bindings.map((binding) => [binding.inputPath, binding])
8187
8263
  ).values()
8188
8264
  ];
8189
8265
  const localFiles = uniqueBindings.flatMap((binding) => {
8190
- const value = getDottedInputValue(input.runtimeInput, binding.inputPath);
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
- input.progress.phase(
8274
+ input2.progress.phase(
8199
8275
  localFiles.length === 1 ? "staging input file" : "staging input files"
8200
8276
  );
8201
- const staged = await input.client.stagePlayFiles(
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
- input.runtimeInput,
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
- input.runtimeInput,
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(input) {
8574
+ function buildMapTableDebugCommand(input2) {
8499
8575
  try {
8500
8576
  const tableName = validatePlaySheetTableName(
8501
- input.playName,
8502
- input.tableNamespace
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(input.runId)} limit 20`;
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(input) {
8528
- if (input.jsonOutput || !input.runId || input.runId === "pending") {
8603
+ function emitLiveDebugTableHints(input2) {
8604
+ if (input2.jsonOutput || !input2.runId || input2.runId === "pending") {
8529
8605
  return;
8530
8606
  }
8531
- input.state.emittedDebugKeys ??= /* @__PURE__ */ new Set();
8532
- const receiptsKey = `receipts:${input.runId}`;
8533
- if (!input.state.emittedDebugKeys.has(receiptsKey)) {
8534
- input.state.emittedDebugKeys.add(receiptsKey);
8535
- input.progress.writeLine(
8536
- `Debug top-level outputs: ${buildStepReceiptsDebugCommand(input.runId)}`,
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(input.event);
8616
+ const tableNamespace = extractTableNamespaceFromLiveEvent(input2.event);
8541
8617
  if (!tableNamespace) {
8542
8618
  return;
8543
8619
  }
8544
- const tableKey = `table:${input.runId}:${tableNamespace}`;
8545
- if (input.state.emittedDebugKeys.has(tableKey)) {
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: input.playName,
8550
- runId: input.runId,
8625
+ playName: input2.playName,
8626
+ runId: input2.runId,
8551
8627
  tableNamespace
8552
8628
  });
8553
8629
  if (!command) {
8554
8630
  return;
8555
8631
  }
8556
- input.state.emittedDebugKeys.add(tableKey);
8557
- input.progress.writeLine(
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(input) {
8591
- const completed = typeof input.completed === "number" && Number.isFinite(input.completed) ? input.completed : null;
8592
- const total = typeof input.total === "number" && Number.isFinite(input.total) ? input.total : null;
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 input.failed === "number" && Number.isFinite(input.failed) && input.failed > 0 ? `, failed ${formatInteger(input.failed)}` : "";
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(input) {
8643
- for (const line of input.lines) {
8718
+ function printPlayProgressLines(input2) {
8719
+ for (const line of input2.lines) {
8644
8720
  const signature = line.trim();
8645
- if (!signature || input.state.lastProgressSignature === signature) {
8721
+ if (!signature || input2.state.lastProgressSignature === signature) {
8646
8722
  continue;
8647
8723
  }
8648
- input.state.lastProgressSignature = signature;
8649
- input.progress.writeLine(line);
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(input) {
8658
- if (input.jsonOutput || input.noOpen || !input.dashboardUrl) {
8733
+ function openPlayDashboard(input2) {
8734
+ if (input2.jsonOutput || input2.noOpen || !input2.dashboardUrl) {
8659
8735
  return;
8660
8736
  }
8661
- openInBrowser(input.dashboardUrl);
8737
+ openInBrowser(input2.dashboardUrl);
8662
8738
  }
8663
- function printPlayLogLines(input) {
8664
- for (const line of input.lines) {
8665
- if (input.emitLogs) {
8739
+ function printPlayLogLines(input2) {
8740
+ for (const line of input2.lines) {
8741
+ if (input2.emitLogs) {
8666
8742
  const formatted = formatPlayLogLine(
8667
8743
  line,
8668
- input.status ?? void 0,
8669
- input.state
8744
+ input2.status ?? void 0,
8745
+ input2.state
8670
8746
  );
8671
8747
  if (formatted) {
8672
- input.progress.writeLogLine(formatted);
8748
+ input2.progress.writeLogLine(formatted);
8673
8749
  }
8674
8750
  }
8675
- input.state.lastLogIndex += 1;
8751
+ input2.state.lastLogIndex += 1;
8676
8752
  }
8677
8753
  }
8678
- function assertPlayWaitNotTimedOut(input) {
8679
- if (input.waitTimeoutMs !== null && Date.now() - input.startedAt >= input.waitTimeoutMs) {
8680
- const hasRealRunId = input.workflowId.length > 0 && input.workflowId !== "pending";
8681
- const phaseSuffix = input.lastPhase && input.lastPhase.trim() ? ` (last observed phase: ${input.lastPhase.trim()})` : "";
8682
- const tailHint = hasRealRunId ? ` Run 'deepline runs tail ${input.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.`;
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 ? input.workflowId : "<no run id>"} after ${Math.ceil(input.waitTimeoutMs / 1e3)}s${phaseSuffix}.${tailHint}`,
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: input.workflowId, workflowId: input.workflowId } : {},
8689
- ...input.lastPhase ? { phase: input.lastPhase } : {},
8690
- timeoutMs: input.waitTimeoutMs
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(input) {
8771
+ async function waitForPlayCompletionByStream(input2) {
8696
8772
  const controller = new AbortController();
8697
8773
  let timedOut = false;
8698
8774
  let lastPhase = null;
8699
- const timeout = input.waitTimeoutMs === null ? null : setTimeout(
8775
+ const timeout = input2.waitTimeoutMs === null ? null : setTimeout(
8700
8776
  () => {
8701
8777
  timedOut = true;
8702
8778
  controller.abort();
8703
8779
  },
8704
- Math.max(1, input.waitTimeoutMs - (Date.now() - input.startedAt))
8780
+ Math.max(1, input2.waitTimeoutMs - (Date.now() - input2.startedAt))
8705
8781
  );
8706
8782
  try {
8707
- for await (const event of input.client.streamPlayRunEvents(
8708
- input.workflowId,
8783
+ for await (const event of input2.client.streamPlayRunEvents(
8784
+ input2.workflowId,
8709
8785
  { signal: controller.signal }
8710
8786
  )) {
8711
- assertPlayWaitNotTimedOut({ ...input, lastPhase });
8787
+ assertPlayWaitNotTimedOut({ ...input2, lastPhase });
8712
8788
  const phase = describeLiveEventPhase(event);
8713
8789
  if (phase) {
8714
8790
  lastPhase = phase;
8715
- input.progress.phase(phase);
8791
+ input2.progress.phase(phase);
8716
8792
  }
8717
8793
  emitLiveDebugTableHints({
8718
8794
  event,
8719
- playName: input.playName,
8720
- runId: input.workflowId,
8721
- jsonOutput: input.jsonOutput,
8722
- state: input.state,
8723
- progress: input.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: input.jsonOutput,
8729
- emitLogs: input.emitLogs,
8730
- state: input.state,
8731
- progress: input.progress
8804
+ jsonOutput: input2.jsonOutput,
8805
+ emitLogs: input2.emitLogs,
8806
+ state: input2.state,
8807
+ progress: input2.progress
8732
8808
  });
8733
- if (!input.jsonOutput) {
8809
+ if (!input2.jsonOutput) {
8734
8810
  printPlayProgressLines({
8735
8811
  lines: getProgressLinesFromLiveEvent(event),
8736
- state: input.state,
8737
- progress: input.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 input.client.getPlayStatus(input.workflowId, {
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 input.dashboardUrl ? { ...finalStatus, dashboardUrl: input.dashboardUrl } : finalStatus;
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({ ...input, lastPhase });
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=${input.workflowId}${phaseSuffix}.`,
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: input.workflowId,
8767
- workflowId: input.workflowId,
8842
+ runId: input2.workflowId,
8843
+ workflowId: input2.workflowId,
8768
8844
  ...lastPhase ? { phase: lastPhase } : {}
8769
8845
  }
8770
8846
  );
8771
8847
  }
8772
- async function startAndWaitForPlayCompletionByStream(input) {
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(input);
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 (!input.jsonOutput) {
8780
- input.progress.writeLine(
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: input.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 ${input.playName} did not start after retrying transient start failures.`,
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(input) {
8876
+ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
8801
8877
  const startedAt = Date.now();
8802
8878
  const dashboardUrl = buildPlayDashboardUrl(
8803
- input.client.baseUrl,
8804
- input.playName
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 timeout = input.waitTimeoutMs === null ? null : setTimeout(
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, input.waitTimeoutMs)
8903
+ Math.max(1, input2.waitTimeoutMs)
8824
8904
  );
8825
8905
  try {
8826
- for await (const event of input.client.startPlayRunStream(input.request, {
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 (!input.jsonOutput) {
8917
+ if (!input2.jsonOutput) {
8838
8918
  writeStartedPlayRun({
8839
8919
  runId: workflowId,
8840
- playName: input.playName,
8920
+ playName: input2.playName,
8841
8921
  dashboardUrl,
8842
8922
  jsonOutput: false,
8843
- progress: input.progress
8923
+ progress: input2.progress
8844
8924
  });
8845
8925
  }
8846
8926
  openPlayDashboard({
8847
8927
  dashboardUrl,
8848
- jsonOutput: input.jsonOutput,
8849
- noOpen: input.noOpen
8928
+ jsonOutput: input2.jsonOutput,
8929
+ noOpen: input2.noOpen
8850
8930
  });
8851
- input.progress.phase(`loading play on ${dashboardUrl}`);
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: input.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
- input.progress.phase(phase);
8943
+ input2.progress.phase(phase);
8864
8944
  }
8865
8945
  printPlayLogLines({
8866
8946
  lines: getLogLinesFromLiveEvent(event),
8867
8947
  status: null,
8868
- jsonOutput: input.jsonOutput,
8869
- emitLogs: input.emitLogs,
8948
+ jsonOutput: input2.jsonOutput,
8949
+ emitLogs: input2.emitLogs,
8870
8950
  state,
8871
- progress: input.progress
8951
+ progress: input2.progress
8872
8952
  });
8873
8953
  emitLiveDebugTableHints({
8874
8954
  event,
8875
- playName: input.playName,
8955
+ playName: input2.playName,
8876
8956
  runId: workflowId,
8877
- jsonOutput: input.jsonOutput,
8957
+ jsonOutput: input2.jsonOutput,
8878
8958
  state,
8879
- progress: input.progress
8959
+ progress: input2.progress
8880
8960
  });
8881
- if (!input.jsonOutput) {
8961
+ if (!input2.jsonOutput) {
8882
8962
  printPlayProgressLines({
8883
8963
  lines: getProgressLinesFromLiveEvent(event),
8884
8964
  state,
8885
- progress: input.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: input.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: input.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 (!input.jsonOutput) {
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: input.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: input.client,
8936
- playName: input.playName,
9015
+ client: input2.client,
9016
+ playName: input2.playName,
8937
9017
  workflowId: lastKnownWorkflowId,
8938
9018
  dashboardUrl,
8939
- jsonOutput: input.jsonOutput,
8940
- emitLogs: input.emitLogs,
8941
- waitTimeoutMs: input.waitTimeoutMs,
9019
+ jsonOutput: input2.jsonOutput,
9020
+ emitLogs: input2.emitLogs,
9021
+ waitTimeoutMs: input2.waitTimeoutMs,
8942
9022
  startedAt,
8943
9023
  state,
8944
- progress: input.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 (!input.jsonOutput) {
8955
- input.progress.writeLine(
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: input.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: input.client,
8972
- playName: input.playName,
9051
+ client: input2.client,
9052
+ playName: input2.playName,
8973
9053
  workflowId: lastKnownWorkflowId,
8974
9054
  dashboardUrl,
8975
- jsonOutput: input.jsonOutput,
8976
- emitLogs: input.emitLogs,
8977
- waitTimeoutMs: input.waitTimeoutMs,
9055
+ jsonOutput: input2.jsonOutput,
9056
+ emitLogs: input2.emitLogs,
9057
+ waitTimeoutMs: input2.waitTimeoutMs,
8978
9058
  startedAt,
8979
9059
  state,
8980
- progress: input.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 output = {};
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
- output[key] = compactReturnValue(entry, depth + 1);
9152
+ output2[key] = compactReturnValue(entry, depth + 1);
9073
9153
  }
9074
- return output;
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(input) {
9284
- const operation = getStringField(input.billing, "operation_id") ?? getStringField(input.billing, "operation") ?? extractToolIdFromErrorText(input.error) ?? getStringField(input.billing, "provider") ?? "tool call";
9285
- const balance = formatCreditAmount(input.billing.balance_credits);
9286
- const required = formatCreditAmount(input.billing.required_credits);
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
- input.billing.recommended_add_credits ?? input.billing.needed_credits
9368
+ input2.billing.recommended_add_credits ?? input2.billing.needed_credits
9289
9369
  );
9290
- const billingUrl = getStringField(input.billing, "billing_url");
9291
- const workspace = getStringField(input.billing, "workspace_id") ?? getStringField(input.billing, "workspaceId");
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(input) {
9297
- const progress = input.status.progress;
9298
- const rowsInfo = extractCanonicalRowsInfo(input.status);
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(input.billing, "billing_url");
9386
+ const billingUrl = getStringField(input2.billing, "billing_url");
9307
9387
  const recommended = formatCreditAmount(
9308
- input.billing.recommended_add_credits ?? input.billing.needed_credits
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 = input.status.runId?.trim();
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 output = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
9651
- const actions = output?.actions && typeof output.actions === "object" && !Array.isArray(output.actions) ? output.actions : null;
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 output = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
9674
- const rowCount = output && typeof output.rowCount === "number" ? ` rows=${formatInteger(output.rowCount)}` : "";
9675
- const preview = output?.preview && typeof output.preview === "object" && !Array.isArray(output.preview) ? output.preview : null;
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(output?.summary));
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(input) {
9762
- if (!getPlayRunPackage(input.status)) {
9763
- return input.status;
9841
+ async function resolvePlayRunOutputStatus(input2) {
9842
+ if (!getPlayRunPackage(input2.status)) {
9843
+ return input2.status;
9764
9844
  }
9765
- const runId = input.status.runId;
9845
+ const runId = input2.status.runId;
9766
9846
  if (!runId) {
9767
- return input.status;
9847
+ return input2.status;
9768
9848
  }
9769
- const refreshedStatus = await input.client.getPlayStatus(runId, {
9849
+ const refreshedStatus = await input2.client.getPlayStatus(runId, {
9770
9850
  billing: false,
9771
- full: input.fullJson
9851
+ full: input2.fullJson
9772
9852
  });
9773
- const dashboardUrl = input.status.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(input) {
9805
- const playName = extractRunPlayName(input.status);
9806
- const tableNamespace = input.rowsInfo.tableNamespace?.trim();
9807
- if (!playName || !tableNamespace || input.rowsInfo.totalRows <= 0) {
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(input.status.runId)} limit ${input.rowsInfo.totalRows}`;
9814
- const base = `deepline customer-db query --sql ${shellSingleQuote(sql)} --max-rows ${input.rowsInfo.totalRows}`;
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)(input.outPath))}`
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(input) {
9870
- const playName = extractRunPlayName(input.status);
9871
- const tableNamespace = input.rowsInfo.tableNamespace?.trim();
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 = input.rowsInfo.totalRows;
9957
+ let expectedTotal = input2.rowsInfo.totalRows;
9878
9958
  while (true) {
9879
- const page = await input.client.runs.exportDatasetRows({
9959
+ const page = await input2.client.runs.exportDatasetRows({
9880
9960
  playName,
9881
9961
  tableNamespace,
9882
- runId: input.status.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 < input.rowsInfo.totalRows) {
9977
+ if (rows.length < input2.rowsInfo.totalRows) {
9898
9978
  return null;
9899
9979
  }
9900
9980
  const columns = mergeExportColumns(
9901
- input.rowsInfo.columnsExplicit ? input.rowsInfo.columns : [],
9981
+ input2.rowsInfo.columnsExplicit ? input2.rowsInfo.columns : [],
9902
9982
  rows
9903
9983
  );
9904
9984
  return {
9905
- ...input.rowsInfo,
9985
+ ...input2.rowsInfo,
9906
9986
  rows,
9907
9987
  columns,
9908
9988
  totalRows: rows.length,
9909
9989
  complete: true,
9910
- source: `${input.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
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(input) {
10092
+ function formatActiveRunConflictError(input2) {
10013
10093
  const lines = [
10014
- `Active run exists for ${input.playName}. Use --force to supersede, or inspect/stop the active run first.`
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 input.activeRuns.slice(0, 3)) {
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(input) {
10131
- if (input.package && isPlayRunPackageValue(input.package)) {
10132
- if (input.jsonOutput) {
10133
- printCommandEnvelope(input.package, { json: true });
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(input.package);
10137
- const output2 = lines2.join("\n");
10138
- if (input.progress) {
10139
- input.progress.writeLine(output2, process.stdout);
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(input.package, {
10222
+ printCommandEnvelope(input2.package, {
10143
10223
  json: false,
10144
- text: `${output2}
10224
+ text: `${output3}
10145
10225
  `
10146
10226
  });
10147
10227
  return;
10148
10228
  }
10149
10229
  const payload = {
10150
- runId: input.runId,
10151
- workflowId: input.runId,
10152
- name: input.playName,
10153
- status: input.status ?? "started",
10154
- dashboardUrl: input.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 ${input.runId} --json`,
10157
- full: `deepline runs get ${input.runId} --full --json`,
10158
- logs: `deepline runs logs ${input.runId} --json`,
10159
- export: `deepline runs export ${input.runId} --out output.csv`,
10160
- stop: `deepline runs stop ${input.runId} --reason "stale lock" --json`
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 ${input.playName}`,
10165
- ` run id: ${input.runId}`,
10166
- ` inspect: deepline runs get ${input.runId} --json`,
10167
- ` full debug: deepline runs get ${input.runId} --full --json`,
10168
- ` logs: deepline runs logs ${input.runId} --json`,
10169
- ` export after completion: deepline runs export ${input.runId} --out output.csv`,
10170
- ` stop run: deepline runs stop ${input.runId} --reason "stale lock" --json`
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 (input.jsonOutput) {
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 (input.dashboardUrl) {
10183
- lines.push(` play page: ${input.dashboardUrl}`);
10262
+ if (input2.dashboardUrl) {
10263
+ lines.push(` play page: ${input2.dashboardUrl}`);
10184
10264
  }
10185
- const output = lines.join("\n");
10186
- if (input.progress) {
10187
- input.progress.writeLine(output, process.stdout);
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: `${output}
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 input = null;
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
- input = parseJsonInput(args[++index]);
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
- input ??= {};
10274
- setDottedInputValue(input, path, parseInputFlagValue(value));
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(input) {
10677
- if (input.revisionId) {
10678
- return input.revisionId;
10756
+ async function resolveNamedRunRevisionId(input2) {
10757
+ if (input2.revisionId) {
10758
+ return input2.revisionId;
10679
10759
  }
10680
- if (input.selector === "latest") {
10681
- const versions = await input.client.listPlayVersions(input.playName);
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 ${input.playName}.`);
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(input) {
13690
- const stem = safeFileStem(input.toolId);
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 = input.rows.length > 0 ? `${JSON.stringify(input.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
13698
- const columns = Object.keys(input.rows[0] ?? {}).join(", ");
13699
- const rowKey = Object.prototype.hasOwnProperty.call(input.rows[0] ?? {}, "id") ? '"id"' : "(row) => JSON.stringify(row)";
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(input.toolId)},
13705
- tool: ${JSON.stringify(input.toolId)},
13706
- input: ${JSON.stringify(input.payload)},
13707
- description: ${JSON.stringify(`Seed ${input.toolId} rows for workflow expansion.`)},
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(input) {
13740
- const envelope = commandEnvelopeFromRawResponse(input.rawResponse);
13741
- const summaryEntries = Object.entries(input.summary);
13742
- const outputPreview = input.listConversion ? {
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: input.listConversion.rows.length,
13745
- columns: Object.keys(input.listConversion.rows[0] ?? {}),
13746
- preview: input.listConversion.rows.slice(0, 5),
13747
- listStrategy: input.listConversion.strategy,
13748
- listSourcePath: input.listConversion.sourcePath
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: input.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 ${input.toolId} --input ${shellQuote(JSON.stringify(input.params))} --json`;
13755
- const actions = input.listConversion ? [
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: input.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
- ...input.listConversion ? {
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: input.listConversion.sourcePath ?? "auto-detected list in the CLI response preview"
14062
+ listSourcePath: input2.listConversion.sourcePath ?? "auto-detected list in the CLI response preview"
13771
14063
  } : {}
13772
14064
  },
13773
14065
  render: {
13774
- sections: input.listConversion ? [
14066
+ sections: input2.listConversion ? [
13775
14067
  {
13776
14068
  title: "output",
13777
14069
  lines: [
13778
- `${input.listConversion.rows.length} row(s) extracted from ${input.listConversion.sourcePath ?? "auto-detected list"}`,
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(input.listConversion.rows[0] ?? {}))}`,
13781
- `preview: ${JSON.stringify(input.listConversion.rows.slice(0, 5))}`
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(input.rawResponse, null, 2)]
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
- const packageUrl = new URL(
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
- const packageUrl = new URL(
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
- if (process.argv.includes("--json")) {
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}`);