deepline 0.3.184 → 0.3.186

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 (42) hide show
  1. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  2. package/dist/bundling-sources/sdk/src/types.ts +4 -0
  3. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +53 -0
  4. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +751 -193
  5. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +4 -0
  6. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +3 -1
  7. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +1 -0
  8. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +437 -150
  9. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +47 -4
  10. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +3 -1
  11. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +18 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +229 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +3 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/contracts.ts +16 -1
  15. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +3 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +22 -2
  17. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +6 -1
  18. package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +11 -5
  19. package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +102 -12
  20. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +8 -0
  21. package/dist/bundling-sources/shared_libs/play-runtime/runtime-telemetry.ts +9 -0
  22. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +7 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +136 -28
  24. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-scope.ts +80 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +897 -207
  26. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +271 -25
  27. package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +21 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +120 -34
  29. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +82 -2
  30. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +7 -2
  31. package/dist/cli/index.js +29 -3
  32. package/dist/cli/index.mjs +29 -3
  33. package/dist/index.d.mts +4 -0
  34. package/dist/index.d.ts +4 -0
  35. package/dist/index.js +1 -1
  36. package/dist/index.mjs +1 -1
  37. package/dist/install-integrity.json +2 -0
  38. package/dist/release.d.mts +1 -1
  39. package/dist/release.d.ts +1 -1
  40. package/dist/release.js +1 -1
  41. package/dist/release.mjs +1 -1
  42. package/package.json +1 -1
@@ -29,6 +29,8 @@ export const TOOL_EXECUTE_CONCURRENCY_BACKPRESSURE_MAX_ATTEMPTS = 65;
29
29
  // for an operation that has not opted into ordinary transient-5xx retries.
30
30
  // Keep its window aligned with other local control-plane queue signals.
31
31
  export const TOOL_EXECUTE_RUNTIME_SCHEDULER_CAPACITY_MAX_ATTEMPTS = 65;
32
+ /** Re-admission after a stale shared provider permit is safely replayable. */
33
+ export const TOOL_EXECUTE_PROVIDER_PACING_WAIT_MAX_ATTEMPTS = 65;
32
34
  export const TOOL_EXECUTE_TRANSPORT_MAX_ATTEMPTS = 3;
33
35
  export const TOOL_EXECUTE_TRANSPORT_RETRY_DELAY_MS = 1_000;
34
36
  export const TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS = 1_000;
@@ -69,6 +71,15 @@ export const TOOL_EXECUTE_RUNNER_ACCEPTS_CONCURRENCY_BACKPRESSURE =
69
71
  /** The capability tokens this runner build advertises on provider execute. */
70
72
  export const TOOL_EXECUTE_RUNNER_ACCEPTS_VALUE =
71
73
  TOOL_EXECUTE_RUNNER_ACCEPTS_CONCURRENCY_BACKPRESSURE;
74
+ /** Runner proof headers consumed only by the execution gateway. */
75
+ export const TOOL_EXECUTE_PROVIDER_RATE_SCOPE_HEADER =
76
+ 'x-deepline-provider-rate-scope';
77
+ export const TOOL_EXECUTE_PROVIDER_RATE_RETRY_SNAPSHOT_HEADER =
78
+ 'x-deepline-provider-rate-retry-snapshot';
79
+ /** Server-minted only for an internal executor's provider-owned 429. */
80
+ export const TOOL_EXECUTE_PROVIDER_THROTTLE_HEADER =
81
+ 'x-deepline-provider-throttle';
82
+ export const TOOL_EXECUTE_PROVIDER_PACING_WAIT_CODE = 'PROVIDER_PACING_WAIT';
72
83
 
73
84
  /**
74
85
  * Parse the advertisement as a comma-separated token list so a later runner can
@@ -106,6 +117,7 @@ export type ToolExecuteHttpRetryDecision = {
106
117
  | 'rate_limit'
107
118
  | 'concurrency_backpressure'
108
119
  | 'runtime_scheduler_capacity'
120
+ | 'provider_pacing_wait'
109
121
  | 'idempotency_in_progress'
110
122
  | 'gateway_invocation_in_progress'
111
123
  | 'customer_db_storage_unavailable'
@@ -122,6 +134,8 @@ export type ToolExecuteHttpFailureOutcome = ToolExecuteHttpRetryDecision & {
122
134
  fate: 'retry' | 'settle_row_failure' | 'fail_run';
123
135
  retryDelayMs: number;
124
136
  backpressureDelayMs: number | null;
137
+ /** Retry-After for known-not-dispatched gateway pacing; not provider feedback. */
138
+ providerPacingWaitMs: number | null;
125
139
  chargeRetryBudget: boolean;
126
140
  /** The response proves the provider request was never dispatched. */
127
141
  knownNotDispatched: boolean;
@@ -214,6 +228,19 @@ function isRuntimeSchedulerCapacityResponse(input: {
214
228
  );
215
229
  }
216
230
 
231
+ function isProviderPacingWaitResponse(input: {
232
+ status: number;
233
+ bodyText: string;
234
+ }): boolean {
235
+ const body = parseJsonObject(input.bodyText);
236
+ return (
237
+ input.status === 503 &&
238
+ body?.code === TOOL_EXECUTE_PROVIDER_PACING_WAIT_CODE &&
239
+ body.failure_origin === 'deepline_rate_limit' &&
240
+ body.provider_request_dispatched === false
241
+ );
242
+ }
243
+
217
244
  function idempotencyInProgressRetryDelayMs(attempt: number): number {
218
245
  return (
219
246
  TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_RETRY_DELAYS_MS[
@@ -249,6 +276,7 @@ function decideToolExecuteHttpRetry(input: {
249
276
  customerDbStorageUnavailable?: boolean;
250
277
  concurrencyBackpressure?: boolean;
251
278
  runtimeSchedulerCapacity?: boolean;
279
+ providerPacingWait?: boolean;
252
280
  hardBillingFailure?: boolean;
253
281
  hasRetryAfterHeader?: boolean;
254
282
  transientHttpRetrySafe?: boolean;
@@ -289,6 +317,13 @@ function decideToolExecuteHttpRetry(input: {
289
317
  reason: 'runtime_scheduler_capacity',
290
318
  };
291
319
  }
320
+ if (input.providerPacingWait) {
321
+ return {
322
+ retryable: true,
323
+ attemptCap: TOOL_EXECUTE_PROVIDER_PACING_WAIT_MAX_ATTEMPTS,
324
+ reason: 'provider_pacing_wait',
325
+ };
326
+ }
292
327
  if (input.gatewayInvocationInProgress) {
293
328
  return {
294
329
  retryable: true,
@@ -342,6 +377,7 @@ export function createToolExecuteHttpFailureAttemptTracker(): ToolExecuteHttpFai
342
377
  rate_limit: 0,
343
378
  concurrency_backpressure: 0,
344
379
  runtime_scheduler_capacity: 0,
380
+ provider_pacing_wait: 0,
345
381
  idempotency_in_progress: 0,
346
382
  gateway_invocation_in_progress: 0,
347
383
  customer_db_storage_unavailable: 0,
@@ -376,6 +412,10 @@ export function createToolExecuteHttpFailureAttemptTracker(): ToolExecuteHttpFai
376
412
  status: input.status,
377
413
  bodyText: input.bodyText ?? '',
378
414
  }),
415
+ providerPacingWait: isProviderPacingWaitResponse({
416
+ status: input.status,
417
+ bodyText: input.bodyText ?? '',
418
+ }),
379
419
  hasRetryAfterHeader: true,
380
420
  transientHttpRetrySafe: input.transientHttpRetrySafe === true,
381
421
  });
@@ -391,12 +431,12 @@ export function parseToolExecuteRetryAfterMs(
391
431
  ): number {
392
432
  if (!header) return TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
393
433
  const seconds = Number(header);
394
- if (Number.isFinite(seconds) && seconds > 0) {
434
+ if (Number.isFinite(seconds) && seconds >= 0) {
395
435
  return Math.ceil(seconds * 1000);
396
436
  }
397
437
  const retryAt = Date.parse(header);
398
438
  if (Number.isFinite(retryAt)) {
399
- return Math.max(1, retryAt - nowMs);
439
+ return Math.max(0, retryAt - nowMs);
400
440
  }
401
441
  return TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
402
442
  }
@@ -423,6 +463,7 @@ export function classifyToolExecuteHttpFailure(input: {
423
463
  isCustomerDbStorageUnavailableResponse(input);
424
464
  const concurrencyBackpressure = isConcurrencyBackpressureResponse(input);
425
465
  const runtimeSchedulerCapacity = isRuntimeSchedulerCapacityResponse(input);
466
+ const providerPacingWait = isProviderPacingWaitResponse(input);
426
467
  const initialRetryDecision = decideToolExecuteHttpRetry({
427
468
  status: input.status,
428
469
  idempotencyInProgress,
@@ -430,13 +471,33 @@ export function classifyToolExecuteHttpFailure(input: {
430
471
  customerDbStorageUnavailable,
431
472
  concurrencyBackpressure,
432
473
  runtimeSchedulerCapacity,
474
+ providerPacingWait,
433
475
  hasRetryAfterHeader,
434
476
  transientHttpRetrySafe,
435
477
  });
436
- const retryAfterMs = parseToolExecuteRetryAfterMs(
437
- input.retryAfterHeader,
438
- input.nowMs,
439
- );
478
+ const providerPacingWaitBody = providerPacingWait
479
+ ? parseJsonObject(input.bodyText)
480
+ : null;
481
+ const rawProviderPacingWaitMs = providerPacingWaitBody?.retry_after_ms;
482
+ const exactProviderPacingWaitMs =
483
+ typeof rawProviderPacingWaitMs === 'number' &&
484
+ Number.isFinite(rawProviderPacingWaitMs) &&
485
+ rawProviderPacingWaitMs >= 0
486
+ ? rawProviderPacingWaitMs
487
+ : null;
488
+ const attestedProviderDeadline =
489
+ providerPacingWait &&
490
+ (providerPacingWaitBody?.reason === 'retry_after' ||
491
+ providerPacingWaitBody?.reason === 'stale_permit') &&
492
+ typeof providerPacingWaitBody?.retry_at_ms === 'number' &&
493
+ Number.isFinite(providerPacingWaitBody.retry_at_ms) &&
494
+ providerPacingWaitBody.retry_at_ms > (input.nowMs ?? Date.now()) &&
495
+ exactProviderPacingWaitMs !== null &&
496
+ exactProviderPacingWaitMs > 0;
497
+ const retryAfterMs =
498
+ providerPacingWait && exactProviderPacingWaitMs !== null
499
+ ? exactProviderPacingWaitMs
500
+ : parseToolExecuteRetryAfterMs(input.retryAfterHeader, input.nowMs);
440
501
  const error = normalizeToolHttpErrorMessage({
441
502
  toolId: input.toolId,
442
503
  status: input.status,
@@ -446,7 +507,9 @@ export function classifyToolExecuteHttpFailure(input: {
446
507
  schemaVersion: input.schemaVersion,
447
508
  retryable: initialRetryDecision.retryable,
448
509
  retryAfterMs:
449
- (input.status === 429 && hasRetryAfterHeader) || runtimeSchedulerCapacity
510
+ (input.status === 429 && hasRetryAfterHeader) ||
511
+ runtimeSchedulerCapacity ||
512
+ providerPacingWait
450
513
  ? retryAfterMs
451
514
  : null,
452
515
  });
@@ -458,6 +521,11 @@ export function classifyToolExecuteHttpFailure(input: {
458
521
  error.message = `${error.message} (provider call ${Math.round(input.providerLatencyMs)}ms)`;
459
522
  }
460
523
  const hardBillingFailure = isHardBillingToolHttpError(error);
524
+ const providerOwnedRateLimit =
525
+ input.status === 429 &&
526
+ !hardBillingFailure &&
527
+ error instanceof ToolExecutionError &&
528
+ error.origin === 'provider';
461
529
  const retryDecision = decideToolExecuteHttpRetry({
462
530
  status: input.status,
463
531
  idempotencyInProgress,
@@ -465,12 +533,15 @@ export function classifyToolExecuteHttpFailure(input: {
465
533
  customerDbStorageUnavailable,
466
534
  concurrencyBackpressure,
467
535
  runtimeSchedulerCapacity,
536
+ providerPacingWait,
468
537
  hardBillingFailure,
469
538
  hasRetryAfterHeader,
470
539
  transientHttpRetrySafe,
471
540
  });
472
541
  const shouldRetry =
473
- retryDecision.retryable && input.attempt < retryDecision.attemptCap;
542
+ providerOwnedRateLimit ||
543
+ attestedProviderDeadline ||
544
+ (retryDecision.retryable && input.attempt < retryDecision.attemptCap);
474
545
  // In-attempt retry safety and later-run repairability are different
475
546
  // decisions. A non-idempotent 5xx must not be repeated automatically inside
476
547
  // this execution attempt, but an explicit later `plays run` must be able to
@@ -496,23 +567,37 @@ export function classifyToolExecuteHttpFailure(input: {
496
567
  TOOL_EXECUTE_RETRY_DELAY_MAX_MS,
497
568
  Math.max(retryAfterMs, TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS),
498
569
  )
499
- : input.status === 429
500
- ? Math.min(
501
- TOOL_EXECUTE_RATE_LIMIT_RETRY_DELAY_MAX_MS,
502
- Math.max(
503
- retryAfterMs,
504
- TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS * input.attempt,
505
- ),
506
- )
507
- : retryDecision.reason === 'idempotency_in_progress' &&
508
- !hasRetryAfterHeader
509
- ? idempotencyInProgressRetryDelayMs(input.attempt)
510
- : retryDecision.reason === 'gateway_invocation_in_progress' &&
570
+ : retryDecision.reason === 'provider_pacing_wait'
571
+ ? retryAfterMs
572
+ : input.status === 429
573
+ ? hasRetryAfterHeader
574
+ ? providerOwnedRateLimit
575
+ ? // The provider's explicit deadline is authoritative. Attempt-
576
+ // scaled fallback backoff is only for a bare 429; extending a
577
+ // valid Retry-After by the attempt number needlessly idles this
578
+ // row after the shared provider pacer has already enforced the
579
+ // deadline for every caller using the credential.
580
+ retryAfterMs
581
+ : Math.max(
582
+ retryAfterMs,
583
+ TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS * input.attempt,
584
+ )
585
+ : Math.min(
586
+ TOOL_EXECUTE_RATE_LIMIT_RETRY_DELAY_MAX_MS,
587
+ Math.max(
588
+ retryAfterMs,
589
+ TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS * input.attempt,
590
+ ),
591
+ )
592
+ : retryDecision.reason === 'idempotency_in_progress' &&
511
593
  !hasRetryAfterHeader
512
594
  ? idempotencyInProgressRetryDelayMs(input.attempt)
513
- : retryAfterMs > 0
514
- ? Math.min(TOOL_EXECUTE_RETRY_DELAY_MAX_MS, retryAfterMs)
515
- : TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
595
+ : retryDecision.reason === 'gateway_invocation_in_progress' &&
596
+ !hasRetryAfterHeader
597
+ ? idempotencyInProgressRetryDelayMs(input.attempt)
598
+ : retryAfterMs > 0
599
+ ? Math.min(TOOL_EXECUTE_RETRY_DELAY_MAX_MS, retryAfterMs)
600
+ : TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
516
601
  return {
517
602
  ...retryDecision,
518
603
  error,
@@ -528,24 +613,25 @@ export function classifyToolExecuteHttpFailure(input: {
528
613
  // caller, and malformed responses are never evidence that a provider is
529
614
  // throttling; feeding any of them into the pacer can incorrectly exhaust
530
615
  // every customer sharing that provider credential.
531
- backpressureDelayMs:
532
- input.status === 429 &&
533
- retryDecision.reason !== 'hard_billing_error' &&
534
- error instanceof ToolExecutionError &&
535
- error.origin === 'provider'
536
- ? hasRetryAfterHeader && retryAfterMs > 0
537
- ? retryAfterMs
538
- : TOOL_EXECUTE_BARE_RATE_LIMIT_BACKPRESSURE_MS
539
- : null,
616
+ backpressureDelayMs: providerOwnedRateLimit
617
+ ? hasRetryAfterHeader
618
+ ? retryAfterMs
619
+ : TOOL_EXECUTE_BARE_RATE_LIMIT_BACKPRESSURE_MS
620
+ : null,
621
+ providerPacingWaitMs:
622
+ attestedProviderDeadline && shouldRetry ? retryAfterMs : null,
540
623
  chargeRetryBudget:
541
624
  shouldRetry &&
625
+ !providerOwnedRateLimit &&
542
626
  retryDecision.reason !== 'gateway_invocation_in_progress' &&
543
627
  retryDecision.reason !== 'concurrency_backpressure' &&
544
- retryDecision.reason !== 'runtime_scheduler_capacity',
628
+ retryDecision.reason !== 'runtime_scheduler_capacity' &&
629
+ retryDecision.reason !== 'provider_pacing_wait',
545
630
  // Scheduler capacity and the relay's explicit concurrency shed both occur
546
631
  // before a provider request is dispatched. Carry that proof in the shared
547
632
  // classification so the retry boundary can safely pace either response
548
633
  // without asking a non-idempotent provider call to be replayed.
549
- knownNotDispatched: runtimeSchedulerCapacity || concurrencyBackpressure,
634
+ knownNotDispatched:
635
+ runtimeSchedulerCapacity || concurrencyBackpressure || providerPacingWait,
550
636
  };
551
637
  }
@@ -1593,6 +1593,22 @@ function serializedListRowsFromRaw(input: {
1593
1593
  return entries.length > 0 ? Object.fromEntries(entries) : undefined;
1594
1594
  }
1595
1595
 
1596
+ /**
1597
+ * V2 receipts keep the complete provider body in rawV2. Use that body as the
1598
+ * durable source for list handles instead of writing the same rows to the
1599
+ * compatibility-only listRows field.
1600
+ */
1601
+ function serializedListRowsFromRawV2(input: {
1602
+ rawV2: unknown;
1603
+ view: 'data' | 'rawV2';
1604
+ metadata: ToolResultMetadataInput;
1605
+ }): Record<string, Array<Record<string, unknown>>> | undefined {
1606
+ return serializedListRowsFromRaw({
1607
+ raw: legacyRawFromToolResponseRawV2(input.rawV2, input.view),
1608
+ metadata: input.metadata,
1609
+ });
1610
+ }
1611
+
1596
1612
  function preservedSerializedListRows(
1597
1613
  value: ToolExecuteResult,
1598
1614
  ): Record<string, Array<Record<string, unknown>>> | undefined {
@@ -1864,6 +1880,52 @@ function sameJsonValue(left: unknown, right: unknown): boolean {
1864
1880
  }
1865
1881
  }
1866
1882
 
1883
+ /**
1884
+ * New V2 receipts must not carry a second full copy of list rows. Keep the
1885
+ * optional field when the rows cannot be proven identical to the canonical
1886
+ * rawV2 body; this makes the compaction conservative for unusual or historical
1887
+ * envelopes while allowing ordinary V2 receipts to store rows exactly once.
1888
+ */
1889
+ function listRowsAreInCanonicalRawV2(input: {
1890
+ rawV2: unknown;
1891
+ view: 'data' | 'rawV2';
1892
+ metadata: ToolResultMetadataInput;
1893
+ listRows: Record<string, Array<Record<string, unknown>>> | undefined;
1894
+ }): boolean {
1895
+ if (!input.listRows || Object.keys(input.listRows).length === 0) {
1896
+ return false;
1897
+ }
1898
+ const canonicalRows = serializedListRowsFromRawV2({
1899
+ rawV2: input.rawV2,
1900
+ view: input.view,
1901
+ metadata: input.metadata,
1902
+ });
1903
+ if (!canonicalRows) return false;
1904
+ return Object.entries(input.listRows).every(([name, rows]) =>
1905
+ sameJsonValue(canonicalRows[name], rows),
1906
+ );
1907
+ }
1908
+
1909
+ function completeListRowsForDatasets(input: {
1910
+ listRows: Record<string, Array<Record<string, unknown>>> | undefined;
1911
+ listDatasets:
1912
+ | Record<string, SerializedPlayDataset<Record<string, unknown>>>
1913
+ | undefined;
1914
+ }): Record<string, Array<Record<string, unknown>>> | undefined {
1915
+ if (!input.listRows || !input.listDatasets) return undefined;
1916
+ const datasets = Object.entries(input.listDatasets);
1917
+ if (datasets.length === 0) return undefined;
1918
+ if (
1919
+ !datasets.every(([name, dataset]) => {
1920
+ const rows = input.listRows?.[name];
1921
+ return rows !== undefined && rows.length >= dataset.count;
1922
+ })
1923
+ ) {
1924
+ return undefined;
1925
+ }
1926
+ return input.listRows;
1927
+ }
1928
+
1867
1929
  function responseMetaOutsideRawV2(input: {
1868
1930
  rawV2: unknown;
1869
1931
  view: 'data' | 'rawV2';
@@ -1931,6 +1993,14 @@ export function serializeToolExecuteResult(
1931
1993
  });
1932
1994
  if (Object.prototype.hasOwnProperty.call(value.toolResponse, 'rawV2')) {
1933
1995
  const view = value.toolResponse.view ?? 'rawV2';
1996
+ const persistedListRows = listRowsAreInCanonicalRawV2({
1997
+ rawV2: value.toolResponse.rawV2,
1998
+ view,
1999
+ metadata,
2000
+ listRows,
2001
+ })
2002
+ ? undefined
2003
+ : listRows;
1934
2004
  const responseMeta = responseMetaOutsideRawV2({
1935
2005
  rawV2: value.toolResponse.rawV2,
1936
2006
  view,
@@ -1960,7 +2030,7 @@ export function serializeToolExecuteResult(
1960
2030
  ...(responseMeta ? { responseMeta } : {}),
1961
2031
  },
1962
2032
  ...(listDatasets ? { listDatasets } : {}),
1963
- ...(listRows ? { listRows } : {}),
2033
+ ...(persistedListRows ? { listRows: persistedListRows } : {}),
1964
2034
  ...(targetValues ? { targetValues } : {}),
1965
2035
  metadata,
1966
2036
  execution: value._metadata.execution,
@@ -2023,6 +2093,16 @@ export function deserializeToolExecuteResult(
2023
2093
  )
2024
2094
  ? value.toolResponse.legacyRaw
2025
2095
  : raw;
2096
+ const listRows =
2097
+ value.listRows ??
2098
+ completeListRowsForDatasets({
2099
+ listRows: serializedListRowsFromRawV2({
2100
+ rawV2,
2101
+ view,
2102
+ metadata: value.metadata,
2103
+ }),
2104
+ listDatasets: value.listDatasets,
2105
+ });
2026
2106
  return applySerializedListDatasets(
2027
2107
  applySerializedTargetValues(
2028
2108
  createToolExecuteResult({
@@ -2045,7 +2125,7 @@ export function deserializeToolExecuteResult(
2045
2125
  value.targetValues,
2046
2126
  ),
2047
2127
  value.listDatasets,
2048
- value.listRows,
2128
+ listRows,
2049
2129
  );
2050
2130
  }
2051
2131
  return applySerializedListDatasets(
@@ -119,7 +119,7 @@ export type SerializedToolExecuteResultV1 = {
119
119
  meta?: Record<string, unknown>;
120
120
  };
121
121
  listDatasets?: Record<string, SerializedPlayDataset<Record<string, unknown>>>;
122
- /** Full declared list rows used to rehydrate list Dataset Handles. */
122
+ /** Full declared list rows retained by historical V1 receipts. */
123
123
  listRows?: Record<string, Array<Record<string, unknown>>>;
124
124
  /** Computed scalar/object getters preserved before raw list previews are clipped. */
125
125
  targetValues?: Record<string, ToolResultTargetMetadata>;
@@ -133,7 +133,7 @@ export type SerializedToolExecuteResultV1 = {
133
133
  */
134
134
  export type SerializedToolExecuteResultV2 = Omit<
135
135
  SerializedToolExecuteResultV1,
136
- '__kind' | 'toolResponse'
136
+ '__kind' | 'toolResponse' | 'listRows'
137
137
  > & {
138
138
  __kind: 'deepline.tool_execute_result.v2';
139
139
  toolResponse: {
@@ -144,6 +144,11 @@ export type SerializedToolExecuteResultV2 = Omit<
144
144
  /** Deepline-owned additions not already represented in `rawV2.meta`. */
145
145
  responseMeta?: Record<string, unknown>;
146
146
  };
147
+ /**
148
+ * Compatibility fallback for older V2 receipts whose rawV2 body was not
149
+ * complete. New V2 receipts derive list rows from rawV2 and omit this copy.
150
+ */
151
+ listRows?: Record<string, Array<Record<string, unknown>>>;
147
152
  };
148
153
 
149
154
  export type SerializedToolExecuteResult =
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.184",
3054
+ version: "0.3.186",
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
@@ -27485,7 +27485,9 @@ function readLiveCronMetadata(play) {
27485
27485
  return {
27486
27486
  schedule: typeof metadata?.cronSchedule === "string" ? metadata.cronSchedule : null,
27487
27487
  timezone: typeof metadata?.cronTimezone === "string" ? metadata.cronTimezone : null,
27488
- nextScheduledAt: typeof metadata?.nextScheduledAt === "number" ? metadata.nextScheduledAt : null
27488
+ nextScheduledAt: typeof metadata?.nextScheduledAt === "number" ? metadata.nextScheduledAt : null,
27489
+ blockedAt: typeof metadata?.blockedAt === "number" ? metadata.blockedAt : null,
27490
+ blockedReasonCode: typeof metadata?.blockedReasonCode === "string" ? metadata.blockedReasonCode : null
27489
27491
  };
27490
27492
  }
27491
27493
  function liveTriggerStatusLines(status, play) {
@@ -27504,6 +27506,18 @@ function liveTriggerStatusLines(status, play) {
27504
27506
  }
27505
27507
  if (status?.blockedReason) {
27506
27508
  lines.push(` Schedule issue: ${status.blockedReason}`);
27509
+ if (status.blockedReasonCode || cron.blockedReasonCode) {
27510
+ lines.push(
27511
+ ` Schedule issue code: ${status.blockedReasonCode ?? cron.blockedReasonCode}`
27512
+ );
27513
+ }
27514
+ const blockedAt = status.blockedAt ?? cron.blockedAt;
27515
+ if (blockedAt !== null && blockedAt !== void 0) {
27516
+ lines.push(` Schedule blocked at: ${formatTimestamp(blockedAt)}`);
27517
+ }
27518
+ lines.push(
27519
+ " Recovery: republish the live revision to re-arm this schedule after the platform issue is fixed."
27520
+ );
27507
27521
  }
27508
27522
  }
27509
27523
  if (status?.webhook) {
@@ -27516,7 +27530,9 @@ function triggerStatusFromMetadata(value) {
27516
27530
  return {
27517
27531
  cron: typeof metadata?.cronStatus === "string" ? metadata.cronStatus : null,
27518
27532
  webhook: typeof metadata?.webhookStatus === "string" ? metadata.webhookStatus : null,
27519
- blockedReason: typeof metadata?.blockedReason === "string" ? metadata.blockedReason : null
27533
+ blockedReason: typeof metadata?.blockedReason === "string" ? metadata.blockedReason : null,
27534
+ blockedReasonCode: typeof metadata?.blockedReasonCode === "string" ? metadata.blockedReasonCode : null,
27535
+ blockedAt: typeof metadata?.blockedAt === "number" ? metadata.blockedAt : null
27520
27536
  };
27521
27537
  }
27522
27538
  function printPublishReceipt(input2) {
@@ -29318,6 +29334,16 @@ async function handlePlayList(args) {
29318
29334
  );
29319
29335
  if (play.triggerStatus.blockedReason) {
29320
29336
  lines.push(` schedule issue: ${play.triggerStatus.blockedReason}`);
29337
+ if (play.triggerStatus.blockedReasonCode) {
29338
+ lines.push(
29339
+ ` schedule issue code: ${play.triggerStatus.blockedReasonCode}`
29340
+ );
29341
+ }
29342
+ if (play.triggerStatus.blockedAt !== void 0) {
29343
+ lines.push(
29344
+ ` schedule blocked at: ${formatTimestamp(play.triggerStatus.blockedAt)}`
29345
+ );
29346
+ }
29321
29347
  }
29322
29348
  } else {
29323
29349
  lines.push(" scheduled execution: not configured");
@@ -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.184",
3049
+ version: "0.3.186",
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
@@ -27557,7 +27557,9 @@ function readLiveCronMetadata(play) {
27557
27557
  return {
27558
27558
  schedule: typeof metadata?.cronSchedule === "string" ? metadata.cronSchedule : null,
27559
27559
  timezone: typeof metadata?.cronTimezone === "string" ? metadata.cronTimezone : null,
27560
- nextScheduledAt: typeof metadata?.nextScheduledAt === "number" ? metadata.nextScheduledAt : null
27560
+ nextScheduledAt: typeof metadata?.nextScheduledAt === "number" ? metadata.nextScheduledAt : null,
27561
+ blockedAt: typeof metadata?.blockedAt === "number" ? metadata.blockedAt : null,
27562
+ blockedReasonCode: typeof metadata?.blockedReasonCode === "string" ? metadata.blockedReasonCode : null
27561
27563
  };
27562
27564
  }
27563
27565
  function liveTriggerStatusLines(status, play) {
@@ -27576,6 +27578,18 @@ function liveTriggerStatusLines(status, play) {
27576
27578
  }
27577
27579
  if (status?.blockedReason) {
27578
27580
  lines.push(` Schedule issue: ${status.blockedReason}`);
27581
+ if (status.blockedReasonCode || cron.blockedReasonCode) {
27582
+ lines.push(
27583
+ ` Schedule issue code: ${status.blockedReasonCode ?? cron.blockedReasonCode}`
27584
+ );
27585
+ }
27586
+ const blockedAt = status.blockedAt ?? cron.blockedAt;
27587
+ if (blockedAt !== null && blockedAt !== void 0) {
27588
+ lines.push(` Schedule blocked at: ${formatTimestamp(blockedAt)}`);
27589
+ }
27590
+ lines.push(
27591
+ " Recovery: republish the live revision to re-arm this schedule after the platform issue is fixed."
27592
+ );
27579
27593
  }
27580
27594
  }
27581
27595
  if (status?.webhook) {
@@ -27588,7 +27602,9 @@ function triggerStatusFromMetadata(value) {
27588
27602
  return {
27589
27603
  cron: typeof metadata?.cronStatus === "string" ? metadata.cronStatus : null,
27590
27604
  webhook: typeof metadata?.webhookStatus === "string" ? metadata.webhookStatus : null,
27591
- blockedReason: typeof metadata?.blockedReason === "string" ? metadata.blockedReason : null
27605
+ blockedReason: typeof metadata?.blockedReason === "string" ? metadata.blockedReason : null,
27606
+ blockedReasonCode: typeof metadata?.blockedReasonCode === "string" ? metadata.blockedReasonCode : null,
27607
+ blockedAt: typeof metadata?.blockedAt === "number" ? metadata.blockedAt : null
27592
27608
  };
27593
27609
  }
27594
27610
  function printPublishReceipt(input2) {
@@ -29390,6 +29406,16 @@ async function handlePlayList(args) {
29390
29406
  );
29391
29407
  if (play.triggerStatus.blockedReason) {
29392
29408
  lines.push(` schedule issue: ${play.triggerStatus.blockedReason}`);
29409
+ if (play.triggerStatus.blockedReasonCode) {
29410
+ lines.push(
29411
+ ` schedule issue code: ${play.triggerStatus.blockedReasonCode}`
29412
+ );
29413
+ }
29414
+ if (play.triggerStatus.blockedAt !== void 0) {
29415
+ lines.push(
29416
+ ` schedule blocked at: ${formatTimestamp(play.triggerStatus.blockedAt)}`
29417
+ );
29418
+ }
29393
29419
  }
29394
29420
  } else {
29395
29421
  lines.push(" scheduled execution: not configured");
package/dist/index.d.mts CHANGED
@@ -2207,6 +2207,8 @@ interface PlayDefinitionDetail {
2207
2207
  cronTimezone?: string | null;
2208
2208
  nextScheduledAt?: number | null;
2209
2209
  lastScheduledAt?: number | null;
2210
+ blockedAt?: number | null;
2211
+ blockedReasonCode?: string | null;
2210
2212
  blockedReason?: string | null;
2211
2213
  [key: string]: unknown;
2212
2214
  } | null;
@@ -2270,6 +2272,8 @@ interface PlayTriggerStatus {
2270
2272
  cron: string | null;
2271
2273
  webhook: string | null;
2272
2274
  blockedReason: string | null;
2275
+ blockedReasonCode?: string;
2276
+ blockedAt?: number;
2273
2277
  }
2274
2278
  interface ProductNotificationEventDefinition {
2275
2279
  id: string;
package/dist/index.d.ts CHANGED
@@ -2207,6 +2207,8 @@ interface PlayDefinitionDetail {
2207
2207
  cronTimezone?: string | null;
2208
2208
  nextScheduledAt?: number | null;
2209
2209
  lastScheduledAt?: number | null;
2210
+ blockedAt?: number | null;
2211
+ blockedReasonCode?: string | null;
2210
2212
  blockedReason?: string | null;
2211
2213
  [key: string]: unknown;
2212
2214
  } | null;
@@ -2270,6 +2272,8 @@ interface PlayTriggerStatus {
2270
2272
  cron: string | null;
2271
2273
  webhook: string | null;
2272
2274
  blockedReason: string | null;
2275
+ blockedReasonCode?: string;
2276
+ blockedAt?: number;
2273
2277
  }
2274
2278
  interface ProductNotificationEventDefinition {
2275
2279
  id: string;
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.184",
867
+ version: "0.3.186",
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
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.184",
771
+ version: "0.3.186",
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
@@ -209,6 +209,7 @@
209
209
  "dist/bundling-sources/shared_libs/play-runtime/internal-bootstrap-token.ts",
210
210
  "dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts",
211
211
  "dist/bundling-sources/shared_libs/play-runtime/lane-retirement-gate.ts",
212
+ "dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts",
212
213
  "dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts",
213
214
  "dist/bundling-sources/shared_libs/play-runtime/lease-policy.ts",
214
215
  "dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts",
@@ -388,6 +389,7 @@
388
389
  "dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-budget-state.ts",
389
390
  "dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts",
390
391
  "dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts",
392
+ "dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-scope.ts",
391
393
  "dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts",
392
394
  "dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts",
393
395
  "dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-completion-coalescer.ts",
@@ -149,7 +149,7 @@ type SdkRelease = {
149
149
  supportPolicy: SdkSupportPolicy;
150
150
  };
151
151
  declare const SDK_RELEASE: {
152
- readonly version: "0.3.184";
152
+ readonly version: "0.3.186";
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;