deepline 0.3.409 → 0.3.411

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 (215) hide show
  1. package/dist/bundling-sources/sdk/src/agent-runtime.ts +18 -1
  2. package/dist/bundling-sources/sdk/src/client.ts +206 -333
  3. package/dist/bundling-sources/sdk/src/compat.ts +45 -2
  4. package/dist/bundling-sources/sdk/src/db/query.ts +9 -10
  5. package/dist/bundling-sources/sdk/src/http.ts +38 -20
  6. package/dist/bundling-sources/sdk/src/index.ts +4 -5
  7. package/dist/bundling-sources/sdk/src/play.ts +10 -10
  8. package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +6 -4
  9. package/dist/bundling-sources/sdk/src/plays/check-local-play-graph.ts +114 -0
  10. package/dist/bundling-sources/sdk/src/plays/client.ts +431 -0
  11. package/dist/bundling-sources/sdk/src/plays/local-play-execution.ts +2 -2
  12. package/dist/bundling-sources/sdk/src/plays/run-request.ts +106 -16
  13. package/dist/bundling-sources/sdk/src/release.ts +13 -7
  14. package/dist/bundling-sources/sdk/src/runs/read-errors.ts +8 -0
  15. package/dist/bundling-sources/sdk/src/runs/watch-polling.ts +124 -13
  16. package/dist/bundling-sources/sdk/src/tool-calls.ts +108 -19
  17. package/dist/bundling-sources/sdk/src/types.ts +18 -0
  18. package/dist/bundling-sources/shared_libs/integration-contracts/execute-retry-contract.ts +37 -0
  19. package/dist/bundling-sources/shared_libs/integration-contracts/package.json +3 -0
  20. package/dist/bundling-sources/shared_libs/monitors/package.json +1 -1
  21. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +3 -1
  22. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +1 -1
  23. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +277 -76
  24. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +6 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/dataset-row-input.ts +124 -0
  26. package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +6 -62
  27. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +1 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/durable-tool-identity.ts +67 -0
  29. package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +64 -6
  30. package/dist/bundling-sources/shared_libs/play-runtime/freshness-receipt-execution.ts +1 -5
  31. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +1 -1
  32. package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +3 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/play-http-request.ts +10 -0
  34. package/dist/bundling-sources/shared_libs/play-runtime/query-result-dataset.ts +3 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +3 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +26 -16
  37. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +36 -11
  38. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +35 -0
  39. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +21 -0
  40. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +21 -6
  41. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +11 -2
  42. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +85 -20
  43. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +71 -13
  44. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-execution-queries.ts +100 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +9 -5
  46. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +337 -146
  47. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +26 -12
  48. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +3 -1
  49. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +425 -102
  50. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +4 -0
  52. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +9 -0
  53. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +181 -124
  54. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-worker-wake.ts +152 -0
  55. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +5 -3
  56. package/dist/bundling-sources/shared_libs/play-runtime/tool-cache-policy.ts +31 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +10 -0
  58. package/dist/bundling-sources/shared_libs/plays/ambiguous-write-error.ts +25 -0
  59. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -0
  60. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +63 -68
  61. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +129 -63
  62. package/dist/bundling-sources/shared_libs/plays/contracts.ts +14 -0
  63. package/dist/bundling-sources/shared_libs/plays/enrich-play-compiler.ts +58 -16
  64. package/dist/bundling-sources/shared_libs/plays/fetch-http-error.ts +50 -0
  65. package/dist/bundling-sources/shared_libs/plays/source-authoring-edition.ts +351 -0
  66. package/dist/bundling-sources/shared_libs/plays/tool-list-getter-mode.ts +9 -0
  67. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
  68. package/dist/cli/auth-M7TBLW55.js +40 -0
  69. package/dist/cli/{auth-5HIIACF7.mjs → auth-YD6ZTMB2.mjs} +6 -6
  70. package/dist/cli/{billing-4275N7FL.js → billing-2L3MOB42.js} +84 -84
  71. package/dist/cli/{billing-EVZ3ZWKC.mjs → billing-ZT46GV4C.mjs} +8 -8
  72. package/dist/cli/{chunk-ZAAKSJAS.js → chunk-27GJKC5Q.js} +17 -10
  73. package/dist/cli/{chunk-UHNDVD3P.js → chunk-2H4EY7KH.js} +100 -41
  74. package/dist/cli/{chunk-GAICVLKL.js → chunk-2NI6DHN7.js} +2 -2
  75. package/dist/cli/{chunk-JGHG4NBA.js → chunk-2WUY3VNK.js} +19 -4
  76. package/dist/cli/{chunk-FHPCKULR.mjs → chunk-4BA6ATHA.mjs} +2 -2
  77. package/dist/cli/{chunk-RTCDW2GU.js → chunk-4O4WNFFC.js} +170 -49
  78. package/dist/cli/{chunk-OSDXE27V.mjs → chunk-4PG4ARL2.mjs} +17 -10
  79. package/dist/cli/{chunk-AU4OFDFX.js → chunk-5IGDNBG7.js} +26 -26
  80. package/dist/cli/{chunk-WYQO2CBS.mjs → chunk-5LRWWMRV.mjs} +149 -28
  81. package/dist/cli/{chunk-PMVFAYL7.mjs → chunk-63ILLN5H.mjs} +2 -2
  82. package/dist/cli/chunk-6AUE6JXY.js +35 -0
  83. package/dist/cli/chunk-7DSMMCXP.js +501 -0
  84. package/dist/cli/{chunk-6BJK4EJ3.mjs → chunk-AARWVK4C.mjs} +2132 -65
  85. package/dist/cli/{chunk-FERRDNMO.js → chunk-AD47BXN2.js} +5 -5
  86. package/dist/cli/{chunk-J6DCKJNM.mjs → chunk-BJV3VSKE.mjs} +16 -1
  87. package/dist/cli/{chunk-S6R3OX7B.js → chunk-E4CABWXL.js} +25 -2
  88. package/dist/cli/{chunk-NXGCO4JB.mjs → chunk-E4IXDAZI.mjs} +5 -0
  89. package/dist/cli/{chunk-BEVLCKXG.mjs → chunk-E4KBNNNB.mjs} +1 -1
  90. package/dist/cli/{chunk-2PRO2JTX.mjs → chunk-E52TKKVI.mjs} +36 -284
  91. package/dist/cli/chunk-FR2ILQ4G.mjs +8 -0
  92. package/dist/cli/{chunk-2GI3QD3L.js → chunk-FRVPOXGB.js} +644 -330
  93. package/dist/cli/chunk-G43JLBDE.mjs +501 -0
  94. package/dist/cli/{chunk-BZAMOCPA.mjs → chunk-IMZ56EOH.mjs} +3 -3
  95. package/dist/cli/chunk-IPGV6VFA.mjs +6084 -0
  96. package/dist/cli/{chunk-IT3XBJQR.mjs → chunk-IR3AKJAY.mjs} +330 -625
  97. package/dist/cli/chunk-J33TSWO5.js +8 -0
  98. package/dist/cli/chunk-JQMZUWNM.mjs +35 -0
  99. package/dist/cli/chunk-JYHSEGRM.js +6084 -0
  100. package/dist/cli/{chunk-JI2B4RZP.mjs → chunk-KCC3FKIW.mjs} +71 -12
  101. package/dist/cli/{chunk-6IKARAYD.mjs → chunk-L2VKAASU.mjs} +23 -0
  102. package/dist/cli/{chunk-O3VSXP2F.js → chunk-LWBM5FFL.js} +50 -50
  103. package/dist/cli/{chunk-VWBTTJYQ.mjs → chunk-M6OASCVL.mjs} +6 -3
  104. package/dist/cli/{chunk-YHPYUZZX.mjs → chunk-MAMVGOSC.mjs} +1 -1
  105. package/dist/cli/{chunk-Q2E4E4FJ.js → chunk-NPBJI7RE.js} +8 -8
  106. package/dist/cli/chunk-NQWIZ5PZ.js +313 -0
  107. package/dist/cli/{chunk-HQXL5526.mjs → chunk-NUX2QHNC.mjs} +1 -1
  108. package/dist/cli/{chunk-TQNHMWUR.mjs → chunk-OGSXENOF.mjs} +5 -2
  109. package/dist/cli/{chunk-SEFMGO3Z.js → chunk-OQQOXSYA.js} +2184 -117
  110. package/dist/cli/{chunk-FJCIUF34.js → chunk-OZSC6CEW.js} +128 -376
  111. package/dist/cli/{chunk-NZSF57UO.mjs → chunk-PO2VU6WV.mjs} +2 -2
  112. package/dist/cli/{chunk-7P5AA3SN.js → chunk-PPDBRJRW.js} +6 -1
  113. package/dist/cli/{chunk-ILHRA7AD.js → chunk-QADCFSGH.js} +7 -7
  114. package/dist/cli/{chunk-N44JHMKY.mjs → chunk-RFES6Q2J.mjs} +452 -138
  115. package/dist/cli/{chunk-DEC3JECC.js → chunk-RMINBDYY.js} +5 -2
  116. package/dist/cli/{chunk-WLOCMJWV.js → chunk-TPFD4F5S.js} +426 -721
  117. package/dist/cli/{chunk-V76R6HMV.js → chunk-U5AQKE3T.js} +1029 -806
  118. package/dist/cli/{chunk-PBZYY7VZ.mjs → chunk-UAEVKAUR.mjs} +734 -511
  119. package/dist/cli/{chunk-WHG43Z67.js → chunk-VGHWJL4W.js} +11 -8
  120. package/dist/cli/chunk-VKKVSFRD.js +62 -0
  121. package/dist/cli/{chunk-GSK6NHVM.js → chunk-WU4U6VSB.js} +5 -5
  122. package/dist/cli/chunk-XAB47ZRV.mjs +313 -0
  123. package/dist/cli/{chunk-JRAVVJ3T.mjs → chunk-XJD6LZCO.mjs} +2 -2
  124. package/dist/cli/chunk-ZCALLYF6.mjs +62 -0
  125. package/dist/cli/{chunk-YD7B53RW.js → chunk-ZHWBU36H.js} +12 -12
  126. package/dist/cli/{csv-A2MP6EFV.mjs → csv-BKNRRW7D.mjs} +5 -5
  127. package/dist/cli/{csv-BBOTCGQY.js → csv-SVDP2EU7.js} +14 -14
  128. package/dist/cli/{db-3W5DMTUX.mjs → db-LU4KLRM6.mjs} +15 -20
  129. package/dist/cli/{db-G4CODDCA.js → db-OQ6S7TTZ.js} +42 -47
  130. package/dist/cli/{describe-PQTQ5B6F.js → describe-45TGETKR.js} +27 -22
  131. package/dist/cli/{describe-XYJ2ZT4M.mjs → describe-U4KOGDRA.mjs} +20 -15
  132. package/dist/cli/describe-core.d.mts +2 -2
  133. package/dist/cli/describe-core.d.ts +2 -2
  134. package/dist/cli/describe-core.js +6 -6
  135. package/dist/cli/describe-core.mjs +5 -5
  136. package/dist/cli/{executions-UR67CA5H.mjs → executions-2GAAUXLA.mjs} +8 -8
  137. package/dist/cli/{executions-TLANVR7Y.js → executions-VZN56VRC.js} +10 -10
  138. package/dist/cli/{feedback-6C2YTRJL.js → feedback-NS76B5GU.js} +13 -9
  139. package/dist/cli/{feedback-WHCMGEIL.mjs → feedback-XW5IWA5R.mjs} +11 -7
  140. package/dist/cli/{git-GWLB6VSA.mjs → git-CLI66XP6.mjs} +6 -6
  141. package/dist/cli/git-VGYRGFEN.js +24 -0
  142. package/dist/cli/index.js +236 -348
  143. package/dist/cli/index.mjs +162 -274
  144. package/dist/cli/{legacy-noops-ZUFA7RWI.js → legacy-noops-HCFB3ZOV.js} +9 -9
  145. package/dist/cli/{legacy-noops-KF4XIFEF.mjs → legacy-noops-ODDOMLBL.mjs} +6 -6
  146. package/dist/cli/{monitors-TB3K2IVE.js → monitors-7WXQ7JFT.js} +94 -94
  147. package/dist/cli/{monitors-6UOIDIMB.mjs → monitors-ZXX456TE.mjs} +8 -8
  148. package/dist/cli/{org-CKWMBPIR.js → org-YLX5PHBQ.js} +68 -68
  149. package/dist/cli/{org-WGHHMVDZ.mjs → org-YUN3TLNP.mjs} +8 -8
  150. package/dist/cli/{play-LYPAXCLD.mjs → play-LL73A7EP.mjs} +533 -98
  151. package/dist/cli/{play-N2B3KAVS.js → play-YGOXL52D.js} +1067 -632
  152. package/dist/cli/{providers-6DI5BVZJ.mjs → providers-35QSAUHL.mjs} +8 -8
  153. package/dist/cli/{providers-UR42MD6Z.js → providers-RHCIU2PX.js} +11 -11
  154. package/dist/cli/{quickstart-MNA2S6PO.mjs → quickstart-6BN3LCZH.mjs} +5 -5
  155. package/dist/cli/{quickstart-FCJG4XGB.js → quickstart-ORMM4NRK.js} +7 -7
  156. package/dist/cli/search-EWDMUPHR.js +30 -0
  157. package/dist/cli/{search-VPPYUJ2M.mjs → search-GAERWLSE.mjs} +9 -9
  158. package/dist/cli/{secrets-QOSMVO36.js → secrets-3AFCTGT7.js} +17 -17
  159. package/dist/cli/{secrets-DRI4W7Z5.mjs → secrets-FCL5PALY.mjs} +8 -8
  160. package/dist/cli/sessions-3OEHEQG7.js +16 -0
  161. package/dist/cli/{sessions-DQNUKP43.mjs → sessions-RSSL7I7O.mjs} +6 -6
  162. package/dist/cli/{settings-DWDK3Y2R.mjs → settings-GE4NRE7Y.mjs} +12 -12
  163. package/dist/cli/{settings-JUGGCOPS.js → settings-RX5K4I7H.js} +79 -79
  164. package/dist/cli/{setup-AWBHNYXK.js → setup-N3ZNAEL5.js} +45 -44
  165. package/dist/cli/{setup-D5DWVNY4.mjs → setup-X3RXGG4F.mjs} +11 -10
  166. package/dist/cli/{skills-YV2XR35J.mjs → skills-5JEAJBDE.mjs} +7 -7
  167. package/dist/cli/skills-VAAQVEQC.js +29 -0
  168. package/dist/cli/tools-BYYOT2DU.js +44 -0
  169. package/dist/cli/{tools-VFJYHNV2.mjs → tools-JOKUWEBZ.mjs} +19 -14
  170. package/dist/cli/update-36G4ZD7B.js +31 -0
  171. package/dist/cli/{update-IM6VOTGL.mjs → update-UBHEVFR3.mjs} +11 -9
  172. package/dist/cli/{workflow-26URBWPV.mjs → workflow-FR6EXAXF.mjs} +44 -20
  173. package/dist/cli/{workflow-3BS6U6SL.js → workflow-SZAVOHN6.js} +54 -30
  174. package/dist/{client-BfInrZPB.d.mts → client-74k4IPh6.d.mts} +135 -54
  175. package/dist/{client-BMjJFpan.d.ts → client-C1IK1f8c.d.ts} +135 -54
  176. package/dist/{compiler-manifest-Ycx-hoAr.d.mts → compiler-manifest-lzWpbV3w.d.mts} +83 -66
  177. package/dist/{compiler-manifest-Ycx-hoAr.d.ts → compiler-manifest-lzWpbV3w.d.ts} +83 -66
  178. package/dist/{index-CZXgiN3E.d.mts → index-C8Cy-YTm.d.ts} +5 -1
  179. package/dist/{index-NPG5pqxQ.d.ts → index-CtNK-0nI.d.mts} +5 -1
  180. package/dist/index.d.mts +47 -9
  181. package/dist/index.d.ts +47 -9
  182. package/dist/index.js +17 -14
  183. package/dist/index.mjs +13 -10
  184. package/dist/install-integrity.json +118 -102
  185. package/dist/plays/bundle-play-file.d.mts +3 -3
  186. package/dist/plays/bundle-play-file.d.ts +3 -3
  187. package/dist/plays/bundle-play-file.mjs +5 -4
  188. package/dist/plays/csv-data-input.js +3 -3
  189. package/dist/plays/csv-data-input.mjs +2 -2
  190. package/dist/plays/play-description.d.mts +2 -2
  191. package/dist/plays/play-description.d.ts +2 -2
  192. package/dist/plays/run-request.d.mts +2 -2
  193. package/dist/plays/run-request.d.ts +2 -2
  194. package/dist/plays/run-request.js +11 -3
  195. package/dist/plays/run-request.mjs +10 -2
  196. package/dist/release.d.mts +15 -6
  197. package/dist/release.d.ts +15 -6
  198. package/dist/release.js +2 -2
  199. package/dist/release.mjs +1 -1
  200. package/package.json +2 -2
  201. package/dist/cli/auth-F6BX32XZ.js +0 -40
  202. package/dist/cli/chunk-264PC2RN.mjs +0 -83
  203. package/dist/cli/chunk-44ZTYHMQ.mjs +0 -155
  204. package/dist/cli/chunk-53HN7WZN.js +0 -392
  205. package/dist/cli/chunk-7AALNGTA.mjs +0 -392
  206. package/dist/cli/chunk-ALD4COBH.js +0 -155
  207. package/dist/cli/chunk-CLJGSOVM.mjs +0 -1716
  208. package/dist/cli/chunk-WNUR6VP5.js +0 -83
  209. package/dist/cli/chunk-Z4VNJOF7.js +0 -1716
  210. package/dist/cli/git-VQFF6D7C.js +0 -24
  211. package/dist/cli/search-NCEEONMQ.js +0 -30
  212. package/dist/cli/sessions-3WYKQABW.js +0 -16
  213. package/dist/cli/skills-AKPAJVSO.js +0 -29
  214. package/dist/cli/tools-RBKEK6PM.js +0 -39
  215. package/dist/cli/update-VFNUBLDA.js +0 -29
@@ -1,6 +1,14 @@
1
1
  import { DeeplineError } from '../errors';
2
2
 
3
3
  export function isTransientPlayRunReadError(error: unknown): boolean {
4
+ // The HTTP failure is diagnostic; an unconfirmed admission has no identity
5
+ // that makes repeating it safe, even when its response was a 5xx.
6
+ if (
7
+ error instanceof DeeplineError &&
8
+ error.code === 'PLAY_START_OUTCOME_UNKNOWN'
9
+ ) {
10
+ return false;
11
+ }
4
12
  if (
5
13
  error instanceof DeeplineError &&
6
14
  error.code === 'PLAY_STREAM_NETWORK_ABORTED'
@@ -9,21 +9,37 @@ import {
9
9
  } from '../../../shared_libs/play-runtime/run-snapshot-stream.js';
10
10
  import { isTransientPlayRunReadError } from './read-errors';
11
11
 
12
- /** The watch endpoint is a small authenticated REST read, polled every two seconds. */
12
+ /** Steady-state cadence for the small authenticated REST snapshot. */
13
13
  export const RUN_WATCH_POLL_INTERVAL_MS = 2_000;
14
+ const RUN_WATCH_STARTUP_POLL_INTERVAL_MS = 500;
15
+ const RUN_WATCH_STARTUP_WINDOW_MS = 6_000;
14
16
 
15
17
  type WatchHttp = {
16
18
  get<T = unknown>(
17
19
  path: string,
18
- options?: { signal?: AbortSignal },
20
+ options?: {
21
+ signal?: AbortSignal;
22
+ onResponse?: (response: Response) => void;
23
+ },
19
24
  ): Promise<T>;
20
25
  };
21
26
 
27
+ export type WatchPollObservation = {
28
+ poll: number;
29
+ durationMs: number;
30
+ status?: number;
31
+ serverTiming?: string;
32
+ };
33
+
22
34
  export type WatchRunEventsOptions = {
23
35
  http: WatchHttp;
24
36
  runId: string;
25
37
  signal?: AbortSignal;
26
- /** @internal Test seam; production callers use the fixed two-second cadence. */
38
+ /** Defer log-store reads until the run is terminal; the final log tail is unchanged. */
39
+ deferLogs?: boolean;
40
+ /** Skip log-store reads entirely for consumers that never render run logs. */
41
+ omitTerminalLogs?: boolean;
42
+ /** @internal Test seam; overrides the entire adaptive cadence. */
27
43
  pollIntervalMs?: number;
28
44
  onNotice?: (message: string) => void;
29
45
  onRetry?: (info: {
@@ -31,11 +47,24 @@ export type WatchRunEventsOptions = {
31
47
  delayMs: number;
32
48
  reason: string;
33
49
  }) => void;
50
+ /** @internal Exposes bounded request timing for CLI diagnostics. */
51
+ onPoll?: (observation: WatchPollObservation) => void;
52
+ /** @internal Request the existing status response on the terminal poll. */
53
+ terminalStatus?: {
54
+ full?: boolean;
55
+ billing?: boolean;
56
+ runStatus?: boolean;
57
+ onStatus: (
58
+ response: Record<string, unknown>,
59
+ status: string,
60
+ ) => void | Promise<void>;
61
+ };
34
62
  };
35
63
 
36
64
  type WatchSnapshotResponse = {
37
65
  runId: string;
38
66
  snapshot: PlayRunLiveSnapshot;
67
+ terminalStatus?: Record<string, unknown>;
39
68
  };
40
69
 
41
70
  type WatchRunLogPage = {
@@ -83,7 +112,24 @@ function readSnapshotResponse(
83
112
  ) {
84
113
  throw new Error(`Run watch returned an invalid snapshot for ${runId}.`);
85
114
  }
86
- return { runId, snapshot: snapshot as PlayRunLiveSnapshot };
115
+ if (
116
+ record.terminalStatus !== undefined &&
117
+ (!record.terminalStatus ||
118
+ typeof record.terminalStatus !== 'object' ||
119
+ Array.isArray(record.terminalStatus) ||
120
+ !isTerminalPlayRunLiveStatus((snapshot as PlayRunLiveSnapshot).status))
121
+ ) {
122
+ throw new Error(
123
+ `Run watch returned an invalid terminal status for ${runId}.`,
124
+ );
125
+ }
126
+ return {
127
+ runId,
128
+ snapshot: snapshot as PlayRunLiveSnapshot,
129
+ ...(record.terminalStatus !== undefined
130
+ ? { terminalStatus: record.terminalStatus as Record<string, unknown> }
131
+ : {}),
132
+ };
87
133
  }
88
134
 
89
135
  async function backfillRotatedLogTail(input: {
@@ -141,26 +187,85 @@ export async function* watchRunEvents(
141
187
  options: WatchRunEventsOptions,
142
188
  ): AsyncGenerator<PlayRunStreamEvent> {
143
189
  const { http, runId, signal } = options;
144
- const path = `/api/v2/runs/${encodeURIComponent(runId)}?watchSnapshot=true`;
190
+ const params = new URLSearchParams({ watchSnapshot: 'true' });
191
+ if (options.deferLogs) params.set('deferLogs', 'true');
192
+ if (options.omitTerminalLogs) params.set('omitTerminalLogs', 'true');
193
+ if (options.terminalStatus) {
194
+ params.set(
195
+ 'terminalStatus',
196
+ options.terminalStatus.full ? 'full' : 'compact',
197
+ );
198
+ if (options.terminalStatus.billing === false)
199
+ params.set('billing', 'false');
200
+ if (options.terminalStatus.runStatus)
201
+ params.set('terminalRunStatus', 'true');
202
+ }
203
+ const path = `/api/v2/runs/${encodeURIComponent(runId)}?${params}`;
145
204
  const streamId = `play-run-watch:${runId}`;
146
- const pollIntervalMs = options.pollIntervalMs ?? RUN_WATCH_POLL_INTERVAL_MS;
205
+ const watchStartedAt = Date.now();
147
206
  let previous: PlayRunStreamDiffState = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
148
207
  let consecutiveFailures = 0;
149
208
  let outageNoticeSent = false;
209
+ let pollCount = 0;
150
210
 
151
211
  while (!signal?.aborted) {
152
212
  const pollStartedAt = Date.now();
213
+ const poll = ++pollCount;
214
+ // Keep a moderate cadence through the sandbox startup window. This halves
215
+ // short-run snapshot reads while avoiding a two-second detection gap just
216
+ // after Daytona finishes starting a fresh sandbox.
217
+ const pollIntervalMs =
218
+ options.pollIntervalMs ??
219
+ (pollStartedAt - watchStartedAt < RUN_WATCH_STARTUP_WINDOW_MS
220
+ ? RUN_WATCH_STARTUP_POLL_INTERVAL_MS
221
+ : RUN_WATCH_POLL_INTERVAL_MS);
153
222
  let snapshot: PlayRunLiveSnapshot;
223
+ let terminalStatus: Record<string, unknown> | undefined;
224
+ let responseStatus: number | undefined;
225
+ let serverTiming: string | undefined;
226
+ let pollReported = false;
227
+ const reportPoll = () => {
228
+ if (!options.onPoll || pollReported) return;
229
+ pollReported = true;
230
+ try {
231
+ options.onPoll({
232
+ poll,
233
+ durationMs: Date.now() - pollStartedAt,
234
+ ...(responseStatus !== undefined ? { status: responseStatus } : {}),
235
+ ...(serverTiming ? { serverTiming } : {}),
236
+ });
237
+ } catch {
238
+ // Diagnostics must not turn a successful poll into a retry.
239
+ }
240
+ };
154
241
  try {
155
- const response = await http.get<unknown>(path, { signal });
156
- snapshot = await backfillRotatedLogTail({
157
- http,
158
- runId,
159
- snapshot: readSnapshotResponse(response, runId).snapshot,
160
- previous,
242
+ const response = await http.get<unknown>(path, {
161
243
  signal,
244
+ ...(options.onPoll
245
+ ? {
246
+ onResponse: (response: Response) => {
247
+ responseStatus = response.status;
248
+ serverTiming =
249
+ response.headers.get('server-timing') ?? undefined;
250
+ },
251
+ }
252
+ : {}),
162
253
  });
254
+ const parsed = readSnapshotResponse(response, runId);
255
+ terminalStatus = parsed.terminalStatus;
256
+ // Deferred watchers need the terminal tail, not a replay of every skipped log.
257
+ snapshot = options.deferLogs
258
+ ? parsed.snapshot
259
+ : await backfillRotatedLogTail({
260
+ http,
261
+ runId,
262
+ snapshot: parsed.snapshot,
263
+ previous,
264
+ signal,
265
+ });
266
+ reportPoll();
163
267
  } catch (error) {
268
+ reportPoll();
164
269
  if (signal?.aborted) {
165
270
  return;
166
271
  }
@@ -176,7 +281,7 @@ export async function* watchRunEvents(
176
281
  reason,
177
282
  });
178
283
  options.onNotice?.(
179
- `[watch] run snapshot request failed; retrying every ${pollIntervalMs / 1_000}s (${reason})`,
284
+ `[watch] run snapshot request failed; retrying snapshot polling (${reason})`,
180
285
  );
181
286
  outageNoticeSent = true;
182
287
  }
@@ -196,6 +301,12 @@ export async function* watchRunEvents(
196
301
  }
197
302
  consecutiveFailures = 0;
198
303
 
304
+ // Give the consumer the same durable status it would otherwise fetch
305
+ // before emitting terminal events that cause that serial HTTP request.
306
+ if (terminalStatus) {
307
+ await options.terminalStatus?.onStatus(terminalStatus, snapshot.status);
308
+ }
309
+
199
310
  const diff = diffPlayRunStreamEvents({
200
311
  streamId,
201
312
  snapshot,
@@ -1,5 +1,9 @@
1
1
  import { resolveLookupClientTimeoutMs } from '../../shared_libs/integration-contracts/lookup-execution-policy.js';
2
2
  import type { ToolResultBilling } from '../../shared_libs/plays/tool-result-types.js';
3
+ import {
4
+ parseExecuteServerTiming,
5
+ type ExecuteServerTiming,
6
+ } from '../../shared_libs/play-runtime/execute-server-timing';
3
7
  import { resolveTheirstackClientTimeoutMs } from '../../shared_libs/integration-contracts/theirstack/execution-policy.js';
4
8
  import { resolveWaterfallClientTimeoutMs } from '../../shared_libs/integration-contracts/waterfall/execution-policy.js';
5
9
  import {
@@ -19,6 +23,7 @@ import {
19
23
  import { DeeplineError, ToolExecutionError } from './errors';
20
24
  import type { HttpClient } from './http';
21
25
  import { validateCliInvocationId } from './cli-invocation-id';
26
+ import { ATOMIC_TOOL_EXECUTE_SUPPORTED_HEADER } from '../../shared_libs/integration-contracts/execute-retry-contract.js';
22
27
 
23
28
  const INCLUDE_TOOL_METADATA_HEADER = 'x-deepline-include-tool-metadata';
24
29
  const EXECUTE_RESPONSE_CONTRACT_HEADER = 'x-deepline-execute-response-contract';
@@ -117,6 +122,8 @@ const DEEPLINEAGENT_EXECUTE_TIMEOUT_MS = 15 * 60 * 1000;
117
122
 
118
123
  export type ExecuteToolRawOptions = {
119
124
  includeToolMetadata?: boolean;
125
+ /** Use the atomic-tools endpoint, which rejects Plays before charge admission. */
126
+ atomicToolOnly?: boolean;
120
127
  responseIntent?: 'dataset' | 'raw' | 'row_artifact';
121
128
  metadata?: Record<string, unknown>;
122
129
  timeout?: number;
@@ -140,7 +147,9 @@ export type ExecuteToolRawOptions = {
140
147
  receivedAtMs: number;
141
148
  httpStatus: number;
142
149
  state: 'completed' | 'failed' | 'cancelled';
143
- }) => void;
150
+ }) => void | Promise<void>;
151
+ /** Optional response-path diagnostics; does not affect execution or retries. */
152
+ onServerTiming?: (timing: ExecuteServerTiming | null) => void | Promise<void>;
144
153
  };
145
154
 
146
155
  /** Durable state returned for a keyed tool execution. */
@@ -376,13 +385,6 @@ export class ToolCalls {
376
385
  inputSnapshot,
377
386
  this.configuredRequestTimeoutMs,
378
387
  );
379
- if (idempotencyKey !== undefined) {
380
- await this.lookupExecutionByKey(
381
- idempotencyKey,
382
- timeoutMs,
383
- options?.cliInvocationId,
384
- );
385
- }
386
388
  const isApifySync = toolId.trim().toLowerCase() === 'apify_run_actor_sync';
387
389
  const headers = {
388
390
  [EXECUTE_RESPONSE_CONTRACT_HEADER]: RAW_V2_EXECUTE_RESPONSE_CONTRACT,
@@ -436,18 +438,35 @@ export class ToolCalls {
436
438
  : failure
437
439
  ? 'failed'
438
440
  : null;
439
- if (terminal)
440
- options?.onResponseReceived?.({
441
+ if (!terminal || !options?.onResponseReceived) return;
442
+ const reportObservationFailure = () =>
443
+ console.error('[tools.execute] response observation failed');
444
+ try {
445
+ const notification = options.onResponseReceived({
441
446
  receivedAtMs: lastResponse.receivedAtMs,
442
447
  httpStatus: lastResponse.httpStatus,
443
448
  state: terminal,
444
449
  });
450
+ void Promise.resolve(notification).catch(reportObservationFailure);
451
+ } catch {
452
+ reportObservationFailure();
453
+ }
445
454
  };
446
- const request = async (requestTimeoutMs: number | undefined) => {
447
- lastResponse = null;
448
- try {
449
- return await this.http.post<ToolExecution<TData, TMeta>>(
450
- `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
455
+ const legacyEndpoint = `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`;
456
+ let useLegacyEndpoint = idempotencyKey === undefined;
457
+ const atomicToolOnly = options?.atomicToolOnly === true;
458
+ const dispatchRequest = async (
459
+ requestTimeoutMs: number | undefined,
460
+ ): Promise<ToolExecution<TData, TMeta>> => {
461
+ let recoverySupported = false;
462
+ let atomicToolsSupported = false;
463
+ const post = () =>
464
+ this.http.post<ToolExecution<TData, TMeta>>(
465
+ atomicToolOnly
466
+ ? `/api/v2/tools/${encodeURIComponent(toolId)}/execute`
467
+ : useLegacyEndpoint
468
+ ? legacyEndpoint
469
+ : `/api/v2/executions/by-key/${encodeURIComponent(idempotencyKey!)}?tool_id=${encodeURIComponent(toolId)}`,
451
470
  {
452
471
  payload: inputSnapshot,
453
472
  ...(metadataSnapshot ? { metadata: metadataSnapshot } : {}),
@@ -456,21 +475,91 @@ export class ToolCalls {
456
475
  {
457
476
  timeout: requestTimeoutMs,
458
477
  maxRetries: idempotencyKey ? 0 : (options?.maxRetries ?? 0),
459
- retryApiErrors: options?.retryApiErrors === true,
478
+ ...(atomicToolOnly &&
479
+ !idempotencyKey &&
480
+ options?.maxRetries === undefined
481
+ ? { executePolicyMaxRetries: 2 }
482
+ : {}),
483
+ retryApiErrors: atomicToolOnly || options?.retryApiErrors === true,
484
+ retryFromExecutePolicy: atomicToolOnly,
460
485
  exactUrlOnly: true,
461
486
  toolId,
462
487
  idempotencyKey,
463
- onResponse: () => {
488
+ onResponse: (response) => {
464
489
  lastResponse = null;
490
+ atomicToolsSupported =
491
+ response.headers.get(ATOMIC_TOOL_EXECUTE_SUPPORTED_HEADER) ===
492
+ 'true';
493
+ recoverySupported =
494
+ response.headers.get('X-Deepline-Idempotency-Supported') ===
495
+ 'true';
496
+ if (options?.onServerTiming) {
497
+ try {
498
+ const notification = options.onServerTiming(
499
+ parseExecuteServerTiming(
500
+ response.headers.get('server-timing'),
501
+ ),
502
+ );
503
+ void Promise.resolve(notification).catch(() => undefined);
504
+ } catch {
505
+ // Diagnostic callbacks cannot turn a delivered mutation into
506
+ // an ambiguous failure or trigger execution recovery.
507
+ }
508
+ }
465
509
  },
466
510
  onResponseBody: (observation) => {
467
511
  lastResponse = observation;
468
512
  },
469
513
  },
470
514
  );
515
+ try {
516
+ return await post();
517
+ } catch (error) {
518
+ if (atomicToolOnly) {
519
+ if (
520
+ !atomicToolsSupported &&
521
+ !recoverySupported &&
522
+ !(error instanceof ToolExecutionError) &&
523
+ error instanceof DeeplineError &&
524
+ (error.statusCode === 404 || error.statusCode === 405)
525
+ ) {
526
+ throw new DeeplineError(
527
+ 'This server does not support atomic tool execution.',
528
+ error.statusCode,
529
+ 'ATOMIC_TOOL_EXECUTE_UNSUPPORTED',
530
+ );
531
+ }
532
+ throw error;
533
+ }
534
+ // Older servers reject this named action before dispatch. Confirm their
535
+ // legacy recovery contract before sending a mutating request there.
536
+ // Supported tool failures, ambiguous delivery, and auth errors never
537
+ // trigger this fallback.
538
+ if (
539
+ useLegacyEndpoint ||
540
+ recoverySupported ||
541
+ !(error instanceof DeeplineError) ||
542
+ (error.statusCode !== 404 && error.statusCode !== 405)
543
+ )
544
+ throw error;
545
+ lastResponse = null;
546
+ await this.lookupExecutionByKey(
547
+ idempotencyKey!,
548
+ requestTimeoutMs,
549
+ options?.cliInvocationId,
550
+ );
551
+ useLegacyEndpoint = true;
552
+ return post();
553
+ }
554
+ };
555
+ const request = async (
556
+ requestTimeoutMs: number | undefined,
557
+ ): Promise<ToolExecution<TData, TMeta>> => {
558
+ lastResponse = null;
559
+ try {
560
+ return await dispatchRequest(requestTimeoutMs);
471
561
  } catch (error) {
472
- // Only the final HTTP rejection, not an intermediate retry or an
473
- // ambiguous network/cancellation failure, proves a response endpoint.
562
+ // Observe only the final rejection, after compatibility dispatch.
474
563
  observeTerminal({ error });
475
564
  throw error;
476
565
  }
@@ -219,6 +219,18 @@ export interface ProviderDefinition {
219
219
  */
220
220
  export type { DeeplineToolCategory };
221
221
 
222
+ /** Visible category membership count; a tool can belong to several categories. */
223
+ export interface ToolCategorySummary {
224
+ name: string;
225
+ count: number;
226
+ }
227
+
228
+ /** Selected tool definitions and all visible category counts. */
229
+ export interface ToolCategoryListing {
230
+ categories: ToolCategorySummary[];
231
+ tools: ToolDefinition[];
232
+ }
233
+
222
234
  /**
223
235
  * Summary definition of a callable provider-backed tool.
224
236
  *
@@ -877,6 +889,8 @@ export interface PlayRunPackage {
877
889
  warnings?: string[];
878
890
  /** Step-level summaries emitted by the runtime. */
879
891
  steps: Array<Record<string, unknown>>;
892
+ /** Whether the admitted graph or observed ledger expects public steps. */
893
+ stepsExpected?: boolean;
880
894
  /** Named output summaries, including dataset handles and scalar outputs. */
881
895
  outputs: Record<string, Record<string, unknown>>;
882
896
  /** Every durable Dataset Handle explicitly registered by this run. */
@@ -1854,6 +1868,8 @@ export interface PlayRunStart {
1854
1868
  dashboardUrl?: string;
1855
1869
  /** Terminal status returned when the start request used a short completion wait. */
1856
1870
  finalStatus?: unknown;
1871
+ /** Explicit full representation assembled by the canonical status reader. */
1872
+ finalStatusView?: 'full';
1857
1873
  /** Canonical compact run package returned by current SDK/API responses. */
1858
1874
  package?: PlayRunPackage;
1859
1875
  }
@@ -2178,6 +2194,8 @@ export interface StartPlayRunRequest {
2178
2194
  maxCredits?: number;
2179
2195
  /** Optionally let the start request wait briefly and return a terminal result. */
2180
2196
  waitForCompletionMs?: number;
2197
+ /** Request full terminal status within an optional start completion wait. */
2198
+ terminalStatus?: 'full';
2181
2199
  /**
2182
2200
  * Per-run execution profile override. The server defaults to absurd. The
2183
2201
  * Only `absurd` is accepted; most callers should leave this unset.
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Trusted app-to-execution-gateway contract for replaying a completed
3
+ * integration attempt. The app resolves provider policy while it has the
4
+ * executable integration catalog loaded; the gateway persists this value with
5
+ * the exact response bytes and never loads provider code itself.
6
+ */
7
+ export const EXECUTE_RETRY_POLICY_HEADER = 'x-deepline-execute-retry-policy';
8
+
9
+ export const EXECUTE_RETRY_POLICY_VERSION = 1;
10
+
11
+ export type ExecuteRetryPolicy =
12
+ | 'transient-http-safe'
13
+ | 'transient-http-unsafe';
14
+
15
+ export function serializeExecuteRetryPolicy(
16
+ retrySafeTransientHttp: boolean,
17
+ ): string {
18
+ return `v${EXECUTE_RETRY_POLICY_VERSION}:${
19
+ retrySafeTransientHttp ? 'transient-http-safe' : 'transient-http-unsafe'
20
+ }`;
21
+ }
22
+
23
+ export function parseExecuteRetryPolicy(
24
+ value: string | null | undefined,
25
+ ): ExecuteRetryPolicy | null {
26
+ if (value === `v${EXECUTE_RETRY_POLICY_VERSION}:transient-http-safe`) {
27
+ return 'transient-http-safe';
28
+ }
29
+ if (value === `v${EXECUTE_RETRY_POLICY_VERSION}:transient-http-unsafe`) {
30
+ return 'transient-http-unsafe';
31
+ }
32
+ return null;
33
+ }
34
+
35
+ /** Marks authoritative responses from the atomic-tools execution endpoint. */
36
+ export const ATOMIC_TOOL_EXECUTE_SUPPORTED_HEADER =
37
+ 'x-deepline-atomic-tool-supported';
@@ -0,0 +1,3 @@
1
+ {
2
+ "sideEffects": false
3
+ }
@@ -132,7 +132,7 @@
132
132
  "@deepline/product-notifications": "workspace:*",
133
133
  "@vercel/oidc": "^3.0.5",
134
134
  "@vercel/queue": "^0.4.0",
135
- "next": "16.3.6",
135
+ "next": "16.4.1",
136
136
  "pg": "^8.19.0",
137
137
  "react": "19.2.5",
138
138
  "@deepline/integration-contracts": "workspace:*"
@@ -193,7 +193,7 @@ export async function uploadBufferToR2(input: {
193
193
  logR2Perf('client', input.key, clientStartedAt, { kind: bucketKind });
194
194
 
195
195
  const sendStartedAt = Date.now();
196
- await client.send(
196
+ const result = await client.send(
197
197
  new PutObjectCommand({
198
198
  Bucket: config.bucket,
199
199
  Key: input.key,
@@ -203,6 +203,8 @@ export async function uploadBufferToR2(input: {
203
203
  }),
204
204
  );
205
205
  logR2Perf('put-send', input.key, sendStartedAt, {
206
+ attempts: result.$metadata.attempts ?? null,
207
+ retryDelayMs: result.$metadata.totalRetryDelay ?? null,
206
208
  kind: bucketKind,
207
209
  bytes: input.body.byteLength,
208
210
  });
@@ -1422,7 +1422,7 @@ export async function executeAsyncOperationLifecycle<Response>(input: {
1422
1422
  typeof totalPages === 'number' &&
1423
1423
  Number.isSafeInteger(totalPages)
1424
1424
  ) {
1425
- return page + 1 >= totalPages;
1425
+ return page - pagination.startPage + 1 >= totalPages;
1426
1426
  }
1427
1427
  // Older providers sometimes omit both pagination markers for a
1428
1428
  // one-page result. Treat only an explicit `last: false` as proof