deepline 0.3.408 → 0.3.410

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 (217) hide show
  1. package/dist/bundling-sources/sdk/src/agent-runtime.ts +18 -1
  2. package/dist/bundling-sources/sdk/src/client.ts +212 -334
  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/play-data-plane/r2.ts +3 -1
  21. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +277 -76
  22. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +6 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/dataset-row-input.ts +124 -0
  24. package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +6 -62
  25. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +1 -0
  26. package/dist/bundling-sources/shared_libs/play-runtime/durable-tool-identity.ts +67 -0
  27. package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +64 -6
  28. package/dist/bundling-sources/shared_libs/play-runtime/freshness-receipt-execution.ts +1 -5
  29. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +1 -1
  30. package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +3 -0
  31. package/dist/bundling-sources/shared_libs/play-runtime/play-http-request.ts +10 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/query-result-dataset.ts +3 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +3 -0
  34. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +26 -16
  35. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +36 -11
  36. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +35 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +21 -0
  38. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +21 -6
  39. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +11 -2
  40. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +85 -20
  41. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +71 -13
  42. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-execution-queries.ts +100 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +9 -5
  44. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +337 -146
  45. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +26 -12
  46. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +3 -1
  47. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +425 -102
  48. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
  49. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +4 -0
  50. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +9 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +181 -124
  52. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-worker-wake.ts +152 -0
  53. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +5 -3
  54. package/dist/bundling-sources/shared_libs/play-runtime/tool-cache-policy.ts +31 -0
  55. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +10 -0
  56. package/dist/bundling-sources/shared_libs/plays/ambiguous-write-error.ts +25 -0
  57. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -0
  58. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +63 -68
  59. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +129 -63
  60. package/dist/bundling-sources/shared_libs/plays/contracts.ts +14 -0
  61. package/dist/bundling-sources/shared_libs/plays/enrich-play-compiler.ts +58 -16
  62. package/dist/bundling-sources/shared_libs/plays/fetch-http-error.ts +50 -0
  63. package/dist/bundling-sources/shared_libs/plays/source-authoring-edition.ts +351 -0
  64. package/dist/bundling-sources/shared_libs/plays/tool-list-getter-mode.ts +9 -0
  65. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
  66. package/dist/cli/{auth-UVD3CUBB.mjs → auth-LLXLIILR.mjs} +6 -6
  67. package/dist/cli/auth-UG4WOYGL.js +40 -0
  68. package/dist/cli/{billing-BZVTXXLM.mjs → billing-5FVXZYAC.mjs} +8 -8
  69. package/dist/cli/{billing-BZVYAF6T.js → billing-NFPK7GYP.js} +84 -84
  70. package/dist/cli/{chunk-ZAAKSJAS.js → chunk-27GJKC5Q.js} +17 -10
  71. package/dist/cli/{chunk-UHNDVD3P.js → chunk-2H4EY7KH.js} +100 -41
  72. package/dist/cli/{chunk-WTT6CLED.mjs → chunk-2YR7BIIC.mjs} +5 -2
  73. package/dist/cli/{chunk-3ZB6IIA7.js → chunk-36AHOWVS.js} +26 -26
  74. package/dist/cli/{chunk-OSDXE27V.mjs → chunk-4PG4ARL2.mjs} +17 -10
  75. package/dist/cli/{chunk-LOYISF7S.mjs → chunk-4XQLVUC7.mjs} +738 -512
  76. package/dist/cli/{chunk-J5PTX66Y.js → chunk-5MLCBXXU.js} +8 -1
  77. package/dist/cli/chunk-5TUGWDEB.js +313 -0
  78. package/dist/cli/{chunk-D6FFBSM5.js → chunk-5UUQAGJS.js} +5 -2
  79. package/dist/cli/{chunk-4CFULMRB.mjs → chunk-5V5Y37BC.mjs} +2 -2
  80. package/dist/cli/{chunk-PMVFAYL7.mjs → chunk-63ILLN5H.mjs} +2 -2
  81. package/dist/cli/{chunk-AUMD2VXP.js → chunk-63S7X326.js} +1032 -806
  82. package/dist/cli/{chunk-4QFT5LGV.mjs → chunk-6PGATQ6L.mjs} +6 -3
  83. package/dist/cli/{chunk-6BJK4EJ3.mjs → chunk-AARWVK4C.mjs} +2132 -65
  84. package/dist/cli/{chunk-FERRDNMO.js → chunk-AD47BXN2.js} +5 -5
  85. package/dist/cli/{chunk-4RNDKFNQ.js → chunk-D37FEBES.js} +2 -2
  86. package/dist/cli/{chunk-S6R3OX7B.js → chunk-E4CABWXL.js} +25 -2
  87. package/dist/cli/{chunk-NXGCO4JB.mjs → chunk-E4IXDAZI.mjs} +5 -0
  88. package/dist/cli/chunk-EQ4Z7RJW.mjs +35 -0
  89. package/dist/cli/chunk-FR2ILQ4G.mjs +8 -0
  90. package/dist/cli/{chunk-QUAQX3FQ.js → chunk-FVLNYDI4.js} +128 -376
  91. package/dist/cli/{chunk-BRJUESQV.js → chunk-FZJAM576.js} +50 -50
  92. package/dist/cli/{chunk-BZAMOCPA.mjs → chunk-IMZ56EOH.mjs} +3 -3
  93. package/dist/cli/{chunk-IOHRWLQE.mjs → chunk-IPG42SD2.mjs} +452 -138
  94. package/dist/cli/chunk-J33TSWO5.js +8 -0
  95. package/dist/cli/{chunk-XXLXOUUU.mjs → chunk-JNXJZ577.mjs} +1 -1
  96. package/dist/cli/{chunk-JI2B4RZP.mjs → chunk-KCC3FKIW.mjs} +71 -12
  97. package/dist/cli/{chunk-6IKARAYD.mjs → chunk-L2VKAASU.mjs} +23 -0
  98. package/dist/cli/{chunk-PYZZMAJQ.mjs → chunk-LFSHGNT2.mjs} +8 -1
  99. package/dist/cli/{chunk-2XXXFPTD.js → chunk-LTFL4JRN.js} +426 -721
  100. package/dist/cli/{chunk-YHPYUZZX.mjs → chunk-MAMVGOSC.mjs} +1 -1
  101. package/dist/cli/{chunk-URACNNLO.mjs → chunk-MN2OWLFA.mjs} +2 -2
  102. package/dist/cli/{chunk-Q3PUHXOY.js → chunk-NF4V5DTY.js} +12 -12
  103. package/dist/cli/{chunk-Q2E4E4FJ.js → chunk-NPBJI7RE.js} +8 -8
  104. package/dist/cli/chunk-NTVLGHFM.js +501 -0
  105. package/dist/cli/{chunk-HQXL5526.mjs → chunk-NUX2QHNC.mjs} +1 -1
  106. package/dist/cli/{chunk-E3PJF6YP.js → chunk-OBB4QXHA.js} +19 -4
  107. package/dist/cli/{chunk-SEFMGO3Z.js → chunk-OQQOXSYA.js} +2184 -117
  108. package/dist/cli/chunk-OZ6E3IRZ.js +6084 -0
  109. package/dist/cli/{chunk-7P5AA3SN.js → chunk-PPDBRJRW.js} +6 -1
  110. package/dist/cli/{chunk-IWBXJDZA.mjs → chunk-PZSLPBDA.mjs} +2 -2
  111. package/dist/cli/{chunk-ILHRA7AD.js → chunk-QADCFSGH.js} +7 -7
  112. package/dist/cli/{chunk-ECVLPS67.js → chunk-QJI5FIOW.js} +170 -49
  113. package/dist/cli/{chunk-I3DHIXVJ.mjs → chunk-QL22Y56M.mjs} +149 -28
  114. package/dist/cli/{chunk-SD7MXAJA.mjs → chunk-RFB25DSQ.mjs} +36 -284
  115. package/dist/cli/chunk-T44IIOT6.mjs +501 -0
  116. package/dist/cli/chunk-VK2LZ5IP.js +35 -0
  117. package/dist/cli/chunk-VKKVSFRD.js +62 -0
  118. package/dist/cli/{chunk-RWCY6YI2.js → chunk-VYKV5XHL.js} +644 -330
  119. package/dist/cli/{chunk-GSK6NHVM.js → chunk-WU4U6VSB.js} +5 -5
  120. package/dist/cli/chunk-XHLKJOTN.mjs +313 -0
  121. package/dist/cli/{chunk-MJELBQBU.mjs → chunk-XIHWSXSV.mjs} +330 -625
  122. package/dist/cli/chunk-XNZJKRJA.mjs +6084 -0
  123. package/dist/cli/chunk-ZCALLYF6.mjs +62 -0
  124. package/dist/cli/{chunk-ZBABPK6Y.js → chunk-ZFZ427HN.js} +11 -8
  125. package/dist/cli/{chunk-SJVVBWRL.mjs → chunk-ZKYEW55U.mjs} +16 -1
  126. package/dist/cli/command-docs.js +2 -2
  127. package/dist/cli/command-docs.mjs +1 -1
  128. package/dist/cli/{csv-XLGLHJ6P.js → csv-7U3FJYKZ.js} +14 -14
  129. package/dist/cli/{csv-WPSXG6ZZ.mjs → csv-ZWLDMM4A.mjs} +5 -5
  130. package/dist/cli/{db-5PTNJG4X.js → db-DNCGV5PC.js} +42 -47
  131. package/dist/cli/{db-ABS57ABJ.mjs → db-IMYXVMGI.mjs} +15 -20
  132. package/dist/cli/{describe-PVWQJ2PB.mjs → describe-Q23DWJUK.mjs} +20 -15
  133. package/dist/cli/{describe-EZS6PQXA.js → describe-S34JUX5W.js} +27 -22
  134. package/dist/cli/describe-core.d.mts +2 -2
  135. package/dist/cli/describe-core.d.ts +2 -2
  136. package/dist/cli/describe-core.js +6 -6
  137. package/dist/cli/describe-core.mjs +5 -5
  138. package/dist/cli/{executions-OKJGATQZ.mjs → executions-A73EUGSI.mjs} +8 -8
  139. package/dist/cli/{executions-FNTAFQ7Y.js → executions-XOMPX2YJ.js} +10 -10
  140. package/dist/cli/{feedback-W27HDMRR.mjs → feedback-N4GJ2POI.mjs} +11 -7
  141. package/dist/cli/{feedback-6YBOMSUA.js → feedback-QTCHNJJH.js} +13 -9
  142. package/dist/cli/{git-YOOUEL6M.mjs → git-4Q3JIQYZ.mjs} +6 -6
  143. package/dist/cli/git-I6CPBEVG.js +24 -0
  144. package/dist/cli/index.js +240 -352
  145. package/dist/cli/index.mjs +163 -275
  146. package/dist/cli/{legacy-noops-V6OKW7VR.mjs → legacy-noops-3SOVGFF7.mjs} +6 -6
  147. package/dist/cli/{legacy-noops-2VZ7XT6C.js → legacy-noops-4OSHZM34.js} +9 -9
  148. package/dist/cli/{monitors-FBWGVIUS.js → monitors-LVE2KZNG.js} +94 -94
  149. package/dist/cli/{monitors-P2YYWTWT.mjs → monitors-QP2XID2B.mjs} +8 -8
  150. package/dist/cli/{org-DVMG6H3C.mjs → org-IVRETVQA.mjs} +8 -8
  151. package/dist/cli/{org-3XUSVX5T.js → org-XFLK5IAP.js} +68 -68
  152. package/dist/cli/{play-GNC5CQAS.mjs → play-DE7VH6NU.mjs} +533 -98
  153. package/dist/cli/{play-YG5L4BWQ.js → play-XXTPPP23.js} +1067 -632
  154. package/dist/cli/{providers-7PSWG2OV.js → providers-DLD3I4JF.js} +11 -11
  155. package/dist/cli/{providers-JR33SLWL.mjs → providers-GX2NIZQQ.mjs} +8 -8
  156. package/dist/cli/{quickstart-VUOBQYIQ.mjs → quickstart-72B4L4PK.mjs} +5 -5
  157. package/dist/cli/{quickstart-FDVZ5BL3.js → quickstart-XNS3HSWC.js} +7 -7
  158. package/dist/cli/search-6NCH4HB5.js +30 -0
  159. package/dist/cli/{search-JZYLO33K.mjs → search-SUTRANJI.mjs} +9 -9
  160. package/dist/cli/{secrets-VS266FVA.js → secrets-6OBLOVEV.js} +17 -17
  161. package/dist/cli/{secrets-3MCYBT4I.mjs → secrets-FPFXXNUH.mjs} +8 -8
  162. package/dist/cli/sessions-235532DR.js +16 -0
  163. package/dist/cli/{sessions-ELLLT23E.mjs → sessions-R25I4QKN.mjs} +6 -6
  164. package/dist/cli/{settings-PZCKAFII.mjs → settings-AOP6F5PZ.mjs} +12 -12
  165. package/dist/cli/{settings-7364NMMA.js → settings-VL5FOFPN.js} +79 -79
  166. package/dist/cli/{setup-PMWYLCT6.js → setup-BSC67YT3.js} +45 -44
  167. package/dist/cli/{setup-A7GQ4KIA.mjs → setup-ZMPHBHVJ.mjs} +11 -10
  168. package/dist/cli/skills-3IWLYYRL.js +29 -0
  169. package/dist/cli/{skills-WS6BIFPQ.mjs → skills-KF65TVFO.mjs} +7 -7
  170. package/dist/cli/tools-LR66SPYU.js +44 -0
  171. package/dist/cli/{tools-BR4DOZA2.mjs → tools-SX4XIPM7.mjs} +19 -14
  172. package/dist/cli/{update-D2B7UNFT.mjs → update-QRMFRAQQ.mjs} +11 -9
  173. package/dist/cli/update-SP7UEO53.js +31 -0
  174. package/dist/cli/{workflow-PQXC2R47.mjs → workflow-FOEEEB7G.mjs} +44 -20
  175. package/dist/cli/{workflow-6ODTCYXU.js → workflow-KOCK2FLW.js} +54 -30
  176. package/dist/{client-Z9Pye1Wm.d.mts → client-74k4IPh6.d.mts} +137 -54
  177. package/dist/{client-BcvhDfJJ.d.ts → client-C1IK1f8c.d.ts} +137 -54
  178. package/dist/{compiler-manifest-Ycx-hoAr.d.mts → compiler-manifest-lzWpbV3w.d.mts} +83 -66
  179. package/dist/{compiler-manifest-Ycx-hoAr.d.ts → compiler-manifest-lzWpbV3w.d.ts} +83 -66
  180. package/dist/{index-CZXgiN3E.d.mts → index-C8Cy-YTm.d.ts} +5 -1
  181. package/dist/{index-NPG5pqxQ.d.ts → index-CtNK-0nI.d.mts} +5 -1
  182. package/dist/index.d.mts +47 -9
  183. package/dist/index.d.ts +47 -9
  184. package/dist/index.js +17 -14
  185. package/dist/index.mjs +13 -10
  186. package/dist/install-integrity.json +120 -104
  187. package/dist/plays/bundle-play-file.d.mts +3 -3
  188. package/dist/plays/bundle-play-file.d.ts +3 -3
  189. package/dist/plays/bundle-play-file.mjs +5 -4
  190. package/dist/plays/csv-data-input.js +3 -3
  191. package/dist/plays/csv-data-input.mjs +2 -2
  192. package/dist/plays/play-description.d.mts +2 -2
  193. package/dist/plays/play-description.d.ts +2 -2
  194. package/dist/plays/run-request.d.mts +2 -2
  195. package/dist/plays/run-request.d.ts +2 -2
  196. package/dist/plays/run-request.js +11 -3
  197. package/dist/plays/run-request.mjs +10 -2
  198. package/dist/release.d.mts +15 -6
  199. package/dist/release.d.ts +15 -6
  200. package/dist/release.js +2 -2
  201. package/dist/release.mjs +1 -1
  202. package/package.json +2 -2
  203. package/dist/cli/auth-3GB2K636.js +0 -40
  204. package/dist/cli/chunk-67RWR34T.mjs +0 -155
  205. package/dist/cli/chunk-CLJGSOVM.mjs +0 -1716
  206. package/dist/cli/chunk-HQY2SG3K.js +0 -83
  207. package/dist/cli/chunk-OSFWFV72.js +0 -155
  208. package/dist/cli/chunk-Q3LFI3VH.js +0 -392
  209. package/dist/cli/chunk-WPAB4DCU.mjs +0 -83
  210. package/dist/cli/chunk-YMOFWHGO.mjs +0 -392
  211. package/dist/cli/chunk-Z4VNJOF7.js +0 -1716
  212. package/dist/cli/git-YKUXXJOR.js +0 -24
  213. package/dist/cli/search-PPPYC5OZ.js +0 -30
  214. package/dist/cli/sessions-TEHEWW7O.js +0 -16
  215. package/dist/cli/skills-SYS7VRRK.js +0 -29
  216. package/dist/cli/tools-KK4BKVQR.js +0 -39
  217. package/dist/cli/update-2IV5JTX2.js +0 -29
@@ -79,6 +79,14 @@ export type {
79
79
  ToolExecution,
80
80
  } from './tool-calls';
81
81
  import { HttpClient } from './http';
82
+ import {
83
+ PlayClient,
84
+ type ClientEnvironment,
85
+ normalizePlayRunIntegrationMode,
86
+ normalizePlayStatus,
87
+ resolveStartPlayRunRequest,
88
+ runtimeSelectionHeaders,
89
+ } from './plays/client';
82
90
  import { PRODUCT_NOTIFICATION_SLACK_OAUTH_SCOPES } from '../../shared_libs/product-notifications/contract.js';
83
91
  import {
84
92
  DEFAULT_PRODUCT_NOTIFICATION_DELIVERY_TIMING,
@@ -90,7 +98,10 @@ import {
90
98
  type EffectiveProductNotificationGroup,
91
99
  type ProductNotificationGroupDraft,
92
100
  } from '../../shared_libs/product-notifications/configuration.js';
93
- import { watchRunEvents as pollRunSnapshotEvents } from './runs/watch-polling';
101
+ import {
102
+ watchRunEvents as pollRunSnapshotEvents,
103
+ type WatchPollObservation,
104
+ } from './runs/watch-polling';
94
105
  import { encodeRunLogsCursor, parseRunLogsCursor } from './runs/log-cursor';
95
106
  import {
96
107
  normalizeRunEventOperationRequest,
@@ -139,6 +150,8 @@ import type {
139
150
  PublishSharePageRequest,
140
151
  UpdateSharePageRequest,
141
152
  ToolDefinition,
153
+ ToolCategorySummary,
154
+ ToolCategoryListing,
142
155
  ProviderDefinition,
143
156
  ToolSearchOptions,
144
157
  ToolSearchResult,
@@ -159,24 +172,19 @@ import {
159
172
  isPlayRunPackage,
160
173
  mintStagedPlayFileUploads,
161
174
  normalizePlayRunStart,
175
+ CLI_PLAY_RUN_START_STREAM_PATH,
176
+ CliPlayAdmissionUnsupportedError,
162
177
  PLAY_RUN_START_STREAM_PATH,
163
178
  stagePlayFiles,
164
- startPlayRun,
165
179
  preparePlayRunAdmission,
166
180
  type MintStagedFileUpload,
181
+ type PlayRunStartOptions,
167
182
  type ResolvedStartPlayRunRequest,
168
183
  } from './plays/run-request';
169
184
  import type { PlayCompilerManifest } from '../../shared_libs/plays/compiler-manifest.js';
170
185
  import type { EnrichCompiledConfig } from './cli/enrich-play-compiler';
186
+ import { COORDINATOR_INTERNAL_TOKEN_HEADER } from '../../shared_libs/play-runtime/coordinator-headers.js';
171
187
  import {
172
- COORDINATOR_INTERNAL_TOKEN_HEADER,
173
- RUNTIME_ENVIRONMENT_TOKEN_HEADER,
174
- RETAINED_PIPELINE_RECEIVERS_HEADER,
175
- } from '../../shared_libs/play-runtime/coordinator-headers.js';
176
- import {
177
- normalizePlayRuntimeEnvironment,
178
- normalizePlayRuntimeNamespace,
179
- normalizePlayRuntimeSandboxPlacementPolicy,
180
188
  normalizePlayRuntimeSelection,
181
189
  type PlayRuntimeSelection,
182
190
  } from '../../shared_libs/play-runtime/runtime-environment.js';
@@ -189,6 +197,57 @@ export type SlackNotificationTarget =
189
197
  | { channel: string; memberId?: never }
190
198
  | { channel?: never; memberId: string };
191
199
 
200
+ type ToolDiscoveryResponse = {
201
+ view?: string;
202
+ categories?: unknown;
203
+ tools?: ToolDefinition[];
204
+ };
205
+
206
+ function invalidToolDiscoveryResponse(): DeeplineError {
207
+ return new DeeplineError(
208
+ 'The server returned an invalid tool discovery response.',
209
+ 502,
210
+ 'INVALID_TOOL_DISCOVERY_RESPONSE',
211
+ );
212
+ }
213
+
214
+ function readToolCategorySummaries(value: unknown): ToolCategorySummary[] {
215
+ if (!Array.isArray(value)) throw invalidToolDiscoveryResponse();
216
+ const seen = new Set<string>();
217
+ return value.map((item: unknown) => {
218
+ if (
219
+ !item ||
220
+ typeof item !== 'object' ||
221
+ !('name' in item) ||
222
+ typeof item.name !== 'string' ||
223
+ !item.name.trim() ||
224
+ seen.has(item.name) ||
225
+ !('count' in item) ||
226
+ typeof item.count !== 'number' ||
227
+ !Number.isSafeInteger(item.count) ||
228
+ item.count < 0
229
+ ) {
230
+ throw invalidToolDiscoveryResponse();
231
+ }
232
+ seen.add(item.name);
233
+ return { name: item.name, count: item.count };
234
+ });
235
+ }
236
+
237
+ function summarizeToolCategories(
238
+ tools: ToolDefinition[],
239
+ ): ToolCategorySummary[] {
240
+ const counts = new Map<string, number>();
241
+ for (const tool of tools) {
242
+ for (const category of tool.categories ?? []) {
243
+ counts.set(category, (counts.get(category) ?? 0) + 1);
244
+ }
245
+ }
246
+ return [...counts]
247
+ .map(([name, count]) => ({ name, count }))
248
+ .sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
249
+ }
250
+
192
251
  export type CreateNotificationInput = {
193
252
  name: string;
194
253
  provider: 'slack';
@@ -331,174 +390,6 @@ export type IngestionStorageRepairResult = {
331
390
  };
332
391
  };
333
392
 
334
- function normalizePlayRunIntegrationMode(
335
- value: unknown,
336
- ): 'live' | 'eval_stub' | 'fixture' | undefined {
337
- if (value === 'live' || value === 'eval_stub' || value === 'fixture') {
338
- return value;
339
- }
340
- return undefined;
341
- }
342
-
343
- type ClientEnvironment = Readonly<Record<string, string | undefined>>;
344
-
345
- function resolvePlayRunIntegrationMode(
346
- request: StartPlayRunRequest,
347
- env: ClientEnvironment,
348
- ): 'live' | 'eval_stub' | 'fixture' | undefined {
349
- return normalizePlayRunIntegrationMode(
350
- request.integrationMode ?? env.DEEPLINE_EVAL_INTEGRATION_MODE,
351
- );
352
- }
353
-
354
- function resolvePlayRunRuntimeSelection(
355
- request: StartPlayRunRequest,
356
- env: ClientEnvironment,
357
- ): PlayRuntimeSelection | undefined {
358
- if (request.runtime !== undefined) {
359
- const runtime = normalizePlayRuntimeSelection(request.runtime);
360
- if (!runtime) {
361
- throw new DeeplineError(
362
- 'runtime must be { environment: "preview", namespace, backend?: "daytona" | "modal", sandboxPlacementPolicy?: "policy_name@1" } with namespace matching ^[a-z][a-z0-9-]{0,30}$.',
363
- undefined,
364
- 'INVALID_RUNTIME_SELECTION',
365
- );
366
- }
367
- return runtime;
368
- }
369
- // These variables select where the app executes a run, not which app the
370
- // SDK calls. DEEPLINE_API_BASE_URL still chooses the app host. Environment
371
- // opts into remote preview routing, namespace names the isolated lane, and
372
- // the token only authorizes that selection. Omitting all three leaves the
373
- // app free to use its native runtime (local for a local app, prod for prod).
374
- const configured = env.DEEPLINE_RUNTIME_ENVIRONMENT?.trim();
375
- const configuredNamespace = env.DEEPLINE_RUNTIME_NAMESPACE?.trim();
376
- const configuredToken = env.DEEPLINE_RUNTIME_ENVIRONMENT_TOKEN?.trim();
377
- const configuredPlacementPolicy =
378
- env.DEEPLINE_RUNTIME_SANDBOX_PLACEMENT_POLICY?.trim();
379
- if (!configured) {
380
- if (configuredNamespace || configuredToken || configuredPlacementPolicy) {
381
- // Name the variables that are actually set. This branch is almost always
382
- // hit by a stale value auto-loaded from a .env/.env.local rather than by
383
- // a deliberate export, so the message has to say where to look and how
384
- // to run the command anyway.
385
- const present: string[] = [];
386
- if (configuredNamespace) present.push('DEEPLINE_RUNTIME_NAMESPACE');
387
- if (configuredToken) present.push('DEEPLINE_RUNTIME_ENVIRONMENT_TOKEN');
388
- if (configuredPlacementPolicy) {
389
- present.push('DEEPLINE_RUNTIME_SANDBOX_PLACEMENT_POLICY');
390
- }
391
- const isPlural = present.length > 1;
392
- throw new DeeplineError(
393
- [
394
- `Incomplete play runtime selection: ${present.join(' and ')} ${isPlural ? 'are' : 'is'} set but DEEPLINE_RUNTIME_ENVIRONMENT is not.`,
395
- 'Preview routing requires DEEPLINE_RUNTIME_ENVIRONMENT=preview together with DEEPLINE_RUNTIME_NAMESPACE; the token alone authorizes nothing.',
396
- `If you did not export ${isPlural ? 'these' : 'this'} yourself, ${isPlural ? 'they were' : 'it was'} most likely auto-loaded from a .env or .env.local in the current directory (bun loads those automatically, and in a git worktree .env.local is usually a symlink to the main checkout).`,
397
- `To run against the app-native runtime, clear ${isPlural ? 'them' : 'it'} for this command: ${present.map((name) => `${name}=`).join(' ')} <your deepline command>`,
398
- ].join('\n'),
399
- undefined,
400
- 'INVALID_RUNTIME_ENVIRONMENT',
401
- );
402
- }
403
- return undefined;
404
- }
405
- const environment = normalizePlayRuntimeEnvironment(configured);
406
- if (!environment) {
407
- throw new DeeplineError(
408
- `DEEPLINE_RUNTIME_ENVIRONMENT supports only explicit preview selection. Received "${configured}". Omit it to use the app-native runtime.`,
409
- undefined,
410
- 'INVALID_RUNTIME_ENVIRONMENT',
411
- );
412
- }
413
- const namespace = normalizePlayRuntimeNamespace(configuredNamespace);
414
- if (!namespace) {
415
- throw new DeeplineError(
416
- 'DEEPLINE_RUNTIME_NAMESPACE is required for preview and must match ^[a-z][a-z0-9-]{0,30}$.',
417
- undefined,
418
- 'INVALID_RUNTIME_NAMESPACE',
419
- );
420
- }
421
- const configuredBackendValue = env.DEEPLINE_PLAY_RUNNER_BACKEND?.trim();
422
- const configuredBackend =
423
- configuredBackendValue === 'daytona' || configuredBackendValue === 'modal'
424
- ? configuredBackendValue
425
- : undefined;
426
- if (configuredBackendValue && !configuredBackend) {
427
- throw new DeeplineError(
428
- `DEEPLINE_PLAY_RUNNER_BACKEND must be daytona or modal for preview runtime selection. Received "${configuredBackendValue}".`,
429
- undefined,
430
- 'INVALID_RUNTIME_BACKEND',
431
- );
432
- }
433
- if (
434
- configuredPlacementPolicy &&
435
- !normalizePlayRuntimeSandboxPlacementPolicy(configuredPlacementPolicy)
436
- ) {
437
- throw new DeeplineError(
438
- `DEEPLINE_RUNTIME_SANDBOX_PLACEMENT_POLICY must be a versioned placement policy id such as daytona_only@1. Received "${configuredPlacementPolicy}".`,
439
- undefined,
440
- 'INVALID_RUNTIME_SANDBOX_PLACEMENT_POLICY',
441
- );
442
- }
443
- return {
444
- environment,
445
- namespace,
446
- ...(configuredBackend ? { backend: configuredBackend } : {}),
447
- ...(configuredPlacementPolicy
448
- ? { sandboxPlacementPolicy: configuredPlacementPolicy }
449
- : {}),
450
- };
451
- }
452
-
453
- /**
454
- * Resolve the environment-derived run-start fields (eval integration mode,
455
- * test policy overrides, preview runtime) into explicit request fields, in the
456
- * order the SDK has always validated them. The shared body builder in
457
- * `plays/run-request` never reads the environment.
458
- */
459
- function resolveStartPlayRunRequest(
460
- request: StartPlayRunRequest,
461
- env: ClientEnvironment,
462
- ): {
463
- request: ResolvedStartPlayRunRequest;
464
- runtime: PlayRuntimeSelection | undefined;
465
- } {
466
- const integrationMode = resolvePlayRunIntegrationMode(request, env);
467
- const testPolicyOverrides =
468
- request.testPolicyOverrides ?? parseEnvTestPolicyOverrides(env);
469
- const runtime = resolvePlayRunRuntimeSelection(request, env);
470
- const resolved: ResolvedStartPlayRunRequest = { ...request };
471
- delete resolved.integrationMode;
472
- delete resolved.runtime;
473
- delete resolved.testPolicyOverrides;
474
- if (integrationMode) resolved.integrationMode = integrationMode;
475
- if (runtime) resolved.runtime = runtime;
476
- if (testPolicyOverrides) resolved.testPolicyOverrides = testPolicyOverrides;
477
- return { request: resolved, runtime };
478
- }
479
-
480
- function runtimeSelectionHeaders(
481
- runtime: PlayRuntimeSelection | undefined,
482
- env: ClientEnvironment,
483
- ): Record<string, string> | undefined {
484
- if (!runtime) return undefined;
485
- // Keep the credential out of the typed runtime payload. The app consumes it
486
- // at the HTTP boundary and never forwards it to Fly, Absurd, or Daytona.
487
- const token = env.DEEPLINE_RUNTIME_ENVIRONMENT_TOKEN?.trim();
488
- if (!token) {
489
- throw new DeeplineError(
490
- 'DEEPLINE_RUNTIME_ENVIRONMENT_TOKEN is required for explicit preview runtime selection.',
491
- undefined,
492
- 'RUNTIME_ENVIRONMENT_TOKEN_REQUIRED',
493
- );
494
- }
495
- const receivers = env.DEEPLINE_RUNTIME_RETAINED_PIPELINE_RECEIVERS?.trim();
496
- return {
497
- [RUNTIME_ENVIRONMENT_TOKEN_HEADER]: token,
498
- ...(receivers ? { [RETAINED_PIPELINE_RECEIVERS_HEADER]: receivers } : {}),
499
- };
500
- }
501
-
502
393
  /** The isolated PR estate needs its existing internal credential to read its pinned scheduler scope. */
503
394
  function isolatedCiRuntimeEventReadHeaders(
504
395
  env: ClientEnvironment,
@@ -522,40 +413,6 @@ function isolatedCiRuntimeEventReadHeaders(
522
413
  return { [COORDINATOR_INTERNAL_TOKEN_HEADER]: token };
523
414
  }
524
415
 
525
- function normalizeTestPolicyOverrides(
526
- value: unknown,
527
- source: string,
528
- ): Record<string, unknown> {
529
- if (value && typeof value === 'object' && !Array.isArray(value)) {
530
- return value as Record<string, unknown>;
531
- }
532
- throw new DeeplineError(
533
- `${source} must be a JSON object.`,
534
- undefined,
535
- 'INVALID_TEST_POLICY_OVERRIDES',
536
- );
537
- }
538
-
539
- function parseEnvTestPolicyOverrides(
540
- env: ClientEnvironment,
541
- ): Record<string, unknown> | undefined {
542
- const raw = env.DEEPLINE_TEST_POLICY_OVERRIDES;
543
- const trimmed = raw?.trim();
544
- if (!trimmed) return undefined;
545
- let parsed: unknown;
546
- try {
547
- parsed = JSON.parse(trimmed);
548
- } catch (error) {
549
- const detail = error instanceof Error ? ` ${error.message}` : '';
550
- throw new DeeplineError(
551
- `DEEPLINE_TEST_POLICY_OVERRIDES must be valid JSON.${detail}`,
552
- undefined,
553
- 'INVALID_TEST_POLICY_OVERRIDES',
554
- );
555
- }
556
- return normalizeTestPolicyOverrides(parsed, 'DEEPLINE_TEST_POLICY_OVERRIDES');
557
- }
558
-
559
416
  function sleep(ms: number): Promise<void> {
560
417
  return new Promise((resolve) => setTimeout(resolve, ms));
561
418
  }
@@ -1288,7 +1145,7 @@ export type StopAllRunsOptions = {
1288
1145
 
1289
1146
  /** Current mutable customer database namespace exposed as `client.db`. */
1290
1147
  export type DbNamespace = {
1291
- /** Run a bounded SQL query; every request is attempted once. */
1148
+ /** Run bounded SQL; unkeyed requests run once, while keyed requests retain one recovery identity across safe retries. */
1292
1149
  query: (input: CustomerDbQueryOptions) => Promise<CustomerDbQueryResult>;
1293
1150
  /** Describe the request, effects and recovery policy without executing SQL. */
1294
1151
  planQuery: (input: CustomerDbQueryOptions) => CustomerDbQueryPlan;
@@ -2433,6 +2290,10 @@ export type BillingUsageEvent = {
2433
2290
  pricing_model: string | null;
2434
2291
  policy_id: string | null;
2435
2292
  created_at: string;
2293
+ /** Present when the original request is resolved through its canonical charge. */
2294
+ charge_state?: BillingRecentUsageEntry['charge_state'];
2295
+ /** Pending/unknown amounts are null; a final amount can be zero. */
2296
+ charge_finality?: BillingRecentUsageEntry['charge_finality'];
2436
2297
  };
2437
2298
 
2438
2299
  /** One customer-facing recent billing operation from `/api/v2/billing/usage`. */
@@ -2650,54 +2511,6 @@ function preferPrebuiltPlayDescriptions<T extends PlayDescription>(
2650
2511
  .map(({ play }) => play);
2651
2512
  }
2652
2513
 
2653
- function normalizePlayStatus(raw: Record<string, unknown>): PlayStatus {
2654
- const runPackage = isPlayRunPackage(raw)
2655
- ? raw
2656
- : isPlayRunPackage(raw.package)
2657
- ? raw.package
2658
- : null;
2659
- const packageRun = runPackage?.run;
2660
- const rawStatus =
2661
- typeof raw.status === 'string'
2662
- ? raw.status
2663
- : typeof packageRun?.status === 'string'
2664
- ? packageRun.status
2665
- : null;
2666
- const status = decodePlayRunPublicStatus(rawStatus);
2667
- if (!status) {
2668
- throw new Error(
2669
- `Invalid play run lifecycle status in API response: ${JSON.stringify(rawStatus)}.`,
2670
- );
2671
- }
2672
- const runId =
2673
- typeof raw.runId === 'string'
2674
- ? raw.runId
2675
- : typeof raw.workflowId === 'string'
2676
- ? raw.workflowId
2677
- : (packageRun?.id ?? '');
2678
- const legacyOverview = runPackage?.overview ?? raw.overview;
2679
- const runStatus = runPackage?.runStatus ?? raw.runStatus;
2680
- return {
2681
- ...(raw as unknown as Omit<PlayStatus, 'runId' | 'status'>),
2682
- runId,
2683
- ...(isRecord(legacyOverview)
2684
- ? {
2685
- overview: legacyOverview as unknown as RunLifecycleStatus,
2686
- }
2687
- : {}),
2688
- ...(isRecord(runStatus)
2689
- ? { runStatus: runStatus as unknown as RunGetStatus }
2690
- : {}),
2691
- ...(runPackage
2692
- ? {
2693
- package: runPackage,
2694
- outputs: runPackage.outputs,
2695
- }
2696
- : {}),
2697
- status,
2698
- };
2699
- }
2700
-
2701
2514
  function readStringArray(value: unknown): string[] {
2702
2515
  return Array.isArray(value)
2703
2516
  ? value.filter((line): line is string => typeof line === 'string')
@@ -2905,6 +2718,7 @@ function playRunResultFromStatus(
2905
2718
  export class DeeplineClient {
2906
2719
  private readonly http: HttpClient;
2907
2720
  private readonly toolCalls: ToolCalls;
2721
+ private readonly playClient: PlayClient;
2908
2722
  private readonly config: ResolvedConfig;
2909
2723
  private readonly environment: ClientEnvironment;
2910
2724
  /** Canonical run lifecycle namespace backed by `/api/v2/runs`. */
@@ -2931,6 +2745,7 @@ export class DeeplineClient {
2931
2745
  this.config = resolveConfig(options);
2932
2746
  this.environment = this.config.environment ?? process.env;
2933
2747
  this.http = new HttpClient(this.config);
2748
+ this.playClient = new PlayClient(this.http, this.environment);
2934
2749
  this.toolCalls = new ToolCalls(
2935
2750
  this.http,
2936
2751
  this.config.timeout,
@@ -2978,7 +2793,7 @@ export class DeeplineClient {
2978
2793
  };
2979
2794
  this.db = {
2980
2795
  query: (input) => this.queryDb(input),
2981
- planQuery: (input) => planCustomerDbQuery(input),
2796
+ planQuery: (input) => planCustomerDbQuery(input, this.config.maxRetries),
2982
2797
  };
2983
2798
  this.billing = {
2984
2799
  quote: (input) =>
@@ -3220,6 +3035,57 @@ export class DeeplineClient {
3220
3035
  return res.tools;
3221
3036
  }
3222
3037
 
3038
+ /** List category counts without downloading tool definitions. */
3039
+ async listToolCategories(): Promise<ToolCategorySummary[]> {
3040
+ const response = await this.http.get<ToolDiscoveryResponse>(
3041
+ '/api/v2/tools?view=categories&compact=true',
3042
+ );
3043
+ if (response.view === 'categories') {
3044
+ return readToolCategorySummaries(response.categories);
3045
+ }
3046
+ // Older servers ignore the additive view and return their existing list.
3047
+ if (response.view === undefined && Array.isArray(response.tools)) {
3048
+ return summarizeToolCategories(response.tools);
3049
+ }
3050
+ throw invalidToolDiscoveryResponse();
3051
+ }
3052
+
3053
+ /** Read one complete category and its live category counts in one request. */
3054
+ async listToolsInCategory(
3055
+ category: string,
3056
+ options?: { compact?: boolean },
3057
+ ): Promise<ToolCategoryListing> {
3058
+ const normalizedCategory = category.trim();
3059
+ if (!normalizedCategory || category.includes(',')) {
3060
+ throw new DeeplineError(
3061
+ 'Provide one non-empty tool category.',
3062
+ 400,
3063
+ 'INVALID_TOOL_CATEGORY',
3064
+ );
3065
+ }
3066
+ const params = new URLSearchParams({
3067
+ view: 'category',
3068
+ categories: normalizedCategory,
3069
+ compact: options?.compact === true ? 'true' : 'false',
3070
+ });
3071
+ const response = await this.http.get<ToolDiscoveryResponse>(
3072
+ `/api/v2/tools?${params}`,
3073
+ );
3074
+ if (
3075
+ !Array.isArray(response.tools) ||
3076
+ (response.view !== 'category' && response.view !== undefined)
3077
+ ) {
3078
+ throw invalidToolDiscoveryResponse();
3079
+ }
3080
+ return {
3081
+ tools: response.tools,
3082
+ categories:
3083
+ response.view === 'category'
3084
+ ? readToolCategorySummaries(response.categories)
3085
+ : await this.listToolCategories(),
3086
+ };
3087
+ }
3088
+
3223
3089
  /** List discoverable providers without requiring a local plugin catalog. */
3224
3090
  async listProviders(options?: {
3225
3091
  changed?: boolean;
@@ -3394,7 +3260,7 @@ export class DeeplineClient {
3394
3260
  private async queryDb(
3395
3261
  input: CustomerDbQueryOptions,
3396
3262
  ): Promise<CustomerDbQueryResult> {
3397
- return queryCustomerDatabase(this.http, input);
3263
+ return queryCustomerDatabase(this.http, input, this.config.maxRetries);
3398
3264
  }
3399
3265
 
3400
3266
  /**
@@ -3469,21 +3335,9 @@ export class DeeplineClient {
3469
3335
  */
3470
3336
  async startPlayRun(
3471
3337
  request: StartPlayRunRequest,
3472
- options?: {
3473
- onSubmission?: (intent: {
3474
- workflowId: string;
3475
- orgId: string;
3476
- request: Record<string, unknown>;
3477
- }) => void | Promise<void>;
3478
- },
3338
+ options?: PlayRunStartOptions,
3479
3339
  ): Promise<PlayRunStart> {
3480
- const resolved = resolveStartPlayRunRequest(request, this.environment);
3481
- return startPlayRun(
3482
- this.http,
3483
- resolved.request,
3484
- runtimeSelectionHeaders(resolved.runtime, this.environment),
3485
- options?.onSubmission,
3486
- );
3340
+ return this.playClient.startPlayRun(request, options);
3487
3341
  }
3488
3342
 
3489
3343
  /**
@@ -3493,6 +3347,7 @@ export class DeeplineClient {
3493
3347
  async preparePlayRunAdmission(
3494
3348
  request: StartPlayRunRequest,
3495
3349
  options?: {
3350
+ cliAdmission?: boolean;
3496
3351
  onSubmission?: (intent: {
3497
3352
  workflowId: string;
3498
3353
  orgId: string;
@@ -3530,17 +3385,28 @@ export class DeeplineClient {
3530
3385
  );
3531
3386
  }
3532
3387
  submitted = true;
3533
- for await (const event of http.streamSse<PlayLiveEvent>(
3534
- PLAY_RUN_START_STREAM_PATH,
3535
- {
3388
+ const streamPath = options?.cliAdmission
3389
+ ? CLI_PLAY_RUN_START_STREAM_PATH
3390
+ : PLAY_RUN_START_STREAM_PATH;
3391
+ try {
3392
+ for await (const event of http.streamSse<PlayLiveEvent>(streamPath, {
3536
3393
  method: 'POST',
3537
3394
  body: JSON.parse(bodyJson),
3538
3395
  headers,
3539
3396
  signal: streamOptions?.signal,
3540
3397
  exactUrlOnly: true,
3541
- },
3542
- )) {
3543
- if (event.scope === 'play') yield event;
3398
+ })) {
3399
+ if (event.scope === 'play') yield event;
3400
+ }
3401
+ } catch (error) {
3402
+ if (
3403
+ options?.cliAdmission &&
3404
+ error instanceof DeeplineError &&
3405
+ (error.statusCode === 404 || error.statusCode === 405)
3406
+ ) {
3407
+ throw new CliPlayAdmissionUnsupportedError(error.statusCode);
3408
+ }
3409
+ throw error;
3544
3410
  }
3545
3411
  },
3546
3412
  };
@@ -4061,27 +3927,31 @@ export class DeeplineClient {
4061
3927
  workflowId: string,
4062
3928
  options?: { billing?: boolean; full?: boolean },
4063
3929
  ): Promise<PlayStatus> {
4064
- const params = new URLSearchParams();
4065
- if (options?.billing === false) {
4066
- params.set('billing', 'false');
4067
- }
4068
- if (options?.full === true) {
4069
- params.set('full', 'true');
4070
- }
4071
- const query = params.size > 0 ? `?${params.toString()}` : '';
4072
- const response = await this.http.get<Record<string, unknown>>(
4073
- `/api/v2/runs/${encodeURIComponent(workflowId)}${query}`,
4074
- );
4075
- return normalizePlayStatus(response);
3930
+ return this.playClient.getPlayStatus(workflowId, options);
4076
3931
  }
4077
3932
 
4078
- /** Poll authenticated run snapshots every two seconds and emit changed events. */
3933
+ /**
3934
+ * Poll authenticated snapshots and emit changes; `deferLogs` delays terminal logs; `omitTerminalLogs` skips them.
3935
+ */
4079
3936
  async *watchRunEvents(
4080
3937
  workflowId: string,
4081
3938
  options?: {
4082
3939
  signal?: AbortSignal;
4083
3940
  onNotice?: (message: string) => void;
4084
3941
  onRetry?: RunsWatchOptions['onRetry'];
3942
+ /** Defer log-store reads until the run is terminal; the final log tail is unchanged. */
3943
+ deferLogs?: boolean;
3944
+ /** Skip log-store reads entirely for consumers that never render run logs. */
3945
+ omitTerminalLogs?: boolean;
3946
+ /** @internal Exposes bounded request timing for CLI diagnostics. */
3947
+ onPoll?: (observation: WatchPollObservation) => void;
3948
+ /** @internal Receive the requested durable status before terminal events. */
3949
+ terminalStatus?: {
3950
+ full?: boolean;
3951
+ billing?: boolean;
3952
+ runStatus?: boolean;
3953
+ onStatus: (status: PlayStatus) => void | Promise<void>;
3954
+ };
4085
3955
  },
4086
3956
  ): AsyncGenerator<PlayLiveEvent> {
4087
3957
  for await (const event of pollRunSnapshotEvents({
@@ -4090,6 +3960,31 @@ export class DeeplineClient {
4090
3960
  signal: options?.signal,
4091
3961
  onNotice: options?.onNotice,
4092
3962
  onRetry: options?.onRetry,
3963
+ deferLogs: options?.deferLogs,
3964
+ omitTerminalLogs: options?.omitTerminalLogs,
3965
+ onPoll: options?.onPoll,
3966
+ ...(options?.terminalStatus
3967
+ ? {
3968
+ terminalStatus: {
3969
+ ...options.terminalStatus,
3970
+ onStatus: async (
3971
+ raw: Record<string, unknown>,
3972
+ expectedStatus: string,
3973
+ ) => {
3974
+ const status = normalizePlayStatus(raw);
3975
+ if (
3976
+ status.runId !== workflowId ||
3977
+ status.status !== expectedStatus
3978
+ ) {
3979
+ throw new Error(
3980
+ `Run watch returned a mismatched terminal status for ${workflowId}.`,
3981
+ );
3982
+ }
3983
+ await options.terminalStatus?.onStatus(status);
3984
+ },
3985
+ },
3986
+ }
3987
+ : {}),
4093
3988
  })) {
4094
3989
  yield event as PlayLiveEvent;
4095
3990
  }
@@ -4155,10 +4050,17 @@ export class DeeplineClient {
4155
4050
  // Forward events without retaining their log history. Only lifecycle
4156
4051
  // evidence is needed here; the final package comes from the durable read.
4157
4052
  let terminalObserved = false;
4053
+ let terminalStatus: PlayStatus | null = null;
4158
4054
  for await (const event of this.watchRunEvents(runId, {
4159
4055
  signal: options?.signal,
4160
4056
  onNotice: options?.onNotice,
4161
4057
  onRetry: options?.onRetry ?? options?.onReconnect,
4058
+ terminalStatus: {
4059
+ runStatus: true,
4060
+ onStatus: (status) => {
4061
+ terminalStatus = status;
4062
+ },
4063
+ },
4162
4064
  })) {
4163
4065
  options?.onEvent?.(event);
4164
4066
  if (isTerminalPlayRunLifecycleStatus(playLiveRunStatus(event))) {
@@ -4168,7 +4070,7 @@ export class DeeplineClient {
4168
4070
  if (options?.signal?.aborted) {
4169
4071
  throw new DeeplineError('Run watch aborted.', undefined, 'ABORTED');
4170
4072
  }
4171
- const refreshed = await this.getRunStatus(runId);
4073
+ const refreshed = terminalStatus ?? (await this.getRunStatus(runId));
4172
4074
  if (
4173
4075
  terminalObserved ||
4174
4076
  isTerminalPlayRunLifecycleStatus(refreshed.status)
@@ -4210,10 +4112,7 @@ export class DeeplineClient {
4210
4112
  * ```
4211
4113
  */
4212
4114
  async cancelPlay(workflowId: string): Promise<void> {
4213
- await this.http.request(
4214
- `/api/v2/runs/${encodeURIComponent(workflowId)}/stop`,
4215
- { method: 'POST' },
4216
- );
4115
+ return this.playClient.cancelPlay(workflowId);
4217
4116
  }
4218
4117
 
4219
4118
  /**
@@ -4226,10 +4125,7 @@ export class DeeplineClient {
4226
4125
  workflowId: string,
4227
4126
  options?: { reason?: string },
4228
4127
  ): Promise<StopPlayRunResult> {
4229
- return this.http.post<StopPlayRunResult>(
4230
- `/api/v2/runs/${encodeURIComponent(workflowId)}/stop`,
4231
- options?.reason ? { reason: options.reason } : {},
4232
- );
4128
+ return this.playClient.stopPlay(workflowId, options);
4233
4129
  }
4234
4130
 
4235
4131
  /**
@@ -4250,11 +4146,7 @@ export class DeeplineClient {
4250
4146
  * ```
4251
4147
  */
4252
4148
  async listPlayRuns(playName: string): Promise<PlayRunListItem[]> {
4253
- const encodedName = encodeURIComponent(playName);
4254
- const response = await this.http.get<{ runs: PlayRunListItem[] }>(
4255
- `/api/v2/plays/${encodedName}/runs`,
4256
- );
4257
- return response.runs ?? [];
4149
+ return this.playClient.listPlayRuns(playName);
4258
4150
  }
4259
4151
 
4260
4152
  // ---------------------------------------------------------------------------
@@ -5698,6 +5590,8 @@ export class DeeplineClient {
5698
5590
  async searchPlays(options: {
5699
5591
  query: string;
5700
5592
  compact?: boolean;
5593
+ /** Include compiled pipelines. Defaults to true for compatibility. */
5594
+ pipeline?: boolean;
5701
5595
  scope?: 'prebuilt' | 'owned' | 'all';
5702
5596
  cliInvocationId?: string;
5703
5597
  }): Promise<PlayDescription[]> {
@@ -5723,7 +5617,10 @@ export class DeeplineClient {
5723
5617
  },
5724
5618
  );
5725
5619
  const plays = (response.plays ?? []).map((play) =>
5726
- describePlayListItem(play, { ...options, pipeline: true }),
5620
+ describePlayListItem(play, {
5621
+ ...options,
5622
+ pipeline: options.pipeline ?? true,
5623
+ }),
5727
5624
  );
5728
5625
  if (scope === 'prebuilt') {
5729
5626
  return plays.filter(isPrebuiltPlayDescription);
@@ -5757,13 +5654,7 @@ export class DeeplineClient {
5757
5654
  guidance?: boolean;
5758
5655
  },
5759
5656
  ): Promise<PlayDetail> {
5760
- const encodedName = encodeURIComponent(name);
5761
- const query = options?.source
5762
- ? `?include=source&revision=${encodeURIComponent(options.source)}`
5763
- : options?.guidance
5764
- ? '?include=guidance'
5765
- : '';
5766
- return this.http.get<PlayDetail>(`/api/v2/plays/${encodedName}${query}`);
5657
+ return this.playClient.getPlay(name, options);
5767
5658
  }
5768
5659
 
5769
5660
  /** Read one trigger inventory page without loading run histories. */
@@ -5852,11 +5743,7 @@ export class DeeplineClient {
5852
5743
  name: string,
5853
5744
  request: ClearPlayHistoryRequest = {},
5854
5745
  ): Promise<ClearPlayHistoryResult> {
5855
- const encodedName = encodeURIComponent(name);
5856
- return this.http.post<ClearPlayHistoryResult>(
5857
- `/api/v2/plays/${encodedName}/history/clear`,
5858
- request,
5859
- );
5746
+ return this.playClient.clearPlayHistory(name, request);
5860
5747
  }
5861
5748
 
5862
5749
  /**
@@ -5872,12 +5759,7 @@ export class DeeplineClient {
5872
5759
  name: string,
5873
5760
  options?: { full?: boolean },
5874
5761
  ): Promise<PlayRevisionSummary[]> {
5875
- const encodedName = encodeURIComponent(name);
5876
- const suffix = options?.full ? '?full=true' : '';
5877
- const response = await this.http.get<{ versions: PlayRevisionSummary[] }>(
5878
- `/api/v2/plays/${encodedName}/versions${suffix}`,
5879
- );
5880
- return response.versions ?? [];
5762
+ return this.playClient.listPlayVersions(name, options);
5881
5763
  }
5882
5764
 
5883
5765
  /**
@@ -5902,11 +5784,7 @@ export class DeeplineClient {
5902
5784
  name: string,
5903
5785
  request: PublishPlayVersionRequest = {},
5904
5786
  ): Promise<PublishPlayVersionResult> {
5905
- const encodedName = encodeURIComponent(name);
5906
- return this.http.post<PublishPlayVersionResult>(
5907
- `/api/v2/plays/${encodedName}/live`,
5908
- request,
5909
- );
5787
+ return this.playClient.publishPlayVersion(name, request);
5910
5788
  }
5911
5789
 
5912
5790
  /**