deepline 0.3.219 → 0.3.220

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.
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
200
200
  // getters keep their established compatibility behavior.
201
201
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
202
202
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
203
- version: '0.3.219',
203
+ version: '0.3.220',
204
204
  updateSummary:
205
205
  'Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.',
206
206
  packageCapabilities: {
@@ -237,7 +237,14 @@ export function derivePlayActivityVisibility(input: {
237
237
  }
238
238
  if (state.kind === 'queued' || state.kind === 'scheduled') return 'headline';
239
239
  if (state.kind === 'retrying') {
240
- return state.retryAt - input.now <= 30_000 ? 'hidden' : 'timeline';
240
+ if (
241
+ state.reason === 'rate_limit' &&
242
+ input.observation.target.kind === 'capacity'
243
+ ) {
244
+ return 'headline';
245
+ }
246
+ if (state.retryAt - input.now <= 30_000) return 'hidden';
247
+ return state.reason === 'rate_limit' ? 'headline' : 'timeline';
241
248
  }
242
249
  if (state.kind === 'active') return 'headline';
243
250
  return 'timeline';
@@ -292,6 +299,9 @@ export function summarizePlayActivity(
292
299
  }
293
300
  return `Paused: ${label}; the legacy producer did not report a typed reason.`;
294
301
  case 'retrying':
302
+ if (state.reason === 'rate_limit') {
303
+ return `Waiting for ${label} request capacity; the run will retry automatically.`;
304
+ }
295
305
  return `Delayed: ${label} will retry automatically.`;
296
306
  case 'scheduled':
297
307
  return `Scheduled: ${label} will resume automatically.`;
@@ -397,9 +407,19 @@ export function projectPlayRunActivity(input: {
397
407
  return null;
398
408
  }
399
409
 
400
- const explicit = [...(input.explicit ?? [])]
410
+ const latestExplicit = [...(input.explicit ?? [])]
401
411
  .filter((candidate) => !isTerminalActivityState(candidate.state))
402
412
  .sort((left, right) => right.observedAt - left.observedAt)[0];
413
+ // A provider wait is an observation, not a permanent run state. Once its
414
+ // deadline has passed, use the current lifecycle/step facts until the next
415
+ // producer observation arrives instead of claiming the old hold persists.
416
+ const explicit =
417
+ latestExplicit?.target.kind === 'capacity' &&
418
+ latestExplicit.target.pool === 'provider' &&
419
+ latestExplicit.state.kind === 'retrying' &&
420
+ latestExplicit.state.retryAt < now
421
+ ? null
422
+ : latestExplicit;
403
423
  if (explicit) return projection(explicit, now);
404
424
 
405
425
  if (input.waitKind === 'detached_runner') {
@@ -11525,6 +11525,15 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11525
11525
  })}`,
11526
11526
  { level: 'warn' },
11527
11527
  );
11528
+ // The ordinary provider sleep emits this below. A mixed event/provider
11529
+ // suspension takes the event-batch path instead, so report its one
11530
+ // aggregate provider hold here rather than once for every waiting row.
11531
+ if (uniqueBoundaries.length > 0) {
11532
+ this.observeProviderCapacityWait(
11533
+ earliestHold.provider,
11534
+ providerWakeAtMs,
11535
+ );
11536
+ }
11528
11537
  }
11529
11538
  this.pendingRowEventBoundaries = [];
11530
11539
  if (uniqueBoundaries.length > 0) {
@@ -14582,6 +14591,26 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
14582
14591
  );
14583
14592
  }
14584
14593
 
14594
+ private observeProviderCapacityWait(
14595
+ provider: string,
14596
+ retryAtMs: number,
14597
+ ): void {
14598
+ const observedAt = Date.now();
14599
+ this.emitExecutionEvent({
14600
+ type: 'activity.observed',
14601
+ observation: {
14602
+ activityId: `capacity:provider:${provider}`,
14603
+ target: { kind: 'capacity', pool: 'provider', label: provider },
14604
+ state: {
14605
+ kind: 'retrying',
14606
+ reason: 'rate_limit',
14607
+ retryAt: Math.max(observedAt, retryAtMs),
14608
+ },
14609
+ observedAt,
14610
+ },
14611
+ });
14612
+ }
14613
+
14585
14614
  private async waitForProviderBackpressure(
14586
14615
  provider: string,
14587
14616
  retryAtMs: number,
@@ -14633,6 +14662,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
14633
14662
  })}`,
14634
14663
  { level: 'warn' },
14635
14664
  );
14665
+ this.observeProviderCapacityWait(provider, Date.now() + delayMs);
14636
14666
  this.suspendDurably({ kind: 'sleep', boundaryId, delayMs });
14637
14667
  }
14638
14668
 
package/dist/cli/index.js CHANGED
@@ -3051,7 +3051,7 @@ var SDK_RELEASE = {
3051
3051
  // getters keep their established compatibility behavior.
3052
3052
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3053
3053
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3054
- version: "0.3.219",
3054
+ version: "0.3.220",
3055
3055
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3056
3056
  packageCapabilities: {
3057
3057
  updatePreferences: 1
@@ -5121,7 +5121,11 @@ function derivePlayActivityVisibility(input2) {
5121
5121
  }
5122
5122
  if (state.kind === "queued" || state.kind === "scheduled") return "headline";
5123
5123
  if (state.kind === "retrying") {
5124
- return state.retryAt - input2.now <= 3e4 ? "hidden" : "timeline";
5124
+ if (state.reason === "rate_limit" && input2.observation.target.kind === "capacity") {
5125
+ return "headline";
5126
+ }
5127
+ if (state.retryAt - input2.now <= 3e4) return "hidden";
5128
+ return state.reason === "rate_limit" ? "headline" : "timeline";
5125
5129
  }
5126
5130
  if (state.kind === "active") return "headline";
5127
5131
  return "timeline";
@@ -5166,6 +5170,9 @@ function summarizePlayActivity(observation) {
5166
5170
  }
5167
5171
  return `Paused: ${label}; the legacy producer did not report a typed reason.`;
5168
5172
  case "retrying":
5173
+ if (state.reason === "rate_limit") {
5174
+ return `Waiting for ${label} request capacity; the run will retry automatically.`;
5175
+ }
5169
5176
  return `Delayed: ${label} will retry automatically.`;
5170
5177
  case "scheduled":
5171
5178
  return `Scheduled: ${label} will resume automatically.`;
@@ -5193,7 +5200,8 @@ function projectPlayRunActivity(input2) {
5193
5200
  if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
5194
5201
  return null;
5195
5202
  }
5196
- const explicit = [...input2.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
5203
+ const latestExplicit = [...input2.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
5204
+ const explicit = latestExplicit?.target.kind === "capacity" && latestExplicit.target.pool === "provider" && latestExplicit.state.kind === "retrying" && latestExplicit.state.retryAt < now ? null : latestExplicit;
5197
5205
  if (explicit) return projection(explicit, now);
5198
5206
  if (input2.waitKind === "detached_runner") {
5199
5207
  return projection(
@@ -25833,6 +25841,15 @@ function formatPlayLogLine(rawLine, status, state) {
25833
25841
  }) : null;
25834
25842
  const message = timestampMatch?.[2] ?? line;
25835
25843
  const prefix = timestamp ? `${timestamp} ` : "";
25844
+ if (!state.verbose && isProviderRowWaitLogLine(line)) return null;
25845
+ const providerWait = formatProviderCapacityWaitLogLine(line);
25846
+ if (providerWait && !state.verbose) {
25847
+ return logLevelReaches("warn", state.logLevel ?? "info") ? `${prefix}${providerWait}` : null;
25848
+ }
25849
+ const mapProgress = formatMapProgressDiagnosticLogLine(line);
25850
+ if (mapProgress && !state.verbose) {
25851
+ return logLevelReaches("info", state.logLevel ?? "info") ? `${prefix}${mapProgress}` : null;
25852
+ }
25836
25853
  if (/\[worker\] picked up run\b/.test(message)) {
25837
25854
  if (!logLevelReaches("info", state.logLevel ?? "info")) {
25838
25855
  return null;
@@ -25874,6 +25891,59 @@ function formatPlayLogLine(rawLine, status, state) {
25874
25891
  }
25875
25892
  return `${prefix}${message}`;
25876
25893
  }
25894
+ function runtimeLogMessage(line) {
25895
+ const timestampMatch = line.match(/^\[([^\]]+)\]\s*(.*)$/);
25896
+ const message = timestampMatch && !Number.isNaN(Date.parse(timestampMatch[1])) ? timestampMatch[2] : line;
25897
+ return message.replace(/^\[(?:debug|info|warn|error)\]\s*/i, "");
25898
+ }
25899
+ function isProviderRowWaitLogLine(line) {
25900
+ return /^\[runtime\.provider\.row_wait\]\s+\{/.test(runtimeLogMessage(line));
25901
+ }
25902
+ function formatProviderCapacityWaitLogLine(line) {
25903
+ const match = runtimeLogMessage(line).match(
25904
+ /^\[runtime\.provider\.(map_wait|row_wait|wait)\]\s+(\{.*\})$/
25905
+ );
25906
+ if (!match) return null;
25907
+ let details;
25908
+ try {
25909
+ const parsed = JSON.parse(match[2]);
25910
+ const record3 = readRecord(parsed);
25911
+ if (!record3) return null;
25912
+ details = record3;
25913
+ } catch {
25914
+ return null;
25915
+ }
25916
+ const provider = typeof details.provider === "string" ? details.provider.trim() : "";
25917
+ const retryAt = typeof details.retry_at === "string" ? isoTimestamp(details.retry_at) : null;
25918
+ if (!provider || !retryAt) return null;
25919
+ const waitingRows = readNonNegativeInteger(details.waiting_rows);
25920
+ return `Waiting for ${provider} request capacity` + (waitingRows === null ? "" : `; ${formatInteger(waitingRows)} rows waiting`) + `; next attempt scheduled for ${retryAt}`;
25921
+ }
25922
+ function formatMapProgressDiagnosticLogLine(line) {
25923
+ const match = runtimeLogMessage(line).match(
25924
+ /^\[runtime\.map_(heartbeat|stall)\]\s+(\{.*\})$/
25925
+ );
25926
+ if (!match) return null;
25927
+ let details;
25928
+ try {
25929
+ const parsed = JSON.parse(match[2]);
25930
+ const record3 = readRecord(parsed);
25931
+ if (!record3) return null;
25932
+ details = record3;
25933
+ } catch {
25934
+ return null;
25935
+ }
25936
+ const map = typeof details.map === "string" ? details.map.trim() : "";
25937
+ if (!map) return null;
25938
+ if (match[1] === "stall") {
25939
+ return `No rows completed during the last observation window in ${map}.`;
25940
+ }
25941
+ const settled = readNonNegativeInteger(details.rows_settled);
25942
+ const active = readNonNegativeInteger(details.rows_active);
25943
+ const waiting = readNonNegativeInteger(details.rows_waiting);
25944
+ if (settled === null || active === null || waiting === null) return null;
25945
+ return `${map}: ${formatInteger(settled)} rows completed, ${formatInteger(active)} active, ${formatInteger(waiting)} waiting.`;
25946
+ }
25877
25947
  function isDatasetResultEnvelope(value) {
25878
25948
  return value !== null && typeof value === "object" && !Array.isArray(value) && value.kind === "dataset";
25879
25949
  }
@@ -26710,6 +26780,23 @@ function formatPackageDatasetActionLines(packaged, options) {
26710
26780
  const returned = packageReturnedDatasetIdentity(packaged);
26711
26781
  const includeSummary = options?.includeSummary ?? true;
26712
26782
  const lines = [];
26783
+ const steps = readRecordArray(packaged.steps);
26784
+ const stepsByDatasetId = /* @__PURE__ */ new Map();
26785
+ const stepsByPath = /* @__PURE__ */ new Map();
26786
+ const stepsByNamespace = /* @__PURE__ */ new Map();
26787
+ for (const step of steps) {
26788
+ if (step.kind !== "dataset") continue;
26789
+ const output2 = readRecord(step.output);
26790
+ if (typeof output2?.datasetId === "string") {
26791
+ stepsByDatasetId.set(output2.datasetId, step);
26792
+ }
26793
+ if (typeof output2?.path === "string") {
26794
+ stepsByPath.set(output2.path, step);
26795
+ }
26796
+ if (typeof step.id === "string") {
26797
+ stepsByNamespace.set(step.id, step);
26798
+ }
26799
+ }
26713
26800
  for (const dataset of packageDatasetRecords(packaged)) {
26714
26801
  const path = typeof dataset.path === "string" && dataset.path.trim() ? dataset.path.trim() : "dataset";
26715
26802
  const datasetId = typeof dataset.datasetId === "string" ? dataset.datasetId.trim() : "";
@@ -26722,7 +26809,7 @@ function formatPackageDatasetActionLines(packaged, options) {
26722
26809
  const actions = readRecord(dataset.actions) ?? {};
26723
26810
  if (countUnconfirmed) {
26724
26811
  lines.push(
26725
- ` dataset ${path}: row count unconfirmed (at least ${formatInteger(persistedLowerBound)} persisted); export this run to inspect saved rows`
26812
+ ` dataset ${path}: row count unconfirmed (at least ${formatInteger(persistedLowerBound)} persisted)`
26726
26813
  );
26727
26814
  } else if (includeSummary) {
26728
26815
  if (category === "recovered" && Object.keys(actions).length === 0) {
@@ -26735,21 +26822,50 @@ function formatPackageDatasetActionLines(packaged, options) {
26735
26822
  );
26736
26823
  }
26737
26824
  }
26825
+ const step = (datasetId ? stepsByDatasetId.get(datasetId) : void 0) ?? stepsByPath.get(path) ?? (typeof dataset.tableNamespace === "string" ? stepsByNamespace.get(dataset.tableNamespace) : void 0);
26826
+ const progress = readRecord(step?.progress);
26827
+ if (progress) {
26828
+ const executed = readNonNegativeInteger(progress.executed);
26829
+ const total = readNonNegativeInteger(progress.total);
26830
+ const reused = readNonNegativeInteger(progress.reused);
26831
+ const pending = readNonNegativeInteger(progress.pending);
26832
+ const active = readNonNegativeInteger(progress.activeRows);
26833
+ const parts = [
26834
+ executed === null ? "executed unknown" : `${formatInteger(executed)}${total === null ? "" : `/${formatInteger(total)}`} executed`,
26835
+ ...reused === null || reused === 0 ? [] : [`${formatInteger(reused)} reused`],
26836
+ ...pending === null ? [] : [`${formatInteger(pending)} pending`],
26837
+ ...active === null ? [] : [`${formatInteger(active)} active`]
26838
+ ];
26839
+ lines.push(` progress: ${parts.join(" \xB7 ")}`);
26840
+ }
26841
+ if (lifecycle) {
26842
+ const succeeded = readNonNegativeInteger(lifecycle.succeededRowsAtLeast);
26843
+ const failed = readNonNegativeInteger(lifecycle.failedRowsAtLeast);
26844
+ const complete = lifecycle.complete === true;
26845
+ lines.push(
26846
+ ` saved: ${complete ? "" : "at least "}${formatInteger(persistedLowerBound)} persisted${succeeded === null ? "" : ` \xB7 ${complete ? "" : "at least "}${formatInteger(succeeded)} succeeded`}${failed === null ? "" : ` \xB7 ${complete ? "" : "at least "}${formatInteger(failed)} failed`}`
26847
+ );
26848
+ }
26738
26849
  const exportAction = readRecord(actions.exportCsv);
26739
26850
  const exportCommand = actionToCommand(exportAction);
26740
26851
  const exportScope = readRecord(exportAction?.scope);
26852
+ const queryAction = readRecord(actions.query);
26853
+ const queryScope = readRecord(queryAction?.scope);
26854
+ const runQueryCommand = queryScope?.kind === "run" ? actionToCommand(queryAction) : null;
26741
26855
  const currentQueryCommand = actionToCommand(actions.queryCurrentTable);
26742
26856
  const legacyQueryCommand = actionToCommand(actions.query);
26857
+ if (runQueryCommand) {
26858
+ lines.push(` query rows from this run: ${runQueryCommand}`);
26859
+ } else if (currentQueryCommand) {
26860
+ lines.push(` query current table: ${currentQueryCommand}`);
26861
+ } else if (legacyQueryCommand) {
26862
+ lines.push(` query run rows (legacy): ${legacyQueryCommand}`);
26863
+ }
26743
26864
  if (exportCommand) {
26744
26865
  lines.push(
26745
26866
  exportScope?.kind === "database" ? ` export current table (may include other runs): ${exportCommand}` : ` export this run: ${exportCommand}`
26746
26867
  );
26747
26868
  }
26748
- if (currentQueryCommand) {
26749
- lines.push(` query current table: ${currentQueryCommand}`);
26750
- } else if (legacyQueryCommand) {
26751
- lines.push(` query run rows (legacy): ${legacyQueryCommand}`);
26752
- }
26753
26869
  const unavailable = readRecord(dataset.exportUnavailable);
26754
26870
  if (typeof unavailable?.reason === "string" && typeof unavailable.message === "string") {
26755
26871
  lines.push(
@@ -26813,12 +26929,42 @@ function formatInlinePackageValue(value) {
26813
26929
  function formatPackageValueOutputLines(packaged) {
26814
26930
  const outputs = packaged.outputs && typeof packaged.outputs === "object" && !Array.isArray(packaged.outputs) ? packaged.outputs : null;
26815
26931
  if (!outputs) return [];
26816
- const valueOutputs = Object.entries(outputs).filter(([, output2]) => {
26817
- return output2 && typeof output2 === "object" && !Array.isArray(output2) && output2.kind === "value" && Object.prototype.hasOwnProperty.call(output2, "value");
26818
- });
26819
- if (valueOutputs.length === 0) return [];
26820
- const lines = [" outputs:"];
26821
- for (const [name, output2] of valueOutputs.slice(0, 8)) {
26932
+ const returned = Object.entries(outputs).filter(([, output2]) => {
26933
+ const record3 = readRecord(output2);
26934
+ return record3?.kind === "dataset" || record3?.kind === "value" && Object.prototype.hasOwnProperty.call(record3, "value");
26935
+ });
26936
+ if (returned.length === 0) return [];
26937
+ const datasets = packageDatasetRecords(packaged);
26938
+ const datasetSteps = readRecordArray(packaged.steps).filter(
26939
+ (step) => step.kind === "dataset"
26940
+ );
26941
+ const lines = [" result:"];
26942
+ for (const [name, rawOutput] of returned.slice(0, 8)) {
26943
+ const output2 = readRecord(rawOutput);
26944
+ if (output2.kind === "dataset") {
26945
+ const path = typeof output2.dataset === "string" ? output2.dataset : name;
26946
+ const rowCount = readNonNegativeInteger(output2.rowCount);
26947
+ lines.push(
26948
+ ` ${name}: dataset ${path}${rowCount === null ? "" : ` (${formatInteger(rowCount)} persisted rows)`}`
26949
+ );
26950
+ const dataset = datasets.find(
26951
+ (candidate) => typeof output2.datasetId === "string" && candidate.datasetId === output2.datasetId || candidate.path === path
26952
+ );
26953
+ const stepOutput = datasetSteps.map((step) => readRecord(step.output)).find(
26954
+ (candidate) => typeof output2.datasetId === "string" && candidate?.datasetId === output2.datasetId || candidate?.path === path
26955
+ );
26956
+ const preview = readRecord(stepOutput?.preview ?? dataset?.preview);
26957
+ const rows = Array.isArray(preview?.rows) ? preview.rows.slice(0, 2) : [];
26958
+ if (rows.length > 0) {
26959
+ lines.push(` sample rows (${rows.length}):`);
26960
+ lines.push(
26961
+ ...rows.map(
26962
+ (row) => ` ${clampJsonPreviewText(JSON.stringify(row) ?? String(row), 350)}`
26963
+ )
26964
+ );
26965
+ }
26966
+ continue;
26967
+ }
26822
26968
  const value = output2.value;
26823
26969
  const compacted = compactReturnValue(value);
26824
26970
  if (compacted && typeof compacted === "object") {
@@ -26828,8 +26974,8 @@ function formatPackageValueOutputLines(packaged) {
26828
26974
  lines.push(` ${name}: ${formatInlinePackageValue(value)}`);
26829
26975
  }
26830
26976
  }
26831
- if (valueOutputs.length > 8) {
26832
- lines.push(` ... ${valueOutputs.length - 8} more output(s)`);
26977
+ if (returned.length > 8) {
26978
+ lines.push(` ... ${returned.length - 8} more output(s)`);
26833
26979
  }
26834
26980
  return lines;
26835
26981
  }
@@ -26885,9 +27031,9 @@ function buildRunActivityTextLines(run) {
26885
27031
  const reason = readRecord(state.reason);
26886
27032
  if (kind === "retrying") {
26887
27033
  const attempt = typeof state.attempt === "number" ? ` (attempt ${state.attempt})` : "";
26888
- const why = typeof state.reason === "string" ? ` after ${state.reason}` : "";
27034
+ const why = typeof state.reason === "string" && state.reason !== "rate_limit" ? ` after ${state.reason}` : "";
26889
27035
  lines.push(
26890
- ` next retry: ${activityIsoTimestamp(state.retryAt) ?? "unknown"}${why}${attempt}`
27036
+ ` ${state.reason === "rate_limit" ? "next attempt" : "next retry"}: ${activityIsoTimestamp(state.retryAt) ?? "unknown"}${why}${attempt}`
26891
27037
  );
26892
27038
  } else if (kind === "scheduled") {
26893
27039
  lines.push(
@@ -26946,16 +27092,65 @@ function buildRunStatusEvidenceTextLines(packaged) {
26946
27092
  }
26947
27093
  return lines;
26948
27094
  }
26949
- function buildRecentRunLogTextLines(packaged) {
26950
- const logs = readRecord(packaged.logs);
26951
- const tail = Array.isArray(logs?.tail) ? logs.tail.filter((line) => typeof line === "string") : [];
27095
+ function formatRunTimingTextLines(run) {
27096
+ const time = (value) => typeof value === "number" || typeof value === "string" ? isoTimestamp(value) : null;
27097
+ const accepted = time(run.acceptedAt);
27098
+ const started = time(run.startedAt);
27099
+ const updated = time(run.updatedAt);
27100
+ const finished = time(run.finishedAt);
27101
+ const duration = typeof run.durationMs === "number" && Number.isFinite(run.durationMs) ? Math.max(0, Math.round(run.durationMs / 1e3)) : null;
27102
+ const age = (value) => {
27103
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
27104
+ const seconds = Math.floor((Date.now() - value) / 1e3);
27105
+ if (seconds < 0) return null;
27106
+ if (seconds < 60) return `${seconds}s`;
27107
+ if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
27108
+ if (seconds < 86400)
27109
+ return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
27110
+ return `${Math.floor(seconds / 86400)}d`;
27111
+ };
27112
+ const active = run.status === "running" || run.status === "queued" || run.status === "waiting";
27113
+ const elapsed = active ? age(run.startedAt) : null;
27114
+ const updateAge = active ? age(run.updatedAt) : null;
27115
+ if (!accepted && !started && !updated && !finished && duration === null)
27116
+ return [];
27117
+ return [
27118
+ ` time: ${[
27119
+ ...accepted ? [`accepted ${accepted}`] : [],
27120
+ ...started ? [`started ${started}`] : [],
27121
+ ...updated ? [`updated ${updated}`] : [],
27122
+ ...finished ? [`finished ${finished}`] : [],
27123
+ ...duration === null ? [] : [`duration ${duration}s`],
27124
+ ...elapsed ? [`elapsed ${elapsed}`] : [],
27125
+ ...updateAge ? [`last update ${updateAge} ago`] : []
27126
+ ].join(" \xB7 ")}`
27127
+ ];
27128
+ }
27129
+ function formatRecentRunLogLines(value) {
27130
+ const logs = readRecord(value);
27131
+ if (!logs || !Array.isArray(logs.tail)) return [];
27132
+ const tail = logs.tail.filter(
27133
+ (line) => typeof line === "string"
27134
+ );
26952
27135
  if (tail.length === 0) return [];
26953
- const visible = tail.slice(-5);
26954
- const total = typeof logs?.totalCount === "number" && Number.isFinite(logs.totalCount) ? ` of ${formatInteger(logs.totalCount)}` : "";
26955
- const lines = [` recent logs: showing ${visible.length}${total}`];
26956
- lines.push(...visible.map((line) => ` ${line}`));
26957
- if (logs?.truncated === true) {
26958
- lines.push(" older log lines were truncated by the retention cap");
27136
+ const shown = tail.map((line) => classifyLogLine(line)).filter(
27137
+ (entry) => entry.level !== "debug" && !isProviderRowWaitLogLine(entry.line)
27138
+ ).slice(-8);
27139
+ const total = readNonNegativeInteger(logs.totalCount);
27140
+ if (shown.length === 0) {
27141
+ return [
27142
+ ` recent logs: no non-debug lines in the retained preview (${total === null ? "total unknown" : `${formatInteger(total)} total`})`,
27143
+ ...logs.truncated === true ? [" [older log bodies lost to retention limit]"] : []
27144
+ ];
27145
+ }
27146
+ const lines = [
27147
+ ` recent logs (${total === null ? "count unknown" : `${formatInteger(total)} total`}; showing ${shown.length}):`,
27148
+ ...shown.map(
27149
+ (entry) => ` ${clampJsonPreviewText(formatProviderCapacityWaitLogLine(entry.line) ?? formatMapProgressDiagnosticLogLine(entry.line) ?? entry.line, 350)}`
27150
+ )
27151
+ ];
27152
+ if (logs.truncated === true) {
27153
+ lines.push(" [older log bodies lost to retention limit]");
26959
27154
  }
26960
27155
  return lines;
26961
27156
  }
@@ -27025,17 +27220,18 @@ function buildRunPackageTextLines(packaged) {
27025
27220
  if (playName && !isRuntimeLimitCheckpoint) {
27026
27221
  lines.push(` play: ${playName}`);
27027
27222
  }
27223
+ lines.push(...formatRunTimingTextLines(run));
27028
27224
  if (!isRuntimeLimitCheckpoint) {
27029
27225
  lines.push(...buildRunActivityTextLines(run));
27030
27226
  }
27031
27227
  lines.push(...buildRunStatusEvidenceTextLines(packaged));
27032
- lines.push(...buildRecentRunLogTextLines(packaged));
27033
27228
  lines.push(...formatPackageValueOutputLines(packaged));
27034
27229
  lines.push(
27035
27230
  ...formatPackageDatasetActionLines(packaged, {
27036
27231
  includeSummary: !isRuntimeLimitCheckpoint
27037
27232
  })
27038
27233
  );
27234
+ lines.push(...formatRecentRunLogLines(packaged.logs));
27039
27235
  const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
27040
27236
  const logsCommand = actionToCommand(next.logs);
27041
27237
  for (const step of isRuntimeLimitCheckpoint ? [] : readRecordArray(packaged.steps).slice(0, 8)) {
@@ -29738,6 +29934,7 @@ async function handleRunTail(args) {
29738
29934
  const jsonLines = args.includes("--jsonl");
29739
29935
  const jsonOutput = !jsonLines && argsWantJson(args);
29740
29936
  const compact = args.includes("--compact");
29937
+ const showLiveLogs = debug || hasExplicitLogLevel || !jsonOutput && !compact;
29741
29938
  const compactState = {
29742
29939
  lastLogIndex: 0,
29743
29940
  emittedRunnerStarted: false,
@@ -29757,8 +29954,8 @@ async function handleRunTail(args) {
29757
29954
  })}
29758
29955
  `
29759
29956
  );
29760
- } : compact || debug || hasExplicitLogLevel ? (event) => {
29761
- if (debug || hasExplicitLogLevel) {
29957
+ } : compact || showLiveLogs ? (event) => {
29958
+ if (showLiveLogs) {
29762
29959
  for (const line of getLogLinesFromLiveEvent(event)) {
29763
29960
  const formatted = formatPlayLogLine(
29764
29961
  line,
@@ -31962,7 +32159,9 @@ Examples:
31962
32159
  "after",
31963
32160
  `
31964
32161
  Notes:
31965
- Full run status read. Use --full --json when debugging raw stream/status fields.
32162
+ Shows per-dataset progress, recorded Deepline usage, recent logs, and the
32163
+ returned result when present. Registered sheets offer a run-scoped query
32164
+ without reading or creating dataset rows. Use --full --json for raw detail.
31966
32165
  Use --input only when you intentionally need the original payload; it can
31967
32166
  contain customer data and is never included in ordinary status output.
31968
32167
 
@@ -32070,8 +32269,9 @@ Examples:
32070
32269
  "after",
32071
32270
  `
32072
32271
  Notes:
32073
- Streams live run events until the stream ends. Use get for current status and
32074
- logs for persisted log history. In human output, --compact prints deduplicated
32272
+ Streams live run events until the stream ends. Human output shows info and
32273
+ warning logs as they arrive. Use get for current status and logs for persisted
32274
+ log history. In human output, --compact prints deduplicated
32075
32275
  step transitions and progress instead of the full event stream. --json emits
32076
32276
  one terminal package. --jsonl emits canonical live events as JSON Lines and
32077
32277
  ends with the same compact package shape as runs get --json. --log-level
@@ -3046,7 +3046,7 @@ var SDK_RELEASE = {
3046
3046
  // getters keep their established compatibility behavior.
3047
3047
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3048
3048
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3049
- version: "0.3.219",
3049
+ version: "0.3.220",
3050
3050
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3051
3051
  packageCapabilities: {
3052
3052
  updatePreferences: 1
@@ -5116,7 +5116,11 @@ function derivePlayActivityVisibility(input2) {
5116
5116
  }
5117
5117
  if (state.kind === "queued" || state.kind === "scheduled") return "headline";
5118
5118
  if (state.kind === "retrying") {
5119
- return state.retryAt - input2.now <= 3e4 ? "hidden" : "timeline";
5119
+ if (state.reason === "rate_limit" && input2.observation.target.kind === "capacity") {
5120
+ return "headline";
5121
+ }
5122
+ if (state.retryAt - input2.now <= 3e4) return "hidden";
5123
+ return state.reason === "rate_limit" ? "headline" : "timeline";
5120
5124
  }
5121
5125
  if (state.kind === "active") return "headline";
5122
5126
  return "timeline";
@@ -5161,6 +5165,9 @@ function summarizePlayActivity(observation) {
5161
5165
  }
5162
5166
  return `Paused: ${label}; the legacy producer did not report a typed reason.`;
5163
5167
  case "retrying":
5168
+ if (state.reason === "rate_limit") {
5169
+ return `Waiting for ${label} request capacity; the run will retry automatically.`;
5170
+ }
5164
5171
  return `Delayed: ${label} will retry automatically.`;
5165
5172
  case "scheduled":
5166
5173
  return `Scheduled: ${label} will resume automatically.`;
@@ -5188,7 +5195,8 @@ function projectPlayRunActivity(input2) {
5188
5195
  if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
5189
5196
  return null;
5190
5197
  }
5191
- const explicit = [...input2.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
5198
+ const latestExplicit = [...input2.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
5199
+ const explicit = latestExplicit?.target.kind === "capacity" && latestExplicit.target.pool === "provider" && latestExplicit.state.kind === "retrying" && latestExplicit.state.retryAt < now ? null : latestExplicit;
5192
5200
  if (explicit) return projection(explicit, now);
5193
5201
  if (input2.waitKind === "detached_runner") {
5194
5202
  return projection(
@@ -25906,6 +25914,15 @@ function formatPlayLogLine(rawLine, status, state) {
25906
25914
  }) : null;
25907
25915
  const message = timestampMatch?.[2] ?? line;
25908
25916
  const prefix = timestamp ? `${timestamp} ` : "";
25917
+ if (!state.verbose && isProviderRowWaitLogLine(line)) return null;
25918
+ const providerWait = formatProviderCapacityWaitLogLine(line);
25919
+ if (providerWait && !state.verbose) {
25920
+ return logLevelReaches("warn", state.logLevel ?? "info") ? `${prefix}${providerWait}` : null;
25921
+ }
25922
+ const mapProgress = formatMapProgressDiagnosticLogLine(line);
25923
+ if (mapProgress && !state.verbose) {
25924
+ return logLevelReaches("info", state.logLevel ?? "info") ? `${prefix}${mapProgress}` : null;
25925
+ }
25909
25926
  if (/\[worker\] picked up run\b/.test(message)) {
25910
25927
  if (!logLevelReaches("info", state.logLevel ?? "info")) {
25911
25928
  return null;
@@ -25947,6 +25964,59 @@ function formatPlayLogLine(rawLine, status, state) {
25947
25964
  }
25948
25965
  return `${prefix}${message}`;
25949
25966
  }
25967
+ function runtimeLogMessage(line) {
25968
+ const timestampMatch = line.match(/^\[([^\]]+)\]\s*(.*)$/);
25969
+ const message = timestampMatch && !Number.isNaN(Date.parse(timestampMatch[1])) ? timestampMatch[2] : line;
25970
+ return message.replace(/^\[(?:debug|info|warn|error)\]\s*/i, "");
25971
+ }
25972
+ function isProviderRowWaitLogLine(line) {
25973
+ return /^\[runtime\.provider\.row_wait\]\s+\{/.test(runtimeLogMessage(line));
25974
+ }
25975
+ function formatProviderCapacityWaitLogLine(line) {
25976
+ const match = runtimeLogMessage(line).match(
25977
+ /^\[runtime\.provider\.(map_wait|row_wait|wait)\]\s+(\{.*\})$/
25978
+ );
25979
+ if (!match) return null;
25980
+ let details;
25981
+ try {
25982
+ const parsed = JSON.parse(match[2]);
25983
+ const record3 = readRecord(parsed);
25984
+ if (!record3) return null;
25985
+ details = record3;
25986
+ } catch {
25987
+ return null;
25988
+ }
25989
+ const provider = typeof details.provider === "string" ? details.provider.trim() : "";
25990
+ const retryAt = typeof details.retry_at === "string" ? isoTimestamp(details.retry_at) : null;
25991
+ if (!provider || !retryAt) return null;
25992
+ const waitingRows = readNonNegativeInteger(details.waiting_rows);
25993
+ return `Waiting for ${provider} request capacity` + (waitingRows === null ? "" : `; ${formatInteger(waitingRows)} rows waiting`) + `; next attempt scheduled for ${retryAt}`;
25994
+ }
25995
+ function formatMapProgressDiagnosticLogLine(line) {
25996
+ const match = runtimeLogMessage(line).match(
25997
+ /^\[runtime\.map_(heartbeat|stall)\]\s+(\{.*\})$/
25998
+ );
25999
+ if (!match) return null;
26000
+ let details;
26001
+ try {
26002
+ const parsed = JSON.parse(match[2]);
26003
+ const record3 = readRecord(parsed);
26004
+ if (!record3) return null;
26005
+ details = record3;
26006
+ } catch {
26007
+ return null;
26008
+ }
26009
+ const map = typeof details.map === "string" ? details.map.trim() : "";
26010
+ if (!map) return null;
26011
+ if (match[1] === "stall") {
26012
+ return `No rows completed during the last observation window in ${map}.`;
26013
+ }
26014
+ const settled = readNonNegativeInteger(details.rows_settled);
26015
+ const active = readNonNegativeInteger(details.rows_active);
26016
+ const waiting = readNonNegativeInteger(details.rows_waiting);
26017
+ if (settled === null || active === null || waiting === null) return null;
26018
+ return `${map}: ${formatInteger(settled)} rows completed, ${formatInteger(active)} active, ${formatInteger(waiting)} waiting.`;
26019
+ }
25950
26020
  function isDatasetResultEnvelope(value) {
25951
26021
  return value !== null && typeof value === "object" && !Array.isArray(value) && value.kind === "dataset";
25952
26022
  }
@@ -26783,6 +26853,23 @@ function formatPackageDatasetActionLines(packaged, options) {
26783
26853
  const returned = packageReturnedDatasetIdentity(packaged);
26784
26854
  const includeSummary = options?.includeSummary ?? true;
26785
26855
  const lines = [];
26856
+ const steps = readRecordArray(packaged.steps);
26857
+ const stepsByDatasetId = /* @__PURE__ */ new Map();
26858
+ const stepsByPath = /* @__PURE__ */ new Map();
26859
+ const stepsByNamespace = /* @__PURE__ */ new Map();
26860
+ for (const step of steps) {
26861
+ if (step.kind !== "dataset") continue;
26862
+ const output2 = readRecord(step.output);
26863
+ if (typeof output2?.datasetId === "string") {
26864
+ stepsByDatasetId.set(output2.datasetId, step);
26865
+ }
26866
+ if (typeof output2?.path === "string") {
26867
+ stepsByPath.set(output2.path, step);
26868
+ }
26869
+ if (typeof step.id === "string") {
26870
+ stepsByNamespace.set(step.id, step);
26871
+ }
26872
+ }
26786
26873
  for (const dataset of packageDatasetRecords(packaged)) {
26787
26874
  const path = typeof dataset.path === "string" && dataset.path.trim() ? dataset.path.trim() : "dataset";
26788
26875
  const datasetId = typeof dataset.datasetId === "string" ? dataset.datasetId.trim() : "";
@@ -26795,7 +26882,7 @@ function formatPackageDatasetActionLines(packaged, options) {
26795
26882
  const actions = readRecord(dataset.actions) ?? {};
26796
26883
  if (countUnconfirmed) {
26797
26884
  lines.push(
26798
- ` dataset ${path}: row count unconfirmed (at least ${formatInteger(persistedLowerBound)} persisted); export this run to inspect saved rows`
26885
+ ` dataset ${path}: row count unconfirmed (at least ${formatInteger(persistedLowerBound)} persisted)`
26799
26886
  );
26800
26887
  } else if (includeSummary) {
26801
26888
  if (category === "recovered" && Object.keys(actions).length === 0) {
@@ -26808,21 +26895,50 @@ function formatPackageDatasetActionLines(packaged, options) {
26808
26895
  );
26809
26896
  }
26810
26897
  }
26898
+ const step = (datasetId ? stepsByDatasetId.get(datasetId) : void 0) ?? stepsByPath.get(path) ?? (typeof dataset.tableNamespace === "string" ? stepsByNamespace.get(dataset.tableNamespace) : void 0);
26899
+ const progress = readRecord(step?.progress);
26900
+ if (progress) {
26901
+ const executed = readNonNegativeInteger(progress.executed);
26902
+ const total = readNonNegativeInteger(progress.total);
26903
+ const reused = readNonNegativeInteger(progress.reused);
26904
+ const pending = readNonNegativeInteger(progress.pending);
26905
+ const active = readNonNegativeInteger(progress.activeRows);
26906
+ const parts = [
26907
+ executed === null ? "executed unknown" : `${formatInteger(executed)}${total === null ? "" : `/${formatInteger(total)}`} executed`,
26908
+ ...reused === null || reused === 0 ? [] : [`${formatInteger(reused)} reused`],
26909
+ ...pending === null ? [] : [`${formatInteger(pending)} pending`],
26910
+ ...active === null ? [] : [`${formatInteger(active)} active`]
26911
+ ];
26912
+ lines.push(` progress: ${parts.join(" \xB7 ")}`);
26913
+ }
26914
+ if (lifecycle) {
26915
+ const succeeded = readNonNegativeInteger(lifecycle.succeededRowsAtLeast);
26916
+ const failed = readNonNegativeInteger(lifecycle.failedRowsAtLeast);
26917
+ const complete = lifecycle.complete === true;
26918
+ lines.push(
26919
+ ` saved: ${complete ? "" : "at least "}${formatInteger(persistedLowerBound)} persisted${succeeded === null ? "" : ` \xB7 ${complete ? "" : "at least "}${formatInteger(succeeded)} succeeded`}${failed === null ? "" : ` \xB7 ${complete ? "" : "at least "}${formatInteger(failed)} failed`}`
26920
+ );
26921
+ }
26811
26922
  const exportAction = readRecord(actions.exportCsv);
26812
26923
  const exportCommand = actionToCommand(exportAction);
26813
26924
  const exportScope = readRecord(exportAction?.scope);
26925
+ const queryAction = readRecord(actions.query);
26926
+ const queryScope = readRecord(queryAction?.scope);
26927
+ const runQueryCommand = queryScope?.kind === "run" ? actionToCommand(queryAction) : null;
26814
26928
  const currentQueryCommand = actionToCommand(actions.queryCurrentTable);
26815
26929
  const legacyQueryCommand = actionToCommand(actions.query);
26930
+ if (runQueryCommand) {
26931
+ lines.push(` query rows from this run: ${runQueryCommand}`);
26932
+ } else if (currentQueryCommand) {
26933
+ lines.push(` query current table: ${currentQueryCommand}`);
26934
+ } else if (legacyQueryCommand) {
26935
+ lines.push(` query run rows (legacy): ${legacyQueryCommand}`);
26936
+ }
26816
26937
  if (exportCommand) {
26817
26938
  lines.push(
26818
26939
  exportScope?.kind === "database" ? ` export current table (may include other runs): ${exportCommand}` : ` export this run: ${exportCommand}`
26819
26940
  );
26820
26941
  }
26821
- if (currentQueryCommand) {
26822
- lines.push(` query current table: ${currentQueryCommand}`);
26823
- } else if (legacyQueryCommand) {
26824
- lines.push(` query run rows (legacy): ${legacyQueryCommand}`);
26825
- }
26826
26942
  const unavailable = readRecord(dataset.exportUnavailable);
26827
26943
  if (typeof unavailable?.reason === "string" && typeof unavailable.message === "string") {
26828
26944
  lines.push(
@@ -26886,12 +27002,42 @@ function formatInlinePackageValue(value) {
26886
27002
  function formatPackageValueOutputLines(packaged) {
26887
27003
  const outputs = packaged.outputs && typeof packaged.outputs === "object" && !Array.isArray(packaged.outputs) ? packaged.outputs : null;
26888
27004
  if (!outputs) return [];
26889
- const valueOutputs = Object.entries(outputs).filter(([, output2]) => {
26890
- return output2 && typeof output2 === "object" && !Array.isArray(output2) && output2.kind === "value" && Object.prototype.hasOwnProperty.call(output2, "value");
26891
- });
26892
- if (valueOutputs.length === 0) return [];
26893
- const lines = [" outputs:"];
26894
- for (const [name, output2] of valueOutputs.slice(0, 8)) {
27005
+ const returned = Object.entries(outputs).filter(([, output2]) => {
27006
+ const record3 = readRecord(output2);
27007
+ return record3?.kind === "dataset" || record3?.kind === "value" && Object.prototype.hasOwnProperty.call(record3, "value");
27008
+ });
27009
+ if (returned.length === 0) return [];
27010
+ const datasets = packageDatasetRecords(packaged);
27011
+ const datasetSteps = readRecordArray(packaged.steps).filter(
27012
+ (step) => step.kind === "dataset"
27013
+ );
27014
+ const lines = [" result:"];
27015
+ for (const [name, rawOutput] of returned.slice(0, 8)) {
27016
+ const output2 = readRecord(rawOutput);
27017
+ if (output2.kind === "dataset") {
27018
+ const path = typeof output2.dataset === "string" ? output2.dataset : name;
27019
+ const rowCount = readNonNegativeInteger(output2.rowCount);
27020
+ lines.push(
27021
+ ` ${name}: dataset ${path}${rowCount === null ? "" : ` (${formatInteger(rowCount)} persisted rows)`}`
27022
+ );
27023
+ const dataset = datasets.find(
27024
+ (candidate) => typeof output2.datasetId === "string" && candidate.datasetId === output2.datasetId || candidate.path === path
27025
+ );
27026
+ const stepOutput = datasetSteps.map((step) => readRecord(step.output)).find(
27027
+ (candidate) => typeof output2.datasetId === "string" && candidate?.datasetId === output2.datasetId || candidate?.path === path
27028
+ );
27029
+ const preview = readRecord(stepOutput?.preview ?? dataset?.preview);
27030
+ const rows = Array.isArray(preview?.rows) ? preview.rows.slice(0, 2) : [];
27031
+ if (rows.length > 0) {
27032
+ lines.push(` sample rows (${rows.length}):`);
27033
+ lines.push(
27034
+ ...rows.map(
27035
+ (row) => ` ${clampJsonPreviewText(JSON.stringify(row) ?? String(row), 350)}`
27036
+ )
27037
+ );
27038
+ }
27039
+ continue;
27040
+ }
26895
27041
  const value = output2.value;
26896
27042
  const compacted = compactReturnValue(value);
26897
27043
  if (compacted && typeof compacted === "object") {
@@ -26901,8 +27047,8 @@ function formatPackageValueOutputLines(packaged) {
26901
27047
  lines.push(` ${name}: ${formatInlinePackageValue(value)}`);
26902
27048
  }
26903
27049
  }
26904
- if (valueOutputs.length > 8) {
26905
- lines.push(` ... ${valueOutputs.length - 8} more output(s)`);
27050
+ if (returned.length > 8) {
27051
+ lines.push(` ... ${returned.length - 8} more output(s)`);
26906
27052
  }
26907
27053
  return lines;
26908
27054
  }
@@ -26958,9 +27104,9 @@ function buildRunActivityTextLines(run) {
26958
27104
  const reason = readRecord(state.reason);
26959
27105
  if (kind === "retrying") {
26960
27106
  const attempt = typeof state.attempt === "number" ? ` (attempt ${state.attempt})` : "";
26961
- const why = typeof state.reason === "string" ? ` after ${state.reason}` : "";
27107
+ const why = typeof state.reason === "string" && state.reason !== "rate_limit" ? ` after ${state.reason}` : "";
26962
27108
  lines.push(
26963
- ` next retry: ${activityIsoTimestamp(state.retryAt) ?? "unknown"}${why}${attempt}`
27109
+ ` ${state.reason === "rate_limit" ? "next attempt" : "next retry"}: ${activityIsoTimestamp(state.retryAt) ?? "unknown"}${why}${attempt}`
26964
27110
  );
26965
27111
  } else if (kind === "scheduled") {
26966
27112
  lines.push(
@@ -27019,16 +27165,65 @@ function buildRunStatusEvidenceTextLines(packaged) {
27019
27165
  }
27020
27166
  return lines;
27021
27167
  }
27022
- function buildRecentRunLogTextLines(packaged) {
27023
- const logs = readRecord(packaged.logs);
27024
- const tail = Array.isArray(logs?.tail) ? logs.tail.filter((line) => typeof line === "string") : [];
27168
+ function formatRunTimingTextLines(run) {
27169
+ const time = (value) => typeof value === "number" || typeof value === "string" ? isoTimestamp(value) : null;
27170
+ const accepted = time(run.acceptedAt);
27171
+ const started = time(run.startedAt);
27172
+ const updated = time(run.updatedAt);
27173
+ const finished = time(run.finishedAt);
27174
+ const duration = typeof run.durationMs === "number" && Number.isFinite(run.durationMs) ? Math.max(0, Math.round(run.durationMs / 1e3)) : null;
27175
+ const age = (value) => {
27176
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
27177
+ const seconds = Math.floor((Date.now() - value) / 1e3);
27178
+ if (seconds < 0) return null;
27179
+ if (seconds < 60) return `${seconds}s`;
27180
+ if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
27181
+ if (seconds < 86400)
27182
+ return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
27183
+ return `${Math.floor(seconds / 86400)}d`;
27184
+ };
27185
+ const active = run.status === "running" || run.status === "queued" || run.status === "waiting";
27186
+ const elapsed = active ? age(run.startedAt) : null;
27187
+ const updateAge = active ? age(run.updatedAt) : null;
27188
+ if (!accepted && !started && !updated && !finished && duration === null)
27189
+ return [];
27190
+ return [
27191
+ ` time: ${[
27192
+ ...accepted ? [`accepted ${accepted}`] : [],
27193
+ ...started ? [`started ${started}`] : [],
27194
+ ...updated ? [`updated ${updated}`] : [],
27195
+ ...finished ? [`finished ${finished}`] : [],
27196
+ ...duration === null ? [] : [`duration ${duration}s`],
27197
+ ...elapsed ? [`elapsed ${elapsed}`] : [],
27198
+ ...updateAge ? [`last update ${updateAge} ago`] : []
27199
+ ].join(" \xB7 ")}`
27200
+ ];
27201
+ }
27202
+ function formatRecentRunLogLines(value) {
27203
+ const logs = readRecord(value);
27204
+ if (!logs || !Array.isArray(logs.tail)) return [];
27205
+ const tail = logs.tail.filter(
27206
+ (line) => typeof line === "string"
27207
+ );
27025
27208
  if (tail.length === 0) return [];
27026
- const visible = tail.slice(-5);
27027
- const total = typeof logs?.totalCount === "number" && Number.isFinite(logs.totalCount) ? ` of ${formatInteger(logs.totalCount)}` : "";
27028
- const lines = [` recent logs: showing ${visible.length}${total}`];
27029
- lines.push(...visible.map((line) => ` ${line}`));
27030
- if (logs?.truncated === true) {
27031
- lines.push(" older log lines were truncated by the retention cap");
27209
+ const shown = tail.map((line) => classifyLogLine(line)).filter(
27210
+ (entry) => entry.level !== "debug" && !isProviderRowWaitLogLine(entry.line)
27211
+ ).slice(-8);
27212
+ const total = readNonNegativeInteger(logs.totalCount);
27213
+ if (shown.length === 0) {
27214
+ return [
27215
+ ` recent logs: no non-debug lines in the retained preview (${total === null ? "total unknown" : `${formatInteger(total)} total`})`,
27216
+ ...logs.truncated === true ? [" [older log bodies lost to retention limit]"] : []
27217
+ ];
27218
+ }
27219
+ const lines = [
27220
+ ` recent logs (${total === null ? "count unknown" : `${formatInteger(total)} total`}; showing ${shown.length}):`,
27221
+ ...shown.map(
27222
+ (entry) => ` ${clampJsonPreviewText(formatProviderCapacityWaitLogLine(entry.line) ?? formatMapProgressDiagnosticLogLine(entry.line) ?? entry.line, 350)}`
27223
+ )
27224
+ ];
27225
+ if (logs.truncated === true) {
27226
+ lines.push(" [older log bodies lost to retention limit]");
27032
27227
  }
27033
27228
  return lines;
27034
27229
  }
@@ -27098,17 +27293,18 @@ function buildRunPackageTextLines(packaged) {
27098
27293
  if (playName && !isRuntimeLimitCheckpoint) {
27099
27294
  lines.push(` play: ${playName}`);
27100
27295
  }
27296
+ lines.push(...formatRunTimingTextLines(run));
27101
27297
  if (!isRuntimeLimitCheckpoint) {
27102
27298
  lines.push(...buildRunActivityTextLines(run));
27103
27299
  }
27104
27300
  lines.push(...buildRunStatusEvidenceTextLines(packaged));
27105
- lines.push(...buildRecentRunLogTextLines(packaged));
27106
27301
  lines.push(...formatPackageValueOutputLines(packaged));
27107
27302
  lines.push(
27108
27303
  ...formatPackageDatasetActionLines(packaged, {
27109
27304
  includeSummary: !isRuntimeLimitCheckpoint
27110
27305
  })
27111
27306
  );
27307
+ lines.push(...formatRecentRunLogLines(packaged.logs));
27112
27308
  const next = packaged.next && typeof packaged.next === "object" && !Array.isArray(packaged.next) ? packaged.next : {};
27113
27309
  const logsCommand = actionToCommand(next.logs);
27114
27310
  for (const step of isRuntimeLimitCheckpoint ? [] : readRecordArray(packaged.steps).slice(0, 8)) {
@@ -29811,6 +30007,7 @@ async function handleRunTail(args) {
29811
30007
  const jsonLines = args.includes("--jsonl");
29812
30008
  const jsonOutput = !jsonLines && argsWantJson(args);
29813
30009
  const compact = args.includes("--compact");
30010
+ const showLiveLogs = debug || hasExplicitLogLevel || !jsonOutput && !compact;
29814
30011
  const compactState = {
29815
30012
  lastLogIndex: 0,
29816
30013
  emittedRunnerStarted: false,
@@ -29830,8 +30027,8 @@ async function handleRunTail(args) {
29830
30027
  })}
29831
30028
  `
29832
30029
  );
29833
- } : compact || debug || hasExplicitLogLevel ? (event) => {
29834
- if (debug || hasExplicitLogLevel) {
30030
+ } : compact || showLiveLogs ? (event) => {
30031
+ if (showLiveLogs) {
29835
30032
  for (const line of getLogLinesFromLiveEvent(event)) {
29836
30033
  const formatted = formatPlayLogLine(
29837
30034
  line,
@@ -32035,7 +32232,9 @@ Examples:
32035
32232
  "after",
32036
32233
  `
32037
32234
  Notes:
32038
- Full run status read. Use --full --json when debugging raw stream/status fields.
32235
+ Shows per-dataset progress, recorded Deepline usage, recent logs, and the
32236
+ returned result when present. Registered sheets offer a run-scoped query
32237
+ without reading or creating dataset rows. Use --full --json for raw detail.
32039
32238
  Use --input only when you intentionally need the original payload; it can
32040
32239
  contain customer data and is never included in ordinary status output.
32041
32240
 
@@ -32143,8 +32342,9 @@ Examples:
32143
32342
  "after",
32144
32343
  `
32145
32344
  Notes:
32146
- Streams live run events until the stream ends. Use get for current status and
32147
- logs for persisted log history. In human output, --compact prints deduplicated
32345
+ Streams live run events until the stream ends. Human output shows info and
32346
+ warning logs as they arrive. Use get for current status and logs for persisted
32347
+ log history. In human output, --compact prints deduplicated
32148
32348
  step transitions and progress instead of the full event stream. --json emits
32149
32349
  one terminal package. --jsonl emits canonical live events as JSON Lines and
32150
32350
  ends with the same compact package shape as runs get --json. --log-level
package/dist/index.js CHANGED
@@ -864,7 +864,7 @@ var SDK_RELEASE = {
864
864
  // getters keep their established compatibility behavior.
865
865
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
866
866
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
867
- version: "0.3.219",
867
+ version: "0.3.220",
868
868
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
869
869
  packageCapabilities: {
870
870
  updatePreferences: 1
@@ -2872,7 +2872,11 @@ function derivePlayActivityVisibility(input) {
2872
2872
  }
2873
2873
  if (state.kind === "queued" || state.kind === "scheduled") return "headline";
2874
2874
  if (state.kind === "retrying") {
2875
- return state.retryAt - input.now <= 3e4 ? "hidden" : "timeline";
2875
+ if (state.reason === "rate_limit" && input.observation.target.kind === "capacity") {
2876
+ return "headline";
2877
+ }
2878
+ if (state.retryAt - input.now <= 3e4) return "hidden";
2879
+ return state.reason === "rate_limit" ? "headline" : "timeline";
2876
2880
  }
2877
2881
  if (state.kind === "active") return "headline";
2878
2882
  return "timeline";
@@ -2917,6 +2921,9 @@ function summarizePlayActivity(observation) {
2917
2921
  }
2918
2922
  return `Paused: ${label}; the legacy producer did not report a typed reason.`;
2919
2923
  case "retrying":
2924
+ if (state.reason === "rate_limit") {
2925
+ return `Waiting for ${label} request capacity; the run will retry automatically.`;
2926
+ }
2920
2927
  return `Delayed: ${label} will retry automatically.`;
2921
2928
  case "scheduled":
2922
2929
  return `Scheduled: ${label} will resume automatically.`;
@@ -2944,7 +2951,8 @@ function projectPlayRunActivity(input) {
2944
2951
  if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
2945
2952
  return null;
2946
2953
  }
2947
- const explicit = [...input.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
2954
+ const latestExplicit = [...input.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
2955
+ const explicit = latestExplicit?.target.kind === "capacity" && latestExplicit.target.pool === "provider" && latestExplicit.state.kind === "retrying" && latestExplicit.state.retryAt < now ? null : latestExplicit;
2948
2956
  if (explicit) return projection(explicit, now);
2949
2957
  if (input.waitKind === "detached_runner") {
2950
2958
  return projection(
package/dist/index.mjs CHANGED
@@ -768,7 +768,7 @@ var SDK_RELEASE = {
768
768
  // getters keep their established compatibility behavior.
769
769
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
770
770
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
771
- version: "0.3.219",
771
+ version: "0.3.220",
772
772
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
773
773
  packageCapabilities: {
774
774
  updatePreferences: 1
@@ -2776,7 +2776,11 @@ function derivePlayActivityVisibility(input) {
2776
2776
  }
2777
2777
  if (state.kind === "queued" || state.kind === "scheduled") return "headline";
2778
2778
  if (state.kind === "retrying") {
2779
- return state.retryAt - input.now <= 3e4 ? "hidden" : "timeline";
2779
+ if (state.reason === "rate_limit" && input.observation.target.kind === "capacity") {
2780
+ return "headline";
2781
+ }
2782
+ if (state.retryAt - input.now <= 3e4) return "hidden";
2783
+ return state.reason === "rate_limit" ? "headline" : "timeline";
2780
2784
  }
2781
2785
  if (state.kind === "active") return "headline";
2782
2786
  return "timeline";
@@ -2821,6 +2825,9 @@ function summarizePlayActivity(observation) {
2821
2825
  }
2822
2826
  return `Paused: ${label}; the legacy producer did not report a typed reason.`;
2823
2827
  case "retrying":
2828
+ if (state.reason === "rate_limit") {
2829
+ return `Waiting for ${label} request capacity; the run will retry automatically.`;
2830
+ }
2824
2831
  return `Delayed: ${label} will retry automatically.`;
2825
2832
  case "scheduled":
2826
2833
  return `Scheduled: ${label} will resume automatically.`;
@@ -2848,7 +2855,8 @@ function projectPlayRunActivity(input) {
2848
2855
  if (normalizedStatus === "completed" || normalizedStatus === "failed" || normalizedStatus === "cancelled" || normalizedStatus === "terminated" || normalizedStatus === "timed_out") {
2849
2856
  return null;
2850
2857
  }
2851
- const explicit = [...input.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
2858
+ const latestExplicit = [...input.explicit ?? []].filter((candidate) => !isTerminalActivityState(candidate.state)).sort((left, right) => right.observedAt - left.observedAt)[0];
2859
+ const explicit = latestExplicit?.target.kind === "capacity" && latestExplicit.target.pool === "provider" && latestExplicit.state.kind === "retrying" && latestExplicit.state.retryAt < now ? null : latestExplicit;
2852
2860
  if (explicit) return projection(explicit, now);
2853
2861
  if (input.waitKind === "detached_runner") {
2854
2862
  return projection(
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.219";
152
+ readonly version: "0.3.220";
153
153
  readonly updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.";
154
154
  readonly packageCapabilities: {
155
155
  readonly updatePreferences: 1;
package/dist/release.d.ts CHANGED
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.219";
152
+ readonly version: "0.3.220";
153
153
  readonly updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.";
154
154
  readonly packageCapabilities: {
155
155
  readonly updatePreferences: 1;
package/dist/release.js CHANGED
@@ -74,7 +74,7 @@ var SDK_RELEASE = {
74
74
  // getters keep their established compatibility behavior.
75
75
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
76
76
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
77
- version: "0.3.219",
77
+ version: "0.3.220",
78
78
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
79
79
  packageCapabilities: {
80
80
  updatePreferences: 1
package/dist/release.mjs CHANGED
@@ -48,7 +48,7 @@ var SDK_RELEASE = {
48
48
  // getters keep their established compatibility behavior.
49
49
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
50
50
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
51
- version: "0.3.219",
51
+ version: "0.3.220",
52
52
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
53
53
  packageCapabilities: {
54
54
  updatePreferences: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.3.219",
3
+ "version": "0.3.220",
4
4
  "description": "GTM data CLI and TypeScript SDK for coding agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://code.deepline.com",