deepline 0.1.119 → 0.1.121

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 (148) hide show
  1. package/README.md +4 -0
  2. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/README.md +21 -0
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +185 -0
  4. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-batch.ts +107 -0
  5. package/dist/{repo → bundling-sources}/sdk/src/client.ts +116 -12
  6. package/dist/bundling-sources/sdk/src/compat.ts +191 -0
  7. package/dist/bundling-sources/sdk/src/gtm.ts +146 -0
  8. package/dist/bundling-sources/sdk/src/helpers.ts +12 -0
  9. package/dist/{repo → bundling-sources}/sdk/src/index.ts +2 -1
  10. package/dist/{repo → bundling-sources}/sdk/src/play.ts +3 -1
  11. package/dist/{repo → bundling-sources}/sdk/src/plays/bundle-play-file.ts +17 -5
  12. package/dist/{repo → bundling-sources}/sdk/src/release.ts +2 -2
  13. package/dist/{repo → bundling-sources}/sdk/src/runs/observe-transport.ts +2 -3
  14. package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +3 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +838 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5510 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +261 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +828 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/dataset-id.ts +10 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/daytona-runtime-config.ts +50 -0
  21. package/dist/bundling-sources/shared_libs/play-runtime/durability-store.ts +20 -0
  22. package/dist/bundling-sources/shared_libs/play-runtime/event-wait-tools.ts +9 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +171 -0
  24. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-diagnosis.ts +321 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-target.ts +158 -0
  26. package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +34 -0
  27. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +34 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +50 -0
  29. package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +119 -0
  30. package/dist/{repo → bundling-sources}/shared_libs/play-runtime/map-row-identity.ts +1 -1
  31. package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +636 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/postgres-json.ts +9 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/progress-emitter.ts +197 -0
  34. package/dist/bundling-sources/shared_libs/play-runtime/projection.ts +262 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +143 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/public-play-contract.ts +42 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +40 -0
  38. package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +178 -0
  39. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +4015 -0
  40. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constraints.ts +2 -0
  41. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +238 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-pg.ts +53 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +149 -0
  44. package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +68 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/tool-batch-executor.ts +149 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +159 -0
  47. package/dist/bundling-sources/shared_libs/play-runtime/tracing.ts +33 -0
  48. package/dist/bundling-sources/shared_libs/play-runtime/waterfall-replay.ts +79 -0
  49. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +139 -0
  50. package/dist/bundling-sources/shared_libs/plays/artifact-transport.ts +14 -0
  51. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +49 -0
  52. package/dist/bundling-sources/shared_libs/plays/compiler-manifest.ts +41 -0
  53. package/dist/bundling-sources/shared_libs/plays/dataset-summary.ts +163 -0
  54. package/dist/bundling-sources/shared_libs/plays/definition.ts +267 -0
  55. package/dist/bundling-sources/shared_libs/plays/file-refs.ts +11 -0
  56. package/dist/bundling-sources/shared_libs/plays/input-contract.ts +146 -0
  57. package/dist/bundling-sources/shared_libs/plays/resolve-static-pipeline.ts +190 -0
  58. package/dist/bundling-sources/shared_libs/plays/runtime-validation.ts +417 -0
  59. package/dist/bundling-sources/shared_libs/plays/tool-codegen.ts +142 -0
  60. package/dist/bundling-sources/shared_libs/security/safe-outbound-fetch.ts +274 -0
  61. package/dist/bundling-sources/shared_libs/temporal/preview-config.ts +150 -0
  62. package/dist/cli/index.js +811 -2207
  63. package/dist/cli/index.mjs +847 -2258
  64. package/dist/compiler-manifest-BjoRENv9.d.mts +227 -0
  65. package/dist/compiler-manifest-BjoRENv9.d.ts +227 -0
  66. package/dist/index.d.mts +8 -231
  67. package/dist/index.d.ts +8 -231
  68. package/dist/index.js +101 -15
  69. package/dist/index.mjs +101 -15
  70. package/dist/plays/bundle-play-file.d.mts +120 -0
  71. package/dist/plays/bundle-play-file.d.ts +120 -0
  72. package/dist/plays/bundle-play-file.mjs +1830 -0
  73. package/package.json +4 -9
  74. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-await.ts +0 -0
  75. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-submit.ts +0 -0
  76. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/coordinator-entry.ts +0 -0
  77. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/dedup-do.ts +0 -0
  78. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/entry.ts +0 -0
  79. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/csv-rows.ts +0 -0
  80. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/dataset-handles.ts +0 -0
  81. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +0 -0
  82. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/live-progress.ts +0 -0
  83. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +0 -0
  84. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/receipts.ts +0 -0
  85. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/row-isolation.ts +0 -0
  86. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/tool-http-errors.ts +0 -0
  87. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-instance-create.ts +0 -0
  88. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry-state.ts +0 -0
  89. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry.ts +0 -0
  90. /package/dist/{repo → bundling-sources}/sdk/src/agent-runtime.ts +0 -0
  91. /package/dist/{repo → bundling-sources}/sdk/src/config.ts +0 -0
  92. /package/dist/{repo → bundling-sources}/sdk/src/errors.ts +0 -0
  93. /package/dist/{repo → bundling-sources}/sdk/src/http.ts +0 -0
  94. /package/dist/{repo → bundling-sources}/sdk/src/plays/harness-stub.ts +0 -0
  95. /package/dist/{repo → bundling-sources}/sdk/src/plays/local-file-discovery.ts +0 -0
  96. /package/dist/{repo → bundling-sources}/sdk/src/stream-reconnect.ts +0 -0
  97. /package/dist/{repo → bundling-sources}/sdk/src/tool-output.ts +0 -0
  98. /package/dist/{repo → bundling-sources}/sdk/src/types.ts +0 -0
  99. /package/dist/{repo → bundling-sources}/sdk/src/version.ts +0 -0
  100. /package/dist/{repo → bundling-sources}/sdk/src/worker-play-entry.ts +0 -0
  101. /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/cell-policy.ts +0 -0
  102. /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/column-names.ts +0 -0
  103. /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/sheet-contract.ts +0 -0
  104. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/backend.ts +0 -0
  105. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batch-runtime.ts +0 -0
  106. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batching-types.ts +0 -0
  107. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/cell-staleness.ts +0 -0
  108. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/coordinator-headers.ts +0 -0
  109. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/csv-rename.ts +0 -0
  110. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-crypto.ts +0 -0
  111. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-plan.ts +0 -0
  112. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session.ts +0 -0
  113. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/dedup-backend.ts +0 -0
  114. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/default-batch-strategies.ts +0 -0
  115. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/email-status.ts +0 -0
  116. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/execution-plan.ts +0 -0
  117. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/extractor-targets.ts +0 -0
  118. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/fullenrich-batching.ts +0 -0
  119. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/coordinator-rate-state-backend.ts +0 -0
  120. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/governor.ts +0 -0
  121. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/policy.ts +0 -0
  122. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/rate-state-backend.ts +0 -0
  123. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/live-events.ts +0 -0
  124. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/play-runtime-batching-registry.ts +0 -0
  125. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/profiles.ts +0 -0
  126. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/providers.ts +0 -0
  127. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-failure.ts +0 -0
  128. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-ledger.ts +0 -0
  129. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-snapshot-stream.ts +0 -0
  130. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/scheduler-backend.ts +0 -0
  131. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-capability.ts +0 -0
  132. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-redaction.ts +0 -0
  133. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-lifecycle-tracker.ts +0 -0
  134. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-program-dataset-builder.ts +0 -0
  135. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/submit-limits.ts +0 -0
  136. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/tool-result.ts +0 -0
  137. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/work-receipts.ts +0 -0
  138. /package/dist/{repo → bundling-sources}/shared_libs/plays/bootstrap-routes.ts +0 -0
  139. /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/index.ts +0 -0
  140. /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/limits.ts +0 -0
  141. /package/dist/{repo → bundling-sources}/shared_libs/plays/contracts.ts +0 -0
  142. /package/dist/{repo → bundling-sources}/shared_libs/plays/dataset.ts +0 -0
  143. /package/dist/{repo → bundling-sources}/shared_libs/plays/row-identity.ts +0 -0
  144. /package/dist/{repo → bundling-sources}/shared_libs/plays/secret-guardrails.ts +0 -0
  145. /package/dist/{repo → bundling-sources}/shared_libs/plays/static-pipeline.ts +0 -0
  146. /package/dist/{repo → bundling-sources}/shared_libs/security/outbound-url-policy.ts +0 -0
  147. /package/dist/{repo → bundling-sources}/shared_libs/security/safe-fetch.ts +0 -0
  148. /package/dist/{repo → bundling-sources}/shared_libs/temporal/constants.ts +0 -0
@@ -158,9 +158,9 @@ function configureProxyFromEnv() {
158
158
  configureProxyFromEnv();
159
159
 
160
160
  // src/cli/index.ts
161
- import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile6 } from "fs/promises";
162
- import { join as join17 } from "path";
163
- import { tmpdir as tmpdir5 } from "os";
161
+ import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile5 } from "fs/promises";
162
+ import { join as join14 } from "path";
163
+ import { tmpdir as tmpdir3 } from "os";
164
164
  import { Command as Command3 } from "commander";
165
165
 
166
166
  // src/config.ts
@@ -380,10 +380,10 @@ var SDK_RELEASE = {
380
380
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
381
381
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
382
382
  // the SDK enrich generator's one-second stale policy.
383
- version: "0.1.119",
383
+ version: "0.1.121",
384
384
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
385
385
  supportPolicy: {
386
- latest: "0.1.119",
386
+ latest: "0.1.121",
387
387
  minimumSupported: "0.1.53",
388
388
  deprecatedBelow: "0.1.53",
389
389
  commandMinimumSupported: [
@@ -896,7 +896,7 @@ function decodeSseFrame(frame) {
896
896
  return parsed;
897
897
  }
898
898
  function sleep(ms) {
899
- return new Promise((resolve16) => setTimeout(resolve16, ms));
899
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
900
900
  }
901
901
  function withCoworkNetworkHint(message) {
902
902
  if (!isCoworkLikeSandbox() || message.includes(COWORK_NETWORK_HINT)) {
@@ -1653,14 +1653,14 @@ async function* observeRunEvents(options) {
1653
1653
  try {
1654
1654
  for (; ; ) {
1655
1655
  if (queue.length === 0) {
1656
- const waitForItem = new Promise((resolve16) => {
1657
- wake = resolve16;
1656
+ const waitForItem = new Promise((resolve13) => {
1657
+ wake = resolve13;
1658
1658
  });
1659
1659
  if (!sawFirstSnapshot) {
1660
1660
  const timedOut = await Promise.race([
1661
1661
  waitForItem.then(() => false),
1662
1662
  new Promise(
1663
- (resolve16) => setTimeout(() => resolve16(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
1663
+ (resolve13) => setTimeout(() => resolve13(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
1664
1664
  )
1665
1665
  ]);
1666
1666
  if (timedOut && queue.length === 0) {
@@ -1760,7 +1760,7 @@ var REGISTER_PLAY_ARTIFACTS_COMPILE_CONCURRENCY = 3;
1760
1760
  var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_COUNT = 3;
1761
1761
  var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_BYTES = 25e5;
1762
1762
  function sleep2(ms) {
1763
- return new Promise((resolve16) => setTimeout(resolve16, ms));
1763
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
1764
1764
  }
1765
1765
  function isTransientCompileManifestError(error) {
1766
1766
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -2877,20 +2877,105 @@ var DeeplineClient = class {
2877
2877
  return response.runs ?? [];
2878
2878
  }
2879
2879
  /**
2880
- * Observe one run's live events through the Convex Run Snapshot
2881
- * subscription transport (ADR-0008). Yields the same `play.*` event
2882
- * envelopes as {@link streamPlayRunEvents} and ends after the terminal
2883
- * snapshot. Throws {@link RunObserveTransportUnavailableError} when this
2884
- * server cannot serve the transport (older server, unconfigured grants, or
2885
- * unreachable Convex) — callers fall back to the SSE stream with a notice.
2880
+ * Observe one run's live events. Uses the Convex Run Snapshot subscription
2881
+ * transport first (ADR-0008), then falls back to the canonical SSE stream
2882
+ * when the subscription transport or its optional client modules are not
2883
+ * available. Pass `fallback: 'none'` to receive
2884
+ * {@link RunObserveTransportUnavailableError} instead.
2886
2885
  */
2887
- observeRunEvents(runId, options) {
2888
- return observeRunEvents({
2889
- http: this.http,
2886
+ async *observeRunEvents(runId, options) {
2887
+ let yieldedObserveEvent = false;
2888
+ try {
2889
+ for await (const event of observeRunEvents({
2890
+ http: this.http,
2891
+ runId,
2892
+ signal: options?.signal,
2893
+ onNotice: options?.onNotice
2894
+ })) {
2895
+ yieldedObserveEvent = true;
2896
+ yield event;
2897
+ }
2898
+ } catch (error) {
2899
+ if (!(error instanceof RunObserveTransportUnavailableError) || yieldedObserveEvent || options?.fallback === "none") {
2900
+ throw error;
2901
+ }
2902
+ options?.onNotice?.(
2903
+ `[observe] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
2904
+ );
2905
+ yield* this.streamPlayRunEventsUntilTerminal(runId, options);
2906
+ }
2907
+ }
2908
+ async *streamPlayRunEventsUntilTerminal(runId, options) {
2909
+ const state = {
2890
2910
  runId,
2891
- signal: options?.signal,
2892
- onNotice: options?.onNotice
2893
- });
2911
+ status: "running",
2912
+ logs: [],
2913
+ lastLogSeq: 0,
2914
+ latest: null
2915
+ };
2916
+ let lastEventId;
2917
+ let reconnectAttempt = 0;
2918
+ for (; ; ) {
2919
+ if (options?.signal?.aborted) {
2920
+ return;
2921
+ }
2922
+ const connectedAt = Date.now();
2923
+ let sawEvent = false;
2924
+ let endedReason = "stream window ended before a terminal event";
2925
+ try {
2926
+ for await (const event of this.streamPlayRunEvents(runId, {
2927
+ mode: "cli",
2928
+ signal: options?.signal,
2929
+ ...lastEventId ? { lastEventId } : {}
2930
+ })) {
2931
+ sawEvent = true;
2932
+ if (event.cursor?.trim()) {
2933
+ lastEventId = event.cursor;
2934
+ }
2935
+ yield event;
2936
+ const status = updatePlayLiveStatusState(state, event);
2937
+ if (status && TERMINAL_PLAY_STATUSES.has(status.status)) {
2938
+ return;
2939
+ }
2940
+ }
2941
+ } catch (error) {
2942
+ if (options?.signal?.aborted) {
2943
+ return;
2944
+ }
2945
+ if (!isTransientPlayStreamError(error)) {
2946
+ throw error;
2947
+ }
2948
+ endedReason = error instanceof Error ? error.message : String(error);
2949
+ }
2950
+ let refreshed = null;
2951
+ try {
2952
+ refreshed = await this.getRunStatus(runId);
2953
+ } catch (error) {
2954
+ if (!isTransientPlayStreamError(error)) {
2955
+ throw error;
2956
+ }
2957
+ }
2958
+ if (refreshed && TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
2959
+ yield {
2960
+ cursor: String(Date.now()),
2961
+ streamId: `sse-fallback:${runId}`,
2962
+ scope: "play",
2963
+ type: "play.run.status",
2964
+ at: (/* @__PURE__ */ new Date()).toISOString(),
2965
+ payload: refreshed
2966
+ };
2967
+ return;
2968
+ }
2969
+ if (sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
2970
+ reconnectAttempt = 0;
2971
+ }
2972
+ const delayMs = streamReconnectDelayMs(reconnectAttempt);
2973
+ reconnectAttempt += 1;
2974
+ options?.onNotice?.(
2975
+ `[observe] SSE tail window ended before terminal status (${endedReason}); reconnecting to run ${runId}`
2976
+ );
2977
+ await sleep2(delayMs);
2978
+ }
2894
2979
  }
2895
2980
  /**
2896
2981
  * Tail one run through the subscription transport until terminal, then
@@ -2906,7 +2991,8 @@ var DeeplineClient = class {
2906
2991
  };
2907
2992
  for await (const event of this.observeRunEvents(runId, {
2908
2993
  signal: options?.signal,
2909
- onNotice: options?.onNotice
2994
+ onNotice: options?.onNotice,
2995
+ fallback: "none"
2910
2996
  })) {
2911
2997
  const status = updatePlayLiveStatusState(state, event);
2912
2998
  if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
@@ -4210,7 +4296,7 @@ function buildCandidateUrls2(url) {
4210
4296
  }
4211
4297
  }
4212
4298
  function sleep4(ms) {
4213
- return new Promise((resolve16) => setTimeout(resolve16, ms));
4299
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
4214
4300
  }
4215
4301
  function printDeeplineLogo() {
4216
4302
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -4245,10 +4331,8 @@ async function claimInstallBonus(baseUrl, apiKey) {
4245
4331
  apiKey,
4246
4332
  {}
4247
4333
  );
4248
- if (status !== 200) {
4249
- return;
4250
- }
4251
- const granted = Number(data.credits_granted ?? 0);
4334
+ if (status !== 200) return;
4335
+ const granted = typeof data.credits_granted === "number" ? data.credits_granted : 0;
4252
4336
  const alreadyGranted = data.already_granted === true;
4253
4337
  if (granted > 0) {
4254
4338
  console.log(`
@@ -6162,38 +6246,38 @@ function buildDatasetStats(rows, totalRows = rows.length, columns = inferColumns
6162
6246
  }
6163
6247
  }
6164
6248
  const denominator = nonEmpty + empty;
6165
- const stat4 = {
6249
+ const stat2 = {
6166
6250
  non_empty: percentText(nonEmpty, denominator),
6167
6251
  unique: valueCounts.size
6168
6252
  };
6169
6253
  const rawExecutionStats = executionStats?.columnStats[column];
6170
6254
  if (rawExecutionStats) {
6171
- stat4.execution = formatDatasetExecutionStats(
6255
+ stat2.execution = formatDatasetExecutionStats(
6172
6256
  rawExecutionStats,
6173
6257
  totalRows
6174
6258
  );
6175
6259
  }
6176
6260
  if (sampleValue !== void 0 && sampleValueType) {
6177
- stat4.sample_value = sampleValue;
6178
- stat4.sample_type = sampleValueType;
6261
+ stat2.sample_value = sampleValue;
6262
+ stat2.sample_type = sampleValueType;
6179
6263
  }
6180
6264
  if (valueCounts.size > 0 && valueCounts.size < nonEmpty) {
6181
6265
  const top = [...valueCounts.entries()].sort((left, right) => right[1] - left[1]).slice(0, 3);
6182
6266
  const topKeys = new Set(top.map(([key]) => key));
6183
6267
  const otherCount = [...valueCounts.entries()].filter(([key]) => !topKeys.has(key)).reduce((sum, [, count]) => sum + count, 0);
6184
- stat4.top_values = Object.fromEntries(
6268
+ stat2.top_values = Object.fromEntries(
6185
6269
  top.map(([key, count]) => [key, countPercentText(count, denominator)])
6186
6270
  );
6187
6271
  if (otherCount > 0) {
6188
- stat4.top_values["(other)"] = countPercentText(otherCount, denominator);
6272
+ stat2.top_values["(other)"] = countPercentText(otherCount, denominator);
6189
6273
  }
6190
6274
  if (empty > 0) {
6191
- stat4.top_values["(null)"] = countPercentText(empty, denominator);
6275
+ stat2.top_values["(null)"] = countPercentText(empty, denominator);
6192
6276
  }
6193
6277
  } else if (empty > 0 && nonEmpty > 0) {
6194
- stat4.top_values = { "(null)": countPercentText(empty, denominator) };
6278
+ stat2.top_values = { "(null)": countPercentText(empty, denominator) };
6195
6279
  }
6196
- columnStats[column] = stat4;
6280
+ columnStats[column] = stat2;
6197
6281
  }
6198
6282
  return {
6199
6283
  total_rows: totalRows,
@@ -6679,1938 +6763,123 @@ Examples:
6679
6763
 
6680
6764
  // src/cli/commands/enrich.ts
6681
6765
  import {
6682
- mkdir as mkdir4,
6766
+ mkdir as mkdir3,
6683
6767
  mkdtemp,
6684
- readFile as readFile3,
6768
+ readFile,
6685
6769
  rm,
6686
- stat as stat3,
6687
- writeFile as writeFile4
6770
+ stat,
6771
+ writeFile as writeFile3
6688
6772
  } from "fs/promises";
6689
- import { homedir as homedir6, tmpdir as tmpdir3 } from "os";
6690
- import { join as join9, resolve as resolve11 } from "path";
6773
+ import { homedir as homedir6, tmpdir } from "os";
6774
+ import { join as join6, resolve as resolve8 } from "path";
6691
6775
 
6692
6776
  // src/cli/commands/play.ts
6693
- import { createHash as createHash3 } from "crypto";
6777
+ import { createHash } from "crypto";
6694
6778
  import {
6695
- existsSync as existsSync8,
6696
- readFileSync as readFileSync7,
6779
+ existsSync as existsSync6,
6780
+ readFileSync as readFileSync6,
6697
6781
  readdirSync,
6698
6782
  realpathSync,
6699
6783
  statSync as statSync2,
6700
6784
  writeFileSync as writeFileSync8
6701
6785
  } from "fs";
6702
- import { basename as basename3, dirname as dirname9, join as join8, resolve as resolve10 } from "path";
6786
+ import { basename, dirname as dirname6, join as join5, resolve as resolve7 } from "path";
6703
6787
  import { parse as parseCsvSync2 } from "csv-parse/sync";
6704
6788
 
6705
- // src/plays/bundle-play-file.ts
6706
- import { tmpdir as tmpdir2 } from "os";
6707
- import { dirname as dirname8, join as join7, resolve as resolve8 } from "path";
6708
- import { fileURLToPath } from "url";
6709
- import { existsSync as existsSync7 } from "fs";
6710
-
6711
- // ../shared_libs/plays/bundling/index.ts
6712
- import { createHash } from "crypto";
6713
- import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
6714
- import { mkdir as mkdir3, readFile, realpath, stat, writeFile as writeFile3 } from "fs/promises";
6715
- import { tmpdir } from "os";
6716
- import {
6717
- basename,
6718
- dirname as dirname6,
6719
- extname,
6720
- isAbsolute,
6721
- join as join5,
6722
- relative,
6723
- resolve as resolve6
6724
- } from "path";
6725
- import { builtinModules } from "module";
6726
- import { build } from "esbuild";
6789
+ // src/cli/commands/plays/bootstrap.ts
6790
+ import { closeSync, openSync, readSync, statSync, writeFileSync as writeFileSync7 } from "fs";
6791
+ import { isAbsolute, relative, resolve as resolve6 } from "path";
6792
+ import { parse as parseCsvSync } from "csv-parse/sync";
6727
6793
 
6728
- // ../shared_libs/play-runtime/backend.ts
6729
- var PLAY_RUNTIME_BACKENDS = {
6730
- localProcess: "local_process",
6731
- daytona: "daytona",
6732
- // Artifact/runtime contract for Cloudflare Dynamic Workers. This is no
6733
- // longer a standalone runner backend; use profile=workers_edge so the
6734
- // cf-workflows scheduler owns loading and execution.
6735
- cloudflareWorkers: "cloudflare_workers"
6736
- };
6737
- var PLAY_ARTIFACT_KINDS = {
6738
- cjsNode20: "cjs_node20",
6739
- esmWorkers: "esm_workers"
6794
+ // ../shared_libs/plays/bootstrap-routes.ts
6795
+ var PLAY_BOOTSTRAP_TEMPLATES = [
6796
+ "people-list",
6797
+ "company-list",
6798
+ "people-email",
6799
+ "people-phone",
6800
+ "company-people",
6801
+ "company-people-email",
6802
+ "company-people-phone"
6803
+ ];
6804
+ var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
6805
+ var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
6806
+ var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
6807
+ email_finder: "email_finder",
6808
+ phone_finder: "phone_finder"
6740
6809
  };
6741
- var PLAY_BACKEND_DESCRIPTORS = {
6742
- [PLAY_RUNTIME_BACKENDS.localProcess]: {
6743
- id: PLAY_RUNTIME_BACKENDS.localProcess,
6744
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
6745
- label: "Local node subprocess"
6746
- },
6747
- [PLAY_RUNTIME_BACKENDS.daytona]: {
6748
- id: PLAY_RUNTIME_BACKENDS.daytona,
6749
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
6750
- label: "Daytona sandbox"
6751
- },
6752
- [PLAY_RUNTIME_BACKENDS.cloudflareWorkers]: {
6753
- id: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
6754
- artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
6755
- label: "Cloudflare Dynamic Workers"
6756
- }
6810
+ var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
6811
+ email_finder: "email",
6812
+ phone_finder: "phone"
6757
6813
  };
6758
-
6759
- // ../shared_libs/plays/contracts.ts
6760
- var PLAY_PUBLIC_API_VERSION = 1;
6761
- var PLAY_ARTIFACT_VERSION = 1;
6762
- var PLAY_MIN_RUNNER_VERSION = 1;
6763
- var PLAY_RUNTIME_FEATURES = [
6764
- "artifact_storage",
6765
- "checkpoint_resume",
6766
- "durable_sleep",
6767
- "packaged_files"
6768
- ];
6769
- function buildPlayContractCompatibility(input2) {
6770
- return {
6771
- apiVersion: PLAY_PUBLIC_API_VERSION,
6772
- artifactVersion: PLAY_ARTIFACT_VERSION,
6773
- minRunnerVersion: PLAY_MIN_RUNNER_VERSION,
6774
- runtimeFeatures: [...PLAY_RUNTIME_FEATURES],
6775
- runtimeBackend: input2?.runtimeBackend ?? null
6776
- };
6777
- }
6778
-
6779
- // ../shared_libs/plays/secret-guardrails.ts
6780
- var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
6781
- var PRIVATE_KEY_PATTERN = /-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/;
6782
- var BEARER_LITERAL_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/i;
6783
- var ASSIGNMENT_SECRET_LITERAL_PATTERN = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*['"][^'"]{12,}['"]/i;
6784
- var HIGH_ENTROPY_LITERAL_PATTERN = /['"]([A-Za-z0-9+/=_-]{32,})['"]/g;
6785
- function shannonEntropy(value) {
6786
- const counts = /* @__PURE__ */ new Map();
6787
- for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
6788
- return [...counts.values()].reduce((entropy, count) => {
6789
- const p = count / value.length;
6790
- return entropy - p * Math.log2(p);
6791
- }, 0);
6792
- }
6793
- function collectInlineSecretFindings(sourceCode) {
6794
- const findings = [];
6795
- for (const match of sourceCode.matchAll(SECRET_ENV_PATTERN)) {
6796
- findings.push(`process.env.${match[1]}`);
6797
- }
6798
- if (PRIVATE_KEY_PATTERN.test(sourceCode)) findings.push("private key block");
6799
- if (BEARER_LITERAL_PATTERN.test(sourceCode))
6800
- findings.push("bearer token literal");
6801
- if (ASSIGNMENT_SECRET_LITERAL_PATTERN.test(sourceCode)) {
6802
- findings.push("secret-looking assignment literal");
6803
- }
6804
- for (const match of sourceCode.matchAll(HIGH_ENTROPY_LITERAL_PATTERN)) {
6805
- const literal = match[1] ?? "";
6806
- if (literal.length >= 40 && shannonEntropy(literal) >= 4.2) {
6807
- findings.push("high-entropy string literal");
6808
- break;
6809
- }
6810
- }
6811
- return [...new Set(findings)];
6812
- }
6813
- function validatePlaySourceHasNoInlineSecrets(input2) {
6814
- const findings = collectInlineSecretFindings(input2.sourceCode);
6815
- if (!findings.length) return;
6816
- throw new Error(
6817
- [
6818
- `Play source ${input2.filePath} appears to contain inline secret material: ${[
6819
- ...new Set(findings)
6820
- ].join(", ")}.`,
6821
- 'Author secrets in the dashboard and use ctx.secrets.get("NAME") with an approved helper such as ctx.secrets.bearer(handle).'
6822
- ].join(" ")
6823
- );
6814
+ function isPlayBootstrapTemplate(value) {
6815
+ return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
6824
6816
  }
6825
- function validatePlaySourceFilesHaveNoInlineSecrets(sourceFiles) {
6826
- for (const [filePath, sourceCode] of Object.entries(sourceFiles)) {
6827
- validatePlaySourceHasNoInlineSecrets({ filePath, sourceCode });
6828
- }
6817
+ function formatPlayBootstrapTemplates() {
6818
+ return PLAY_BOOTSTRAP_TEMPLATES.join("|");
6829
6819
  }
6830
6820
 
6831
- // ../shared_libs/plays/bundling/limits.ts
6832
- var MAX_PLAY_BUNDLE_BYTES = 30 * 1024 * 1024;
6833
- var MAX_ESM_WORKERS_BUNDLE_BYTES = 115e4;
6834
-
6835
- // ../shared_libs/plays/bundling/index.ts
6836
- var PLAY_BUNDLE_CACHE_VERSION = 24;
6837
- var PLAY_ARTIFACT_CACHE_DIR = join5(
6838
- tmpdir(),
6839
- `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION}`
6840
- );
6841
- var PLAY_PROXY_NAMESPACE = "deepline-play-runtime-ref";
6842
- var SOURCE_EXTENSIONS = [
6843
- ".ts",
6844
- ".tsx",
6845
- ".mts",
6846
- ".cts",
6847
- ".js",
6848
- ".jsx",
6849
- ".mjs",
6850
- ".cjs",
6851
- ".json"
6852
- ];
6853
- var WORKERS_PLAY_ENTRY_VIRTUAL = "deepline-play-entry";
6854
- var PLAY_SOURCE_FILE_PATTERN = /\.play\.(?:[cm]?[jt]sx?)$/i;
6855
- var NODE_BUILTIN_SET = new Set(
6856
- builtinModules.flatMap(
6857
- (name) => name.startsWith("node:") ? [name, name.slice(5)] : [name, `node:${name}`]
6858
- )
6859
- );
6860
- function assertValidExportName(exportName) {
6861
- if (exportName === "default") return;
6862
- if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(exportName)) {
6863
- throw new Error(
6864
- `Invalid play export name "${exportName}". Named prebuilt exports must be valid JavaScript identifiers.`
6865
- );
6866
- }
6867
- }
6868
- function sha256(value) {
6869
- return createHash("sha256").update(value).digest("hex");
6870
- }
6871
- function formatEsbuildMessage(message) {
6872
- const location = message.location ? `${message.location.file}:${message.location.line}:${message.location.column}` : null;
6873
- return location ? `${location} ${message.text}` : message.text;
6874
- }
6875
- function isLocalSpecifier(specifier) {
6876
- return specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/") || specifier.startsWith("file:");
6877
- }
6878
- async function normalizeLocalPath(filePath) {
6879
- try {
6880
- return await realpath(filePath);
6881
- } catch {
6882
- return resolve6(filePath);
6821
+ // src/cli/commands/plays/bootstrap.ts
6822
+ function parseReferencedPlayTarget(target) {
6823
+ const trimmed = target.trim();
6824
+ const slashIndex = trimmed.indexOf("/");
6825
+ if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
6826
+ return { ownerSlug: null, playName: trimmed, unqualifiedPlayName: trimmed };
6883
6827
  }
6884
- }
6885
- function createPlayWorkspace(entryFile) {
6886
6828
  return {
6887
- entryFile,
6888
- rootDir: dirname6(entryFile)
6829
+ ownerSlug: trimmed.slice(0, slashIndex),
6830
+ playName: trimmed,
6831
+ unqualifiedPlayName: trimmed.slice(slashIndex + 1)
6889
6832
  };
6890
6833
  }
6891
- function isPathInsideDirectory(filePath, directory) {
6892
- return filePath === directory || filePath.startsWith(`${directory}/`);
6893
- }
6894
- function assertWithinPlayWorkspace(input2) {
6895
- if (isPathInsideDirectory(input2.resolvedPath, input2.workspace.rootDir)) {
6896
- return;
6834
+ function parsePositiveInteger2(value, flagName) {
6835
+ const parsed = Number.parseInt(value, 10);
6836
+ if (!Number.isFinite(parsed) || parsed <= 0) {
6837
+ throw new PlayBootstrapUsageError(
6838
+ `${flagName} must be a positive integer.`
6839
+ );
6897
6840
  }
6898
- throw new Error(
6899
- `${input2.importer}:${input2.line}:${input2.column} Local play imports must stay inside the play workspace (${input2.workspace.rootDir}). Import "${input2.specifier}" resolved to ${input2.resolvedPath}, which crosses into app/backend code. Use the public SDK/API surface or move shared helpers into the play workspace.`
6900
- );
6841
+ return parsed;
6901
6842
  }
6902
- function getPackageName(specifier) {
6903
- if (specifier.startsWith("@")) {
6904
- const [scope, name] = specifier.split("/");
6905
- return scope && name ? `${scope}/${name}` : specifier;
6906
- }
6907
- return specifier.split("/")[0] ?? specifier;
6843
+ function isRecord5(value) {
6844
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
6908
6845
  }
6909
- function isPlaySourceFile(filePath) {
6910
- return PLAY_SOURCE_FILE_PATTERN.test(filePath);
6846
+ function stringValue(value) {
6847
+ return typeof value === "string" ? value.trim() : "";
6911
6848
  }
6912
- function stripCommentsToSpaces(source) {
6913
- return source.replace(/\/\*[\s\S]*?\*\//g, (match) => match.replace(/[^\n]/g, " ")).replace(
6914
- /(^|[^:])\/\/.*$/gm,
6915
- (match, prefix) => prefix + " ".repeat(Math.max(0, match.length - prefix.length))
6849
+ function extractionEntries(value) {
6850
+ if (Array.isArray(value)) return value.filter(isRecord5);
6851
+ if (!isRecord5(value)) return [];
6852
+ return Object.entries(value).map(
6853
+ ([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
6916
6854
  );
6917
6855
  }
6918
- function lineAndColumnAt(source, index) {
6919
- const prefix = source.slice(0, index);
6920
- const lines = prefix.split("\n");
6921
- return { line: lines.length, column: lines[lines.length - 1].length + 1 };
6922
- }
6923
- function findSourceImportReferences(sourceCode) {
6924
- const source = stripCommentsToSpaces(sourceCode);
6925
- const references = [];
6926
- const addReference = (specifier, specifierIndex, kind) => {
6927
- if (!specifier) return;
6928
- const position = lineAndColumnAt(sourceCode, specifierIndex);
6929
- references.push({
6930
- specifier,
6931
- line: position.line,
6932
- column: position.column,
6933
- kind
6934
- });
6935
- };
6936
- const staticImportPattern = /\b(?:import|export)\s+(?!type\b)(?:[\s\S]*?\s+from\s*)?(['"])([^'"\n]+)\1/g;
6937
- for (const match of source.matchAll(staticImportPattern)) {
6938
- addReference(
6939
- match[2],
6940
- match.index + match[0].lastIndexOf(match[1]),
6941
- "static"
6942
- );
6943
- }
6944
- const dynamicImportPattern = /\bimport\s*\(\s*(['"])([^'"\n]+)\1/g;
6945
- for (const match of source.matchAll(dynamicImportPattern)) {
6946
- addReference(
6947
- match[2],
6948
- match.index + match[0].lastIndexOf(match[1]),
6949
- "dynamic-import"
6950
- );
6951
- }
6952
- const requirePattern = /\brequire\s*\(\s*(['"])([^'"\n]+)\1/g;
6953
- for (const match of source.matchAll(requirePattern)) {
6954
- addReference(
6955
- match[2],
6956
- match.index + match[0].lastIndexOf(match[1]),
6957
- "require"
6958
- );
6856
+ var PlayBootstrapError = class extends Error {
6857
+ constructor(message, exitCode) {
6858
+ super(message);
6859
+ this.exitCode = exitCode;
6959
6860
  }
6960
- const literalDynamicImportIndexes = new Set(
6961
- [...source.matchAll(dynamicImportPattern)].map((match) => match.index)
6962
- );
6963
- for (const match of source.matchAll(/\bimport\s*\(/g)) {
6964
- if (literalDynamicImportIndexes.has(match.index)) continue;
6965
- const position = lineAndColumnAt(sourceCode, match.index);
6966
- throw new Error(
6967
- `:${position.line}:${position.column} Dynamic import() is not allowed in plays. Use static imports instead.`
6968
- );
6861
+ exitCode;
6862
+ };
6863
+ var PlayBootstrapUsageError = class extends PlayBootstrapError {
6864
+ constructor(message) {
6865
+ super(message, 2);
6969
6866
  }
6970
- const literalRequireIndexes = new Set(
6971
- [...source.matchAll(requirePattern)].map((match) => match.index)
6972
- );
6973
- for (const match of source.matchAll(/\brequire\s*\(/g)) {
6974
- if (literalRequireIndexes.has(match.index)) continue;
6975
- const position = lineAndColumnAt(sourceCode, match.index);
6976
- throw new Error(
6977
- `:${position.line}:${position.column} Dynamic require() is not allowed in plays. Use static imports or require("literal") only.`
6978
- );
6867
+ };
6868
+ var PlayBootstrapValidationError = class extends PlayBootstrapError {
6869
+ constructor(message) {
6870
+ super(message, 7);
6979
6871
  }
6980
- return references.sort(
6981
- (left, right) => left.line === right.line ? left.column - right.column : left.line - right.line
6982
- );
6872
+ };
6873
+ var CSV_HEADER_SAMPLE_BYTES = 64 * 1024;
6874
+ function parseCsvList(value) {
6875
+ return value.split(",").map((item) => item.trim()).filter(Boolean);
6983
6876
  }
6984
- function unquoteStringLiteral(literal) {
6985
- const trimmed = literal.trim();
6986
- const quote = trimmed[0];
6987
- if (quote !== '"' && quote !== "'" || trimmed[trimmed.length - 1] !== quote) {
6988
- return null;
6989
- }
6990
- try {
6991
- return JSON.parse(
6992
- quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
6993
- );
6994
- } catch {
6995
- return trimmed.slice(1, -1);
6877
+ function parseProviderList(value, flag) {
6878
+ const providers = parseCsvList(value);
6879
+ if (providers.length === 0) {
6880
+ throw new PlayBootstrapUsageError(`${flag} provider list cannot be empty.`);
6996
6881
  }
6997
- }
6998
- function findMatchingBrace(source, openIndex) {
6999
- let depth = 0;
7000
- let quote = null;
7001
- let escaped = false;
7002
- for (let index = openIndex; index < source.length; index += 1) {
7003
- const char = source[index];
7004
- if (quote) {
7005
- if (escaped) {
7006
- escaped = false;
7007
- } else if (char === "\\") {
7008
- escaped = true;
7009
- } else if (char === quote) {
7010
- quote = null;
7011
- }
7012
- continue;
7013
- }
7014
- if (char === '"' || char === "'" || char === "`") {
7015
- quote = char;
7016
- continue;
7017
- }
7018
- if (char === "{") depth += 1;
7019
- if (char === "}") {
7020
- depth -= 1;
7021
- if (depth === 0) return index;
7022
- }
7023
- }
7024
- return -1;
7025
- }
7026
- function extractDefinedPlayName(sourceCode) {
7027
- const source = stripCommentsToSpaces(sourceCode);
7028
- const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
7029
- for (const match of source.matchAll(callPattern)) {
7030
- const openParen = match.index + match[0].length - 1;
7031
- const firstArgStart = openParen + 1;
7032
- const firstNonSpace = source.slice(firstArgStart).search(/\S/);
7033
- if (firstNonSpace < 0) continue;
7034
- const argIndex = firstArgStart + firstNonSpace;
7035
- const quote = source[argIndex];
7036
- if (quote === '"' || quote === "'") {
7037
- const literalMatch = source.slice(argIndex).match(/^(['"])(?:\\.|(?!\1)[\s\S])*\1/);
7038
- const value = literalMatch ? unquoteStringLiteral(literalMatch[0]) : null;
7039
- if (value?.trim()) return value.trim();
7040
- }
7041
- if (quote === "{") {
7042
- const closeBrace = findMatchingBrace(source, argIndex);
7043
- if (closeBrace < 0) continue;
7044
- const objectSource = source.slice(argIndex + 1, closeBrace);
7045
- const idMatch = objectSource.match(
7046
- /(?:^|[,{\s])(?:id|['"]id['"])\s*:\s*(['"])([\s\S]*?)\1/
7047
- );
7048
- if (idMatch?.[2]?.trim()) {
7049
- return idMatch[2].trim();
7050
- }
7051
- }
7052
- }
7053
- return null;
7054
- }
7055
- function canonicalizeRootPlayNameForWorkersRuntimeHash(sourceCode) {
7056
- const source = stripCommentsToSpaces(sourceCode);
7057
- const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
7058
- const match = callPattern.exec(source);
7059
- if (!match) return sourceCode;
7060
- const openParen = match.index + match[0].length - 1;
7061
- const firstArgStart = openParen + 1;
7062
- const firstNonSpace = source.slice(firstArgStart).search(/\S/);
7063
- if (firstNonSpace < 0) return sourceCode;
7064
- const argIndex = firstArgStart + firstNonSpace;
7065
- const quote = source[argIndex];
7066
- if (quote === '"' || quote === "'") {
7067
- const literalMatch = source.slice(argIndex).match(/^(['"])(?:\\.|(?!\1)[\s\S])*\1/);
7068
- if (!literalMatch) return sourceCode;
7069
- const replacement = `${quote}__deepline_runtime_play_name__${quote}`;
7070
- return `${sourceCode.slice(0, argIndex)}${replacement}${sourceCode.slice(argIndex + literalMatch[0].length)}`;
7071
- }
7072
- if (quote !== "{") return sourceCode;
7073
- const closeBrace = findMatchingBrace(source, argIndex);
7074
- if (closeBrace < 0) return sourceCode;
7075
- const objectSource = source.slice(argIndex + 1, closeBrace);
7076
- const idMatch = objectSource.match(
7077
- /(^|[,{\s])((?:id|['"]id['"])\s*:\s*)(['"])([\s\S]*?)\3/
7078
- );
7079
- if (!idMatch || idMatch.index === void 0) return sourceCode;
7080
- const idValueStart = argIndex + 1 + idMatch.index + idMatch[1].length + idMatch[2].length + idMatch[3].length;
7081
- return `${sourceCode.slice(0, idValueStart)}__deepline_runtime_play_name__${sourceCode.slice(idValueStart + idMatch[4].length)}`;
7082
- }
7083
- function workersRuntimeGraphFilePath(input2) {
7084
- if (input2.filePath === input2.entryFile) return "<entry>";
7085
- const entryRelative = relative(dirname6(input2.entryFile), input2.filePath);
7086
- if (entryRelative && !entryRelative.startsWith("..")) {
7087
- return entryRelative.replaceAll("\\", "/");
7088
- }
7089
- return `<project>/${relative(input2.adapter.projectRoot, input2.filePath).replaceAll("\\", "/")}`;
7090
- }
7091
- function buildWorkersRuntimeGraphHash(input2) {
7092
- const sourceFiles = Object.entries(input2.analysis.sourceFiles).map(([filePath, contents]) => ({
7093
- filePath: workersRuntimeGraphFilePath({
7094
- entryFile: input2.entryFile,
7095
- filePath,
7096
- adapter: input2.adapter
7097
- }),
7098
- hash: sha256(
7099
- filePath === input2.entryFile ? canonicalizeRootPlayNameForWorkersRuntimeHash(contents) : contents
7100
- )
7101
- })).sort((left, right) => left.filePath.localeCompare(right.filePath));
7102
- return sha256(
7103
- JSON.stringify({
7104
- entryFile: "<entry>",
7105
- entryExport: input2.exportName,
7106
- localFiles: sourceFiles,
7107
- nodeBuiltins: [...input2.analysis.importPolicy.nodeBuiltins].sort(),
7108
- packages: input2.analysis.importPolicy.packages.map(({ name, version }) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name)),
7109
- importedPlayDependencies: input2.analysis.importedPlayDependencies.map((dependency) => ({
7110
- filePath: workersRuntimeGraphFilePath({
7111
- entryFile: input2.entryFile,
7112
- filePath: dependency.filePath,
7113
- adapter: input2.adapter
7114
- }),
7115
- playName: dependency.playName
7116
- })).sort((left, right) => left.filePath.localeCompare(right.filePath))
7117
- })
7118
- );
7119
- }
7120
- function readPackageVersionFromPackageJson(packageJsonPath, packageName) {
7121
- try {
7122
- const packageJson = JSON.parse(readFileSync6(packageJsonPath, "utf-8"));
7123
- if (packageJson.name === packageName && typeof packageJson.version === "string") {
7124
- return packageJson.version;
7125
- }
7126
- } catch {
7127
- return null;
7128
- }
7129
- return null;
7130
- }
7131
- function findPackageJsonPathFrom(startDir, packageName) {
7132
- if (!isAbsolute(startDir)) {
7133
- throw new Error(
7134
- `Package resolution requires an absolute start directory, got ${startDir}`
7135
- );
7136
- }
7137
- let current = startDir;
7138
- while (true) {
7139
- const packageJsonPath = join5(
7140
- current,
7141
- "node_modules",
7142
- packageName,
7143
- "package.json"
7144
- );
7145
- if (existsSync6(packageJsonPath)) {
7146
- return packageJsonPath;
7147
- }
7148
- const parent = dirname6(current);
7149
- if (parent === current) {
7150
- return null;
7151
- }
7152
- current = parent;
7153
- }
7154
- }
7155
- function findPackageJsonPath(packageName, fromFile, adapter) {
7156
- const startDirs = [
7157
- resolve6(dirname6(fromFile)),
7158
- resolve6(adapter.projectRoot),
7159
- resolve6(dirname6(adapter.sdkPackageJson))
7160
- ];
7161
- const seen = /* @__PURE__ */ new Set();
7162
- for (const startDir of startDirs) {
7163
- if (seen.has(startDir)) continue;
7164
- seen.add(startDir);
7165
- const packageJsonPath = findPackageJsonPathFrom(startDir, packageName);
7166
- if (packageJsonPath) return packageJsonPath;
7167
- }
7168
- const adapterNodeModulesPackageJson = join5(
7169
- adapter.nodeModulesDir,
7170
- packageName,
7171
- "package.json"
7172
- );
7173
- return existsSync6(adapterNodeModulesPackageJson) ? adapterNodeModulesPackageJson : null;
7174
- }
7175
- function localSdkAliasPlugin(adapter, options) {
7176
- const entryFile = options?.workersRuntime ? adapter.sdkWorkersEntryFile : adapter.sdkEntryFile;
7177
- if (!existsSync6(entryFile)) {
7178
- return null;
7179
- }
7180
- return {
7181
- name: "deepline-sdk-local-alias",
7182
- setup(buildContext) {
7183
- buildContext.onResolve({ filter: /^deepline$/ }, () => ({
7184
- path: entryFile
7185
- }));
7186
- buildContext.onResolve({ filter: /^deepline\/helpers$/ }, () => ({
7187
- path: join5(adapter.sdkSourceRoot, "helpers.ts")
7188
- }));
7189
- }
7190
- };
7191
- }
7192
- function workersPlayEntryAliasPlugin(playFilePath) {
7193
- return {
7194
- name: "deepline-workers-play-entry-alias",
7195
- setup(buildContext) {
7196
- buildContext.onResolve(
7197
- { filter: new RegExp(`^${WORKERS_PLAY_ENTRY_VIRTUAL}$`) },
7198
- () => ({ path: playFilePath })
7199
- );
7200
- }
7201
- };
7202
- }
7203
- function workersNamedPlayEntryAliasPlugin(playFilePath, exportName) {
7204
- return {
7205
- name: "deepline-workers-named-play-entry-alias",
7206
- setup(buildContext) {
7207
- buildContext.onResolve(
7208
- { filter: new RegExp(`^${WORKERS_PLAY_ENTRY_VIRTUAL}$`) },
7209
- () => ({
7210
- path: `${playFilePath}.${exportName}.entry.ts`,
7211
- namespace: "deepline-named-play-entry"
7212
- })
7213
- );
7214
- buildContext.onLoad(
7215
- { filter: /.*/, namespace: "deepline-named-play-entry" },
7216
- () => ({
7217
- contents: `export { ${exportName} as default } from ${JSON.stringify(playFilePath)};
7218
- `,
7219
- loader: "ts",
7220
- resolveDir: dirname6(playFilePath)
7221
- })
7222
- );
7223
- }
7224
- };
7225
- }
7226
- function workersNodeBuiltinStubPlugin() {
7227
- const UNSUPPORTED = /* @__PURE__ */ new Set([
7228
- "node:fs",
7229
- "node:fs/promises",
7230
- "node:os",
7231
- "node:child_process"
7232
- ]);
7233
- return {
7234
- name: "deepline-workers-node-builtin-stub",
7235
- setup(buildContext) {
7236
- buildContext.onResolve({ filter: /^node:/ }, (args) => {
7237
- if (!UNSUPPORTED.has(args.path)) return null;
7238
- return { path: args.path, namespace: "deepline-workers-node-stub" };
7239
- });
7240
- buildContext.onLoad(
7241
- { filter: /.*/, namespace: "deepline-workers-node-stub" },
7242
- (args) => {
7243
- const builtinName = args.path;
7244
- const stubSource = `
7245
- const message = ${JSON.stringify(
7246
- `Workers backend: ${builtinName} is not available in Cloudflare Workers (no filesystem / no OS). Run this play on Daytona or local-process backend if it needs node builtins.`
7247
- )};
7248
- function makeThrower(name) {
7249
- return new Proxy(function() { throw new Error(message + ' (called: ' + name + ')'); }, {
7250
- get(_t, prop) {
7251
- if (prop === '__esModule') return true;
7252
- if (typeof prop === 'symbol') return undefined;
7253
- return makeThrower(name + '.' + String(prop));
7254
- },
7255
- apply() { throw new Error(message + ' (called: ' + name + ')'); },
7256
- construct() { throw new Error(message + ' (constructed: ' + name + ')'); },
7257
- });
7258
- }
7259
- module.exports = makeThrower(${JSON.stringify(builtinName)});
7260
- `;
7261
- return { contents: stubSource, loader: "js" };
7262
- }
7263
- );
7264
- }
7265
- };
7266
- }
7267
- function zodNonEnglishLocaleStubPlugin() {
7268
- const LOCALE_PATH_FILTER = /[\\/]zod[\\/]v4[\\/]locales[\\/][^\\/]+\.(?:c?js|mjs)$/;
7269
- const NAMESPACE = "deepline-zod-locale-stub";
7270
- return {
7271
- name: "deepline-zod-non-english-locale-stub",
7272
- setup(buildContext) {
7273
- buildContext.onResolve({ filter: LOCALE_PATH_FILTER }, (args) => {
7274
- const norm = args.path.replace(/\\/g, "/");
7275
- const file = norm.slice(norm.lastIndexOf("/") + 1);
7276
- if (/^en(?:[-_][A-Za-z]+)?\.(?:c?js|mjs)$/.test(file)) {
7277
- return null;
7278
- }
7279
- return { path: args.path, namespace: NAMESPACE };
7280
- });
7281
- buildContext.onLoad({ filter: /.*/, namespace: NAMESPACE }, () => ({
7282
- // zod locales export a default object literal. Empty object is
7283
- // structurally compatible — accessing any locale key returns
7284
- // undefined and zod falls back to its built-in English.
7285
- contents: "export default {};",
7286
- loader: "js"
7287
- }));
7288
- }
7289
- };
7290
- }
7291
- var WORKERS_BANNED_NODE_MODULES = /* @__PURE__ */ new Set([
7292
- "node:fs",
7293
- "node:fs/promises",
7294
- "node:net",
7295
- "node:child_process",
7296
- "node:cluster",
7297
- "node:tls",
7298
- "node:dgram",
7299
- "node:dns",
7300
- "node:dns/promises",
7301
- "node:repl",
7302
- "node:vm",
7303
- "node:worker_threads"
7304
- ]);
7305
- function workersNodeImportBanlistPlugin(adapter) {
7306
- return {
7307
- name: "deepline-workers-node-import-banlist",
7308
- setup(buildContext) {
7309
- buildContext.onResolve({ filter: /^node:/ }, (args) => {
7310
- if (!WORKERS_BANNED_NODE_MODULES.has(args.path)) return null;
7311
- const importer = args.importer ?? "";
7312
- if (importer.startsWith(adapter.sdkSourceRoot)) {
7313
- return null;
7314
- }
7315
- return {
7316
- errors: [
7317
- {
7318
- text: `Module "${args.path}" is not allowed in workers_edge plays. See AGENTS.md for the V8 isolate boundary.`,
7319
- detail: { importer: args.importer, kind: args.kind }
7320
- }
7321
- ]
7322
- };
7323
- });
7324
- }
7325
- };
7326
- }
7327
- function buildImportedPlayProxyModule(playName) {
7328
- const serializedName = JSON.stringify(playName);
7329
- return `
7330
- const PLAY_METADATA_SYMBOL = Symbol.for('deepline.play.metadata');
7331
- const importedPlayRef = async function importedPlayRef(ctx, input) {
7332
- return ctx.runPlay(${JSON.stringify(`imported_${playName.replace(/[^A-Za-z0-9_]+/g, "_")}`)}, importedPlayRef, input, {
7333
- description: 'Run the imported Deepline play dependency.',
7334
- });
7335
- };
7336
- Object.defineProperty(importedPlayRef, 'playName', {
7337
- value: ${serializedName},
7338
- enumerable: true,
7339
- configurable: false,
7340
- writable: false,
7341
- });
7342
- Object.defineProperty(importedPlayRef, PLAY_METADATA_SYMBOL, {
7343
- value: { name: ${serializedName} },
7344
- enumerable: false,
7345
- configurable: false,
7346
- writable: false,
7347
- });
7348
- export const playName = ${serializedName};
7349
- export const name = ${serializedName};
7350
- export default importedPlayRef;
7351
- `;
7352
- }
7353
- function importedPlayProxyPlugin(importedPlayDependencies) {
7354
- if (importedPlayDependencies.length === 0) {
7355
- return null;
7356
- }
7357
- const dependenciesByPath = new Map(
7358
- importedPlayDependencies.map((dependency) => [
7359
- dependency.filePath,
7360
- dependency
7361
- ])
7362
- );
7363
- return {
7364
- name: "deepline-imported-play-proxy",
7365
- setup(buildContext) {
7366
- buildContext.onResolve({ filter: /.*/ }, async (args) => {
7367
- if (!args.importer || !isLocalSpecifier(args.path)) {
7368
- return null;
7369
- }
7370
- const resolvedPath = await resolveLocalImport(args.importer, args.path);
7371
- const dependency = dependenciesByPath.get(resolvedPath);
7372
- if (!dependency) {
7373
- return null;
7374
- }
7375
- return {
7376
- path: dependency.filePath,
7377
- namespace: PLAY_PROXY_NAMESPACE,
7378
- pluginData: dependency
7379
- };
7380
- });
7381
- buildContext.onLoad(
7382
- { filter: /.*/, namespace: PLAY_PROXY_NAMESPACE },
7383
- async (args) => {
7384
- const dependency = args.pluginData ?? dependenciesByPath.get(args.path);
7385
- if (!dependency) {
7386
- return null;
7387
- }
7388
- return {
7389
- contents: buildImportedPlayProxyModule(dependency.playName),
7390
- loader: "ts",
7391
- resolveDir: dirname6(args.path)
7392
- };
7393
- }
7394
- );
7395
- }
7396
- };
7397
- }
7398
- async function fileExists(filePath) {
7399
- try {
7400
- await stat(filePath);
7401
- return true;
7402
- } catch {
7403
- return false;
7404
- }
7405
- }
7406
- async function resolveLocalImport(fromFile, specifier) {
7407
- if (specifier.startsWith("file:")) {
7408
- return normalizeLocalPath(new URL(specifier).pathname);
7409
- }
7410
- const base = isAbsolute(specifier) ? resolve6(specifier) : resolve6(dirname6(fromFile), specifier);
7411
- const candidates = [base];
7412
- const explicitExtension = extname(base).toLowerCase();
7413
- if (!explicitExtension) {
7414
- candidates.push(
7415
- ...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`)
7416
- );
7417
- candidates.push(
7418
- ...SOURCE_EXTENSIONS.map((extension) => join5(base, `index${extension}`))
7419
- );
7420
- } else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
7421
- const stem = base.slice(0, -explicitExtension.length);
7422
- candidates.push(
7423
- ...SOURCE_EXTENSIONS.map((extension) => `${stem}${extension}`)
7424
- );
7425
- }
7426
- for (const candidate of candidates) {
7427
- if (await fileExists(candidate)) {
7428
- return normalizeLocalPath(candidate);
7429
- }
7430
- }
7431
- throw new Error(
7432
- `Could not resolve local import "${specifier}" from ${fromFile}`
7433
- );
7434
- }
7435
- function resolvePackageImport(specifier, fromFile, adapter) {
7436
- const packageName = getPackageName(specifier);
7437
- if (packageName === "deepline" && existsSync6(adapter.sdkPackageJson)) {
7438
- const packageJson = JSON.parse(
7439
- readFileSync6(adapter.sdkPackageJson, "utf-8")
7440
- );
7441
- return {
7442
- name: "deepline",
7443
- version: packageJson.version ?? null
7444
- };
7445
- }
7446
- const packageJsonPath = findPackageJsonPath(packageName, fromFile, adapter);
7447
- if (!packageJsonPath) {
7448
- throw new Error(`Could not resolve "${specifier}" from ${fromFile}`);
7449
- }
7450
- return {
7451
- name: packageName,
7452
- version: readPackageVersionFromPackageJson(packageJsonPath, packageName)
7453
- };
7454
- }
7455
- async function analyzeSourceGraph(entryFile, adapter) {
7456
- const absoluteEntryFile = await normalizeLocalPath(entryFile);
7457
- const workspace = createPlayWorkspace(absoluteEntryFile);
7458
- const localFiles = /* @__PURE__ */ new Map();
7459
- const nodeBuiltins = /* @__PURE__ */ new Set();
7460
- const packages = /* @__PURE__ */ new Map();
7461
- const importedPlayDependencies = /* @__PURE__ */ new Map();
7462
- const visited = /* @__PURE__ */ new Set();
7463
- const visitFile = async (filePath) => {
7464
- const absolutePath = await normalizeLocalPath(filePath);
7465
- if (visited.has(absolutePath)) {
7466
- return;
7467
- }
7468
- visited.add(absolutePath);
7469
- const sourceCode2 = await readFile(absolutePath, "utf-8");
7470
- localFiles.set(absolutePath, sourceCode2);
7471
- if (extname(absolutePath).toLowerCase() === ".json") {
7472
- return;
7473
- }
7474
- const handleSpecifier = async (specifier, line, column, kind) => {
7475
- if (kind === "dynamic-import") {
7476
- throw new Error(
7477
- `${absolutePath}:${line}:${column} Dynamic import() is not allowed in plays. Use static imports instead.`
7478
- );
7479
- }
7480
- if (NODE_BUILTIN_SET.has(specifier)) {
7481
- nodeBuiltins.add(
7482
- specifier.startsWith("node:") ? specifier : `node:${specifier}`
7483
- );
7484
- return;
7485
- }
7486
- if (isLocalSpecifier(specifier)) {
7487
- const resolved = await resolveLocalImport(absolutePath, specifier);
7488
- assertWithinPlayWorkspace({
7489
- importer: absolutePath,
7490
- specifier,
7491
- resolvedPath: resolved,
7492
- workspace,
7493
- line,
7494
- column
7495
- });
7496
- if (resolved !== absoluteEntryFile && isPlaySourceFile(resolved)) {
7497
- const importedSource = await readFile(resolved, "utf-8");
7498
- const importedPlayName = extractDefinedPlayName(importedSource);
7499
- if (!importedPlayName) {
7500
- throw new Error(
7501
- `${absolutePath}:${line}:${column} Imported play file "${specifier}" must export definePlay(...) so it can be runtime-composed.`
7502
- );
7503
- }
7504
- importedPlayDependencies.set(resolved, {
7505
- filePath: resolved,
7506
- playName: importedPlayName
7507
- });
7508
- return;
7509
- }
7510
- await visitFile(resolved);
7511
- return;
7512
- }
7513
- if (specifier.includes(":")) {
7514
- throw new Error(
7515
- `${absolutePath}:${line}:${column} Unsupported import specifier "${specifier}". Allowed imports are relative files, Node builtins, and installed packages.`
7516
- );
7517
- }
7518
- const packageImport = resolvePackageImport(
7519
- specifier,
7520
- absolutePath,
7521
- adapter
7522
- );
7523
- packages.set(packageImport.name, packageImport.version);
7524
- };
7525
- try {
7526
- for (const reference of findSourceImportReferences(sourceCode2)) {
7527
- await handleSpecifier(
7528
- reference.specifier,
7529
- reference.line,
7530
- reference.column,
7531
- reference.kind
7532
- );
7533
- }
7534
- } catch (error) {
7535
- if (error instanceof Error && error.message.startsWith(":")) {
7536
- throw new Error(`${absolutePath}${error.message}`);
7537
- }
7538
- throw error;
7539
- }
7540
- };
7541
- await visitFile(absoluteEntryFile);
7542
- const sourceCode = localFiles.get(absoluteEntryFile) ?? "";
7543
- const sourceHash = sha256(sourceCode);
7544
- const graphHash = sha256(
7545
- JSON.stringify({
7546
- entryFile: absoluteEntryFile,
7547
- localFiles: [...localFiles.entries()].map(([filePath, contents]) => ({ filePath, hash: sha256(contents) })).sort((left, right) => left.filePath.localeCompare(right.filePath)),
7548
- nodeBuiltins: [...nodeBuiltins].sort(),
7549
- packages: [...packages.entries()].map(([name, version]) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name)),
7550
- importedPlayDependencies: [...importedPlayDependencies.values()].map((dependency) => ({
7551
- filePath: dependency.filePath,
7552
- playName: dependency.playName
7553
- })).sort((left, right) => left.filePath.localeCompare(right.filePath))
7554
- })
7555
- );
7556
- const playName = extractDefinedPlayName(sourceCode);
7557
- return {
7558
- sourceCode,
7559
- sourceFiles: Object.fromEntries(
7560
- [...localFiles.entries()].sort(
7561
- (left, right) => left[0].localeCompare(right[0])
7562
- )
7563
- ),
7564
- sourceHash,
7565
- graphHash,
7566
- importPolicy: {
7567
- localFiles: [...localFiles.keys()].sort(),
7568
- nodeBuiltins: [...nodeBuiltins].sort(),
7569
- packages: [...packages.entries()].map(([name, version]) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name))
7570
- },
7571
- playName,
7572
- importedPlayDependencies: [...importedPlayDependencies.values()].sort(
7573
- (left, right) => left.filePath.localeCompare(right.filePath)
7574
- )
7575
- };
7576
- }
7577
- async function computeWorkersHarnessFingerprintWithAdapter(adapter) {
7578
- const { readdir } = await import("fs/promises");
7579
- const addFilePart = async (parts2, rootDir, filePath) => {
7580
- const contents = await readFile(filePath, "utf-8");
7581
- parts2.push({
7582
- name: `${basename(rootDir)}:${filePath.slice(rootDir.length + 1)}`,
7583
- hash: sha256(contents)
7584
- });
7585
- };
7586
- const collectTopLevelTsFiles = async (rootDir, parts2) => {
7587
- if (!await fileExists(rootDir)) return;
7588
- const entries2 = await readdir(rootDir, { withFileTypes: true });
7589
- const tsFiles2 = entries2.filter((entry) => entry.isFile() && /\.[cm]?ts$/.test(entry.name)).map((entry) => entry.name).sort();
7590
- for (const name of tsFiles2) {
7591
- await addFilePart(parts2, rootDir, join5(rootDir, name));
7592
- }
7593
- };
7594
- const collectIntegrationBatchingFiles = async (rootDir, parts2) => {
7595
- if (!await fileExists(rootDir)) return;
7596
- const entries2 = await readdir(rootDir, { withFileTypes: true });
7597
- const filePaths = [];
7598
- for (const entry of entries2) {
7599
- if (entry.isFile() && (entry.name === "play-runtime-batching-registry.ts" || /^batching.*\.ts$/.test(entry.name))) {
7600
- filePaths.push(join5(rootDir, entry.name));
7601
- }
7602
- if (entry.isDirectory()) {
7603
- const batchingFile = join5(rootDir, entry.name, "batching.ts");
7604
- if (await fileExists(batchingFile)) {
7605
- filePaths.push(batchingFile);
7606
- }
7607
- }
7608
- }
7609
- for (const filePath of filePaths.sort()) {
7610
- await addFilePart(parts2, rootDir, filePath);
7611
- }
7612
- };
7613
- const entries = await readdir(adapter.workersHarnessFilesDir, {
7614
- withFileTypes: true
7615
- });
7616
- const tsFiles = entries.filter((e) => e.isFile() && /\.[cm]?ts$/.test(e.name)).map((e) => e.name).sort();
7617
- const parts = [];
7618
- for (const name of tsFiles) {
7619
- await addFilePart(
7620
- parts,
7621
- adapter.workersHarnessFilesDir,
7622
- join5(adapter.workersHarnessFilesDir, name)
7623
- );
7624
- }
7625
- for (const dir of adapter.workersRuntimeFingerprintDirs ?? []) {
7626
- if (basename(dir) === "integrations") {
7627
- await collectIntegrationBatchingFiles(dir, parts);
7628
- } else {
7629
- await collectTopLevelTsFiles(dir, parts);
7630
- }
7631
- }
7632
- return sha256(JSON.stringify(parts));
7633
- }
7634
- function artifactCachePath(graphHash, artifactKind, adapter) {
7635
- return join5(
7636
- adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR,
7637
- `${graphHash}.${artifactKind}.json`
7638
- );
7639
- }
7640
- async function readArtifactCache(graphHash, artifactKind, adapter) {
7641
- try {
7642
- const serialized = await readFile(
7643
- artifactCachePath(graphHash, artifactKind, adapter),
7644
- "utf-8"
7645
- );
7646
- return JSON.parse(serialized);
7647
- } catch {
7648
- return null;
7649
- }
7650
- }
7651
- async function writeArtifactCache(artifact, adapter) {
7652
- const cacheDir = adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR;
7653
- await mkdir3(cacheDir, { recursive: true });
7654
- await writeFile3(
7655
- artifactCachePath(
7656
- artifact.graphHash,
7657
- artifact.artifactKind ?? PLAY_ARTIFACT_KINDS.cjsNode20,
7658
- adapter
7659
- ),
7660
- JSON.stringify(artifact),
7661
- "utf-8"
7662
- );
7663
- }
7664
- function normalizeSourceMapForRuntime(sourceMapText, projectRoot) {
7665
- const parsed = JSON.parse(sourceMapText);
7666
- parsed.sources = (parsed.sources ?? []).map((sourcePath) => {
7667
- if (sourcePath.startsWith("data:") || sourcePath.startsWith("node:") || sourcePath.startsWith("/") || /^[a-zA-Z]+:\/\//.test(sourcePath)) {
7668
- return sourcePath;
7669
- }
7670
- return join5(projectRoot, sourcePath);
7671
- });
7672
- parsed.sourceRoot = void 0;
7673
- return JSON.stringify(parsed);
7674
- }
7675
- function getBundleSizeErrorForBytes(filePath, bundleBytes, artifactKind) {
7676
- if (bundleBytes > MAX_PLAY_BUNDLE_BYTES) {
7677
- return `${filePath} Play bundle exceeds the 30 MiB limit (${bundleBytes} bytes > ${MAX_PLAY_BUNDLE_BYTES} bytes).`;
7678
- }
7679
- if (artifactKind === PLAY_ARTIFACT_KINDS.esmWorkers && bundleBytes > MAX_ESM_WORKERS_BUNDLE_BYTES) {
7680
- const mib = (bundleBytes / 1024 / 1024).toFixed(2);
7681
- const limitMib = (MAX_ESM_WORKERS_BUNDLE_BYTES / 1024 / 1024).toFixed(2);
7682
- return `${filePath} Cloudflare Workers bundle is ${mib} MiB, above the workerd local-mode threshold of ${limitMib} MiB. Bundles past this size silently hang without executing the workflow body. Reduce dependencies (top offenders are usually date-fns, lodash, large schema libs) or split the play into smaller pieces with ctx.runPlay.`;
7683
- }
7684
- return null;
7685
- }
7686
- function getBundleSizeError(filePath, bundledCode, artifactKind) {
7687
- return getBundleSizeErrorForBytes(
7688
- filePath,
7689
- Buffer.byteLength(bundledCode, "utf8"),
7690
- artifactKind
7691
- );
7692
- }
7693
- async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter, exportName) {
7694
- const sdkAliasPlugin = localSdkAliasPlugin(adapter);
7695
- const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
7696
- const namedExportShim = exportName === "default" ? null : `export { ${exportName} as default } from ${JSON.stringify(entryFile)};
7697
- `;
7698
- const result = await build({
7699
- ...namedExportShim ? {
7700
- stdin: {
7701
- contents: namedExportShim,
7702
- resolveDir: dirname6(entryFile),
7703
- sourcefile: `${basename(entryFile)}.${exportName}.entry.ts`,
7704
- loader: "ts"
7705
- }
7706
- } : { entryPoints: [entryFile] },
7707
- absWorkingDir: adapter.projectRoot,
7708
- bundle: true,
7709
- format: "cjs",
7710
- nodePaths: [adapter.nodeModulesDir],
7711
- platform: "node",
7712
- target: ["node20"],
7713
- outfile: "play-artifact.cjs",
7714
- write: false,
7715
- sourcemap: "external",
7716
- sourcesContent: false,
7717
- logLevel: "silent",
7718
- legalComments: "none",
7719
- plugins: [sdkAliasPlugin, playProxyPlugin].filter(
7720
- (plugin) => plugin != null
7721
- )
7722
- });
7723
- const codeFile = result.outputFiles?.find((f) => f.path.endsWith(".cjs"));
7724
- const mapFile = result.outputFiles?.find((f) => f.path.endsWith(".cjs.map"));
7725
- if (!codeFile?.text || !mapFile?.text) {
7726
- return ["Play bundling produced incomplete output."];
7727
- }
7728
- return {
7729
- bundledCode: codeFile.text,
7730
- sourceMapText: mapFile.text,
7731
- outputExtension: "cjs"
7732
- };
7733
- }
7734
- async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies, adapter, exportName) {
7735
- const sdkAliasPlugin = localSdkAliasPlugin(adapter, { workersRuntime: true });
7736
- const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
7737
- const playEntryAlias = exportName === "default" ? workersPlayEntryAliasPlugin(playEntryFile) : workersNamedPlayEntryAliasPlugin(playEntryFile, exportName);
7738
- const result = await build({
7739
- // Entry is the Workers harness; it imports the play via the virtual
7740
- // `deepline-play-entry` alias resolved by workersPlayEntryAliasPlugin.
7741
- entryPoints: [adapter.workersHarnessEntryFile],
7742
- absWorkingDir: adapter.projectRoot,
7743
- bundle: true,
7744
- format: "esm",
7745
- nodePaths: [adapter.nodeModulesDir],
7746
- // Browser platform with workerd + worker conditions matches Cloudflare's
7747
- // V8-isolate runtime. Avoids accidentally pulling node-only branches of
7748
- // dual-publish packages.
7749
- platform: "browser",
7750
- conditions: ["workerd", "worker", "browser", "import", "default"],
7751
- mainFields: ["module", "main"],
7752
- target: ["es2022"],
7753
- outfile: "play-worker.mjs",
7754
- write: false,
7755
- sourcemap: "external",
7756
- sourcesContent: false,
7757
- logLevel: "silent",
7758
- legalComments: "none",
7759
- // Aggressive minify + treeshake: a tiny play (<1KB source) was producing
7760
- // an ~870KB bundle, dominated by zod's locale files (~260KB unused) and
7761
- // dead-code branches across `shared_libs/play-runtime/*` and the SDK.
7762
- // Both DCE on with these flags. workerd compiles each unique-graphHash
7763
- // bundle on first dispatch, so bundle bytes translate ~linearly into
7764
- // per-play cold latency on workers_edge. External sourcemap remains
7765
- // unchanged (`sourcemap: 'external'`), so debugging is unaffected.
7766
- minify: true,
7767
- treeShaking: true,
7768
- // Most node:* builtins are provided by Cloudflare's `nodejs_compat` flag.
7769
- // The unsupported subset (fs, fs/promises, os, child_process) gets
7770
- // replaced with throwing stubs by workersNodeBuiltinStubPlugin so deploy
7771
- // validation passes; anything supported (path, crypto, buffer, etc.) is
7772
- // marked external and resolved at runtime by the Workers runtime.
7773
- external: ["node:*", "cloudflare:workers"],
7774
- plugins: [
7775
- // Banlist runs first so a forbidden import errors out before any other
7776
- // resolver (esp. the workersNodeBuiltinStubPlugin which would silently
7777
- // turn it into a throwing-stub).
7778
- workersNodeImportBanlistPlugin(adapter),
7779
- sdkAliasPlugin,
7780
- playProxyPlugin,
7781
- playEntryAlias,
7782
- workersNodeBuiltinStubPlugin(),
7783
- // Strip non-English zod locale data from the bundle. zod's locales
7784
- // are re-exported as a static namespace from `zod/v4/core`, so
7785
- // tree-shaking can't drop them; this plugin replaces each
7786
- // non-English locale module with an empty default export at bundle
7787
- // time. ~150–200 KB savings on every per-play bundle, with no
7788
- // behavior change (we only surface English messages anyway).
7789
- // If the bundle suddenly grows back, check whether a new dep added
7790
- // its own zod copy or whether zod's locale layout changed.
7791
- zodNonEnglishLocaleStubPlugin()
7792
- ].filter((plugin) => plugin != null)
7793
- });
7794
- const codeFile = result.outputFiles?.find((f) => f.path.endsWith(".mjs"));
7795
- const mapFile = result.outputFiles?.find((f) => f.path.endsWith(".mjs.map"));
7796
- if (!codeFile?.text || !mapFile?.text) {
7797
- return ["Workers play bundling produced incomplete output."];
7798
- }
7799
- return {
7800
- bundledCode: codeFile.text,
7801
- sourceMapText: mapFile.text,
7802
- outputExtension: "mjs"
7803
- };
7804
- }
7805
- var PLAY_ARTIFACT_TARGET_ADAPTERS = {
7806
- [PLAY_ARTIFACT_KINDS.cjsNode20]: {
7807
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
7808
- codeFormat: "cjs_module",
7809
- includeWorkersHarnessInGraphHash: false,
7810
- runEsbuild: ({
7811
- entryFile,
7812
- importedPlayDependencies,
7813
- adapter,
7814
- exportName
7815
- }) => runEsbuildForCjsNode(
7816
- entryFile,
7817
- importedPlayDependencies,
7818
- adapter,
7819
- exportName
7820
- )
7821
- },
7822
- [PLAY_ARTIFACT_KINDS.esmWorkers]: {
7823
- artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
7824
- codeFormat: "esm_module",
7825
- includeWorkersHarnessInGraphHash: true,
7826
- runEsbuild: ({
7827
- entryFile,
7828
- importedPlayDependencies,
7829
- adapter,
7830
- exportName
7831
- }) => runEsbuildForEsmWorkers(
7832
- entryFile,
7833
- importedPlayDependencies,
7834
- adapter,
7835
- exportName
7836
- )
7837
- }
7838
- };
7839
- function resolvePlayArtifactTargetAdapter(artifactKind) {
7840
- return PLAY_ARTIFACT_TARGET_ADAPTERS[artifactKind];
7841
- }
7842
- async function bundlePlayFile(filePath, options) {
7843
- const adapter = options.adapter;
7844
- const target = options.target ?? PLAY_ARTIFACT_KINDS.cjsNode20;
7845
- const targetAdapter = resolvePlayArtifactTargetAdapter(target);
7846
- const exportName = options.exportName?.trim() || "default";
7847
- assertValidExportName(exportName);
7848
- const absolutePath = await normalizeLocalPath(filePath);
7849
- adapter.warnAboutNonDevelopmentBundling?.(absolutePath);
7850
- try {
7851
- const analysis = await analyzeSourceGraph(absolutePath, adapter);
7852
- analysis.graphHash = target === PLAY_ARTIFACT_KINDS.esmWorkers ? buildWorkersRuntimeGraphHash({
7853
- analysis,
7854
- entryFile: absolutePath,
7855
- adapter,
7856
- exportName
7857
- }) : sha256(`${analysis.graphHash}
7858
- entry-export:${exportName}`);
7859
- if (targetAdapter.includeWorkersHarnessInGraphHash) {
7860
- const harnessFingerprint = await computeWorkersHarnessFingerprintWithAdapter(adapter);
7861
- analysis.graphHash = sha256(
7862
- `${analysis.graphHash}
7863
- workers-harness:${harnessFingerprint}`
7864
- );
7865
- }
7866
- try {
7867
- validatePlaySourceFilesHaveNoInlineSecrets(analysis.sourceFiles);
7868
- } catch (error) {
7869
- return {
7870
- success: false,
7871
- filePath: absolutePath,
7872
- errors: [error instanceof Error ? error.message : String(error)]
7873
- };
7874
- }
7875
- const typecheckErrors = [
7876
- ...await adapter.typecheckPlaySource?.({
7877
- sourceCode: analysis.sourceCode,
7878
- sourcePath: absolutePath,
7879
- importedFilePaths: [
7880
- ...analysis.importPolicy.localFiles,
7881
- ...analysis.importedPlayDependencies.map(
7882
- (dependency) => dependency.filePath
7883
- )
7884
- ]
7885
- }) ?? []
7886
- ];
7887
- if (typecheckErrors.length > 0) {
7888
- return {
7889
- success: false,
7890
- filePath: absolutePath,
7891
- errors: typecheckErrors
7892
- };
7893
- }
7894
- const canUseArtifactCache = target !== PLAY_ARTIFACT_KINDS.esmWorkers;
7895
- const cachedArtifact = canUseArtifactCache ? await readArtifactCache(analysis.graphHash, target, adapter) : null;
7896
- const discoveredFiles = await adapter.discoverPackagedLocalFiles(absolutePath);
7897
- if (cachedArtifact) {
7898
- const cachedArtifactSizeError = getBundleSizeError(
7899
- absolutePath,
7900
- cachedArtifact.bundledCode,
7901
- target
7902
- );
7903
- if (cachedArtifactSizeError) {
7904
- return {
7905
- success: false,
7906
- filePath: absolutePath,
7907
- errors: [cachedArtifactSizeError]
7908
- };
7909
- }
7910
- return {
7911
- success: true,
7912
- artifact: {
7913
- ...cachedArtifact,
7914
- entryFile: absolutePath,
7915
- sourceHash: analysis.sourceHash,
7916
- importPolicy: analysis.importPolicy,
7917
- cacheHit: true
7918
- },
7919
- sourceCode: analysis.sourceCode,
7920
- sourceFiles: analysis.sourceFiles,
7921
- filePath: absolutePath,
7922
- playName: analysis.playName,
7923
- packagedFiles: discoveredFiles.files,
7924
- unresolvedFileReferences: discoveredFiles.unresolved,
7925
- importedPlayDependencies: analysis.importedPlayDependencies
7926
- };
7927
- }
7928
- const buildOutcome = await targetAdapter.runEsbuild({
7929
- entryFile: absolutePath,
7930
- importedPlayDependencies: analysis.importedPlayDependencies,
7931
- adapter,
7932
- exportName
7933
- });
7934
- if (Array.isArray(buildOutcome)) {
7935
- return {
7936
- success: false,
7937
- filePath: absolutePath,
7938
- errors: buildOutcome
7939
- };
7940
- }
7941
- const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
7942
- const normalizedSourceMap = normalizeSourceMapForRuntime(
7943
- sourceMapText,
7944
- resolve6(adapter.projectRoot)
7945
- );
7946
- const virtualBaseName = exportName === "default" ? basename(absolutePath).replace(/\.[^.]+$/, "") : `${basename(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
7947
- const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
7948
- const executableCode = `${bundledCode}
7949
- //# sourceMappingURL=${basename(virtualFilename)}.map
7950
- `;
7951
- const bundleSizeError = getBundleSizeError(
7952
- absolutePath,
7953
- executableCode,
7954
- target
7955
- );
7956
- if (bundleSizeError) {
7957
- return {
7958
- success: false,
7959
- filePath: absolutePath,
7960
- errors: [bundleSizeError]
7961
- };
7962
- }
7963
- const artifact = {
7964
- codeFormat: targetAdapter.codeFormat,
7965
- artifactKind: target,
7966
- entryFile: absolutePath,
7967
- virtualFilename,
7968
- sourceHash: analysis.sourceHash,
7969
- graphHash: analysis.graphHash,
7970
- artifactHash: sha256(executableCode),
7971
- sourceMapHash: sha256(normalizedSourceMap),
7972
- bundledCode: executableCode,
7973
- sourceMap: normalizedSourceMap,
7974
- importPolicy: analysis.importPolicy,
7975
- compatibility: buildPlayContractCompatibility(),
7976
- generatedAt: Date.now(),
7977
- cacheHit: false
7978
- };
7979
- if (canUseArtifactCache) {
7980
- await writeArtifactCache(artifact, adapter);
7981
- }
7982
- return {
7983
- success: true,
7984
- artifact,
7985
- sourceCode: analysis.sourceCode,
7986
- sourceFiles: analysis.sourceFiles,
7987
- filePath: absolutePath,
7988
- playName: analysis.playName,
7989
- packagedFiles: discoveredFiles.files,
7990
- unresolvedFileReferences: discoveredFiles.unresolved,
7991
- importedPlayDependencies: analysis.importedPlayDependencies
7992
- };
7993
- } catch (error) {
7994
- if (error && typeof error === "object" && "errors" in error) {
7995
- const errors = Array.isArray(error.errors) ? error.errors.map(formatEsbuildMessage) : ["Play bundling failed."];
7996
- return {
7997
- success: false,
7998
- filePath: absolutePath,
7999
- errors
8000
- };
8001
- }
8002
- return {
8003
- success: false,
8004
- filePath: absolutePath,
8005
- errors: [error instanceof Error ? error.message : String(error)]
8006
- };
8007
- }
8008
- }
8009
-
8010
- // ../shared_libs/play-runtime/dedup-backend.ts
8011
- var PLAY_DEDUP_BACKENDS = {
8012
- inMemory: "in_memory",
8013
- neonTable: "neon_table",
8014
- durableObject: "durable_object"
8015
- };
8016
-
8017
- // ../shared_libs/play-runtime/scheduler-backend.ts
8018
- var PLAY_SCHEDULER_BACKENDS = {
8019
- temporal: "temporal",
8020
- cfWorkflows: "cf-workflows",
8021
- /**
8022
- * Private legacy id retained only so old persisted rows can be interpreted.
8023
- * It is not a selectable scheduler backend after the Hatchet hard cutover.
8024
- */
8025
- postgres: "postgres",
8026
- hatchet: "hatchet",
8027
- inProcess: "in-process"
8028
- };
8029
-
8030
- // ../shared_libs/play-runtime/providers.ts
8031
- var PLAY_RUNTIME_PROVIDER_IDS = {
8032
- workersEdge: "workers_edge",
8033
- hatchet: "hatchet",
8034
- local: "local"
8035
- };
8036
- var PLAY_RUNTIME_PROVIDERS = {
8037
- workers_edge: {
8038
- id: PLAY_RUNTIME_PROVIDER_IDS.workersEdge,
8039
- scheduler: PLAY_SCHEDULER_BACKENDS.cfWorkflows,
8040
- runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
8041
- dedup: PLAY_DEDUP_BACKENDS.durableObject,
8042
- artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
8043
- label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
8044
- },
8045
- hatchet: {
8046
- id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
8047
- scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
8048
- runner: PLAY_RUNTIME_BACKENDS.daytona,
8049
- dedup: PLAY_DEDUP_BACKENDS.durableObject,
8050
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
8051
- label: "Hatchet scheduler + one-shot Daytona runner + DO dedup"
8052
- },
8053
- local: {
8054
- id: PLAY_RUNTIME_PROVIDER_IDS.local,
8055
- scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
8056
- runner: PLAY_RUNTIME_BACKENDS.localProcess,
8057
- dedup: PLAY_DEDUP_BACKENDS.inMemory,
8058
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
8059
- label: "Local Temporal scheduler + local subprocess runner (tests)"
8060
- }
8061
- };
8062
- function defaultPlayRuntimeProvider() {
8063
- return PLAY_RUNTIME_PROVIDERS.workers_edge;
8064
- }
8065
- function resolvePlayRuntimeProvider(override) {
8066
- if (override?.trim()) {
8067
- const id = override.trim();
8068
- if (id in PLAY_RUNTIME_PROVIDERS) {
8069
- return PLAY_RUNTIME_PROVIDERS[id];
8070
- }
8071
- throw new Error(
8072
- `Unknown play runtime provider "${id}". Expected one of: ${Object.keys(
8073
- PLAY_RUNTIME_PROVIDERS
8074
- ).join(", ")}.`
8075
- );
8076
- }
8077
- return defaultPlayRuntimeProvider();
8078
- }
8079
-
8080
- // ../shared_libs/play-runtime/profiles.ts
8081
- var PLAY_EXECUTION_PROFILE_IDS = {
8082
- ...PLAY_RUNTIME_PROVIDER_IDS
8083
- };
8084
- var PLAY_EXECUTION_PROFILES = PLAY_RUNTIME_PROVIDERS;
8085
- function resolveExecutionProfile(override) {
8086
- try {
8087
- return resolvePlayRuntimeProvider(override);
8088
- } catch (error) {
8089
- if (override?.trim()) {
8090
- throw new Error(
8091
- `Unknown execution profile "${override.trim()}". Expected one of: ${Object.keys(
8092
- PLAY_EXECUTION_PROFILES
8093
- ).join(", ")}.`
8094
- );
8095
- }
8096
- throw error;
8097
- }
8098
- }
8099
-
8100
- // src/plays/local-file-discovery.ts
8101
- import { createHash as createHash2 } from "crypto";
8102
- import { readFile as readFile2, stat as stat2 } from "fs/promises";
8103
- import {
8104
- basename as basename2,
8105
- dirname as dirname7,
8106
- extname as extname2,
8107
- isAbsolute as isAbsolute2,
8108
- join as join6,
8109
- relative as relative2,
8110
- resolve as resolve7
8111
- } from "path";
8112
- var SOURCE_EXTENSIONS2 = [
8113
- ".ts",
8114
- ".tsx",
8115
- ".mts",
8116
- ".cts",
8117
- ".js",
8118
- ".jsx",
8119
- ".mjs",
8120
- ".cjs",
8121
- ".json"
8122
- ];
8123
- function sha2562(buffer) {
8124
- return createHash2("sha256").update(buffer).digest("hex");
8125
- }
8126
- function contentTypeForFile(filePath) {
8127
- const extension = extname2(filePath).toLowerCase();
8128
- if (extension === ".csv") return "text/csv";
8129
- if (extension === ".json") return "application/json";
8130
- if (extension === ".txt") return "text/plain";
8131
- return "application/octet-stream";
8132
- }
8133
- function stripCommentsToSpaces2(source) {
8134
- return source.replace(/\/\*[\s\S]*?\*\//g, (match) => match.replace(/[^\n]/g, " ")).replace(
8135
- /(^|[^:])\/\/.*$/gm,
8136
- (match, prefix) => prefix + " ".repeat(Math.max(0, match.length - prefix.length))
8137
- );
8138
- }
8139
- function unquoteStringLiteral2(literal) {
8140
- const trimmed = literal.trim();
8141
- const quote = trimmed[0];
8142
- if (quote !== '"' && quote !== "'" || trimmed[trimmed.length - 1] !== quote) {
8143
- return null;
8144
- }
8145
- try {
8146
- return JSON.parse(
8147
- quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
8148
- );
8149
- } catch {
8150
- return trimmed.slice(1, -1);
8151
- }
8152
- }
8153
- function splitTopLevelPlus(expression) {
8154
- const parts = [];
8155
- let start = 0;
8156
- let depth = 0;
8157
- let quote = null;
8158
- let escaped = false;
8159
- for (let index = 0; index < expression.length; index += 1) {
8160
- const char = expression[index];
8161
- if (quote) {
8162
- if (escaped) {
8163
- escaped = false;
8164
- } else if (char === "\\") {
8165
- escaped = true;
8166
- } else if (char === quote) {
8167
- quote = null;
8168
- }
8169
- continue;
8170
- }
8171
- if (char === '"' || char === "'" || char === "`") {
8172
- quote = char;
8173
- continue;
8174
- }
8175
- if (char === "(" || char === "[" || char === "{") depth += 1;
8176
- if (char === ")" || char === "]" || char === "}") depth -= 1;
8177
- if (char === "+" && depth === 0) {
8178
- parts.push(expression.slice(start, index));
8179
- start = index + 1;
8180
- }
8181
- }
8182
- if (parts.length === 0) return null;
8183
- parts.push(expression.slice(start));
8184
- return parts;
8185
- }
8186
- function stripOuterParens(expression) {
8187
- let value = expression.trim();
8188
- while (value.startsWith("(") && value.endsWith(")")) {
8189
- value = value.slice(1, -1).trim();
8190
- }
8191
- return value;
8192
- }
8193
- function isRuntimeInputExpression(expression) {
8194
- return /(^|[^\w$])input([^\w$]|$)/.test(expression);
8195
- }
8196
- function resolveStringExpression(expression, constants) {
8197
- const value = stripOuterParens(expression);
8198
- if (/^(['"])(?:\\.|(?!\1)[\s\S])*\1$/.test(value)) {
8199
- return unquoteStringLiteral2(value);
8200
- }
8201
- if (/^`(?:\\.|[^`$]|\$(?!\{))*`$/.test(value)) {
8202
- return value.slice(1, -1);
8203
- }
8204
- if (/^[A-Za-z_$][\w$]*$/.test(value)) {
8205
- return constants.get(value) ?? null;
8206
- }
8207
- const parts = splitTopLevelPlus(value);
8208
- if (parts) {
8209
- const resolved = parts.map(
8210
- (part) => resolveStringExpression(part, constants)
8211
- );
8212
- return resolved.every((part) => part != null) ? resolved.join("") : null;
8213
- }
8214
- return null;
8215
- }
8216
- function collectTopLevelStringConstants(sourceCode) {
8217
- const constants = /* @__PURE__ */ new Map();
8218
- const source = stripCommentsToSpaces2(sourceCode);
8219
- for (const match of source.matchAll(
8220
- /(?:^|\n)\s*const\s+([A-Za-z_$][\w$]*)\s*=\s*([^;\n]+)/g
8221
- )) {
8222
- const resolved = resolveStringExpression(match[2], constants);
8223
- if (resolved != null) {
8224
- constants.set(match[1], resolved);
8225
- }
8226
- }
8227
- return constants;
8228
- }
8229
- function findMatchingGenericEnd(source, openIndex) {
8230
- let depth = 0;
8231
- let quote = null;
8232
- let escaped = false;
8233
- for (let index = openIndex; index < source.length; index += 1) {
8234
- const char = source[index];
8235
- if (quote) {
8236
- if (escaped) {
8237
- escaped = false;
8238
- } else if (char === "\\") {
8239
- escaped = true;
8240
- } else if (char === quote) {
8241
- quote = null;
8242
- }
8243
- continue;
8244
- }
8245
- if (char === '"' || char === "'" || char === "`") {
8246
- quote = char;
8247
- continue;
8248
- }
8249
- if (char === "<") depth += 1;
8250
- if (char === ">") {
8251
- depth -= 1;
8252
- if (depth === 0) return index;
8253
- }
8254
- }
8255
- return -1;
8256
- }
8257
- function findCallOpenParen(source, afterCsvIndex) {
8258
- let index = afterCsvIndex;
8259
- while (/\s/.test(source[index] ?? "")) index += 1;
8260
- if (source[index] === "<") {
8261
- const genericEnd = findMatchingGenericEnd(source, index);
8262
- if (genericEnd < 0) return -1;
8263
- index = genericEnd + 1;
8264
- while (/\s/.test(source[index] ?? "")) index += 1;
8265
- }
8266
- return source[index] === "(" ? index : -1;
8267
- }
8268
- function firstCallArgument(source, openParen) {
8269
- let depth = 0;
8270
- let quote = null;
8271
- let escaped = false;
8272
- const start = openParen + 1;
8273
- for (let index = start; index < source.length; index += 1) {
8274
- const char = source[index];
8275
- if (quote) {
8276
- if (escaped) {
8277
- escaped = false;
8278
- } else if (char === "\\") {
8279
- escaped = true;
8280
- } else if (char === quote) {
8281
- quote = null;
8282
- }
8283
- continue;
8284
- }
8285
- if (char === '"' || char === "'" || char === "`") {
8286
- quote = char;
8287
- continue;
8288
- }
8289
- if (char === "(" || char === "[" || char === "{") depth += 1;
8290
- if (char === ")" && depth === 0) {
8291
- const text = source.slice(start, index).trim();
8292
- return text ? { text, start, end: index } : null;
8293
- }
8294
- if (char === "," && depth === 0) {
8295
- const text = source.slice(start, index).trim();
8296
- return text ? { text, start, end: index } : null;
8297
- }
8298
- if (char === ")" || char === "]" || char === "}") depth -= 1;
8299
- }
8300
- return null;
8301
- }
8302
- function localImportSpecifiers(sourceCode) {
8303
- const source = stripCommentsToSpaces2(sourceCode);
8304
- const specifiers = [];
8305
- for (const match of source.matchAll(
8306
- /\b(?:import|export)\s+(?!type\b)(?:[\s\S]*?\s+from\s*)?['"]([^'"]+)['"]/g
8307
- )) {
8308
- if (match[1]?.startsWith(".")) specifiers.push(match[1]);
8309
- }
8310
- for (const match of source.matchAll(
8311
- /\brequire\s*\(\s*(['"])(\.[^'"]*)\1\s*\)/g
8312
- )) {
8313
- specifiers.push(match[2]);
8314
- }
8315
- return specifiers;
8316
- }
8317
- async function fileExists2(filePath) {
8318
- try {
8319
- await stat2(filePath);
8320
- return true;
8321
- } catch {
8322
- return false;
8323
- }
8324
- }
8325
- function isPathInsideDirectory2(filePath, directory) {
8326
- const relativePath = relative2(directory, filePath);
8327
- return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute2(relativePath);
8328
- }
8329
- async function resolveLocalImport2(fromFile, specifier) {
8330
- const base = isAbsolute2(specifier) ? resolve7(specifier) : resolve7(dirname7(fromFile), specifier);
8331
- const candidates = [base];
8332
- const explicitExtension = extname2(base).toLowerCase();
8333
- if (!explicitExtension) {
8334
- candidates.push(
8335
- ...SOURCE_EXTENSIONS2.map((extension) => `${base}${extension}`)
8336
- );
8337
- candidates.push(
8338
- ...SOURCE_EXTENSIONS2.map((extension) => join6(base, `index${extension}`))
8339
- );
8340
- } else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
8341
- const stem = base.slice(0, -explicitExtension.length);
8342
- candidates.push(
8343
- ...SOURCE_EXTENSIONS2.map((extension) => `${stem}${extension}`)
8344
- );
8345
- }
8346
- for (const candidate of candidates) {
8347
- if (await fileExists2(candidate)) {
8348
- return candidate;
8349
- }
8350
- }
8351
- throw new Error(
8352
- `Could not resolve local import "${specifier}" from ${fromFile}`
8353
- );
8354
- }
8355
- async function discoverPackagedLocalFiles(entryFile) {
8356
- const absoluteEntryFile = resolve7(entryFile);
8357
- const packagingRoot = dirname7(absoluteEntryFile);
8358
- const files = /* @__PURE__ */ new Map();
8359
- const unresolved = [];
8360
- const visitedFiles = /* @__PURE__ */ new Set();
8361
- const visitSourceFile = async (filePath) => {
8362
- const absolutePath = resolve7(filePath);
8363
- if (visitedFiles.has(absolutePath)) {
8364
- return;
8365
- }
8366
- visitedFiles.add(absolutePath);
8367
- const sourceCode = await readFile2(absolutePath, "utf-8");
8368
- const scanSource = stripCommentsToSpaces2(sourceCode);
8369
- const constants = collectTopLevelStringConstants(sourceCode);
8370
- const childVisits = [];
8371
- for (const match of scanSource.matchAll(
8372
- /\b([A-Za-z_$][\w$]*)\s*\.\s*csv\b/g
8373
- )) {
8374
- const target = match[1];
8375
- if (target !== "ctx" && !target.endsWith("Ctx")) {
8376
- continue;
8377
- }
8378
- const openParen = findCallOpenParen(
8379
- scanSource,
8380
- match.index + match[0].length
8381
- );
8382
- if (openParen < 0) {
8383
- continue;
8384
- }
8385
- const argument = firstCallArgument(scanSource, openParen);
8386
- if (!argument) {
8387
- unresolved.push({
8388
- sourceFragment: "ctx.csv()",
8389
- message: "ctx.csv() requires a file path string or input reference."
8390
- });
8391
- } else if (!isRuntimeInputExpression(argument.text)) {
8392
- const resolvedPath = resolveStringExpression(argument.text, constants);
8393
- if (resolvedPath == null) {
8394
- unresolved.push({
8395
- sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
8396
- message: "Could not resolve this ctx.csv(...) path at submit time. Use a string literal, a top-level const string, or pass a runtime input like input.file."
8397
- });
8398
- } else {
8399
- const absoluteCsvPath = resolve7(dirname7(absolutePath), resolvedPath);
8400
- if (isAbsolute2(resolvedPath) || !isPathInsideDirectory2(absoluteCsvPath, packagingRoot)) {
8401
- unresolved.push({
8402
- sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
8403
- message: "ctx.csv(...) packaged file paths must be relative paths inside the play directory. Pass external files at runtime with input.file instead."
8404
- });
8405
- continue;
8406
- }
8407
- const buffer = await readFile2(absoluteCsvPath);
8408
- const stats = await stat2(absoluteCsvPath);
8409
- files.set(absoluteCsvPath, {
8410
- sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
8411
- logicalPath: resolvedPath,
8412
- absolutePath: absoluteCsvPath,
8413
- bytes: stats.size,
8414
- contentHash: sha2562(buffer),
8415
- contentType: contentTypeForFile(absoluteCsvPath)
8416
- });
8417
- }
8418
- }
8419
- }
8420
- for (const specifier of localImportSpecifiers(sourceCode)) {
8421
- childVisits.push(
8422
- resolveLocalImport2(absolutePath, specifier).then(
8423
- (resolvedImport) => visitSourceFile(resolvedImport)
8424
- )
8425
- );
8426
- }
8427
- await Promise.all(childVisits);
8428
- };
8429
- await visitSourceFile(absoluteEntryFile);
8430
- return {
8431
- files: [...files.values()],
8432
- unresolved
8433
- };
8434
- }
8435
-
8436
- // src/plays/bundle-play-file.ts
8437
- var PLAY_BUNDLE_CACHE_VERSION2 = 30;
8438
- var MODULE_DIR = dirname8(fileURLToPath(import.meta.url));
8439
- var SDK_PACKAGE_ROOT = resolve8(MODULE_DIR, "..", "..");
8440
- var SOURCE_REPO_ROOT = resolve8(SDK_PACKAGE_ROOT, "..");
8441
- var HAS_SOURCE_BUNDLING_SOURCES = existsSync7(
8442
- resolve8(SOURCE_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
8443
- );
8444
- var PACKAGED_REPO_ROOT = resolve8(SDK_PACKAGE_ROOT, "dist", "repo");
8445
- var HAS_PACKAGED_BUNDLING_SOURCES = existsSync7(
8446
- resolve8(PACKAGED_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
8447
- );
8448
- var PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? SOURCE_REPO_ROOT : HAS_PACKAGED_BUNDLING_SOURCES ? PACKAGED_REPO_ROOT : resolve8(SDK_PACKAGE_ROOT, "..");
8449
- var SDK_SOURCE_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? resolve8(SOURCE_REPO_ROOT, "sdk", "src") : HAS_PACKAGED_BUNDLING_SOURCES ? resolve8(PACKAGED_REPO_ROOT, "sdk", "src") : resolve8(SDK_PACKAGE_ROOT, "src");
8450
- var SDK_PACKAGE_JSON = resolve8(SDK_PACKAGE_ROOT, "package.json");
8451
- var SDK_ENTRY_FILE = resolve8(SDK_SOURCE_ROOT, "index.ts");
8452
- var SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : resolve8(SDK_PACKAGE_ROOT, "dist", "index.d.ts");
8453
- var SDK_WORKERS_ENTRY_FILE = resolve8(SDK_SOURCE_ROOT, "worker-play-entry.ts");
8454
- var WORKERS_HARNESS_ENTRY_FILE = resolve8(
8455
- PROJECT_ROOT,
8456
- "apps",
8457
- "play-runner-workers",
8458
- "src",
8459
- "entry.ts"
8460
- );
8461
- var WORKERS_HARNESS_FILES_DIR = resolve8(
8462
- PROJECT_ROOT,
8463
- "apps",
8464
- "play-runner-workers",
8465
- "src"
8466
- );
8467
- var hasWarnedAboutNonDevelopmentBundling = false;
8468
- function warnAboutNonDevelopmentBundling(filePath) {
8469
- if (hasWarnedAboutNonDevelopmentBundling) {
8470
- return;
8471
- }
8472
- const nodeEnv = String(process.env.NODE_ENV ?? "").trim().toLowerCase();
8473
- if (!nodeEnv || nodeEnv === "development" || nodeEnv === "test") {
8474
- return;
8475
- }
8476
- hasWarnedAboutNonDevelopmentBundling = true;
8477
- console.warn(
8478
- `[deepline] Warning: live play bundling was invoked while NODE_ENV=${nodeEnv} for ${filePath}. This source-first SDK path is intended for local development. For preview/production, run a published or prebuilt play reference instead of bundling source at runtime.`
8479
- );
8480
- console.warn(
8481
- '[deepline] Preferred production call pattern: client.play("person-to-email").run(...) or run a previously registered/published org play.'
8482
- );
8483
- }
8484
- function defaultPlayBundleTarget() {
8485
- return resolveExecutionProfile(null).artifactKind;
8486
- }
8487
- function createSdkPlayBundlingAdapter() {
8488
- return {
8489
- projectRoot: PROJECT_ROOT,
8490
- nodeModulesDir: resolve8(PROJECT_ROOT, "node_modules"),
8491
- cacheDir: join7(
8492
- tmpdir2(),
8493
- `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`
8494
- ),
8495
- sdkSourceRoot: SDK_SOURCE_ROOT,
8496
- sdkPackageJson: SDK_PACKAGE_JSON,
8497
- sdkEntryFile: SDK_ENTRY_FILE,
8498
- sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !existsSync7(SDK_TYPES_ENTRY_FILE) ? SDK_ENTRY_FILE : SDK_TYPES_ENTRY_FILE,
8499
- sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
8500
- workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
8501
- workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
8502
- workersRuntimeFingerprintDirs: [
8503
- resolve8(PROJECT_ROOT, "shared_libs", "play-runtime")
8504
- ],
8505
- discoverPackagedLocalFiles,
8506
- warnAboutNonDevelopmentBundling
8507
- };
8508
- }
8509
- async function bundlePlayFile2(filePath, options = {}) {
8510
- const result = await bundlePlayFile(filePath, {
8511
- target: options.target ?? defaultPlayBundleTarget(),
8512
- exportName: options.exportName,
8513
- adapter: createSdkPlayBundlingAdapter()
8514
- });
8515
- if (result.success)
8516
- validatePlaySourceFilesHaveNoInlineSecrets(result.sourceFiles);
8517
- return result;
8518
- }
8519
-
8520
- // src/cli/commands/plays/bootstrap.ts
8521
- import { closeSync, openSync, readSync, statSync, writeFileSync as writeFileSync7 } from "fs";
8522
- import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve9 } from "path";
8523
- import { parse as parseCsvSync } from "csv-parse/sync";
8524
-
8525
- // ../shared_libs/plays/bootstrap-routes.ts
8526
- var PLAY_BOOTSTRAP_TEMPLATES = [
8527
- "people-list",
8528
- "company-list",
8529
- "people-email",
8530
- "people-phone",
8531
- "company-people",
8532
- "company-people-email",
8533
- "company-people-phone"
8534
- ];
8535
- var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
8536
- var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
8537
- var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
8538
- email_finder: "email_finder",
8539
- phone_finder: "phone_finder"
8540
- };
8541
- var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
8542
- email_finder: "email",
8543
- phone_finder: "phone"
8544
- };
8545
- function isPlayBootstrapTemplate(value) {
8546
- return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
8547
- }
8548
- function formatPlayBootstrapTemplates() {
8549
- return PLAY_BOOTSTRAP_TEMPLATES.join("|");
8550
- }
8551
-
8552
- // src/cli/commands/plays/bootstrap.ts
8553
- function parseReferencedPlayTarget(target) {
8554
- const trimmed = target.trim();
8555
- const slashIndex = trimmed.indexOf("/");
8556
- if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
8557
- return { ownerSlug: null, playName: trimmed, unqualifiedPlayName: trimmed };
8558
- }
8559
- return {
8560
- ownerSlug: trimmed.slice(0, slashIndex),
8561
- playName: trimmed,
8562
- unqualifiedPlayName: trimmed.slice(slashIndex + 1)
8563
- };
8564
- }
8565
- function parsePositiveInteger2(value, flagName) {
8566
- const parsed = Number.parseInt(value, 10);
8567
- if (!Number.isFinite(parsed) || parsed <= 0) {
8568
- throw new PlayBootstrapUsageError(
8569
- `${flagName} must be a positive integer.`
8570
- );
8571
- }
8572
- return parsed;
8573
- }
8574
- function isRecord5(value) {
8575
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
8576
- }
8577
- function stringValue(value) {
8578
- return typeof value === "string" ? value.trim() : "";
8579
- }
8580
- function extractionEntries(value) {
8581
- if (Array.isArray(value)) return value.filter(isRecord5);
8582
- if (!isRecord5(value)) return [];
8583
- return Object.entries(value).map(
8584
- ([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
8585
- );
8586
- }
8587
- var PlayBootstrapError = class extends Error {
8588
- constructor(message, exitCode) {
8589
- super(message);
8590
- this.exitCode = exitCode;
8591
- }
8592
- exitCode;
8593
- };
8594
- var PlayBootstrapUsageError = class extends PlayBootstrapError {
8595
- constructor(message) {
8596
- super(message, 2);
8597
- }
8598
- };
8599
- var PlayBootstrapValidationError = class extends PlayBootstrapError {
8600
- constructor(message) {
8601
- super(message, 7);
8602
- }
8603
- };
8604
- var CSV_HEADER_SAMPLE_BYTES = 64 * 1024;
8605
- function parseCsvList(value) {
8606
- return value.split(",").map((item) => item.trim()).filter(Boolean);
8607
- }
8608
- function parseProviderList(value, flag) {
8609
- const providers = parseCsvList(value);
8610
- if (providers.length === 0) {
8611
- throw new PlayBootstrapUsageError(`${flag} provider list cannot be empty.`);
8612
- }
8613
- return providers;
6882
+ return providers;
8614
6883
  }
8615
6884
  function parseBootstrapPrefixedRef(value, flag) {
8616
6885
  const separatorIndex = value.indexOf(":");
@@ -8948,7 +7217,7 @@ function inferCsvColumnSpecs(headers, rows) {
8948
7217
  }));
8949
7218
  }
8950
7219
  function readCsvSample(csvPath) {
8951
- const resolvedPath = resolve9(csvPath);
7220
+ const resolvedPath = resolve6(csvPath);
8952
7221
  const size = statSync(resolvedPath).size;
8953
7222
  const fd = openSync(resolvedPath, "r");
8954
7223
  const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
@@ -9023,9 +7292,9 @@ ${properties}
9023
7292
  }
9024
7293
  function packagedCsvPathForPlay(csvPath) {
9025
7294
  const playDir = process.cwd();
9026
- const absoluteCsvPath = resolve9(csvPath);
9027
- const relativePath = relative3(playDir, absoluteCsvPath);
9028
- if (relativePath === "" || relativePath.startsWith("..") || isAbsolute3(relativePath)) {
7295
+ const absoluteCsvPath = resolve6(csvPath);
7296
+ const relativePath = relative(playDir, absoluteCsvPath);
7297
+ if (relativePath === "" || relativePath.startsWith("..") || isAbsolute(relativePath)) {
9029
7298
  throw new PlayBootstrapUsageError(
9030
7299
  `--from csv:${csvPath} must point to a file inside the directory where you run plays bootstrap. Run bootstrap from the intended play directory and write the play with --out there.`
9031
7300
  );
@@ -9944,8 +8213,8 @@ async function runPlayBootstrap(args) {
9944
8213
  ...csvContext
9945
8214
  });
9946
8215
  if (options.out) {
9947
- writeFileSync7(resolve9(options.out), source, "utf-8");
9948
- process.stdout.write(`Wrote ${resolve9(options.out)}
8216
+ writeFileSync7(resolve6(options.out), source, "utf-8");
8217
+ process.stdout.write(`Wrote ${resolve6(options.out)}
9949
8218
  `);
9950
8219
  return 0;
9951
8220
  }
@@ -10211,110 +8480,390 @@ async function traceCliSpan(phase, fields, run) {
10211
8480
  if (!isCliTraceEnabled()) {
10212
8481
  return run();
10213
8482
  }
10214
- const startedAt = Date.now();
8483
+ const startedAt = Date.now();
8484
+ try {
8485
+ const result = await run();
8486
+ recordCliTrace({
8487
+ phase,
8488
+ ms: Date.now() - startedAt,
8489
+ ok: true,
8490
+ ...fields
8491
+ });
8492
+ return result;
8493
+ } catch (error) {
8494
+ recordCliTrace({
8495
+ phase,
8496
+ ms: Date.now() - startedAt,
8497
+ ok: false,
8498
+ error: error instanceof Error ? error.message : String(error),
8499
+ ...fields
8500
+ });
8501
+ throw error;
8502
+ }
8503
+ }
8504
+
8505
+ // src/cli/play-check-hints.ts
8506
+ var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists .get() only works for declared Deepline getters listed by `deepline tools describe <tool> --json`. Use `toolExecutionResult.toolResponse.raw` for provider/tool-specific fields.";
8507
+ var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Use `.peek(n)` for a small preview or `.materialize()` when you intentionally need rows in memory; do not use `.rows`, `.toArray()`, or array methods directly on the dataset handle.";
8508
+ var ROW_PROPERTY_HINT = "Deepline hint: this row type only contains fields produced by the CSV/schema and previous map steps. Check source column casing and the exact output field names from earlier steps before scaling.";
8509
+ var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for replay-safe receipts.";
8510
+ var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or map-backed batch plays must be run directly, exported, then consumed by a separate play.";
8511
+ var MAP_BACKED_CHILD_HINT = "Deepline hint: map-backed child plays own durable table state and cannot be called from another play. Run that play directly, export its dataset, then pass the CSV to the next play.";
8512
+ function sourceLineForError(sourceCode, error) {
8513
+ const match = error.match(/:(\d+):(\d+)\s/);
8514
+ const lineNumber = match?.[1] ? Number(match[1]) : NaN;
8515
+ if (!Number.isInteger(lineNumber) || lineNumber < 1) return "";
8516
+ return sourceCode.split(/\r?\n/)[lineNumber - 1] ?? "";
8517
+ }
8518
+ function looksLikeInvalidExtractedGetter(error, sourceLine) {
8519
+ if (!/Property '[^']+' does not exist on type/.test(error)) return false;
8520
+ return /\bextracted(?:Values|Lists)\s*\./.test(sourceLine);
8521
+ }
8522
+ function looksLikeDatasetApiMisuse(error, sourceLine) {
8523
+ return /Property '(?:rows|toArray|forEach|map|filter|reduce)' does not exist on type '[^']*PlayDataset/.test(
8524
+ error
8525
+ ) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
8526
+ sourceLine
8527
+ );
8528
+ }
8529
+ function looksLikeRowPropertyMismatch(error, sourceLine) {
8530
+ if (!/Property '[^']+' does not exist on type/.test(error)) return false;
8531
+ if (looksLikeInvalidExtractedGetter(error, sourceLine)) return false;
8532
+ return /\brow\.[A-Za-z_][A-Za-z0-9_]*/.test(sourceLine);
8533
+ }
8534
+ function looksLikeToolsExecuteSignature(error, sourceLine) {
8535
+ return /ctx\.tools\.execute requires a request object/i.test(error) || /Expected 1 arguments?, but got [2-9]/.test(error) && /\btools\.execute\(/.test(sourceLine);
8536
+ }
8537
+ function looksLikeRunPlaySignature(error, sourceLine) {
8538
+ return /ctx\.runPlay/i.test(error) || /(?:Expected|Argument of type|No overload matches)/.test(error) && /\brunPlay\(/.test(sourceLine);
8539
+ }
8540
+ function looksLikeMapBackedChild(error) {
8541
+ return /map-backed child play|direct-run-only|cannot call a map-backed|own durable table/i.test(
8542
+ error
8543
+ );
8544
+ }
8545
+ function hintForError(error, sourceLine) {
8546
+ if (looksLikeInvalidExtractedGetter(error, sourceLine)) {
8547
+ return EXTRACTED_GETTER_ERROR_HINT;
8548
+ }
8549
+ if (looksLikeDatasetApiMisuse(error, sourceLine)) {
8550
+ return DATASET_API_HINT;
8551
+ }
8552
+ if (looksLikeToolsExecuteSignature(error, sourceLine)) {
8553
+ return TOOLS_EXECUTE_SIGNATURE_HINT;
8554
+ }
8555
+ if (looksLikeMapBackedChild(error)) {
8556
+ return MAP_BACKED_CHILD_HINT;
8557
+ }
8558
+ if (looksLikeRunPlaySignature(error, sourceLine)) {
8559
+ return RUN_PLAY_SIGNATURE_HINT;
8560
+ }
8561
+ if (looksLikeRowPropertyMismatch(error, sourceLine)) {
8562
+ return ROW_PROPERTY_HINT;
8563
+ }
8564
+ return null;
8565
+ }
8566
+ function addPlayCheckRepairHints(input2) {
8567
+ const addedHints = /* @__PURE__ */ new Set();
8568
+ return input2.errors.map((error) => {
8569
+ const line = sourceLineForError(input2.sourceCode, error);
8570
+ const hint = hintForError(error, line);
8571
+ if (!hint || addedHints.has(hint) || error.includes(hint)) {
8572
+ return error;
8573
+ }
8574
+ addedHints.add(hint);
8575
+ return `${error}
8576
+ ${hint}`;
8577
+ });
8578
+ }
8579
+
8580
+ // ../shared_libs/play-runtime/backend.ts
8581
+ var PLAY_RUNTIME_BACKENDS = {
8582
+ localProcess: "local_process",
8583
+ daytona: "daytona",
8584
+ // Artifact/runtime contract for Cloudflare Dynamic Workers. This is no
8585
+ // longer a standalone runner backend; use profile=workers_edge so the
8586
+ // cf-workflows scheduler owns loading and execution.
8587
+ cloudflareWorkers: "cloudflare_workers"
8588
+ };
8589
+ var PLAY_ARTIFACT_KINDS = {
8590
+ cjsNode20: "cjs_node20",
8591
+ esmWorkers: "esm_workers"
8592
+ };
8593
+ var PLAY_BACKEND_DESCRIPTORS = {
8594
+ [PLAY_RUNTIME_BACKENDS.localProcess]: {
8595
+ id: PLAY_RUNTIME_BACKENDS.localProcess,
8596
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
8597
+ label: "Local node subprocess"
8598
+ },
8599
+ [PLAY_RUNTIME_BACKENDS.daytona]: {
8600
+ id: PLAY_RUNTIME_BACKENDS.daytona,
8601
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
8602
+ label: "Daytona sandbox"
8603
+ },
8604
+ [PLAY_RUNTIME_BACKENDS.cloudflareWorkers]: {
8605
+ id: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
8606
+ artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
8607
+ label: "Cloudflare Dynamic Workers"
8608
+ }
8609
+ };
8610
+
8611
+ // ../shared_libs/play-runtime/dedup-backend.ts
8612
+ var PLAY_DEDUP_BACKENDS = {
8613
+ inMemory: "in_memory",
8614
+ neonTable: "neon_table",
8615
+ durableObject: "durable_object"
8616
+ };
8617
+
8618
+ // ../shared_libs/play-runtime/scheduler-backend.ts
8619
+ var PLAY_SCHEDULER_BACKENDS = {
8620
+ temporal: "temporal",
8621
+ cfWorkflows: "cf-workflows",
8622
+ /**
8623
+ * Private legacy id retained only so old persisted rows can be interpreted.
8624
+ * It is not a selectable scheduler backend after the Hatchet hard cutover.
8625
+ */
8626
+ postgres: "postgres",
8627
+ hatchet: "hatchet",
8628
+ inProcess: "in-process"
8629
+ };
8630
+
8631
+ // ../shared_libs/play-runtime/providers.ts
8632
+ var PLAY_RUNTIME_PROVIDER_IDS = {
8633
+ workersEdge: "workers_edge",
8634
+ hatchet: "hatchet",
8635
+ local: "local"
8636
+ };
8637
+ var PLAY_RUNTIME_PROVIDERS = {
8638
+ workers_edge: {
8639
+ id: PLAY_RUNTIME_PROVIDER_IDS.workersEdge,
8640
+ scheduler: PLAY_SCHEDULER_BACKENDS.cfWorkflows,
8641
+ runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
8642
+ dedup: PLAY_DEDUP_BACKENDS.durableObject,
8643
+ artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
8644
+ label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
8645
+ },
8646
+ hatchet: {
8647
+ id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
8648
+ scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
8649
+ runner: PLAY_RUNTIME_BACKENDS.daytona,
8650
+ dedup: PLAY_DEDUP_BACKENDS.durableObject,
8651
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
8652
+ label: "Hatchet scheduler + one-shot Daytona runner + DO dedup"
8653
+ },
8654
+ local: {
8655
+ id: PLAY_RUNTIME_PROVIDER_IDS.local,
8656
+ scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
8657
+ runner: PLAY_RUNTIME_BACKENDS.localProcess,
8658
+ dedup: PLAY_DEDUP_BACKENDS.inMemory,
8659
+ artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
8660
+ label: "Local Temporal scheduler + local subprocess runner (tests)"
8661
+ }
8662
+ };
8663
+ function defaultPlayRuntimeProvider() {
8664
+ return PLAY_RUNTIME_PROVIDERS.workers_edge;
8665
+ }
8666
+ function resolvePlayRuntimeProvider(override) {
8667
+ if (override?.trim()) {
8668
+ const id = override.trim();
8669
+ if (id in PLAY_RUNTIME_PROVIDERS) {
8670
+ return PLAY_RUNTIME_PROVIDERS[id];
8671
+ }
8672
+ throw new Error(
8673
+ `Unknown play runtime provider "${id}". Expected one of: ${Object.keys(
8674
+ PLAY_RUNTIME_PROVIDERS
8675
+ ).join(", ")}.`
8676
+ );
8677
+ }
8678
+ return defaultPlayRuntimeProvider();
8679
+ }
8680
+
8681
+ // ../shared_libs/play-runtime/profiles.ts
8682
+ var PLAY_EXECUTION_PROFILE_IDS = {
8683
+ ...PLAY_RUNTIME_PROVIDER_IDS
8684
+ };
8685
+ var PLAY_EXECUTION_PROFILES = PLAY_RUNTIME_PROVIDERS;
8686
+ function resolveExecutionProfile(override) {
10215
8687
  try {
10216
- const result = await run();
10217
- recordCliTrace({
10218
- phase,
10219
- ms: Date.now() - startedAt,
10220
- ok: true,
10221
- ...fields
10222
- });
10223
- return result;
8688
+ return resolvePlayRuntimeProvider(override);
10224
8689
  } catch (error) {
10225
- recordCliTrace({
10226
- phase,
10227
- ms: Date.now() - startedAt,
10228
- ok: false,
10229
- error: error instanceof Error ? error.message : String(error),
10230
- ...fields
10231
- });
8690
+ if (override?.trim()) {
8691
+ throw new Error(
8692
+ `Unknown execution profile "${override.trim()}". Expected one of: ${Object.keys(
8693
+ PLAY_EXECUTION_PROFILES
8694
+ ).join(", ")}.`
8695
+ );
8696
+ }
10232
8697
  throw error;
10233
8698
  }
10234
8699
  }
10235
8700
 
10236
- // src/cli/play-check-hints.ts
10237
- var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists .get() only works for declared Deepline getters listed by `deepline tools describe <tool> --json`. Use `toolExecutionResult.toolResponse.raw` for provider/tool-specific fields.";
10238
- var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Use `.peek(n)` for a small preview or `.materialize()` when you intentionally need rows in memory; do not use `.rows`, `.toArray()`, or array methods directly on the dataset handle.";
10239
- var ROW_PROPERTY_HINT = "Deepline hint: this row type only contains fields produced by the CSV/schema and previous map steps. Check source column casing and the exact output field names from earlier steps before scaling.";
10240
- var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for replay-safe receipts.";
10241
- var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or map-backed batch plays must be run directly, exported, then consumed by a separate play.";
10242
- var MAP_BACKED_CHILD_HINT = "Deepline hint: map-backed child plays own durable table state and cannot be called from another play. Run that play directly, export its dataset, then pass the CSV to the next play.";
10243
- function sourceLineForError(sourceCode, error) {
10244
- const match = error.match(/:(\d+):(\d+)\s/);
10245
- const lineNumber = match?.[1] ? Number(match[1]) : NaN;
10246
- if (!Number.isInteger(lineNumber) || lineNumber < 1) return "";
10247
- return sourceCode.split(/\r?\n/)[lineNumber - 1] ?? "";
10248
- }
10249
- function looksLikeInvalidExtractedGetter(error, sourceLine) {
10250
- if (!/Property '[^']+' does not exist on type/.test(error)) return false;
10251
- return /\bextracted(?:Values|Lists)\s*\./.test(sourceLine);
10252
- }
10253
- function looksLikeDatasetApiMisuse(error, sourceLine) {
10254
- return /Property '(?:rows|toArray|forEach|map|filter|reduce)' does not exist on type '[^']*PlayDataset/.test(
10255
- error
10256
- ) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
10257
- sourceLine
10258
- );
10259
- }
10260
- function looksLikeRowPropertyMismatch(error, sourceLine) {
10261
- if (!/Property '[^']+' does not exist on type/.test(error)) return false;
10262
- if (looksLikeInvalidExtractedGetter(error, sourceLine)) return false;
10263
- return /\brow\.[A-Za-z_][A-Za-z0-9_]*/.test(sourceLine);
10264
- }
10265
- function looksLikeToolsExecuteSignature(error, sourceLine) {
10266
- return /ctx\.tools\.execute requires a request object/i.test(error) || /Expected 1 arguments?, but got [2-9]/.test(error) && /\btools\.execute\(/.test(sourceLine);
10267
- }
10268
- function looksLikeRunPlaySignature(error, sourceLine) {
10269
- return /ctx\.runPlay/i.test(error) || /(?:Expected|Argument of type|No overload matches)/.test(error) && /\brunPlay\(/.test(sourceLine);
8701
+ // ../shared_libs/play-runtime/internal-step-ids.ts
8702
+ var INTERNAL_GLUE_NODE_ID_PREFIX = "run_javascript:";
8703
+ function isInternalGlueStepId(stepId) {
8704
+ return typeof stepId === "string" && stepId.startsWith(INTERNAL_GLUE_NODE_ID_PREFIX);
10270
8705
  }
10271
- function looksLikeMapBackedChild(error) {
10272
- return /map-backed child play|direct-run-only|cannot call a map-backed|own durable table/i.test(
10273
- error
10274
- );
8706
+
8707
+ // src/cli/commands/play.ts
8708
+ var PLAY_BUNDLER_MODULE_PATHS = [
8709
+ // Built CLI bundle: dist/cli/index.mjs -> dist/plays/bundle-play-file.mjs.
8710
+ ["..", "plays", "bundle-play-file.mjs"].join("/"),
8711
+ // Source CLI: src/cli/commands/play.ts -> src/plays/bundle-play-file.ts.
8712
+ ["..", "..", "plays", "bundle-play-file.js"].join("/")
8713
+ ];
8714
+ var playBundlerPromise = null;
8715
+ async function loadPlayBundler() {
8716
+ playBundlerPromise ??= (async () => {
8717
+ const errors = [];
8718
+ for (const modulePath of PLAY_BUNDLER_MODULE_PATHS) {
8719
+ try {
8720
+ return await import(modulePath);
8721
+ } catch (error) {
8722
+ errors.push(
8723
+ `${modulePath}: ${error instanceof Error ? error.message : String(error)}`
8724
+ );
8725
+ }
8726
+ }
8727
+ playBundlerPromise = null;
8728
+ throw new Error(
8729
+ `Local play-file bundling is unavailable in this Deepline SDK install. Reinstall the package, or run a saved/prebuilt play by name while you repair the install. Bundler load failed: ${errors.join("; ")}`
8730
+ );
8731
+ })();
8732
+ return playBundlerPromise;
10275
8733
  }
10276
- function hintForError(error, sourceLine) {
10277
- if (looksLikeInvalidExtractedGetter(error, sourceLine)) {
10278
- return EXTRACTED_GETTER_ERROR_HINT;
10279
- }
10280
- if (looksLikeDatasetApiMisuse(error, sourceLine)) {
10281
- return DATASET_API_HINT;
10282
- }
10283
- if (looksLikeToolsExecuteSignature(error, sourceLine)) {
10284
- return TOOLS_EXECUTE_SIGNATURE_HINT;
10285
- }
10286
- if (looksLikeMapBackedChild(error)) {
10287
- return MAP_BACKED_CHILD_HINT;
10288
- }
10289
- if (looksLikeRunPlaySignature(error, sourceLine)) {
10290
- return RUN_PLAY_SIGNATURE_HINT;
8734
+ function stripCommentsToSpaces(source) {
8735
+ let output2 = "";
8736
+ let quote = null;
8737
+ let escaped = false;
8738
+ let lineComment = false;
8739
+ let blockComment = false;
8740
+ for (let index = 0; index < source.length; index += 1) {
8741
+ const char = source[index];
8742
+ const next = source[index + 1];
8743
+ if (lineComment) {
8744
+ if (char === "\n" || char === "\r") {
8745
+ lineComment = false;
8746
+ output2 += char;
8747
+ } else {
8748
+ output2 += " ";
8749
+ }
8750
+ continue;
8751
+ }
8752
+ if (blockComment) {
8753
+ if (char === "*" && next === "/") {
8754
+ output2 += " ";
8755
+ index += 1;
8756
+ blockComment = false;
8757
+ } else {
8758
+ output2 += char === "\n" || char === "\r" ? char : " ";
8759
+ }
8760
+ continue;
8761
+ }
8762
+ if (quote) {
8763
+ output2 += char;
8764
+ if (escaped) {
8765
+ escaped = false;
8766
+ } else if (char === "\\") {
8767
+ escaped = true;
8768
+ } else if (char === quote) {
8769
+ quote = null;
8770
+ }
8771
+ continue;
8772
+ }
8773
+ if (char === '"' || char === "'" || char === "`") {
8774
+ quote = char;
8775
+ output2 += char;
8776
+ continue;
8777
+ }
8778
+ if (char === "/" && next === "/") {
8779
+ output2 += " ";
8780
+ index += 1;
8781
+ lineComment = true;
8782
+ continue;
8783
+ }
8784
+ if (char === "/" && next === "*") {
8785
+ output2 += " ";
8786
+ index += 1;
8787
+ blockComment = true;
8788
+ continue;
8789
+ }
8790
+ output2 += char;
10291
8791
  }
10292
- if (looksLikeRowPropertyMismatch(error, sourceLine)) {
10293
- return ROW_PROPERTY_HINT;
8792
+ return output2;
8793
+ }
8794
+ function unquotePlayNameLiteral(raw) {
8795
+ if (raw.length < 2) return null;
8796
+ const quote = raw[0];
8797
+ let value = "";
8798
+ for (let index = 1; index < raw.length - 1; index += 1) {
8799
+ const char = raw[index];
8800
+ if (char !== "\\") {
8801
+ value += char;
8802
+ continue;
8803
+ }
8804
+ index += 1;
8805
+ const escaped = raw[index];
8806
+ if (escaped === void 0) return null;
8807
+ value += escaped === "n" ? "\n" : escaped === "r" ? "\r" : escaped === "t" ? " " : escaped;
10294
8808
  }
10295
- return null;
8809
+ if (quote === "`" && value.includes("${")) return null;
8810
+ return value;
10296
8811
  }
10297
- function addPlayCheckRepairHints(input2) {
10298
- const addedHints = /* @__PURE__ */ new Set();
10299
- return input2.errors.map((error) => {
10300
- const line = sourceLineForError(input2.sourceCode, error);
10301
- const hint = hintForError(error, line);
10302
- if (!hint || addedHints.has(hint) || error.includes(hint)) {
10303
- return error;
8812
+ function findMatchingBrace(source, openIndex) {
8813
+ let depth = 0;
8814
+ let quote = null;
8815
+ let escaped = false;
8816
+ for (let index = openIndex; index < source.length; index += 1) {
8817
+ const char = source[index];
8818
+ if (quote) {
8819
+ if (escaped) {
8820
+ escaped = false;
8821
+ } else if (char === "\\") {
8822
+ escaped = true;
8823
+ } else if (char === quote) {
8824
+ quote = null;
8825
+ }
8826
+ continue;
10304
8827
  }
10305
- addedHints.add(hint);
10306
- return `${error}
10307
- ${hint}`;
10308
- });
8828
+ if (char === '"' || char === "'" || char === "`") {
8829
+ quote = char;
8830
+ continue;
8831
+ }
8832
+ if (char === "{") depth += 1;
8833
+ if (char === "}") {
8834
+ depth -= 1;
8835
+ if (depth === 0) return index;
8836
+ }
8837
+ }
8838
+ return -1;
10309
8839
  }
10310
-
10311
- // ../shared_libs/play-runtime/internal-step-ids.ts
10312
- var INTERNAL_GLUE_NODE_ID_PREFIX = "run_javascript:";
10313
- function isInternalGlueStepId(stepId) {
10314
- return typeof stepId === "string" && stepId.startsWith(INTERNAL_GLUE_NODE_ID_PREFIX);
8840
+ function extractDefinedPlayName(code) {
8841
+ const source = stripCommentsToSpaces(code);
8842
+ const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
8843
+ for (const match of source.matchAll(callPattern)) {
8844
+ const openParen = match.index + match[0].length - 1;
8845
+ const firstArgStart = openParen + 1;
8846
+ const firstNonSpace = source.slice(firstArgStart).search(/\S/);
8847
+ if (firstNonSpace < 0) continue;
8848
+ const argIndex = firstArgStart + firstNonSpace;
8849
+ const quote = source[argIndex];
8850
+ if (quote === '"' || quote === "'" || quote === "`") {
8851
+ const literalMatch = source.slice(argIndex).match(/^(['"`])(?:\\.|(?!\1)[\s\S])*\1/);
8852
+ const value2 = literalMatch ? unquotePlayNameLiteral(literalMatch[0]) : null;
8853
+ if (value2?.trim()) return value2.trim();
8854
+ }
8855
+ if (quote !== "{") continue;
8856
+ const closeBrace = findMatchingBrace(source, argIndex);
8857
+ if (closeBrace < 0) continue;
8858
+ const objectSource = source.slice(argIndex + 1, closeBrace);
8859
+ const idMatch = objectSource.match(
8860
+ /(?:^|[,{\s])(?:id|name|['"](?:id|name)['"])\s*:\s*(['"`])((?:\\.|(?!\1)[\s\S])*)\1/
8861
+ );
8862
+ const value = idMatch ? unquotePlayNameLiteral(`${idMatch[1]}${idMatch[2]}${idMatch[1]}`) : null;
8863
+ if (value?.trim()) return value.trim();
8864
+ }
8865
+ return null;
10315
8866
  }
10316
-
10317
- // src/cli/commands/play.ts
10318
8867
  var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
10319
8868
  "--json",
10320
8869
  "--wait",
@@ -10349,7 +8898,7 @@ function traceCliSync(phase, fields, run) {
10349
8898
  }
10350
8899
  }
10351
8900
  function sleep5(ms) {
10352
- return new Promise((resolve16) => setTimeout(resolve16, ms));
8901
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
10353
8902
  }
10354
8903
  function parseReferencedPlayTarget2(target) {
10355
8904
  const trimmed = target.trim();
@@ -10393,7 +8942,7 @@ function formatPlayListReference(play) {
10393
8942
  return play.reference || play.name;
10394
8943
  }
10395
8944
  function defaultMaterializedPlayPath(reference) {
10396
- return resolve10(defaultStarterPlayPath(reference));
8945
+ return resolve7(defaultStarterPlayPath(reference));
10397
8946
  }
10398
8947
  function defaultStarterPlayPath(reference) {
10399
8948
  const playName = parseReferencedPlayTarget2(reference).unqualifiedPlayName;
@@ -10419,8 +8968,8 @@ function materializeRemotePlaySource(input2) {
10419
8968
  return null;
10420
8969
  }
10421
8970
  const outputPath = input2.outPath ?? defaultMaterializedPlayPath(input2.playName);
10422
- if (existsSync8(outputPath)) {
10423
- const existingSource = readFileSync7(outputPath, "utf-8");
8971
+ if (existsSync6(outputPath)) {
8972
+ const existingSource = readFileSync6(outputPath, "utf-8");
10424
8973
  if (existingSource === input2.sourceCode) {
10425
8974
  return { path: outputPath, status: "unchanged", created: false };
10426
8975
  }
@@ -10472,7 +9021,7 @@ function extractPlayName(code, filePath) {
10472
9021
  throw buildMissingDefinePlayError(filePath);
10473
9022
  }
10474
9023
  function isFileTarget(target) {
10475
- return existsSync8(resolve10(target));
9024
+ return existsSync6(resolve7(target));
10476
9025
  }
10477
9026
  function looksLikeRunId(target) {
10478
9027
  return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
@@ -10501,7 +9050,7 @@ function parsePositiveInteger3(value, flagName) {
10501
9050
  return parsed;
10502
9051
  }
10503
9052
  function parseJsonInput(raw) {
10504
- const source = raw.startsWith("@") ? readFileSync7(resolve10(raw.slice(1)), "utf-8") : raw;
9053
+ const source = raw.startsWith("@") ? readFileSync6(resolve7(raw.slice(1)), "utf-8") : raw;
10505
9054
  const parsed = JSON.parse(source);
10506
9055
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
10507
9056
  throw new Error("--input must be a JSON object.");
@@ -10603,7 +9152,7 @@ function fileInputBindingsFromStaticPipeline(staticPipeline) {
10603
9152
  function isLocalFilePathValue(value) {
10604
9153
  if (typeof value !== "string" || !value.trim()) return false;
10605
9154
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
10606
- return existsSync8(resolve10(value));
9155
+ return existsSync6(resolve7(value));
10607
9156
  }
10608
9157
  function inputContainsLocalFilePath(value) {
10609
9158
  if (isLocalFilePathValue(value)) {
@@ -10650,7 +9199,7 @@ function collectLocalFileInputRefs(value, inputPath, key, out) {
10650
9199
  const looksLikeFile = /\.[a-z0-9]{1,8}$/i.test(trimmed);
10651
9200
  if (keyIsCsvData) {
10652
9201
  out.push({ inputPath, value: trimmed, isCsvData: true });
10653
- } else if (endsWithCsv || looksLikeFile && existsSync8(resolve10(trimmed))) {
9202
+ } else if (endsWithCsv || looksLikeFile && existsSync6(resolve7(trimmed))) {
10654
9203
  out.push({ inputPath, value: trimmed, isCsvData: false });
10655
9204
  }
10656
9205
  return;
@@ -10692,8 +9241,8 @@ function preflightLocalFileInputs(runtimeInput) {
10692
9241
  collectLocalFileInputRefs(value, key, key, refs);
10693
9242
  }
10694
9243
  for (const ref of refs) {
10695
- const absolutePath = resolve10(ref.value);
10696
- if (!existsSync8(absolutePath)) {
9244
+ const absolutePath = resolve7(ref.value);
9245
+ if (!existsSync6(absolutePath)) {
10697
9246
  throw new DeeplineError(
10698
9247
  `Input ${ref.inputPath} references a local file that does not exist: ${ref.value} (resolved to ${absolutePath}). No run was created.`,
10699
9248
  void 0,
@@ -10701,9 +9250,9 @@ function preflightLocalFileInputs(runtimeInput) {
10701
9250
  { inputPath: ref.inputPath, path: ref.value, resolved: absolutePath }
10702
9251
  );
10703
9252
  }
10704
- let stat4;
9253
+ let stat2;
10705
9254
  try {
10706
- stat4 = statSync2(absolutePath);
9255
+ stat2 = statSync2(absolutePath);
10707
9256
  } catch (error) {
10708
9257
  throw new DeeplineError(
10709
9258
  `Input ${ref.inputPath} references a local file that is not readable: ${ref.value} (${error instanceof Error ? error.message : String(error)}). No run was created.`,
@@ -10712,7 +9261,7 @@ function preflightLocalFileInputs(runtimeInput) {
10712
9261
  { inputPath: ref.inputPath, path: ref.value }
10713
9262
  );
10714
9263
  }
10715
- if (!stat4.isFile()) {
9264
+ if (!stat2.isFile()) {
10716
9265
  throw new DeeplineError(
10717
9266
  `Input ${ref.inputPath} references ${ref.value}, which is not a file. No run was created.`,
10718
9267
  void 0,
@@ -10729,7 +9278,7 @@ function preflightLocalFileInputs(runtimeInput) {
10729
9278
  function preflightCsvDataInput(ref, absolutePath) {
10730
9279
  let content;
10731
9280
  try {
10732
- content = readFileSync7(absolutePath, "utf-8");
9281
+ content = readFileSync6(absolutePath, "utf-8");
10733
9282
  } catch (error) {
10734
9283
  throw new DeeplineError(
10735
9284
  `Input ${ref.inputPath} CSV ${ref.value} is not readable: ${error instanceof Error ? error.message : String(error)}. No run was created.`,
@@ -10811,8 +9360,8 @@ async function stageFileInputArgs(input2) {
10811
9360
  const localFiles = uniqueBindings.flatMap((binding) => {
10812
9361
  const value = getDottedInputValue(input2.runtimeInput, binding.inputPath);
10813
9362
  if (!isLocalFilePathValue(value)) return [];
10814
- const absolutePath = resolve10(value);
10815
- return [{ binding, absolutePath, logicalPath: basename3(absolutePath) }];
9363
+ const absolutePath = resolve7(value);
9364
+ return [{ binding, absolutePath, logicalPath: basename(absolutePath) }];
10816
9365
  });
10817
9366
  if (localFiles.length === 0) {
10818
9367
  return { inputFile: null, packagedFiles: [] };
@@ -10844,20 +9393,20 @@ async function stageFileInputArgs(input2) {
10844
9393
  };
10845
9394
  }
10846
9395
  function stageFile(logicalPath, absolutePath) {
10847
- const buffer = readFileSync7(absolutePath);
9396
+ const buffer = readFileSync6(absolutePath);
10848
9397
  return {
10849
9398
  logicalPath,
10850
9399
  contentBase64: buffer.toString("base64"),
10851
- contentHash: createHash3("sha256").update(buffer).digest("hex"),
9400
+ contentHash: createHash("sha256").update(buffer).digest("hex"),
10852
9401
  contentType: absolutePath.toLowerCase().endsWith(".csv") ? "text/csv" : absolutePath.toLowerCase().endsWith(".json") ? "application/json" : "application/octet-stream",
10853
9402
  bytes: buffer.byteLength
10854
9403
  };
10855
9404
  }
10856
9405
  function normalizePlayPath(filePath) {
10857
9406
  try {
10858
- return realpathSync.native(resolve10(filePath));
9407
+ return realpathSync.native(resolve7(filePath));
10859
9408
  } catch {
10860
- return resolve10(filePath);
9409
+ return resolve7(filePath);
10861
9410
  }
10862
9411
  }
10863
9412
  function formatBundlingErrors(filePath, errors) {
@@ -10868,6 +9417,7 @@ function formatUnresolvedPackagedFiles(filePath, unresolvedFileReferences) {
10868
9417
  return `Failed to package local ctx.csv(...) files in ${filePath}: ${details}`;
10869
9418
  }
10870
9419
  async function collectBundledPlayGraph(entryFile, profile = null) {
9420
+ const playBundler = await loadPlayBundler();
10871
9421
  const nodes = /* @__PURE__ */ new Map();
10872
9422
  const visiting = /* @__PURE__ */ new Set();
10873
9423
  const artifactKind = resolveExecutionProfile(profile).artifactKind;
@@ -10884,7 +9434,7 @@ async function collectBundledPlayGraph(entryFile, profile = null) {
10884
9434
  }
10885
9435
  visiting.add(absolutePath);
10886
9436
  try {
10887
- const bundleResult = await bundlePlayFile2(absolutePath, {
9437
+ const bundleResult = await playBundler.bundlePlayFile(absolutePath, {
10888
9438
  target: artifactKind
10889
9439
  });
10890
9440
  if (bundleResult.success === false) {
@@ -11508,6 +10058,7 @@ async function waitForPlayCompletionByStream(input2) {
11508
10058
  input2.workflowId,
11509
10059
  {
11510
10060
  signal: controller.signal,
10061
+ fallback: "none",
11511
10062
  onNotice: input2.jsonOutput ? void 0 : (message) => input2.progress.writeLine(message)
11512
10063
  }
11513
10064
  )) {
@@ -12521,15 +11072,15 @@ function formatDatasetStatsLines(datasetStats, indent2 = " ") {
12521
11072
  return [];
12522
11073
  }
12523
11074
  const lines = [`${indent2}summary:`];
12524
- for (const [column, stat4] of Object.entries(datasetStats.columnStats).slice(
11075
+ for (const [column, stat2] of Object.entries(datasetStats.columnStats).slice(
12525
11076
  0,
12526
11077
  12
12527
11078
  )) {
12528
- const topValues = stat4.top_values ? `, top_values=${Object.entries(stat4.top_values).slice(0, 3).map(([value, count]) => `${value}=${count}`).join(", ")}` : "";
12529
- const sample = stat4.sample_value !== void 0 ? `, sample_value=${JSON.stringify(stat4.sample_value)}` : "";
12530
- const execution = stat4.execution ? `, execution=${Object.entries(stat4.execution).map(([bucket, count]) => `${bucket}=${count}`).join(", ")}` : "";
11079
+ const topValues = stat2.top_values ? `, top_values=${Object.entries(stat2.top_values).slice(0, 3).map(([value, count]) => `${value}=${count}`).join(", ")}` : "";
11080
+ const sample = stat2.sample_value !== void 0 ? `, sample_value=${JSON.stringify(stat2.sample_value)}` : "";
11081
+ const execution = stat2.execution ? `, execution=${Object.entries(stat2.execution).map(([bucket, count]) => `${bucket}=${count}`).join(", ")}` : "";
12531
11082
  lines.push(
12532
- `${indent2} ${column}: non_empty=${stat4.non_empty}, unique=${stat4.unique}${topValues}${sample}${execution}`
11083
+ `${indent2} ${column}: non_empty=${stat2.non_empty}, unique=${stat2.unique}${topValues}${sample}${execution}`
12533
11084
  );
12534
11085
  }
12535
11086
  return lines;
@@ -12842,7 +11393,7 @@ function shellSingleQuote(value) {
12842
11393
  return `'${value.replace(/'/g, `'\\''`)}'`;
12843
11394
  }
12844
11395
  function runExportRetryCommand(runId, outPath, datasetPath) {
12845
- return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(resolve10(outPath))}`;
11396
+ return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(resolve7(outPath))}`;
12846
11397
  }
12847
11398
  function extractRunPlayName(status) {
12848
11399
  const run = status.run;
@@ -13646,7 +12197,7 @@ async function handlePlayCheck(args) {
13646
12197
  }
13647
12198
  return 0;
13648
12199
  } catch (error) {
13649
- const resolved = resolve10(options.target);
12200
+ const resolved = resolve7(options.target);
13650
12201
  const message = error instanceof Error && error.message ? error.message : `File not found: ${resolved}`;
13651
12202
  if (options.jsonOutput) {
13652
12203
  process.stdout.write(
@@ -13663,8 +12214,8 @@ async function handlePlayCheck(args) {
13663
12214
  return 1;
13664
12215
  }
13665
12216
  }
13666
- const absolutePlayPath = resolve10(options.target);
13667
- const sourceCode = readFileSync7(absolutePlayPath, "utf-8");
12217
+ const absolutePlayPath = resolve7(options.target);
12218
+ const sourceCode = readFileSync6(absolutePlayPath, "utf-8");
13668
12219
  let graph;
13669
12220
  try {
13670
12221
  graph = await collectBundledPlayGraph(absolutePlayPath);
@@ -13743,12 +12294,12 @@ async function handleFileBackedRun(options) {
13743
12294
  }
13744
12295
  const client2 = new DeeplineClient();
13745
12296
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
13746
- const absolutePlayPath = resolve10(options.target.path);
12297
+ const absolutePlayPath = resolve7(options.target.path);
13747
12298
  progress.phase("compiling play");
13748
12299
  const sourceCode = traceCliSync(
13749
12300
  "cli.play_file_read_source",
13750
12301
  { targetKind: "file" },
13751
- () => readFileSync7(absolutePlayPath, "utf-8")
12302
+ () => readFileSync6(absolutePlayPath, "utf-8")
13752
12303
  );
13753
12304
  const runtimeInput = options.input ? { ...options.input } : {};
13754
12305
  try {
@@ -14067,11 +12618,11 @@ async function handlePlayRun(args) {
14067
12618
  if (isFileTarget(options.target.path)) {
14068
12619
  return handleFileBackedRun(options);
14069
12620
  }
14070
- const resolved = resolve10(options.target.path);
12621
+ const resolved = resolve7(options.target.path);
14071
12622
  console.error(`File not found: ${resolved}`);
14072
- const dir = dirname9(resolved);
14073
- if (existsSync8(dir)) {
14074
- const base = basename3(resolved);
12623
+ const dir = dirname6(resolved);
12624
+ if (existsSync6(dir)) {
12625
+ const base = basename(resolved);
14075
12626
  try {
14076
12627
  const siblings = readdirSync(dir).filter(
14077
12628
  (f) => f.includes(base.replace(/\.(play\.)?ts$/, "")) || f.endsWith(".play.ts")
@@ -14079,7 +12630,7 @@ async function handlePlayRun(args) {
14079
12630
  if (siblings.length > 0) {
14080
12631
  console.error(`Did you mean one of these?`);
14081
12632
  for (const s of siblings.slice(0, 5)) {
14082
- console.error(` ${join8(dir, s)}`);
12633
+ console.error(` ${join5(dir, s)}`);
14083
12634
  }
14084
12635
  }
14085
12636
  } catch {
@@ -14234,7 +12785,7 @@ async function handleRunLogs(args) {
14234
12785
  continue;
14235
12786
  }
14236
12787
  if (arg === "--out" && args[index + 1]) {
14237
- outPath = resolve10(args[++index]);
12788
+ outPath = resolve7(args[++index]);
14238
12789
  }
14239
12790
  }
14240
12791
  const client2 = new DeeplineClient();
@@ -14366,7 +12917,7 @@ async function handleRunExport(args) {
14366
12917
  for (let index = 0; index < args.length; index += 1) {
14367
12918
  const arg = args[index];
14368
12919
  if (arg === "--out" && args[index + 1]) {
14369
- outPath = resolve10(args[++index]);
12920
+ outPath = resolve7(args[++index]);
14370
12921
  continue;
14371
12922
  }
14372
12923
  if (arg === "--dataset" && args[index + 1]) {
@@ -14374,7 +12925,7 @@ async function handleRunExport(args) {
14374
12925
  continue;
14375
12926
  }
14376
12927
  if (arg === "--metadata-out" && args[index + 1]) {
14377
- metadataOutPath = resolve10(args[++index]);
12928
+ metadataOutPath = resolve7(args[++index]);
14378
12929
  }
14379
12930
  }
14380
12931
  if (!outPath) {
@@ -14446,10 +12997,10 @@ async function handlePlayGet(args) {
14446
12997
  for (let index = 1; index < args.length; index += 1) {
14447
12998
  const arg = args[index];
14448
12999
  if (arg === "--out" && args[index + 1]) {
14449
- outPath = resolve10(args[++index]);
13000
+ outPath = resolve7(args[++index]);
14450
13001
  }
14451
13002
  }
14452
- const playName = isFileTarget(target) ? extractPlayName(readFileSync7(resolve10(target), "utf-8"), resolve10(target)) : parseReferencedPlayTarget2(target).playName;
13003
+ const playName = isFileTarget(target) ? extractPlayName(readFileSync6(resolve7(target), "utf-8"), resolve7(target)) : parseReferencedPlayTarget2(target).playName;
14453
13004
  const detail = isFileTarget(target) ? await client2.getPlay(playName) : await assertCanonicalNamedPlayReference(client2, target);
14454
13005
  const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
14455
13006
  const materializedFile = outPath ? materializeRemotePlaySource({
@@ -14892,7 +13443,7 @@ async function handlePlayDescribe(args) {
14892
13443
  const definedName = isFileTarget(playName) ? (() => {
14893
13444
  try {
14894
13445
  return extractPlayName(
14895
- readFileSync7(resolve10(playName), "utf-8"),
13446
+ readFileSync6(resolve7(playName), "utf-8"),
14896
13447
  playName
14897
13448
  );
14898
13449
  } catch {
@@ -14973,7 +13524,7 @@ async function handlePlayPublish(args) {
14973
13524
  graph = await traceCliSpan(
14974
13525
  "cli.play_publish_bundle_graph",
14975
13526
  { targetKind: "file" },
14976
- () => collectBundledPlayGraph(resolve10(playName))
13527
+ () => collectBundledPlayGraph(resolve7(playName))
14977
13528
  );
14978
13529
  await traceCliSpan(
14979
13530
  "cli.play_publish_compile_manifests",
@@ -15093,14 +13644,15 @@ Concepts:
15093
13644
  Stable ctx.tools.execute({ id, tool, input }) calls are replay-safe.
15094
13645
  ctx.dataset adds row keys and row progress.
15095
13646
  Named play runs use the live revision unless --latest or --revision-id is set.
15096
- Running a local file does not make it live; use set-live/publish explicitly.
13647
+ Installed npm and repo-local CLIs can run saved/prebuilt plays by name or
13648
+ bundle local .play.ts files for development workflows.
13649
+ Running a local file does not make it live; use publish or set-live for that.
15097
13650
 
15098
13651
  Common commands:
15099
13652
  deepline plays search email --json
15100
13653
  deepline plays describe prebuilt/person-linkedin-to-email --json
15101
- deepline plays check my.play.ts
15102
- deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
15103
- deepline plays set-live my.play.ts --json
13654
+ deepline plays check prebuilt/name-and-domain-to-email-waterfall-batch
13655
+ deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
15104
13656
  deepline plays get prebuilt/person-linkedin-to-email --json
15105
13657
  `
15106
13658
  );
@@ -15108,14 +13660,14 @@ Common commands:
15108
13660
  "after",
15109
13661
  `
15110
13662
  Notes:
15111
- Validates a local play without storing it, promoting it, or starting a run.
15112
- This uses the authoritative cloud preflight path.
15113
13663
  For named or prebuilt plays, validates that the contract is discoverable
15114
13664
  without starting a run or spending Deepline credits.
13665
+ Local .play.ts checks bundle the play, validate its artifact, and stop before
13666
+ any cloud run is created.
15115
13667
 
15116
13668
  Examples:
15117
- deepline plays check my.play.ts
15118
13669
  deepline plays check prebuilt/name-and-domain-to-email-waterfall-batch
13670
+ deepline plays check my-play --json
15119
13671
  deepline plays check my.play.ts --json
15120
13672
  `
15121
13673
  ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
@@ -15124,11 +13676,10 @@ Examples:
15124
13676
  ...options.json ? ["--json"] : []
15125
13677
  ]);
15126
13678
  });
15127
- play.command("run [target]").description("Run a play file or named play.").allowUnknownOption(true).allowExcessArguments(true).addHelpText(
13679
+ play.command("run [target]").description("Run a named/prebuilt play or local play file.").allowUnknownOption(true).allowExcessArguments(true).addHelpText(
15128
13680
  "after",
15129
13681
  `
15130
13682
  Notes:
15131
- Local files are bundled, preflighted, then run in Deepline cloud.
15132
13683
  Named plays run the live saved revision.
15133
13684
  Unknown --foo value and --foo.bar value flags are passed into play input.
15134
13685
  Example: --limit 5 becomes input.limit = 5.
@@ -15168,11 +13719,11 @@ Idempotent execution:
15168
13719
  .run({ key: 'domain' })
15169
13720
 
15170
13721
  Examples:
13722
+ deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
13723
+ deepline plays run long-background-play --no-wait
15171
13724
  deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
15172
13725
  deepline plays run my.play.ts --input @input.json --json
15173
- deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
15174
13726
  deepline plays run cto-search.play.ts --limit 5
15175
- deepline plays run long-background-play --no-wait
15176
13727
  deepline runs export <run-id> --out output.csv
15177
13728
  deepline runs get <run-id>
15178
13729
  `
@@ -15365,20 +13916,21 @@ Examples:
15365
13916
  "after",
15366
13917
  `
15367
13918
  Notes:
15368
- Mutates cloud state. For a local file, this bundles, validates, saves a new
15369
- revision, and promotes that revision live. For a saved play, --latest or
15370
- --revision-id promotes an existing saved revision live.
13919
+ Mutates cloud state. For a saved play, --latest or --revision-id promotes an
13920
+ existing saved revision live.
13921
+ Local .play.ts publishing bundles the file, validates it, saves a revision,
13922
+ and promotes that revision live.
15371
13923
  Running a local file with plays run does not publish it.
15372
13924
 
15373
13925
  Examples:
15374
- deepline plays set-live my.play.ts --json
15375
13926
  deepline plays set-live my-play --latest --json
15376
13927
  deepline plays set-live my-play --revision-id <revision-id> --json
13928
+ deepline plays set-live my.play.ts --json
15377
13929
  deepline plays publish my.play.ts --json
15378
13930
  `
15379
13931
  );
15380
13932
  addPublishHelp(
15381
- play.command("publish <target>").description("Bundle, validate, save, and promote a play revision live.")
13933
+ play.command("publish <target>").description("Promote a saved play revision or publish a local play file.")
15382
13934
  ).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
15383
13935
  process.exitCode = await handlePlayPublish([
15384
13936
  target,
@@ -15389,7 +13941,7 @@ Examples:
15389
13941
  });
15390
13942
  addPublishHelp(
15391
13943
  play.command("set-live <target>").description(
15392
- "Promote a local file or saved revision as the live play revision."
13944
+ "Promote a saved revision or publish a local play file."
15393
13945
  )
15394
13946
  ).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
15395
13947
  process.exitCode = await handlePlayPublish([
@@ -17264,7 +15816,7 @@ function expandAtFilePath(rawPath) {
17264
15816
  return homedir6();
17265
15817
  }
17266
15818
  if (expanded.startsWith("~/") || expanded.startsWith("~\\")) {
17267
- return join9(homedir6(), expanded.slice(2));
15819
+ return join6(homedir6(), expanded.slice(2));
17268
15820
  }
17269
15821
  return expanded;
17270
15822
  }
@@ -17277,7 +15829,7 @@ async function readAtFileReference(value, argumentName, strip = true) {
17277
15829
  throw new Error(`Invalid ${argumentName} value: empty @file path.`);
17278
15830
  }
17279
15831
  try {
17280
- const text = await readFile3(filePath, "utf8");
15832
+ const text = await readFile(filePath, "utf8");
17281
15833
  const normalized = text.replace(/^\uFEFF/, "");
17282
15834
  return strip ? normalized.trim() : normalized;
17283
15835
  } catch (error) {
@@ -17448,9 +16000,9 @@ async function buildPlanArgs(args) {
17448
16000
  return planArgs;
17449
16001
  }
17450
16002
  async function assertInputCsvExists(inputCsv) {
17451
- const path = resolve11(inputCsv);
16003
+ const path = resolve8(inputCsv);
17452
16004
  try {
17453
- const info = await stat3(path);
16005
+ const info = await stat(path);
17454
16006
  if (info.isFile()) {
17455
16007
  return;
17456
16008
  }
@@ -17462,8 +16014,8 @@ async function assertInputCsvExists(inputCsv) {
17462
16014
  }
17463
16015
  }
17464
16016
  async function assertSafeOutputPath(inputCsv, outputPath) {
17465
- const input2 = resolve11(inputCsv);
17466
- const output2 = resolve11(outputPath);
16017
+ const input2 = resolve8(inputCsv);
16018
+ const output2 = resolve8(outputPath);
17467
16019
  if (input2 === output2) {
17468
16020
  throw new Error(
17469
16021
  "--input and --output must be different files when not using --in-place."
@@ -17471,8 +16023,8 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
17471
16023
  }
17472
16024
  try {
17473
16025
  const [inputInfo, outputInfo] = await Promise.all([
17474
- stat3(input2),
17475
- stat3(output2)
16026
+ stat(input2),
16027
+ stat(output2)
17476
16028
  ]);
17477
16029
  if (inputInfo.dev === outputInfo.dev && inputInfo.ino === outputInfo.ino) {
17478
16030
  throw new Error(
@@ -17492,7 +16044,7 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
17492
16044
  }
17493
16045
  async function regularFileExists(path) {
17494
16046
  try {
17495
- const info = await stat3(resolve11(path));
16047
+ const info = await stat(resolve8(path));
17496
16048
  return info.isFile();
17497
16049
  } catch (error) {
17498
16050
  const code = error && typeof error === "object" ? error.code : void 0;
@@ -17503,7 +16055,7 @@ async function regularFileExists(path) {
17503
16055
  }
17504
16056
  }
17505
16057
  async function readConfig(path) {
17506
- const source = await readFile3(resolve11(path), "utf8");
16058
+ const source = await readFile(resolve8(path), "utf8");
17507
16059
  let parsed;
17508
16060
  try {
17509
16061
  parsed = JSON.parse(source);
@@ -17788,7 +16340,7 @@ async function runGeneratedEnrichPlay(runArgs, options = {}) {
17788
16340
  });
17789
16341
  } catch (error) {
17790
16342
  if (attempt === 0 && isPlayStartStreamEndedError(error)) {
17791
- await new Promise((resolve16) => setTimeout(resolve16, 250));
16343
+ await new Promise((resolve13) => setTimeout(resolve13, 250));
17792
16344
  continue;
17793
16345
  }
17794
16346
  throw error;
@@ -17819,8 +16371,8 @@ async function writeOutputCsv(outputPath, status, options) {
17819
16371
  ]),
17820
16372
  options?.config
17821
16373
  );
17822
- await writeFile4(
17823
- resolve11(outputPath),
16374
+ await writeFile3(
16375
+ resolve8(outputPath),
17824
16376
  csvStringFromRows(merged.rows, columns),
17825
16377
  "utf8"
17826
16378
  );
@@ -17830,7 +16382,7 @@ async function writeOutputCsv(outputPath, status, options) {
17830
16382
  selectedRows: rowsInfo.totalRows,
17831
16383
  enrichedRows: rowsInfo.rows.length,
17832
16384
  rows: merged.rows.length,
17833
- path: resolve11(outputPath),
16385
+ path: resolve8(outputPath),
17834
16386
  enrichedDataRows: rowsInfo.rows
17835
16387
  };
17836
16388
  }
@@ -18019,12 +16571,12 @@ function firstAliasExecutionCounts(input2) {
18019
16571
  const aliases = collectConfigScalarAliasOrder(input2.config);
18020
16572
  const summaries = collectColumnStats(input2.status);
18021
16573
  for (const alias of aliases) {
18022
- const stat4 = summaries.map((summary) => summary[alias]).find(isRecord7);
18023
- if (!stat4) continue;
16574
+ const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
16575
+ if (!stat2) continue;
18024
16576
  if (input2.forceAliases.has(normalizeAlias2(alias))) {
18025
16577
  return { executed: input2.selectedRows, reused: 0 };
18026
16578
  }
18027
- const execution = isRecord7(stat4.execution) ? stat4.execution : null;
16579
+ const execution = isRecord7(stat2.execution) ? stat2.execution : null;
18028
16580
  if (!execution) continue;
18029
16581
  return {
18030
16582
  executed: parseExecutionCount(execution["completed:executed"]),
@@ -18084,11 +16636,11 @@ function rewriteEnrichJsonStatus(input2) {
18084
16636
  if (isRecord7(next.columnStats) && selectedRows > 0) {
18085
16637
  const columnStats = { ...next.columnStats };
18086
16638
  for (const alias of forcedAliases) {
18087
- const stat4 = isRecord7(columnStats[alias]) ? columnStats[alias] : null;
18088
- const execution = isRecord7(stat4?.execution) ? stat4.execution : null;
18089
- if (!stat4 || !execution) continue;
16639
+ const stat2 = isRecord7(columnStats[alias]) ? columnStats[alias] : null;
16640
+ const execution = isRecord7(stat2?.execution) ? stat2.execution : null;
16641
+ if (!stat2 || !execution) continue;
18090
16642
  columnStats[alias] = {
18091
- ...stat4,
16643
+ ...stat2,
18092
16644
  execution: {
18093
16645
  ...execution,
18094
16646
  "completed:executed": executionSummaryText(
@@ -18125,9 +16677,9 @@ async function persistEnrichFailureReport(input2) {
18125
16677
  if (input2.jobs.length === 0) {
18126
16678
  return null;
18127
16679
  }
18128
- const stateDir = join9(homedir6(), ".local", "deepline", "runtime", "state");
18129
- await mkdir4(stateDir, { recursive: true });
18130
- const reportPath = join9(
16680
+ const stateDir = join6(homedir6(), ".local", "deepline", "runtime", "state");
16681
+ await mkdir3(stateDir, { recursive: true });
16682
+ const reportPath = join6(
18131
16683
  stateDir,
18132
16684
  `run-block-failures-${Math.floor(Date.now() / 1e3)}-${process.pid}.json`
18133
16685
  );
@@ -18151,7 +16703,7 @@ async function persistEnrichFailureReport(input2) {
18151
16703
  if (input2.rows.rowStart !== null && input2.rows.rowEnd !== null) {
18152
16704
  report.rows = { start: input2.rows.rowStart, end: input2.rows.rowEnd };
18153
16705
  }
18154
- await writeFile4(reportPath, `${JSON.stringify(report, null, 2)}
16706
+ await writeFile3(reportPath, `${JSON.stringify(report, null, 2)}
18155
16707
  `, "utf8");
18156
16708
  return reportPath;
18157
16709
  }
@@ -18564,8 +17116,8 @@ function registerEnrichCommand(program) {
18564
17116
  if (options.json) {
18565
17117
  printJson({
18566
17118
  dryRun: true,
18567
- input: resolve11(inputCsv),
18568
- output: options.output ? resolve11(options.output) : null,
17119
+ input: resolve8(inputCsv),
17120
+ output: options.output ? resolve8(options.output) : null,
18569
17121
  plan: summary
18570
17122
  });
18571
17123
  return;
@@ -18589,12 +17141,12 @@ function registerEnrichCommand(program) {
18589
17141
  forceAliases,
18590
17142
  playName: options.name
18591
17143
  });
18592
- const tempDir = await mkdtemp(join9(tmpdir3(), "deepline-enrich-play-"));
18593
- const tempPlay = join9(tempDir, "deepline-enrich.play.ts");
17144
+ const tempDir = await mkdtemp(join6(tmpdir(), "deepline-enrich-play-"));
17145
+ const tempPlay = join6(tempDir, "deepline-enrich.play.ts");
18594
17146
  try {
18595
- await writeFile4(tempPlay, playSource, "utf8");
17147
+ await writeFile3(tempPlay, playSource, "utf8");
18596
17148
  const runtimeInput = {
18597
- file: resolve11(sourceCsvPath),
17149
+ file: resolve8(sourceCsvPath),
18598
17150
  ...rows.rowStart !== null ? { rowStart: rows.rowStart } : {},
18599
17151
  ...rows.rowEnd !== null ? { rowEnd: rows.rowEnd } : {}
18600
17152
  };
@@ -18756,15 +17308,15 @@ Examples:
18756
17308
 
18757
17309
  // src/cli/commands/sessions.ts
18758
17310
  import {
18759
- existsSync as existsSync9,
17311
+ existsSync as existsSync7,
18760
17312
  mkdirSync as mkdirSync5,
18761
17313
  readdirSync as readdirSync2,
18762
- readFileSync as readFileSync8,
17314
+ readFileSync as readFileSync7,
18763
17315
  statSync as statSync3,
18764
17316
  writeFileSync as writeFileSync9
18765
17317
  } from "fs";
18766
17318
  import { homedir as homedir7, platform } from "os";
18767
- import { basename as basename4, dirname as dirname10, join as join10, resolve as resolve12 } from "path";
17319
+ import { basename as basename2, dirname as dirname7, join as join7, resolve as resolve9 } from "path";
18768
17320
  import { gzipSync } from "zlib";
18769
17321
  import { randomUUID } from "crypto";
18770
17322
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -18783,36 +17335,36 @@ function homeDir() {
18783
17335
  function detectShellContext() {
18784
17336
  const shellPath = process.env.SHELL?.trim() || process.env.ComSpec?.trim() || process.env.COMSPEC?.trim() || "";
18785
17337
  return {
18786
- shell: shellPath ? basename4(shellPath).replace(/\.exe$/i, "") : "unknown",
17338
+ shell: shellPath ? basename2(shellPath).replace(/\.exe$/i, "") : "unknown",
18787
17339
  shell_path: shellPath || null,
18788
17340
  os: platform(),
18789
17341
  cwd: process.cwd()
18790
17342
  };
18791
17343
  }
18792
17344
  function claudeProjectsRoot() {
18793
- return join10(homeDir(), ".claude", "projects");
17345
+ return join7(homeDir(), ".claude", "projects");
18794
17346
  }
18795
17347
  function codexSessionsRoot() {
18796
- return join10(homeDir(), ".codex", "sessions");
17348
+ return join7(homeDir(), ".codex", "sessions");
18797
17349
  }
18798
17350
  function listClaudeSessionFiles() {
18799
17351
  const root = claudeProjectsRoot();
18800
- if (!existsSync9(root)) return [];
17352
+ if (!existsSync7(root)) return [];
18801
17353
  const projectDirs = readDirectoryNames(root);
18802
17354
  const files = [];
18803
17355
  for (const projectDir of projectDirs) {
18804
- const fullProjectDir = join10(root, projectDir);
17356
+ const fullProjectDir = join7(root, projectDir);
18805
17357
  for (const fileName of readDirectoryNames(fullProjectDir)) {
18806
17358
  if (fileName.endsWith(".jsonl")) {
18807
- const filePath = join10(fullProjectDir, fileName);
17359
+ const filePath = join7(fullProjectDir, fileName);
18808
17360
  const sessionId = sessionIdFromClaudeFilePath(filePath);
18809
- const stat4 = statIfReadable(filePath);
18810
- if (sessionId && stat4) {
17361
+ const stat2 = statIfReadable(filePath);
17362
+ if (sessionId && stat2) {
18811
17363
  files.push({
18812
17364
  agent: "claude",
18813
17365
  sessionId,
18814
17366
  filePath,
18815
- mtimeMs: stat4.mtimeMs
17367
+ mtimeMs: stat2.mtimeMs
18816
17368
  });
18817
17369
  }
18818
17370
  }
@@ -18822,14 +17374,14 @@ function listClaudeSessionFiles() {
18822
17374
  }
18823
17375
  function listCodexSessionFiles() {
18824
17376
  const root = codexSessionsRoot();
18825
- if (!existsSync9(root)) return [];
17377
+ if (!existsSync7(root)) return [];
18826
17378
  const files = [];
18827
17379
  for (const filePath of listJsonlFilesRecursive(root, 5)) {
18828
- const stat4 = statIfReadable(filePath);
18829
- if (!stat4) continue;
17380
+ const stat2 = statIfReadable(filePath);
17381
+ if (!stat2) continue;
18830
17382
  const sessionId = sessionIdFromCodexFilePath(filePath) ?? readCodexSessionId(filePath);
18831
17383
  if (!sessionId) continue;
18832
- files.push({ agent: "codex", sessionId, filePath, mtimeMs: stat4.mtimeMs });
17384
+ files.push({ agent: "codex", sessionId, filePath, mtimeMs: stat2.mtimeMs });
18833
17385
  }
18834
17386
  return files;
18835
17387
  }
@@ -18861,7 +17413,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
18861
17413
  return;
18862
17414
  }
18863
17415
  for (const entry of entries) {
18864
- const fullPath = join10(dir, entry.name);
17416
+ const fullPath = join7(dir, entry.name);
18865
17417
  if (entry.isDirectory()) {
18866
17418
  visit(fullPath, depth + 1);
18867
17419
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
@@ -18889,15 +17441,15 @@ function newestSessionFile(agent) {
18889
17441
  return newest;
18890
17442
  }
18891
17443
  function sessionIdFromClaudeFilePath(filePath) {
18892
- return basename4(filePath, ".jsonl");
17444
+ return basename2(filePath, ".jsonl");
18893
17445
  }
18894
17446
  function sessionIdFromCodexFilePath(filePath) {
18895
- const match = basename4(filePath, ".jsonl").match(UUID_IN_TEXT_RE);
17447
+ const match = basename2(filePath, ".jsonl").match(UUID_IN_TEXT_RE);
18896
17448
  return match?.[0] ?? null;
18897
17449
  }
18898
17450
  function readCodexSessionId(filePath) {
18899
17451
  try {
18900
- for (const line of normalizedJsonLines(readFileSync8(filePath)).slice(
17452
+ for (const line of normalizedJsonLines(readFileSync7(filePath)).slice(
18901
17453
  0,
18902
17454
  20
18903
17455
  )) {
@@ -19174,25 +17726,25 @@ async function uploadChunkedSessions(sessions, options) {
19174
17726
  }
19175
17727
  async function handleSessionsSend(options) {
19176
17728
  if (options.file) {
19177
- const filePath = resolve12(options.file);
19178
- if (!existsSync9(filePath)) {
17729
+ const filePath = resolve9(options.file);
17730
+ if (!existsSync7(filePath)) {
19179
17731
  throw new Error(`File not found: ${options.file}`);
19180
17732
  }
19181
17733
  const response2 = await uploadPayload("/api/v2/cli/send-session", {
19182
- file: readFileSync8(filePath).toString("base64"),
19183
- filename: basename4(filePath)
17734
+ file: readFileSync7(filePath).toString("base64"),
17735
+ filename: basename2(filePath)
19184
17736
  });
19185
17737
  printCommandEnvelope(
19186
17738
  {
19187
17739
  ...response2,
19188
17740
  ok: true,
19189
- filename: basename4(filePath),
17741
+ filename: basename2(filePath),
19190
17742
  render: {
19191
17743
  sections: [
19192
17744
  {
19193
17745
  title: "sessions send",
19194
17746
  lines: [
19195
- `File '${basename4(filePath)}' uploaded to #internal-reports.`
17747
+ `File '${basename2(filePath)}' uploaded to #internal-reports.`
19196
17748
  ]
19197
17749
  }
19198
17750
  ]
@@ -19209,7 +17761,7 @@ async function handleSessionsSend(options) {
19209
17761
  agent: options.agent
19210
17762
  });
19211
17763
  const built = targets.map((target) => {
19212
- const upload = buildSessionUploadContent(readFileSync8(target.filePath));
17764
+ const upload = buildSessionUploadContent(readFileSync7(target.filePath));
19213
17765
  return { ...target, ...upload };
19214
17766
  });
19215
17767
  if (built.some((session) => session.needsChunking)) {
@@ -19273,28 +17825,28 @@ function fallbackViewerAssets() {
19273
17825
  };
19274
17826
  }
19275
17827
  function loadViewerAssets() {
19276
- const cliEntry = process.argv[1]?.trim() ? resolve12(process.argv[1]) : null;
17828
+ const cliEntry = process.argv[1]?.trim() ? resolve9(process.argv[1]) : null;
19277
17829
  const candidateRoots2 = [
19278
17830
  ...cliEntry ? [
19279
- join10(dirname10(dirname10(cliEntry)), "viewer"),
19280
- join10(
19281
- dirname10(dirname10(dirname10(cliEntry))),
17831
+ join7(dirname7(dirname7(cliEntry)), "viewer"),
17832
+ join7(
17833
+ dirname7(dirname7(dirname7(cliEntry))),
19282
17834
  "src",
19283
17835
  "lib",
19284
17836
  "cli",
19285
17837
  "viewer"
19286
17838
  )
19287
17839
  ] : [],
19288
- join10(process.cwd(), "src", "lib", "cli", "viewer")
17840
+ join7(process.cwd(), "src", "lib", "cli", "viewer")
19289
17841
  ];
19290
17842
  for (const root of candidateRoots2) {
19291
17843
  try {
19292
- const cssPath = join10(root, "viewer.css");
19293
- const jsPath = join10(root, "viewer.js");
19294
- if (!existsSync9(cssPath) || !existsSync9(jsPath)) continue;
17844
+ const cssPath = join7(root, "viewer.css");
17845
+ const jsPath = join7(root, "viewer.js");
17846
+ if (!existsSync7(cssPath) || !existsSync7(jsPath)) continue;
19295
17847
  return {
19296
- css: readFileSync8(cssPath, "utf8"),
19297
- js: readFileSync8(jsPath, "utf8")
17848
+ css: readFileSync7(cssPath, "utf8"),
17849
+ js: readFileSync7(jsPath, "utf8")
19298
17850
  };
19299
17851
  } catch {
19300
17852
  continue;
@@ -19318,21 +17870,21 @@ async function handleSessionsRender(options) {
19318
17870
  currentSession: options.currentSession,
19319
17871
  agent: options.agent
19320
17872
  });
19321
- let outputPath = options.output ? resolve12(options.output) : "";
17873
+ let outputPath = options.output ? resolve9(options.output) : "";
19322
17874
  if (!outputPath) {
19323
- const outputDir = join10(process.cwd(), "deepline", "data");
17875
+ const outputDir = join7(process.cwd(), "deepline", "data");
19324
17876
  mkdirSync5(outputDir, { recursive: true });
19325
- outputPath = join10(
17877
+ outputPath = join7(
19326
17878
  outputDir,
19327
17879
  targets.length > 1 ? "session-viewer.html" : `session-${targets[0]?.sessionId}.html`
19328
17880
  );
19329
17881
  } else {
19330
- mkdirSync5(dirname10(outputPath), { recursive: true });
17882
+ mkdirSync5(dirname7(outputPath), { recursive: true });
19331
17883
  }
19332
17884
  const sessions = targets.map((target) => ({
19333
17885
  label: target.label,
19334
17886
  events: parsePreparedEvents(
19335
- prepareSessionBuffer(readFileSync8(target.filePath))
17887
+ prepareSessionBuffer(readFileSync7(target.filePath))
19336
17888
  )
19337
17889
  }));
19338
17890
  const { css, js } = loadViewerAssets();
@@ -19795,17 +18347,17 @@ function hasClaudeBinary() {
19795
18347
  }
19796
18348
  }
19797
18349
  function launchClaude(prompt) {
19798
- return new Promise((resolve16) => {
18350
+ return new Promise((resolve13) => {
19799
18351
  const child = spawn("claude", [prompt], {
19800
18352
  stdio: "inherit",
19801
18353
  shell: process.platform === "win32"
19802
18354
  });
19803
- child.on("error", () => resolve16(EXIT_SERVER3));
19804
- child.on("close", (status) => resolve16(status ?? EXIT_OK2));
18355
+ child.on("error", () => resolve13(EXIT_SERVER3));
18356
+ child.on("close", (status) => resolve13(status ?? EXIT_OK2));
19805
18357
  });
19806
18358
  }
19807
18359
  function readBody(req) {
19808
- return new Promise((resolve16, reject) => {
18360
+ return new Promise((resolve13, reject) => {
19809
18361
  let raw = "";
19810
18362
  req.setEncoding("utf8");
19811
18363
  req.on("data", (chunk) => {
@@ -19815,7 +18367,7 @@ function readBody(req) {
19815
18367
  req.destroy();
19816
18368
  }
19817
18369
  });
19818
- req.on("end", () => resolve16(raw));
18370
+ req.on("end", () => resolve13(raw));
19819
18371
  req.on("error", reject);
19820
18372
  });
19821
18373
  }
@@ -19870,7 +18422,7 @@ function startCallbackServer(input2) {
19870
18422
  writeJson(res, 400, { error: "Invalid request body." });
19871
18423
  });
19872
18424
  });
19873
- return new Promise((resolve16, reject) => {
18425
+ return new Promise((resolve13, reject) => {
19874
18426
  server.once("error", reject);
19875
18427
  server.listen(0, "127.0.0.1", () => {
19876
18428
  const address = server.address();
@@ -19878,7 +18430,7 @@ function startCallbackServer(input2) {
19878
18430
  reject(new Error("Failed to bind quickstart callback server."));
19879
18431
  return;
19880
18432
  }
19881
- resolve16({ server, port: address.port });
18433
+ resolve13({ server, port: address.port });
19882
18434
  });
19883
18435
  });
19884
18436
  }
@@ -19904,8 +18456,8 @@ async function handleQuickstart(options) {
19904
18456
  }
19905
18457
  const state = randomBytes(32).toString("hex");
19906
18458
  let resolveSelection;
19907
- const selectionPromise = new Promise((resolve16) => {
19908
- resolveSelection = resolve16;
18459
+ const selectionPromise = new Promise((resolve13) => {
18460
+ resolveSelection = resolve13;
19909
18461
  });
19910
18462
  let callback;
19911
18463
  try {
@@ -20039,7 +18591,7 @@ async function readHiddenLine(prompt) {
20039
18591
  if (typeof input.setRawMode === "function") input.setRawMode(true);
20040
18592
  let value = "";
20041
18593
  input.resume();
20042
- return await new Promise((resolve16, reject) => {
18594
+ return await new Promise((resolve13, reject) => {
20043
18595
  let settled = false;
20044
18596
  const cleanup = () => {
20045
18597
  input.off("data", onData);
@@ -20054,7 +18606,7 @@ async function readHiddenLine(prompt) {
20054
18606
  settled = true;
20055
18607
  output.write("\n");
20056
18608
  cleanup();
20057
- resolve16(line);
18609
+ resolve13(line);
20058
18610
  };
20059
18611
  const fail = (error) => {
20060
18612
  if (settled) return;
@@ -20225,9 +18777,9 @@ Examples:
20225
18777
  }
20226
18778
 
20227
18779
  // src/cli/commands/switch.ts
20228
- import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
18780
+ import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync10 } from "fs";
20229
18781
  import { homedir as homedir8 } from "os";
20230
- import { dirname as dirname11, join as join11 } from "path";
18782
+ import { dirname as dirname8, join as join8 } from "path";
20231
18783
  function hostSlugFromBaseUrl(baseUrl) {
20232
18784
  try {
20233
18785
  const url = new URL(baseUrl);
@@ -20248,7 +18800,7 @@ function resolveConfigScope() {
20248
18800
  }
20249
18801
  function activeFamilyPath() {
20250
18802
  const home = process.env.HOME || process.env.USERPROFILE || homedir8();
20251
- return join11(
18803
+ return join8(
20252
18804
  home,
20253
18805
  ".local",
20254
18806
  "deepline",
@@ -20260,14 +18812,14 @@ function activeFamilyPath() {
20260
18812
  function readActiveFamily() {
20261
18813
  const path = activeFamilyPath();
20262
18814
  try {
20263
- return readFileSync9(path, "utf-8").trim() || "sdk";
18815
+ return readFileSync8(path, "utf-8").trim() || "sdk";
20264
18816
  } catch {
20265
18817
  return "sdk";
20266
18818
  }
20267
18819
  }
20268
18820
  function writeActiveFamily(family) {
20269
18821
  const path = activeFamilyPath();
20270
- mkdirSync6(dirname11(path), { recursive: true });
18822
+ mkdirSync6(dirname8(path), { recursive: true });
20271
18823
  writeFileSync10(path, `${family}
20272
18824
  `, "utf-8");
20273
18825
  return path;
@@ -20285,7 +18837,7 @@ function handleSwitch(action, options) {
20285
18837
  ok: true,
20286
18838
  active_family: activeFamily,
20287
18839
  active_family_path: path,
20288
- active_family_file_exists: existsSync10(path),
18840
+ active_family_file_exists: existsSync8(path),
20289
18841
  render: {
20290
18842
  sections: [
20291
18843
  {
@@ -20387,18 +18939,18 @@ Examples:
20387
18939
  import { Option } from "commander";
20388
18940
  import {
20389
18941
  chmodSync,
20390
- existsSync as existsSync11,
18942
+ existsSync as existsSync9,
20391
18943
  mkdtempSync,
20392
- readFileSync as readFileSync10,
18944
+ readFileSync as readFileSync9,
20393
18945
  writeFileSync as writeFileSync12
20394
18946
  } from "fs";
20395
- import { tmpdir as tmpdir4 } from "os";
20396
- import { join as join13, resolve as resolve13 } from "path";
18947
+ import { tmpdir as tmpdir2 } from "os";
18948
+ import { join as join10, resolve as resolve10 } from "path";
20397
18949
 
20398
18950
  // src/tool-output.ts
20399
18951
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync11 } from "fs";
20400
18952
  import { homedir as homedir9 } from "os";
20401
- import { join as join12 } from "path";
18953
+ import { join as join9 } from "path";
20402
18954
  function isPlainObject(value) {
20403
18955
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
20404
18956
  }
@@ -20494,19 +19046,19 @@ function tryConvertToList(payload, options) {
20494
19046
  return null;
20495
19047
  }
20496
19048
  function ensureOutputDir() {
20497
- const outputDir = join12(homedir9(), ".local", "share", "deepline", "data");
19049
+ const outputDir = join9(homedir9(), ".local", "share", "deepline", "data");
20498
19050
  mkdirSync7(outputDir, { recursive: true });
20499
19051
  return outputDir;
20500
19052
  }
20501
19053
  function writeJsonOutputFile(payload, stem) {
20502
19054
  const outputDir = ensureOutputDir();
20503
- const outputPath = join12(outputDir, `${stem}_${Date.now()}.json`);
19055
+ const outputPath = join9(outputDir, `${stem}_${Date.now()}.json`);
20504
19056
  writeFileSync11(outputPath, JSON.stringify(payload, null, 2), "utf-8");
20505
19057
  return outputPath;
20506
19058
  }
20507
19059
  function writeCsvOutputFile(rows, stem) {
20508
19060
  const outputDir = ensureOutputDir();
20509
- const outputPath = join12(outputDir, `${stem}_${Date.now()}.csv`);
19061
+ const outputPath = join9(outputDir, `${stem}_${Date.now()}.csv`);
20510
19062
  const seen = /* @__PURE__ */ new Set();
20511
19063
  const columns = [];
20512
19064
  for (const row of rows) {
@@ -21583,11 +20135,11 @@ function normalizeOutputFormat(raw) {
21583
20135
  }
21584
20136
  function resolveAtFilePath(rawPath) {
21585
20137
  const trimmed = rawPath.trim();
21586
- const resolved = resolve13(trimmed);
21587
- if (existsSync11(resolved)) return resolved;
20138
+ const resolved = resolve10(trimmed);
20139
+ if (existsSync9(resolved)) return resolved;
21588
20140
  if (process.platform !== "win32" && trimmed.includes("\\")) {
21589
- const normalized = resolve13(trimmed.replace(/\\/g, "/"));
21590
- if (existsSync11(normalized)) return normalized;
20141
+ const normalized = resolve10(trimmed.replace(/\\/g, "/"));
20142
+ if (existsSync9(normalized)) return normalized;
21591
20143
  }
21592
20144
  return resolved;
21593
20145
  }
@@ -21598,7 +20150,7 @@ function readJsonArgument(raw, flagName) {
21598
20150
  throw new Error(`Invalid ${flagName} value: empty @file path.`);
21599
20151
  }
21600
20152
  try {
21601
- return readFileSync10(resolveAtFilePath(filePath), "utf8").replace(
20153
+ return readFileSync9(resolveAtFilePath(filePath), "utf8").replace(
21602
20154
  /^\uFEFF/,
21603
20155
  ""
21604
20156
  );
@@ -21700,9 +20252,9 @@ function starterScriptJson(script) {
21700
20252
  function seedToolListScript(input2) {
21701
20253
  const stem = safeFileStem(input2.toolId);
21702
20254
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
21703
- const scriptDir = mkdtempSync(join13(tmpdir4(), "deepline-workflow-seed-"));
20255
+ const scriptDir = mkdtempSync(join10(tmpdir2(), "deepline-workflow-seed-"));
21704
20256
  chmodSync(scriptDir, 448);
21705
- const scriptPath = join13(scriptDir, fileName);
20257
+ const scriptPath = join10(scriptDir, fileName);
21706
20258
  const projectDir = `deepline/projects/${stem}-workflow`;
21707
20259
  const playName = `${stem}-workflow`;
21708
20260
  const sampleRows = input2.rows.length > 0 ? `${JSON.stringify(input2.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
@@ -22002,11 +20554,48 @@ async function executeTool(args) {
22002
20554
  }
22003
20555
 
22004
20556
  // src/cli/commands/workflow.ts
22005
- import { mkdir as mkdir5, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
22006
- import { dirname as dirname12, join as join14, resolve as resolve14 } from "path";
20557
+ import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile4 } from "fs/promises";
20558
+ import { dirname as dirname9, join as join11, resolve as resolve11 } from "path";
20559
+
20560
+ // src/cli/workflow-to-play.ts
20561
+ import { createHash as createHash2 } from "crypto";
20562
+
20563
+ // ../shared_libs/plays/secret-guardrails.ts
20564
+ var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
20565
+ var PRIVATE_KEY_PATTERN = /-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/;
20566
+ var BEARER_LITERAL_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/i;
20567
+ var ASSIGNMENT_SECRET_LITERAL_PATTERN = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*['"][^'"]{12,}['"]/i;
20568
+ var HIGH_ENTROPY_LITERAL_PATTERN = /['"]([A-Za-z0-9+/=_-]{32,})['"]/g;
20569
+ function shannonEntropy(value) {
20570
+ const counts = /* @__PURE__ */ new Map();
20571
+ for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
20572
+ return [...counts.values()].reduce((entropy, count) => {
20573
+ const p = count / value.length;
20574
+ return entropy - p * Math.log2(p);
20575
+ }, 0);
20576
+ }
20577
+ function collectInlineSecretFindings(sourceCode) {
20578
+ const findings = [];
20579
+ for (const match of sourceCode.matchAll(SECRET_ENV_PATTERN)) {
20580
+ findings.push(`process.env.${match[1]}`);
20581
+ }
20582
+ if (PRIVATE_KEY_PATTERN.test(sourceCode)) findings.push("private key block");
20583
+ if (BEARER_LITERAL_PATTERN.test(sourceCode))
20584
+ findings.push("bearer token literal");
20585
+ if (ASSIGNMENT_SECRET_LITERAL_PATTERN.test(sourceCode)) {
20586
+ findings.push("secret-looking assignment literal");
20587
+ }
20588
+ for (const match of sourceCode.matchAll(HIGH_ENTROPY_LITERAL_PATTERN)) {
20589
+ const literal = match[1] ?? "";
20590
+ if (literal.length >= 40 && shannonEntropy(literal) >= 4.2) {
20591
+ findings.push("high-entropy string literal");
20592
+ break;
20593
+ }
20594
+ }
20595
+ return [...new Set(findings)];
20596
+ }
22007
20597
 
22008
20598
  // src/cli/workflow-to-play.ts
22009
- import { createHash as createHash4 } from "crypto";
22010
20599
  var HITL_WAIT_FOR_SIGNAL_TOOL = "deepline_workflow_wait_for_signal";
22011
20600
  var HITL_SLACK_TOOL = "slack_message_with_hitl";
22012
20601
  var SUB_WORKFLOW_TOOL_PREFIX = "deepline_workflow_";
@@ -22112,7 +20701,7 @@ function sanitizePlayNameSegment(value) {
22112
20701
  }
22113
20702
  function deriveWorkflowPlayName(workflowName) {
22114
20703
  const base = sanitizePlayNameSegment(workflowName) || "workflow";
22115
- const suffix = createHash4("sha256").update(workflowName).digest("hex").slice(0, 8);
20704
+ const suffix = createHash2("sha256").update(workflowName).digest("hex").slice(0, 8);
22116
20705
  const reserved = suffix.length + 1;
22117
20706
  const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
22118
20707
  let name = `${base.slice(0, allowedBase)}_${suffix}`;
@@ -22210,7 +20799,7 @@ function readStatus(payload) {
22210
20799
  }
22211
20800
  async function readJsonOption(payload, file) {
22212
20801
  if (file) {
22213
- const raw = await readFile4(resolve14(file), "utf8");
20802
+ const raw = await readFile2(resolve11(file), "utf8");
22214
20803
  return JSON.parse(raw);
22215
20804
  }
22216
20805
  if (payload) {
@@ -22244,9 +20833,9 @@ async function transformOne(api, workflowId, outDir, publish) {
22244
20833
  revision.config,
22245
20834
  { workflowName: workflow.name, version: revision.version }
22246
20835
  );
22247
- const file = join14(resolve14(outDir), `${compiled.playName}.play.ts`);
22248
- await mkdir5(dirname12(file), { recursive: true });
22249
- await writeFile5(file, compiled.sourceCode, "utf8");
20836
+ const file = join11(resolve11(outDir), `${compiled.playName}.play.ts`);
20837
+ await mkdir4(dirname9(file), { recursive: true });
20838
+ await writeFile4(file, compiled.sourceCode, "utf8");
22250
20839
  let published = false;
22251
20840
  if (publish) {
22252
20841
  const code = await handlePlayPublish([file]);
@@ -22493,15 +21082,15 @@ Notes:
22493
21082
  // src/cli/commands/update.ts
22494
21083
  import { spawn as spawn2 } from "child_process";
22495
21084
  import {
22496
- existsSync as existsSync12,
21085
+ existsSync as existsSync10,
22497
21086
  mkdirSync as mkdirSync8,
22498
- readFileSync as readFileSync11,
21087
+ readFileSync as readFileSync10,
22499
21088
  renameSync,
22500
21089
  rmSync as rmSync3,
22501
21090
  writeFileSync as writeFileSync13
22502
21091
  } from "fs";
22503
21092
  import { homedir as homedir10 } from "os";
22504
- import { dirname as dirname13, isAbsolute as isAbsolute4, join as join15, relative as relative4, resolve as resolve15 } from "path";
21093
+ import { dirname as dirname10, isAbsolute as isAbsolute2, join as join12, relative as relative2, resolve as resolve12 } from "path";
22505
21094
  function posixShellQuote(value) {
22506
21095
  return `'${value.replace(/'/g, `'\\''`)}'`;
22507
21096
  }
@@ -22524,11 +21113,11 @@ function sidecarStateDir(input2) {
22524
21113
  if (!scope || scope.includes("/") || scope.includes("\\")) {
22525
21114
  return null;
22526
21115
  }
22527
- return join15(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
21116
+ return join12(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
22528
21117
  }
22529
21118
  function readOptionalText(path) {
22530
21119
  try {
22531
- return readFileSync11(path, "utf8").trim();
21120
+ return readFileSync10(path, "utf8").trim();
22532
21121
  } catch {
22533
21122
  return "";
22534
21123
  }
@@ -22536,26 +21125,26 @@ function readOptionalText(path) {
22536
21125
  function resolvePythonSidecarUpdatePlan(options) {
22537
21126
  const stateDir = sidecarStateDir(options);
22538
21127
  if (!stateDir) return null;
22539
- const relativeEntrypoint = relative4(
22540
- resolve15(stateDir),
22541
- resolve15(options.entrypoint)
21128
+ const relativeEntrypoint = relative2(
21129
+ resolve12(stateDir),
21130
+ resolve12(options.entrypoint)
22542
21131
  );
22543
- if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || isAbsolute4(relativeEntrypoint)) {
21132
+ if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || isAbsolute2(relativeEntrypoint)) {
22544
21133
  return null;
22545
21134
  }
22546
- const installMethod = readOptionalText(join15(stateDir, ".install-method"));
21135
+ const installMethod = readOptionalText(join12(stateDir, ".install-method"));
22547
21136
  if (installMethod !== "python-sidecar") return null;
22548
21137
  const scope = options.env.DEEPLINE_CONFIG_SCOPE?.trim() || "";
22549
21138
  const hostUrl = options.env.DEEPLINE_HOST_URL?.trim() || "";
22550
- const nodeBin = readOptionalText(join15(stateDir, ".node-bin")) || process.execPath;
22551
- const sidecarPath = readOptionalText(join15(stateDir, ".command-path")) || join15(
21139
+ const nodeBin = readOptionalText(join12(stateDir, ".node-bin")) || process.execPath;
21140
+ const sidecarPath = readOptionalText(join12(stateDir, ".command-path")) || join12(
22552
21141
  stateDir,
22553
21142
  "bin",
22554
21143
  process.platform === "win32" ? "deepline-sdk.cmd" : "deepline-sdk"
22555
21144
  );
22556
21145
  const packageSpec = options.packageSpec || "deepline@latest";
22557
21146
  const npmCommand = "npm";
22558
- const manualCommand = `${npmCommand} install --prefix ${shellQuote3(join15(stateDir, "versions", "<version>"))} --no-audit --no-fund ${shellQuote3(packageSpec)}`;
21147
+ const manualCommand = `${npmCommand} install --prefix ${shellQuote3(join12(stateDir, "versions", "<version>"))} --no-audit --no-fund ${shellQuote3(packageSpec)}`;
22559
21148
  return {
22560
21149
  kind: "python-sidecar",
22561
21150
  stateDir,
@@ -22569,12 +21158,12 @@ function resolvePythonSidecarUpdatePlan(options) {
22569
21158
  };
22570
21159
  }
22571
21160
  function findRepoBackedSdkRoot(startPath) {
22572
- let current = resolve15(startPath);
21161
+ let current = resolve12(startPath);
22573
21162
  while (true) {
22574
- if (existsSync12(join15(current, "sdk", "package.json")) && existsSync12(join15(current, "sdk", "bin", "deepline-dev.ts"))) {
21163
+ if (existsSync10(join12(current, "sdk", "package.json")) && existsSync10(join12(current, "sdk", "bin", "deepline-dev.ts"))) {
22575
21164
  return current;
22576
21165
  }
22577
- const parent = dirname13(current);
21166
+ const parent = dirname10(current);
22578
21167
  if (parent === current) return null;
22579
21168
  current = parent;
22580
21169
  }
@@ -22582,8 +21171,8 @@ function findRepoBackedSdkRoot(startPath) {
22582
21171
  function resolveUpdatePlan(options = {}) {
22583
21172
  const env = options.env ?? process.env;
22584
21173
  const homeDir2 = options.homeDir ?? homedir10();
22585
- const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve15(process.argv[1]) : "");
22586
- const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname13(entrypoint)) : null;
21174
+ const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve12(process.argv[1]) : "");
21175
+ const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname10(entrypoint)) : null;
22587
21176
  if (sourceRoot) {
22588
21177
  return {
22589
21178
  kind: "source",
@@ -22613,7 +21202,7 @@ function safeVersionSegment(value) {
22613
21202
  return /^[0-9A-Za-z._-]+$/.test(normalized) ? normalized : "";
22614
21203
  }
22615
21204
  function entryPathInVersionDir(versionDir) {
22616
- return join15(
21205
+ return join12(
22617
21206
  versionDir,
22618
21207
  "node_modules",
22619
21208
  "deepline",
@@ -22623,14 +21212,14 @@ function entryPathInVersionDir(versionDir) {
22623
21212
  );
22624
21213
  }
22625
21214
  function installedPackageVersion(versionDir) {
22626
- const packageJsonPath = join15(
21215
+ const packageJsonPath = join12(
22627
21216
  versionDir,
22628
21217
  "node_modules",
22629
21218
  "deepline",
22630
21219
  "package.json"
22631
21220
  );
22632
21221
  try {
22633
- const parsed = JSON.parse(readFileSync11(packageJsonPath, "utf8"));
21222
+ const parsed = JSON.parse(readFileSync10(packageJsonPath, "utf8"));
22634
21223
  return typeof parsed.version === "string" ? safeVersionSegment(parsed.version) : "";
22635
21224
  } catch {
22636
21225
  return "";
@@ -22654,7 +21243,7 @@ function runCommand(command, args, env = process.env) {
22654
21243
  });
22655
21244
  }
22656
21245
  function writeSidecarLauncher(input2) {
22657
- mkdirSync8(dirname13(input2.path), { recursive: true });
21246
+ mkdirSync8(dirname10(input2.path), { recursive: true });
22658
21247
  if (process.platform === "win32") {
22659
21248
  writeFileSync13(
22660
21249
  input2.path,
@@ -22681,17 +21270,17 @@ function writeSidecarLauncher(input2) {
22681
21270
  );
22682
21271
  }
22683
21272
  async function runPythonSidecarUpdatePlan(plan) {
22684
- const versionsDir = join15(plan.stateDir, "versions");
22685
- const tempDir = join15(
21273
+ const versionsDir = join12(plan.stateDir, "versions");
21274
+ const tempDir = join12(
22686
21275
  versionsDir,
22687
21276
  `.tmp-sdk-update-${process.pid}-${Date.now()}`
22688
21277
  );
22689
21278
  rmSync3(tempDir, { recursive: true, force: true });
22690
21279
  mkdirSync8(tempDir, { recursive: true });
22691
- writeFileSync13(join15(tempDir, "package.json"), '{"private":true}\n', "utf8");
21280
+ writeFileSync13(join12(tempDir, "package.json"), '{"private":true}\n', "utf8");
22692
21281
  const env = {
22693
21282
  ...process.env,
22694
- PATH: `${dirname13(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
21283
+ PATH: `${dirname10(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
22695
21284
  };
22696
21285
  const installExitCode = await runCommand(
22697
21286
  plan.npmCommand,
@@ -22717,9 +21306,9 @@ async function runPythonSidecarUpdatePlan(plan) {
22717
21306
  rmSync3(tempDir, { recursive: true, force: true });
22718
21307
  return 1;
22719
21308
  }
22720
- const finalDir = join15(versionsDir, installedVersion);
21309
+ const finalDir = join12(versionsDir, installedVersion);
22721
21310
  const finalEntryPath = entryPathInVersionDir(finalDir);
22722
- if (existsSync12(finalEntryPath)) {
21311
+ if (existsSync10(finalEntryPath)) {
22723
21312
  rmSync3(tempDir, { recursive: true, force: true });
22724
21313
  } else {
22725
21314
  rmSync3(finalDir, { recursive: true, force: true });
@@ -22734,7 +21323,7 @@ async function runPythonSidecarUpdatePlan(plan) {
22734
21323
  return 1;
22735
21324
  }
22736
21325
  }
22737
- if (!existsSync12(finalEntryPath)) {
21326
+ if (!existsSync10(finalEntryPath)) {
22738
21327
  process.stderr.write(
22739
21328
  `Updated Deepline SDK CLI entrypoint missing: ${finalEntryPath}
22740
21329
  `
@@ -22749,27 +21338,27 @@ async function runPythonSidecarUpdatePlan(plan) {
22749
21338
  entryPath: finalEntryPath
22750
21339
  });
22751
21340
  writeFileSync13(
22752
- join15(plan.stateDir, ".version"),
21341
+ join12(plan.stateDir, ".version"),
22753
21342
  `${installedVersion}
22754
21343
  `,
22755
21344
  "utf8"
22756
21345
  );
22757
21346
  writeFileSync13(
22758
- join15(plan.stateDir, ".install-method"),
21347
+ join12(plan.stateDir, ".install-method"),
22759
21348
  "python-sidecar\n",
22760
21349
  "utf8"
22761
21350
  );
22762
21351
  writeFileSync13(
22763
- join15(plan.stateDir, ".command-path"),
21352
+ join12(plan.stateDir, ".command-path"),
22764
21353
  `${plan.sidecarPath}
22765
21354
  `,
22766
21355
  "utf8"
22767
21356
  );
22768
- writeFileSync13(join15(plan.stateDir, ".runner"), "node\n", "utf8");
22769
- writeFileSync13(join15(plan.stateDir, ".node-bin"), `${plan.nodeBin}
21357
+ writeFileSync13(join12(plan.stateDir, ".runner"), "node\n", "utf8");
21358
+ writeFileSync13(join12(plan.stateDir, ".node-bin"), `${plan.nodeBin}
22770
21359
  `, "utf8");
22771
21360
  writeFileSync13(
22772
- join15(plan.stateDir, ".entry-path"),
21361
+ join12(plan.stateDir, ".entry-path"),
22773
21362
  `${finalEntryPath}
22774
21363
  `,
22775
21364
  "utf8"
@@ -23056,7 +21645,7 @@ function shouldSkipSelfUpdate() {
23056
21645
  return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || isCi();
23057
21646
  }
23058
21647
  function relaunchCurrentCommand(plan) {
23059
- return new Promise((resolve16) => {
21648
+ return new Promise((resolve13) => {
23060
21649
  const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
23061
21650
  const args = plan.kind === "python-sidecar" ? process.argv.slice(2) : process.argv.slice(1);
23062
21651
  const child = spawn3(command, args, {
@@ -23072,9 +21661,9 @@ function relaunchCurrentCommand(plan) {
23072
21661
  `Deepline SDK/CLI updated, but relaunch failed: ${error.message}
23073
21662
  `
23074
21663
  );
23075
- resolve16(1);
21664
+ resolve13(1);
23076
21665
  });
23077
- child.on("close", (code) => resolve16(code ?? 1));
21666
+ child.on("close", (code) => resolve13(code ?? 1));
23078
21667
  });
23079
21668
  }
23080
21669
  async function maybeAutoUpdateAndRelaunch(response) {
@@ -23113,9 +21702,9 @@ async function maybeAutoUpdateAndRelaunch(response) {
23113
21702
 
23114
21703
  // src/cli/skills-sync.ts
23115
21704
  import { spawn as spawn4, spawnSync as spawnSync2 } from "child_process";
23116
- import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync14 } from "fs";
21705
+ import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync14 } from "fs";
23117
21706
  import { homedir as homedir11 } from "os";
23118
- import { dirname as dirname14, join as join16 } from "path";
21707
+ import { dirname as dirname11, join as join13 } from "path";
23119
21708
  var CHECK_TIMEOUT_MS2 = 3e3;
23120
21709
  var SDK_PLAY_SKILL_NAME = "deepline-plays";
23121
21710
  var attemptedSync = false;
@@ -23129,20 +21718,20 @@ function activePluginSkillsDir() {
23129
21718
  return "";
23130
21719
  }
23131
21720
  const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
23132
- return dir && existsSync13(dir) ? dir : "";
21721
+ return dir && existsSync11(dir) ? dir : "";
23133
21722
  }
23134
21723
  function readPluginSkillsVersion() {
23135
21724
  const dir = activePluginSkillsDir();
23136
21725
  if (!dir) return "";
23137
21726
  try {
23138
- return readFileSync12(join16(dir, ".version"), "utf-8").trim();
21727
+ return readFileSync11(join13(dir, ".version"), "utf-8").trim();
23139
21728
  } catch {
23140
21729
  return "";
23141
21730
  }
23142
21731
  }
23143
21732
  function sdkSkillsVersionPath(baseUrl) {
23144
21733
  const home = process.env.HOME?.trim() || homedir11();
23145
- return join16(
21734
+ return join13(
23146
21735
  home,
23147
21736
  ".local",
23148
21737
  "deepline",
@@ -23155,16 +21744,16 @@ function readLocalSkillsVersion(baseUrl) {
23155
21744
  const pluginVersion = readPluginSkillsVersion();
23156
21745
  if (pluginVersion) return pluginVersion;
23157
21746
  const path = sdkSkillsVersionPath(baseUrl);
23158
- if (!existsSync13(path)) return "";
21747
+ if (!existsSync11(path)) return "";
23159
21748
  try {
23160
- return readFileSync12(path, "utf-8").trim();
21749
+ return readFileSync11(path, "utf-8").trim();
23161
21750
  } catch {
23162
21751
  return "";
23163
21752
  }
23164
21753
  }
23165
21754
  function writeLocalSkillsVersion(baseUrl, version) {
23166
21755
  const path = sdkSkillsVersionPath(baseUrl);
23167
- mkdirSync9(dirname14(path), { recursive: true });
21756
+ mkdirSync9(dirname11(path), { recursive: true });
23168
21757
  writeFileSync14(path, `${version}
23169
21758
  `, "utf-8");
23170
21759
  }
@@ -23263,7 +21852,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
23263
21852
  return [npxInstall];
23264
21853
  }
23265
21854
  function runOneSkillsInstall(install) {
23266
- return new Promise((resolve16) => {
21855
+ return new Promise((resolve13) => {
23267
21856
  const child = spawn4(install.command, install.args, {
23268
21857
  stdio: ["ignore", "ignore", "pipe"],
23269
21858
  env: process.env
@@ -23273,7 +21862,7 @@ function runOneSkillsInstall(install) {
23273
21862
  stderr += chunk.toString("utf-8");
23274
21863
  });
23275
21864
  child.on("error", (error) => {
23276
- resolve16({
21865
+ resolve13({
23277
21866
  ok: false,
23278
21867
  detail: `failed to start ${install.command}: ${error.message}`,
23279
21868
  manualCommand: install.manualCommand
@@ -23281,11 +21870,11 @@ function runOneSkillsInstall(install) {
23281
21870
  });
23282
21871
  child.on("close", (code) => {
23283
21872
  if (code === 0) {
23284
- resolve16({ ok: true, detail: "", manualCommand: install.manualCommand });
21873
+ resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
23285
21874
  return;
23286
21875
  }
23287
21876
  const detail = stderr.trim();
23288
- resolve16({
21877
+ resolve13({
23289
21878
  ok: false,
23290
21879
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
23291
21880
  manualCommand: install.manualCommand
@@ -23631,10 +22220,10 @@ function topLevelCommandKnown(program, commandName) {
23631
22220
  );
23632
22221
  }
23633
22222
  async function runPlayRunnerHealthCheck() {
23634
- const dir = await mkdtemp2(join17(tmpdir5(), "deepline-health-play-"));
23635
- const file = join17(dir, "health-check.play.ts");
22223
+ const dir = await mkdtemp2(join14(tmpdir3(), "deepline-health-play-"));
22224
+ const file = join14(dir, "health-check.play.ts");
23636
22225
  try {
23637
- await writeFile6(
22226
+ await writeFile5(
23638
22227
  file,
23639
22228
  [
23640
22229
  "import { definePlay } from 'deepline';",