deepline 0.1.153 → 0.1.155

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.
Files changed (48) hide show
  1. package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +15 -0
  2. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +1180 -825
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +34 -18
  4. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +41 -0
  5. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/receipts.ts +143 -8
  6. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-receipts.ts +104 -0
  7. package/dist/bundling-sources/sdk/src/index.ts +0 -1
  8. package/dist/bundling-sources/sdk/src/play.ts +3 -48
  9. package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +27 -2
  10. package/dist/bundling-sources/sdk/src/release.ts +6 -4
  11. package/dist/bundling-sources/sdk/src/worker-play-entry.ts +0 -10
  12. package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +0 -1
  13. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +87 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +0 -59
  15. package/dist/bundling-sources/shared_libs/play-runtime/cell-staleness.ts +0 -253
  16. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +805 -1570
  17. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +47 -74
  18. package/dist/bundling-sources/shared_libs/play-runtime/default-batch-strategies.ts +36 -14
  19. package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +145 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +284 -0
  21. package/dist/bundling-sources/shared_libs/play-runtime/postgres-json.ts +12 -5
  22. package/dist/bundling-sources/shared_libs/play-runtime/run-lifecycle-policy.ts +78 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +10 -45
  24. package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +1 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +923 -535
  26. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +45 -76
  27. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +12 -1
  28. package/dist/bundling-sources/shared_libs/play-runtime/step-program-dataset-builder.ts +1 -14
  29. package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +159 -0
  30. package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +4 -1
  31. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +32 -0
  32. package/dist/bundling-sources/shared_libs/plays/definition.ts +4 -2
  33. package/dist/bundling-sources/shared_libs/plays/runtime-validation.ts +3 -14
  34. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +1 -43
  35. package/dist/cli/index.js +1305 -401
  36. package/dist/cli/index.mjs +1273 -363
  37. package/dist/{compiler-manifest-BjoRENv9.d.ts → compiler-manifest-DW1flrHk.d.mts} +0 -9
  38. package/dist/{compiler-manifest-BjoRENv9.d.mts → compiler-manifest-DW1flrHk.d.ts} +0 -9
  39. package/dist/index.d.mts +9 -38
  40. package/dist/index.d.ts +9 -38
  41. package/dist/index.js +26 -13
  42. package/dist/index.mjs +26 -13
  43. package/dist/plays/bundle-play-file.d.mts +2 -2
  44. package/dist/plays/bundle-play-file.d.ts +2 -2
  45. package/package.json +1 -1
  46. package/dist/bundling-sources/shared_libs/play-data-plane/cell-policy.ts +0 -76
  47. package/dist/bundling-sources/shared_libs/play-runtime/progress-emitter.ts +0 -197
  48. package/dist/bundling-sources/shared_libs/play-runtime/waterfall-replay.ts +0 -79
package/dist/cli/index.js CHANGED
@@ -182,8 +182,8 @@ configureProxyFromEnv();
182
182
 
183
183
  // src/cli/index.ts
184
184
  var import_promises5 = require("fs/promises");
185
- var import_node_path19 = require("path");
186
- var import_node_os14 = require("os");
185
+ var import_node_path20 = require("path");
186
+ var import_node_os15 = require("os");
187
187
  var import_commander3 = require("commander");
188
188
 
189
189
  // src/config.ts
@@ -655,17 +655,19 @@ var SDK_RELEASE = {
655
655
  // the SDK enrich generator's one-second stale policy.
656
656
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
657
657
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
658
- version: "0.1.153",
658
+ // 0.1.154 removes the short-lived generated enrich StepOptions recompute
659
+ // fields shipped in 0.1.153.
660
+ version: "0.1.155",
659
661
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
660
662
  supportPolicy: {
661
- latest: "0.1.153",
663
+ latest: "0.1.155",
662
664
  minimumSupported: "0.1.53",
663
665
  deprecatedBelow: "0.1.53",
664
666
  commandMinimumSupported: [
665
667
  {
666
668
  command: "enrich",
667
- minimumSupported: "0.1.108",
668
- reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
669
+ minimumSupported: "0.1.154",
670
+ reason: "Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source."
669
671
  },
670
672
  {
671
673
  command: "plays",
@@ -1252,7 +1254,7 @@ function decodeSseFrame(frame) {
1252
1254
  return parsed;
1253
1255
  }
1254
1256
  function sleep(ms) {
1255
- return new Promise((resolve13) => setTimeout(resolve13, ms));
1257
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
1256
1258
  }
1257
1259
  function withCoworkNetworkHint(message) {
1258
1260
  if (!isCoworkLikeSandbox2() || message.includes(COWORK_NETWORK_HINT)) {
@@ -1462,8 +1464,15 @@ function normalizeStepProgress(value) {
1462
1464
  };
1463
1465
  }
1464
1466
 
1465
- // ../shared_libs/play-runtime/run-snapshot-stream.ts
1466
- function normalizePlayRunLiveStatus(value) {
1467
+ // ../shared_libs/play-runtime/run-lifecycle-policy.ts
1468
+ var TERMINAL_PLAY_RUN_STATUSES = /* @__PURE__ */ new Set([
1469
+ "completed",
1470
+ "failed",
1471
+ "cancelled",
1472
+ "terminated",
1473
+ "timed_out"
1474
+ ]);
1475
+ function normalizePlayRunLifecycleStatus(value) {
1467
1476
  const normalized = String(value ?? "").trim().toLowerCase();
1468
1477
  switch (normalized) {
1469
1478
  case "queued":
@@ -1471,6 +1480,7 @@ function normalizePlayRunLiveStatus(value) {
1471
1480
  return "running";
1472
1481
  case "running":
1473
1482
  case "started":
1483
+ case "waiting":
1474
1484
  return "running";
1475
1485
  case "completed":
1476
1486
  case "complete":
@@ -1491,8 +1501,16 @@ function normalizePlayRunLiveStatus(value) {
1491
1501
  return "unknown";
1492
1502
  }
1493
1503
  }
1504
+ function isTerminalPlayRunLifecycleStatus(status) {
1505
+ return TERMINAL_PLAY_RUN_STATUSES.has(normalizePlayRunLifecycleStatus(status));
1506
+ }
1507
+
1508
+ // ../shared_libs/play-runtime/run-snapshot-stream.ts
1509
+ function normalizePlayRunLiveStatus(value) {
1510
+ return normalizePlayRunLifecycleStatus(value);
1511
+ }
1494
1512
  function isTerminalPlayRunLiveStatus(status) {
1495
- return status === "completed" || status === "failed" || status === "cancelled" || status === "terminated" || status === "timed_out";
1513
+ return isTerminalPlayRunLifecycleStatus(status);
1496
1514
  }
1497
1515
  function isRecord2(value) {
1498
1516
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -2021,14 +2039,14 @@ async function* observeRunEvents(options) {
2021
2039
  try {
2022
2040
  for (; ; ) {
2023
2041
  if (queue.length === 0) {
2024
- const waitForItem = new Promise((resolve13) => {
2025
- wake = resolve13;
2042
+ const waitForItem = new Promise((resolve14) => {
2043
+ wake = resolve14;
2026
2044
  });
2027
2045
  if (!sawFirstSnapshot) {
2028
2046
  const timedOut = await Promise.race([
2029
2047
  waitForItem.then(() => false),
2030
2048
  new Promise(
2031
- (resolve13) => setTimeout(() => resolve13(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
2049
+ (resolve14) => setTimeout(() => resolve14(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
2032
2050
  )
2033
2051
  ]);
2034
2052
  if (timedOut && queue.length === 0) {
@@ -2129,7 +2147,7 @@ var REGISTER_PLAY_ARTIFACTS_COMPILE_CONCURRENCY = 3;
2129
2147
  var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_COUNT = 3;
2130
2148
  var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_BYTES = 25e5;
2131
2149
  function sleep2(ms) {
2132
- return new Promise((resolve13) => setTimeout(resolve13, ms));
2150
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
2133
2151
  }
2134
2152
  function isTransientCompileManifestError(error) {
2135
2153
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -4795,7 +4813,7 @@ function buildCandidateUrls2(url) {
4795
4813
  }
4796
4814
  }
4797
4815
  function sleep4(ms) {
4798
- return new Promise((resolve13) => setTimeout(resolve13, ms));
4816
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
4799
4817
  }
4800
4818
  function printDeeplineLogo() {
4801
4819
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -6214,6 +6232,13 @@ Examples:
6214
6232
  ).requiredOption("--code <code>", "Code to redeem").option("--no-open", "Do not open a browser").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(({ code, ...options }) => handleRedeemCode(code, options));
6215
6233
  }
6216
6234
 
6235
+ // src/cli/commands/csv.ts
6236
+ var import_node_child_process = require("child_process");
6237
+ var import_node_crypto2 = require("crypto");
6238
+ var import_node_fs7 = require("fs");
6239
+ var import_node_os7 = require("os");
6240
+ var import_node_path8 = require("path");
6241
+
6217
6242
  // src/cli/dataset-stats.ts
6218
6243
  var import_node_fs6 = require("fs");
6219
6244
  var import_node_path7 = require("path");
@@ -6553,6 +6578,7 @@ function collectCanonicalRowsInfos(statusOrResult) {
6553
6578
  total: totalFromMetadata,
6554
6579
  output: candidates
6555
6580
  });
6581
+ candidates.push(...collectPackagedStepDatasetCandidates(statusOrResult));
6556
6582
  const seen = /* @__PURE__ */ new Set();
6557
6583
  const infos = [];
6558
6584
  for (const candidate of candidates) {
@@ -6931,6 +6957,311 @@ async function handleCsvShow(options) {
6931
6957
  `
6932
6958
  );
6933
6959
  }
6960
+ function csvRenderStatePath() {
6961
+ return (0, import_node_path8.join)((0, import_node_os7.homedir)(), ".local", "deepline", "runtime", "csv-render.json");
6962
+ }
6963
+ function csvRenderLogPath() {
6964
+ return (0, import_node_path8.join)((0, import_node_os7.homedir)(), ".local", "deepline", "runtime", "csv-render.log");
6965
+ }
6966
+ function ensureCsvRenderStateDir() {
6967
+ (0, import_node_fs7.mkdirSync)((0, import_node_path8.join)((0, import_node_os7.homedir)(), ".local", "deepline", "runtime"), {
6968
+ recursive: true
6969
+ });
6970
+ }
6971
+ function readCsvRenderState() {
6972
+ try {
6973
+ const parsed = JSON.parse((0, import_node_fs7.readFileSync)(csvRenderStatePath(), "utf8"));
6974
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
6975
+ } catch {
6976
+ return {};
6977
+ }
6978
+ }
6979
+ function writeCsvRenderState(state) {
6980
+ ensureCsvRenderStateDir();
6981
+ (0, import_node_fs7.writeFileSync)(csvRenderStatePath(), `${JSON.stringify(state, null, 2)}
6982
+ `);
6983
+ }
6984
+ function parseCsvRenderPort(raw) {
6985
+ const value = Number.parseInt(String(raw ?? "4174").replace(/^:/, ""), 10);
6986
+ if (!Number.isInteger(value) || value <= 0 || value > 65535) {
6987
+ throw new Error(`Invalid --port value: ${raw ?? ""}`);
6988
+ }
6989
+ return value;
6990
+ }
6991
+ function processAlive(pid) {
6992
+ if (!Number.isInteger(pid) || pid <= 0) {
6993
+ return false;
6994
+ }
6995
+ try {
6996
+ process.kill(pid, 0);
6997
+ return true;
6998
+ } catch {
6999
+ return false;
7000
+ }
7001
+ }
7002
+ function isOwnedCsvRenderHealth(health, state) {
7003
+ return Boolean(health?.ok) && Number.isInteger(state.pid) && health?.pid === state.pid && Boolean(state.token) && health?.token === state.token;
7004
+ }
7005
+ async function fetchCsvRenderHealth(url) {
7006
+ try {
7007
+ const response = await fetch(`${url}/health`);
7008
+ if (!response.ok) {
7009
+ return null;
7010
+ }
7011
+ const parsed = await response.json();
7012
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
7013
+ } catch {
7014
+ return null;
7015
+ }
7016
+ }
7017
+ async function waitForRenderHealth(url, state) {
7018
+ const deadline = Date.now() + 5e3;
7019
+ while (Date.now() < deadline) {
7020
+ if (isOwnedCsvRenderHealth(await fetchCsvRenderHealth(url), state)) {
7021
+ return true;
7022
+ }
7023
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 100));
7024
+ }
7025
+ return false;
7026
+ }
7027
+ async function waitForRenderStopped(url) {
7028
+ const deadline = Date.now() + 2e3;
7029
+ while (Date.now() < deadline) {
7030
+ try {
7031
+ await fetch(`${url}/health`);
7032
+ } catch {
7033
+ return;
7034
+ }
7035
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 100));
7036
+ }
7037
+ }
7038
+ var CSV_RENDER_SERVER_SOURCE = String.raw`
7039
+ const http = require('node:http');
7040
+ const fs = require('node:fs');
7041
+ const path = require('node:path');
7042
+
7043
+ const port = Number.parseInt(process.env.DEEPLINE_CSV_RENDER_PORT || '4174', 10);
7044
+ const csvPath = process.env.DEEPLINE_CSV_RENDER_CSV || '';
7045
+ const token = process.env.DEEPLINE_CSV_RENDER_TOKEN || '';
7046
+
7047
+ function send(res, status, contentType, body) {
7048
+ res.writeHead(status, {
7049
+ 'content-type': contentType,
7050
+ 'cache-control': 'no-store',
7051
+ });
7052
+ res.end(body);
7053
+ }
7054
+
7055
+ function readCsvText() {
7056
+ if (!csvPath) return '';
7057
+ try {
7058
+ return fs.readFileSync(csvPath, 'utf8');
7059
+ } catch (error) {
7060
+ return 'Unable to read CSV: ' + (error && error.message ? error.message : String(error));
7061
+ }
7062
+ }
7063
+
7064
+ const server = http.createServer((req, res) => {
7065
+ const url = new URL(req.url || '/', 'http://127.0.0.1:' + port);
7066
+ if (url.pathname === '/health') {
7067
+ send(res, 200, 'application/json', JSON.stringify({ ok: true, pid: process.pid, csvPath, token }));
7068
+ return;
7069
+ }
7070
+ if (url.pathname === '/csv.txt') {
7071
+ send(res, 200, 'text/plain; charset=utf-8', readCsvText());
7072
+ return;
7073
+ }
7074
+ if (url.pathname === '/csv.json') {
7075
+ send(res, 200, 'application/json', JSON.stringify({ csvPath, text: readCsvText() }));
7076
+ return;
7077
+ }
7078
+ const title = csvPath ? path.basename(csvPath) : 'CSV renderer';
7079
+ const escapedTitle = title.replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[ch]));
7080
+ const escapedCsv = readCsvText().replace(/[&<>]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[ch]));
7081
+ send(res, 200, 'text/html; charset=utf-8', '<!doctype html><html><head><meta charset="utf-8"><title>' + escapedTitle + '</title><style>body{font:14px system-ui,sans-serif;margin:24px}pre{white-space:pre-wrap;border:1px solid #ddd;padding:16px;border-radius:8px}</style></head><body><h1>' + escapedTitle + '</h1><pre>' + escapedCsv + '</pre></body></html>');
7082
+ });
7083
+
7084
+ server.listen(port, '127.0.0.1');
7085
+ process.on('SIGTERM', () => server.close(() => process.exit(0)));
7086
+ process.on('SIGINT', () => server.close(() => process.exit(0)));
7087
+ `;
7088
+ async function openBrowser(url) {
7089
+ const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
7090
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
7091
+ const child = (0, import_node_child_process.spawn)(opener, args, { detached: true, stdio: "ignore" });
7092
+ child.on("error", () => {
7093
+ });
7094
+ child.unref();
7095
+ }
7096
+ async function handleCsvRenderStart(options) {
7097
+ const port = parseCsvRenderPort(options.port);
7098
+ const csvPath = options.csv ? (0, import_node_path8.resolve)(options.csv) : "";
7099
+ if (csvPath && !(0, import_node_fs7.existsSync)(csvPath)) {
7100
+ throw new Error(`CSV not found: ${csvPath}`);
7101
+ }
7102
+ const url = `http://127.0.0.1:${port}`;
7103
+ const existing = readCsvRenderState();
7104
+ if (processAlive(existing.pid) && existing.url) {
7105
+ const existingOwned = isOwnedCsvRenderHealth(
7106
+ await fetchCsvRenderHealth(existing.url),
7107
+ existing
7108
+ );
7109
+ const sameUrl = existing.url === url;
7110
+ const sameCsv = !csvPath || existing.csvPath === csvPath;
7111
+ if (existingOwned && (!sameUrl || !sameCsv)) {
7112
+ try {
7113
+ process.kill(existing.pid, "SIGTERM");
7114
+ } catch {
7115
+ }
7116
+ await waitForRenderStopped(existing.url);
7117
+ if (processAlive(existing.pid)) {
7118
+ try {
7119
+ process.kill(existing.pid, "SIGKILL");
7120
+ } catch {
7121
+ }
7122
+ }
7123
+ (0, import_node_fs7.rmSync)(csvRenderStatePath(), { force: true });
7124
+ } else if (existingOwned) {
7125
+ process.stdout.write(
7126
+ "Playground render is already running; reusing current process.\n"
7127
+ );
7128
+ process.stdout.write(`Render URL: ${existing.url}
7129
+ `);
7130
+ if (options.open) {
7131
+ await openBrowser(existing.url);
7132
+ }
7133
+ return;
7134
+ } else {
7135
+ (0, import_node_fs7.rmSync)(csvRenderStatePath(), { force: true });
7136
+ }
7137
+ }
7138
+ ensureCsvRenderStateDir();
7139
+ const logPath = csvRenderLogPath();
7140
+ const token = (0, import_node_crypto2.randomUUID)();
7141
+ const child = (0, import_node_child_process.spawn)(process.execPath, ["-e", CSV_RENDER_SERVER_SOURCE], {
7142
+ detached: true,
7143
+ stdio: ["ignore", "ignore", "ignore"],
7144
+ env: {
7145
+ ...process.env,
7146
+ DEEPLINE_CSV_RENDER_PORT: String(port),
7147
+ DEEPLINE_CSV_RENDER_CSV: csvPath,
7148
+ DEEPLINE_CSV_RENDER_TOKEN: token
7149
+ }
7150
+ });
7151
+ child.unref();
7152
+ const state = {
7153
+ pid: child.pid ?? null,
7154
+ port,
7155
+ url,
7156
+ csvPath,
7157
+ logPath,
7158
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
7159
+ token
7160
+ };
7161
+ const started = await waitForRenderHealth(url, state);
7162
+ if (!started) {
7163
+ if (processAlive(child.pid)) {
7164
+ process.kill(child.pid, "SIGTERM");
7165
+ }
7166
+ throw new Error(`Timed out waiting for CSV render to start at ${url}.`);
7167
+ }
7168
+ writeCsvRenderState(state);
7169
+ (0, import_node_fs7.writeFileSync)(
7170
+ logPath,
7171
+ `CSV render started at ${state.startedAt} on ${url}
7172
+ `
7173
+ );
7174
+ process.stdout.write("Playground render is running.\n");
7175
+ process.stdout.write(`Render PID: ${child.pid}
7176
+ `);
7177
+ process.stdout.write(`Render URL: ${url}
7178
+ `);
7179
+ if (options.open) {
7180
+ await openBrowser(url);
7181
+ }
7182
+ }
7183
+ async function handleCsvRenderStatus(options) {
7184
+ const state = readCsvRenderState();
7185
+ const processExists = processAlive(state.pid);
7186
+ const url = state.url ?? "";
7187
+ let health = "unknown";
7188
+ let owned = false;
7189
+ if (processExists && url) {
7190
+ const renderHealth = await fetchCsvRenderHealth(url);
7191
+ owned = isOwnedCsvRenderHealth(renderHealth, state);
7192
+ health = owned ? "healthy" : "unhealthy";
7193
+ }
7194
+ const status = processExists && owned ? "running" : processExists ? "unhealthy" : "stopped";
7195
+ const payload = {
7196
+ status,
7197
+ pid: owned ? state.pid : null,
7198
+ process_alive: owned,
7199
+ url,
7200
+ log_path: state.logPath ?? "",
7201
+ mode: "background",
7202
+ started_at: owned ? state.startedAt ?? "" : "",
7203
+ health_status: health,
7204
+ health_checked_at: (/* @__PURE__ */ new Date()).toISOString(),
7205
+ stale_cleaned: true
7206
+ };
7207
+ const lines = [`Render Status: ${payload.status}`];
7208
+ if (payload.pid) lines.push(`Render PID: ${payload.pid}`);
7209
+ if (payload.url) lines.push(`Render URL: ${payload.url}`);
7210
+ lines.push(`Render Health: ${payload.health_status}`);
7211
+ printCommandEnvelope(payload, {
7212
+ json: options.json,
7213
+ text: `${lines.join("\n")}
7214
+ `
7215
+ });
7216
+ }
7217
+ function terminateRenderProcess(pid) {
7218
+ try {
7219
+ process.kill(pid, "SIGTERM");
7220
+ } catch {
7221
+ return false;
7222
+ }
7223
+ return true;
7224
+ }
7225
+ async function handleCsvRenderStop(options) {
7226
+ const state = readCsvRenderState();
7227
+ const stopped = [];
7228
+ const failed = [];
7229
+ const owned = processAlive(state.pid) && Boolean(state.url) && isOwnedCsvRenderHealth(await fetchCsvRenderHealth(state.url), state);
7230
+ if (owned && processAlive(state.pid)) {
7231
+ if (terminateRenderProcess(state.pid)) {
7232
+ stopped.push(state.pid);
7233
+ } else {
7234
+ failed.push(state.pid);
7235
+ }
7236
+ }
7237
+ (0, import_node_fs7.rmSync)(csvRenderStatePath(), { force: true });
7238
+ const payload = {
7239
+ ok: failed.length === 0,
7240
+ stopped_count: stopped.length,
7241
+ failed_count: failed.length,
7242
+ stopped_pids: stopped,
7243
+ failed_pids: failed
7244
+ };
7245
+ const text = stopped.length > 0 ? `Stopped playground render process(es): ${stopped.join(" ")}
7246
+ ` : "No running playground render process found.\n";
7247
+ printCommandEnvelope(payload, { json: options.json, text });
7248
+ }
7249
+ async function handleCsvRender(action, options) {
7250
+ const normalized = action ?? "start";
7251
+ if (normalized === "start") {
7252
+ await handleCsvRenderStart(options);
7253
+ return;
7254
+ }
7255
+ if (normalized === "status") {
7256
+ await handleCsvRenderStatus(options);
7257
+ return;
7258
+ }
7259
+ if (normalized === "stop") {
7260
+ await handleCsvRenderStop(options);
7261
+ return;
7262
+ }
7263
+ throw new Error(`Unknown csv render action: ${normalized}`);
7264
+ }
6934
7265
  function registerCsvCommands(program) {
6935
7266
  const csv = program.command("csv").description("Inspect local CSV files.").addHelpText(
6936
7267
  "after",
@@ -6957,11 +7288,13 @@ Examples:
6957
7288
  deepline csv show --csv leads.csv --summary
6958
7289
  `
6959
7290
  ).requiredOption("--csv <path>", "Input CSV path").option("--format <format>", "Output format: json, csv, or table", "json").option("--rows <range>", "Row range start:end", "0:19").option("--columns <names>", "Comma-separated column names to include").option("--summary", "Print a summary payload instead of row output").option("--verbose", "Do not truncate long values in table output").action(handleCsvShow);
7291
+ const render = csv.command("render").description("Start, inspect, or stop a local CSV renderer.").argument("[action]", "start, status, or stop", "start").option("--port <port>", "Local renderer port.", "4174").option("--csv <path>", "CSV path to display.").option("--open", "Open the renderer in a browser.").option("--json", "Emit JSON for status/stop.").action(handleCsvRender);
7292
+ render.showHelpAfterError();
6960
7293
  }
6961
7294
 
6962
7295
  // src/cli/commands/db.ts
6963
- var import_node_fs7 = require("fs");
6964
- var import_node_path8 = require("path");
7296
+ var import_node_fs8 = require("fs");
7297
+ var import_node_path9 = require("path");
6965
7298
  var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set(["table", "json", "csv", "markdown"]);
6966
7299
  var CUSTOMER_DB_QUERY_MAX_ROWS = 1e3;
6967
7300
  function parsePositiveInteger(value, flagName) {
@@ -7084,8 +7417,8 @@ function formatDbQueryError(sql, error) {
7084
7417
  return errorMessage(error);
7085
7418
  }
7086
7419
  function writeCustomerDbCsv(result, outPath) {
7087
- const resolved = (0, import_node_path8.resolve)(outPath);
7088
- (0, import_node_fs7.writeFileSync)(
7420
+ const resolved = (0, import_node_path9.resolve)(outPath);
7421
+ (0, import_node_fs8.writeFileSync)(
7089
7422
  resolved,
7090
7423
  dataExportCsvString(customerDbRows(result), customerDbColumnNames(result)),
7091
7424
  "utf-8"
@@ -7197,8 +7530,8 @@ async function handleDbQuery(args) {
7197
7530
  customerDbColumnNames(result)
7198
7531
  );
7199
7532
  if (outPath) {
7200
- const exportedPath = (0, import_node_path8.resolve)(outPath);
7201
- (0, import_node_fs7.writeFileSync)(exportedPath, content, "utf-8");
7533
+ const exportedPath = (0, import_node_path9.resolve)(outPath);
7534
+ (0, import_node_fs8.writeFileSync)(exportedPath, content, "utf-8");
7202
7535
  printCommandEnvelope(
7203
7536
  dbQueryExportEnvelope({
7204
7537
  result,
@@ -7300,18 +7633,18 @@ Examples:
7300
7633
 
7301
7634
  // src/cli/commands/enrich.ts
7302
7635
  var import_promises3 = require("fs/promises");
7303
- var import_node_os7 = require("os");
7304
- var import_node_path11 = require("path");
7636
+ var import_node_os8 = require("os");
7637
+ var import_node_path12 = require("path");
7305
7638
 
7306
7639
  // src/cli/commands/play.ts
7307
- var import_node_crypto2 = require("crypto");
7308
- var import_node_fs9 = require("fs");
7309
- var import_node_path10 = require("path");
7640
+ var import_node_crypto3 = require("crypto");
7641
+ var import_node_fs10 = require("fs");
7642
+ var import_node_path11 = require("path");
7310
7643
  var import_sync5 = require("csv-parse/sync");
7311
7644
 
7312
7645
  // src/cli/commands/plays/bootstrap.ts
7313
- var import_node_fs8 = require("fs");
7314
- var import_node_path9 = require("path");
7646
+ var import_node_fs9 = require("fs");
7647
+ var import_node_path10 = require("path");
7315
7648
  var import_sync4 = require("csv-parse/sync");
7316
7649
 
7317
7650
  // ../shared_libs/plays/bootstrap-routes.ts
@@ -7740,13 +8073,13 @@ function inferCsvColumnSpecs(headers, rows) {
7740
8073
  }));
7741
8074
  }
7742
8075
  function readCsvSample(csvPath) {
7743
- const resolvedPath = (0, import_node_path9.resolve)(csvPath);
7744
- const size = (0, import_node_fs8.statSync)(resolvedPath).size;
7745
- const fd = (0, import_node_fs8.openSync)(resolvedPath, "r");
8076
+ const resolvedPath = (0, import_node_path10.resolve)(csvPath);
8077
+ const size = (0, import_node_fs9.statSync)(resolvedPath).size;
8078
+ const fd = (0, import_node_fs9.openSync)(resolvedPath, "r");
7746
8079
  const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
7747
8080
  const buffer = Buffer.alloc(byteLength);
7748
- const bytesRead = (0, import_node_fs8.readSync)(fd, buffer, 0, byteLength, 0);
7749
- (0, import_node_fs8.closeSync)(fd);
8081
+ const bytesRead = (0, import_node_fs9.readSync)(fd, buffer, 0, byteLength, 0);
8082
+ (0, import_node_fs9.closeSync)(fd);
7750
8083
  if (bytesRead === 0) {
7751
8084
  throw new PlayBootstrapUsageError(`--from csv:${csvPath} is empty.`);
7752
8085
  }
@@ -7815,9 +8148,9 @@ ${properties}
7815
8148
  }
7816
8149
  function packagedCsvPathForPlay(csvPath) {
7817
8150
  const playDir = process.cwd();
7818
- const absoluteCsvPath = (0, import_node_path9.resolve)(csvPath);
7819
- const relativePath = (0, import_node_path9.relative)(playDir, absoluteCsvPath);
7820
- if (relativePath === "" || relativePath.startsWith("..") || (0, import_node_path9.isAbsolute)(relativePath)) {
8151
+ const absoluteCsvPath = (0, import_node_path10.resolve)(csvPath);
8152
+ const relativePath = (0, import_node_path10.relative)(playDir, absoluteCsvPath);
8153
+ if (relativePath === "" || relativePath.startsWith("..") || (0, import_node_path10.isAbsolute)(relativePath)) {
7821
8154
  throw new PlayBootstrapUsageError(
7822
8155
  `--from csv:${csvPath} must point to a file inside the directory where you run plays bootstrap. Run bootstrap from the intended play directory and write the play with --out there.`
7823
8156
  );
@@ -8739,8 +9072,8 @@ async function runPlayBootstrap(args) {
8739
9072
  ...csvContext
8740
9073
  });
8741
9074
  if (options.out) {
8742
- (0, import_node_fs8.writeFileSync)((0, import_node_path9.resolve)(options.out), source, "utf-8");
8743
- process.stdout.write(`Wrote ${(0, import_node_path9.resolve)(options.out)}
9075
+ (0, import_node_fs9.writeFileSync)((0, import_node_path10.resolve)(options.out), source, "utf-8");
9076
+ process.stdout.write(`Wrote ${(0, import_node_path10.resolve)(options.out)}
8744
9077
  `);
8745
9078
  return 0;
8746
9079
  }
@@ -9424,7 +9757,7 @@ function traceCliSync(phase, fields, run) {
9424
9757
  }
9425
9758
  }
9426
9759
  function sleep5(ms) {
9427
- return new Promise((resolve13) => setTimeout(resolve13, ms));
9760
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
9428
9761
  }
9429
9762
  function parseReferencedPlayTarget2(target) {
9430
9763
  const trimmed = target.trim();
@@ -9468,7 +9801,7 @@ function formatPlayListReference(play) {
9468
9801
  return play.reference || play.name;
9469
9802
  }
9470
9803
  function defaultMaterializedPlayPath(reference) {
9471
- return (0, import_node_path10.resolve)(defaultStarterPlayPath(reference));
9804
+ return (0, import_node_path11.resolve)(defaultStarterPlayPath(reference));
9472
9805
  }
9473
9806
  function defaultStarterPlayPath(reference) {
9474
9807
  const playName = parseReferencedPlayTarget2(reference).unqualifiedPlayName;
@@ -9494,15 +9827,15 @@ function materializeRemotePlaySource(input2) {
9494
9827
  return null;
9495
9828
  }
9496
9829
  const outputPath = input2.outPath ?? defaultMaterializedPlayPath(input2.playName);
9497
- if ((0, import_node_fs9.existsSync)(outputPath)) {
9498
- const existingSource = (0, import_node_fs9.readFileSync)(outputPath, "utf-8");
9830
+ if ((0, import_node_fs10.existsSync)(outputPath)) {
9831
+ const existingSource = (0, import_node_fs10.readFileSync)(outputPath, "utf-8");
9499
9832
  if (existingSource === input2.sourceCode) {
9500
9833
  return { path: outputPath, status: "unchanged", created: false };
9501
9834
  }
9502
- (0, import_node_fs9.writeFileSync)(outputPath, input2.sourceCode, "utf-8");
9835
+ (0, import_node_fs10.writeFileSync)(outputPath, input2.sourceCode, "utf-8");
9503
9836
  return { path: outputPath, status: "updated", created: false };
9504
9837
  }
9505
- (0, import_node_fs9.writeFileSync)(outputPath, input2.sourceCode, "utf-8");
9838
+ (0, import_node_fs10.writeFileSync)(outputPath, input2.sourceCode, "utf-8");
9506
9839
  return { path: outputPath, status: "created", created: true };
9507
9840
  }
9508
9841
  function formatLoadedPlayMessage(materializedFile) {
@@ -9547,7 +9880,7 @@ function extractPlayName(code, filePath) {
9547
9880
  throw buildMissingDefinePlayError(filePath);
9548
9881
  }
9549
9882
  function isFileTarget(target) {
9550
- return (0, import_node_fs9.existsSync)((0, import_node_path10.resolve)(target));
9883
+ return (0, import_node_fs10.existsSync)((0, import_node_path11.resolve)(target));
9551
9884
  }
9552
9885
  function looksLikeRunId(target) {
9553
9886
  return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
@@ -9576,7 +9909,7 @@ function parsePositiveInteger3(value, flagName) {
9576
9909
  return parsed;
9577
9910
  }
9578
9911
  function parseJsonInput(raw) {
9579
- const source = raw.startsWith("@") ? (0, import_node_fs9.readFileSync)((0, import_node_path10.resolve)(raw.slice(1)), "utf-8") : raw;
9912
+ const source = raw.startsWith("@") ? (0, import_node_fs10.readFileSync)((0, import_node_path11.resolve)(raw.slice(1)), "utf-8") : raw;
9580
9913
  const parsed = JSON.parse(source);
9581
9914
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
9582
9915
  throw new Error("--input must be a JSON object.");
@@ -9678,7 +10011,7 @@ function fileInputBindingsFromStaticPipeline(staticPipeline) {
9678
10011
  function isLocalFilePathValue(value) {
9679
10012
  if (typeof value !== "string" || !value.trim()) return false;
9680
10013
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
9681
- return (0, import_node_fs9.existsSync)((0, import_node_path10.resolve)(value));
10014
+ return (0, import_node_fs10.existsSync)((0, import_node_path11.resolve)(value));
9682
10015
  }
9683
10016
  function inputContainsLocalFilePath(value) {
9684
10017
  if (isLocalFilePathValue(value)) {
@@ -9725,7 +10058,7 @@ function collectLocalFileInputRefs(value, inputPath, key, out) {
9725
10058
  const looksLikeFile = /\.[a-z0-9]{1,8}$/i.test(trimmed);
9726
10059
  if (keyIsCsvData) {
9727
10060
  out.push({ inputPath, value: trimmed, isCsvData: true });
9728
- } else if (endsWithCsv || looksLikeFile && (0, import_node_fs9.existsSync)((0, import_node_path10.resolve)(trimmed))) {
10061
+ } else if (endsWithCsv || looksLikeFile && (0, import_node_fs10.existsSync)((0, import_node_path11.resolve)(trimmed))) {
9729
10062
  out.push({ inputPath, value: trimmed, isCsvData: false });
9730
10063
  }
9731
10064
  return;
@@ -9767,8 +10100,8 @@ function preflightLocalFileInputs(runtimeInput) {
9767
10100
  collectLocalFileInputRefs(value, key, key, refs);
9768
10101
  }
9769
10102
  for (const ref of refs) {
9770
- const absolutePath = (0, import_node_path10.resolve)(ref.value);
9771
- if (!(0, import_node_fs9.existsSync)(absolutePath)) {
10103
+ const absolutePath = (0, import_node_path11.resolve)(ref.value);
10104
+ if (!(0, import_node_fs10.existsSync)(absolutePath)) {
9772
10105
  throw new DeeplineError(
9773
10106
  `Input ${ref.inputPath} references a local file that does not exist: ${ref.value} (resolved to ${absolutePath}). No run was created.`,
9774
10107
  void 0,
@@ -9778,7 +10111,7 @@ function preflightLocalFileInputs(runtimeInput) {
9778
10111
  }
9779
10112
  let stat2;
9780
10113
  try {
9781
- stat2 = (0, import_node_fs9.statSync)(absolutePath);
10114
+ stat2 = (0, import_node_fs10.statSync)(absolutePath);
9782
10115
  } catch (error) {
9783
10116
  throw new DeeplineError(
9784
10117
  `Input ${ref.inputPath} references a local file that is not readable: ${ref.value} (${error instanceof Error ? error.message : String(error)}). No run was created.`,
@@ -9804,7 +10137,7 @@ function preflightLocalFileInputs(runtimeInput) {
9804
10137
  function preflightCsvDataInput(ref, absolutePath) {
9805
10138
  let content;
9806
10139
  try {
9807
- content = (0, import_node_fs9.readFileSync)(absolutePath, "utf-8");
10140
+ content = (0, import_node_fs10.readFileSync)(absolutePath, "utf-8");
9808
10141
  } catch (error) {
9809
10142
  throw new DeeplineError(
9810
10143
  `Input ${ref.inputPath} CSV ${ref.value} is not readable: ${error instanceof Error ? error.message : String(error)}. No run was created.`,
@@ -9886,8 +10219,8 @@ async function stageFileInputArgs(input2) {
9886
10219
  const localFiles = uniqueBindings.flatMap((binding) => {
9887
10220
  const value = getDottedInputValue(input2.runtimeInput, binding.inputPath);
9888
10221
  if (!isLocalFilePathValue(value)) return [];
9889
- const absolutePath = (0, import_node_path10.resolve)(value);
9890
- return [{ binding, absolutePath, logicalPath: (0, import_node_path10.basename)(absolutePath) }];
10222
+ const absolutePath = (0, import_node_path11.resolve)(value);
10223
+ return [{ binding, absolutePath, logicalPath: (0, import_node_path11.basename)(absolutePath) }];
9891
10224
  });
9892
10225
  if (localFiles.length === 0) {
9893
10226
  return { inputFile: null, packagedFiles: [] };
@@ -9919,20 +10252,20 @@ async function stageFileInputArgs(input2) {
9919
10252
  };
9920
10253
  }
9921
10254
  function stageFile(logicalPath, absolutePath) {
9922
- const buffer = (0, import_node_fs9.readFileSync)(absolutePath);
10255
+ const buffer = (0, import_node_fs10.readFileSync)(absolutePath);
9923
10256
  return {
9924
10257
  logicalPath,
9925
10258
  contentBase64: buffer.toString("base64"),
9926
- contentHash: (0, import_node_crypto2.createHash)("sha256").update(buffer).digest("hex"),
10259
+ contentHash: (0, import_node_crypto3.createHash)("sha256").update(buffer).digest("hex"),
9927
10260
  contentType: absolutePath.toLowerCase().endsWith(".csv") ? "text/csv" : absolutePath.toLowerCase().endsWith(".json") ? "application/json" : "application/octet-stream",
9928
10261
  bytes: buffer.byteLength
9929
10262
  };
9930
10263
  }
9931
10264
  function normalizePlayPath(filePath) {
9932
10265
  try {
9933
- return import_node_fs9.realpathSync.native((0, import_node_path10.resolve)(filePath));
10266
+ return import_node_fs10.realpathSync.native((0, import_node_path11.resolve)(filePath));
9934
10267
  } catch {
9935
- return (0, import_node_path10.resolve)(filePath);
10268
+ return (0, import_node_path11.resolve)(filePath);
9936
10269
  }
9937
10270
  }
9938
10271
  function formatBundlingErrors(filePath, errors) {
@@ -11999,7 +12332,7 @@ function shellSingleQuote(value) {
11999
12332
  return `'${value.replace(/'/g, `'\\''`)}'`;
12000
12333
  }
12001
12334
  function runExportRetryCommand(runId, outPath, datasetPath) {
12002
- return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote((0, import_node_path10.resolve)(outPath))}`;
12335
+ return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote((0, import_node_path11.resolve)(outPath))}`;
12003
12336
  }
12004
12337
  function extractRunPlayName(status) {
12005
12338
  const run = status.run;
@@ -12804,7 +13137,7 @@ async function handlePlayCheck(args) {
12804
13137
  }
12805
13138
  return 0;
12806
13139
  } catch (error) {
12807
- const resolved = (0, import_node_path10.resolve)(options.target);
13140
+ const resolved = (0, import_node_path11.resolve)(options.target);
12808
13141
  const message = error instanceof Error && error.message ? error.message : `File not found: ${resolved}`;
12809
13142
  if (options.jsonOutput) {
12810
13143
  process.stdout.write(
@@ -12821,8 +13154,8 @@ async function handlePlayCheck(args) {
12821
13154
  return 1;
12822
13155
  }
12823
13156
  }
12824
- const absolutePlayPath = (0, import_node_path10.resolve)(options.target);
12825
- const sourceCode = (0, import_node_fs9.readFileSync)(absolutePlayPath, "utf-8");
13157
+ const absolutePlayPath = (0, import_node_path11.resolve)(options.target);
13158
+ const sourceCode = (0, import_node_fs10.readFileSync)(absolutePlayPath, "utf-8");
12826
13159
  let graph;
12827
13160
  try {
12828
13161
  graph = await collectBundledPlayGraph(absolutePlayPath);
@@ -12922,12 +13255,12 @@ async function handleFileBackedRun(options) {
12922
13255
  }
12923
13256
  const client2 = new DeeplineClient();
12924
13257
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
12925
- const absolutePlayPath = (0, import_node_path10.resolve)(options.target.path);
13258
+ const absolutePlayPath = (0, import_node_path11.resolve)(options.target.path);
12926
13259
  progress.phase("compiling play");
12927
13260
  const sourceCode = traceCliSync(
12928
13261
  "cli.play_file_read_source",
12929
13262
  { targetKind: "file" },
12930
- () => (0, import_node_fs9.readFileSync)(absolutePlayPath, "utf-8")
13263
+ () => (0, import_node_fs10.readFileSync)(absolutePlayPath, "utf-8")
12931
13264
  );
12932
13265
  const runtimeInput = options.input ? { ...options.input } : {};
12933
13266
  try {
@@ -13248,19 +13581,19 @@ async function handlePlayRun(args) {
13248
13581
  if (isFileTarget(options.target.path)) {
13249
13582
  return handleFileBackedRun(options);
13250
13583
  }
13251
- const resolved = (0, import_node_path10.resolve)(options.target.path);
13584
+ const resolved = (0, import_node_path11.resolve)(options.target.path);
13252
13585
  console.error(`File not found: ${resolved}`);
13253
- const dir = (0, import_node_path10.dirname)(resolved);
13254
- if ((0, import_node_fs9.existsSync)(dir)) {
13255
- const base = (0, import_node_path10.basename)(resolved);
13586
+ const dir = (0, import_node_path11.dirname)(resolved);
13587
+ if ((0, import_node_fs10.existsSync)(dir)) {
13588
+ const base = (0, import_node_path11.basename)(resolved);
13256
13589
  try {
13257
- const siblings = (0, import_node_fs9.readdirSync)(dir).filter(
13590
+ const siblings = (0, import_node_fs10.readdirSync)(dir).filter(
13258
13591
  (f) => f.includes(base.replace(/\.(play\.)?ts$/, "")) || f.endsWith(".play.ts")
13259
13592
  );
13260
13593
  if (siblings.length > 0) {
13261
13594
  console.error(`Did you mean one of these?`);
13262
13595
  for (const s of siblings.slice(0, 5)) {
13263
- console.error(` ${(0, import_node_path10.join)(dir, s)}`);
13596
+ console.error(` ${(0, import_node_path11.join)(dir, s)}`);
13264
13597
  }
13265
13598
  }
13266
13599
  } catch {
@@ -13419,14 +13752,14 @@ async function handleRunLogs(args) {
13419
13752
  continue;
13420
13753
  }
13421
13754
  if (arg === "--out" && args[index + 1]) {
13422
- outPath = (0, import_node_path10.resolve)(args[++index]);
13755
+ outPath = (0, import_node_path11.resolve)(args[++index]);
13423
13756
  }
13424
13757
  }
13425
13758
  const client2 = new DeeplineClient();
13426
13759
  if (outPath) {
13427
13760
  const result2 = await client2.runs.logs(runId, { all: true });
13428
13761
  const logs = result2.entries;
13429
- (0, import_node_fs9.writeFileSync)(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
13762
+ (0, import_node_fs10.writeFileSync)(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
13430
13763
  printCommandEnvelope(
13431
13764
  {
13432
13765
  runId: result2.runId,
@@ -13576,7 +13909,7 @@ async function handleRunExport(args) {
13576
13909
  for (let index = 0; index < args.length; index += 1) {
13577
13910
  const arg = args[index];
13578
13911
  if (arg === "--out" && args[index + 1]) {
13579
- outPath = (0, import_node_path10.resolve)(args[++index]);
13912
+ outPath = (0, import_node_path11.resolve)(args[++index]);
13580
13913
  continue;
13581
13914
  }
13582
13915
  if (arg === "--dataset" && args[index + 1]) {
@@ -13584,7 +13917,7 @@ async function handleRunExport(args) {
13584
13917
  continue;
13585
13918
  }
13586
13919
  if (arg === "--metadata-out" && args[index + 1]) {
13587
- metadataOutPath = (0, import_node_path10.resolve)(args[++index]);
13920
+ metadataOutPath = (0, import_node_path11.resolve)(args[++index]);
13588
13921
  }
13589
13922
  }
13590
13923
  if (!outPath) {
@@ -13624,7 +13957,7 @@ async function handleRunExport(args) {
13624
13957
  }
13625
13958
  };
13626
13959
  if (metadataOutPath) {
13627
- (0, import_node_fs9.writeFileSync)(
13960
+ (0, import_node_fs10.writeFileSync)(
13628
13961
  metadataOutPath,
13629
13962
  `${JSON.stringify(payload, null, 2)}
13630
13963
  `,
@@ -13656,10 +13989,10 @@ async function handlePlayGet(args) {
13656
13989
  for (let index = 1; index < args.length; index += 1) {
13657
13990
  const arg = args[index];
13658
13991
  if (arg === "--out" && args[index + 1]) {
13659
- outPath = (0, import_node_path10.resolve)(args[++index]);
13992
+ outPath = (0, import_node_path11.resolve)(args[++index]);
13660
13993
  }
13661
13994
  }
13662
- const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs9.readFileSync)((0, import_node_path10.resolve)(target), "utf-8"), (0, import_node_path10.resolve)(target)) : parseReferencedPlayTarget2(target).playName;
13995
+ const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs10.readFileSync)((0, import_node_path11.resolve)(target), "utf-8"), (0, import_node_path11.resolve)(target)) : parseReferencedPlayTarget2(target).playName;
13663
13996
  const detail = isFileTarget(target) ? await client2.getPlay(playName) : await assertCanonicalNamedPlayReference(client2, target);
13664
13997
  const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
13665
13998
  const materializedFile = outPath ? materializeRemotePlaySource({
@@ -14108,7 +14441,7 @@ async function handlePlayDescribe(args) {
14108
14441
  const definedName = isFileTarget(playName) ? (() => {
14109
14442
  try {
14110
14443
  return extractPlayName(
14111
- (0, import_node_fs9.readFileSync)((0, import_node_path10.resolve)(playName), "utf-8"),
14444
+ (0, import_node_fs10.readFileSync)((0, import_node_path11.resolve)(playName), "utf-8"),
14112
14445
  playName
14113
14446
  );
14114
14447
  } catch {
@@ -14189,7 +14522,7 @@ async function handlePlayPublish(args) {
14189
14522
  graph = await traceCliSpan(
14190
14523
  "cli.play_publish_bundle_graph",
14191
14524
  { targetKind: "file" },
14192
- () => collectBundledPlayGraph((0, import_node_path10.resolve)(playName))
14525
+ () => collectBundledPlayGraph((0, import_node_path11.resolve)(playName))
14193
14526
  );
14194
14527
  assertBundledPlayGraphDescriptions(graph);
14195
14528
  await traceCliSpan(
@@ -14378,12 +14711,15 @@ Idempotent execution:
14378
14711
  }))
14379
14712
  .run({ key: 'domain' });
14380
14713
 
14381
- Reuse needs the same play, tool id, dataset name, row key, and compatible logic.
14382
- To recompute a visible cell on a later cron/user run after a window, put
14383
- staleAfterSeconds on the cell-producing column:
14714
+ Reuse needs the same play, call id, semantic input, auth scope, and cache
14715
+ policy. Dataset cells are storage; put freshness on the actual call:
14384
14716
 
14385
- .withColumn('cto', resolver, { staleAfterSeconds: 86400 })
14386
- .run({ key: 'domain' })
14717
+ await ctx.tools.execute({
14718
+ id: 'find_cto',
14719
+ tool: 'dropleads_search_people',
14720
+ input: { filters: { companyDomains: [row.domain], jobTitles: ['CTO'] }, pagination: { page: 1, limit: 1 } },
14721
+ staleAfterSeconds: 86400,
14722
+ });
14387
14723
 
14388
14724
  Examples:
14389
14725
  deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
@@ -15240,12 +15576,10 @@ function getterFromLegacyExtractJs(extractJs, fallbackAlias) {
15240
15576
  // src/cli/enrich-compat-adapter.ts
15241
15577
  var ENRICH_COMPAT_DEFAULT_PLAY_NAME = "deepline-enrich-v1-compat";
15242
15578
  var ENRICH_COMPAT_DEFAULT_MAP_NAME = "deepline_enrich_rows";
15243
- var ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE = "{ recompute: true }";
15244
15579
  function buildEnrichCompatibilityPlan(options = {}) {
15245
15580
  return {
15246
15581
  playName: options.playName?.trim() || ENRICH_COMPAT_DEFAULT_PLAY_NAME,
15247
- mapName: options.mapName?.trim() || ENRICH_COMPAT_DEFAULT_MAP_NAME,
15248
- metadataCellPolicySource: ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE
15582
+ mapName: options.mapName?.trim() || ENRICH_COMPAT_DEFAULT_MAP_NAME
15249
15583
  };
15250
15584
  }
15251
15585
 
@@ -15327,7 +15661,7 @@ function renderExecuteStep(command, options = {
15327
15661
  if (command.play) {
15328
15662
  return renderPlayStep(command, options);
15329
15663
  }
15330
- if (command.tool === "run_javascript" && options.inlineRunJavascript) {
15664
+ if (command.tool === "run_javascript" && options.inlineRunJavascript && canInlineRunJavascript(command)) {
15331
15665
  return renderInlineJavascriptStep(command, options);
15332
15666
  }
15333
15667
  if (options.idiomaticGetters) {
@@ -15337,9 +15671,7 @@ function renderExecuteStep(command, options = {
15337
15671
  const callId = stringLiteral(commandCallId(command));
15338
15672
  const tool = stringLiteral(command.tool);
15339
15673
  const payload = stableJson(command.payload ?? {});
15340
- const extractJs = command.extract_js ? `({ row, result, data, raw, pick, extract, extractList, target, get }) => { const input = row; const context = row;
15341
- ${indent(renderJavascriptBody(command.extract_js), 6)}
15342
- }` : "null";
15674
+ const extractJs = renderExtractFunction(command, 6);
15343
15675
  const runIfJs = options.nativeRunIf ? "null" : renderRunIfFunction(command) ?? "null";
15344
15676
  const description = command.description ? `,
15345
15677
  description: ${stringLiteral(command.description)}` : "";
@@ -15365,6 +15697,23 @@ ${indent(renderJavascriptBody(command.extract_js), 6)}
15365
15697
  `}`
15366
15698
  ].join("\n");
15367
15699
  }
15700
+ function canInlineRunJavascript(command) {
15701
+ const code = typeof command.payload?.code === "string" ? command.payload.code : "";
15702
+ if (/\btriggerWorkflow\b/.test(code)) {
15703
+ return false;
15704
+ }
15705
+ try {
15706
+ assertUserCodeIsSafe(code, `run_javascript step "${command.alias}"`);
15707
+ } catch {
15708
+ return false;
15709
+ }
15710
+ return true;
15711
+ }
15712
+ function renderExtractFunction(command, indentSpaces) {
15713
+ return command.extract_js ? `({ row, result, data, raw, pick, extract, extractList, target, get }) => { const input = row; const context = row;
15714
+ ${indent(renderJavascriptBody(command.extract_js), indentSpaces)}
15715
+ }` : "null";
15716
+ }
15368
15717
  function renderRunIfFunction(command) {
15369
15718
  return command.run_if_js ? `(row) => { const input = row; const context = row;
15370
15719
  ${indent(renderJavascriptBody(command.run_if_js), 6)}
@@ -15452,6 +15801,11 @@ function renderPlayStep(command, options) {
15452
15801
  ].join("\n");
15453
15802
  }
15454
15803
  function renderInlineJavascriptStep(command, options) {
15804
+ const alias = stringLiteral(command.alias);
15805
+ const extractJs = renderExtractFunction(command, 4);
15806
+ const legacyEnvelope = options.legacyEnvelope ? "true" : "false";
15807
+ const resultExpression = command.extract_js ? `__dlExtract(${alias}, result, row as Record<string, unknown>, ${extractJs}, ${legacyEnvelope})` : "result";
15808
+ const payload = stableJson(command.payload ?? {});
15455
15809
  const code = typeof command.payload?.code === "string" ? command.payload.code : "return null;";
15456
15810
  const runIfLines = command.run_if_js && !options.nativeRunIf ? [
15457
15811
  ` if (!((row: Record<string, any>) => { const input = row; const context = row;`,
@@ -15462,9 +15816,23 @@ function renderInlineJavascriptStep(command, options) {
15462
15816
  `async (row) => {`,
15463
15817
  ...options.precheck ? [` if (${options.precheck}) return null;`] : [],
15464
15818
  ...runIfLines,
15465
- ` return ((row: Record<string, any>, input: Record<string, any>, context: Record<string, any>) => {`,
15819
+ ...options.waterfallSoftFail ? [` try {`] : [],
15820
+ `${options.waterfallSoftFail ? " " : " "}const __dlPayload = __dlRuntimePayload('run_javascript', __dlTemplate(${payload}, row as Record<string, unknown>) as Record<string, unknown>, row as Record<string, unknown>);`,
15821
+ `${options.waterfallSoftFail ? " " : " "}const rawResult = ((row: Record<string, any>, input: Record<string, any>, context: Record<string, any>) => {`,
15822
+ `${options.waterfallSoftFail ? " " : " "} const payload = __dlPayload as Record<string, any>;`,
15823
+ `${options.waterfallSoftFail ? " " : " "} const extract = __dlInlineExtract;`,
15824
+ `${options.waterfallSoftFail ? " " : " "} const extractList = __dlInlineExtractList;`,
15825
+ `${options.waterfallSoftFail ? " " : " "} return (() => {`,
15466
15826
  indent(renderJavascriptBody(code), 4),
15467
- ` })(row as Record<string, any>, row as Record<string, any>, row as Record<string, any>);`,
15827
+ `${options.waterfallSoftFail ? " " : " "} })();`,
15828
+ `${options.waterfallSoftFail ? " " : " "}})(row as Record<string, any>, row as Record<string, any>, row as Record<string, any>);`,
15829
+ `${options.waterfallSoftFail ? " " : " "}const result = await Promise.resolve(rawResult);`,
15830
+ `${options.waterfallSoftFail ? " " : " "}return ${resultExpression};`,
15831
+ ...options.waterfallSoftFail ? [
15832
+ ` } catch (error) {`,
15833
+ ` return __dlExtractorFailure(error);`,
15834
+ ` }`
15835
+ ] : [],
15468
15836
  `}`
15469
15837
  ].join("\n");
15470
15838
  }
@@ -15474,18 +15842,16 @@ function renderJavascriptBody(source) {
15474
15842
  if (/^(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/.test(trimmed)) {
15475
15843
  return `return (${trimmed});`;
15476
15844
  }
15477
- if (trimmed && !trimmed.includes("\n") && !trimmed.includes(";") && !/\breturn\b/.test(trimmed)) {
15845
+ if (trimmed && !trimmed.includes("\n") && !trimmed.includes(";") && !/\breturn\b/.test(trimmed) && !/^(?:throw|if|for|while|switch|try|catch|const|let|var|class|function)\b/.test(
15846
+ trimmed
15847
+ )) {
15478
15848
  return `return (${trimmed});`;
15479
15849
  }
15480
15850
  return source;
15481
15851
  }
15482
15852
  function renderColumnStep(alias, resolverSource, options = {}) {
15483
15853
  const resolver = indent(resolverSource, 8);
15484
- const optionFields = [
15485
- ...options.recompute === true ? ["recompute: true"] : [],
15486
- ...options.recomputeOnError === true ? ["recomputeOnError: true"] : [],
15487
- ...options.runIfSource ? [`runIf: ${options.runIfSource}`] : []
15488
- ];
15854
+ const optionFields = options.runIfSource ? [`runIf: ${options.runIfSource}`] : [];
15489
15855
  const optionSource = optionFields.length > 0 ? `{ ${optionFields.join(", ")} }` : null;
15490
15856
  return [
15491
15857
  ` .withColumn(${stringLiteral(alias)},`,
@@ -15562,7 +15928,7 @@ function collectGeneratedAliases(commands) {
15562
15928
  }
15563
15929
  return aliases;
15564
15930
  }
15565
- function renderMetadataColumnStep(config, policySource) {
15931
+ function renderMetadataColumnStep(config) {
15566
15932
  const columns = collectMetadataColumns(config.commands);
15567
15933
  if (Object.keys(columns).length === 0) {
15568
15934
  return "";
@@ -15570,7 +15936,6 @@ function renderMetadataColumnStep(config, policySource) {
15570
15936
  return [
15571
15937
  ` .withColumn('_metadata',`,
15572
15938
  ` (row) => __dlMergeMetadata(__dlMetadataFromRow(row), ${stableJson({ columns })}),`,
15573
- ` ${policySource},`,
15574
15939
  ` )`
15575
15940
  ].join("\n");
15576
15941
  }
@@ -15605,16 +15970,11 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15605
15970
  nativeRunIf: Boolean(runIfSource)
15606
15971
  }),
15607
15972
  {
15608
- recompute: force,
15609
- recomputeOnError: true,
15610
15973
  runIfSource
15611
15974
  }
15612
15975
  );
15613
15976
  }).filter((line) => line !== null);
15614
15977
  const aliases = activeChildren.map((nested) => nested.alias);
15615
- const forceParent = forceAliases.has(normalizeAlias(command.with_waterfall)) || activeChildren.some(
15616
- (nested) => forceAliases.has(normalizeAlias(nested.alias))
15617
- );
15618
15978
  const returnExpr = typeof command.min_results === "number" ? `__dlFirstMinResults(row, ${stableJson(aliases)}, ${Math.max(
15619
15979
  1,
15620
15980
  Math.trunc(command.min_results)
@@ -15624,13 +15984,10 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15624
15984
  }
15625
15985
  return [
15626
15986
  ...columnSteps,
15627
- renderColumnStep(command.with_waterfall, `(row) => ${returnExpr}`, {
15628
- recompute: forceParent
15629
- }),
15987
+ renderColumnStep(command.with_waterfall, `(row) => ${returnExpr}`),
15630
15988
  renderColumnStep(
15631
15989
  `${command.with_waterfall}_source`,
15632
- typeof command.min_results === "number" ? `(row) => __dlContributingAliases(row, ${stableJson(aliases)})` : `(row) => __dlFirstMeaningfulAlias(row, ${stableJson(aliases)})`,
15633
- { recompute: forceParent }
15990
+ typeof command.min_results === "number" ? `(row) => __dlContributingAliases(row, ${stableJson(aliases)})` : `(row) => __dlFirstMeaningfulAlias(row, ${stableJson(aliases)})`
15634
15991
  )
15635
15992
  ];
15636
15993
  }
@@ -15670,19 +16027,15 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15670
16027
  nativeRunIf: Boolean(runIfSource)
15671
16028
  }),
15672
16029
  {
15673
- recompute: force,
15674
- recomputeOnError: true,
15675
16030
  runIfSource
15676
16031
  }
15677
16032
  )
15678
16033
  );
15679
16034
  });
15680
16035
  const columnStepSource = columnSteps.length > 0 ? columnSteps.join("\n") : ` .withColumn('noop', () => null)`;
15681
- const metadataColumnSource = renderMetadataColumnStep(
15682
- config,
15683
- compatibility.metadataCellPolicySource
15684
- );
16036
+ const metadataColumnSource = renderMetadataColumnStep(config);
15685
16037
  const generatedAliases = collectGeneratedAliases(config.commands);
16038
+ const runOptionsSource = options.failFast ? `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart), onRowError: 'fail' as const }` : `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart) }`;
15686
16039
  const body = [
15687
16040
  `export default definePlay(${stringLiteral(playName)}, async (ctx, input: EnrichInput) => {`,
15688
16041
  ` const sourceRows = await ctx.csv<Record<string, unknown>>(input.file);`,
@@ -15693,7 +16046,7 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15693
16046
  ` for await (const row of sourceRows) {`,
15694
16047
  ` if (rowEndExclusive !== undefined && sourceRowIndex >= rowEndExclusive) break;`,
15695
16048
  ` if (sourceRowIndex >= rowStart) {`,
15696
- ` rows.push(__dlPrepareEnrichRow(row, ${stableJson(generatedAliases)}));`,
16049
+ ` rows.push(__dlPrepareEnrichRow(row, ${stableJson(generatedAliases)}, sourceRowIndex));`,
15697
16050
  ` }`,
15698
16051
  ` sourceRowIndex += 1;`,
15699
16052
  ` }`,
@@ -15701,7 +16054,7 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15701
16054
  ` .dataset(${stringLiteral(mapName)}, rows)`,
15702
16055
  columnStepSource,
15703
16056
  ...metadataColumnSource ? [metadataColumnSource] : [],
15704
- ` .run({ key: (row, index) => __dlStableRowKey(row, index + rowStart) });`,
16057
+ ` .run(${runOptionsSource});`,
15705
16058
  ` return { rows: enriched, count: await enriched.count() };`,
15706
16059
  `}, { description: ${stringLiteral("Read a CSV file, run the configured Deepline enrich commands, and return enriched rows.")} });`
15707
16060
  ];
@@ -15910,6 +16263,7 @@ function helperSource() {
15910
16263
  ` if (typeof value === 'string') {`,
15911
16264
  ` const lower = value.trim().toLowerCase();`,
15912
16265
  ` if (!lower) return false;`,
16266
+ ` if (/^column\\s+.+\\s+failed\\b/.test(lower)) return true;`,
15913
16267
  ` if (lower.startsWith('error:') || lower.includes(': error:') || lower.includes('"error"')) return true;`,
15914
16268
  ` try {`,
15915
16269
  ` return __dlGeneratedCellError(JSON.parse(value));`,
@@ -15953,12 +16307,14 @@ function helperSource() {
15953
16307
  ` return context;`,
15954
16308
  `}`,
15955
16309
  ``,
15956
- `function __dlPrepareEnrichRow(row: Record<string, unknown>, aliases: string[]): Record<string, unknown> {`,
16310
+ `function __dlPrepareEnrichRow(row: Record<string, unknown>, aliases: string[], sourceRowIndex?: number): Record<string, unknown> {`,
15957
16311
  ` const cleaned = __dlStripErroredGeneratedColumns(row, aliases);`,
15958
16312
  ` const templateContext = __dlTemplateContext(cleaned);`,
15959
16313
  ` return {`,
15960
16314
  ` ...templateContext,`,
15961
16315
  ` ...cleaned,`,
16316
+ ` ...(typeof sourceRowIndex === 'number' && '__deeplineSourceRowIndex' in cleaned ? { __deeplineOriginalSourceRowIndex: cleaned.__deeplineSourceRowIndex } : {}),`,
16317
+ ` ...(typeof sourceRowIndex === 'number' ? { __deeplineSourceRowIndex: sourceRowIndex } : {}),`,
15962
16318
  ` __deeplineCsvProjectedFields: Object.keys(templateContext),`,
15963
16319
  ` __deeplineCsvProjectedValues: templateContext,`,
15964
16320
  ` };`,
@@ -16049,6 +16405,10 @@ function helperSource() {
16049
16405
  ` return String(index);`,
16050
16406
  `}`,
16051
16407
  ``,
16408
+ `function __dlEnrichRowKey(row: Record<string, unknown>, index: number): string {`,
16409
+ " return `${__dlStableRowKey(row, index)}:${index}`;",
16410
+ `}`,
16411
+ ``,
16052
16412
  `function __dlScalarValue(value: unknown): unknown {`,
16053
16413
  ` if (value && typeof value === 'object' && !Array.isArray(value)) {`,
16054
16414
  ` const record = value as Record<string, unknown>;`,
@@ -16261,6 +16621,29 @@ function helperSource() {
16261
16621
  ``,
16262
16622
  `type __DlExtractorHelpers = { row: Record<string, unknown>; result: unknown; data: unknown; raw: unknown; pick: (paths: string[] | string) => unknown; extract: (...args: unknown[]) => unknown; extractList: (...args: unknown[]) => unknown[]; target: (paths: string[] | string) => unknown; get: (path: string) => unknown };`,
16263
16623
  ``,
16624
+ `function __dlInlineExtractorArgs(args: unknown[]): { payload: unknown; selector: unknown } {`,
16625
+ ` if (args.length >= 3) return { payload: args[1], selector: args[2] };`,
16626
+ ` if (args.length >= 2) return { payload: args[0], selector: args[1] };`,
16627
+ ` return { payload: args[0], selector: undefined };`,
16628
+ `}`,
16629
+ ``,
16630
+ `function __dlInlineExtract(...args: unknown[]): unknown {`,
16631
+ ` const { payload, selector } = __dlInlineExtractorArgs(args);`,
16632
+ ` if (selector === undefined) return payload;`,
16633
+ ` const keys = __dlSelectorKeys(selector);`,
16634
+ ` if (keys) return Object.fromEntries(keys.map((key) => [key, __dlExtractTarget(payload, key) ?? null]));`,
16635
+ ` if (Array.isArray(selector)) return __dlFirstByPaths(payload, selector.map(String));`,
16636
+ ` if (typeof selector === 'string') return __dlExtractTarget(payload, selector) ?? __dlFirstByPaths(payload, selector);`,
16637
+ ` return selector;`,
16638
+ `}`,
16639
+ ``,
16640
+ `function __dlInlineExtractList(...args: unknown[]): unknown[] {`,
16641
+ ` const { payload, selector } = __dlInlineExtractorArgs(args);`,
16642
+ ` const rows = __dlFindList(payload, selector);`,
16643
+ ` const keys = __dlSelectorKeys(selector);`,
16644
+ ` return keys ? __dlProjectListRows(rows, keys, payload) : rows;`,
16645
+ `}`,
16646
+ ``,
16264
16647
  `function __dlErrorMessage(error: unknown): string {`,
16265
16648
  ` if (error instanceof Error && error.message) return error.message;`,
16266
16649
  ` if (typeof error === 'string' && error.trim()) return error.trim();`,
@@ -16282,8 +16665,8 @@ function helperSource() {
16282
16665
  ` return /\\b5\\d\\d\\b/.test(detail) || detail.includes('upstream_failure') || detail.includes('"error_category":"upstream"') || (detail.includes('"failure_origin":"provider"') && detail.includes('"status":5')) || detail.includes('bad gateway') || detail.includes('gateway time-out') || detail.includes('gateway timeout') || detail.includes('service unavailable');`,
16283
16666
  `}`,
16284
16667
  ``,
16285
- `function __dlWaterfallToolFailure(error: unknown): unknown {`,
16286
- ` if (__dlRecoverableWaterfallToolError(error)) return __dlExtractorFailure(error);`,
16668
+ `function __dlWaterfallToolFailure(error: unknown, tool?: string): unknown {`,
16669
+ ` if (tool === 'run_javascript' || __dlRecoverableWaterfallToolError(error)) return __dlExtractorFailure(error);`,
16287
16670
  ` throw error;`,
16288
16671
  `}`,
16289
16672
  ``,
@@ -16420,7 +16803,7 @@ function helperSource() {
16420
16803
  ` ...(input.force ? { force: true } : {}),`,
16421
16804
  ` });`,
16422
16805
  ` } catch (error) {`,
16423
- ` if (input.waterfallSoftFail) return __dlWaterfallToolFailure(error);`,
16806
+ ` if (input.waterfallSoftFail) return __dlWaterfallToolFailure(error, input.tool);`,
16424
16807
  ` throw error;`,
16425
16808
  ` }`,
16426
16809
  ` return __dlExtract(input.alias, result, input.row, input.extract, Boolean(input.legacyEnvelope));`,
@@ -16431,6 +16814,10 @@ function helperSource() {
16431
16814
  // src/cli/commands/enrich.ts
16432
16815
  var ENRICH_EXPORT_PAGE_SIZE = 5e3;
16433
16816
  var ENRICH_AUTO_BATCH_ROWS = 250;
16817
+ var ENRICH_EXPORT_BACKING_ROWS_WAIT_MS = 6e4;
16818
+ var ENRICH_EXPORT_BACKING_ROWS_POLL_MS = 1e3;
16819
+ var ENRICH_SOURCE_ROW_INDEX_COLUMN = "__deeplineSourceRowIndex";
16820
+ var ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN = "__deeplineOriginalSourceRowIndex";
16434
16821
  var EXIT_SERVER2 = 5;
16435
16822
  var ENRICH_DEBUG_T0 = Date.now();
16436
16823
  var GENERATED_ENRICH_ROWS_TABLE_NAMESPACE = "deepline_enrich_rows";
@@ -16545,6 +16932,17 @@ function emitEnrichDebug(message) {
16545
16932
  `
16546
16933
  );
16547
16934
  }
16935
+ function sleep6(ms) {
16936
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
16937
+ }
16938
+ function enrichExportBackingRowsWaitMs() {
16939
+ const raw = process.env.DEEPLINE_ENRICH_EXPORT_BACKING_ROWS_WAIT_MS?.trim();
16940
+ if (!raw) {
16941
+ return ENRICH_EXPORT_BACKING_ROWS_WAIT_MS;
16942
+ }
16943
+ const parsed = Number.parseInt(raw, 10);
16944
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : ENRICH_EXPORT_BACKING_ROWS_WAIT_MS;
16945
+ }
16548
16946
  function emitEnrichDebugValidationLines(config) {
16549
16947
  for (const line of buildEnrichDebugValidationLines(config)) {
16550
16948
  emitEnrichDebug(line);
@@ -16557,10 +16955,10 @@ function expandAtFilePath(rawPath) {
16557
16955
  (_match, bareName, bracedName) => process.env[bareName ?? bracedName ?? ""] ?? ""
16558
16956
  );
16559
16957
  if (expanded === "~") {
16560
- return (0, import_node_os7.homedir)();
16958
+ return (0, import_node_os8.homedir)();
16561
16959
  }
16562
16960
  if (expanded.startsWith("~/") || expanded.startsWith("~\\")) {
16563
- return (0, import_node_path11.join)((0, import_node_os7.homedir)(), expanded.slice(2));
16961
+ return (0, import_node_path12.join)((0, import_node_os8.homedir)(), expanded.slice(2));
16564
16962
  }
16565
16963
  return expanded;
16566
16964
  }
@@ -16694,6 +17092,7 @@ async function buildPlanArgs(args) {
16694
17092
  "--dry-run",
16695
17093
  "--json",
16696
17094
  "--force",
17095
+ "--fail-fast",
16697
17096
  "--all",
16698
17097
  "--in-place",
16699
17098
  "--no-open"
@@ -16744,7 +17143,7 @@ async function buildPlanArgs(args) {
16744
17143
  return planArgs;
16745
17144
  }
16746
17145
  async function assertInputCsvExists(inputCsv) {
16747
- const path = (0, import_node_path11.resolve)(inputCsv);
17146
+ const path = (0, import_node_path12.resolve)(inputCsv);
16748
17147
  try {
16749
17148
  const info = await (0, import_promises3.stat)(path);
16750
17149
  if (info.isFile()) {
@@ -16758,8 +17157,8 @@ async function assertInputCsvExists(inputCsv) {
16758
17157
  }
16759
17158
  }
16760
17159
  async function assertSafeOutputPath(inputCsv, outputPath) {
16761
- const input2 = (0, import_node_path11.resolve)(inputCsv);
16762
- const output2 = (0, import_node_path11.resolve)(outputPath);
17160
+ const input2 = (0, import_node_path12.resolve)(inputCsv);
17161
+ const output2 = (0, import_node_path12.resolve)(outputPath);
16763
17162
  if (input2 === output2) {
16764
17163
  throw new Error(
16765
17164
  "--input and --output must be different files when not using --in-place."
@@ -16788,7 +17187,7 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
16788
17187
  }
16789
17188
  async function regularFileExists(path) {
16790
17189
  try {
16791
- const info = await (0, import_promises3.stat)((0, import_node_path11.resolve)(path));
17190
+ const info = await (0, import_promises3.stat)((0, import_node_path12.resolve)(path));
16792
17191
  return info.isFile();
16793
17192
  } catch (error) {
16794
17193
  const code = error && typeof error === "object" ? error.code : void 0;
@@ -16799,7 +17198,7 @@ async function regularFileExists(path) {
16799
17198
  }
16800
17199
  }
16801
17200
  async function readConfig(path) {
16802
- const source = await (0, import_promises3.readFile)((0, import_node_path11.resolve)(path), "utf8");
17201
+ const source = await (0, import_promises3.readFile)((0, import_node_path12.resolve)(path), "utf8");
16803
17202
  let parsed;
16804
17203
  try {
16805
17204
  parsed = JSON.parse(source);
@@ -17076,15 +17475,47 @@ function isPlayStartStreamEndedError(error) {
17076
17475
  "Play start stream ended before a terminal status"
17077
17476
  );
17078
17477
  }
17079
- async function runGeneratedEnrichPlay(runArgs, options = {}) {
17478
+ function runIdFromGeneratedEnrichWatchError(error) {
17479
+ if (error instanceof DeeplineError) {
17480
+ const detailRunId = typeof error.details?.runId === "string" ? error.details.runId : typeof error.details?.workflowId === "string" ? error.details.workflowId : null;
17481
+ if (detailRunId?.trim()) {
17482
+ return detailRunId.trim();
17483
+ }
17484
+ }
17485
+ const message = error instanceof Error ? error.message : String(error ?? "");
17486
+ return message.match(/\b(play\/\S+\/run\/\S+)/)?.[1] ?? null;
17487
+ }
17488
+ function shouldStopGeneratedEnrichRunAfterWatchError(error) {
17489
+ if (error instanceof DeeplineError) {
17490
+ return error.code === "PLAY_WAIT_TIMEOUT" || error.code === "PLAY_START_STREAM_ENDED" || error.code === "PLAY_LIVE_STREAM_ENDED";
17491
+ }
17492
+ if (!(error instanceof Error)) {
17493
+ return false;
17494
+ }
17495
+ return error.message.includes("Timed out waiting for play") || error.message.includes("ended before a terminal status");
17496
+ }
17497
+ async function stopGeneratedEnrichRunAfterWatchError(client2, error) {
17498
+ if (!shouldStopGeneratedEnrichRunAfterWatchError(error)) {
17499
+ return;
17500
+ }
17501
+ const runId = runIdFromGeneratedEnrichWatchError(error);
17502
+ if (!runId) {
17503
+ return;
17504
+ }
17505
+ await client2.runs.stop(runId, {
17506
+ reason: "deepline enrich watch exited before terminal status"
17507
+ }).catch(() => void 0);
17508
+ }
17509
+ async function runGeneratedEnrichPlay(client2, runArgs, options = {}) {
17080
17510
  for (let attempt = 0; attempt < 2; attempt += 1) {
17081
17511
  try {
17082
17512
  return await captureStdout(() => handlePlayRun(runArgs), {
17083
17513
  passthrough: options.passthroughStdout
17084
17514
  });
17085
17515
  } catch (error) {
17516
+ await stopGeneratedEnrichRunAfterWatchError(client2, error);
17086
17517
  if (attempt === 0 && isPlayStartStreamEndedError(error)) {
17087
- await new Promise((resolve13) => setTimeout(resolve13, 250));
17518
+ await sleep6(250);
17088
17519
  continue;
17089
17520
  }
17090
17521
  throw error;
@@ -17104,20 +17535,41 @@ async function writeOutputCsv(outputPath, status, options) {
17104
17535
  "The generated play did not return row-shaped output, and no durable enrich rows were available to export."
17105
17536
  );
17106
17537
  }
17107
- if (options?.client) {
17108
- rowsInfo = await fetchBackingRowsForCsvExport({
17109
- client: options.client,
17110
- status,
17111
- rowsInfo
17112
- }).catch(() => null) ?? rowsInfo;
17538
+ const selectedSourceRows = selectedSourceCsvRowCount(options);
17539
+ const shouldFetchBackingRows = options?.client && shouldFetchBackingRowsForEnrichExport(rowsInfo, status, {
17540
+ selectedSourceRows
17541
+ });
17542
+ if (options?.client && shouldFetchBackingRows) {
17543
+ let fetchedRowsInfo = null;
17544
+ try {
17545
+ fetchedRowsInfo = await fetchBackingRowsForCsvExport({
17546
+ client: options.client,
17547
+ status,
17548
+ rowsInfo,
17549
+ sourceRowStart: options.rows?.rowStart ?? 0,
17550
+ expectedRows: selectedSourceRows
17551
+ });
17552
+ } catch (error) {
17553
+ throw new Error(
17554
+ `Failed to fetch durable generated enrich rows for CSV export: ${error instanceof Error ? error.message : String(error)}`
17555
+ );
17556
+ }
17557
+ rowsInfo = fetchedRowsInfo ?? rowsInfo;
17113
17558
  }
17114
17559
  const allowPartial = options?.allowPartial === true && !rowsInfo.complete && rowsInfo.rows.length > 0 && Boolean(options?.sourceCsvPath);
17115
17560
  assertCompleteRowsForCsvExport(rowsInfo, status, outputPath, {
17116
17561
  allowPartial
17117
17562
  });
17563
+ const statusFailureMessages = options?.config && rowsInfo.rows.length > 0 ? collectCompleteStatusFailureMessages({
17564
+ config: options.config,
17565
+ status,
17566
+ rowRange: options.rows ?? { rowStart: 0, rowEnd: null },
17567
+ rowCount: rowsInfo.rows.length
17568
+ }) : /* @__PURE__ */ new Map();
17118
17569
  const merged = mergeRowsForCsvExport(rowsInfo.rows, {
17119
17570
  ...options,
17120
- allowPartial
17571
+ allowPartial,
17572
+ statusFailureMessages
17121
17573
  });
17122
17574
  const columns = orderEnrichCsvColumns(
17123
17575
  dataExportColumns(merged.rows, [
@@ -17127,7 +17579,7 @@ async function writeOutputCsv(outputPath, status, options) {
17127
17579
  options?.config
17128
17580
  );
17129
17581
  await (0, import_promises3.writeFile)(
17130
- (0, import_node_path11.resolve)(outputPath),
17582
+ (0, import_node_path12.resolve)(outputPath),
17131
17583
  csvStringFromRows(merged.rows, columns),
17132
17584
  "utf8"
17133
17585
  );
@@ -17137,7 +17589,7 @@ async function writeOutputCsv(outputPath, status, options) {
17137
17589
  selectedRows: rowsInfo.totalRows,
17138
17590
  enrichedRows: rowsInfo.rows.length,
17139
17591
  rows: merged.rows.length,
17140
- path: (0, import_node_path11.resolve)(outputPath),
17592
+ path: (0, import_node_path12.resolve)(outputPath),
17141
17593
  partial: !rowsInfo.complete,
17142
17594
  enrichedDataRows: rowsInfo.rows
17143
17595
  };
@@ -17181,16 +17633,23 @@ async function buildEnrichFailureReport(input2) {
17181
17633
  rows: input2.rows,
17182
17634
  rowRange: input2.rowRange,
17183
17635
  client: input2.client,
17184
- outputPath: input2.exportResult?.path ?? input2.outputPath ?? null
17636
+ outputPath: input2.exportResult?.path ?? input2.outputPath ?? null,
17637
+ status: input2.status
17185
17638
  });
17186
17639
  }
17187
17640
  function recordField(value, key) {
17188
17641
  return value && typeof value === "object" && !Array.isArray(value) ? value[key] : void 0;
17189
17642
  }
17190
17643
  function extractRunId(status) {
17644
+ const run = recordField(status, "run");
17645
+ const nestedRun = recordField(run, "run");
17191
17646
  const candidates = [
17192
17647
  recordField(status, "runId"),
17193
- recordField(recordField(status, "run"), "id")
17648
+ recordField(status, "id"),
17649
+ recordField(run, "runId"),
17650
+ recordField(run, "id"),
17651
+ recordField(nestedRun, "runId"),
17652
+ recordField(nestedRun, "id")
17194
17653
  ];
17195
17654
  for (const candidate of candidates) {
17196
17655
  if (typeof candidate === "string" && candidate.trim()) {
@@ -17265,20 +17724,102 @@ function fallbackRowsInfoForGeneratedEnrichExport(status, options) {
17265
17724
  if (totalRows === null) {
17266
17725
  return null;
17267
17726
  }
17268
- const tableNamespaces = /* @__PURE__ */ new Set();
17269
- collectStringFields(status, "tableNamespace", tableNamespaces);
17270
- collectStringFields(status, "artifactTableNamespace", tableNamespaces);
17271
- const tableNamespace = tableNamespaces.values().next().value ?? GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
17272
17727
  return {
17273
17728
  rows: [],
17274
17729
  totalRows,
17275
17730
  columns: [],
17276
17731
  columnsExplicit: false,
17277
17732
  complete: false,
17278
- source: tableNamespace,
17279
- tableNamespace
17733
+ source: GENERATED_ENRICH_ROWS_TABLE_NAMESPACE,
17734
+ tableNamespace: GENERATED_ENRICH_ROWS_TABLE_NAMESPACE
17280
17735
  };
17281
17736
  }
17737
+ function hasLossyPreviewPlaceholder(value, depth = 0) {
17738
+ if (depth > 8) {
17739
+ return false;
17740
+ }
17741
+ if (value === "[Array]" || value === "[Object]") {
17742
+ return true;
17743
+ }
17744
+ if (Array.isArray(value)) {
17745
+ return value.some((item) => hasLossyPreviewPlaceholder(item, depth + 1));
17746
+ }
17747
+ if (value && typeof value === "object") {
17748
+ return Object.values(value).some(
17749
+ (item) => hasLossyPreviewPlaceholder(item, depth + 1)
17750
+ );
17751
+ }
17752
+ return false;
17753
+ }
17754
+ function shouldFetchBackingRowsForEnrichExport(rowsInfo, status, options = {}) {
17755
+ const terminalStatus = readEnrichRunStatus(status);
17756
+ const tableNamespace = rowsInfo.tableNamespace?.trim();
17757
+ if (terminalStatus === "failed" || terminalStatus === "cancelled") {
17758
+ return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && (rowsInfo.recovered === true || hasPartialRunOutputWarning(status));
17759
+ }
17760
+ if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
17761
+ return true;
17762
+ }
17763
+ if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && hasFailedRowSignal(status)) {
17764
+ return true;
17765
+ }
17766
+ if (!rowsInfo.complete) {
17767
+ return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
17768
+ }
17769
+ return rowsInfo.rows.some((row) => hasLossyPreviewPlaceholder(row));
17770
+ }
17771
+ function hasPartialRunOutputWarning(status) {
17772
+ const warningLists = [
17773
+ recordField(status, "warnings"),
17774
+ recordField(recordField(status, "run"), "warnings")
17775
+ ];
17776
+ return warningLists.some(
17777
+ (warnings) => Array.isArray(warnings) && warnings.some(
17778
+ (warning) => typeof warning === "string" && warning.includes("Run output is partial: showing") && warning.includes("preview row(s)")
17779
+ )
17780
+ );
17781
+ }
17782
+ function numericFailedRowSignal(value) {
17783
+ if (typeof value === "number" && Number.isFinite(value)) {
17784
+ return value;
17785
+ }
17786
+ if (typeof value !== "string") {
17787
+ return 0;
17788
+ }
17789
+ const match = value.match(/^\s*(\d+)/);
17790
+ return match ? Number(match[1]) : 0;
17791
+ }
17792
+ function hasFailedRowSignal(value, depth = 0) {
17793
+ if (depth > 16 || !value || typeof value !== "object") {
17794
+ return false;
17795
+ }
17796
+ if (Array.isArray(value)) {
17797
+ return value.some((item) => hasFailedRowSignal(item, depth + 1));
17798
+ }
17799
+ for (const [key, child] of Object.entries(value)) {
17800
+ const normalizedKey = key.toLowerCase().replace(/[^a-z0-9]/g, "");
17801
+ if ((normalizedKey === "failed" || normalizedKey === "failedrows" || normalizedKey === "failedcount") && numericFailedRowSignal(child) > 0) {
17802
+ return true;
17803
+ }
17804
+ if (hasFailedRowSignal(child, depth + 1)) {
17805
+ return true;
17806
+ }
17807
+ }
17808
+ return false;
17809
+ }
17810
+ function readEnrichRunStatus(status) {
17811
+ const candidates = [
17812
+ recordField(status, "status"),
17813
+ recordField(recordField(status, "run"), "status"),
17814
+ recordField(recordField(status, "progress"), "status")
17815
+ ];
17816
+ for (const candidate of candidates) {
17817
+ if (typeof candidate === "string" && candidate.trim()) {
17818
+ return candidate.trim().toLowerCase();
17819
+ }
17820
+ }
17821
+ return null;
17822
+ }
17282
17823
  function firstCollectedStringField(value, key) {
17283
17824
  const fields = /* @__PURE__ */ new Set();
17284
17825
  collectStringFields(value, key, fields);
@@ -17306,14 +17847,22 @@ function emitPlainBatchRunFailure(input2) {
17306
17847
  );
17307
17848
  }
17308
17849
  }
17309
- function exportableSheetRow2(row) {
17850
+ function exportableSheetRow2(row, sourceRowStart = 0) {
17310
17851
  if (!row || typeof row !== "object" || Array.isArray(row)) {
17311
17852
  return null;
17312
17853
  }
17313
17854
  const record = row;
17314
17855
  const data = record.data;
17315
17856
  if (data && typeof data === "object" && !Array.isArray(data)) {
17316
- return data;
17857
+ const exported = { ...data };
17858
+ const inputIndex = typeof record.inputIndex === "number" ? record.inputIndex : typeof record.inputIndex === "string" && record.inputIndex.trim() ? Number(record.inputIndex) : Number.NaN;
17859
+ if (Number.isInteger(inputIndex) && inputIndex >= 0) {
17860
+ if (ENRICH_SOURCE_ROW_INDEX_COLUMN in exported) {
17861
+ exported[ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN] = exported[ENRICH_SOURCE_ROW_INDEX_COLUMN];
17862
+ }
17863
+ exported[ENRICH_SOURCE_ROW_INDEX_COLUMN] = sourceRowStart + inputIndex;
17864
+ }
17865
+ return exported;
17317
17866
  }
17318
17867
  const fallback = { ...record };
17319
17868
  for (const key of [
@@ -17333,6 +17882,28 @@ function exportableSheetRow2(row) {
17333
17882
  }
17334
17883
  return fallback;
17335
17884
  }
17885
+ function sourceRowIndexFromEnrichRow(row, start, end) {
17886
+ const value = row[ENRICH_SOURCE_ROW_INDEX_COLUMN];
17887
+ const parsed = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : Number.NaN;
17888
+ if (!Number.isInteger(parsed) || parsed < start || parsed > end) {
17889
+ return null;
17890
+ }
17891
+ return parsed;
17892
+ }
17893
+ function stripEnrichSourceRowIndex(row) {
17894
+ if (!(ENRICH_SOURCE_ROW_INDEX_COLUMN in row)) {
17895
+ return row;
17896
+ }
17897
+ const stripped = { ...row };
17898
+ const hadOriginal = ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN in stripped;
17899
+ const originalSourceRowIndex = stripped[ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN];
17900
+ delete stripped[ENRICH_SOURCE_ROW_INDEX_COLUMN];
17901
+ delete stripped[ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN];
17902
+ if (hadOriginal) {
17903
+ stripped[ENRICH_SOURCE_ROW_INDEX_COLUMN] = originalSourceRowIndex;
17904
+ }
17905
+ return stripped;
17906
+ }
17336
17907
  function collectHardFailureAliases(config) {
17337
17908
  const aliases = [];
17338
17909
  const seen = /* @__PURE__ */ new Set();
@@ -17354,6 +17925,14 @@ function collectHardFailureAliases(config) {
17354
17925
  }
17355
17926
  function cellFailureError(value) {
17356
17927
  const parsed = parseMaybeJsonObject(value);
17928
+ if (!isRecord7(parsed)) {
17929
+ const text = typeof parsed === "string" ? parsed.trim() : "";
17930
+ if (/^(?:[A-Za-z0-9_:-]+:\s*)?(?:Error|TypeError|ReferenceError|SyntaxError|RangeError):\s+/.test(
17931
+ text
17932
+ ) || /^(?:[A-Za-z0-9_:-]+:\s*)?Column status:\s*(?:error|failed)\b/i.test(text)) {
17933
+ return { message: text };
17934
+ }
17935
+ }
17357
17936
  if (!isRecord7(parsed)) {
17358
17937
  return null;
17359
17938
  }
@@ -17385,7 +17964,9 @@ function buildEnrichWaterfallSummaryLines(config, rows) {
17385
17964
  continue;
17386
17965
  }
17387
17966
  const failures = rows.filter(
17388
- (row) => cellFailureError(row[child.alias])
17967
+ (row) => aliasFailureCellCandidates(row, child.alias).some(
17968
+ (candidate) => Boolean(cellFailureError(candidate))
17969
+ )
17389
17970
  ).length;
17390
17971
  if (failures > 0) {
17391
17972
  lines.push(
@@ -17396,6 +17977,56 @@ function buildEnrichWaterfallSummaryLines(config, rows) {
17396
17977
  }
17397
17978
  return lines;
17398
17979
  }
17980
+ function aliasFailureCellCandidates(row, alias) {
17981
+ const candidates = [row[alias]];
17982
+ const nested = {};
17983
+ const dottedPrefix = `${alias}.`;
17984
+ const underscorePrefix = `${alias}__`;
17985
+ for (const [key, value] of Object.entries(row)) {
17986
+ if (key.startsWith(dottedPrefix)) {
17987
+ assignFlattenedFailurePath(nested, key.slice(dottedPrefix.length), value);
17988
+ } else if (key.startsWith(underscorePrefix)) {
17989
+ assignFlattenedFailurePath(nested, key.slice(underscorePrefix.length), value);
17990
+ }
17991
+ }
17992
+ if (Object.keys(nested).length > 0) {
17993
+ candidates.push(nested);
17994
+ }
17995
+ return candidates;
17996
+ }
17997
+ function assignFlattenedFailurePath(target, field, value) {
17998
+ const parts = field.includes(".") ? field.split(".") : field.split("__");
17999
+ const normalized = parts.map((part) => part.trim()).filter(Boolean);
18000
+ if (normalized.length <= 1) {
18001
+ target[field] = value;
18002
+ return;
18003
+ }
18004
+ let cursor = target;
18005
+ for (const part of normalized.slice(0, -1)) {
18006
+ const existing = cursor[part];
18007
+ if (!isRecord7(existing)) {
18008
+ const next = {};
18009
+ cursor[part] = next;
18010
+ cursor = next;
18011
+ } else {
18012
+ cursor = existing;
18013
+ }
18014
+ }
18015
+ cursor[normalized[normalized.length - 1] ?? field] = value;
18016
+ }
18017
+ function aliasFlattenedCells(row, alias) {
18018
+ const cells = [];
18019
+ const dottedPrefix = `${alias}.`;
18020
+ const underscorePrefix = `${alias}__`;
18021
+ for (const [key, value] of Object.entries(row)) {
18022
+ if (key.startsWith(dottedPrefix)) {
18023
+ cells.push({ field: key.slice(dottedPrefix.length), value });
18024
+ } else if (key.startsWith(underscorePrefix)) {
18025
+ cells.push({ field: key.slice(underscorePrefix.length), value });
18026
+ }
18027
+ }
18028
+ return cells;
18029
+ }
17399
18030
  function collectEnrichFailureJobs(input2) {
17400
18031
  const aliases = collectHardFailureAliases(input2.config);
17401
18032
  if (aliases.length === 0 || input2.rows.length === 0) {
@@ -17405,11 +18036,13 @@ function collectEnrichFailureJobs(input2) {
17405
18036
  const jobs = [];
17406
18037
  input2.rows.forEach((row, rowIndex) => {
17407
18038
  aliases.forEach((alias, aliasIndex) => {
17408
- const failure = cellFailureError(row[alias]);
18039
+ const failure = aliasFailureCellCandidates(row, alias).map(cellFailureError).find(
18040
+ (candidate) => Boolean(candidate)
18041
+ );
17409
18042
  if (!failure) {
17410
18043
  return;
17411
18044
  }
17412
- const rowId = rowOffset + rowIndex;
18045
+ const rowId = sourceRowIndexFromEnrichRow(row, 0, Number.MAX_SAFE_INTEGER) ?? rowOffset + rowIndex;
17413
18046
  jobs.push({
17414
18047
  job_id: `row-${rowId}-${alias}`,
17415
18048
  row_id: rowId,
@@ -17425,6 +18058,72 @@ function collectEnrichFailureJobs(input2) {
17425
18058
  });
17426
18059
  return jobs;
17427
18060
  }
18061
+ function collectStatusFailureJobs(input2) {
18062
+ const aliases = collectHardFailureAliases(input2.config);
18063
+ if (aliases.length === 0) {
18064
+ return [];
18065
+ }
18066
+ const summaries = collectColumnStats(input2.status);
18067
+ const rowStart = input2.rowRange.rowStart ?? 0;
18068
+ const selectedRows = input2.rowRange.rowEnd !== null && input2.rowRange.rowEnd >= rowStart ? input2.rowRange.rowEnd - rowStart + 1 : Number.MAX_SAFE_INTEGER;
18069
+ const jobs = [];
18070
+ aliases.forEach((alias, aliasIndex) => {
18071
+ const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
18072
+ if (!stat2) {
18073
+ return;
18074
+ }
18075
+ const execution = isRecord7(stat2.execution) ? stat2.execution : null;
18076
+ const failedCount = Math.min(
18077
+ selectedRows,
18078
+ Math.max(
18079
+ numericFailedRowSignal(stat2.failed),
18080
+ numericFailedRowSignal(stat2.failedRows),
18081
+ numericFailedRowSignal(execution?.failed)
18082
+ )
18083
+ );
18084
+ if (!Number.isFinite(failedCount) || failedCount <= 0) {
18085
+ return;
18086
+ }
18087
+ const message = firstCollectedStringField(stat2, "error") ?? firstCollectedStringField(stat2, "message") ?? `Column ${alias} failed for ${failedCount} row(s).`;
18088
+ for (let offset = 0; offset < failedCount; offset += 1) {
18089
+ const rowId = rowStart + offset;
18090
+ jobs.push({
18091
+ job_id: `row-${rowId}-${alias}`,
18092
+ row_id: rowId,
18093
+ col_index: aliasIndex,
18094
+ column: alias,
18095
+ status: "failed",
18096
+ last_error: message,
18097
+ error: message
18098
+ });
18099
+ }
18100
+ });
18101
+ return jobs;
18102
+ }
18103
+ function collectCompleteStatusFailureMessages(input2) {
18104
+ const requiredCount = Math.max(1, Math.trunc(input2.rowCount));
18105
+ const jobs = collectStatusFailureJobs({
18106
+ config: input2.config,
18107
+ status: input2.status,
18108
+ rowRange: input2.rowRange
18109
+ });
18110
+ const byAlias = /* @__PURE__ */ new Map();
18111
+ for (const job of jobs) {
18112
+ const alias = normalizeAlias2(job.column);
18113
+ const existing = byAlias.get(alias);
18114
+ byAlias.set(alias, {
18115
+ count: (existing?.count ?? 0) + 1,
18116
+ message: existing?.message ?? job.last_error
18117
+ });
18118
+ }
18119
+ const complete = /* @__PURE__ */ new Map();
18120
+ for (const [alias, value] of byAlias) {
18121
+ if (value.count >= requiredCount) {
18122
+ complete.set(alias, value.message);
18123
+ }
18124
+ }
18125
+ return complete;
18126
+ }
17428
18127
  function parseExecutionCount(value) {
17429
18128
  if (typeof value === "number" && Number.isFinite(value)) {
17430
18129
  return Math.max(0, Math.trunc(value));
@@ -17567,9 +18266,9 @@ async function persistEnrichFailureReport(input2) {
17567
18266
  if (input2.jobs.length === 0) {
17568
18267
  return null;
17569
18268
  }
17570
- const stateDir = (0, import_node_path11.join)((0, import_node_os7.homedir)(), ".local", "deepline", "runtime", "state");
18269
+ const stateDir = (0, import_node_path12.join)((0, import_node_os8.homedir)(), ".local", "deepline", "runtime", "state");
17571
18270
  await (0, import_promises3.mkdir)(stateDir, { recursive: true });
17572
- const reportPath = (0, import_node_path11.join)(
18271
+ const reportPath = (0, import_node_path12.join)(
17573
18272
  stateDir,
17574
18273
  `run-block-failures-${Math.floor(Date.now() / 1e3)}-${process.pid}.json`
17575
18274
  );
@@ -17598,11 +18297,16 @@ async function persistEnrichFailureReport(input2) {
17598
18297
  return reportPath;
17599
18298
  }
17600
18299
  async function maybeEmitEnrichFailureReport(input2) {
17601
- const jobs = collectEnrichFailureJobs({
18300
+ const rowJobs = collectEnrichFailureJobs({
17602
18301
  config: input2.config,
17603
18302
  rows: input2.rows,
17604
18303
  rowStart: input2.rowRange.rowStart
17605
18304
  });
18305
+ const jobs = rowJobs.length > 0 || input2.status === void 0 ? rowJobs : collectStatusFailureJobs({
18306
+ config: input2.config,
18307
+ status: input2.status,
18308
+ rowRange: input2.rowRange
18309
+ });
17606
18310
  if (jobs.length === 0) {
17607
18311
  return null;
17608
18312
  }
@@ -17660,75 +18364,139 @@ function mergePreferredColumns(preferredColumns, rows) {
17660
18364
  async function fetchBackingRowsForCsvExport(input2) {
17661
18365
  const runId = extractRunId(input2.status);
17662
18366
  const playName = extractPlayName2(input2.status);
17663
- const tableNamespace = input2.rowsInfo.tableNamespace?.trim();
18367
+ const tableNamespace = input2.rowsInfo.tableNamespace?.trim() || GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
17664
18368
  if (!runId || !playName || !tableNamespace) {
17665
18369
  return null;
17666
18370
  }
17667
- const sheetRows = [];
17668
- let offset = 0;
17669
- let expectedTotal = input2.rowsInfo.totalRows;
17670
- while (true) {
17671
- const page = await input2.client.runs.exportDatasetRows({
17672
- playName,
17673
- tableNamespace,
17674
- runId,
17675
- limit: ENRICH_EXPORT_PAGE_SIZE,
17676
- offset,
17677
- rowMode: "all"
17678
- });
17679
- sheetRows.push(...page.rows);
17680
- const summaryTotal = page.summary?.stats?.total;
17681
- if (typeof summaryTotal === "number" && Number.isFinite(summaryTotal)) {
17682
- expectedTotal = Math.max(expectedTotal, Math.trunc(summaryTotal));
18371
+ const deadline = Date.now() + enrichExportBackingRowsWaitMs();
18372
+ let lastRows = [];
18373
+ const minimumExpectedRows = typeof input2.expectedRows === "number" && input2.expectedRows > 0 ? Math.trunc(input2.expectedRows) : input2.rowsInfo.totalRows;
18374
+ let lastExpectedTotal = minimumExpectedRows;
18375
+ for (; ; ) {
18376
+ const sheetRows = [];
18377
+ let offset = 0;
18378
+ let expectedTotal = minimumExpectedRows;
18379
+ while (true) {
18380
+ const page = await input2.client.runs.exportDatasetRows({
18381
+ playName,
18382
+ tableNamespace,
18383
+ runId,
18384
+ limit: ENRICH_EXPORT_PAGE_SIZE,
18385
+ offset,
18386
+ rowMode: "all"
18387
+ });
18388
+ sheetRows.push(...page.rows);
18389
+ const summaryTotal = page.summary?.stats?.total;
18390
+ if (typeof summaryTotal === "number" && Number.isFinite(summaryTotal)) {
18391
+ expectedTotal = Math.max(expectedTotal, Math.trunc(summaryTotal));
18392
+ }
18393
+ if (page.rows.length < ENRICH_EXPORT_PAGE_SIZE || sheetRows.length >= expectedTotal) {
18394
+ break;
18395
+ }
18396
+ offset += page.rows.length;
17683
18397
  }
17684
- if (page.rows.length < ENRICH_EXPORT_PAGE_SIZE || sheetRows.length >= expectedTotal) {
18398
+ const rows = sheetRows.map((row) => exportableSheetRow2(row, input2.sourceRowStart ?? 0)).filter((row) => Boolean(row));
18399
+ lastRows = rows;
18400
+ lastExpectedTotal = expectedTotal;
18401
+ if (expectedTotal > 0 && rows.length >= expectedTotal || expectedTotal === 0 && rows.length > 0) {
18402
+ return {
18403
+ ...input2.rowsInfo,
18404
+ rows,
18405
+ columns: mergePreferredColumns(
18406
+ input2.rowsInfo.columnsExplicit ? input2.rowsInfo.columns : [],
18407
+ rows
18408
+ ),
18409
+ totalRows: Math.max(rows.length, expectedTotal),
18410
+ complete: true,
18411
+ source: `${input2.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
18412
+ };
18413
+ }
18414
+ if (Date.now() >= deadline) {
17685
18415
  break;
17686
18416
  }
17687
- offset += page.rows.length;
18417
+ await sleep6(ENRICH_EXPORT_BACKING_ROWS_POLL_MS);
17688
18418
  }
17689
- const rows = sheetRows.map(exportableSheetRow2).filter((row) => Boolean(row));
17690
- if (rows.length < input2.rowsInfo.totalRows) {
18419
+ if (lastRows.length <= input2.rowsInfo.rows.length) {
17691
18420
  return null;
17692
18421
  }
17693
18422
  return {
17694
18423
  ...input2.rowsInfo,
17695
- rows,
18424
+ rows: lastRows,
17696
18425
  columns: mergePreferredColumns(
17697
18426
  input2.rowsInfo.columnsExplicit ? input2.rowsInfo.columns : [],
17698
- rows
18427
+ lastRows
17699
18428
  ),
17700
- totalRows: rows.length,
17701
- complete: true,
18429
+ totalRows: Math.max(lastExpectedTotal, input2.rowsInfo.totalRows),
18430
+ complete: false,
17702
18431
  source: `${input2.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
17703
18432
  };
17704
18433
  }
17705
18434
  function mergeRowsForCsvExport(enrichedRows, options) {
17706
- const rows = dataExportRows(normalizeEnrichRowsForCsvExport(enrichedRows));
18435
+ const rows = dataExportRows(
18436
+ normalizeEnrichRowsForCsvExport(enrichedRows, options?.config, {
18437
+ statusFailureMessages: options?.statusFailureMessages
18438
+ })
18439
+ );
17707
18440
  const range = options?.rows;
17708
- if (!options?.sourceCsvPath || !options.inPlace && !options.allowPartial && (range?.rowStart === null || range?.rowStart === void 0)) {
17709
- return { rows, preferredColumns: [] };
18441
+ if (!options?.sourceCsvPath) {
18442
+ return {
18443
+ rows: rows.map(stripEnrichSourceRowIndex),
18444
+ preferredColumns: []
18445
+ };
17710
18446
  }
17711
18447
  const parsedBaseRows = readCsvRows(options.sourceCsvPath);
17712
18448
  const preferredColumns = Object.keys(parsedBaseRows[0] ?? {});
17713
18449
  const baseRows = parsedBaseRows.map(
17714
- (row) => ({ ...row })
18450
+ (row) => ({
18451
+ ...row
18452
+ })
17715
18453
  );
17716
18454
  const start = Math.max(0, range?.rowStart ?? 0);
17717
18455
  const maxEnd = Math.max(start, baseRows.length - 1);
17718
18456
  const inclusiveEnd = range?.rowEnd === null || range?.rowEnd === void 0 ? maxEnd : Math.min(maxEnd, range.rowEnd);
17719
18457
  const expectedSelectedRows = baseRows.length === 0 ? 0 : Math.max(0, inclusiveEnd - start + 1);
17720
- if (rows.length < expectedSelectedRows && !options.allowPartial) {
18458
+ const canMergeSparseBySourceIndex = rows.length > 0 && rows.every(
18459
+ (row) => sourceRowIndexFromEnrichRow(row, start, inclusiveEnd) !== null
18460
+ );
18461
+ if (rows.length < expectedSelectedRows && !options.allowPartial && !canMergeSparseBySourceIndex) {
17721
18462
  throw new Error(
17722
18463
  `Refusing to write a partial in-place CSV export: the run returned ${rows.length} row(s) for ${expectedSelectedRows} selected source row(s).`
17723
18464
  );
17724
18465
  }
17725
18466
  const merged = [...baseRows];
18467
+ if (canMergeSparseBySourceIndex) {
18468
+ for (const rawEnriched of rows) {
18469
+ const rowIndex = sourceRowIndexFromEnrichRow(
18470
+ rawEnriched,
18471
+ start,
18472
+ inclusiveEnd
18473
+ );
18474
+ if (rowIndex === null) {
18475
+ continue;
18476
+ }
18477
+ const enriched = stripEnrichSourceRowIndex(rawEnriched);
18478
+ const base = merged[rowIndex] ?? {};
18479
+ merged[rowIndex] = {
18480
+ ...base,
18481
+ ...enriched
18482
+ };
18483
+ const metadata = mergeLegacyMetadataCell(
18484
+ base._metadata,
18485
+ enriched._metadata
18486
+ );
18487
+ if (metadata !== void 0) {
18488
+ merged[rowIndex]._metadata = metadata;
18489
+ }
18490
+ }
18491
+ return { rows: merged, preferredColumns };
18492
+ }
17726
18493
  let selectedIndex = 0;
17727
18494
  for (let rowIndex = start; rowIndex <= inclusiveEnd; rowIndex += 1) {
17728
- const enriched = rows[selectedIndex++];
17729
- if (!enriched) {
18495
+ const rawEnriched = rows[selectedIndex++];
18496
+ if (!rawEnriched) {
17730
18497
  break;
17731
18498
  }
18499
+ const enriched = stripEnrichSourceRowIndex(rawEnriched);
17732
18500
  const base = merged[rowIndex] ?? {};
17733
18501
  merged[rowIndex] = {
17734
18502
  ...base,
@@ -17807,21 +18575,146 @@ function orderEnrichCsvColumns(columns, config) {
17807
18575
  function isNonEmptyCsvCell(value) {
17808
18576
  return value !== null && value !== void 0 && String(value).trim() !== "";
17809
18577
  }
17810
- function normalizeEnrichRowsForCsvExport(rows) {
18578
+ var ENRICH_FLATTENED_SUCCESS_FIELD_PRIORITY = [
18579
+ "matched_result",
18580
+ "matchedResult",
18581
+ "value",
18582
+ "email",
18583
+ "url",
18584
+ "domain",
18585
+ "name",
18586
+ "result"
18587
+ ];
18588
+ var ENRICH_FLATTENED_CONTROL_FIELDS = /* @__PURE__ */ new Set([
18589
+ "error",
18590
+ "last_error",
18591
+ "message",
18592
+ "operation",
18593
+ "provider",
18594
+ "status"
18595
+ ]);
18596
+ function materializeCsvCellValue(value) {
18597
+ if (value && typeof value === "object") {
18598
+ return JSON.stringify(value);
18599
+ }
18600
+ return value;
18601
+ }
18602
+ function materializeAliasSuccessCell(row, alias) {
18603
+ const direct = row[alias];
18604
+ if (isRecord7(direct)) {
18605
+ if (Object.prototype.hasOwnProperty.call(direct, "matched_result") || Object.prototype.hasOwnProperty.call(direct, "matchedResult") || Object.prototype.hasOwnProperty.call(direct, "result")) {
18606
+ return materializeCsvCellValue(direct);
18607
+ }
18608
+ const directCells = [];
18609
+ for (const [field, value] of Object.entries(direct)) {
18610
+ if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
18611
+ continue;
18612
+ }
18613
+ if (isNonEmptyCsvCell(value)) {
18614
+ directCells.push({ field, value });
18615
+ }
18616
+ }
18617
+ for (const preferredField of [alias, ...ENRICH_FLATTENED_SUCCESS_FIELD_PRIORITY]) {
18618
+ const preferred = directCells.find(({ field }) => field === preferredField);
18619
+ if (preferred) {
18620
+ return materializeCsvCellValue(preferred.value);
18621
+ }
18622
+ }
18623
+ if (directCells.length === 1) {
18624
+ return materializeCsvCellValue(directCells[0].value);
18625
+ }
18626
+ if (directCells.length > 1) {
18627
+ return JSON.stringify(
18628
+ Object.fromEntries(
18629
+ directCells.map(({ field, value }) => [field, value])
18630
+ )
18631
+ );
18632
+ }
18633
+ }
18634
+ const cells = aliasFlattenedCells(row, alias).filter(({ field, value }) => {
18635
+ if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
18636
+ return false;
18637
+ }
18638
+ return isNonEmptyCsvCell(value);
18639
+ });
18640
+ if (cells.length === 0) {
18641
+ return void 0;
18642
+ }
18643
+ for (const preferredField of ENRICH_FLATTENED_SUCCESS_FIELD_PRIORITY) {
18644
+ const preferred = cells.find(({ field }) => field === preferredField);
18645
+ if (preferred) {
18646
+ return materializeCsvCellValue(preferred.value);
18647
+ }
18648
+ }
18649
+ if (cells.length === 1) {
18650
+ return materializeCsvCellValue(cells[0].value);
18651
+ }
18652
+ return JSON.stringify(
18653
+ Object.fromEntries(cells.map(({ field, value }) => [field, value]))
18654
+ );
18655
+ }
18656
+ function normalizeEnrichRowsForCsvExport(rows, config, options) {
18657
+ const aliases = config ? collectConfigScalarAliasOrder(config) : [];
17811
18658
  return rows.map((row) => {
17812
18659
  const metadata = legacyMetadataFromRow(row);
17813
- if (!metadata) {
17814
- return row;
18660
+ const normalized = metadata ? { ...row, _metadata: metadata } : { ...row };
18661
+ if (metadata) {
18662
+ delete normalized.metadata;
18663
+ delete normalized["metadata.columns"];
18664
+ delete normalized.metadata__columns;
17815
18665
  }
17816
- const normalized = { ...row, _metadata: metadata };
17817
- delete normalized.metadata;
17818
- delete normalized["metadata.columns"];
17819
- delete normalized.metadata__columns;
17820
18666
  for (const key of Object.keys(normalized)) {
17821
18667
  if (key.startsWith("metadata.columns.") || key.startsWith("metadata__columns.")) {
17822
18668
  delete normalized[key];
17823
18669
  }
17824
18670
  }
18671
+ const failureAliases = /* @__PURE__ */ new Set();
18672
+ for (const key of Object.keys(normalized)) {
18673
+ const dotted = key.match(
18674
+ /^(.+)\.(?:error|last_error|message|operation|provider|result|status)$/
18675
+ );
18676
+ const underscored = key.match(
18677
+ /^(.+)__(?:error|last_error|message|operation|provider|result|status)$/
18678
+ );
18679
+ const alias = dotted?.[1] ?? underscored?.[1] ?? null;
18680
+ if (alias) {
18681
+ failureAliases.add(alias);
18682
+ }
18683
+ }
18684
+ for (const alias of failureAliases) {
18685
+ if (isNonEmptyCsvCell(normalized[alias])) {
18686
+ continue;
18687
+ }
18688
+ const failure = aliasFailureCellCandidates(normalized, alias).map(cellFailureError).find(
18689
+ (candidate) => Boolean(candidate)
18690
+ );
18691
+ if (failure) {
18692
+ normalized[alias] = failure.message;
18693
+ }
18694
+ }
18695
+ for (const alias of aliases) {
18696
+ const value = materializeAliasSuccessCell(normalized, alias);
18697
+ if (value !== void 0) {
18698
+ normalized[alias] = value;
18699
+ continue;
18700
+ }
18701
+ if (isNonEmptyCsvCell(normalized[alias])) {
18702
+ continue;
18703
+ }
18704
+ const failure = aliasFailureCellCandidates(normalized, alias).map(cellFailureError).find(
18705
+ (candidate) => Boolean(candidate)
18706
+ );
18707
+ if (failure) {
18708
+ normalized[alias] = failure.message;
18709
+ continue;
18710
+ }
18711
+ const statusFailureMessage = options?.statusFailureMessages?.get(
18712
+ normalizeAlias2(alias)
18713
+ );
18714
+ if (statusFailureMessage) {
18715
+ normalized[alias] = statusFailureMessage;
18716
+ }
18717
+ }
17825
18718
  return normalized;
17826
18719
  });
17827
18720
  }
@@ -17984,6 +18877,9 @@ function registerEnrichCommand(program) {
17984
18877
  ).option(
17985
18878
  "--profile <id>",
17986
18879
  "Internal/testing: override the execution profile for the generated play run."
18880
+ ).option(
18881
+ "--fail-fast",
18882
+ "Fail the generated play when any selected row errors, while preserving recovered runtime-sheet rows for export."
17987
18883
  ).action(async (options, _command) => {
17988
18884
  if (options.inPlace && options.dryRun) {
17989
18885
  throw new Error("--in-place is not supported with --dry-run.");
@@ -18007,14 +18903,16 @@ function registerEnrichCommand(program) {
18007
18903
  const forceAliases2 = resolveForceAliases(config, options);
18008
18904
  const playSource2 = compileEnrichConfigToPlaySource(config, {
18009
18905
  forceAliases: forceAliases2,
18010
- playName: options.name
18906
+ playName: options.name,
18907
+ inlineRunJavascript: true,
18908
+ failFast: options.failFast
18011
18909
  });
18012
18910
  const summary = summarizePlan(config, playSource2);
18013
18911
  if (options.json) {
18014
18912
  printJson({
18015
18913
  dryRun: true,
18016
- input: (0, import_node_path11.resolve)(inputCsv),
18017
- output: options.output ? (0, import_node_path11.resolve)(options.output) : null,
18914
+ input: (0, import_node_path12.resolve)(inputCsv),
18915
+ output: options.output ? (0, import_node_path12.resolve)(options.output) : null,
18018
18916
  plan: summary
18019
18917
  });
18020
18918
  return;
@@ -18036,15 +18934,17 @@ function registerEnrichCommand(program) {
18036
18934
  }
18037
18935
  const playSource = compileEnrichConfigToPlaySource(config, {
18038
18936
  forceAliases,
18039
- playName: options.name
18937
+ playName: options.name,
18938
+ inlineRunJavascript: true,
18939
+ failFast: options.failFast
18040
18940
  });
18041
- const tempDir = await (0, import_promises3.mkdtemp)((0, import_node_path11.join)((0, import_node_os7.tmpdir)(), "deepline-enrich-play-"));
18042
- const tempPlay = (0, import_node_path11.join)(tempDir, "deepline-enrich.play.ts");
18941
+ const tempDir = await (0, import_promises3.mkdtemp)((0, import_node_path12.join)((0, import_node_os8.tmpdir)(), "deepline-enrich-play-"));
18942
+ const tempPlay = (0, import_node_path12.join)(tempDir, "deepline-enrich.play.ts");
18043
18943
  try {
18044
18944
  await (0, import_promises3.writeFile)(tempPlay, playSource, "utf8");
18045
18945
  const runOne = async (input2) => {
18046
18946
  const runtimeInput = {
18047
- file: (0, import_node_path11.resolve)(input2.sourceCsvPath),
18947
+ file: (0, import_node_path12.resolve)(input2.sourceCsvPath),
18048
18948
  ...input2.rows.rowStart !== null ? { rowStart: input2.rows.rowStart } : {},
18049
18949
  ...input2.rows.rowEnd !== null ? { rowEnd: input2.rows.rowEnd } : {}
18050
18950
  };
@@ -18070,7 +18970,7 @@ function registerEnrichCommand(program) {
18070
18970
  if (timeoutSeconds !== null && Number.isFinite(timeoutSeconds) && timeoutSeconds > 0) {
18071
18971
  runArgs.push("--tail-timeout-ms", String(timeoutSeconds * 1e3));
18072
18972
  }
18073
- const captured2 = await runGeneratedEnrichPlay(runArgs, {
18973
+ const captured2 = await runGeneratedEnrichPlay(client2, runArgs, {
18074
18974
  passthroughStdout: input2.passthroughStdout
18075
18975
  });
18076
18976
  const status2 = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
@@ -18097,7 +18997,7 @@ function registerEnrichCommand(program) {
18097
18997
  );
18098
18998
  if (!options.json) {
18099
18999
  process.stderr.write(
18100
- `Large enrich input selected ${selectedRange.count.toLocaleString()} rows. Running ${chunkCount.toLocaleString()} sequential batch runs of up to ${ENRICH_AUTO_BATCH_ROWS.toLocaleString()} rows and merging ${(0, import_node_path11.resolve)(outputPath)}.
19000
+ `Large enrich input selected ${selectedRange.count.toLocaleString()} rows. Running ${chunkCount.toLocaleString()} sequential batch runs of up to ${ENRICH_AUTO_BATCH_ROWS.toLocaleString()} rows and merging ${(0, import_node_path12.resolve)(outputPath)}.
18101
19001
  `
18102
19002
  );
18103
19003
  }
@@ -18173,7 +19073,8 @@ function registerEnrichCommand(program) {
18173
19073
  rowEnd: selectedRange.end
18174
19074
  },
18175
19075
  client: client2,
18176
- outputPath
19076
+ outputPath,
19077
+ status: lastStatus
18177
19078
  });
18178
19079
  if (options.json) {
18179
19080
  const run = rewriteEnrichJsonStatus({
@@ -18237,7 +19138,8 @@ function registerEnrichCommand(program) {
18237
19138
  rowRange: rows,
18238
19139
  client: client2,
18239
19140
  exportResult,
18240
- outputPath
19141
+ outputPath,
19142
+ status
18241
19143
  });
18242
19144
  if (options.json) {
18243
19145
  printJson({
@@ -18262,7 +19164,8 @@ function registerEnrichCommand(program) {
18262
19164
  rowRange: rows,
18263
19165
  client: client2,
18264
19166
  exportResult,
18265
- outputPath
19167
+ outputPath,
19168
+ status
18266
19169
  });
18267
19170
  const run = rewriteEnrichJsonStatus({
18268
19171
  status,
@@ -18306,7 +19209,8 @@ function registerEnrichCommand(program) {
18306
19209
  rows: rowsForFailureReport,
18307
19210
  rowRange: rows,
18308
19211
  client: client2,
18309
- outputPath: exportResult?.path ?? outputPath ?? null
19212
+ outputPath: exportResult?.path ?? outputPath ?? null,
19213
+ status
18310
19214
  });
18311
19215
  if (failureReport) {
18312
19216
  process.exitCode = EXIT_SERVER2;
@@ -18362,11 +19266,11 @@ Examples:
18362
19266
  }
18363
19267
 
18364
19268
  // src/cli/commands/sessions.ts
18365
- var import_node_fs10 = require("fs");
18366
- var import_node_os8 = require("os");
18367
- var import_node_path12 = require("path");
19269
+ var import_node_fs11 = require("fs");
19270
+ var import_node_os9 = require("os");
19271
+ var import_node_path13 = require("path");
18368
19272
  var import_node_zlib = require("zlib");
18369
- var import_node_crypto3 = require("crypto");
19273
+ var import_node_crypto4 = require("crypto");
18370
19274
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
18371
19275
  var UUID_IN_TEXT_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
18372
19276
  var MAX_SESSION_UPLOAD_BYTES = 35e5;
@@ -18378,33 +19282,33 @@ var MAX_EVENT_OBJECT_KEYS = 80;
18378
19282
  var TRUNCATION_MARKER = "...[truncated]";
18379
19283
  var NOISE_EVENT_TYPES = /* @__PURE__ */ new Set(["progress", "file-history-snapshot"]);
18380
19284
  function homeDir() {
18381
- return process.env.HOME?.trim() || (0, import_node_os8.homedir)();
19285
+ return process.env.HOME?.trim() || (0, import_node_os9.homedir)();
18382
19286
  }
18383
19287
  function detectShellContext() {
18384
19288
  const shellPath = process.env.SHELL?.trim() || process.env.ComSpec?.trim() || process.env.COMSPEC?.trim() || "";
18385
19289
  return {
18386
- shell: shellPath ? (0, import_node_path12.basename)(shellPath).replace(/\.exe$/i, "") : "unknown",
19290
+ shell: shellPath ? (0, import_node_path13.basename)(shellPath).replace(/\.exe$/i, "") : "unknown",
18387
19291
  shell_path: shellPath || null,
18388
- os: (0, import_node_os8.platform)(),
19292
+ os: (0, import_node_os9.platform)(),
18389
19293
  cwd: process.cwd()
18390
19294
  };
18391
19295
  }
18392
19296
  function claudeProjectsRoot() {
18393
- return (0, import_node_path12.join)(homeDir(), ".claude", "projects");
19297
+ return (0, import_node_path13.join)(homeDir(), ".claude", "projects");
18394
19298
  }
18395
19299
  function codexSessionsRoot() {
18396
- return (0, import_node_path12.join)(homeDir(), ".codex", "sessions");
19300
+ return (0, import_node_path13.join)(homeDir(), ".codex", "sessions");
18397
19301
  }
18398
19302
  function listClaudeSessionFiles() {
18399
19303
  const root = claudeProjectsRoot();
18400
- if (!(0, import_node_fs10.existsSync)(root)) return [];
19304
+ if (!(0, import_node_fs11.existsSync)(root)) return [];
18401
19305
  const projectDirs = readDirectoryNames(root);
18402
19306
  const files = [];
18403
19307
  for (const projectDir of projectDirs) {
18404
- const fullProjectDir = (0, import_node_path12.join)(root, projectDir);
19308
+ const fullProjectDir = (0, import_node_path13.join)(root, projectDir);
18405
19309
  for (const fileName of readDirectoryNames(fullProjectDir)) {
18406
19310
  if (fileName.endsWith(".jsonl")) {
18407
- const filePath = (0, import_node_path12.join)(fullProjectDir, fileName);
19311
+ const filePath = (0, import_node_path13.join)(fullProjectDir, fileName);
18408
19312
  const sessionId = sessionIdFromClaudeFilePath(filePath);
18409
19313
  const stat2 = statIfReadable(filePath);
18410
19314
  if (sessionId && stat2) {
@@ -18422,7 +19326,7 @@ function listClaudeSessionFiles() {
18422
19326
  }
18423
19327
  function listCodexSessionFiles() {
18424
19328
  const root = codexSessionsRoot();
18425
- if (!(0, import_node_fs10.existsSync)(root)) return [];
19329
+ if (!(0, import_node_fs11.existsSync)(root)) return [];
18426
19330
  const files = [];
18427
19331
  for (const filePath of listJsonlFilesRecursive(root, 5)) {
18428
19332
  const stat2 = statIfReadable(filePath);
@@ -18445,7 +19349,7 @@ function listSessionFiles(agent) {
18445
19349
  }
18446
19350
  function readDirectoryNames(dir) {
18447
19351
  try {
18448
- return (0, import_node_fs10.readdirSync)(dir);
19352
+ return (0, import_node_fs11.readdirSync)(dir);
18449
19353
  } catch {
18450
19354
  return [];
18451
19355
  }
@@ -18456,12 +19360,12 @@ function listJsonlFilesRecursive(root, maxDepth) {
18456
19360
  if (depth > maxDepth) return;
18457
19361
  let entries;
18458
19362
  try {
18459
- entries = (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true });
19363
+ entries = (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true });
18460
19364
  } catch {
18461
19365
  return;
18462
19366
  }
18463
19367
  for (const entry of entries) {
18464
- const fullPath = (0, import_node_path12.join)(dir, entry.name);
19368
+ const fullPath = (0, import_node_path13.join)(dir, entry.name);
18465
19369
  if (entry.isDirectory()) {
18466
19370
  visit(fullPath, depth + 1);
18467
19371
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
@@ -18474,7 +19378,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
18474
19378
  }
18475
19379
  function statIfReadable(filePath) {
18476
19380
  try {
18477
- return (0, import_node_fs10.statSync)(filePath);
19381
+ return (0, import_node_fs11.statSync)(filePath);
18478
19382
  } catch {
18479
19383
  return null;
18480
19384
  }
@@ -18489,15 +19393,15 @@ function newestSessionFile(agent) {
18489
19393
  return newest;
18490
19394
  }
18491
19395
  function sessionIdFromClaudeFilePath(filePath) {
18492
- return (0, import_node_path12.basename)(filePath, ".jsonl");
19396
+ return (0, import_node_path13.basename)(filePath, ".jsonl");
18493
19397
  }
18494
19398
  function sessionIdFromCodexFilePath(filePath) {
18495
- const match = (0, import_node_path12.basename)(filePath, ".jsonl").match(UUID_IN_TEXT_RE);
19399
+ const match = (0, import_node_path13.basename)(filePath, ".jsonl").match(UUID_IN_TEXT_RE);
18496
19400
  return match?.[0] ?? null;
18497
19401
  }
18498
19402
  function readCodexSessionId(filePath) {
18499
19403
  try {
18500
- for (const line of normalizedJsonLines((0, import_node_fs10.readFileSync)(filePath)).slice(
19404
+ for (const line of normalizedJsonLines((0, import_node_fs11.readFileSync)(filePath)).slice(
18501
19405
  0,
18502
19406
  20
18503
19407
  )) {
@@ -18728,7 +19632,7 @@ async function uploadPayload(path, payload) {
18728
19632
  return await http.post(path, payload);
18729
19633
  }
18730
19634
  async function uploadChunkedSessions(sessions, options) {
18731
- const uploadId = (0, import_node_crypto3.randomUUID)();
19635
+ const uploadId = (0, import_node_crypto4.randomUUID)();
18732
19636
  for (const session of sessions) {
18733
19637
  const bytes = Buffer.from(session.encodedContent, "base64");
18734
19638
  const chunks = [];
@@ -18774,25 +19678,25 @@ async function uploadChunkedSessions(sessions, options) {
18774
19678
  }
18775
19679
  async function handleSessionsSend(options) {
18776
19680
  if (options.file) {
18777
- const filePath = (0, import_node_path12.resolve)(options.file);
18778
- if (!(0, import_node_fs10.existsSync)(filePath)) {
19681
+ const filePath = (0, import_node_path13.resolve)(options.file);
19682
+ if (!(0, import_node_fs11.existsSync)(filePath)) {
18779
19683
  throw new Error(`File not found: ${options.file}`);
18780
19684
  }
18781
19685
  const response2 = await uploadPayload("/api/v2/cli/send-session", {
18782
- file: (0, import_node_fs10.readFileSync)(filePath).toString("base64"),
18783
- filename: (0, import_node_path12.basename)(filePath)
19686
+ file: (0, import_node_fs11.readFileSync)(filePath).toString("base64"),
19687
+ filename: (0, import_node_path13.basename)(filePath)
18784
19688
  });
18785
19689
  printCommandEnvelope(
18786
19690
  {
18787
19691
  ...response2,
18788
19692
  ok: true,
18789
- filename: (0, import_node_path12.basename)(filePath),
19693
+ filename: (0, import_node_path13.basename)(filePath),
18790
19694
  render: {
18791
19695
  sections: [
18792
19696
  {
18793
19697
  title: "sessions send",
18794
19698
  lines: [
18795
- `File '${(0, import_node_path12.basename)(filePath)}' uploaded to #internal-reports.`
19699
+ `File '${(0, import_node_path13.basename)(filePath)}' uploaded to #internal-reports.`
18796
19700
  ]
18797
19701
  }
18798
19702
  ]
@@ -18809,7 +19713,7 @@ async function handleSessionsSend(options) {
18809
19713
  agent: options.agent
18810
19714
  });
18811
19715
  const built = targets.map((target) => {
18812
- const upload = buildSessionUploadContent((0, import_node_fs10.readFileSync)(target.filePath));
19716
+ const upload = buildSessionUploadContent((0, import_node_fs11.readFileSync)(target.filePath));
18813
19717
  return { ...target, ...upload };
18814
19718
  });
18815
19719
  if (built.some((session) => session.needsChunking)) {
@@ -18873,28 +19777,28 @@ function fallbackViewerAssets() {
18873
19777
  };
18874
19778
  }
18875
19779
  function loadViewerAssets() {
18876
- const cliEntry = process.argv[1]?.trim() ? (0, import_node_path12.resolve)(process.argv[1]) : null;
19780
+ const cliEntry = process.argv[1]?.trim() ? (0, import_node_path13.resolve)(process.argv[1]) : null;
18877
19781
  const candidateRoots2 = [
18878
19782
  ...cliEntry ? [
18879
- (0, import_node_path12.join)((0, import_node_path12.dirname)((0, import_node_path12.dirname)(cliEntry)), "viewer"),
18880
- (0, import_node_path12.join)(
18881
- (0, import_node_path12.dirname)((0, import_node_path12.dirname)((0, import_node_path12.dirname)(cliEntry))),
19783
+ (0, import_node_path13.join)((0, import_node_path13.dirname)((0, import_node_path13.dirname)(cliEntry)), "viewer"),
19784
+ (0, import_node_path13.join)(
19785
+ (0, import_node_path13.dirname)((0, import_node_path13.dirname)((0, import_node_path13.dirname)(cliEntry))),
18882
19786
  "src",
18883
19787
  "lib",
18884
19788
  "cli",
18885
19789
  "viewer"
18886
19790
  )
18887
19791
  ] : [],
18888
- (0, import_node_path12.join)(process.cwd(), "src", "lib", "cli", "viewer")
19792
+ (0, import_node_path13.join)(process.cwd(), "src", "lib", "cli", "viewer")
18889
19793
  ];
18890
19794
  for (const root of candidateRoots2) {
18891
19795
  try {
18892
- const cssPath = (0, import_node_path12.join)(root, "viewer.css");
18893
- const jsPath = (0, import_node_path12.join)(root, "viewer.js");
18894
- if (!(0, import_node_fs10.existsSync)(cssPath) || !(0, import_node_fs10.existsSync)(jsPath)) continue;
19796
+ const cssPath = (0, import_node_path13.join)(root, "viewer.css");
19797
+ const jsPath = (0, import_node_path13.join)(root, "viewer.js");
19798
+ if (!(0, import_node_fs11.existsSync)(cssPath) || !(0, import_node_fs11.existsSync)(jsPath)) continue;
18895
19799
  return {
18896
- css: (0, import_node_fs10.readFileSync)(cssPath, "utf8"),
18897
- js: (0, import_node_fs10.readFileSync)(jsPath, "utf8")
19800
+ css: (0, import_node_fs11.readFileSync)(cssPath, "utf8"),
19801
+ js: (0, import_node_fs11.readFileSync)(jsPath, "utf8")
18898
19802
  };
18899
19803
  } catch {
18900
19804
  continue;
@@ -18918,21 +19822,21 @@ async function handleSessionsRender(options) {
18918
19822
  currentSession: options.currentSession,
18919
19823
  agent: options.agent
18920
19824
  });
18921
- let outputPath = options.output ? (0, import_node_path12.resolve)(options.output) : "";
19825
+ let outputPath = options.output ? (0, import_node_path13.resolve)(options.output) : "";
18922
19826
  if (!outputPath) {
18923
- const outputDir = (0, import_node_path12.join)(process.cwd(), "deepline", "data");
18924
- (0, import_node_fs10.mkdirSync)(outputDir, { recursive: true });
18925
- outputPath = (0, import_node_path12.join)(
19827
+ const outputDir = (0, import_node_path13.join)(process.cwd(), "deepline", "data");
19828
+ (0, import_node_fs11.mkdirSync)(outputDir, { recursive: true });
19829
+ outputPath = (0, import_node_path13.join)(
18926
19830
  outputDir,
18927
19831
  targets.length > 1 ? "session-viewer.html" : `session-${targets[0]?.sessionId}.html`
18928
19832
  );
18929
19833
  } else {
18930
- (0, import_node_fs10.mkdirSync)((0, import_node_path12.dirname)(outputPath), { recursive: true });
19834
+ (0, import_node_fs11.mkdirSync)((0, import_node_path13.dirname)(outputPath), { recursive: true });
18931
19835
  }
18932
19836
  const sessions = targets.map((target) => ({
18933
19837
  label: target.label,
18934
19838
  events: parsePreparedEvents(
18935
- prepareSessionBuffer((0, import_node_fs10.readFileSync)(target.filePath))
19839
+ prepareSessionBuffer((0, import_node_fs11.readFileSync)(target.filePath))
18936
19840
  )
18937
19841
  }));
18938
19842
  const { css, js } = loadViewerAssets();
@@ -18955,7 +19859,7 @@ ${refreshMeta}
18955
19859
  <script>${js}</script>
18956
19860
  </body>
18957
19861
  </html>`;
18958
- (0, import_node_fs10.writeFileSync)(outputPath, html, "utf8");
19862
+ (0, import_node_fs11.writeFileSync)(outputPath, html, "utf8");
18959
19863
  printCommandEnvelope(
18960
19864
  {
18961
19865
  ok: true,
@@ -19939,8 +20843,8 @@ Examples:
19939
20843
  }
19940
20844
 
19941
20845
  // src/cli/commands/quickstart.ts
19942
- var import_node_child_process = require("child_process");
19943
- var import_node_crypto4 = require("crypto");
20846
+ var import_node_child_process2 = require("child_process");
20847
+ var import_node_crypto5 = require("crypto");
19944
20848
  var import_node_http = require("http");
19945
20849
  var EXIT_OK2 = 0;
19946
20850
  var EXIT_AUTH2 = 1;
@@ -19952,7 +20856,7 @@ function shellQuote(arg) {
19952
20856
  }
19953
20857
  function hasClaudeBinary() {
19954
20858
  try {
19955
- const result = (0, import_node_child_process.spawnSync)("claude", ["--version"], {
20859
+ const result = (0, import_node_child_process2.spawnSync)("claude", ["--version"], {
19956
20860
  stdio: "ignore",
19957
20861
  shell: process.platform === "win32"
19958
20862
  });
@@ -19962,17 +20866,17 @@ function hasClaudeBinary() {
19962
20866
  }
19963
20867
  }
19964
20868
  function launchClaude(prompt) {
19965
- return new Promise((resolve13) => {
19966
- const child = (0, import_node_child_process.spawn)("claude", [prompt], {
20869
+ return new Promise((resolve14) => {
20870
+ const child = (0, import_node_child_process2.spawn)("claude", [prompt], {
19967
20871
  stdio: "inherit",
19968
20872
  shell: process.platform === "win32"
19969
20873
  });
19970
- child.on("error", () => resolve13(EXIT_SERVER3));
19971
- child.on("close", (status) => resolve13(status ?? EXIT_OK2));
20874
+ child.on("error", () => resolve14(EXIT_SERVER3));
20875
+ child.on("close", (status) => resolve14(status ?? EXIT_OK2));
19972
20876
  });
19973
20877
  }
19974
20878
  function readBody(req) {
19975
- return new Promise((resolve13, reject) => {
20879
+ return new Promise((resolve14, reject) => {
19976
20880
  let raw = "";
19977
20881
  req.setEncoding("utf8");
19978
20882
  req.on("data", (chunk) => {
@@ -19982,7 +20886,7 @@ function readBody(req) {
19982
20886
  req.destroy();
19983
20887
  }
19984
20888
  });
19985
- req.on("end", () => resolve13(raw));
20889
+ req.on("end", () => resolve14(raw));
19986
20890
  req.on("error", reject);
19987
20891
  });
19988
20892
  }
@@ -20037,7 +20941,7 @@ function startCallbackServer(input2) {
20037
20941
  writeJson(res, 400, { error: "Invalid request body." });
20038
20942
  });
20039
20943
  });
20040
- return new Promise((resolve13, reject) => {
20944
+ return new Promise((resolve14, reject) => {
20041
20945
  server.once("error", reject);
20042
20946
  server.listen(0, "127.0.0.1", () => {
20043
20947
  const address = server.address();
@@ -20045,7 +20949,7 @@ function startCallbackServer(input2) {
20045
20949
  reject(new Error("Failed to bind quickstart callback server."));
20046
20950
  return;
20047
20951
  }
20048
- resolve13({ server, port: address.port });
20952
+ resolve14({ server, port: address.port });
20049
20953
  });
20050
20954
  });
20051
20955
  }
@@ -20069,10 +20973,10 @@ async function handleQuickstart(options) {
20069
20973
  return EXIT_AUTH2;
20070
20974
  }
20071
20975
  }
20072
- const state = (0, import_node_crypto4.randomBytes)(32).toString("hex");
20976
+ const state = (0, import_node_crypto5.randomBytes)(32).toString("hex");
20073
20977
  let resolveSelection;
20074
- const selectionPromise = new Promise((resolve13) => {
20075
- resolveSelection = resolve13;
20978
+ const selectionPromise = new Promise((resolve14) => {
20979
+ resolveSelection = resolve14;
20076
20980
  });
20077
20981
  let callback;
20078
20982
  try {
@@ -20211,7 +21115,7 @@ async function readHiddenLine(prompt, streams = {}) {
20211
21115
  }
20212
21116
  let value = "";
20213
21117
  inputStream.resume();
20214
- return await new Promise((resolve13, reject) => {
21118
+ return await new Promise((resolve14, reject) => {
20215
21119
  let settled = false;
20216
21120
  const cleanup = () => {
20217
21121
  inputStream.off("data", onData);
@@ -20229,7 +21133,7 @@ async function readHiddenLine(prompt, streams = {}) {
20229
21133
  settled = true;
20230
21134
  outputStream.write("\n");
20231
21135
  cleanup();
20232
- resolve13(line);
21136
+ resolve14(line);
20233
21137
  };
20234
21138
  const fail = (error) => {
20235
21139
  if (settled) return;
@@ -20400,9 +21304,9 @@ Examples:
20400
21304
  }
20401
21305
 
20402
21306
  // src/cli/commands/switch.ts
20403
- var import_node_fs11 = require("fs");
20404
- var import_node_os9 = require("os");
20405
- var import_node_path13 = require("path");
21307
+ var import_node_fs12 = require("fs");
21308
+ var import_node_os10 = require("os");
21309
+ var import_node_path14 = require("path");
20406
21310
  function hostSlugFromBaseUrl(baseUrl) {
20407
21311
  try {
20408
21312
  const url = new URL(baseUrl);
@@ -20422,8 +21326,8 @@ function resolveConfigScope() {
20422
21326
  return hostSlugFromBaseUrl(autoDetectBaseUrl());
20423
21327
  }
20424
21328
  function activeFamilyPath() {
20425
- const home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os9.homedir)();
20426
- return (0, import_node_path13.join)(
21329
+ const home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os10.homedir)();
21330
+ return (0, import_node_path14.join)(
20427
21331
  home,
20428
21332
  ".local",
20429
21333
  "deepline",
@@ -20435,15 +21339,15 @@ function activeFamilyPath() {
20435
21339
  function readActiveFamily() {
20436
21340
  const path = activeFamilyPath();
20437
21341
  try {
20438
- return (0, import_node_fs11.readFileSync)(path, "utf-8").trim() || "sdk";
21342
+ return (0, import_node_fs12.readFileSync)(path, "utf-8").trim() || "sdk";
20439
21343
  } catch {
20440
21344
  return "sdk";
20441
21345
  }
20442
21346
  }
20443
21347
  function writeActiveFamily(family) {
20444
21348
  const path = activeFamilyPath();
20445
- (0, import_node_fs11.mkdirSync)((0, import_node_path13.dirname)(path), { recursive: true });
20446
- (0, import_node_fs11.writeFileSync)(path, `${family}
21349
+ (0, import_node_fs12.mkdirSync)((0, import_node_path14.dirname)(path), { recursive: true });
21350
+ (0, import_node_fs12.writeFileSync)(path, `${family}
20447
21351
  `, "utf-8");
20448
21352
  return path;
20449
21353
  }
@@ -20460,7 +21364,7 @@ function handleSwitch(action, options) {
20460
21364
  ok: true,
20461
21365
  active_family: activeFamily,
20462
21366
  active_family_path: path,
20463
- active_family_file_exists: (0, import_node_fs11.existsSync)(path),
21367
+ active_family_file_exists: (0, import_node_fs12.existsSync)(path),
20464
21368
  render: {
20465
21369
  sections: [
20466
21370
  {
@@ -20560,14 +21464,14 @@ Examples:
20560
21464
 
20561
21465
  // src/cli/commands/tools.ts
20562
21466
  var import_commander2 = require("commander");
21467
+ var import_node_fs14 = require("fs");
21468
+ var import_node_os12 = require("os");
21469
+ var import_node_path16 = require("path");
21470
+
21471
+ // src/tool-output.ts
20563
21472
  var import_node_fs13 = require("fs");
20564
21473
  var import_node_os11 = require("os");
20565
21474
  var import_node_path15 = require("path");
20566
-
20567
- // src/tool-output.ts
20568
- var import_node_fs12 = require("fs");
20569
- var import_node_os10 = require("os");
20570
- var import_node_path14 = require("path");
20571
21475
  function isPlainObject(value) {
20572
21476
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
20573
21477
  }
@@ -20694,19 +21598,19 @@ function projectRowOutput(conversion) {
20694
21598
  };
20695
21599
  }
20696
21600
  function ensureOutputDir() {
20697
- const outputDir = (0, import_node_path14.join)((0, import_node_os10.homedir)(), ".local", "share", "deepline", "data");
20698
- (0, import_node_fs12.mkdirSync)(outputDir, { recursive: true });
21601
+ const outputDir = (0, import_node_path15.join)((0, import_node_os11.homedir)(), ".local", "share", "deepline", "data");
21602
+ (0, import_node_fs13.mkdirSync)(outputDir, { recursive: true });
20699
21603
  return outputDir;
20700
21604
  }
20701
21605
  function writeJsonOutputFile(payload, stem) {
20702
21606
  const outputDir = ensureOutputDir();
20703
- const outputPath = (0, import_node_path14.join)(outputDir, `${stem}_${Date.now()}.json`);
20704
- (0, import_node_fs12.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
21607
+ const outputPath = (0, import_node_path15.join)(outputDir, `${stem}_${Date.now()}.json`);
21608
+ (0, import_node_fs13.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
20705
21609
  return outputPath;
20706
21610
  }
20707
21611
  function writeCsvOutputFile(rows, stem, options) {
20708
- const outputPath = options?.outPath ? options.outPath : (0, import_node_path14.join)(ensureOutputDir(), `${stem}_${Date.now()}.csv`);
20709
- (0, import_node_fs12.mkdirSync)((0, import_node_path14.dirname)(outputPath), { recursive: true });
21612
+ const outputPath = options?.outPath ? options.outPath : (0, import_node_path15.join)(ensureOutputDir(), `${stem}_${Date.now()}.csv`);
21613
+ (0, import_node_fs13.mkdirSync)((0, import_node_path15.dirname)(outputPath), { recursive: true });
20710
21614
  const columns = columnsForRows(rows);
20711
21615
  const escapeCell = (value) => {
20712
21616
  const normalized = value == null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
@@ -20715,19 +21619,19 @@ function writeCsvOutputFile(rows, stem, options) {
20715
21619
  }
20716
21620
  return normalized;
20717
21621
  };
20718
- const fd = (0, import_node_fs12.openSync)(outputPath, "w");
21622
+ const fd = (0, import_node_fs13.openSync)(outputPath, "w");
20719
21623
  try {
20720
- (0, import_node_fs12.writeSync)(fd, `${columns.map(escapeCell).join(",")}
21624
+ (0, import_node_fs13.writeSync)(fd, `${columns.map(escapeCell).join(",")}
20721
21625
  `);
20722
21626
  for (const row of rows) {
20723
- (0, import_node_fs12.writeSync)(
21627
+ (0, import_node_fs13.writeSync)(
20724
21628
  fd,
20725
21629
  `${columns.map((column) => escapeCell(row[column])).join(",")}
20726
21630
  `
20727
21631
  );
20728
21632
  }
20729
21633
  } finally {
20730
- (0, import_node_fs12.closeSync)(fd);
21634
+ (0, import_node_fs13.closeSync)(fd);
20731
21635
  }
20732
21636
  const previewRows = rows.slice(0, 5);
20733
21637
  const previewColumns = columns.slice(0, 5);
@@ -21872,11 +22776,11 @@ function normalizeOutputFormat(raw) {
21872
22776
  }
21873
22777
  function resolveAtFilePath(rawPath) {
21874
22778
  const trimmed = rawPath.trim();
21875
- const resolved = (0, import_node_path15.resolve)(trimmed);
21876
- if ((0, import_node_fs13.existsSync)(resolved)) return resolved;
22779
+ const resolved = (0, import_node_path16.resolve)(trimmed);
22780
+ if ((0, import_node_fs14.existsSync)(resolved)) return resolved;
21877
22781
  if (process.platform !== "win32" && trimmed.includes("\\")) {
21878
- const normalized = (0, import_node_path15.resolve)(trimmed.replace(/\\/g, "/"));
21879
- if ((0, import_node_fs13.existsSync)(normalized)) return normalized;
22782
+ const normalized = (0, import_node_path16.resolve)(trimmed.replace(/\\/g, "/"));
22783
+ if ((0, import_node_fs14.existsSync)(normalized)) return normalized;
21880
22784
  }
21881
22785
  return resolved;
21882
22786
  }
@@ -21887,7 +22791,7 @@ function readJsonArgument(raw, flagName) {
21887
22791
  throw new Error(`Invalid ${flagName} value: empty @file path.`);
21888
22792
  }
21889
22793
  try {
21890
- return (0, import_node_fs13.readFileSync)(resolveAtFilePath(filePath), "utf8").replace(
22794
+ return (0, import_node_fs14.readFileSync)(resolveAtFilePath(filePath), "utf8").replace(
21891
22795
  /^\uFEFF/,
21892
22796
  ""
21893
22797
  );
@@ -21964,7 +22868,7 @@ function parseExecuteOptions(args) {
21964
22868
  continue;
21965
22869
  }
21966
22870
  if ((arg === "--out" || arg === "-o") && args[index + 1]) {
21967
- outPath = (0, import_node_path15.resolve)(args[++index]);
22871
+ outPath = (0, import_node_path16.resolve)(args[++index]);
21968
22872
  continue;
21969
22873
  }
21970
22874
  throw new Error(`Unknown option: ${arg}`);
@@ -21994,9 +22898,9 @@ function starterScriptJson(script) {
21994
22898
  function seedToolListScript(input2) {
21995
22899
  const stem = safeFileStem(input2.toolId);
21996
22900
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
21997
- const scriptDir = (0, import_node_fs13.mkdtempSync)((0, import_node_path15.join)((0, import_node_os11.tmpdir)(), "deepline-workflow-seed-"));
21998
- (0, import_node_fs13.chmodSync)(scriptDir, 448);
21999
- const scriptPath = (0, import_node_path15.join)(scriptDir, fileName);
22901
+ const scriptDir = (0, import_node_fs14.mkdtempSync)((0, import_node_path16.join)((0, import_node_os12.tmpdir)(), "deepline-workflow-seed-"));
22902
+ (0, import_node_fs14.chmodSync)(scriptDir, 448);
22903
+ const scriptPath = (0, import_node_path16.join)(scriptDir, fileName);
22000
22904
  const projectDir = `deepline/projects/${stem}-workflow`;
22001
22905
  const playName = `${stem}-workflow`;
22002
22906
  const sampleRows = input2.rows.length > 0 ? `${JSON.stringify(input2.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
@@ -22039,7 +22943,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
22039
22943
  description: ${JSON.stringify(`Seed ${input2.toolId} rows into a Deepline workflow-ready dataset.`)},
22040
22944
  });
22041
22945
  `;
22042
- (0, import_node_fs13.writeFileSync)(scriptPath, script, { encoding: "utf-8", mode: 384 });
22946
+ (0, import_node_fs14.writeFileSync)(scriptPath, script, { encoding: "utf-8", mode: 384 });
22043
22947
  return {
22044
22948
  path: scriptPath,
22045
22949
  sourceCode: script,
@@ -22370,10 +23274,10 @@ async function executeTool(args) {
22370
23274
 
22371
23275
  // src/cli/commands/workflow.ts
22372
23276
  var import_promises4 = require("fs/promises");
22373
- var import_node_path16 = require("path");
23277
+ var import_node_path17 = require("path");
22374
23278
 
22375
23279
  // src/cli/workflow-to-play.ts
22376
- var import_node_crypto5 = require("crypto");
23280
+ var import_node_crypto6 = require("crypto");
22377
23281
 
22378
23282
  // ../shared_libs/plays/secret-guardrails.ts
22379
23283
  var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
@@ -22516,7 +23420,7 @@ function sanitizePlayNameSegment(value) {
22516
23420
  }
22517
23421
  function deriveWorkflowPlayName(workflowName) {
22518
23422
  const base = sanitizePlayNameSegment(workflowName) || "workflow";
22519
- const suffix = (0, import_node_crypto5.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
23423
+ const suffix = (0, import_node_crypto6.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
22520
23424
  const reserved = suffix.length + 1;
22521
23425
  const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
22522
23426
  let name = `${base.slice(0, allowedBase)}_${suffix}`;
@@ -22614,7 +23518,7 @@ function readStatus(payload) {
22614
23518
  }
22615
23519
  async function readJsonOption(payload, file) {
22616
23520
  if (file) {
22617
- const raw = await (0, import_promises4.readFile)((0, import_node_path16.resolve)(file), "utf8");
23521
+ const raw = await (0, import_promises4.readFile)((0, import_node_path17.resolve)(file), "utf8");
22618
23522
  return JSON.parse(raw);
22619
23523
  }
22620
23524
  if (payload) {
@@ -22648,8 +23552,8 @@ async function transformOne(api, workflowId, outDir, publish) {
22648
23552
  revision.config,
22649
23553
  { workflowName: workflow.name, version: revision.version }
22650
23554
  );
22651
- const file = (0, import_node_path16.join)((0, import_node_path16.resolve)(outDir), `${compiled.playName}.play.ts`);
22652
- await (0, import_promises4.mkdir)((0, import_node_path16.dirname)(file), { recursive: true });
23555
+ const file = (0, import_node_path17.join)((0, import_node_path17.resolve)(outDir), `${compiled.playName}.play.ts`);
23556
+ await (0, import_promises4.mkdir)((0, import_node_path17.dirname)(file), { recursive: true });
22653
23557
  await (0, import_promises4.writeFile)(file, compiled.sourceCode, "utf8");
22654
23558
  let published = false;
22655
23559
  if (publish) {
@@ -22895,16 +23799,16 @@ Notes:
22895
23799
  }
22896
23800
 
22897
23801
  // src/cli/commands/update.ts
23802
+ var import_node_child_process4 = require("child_process");
23803
+ var import_node_fs16 = require("fs");
23804
+ var import_node_os13 = require("os");
23805
+ var import_node_path19 = require("path");
23806
+
23807
+ // src/cli/skills-sync.ts
22898
23808
  var import_node_child_process3 = require("child_process");
22899
23809
  var import_node_fs15 = require("fs");
22900
- var import_node_os12 = require("os");
22901
23810
  var import_node_path18 = require("path");
22902
23811
 
22903
- // src/cli/skills-sync.ts
22904
- var import_node_child_process2 = require("child_process");
22905
- var import_node_fs14 = require("fs");
22906
- var import_node_path17 = require("path");
22907
-
22908
23812
  // ../shared_libs/cli/install-commands.json
22909
23813
  var install_commands_default = {
22910
23814
  skills: {
@@ -23022,38 +23926,38 @@ function activePluginSkillsDir() {
23022
23926
  return "";
23023
23927
  }
23024
23928
  const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
23025
- return dir && (0, import_node_fs14.existsSync)(dir) ? dir : "";
23929
+ return dir && (0, import_node_fs15.existsSync)(dir) ? dir : "";
23026
23930
  }
23027
23931
  function readPluginSkillsVersion() {
23028
23932
  const dir = activePluginSkillsDir();
23029
23933
  if (!dir) return "";
23030
23934
  try {
23031
- return (0, import_node_fs14.readFileSync)((0, import_node_path17.join)(dir, ".version"), "utf-8").trim();
23935
+ return (0, import_node_fs15.readFileSync)((0, import_node_path18.join)(dir, ".version"), "utf-8").trim();
23032
23936
  } catch {
23033
23937
  return "";
23034
23938
  }
23035
23939
  }
23036
23940
  function sdkSkillsVersionPath(baseUrl) {
23037
- return (0, import_node_path17.join)(sdkCliStateDirPath(baseUrl), "skills-version");
23941
+ return (0, import_node_path18.join)(sdkCliStateDirPath(baseUrl), "skills-version");
23038
23942
  }
23039
23943
  function legacySdkSkillsVersionPath(baseUrl) {
23040
- return (0, import_node_path17.join)((0, import_node_path17.dirname)(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
23944
+ return (0, import_node_path18.join)((0, import_node_path18.dirname)(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
23041
23945
  }
23042
23946
  function readSdkSkillsLocalVersion(baseUrl) {
23043
23947
  const pluginVersion = readPluginSkillsVersion();
23044
23948
  if (pluginVersion) return pluginVersion;
23045
- const path = (0, import_node_fs14.existsSync)(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
23046
- if (!(0, import_node_fs14.existsSync)(path)) return "";
23949
+ const path = (0, import_node_fs15.existsSync)(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
23950
+ if (!(0, import_node_fs15.existsSync)(path)) return "";
23047
23951
  try {
23048
- return (0, import_node_fs14.readFileSync)(path, "utf-8").trim();
23952
+ return (0, import_node_fs15.readFileSync)(path, "utf-8").trim();
23049
23953
  } catch {
23050
23954
  return "";
23051
23955
  }
23052
23956
  }
23053
23957
  function writeLocalSkillsVersion(baseUrl, version) {
23054
23958
  const path = sdkSkillsVersionPath(baseUrl);
23055
- (0, import_node_fs14.mkdirSync)((0, import_node_path17.dirname)(path), { recursive: true });
23056
- (0, import_node_fs14.writeFileSync)(path, `${version}
23959
+ (0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(path), { recursive: true });
23960
+ (0, import_node_fs15.writeFileSync)(path, `${version}
23057
23961
  `, "utf-8");
23058
23962
  }
23059
23963
  function sortedUniqueSkillNames(names) {
@@ -23121,7 +24025,7 @@ function buildBunxSkillsInstallArgs(baseUrl, skillNames) {
23121
24025
  });
23122
24026
  }
23123
24027
  function hasCommand(command) {
23124
- const result = (0, import_node_child_process2.spawnSync)(command, ["--version"], {
24028
+ const result = (0, import_node_child_process3.spawnSync)(command, ["--version"], {
23125
24029
  stdio: "ignore",
23126
24030
  shell: process.platform === "win32"
23127
24031
  });
@@ -23151,8 +24055,8 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
23151
24055
  return [npxInstall];
23152
24056
  }
23153
24057
  function runOneSkillsInstall(install) {
23154
- return new Promise((resolve13) => {
23155
- const child = (0, import_node_child_process2.spawn)(install.command, install.args, {
24058
+ return new Promise((resolve14) => {
24059
+ const child = (0, import_node_child_process3.spawn)(install.command, install.args, {
23156
24060
  stdio: ["ignore", "ignore", "pipe"],
23157
24061
  env: process.env
23158
24062
  });
@@ -23161,7 +24065,7 @@ function runOneSkillsInstall(install) {
23161
24065
  stderr += chunk.toString("utf-8");
23162
24066
  });
23163
24067
  child.on("error", (error) => {
23164
- resolve13({
24068
+ resolve14({
23165
24069
  ok: false,
23166
24070
  detail: `failed to start ${install.command}: ${error.message}`,
23167
24071
  manualCommand: install.manualCommand
@@ -23169,11 +24073,11 @@ function runOneSkillsInstall(install) {
23169
24073
  });
23170
24074
  child.on("close", (code) => {
23171
24075
  if (code === 0) {
23172
- resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
24076
+ resolve14({ ok: true, detail: "", manualCommand: install.manualCommand });
23173
24077
  return;
23174
24078
  }
23175
24079
  const detail = stderr.trim();
23176
- resolve13({
24080
+ resolve14({
23177
24081
  ok: false,
23178
24082
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
23179
24083
  manualCommand: install.manualCommand
@@ -23236,7 +24140,7 @@ function runLegacySkillsCleanup() {
23236
24140
  }
23237
24141
  ];
23238
24142
  for (const candidate of candidates) {
23239
- const result = (0, import_node_child_process2.spawnSync)(candidate.command, candidate.args, {
24143
+ const result = (0, import_node_child_process3.spawnSync)(candidate.command, candidate.args, {
23240
24144
  stdio: "ignore",
23241
24145
  shell: process.platform === "win32"
23242
24146
  });
@@ -23330,11 +24234,11 @@ function sidecarStateDir(input2) {
23330
24234
  if (!scope || scope.includes("/") || scope.includes("\\")) {
23331
24235
  return null;
23332
24236
  }
23333
- return (0, import_node_path18.join)(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
24237
+ return (0, import_node_path19.join)(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
23334
24238
  }
23335
24239
  function readOptionalText(path) {
23336
24240
  try {
23337
- return (0, import_node_fs15.readFileSync)(path, "utf8").trim();
24241
+ return (0, import_node_fs16.readFileSync)(path, "utf8").trim();
23338
24242
  } catch {
23339
24243
  return "";
23340
24244
  }
@@ -23342,26 +24246,26 @@ function readOptionalText(path) {
23342
24246
  function resolvePythonSidecarUpdatePlan(options) {
23343
24247
  const stateDir = sidecarStateDir(options);
23344
24248
  if (!stateDir) return null;
23345
- const relativeEntrypoint = (0, import_node_path18.relative)(
23346
- (0, import_node_path18.resolve)(stateDir),
23347
- (0, import_node_path18.resolve)(options.entrypoint)
24249
+ const relativeEntrypoint = (0, import_node_path19.relative)(
24250
+ (0, import_node_path19.resolve)(stateDir),
24251
+ (0, import_node_path19.resolve)(options.entrypoint)
23348
24252
  );
23349
- if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || (0, import_node_path18.isAbsolute)(relativeEntrypoint)) {
24253
+ if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || (0, import_node_path19.isAbsolute)(relativeEntrypoint)) {
23350
24254
  return null;
23351
24255
  }
23352
- const installMethod = readOptionalText((0, import_node_path18.join)(stateDir, ".install-method"));
24256
+ const installMethod = readOptionalText((0, import_node_path19.join)(stateDir, ".install-method"));
23353
24257
  if (installMethod !== "python-sidecar") return null;
23354
24258
  const scope = options.env.DEEPLINE_CONFIG_SCOPE?.trim() || "";
23355
24259
  const hostUrl = options.env.DEEPLINE_HOST_URL?.trim() || "";
23356
- const nodeBin = readOptionalText((0, import_node_path18.join)(stateDir, ".node-bin")) || process.execPath;
23357
- const sidecarPath = readOptionalText((0, import_node_path18.join)(stateDir, ".command-path")) || (0, import_node_path18.join)(
24260
+ const nodeBin = readOptionalText((0, import_node_path19.join)(stateDir, ".node-bin")) || process.execPath;
24261
+ const sidecarPath = readOptionalText((0, import_node_path19.join)(stateDir, ".command-path")) || (0, import_node_path19.join)(
23358
24262
  stateDir,
23359
24263
  "bin",
23360
24264
  process.platform === "win32" ? "deepline-sdk.cmd" : "deepline-sdk"
23361
24265
  );
23362
24266
  const packageSpec = options.packageSpec || "deepline@latest";
23363
24267
  const npmCommand = "npm";
23364
- const versionDir = (0, import_node_path18.join)(stateDir, "versions", "<version>");
24268
+ const versionDir = (0, import_node_path19.join)(stateDir, "versions", "<version>");
23365
24269
  const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote4(versionDir)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote4).join(" ")} ${shellQuote4(packageSpec)}`;
23366
24270
  return {
23367
24271
  kind: "python-sidecar",
@@ -23376,12 +24280,12 @@ function resolvePythonSidecarUpdatePlan(options) {
23376
24280
  };
23377
24281
  }
23378
24282
  function findRepoBackedSdkRoot(startPath) {
23379
- let current = (0, import_node_path18.resolve)(startPath);
24283
+ let current = (0, import_node_path19.resolve)(startPath);
23380
24284
  while (true) {
23381
- if ((0, import_node_fs15.existsSync)((0, import_node_path18.join)(current, "sdk", "package.json")) && (0, import_node_fs15.existsSync)((0, import_node_path18.join)(current, "sdk", "bin", "deepline-dev.ts"))) {
24285
+ if ((0, import_node_fs16.existsSync)((0, import_node_path19.join)(current, "sdk", "package.json")) && (0, import_node_fs16.existsSync)((0, import_node_path19.join)(current, "sdk", "bin", "deepline-dev.ts"))) {
23382
24286
  return current;
23383
24287
  }
23384
- const parent = (0, import_node_path18.dirname)(current);
24288
+ const parent = (0, import_node_path19.dirname)(current);
23385
24289
  if (parent === current) return null;
23386
24290
  current = parent;
23387
24291
  }
@@ -23389,9 +24293,9 @@ function findRepoBackedSdkRoot(startPath) {
23389
24293
  function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
23390
24294
  const normalized = (() => {
23391
24295
  try {
23392
- return (0, import_node_fs15.realpathSync)(entrypoint);
24296
+ return (0, import_node_fs16.realpathSync)(entrypoint);
23393
24297
  } catch {
23394
- return (0, import_node_path18.resolve)(entrypoint);
24298
+ return (0, import_node_path19.resolve)(entrypoint);
23395
24299
  }
23396
24300
  })();
23397
24301
  const parts = normalized.split(/[\\/]+/);
@@ -23409,9 +24313,9 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
23409
24313
  }
23410
24314
  function resolveUpdatePlan(options = {}) {
23411
24315
  const env = options.env ?? process.env;
23412
- const homeDir2 = options.homeDir ?? (0, import_node_os12.homedir)();
23413
- const entrypoint = options.entrypoint ?? (process.argv[1] ? (0, import_node_path18.resolve)(process.argv[1]) : "");
23414
- const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path18.dirname)(entrypoint)) : null;
24316
+ const homeDir2 = options.homeDir ?? (0, import_node_os13.homedir)();
24317
+ const entrypoint = options.entrypoint ?? (process.argv[1] ? (0, import_node_path19.resolve)(process.argv[1]) : "");
24318
+ const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path19.dirname)(entrypoint)) : null;
23415
24319
  if (sourceRoot) {
23416
24320
  return {
23417
24321
  kind: "source",
@@ -23449,10 +24353,10 @@ var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
23449
24353
  function autoUpdateFailurePath(plan) {
23450
24354
  if (plan.kind === "source") return null;
23451
24355
  if (plan.kind === "python-sidecar") {
23452
- return (0, import_node_path18.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
24356
+ return (0, import_node_path19.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
23453
24357
  }
23454
- return (0, import_node_path18.join)(
23455
- (0, import_node_os12.homedir)(),
24358
+ return (0, import_node_path19.join)(
24359
+ (0, import_node_os13.homedir)(),
23456
24360
  ".local",
23457
24361
  "deepline",
23458
24362
  "sdk-cli",
@@ -23469,7 +24373,7 @@ function readAutoUpdateFailure(plan) {
23469
24373
  if (!path) return null;
23470
24374
  try {
23471
24375
  const parsed = JSON.parse(
23472
- (0, import_node_fs15.readFileSync)(path, "utf8")
24376
+ (0, import_node_fs16.readFileSync)(path, "utf8")
23473
24377
  );
23474
24378
  if ((parsed.kind === "npm-global" || parsed.kind === "python-sidecar") && typeof parsed.packageSpec === "string" && typeof parsed.failedAt === "string" && typeof parsed.exitCode === "number" && typeof parsed.manualCommand === "string") {
23475
24379
  return parsed;
@@ -23490,8 +24394,8 @@ function writeAutoUpdateFailure(plan, exitCode) {
23490
24394
  manualCommand: plan.manualCommand
23491
24395
  };
23492
24396
  try {
23493
- (0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(path), { recursive: true });
23494
- (0, import_node_fs15.writeFileSync)(path, `${JSON.stringify(marker, null, 2)}
24397
+ (0, import_node_fs16.mkdirSync)((0, import_node_path19.dirname)(path), { recursive: true });
24398
+ (0, import_node_fs16.writeFileSync)(path, `${JSON.stringify(marker, null, 2)}
23495
24399
  `, "utf8");
23496
24400
  } catch {
23497
24401
  }
@@ -23500,7 +24404,7 @@ function clearAutoUpdateFailure(plan) {
23500
24404
  const path = autoUpdateFailurePath(plan);
23501
24405
  if (!path) return;
23502
24406
  try {
23503
- (0, import_node_fs15.unlinkSync)(path);
24407
+ (0, import_node_fs16.unlinkSync)(path);
23504
24408
  } catch {
23505
24409
  }
23506
24410
  }
@@ -23536,7 +24440,7 @@ function safeVersionSegment(value) {
23536
24440
  return /^[0-9A-Za-z._-]+$/.test(normalized) ? normalized : "";
23537
24441
  }
23538
24442
  function entryPathInVersionDir(versionDir) {
23539
- return (0, import_node_path18.join)(
24443
+ return (0, import_node_path19.join)(
23540
24444
  versionDir,
23541
24445
  "node_modules",
23542
24446
  "deepline",
@@ -23546,14 +24450,14 @@ function entryPathInVersionDir(versionDir) {
23546
24450
  );
23547
24451
  }
23548
24452
  function installedPackageVersion(versionDir) {
23549
- const packageJsonPath = (0, import_node_path18.join)(
24453
+ const packageJsonPath = (0, import_node_path19.join)(
23550
24454
  versionDir,
23551
24455
  "node_modules",
23552
24456
  "deepline",
23553
24457
  "package.json"
23554
24458
  );
23555
24459
  try {
23556
- const parsed = JSON.parse((0, import_node_fs15.readFileSync)(packageJsonPath, "utf8"));
24460
+ const parsed = JSON.parse((0, import_node_fs16.readFileSync)(packageJsonPath, "utf8"));
23557
24461
  return typeof parsed.version === "string" ? safeVersionSegment(parsed.version) : "";
23558
24462
  } catch {
23559
24463
  return "";
@@ -23561,7 +24465,7 @@ function installedPackageVersion(versionDir) {
23561
24465
  }
23562
24466
  function runCommand(command, args, env = process.env, options = {}) {
23563
24467
  return new Promise((resolveExitCode) => {
23564
- const child = (0, import_node_child_process3.spawn)(command, args, {
24468
+ const child = (0, import_node_child_process4.spawn)(command, args, {
23565
24469
  stdio: options.stdio === "stderr" ? ["inherit", "pipe", "pipe"] : "inherit",
23566
24470
  shell: process.platform === "win32",
23567
24471
  env
@@ -23585,9 +24489,9 @@ function runCommand(command, args, env = process.env, options = {}) {
23585
24489
  });
23586
24490
  }
23587
24491
  function writeSidecarLauncher(input2) {
23588
- (0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(input2.path), { recursive: true });
24492
+ (0, import_node_fs16.mkdirSync)((0, import_node_path19.dirname)(input2.path), { recursive: true });
23589
24493
  if (process.platform === "win32") {
23590
- (0, import_node_fs15.writeFileSync)(
24494
+ (0, import_node_fs16.writeFileSync)(
23591
24495
  input2.path,
23592
24496
  [
23593
24497
  `@set DEEPLINE_HOST_URL=${input2.hostUrl.replace(/\r?\n/g, "")}`,
@@ -23599,7 +24503,7 @@ function writeSidecarLauncher(input2) {
23599
24503
  );
23600
24504
  return;
23601
24505
  }
23602
- (0, import_node_fs15.writeFileSync)(
24506
+ (0, import_node_fs16.writeFileSync)(
23603
24507
  input2.path,
23604
24508
  [
23605
24509
  "#!/usr/bin/env sh",
@@ -23612,17 +24516,17 @@ function writeSidecarLauncher(input2) {
23612
24516
  );
23613
24517
  }
23614
24518
  async function runPythonSidecarUpdatePlan(plan, options = {}) {
23615
- const versionsDir = (0, import_node_path18.join)(plan.stateDir, "versions");
23616
- const tempDir = (0, import_node_path18.join)(
24519
+ const versionsDir = (0, import_node_path19.join)(plan.stateDir, "versions");
24520
+ const tempDir = (0, import_node_path19.join)(
23617
24521
  versionsDir,
23618
24522
  `.tmp-sdk-update-${process.pid}-${Date.now()}`
23619
24523
  );
23620
- (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
23621
- (0, import_node_fs15.mkdirSync)(tempDir, { recursive: true });
23622
- (0, import_node_fs15.writeFileSync)((0, import_node_path18.join)(tempDir, "package.json"), NPM_SDK_SIDECAR_PACKAGE_JSON);
24524
+ (0, import_node_fs16.rmSync)(tempDir, { recursive: true, force: true });
24525
+ (0, import_node_fs16.mkdirSync)(tempDir, { recursive: true });
24526
+ (0, import_node_fs16.writeFileSync)((0, import_node_path19.join)(tempDir, "package.json"), NPM_SDK_SIDECAR_PACKAGE_JSON);
23623
24527
  const env = {
23624
24528
  ...process.env,
23625
- PATH: `${(0, import_node_path18.dirname)(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
24529
+ PATH: `${(0, import_node_path19.dirname)(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
23626
24530
  };
23627
24531
  const installExitCode = await runCommand(
23628
24532
  plan.npmCommand,
@@ -23637,7 +24541,7 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23637
24541
  options
23638
24542
  );
23639
24543
  if (installExitCode !== 0) {
23640
- (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
24544
+ (0, import_node_fs16.rmSync)(tempDir, { recursive: true, force: true });
23641
24545
  return installExitCode;
23642
24546
  }
23643
24547
  const installedVersion = installedPackageVersion(tempDir);
@@ -23645,19 +24549,19 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23645
24549
  process.stderr.write(
23646
24550
  "Updated Deepline SDK package did not report a version.\n"
23647
24551
  );
23648
- (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
24552
+ (0, import_node_fs16.rmSync)(tempDir, { recursive: true, force: true });
23649
24553
  return 1;
23650
24554
  }
23651
- const finalDir = (0, import_node_path18.join)(versionsDir, installedVersion);
24555
+ const finalDir = (0, import_node_path19.join)(versionsDir, installedVersion);
23652
24556
  const finalEntryPath = entryPathInVersionDir(finalDir);
23653
- if ((0, import_node_fs15.existsSync)(finalEntryPath)) {
23654
- (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
24557
+ if ((0, import_node_fs16.existsSync)(finalEntryPath)) {
24558
+ (0, import_node_fs16.rmSync)(tempDir, { recursive: true, force: true });
23655
24559
  } else {
23656
- (0, import_node_fs15.rmSync)(finalDir, { recursive: true, force: true });
24560
+ (0, import_node_fs16.rmSync)(finalDir, { recursive: true, force: true });
23657
24561
  try {
23658
- (0, import_node_fs15.renameSync)(tempDir, finalDir);
24562
+ (0, import_node_fs16.renameSync)(tempDir, finalDir);
23659
24563
  } catch (error) {
23660
- (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
24564
+ (0, import_node_fs16.rmSync)(tempDir, { recursive: true, force: true });
23661
24565
  process.stderr.write(
23662
24566
  `Failed to publish Deepline SDK sidecar update: ${error.message}
23663
24567
  `
@@ -23665,7 +24569,7 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23665
24569
  return 1;
23666
24570
  }
23667
24571
  }
23668
- if (!(0, import_node_fs15.existsSync)(finalEntryPath)) {
24572
+ if (!(0, import_node_fs16.existsSync)(finalEntryPath)) {
23669
24573
  process.stderr.write(
23670
24574
  `Updated Deepline SDK CLI entrypoint missing: ${finalEntryPath}
23671
24575
  `
@@ -23679,28 +24583,28 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23679
24583
  nodeBin: plan.nodeBin,
23680
24584
  entryPath: finalEntryPath
23681
24585
  });
23682
- (0, import_node_fs15.writeFileSync)(
23683
- (0, import_node_path18.join)(plan.stateDir, ".version"),
24586
+ (0, import_node_fs16.writeFileSync)(
24587
+ (0, import_node_path19.join)(plan.stateDir, ".version"),
23684
24588
  `${installedVersion}
23685
24589
  `,
23686
24590
  "utf8"
23687
24591
  );
23688
- (0, import_node_fs15.writeFileSync)(
23689
- (0, import_node_path18.join)(plan.stateDir, ".install-method"),
24592
+ (0, import_node_fs16.writeFileSync)(
24593
+ (0, import_node_path19.join)(plan.stateDir, ".install-method"),
23690
24594
  "python-sidecar\n",
23691
24595
  "utf8"
23692
24596
  );
23693
- (0, import_node_fs15.writeFileSync)(
23694
- (0, import_node_path18.join)(plan.stateDir, ".command-path"),
24597
+ (0, import_node_fs16.writeFileSync)(
24598
+ (0, import_node_path19.join)(plan.stateDir, ".command-path"),
23695
24599
  `${plan.sidecarPath}
23696
24600
  `,
23697
24601
  "utf8"
23698
24602
  );
23699
- (0, import_node_fs15.writeFileSync)((0, import_node_path18.join)(plan.stateDir, ".runner"), "node\n", "utf8");
23700
- (0, import_node_fs15.writeFileSync)((0, import_node_path18.join)(plan.stateDir, ".node-bin"), `${plan.nodeBin}
24603
+ (0, import_node_fs16.writeFileSync)((0, import_node_path19.join)(plan.stateDir, ".runner"), "node\n", "utf8");
24604
+ (0, import_node_fs16.writeFileSync)((0, import_node_path19.join)(plan.stateDir, ".node-bin"), `${plan.nodeBin}
23701
24605
  `, "utf8");
23702
- (0, import_node_fs15.writeFileSync)(
23703
- (0, import_node_path18.join)(plan.stateDir, ".entry-path"),
24606
+ (0, import_node_fs16.writeFileSync)(
24607
+ (0, import_node_path19.join)(plan.stateDir, ".entry-path"),
23704
24608
  `${finalEntryPath}
23705
24609
  `,
23706
24610
  "utf8"
@@ -23889,7 +24793,7 @@ function unknownCommandNameFromMessage(message) {
23889
24793
  }
23890
24794
 
23891
24795
  // src/cli/self-update.ts
23892
- var import_node_child_process4 = require("child_process");
24796
+ var import_node_child_process5 = require("child_process");
23893
24797
  function envTruthy(name) {
23894
24798
  const value = process.env[name]?.trim().toLowerCase();
23895
24799
  return value === "1" || value === "true" || value === "yes";
@@ -23935,10 +24839,10 @@ function isDowngradeAutoUpdateResponse(response) {
23935
24839
  return compareSemver(target, current) < 0;
23936
24840
  }
23937
24841
  function relaunchCurrentCommand(plan) {
23938
- return new Promise((resolve13) => {
24842
+ return new Promise((resolve14) => {
23939
24843
  const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
23940
24844
  const args = plan.kind === "python-sidecar" ? process.argv.slice(2) : process.argv.slice(1);
23941
- const child = (0, import_node_child_process4.spawn)(command, args, {
24845
+ const child = (0, import_node_child_process5.spawn)(command, args, {
23942
24846
  stdio: "inherit",
23943
24847
  shell: process.platform === "win32",
23944
24848
  env: {
@@ -23951,9 +24855,9 @@ function relaunchCurrentCommand(plan) {
23951
24855
  `Deepline SDK/CLI updated, but relaunch failed: ${error.message}
23952
24856
  `
23953
24857
  );
23954
- resolve13(1);
24858
+ resolve14(1);
23955
24859
  });
23956
- child.on("close", (code) => resolve13(code ?? 1));
24860
+ child.on("close", (code) => resolve14(code ?? 1));
23957
24861
  });
23958
24862
  }
23959
24863
  async function maybeAutoUpdateAndRelaunch(response) {
@@ -24003,7 +24907,7 @@ async function maybeAutoUpdateAndRelaunch(response) {
24003
24907
  }
24004
24908
 
24005
24909
  // src/cli/failure-reporting.ts
24006
- var import_node_os13 = require("os");
24910
+ var import_node_os14 = require("os");
24007
24911
  var FAILURE_REPORT_DISABLE_ENV = "DEEPLINE_DISABLE_FAILURE_REPORTING";
24008
24912
  var REPORT_FAILURE_TIMEOUT_MS = 1e4;
24009
24913
  var MAX_FAILURE_TEXT_CHARS = 4e3;
@@ -24105,12 +25009,12 @@ function isNetworkFailure(error) {
24105
25009
  }
24106
25010
  function buildEnvironmentContext() {
24107
25011
  const context = {
24108
- os: (0, import_node_os13.platform)(),
24109
- os_release: (0, import_node_os13.release)(),
24110
- platform: `${(0, import_node_os13.platform)()}-${(0, import_node_os13.release)()}-${process.arch}`,
25012
+ os: (0, import_node_os14.platform)(),
25013
+ os_release: (0, import_node_os14.release)(),
25014
+ platform: `${(0, import_node_os14.platform)()}-${(0, import_node_os14.release)()}-${process.arch}`,
24111
25015
  node_version: process.version,
24112
25016
  runtime: "Node.js",
24113
- hostname: (0, import_node_os13.hostname)(),
25017
+ hostname: (0, import_node_os14.hostname)(),
24114
25018
  agent_runtime: detectAgentRuntime()
24115
25019
  };
24116
25020
  for (const key of ["CLAUDE_CODE_REMOTE", "DEEPLINE_PLUGIN_MODE"]) {
@@ -24303,8 +25207,8 @@ function topLevelCommandKnown(program, commandName) {
24303
25207
  );
24304
25208
  }
24305
25209
  async function runPlayRunnerHealthCheck() {
24306
- const dir = await (0, import_promises5.mkdtemp)((0, import_node_path19.join)((0, import_node_os14.tmpdir)(), "deepline-health-play-"));
24307
- const file = (0, import_node_path19.join)(dir, "health-check.play.ts");
25210
+ const dir = await (0, import_promises5.mkdtemp)((0, import_node_path20.join)((0, import_node_os15.tmpdir)(), "deepline-health-play-"));
25211
+ const file = (0, import_node_path20.join)(dir, "health-check.play.ts");
24308
25212
  try {
24309
25213
  await (0, import_promises5.writeFile)(
24310
25214
  file,