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
@@ -481,6 +481,8 @@ export interface BatchRequest {
481
481
  }
482
482
 
483
483
  export interface MapStartResult {
484
+ /** Opt-in authoritative completed cells, separate from merged input rows. */
485
+ previousCells?: import('./dataset-row-input').DatasetPreviousCells[];
484
486
  /** Rows that need processing for this run. Previous values may be included for context. */
485
487
  pendingRows: Record<string, unknown>[];
486
488
  /** Rows already terminal for this run and safe to count as completed. */
@@ -825,6 +827,8 @@ export interface ContextOptions {
825
827
  authoringContractEdition?: PlayAuthoringContractEdition;
826
828
  /** Direct/local callers may opt into the new terminal Slack HITL outcome. */
827
829
  slackHitlTimeoutOutcome?: 'park' | 'error';
830
+ /** Artifact-pinned dataset input policy; missing retains legacy hydration. */
831
+ datasetRowInput?: 'current_run';
828
832
  /** Error shape pinned by the immutable play artifact; missing preserves legacy schema 0. */
829
833
  toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
830
834
  /** Execute-result contract pinned by the immutable Play artifact. */
@@ -967,6 +971,8 @@ export interface ContextOptions {
967
971
  executorToken?: string;
968
972
  staticPipeline?: PlayStaticPipeline | null;
969
973
  forceRefresh?: boolean;
974
+ includePreviousCells?: boolean;
975
+ previousCellsBudgetBytes?: number;
970
976
  inputOffset?: number;
971
977
  mode?: RuntimeDatasetRunOptions['mode'];
972
978
  columnTypes?: PlayDatasetColumnTypes;
@@ -0,0 +1,124 @@
1
+ import { copyPlayDatasetSourceRowIdentity } from '../plays/dataset';
2
+ import type { PreviousCell } from '../plays/cell-staleness';
3
+ import { cloneCsvAliasedRow } from './csv-rename';
4
+ import {
5
+ runtimeJsonByteLength,
6
+ type RuntimeMemoryLedger,
7
+ type RuntimeMemoryLedgerHandle,
8
+ } from './memory-ledger';
9
+
10
+ export type DatasetPreviousCells = {
11
+ key: string;
12
+ cells: Record<string, PreviousCell>;
13
+ };
14
+
15
+ // Match the ordinary runtime API decoded-response limit, including both the
16
+ // legacy projection and opted-in history. Never truncate a historical cell.
17
+ const MAX_ADMISSION_BYTES = 16 * 1024 * 1024;
18
+
19
+ export function assertDatasetAdmissionHistory(
20
+ result: { previousCells?: DatasetPreviousCells[] },
21
+ budgetBytes = MAX_ADMISSION_BYTES,
22
+ ): Map<string, Record<string, PreviousCell>> {
23
+ if (!Array.isArray(result.previousCells)) {
24
+ throw new Error(
25
+ 'Dataset admission did not return requested previous cells. Deploy dataset row input readers before activating new artifacts.',
26
+ );
27
+ }
28
+ const limit = Math.min(MAX_ADMISSION_BYTES, budgetBytes);
29
+ if (!Number.isFinite(limit) || limit < 1) {
30
+ throw new Error(
31
+ 'Dataset admission history requires a positive byte budget.',
32
+ );
33
+ }
34
+ if (runtimeJsonByteLength(result) > limit) {
35
+ throw new Error(
36
+ `Dataset admission with previous cells exceeds the ${limit} byte budget.`,
37
+ );
38
+ }
39
+ return new Map(result.previousCells.map(({ key, cells }) => [key, cells]));
40
+ }
41
+
42
+ export function persistedFieldsAbsentFromInputRow(
43
+ inputRow: Record<string, unknown>,
44
+ persisted: Record<string, unknown>,
45
+ ): Record<string, unknown> {
46
+ return Object.fromEntries(
47
+ Object.entries(persisted).filter(
48
+ ([key]) => !Object.prototype.hasOwnProperty.call(inputRow, key),
49
+ ),
50
+ );
51
+ }
52
+
53
+ type RowHistory = {
54
+ cells: Record<string, PreviousCell>;
55
+ bytes: number;
56
+ memory?: RuntimeMemoryLedgerHandle;
57
+ };
58
+
59
+ /** Private execution context, copied at the runtime's row-cloning seam. */
60
+ export class DatasetRowInputView {
61
+ private readonly history = new WeakMap<object, RowHistory>();
62
+
63
+ seed(
64
+ input: Record<string, unknown>,
65
+ persisted: Record<string, unknown> | undefined,
66
+ policy: 'legacy' | 'current_run',
67
+ cells: Record<string, PreviousCell> = {},
68
+ ): Record<string, unknown> {
69
+ const extra = persistedFieldsAbsentFromInputRow(input, persisted ?? {});
70
+ if (policy === 'legacy' && !persisted) return input;
71
+ const row = cloneCsvAliasedRow(
72
+ input,
73
+ policy === 'legacy'
74
+ ? extra
75
+ : Object.fromEntries(
76
+ Object.entries(extra).filter(([key]) =>
77
+ key.startsWith('__deepline'),
78
+ ),
79
+ ),
80
+ );
81
+ if (policy === 'current_run') {
82
+ copyPlayDatasetSourceRowIdentity(input, row);
83
+ this.history.set(row, { cells, bytes: runtimeJsonByteLength(cells) });
84
+ }
85
+ return row;
86
+ }
87
+
88
+ copy<T extends object>(source: object, target: T): T {
89
+ const history = this.history.get(source);
90
+ if (history) this.history.set(target, history);
91
+ return target;
92
+ }
93
+
94
+ previous(row: object, field: string): PreviousCell | undefined {
95
+ const cells = this.history.get(row)?.cells;
96
+ return cells && Object.prototype.hasOwnProperty.call(cells, field)
97
+ ? cells[field]
98
+ : undefined;
99
+ }
100
+
101
+ memoryValue(row: Record<string, unknown>): unknown {
102
+ const history = this.history.get(row);
103
+ return history ? { row, previousCells: history.cells } : row;
104
+ }
105
+
106
+ retain(row: object, ledger: RuntimeMemoryLedger): void {
107
+ const history = this.history.get(row);
108
+ if (history && !history.memory && history.bytes > 0) {
109
+ history.memory = ledger.register({
110
+ category: 'hydrationReadBack',
111
+ bytes: history.bytes,
112
+ });
113
+ }
114
+ }
115
+
116
+ release(row: object): void {
117
+ const history = this.history.get(row);
118
+ if (!history) return;
119
+ history.memory?.release();
120
+ history.memory = undefined;
121
+ history.cells = {};
122
+ history.bytes = 0;
123
+ }
124
+ }
@@ -1,3 +1,9 @@
1
+ import { buildDurableToolReceiptPrefix } from './durable-tool-identity';
2
+ export {
3
+ buildDurableToolCallAuthScopeDigest,
4
+ buildDurableToolReceiptPrefix,
5
+ buildDurableToolPayloadProviderIdempotencyKey,
6
+ } from './durable-tool-identity';
1
7
  import {
2
8
  normalizeTableNamespace,
3
9
  sha256Hex,
@@ -200,32 +206,6 @@ export function buildDurableRunPlayInvocationScope(input: {
200
206
  );
201
207
  }
202
208
 
203
- export function buildDurableToolCallAuthScopeDigest(input: {
204
- orgId?: string | null;
205
- toolId: string;
206
- executionAuthScopeDigest?: string | null;
207
- }): string {
208
- return sha256Hex(
209
- stableStringify({
210
- orgId: input.orgId?.trim() || 'org',
211
- toolId: input.toolId.trim(),
212
- executionAuthScopeDigest: input.executionAuthScopeDigest?.trim() || null,
213
- }),
214
- );
215
- }
216
-
217
- export function buildDurableToolReceiptPrefix(input: {
218
- orgId?: string | null;
219
- toolId: string;
220
- }): string {
221
- const orgId = input.orgId?.trim() || 'org';
222
- const toolId = input.toolId.trim();
223
- if (!toolId) {
224
- throw new Error('Durable tool receipt prefix requires a non-empty toolId.');
225
- }
226
- return `ctx:${orgId}:call:tool:${normalizeTableNamespace(toolId)}:`;
227
- }
228
-
229
209
  /** Partition a completed-result receipt without changing its accepted wire
230
210
  * shape. The semantic key still includes payload/auth/action/presentation. */
231
211
  export function scopeToolReceiptToInvocation(input: {
@@ -302,39 +282,3 @@ function commonDurableToolReceiptPrefix(
302
282
  }
303
283
  return commonPrefix ?? '';
304
284
  }
305
-
306
- /**
307
- * Provider-native batch caching is keyed by the exact compiled provider
308
- * payload. Result-cache identities coordinate local publication; they never
309
- * stand in for a provider operation identity.
310
- *
311
- * An explicit force refresh is deliberately a separate namespace: it asks for
312
- * a fresh provider operation even when the payload itself is unchanged.
313
- */
314
- export function buildDurableToolPayloadProviderIdempotencyKey(input: {
315
- orgId?: string | null;
316
- toolId: string;
317
- executionAuthScopeDigest?: string | null;
318
- providerActionVersion?: string | null;
319
- payload: Record<string, unknown>;
320
- forceRefreshIdentities?: readonly string[];
321
- }): string {
322
- const toolId = input.toolId.trim();
323
- if (!toolId) {
324
- throw new Error(
325
- 'Provider payload idempotency key needs a non-empty toolId.',
326
- );
327
- }
328
- const forceRefreshIdentities = input.forceRefreshIdentities
329
- ?.map((identity) => identity.trim())
330
- .filter(Boolean);
331
- const orgId = input.orgId?.trim() || 'org';
332
- return `ctx:${orgId}:operation:tool:${normalizeTableNamespace(toolId)}:payload-v1:${sha256Hex(
333
- stableStringify({
334
- executionAuthScopeDigest: input.executionAuthScopeDigest?.trim() || null,
335
- providerActionVersion: input.providerActionVersion?.trim() || null,
336
- payload: input.payload,
337
- ...(forceRefreshIdentities?.length ? { forceRefreshIdentities } : {}),
338
- }),
339
- )}`;
340
- }
@@ -4,6 +4,7 @@ import {
4
4
  isToolExecuteResult,
5
5
  serializeToolExecuteResult,
6
6
  } from './tool-result';
7
+ export { executeWithFreshnessReceipt } from './freshness-receipt-execution';
7
8
  import { assertNoSecretTaint } from './secret-capability';
8
9
  import type { RuntimeStepReceipt } from './ctx-types';
9
10
  import {
@@ -0,0 +1,67 @@
1
+ import {
2
+ normalizeTableNamespace,
3
+ sha256Hex,
4
+ stableStringify,
5
+ } from '../plays/row-identity';
6
+
7
+ export function buildDurableToolCallAuthScopeDigest(input: {
8
+ orgId?: string | null;
9
+ toolId: string;
10
+ executionAuthScopeDigest?: string | null;
11
+ }): string {
12
+ return sha256Hex(
13
+ stableStringify({
14
+ orgId: input.orgId?.trim() || 'org',
15
+ toolId: input.toolId.trim(),
16
+ executionAuthScopeDigest: input.executionAuthScopeDigest?.trim() || null,
17
+ }),
18
+ );
19
+ }
20
+
21
+ export function buildDurableToolReceiptPrefix(input: {
22
+ orgId?: string | null;
23
+ toolId: string;
24
+ }): string {
25
+ const orgId = input.orgId?.trim() || 'org';
26
+ const toolId = input.toolId.trim();
27
+ if (!toolId) {
28
+ throw new Error('Durable tool receipt prefix requires a non-empty toolId.');
29
+ }
30
+ return `ctx:${orgId}:call:tool:${normalizeTableNamespace(toolId)}:`;
31
+ }
32
+
33
+ /**
34
+ * Provider-native batch caching is keyed by the exact compiled provider
35
+ * payload. Result-cache identities coordinate local publication; they never
36
+ * stand in for a provider operation identity.
37
+ *
38
+ * An explicit force refresh is deliberately a separate namespace: it asks for
39
+ * a fresh provider operation even when the payload itself is unchanged.
40
+ */
41
+ export function buildDurableToolPayloadProviderIdempotencyKey(input: {
42
+ orgId?: string | null;
43
+ toolId: string;
44
+ executionAuthScopeDigest?: string | null;
45
+ providerActionVersion?: string | null;
46
+ payload: Record<string, unknown>;
47
+ forceRefreshIdentities?: readonly string[];
48
+ }): string {
49
+ const toolId = input.toolId.trim();
50
+ if (!toolId) {
51
+ throw new Error(
52
+ 'Provider payload idempotency key needs a non-empty toolId.',
53
+ );
54
+ }
55
+ const forceRefreshIdentities = input.forceRefreshIdentities
56
+ ?.map((identity) => identity.trim())
57
+ .filter(Boolean);
58
+ const orgId = input.orgId?.trim() || 'org';
59
+ return `ctx:${orgId}:operation:tool:${normalizeTableNamespace(toolId)}:payload-v1:${sha256Hex(
60
+ stableStringify({
61
+ executionAuthScopeDigest: input.executionAuthScopeDigest?.trim() || null,
62
+ providerActionVersion: input.providerActionVersion?.trim() || null,
63
+ payload: input.payload,
64
+ ...(forceRefreshIdentities?.length ? { forceRefreshIdentities } : {}),
65
+ }),
66
+ )}`;
67
+ }
@@ -10,21 +10,44 @@ export const EXECUTE_SERVER_TIMING_STAGES = [
10
10
  'auth',
11
11
  'rate_limit',
12
12
  'catalog',
13
+ // Local preparation accumulates compilation/hooks/pricing inside catalog
14
+ // and executor loading before the final provider permit. Do not add it to
15
+ // catalog or total. Credential selection excludes charge admission.
16
+ 'credential_plan',
17
+ 'provider_prepare',
13
18
  'charge_open',
14
19
  // Charge admission substages. `charge_open` keeps its original meaning — the
15
20
  // TOTAL of all charge-admission work — so an existing reader is unchanged and
16
- // these four explain work inside it. RPC stages include their retry waits,
17
- // so `charge_retry_wait` overlaps them; do not sum all four as disjoint time.
21
+ // these four explain work inside it. The authorization action adapter splits
22
+ // its wall into snapshot, remaining action time and application retry gaps.
18
23
  // Absent stages are unobserved, not confident zero durations.
19
24
  // - `charge_eligibility` canonical wallet and cap authorization snapshot
20
25
  // - `charge_cap_preflight` legacy standalone cap work (zero in current path)
21
- // - `charge_open_mutation` the `openCharge` mutation, its retries included
26
+ // - `charge_open_mutation` remaining action wall, including transport and
27
+ // failed attempts; legacy name, not mutation CPU
22
28
  // - `charge_retry_wait` elapsed gaps before application RPC retries;
23
29
  // native Convex logs attribute internal OCC retries
24
30
  'charge_eligibility',
25
31
  'charge_cap_preflight',
26
32
  'charge_open_mutation',
27
33
  'charge_retry_wait',
34
+ // Billing completion slices explain the full stage, including transport.
35
+ // Handoff headers/body are nested within billing_handoff, not additive.
36
+ 'billing_settle',
37
+ 'billing_price',
38
+ 'billing_precision',
39
+ 'billing_caps',
40
+ 'billing_catalog',
41
+ 'billing_witness',
42
+ 'billing_handoff',
43
+ 'billing_handoff_rpc',
44
+ 'billing_handoff_headers',
45
+ 'billing_handoff_after_headers',
46
+ // Process-wide activity over the RPC interval, including concurrent work.
47
+ // These overlap the wall clocks above; they are not request-attributed CPU.
48
+ 'billing_handoff_process_cpu',
49
+ 'billing_handoff_event_loop_active',
50
+ 'billing_handoff_event_loop_idle',
28
51
  'fixture_load',
29
52
  'execute',
30
53
  'identity',
@@ -78,11 +101,44 @@ export const EXECUTE_SERVER_TIMING_STAGES = [
78
101
  'upstream_body',
79
102
  ] as const;
80
103
 
104
+ // The public recovery handler surrounds the core: its total includes durable
105
+ // response storage and receipt acknowledgement. Keep the core's total intact.
106
+ export const PUBLIC_EXECUTE_SERVER_TIMING_STAGES = [
107
+ // Route total includes lazy execution-module loading. The handler's
108
+ // public_total keeps its existing meaning so older readers remain valid.
109
+ 'public_load',
110
+ 'public_route',
111
+ // Core and recovery initialization overlap authentication. Their wall is
112
+ // included in public_total; these stages are not additive.
113
+ 'public_core_load',
114
+ 'public_recovery_load',
115
+ 'public_auth',
116
+ 'public_claim',
117
+ 'public_claim_headers',
118
+ 'public_claim_after_headers',
119
+ 'public_core',
120
+ 'public_prepare',
121
+ 'public_r2',
122
+ 'public_complete',
123
+ 'public_complete_headers',
124
+ 'public_complete_after_headers',
125
+ 'public_total',
126
+ ] as const;
127
+
128
+ export type PublicExecuteServerTimingStage =
129
+ (typeof PUBLIC_EXECUTE_SERVER_TIMING_STAGES)[number];
130
+
131
+ const ALL_EXECUTE_SERVER_TIMING_STAGES = /* @__PURE__ */ (() =>
132
+ [
133
+ ...EXECUTE_SERVER_TIMING_STAGES,
134
+ ...PUBLIC_EXECUTE_SERVER_TIMING_STAGES,
135
+ ] as const)();
136
+
81
137
  export type ExecuteServerTimingStage =
82
138
  (typeof EXECUTE_SERVER_TIMING_STAGES)[number];
83
139
 
84
140
  export type ExecuteServerTiming = Record<
85
- ExecuteServerTimingStage,
141
+ ExecuteServerTimingStage | PublicExecuteServerTimingStage,
86
142
  number | null
87
143
  >;
88
144
 
@@ -118,12 +174,14 @@ export function parseExecuteServerTiming(
118
174
  }
119
175
  }
120
176
  const timing = Object.fromEntries(
121
- EXECUTE_SERVER_TIMING_STAGES.map((stage) => [
177
+ ALL_EXECUTE_SERVER_TIMING_STAGES.map((stage) => [
122
178
  stage,
123
179
  durations.get(stage) ?? null,
124
180
  ]),
125
181
  ) as ExecuteServerTiming;
126
- return EXECUTE_SERVER_TIMING_STAGES.some((stage) => timing[stage] !== null)
182
+ return ALL_EXECUTE_SERVER_TIMING_STAGES.some(
183
+ (stage) => timing[stage] !== null,
184
+ )
127
185
  ? timing
128
186
  : null;
129
187
  }
@@ -17,11 +17,7 @@ import {
17
17
  type CompletedCall = {
18
18
  completedAt: number;
19
19
  value?: unknown;
20
- /**
21
- * Large tool results already live in their canonical result receipt. Keep a
22
- * receipt-key indirection here instead of copying the full result into each
23
- * operation and reusable freshness receipt.
24
- */
20
+ /** Reuse a result already stored by its canonical receipt without copying it. */
25
21
  valueReceiptKey?: string;
26
22
  undefinedValue?: true;
27
23
  };
@@ -15,7 +15,7 @@ export const MAX_LEDGER_RESULT_PAYLOAD_BYTES = LEDGER_TERMINAL_RESULT_MAX_BYTES;
15
15
  export const MAX_LEDGER_LOG_LINES_PER_EVENT = 500;
16
16
  export const MAX_LEDGER_LOG_LINE_LENGTH = 2_000;
17
17
 
18
- const ledgerIngressRedactor = createSecretRedactionContext();
18
+ const ledgerIngressRedactor = /* @__PURE__ */ createSecretRedactionContext();
19
19
 
20
20
  export function redactLedgerString(value: unknown): string | null {
21
21
  if (typeof value !== 'string' || !value.trim()) return null;
@@ -24,6 +24,7 @@ import {
24
24
  */
25
25
  export type PlayArtifactRuntimeContract = Readonly<{
26
26
  semantics: PlayRuntimeSemantics;
27
+ datasetRowInput: 'legacy' | 'current_run';
27
28
  /** Additive artifact fact; missing persisted fields resolve to `park`. */
28
29
  slackHitlTimeoutOutcome: 'park' | 'error';
29
30
  toolErrorSchemaVersion: ToolExecutionErrorSchemaVersion;
@@ -33,6 +34,7 @@ export type PlayArtifactRuntimeContract = Readonly<{
33
34
 
34
35
  export type PlayArtifactRuntimeContractInput = {
35
36
  authoringContractEdition?: PlayAuthoringContractEdition | null;
37
+ datasetRowInput?: 'current_run';
36
38
  slackHitlTimeoutOutcome?: 'park' | 'error' | null;
37
39
  toolResponseContract?: ToolResponseContract | null;
38
40
  toolResponseReceiptRevision?: string | null;
@@ -50,6 +52,7 @@ export function resolvePlayArtifactRuntimeContract(
50
52
  const toolResponseReceiptRevision =
51
53
  input.toolResponseReceiptRevision ?? undefined;
52
54
  return Object.freeze({
55
+ datasetRowInput: input.datasetRowInput ?? 'legacy',
53
56
  semantics: resolvePlayRuntimeSemantics(
54
57
  input.authoringContractEdition ?? PLAY_AUTHORING_CONTRACT_EDITION,
55
58
  ),
@@ -1,6 +1,7 @@
1
1
  import type { SafeFetchImplementation } from '../security/safe-fetch';
2
2
  import type { RuntimeResourceGovernor } from './resource-governor';
3
3
  import { CTX_FETCH_EGRESS_TOOL_ID } from './builtin-pacing';
4
+ import { CtxFetchAmbiguousWriteError } from '../plays/ambiguous-write-error';
4
5
  import {
5
6
  positiveTimeoutMs,
6
7
  RUNTIME_RELIABILITY_POLICY,
@@ -216,6 +217,7 @@ export async function sendPlayHttpRequest(input: {
216
217
  timeouts?: { headersMs?: number; bodyMs?: number; totalMs?: number };
217
218
  fetchImpl?: SafeFetchImplementation;
218
219
  log: (message: string) => void;
220
+ reportAmbiguousWrite?: boolean;
219
221
  }): Promise<{ response: Response; bodyText: string }> {
220
222
  const { url, init } = input;
221
223
  const method = String(init.method ?? 'GET').toUpperCase();
@@ -244,6 +246,7 @@ export async function sendPlayHttpRequest(input: {
244
246
  const { safePublicFetch } = await loadSafeFetch();
245
247
  let transportAttempt = 1;
246
248
  let rateLimitAttempt = 0;
249
+ let writeDispatched = false;
247
250
  while (true) {
248
251
  const attemptController = new AbortController();
249
252
  let permit: Awaited<
@@ -309,6 +312,8 @@ export async function sendPlayHttpRequest(input: {
309
312
  phase: 'headers',
310
313
  run: () => {
311
314
  dispatched = true;
315
+ if (!['GET', 'HEAD', 'OPTIONS'].includes(method))
316
+ writeDispatched = true;
312
317
  return (input.fetchImpl ?? globalThis.fetch)(
313
318
  physicalUrl,
314
319
  physicalInit,
@@ -333,6 +338,11 @@ export async function sendPlayHttpRequest(input: {
333
338
  void response?.body?.cancel(error).catch(() => undefined);
334
339
  response = null;
335
340
  bodyText = null;
341
+ if (input.reportAmbiguousWrite && writeDispatched) {
342
+ throw new CtxFetchAmbiguousWriteError(method, new URL(url).origin, {
343
+ cause: error,
344
+ });
345
+ }
336
346
  if (error instanceof CtxFetchTimeoutError) throw error;
337
347
  if (init.signal?.aborted) {
338
348
  throw init.signal.reason ?? error;
@@ -120,6 +120,9 @@ export function isQueryResultDatasetReadRequest(
120
120
  input: Record<string, unknown>,
121
121
  ): boolean {
122
122
  if (!isQueryResultDatasetTool(toolId)) return false;
123
+ // Absence keeps the historical live dataset behavior.
124
+ if (isCustomerDbDatasetTool(toolId) && input.result_mode === 'rows')
125
+ return false;
123
126
  if (
124
127
  (isSnowflakeQueryDatasetTool(toolId) ||
125
128
  isDatabricksQueryDatasetTool(toolId)) &&
@@ -163,11 +163,14 @@ export const EGRESS_PROBE_BUDGET_MS = 3_000;
163
163
  const EGRESS_PROBE_REQUESTS_PER_TARGET = 6;
164
164
 
165
165
  export async function collectStartupEgressProbeLines(input: {
166
+ /** Network benchmarks are opt-in and must not delay ordinary Plays. */
167
+ enabled?: boolean;
166
168
  receiptGatewayBaseUrl: string | null;
167
169
  executionRelayBaseUrl: string | null;
168
170
  /** Bearer credential for the gateway's authenticated bandwidth sink. */
169
171
  executorToken?: string | null;
170
172
  }): Promise<string[]> {
173
+ if (input.enabled !== true) return [];
171
174
  const gateway = input.receiptGatewayBaseUrl?.trim().replace(/\/$/, '') || '';
172
175
  const relay = input.executionRelayBaseUrl?.trim().replace(/\/$/, '') || '';
173
176
  const targets: Array<{ target: EgressProbeTarget; baseUrl: string }> = [];
@@ -2378,6 +2378,7 @@ async function run(
2378
2378
  const artifactRuntimeContract = resolvePlayArtifactRuntimeContract({
2379
2379
  authoringContractEdition: artifactCompatibility.authoringContractEdition,
2380
2380
  slackHitlTimeoutOutcome: artifactCompatibility.slackHitlTimeoutOutcome,
2381
+ datasetRowInput: artifactCompatibility.datasetRowInput,
2381
2382
  toolResponseContract: config.context.toolResponseContract,
2382
2383
  toolResponseReceiptRevision: config.context.toolResponseReceiptRevision,
2383
2384
  });
@@ -2819,6 +2820,8 @@ async function run(
2819
2820
  rows: items,
2820
2821
  stableWriteIntent: true,
2821
2822
  pendingRerunAdmission: true,
2823
+ includePreviousCells: mapContext.includePreviousCells,
2824
+ previousCellsBudgetBytes: mapContext.previousCellsBudgetBytes,
2822
2825
  inputOffset: mapContext.inputOffset,
2823
2826
  mode: mapContext.mode,
2824
2827
  runId,
@@ -3382,8 +3385,9 @@ async function run(
3382
3385
  options,
3383
3386
  );
3384
3387
  for (const line of await collectStartupEgressProbeLines({
3388
+ enabled: process.env.DEEPLINE_RUNTIME_RECEIPT_TRACE === '1',
3385
3389
  // A local/direct executor can use baseUrl without a receipt gateway.
3386
- // Probe only the explicit data-plane hop.
3390
+ // Probe only the explicit data-plane hop in explicit diagnostic mode.
3387
3391
  receiptGatewayBaseUrl: config.context.receiptGatewayBaseUrl ?? null,
3388
3392
  executionRelayBaseUrl: config.context.executionGatewayBaseUrl ?? null,
3389
3393
  executorToken: config.context.executorToken ?? null,
@@ -4236,23 +4240,26 @@ export async function waitForRunnerExecutionAcknowledgement(
4236
4240
  timeoutMs = RUNNER_EXECUTION_ACK_TIMEOUT_MS,
4237
4241
  ): Promise<void> {
4238
4242
  if (!heartbeat) return;
4239
- const deadline = Date.now() + Math.max(1, timeoutMs);
4240
- let retryDelayMs = 100;
4241
- while (Date.now() < deadline) {
4242
- heartbeat.requestHeartbeat();
4243
- const remainingMs = Math.max(1, deadline - Date.now());
4244
- const acknowledged = await Promise.race([
4245
- heartbeat.executionAcknowledged.then(() => true),
4246
- new Promise<false>((resolve) =>
4247
- setTimeout(resolve, Math.min(retryDelayMs, remainingMs), false),
4248
- ),
4243
+ heartbeat.requestHeartbeat();
4244
+ let timeout: ReturnType<typeof setTimeout> | undefined;
4245
+ try {
4246
+ await Promise.race([
4247
+ heartbeat.executionAcknowledged,
4248
+ new Promise<never>((_resolve, reject) => {
4249
+ timeout = setTimeout(
4250
+ () =>
4251
+ reject(
4252
+ new Error(
4253
+ `RUNTIME_SANDBOX_START_FAILED: scheduler did not acknowledge the detached runner park within ${Math.max(1, timeoutMs)}ms. Customer play code was not started.`,
4254
+ ),
4255
+ ),
4256
+ Math.max(1, timeoutMs),
4257
+ );
4258
+ }),
4249
4259
  ]);
4250
- if (acknowledged) return;
4251
- retryDelayMs = Math.min(1_000, retryDelayMs * 2);
4260
+ } finally {
4261
+ if (timeout) clearTimeout(timeout);
4252
4262
  }
4253
- throw new Error(
4254
- `RUNTIME_SANDBOX_START_FAILED: scheduler did not acknowledge the detached runner park within ${Math.max(1, timeoutMs)}ms. Customer play code was not started.`,
4255
- );
4256
4263
  }
4257
4264
 
4258
4265
  /**
@@ -4384,6 +4391,8 @@ async function pushRunnerTerminalIfConfigured(
4384
4391
  executorToken: context.executorToken,
4385
4392
  runId: context.runId,
4386
4393
  result,
4394
+ runtimeCompletedPath:
4395
+ process.env.DEEPLINE_PLAY_RUNNER_RUNTIME_COMPLETED_PATH,
4387
4396
  ...options,
4388
4397
  });
4389
4398
  }
@@ -4433,6 +4442,7 @@ function startRunnerPushHeartbeatFromConfig(
4433
4442
  executorToken,
4434
4443
  runId: push.runId,
4435
4444
  leaseSeconds: push.leaseSeconds,
4445
+ waitForSchedulerPark: true,
4436
4446
  onSelfTerminate: (stop) => {
4437
4447
  onSelfTerminate?.(stop);
4438
4448
  void terminateRunnerForHeartbeatStop(stop);