deepline 0.1.210 → 0.1.212

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 (40) hide show
  1. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +203 -12
  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/map-chunk-plan.ts +15 -0
  4. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-latency-profile.ts +90 -0
  5. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-dispatch.ts +162 -100
  6. package/dist/bundling-sources/sdk/src/client.ts +118 -3
  7. package/dist/bundling-sources/sdk/src/play.ts +2 -0
  8. package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +1 -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 +253 -30
  12. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +365 -103
  13. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +12 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/dataset-id.ts +10 -4
  15. package/dist/bundling-sources/shared_libs/play-runtime/db-session.ts +9 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +45 -8
  17. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +14 -2
  18. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +4 -2
  19. package/dist/bundling-sources/shared_libs/play-runtime/receipt-sql.ts +21 -1
  20. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +128 -6
  21. package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +7 -0
  22. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +5 -1
  23. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +37 -5
  24. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +19 -10
  25. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +63 -7
  26. package/dist/bundling-sources/shared_libs/play-runtime/secret-capability.ts +18 -4
  27. package/dist/bundling-sources/shared_libs/play-runtime/single-flight.ts +31 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +12 -1
  29. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +29 -9
  30. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-state-machine.ts +22 -1
  31. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +79 -1
  32. package/dist/bundling-sources/shared_libs/plays/dataset.ts +41 -5
  33. package/dist/cli/index.js +728 -239
  34. package/dist/cli/index.mjs +728 -239
  35. package/dist/index.d.mts +93 -7
  36. package/dist/index.d.ts +93 -7
  37. package/dist/index.js +245 -46
  38. package/dist/index.mjs +245 -46
  39. package/dist/plays/bundle-play-file.mjs +65 -4
  40. 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.210",
611
+ version: "0.1.212",
612
612
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
613
613
  supportPolicy: {
614
- latest: "0.1.210",
614
+ latest: "0.1.212",
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)) {
7447
- continue;
7448
- }
7449
- const output2 = step.output;
7450
- if (!isPackagedDatasetOutput(output2)) {
7627
+ for (const output2 of datasets) {
7628
+ if (!isRecord5(output2) || !isPackagedDatasetOutput(output2)) {
7451
7629
  continue;
7452
7630
  }
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
  }
@@ -10855,7 +11033,8 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
10855
11033
  "--logs",
10856
11034
  "--full",
10857
11035
  "--force",
10858
- "--no-open"
11036
+ "--no-open",
11037
+ "--debug-map-latency"
10859
11038
  ]);
10860
11039
  function traceCliSync(phase, fields, run) {
10861
11040
  const startedAt = Date.now();
@@ -12443,6 +12622,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12443
12622
  let timedOut = false;
12444
12623
  let emittedDashboardUrl = false;
12445
12624
  let lastKnownWorkflowId = "";
12625
+ let launchedRevisionId = input2.request.revisionId?.trim() || null;
12446
12626
  let eventCount = 0;
12447
12627
  let firstRunIdMs = null;
12448
12628
  let lastPhase = null;
@@ -12468,13 +12648,24 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12468
12648
  }
12469
12649
  throw error;
12470
12650
  }
12471
- 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;
12472
12656
  };
12473
12657
  try {
12474
12658
  for await (const event of input2.client.startPlayRunStream(input2.request, {
12475
12659
  signal: controller.signal
12476
12660
  })) {
12477
12661
  eventCount += 1;
12662
+ const eventRevisionId = getStringField(
12663
+ getEventPayload(event),
12664
+ "revisionId"
12665
+ );
12666
+ if (eventRevisionId) {
12667
+ launchedRevisionId = eventRevisionId;
12668
+ }
12478
12669
  const eventRunId = getRunIdFromLiveEvent(event);
12479
12670
  if (typeof eventRunId === "string" && eventRunId && eventRunId !== "pending") {
12480
12671
  lastKnownWorkflowId = eventRunId;
@@ -12551,7 +12742,11 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12551
12742
  const finalStatus = getFinalStatusFromLiveEvent(event);
12552
12743
  if (finalStatus) {
12553
12744
  lastKnownWorkflowId ||= finalStatus.runId ?? "";
12554
- 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
+ };
12555
12750
  if (!canonicalTerminal) {
12556
12751
  recordCliTrace({
12557
12752
  phase: "cli.play_start_stream_stale_terminal_ignored",
@@ -12923,6 +13118,10 @@ function buildRunNextCommands(status) {
12923
13118
  stop: `deepline runs stop ${runId} --reason "stale lock" --json`,
12924
13119
  logs: `deepline runs logs ${runId} --out run.log --json`
12925
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
+ }
12926
13125
  if (status.dashboardUrl) {
12927
13126
  commands.open = `Open ${status.dashboardUrl} to see results.`;
12928
13127
  }
@@ -13074,7 +13273,7 @@ function buildInsufficientCreditsSummaryLines(input2) {
13074
13273
  const lines = [
13075
13274
  " status: stopped_insufficient_credits",
13076
13275
  completed === null ? " completed rows: unknown" : ` completed rows: ${formatInteger(completed)}${total !== null ? ` of ${formatInteger(total)}` : ""}`,
13077
- " 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"
13078
13277
  ];
13079
13278
  const billingUrl = getStringField(input2.billing, "billing_url");
13080
13279
  const recommended = formatCreditAmount(
@@ -13274,15 +13473,44 @@ function withTerminalPlayIdentity(status, playName) {
13274
13473
  function compactPlayStatus(status) {
13275
13474
  const packaged = getPlayRunPackage(status);
13276
13475
  if (packaged) {
13277
- 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;
13278
13480
  if (!error2) {
13279
- 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;
13280
13492
  }
13281
- const run = packaged.run && typeof packaged.run === "object" ? packaged.run : null;
13493
+ const run = packagedRun;
13282
13494
  return {
13283
13495
  ...packaged,
13284
- error: error2,
13285
- ...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 } } : {}
13286
13514
  };
13287
13515
  }
13288
13516
  const rowsInfo = extractCanonicalRowsInfo(status);
@@ -13305,6 +13533,7 @@ function compactPlayStatus(status) {
13305
13533
  steps: normalizeStepsForEnvelope(status),
13306
13534
  errors: normalizeErrorsForEnvelope(status, error),
13307
13535
  logs: normalizeLogsForEnvelope(status),
13536
+ ...status.failedLogs ? { failedLogs: status.failedLogs } : {},
13308
13537
  ...displayError ? { error: displayError } : {},
13309
13538
  ...warnings.length > 0 ? { warnings } : {},
13310
13539
  ...result !== void 0 ? { result: defaultResultForEnvelope(result) } : {},
@@ -13312,6 +13541,16 @@ function compactPlayStatus(status) {
13312
13541
  next: buildRunNextCommands(status)
13313
13542
  };
13314
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
+ }
13315
13554
  function readRunPackageRun(packaged) {
13316
13555
  return packaged.run && typeof packaged.run === "object" && !Array.isArray(packaged.run) ? packaged.run : {};
13317
13556
  }
@@ -13431,6 +13670,14 @@ function actionToCommand(action) {
13431
13670
  record.datasetPath
13432
13671
  )} --out ${shellSingleQuote(`${record.datasetPath.split(".").pop() || "dataset"}.csv`)}`;
13433
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
+ }
13434
13681
  if (record.kind === "deepline_db_query" && typeof record.sql === "string") {
13435
13682
  const maxRows = typeof record.maxRows === "number" && Number.isFinite(record.maxRows) ? Math.trunc(record.maxRows) : 20;
13436
13683
  return `deepline db query --sql ${shellSingleQuote(record.sql)} --max-rows ${maxRows} --json`;
@@ -13438,6 +13685,10 @@ function actionToCommand(action) {
13438
13685
  return null;
13439
13686
  }
13440
13687
  function readFirstDatasetActions(packaged) {
13688
+ for (const dataset of readRecordArray(packaged.datasets)) {
13689
+ const actions = readRecord(dataset.actions);
13690
+ if (actions) return actions;
13691
+ }
13441
13692
  for (const step of readRecordArray(packaged.steps)) {
13442
13693
  const output2 = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
13443
13694
  const actions = output2?.actions && typeof output2.actions === "object" && !Array.isArray(output2.actions) ? output2.actions : null;
@@ -13487,13 +13738,34 @@ function buildRunPackageTextLines(packaged) {
13487
13738
  if (runError && (status === "failed" || status === "cancelled")) {
13488
13739
  lines.push(` error: ${truncateErrorForDisplay(runError, runId)}`);
13489
13740
  }
13490
- for (const step of readRecordArray(packaged.steps)) {
13491
- const output2 = step.output && typeof step.output === "object" && !Array.isArray(step.output) ? step.output : null;
13492
- 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;
13493
13765
  const rowCount = typeof output2.rowCount === "number" ? formatInteger(output2.rowCount) : "persisted";
13494
13766
  const datasetPath = typeof output2.path === "string" ? output2.path : "dataset";
13495
13767
  lines.push(
13496
- ` 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`
13497
13769
  );
13498
13770
  }
13499
13771
  if (playName) {
@@ -13502,6 +13774,7 @@ function buildRunPackageTextLines(packaged) {
13502
13774
  lines.push(...formatPackageValueOutputLines(packaged));
13503
13775
  const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
13504
13776
  const billingCommand = actionToCommand(next.billing);
13777
+ const logsCommand = actionToCommand(next.logs);
13505
13778
  if (billingCommand) {
13506
13779
  const costState = status === "completed" || status === "failed" || status === "cancelled" ? "settles asynchronously \u2014 run the billing command below for totals" : "pending";
13507
13780
  lines.push(` cost: ${costState}`);
@@ -13526,12 +13799,49 @@ function buildRunPackageTextLines(packaged) {
13526
13799
  const inspectCommand = actionToCommand(next.inspect);
13527
13800
  const queryCommand = actionToCommand(next.query) ?? actionToCommand(datasetActions.query);
13528
13801
  const exportCommand = actionToCommand(next.export) ?? actionToCommand(datasetActions.exportCsv);
13802
+ const runAgainCommand = typeof next.run === "string" && next.run.trim() ? next.run.trim() : null;
13529
13803
  if (inspectCommand) lines.push(` inspect: ${inspectCommand}`);
13804
+ if (logsCommand) lines.push(` logs: ${logsCommand}`);
13530
13805
  if (billingCommand) lines.push(` billing: ${billingCommand}`);
13531
13806
  if (queryCommand) lines.push(` query: ${queryCommand}`);
13532
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
+ }
13533
13812
  return lines;
13534
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
+ }
13535
13845
  function writePlayResult(status, jsonOutput, options) {
13536
13846
  const packaged = getPlayRunPackage(status);
13537
13847
  if (jsonOutput) {
@@ -13541,8 +13851,9 @@ function writePlayResult(status, jsonOutput, options) {
13541
13851
  return;
13542
13852
  }
13543
13853
  if (packaged && !options?.fullJson) {
13544
- const lines2 = buildRunPackageTextLines(packaged);
13545
- printCommandEnvelope(packaged, {
13854
+ const displayPackage = compactPlayStatus(status);
13855
+ const lines2 = buildRunPackageTextLines(displayPackage);
13856
+ printCommandEnvelope(displayPackage, {
13546
13857
  json: false,
13547
13858
  text: `${lines2.join("\n")}
13548
13859
  `
@@ -13569,6 +13880,21 @@ function writePlayResult(status, jsonOutput, options) {
13569
13880
  const displayError = formatPlayErrorForDisplay(status, progressError) ?? progressError;
13570
13881
  lines.push(` error: ${truncateErrorForDisplay(displayError, runId)}`);
13571
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
+ }
13572
13898
  const renderedServerView = renderServerResultView(status.resultView);
13573
13899
  if (result) {
13574
13900
  lines.push(...formatReturnValue(result));
@@ -13611,20 +13937,27 @@ async function resolvePlayRunOutputStatus(input2) {
13611
13937
  const streamedPackage = getPlayRunPackage(input2.status);
13612
13938
  const refreshForFullJson = input2.fullJson && streamedPackage !== null;
13613
13939
  const streamedTextPackageIncomplete = !input2.jsonOutput && input2.status.status === "completed" && playRunPackageTextLedgerIncomplete(streamedPackage);
13614
- if (!refreshForFullJson && !streamedTextPackageIncomplete) {
13940
+ const refreshFailedTerminal = input2.status.status === "failed";
13941
+ if (!refreshForFullJson && !streamedTextPackageIncomplete && !refreshFailedTerminal) {
13615
13942
  return input2.status;
13616
13943
  }
13617
13944
  let refreshedStatus = await input2.client.getPlayStatus(runId, {
13618
13945
  billing: false,
13619
13946
  full: input2.fullJson
13620
13947
  });
13621
- 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) {
13622
13949
  await sleep5(250);
13623
13950
  refreshedStatus = await input2.client.getPlayStatus(runId, {
13624
13951
  billing: false,
13625
13952
  full: input2.fullJson
13626
13953
  });
13627
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
+ }
13628
13961
  const dashboardUrl = input2.status.dashboardUrl;
13629
13962
  return typeof dashboardUrl === "string" ? { ...refreshedStatus, dashboardUrl } : refreshedStatus;
13630
13963
  }
@@ -13759,37 +14092,16 @@ function resolveDatasetByName(available, datasetPath) {
13759
14092
  if (exact) {
13760
14093
  return exact;
13761
14094
  }
14095
+ const byDatasetId = available.find((info) => info.datasetId === target);
14096
+ if (byDatasetId) {
14097
+ return byDatasetId;
14098
+ }
13762
14099
  const byNamespace = available.find(
13763
14100
  (info) => info.tableNamespace && info.tableNamespace === target
13764
14101
  );
13765
14102
  if (byNamespace) {
13766
14103
  return byNamespace;
13767
14104
  }
13768
- const trailing = target.split(".").filter(Boolean).at(-1);
13769
- if (!trailing) {
13770
- return null;
13771
- }
13772
- const byTrailing = available.find(
13773
- (info) => info.tableNamespace === trailing || typeof info.source === "string" && info.source.split(".").filter(Boolean).at(-1) === trailing
13774
- );
13775
- if (byTrailing) {
13776
- return byTrailing;
13777
- }
13778
- if (target.split(".").filter(Boolean)[0] === "result") {
13779
- const recovered = available.filter((info) => info.recovered);
13780
- if (recovered.length === 1) {
13781
- return recovered[0];
13782
- }
13783
- if (recovered.length > 1) {
13784
- const names = recovered.map((info) => info.tableNamespace ?? info.source).filter((name) => typeof name === "string");
13785
- throw new DeeplineError(
13786
- `Run returned multiple recovered datasets; '${target}' is ambiguous. Choose one with --dataset <path>: ${names.join(", ")}.`,
13787
- void 0,
13788
- "RUN_EXPORT_DATASET_AMBIGUOUS",
13789
- { dataset: target, available: names }
13790
- );
13791
- }
13792
- }
13793
14105
  return null;
13794
14106
  }
13795
14107
  function assertDatasetHasExportableRows(input2) {
@@ -13969,7 +14281,7 @@ function extractPlayValidationErrors(value) {
13969
14281
  if (value instanceof DeeplineError) {
13970
14282
  return extractPlayValidationErrors(value.details);
13971
14283
  }
13972
- if (!isRecord6(value)) {
14284
+ if (!isRecord7(value)) {
13973
14285
  return [];
13974
14286
  }
13975
14287
  const directErrors = stringArrayField(value, "errors");
@@ -14202,6 +14514,7 @@ function parsePlayRunOptions(args) {
14202
14514
  const emitLogs = !jsonOutput || args.includes("--logs");
14203
14515
  const force = args.includes("--force");
14204
14516
  const noOpen = args.includes("--no-open");
14517
+ const debugMapLatency = args.includes("--debug-map-latency");
14205
14518
  let waitTimeoutMs = null;
14206
14519
  let profile = null;
14207
14520
  for (let index = 0; index < args.length; index += 1) {
@@ -14320,7 +14633,8 @@ function parsePlayRunOptions(args) {
14320
14633
  waitTimeoutMs,
14321
14634
  force,
14322
14635
  noOpen,
14323
- profile
14636
+ profile,
14637
+ debugMapLatency
14324
14638
  };
14325
14639
  }
14326
14640
  function parsePlayCheckOptions(args) {
@@ -14335,7 +14649,7 @@ function shouldUseLocalOnlyPlayCheck() {
14335
14649
  const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
14336
14650
  return value === "1" || value === "true" || value === "yes" || value === "on";
14337
14651
  }
14338
- function isRecord6(value) {
14652
+ function isRecord7(value) {
14339
14653
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
14340
14654
  }
14341
14655
  function stringValue2(value) {
@@ -14345,14 +14659,14 @@ function asArray(value) {
14345
14659
  return Array.isArray(value) ? value : [];
14346
14660
  }
14347
14661
  function extractionEntries2(value) {
14348
- if (Array.isArray(value)) return value.filter(isRecord6);
14349
- if (!isRecord6(value)) return [];
14662
+ if (Array.isArray(value)) return value.filter(isRecord7);
14663
+ if (!isRecord7(value)) return [];
14350
14664
  return Object.entries(value).map(
14351
- ([name, entry]) => isRecord6(entry) ? { name, ...entry } : { name }
14665
+ ([name, entry]) => isRecord7(entry) ? { name, ...entry } : { name }
14352
14666
  );
14353
14667
  }
14354
14668
  function firstRawPath(entry) {
14355
- const details = isRecord6(entry.details) ? entry.details : {};
14669
+ const details = isRecord7(entry.details) ? entry.details : {};
14356
14670
  const paths = [
14357
14671
  ...asArray(details.rawToolOutputPaths),
14358
14672
  ...asArray(details.raw_tool_output_paths),
@@ -14370,12 +14684,12 @@ function checkHintRawPath(value) {
14370
14684
  function collectStaticPipelineToolIds(staticPipeline) {
14371
14685
  const seen = /* @__PURE__ */ new Set();
14372
14686
  const visitPipeline = (pipeline) => {
14373
- if (!isRecord6(pipeline)) return;
14687
+ if (!isRecord7(pipeline)) return;
14374
14688
  for (const step of [
14375
14689
  ...asArray(pipeline.stages),
14376
14690
  ...asArray(pipeline.substeps)
14377
14691
  ]) {
14378
- if (!isRecord6(step)) continue;
14692
+ if (!isRecord7(step)) continue;
14379
14693
  if (step.type === "tool") {
14380
14694
  const toolId = stringValue2(step.toolId) || stringValue2(step.tool);
14381
14695
  if (toolId) seen.add(toolId);
@@ -14389,9 +14703,9 @@ function collectStaticPipelineToolIds(staticPipeline) {
14389
14703
  return [...seen].sort();
14390
14704
  }
14391
14705
  function toolGetterHintFromMetadata(toolId, tool) {
14392
- const usageGuidance = isRecord6(tool.usageGuidance) ? tool.usageGuidance : {};
14393
- const resultGuidance = isRecord6(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord6(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
14394
- 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 : {};
14395
14709
  const lists = extractionEntries2(
14396
14710
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
14397
14711
  ).map((entry) => ({
@@ -14805,6 +15119,7 @@ async function handleFileBackedRun(options) {
14805
15119
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
14806
15120
  ...options.force ? { force: true } : {},
14807
15121
  ...options.profile ? { profile: options.profile } : {},
15122
+ ...options.debugMapLatency ? { testPolicyOverrides: { mapLatencyProfile: true } } : {},
14808
15123
  ...integrationMode ? { integrationMode } : {}
14809
15124
  };
14810
15125
  if (options.watch) {
@@ -14830,14 +15145,17 @@ async function handleFileBackedRun(options) {
14830
15145
  } else {
14831
15146
  progress.fail();
14832
15147
  }
14833
- const outputStatus = withTerminalPlayIdentity(
14834
- await resolvePlayRunOutputStatus({
14835
- client: client2,
14836
- status: finalStatus,
14837
- fullJson: options.fullJson,
14838
- jsonOutput: options.jsonOutput
14839
- }),
14840
- 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
14841
15159
  );
14842
15160
  traceCliSync(
14843
15161
  "cli.play_write_result",
@@ -14846,7 +15164,7 @@ async function handleFileBackedRun(options) {
14846
15164
  fullJson: options.fullJson
14847
15165
  })
14848
15166
  );
14849
- return finalStatus.status === "completed" ? 0 : 1;
15167
+ return outputStatus.status === "completed" ? 0 : 1;
14850
15168
  }
14851
15169
  progress.phase("starting run");
14852
15170
  const started = await traceCliSpan(
@@ -14966,6 +15284,7 @@ async function handleNamedRun(options) {
14966
15284
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
14967
15285
  ...options.force ? { force: true } : {},
14968
15286
  ...options.profile ? { profile: options.profile } : {},
15287
+ ...options.debugMapLatency ? { testPolicyOverrides: { mapLatencyProfile: true } } : {},
14969
15288
  ...integrationMode ? { integrationMode } : {}
14970
15289
  };
14971
15290
  if (options.watch) {
@@ -14993,14 +15312,18 @@ async function handleNamedRun(options) {
14993
15312
  } else {
14994
15313
  progress.fail();
14995
15314
  }
14996
- const outputStatus = withTerminalPlayIdentity(
14997
- await resolvePlayRunOutputStatus({
14998
- client: client2,
14999
- status: finalStatus,
15000
- fullJson: options.fullJson,
15001
- jsonOutput: options.jsonOutput
15002
- }),
15003
- 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
15004
15327
  );
15005
15328
  traceCliSync(
15006
15329
  "cli.play_write_result",
@@ -15009,7 +15332,7 @@ async function handleNamedRun(options) {
15009
15332
  fullJson: options.fullJson
15010
15333
  })
15011
15334
  );
15012
- return finalStatus.status === "completed" ? 0 : 1;
15335
+ return outputStatus.status === "completed" ? 0 : 1;
15013
15336
  }
15014
15337
  progress.phase("starting run");
15015
15338
  const started = await traceCliSpan(
@@ -15070,7 +15393,7 @@ async function handlePlayRun(args) {
15070
15393
  function parseRunIdPositional(args, usage) {
15071
15394
  for (let index = 0; index < args.length; index += 1) {
15072
15395
  const arg = args[index];
15073
- 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") {
15074
15397
  if (arg === "--limit" && args[index + 1]) {
15075
15398
  index += 1;
15076
15399
  }
@@ -15087,7 +15410,7 @@ function parseRunIdPositional(args, usage) {
15087
15410
  throw new DeeplineError(usage);
15088
15411
  }
15089
15412
  async function handleRunGet(args) {
15090
- const usage = "Usage: deepline runs get <run-id> [--json] [--full]";
15413
+ const usage = "Usage: deepline runs get <run-id> [--json] [--full] [--log-failed]";
15091
15414
  let runId;
15092
15415
  try {
15093
15416
  runId = parseRunIdPositional(args, usage);
@@ -15097,7 +15420,8 @@ async function handleRunGet(args) {
15097
15420
  }
15098
15421
  const client2 = new DeeplineClient();
15099
15422
  const status = await client2.runs.get(runId, {
15100
- full: args.includes("--full")
15423
+ full: args.includes("--full"),
15424
+ failedLogs: args.includes("--log-failed")
15101
15425
  });
15102
15426
  writePlayResult(status, argsWantJson(args), {
15103
15427
  fullJson: args.includes("--full")
@@ -15186,7 +15510,37 @@ async function handleRunTail(args) {
15186
15510
  }
15187
15511
  const client2 = new DeeplineClient();
15188
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
+ };
15189
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,
15190
15544
  // Human mode only: in --json mode emit nothing non-protocol.
15191
15545
  onReconnect: jsonOutput ? void 0 : ({ reason }) => {
15192
15546
  process.stderr.write(
@@ -15199,7 +15553,7 @@ async function handleRunTail(args) {
15199
15553
  return status.status === "failed" ? 1 : 0;
15200
15554
  }
15201
15555
  async function handleRunLogs(args) {
15202
- 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]";
15203
15557
  let runId;
15204
15558
  try {
15205
15559
  runId = parseRunIdPositional(args, usage);
@@ -15209,6 +15563,7 @@ async function handleRunLogs(args) {
15209
15563
  }
15210
15564
  let limit = 200;
15211
15565
  let outPath = null;
15566
+ const failed = args.includes("--failed");
15212
15567
  for (let index = 0; index < args.length; index += 1) {
15213
15568
  const arg = args[index];
15214
15569
  if (arg === "--limit" && args[index + 1]) {
@@ -15219,6 +15574,12 @@ async function handleRunLogs(args) {
15219
15574
  outPath = resolve8(args[++index]);
15220
15575
  }
15221
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
+ }
15222
15583
  const client2 = new DeeplineClient();
15223
15584
  if (outPath) {
15224
15585
  const result2 = await client2.runs.logs(runId, { all: true });
@@ -15250,7 +15611,8 @@ async function handleRunLogs(args) {
15250
15611
  );
15251
15612
  return 0;
15252
15613
  }
15253
- const result = await client2.runs.logs(runId, { limit });
15614
+ const result = await client2.runs.logs(runId, { limit, failed });
15615
+ const text = buildRunLogsText(result);
15254
15616
  printCommandEnvelope(
15255
15617
  {
15256
15618
  runId: result.runId,
@@ -15262,18 +15624,33 @@ async function handleRunLogs(args) {
15262
15624
  hasMore: result.hasMore,
15263
15625
  ...result.logsTruncated ? { logsTruncated: true } : {},
15264
15626
  entries: result.entries,
15627
+ ...result.view ? { view: result.view } : {},
15628
+ ...result.association ? { association: result.association } : {},
15629
+ ...result.warning ? { warning: result.warning } : {},
15265
15630
  next: {
15631
+ ...result.next ?? {},
15266
15632
  export: `deepline runs logs ${result.runId} --out run.log --json`
15267
15633
  },
15268
15634
  render: { sections: [{ title: "run logs", lines: result.entries }] }
15269
15635
  },
15270
15636
  {
15271
15637
  json: argsWantJson(args),
15272
- text: `${result.entries.join("\n")}${result.entries.length > 0 ? "\n" : ""}`
15638
+ text
15273
15639
  }
15274
15640
  );
15275
15641
  return 0;
15276
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
+ }
15277
15654
  async function handleRunStop(args) {
15278
15655
  const usage = 'Usage: deepline runs stop <run-id> [--reason "text"] [--json]';
15279
15656
  let runId;
@@ -16172,8 +16549,8 @@ Idempotent execution:
16172
16549
 
16173
16550
  await ctx.tools.execute({ id: 'company_lookup', tool, input });
16174
16551
 
16175
- The authored id is still required for readable logs, metadata, and receipt
16176
- 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.
16177
16554
 
16178
16555
  For rows, use ctx.dataset plus a stable row key:
16179
16556
 
@@ -16214,7 +16591,10 @@ Examples:
16214
16591
  ).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
16215
16592
  "--logs",
16216
16593
  "When output is non-interactive, stream play logs to stderr while waiting"
16217
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
16594
+ ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
16595
+ "--debug-map-latency",
16596
+ "Internal diagnostics: emit one aggregate latency profile per dataset map"
16597
+ ).option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
16218
16598
  "afterAll",
16219
16599
  `
16220
16600
  Pass-through input flags:
@@ -16250,6 +16630,7 @@ Pass-through input flags:
16250
16630
  ...options.logs ? ["--logs"] : [],
16251
16631
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
16252
16632
  ...options.force ? ["--force"] : [],
16633
+ ...options.debugMapLatency ? ["--debug-map-latency"] : [],
16253
16634
  ...options.noOpen || options.open === false ? ["--no-open"] : [],
16254
16635
  ...options.json ? ["--json"] : [],
16255
16636
  ...options.full ? ["--full"] : [],
@@ -16478,13 +16859,18 @@ Notes:
16478
16859
  Examples:
16479
16860
  deepline runs get play/my-play/run/20260501t000000-000
16480
16861
  deepline runs get play/my-play/run/20260501t000000-000 --json
16862
+ deepline runs get play/my-play/run/20260501t000000-000 --log-failed --json
16481
16863
  deepline runs get play/my-play/run/20260501t000000-000 --full --json
16482
16864
  `
16483
- ).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) => {
16484
16869
  process.exitCode = await handleRunGet([
16485
16870
  runId,
16486
16871
  ...options.json ? ["--json"] : [],
16487
- ...options.full ? ["--full"] : []
16872
+ ...options.full ? ["--full"] : [],
16873
+ ...options.logFailed ? ["--log-failed"] : []
16488
16874
  ]);
16489
16875
  });
16490
16876
  runs.command("list").description("List play runs.").addHelpText(
@@ -16528,13 +16914,17 @@ Examples:
16528
16914
  `
16529
16915
  Notes:
16530
16916
  Streams live run events until the stream ends. Use get for current status and
16531
- 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.
16532
16919
 
16533
16920
  Examples:
16534
16921
  deepline runs tail play/my-play/run/20260501t000000-000
16535
16922
  deepline runs tail play/my-play/run/20260501t000000-000 --compact --json
16536
16923
  `
16537
- ).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) => {
16538
16928
  process.exitCode = await handleRunTail([
16539
16929
  runId,
16540
16930
  ...options.json ? ["--json"] : [],
@@ -16551,17 +16941,19 @@ Notes:
16551
16941
  Examples:
16552
16942
  deepline runs logs play/my-play/run/20260501t000000-000
16553
16943
  deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
16944
+ deepline runs logs play/my-play/run/20260501t000000-000 --failed --json
16554
16945
  deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
16555
16946
  `
16556
16947
  ).option(
16557
16948
  "--limit <count>",
16558
16949
  "Maximum recent log lines to print without --out",
16559
16950
  "200"
16560
- ).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) => {
16561
16952
  process.exitCode = await handleRunLogs([
16562
16953
  runId,
16563
16954
  ...options.limit ? ["--limit", options.limit] : [],
16564
16955
  ...options.out ? ["--out", options.out] : [],
16956
+ ...options.failed ? ["--failed"] : [],
16565
16957
  ...options.json ? ["--json"] : []
16566
16958
  ]);
16567
16959
  });
@@ -17299,6 +17691,8 @@ function renderPlayStep(command, options) {
17299
17691
  ` const __dlRunIf = ${runIfJs};`,
17300
17692
  ` if (!__dlRunIf(templateRow)) return null;`
17301
17693
  ] : [];
17694
+ const inline = command.play?.inline;
17695
+ const inlineHandler = inline ? `__dlInlinePlay_${inline.sourceHash.slice(0, 16)}` : null;
17302
17696
  return [
17303
17697
  `async (row, stepCtx) => {`,
17304
17698
  ...options.precheck ? [` if (${options.precheck}) return null;`] : [],
@@ -17308,9 +17702,16 @@ function renderPlayStep(command, options) {
17308
17702
  ` if (__dlShouldSkipBlankPlayPayload(payload)) return null;`,
17309
17703
  ` let result: unknown;`,
17310
17704
  ` try {`,
17311
- ` result = await stepCtx.runPlay(${callId}, ${playRef}, payload, {`,
17312
- ` description: ${stringLiteral(command.description ?? command.alias)}`,
17313
- ` });`,
17705
+ ...inlineHandler ? [
17706
+ // Enrich validates and normalizes this payload against the certified
17707
+ // prebuilt contract before code generation. The attachment retains
17708
+ // its concrete input type, while generated payloads are records.
17709
+ ` result = await __dlRunInlinePlay(${inlineHandler}, stepCtx, payload as never, ${options.force});`
17710
+ ] : [
17711
+ ` result = await stepCtx.runPlay(${callId}, ${playRef}, payload, {`,
17712
+ ` description: ${stringLiteral(command.description ?? command.alias)}`,
17713
+ ` });`
17714
+ ],
17314
17715
  ` } catch (error) {`,
17315
17716
  ...options.waterfallSoftFail ? [` return __dlWaterfallToolFailure(error);`] : [` throw error;`],
17316
17717
  ` }`,
@@ -17318,6 +17719,19 @@ function renderPlayStep(command, options) {
17318
17719
  `}`
17319
17720
  ].join("\n");
17320
17721
  }
17722
+ function collectInlinePlayHandlers(commands) {
17723
+ const handlers = /* @__PURE__ */ new Map();
17724
+ const visit = (command) => {
17725
+ if (isWaterfall(command)) {
17726
+ command.commands.forEach(visit);
17727
+ return;
17728
+ }
17729
+ const inline = command.play?.inline;
17730
+ if (inline) handlers.set(inline.sourceHash, inline);
17731
+ };
17732
+ commands.forEach(visit);
17733
+ return [...handlers.values()];
17734
+ }
17321
17735
  function renderInlineJavascriptStep(command, options) {
17322
17736
  const alias = stringLiteral(command.alias);
17323
17737
  const extractJs = renderExtractFunction(command, 4);
@@ -17518,6 +17932,10 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
17518
17932
  [...options.forceAliases ?? []].map((alias) => normalizeAlias(alias))
17519
17933
  );
17520
17934
  const columnSteps = [];
17935
+ const inlineHandlers = collectInlinePlayHandlers(config.commands);
17936
+ const inlineTypeImports = [
17937
+ ...new Set(inlineHandlers.flatMap((inline) => inline.typeImports ?? []))
17938
+ ].sort();
17521
17939
  config.commands.forEach((command) => {
17522
17940
  if (isWaterfall(command)) {
17523
17941
  columnSteps.push(
@@ -17555,6 +17973,19 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
17555
17973
  const generatedAliases = collectGeneratedAliases(config.commands);
17556
17974
  const runOptionsSource = options.failFast ? `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart), onRowError: 'fail' as const }` : `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart) }`;
17557
17975
  const body = [
17976
+ `function __dlRunInlinePlay<TContext, TInput, TOutput>(handler: (ctx: TContext, input: TInput) => Promise<TOutput>, scope: TContext, payload: TInput, force: boolean): Promise<TOutput> {`,
17977
+ ` if (!force) return handler(scope, payload);`,
17978
+ ` const runtimeScope = scope as TContext & { __deeplineRunWithForcedTools?: <T>(run: () => Promise<T>) => Promise<T> };`,
17979
+ ` if (typeof runtimeScope.__deeplineRunWithForcedTools !== 'function') {`,
17980
+ ` throw new Error('This runtime does not support forced certified inline play execution.');`,
17981
+ ` }`,
17982
+ ` return runtimeScope.__deeplineRunWithForcedTools(() => handler(scope, payload));`,
17983
+ `}`,
17984
+ ``,
17985
+ ...inlineHandlers.flatMap((inline) => [
17986
+ `const __dlInlinePlay_${inline.sourceHash.slice(0, 16)} = ${inline.functionExpressionSource};`,
17987
+ ``
17988
+ ]),
17558
17989
  `export default definePlay(${stringLiteral(playName)}, async (ctx, input: EnrichInput) => {`,
17559
17990
  ` const sourceRows = await ctx.csv<Record<string, unknown>>(input.file);`,
17560
17991
  ` const rowStart = __dlNonNegativeInteger(input.rowStart, 0);`,
@@ -17579,7 +18010,8 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
17579
18010
  const helpers = idiomaticGetters ? selectUsedHelpers(helperSource(), body.join("\n")) : helperSource();
17580
18011
  return [
17581
18012
  ...inlineRunJavascript && configHasRunJavascript(config) ? ["// @ts-nocheck", "/* eslint-disable */", ""] : [],
17582
- `import { definePlay } from 'deepline';`,
18013
+ `import { definePlay, steps } from 'deepline';`,
18014
+ ...inlineTypeImports.length > 0 ? [`import type { ${inlineTypeImports.join(", ")} } from 'deepline';`] : [],
17583
18015
  ``,
17584
18016
  `type EnrichInput = { file: string; rowStart?: number | null; rowEnd?: number | null };`,
17585
18017
  ``,
@@ -18434,7 +18866,7 @@ function isMarkedTestAiInferenceCommand(command) {
18434
18866
  if (normalizeEnrichPlayRef(command.tool) !== "run_javascript") {
18435
18867
  return false;
18436
18868
  }
18437
- 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;
18438
18870
  }
18439
18871
  function enrichDebugEnabled(env = process.env) {
18440
18872
  const raw = String(env.DEEPLINE_DEBUG_ENRICH ?? "").trim().toLowerCase();
@@ -18693,6 +19125,27 @@ function sdkEnrichCommandText(args) {
18693
19125
  }
18694
19126
  return `${command.slice(0, SDK_ENRICH_TELEMETRY_COMMAND_MAX_LENGTH - 3)}...`;
18695
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
+ }
18696
19149
  function countConfiguredEnrichColumns(config) {
18697
19150
  const count = (commands) => commands.reduce((total, command) => {
18698
19151
  if ("with_waterfall" in command) {
@@ -18794,7 +19247,8 @@ async function buildPlanArgs(args) {
18794
19247
  "--fail-fast",
18795
19248
  "--all",
18796
19249
  "--in-place",
18797
- "--no-open"
19250
+ "--no-open",
19251
+ "--debug-map-latency"
18798
19252
  ]);
18799
19253
  const planArgs = [];
18800
19254
  for (let index = 0; index < args.length; index += 1) {
@@ -19149,7 +19603,7 @@ async function resolveWatchedGeneratedPlayStatus(input2) {
19149
19603
  }
19150
19604
  return input2.client.runs.get(runId, { full: true });
19151
19605
  }
19152
- function isRecord7(value) {
19606
+ function isRecord8(value) {
19153
19607
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
19154
19608
  }
19155
19609
  async function captureStdout(run, options = {}) {
@@ -19436,13 +19890,13 @@ function readFirstEnrichDatasetActions(value) {
19436
19890
  return null;
19437
19891
  }
19438
19892
  const record = candidate;
19439
- const actions = isRecord7(record.actions) ? record.actions : null;
19440
- 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;
19441
19895
  if (query?.kind === "deepline_db_query") {
19442
19896
  return {
19443
19897
  dataset: record,
19444
19898
  query,
19445
- ...isRecord7(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
19899
+ ...isRecord8(actions?.exportCsv) ? { exportCsv: actions.exportCsv } : {}
19446
19900
  };
19447
19901
  }
19448
19902
  if (options.allowLegacy && record.kind === "dataset" && typeof record.queryDatasetCommand === "string" && record.queryDatasetCommand.trim()) {
@@ -19495,7 +19949,7 @@ function enrichCustomerDbJson(input2) {
19495
19949
  const dataset = actions.dataset;
19496
19950
  const sql = actionStringField(query, "sql") ?? parseSqlFromDbQueryCommand(actions.queryDatasetCommand);
19497
19951
  const datasetPath = actionStringField(query, "datasetPath") ?? actionStringField(dataset, "path") ?? actionStringField(dataset, "tableNamespace");
19498
- const api = isRecord7(query.api) ? query.api : null;
19952
+ const api = isRecord8(query.api) ? query.api : null;
19499
19953
  const apiPath = actionStringField(api ?? {}, "path") ?? "/api/v2/db/query";
19500
19954
  const apiMethod = actionStringField(api ?? {}, "method") ?? "POST";
19501
19955
  if (!datasetPath) {
@@ -19564,11 +20018,11 @@ function sqlStringLiteral(value) {
19564
20018
  return `'${value.replace(/'/g, "''")}'`;
19565
20019
  }
19566
20020
  function failureAliasFromCellMeta(cellMeta) {
19567
- if (!isRecord7(cellMeta)) {
20021
+ if (!isRecord8(cellMeta)) {
19568
20022
  return null;
19569
20023
  }
19570
20024
  for (const [alias, meta] of Object.entries(cellMeta)) {
19571
- if (!isRecord7(meta)) {
20025
+ if (!isRecord8(meta)) {
19572
20026
  continue;
19573
20027
  }
19574
20028
  const failure = failureCellFromMeta(meta, {});
@@ -20106,7 +20560,7 @@ function exportableSheetRow2(row, sourceRowStart = 0) {
20106
20560
  return fallback;
20107
20561
  }
20108
20562
  function failureCellFromMeta(meta, fallback) {
20109
- if (!isRecord7(meta)) {
20563
+ if (!isRecord8(meta)) {
20110
20564
  return null;
20111
20565
  }
20112
20566
  const status = typeof meta.status === "string" ? meta.status.trim().toLowerCase() : "";
@@ -20126,7 +20580,7 @@ function failureCellFromMeta(meta, fallback) {
20126
20580
  };
20127
20581
  }
20128
20582
  function applyFailureCellMeta(row, cellMeta, fallback) {
20129
- if (!isRecord7(cellMeta)) {
20583
+ if (!isRecord8(cellMeta)) {
20130
20584
  return;
20131
20585
  }
20132
20586
  for (const [field, meta] of Object.entries(cellMeta)) {
@@ -20370,7 +20824,7 @@ function stableRowSnapshot(value) {
20370
20824
  }
20371
20825
  function cellFailureError(value) {
20372
20826
  const parsed = parseMaybeJsonObject(value);
20373
- if (!isRecord7(parsed)) {
20827
+ if (!isRecord8(parsed)) {
20374
20828
  const text = typeof parsed === "string" ? parsed.trim() : "";
20375
20829
  if (/^(?:[A-Za-z0-9_:-]+:\s*)?(?:Error|TypeError|ReferenceError|SyntaxError|RangeError):\s+/.test(
20376
20830
  text
@@ -20378,12 +20832,12 @@ function cellFailureError(value) {
20378
20832
  return { message: text };
20379
20833
  }
20380
20834
  }
20381
- if (!isRecord7(parsed)) {
20835
+ if (!isRecord8(parsed)) {
20382
20836
  return null;
20383
20837
  }
20384
20838
  const status = typeof parsed.status === "string" ? parsed.status.trim().toLowerCase() : "";
20385
20839
  const directError = typeof parsed.error === "string" ? parsed.error.trim() : typeof parsed.last_error === "string" ? parsed.last_error.trim() : "";
20386
- const result = isRecord7(parsed.result) ? parsed.result : null;
20840
+ const result = isRecord8(parsed.result) ? parsed.result : null;
20387
20841
  const resultError = typeof result?.error === "string" ? result.error.trim() : typeof result?.message === "string" ? result.message.trim() : "";
20388
20842
  if (!directError && !resultError && status !== "error" && status !== "failed") {
20389
20843
  return null;
@@ -20453,7 +20907,7 @@ function assignFlattenedFailurePath(target, field, value) {
20453
20907
  let cursor = target;
20454
20908
  for (const part of normalized.slice(0, -1)) {
20455
20909
  const existing = cursor[part];
20456
- if (!isRecord7(existing)) {
20910
+ if (!isRecord8(existing)) {
20457
20911
  const next = {};
20458
20912
  cursor[part] = next;
20459
20913
  cursor = next;
@@ -20617,10 +21071,10 @@ function waterfallExecutionSignal(status, spec) {
20617
21071
  let everyChildStatOnlyConditionSkipped = true;
20618
21072
  const childAliasesWithStats = /* @__PURE__ */ new Set();
20619
21073
  for (const childAlias of childAliases) {
20620
- for (const stat2 of summaries.map((summary) => summary[childAlias]).filter(isRecord7)) {
21074
+ for (const stat2 of summaries.map((summary) => summary[childAlias]).filter(isRecord8)) {
20621
21075
  sawChildStats = true;
20622
21076
  childAliasesWithStats.add(childAlias);
20623
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21077
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20624
21078
  const executedSummary = parseExecutionSummary(
20625
21079
  execution?.["completed:executed"]
20626
21080
  );
@@ -20650,7 +21104,7 @@ function waterfallExecutionSignal(status, spec) {
20650
21104
  }
20651
21105
  function emptyWaterfallStatsEvidence(status, spec) {
20652
21106
  const summaries = collectColumnStats(status);
20653
- const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord7);
21107
+ const parentStats = summaries.map((summary) => summary[spec.alias]).filter(isRecord8);
20654
21108
  for (const stat2 of parentStats) {
20655
21109
  const nonEmpty = parseExecutionSummary(stat2.non_empty);
20656
21110
  if (nonEmpty?.total && nonEmpty.count === 0) {
@@ -20664,7 +21118,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
20664
21118
  let selectedRows = 0;
20665
21119
  let sawStatsForEveryChild = true;
20666
21120
  for (const childAlias of childAliases) {
20667
- const stat2 = summaries.map((summary) => summary[childAlias]).find(isRecord7);
21121
+ const stat2 = summaries.map((summary) => summary[childAlias]).find(isRecord8);
20668
21122
  if (!stat2) {
20669
21123
  sawStatsForEveryChild = false;
20670
21124
  break;
@@ -20673,7 +21127,7 @@ function emptyWaterfallStatsEvidence(status, spec) {
20673
21127
  if ((nonEmpty?.count ?? 0) > 0) {
20674
21128
  return null;
20675
21129
  }
20676
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21130
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20677
21131
  const executed = parseExecutionSummary(execution?.["completed:executed"]);
20678
21132
  const reused = parseExecutionSummary(execution?.["completed:reused"]);
20679
21133
  const skipped = parseExecutionSummary(execution?.["skipped:condition"]);
@@ -20715,11 +21169,11 @@ function collectStatusFailureJobs(input2) {
20715
21169
  const jobs = [];
20716
21170
  aliases.forEach((spec, aliasIndex) => {
20717
21171
  const { alias } = spec;
20718
- const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
21172
+ const stat2 = summaries.map((summary) => summary[alias]).find(isRecord8);
20719
21173
  if (!stat2) {
20720
21174
  return;
20721
21175
  }
20722
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21176
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20723
21177
  const failedCount = Math.min(
20724
21178
  selectedRows,
20725
21179
  Math.max(
@@ -20826,10 +21280,10 @@ function collectColumnStats(status) {
20826
21280
  value.forEach(visit);
20827
21281
  return;
20828
21282
  }
20829
- if (!isRecord7(value)) {
21283
+ if (!isRecord8(value)) {
20830
21284
  return;
20831
21285
  }
20832
- if (isRecord7(value.columnStats)) {
21286
+ if (isRecord8(value.columnStats)) {
20833
21287
  summaries.push(value.columnStats);
20834
21288
  }
20835
21289
  Object.values(value).forEach(visit);
@@ -20841,12 +21295,12 @@ function firstAliasExecutionCounts(input2) {
20841
21295
  const aliases = collectConfigScalarAliasOrder(input2.config);
20842
21296
  const summaries = collectColumnStats(input2.status);
20843
21297
  for (const alias of aliases) {
20844
- const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
21298
+ const stat2 = summaries.map((summary) => summary[alias]).find(isRecord8);
20845
21299
  if (!stat2) continue;
20846
21300
  if (input2.forceAliases.has(normalizeAlias2(alias))) {
20847
21301
  return { executed: input2.selectedRows, reused: 0 };
20848
21302
  }
20849
- const execution = isRecord7(stat2.execution) ? stat2.execution : null;
21303
+ const execution = isRecord8(stat2.execution) ? stat2.execution : null;
20850
21304
  if (!execution) continue;
20851
21305
  return {
20852
21306
  executed: parseExecutionCount(execution["completed:executed"]),
@@ -20873,14 +21327,14 @@ function rewriteEnrichJsonStatus(input2) {
20873
21327
  if (Array.isArray(value)) {
20874
21328
  return value.map(rewrite);
20875
21329
  }
20876
- if (!isRecord7(value)) {
21330
+ if (!isRecord8(value)) {
20877
21331
  return value;
20878
21332
  }
20879
21333
  const next = {};
20880
21334
  for (const [key, entry] of Object.entries(value)) {
20881
21335
  next[key] = rewrite(entry);
20882
21336
  }
20883
- if (isRecord7(next.progress)) {
21337
+ if (isRecord8(next.progress)) {
20884
21338
  next.progress = {
20885
21339
  ...next.progress,
20886
21340
  ...selectedRows > 0 ? { total: selectedRows } : {},
@@ -20889,8 +21343,8 @@ function rewriteEnrichJsonStatus(input2) {
20889
21343
  ...failedRows > 0 ? { failed: failedRows, pending: 0 } : {}
20890
21344
  };
20891
21345
  }
20892
- if (isRecord7(next.summary)) {
20893
- 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;
20894
21348
  if (failedRows > 0) {
20895
21349
  next.summary = {
20896
21350
  ...next.summary,
@@ -20903,11 +21357,11 @@ function rewriteEnrichJsonStatus(input2) {
20903
21357
  };
20904
21358
  }
20905
21359
  }
20906
- if (isRecord7(next.columnStats) && selectedRows > 0) {
21360
+ if (isRecord8(next.columnStats) && selectedRows > 0) {
20907
21361
  const columnStats = { ...next.columnStats };
20908
21362
  for (const alias of forcedAliases) {
20909
- const stat2 = isRecord7(columnStats[alias]) ? columnStats[alias] : null;
20910
- 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;
20911
21365
  if (!stat2 || !execution) continue;
20912
21366
  columnStats[alias] = {
20913
21367
  ...stat2,
@@ -20926,14 +21380,14 @@ function rewriteEnrichJsonStatus(input2) {
20926
21380
  return next;
20927
21381
  };
20928
21382
  const rewritten = rewrite(input2.status);
20929
- if (failedRows === 0 || !isRecord7(rewritten)) {
21383
+ if (failedRows === 0 || !isRecord8(rewritten)) {
20930
21384
  return rewritten;
20931
21385
  }
20932
21386
  const partialStatus = selectedRows > 0 && failedRows < selectedRows ? "partial_success" : "failed";
20933
21387
  return {
20934
21388
  ...rewritten,
20935
21389
  ...rewritten.status === "completed" || rewritten.status === "failed" ? { status: partialStatus } : {},
20936
- ...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 } } : {}
20937
21391
  };
20938
21392
  }
20939
21393
  function summarizeFailedJobError(value) {
@@ -21347,11 +21801,15 @@ async function fetchBackingRowsForCsvExport(input2) {
21347
21801
  }
21348
21802
  function mergeRowsForCsvExport(enrichedRows, options) {
21349
21803
  const compactAliases = options?.config ? enrichAiRuntimeCompactAliases(options.config) : /* @__PURE__ */ new Set();
21804
+ const preservedAliases = /* @__PURE__ */ new Set([
21805
+ ...compactAliases,
21806
+ ...options?.config ? collectConfigPlayAliases(options.config) : []
21807
+ ]);
21350
21808
  const rows = dataExportRows(
21351
21809
  normalizeEnrichRowsForCsvExport(enrichedRows, options?.config, {
21352
21810
  statusFailureMessages: options?.statusFailureMessages
21353
21811
  }),
21354
- { preserveJsonStringColumns: compactAliases }
21812
+ { preserveJsonStringColumns: preservedAliases }
21355
21813
  );
21356
21814
  const range = options?.rows;
21357
21815
  if (!options?.sourceCsvPath) {
@@ -21428,6 +21886,22 @@ function mergeRowsForCsvExport(enrichedRows, options) {
21428
21886
  }
21429
21887
  return { rows: merged, preferredColumns };
21430
21888
  }
21889
+ function collectConfigPlayAliases(config) {
21890
+ const aliases = /* @__PURE__ */ new Set();
21891
+ const visit = (commands) => {
21892
+ for (const command of commands) {
21893
+ if ("with_waterfall" in command) {
21894
+ visit(command.commands);
21895
+ continue;
21896
+ }
21897
+ if (!command.disabled && command.play) {
21898
+ aliases.add(normalizeAlias2(command.alias));
21899
+ }
21900
+ }
21901
+ };
21902
+ visit(config.commands);
21903
+ return aliases;
21904
+ }
21431
21905
  function collectConfigScalarAliasOrder(config) {
21432
21906
  const aliases = [];
21433
21907
  const seen = /* @__PURE__ */ new Set();
@@ -21525,7 +21999,7 @@ function materializeCsvCellValue(value) {
21525
21999
  return value;
21526
22000
  }
21527
22001
  function compactArrayEnvelopeCompleteValue(value) {
21528
- if (!isRecord7(value) || value.kind !== "array") {
22002
+ if (!isRecord8(value) || value.kind !== "array") {
21529
22003
  return null;
21530
22004
  }
21531
22005
  if (!Array.isArray(value.preview)) {
@@ -21539,7 +22013,7 @@ function compactArrayEnvelopeCompleteValue(value) {
21539
22013
  }
21540
22014
  function disambiguateCompactAiInferencePayload(value) {
21541
22015
  const parsed = parseMaybeJsonObject(value);
21542
- if (!isRecord7(parsed) || !cellFailureError(parsed)) {
22016
+ if (!isRecord8(parsed) || !cellFailureError(parsed)) {
21543
22017
  return value;
21544
22018
  }
21545
22019
  return {
@@ -21548,14 +22022,14 @@ function disambiguateCompactAiInferencePayload(value) {
21548
22022
  };
21549
22023
  }
21550
22024
  function compactAiInferenceCellForCsv(value) {
21551
- if (!isRecord7(value)) {
22025
+ if (!isRecord8(value)) {
21552
22026
  return value;
21553
22027
  }
21554
22028
  const extractedJson = value.extracted_json;
21555
22029
  if (extractedJson !== null && extractedJson !== void 0) {
21556
22030
  return disambiguateCompactAiInferencePayload(extractedJson);
21557
22031
  }
21558
- const result = isRecord7(value.result) ? value.result : null;
22032
+ const result = isRecord8(value.result) ? value.result : null;
21559
22033
  const object = result?.object;
21560
22034
  if (object !== null && object !== void 0) {
21561
22035
  return disambiguateCompactAiInferencePayload(object);
@@ -21572,17 +22046,20 @@ function compactAiInferenceCellForCsv(value) {
21572
22046
  }
21573
22047
  function materializeEnrichAliasCellForCsv(row, alias, options) {
21574
22048
  const direct = row[alias];
21575
- if (isRecord7(direct)) {
22049
+ if (isRecord8(direct)) {
21576
22050
  const completeArray = compactArrayEnvelopeCompleteValue(direct);
21577
22051
  if (completeArray) {
21578
22052
  return materializeCsvCellValue(completeArray);
21579
22053
  }
21580
- 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")) {
21581
22055
  return materializeCsvCellValue(compactAiInferenceCellForCsv(direct));
21582
22056
  }
21583
22057
  if (Object.prototype.hasOwnProperty.call(direct, "matched_result") || Object.prototype.hasOwnProperty.call(direct, "matchedResult") || Object.prototype.hasOwnProperty.call(direct, "result")) {
21584
22058
  return materializeCsvCellValue(direct);
21585
22059
  }
22060
+ if (options?.preservePlainObject && !Object.prototype.hasOwnProperty.call(direct, "_metadata")) {
22061
+ return materializeCsvCellValue(direct);
22062
+ }
21586
22063
  const directCells = [];
21587
22064
  for (const [field, value] of Object.entries(direct)) {
21588
22065
  if (!isEnrichAliasPayloadField(field)) {
@@ -21639,6 +22116,7 @@ function materializeEnrichAliasCellForCsv(row, alias, options) {
21639
22116
  function normalizeEnrichRowsForCsvExport(rows, config, options) {
21640
22117
  const aliases = config ? collectConfigScalarAliasOrder(config) : [];
21641
22118
  const aiCompactAliases = config ? enrichAiRuntimeCompactAliases(config) : null;
22119
+ const playAliases = config ? collectConfigPlayAliases(config) : /* @__PURE__ */ new Set();
21642
22120
  const failureOperationByAlias = hardFailureOperationByAlias(config);
21643
22121
  return rows.map((row) => {
21644
22122
  const metadata = legacyMetadataFromRow(row);
@@ -21682,7 +22160,8 @@ function normalizeEnrichRowsForCsvExport(rows, config, options) {
21682
22160
  }
21683
22161
  for (const alias of aliases) {
21684
22162
  const value = materializeEnrichAliasCellForCsv(normalized, alias, {
21685
- compactAiCell: aiCompactAliases?.has(normalizeAlias2(alias)) ?? false
22163
+ compactAiCell: aiCompactAliases?.has(normalizeAlias2(alias)) ?? false,
22164
+ preservePlainObject: playAliases.has(normalizeAlias2(alias))
21686
22165
  });
21687
22166
  if (value !== void 0) {
21688
22167
  normalized[alias] = value;
@@ -21713,11 +22192,11 @@ function normalizeEnrichRowsForCsvExport(rows, config, options) {
21713
22192
  }
21714
22193
  function legacyMetadataFromRow(row) {
21715
22194
  const direct = parseLegacyMetadataCell(row._metadata);
21716
- if (direct && isRecord7(direct.columns)) {
22195
+ if (direct && isRecord8(direct.columns)) {
21717
22196
  return direct;
21718
22197
  }
21719
22198
  const relocated = parseLegacyMetadataCell(row.metadata);
21720
- if (relocated && isRecord7(relocated.columns)) {
22199
+ if (relocated && isRecord8(relocated.columns)) {
21721
22200
  return relocated;
21722
22201
  }
21723
22202
  const flattenedColumns = parseLegacyMetadataCell(row["metadata.columns"]);
@@ -21734,7 +22213,7 @@ function legacyMetadataFromRow(row) {
21734
22213
  }
21735
22214
  function parseLegacyMetadataCell(value) {
21736
22215
  const parsed = parseMaybeJsonObject(value);
21737
- if (isRecord7(parsed)) {
22216
+ if (isRecord8(parsed)) {
21738
22217
  return parsed;
21739
22218
  }
21740
22219
  if (typeof value !== "string") {
@@ -21751,12 +22230,12 @@ function parseLegacyMetadataCell(value) {
21751
22230
  for (const candidate of candidates) {
21752
22231
  try {
21753
22232
  const decoded = JSON.parse(candidate);
21754
- if (isRecord7(decoded)) {
22233
+ if (isRecord8(decoded)) {
21755
22234
  return decoded;
21756
22235
  }
21757
22236
  if (typeof decoded === "string") {
21758
22237
  const nested = JSON.parse(decoded);
21759
- if (isRecord7(nested)) {
22238
+ if (isRecord8(nested)) {
21760
22239
  return nested;
21761
22240
  }
21762
22241
  }
@@ -21766,8 +22245,8 @@ function parseLegacyMetadataCell(value) {
21766
22245
  return null;
21767
22246
  }
21768
22247
  function mergeLegacyMetadataRecords(base, enriched) {
21769
- const baseColumns = isRecord7(base.columns) ? base.columns : null;
21770
- 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;
21771
22250
  const merged = {
21772
22251
  ...base,
21773
22252
  ...enriched
@@ -21870,6 +22349,9 @@ function registerEnrichCommand(program) {
21870
22349
  ).option(
21871
22350
  "--profile <id>",
21872
22351
  "Internal/testing: override the execution profile for the generated play run."
22352
+ ).option(
22353
+ "--debug-map-latency",
22354
+ "Internal diagnostics: emit one aggregate latency profile per dataset map."
21873
22355
  ).option(
21874
22356
  "--fail-fast",
21875
22357
  "Fail the generated play when any selected row errors, while preserving recovered runtime-sheet rows for export."
@@ -22015,6 +22497,9 @@ function registerEnrichCommand(program) {
22015
22497
  if (options.profile) {
22016
22498
  runArgs.push("--profile", options.profile);
22017
22499
  }
22500
+ if (options.debugMapLatency) {
22501
+ runArgs.push("--debug-map-latency");
22502
+ }
22018
22503
  if (options.noOpen || input2.suppressOpen) {
22019
22504
  runArgs.push("--no-open");
22020
22505
  }
@@ -22031,11 +22516,15 @@ function registerEnrichCommand(program) {
22031
22516
  const captured2 = await runGeneratedEnrichPlay(client2, runArgs, {
22032
22517
  passthroughStdout: input2.passthroughStdout
22033
22518
  });
22034
- const status2 = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
22519
+ const generatedPlayStatus = input2.json ? parseJsonOutput(captured2.stdout) : await resolveWatchedGeneratedPlayStatus({
22035
22520
  client: client2,
22036
22521
  stdout: captured2.stdout,
22037
22522
  exitCode: captured2.result
22038
22523
  });
22524
+ const status2 = rewriteGeneratedPlayRerunForEnrich(
22525
+ generatedPlayStatus,
22526
+ sdkEnrichCommandText(args)
22527
+ );
22039
22528
  const exportResult2 = await maybeWriteOutputCsv({
22040
22529
  outputPath,
22041
22530
  status: status2,
@@ -26269,7 +26758,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
26269
26758
  }
26270
26759
  function extractionContractEntries(entries) {
26271
26760
  return entries.flatMap((entry) => {
26272
- if (!isRecord8(entry)) return [];
26761
+ if (!isRecord9(entry)) return [];
26273
26762
  const name = stringField2(entry, "name");
26274
26763
  const expression = stringField2(entry, "expression");
26275
26764
  return name && expression ? [{ name, expression }] : [];
@@ -26277,8 +26766,8 @@ function extractionContractEntries(entries) {
26277
26766
  }
26278
26767
  function printCompactToolContract(tool, requestedToolId) {
26279
26768
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
26280
- const cost = isRecord8(contract.cost) ? contract.cost : {};
26281
- const getters = isRecord8(contract.getters) ? contract.getters : {};
26769
+ const cost = isRecord9(contract.cost) ? contract.cost : {};
26770
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
26282
26771
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
26283
26772
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
26284
26773
  const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
@@ -26295,7 +26784,7 @@ function printCompactToolContract(tool, requestedToolId) {
26295
26784
  console.log("");
26296
26785
  console.log("Inputs:");
26297
26786
  for (const field of inputFields) {
26298
- if (!isRecord8(field)) continue;
26787
+ if (!isRecord9(field)) continue;
26299
26788
  const name = stringField2(field, "name");
26300
26789
  if (!name) continue;
26301
26790
  const required = field.required ? "*" : "";
@@ -26308,7 +26797,7 @@ function printCompactToolContract(tool, requestedToolId) {
26308
26797
  }
26309
26798
  console.log("");
26310
26799
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
26311
- const starterScript = isRecord8(contract.starterScript) ? contract.starterScript : {};
26800
+ const starterScript = isRecord9(contract.starterScript) ? contract.starterScript : {};
26312
26801
  const starterPath = stringField2(starterScript, "path");
26313
26802
  if (starterPath) {
26314
26803
  console.log("");
@@ -26322,14 +26811,14 @@ function printCompactToolContract(tool, requestedToolId) {
26322
26811
  console.log("Getters:");
26323
26812
  if (listGetters.length) console.log("Lists:");
26324
26813
  for (const entry of listGetters) {
26325
- if (isRecord8(entry))
26814
+ if (isRecord9(entry))
26326
26815
  console.log(
26327
26816
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26328
26817
  );
26329
26818
  }
26330
26819
  if (valueGetters.length) console.log("Values:");
26331
26820
  for (const entry of valueGetters) {
26332
- if (isRecord8(entry))
26821
+ if (isRecord9(entry))
26333
26822
  console.log(
26334
26823
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26335
26824
  );
@@ -26342,7 +26831,7 @@ function printCompactToolContract(tool, requestedToolId) {
26342
26831
  }
26343
26832
  function printToolPricingOnly(tool, requestedToolId, options = {}) {
26344
26833
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
26345
- const cost = isRecord8(contract.cost) ? contract.cost : {};
26834
+ const cost = isRecord9(contract.cost) ? contract.cost : {};
26346
26835
  const pricingModel = stringField2(cost, "pricingModel") || "unknown";
26347
26836
  const billingMode = stringField2(cost, "billingMode") || "unknown";
26348
26837
  const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : pricingModel === "fixed" ? "call" : pricingModel.replace(/^per_/, "") || "unit";
@@ -26362,7 +26851,7 @@ function printToolSchemaOnly(tool, requestedToolId) {
26362
26851
  }
26363
26852
  console.log("Inputs:");
26364
26853
  for (const field of inputFields) {
26365
- if (!isRecord8(field)) continue;
26854
+ if (!isRecord9(field)) continue;
26366
26855
  const name = stringField2(field, "name");
26367
26856
  if (!name) continue;
26368
26857
  const required = field.required ? "*" : "";
@@ -26392,10 +26881,10 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
26392
26881
  ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
26393
26882
  );
26394
26883
  console.log("});");
26395
- const getters = isRecord8(contract.getters) ? contract.getters : {};
26884
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
26396
26885
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
26397
26886
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
26398
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord8);
26887
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord9);
26399
26888
  if (firstGetter) {
26400
26889
  const name = stringField2(firstGetter, "name") || "value";
26401
26890
  const expression = stringField2(firstGetter, "expression");
@@ -26431,7 +26920,7 @@ function printPlayLikeToolUsage(tool, requestedToolId) {
26431
26920
  }
26432
26921
  function printToolGettersOnly(tool, requestedToolId) {
26433
26922
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
26434
- const getters = isRecord8(contract.getters) ? contract.getters : {};
26923
+ const getters = isRecord9(contract.getters) ? contract.getters : {};
26435
26924
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
26436
26925
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
26437
26926
  console.log(`Getters: ${contract.toolId}`);
@@ -26444,7 +26933,7 @@ function printToolGettersOnly(tool, requestedToolId) {
26444
26933
  if (listGetters.length) {
26445
26934
  console.log("Lists:");
26446
26935
  for (const entry of listGetters) {
26447
- if (isRecord8(entry))
26936
+ if (isRecord9(entry))
26448
26937
  console.log(
26449
26938
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26450
26939
  );
@@ -26453,7 +26942,7 @@ function printToolGettersOnly(tool, requestedToolId) {
26453
26942
  if (valueGetters.length) {
26454
26943
  console.log("Values:");
26455
26944
  for (const entry of valueGetters) {
26456
- if (isRecord8(entry))
26945
+ if (isRecord9(entry))
26457
26946
  console.log(
26458
26947
  `- ${stringField2(entry, "name")}: ${playResultExpression(entry)}`
26459
26948
  );
@@ -26479,7 +26968,7 @@ function sampleValueForField(field) {
26479
26968
  function samplePayloadForInputFields(fields) {
26480
26969
  return Object.fromEntries(
26481
26970
  fields.slice(0, 4).flatMap((field) => {
26482
- if (!isRecord8(field)) return [];
26971
+ if (!isRecord9(field)) return [];
26483
26972
  const name = stringField2(field, "name");
26484
26973
  if (!name) return [];
26485
26974
  return [[name, sampleValueForField(field)]];
@@ -26597,12 +27086,12 @@ function formatListedToolCost(tool) {
26597
27086
  }
26598
27087
  function toolInputFieldsForDisplay(inputSchema) {
26599
27088
  if (Array.isArray(inputSchema.fields))
26600
- return inputSchema.fields.filter(isRecord8);
26601
- const jsonSchema = isRecord8(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
26602
- 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 : {};
26603
27092
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
26604
27093
  return Object.entries(properties).map(([name, value]) => {
26605
- const property = isRecord8(value) ? value : {};
27094
+ const property = isRecord9(value) ? value : {};
26606
27095
  return {
26607
27096
  name,
26608
27097
  type: typeof property.type === "string" ? property.type : "unknown",
@@ -26631,15 +27120,15 @@ function printJsonPreview(label, payload) {
26631
27120
  }
26632
27121
  function samplePayload(samples, key) {
26633
27122
  const entry = samples[key];
26634
- if (!isRecord8(entry)) return void 0;
27123
+ if (!isRecord9(entry)) return void 0;
26635
27124
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
26636
27125
  }
26637
27126
  function commandEnvelopeFromRawResponse(rawResponse) {
26638
- return isRecord8(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
27127
+ return isRecord9(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
26639
27128
  }
26640
27129
  function listExtractorPathsFromUsageGuidance(tool) {
26641
27130
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
26642
- 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) : [];
26643
27132
  return extractedLists.flatMap((entry) => {
26644
27133
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
26645
27134
  if (!Array.isArray(paths)) return [];
@@ -26655,7 +27144,7 @@ function formatDecimal(value) {
26655
27144
  function formatUsd(value) {
26656
27145
  return `$${formatDecimal(value)}`;
26657
27146
  }
26658
- function isRecord8(value) {
27147
+ function isRecord9(value) {
26659
27148
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
26660
27149
  }
26661
27150
  function stringField2(source, ...keys) {
@@ -26682,7 +27171,7 @@ function arrayField2(source, ...keys) {
26682
27171
  function recordField2(source, ...keys) {
26683
27172
  for (const key of keys) {
26684
27173
  const value = source[key];
26685
- if (isRecord8(value)) return value;
27174
+ if (isRecord9(value)) return value;
26686
27175
  }
26687
27176
  return {};
26688
27177
  }
@@ -26748,7 +27237,7 @@ function parseJsonObjectArgument(raw, flagName) {
26748
27237
  }
26749
27238
  throw invalidJsonError(flagName, message);
26750
27239
  }
26751
- if (!isRecord8(parsed)) {
27240
+ if (!isRecord9(parsed)) {
26752
27241
  throw invalidJsonError(flagName, "expected an object.");
26753
27242
  }
26754
27243
  return parsed;
@@ -26894,7 +27383,7 @@ function buildToolExecuteBaseEnvelope(input2) {
26894
27383
  kind: summaryEntries.length > 0 ? "object" : "raw",
26895
27384
  summary: input2.summary
26896
27385
  };
26897
- 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");
26898
27387
  const envelopeHasDeclaredOutput = Object.prototype.hasOwnProperty.call(
26899
27388
  envelope,
26900
27389
  "output"
@@ -27113,7 +27602,7 @@ async function executeTool(args) {
27113
27602
  {
27114
27603
  ...baseEnvelope,
27115
27604
  local: {
27116
- ...isRecord8(baseEnvelope.local) ? baseEnvelope.local : {},
27605
+ ...isRecord9(baseEnvelope.local) ? baseEnvelope.local : {},
27117
27606
  payload_file: jsonPath
27118
27607
  }
27119
27608
  },