deepline 0.2.55 → 0.2.56

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 (41) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +14 -0
  2. package/dist/bundling-sources/sdk/src/http.ts +19 -1
  3. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  4. package/dist/bundling-sources/sdk/src/stream-reconnect.ts +6 -0
  5. package/dist/bundling-sources/sdk/src/types.ts +7 -0
  6. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +146 -12
  7. package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +6 -3
  8. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +1631 -748
  9. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +20 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +81 -52
  11. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +146 -6
  12. package/dist/bundling-sources/shared_libs/play-runtime/gateway-auth-session.ts +56 -22
  13. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +14 -11
  14. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +21 -2
  15. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +81 -21
  16. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +7 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +21 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +27 -2
  20. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +49 -10
  21. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +96 -3
  22. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +341 -67
  23. package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +10 -0
  24. package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +8 -1
  25. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-pg.ts +17 -2
  26. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +4 -1
  27. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +17 -1
  28. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +16 -2
  29. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-writer.ts +25 -0
  30. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +3 -0
  31. package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +2 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +80 -1
  33. package/dist/bundling-sources/shared_libs/security/safe-fetch.ts +9 -0
  34. package/dist/bundling-sources/shared_libs/security/safe-outbound-fetch.ts +85 -48
  35. package/dist/cli/index.js +409 -51
  36. package/dist/cli/index.mjs +389 -25
  37. package/dist/index.d.mts +19 -1
  38. package/dist/index.d.ts +19 -1
  39. package/dist/index.js +29 -2
  40. package/dist/index.mjs +29 -2
  41. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -185,7 +185,7 @@ function configureProxyFromEnv() {
185
185
  configureProxyFromEnv();
186
186
 
187
187
  // src/cli/index.ts
188
- var import_promises8 = require("fs/promises");
188
+ var import_promises9 = require("fs/promises");
189
189
  var import_node_path26 = require("path");
190
190
  var import_node_os19 = require("os");
191
191
  var import_commander4 = require("commander");
@@ -1044,7 +1044,7 @@ var SDK_RELEASE = {
1044
1044
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
1045
1045
  // exposed storage-dependent synchronous access. This deliberate minor
1046
1046
  // release keeps lazy paging semantics independent of row residency.
1047
- version: "0.2.55",
1047
+ version: "0.2.56",
1048
1048
  contracts: {
1049
1049
  api: {
1050
1050
  name: "sdk-http-api",
@@ -1627,9 +1627,26 @@ var HttpClient = class {
1627
1627
  if (error instanceof AuthError || error instanceof DeeplineError) {
1628
1628
  throw error;
1629
1629
  }
1630
- lastError = error instanceof Error ? error : new Error(String(error));
1630
+ const normalized = error instanceof Error ? error : new Error(String(error));
1631
+ if (isAbortLikeError(normalized) && options?.signal?.aborted) {
1632
+ throw new DeeplineError(
1633
+ `Stream from ${this.config.baseUrl} was aborted by the caller.`,
1634
+ void 0,
1635
+ "ABORTED"
1636
+ );
1637
+ }
1638
+ lastError = normalized;
1631
1639
  }
1632
1640
  }
1641
+ if (lastError && isAbortLikeError(lastError)) {
1642
+ throw new DeeplineError(
1643
+ withCoworkNetworkHint(
1644
+ `Unable to stream from ${this.config.baseUrl}. The remote stream was interrupted.`
1645
+ ),
1646
+ void 0,
1647
+ "PLAY_STREAM_NETWORK_ABORTED"
1648
+ );
1649
+ }
1633
1650
  throw new DeeplineError(
1634
1651
  withCoworkNetworkHint(
1635
1652
  lastError?.message ? `Unable to stream from ${this.config.baseUrl}. ${lastError.message}` : `Unable to stream from ${this.config.baseUrl}.`
@@ -1892,6 +1909,9 @@ function streamReconnectDelayMs(attempt) {
1892
1909
  return Math.max(1, Math.floor(Math.random() * (cappedExponentialMs + 1)));
1893
1910
  }
1894
1911
  function isTransientPlayStreamError(error) {
1912
+ if (error instanceof DeeplineError && error.code === "PLAY_STREAM_NETWORK_ABORTED") {
1913
+ return true;
1914
+ }
1895
1915
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
1896
1916
  return error.statusCode >= 500 && error.statusCode < 600;
1897
1917
  }
@@ -2044,6 +2064,7 @@ var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
2044
2064
  var RUNTIME_RECEIPT_COMPLETION_BUFFER_MAX_BYTES = 32 * 1024 * 1024;
2045
2065
  var RUNNER_TERMINAL_PUSH_MAX_BODY_BYTES = 16 * 1024 * 1024;
2046
2066
  var RUNTIME_RECEIPT_GATEWAY_BATCH_MAX_BYTES = 12 * 1024 * 1024;
2067
+ var RUNTIME_RECEIPT_WRITER_TARGET_BATCH_BYTES = 4 * 1024 * 1024;
2047
2068
  var RUNNER_POST_TERMINAL_DIAGNOSTIC_MAX_BYTES = 64 * 1024;
2048
2069
 
2049
2070
  // ../shared_libs/play-runtime/ledger-safe-payload.ts
@@ -4626,6 +4647,10 @@ var DeeplineClient = class {
4626
4647
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
4627
4648
  ...request.force ? { force: true } : {},
4628
4649
  ...forceToolRefresh ? { forceToolRefresh: true } : {},
4650
+ ...typeof request.maxConcurrentExternalCalls === "number" ? {
4651
+ maxConcurrentExternalCalls: request.maxConcurrentExternalCalls
4652
+ } : {},
4653
+ ...typeof request.maxConcurrentRows === "number" ? { maxConcurrentRows: request.maxConcurrentRows } : {},
4629
4654
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
4630
4655
  // Profile selection is the API's job, not the CLI's. The server
4631
4656
  // defaults to absurd; callers normally omit this field.
@@ -4678,6 +4703,8 @@ var DeeplineClient = class {
4678
4703
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
4679
4704
  ...request.force ? { force: true } : {},
4680
4705
  ...forceToolRefresh ? { forceToolRefresh: true } : {},
4706
+ ...typeof request.maxConcurrentExternalCalls === "number" ? { maxConcurrentExternalCalls: request.maxConcurrentExternalCalls } : {},
4707
+ ...typeof request.maxConcurrentRows === "number" ? { maxConcurrentRows: request.maxConcurrentRows } : {},
4681
4708
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
4682
4709
  ...request.profile ? { profile: request.profile } : {},
4683
4710
  ...integrationMode ? { integrationMode } : {},
@@ -8758,14 +8785,14 @@ function invoiceDateText(createdAt) {
8758
8785
  }
8759
8786
  function invoiceLine(entry, compact) {
8760
8787
  const amount = invoiceAmountText(entry.amount_cents, entry.currency);
8761
- const link = entry.url ?? "(no link)";
8788
+ const link2 = entry.url ?? "(no link)";
8762
8789
  if (compact) {
8763
8790
  return [
8764
8791
  entry.id,
8765
8792
  invoiceDateText(entry.created_at),
8766
8793
  amount,
8767
8794
  entry.status,
8768
- link
8795
+ link2
8769
8796
  ].join(" | ");
8770
8797
  }
8771
8798
  return [
@@ -8773,7 +8800,7 @@ function invoiceLine(entry, compact) {
8773
8800
  entry.description,
8774
8801
  amount,
8775
8802
  entry.status,
8776
- link
8803
+ link2
8777
8804
  ].join(" | ");
8778
8805
  }
8779
8806
  async function handleInvoices(options) {
@@ -10917,7 +10944,7 @@ Examples:
10917
10944
  }
10918
10945
 
10919
10946
  // src/cli/commands/enrich.ts
10920
- var import_promises5 = require("fs/promises");
10947
+ var import_promises6 = require("fs/promises");
10921
10948
  var import_node_os10 = require("os");
10922
10949
  var import_node_path15 = require("path");
10923
10950
  var import_commander2 = require("commander");
@@ -10925,6 +10952,7 @@ var import_commander2 = require("commander");
10925
10952
  // src/cli/commands/play.ts
10926
10953
  var import_node_crypto6 = require("crypto");
10927
10954
  var import_node_fs12 = require("fs");
10955
+ var import_promises5 = require("fs/promises");
10928
10956
  var import_node_path14 = require("path");
10929
10957
  var import_sync5 = require("csv-parse/sync");
10930
10958
 
@@ -17577,6 +17605,31 @@ ${hint}`;
17577
17605
  });
17578
17606
  }
17579
17607
 
17608
+ // ../shared_libs/play-runtime/governor/policy.ts
17609
+ var DEFAULT_MAX_CONCURRENT_EXTERNAL_CALLS = 64;
17610
+ var MAX_CONFIGURABLE_CONCURRENT_EXTERNAL_CALLS = 256;
17611
+ var MAX_CONFIGURABLE_CONCURRENT_ROWS = 1e3;
17612
+ function resolveMaxConcurrentExternalCalls(requested) {
17613
+ if (requested === void 0 || requested === null) {
17614
+ return DEFAULT_MAX_CONCURRENT_EXTERNAL_CALLS;
17615
+ }
17616
+ if (!Number.isSafeInteger(requested) || requested < 1 || requested > MAX_CONFIGURABLE_CONCURRENT_EXTERNAL_CALLS) {
17617
+ throw new Error(
17618
+ `maxConcurrentExternalCalls must be a whole number from 1 through ${MAX_CONFIGURABLE_CONCURRENT_EXTERNAL_CALLS}.`
17619
+ );
17620
+ }
17621
+ return requested;
17622
+ }
17623
+ function resolveMaxConcurrentRows(requested) {
17624
+ if (requested === void 0 || requested === null) return null;
17625
+ if (!Number.isSafeInteger(requested) || requested < 1 || requested > MAX_CONFIGURABLE_CONCURRENT_ROWS) {
17626
+ throw new Error(
17627
+ `maxConcurrentRows must be a whole number from 1 through ${MAX_CONFIGURABLE_CONCURRENT_ROWS}.`
17628
+ );
17629
+ }
17630
+ return requested;
17631
+ }
17632
+
17580
17633
  // ../shared_libs/play-runtime/sandbox-runtime-limits.ts
17581
17634
  var PLAY_SANDBOX_SIZE_LIMITS = {
17582
17635
  standard: {
@@ -17801,6 +17854,7 @@ function stripLeadingTimestamp(line) {
17801
17854
  // ../shared_libs/play-runtime/fixture-behavior.ts
17802
17855
  var FIXTURE_BEHAVIOR_VERSION = 1;
17803
17856
  var FIXTURE_BEHAVIOR_RESPONSE_VERSION = 2;
17857
+ var FIXTURE_BEHAVIOR_REPLAY_VERSION = 3;
17804
17858
  var MAX_FIXTURE_RESPONSE_DELAY_SAMPLES = 256;
17805
17859
  var MAX_FIXTURE_RESPONSE_DELAY_MS = 8 * 6e4;
17806
17860
  var MAX_FIXTURE_RESPONSE_ERROR_MESSAGE_LENGTH = 500;
@@ -17812,7 +17866,11 @@ function validateFixtureBehavior(value) {
17812
17866
  return { ok: false, error: "fixtureBehavior must be a JSON object." };
17813
17867
  }
17814
17868
  const record = value;
17815
- const supportedKeys = record.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION ? /* @__PURE__ */ new Set(["version", "responseSamples"]) : /* @__PURE__ */ new Set(["version", "responseDelaySamplesMs"]);
17869
+ const supportedKeys = record.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION || record.version === FIXTURE_BEHAVIOR_REPLAY_VERSION ? /* @__PURE__ */ new Set([
17870
+ "version",
17871
+ "responseSamples",
17872
+ ...record.version === FIXTURE_BEHAVIOR_REPLAY_VERSION ? ["replayBundle"] : []
17873
+ ]) : /* @__PURE__ */ new Set(["version", "responseDelaySamplesMs"]);
17816
17874
  const unknownKeys = Object.keys(record).filter(
17817
17875
  (key) => !supportedKeys.has(key)
17818
17876
  );
@@ -17822,13 +17880,13 @@ function validateFixtureBehavior(value) {
17822
17880
  error: `Unsupported fixtureBehavior field "${unknownKeys[0]}".`
17823
17881
  };
17824
17882
  }
17825
- if (record.version !== FIXTURE_BEHAVIOR_VERSION && record.version !== FIXTURE_BEHAVIOR_RESPONSE_VERSION) {
17883
+ if (record.version !== FIXTURE_BEHAVIOR_VERSION && record.version !== FIXTURE_BEHAVIOR_RESPONSE_VERSION && record.version !== FIXTURE_BEHAVIOR_REPLAY_VERSION) {
17826
17884
  return {
17827
17885
  ok: false,
17828
- error: `fixtureBehavior.version must be ${FIXTURE_BEHAVIOR_VERSION} or ${FIXTURE_BEHAVIOR_RESPONSE_VERSION}.`
17886
+ error: `fixtureBehavior.version must be ${FIXTURE_BEHAVIOR_VERSION} or ${FIXTURE_BEHAVIOR_RESPONSE_VERSION}, or ${FIXTURE_BEHAVIOR_REPLAY_VERSION}.`
17829
17887
  };
17830
17888
  }
17831
- if (record.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION) {
17889
+ if (record.version === FIXTURE_BEHAVIOR_RESPONSE_VERSION || record.version === FIXTURE_BEHAVIOR_REPLAY_VERSION) {
17832
17890
  if (!Array.isArray(record.responseSamples) || record.responseSamples.length === 0 || record.responseSamples.length > MAX_FIXTURE_RESPONSE_DELAY_SAMPLES) {
17833
17891
  return {
17834
17892
  ok: false,
@@ -17935,6 +17993,72 @@ function validateFixtureBehavior(value) {
17935
17993
  ...httpError ? { httpError } : {}
17936
17994
  });
17937
17995
  }
17996
+ let replayBundle;
17997
+ if (record.version === FIXTURE_BEHAVIOR_REPLAY_VERSION) {
17998
+ if (!record.replayBundle || typeof record.replayBundle !== "object" || Array.isArray(record.replayBundle)) {
17999
+ return {
18000
+ ok: false,
18001
+ error: "fixtureBehavior.replayBundle must be an object."
18002
+ };
18003
+ }
18004
+ const replay = record.replayBundle;
18005
+ const replayUnknownKeys = Object.keys(replay).filter(
18006
+ (key) => key !== "bundleId" && key !== "manifestSha256" && key !== "syntheticFallbackToolIds"
18007
+ );
18008
+ if (replayUnknownKeys.length > 0) {
18009
+ return {
18010
+ ok: false,
18011
+ error: `Unsupported fixtureBehavior.replayBundle field "${replayUnknownKeys[0]}".`
18012
+ };
18013
+ }
18014
+ const digestPattern = /^[a-f0-9]{64}$/;
18015
+ if (typeof replay.bundleId !== "string" || !digestPattern.test(replay.bundleId)) {
18016
+ return {
18017
+ ok: false,
18018
+ error: "fixtureBehavior.replayBundle.bundleId must be a lowercase SHA-256 digest."
18019
+ };
18020
+ }
18021
+ if (typeof replay.manifestSha256 !== "string" || !digestPattern.test(replay.manifestSha256)) {
18022
+ return {
18023
+ ok: false,
18024
+ error: "fixtureBehavior.replayBundle.manifestSha256 must be a lowercase SHA-256 digest."
18025
+ };
18026
+ }
18027
+ let syntheticFallbackToolIds;
18028
+ if (replay.syntheticFallbackToolIds !== void 0) {
18029
+ if (!Array.isArray(replay.syntheticFallbackToolIds) || replay.syntheticFallbackToolIds.length === 0 || replay.syntheticFallbackToolIds.length > 32) {
18030
+ return {
18031
+ ok: false,
18032
+ error: "fixtureBehavior.replayBundle.syntheticFallbackToolIds must contain 1-32 tool ids."
18033
+ };
18034
+ }
18035
+ syntheticFallbackToolIds = [];
18036
+ for (const rawToolId of replay.syntheticFallbackToolIds) {
18037
+ if (typeof rawToolId !== "string" || rawToolId !== rawToolId.trim().toLowerCase() || !/^[a-z0-9][a-z0-9_.-]*$/.test(rawToolId) || rawToolId.length > 250 || syntheticFallbackToolIds.includes(rawToolId)) {
18038
+ return {
18039
+ ok: false,
18040
+ error: "fixtureBehavior.replayBundle.syntheticFallbackToolIds contains an invalid tool id."
18041
+ };
18042
+ }
18043
+ syntheticFallbackToolIds.push(rawToolId);
18044
+ }
18045
+ }
18046
+ replayBundle = {
18047
+ bundleId: replay.bundleId,
18048
+ manifestSha256: replay.manifestSha256,
18049
+ ...syntheticFallbackToolIds ? { syntheticFallbackToolIds } : {}
18050
+ };
18051
+ }
18052
+ if (record.version === FIXTURE_BEHAVIOR_REPLAY_VERSION) {
18053
+ return {
18054
+ ok: true,
18055
+ behavior: {
18056
+ version: FIXTURE_BEHAVIOR_REPLAY_VERSION,
18057
+ responseSamples: samples2,
18058
+ replayBundle
18059
+ }
18060
+ };
18061
+ }
17938
18062
  return {
17939
18063
  ok: true,
17940
18064
  behavior: {
@@ -18027,6 +18151,114 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
18027
18151
  "--debug-map-latency",
18028
18152
  "--debug-fixture-provider-pacing"
18029
18153
  ]);
18154
+ async function pathExistsIncludingSymlink(path) {
18155
+ try {
18156
+ await (0, import_promises5.lstat)(path);
18157
+ return true;
18158
+ } catch (error) {
18159
+ if (error.code === "ENOENT") {
18160
+ return false;
18161
+ }
18162
+ throw error;
18163
+ }
18164
+ }
18165
+ function runIdFileTempPath(destination) {
18166
+ return (0, import_node_path14.join)(
18167
+ (0, import_node_path14.dirname)(destination),
18168
+ `.${(0, import_node_path14.basename)(destination)}.${process.pid}.${(0, import_node_crypto6.randomUUID)()}.tmp`
18169
+ );
18170
+ }
18171
+ async function removeRunIdTempFile(path) {
18172
+ try {
18173
+ await (0, import_promises5.unlink)(path);
18174
+ } catch (error) {
18175
+ if (error.code !== "ENOENT") {
18176
+ throw error;
18177
+ }
18178
+ }
18179
+ }
18180
+ async function preflightRunIdFile(path) {
18181
+ const destination = (0, import_node_path14.resolve)(path);
18182
+ if (await pathExistsIncludingSymlink(destination)) {
18183
+ throw new Error(
18184
+ `--run-id-file destination already exists: ${destination}. Choose a new path so this run cannot overwrite another run identity.`
18185
+ );
18186
+ }
18187
+ const tempPath = runIdFileTempPath(destination);
18188
+ let handle = null;
18189
+ try {
18190
+ handle = await (0, import_promises5.open)(tempPath, "wx", 384);
18191
+ await handle.sync();
18192
+ } catch (error) {
18193
+ throw new Error(
18194
+ `Cannot write --run-id-file destination ${destination}: ${error instanceof Error ? error.message : String(error)}`
18195
+ );
18196
+ } finally {
18197
+ await handle?.close();
18198
+ await removeRunIdTempFile(tempPath);
18199
+ }
18200
+ return destination;
18201
+ }
18202
+ async function readRunIdFile(destination) {
18203
+ if (!await pathExistsIncludingSymlink(destination)) {
18204
+ return null;
18205
+ }
18206
+ let parsed;
18207
+ try {
18208
+ parsed = JSON.parse(await (0, import_promises5.readFile)(destination, "utf8"));
18209
+ } catch (error) {
18210
+ throw new Error(
18211
+ `--run-id-file destination contains invalid JSON: ${destination}. Refusing to overwrite it (${error instanceof Error ? error.message : String(error)}).`
18212
+ );
18213
+ }
18214
+ if (!parsed || typeof parsed !== "object" || parsed.version !== 1 || typeof parsed.runId !== "string" || !parsed.runId) {
18215
+ throw new Error(
18216
+ `--run-id-file destination has an unsupported identity record: ${destination}. Refusing to overwrite it.`
18217
+ );
18218
+ }
18219
+ return parsed;
18220
+ }
18221
+ async function writePlayRunIdFile(destination, runId) {
18222
+ const existing = await readRunIdFile(destination);
18223
+ if (existing) {
18224
+ if (existing.runId === runId) return;
18225
+ throw new Error(
18226
+ `--run-id-file destination already records run ${existing.runId}; refusing to replace it with ${runId}: ${destination}`
18227
+ );
18228
+ }
18229
+ const tempPath = runIdFileTempPath(destination);
18230
+ let handle = null;
18231
+ try {
18232
+ handle = await (0, import_promises5.open)(tempPath, "wx", 384);
18233
+ await handle.writeFile(
18234
+ `${JSON.stringify({ version: 1, runId })}
18235
+ `,
18236
+ "utf8"
18237
+ );
18238
+ await handle.sync();
18239
+ await handle.close();
18240
+ handle = null;
18241
+ try {
18242
+ await (0, import_promises5.link)(tempPath, destination);
18243
+ const directory = await (0, import_promises5.open)((0, import_node_path14.dirname)(destination), "r");
18244
+ try {
18245
+ await directory.sync();
18246
+ } finally {
18247
+ await directory.close();
18248
+ }
18249
+ } catch (error) {
18250
+ if (error.code !== "EEXIST") throw error;
18251
+ const raced = await readRunIdFile(destination);
18252
+ if (raced?.runId === runId) return;
18253
+ throw new Error(
18254
+ `--run-id-file destination already records run ${raced?.runId ?? "<invalid>"}; refusing to replace it with ${runId}: ${destination}`
18255
+ );
18256
+ }
18257
+ } finally {
18258
+ await handle?.close();
18259
+ await removeRunIdTempFile(tempPath);
18260
+ }
18261
+ }
18030
18262
  function traceCliSync(phase, fields, run) {
18031
18263
  const startedAt = Date.now();
18032
18264
  try {
@@ -19431,8 +19663,8 @@ function buildPlayDashboardUrl(baseUrl, playName) {
19431
19663
  const encodedPlayName = encodeURIComponent(playName);
19432
19664
  return `${trimmedBase}/dashboard/plays/${encodedPlayName}`;
19433
19665
  }
19434
- function openPlayDashboard(dashboardUrl, open) {
19435
- if (open && dashboardUrl) {
19666
+ function openPlayDashboard(dashboardUrl, open2) {
19667
+ if (open2 && dashboardUrl) {
19436
19668
  openInBrowser(dashboardUrl);
19437
19669
  }
19438
19670
  }
@@ -19468,9 +19700,11 @@ function assertPlayWaitNotTimedOut(input2) {
19468
19700
  );
19469
19701
  }
19470
19702
  }
19703
+ var PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS = 15e3;
19471
19704
  async function waitForPlayCompletionByStream(input2) {
19472
19705
  let lastPhase = null;
19473
19706
  let reconnectAttempt = 0;
19707
+ let nextDurableProbeAt = Date.now() + PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS;
19474
19708
  const withDashboardUrl = (status) => input2.dashboardUrl ? { ...status, dashboardUrl: input2.dashboardUrl } : status;
19475
19709
  const remainingWaitMs = () => input2.waitTimeoutMs === null ? null : input2.waitTimeoutMs - (Date.now() - input2.startedAt);
19476
19710
  const fetchTerminalStatus = async () => {
@@ -19489,6 +19723,14 @@ async function waitForPlayCompletionByStream(input2) {
19489
19723
  };
19490
19724
  const handleLiveEvent = async (event) => {
19491
19725
  assertPlayWaitNotTimedOut({ ...input2, lastPhase });
19726
+ const now = Date.now();
19727
+ if (now >= nextDurableProbeAt) {
19728
+ nextDurableProbeAt = now + PLAY_DURABLE_STATUS_PROBE_INTERVAL_MS;
19729
+ const durableTerminal = await fetchTerminalStatus();
19730
+ if (durableTerminal) {
19731
+ return durableTerminal;
19732
+ }
19733
+ }
19492
19734
  const phase = describeLiveEventPhase(event);
19493
19735
  if (phase) {
19494
19736
  lastPhase = phase;
@@ -19737,7 +19979,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
19737
19979
  lastKnownWorkflowId = eventRunId;
19738
19980
  firstRunIdMs ??= Date.now() - startedAt;
19739
19981
  if (runStartedNow) {
19740
- input2.onRunStarted?.(eventRunId);
19982
+ await input2.onRunStarted?.(eventRunId);
19741
19983
  }
19742
19984
  }
19743
19985
  if (eventConfirmsPlayRunLaunch(event) && eventRunId === lastKnownWorkflowId) {
@@ -21016,6 +21258,15 @@ function buildOrdinaryPlayRunCommand(options, resolvedRevisionId) {
21016
21258
  }
21017
21259
  if (options.profile)
21018
21260
  parts.push("--profile", shellSingleQuote(options.profile));
21261
+ if (options.maxConcurrentExternalCalls !== null) {
21262
+ parts.push(
21263
+ "--max-concurrent-external-calls",
21264
+ String(options.maxConcurrentExternalCalls)
21265
+ );
21266
+ }
21267
+ if (options.maxConcurrentRows !== null) {
21268
+ parts.push("--max-concurrent-rows", String(options.maxConcurrentRows));
21269
+ }
21019
21270
  const pinnedRevisionId = options.target.kind === "name" ? resolvedRevisionId ?? options.revisionId : null;
21020
21271
  if (pinnedRevisionId) {
21021
21272
  parts.push("--revision-id", shellSingleQuote(pinnedRevisionId));
@@ -21885,7 +22136,7 @@ function writeStartedPlayRun(input2) {
21885
22136
  );
21886
22137
  }
21887
22138
  function parsePlayRunOptions(args) {
21888
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
22139
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--run-id-file <path>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
21889
22140
  let filePath = null;
21890
22141
  let playName = null;
21891
22142
  let input2 = null;
@@ -21896,15 +22147,18 @@ function parsePlayRunOptions(args) {
21896
22147
  const fullJson = args.includes("--full");
21897
22148
  const emitLogs = !jsonOutput || args.includes("--logs");
21898
22149
  const force = args.includes("--force");
21899
- const open = args.includes("--open");
22150
+ const open2 = args.includes("--open");
21900
22151
  const debugMapLatency = args.includes("--debug-map-latency");
21901
22152
  const debugFixtureProviderPacing = args.includes(
21902
22153
  "--debug-fixture-provider-pacing"
21903
22154
  );
21904
22155
  const verboseLogs = args.includes("--logs") || debugMapLatency;
21905
22156
  let waitTimeoutMs = null;
22157
+ let maxConcurrentExternalCalls = null;
22158
+ let maxConcurrentRows = null;
21906
22159
  let profile = null;
21907
22160
  let fixtureBehavior = null;
22161
+ let runIdFile = null;
21908
22162
  for (let index = 0; index < args.length; index += 1) {
21909
22163
  const arg = args[index];
21910
22164
  if (arg === "--file" && args[index + 1]) {
@@ -21919,6 +22173,23 @@ function parsePlayRunOptions(args) {
21919
22173
  input2 = parseJsonInput(args[++index]);
21920
22174
  continue;
21921
22175
  }
22176
+ if (arg === "--run-id-file") {
22177
+ const value = args[index + 1];
22178
+ if (!value || value.startsWith("--")) {
22179
+ throw new Error("--run-id-file requires a destination path.");
22180
+ }
22181
+ runIdFile = value;
22182
+ index += 1;
22183
+ continue;
22184
+ }
22185
+ if (arg.startsWith("--run-id-file=")) {
22186
+ const value = arg.slice("--run-id-file=".length);
22187
+ if (!value) {
22188
+ throw new Error("--run-id-file requires a destination path.");
22189
+ }
22190
+ runIdFile = value;
22191
+ continue;
22192
+ }
21922
22193
  if (arg === "--revision-id" && args[index + 1]) {
21923
22194
  revisionId = args[++index];
21924
22195
  continue;
@@ -21933,6 +22204,41 @@ function parsePlayRunOptions(args) {
21933
22204
  index += 1;
21934
22205
  continue;
21935
22206
  }
22207
+ if (arg === "--max-concurrent-external-calls") {
22208
+ const value = args[index + 1];
22209
+ if (!value || value.startsWith("--")) {
22210
+ throw new Error(
22211
+ "--max-concurrent-external-calls requires a whole number."
22212
+ );
22213
+ }
22214
+ if (!/^[1-9]\d*$/.test(value)) {
22215
+ throw new Error(
22216
+ "--max-concurrent-external-calls requires a positive whole number."
22217
+ );
22218
+ }
22219
+ maxConcurrentExternalCalls = parsePositiveInteger3(
22220
+ value,
22221
+ "--max-concurrent-external-calls"
22222
+ );
22223
+ resolveMaxConcurrentExternalCalls(maxConcurrentExternalCalls);
22224
+ index += 1;
22225
+ continue;
22226
+ }
22227
+ if (arg === "--max-concurrent-rows") {
22228
+ const value = args[index + 1];
22229
+ if (!value || value.startsWith("--")) {
22230
+ throw new Error("--max-concurrent-rows requires a whole number.");
22231
+ }
22232
+ if (!/^[1-9]\d*$/.test(value)) {
22233
+ throw new Error(
22234
+ "--max-concurrent-rows requires a positive whole number."
22235
+ );
22236
+ }
22237
+ maxConcurrentRows = parsePositiveInteger3(value, "--max-concurrent-rows");
22238
+ resolveMaxConcurrentRows(maxConcurrentRows);
22239
+ index += 1;
22240
+ continue;
22241
+ }
21936
22242
  if (arg === "--fixture-behavior") {
21937
22243
  const value = args[index + 1];
21938
22244
  if (!value) {
@@ -22043,11 +22349,14 @@ function parsePlayRunOptions(args) {
22043
22349
  fullJson,
22044
22350
  waitTimeoutMs,
22045
22351
  force,
22046
- open,
22352
+ maxConcurrentExternalCalls,
22353
+ maxConcurrentRows,
22354
+ open: open2,
22047
22355
  profile,
22048
22356
  debugMapLatency,
22049
22357
  debugFixtureProviderPacing,
22050
- fixtureBehavior
22358
+ fixtureBehavior,
22359
+ runIdFile
22051
22360
  };
22052
22361
  }
22053
22362
  function parsePlayCheckOptions(args) {
@@ -22730,6 +23039,8 @@ async function handleFileBackedRun(options, hooks) {
22730
23039
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
22731
23040
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
22732
23041
  ...options.force ? { force: true } : {},
23042
+ ...options.maxConcurrentExternalCalls !== null ? { maxConcurrentExternalCalls: options.maxConcurrentExternalCalls } : {},
23043
+ ...options.maxConcurrentRows !== null ? { maxConcurrentRows: options.maxConcurrentRows } : {},
22733
23044
  ...options.profile ? { profile: options.profile } : {},
22734
23045
  ...Object.keys(testPolicyOverrides).length > 0 ? { testPolicyOverrides } : {},
22735
23046
  ...integrationMode ? { integrationMode } : {},
@@ -22790,6 +23101,7 @@ async function handleFileBackedRun(options, hooks) {
22790
23101
  throw await normalizePlayStartError(client2, error, playName);
22791
23102
  })
22792
23103
  );
23104
+ await hooks?.onRunStarted?.(started.workflowId);
22793
23105
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
22794
23106
  openPlayDashboard(resolvedDashboardUrl, options.open);
22795
23107
  progress.phase("started run");
@@ -22910,6 +23222,8 @@ async function handleNamedRun(options, hooks) {
22910
23222
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
22911
23223
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
22912
23224
  ...options.force ? { force: true } : {},
23225
+ ...options.maxConcurrentExternalCalls !== null ? { maxConcurrentExternalCalls: options.maxConcurrentExternalCalls } : {},
23226
+ ...options.maxConcurrentRows !== null ? { maxConcurrentRows: options.maxConcurrentRows } : {},
22913
23227
  ...options.profile ? { profile: options.profile } : {},
22914
23228
  ...Object.keys(testPolicyOverrides).length > 0 ? { testPolicyOverrides } : {},
22915
23229
  ...integrationMode ? { integrationMode } : {},
@@ -22975,6 +23289,7 @@ async function handleNamedRun(options, hooks) {
22975
23289
  });
22976
23290
  })
22977
23291
  );
23292
+ await hooks?.onRunStarted?.(started.workflowId);
22978
23293
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
22979
23294
  openPlayDashboard(resolvedDashboardUrl, options.open);
22980
23295
  progress.phase("started run");
@@ -22991,10 +23306,28 @@ async function handleNamedRun(options, hooks) {
22991
23306
  return 0;
22992
23307
  }
22993
23308
  async function handlePlayRun(args, hooks) {
22994
- const options = parsePlayRunOptions(args);
23309
+ const parsedOptions = parsePlayRunOptions(args);
23310
+ const options = parsedOptions.runIdFile ? {
23311
+ ...parsedOptions,
23312
+ runIdFile: await preflightRunIdFile(parsedOptions.runIdFile)
23313
+ } : parsedOptions;
23314
+ const runHooks = options.runIdFile ? {
23315
+ ...hooks,
23316
+ onRunStarted: async (runId) => {
23317
+ try {
23318
+ await writePlayRunIdFile(options.runIdFile, runId);
23319
+ } catch (error) {
23320
+ throw new Error(
23321
+ `Run ${runId} was accepted, but its identity could not be persisted to ${options.runIdFile}: ${error instanceof Error ? error.message : String(error)}. Inspect it with 'deepline runs get ${runId} --full --json'; do not submit a replacement run.`,
23322
+ { cause: error }
23323
+ );
23324
+ }
23325
+ await hooks?.onRunStarted?.(runId);
23326
+ }
23327
+ } : hooks;
22995
23328
  if (options.target.kind === "file") {
22996
23329
  if (isFileTarget(options.target.path)) {
22997
- return handleFileBackedRun(options, hooks);
23330
+ return handleFileBackedRun(options, runHooks);
22998
23331
  }
22999
23332
  const resolved = (0, import_node_path14.resolve)(options.target.path);
23000
23333
  console.error(`File not found: ${resolved}`);
@@ -23016,7 +23349,7 @@ async function handlePlayRun(args, hooks) {
23016
23349
  }
23017
23350
  return 1;
23018
23351
  }
23019
- return handleNamedRun(options, hooks);
23352
+ return handleNamedRun(options, runHooks);
23020
23353
  }
23021
23354
  function parseRunIdPositional(args, usage) {
23022
23355
  for (let index = 0; index < args.length; index += 1) {
@@ -24344,10 +24677,18 @@ Notes:
24344
24677
  next commands. --watch and --wait are accepted compatibility aliases for the
24345
24678
  default behavior. Use --no-wait only when you intentionally want
24346
24679
  a fire-and-forget run id.
24680
+ --run-id-file writes the durable run id to a versioned JSON file as soon as
24681
+ the server accepts the run. The destination must not already exist.
24347
24682
  The play page URL is printed when the run starts. Pass --open to open it in a browser.
24348
24683
  Concurrent runs for the same play are allowed.
24349
24684
  --force starts a fresh run graph without refreshing completed provider calls.
24350
24685
  It does not cancel active sibling runs.
24686
+ --max-concurrent-external-calls controls the per-run provider-tool/ctx.fetch
24687
+ resident-work ceiling. Default: ${DEFAULT_MAX_CONCURRENT_EXTERNAL_CALLS}; accepted range: 1-${MAX_CONFIGURABLE_CONCURRENT_EXTERNAL_CALLS}.
24688
+ Provider pacing and sandbox memory limits still apply.
24689
+ --max-concurrent-rows sets the run-wide default and ceiling for live map row
24690
+ resolvers. Accepted range: 1-${MAX_CONFIGURABLE_CONCURRENT_ROWS}. The runtime
24691
+ may lower it when source-row size exceeds the active-row memory budget.
24351
24692
  This command starts cloud work and may spend Deepline credits through tool calls.
24352
24693
 
24353
24694
  Idempotent execution:
@@ -24383,8 +24724,10 @@ Idempotent execution:
24383
24724
  Examples:
24384
24725
  deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
24385
24726
  deepline plays run long-background-play --no-wait
24727
+ deepline plays run long-background-play --run-id-file ./run-id.json
24386
24728
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
24387
24729
  deepline plays run my.play.ts --profile absurd
24730
+ deepline plays run my.play.ts --max-concurrent-external-calls 20
24388
24731
  deepline plays run my.play.ts --input @input.json --json
24389
24732
  deepline plays run cto-search.play.ts --limit 5
24390
24733
  deepline runs export <run-id> --out output.csv
@@ -24400,9 +24743,18 @@ Examples:
24400
24743
  "--fixture-behavior <json>",
24401
24744
  "Internal/testing: fixture response behavior JSON object or @file path"
24402
24745
  ).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
24746
+ "--run-id-file <path>",
24747
+ "Atomically write the accepted run id to a new JSON file"
24748
+ ).option(
24403
24749
  "--logs",
24404
24750
  "When output is non-interactive, stream play logs to stderr while waiting"
24405
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option("--open", "Open the play page in a browser after the run starts").option(
24751
+ ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
24752
+ "--max-concurrent-external-calls <count>",
24753
+ `Concurrent provider-tool and ctx.fetch executions (${DEFAULT_MAX_CONCURRENT_EXTERNAL_CALLS} default, max ${MAX_CONFIGURABLE_CONCURRENT_EXTERNAL_CALLS})`
24754
+ ).option(
24755
+ "--max-concurrent-rows <count>",
24756
+ `Run-wide dataset map row resolver ceiling (max ${MAX_CONFIGURABLE_CONCURRENT_ROWS})`
24757
+ ).option("--open", "Open the play page in a browser after the run starts").option(
24406
24758
  "--debug-map-latency",
24407
24759
  "Internal diagnostics: emit one aggregate latency profile per dataset map"
24408
24760
  ).option(
@@ -24441,10 +24793,16 @@ Pass-through input flags:
24441
24793
  ...options.profile ? ["--profile", options.profile] : [],
24442
24794
  ...options.fixtureBehavior ? ["--fixture-behavior", options.fixtureBehavior] : [],
24443
24795
  ...options.wait === false ? ["--no-wait"] : [],
24796
+ ...options.runIdFile ? ["--run-id-file", options.runIdFile] : [],
24444
24797
  ...options.watch || options.wait ? ["--watch"] : [],
24445
24798
  ...options.logs ? ["--logs"] : [],
24446
24799
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
24447
24800
  ...options.force ? ["--force"] : [],
24801
+ ...options.maxConcurrentExternalCalls ? [
24802
+ "--max-concurrent-external-calls",
24803
+ options.maxConcurrentExternalCalls
24804
+ ] : [],
24805
+ ...options.maxConcurrentRows ? ["--max-concurrent-rows", options.maxConcurrentRows] : [],
24448
24806
  ...options.open ? ["--open"] : [],
24449
24807
  ...options.debugMapLatency ? ["--debug-map-latency"] : [],
24450
24808
  ...options.debugFixtureProviderPacing ? ["--debug-fixture-provider-pacing"] : [],
@@ -26833,7 +27191,7 @@ async function readAtFileReference(value, argumentName, strip = true) {
26833
27191
  throw new Error(`Invalid ${argumentName} value: empty @file path.`);
26834
27192
  }
26835
27193
  try {
26836
- const text = await (0, import_promises5.readFile)(filePath, "utf8");
27194
+ const text = await (0, import_promises6.readFile)(filePath, "utf8");
26837
27195
  const normalized = text.replace(/^\uFEFF/, "");
26838
27196
  return strip ? normalized.trim() : normalized;
26839
27197
  } catch (error) {
@@ -27131,7 +27489,7 @@ async function buildPlanArgs(args) {
27131
27489
  async function assertInputCsvExists(inputCsv) {
27132
27490
  const path = (0, import_node_path15.resolve)(inputCsv);
27133
27491
  try {
27134
- const info = await (0, import_promises5.stat)(path);
27492
+ const info = await (0, import_promises6.stat)(path);
27135
27493
  if (info.isFile()) {
27136
27494
  return;
27137
27495
  }
@@ -27152,8 +27510,8 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
27152
27510
  }
27153
27511
  try {
27154
27512
  const [inputInfo, outputInfo] = await Promise.all([
27155
- (0, import_promises5.stat)(input2),
27156
- (0, import_promises5.stat)(output2)
27513
+ (0, import_promises6.stat)(input2),
27514
+ (0, import_promises6.stat)(output2)
27157
27515
  ]);
27158
27516
  if (inputInfo.dev === outputInfo.dev && inputInfo.ino === outputInfo.ino) {
27159
27517
  throw new Error(
@@ -27173,7 +27531,7 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
27173
27531
  }
27174
27532
  async function regularFileExists(path) {
27175
27533
  try {
27176
- const info = await (0, import_promises5.stat)((0, import_node_path15.resolve)(path));
27534
+ const info = await (0, import_promises6.stat)((0, import_node_path15.resolve)(path));
27177
27535
  return info.isFile();
27178
27536
  } catch (error) {
27179
27537
  const code = error && typeof error === "object" ? error.code : void 0;
@@ -27184,7 +27542,7 @@ async function regularFileExists(path) {
27184
27542
  }
27185
27543
  }
27186
27544
  async function readConfig(path) {
27187
- const source = await (0, import_promises5.readFile)((0, import_node_path15.resolve)(path), "utf8");
27545
+ const source = await (0, import_promises6.readFile)((0, import_node_path15.resolve)(path), "utf8");
27188
27546
  let parsed;
27189
27547
  try {
27190
27548
  parsed = JSON.parse(source);
@@ -27605,7 +27963,7 @@ async function writeOutputCsv(outputPath, status, options) {
27605
27963
  ]),
27606
27964
  options?.config
27607
27965
  );
27608
- await (0, import_promises5.writeFile)(
27966
+ await (0, import_promises6.writeFile)(
27609
27967
  (0, import_node_path15.resolve)(outputPath),
27610
27968
  csvStringFromRows(merged.rows, columns),
27611
27969
  "utf8"
@@ -29285,7 +29643,7 @@ async function persistEnrichFailureReport(input2) {
29285
29643
  }
29286
29644
  const stateDir = (0, import_node_path15.join)((0, import_node_os10.homedir)(), ".local", "deepline", "runtime", "state");
29287
29645
  const reportPrefix = input2.jobs.length > 0 ? "run-block-failures" : "enrich-issues";
29288
- await (0, import_promises5.mkdir)(stateDir, { recursive: true });
29646
+ await (0, import_promises6.mkdir)(stateDir, { recursive: true });
29289
29647
  const reportPath = (0, import_node_path15.join)(
29290
29648
  stateDir,
29291
29649
  `${reportPrefix}-${Math.floor(Date.now() / 1e3)}-${process.pid}.json`
@@ -29311,7 +29669,7 @@ async function persistEnrichFailureReport(input2) {
29311
29669
  if (input2.rows.rowStart !== null && input2.rows.rowEnd !== null) {
29312
29670
  report.rows = { start: input2.rows.rowStart, end: input2.rows.rowEnd };
29313
29671
  }
29314
- await (0, import_promises5.writeFile)(reportPath, `${JSON.stringify(report, null, 2)}
29672
+ await (0, import_promises6.writeFile)(reportPath, `${JSON.stringify(report, null, 2)}
29315
29673
  `, "utf8");
29316
29674
  return reportPath;
29317
29675
  }
@@ -30214,13 +30572,13 @@ function registerEnrichCommand(program) {
30214
30572
  sdkEnrichTelemetryCompleted = true;
30215
30573
  await completeSdkEnrichTelemetry(sdkEnrichTelemetry, input2);
30216
30574
  };
30217
- const tempDir = await (0, import_promises5.mkdtemp)((0, import_node_path15.join)((0, import_node_os10.tmpdir)(), "deepline-enrich-play-"));
30575
+ const tempDir = await (0, import_promises6.mkdtemp)((0, import_node_path15.join)((0, import_node_os10.tmpdir)(), "deepline-enrich-play-"));
30218
30576
  await emitSdkEnrichTelemetry(sdkEnrichTelemetry, "enrich_started");
30219
30577
  const tempPlay = (0, import_node_path15.join)(tempDir, "deepline-enrich.play.ts");
30220
30578
  let inPlaceTempDir = null;
30221
30579
  let inPlaceTempOutputPath = null;
30222
30580
  const inPlaceFinalOutputPath = options.inPlace ? (0, import_node_path15.resolve)(inputCsv) : null;
30223
- const inPlaceCommitOutputPath = options.inPlace ? (await (0, import_promises5.lstat)(inputCsv)).isSymbolicLink() ? await (0, import_promises5.realpath)(inputCsv) : inPlaceFinalOutputPath : null;
30581
+ const inPlaceCommitOutputPath = options.inPlace ? (await (0, import_promises6.lstat)(inputCsv)).isSymbolicLink() ? await (0, import_promises6.realpath)(inputCsv) : inPlaceFinalOutputPath : null;
30224
30582
  const failureReportOutputPath = options.inPlace ? inPlaceFinalOutputPath : null;
30225
30583
  const enrichIssueFollowUpOutputPath = options.inPlace && inPlaceFinalOutputPath ? sidecarEnrichRowsExportPath(inPlaceFinalOutputPath) : null;
30226
30584
  let activeRunId2 = null;
@@ -30241,16 +30599,16 @@ function registerEnrichCommand(program) {
30241
30599
  return;
30242
30600
  }
30243
30601
  if (inPlaceTempDir) {
30244
- await (0, import_promises5.rm)(inPlaceTempDir, { recursive: true, force: true });
30602
+ await (0, import_promises6.rm)(inPlaceTempDir, { recursive: true, force: true });
30245
30603
  }
30246
- inPlaceTempDir = await (0, import_promises5.mkdtemp)(
30604
+ inPlaceTempDir = await (0, import_promises6.mkdtemp)(
30247
30605
  (0, import_node_path15.join)(
30248
30606
  (0, import_node_path15.dirname)(inPlaceCommitOutputPath ?? (0, import_node_path15.resolve)(inputCsv)),
30249
30607
  ".deepline-enrich-in-place-"
30250
30608
  )
30251
30609
  );
30252
30610
  inPlaceTempOutputPath = (0, import_node_path15.join)(inPlaceTempDir, "output.csv");
30253
- await (0, import_promises5.copyFile)((0, import_node_path15.resolve)(inputCsv), inPlaceTempOutputPath);
30611
+ await (0, import_promises6.copyFile)((0, import_node_path15.resolve)(inputCsv), inPlaceTempOutputPath);
30254
30612
  outputPath = inPlaceTempOutputPath;
30255
30613
  };
30256
30614
  const commitInPlaceOutput = async (exportResult) => {
@@ -30258,12 +30616,12 @@ function registerEnrichCommand(program) {
30258
30616
  return exportResult;
30259
30617
  }
30260
30618
  const committedTempDir = inPlaceTempDir;
30261
- await (0, import_promises5.rename)(inPlaceTempOutputPath, inPlaceCommitOutputPath);
30619
+ await (0, import_promises6.rename)(inPlaceTempOutputPath, inPlaceCommitOutputPath);
30262
30620
  inPlaceTempDir = null;
30263
30621
  inPlaceTempOutputPath = null;
30264
30622
  outputPath = inPlaceFinalOutputPath;
30265
30623
  if (committedTempDir) {
30266
- await (0, import_promises5.rm)(committedTempDir, { recursive: true, force: true });
30624
+ await (0, import_promises6.rm)(committedTempDir, { recursive: true, force: true });
30267
30625
  }
30268
30626
  if (!exportResult) {
30269
30627
  return null;
@@ -30276,7 +30634,7 @@ function registerEnrichCommand(program) {
30276
30634
  try {
30277
30635
  process.once("SIGINT", onSigint);
30278
30636
  process.once("SIGTERM", onSigterm);
30279
- await (0, import_promises5.writeFile)(tempPlay, playSource, "utf8");
30637
+ await (0, import_promises6.writeFile)(tempPlay, playSource, "utf8");
30280
30638
  if (options.inPlace) {
30281
30639
  await prepareInPlaceOutput();
30282
30640
  }
@@ -30470,11 +30828,11 @@ function registerEnrichCommand(program) {
30470
30828
  process.removeListener("SIGINT", onSigint);
30471
30829
  process.removeListener("SIGTERM", onSigterm);
30472
30830
  if (inPlaceTempDir) {
30473
- await (0, import_promises5.rm)(inPlaceTempDir, { recursive: true, force: true });
30831
+ await (0, import_promises6.rm)(inPlaceTempDir, { recursive: true, force: true });
30474
30832
  } else if (inPlaceTempOutputPath) {
30475
- await (0, import_promises5.rm)(inPlaceTempOutputPath, { force: true });
30833
+ await (0, import_promises6.rm)(inPlaceTempOutputPath, { force: true });
30476
30834
  }
30477
- await (0, import_promises5.rm)(tempDir, { recursive: true, force: true });
30835
+ await (0, import_promises6.rm)(tempDir, { recursive: true, force: true });
30478
30836
  }
30479
30837
  });
30480
30838
  }
@@ -31366,7 +31724,7 @@ Examples:
31366
31724
 
31367
31725
  // src/cli/commands/monitors.ts
31368
31726
  var import_node_fs14 = require("fs");
31369
- var import_promises6 = require("readline/promises");
31727
+ var import_promises7 = require("readline/promises");
31370
31728
  var JSON_OPTION_DESCRIPTION = "Emit JSON output. Also automatic when stdout is piped";
31371
31729
  function withJsonOption(command) {
31372
31730
  return command.option("--json", JSON_OPTION_DESCRIPTION);
@@ -32135,7 +32493,7 @@ async function handleMonitorsValidate(key, options) {
32135
32493
  if (result.valid === false) process.exitCode = 7;
32136
32494
  }
32137
32495
  async function confirmMonitorDelete(key, options) {
32138
- const rl = (0, import_promises6.createInterface)({
32496
+ const rl = (0, import_promises7.createInterface)({
32139
32497
  input: process.stdin,
32140
32498
  output: process.stderr
32141
32499
  });
@@ -36156,7 +36514,7 @@ Examples:
36156
36514
  }
36157
36515
 
36158
36516
  // src/cli/commands/workflow.ts
36159
- var import_promises7 = require("fs/promises");
36517
+ var import_promises8 = require("fs/promises");
36160
36518
  var import_node_path20 = require("path");
36161
36519
 
36162
36520
  // src/cli/workflow-to-play.ts
@@ -36366,7 +36724,7 @@ function readStatus(payload) {
36366
36724
  }
36367
36725
  async function readJsonOption(payload, file) {
36368
36726
  if (file) {
36369
- const raw = await (0, import_promises7.readFile)((0, import_node_path20.resolve)(file), "utf8");
36727
+ const raw = await (0, import_promises8.readFile)((0, import_node_path20.resolve)(file), "utf8");
36370
36728
  return JSON.parse(raw);
36371
36729
  }
36372
36730
  if (payload) {
@@ -36401,8 +36759,8 @@ async function transformOne(api, workflowId, outDir, publish) {
36401
36759
  { workflowName: workflow.name, version: revision.version }
36402
36760
  );
36403
36761
  const file = (0, import_node_path20.join)((0, import_node_path20.resolve)(outDir), `${compiled.playName}.play.ts`);
36404
- await (0, import_promises7.mkdir)((0, import_node_path20.dirname)(file), { recursive: true });
36405
- await (0, import_promises7.writeFile)(file, compiled.sourceCode, "utf8");
36762
+ await (0, import_promises8.mkdir)((0, import_node_path20.dirname)(file), { recursive: true });
36763
+ await (0, import_promises8.writeFile)(file, compiled.sourceCode, "utf8");
36406
36764
  let published = false;
36407
36765
  if (publish) {
36408
36766
  const code = await handlePlayPublish([file]);
@@ -40477,10 +40835,10 @@ function topLevelCommandKnown(program, commandName) {
40477
40835
  );
40478
40836
  }
40479
40837
  async function runPlayRunnerHealthCheck() {
40480
- const dir = await (0, import_promises8.mkdtemp)((0, import_node_path26.join)((0, import_node_os19.tmpdir)(), "deepline-health-play-"));
40838
+ const dir = await (0, import_promises9.mkdtemp)((0, import_node_path26.join)((0, import_node_os19.tmpdir)(), "deepline-health-play-"));
40481
40839
  const file = (0, import_node_path26.join)(dir, "health-check.play.ts");
40482
40840
  try {
40483
- await (0, import_promises8.writeFile)(
40841
+ await (0, import_promises9.writeFile)(
40484
40842
  file,
40485
40843
  [
40486
40844
  "import { definePlay } from 'deepline';",
@@ -40529,7 +40887,7 @@ async function runPlayRunnerHealthCheck() {
40529
40887
  }
40530
40888
  };
40531
40889
  } finally {
40532
- await (0, import_promises8.rm)(dir, { recursive: true, force: true });
40890
+ await (0, import_promises9.rm)(dir, { recursive: true, force: true });
40533
40891
  }
40534
40892
  }
40535
40893
  function pickString(value, ...keys) {