deepline 0.1.213 → 0.1.215

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 (32) hide show
  1. package/dist/bundling-sources/apps/play-runner-workers/src/child-manifest-resolver.ts +107 -0
  2. package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +85 -10
  3. package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-runtime-proxy.ts +34 -0
  4. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +50 -36
  5. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +12 -0
  6. package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry.ts +4 -0
  7. package/dist/bundling-sources/sdk/src/client.ts +1 -2
  8. package/dist/bundling-sources/sdk/src/release.ts +2 -2
  9. package/dist/bundling-sources/sdk/src/types.ts +2 -3
  10. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +21 -3
  11. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +73 -28
  12. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +14 -3
  13. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +19 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/profiles.ts +22 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/providers.ts +33 -1
  16. package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +13 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +5 -2
  18. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +66 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +18 -55
  20. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +57 -25
  21. package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +17 -1
  22. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +3 -2
  23. package/dist/bundling-sources/shared_libs/play-runtime/secret-redaction.ts +11 -1
  24. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +10 -0
  25. package/dist/cli/index.js +80 -443
  26. package/dist/cli/index.mjs +80 -443
  27. package/dist/index.d.mts +2 -3
  28. package/dist/index.d.ts +2 -3
  29. package/dist/index.js +7 -6
  30. package/dist/index.mjs +7 -6
  31. package/dist/plays/bundle-play-file.mjs +1 -1
  32. package/package.json +1 -1
@@ -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.213",
611
+ version: "0.1.215",
612
612
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
613
613
  supportPolicy: {
614
- latest: "0.1.213",
614
+ latest: "0.1.215",
615
615
  minimumSupported: "0.1.53",
616
616
  deprecatedBelow: "0.1.53",
617
617
  commandMinimumSupported: [
@@ -1349,8 +1349,10 @@ var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
1349
1349
  var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
1350
1350
  var JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
1351
1351
  var PRIVATE_KEY_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
1352
- var COMMON_SECRET_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs]|key|token|secret|api[_-]?key)[A-Za-z0-9_./+=:-]{12,}\b/gi;
1352
+ var COMMON_SECRET_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs])[A-Za-z0-9_./+=:-]{12,}\b/gi;
1353
+ var GENERIC_PREFIXED_SECRET_RE = /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
1353
1354
  var URL_SECRET_VALUE_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
1355
+ var GENERIC_SECRET_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
1354
1356
  var HIGH_ENTROPY_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password|authorization|access[_-]?token|refresh[_-]?token)\b\s*[:=]\s*["']?[^"',\s]{16,}["']?/gi;
1355
1357
  var SENSITIVE_URL_PARAM_RE = /[?#&](?:\w*(?:key|token)|secret|password|authorization|credential|signature|sig)(?:=|$)/i;
1356
1358
  function escapeRegExp(value) {
@@ -1367,7 +1369,7 @@ function redactSecretLikeString(value) {
1367
1369
  }
1368
1370
  if (!URL_SECRET_VALUE_RE.test(value)) return value;
1369
1371
  }
1370
- return value.replace(PRIVATE_KEY_RE, SECRET_REDACTION_PLACEHOLDER).replace(BEARER_TOKEN_RE, `Bearer ${SECRET_REDACTION_PLACEHOLDER}`).replace(JWT_RE, SECRET_REDACTION_PLACEHOLDER).replace(COMMON_SECRET_RE, SECRET_REDACTION_PLACEHOLDER).replace(HIGH_ENTROPY_ASSIGNMENT_RE, (match) => {
1372
+ return value.replace(PRIVATE_KEY_RE, SECRET_REDACTION_PLACEHOLDER).replace(BEARER_TOKEN_RE, `Bearer ${SECRET_REDACTION_PLACEHOLDER}`).replace(JWT_RE, SECRET_REDACTION_PLACEHOLDER).replace(COMMON_SECRET_RE, SECRET_REDACTION_PLACEHOLDER).replace(GENERIC_PREFIXED_SECRET_RE, SECRET_REDACTION_PLACEHOLDER).replace(GENERIC_SECRET_ASSIGNMENT_RE, SECRET_REDACTION_PLACEHOLDER).replace(HIGH_ENTROPY_ASSIGNMENT_RE, (match) => {
1371
1373
  const separator = match.includes("=") ? "=" : ":";
1372
1374
  const [key] = match.split(separator, 1);
1373
1375
  return `${key.trim()}${separator}${SECRET_REDACTION_PLACEHOLDER}`;
@@ -3032,8 +3034,7 @@ var DeeplineClient = class {
3032
3034
  ...forceToolRefresh ? { forceToolRefresh: true } : {},
3033
3035
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
3034
3036
  // Profile selection is the API's job, not the CLI's. The server
3035
- // defaults to workers_edge; tests and runtime probes that want a
3036
- // different profile pass `request.profile` explicitly.
3037
+ // defaults to absurd; callers normally omit this field.
3037
3038
  ...request.profile ? { profile: request.profile } : {},
3038
3039
  ...integrationMode ? { integrationMode } : {},
3039
3040
  ...testPolicyOverrides ? { testPolicyOverrides } : {}
@@ -10792,6 +10793,18 @@ var PLAY_RUNTIME_PROVIDER_IDS = {
10792
10793
  workersEdge: "workers_edge",
10793
10794
  absurd: "absurd"
10794
10795
  };
10796
+ var PLAY_RUNTIME_PROVIDER_DISABLED_CODE = "PLAY_RUNTIME_PROVIDER_DISABLED";
10797
+ var PlayRuntimeProviderDisabledError = class extends Error {
10798
+ code = PLAY_RUNTIME_PROVIDER_DISABLED_CODE;
10799
+ profile;
10800
+ constructor(profile) {
10801
+ super(
10802
+ `Play runtime profile "${profile}" is disabled. Deepline runs now execute on the "absurd" profile.`
10803
+ );
10804
+ this.name = "PlayRuntimeProviderDisabledError";
10805
+ this.profile = profile;
10806
+ }
10807
+ };
10795
10808
  var PLAY_RUNTIME_PROVIDERS = {
10796
10809
  workers_edge: {
10797
10810
  id: PLAY_RUNTIME_PROVIDER_IDS.workersEdge,
@@ -10814,7 +10827,12 @@ var PLAY_RUNTIME_PROVIDERS = {
10814
10827
  }
10815
10828
  };
10816
10829
  function defaultPlayRuntimeProvider() {
10817
- return PLAY_RUNTIME_PROVIDERS.workers_edge;
10830
+ return PLAY_RUNTIME_PROVIDERS.absurd;
10831
+ }
10832
+ function assertPlayRuntimeProviderEnabled(provider) {
10833
+ if (provider.id === PLAY_RUNTIME_PROVIDER_IDS.workersEdge) {
10834
+ throw new PlayRuntimeProviderDisabledError(provider.id);
10835
+ }
10818
10836
  }
10819
10837
  function resolvePlayRuntimeProvider(override) {
10820
10838
  if (override?.trim()) {
@@ -10830,17 +10848,22 @@ function resolvePlayRuntimeProvider(override) {
10830
10848
  }
10831
10849
  return defaultPlayRuntimeProvider();
10832
10850
  }
10851
+ function resolveEnabledPlayRuntimeProvider(override) {
10852
+ const provider = resolvePlayRuntimeProvider(override);
10853
+ assertPlayRuntimeProviderEnabled(provider);
10854
+ return provider;
10855
+ }
10833
10856
 
10834
10857
  // ../shared_libs/play-runtime/profiles.ts
10835
10858
  var PLAY_EXECUTION_PROFILE_IDS = {
10836
10859
  ...PLAY_RUNTIME_PROVIDER_IDS
10837
10860
  };
10838
10861
  var PLAY_EXECUTION_PROFILES = PLAY_RUNTIME_PROVIDERS;
10839
- function resolveExecutionProfile(override) {
10862
+ function resolveEnabledExecutionProfile(override) {
10840
10863
  try {
10841
- return resolvePlayRuntimeProvider(override);
10864
+ return resolveEnabledPlayRuntimeProvider(override);
10842
10865
  } catch (error) {
10843
- if (override?.trim()) {
10866
+ if (override?.trim() && error instanceof Error && /Unsupported play runtime provider/.test(error.message)) {
10844
10867
  throw new Error(
10845
10868
  `Unknown execution profile "${override.trim()}". Expected one of: ${Object.keys(
10846
10869
  PLAY_EXECUTION_PROFILES
@@ -11788,7 +11811,7 @@ async function collectBundledPlayGraph(entryFile, profile = null) {
11788
11811
  const playBundler = await loadPlayBundler();
11789
11812
  const nodes = /* @__PURE__ */ new Map();
11790
11813
  const visiting = /* @__PURE__ */ new Set();
11791
- const artifactKind = resolveExecutionProfile(profile).artifactKind;
11814
+ const artifactKind = resolveEnabledExecutionProfile(profile).artifactKind;
11792
11815
  const visit = async (filePath) => {
11793
11816
  const absolutePath = normalizePlayPath(filePath);
11794
11817
  const cached = nodes.get(absolutePath);
@@ -14502,7 +14525,7 @@ function writeStartedPlayRun(input2) {
14502
14525
  );
14503
14526
  }
14504
14527
  function parsePlayRunOptions(args) {
14505
- 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 Production defaults to workers_edge. Use --profile absurd only for an explicit Absurd run.\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.";
14528
+ 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 Runs default to absurd. The workers_edge profile is disabled.\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.";
14506
14529
  let filePath = null;
14507
14530
  let playName = null;
14508
14531
  let input2 = null;
@@ -14541,7 +14564,7 @@ function parsePlayRunOptions(args) {
14541
14564
  throw new Error("--profile requires an execution profile id.");
14542
14565
  }
14543
14566
  profile = value.trim();
14544
- resolveExecutionProfile(profile);
14567
+ resolveEnabledExecutionProfile(profile);
14545
14568
  index += 1;
14546
14569
  continue;
14547
14570
  }
@@ -15017,7 +15040,7 @@ async function handlePlayCheck(args) {
15017
15040
  }
15018
15041
  return enrichedResult.valid ? 0 : 1;
15019
15042
  }
15020
- async function handleFileBackedRun(options) {
15043
+ async function handleFileBackedRun(options, hooks) {
15021
15044
  if (options.target.kind !== "file") {
15022
15045
  throw new Error("Expected a file-backed play run target.");
15023
15046
  }
@@ -15157,6 +15180,7 @@ async function handleFileBackedRun(options) {
15157
15180
  ),
15158
15181
  options
15159
15182
  );
15183
+ hooks?.onTerminalStatus?.(outputStatus);
15160
15184
  traceCliSync(
15161
15185
  "cli.play_write_result",
15162
15186
  { targetKind: "file", playName },
@@ -15206,7 +15230,7 @@ async function resolveNamedRunRevisionId(input2) {
15206
15230
  }
15207
15231
  return null;
15208
15232
  }
15209
- async function handleNamedRun(options) {
15233
+ async function handleNamedRun(options, hooks) {
15210
15234
  if (options.target.kind !== "name") {
15211
15235
  throw new Error("Expected a named play run target.");
15212
15236
  }
@@ -15325,6 +15349,7 @@ async function handleNamedRun(options) {
15325
15349
  options,
15326
15350
  finalStatus.revisionId ?? selectedRevisionId
15327
15351
  );
15352
+ hooks?.onTerminalStatus?.(outputStatus);
15328
15353
  traceCliSync(
15329
15354
  "cli.play_write_result",
15330
15355
  { targetKind: "name", playName },
@@ -15362,11 +15387,11 @@ async function handleNamedRun(options) {
15362
15387
  });
15363
15388
  return 0;
15364
15389
  }
15365
- async function handlePlayRun(args) {
15390
+ async function handlePlayRun(args, hooks) {
15366
15391
  const options = parsePlayRunOptions(args);
15367
15392
  if (options.target.kind === "file") {
15368
15393
  if (isFileTarget(options.target.path)) {
15369
- return handleFileBackedRun(options);
15394
+ return handleFileBackedRun(options, hooks);
15370
15395
  }
15371
15396
  const resolved = resolve8(options.target.path);
15372
15397
  console.error(`File not found: ${resolved}`);
@@ -15388,7 +15413,7 @@ async function handlePlayRun(args) {
15388
15413
  }
15389
15414
  return 1;
15390
15415
  }
15391
- return handleNamedRun(options);
15416
+ return handleNamedRun(options, hooks);
15392
15417
  }
15393
15418
  function parseRunIdPositional(args, usage) {
15394
15419
  for (let index = 0; index < args.length; index += 1) {
@@ -18815,9 +18840,6 @@ function helperSource() {
18815
18840
 
18816
18841
  // src/cli/commands/enrich.ts
18817
18842
  var ENRICH_EXPORT_PAGE_SIZE = 5e3;
18818
- var ENRICH_AUTO_BATCH_ROWS = 200;
18819
- var ENRICH_HEAVY_PLAY_AUTO_BATCH_ROWS = 25;
18820
- var ENRICH_NESTED_PROVIDER_AUTO_BATCH_ROWS = 50;
18821
18843
  var ENRICH_EXPORT_BACKING_ROWS_WAIT_MS = 6e4;
18822
18844
  var ENRICH_EXPORT_BACKING_ROWS_POLL_MS = 1e3;
18823
18845
  var ENRICH_CUSTOMER_DB_FAILURE_LOOKUP_RETRY_DELAYS_MS = [1e3, 3e3, 7e3];
@@ -18830,12 +18852,7 @@ var ENRICH_DEBUG_T0 = Date.now();
18830
18852
  var GENERATED_ENRICH_ROWS_TABLE_NAMESPACE = "deepline_enrich_rows";
18831
18853
  var SDK_ENRICH_TELEMETRY_TIMEOUT_MS = 1e4;
18832
18854
  var SDK_ENRICH_TELEMETRY_COMMAND_MAX_LENGTH = 2e4;
18833
- var HEAVY_ENRICH_AUTO_BATCH_PLAYS = /* @__PURE__ */ new Set([
18834
- "company-to-contact",
18835
- "company-to-contact-by-role-waterfall",
18836
- "company_to_contact_by_role_waterfall"
18837
- ]);
18838
- var HEAVY_ENRICH_AUTO_BATCH_TOOLS = /* @__PURE__ */ new Set([
18855
+ var ENRICH_AI_RUNTIME_COMPACT_TOOLS = /* @__PURE__ */ new Set([
18839
18856
  "ai_inference",
18840
18857
  "aiinference",
18841
18858
  "deeplineagent",
@@ -19662,9 +19679,18 @@ async function stopGeneratedEnrichRunAfterWatchError(client2, error) {
19662
19679
  async function runGeneratedEnrichPlay(client2, runArgs, options = {}) {
19663
19680
  for (let attempt = 0; attempt < 2; attempt += 1) {
19664
19681
  try {
19665
- return await captureStdout(() => handlePlayRun(runArgs), {
19666
- passthrough: options.passthroughStdout
19667
- });
19682
+ let terminalStatus2 = null;
19683
+ const captured2 = await captureStdout(
19684
+ () => handlePlayRun(runArgs, {
19685
+ onTerminalStatus: (status) => {
19686
+ terminalStatus2 = status;
19687
+ }
19688
+ }),
19689
+ {
19690
+ passthrough: options.passthroughStdout
19691
+ }
19692
+ );
19693
+ return { ...captured2, terminalStatus: terminalStatus2 };
19668
19694
  } catch (error) {
19669
19695
  await stopGeneratedEnrichRunAfterWatchError(client2, error);
19670
19696
  if (attempt === 0 && isPlayStartStreamEndedError(error)) {
@@ -19674,9 +19700,16 @@ async function runGeneratedEnrichPlay(client2, runArgs, options = {}) {
19674
19700
  throw error;
19675
19701
  }
19676
19702
  }
19677
- return captureStdout(() => handlePlayRun(runArgs), {
19678
- passthrough: options.passthroughStdout
19679
- });
19703
+ let terminalStatus = null;
19704
+ const captured = await captureStdout(
19705
+ () => handlePlayRun(runArgs, {
19706
+ onTerminalStatus: (status) => {
19707
+ terminalStatus = status;
19708
+ }
19709
+ }),
19710
+ { passthrough: options.passthroughStdout }
19711
+ );
19712
+ return { ...captured, terminalStatus };
19680
19713
  }
19681
19714
  async function writeOutputCsv(outputPath, status, options) {
19682
19715
  let rowsInfo = extractCanonicalRowsInfo(status);
@@ -19759,71 +19792,6 @@ function normalizeEnrichPlayRef(value) {
19759
19792
  const normalized = value.trim().toLowerCase().replace(/^prebuilt\//, "");
19760
19793
  return normalized || null;
19761
19794
  }
19762
- function configContainsHeavyEnrichPlay(config) {
19763
- const visit = (commands) => {
19764
- for (const command of commands) {
19765
- if ("with_waterfall" in command) {
19766
- if (visit(command.commands)) {
19767
- return true;
19768
- }
19769
- continue;
19770
- }
19771
- if (command.disabled) {
19772
- continue;
19773
- }
19774
- const candidates = [
19775
- command.tool,
19776
- command.operation,
19777
- command.play?.ref,
19778
- command.play?.ref?.replace(/^prebuilt\//, "")
19779
- ];
19780
- if (candidates.map(normalizeEnrichPlayRef).some(
19781
- (candidate) => candidate !== null && HEAVY_ENRICH_AUTO_BATCH_PLAYS.has(candidate)
19782
- )) {
19783
- return true;
19784
- }
19785
- const normalizedTool = normalizeEnrichPlayRef(command.tool);
19786
- const normalizedOperation = normalizeEnrichPlayRef(command.operation);
19787
- if (isMarkedTestAiInferenceCommand(command) || normalizedTool && HEAVY_ENRICH_AUTO_BATCH_TOOLS.has(normalizedTool) || normalizedOperation && HEAVY_ENRICH_AUTO_BATCH_TOOLS.has(normalizedOperation)) {
19788
- return true;
19789
- }
19790
- }
19791
- return false;
19792
- };
19793
- return visit(config.commands);
19794
- }
19795
- function configContainsNestedProviderEnrichWorkload(config) {
19796
- let hasNestedPlayStep = false;
19797
- let hasSubrequestProviderStep = false;
19798
- const visit = (commands) => {
19799
- for (const command of commands) {
19800
- if ("with_waterfall" in command) {
19801
- visit(command.commands);
19802
- continue;
19803
- }
19804
- if (command.disabled) {
19805
- continue;
19806
- }
19807
- const normalizedTool = normalizeEnrichPlayRef(command.tool);
19808
- if (command.play || normalizedTool === "test-play") {
19809
- hasNestedPlayStep = true;
19810
- } else if (normalizedTool !== null && normalizedTool !== "run_javascript") {
19811
- hasSubrequestProviderStep = true;
19812
- }
19813
- }
19814
- };
19815
- visit(config.commands);
19816
- return hasNestedPlayStep && hasSubrequestProviderStep;
19817
- }
19818
- function enrichAutoBatchRowsForConfig(config) {
19819
- if (configContainsHeavyEnrichPlay(config)) {
19820
- return ENRICH_HEAVY_PLAY_AUTO_BATCH_ROWS;
19821
- }
19822
- if (configContainsNestedProviderEnrichWorkload(config)) {
19823
- return ENRICH_NESTED_PROVIDER_AUTO_BATCH_ROWS;
19824
- }
19825
- return ENRICH_AUTO_BATCH_ROWS;
19826
- }
19827
19795
  function enrichAiRuntimeCompactAliases(config) {
19828
19796
  const aliases = /* @__PURE__ */ new Set();
19829
19797
  const visit = (commands) => {
@@ -19837,7 +19805,7 @@ function enrichAiRuntimeCompactAliases(config) {
19837
19805
  }
19838
19806
  const normalizedTool = normalizeEnrichPlayRef(command.tool);
19839
19807
  const normalizedOperation = normalizeEnrichPlayRef(command.operation);
19840
- if (isMarkedTestAiInferenceCommand(command) || normalizedTool && HEAVY_ENRICH_AUTO_BATCH_TOOLS.has(normalizedTool) || normalizedOperation && HEAVY_ENRICH_AUTO_BATCH_TOOLS.has(normalizedOperation)) {
19808
+ if (isMarkedTestAiInferenceCommand(command) || normalizedTool && ENRICH_AI_RUNTIME_COMPACT_TOOLS.has(normalizedTool) || normalizedOperation && ENRICH_AI_RUNTIME_COMPACT_TOOLS.has(normalizedOperation)) {
19841
19809
  aliases.add(normalizeAlias2(command.alias));
19842
19810
  }
19843
19811
  }
@@ -19848,13 +19816,14 @@ function enrichAiRuntimeCompactAliases(config) {
19848
19816
  async function maybeWriteOutputCsv(input2) {
19849
19817
  if (!input2.outputPath) return null;
19850
19818
  try {
19819
+ const terminalStatus = readEnrichRunStatus(input2.status);
19851
19820
  return await writeOutputCsv(input2.outputPath, input2.status, {
19852
19821
  client: input2.client,
19853
19822
  config: input2.config,
19854
19823
  sourceCsvPath: input2.sourceCsvPath,
19855
19824
  rows: input2.rows,
19856
19825
  inPlace: input2.inPlace,
19857
- allowPartial: input2.capturedResult !== 0
19826
+ allowPartial: input2.capturedResult !== 0 || terminalStatus === "failed" || terminalStatus === "cancelled" || hasFailedRowSignal(input2.status)
19858
19827
  });
19859
19828
  } catch (error) {
19860
19829
  if (input2.capturedResult !== 0 && isMissingRowsForCsvExportError(error)) {
@@ -20247,55 +20216,14 @@ function selectedSourceCsvRange(sourceCsvPath, rows) {
20247
20216
  sourceRows
20248
20217
  };
20249
20218
  }
20250
- function compactRuntimeCsvCell(value) {
20251
- const parsed = parseMaybeJsonObject(value);
20252
- const compacted = compactAiInferenceCellForCsv(parsed);
20253
- return materializeCsvCellValue(compacted);
20254
- }
20255
- async function writeSlimBatchedRuntimeCsv(input2) {
20256
- const cleanRows = readCsvRows(input2.cleanSourceCsvPath).map(
20257
- (row) => ({ ...row })
20258
- );
20259
- const mergeRows = readCsvRows(input2.mergeSourceCsvPath);
20260
- const preserveJsonStringColumns = /* @__PURE__ */ new Set([
20261
- ...cleanRows.flatMap((row) => Object.keys(row)),
20262
- ...mergeRows.flatMap((row) => Object.keys(row))
20263
- ]);
20264
- const selectedRange = selectedSourceCsvRange(
20265
- input2.mergeSourceCsvPath,
20266
- input2.rows
20267
- );
20268
- for (let rowIndex = selectedRange.start; rowIndex <= selectedRange.end; rowIndex += 1) {
20269
- const mergeRow = mergeRows[rowIndex];
20270
- if (!mergeRow) {
20271
- continue;
20272
- }
20273
- const baseRow = cleanRows[rowIndex] ?? {};
20274
- const compactOverlayCell = ([key, value]) => {
20275
- return [
20276
- key,
20277
- input2.compactAliases.has(normalizeAlias2(key)) ? compactRuntimeCsvCell(value) : value
20278
- ];
20279
- };
20280
- cleanRows[rowIndex] = {
20281
- ...baseRow,
20282
- ...Object.fromEntries(Object.entries(mergeRow).map(compactOverlayCell))
20283
- };
20284
- }
20285
- const columns = dataExportColumns(
20286
- dataExportRows(cleanRows, { preserveJsonStringColumns })
20287
- );
20288
- await writeFile3(
20289
- input2.outputPath,
20290
- csvStringFromRows(cleanRows, columns),
20291
- "utf8"
20292
- );
20293
- }
20294
20219
  function selectedSourceCsvRowCount(options) {
20295
20220
  if (!options?.sourceCsvPath) {
20296
20221
  return null;
20297
20222
  }
20298
- return selectedSourceCsvRange(options.sourceCsvPath, options.rows).count;
20223
+ const totalRows = readCsvRows(options.sourceCsvPath).length;
20224
+ const start = Math.max(0, options.rows?.rowStart ?? 0);
20225
+ const end = options.rows?.rowEnd === null || options.rows?.rowEnd === void 0 ? totalRows - 1 : Math.min(totalRows - 1, options.rows.rowEnd);
20226
+ return Math.max(0, end - start + 1);
20299
20227
  }
20300
20228
  function collectStringFields(value, key, output2, depth = 0) {
20301
20229
  if (depth > 12 || !value || typeof value !== "object") {
@@ -20476,13 +20404,9 @@ function firstCollectedStringField(value, key) {
20476
20404
  collectStringFields(value, key, fields);
20477
20405
  return fields.values().next().value ?? null;
20478
20406
  }
20479
- function emitPlainBatchRunFailure(input2) {
20480
- process.stderr.write(
20481
- `Batch ${input2.chunkIndex + 1}/${input2.chunkCount} failed for rows ${input2.rows.rowStart}:${input2.rows.rowEnd}.
20482
- `
20483
- );
20484
- const runId = extractRunId(input2.status) ?? firstCollectedStringField(input2.status, "runId");
20485
- const error = firstCollectedStringField(input2.status, "error") ?? firstCollectedStringField(input2.status, "message");
20407
+ function emitPlainRunFailure(status) {
20408
+ const runId = extractRunId(status) ?? firstCollectedStringField(status, "runId");
20409
+ const error = firstCollectedStringField(status, "error") ?? firstCollectedStringField(status, "message");
20486
20410
  if (runId) {
20487
20411
  process.stderr.write(`Run id: ${runId}
20488
20412
  `);
@@ -20613,22 +20537,6 @@ function mergeExportedSheetRow(target, next) {
20613
20537
  target._metadata = metadata;
20614
20538
  }
20615
20539
  }
20616
- function countEnrichedRowsInSourceRange(exportResult, rows) {
20617
- const start = Math.max(0, rows.rowStart ?? 0);
20618
- const end = rows.rowEnd === null || rows.rowEnd === void 0 ? Number.MAX_SAFE_INTEGER : Math.max(start, rows.rowEnd);
20619
- const rowIndexes = /* @__PURE__ */ new Set();
20620
- for (const row of exportResult.enrichedDataRows) {
20621
- const rowIndex = sourceRowIndexFromEnrichRow(row, start, end);
20622
- if (rowIndex !== null) {
20623
- rowIndexes.add(rowIndex);
20624
- }
20625
- }
20626
- if (rowIndexes.size > 0) {
20627
- return rowIndexes.size;
20628
- }
20629
- const selectedRows = end === Number.MAX_SAFE_INTEGER ? exportResult.enrichedRows : end - start + 1;
20630
- return Math.min(exportResult.enrichedRows, Math.max(0, selectedRows));
20631
- }
20632
20540
  function coalesceExportableSheetRows(rows, sourceRowStart = 0) {
20633
20541
  const mergedRows = [];
20634
20542
  const bySourceRowIndex = /* @__PURE__ */ new Map();
@@ -21454,12 +21362,6 @@ function sidecarEnrichRowsExportPath(outputPath) {
21454
21362
  const stem = basename2(resolved, ext);
21455
21363
  return join7(dirname7(resolved), `${stem}.deepline-enrich-rows${ext}`);
21456
21364
  }
21457
- function sidecarEnrichBatchManifestPath(outputPath) {
21458
- const resolved = resolve9(outputPath);
21459
- const ext = extname(resolved) || ".csv";
21460
- const stem = basename2(resolved, ext);
21461
- return join7(dirname7(resolved), `${stem}.deepline-enrich-batches.json`);
21462
- }
21463
21365
  function collectDatasetFollowUpCommands(value, state) {
21464
21366
  if (state.depth > 12 || !value || typeof value !== "object" || state.commands.length >= 8) {
21465
21367
  return;
@@ -22516,7 +22418,7 @@ function registerEnrichCommand(program) {
22516
22418
  const captured2 = await runGeneratedEnrichPlay(client2, runArgs, {
22517
22419
  passthroughStdout: input2.passthroughStdout
22518
22420
  });
22519
- const generatedPlayStatus = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
22421
+ const generatedPlayStatus = input2.json ? parseJsonOutput(captured2.stdout) : captured2.terminalStatus ?? await resolveWatchedGeneratedPlayStatus({
22520
22422
  client: client2,
22521
22423
  stdout: captured2.stdout,
22522
22424
  exitCode: captured2.result
@@ -22537,274 +22439,6 @@ function registerEnrichCommand(program) {
22537
22439
  });
22538
22440
  return { captured: captured2, status: status2, exportResult: exportResult2 };
22539
22441
  };
22540
- const autoBatchRows = enrichAutoBatchRowsForConfig(config);
22541
- if (outputPath && selectedRange.count > autoBatchRows) {
22542
- const chunkCount = Math.ceil(selectedRange.count / autoBatchRows);
22543
- const batchManifestPath = sidecarEnrichBatchManifestPath(
22544
- inPlaceFinalOutputPath ?? resolve9(outputPath)
22545
- );
22546
- const batchManifest = {
22547
- version: 1,
22548
- kind: "deepline_enrich_batch_manifest",
22549
- input: resolve9(inputCsv),
22550
- output: inPlaceFinalOutputPath ?? resolve9(outputPath),
22551
- selectedRows: selectedRange.count,
22552
- sourceCsvRows: selectedRange.sourceRows,
22553
- chunkRows: autoBatchRows,
22554
- chunks: chunkCount,
22555
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
22556
- batches: []
22557
- };
22558
- const writeBatchManifest = async () => {
22559
- batchManifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
22560
- await writeFile3(
22561
- batchManifestPath,
22562
- `${JSON.stringify(batchManifest, null, 2)}
22563
- `,
22564
- "utf8"
22565
- );
22566
- };
22567
- const appendBatchManifestEntry = async (input2) => {
22568
- const runId = extractRunId(input2.status) ?? firstCollectedStringField(input2.status, "runId");
22569
- batchManifest.batches.push({
22570
- chunk: input2.chunkIndex + 1,
22571
- chunks: chunkCount,
22572
- rows: {
22573
- rowStart: input2.rows.rowStart,
22574
- rowEnd: input2.rows.rowEnd
22575
- },
22576
- status: readEnrichRunStatus(input2.status),
22577
- runId,
22578
- customer_db: enrichCustomerDbJson({
22579
- status: input2.status,
22580
- client: client2,
22581
- outputPath: enrichIssueFollowUpOutputPath ?? input2.exportResult?.path ?? outputPath
22582
- }),
22583
- output: enrichOutputJson(input2.exportResult),
22584
- completedAt: (/* @__PURE__ */ new Date()).toISOString()
22585
- });
22586
- await writeBatchManifest();
22587
- };
22588
- await writeBatchManifest();
22589
- if (!options.json) {
22590
- process.stderr.write(
22591
- `Large enrich input selected ${selectedRange.count.toLocaleString()} rows. Running ${chunkCount.toLocaleString()} sequential batch runs of up to ${autoBatchRows.toLocaleString()} rows and merging ${resolve9(outputPath)}.
22592
- `
22593
- );
22594
- }
22595
- process.stderr.write(
22596
- `Batch recovery manifest: ${batchManifestPath}
22597
- `
22598
- );
22599
- let workingMergeSourceCsvPath = sourceCsvPath;
22600
- let lastStatus = null;
22601
- const batchStatuses = [];
22602
- let finalExportResult = null;
22603
- let totalEnrichedRows = 0;
22604
- const batchFailureRows = [];
22605
- const runtimeCompactAliases = enrichAiRuntimeCompactAliases(config);
22606
- for (let chunkStart = selectedRange.start, chunkIndex = 0; chunkStart <= selectedRange.end; chunkStart += autoBatchRows, chunkIndex += 1) {
22607
- const chunkRows = {
22608
- rowStart: chunkStart,
22609
- rowEnd: Math.min(
22610
- selectedRange.end,
22611
- chunkStart + autoBatchRows - 1
22612
- )
22613
- };
22614
- if (!options.json) {
22615
- process.stderr.write(
22616
- `Batch ${chunkIndex + 1}/${chunkCount}: rows ${chunkRows.rowStart}:${chunkRows.rowEnd}
22617
- `
22618
- );
22619
- }
22620
- const runtimeSourceCsvPath = options.inPlace ? sourceCsvPath : workingMergeSourceCsvPath === inputCsv ? inputCsv : join7(tempDir, `runtime-batch-${chunkIndex}.csv`);
22621
- if (!options.inPlace && runtimeSourceCsvPath !== inputCsv) {
22622
- await writeSlimBatchedRuntimeCsv({
22623
- cleanSourceCsvPath: inputCsv,
22624
- mergeSourceCsvPath: workingMergeSourceCsvPath,
22625
- rows: chunkRows,
22626
- compactAliases: runtimeCompactAliases,
22627
- outputPath: runtimeSourceCsvPath
22628
- });
22629
- }
22630
- const chunk = await runOne({
22631
- sourceCsvPath: runtimeSourceCsvPath,
22632
- mergeSourceCsvPath: workingMergeSourceCsvPath,
22633
- rows: chunkRows,
22634
- json: true,
22635
- passthroughStdout: false,
22636
- suppressOpen: true
22637
- });
22638
- lastStatus = chunk.status;
22639
- batchStatuses.push(chunk.status);
22640
- if (chunk.captured.result !== 0) {
22641
- let currentChunkCommittedExportResult = null;
22642
- if (chunk.exportResult) {
22643
- finalExportResult = chunk.exportResult;
22644
- totalEnrichedRows += countEnrichedRowsInSourceRange(
22645
- chunk.exportResult,
22646
- chunkRows
22647
- );
22648
- batchFailureRows.push(...chunk.exportResult.enrichedDataRows);
22649
- }
22650
- const failureReport3 = await maybeEmitEnrichFailureReport({
22651
- config,
22652
- rows: batchFailureRows,
22653
- rowRange: {
22654
- rowStart: selectedRange.start,
22655
- rowEnd: selectedRange.end
22656
- },
22657
- statusRowRange: chunkRows,
22658
- client: client2,
22659
- outputPath: failureReportOutputPath ?? finalExportResult?.path ?? outputPath,
22660
- followUpOutputPath: enrichIssueFollowUpOutputPath,
22661
- status: chunk.status,
22662
- waterfallStatus: batchStatuses,
22663
- ...finalExportResult ? { rowSetComplete: !finalExportResult.partial } : {}
22664
- });
22665
- if (chunk.exportResult) {
22666
- currentChunkCommittedExportResult = await commitInPlaceOutput(
22667
- chunk.exportResult
22668
- );
22669
- finalExportResult = currentChunkCommittedExportResult;
22670
- }
22671
- const reportedExportResult = currentChunkCommittedExportResult ?? finalExportResult;
22672
- await appendBatchManifestEntry({
22673
- chunkIndex,
22674
- rows: chunkRows,
22675
- status: chunk.status,
22676
- exportResult: currentChunkCommittedExportResult
22677
- });
22678
- if (options.json) {
22679
- printJson({
22680
- ok: false,
22681
- batch: {
22682
- chunk: chunkIndex + 1,
22683
- chunks: chunkCount,
22684
- rows: chunkRows,
22685
- manifest: batchManifestPath
22686
- },
22687
- result: chunk.status,
22688
- output: reportedExportResult ? {
22689
- sourceCsvRows: selectedRange.sourceRows,
22690
- selectedRows: selectedRange.count,
22691
- enrichedRows: totalEnrichedRows,
22692
- path: reportedExportResult.path,
22693
- ...reportedExportResult.partial ? {
22694
- rows: reportedExportResult.rows,
22695
- partial: true
22696
- } : {}
22697
- } : null,
22698
- customer_db: enrichCustomerDbJson({
22699
- status: chunk.status,
22700
- client: client2,
22701
- outputPath: enrichIssueFollowUpOutputPath ?? reportedExportResult?.path ?? outputPath
22702
- }),
22703
- ...enrichReportJson(failureReport3)
22704
- });
22705
- } else {
22706
- if (reportedExportResult) {
22707
- process.stderr.write(
22708
- `Wrote ${reportedExportResult.rows} row(s) to ${reportedExportResult.path}${reportedExportResult.partial ? " (partial run output)" : ""}
22709
- `
22710
- );
22711
- }
22712
- emitPlainBatchRunFailure({
22713
- chunkIndex,
22714
- chunkCount,
22715
- rows: chunkRows,
22716
- status: chunk.status
22717
- });
22718
- }
22719
- process.exitCode = failureReport3 ? EXIT_SERVER2 : chunk.captured.result;
22720
- await completeTelemetry({
22721
- status: "failed",
22722
- failedJobs: failureReport3?.jobs.length ?? 1
22723
- });
22724
- return;
22725
- }
22726
- if (chunk.exportResult) {
22727
- totalEnrichedRows += countEnrichedRowsInSourceRange(
22728
- chunk.exportResult,
22729
- chunkRows
22730
- );
22731
- batchFailureRows.push(...chunk.exportResult.enrichedDataRows);
22732
- finalExportResult = options.inPlace ? await commitInPlaceOutput(chunk.exportResult) : chunk.exportResult;
22733
- await appendBatchManifestEntry({
22734
- chunkIndex,
22735
- rows: chunkRows,
22736
- status: chunk.status,
22737
- exportResult: finalExportResult
22738
- });
22739
- workingMergeSourceCsvPath = outputPath;
22740
- if (options.inPlace && (chunkRows.rowEnd ?? selectedRange.end) < selectedRange.end) {
22741
- await prepareInPlaceOutput();
22742
- }
22743
- }
22744
- }
22745
- const outputRows = readCsvRows(outputPath);
22746
- const failureReport2 = await maybeEmitEnrichFailureReport({
22747
- config,
22748
- rows: batchFailureRows,
22749
- rowRange: {
22750
- rowStart: selectedRange.start,
22751
- rowEnd: selectedRange.end
22752
- },
22753
- client: client2,
22754
- outputPath: failureReportOutputPath ?? finalExportResult?.path ?? outputPath,
22755
- followUpOutputPath: enrichIssueFollowUpOutputPath,
22756
- status: lastStatus,
22757
- waterfallStatus: batchStatuses,
22758
- ...finalExportResult ? { rowSetComplete: !finalExportResult.partial } : {}
22759
- });
22760
- finalExportResult = await commitInPlaceOutput(finalExportResult);
22761
- if (options.json) {
22762
- const run = rewriteEnrichJsonStatus({
22763
- status: lastStatus,
22764
- config,
22765
- forceAliases,
22766
- output: finalExportResult ? {
22767
- ...finalExportResult,
22768
- sourceCsvRows: selectedRange.sourceRows,
22769
- selectedRows: selectedRange.count,
22770
- enrichedRows: totalEnrichedRows,
22771
- rows: outputRows.length,
22772
- enrichedDataRows: outputRows
22773
- } : null,
22774
- failureReport: failureReport2
22775
- });
22776
- printJson({
22777
- ok: !failureReport2,
22778
- run,
22779
- batch: {
22780
- chunks: chunkCount,
22781
- chunkRows: autoBatchRows,
22782
- selectedRows: selectedRange.count,
22783
- manifest: batchManifestPath
22784
- },
22785
- output: finalExportResult ? {
22786
- sourceCsvRows: selectedRange.sourceRows,
22787
- selectedRows: selectedRange.count,
22788
- enrichedRows: totalEnrichedRows,
22789
- path: finalExportResult.path
22790
- } : null,
22791
- customer_db: enrichCustomerDbJson({
22792
- status: lastStatus,
22793
- client: client2,
22794
- outputPath: enrichIssueFollowUpOutputPath ?? finalExportResult?.path ?? outputPath
22795
- }),
22796
- ...enrichReportJson(failureReport2)
22797
- });
22798
- }
22799
- if (failureReport2) {
22800
- process.exitCode = EXIT_SERVER2;
22801
- }
22802
- await completeTelemetry({
22803
- status: failureReport2 ? "completed_with_failures" : "completed",
22804
- failedJobs: failureReport2?.jobs.length ?? 0
22805
- });
22806
- return;
22807
- }
22808
22442
  const { captured, status, exportResult } = await runOne({
22809
22443
  sourceCsvPath,
22810
22444
  rows,
@@ -22820,6 +22454,9 @@ function registerEnrichCommand(program) {
22820
22454
  `
22821
22455
  );
22822
22456
  }
22457
+ if (!options.json) {
22458
+ emitPlainRunFailure(status);
22459
+ }
22823
22460
  const failureReport2 = await buildEnrichFailureReport({
22824
22461
  config,
22825
22462
  rows: rowsForFailureReport,