@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.
- package/dist/control-api.d.ts +17 -4
- package/dist/control-api.js +722 -84
- package/dist/control-web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/control-web/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/control-web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/control-web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/control-web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/control-web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/control-web/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/control-web/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/control-web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/control-web/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/control-web/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/control-web/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/control-web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/control-web/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/control-web/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/control-web/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/control-web/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/control-web/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/control-web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/control-web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/control-web/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/control-web/assets/abap-CLvhMVsD.js +1 -0
- package/dist/control-web/assets/abnfDiagram-VRR7QNED-D_NL89dn.js +1 -0
- package/dist/control-web/assets/actionscript-3--17pq3dv.js +1 -0
- package/dist/control-web/assets/ada-C5qYipkI.js +1 -0
- package/dist/control-web/assets/andromeeda-vGVdxbeo.js +1 -0
- package/dist/control-web/assets/angular-html-DlZBZkSp.js +1 -0
- package/dist/control-web/assets/angular-ts-BVPGOT0K.js +1 -0
- package/dist/control-web/assets/apache-U0d_L8uA.js +1 -0
- package/dist/control-web/assets/apex-CGTLDQj6.js +1 -0
- package/dist/control-web/assets/apl-cDmXqmZ-.js +1 -0
- package/dist/control-web/assets/applescript-CCn79oCD.js +1 -0
- package/dist/control-web/assets/ara-4CJ0cIlV.js +1 -0
- package/dist/control-web/assets/arc-Pry-7G1_.js +1 -0
- package/dist/control-web/assets/architecture-TIHT7OUA-C9wU1KtW.js +1 -0
- package/dist/control-web/assets/architectureDiagram-ZJ3FMSHR-CV0rxVH6.js +36 -0
- package/dist/control-web/assets/array-BifhSqXX.js +1 -0
- package/dist/control-web/assets/asciidoc-DE70LPWp.js +1 -0
- package/dist/control-web/assets/asm-Cmm7eHzH.js +1 -0
- package/dist/control-web/assets/astro-B1Q6BwBx.js +1 -0
- package/dist/control-web/assets/aurora-x-CDeNXAV0.js +1 -0
- package/dist/control-web/assets/awk-BWXHIvNe.js +1 -0
- package/dist/control-web/assets/ayu-dark-DluEY0Gj.js +1 -0
- package/dist/control-web/assets/ayu-light-C3h-C4tm.js +1 -0
- package/dist/control-web/assets/ayu-mirage-Bqwy1Gya.js +1 -0
- package/dist/control-web/assets/ballerina-B7ZEbQpA.js +1 -0
- package/dist/control-web/assets/bat-Bo4NYOV-.js +1 -0
- package/dist/control-web/assets/beancount-D-usSTwE.js +1 -0
- package/dist/control-web/assets/berry-DKpUyyne.js +1 -0
- package/dist/control-web/assets/bibtex-Ci_nEsc7.js +1 -0
- package/dist/control-web/assets/bicep-CUHmPFLl.js +1 -0
- package/dist/control-web/assets/bird2-C2hNVINV.js +1 -0
- package/dist/control-web/assets/blade-Xpu-LGTm.js +1 -0
- package/dist/control-web/assets/blockDiagram-677ZJIJ3-Cc7nrkZh.js +132 -0
- package/dist/control-web/assets/bsl-BkkzgIyY.js +1 -0
- package/dist/control-web/assets/c-iCihek07.js +1 -0
- package/dist/control-web/assets/c3-CnJL0r0V.js +1 -0
- package/dist/control-web/assets/c4Diagram-LMCZKHZV-BPRU9m-F.js +10 -0
- package/dist/control-web/assets/cadence-CQ2zXKGN.js +1 -0
- package/dist/control-web/assets/cairo-DLTphjLi.js +1 -0
- package/dist/control-web/assets/catppuccin-frappe-3VR1Za6u.js +1 -0
- package/dist/control-web/assets/catppuccin-latte-DwIHMF0Q.js +1 -0
- package/dist/control-web/assets/catppuccin-macchiato-DYnBP6_5.js +1 -0
- package/dist/control-web/assets/catppuccin-mocha-DYhrFGRu.js +1 -0
- package/dist/control-web/assets/channel-BFm2_j8K.js +1 -0
- package/dist/control-web/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/control-web/assets/chunk-32BRIVSS-Bbq3O54m.js +1 -0
- package/dist/control-web/assets/chunk-52WLFC77-sD4al-Ob.js +10 -0
- package/dist/control-web/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/control-web/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
- package/dist/control-web/assets/chunk-C7G6YPKG-DqHaDS1O.js +1 -0
- package/dist/control-web/assets/chunk-EX3LRPZG-36GNQ5wp.js +231 -0
- package/dist/control-web/assets/chunk-HOUHSVGY-DeZ63q1j.js +1 -0
- package/dist/control-web/assets/chunk-ICXQ74PX-D2yF6lD_.js +2 -0
- package/dist/control-web/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/control-web/assets/chunk-KEIR6QF5-BICK3FdT.js +161 -0
- package/dist/control-web/assets/chunk-MOJQB5TN-CdaKyBz5.js +88 -0
- package/dist/control-web/assets/chunk-OGEWGWER-eOXC7kiH.js +1 -0
- package/dist/control-web/assets/chunk-PUDLZKDR-6w0LILL_.js +156 -0
- package/dist/control-web/assets/chunk-Q4XR5HBZ-CXgD5TGL.js +70 -0
- package/dist/control-web/assets/chunk-RYQCIY6F-BsoV8yK2.js +1 -0
- package/dist/control-web/assets/chunk-V7JOEXUC-BfoZ78b6.js +206 -0
- package/dist/control-web/assets/chunk-VR4S4FIN-BW2gCEMQ.js +1 -0
- package/dist/control-web/assets/chunk-WYO6CB5R-CHn7hulw.js +128 -0
- package/dist/control-web/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
- package/dist/control-web/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/control-web/assets/chunk-ZGVPDNZ5-CmFP0-fr.js +62 -0
- package/dist/control-web/assets/clarity-SemFz856.js +1 -0
- package/dist/control-web/assets/classDiagram-OUVF2IWQ-CUe_bETB.js +1 -0
- package/dist/control-web/assets/classDiagram-v2-EOCWNBFH-CUe_bETB.js +1 -0
- package/dist/control-web/assets/clojure-DqKBuwfJ.js +1 -0
- package/dist/control-web/assets/cmake-Bj61d0ZC.js +1 -0
- package/dist/control-web/assets/cobol-BsV-839J.js +1 -0
- package/dist/control-web/assets/codeowners-C8r90Shi.js +1 -0
- package/dist/control-web/assets/codeql-oeQT6MSM.js +1 -0
- package/dist/control-web/assets/coffee-CiiSLhB6.js +1 -0
- package/dist/control-web/assets/common-lisp-Cv5bFMCO.js +1 -0
- package/dist/control-web/assets/coq-BrsZFFmf.js +1 -0
- package/dist/control-web/assets/cose-bilkent-JH36ORCC-lJEhNiw_.js +1 -0
- package/dist/control-web/assets/cpp-DjoE5qBx.js +1 -0
- package/dist/control-web/assets/crystal-DDxHDkHz.js +1 -0
- package/dist/control-web/assets/csharp-Ct8U2NOr.js +1 -0
- package/dist/control-web/assets/css-LjpOdHib.js +1 -0
- package/dist/control-web/assets/csv-Dx-8-gkx.js +1 -0
- package/dist/control-web/assets/cue-CE9AQfxI.js +1 -0
- package/dist/control-web/assets/cynefin-VYW2F7L2-NaLr7Qlq.js +1 -0
- package/dist/control-web/assets/cynefinDiagram-TSTJHNR4-C90wpjAI.js +62 -0
- package/dist/control-web/assets/cypher-ClKdZ_lG.js +1 -0
- package/dist/control-web/assets/cytoscape.esm-B-NFISlW.js +321 -0
- package/dist/control-web/assets/d-qD-0Kul2.js +1 -0
- package/dist/control-web/assets/dagre-Buvkdvvj.js +1 -0
- package/dist/control-web/assets/dagre-VKFMJZFB-BxrPFWTb.js +4 -0
- package/dist/control-web/assets/dark-plus-Cs2F2srj.js +1 -0
- package/dist/control-web/assets/dart-DkHntEIa.js +1 -0
- package/dist/control-web/assets/dax-BkyTk9wS.js +1 -0
- package/dist/control-web/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/control-web/assets/desktop-Dlh5hvp9.js +1 -0
- package/dist/control-web/assets/diagram-FQU43EPY-VIQINsvz.js +3 -0
- package/dist/control-web/assets/diagram-G47NLZAW-DFeAfYXn.js +24 -0
- package/dist/control-web/assets/diagram-NH7WQ7WH-ATzdppDd.js +24 -0
- package/dist/control-web/assets/diagram-OA4YK3LP-DJZpWmbl.js +30 -0
- package/dist/control-web/assets/diagram-WEI45ONY-CqDHcW3g.js +41 -0
- package/dist/control-web/assets/diff-woXpYk--.js +1 -0
- package/dist/control-web/assets/dist-Dx9YWgcW.js +153 -0
- package/dist/control-web/assets/dist-v5Q1xZ2K.js +1 -0
- package/dist/control-web/assets/docker-IyjqRm3v.js +1 -0
- package/dist/control-web/assets/dotenv-_5a1GRtc.js +1 -0
- package/dist/control-web/assets/dracula-BHWKrbxM.js +1 -0
- package/dist/control-web/assets/dracula-soft-5eyTD99u.js +1 -0
- package/dist/control-web/assets/dream-maker-DW3nJb8Q.js +1 -0
- package/dist/control-web/assets/ebnfDiagram-CCIWWBDH-DnP6dHND.js +1 -0
- package/dist/control-web/assets/edge-8z7Jp9dO.js +1 -0
- package/dist/control-web/assets/elixir-CUV54ev5.js +1 -0
- package/dist/control-web/assets/elm-o4NJxfws.js +1 -0
- package/dist/control-web/assets/emacs-lisp-C9PiwqqW.js +1 -0
- package/dist/control-web/assets/erDiagram-Q63AITRT-Bo8bFqrZ.js +85 -0
- package/dist/control-web/assets/erb-CIsHcwm1.js +1 -0
- package/dist/control-web/assets/erlang-Cphh6RMH.js +1 -0
- package/dist/control-web/assets/eventmodeling-45OFAUF4-DTN8wqsu.js +1 -0
- package/dist/control-web/assets/everforest-dark-sB-x3p7T.js +1 -0
- package/dist/control-web/assets/everforest-light-Df2xbC6M.js +1 -0
- package/dist/control-web/assets/fennel-DQxkIbk2.js +1 -0
- package/dist/control-web/assets/fish-BJitypiv.js +1 -0
- package/dist/control-web/assets/flowDiagram-23GEKE2U-BwjqRyvd.js +1 -0
- package/dist/control-web/assets/fluent-C03EYrpw.js +1 -0
- package/dist/control-web/assets/fortran-fixed-form-DEKoE2YW.js +1 -0
- package/dist/control-web/assets/fortran-free-form-CYNrtFtB.js +1 -0
- package/dist/control-web/assets/fsharp-D13ZGOAj.js +1 -0
- package/dist/control-web/assets/ganttDiagram-NO4QXBWP-kxQaBTzd.js +292 -0
- package/dist/control-web/assets/gdresource-C0sCabJj.js +1 -0
- package/dist/control-web/assets/gdscript-Cp2uCuqX.js +1 -0
- package/dist/control-web/assets/gdshader-CBce3t8t.js +1 -0
- package/dist/control-web/assets/genie-CV2tkWYe.js +1 -0
- package/dist/control-web/assets/gherkin-DExj1W_8.js +1 -0
- package/dist/control-web/assets/git-commit-BSykSTBG.js +1 -0
- package/dist/control-web/assets/git-rebase-BDPpS8w6.js +1 -0
- package/dist/control-web/assets/gitGraph-TEB2WS4Q-a646NnuJ.js +1 -0
- package/dist/control-web/assets/gitGraphDiagram-IHSO6WYX-BBe0q0At.js +106 -0
- package/dist/control-web/assets/github-dark-C-LZuMrd.js +1 -0
- package/dist/control-web/assets/github-dark-default-DXG-b-1a.js +1 -0
- package/dist/control-web/assets/github-dark-dimmed-Bx1FflLF.js +1 -0
- package/dist/control-web/assets/github-dark-high-contrast-B_tTalzw.js +1 -0
- package/dist/control-web/assets/github-light-EUqPIrTm.js +1 -0
- package/dist/control-web/assets/github-light-default-BXViO-2h.js +1 -0
- package/dist/control-web/assets/github-light-high-contrast-B68TUdTA.js +1 -0
- package/dist/control-web/assets/gleam-CSRkHgEL.js +1 -0
- package/dist/control-web/assets/glimmer-js-OEO36pDk.js +1 -0
- package/dist/control-web/assets/glimmer-ts-BnAPyISE.js +1 -0
- package/dist/control-web/assets/glsl-D5MA2a_X.js +1 -0
- package/dist/control-web/assets/gn-ilITqXS6.js +1 -0
- package/dist/control-web/assets/gnuplot-7GGW24-e.js +1 -0
- package/dist/control-web/assets/go-BJwz_mda.js +1 -0
- package/dist/control-web/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/control-web/assets/graphql-Ctjuxyvl.js +1 -0
- package/dist/control-web/assets/groovy-CacY0gHj.js +1 -0
- package/dist/control-web/assets/gruvbox-dark-hard-C820rvS2.js +1 -0
- package/dist/control-web/assets/gruvbox-dark-medium-BPjhmG05.js +1 -0
- package/dist/control-web/assets/gruvbox-dark-soft-MrdJrrXF.js +1 -0
- package/dist/control-web/assets/gruvbox-light-hard-BC_s9l72.js +1 -0
- package/dist/control-web/assets/gruvbox-light-medium-BAWPOn9u.js +1 -0
- package/dist/control-web/assets/gruvbox-light-soft-BSMLrYjP.js +1 -0
- package/dist/control-web/assets/hack-D_mkkoLd.js +1 -0
- package/dist/control-web/assets/haml-mpgecWZ6.js +1 -0
- package/dist/control-web/assets/handlebars-CAx_777f.js +1 -0
- package/dist/control-web/assets/haskell-D8IpX4py.js +1 -0
- package/dist/control-web/assets/haxe-OTjmBuCE.js +1 -0
- package/dist/control-web/assets/hcl-Dh228itO.js +1 -0
- package/dist/control-web/assets/highlighted-body-OFNGDK62-DVCHy9oI.js +1 -0
- package/dist/control-web/assets/hjson-CxZEssPk.js +1 -0
- package/dist/control-web/assets/hlsl-Cvrh5tZx.js +1 -0
- package/dist/control-web/assets/horizon-CE9ld1lL.js +1 -0
- package/dist/control-web/assets/horizon-bright-Br1oVSNq.js +1 -0
- package/dist/control-web/assets/houston-CsvMBhTu.js +1 -0
- package/dist/control-web/assets/html-B2lrdnWr.js +1 -0
- package/dist/control-web/assets/html-derivative-CDfZYcul.js +1 -0
- package/dist/control-web/assets/http-kmH8AyfE.js +1 -0
- package/dist/control-web/assets/hurl-DCZHXKU4.js +1 -0
- package/dist/control-web/assets/hxml-B0Qn7Nwc.js +1 -0
- package/dist/control-web/assets/hy-CZbG8q4J.js +1 -0
- package/dist/control-web/assets/imba-DsUTQ-LC.js +1 -0
- package/dist/control-web/assets/index-D7URT6K_.js +140 -0
- package/dist/control-web/assets/index-uEpvRMX9.css +1 -0
- package/dist/control-web/assets/info-DKCQHKI2-Cp_JrY-b.js +1 -0
- package/dist/control-web/assets/infoDiagram-FWYZ7A6U-CAm-h4F_.js +2 -0
- package/dist/control-web/assets/ini-B5eOa1yu.js +1 -0
- package/dist/control-web/assets/init-C-OQMol4.js +1 -0
- package/dist/control-web/assets/ishikawaDiagram-FXEZZL3T-O17pqcWr.js +70 -0
- package/dist/control-web/assets/java-DdHNQ9hk.js +1 -0
- package/dist/control-web/assets/javascript-obGGvMPs.js +1 -0
- package/dist/control-web/assets/jinja-BMiPVedm.js +1 -0
- package/dist/control-web/assets/jison-CBjhYtSs.js +1 -0
- package/dist/control-web/assets/journeyDiagram-5HDEW3XC-DQ-JuSoR.js +139 -0
- package/dist/control-web/assets/json-DAgxKhMr.js +1 -0
- package/dist/control-web/assets/json5-BR5RXkoi.js +1 -0
- package/dist/control-web/assets/jsonc-CYpm1nAK.js +1 -0
- package/dist/control-web/assets/jsonl-CmCQp5Yx.js +1 -0
- package/dist/control-web/assets/jsonnet-CJTPZ8u_.js +1 -0
- package/dist/control-web/assets/jssm-DXw9l8Rf.js +1 -0
- package/dist/control-web/assets/jsx-gTgmArGx.js +1 -0
- package/dist/control-web/assets/julia-CjHxn3vf.js +1 -0
- package/dist/control-web/assets/just-DMArCiVH.js +1 -0
- package/dist/control-web/assets/kanagawa-dragon-CXtmUGW6.js +1 -0
- package/dist/control-web/assets/kanagawa-lotus-BN08jTvb.js +1 -0
- package/dist/control-web/assets/kanagawa-wave-CTweb8Dz.js +1 -0
- package/dist/control-web/assets/kanban-definition-HUTT4EX6-Cgv3kPbm.js +89 -0
- package/dist/control-web/assets/katex-CyHG4N6b.js +1 -0
- package/dist/control-web/assets/kdl-CsD5j6eV.js +1 -0
- package/dist/control-web/assets/kotlin-DhhofPvG.js +1 -0
- package/dist/control-web/assets/kusto-BUv0MjJC.js +1 -0
- package/dist/control-web/assets/laserwave-C_8bwKvT.js +1 -0
- package/dist/control-web/assets/latex-D9bvcAJr.js +1 -0
- package/dist/control-web/assets/lean-CewbzKMR.js +1 -0
- package/dist/control-web/assets/less-DVTAwKKz.js +1 -0
- package/dist/control-web/assets/lib-BZ_F5vVH.js +1 -0
- package/dist/control-web/assets/light-plus-DVQuIRkW.js +1 -0
- package/dist/control-web/assets/line-DUsXzGJZ.js +1 -0
- package/dist/control-web/assets/linear-DmucvK78.js +1 -0
- package/dist/control-web/assets/liquid-CCX5qouA.js +1 -0
- package/dist/control-web/assets/llvm-Cm23YOpf.js +1 -0
- package/dist/control-web/assets/log-BNLmms1o.js +1 -0
- package/dist/control-web/assets/logo-Cluzi2Zq.js +1 -0
- package/dist/control-web/assets/lua-FONpmTUP.js +1 -0
- package/dist/control-web/assets/luau-CNKltnaQ.js +1 -0
- package/dist/control-web/assets/make-Dixweg8N.js +1 -0
- package/dist/control-web/assets/map-BaFkSB1l.js +1 -0
- package/dist/control-web/assets/markdown-BYOwaDjH.js +1 -0
- package/dist/control-web/assets/markdown-streamdown-4N4AcNp5.js +433 -0
- package/dist/control-web/assets/markdown-streamdown-DEcVZfaU.css +1 -0
- package/dist/control-web/assets/marko-oPGh3KfH.js +1 -0
- package/dist/control-web/assets/material-theme-Bm3Qr25_.js +1 -0
- package/dist/control-web/assets/material-theme-darker-2IIEA8gg.js +1 -0
- package/dist/control-web/assets/material-theme-lighter-uhdI0v04.js +1 -0
- package/dist/control-web/assets/material-theme-ocean-CHQ94UKr.js +1 -0
- package/dist/control-web/assets/material-theme-palenight-B5W6OYN7.js +1 -0
- package/dist/control-web/assets/matlab-D7qyCx1q.js +1 -0
- package/dist/control-web/assets/mdc-B_uQHOlt.js +1 -0
- package/dist/control-web/assets/mdx-DQZ5AkYe.js +1 -0
- package/dist/control-web/assets/mermaid-Bk4SNUv9.js +1 -0
- package/dist/control-web/assets/mermaid-GHXKKRXX-BElZGKGd.js +1 -0
- package/dist/control-web/assets/mermaid-parser.core-VMln12Kd.js +7 -0
- package/dist/control-web/assets/min-dark-BSWPekZh.js +1 -0
- package/dist/control-web/assets/min-light-DDpmG2fV.js +1 -0
- package/dist/control-web/assets/mindmap-definition-LN4V7U3C-Bn0lH-UM.js +96 -0
- package/dist/control-web/assets/mipsasm-BMqwQI7S.js +1 -0
- package/dist/control-web/assets/mojo-BgCJLMeH.js +1 -0
- package/dist/control-web/assets/monokai-CdkpiU2Y.js +1 -0
- package/dist/control-web/assets/moonbit-CaWjb8XO.js +1 -0
- package/dist/control-web/assets/move-B1IS1UjX.js +1 -0
- package/dist/control-web/assets/narrat-_X_XdTYD.js +1 -0
- package/dist/control-web/assets/nextflow-Bbiyy34d.js +1 -0
- package/dist/control-web/assets/nextflow-groovy-Dc_ddanL.js +1 -0
- package/dist/control-web/assets/nginx-BTMw9COX.js +1 -0
- package/dist/control-web/assets/night-owl-DhmEMT88.js +1 -0
- package/dist/control-web/assets/night-owl-light-eJ-hLW7d.js +1 -0
- package/dist/control-web/assets/nim-8PQFL6ZB.js +1 -0
- package/dist/control-web/assets/nix-IvuFDN5E.js +1 -0
- package/dist/control-web/assets/nord-Cb4Vim4T.js +1 -0
- package/dist/control-web/assets/nushell-DcLAeLz5.js +1 -0
- package/dist/control-web/assets/objective-c-D1A_Heim.js +1 -0
- package/dist/control-web/assets/objective-cpp-BsSzOQcm.js +1 -0
- package/dist/control-web/assets/ocaml-O90oeIOV.js +1 -0
- package/dist/control-web/assets/odin-B1RWQWA5.js +1 -0
- package/dist/control-web/assets/one-dark-pro-CLwyXe_n.js +1 -0
- package/dist/control-web/assets/one-light-D7Lr4KcI.js +1 -0
- package/dist/control-web/assets/openscad-BUDT5pXO.js +1 -0
- package/dist/control-web/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/control-web/assets/packet-7NZHBO7P-Zw8iJ8lo.js +1 -0
- package/dist/control-web/assets/pascal-4ZHwLPI5.js +1 -0
- package/dist/control-web/assets/path-fybaL0A-.js +1 -0
- package/dist/control-web/assets/pegDiagram-2B236MQR-CtF7vVs_.js +1 -0
- package/dist/control-web/assets/perl-Vf0i0hAx.js +1 -0
- package/dist/control-web/assets/php-am1OsKhm.js +1 -0
- package/dist/control-web/assets/pie-RZYD4A2V-su_3QGU2.js +1 -0
- package/dist/control-web/assets/pieDiagram-ENE6RG2P-BkMUBLE1.js +39 -0
- package/dist/control-web/assets/pkl-ot-7Btpt.js +1 -0
- package/dist/control-web/assets/plastic-DQwYfKfQ.js +1 -0
- package/dist/control-web/assets/plsql-DGHpHOYJ.js +1 -0
- package/dist/control-web/assets/po-BiJDBrnU.js +1 -0
- package/dist/control-web/assets/poimandres-DRFjx7u4.js +1 -0
- package/dist/control-web/assets/polar-C7UOKdEL.js +1 -0
- package/dist/control-web/assets/postcss-BXeXVLqQ.js +1 -0
- package/dist/control-web/assets/powerquery-DNMTfnFr.js +1 -0
- package/dist/control-web/assets/powershell-DshXNtvi.js +1 -0
- package/dist/control-web/assets/prisma-BsRQq5mF.js +1 -0
- package/dist/control-web/assets/prolog-iXnhIJG7.js +1 -0
- package/dist/control-web/assets/proto-DB4EqR-F.js +1 -0
- package/dist/control-web/assets/pug-DO6yvBr3.js +1 -0
- package/dist/control-web/assets/puppet-CDv2pdJW.js +1 -0
- package/dist/control-web/assets/purescript-9MfHhQsQ.js +1 -0
- package/dist/control-web/assets/python-gzcpVVnB.js +1 -0
- package/dist/control-web/assets/qml-_a-QhfPD.js +1 -0
- package/dist/control-web/assets/qmldir-DCQb3MpD.js +1 -0
- package/dist/control-web/assets/qss-Fe1Jh2GI.js +1 -0
- package/dist/control-web/assets/quadrantDiagram-ABIIQ3AL-ba-VaqMe.js +7 -0
- package/dist/control-web/assets/r-D6UWEOL2.js +1 -0
- package/dist/control-web/assets/racket-DcIDlBhZ.js +1 -0
- package/dist/control-web/assets/radar-I7S5WNFK-Dat0rqem.js +1 -0
- package/dist/control-web/assets/railroad-3IZDKUUU-Dh2-s8r8.js +1 -0
- package/dist/control-web/assets/railroad-abnf-AHOZXSZD-CNUwq0JR.js +1 -0
- package/dist/control-web/assets/railroad-ebnf-EBAXGLYW-RHr0duea.js +1 -0
- package/dist/control-web/assets/railroad-peg-LSFZ7HO6-CVBWS2eU.js +1 -0
- package/dist/control-web/assets/railroadDiagram-RFXS5EU6-BiJX3SY-.js +1 -0
- package/dist/control-web/assets/raku-B3gFvitq.js +1 -0
- package/dist/control-web/assets/razor-CMVBVp3T.js +1 -0
- package/dist/control-web/assets/red-CJ3rzSJv.js +1 -0
- package/dist/control-web/assets/reg-CRGYupPL.js +1 -0
- package/dist/control-web/assets/regexp-DR20uMnK.js +1 -0
- package/dist/control-web/assets/rel-BtDbiS_P.js +1 -0
- package/dist/control-web/assets/requirementDiagram-TGXJPOKE-CFfakCzs.js +84 -0
- package/dist/control-web/assets/riscv-Ckw8ddFX.js +1 -0
- package/dist/control-web/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/dist/control-web/assets/ron-VUp2lXgN.js +1 -0
- package/dist/control-web/assets/rose-pine-BthvhNj6.js +1 -0
- package/dist/control-web/assets/rose-pine-dawn-Dg85fqjY.js +1 -0
- package/dist/control-web/assets/rose-pine-moon-hon4tzzS.js +1 -0
- package/dist/control-web/assets/rosmsg-CAekHB0j.js +1 -0
- package/dist/control-web/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dist/control-web/assets/rst-CgIrbW_q.js +1 -0
- package/dist/control-web/assets/ruby-Dp6Zud9H.js +1 -0
- package/dist/control-web/assets/rust-Cfkwpbl8.js +1 -0
- package/dist/control-web/assets/sankeyDiagram-HTMAVEWB-jgDi0God.js +40 -0
- package/dist/control-web/assets/sas-B6p8-ynO.js +1 -0
- package/dist/control-web/assets/sass-DXrisJhu.js +1 -0
- package/dist/control-web/assets/scala-DKOlJaKm.js +1 -0
- package/dist/control-web/assets/scheme-DQCgrYNe.js +1 -0
- package/dist/control-web/assets/scss-DcoSS-ti.js +1 -0
- package/dist/control-web/assets/sdbl-bTVj8UrX.js +1 -0
- package/dist/control-web/assets/sequenceDiagram-DBY2YBRQ-DBfyyb0N.js +162 -0
- package/dist/control-web/assets/shaderlab-TOUzSsQk.js +1 -0
- package/dist/control-web/assets/shellscript-Da78Ox-3.js +1 -0
- package/dist/control-web/assets/shellsession-CVsQGYfZ.js +1 -0
- package/dist/control-web/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
- package/dist/control-web/assets/slack-dark-DnToyrRv.js +1 -0
- package/dist/control-web/assets/slack-ochin-B2OO5cIa.js +1 -0
- package/dist/control-web/assets/smalltalk-B16xEiuN.js +1 -0
- package/dist/control-web/assets/snazzy-light-4G7pJPwS.js +1 -0
- package/dist/control-web/assets/solarized-dark-DV17i1UV.js +1 -0
- package/dist/control-web/assets/solarized-light-DSh2HLQt.js +1 -0
- package/dist/control-web/assets/solidity-CKzVLygQ.js +1 -0
- package/dist/control-web/assets/soy-B5n_eHSp.js +1 -0
- package/dist/control-web/assets/sparql-D_iOobhT.js +1 -0
- package/dist/control-web/assets/splunk-BC2Px7Mm.js +1 -0
- package/dist/control-web/assets/sql-ClgswhA6.js +1 -0
- package/dist/control-web/assets/src-B6xuSHsQ.js +1 -0
- package/dist/control-web/assets/ssh-config-BgfXC-Er.js +1 -0
- package/dist/control-web/assets/stata-RoaAgbqU.js +1 -0
- package/dist/control-web/assets/stateDiagram-2N3HPSRC-Dwb_ncVi.js +1 -0
- package/dist/control-web/assets/stateDiagram-v2-6OUMAXLB-DI0opaA1.js +1 -0
- package/dist/control-web/assets/stylus-B6D30XZt.js +1 -0
- package/dist/control-web/assets/surrealql-DIn4NJsS.js +1 -0
- package/dist/control-web/assets/svelte-CIt8Fl9I.js +1 -0
- package/dist/control-web/assets/swift-DonLKvLd.js +1 -0
- package/dist/control-web/assets/swimlanes-5IMT3BWC-DW0LuiIV.js +2 -0
- package/dist/control-web/assets/swimlanesDiagram-G3AALYLV-DDTVjcOR.js +8 -0
- package/dist/control-web/assets/synthwave-84-nFMaYfgc.js +1 -0
- package/dist/control-web/assets/system-verilog-DJ5XKQeo.js +1 -0
- package/dist/control-web/assets/systemd-BxMlprV5.js +1 -0
- package/dist/control-web/assets/talonscript-CohzipZa.js +1 -0
- package/dist/control-web/assets/tasl-DMoTqEGO.js +1 -0
- package/dist/control-web/assets/tcl-CZd0xW_V.js +1 -0
- package/dist/control-web/assets/templ-BREsJpNc.js +1 -0
- package/dist/control-web/assets/terraform-DswuEJGm.js +1 -0
- package/dist/control-web/assets/tex-0w6-Dtgt.js +1 -0
- package/dist/control-web/assets/timeline-definition-FHXFAJF6-DeX4B_B8.js +120 -0
- package/dist/control-web/assets/tokyo-night-oM2G3aXe.js +1 -0
- package/dist/control-web/assets/toml-CcmNWLt0.js +1 -0
- package/dist/control-web/assets/treeView-QDETBFTQ-D1UXtICj.js +1 -0
- package/dist/control-web/assets/treemap-6X3UGDF4-CrppzjZH.js +1 -0
- package/dist/control-web/assets/ts-tags-q3pptdMi.js +1 -0
- package/dist/control-web/assets/tsv-sltzmVWM.js +1 -0
- package/dist/control-web/assets/tsx-CUOciP0b.js +1 -0
- package/dist/control-web/assets/turtle-ByJddavk.js +1 -0
- package/dist/control-web/assets/twig-LIeLXgf5.js +1 -0
- package/dist/control-web/assets/typescript-BydbNFcO.js +1 -0
- package/dist/control-web/assets/typespec-B88KGewJ.js +1 -0
- package/dist/control-web/assets/typst-DI99ib-x.js +1 -0
- package/dist/control-web/assets/v-DETTlOr0.js +1 -0
- package/dist/control-web/assets/vala-zf12oZj6.js +1 -0
- package/dist/control-web/assets/vb-Djn5o6TS.js +1 -0
- package/dist/control-web/assets/vennDiagram-L72KCM5P-BYpf-7VR.js +34 -0
- package/dist/control-web/assets/verilog-CiiDBU1e.js +1 -0
- package/dist/control-web/assets/vesper-D5bVUKB1.js +1 -0
- package/dist/control-web/assets/vhdl-BroJfC0k.js +1 -0
- package/dist/control-web/assets/viml-DvXPmvsu.js +1 -0
- package/dist/control-web/assets/vitesse-black-fwtXNY1n.js +1 -0
- package/dist/control-web/assets/vitesse-dark-BZCL-v6S.js +1 -0
- package/dist/control-web/assets/vitesse-light-VbXTXTou.js +1 -0
- package/dist/control-web/assets/vue-DVSfBueU.js +1 -0
- package/dist/control-web/assets/vue-html-DkKkQnZL.js +1 -0
- package/dist/control-web/assets/vue-vine-pWqEcBkW.js +1 -0
- package/dist/control-web/assets/vyper-CgoNMtux.js +1 -0
- package/dist/control-web/assets/wardley-OPB4EBWU-B9rA0UsV.js +1 -0
- package/dist/control-web/assets/wardleyDiagram-EHGQE667-BdvAUa5F.js +78 -0
- package/dist/control-web/assets/wasm-BnjxR4X6.js +1 -0
- package/dist/control-web/assets/wasm-ByWQv1Qj.js +1 -0
- package/dist/control-web/assets/wenyan-C8pVoKbM.js +1 -0
- package/dist/control-web/assets/wgsl-BsKzXJz4.js +1 -0
- package/dist/control-web/assets/wikitext-ClFFjSW2.js +1 -0
- package/dist/control-web/assets/wit-DdvCle-K.js +1 -0
- package/dist/control-web/assets/wolfram-DLL8P-h_.js +1 -0
- package/dist/control-web/assets/xml-BlnrEAEy.js +1 -0
- package/dist/control-web/assets/xsl-BOPS8gLt.js +1 -0
- package/dist/control-web/assets/xychartDiagram-FW5EYKEG-BaEV3pGm.js +7 -0
- package/dist/control-web/assets/yaml-Du_6cdrH.js +1 -0
- package/dist/control-web/assets/zenscript-BnlCZFoB.js +1 -0
- package/dist/control-web/assets/zig-CMLA9XwU.js +1 -0
- package/dist/control-web/index.html +3 -2
- package/dist/control-web-dist.d.ts +1 -1
- package/dist/control-web-dist.js +4 -2
- package/dist/desktop-browser-host.d.ts +3 -1
- package/dist/desktop-browser-host.js +39 -4
- package/dist/direct-runtime-server.js +187 -153
- package/dist/machine-session-service.d.ts +105 -15
- package/dist/machine-session-service.js +781 -87
- package/dist/remote-runtime-dispatcher.d.ts +2 -2
- package/dist/remote-runtime-dispatcher.js +42 -2
- package/dist/remote-runtime-session-projection.d.ts +1 -0
- package/dist/remote-runtime-session-projection.js +12 -0
- package/dist/server.d.ts +64 -11
- package/dist/server.js +422 -55
- package/dist/session-browser-service.d.ts +24 -4
- package/dist/session-browser-service.js +127 -1
- package/dist/session-pending-inputs.d.ts +42 -0
- package/dist/session-pending-inputs.js +87 -0
- package/dist/session-portal.d.ts +54 -0
- package/dist/session-portal.js +997 -0
- package/dist/session-runtime-index.d.ts +3 -6
- package/dist/session-runtime-index.js +96 -38
- package/dist/session-terminal-host.d.ts +22 -2
- package/dist/session-terminal-host.js +66 -83
- package/dist/terminal-ws.d.ts +4 -1
- package/dist/terminal-ws.js +93 -27
- package/package.json +7 -7
- package/dist/control-web/assets/highlighted-body-OFNGDK62-DWWsUtHF.js +0 -1
- package/dist/control-web/assets/index-BnX7NWJX.js +0 -689
- package/dist/control-web/assets/index-CUoWRX2i.css +0 -32
- package/dist/control-web/assets/mermaid-GHXKKRXX-C1fxAgiw.js +0 -131
package/dist/control-api.js
CHANGED
|
@@ -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
|
-
!
|
|
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
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
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
|
-
|
|
903
|
+
const byteLength = Number(contentLengthHeader);
|
|
904
|
+
if (!Number.isSafeInteger(byteLength) || byteLength <= 0) {
|
|
873
905
|
ctx.status = 400;
|
|
874
|
-
ctx.body = { error: "
|
|
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
|
|
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
|
|
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
|
-
|
|
922
|
-
|
|
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
|
-
|
|
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 >
|
|
977
|
+
if (begun.offset < 0 || begun.offset > byteLength) {
|
|
934
978
|
throw runtimeProtocolError("Runtime Session resource upload offset is invalid");
|
|
935
979
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
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 !==
|
|
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
|
|
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
|
|
1016
|
-
|
|
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
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
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("
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
3165
|
-
|
|
3166
|
-
|
|
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
|
|
3172
|
-
|
|
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:
|
|
3179
|
-
|
|
3180
|
-
|
|
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?.
|
|
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
|
-
|
|
3406
|
-
|
|
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) {
|