@cc-monitoring/proxy-core 0.3.1 → 0.4.0
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/cli/__tests__/commands.test.js +1 -1
- package/dist/cli/commands/exec.js +31 -42
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.B9A39uFv.js → app.DtYNT5zS.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.C4sjikMO.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DdhC696L.js → VPLocalSearchBox.DpXF9ZAI.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CfB2tOFi.js → theme.TS_gUyc7.js} +2 -2
- package/dist/docs/assets/{proxy-cli_data-hooks.md.w9Oe1OD3.js → proxy-cli_data-hooks.md.Bz8CVbxO.js} +1 -1
- package/dist/docs/assets/{proxy-core_ui-routes.md.Dyqkeoiv.js → proxy-core_ui-routes.md.B21t1p7R.js} +1 -1
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/index.html +3 -3
- package/dist/docs/overview.html +3 -3
- package/dist/docs/packages-utils.html +3 -3
- package/dist/docs/proxy-admin/env-and-build.html +3 -3
- package/dist/docs/proxy-admin/index.html +3 -3
- package/dist/docs/proxy-admin/layout-and-menu.html +3 -3
- package/dist/docs/proxy-admin/pages.html +3 -3
- package/dist/docs/proxy-admin/routing-and-auth.html +3 -3
- package/dist/docs/proxy-admin/services-and-mock.html +3 -3
- package/dist/docs/proxy-cli/api-layer.html +3 -3
- package/dist/docs/proxy-cli/app-shell.html +3 -3
- package/dist/docs/proxy-cli/components-common.html +3 -3
- package/dist/docs/proxy-cli/components-config.html +3 -3
- package/dist/docs/proxy-cli/components-requests.html +3 -3
- package/dist/docs/proxy-cli/components-stats.html +3 -3
- package/dist/docs/proxy-cli/components-status.html +3 -3
- package/dist/docs/proxy-cli/data-hooks.html +5 -5
- package/dist/docs/proxy-cli/index.html +3 -3
- package/dist/docs/proxy-cli/utils-and-i18n.html +3 -3
- package/dist/docs/proxy-core/chat-api.html +3 -3
- package/dist/docs/proxy-core/cli.html +3 -3
- package/dist/docs/proxy-core/config.html +3 -3
- package/dist/docs/proxy-core/data-layer.html +3 -3
- package/dist/docs/proxy-core/entry.html +3 -3
- package/dist/docs/proxy-core/index.html +3 -3
- package/dist/docs/proxy-core/pm2.html +3 -3
- package/dist/docs/proxy-core/providers.html +3 -3
- package/dist/docs/proxy-core/proxy.html +3 -3
- package/dist/docs/proxy-core/stats.html +3 -3
- package/dist/docs/proxy-core/tool.html +3 -3
- package/dist/docs/proxy-core/ui-routes.html +5 -5
- package/dist/docs/proxy-core/utilities.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/request-flow.html +3 -3
- package/dist/logger/index.d.ts +0 -3
- package/dist/logger/index.js +0 -1
- package/dist/mcp-server/tools.js +8 -9
- package/dist/server/__tests__/providers-route.test.js +1 -0
- package/dist/server/auth.d.ts +0 -1
- package/dist/server/auth.js +1 -1
- package/dist/server/chat-route.js +48 -162
- package/dist/server/data-push.d.ts +0 -1
- package/dist/server/data-push.js +0 -7
- package/dist/server/proxy.js +128 -224
- package/dist/server/ui-route.js +76 -59
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.js +1 -1
- package/dist/tools/registry.d.ts +0 -4
- package/dist/tools/registry.js +0 -8
- package/dist/types/config.d.ts +0 -13
- package/dist/types/pm2.d.ts +1 -2
- package/dist/ui/assets/{1c-DAu68mP4.js → 1c-CCx-FOtz.js} +1 -1
- package/dist/ui/assets/{abnf-Cu8RHCHK.js → abnf-Bwbi42Z8.js} +1 -1
- package/dist/ui/assets/{abnfDiagram-VRR7QNED-BUBToPXF.js → abnfDiagram-VRR7QNED-Dm1-8q0E.js} +1 -1
- package/dist/ui/assets/{accesslog-BG-34XOy.js → accesslog-DCytz_-m.js} +1 -1
- package/dist/ui/assets/{actionscript-iw0HHMGM.js → actionscript-3udf15oh.js} +1 -1
- package/dist/ui/assets/{ada-qRqj6VGQ.js → ada-M5Xa74xG.js} +1 -1
- package/dist/ui/assets/{angelscript-BeaXyx_P.js → angelscript-qlrFxfW-.js} +1 -1
- package/dist/ui/assets/{apache-CU8d-z9X.js → apache-B-sF-DQH.js} +1 -1
- package/dist/ui/assets/{applescript-d1Wxkqz1.js → applescript-4FdcBnbI.js} +1 -1
- package/dist/ui/assets/{arc-BMsPIm3j.js → arc-BB3K1enp.js} +1 -1
- package/dist/ui/assets/{arcade-CtbgrWTM.js → arcade-B_yqWaaG.js} +1 -1
- package/dist/ui/assets/{architectureDiagram-ZJ3FMSHR-CVjC5TrS.js → architectureDiagram-ZJ3FMSHR-B39vkY8V.js} +1 -1
- package/dist/ui/assets/{arduino-Bc9L39Hr.js → arduino-yAcBoTWU.js} +1 -1
- package/dist/ui/assets/{armasm-DuWmpjWR.js → armasm-wIcY84bI.js} +1 -1
- package/dist/ui/assets/{asciidoc-CDIhFTnx.js → asciidoc-Bxnu28-Z.js} +1 -1
- package/dist/ui/assets/{aspectj-SYj-57Es.js → aspectj-B2cKJA_O.js} +1 -1
- package/dist/ui/assets/{autohotkey-hBi5dq37.js → autohotkey-B_rMWTtE.js} +1 -1
- package/dist/ui/assets/{autoit-BSawXzhg.js → autoit-DwcuvMwv.js} +1 -1
- package/dist/ui/assets/{avrasm-CwYom8Np.js → avrasm-heGX1PXK.js} +1 -1
- package/dist/ui/assets/{awk-BvBRfGo2.js → awk-BiqCQAEf.js} +1 -1
- package/dist/ui/assets/{axapta-CqUavA8k.js → axapta-Cv8M-Ih6.js} +1 -1
- package/dist/ui/assets/{bash-BS_ZnmEu.js → bash-Divgn3JV.js} +1 -1
- package/dist/ui/assets/{basic-xbP4IXrN.js → basic-B9dnAP55.js} +1 -1
- package/dist/ui/assets/{blockDiagram-677ZJIJ3-CmpI3f5p.js → blockDiagram-677ZJIJ3-DQ1mf7A_.js} +1 -1
- package/dist/ui/assets/{bnf-BECwu6uW.js → bnf-kIL5mSsP.js} +1 -1
- package/dist/ui/assets/{brainfuck-QQgu4j4N.js → brainfuck-DqB7xDjH.js} +1 -1
- package/dist/ui/assets/{coq-IDMIFfem.js → c-HmsCM6sx.js} +1 -1
- package/dist/ui/assets/{c-like-DYrFOtXy.js → c-like-De5MhE7G.js} +1 -1
- package/dist/ui/assets/{c4Diagram-LMCZKHZV-B6Hgngz9.js → c4Diagram-LMCZKHZV-DQxtYsAx.js} +1 -1
- package/dist/ui/assets/{cal-CNMrJ6v5.js → cal-mYdfz9en.js} +1 -1
- package/dist/ui/assets/{capnproto-DYCKl6oY.js → capnproto-D04CRlOt.js} +1 -1
- package/dist/ui/assets/{ceylon-mb8tRPl0.js → ceylon-pi9lFCja.js} +1 -1
- package/dist/ui/assets/channel-ChTtxQDg.js +1 -0
- package/dist/ui/assets/{chunk-2Q5K7J3B-LxvQ-G67.js → chunk-2Q5K7J3B-BDD1nPt8.js} +1 -1
- package/dist/ui/assets/{chunk-32BRIVSS-DxzKK6Aw.js → chunk-32BRIVSS-DgeQFBb5.js} +1 -1
- package/dist/ui/assets/{chunk-5VM5RSS4-CZEoYJ2W.js → chunk-5VM5RSS4-C7Xf2SnI.js} +1 -1
- package/dist/ui/assets/{chunk-EX3LRPZG-DS2PytrN.js → chunk-EX3LRPZG-B_3p1HEv.js} +1 -1
- package/dist/ui/assets/{chunk-JWPE2WC7-UX0Sr1Ie.js → chunk-JWPE2WC7-Dvs7u8eY.js} +1 -1
- package/dist/ui/assets/{chunk-MOJQB5TN-YbJgT9t4.js → chunk-MOJQB5TN-By21wDCN.js} +1 -1
- package/dist/ui/assets/{chunk-RYQCIY6F-DS2VH_U9.js → chunk-RYQCIY6F-6NC700r1.js} +1 -1
- package/dist/ui/assets/{chunk-V7JOEXUC-CZr0pkI1.js → chunk-V7JOEXUC-vEUqZ3rh.js} +1 -1
- package/dist/ui/assets/{chunk-VR4S4FIN-50opPAD3.js → chunk-VR4S4FIN-6tX2dNN9.js} +1 -1
- package/dist/ui/assets/{chunk-XXDRQBXY-DAAX9l7U.js → chunk-XXDRQBXY-qDb2jxAR.js} +1 -1
- package/dist/ui/assets/classDiagram-OUVF2IWQ-Ccbvamlu.js +1 -0
- package/dist/ui/assets/classDiagram-v2-EOCWNBFH-Ccbvamlu.js +1 -0
- package/dist/ui/assets/{clean-C4X7dSkh.js → clean-CLCsDUl1.js} +1 -1
- package/dist/ui/assets/{clojure-DSg9gUa7.js → clojure-dVi5Xifj.js} +1 -1
- package/dist/ui/assets/{clojure-repl-CagRYx7h.js → clojure-repl-BO_FpFmF.js} +1 -1
- package/dist/ui/assets/{cmake-CFdBn53c.js → cmake-CP5aJbyK.js} +1 -1
- package/dist/ui/assets/{coffeescript-CJZtMOPx.js → coffeescript-ZEfu_9pF.js} +1 -1
- package/dist/ui/assets/{c-BRJEPYra.js → coq-6aKUn3zn.js} +1 -1
- package/dist/ui/assets/{cos-Bx2VJuzG.js → cos-BohCnRN2.js} +1 -1
- package/dist/ui/assets/{cose-bilkent-JH36ORCC-zWRLsZpZ.js → cose-bilkent-JH36ORCC-DyXCbbro.js} +1 -1
- package/dist/ui/assets/{cpp-CsG6DlC4.js → cpp-FOgPWPEt.js} +1 -1
- package/dist/ui/assets/{crmsh-DTy9MnmJ.js → crmsh-B0OYb-Oe.js} +1 -1
- package/dist/ui/assets/{crystal-BwgrLrZ1.js → crystal-CuWb_dXm.js} +1 -1
- package/dist/ui/assets/{csharp-B2VeTPAF.js → csharp-BbcqM09j.js} +1 -1
- package/dist/ui/assets/{csp-CTpydNhH.js → csp-rgHnTaDq.js} +1 -1
- package/dist/ui/assets/{css-B0mMUbpY.js → css-C-ibh7ZG.js} +1 -1
- package/dist/ui/assets/{cynefin-VYW2F7L2-BmjQEj6q.js → cynefin-VYW2F7L2-CkuBhgC4.js} +1 -1
- package/dist/ui/assets/{cynefinDiagram-TSTJHNR4-Dr0Zrke0.js → cynefinDiagram-TSTJHNR4-eycFyDao.js} +1 -1
- package/dist/ui/assets/{d-DjuDZnbI.js → d-C0gXxJ0O.js} +1 -1
- package/dist/ui/assets/{dagre-VKFMJZFB-xoTPT2Uu.js → dagre-VKFMJZFB-DzqX9e49.js} +1 -1
- package/dist/ui/assets/{dart-xR3GU9TJ.js → dart-C-fTpuUV.js} +1 -1
- package/dist/ui/assets/{delphi-bJas5QnG.js → delphi-Chm0B9xv.js} +1 -1
- package/dist/ui/assets/{diagram-FQU43EPY-rL_IU7gU.js → diagram-FQU43EPY-BEgCqfg1.js} +1 -1
- package/dist/ui/assets/{diagram-G47NLZAW-EcDiCVGj.js → diagram-G47NLZAW-Cw11Vs2v.js} +1 -1
- package/dist/ui/assets/{diagram-NH7WQ7WH-CGGXOjev.js → diagram-NH7WQ7WH-DSG_UWpP.js} +1 -1
- package/dist/ui/assets/{diagram-OA4YK3LP-DnE7hDjD.js → diagram-OA4YK3LP-CJz-WOaJ.js} +1 -1
- package/dist/ui/assets/{diagram-WEI45ONY-CTJH5eD8.js → diagram-WEI45ONY-CBXjBCvc.js} +1 -1
- package/dist/ui/assets/{diff-doJFF3fv.js → diff-C-vyuMSL.js} +1 -1
- package/dist/ui/assets/{django-D3b-owa_.js → django-CJK7lReT.js} +1 -1
- package/dist/ui/assets/{dns-C42KYV-Z.js → dns-D02SHjSy.js} +1 -1
- package/dist/ui/assets/{dockerfile-9KUINc2j.js → dockerfile-trKL1Bqu.js} +1 -1
- package/dist/ui/assets/{dos-CxnlJ6qp.js → dos-C52dy-sK.js} +1 -1
- package/dist/ui/assets/{dsconfig-6CMMCwmY.js → dsconfig-MzHgzVrt.js} +1 -1
- package/dist/ui/assets/{dts-D78rdUIB.js → dts-B137dHyX.js} +1 -1
- package/dist/ui/assets/{dust-Dv1uTfJU.js → dust-BcbM0r5C.js} +1 -1
- package/dist/ui/assets/{ebnf-BGbG1cFK.js → ebnf-DkbpI7bK.js} +1 -1
- package/dist/ui/assets/{ebnfDiagram-CCIWWBDH-z2VgRSUV.js → ebnfDiagram-CCIWWBDH-aI5uQ7w1.js} +1 -1
- package/dist/ui/assets/{elixir-ZgAQVY1J.js → elixir-BOtDuqQy.js} +1 -1
- package/dist/ui/assets/{elm-CudiFuNu.js → elm-DS8Tyyu-.js} +1 -1
- package/dist/ui/assets/{erDiagram-Q63AITRT-X1TODuRv.js → erDiagram-Q63AITRT-2vCbd4Mm.js} +1 -1
- package/dist/ui/assets/{erb-Bz_NZh6W.js → erb-CSXECRbn.js} +1 -1
- package/dist/ui/assets/{erlang-DNuj1nb2.js → erlang-BMxlgKPJ.js} +1 -1
- package/dist/ui/assets/{erlang-repl-SP1Gan9W.js → erlang-repl-DPzlolPg.js} +1 -1
- package/dist/ui/assets/{excel-0K77uECF.js → excel-CW2Uxed3.js} +1 -1
- package/dist/ui/assets/{fix-CalJq7JD.js → fix-UW84SlCs.js} +1 -1
- package/dist/ui/assets/{flix-BlIs11_w.js → flix-4UGiPULd.js} +1 -1
- package/dist/ui/assets/{flowDiagram-23GEKE2U-DA2dnmc0.js → flowDiagram-23GEKE2U-R5PbCbZI.js} +1 -1
- package/dist/ui/assets/{fortran-ZCobXY2R.js → fortran-nhHsngdu.js} +1 -1
- package/dist/ui/assets/{fsharp-Be8rwUtc.js → fsharp-CDyZ1ST5.js} +1 -1
- package/dist/ui/assets/{gams-DUat8frQ.js → gams-DHzkkUie.js} +1 -1
- package/dist/ui/assets/{ganttDiagram-NO4QXBWP-DdFwaIGZ.js → ganttDiagram-NO4QXBWP-CGcq4Ie_.js} +1 -1
- package/dist/ui/assets/{gauss-BB4U88dy.js → gauss-DdhFGyBv.js} +1 -1
- package/dist/ui/assets/{gcode-DzeUZuZg.js → gcode-ImHh8OLA.js} +1 -1
- package/dist/ui/assets/{gherkin-B_8vW_BO.js → gherkin-CTWAW-XR.js} +1 -1
- package/dist/ui/assets/{gitGraphDiagram-IHSO6WYX-B-Dn8x6I.js → gitGraphDiagram-IHSO6WYX-8nM2Z9lD.js} +1 -1
- package/dist/ui/assets/{glsl-DGHGjPC1.js → glsl-0_W_27G2.js} +1 -1
- package/dist/ui/assets/{gml-BYEku8Yh.js → gml-BoDggu2z.js} +1 -1
- package/dist/ui/assets/{go-D8aSgQMc.js → go-DYfFygwl.js} +1 -1
- package/dist/ui/assets/{golo-CDjCU_jh.js → golo-Mlq-TCg9.js} +1 -1
- package/dist/ui/assets/{gradle-BeUw7tl_.js → gradle-BALAinEB.js} +1 -1
- package/dist/ui/assets/{groovy-5iCQOtR3.js → groovy-Dht--dWU.js} +1 -1
- package/dist/ui/assets/{haml-BEdL8FJi.js → haml-DpMrxg0d.js} +1 -1
- package/dist/ui/assets/{handlebars-BuYQNzoK.js → handlebars-DqHzujNj.js} +1 -1
- package/dist/ui/assets/{haskell-I4FCBcW0.js → haskell-DZSchhkY.js} +1 -1
- package/dist/ui/assets/{haxe-yigyKfFr.js → haxe-C0zBRjdy.js} +1 -1
- package/dist/ui/assets/{hsp-ZUk4j7d1.js → hsp-D_PwbSv2.js} +1 -1
- package/dist/ui/assets/{htmlbars-QYP3lT3u.js → htmlbars-DxAFMG8u.js} +1 -1
- package/dist/ui/assets/{http-BJpD1O71.js → http-DvTRF0Do.js} +1 -1
- package/dist/ui/assets/{hy-CIJ1bP6S.js → hy-lVO-kNyp.js} +1 -1
- package/dist/ui/assets/{index-BDXWttnT.js → index-BbMRVVGt.js} +3 -3
- package/dist/ui/assets/{index-COAgrx1J.js → index-Ci23SMK2.js} +242 -242
- package/dist/ui/assets/index-DlsVXaHT.css +10 -0
- package/dist/ui/assets/{infoDiagram-FWYZ7A6U-fTg9eLNt.js → infoDiagram-FWYZ7A6U-C7WYDlvc.js} +1 -1
- package/dist/ui/assets/{inform7-DAsu-lC2.js → inform7-B8Tf2n8v.js} +1 -1
- package/dist/ui/assets/{ini-Bhz-zHCg.js → ini-DSoYMaLF.js} +1 -1
- package/dist/ui/assets/{irpf90-BunhbwBl.js → irpf90-RCPdkB14.js} +1 -1
- package/dist/ui/assets/{isbl-q9L6hOhP.js → isbl-C2p75PPj.js} +1 -1
- package/dist/ui/assets/{ishikawaDiagram-FXEZZL3T-B8G0sdgd.js → ishikawaDiagram-FXEZZL3T-Cm6jsPlc.js} +1 -1
- package/dist/ui/assets/{java-Iks5Pkau.js → java-DeY4Yuia.js} +1 -1
- package/dist/ui/assets/{javascript-C4vltXPw.js → javascript-3uX1CO-H.js} +1 -1
- package/dist/ui/assets/{jboss-cli-BQBvd2X2.js → jboss-cli-DgnD8mEc.js} +1 -1
- package/dist/ui/assets/{journeyDiagram-5HDEW3XC-Crbzgrum.js → journeyDiagram-5HDEW3XC-DEGV1uA5.js} +1 -1
- package/dist/ui/assets/{json-DXK0_jUK.js → json-BV2PmJJp.js} +1 -1
- package/dist/ui/assets/{julia-CCYoBiYK.js → julia-B-m8kQm7.js} +1 -1
- package/dist/ui/assets/{julia-repl-y8v2Oorl.js → julia-repl-C51atU2X.js} +1 -1
- package/dist/ui/assets/{kanban-definition-HUTT4EX6-C8sCOsBX.js → kanban-definition-HUTT4EX6-BJ4k5iTX.js} +1 -1
- package/dist/ui/assets/{kotlin-Bnjk7_fw.js → kotlin-CYBziIgl.js} +1 -1
- package/dist/ui/assets/{lasso-B-al6x63.js → lasso-Dw2SBMDW.js} +1 -1
- package/dist/ui/assets/{latex-BUmqlb9r.js → latex-Dpd35yke.js} +1 -1
- package/dist/ui/assets/{ldif-D42RWj6Q.js → ldif-Ce9EZU__.js} +1 -1
- package/dist/ui/assets/{leaf-CrH4BZ0m.js → leaf-CpkZzQtC.js} +1 -1
- package/dist/ui/assets/{less-upmRlQQW.js → less-Uzo7M0FD.js} +1 -1
- package/dist/ui/assets/{lisp-DHYS22SA.js → lisp-DWXDlJYm.js} +1 -1
- package/dist/ui/assets/{livecodeserver-CeQNmFP3.js → livecodeserver-uEyPEgVJ.js} +1 -1
- package/dist/ui/assets/{livescript-PJWpY1JI.js → livescript-BQ5f07oK.js} +1 -1
- package/dist/ui/assets/{llvm-BKtKWwCt.js → llvm-BAvP-skE.js} +1 -1
- package/dist/ui/assets/{lsl-RWRLRjk7.js → lsl-DhbiIKu6.js} +1 -1
- package/dist/ui/assets/{lua-BFUDiPGm.js → lua-COxeUeLx.js} +1 -1
- package/dist/ui/assets/{makefile-CUDyOz5D.js → makefile-DhDx-IgL.js} +1 -1
- package/dist/ui/assets/{markdown-zZCLypc6.js → markdown-DX5_kSxq.js} +1 -1
- package/dist/ui/assets/{mathematica-BHbxKxnq.js → mathematica-D351ZddB.js} +1 -1
- package/dist/ui/assets/{matlab-DlGtg--p.js → matlab-CELqIiwF.js} +1 -1
- package/dist/ui/assets/{maxima-BBBeS3Ra.js → maxima-B_YljrMm.js} +1 -1
- package/dist/ui/assets/{mel-nh8j7W_6.js → mel-DltsbNS8.js} +1 -1
- package/dist/ui/assets/{mercury-DyyD-pqr.js → mercury-axX-5Vjj.js} +1 -1
- package/dist/ui/assets/{mindmap-definition-LN4V7U3C-CJlhDHqM.js → mindmap-definition-LN4V7U3C-Bl1EJo6p.js} +1 -1
- package/dist/ui/assets/{mipsasm-hiEhRRiq.js → mipsasm-BxmerVwX.js} +1 -1
- package/dist/ui/assets/{mizar-BZa3iAAL.js → mizar-XNHfbpL2.js} +1 -1
- package/dist/ui/assets/{mojolicious-BCIm2V_y.js → mojolicious-BR0U_7zk.js} +1 -1
- package/dist/ui/assets/{monkey-zmK-7N8b.js → monkey-lLuu9_f-.js} +1 -1
- package/dist/ui/assets/{moonscript-BsS_Mn3D.js → moonscript-DoaZ3DRQ.js} +1 -1
- package/dist/ui/assets/{n1ql-D7xVgDP0.js → n1ql-C6TId6Iu.js} +1 -1
- package/dist/ui/assets/{nginx-ct2q4dtd.js → nginx-BezSG-JT.js} +1 -1
- package/dist/ui/assets/{nim-RO0UOmW3.js → nim-Bb0rfXie.js} +1 -1
- package/dist/ui/assets/{nix-BcRJxPKH.js → nix-o3sJ5-54.js} +1 -1
- package/dist/ui/assets/{node-repl-DgIefwxW.js → node-repl-Sv5hhcTf.js} +1 -1
- package/dist/ui/assets/{nsis-DqHs9QhB.js → nsis-B45BJFhF.js} +1 -1
- package/dist/ui/assets/{objectivec-BBcWqc7Y.js → objectivec-CzS6zVgh.js} +1 -1
- package/dist/ui/assets/{ocaml-BExfw7D6.js → ocaml-Bqux7PyP.js} +1 -1
- package/dist/ui/assets/{openscad-CHPRELQb.js → openscad-4Wf6mF84.js} +1 -1
- package/dist/ui/assets/{oxygene-DpS9uMJW.js → oxygene-Fvwqgkkt.js} +1 -1
- package/dist/ui/assets/{parser3-CjJ_QdBp.js → parser3-zEfzT5wv.js} +1 -1
- package/dist/ui/assets/{pegDiagram-2B236MQR-GM70woGy.js → pegDiagram-2B236MQR-Dd4rIztM.js} +1 -1
- package/dist/ui/assets/{perl-BSNM2Kt8.js → perl-CsS1Gs6o.js} +1 -1
- package/dist/ui/assets/{pf-Z-hKf_88.js → pf-BNH1jO0R.js} +1 -1
- package/dist/ui/assets/{pgsql-DDgznxBg.js → pgsql-DqPigHrq.js} +1 -1
- package/dist/ui/assets/{php-BzAhxF-l.js → php-CdOl9bRs.js} +1 -1
- package/dist/ui/assets/{php-template-DkgcKHRc.js → php-template-DPfirJg2.js} +1 -1
- package/dist/ui/assets/{pieDiagram-ENE6RG2P-Bst7mPyz.js → pieDiagram-ENE6RG2P-DGaJNf4S.js} +1 -1
- package/dist/ui/assets/{plaintext-BYEppD0R.js → plaintext-EHbgBKzw.js} +1 -1
- package/dist/ui/assets/{pony-BT_kQd1K.js → pony-DmJajtp2.js} +1 -1
- package/dist/ui/assets/{powershell-BfRsuSsf.js → powershell-DfGzdWR6.js} +1 -1
- package/dist/ui/assets/{processing-DpzWe5Iu.js → processing-BT0ETgPG.js} +1 -1
- package/dist/ui/assets/{profile-BCOhS5cM.js → profile-B3I-x5Lt.js} +1 -1
- package/dist/ui/assets/{prolog-OxaCCaW8.js → prolog-B_4QJIvI.js} +1 -1
- package/dist/ui/assets/{properties-DMFlA2Ca.js → properties-BFVI8weS.js} +1 -1
- package/dist/ui/assets/{protobuf-CRDFkXvZ.js → protobuf-PaF39oZZ.js} +1 -1
- package/dist/ui/assets/{puppet-DnrVyLzx.js → puppet-BDC6Q8VF.js} +1 -1
- package/dist/ui/assets/{purebasic-Dht4Hniv.js → purebasic-B2ejrOZK.js} +1 -1
- package/dist/ui/assets/{python-B0aMirWu.js → python-BOxtIk9H.js} +1 -1
- package/dist/ui/assets/{python-repl-BlYDBGa7.js → python-repl-BslBh_Mx.js} +1 -1
- package/dist/ui/assets/{q-DzrtW9kT.js → q-BPe8WLGW.js} +1 -1
- package/dist/ui/assets/{qml-DnfQsR3i.js → qml-BazRR6fz.js} +1 -1
- package/dist/ui/assets/{quadrantDiagram-ABIIQ3AL-DNRYurBT.js → quadrantDiagram-ABIIQ3AL-BQ7aPkHk.js} +1 -1
- package/dist/ui/assets/{r-DGI_ZuTD.js → r-C09pGNJC.js} +1 -1
- package/dist/ui/assets/{railroadDiagram-RFXS5EU6-CmbC3Vz4.js → railroadDiagram-RFXS5EU6-sCO9VGvE.js} +1 -1
- package/dist/ui/assets/{reasonml-3SohMgh2.js → reasonml-S7dzwVL9.js} +1 -1
- package/dist/ui/assets/{requirementDiagram-TGXJPOKE-8CxrXHco.js → requirementDiagram-TGXJPOKE-CfT5aVZg.js} +1 -1
- package/dist/ui/assets/{rib-DfRSd4Qa.js → rib-fM2EwQd4.js} +1 -1
- package/dist/ui/assets/{roboconf-CQczGdGW.js → roboconf-D7AaeyrW.js} +1 -1
- package/dist/ui/assets/{routeros-DCka-T2i.js → routeros-c6Q7mKuq.js} +1 -1
- package/dist/ui/assets/{rsl-Dr8MOwMo.js → rsl-sCpEQBxh.js} +1 -1
- package/dist/ui/assets/{ruby-C2zFSkh_.js → ruby-lcKhz2w9.js} +1 -1
- package/dist/ui/assets/{ruleslanguage-C97YsgQq.js → ruleslanguage-BW4ATOuX.js} +1 -1
- package/dist/ui/assets/{rust-H3h8kd9A.js → rust-BbpU-0VY.js} +1 -1
- package/dist/ui/assets/{sankeyDiagram-HTMAVEWB-DBXLWjEq.js → sankeyDiagram-HTMAVEWB-CaweCpvN.js} +1 -1
- package/dist/ui/assets/{sas-04z0Xu8P.js → sas-BPt5R0dx.js} +1 -1
- package/dist/ui/assets/{scala-DyB9Aoiv.js → scala-DxW_vqXs.js} +1 -1
- package/dist/ui/assets/{scheme-DBj6nxUi.js → scheme-T2Q_jWzT.js} +1 -1
- package/dist/ui/assets/{scilab-Btj7AD9s.js → scilab-DMORg9lV.js} +1 -1
- package/dist/ui/assets/{scss-BXZJyXt7.js → scss-t0VsosqT.js} +1 -1
- package/dist/ui/assets/{sequenceDiagram-DBY2YBRQ-DXIkBFKC.js → sequenceDiagram-DBY2YBRQ-o-H_R4zb.js} +1 -1
- package/dist/ui/assets/{shell-BsreQR1Z.js → shell-CnCDa1s9.js} +1 -1
- package/dist/ui/assets/{sizeCapture-X5ZJPWSS-ocS9jxAQ.js → sizeCapture-X5ZJPWSS-BNLkHGDS.js} +1 -1
- package/dist/ui/assets/{smali-D9wQw9zm.js → smali-_n-BxJyG.js} +1 -1
- package/dist/ui/assets/{smalltalk-Dku6G_H3.js → smalltalk-B90PXJwK.js} +1 -1
- package/dist/ui/assets/{sml-BknyU6ya.js → sml-fuY7bj-n.js} +1 -1
- package/dist/ui/assets/{sqf-DRYMaOg8.js → sqf-COpwkyuo.js} +1 -1
- package/dist/ui/assets/{sql-Cw3Ax4KA.js → sql-CXIT0j-x.js} +1 -1
- package/dist/ui/assets/{sql_more-vWdslLE0.js → sql_more-C1Oxq4rx.js} +1 -1
- package/dist/ui/assets/{stan-8XH5bDS6.js → stan-BZEpaHeC.js} +1 -1
- package/dist/ui/assets/{stata-4e77wgfe.js → stata-CkBwaiZM.js} +1 -1
- package/dist/ui/assets/{stateDiagram-2N3HPSRC-RMmL9jMG.js → stateDiagram-2N3HPSRC-BkdnNF7I.js} +1 -1
- package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-0JnZ1VSQ.js +1 -0
- package/dist/ui/assets/{step21-ByIeDMY3.js → step21-fs9N_U3O.js} +1 -1
- package/dist/ui/assets/{stylus-ZAhJyWsw.js → stylus-Bs_9cvKZ.js} +1 -1
- package/dist/ui/assets/{subunit-pPW2UGkj.js → subunit-DvgcOCqJ.js} +1 -1
- package/dist/ui/assets/{swift-CX3BB5az.js → swift-BE4ONsur.js} +1 -1
- package/dist/ui/assets/{swimlanes-5IMT3BWC-C2zAuJ56.js → swimlanes-5IMT3BWC-uqTAc7o7.js} +2 -2
- package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DQRIIEmi.js +8 -0
- package/dist/ui/assets/{taggerscript-BHcjbWIC.js → taggerscript-BhmPJ64C.js} +1 -1
- package/dist/ui/assets/{tap-BOl1lBlS.js → tap-DkueIVKV.js} +1 -1
- package/dist/ui/assets/{tcl-DZjeOBDh.js → tcl-DyXOOkFi.js} +1 -1
- package/dist/ui/assets/{thrift-BxboWg4x.js → thrift-Dhgbk56T.js} +1 -1
- package/dist/ui/assets/{timeline-definition-FHXFAJF6-BOxsxyq_.js → timeline-definition-FHXFAJF6-DBAk9Ouc.js} +1 -1
- package/dist/ui/assets/{tp-BNM6ql3J.js → tp-BsXyrRGH.js} +1 -1
- package/dist/ui/assets/{twig-Dj9ZiXD4.js → twig-J0HqIuHw.js} +1 -1
- package/dist/ui/assets/{typescript-7MEJlu_6.js → typescript-Dkwvul39.js} +1 -1
- package/dist/ui/assets/{vala-DNqOAgHJ.js → vala-CRGnf8aY.js} +1 -1
- package/dist/ui/assets/{vbnet-T0mNKVc_.js → vbnet-BtJAUe3z.js} +1 -1
- package/dist/ui/assets/{vbscript-CeuwVMAI.js → vbscript-RgFFNuM3.js} +1 -1
- package/dist/ui/assets/{vbscript-html-BbJSt2w6.js → vbscript-html-DO32Io9Y.js} +1 -1
- package/dist/ui/assets/{vennDiagram-L72KCM5P-BX9mWeiT.js → vennDiagram-L72KCM5P-BJi6y0hh.js} +1 -1
- package/dist/ui/assets/{verilog-DYuhYfkX.js → verilog-C4h6MLcI.js} +1 -1
- package/dist/ui/assets/{vhdl-Cf9aT-t7.js → vhdl-DOafePyU.js} +1 -1
- package/dist/ui/assets/{vim-DciP44K1.js → vim-BAdTA9TY.js} +1 -1
- package/dist/ui/assets/{wardleyDiagram-EHGQE667-CDj2rOzu.js → wardleyDiagram-EHGQE667-C7c_4IJ6.js} +1 -1
- package/dist/ui/assets/{x86asm-E-AN_LXO.js → x86asm-BCL6__QH.js} +1 -1
- package/dist/ui/assets/{xl-CxYLJelN.js → xl-qIzE4HOe.js} +1 -1
- package/dist/ui/assets/{xml-yz1SRLuU.js → xml-DE2sJXYU.js} +1 -1
- package/dist/ui/assets/{xquery-BLzBF3tV.js → xquery-CQ35t92y.js} +1 -1
- package/dist/ui/assets/{xychartDiagram-FW5EYKEG-Czapk9-Z.js → xychartDiagram-FW5EYKEG-D2ILn0jL.js} +1 -1
- package/dist/ui/assets/{yaml-Cv4Y7iN_.js → yaml-5KaAvG5C.js} +1 -1
- package/dist/ui/assets/{zephir-KRcdQfEX.js → zephir-CbR3Ryfq.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/utils/__tests__/abort-signals.test.js +67 -0
- package/dist/utils/__tests__/inject-loop.test.js +1 -53
- package/dist/utils/__tests__/learn-tasks-db.test.js +82 -0
- package/dist/utils/__tests__/openai-converter.test.js +25 -0
- package/dist/utils/__tests__/pi-crawl-tools.test.js +15 -4
- package/dist/utils/__tests__/pi-dedup-reconcile.test.js +11 -9
- package/dist/utils/__tests__/pi-events.test.js +172 -0
- package/dist/utils/__tests__/pi-learn-orchestrator.test.js +216 -6
- package/dist/utils/__tests__/pi-runtime-json.test.js +38 -3
- package/dist/utils/__tests__/providers-db.test.js +40 -2
- package/dist/utils/__tests__/request-writer.test.js +271 -39
- package/dist/utils/__tests__/sse-protocol.test.d.ts +1 -0
- package/dist/utils/__tests__/sse-protocol.test.js +115 -0
- package/dist/utils/__tests__/vault.test.d.ts +1 -0
- package/dist/utils/__tests__/{knowledge-store.test.js → vault.test.js} +16 -16
- package/dist/utils/abort-signals.d.ts +13 -0
- package/dist/utils/abort-signals.js +33 -0
- package/dist/utils/db.d.ts +1 -0
- package/dist/utils/db.js +24 -0
- package/dist/utils/esm-dirname.d.ts +0 -15
- package/dist/utils/esm-dirname.js +0 -4
- package/dist/utils/inject-loop.d.ts +0 -27
- package/dist/utils/inject-loop.js +2 -56
- package/dist/utils/learn-tasks-db.d.ts +15 -0
- package/dist/utils/learn-tasks-db.js +35 -0
- package/dist/utils/openai-converter.js +88 -78
- package/dist/utils/pi-browser-tools.d.ts +0 -2
- package/dist/utils/pi-browser-tools.js +0 -174
- package/dist/utils/pi-crawl-tools.d.ts +2 -1
- package/dist/utils/pi-crawl-tools.js +16 -11
- package/dist/utils/pi-dedup.d.ts +8 -30
- package/dist/utils/pi-dedup.js +32 -67
- package/dist/utils/pi-events.d.ts +65 -0
- package/dist/utils/pi-events.js +98 -0
- package/dist/utils/pi-learn-orchestrator.d.ts +6 -5
- package/dist/utils/pi-learn-orchestrator.js +71 -106
- package/dist/utils/pi-runtime.d.ts +5 -6
- package/dist/utils/pi-runtime.js +38 -42
- package/dist/utils/pi-sandbox-ops.d.ts +0 -36
- package/dist/utils/pi-sandbox-ops.js +5 -190
- package/dist/utils/providers-db.d.ts +3 -0
- package/dist/utils/providers-db.js +21 -7
- package/dist/utils/request-writer.d.ts +59 -30
- package/dist/utils/request-writer.js +178 -58
- package/dist/utils/sse-protocol.d.ts +34 -0
- package/dist/utils/sse-protocol.js +121 -0
- package/dist/utils/sse-stream-processor.d.ts +4 -9
- package/dist/utils/sse-stream-processor.js +13 -104
- package/dist/utils/sse-writer.d.ts +1 -1
- package/dist/utils/sse-writer.js +3 -2
- package/dist/utils/stats-aggregator.js +3 -0
- package/dist/utils/tool-injector.js +7 -0
- package/dist/utils/vault.d.ts +111 -0
- package/dist/utils/vault.js +434 -0
- package/package.json +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.B6Qfxe6W.js +0 -1
- package/dist/types/api.d.ts +0 -20
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -4
- package/dist/types/log.d.ts +0 -13
- package/dist/ui/assets/channel-Bc4Td8eZ.js +0 -1
- package/dist/ui/assets/classDiagram-OUVF2IWQ-BicxhZFq.js +0 -1
- package/dist/ui/assets/classDiagram-v2-EOCWNBFH-BicxhZFq.js +0 -1
- package/dist/ui/assets/index-C0fxlU9d.css +0 -10
- package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-QvaEO5U6.js +0 -1
- package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DPgCOY0D.js +0 -8
- package/dist/utils/__tests__/sse-accumulator.test.js +0 -83
- package/dist/utils/knowledge-store.d.ts +0 -51
- package/dist/utils/knowledge-store.js +0 -241
- package/dist/utils/migrate-files-to-db.d.ts +0 -1
- package/dist/utils/migrate-files-to-db.js +0 -138
- package/dist/utils/sse-accumulator.d.ts +0 -9
- package/dist/utils/sse-accumulator.js +0 -59
- /package/dist/docs/assets/{proxy-cli_data-hooks.md.w9Oe1OD3.lean.js → proxy-cli_data-hooks.md.Bz8CVbxO.lean.js} +0 -0
- /package/dist/docs/assets/{proxy-core_ui-routes.md.Dyqkeoiv.lean.js → proxy-core_ui-routes.md.B21t1p7R.lean.js} +0 -0
- /package/dist/{types/api.js → utils/__tests__/abort-signals.test.d.ts} +0 -0
- /package/dist/{types/log.js → utils/__tests__/learn-tasks-db.test.d.ts} +0 -0
- /package/dist/utils/__tests__/{knowledge-store.test.d.ts → openai-converter.test.d.ts} +0 -0
- /package/dist/utils/__tests__/{sse-accumulator.test.d.ts → pi-events.test.d.ts} +0 -0
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
import { initDatabase, getDatabase } from './db.js';
|
|
2
2
|
import { parseUpstreamEvents } from './inject-loop.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return messageDelta?.usage;
|
|
8
|
-
}
|
|
9
|
-
// --- SSE Event Batch Writer (incremental DB writes during streaming) ---
|
|
10
|
-
export const EVENT_BATCH_SIZE = 10;
|
|
11
|
-
// Cached prepared statements for batch writes
|
|
3
|
+
import { pushNewRequest } from '../server/data-push.js';
|
|
4
|
+
// --- Private implementation ---
|
|
5
|
+
const EVENT_BATCH_SIZE = 10;
|
|
6
|
+
// Cached prepared statement for batch writes
|
|
12
7
|
let insertEventStmt = null;
|
|
13
|
-
let deleteRequestStmt = null;
|
|
14
8
|
let cachedDbInstance = null;
|
|
15
|
-
// Invalidate cached
|
|
9
|
+
// Invalidate cached stmt when DB instance changes (tests create fresh DB per suite)
|
|
16
10
|
function ensureStmtCacheValid(db) {
|
|
17
11
|
if (db !== cachedDbInstance) {
|
|
18
12
|
insertEventStmt = null;
|
|
19
|
-
deleteRequestStmt = null;
|
|
20
13
|
cachedDbInstance = db;
|
|
21
14
|
}
|
|
22
15
|
}
|
|
23
16
|
/**
|
|
24
17
|
* Flush a batch of SSE events to the response_events table.
|
|
25
|
-
* Called during streaming every ~10 events to avoid in-memory accumulation.
|
|
26
18
|
*/
|
|
27
|
-
|
|
19
|
+
function flushEventBatch(sessionId, requestId, batch, startIndex) {
|
|
28
20
|
const db = getDatabase();
|
|
29
21
|
ensureStmtCacheValid(db);
|
|
30
22
|
if (!insertEventStmt) {
|
|
@@ -35,28 +27,15 @@ export function flushEventBatch(sessionId, requestId, batch, startIndex) {
|
|
|
35
27
|
insertEventStmt.run(requestId, sessionId, startIndex + i, event.type ?? null, JSON.stringify(event.data));
|
|
36
28
|
}
|
|
37
29
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
db.prepare('DELETE FROM response_events WHERE request_id = ? AND session_id = ?').run(requestId, sessionId);
|
|
30
|
+
function extractUsage(events) {
|
|
31
|
+
if (!events)
|
|
32
|
+
return undefined;
|
|
33
|
+
const messageDelta = events.find((e) => e?.type === 'message_delta');
|
|
34
|
+
return messageDelta?.usage;
|
|
44
35
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const db = initDatabase();
|
|
49
|
-
const events = data.response?.events;
|
|
50
|
-
const usage = events ? extractTokenUsage(events) : undefined;
|
|
51
|
-
// For JSON responses (non-streaming), events are still in the array — flush them first
|
|
52
|
-
if (events && events.length > 0) {
|
|
53
|
-
const batch = events.map((e, i) => ({
|
|
54
|
-
index: i,
|
|
55
|
-
type: e?.type ?? undefined,
|
|
56
|
-
data: e
|
|
57
|
-
}));
|
|
58
|
-
flushEventBatch(sessionId, requestId, batch, 0);
|
|
59
|
-
}
|
|
36
|
+
function writeCompletedRow(args) {
|
|
37
|
+
const db = getDatabase();
|
|
38
|
+
const { meta } = args;
|
|
60
39
|
const stmt = db.prepare(`
|
|
61
40
|
INSERT OR REPLACE INTO requests (
|
|
62
41
|
request_id, session_id, timestamp, method, path, status_code, response_time,
|
|
@@ -68,24 +47,155 @@ export async function saveRequestDB(sessionId, requestId, data) {
|
|
|
68
47
|
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
|
69
48
|
)
|
|
70
49
|
`);
|
|
71
|
-
stmt.run(requestId, sessionId,
|
|
72
|
-
|
|
73
|
-
: 0, data.apiKey || null, data.proxyApiKey || null, data.baseUrl || null, data.model || null, data.machineId || null, data.request.headers['user-agent'] || null, usage?.input_tokens || null, usage?.output_tokens || null, usage?.cache_read_input_tokens || null, usage?.cache_creation_input_tokens || null, JSON.stringify(data.request.headers), data.request.body ? JSON.stringify(data.request.body) : null, data.response?.headers ? JSON.stringify(data.response.headers) : null, null, // response_events now stored in separate table
|
|
74
|
-
data.response?.completedAt || null, data.response?.closedAt || null, data.response?.error || null);
|
|
50
|
+
stmt.run(args.requestId, meta.sessionId, meta.timestamp, meta.request.method, meta.request.path, args.statusCode, args.responseTime, meta.apiKey || null, meta.proxyApiKey || null, meta.baseUrl || null, meta.model || null, meta.machineId || null, meta.request.headers['user-agent'] || null, args.usage?.input_tokens || null, args.usage?.output_tokens || null, args.usage?.cache_read_input_tokens || null, args.usage?.cache_creation_input_tokens || null, JSON.stringify(meta.request.headers), meta.request.body ? JSON.stringify(meta.request.body) : null, args.headers ? JSON.stringify(args.headers) : null, null, // response_events now stored in separate table
|
|
51
|
+
args.completedAt || null, args.closedAt || null, args.error || null);
|
|
75
52
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
53
|
+
function buildSummary(meta, requestId, statusCode, responseTime, usage, withPendingId, closedAt) {
|
|
54
|
+
return {
|
|
55
|
+
requestId,
|
|
56
|
+
sessionId: meta.sessionId,
|
|
57
|
+
compositeId: `${meta.sessionId}:${requestId}`,
|
|
58
|
+
timestamp: meta.timestamp,
|
|
59
|
+
method: meta.request.method,
|
|
60
|
+
path: meta.request.path,
|
|
61
|
+
statusCode,
|
|
62
|
+
responseTime,
|
|
63
|
+
baseUrl: meta.baseUrl,
|
|
64
|
+
model: meta.model,
|
|
65
|
+
machineId: meta.machineId,
|
|
66
|
+
userAgent: meta.request.headers['user-agent'],
|
|
67
|
+
usage,
|
|
68
|
+
pendingId: withPendingId ? `${meta.sessionId}:${meta.localRequestId}` : undefined,
|
|
69
|
+
closedAt
|
|
70
|
+
};
|
|
80
71
|
}
|
|
81
|
-
//
|
|
82
|
-
export function
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
72
|
+
// --- Public API ---
|
|
73
|
+
export function createRequestRecorder(meta) {
|
|
74
|
+
const eventBatch = [];
|
|
75
|
+
const tailBuffer = [];
|
|
76
|
+
let eventIndex = 0;
|
|
77
|
+
const startTime = Date.now();
|
|
78
|
+
let pendingCalled = false;
|
|
79
|
+
function flushRemaining() {
|
|
80
|
+
if (eventBatch.length > 0) {
|
|
81
|
+
flushEventBatch(meta.sessionId, meta.localRequestId, eventBatch, eventIndex - eventBatch.length);
|
|
82
|
+
eventBatch.length = 0;
|
|
83
|
+
}
|
|
87
84
|
}
|
|
88
|
-
|
|
85
|
+
function appendEvent(event) {
|
|
86
|
+
const entry = { index: eventIndex, type: event?.type, data: event };
|
|
87
|
+
eventBatch.push(entry);
|
|
88
|
+
// Maintain tail buffer (last 5 events for usage extraction)
|
|
89
|
+
tailBuffer.push(event);
|
|
90
|
+
if (tailBuffer.length > 5) {
|
|
91
|
+
tailBuffer.shift();
|
|
92
|
+
}
|
|
93
|
+
// Flush batch to DB when threshold reached
|
|
94
|
+
if (eventBatch.length >= EVENT_BATCH_SIZE) {
|
|
95
|
+
flushEventBatch(meta.sessionId, meta.localRequestId, eventBatch, eventIndex - eventBatch.length + 1);
|
|
96
|
+
eventBatch.length = 0; // Reset batch (memory freed)
|
|
97
|
+
}
|
|
98
|
+
eventIndex++;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
async pending() {
|
|
102
|
+
if (pendingCalled)
|
|
103
|
+
return;
|
|
104
|
+
pendingCalled = true;
|
|
105
|
+
writeCompletedRow({
|
|
106
|
+
meta,
|
|
107
|
+
requestId: meta.localRequestId,
|
|
108
|
+
statusCode: 0,
|
|
109
|
+
responseTime: 0
|
|
110
|
+
});
|
|
111
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, 0, 0, undefined, false), 'pending');
|
|
112
|
+
},
|
|
113
|
+
appendEvent,
|
|
114
|
+
// 上游响应头到达:回写真实 status_code,状态仍 pending(UI 保留 spinner)
|
|
115
|
+
headers({ statusCode, headers }) {
|
|
116
|
+
getDatabase().prepare('UPDATE requests SET status_code = ?, response_headers = ? WHERE request_id = ? AND session_id = ?').run(statusCode, headers ? JSON.stringify(headers) : null, meta.localRequestId, meta.sessionId);
|
|
117
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, statusCode, 0, undefined, false, undefined), 'pending');
|
|
118
|
+
},
|
|
119
|
+
async complete({ cloudRequestId, statusCode, headers }) {
|
|
120
|
+
// Flush remaining events in batch
|
|
121
|
+
flushRemaining();
|
|
122
|
+
// Usage synthesis: prefer message_delta, otherwise convert OpenAI-style usage
|
|
123
|
+
let usage = extractUsage(tailBuffer);
|
|
124
|
+
if (!usage) {
|
|
125
|
+
const openaiEvent = tailBuffer.find((e) => e?.usage);
|
|
126
|
+
if (openaiEvent) {
|
|
127
|
+
appendEvent({
|
|
128
|
+
type: 'message_delta',
|
|
129
|
+
usage: {
|
|
130
|
+
output_tokens: openaiEvent.usage.completion_tokens || 0
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
usage = extractUsage(tailBuffer);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Ensure the synthetic event (if any) is written before row replacement
|
|
137
|
+
flushRemaining();
|
|
138
|
+
const completedAt = new Date().toISOString();
|
|
139
|
+
const finalId = cloudRequestId ?? meta.localRequestId;
|
|
140
|
+
const responseTime = Date.now() - startTime;
|
|
141
|
+
const db = getDatabase();
|
|
142
|
+
if (finalId !== meta.localRequestId) {
|
|
143
|
+
const replace = db.transaction(() => {
|
|
144
|
+
db.prepare('UPDATE response_events SET request_id = ? WHERE request_id = ? AND session_id = ?').run(finalId, meta.localRequestId, meta.sessionId);
|
|
145
|
+
writeCompletedRow({
|
|
146
|
+
meta, requestId: finalId, statusCode, responseTime, headers, usage, completedAt
|
|
147
|
+
});
|
|
148
|
+
db.prepare('DELETE FROM requests WHERE request_id = ? AND session_id = ?').run(meta.localRequestId, meta.sessionId);
|
|
149
|
+
});
|
|
150
|
+
replace();
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
writeCompletedRow({
|
|
154
|
+
meta, requestId: finalId, statusCode, responseTime, headers, usage, completedAt
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
pushNewRequest(buildSummary(meta, finalId, statusCode, responseTime, usage, finalId !== meta.localRequestId), 'completed');
|
|
158
|
+
},
|
|
159
|
+
// 流被截断/挂死:保留真实 status_code,通过 closed_at + error 标记中断
|
|
160
|
+
interrupt({ statusCode, error }) {
|
|
161
|
+
flushRemaining();
|
|
162
|
+
const responseTime = Date.now() - startTime;
|
|
163
|
+
const closedAt = new Date().toISOString();
|
|
164
|
+
getDatabase().prepare('UPDATE requests SET status_code = ?, response_time = ?, closed_at = ?, error = ? WHERE request_id = ? AND session_id = ?').run(statusCode, responseTime, closedAt, error, meta.localRequestId, meta.sessionId);
|
|
165
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, statusCode, responseTime, undefined, false, closedAt), 'completed');
|
|
166
|
+
},
|
|
167
|
+
fail({ statusCode, error }) {
|
|
168
|
+
const responseTime = Date.now() - startTime;
|
|
169
|
+
const closedAt = new Date().toISOString();
|
|
170
|
+
getDatabase().prepare('UPDATE requests SET status_code = ?, response_time = ?, closed_at = ?, error = ? WHERE request_id = ? AND session_id = ?').run(statusCode, responseTime, closedAt, error, meta.localRequestId, meta.sessionId);
|
|
171
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, statusCode, responseTime, undefined, false, closedAt), 'completed');
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// Record an inject loop iteration: completed row + events + push, no pending, responseTime 0
|
|
176
|
+
export async function recordIteration(meta) {
|
|
177
|
+
initDatabase();
|
|
178
|
+
const events = meta.response.events ?? [];
|
|
179
|
+
if (events.length > 0) {
|
|
180
|
+
const batch = events.map((e, i) => ({
|
|
181
|
+
index: i,
|
|
182
|
+
type: e?.type,
|
|
183
|
+
data: e
|
|
184
|
+
}));
|
|
185
|
+
flushEventBatch(meta.sessionId, meta.localRequestId, batch, 0);
|
|
186
|
+
}
|
|
187
|
+
const usage = extractUsage(events);
|
|
188
|
+
const completedAt = new Date().toISOString();
|
|
189
|
+
writeCompletedRow({
|
|
190
|
+
meta,
|
|
191
|
+
requestId: meta.localRequestId,
|
|
192
|
+
statusCode: meta.response.statusCode,
|
|
193
|
+
responseTime: 0,
|
|
194
|
+
headers: meta.response.headers,
|
|
195
|
+
usage,
|
|
196
|
+
completedAt
|
|
197
|
+
});
|
|
198
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, meta.response.statusCode, 0, usage, false), 'completed');
|
|
89
199
|
}
|
|
90
200
|
// Load single request by compositeId (sessionId:requestId)
|
|
91
201
|
export async function loadRequestDB(compositeId) {
|
|
@@ -165,7 +275,7 @@ export async function listRequestDB(limit = 1000, before) {
|
|
|
165
275
|
SELECT
|
|
166
276
|
request_id, session_id, timestamp, method, path, status_code, response_time,
|
|
167
277
|
api_key, proxy_api_key, base_url, model, machine_id, user_agent,
|
|
168
|
-
input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens
|
|
278
|
+
input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, closed_at
|
|
169
279
|
FROM requests
|
|
170
280
|
${whereClause}
|
|
171
281
|
ORDER BY timestamp DESC
|
|
@@ -194,7 +304,8 @@ export async function listRequestDB(limit = 1000, before) {
|
|
|
194
304
|
output_tokens: row.output_tokens,
|
|
195
305
|
cache_read_input_tokens: row.cache_read_tokens,
|
|
196
306
|
cache_creation_input_tokens: row.cache_creation_tokens
|
|
197
|
-
} : undefined
|
|
307
|
+
} : undefined,
|
|
308
|
+
closedAt: row.closed_at || undefined
|
|
198
309
|
})),
|
|
199
310
|
hasMore
|
|
200
311
|
};
|
|
@@ -212,13 +323,22 @@ export async function cleanOldRequestsDB(daysToKeep = 7) {
|
|
|
212
323
|
db.prepare(`DELETE FROM response_events WHERE request_id IN (SELECT request_id FROM requests WHERE timestamp < ?)`).run(cutoff);
|
|
213
324
|
db.prepare(`DELETE FROM requests WHERE timestamp < ?`).run(cutoff);
|
|
214
325
|
}
|
|
215
|
-
//
|
|
216
|
-
|
|
326
|
+
// 启动时回收上次进程遗留的僵尸 SSE 行:未完成、未关闭且超龄,逐行标记为中断
|
|
327
|
+
// (status_code 保持原值不动),返回处理行数
|
|
328
|
+
export function interruptStaleRequestsOnStartup(maxAgeMs = 5 * 60000) {
|
|
217
329
|
const db = initDatabase();
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
330
|
+
const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
|
|
331
|
+
const rows = db.prepare(`
|
|
332
|
+
SELECT request_id, session_id
|
|
333
|
+
FROM requests
|
|
334
|
+
WHERE completed_at IS NULL AND closed_at IS NULL AND timestamp < ?
|
|
335
|
+
`).all(cutoff);
|
|
336
|
+
const closedAt = new Date().toISOString();
|
|
337
|
+
const stmt = db.prepare('UPDATE requests SET closed_at = ?, error = ? WHERE request_id = ? AND session_id = ?');
|
|
338
|
+
for (const row of rows) {
|
|
339
|
+
stmt.run(closedAt, 'interrupted: proxy restarted', row.request_id, row.session_id);
|
|
340
|
+
}
|
|
341
|
+
return rows.length;
|
|
222
342
|
}
|
|
223
343
|
// Load session history for multi-turn chat resume
|
|
224
344
|
// Returns the last request's messages + assistant response, to prepend to new messages
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE 帧协议:字节流 ↔ SSE 帧 的唯一知识收敛点。
|
|
3
|
+
*
|
|
4
|
+
* - SSE 帧(frame):字节流按 SSE 规范切分出的单位,由若干字段行
|
|
5
|
+
* (event: / data: / id: / 注释 / 空行分发)组成。
|
|
6
|
+
* - SSE 事件(event):SSE 帧的 data 字段解析出的 JSON 消息。
|
|
7
|
+
*
|
|
8
|
+
* 解析遵循 HTML spec 的 event stream 语义:残帧缓冲、LF/CRLF/CR 行尾、
|
|
9
|
+
* 空行分发、字段行去掉恰好一个可选空格。
|
|
10
|
+
*/
|
|
11
|
+
export interface SSEFrame {
|
|
12
|
+
event?: string;
|
|
13
|
+
data: string[];
|
|
14
|
+
id?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface SSEDecoder {
|
|
17
|
+
write(chunk: Buffer | string): void;
|
|
18
|
+
end(): void;
|
|
19
|
+
}
|
|
20
|
+
/** 创建 SSE 帧解码器:每分发一个完整 SSE 帧回调一次 */
|
|
21
|
+
export declare function createSSEDecoder(onFrame: (frame: SSEFrame) => void): SSEDecoder;
|
|
22
|
+
/**
|
|
23
|
+
* 编码单个 SSE 帧。data 为已序列化好的字符串(调用方负责 JSON.stringify)。
|
|
24
|
+
* 有 event:`event: <event>\ndata: <data>\n\n`;无 event:`data: <data>\n\n`。
|
|
25
|
+
*/
|
|
26
|
+
export declare function encodeSSEFrame(args: {
|
|
27
|
+
event?: string;
|
|
28
|
+
data: string;
|
|
29
|
+
}): string;
|
|
30
|
+
/**
|
|
31
|
+
* 创建 SSE 事件解码器:帧 data 用 \n join 后,[DONE] 触发 onDone,
|
|
32
|
+
* 其余尝试 JSON.parse 成功后触发 onEvent,解析失败静默跳过。
|
|
33
|
+
*/
|
|
34
|
+
export declare function createEventDecoder(onEvent: (event: any) => void, onDone?: () => void): SSEDecoder;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE 帧协议:字节流 ↔ SSE 帧 的唯一知识收敛点。
|
|
3
|
+
*
|
|
4
|
+
* - SSE 帧(frame):字节流按 SSE 规范切分出的单位,由若干字段行
|
|
5
|
+
* (event: / data: / id: / 注释 / 空行分发)组成。
|
|
6
|
+
* - SSE 事件(event):SSE 帧的 data 字段解析出的 JSON 消息。
|
|
7
|
+
*
|
|
8
|
+
* 解析遵循 HTML spec 的 event stream 语义:残帧缓冲、LF/CRLF/CR 行尾、
|
|
9
|
+
* 空行分发、字段行去掉恰好一个可选空格。
|
|
10
|
+
*/
|
|
11
|
+
/** 创建 SSE 帧解码器:每分发一个完整 SSE 帧回调一次 */
|
|
12
|
+
export function createSSEDecoder(onFrame) {
|
|
13
|
+
// 残帧缓冲:跨 chunk 的不完整行
|
|
14
|
+
let leftover = '';
|
|
15
|
+
let event;
|
|
16
|
+
let data = [];
|
|
17
|
+
let id;
|
|
18
|
+
/** 分发当前帧:至少含一个 data 行才回调;分发后重置字段状态 */
|
|
19
|
+
function dispatch() {
|
|
20
|
+
if (data.length > 0) {
|
|
21
|
+
onFrame({ event, data, id });
|
|
22
|
+
}
|
|
23
|
+
event = undefined;
|
|
24
|
+
id = undefined;
|
|
25
|
+
data = [];
|
|
26
|
+
}
|
|
27
|
+
/** 处理一个完整行 */
|
|
28
|
+
function handleLine(line) {
|
|
29
|
+
// 空行 = 一帧分发
|
|
30
|
+
if (line === '') {
|
|
31
|
+
dispatch();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// 以冒号开头的行是注释,忽略
|
|
35
|
+
if (line.startsWith(':'))
|
|
36
|
+
return;
|
|
37
|
+
let field;
|
|
38
|
+
let value;
|
|
39
|
+
const colon = line.indexOf(':');
|
|
40
|
+
if (colon === -1) {
|
|
41
|
+
field = line;
|
|
42
|
+
value = '';
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
field = line.slice(0, colon);
|
|
46
|
+
value = line.slice(colon + 1);
|
|
47
|
+
// 去掉字段值行首恰好一个可选空格
|
|
48
|
+
if (value.startsWith(' '))
|
|
49
|
+
value = value.slice(1);
|
|
50
|
+
}
|
|
51
|
+
if (field === 'event') {
|
|
52
|
+
event = value;
|
|
53
|
+
}
|
|
54
|
+
else if (field === 'data') {
|
|
55
|
+
// 多行 data 逐行保留,消费时用 \n join
|
|
56
|
+
data.push(value);
|
|
57
|
+
}
|
|
58
|
+
else if (field === 'id') {
|
|
59
|
+
id = value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** 消费文本中所有完整行,末段保留为残帧 */
|
|
63
|
+
function feed(text) {
|
|
64
|
+
// CRLF 与单独 CR 统一为 LF
|
|
65
|
+
const normalized = text.replace(/\r\n?/g, '\n');
|
|
66
|
+
const lines = normalized.split('\n');
|
|
67
|
+
leftover = lines.pop() || '';
|
|
68
|
+
for (const line of lines)
|
|
69
|
+
handleLine(line);
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
write(chunk) {
|
|
73
|
+
const chunkText = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');
|
|
74
|
+
feed(leftover + chunkText);
|
|
75
|
+
},
|
|
76
|
+
end() {
|
|
77
|
+
// 先按残帧缓冲补一次切行
|
|
78
|
+
if (leftover !== '') {
|
|
79
|
+
const normalized = leftover.replace(/\r\n?/g, '\n');
|
|
80
|
+
leftover = '';
|
|
81
|
+
for (const line of normalized.split('\n'))
|
|
82
|
+
handleLine(line);
|
|
83
|
+
}
|
|
84
|
+
// 再对缓冲中尚未分发的非空帧做一次分发(末尾无空行也能输出最后一帧)
|
|
85
|
+
if (data.length > 0)
|
|
86
|
+
dispatch();
|
|
87
|
+
// 清空状态
|
|
88
|
+
leftover = '';
|
|
89
|
+
event = undefined;
|
|
90
|
+
id = undefined;
|
|
91
|
+
data = [];
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 编码单个 SSE 帧。data 为已序列化好的字符串(调用方负责 JSON.stringify)。
|
|
97
|
+
* 有 event:`event: <event>\ndata: <data>\n\n`;无 event:`data: <data>\n\n`。
|
|
98
|
+
*/
|
|
99
|
+
export function encodeSSEFrame(args) {
|
|
100
|
+
const prefix = args.event !== undefined ? `event: ${args.event}\n` : '';
|
|
101
|
+
return `${prefix}data: ${args.data}\n\n`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 创建 SSE 事件解码器:帧 data 用 \n join 后,[DONE] 触发 onDone,
|
|
105
|
+
* 其余尝试 JSON.parse 成功后触发 onEvent,解析失败静默跳过。
|
|
106
|
+
*/
|
|
107
|
+
export function createEventDecoder(onEvent, onDone) {
|
|
108
|
+
return createSSEDecoder((frame) => {
|
|
109
|
+
const text = frame.data.join('\n');
|
|
110
|
+
if (text.trim() === '[DONE]') {
|
|
111
|
+
onDone?.();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
onEvent(JSON.parse(text));
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// 非 JSON data 静默跳过
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
@@ -4,23 +4,18 @@ import { type ParsedUpstream } from './inject-loop.js';
|
|
|
4
4
|
* SSE 增量流式处理器:边转发原始 chunk 到客户端,边增量解析事件累积状态。
|
|
5
5
|
* stream end 后提供 getParsedUpstream() 和 hasInjectedToolUse() 供注入检测。
|
|
6
6
|
*
|
|
7
|
-
* 跨 chunk
|
|
7
|
+
* 跨 chunk 残帧由内部 sse-protocol decoder 缓冲处理。
|
|
8
8
|
*/
|
|
9
9
|
export declare class SSEStreamProcessor {
|
|
10
10
|
events: any[];
|
|
11
|
-
private
|
|
12
|
-
private stopReason;
|
|
13
|
-
private usage;
|
|
14
|
-
private leftover;
|
|
11
|
+
private decoder;
|
|
15
12
|
private raw;
|
|
16
13
|
constructor(raw: ServerResponse);
|
|
17
14
|
/** 处理一个 chunk:转发到 reply.raw + 增量解析事件 */
|
|
18
15
|
processChunk(chunk: Buffer): void;
|
|
19
|
-
/**
|
|
16
|
+
/** 收尾残帧(stream end 后调用) */
|
|
20
17
|
flushLeftover(): void;
|
|
21
|
-
/**
|
|
22
|
-
private processEvent;
|
|
23
|
-
/** 从累积状态构建 ParsedUpstream */
|
|
18
|
+
/** 从累积事件构建 ParsedUpstream */
|
|
24
19
|
getParsedUpstream(): ParsedUpstream;
|
|
25
20
|
/** 检测是否有注入的 MCP tool_use */
|
|
26
21
|
hasInjectedToolUse(): boolean;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { findInjectedCall } from './inject-loop.js';
|
|
1
|
+
import { findInjectedCall, parseUpstreamEvents } from './inject-loop.js';
|
|
2
|
+
import { createEventDecoder } from './sse-protocol.js';
|
|
2
3
|
/**
|
|
3
4
|
* SSE 增量流式处理器:边转发原始 chunk 到客户端,边增量解析事件累积状态。
|
|
4
5
|
* stream end 后提供 getParsedUpstream() 和 hasInjectedToolUse() 供注入检测。
|
|
5
6
|
*
|
|
6
|
-
* 跨 chunk
|
|
7
|
+
* 跨 chunk 残帧由内部 sse-protocol decoder 缓冲处理。
|
|
7
8
|
*/
|
|
8
9
|
export class SSEStreamProcessor {
|
|
9
10
|
constructor(raw) {
|
|
@@ -13,29 +14,11 @@ export class SSEStreamProcessor {
|
|
|
13
14
|
writable: true,
|
|
14
15
|
value: []
|
|
15
16
|
});
|
|
16
|
-
Object.defineProperty(this, "
|
|
17
|
+
Object.defineProperty(this, "decoder", {
|
|
17
18
|
enumerable: true,
|
|
18
19
|
configurable: true,
|
|
19
20
|
writable: true,
|
|
20
|
-
value:
|
|
21
|
-
});
|
|
22
|
-
Object.defineProperty(this, "stopReason", {
|
|
23
|
-
enumerable: true,
|
|
24
|
-
configurable: true,
|
|
25
|
-
writable: true,
|
|
26
|
-
value: ''
|
|
27
|
-
});
|
|
28
|
-
Object.defineProperty(this, "usage", {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
configurable: true,
|
|
31
|
-
writable: true,
|
|
32
|
-
value: undefined
|
|
33
|
-
});
|
|
34
|
-
Object.defineProperty(this, "leftover", {
|
|
35
|
-
enumerable: true,
|
|
36
|
-
configurable: true,
|
|
37
|
-
writable: true,
|
|
38
|
-
value: ''
|
|
21
|
+
value: void 0
|
|
39
22
|
});
|
|
40
23
|
Object.defineProperty(this, "raw", {
|
|
41
24
|
enumerable: true,
|
|
@@ -44,101 +27,27 @@ export class SSEStreamProcessor {
|
|
|
44
27
|
value: void 0
|
|
45
28
|
});
|
|
46
29
|
this.raw = raw;
|
|
30
|
+
this.decoder = createEventDecoder((event) => this.events.push(event));
|
|
47
31
|
}
|
|
48
32
|
/** 处理一个 chunk:转发到 reply.raw + 增量解析事件 */
|
|
49
33
|
processChunk(chunk) {
|
|
50
34
|
// 转发原始 chunk 到客户端
|
|
51
35
|
this.raw.write(chunk);
|
|
52
|
-
|
|
53
|
-
const lines = text.split('\n');
|
|
54
|
-
// 最后一行可能不完整,保留到下次
|
|
55
|
-
this.leftover = lines.pop() || '';
|
|
56
|
-
for (const line of lines) {
|
|
57
|
-
if (line.startsWith('data:')) {
|
|
58
|
-
const d = line.slice(5).trim();
|
|
59
|
-
if (!d || d === '[DONE]')
|
|
60
|
-
continue;
|
|
61
|
-
try {
|
|
62
|
-
const event = JSON.parse(d);
|
|
63
|
-
this.events.push(event);
|
|
64
|
-
this.processEvent(event);
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
// 非 JSON 行跳过
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
36
|
+
this.decoder.write(chunk);
|
|
71
37
|
}
|
|
72
|
-
/**
|
|
38
|
+
/** 收尾残帧(stream end 后调用) */
|
|
73
39
|
flushLeftover() {
|
|
74
|
-
|
|
75
|
-
const d = this.leftover.slice(5).trim();
|
|
76
|
-
if (d && d !== '[DONE]') {
|
|
77
|
-
try {
|
|
78
|
-
const event = JSON.parse(d);
|
|
79
|
-
this.events.push(event);
|
|
80
|
-
this.processEvent(event);
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
// skip
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
this.leftover = '';
|
|
40
|
+
this.decoder.end();
|
|
88
41
|
}
|
|
89
|
-
/**
|
|
90
|
-
processEvent(e) {
|
|
91
|
-
if (e?.type === 'content_block_start') {
|
|
92
|
-
const cb = e.content_block || {};
|
|
93
|
-
this.contentBlocks.set(e.index, {
|
|
94
|
-
type: cb.type,
|
|
95
|
-
text: cb.type === 'text' ? '' : undefined,
|
|
96
|
-
id: cb.id,
|
|
97
|
-
name: cb.name,
|
|
98
|
-
input: cb.type === 'tool_use' ? '' : undefined
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
else if (e?.type === 'content_block_delta') {
|
|
102
|
-
const b = this.contentBlocks.get(e.index);
|
|
103
|
-
if (!b)
|
|
104
|
-
return;
|
|
105
|
-
const d = e.delta || {};
|
|
106
|
-
if (d.type === 'text_delta')
|
|
107
|
-
b.text = (b.text || '') + d.text;
|
|
108
|
-
if (d.type === 'thinking_delta')
|
|
109
|
-
b.text = (b.text || '') + d.thinking;
|
|
110
|
-
if (d.type === 'input_json_delta')
|
|
111
|
-
b.input = (b.input || '') + (d.partial_json || '');
|
|
112
|
-
}
|
|
113
|
-
else if (e?.type === 'message_delta') {
|
|
114
|
-
this.stopReason = e.delta?.stop_reason || this.stopReason;
|
|
115
|
-
this.usage = e.usage;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
/** 从累积状态构建 ParsedUpstream */
|
|
42
|
+
/** 从累积事件构建 ParsedUpstream */
|
|
119
43
|
getParsedUpstream() {
|
|
120
|
-
|
|
121
|
-
.sort((a, b) => a[0] - b[0])
|
|
122
|
-
.map(([, b]) => {
|
|
123
|
-
if (b.type === 'tool_use') {
|
|
124
|
-
let input = {};
|
|
125
|
-
try {
|
|
126
|
-
input = b.input ? JSON.parse(b.input) : {};
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
input = {};
|
|
130
|
-
}
|
|
131
|
-
return { ...b, input };
|
|
132
|
-
}
|
|
133
|
-
return b;
|
|
134
|
-
});
|
|
135
|
-
return { blocks: ordered, stopReason: this.stopReason, usage: this.usage };
|
|
44
|
+
return parseUpstreamEvents(this.events);
|
|
136
45
|
}
|
|
137
46
|
/** 检测是否有注入的 MCP tool_use */
|
|
138
47
|
hasInjectedToolUse() {
|
|
139
|
-
if (this.stopReason !== 'tool_use')
|
|
140
|
-
return false;
|
|
141
48
|
const parsed = this.getParsedUpstream();
|
|
49
|
+
if (parsed.stopReason !== 'tool_use')
|
|
50
|
+
return false;
|
|
142
51
|
return !!findInjectedCall(parsed);
|
|
143
52
|
}
|
|
144
53
|
}
|
package/dist/utils/sse-writer.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { encodeSSEFrame } from './sse-protocol.js';
|
|
1
2
|
/**
|
|
2
|
-
* SSE 构造器(后端)—— 与 sse-
|
|
3
|
+
* SSE 构造器(后端)—— 与 sse-protocol(帧解析器)互为逆向。
|
|
3
4
|
*
|
|
4
5
|
* 用于 proxy 主动构造并回写合成 SSE 流,让 Claude Code 客户端
|
|
5
6
|
* 将其识别为一次正常的模型文本回答。事件骨架遵循 Anthropic
|
|
@@ -7,7 +8,7 @@
|
|
|
7
8
|
*/
|
|
8
9
|
/** 写单个 SSE 事件:`event: <type>\ndata: {json}\n\n`(Anthropic 双行格式) */
|
|
9
10
|
export function writeSSEEvent(raw, event) {
|
|
10
|
-
raw.write(
|
|
11
|
+
raw.write(encodeSSEFrame({ event: event.type, data: JSON.stringify(event) }));
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
13
14
|
* 把一段文本伪装成模型的正常 text 输出,构造完整合成流写回。
|