deepline 0.1.211 → 0.1.213

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 (54) hide show
  1. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +317 -340
  2. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/customer-console.ts +23 -0
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-dispatch.ts +1 -1
  4. package/dist/bundling-sources/sdk/src/client.ts +118 -3
  5. package/dist/bundling-sources/sdk/src/index.ts +2 -0
  6. package/dist/bundling-sources/sdk/src/play.ts +8 -1
  7. package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +1 -1
  8. package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +11 -1
  9. package/dist/bundling-sources/sdk/src/release.ts +2 -2
  10. package/dist/bundling-sources/sdk/src/types.ts +47 -0
  11. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +302 -30
  12. package/dist/bundling-sources/shared_libs/play-runtime/child-execution-placement.ts +14 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/child-execution-strategy.ts +57 -23
  14. package/dist/bundling-sources/shared_libs/play-runtime/completed-receipt-cache.ts +166 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +164 -121
  16. package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +2 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +42 -1
  18. package/dist/bundling-sources/shared_libs/play-runtime/dataset-id.ts +10 -4
  19. package/dist/bundling-sources/shared_libs/play-runtime/db-session.ts +9 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +163 -7
  21. package/dist/bundling-sources/shared_libs/play-runtime/gateway-auth-session.ts +93 -0
  22. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +14 -2
  23. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +4 -2
  24. package/dist/bundling-sources/shared_libs/play-runtime/play-call-execution.ts +1 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/receipt-completion-sink.ts +16 -1
  26. package/dist/bundling-sources/shared_libs/play-runtime/receipt-sql.ts +21 -1
  27. package/dist/bundling-sources/shared_libs/play-runtime/receipt-state-sink.ts +10 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +80 -3
  29. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +128 -6
  30. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +7 -0
  31. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +94 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +91 -6
  33. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +19 -10
  34. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +540 -92
  35. package/dist/bundling-sources/shared_libs/play-runtime/runtime-postgres-admission.ts +162 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/secret-capability.ts +18 -4
  37. package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +16 -17
  38. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +29 -9
  39. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-state-machine.ts +22 -1
  40. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +1 -0
  41. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +79 -1
  42. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +2 -4
  43. package/dist/cli/index.js +637 -229
  44. package/dist/cli/index.mjs +637 -229
  45. package/dist/{compiler-manifest-j6z8qzpd.d.mts → compiler-manifest-BhgZ23A4.d.mts} +1 -0
  46. package/dist/{compiler-manifest-j6z8qzpd.d.ts → compiler-manifest-BhgZ23A4.d.ts} +1 -0
  47. package/dist/index.d.mts +84 -11
  48. package/dist/index.d.ts +84 -11
  49. package/dist/index.js +225 -43
  50. package/dist/index.mjs +225 -43
  51. package/dist/plays/bundle-play-file.d.mts +2 -2
  52. package/dist/plays/bundle-play-file.d.ts +2 -2
  53. package/dist/plays/bundle-play-file.mjs +65 -4
  54. 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.211",
611
+ version: "0.1.213",
612
612
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
613
613
  supportPolicy: {
614
- latest: "0.1.211",
614
+ latest: "0.1.213",
615
615
  minimumSupported: "0.1.53",
616
616
  deprecatedBelow: "0.1.53",
617
617
  commandMinimumSupported: [
@@ -1344,9 +1344,91 @@ function normalizePlayRunLedgerTerminalSource(value) {
1344
1344
  ) ? value : null;
1345
1345
  }
1346
1346
 
1347
+ // ../shared_libs/play-runtime/secret-redaction.ts
1348
+ var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
1349
+ var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
1350
+ var JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
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;
1353
+ var URL_SECRET_VALUE_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
1354
+ var HIGH_ENTROPY_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password|authorization|access[_-]?token|refresh[_-]?token)\b\s*[:=]\s*["']?[^"',\s]{16,}["']?/gi;
1355
+ var SENSITIVE_URL_PARAM_RE = /[?#&](?:\w*(?:key|token)|secret|password|authorization|credential|signature|sig)(?:=|$)/i;
1356
+ function escapeRegExp(value) {
1357
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1358
+ }
1359
+ function isRecord(value) {
1360
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1361
+ }
1362
+ function redactSecretLikeString(value) {
1363
+ const trimmed = value.trim();
1364
+ if (/^https?:\/\/\S+$/i.test(trimmed)) {
1365
+ if (/^https?:\/\/[^/?#@]+@/i.test(trimmed) || SENSITIVE_URL_PARAM_RE.test(trimmed)) {
1366
+ return SECRET_REDACTION_PLACEHOLDER;
1367
+ }
1368
+ if (!URL_SECRET_VALUE_RE.test(value)) return value;
1369
+ }
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) => {
1371
+ const separator = match.includes("=") ? "=" : ":";
1372
+ const [key] = match.split(separator, 1);
1373
+ return `${key.trim()}${separator}${SECRET_REDACTION_PLACEHOLDER}`;
1374
+ });
1375
+ }
1376
+ function createSecretRedactionContext(initialValues = []) {
1377
+ const exactSecrets = /* @__PURE__ */ new Set();
1378
+ function register(value) {
1379
+ if (value.length >= 4) exactSecrets.add(value);
1380
+ }
1381
+ for (const value of initialValues) register(value);
1382
+ function redactString(value) {
1383
+ let output2 = value;
1384
+ for (const secret of exactSecrets) {
1385
+ output2 = output2.replace(
1386
+ new RegExp(escapeRegExp(secret), "g"),
1387
+ SECRET_REDACTION_PLACEHOLDER
1388
+ );
1389
+ try {
1390
+ const encoded = encodeURIComponent(secret);
1391
+ if (encoded !== secret) {
1392
+ output2 = output2.replace(
1393
+ new RegExp(escapeRegExp(encoded), "g"),
1394
+ SECRET_REDACTION_PLACEHOLDER
1395
+ );
1396
+ }
1397
+ } catch {
1398
+ }
1399
+ }
1400
+ return redactSecretLikeString(output2);
1401
+ }
1402
+ function redact(value) {
1403
+ if (typeof value === "string") return redactString(value);
1404
+ if (Array.isArray(value)) return value.map((entry) => redact(entry));
1405
+ if (isRecord(value)) {
1406
+ return Object.fromEntries(
1407
+ Object.entries(value).map(([key, entry]) => [key, redact(entry)])
1408
+ );
1409
+ }
1410
+ return value;
1411
+ }
1412
+ return {
1413
+ register,
1414
+ redactString,
1415
+ redact
1416
+ };
1417
+ }
1418
+
1419
+ // ../shared_libs/play-runtime/output-size-limits.ts
1420
+ var encoder = typeof TextEncoder === "undefined" ? null : new TextEncoder();
1421
+ var CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 1 * 1024 * 1024;
1422
+ var CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 2 * 1024 * 1024;
1423
+ var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
1424
+ var RUNTIME_RECEIPT_COMPLETION_BUFFER_MAX_BYTES = 32 * 1024 * 1024;
1425
+
1426
+ // ../shared_libs/play-runtime/ledger-safe-payload.ts
1427
+ var ledgerIngressRedactor = createSecretRedactionContext();
1428
+
1347
1429
  // ../shared_libs/play-runtime/run-ledger.ts
1348
1430
  var LOG_TAIL_LIMIT = 100;
1349
- function isRecord(value) {
1431
+ function isRecord2(value) {
1350
1432
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1351
1433
  }
1352
1434
  function finiteNumber(value) {
@@ -1428,6 +1510,8 @@ function createEmptyPlayRunLedgerSnapshot(input2) {
1428
1510
  durationMs: startedAt !== null && finishedAt !== null ? Math.max(0, finishedAt - startedAt) : null,
1429
1511
  orderedStepIds: [],
1430
1512
  stepsById: {},
1513
+ orderedDatasetIds: [],
1514
+ datasetsById: {},
1431
1515
  logTail: [],
1432
1516
  totalLogCount: 0,
1433
1517
  logsTruncated: false,
@@ -1437,21 +1521,21 @@ function createEmptyPlayRunLedgerSnapshot(input2) {
1437
1521
  };
1438
1522
  }
1439
1523
  function normalizePlayRunLedgerSnapshot(value, fallback) {
1440
- if (!isRecord(value)) {
1524
+ if (!isRecord2(value)) {
1441
1525
  return createEmptyPlayRunLedgerSnapshot(fallback);
1442
1526
  }
1443
1527
  const orderedStepIds = Array.isArray(value.orderedStepIds) ? value.orderedStepIds.filter(
1444
1528
  (entry) => typeof entry === "string" && Boolean(entry.trim())
1445
1529
  ) : [];
1446
- const rawSteps = isRecord(value.stepsById) ? value.stepsById : {};
1530
+ const rawSteps = isRecord2(value.stepsById) ? value.stepsById : {};
1447
1531
  const stepsById = {};
1448
1532
  for (const [stepId, rawStep] of Object.entries(rawSteps)) {
1449
- if (!stepId.trim() || !isRecord(rawStep)) continue;
1533
+ if (!stepId.trim() || !isRecord2(rawStep)) continue;
1450
1534
  const rawStatus = normalizeStepStatus(rawStep.status);
1451
1535
  if (!rawStatus) continue;
1452
1536
  const completedAt = finiteNumber(rawStep.completedAt);
1453
1537
  const status = rawStatus === "running" && completedAt !== null ? "completed" : rawStatus;
1454
- const rawProgress = isRecord(rawStep.progress) ? rawStep.progress : null;
1538
+ const rawProgress = isRecord2(rawStep.progress) ? rawStep.progress : null;
1455
1539
  stepsById[stepId] = {
1456
1540
  stepId,
1457
1541
  label: optionalString(rawStep.label),
@@ -1466,6 +1550,23 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1466
1550
  progress: rawProgress ? normalizeStepProgress(rawProgress) : null
1467
1551
  };
1468
1552
  }
1553
+ const rawDatasets = isRecord2(value.datasetsById) ? value.datasetsById : {};
1554
+ const datasetsById = {};
1555
+ for (const [datasetId, rawDataset] of Object.entries(rawDatasets)) {
1556
+ if (!datasetId.trim() || !isRecord2(rawDataset)) continue;
1557
+ const phase = rawDataset.phase === "available" || rawDataset.phase === "failed" ? rawDataset.phase : "registered";
1558
+ datasetsById[datasetId] = {
1559
+ datasetId,
1560
+ path: optionalString(rawDataset.path) ?? `datasets.${datasetId}`,
1561
+ tableNamespace: optionalString(rawDataset.tableNamespace) ?? datasetId,
1562
+ phase,
1563
+ persistedRows: Math.max(0, finiteNumber(rawDataset.persistedRows) ?? 0),
1564
+ succeededRows: Math.max(0, finiteNumber(rawDataset.succeededRows) ?? 0),
1565
+ failedRows: Math.max(0, finiteNumber(rawDataset.failedRows) ?? 0),
1566
+ complete: rawDataset.complete === true,
1567
+ updatedAt: finiteNumber(rawDataset.updatedAt) ?? 0
1568
+ };
1569
+ }
1469
1570
  const createdAt = finiteNumber(value.createdAt) ?? fallback.createdAt ?? null;
1470
1571
  const startedAt = finiteNumber(value.startedAt) ?? fallback.startedAt ?? null;
1471
1572
  const finishedAt = finiteNumber(value.finishedAt) ?? fallback.finishedAt ?? null;
@@ -1485,6 +1586,10 @@ function normalizePlayRunLedgerSnapshot(value, fallback) {
1485
1586
  durationMs: startedAt !== null && finishedAt !== null ? Math.max(0, finishedAt - startedAt) : finiteNumber(value.durationMs),
1486
1587
  orderedStepIds: orderedStepIds.filter((stepId) => stepsById[stepId]),
1487
1588
  stepsById,
1589
+ orderedDatasetIds: (Array.isArray(value.orderedDatasetIds) ? value.orderedDatasetIds : Object.keys(datasetsById)).filter(
1590
+ (datasetId) => typeof datasetId === "string" && Boolean(datasetsById[datasetId])
1591
+ ),
1592
+ datasetsById,
1488
1593
  logTail: logTail.slice(-LOG_TAIL_LIMIT),
1489
1594
  // Snapshots persisted before totalLogCount existed only know the retained
1490
1595
  // tail, so the best lower bound for the cumulative count is the tail size.
@@ -1579,18 +1684,18 @@ function normalizePlayRunLiveStatus(value) {
1579
1684
  function isTerminalPlayRunLiveStatus(status) {
1580
1685
  return isTerminalPlayRunLifecycleStatus(status);
1581
1686
  }
1582
- function isRecord2(value) {
1687
+ function isRecord3(value) {
1583
1688
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
1584
1689
  }
1585
1690
  function finiteNumber2(value) {
1586
1691
  return typeof value === "number" && Number.isFinite(value) ? value : null;
1587
1692
  }
1588
1693
  function extractTerminalRunLogTail(result) {
1589
- if (!isRecord2(result) || !isRecord2(result._metadata)) {
1694
+ if (!isRecord3(result) || !isRecord3(result._metadata)) {
1590
1695
  return null;
1591
1696
  }
1592
1697
  const runLogTail = result._metadata.runLogTail;
1593
- if (!isRecord2(runLogTail) || !Array.isArray(runLogTail.tail)) {
1698
+ if (!isRecord3(runLogTail) || !Array.isArray(runLogTail.tail)) {
1594
1699
  return null;
1595
1700
  }
1596
1701
  const logTail = runLogTail.tail.filter(
@@ -1646,6 +1751,9 @@ function buildSnapshotFromLedger(snapshot) {
1646
1751
  ...snapshot.logsTruncated ? { logsTruncated: true } : {},
1647
1752
  activeArtifactTableNamespace: snapshot.activeArtifactTableNamespace ?? null,
1648
1753
  resultTableNamespace: snapshot.resultTableNamespace ?? null,
1754
+ datasets: snapshot.orderedDatasetIds.map((datasetId) => snapshot.datasetsById[datasetId]).filter(
1755
+ (dataset) => Boolean(dataset)
1756
+ ),
1649
1757
  nodeStates,
1650
1758
  activeNodeId: snapshot.activeStepId ?? null,
1651
1759
  ...rowOutcomes ? { rowOutcomes } : {}
@@ -2322,8 +2430,9 @@ function resolveToolExecuteTimeoutMs(toolId) {
2322
2430
  const normalized = toolId.trim().toLowerCase();
2323
2431
  return normalized === "deeplineagent" || normalized === "deeplineagent_deeplineagent" || normalized === "ai_inference" || normalized === "deeplineagent_ai_inference" || normalized === "aiinference" ? DEEPLINEAGENT_EXECUTE_TIMEOUT_MS : void 0;
2324
2432
  }
2433
+ var RUNS_FAILED_LOG_LIMIT = 20;
2325
2434
  var RUN_LOGS_PAGE_LIMIT = 1e3;
2326
- function isRecord3(value) {
2435
+ function isRecord4(value) {
2327
2436
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
2328
2437
  }
2329
2438
  function isPrebuiltPlayDescription(play) {
@@ -2480,7 +2589,7 @@ function updatePlayLiveStatusState(state, event) {
2480
2589
  }
2481
2590
  const runId = typeof payload.runId === "string" && payload.runId ? payload.runId : isPlayRunPackage(payload) ? payload.run.id : state.runId;
2482
2591
  const status = normalizeLiveStatus(payload.status) ?? (isPlayRunPackage(payload) ? normalizeLiveStatus(payload.run.status) : null) ?? state.status;
2483
- const progressPayload = isRecord3(payload.progress) ? payload.progress : {};
2592
+ const progressPayload = isRecord4(payload.progress) ? payload.progress : {};
2484
2593
  if (event.type === "play.run.final_status" && state.logs.length === 0 && state.lastLogSeq === 0) {
2485
2594
  const payloadLogs = readStringArray(payload.logs);
2486
2595
  const progressLogs = readStringArray(progressPayload.logs);
@@ -2595,9 +2704,9 @@ var DeeplineClient = class {
2595
2704
  return fields.length > 0 ? { fields } : schema;
2596
2705
  }
2597
2706
  schemaMetadata(schema, key) {
2598
- if (!isRecord3(schema)) return null;
2707
+ if (!isRecord4(schema)) return null;
2599
2708
  const value = schema[key];
2600
- return isRecord3(value) ? value : null;
2709
+ return isRecord4(value) ? value : null;
2601
2710
  }
2602
2711
  playRunCommand(play, options) {
2603
2712
  const target = play.reference || play.name;
@@ -2646,7 +2755,7 @@ var DeeplineClient = class {
2646
2755
  aliases,
2647
2756
  inputSchema: options?.compact ? this.compactSchema(play.inputSchema) : play.inputSchema ?? null,
2648
2757
  outputSchema: options?.compact ? this.compactSchema(play.outputSchema) : play.outputSchema ?? null,
2649
- staticPipeline: isRecord3(play.staticPipeline) ? play.staticPipeline : isRecord3(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord3(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
2758
+ staticPipeline: isRecord4(play.staticPipeline) ? play.staticPipeline : isRecord4(play.currentRevision?.staticPipeline) ? play.currentRevision.staticPipeline : isRecord4(play.liveRevision?.staticPipeline) ? play.liveRevision.staticPipeline : null,
2650
2759
  ...csvInput ? { csvInput } : {},
2651
2760
  ...rowOutputSchema ? { rowOutputSchema } : {},
2652
2761
  runCommand: runCommand2,
@@ -3580,7 +3689,46 @@ var DeeplineClient = class {
3580
3689
  const response = await this.http.get(
3581
3690
  `/api/v2/runs/${encodeURIComponent(runId)}${query}`
3582
3691
  );
3583
- return normalizePlayStatus(response);
3692
+ const status = normalizePlayStatus(response);
3693
+ if (options?.failedLogs !== true || status.status !== "failed") {
3694
+ return status;
3695
+ }
3696
+ const requestedFailedLogLimit = typeof options.failedLogLimit === "number" && Number.isFinite(options.failedLogLimit) ? Math.max(1, Math.floor(options.failedLogLimit)) : RUNS_FAILED_LOG_LIMIT;
3697
+ let failedLogs;
3698
+ let failedLogsLoaded = true;
3699
+ try {
3700
+ failedLogs = await this.getRunLogs(runId, {
3701
+ failed: true,
3702
+ limit: Math.min(RUNS_FAILED_LOG_LIMIT, requestedFailedLogLimit)
3703
+ });
3704
+ } catch (error) {
3705
+ failedLogsLoaded = false;
3706
+ const retryCommand = `deepline runs get ${runId} --log-failed --json`;
3707
+ const reason = error instanceof Error && error.message.trim() ? ` (${error.message.trim().slice(0, 500)})` : "";
3708
+ failedLogs = {
3709
+ runId,
3710
+ totalCount: 0,
3711
+ returnedCount: 0,
3712
+ firstSequence: null,
3713
+ lastSequence: null,
3714
+ truncated: false,
3715
+ hasMore: false,
3716
+ entries: [],
3717
+ view: "failed",
3718
+ warning: `Failed logs could not be loaded${reason}. The run status and persisted datasets are still available.`,
3719
+ next: { logs: retryCommand }
3720
+ };
3721
+ }
3722
+ return {
3723
+ ...status,
3724
+ failedLogs: {
3725
+ ...failedLogs,
3726
+ view: "failed",
3727
+ ...failedLogsLoaded ? {
3728
+ association: failedLogs.association ?? "terminal_failure_window"
3729
+ } : {}
3730
+ }
3731
+ };
3584
3732
  }
3585
3733
  /**
3586
3734
  * List play runs using the public runs resource model.
@@ -3731,6 +3879,7 @@ var DeeplineClient = class {
3731
3879
  onNotice: options?.onNotice,
3732
3880
  fallback: "none"
3733
3881
  })) {
3882
+ options?.onEvent?.(event);
3734
3883
  const status = updatePlayLiveStatusState(state, event);
3735
3884
  if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
3736
3885
  continue;
@@ -3794,6 +3943,7 @@ var DeeplineClient = class {
3794
3943
  mode: "cli",
3795
3944
  signal: options?.signal
3796
3945
  })) {
3946
+ options?.onEvent?.(event);
3797
3947
  sawEvent = true;
3798
3948
  const status = updatePlayLiveStatusState(state, event);
3799
3949
  if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
@@ -3843,6 +3993,37 @@ var DeeplineClient = class {
3843
3993
  * ```
3844
3994
  */
3845
3995
  async getRunLogs(runId, options) {
3996
+ if (options?.all === true && options.failed === true) {
3997
+ throw new DeeplineError(
3998
+ "runs.logs cannot combine all and failed views.",
3999
+ void 0,
4000
+ "INVALID_RUN_LOG_VIEW"
4001
+ );
4002
+ }
4003
+ if (options?.failed === true) {
4004
+ const requestedLimit = typeof options.limit === "number" && Number.isFinite(options.limit) && options.limit > 0 ? Math.trunc(options.limit) : RUNS_FAILED_LOG_LIMIT;
4005
+ const failedLimit = Math.min(RUNS_FAILED_LOG_LIMIT, requestedLimit);
4006
+ const page = await this.http.get(
4007
+ `/api/v2/runs/${encodeURIComponent(runId)}/logs?view=failed&limit=${failedLimit}`
4008
+ );
4009
+ return {
4010
+ runId: page.runId,
4011
+ totalCount: page.totalLogCount,
4012
+ returnedCount: page.entries.length,
4013
+ firstSequence: page.firstSeq,
4014
+ lastSequence: page.lastSeq,
4015
+ // The failed view is a complete designed window, not a pageable slice.
4016
+ // `truncated` means retention loss here; association/warning explain it.
4017
+ truncated: page.logsTruncated === true,
4018
+ hasMore: false,
4019
+ entries: page.entries.map((entry) => entry.line),
4020
+ view: page.view ?? "failed",
4021
+ association: page.association ?? "terminal_failure_window",
4022
+ ...page.warning ? { warning: page.warning } : {},
4023
+ ...page.next ? { next: page.next } : {},
4024
+ ...page.logsTruncated ? { logsTruncated: true } : {}
4025
+ };
4026
+ }
3846
4027
  const limit = options?.all ? Number.MAX_SAFE_INTEGER : typeof options?.limit === "number" && Number.isFinite(options.limit) && options.limit > 0 ? Math.trunc(options.limit) : 200;
3847
4028
  const fetchPage = (afterSeq2, pageLimit) => this.http.get(
3848
4029
  `/api/v2/runs/${encodeURIComponent(runId)}/logs?afterSeq=${afterSeq2}&limit=${pageLimit}`
@@ -3876,6 +4057,7 @@ var DeeplineClient = class {
3876
4057
  truncated: entries.length < probe.totalLogCount,
3877
4058
  hasMore: lastSequence !== null && lastSequence < lastStoredSeq,
3878
4059
  entries: entries.map((entry) => entry.line),
4060
+ view: options?.all ? "all" : "tail",
3879
4061
  ...probe.logsTruncated ? { logsTruncated: true } : {}
3880
4062
  };
3881
4063
  }
@@ -7179,14 +7361,14 @@ function sanitizeCsvProjectionInfo(input2) {
7179
7361
  const rows = input2.rows.map(stripCsvProjectionFields);
7180
7362
  return { rows, columns };
7181
7363
  }
7182
- function isRecord4(value) {
7364
+ function isRecord5(value) {
7183
7365
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
7184
7366
  }
7185
7367
  function isSerializedDataset(value) {
7186
- return isRecord4(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
7368
+ return isRecord5(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
7187
7369
  }
7188
7370
  function isPackagedDatasetOutput(value) {
7189
- return isRecord4(value) && value.kind === "dataset" && isRecord4(value.preview) && Array.isArray(value.preview.rows);
7371
+ return isRecord5(value) && value.kind === "dataset" && isRecord5(value.preview) && Array.isArray(value.preview.rows);
7190
7372
  }
7191
7373
  function pathParts(path) {
7192
7374
  return path.split(".").map((part) => part.trim()).filter(Boolean);
@@ -7194,7 +7376,7 @@ function pathParts(path) {
7194
7376
  function valueAtPath(root, path) {
7195
7377
  let cursor = root;
7196
7378
  for (const part of pathParts(path)) {
7197
- if (!isRecord4(cursor)) {
7379
+ if (!isRecord5(cursor)) {
7198
7380
  return void 0;
7199
7381
  }
7200
7382
  cursor = cursor[part];
@@ -7202,17 +7384,17 @@ function valueAtPath(root, path) {
7202
7384
  return cursor;
7203
7385
  }
7204
7386
  function totalRowsForDataset(result, datasetPath) {
7205
- const metadata = isRecord4(result._metadata) ? result._metadata : null;
7387
+ const metadata = isRecord5(result._metadata) ? result._metadata : null;
7206
7388
  const parentPath = datasetPath.split(".").slice(0, -1).join(".");
7207
7389
  const parent = parentPath ? valueAtPath({ result }, parentPath) : result;
7208
- return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord4(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
7390
+ return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord5(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
7209
7391
  }
7210
7392
  function rowArray(value) {
7211
7393
  if (!Array.isArray(value)) {
7212
7394
  return null;
7213
7395
  }
7214
7396
  const rows = value.filter(
7215
- (row) => isRecord4(row)
7397
+ (row) => isRecord5(row)
7216
7398
  );
7217
7399
  return rows.length === value.length ? rows : null;
7218
7400
  }
@@ -7236,7 +7418,7 @@ function inferColumns(rows) {
7236
7418
  return columns;
7237
7419
  }
7238
7420
  function columnsFromDatasetSummary(summary) {
7239
- if (!isRecord4(summary) || !isRecord4(summary.columnStats)) {
7421
+ if (!isRecord5(summary) || !isRecord5(summary.columnStats)) {
7240
7422
  return [];
7241
7423
  }
7242
7424
  return Object.keys(summary.columnStats).filter((column) => column);
@@ -7326,7 +7508,7 @@ function collectDatasetCandidates(input2) {
7326
7508
  });
7327
7509
  return;
7328
7510
  }
7329
- if (!isRecord4(input2.value)) {
7511
+ if (!isRecord5(input2.value)) {
7330
7512
  return;
7331
7513
  }
7332
7514
  for (const [key, child] of Object.entries(input2.value)) {
@@ -7343,12 +7525,12 @@ function collectDatasetCandidates(input2) {
7343
7525
  }
7344
7526
  }
7345
7527
  function collectCanonicalRowsInfos(statusOrResult) {
7346
- const root = isRecord4(statusOrResult) ? statusOrResult : null;
7347
- const result = isRecord4(root?.result) ? root.result : root;
7528
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
7529
+ const result = isRecord5(root?.result) ? root.result : root;
7348
7530
  if (!result) {
7349
7531
  return [];
7350
7532
  }
7351
- const metadata = isRecord4(result._metadata) ? result._metadata : null;
7533
+ const metadata = isRecord5(result._metadata) ? result._metadata : null;
7352
7534
  const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
7353
7535
  const candidates = [
7354
7536
  {
@@ -7372,8 +7554,8 @@ function collectCanonicalRowsInfos(statusOrResult) {
7372
7554
  total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
7373
7555
  }
7374
7556
  ];
7375
- if (isRecord4(result.output)) {
7376
- const outputMetadata = isRecord4(result.output._metadata) ? result.output._metadata : null;
7557
+ if (isRecord5(result.output)) {
7558
+ const outputMetadata = isRecord5(result.output._metadata) ? result.output._metadata : null;
7377
7559
  const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
7378
7560
  candidates.push(
7379
7561
  {
@@ -7400,14 +7582,14 @@ function collectCanonicalRowsInfos(statusOrResult) {
7400
7582
  }
7401
7583
  if (Array.isArray(result.steps)) {
7402
7584
  result.steps.forEach((step, index) => {
7403
- if (!isRecord4(step) || !isRecord4(step.output)) {
7585
+ if (!isRecord5(step) || !isRecord5(step.output)) {
7404
7586
  return;
7405
7587
  }
7406
7588
  const source = typeof step.output.path === "string" ? step.output.path : typeof step.id === "string" ? `steps.${step.id}.output` : `steps.${index}.output`;
7407
7589
  candidates.push({
7408
7590
  source,
7409
7591
  value: step.output,
7410
- total: step.output.rowCount ?? (isRecord4(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord4(step.progress) ? step.progress.total : void 0)
7592
+ total: step.output.rowCount ?? (isRecord5(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord5(step.progress) ? step.progress.total : void 0)
7411
7593
  });
7412
7594
  });
7413
7595
  }
@@ -7417,7 +7599,7 @@ function collectCanonicalRowsInfos(statusOrResult) {
7417
7599
  total: totalFromMetadata,
7418
7600
  output: candidates
7419
7601
  });
7420
- candidates.push(...collectPackagedStepDatasetCandidates(statusOrResult));
7602
+ candidates.push(...collectPackagedDatasetCandidates(statusOrResult));
7421
7603
  const seen = /* @__PURE__ */ new Set();
7422
7604
  const infos = [];
7423
7605
  for (const candidate of candidates) {
@@ -7434,37 +7616,33 @@ function collectCanonicalRowsInfos(statusOrResult) {
7434
7616
  }
7435
7617
  return infos;
7436
7618
  }
7437
- function collectPackagedStepDatasetCandidates(statusOrResult) {
7438
- const root = isRecord4(statusOrResult) ? statusOrResult : null;
7619
+ function collectPackagedDatasetCandidates(statusOrResult) {
7620
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
7439
7621
  if (!root) {
7440
7622
  return [];
7441
7623
  }
7442
- const pkg = isRecord4(root.package) ? root.package : root;
7443
- const steps = Array.isArray(pkg.steps) ? pkg.steps : [];
7624
+ const pkg = isRecord5(root.package) ? root.package : root;
7625
+ const datasets = Array.isArray(pkg.datasets) ? pkg.datasets : [];
7444
7626
  const candidates = [];
7445
- for (const step of steps) {
7446
- if (!isRecord4(step) || !isRecord4(step.output)) {
7627
+ for (const output2 of datasets) {
7628
+ if (!isRecord5(output2) || !isPackagedDatasetOutput(output2)) {
7447
7629
  continue;
7448
7630
  }
7449
- const output2 = step.output;
7450
- if (!isPackagedDatasetOutput(output2)) {
7451
- continue;
7452
- }
7453
- const source = typeof output2.path === "string" && output2.path.trim() ? output2.path.trim() : typeof step.id === "string" ? step.id : null;
7631
+ const source = typeof output2.path === "string" && output2.path.trim() ? output2.path.trim() : null;
7454
7632
  if (!source) {
7455
7633
  continue;
7456
7634
  }
7457
7635
  candidates.push({
7458
7636
  source,
7459
7637
  value: output2,
7460
- total: output2.rowCount ?? (isRecord4(output2.preview) ? output2.preview.totalRows : void 0) ?? (isRecord4(step.progress) ? step.progress.total : void 0)
7638
+ total: output2.rowCount ?? (isRecord5(output2.preview) ? output2.preview.totalRows : void 0)
7461
7639
  });
7462
7640
  }
7463
7641
  return candidates;
7464
7642
  }
7465
7643
  function collectSerializedDatasetRowsInfos(statusOrResult) {
7466
- const root = isRecord4(statusOrResult) ? statusOrResult : null;
7467
- const result = isRecord4(root?.result) ? root.result : root;
7644
+ const root = isRecord5(statusOrResult) ? statusOrResult : null;
7645
+ const result = isRecord5(root?.result) ? root.result : root;
7468
7646
  const candidates = [];
7469
7647
  if (result) {
7470
7648
  collectDatasetCandidates({
@@ -7472,7 +7650,7 @@ function collectSerializedDatasetRowsInfos(statusOrResult) {
7472
7650
  path: "result",
7473
7651
  output: candidates
7474
7652
  });
7475
- if (isRecord4(result.output)) {
7653
+ if (isRecord5(result.output)) {
7476
7654
  collectDatasetCandidates({
7477
7655
  value: result.output,
7478
7656
  path: "result",
@@ -7480,7 +7658,7 @@ function collectSerializedDatasetRowsInfos(statusOrResult) {
7480
7658
  });
7481
7659
  }
7482
7660
  }
7483
- candidates.push(...collectPackagedStepDatasetCandidates(statusOrResult));
7661
+ candidates.push(...collectPackagedDatasetCandidates(statusOrResult));
7484
7662
  const seen = /* @__PURE__ */ new Set();
7485
7663
  const infos = [];
7486
7664
  for (const candidate of candidates) {
@@ -7544,13 +7722,13 @@ function summarizeSampleValue(value, depth = 0) {
7544
7722
  if (typeof parsed === "number" || typeof parsed === "boolean") return parsed;
7545
7723
  if (depth >= 3) {
7546
7724
  if (Array.isArray(parsed)) return [];
7547
- if (isRecord4(parsed)) return {};
7725
+ if (isRecord5(parsed)) return {};
7548
7726
  return compactScalar(parsed);
7549
7727
  }
7550
7728
  if (Array.isArray(parsed)) {
7551
7729
  return parsed.slice(0, 3).map((item) => summarizeSampleValue(item, depth + 1));
7552
7730
  }
7553
- if (isRecord4(parsed)) {
7731
+ if (isRecord5(parsed)) {
7554
7732
  const out = {};
7555
7733
  for (const [key, nested] of Object.entries(parsed)) {
7556
7734
  if (["__dl", "meta", "metadata"].includes(key)) {
@@ -7581,7 +7759,7 @@ function compactCell(value) {
7581
7759
  }
7582
7760
  return `[${parsed.length} items]`;
7583
7761
  }
7584
- if (isRecord4(parsed)) {
7762
+ if (isRecord5(parsed)) {
7585
7763
  for (const key of ["matched_result", "output"]) {
7586
7764
  if (parsed[key] !== null && parsed[key] !== void 0 && parsed[key] !== "") {
7587
7765
  return compactCell(parsed[key]);
@@ -8644,17 +8822,17 @@ function parsePositiveInteger2(value, flagName) {
8644
8822
  }
8645
8823
  return parsed;
8646
8824
  }
8647
- function isRecord5(value) {
8825
+ function isRecord6(value) {
8648
8826
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
8649
8827
  }
8650
8828
  function stringValue(value) {
8651
8829
  return typeof value === "string" ? value.trim() : "";
8652
8830
  }
8653
8831
  function extractionEntries(value) {
8654
- if (Array.isArray(value)) return value.filter(isRecord5);
8655
- if (!isRecord5(value)) return [];
8832
+ if (Array.isArray(value)) return value.filter(isRecord6);
8833
+ if (!isRecord6(value)) return [];
8656
8834
  return Object.entries(value).map(
8657
- ([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
8835
+ ([name, entry]) => isRecord6(entry) ? { name, ...entry } : { name }
8658
8836
  );
8659
8837
  }
8660
8838
  var PlayBootstrapError = class extends Error {
@@ -9216,7 +9394,7 @@ function readCsvSampleRows(sample) {
9216
9394
  relax_column_count: true,
9217
9395
  trim: true
9218
9396
  });
9219
- return Array.isArray(parsedRows) ? parsedRows.filter(isRecord5) : [];
9397
+ return Array.isArray(parsedRows) ? parsedRows.filter(isRecord6) : [];
9220
9398
  }
9221
9399
  function readSourceCsvColumnSpecs(csvPath) {
9222
9400
  const sample = readCsvSample(csvPath);
@@ -9249,16 +9427,16 @@ function packagedCsvPathForPlay(csvPath) {
9249
9427
  return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
9250
9428
  }
9251
9429
  function getterNamesFromTool(tool, kind) {
9252
- const usageGuidance = isRecord5(tool?.usageGuidance) ? tool.usageGuidance : {};
9253
- const resultGuidance = isRecord5(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord5(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
9430
+ const usageGuidance = isRecord6(tool?.usageGuidance) ? tool.usageGuidance : {};
9431
+ const resultGuidance = isRecord6(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord6(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
9254
9432
  const key = kind === "list" ? "extractedLists" : "extractedValues";
9255
9433
  const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
9256
9434
  return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
9257
9435
  }
9258
9436
  function targetGettersFromTool(tool) {
9259
- const record = isRecord5(tool) ? tool : {};
9437
+ const record = isRecord6(tool) ? tool : {};
9260
9438
  const raw = record.targetGetters ?? record.target_getters;
9261
- if (!isRecord5(raw)) return {};
9439
+ if (!isRecord6(raw)) return {};
9262
9440
  const entries = [];
9263
9441
  for (const [target, value] of Object.entries(raw)) {
9264
9442
  const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
@@ -9279,10 +9457,10 @@ function listRowCandidateKeysFromTool(tool) {
9279
9457
  return [...keys].sort();
9280
9458
  }
9281
9459
  function inputPropertyNames(schema) {
9282
- if (!isRecord5(schema)) return [];
9283
- if (isRecord5(schema.properties)) return Object.keys(schema.properties);
9460
+ if (!isRecord6(schema)) return [];
9461
+ if (isRecord6(schema.properties)) return Object.keys(schema.properties);
9284
9462
  if (Array.isArray(schema.fields)) {
9285
- return schema.fields.filter(isRecord5).map((field) => stringValue(field.name)).filter(Boolean);
9463
+ return schema.fields.filter(isRecord6).map((field) => stringValue(field.name)).filter(Boolean);
9286
9464
  }
9287
9465
  return [];
9288
9466
  }
@@ -9296,7 +9474,7 @@ function schemaFieldDetails(schema) {
9296
9474
  return { required, optional };
9297
9475
  }
9298
9476
  function jsonSchemaTypeExpression(schema) {
9299
- if (!isRecord5(schema)) return "unknown";
9477
+ if (!isRecord6(schema)) return "unknown";
9300
9478
  const type = schema.type;
9301
9479
  if (Array.isArray(type)) {
9302
9480
  return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
@@ -9326,7 +9504,7 @@ function jsonSchemaTypeExpression(schema) {
9326
9504
  }
9327
9505
  }
9328
9506
  function objectPropertySchema(schema, property) {
9329
- return isRecord5(schema) && isRecord5(schema.properties) ? schema.properties[property] : null;
9507
+ return isRecord6(schema) && isRecord6(schema.properties) ? schema.properties[property] : null;
9330
9508
  }
9331
9509
  function playOutputHasField(schema, field) {
9332
9510
  return objectPropertySchema(schema, field) != null;
@@ -9502,14 +9680,14 @@ ${indent2.slice(2)}}`;
9502
9680
  }
9503
9681
  function requiredPlayInputFields(play) {
9504
9682
  const schema = play?.inputSchema;
9505
- if (!isRecord5(schema)) return [];
9683
+ if (!isRecord6(schema)) return [];
9506
9684
  if (Array.isArray(schema.required)) {
9507
9685
  return schema.required.filter(
9508
9686
  (value) => typeof value === "string"
9509
9687
  );
9510
9688
  }
9511
9689
  if (Array.isArray(schema.fields)) {
9512
- return schema.fields.filter(isRecord5).filter(
9690
+ return schema.fields.filter(isRecord6).filter(
9513
9691
  (field) => field.required === true && typeof field.name === "string"
9514
9692
  ).map((field) => String(field.name));
9515
9693
  }
@@ -9690,7 +9868,7 @@ function validateBootstrapRoutes(input2) {
9690
9868
  }
9691
9869
  }
9692
9870
  function staticPipelineSubsteps(pipeline) {
9693
- if (!isRecord5(pipeline)) return [];
9871
+ if (!isRecord6(pipeline)) return [];
9694
9872
  return [
9695
9873
  ...extractionEntries(pipeline.stages),
9696
9874
  ...extractionEntries(pipeline.substeps)
@@ -9698,7 +9876,7 @@ function staticPipelineSubsteps(pipeline) {
9698
9876
  }
9699
9877
  function playUsesMapBackedRuntime(play) {
9700
9878
  const pipeline = play?.staticPipeline;
9701
- if (!isRecord5(pipeline)) return false;
9879
+ if (!isRecord6(pipeline)) return false;
9702
9880
  if (stringValue(pipeline.tableNamespace)) return true;
9703
9881
  return staticPipelineSubsteps(pipeline).some((substep) => {
9704
9882
  if (stringValue(substep.type) === "map") return true;
@@ -9707,7 +9885,7 @@ function playUsesMapBackedRuntime(play) {
9707
9885
  aliases: [],
9708
9886
  runCommand: "",
9709
9887
  examples: [],
9710
- staticPipeline: isRecord5(substep.pipeline) ? substep.pipeline : null
9888
+ staticPipeline: isRecord6(substep.pipeline) ? substep.pipeline : null
9711
9889
  });
9712
9890
  });
9713
9891
  }
@@ -12444,6 +12622,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12444
12622
  let timedOut = false;
12445
12623
  let emittedDashboardUrl = false;
12446
12624
  let lastKnownWorkflowId = "";
12625
+ let launchedRevisionId = input2.request.revisionId?.trim() || null;
12447
12626
  let eventCount = 0;
12448
12627
  let firstRunIdMs = null;
12449
12628
  let lastPhase = null;
@@ -12469,13 +12648,24 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12469
12648
  }
12470
12649
  throw error;
12471
12650
  }
12472
- return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? { ...refreshed, dashboardUrl } : null;
12651
+ return TERMINAL_PLAY_STATUSES2.has(refreshed.status) ? {
12652
+ ...refreshed,
12653
+ dashboardUrl,
12654
+ ...launchedRevisionId ? { revisionId: launchedRevisionId } : {}
12655
+ } : null;
12473
12656
  };
12474
12657
  try {
12475
12658
  for await (const event of input2.client.startPlayRunStream(input2.request, {
12476
12659
  signal: controller.signal
12477
12660
  })) {
12478
12661
  eventCount += 1;
12662
+ const eventRevisionId = getStringField(
12663
+ getEventPayload(event),
12664
+ "revisionId"
12665
+ );
12666
+ if (eventRevisionId) {
12667
+ launchedRevisionId = eventRevisionId;
12668
+ }
12479
12669
  const eventRunId = getRunIdFromLiveEvent(event);
12480
12670
  if (typeof eventRunId === "string" && eventRunId && eventRunId !== "pending") {
12481
12671
  lastKnownWorkflowId = eventRunId;
@@ -12552,7 +12742,11 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12552
12742
  const finalStatus = getFinalStatusFromLiveEvent(event);
12553
12743
  if (finalStatus) {
12554
12744
  lastKnownWorkflowId ||= finalStatus.runId ?? "";
12555
- const canonicalTerminal = input2.request.profile === "absurd" ? await fetchKnownTerminalStatus() : { ...finalStatus, dashboardUrl };
12745
+ const canonicalTerminal = input2.request.profile === "absurd" ? await fetchKnownTerminalStatus() : {
12746
+ ...finalStatus,
12747
+ dashboardUrl,
12748
+ ...launchedRevisionId ? { revisionId: launchedRevisionId } : {}
12749
+ };
12556
12750
  if (!canonicalTerminal) {
12557
12751
  recordCliTrace({
12558
12752
  phase: "cli.play_start_stream_stale_terminal_ignored",
@@ -12924,6 +13118,10 @@ function buildRunNextCommands(status) {
12924
13118
  stop: `deepline runs stop ${runId} --reason "stale lock" --json`,
12925
13119
  logs: `deepline runs logs ${runId} --out run.log --json`
12926
13120
  };
13121
+ if (status.status === "failed") {
13122
+ commands.failedLogs = `deepline runs get ${runId} --log-failed --json`;
13123
+ if (status.rerunCommand) commands.run = status.rerunCommand;
13124
+ }
12927
13125
  if (status.dashboardUrl) {
12928
13126
  commands.open = `Open ${status.dashboardUrl} to see results.`;
12929
13127
  }
@@ -13075,7 +13273,7 @@ function buildInsufficientCreditsSummaryLines(input2) {
13075
13273
  const lines = [
13076
13274
  " status: stopped_insufficient_credits",
13077
13275
  completed === null ? " completed rows: unknown" : ` completed rows: ${formatInteger(completed)}${total !== null ? ` of ${formatInteger(total)}` : ""}`,
13078
- " reusable receipts: yes; rerun after adding credits to continue from completed provider work"
13276
+ " completed provider work: reused automatically when you rerun after adding credits"
13079
13277
  ];
13080
13278
  const billingUrl = getStringField(input2.billing, "billing_url");
13081
13279
  const recommended = formatCreditAmount(
@@ -13275,15 +13473,44 @@ function withTerminalPlayIdentity(status, playName) {
13275
13473
  function compactPlayStatus(status) {
13276
13474
  const packaged = getPlayRunPackage(status);
13277
13475
  if (packaged) {
13278
- const error2 = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : null);
13476
+ const packagedRun = readRecord(packaged.run);
13477
+ const packagedError = typeof packagedRun?.error === "string" ? packagedRun.error : null;
13478
+ const error2 = selectRunErrorForDisplay(status) ?? (typeof status.error === "string" ? String(status.error) : packagedError);
13479
+ const compactError = error2 ? compactRunErrorForEnvelope(error2, status.runId) : null;
13279
13480
  if (!error2) {
13280
- return packaged;
13481
+ return status.failedLogs || status.rerunCommand ? {
13482
+ ...packaged,
13483
+ ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
13484
+ next: {
13485
+ ...readRecord(packaged.next) ?? {},
13486
+ ...status.failedLogs ? {
13487
+ failedLogs: `deepline runs get ${status.runId} --log-failed --json`
13488
+ } : {},
13489
+ ...status.rerunCommand ? { run: status.rerunCommand } : {}
13490
+ }
13491
+ } : packaged;
13281
13492
  }
13282
- const run = packaged.run && typeof packaged.run === "object" ? packaged.run : null;
13493
+ const run = packagedRun;
13283
13494
  return {
13284
13495
  ...packaged,
13285
- error: error2,
13286
- ...run ? { run: { ...run, error: error2 } } : {}
13496
+ ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
13497
+ ...status.failedLogs ? {
13498
+ next: {
13499
+ ...readRecord(packaged.next) ?? {},
13500
+ failedLogs: `deepline runs get ${status.runId} --log-failed --json`
13501
+ }
13502
+ } : {},
13503
+ ...status.rerunCommand ? {
13504
+ next: {
13505
+ ...readRecord(packaged.next) ?? {},
13506
+ ...status.failedLogs ? {
13507
+ failedLogs: `deepline runs get ${status.runId} --log-failed --json`
13508
+ } : {},
13509
+ run: status.rerunCommand
13510
+ }
13511
+ } : {},
13512
+ error: compactError,
13513
+ ...run ? { run: { ...run, error: compactError } } : {}
13287
13514
  };
13288
13515
  }
13289
13516
  const rowsInfo = extractCanonicalRowsInfo(status);
@@ -13306,6 +13533,7 @@ function compactPlayStatus(status) {
13306
13533
  steps: normalizeStepsForEnvelope(status),
13307
13534
  errors: normalizeErrorsForEnvelope(status, error),
13308
13535
  logs: normalizeLogsForEnvelope(status),
13536
+ ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
13309
13537
  ...displayError ? { error: displayError } : {},
13310
13538
  ...warnings.length > 0 ? { warnings } : {},
13311
13539
  ...result !== void 0 ? { result: defaultResultForEnvelope(result) } : {},
@@ -13313,6 +13541,16 @@ function compactPlayStatus(status) {
13313
13541
  next: buildRunNextCommands(status)
13314
13542
  };
13315
13543
  }
13544
+ function compactRunErrorForEnvelope(message, runId) {
13545
+ const lines = message.split("\n");
13546
+ const firstStackFrame = lines.findIndex(
13547
+ (line, index) => index > 0 && /^\s*at\s+.*(?:\(?[^()\s]+:\d+:\d+\)?|native\)?|<anonymous>\)?)\s*$/u.test(
13548
+ line
13549
+ )
13550
+ );
13551
+ const headline = firstStackFrame >= 0 ? lines.slice(0, firstStackFrame).join("\n") : message;
13552
+ return truncateErrorForDisplay(headline, runId, 1e3);
13553
+ }
13316
13554
  function readRunPackageRun(packaged) {
13317
13555
  return packaged.run && typeof packaged.run === "object" && !Array.isArray(packaged.run) ? packaged.run : {};
13318
13556
  }
@@ -13432,6 +13670,14 @@ function actionToCommand(action) {
13432
13670
  record.datasetPath
13433
13671
  )} --out ${shellSingleQuote(`${record.datasetPath.split(".").pop() || "dataset"}.csv`)}`;
13434
13672
  }
13673
+ if (record.kind === "deepline_run_logs") {
13674
+ if (typeof record.command === "string" && record.command.trim()) {
13675
+ return record.command;
13676
+ }
13677
+ if (typeof record.runId === "string") {
13678
+ return record.view === "failed" ? `deepline runs get ${record.runId} --log-failed --json` : `deepline runs logs ${record.runId} --json`;
13679
+ }
13680
+ }
13435
13681
  if (record.kind === "deepline_db_query" && typeof record.sql === "string") {
13436
13682
  const maxRows = typeof record.maxRows === "number" && Number.isFinite(record.maxRows) ? Math.trunc(record.maxRows) : 20;
13437
13683
  return `deepline db query --sql ${shellSingleQuote(record.sql)} --max-rows ${maxRows} --json`;
@@ -13439,6 +13685,10 @@ function actionToCommand(action) {
13439
13685
  return null;
13440
13686
  }
13441
13687
  function readFirstDatasetActions(packaged) {
13688
+ for (const dataset of readRecordArray(packaged.datasets)) {
13689
+ const actions = readRecord(dataset.actions);
13690
+ if (actions) return actions;
13691
+ }
13442
13692
  for (const step of readRecordArray(packaged.steps)) {
13443
13693
  const output2 = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
13444
13694
  const actions = output2?.actions && typeof output2.actions === "object" && !Array.isArray(output2.actions) ? output2.actions : null;
@@ -13488,13 +13738,34 @@ function buildRunPackageTextLines(packaged) {
13488
13738
  if (runError && (status === "failed" || status === "cancelled")) {
13489
13739
  lines.push(` error: ${truncateErrorForDisplay(runError, runId)}`);
13490
13740
  }
13491
- for (const step of readRecordArray(packaged.steps)) {
13492
- const output2 = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
13493
- if (!output2 || output2.recovered !== true) continue;
13741
+ const failedLogs = readRecord(packaged.failedLogs);
13742
+ const failedLogEntries = Array.isArray(failedLogs?.entries) ? failedLogs.entries.filter(
13743
+ (entry) => typeof entry === "string"
13744
+ ) : [];
13745
+ const failedLogAssociation = typeof failedLogs?.association === "string" ? failedLogs.association : null;
13746
+ const failedLogWarning = typeof failedLogs?.warning === "string" && failedLogs.warning.trim() ? failedLogs.warning.trim() : null;
13747
+ if (failedLogEntries.length > 0) {
13748
+ lines.push(" failed logs:");
13749
+ lines.push(...failedLogEntries.map((entry) => ` ${entry}`));
13750
+ }
13751
+ if (failedLogAssociation === "retained_before_truncation") {
13752
+ lines.push(" failed log context: last retained lines before truncation");
13753
+ }
13754
+ if (failedLogWarning) {
13755
+ lines.push(` warning: ${failedLogWarning}`);
13756
+ }
13757
+ const failedLogNext = readRecord(failedLogs?.next);
13758
+ if (failedLogWarning && typeof failedLogNext?.logs === "string") {
13759
+ lines.push(
13760
+ failedLogAssociation === "retained_before_truncation" ? ` retained logs: ${failedLogNext.logs}` : ` retry failed logs: ${failedLogNext.logs}`
13761
+ );
13762
+ }
13763
+ for (const output2 of readRecordArray(packaged.datasets)) {
13764
+ if (output2.recovered !== true) continue;
13494
13765
  const rowCount = typeof output2.rowCount === "number" ? formatInteger(output2.rowCount) : "persisted";
13495
13766
  const datasetPath = typeof output2.path === "string" ? output2.path : "dataset";
13496
13767
  lines.push(
13497
- ` recoverable: ${rowCount} rows persisted in ${datasetPath} \u2014 re-running reuses them; export with the command below`
13768
+ ` dataset ${datasetPath}: available, ${rowCount} rows persisted; re-running reuses completed work`
13498
13769
  );
13499
13770
  }
13500
13771
  if (playName) {
@@ -13503,6 +13774,7 @@ function buildRunPackageTextLines(packaged) {
13503
13774
  lines.push(...formatPackageValueOutputLines(packaged));
13504
13775
  const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
13505
13776
  const billingCommand = actionToCommand(next.billing);
13777
+ const logsCommand = actionToCommand(next.logs);
13506
13778
  if (billingCommand) {
13507
13779
  const costState = status === "completed" || status === "failed" || status === "cancelled" ? "settles asynchronously \u2014 run the billing command below for totals" : "pending";
13508
13780
  lines.push(` cost: ${costState}`);
@@ -13527,12 +13799,49 @@ function buildRunPackageTextLines(packaged) {
13527
13799
  const inspectCommand = actionToCommand(next.inspect);
13528
13800
  const queryCommand = actionToCommand(next.query) ?? actionToCommand(datasetActions.query);
13529
13801
  const exportCommand = actionToCommand(next.export) ?? actionToCommand(datasetActions.exportCsv);
13802
+ const runAgainCommand = typeof next.run === "string" && next.run.trim() ? next.run.trim() : null;
13530
13803
  if (inspectCommand) lines.push(` inspect: ${inspectCommand}`);
13804
+ if (logsCommand) lines.push(` logs: ${logsCommand}`);
13531
13805
  if (billingCommand) lines.push(` billing: ${billingCommand}`);
13532
13806
  if (queryCommand) lines.push(` query: ${queryCommand}`);
13533
13807
  if (exportCommand) lines.push(` export CSV: ${exportCommand}`);
13808
+ if (runAgainCommand) {
13809
+ lines.push(" run again (completed work is reused):");
13810
+ lines.push(` ${runAgainCommand}`);
13811
+ }
13534
13812
  return lines;
13535
13813
  }
13814
+ function buildOrdinaryPlayRunCommand(options, resolvedRevisionId) {
13815
+ const target = options.target.kind === "file" ? options.target.path : options.target.name;
13816
+ const parts = ["deepline", "plays", "run", shellSingleQuote(target)];
13817
+ if (options.input && Object.keys(options.input).length > 0) {
13818
+ parts.push("--input", shellSingleQuote(JSON.stringify(options.input)));
13819
+ }
13820
+ if (options.profile)
13821
+ parts.push("--profile", shellSingleQuote(options.profile));
13822
+ const pinnedRevisionId = options.target.kind === "name" ? resolvedRevisionId ?? options.revisionId : null;
13823
+ if (pinnedRevisionId) {
13824
+ parts.push("--revision-id", shellSingleQuote(pinnedRevisionId));
13825
+ } else if (options.revisionSelector === "latest") {
13826
+ parts.push("--latest");
13827
+ } else if (options.revisionSelector === "live") {
13828
+ parts.push("--live");
13829
+ }
13830
+ if (options.waitTimeoutMs !== null) {
13831
+ parts.push("--tail-timeout-ms", String(options.waitTimeoutMs));
13832
+ }
13833
+ if (options.noOpen) parts.push("--no-open");
13834
+ if (options.fullJson) parts.push("--full");
13835
+ if (options.jsonOutput && options.emitLogs) parts.push("--logs");
13836
+ if (options.jsonOutput) parts.push("--json");
13837
+ return parts.join(" ");
13838
+ }
13839
+ function withOrdinaryRunAgainCommand(status, options, resolvedRevisionId) {
13840
+ return status.status === "failed" ? {
13841
+ ...status,
13842
+ rerunCommand: buildOrdinaryPlayRunCommand(options, resolvedRevisionId)
13843
+ } : status;
13844
+ }
13536
13845
  function writePlayResult(status, jsonOutput, options) {
13537
13846
  const packaged = getPlayRunPackage(status);
13538
13847
  if (jsonOutput) {
@@ -13542,8 +13851,9 @@ function writePlayResult(status, jsonOutput, options) {
13542
13851
  return;
13543
13852
  }
13544
13853
  if (packaged && !options?.fullJson) {
13545
- const lines2 = buildRunPackageTextLines(packaged);
13546
- printCommandEnvelope(packaged, {
13854
+ const displayPackage = compactPlayStatus(status);
13855
+ const lines2 = buildRunPackageTextLines(displayPackage);
13856
+ printCommandEnvelope(displayPackage, {
13547
13857
  json: false,
13548
13858
  text: `${lines2.join("\n")}
13549
13859
  `
@@ -13570,6 +13880,21 @@ function writePlayResult(status, jsonOutput, options) {
13570
13880
  const displayError = formatPlayErrorForDisplay(status, progressError) ?? progressError;
13571
13881
  lines.push(` error: ${truncateErrorForDisplay(displayError, runId)}`);
13572
13882
  }
13883
+ if (status.status === "failed") {
13884
+ const failedLogEntries = status.failedLogs?.entries ?? [];
13885
+ if (failedLogEntries.length > 0) {
13886
+ lines.push(" failed logs:");
13887
+ lines.push(...failedLogEntries.map((entry) => ` ${entry}`));
13888
+ } else {
13889
+ lines.push(
13890
+ ` failed logs: deepline runs get ${runId} --log-failed --json`
13891
+ );
13892
+ }
13893
+ if (status.rerunCommand) {
13894
+ lines.push(" run again (completed work is reused):");
13895
+ lines.push(` ${status.rerunCommand}`);
13896
+ }
13897
+ }
13573
13898
  const renderedServerView = renderServerResultView(status.resultView);
13574
13899
  if (result) {
13575
13900
  lines.push(...formatReturnValue(result));
@@ -13612,20 +13937,27 @@ async function resolvePlayRunOutputStatus(input2) {
13612
13937
  const streamedPackage = getPlayRunPackage(input2.status);
13613
13938
  const refreshForFullJson = input2.fullJson && streamedPackage !== null;
13614
13939
  const streamedTextPackageIncomplete = !input2.jsonOutput && input2.status.status === "completed" && playRunPackageTextLedgerIncomplete(streamedPackage);
13615
- if (!refreshForFullJson && !streamedTextPackageIncomplete) {
13940
+ const refreshFailedTerminal = input2.status.status === "failed";
13941
+ if (!refreshForFullJson && !streamedTextPackageIncomplete && !refreshFailedTerminal) {
13616
13942
  return input2.status;
13617
13943
  }
13618
13944
  let refreshedStatus = await input2.client.getPlayStatus(runId, {
13619
13945
  billing: false,
13620
13946
  full: input2.fullJson
13621
13947
  });
13622
- for (let attempt = 0; attempt < 3 && streamedTextPackageIncomplete && refreshedStatus.status === "completed" && playRunPackageTextLedgerIncomplete(getPlayRunPackage(refreshedStatus)); attempt += 1) {
13948
+ for (let attempt = 0; attempt < 3 && (streamedTextPackageIncomplete && refreshedStatus.status === "completed" && playRunPackageTextLedgerIncomplete(getPlayRunPackage(refreshedStatus)) || refreshFailedTerminal && (refreshedStatus.status !== "failed" || getPlayRunPackage(refreshedStatus) === null)); attempt += 1) {
13623
13949
  await sleep5(250);
13624
13950
  refreshedStatus = await input2.client.getPlayStatus(runId, {
13625
13951
  billing: false,
13626
13952
  full: input2.fullJson
13627
13953
  });
13628
13954
  }
13955
+ if (refreshFailedTerminal && (refreshedStatus.status !== "failed" || getPlayRunPackage(refreshedStatus) === null)) {
13956
+ return input2.status;
13957
+ }
13958
+ if (input2.status.status === "completed" && refreshedStatus.status !== "completed") {
13959
+ return input2.status;
13960
+ }
13629
13961
  const dashboardUrl = input2.status.dashboardUrl;
13630
13962
  return typeof dashboardUrl === "string" ? { ...refreshedStatus, dashboardUrl } : refreshedStatus;
13631
13963
  }
@@ -13760,37 +14092,16 @@ function resolveDatasetByName(available, datasetPath) {
13760
14092
  if (exact) {
13761
14093
  return exact;
13762
14094
  }
14095
+ const byDatasetId = available.find((info) => info.datasetId === target);
14096
+ if (byDatasetId) {
14097
+ return byDatasetId;
14098
+ }
13763
14099
  const byNamespace = available.find(
13764
14100
  (info) => info.tableNamespace && info.tableNamespace === target
13765
14101
  );
13766
14102
  if (byNamespace) {
13767
14103
  return byNamespace;
13768
14104
  }
13769
- const trailing = target.split(".").filter(Boolean).at(-1);
13770
- if (!trailing) {
13771
- return null;
13772
- }
13773
- const byTrailing = available.find(
13774
- (info) => info.tableNamespace === trailing || typeof info.source === "string" && info.source.split(".").filter(Boolean).at(-1) === trailing
13775
- );
13776
- if (byTrailing) {
13777
- return byTrailing;
13778
- }
13779
- if (target.split(".").filter(Boolean)[0] === "result") {
13780
- const recovered = available.filter((info) => info.recovered);
13781
- if (recovered.length === 1) {
13782
- return recovered[0];
13783
- }
13784
- if (recovered.length > 1) {
13785
- const names = recovered.map((info) => info.tableNamespace ?? info.source).filter((name) => typeof name === "string");
13786
- throw new DeeplineError(
13787
- `Run returned multiple recovered datasets; '${target}' is ambiguous. Choose one with --dataset <path>: ${names.join(", ")}.`,
13788
- void 0,
13789
- "RUN_EXPORT_DATASET_AMBIGUOUS",
13790
- { dataset: target, available: names }
13791
- );
13792
- }
13793
- }
13794
14105
  return null;
13795
14106
  }
13796
14107
  function assertDatasetHasExportableRows(input2) {
@@ -13970,7 +14281,7 @@ function extractPlayValidationErrors(value) {
13970
14281
  if (value instanceof DeeplineError) {
13971
14282
  return extractPlayValidationErrors(value.details);
13972
14283
  }
13973
- if (!isRecord6(value)) {
14284
+ if (!isRecord7(value)) {
13974
14285
  return [];
13975
14286
  }
13976
14287
  const directErrors = stringArrayField(value, "errors");
@@ -14338,7 +14649,7 @@ function shouldUseLocalOnlyPlayCheck() {
14338
14649
  const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
14339
14650
  return value === "1" || value === "true" || value === "yes" || value === "on";
14340
14651
  }
14341
- function isRecord6(value) {
14652
+ function isRecord7(value) {
14342
14653
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
14343
14654
  }
14344
14655
  function stringValue2(value) {
@@ -14348,14 +14659,14 @@ function asArray(value) {
14348
14659
  return Array.isArray(value) ? value : [];
14349
14660
  }
14350
14661
  function extractionEntries2(value) {
14351
- if (Array.isArray(value)) return value.filter(isRecord6);
14352
- if (!isRecord6(value)) return [];
14662
+ if (Array.isArray(value)) return value.filter(isRecord7);
14663
+ if (!isRecord7(value)) return [];
14353
14664
  return Object.entries(value).map(
14354
- ([name, entry]) => isRecord6(entry) ? { name, ...entry } : { name }
14665
+ ([name, entry]) => isRecord7(entry) ? { name, ...entry } : { name }
14355
14666
  );
14356
14667
  }
14357
14668
  function firstRawPath(entry) {
14358
- const details = isRecord6(entry.details) ? entry.details : {};
14669
+ const details = isRecord7(entry.details) ? entry.details : {};
14359
14670
  const paths = [
14360
14671
  ...asArray(details.rawToolOutputPaths),
14361
14672
  ...asArray(details.raw_tool_output_paths),
@@ -14373,12 +14684,12 @@ function checkHintRawPath(value) {
14373
14684
  function collectStaticPipelineToolIds(staticPipeline) {
14374
14685
  const seen = /* @__PURE__ */ new Set();
14375
14686
  const visitPipeline = (pipeline) => {
14376
- if (!isRecord6(pipeline)) return;
14687
+ if (!isRecord7(pipeline)) return;
14377
14688
  for (const step of [
14378
14689
  ...asArray(pipeline.stages),
14379
14690
  ...asArray(pipeline.substeps)
14380
14691
  ]) {
14381
- if (!isRecord6(step)) continue;
14692
+ if (!isRecord7(step)) continue;
14382
14693
  if (step.type === "tool") {
14383
14694
  const toolId = stringValue2(step.toolId) || stringValue2(step.tool);
14384
14695
  if (toolId) seen.add(toolId);
@@ -14392,9 +14703,9 @@ function collectStaticPipelineToolIds(staticPipeline) {
14392
14703
  return [...seen].sort();
14393
14704
  }
14394
14705
  function toolGetterHintFromMetadata(toolId, tool) {
14395
- const usageGuidance = isRecord6(tool.usageGuidance) ? tool.usageGuidance : {};
14396
- const resultGuidance = isRecord6(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord6(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
14397
- const toolResponse = isRecord6(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord6(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
14706
+ const usageGuidance = isRecord7(tool.usageGuidance) ? tool.usageGuidance : {};
14707
+ const resultGuidance = isRecord7(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord7(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
14708
+ const toolResponse = isRecord7(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord7(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
14398
14709
  const lists = extractionEntries2(
14399
14710
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
14400
14711
  ).map((entry) => ({
@@ -14834,14 +15145,17 @@ async function handleFileBackedRun(options) {
14834
15145
  } else {
14835
15146
  progress.fail();
14836
15147
  }
14837
- const outputStatus = withTerminalPlayIdentity(
14838
- await resolvePlayRunOutputStatus({
14839
- client: client2,
14840
- status: finalStatus,
14841
- fullJson: options.fullJson,
14842
- jsonOutput: options.jsonOutput
14843
- }),
14844
- playName
15148
+ const outputStatus = withOrdinaryRunAgainCommand(
15149
+ withTerminalPlayIdentity(
15150
+ await resolvePlayRunOutputStatus({
15151
+ client: client2,
15152
+ status: finalStatus,
15153
+ fullJson: options.fullJson,
15154
+ jsonOutput: options.jsonOutput
15155
+ }),
15156
+ playName
15157
+ ),
15158
+ options
14845
15159
  );
14846
15160
  traceCliSync(
14847
15161
  "cli.play_write_result",
@@ -14850,7 +15164,7 @@ async function handleFileBackedRun(options) {
14850
15164
  fullJson: options.fullJson
14851
15165
  })
14852
15166
  );
14853
- return finalStatus.status === "completed" ? 0 : 1;
15167
+ return outputStatus.status === "completed" ? 0 : 1;
14854
15168
  }
14855
15169
  progress.phase("starting run");
14856
15170
  const started = await traceCliSpan(
@@ -14998,14 +15312,18 @@ async function handleNamedRun(options) {
14998
15312
  } else {
14999
15313
  progress.fail();
15000
15314
  }
15001
- const outputStatus = withTerminalPlayIdentity(
15002
- await resolvePlayRunOutputStatus({
15003
- client: client2,
15004
- status: finalStatus,
15005
- fullJson: options.fullJson,
15006
- jsonOutput: options.jsonOutput
15007
- }),
15008
- playName
15315
+ const outputStatus = withOrdinaryRunAgainCommand(
15316
+ withTerminalPlayIdentity(
15317
+ await resolvePlayRunOutputStatus({
15318
+ client: client2,
15319
+ status: finalStatus,
15320
+ fullJson: options.fullJson,
15321
+ jsonOutput: options.jsonOutput
15322
+ }),
15323
+ playName
15324
+ ),
15325
+ options,
15326
+ finalStatus.revisionId ?? selectedRevisionId
15009
15327
  );
15010
15328
  traceCliSync(
15011
15329
  "cli.play_write_result",
@@ -15014,7 +15332,7 @@ async function handleNamedRun(options) {
15014
15332
  fullJson: options.fullJson
15015
15333
  })
15016
15334
  );
15017
- return finalStatus.status === "completed" ? 0 : 1;
15335
+ return outputStatus.status === "completed" ? 0 : 1;
15018
15336
  }
15019
15337
  progress.phase("starting run");
15020
15338
  const started = await traceCliSpan(
@@ -15075,7 +15393,7 @@ async function handlePlayRun(args) {
15075
15393
  function parseRunIdPositional(args, usage) {
15076
15394
  for (let index = 0; index < args.length; index += 1) {
15077
15395
  const arg = args[index];
15078
- if (arg === "--json" || arg === "--full" || arg === "--logs" || arg === "--compact" || arg === "--limit") {
15396
+ if (arg === "--json" || arg === "--full" || arg === "--logs" || arg === "--compact" || arg === "--log-failed" || arg === "--failed" || arg === "--limit") {
15079
15397
  if (arg === "--limit" && args[index + 1]) {
15080
15398
  index += 1;
15081
15399
  }
@@ -15092,7 +15410,7 @@ function parseRunIdPositional(args, usage) {
15092
15410
  throw new DeeplineError(usage);
15093
15411
  }
15094
15412
  async function handleRunGet(args) {
15095
- const usage = "Usage: deepline runs get <run-id> [--json] [--full]";
15413
+ const usage = "Usage: deepline runs get <run-id> [--json] [--full] [--log-failed]";
15096
15414
  let runId;
15097
15415
  try {
15098
15416
  runId = parseRunIdPositional(args, usage);
@@ -15102,7 +15420,8 @@ async function handleRunGet(args) {
15102
15420
  }
15103
15421
  const client2 = new DeeplineClient();
15104
15422
  const status = await client2.runs.get(runId, {
15105
- full: args.includes("--full")
15423
+ full: args.includes("--full"),
15424
+ failedLogs: args.includes("--log-failed")
15106
15425
  });
15107
15426
  writePlayResult(status, argsWantJson(args), {
15108
15427
  fullJson: args.includes("--full")
@@ -15191,7 +15510,37 @@ async function handleRunTail(args) {
15191
15510
  }
15192
15511
  const client2 = new DeeplineClient();
15193
15512
  const jsonOutput = argsWantJson(args);
15513
+ const compact = args.includes("--compact");
15514
+ const compactState = {
15515
+ lastLogIndex: 0,
15516
+ emittedRunnerStarted: false,
15517
+ lastProgressSignature: null,
15518
+ lastProgressHeartbeatAt: 0,
15519
+ lastStatusHeartbeatAt: 0
15520
+ };
15194
15521
  const status = await client2.runs.tail(runId, {
15522
+ onEvent: compact && !jsonOutput ? (event) => {
15523
+ const transition = getStepTransitionLineFromLiveEvent(
15524
+ event,
15525
+ compactState
15526
+ );
15527
+ if (transition) process.stdout.write(`${transition}
15528
+ `);
15529
+ for (const line of getProgressLinesFromLiveEvent(event)) {
15530
+ const nowMs = Date.now();
15531
+ if (shouldPrintPlayProgressLine({
15532
+ signature: line,
15533
+ lastProgressSignature: compactState.lastProgressSignature,
15534
+ lastProgressHeartbeatAt: compactState.lastProgressHeartbeatAt,
15535
+ nowMs
15536
+ })) {
15537
+ compactState.lastProgressSignature = line;
15538
+ compactState.lastProgressHeartbeatAt = nowMs;
15539
+ process.stdout.write(`${line}
15540
+ `);
15541
+ }
15542
+ }
15543
+ } : void 0,
15195
15544
  // Human mode only: in --json mode emit nothing non-protocol.
15196
15545
  onReconnect: jsonOutput ? void 0 : ({ reason }) => {
15197
15546
  process.stderr.write(
@@ -15204,7 +15553,7 @@ async function handleRunTail(args) {
15204
15553
  return status.status === "failed" ? 1 : 0;
15205
15554
  }
15206
15555
  async function handleRunLogs(args) {
15207
- const usage = "Usage: deepline runs logs <run-id> [--limit 200] [--out run.log] [--json]";
15556
+ const usage = "Usage: deepline runs logs <run-id> [--limit 200] [--failed] [--out run.log] [--json]";
15208
15557
  let runId;
15209
15558
  try {
15210
15559
  runId = parseRunIdPositional(args, usage);
@@ -15214,6 +15563,7 @@ async function handleRunLogs(args) {
15214
15563
  }
15215
15564
  let limit = 200;
15216
15565
  let outPath = null;
15566
+ const failed = args.includes("--failed");
15217
15567
  for (let index = 0; index < args.length; index += 1) {
15218
15568
  const arg = args[index];
15219
15569
  if (arg === "--limit" && args[index + 1]) {
@@ -15224,6 +15574,12 @@ async function handleRunLogs(args) {
15224
15574
  outPath = resolve8(args[++index]);
15225
15575
  }
15226
15576
  }
15577
+ if (failed && outPath) {
15578
+ console.error(
15579
+ "--failed cannot be combined with --out. Remove --failed to export the full persisted log stream."
15580
+ );
15581
+ return 1;
15582
+ }
15227
15583
  const client2 = new DeeplineClient();
15228
15584
  if (outPath) {
15229
15585
  const result2 = await client2.runs.logs(runId, { all: true });
@@ -15255,7 +15611,8 @@ async function handleRunLogs(args) {
15255
15611
  );
15256
15612
  return 0;
15257
15613
  }
15258
- const result = await client2.runs.logs(runId, { limit });
15614
+ const result = await client2.runs.logs(runId, { limit, failed });
15615
+ const text = buildRunLogsText(result);
15259
15616
  printCommandEnvelope(
15260
15617
  {
15261
15618
  runId: result.runId,
@@ -15267,18 +15624,33 @@ async function handleRunLogs(args) {
15267
15624
  hasMore: result.hasMore,
15268
15625
  ...result.logsTruncated ? { logsTruncated: true } : {},
15269
15626
  entries: result.entries,
15627
+ ...result.view ? { view: result.view } : {},
15628
+ ...result.association ? { association: result.association } : {},
15629
+ ...result.warning ? { warning: result.warning } : {},
15270
15630
  next: {
15631
+ ...result.next ?? {},
15271
15632
  export: `deepline runs logs ${result.runId} --out run.log --json`
15272
15633
  },
15273
15634
  render: { sections: [{ title: "run logs", lines: result.entries }] }
15274
15635
  },
15275
15636
  {
15276
15637
  json: argsWantJson(args),
15277
- text: `${result.entries.join("\n")}${result.entries.length > 0 ? "\n" : ""}`
15638
+ text
15278
15639
  }
15279
15640
  );
15280
15641
  return 0;
15281
15642
  }
15643
+ function buildRunLogsText(result) {
15644
+ const lines = [...result.entries];
15645
+ if (result.warning) {
15646
+ if (lines.length > 0) lines.push("");
15647
+ lines.push(`warning: ${result.warning}`);
15648
+ lines.push(
15649
+ `retained logs: ${result.next?.logs ?? `deepline runs logs ${result.runId} --out run.log --json`}`
15650
+ );
15651
+ }
15652
+ return `${lines.join("\n")}${lines.length > 0 ? "\n" : ""}`;
15653
+ }
15282
15654
  async function handleRunStop(args) {
15283
15655
  const usage = 'Usage: deepline runs stop <run-id> [--reason "text"] [--json]';
15284
15656
  let runId;
@@ -16177,8 +16549,8 @@ Idempotent execution:
16177
16549
 
16178
16550
  await ctx.tools.execute({ id: 'company_lookup', tool, input });
16179
16551
 
16180
- The authored id is still required for readable logs, metadata, and receipt
16181
- attachment, but renaming it alone does not rebuy the same provider request.
16552
+ The authored id is still required for readable logs and metadata, but
16553
+ renaming it alone does not rebuy the same provider request.
16182
16554
 
16183
16555
  For rows, use ctx.dataset plus a stable row key:
16184
16556
 
@@ -16487,13 +16859,18 @@ Notes:
16487
16859
  Examples:
16488
16860
  deepline runs get play/my-play/run/20260501t000000-000
16489
16861
  deepline runs get play/my-play/run/20260501t000000-000 --json
16862
+ deepline runs get play/my-play/run/20260501t000000-000 --log-failed --json
16490
16863
  deepline runs get play/my-play/run/20260501t000000-000 --full --json
16491
16864
  `
16492
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--full", "Debug only: with --json, emit the raw status payload").action(async (runId, options) => {
16865
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--full", "Debug only: with --json, emit the raw status payload").option(
16866
+ "--log-failed",
16867
+ "Attach a bounded terminal-failure log window for failed runs"
16868
+ ).action(async (runId, options) => {
16493
16869
  process.exitCode = await handleRunGet([
16494
16870
  runId,
16495
16871
  ...options.json ? ["--json"] : [],
16496
- ...options.full ? ["--full"] : []
16872
+ ...options.full ? ["--full"] : [],
16873
+ ...options.logFailed ? ["--log-failed"] : []
16497
16874
  ]);
16498
16875
  });
16499
16876
  runs.command("list").description("List play runs.").addHelpText(
@@ -16537,13 +16914,17 @@ Examples:
16537
16914
  `
16538
16915
  Notes:
16539
16916
  Streams live run events until the stream ends. Use get for current status and
16540
- logs for persisted log history.
16917
+ logs for persisted log history. In human output, --compact prints deduplicated
16918
+ step transitions and progress instead of the full event stream.
16541
16919
 
16542
16920
  Examples:
16543
16921
  deepline runs tail play/my-play/run/20260501t000000-000
16544
16922
  deepline runs tail play/my-play/run/20260501t000000-000 --compact --json
16545
16923
  `
16546
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--compact", "Drop verbose fields from JSON output").action(async (runId, options) => {
16924
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
16925
+ "--compact",
16926
+ "Show deduplicated step transitions and progress; compact JSON output"
16927
+ ).action(async (runId, options) => {
16547
16928
  process.exitCode = await handleRunTail([
16548
16929
  runId,
16549
16930
  ...options.json ? ["--json"] : [],
@@ -16560,17 +16941,19 @@ Notes:
16560
16941
  Examples:
16561
16942
  deepline runs logs play/my-play/run/20260501t000000-000
16562
16943
  deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
16944
+ deepline runs logs play/my-play/run/20260501t000000-000 --failed --json
16563
16945
  deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
16564
16946
  `
16565
16947
  ).option(
16566
16948
  "--limit <count>",
16567
16949
  "Maximum recent log lines to print without --out",
16568
16950
  "200"
16569
- ).option("--out <path>", "Write the full persisted log stream to a file").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
16951
+ ).option("--out <path>", "Write the full persisted log stream to a file").option("--failed", "Show the bounded terminal-failure log window").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
16570
16952
  process.exitCode = await handleRunLogs([
16571
16953
  runId,
16572
16954
  ...options.limit ? ["--limit", options.limit] : [],
16573
16955
  ...options.out ? ["--out", options.out] : [],
16956
+ ...options.failed ? ["--failed"] : [],
16574
16957
  ...options.json ? ["--json"] : []
16575
16958
  ]);
16576
16959
  });
@@ -18483,7 +18866,7 @@ function isMarkedTestAiInferenceCommand(command) {
18483
18866
  if (normalizeEnrichPlayRef(command.tool) !== "run_javascript") {
18484
18867
  return false;
18485
18868
  }
18486
- return isRecord7(command.payload) && command.payload[ENRICH_TEST_AI_INFERENCE_PAYLOAD_MARKER] === true;
18869
+ return isRecord8(command.payload) && command.payload[ENRICH_TEST_AI_INFERENCE_PAYLOAD_MARKER] === true;
18487
18870
  }
18488
18871
  function enrichDebugEnabled(env = process.env) {
18489
18872
  const raw = String(env.DEEPLINE_DEBUG_ENRICH ?? "").trim().toLowerCase();
@@ -18742,6 +19125,27 @@ function sdkEnrichCommandText(args) {
18742
19125
  }
18743
19126
  return `${command.slice(0, SDK_ENRICH_TELEMETRY_COMMAND_MAX_LENGTH - 3)}...`;
18744
19127
  }
19128
+ function rewriteGeneratedPlayRerunForEnrich(status, enrichCommand) {
19129
+ const rewrite = (value) => {
19130
+ if (Array.isArray(value)) {
19131
+ return value.map(rewrite);
19132
+ }
19133
+ if (!isRecord8(value)) {
19134
+ return value;
19135
+ }
19136
+ const next = Object.fromEntries(
19137
+ Object.entries(value).map(([key, entry]) => [
19138
+ key,
19139
+ key === "rerunCommand" && typeof entry === "string" ? enrichCommand : rewrite(entry)
19140
+ ])
19141
+ );
19142
+ if (isRecord8(next.next) && typeof next.next.run === "string") {
19143
+ next.next = { ...next.next, run: enrichCommand };
19144
+ }
19145
+ return next;
19146
+ };
19147
+ return rewrite(status);
19148
+ }
18745
19149
  function countConfiguredEnrichColumns(config) {
18746
19150
  const count = (commands) => commands.reduce((total, command) => {
18747
19151
  if ("with_waterfall" in command) {
@@ -19199,7 +19603,7 @@ async function resolveWatchedGeneratedPlayStatus(input2) {
19199
19603
  }
19200
19604
  return input2.client.runs.get(runId, { full: true });
19201
19605
  }
19202
- function isRecord7(value) {
19606
+ function isRecord8(value) {
19203
19607
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
19204
19608
  }
19205
19609
  async function captureStdout(run, options = {}) {
@@ -19486,13 +19890,13 @@ function readFirstEnrichDatasetActions(value) {
19486
19890
  return null;
19487
19891
  }
19488
19892
  const record = candidate;
19489
- const actions = isRecord7(record.actions) ? record.actions : null;
19490
- const query = isRecord7(actions?.query) ? actions.query : null;
19893
+ const actions = isRecord8(record.actions) ? record.actions : null;
19894
+ const query = isRecord8(actions?.query) ? actions.query : null;
19491
19895
  if (query?.kind === "deepline_db_query") {
19492
19896
  return {
19493
19897
  dataset: record,
19494
19898
  query,
19495
- ...isRecord7(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
19899
+ ...isRecord8(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
19496
19900
  };
19497
19901
  }
19498
19902
  if (options.allowLegacy && record.kind === "dataset" && typeof record.queryDatasetCommand === "string" && record.queryDatasetCommand.trim()) {
@@ -19545,7 +19949,7 @@ function enrichCustomerDbJson(input2) {
19545
19949
  const dataset = actions.dataset;
19546
19950
  const sql = actionStringField(query, "sql") ?? parseSqlFromDbQueryCommand(actions.queryDatasetCommand);
19547
19951
  const datasetPath = actionStringField(query, "datasetPath") ?? actionStringField(dataset, "path") ?? actionStringField(dataset, "tableNamespace");
19548
- const api = isRecord7(query.api) ? query.api : null;
19952
+ const api = isRecord8(query.api) ? query.api : null;
19549
19953
  const apiPath = actionStringField(api ?? {}, "path") ?? "/api/v2/db/query";
19550
19954
  const apiMethod = actionStringField(api ?? {}, "method") ?? "POST";
19551
19955
  if (!datasetPath) {
@@ -19614,11 +20018,11 @@ function sqlStringLiteral(value) {
19614
20018
  return `'${value.replace(/'/g, "''")}'`;
19615
20019
  }
19616
20020
  function failureAliasFromCellMeta(cellMeta) {
19617
- if (!isRecord7(cellMeta)) {
20021
+ if (!isRecord8(cellMeta)) {
19618
20022
  return null;
19619
20023
  }
19620
20024
  for (const [alias, meta] of Object.entries(cellMeta)) {
19621
- if (!isRecord7(meta)) {
20025
+ if (!isRecord8(meta)) {
19622
20026
  continue;
19623
20027
  }
19624
20028
  const failure = failureCellFromMeta(meta, {});
@@ -20156,7 +20560,7 @@ function exportableSheetRow2(row, sourceRowStart = 0) {
20156
20560
  return fallback;
20157
20561
  }
20158
20562
  function failureCellFromMeta(meta, fallback) {
20159
- if (!isRecord7(meta)) {
20563
+ if (!isRecord8(meta)) {
20160
20564
  return null;
20161
20565
  }
20162
20566
  const status = typeof meta.status === "string" ? meta.status.trim().toLowerCase() : "";
@@ -20176,7 +20580,7 @@ function failureCellFromMeta(meta, fallback) {
20176
20580
  };
20177
20581
  }
20178
20582
  function applyFailureCellMeta(row, cellMeta, fallback) {
20179
- if (!isRecord7(cellMeta)) {
20583
+ if (!isRecord8(cellMeta)) {
20180
20584
  return;
20181
20585
  }
20182
20586
  for (const [field, meta] of Object.entries(cellMeta)) {
@@ -20420,7 +20824,7 @@ function stableRowSnapshot(value) {
20420
20824
  }
20421
20825
  function cellFailureError(value) {
20422
20826
  const parsed = parseMaybeJsonObject(value);
20423
- if (!isRecord7(parsed)) {
20827
+ if (!isRecord8(parsed)) {
20424
20828
  const text = typeof parsed === "string" ? parsed.trim() : "";
20425
20829
  if (/^(?:[A-Za-z0-9_:-]+:\s*)?(?:Error|TypeError|ReferenceError|SyntaxError|RangeError):\s+/.test(
20426
20830
  text
@@ -20428,12 +20832,12 @@ function cellFailureError(value) {
20428
20832
  return { message: text };
20429
20833
  }
20430
20834
  }
20431
- if (!isRecord7(parsed)) {
20835
+ if (!isRecord8(parsed)) {
20432
20836
  return null;
20433
20837
  }
20434
20838
  const status = typeof parsed.status === "string" ? parsed.status.trim().toLowerCase() : "";
20435
20839
  const directError = typeof parsed.error === "string" ? parsed.error.trim() : typeof parsed.last_error === "string" ? parsed.last_error.trim() : "";
20436
- const result = isRecord7(parsed.result) ? parsed.result : null;
20840
+ const result = isRecord8(parsed.result) ? parsed.result : null;
20437
20841
  const resultError = typeof result?.error === "string" ? result.error.trim() : typeof result?.message === "string" ? result.message.trim() : "";
20438
20842
  if (!directError && !resultError && status !== "error" && status !== "failed") {
20439
20843
  return null;
@@ -20503,7 +20907,7 @@ function assignFlattenedFailurePath(target, field, value) {
20503
20907
  let cursor = target;
20504
20908
  for (const part of normalized.slice(0, -1)) {
20505
20909
  const existing = cursor[part];
20506
- if (!isRecord7(existing)) {
20910
+ if (!isRecord8(existing)) {
20507
20911
  const next = {};
20508
20912
  cursor[part] = next;
20509
20913
  cursor = next;
@@ -20667,10 +21071,10 @@ function waterfallExecutionSignal(status, spec) {
20667
21071
  let everyChildStatOnlyConditionSkipped = true;
20668
21072
  const childAliasesWithStats = /* @__PURE__ */ new Set();
20669
21073
  for (const childAlias of childAliases) {
20670
- for (const stat2 of summaries.map((summary) => summary[childAlias]).filter(isRecord7)) {
21074
+ for (const stat2 of summaries.map((summary) => summary[childAlias]).filter(isRecord8)) {
20671
21075
  sawChildStats = true;
20672
21076
  childAliasesWithStats.add(childAlias);
20673
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21077
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20674
21078
  const executedSummary = parseExecutionSummary(
20675
21079
  execution?.["completed:executed"]
20676
21080
  );
@@ -20700,7 +21104,7 @@ function waterfallExecutionSignal(status, spec) {
20700
21104
  }
20701
21105
  function emptyWaterfallStatsEvidence(status, spec) {
20702
21106
  const summaries = collectColumnStats(status);
20703
- const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord7);
21107
+ const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord8);
20704
21108
  for (const stat2 of parentStats) {
20705
21109
  const nonEmpty = parseExecutionSummary(stat2.non_empty);
20706
21110
  if (nonEmpty?.total && nonEmpty.count === 0) {
@@ -20714,7 +21118,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
20714
21118
  let selectedRows = 0;
20715
21119
  let sawStatsForEveryChild = true;
20716
21120
  for (const childAlias of childAliases) {
20717
- const stat2 = summaries.map((summary) => summary[childAlias]).find(isRecord7);
21121
+ const stat2 = summaries.map((summary) => summary[childAlias]).find(isRecord8);
20718
21122
  if (!stat2) {
20719
21123
  sawStatsForEveryChild = false;
20720
21124
  break;
@@ -20723,7 +21127,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
20723
21127
  if ((nonEmpty?.count ?? 0) > 0) {
20724
21128
  return null;
20725
21129
  }
20726
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21130
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20727
21131
  const executed = parseExecutionSummary(execution?.["completed:executed"]);
20728
21132
  const reused = parseExecutionSummary(execution?.["completed:reused"]);
20729
21133
  const skipped = parseExecutionSummary(execution?.["skipped:condition"]);
@@ -20765,11 +21169,11 @@ function collectStatusFailureJobs(input2) {
20765
21169
  const jobs = [];
20766
21170
  aliases.forEach((spec, aliasIndex) => {
20767
21171
  const { alias } = spec;
20768
- const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
21172
+ const stat2 = summaries.map((summary) => summary[alias]).find(isRecord8);
20769
21173
  if (!stat2) {
20770
21174
  return;
20771
21175
  }
20772
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21176
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20773
21177
  const failedCount = Math.min(
20774
21178
  selectedRows,
20775
21179
  Math.max(
@@ -20876,10 +21280,10 @@ function collectColumnStats(status) {
20876
21280
  value.forEach(visit);
20877
21281
  return;
20878
21282
  }
20879
- if (!isRecord7(value)) {
21283
+ if (!isRecord8(value)) {
20880
21284
  return;
20881
21285
  }
20882
- if (isRecord7(value.columnStats)) {
21286
+ if (isRecord8(value.columnStats)) {
20883
21287
  summaries.push(value.columnStats);
20884
21288
  }
20885
21289
  Object.values(value).forEach(visit);
@@ -20891,12 +21295,12 @@ function firstAliasExecutionCounts(input2) {
20891
21295
  const aliases = collectConfigScalarAliasOrder(input2.config);
20892
21296
  const summaries = collectColumnStats(input2.status);
20893
21297
  for (const alias of aliases) {
20894
- const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
21298
+ const stat2 = summaries.map((summary) => summary[alias]).find(isRecord8);
20895
21299
  if (!stat2) continue;
20896
21300
  if (input2.forceAliases.has(normalizeAlias2(alias))) {
20897
21301
  return { executed: input2.selectedRows, reused: 0 };
20898
21302
  }
20899
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21303
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20900
21304
  if (!execution) continue;
20901
21305
  return {
20902
21306
  executed: parseExecutionCount(execution["completed:executed"]),
@@ -20923,14 +21327,14 @@ function rewriteEnrichJsonStatus(input2) {
20923
21327
  if (Array.isArray(value)) {
20924
21328
  return value.map(rewrite);
20925
21329
  }
20926
- if (!isRecord7(value)) {
21330
+ if (!isRecord8(value)) {
20927
21331
  return value;
20928
21332
  }
20929
21333
  const next = {};
20930
21334
  for (const [key, entry] of Object.entries(value)) {
20931
21335
  next[key] = rewrite(entry);
20932
21336
  }
20933
- if (isRecord7(next.progress)) {
21337
+ if (isRecord8(next.progress)) {
20934
21338
  next.progress = {
20935
21339
  ...next.progress,
20936
21340
  ...selectedRows > 0 ? { total: selectedRows } : {},
@@ -20939,8 +21343,8 @@ function rewriteEnrichJsonStatus(input2) {
20939
21343
  ...failedRows > 0 ? { failed: failedRows, pending: 0 } : {}
20940
21344
  };
20941
21345
  }
20942
- if (isRecord7(next.summary)) {
20943
- const rowCounts = isRecord7(next.summary.rowCounts) ? next.summary.rowCounts : null;
21346
+ if (isRecord8(next.summary)) {
21347
+ const rowCounts = isRecord8(next.summary.rowCounts) ? next.summary.rowCounts : null;
20944
21348
  if (failedRows > 0) {
20945
21349
  next.summary = {
20946
21350
  ...next.summary,
@@ -20953,11 +21357,11 @@ function rewriteEnrichJsonStatus(input2) {
20953
21357
  };
20954
21358
  }
20955
21359
  }
20956
- if (isRecord7(next.columnStats) && selectedRows > 0) {
21360
+ if (isRecord8(next.columnStats) && selectedRows > 0) {
20957
21361
  const columnStats = { ...next.columnStats };
20958
21362
  for (const alias of forcedAliases) {
20959
- const stat2 = isRecord7(columnStats[alias]) ? columnStats[alias] : null;
20960
- const execution = isRecord7(stat2?.execution) ? stat2.execution : null;
21363
+ const stat2 = isRecord8(columnStats[alias]) ? columnStats[alias] : null;
21364
+ const execution = isRecord8(stat2?.execution) ? stat2.execution : null;
20961
21365
  if (!stat2 || !execution) continue;
20962
21366
  columnStats[alias] = {
20963
21367
  ...stat2,
@@ -20976,14 +21380,14 @@ function rewriteEnrichJsonStatus(input2) {
20976
21380
  return next;
20977
21381
  };
20978
21382
  const rewritten = rewrite(input2.status);
20979
- if (failedRows === 0 || !isRecord7(rewritten)) {
21383
+ if (failedRows === 0 || !isRecord8(rewritten)) {
20980
21384
  return rewritten;
20981
21385
  }
20982
21386
  const partialStatus = selectedRows > 0 && failedRows < selectedRows ? "partial_success" : "failed";
20983
21387
  return {
20984
21388
  ...rewritten,
20985
21389
  ...rewritten.status === "completed" || rewritten.status === "failed" ? { status: partialStatus } : {},
20986
- ...isRecord7(rewritten.run) && (rewritten.run.status === "completed" || rewritten.run.status === "failed") ? { run: { ...rewritten.run, status: partialStatus } } : {}
21390
+ ...isRecord8(rewritten.run) && (rewritten.run.status === "completed" || rewritten.run.status === "failed") ? { run: { ...rewritten.run, status: partialStatus } } : {}
20987
21391
  };
20988
21392
  }
20989
21393
  function summarizeFailedJobError(value) {
@@ -21595,7 +21999,7 @@ function materializeCsvCellValue(value) {
21595
21999
  return value;
21596
22000
  }
21597
22001
  function compactArrayEnvelopeCompleteValue(value) {
21598
- if (!isRecord7(value) || value.kind !== "array") {
22002
+ if (!isRecord8(value) || value.kind !== "array") {
21599
22003
  return null;
21600
22004
  }
21601
22005
  if (!Array.isArray(value.preview)) {
@@ -21609,7 +22013,7 @@ function compactArrayEnvelopeCompleteValue(value) {
21609
22013
  }
21610
22014
  function disambiguateCompactAiInferencePayload(value) {
21611
22015
  const parsed = parseMaybeJsonObject(value);
21612
- if (!isRecord7(parsed) || !cellFailureError(parsed)) {
22016
+ if (!isRecord8(parsed) || !cellFailureError(parsed)) {
21613
22017
  return value;
21614
22018
  }
21615
22019
  return {
@@ -21618,14 +22022,14 @@ function disambiguateCompactAiInferencePayload(value) {
21618
22022
  };
21619
22023
  }
21620
22024
  function compactAiInferenceCellForCsv(value) {
21621
- if (!isRecord7(value)) {
22025
+ if (!isRecord8(value)) {
21622
22026
  return value;
21623
22027
  }
21624
22028
  const extractedJson = value.extracted_json;
21625
22029
  if (extractedJson !== null && extractedJson !== void 0) {
21626
22030
  return disambiguateCompactAiInferencePayload(extractedJson);
21627
22031
  }
21628
- const result = isRecord7(value.result) ? value.result : null;
22032
+ const result = isRecord8(value.result) ? value.result : null;
21629
22033
  const object = result?.object;
21630
22034
  if (object !== null && object !== void 0) {
21631
22035
  return disambiguateCompactAiInferencePayload(object);
@@ -21642,12 +22046,12 @@ function compactAiInferenceCellForCsv(value) {
21642
22046
  }
21643
22047
  function materializeEnrichAliasCellForCsv(row, alias, options) {
21644
22048
  const direct = row[alias];
21645
- if (isRecord7(direct)) {
22049
+ if (isRecord8(direct)) {
21646
22050
  const completeArray = compactArrayEnvelopeCompleteValue(direct);
21647
22051
  if (completeArray) {
21648
22052
  return materializeCsvCellValue(completeArray);
21649
22053
  }
21650
- if (options?.compactAiCell && direct.status === "completed" && (isRecord7(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
22054
+ if (options?.compactAiCell && direct.status === "completed" && (isRecord8(direct.result) || Object.prototype.hasOwnProperty.call(direct, "extracted_json") || typeof direct.output === "string")) {
21651
22055
  return materializeCsvCellValue(compactAiInferenceCellForCsv(direct));
21652
22056
  }
21653
22057
  if (Object.prototype.hasOwnProperty.call(direct, "matched_result") || Object.prototype.hasOwnProperty.call(direct, "matchedResult") || Object.prototype.hasOwnProperty.call(direct, "result")) {
@@ -21788,11 +22192,11 @@ function normalizeEnrichRowsForCsvExport(rows, config, options) {
21788
22192
  }
21789
22193
  function legacyMetadataFromRow(row) {
21790
22194
  const direct = parseLegacyMetadataCell(row._metadata);
21791
- if (direct && isRecord7(direct.columns)) {
22195
+ if (direct && isRecord8(direct.columns)) {
21792
22196
  return direct;
21793
22197
  }
21794
22198
  const relocated = parseLegacyMetadataCell(row.metadata);
21795
- if (relocated && isRecord7(relocated.columns)) {
22199
+ if (relocated && isRecord8(relocated.columns)) {
21796
22200
  return relocated;
21797
22201
  }
21798
22202
  const flattenedColumns = parseLegacyMetadataCell(row["metadata.columns"]);
@@ -21809,7 +22213,7 @@ function legacyMetadataFromRow(row) {
21809
22213
  }
21810
22214
  function parseLegacyMetadataCell(value) {
21811
22215
  const parsed = parseMaybeJsonObject(value);
21812
- if (isRecord7(parsed)) {
22216
+ if (isRecord8(parsed)) {
21813
22217
  return parsed;
21814
22218
  }
21815
22219
  if (typeof value !== "string") {
@@ -21826,12 +22230,12 @@ function parseLegacyMetadataCell(value) {
21826
22230
  for (const candidate of candidates) {
21827
22231
  try {
21828
22232
  const decoded = JSON.parse(candidate);
21829
- if (isRecord7(decoded)) {
22233
+ if (isRecord8(decoded)) {
21830
22234
  return decoded;
21831
22235
  }
21832
22236
  if (typeof decoded === "string") {
21833
22237
  const nested = JSON.parse(decoded);
21834
- if (isRecord7(nested)) {
22238
+ if (isRecord8(nested)) {
21835
22239
  return nested;
21836
22240
  }
21837
22241
  }
@@ -21841,8 +22245,8 @@ function parseLegacyMetadataCell(value) {
21841
22245
  return null;
21842
22246
  }
21843
22247
  function mergeLegacyMetadataRecords(base, enriched) {
21844
- const baseColumns = isRecord7(base.columns) ? base.columns : null;
21845
- const enrichedColumns = isRecord7(enriched.columns) ? enriched.columns : null;
22248
+ const baseColumns = isRecord8(base.columns) ? base.columns : null;
22249
+ const enrichedColumns = isRecord8(enriched.columns) ? enriched.columns : null;
21846
22250
  const merged = {
21847
22251
  ...base,
21848
22252
  ...enriched
@@ -22112,11 +22516,15 @@ function registerEnrichCommand(program) {
22112
22516
  const captured2 = await runGeneratedEnrichPlay(client2, runArgs, {
22113
22517
  passthroughStdout: input2.passthroughStdout
22114
22518
  });
22115
- const status2 = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
22519
+ const generatedPlayStatus = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
22116
22520
  client: client2,
22117
22521
  stdout: captured2.stdout,
22118
22522
  exitCode: captured2.result
22119
22523
  });
22524
+ const status2 = rewriteGeneratedPlayRerunForEnrich(
22525
+ generatedPlayStatus,
22526
+ sdkEnrichCommandText(args)
22527
+ );
22120
22528
  const exportResult2 = await maybeWriteOutputCsv({
22121
22529
  outputPath,
22122
22530
  status: status2,
@@ -26350,7 +26758,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
26350
26758
  }
26351
26759
  function extractionContractEntries(entries) {
26352
26760
  return entries.flatMap((entry) => {
26353
- if (!isRecord8(entry)) return [];
26761
+ if (!isRecord9(entry)) return [];
26354
26762
  const name = stringField2(entry, "name");
26355
26763
  const expression = stringField2(entry, "expression");
26356
26764
  return name && expression ? [{ name, expression }] : [];
@@ -26358,8 +26766,8 @@ function extractionContractEntries(entries) {
26358
26766
  }
26359
26767
  function printCompactToolContract(tool, requestedToolId) {
26360
26768
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
26361
- const cost = isRecord8(contract.cost) ? contract.cost : {};
26362
- const getters = isRecord8(contract.getters) ? contract.getters : {};
26769
+ const cost = isRecord9(contract.cost) ? contract.cost : {};
26770
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
26363
26771
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
26364
26772
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
26365
26773
  const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
@@ -26376,7 +26784,7 @@ function printCompactToolContract(tool, requestedToolId) {
26376
26784
  console.log("");
26377
26785
  console.log("Inputs:");
26378
26786
  for (const field of inputFields) {
26379
- if (!isRecord8(field)) continue;
26787
+ if (!isRecord9(field)) continue;
26380
26788
  const name = stringField2(field, "name");
26381
26789
  if (!name) continue;
26382
26790
  const required = field.required ? "*" : "";
@@ -26389,7 +26797,7 @@ function printCompactToolContract(tool, requestedToolId) {
26389
26797
  }
26390
26798
  console.log("");
26391
26799
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
26392
- const starterScript = isRecord8(contract.starterScript) ? contract.starterScript : {};
26800
+ const starterScript = isRecord9(contract.starterScript) ? contract.starterScript : {};
26393
26801
  const starterPath = stringField2(starterScript, "path");
26394
26802
  if (starterPath) {
26395
26803
  console.log("");
@@ -26403,14 +26811,14 @@ function printCompactToolContract(tool, requestedToolId) {
26403
26811
  console.log("Getters:");
26404
26812
  if (listGetters.length) console.log("Lists:");
26405
26813
  for (const entry of listGetters) {
26406
- if (isRecord8(entry))
26814
+ if (isRecord9(entry))
26407
26815
  console.log(
26408
26816
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26409
26817
  );
26410
26818
  }
26411
26819
  if (valueGetters.length) console.log("Values:");
26412
26820
  for (const entry of valueGetters) {
26413
- if (isRecord8(entry))
26821
+ if (isRecord9(entry))
26414
26822
  console.log(
26415
26823
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26416
26824
  );
@@ -26423,7 +26831,7 @@ function printCompactToolContract(tool, requestedToolId) {
26423
26831
  }
26424
26832
  function printToolPricingOnly(tool, requestedToolId, options = {}) {
26425
26833
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
26426
- const cost = isRecord8(contract.cost) ? contract.cost : {};
26834
+ const cost = isRecord9(contract.cost) ? contract.cost : {};
26427
26835
  const pricingModel = stringField2(cost, "pricingModel") || "unknown";
26428
26836
  const billingMode = stringField2(cost, "billingMode") || "unknown";
26429
26837
  const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : pricingModel === "fixed" ? "call" : pricingModel.replace(/^per_/, "") || "unit";
@@ -26443,7 +26851,7 @@ function printToolSchemaOnly(tool, requestedToolId) {
26443
26851
  }
26444
26852
  console.log("Inputs:");
26445
26853
  for (const field of inputFields) {
26446
- if (!isRecord8(field)) continue;
26854
+ if (!isRecord9(field)) continue;
26447
26855
  const name = stringField2(field, "name");
26448
26856
  if (!name) continue;
26449
26857
  const required = field.required ? "*" : "";
@@ -26473,10 +26881,10 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
26473
26881
  ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
26474
26882
  );
26475
26883
  console.log("});");
26476
- const getters = isRecord8(contract.getters) ? contract.getters : {};
26884
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
26477
26885
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
26478
26886
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
26479
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord8);
26887
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord9);
26480
26888
  if (firstGetter) {
26481
26889
  const name = stringField2(firstGetter, "name") || "value";
26482
26890
  const expression = stringField2(firstGetter, "expression");
@@ -26512,7 +26920,7 @@ function printPlayLikeToolUsage(tool, requestedToolId) {
26512
26920
  }
26513
26921
  function printToolGettersOnly(tool, requestedToolId) {
26514
26922
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
26515
- const getters = isRecord8(contract.getters) ? contract.getters : {};
26923
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
26516
26924
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
26517
26925
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
26518
26926
  console.log(`Getters: ${contract.toolId}`);
@@ -26525,7 +26933,7 @@ function printToolGettersOnly(tool, requestedToolId) {
26525
26933
  if (listGetters.length) {
26526
26934
  console.log("Lists:");
26527
26935
  for (const entry of listGetters) {
26528
- if (isRecord8(entry))
26936
+ if (isRecord9(entry))
26529
26937
  console.log(
26530
26938
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26531
26939
  );
@@ -26534,7 +26942,7 @@ function printToolGettersOnly(tool, requestedToolId) {
26534
26942
  if (valueGetters.length) {
26535
26943
  console.log("Values:");
26536
26944
  for (const entry of valueGetters) {
26537
- if (isRecord8(entry))
26945
+ if (isRecord9(entry))
26538
26946
  console.log(
26539
26947
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26540
26948
  );
@@ -26560,7 +26968,7 @@ function sampleValueForField(field) {
26560
26968
  function samplePayloadForInputFields(fields) {
26561
26969
  return Object.fromEntries(
26562
26970
  fields.slice(0, 4).flatMap((field) => {
26563
- if (!isRecord8(field)) return [];
26971
+ if (!isRecord9(field)) return [];
26564
26972
  const name = stringField2(field, "name");
26565
26973
  if (!name) return [];
26566
26974
  return [[name, sampleValueForField(field)]];
@@ -26678,12 +27086,12 @@ function formatListedToolCost(tool) {
26678
27086
  }
26679
27087
  function toolInputFieldsForDisplay(inputSchema) {
26680
27088
  if (Array.isArray(inputSchema.fields))
26681
- return inputSchema.fields.filter(isRecord8);
26682
- const jsonSchema = isRecord8(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
26683
- const properties = isRecord8(jsonSchema.properties) ? jsonSchema.properties : {};
27089
+ return inputSchema.fields.filter(isRecord9);
27090
+ const jsonSchema = isRecord9(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
27091
+ const properties = isRecord9(jsonSchema.properties) ? jsonSchema.properties : {};
26684
27092
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
26685
27093
  return Object.entries(properties).map(([name, value]) => {
26686
- const property = isRecord8(value) ? value : {};
27094
+ const property = isRecord9(value) ? value : {};
26687
27095
  return {
26688
27096
  name,
26689
27097
  type: typeof property.type === "string" ? property.type : "unknown",
@@ -26712,15 +27120,15 @@ function printJsonPreview(label, payload) {
26712
27120
  }
26713
27121
  function samplePayload(samples, key) {
26714
27122
  const entry = samples[key];
26715
- if (!isRecord8(entry)) return void 0;
27123
+ if (!isRecord9(entry)) return void 0;
26716
27124
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
26717
27125
  }
26718
27126
  function commandEnvelopeFromRawResponse(rawResponse) {
26719
- return isRecord8(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
27127
+ return isRecord9(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
26720
27128
  }
26721
27129
  function listExtractorPathsFromUsageGuidance(tool) {
26722
27130
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
26723
- const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord8(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
27131
+ const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord9(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
26724
27132
  return extractedLists.flatMap((entry) => {
26725
27133
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
26726
27134
  if (!Array.isArray(paths)) return [];
@@ -26736,7 +27144,7 @@ function formatDecimal(value) {
26736
27144
  function formatUsd(value) {
26737
27145
  return `$${formatDecimal(value)}`;
26738
27146
  }
26739
- function isRecord8(value) {
27147
+ function isRecord9(value) {
26740
27148
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
26741
27149
  }
26742
27150
  function stringField2(source, ...keys) {
@@ -26763,7 +27171,7 @@ function arrayField2(source, ...keys) {
26763
27171
  function recordField2(source, ...keys) {
26764
27172
  for (const key of keys) {
26765
27173
  const value = source[key];
26766
- if (isRecord8(value)) return value;
27174
+ if (isRecord9(value)) return value;
26767
27175
  }
26768
27176
  return {};
26769
27177
  }
@@ -26829,7 +27237,7 @@ function parseJsonObjectArgument(raw, flagName) {
26829
27237
  }
26830
27238
  throw invalidJsonError(flagName, message);
26831
27239
  }
26832
- if (!isRecord8(parsed)) {
27240
+ if (!isRecord9(parsed)) {
26833
27241
  throw invalidJsonError(flagName, "expected an object.");
26834
27242
  }
26835
27243
  return parsed;
@@ -26975,7 +27383,7 @@ function buildToolExecuteBaseEnvelope(input2) {
26975
27383
  kind: summaryEntries.length > 0 ? "object" : "raw",
26976
27384
  summary: input2.summary
26977
27385
  };
26978
- const envelopeHasCanonicalOutput = isRecord8(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
27386
+ const envelopeHasCanonicalOutput = isRecord9(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
26979
27387
  const envelopeHasDeclaredOutput = Object.prototype.hasOwnProperty.call(
26980
27388
  envelope,
26981
27389
  "output"
@@ -27194,7 +27602,7 @@ async function executeTool(args) {
27194
27602
  {
27195
27603
  ...baseEnvelope,
27196
27604
  local: {
27197
- ...isRecord8(baseEnvelope.local) ? baseEnvelope.local : {},
27605
+ ...isRecord9(baseEnvelope.local) ? baseEnvelope.local : {},
27198
27606
  payload_file: jsonPath
27199
27607
  }
27200
27608
  },