deepline 0.3.461 → 0.3.463

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 (297) hide show
  1. package/dist/bundling-sources/sdk/src/client-core.ts +7593 -0
  2. package/dist/bundling-sources/sdk/src/client.ts +8 -7366
  3. package/dist/bundling-sources/sdk/src/http-core.ts +1239 -0
  4. package/dist/bundling-sources/sdk/src/http.ts +6 -1231
  5. package/dist/bundling-sources/sdk/src/index.ts +4 -1
  6. package/dist/bundling-sources/sdk/src/play.ts +5 -5
  7. package/dist/bundling-sources/sdk/src/plays/client-core.ts +437 -0
  8. package/dist/bundling-sources/sdk/src/plays/client.ts +4 -421
  9. package/dist/bundling-sources/sdk/src/plays/input-example.ts +3 -4
  10. package/dist/bundling-sources/sdk/src/plays/play-description.ts +1 -1
  11. package/dist/bundling-sources/sdk/src/plays/run-request.ts +1 -1
  12. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  13. package/dist/bundling-sources/sdk/src/server.ts +43 -0
  14. package/dist/bundling-sources/sdk/src/types.ts +15 -5
  15. package/dist/bundling-sources/shared_libs/integration-contracts/billing-entitlements.ts +15 -0
  16. package/dist/bundling-sources/shared_libs/monitors/billing/tamradar.ts +17 -17
  17. package/dist/bundling-sources/shared_libs/monitors/callback-security.ts +0 -307
  18. package/dist/bundling-sources/shared_libs/monitors/http-error-response.ts +3 -0
  19. package/dist/bundling-sources/shared_libs/monitors/lifecycle-notifications.ts +3 -2
  20. package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
  21. package/dist/bundling-sources/shared_libs/monitors/provider-callback-verification.ts +34 -0
  22. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +61 -0
  23. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-upstream-identity.ts +122 -2
  24. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-dead-letter.ts +11 -1
  25. package/dist/bundling-sources/shared_libs/monitors/signal-radars/inbound-failure-codes.ts +24 -0
  26. package/dist/bundling-sources/shared_libs/observability/dlq.ts +32 -0
  27. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +57 -3
  28. package/dist/bundling-sources/shared_libs/observability/scheduled-work.ts +1 -0
  29. package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +66 -1
  30. package/dist/bundling-sources/shared_libs/play-data-plane/sheet-column-storage.ts +36 -7
  31. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +250 -11
  32. package/dist/bundling-sources/shared_libs/play-runtime/array-input-store.ts +319 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +991 -359
  34. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +17 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +13 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +110 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +155 -6
  38. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +110 -6
  39. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -13
  40. package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +14 -1
  41. package/dist/bundling-sources/shared_libs/play-runtime/fixture-behavior.ts +57 -1
  42. package/dist/bundling-sources/shared_libs/play-runtime/free-company-lookup-batching.ts +218 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +42 -5
  44. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-budget-state-backend.ts +6 -1
  45. package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +92 -31
  46. package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +69 -14
  47. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +93 -23
  48. package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +15 -4
  49. package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +22 -18
  50. package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +5 -0
  51. package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +2 -0
  52. package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +190 -14
  53. package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +131 -0
  54. package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +77 -2
  55. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +271 -2
  56. package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +51 -0
  57. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/contracts.ts +2 -0
  58. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/sandbox-cleanup/job.ts +27 -1
  59. package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
  60. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
  61. package/dist/bundling-sources/shared_libs/play-runtime/provider-text-for-log.ts +63 -0
  62. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +19 -0
  63. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +112 -16
  64. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +104 -2
  65. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +265 -151
  66. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-gateway-transport.ts +17 -0
  67. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +35 -14
  68. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-sheet-persistence-retry.ts +12 -1
  69. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +4 -0
  70. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-labels.ts +36 -0
  71. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +136 -70
  72. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +237 -36
  73. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +148 -4
  74. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +6 -0
  75. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +285 -32
  76. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +251 -56
  77. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +29 -4
  78. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/sandbox-create-outcome.ts +27 -0
  79. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +22 -1
  80. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1397 -382
  81. package/dist/bundling-sources/shared_libs/play-runtime/runtime-array-input-receipts.ts +920 -0
  82. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +16 -0
  83. package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +38 -0
  84. package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +6 -0
  85. package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -1
  86. package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +30 -0
  87. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +14 -3
  88. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +31 -4
  89. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-transition.ts +47 -0
  90. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +20 -7
  91. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +12 -0
  92. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/index.ts +9 -0
  93. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +10 -0
  94. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +4 -0
  95. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +1496 -320
  96. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +31 -1
  97. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1389 -129
  98. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +36 -0
  99. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
  100. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +162 -23
  101. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +499 -115
  102. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +377 -9
  103. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-ledger-reconciliation.ts +117 -8
  104. package/dist/bundling-sources/shared_libs/play-runtime/secret-resolution-retry-policy.ts +25 -0
  105. package/dist/bundling-sources/shared_libs/play-runtime/terminal-runtime-performance.ts +391 -0
  106. package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +40 -0
  107. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +6 -0
  108. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/mapped-calls.ts +171 -0
  109. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +16 -1
  110. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +38 -12
  111. package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +33 -9
  112. package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +28 -0
  113. package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +55 -5
  114. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +41 -1
  115. package/dist/bundling-sources/shared_libs/plays/contracts.ts +4 -0
  116. package/dist/bundling-sources/shared_libs/plays/dataset.ts +9 -3
  117. package/dist/bundling-sources/shared_libs/plays/deploy/manifest-contract.ts +2 -0
  118. package/dist/bundling-sources/shared_libs/plays/deploy/manifest.ts +3 -2
  119. package/dist/bundling-sources/shared_libs/plays/deploy/project-serializer.ts +2 -2
  120. package/dist/bundling-sources/shared_libs/plays/run-output-summary.ts +66 -0
  121. package/dist/bundling-sources/shared_libs/plays/script-entry.ts +1 -1
  122. package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +43 -1
  123. package/dist/bundling-sources/shared_libs/product-notifications/content.ts +9 -0
  124. package/dist/bundling-sources/shared_libs/product-notifications/email.ts +91 -13
  125. package/dist/bundling-sources/shared_libs/product-notifications/events.ts +3 -0
  126. package/dist/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +41 -24
  127. package/dist/bundling-sources/shared_libs/security/attested-client-ip.ts +91 -0
  128. package/dist/bundling-sources/shared_libs/security/internal-actor.ts +0 -11
  129. package/dist/cli/{auth-6HJXNWUG.mjs → auth-LZLBR4C3.mjs} +5 -4
  130. package/dist/cli/auth-XPGKBJKB.js +41 -0
  131. package/dist/cli/{billing-6P5HO6QG.js → billing-6TJPNJQD.js} +152 -78
  132. package/dist/cli/{billing-MJ42N7YF.mjs → billing-OTOP5RE4.mjs} +84 -10
  133. package/dist/cli/{chunk-FCAZQ7WV.js → chunk-2NISBXMN.js} +52 -50
  134. package/dist/cli/{chunk-PNATXKLP.js → chunk-2ZIRCBYG.js} +6 -6
  135. package/dist/cli/{chunk-5FDKJQZE.js → chunk-3BOIOCNX.js} +1 -1
  136. package/dist/cli/chunk-3BVLLJ3H.mjs +1038 -0
  137. package/dist/cli/{chunk-FJZILBL7.mjs → chunk-3U5EAP6E.mjs} +5 -5
  138. package/dist/cli/{describe-FRAVCY5F.mjs → chunk-4YZKBBLZ.mjs} +19 -36
  139. package/dist/cli/{chunk-QWRHGGUH.js → chunk-5DRNNC72.js} +20 -2
  140. package/dist/cli/{chunk-Z2GUFYT6.js → chunk-5LEAXRHV.js} +11 -11
  141. package/dist/cli/{chunk-5MDIZX7M.js → chunk-5LHXOIPT.js} +8 -6
  142. package/dist/cli/{chunk-NMJ4D2WO.js → chunk-6PMCRYDA.js} +216 -91
  143. package/dist/cli/{chunk-EBU7LQ64.js → chunk-6V7KVRR5.js} +3 -3
  144. package/dist/cli/{chunk-MGXEUZHL.mjs → chunk-7D6X7IXW.mjs} +7 -5
  145. package/dist/cli/{chunk-SAZFZQRI.js → chunk-7FCYPAPP.js} +2 -2
  146. package/dist/cli/{chunk-ACCR7POB.js → chunk-7XYDDCQ2.js} +27 -27
  147. package/dist/cli/{chunk-5IYOUBFZ.js → chunk-ALZBANZI.js} +28 -54
  148. package/dist/cli/{chunk-3DNKFH2G.mjs → chunk-BAPTQDLF.mjs} +19 -1
  149. package/dist/cli/chunk-BGNWI3KH.js +827 -0
  150. package/dist/cli/{chunk-V7REJRDZ.mjs → chunk-C25QE4CH.mjs} +1 -1
  151. package/dist/cli/{chunk-FGMX4HUZ.js → chunk-CBZP6J3V.js} +29 -27
  152. package/dist/cli/{chunk-QEYHTIV4.mjs → chunk-CTQ56DXP.mjs} +10 -1
  153. package/dist/cli/{chunk-IHHLTHE7.mjs → chunk-CVQ7N5CV.mjs} +267 -38
  154. package/dist/cli/{chunk-7DH2FD7Y.mjs → chunk-D464JW3N.mjs} +5 -85
  155. package/dist/cli/{chunk-MEAIOXJL.mjs → chunk-DHXCBITQ.mjs} +7 -5
  156. package/dist/cli/chunk-F2RHUPVH.mjs +827 -0
  157. package/dist/cli/chunk-F6QV42MC.mjs +91 -0
  158. package/dist/cli/{chunk-OZBWRICM.js → chunk-FK2HNDCN.js} +2 -2
  159. package/dist/cli/{chunk-BGY2PLP7.mjs → chunk-GUT7CLOL.mjs} +23 -49
  160. package/dist/cli/{chunk-RY4IVOU3.mjs → chunk-I624J4H5.mjs} +16 -806
  161. package/dist/cli/{chunk-Z2XUZC34.js → chunk-IAYSWZDJ.js} +188 -76
  162. package/dist/cli/{chunk-FGLKOWSC.mjs → chunk-IKWRUNAP.mjs} +1 -1
  163. package/dist/cli/{chunk-KCCOQ5G5.js → chunk-JVDKZJUH.js} +511 -282
  164. package/dist/cli/{chunk-HDFRJ4IT.mjs → chunk-JVHOS3K3.mjs} +177 -65
  165. package/dist/cli/chunk-LYFKBLJI.mjs +1039 -0
  166. package/dist/cli/{chunk-SLEUWLJE.mjs → chunk-MSY22NQW.mjs} +5 -5
  167. package/dist/cli/{chunk-5FY72YOV.js → chunk-NAPTMYTY.js} +8 -8
  168. package/dist/cli/{chunk-O6QOMHCH.js → chunk-NDHJR2WZ.js} +37 -35
  169. package/dist/cli/{chunk-KXMNM4AQ.js → chunk-NMU3VR5U.js} +4 -5
  170. package/dist/cli/chunk-NTLI6P6Y.mjs +19 -0
  171. package/dist/cli/{chunk-RFONC4WJ.mjs → chunk-O3BJYD6D.mjs} +3 -3
  172. package/dist/cli/{describe-2WQY7ZCY.js → chunk-PVY4DPPF.js} +27 -44
  173. package/dist/cli/{chunk-WIYWSYDS.mjs → chunk-Q2EIZKVX.mjs} +3 -3
  174. package/dist/cli/{chunk-VZBCEA5S.mjs → chunk-RD6IQ2JY.mjs} +223 -92
  175. package/dist/cli/chunk-RGOUCIIZ.js +1039 -0
  176. package/dist/cli/{chunk-EIMG75BT.mjs → chunk-S3A4IXBQ.mjs} +4 -5
  177. package/dist/cli/{chunk-QIW7TVV6.mjs → chunk-S4XQCFES.mjs} +14 -12
  178. package/dist/cli/chunk-SKU6ECIY.js +19 -0
  179. package/dist/cli/{chunk-CRYOUPEB.js → chunk-TIRBDQ3W.js} +16 -16
  180. package/dist/cli/{chunk-G7L27KZB.mjs → chunk-TKAQR3IB.mjs} +31 -21
  181. package/dist/cli/{chunk-MDJPEGVN.js → chunk-UC4SFYNU.js} +392 -261
  182. package/dist/cli/{chunk-3BMLICF7.mjs → chunk-UIURR26V.mjs} +13 -8
  183. package/dist/cli/{chunk-TNMBPMMC.js → chunk-UROQDCVW.js} +13 -4
  184. package/dist/cli/{chunk-R64BGGRQ.mjs → chunk-VDGTTH7K.mjs} +2 -2
  185. package/dist/cli/chunk-VLEVVDWG.js +91 -0
  186. package/dist/cli/{chunk-R2GLGLDR.mjs → chunk-VPHN2HAL.mjs} +216 -91
  187. package/dist/cli/chunk-VY2GBNTX.js +1038 -0
  188. package/dist/cli/{chunk-CFUTOWE4.js → chunk-WG3KGAII.js} +8 -88
  189. package/dist/cli/{chunk-QAJAJPKK.mjs → chunk-WUMIYOXQ.mjs} +4 -2
  190. package/dist/cli/{chunk-SCIR5JXW.js → chunk-WUZS2HK6.js} +56 -51
  191. package/dist/cli/{chunk-T3MVIPHG.mjs → chunk-XDWS2JJT.mjs} +1 -1
  192. package/dist/cli/{chunk-KGQNIA37.js → chunk-XQCTG5OO.js} +44 -34
  193. package/dist/cli/{chunk-KVJ5VHW5.mjs → chunk-XW2JIYG7.mjs} +2 -2
  194. package/dist/cli/chunk-YGGIZ3VT.js +920 -0
  195. package/dist/cli/command-docs.d.mts +5 -0
  196. package/dist/cli/command-docs.d.ts +5 -0
  197. package/dist/cli/command-docs.js +2 -2
  198. package/dist/cli/command-docs.mjs +1 -1
  199. package/dist/cli/{csv-NX7NO3O6.js → csv-EH5QWR4O.js} +13 -12
  200. package/dist/cli/{csv-DQ6GW5B5.mjs → csv-OK45Z5XQ.mjs} +4 -3
  201. package/dist/cli/{db-R72DFMP6.js → db-3ESJKETS.js} +30 -27
  202. package/dist/cli/{db-2YP33M4K.mjs → db-6Z5E4HKN.mjs} +10 -7
  203. package/dist/cli/describe-PNDQB7YS.mjs +48 -0
  204. package/dist/cli/describe-QUF7VTTR.js +48 -0
  205. package/dist/cli/describe-core.d.mts +153 -5
  206. package/dist/cli/describe-core.d.ts +153 -5
  207. package/dist/cli/describe-core.js +9 -5
  208. package/dist/cli/describe-core.mjs +10 -6
  209. package/dist/cli/{executions-WFBU7L2Q.mjs → executions-2NTWQFEG.mjs} +7 -5
  210. package/dist/cli/{executions-ZLHD4QIT.js → executions-KUOBRX5V.js} +9 -7
  211. package/dist/cli/{feedback-CN3HJFVF.mjs → feedback-7RPRMSGY.mjs} +6 -5
  212. package/dist/cli/{feedback-NDV6TPHG.js → feedback-UPHAZJ4C.js} +10 -9
  213. package/dist/cli/getting-started.d.mts +6 -6
  214. package/dist/cli/getting-started.d.ts +6 -6
  215. package/dist/cli/getting-started.js +2 -2
  216. package/dist/cli/getting-started.mjs +1 -1
  217. package/dist/cli/{git-QAD6E3HW.mjs → git-SCYP6WSZ.mjs} +5 -4
  218. package/dist/cli/git-UH653WHV.js +25 -0
  219. package/dist/cli/index.js +152 -142
  220. package/dist/cli/index.mjs +56 -46
  221. package/dist/cli/{legacy-noops-KVC5QJ74.js → legacy-noops-7XMFCVRG.js} +8 -7
  222. package/dist/cli/{legacy-noops-TPTKNBI2.mjs → legacy-noops-A4KYAGI6.mjs} +5 -4
  223. package/dist/cli/{monitors-SV57JFLO.mjs → monitors-FLC5J7RI.mjs} +19 -6
  224. package/dist/cli/{monitors-KCROV6PJ.js → monitors-NZV6IX5H.js} +103 -90
  225. package/dist/cli/{org-NJYX5743.js → org-IZ7UP3XF.js} +70 -67
  226. package/dist/cli/{org-KX6QIR7A.mjs → org-LUETJ7Z5.mjs} +9 -6
  227. package/dist/cli/pages-22ML3O7O.js +252 -0
  228. package/dist/cli/pages-EUX5EAGF.mjs +252 -0
  229. package/dist/cli/{play-IQQ57L7Z.mjs → play-CDHPAKKM.mjs} +512 -1508
  230. package/dist/cli/{play-32L7EQN4.js → play-USJBQADG.js} +1090 -2086
  231. package/dist/cli/{providers-4WEC2EQN.mjs → providers-CCXZ3SQF.mjs} +7 -5
  232. package/dist/cli/{providers-ZQV6QLVQ.js → providers-WFEUNPGC.js} +10 -8
  233. package/dist/cli/{quickstart-HKUSFADF.js → quickstart-O4JSUORZ.js} +13 -12
  234. package/dist/cli/{quickstart-RQ76RIUE.mjs → quickstart-ZUULI635.mjs} +5 -4
  235. package/dist/cli/run-ISDJYJMU.js +443 -0
  236. package/dist/cli/run-QJ4NX5F5.mjs +443 -0
  237. package/dist/cli/{search-ZRAVFBZC.mjs → search-IX3XKZJ3.mjs} +8 -6
  238. package/dist/cli/search-TIFNLRPM.js +32 -0
  239. package/dist/cli/{secrets-CMJOVNVH.mjs → secrets-7VUDXTUZ.mjs} +7 -5
  240. package/dist/cli/{secrets-J3G5Y43U.js → secrets-ELQSNCTR.js} +16 -14
  241. package/dist/cli/{sessions-WY7VN4AE.js → sessions-A3FG3AZX.js} +6 -5
  242. package/dist/cli/{sessions-MDQYY5CB.mjs → sessions-VOIQ62GB.mjs} +5 -4
  243. package/dist/cli/{settings-4RWZPCT5.mjs → settings-S6N6EFBG.mjs} +14 -11
  244. package/dist/cli/{settings-HTNTFKCE.js → settings-ZTXQEMZI.js} +80 -77
  245. package/dist/cli/{setup-P3GYYZWG.mjs → setup-AYPIK4JE.mjs} +12 -10
  246. package/dist/cli/{setup-QGCAP62X.js → setup-Y3WOIFLS.js} +53 -51
  247. package/dist/cli/{skills-7NAE4ICL.mjs → skills-5SF5QWNI.mjs} +7 -6
  248. package/dist/cli/skills-MWFRMG3H.js +31 -0
  249. package/dist/cli/tools-3XNZ4J64.mjs +55 -0
  250. package/dist/cli/tools-XEC4OD3R.js +55 -0
  251. package/dist/cli/{update-GODLRKNB.mjs → update-3U4OVX5R.mjs} +9 -8
  252. package/dist/cli/update-DWYEYTZE.js +33 -0
  253. package/dist/cli/{workflow-4BXOUVEO.mjs → workflow-2M5JP7SA.mjs} +10 -8
  254. package/dist/cli/{workflow-AO3A6LXN.js → workflow-RM7H7555.js} +20 -18
  255. package/dist/client-DS2IWYZF.d.ts +10 -0
  256. package/dist/client-DTwnz_AW.d.mts +10 -0
  257. package/dist/{client-CYqG23K1.d.ts → client-core-B_6HAIBy.d.ts} +385 -12
  258. package/dist/{client-BbU5_j7n.d.mts → client-core-DzBSlY1U.d.mts} +385 -12
  259. package/dist/{compiler-manifest-CWz_sNOQ.d.ts → compiler-manifest-Dcyd3-Zd.d.mts} +43 -1
  260. package/dist/{compiler-manifest-CWz_sNOQ.d.mts → compiler-manifest-Dcyd3-Zd.d.ts} +43 -1
  261. package/dist/errors-d-sTrZhe.d.mts +142 -0
  262. package/dist/errors-yQwfgrcX.d.ts +142 -0
  263. package/dist/{index-BF2JB_Ug.d.mts → index-C6oXchjN.d.mts} +1 -1
  264. package/dist/{index-4NPXDzlD.d.ts → index-P56zy_z5.d.ts} +1 -1
  265. package/dist/index.d.mts +11 -147
  266. package/dist/index.d.ts +11 -147
  267. package/dist/index.js +16 -12
  268. package/dist/index.mjs +15 -11
  269. package/dist/install-integrity.json +141 -104
  270. package/dist/plays/bundle-play-file.d.mts +3 -3
  271. package/dist/plays/bundle-play-file.d.ts +3 -3
  272. package/dist/plays/bundle-play-file.mjs +2 -1
  273. package/dist/plays/play-description.d.mts +2 -2
  274. package/dist/plays/play-description.d.ts +2 -2
  275. package/dist/plays/play-description.js +2 -2
  276. package/dist/plays/play-description.mjs +1 -1
  277. package/dist/plays/run-request.d.mts +2 -2
  278. package/dist/plays/run-request.d.ts +2 -2
  279. package/dist/release.d.mts +1 -1
  280. package/dist/release.d.ts +1 -1
  281. package/dist/release.js +2 -2
  282. package/dist/release.mjs +1 -1
  283. package/dist/server.d.mts +17 -0
  284. package/dist/server.d.ts +17 -0
  285. package/dist/server.js +76 -0
  286. package/dist/server.mjs +76 -0
  287. package/package.json +6 -1
  288. package/dist/cli/auth-IACERYQH.js +0 -40
  289. package/dist/cli/chunk-PQUUWFXY.js +0 -95
  290. package/dist/cli/chunk-YBWAG72P.mjs +0 -95
  291. package/dist/cli/chunk-YQDUODZW.js +0 -1710
  292. package/dist/cli/git-JVI36ZFV.js +0 -24
  293. package/dist/cli/search-75X5LTDE.js +0 -30
  294. package/dist/cli/skills-BKJ53JOQ.js +0 -30
  295. package/dist/cli/tools-COWMIEJ6.mjs +0 -45
  296. package/dist/cli/tools-TASOCE7I.js +0 -45
  297. package/dist/cli/update-SJIKVME6.js +0 -32
@@ -1,1235 +1,10 @@
1
- /**
2
- * HTTP transport layer for the Deepline SDK.
3
- *
4
- * Handles authentication, retries with exponential backoff, localhost failover
5
- * (tries both `localhost` and `127.0.0.1`), and structured error mapping.
6
- *
7
- * ## Retry behavior
8
- *
9
- * - **Max attempts**: `1 + maxRetries` (default: 4 total attempts)
10
- * - **Backoff**: exponential — 1s, 2s, 4s, 8s, ... capped at 30s
11
- * - **Total automatic retry wait**: 30s per request; a longer upstream
12
- * `Retry-After` is returned to the caller instead of blocking the request
13
- * - **Retryable**: network errors, timeouts, HTTP 429 (rate limit)
14
- * - **Not retryable**: HTTP 401 (auth error), HTTP 403 and other 4xx API errors
15
- *
16
- * ## Localhost failover
17
- *
18
- * Local development hosts try loopback variants. This handles DNS resolution
19
- * differences across platforms.
20
- *
21
- * @module
22
- */
23
- import type { ResolvedConfig } from './types';
24
- import {
25
- AuthError,
26
- DeeplineError,
27
- RateLimitError,
28
- ToolExecutionError,
29
- ToolRateLimitError,
30
- } from './errors';
31
- import {
32
- deserializeToolExecutionFailure,
33
- serializeToolExecutionFailure,
34
- TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
35
- } from '../../shared_libs/plays/tool-execution-error';
36
- import { SDK_API_CONTRACT, SDK_VERSION } from './version';
37
- import { apiErrorCodeFromResponse, apiErrorMessage } from './api-error';
38
- import type { LiveEventEnvelope } from './types';
39
- import {
40
- agentSessionIdFromEnvironment,
41
- detectAgentRuntime,
42
- isCoworkLikeSandbox,
43
- } from './agent-runtime';
1
+ /** HTTP transport with the local SDK skills diagnostic enabled. */
2
+ import { HttpClient as HttpClientCore } from './http-core';
44
3
  import { readSdkSkillsLocalVersion } from './skills-version';
45
- import { deploymentProtectionHeaders } from './deployment-protection';
46
- import {
47
- ABSURD_RELEASE_OVERRIDE_HEADER,
48
- RETAINED_PIPELINE_RECEIVERS_HEADER,
49
- COORDINATOR_INTERNAL_TOKEN_HEADER,
50
- COORDINATOR_URL_OVERRIDE_HEADER,
51
- PREFERRED_RECEIPT_GATEWAY_MACHINE_ID_HEADER,
52
- RUNTIME_SCHEDULER_SCHEMA_OVERRIDE_HEADER,
53
- SYNTHETIC_RUN_HEADER,
54
- WORKER_CALLBACK_URL_OVERRIDE_HEADER,
55
- } from '../../shared_libs/play-runtime/coordinator-headers.js';
56
- import { PLAY_RUNTIME_TEST_FAULT_HEADER } from '../../shared_libs/play-runtime/test-runtime-seams.js';
57
- import {
58
- EXECUTE_RETRY_POLICY_HEADER,
59
- parseExecuteRetryPolicy,
60
- } from '../../shared_libs/integration-contracts/execute-retry-contract.js';
61
-
62
- const MAX_DIAGNOSTIC_HEADER_LENGTH = 120;
63
- const COWORK_NETWORK_HINT =
64
- 'Claude Cowork appears to be running Deepline in a network-restricted sandbox. In Claude Desktop, open Settings > Capabilities, turn on Allow network egress, and set Domain allowlist to All domains for the Cowork session.';
65
- const REQUEST_TIMEOUT_MARKER = Symbol('deeplineRequestTimeout');
66
- const REQUEST_ABORT_MARKER = Symbol('deeplineRequestAbort');
67
- const MAX_AUTOMATIC_RETRY_WAIT_MS = 30_000;
68
-
69
- interface RequestOptions {
70
- method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
71
- body?: unknown;
72
- formData?: FormData | (() => FormData);
73
- headers?: Record<string, string>;
74
- /** Per-request timeout override in milliseconds. */
75
- timeout?: number;
76
- /** Cancel this request, including body reads, failover, and retry waits. */
77
- signal?: AbortSignal;
78
- /**
79
- * Retry HTTP 408/425/5xx JSON API responses. Use only for idempotent requests;
80
- * most mutating API calls must fail loudly after the first server response.
81
- */
82
- retryApiErrors?: boolean;
83
- /**
84
- * Only explicit server-authorized responses may retry; transport failures
85
- * never retry unless `retryAmbiguousDelivery` is also set.
86
- */
87
- retryFromExecutePolicy?: boolean;
88
- /**
89
- * The server declared this tool safe to resend after a timeout or lost
90
- * response, so those failures retry and stay retryable when exhausted.
91
- */
92
- retryAmbiguousDelivery?: boolean;
93
- /** Retry budget enabled only by an explicit safe execute-policy response. */
94
- executePolicyMaxRetries?: number;
95
- /** Per-request retry override. Use 0 for possibly delivered mutating calls. */
96
- maxRetries?: number;
97
- /** Disable localhost/127.0.0.1 failover for non-idempotent requests. */
98
- exactUrlOnly?: boolean;
99
- /**
100
- * Return a server-owned 429 envelope as a DeeplineError instead of replacing
101
- * it with the transport's generic RateLimitError. Lifecycle mutations use
102
- * this when their response explains whether the upstream change applied.
103
- */
104
- preserveRateLimitResponse?: boolean;
105
- /** Enables endpoint-specific structured tool failure mapping. */
106
- toolId?: string;
107
- onResponse?: (response: Response) => void;
108
- /** Observation after the entire response body arrives, before error mapping. */
109
- onResponseBody?: (observation: {
110
- receivedAtMs: number;
111
- httpStatus: number;
112
- body: unknown;
113
- }) => void;
114
- allowNotFound?: boolean;
115
- idempotencyKey?: string;
116
- }
117
-
118
- interface StreamOptions {
119
- method?: 'GET' | 'POST';
120
- /** An unkeyed mutation must not try another URL after a lost response. */
121
- exactUrlOnly?: boolean;
122
- body?: unknown;
123
- headers?: Record<string, string>;
124
- signal?: AbortSignal;
125
- }
126
-
127
- type RequestAbortTaggedError = Error & {
128
- [REQUEST_TIMEOUT_MARKER]?: number;
129
- [REQUEST_ABORT_MARKER]?: true;
130
- };
131
-
132
- function requestCancelledError(signal: AbortSignal): RequestAbortTaggedError {
133
- const error = withErrorCause(new Error('Request aborted'), signal.reason);
134
- (error as RequestAbortTaggedError)[REQUEST_ABORT_MARKER] = true;
135
- return error;
136
- }
137
-
138
- function normalizeRequestAbortError(
139
- error: unknown,
140
- input: { timeoutMs: number; timedOut: boolean },
141
- ): Error {
142
- const normalized = error instanceof Error ? error : new Error(String(error));
143
- const tagged = normalized as RequestAbortTaggedError;
144
- if (input.timedOut) {
145
- tagged[REQUEST_TIMEOUT_MARKER] = input.timeoutMs;
146
- } else if (isAbortLikeError(normalized)) {
147
- tagged[REQUEST_ABORT_MARKER] = true;
148
- }
149
- return normalized;
150
- }
151
-
152
- /**
153
- * Merge caller-supplied headers over everything the transport already derived
154
- * from the environment, so an explicitly passed header always wins.
155
- *
156
- * HTTP header names are case-insensitive, so an existing header is removed by
157
- * case-insensitive match before the incoming name is set. Without
158
- * that, `Authorization` and `authorization` would both survive into the record
159
- * and `new Headers(record)` would concatenate the two values.
160
- */
161
- function applyExplicitHeaders(
162
- headers: Record<string, string>,
163
- explicit: Record<string, string> | undefined,
164
- ): Record<string, string> {
165
- if (!explicit) return headers;
166
- for (const [rawName, value] of Object.entries(explicit)) {
167
- const name = rawName.trim().toLowerCase();
168
- if (!name) continue;
169
- for (const existing of Object.keys(headers)) {
170
- if (existing.toLowerCase() === name) delete headers[existing];
171
- }
172
- headers[rawName.trim()] = value;
173
- }
174
- return headers;
175
- }
176
-
177
- function isAbortLikeError(error: Error): boolean {
178
- const name = error.name.toLowerCase();
179
- const message = error.message.toLowerCase();
180
- return (
181
- name === 'aborterror' ||
182
- message.includes('operation was aborted') ||
183
- message === 'aborted'
184
- );
185
- }
186
-
187
- function withErrorCause<T extends Error>(error: T, cause: unknown): T {
188
- if (cause !== null && cause !== undefined) {
189
- Object.defineProperty(error, 'cause', {
190
- value: cause,
191
- configurable: true,
192
- writable: true,
193
- });
194
- }
195
- return error;
196
- }
197
-
198
- function mapNetworkError(
199
- baseUrl: string,
200
- error: Error | null,
201
- targetLabel: string,
202
- ): {
203
- message: string;
204
- code: string;
205
- details?: Record<string, unknown>;
206
- } {
207
- const tagged = error as RequestAbortTaggedError | null;
208
- const timeoutMs = tagged?.[REQUEST_TIMEOUT_MARKER];
209
- if (typeof timeoutMs === 'number') {
210
- return {
211
- message: `Request to ${targetLabel} timed out after ${timeoutMs}ms while waiting for a response.`,
212
- code: 'NETWORK_TIMEOUT',
213
- details: { timeoutMs, target: targetLabel },
214
- };
215
- }
216
- if (tagged?.[REQUEST_ABORT_MARKER]) {
217
- return {
218
- message: `Request to ${targetLabel} was aborted before it completed.`,
219
- code: 'NETWORK_ABORTED',
220
- };
221
- }
222
- return {
223
- message: error?.message
224
- ? `Unable to connect to ${baseUrl}. ${error.message}`
225
- : `Unable to connect to ${baseUrl}. Is the computer able to access the url?`,
226
- code: 'NETWORK_ERROR',
227
- };
228
- }
229
-
230
- function describeRequestTarget(path: string): string {
231
- const toolExecuteMatch = path.match(
232
- /^\/api\/v2\/integrations\/([^/?#]+)\/execute(?:[/?#]|$)/,
233
- );
234
- if (toolExecuteMatch) {
235
- return providerLabelFromToolId(decodeURIComponent(toolExecuteMatch[1]));
236
- }
237
- return 'Deepline';
238
- }
239
-
240
- function networkDiagnosticUrl(value: string): string | undefined {
241
- try {
242
- const url = new URL(value);
243
- if (url.protocol !== 'https:' && url.protocol !== 'http:') return undefined;
244
- // Diagnostics never retain URL credentials, query values, or fragments.
245
- return `${url.origin}${url.pathname}`;
246
- } catch {
247
- // Preserve the original transport failure for malformed request URLs.
248
- return undefined;
249
- }
250
- }
251
-
252
- function providerLabelFromToolId(toolId: string): string {
253
- const normalized = toolId.trim().toLowerCase();
254
- const provider = normalized.split(/[_:./-]+/)[0];
255
- return provider || normalized || 'provider';
256
- }
257
-
258
- function isRecord(value: unknown): value is Record<string, unknown> {
259
- return value !== null && typeof value === 'object' && !Array.isArray(value);
260
- }
261
-
262
- /**
263
- * Low-level HTTP client used internally by {@link DeeplineClient}.
264
- *
265
- * You typically don't construct this directly — it's created automatically
266
- * when you instantiate `DeeplineClient` or call `Deepline.connect()`.
267
- *
268
- * @example
269
- * ```typescript
270
- * // Internal usage pattern:
271
- * const http = new HttpClient(resolvedConfig);
272
- * const tools = await http.get<{ tools: ToolDefinition[] }>('/api/v2/tools');
273
- * const result = await http.post('/api/v2/integrations/apollo/execute', { payload: input });
274
- * ```
275
- */
276
- export class HttpClient {
277
- constructor(private config: ResolvedConfig) {}
278
-
279
- private cleanDiagnosticHeader(
280
- value: string | null | undefined,
281
- ): string | null {
282
- const normalized = String(value ?? '')
283
- .replace(/[\u0000-\u001f\u007f]/g, ' ')
284
- .trim()
285
- .slice(0, MAX_DIAGNOSTIC_HEADER_LENGTH);
286
- return normalized || null;
287
- }
288
-
289
- private environment(): Readonly<Record<string, string | undefined>> {
290
- return (
291
- this.config.environment ??
292
- (typeof process !== 'undefined' ? process.env : {})
293
- );
294
- }
295
-
296
- private readSkillsVersionHeader(): string | null {
297
- const explicit = this.cleanDiagnosticHeader(
298
- this.environment().DEEPLINE_SKILLS_VERSION,
299
- );
300
- if (explicit) return explicit;
301
- try {
302
- return this.cleanDiagnosticHeader(
303
- readSdkSkillsLocalVersion(this.config.baseUrl),
304
- );
305
- } catch {
306
- return null;
307
- }
308
- }
309
-
310
- private authHeaders(extra?: Record<string, string>): Record<string, string> {
311
- const env = this.environment();
312
- const transportHeaders: Record<string, string> = {
313
- Authorization: `Bearer ${this.config.apiKey}`,
314
- 'User-Agent': `deepline-ts-sdk/${SDK_VERSION}`,
315
- 'X-Deepline-Client-Family': 'sdk',
316
- 'X-Deepline-CLI-Family': 'sdk',
317
- 'X-Deepline-Agent-Runtime': detectAgentRuntime(
318
- this.config.environment ? { env, detectCowork: false } : {},
319
- ),
320
- 'X-Deepline-CLI-Version': SDK_VERSION,
321
- 'X-Deepline-SDK-Version': SDK_VERSION,
322
- 'X-Deepline-API-Contract': SDK_API_CONTRACT,
323
- 'X-Deepline-Run-Result-Shape': 'canonical',
324
- };
325
- const headers = deploymentProtectionHeaders(env);
326
- const skillsVersion = this.readSkillsVersionHeader();
327
- if (skillsVersion) {
328
- headers['X-Deepline-Skills-Version'] = skillsVersion;
329
- }
330
- const agentSessionId = agentSessionIdFromEnvironment(env);
331
- if (agentSessionId) {
332
- headers['X-Deepline-Agent-Session-Id'] = agentSessionId;
333
- }
334
- const playArtifactR2Prefix = env.DEEPLINE_PLAY_ARTIFACT_R2_PREFIX;
335
- if (playArtifactR2Prefix) {
336
- headers['x-deepline-play-artifact-r2-prefix'] = playArtifactR2Prefix;
337
- }
338
- const coordinatorUrl = env.DEEPLINE_COORDINATOR_URL;
339
- const coordinatorInternalToken = env.DEEPLINE_INTERNAL_TOKEN;
340
- const absurdReleaseOverride = env.DEEPLINE_ABSURD_RELEASE;
341
- const preferredReceiptGatewayMachineId =
342
- env.DEEPLINE_PREFERRED_RECEIPT_GATEWAY_MACHINE_ID;
343
- if (coordinatorUrl?.trim()) {
344
- headers[COORDINATOR_URL_OVERRIDE_HEADER] = coordinatorUrl.trim();
345
- }
346
- const workerCallbackUrl = env.DEEPLINE_WORKER_CALLBACK_URL;
347
- if (workerCallbackUrl?.trim()) {
348
- headers[WORKER_CALLBACK_URL_OVERRIDE_HEADER] = workerCallbackUrl.trim();
349
- }
350
- const runtimeSchedulerSchema = env.DEEPLINE_RUNTIME_SCHEDULER_SCHEMA;
351
- if (runtimeSchedulerSchema?.trim()) {
352
- headers[RUNTIME_SCHEDULER_SCHEMA_OVERRIDE_HEADER] =
353
- runtimeSchedulerSchema.trim();
354
- }
355
- // Automated test harnesses (e.g. tests/gauntlet-e2e-tests) set DEEPLINE_SYNTHETIC_RUN
356
- // so their intentionally failing plays do not page the SDK CLI error
357
- // channel. Honored server-side only in non-prod (see plays/run route).
358
- const syntheticRun = env.DEEPLINE_SYNTHETIC_RUN;
359
- if (syntheticRun && syntheticRun.trim() && syntheticRun.trim() !== '0') {
360
- headers[SYNTHETIC_RUN_HEADER] = '1';
361
- }
362
- // Test-only runtime seam. The server validates both environment and value
363
- // before honoring this header.
364
- const runtimeTestFault = env.DEEPLINE_TEST_RUNTIME_FAULT;
365
- if (runtimeTestFault?.trim()) {
366
- headers[PLAY_RUNTIME_TEST_FAULT_HEADER] = runtimeTestFault.trim();
367
- }
368
- const retainedReceivers =
369
- env.DEEPLINE_RUNTIME_RETAINED_PIPELINE_RECEIVERS?.trim();
370
- if (retainedReceivers && coordinatorInternalToken?.trim()) {
371
- headers[RETAINED_PIPELINE_RECEIVERS_HEADER] = retainedReceivers;
372
- headers[COORDINATOR_INTERNAL_TOKEN_HEADER] =
373
- coordinatorInternalToken.trim();
374
- }
375
- if (absurdReleaseOverride?.trim() && coordinatorInternalToken?.trim()) {
376
- headers[ABSURD_RELEASE_OVERRIDE_HEADER] = absurdReleaseOverride.trim();
377
- }
378
- if (
379
- preferredReceiptGatewayMachineId?.trim() &&
380
- coordinatorInternalToken?.trim()
381
- ) {
382
- headers[PREFERRED_RECEIPT_GATEWAY_MACHINE_ID_HEADER] =
383
- preferredReceiptGatewayMachineId.trim();
384
- }
385
- if (
386
- coordinatorInternalToken?.trim() &&
387
- (coordinatorUrl?.trim() ||
388
- workerCallbackUrl?.trim() ||
389
- runtimeTestFault?.trim() ||
390
- absurdReleaseOverride?.trim() ||
391
- preferredReceiptGatewayMachineId?.trim())
392
- ) {
393
- headers[COORDINATOR_INTERNAL_TOKEN_HEADER] =
394
- coordinatorInternalToken.trim();
395
- }
396
- // Explicit client-option headers (e.g. `deepline plays run --header`) are
397
- // applied last so an operator can override an env-derived header without
398
- // rewriting the environment. Authorization of these headers stays
399
- // server-side.
400
- // Preserve layer precedence without leaving differently-cased duplicates
401
- // for Fetch to concatenate. Environment-derived headers still supersede
402
- // per-request headers, and explicit client-option headers remain last.
403
- return applyExplicitHeaders(
404
- applyExplicitHeaders(
405
- applyExplicitHeaders(transportHeaders, extra),
406
- headers,
407
- ),
408
- this.config.headers,
409
- );
410
- }
411
-
412
- /**
413
- * Send an HTTP request with automatic retries and error handling.
414
- *
415
- * @typeParam T - Expected response body type
416
- * @param path - API path (e.g. `"/api/v2/tools"`)
417
- * @param options - HTTP method, body, headers, and timeout
418
- * @returns Parsed JSON response body
419
- * @throws {@link AuthError} on Deepline-auth HTTP 401/403 (immediate, no retry)
420
- * @throws {@link RateLimitError} on HTTP 429 after all retries exhausted
421
- * @throws {@link DeeplineError} on other API errors or connection failures
422
- */
423
- async request<T = unknown>(
424
- path: string,
425
- options?: RequestOptions,
426
- ): Promise<T> {
427
- const baseUrl = this.config.baseUrl;
428
- const url = `${baseUrl}${path}`;
429
- const method = options?.method ?? 'GET';
430
- const requestStartedAt = Date.now();
431
- let fetchAttempts = 0;
432
- let lastRequestUrl = url;
433
- let networkFailedAt: number | undefined;
434
- let networkPhase:
435
- | 'before_request'
436
- | 'retry_wait'
437
- | 'awaiting_headers'
438
- | 'reading_body' = 'before_request';
439
-
440
- const headers = this.authHeaders(options?.headers);
441
-
442
- if (options?.body !== undefined) {
443
- applyExplicitHeaders(headers, { 'Content-Type': 'application/json' });
444
- }
445
-
446
- let lastError: Error | null = null;
447
- const candidateUrls = options?.exactUrlOnly
448
- ? [url]
449
- : buildCandidateUrls(url);
450
- let retryAfterDelayMs: number | null = null;
451
- let totalRetryWaitMs = 0;
452
-
453
- let maxRetries = options?.maxRetries ?? this.config.maxRetries;
454
-
455
- requestAttempts: for (let attempt = 0; attempt <= maxRetries; attempt++) {
456
- if (options?.signal?.aborted) {
457
- lastError = requestCancelledError(options.signal);
458
- networkFailedAt = Date.now();
459
- break;
460
- }
461
- if (attempt > 0) {
462
- const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1), 30_000);
463
- const delayMs =
464
- retryAfterDelayMs === null
465
- ? backoffMs
466
- : Math.max(backoffMs, retryAfterDelayMs);
467
- retryAfterDelayMs = null;
468
- if (totalRetryWaitMs + delayMs > MAX_AUTOMATIC_RETRY_WAIT_MS) {
469
- // Honor the upstream delay by returning its original error. Never
470
- // retry sooner than requested, and never let automatic retries hold
471
- // the caller for an unbounded series of Retry-After sleeps.
472
- break requestAttempts;
473
- }
474
- totalRetryWaitMs += delayMs;
475
- networkPhase = 'retry_wait';
476
- try {
477
- await sleep(delayMs, options?.signal);
478
- } catch (error) {
479
- lastError = error instanceof Error ? error : new Error(String(error));
480
- networkFailedAt = Date.now();
481
- break;
482
- }
483
- }
484
-
485
- for (const candidateUrl of candidateUrls) {
486
- if (options?.signal?.aborted) {
487
- lastError = requestCancelledError(options.signal);
488
- networkFailedAt = Date.now();
489
- break requestAttempts;
490
- }
491
- const controller = new AbortController();
492
- const timeoutMs = options?.timeout ?? this.config.timeout;
493
- let requestTimedOut = false;
494
- const timeoutId = setTimeout(() => {
495
- requestTimedOut = true;
496
- controller.abort();
497
- }, timeoutMs);
498
- const abortRequest = () => controller.abort();
499
- options?.signal?.addEventListener('abort', abortRequest, {
500
- once: true,
501
- });
502
-
503
- networkPhase = 'before_request';
504
- try {
505
- const requestBody =
506
- options?.formData !== undefined
507
- ? typeof options.formData === 'function'
508
- ? options.formData()
509
- : options.formData
510
- : options?.body !== undefined
511
- ? JSON.stringify(options.body)
512
- : undefined;
513
- fetchAttempts += 1;
514
- lastRequestUrl = candidateUrl;
515
- networkPhase = 'awaiting_headers';
516
- const response = await fetch(candidateUrl, {
517
- method,
518
- headers,
519
- body: requestBody,
520
- signal: controller.signal,
521
- });
522
-
523
- networkPhase = 'reading_body';
524
- options?.onResponse?.(response);
525
- if (response.status === 404 && options?.allowNotFound) {
526
- clearTimeout(timeoutId);
527
- return null as T;
528
- }
529
-
530
- // Receiving headers is not completion: a stalled response body must
531
- // remain inside the same request deadline and abort its connection.
532
- const body = await response.text();
533
- const receivedAtMs = Date.now();
534
- clearTimeout(timeoutId);
535
- const parsed = parseResponseBody(body);
536
- options?.onResponseBody?.({
537
- receivedAtMs,
538
- httpStatus: response.status,
539
- body: parsed,
540
- });
541
- const responseRetryAllowed =
542
- options?.retryFromExecutePolicy !== true ||
543
- parseExecuteRetryPolicy(
544
- response.headers.get(EXECUTE_RETRY_POLICY_HEADER),
545
- ) === 'transient-http-safe';
546
- if (
547
- options?.retryFromExecutePolicy === true &&
548
- responseRetryAllowed &&
549
- options.executePolicyMaxRetries !== undefined
550
- ) {
551
- maxRetries = options.executePolicyMaxRetries;
552
- }
553
-
554
- const structuredToolError =
555
- options?.toolId && !response.ok
556
- ? deserializeToolExecutionFailure(
557
- apiErrorMessage(parsed, response.status),
558
- isRecord(parsed)
559
- ? (parsed as Record<string, unknown>).tool_error
560
- : null,
561
- TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
562
- )
563
- : null;
564
- if (structuredToolError) {
565
- if (response.status === 429) {
566
- const retryAfter = parseRetryAfter(response);
567
- const failure =
568
- serializeToolExecutionFailure(structuredToolError);
569
- lastError =
570
- failure === null
571
- ? structuredToolError
572
- : new ToolRateLimitError(structuredToolError.message, {
573
- ...failure,
574
- retryAfterMs:
575
- failure.retryAfterMs ?? Math.max(0, retryAfter),
576
- });
577
- if (responseRetryAllowed && attempt < maxRetries) {
578
- retryAfterDelayMs = retryAfter;
579
- break;
580
- }
581
- throw lastError;
582
- }
583
- throw structuredToolError;
584
- }
585
-
586
- if (response.status === 429) {
587
- if (
588
- options?.preserveRateLimitResponse &&
589
- isMonitorRateLimitEnvelope(parsed)
590
- ) {
591
- throw new DeeplineError(
592
- apiErrorMessage(parsed, response.status),
593
- response.status,
594
- apiErrorCodeFromResponse(parsed),
595
- { response: parsed },
596
- );
597
- }
598
- const retryAfter = parseRetryAfter(response);
599
- lastError = new RateLimitError(retryAfter);
600
- if (responseRetryAllowed && attempt < maxRetries) {
601
- retryAfterDelayMs = retryAfter;
602
- break;
603
- }
604
- throw lastError;
605
- }
606
-
607
- if (
608
- response.status === 401 &&
609
- !isProviderOriginatedHttpError(parsed)
610
- ) {
611
- throw new AuthError(apiErrorMessage(parsed, response.status));
612
- }
613
- if (!response.ok) {
614
- const retryableApiError =
615
- options?.retryApiErrors === true &&
616
- responseRetryAllowed &&
617
- isRetryableApiErrorResponse(response.status);
618
- // A 5xx that escaped a Worker can return Cloudflare's default HTML
619
- // error page. Never surface raw HTML to CLI users: replace the
620
- // message with a structured summary and store a short flag in
621
- // details instead of the full HTML body. JSON-envelope handling
622
- // below is unchanged.
623
- const htmlError = detectHtmlErrorBody(
624
- body,
625
- response.headers.get('content-type'),
626
- );
627
- if (htmlError) {
628
- lastError = new DeeplineError(
629
- htmlError.message(response.status),
630
- response.status,
631
- 'API_ERROR',
632
- {
633
- htmlErrorPage: true,
634
- ...(htmlError.title ? { title: htmlError.title } : {}),
635
- ...(htmlError.workerThrewException
636
- ? { workerThrewException: true }
637
- : {}),
638
- },
639
- );
640
- if (retryableApiError && attempt < maxRetries) {
641
- retryAfterDelayMs = parseOptionalRetryAfter(response);
642
- break;
643
- }
644
- throw lastError;
645
- }
646
- const errorValue =
647
- typeof parsed === 'object' && parsed && 'error' in parsed
648
- ? (parsed as Record<string, unknown>).error
649
- : undefined;
650
- const msg =
651
- typeof errorValue === 'string'
652
- ? errorValue
653
- : errorValue &&
654
- typeof errorValue === 'object' &&
655
- 'message' in errorValue &&
656
- typeof (errorValue as Record<string, unknown>).message ===
657
- 'string'
658
- ? (errorValue as Record<string, string>).message
659
- : typeof parsed === 'object' &&
660
- parsed &&
661
- 'message' in parsed &&
662
- typeof (parsed as Record<string, unknown>).message ===
663
- 'string'
664
- ? (parsed as Record<string, string>).message
665
- : `HTTP ${response.status}`;
666
- const apiErrorCode = apiErrorCodeFromResponse(parsed);
667
- lastError = new DeeplineError(msg, response.status, apiErrorCode, {
668
- response: parsed,
669
- });
670
- if (retryableApiError && attempt < maxRetries) {
671
- retryAfterDelayMs = parseOptionalRetryAfter(response);
672
- break;
673
- }
674
- throw lastError;
675
- }
676
-
677
- // Vercel's deployment-protection interstitial is served as a 2xx
678
- // HTML page, so it never reaches the !ok branch above. Without this
679
- // the caller receives a string where it expected JSON and reports
680
- // whatever field it found missing — an expired `vercel login` shows
681
- // up as an unrelated validation error several layers away.
682
- if (typeof parsed === 'string') {
683
- const interstitial = detectHtmlErrorBody(
684
- body,
685
- response.headers.get('content-type'),
686
- );
687
- if (interstitial) {
688
- throw new DeeplineError(
689
- `${this.config.baseUrl} returned a deployment-protection page ` +
690
- 'instead of JSON. Set VERCEL_PROTECTION_BYPASS_TOKEN, or run ' +
691
- '`vercel login` if the CLI session expired.',
692
- response.status,
693
- 'DEPLOYMENT_PROTECTED',
694
- { htmlErrorPage: true },
695
- );
696
- }
697
- }
698
-
699
- return parsed as T;
700
- } catch (error) {
701
- clearTimeout(timeoutId);
702
- networkFailedAt = Date.now();
703
- if (options?.signal?.aborted) {
704
- lastError = requestCancelledError(options.signal);
705
- break requestAttempts;
706
- }
707
- if (error instanceof AuthError || error instanceof DeeplineError) {
708
- throw error;
709
- }
710
- if (error instanceof RateLimitError) {
711
- lastError = error;
712
- break;
713
- }
714
- lastError = normalizeRequestAbortError(error, {
715
- timeoutMs,
716
- timedOut: requestTimedOut,
717
- });
718
- if (
719
- options?.retryFromExecutePolicy &&
720
- options.retryAmbiguousDelivery !== true
721
- ) {
722
- break requestAttempts;
723
- }
724
- } finally {
725
- clearTimeout(timeoutId);
726
- options?.signal?.removeEventListener('abort', abortRequest);
727
- }
728
- }
729
-
730
- if (attempt < maxRetries) continue;
731
- }
732
-
733
- if (lastError instanceof DeeplineError) {
734
- throw lastError;
735
- }
736
- const mappedNetworkError = mapNetworkError(
737
- baseUrl,
738
- lastError,
739
- describeRequestTarget(path),
740
- );
741
- const failedAt = networkFailedAt ?? Date.now();
742
- const diagnosticUrl = networkDiagnosticUrl(lastRequestUrl);
743
- const networkDetails = {
744
- ...mappedNetworkError.details,
745
- request: {
746
- method,
747
- ...(diagnosticUrl === undefined ? {} : { url: diagnosticUrl }),
748
- failedAtUtc: new Date(failedAt).toISOString(),
749
- // Elapsed time covers the entire logical request, including retries.
750
- elapsedMs: Math.max(0, failedAt - requestStartedAt),
751
- attempts: fetchAttempts,
752
- phase: networkPhase,
753
- },
754
- };
755
- if (options?.toolId) {
756
- const code = mappedNetworkError.code;
757
- throw withErrorCause(
758
- new ToolExecutionError(
759
- withCoworkNetworkHint(mappedNetworkError.message),
760
- {
761
- toolId: options.toolId,
762
- provider: providerLabelFromToolId(options.toolId),
763
- operation: options.toolId,
764
- code,
765
- origin: 'deepline',
766
- category: 'network',
767
- // A direct client timeout has ambiguous delivery. Fail closed unless
768
- // the server returns the authoritative action delivery contract.
769
- retryable: options.retryAmbiguousDelivery === true,
770
- statusCode: null,
771
- requestId: null,
772
- retryAfterMs: null,
773
- networkKind:
774
- code === 'NETWORK_TIMEOUT'
775
- ? 'timeout'
776
- : code === 'NETWORK_ABORTED'
777
- ? 'unknown'
778
- : 'unavailable',
779
- networkScope: 'client_to_deepline',
780
- details: networkDetails,
781
- publicDetails: options.idempotencyKey
782
- ? { idempotencyKey: options.idempotencyKey }
783
- : null,
784
- },
785
- ),
786
- lastError,
787
- );
788
- }
789
- throw withErrorCause(
790
- new DeeplineError(
791
- withCoworkNetworkHint(mappedNetworkError.message),
792
- undefined,
793
- mappedNetworkError.code,
794
- networkDetails,
795
- ),
796
- lastError,
797
- );
798
- }
799
-
800
- /**
801
- * Send a GET request.
802
- *
803
- * @typeParam T - Expected response body type
804
- * @param path - API path (e.g. `"/api/v2/tools"`)
805
- */
806
- async get<T = unknown>(
807
- path: string,
808
- options?: Pick<
809
- RequestOptions,
810
- | 'retryApiErrors'
811
- | 'timeout'
812
- | 'signal'
813
- | 'maxRetries'
814
- | 'exactUrlOnly'
815
- | 'toolId'
816
- | 'onResponse'
817
- | 'onResponseBody'
818
- | 'allowNotFound'
819
- | 'idempotencyKey'
820
- | 'headers'
821
- >,
822
- ): Promise<T> {
823
- return this.request<T>(path, {
824
- method: 'GET',
825
- retryApiErrors: true,
826
- ...options,
827
- });
828
- }
829
-
830
- async *streamSse<TEvent extends LiveEventEnvelope = LiveEventEnvelope>(
831
- path: string,
832
- options?: StreamOptions,
833
- ): AsyncGenerator<TEvent> {
834
- const url = `${this.config.baseUrl}${path}`;
835
- const method = options?.method ?? 'GET';
836
- const headers = this.authHeaders({
837
- Accept: 'text/event-stream',
838
- ...options?.headers,
839
- });
840
- if (options?.body !== undefined) {
841
- applyExplicitHeaders(headers, { 'Content-Type': 'application/json' });
842
- }
843
- let lastError: Error | null = null;
844
-
845
- const candidateUrls = options?.exactUrlOnly
846
- ? [url]
847
- : buildCandidateUrls(url);
848
- for (const candidateUrl of candidateUrls) {
849
- try {
850
- const response = await fetch(candidateUrl, {
851
- method,
852
- headers,
853
- body:
854
- options?.body !== undefined
855
- ? JSON.stringify(options.body)
856
- : undefined,
857
- signal: options?.signal,
858
- });
859
-
860
- if (!response.ok) {
861
- const body = await response.text();
862
- const parsed = parseResponseBody(body);
863
- if (
864
- response.status === 401 &&
865
- !isProviderOriginatedHttpError(parsed)
866
- ) {
867
- throw new AuthError(apiErrorMessage(parsed, response.status));
868
- }
869
- const htmlError = detectHtmlErrorBody(
870
- body,
871
- response.headers.get('content-type'),
872
- );
873
- if (htmlError) {
874
- throw new DeeplineError(
875
- htmlError.message(response.status),
876
- response.status,
877
- 'API_ERROR',
878
- {
879
- htmlErrorPage: true,
880
- ...(htmlError.title ? { title: htmlError.title } : {}),
881
- ...(htmlError.workerThrewException
882
- ? { workerThrewException: true }
883
- : {}),
884
- },
885
- );
886
- }
887
- throw new DeeplineError(
888
- apiErrorMessage(parsed, response.status),
889
- response.status,
890
- apiErrorCodeFromResponse(parsed),
891
- { response: parsed },
892
- );
893
- }
894
- if (!response.body) {
895
- throw new DeeplineError('SSE response did not include a body.');
896
- }
897
-
898
- yield* decodeSseStream<TEvent>(response.body);
899
- return;
900
- } catch (error) {
901
- if (error instanceof AuthError || error instanceof DeeplineError) {
902
- throw error;
903
- }
904
- const normalized =
905
- error instanceof Error ? error : new Error(String(error));
906
- if (isAbortLikeError(normalized) && options?.signal?.aborted) {
907
- throw new DeeplineError(
908
- `Stream from ${this.config.baseUrl} was aborted by the caller.`,
909
- undefined,
910
- 'ABORTED',
911
- );
912
- }
913
- lastError = normalized;
914
- }
915
- }
916
-
917
- if (lastError && isAbortLikeError(lastError)) {
918
- throw new DeeplineError(
919
- withCoworkNetworkHint(
920
- `Unable to stream from ${this.config.baseUrl}. The remote stream was interrupted.`,
921
- ),
922
- undefined,
923
- 'PLAY_STREAM_NETWORK_ABORTED',
924
- );
925
- }
926
- throw new DeeplineError(
927
- withCoworkNetworkHint(
928
- lastError?.message
929
- ? `Unable to stream from ${this.config.baseUrl}. ${lastError.message}`
930
- : `Unable to stream from ${this.config.baseUrl}.`,
931
- ),
932
- );
933
- }
934
-
935
- /**
936
- * Send a POST request with a JSON body.
937
- *
938
- * @typeParam T - Expected response body type
939
- * @param path - API path
940
- * @param body - Request body (will be JSON-serialized)
941
- */
942
- async post<T = unknown>(
943
- path: string,
944
- body: unknown,
945
- headers?: Record<string, string>,
946
- options?: Pick<
947
- RequestOptions,
948
- | 'retryApiErrors'
949
- | 'retryFromExecutePolicy'
950
- | 'retryAmbiguousDelivery'
951
- | 'executePolicyMaxRetries'
952
- | 'timeout'
953
- | 'signal'
954
- | 'maxRetries'
955
- | 'exactUrlOnly'
956
- | 'toolId'
957
- | 'onResponse'
958
- | 'onResponseBody'
959
- | 'allowNotFound'
960
- | 'idempotencyKey'
961
- >,
962
- ): Promise<T> {
963
- return this.request<T>(path, {
964
- method: 'POST',
965
- body,
966
- headers,
967
- ...options,
968
- });
969
- }
970
-
971
- async postFormData<T = unknown>(
972
- path: string,
973
- formData: FormData | (() => FormData),
974
- headers?: Record<string, string>,
975
- ): Promise<T> {
976
- return this.request<T>(path, {
977
- method: 'POST',
978
- formData,
979
- headers,
980
- });
981
- }
982
-
983
- /**
984
- * Send a PATCH request with a JSON body.
985
- *
986
- * @typeParam T - Expected response body type
987
- * @param path - API path
988
- * @param body - JSON-serializable request body
989
- */
990
- async patch<T = unknown>(
991
- path: string,
992
- body?: unknown,
993
- headers?: Record<string, string>,
994
- ): Promise<T> {
995
- return this.request<T>(path, {
996
- method: 'PATCH',
997
- body,
998
- headers,
999
- });
1000
- }
1001
-
1002
- async put<T = unknown>(
1003
- path: string,
1004
- body?: unknown,
1005
- headers?: Record<string, string>,
1006
- ): Promise<T> {
1007
- return this.request<T>(path, { method: 'PUT', body, headers });
1008
- }
1009
-
1010
- /**
1011
- * Send a DELETE request.
1012
- *
1013
- * @typeParam T - Expected response body type
1014
- * @param path - API path
1015
- */
1016
- async delete<T = unknown>(path: string): Promise<T> {
1017
- return this.request<T>(path, { method: 'DELETE' });
1018
- }
1019
- }
1020
-
1021
- function parseResponseBody(body: string): unknown {
1022
- try {
1023
- return JSON.parse(body);
1024
- } catch {
1025
- return body;
1026
- }
1027
- }
1028
-
1029
- /**
1030
- * A provider can reject its own credential with HTTP 401 while the caller's
1031
- * Deepline API key remains valid. The API envelope is authoritative in that
1032
- * case, so preserve it as a regular DeeplineError rather than prompting the
1033
- * caller to replace DEEPLINE_API_KEY.
1034
- */
1035
- function isProviderOriginatedHttpError(parsed: unknown): boolean {
1036
- const response = asRecord(parsed);
1037
- const error = asRecord(response?.error);
1038
- const failureOrigin = error?.failure_origin ?? response?.failure_origin;
1039
- const code = error?.code ?? response?.code;
1040
- return failureOrigin === 'provider' || code === 'UPSTREAM_BLOCKED';
1041
- }
1042
-
1043
- /**
1044
- * A monitor deployment may receive a safe, actionable 429 from Deepline after
1045
- * an upstream lifecycle attempt. Do not treat a CDN/WAF 429 as that envelope:
1046
- * it can be arbitrary HTML or text and must retain normal RateLimitError
1047
- * behavior.
1048
- */
1049
- function isMonitorRateLimitEnvelope(parsed: unknown): boolean {
1050
- const response = asRecord(parsed);
1051
- const error = asRecord(response?.error);
1052
- return (
1053
- (error?.code === 'monitor_upstream_rate_limited' ||
1054
- error?.code === 'monitor_preview_rate_limited') &&
1055
- typeof error.message === 'string'
1056
- );
1057
- }
1058
-
1059
- function asRecord(value: unknown): Record<string, unknown> | null {
1060
- return typeof value === 'object' && value !== null
1061
- ? (value as Record<string, unknown>)
1062
- : null;
1063
- }
1064
-
1065
- function isRetryableApiErrorResponse(status: number): boolean {
1066
- return status === 408 || status === 425 || (status >= 500 && status < 600);
1067
- }
1068
-
1069
- /**
1070
- * Detect a raw Cloudflare HTML error page in an error response body.
1071
- *
1072
- * A 5xx that escaped a Worker can return Cloudflare's default HTML error page
1073
- * ("Worker threw exception" / error code 1042). We must never surface raw HTML
1074
- * to CLI users — it lands verbatim in `DeeplineError.message`/`details`. When
1075
- * detected, we synthesize a structured message (status + extracted <title>) and
1076
- * preserve the literal token `Worker threw exception` when present, since SDK
1077
- * retry classifiers (`isTransientPlayRunReadError`) regex-match on it.
1078
- */
1079
- function detectHtmlErrorBody(
1080
- body: string,
1081
- contentType?: string | null,
1082
- ): {
1083
- title?: string;
1084
- workerThrewException: boolean;
1085
- message: (status: number) => string;
1086
- } | null {
1087
- const trimmed = body.trim();
1088
- const lower = trimmed.toLowerCase();
1089
- const isHtml =
1090
- (contentType ?? '').toLowerCase().includes('text/html') ||
1091
- lower.startsWith('<!doctype') ||
1092
- lower.startsWith('<html');
1093
- if (!isHtml) {
1094
- return null;
1095
- }
1096
- const titleMatch = trimmed.match(/<title[^>]*>([\s\S]*?)<\/title>/i);
1097
- const title = titleMatch?.[1]?.replace(/\s+/g, ' ').trim() || undefined;
1098
- const workerThrewException = /worker threw exception/i.test(trimmed);
1099
- return {
1100
- title,
1101
- workerThrewException,
1102
- message: (status: number): string => {
1103
- // Detail segments joined with ': ', then the suppression note appended
1104
- // in parens so it never reads as another colon-delimited segment.
1105
- const segments = [`HTTP ${status}`];
1106
- if (workerThrewException) {
1107
- segments.push('Worker threw exception');
1108
- }
1109
- if (title) {
1110
- segments.push(title);
1111
- }
1112
- return `${segments.join(': ')} (Cloudflare HTML error page suppressed)`;
1113
- },
1114
- };
1115
- }
1116
-
1117
- /** Parse the `Retry-After` header as milliseconds. Falls back to 5000ms. */
1118
- function parseRetryAfter(response: Response): number {
1119
- return parseOptionalRetryAfter(response) ?? 5000;
1120
- }
1121
-
1122
- function parseOptionalRetryAfter(response: Response): number | null {
1123
- const header = response.headers.get('retry-after');
1124
- if (header) {
1125
- const seconds = Number(header);
1126
- if (Number.isFinite(seconds) && seconds > 0) {
1127
- return seconds * 1000;
1128
- }
1129
- }
1130
- return null;
1131
- }
1132
-
1133
- /**
1134
- * For local development URLs, generate loopback variants to handle platform DNS
1135
- * differences.
1136
- */
1137
- function buildCandidateUrls(url: string): string[] {
1138
- try {
1139
- const parsed = new URL(url);
1140
- const candidates = [url];
1141
- if (parsed.hostname === 'localhost') {
1142
- const loopback = new URL(url);
1143
- loopback.hostname = '127.0.0.1';
1144
- candidates.push(loopback.toString());
1145
- }
1146
- return [...new Set(candidates)];
1147
- } catch {
1148
- return [url];
1149
- }
1150
- }
1151
-
1152
- async function* decodeSseStream<TEvent extends LiveEventEnvelope>(
1153
- body: ReadableStream<Uint8Array>,
1154
- ): AsyncGenerator<TEvent> {
1155
- const reader = body.getReader();
1156
- const decoder = new TextDecoder();
1157
- let buffered = '';
1158
-
1159
- try {
1160
- while (true) {
1161
- const { value, done } = await reader.read();
1162
- if (done) break;
1163
- buffered += decoder.decode(value, { stream: true });
1164
- const frames = buffered.split(/\r?\n\r?\n/);
1165
- buffered = frames.pop() ?? '';
1166
- for (const frame of frames) {
1167
- const event = decodeSseFrame<TEvent>(frame);
1168
- if (event) {
1169
- yield event;
1170
- }
1171
- }
1172
- }
1173
-
1174
- buffered += decoder.decode();
1175
- const event = decodeSseFrame<TEvent>(buffered);
1176
- if (event) {
1177
- yield event;
1178
- }
1179
- } finally {
1180
- reader.releaseLock();
1181
- }
1182
- }
1183
-
1184
- function decodeSseFrame<TEvent extends LiveEventEnvelope>(
1185
- frame: string,
1186
- ): TEvent | null {
1187
- const data = frame
1188
- .split(/\r?\n/)
1189
- .filter((line) => line.startsWith('data:'))
1190
- .map((line) => line.slice('data:'.length).trimStart())
1191
- .join('\n')
1192
- .trim();
1193
- if (!data) {
1194
- return null;
1195
- }
1196
- const parsed = JSON.parse(data) as Partial<LiveEventEnvelope>;
1197
- if (
1198
- !parsed ||
1199
- typeof parsed !== 'object' ||
1200
- typeof parsed.cursor !== 'string' ||
1201
- typeof parsed.streamId !== 'string' ||
1202
- typeof parsed.scope !== 'string' ||
1203
- typeof parsed.type !== 'string' ||
1204
- typeof parsed.at !== 'string'
1205
- ) {
1206
- return null;
1207
- }
1208
- return parsed as TEvent;
1209
- }
1210
-
1211
- function sleep(ms: number, signal?: AbortSignal): Promise<void> {
1212
- return new Promise((resolve, reject) => {
1213
- if (signal?.aborted) {
1214
- reject(requestCancelledError(signal));
1215
- return;
1216
- }
1217
- const timeoutId = setTimeout(() => {
1218
- signal?.removeEventListener('abort', abort);
1219
- resolve();
1220
- }, ms);
1221
- const abort = () => {
1222
- clearTimeout(timeoutId);
1223
- signal?.removeEventListener('abort', abort);
1224
- reject(requestCancelledError(signal!));
1225
- };
1226
- signal?.addEventListener('abort', abort, { once: true });
1227
- });
1228
- }
4
+ import type { ResolvedConfig } from './types';
1229
5
 
1230
- function withCoworkNetworkHint(message: string): string {
1231
- if (!isCoworkLikeSandbox() || message.includes(COWORK_NETWORK_HINT)) {
1232
- return message;
6
+ export class HttpClient extends HttpClientCore {
7
+ constructor(config: ResolvedConfig) {
8
+ super(config, readSdkSkillsLocalVersion);
1233
9
  }
1234
- return `${message}\n${COWORK_NETWORK_HINT}`;
1235
10
  }