deepline 0.1.199 → 0.1.200

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 (72) hide show
  1. package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +5 -1
  2. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +51 -17
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/README.md +1 -1
  4. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +16 -0
  5. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/receipts.ts +40 -9
  6. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-dispatch.ts +108 -39
  7. package/dist/bundling-sources/sdk/src/http.ts +5 -2
  8. package/dist/bundling-sources/sdk/src/play.ts +1 -1
  9. package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +7 -0
  10. package/dist/bundling-sources/sdk/src/release.ts +2 -2
  11. package/dist/bundling-sources/sdk/src/worker-play-entry.ts +11 -55
  12. package/dist/bundling-sources/shared_libs/play-runtime/adaptive-tool-dispatcher.ts +355 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +172 -73
  14. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +1794 -377
  15. package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +3 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +67 -4
  17. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +161 -39
  18. package/dist/bundling-sources/shared_libs/play-runtime/governor/adaptive-admission.ts +218 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +1 -1
  20. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +115 -25
  21. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +17 -17
  22. package/dist/bundling-sources/shared_libs/play-runtime/lease-policy.ts +22 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +2 -1
  24. package/dist/bundling-sources/shared_libs/play-runtime/live-events.ts +0 -1
  25. package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +265 -0
  26. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +135 -0
  27. package/dist/bundling-sources/shared_libs/play-runtime/play-input.ts +17 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +0 -3
  29. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +10 -1
  30. package/dist/bundling-sources/shared_libs/play-runtime/providers.ts +9 -15
  31. package/dist/bundling-sources/shared_libs/play-runtime/receipt-completion-sink.ts +262 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/receipt-heartbeat-supervisor.ts +64 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/receipt-sql.ts +76 -8
  34. package/dist/bundling-sources/shared_libs/play-runtime/receipt-state-sink.ts +59 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +3 -2
  36. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +269 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +2 -3
  38. package/dist/bundling-sources/shared_libs/play-runtime/run-terminal-source.ts +0 -1
  39. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +433 -0
  40. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +227 -0
  41. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +882 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +573 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/bundle.ts +264 -0
  44. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/index.ts +33 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runner-events.ts +35 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +53 -0
  47. package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +0 -1
  48. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +459 -103
  49. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +12 -0
  50. package/dist/bundling-sources/shared_libs/play-runtime/runtime-infra-mode.ts +23 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-attempt-state-machine.ts +23 -2
  52. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +16 -24
  53. package/dist/bundling-sources/shared_libs/play-runtime/serial-task-queue.ts +26 -0
  54. package/dist/bundling-sources/shared_libs/play-runtime/submit-limits.ts +1 -1
  55. package/dist/bundling-sources/shared_libs/play-runtime/vercel-protection.ts +81 -0
  56. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-state-machine.ts +54 -9
  57. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +17 -3
  58. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +0 -20
  59. package/dist/bundling-sources/shared_libs/plays/dataset.ts +105 -4
  60. package/dist/bundling-sources/shared_libs/plays/row-identity.ts +4 -11
  61. package/dist/cli/index.js +167 -54
  62. package/dist/cli/index.mjs +167 -54
  63. package/dist/index.d.mts +1 -1
  64. package/dist/index.d.ts +1 -1
  65. package/dist/index.js +8 -8
  66. package/dist/index.mjs +8 -8
  67. package/dist/plays/bundle-play-file.mjs +15 -20
  68. package/package.json +1 -1
  69. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-diagnosis.ts +0 -321
  70. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-target.ts +0 -158
  71. package/dist/bundling-sources/shared_libs/temporal/constants.ts +0 -39
  72. package/dist/bundling-sources/shared_libs/temporal/preview-config.ts +0 -150
@@ -608,10 +608,10 @@ var SDK_RELEASE = {
608
608
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
609
609
  // fields shipped in 0.1.153.
610
610
  // 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
611
- version: "0.1.199",
611
+ version: "0.1.200",
612
612
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
613
613
  supportPolicy: {
614
- latest: "0.1.199",
614
+ latest: "0.1.200",
615
615
  minimumSupported: "0.1.53",
616
616
  deprecatedBelow: "0.1.53",
617
617
  commandMinimumSupported: [
@@ -1052,7 +1052,10 @@ var HttpClient = class {
1052
1052
  * @param path - API path (e.g. `"/api/v2/tools"`)
1053
1053
  */
1054
1054
  async get(path) {
1055
- return this.request(path, { method: "GET" });
1055
+ return this.request(path, {
1056
+ method: "GET",
1057
+ retryApiErrors: true
1058
+ });
1056
1059
  }
1057
1060
  async *streamSse(path, options) {
1058
1061
  const url = `${this.config.baseUrl}${path}`;
@@ -1326,7 +1329,6 @@ function resolveTimingWindow(input2) {
1326
1329
  // ../shared_libs/play-runtime/run-terminal-source.ts
1327
1330
  var PLAY_RUN_LEDGER_EVENT_SOURCES = [
1328
1331
  "worker",
1329
- "temporal",
1330
1332
  "convex",
1331
1333
  "coordinator",
1332
1334
  "system"
@@ -7033,7 +7035,7 @@ function isRecord4(value) {
7033
7035
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
7034
7036
  }
7035
7037
  function isSerializedDataset(value) {
7036
- return isRecord4(value) && value.kind === "dataset" && typeof value.count === "number" && Array.isArray(value.preview);
7038
+ return isRecord4(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
7037
7039
  }
7038
7040
  function isPackagedDatasetOutput(value) {
7039
7041
  return isRecord4(value) && value.kind === "dataset" && isRecord4(value.preview) && Array.isArray(value.preview.rows);
@@ -7094,7 +7096,7 @@ function columnsFromDatasetSummary(summary) {
7094
7096
  function canonicalRowsInfoFromCandidate(input2) {
7095
7097
  const candidate = input2;
7096
7098
  if (isSerializedDataset(candidate.value)) {
7097
- const rawRows = rowArray(candidate.value.preview) ?? [];
7099
+ const rawRows = Array.isArray(candidate.value.preview) ? rowArray(candidate.value.preview) ?? [] : [];
7098
7100
  const totalRows2 = readNumber(candidate.value.count) ?? rawRows.length;
7099
7101
  const hasExplicitColumns = Array.isArray(candidate.value.columns) && candidate.value.columns.every((column) => typeof column === "string");
7100
7102
  const rawColumns = hasExplicitColumns ? candidate.value.columns : inferColumns(rawRows);
@@ -7322,6 +7324,13 @@ function collectSerializedDatasetRowsInfos(statusOrResult) {
7322
7324
  path: "result",
7323
7325
  output: candidates
7324
7326
  });
7327
+ if (isRecord4(result.output)) {
7328
+ collectDatasetCandidates({
7329
+ value: result.output,
7330
+ path: "result",
7331
+ output: candidates
7332
+ });
7333
+ }
7325
7334
  }
7326
7335
  candidates.push(...collectPackagedStepDatasetCandidates(statusOrResult));
7327
7336
  const seen = /* @__PURE__ */ new Set();
@@ -10440,22 +10449,22 @@ var PLAY_DEDUP_BACKENDS = {
10440
10449
 
10441
10450
  // ../shared_libs/play-runtime/scheduler-backend.ts
10442
10451
  var PLAY_SCHEDULER_BACKENDS = {
10443
- temporal: "temporal",
10444
10452
  cfWorkflows: "cf-workflows",
10453
+ /** Private legacy id retained only so old persisted rows can be interpreted. */
10454
+ postgres: "postgres",
10445
10455
  /**
10446
- * Private legacy id retained only so old persisted rows can be interpreted.
10447
- * It is not a selectable scheduler backend after the Hatchet hard cutover.
10456
+ * Postgres-native durable-execution scheduler (vendored Absurd engine). Runs
10457
+ * on the battle-tested run-state store without an external workflow engine.
10458
+ * Selected explicitly by the `absurd` profile.
10448
10459
  */
10449
- postgres: "postgres",
10450
- hatchet: "hatchet",
10460
+ absurd: "absurd",
10451
10461
  inProcess: "in-process"
10452
10462
  };
10453
10463
 
10454
10464
  // ../shared_libs/play-runtime/providers.ts
10455
10465
  var PLAY_RUNTIME_PROVIDER_IDS = {
10456
10466
  workersEdge: "workers_edge",
10457
- hatchet: "hatchet",
10458
- local: "local"
10467
+ absurd: "absurd"
10459
10468
  };
10460
10469
  var PLAY_RUNTIME_PROVIDERS = {
10461
10470
  workers_edge: {
@@ -10466,21 +10475,16 @@ var PLAY_RUNTIME_PROVIDERS = {
10466
10475
  artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
10467
10476
  label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
10468
10477
  },
10469
- hatchet: {
10470
- id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
10471
- scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
10478
+ absurd: {
10479
+ id: PLAY_RUNTIME_PROVIDER_IDS.absurd,
10480
+ scheduler: PLAY_SCHEDULER_BACKENDS.absurd,
10481
+ // Server runs execute on Daytona; the local-dev/test shape swaps the runner
10482
+ // axis to local_process (same as the local profile) via an explicit
10483
+ // runtimeBackend override at submit while tests drive local_process.
10472
10484
  runner: PLAY_RUNTIME_BACKENDS.daytona,
10473
10485
  dedup: PLAY_DEDUP_BACKENDS.inMemory,
10474
10486
  artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
10475
- label: "Hatchet scheduler + one-shot Daytona runner + receipt-backed in-process dedup"
10476
- },
10477
- local: {
10478
- id: PLAY_RUNTIME_PROVIDER_IDS.local,
10479
- scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
10480
- runner: PLAY_RUNTIME_BACKENDS.localProcess,
10481
- dedup: PLAY_DEDUP_BACKENDS.inMemory,
10482
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
10483
- label: "Local Temporal scheduler + local subprocess runner (tests)"
10487
+ label: "Absurd (Postgres-native durable) scheduler + one-shot Daytona runner + receipt-backed in-process dedup"
10484
10488
  }
10485
10489
  };
10486
10490
  function defaultPlayRuntimeProvider() {
@@ -10493,7 +10497,7 @@ function resolvePlayRuntimeProvider(override) {
10493
10497
  return PLAY_RUNTIME_PROVIDERS[id];
10494
10498
  }
10495
10499
  throw new Error(
10496
- `Unknown play runtime provider "${id}". Expected one of: ${Object.keys(
10500
+ `Unsupported play runtime provider "${id}". Expected one of: ${Object.keys(
10497
10501
  PLAY_RUNTIME_PROVIDERS
10498
10502
  ).join(", ")}.`
10499
10503
  );
@@ -14017,7 +14021,7 @@ function writeStartedPlayRun(input2) {
14017
14021
  );
14018
14022
  }
14019
14023
  function parsePlayRunOptions(args) {
14020
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n --profile defaults to workers_edge; pass hatchet explicitly for Hatchet runtime comparison.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
14024
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n --profile defaults to workers_edge, unless your local dev server exports a dev default such as absurd.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
14021
14025
  let filePath = null;
14022
14026
  let playName = null;
14023
14027
  let input2 = null;
@@ -18963,7 +18967,8 @@ async function writeOutputCsv(outputPath, status, options) {
18963
18967
  }
18964
18968
  const selectedSourceRows = selectedSourceCsvRowCount(options);
18965
18969
  const shouldFetchBackingRows = options?.client && shouldFetchBackingRowsForEnrichExport(rowsInfo, status, {
18966
- selectedSourceRows
18970
+ selectedSourceRows,
18971
+ expectedAliases: options?.config ? collectConfigScalarAliasOrder(options.config) : []
18967
18972
  });
18968
18973
  if (options?.client && shouldFetchBackingRows) {
18969
18974
  let fetchedRowsInfo = null;
@@ -19000,6 +19005,7 @@ async function writeOutputCsv(outputPath, status, options) {
19000
19005
  const columns = orderEnrichCsvColumns(
19001
19006
  dataExportColumns(merged.rows, [
19002
19007
  ...merged.preferredColumns,
19008
+ ...options?.config ? collectConfigScalarAliasOrder(options.config) : [],
19003
19009
  ...rowsInfo.columns
19004
19010
  ]),
19005
19011
  options?.config
@@ -19657,26 +19663,39 @@ function shouldFetchBackingRowsForEnrichExport(rowsInfo, status, options = {}) {
19657
19663
  rowsInfo,
19658
19664
  status
19659
19665
  );
19666
+ const isGeneratedEnrichRows = tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
19660
19667
  if (terminalStatus === "failed" || terminalStatus === "cancelled") {
19661
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && rowsInfo.source !== null && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19668
+ if (isGeneratedEnrichRows && rowsInfo.source !== null && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19662
19669
  return true;
19663
19670
  }
19664
- return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && (rowsInfo.recovered === true || hasPartialRunOutputWarning(status));
19671
+ return isGeneratedEnrichRows && (rowsInfo.recovered === true || hasPartialRunOutputWarning(status));
19665
19672
  }
19666
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19673
+ if (isGeneratedEnrichRows && typeof options.selectedSourceRows === "number" && rowsInfo.rows.length < options.selectedSourceRows) {
19667
19674
  return true;
19668
19675
  }
19669
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && typeof options.selectedSourceRows === "number" && options.selectedSourceRows > 0) {
19676
+ if (isGeneratedEnrichRows && (typeof options.selectedSourceRows === "number" && options.selectedSourceRows > 0 || rowsMissingExpectedAlias(rowsInfo.rows, options.expectedAliases))) {
19670
19677
  return true;
19671
19678
  }
19672
- if (tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE && hasFailedRowSignal(status)) {
19679
+ if (isGeneratedEnrichRows && hasFailedRowSignal(status)) {
19673
19680
  return true;
19674
19681
  }
19675
19682
  if (!rowsInfo.complete) {
19676
- return tableNamespace === GENERATED_ENRICH_ROWS_TABLE_NAMESPACE;
19683
+ return isGeneratedEnrichRows;
19677
19684
  }
19678
19685
  return rowsInfo.rows.some((row) => hasLossyPreviewPlaceholder(row));
19679
19686
  }
19687
+ function rowsMissingExpectedAlias(rows, expectedAliases) {
19688
+ if (rows.length === 0 || !expectedAliases?.length) {
19689
+ return false;
19690
+ }
19691
+ const rowAliases = /* @__PURE__ */ new Set();
19692
+ for (const row of rows) {
19693
+ for (const key of Object.keys(row)) {
19694
+ rowAliases.add(normalizeAlias2(key));
19695
+ }
19696
+ }
19697
+ return expectedAliases.map((alias) => normalizeAlias2(alias)).filter(Boolean).some((alias) => !rowAliases.has(alias));
19698
+ }
19680
19699
  function hasPartialRunOutputWarning(status) {
19681
19700
  const warningLists = [
19682
19701
  recordField(status, "warnings"),
@@ -20242,6 +20261,18 @@ function collectEmptyWaterfallIssues(input2) {
20242
20261
  if (executionSignal === "all_condition_skipped" || executionSignal === "unknown" && waterfallChildrenAreStaticallySkipped(spec)) {
20243
20262
  return;
20244
20263
  }
20264
+ const statsEvidence = emptyWaterfallStatsEvidence(input2.status, spec);
20265
+ if (statsEvidence && input2.rowSetComplete && input2.outputPath) {
20266
+ issues.push(
20267
+ emptyWaterfallIssue({
20268
+ spec,
20269
+ selectedRows: statsEvidence.selectedRows,
20270
+ runId,
20271
+ followUpCommands
20272
+ })
20273
+ );
20274
+ return;
20275
+ }
20245
20276
  const logicalRows = /* @__PURE__ */ new Map();
20246
20277
  input2.rows.forEach((row, rowIndex) => {
20247
20278
  const sourceRowId = sourceRowIndexFromEnrichRow(
@@ -20263,24 +20294,34 @@ function collectEmptyWaterfallIssues(input2) {
20263
20294
  return;
20264
20295
  }
20265
20296
  const selectedRows = logicalRows.size;
20266
- const message = `Waterfall ${spec.alias} produced 0 values for ${selectedRows} selected row(s).`;
20267
- issues.push({
20268
- issue_id: `${spec.alias}-empty-waterfall`,
20269
- kind: "empty_waterfall",
20270
- severity: "needs_attention",
20271
- column: spec.alias,
20272
- selected_rows: selectedRows,
20273
- rows_with_value: 0,
20274
- rows_without_value: selectedRows,
20275
- message,
20276
- next_steps: enrichIssueNextSteps({ runId }),
20277
- follow_up_commands: followUpCommands,
20278
- ...spec.operation ? { operation: spec.operation } : {},
20279
- ...runId ? { run_id: runId } : {}
20280
- });
20297
+ issues.push(
20298
+ emptyWaterfallIssue({
20299
+ spec,
20300
+ selectedRows,
20301
+ runId,
20302
+ followUpCommands
20303
+ })
20304
+ );
20281
20305
  });
20282
20306
  return issues;
20283
20307
  }
20308
+ function emptyWaterfallIssue(input2) {
20309
+ const message = `Waterfall ${input2.spec.alias} produced 0 values for ${input2.selectedRows} selected row(s).`;
20310
+ return {
20311
+ issue_id: `${input2.spec.alias}-empty-waterfall`,
20312
+ kind: "empty_waterfall",
20313
+ severity: "needs_attention",
20314
+ column: input2.spec.alias,
20315
+ selected_rows: input2.selectedRows,
20316
+ rows_with_value: 0,
20317
+ rows_without_value: input2.selectedRows,
20318
+ message,
20319
+ next_steps: enrichIssueNextSteps({ runId: input2.runId }),
20320
+ follow_up_commands: input2.followUpCommands,
20321
+ ...input2.spec.operation ? { operation: input2.spec.operation } : {},
20322
+ ...input2.runId ? { run_id: input2.runId } : {}
20323
+ };
20324
+ }
20284
20325
  function waterfallChildrenAreStaticallySkipped(spec) {
20285
20326
  const childAliases = spec.childAliases ?? [];
20286
20327
  if (childAliases.length === 0 || !spec.childRunIfJsByAlias) {
@@ -20314,14 +20355,18 @@ function waterfallExecutionSignal(status, spec) {
20314
20355
  const executedSummary = parseExecutionSummary(
20315
20356
  execution?.["completed:executed"]
20316
20357
  );
20358
+ const reusedSummary = parseExecutionSummary(
20359
+ execution?.["completed:reused"]
20360
+ );
20317
20361
  const skippedConditionSummary = parseExecutionSummary(
20318
20362
  execution?.["skipped:condition"]
20319
20363
  );
20320
20364
  const executedCount = executedSummary?.count ?? 0;
20365
+ const reusedCount = reusedSummary?.count ?? 0;
20321
20366
  const skippedConditionCount = skippedConditionSummary?.count ?? 0;
20322
- const totalCount = executedSummary?.total ?? skippedConditionSummary?.total;
20323
- const onlyConditionSkips = totalCount !== void 0 && skippedConditionCount >= totalCount && executedCount <= skippedConditionCount;
20324
- if (executedCount > 0 && !onlyConditionSkips || numericFailedRowSignal(execution?.failed) > 0 || numericFailedRowSignal(stat2.failed) > 0 || numericFailedRowSignal(stat2.failedRows) > 0) {
20367
+ const totalCount = executedSummary?.total ?? reusedSummary?.total ?? skippedConditionSummary?.total;
20368
+ const onlyConditionSkips = totalCount !== void 0 && skippedConditionCount >= totalCount && executedCount + reusedCount <= skippedConditionCount;
20369
+ if (executedCount + reusedCount > 0 && !onlyConditionSkips || numericFailedRowSignal(execution?.failed) > 0 || numericFailedRowSignal(stat2.failed) > 0 || numericFailedRowSignal(stat2.failedRows) > 0) {
20325
20370
  return "executed";
20326
20371
  }
20327
20372
  if (!onlyConditionSkips) {
@@ -20334,6 +20379,48 @@ function waterfallExecutionSignal(status, spec) {
20334
20379
  }
20335
20380
  return "unknown";
20336
20381
  }
20382
+ function emptyWaterfallStatsEvidence(status, spec) {
20383
+ const summaries = collectColumnStats(status);
20384
+ const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord7);
20385
+ for (const stat2 of parentStats) {
20386
+ const nonEmpty = parseExecutionSummary(stat2.non_empty);
20387
+ if (nonEmpty?.total && nonEmpty.count === 0) {
20388
+ return { selectedRows: nonEmpty.total };
20389
+ }
20390
+ }
20391
+ const childAliases = spec.childAliases ?? [];
20392
+ if (childAliases.length === 0) {
20393
+ return null;
20394
+ }
20395
+ let selectedRows = 0;
20396
+ let sawStatsForEveryChild = true;
20397
+ for (const childAlias of childAliases) {
20398
+ const stat2 = summaries.map((summary) => summary[childAlias]).find(isRecord7);
20399
+ if (!stat2) {
20400
+ sawStatsForEveryChild = false;
20401
+ break;
20402
+ }
20403
+ const nonEmpty = parseExecutionSummary(stat2.non_empty);
20404
+ if ((nonEmpty?.count ?? 0) > 0) {
20405
+ return null;
20406
+ }
20407
+ const execution = isRecord7(stat2.execution) ? stat2.execution : null;
20408
+ const executed = parseExecutionSummary(execution?.["completed:executed"]);
20409
+ const reused = parseExecutionSummary(execution?.["completed:reused"]);
20410
+ const skipped = parseExecutionSummary(execution?.["skipped:condition"]);
20411
+ selectedRows = Math.max(
20412
+ selectedRows,
20413
+ nonEmpty?.total ?? 0,
20414
+ executed?.total ?? 0,
20415
+ reused?.total ?? 0,
20416
+ skipped?.total ?? 0
20417
+ );
20418
+ }
20419
+ if (!sawStatsForEveryChild || selectedRows <= 0 || waterfallExecutionSignal(status, spec) === "all_condition_skipped") {
20420
+ return null;
20421
+ }
20422
+ return { selectedRows };
20423
+ }
20337
20424
  function mergeEnrichFailureJobs(...jobGroups) {
20338
20425
  const merged = [];
20339
20426
  const seen = /* @__PURE__ */ new Set();
@@ -21153,12 +21240,34 @@ var ENRICH_FLATTENED_CONTROL_FIELDS = /* @__PURE__ */ new Set([
21153
21240
  "provider",
21154
21241
  "status"
21155
21242
  ]);
21243
+ var ENRICH_ALIAS_METADATA_FIELDS = /* @__PURE__ */ new Set([
21244
+ "_metadata",
21245
+ "metadata",
21246
+ "metadata.columns",
21247
+ "metadata__columns"
21248
+ ]);
21249
+ function isEnrichAliasPayloadField(field) {
21250
+ return !field.startsWith("_") && !ENRICH_FLATTENED_CONTROL_FIELDS.has(field) && !ENRICH_ALIAS_METADATA_FIELDS.has(field);
21251
+ }
21156
21252
  function materializeCsvCellValue(value) {
21157
21253
  if (value && typeof value === "object") {
21158
21254
  return csvSafeJsonString(value);
21159
21255
  }
21160
21256
  return value;
21161
21257
  }
21258
+ function compactArrayEnvelopeCompleteValue(value) {
21259
+ if (!isRecord7(value) || value.kind !== "array") {
21260
+ return null;
21261
+ }
21262
+ if (!Array.isArray(value.preview)) {
21263
+ return null;
21264
+ }
21265
+ const length = typeof value.length === "number" && Number.isFinite(value.length) ? Math.max(0, Math.trunc(value.length)) : null;
21266
+ if (length === null || length > value.preview.length) {
21267
+ return null;
21268
+ }
21269
+ return value.preview.slice(0, length);
21270
+ }
21162
21271
  function disambiguateCompactAiInferencePayload(value) {
21163
21272
  const parsed = parseMaybeJsonObject(value);
21164
21273
  if (!isRecord7(parsed) || !cellFailureError(parsed)) {
@@ -21195,6 +21304,10 @@ function compactAiInferenceCellForCsv(value) {
21195
21304
  function materializeEnrichAliasCellForCsv(row, alias, options) {
21196
21305
  const direct = row[alias];
21197
21306
  if (isRecord7(direct)) {
21307
+ const completeArray = compactArrayEnvelopeCompleteValue(direct);
21308
+ if (completeArray) {
21309
+ return materializeCsvCellValue(completeArray);
21310
+ }
21198
21311
  if (options?.compactAiCell && direct.status === "completed" && (isRecord7(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
21199
21312
  return materializeCsvCellValue(compactAiInferenceCellForCsv(direct));
21200
21313
  }
@@ -21203,7 +21316,7 @@ function materializeEnrichAliasCellForCsv(row, alias, options) {
21203
21316
  }
21204
21317
  const directCells = [];
21205
21318
  for (const [field, value] of Object.entries(direct)) {
21206
- if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
21319
+ if (!isEnrichAliasPayloadField(field)) {
21207
21320
  continue;
21208
21321
  }
21209
21322
  if (isNonEmptyCsvCell(value)) {
@@ -21233,7 +21346,7 @@ function materializeEnrichAliasCellForCsv(row, alias, options) {
21233
21346
  }
21234
21347
  }
21235
21348
  const cells = aliasFlattenedCells(row, alias).filter(({ field, value }) => {
21236
- if (ENRICH_FLATTENED_CONTROL_FIELDS.has(field)) {
21349
+ if (!isEnrichAliasPayloadField(field)) {
21237
21350
  return false;
21238
21351
  }
21239
21352
  return isNonEmptyCsvCell(value);
package/dist/index.d.mts CHANGED
@@ -3640,7 +3640,7 @@ interface DeeplinePlayRuntimeContext {
3640
3640
  *
3641
3641
  * // Poll status
3642
3642
  * const status = await job.status();
3643
- * console.log(status.temporalStatus); // 'RUNNING'
3643
+ * console.log(status.status); // 'running'
3644
3644
  *
3645
3645
  * // Stream logs until completion
3646
3646
  * const finalStatus = await job.tail({
package/dist/index.d.ts CHANGED
@@ -3640,7 +3640,7 @@ interface DeeplinePlayRuntimeContext {
3640
3640
  *
3641
3641
  * // Poll status
3642
3642
  * const status = await job.status();
3643
- * console.log(status.temporalStatus); // 'RUNNING'
3643
+ * console.log(status.status); // 'running'
3644
3644
  *
3645
3645
  * // Stream logs until completion
3646
3646
  * const finalStatus = await job.tail({
package/dist/index.js CHANGED
@@ -422,10 +422,10 @@ var SDK_RELEASE = {
422
422
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
423
423
  // fields shipped in 0.1.153.
424
424
  // 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
425
- version: "0.1.199",
425
+ version: "0.1.200",
426
426
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
427
427
  supportPolicy: {
428
- latest: "0.1.199",
428
+ latest: "0.1.200",
429
429
  minimumSupported: "0.1.53",
430
430
  deprecatedBelow: "0.1.53",
431
431
  commandMinimumSupported: [
@@ -866,7 +866,10 @@ var HttpClient = class {
866
866
  * @param path - API path (e.g. `"/api/v2/tools"`)
867
867
  */
868
868
  async get(path) {
869
- return this.request(path, { method: "GET" });
869
+ return this.request(path, {
870
+ method: "GET",
871
+ retryApiErrors: true
872
+ });
870
873
  }
871
874
  async *streamSse(path, options) {
872
875
  const url = `${this.config.baseUrl}${path}`;
@@ -1140,7 +1143,6 @@ function resolveTimingWindow(input) {
1140
1143
  // ../shared_libs/play-runtime/run-terminal-source.ts
1141
1144
  var PLAY_RUN_LEDGER_EVENT_SOURCES = [
1142
1145
  "worker",
1143
- "temporal",
1144
1146
  "convex",
1145
1147
  "coordinator",
1146
1148
  "system"
@@ -4772,13 +4774,11 @@ function sanitizeIdentifierPart(value) {
4772
4774
  function validateIdentifierPart(rawValue, label, maxLength) {
4773
4775
  const sanitized = sanitizeIdentifierPart(rawValue);
4774
4776
  if (!sanitized) {
4775
- throw new Error(
4776
- `${label} must contain at least one letter or number after normalization. Use only letters, numbers, underscores, or hyphens.`
4777
- );
4777
+ throw new Error(`${label} must contain a letter or number.`);
4778
4778
  }
4779
4779
  if (sanitized.length > maxLength) {
4780
4780
  throw new Error(
4781
- `${label} is too long after normalization (${sanitized.length}/${maxLength}). Shorten it to ${maxLength} characters or fewer. Normalized value: "${sanitized}".`
4781
+ `${label} is too long after normalization (${sanitized.length}/${maxLength}): "${sanitized}".`
4782
4782
  );
4783
4783
  }
4784
4784
  return sanitized;
package/dist/index.mjs CHANGED
@@ -352,10 +352,10 @@ var SDK_RELEASE = {
352
352
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
353
353
  // fields shipped in 0.1.153.
354
354
  // 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
355
- version: "0.1.199",
355
+ version: "0.1.200",
356
356
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
357
357
  supportPolicy: {
358
- latest: "0.1.199",
358
+ latest: "0.1.200",
359
359
  minimumSupported: "0.1.53",
360
360
  deprecatedBelow: "0.1.53",
361
361
  commandMinimumSupported: [
@@ -796,7 +796,10 @@ var HttpClient = class {
796
796
  * @param path - API path (e.g. `"/api/v2/tools"`)
797
797
  */
798
798
  async get(path) {
799
- return this.request(path, { method: "GET" });
799
+ return this.request(path, {
800
+ method: "GET",
801
+ retryApiErrors: true
802
+ });
800
803
  }
801
804
  async *streamSse(path, options) {
802
805
  const url = `${this.config.baseUrl}${path}`;
@@ -1070,7 +1073,6 @@ function resolveTimingWindow(input) {
1070
1073
  // ../shared_libs/play-runtime/run-terminal-source.ts
1071
1074
  var PLAY_RUN_LEDGER_EVENT_SOURCES = [
1072
1075
  "worker",
1073
- "temporal",
1074
1076
  "convex",
1075
1077
  "coordinator",
1076
1078
  "system"
@@ -4702,13 +4704,11 @@ function sanitizeIdentifierPart(value) {
4702
4704
  function validateIdentifierPart(rawValue, label, maxLength) {
4703
4705
  const sanitized = sanitizeIdentifierPart(rawValue);
4704
4706
  if (!sanitized) {
4705
- throw new Error(
4706
- `${label} must contain at least one letter or number after normalization. Use only letters, numbers, underscores, or hyphens.`
4707
- );
4707
+ throw new Error(`${label} must contain a letter or number.`);
4708
4708
  }
4709
4709
  if (sanitized.length > maxLength) {
4710
4710
  throw new Error(
4711
- `${label} is too long after normalization (${sanitized.length}/${maxLength}). Shorten it to ${maxLength} characters or fewer. Normalized value: "${sanitized}".`
4711
+ `${label} is too long after normalization (${sanitized.length}/${maxLength}): "${sanitized}".`
4712
4712
  );
4713
4713
  }
4714
4714
  return sanitized;
@@ -1733,22 +1733,22 @@ var PLAY_DEDUP_BACKENDS = {
1733
1733
 
1734
1734
  // ../shared_libs/play-runtime/scheduler-backend.ts
1735
1735
  var PLAY_SCHEDULER_BACKENDS = {
1736
- temporal: "temporal",
1737
1736
  cfWorkflows: "cf-workflows",
1737
+ /** Private legacy id retained only so old persisted rows can be interpreted. */
1738
+ postgres: "postgres",
1738
1739
  /**
1739
- * Private legacy id retained only so old persisted rows can be interpreted.
1740
- * It is not a selectable scheduler backend after the Hatchet hard cutover.
1740
+ * Postgres-native durable-execution scheduler (vendored Absurd engine). Runs
1741
+ * on the battle-tested run-state store without an external workflow engine.
1742
+ * Selected explicitly by the `absurd` profile.
1741
1743
  */
1742
- postgres: "postgres",
1743
- hatchet: "hatchet",
1744
+ absurd: "absurd",
1744
1745
  inProcess: "in-process"
1745
1746
  };
1746
1747
 
1747
1748
  // ../shared_libs/play-runtime/providers.ts
1748
1749
  var PLAY_RUNTIME_PROVIDER_IDS = {
1749
1750
  workersEdge: "workers_edge",
1750
- hatchet: "hatchet",
1751
- local: "local"
1751
+ absurd: "absurd"
1752
1752
  };
1753
1753
  var PLAY_RUNTIME_PROVIDERS = {
1754
1754
  workers_edge: {
@@ -1759,21 +1759,16 @@ var PLAY_RUNTIME_PROVIDERS = {
1759
1759
  artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
1760
1760
  label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
1761
1761
  },
1762
- hatchet: {
1763
- id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
1764
- scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
1762
+ absurd: {
1763
+ id: PLAY_RUNTIME_PROVIDER_IDS.absurd,
1764
+ scheduler: PLAY_SCHEDULER_BACKENDS.absurd,
1765
+ // Server runs execute on Daytona; the local-dev/test shape swaps the runner
1766
+ // axis to local_process (same as the local profile) via an explicit
1767
+ // runtimeBackend override at submit while tests drive local_process.
1765
1768
  runner: PLAY_RUNTIME_BACKENDS.daytona,
1766
1769
  dedup: PLAY_DEDUP_BACKENDS.inMemory,
1767
1770
  artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
1768
- label: "Hatchet scheduler + one-shot Daytona runner + receipt-backed in-process dedup"
1769
- },
1770
- local: {
1771
- id: PLAY_RUNTIME_PROVIDER_IDS.local,
1772
- scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
1773
- runner: PLAY_RUNTIME_BACKENDS.localProcess,
1774
- dedup: PLAY_DEDUP_BACKENDS.inMemory,
1775
- artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
1776
- label: "Local Temporal scheduler + local subprocess runner (tests)"
1771
+ label: "Absurd (Postgres-native durable) scheduler + one-shot Daytona runner + receipt-backed in-process dedup"
1777
1772
  }
1778
1773
  };
1779
1774
  function defaultPlayRuntimeProvider() {
@@ -1786,7 +1781,7 @@ function resolvePlayRuntimeProvider(override) {
1786
1781
  return PLAY_RUNTIME_PROVIDERS[id];
1787
1782
  }
1788
1783
  throw new Error(
1789
- `Unknown play runtime provider "${id}". Expected one of: ${Object.keys(
1784
+ `Unsupported play runtime provider "${id}". Expected one of: ${Object.keys(
1790
1785
  PLAY_RUNTIME_PROVIDERS
1791
1786
  ).join(", ")}.`
1792
1787
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.199",
3
+ "version": "0.1.200",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {