deepline 0.1.153 → 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 +15 -0
  2. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +1180 -825
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +34 -18
  4. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +41 -0
  5. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/receipts.ts +143 -8
  6. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-receipts.ts +104 -0
  7. package/dist/bundling-sources/sdk/src/index.ts +0 -1
  8. package/dist/bundling-sources/sdk/src/play.ts +3 -48
  9. package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +27 -2
  10. package/dist/bundling-sources/sdk/src/release.ts +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 +45 -76
  27. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +12 -1
  28. package/dist/bundling-sources/shared_libs/play-runtime/step-program-dataset-builder.ts +1 -14
  29. package/dist/bundling-sources/shared_libs/play-runtime/tool-execution-outcome.ts +159 -0
  30. package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +4 -1
  31. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +32 -0
  32. package/dist/bundling-sources/shared_libs/plays/definition.ts +4 -2
  33. package/dist/bundling-sources/shared_libs/plays/runtime-validation.ts +3 -14
  34. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +1 -43
  35. package/dist/cli/index.js +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
@@ -159,7 +159,7 @@ configureProxyFromEnv();
159
159
 
160
160
  // src/cli/index.ts
161
161
  import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile5 } from "fs/promises";
162
- import { join as join14 } from "path";
162
+ import { join as join15 } from "path";
163
163
  import { tmpdir as tmpdir4 } from "os";
164
164
  import { Command as Command3 } from "commander";
165
165
 
@@ -640,10 +640,10 @@ var SDK_RELEASE = {
640
640
  // the SDK enrich generator's one-second stale policy.
641
641
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
642
642
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
643
- version: "0.1.153",
643
+ version: "0.1.154",
644
644
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
645
645
  supportPolicy: {
646
- latest: "0.1.153",
646
+ latest: "0.1.154",
647
647
  minimumSupported: "0.1.53",
648
648
  deprecatedBelow: "0.1.53",
649
649
  commandMinimumSupported: [
@@ -1237,7 +1237,7 @@ function decodeSseFrame(frame) {
1237
1237
  return parsed;
1238
1238
  }
1239
1239
  function sleep(ms) {
1240
- return new Promise((resolve13) => setTimeout(resolve13, ms));
1240
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
1241
1241
  }
1242
1242
  function withCoworkNetworkHint(message) {
1243
1243
  if (!isCoworkLikeSandbox2() || message.includes(COWORK_NETWORK_HINT)) {
@@ -1447,8 +1447,15 @@ function normalizeStepProgress(value) {
1447
1447
  };
1448
1448
  }
1449
1449
 
1450
- // ../shared_libs/play-runtime/run-snapshot-stream.ts
1451
- function normalizePlayRunLiveStatus(value) {
1450
+ // ../shared_libs/play-runtime/run-lifecycle-policy.ts
1451
+ var TERMINAL_PLAY_RUN_STATUSES = /* @__PURE__ */ new Set([
1452
+ "completed",
1453
+ "failed",
1454
+ "cancelled",
1455
+ "terminated",
1456
+ "timed_out"
1457
+ ]);
1458
+ function normalizePlayRunLifecycleStatus(value) {
1452
1459
  const normalized = String(value ?? "").trim().toLowerCase();
1453
1460
  switch (normalized) {
1454
1461
  case "queued":
@@ -1456,6 +1463,7 @@ function normalizePlayRunLiveStatus(value) {
1456
1463
  return "running";
1457
1464
  case "running":
1458
1465
  case "started":
1466
+ case "waiting":
1459
1467
  return "running";
1460
1468
  case "completed":
1461
1469
  case "complete":
@@ -1476,8 +1484,16 @@ function normalizePlayRunLiveStatus(value) {
1476
1484
  return "unknown";
1477
1485
  }
1478
1486
  }
1487
+ function isTerminalPlayRunLifecycleStatus(status) {
1488
+ return TERMINAL_PLAY_RUN_STATUSES.has(normalizePlayRunLifecycleStatus(status));
1489
+ }
1490
+
1491
+ // ../shared_libs/play-runtime/run-snapshot-stream.ts
1492
+ function normalizePlayRunLiveStatus(value) {
1493
+ return normalizePlayRunLifecycleStatus(value);
1494
+ }
1479
1495
  function isTerminalPlayRunLiveStatus(status) {
1480
- return status === "completed" || status === "failed" || status === "cancelled" || status === "terminated" || status === "timed_out";
1496
+ return isTerminalPlayRunLifecycleStatus(status);
1481
1497
  }
1482
1498
  function isRecord2(value) {
1483
1499
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -2006,14 +2022,14 @@ async function* observeRunEvents(options) {
2006
2022
  try {
2007
2023
  for (; ; ) {
2008
2024
  if (queue.length === 0) {
2009
- const waitForItem = new Promise((resolve13) => {
2010
- wake = resolve13;
2025
+ const waitForItem = new Promise((resolve14) => {
2026
+ wake = resolve14;
2011
2027
  });
2012
2028
  if (!sawFirstSnapshot) {
2013
2029
  const timedOut = await Promise.race([
2014
2030
  waitForItem.then(() => false),
2015
2031
  new Promise(
2016
- (resolve13) => setTimeout(() => resolve13(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
2032
+ (resolve14) => setTimeout(() => resolve14(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
2017
2033
  )
2018
2034
  ]);
2019
2035
  if (timedOut && queue.length === 0) {
@@ -2114,7 +2130,7 @@ var REGISTER_PLAY_ARTIFACTS_COMPILE_CONCURRENCY = 3;
2114
2130
  var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_COUNT = 3;
2115
2131
  var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_BYTES = 25e5;
2116
2132
  function sleep2(ms) {
2117
- return new Promise((resolve13) => setTimeout(resolve13, ms));
2133
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
2118
2134
  }
2119
2135
  function isTransientCompileManifestError(error) {
2120
2136
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -4792,7 +4808,7 @@ function buildCandidateUrls2(url) {
4792
4808
  }
4793
4809
  }
4794
4810
  function sleep4(ms) {
4795
- return new Promise((resolve13) => setTimeout(resolve13, ms));
4811
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
4796
4812
  }
4797
4813
  function printDeeplineLogo() {
4798
4814
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -6211,6 +6227,19 @@ Examples:
6211
6227
  ).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));
6212
6228
  }
6213
6229
 
6230
+ // src/cli/commands/csv.ts
6231
+ import { spawn } from "child_process";
6232
+ import { randomUUID } from "crypto";
6233
+ import {
6234
+ existsSync as existsSync6,
6235
+ mkdirSync as mkdirSync5,
6236
+ readFileSync as readFileSync6,
6237
+ rmSync as rmSync3,
6238
+ writeFileSync as writeFileSync6
6239
+ } from "fs";
6240
+ import { homedir as homedir6 } from "os";
6241
+ import { join as join5, resolve as resolve5 } from "path";
6242
+
6214
6243
  // src/cli/dataset-stats.ts
6215
6244
  import { writeFileSync as writeFileSync5 } from "fs";
6216
6245
  import { resolve as resolve4 } from "path";
@@ -6550,6 +6579,7 @@ function collectCanonicalRowsInfos(statusOrResult) {
6550
6579
  total: totalFromMetadata,
6551
6580
  output: candidates
6552
6581
  });
6582
+ candidates.push(...collectPackagedStepDatasetCandidates(statusOrResult));
6553
6583
  const seen = /* @__PURE__ */ new Set();
6554
6584
  const infos = [];
6555
6585
  for (const candidate of candidates) {
@@ -6928,6 +6958,311 @@ async function handleCsvShow(options) {
6928
6958
  `
6929
6959
  );
6930
6960
  }
6961
+ function csvRenderStatePath() {
6962
+ return join5(homedir6(), ".local", "deepline", "runtime", "csv-render.json");
6963
+ }
6964
+ function csvRenderLogPath() {
6965
+ return join5(homedir6(), ".local", "deepline", "runtime", "csv-render.log");
6966
+ }
6967
+ function ensureCsvRenderStateDir() {
6968
+ mkdirSync5(join5(homedir6(), ".local", "deepline", "runtime"), {
6969
+ recursive: true
6970
+ });
6971
+ }
6972
+ function readCsvRenderState() {
6973
+ try {
6974
+ const parsed = JSON.parse(readFileSync6(csvRenderStatePath(), "utf8"));
6975
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
6976
+ } catch {
6977
+ return {};
6978
+ }
6979
+ }
6980
+ function writeCsvRenderState(state) {
6981
+ ensureCsvRenderStateDir();
6982
+ writeFileSync6(csvRenderStatePath(), `${JSON.stringify(state, null, 2)}
6983
+ `);
6984
+ }
6985
+ function parseCsvRenderPort(raw) {
6986
+ const value = Number.parseInt(String(raw ?? "4174").replace(/^:/, ""), 10);
6987
+ if (!Number.isInteger(value) || value <= 0 || value > 65535) {
6988
+ throw new Error(`Invalid --port value: ${raw ?? ""}`);
6989
+ }
6990
+ return value;
6991
+ }
6992
+ function processAlive(pid) {
6993
+ if (!Number.isInteger(pid) || pid <= 0) {
6994
+ return false;
6995
+ }
6996
+ try {
6997
+ process.kill(pid, 0);
6998
+ return true;
6999
+ } catch {
7000
+ return false;
7001
+ }
7002
+ }
7003
+ function isOwnedCsvRenderHealth(health, state) {
7004
+ return Boolean(health?.ok) && Number.isInteger(state.pid) && health?.pid === state.pid && Boolean(state.token) && health?.token === state.token;
7005
+ }
7006
+ async function fetchCsvRenderHealth(url) {
7007
+ try {
7008
+ const response = await fetch(`${url}/health`);
7009
+ if (!response.ok) {
7010
+ return null;
7011
+ }
7012
+ const parsed = await response.json();
7013
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
7014
+ } catch {
7015
+ return null;
7016
+ }
7017
+ }
7018
+ async function waitForRenderHealth(url, state) {
7019
+ const deadline = Date.now() + 5e3;
7020
+ while (Date.now() < deadline) {
7021
+ if (isOwnedCsvRenderHealth(await fetchCsvRenderHealth(url), state)) {
7022
+ return true;
7023
+ }
7024
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 100));
7025
+ }
7026
+ return false;
7027
+ }
7028
+ async function waitForRenderStopped(url) {
7029
+ const deadline = Date.now() + 2e3;
7030
+ while (Date.now() < deadline) {
7031
+ try {
7032
+ await fetch(`${url}/health`);
7033
+ } catch {
7034
+ return;
7035
+ }
7036
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 100));
7037
+ }
7038
+ }
7039
+ var CSV_RENDER_SERVER_SOURCE = String.raw`
7040
+ const http = require('node:http');
7041
+ const fs = require('node:fs');
7042
+ const path = require('node:path');
7043
+
7044
+ const port = Number.parseInt(process.env.DEEPLINE_CSV_RENDER_PORT || '4174', 10);
7045
+ const csvPath = process.env.DEEPLINE_CSV_RENDER_CSV || '';
7046
+ const token = process.env.DEEPLINE_CSV_RENDER_TOKEN || '';
7047
+
7048
+ function send(res, status, contentType, body) {
7049
+ res.writeHead(status, {
7050
+ 'content-type': contentType,
7051
+ 'cache-control': 'no-store',
7052
+ });
7053
+ res.end(body);
7054
+ }
7055
+
7056
+ function readCsvText() {
7057
+ if (!csvPath) return '';
7058
+ try {
7059
+ return fs.readFileSync(csvPath, 'utf8');
7060
+ } catch (error) {
7061
+ return 'Unable to read CSV: ' + (error && error.message ? error.message : String(error));
7062
+ }
7063
+ }
7064
+
7065
+ const server = http.createServer((req, res) => {
7066
+ const url = new URL(req.url || '/', 'http://127.0.0.1:' + port);
7067
+ if (url.pathname === '/health') {
7068
+ send(res, 200, 'application/json', JSON.stringify({ ok: true, pid: process.pid, csvPath, token }));
7069
+ return;
7070
+ }
7071
+ if (url.pathname === '/csv.txt') {
7072
+ send(res, 200, 'text/plain; charset=utf-8', readCsvText());
7073
+ return;
7074
+ }
7075
+ if (url.pathname === '/csv.json') {
7076
+ send(res, 200, 'application/json', JSON.stringify({ csvPath, text: readCsvText() }));
7077
+ return;
7078
+ }
7079
+ const title = csvPath ? path.basename(csvPath) : 'CSV renderer';
7080
+ const escapedTitle = title.replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[ch]));
7081
+ const escapedCsv = readCsvText().replace(/[&<>]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[ch]));
7082
+ 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>');
7083
+ });
7084
+
7085
+ server.listen(port, '127.0.0.1');
7086
+ process.on('SIGTERM', () => server.close(() => process.exit(0)));
7087
+ process.on('SIGINT', () => server.close(() => process.exit(0)));
7088
+ `;
7089
+ async function openBrowser(url) {
7090
+ const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
7091
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
7092
+ const child = spawn(opener, args, { detached: true, stdio: "ignore" });
7093
+ child.on("error", () => {
7094
+ });
7095
+ child.unref();
7096
+ }
7097
+ async function handleCsvRenderStart(options) {
7098
+ const port = parseCsvRenderPort(options.port);
7099
+ const csvPath = options.csv ? resolve5(options.csv) : "";
7100
+ if (csvPath && !existsSync6(csvPath)) {
7101
+ throw new Error(`CSV not found: ${csvPath}`);
7102
+ }
7103
+ const url = `http://127.0.0.1:${port}`;
7104
+ const existing = readCsvRenderState();
7105
+ if (processAlive(existing.pid) && existing.url) {
7106
+ const existingOwned = isOwnedCsvRenderHealth(
7107
+ await fetchCsvRenderHealth(existing.url),
7108
+ existing
7109
+ );
7110
+ const sameUrl = existing.url === url;
7111
+ const sameCsv = !csvPath || existing.csvPath === csvPath;
7112
+ if (existingOwned && (!sameUrl || !sameCsv)) {
7113
+ try {
7114
+ process.kill(existing.pid, "SIGTERM");
7115
+ } catch {
7116
+ }
7117
+ await waitForRenderStopped(existing.url);
7118
+ if (processAlive(existing.pid)) {
7119
+ try {
7120
+ process.kill(existing.pid, "SIGKILL");
7121
+ } catch {
7122
+ }
7123
+ }
7124
+ rmSync3(csvRenderStatePath(), { force: true });
7125
+ } else if (existingOwned) {
7126
+ process.stdout.write(
7127
+ "Playground render is already running; reusing current process.\n"
7128
+ );
7129
+ process.stdout.write(`Render URL: ${existing.url}
7130
+ `);
7131
+ if (options.open) {
7132
+ await openBrowser(existing.url);
7133
+ }
7134
+ return;
7135
+ } else {
7136
+ rmSync3(csvRenderStatePath(), { force: true });
7137
+ }
7138
+ }
7139
+ ensureCsvRenderStateDir();
7140
+ const logPath = csvRenderLogPath();
7141
+ const token = randomUUID();
7142
+ const child = spawn(process.execPath, ["-e", CSV_RENDER_SERVER_SOURCE], {
7143
+ detached: true,
7144
+ stdio: ["ignore", "ignore", "ignore"],
7145
+ env: {
7146
+ ...process.env,
7147
+ DEEPLINE_CSV_RENDER_PORT: String(port),
7148
+ DEEPLINE_CSV_RENDER_CSV: csvPath,
7149
+ DEEPLINE_CSV_RENDER_TOKEN: token
7150
+ }
7151
+ });
7152
+ child.unref();
7153
+ const state = {
7154
+ pid: child.pid ?? null,
7155
+ port,
7156
+ url,
7157
+ csvPath,
7158
+ logPath,
7159
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
7160
+ token
7161
+ };
7162
+ const started = await waitForRenderHealth(url, state);
7163
+ if (!started) {
7164
+ if (processAlive(child.pid)) {
7165
+ process.kill(child.pid, "SIGTERM");
7166
+ }
7167
+ throw new Error(`Timed out waiting for CSV render to start at ${url}.`);
7168
+ }
7169
+ writeCsvRenderState(state);
7170
+ writeFileSync6(
7171
+ logPath,
7172
+ `CSV render started at ${state.startedAt} on ${url}
7173
+ `
7174
+ );
7175
+ process.stdout.write("Playground render is running.\n");
7176
+ process.stdout.write(`Render PID: ${child.pid}
7177
+ `);
7178
+ process.stdout.write(`Render URL: ${url}
7179
+ `);
7180
+ if (options.open) {
7181
+ await openBrowser(url);
7182
+ }
7183
+ }
7184
+ async function handleCsvRenderStatus(options) {
7185
+ const state = readCsvRenderState();
7186
+ const processExists = processAlive(state.pid);
7187
+ const url = state.url ?? "";
7188
+ let health = "unknown";
7189
+ let owned = false;
7190
+ if (processExists && url) {
7191
+ const renderHealth = await fetchCsvRenderHealth(url);
7192
+ owned = isOwnedCsvRenderHealth(renderHealth, state);
7193
+ health = owned ? "healthy" : "unhealthy";
7194
+ }
7195
+ const status = processExists && owned ? "running" : processExists ? "unhealthy" : "stopped";
7196
+ const payload = {
7197
+ status,
7198
+ pid: owned ? state.pid : null,
7199
+ process_alive: owned,
7200
+ url,
7201
+ log_path: state.logPath ?? "",
7202
+ mode: "background",
7203
+ started_at: owned ? state.startedAt ?? "" : "",
7204
+ health_status: health,
7205
+ health_checked_at: (/* @__PURE__ */ new Date()).toISOString(),
7206
+ stale_cleaned: true
7207
+ };
7208
+ const lines = [`Render Status: ${payload.status}`];
7209
+ if (payload.pid) lines.push(`Render PID: ${payload.pid}`);
7210
+ if (payload.url) lines.push(`Render URL: ${payload.url}`);
7211
+ lines.push(`Render Health: ${payload.health_status}`);
7212
+ printCommandEnvelope(payload, {
7213
+ json: options.json,
7214
+ text: `${lines.join("\n")}
7215
+ `
7216
+ });
7217
+ }
7218
+ function terminateRenderProcess(pid) {
7219
+ try {
7220
+ process.kill(pid, "SIGTERM");
7221
+ } catch {
7222
+ return false;
7223
+ }
7224
+ return true;
7225
+ }
7226
+ async function handleCsvRenderStop(options) {
7227
+ const state = readCsvRenderState();
7228
+ const stopped = [];
7229
+ const failed = [];
7230
+ const owned = processAlive(state.pid) && Boolean(state.url) && isOwnedCsvRenderHealth(await fetchCsvRenderHealth(state.url), state);
7231
+ if (owned && processAlive(state.pid)) {
7232
+ if (terminateRenderProcess(state.pid)) {
7233
+ stopped.push(state.pid);
7234
+ } else {
7235
+ failed.push(state.pid);
7236
+ }
7237
+ }
7238
+ rmSync3(csvRenderStatePath(), { force: true });
7239
+ const payload = {
7240
+ ok: failed.length === 0,
7241
+ stopped_count: stopped.length,
7242
+ failed_count: failed.length,
7243
+ stopped_pids: stopped,
7244
+ failed_pids: failed
7245
+ };
7246
+ const text = stopped.length > 0 ? `Stopped playground render process(es): ${stopped.join(" ")}
7247
+ ` : "No running playground render process found.\n";
7248
+ printCommandEnvelope(payload, { json: options.json, text });
7249
+ }
7250
+ async function handleCsvRender(action, options) {
7251
+ const normalized = action ?? "start";
7252
+ if (normalized === "start") {
7253
+ await handleCsvRenderStart(options);
7254
+ return;
7255
+ }
7256
+ if (normalized === "status") {
7257
+ await handleCsvRenderStatus(options);
7258
+ return;
7259
+ }
7260
+ if (normalized === "stop") {
7261
+ await handleCsvRenderStop(options);
7262
+ return;
7263
+ }
7264
+ throw new Error(`Unknown csv render action: ${normalized}`);
7265
+ }
6931
7266
  function registerCsvCommands(program) {
6932
7267
  const csv = program.command("csv").description("Inspect local CSV files.").addHelpText(
6933
7268
  "after",
@@ -6954,11 +7289,13 @@ Examples:
6954
7289
  deepline csv show --csv leads.csv --summary
6955
7290
  `
6956
7291
  ).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);
7292
+ 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);
7293
+ render.showHelpAfterError();
6957
7294
  }
6958
7295
 
6959
7296
  // src/cli/commands/db.ts
6960
- import { writeFileSync as writeFileSync6 } from "fs";
6961
- import { resolve as resolve5 } from "path";
7297
+ import { writeFileSync as writeFileSync7 } from "fs";
7298
+ import { resolve as resolve6 } from "path";
6962
7299
  var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set(["table", "json", "csv", "markdown"]);
6963
7300
  var CUSTOMER_DB_QUERY_MAX_ROWS = 1e3;
6964
7301
  function parsePositiveInteger(value, flagName) {
@@ -7081,8 +7418,8 @@ function formatDbQueryError(sql, error) {
7081
7418
  return errorMessage(error);
7082
7419
  }
7083
7420
  function writeCustomerDbCsv(result, outPath) {
7084
- const resolved = resolve5(outPath);
7085
- writeFileSync6(
7421
+ const resolved = resolve6(outPath);
7422
+ writeFileSync7(
7086
7423
  resolved,
7087
7424
  dataExportCsvString(customerDbRows(result), customerDbColumnNames(result)),
7088
7425
  "utf-8"
@@ -7194,8 +7531,8 @@ async function handleDbQuery(args) {
7194
7531
  customerDbColumnNames(result)
7195
7532
  );
7196
7533
  if (outPath) {
7197
- const exportedPath = resolve5(outPath);
7198
- writeFileSync6(exportedPath, content, "utf-8");
7534
+ const exportedPath = resolve6(outPath);
7535
+ writeFileSync7(exportedPath, content, "utf-8");
7199
7536
  printCommandEnvelope(
7200
7537
  dbQueryExportEnvelope({
7201
7538
  result,
@@ -7304,20 +7641,20 @@ import {
7304
7641
  stat,
7305
7642
  writeFile as writeFile3
7306
7643
  } from "fs/promises";
7307
- import { homedir as homedir6, tmpdir as tmpdir2 } from "os";
7308
- import { join as join6, resolve as resolve8 } from "path";
7644
+ import { homedir as homedir7, tmpdir as tmpdir2 } from "os";
7645
+ import { join as join7, resolve as resolve9 } from "path";
7309
7646
 
7310
7647
  // src/cli/commands/play.ts
7311
7648
  import { createHash as createHash2 } from "crypto";
7312
7649
  import {
7313
- existsSync as existsSync6,
7314
- readFileSync as readFileSync6,
7650
+ existsSync as existsSync7,
7651
+ readFileSync as readFileSync7,
7315
7652
  readdirSync as readdirSync2,
7316
7653
  realpathSync as realpathSync2,
7317
7654
  statSync as statSync3,
7318
- writeFileSync as writeFileSync8
7655
+ writeFileSync as writeFileSync9
7319
7656
  } from "fs";
7320
- import { basename, dirname as dirname6, join as join5, resolve as resolve7 } from "path";
7657
+ import { basename, dirname as dirname6, join as join6, resolve as resolve8 } from "path";
7321
7658
  import { parse as parseCsvSync2 } from "csv-parse/sync";
7322
7659
 
7323
7660
  // src/cli/commands/plays/bootstrap.ts
@@ -7326,9 +7663,9 @@ import {
7326
7663
  openSync,
7327
7664
  readSync,
7328
7665
  statSync as statSync2,
7329
- writeFileSync as writeFileSync7
7666
+ writeFileSync as writeFileSync8
7330
7667
  } from "fs";
7331
- import { isAbsolute, relative, resolve as resolve6 } from "path";
7668
+ import { isAbsolute, relative, resolve as resolve7 } from "path";
7332
7669
  import { parse as parseCsvSync } from "csv-parse/sync";
7333
7670
 
7334
7671
  // ../shared_libs/plays/bootstrap-routes.ts
@@ -7757,7 +8094,7 @@ function inferCsvColumnSpecs(headers, rows) {
7757
8094
  }));
7758
8095
  }
7759
8096
  function readCsvSample(csvPath) {
7760
- const resolvedPath = resolve6(csvPath);
8097
+ const resolvedPath = resolve7(csvPath);
7761
8098
  const size = statSync2(resolvedPath).size;
7762
8099
  const fd = openSync(resolvedPath, "r");
7763
8100
  const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
@@ -7832,7 +8169,7 @@ ${properties}
7832
8169
  }
7833
8170
  function packagedCsvPathForPlay(csvPath) {
7834
8171
  const playDir = process.cwd();
7835
- const absoluteCsvPath = resolve6(csvPath);
8172
+ const absoluteCsvPath = resolve7(csvPath);
7836
8173
  const relativePath = relative(playDir, absoluteCsvPath);
7837
8174
  if (relativePath === "" || relativePath.startsWith("..") || isAbsolute(relativePath)) {
7838
8175
  throw new PlayBootstrapUsageError(
@@ -8756,8 +9093,8 @@ async function runPlayBootstrap(args) {
8756
9093
  ...csvContext
8757
9094
  });
8758
9095
  if (options.out) {
8759
- writeFileSync7(resolve6(options.out), source, "utf-8");
8760
- process.stdout.write(`Wrote ${resolve6(options.out)}
9096
+ writeFileSync8(resolve7(options.out), source, "utf-8");
9097
+ process.stdout.write(`Wrote ${resolve7(options.out)}
8761
9098
  `);
8762
9099
  return 0;
8763
9100
  }
@@ -9441,7 +9778,7 @@ function traceCliSync(phase, fields, run) {
9441
9778
  }
9442
9779
  }
9443
9780
  function sleep5(ms) {
9444
- return new Promise((resolve13) => setTimeout(resolve13, ms));
9781
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
9445
9782
  }
9446
9783
  function parseReferencedPlayTarget2(target) {
9447
9784
  const trimmed = target.trim();
@@ -9485,7 +9822,7 @@ function formatPlayListReference(play) {
9485
9822
  return play.reference || play.name;
9486
9823
  }
9487
9824
  function defaultMaterializedPlayPath(reference) {
9488
- return resolve7(defaultStarterPlayPath(reference));
9825
+ return resolve8(defaultStarterPlayPath(reference));
9489
9826
  }
9490
9827
  function defaultStarterPlayPath(reference) {
9491
9828
  const playName = parseReferencedPlayTarget2(reference).unqualifiedPlayName;
@@ -9511,15 +9848,15 @@ function materializeRemotePlaySource(input2) {
9511
9848
  return null;
9512
9849
  }
9513
9850
  const outputPath = input2.outPath ?? defaultMaterializedPlayPath(input2.playName);
9514
- if (existsSync6(outputPath)) {
9515
- const existingSource = readFileSync6(outputPath, "utf-8");
9851
+ if (existsSync7(outputPath)) {
9852
+ const existingSource = readFileSync7(outputPath, "utf-8");
9516
9853
  if (existingSource === input2.sourceCode) {
9517
9854
  return { path: outputPath, status: "unchanged", created: false };
9518
9855
  }
9519
- writeFileSync8(outputPath, input2.sourceCode, "utf-8");
9856
+ writeFileSync9(outputPath, input2.sourceCode, "utf-8");
9520
9857
  return { path: outputPath, status: "updated", created: false };
9521
9858
  }
9522
- writeFileSync8(outputPath, input2.sourceCode, "utf-8");
9859
+ writeFileSync9(outputPath, input2.sourceCode, "utf-8");
9523
9860
  return { path: outputPath, status: "created", created: true };
9524
9861
  }
9525
9862
  function formatLoadedPlayMessage(materializedFile) {
@@ -9564,7 +9901,7 @@ function extractPlayName(code, filePath) {
9564
9901
  throw buildMissingDefinePlayError(filePath);
9565
9902
  }
9566
9903
  function isFileTarget(target) {
9567
- return existsSync6(resolve7(target));
9904
+ return existsSync7(resolve8(target));
9568
9905
  }
9569
9906
  function looksLikeRunId(target) {
9570
9907
  return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
@@ -9593,7 +9930,7 @@ function parsePositiveInteger3(value, flagName) {
9593
9930
  return parsed;
9594
9931
  }
9595
9932
  function parseJsonInput(raw) {
9596
- const source = raw.startsWith("@") ? readFileSync6(resolve7(raw.slice(1)), "utf-8") : raw;
9933
+ const source = raw.startsWith("@") ? readFileSync7(resolve8(raw.slice(1)), "utf-8") : raw;
9597
9934
  const parsed = JSON.parse(source);
9598
9935
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
9599
9936
  throw new Error("--input must be a JSON object.");
@@ -9695,7 +10032,7 @@ function fileInputBindingsFromStaticPipeline(staticPipeline) {
9695
10032
  function isLocalFilePathValue(value) {
9696
10033
  if (typeof value !== "string" || !value.trim()) return false;
9697
10034
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
9698
- return existsSync6(resolve7(value));
10035
+ return existsSync7(resolve8(value));
9699
10036
  }
9700
10037
  function inputContainsLocalFilePath(value) {
9701
10038
  if (isLocalFilePathValue(value)) {
@@ -9742,7 +10079,7 @@ function collectLocalFileInputRefs(value, inputPath, key, out) {
9742
10079
  const looksLikeFile = /\.[a-z0-9]{1,8}$/i.test(trimmed);
9743
10080
  if (keyIsCsvData) {
9744
10081
  out.push({ inputPath, value: trimmed, isCsvData: true });
9745
- } else if (endsWithCsv || looksLikeFile && existsSync6(resolve7(trimmed))) {
10082
+ } else if (endsWithCsv || looksLikeFile && existsSync7(resolve8(trimmed))) {
9746
10083
  out.push({ inputPath, value: trimmed, isCsvData: false });
9747
10084
  }
9748
10085
  return;
@@ -9784,8 +10121,8 @@ function preflightLocalFileInputs(runtimeInput) {
9784
10121
  collectLocalFileInputRefs(value, key, key, refs);
9785
10122
  }
9786
10123
  for (const ref of refs) {
9787
- const absolutePath = resolve7(ref.value);
9788
- if (!existsSync6(absolutePath)) {
10124
+ const absolutePath = resolve8(ref.value);
10125
+ if (!existsSync7(absolutePath)) {
9789
10126
  throw new DeeplineError(
9790
10127
  `Input ${ref.inputPath} references a local file that does not exist: ${ref.value} (resolved to ${absolutePath}). No run was created.`,
9791
10128
  void 0,
@@ -9821,7 +10158,7 @@ function preflightLocalFileInputs(runtimeInput) {
9821
10158
  function preflightCsvDataInput(ref, absolutePath) {
9822
10159
  let content;
9823
10160
  try {
9824
- content = readFileSync6(absolutePath, "utf-8");
10161
+ content = readFileSync7(absolutePath, "utf-8");
9825
10162
  } catch (error) {
9826
10163
  throw new DeeplineError(
9827
10164
  `Input ${ref.inputPath} CSV ${ref.value} is not readable: ${error instanceof Error ? error.message : String(error)}. No run was created.`,
@@ -9903,7 +10240,7 @@ async function stageFileInputArgs(input2) {
9903
10240
  const localFiles = uniqueBindings.flatMap((binding) => {
9904
10241
  const value = getDottedInputValue(input2.runtimeInput, binding.inputPath);
9905
10242
  if (!isLocalFilePathValue(value)) return [];
9906
- const absolutePath = resolve7(value);
10243
+ const absolutePath = resolve8(value);
9907
10244
  return [{ binding, absolutePath, logicalPath: basename(absolutePath) }];
9908
10245
  });
9909
10246
  if (localFiles.length === 0) {
@@ -9936,7 +10273,7 @@ async function stageFileInputArgs(input2) {
9936
10273
  };
9937
10274
  }
9938
10275
  function stageFile(logicalPath, absolutePath) {
9939
- const buffer = readFileSync6(absolutePath);
10276
+ const buffer = readFileSync7(absolutePath);
9940
10277
  return {
9941
10278
  logicalPath,
9942
10279
  contentBase64: buffer.toString("base64"),
@@ -9947,9 +10284,9 @@ function stageFile(logicalPath, absolutePath) {
9947
10284
  }
9948
10285
  function normalizePlayPath(filePath) {
9949
10286
  try {
9950
- return realpathSync2.native(resolve7(filePath));
10287
+ return realpathSync2.native(resolve8(filePath));
9951
10288
  } catch {
9952
- return resolve7(filePath);
10289
+ return resolve8(filePath);
9953
10290
  }
9954
10291
  }
9955
10292
  function formatBundlingErrors(filePath, errors) {
@@ -12016,7 +12353,7 @@ function shellSingleQuote(value) {
12016
12353
  return `'${value.replace(/'/g, `'\\''`)}'`;
12017
12354
  }
12018
12355
  function runExportRetryCommand(runId, outPath, datasetPath) {
12019
- return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(resolve7(outPath))}`;
12356
+ return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(resolve8(outPath))}`;
12020
12357
  }
12021
12358
  function extractRunPlayName(status) {
12022
12359
  const run = status.run;
@@ -12821,7 +13158,7 @@ async function handlePlayCheck(args) {
12821
13158
  }
12822
13159
  return 0;
12823
13160
  } catch (error) {
12824
- const resolved = resolve7(options.target);
13161
+ const resolved = resolve8(options.target);
12825
13162
  const message = error instanceof Error && error.message ? error.message : `File not found: ${resolved}`;
12826
13163
  if (options.jsonOutput) {
12827
13164
  process.stdout.write(
@@ -12838,8 +13175,8 @@ async function handlePlayCheck(args) {
12838
13175
  return 1;
12839
13176
  }
12840
13177
  }
12841
- const absolutePlayPath = resolve7(options.target);
12842
- const sourceCode = readFileSync6(absolutePlayPath, "utf-8");
13178
+ const absolutePlayPath = resolve8(options.target);
13179
+ const sourceCode = readFileSync7(absolutePlayPath, "utf-8");
12843
13180
  let graph;
12844
13181
  try {
12845
13182
  graph = await collectBundledPlayGraph(absolutePlayPath);
@@ -12939,12 +13276,12 @@ async function handleFileBackedRun(options) {
12939
13276
  }
12940
13277
  const client2 = new DeeplineClient();
12941
13278
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
12942
- const absolutePlayPath = resolve7(options.target.path);
13279
+ const absolutePlayPath = resolve8(options.target.path);
12943
13280
  progress.phase("compiling play");
12944
13281
  const sourceCode = traceCliSync(
12945
13282
  "cli.play_file_read_source",
12946
13283
  { targetKind: "file" },
12947
- () => readFileSync6(absolutePlayPath, "utf-8")
13284
+ () => readFileSync7(absolutePlayPath, "utf-8")
12948
13285
  );
12949
13286
  const runtimeInput = options.input ? { ...options.input } : {};
12950
13287
  try {
@@ -13265,10 +13602,10 @@ async function handlePlayRun(args) {
13265
13602
  if (isFileTarget(options.target.path)) {
13266
13603
  return handleFileBackedRun(options);
13267
13604
  }
13268
- const resolved = resolve7(options.target.path);
13605
+ const resolved = resolve8(options.target.path);
13269
13606
  console.error(`File not found: ${resolved}`);
13270
13607
  const dir = dirname6(resolved);
13271
- if (existsSync6(dir)) {
13608
+ if (existsSync7(dir)) {
13272
13609
  const base = basename(resolved);
13273
13610
  try {
13274
13611
  const siblings = readdirSync2(dir).filter(
@@ -13277,7 +13614,7 @@ async function handlePlayRun(args) {
13277
13614
  if (siblings.length > 0) {
13278
13615
  console.error(`Did you mean one of these?`);
13279
13616
  for (const s of siblings.slice(0, 5)) {
13280
- console.error(` ${join5(dir, s)}`);
13617
+ console.error(` ${join6(dir, s)}`);
13281
13618
  }
13282
13619
  }
13283
13620
  } catch {
@@ -13436,14 +13773,14 @@ async function handleRunLogs(args) {
13436
13773
  continue;
13437
13774
  }
13438
13775
  if (arg === "--out" && args[index + 1]) {
13439
- outPath = resolve7(args[++index]);
13776
+ outPath = resolve8(args[++index]);
13440
13777
  }
13441
13778
  }
13442
13779
  const client2 = new DeeplineClient();
13443
13780
  if (outPath) {
13444
13781
  const result2 = await client2.runs.logs(runId, { all: true });
13445
13782
  const logs = result2.entries;
13446
- writeFileSync8(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
13783
+ writeFileSync9(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
13447
13784
  printCommandEnvelope(
13448
13785
  {
13449
13786
  runId: result2.runId,
@@ -13593,7 +13930,7 @@ async function handleRunExport(args) {
13593
13930
  for (let index = 0; index < args.length; index += 1) {
13594
13931
  const arg = args[index];
13595
13932
  if (arg === "--out" && args[index + 1]) {
13596
- outPath = resolve7(args[++index]);
13933
+ outPath = resolve8(args[++index]);
13597
13934
  continue;
13598
13935
  }
13599
13936
  if (arg === "--dataset" && args[index + 1]) {
@@ -13601,7 +13938,7 @@ async function handleRunExport(args) {
13601
13938
  continue;
13602
13939
  }
13603
13940
  if (arg === "--metadata-out" && args[index + 1]) {
13604
- metadataOutPath = resolve7(args[++index]);
13941
+ metadataOutPath = resolve8(args[++index]);
13605
13942
  }
13606
13943
  }
13607
13944
  if (!outPath) {
@@ -13641,7 +13978,7 @@ async function handleRunExport(args) {
13641
13978
  }
13642
13979
  };
13643
13980
  if (metadataOutPath) {
13644
- writeFileSync8(
13981
+ writeFileSync9(
13645
13982
  metadataOutPath,
13646
13983
  `${JSON.stringify(payload, null, 2)}
13647
13984
  `,
@@ -13673,10 +14010,10 @@ async function handlePlayGet(args) {
13673
14010
  for (let index = 1; index < args.length; index += 1) {
13674
14011
  const arg = args[index];
13675
14012
  if (arg === "--out" && args[index + 1]) {
13676
- outPath = resolve7(args[++index]);
14013
+ outPath = resolve8(args[++index]);
13677
14014
  }
13678
14015
  }
13679
- const playName = isFileTarget(target) ? extractPlayName(readFileSync6(resolve7(target), "utf-8"), resolve7(target)) : parseReferencedPlayTarget2(target).playName;
14016
+ const playName = isFileTarget(target) ? extractPlayName(readFileSync7(resolve8(target), "utf-8"), resolve8(target)) : parseReferencedPlayTarget2(target).playName;
13680
14017
  const detail = isFileTarget(target) ? await client2.getPlay(playName) : await assertCanonicalNamedPlayReference(client2, target);
13681
14018
  const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
13682
14019
  const materializedFile = outPath ? materializeRemotePlaySource({
@@ -14125,7 +14462,7 @@ async function handlePlayDescribe(args) {
14125
14462
  const definedName = isFileTarget(playName) ? (() => {
14126
14463
  try {
14127
14464
  return extractPlayName(
14128
- readFileSync6(resolve7(playName), "utf-8"),
14465
+ readFileSync7(resolve8(playName), "utf-8"),
14129
14466
  playName
14130
14467
  );
14131
14468
  } catch {
@@ -14206,7 +14543,7 @@ async function handlePlayPublish(args) {
14206
14543
  graph = await traceCliSpan(
14207
14544
  "cli.play_publish_bundle_graph",
14208
14545
  { targetKind: "file" },
14209
- () => collectBundledPlayGraph(resolve7(playName))
14546
+ () => collectBundledPlayGraph(resolve8(playName))
14210
14547
  );
14211
14548
  assertBundledPlayGraphDescriptions(graph);
14212
14549
  await traceCliSpan(
@@ -14395,12 +14732,15 @@ Idempotent execution:
14395
14732
  }))
14396
14733
  .run({ key: 'domain' });
14397
14734
 
14398
- Reuse needs the same play, tool id, dataset name, row key, and compatible logic.
14399
- To recompute a visible cell on a later cron/user run after a window, put
14400
- staleAfterSeconds on the cell-producing column:
14735
+ Reuse needs the same play, call id, semantic input, auth scope, and cache
14736
+ policy. Dataset cells are storage; put freshness on the actual call:
14401
14737
 
14402
- .withColumn('cto', resolver, { staleAfterSeconds: 86400 })
14403
- .run({ key: 'domain' })
14738
+ await ctx.tools.execute({
14739
+ id: 'find_cto',
14740
+ tool: 'dropleads_search_people',
14741
+ input: { filters: { companyDomains: [row.domain], jobTitles: ['CTO'] }, pagination: { page: 1, limit: 1 } },
14742
+ staleAfterSeconds: 86400,
14743
+ });
14404
14744
 
14405
14745
  Examples:
14406
14746
  deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
@@ -15257,12 +15597,10 @@ function getterFromLegacyExtractJs(extractJs, fallbackAlias) {
15257
15597
  // src/cli/enrich-compat-adapter.ts
15258
15598
  var ENRICH_COMPAT_DEFAULT_PLAY_NAME = "deepline-enrich-v1-compat";
15259
15599
  var ENRICH_COMPAT_DEFAULT_MAP_NAME = "deepline_enrich_rows";
15260
- var ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE = "{ recompute: true }";
15261
15600
  function buildEnrichCompatibilityPlan(options = {}) {
15262
15601
  return {
15263
15602
  playName: options.playName?.trim() || ENRICH_COMPAT_DEFAULT_PLAY_NAME,
15264
- mapName: options.mapName?.trim() || ENRICH_COMPAT_DEFAULT_MAP_NAME,
15265
- metadataCellPolicySource: ENRICH_COMPAT_METADATA_CELL_POLICY_SOURCE
15603
+ mapName: options.mapName?.trim() || ENRICH_COMPAT_DEFAULT_MAP_NAME
15266
15604
  };
15267
15605
  }
15268
15606
 
@@ -15344,7 +15682,7 @@ function renderExecuteStep(command, options = {
15344
15682
  if (command.play) {
15345
15683
  return renderPlayStep(command, options);
15346
15684
  }
15347
- if (command.tool === "run_javascript" && options.inlineRunJavascript) {
15685
+ if (command.tool === "run_javascript" && options.inlineRunJavascript && canInlineRunJavascript(command)) {
15348
15686
  return renderInlineJavascriptStep(command, options);
15349
15687
  }
15350
15688
  if (options.idiomaticGetters) {
@@ -15354,9 +15692,7 @@ function renderExecuteStep(command, options = {
15354
15692
  const callId = stringLiteral(commandCallId(command));
15355
15693
  const tool = stringLiteral(command.tool);
15356
15694
  const payload = stableJson(command.payload ?? {});
15357
- const extractJs = command.extract_js ? `({ row, result, data, raw, pick, extract, extractList, target, get }) => { const input = row; const context = row;
15358
- ${indent(renderJavascriptBody(command.extract_js), 6)}
15359
- }` : "null";
15695
+ const extractJs = renderExtractFunction(command, 6);
15360
15696
  const runIfJs = options.nativeRunIf ? "null" : renderRunIfFunction(command) ?? "null";
15361
15697
  const description = command.description ? `,
15362
15698
  description: ${stringLiteral(command.description)}` : "";
@@ -15382,6 +15718,23 @@ ${indent(renderJavascriptBody(command.extract_js), 6)}
15382
15718
  `}`
15383
15719
  ].join("\n");
15384
15720
  }
15721
+ function canInlineRunJavascript(command) {
15722
+ const code = typeof command.payload?.code === "string" ? command.payload.code : "";
15723
+ if (/\btriggerWorkflow\b/.test(code)) {
15724
+ return false;
15725
+ }
15726
+ try {
15727
+ assertUserCodeIsSafe(code, `run_javascript step "${command.alias}"`);
15728
+ } catch {
15729
+ return false;
15730
+ }
15731
+ return true;
15732
+ }
15733
+ function renderExtractFunction(command, indentSpaces) {
15734
+ return command.extract_js ? `({ row, result, data, raw, pick, extract, extractList, target, get }) => { const input = row; const context = row;
15735
+ ${indent(renderJavascriptBody(command.extract_js), indentSpaces)}
15736
+ }` : "null";
15737
+ }
15385
15738
  function renderRunIfFunction(command) {
15386
15739
  return command.run_if_js ? `(row) => { const input = row; const context = row;
15387
15740
  ${indent(renderJavascriptBody(command.run_if_js), 6)}
@@ -15469,6 +15822,11 @@ function renderPlayStep(command, options) {
15469
15822
  ].join("\n");
15470
15823
  }
15471
15824
  function renderInlineJavascriptStep(command, options) {
15825
+ const alias = stringLiteral(command.alias);
15826
+ const extractJs = renderExtractFunction(command, 4);
15827
+ const legacyEnvelope = options.legacyEnvelope ? "true" : "false";
15828
+ const resultExpression = command.extract_js ? `__dlExtract(${alias}, result, row as Record<string, unknown>, ${extractJs}, ${legacyEnvelope})` : "result";
15829
+ const payload = stableJson(command.payload ?? {});
15472
15830
  const code = typeof command.payload?.code === "string" ? command.payload.code : "return null;";
15473
15831
  const runIfLines = command.run_if_js && !options.nativeRunIf ? [
15474
15832
  ` if (!((row: Record<string, any>) => { const input = row; const context = row;`,
@@ -15479,9 +15837,23 @@ function renderInlineJavascriptStep(command, options) {
15479
15837
  `async (row) => {`,
15480
15838
  ...options.precheck ? [` if (${options.precheck}) return null;`] : [],
15481
15839
  ...runIfLines,
15482
- ` return ((row: Record<string, any>, input: Record<string, any>, context: Record<string, any>) => {`,
15840
+ ...options.waterfallSoftFail ? [` try {`] : [],
15841
+ `${options.waterfallSoftFail ? " " : " "}const __dlPayload = __dlRuntimePayload('run_javascript', __dlTemplate(${payload}, row as Record<string, unknown>) as Record<string, unknown>, row as Record<string, unknown>);`,
15842
+ `${options.waterfallSoftFail ? " " : " "}const rawResult = ((row: Record<string, any>, input: Record<string, any>, context: Record<string, any>) => {`,
15843
+ `${options.waterfallSoftFail ? " " : " "} const payload = __dlPayload as Record<string, any>;`,
15844
+ `${options.waterfallSoftFail ? " " : " "} const extract = __dlInlineExtract;`,
15845
+ `${options.waterfallSoftFail ? " " : " "} const extractList = __dlInlineExtractList;`,
15846
+ `${options.waterfallSoftFail ? " " : " "} return (() => {`,
15483
15847
  indent(renderJavascriptBody(code), 4),
15484
- ` })(row as Record<string, any>, row as Record<string, any>, row as Record<string, any>);`,
15848
+ `${options.waterfallSoftFail ? " " : " "} })();`,
15849
+ `${options.waterfallSoftFail ? " " : " "}})(row as Record<string, any>, row as Record<string, any>, row as Record<string, any>);`,
15850
+ `${options.waterfallSoftFail ? " " : " "}const result = await Promise.resolve(rawResult);`,
15851
+ `${options.waterfallSoftFail ? " " : " "}return ${resultExpression};`,
15852
+ ...options.waterfallSoftFail ? [
15853
+ ` } catch (error) {`,
15854
+ ` return __dlExtractorFailure(error);`,
15855
+ ` }`
15856
+ ] : [],
15485
15857
  `}`
15486
15858
  ].join("\n");
15487
15859
  }
@@ -15491,18 +15863,16 @@ function renderJavascriptBody(source) {
15491
15863
  if (/^(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/.test(trimmed)) {
15492
15864
  return `return (${trimmed});`;
15493
15865
  }
15494
- if (trimmed && !trimmed.includes("\n") && !trimmed.includes(";") && !/\breturn\b/.test(trimmed)) {
15866
+ 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(
15867
+ trimmed
15868
+ )) {
15495
15869
  return `return (${trimmed});`;
15496
15870
  }
15497
15871
  return source;
15498
15872
  }
15499
15873
  function renderColumnStep(alias, resolverSource, options = {}) {
15500
15874
  const resolver = indent(resolverSource, 8);
15501
- const optionFields = [
15502
- ...options.recompute === true ? ["recompute: true"] : [],
15503
- ...options.recomputeOnError === true ? ["recomputeOnError: true"] : [],
15504
- ...options.runIfSource ? [`runIf: ${options.runIfSource}`] : []
15505
- ];
15875
+ const optionFields = options.runIfSource ? [`runIf: ${options.runIfSource}`] : [];
15506
15876
  const optionSource = optionFields.length > 0 ? `{ ${optionFields.join(", ")} }` : null;
15507
15877
  return [
15508
15878
  ` .withColumn(${stringLiteral(alias)},`,
@@ -15579,7 +15949,7 @@ function collectGeneratedAliases(commands) {
15579
15949
  }
15580
15950
  return aliases;
15581
15951
  }
15582
- function renderMetadataColumnStep(config, policySource) {
15952
+ function renderMetadataColumnStep(config) {
15583
15953
  const columns = collectMetadataColumns(config.commands);
15584
15954
  if (Object.keys(columns).length === 0) {
15585
15955
  return "";
@@ -15587,7 +15957,6 @@ function renderMetadataColumnStep(config, policySource) {
15587
15957
  return [
15588
15958
  ` .withColumn('_metadata',`,
15589
15959
  ` (row) => __dlMergeMetadata(__dlMetadataFromRow(row), ${stableJson({ columns })}),`,
15590
- ` ${policySource},`,
15591
15960
  ` )`
15592
15961
  ].join("\n");
15593
15962
  }
@@ -15622,16 +15991,11 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15622
15991
  nativeRunIf: Boolean(runIfSource)
15623
15992
  }),
15624
15993
  {
15625
- recompute: force,
15626
- recomputeOnError: true,
15627
15994
  runIfSource
15628
15995
  }
15629
15996
  );
15630
15997
  }).filter((line) => line !== null);
15631
15998
  const aliases = activeChildren.map((nested) => nested.alias);
15632
- const forceParent = forceAliases.has(normalizeAlias(command.with_waterfall)) || activeChildren.some(
15633
- (nested) => forceAliases.has(normalizeAlias(nested.alias))
15634
- );
15635
15999
  const returnExpr = typeof command.min_results === "number" ? `__dlFirstMinResults(row, ${stableJson(aliases)}, ${Math.max(
15636
16000
  1,
15637
16001
  Math.trunc(command.min_results)
@@ -15641,13 +16005,10 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
15641
16005
  }
15642
16006
  return [
15643
16007
  ...columnSteps,
15644
- renderColumnStep(command.with_waterfall, `(row) => ${returnExpr}`, {
15645
- recompute: forceParent
15646
- }),
16008
+ renderColumnStep(command.with_waterfall, `(row) => ${returnExpr}`),
15647
16009
  renderColumnStep(
15648
16010
  `${command.with_waterfall}_source`,
15649
- typeof command.min_results === "number" ? `(row) => __dlContributingAliases(row, ${stableJson(aliases)})` : `(row) => __dlFirstMeaningfulAlias(row, ${stableJson(aliases)})`,
15650
- { recompute: forceParent }
16011
+ typeof command.min_results === "number" ? `(row) => __dlContributingAliases(row, ${stableJson(aliases)})` : `(row) => __dlFirstMeaningfulAlias(row, ${stableJson(aliases)})`
15651
16012
  )
15652
16013
  ];
15653
16014
  }
@@ -15687,19 +16048,15 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15687
16048
  nativeRunIf: Boolean(runIfSource)
15688
16049
  }),
15689
16050
  {
15690
- recompute: force,
15691
- recomputeOnError: true,
15692
16051
  runIfSource
15693
16052
  }
15694
16053
  )
15695
16054
  );
15696
16055
  });
15697
16056
  const columnStepSource = columnSteps.length > 0 ? columnSteps.join("\n") : ` .withColumn('noop', () => null)`;
15698
- const metadataColumnSource = renderMetadataColumnStep(
15699
- config,
15700
- compatibility.metadataCellPolicySource
15701
- );
16057
+ const metadataColumnSource = renderMetadataColumnStep(config);
15702
16058
  const generatedAliases = collectGeneratedAliases(config.commands);
16059
+ const runOptionsSource = options.failFast ? `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart), onRowError: 'fail' as const }` : `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart) }`;
15703
16060
  const body = [
15704
16061
  `export default definePlay(${stringLiteral(playName)}, async (ctx, input: EnrichInput) => {`,
15705
16062
  ` const sourceRows = await ctx.csv<Record<string, unknown>>(input.file);`,
@@ -15710,7 +16067,7 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15710
16067
  ` for await (const row of sourceRows) {`,
15711
16068
  ` if (rowEndExclusive !== undefined && sourceRowIndex >= rowEndExclusive) break;`,
15712
16069
  ` if (sourceRowIndex >= rowStart) {`,
15713
- ` rows.push(__dlPrepareEnrichRow(row, ${stableJson(generatedAliases)}));`,
16070
+ ` rows.push(__dlPrepareEnrichRow(row, ${stableJson(generatedAliases)}, sourceRowIndex));`,
15714
16071
  ` }`,
15715
16072
  ` sourceRowIndex += 1;`,
15716
16073
  ` }`,
@@ -15718,7 +16075,7 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
15718
16075
  ` .dataset(${stringLiteral(mapName)}, rows)`,
15719
16076
  columnStepSource,
15720
16077
  ...metadataColumnSource ? [metadataColumnSource] : [],
15721
- ` .run({ key: (row, index) => __dlStableRowKey(row, index + rowStart) });`,
16078
+ ` .run(${runOptionsSource});`,
15722
16079
  ` return { rows: enriched, count: await enriched.count() };`,
15723
16080
  `}, { description: ${stringLiteral("Read a CSV file, run the configured Deepline enrich commands, and return enriched rows.")} });`
15724
16081
  ];
@@ -15927,6 +16284,7 @@ function helperSource() {
15927
16284
  ` if (typeof value === 'string') {`,
15928
16285
  ` const lower = value.trim().toLowerCase();`,
15929
16286
  ` if (!lower) return false;`,
16287
+ ` if (/^column\\s+.+\\s+failed\\b/.test(lower)) return true;`,
15930
16288
  ` if (lower.startsWith('error:') || lower.includes(': error:') || lower.includes('"error"')) return true;`,
15931
16289
  ` try {`,
15932
16290
  ` return __dlGeneratedCellError(JSON.parse(value));`,
@@ -15970,12 +16328,14 @@ function helperSource() {
15970
16328
  ` return context;`,
15971
16329
  `}`,
15972
16330
  ``,
15973
- `function __dlPrepareEnrichRow(row: Record<string, unknown>, aliases: string[]): Record<string, unknown> {`,
16331
+ `function __dlPrepareEnrichRow(row: Record<string, unknown>, aliases: string[], sourceRowIndex?: number): Record<string, unknown> {`,
15974
16332
  ` const cleaned = __dlStripErroredGeneratedColumns(row, aliases);`,
15975
16333
  ` const templateContext = __dlTemplateContext(cleaned);`,
15976
16334
  ` return {`,
15977
16335
  ` ...templateContext,`,
15978
16336
  ` ...cleaned,`,
16337
+ ` ...(typeof sourceRowIndex === 'number' && '__deeplineSourceRowIndex' in cleaned ? { __deeplineOriginalSourceRowIndex: cleaned.__deeplineSourceRowIndex } : {}),`,
16338
+ ` ...(typeof sourceRowIndex === 'number' ? { __deeplineSourceRowIndex: sourceRowIndex } : {}),`,
15979
16339
  ` __deeplineCsvProjectedFields: Object.keys(templateContext),`,
15980
16340
  ` __deeplineCsvProjectedValues: templateContext,`,
15981
16341
  ` };`,
@@ -16066,6 +16426,10 @@ function helperSource() {
16066
16426
  ` return String(index);`,
16067
16427
  `}`,
16068
16428
  ``,
16429
+ `function __dlEnrichRowKey(row: Record<string, unknown>, index: number): string {`,
16430
+ " return `${__dlStableRowKey(row, index)}:${index}`;",
16431
+ `}`,
16432
+ ``,
16069
16433
  `function __dlScalarValue(value: unknown): unknown {`,
16070
16434
  ` if (value && typeof value === 'object' && !Array.isArray(value)) {`,
16071
16435
  ` const record = value as Record<string, unknown>;`,
@@ -16278,6 +16642,29 @@ function helperSource() {
16278
16642
  ``,
16279
16643
  `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 };`,
16280
16644
  ``,
16645
+ `function __dlInlineExtractorArgs(args: unknown[]): { payload: unknown; selector: unknown } {`,
16646
+ ` if (args.length >= 3) return { payload: args[1], selector: args[2] };`,
16647
+ ` if (args.length >= 2) return { payload: args[0], selector: args[1] };`,
16648
+ ` return { payload: args[0], selector: undefined };`,
16649
+ `}`,
16650
+ ``,
16651
+ `function __dlInlineExtract(...args: unknown[]): unknown {`,
16652
+ ` const { payload, selector } = __dlInlineExtractorArgs(args);`,
16653
+ ` if (selector === undefined) return payload;`,
16654
+ ` const keys = __dlSelectorKeys(selector);`,
16655
+ ` if (keys) return Object.fromEntries(keys.map((key) => [key, __dlExtractTarget(payload, key) ?? null]));`,
16656
+ ` if (Array.isArray(selector)) return __dlFirstByPaths(payload, selector.map(String));`,
16657
+ ` if (typeof selector === 'string') return __dlExtractTarget(payload, selector) ?? __dlFirstByPaths(payload, selector);`,
16658
+ ` return selector;`,
16659
+ `}`,
16660
+ ``,
16661
+ `function __dlInlineExtractList(...args: unknown[]): unknown[] {`,
16662
+ ` const { payload, selector } = __dlInlineExtractorArgs(args);`,
16663
+ ` const rows = __dlFindList(payload, selector);`,
16664
+ ` const keys = __dlSelectorKeys(selector);`,
16665
+ ` return keys ? __dlProjectListRows(rows, keys, payload) : rows;`,
16666
+ `}`,
16667
+ ``,
16281
16668
  `function __dlErrorMessage(error: unknown): string {`,
16282
16669
  ` if (error instanceof Error && error.message) return error.message;`,
16283
16670
  ` if (typeof error === 'string' && error.trim()) return error.trim();`,
@@ -16299,8 +16686,8 @@ function helperSource() {
16299
16686
  ` 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');`,
16300
16687
  `}`,
16301
16688
  ``,
16302
- `function __dlWaterfallToolFailure(error: unknown): unknown {`,
16303
- ` if (__dlRecoverableWaterfallToolError(error)) return __dlExtractorFailure(error);`,
16689
+ `function __dlWaterfallToolFailure(error: unknown, tool?: string): unknown {`,
16690
+ ` if (tool === 'run_javascript' || __dlRecoverableWaterfallToolError(error)) return __dlExtractorFailure(error);`,
16304
16691
  ` throw error;`,
16305
16692
  `}`,
16306
16693
  ``,
@@ -16437,7 +16824,7 @@ function helperSource() {
16437
16824
  ` ...(input.force ? { force: true } : {}),`,
16438
16825
  ` });`,
16439
16826
  ` } catch (error) {`,
16440
- ` if (input.waterfallSoftFail) return __dlWaterfallToolFailure(error);`,
16827
+ ` if (input.waterfallSoftFail) return __dlWaterfallToolFailure(error, input.tool);`,
16441
16828
  ` throw error;`,
16442
16829
  ` }`,
16443
16830
  ` return __dlExtract(input.alias, result, input.row, input.extract, Boolean(input.legacyEnvelope));`,
@@ -16448,6 +16835,10 @@ function helperSource() {
16448
16835
  // src/cli/commands/enrich.ts
16449
16836
  var ENRICH_EXPORT_PAGE_SIZE = 5e3;
16450
16837
  var ENRICH_AUTO_BATCH_ROWS = 250;
16838
+ var ENRICH_EXPORT_BACKING_ROWS_WAIT_MS = 6e4;
16839
+ var ENRICH_EXPORT_BACKING_ROWS_POLL_MS = 1e3;
16840
+ var ENRICH_SOURCE_ROW_INDEX_COLUMN = "__deeplineSourceRowIndex";
16841
+ var ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN = "__deeplineOriginalSourceRowIndex";
16451
16842
  var EXIT_SERVER2 = 5;
16452
16843
  var ENRICH_DEBUG_T0 = Date.now();
16453
16844
  var GENERATED_ENRICH_ROWS_TABLE_NAMESPACE = "deepline_enrich_rows";
@@ -16562,6 +16953,17 @@ function emitEnrichDebug(message) {
16562
16953
  `
16563
16954
  );
16564
16955
  }
16956
+ function sleep6(ms) {
16957
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
16958
+ }
16959
+ function enrichExportBackingRowsWaitMs() {
16960
+ const raw = process.env.DEEPLINE_ENRICH_EXPORT_BACKING_ROWS_WAIT_MS?.trim();
16961
+ if (!raw) {
16962
+ return ENRICH_EXPORT_BACKING_ROWS_WAIT_MS;
16963
+ }
16964
+ const parsed = Number.parseInt(raw, 10);
16965
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : ENRICH_EXPORT_BACKING_ROWS_WAIT_MS;
16966
+ }
16565
16967
  function emitEnrichDebugValidationLines(config) {
16566
16968
  for (const line of buildEnrichDebugValidationLines(config)) {
16567
16969
  emitEnrichDebug(line);
@@ -16574,10 +16976,10 @@ function expandAtFilePath(rawPath) {
16574
16976
  (_match, bareName, bracedName) => process.env[bareName ?? bracedName ?? ""] ?? ""
16575
16977
  );
16576
16978
  if (expanded === "~") {
16577
- return homedir6();
16979
+ return homedir7();
16578
16980
  }
16579
16981
  if (expanded.startsWith("~/") || expanded.startsWith("~\\")) {
16580
- return join6(homedir6(), expanded.slice(2));
16982
+ return join7(homedir7(), expanded.slice(2));
16581
16983
  }
16582
16984
  return expanded;
16583
16985
  }
@@ -16711,6 +17113,7 @@ async function buildPlanArgs(args) {
16711
17113
  "--dry-run",
16712
17114
  "--json",
16713
17115
  "--force",
17116
+ "--fail-fast",
16714
17117
  "--all",
16715
17118
  "--in-place",
16716
17119
  "--no-open"
@@ -16761,7 +17164,7 @@ async function buildPlanArgs(args) {
16761
17164
  return planArgs;
16762
17165
  }
16763
17166
  async function assertInputCsvExists(inputCsv) {
16764
- const path = resolve8(inputCsv);
17167
+ const path = resolve9(inputCsv);
16765
17168
  try {
16766
17169
  const info = await stat(path);
16767
17170
  if (info.isFile()) {
@@ -16775,8 +17178,8 @@ async function assertInputCsvExists(inputCsv) {
16775
17178
  }
16776
17179
  }
16777
17180
  async function assertSafeOutputPath(inputCsv, outputPath) {
16778
- const input2 = resolve8(inputCsv);
16779
- const output2 = resolve8(outputPath);
17181
+ const input2 = resolve9(inputCsv);
17182
+ const output2 = resolve9(outputPath);
16780
17183
  if (input2 === output2) {
16781
17184
  throw new Error(
16782
17185
  "--input and --output must be different files when not using --in-place."
@@ -16805,7 +17208,7 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
16805
17208
  }
16806
17209
  async function regularFileExists(path) {
16807
17210
  try {
16808
- const info = await stat(resolve8(path));
17211
+ const info = await stat(resolve9(path));
16809
17212
  return info.isFile();
16810
17213
  } catch (error) {
16811
17214
  const code = error && typeof error === "object" ? error.code : void 0;
@@ -16816,7 +17219,7 @@ async function regularFileExists(path) {
16816
17219
  }
16817
17220
  }
16818
17221
  async function readConfig(path) {
16819
- const source = await readFile(resolve8(path), "utf8");
17222
+ const source = await readFile(resolve9(path), "utf8");
16820
17223
  let parsed;
16821
17224
  try {
16822
17225
  parsed = JSON.parse(source);
@@ -17093,15 +17496,47 @@ function isPlayStartStreamEndedError(error) {
17093
17496
  "Play start stream ended before a terminal status"
17094
17497
  );
17095
17498
  }
17096
- async function runGeneratedEnrichPlay(runArgs, options = {}) {
17499
+ function runIdFromGeneratedEnrichWatchError(error) {
17500
+ if (error instanceof DeeplineError) {
17501
+ const detailRunId = typeof error.details?.runId === "string" ? error.details.runId : typeof error.details?.workflowId === "string" ? error.details.workflowId : null;
17502
+ if (detailRunId?.trim()) {
17503
+ return detailRunId.trim();
17504
+ }
17505
+ }
17506
+ const message = error instanceof Error ? error.message : String(error ?? "");
17507
+ return message.match(/\b(play\/\S+\/run\/\S+)/)?.[1] ?? null;
17508
+ }
17509
+ function shouldStopGeneratedEnrichRunAfterWatchError(error) {
17510
+ if (error instanceof DeeplineError) {
17511
+ return error.code === "PLAY_WAIT_TIMEOUT" || error.code === "PLAY_START_STREAM_ENDED" || error.code === "PLAY_LIVE_STREAM_ENDED";
17512
+ }
17513
+ if (!(error instanceof Error)) {
17514
+ return false;
17515
+ }
17516
+ return error.message.includes("Timed out waiting for play") || error.message.includes("ended before a terminal status");
17517
+ }
17518
+ async function stopGeneratedEnrichRunAfterWatchError(client2, error) {
17519
+ if (!shouldStopGeneratedEnrichRunAfterWatchError(error)) {
17520
+ return;
17521
+ }
17522
+ const runId = runIdFromGeneratedEnrichWatchError(error);
17523
+ if (!runId) {
17524
+ return;
17525
+ }
17526
+ await client2.runs.stop(runId, {
17527
+ reason: "deepline enrich watch exited before terminal status"
17528
+ }).catch(() => void 0);
17529
+ }
17530
+ async function runGeneratedEnrichPlay(client2, runArgs, options = {}) {
17097
17531
  for (let attempt = 0; attempt < 2; attempt += 1) {
17098
17532
  try {
17099
17533
  return await captureStdout(() => handlePlayRun(runArgs), {
17100
17534
  passthrough: options.passthroughStdout
17101
17535
  });
17102
17536
  } catch (error) {
17537
+ await stopGeneratedEnrichRunAfterWatchError(client2, error);
17103
17538
  if (attempt === 0 && isPlayStartStreamEndedError(error)) {
17104
- await new Promise((resolve13) => setTimeout(resolve13, 250));
17539
+ await sleep6(250);
17105
17540
  continue;
17106
17541
  }
17107
17542
  throw error;
@@ -17121,20 +17556,41 @@ async function writeOutputCsv(outputPath, status, options) {
17121
17556
  "The generated play did not return row-shaped output, and no durable enrich rows were available to export."
17122
17557
  );
17123
17558
  }
17124
- if (options?.client) {
17125
- rowsInfo = await fetchBackingRowsForCsvExport({
17126
- client: options.client,
17127
- status,
17128
- rowsInfo
17129
- }).catch(() => null) ?? rowsInfo;
17559
+ const selectedSourceRows = selectedSourceCsvRowCount(options);
17560
+ const shouldFetchBackingRows = options?.client && shouldFetchBackingRowsForEnrichExport(rowsInfo, status, {
17561
+ selectedSourceRows
17562
+ });
17563
+ if (options?.client && shouldFetchBackingRows) {
17564
+ let fetchedRowsInfo = null;
17565
+ try {
17566
+ fetchedRowsInfo = await fetchBackingRowsForCsvExport({
17567
+ client: options.client,
17568
+ status,
17569
+ rowsInfo,
17570
+ sourceRowStart: options.rows?.rowStart ?? 0,
17571
+ expectedRows: selectedSourceRows
17572
+ });
17573
+ } catch (error) {
17574
+ throw new Error(
17575
+ `Failed to fetch durable generated enrich rows for CSV export: ${error instanceof Error ? error.message : String(error)}`
17576
+ );
17577
+ }
17578
+ rowsInfo = fetchedRowsInfo ?? rowsInfo;
17130
17579
  }
17131
17580
  const allowPartial = options?.allowPartial === true && !rowsInfo.complete && rowsInfo.rows.length > 0 && Boolean(options?.sourceCsvPath);
17132
17581
  assertCompleteRowsForCsvExport(rowsInfo, status, outputPath, {
17133
17582
  allowPartial
17134
17583
  });
17584
+ const statusFailureMessages = options?.config && rowsInfo.rows.length > 0 ? collectCompleteStatusFailureMessages({
17585
+ config: options.config,
17586
+ status,
17587
+ rowRange: options.rows ?? { rowStart: 0, rowEnd: null },
17588
+ rowCount: rowsInfo.rows.length
17589
+ }) : /* @__PURE__ */ new Map();
17135
17590
  const merged = mergeRowsForCsvExport(rowsInfo.rows, {
17136
17591
  ...options,
17137
- allowPartial
17592
+ allowPartial,
17593
+ statusFailureMessages
17138
17594
  });
17139
17595
  const columns = orderEnrichCsvColumns(
17140
17596
  dataExportColumns(merged.rows, [
@@ -17144,7 +17600,7 @@ async function writeOutputCsv(outputPath, status, options) {
17144
17600
  options?.config
17145
17601
  );
17146
17602
  await writeFile3(
17147
- resolve8(outputPath),
17603
+ resolve9(outputPath),
17148
17604
  csvStringFromRows(merged.rows, columns),
17149
17605
  "utf8"
17150
17606
  );
@@ -17154,7 +17610,7 @@ async function writeOutputCsv(outputPath, status, options) {
17154
17610
  selectedRows: rowsInfo.totalRows,
17155
17611
  enrichedRows: rowsInfo.rows.length,
17156
17612
  rows: merged.rows.length,
17157
- path: resolve8(outputPath),
17613
+ path: resolve9(outputPath),
17158
17614
  partial: !rowsInfo.complete,
17159
17615
  enrichedDataRows: rowsInfo.rows
17160
17616
  };
@@ -17198,16 +17654,23 @@ async function buildEnrichFailureReport(input2) {
17198
17654
  rows: input2.rows,
17199
17655
  rowRange: input2.rowRange,
17200
17656
  client: input2.client,
17201
- outputPath: input2.exportResult?.path ?? input2.outputPath ?? null
17657
+ outputPath: input2.exportResult?.path ?? input2.outputPath ?? null,
17658
+ status: input2.status
17202
17659
  });
17203
17660
  }
17204
17661
  function recordField(value, key) {
17205
17662
  return value && typeof value === "object" && !Array.isArray(value) ? value[key] : void 0;
17206
17663
  }
17207
17664
  function extractRunId(status) {
17665
+ const run = recordField(status, "run");
17666
+ const nestedRun = recordField(run, "run");
17208
17667
  const candidates = [
17209
17668
  recordField(status, "runId"),
17210
- recordField(recordField(status, "run"), "id")
17669
+ recordField(status, "id"),
17670
+ recordField(run, "runId"),
17671
+ recordField(run, "id"),
17672
+ recordField(nestedRun, "runId"),
17673
+ recordField(nestedRun, "id")
17211
17674
  ];
17212
17675
  for (const candidate of candidates) {
17213
17676
  if (typeof candidate === "string" && candidate.trim()) {
@@ -17282,20 +17745,102 @@ function fallbackRowsInfoForGeneratedEnrichExport(status, options) {
17282
17745
  if (totalRows === null) {
17283
17746
  return null;
17284
17747
  }
17285
- const tableNamespaces = /* @__PURE__ */ new Set();
17286
- collectStringFields(status, "tableNamespace", tableNamespaces);
17287
- collectStringFields(status, "artifactTableNamespace", tableNamespaces);
17288
- const tableNamespace = tableNamespaces.values().next().value ?? GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
17289
17748
  return {
17290
17749
  rows: [],
17291
17750
  totalRows,
17292
17751
  columns: [],
17293
17752
  columnsExplicit: false,
17294
17753
  complete: false,
17295
- source: tableNamespace,
17296
- tableNamespace
17754
+ source: GENERATED_ENRICH_ROWS_TABLE_NAMESPACE,
17755
+ tableNamespace: GENERATED_ENRICH_ROWS_TABLE_NAMESPACE
17297
17756
  };
17298
17757
  }
17758
+ function hasLossyPreviewPlaceholder(value, depth = 0) {
17759
+ if (depth > 8) {
17760
+ return false;
17761
+ }
17762
+ if (value === "[Array]" || value === "[Object]") {
17763
+ return true;
17764
+ }
17765
+ if (Array.isArray(value)) {
17766
+ return value.some((item) => hasLossyPreviewPlaceholder(item, depth + 1));
17767
+ }
17768
+ if (value && typeof value === "object") {
17769
+ return Object.values(value).some(
17770
+ (item) => hasLossyPreviewPlaceholder(item, depth + 1)
17771
+ );
17772
+ }
17773
+ return false;
17774
+ }
17775
+ function shouldFetchBackingRowsForEnrichExport(rowsInfo, status, options = {}) {
17776
+ const terminalStatus = readEnrichRunStatus(status);
17777
+ const tableNamespace = rowsInfo.tableNamespace?.trim();
17778
+ if (terminalStatus === "failed" || terminalStatus === "cancelled") {
17779
+ return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && (rowsInfo.recovered === true || hasPartialRunOutputWarning(status));
17780
+ }
17781
+ if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
17782
+ return true;
17783
+ }
17784
+ if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && hasFailedRowSignal(status)) {
17785
+ return true;
17786
+ }
17787
+ if (!rowsInfo.complete) {
17788
+ return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
17789
+ }
17790
+ return rowsInfo.rows.some((row) => hasLossyPreviewPlaceholder(row));
17791
+ }
17792
+ function hasPartialRunOutputWarning(status) {
17793
+ const warningLists = [
17794
+ recordField(status, "warnings"),
17795
+ recordField(recordField(status, "run"), "warnings")
17796
+ ];
17797
+ return warningLists.some(
17798
+ (warnings) => Array.isArray(warnings) && warnings.some(
17799
+ (warning) => typeof warning === "string" && warning.includes("Run output is partial: showing") && warning.includes("preview row(s)")
17800
+ )
17801
+ );
17802
+ }
17803
+ function numericFailedRowSignal(value) {
17804
+ if (typeof value === "number" && Number.isFinite(value)) {
17805
+ return value;
17806
+ }
17807
+ if (typeof value !== "string") {
17808
+ return 0;
17809
+ }
17810
+ const match = value.match(/^\s*(\d+)/);
17811
+ return match ? Number(match[1]) : 0;
17812
+ }
17813
+ function hasFailedRowSignal(value, depth = 0) {
17814
+ if (depth > 16 || !value || typeof value !== "object") {
17815
+ return false;
17816
+ }
17817
+ if (Array.isArray(value)) {
17818
+ return value.some((item) => hasFailedRowSignal(item, depth + 1));
17819
+ }
17820
+ for (const [key, child] of Object.entries(value)) {
17821
+ const normalizedKey = key.toLowerCase().replace(/[^a-z0-9]/g, "");
17822
+ if ((normalizedKey === "failed" || normalizedKey === "failedrows" || normalizedKey === "failedcount") && numericFailedRowSignal(child) > 0) {
17823
+ return true;
17824
+ }
17825
+ if (hasFailedRowSignal(child, depth + 1)) {
17826
+ return true;
17827
+ }
17828
+ }
17829
+ return false;
17830
+ }
17831
+ function readEnrichRunStatus(status) {
17832
+ const candidates = [
17833
+ recordField(status, "status"),
17834
+ recordField(recordField(status, "run"), "status"),
17835
+ recordField(recordField(status, "progress"), "status")
17836
+ ];
17837
+ for (const candidate of candidates) {
17838
+ if (typeof candidate === "string" && candidate.trim()) {
17839
+ return candidate.trim().toLowerCase();
17840
+ }
17841
+ }
17842
+ return null;
17843
+ }
17299
17844
  function firstCollectedStringField(value, key) {
17300
17845
  const fields = /* @__PURE__ */ new Set();
17301
17846
  collectStringFields(value, key, fields);
@@ -17323,14 +17868,22 @@ function emitPlainBatchRunFailure(input2) {
17323
17868
  );
17324
17869
  }
17325
17870
  }
17326
- function exportableSheetRow2(row) {
17871
+ function exportableSheetRow2(row, sourceRowStart = 0) {
17327
17872
  if (!row || typeof row !== "object" || Array.isArray(row)) {
17328
17873
  return null;
17329
17874
  }
17330
17875
  const record = row;
17331
17876
  const data = record.data;
17332
17877
  if (data && typeof data === "object" && !Array.isArray(data)) {
17333
- return data;
17878
+ const exported = { ...data };
17879
+ const inputIndex = typeof record.inputIndex === "number" ? record.inputIndex : typeof record.inputIndex === "string" && record.inputIndex.trim() ? Number(record.inputIndex) : Number.NaN;
17880
+ if (Number.isInteger(inputIndex) && inputIndex >= 0) {
17881
+ if (ENRICH_SOURCE_ROW_INDEX_COLUMN in exported) {
17882
+ exported[ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN] = exported[ENRICH_SOURCE_ROW_INDEX_COLUMN];
17883
+ }
17884
+ exported[ENRICH_SOURCE_ROW_INDEX_COLUMN] = sourceRowStart + inputIndex;
17885
+ }
17886
+ return exported;
17334
17887
  }
17335
17888
  const fallback = { ...record };
17336
17889
  for (const key of [
@@ -17350,6 +17903,28 @@ function exportableSheetRow2(row) {
17350
17903
  }
17351
17904
  return fallback;
17352
17905
  }
17906
+ function sourceRowIndexFromEnrichRow(row, start, end) {
17907
+ const value = row[ENRICH_SOURCE_ROW_INDEX_COLUMN];
17908
+ const parsed = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : Number.NaN;
17909
+ if (!Number.isInteger(parsed) || parsed < start || parsed > end) {
17910
+ return null;
17911
+ }
17912
+ return parsed;
17913
+ }
17914
+ function stripEnrichSourceRowIndex(row) {
17915
+ if (!(ENRICH_SOURCE_ROW_INDEX_COLUMN in row)) {
17916
+ return row;
17917
+ }
17918
+ const stripped = { ...row };
17919
+ const hadOriginal = ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN in stripped;
17920
+ const originalSourceRowIndex = stripped[ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN];
17921
+ delete stripped[ENRICH_SOURCE_ROW_INDEX_COLUMN];
17922
+ delete stripped[ENRICH_ORIGINAL_SOURCE_ROW_INDEX_COLUMN];
17923
+ if (hadOriginal) {
17924
+ stripped[ENRICH_SOURCE_ROW_INDEX_COLUMN] = originalSourceRowIndex;
17925
+ }
17926
+ return stripped;
17927
+ }
17353
17928
  function collectHardFailureAliases(config) {
17354
17929
  const aliases = [];
17355
17930
  const seen = /* @__PURE__ */ new Set();
@@ -17371,6 +17946,14 @@ function collectHardFailureAliases(config) {
17371
17946
  }
17372
17947
  function cellFailureError(value) {
17373
17948
  const parsed = parseMaybeJsonObject(value);
17949
+ if (!isRecord7(parsed)) {
17950
+ const text = typeof parsed === "string" ? parsed.trim() : "";
17951
+ if (/^(?:[A-Za-z0-9_:-]+:\s*)?(?:Error|TypeError|ReferenceError|SyntaxError|RangeError):\s+/.test(
17952
+ text
17953
+ ) || /^(?:[A-Za-z0-9_:-]+:\s*)?Column status:\s*(?:error|failed)\b/i.test(text)) {
17954
+ return { message: text };
17955
+ }
17956
+ }
17374
17957
  if (!isRecord7(parsed)) {
17375
17958
  return null;
17376
17959
  }
@@ -17402,7 +17985,9 @@ function buildEnrichWaterfallSummaryLines(config, rows) {
17402
17985
  continue;
17403
17986
  }
17404
17987
  const failures = rows.filter(
17405
- (row) => cellFailureError(row[child.alias])
17988
+ (row) => aliasFailureCellCandidates(row, child.alias).some(
17989
+ (candidate) => Boolean(cellFailureError(candidate))
17990
+ )
17406
17991
  ).length;
17407
17992
  if (failures > 0) {
17408
17993
  lines.push(
@@ -17413,6 +17998,56 @@ function buildEnrichWaterfallSummaryLines(config, rows) {
17413
17998
  }
17414
17999
  return lines;
17415
18000
  }
18001
+ function aliasFailureCellCandidates(row, alias) {
18002
+ const candidates = [row[alias]];
18003
+ const nested = {};
18004
+ const dottedPrefix = `${alias}.`;
18005
+ const underscorePrefix = `${alias}__`;
18006
+ for (const [key, value] of Object.entries(row)) {
18007
+ if (key.startsWith(dottedPrefix)) {
18008
+ assignFlattenedFailurePath(nested, key.slice(dottedPrefix.length), value);
18009
+ } else if (key.startsWith(underscorePrefix)) {
18010
+ assignFlattenedFailurePath(nested, key.slice(underscorePrefix.length), value);
18011
+ }
18012
+ }
18013
+ if (Object.keys(nested).length > 0) {
18014
+ candidates.push(nested);
18015
+ }
18016
+ return candidates;
18017
+ }
18018
+ function assignFlattenedFailurePath(target, field, value) {
18019
+ const parts = field.includes(".") ? field.split(".") : field.split("__");
18020
+ const normalized = parts.map((part) => part.trim()).filter(Boolean);
18021
+ if (normalized.length <= 1) {
18022
+ target[field] = value;
18023
+ return;
18024
+ }
18025
+ let cursor = target;
18026
+ for (const part of normalized.slice(0, -1)) {
18027
+ const existing = cursor[part];
18028
+ if (!isRecord7(existing)) {
18029
+ const next = {};
18030
+ cursor[part] = next;
18031
+ cursor = next;
18032
+ } else {
18033
+ cursor = existing;
18034
+ }
18035
+ }
18036
+ cursor[normalized[normalized.length - 1] ?? field] = value;
18037
+ }
18038
+ function aliasFlattenedCells(row, alias) {
18039
+ const cells = [];
18040
+ const dottedPrefix = `${alias}.`;
18041
+ const underscorePrefix = `${alias}__`;
18042
+ for (const [key, value] of Object.entries(row)) {
18043
+ if (key.startsWith(dottedPrefix)) {
18044
+ cells.push({ field: key.slice(dottedPrefix.length), value });
18045
+ } else if (key.startsWith(underscorePrefix)) {
18046
+ cells.push({ field: key.slice(underscorePrefix.length), value });
18047
+ }
18048
+ }
18049
+ return cells;
18050
+ }
17416
18051
  function collectEnrichFailureJobs(input2) {
17417
18052
  const aliases = collectHardFailureAliases(input2.config);
17418
18053
  if (aliases.length === 0 || input2.rows.length === 0) {
@@ -17422,11 +18057,13 @@ function collectEnrichFailureJobs(input2) {
17422
18057
  const jobs = [];
17423
18058
  input2.rows.forEach((row, rowIndex) => {
17424
18059
  aliases.forEach((alias, aliasIndex) => {
17425
- const failure = cellFailureError(row[alias]);
18060
+ const failure = aliasFailureCellCandidates(row, alias).map(cellFailureError).find(
18061
+ (candidate) => Boolean(candidate)
18062
+ );
17426
18063
  if (!failure) {
17427
18064
  return;
17428
18065
  }
17429
- const rowId = rowOffset + rowIndex;
18066
+ const rowId = sourceRowIndexFromEnrichRow(row, 0, Number.MAX_SAFE_INTEGER) ?? rowOffset + rowIndex;
17430
18067
  jobs.push({
17431
18068
  job_id: `row-${rowId}-${alias}`,
17432
18069
  row_id: rowId,
@@ -17442,6 +18079,72 @@ function collectEnrichFailureJobs(input2) {
17442
18079
  });
17443
18080
  return jobs;
17444
18081
  }
18082
+ function collectStatusFailureJobs(input2) {
18083
+ const aliases = collectHardFailureAliases(input2.config);
18084
+ if (aliases.length === 0) {
18085
+ return [];
18086
+ }
18087
+ const summaries = collectColumnStats(input2.status);
18088
+ const rowStart = input2.rowRange.rowStart ?? 0;
18089
+ const selectedRows = input2.rowRange.rowEnd !== null && input2.rowRange.rowEnd >= rowStart ? input2.rowRange.rowEnd - rowStart + 1 : Number.MAX_SAFE_INTEGER;
18090
+ const jobs = [];
18091
+ aliases.forEach((alias, aliasIndex) => {
18092
+ const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
18093
+ if (!stat2) {
18094
+ return;
18095
+ }
18096
+ const execution = isRecord7(stat2.execution) ? stat2.execution : null;
18097
+ const failedCount = Math.min(
18098
+ selectedRows,
18099
+ Math.max(
18100
+ numericFailedRowSignal(stat2.failed),
18101
+ numericFailedRowSignal(stat2.failedRows),
18102
+ numericFailedRowSignal(execution?.failed)
18103
+ )
18104
+ );
18105
+ if (!Number.isFinite(failedCount) || failedCount <= 0) {
18106
+ return;
18107
+ }
18108
+ const message = firstCollectedStringField(stat2, "error") ?? firstCollectedStringField(stat2, "message") ?? `Column ${alias} failed for ${failedCount} row(s).`;
18109
+ for (let offset = 0; offset < failedCount; offset += 1) {
18110
+ const rowId = rowStart + offset;
18111
+ jobs.push({
18112
+ job_id: `row-${rowId}-${alias}`,
18113
+ row_id: rowId,
18114
+ col_index: aliasIndex,
18115
+ column: alias,
18116
+ status: "failed",
18117
+ last_error: message,
18118
+ error: message
18119
+ });
18120
+ }
18121
+ });
18122
+ return jobs;
18123
+ }
18124
+ function collectCompleteStatusFailureMessages(input2) {
18125
+ const requiredCount = Math.max(1, Math.trunc(input2.rowCount));
18126
+ const jobs = collectStatusFailureJobs({
18127
+ config: input2.config,
18128
+ status: input2.status,
18129
+ rowRange: input2.rowRange
18130
+ });
18131
+ const byAlias = /* @__PURE__ */ new Map();
18132
+ for (const job of jobs) {
18133
+ const alias = normalizeAlias2(job.column);
18134
+ const existing = byAlias.get(alias);
18135
+ byAlias.set(alias, {
18136
+ count: (existing?.count ?? 0) + 1,
18137
+ message: existing?.message ?? job.last_error
18138
+ });
18139
+ }
18140
+ const complete = /* @__PURE__ */ new Map();
18141
+ for (const [alias, value] of byAlias) {
18142
+ if (value.count >= requiredCount) {
18143
+ complete.set(alias, value.message);
18144
+ }
18145
+ }
18146
+ return complete;
18147
+ }
17445
18148
  function parseExecutionCount(value) {
17446
18149
  if (typeof value === "number" && Number.isFinite(value)) {
17447
18150
  return Math.max(0, Math.trunc(value));
@@ -17584,9 +18287,9 @@ async function persistEnrichFailureReport(input2) {
17584
18287
  if (input2.jobs.length === 0) {
17585
18288
  return null;
17586
18289
  }
17587
- const stateDir = join6(homedir6(), ".local", "deepline", "runtime", "state");
18290
+ const stateDir = join7(homedir7(), ".local", "deepline", "runtime", "state");
17588
18291
  await mkdir3(stateDir, { recursive: true });
17589
- const reportPath = join6(
18292
+ const reportPath = join7(
17590
18293
  stateDir,
17591
18294
  `run-block-failures-${Math.floor(Date.now() / 1e3)}-${process.pid}.json`
17592
18295
  );
@@ -17615,11 +18318,16 @@ async function persistEnrichFailureReport(input2) {
17615
18318
  return reportPath;
17616
18319
  }
17617
18320
  async function maybeEmitEnrichFailureReport(input2) {
17618
- const jobs = collectEnrichFailureJobs({
18321
+ const rowJobs = collectEnrichFailureJobs({
17619
18322
  config: input2.config,
17620
18323
  rows: input2.rows,
17621
18324
  rowStart: input2.rowRange.rowStart
17622
18325
  });
18326
+ const jobs = rowJobs.length > 0 || input2.status === void 0 ? rowJobs : collectStatusFailureJobs({
18327
+ config: input2.config,
18328
+ status: input2.status,
18329
+ rowRange: input2.rowRange
18330
+ });
17623
18331
  if (jobs.length === 0) {
17624
18332
  return null;
17625
18333
  }
@@ -17677,75 +18385,139 @@ function mergePreferredColumns(preferredColumns, rows) {
17677
18385
  async function fetchBackingRowsForCsvExport(input2) {
17678
18386
  const runId = extractRunId(input2.status);
17679
18387
  const playName = extractPlayName2(input2.status);
17680
- const tableNamespace = input2.rowsInfo.tableNamespace?.trim();
18388
+ const tableNamespace = input2.rowsInfo.tableNamespace?.trim() || GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
17681
18389
  if (!runId || !playName || !tableNamespace) {
17682
18390
  return null;
17683
18391
  }
17684
- const sheetRows = [];
17685
- let offset = 0;
17686
- let expectedTotal = input2.rowsInfo.totalRows;
17687
- while (true) {
17688
- const page = await input2.client.runs.exportDatasetRows({
17689
- playName,
17690
- tableNamespace,
17691
- runId,
17692
- limit: ENRICH_EXPORT_PAGE_SIZE,
17693
- offset,
17694
- rowMode: "all"
17695
- });
17696
- sheetRows.push(...page.rows);
17697
- const summaryTotal = page.summary?.stats?.total;
17698
- if (typeof summaryTotal === "number" && Number.isFinite(summaryTotal)) {
17699
- expectedTotal = Math.max(expectedTotal, Math.trunc(summaryTotal));
18392
+ const deadline = Date.now() + enrichExportBackingRowsWaitMs();
18393
+ let lastRows = [];
18394
+ const minimumExpectedRows = typeof input2.expectedRows === "number" && input2.expectedRows > 0 ? Math.trunc(input2.expectedRows) : input2.rowsInfo.totalRows;
18395
+ let lastExpectedTotal = minimumExpectedRows;
18396
+ for (; ; ) {
18397
+ const sheetRows = [];
18398
+ let offset = 0;
18399
+ let expectedTotal = minimumExpectedRows;
18400
+ while (true) {
18401
+ const page = await input2.client.runs.exportDatasetRows({
18402
+ playName,
18403
+ tableNamespace,
18404
+ runId,
18405
+ limit: ENRICH_EXPORT_PAGE_SIZE,
18406
+ offset,
18407
+ rowMode: "all"
18408
+ });
18409
+ sheetRows.push(...page.rows);
18410
+ const summaryTotal = page.summary?.stats?.total;
18411
+ if (typeof summaryTotal === "number" && Number.isFinite(summaryTotal)) {
18412
+ expectedTotal = Math.max(expectedTotal, Math.trunc(summaryTotal));
18413
+ }
18414
+ if (page.rows.length < ENRICH_EXPORT_PAGE_SIZE || sheetRows.length >= expectedTotal) {
18415
+ break;
18416
+ }
18417
+ offset += page.rows.length;
17700
18418
  }
17701
- if (page.rows.length < ENRICH_EXPORT_PAGE_SIZE || sheetRows.length >= expectedTotal) {
18419
+ const rows = sheetRows.map((row) => exportableSheetRow2(row, input2.sourceRowStart ?? 0)).filter((row) => Boolean(row));
18420
+ lastRows = rows;
18421
+ lastExpectedTotal = expectedTotal;
18422
+ if (expectedTotal > 0 && rows.length >= expectedTotal || expectedTotal === 0 && rows.length > 0) {
18423
+ return {
18424
+ ...input2.rowsInfo,
18425
+ rows,
18426
+ columns: mergePreferredColumns(
18427
+ input2.rowsInfo.columnsExplicit ? input2.rowsInfo.columns : [],
18428
+ rows
18429
+ ),
18430
+ totalRows: Math.max(rows.length, expectedTotal),
18431
+ complete: true,
18432
+ source: `${input2.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
18433
+ };
18434
+ }
18435
+ if (Date.now() >= deadline) {
17702
18436
  break;
17703
18437
  }
17704
- offset += page.rows.length;
18438
+ await sleep6(ENRICH_EXPORT_BACKING_ROWS_POLL_MS);
17705
18439
  }
17706
- const rows = sheetRows.map(exportableSheetRow2).filter((row) => Boolean(row));
17707
- if (rows.length < input2.rowsInfo.totalRows) {
18440
+ if (lastRows.length <= input2.rowsInfo.rows.length) {
17708
18441
  return null;
17709
18442
  }
17710
18443
  return {
17711
18444
  ...input2.rowsInfo,
17712
- rows,
18445
+ rows: lastRows,
17713
18446
  columns: mergePreferredColumns(
17714
18447
  input2.rowsInfo.columnsExplicit ? input2.rowsInfo.columns : [],
17715
- rows
18448
+ lastRows
17716
18449
  ),
17717
- totalRows: rows.length,
17718
- complete: true,
18450
+ totalRows: Math.max(lastExpectedTotal, input2.rowsInfo.totalRows),
18451
+ complete: false,
17719
18452
  source: `${input2.rowsInfo.source ?? "result.rows"} -> /api/v2/plays/${playName}/sheet?tableNamespace=${tableNamespace}`
17720
18453
  };
17721
18454
  }
17722
18455
  function mergeRowsForCsvExport(enrichedRows, options) {
17723
- const rows = dataExportRows(normalizeEnrichRowsForCsvExport(enrichedRows));
18456
+ const rows = dataExportRows(
18457
+ normalizeEnrichRowsForCsvExport(enrichedRows, options?.config, {
18458
+ statusFailureMessages: options?.statusFailureMessages
18459
+ })
18460
+ );
17724
18461
  const range = options?.rows;
17725
- if (!options?.sourceCsvPath || !options.inPlace && !options.allowPartial && (range?.rowStart === null || range?.rowStart === void 0)) {
17726
- return { rows, preferredColumns: [] };
18462
+ if (!options?.sourceCsvPath) {
18463
+ return {
18464
+ rows: rows.map(stripEnrichSourceRowIndex),
18465
+ preferredColumns: []
18466
+ };
17727
18467
  }
17728
18468
  const parsedBaseRows = readCsvRows(options.sourceCsvPath);
17729
18469
  const preferredColumns = Object.keys(parsedBaseRows[0] ?? {});
17730
18470
  const baseRows = parsedBaseRows.map(
17731
- (row) => ({ ...row })
18471
+ (row) => ({
18472
+ ...row
18473
+ })
17732
18474
  );
17733
18475
  const start = Math.max(0, range?.rowStart ?? 0);
17734
18476
  const maxEnd = Math.max(start, baseRows.length - 1);
17735
18477
  const inclusiveEnd = range?.rowEnd === null || range?.rowEnd === void 0 ? maxEnd : Math.min(maxEnd, range.rowEnd);
17736
18478
  const expectedSelectedRows = baseRows.length === 0 ? 0 : Math.max(0, inclusiveEnd - start + 1);
17737
- if (rows.length < expectedSelectedRows && !options.allowPartial) {
18479
+ const canMergeSparseBySourceIndex = rows.length > 0 && rows.every(
18480
+ (row) => sourceRowIndexFromEnrichRow(row, start, inclusiveEnd) !== null
18481
+ );
18482
+ if (rows.length < expectedSelectedRows && !options.allowPartial && !canMergeSparseBySourceIndex) {
17738
18483
  throw new Error(
17739
18484
  `Refusing to write a partial in-place CSV export: the run returned ${rows.length} row(s) for ${expectedSelectedRows} selected source row(s).`
17740
18485
  );
17741
18486
  }
17742
18487
  const merged = [...baseRows];
18488
+ if (canMergeSparseBySourceIndex) {
18489
+ for (const rawEnriched of rows) {
18490
+ const rowIndex = sourceRowIndexFromEnrichRow(
18491
+ rawEnriched,
18492
+ start,
18493
+ inclusiveEnd
18494
+ );
18495
+ if (rowIndex === null) {
18496
+ continue;
18497
+ }
18498
+ const enriched = stripEnrichSourceRowIndex(rawEnriched);
18499
+ const base = merged[rowIndex] ?? {};
18500
+ merged[rowIndex] = {
18501
+ ...base,
18502
+ ...enriched
18503
+ };
18504
+ const metadata = mergeLegacyMetadataCell(
18505
+ base._metadata,
18506
+ enriched._metadata
18507
+ );
18508
+ if (metadata !== void 0) {
18509
+ merged[rowIndex]._metadata = metadata;
18510
+ }
18511
+ }
18512
+ return { rows: merged, preferredColumns };
18513
+ }
17743
18514
  let selectedIndex = 0;
17744
18515
  for (let rowIndex = start; rowIndex <= inclusiveEnd; rowIndex += 1) {
17745
- const enriched = rows[selectedIndex++];
17746
- if (!enriched) {
18516
+ const rawEnriched = rows[selectedIndex++];
18517
+ if (!rawEnriched) {
17747
18518
  break;
17748
18519
  }
18520
+ const enriched = stripEnrichSourceRowIndex(rawEnriched);
17749
18521
  const base = merged[rowIndex] ?? {};
17750
18522
  merged[rowIndex] = {
17751
18523
  ...base,
@@ -17824,21 +18596,146 @@ function orderEnrichCsvColumns(columns, config) {
17824
18596
  function isNonEmptyCsvCell(value) {
17825
18597
  return value !== null && value !== void 0 && String(value).trim() !== "";
17826
18598
  }
17827
- function normalizeEnrichRowsForCsvExport(rows) {
18599
+ var ENRICH_FLATTENED_SUCCESS_FIELD_PRIORITY = [
18600
+ "matched_result",
18601
+ "matchedResult",
18602
+ "value",
18603
+ "email",
18604
+ "url",
18605
+ "domain",
18606
+ "name",
18607
+ "result"
18608
+ ];
18609
+ var ENRICH_FLATTENED_CONTROL_FIELDS = /* @__PURE__ */ new Set([
18610
+ "error",
18611
+ "last_error",
18612
+ "message",
18613
+ "operation",
18614
+ "provider",
18615
+ "status"
18616
+ ]);
18617
+ function materializeCsvCellValue(value) {
18618
+ if (value && typeof value === "object") {
18619
+ return JSON.stringify(value);
18620
+ }
18621
+ return value;
18622
+ }
18623
+ function materializeAliasSuccessCell(row, alias) {
18624
+ const direct = row[alias];
18625
+ if (isRecord7(direct)) {
18626
+ if (Object.prototype.hasOwnProperty.call(direct, "matched_result") || Object.prototype.hasOwnProperty.call(direct, "matchedResult") || Object.prototype.hasOwnProperty.call(direct, "result")) {
18627
+ return materializeCsvCellValue(direct);
18628
+ }
18629
+ const directCells = [];
18630
+ for (const [field, value] of Object.entries(direct)) {
18631
+ if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
18632
+ continue;
18633
+ }
18634
+ if (isNonEmptyCsvCell(value)) {
18635
+ directCells.push({ field, value });
18636
+ }
18637
+ }
18638
+ for (const preferredField of [alias, ...ENRICH_FLATTENED_SUCCESS_FIELD_PRIORITY]) {
18639
+ const preferred = directCells.find(({ field }) => field === preferredField);
18640
+ if (preferred) {
18641
+ return materializeCsvCellValue(preferred.value);
18642
+ }
18643
+ }
18644
+ if (directCells.length === 1) {
18645
+ return materializeCsvCellValue(directCells[0].value);
18646
+ }
18647
+ if (directCells.length > 1) {
18648
+ return JSON.stringify(
18649
+ Object.fromEntries(
18650
+ directCells.map(({ field, value }) => [field, value])
18651
+ )
18652
+ );
18653
+ }
18654
+ }
18655
+ const cells = aliasFlattenedCells(row, alias).filter(({ field, value }) => {
18656
+ if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
18657
+ return false;
18658
+ }
18659
+ return isNonEmptyCsvCell(value);
18660
+ });
18661
+ if (cells.length === 0) {
18662
+ return void 0;
18663
+ }
18664
+ for (const preferredField of ENRICH_FLATTENED_SUCCESS_FIELD_PRIORITY) {
18665
+ const preferred = cells.find(({ field }) => field === preferredField);
18666
+ if (preferred) {
18667
+ return materializeCsvCellValue(preferred.value);
18668
+ }
18669
+ }
18670
+ if (cells.length === 1) {
18671
+ return materializeCsvCellValue(cells[0].value);
18672
+ }
18673
+ return JSON.stringify(
18674
+ Object.fromEntries(cells.map(({ field, value }) => [field, value]))
18675
+ );
18676
+ }
18677
+ function normalizeEnrichRowsForCsvExport(rows, config, options) {
18678
+ const aliases = config ? collectConfigScalarAliasOrder(config) : [];
17828
18679
  return rows.map((row) => {
17829
18680
  const metadata = legacyMetadataFromRow(row);
17830
- if (!metadata) {
17831
- return row;
18681
+ const normalized = metadata ? { ...row, _metadata: metadata } : { ...row };
18682
+ if (metadata) {
18683
+ delete normalized.metadata;
18684
+ delete normalized["metadata.columns"];
18685
+ delete normalized.metadata__columns;
17832
18686
  }
17833
- const normalized = { ...row, _metadata: metadata };
17834
- delete normalized.metadata;
17835
- delete normalized["metadata.columns"];
17836
- delete normalized.metadata__columns;
17837
18687
  for (const key of Object.keys(normalized)) {
17838
18688
  if (key.startsWith("metadata.columns.") || key.startsWith("metadata__columns.")) {
17839
18689
  delete normalized[key];
17840
18690
  }
17841
18691
  }
18692
+ const failureAliases = /* @__PURE__ */ new Set();
18693
+ for (const key of Object.keys(normalized)) {
18694
+ const dotted = key.match(
18695
+ /^(.+)\.(?:error|last_error|message|operation|provider|result|status)$/
18696
+ );
18697
+ const underscored = key.match(
18698
+ /^(.+)__(?:error|last_error|message|operation|provider|result|status)$/
18699
+ );
18700
+ const alias = dotted?.[1] ?? underscored?.[1] ?? null;
18701
+ if (alias) {
18702
+ failureAliases.add(alias);
18703
+ }
18704
+ }
18705
+ for (const alias of failureAliases) {
18706
+ if (isNonEmptyCsvCell(normalized[alias])) {
18707
+ continue;
18708
+ }
18709
+ const failure = aliasFailureCellCandidates(normalized, alias).map(cellFailureError).find(
18710
+ (candidate) => Boolean(candidate)
18711
+ );
18712
+ if (failure) {
18713
+ normalized[alias] = failure.message;
18714
+ }
18715
+ }
18716
+ for (const alias of aliases) {
18717
+ const value = materializeAliasSuccessCell(normalized, alias);
18718
+ if (value !== void 0) {
18719
+ normalized[alias] = value;
18720
+ continue;
18721
+ }
18722
+ if (isNonEmptyCsvCell(normalized[alias])) {
18723
+ continue;
18724
+ }
18725
+ const failure = aliasFailureCellCandidates(normalized, alias).map(cellFailureError).find(
18726
+ (candidate) => Boolean(candidate)
18727
+ );
18728
+ if (failure) {
18729
+ normalized[alias] = failure.message;
18730
+ continue;
18731
+ }
18732
+ const statusFailureMessage = options?.statusFailureMessages?.get(
18733
+ normalizeAlias2(alias)
18734
+ );
18735
+ if (statusFailureMessage) {
18736
+ normalized[alias] = statusFailureMessage;
18737
+ }
18738
+ }
17842
18739
  return normalized;
17843
18740
  });
17844
18741
  }
@@ -18001,6 +18898,9 @@ function registerEnrichCommand(program) {
18001
18898
  ).option(
18002
18899
  "--profile <id>",
18003
18900
  "Internal/testing: override the execution profile for the generated play run."
18901
+ ).option(
18902
+ "--fail-fast",
18903
+ "Fail the generated play when any selected row errors, while preserving recovered runtime-sheet rows for export."
18004
18904
  ).action(async (options, _command) => {
18005
18905
  if (options.inPlace && options.dryRun) {
18006
18906
  throw new Error("--in-place is not supported with --dry-run.");
@@ -18024,14 +18924,16 @@ function registerEnrichCommand(program) {
18024
18924
  const forceAliases2 = resolveForceAliases(config, options);
18025
18925
  const playSource2 = compileEnrichConfigToPlaySource(config, {
18026
18926
  forceAliases: forceAliases2,
18027
- playName: options.name
18927
+ playName: options.name,
18928
+ inlineRunJavascript: true,
18929
+ failFast: options.failFast
18028
18930
  });
18029
18931
  const summary = summarizePlan(config, playSource2);
18030
18932
  if (options.json) {
18031
18933
  printJson({
18032
18934
  dryRun: true,
18033
- input: resolve8(inputCsv),
18034
- output: options.output ? resolve8(options.output) : null,
18935
+ input: resolve9(inputCsv),
18936
+ output: options.output ? resolve9(options.output) : null,
18035
18937
  plan: summary
18036
18938
  });
18037
18939
  return;
@@ -18053,15 +18955,17 @@ function registerEnrichCommand(program) {
18053
18955
  }
18054
18956
  const playSource = compileEnrichConfigToPlaySource(config, {
18055
18957
  forceAliases,
18056
- playName: options.name
18958
+ playName: options.name,
18959
+ inlineRunJavascript: true,
18960
+ failFast: options.failFast
18057
18961
  });
18058
- const tempDir = await mkdtemp(join6(tmpdir2(), "deepline-enrich-play-"));
18059
- const tempPlay = join6(tempDir, "deepline-enrich.play.ts");
18962
+ const tempDir = await mkdtemp(join7(tmpdir2(), "deepline-enrich-play-"));
18963
+ const tempPlay = join7(tempDir, "deepline-enrich.play.ts");
18060
18964
  try {
18061
18965
  await writeFile3(tempPlay, playSource, "utf8");
18062
18966
  const runOne = async (input2) => {
18063
18967
  const runtimeInput = {
18064
- file: resolve8(input2.sourceCsvPath),
18968
+ file: resolve9(input2.sourceCsvPath),
18065
18969
  ...input2.rows.rowStart !== null ? { rowStart: input2.rows.rowStart } : {},
18066
18970
  ...input2.rows.rowEnd !== null ? { rowEnd: input2.rows.rowEnd } : {}
18067
18971
  };
@@ -18087,7 +18991,7 @@ function registerEnrichCommand(program) {
18087
18991
  if (timeoutSeconds !== null && Number.isFinite(timeoutSeconds) && timeoutSeconds > 0) {
18088
18992
  runArgs.push("--tail-timeout-ms", String(timeoutSeconds * 1e3));
18089
18993
  }
18090
- const captured2 = await runGeneratedEnrichPlay(runArgs, {
18994
+ const captured2 = await runGeneratedEnrichPlay(client2, runArgs, {
18091
18995
  passthroughStdout: input2.passthroughStdout
18092
18996
  });
18093
18997
  const status2 = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
@@ -18114,7 +19018,7 @@ function registerEnrichCommand(program) {
18114
19018
  );
18115
19019
  if (!options.json) {
18116
19020
  process.stderr.write(
18117
- `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 ${resolve8(outputPath)}.
19021
+ `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 ${resolve9(outputPath)}.
18118
19022
  `
18119
19023
  );
18120
19024
  }
@@ -18190,7 +19094,8 @@ function registerEnrichCommand(program) {
18190
19094
  rowEnd: selectedRange.end
18191
19095
  },
18192
19096
  client: client2,
18193
- outputPath
19097
+ outputPath,
19098
+ status: lastStatus
18194
19099
  });
18195
19100
  if (options.json) {
18196
19101
  const run = rewriteEnrichJsonStatus({
@@ -18254,7 +19159,8 @@ function registerEnrichCommand(program) {
18254
19159
  rowRange: rows,
18255
19160
  client: client2,
18256
19161
  exportResult,
18257
- outputPath
19162
+ outputPath,
19163
+ status
18258
19164
  });
18259
19165
  if (options.json) {
18260
19166
  printJson({
@@ -18279,7 +19185,8 @@ function registerEnrichCommand(program) {
18279
19185
  rowRange: rows,
18280
19186
  client: client2,
18281
19187
  exportResult,
18282
- outputPath
19188
+ outputPath,
19189
+ status
18283
19190
  });
18284
19191
  const run = rewriteEnrichJsonStatus({
18285
19192
  status,
@@ -18323,7 +19230,8 @@ function registerEnrichCommand(program) {
18323
19230
  rows: rowsForFailureReport,
18324
19231
  rowRange: rows,
18325
19232
  client: client2,
18326
- outputPath: exportResult?.path ?? outputPath ?? null
19233
+ outputPath: exportResult?.path ?? outputPath ?? null,
19234
+ status
18327
19235
  });
18328
19236
  if (failureReport) {
18329
19237
  process.exitCode = EXIT_SERVER2;
@@ -18380,17 +19288,17 @@ Examples:
18380
19288
 
18381
19289
  // src/cli/commands/sessions.ts
18382
19290
  import {
18383
- existsSync as existsSync7,
18384
- mkdirSync as mkdirSync5,
19291
+ existsSync as existsSync8,
19292
+ mkdirSync as mkdirSync6,
18385
19293
  readdirSync as readdirSync3,
18386
- readFileSync as readFileSync7,
19294
+ readFileSync as readFileSync8,
18387
19295
  statSync as statSync4,
18388
- writeFileSync as writeFileSync9
19296
+ writeFileSync as writeFileSync10
18389
19297
  } from "fs";
18390
- import { homedir as homedir7, platform } from "os";
18391
- import { basename as basename2, dirname as dirname7, join as join7, resolve as resolve9 } from "path";
19298
+ import { homedir as homedir8, platform } from "os";
19299
+ import { basename as basename2, dirname as dirname7, join as join8, resolve as resolve10 } from "path";
18392
19300
  import { gzipSync } from "zlib";
18393
- import { randomUUID } from "crypto";
19301
+ import { randomUUID as randomUUID2 } from "crypto";
18394
19302
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
18395
19303
  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;
18396
19304
  var MAX_SESSION_UPLOAD_BYTES = 35e5;
@@ -18402,7 +19310,7 @@ var MAX_EVENT_OBJECT_KEYS = 80;
18402
19310
  var TRUNCATION_MARKER = "...[truncated]";
18403
19311
  var NOISE_EVENT_TYPES = /* @__PURE__ */ new Set(["progress", "file-history-snapshot"]);
18404
19312
  function homeDir() {
18405
- return process.env.HOME?.trim() || homedir7();
19313
+ return process.env.HOME?.trim() || homedir8();
18406
19314
  }
18407
19315
  function detectShellContext() {
18408
19316
  const shellPath = process.env.SHELL?.trim() || process.env.ComSpec?.trim() || process.env.COMSPEC?.trim() || "";
@@ -18414,21 +19322,21 @@ function detectShellContext() {
18414
19322
  };
18415
19323
  }
18416
19324
  function claudeProjectsRoot() {
18417
- return join7(homeDir(), ".claude", "projects");
19325
+ return join8(homeDir(), ".claude", "projects");
18418
19326
  }
18419
19327
  function codexSessionsRoot() {
18420
- return join7(homeDir(), ".codex", "sessions");
19328
+ return join8(homeDir(), ".codex", "sessions");
18421
19329
  }
18422
19330
  function listClaudeSessionFiles() {
18423
19331
  const root = claudeProjectsRoot();
18424
- if (!existsSync7(root)) return [];
19332
+ if (!existsSync8(root)) return [];
18425
19333
  const projectDirs = readDirectoryNames(root);
18426
19334
  const files = [];
18427
19335
  for (const projectDir of projectDirs) {
18428
- const fullProjectDir = join7(root, projectDir);
19336
+ const fullProjectDir = join8(root, projectDir);
18429
19337
  for (const fileName of readDirectoryNames(fullProjectDir)) {
18430
19338
  if (fileName.endsWith(".jsonl")) {
18431
- const filePath = join7(fullProjectDir, fileName);
19339
+ const filePath = join8(fullProjectDir, fileName);
18432
19340
  const sessionId = sessionIdFromClaudeFilePath(filePath);
18433
19341
  const stat2 = statIfReadable(filePath);
18434
19342
  if (sessionId && stat2) {
@@ -18446,7 +19354,7 @@ function listClaudeSessionFiles() {
18446
19354
  }
18447
19355
  function listCodexSessionFiles() {
18448
19356
  const root = codexSessionsRoot();
18449
- if (!existsSync7(root)) return [];
19357
+ if (!existsSync8(root)) return [];
18450
19358
  const files = [];
18451
19359
  for (const filePath of listJsonlFilesRecursive(root, 5)) {
18452
19360
  const stat2 = statIfReadable(filePath);
@@ -18485,7 +19393,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
18485
19393
  return;
18486
19394
  }
18487
19395
  for (const entry of entries) {
18488
- const fullPath = join7(dir, entry.name);
19396
+ const fullPath = join8(dir, entry.name);
18489
19397
  if (entry.isDirectory()) {
18490
19398
  visit(fullPath, depth + 1);
18491
19399
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
@@ -18521,7 +19429,7 @@ function sessionIdFromCodexFilePath(filePath) {
18521
19429
  }
18522
19430
  function readCodexSessionId(filePath) {
18523
19431
  try {
18524
- for (const line of normalizedJsonLines(readFileSync7(filePath)).slice(
19432
+ for (const line of normalizedJsonLines(readFileSync8(filePath)).slice(
18525
19433
  0,
18526
19434
  20
18527
19435
  )) {
@@ -18752,7 +19660,7 @@ async function uploadPayload(path, payload) {
18752
19660
  return await http.post(path, payload);
18753
19661
  }
18754
19662
  async function uploadChunkedSessions(sessions, options) {
18755
- const uploadId = randomUUID();
19663
+ const uploadId = randomUUID2();
18756
19664
  for (const session of sessions) {
18757
19665
  const bytes = Buffer.from(session.encodedContent, "base64");
18758
19666
  const chunks = [];
@@ -18798,12 +19706,12 @@ async function uploadChunkedSessions(sessions, options) {
18798
19706
  }
18799
19707
  async function handleSessionsSend(options) {
18800
19708
  if (options.file) {
18801
- const filePath = resolve9(options.file);
18802
- if (!existsSync7(filePath)) {
19709
+ const filePath = resolve10(options.file);
19710
+ if (!existsSync8(filePath)) {
18803
19711
  throw new Error(`File not found: ${options.file}`);
18804
19712
  }
18805
19713
  const response2 = await uploadPayload("/api/v2/cli/send-session", {
18806
- file: readFileSync7(filePath).toString("base64"),
19714
+ file: readFileSync8(filePath).toString("base64"),
18807
19715
  filename: basename2(filePath)
18808
19716
  });
18809
19717
  printCommandEnvelope(
@@ -18833,7 +19741,7 @@ async function handleSessionsSend(options) {
18833
19741
  agent: options.agent
18834
19742
  });
18835
19743
  const built = targets.map((target) => {
18836
- const upload = buildSessionUploadContent(readFileSync7(target.filePath));
19744
+ const upload = buildSessionUploadContent(readFileSync8(target.filePath));
18837
19745
  return { ...target, ...upload };
18838
19746
  });
18839
19747
  if (built.some((session) => session.needsChunking)) {
@@ -18897,11 +19805,11 @@ function fallbackViewerAssets() {
18897
19805
  };
18898
19806
  }
18899
19807
  function loadViewerAssets() {
18900
- const cliEntry = process.argv[1]?.trim() ? resolve9(process.argv[1]) : null;
19808
+ const cliEntry = process.argv[1]?.trim() ? resolve10(process.argv[1]) : null;
18901
19809
  const candidateRoots2 = [
18902
19810
  ...cliEntry ? [
18903
- join7(dirname7(dirname7(cliEntry)), "viewer"),
18904
- join7(
19811
+ join8(dirname7(dirname7(cliEntry)), "viewer"),
19812
+ join8(
18905
19813
  dirname7(dirname7(dirname7(cliEntry))),
18906
19814
  "src",
18907
19815
  "lib",
@@ -18909,16 +19817,16 @@ function loadViewerAssets() {
18909
19817
  "viewer"
18910
19818
  )
18911
19819
  ] : [],
18912
- join7(process.cwd(), "src", "lib", "cli", "viewer")
19820
+ join8(process.cwd(), "src", "lib", "cli", "viewer")
18913
19821
  ];
18914
19822
  for (const root of candidateRoots2) {
18915
19823
  try {
18916
- const cssPath = join7(root, "viewer.css");
18917
- const jsPath = join7(root, "viewer.js");
18918
- if (!existsSync7(cssPath) || !existsSync7(jsPath)) continue;
19824
+ const cssPath = join8(root, "viewer.css");
19825
+ const jsPath = join8(root, "viewer.js");
19826
+ if (!existsSync8(cssPath) || !existsSync8(jsPath)) continue;
18919
19827
  return {
18920
- css: readFileSync7(cssPath, "utf8"),
18921
- js: readFileSync7(jsPath, "utf8")
19828
+ css: readFileSync8(cssPath, "utf8"),
19829
+ js: readFileSync8(jsPath, "utf8")
18922
19830
  };
18923
19831
  } catch {
18924
19832
  continue;
@@ -18942,21 +19850,21 @@ async function handleSessionsRender(options) {
18942
19850
  currentSession: options.currentSession,
18943
19851
  agent: options.agent
18944
19852
  });
18945
- let outputPath = options.output ? resolve9(options.output) : "";
19853
+ let outputPath = options.output ? resolve10(options.output) : "";
18946
19854
  if (!outputPath) {
18947
- const outputDir = join7(process.cwd(), "deepline", "data");
18948
- mkdirSync5(outputDir, { recursive: true });
18949
- outputPath = join7(
19855
+ const outputDir = join8(process.cwd(), "deepline", "data");
19856
+ mkdirSync6(outputDir, { recursive: true });
19857
+ outputPath = join8(
18950
19858
  outputDir,
18951
19859
  targets.length > 1 ? "session-viewer.html" : `session-${targets[0]?.sessionId}.html`
18952
19860
  );
18953
19861
  } else {
18954
- mkdirSync5(dirname7(outputPath), { recursive: true });
19862
+ mkdirSync6(dirname7(outputPath), { recursive: true });
18955
19863
  }
18956
19864
  const sessions = targets.map((target) => ({
18957
19865
  label: target.label,
18958
19866
  events: parsePreparedEvents(
18959
- prepareSessionBuffer(readFileSync7(target.filePath))
19867
+ prepareSessionBuffer(readFileSync8(target.filePath))
18960
19868
  )
18961
19869
  }));
18962
19870
  const { css, js } = loadViewerAssets();
@@ -18979,7 +19887,7 @@ ${refreshMeta}
18979
19887
  <script>${js}</script>
18980
19888
  </body>
18981
19889
  </html>`;
18982
- writeFileSync9(outputPath, html, "utf8");
19890
+ writeFileSync10(outputPath, html, "utf8");
18983
19891
  printCommandEnvelope(
18984
19892
  {
18985
19893
  ok: true,
@@ -19963,7 +20871,7 @@ Examples:
19963
20871
  }
19964
20872
 
19965
20873
  // src/cli/commands/quickstart.ts
19966
- import { spawn, spawnSync } from "child_process";
20874
+ import { spawn as spawn2, spawnSync } from "child_process";
19967
20875
  import { randomBytes } from "crypto";
19968
20876
  import { createServer } from "http";
19969
20877
  var EXIT_OK2 = 0;
@@ -19986,17 +20894,17 @@ function hasClaudeBinary() {
19986
20894
  }
19987
20895
  }
19988
20896
  function launchClaude(prompt) {
19989
- return new Promise((resolve13) => {
19990
- const child = spawn("claude", [prompt], {
20897
+ return new Promise((resolve14) => {
20898
+ const child = spawn2("claude", [prompt], {
19991
20899
  stdio: "inherit",
19992
20900
  shell: process.platform === "win32"
19993
20901
  });
19994
- child.on("error", () => resolve13(EXIT_SERVER3));
19995
- child.on("close", (status) => resolve13(status ?? EXIT_OK2));
20902
+ child.on("error", () => resolve14(EXIT_SERVER3));
20903
+ child.on("close", (status) => resolve14(status ?? EXIT_OK2));
19996
20904
  });
19997
20905
  }
19998
20906
  function readBody(req) {
19999
- return new Promise((resolve13, reject) => {
20907
+ return new Promise((resolve14, reject) => {
20000
20908
  let raw = "";
20001
20909
  req.setEncoding("utf8");
20002
20910
  req.on("data", (chunk) => {
@@ -20006,7 +20914,7 @@ function readBody(req) {
20006
20914
  req.destroy();
20007
20915
  }
20008
20916
  });
20009
- req.on("end", () => resolve13(raw));
20917
+ req.on("end", () => resolve14(raw));
20010
20918
  req.on("error", reject);
20011
20919
  });
20012
20920
  }
@@ -20061,7 +20969,7 @@ function startCallbackServer(input2) {
20061
20969
  writeJson(res, 400, { error: "Invalid request body." });
20062
20970
  });
20063
20971
  });
20064
- return new Promise((resolve13, reject) => {
20972
+ return new Promise((resolve14, reject) => {
20065
20973
  server.once("error", reject);
20066
20974
  server.listen(0, "127.0.0.1", () => {
20067
20975
  const address = server.address();
@@ -20069,7 +20977,7 @@ function startCallbackServer(input2) {
20069
20977
  reject(new Error("Failed to bind quickstart callback server."));
20070
20978
  return;
20071
20979
  }
20072
- resolve13({ server, port: address.port });
20980
+ resolve14({ server, port: address.port });
20073
20981
  });
20074
20982
  });
20075
20983
  }
@@ -20095,8 +21003,8 @@ async function handleQuickstart(options) {
20095
21003
  }
20096
21004
  const state = randomBytes(32).toString("hex");
20097
21005
  let resolveSelection;
20098
- const selectionPromise = new Promise((resolve13) => {
20099
- resolveSelection = resolve13;
21006
+ const selectionPromise = new Promise((resolve14) => {
21007
+ resolveSelection = resolve14;
20100
21008
  });
20101
21009
  let callback;
20102
21010
  try {
@@ -20235,7 +21143,7 @@ async function readHiddenLine(prompt, streams = {}) {
20235
21143
  }
20236
21144
  let value = "";
20237
21145
  inputStream.resume();
20238
- return await new Promise((resolve13, reject) => {
21146
+ return await new Promise((resolve14, reject) => {
20239
21147
  let settled = false;
20240
21148
  const cleanup = () => {
20241
21149
  inputStream.off("data", onData);
@@ -20253,7 +21161,7 @@ async function readHiddenLine(prompt, streams = {}) {
20253
21161
  settled = true;
20254
21162
  outputStream.write("\n");
20255
21163
  cleanup();
20256
- resolve13(line);
21164
+ resolve14(line);
20257
21165
  };
20258
21166
  const fail = (error) => {
20259
21167
  if (settled) return;
@@ -20424,9 +21332,9 @@ Examples:
20424
21332
  }
20425
21333
 
20426
21334
  // src/cli/commands/switch.ts
20427
- import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync10 } from "fs";
20428
- import { homedir as homedir8 } from "os";
20429
- import { dirname as dirname8, join as join8 } from "path";
21335
+ import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync11 } from "fs";
21336
+ import { homedir as homedir9 } from "os";
21337
+ import { dirname as dirname8, join as join9 } from "path";
20430
21338
  function hostSlugFromBaseUrl(baseUrl) {
20431
21339
  try {
20432
21340
  const url = new URL(baseUrl);
@@ -20446,8 +21354,8 @@ function resolveConfigScope() {
20446
21354
  return hostSlugFromBaseUrl(autoDetectBaseUrl());
20447
21355
  }
20448
21356
  function activeFamilyPath() {
20449
- const home = process.env.HOME || process.env.USERPROFILE || homedir8();
20450
- return join8(
21357
+ const home = process.env.HOME || process.env.USERPROFILE || homedir9();
21358
+ return join9(
20451
21359
  home,
20452
21360
  ".local",
20453
21361
  "deepline",
@@ -20459,15 +21367,15 @@ function activeFamilyPath() {
20459
21367
  function readActiveFamily() {
20460
21368
  const path = activeFamilyPath();
20461
21369
  try {
20462
- return readFileSync8(path, "utf-8").trim() || "sdk";
21370
+ return readFileSync9(path, "utf-8").trim() || "sdk";
20463
21371
  } catch {
20464
21372
  return "sdk";
20465
21373
  }
20466
21374
  }
20467
21375
  function writeActiveFamily(family) {
20468
21376
  const path = activeFamilyPath();
20469
- mkdirSync6(dirname8(path), { recursive: true });
20470
- writeFileSync10(path, `${family}
21377
+ mkdirSync7(dirname8(path), { recursive: true });
21378
+ writeFileSync11(path, `${family}
20471
21379
  `, "utf-8");
20472
21380
  return path;
20473
21381
  }
@@ -20484,7 +21392,7 @@ function handleSwitch(action, options) {
20484
21392
  ok: true,
20485
21393
  active_family: activeFamily,
20486
21394
  active_family_path: path,
20487
- active_family_file_exists: existsSync8(path),
21395
+ active_family_file_exists: existsSync9(path),
20488
21396
  render: {
20489
21397
  sections: [
20490
21398
  {
@@ -20586,24 +21494,24 @@ Examples:
20586
21494
  import { Option } from "commander";
20587
21495
  import {
20588
21496
  chmodSync,
20589
- existsSync as existsSync9,
21497
+ existsSync as existsSync10,
20590
21498
  mkdtempSync,
20591
- readFileSync as readFileSync9,
20592
- writeFileSync as writeFileSync12
21499
+ readFileSync as readFileSync10,
21500
+ writeFileSync as writeFileSync13
20593
21501
  } from "fs";
20594
21502
  import { tmpdir as tmpdir3 } from "os";
20595
- import { join as join10, resolve as resolve10 } from "path";
21503
+ import { join as join11, resolve as resolve11 } from "path";
20596
21504
 
20597
21505
  // src/tool-output.ts
20598
21506
  import {
20599
21507
  closeSync as closeSync2,
20600
- mkdirSync as mkdirSync7,
21508
+ mkdirSync as mkdirSync8,
20601
21509
  openSync as openSync2,
20602
- writeFileSync as writeFileSync11,
21510
+ writeFileSync as writeFileSync12,
20603
21511
  writeSync
20604
21512
  } from "fs";
20605
- import { homedir as homedir9 } from "os";
20606
- import { dirname as dirname9, join as join9 } from "path";
21513
+ import { homedir as homedir10 } from "os";
21514
+ import { dirname as dirname9, join as join10 } from "path";
20607
21515
  function isPlainObject(value) {
20608
21516
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
20609
21517
  }
@@ -20730,19 +21638,19 @@ function projectRowOutput(conversion) {
20730
21638
  };
20731
21639
  }
20732
21640
  function ensureOutputDir() {
20733
- const outputDir = join9(homedir9(), ".local", "share", "deepline", "data");
20734
- mkdirSync7(outputDir, { recursive: true });
21641
+ const outputDir = join10(homedir10(), ".local", "share", "deepline", "data");
21642
+ mkdirSync8(outputDir, { recursive: true });
20735
21643
  return outputDir;
20736
21644
  }
20737
21645
  function writeJsonOutputFile(payload, stem) {
20738
21646
  const outputDir = ensureOutputDir();
20739
- const outputPath = join9(outputDir, `${stem}_${Date.now()}.json`);
20740
- writeFileSync11(outputPath, JSON.stringify(payload, null, 2), "utf-8");
21647
+ const outputPath = join10(outputDir, `${stem}_${Date.now()}.json`);
21648
+ writeFileSync12(outputPath, JSON.stringify(payload, null, 2), "utf-8");
20741
21649
  return outputPath;
20742
21650
  }
20743
21651
  function writeCsvOutputFile(rows, stem, options) {
20744
- const outputPath = options?.outPath ? options.outPath : join9(ensureOutputDir(), `${stem}_${Date.now()}.csv`);
20745
- mkdirSync7(dirname9(outputPath), { recursive: true });
21652
+ const outputPath = options?.outPath ? options.outPath : join10(ensureOutputDir(), `${stem}_${Date.now()}.csv`);
21653
+ mkdirSync8(dirname9(outputPath), { recursive: true });
20746
21654
  const columns = columnsForRows(rows);
20747
21655
  const escapeCell = (value) => {
20748
21656
  const normalized = value == null ? "" : typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
@@ -21908,11 +22816,11 @@ function normalizeOutputFormat(raw) {
21908
22816
  }
21909
22817
  function resolveAtFilePath(rawPath) {
21910
22818
  const trimmed = rawPath.trim();
21911
- const resolved = resolve10(trimmed);
21912
- if (existsSync9(resolved)) return resolved;
22819
+ const resolved = resolve11(trimmed);
22820
+ if (existsSync10(resolved)) return resolved;
21913
22821
  if (process.platform !== "win32" && trimmed.includes("\\")) {
21914
- const normalized = resolve10(trimmed.replace(/\\/g, "/"));
21915
- if (existsSync9(normalized)) return normalized;
22822
+ const normalized = resolve11(trimmed.replace(/\\/g, "/"));
22823
+ if (existsSync10(normalized)) return normalized;
21916
22824
  }
21917
22825
  return resolved;
21918
22826
  }
@@ -21923,7 +22831,7 @@ function readJsonArgument(raw, flagName) {
21923
22831
  throw new Error(`Invalid ${flagName} value: empty @file path.`);
21924
22832
  }
21925
22833
  try {
21926
- return readFileSync9(resolveAtFilePath(filePath), "utf8").replace(
22834
+ return readFileSync10(resolveAtFilePath(filePath), "utf8").replace(
21927
22835
  /^\uFEFF/,
21928
22836
  ""
21929
22837
  );
@@ -22000,7 +22908,7 @@ function parseExecuteOptions(args) {
22000
22908
  continue;
22001
22909
  }
22002
22910
  if ((arg === "--out" || arg === "-o") && args[index + 1]) {
22003
- outPath = resolve10(args[++index]);
22911
+ outPath = resolve11(args[++index]);
22004
22912
  continue;
22005
22913
  }
22006
22914
  throw new Error(`Unknown option: ${arg}`);
@@ -22030,9 +22938,9 @@ function starterScriptJson(script) {
22030
22938
  function seedToolListScript(input2) {
22031
22939
  const stem = safeFileStem(input2.toolId);
22032
22940
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
22033
- const scriptDir = mkdtempSync(join10(tmpdir3(), "deepline-workflow-seed-"));
22941
+ const scriptDir = mkdtempSync(join11(tmpdir3(), "deepline-workflow-seed-"));
22034
22942
  chmodSync(scriptDir, 448);
22035
- const scriptPath = join10(scriptDir, fileName);
22943
+ const scriptPath = join11(scriptDir, fileName);
22036
22944
  const projectDir = `deepline/projects/${stem}-workflow`;
22037
22945
  const playName = `${stem}-workflow`;
22038
22946
  const sampleRows = input2.rows.length > 0 ? `${JSON.stringify(input2.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
@@ -22075,7 +22983,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
22075
22983
  description: ${JSON.stringify(`Seed ${input2.toolId} rows into a Deepline workflow-ready dataset.`)},
22076
22984
  });
22077
22985
  `;
22078
- writeFileSync12(scriptPath, script, { encoding: "utf-8", mode: 384 });
22986
+ writeFileSync13(scriptPath, script, { encoding: "utf-8", mode: 384 });
22079
22987
  return {
22080
22988
  path: scriptPath,
22081
22989
  sourceCode: script,
@@ -22406,7 +23314,7 @@ async function executeTool(args) {
22406
23314
 
22407
23315
  // src/cli/commands/workflow.ts
22408
23316
  import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile4 } from "fs/promises";
22409
- import { dirname as dirname10, join as join11, resolve as resolve11 } from "path";
23317
+ import { dirname as dirname10, join as join12, resolve as resolve12 } from "path";
22410
23318
 
22411
23319
  // src/cli/workflow-to-play.ts
22412
23320
  import { createHash as createHash3 } from "crypto";
@@ -22650,7 +23558,7 @@ function readStatus(payload) {
22650
23558
  }
22651
23559
  async function readJsonOption(payload, file) {
22652
23560
  if (file) {
22653
- const raw = await readFile2(resolve11(file), "utf8");
23561
+ const raw = await readFile2(resolve12(file), "utf8");
22654
23562
  return JSON.parse(raw);
22655
23563
  }
22656
23564
  if (payload) {
@@ -22684,7 +23592,7 @@ async function transformOne(api, workflowId, outDir, publish) {
22684
23592
  revision.config,
22685
23593
  { workflowName: workflow.name, version: revision.version }
22686
23594
  );
22687
- const file = join11(resolve11(outDir), `${compiled.playName}.play.ts`);
23595
+ const file = join12(resolve12(outDir), `${compiled.playName}.play.ts`);
22688
23596
  await mkdir4(dirname10(file), { recursive: true });
22689
23597
  await writeFile4(file, compiled.sourceCode, "utf8");
22690
23598
  let published = false;
@@ -22931,24 +23839,24 @@ Notes:
22931
23839
  }
22932
23840
 
22933
23841
  // src/cli/commands/update.ts
22934
- import { spawn as spawn3 } from "child_process";
23842
+ import { spawn as spawn4 } from "child_process";
22935
23843
  import {
22936
- existsSync as existsSync11,
22937
- mkdirSync as mkdirSync9,
23844
+ existsSync as existsSync12,
23845
+ mkdirSync as mkdirSync10,
22938
23846
  realpathSync as realpathSync3,
22939
- readFileSync as readFileSync11,
23847
+ readFileSync as readFileSync12,
22940
23848
  renameSync,
22941
- rmSync as rmSync3,
23849
+ rmSync as rmSync4,
22942
23850
  unlinkSync,
22943
- writeFileSync as writeFileSync14
23851
+ writeFileSync as writeFileSync15
22944
23852
  } from "fs";
22945
- import { homedir as homedir10 } from "os";
22946
- import { dirname as dirname12, isAbsolute as isAbsolute2, join as join13, relative as relative2, resolve as resolve12 } from "path";
23853
+ import { homedir as homedir11 } from "os";
23854
+ import { dirname as dirname12, isAbsolute as isAbsolute2, join as join14, relative as relative2, resolve as resolve13 } from "path";
22947
23855
 
22948
23856
  // src/cli/skills-sync.ts
22949
- import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
22950
- import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync13 } from "fs";
22951
- import { dirname as dirname11, join as join12 } from "path";
23857
+ import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
23858
+ import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync14 } from "fs";
23859
+ import { dirname as dirname11, join as join13 } from "path";
22952
23860
 
22953
23861
  // ../shared_libs/cli/install-commands.json
22954
23862
  var install_commands_default = {
@@ -23067,38 +23975,38 @@ function activePluginSkillsDir() {
23067
23975
  return "";
23068
23976
  }
23069
23977
  const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
23070
- return dir && existsSync10(dir) ? dir : "";
23978
+ return dir && existsSync11(dir) ? dir : "";
23071
23979
  }
23072
23980
  function readPluginSkillsVersion() {
23073
23981
  const dir = activePluginSkillsDir();
23074
23982
  if (!dir) return "";
23075
23983
  try {
23076
- return readFileSync10(join12(dir, ".version"), "utf-8").trim();
23984
+ return readFileSync11(join13(dir, ".version"), "utf-8").trim();
23077
23985
  } catch {
23078
23986
  return "";
23079
23987
  }
23080
23988
  }
23081
23989
  function sdkSkillsVersionPath(baseUrl) {
23082
- return join12(sdkCliStateDirPath(baseUrl), "skills-version");
23990
+ return join13(sdkCliStateDirPath(baseUrl), "skills-version");
23083
23991
  }
23084
23992
  function legacySdkSkillsVersionPath(baseUrl) {
23085
- return join12(dirname11(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
23993
+ return join13(dirname11(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
23086
23994
  }
23087
23995
  function readSdkSkillsLocalVersion(baseUrl) {
23088
23996
  const pluginVersion = readPluginSkillsVersion();
23089
23997
  if (pluginVersion) return pluginVersion;
23090
- const path = existsSync10(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
23091
- if (!existsSync10(path)) return "";
23998
+ const path = existsSync11(sdkSkillsVersionPath(baseUrl)) ? sdkSkillsVersionPath(baseUrl) : legacySdkSkillsVersionPath(baseUrl);
23999
+ if (!existsSync11(path)) return "";
23092
24000
  try {
23093
- return readFileSync10(path, "utf-8").trim();
24001
+ return readFileSync11(path, "utf-8").trim();
23094
24002
  } catch {
23095
24003
  return "";
23096
24004
  }
23097
24005
  }
23098
24006
  function writeLocalSkillsVersion(baseUrl, version) {
23099
24007
  const path = sdkSkillsVersionPath(baseUrl);
23100
- mkdirSync8(dirname11(path), { recursive: true });
23101
- writeFileSync13(path, `${version}
24008
+ mkdirSync9(dirname11(path), { recursive: true });
24009
+ writeFileSync14(path, `${version}
23102
24010
  `, "utf-8");
23103
24011
  }
23104
24012
  function sortedUniqueSkillNames(names) {
@@ -23196,8 +24104,8 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
23196
24104
  return [npxInstall];
23197
24105
  }
23198
24106
  function runOneSkillsInstall(install) {
23199
- return new Promise((resolve13) => {
23200
- const child = spawn2(install.command, install.args, {
24107
+ return new Promise((resolve14) => {
24108
+ const child = spawn3(install.command, install.args, {
23201
24109
  stdio: ["ignore", "ignore", "pipe"],
23202
24110
  env: process.env
23203
24111
  });
@@ -23206,7 +24114,7 @@ function runOneSkillsInstall(install) {
23206
24114
  stderr += chunk.toString("utf-8");
23207
24115
  });
23208
24116
  child.on("error", (error) => {
23209
- resolve13({
24117
+ resolve14({
23210
24118
  ok: false,
23211
24119
  detail: `failed to start ${install.command}: ${error.message}`,
23212
24120
  manualCommand: install.manualCommand
@@ -23214,11 +24122,11 @@ function runOneSkillsInstall(install) {
23214
24122
  });
23215
24123
  child.on("close", (code) => {
23216
24124
  if (code === 0) {
23217
- resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
24125
+ resolve14({ ok: true, detail: "", manualCommand: install.manualCommand });
23218
24126
  return;
23219
24127
  }
23220
24128
  const detail = stderr.trim();
23221
- resolve13({
24129
+ resolve14({
23222
24130
  ok: false,
23223
24131
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
23224
24132
  manualCommand: install.manualCommand
@@ -23375,11 +24283,11 @@ function sidecarStateDir(input2) {
23375
24283
  if (!scope || scope.includes("/") || scope.includes("\\")) {
23376
24284
  return null;
23377
24285
  }
23378
- return join13(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
24286
+ return join14(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
23379
24287
  }
23380
24288
  function readOptionalText(path) {
23381
24289
  try {
23382
- return readFileSync11(path, "utf8").trim();
24290
+ return readFileSync12(path, "utf8").trim();
23383
24291
  } catch {
23384
24292
  return "";
23385
24293
  }
@@ -23388,25 +24296,25 @@ function resolvePythonSidecarUpdatePlan(options) {
23388
24296
  const stateDir = sidecarStateDir(options);
23389
24297
  if (!stateDir) return null;
23390
24298
  const relativeEntrypoint = relative2(
23391
- resolve12(stateDir),
23392
- resolve12(options.entrypoint)
24299
+ resolve13(stateDir),
24300
+ resolve13(options.entrypoint)
23393
24301
  );
23394
24302
  if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || isAbsolute2(relativeEntrypoint)) {
23395
24303
  return null;
23396
24304
  }
23397
- const installMethod = readOptionalText(join13(stateDir, ".install-method"));
24305
+ const installMethod = readOptionalText(join14(stateDir, ".install-method"));
23398
24306
  if (installMethod !== "python-sidecar") return null;
23399
24307
  const scope = options.env.DEEPLINE_CONFIG_SCOPE?.trim() || "";
23400
24308
  const hostUrl = options.env.DEEPLINE_HOST_URL?.trim() || "";
23401
- const nodeBin = readOptionalText(join13(stateDir, ".node-bin")) || process.execPath;
23402
- const sidecarPath = readOptionalText(join13(stateDir, ".command-path")) || join13(
24309
+ const nodeBin = readOptionalText(join14(stateDir, ".node-bin")) || process.execPath;
24310
+ const sidecarPath = readOptionalText(join14(stateDir, ".command-path")) || join14(
23403
24311
  stateDir,
23404
24312
  "bin",
23405
24313
  process.platform === "win32" ? "deepline-sdk.cmd" : "deepline-sdk"
23406
24314
  );
23407
24315
  const packageSpec = options.packageSpec || "deepline@latest";
23408
24316
  const npmCommand = "npm";
23409
- const versionDir = join13(stateDir, "versions", "<version>");
24317
+ const versionDir = join14(stateDir, "versions", "<version>");
23410
24318
  const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote4(versionDir)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote4).join(" ")} ${shellQuote4(packageSpec)}`;
23411
24319
  return {
23412
24320
  kind: "python-sidecar",
@@ -23421,9 +24329,9 @@ function resolvePythonSidecarUpdatePlan(options) {
23421
24329
  };
23422
24330
  }
23423
24331
  function findRepoBackedSdkRoot(startPath) {
23424
- let current = resolve12(startPath);
24332
+ let current = resolve13(startPath);
23425
24333
  while (true) {
23426
- if (existsSync11(join13(current, "sdk", "package.json")) && existsSync11(join13(current, "sdk", "bin", "deepline-dev.ts"))) {
24334
+ if (existsSync12(join14(current, "sdk", "package.json")) && existsSync12(join14(current, "sdk", "bin", "deepline-dev.ts"))) {
23427
24335
  return current;
23428
24336
  }
23429
24337
  const parent = dirname12(current);
@@ -23436,7 +24344,7 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
23436
24344
  try {
23437
24345
  return realpathSync3(entrypoint);
23438
24346
  } catch {
23439
- return resolve12(entrypoint);
24347
+ return resolve13(entrypoint);
23440
24348
  }
23441
24349
  })();
23442
24350
  const parts = normalized.split(/[\\/]+/);
@@ -23454,8 +24362,8 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
23454
24362
  }
23455
24363
  function resolveUpdatePlan(options = {}) {
23456
24364
  const env = options.env ?? process.env;
23457
- const homeDir2 = options.homeDir ?? homedir10();
23458
- const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve12(process.argv[1]) : "");
24365
+ const homeDir2 = options.homeDir ?? homedir11();
24366
+ const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve13(process.argv[1]) : "");
23459
24367
  const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname12(entrypoint)) : null;
23460
24368
  if (sourceRoot) {
23461
24369
  return {
@@ -23494,10 +24402,10 @@ var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
23494
24402
  function autoUpdateFailurePath(plan) {
23495
24403
  if (plan.kind === "source") return null;
23496
24404
  if (plan.kind === "python-sidecar") {
23497
- return join13(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
24405
+ return join14(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
23498
24406
  }
23499
- return join13(
23500
- homedir10(),
24407
+ return join14(
24408
+ homedir11(),
23501
24409
  ".local",
23502
24410
  "deepline",
23503
24411
  "sdk-cli",
@@ -23514,7 +24422,7 @@ function readAutoUpdateFailure(plan) {
23514
24422
  if (!path) return null;
23515
24423
  try {
23516
24424
  const parsed = JSON.parse(
23517
- readFileSync11(path, "utf8")
24425
+ readFileSync12(path, "utf8")
23518
24426
  );
23519
24427
  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") {
23520
24428
  return parsed;
@@ -23535,8 +24443,8 @@ function writeAutoUpdateFailure(plan, exitCode) {
23535
24443
  manualCommand: plan.manualCommand
23536
24444
  };
23537
24445
  try {
23538
- mkdirSync9(dirname12(path), { recursive: true });
23539
- writeFileSync14(path, `${JSON.stringify(marker, null, 2)}
24446
+ mkdirSync10(dirname12(path), { recursive: true });
24447
+ writeFileSync15(path, `${JSON.stringify(marker, null, 2)}
23540
24448
  `, "utf8");
23541
24449
  } catch {
23542
24450
  }
@@ -23581,7 +24489,7 @@ function safeVersionSegment(value) {
23581
24489
  return /^[0-9A-Za-z._-]+$/.test(normalized) ? normalized : "";
23582
24490
  }
23583
24491
  function entryPathInVersionDir(versionDir) {
23584
- return join13(
24492
+ return join14(
23585
24493
  versionDir,
23586
24494
  "node_modules",
23587
24495
  "deepline",
@@ -23591,14 +24499,14 @@ function entryPathInVersionDir(versionDir) {
23591
24499
  );
23592
24500
  }
23593
24501
  function installedPackageVersion(versionDir) {
23594
- const packageJsonPath = join13(
24502
+ const packageJsonPath = join14(
23595
24503
  versionDir,
23596
24504
  "node_modules",
23597
24505
  "deepline",
23598
24506
  "package.json"
23599
24507
  );
23600
24508
  try {
23601
- const parsed = JSON.parse(readFileSync11(packageJsonPath, "utf8"));
24509
+ const parsed = JSON.parse(readFileSync12(packageJsonPath, "utf8"));
23602
24510
  return typeof parsed.version === "string" ? safeVersionSegment(parsed.version) : "";
23603
24511
  } catch {
23604
24512
  return "";
@@ -23606,7 +24514,7 @@ function installedPackageVersion(versionDir) {
23606
24514
  }
23607
24515
  function runCommand(command, args, env = process.env, options = {}) {
23608
24516
  return new Promise((resolveExitCode) => {
23609
- const child = spawn3(command, args, {
24517
+ const child = spawn4(command, args, {
23610
24518
  stdio: options.stdio === "stderr" ? ["inherit", "pipe", "pipe"] : "inherit",
23611
24519
  shell: process.platform === "win32",
23612
24520
  env
@@ -23630,9 +24538,9 @@ function runCommand(command, args, env = process.env, options = {}) {
23630
24538
  });
23631
24539
  }
23632
24540
  function writeSidecarLauncher(input2) {
23633
- mkdirSync9(dirname12(input2.path), { recursive: true });
24541
+ mkdirSync10(dirname12(input2.path), { recursive: true });
23634
24542
  if (process.platform === "win32") {
23635
- writeFileSync14(
24543
+ writeFileSync15(
23636
24544
  input2.path,
23637
24545
  [
23638
24546
  `@set DEEPLINE_HOST_URL=${input2.hostUrl.replace(/\r?\n/g, "")}`,
@@ -23644,7 +24552,7 @@ function writeSidecarLauncher(input2) {
23644
24552
  );
23645
24553
  return;
23646
24554
  }
23647
- writeFileSync14(
24555
+ writeFileSync15(
23648
24556
  input2.path,
23649
24557
  [
23650
24558
  "#!/usr/bin/env sh",
@@ -23657,14 +24565,14 @@ function writeSidecarLauncher(input2) {
23657
24565
  );
23658
24566
  }
23659
24567
  async function runPythonSidecarUpdatePlan(plan, options = {}) {
23660
- const versionsDir = join13(plan.stateDir, "versions");
23661
- const tempDir = join13(
24568
+ const versionsDir = join14(plan.stateDir, "versions");
24569
+ const tempDir = join14(
23662
24570
  versionsDir,
23663
24571
  `.tmp-sdk-update-${process.pid}-${Date.now()}`
23664
24572
  );
23665
- rmSync3(tempDir, { recursive: true, force: true });
23666
- mkdirSync9(tempDir, { recursive: true });
23667
- writeFileSync14(join13(tempDir, "package.json"), NPM_SDK_SIDECAR_PACKAGE_JSON);
24573
+ rmSync4(tempDir, { recursive: true, force: true });
24574
+ mkdirSync10(tempDir, { recursive: true });
24575
+ writeFileSync15(join14(tempDir, "package.json"), NPM_SDK_SIDECAR_PACKAGE_JSON);
23668
24576
  const env = {
23669
24577
  ...process.env,
23670
24578
  PATH: `${dirname12(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
@@ -23682,7 +24590,7 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23682
24590
  options
23683
24591
  );
23684
24592
  if (installExitCode !== 0) {
23685
- rmSync3(tempDir, { recursive: true, force: true });
24593
+ rmSync4(tempDir, { recursive: true, force: true });
23686
24594
  return installExitCode;
23687
24595
  }
23688
24596
  const installedVersion = installedPackageVersion(tempDir);
@@ -23690,19 +24598,19 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23690
24598
  process.stderr.write(
23691
24599
  "Updated Deepline SDK package did not report a version.\n"
23692
24600
  );
23693
- rmSync3(tempDir, { recursive: true, force: true });
24601
+ rmSync4(tempDir, { recursive: true, force: true });
23694
24602
  return 1;
23695
24603
  }
23696
- const finalDir = join13(versionsDir, installedVersion);
24604
+ const finalDir = join14(versionsDir, installedVersion);
23697
24605
  const finalEntryPath = entryPathInVersionDir(finalDir);
23698
- if (existsSync11(finalEntryPath)) {
23699
- rmSync3(tempDir, { recursive: true, force: true });
24606
+ if (existsSync12(finalEntryPath)) {
24607
+ rmSync4(tempDir, { recursive: true, force: true });
23700
24608
  } else {
23701
- rmSync3(finalDir, { recursive: true, force: true });
24609
+ rmSync4(finalDir, { recursive: true, force: true });
23702
24610
  try {
23703
24611
  renameSync(tempDir, finalDir);
23704
24612
  } catch (error) {
23705
- rmSync3(tempDir, { recursive: true, force: true });
24613
+ rmSync4(tempDir, { recursive: true, force: true });
23706
24614
  process.stderr.write(
23707
24615
  `Failed to publish Deepline SDK sidecar update: ${error.message}
23708
24616
  `
@@ -23710,7 +24618,7 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23710
24618
  return 1;
23711
24619
  }
23712
24620
  }
23713
- if (!existsSync11(finalEntryPath)) {
24621
+ if (!existsSync12(finalEntryPath)) {
23714
24622
  process.stderr.write(
23715
24623
  `Updated Deepline SDK CLI entrypoint missing: ${finalEntryPath}
23716
24624
  `
@@ -23724,28 +24632,28 @@ async function runPythonSidecarUpdatePlan(plan, options = {}) {
23724
24632
  nodeBin: plan.nodeBin,
23725
24633
  entryPath: finalEntryPath
23726
24634
  });
23727
- writeFileSync14(
23728
- join13(plan.stateDir, ".version"),
24635
+ writeFileSync15(
24636
+ join14(plan.stateDir, ".version"),
23729
24637
  `${installedVersion}
23730
24638
  `,
23731
24639
  "utf8"
23732
24640
  );
23733
- writeFileSync14(
23734
- join13(plan.stateDir, ".install-method"),
24641
+ writeFileSync15(
24642
+ join14(plan.stateDir, ".install-method"),
23735
24643
  "python-sidecar\n",
23736
24644
  "utf8"
23737
24645
  );
23738
- writeFileSync14(
23739
- join13(plan.stateDir, ".command-path"),
24646
+ writeFileSync15(
24647
+ join14(plan.stateDir, ".command-path"),
23740
24648
  `${plan.sidecarPath}
23741
24649
  `,
23742
24650
  "utf8"
23743
24651
  );
23744
- writeFileSync14(join13(plan.stateDir, ".runner"), "node\n", "utf8");
23745
- writeFileSync14(join13(plan.stateDir, ".node-bin"), `${plan.nodeBin}
24652
+ writeFileSync15(join14(plan.stateDir, ".runner"), "node\n", "utf8");
24653
+ writeFileSync15(join14(plan.stateDir, ".node-bin"), `${plan.nodeBin}
23746
24654
  `, "utf8");
23747
- writeFileSync14(
23748
- join13(plan.stateDir, ".entry-path"),
24655
+ writeFileSync15(
24656
+ join14(plan.stateDir, ".entry-path"),
23749
24657
  `${finalEntryPath}
23750
24658
  `,
23751
24659
  "utf8"
@@ -23934,7 +24842,7 @@ function unknownCommandNameFromMessage(message) {
23934
24842
  }
23935
24843
 
23936
24844
  // src/cli/self-update.ts
23937
- import { spawn as spawn4 } from "child_process";
24845
+ import { spawn as spawn5 } from "child_process";
23938
24846
  function envTruthy(name) {
23939
24847
  const value = process.env[name]?.trim().toLowerCase();
23940
24848
  return value === "1" || value === "true" || value === "yes";
@@ -23980,10 +24888,10 @@ function isDowngradeAutoUpdateResponse(response) {
23980
24888
  return compareSemver(target, current) < 0;
23981
24889
  }
23982
24890
  function relaunchCurrentCommand(plan) {
23983
- return new Promise((resolve13) => {
24891
+ return new Promise((resolve14) => {
23984
24892
  const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
23985
24893
  const args = plan.kind === "python-sidecar" ? process.argv.slice(2) : process.argv.slice(1);
23986
- const child = spawn4(command, args, {
24894
+ const child = spawn5(command, args, {
23987
24895
  stdio: "inherit",
23988
24896
  shell: process.platform === "win32",
23989
24897
  env: {
@@ -23996,9 +24904,9 @@ function relaunchCurrentCommand(plan) {
23996
24904
  `Deepline SDK/CLI updated, but relaunch failed: ${error.message}
23997
24905
  `
23998
24906
  );
23999
- resolve13(1);
24907
+ resolve14(1);
24000
24908
  });
24001
- child.on("close", (code) => resolve13(code ?? 1));
24909
+ child.on("close", (code) => resolve14(code ?? 1));
24002
24910
  });
24003
24911
  }
24004
24912
  async function maybeAutoUpdateAndRelaunch(response) {
@@ -24348,8 +25256,8 @@ function topLevelCommandKnown(program, commandName) {
24348
25256
  );
24349
25257
  }
24350
25258
  async function runPlayRunnerHealthCheck() {
24351
- const dir = await mkdtemp2(join14(tmpdir4(), "deepline-health-play-"));
24352
- const file = join14(dir, "health-check.play.ts");
25259
+ const dir = await mkdtemp2(join15(tmpdir4(), "deepline-health-play-"));
25260
+ const file = join15(dir, "health-check.play.ts");
24353
25261
  try {
24354
25262
  await writeFile5(
24355
25263
  file,