deepline 0.1.152 → 0.1.154

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