@rynx-ai/server 0.1.11-beta.4 → 0.1.11-beta.41

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 (497) hide show
  1. package/dist/control-api.d.ts +17 -4
  2. package/dist/control-api.js +722 -84
  3. package/dist/control-web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  4. package/dist/control-web/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  5. package/dist/control-web/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  6. package/dist/control-web/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  7. package/dist/control-web/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  8. package/dist/control-web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  9. package/dist/control-web/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  10. package/dist/control-web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  11. package/dist/control-web/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  12. package/dist/control-web/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  13. package/dist/control-web/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  14. package/dist/control-web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  15. package/dist/control-web/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  16. package/dist/control-web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  17. package/dist/control-web/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  18. package/dist/control-web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  19. package/dist/control-web/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  20. package/dist/control-web/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  21. package/dist/control-web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  22. package/dist/control-web/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  23. package/dist/control-web/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  24. package/dist/control-web/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  25. package/dist/control-web/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  26. package/dist/control-web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  27. package/dist/control-web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  28. package/dist/control-web/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  29. package/dist/control-web/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  30. package/dist/control-web/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  31. package/dist/control-web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  32. package/dist/control-web/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  33. package/dist/control-web/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  34. package/dist/control-web/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  35. package/dist/control-web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  36. package/dist/control-web/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  37. package/dist/control-web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  38. package/dist/control-web/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  39. package/dist/control-web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  40. package/dist/control-web/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  41. package/dist/control-web/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  42. package/dist/control-web/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  43. package/dist/control-web/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  44. package/dist/control-web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  45. package/dist/control-web/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  46. package/dist/control-web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  47. package/dist/control-web/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  48. package/dist/control-web/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  49. package/dist/control-web/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  50. package/dist/control-web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  51. package/dist/control-web/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  52. package/dist/control-web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  53. package/dist/control-web/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  54. package/dist/control-web/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  55. package/dist/control-web/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  56. package/dist/control-web/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  57. package/dist/control-web/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  58. package/dist/control-web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  59. package/dist/control-web/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  60. package/dist/control-web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  61. package/dist/control-web/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  62. package/dist/control-web/assets/abap-CLvhMVsD.js +1 -0
  63. package/dist/control-web/assets/abnfDiagram-VRR7QNED-D_NL89dn.js +1 -0
  64. package/dist/control-web/assets/actionscript-3--17pq3dv.js +1 -0
  65. package/dist/control-web/assets/ada-C5qYipkI.js +1 -0
  66. package/dist/control-web/assets/andromeeda-vGVdxbeo.js +1 -0
  67. package/dist/control-web/assets/angular-html-DlZBZkSp.js +1 -0
  68. package/dist/control-web/assets/angular-ts-BVPGOT0K.js +1 -0
  69. package/dist/control-web/assets/apache-U0d_L8uA.js +1 -0
  70. package/dist/control-web/assets/apex-CGTLDQj6.js +1 -0
  71. package/dist/control-web/assets/apl-cDmXqmZ-.js +1 -0
  72. package/dist/control-web/assets/applescript-CCn79oCD.js +1 -0
  73. package/dist/control-web/assets/ara-4CJ0cIlV.js +1 -0
  74. package/dist/control-web/assets/arc-Pry-7G1_.js +1 -0
  75. package/dist/control-web/assets/architecture-TIHT7OUA-C9wU1KtW.js +1 -0
  76. package/dist/control-web/assets/architectureDiagram-ZJ3FMSHR-CV0rxVH6.js +36 -0
  77. package/dist/control-web/assets/array-BifhSqXX.js +1 -0
  78. package/dist/control-web/assets/asciidoc-DE70LPWp.js +1 -0
  79. package/dist/control-web/assets/asm-Cmm7eHzH.js +1 -0
  80. package/dist/control-web/assets/astro-B1Q6BwBx.js +1 -0
  81. package/dist/control-web/assets/aurora-x-CDeNXAV0.js +1 -0
  82. package/dist/control-web/assets/awk-BWXHIvNe.js +1 -0
  83. package/dist/control-web/assets/ayu-dark-DluEY0Gj.js +1 -0
  84. package/dist/control-web/assets/ayu-light-C3h-C4tm.js +1 -0
  85. package/dist/control-web/assets/ayu-mirage-Bqwy1Gya.js +1 -0
  86. package/dist/control-web/assets/ballerina-B7ZEbQpA.js +1 -0
  87. package/dist/control-web/assets/bat-Bo4NYOV-.js +1 -0
  88. package/dist/control-web/assets/beancount-D-usSTwE.js +1 -0
  89. package/dist/control-web/assets/berry-DKpUyyne.js +1 -0
  90. package/dist/control-web/assets/bibtex-Ci_nEsc7.js +1 -0
  91. package/dist/control-web/assets/bicep-CUHmPFLl.js +1 -0
  92. package/dist/control-web/assets/bird2-C2hNVINV.js +1 -0
  93. package/dist/control-web/assets/blade-Xpu-LGTm.js +1 -0
  94. package/dist/control-web/assets/blockDiagram-677ZJIJ3-Cc7nrkZh.js +132 -0
  95. package/dist/control-web/assets/bsl-BkkzgIyY.js +1 -0
  96. package/dist/control-web/assets/c-iCihek07.js +1 -0
  97. package/dist/control-web/assets/c3-CnJL0r0V.js +1 -0
  98. package/dist/control-web/assets/c4Diagram-LMCZKHZV-BPRU9m-F.js +10 -0
  99. package/dist/control-web/assets/cadence-CQ2zXKGN.js +1 -0
  100. package/dist/control-web/assets/cairo-DLTphjLi.js +1 -0
  101. package/dist/control-web/assets/catppuccin-frappe-3VR1Za6u.js +1 -0
  102. package/dist/control-web/assets/catppuccin-latte-DwIHMF0Q.js +1 -0
  103. package/dist/control-web/assets/catppuccin-macchiato-DYnBP6_5.js +1 -0
  104. package/dist/control-web/assets/catppuccin-mocha-DYhrFGRu.js +1 -0
  105. package/dist/control-web/assets/channel-BFm2_j8K.js +1 -0
  106. package/dist/control-web/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  107. package/dist/control-web/assets/chunk-32BRIVSS-Bbq3O54m.js +1 -0
  108. package/dist/control-web/assets/chunk-52WLFC77-sD4al-Ob.js +10 -0
  109. package/dist/control-web/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  110. package/dist/control-web/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  111. package/dist/control-web/assets/chunk-C7G6YPKG-DqHaDS1O.js +1 -0
  112. package/dist/control-web/assets/chunk-EX3LRPZG-36GNQ5wp.js +231 -0
  113. package/dist/control-web/assets/chunk-HOUHSVGY-DeZ63q1j.js +1 -0
  114. package/dist/control-web/assets/chunk-ICXQ74PX-D2yF6lD_.js +2 -0
  115. package/dist/control-web/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  116. package/dist/control-web/assets/chunk-KEIR6QF5-BICK3FdT.js +161 -0
  117. package/dist/control-web/assets/chunk-MOJQB5TN-CdaKyBz5.js +88 -0
  118. package/dist/control-web/assets/chunk-OGEWGWER-eOXC7kiH.js +1 -0
  119. package/dist/control-web/assets/chunk-PUDLZKDR-6w0LILL_.js +156 -0
  120. package/dist/control-web/assets/chunk-Q4XR5HBZ-CXgD5TGL.js +70 -0
  121. package/dist/control-web/assets/chunk-RYQCIY6F-BsoV8yK2.js +1 -0
  122. package/dist/control-web/assets/chunk-V7JOEXUC-BfoZ78b6.js +206 -0
  123. package/dist/control-web/assets/chunk-VR4S4FIN-BW2gCEMQ.js +1 -0
  124. package/dist/control-web/assets/chunk-WYO6CB5R-CHn7hulw.js +128 -0
  125. package/dist/control-web/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
  126. package/dist/control-web/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  127. package/dist/control-web/assets/chunk-ZGVPDNZ5-CmFP0-fr.js +62 -0
  128. package/dist/control-web/assets/clarity-SemFz856.js +1 -0
  129. package/dist/control-web/assets/classDiagram-OUVF2IWQ-CUe_bETB.js +1 -0
  130. package/dist/control-web/assets/classDiagram-v2-EOCWNBFH-CUe_bETB.js +1 -0
  131. package/dist/control-web/assets/clojure-DqKBuwfJ.js +1 -0
  132. package/dist/control-web/assets/cmake-Bj61d0ZC.js +1 -0
  133. package/dist/control-web/assets/cobol-BsV-839J.js +1 -0
  134. package/dist/control-web/assets/codeowners-C8r90Shi.js +1 -0
  135. package/dist/control-web/assets/codeql-oeQT6MSM.js +1 -0
  136. package/dist/control-web/assets/coffee-CiiSLhB6.js +1 -0
  137. package/dist/control-web/assets/common-lisp-Cv5bFMCO.js +1 -0
  138. package/dist/control-web/assets/coq-BrsZFFmf.js +1 -0
  139. package/dist/control-web/assets/cose-bilkent-JH36ORCC-lJEhNiw_.js +1 -0
  140. package/dist/control-web/assets/cpp-DjoE5qBx.js +1 -0
  141. package/dist/control-web/assets/crystal-DDxHDkHz.js +1 -0
  142. package/dist/control-web/assets/csharp-Ct8U2NOr.js +1 -0
  143. package/dist/control-web/assets/css-LjpOdHib.js +1 -0
  144. package/dist/control-web/assets/csv-Dx-8-gkx.js +1 -0
  145. package/dist/control-web/assets/cue-CE9AQfxI.js +1 -0
  146. package/dist/control-web/assets/cynefin-VYW2F7L2-NaLr7Qlq.js +1 -0
  147. package/dist/control-web/assets/cynefinDiagram-TSTJHNR4-C90wpjAI.js +62 -0
  148. package/dist/control-web/assets/cypher-ClKdZ_lG.js +1 -0
  149. package/dist/control-web/assets/cytoscape.esm-B-NFISlW.js +321 -0
  150. package/dist/control-web/assets/d-qD-0Kul2.js +1 -0
  151. package/dist/control-web/assets/dagre-Buvkdvvj.js +1 -0
  152. package/dist/control-web/assets/dagre-VKFMJZFB-BxrPFWTb.js +4 -0
  153. package/dist/control-web/assets/dark-plus-Cs2F2srj.js +1 -0
  154. package/dist/control-web/assets/dart-DkHntEIa.js +1 -0
  155. package/dist/control-web/assets/dax-BkyTk9wS.js +1 -0
  156. package/dist/control-web/assets/defaultLocale-BFoDCU3G.js +1 -0
  157. package/dist/control-web/assets/desktop-Dlh5hvp9.js +1 -0
  158. package/dist/control-web/assets/diagram-FQU43EPY-VIQINsvz.js +3 -0
  159. package/dist/control-web/assets/diagram-G47NLZAW-DFeAfYXn.js +24 -0
  160. package/dist/control-web/assets/diagram-NH7WQ7WH-ATzdppDd.js +24 -0
  161. package/dist/control-web/assets/diagram-OA4YK3LP-DJZpWmbl.js +30 -0
  162. package/dist/control-web/assets/diagram-WEI45ONY-CqDHcW3g.js +41 -0
  163. package/dist/control-web/assets/diff-woXpYk--.js +1 -0
  164. package/dist/control-web/assets/dist-Dx9YWgcW.js +153 -0
  165. package/dist/control-web/assets/dist-v5Q1xZ2K.js +1 -0
  166. package/dist/control-web/assets/docker-IyjqRm3v.js +1 -0
  167. package/dist/control-web/assets/dotenv-_5a1GRtc.js +1 -0
  168. package/dist/control-web/assets/dracula-BHWKrbxM.js +1 -0
  169. package/dist/control-web/assets/dracula-soft-5eyTD99u.js +1 -0
  170. package/dist/control-web/assets/dream-maker-DW3nJb8Q.js +1 -0
  171. package/dist/control-web/assets/ebnfDiagram-CCIWWBDH-DnP6dHND.js +1 -0
  172. package/dist/control-web/assets/edge-8z7Jp9dO.js +1 -0
  173. package/dist/control-web/assets/elixir-CUV54ev5.js +1 -0
  174. package/dist/control-web/assets/elm-o4NJxfws.js +1 -0
  175. package/dist/control-web/assets/emacs-lisp-C9PiwqqW.js +1 -0
  176. package/dist/control-web/assets/erDiagram-Q63AITRT-Bo8bFqrZ.js +85 -0
  177. package/dist/control-web/assets/erb-CIsHcwm1.js +1 -0
  178. package/dist/control-web/assets/erlang-Cphh6RMH.js +1 -0
  179. package/dist/control-web/assets/eventmodeling-45OFAUF4-DTN8wqsu.js +1 -0
  180. package/dist/control-web/assets/everforest-dark-sB-x3p7T.js +1 -0
  181. package/dist/control-web/assets/everforest-light-Df2xbC6M.js +1 -0
  182. package/dist/control-web/assets/fennel-DQxkIbk2.js +1 -0
  183. package/dist/control-web/assets/fish-BJitypiv.js +1 -0
  184. package/dist/control-web/assets/flowDiagram-23GEKE2U-BwjqRyvd.js +1 -0
  185. package/dist/control-web/assets/fluent-C03EYrpw.js +1 -0
  186. package/dist/control-web/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
  187. package/dist/control-web/assets/fortran-free-form-CYNrtFtB.js +1 -0
  188. package/dist/control-web/assets/fsharp-D13ZGOAj.js +1 -0
  189. package/dist/control-web/assets/ganttDiagram-NO4QXBWP-kxQaBTzd.js +292 -0
  190. package/dist/control-web/assets/gdresource-C0sCabJj.js +1 -0
  191. package/dist/control-web/assets/gdscript-Cp2uCuqX.js +1 -0
  192. package/dist/control-web/assets/gdshader-CBce3t8t.js +1 -0
  193. package/dist/control-web/assets/genie-CV2tkWYe.js +1 -0
  194. package/dist/control-web/assets/gherkin-DExj1W_8.js +1 -0
  195. package/dist/control-web/assets/git-commit-BSykSTBG.js +1 -0
  196. package/dist/control-web/assets/git-rebase-BDPpS8w6.js +1 -0
  197. package/dist/control-web/assets/gitGraph-TEB2WS4Q-a646NnuJ.js +1 -0
  198. package/dist/control-web/assets/gitGraphDiagram-IHSO6WYX-BBe0q0At.js +106 -0
  199. package/dist/control-web/assets/github-dark-C-LZuMrd.js +1 -0
  200. package/dist/control-web/assets/github-dark-default-DXG-b-1a.js +1 -0
  201. package/dist/control-web/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
  202. package/dist/control-web/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
  203. package/dist/control-web/assets/github-light-EUqPIrTm.js +1 -0
  204. package/dist/control-web/assets/github-light-default-BXViO-2h.js +1 -0
  205. package/dist/control-web/assets/github-light-high-contrast-B68TUdTA.js +1 -0
  206. package/dist/control-web/assets/gleam-CSRkHgEL.js +1 -0
  207. package/dist/control-web/assets/glimmer-js-OEO36pDk.js +1 -0
  208. package/dist/control-web/assets/glimmer-ts-BnAPyISE.js +1 -0
  209. package/dist/control-web/assets/glsl-D5MA2a_X.js +1 -0
  210. package/dist/control-web/assets/gn-ilITqXS6.js +1 -0
  211. package/dist/control-web/assets/gnuplot-7GGW24-e.js +1 -0
  212. package/dist/control-web/assets/go-BJwz_mda.js +1 -0
  213. package/dist/control-web/assets/graphlib-DS17s2tU.js +1 -0
  214. package/dist/control-web/assets/graphql-Ctjuxyvl.js +1 -0
  215. package/dist/control-web/assets/groovy-CacY0gHj.js +1 -0
  216. package/dist/control-web/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
  217. package/dist/control-web/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
  218. package/dist/control-web/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
  219. package/dist/control-web/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
  220. package/dist/control-web/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
  221. package/dist/control-web/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
  222. package/dist/control-web/assets/hack-D_mkkoLd.js +1 -0
  223. package/dist/control-web/assets/haml-mpgecWZ6.js +1 -0
  224. package/dist/control-web/assets/handlebars-CAx_777f.js +1 -0
  225. package/dist/control-web/assets/haskell-D8IpX4py.js +1 -0
  226. package/dist/control-web/assets/haxe-OTjmBuCE.js +1 -0
  227. package/dist/control-web/assets/hcl-Dh228itO.js +1 -0
  228. package/dist/control-web/assets/highlighted-body-OFNGDK62-DVCHy9oI.js +1 -0
  229. package/dist/control-web/assets/hjson-CxZEssPk.js +1 -0
  230. package/dist/control-web/assets/hlsl-Cvrh5tZx.js +1 -0
  231. package/dist/control-web/assets/horizon-CE9ld1lL.js +1 -0
  232. package/dist/control-web/assets/horizon-bright-Br1oVSNq.js +1 -0
  233. package/dist/control-web/assets/houston-CsvMBhTu.js +1 -0
  234. package/dist/control-web/assets/html-B2lrdnWr.js +1 -0
  235. package/dist/control-web/assets/html-derivative-CDfZYcul.js +1 -0
  236. package/dist/control-web/assets/http-kmH8AyfE.js +1 -0
  237. package/dist/control-web/assets/hurl-DCZHXKU4.js +1 -0
  238. package/dist/control-web/assets/hxml-B0Qn7Nwc.js +1 -0
  239. package/dist/control-web/assets/hy-CZbG8q4J.js +1 -0
  240. package/dist/control-web/assets/imba-DsUTQ-LC.js +1 -0
  241. package/dist/control-web/assets/index-D7URT6K_.js +140 -0
  242. package/dist/control-web/assets/index-uEpvRMX9.css +1 -0
  243. package/dist/control-web/assets/info-DKCQHKI2-Cp_JrY-b.js +1 -0
  244. package/dist/control-web/assets/infoDiagram-FWYZ7A6U-CAm-h4F_.js +2 -0
  245. package/dist/control-web/assets/ini-B5eOa1yu.js +1 -0
  246. package/dist/control-web/assets/init-C-OQMol4.js +1 -0
  247. package/dist/control-web/assets/ishikawaDiagram-FXEZZL3T-O17pqcWr.js +70 -0
  248. package/dist/control-web/assets/java-DdHNQ9hk.js +1 -0
  249. package/dist/control-web/assets/javascript-obGGvMPs.js +1 -0
  250. package/dist/control-web/assets/jinja-BMiPVedm.js +1 -0
  251. package/dist/control-web/assets/jison-CBjhYtSs.js +1 -0
  252. package/dist/control-web/assets/journeyDiagram-5HDEW3XC-DQ-JuSoR.js +139 -0
  253. package/dist/control-web/assets/json-DAgxKhMr.js +1 -0
  254. package/dist/control-web/assets/json5-BR5RXkoi.js +1 -0
  255. package/dist/control-web/assets/jsonc-CYpm1nAK.js +1 -0
  256. package/dist/control-web/assets/jsonl-CmCQp5Yx.js +1 -0
  257. package/dist/control-web/assets/jsonnet-CJTPZ8u_.js +1 -0
  258. package/dist/control-web/assets/jssm-DXw9l8Rf.js +1 -0
  259. package/dist/control-web/assets/jsx-gTgmArGx.js +1 -0
  260. package/dist/control-web/assets/julia-CjHxn3vf.js +1 -0
  261. package/dist/control-web/assets/just-DMArCiVH.js +1 -0
  262. package/dist/control-web/assets/kanagawa-dragon-CXtmUGW6.js +1 -0
  263. package/dist/control-web/assets/kanagawa-lotus-BN08jTvb.js +1 -0
  264. package/dist/control-web/assets/kanagawa-wave-CTweb8Dz.js +1 -0
  265. package/dist/control-web/assets/kanban-definition-HUTT4EX6-Cgv3kPbm.js +89 -0
  266. package/dist/control-web/assets/katex-CyHG4N6b.js +1 -0
  267. package/dist/control-web/assets/kdl-CsD5j6eV.js +1 -0
  268. package/dist/control-web/assets/kotlin-DhhofPvG.js +1 -0
  269. package/dist/control-web/assets/kusto-BUv0MjJC.js +1 -0
  270. package/dist/control-web/assets/laserwave-C_8bwKvT.js +1 -0
  271. package/dist/control-web/assets/latex-D9bvcAJr.js +1 -0
  272. package/dist/control-web/assets/lean-CewbzKMR.js +1 -0
  273. package/dist/control-web/assets/less-DVTAwKKz.js +1 -0
  274. package/dist/control-web/assets/lib-BZ_F5vVH.js +1 -0
  275. package/dist/control-web/assets/light-plus-DVQuIRkW.js +1 -0
  276. package/dist/control-web/assets/line-DUsXzGJZ.js +1 -0
  277. package/dist/control-web/assets/linear-DmucvK78.js +1 -0
  278. package/dist/control-web/assets/liquid-CCX5qouA.js +1 -0
  279. package/dist/control-web/assets/llvm-Cm23YOpf.js +1 -0
  280. package/dist/control-web/assets/log-BNLmms1o.js +1 -0
  281. package/dist/control-web/assets/logo-Cluzi2Zq.js +1 -0
  282. package/dist/control-web/assets/lua-FONpmTUP.js +1 -0
  283. package/dist/control-web/assets/luau-CNKltnaQ.js +1 -0
  284. package/dist/control-web/assets/make-Dixweg8N.js +1 -0
  285. package/dist/control-web/assets/map-BaFkSB1l.js +1 -0
  286. package/dist/control-web/assets/markdown-BYOwaDjH.js +1 -0
  287. package/dist/control-web/assets/markdown-streamdown-4N4AcNp5.js +433 -0
  288. package/dist/control-web/assets/markdown-streamdown-DEcVZfaU.css +1 -0
  289. package/dist/control-web/assets/marko-oPGh3KfH.js +1 -0
  290. package/dist/control-web/assets/material-theme-Bm3Qr25_.js +1 -0
  291. package/dist/control-web/assets/material-theme-darker-2IIEA8gg.js +1 -0
  292. package/dist/control-web/assets/material-theme-lighter-uhdI0v04.js +1 -0
  293. package/dist/control-web/assets/material-theme-ocean-CHQ94UKr.js +1 -0
  294. package/dist/control-web/assets/material-theme-palenight-B5W6OYN7.js +1 -0
  295. package/dist/control-web/assets/matlab-D7qyCx1q.js +1 -0
  296. package/dist/control-web/assets/mdc-B_uQHOlt.js +1 -0
  297. package/dist/control-web/assets/mdx-DQZ5AkYe.js +1 -0
  298. package/dist/control-web/assets/mermaid-Bk4SNUv9.js +1 -0
  299. package/dist/control-web/assets/mermaid-GHXKKRXX-BElZGKGd.js +1 -0
  300. package/dist/control-web/assets/mermaid-parser.core-VMln12Kd.js +7 -0
  301. package/dist/control-web/assets/min-dark-BSWPekZh.js +1 -0
  302. package/dist/control-web/assets/min-light-DDpmG2fV.js +1 -0
  303. package/dist/control-web/assets/mindmap-definition-LN4V7U3C-Bn0lH-UM.js +96 -0
  304. package/dist/control-web/assets/mipsasm-BMqwQI7S.js +1 -0
  305. package/dist/control-web/assets/mojo-BgCJLMeH.js +1 -0
  306. package/dist/control-web/assets/monokai-CdkpiU2Y.js +1 -0
  307. package/dist/control-web/assets/moonbit-CaWjb8XO.js +1 -0
  308. package/dist/control-web/assets/move-B1IS1UjX.js +1 -0
  309. package/dist/control-web/assets/narrat-_X_XdTYD.js +1 -0
  310. package/dist/control-web/assets/nextflow-Bbiyy34d.js +1 -0
  311. package/dist/control-web/assets/nextflow-groovy-Dc_ddanL.js +1 -0
  312. package/dist/control-web/assets/nginx-BTMw9COX.js +1 -0
  313. package/dist/control-web/assets/night-owl-DhmEMT88.js +1 -0
  314. package/dist/control-web/assets/night-owl-light-eJ-hLW7d.js +1 -0
  315. package/dist/control-web/assets/nim-8PQFL6ZB.js +1 -0
  316. package/dist/control-web/assets/nix-IvuFDN5E.js +1 -0
  317. package/dist/control-web/assets/nord-Cb4Vim4T.js +1 -0
  318. package/dist/control-web/assets/nushell-DcLAeLz5.js +1 -0
  319. package/dist/control-web/assets/objective-c-D1A_Heim.js +1 -0
  320. package/dist/control-web/assets/objective-cpp-BsSzOQcm.js +1 -0
  321. package/dist/control-web/assets/ocaml-O90oeIOV.js +1 -0
  322. package/dist/control-web/assets/odin-B1RWQWA5.js +1 -0
  323. package/dist/control-web/assets/one-dark-pro-CLwyXe_n.js +1 -0
  324. package/dist/control-web/assets/one-light-D7Lr4KcI.js +1 -0
  325. package/dist/control-web/assets/openscad-BUDT5pXO.js +1 -0
  326. package/dist/control-web/assets/ordinal-BDEzSJ7C.js +1 -0
  327. package/dist/control-web/assets/packet-7NZHBO7P-Zw8iJ8lo.js +1 -0
  328. package/dist/control-web/assets/pascal-4ZHwLPI5.js +1 -0
  329. package/dist/control-web/assets/path-fybaL0A-.js +1 -0
  330. package/dist/control-web/assets/pegDiagram-2B236MQR-CtF7vVs_.js +1 -0
  331. package/dist/control-web/assets/perl-Vf0i0hAx.js +1 -0
  332. package/dist/control-web/assets/php-am1OsKhm.js +1 -0
  333. package/dist/control-web/assets/pie-RZYD4A2V-su_3QGU2.js +1 -0
  334. package/dist/control-web/assets/pieDiagram-ENE6RG2P-BkMUBLE1.js +39 -0
  335. package/dist/control-web/assets/pkl-ot-7Btpt.js +1 -0
  336. package/dist/control-web/assets/plastic-DQwYfKfQ.js +1 -0
  337. package/dist/control-web/assets/plsql-DGHpHOYJ.js +1 -0
  338. package/dist/control-web/assets/po-BiJDBrnU.js +1 -0
  339. package/dist/control-web/assets/poimandres-DRFjx7u4.js +1 -0
  340. package/dist/control-web/assets/polar-C7UOKdEL.js +1 -0
  341. package/dist/control-web/assets/postcss-BXeXVLqQ.js +1 -0
  342. package/dist/control-web/assets/powerquery-DNMTfnFr.js +1 -0
  343. package/dist/control-web/assets/powershell-DshXNtvi.js +1 -0
  344. package/dist/control-web/assets/prisma-BsRQq5mF.js +1 -0
  345. package/dist/control-web/assets/prolog-iXnhIJG7.js +1 -0
  346. package/dist/control-web/assets/proto-DB4EqR-F.js +1 -0
  347. package/dist/control-web/assets/pug-DO6yvBr3.js +1 -0
  348. package/dist/control-web/assets/puppet-CDv2pdJW.js +1 -0
  349. package/dist/control-web/assets/purescript-9MfHhQsQ.js +1 -0
  350. package/dist/control-web/assets/python-gzcpVVnB.js +1 -0
  351. package/dist/control-web/assets/qml-_a-QhfPD.js +1 -0
  352. package/dist/control-web/assets/qmldir-DCQb3MpD.js +1 -0
  353. package/dist/control-web/assets/qss-Fe1Jh2GI.js +1 -0
  354. package/dist/control-web/assets/quadrantDiagram-ABIIQ3AL-ba-VaqMe.js +7 -0
  355. package/dist/control-web/assets/r-D6UWEOL2.js +1 -0
  356. package/dist/control-web/assets/racket-DcIDlBhZ.js +1 -0
  357. package/dist/control-web/assets/radar-I7S5WNFK-Dat0rqem.js +1 -0
  358. package/dist/control-web/assets/railroad-3IZDKUUU-Dh2-s8r8.js +1 -0
  359. package/dist/control-web/assets/railroad-abnf-AHOZXSZD-CNUwq0JR.js +1 -0
  360. package/dist/control-web/assets/railroad-ebnf-EBAXGLYW-RHr0duea.js +1 -0
  361. package/dist/control-web/assets/railroad-peg-LSFZ7HO6-CVBWS2eU.js +1 -0
  362. package/dist/control-web/assets/railroadDiagram-RFXS5EU6-BiJX3SY-.js +1 -0
  363. package/dist/control-web/assets/raku-B3gFvitq.js +1 -0
  364. package/dist/control-web/assets/razor-CMVBVp3T.js +1 -0
  365. package/dist/control-web/assets/red-CJ3rzSJv.js +1 -0
  366. package/dist/control-web/assets/reg-CRGYupPL.js +1 -0
  367. package/dist/control-web/assets/regexp-DR20uMnK.js +1 -0
  368. package/dist/control-web/assets/rel-BtDbiS_P.js +1 -0
  369. package/dist/control-web/assets/requirementDiagram-TGXJPOKE-CFfakCzs.js +84 -0
  370. package/dist/control-web/assets/riscv-Ckw8ddFX.js +1 -0
  371. package/dist/control-web/assets/rolldown-runtime-hePW80VL.js +1 -0
  372. package/dist/control-web/assets/ron-VUp2lXgN.js +1 -0
  373. package/dist/control-web/assets/rose-pine-BthvhNj6.js +1 -0
  374. package/dist/control-web/assets/rose-pine-dawn-Dg85fqjY.js +1 -0
  375. package/dist/control-web/assets/rose-pine-moon-hon4tzzS.js +1 -0
  376. package/dist/control-web/assets/rosmsg-CAekHB0j.js +1 -0
  377. package/dist/control-web/assets/rough.esm-Dy-Kn_BL.js +1 -0
  378. package/dist/control-web/assets/rst-CgIrbW_q.js +1 -0
  379. package/dist/control-web/assets/ruby-Dp6Zud9H.js +1 -0
  380. package/dist/control-web/assets/rust-Cfkwpbl8.js +1 -0
  381. package/dist/control-web/assets/sankeyDiagram-HTMAVEWB-jgDi0God.js +40 -0
  382. package/dist/control-web/assets/sas-B6p8-ynO.js +1 -0
  383. package/dist/control-web/assets/sass-DXrisJhu.js +1 -0
  384. package/dist/control-web/assets/scala-DKOlJaKm.js +1 -0
  385. package/dist/control-web/assets/scheme-DQCgrYNe.js +1 -0
  386. package/dist/control-web/assets/scss-DcoSS-ti.js +1 -0
  387. package/dist/control-web/assets/sdbl-bTVj8UrX.js +1 -0
  388. package/dist/control-web/assets/sequenceDiagram-DBY2YBRQ-DBfyyb0N.js +162 -0
  389. package/dist/control-web/assets/shaderlab-TOUzSsQk.js +1 -0
  390. package/dist/control-web/assets/shellscript-Da78Ox-3.js +1 -0
  391. package/dist/control-web/assets/shellsession-CVsQGYfZ.js +1 -0
  392. package/dist/control-web/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  393. package/dist/control-web/assets/slack-dark-DnToyrRv.js +1 -0
  394. package/dist/control-web/assets/slack-ochin-B2OO5cIa.js +1 -0
  395. package/dist/control-web/assets/smalltalk-B16xEiuN.js +1 -0
  396. package/dist/control-web/assets/snazzy-light-4G7pJPwS.js +1 -0
  397. package/dist/control-web/assets/solarized-dark-DV17i1UV.js +1 -0
  398. package/dist/control-web/assets/solarized-light-DSh2HLQt.js +1 -0
  399. package/dist/control-web/assets/solidity-CKzVLygQ.js +1 -0
  400. package/dist/control-web/assets/soy-B5n_eHSp.js +1 -0
  401. package/dist/control-web/assets/sparql-D_iOobhT.js +1 -0
  402. package/dist/control-web/assets/splunk-BC2Px7Mm.js +1 -0
  403. package/dist/control-web/assets/sql-ClgswhA6.js +1 -0
  404. package/dist/control-web/assets/src-B6xuSHsQ.js +1 -0
  405. package/dist/control-web/assets/ssh-config-BgfXC-Er.js +1 -0
  406. package/dist/control-web/assets/stata-RoaAgbqU.js +1 -0
  407. package/dist/control-web/assets/stateDiagram-2N3HPSRC-Dwb_ncVi.js +1 -0
  408. package/dist/control-web/assets/stateDiagram-v2-6OUMAXLB-DI0opaA1.js +1 -0
  409. package/dist/control-web/assets/stylus-B6D30XZt.js +1 -0
  410. package/dist/control-web/assets/surrealql-DIn4NJsS.js +1 -0
  411. package/dist/control-web/assets/svelte-CIt8Fl9I.js +1 -0
  412. package/dist/control-web/assets/swift-DonLKvLd.js +1 -0
  413. package/dist/control-web/assets/swimlanes-5IMT3BWC-DW0LuiIV.js +2 -0
  414. package/dist/control-web/assets/swimlanesDiagram-G3AALYLV-DDTVjcOR.js +8 -0
  415. package/dist/control-web/assets/synthwave-84-nFMaYfgc.js +1 -0
  416. package/dist/control-web/assets/system-verilog-DJ5XKQeo.js +1 -0
  417. package/dist/control-web/assets/systemd-BxMlprV5.js +1 -0
  418. package/dist/control-web/assets/talonscript-CohzipZa.js +1 -0
  419. package/dist/control-web/assets/tasl-DMoTqEGO.js +1 -0
  420. package/dist/control-web/assets/tcl-CZd0xW_V.js +1 -0
  421. package/dist/control-web/assets/templ-BREsJpNc.js +1 -0
  422. package/dist/control-web/assets/terraform-DswuEJGm.js +1 -0
  423. package/dist/control-web/assets/tex-0w6-Dtgt.js +1 -0
  424. package/dist/control-web/assets/timeline-definition-FHXFAJF6-DeX4B_B8.js +120 -0
  425. package/dist/control-web/assets/tokyo-night-oM2G3aXe.js +1 -0
  426. package/dist/control-web/assets/toml-CcmNWLt0.js +1 -0
  427. package/dist/control-web/assets/treeView-QDETBFTQ-D1UXtICj.js +1 -0
  428. package/dist/control-web/assets/treemap-6X3UGDF4-CrppzjZH.js +1 -0
  429. package/dist/control-web/assets/ts-tags-q3pptdMi.js +1 -0
  430. package/dist/control-web/assets/tsv-sltzmVWM.js +1 -0
  431. package/dist/control-web/assets/tsx-CUOciP0b.js +1 -0
  432. package/dist/control-web/assets/turtle-ByJddavk.js +1 -0
  433. package/dist/control-web/assets/twig-LIeLXgf5.js +1 -0
  434. package/dist/control-web/assets/typescript-BydbNFcO.js +1 -0
  435. package/dist/control-web/assets/typespec-B88KGewJ.js +1 -0
  436. package/dist/control-web/assets/typst-DI99ib-x.js +1 -0
  437. package/dist/control-web/assets/v-DETTlOr0.js +1 -0
  438. package/dist/control-web/assets/vala-zf12oZj6.js +1 -0
  439. package/dist/control-web/assets/vb-Djn5o6TS.js +1 -0
  440. package/dist/control-web/assets/vennDiagram-L72KCM5P-BYpf-7VR.js +34 -0
  441. package/dist/control-web/assets/verilog-CiiDBU1e.js +1 -0
  442. package/dist/control-web/assets/vesper-D5bVUKB1.js +1 -0
  443. package/dist/control-web/assets/vhdl-BroJfC0k.js +1 -0
  444. package/dist/control-web/assets/viml-DvXPmvsu.js +1 -0
  445. package/dist/control-web/assets/vitesse-black-fwtXNY1n.js +1 -0
  446. package/dist/control-web/assets/vitesse-dark-BZCL-v6S.js +1 -0
  447. package/dist/control-web/assets/vitesse-light-VbXTXTou.js +1 -0
  448. package/dist/control-web/assets/vue-DVSfBueU.js +1 -0
  449. package/dist/control-web/assets/vue-html-DkKkQnZL.js +1 -0
  450. package/dist/control-web/assets/vue-vine-pWqEcBkW.js +1 -0
  451. package/dist/control-web/assets/vyper-CgoNMtux.js +1 -0
  452. package/dist/control-web/assets/wardley-OPB4EBWU-B9rA0UsV.js +1 -0
  453. package/dist/control-web/assets/wardleyDiagram-EHGQE667-BdvAUa5F.js +78 -0
  454. package/dist/control-web/assets/wasm-BnjxR4X6.js +1 -0
  455. package/dist/control-web/assets/wasm-ByWQv1Qj.js +1 -0
  456. package/dist/control-web/assets/wenyan-C8pVoKbM.js +1 -0
  457. package/dist/control-web/assets/wgsl-BsKzXJz4.js +1 -0
  458. package/dist/control-web/assets/wikitext-ClFFjSW2.js +1 -0
  459. package/dist/control-web/assets/wit-DdvCle-K.js +1 -0
  460. package/dist/control-web/assets/wolfram-DLL8P-h_.js +1 -0
  461. package/dist/control-web/assets/xml-BlnrEAEy.js +1 -0
  462. package/dist/control-web/assets/xsl-BOPS8gLt.js +1 -0
  463. package/dist/control-web/assets/xychartDiagram-FW5EYKEG-BaEV3pGm.js +7 -0
  464. package/dist/control-web/assets/yaml-Du_6cdrH.js +1 -0
  465. package/dist/control-web/assets/zenscript-BnlCZFoB.js +1 -0
  466. package/dist/control-web/assets/zig-CMLA9XwU.js +1 -0
  467. package/dist/control-web/index.html +3 -2
  468. package/dist/control-web-dist.d.ts +1 -1
  469. package/dist/control-web-dist.js +4 -2
  470. package/dist/desktop-browser-host.d.ts +3 -1
  471. package/dist/desktop-browser-host.js +39 -4
  472. package/dist/direct-runtime-server.js +187 -153
  473. package/dist/machine-session-service.d.ts +105 -15
  474. package/dist/machine-session-service.js +781 -87
  475. package/dist/remote-runtime-dispatcher.d.ts +2 -2
  476. package/dist/remote-runtime-dispatcher.js +42 -2
  477. package/dist/remote-runtime-session-projection.d.ts +1 -0
  478. package/dist/remote-runtime-session-projection.js +12 -0
  479. package/dist/server.d.ts +64 -11
  480. package/dist/server.js +422 -55
  481. package/dist/session-browser-service.d.ts +24 -4
  482. package/dist/session-browser-service.js +127 -1
  483. package/dist/session-pending-inputs.d.ts +42 -0
  484. package/dist/session-pending-inputs.js +87 -0
  485. package/dist/session-portal.d.ts +54 -0
  486. package/dist/session-portal.js +997 -0
  487. package/dist/session-runtime-index.d.ts +3 -6
  488. package/dist/session-runtime-index.js +96 -38
  489. package/dist/session-terminal-host.d.ts +22 -2
  490. package/dist/session-terminal-host.js +66 -83
  491. package/dist/terminal-ws.d.ts +4 -1
  492. package/dist/terminal-ws.js +93 -27
  493. package/package.json +7 -7
  494. package/dist/control-web/assets/highlighted-body-OFNGDK62-DWWsUtHF.js +0 -1
  495. package/dist/control-web/assets/index-BnX7NWJX.js +0 -689
  496. package/dist/control-web/assets/index-CUoWRX2i.css +0 -32
  497. package/dist/control-web/assets/mermaid-GHXKKRXX-C1fxAgiw.js +0 -131
@@ -7,6 +7,7 @@
7
7
  * owns that state and exposes its own management application.
8
8
  */
9
9
  import { timingSafeEqual } from "node:crypto";
10
+ import { Readable } from "node:stream";
10
11
  import Router from "@koa/router";
11
12
  import { skillInstallRecipeSchema, } from "@rynx-ai/core";
12
13
  import { DAEMON_BROWSER_ARTIFACT_CLEAN_PATH, DAEMON_BROWSER_ARTIFACT_INSTALL_PATH, DAEMON_BROWSER_ARTIFACT_UPDATE_PATH, DAEMON_BROWSER_ARTIFACT_VERSION_PATH, DAEMON_CHROME_INSPECTION_PATH, DAEMON_CLEANUP_SESSIONS_PATH, DAEMON_MAINTENANCE_LEASE_HEADER, DAEMON_MAINTENANCE_LEASE_RELEASE_PATH, DAEMON_SHUTDOWN_IF_IDLE_PATH, parseDaemonBrowserArtifactInstallInput, parseDaemonBrowserArtifactUpdateInput, parseDaemonChromeInspectionConfigureInput, parseDaemonCleanupSessionsInput, } from "@rynx-ai/protocol/control";
@@ -19,6 +20,7 @@ import { parseRuntimeBrowserStateGetParams } from "@rynx-ai/protocol/runtime-bro
19
20
  import { encodeDaemonStatus } from "./remote-runtime.js";
20
21
  import { SessionRuntimeIndex } from "./session-runtime-index.js";
21
22
  import { authorizeRuntimeWebRequest, RUNTIME_WEB_CAPABILITY, RUNTIME_WEB_CAPABILITY_HEADER, } from "./runtime-web-auth.js";
23
+ import { MachineSessionServiceFailure, } from "./machine-session-service.js";
22
24
  const PLUGIN_CLI_BODY_MAX_BYTES = 512 * 1024;
23
25
  const PLUGIN_CLI_STDIN_MAX_BYTES = 256 * 1024;
24
26
  const PLUGIN_CLI_ARG_MAX_BYTES = 4 * 1024;
@@ -54,6 +56,8 @@ const RUNTIME_TARGET_SELECTOR_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._~-]{0,255}$/;
54
56
  const SESSION_INTERACTION_RESOLUTION_MAX_BYTES = 128 * 1024;
55
57
  const RUNTIME_BROWSER_RPC_METHODS = new Set([
56
58
  "browser.state.get",
59
+ "browser.request-headers.get",
60
+ "browser.request-headers.set",
57
61
  "browser.open",
58
62
  "browser.close",
59
63
  "browser.page.create",
@@ -630,6 +634,7 @@ export function createControlRouter(opts) {
630
634
  let afterId;
631
635
  let bytes = 0;
632
636
  let runtime;
637
+ let pendingInputs = [];
633
638
  try {
634
639
  for (let pageIndex = 0; pageIndex < REMOTE_RUNTIME_SESSION_BFF_MAX_PAGES; pageIndex += 1) {
635
640
  const page = await lease.call("session.snapshot.get", {
@@ -641,6 +646,7 @@ export function createControlRouter(opts) {
641
646
  throw runtimeProtocolError("Runtime Session snapshot identity changed");
642
647
  }
643
648
  runtime = page.runtime;
649
+ pendingInputs = page.pendingInputs ?? [];
644
650
  for (const item of page.items) {
645
651
  if (ids.has(item.id)) {
646
652
  throw runtimeProtocolError("Runtime Session snapshot repeated an item");
@@ -660,6 +666,7 @@ export function createControlRouter(opts) {
660
666
  ctx.body = {
661
667
  sessionId,
662
668
  items,
669
+ pendingInputs,
663
670
  runtime: materializeRemoteRuntimeSessionRuntimeSnapshot(runtime, items),
664
671
  };
665
672
  return;
@@ -724,6 +731,30 @@ export function createControlRouter(opts) {
724
731
  if (outcome.ok)
725
732
  ctx.body = outcome.result;
726
733
  };
734
+ const runtimeSessionExecutionSettings = async (ctx) => {
735
+ const outcome = await runtimeCall(ctx, "session.execution.get", {
736
+ sessionId: ctx.params.id,
737
+ });
738
+ if (outcome.ok)
739
+ ctx.body = outcome.result;
740
+ };
741
+ const runtimeSessionExecutionSettingsUpdate = async (ctx) => {
742
+ const body = await readRuntimeBody(ctx);
743
+ if (!body)
744
+ return;
745
+ if (!acceptRuntimeBodyKeys(ctx, body, ["model", "reasoningEffort", "collaborationMode"]))
746
+ return;
747
+ const outcome = await runtimeCall(ctx, "session.execution.update", {
748
+ sessionId: ctx.params.id,
749
+ model: body.model,
750
+ reasoningEffort: body.reasoningEffort,
751
+ ...(body.collaborationMode === undefined
752
+ ? {}
753
+ : { collaborationMode: body.collaborationMode }),
754
+ });
755
+ if (outcome.ok)
756
+ ctx.body = outcome.result;
757
+ };
727
758
  const runtimeSessionCreate = async (ctx) => {
728
759
  const body = await readRuntimeBody(ctx);
729
760
  if (!body)
@@ -834,7 +865,13 @@ export function createControlRouter(opts) {
834
865
  };
835
866
  const runtimeSessionResourceUpload = async (ctx) => {
836
867
  const uploadStarted = performance.now();
837
- const mediaType = ctx.get("content-type").split(";", 1)[0]?.trim();
868
+ const mediaType = ctx.get("content-type").split(";", 1)[0]?.trim().toLowerCase();
869
+ const requestedType = ctx.get("x-rynx-resource-type").trim();
870
+ const resourceType = requestedType === "input_image" || requestedType === "input_file"
871
+ ? requestedType
872
+ : SESSION_IMAGE_MEDIA_TYPES.includes(mediaType)
873
+ ? "input_image"
874
+ : "input_file";
838
875
  const clientUploadId = ctx.get("x-rynx-upload-id").trim();
839
876
  const encodedFilename = ctx.get("x-rynx-filename").trim();
840
877
  let filename = "";
@@ -847,7 +884,9 @@ export function createControlRouter(opts) {
847
884
  return;
848
885
  }
849
886
  if (!mediaType ||
850
- !SESSION_IMAGE_MEDIA_TYPES.includes(mediaType) ||
887
+ !isMediaType(mediaType) ||
888
+ (resourceType === "input_image" &&
889
+ !SESSION_IMAGE_MEDIA_TYPES.includes(mediaType)) ||
851
890
  !clientUploadId ||
852
891
  !filename ||
853
892
  filename.length > SESSION_RESOURCE_MAX_FILENAME_CHARS) {
@@ -855,23 +894,21 @@ export function createControlRouter(opts) {
855
894
  ctx.body = { error: "invalid_resource_upload" };
856
895
  return;
857
896
  }
858
- let bytes;
859
- const bodyReadStarted = performance.now();
860
- try {
861
- bytes = await readBoundedBinary(ctx, SESSION_RESOURCE_MAX_IMAGE_BYTES);
862
- }
863
- catch (error) {
864
- ctx.status = error instanceof RequestBodyTooLargeError ? 413 : 400;
865
- ctx.body = {
866
- error: error instanceof RequestBodyTooLargeError
867
- ? "request_too_large"
868
- : "invalid_resource_upload",
869
- };
897
+ const contentLengthHeader = ctx.get("content-length").trim();
898
+ if (!contentLengthHeader) {
899
+ ctx.status = 411;
900
+ ctx.body = { error: "content_length_required" };
870
901
  return;
871
902
  }
872
- if (bytes.byteLength === 0) {
903
+ const byteLength = Number(contentLengthHeader);
904
+ if (!Number.isSafeInteger(byteLength) || byteLength <= 0) {
873
905
  ctx.status = 400;
874
- ctx.body = { error: "empty_resource" };
906
+ ctx.body = { error: "invalid_content_length" };
907
+ return;
908
+ }
909
+ if (resourceType === "input_image" && byteLength > SESSION_RESOURCE_MAX_IMAGE_BYTES) {
910
+ ctx.status = 413;
911
+ ctx.body = { error: "request_too_large" };
875
912
  return;
876
913
  }
877
914
  const sessionId = ctx.params.id;
@@ -879,9 +916,7 @@ export function createControlRouter(opts) {
879
916
  const lease = local ? undefined : await acquireRuntimeLease(ctx);
880
917
  if (!local && !lease)
881
918
  return;
882
- const timings = new Map([
883
- ["body", performance.now() - bodyReadStarted],
884
- ]);
919
+ const timings = new Map();
885
920
  const timed = async (name, operation) => {
886
921
  const started = performance.now();
887
922
  try {
@@ -898,16 +933,18 @@ export function createControlRouter(opts) {
898
933
  ? local.beginResourceUpload({
899
934
  sessionId,
900
935
  clientUploadId,
936
+ type: resourceType,
901
937
  filename,
902
938
  mediaType,
903
- byteLength: bytes.byteLength,
939
+ byteLength,
904
940
  })
905
941
  : lease.call("session.resource.upload.begin", {
906
942
  sessionId,
907
943
  clientUploadId,
944
+ type: resourceType,
908
945
  filename,
909
946
  mediaType,
910
- byteLength: bytes.byteLength,
947
+ byteLength,
911
948
  }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS }));
912
949
  const writeChunk = (uploadId, offset, data) => timed("chunks", () => local
913
950
  ? local.writeResourceUploadChunk({ sessionId, uploadId, offset, data })
@@ -915,44 +952,72 @@ export function createControlRouter(opts) {
915
952
  const commit = (uploadId) => timed("commit", () => local
916
953
  ? local.commitResourceUpload({ sessionId, uploadId })
917
954
  : lease.call("session.resource.upload.commit", { sessionId, uploadId }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS }));
955
+ const discardPartial = (resourceId) => timed("restart", () => local
956
+ ? local.deleteResource({ sessionId, resourceId })
957
+ : lease.call("session.resource.delete", { sessionId, resourceId }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS }));
958
+ let requestResourceId;
959
+ let resourceCommitted = false;
918
960
  try {
919
961
  const resourcePolicy = await policy();
920
962
  if (!resourcePolicy.enabled ||
921
- !resourcePolicy.mediaTypes.includes(mediaType) ||
922
- bytes.byteLength > resourcePolicy.maxImageBytes) {
963
+ (resourceType === "input_image" &&
964
+ (!resourcePolicy.mediaTypes.includes(mediaType) ||
965
+ byteLength > resourcePolicy.maxImageBytes))) {
923
966
  ctx.status = 413;
924
967
  ctx.body = { error: "resource_policy_rejected" };
925
968
  return;
926
969
  }
927
- const begun = await begin();
970
+ let begun = await begin();
928
971
  if (begun.complete && begun.resource) {
972
+ ctx.req.resume();
929
973
  ctx.set("Cache-Control", "no-store");
930
974
  ctx.body = { resource: begun.resource };
931
975
  return;
932
976
  }
933
- if (begun.offset < 0 || begun.offset > bytes.byteLength) {
977
+ if (begun.offset < 0 || begun.offset > byteLength) {
934
978
  throw runtimeProtocolError("Runtime Session resource upload offset is invalid");
935
979
  }
936
- let offset = begun.offset;
937
- while (offset < bytes.byteLength) {
938
- const chunk = bytes.subarray(offset, Math.min(offset + SESSION_RESOURCE_TRANSFER_CHUNK_BYTES, bytes.byteLength));
939
- const written = await writeChunk(begun.uploadId, offset, chunk.toString("base64"));
940
- if (written.offset <= offset || written.offset > bytes.byteLength) {
941
- throw runtimeProtocolError("Runtime Session resource upload did not advance");
980
+ // Browser retries send the complete File body again. A target-side
981
+ // partial cannot be blindly combined with the new body's suffix: the
982
+ // caller may have reused an upload id for changed bytes. Restart the
983
+ // incomplete upload so committed content always matches this request.
984
+ if (begun.offset > 0) {
985
+ const discarded = await discardPartial(begun.resourceId);
986
+ if (!discarded.deleted) {
987
+ throw runtimeProtocolError("Runtime Session partial upload could not be restarted");
988
+ }
989
+ begun = await begin();
990
+ if (begun.complete || begun.offset !== 0) {
991
+ throw runtimeProtocolError("Runtime Session resource upload did not restart");
942
992
  }
943
- offset = written.offset;
944
993
  }
994
+ requestResourceId = begun.resourceId;
995
+ const bodyStarted = performance.now();
996
+ await forwardResourceUploadBody(ctx, begun.uploadId, begun.offset, byteLength, writeChunk);
997
+ timings.set("body", performance.now() - bodyStarted);
945
998
  const committed = await commit(begun.uploadId);
946
999
  if (committed.resource.resourceId !== begun.resourceId ||
1000
+ committed.resource.type !== resourceType ||
947
1001
  committed.resource.mediaType !== mediaType ||
948
- committed.resource.byteLength !== bytes.byteLength) {
1002
+ committed.resource.byteLength !== byteLength) {
949
1003
  throw runtimeProtocolError("Runtime Session resource upload identity changed");
950
1004
  }
1005
+ resourceCommitted = true;
951
1006
  ctx.status = 201;
952
1007
  ctx.set("Cache-Control", "no-store");
953
1008
  ctx.body = committed;
954
1009
  }
955
1010
  catch (error) {
1011
+ if (requestResourceId && !resourceCommitted) {
1012
+ try {
1013
+ await discardPartial(requestResourceId);
1014
+ }
1015
+ catch {
1016
+ // The original error remains authoritative. Targets also reap stale
1017
+ // uploads, so a disconnected target cannot make cleanup block the
1018
+ // browser response indefinitely.
1019
+ }
1020
+ }
956
1021
  runtimeTargetHostError(ctx, error);
957
1022
  }
958
1023
  finally {
@@ -968,7 +1033,7 @@ export function createControlRouter(opts) {
968
1033
  event: "session.resource.upload.slow",
969
1034
  selector: ctx.params.selector,
970
1035
  sessionId,
971
- byteLength: bytes.byteLength,
1036
+ byteLength,
972
1037
  status: ctx.status,
973
1038
  timings: Object.fromEntries([...timings.entries()].map(([name, duration]) => [
974
1039
  name,
@@ -1012,16 +1077,32 @@ export function createControlRouter(opts) {
1012
1077
  const sessionId = ctx.params.id;
1013
1078
  const resourceId = ctx.params.resourceId;
1014
1079
  const local = ctx.params.selector === "local" ? localSessionResources : undefined;
1015
- const lease = local ? undefined : await acquireRuntimeLease(ctx);
1016
- if (!local && !lease)
1080
+ const invocation = downloadInvocationAbortScope(ctx, shutdownSignal);
1081
+ const lease = local ? undefined : await acquireRuntimeLease(ctx, invocation.signal);
1082
+ if (!local && !lease) {
1083
+ invocation.dispose();
1017
1084
  return;
1085
+ }
1086
+ let streamOwnsLease = false;
1087
+ let cleanedUp = false;
1088
+ const cleanup = () => {
1089
+ if (cleanedUp)
1090
+ return;
1091
+ cleanedUp = true;
1092
+ lease?.release();
1093
+ invocation.dispose();
1094
+ };
1018
1095
  try {
1019
1096
  const { resource } = local
1020
1097
  ? await local.getResource({ sessionId, resourceId })
1021
- : await lease.call("session.resource.get", { sessionId, resourceId }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS });
1098
+ : await lease.call("session.resource.get", { sessionId, resourceId }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS, signal: invocation.signal });
1022
1099
  if (resource.resourceId !== resourceId) {
1023
1100
  throw runtimeProtocolError("Runtime Session resource identity changed");
1024
1101
  }
1102
+ const byteLength = resource.byteLength;
1103
+ if (!Number.isSafeInteger(byteLength) || !byteLength || byteLength < 1) {
1104
+ throw runtimeProtocolError("Runtime Session resource length is invalid");
1105
+ }
1025
1106
  const etag = `"sha256-${resource.sha256}"`;
1026
1107
  ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
1027
1108
  ctx.set("ETag", etag);
@@ -1029,48 +1110,68 @@ export function createControlRouter(opts) {
1029
1110
  ctx.status = 304;
1030
1111
  return;
1031
1112
  }
1032
- const chunks = [];
1033
- let offset = 0;
1034
- while (offset < (resource.byteLength ?? 0)) {
1035
- const result = local
1036
- ? await local.readResource({
1037
- sessionId,
1038
- resourceId,
1039
- offset,
1040
- length: SESSION_RESOURCE_TRANSFER_CHUNK_BYTES,
1041
- })
1042
- : await lease.call("session.resource.read", {
1043
- sessionId,
1044
- resourceId,
1045
- offset,
1046
- length: SESSION_RESOURCE_TRANSFER_CHUNK_BYTES,
1047
- }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS });
1048
- const chunk = Buffer.from(result.data, "base64");
1049
- if (result.offset !== offset + chunk.byteLength || (!result.eof && chunk.byteLength === 0)) {
1050
- throw runtimeProtocolError("Runtime Session resource read did not advance");
1051
- }
1052
- chunks.push(chunk);
1053
- offset = result.offset;
1054
- if (result.eof)
1055
- break;
1056
- }
1057
- const body = Buffer.concat(chunks);
1058
- if (body.byteLength !== resource.byteLength) {
1059
- throw runtimeProtocolError("Runtime Session resource length changed");
1113
+ const requestedRange = ctx.get("range");
1114
+ const ifRange = ctx.get("if-range");
1115
+ const range = ifRange && ifRange !== etag
1116
+ ? undefined
1117
+ : parseSingleByteRange(requestedRange, byteLength);
1118
+ if (range === "unsatisfiable") {
1119
+ ctx.status = 416;
1120
+ ctx.set("Content-Range", `bytes */${byteLength}`);
1121
+ return;
1060
1122
  }
1123
+ const start = range?.start ?? 0;
1124
+ const end = range?.end ?? byteLength - 1;
1125
+ const responseLength = end - start + 1;
1061
1126
  ctx.set("Content-Security-Policy", "default-src 'none'; sandbox");
1062
1127
  ctx.set("Cross-Origin-Resource-Policy", "same-origin");
1063
1128
  ctx.set("X-Content-Type-Options", "nosniff");
1064
- ctx.set("Content-Disposition", "inline");
1129
+ ctx.set("Accept-Ranges", "bytes");
1130
+ ctx.set("Content-Disposition", contentDisposition(resource.filename));
1131
+ if (range) {
1132
+ ctx.status = 206;
1133
+ ctx.set("Content-Range", `bytes ${start}-${end}/${byteLength}`);
1134
+ }
1065
1135
  ctx.type = resource.mediaType;
1066
- ctx.length = body.byteLength;
1136
+ ctx.length = responseLength;
1137
+ if (ctx.method === "HEAD") {
1138
+ ctx.status = range ? 206 : 200;
1139
+ return;
1140
+ }
1141
+ streamOwnsLease = true;
1142
+ const body = Readable.from((async function* () {
1143
+ let offset = start;
1144
+ try {
1145
+ while (offset <= end) {
1146
+ const length = Math.min(SESSION_RESOURCE_TRANSFER_CHUNK_BYTES, end - offset + 1);
1147
+ const result = local
1148
+ ? await local.readResource({ sessionId, resourceId, offset, length })
1149
+ : await lease.call("session.resource.read", { sessionId, resourceId, offset, length }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS, signal: invocation.signal });
1150
+ const chunk = Buffer.from(result.data, "base64");
1151
+ if (result.offset !== offset + chunk.byteLength || chunk.byteLength === 0) {
1152
+ throw runtimeProtocolError("Runtime Session resource read did not advance");
1153
+ }
1154
+ offset = result.offset;
1155
+ yield chunk;
1156
+ }
1157
+ if (offset !== end + 1) {
1158
+ throw runtimeProtocolError("Runtime Session resource length changed");
1159
+ }
1160
+ }
1161
+ finally {
1162
+ cleanup();
1163
+ }
1164
+ })());
1165
+ body.once("close", cleanup);
1067
1166
  ctx.body = body;
1068
1167
  }
1069
1168
  catch (error) {
1070
1169
  runtimeTargetHostError(ctx, error);
1071
1170
  }
1072
1171
  finally {
1073
- lease?.release();
1172
+ if (!streamOwnsLease) {
1173
+ cleanup();
1174
+ }
1074
1175
  }
1075
1176
  };
1076
1177
  const runtimeSessionResourceDelete = async (ctx) => {
@@ -1094,6 +1195,243 @@ export function createControlRouter(opts) {
1094
1195
  if (outcome.ok)
1095
1196
  ctx.body = outcome.result;
1096
1197
  };
1198
+ const runtimeSessionItemFileContent = async (ctx) => {
1199
+ const sessionId = ctx.params.id;
1200
+ const itemId = ctx.params.itemId;
1201
+ const partIndex = Number(ctx.params.partIndex);
1202
+ if (!Number.isSafeInteger(partIndex) || partIndex < 0 || partIndex > 1_024) {
1203
+ ctx.status = 400;
1204
+ ctx.body = { error: "invalid_part_index" };
1205
+ return;
1206
+ }
1207
+ const local = ctx.params.selector === "local" ? localMachineSessions : undefined;
1208
+ const invocation = downloadInvocationAbortScope(ctx, shutdownSignal);
1209
+ const lease = local ? undefined : await acquireRuntimeLease(ctx, invocation.signal);
1210
+ if (!local && !lease) {
1211
+ invocation.dispose();
1212
+ return;
1213
+ }
1214
+ let streamOwnsLease = false;
1215
+ let cleanedUp = false;
1216
+ const cleanup = () => {
1217
+ if (cleanedUp)
1218
+ return;
1219
+ cleanedUp = true;
1220
+ lease?.release();
1221
+ invocation.dispose();
1222
+ };
1223
+ try {
1224
+ const { file } = local
1225
+ ? await local.getFile({ sessionId, itemId, partIndex })
1226
+ : await lease.call("session.file.get", { sessionId, itemId, partIndex }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS, signal: invocation.signal });
1227
+ if (file.itemId !== itemId || file.partIndex !== partIndex) {
1228
+ throw runtimeProtocolError("Runtime Session file identity changed");
1229
+ }
1230
+ const etag = `"file-${file.version}"`;
1231
+ ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
1232
+ ctx.set("ETag", etag);
1233
+ if (ctx.get("if-none-match").split(",").map((value) => value.trim()).includes(etag)) {
1234
+ ctx.status = 304;
1235
+ return;
1236
+ }
1237
+ const requestedRange = ctx.get("range");
1238
+ const ifRange = ctx.get("if-range");
1239
+ const range = ifRange && ifRange !== etag
1240
+ ? undefined
1241
+ : parseSingleByteRange(requestedRange, file.byteLength);
1242
+ if (range === "unsatisfiable") {
1243
+ ctx.status = 416;
1244
+ ctx.set("Content-Range", `bytes */${file.byteLength}`);
1245
+ return;
1246
+ }
1247
+ const start = range?.start ?? 0;
1248
+ const end = range?.end ?? file.byteLength - 1;
1249
+ ctx.set("Content-Security-Policy", "default-src 'none'; sandbox");
1250
+ ctx.set("Cross-Origin-Resource-Policy", "same-origin");
1251
+ ctx.set("X-Content-Type-Options", "nosniff");
1252
+ ctx.set("Accept-Ranges", "bytes");
1253
+ ctx.set("Content-Disposition", contentDisposition(file.filename));
1254
+ if (range) {
1255
+ ctx.status = 206;
1256
+ ctx.set("Content-Range", `bytes ${start}-${end}/${file.byteLength}`);
1257
+ }
1258
+ ctx.type = file.mediaType;
1259
+ ctx.length = end - start + 1;
1260
+ if (ctx.method === "HEAD") {
1261
+ ctx.status = range ? 206 : 200;
1262
+ return;
1263
+ }
1264
+ streamOwnsLease = true;
1265
+ const body = Readable.from((async function* () {
1266
+ let offset = start;
1267
+ try {
1268
+ while (offset <= end) {
1269
+ const length = Math.min(SESSION_RESOURCE_TRANSFER_CHUNK_BYTES, end - offset + 1);
1270
+ const result = local
1271
+ ? await local.readFile({
1272
+ sessionId,
1273
+ itemId,
1274
+ partIndex,
1275
+ version: file.version,
1276
+ offset,
1277
+ length,
1278
+ })
1279
+ : await lease.call("session.file.read", {
1280
+ sessionId,
1281
+ itemId,
1282
+ partIndex,
1283
+ version: file.version,
1284
+ offset,
1285
+ length,
1286
+ }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS, signal: invocation.signal });
1287
+ const chunk = Buffer.from(result.data, "base64");
1288
+ if (result.offset !== offset + chunk.byteLength || chunk.byteLength === 0) {
1289
+ throw runtimeProtocolError("Runtime Session file read did not advance");
1290
+ }
1291
+ offset = result.offset;
1292
+ yield chunk;
1293
+ }
1294
+ }
1295
+ finally {
1296
+ cleanup();
1297
+ }
1298
+ })());
1299
+ body.once("close", cleanup);
1300
+ ctx.body = body;
1301
+ }
1302
+ catch (error) {
1303
+ runtimeTargetHostError(ctx, error);
1304
+ }
1305
+ finally {
1306
+ if (!streamOwnsLease) {
1307
+ cleanup();
1308
+ }
1309
+ }
1310
+ };
1311
+ const runtimeSessionWorkspaceFileContent = async (ctx) => {
1312
+ const sessionId = ctx.params.id;
1313
+ const path = ctx.query.path;
1314
+ if (typeof path !== "string" ||
1315
+ path.length === 0 ||
1316
+ path.length > 4_096 ||
1317
+ path.includes("\0")) {
1318
+ ctx.status = 400;
1319
+ ctx.body = { error: "invalid_workspace_file_path" };
1320
+ return;
1321
+ }
1322
+ const local = ctx.params.selector === "local" ? localMachineSessions : undefined;
1323
+ const invocation = downloadInvocationAbortScope(ctx, shutdownSignal);
1324
+ const lease = local ? undefined : await acquireRuntimeLease(ctx, invocation.signal);
1325
+ if (!local && !lease) {
1326
+ invocation.dispose();
1327
+ return;
1328
+ }
1329
+ let streamOwnsLease = false;
1330
+ let cleanedUp = false;
1331
+ const cleanup = () => {
1332
+ if (cleanedUp)
1333
+ return;
1334
+ cleanedUp = true;
1335
+ lease?.release();
1336
+ invocation.dispose();
1337
+ };
1338
+ try {
1339
+ const { file } = local
1340
+ ? await local.getWorkspaceFile({ sessionId, path })
1341
+ : await lease.call("session.workspace.file.get", { sessionId, path }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS, signal: invocation.signal });
1342
+ if (file.path !== path) {
1343
+ throw runtimeProtocolError("Runtime Session workspace file identity changed");
1344
+ }
1345
+ const etag = `"workspace-file-${file.version}"`;
1346
+ ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
1347
+ ctx.set("ETag", etag);
1348
+ if (ctx.get("if-none-match").split(",").map((value) => value.trim()).includes(etag)) {
1349
+ ctx.status = 304;
1350
+ return;
1351
+ }
1352
+ ctx.set("Content-Security-Policy", "default-src 'none'; sandbox");
1353
+ ctx.set("Cross-Origin-Resource-Policy", "same-origin");
1354
+ ctx.set("X-Content-Type-Options", "nosniff");
1355
+ ctx.set("Accept-Ranges", "bytes");
1356
+ ctx.set("Content-Disposition", contentDisposition(file.filename));
1357
+ ctx.type = file.mediaType;
1358
+ if (file.byteLength === 0) {
1359
+ if (ctx.get("range")) {
1360
+ ctx.status = 416;
1361
+ ctx.set("Content-Range", "bytes */0");
1362
+ return;
1363
+ }
1364
+ ctx.status = 200;
1365
+ ctx.length = 0;
1366
+ if (ctx.method !== "HEAD")
1367
+ ctx.body = Buffer.alloc(0);
1368
+ return;
1369
+ }
1370
+ const requestedRange = ctx.get("range");
1371
+ const ifRange = ctx.get("if-range");
1372
+ const range = ifRange && ifRange !== etag
1373
+ ? undefined
1374
+ : parseSingleByteRange(requestedRange, file.byteLength);
1375
+ if (range === "unsatisfiable") {
1376
+ ctx.status = 416;
1377
+ ctx.set("Content-Range", `bytes */${file.byteLength}`);
1378
+ return;
1379
+ }
1380
+ const start = range?.start ?? 0;
1381
+ const end = range?.end ?? file.byteLength - 1;
1382
+ if (range) {
1383
+ ctx.status = 206;
1384
+ ctx.set("Content-Range", `bytes ${start}-${end}/${file.byteLength}`);
1385
+ }
1386
+ ctx.length = end - start + 1;
1387
+ if (ctx.method === "HEAD") {
1388
+ ctx.status = range ? 206 : 200;
1389
+ return;
1390
+ }
1391
+ streamOwnsLease = true;
1392
+ const body = Readable.from((async function* () {
1393
+ let offset = start;
1394
+ try {
1395
+ while (offset <= end) {
1396
+ const length = Math.min(SESSION_RESOURCE_TRANSFER_CHUNK_BYTES, end - offset + 1);
1397
+ const result = local
1398
+ ? await local.readWorkspaceFile({
1399
+ sessionId,
1400
+ path,
1401
+ version: file.version,
1402
+ offset,
1403
+ length,
1404
+ })
1405
+ : await lease.call("session.workspace.file.read", {
1406
+ sessionId,
1407
+ path,
1408
+ version: file.version,
1409
+ offset,
1410
+ length,
1411
+ }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS, signal: invocation.signal });
1412
+ const chunk = Buffer.from(result.data, "base64");
1413
+ if (result.offset !== offset + chunk.byteLength || chunk.byteLength === 0) {
1414
+ throw runtimeProtocolError("Runtime Session workspace file read did not advance");
1415
+ }
1416
+ offset = result.offset;
1417
+ yield chunk;
1418
+ }
1419
+ }
1420
+ finally {
1421
+ cleanup();
1422
+ }
1423
+ })());
1424
+ body.once("close", cleanup);
1425
+ ctx.body = body;
1426
+ }
1427
+ catch (error) {
1428
+ runtimeTargetHostError(ctx, error);
1429
+ }
1430
+ finally {
1431
+ if (!streamOwnsLease)
1432
+ cleanup();
1433
+ }
1434
+ };
1097
1435
  const runtimeSessionMessageEnqueue = async (ctx) => {
1098
1436
  const body = await readRuntimeBody(ctx);
1099
1437
  if (!body)
@@ -1153,6 +1491,32 @@ export function createControlRouter(opts) {
1153
1491
  if (outcome.ok)
1154
1492
  ctx.body = outcome.result;
1155
1493
  };
1494
+ const runtimeBrowserRequestHeaders = async (ctx) => {
1495
+ const outcome = await runtimeCall(ctx, "browser.request-headers.get", {
1496
+ sessionId: ctx.params.id,
1497
+ });
1498
+ if (outcome.ok) {
1499
+ ctx.set("Cache-Control", "no-store");
1500
+ ctx.body = outcome.result;
1501
+ }
1502
+ };
1503
+ const runtimeBrowserRequestHeadersUpdate = async (ctx) => {
1504
+ const body = await readRuntimeBody(ctx);
1505
+ if (!body)
1506
+ return;
1507
+ if (!acceptRuntimeBodyKeys(ctx, body, ["expectedRevision", "enabled", "headers"]))
1508
+ return;
1509
+ const outcome = await runtimeCall(ctx, "browser.request-headers.set", {
1510
+ sessionId: ctx.params.id,
1511
+ expectedRevision: body.expectedRevision,
1512
+ enabled: body.enabled,
1513
+ headers: body.headers,
1514
+ });
1515
+ if (outcome.ok) {
1516
+ ctx.set("Cache-Control", "no-store");
1517
+ ctx.body = outcome.result;
1518
+ }
1519
+ };
1156
1520
  const runtimeBrowserOpen = async (ctx) => {
1157
1521
  const body = await readRuntimeBody(ctx);
1158
1522
  if (!body)
@@ -1714,6 +2078,8 @@ export function createControlRouter(opts) {
1714
2078
  router.get("/api/runtimes/:selector/sessions/launch-options", publicRuntimeRead(runtimeSessionLaunchOptions));
1715
2079
  router.post("/api/runtimes/:selector/sessions", publicRuntimeMutation(runtimeSessionCreate));
1716
2080
  router.post("/api/runtimes/:selector/sessions/:id/fork", publicRuntimeMutation(runtimeSessionFork));
2081
+ router.get("/api/runtimes/:selector/sessions/:id/execution", publicRuntimeRead(runtimeSessionExecutionSettings));
2082
+ router.put("/api/runtimes/:selector/sessions/:id/execution", publicRuntimeMutation(runtimeSessionExecutionSettingsUpdate));
1717
2083
  router.get("/api/runtimes/:selector/sessions/:id/snapshot", publicRuntimeRead(runtimeSessionSnapshot));
1718
2084
  router.get("/api/runtimes/:selector/sessions/:id/snapshot-page", publicRuntimeRead(runtimeSessionSnapshotPage));
1719
2085
  router.get("/api/runtimes/:selector/sessions/:id/stream", publicRuntimeRead(runtimeSessionStream));
@@ -1723,12 +2089,22 @@ export function createControlRouter(opts) {
1723
2089
  router.post("/api/runtimes/:selector/sessions/:id/resources", publicRuntimeMutation(runtimeSessionResourceUpload));
1724
2090
  router.get("/api/runtimes/:selector/sessions/:id/resources/:resourceId", publicRuntimeRead(runtimeSessionResourceMetadata));
1725
2091
  router.get("/api/runtimes/:selector/sessions/:id/resources/:resourceId/content", publicRuntimeRead(runtimeSessionResourceContent));
2092
+ router.head("/api/runtimes/:selector/sessions/:id/resources/:resourceId/content", publicRuntimeRead(runtimeSessionResourceContent));
2093
+ router.get("/api/runtimes/:selector/sessions/:id/items/:itemId/files/:partIndex/content", publicRuntimeRead(runtimeSessionItemFileContent));
2094
+ router.head("/api/runtimes/:selector/sessions/:id/items/:itemId/files/:partIndex/content", publicRuntimeRead(runtimeSessionItemFileContent));
2095
+ router.get("/api/runtimes/:selector/sessions/:id/workspace/files/content", publicRuntimeRead(runtimeSessionWorkspaceFileContent));
2096
+ router.head("/api/runtimes/:selector/sessions/:id/workspace/files/content", publicRuntimeRead(runtimeSessionWorkspaceFileContent));
1726
2097
  router.delete("/api/runtimes/:selector/sessions/:id/resources/:resourceId", publicRuntimeMutation(runtimeSessionResourceDelete));
1727
2098
  router.post("/api/runtimes/:selector/sessions/:id/messages/queue", publicRuntimeMutation(runtimeSessionMessageEnqueue));
1728
2099
  router.post("/api/runtimes/:selector/sessions/:id/terminal/start", publicRuntimeMutation(runtimeSessionTerminalStart));
1729
2100
  router.post("/api/runtimes/:selector/sessions/:id/interactions/:interactionId/resolve", publicRuntimeMutation(runtimeSessionResolveInteraction));
1730
2101
  router.delete("/api/runtimes/:selector/sessions/:id", publicRuntimeMutation(runtimeSessionDelete));
1731
2102
  router.get("/api/runtimes/:selector/sessions/:id/browser", publicRuntimeRead(runtimeBrowserState));
2103
+ router.get("/api/runtimes/:selector/sessions/:id/browser/request-headers",
2104
+ // Header values may be sensitive. Reading them requires the same
2105
+ // process-lifetime capability and Portal grant as a mutation.
2106
+ publicRuntimeMutation(runtimeBrowserRequestHeaders));
2107
+ router.put("/api/runtimes/:selector/sessions/:id/browser/request-headers", publicRuntimeMutation(runtimeBrowserRequestHeadersUpdate));
1732
2108
  router.post("/api/runtimes/:selector/sessions/:id/browser/open", publicRuntimeMutation(runtimeBrowserOpen));
1733
2109
  router.post("/api/runtimes/:selector/sessions/:id/browser/close", publicRuntimeMutation(runtimeBrowserClose));
1734
2110
  router.post("/api/runtimes/:selector/sessions/:id/browser/pages", publicRuntimeMutation(runtimeBrowserPageCreate));
@@ -2711,6 +3087,14 @@ export function createControlRouter(opts) {
2711
3087
  router.get("/api/agents", async (ctx) => {
2712
3088
  ctx.body = { agents: await deps.listAgents() };
2713
3089
  });
3090
+ router.get("/api/agents/runtime-options", async (ctx) => {
3091
+ if (!deps.listAgentRuntimeOptions)
3092
+ return notFound(ctx, "local runtime discovery is unavailable");
3093
+ ctx.set("Cache-Control", "no-store");
3094
+ ctx.body = {
3095
+ runtimes: await deps.listAgentRuntimeOptions({ refresh: asString(ctx.query.refresh) === "1" }),
3096
+ };
3097
+ });
2714
3098
  router.get("/api/agents/:id", async (ctx) => {
2715
3099
  const spec = await deps.getAgent(ctx.params.id);
2716
3100
  if (!spec)
@@ -2723,6 +3107,11 @@ export function createControlRouter(opts) {
2723
3107
  if (!id)
2724
3108
  return bad(ctx, "missing agent id");
2725
3109
  try {
3110
+ if (await deps.getAgent(id)) {
3111
+ ctx.status = 409;
3112
+ ctx.body = { error: "agent id already exists" };
3113
+ return;
3114
+ }
2726
3115
  deps.writeAgent(id, body);
2727
3116
  }
2728
3117
  catch (error) {
@@ -2730,6 +3119,19 @@ export function createControlRouter(opts) {
2730
3119
  }
2731
3120
  ctx.body = { ok: true };
2732
3121
  });
3122
+ router.put("/api/agents/:id", async (ctx) => {
3123
+ const id = ctx.params.id;
3124
+ const body = await readJson(ctx);
3125
+ if (!await deps.getAgent(id))
3126
+ return notFound(ctx, "agent not found");
3127
+ try {
3128
+ deps.writeAgent(id, { ...body, id });
3129
+ }
3130
+ catch (error) {
3131
+ return bad(ctx, error instanceof Error ? error.message : String(error));
3132
+ }
3133
+ ctx.body = { ok: true };
3134
+ });
2733
3135
  router.delete("/api/agents/:id", (ctx) => {
2734
3136
  ctx.body = { ok: deps.removeAgent(ctx.params.id) };
2735
3137
  });
@@ -2769,6 +3171,64 @@ export function createControlRouter(opts) {
2769
3171
  return bad(ctx, error instanceof Error ? error.message : String(error));
2770
3172
  }
2771
3173
  });
3174
+ router.post("/api/skills/local-scan", async (ctx) => {
3175
+ if (!deps.scanLocalSkills)
3176
+ return notFound(ctx, "local Skill discovery is unavailable");
3177
+ const body = await readJson(ctx);
3178
+ const runtime = parseProviderCliId(body.runtime);
3179
+ if (!runtime)
3180
+ return bad(ctx, "runtime must be codex, traex, or claude");
3181
+ try {
3182
+ ctx.body = { candidates: await deps.scanLocalSkills(runtime) };
3183
+ }
3184
+ catch (error) {
3185
+ return bad(ctx, error instanceof Error ? error.message : String(error));
3186
+ }
3187
+ });
3188
+ router.post("/api/skills/local-import", async (ctx) => {
3189
+ if (!deps.importLocalSkills)
3190
+ return notFound(ctx, "local Skill import is unavailable");
3191
+ const body = await readJson(ctx);
3192
+ const runtime = parseProviderCliId(body.runtime);
3193
+ const rawKeys = Array.isArray(body.keys) ? body.keys : [];
3194
+ const keys = rawKeys.length > 0
3195
+ ? rawKeys.filter((value) => typeof value === "string" && value.length > 0)
3196
+ : [];
3197
+ if (!runtime)
3198
+ return bad(ctx, "runtime must be codex, traex, or claude");
3199
+ if (keys.length === 0 || keys.length !== rawKeys.length || keys.length > 100) {
3200
+ return bad(ctx, "keys must contain 1-100 non-empty candidate keys");
3201
+ }
3202
+ try {
3203
+ ctx.body = { results: await deps.importLocalSkills(runtime, keys) };
3204
+ }
3205
+ catch (error) {
3206
+ return bad(ctx, error instanceof Error ? error.message : String(error));
3207
+ }
3208
+ });
3209
+ router.post("/api/skills/import-archive", async (ctx) => {
3210
+ if (!deps.importSkillArchive)
3211
+ return notFound(ctx, "Skill archive import is unavailable");
3212
+ let body;
3213
+ try {
3214
+ body = await readJson(ctx, 29 * 1024 * 1024);
3215
+ }
3216
+ catch (error) {
3217
+ return bad(ctx, error instanceof Error ? error.message : String(error));
3218
+ }
3219
+ const filename = asString(body.filename);
3220
+ const contentBase64 = asString(body.contentBase64);
3221
+ if (!filename || !contentBase64)
3222
+ return bad(ctx, "filename and contentBase64 are required");
3223
+ if (contentBase64.length > 28 * 1024 * 1024)
3224
+ return bad(ctx, "archive payload is too large");
3225
+ try {
3226
+ ctx.body = { results: await deps.importSkillArchive(filename, contentBase64) };
3227
+ }
3228
+ catch (error) {
3229
+ return bad(ctx, error instanceof Error ? error.message : String(error));
3230
+ }
3231
+ });
2772
3232
  router.delete("/api/skills/:name", async (ctx) => {
2773
3233
  try {
2774
3234
  ctx.body = { ok: await deps.removeSkill(ctx.params.name) };
@@ -3107,12 +3567,16 @@ export function createControlRouter(opts) {
3107
3567
  const body = await readJson(ctx);
3108
3568
  const agent = asString(body.agent);
3109
3569
  const provider = asString(body.provider);
3570
+ const permissionPreset = parseSessionPermissionPreset(body.permissionPreset);
3110
3571
  if (body.config != null) {
3111
3572
  return bad(ctx, "inline Agent configs are no longer supported; save an Agent first");
3112
3573
  }
3113
3574
  if (Boolean(agent) === Boolean(provider)) {
3114
3575
  return bad(ctx, "provide exactly one Agent or Provider");
3115
3576
  }
3577
+ if (body.permissionPreset !== undefined && !permissionPreset) {
3578
+ return bad(ctx, "permissionPreset must be default, read-only, workspace-write, or full-access");
3579
+ }
3116
3580
  try {
3117
3581
  ctx.body = await localMachineSessions.create({
3118
3582
  ...(agent ? { agent } : { provider: provider }),
@@ -3120,6 +3584,7 @@ export function createControlRouter(opts) {
3120
3584
  ...(asString(body.reasoningEffort)
3121
3585
  ? { reasoningEffort: asString(body.reasoningEffort) }
3122
3586
  : {}),
3587
+ ...(permissionPreset ? { permissionPreset } : {}),
3123
3588
  ...(asString(body.title) ? { title: asString(body.title) } : {}),
3124
3589
  ...(asString(body.projectId) ? { projectId: asString(body.projectId) } : {}),
3125
3590
  });
@@ -3140,7 +3605,20 @@ export function createControlRouter(opts) {
3140
3605
  }
3141
3606
  catch (error) {
3142
3607
  ctx.status = 503;
3143
- ctx.body = { error: error instanceof Error ? error.message : String(error) };
3608
+ const runtimeFailure = error instanceof MachineSessionServiceFailure
3609
+ ? error.runtimeFailure
3610
+ : undefined;
3611
+ const message = runtimeFailure?.message
3612
+ ?? (error instanceof MachineSessionServiceFailure ? error.detail : undefined)
3613
+ ?? (error instanceof Error ? error.message : String(error));
3614
+ ctx.body = {
3615
+ error: message,
3616
+ code: runtimeFailure?.code
3617
+ ?? (error instanceof MachineSessionServiceFailure ? error.code : "runtime_error"),
3618
+ outcome: error instanceof MachineSessionServiceFailure && error.code === "outcome_unknown"
3619
+ ? "unknown"
3620
+ : "not_started",
3621
+ };
3144
3622
  }
3145
3623
  return;
3146
3624
  }
@@ -3159,26 +3637,31 @@ export function createControlRouter(opts) {
3159
3637
  execution: structuredClone(meta.execution),
3160
3638
  });
3161
3639
  if (!live) {
3640
+ const failure = runnerManager.lastLiveSessionFailure?.(id);
3162
3641
  ctx.status = 503;
3163
3642
  ctx.body = {
3164
- error: `live session unavailable (${meta.execution.provider})`,
3165
- ...(runnerManager.lastLiveSessionError?.(id)
3166
- ? { detail: runnerManager.lastLiveSessionError(id) }
3167
- : {}),
3643
+ error: failure?.message
3644
+ ?? runnerManager.lastLiveSessionError?.(id)
3645
+ ?? `live session unavailable (${meta.execution.provider})`,
3646
+ code: failure?.code ?? "live_unavailable",
3647
+ outcome: "not_started",
3168
3648
  };
3169
3649
  return;
3170
3650
  }
3171
- const outcome = await runnerManager.injectMessage(id, message);
3172
- if (outcome === "injected") {
3651
+ const result = await runnerManager.injectMessage(id, message);
3652
+ const outcome = result.outcome;
3653
+ if (outcome === "injected" || outcome === "steered") {
3173
3654
  ctx.body = { ok: true, injected: true };
3174
3655
  return;
3175
3656
  }
3176
3657
  ctx.status = 503;
3658
+ const failure = runnerManager.lastLiveSessionFailure?.(id);
3177
3659
  ctx.body = {
3178
- error: `live injection ${outcome}`,
3179
- ...(runnerManager.lastLiveSessionError?.(id)
3180
- ? { detail: runnerManager.lastLiveSessionError(id) }
3181
- : {}),
3660
+ error: failure?.message
3661
+ ?? runnerManager.lastLiveSessionError?.(id)
3662
+ ?? `live injection ${outcome}`,
3663
+ code: failure?.code ?? "live_inject_failed",
3664
+ outcome: outcome === "failed" ? "unknown" : "not_started",
3182
3665
  };
3183
3666
  });
3184
3667
  // Stop the session's active turn (the web Stop button). For a live native
@@ -3204,6 +3687,7 @@ export function createControlRouter(opts) {
3204
3687
  ctx.body = {
3205
3688
  sessionId: id,
3206
3689
  items: sessionLog ? await sessionLog.snapshot(id) : [],
3690
+ pendingInputs: [],
3207
3691
  runtime: sessionRuntimeIndex.snapshot(id),
3208
3692
  };
3209
3693
  });
@@ -3294,7 +3778,15 @@ export function createControlRouter(opts) {
3294
3778
  ctx.body = { error: "session_resource_cleanup_failed" };
3295
3779
  return;
3296
3780
  }
3297
- runnerManager?.stopRunner(id);
3781
+ if (runnerManager?.terminateLiveSession) {
3782
+ await runnerManager.terminateLiveSession(id).catch((error) => {
3783
+ console.warn(`[control-api] session=${id} live teardown failed during deletion; continuing best-effort: ${error instanceof Error ? error.message : String(error)}`);
3784
+ return false;
3785
+ });
3786
+ }
3787
+ else {
3788
+ runnerManager?.stopRunner(id);
3789
+ }
3298
3790
  sessionBus?.close(id);
3299
3791
  deps.removeSessionMeta(id);
3300
3792
  // Hard-delete the transcript too — the session list is meta ∪ log, so
@@ -3399,11 +3891,28 @@ export function synthesizeSessionTitle(message, limit = 60) {
3399
3891
  return collapsed;
3400
3892
  return `${collapsed.slice(0, limit - 1).trimEnd()}…`;
3401
3893
  }
3402
- async function readJson(ctx) {
3894
+ async function readJson(ctx, maxBytes) {
3403
3895
  const raw = await new Promise((resolve, reject) => {
3404
3896
  let data = "";
3405
- ctx.req.on("data", (chunk) => (data += chunk));
3406
- ctx.req.on("end", () => resolve(data));
3897
+ let bytes = 0;
3898
+ let exceeded = false;
3899
+ ctx.req.on("data", (chunk) => {
3900
+ if (exceeded)
3901
+ return;
3902
+ bytes += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.byteLength;
3903
+ if (maxBytes !== undefined && bytes > maxBytes) {
3904
+ exceeded = true;
3905
+ data = "";
3906
+ return;
3907
+ }
3908
+ data += chunk;
3909
+ });
3910
+ ctx.req.on("end", () => {
3911
+ if (exceeded)
3912
+ reject(new Error("request body is too large"));
3913
+ else
3914
+ resolve(data);
3915
+ });
3407
3916
  ctx.req.on("error", reject);
3408
3917
  });
3409
3918
  if (!raw.trim())
@@ -3424,6 +3933,14 @@ function parseProviderCliId(value) {
3424
3933
  ? value
3425
3934
  : undefined;
3426
3935
  }
3936
+ function parseSessionPermissionPreset(value) {
3937
+ return value === "default" ||
3938
+ value === "read-only" ||
3939
+ value === "workspace-write" ||
3940
+ value === "full-access"
3941
+ ? value
3942
+ : undefined;
3943
+ }
3427
3944
  function parseProviderCliOperation(value) {
3428
3945
  return value === "install" || value === "update" ? value : undefined;
3429
3946
  }
@@ -3439,6 +3956,14 @@ function optionalRuntimeDevice(body) {
3439
3956
  return body.device === undefined ? {} : { device: body.device };
3440
3957
  }
3441
3958
  function remoteRuntimeRpcTimeoutMs(method, params) {
3959
+ // Native startup/delivery owns phase-specific deadlines and returns their
3960
+ // concrete failures. A BFF deadline here would race those phases and replace
3961
+ // the real error with an ambiguous generic RPC timeout. The setup queue also
3962
+ // awaits Terminal startup before acknowledging the request.
3963
+ if (method === "session.message.send" ||
3964
+ method === "session.message.enqueue" ||
3965
+ method === "session.terminal.start")
3966
+ return null;
3442
3967
  if (method === "session.emulator.attach")
3443
3968
  return REMOTE_RUNTIME_EMULATOR_ATTACH_TIMEOUT_MS;
3444
3969
  if (method === "session.emulator.type") {
@@ -3542,6 +4067,36 @@ function pluginInstallInvocationAbortScope(ctx, shutdownSignal) {
3542
4067
  function browserArtifactInvocationAbortScope(ctx, shutdownSignal) {
3543
4068
  return managementInvocationAbortScope(ctx, shutdownSignal, BROWSER_ARTIFACT_OPERATION_TIMEOUT_MS, "Browser artifact operation");
3544
4069
  }
4070
+ function downloadInvocationAbortScope(ctx, shutdownSignal) {
4071
+ const controller = new AbortController();
4072
+ const abort = (reason) => {
4073
+ if (!controller.signal.aborted)
4074
+ controller.abort(reason);
4075
+ };
4076
+ const onRequestAborted = () => abort(namedError("download request aborted", "AbortError"));
4077
+ const onResponseClose = () => {
4078
+ if (!ctx.res.writableEnded) {
4079
+ abort(namedError("download client disconnected", "AbortError"));
4080
+ }
4081
+ };
4082
+ const onShutdown = () => abort(shutdownSignal?.reason ?? namedError("daemon is shutting down", "AbortError"));
4083
+ ctx.req.once("aborted", onRequestAborted);
4084
+ ctx.res.once("close", onResponseClose);
4085
+ if (shutdownSignal?.aborted)
4086
+ onShutdown();
4087
+ else
4088
+ shutdownSignal?.addEventListener("abort", onShutdown, { once: true });
4089
+ if (ctx.req.aborted)
4090
+ onRequestAborted();
4091
+ return {
4092
+ signal: controller.signal,
4093
+ dispose() {
4094
+ ctx.req.removeListener("aborted", onRequestAborted);
4095
+ ctx.res.removeListener("close", onResponseClose);
4096
+ shutdownSignal?.removeEventListener("abort", onShutdown);
4097
+ },
4098
+ };
4099
+ }
3545
4100
  function managementInvocationAbortScope(ctx, shutdownSignal, timeoutMs, label) {
3546
4101
  const controller = new AbortController();
3547
4102
  const abort = (reason) => {
@@ -3762,8 +4317,14 @@ function runtimeTargetHostError(ctx, error, forcedOutcome) {
3762
4317
  const status = runtimeTargetHttpStatus(code);
3763
4318
  ctx.status = status;
3764
4319
  const outcome = forcedOutcome ?? runtimeTargetErrorOutcome(error);
4320
+ const applicationMessage = error instanceof Error && error.name === "DirectRuntimeRpcError"
4321
+ ? error.message.replace(/^Remote Runtime RPC failed: [^:]+: /, "")
4322
+ : undefined;
3765
4323
  ctx.body = {
3766
- error: status === 500 ? "internal_error" : code,
4324
+ error: applicationMessage ?? (status === 500 ? "internal_error" : code),
4325
+ ...(applicationMessage
4326
+ ? { code: status === 500 ? "internal_error" : code }
4327
+ : {}),
3767
4328
  ...(outcome === undefined ? {} : { outcome }),
3768
4329
  };
3769
4330
  }
@@ -3851,6 +4412,83 @@ function publicRuntimeStreamError(error) {
3851
4412
  }
3852
4413
  class RequestBodyTooLargeError extends Error {
3853
4414
  }
4415
+ function isMediaType(value) {
4416
+ return value.length <= 255 && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(value);
4417
+ }
4418
+ async function forwardResourceUploadBody(ctx, uploadId, resumeOffset, expectedBytes, writeChunk) {
4419
+ let received = 0;
4420
+ let remoteOffset = resumeOffset;
4421
+ let carry = Buffer.alloc(0);
4422
+ for await (const raw of ctx.req) {
4423
+ const incoming = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
4424
+ if (received + incoming.byteLength > expectedBytes) {
4425
+ throw runtimeProtocolError("Resource upload exceeds Content-Length");
4426
+ }
4427
+ const skip = Math.min(incoming.byteLength, Math.max(0, resumeOffset - received));
4428
+ received += incoming.byteLength;
4429
+ let cursor = skip;
4430
+ while (cursor < incoming.byteLength) {
4431
+ const needed = SESSION_RESOURCE_TRANSFER_CHUNK_BYTES - carry.byteLength;
4432
+ const take = Math.min(needed, incoming.byteLength - cursor);
4433
+ carry = carry.byteLength === 0
4434
+ ? incoming.subarray(cursor, cursor + take)
4435
+ : Buffer.concat([carry, incoming.subarray(cursor, cursor + take)]);
4436
+ cursor += take;
4437
+ if (carry.byteLength < SESSION_RESOURCE_TRANSFER_CHUNK_BYTES)
4438
+ continue;
4439
+ const written = await writeChunk(uploadId, remoteOffset, carry.toString("base64"));
4440
+ if (written.offset !== remoteOffset + carry.byteLength) {
4441
+ throw runtimeProtocolError("Runtime Session resource upload did not advance");
4442
+ }
4443
+ remoteOffset = written.offset;
4444
+ carry = Buffer.alloc(0);
4445
+ }
4446
+ }
4447
+ if (received !== expectedBytes) {
4448
+ throw runtimeProtocolError("Resource upload ended before Content-Length");
4449
+ }
4450
+ if (carry.byteLength > 0) {
4451
+ const written = await writeChunk(uploadId, remoteOffset, carry.toString("base64"));
4452
+ if (written.offset !== remoteOffset + carry.byteLength) {
4453
+ throw runtimeProtocolError("Runtime Session resource upload did not advance");
4454
+ }
4455
+ remoteOffset = written.offset;
4456
+ }
4457
+ if (remoteOffset !== expectedBytes) {
4458
+ throw runtimeProtocolError("Runtime Session resource upload length changed");
4459
+ }
4460
+ }
4461
+ function parseSingleByteRange(header, byteLength) {
4462
+ if (!header)
4463
+ return undefined;
4464
+ const match = /^bytes=(\d*)-(\d*)$/.exec(header.trim());
4465
+ if (!match || byteLength <= 0)
4466
+ return "unsatisfiable";
4467
+ const [, startText, endText] = match;
4468
+ if (!startText && !endText)
4469
+ return "unsatisfiable";
4470
+ if (!startText) {
4471
+ const suffix = Number(endText);
4472
+ if (!Number.isSafeInteger(suffix) || suffix <= 0)
4473
+ return "unsatisfiable";
4474
+ return { start: Math.max(0, byteLength - suffix), end: byteLength - 1 };
4475
+ }
4476
+ const start = Number(startText);
4477
+ const requestedEnd = endText ? Number(endText) : byteLength - 1;
4478
+ if (!Number.isSafeInteger(start) ||
4479
+ !Number.isSafeInteger(requestedEnd) ||
4480
+ start < 0 ||
4481
+ requestedEnd < start ||
4482
+ start >= byteLength) {
4483
+ return "unsatisfiable";
4484
+ }
4485
+ return { start, end: Math.min(requestedEnd, byteLength - 1) };
4486
+ }
4487
+ function contentDisposition(filename) {
4488
+ if (!filename)
4489
+ return "inline";
4490
+ return `inline; filename*=UTF-8''${encodeURIComponent(filename)}`;
4491
+ }
3854
4492
  async function readBoundedBinary(ctx, maxBytes) {
3855
4493
  const declaredLength = Number(ctx.get("content-length"));
3856
4494
  if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {