@rynx-ai/server 0.1.11-beta.5 → 0.1.11-beta.51

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 (499) hide show
  1. package/dist/control-api.d.ts +11 -5
  2. package/dist/control-api.js +699 -95
  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 +12 -1
  471. package/dist/desktop-browser-host.js +110 -13
  472. package/dist/direct-runtime-server.js +187 -153
  473. package/dist/machine-session-service.d.ts +96 -15
  474. package/dist/machine-session-service.js +745 -115
  475. package/dist/remote-runtime-dispatcher.d.ts +2 -2
  476. package/dist/remote-runtime-dispatcher.js +39 -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 +67 -16
  480. package/dist/server.js +422 -55
  481. package/dist/session-browser-service.d.ts +50 -4
  482. package/dist/session-browser-service.js +232 -11
  483. package/dist/session-browser-surface-coordinator.d.ts +2 -0
  484. package/dist/session-browser-surface-coordinator.js +15 -0
  485. package/dist/session-pending-inputs.d.ts +42 -0
  486. package/dist/session-pending-inputs.js +87 -0
  487. package/dist/session-portal.d.ts +54 -0
  488. package/dist/session-portal.js +997 -0
  489. package/dist/session-runtime-index.d.ts +3 -6
  490. package/dist/session-runtime-index.js +96 -38
  491. package/dist/session-terminal-host.d.ts +22 -2
  492. package/dist/session-terminal-host.js +66 -83
  493. package/dist/terminal-ws.d.ts +4 -1
  494. package/dist/terminal-ws.js +93 -27
  495. package/package.json +7 -7
  496. package/dist/control-web/assets/highlighted-body-OFNGDK62-B4mcMjmm.js +0 -1
  497. package/dist/control-web/assets/index-5n6D-i-c.css +0 -32
  498. package/dist/control-web/assets/index-D56JQ9oi.js +0 -709
  499. package/dist/control-web/assets/mermaid-GHXKKRXX-DnL0iDTi.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";
@@ -14,11 +15,12 @@ import { DIRECT_RUNTIME_CONTROL_PATH, encodePairingCode, } from "@rynx-ai/protoc
14
15
  import { PLUGIN_CONSOLE_INSTALL_PREPARATIONS_PATH, PLUGIN_CONSOLE_MARKETPLACES_PATH, PLUGIN_INSTALL_PREPARATIONS_PATH, PLUGIN_MARKETPLACES_PATH, parsePluginInstallCommitInput, parsePluginInstallPrepareInput, parsePluginMarketplaceAddInput, } from "@rynx-ai/protocol/plugin-management";
15
16
  import { parseDaemonStatus } from "@rynx-ai/protocol/remote-runtime";
16
17
  import { materializeRemoteRuntimeSessionEvent, materializeRemoteRuntimeSessionRuntimeSnapshot, parseRemoteRuntimeRpcRequest, REMOTE_RUNTIME_RPC_MAX_FRAME_BYTES, SESSION_IMAGE_MEDIA_TYPES, SESSION_RESOURCE_MAX_IMAGE_BYTES, SESSION_RESOURCE_MAX_FILENAME_CHARS, SESSION_RESOURCE_TRANSFER_CHUNK_BYTES, REMOTE_RUNTIME_SESSION_MAX_PAGE_SIZE, } from "@rynx-ai/protocol/remote-runtime-rpc";
17
- import { RUNTIME_BROWSER_BOOTSTRAP_PATH, RUNTIME_BROWSER_CAPABILITY_HEADER, RUNTIME_BROWSER_MANAGEMENT_PATH_PREFIX, RUNTIME_BROWSER_RPC_PATH, RUNTIME_BROWSER_SESSION_ID_HEADER, parseRuntimeBrowserBootstrapCredential, } from "@rynx-ai/protocol/runtime-browser-bootstrap";
18
+ import { RUNTIME_BROWSER_BOOTSTRAP_PATH, RUNTIME_BROWSER_CAPABILITY_HEADER, RUNTIME_BROWSER_MANAGEMENT_PATH_PREFIX, RUNTIME_BROWSER_RPC_PATH, RUNTIME_BROWSER_EXECUTE_PATH, RUNTIME_BROWSER_SESSION_ID_HEADER, parseRuntimeBrowserBootstrapCredential, parseRuntimeBrowserAutomationCommand, } from "@rynx-ai/protocol/runtime-browser-bootstrap";
18
19
  import { parseRuntimeBrowserStateGetParams } from "@rynx-ai/protocol/runtime-browser";
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;
@@ -735,12 +742,15 @@ export function createControlRouter(opts) {
735
742
  const body = await readRuntimeBody(ctx);
736
743
  if (!body)
737
744
  return;
738
- if (!acceptRuntimeBodyKeys(ctx, body, ["model", "reasoningEffort"]))
745
+ if (!acceptRuntimeBodyKeys(ctx, body, ["model", "reasoningEffort", "collaborationMode"]))
739
746
  return;
740
747
  const outcome = await runtimeCall(ctx, "session.execution.update", {
741
748
  sessionId: ctx.params.id,
742
749
  model: body.model,
743
750
  reasoningEffort: body.reasoningEffort,
751
+ ...(body.collaborationMode === undefined
752
+ ? {}
753
+ : { collaborationMode: body.collaborationMode }),
744
754
  });
745
755
  if (outcome.ok)
746
756
  ctx.body = outcome.result;
@@ -855,7 +865,13 @@ export function createControlRouter(opts) {
855
865
  };
856
866
  const runtimeSessionResourceUpload = async (ctx) => {
857
867
  const uploadStarted = performance.now();
858
- 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";
859
875
  const clientUploadId = ctx.get("x-rynx-upload-id").trim();
860
876
  const encodedFilename = ctx.get("x-rynx-filename").trim();
861
877
  let filename = "";
@@ -868,7 +884,9 @@ export function createControlRouter(opts) {
868
884
  return;
869
885
  }
870
886
  if (!mediaType ||
871
- !SESSION_IMAGE_MEDIA_TYPES.includes(mediaType) ||
887
+ !isMediaType(mediaType) ||
888
+ (resourceType === "input_image" &&
889
+ !SESSION_IMAGE_MEDIA_TYPES.includes(mediaType)) ||
872
890
  !clientUploadId ||
873
891
  !filename ||
874
892
  filename.length > SESSION_RESOURCE_MAX_FILENAME_CHARS) {
@@ -876,23 +894,21 @@ export function createControlRouter(opts) {
876
894
  ctx.body = { error: "invalid_resource_upload" };
877
895
  return;
878
896
  }
879
- let bytes;
880
- const bodyReadStarted = performance.now();
881
- try {
882
- bytes = await readBoundedBinary(ctx, SESSION_RESOURCE_MAX_IMAGE_BYTES);
883
- }
884
- catch (error) {
885
- ctx.status = error instanceof RequestBodyTooLargeError ? 413 : 400;
886
- ctx.body = {
887
- error: error instanceof RequestBodyTooLargeError
888
- ? "request_too_large"
889
- : "invalid_resource_upload",
890
- };
897
+ const contentLengthHeader = ctx.get("content-length").trim();
898
+ if (!contentLengthHeader) {
899
+ ctx.status = 411;
900
+ ctx.body = { error: "content_length_required" };
891
901
  return;
892
902
  }
893
- if (bytes.byteLength === 0) {
903
+ const byteLength = Number(contentLengthHeader);
904
+ if (!Number.isSafeInteger(byteLength) || byteLength <= 0) {
894
905
  ctx.status = 400;
895
- 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" };
896
912
  return;
897
913
  }
898
914
  const sessionId = ctx.params.id;
@@ -900,9 +916,7 @@ export function createControlRouter(opts) {
900
916
  const lease = local ? undefined : await acquireRuntimeLease(ctx);
901
917
  if (!local && !lease)
902
918
  return;
903
- const timings = new Map([
904
- ["body", performance.now() - bodyReadStarted],
905
- ]);
919
+ const timings = new Map();
906
920
  const timed = async (name, operation) => {
907
921
  const started = performance.now();
908
922
  try {
@@ -919,16 +933,18 @@ export function createControlRouter(opts) {
919
933
  ? local.beginResourceUpload({
920
934
  sessionId,
921
935
  clientUploadId,
936
+ type: resourceType,
922
937
  filename,
923
938
  mediaType,
924
- byteLength: bytes.byteLength,
939
+ byteLength,
925
940
  })
926
941
  : lease.call("session.resource.upload.begin", {
927
942
  sessionId,
928
943
  clientUploadId,
944
+ type: resourceType,
929
945
  filename,
930
946
  mediaType,
931
- byteLength: bytes.byteLength,
947
+ byteLength,
932
948
  }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS }));
933
949
  const writeChunk = (uploadId, offset, data) => timed("chunks", () => local
934
950
  ? local.writeResourceUploadChunk({ sessionId, uploadId, offset, data })
@@ -936,44 +952,72 @@ export function createControlRouter(opts) {
936
952
  const commit = (uploadId) => timed("commit", () => local
937
953
  ? local.commitResourceUpload({ sessionId, uploadId })
938
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;
939
960
  try {
940
961
  const resourcePolicy = await policy();
941
962
  if (!resourcePolicy.enabled ||
942
- !resourcePolicy.mediaTypes.includes(mediaType) ||
943
- bytes.byteLength > resourcePolicy.maxImageBytes) {
963
+ (resourceType === "input_image" &&
964
+ (!resourcePolicy.mediaTypes.includes(mediaType) ||
965
+ byteLength > resourcePolicy.maxImageBytes))) {
944
966
  ctx.status = 413;
945
967
  ctx.body = { error: "resource_policy_rejected" };
946
968
  return;
947
969
  }
948
- const begun = await begin();
970
+ let begun = await begin();
949
971
  if (begun.complete && begun.resource) {
972
+ ctx.req.resume();
950
973
  ctx.set("Cache-Control", "no-store");
951
974
  ctx.body = { resource: begun.resource };
952
975
  return;
953
976
  }
954
- if (begun.offset < 0 || begun.offset > bytes.byteLength) {
977
+ if (begun.offset < 0 || begun.offset > byteLength) {
955
978
  throw runtimeProtocolError("Runtime Session resource upload offset is invalid");
956
979
  }
957
- let offset = begun.offset;
958
- while (offset < bytes.byteLength) {
959
- const chunk = bytes.subarray(offset, Math.min(offset + SESSION_RESOURCE_TRANSFER_CHUNK_BYTES, bytes.byteLength));
960
- const written = await writeChunk(begun.uploadId, offset, chunk.toString("base64"));
961
- if (written.offset <= offset || written.offset > bytes.byteLength) {
962
- 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");
963
992
  }
964
- offset = written.offset;
965
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);
966
998
  const committed = await commit(begun.uploadId);
967
999
  if (committed.resource.resourceId !== begun.resourceId ||
1000
+ committed.resource.type !== resourceType ||
968
1001
  committed.resource.mediaType !== mediaType ||
969
- committed.resource.byteLength !== bytes.byteLength) {
1002
+ committed.resource.byteLength !== byteLength) {
970
1003
  throw runtimeProtocolError("Runtime Session resource upload identity changed");
971
1004
  }
1005
+ resourceCommitted = true;
972
1006
  ctx.status = 201;
973
1007
  ctx.set("Cache-Control", "no-store");
974
1008
  ctx.body = committed;
975
1009
  }
976
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
+ }
977
1021
  runtimeTargetHostError(ctx, error);
978
1022
  }
979
1023
  finally {
@@ -989,7 +1033,7 @@ export function createControlRouter(opts) {
989
1033
  event: "session.resource.upload.slow",
990
1034
  selector: ctx.params.selector,
991
1035
  sessionId,
992
- byteLength: bytes.byteLength,
1036
+ byteLength,
993
1037
  status: ctx.status,
994
1038
  timings: Object.fromEntries([...timings.entries()].map(([name, duration]) => [
995
1039
  name,
@@ -1033,16 +1077,32 @@ export function createControlRouter(opts) {
1033
1077
  const sessionId = ctx.params.id;
1034
1078
  const resourceId = ctx.params.resourceId;
1035
1079
  const local = ctx.params.selector === "local" ? localSessionResources : undefined;
1036
- const lease = local ? undefined : await acquireRuntimeLease(ctx);
1037
- 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();
1038
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
+ };
1039
1095
  try {
1040
1096
  const { resource } = local
1041
1097
  ? await local.getResource({ sessionId, resourceId })
1042
- : 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 });
1043
1099
  if (resource.resourceId !== resourceId) {
1044
1100
  throw runtimeProtocolError("Runtime Session resource identity changed");
1045
1101
  }
1102
+ const byteLength = resource.byteLength;
1103
+ if (!Number.isSafeInteger(byteLength) || !byteLength || byteLength < 1) {
1104
+ throw runtimeProtocolError("Runtime Session resource length is invalid");
1105
+ }
1046
1106
  const etag = `"sha256-${resource.sha256}"`;
1047
1107
  ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
1048
1108
  ctx.set("ETag", etag);
@@ -1050,48 +1110,68 @@ export function createControlRouter(opts) {
1050
1110
  ctx.status = 304;
1051
1111
  return;
1052
1112
  }
1053
- const chunks = [];
1054
- let offset = 0;
1055
- while (offset < (resource.byteLength ?? 0)) {
1056
- const result = local
1057
- ? await local.readResource({
1058
- sessionId,
1059
- resourceId,
1060
- offset,
1061
- length: SESSION_RESOURCE_TRANSFER_CHUNK_BYTES,
1062
- })
1063
- : await lease.call("session.resource.read", {
1064
- sessionId,
1065
- resourceId,
1066
- offset,
1067
- length: SESSION_RESOURCE_TRANSFER_CHUNK_BYTES,
1068
- }, { timeoutMs: REMOTE_RUNTIME_SESSION_TIMEOUT_MS });
1069
- const chunk = Buffer.from(result.data, "base64");
1070
- if (result.offset !== offset + chunk.byteLength || (!result.eof && chunk.byteLength === 0)) {
1071
- throw runtimeProtocolError("Runtime Session resource read did not advance");
1072
- }
1073
- chunks.push(chunk);
1074
- offset = result.offset;
1075
- if (result.eof)
1076
- break;
1077
- }
1078
- const body = Buffer.concat(chunks);
1079
- if (body.byteLength !== resource.byteLength) {
1080
- 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;
1081
1122
  }
1123
+ const start = range?.start ?? 0;
1124
+ const end = range?.end ?? byteLength - 1;
1125
+ const responseLength = end - start + 1;
1082
1126
  ctx.set("Content-Security-Policy", "default-src 'none'; sandbox");
1083
1127
  ctx.set("Cross-Origin-Resource-Policy", "same-origin");
1084
1128
  ctx.set("X-Content-Type-Options", "nosniff");
1085
- 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
+ }
1086
1135
  ctx.type = resource.mediaType;
1087
- 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);
1088
1166
  ctx.body = body;
1089
1167
  }
1090
1168
  catch (error) {
1091
1169
  runtimeTargetHostError(ctx, error);
1092
1170
  }
1093
1171
  finally {
1094
- lease?.release();
1172
+ if (!streamOwnsLease) {
1173
+ cleanup();
1174
+ }
1095
1175
  }
1096
1176
  };
1097
1177
  const runtimeSessionResourceDelete = async (ctx) => {
@@ -1115,6 +1195,243 @@ export function createControlRouter(opts) {
1115
1195
  if (outcome.ok)
1116
1196
  ctx.body = outcome.result;
1117
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
+ };
1118
1435
  const runtimeSessionMessageEnqueue = async (ctx) => {
1119
1436
  const body = await readRuntimeBody(ctx);
1120
1437
  if (!body)
@@ -1174,6 +1491,32 @@ export function createControlRouter(opts) {
1174
1491
  if (outcome.ok)
1175
1492
  ctx.body = outcome.result;
1176
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
+ };
1177
1520
  const runtimeBrowserOpen = async (ctx) => {
1178
1521
  const body = await readRuntimeBody(ctx);
1179
1522
  if (!body)
@@ -1746,12 +2089,22 @@ export function createControlRouter(opts) {
1746
2089
  router.post("/api/runtimes/:selector/sessions/:id/resources", publicRuntimeMutation(runtimeSessionResourceUpload));
1747
2090
  router.get("/api/runtimes/:selector/sessions/:id/resources/:resourceId", publicRuntimeRead(runtimeSessionResourceMetadata));
1748
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));
1749
2097
  router.delete("/api/runtimes/:selector/sessions/:id/resources/:resourceId", publicRuntimeMutation(runtimeSessionResourceDelete));
1750
2098
  router.post("/api/runtimes/:selector/sessions/:id/messages/queue", publicRuntimeMutation(runtimeSessionMessageEnqueue));
1751
2099
  router.post("/api/runtimes/:selector/sessions/:id/terminal/start", publicRuntimeMutation(runtimeSessionTerminalStart));
1752
2100
  router.post("/api/runtimes/:selector/sessions/:id/interactions/:interactionId/resolve", publicRuntimeMutation(runtimeSessionResolveInteraction));
1753
2101
  router.delete("/api/runtimes/:selector/sessions/:id", publicRuntimeMutation(runtimeSessionDelete));
1754
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));
1755
2108
  router.post("/api/runtimes/:selector/sessions/:id/browser/open", publicRuntimeMutation(runtimeBrowserOpen));
1756
2109
  router.post("/api/runtimes/:selector/sessions/:id/browser/close", publicRuntimeMutation(runtimeBrowserClose));
1757
2110
  router.post("/api/runtimes/:selector/sessions/:id/browser/pages", publicRuntimeMutation(runtimeBrowserPageCreate));
@@ -1771,6 +2124,71 @@ export function createControlRouter(opts) {
1771
2124
  router.post("/api/internal/runtimes/:selector/emulator/gesture", internalRuntimeCall(runtimeGestureEmulator));
1772
2125
  router.post("/api/internal/runtimes/:selector/emulator/kill", internalRuntimeCall((ctx) => runtimeDeviceCommand(ctx, "emulator.kill")));
1773
2126
  router.post("/api/internal/runtimes/:selector/emulator/shutdown", internalRuntimeCall((ctx) => runtimeDeviceCommand(ctx, "emulator.shutdown")));
2127
+ const executeLocalBrowser = async (ctx, management) => {
2128
+ if (!runtimeLocalBrowser?.executeForSession) {
2129
+ notFound(ctx, "Page automation requires a Runtime upgrade");
2130
+ return;
2131
+ }
2132
+ if (!isLoopbackRequest(ctx)) {
2133
+ ctx.status = 403;
2134
+ ctx.body = { error: "loopback_only" };
2135
+ return;
2136
+ }
2137
+ let sessionId;
2138
+ if (management) {
2139
+ if (!isConfiguredDaemonManagement(daemonManagement)) {
2140
+ notFound(ctx, "Daemon management is unavailable");
2141
+ return;
2142
+ }
2143
+ if (!authorizeLoopbackManagementRequest(ctx, daemonManagement.managementToken))
2144
+ return;
2145
+ try {
2146
+ sessionId = parseRuntimeBrowserStateGetParams({ sessionId: ctx.params.sessionId }).sessionId;
2147
+ }
2148
+ catch {
2149
+ bad(ctx, "invalid Session id");
2150
+ return;
2151
+ }
2152
+ }
2153
+ else {
2154
+ try {
2155
+ const credential = parseRuntimeBrowserBootstrapCredential({
2156
+ sessionId: ctx.get(RUNTIME_BROWSER_SESSION_ID_HEADER), capability: ctx.get(RUNTIME_BROWSER_CAPABILITY_HEADER),
2157
+ });
2158
+ if (!await runtimeLocalBrowser.authorizeCredential(credential))
2159
+ throw new Error("unauthorized");
2160
+ sessionId = credential.sessionId;
2161
+ }
2162
+ catch {
2163
+ ctx.status = 401;
2164
+ ctx.body = { error: "invalid Runtime Browser Session capability" };
2165
+ return;
2166
+ }
2167
+ }
2168
+ if (!ctx.is("application/json")) {
2169
+ ctx.status = 415;
2170
+ ctx.body = { error: "unsupported_media_type" };
2171
+ return;
2172
+ }
2173
+ let command;
2174
+ try {
2175
+ command = parseRuntimeBrowserAutomationCommand(await readBoundedJson(ctx, 128 * 1024));
2176
+ }
2177
+ catch (error) {
2178
+ ctx.status = error instanceof RequestBodyTooLargeError ? 413 : 400;
2179
+ ctx.body = { error: "invalid_request" };
2180
+ return;
2181
+ }
2182
+ try {
2183
+ ctx.set("Cache-Control", "no-store");
2184
+ ctx.body = await runtimeLocalBrowser.executeForSession(sessionId, command);
2185
+ }
2186
+ catch (error) {
2187
+ runtimeLocalBrowserError(ctx, error);
2188
+ }
2189
+ };
2190
+ router.post(RUNTIME_BROWSER_EXECUTE_PATH, (ctx) => executeLocalBrowser(ctx, false));
2191
+ router.post(`${RUNTIME_BROWSER_MANAGEMENT_PATH_PREFIX}/:sessionId/execute`, (ctx) => executeLocalBrowser(ctx, true));
1774
2192
  router.get(RUNTIME_BROWSER_BOOTSTRAP_PATH, async (ctx) => {
1775
2193
  if (!runtimeLocalBrowser) {
1776
2194
  return notFound(ctx, "Runtime-local Browser automation is not configured");
@@ -1948,10 +2366,17 @@ export function createControlRouter(opts) {
1948
2366
  }
1949
2367
  if (!authorizeLoopbackManagementRequest(ctx, daemonManagement.managementToken))
1950
2368
  return;
1951
- const maintenanceLeaseToken = ctx.get(DAEMON_MAINTENANCE_LEASE_HEADER).trim() || undefined;
2369
+ if (ctx.get(DAEMON_MAINTENANCE_LEASE_HEADER).trim()) {
2370
+ ctx.set("Cache-Control", "no-store");
2371
+ ctx.status = 410;
2372
+ ctx.body = {
2373
+ error: "cross-process maintenance leases are retired; upgrade the caller",
2374
+ };
2375
+ return;
2376
+ }
1952
2377
  let result;
1953
2378
  try {
1954
- result = await daemonManagement.shutdownIfIdle(maintenanceLeaseToken);
2379
+ result = await daemonManagement.shutdownIfIdle();
1955
2380
  }
1956
2381
  catch (error) {
1957
2382
  ctx.set("Cache-Control", "no-store");
@@ -1966,15 +2391,16 @@ export function createControlRouter(opts) {
1966
2391
  ctx.body = result;
1967
2392
  });
1968
2393
  router.post(DAEMON_MAINTENANCE_LEASE_RELEASE_PATH, (ctx) => {
1969
- if (!isConfiguredDaemonManagement(daemonManagement)
1970
- || !daemonManagement.releaseMaintenanceLease) {
1971
- return notFound(ctx, "daemon maintenance lease management is not configured");
2394
+ if (!isConfiguredDaemonManagement(daemonManagement)) {
2395
+ return notFound(ctx, "daemon management is not configured");
1972
2396
  }
1973
2397
  if (!authorizeLoopbackManagementRequest(ctx, daemonManagement.managementToken))
1974
2398
  return;
1975
- const result = daemonManagement.releaseMaintenanceLease(ctx.get(DAEMON_MAINTENANCE_LEASE_HEADER).trim());
2399
+ // Compatibility for updaters released before Plugin-owned drain became
2400
+ // the sole upgrade fence. New daemons never acquire a Host lease.
2401
+ const result = { outcome: "not_active" };
1976
2402
  ctx.set("Cache-Control", "no-store");
1977
- ctx.status = result.outcome === "denied" ? 403 : 200;
2403
+ ctx.status = 200;
1978
2404
  ctx.body = result;
1979
2405
  });
1980
2406
  router.post(DAEMON_BROWSER_ARTIFACT_INSTALL_PATH, async (ctx) => {
@@ -3178,7 +3604,7 @@ export function createControlRouter(opts) {
3178
3604
  // ── sessions (channel-agnostic agent runs) ───────────────────────────────
3179
3605
  // Create a session bound to a preset agent (`agent`) or an inline spec
3180
3606
  // (`config`, the config-driven / remote-ready path), then drive it with
3181
- // messages over SSE. reference implementation-style: create carries no message.
3607
+ // messages over SSE. Creating the session does not submit a message.
3182
3608
  // One unified list: every session is a machine-session record. The registry
3183
3609
  // (console + every channel) supplies identity — `source` is a plain field, not
3184
3610
  // parsed from the id — and the canonical log supplies recency. A legacy session
@@ -3252,7 +3678,20 @@ export function createControlRouter(opts) {
3252
3678
  }
3253
3679
  catch (error) {
3254
3680
  ctx.status = 503;
3255
- ctx.body = { error: error instanceof Error ? error.message : String(error) };
3681
+ const runtimeFailure = error instanceof MachineSessionServiceFailure
3682
+ ? error.runtimeFailure
3683
+ : undefined;
3684
+ const message = runtimeFailure?.message
3685
+ ?? (error instanceof MachineSessionServiceFailure ? error.detail : undefined)
3686
+ ?? (error instanceof Error ? error.message : String(error));
3687
+ ctx.body = {
3688
+ error: message,
3689
+ code: runtimeFailure?.code
3690
+ ?? (error instanceof MachineSessionServiceFailure ? error.code : "runtime_error"),
3691
+ outcome: error instanceof MachineSessionServiceFailure && error.code === "outcome_unknown"
3692
+ ? "unknown"
3693
+ : "not_started",
3694
+ };
3256
3695
  }
3257
3696
  return;
3258
3697
  }
@@ -3271,26 +3710,31 @@ export function createControlRouter(opts) {
3271
3710
  execution: structuredClone(meta.execution),
3272
3711
  });
3273
3712
  if (!live) {
3713
+ const failure = runnerManager.lastLiveSessionFailure?.(id);
3274
3714
  ctx.status = 503;
3275
3715
  ctx.body = {
3276
- error: `live session unavailable (${meta.execution.provider})`,
3277
- ...(runnerManager.lastLiveSessionError?.(id)
3278
- ? { detail: runnerManager.lastLiveSessionError(id) }
3279
- : {}),
3716
+ error: failure?.message
3717
+ ?? runnerManager.lastLiveSessionError?.(id)
3718
+ ?? `live session unavailable (${meta.execution.provider})`,
3719
+ code: failure?.code ?? "live_unavailable",
3720
+ outcome: "not_started",
3280
3721
  };
3281
3722
  return;
3282
3723
  }
3283
- const outcome = await runnerManager.injectMessage(id, message);
3284
- if (outcome === "injected") {
3724
+ const result = await runnerManager.injectMessage(id, message);
3725
+ const outcome = result.outcome;
3726
+ if (outcome === "injected" || outcome === "steered") {
3285
3727
  ctx.body = { ok: true, injected: true };
3286
3728
  return;
3287
3729
  }
3288
3730
  ctx.status = 503;
3731
+ const failure = runnerManager.lastLiveSessionFailure?.(id);
3289
3732
  ctx.body = {
3290
- error: `live injection ${outcome}`,
3291
- ...(runnerManager.lastLiveSessionError?.(id)
3292
- ? { detail: runnerManager.lastLiveSessionError(id) }
3293
- : {}),
3733
+ error: failure?.message
3734
+ ?? runnerManager.lastLiveSessionError?.(id)
3735
+ ?? `live injection ${outcome}`,
3736
+ code: failure?.code ?? "live_inject_failed",
3737
+ outcome: outcome === "failed" ? "unknown" : "not_started",
3294
3738
  };
3295
3739
  });
3296
3740
  // Stop the session's active turn (the web Stop button). For a live native
@@ -3316,6 +3760,7 @@ export function createControlRouter(opts) {
3316
3760
  ctx.body = {
3317
3761
  sessionId: id,
3318
3762
  items: sessionLog ? await sessionLog.snapshot(id) : [],
3763
+ pendingInputs: [],
3319
3764
  runtime: sessionRuntimeIndex.snapshot(id),
3320
3765
  };
3321
3766
  });
@@ -3406,7 +3851,15 @@ export function createControlRouter(opts) {
3406
3851
  ctx.body = { error: "session_resource_cleanup_failed" };
3407
3852
  return;
3408
3853
  }
3409
- runnerManager?.stopRunner(id);
3854
+ if (runnerManager?.terminateLiveSession) {
3855
+ await runnerManager.terminateLiveSession(id).catch((error) => {
3856
+ console.warn(`[control-api] session=${id} live teardown failed during deletion; continuing best-effort: ${error instanceof Error ? error.message : String(error)}`);
3857
+ return false;
3858
+ });
3859
+ }
3860
+ else {
3861
+ runnerManager?.stopRunner(id);
3862
+ }
3410
3863
  sessionBus?.close(id);
3411
3864
  deps.removeSessionMeta(id);
3412
3865
  // Hard-delete the transcript too — the session list is meta ∪ log, so
@@ -3503,8 +3956,8 @@ function abortAsNull(signal) {
3503
3956
  });
3504
3957
  }
3505
3958
  /** Derive a one-line session title from the first user message: collapse
3506
- * whitespace, trim, and truncate to `limit` chars + an ellipsis (reference implementation's
3507
- * rule — no LLM call). */
3959
+ * whitespace, trim, and fit within `limit` characters, including an ellipsis
3960
+ * when truncated. No LLM call is made. */
3508
3961
  export function synthesizeSessionTitle(message, limit = 60) {
3509
3962
  const collapsed = message.replace(/\s+/g, " ").trim();
3510
3963
  if (collapsed.length <= limit)
@@ -3576,6 +4029,14 @@ function optionalRuntimeDevice(body) {
3576
4029
  return body.device === undefined ? {} : { device: body.device };
3577
4030
  }
3578
4031
  function remoteRuntimeRpcTimeoutMs(method, params) {
4032
+ // Native startup/delivery owns phase-specific deadlines and returns their
4033
+ // concrete failures. A BFF deadline here would race those phases and replace
4034
+ // the real error with an ambiguous generic RPC timeout. The setup queue also
4035
+ // awaits Terminal startup before acknowledging the request.
4036
+ if (method === "session.message.send" ||
4037
+ method === "session.message.enqueue" ||
4038
+ method === "session.terminal.start")
4039
+ return null;
3579
4040
  if (method === "session.emulator.attach")
3580
4041
  return REMOTE_RUNTIME_EMULATOR_ATTACH_TIMEOUT_MS;
3581
4042
  if (method === "session.emulator.type") {
@@ -3679,6 +4140,36 @@ function pluginInstallInvocationAbortScope(ctx, shutdownSignal) {
3679
4140
  function browserArtifactInvocationAbortScope(ctx, shutdownSignal) {
3680
4141
  return managementInvocationAbortScope(ctx, shutdownSignal, BROWSER_ARTIFACT_OPERATION_TIMEOUT_MS, "Browser artifact operation");
3681
4142
  }
4143
+ function downloadInvocationAbortScope(ctx, shutdownSignal) {
4144
+ const controller = new AbortController();
4145
+ const abort = (reason) => {
4146
+ if (!controller.signal.aborted)
4147
+ controller.abort(reason);
4148
+ };
4149
+ const onRequestAborted = () => abort(namedError("download request aborted", "AbortError"));
4150
+ const onResponseClose = () => {
4151
+ if (!ctx.res.writableEnded) {
4152
+ abort(namedError("download client disconnected", "AbortError"));
4153
+ }
4154
+ };
4155
+ const onShutdown = () => abort(shutdownSignal?.reason ?? namedError("daemon is shutting down", "AbortError"));
4156
+ ctx.req.once("aborted", onRequestAborted);
4157
+ ctx.res.once("close", onResponseClose);
4158
+ if (shutdownSignal?.aborted)
4159
+ onShutdown();
4160
+ else
4161
+ shutdownSignal?.addEventListener("abort", onShutdown, { once: true });
4162
+ if (ctx.req.aborted)
4163
+ onRequestAborted();
4164
+ return {
4165
+ signal: controller.signal,
4166
+ dispose() {
4167
+ ctx.req.removeListener("aborted", onRequestAborted);
4168
+ ctx.res.removeListener("close", onResponseClose);
4169
+ shutdownSignal?.removeEventListener("abort", onShutdown);
4170
+ },
4171
+ };
4172
+ }
3682
4173
  function managementInvocationAbortScope(ctx, shutdownSignal, timeoutMs, label) {
3683
4174
  const controller = new AbortController();
3684
4175
  const abort = (reason) => {
@@ -3899,8 +4390,14 @@ function runtimeTargetHostError(ctx, error, forcedOutcome) {
3899
4390
  const status = runtimeTargetHttpStatus(code);
3900
4391
  ctx.status = status;
3901
4392
  const outcome = forcedOutcome ?? runtimeTargetErrorOutcome(error);
4393
+ const applicationMessage = error instanceof Error && error.name === "DirectRuntimeRpcError"
4394
+ ? error.message.replace(/^Remote Runtime RPC failed: [^:]+: /, "")
4395
+ : undefined;
3902
4396
  ctx.body = {
3903
- error: status === 500 ? "internal_error" : code,
4397
+ error: applicationMessage ?? (status === 500 ? "internal_error" : code),
4398
+ ...(applicationMessage
4399
+ ? { code: status === 500 ? "internal_error" : code }
4400
+ : {}),
3904
4401
  ...(outcome === undefined ? {} : { outcome }),
3905
4402
  };
3906
4403
  }
@@ -3909,9 +4406,19 @@ function runtimeLocalBrowserError(ctx, error) {
3909
4406
  ? error.code
3910
4407
  : undefined;
3911
4408
  switch (code) {
4409
+ case "human_control_active":
4410
+ ctx.status = 409;
4411
+ ctx.body = { error: code, hint: "Release Browser Control before Agent actions." };
4412
+ return;
4413
+ case "command_timeout":
4414
+ ctx.status = 504;
4415
+ ctx.body = { error: "command_timeout", outcome: "unknown" };
4416
+ return;
3912
4417
  case "invalid_request":
3913
4418
  ctx.status = 400;
3914
- ctx.body = { error: "invalid_request" };
4419
+ ctx.body = { error: "invalid_request", ...(error instanceof Error && error.name === "PageAutomationError"
4420
+ ? { message: error.message.slice(0, 2048), hint: "Run rynx skills get browser for Browser resources; after opening a Browser, use rynx browser exec -- --help for page commands." }
4421
+ : {}) };
3915
4422
  return;
3916
4423
  case "not_found":
3917
4424
  ctx.status = 404;
@@ -3923,10 +4430,30 @@ function runtimeLocalBrowserError(ctx, error) {
3923
4430
  ctx.body = { error: "unavailable" };
3924
4431
  return;
3925
4432
  case "host_failure":
3926
- case "outcome_unknown":
3927
4433
  ctx.status = 502;
3928
4434
  ctx.body = { error: "operation_failed" };
3929
4435
  return;
4436
+ case "outcome_unknown":
4437
+ ctx.status = 502;
4438
+ ctx.body = { error: "outcome_unknown", outcome: "unknown", hint: "Do not replay this action. Run rynx browser exec -- snapshot -i to inspect its outcome." };
4439
+ return;
4440
+ case "driver_restarted":
4441
+ case "generation_mismatch":
4442
+ ctx.status = 409;
4443
+ ctx.body = { error: code, hint: "Run rynx browser exec -- snapshot -i for fresh Page references." };
4444
+ return;
4445
+ case "capacity":
4446
+ ctx.status = 429;
4447
+ ctx.body = { error: "capacity" };
4448
+ return;
4449
+ case "unsupported":
4450
+ ctx.status = 501;
4451
+ ctx.body = { error: "unsupported", hint: "Upgrade the Runtime and Desktop Host together." };
4452
+ return;
4453
+ case "command_failed":
4454
+ ctx.status = 422;
4455
+ ctx.body = { error: "command_failed", message: error instanceof Error ? error.message : "agent-browser command failed", hint: "Run rynx browser exec -- --help, or inspect a fresh snapshot before another action." };
4456
+ return;
3930
4457
  default:
3931
4458
  ctx.status = 500;
3932
4459
  ctx.body = { error: "internal_error" };
@@ -3988,6 +4515,83 @@ function publicRuntimeStreamError(error) {
3988
4515
  }
3989
4516
  class RequestBodyTooLargeError extends Error {
3990
4517
  }
4518
+ function isMediaType(value) {
4519
+ return value.length <= 255 && /^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(value);
4520
+ }
4521
+ async function forwardResourceUploadBody(ctx, uploadId, resumeOffset, expectedBytes, writeChunk) {
4522
+ let received = 0;
4523
+ let remoteOffset = resumeOffset;
4524
+ let carry = Buffer.alloc(0);
4525
+ for await (const raw of ctx.req) {
4526
+ const incoming = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
4527
+ if (received + incoming.byteLength > expectedBytes) {
4528
+ throw runtimeProtocolError("Resource upload exceeds Content-Length");
4529
+ }
4530
+ const skip = Math.min(incoming.byteLength, Math.max(0, resumeOffset - received));
4531
+ received += incoming.byteLength;
4532
+ let cursor = skip;
4533
+ while (cursor < incoming.byteLength) {
4534
+ const needed = SESSION_RESOURCE_TRANSFER_CHUNK_BYTES - carry.byteLength;
4535
+ const take = Math.min(needed, incoming.byteLength - cursor);
4536
+ carry = carry.byteLength === 0
4537
+ ? incoming.subarray(cursor, cursor + take)
4538
+ : Buffer.concat([carry, incoming.subarray(cursor, cursor + take)]);
4539
+ cursor += take;
4540
+ if (carry.byteLength < SESSION_RESOURCE_TRANSFER_CHUNK_BYTES)
4541
+ continue;
4542
+ const written = await writeChunk(uploadId, remoteOffset, carry.toString("base64"));
4543
+ if (written.offset !== remoteOffset + carry.byteLength) {
4544
+ throw runtimeProtocolError("Runtime Session resource upload did not advance");
4545
+ }
4546
+ remoteOffset = written.offset;
4547
+ carry = Buffer.alloc(0);
4548
+ }
4549
+ }
4550
+ if (received !== expectedBytes) {
4551
+ throw runtimeProtocolError("Resource upload ended before Content-Length");
4552
+ }
4553
+ if (carry.byteLength > 0) {
4554
+ const written = await writeChunk(uploadId, remoteOffset, carry.toString("base64"));
4555
+ if (written.offset !== remoteOffset + carry.byteLength) {
4556
+ throw runtimeProtocolError("Runtime Session resource upload did not advance");
4557
+ }
4558
+ remoteOffset = written.offset;
4559
+ }
4560
+ if (remoteOffset !== expectedBytes) {
4561
+ throw runtimeProtocolError("Runtime Session resource upload length changed");
4562
+ }
4563
+ }
4564
+ function parseSingleByteRange(header, byteLength) {
4565
+ if (!header)
4566
+ return undefined;
4567
+ const match = /^bytes=(\d*)-(\d*)$/.exec(header.trim());
4568
+ if (!match || byteLength <= 0)
4569
+ return "unsatisfiable";
4570
+ const [, startText, endText] = match;
4571
+ if (!startText && !endText)
4572
+ return "unsatisfiable";
4573
+ if (!startText) {
4574
+ const suffix = Number(endText);
4575
+ if (!Number.isSafeInteger(suffix) || suffix <= 0)
4576
+ return "unsatisfiable";
4577
+ return { start: Math.max(0, byteLength - suffix), end: byteLength - 1 };
4578
+ }
4579
+ const start = Number(startText);
4580
+ const requestedEnd = endText ? Number(endText) : byteLength - 1;
4581
+ if (!Number.isSafeInteger(start) ||
4582
+ !Number.isSafeInteger(requestedEnd) ||
4583
+ start < 0 ||
4584
+ requestedEnd < start ||
4585
+ start >= byteLength) {
4586
+ return "unsatisfiable";
4587
+ }
4588
+ return { start, end: Math.min(requestedEnd, byteLength - 1) };
4589
+ }
4590
+ function contentDisposition(filename) {
4591
+ if (!filename)
4592
+ return "inline";
4593
+ return `inline; filename*=UTF-8''${encodeURIComponent(filename)}`;
4594
+ }
3991
4595
  async function readBoundedBinary(ctx, maxBytes) {
3992
4596
  const declaredLength = Number(ctx.get("content-length"));
3993
4597
  if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {