@cc-monitoring/proxy-core 0.3.1 → 0.4.1
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 +20 -1
- package/dist/cli/commands/exec.js +31 -42
- package/dist/cli/commands/repair.d.ts +1 -0
- package/dist/cli/commands/repair.js +15 -0
- package/dist/cli/index.js +30 -0
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.B9A39uFv.js → app.g7N9jkzn.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.IHxQqfJH.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DdhC696L.js → VPLocalSearchBox.BHwI475_.js} +1 -1
- package/dist/docs/assets/chunks/{theme.CfB2tOFi.js → theme.FhAJSNDh.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__/data-push.test.js +44 -0
- package/dist/server/__tests__/providers-route.test.js +1 -0
- package/dist/server/__tests__/proxy.test.js +281 -2
- package/dist/server/__tests__/server.test.js +15 -10
- package/dist/server/__tests__/ui-route.test.js +43 -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 +2 -1
- package/dist/server/data-push.js +22 -7
- package/dist/server/index.js +4 -3
- package/dist/server/proxy.js +193 -229
- package/dist/server/ui-route.js +84 -60
- 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-CaPSZBmB.js} +1 -1
- package/dist/ui/assets/{abnf-Cu8RHCHK.js → abnf-DBDOsmne.js} +1 -1
- package/dist/ui/assets/{abnfDiagram-VRR7QNED-BUBToPXF.js → abnfDiagram-VRR7QNED-D8zK__Mj.js} +1 -1
- package/dist/ui/assets/{accesslog-BG-34XOy.js → accesslog-BOLs2Kig.js} +1 -1
- package/dist/ui/assets/{actionscript-iw0HHMGM.js → actionscript-BZYKhS1B.js} +1 -1
- package/dist/ui/assets/{ada-qRqj6VGQ.js → ada-DyacnMpg.js} +1 -1
- package/dist/ui/assets/{angelscript-BeaXyx_P.js → angelscript-CAN6j0H3.js} +1 -1
- package/dist/ui/assets/{apache-CU8d-z9X.js → apache-BE4vouiQ.js} +1 -1
- package/dist/ui/assets/{applescript-d1Wxkqz1.js → applescript-CS88I1yz.js} +1 -1
- package/dist/ui/assets/{arc-BMsPIm3j.js → arc-CTMmdrSV.js} +1 -1
- package/dist/ui/assets/{arcade-CtbgrWTM.js → arcade-B0f0f5SD.js} +1 -1
- package/dist/ui/assets/{architectureDiagram-ZJ3FMSHR-CVjC5TrS.js → architectureDiagram-ZJ3FMSHR-Dtvpnopp.js} +1 -1
- package/dist/ui/assets/{arduino-Bc9L39Hr.js → arduino-Bhm-OSb2.js} +1 -1
- package/dist/ui/assets/{armasm-DuWmpjWR.js → armasm-CEy-mDHc.js} +1 -1
- package/dist/ui/assets/{asciidoc-CDIhFTnx.js → asciidoc-CrZqQBTj.js} +1 -1
- package/dist/ui/assets/{aspectj-SYj-57Es.js → aspectj-B4IlFyyJ.js} +1 -1
- package/dist/ui/assets/{autohotkey-hBi5dq37.js → autohotkey-Cihy-FjA.js} +1 -1
- package/dist/ui/assets/{autoit-BSawXzhg.js → autoit-Dis_JVJq.js} +1 -1
- package/dist/ui/assets/{avrasm-CwYom8Np.js → avrasm-CVhMycHj.js} +1 -1
- package/dist/ui/assets/{awk-BvBRfGo2.js → awk-BCViwLf5.js} +1 -1
- package/dist/ui/assets/{axapta-CqUavA8k.js → axapta-pWB4JVB_.js} +1 -1
- package/dist/ui/assets/{bash-BS_ZnmEu.js → bash-B6Giryub.js} +1 -1
- package/dist/ui/assets/{basic-xbP4IXrN.js → basic-DcrjcHB0.js} +1 -1
- package/dist/ui/assets/{blockDiagram-677ZJIJ3-CmpI3f5p.js → blockDiagram-677ZJIJ3-DfhtgI1r.js} +1 -1
- package/dist/ui/assets/{bnf-BECwu6uW.js → bnf-cpKU0967.js} +1 -1
- package/dist/ui/assets/{brainfuck-QQgu4j4N.js → brainfuck-CFFdk4cM.js} +1 -1
- package/dist/ui/assets/{coq-IDMIFfem.js → c-CW6KPMeI.js} +1 -1
- package/dist/ui/assets/{c-like-DYrFOtXy.js → c-like-CWn59vrg.js} +1 -1
- package/dist/ui/assets/{c4Diagram-LMCZKHZV-B6Hgngz9.js → c4Diagram-LMCZKHZV-D1Oh6k37.js} +1 -1
- package/dist/ui/assets/{cal-CNMrJ6v5.js → cal-8i26_L39.js} +1 -1
- package/dist/ui/assets/{capnproto-DYCKl6oY.js → capnproto-CviwnFBf.js} +1 -1
- package/dist/ui/assets/{ceylon-mb8tRPl0.js → ceylon-CQyc4rWs.js} +1 -1
- package/dist/ui/assets/channel-Da2MvpNG.js +1 -0
- package/dist/ui/assets/{chunk-2Q5K7J3B-LxvQ-G67.js → chunk-2Q5K7J3B-oswPBwIn.js} +1 -1
- package/dist/ui/assets/{chunk-32BRIVSS-DxzKK6Aw.js → chunk-32BRIVSS-B5pU_9b9.js} +1 -1
- package/dist/ui/assets/{chunk-5VM5RSS4-CZEoYJ2W.js → chunk-5VM5RSS4-gvtfMc4w.js} +1 -1
- package/dist/ui/assets/{chunk-EX3LRPZG-DS2PytrN.js → chunk-EX3LRPZG-BkBaDMy4.js} +1 -1
- package/dist/ui/assets/{chunk-JWPE2WC7-UX0Sr1Ie.js → chunk-JWPE2WC7-Ch-C75ar.js} +1 -1
- package/dist/ui/assets/{chunk-MOJQB5TN-YbJgT9t4.js → chunk-MOJQB5TN-BfYhj1jN.js} +1 -1
- package/dist/ui/assets/{chunk-RYQCIY6F-DS2VH_U9.js → chunk-RYQCIY6F-D8izfruP.js} +1 -1
- package/dist/ui/assets/{chunk-V7JOEXUC-CZr0pkI1.js → chunk-V7JOEXUC-CbzHnW90.js} +1 -1
- package/dist/ui/assets/{chunk-VR4S4FIN-50opPAD3.js → chunk-VR4S4FIN-Dr4M5qZA.js} +1 -1
- package/dist/ui/assets/{chunk-XXDRQBXY-DAAX9l7U.js → chunk-XXDRQBXY-QE-R8dRe.js} +1 -1
- package/dist/ui/assets/classDiagram-OUVF2IWQ-mHUiWjcC.js +1 -0
- package/dist/ui/assets/classDiagram-v2-EOCWNBFH-mHUiWjcC.js +1 -0
- package/dist/ui/assets/{clean-C4X7dSkh.js → clean-DZeAtQ7H.js} +1 -1
- package/dist/ui/assets/{clojure-DSg9gUa7.js → clojure-U4ebZ7NQ.js} +1 -1
- package/dist/ui/assets/{clojure-repl-CagRYx7h.js → clojure-repl-B4QSIzUI.js} +1 -1
- package/dist/ui/assets/{cmake-CFdBn53c.js → cmake-UHexZySb.js} +1 -1
- package/dist/ui/assets/{coffeescript-CJZtMOPx.js → coffeescript-Dg56H9Mr.js} +1 -1
- package/dist/ui/assets/{c-BRJEPYra.js → coq-C1g3mm0X.js} +1 -1
- package/dist/ui/assets/{cos-Bx2VJuzG.js → cos-BL4DdyGh.js} +1 -1
- package/dist/ui/assets/{cose-bilkent-JH36ORCC-zWRLsZpZ.js → cose-bilkent-JH36ORCC-BHQslHP3.js} +1 -1
- package/dist/ui/assets/{cpp-CsG6DlC4.js → cpp-keZI-XAd.js} +1 -1
- package/dist/ui/assets/{crmsh-DTy9MnmJ.js → crmsh-DdXYVeeA.js} +1 -1
- package/dist/ui/assets/{crystal-BwgrLrZ1.js → crystal-C4AN0m0I.js} +1 -1
- package/dist/ui/assets/{csharp-B2VeTPAF.js → csharp-COUyKsNR.js} +1 -1
- package/dist/ui/assets/{csp-CTpydNhH.js → csp-DBc-rgSJ.js} +1 -1
- package/dist/ui/assets/{css-B0mMUbpY.js → css-B8m6O_Pw.js} +1 -1
- package/dist/ui/assets/{cynefin-VYW2F7L2-BmjQEj6q.js → cynefin-VYW2F7L2-B3L-WcKn.js} +1 -1
- package/dist/ui/assets/{cynefinDiagram-TSTJHNR4-Dr0Zrke0.js → cynefinDiagram-TSTJHNR4-fzaM4qcZ.js} +1 -1
- package/dist/ui/assets/{d-DjuDZnbI.js → d-dgQN4Rko.js} +1 -1
- package/dist/ui/assets/{dagre-VKFMJZFB-xoTPT2Uu.js → dagre-VKFMJZFB-DJHj16mR.js} +1 -1
- package/dist/ui/assets/{dart-xR3GU9TJ.js → dart-D2Y7LOq-.js} +1 -1
- package/dist/ui/assets/{delphi-bJas5QnG.js → delphi-DaGcSk5A.js} +1 -1
- package/dist/ui/assets/{diagram-FQU43EPY-rL_IU7gU.js → diagram-FQU43EPY-iZEZ1f-R.js} +1 -1
- package/dist/ui/assets/{diagram-G47NLZAW-EcDiCVGj.js → diagram-G47NLZAW-rkQb3r-C.js} +1 -1
- package/dist/ui/assets/{diagram-NH7WQ7WH-CGGXOjev.js → diagram-NH7WQ7WH-B4Fy72tP.js} +1 -1
- package/dist/ui/assets/{diagram-OA4YK3LP-DnE7hDjD.js → diagram-OA4YK3LP-BndmuIBq.js} +1 -1
- package/dist/ui/assets/{diagram-WEI45ONY-CTJH5eD8.js → diagram-WEI45ONY-CwlAiqOe.js} +1 -1
- package/dist/ui/assets/{diff-doJFF3fv.js → diff-prcRV1Y3.js} +1 -1
- package/dist/ui/assets/{django-D3b-owa_.js → django-B1zIoGSx.js} +1 -1
- package/dist/ui/assets/{dns-C42KYV-Z.js → dns-ZxI_aTwc.js} +1 -1
- package/dist/ui/assets/{dockerfile-9KUINc2j.js → dockerfile-Dp_fT6E-.js} +1 -1
- package/dist/ui/assets/{dos-CxnlJ6qp.js → dos-Cuu5c8vv.js} +1 -1
- package/dist/ui/assets/{dsconfig-6CMMCwmY.js → dsconfig-DcGTOhbS.js} +1 -1
- package/dist/ui/assets/{dts-D78rdUIB.js → dts-DCF8VaRk.js} +1 -1
- package/dist/ui/assets/{dust-Dv1uTfJU.js → dust-DeCmZWMK.js} +1 -1
- package/dist/ui/assets/{ebnf-BGbG1cFK.js → ebnf-BHQQcuF_.js} +1 -1
- package/dist/ui/assets/{ebnfDiagram-CCIWWBDH-z2VgRSUV.js → ebnfDiagram-CCIWWBDH-DJ_RuhTm.js} +1 -1
- package/dist/ui/assets/{elixir-ZgAQVY1J.js → elixir-BHmweJ4d.js} +1 -1
- package/dist/ui/assets/{elm-CudiFuNu.js → elm-v76Hd2B3.js} +1 -1
- package/dist/ui/assets/{erDiagram-Q63AITRT-X1TODuRv.js → erDiagram-Q63AITRT-DVZkY5RZ.js} +1 -1
- package/dist/ui/assets/{erb-Bz_NZh6W.js → erb-xvWF5bfx.js} +1 -1
- package/dist/ui/assets/{erlang-DNuj1nb2.js → erlang-CKBMURym.js} +1 -1
- package/dist/ui/assets/{erlang-repl-SP1Gan9W.js → erlang-repl-BjcfXt3Z.js} +1 -1
- package/dist/ui/assets/{excel-0K77uECF.js → excel-Cdrtxhml.js} +1 -1
- package/dist/ui/assets/{fix-CalJq7JD.js → fix-CB-So5So.js} +1 -1
- package/dist/ui/assets/{flix-BlIs11_w.js → flix-VM9AOrq6.js} +1 -1
- package/dist/ui/assets/{flowDiagram-23GEKE2U-DA2dnmc0.js → flowDiagram-23GEKE2U-vyGW67Xm.js} +1 -1
- package/dist/ui/assets/{fortran-ZCobXY2R.js → fortran-CcwJVO8H.js} +1 -1
- package/dist/ui/assets/{fsharp-Be8rwUtc.js → fsharp-DiATpw1u.js} +1 -1
- package/dist/ui/assets/{gams-DUat8frQ.js → gams-Csg9YNPz.js} +1 -1
- package/dist/ui/assets/{ganttDiagram-NO4QXBWP-DdFwaIGZ.js → ganttDiagram-NO4QXBWP-C2TRbwLw.js} +1 -1
- package/dist/ui/assets/{gauss-BB4U88dy.js → gauss-Bc4TC8Wh.js} +1 -1
- package/dist/ui/assets/{gcode-DzeUZuZg.js → gcode-Rig_2OoA.js} +1 -1
- package/dist/ui/assets/{gherkin-B_8vW_BO.js → gherkin-ByBU06QB.js} +1 -1
- package/dist/ui/assets/{gitGraphDiagram-IHSO6WYX-B-Dn8x6I.js → gitGraphDiagram-IHSO6WYX-CEiqfFIF.js} +1 -1
- package/dist/ui/assets/{glsl-DGHGjPC1.js → glsl-C8D6y2Tn.js} +1 -1
- package/dist/ui/assets/{gml-BYEku8Yh.js → gml-PHpGPHbT.js} +1 -1
- package/dist/ui/assets/{go-D8aSgQMc.js → go-BL_o_3ez.js} +1 -1
- package/dist/ui/assets/{golo-CDjCU_jh.js → golo-CWQ6dTUz.js} +1 -1
- package/dist/ui/assets/{gradle-BeUw7tl_.js → gradle-Y_I2KN2z.js} +1 -1
- package/dist/ui/assets/{groovy-5iCQOtR3.js → groovy-JnIv8p2l.js} +1 -1
- package/dist/ui/assets/{haml-BEdL8FJi.js → haml-B8W_h6mZ.js} +1 -1
- package/dist/ui/assets/{handlebars-BuYQNzoK.js → handlebars-DVm8mJuD.js} +1 -1
- package/dist/ui/assets/{haskell-I4FCBcW0.js → haskell-DlDi2Ty7.js} +1 -1
- package/dist/ui/assets/{haxe-yigyKfFr.js → haxe-CftFNVE-.js} +1 -1
- package/dist/ui/assets/{hsp-ZUk4j7d1.js → hsp-C67xnq9C.js} +1 -1
- package/dist/ui/assets/{htmlbars-QYP3lT3u.js → htmlbars-CmJCm67U.js} +1 -1
- package/dist/ui/assets/{http-BJpD1O71.js → http-b-FPEcHP.js} +1 -1
- package/dist/ui/assets/{hy-CIJ1bP6S.js → hy-BWD3ncpN.js} +1 -1
- package/dist/ui/assets/{index-COAgrx1J.js → index-C7s1zgJb.js} +242 -242
- package/dist/ui/assets/{index-BDXWttnT.js → index-D2UBwfSG.js} +3 -3
- package/dist/ui/assets/index-DlsVXaHT.css +10 -0
- package/dist/ui/assets/{infoDiagram-FWYZ7A6U-fTg9eLNt.js → infoDiagram-FWYZ7A6U-C0Px17IN.js} +1 -1
- package/dist/ui/assets/{inform7-DAsu-lC2.js → inform7-C-OYaMO5.js} +1 -1
- package/dist/ui/assets/{ini-Bhz-zHCg.js → ini-CVyYmykw.js} +1 -1
- package/dist/ui/assets/{irpf90-BunhbwBl.js → irpf90-BcpjWXIz.js} +1 -1
- package/dist/ui/assets/{isbl-q9L6hOhP.js → isbl-ZraBBeEr.js} +1 -1
- package/dist/ui/assets/{ishikawaDiagram-FXEZZL3T-B8G0sdgd.js → ishikawaDiagram-FXEZZL3T-BjmTMgpO.js} +1 -1
- package/dist/ui/assets/{java-Iks5Pkau.js → java-D_mE2DT6.js} +1 -1
- package/dist/ui/assets/{javascript-C4vltXPw.js → javascript-akXESsox.js} +1 -1
- package/dist/ui/assets/{jboss-cli-BQBvd2X2.js → jboss-cli-CFe3gTDt.js} +1 -1
- package/dist/ui/assets/{journeyDiagram-5HDEW3XC-Crbzgrum.js → journeyDiagram-5HDEW3XC-BpgJUvs6.js} +1 -1
- package/dist/ui/assets/{json-DXK0_jUK.js → json-sjN7AzRC.js} +1 -1
- package/dist/ui/assets/{julia-CCYoBiYK.js → julia-BJJYbUMV.js} +1 -1
- package/dist/ui/assets/{julia-repl-y8v2Oorl.js → julia-repl-BwruD8Ix.js} +1 -1
- package/dist/ui/assets/{kanban-definition-HUTT4EX6-C8sCOsBX.js → kanban-definition-HUTT4EX6-DFlE9edA.js} +1 -1
- package/dist/ui/assets/{kotlin-Bnjk7_fw.js → kotlin-CAIQsLCF.js} +1 -1
- package/dist/ui/assets/{lasso-B-al6x63.js → lasso-sU67h-5u.js} +1 -1
- package/dist/ui/assets/{latex-BUmqlb9r.js → latex-CVX-jP88.js} +1 -1
- package/dist/ui/assets/{ldif-D42RWj6Q.js → ldif-DGM9xbFZ.js} +1 -1
- package/dist/ui/assets/{leaf-CrH4BZ0m.js → leaf-AlB_zmwz.js} +1 -1
- package/dist/ui/assets/{less-upmRlQQW.js → less-CKwfEdZQ.js} +1 -1
- package/dist/ui/assets/{lisp-DHYS22SA.js → lisp-CXYLaAPw.js} +1 -1
- package/dist/ui/assets/{livecodeserver-CeQNmFP3.js → livecodeserver-C02fGGTS.js} +1 -1
- package/dist/ui/assets/{livescript-PJWpY1JI.js → livescript-CBMa8QF_.js} +1 -1
- package/dist/ui/assets/{llvm-BKtKWwCt.js → llvm-WXTIohTC.js} +1 -1
- package/dist/ui/assets/{lsl-RWRLRjk7.js → lsl-4obd2U_I.js} +1 -1
- package/dist/ui/assets/{lua-BFUDiPGm.js → lua-DTSy-TjF.js} +1 -1
- package/dist/ui/assets/{makefile-CUDyOz5D.js → makefile-Bf2UEO0i.js} +1 -1
- package/dist/ui/assets/{markdown-zZCLypc6.js → markdown-BgoGmFfJ.js} +1 -1
- package/dist/ui/assets/{mathematica-BHbxKxnq.js → mathematica-CSiA8KQh.js} +1 -1
- package/dist/ui/assets/{matlab-DlGtg--p.js → matlab-DoMvLsGB.js} +1 -1
- package/dist/ui/assets/{maxima-BBBeS3Ra.js → maxima-BFO4dfZO.js} +1 -1
- package/dist/ui/assets/{mel-nh8j7W_6.js → mel-DyBpmDxt.js} +1 -1
- package/dist/ui/assets/{mercury-DyyD-pqr.js → mercury-OL5G5uU6.js} +1 -1
- package/dist/ui/assets/{mindmap-definition-LN4V7U3C-CJlhDHqM.js → mindmap-definition-LN4V7U3C-s-nUZuCs.js} +1 -1
- package/dist/ui/assets/{mipsasm-hiEhRRiq.js → mipsasm-KQwdm39j.js} +1 -1
- package/dist/ui/assets/{mizar-BZa3iAAL.js → mizar-BqndJ30I.js} +1 -1
- package/dist/ui/assets/{mojolicious-BCIm2V_y.js → mojolicious-Bvc1uJd-.js} +1 -1
- package/dist/ui/assets/{monkey-zmK-7N8b.js → monkey-Dl_gLm7-.js} +1 -1
- package/dist/ui/assets/{moonscript-BsS_Mn3D.js → moonscript-BL6R6eAz.js} +1 -1
- package/dist/ui/assets/{n1ql-D7xVgDP0.js → n1ql-C09iOJfQ.js} +1 -1
- package/dist/ui/assets/{nginx-ct2q4dtd.js → nginx-C7W01nBr.js} +1 -1
- package/dist/ui/assets/{nim-RO0UOmW3.js → nim-Dj78szvD.js} +1 -1
- package/dist/ui/assets/{nix-BcRJxPKH.js → nix-BOtGyPmd.js} +1 -1
- package/dist/ui/assets/{node-repl-DgIefwxW.js → node-repl-19nZvZ4A.js} +1 -1
- package/dist/ui/assets/{nsis-DqHs9QhB.js → nsis-ByCl1zIm.js} +1 -1
- package/dist/ui/assets/{objectivec-BBcWqc7Y.js → objectivec-BhdaT_Jr.js} +1 -1
- package/dist/ui/assets/{ocaml-BExfw7D6.js → ocaml-D_NXvSO7.js} +1 -1
- package/dist/ui/assets/{openscad-CHPRELQb.js → openscad-DOhagvnA.js} +1 -1
- package/dist/ui/assets/{oxygene-DpS9uMJW.js → oxygene-5BnkqMRH.js} +1 -1
- package/dist/ui/assets/{parser3-CjJ_QdBp.js → parser3-jSWlxi8m.js} +1 -1
- package/dist/ui/assets/{pegDiagram-2B236MQR-GM70woGy.js → pegDiagram-2B236MQR-CideH-XT.js} +1 -1
- package/dist/ui/assets/{perl-BSNM2Kt8.js → perl-CfsqjZ4b.js} +1 -1
- package/dist/ui/assets/{pf-Z-hKf_88.js → pf-kOewxO29.js} +1 -1
- package/dist/ui/assets/{pgsql-DDgznxBg.js → pgsql-CXm2Xd-Z.js} +1 -1
- package/dist/ui/assets/{php-BzAhxF-l.js → php-CRiA_dH8.js} +1 -1
- package/dist/ui/assets/{php-template-DkgcKHRc.js → php-template-ByMrxqSd.js} +1 -1
- package/dist/ui/assets/{pieDiagram-ENE6RG2P-Bst7mPyz.js → pieDiagram-ENE6RG2P-CJkCdB38.js} +1 -1
- package/dist/ui/assets/{plaintext-BYEppD0R.js → plaintext-BJx0R6A5.js} +1 -1
- package/dist/ui/assets/{pony-BT_kQd1K.js → pony-CozCHtz4.js} +1 -1
- package/dist/ui/assets/{powershell-BfRsuSsf.js → powershell-BT7gMMgn.js} +1 -1
- package/dist/ui/assets/{processing-DpzWe5Iu.js → processing-FOIxn_W_.js} +1 -1
- package/dist/ui/assets/{profile-BCOhS5cM.js → profile-BsoUuD9w.js} +1 -1
- package/dist/ui/assets/{prolog-OxaCCaW8.js → prolog-Bd3gvQ2N.js} +1 -1
- package/dist/ui/assets/{properties-DMFlA2Ca.js → properties-BWGFdny9.js} +1 -1
- package/dist/ui/assets/{protobuf-CRDFkXvZ.js → protobuf-pQSKoOOY.js} +1 -1
- package/dist/ui/assets/{puppet-DnrVyLzx.js → puppet-DnEN_mgS.js} +1 -1
- package/dist/ui/assets/{purebasic-Dht4Hniv.js → purebasic-BqoOGoRw.js} +1 -1
- package/dist/ui/assets/{python-B0aMirWu.js → python-TeVYomkE.js} +1 -1
- package/dist/ui/assets/{python-repl-BlYDBGa7.js → python-repl-zqu5igFS.js} +1 -1
- package/dist/ui/assets/{q-DzrtW9kT.js → q-CZC9Dltd.js} +1 -1
- package/dist/ui/assets/{qml-DnfQsR3i.js → qml-ZNInP45Q.js} +1 -1
- package/dist/ui/assets/{quadrantDiagram-ABIIQ3AL-DNRYurBT.js → quadrantDiagram-ABIIQ3AL-Dd7PwxsF.js} +1 -1
- package/dist/ui/assets/{r-DGI_ZuTD.js → r-B39DAmkC.js} +1 -1
- package/dist/ui/assets/{railroadDiagram-RFXS5EU6-CmbC3Vz4.js → railroadDiagram-RFXS5EU6-DtO5PVFZ.js} +1 -1
- package/dist/ui/assets/{reasonml-3SohMgh2.js → reasonml-B-ZWFJt_.js} +1 -1
- package/dist/ui/assets/{requirementDiagram-TGXJPOKE-8CxrXHco.js → requirementDiagram-TGXJPOKE-DihF4OTj.js} +1 -1
- package/dist/ui/assets/{rib-DfRSd4Qa.js → rib-CnGG0qMF.js} +1 -1
- package/dist/ui/assets/{roboconf-CQczGdGW.js → roboconf-Ewtfps4u.js} +1 -1
- package/dist/ui/assets/{routeros-DCka-T2i.js → routeros-CPcmP1c7.js} +1 -1
- package/dist/ui/assets/{rsl-Dr8MOwMo.js → rsl-NbjWFbPH.js} +1 -1
- package/dist/ui/assets/{ruby-C2zFSkh_.js → ruby-DWDdy5yE.js} +1 -1
- package/dist/ui/assets/{ruleslanguage-C97YsgQq.js → ruleslanguage-Cv_DZe2r.js} +1 -1
- package/dist/ui/assets/{rust-H3h8kd9A.js → rust-NZnsfER5.js} +1 -1
- package/dist/ui/assets/{sankeyDiagram-HTMAVEWB-DBXLWjEq.js → sankeyDiagram-HTMAVEWB-D6i-Mzte.js} +1 -1
- package/dist/ui/assets/{sas-04z0Xu8P.js → sas-C4wv0P6G.js} +1 -1
- package/dist/ui/assets/{scala-DyB9Aoiv.js → scala-DUdTOIgx.js} +1 -1
- package/dist/ui/assets/{scheme-DBj6nxUi.js → scheme-DEdFa14t.js} +1 -1
- package/dist/ui/assets/{scilab-Btj7AD9s.js → scilab-xY51J2bR.js} +1 -1
- package/dist/ui/assets/{scss-BXZJyXt7.js → scss-BEYp1sXc.js} +1 -1
- package/dist/ui/assets/{sequenceDiagram-DBY2YBRQ-DXIkBFKC.js → sequenceDiagram-DBY2YBRQ-njQlqy_J.js} +1 -1
- package/dist/ui/assets/{shell-BsreQR1Z.js → shell-fq6bkhOw.js} +1 -1
- package/dist/ui/assets/{sizeCapture-X5ZJPWSS-ocS9jxAQ.js → sizeCapture-X5ZJPWSS-tLn70-Fb.js} +1 -1
- package/dist/ui/assets/{smali-D9wQw9zm.js → smali-CsSAuSYg.js} +1 -1
- package/dist/ui/assets/{smalltalk-Dku6G_H3.js → smalltalk-DJ7zrd87.js} +1 -1
- package/dist/ui/assets/{sml-BknyU6ya.js → sml-CnDwl0nH.js} +1 -1
- package/dist/ui/assets/{sqf-DRYMaOg8.js → sqf-Cc2SX4Zy.js} +1 -1
- package/dist/ui/assets/{sql-Cw3Ax4KA.js → sql-DUQA_V_4.js} +1 -1
- package/dist/ui/assets/{sql_more-vWdslLE0.js → sql_more-BHoH-8oO.js} +1 -1
- package/dist/ui/assets/{stan-8XH5bDS6.js → stan-D-7F5jH6.js} +1 -1
- package/dist/ui/assets/{stata-4e77wgfe.js → stata-xKD_DnDE.js} +1 -1
- package/dist/ui/assets/{stateDiagram-2N3HPSRC-RMmL9jMG.js → stateDiagram-2N3HPSRC-B4O8weor.js} +1 -1
- package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-CO881_ht.js +1 -0
- package/dist/ui/assets/{step21-ByIeDMY3.js → step21-obc_kzQY.js} +1 -1
- package/dist/ui/assets/{stylus-ZAhJyWsw.js → stylus-CkAUSRd-.js} +1 -1
- package/dist/ui/assets/{subunit-pPW2UGkj.js → subunit-BDv8PGo1.js} +1 -1
- package/dist/ui/assets/{swift-CX3BB5az.js → swift-CHsYyW-p.js} +1 -1
- package/dist/ui/assets/{swimlanes-5IMT3BWC-C2zAuJ56.js → swimlanes-5IMT3BWC-DSr9Ty4A.js} +2 -2
- package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DFMCDs8b.js +8 -0
- package/dist/ui/assets/{taggerscript-BHcjbWIC.js → taggerscript-C_2JQgO9.js} +1 -1
- package/dist/ui/assets/{tap-BOl1lBlS.js → tap-Bi497Z2c.js} +1 -1
- package/dist/ui/assets/{tcl-DZjeOBDh.js → tcl-B1XMvLaD.js} +1 -1
- package/dist/ui/assets/{thrift-BxboWg4x.js → thrift-D9X0Hmmc.js} +1 -1
- package/dist/ui/assets/{timeline-definition-FHXFAJF6-BOxsxyq_.js → timeline-definition-FHXFAJF6-C4_gj50B.js} +1 -1
- package/dist/ui/assets/{tp-BNM6ql3J.js → tp-CJG4Odbx.js} +1 -1
- package/dist/ui/assets/{twig-Dj9ZiXD4.js → twig-flj72_wc.js} +1 -1
- package/dist/ui/assets/{typescript-7MEJlu_6.js → typescript-CWPwVoLd.js} +1 -1
- package/dist/ui/assets/{vala-DNqOAgHJ.js → vala-LuCNWNuU.js} +1 -1
- package/dist/ui/assets/{vbnet-T0mNKVc_.js → vbnet-CGUT6ss0.js} +1 -1
- package/dist/ui/assets/{vbscript-CeuwVMAI.js → vbscript-CNiUBJhn.js} +1 -1
- package/dist/ui/assets/{vbscript-html-BbJSt2w6.js → vbscript-html-CJGgjjbc.js} +1 -1
- package/dist/ui/assets/{vennDiagram-L72KCM5P-BX9mWeiT.js → vennDiagram-L72KCM5P-BxcAUnYo.js} +1 -1
- package/dist/ui/assets/{verilog-DYuhYfkX.js → verilog-C4f9ZBTK.js} +1 -1
- package/dist/ui/assets/{vhdl-Cf9aT-t7.js → vhdl-CyDQIZve.js} +1 -1
- package/dist/ui/assets/{vim-DciP44K1.js → vim-XAUBqa0M.js} +1 -1
- package/dist/ui/assets/{wardleyDiagram-EHGQE667-CDj2rOzu.js → wardleyDiagram-EHGQE667-DlwSH77q.js} +1 -1
- package/dist/ui/assets/{x86asm-E-AN_LXO.js → x86asm-Cp6vHuUx.js} +1 -1
- package/dist/ui/assets/{xl-CxYLJelN.js → xl-BHgDofIM.js} +1 -1
- package/dist/ui/assets/{xml-yz1SRLuU.js → xml-QloVn4s_.js} +1 -1
- package/dist/ui/assets/{xquery-BLzBF3tV.js → xquery-spJZLmyM.js} +1 -1
- package/dist/ui/assets/{xychartDiagram-FW5EYKEG-Czapk9-Z.js → xychartDiagram-FW5EYKEG-BxGVZcnb.js} +1 -1
- package/dist/ui/assets/{yaml-Cv4Y7iN_.js → yaml-CUju4iq0.js} +1 -1
- package/dist/ui/assets/{zephir-KRcdQfEX.js → zephir-ChVpmD0Y.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/utils/__tests__/abort-signals.test.js +67 -0
- package/dist/utils/__tests__/db-maintenance.test.js +55 -0
- package/dist/utils/__tests__/db-migration.test.js +79 -1
- 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.d.ts +1 -0
- 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 +532 -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__/stats-aggregator.test.d.ts +1 -0
- package/dist/utils/__tests__/stats-aggregator.test.js +114 -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-maintenance.d.ts +8 -0
- package/dist/utils/db-maintenance.js +18 -0
- package/dist/utils/db.d.ts +2 -0
- package/dist/utils/db.js +86 -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 +77 -26
- package/dist/utils/request-writer.js +362 -56
- 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.d.ts +1 -1
- package/dist/utils/stats-aggregator.js +44 -24
- package/dist/utils/tool-injector.js +7 -0
- package/dist/utils/vault.d.ts +111 -0
- package/dist/utils/vault.js +434 -0
- package/ecosystem.config.cjs +2 -1
- package/package.json +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.B6Qfxe6W.js +0 -1
- package/dist/server/middleware/__tests__/request-id.test.js +0 -28
- package/dist/server/middleware/request-id.d.ts +0 -2
- package/dist/server/middleware/request-id.js +0 -12
- 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/server/{middleware/__tests__/request-id.test.d.ts → __tests__/data-push.test.d.ts} +0 -0
- /package/dist/{types/api.js → utils/__tests__/abort-signals.test.d.ts} +0 -0
- /package/dist/{types/log.js → utils/__tests__/db-maintenance.test.d.ts} +0 -0
- /package/dist/utils/__tests__/{knowledge-store.test.d.ts → learn-tasks-db.test.d.ts} +0 -0
- /package/dist/utils/__tests__/{sse-accumulator.test.d.ts → openai-converter.test.d.ts} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export interface
|
|
2
|
-
requestId: string;
|
|
1
|
+
export interface RecordedRequest {
|
|
3
2
|
sessionId: string;
|
|
3
|
+
localRequestId: string;
|
|
4
4
|
timestamp: string;
|
|
5
5
|
apiKey?: string;
|
|
6
6
|
proxyApiKey?: string;
|
|
@@ -13,14 +13,6 @@ export interface RequestData {
|
|
|
13
13
|
headers: Record<string, string>;
|
|
14
14
|
body?: any;
|
|
15
15
|
};
|
|
16
|
-
response?: {
|
|
17
|
-
statusCode: number;
|
|
18
|
-
headers?: Record<string, string>;
|
|
19
|
-
events?: any[];
|
|
20
|
-
completedAt?: string;
|
|
21
|
-
closedAt?: string;
|
|
22
|
-
error?: string;
|
|
23
|
-
};
|
|
24
16
|
}
|
|
25
17
|
export interface TokenUsage {
|
|
26
18
|
input_tokens?: number;
|
|
@@ -44,33 +36,92 @@ export interface RequestSummary {
|
|
|
44
36
|
machineId?: string;
|
|
45
37
|
userAgent?: string;
|
|
46
38
|
usage?: TokenUsage;
|
|
39
|
+
closedAt?: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface RequestRecorder {
|
|
43
|
+
pending(): Promise<void>;
|
|
44
|
+
appendEvent(event: any): void;
|
|
45
|
+
headers(args: {
|
|
46
|
+
statusCode: number;
|
|
47
|
+
headers?: Record<string, string>;
|
|
48
|
+
}): void;
|
|
49
|
+
complete(args: {
|
|
50
|
+
cloudRequestId?: string;
|
|
51
|
+
statusCode: number;
|
|
52
|
+
headers?: Record<string, string>;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
interrupt(args: {
|
|
55
|
+
statusCode: number;
|
|
56
|
+
error: string;
|
|
57
|
+
}): void;
|
|
58
|
+
fail(args: {
|
|
59
|
+
statusCode: number;
|
|
60
|
+
error: string;
|
|
61
|
+
}): void;
|
|
62
|
+
}
|
|
63
|
+
interface LoadedRequest {
|
|
64
|
+
requestId: string;
|
|
65
|
+
sessionId: string;
|
|
66
|
+
timestamp: string;
|
|
67
|
+
apiKey?: string;
|
|
68
|
+
proxyApiKey?: string;
|
|
69
|
+
baseUrl?: string;
|
|
70
|
+
model?: string;
|
|
71
|
+
machineId?: string;
|
|
72
|
+
request: {
|
|
73
|
+
method: string;
|
|
74
|
+
path: string;
|
|
75
|
+
headers: Record<string, string>;
|
|
76
|
+
body?: any;
|
|
77
|
+
};
|
|
78
|
+
response?: {
|
|
79
|
+
statusCode: number;
|
|
80
|
+
headers?: Record<string, string>;
|
|
81
|
+
events?: any[];
|
|
82
|
+
completedAt?: string;
|
|
83
|
+
closedAt?: string;
|
|
84
|
+
error?: string;
|
|
85
|
+
};
|
|
47
86
|
}
|
|
48
|
-
export declare function extractTokenUsage(events: any[] | undefined): TokenUsage | undefined;
|
|
49
|
-
export declare const EVENT_BATCH_SIZE = 10;
|
|
50
87
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
88
|
+
* 判断事件集合是否构成一条完整返回的流。
|
|
89
|
+
* Claude:出现 type === 'message_stop'。
|
|
90
|
+
* OpenAI 兼容:chunk 内 choices[0].finish_reason 非空
|
|
91
|
+
* ([DONE] 不入库,不能作为 DB 判定依据)。
|
|
53
92
|
*/
|
|
54
|
-
export declare function
|
|
55
|
-
index: number;
|
|
56
|
-
type?: string;
|
|
57
|
-
data: unknown;
|
|
58
|
-
}>, startIndex: number): void;
|
|
93
|
+
export declare function isStreamCompleteEvents(events: any[] | undefined): boolean;
|
|
59
94
|
/**
|
|
60
|
-
*
|
|
95
|
+
* 从事件集合按字段合并重建 usage,不做整体覆盖。
|
|
96
|
+
* Claude:message_start.usage(input_tokens / cache_*)为底;
|
|
97
|
+
* message_delta.usage 的字段优先(output_tokens 为主,cache 字段也合入)。
|
|
98
|
+
* OpenAI:取带 .usage 的 chunk(prompt_tokens/completion_tokens)。
|
|
61
99
|
*/
|
|
62
|
-
export declare function
|
|
63
|
-
export declare function
|
|
64
|
-
export declare function
|
|
65
|
-
|
|
66
|
-
|
|
100
|
+
export declare function reconstructUsageFromEvents(events: any[] | undefined): TokenUsage | undefined;
|
|
101
|
+
export declare function createRequestRecorder(meta: RecordedRequest): RequestRecorder;
|
|
102
|
+
export declare function recordIteration(meta: RecordedRequest & {
|
|
103
|
+
response: {
|
|
104
|
+
statusCode: number;
|
|
105
|
+
headers?: Record<string, string>;
|
|
106
|
+
events?: any[];
|
|
107
|
+
};
|
|
108
|
+
}): Promise<void>;
|
|
109
|
+
export declare function loadRequestDB(compositeId: string): Promise<LoadedRequest>;
|
|
67
110
|
export declare function listRequestDB(limit?: number, before?: string): Promise<{
|
|
68
111
|
requests: RequestSummary[];
|
|
69
112
|
hasMore: boolean;
|
|
70
113
|
}>;
|
|
71
114
|
export declare function cleanOldRequestsDB(daysToKeep?: number): Promise<void>;
|
|
72
|
-
export declare function
|
|
115
|
+
export declare function interruptStaleRequestsOnStartup(maxAgeMs?: number): {
|
|
116
|
+
completed: number;
|
|
117
|
+
interrupted: number;
|
|
118
|
+
};
|
|
119
|
+
export declare function repairClosedRequests(): {
|
|
120
|
+
recovered: number;
|
|
121
|
+
tokensFilled: number;
|
|
122
|
+
};
|
|
73
123
|
export declare function loadSessionHistory(sessionId: string): {
|
|
74
124
|
messages: any[];
|
|
75
125
|
system?: any;
|
|
76
126
|
} | null;
|
|
127
|
+
export {};
|
|
@@ -1,62 +1,153 @@
|
|
|
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) {
|
|
31
|
-
insertEventStmt = db.prepare('INSERT INTO response_events (request_id, session_id, event_index, event_type, event_data) VALUES (?, ?, ?, ?, ?)');
|
|
23
|
+
insertEventStmt = db.prepare('INSERT OR IGNORE INTO response_events (request_id, session_id, event_index, event_type, event_data) VALUES (?, ?, ?, ?, ?)');
|
|
32
24
|
}
|
|
33
25
|
for (let i = 0; i < batch.length; i++) {
|
|
34
26
|
const event = batch[i];
|
|
35
27
|
insertEventStmt.run(requestId, sessionId, startIndex + i, event.type ?? null, JSON.stringify(event.data));
|
|
36
28
|
}
|
|
37
29
|
}
|
|
30
|
+
function extractUsage(events) {
|
|
31
|
+
if (!events)
|
|
32
|
+
return undefined;
|
|
33
|
+
const messageDelta = events.find((e) => e?.type === 'message_delta');
|
|
34
|
+
return messageDelta?.usage;
|
|
35
|
+
}
|
|
36
|
+
// --- 流完整性判定与 usage 重建(纯函数,事件数组入参)---
|
|
38
37
|
/**
|
|
39
|
-
*
|
|
38
|
+
* 判断事件集合是否构成一条完整返回的流。
|
|
39
|
+
* Claude:出现 type === 'message_stop'。
|
|
40
|
+
* OpenAI 兼容:chunk 内 choices[0].finish_reason 非空
|
|
41
|
+
* ([DONE] 不入库,不能作为 DB 判定依据)。
|
|
40
42
|
*/
|
|
41
|
-
export function
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
export function isStreamCompleteEvents(events) {
|
|
44
|
+
if (!Array.isArray(events))
|
|
45
|
+
return false;
|
|
46
|
+
return events.some(e => {
|
|
47
|
+
if (!e || typeof e !== 'object')
|
|
48
|
+
return false;
|
|
49
|
+
if (e.type === 'message_stop')
|
|
50
|
+
return true;
|
|
51
|
+
const finishReason = e.choices?.[0]?.finish_reason;
|
|
52
|
+
return finishReason !== undefined && finishReason !== null && finishReason !== '';
|
|
53
|
+
});
|
|
44
54
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (events
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
/**
|
|
56
|
+
* 从事件集合按字段合并重建 usage,不做整体覆盖。
|
|
57
|
+
* Claude:message_start.usage(input_tokens / cache_*)为底;
|
|
58
|
+
* message_delta.usage 的字段优先(output_tokens 为主,cache 字段也合入)。
|
|
59
|
+
* OpenAI:取带 .usage 的 chunk(prompt_tokens/completion_tokens)。
|
|
60
|
+
*/
|
|
61
|
+
export function reconstructUsageFromEvents(events) {
|
|
62
|
+
if (!Array.isArray(events))
|
|
63
|
+
return undefined;
|
|
64
|
+
const usage = {};
|
|
65
|
+
let found = false;
|
|
66
|
+
const merge = (field, value, precedence) => {
|
|
67
|
+
if (typeof value !== 'number')
|
|
68
|
+
return;
|
|
69
|
+
if (precedence || usage[field] === undefined) {
|
|
70
|
+
usage[field] = value;
|
|
71
|
+
found = true;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
for (const e of events) {
|
|
75
|
+
if (!e || typeof e !== 'object')
|
|
76
|
+
continue;
|
|
77
|
+
if (e.type === 'message_start' || e.type === 'message_delta') {
|
|
78
|
+
const u = e.usage;
|
|
79
|
+
if (u && typeof u === 'object') {
|
|
80
|
+
const isDelta = e.type === 'message_delta';
|
|
81
|
+
merge('input_tokens', u.input_tokens, isDelta);
|
|
82
|
+
merge('output_tokens', u.output_tokens, isDelta);
|
|
83
|
+
merge('cache_read_input_tokens', u.cache_read_input_tokens, isDelta);
|
|
84
|
+
merge('cache_creation_input_tokens', u.cache_creation_input_tokens, isDelta);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// OpenAI 兼容:带 usage 的 chunk(event_type 通常为 NULL)
|
|
88
|
+
if (e.usage && typeof e.usage === 'object' && e.type !== 'message_start' && e.type !== 'message_delta') {
|
|
89
|
+
const u = e.usage;
|
|
90
|
+
merge('input_tokens', u.input_tokens ?? u.prompt_tokens, false);
|
|
91
|
+
merge('output_tokens', u.output_tokens ?? u.completion_tokens, false);
|
|
92
|
+
}
|
|
59
93
|
}
|
|
94
|
+
return found ? usage : undefined;
|
|
95
|
+
}
|
|
96
|
+
// 定向加载重建所需事件,禁止全量加载事件流(实测有 8000+ 行):
|
|
97
|
+
// 1) Claude 锚点事件(message_start/message_delta/message_stop,通常仅数行)
|
|
98
|
+
// 2) 尾部 10 条事件(覆盖 OpenAI 的 finish_reason / usage,其 event_type 可能为 NULL)
|
|
99
|
+
function loadTargetedEvents(db, requestId, sessionId) {
|
|
100
|
+
const anchorRows = db.prepare(`
|
|
101
|
+
SELECT event_data FROM response_events
|
|
102
|
+
WHERE request_id = ? AND session_id = ?
|
|
103
|
+
AND event_type IN ('message_start', 'message_delta', 'message_stop')
|
|
104
|
+
ORDER BY event_index ASC
|
|
105
|
+
`).all(requestId, sessionId);
|
|
106
|
+
const tailRows = db.prepare(`
|
|
107
|
+
SELECT event_data FROM response_events
|
|
108
|
+
WHERE request_id = ? AND session_id = ?
|
|
109
|
+
ORDER BY event_index DESC
|
|
110
|
+
LIMIT 10
|
|
111
|
+
`).all(requestId, sessionId);
|
|
112
|
+
const seen = new Set();
|
|
113
|
+
const events = [];
|
|
114
|
+
for (const row of [...anchorRows, ...tailRows]) {
|
|
115
|
+
if (seen.has(row.event_data))
|
|
116
|
+
continue;
|
|
117
|
+
seen.add(row.event_data);
|
|
118
|
+
try {
|
|
119
|
+
events.push(JSON.parse(row.event_data));
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// 忽略损坏行
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return events;
|
|
126
|
+
}
|
|
127
|
+
// 按字段回填 token 列(只补 NULL 列),返回是否有列被更新
|
|
128
|
+
function fillTokenColumns(db, requestId, sessionId, usage) {
|
|
129
|
+
const current = db.prepare(`
|
|
130
|
+
SELECT input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens
|
|
131
|
+
FROM requests WHERE request_id = ? AND session_id = ?
|
|
132
|
+
`).get(requestId, sessionId);
|
|
133
|
+
if (!current)
|
|
134
|
+
return false;
|
|
135
|
+
const pairs = [
|
|
136
|
+
['input_tokens', usage.input_tokens],
|
|
137
|
+
['output_tokens', usage.output_tokens],
|
|
138
|
+
['cache_read_tokens', usage.cache_read_input_tokens],
|
|
139
|
+
['cache_creation_tokens', usage.cache_creation_input_tokens]
|
|
140
|
+
];
|
|
141
|
+
const updatable = pairs.filter(([col, v]) => current[col] === null && typeof v === 'number');
|
|
142
|
+
if (updatable.length === 0)
|
|
143
|
+
return false;
|
|
144
|
+
const setSql = updatable.map(([col]) => `${col} = ?`).join(', ');
|
|
145
|
+
db.prepare(`UPDATE requests SET ${setSql} WHERE request_id = ? AND session_id = ?`).run(...updatable.map(([, v]) => v), requestId, sessionId);
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
function writeCompletedRow(args) {
|
|
149
|
+
const db = getDatabase();
|
|
150
|
+
const { meta } = args;
|
|
60
151
|
const stmt = db.prepare(`
|
|
61
152
|
INSERT OR REPLACE INTO requests (
|
|
62
153
|
request_id, session_id, timestamp, method, path, status_code, response_time,
|
|
@@ -68,24 +159,171 @@ export async function saveRequestDB(sessionId, requestId, data) {
|
|
|
68
159
|
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
|
69
160
|
)
|
|
70
161
|
`);
|
|
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);
|
|
162
|
+
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
|
|
163
|
+
args.completedAt || null, args.closedAt || null, args.error || null);
|
|
75
164
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
165
|
+
function buildSummary(meta, requestId, statusCode, responseTime, usage, withPendingId, closedAt) {
|
|
166
|
+
return {
|
|
167
|
+
requestId,
|
|
168
|
+
sessionId: meta.sessionId,
|
|
169
|
+
compositeId: `${meta.sessionId}:${requestId}`,
|
|
170
|
+
timestamp: meta.timestamp,
|
|
171
|
+
method: meta.request.method,
|
|
172
|
+
path: meta.request.path,
|
|
173
|
+
statusCode,
|
|
174
|
+
responseTime,
|
|
175
|
+
baseUrl: meta.baseUrl,
|
|
176
|
+
model: meta.model,
|
|
177
|
+
machineId: meta.machineId,
|
|
178
|
+
userAgent: meta.request.headers['user-agent'],
|
|
179
|
+
usage,
|
|
180
|
+
pendingId: withPendingId ? `${meta.sessionId}:${meta.localRequestId}` : undefined,
|
|
181
|
+
closedAt
|
|
182
|
+
};
|
|
80
183
|
}
|
|
81
|
-
//
|
|
82
|
-
export function
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
184
|
+
// --- Public API ---
|
|
185
|
+
export function createRequestRecorder(meta) {
|
|
186
|
+
const eventBatch = [];
|
|
187
|
+
const tailBuffer = [];
|
|
188
|
+
let eventIndex = 0;
|
|
189
|
+
const startTime = Date.now();
|
|
190
|
+
let pendingCalled = false;
|
|
191
|
+
// recorder 生命周期开始前的事件行下界。complete() 把事件从 localRequestId 迁到
|
|
192
|
+
// cloudRequestId 时只允许迁移 id 大于它的行:request_id(req-N 计数器)在进程
|
|
193
|
+
// 重启后可能复用,同 localRequestId 的历史残留事件属于别的请求,不能被一起迁走。
|
|
194
|
+
const startRow = getDatabase()
|
|
195
|
+
.prepare('SELECT MAX(id) AS m FROM response_events')
|
|
196
|
+
.get();
|
|
197
|
+
const startEventRowId = startRow.m ?? 0;
|
|
198
|
+
function flushRemaining() {
|
|
199
|
+
if (eventBatch.length > 0) {
|
|
200
|
+
flushEventBatch(meta.sessionId, meta.localRequestId, eventBatch, eventIndex - eventBatch.length);
|
|
201
|
+
eventBatch.length = 0;
|
|
202
|
+
}
|
|
87
203
|
}
|
|
88
|
-
|
|
204
|
+
function appendEvent(event) {
|
|
205
|
+
const entry = { index: eventIndex, type: event?.type, data: event };
|
|
206
|
+
eventBatch.push(entry);
|
|
207
|
+
// Maintain tail buffer (last 5 events for usage extraction)
|
|
208
|
+
tailBuffer.push(event);
|
|
209
|
+
if (tailBuffer.length > 5) {
|
|
210
|
+
tailBuffer.shift();
|
|
211
|
+
}
|
|
212
|
+
// Flush batch to DB when threshold reached
|
|
213
|
+
if (eventBatch.length >= EVENT_BATCH_SIZE) {
|
|
214
|
+
flushEventBatch(meta.sessionId, meta.localRequestId, eventBatch, eventIndex - eventBatch.length + 1);
|
|
215
|
+
eventBatch.length = 0; // Reset batch (memory freed)
|
|
216
|
+
}
|
|
217
|
+
eventIndex++;
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
async pending() {
|
|
221
|
+
if (pendingCalled)
|
|
222
|
+
return;
|
|
223
|
+
pendingCalled = true;
|
|
224
|
+
writeCompletedRow({
|
|
225
|
+
meta,
|
|
226
|
+
requestId: meta.localRequestId,
|
|
227
|
+
statusCode: 0,
|
|
228
|
+
responseTime: 0
|
|
229
|
+
});
|
|
230
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, 0, 0, undefined, false), 'pending');
|
|
231
|
+
},
|
|
232
|
+
appendEvent,
|
|
233
|
+
// 上游响应头到达:回写真实 status_code,状态仍 pending(UI 保留 spinner)
|
|
234
|
+
headers({ statusCode, headers }) {
|
|
235
|
+
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);
|
|
236
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, statusCode, 0, undefined, false, undefined), 'pending');
|
|
237
|
+
},
|
|
238
|
+
async complete({ cloudRequestId, statusCode, headers }) {
|
|
239
|
+
// Flush remaining events in batch
|
|
240
|
+
flushRemaining();
|
|
241
|
+
// Usage synthesis: prefer message_delta, otherwise convert OpenAI-style usage
|
|
242
|
+
let usage = extractUsage(tailBuffer);
|
|
243
|
+
if (!usage) {
|
|
244
|
+
const openaiEvent = tailBuffer.find((e) => e?.usage);
|
|
245
|
+
if (openaiEvent) {
|
|
246
|
+
appendEvent({
|
|
247
|
+
type: 'message_delta',
|
|
248
|
+
usage: {
|
|
249
|
+
output_tokens: openaiEvent.usage.completion_tokens || 0
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
usage = extractUsage(tailBuffer);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Ensure the synthetic event (if any) is written before row replacement
|
|
256
|
+
flushRemaining();
|
|
257
|
+
const completedAt = new Date().toISOString();
|
|
258
|
+
const finalId = cloudRequestId ?? meta.localRequestId;
|
|
259
|
+
const responseTime = Date.now() - startTime;
|
|
260
|
+
const db = getDatabase();
|
|
261
|
+
if (finalId !== meta.localRequestId) {
|
|
262
|
+
const replace = db.transaction(() => {
|
|
263
|
+
// id > startEventRowId:只迁本 recorder 创建后写入的事件,
|
|
264
|
+
// 不迁同 localRequestId 的历史残留事件
|
|
265
|
+
db.prepare('UPDATE response_events SET request_id = ? WHERE request_id = ? AND session_id = ? AND id > ?').run(finalId, meta.localRequestId, meta.sessionId, startEventRowId);
|
|
266
|
+
writeCompletedRow({
|
|
267
|
+
meta, requestId: finalId, statusCode, responseTime, headers, usage, completedAt
|
|
268
|
+
});
|
|
269
|
+
db.prepare('DELETE FROM requests WHERE request_id = ? AND session_id = ?').run(meta.localRequestId, meta.sessionId);
|
|
270
|
+
});
|
|
271
|
+
replace();
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
writeCompletedRow({
|
|
275
|
+
meta, requestId: finalId, statusCode, responseTime, headers, usage, completedAt
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
pushNewRequest(buildSummary(meta, finalId, statusCode, responseTime, usage, finalId !== meta.localRequestId), 'completed');
|
|
279
|
+
},
|
|
280
|
+
// 流被截断/挂死:保留真实 status_code,通过 closed_at + error 标记中断;
|
|
281
|
+
// 同时通过定向 SQL(锚点事件 + 尾部事件)重建 usage 并按字段回填 token
|
|
282
|
+
interrupt({ statusCode, error }) {
|
|
283
|
+
flushRemaining();
|
|
284
|
+
const db = getDatabase();
|
|
285
|
+
const responseTime = Date.now() - startTime;
|
|
286
|
+
const closedAt = new Date().toISOString();
|
|
287
|
+
db.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);
|
|
288
|
+
const events = loadTargetedEvents(db, meta.localRequestId, meta.sessionId);
|
|
289
|
+
const usage = reconstructUsageFromEvents(events);
|
|
290
|
+
if (usage) {
|
|
291
|
+
fillTokenColumns(db, meta.localRequestId, meta.sessionId, usage);
|
|
292
|
+
}
|
|
293
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, statusCode, responseTime, usage, false, closedAt), 'completed');
|
|
294
|
+
},
|
|
295
|
+
fail({ statusCode, error }) {
|
|
296
|
+
const responseTime = Date.now() - startTime;
|
|
297
|
+
const closedAt = new Date().toISOString();
|
|
298
|
+
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);
|
|
299
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, statusCode, responseTime, undefined, false, closedAt), 'completed');
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
// Record an inject loop iteration: completed row + events + push, no pending, responseTime 0
|
|
304
|
+
export async function recordIteration(meta) {
|
|
305
|
+
initDatabase();
|
|
306
|
+
const events = meta.response.events ?? [];
|
|
307
|
+
if (events.length > 0) {
|
|
308
|
+
const batch = events.map((e, i) => ({
|
|
309
|
+
index: i,
|
|
310
|
+
type: e?.type,
|
|
311
|
+
data: e
|
|
312
|
+
}));
|
|
313
|
+
flushEventBatch(meta.sessionId, meta.localRequestId, batch, 0);
|
|
314
|
+
}
|
|
315
|
+
const usage = extractUsage(events);
|
|
316
|
+
const completedAt = new Date().toISOString();
|
|
317
|
+
writeCompletedRow({
|
|
318
|
+
meta,
|
|
319
|
+
requestId: meta.localRequestId,
|
|
320
|
+
statusCode: meta.response.statusCode,
|
|
321
|
+
responseTime: 0,
|
|
322
|
+
headers: meta.response.headers,
|
|
323
|
+
usage,
|
|
324
|
+
completedAt
|
|
325
|
+
});
|
|
326
|
+
pushNewRequest(buildSummary(meta, meta.localRequestId, meta.response.statusCode, 0, usage, false), 'completed');
|
|
89
327
|
}
|
|
90
328
|
// Load single request by compositeId (sessionId:requestId)
|
|
91
329
|
export async function loadRequestDB(compositeId) {
|
|
@@ -165,7 +403,7 @@ export async function listRequestDB(limit = 1000, before) {
|
|
|
165
403
|
SELECT
|
|
166
404
|
request_id, session_id, timestamp, method, path, status_code, response_time,
|
|
167
405
|
api_key, proxy_api_key, base_url, model, machine_id, user_agent,
|
|
168
|
-
input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens
|
|
406
|
+
input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, closed_at, error
|
|
169
407
|
FROM requests
|
|
170
408
|
${whereClause}
|
|
171
409
|
ORDER BY timestamp DESC
|
|
@@ -194,7 +432,9 @@ export async function listRequestDB(limit = 1000, before) {
|
|
|
194
432
|
output_tokens: row.output_tokens,
|
|
195
433
|
cache_read_input_tokens: row.cache_read_tokens,
|
|
196
434
|
cache_creation_input_tokens: row.cache_creation_tokens
|
|
197
|
-
} : undefined
|
|
435
|
+
} : undefined,
|
|
436
|
+
closedAt: row.closed_at || undefined,
|
|
437
|
+
error: row.error || undefined
|
|
198
438
|
})),
|
|
199
439
|
hasMore
|
|
200
440
|
};
|
|
@@ -211,14 +451,80 @@ export async function cleanOldRequestsDB(daysToKeep = 7) {
|
|
|
211
451
|
// Delete response_events first (foreign data), then requests
|
|
212
452
|
db.prepare(`DELETE FROM response_events WHERE request_id IN (SELECT request_id FROM requests WHERE timestamp < ?)`).run(cutoff);
|
|
213
453
|
db.prepare(`DELETE FROM requests WHERE timestamp < ?`).run(cutoff);
|
|
454
|
+
// 例行还页:auto_vacuum 未开启时为 no-op;经 ccm vacuum 开启
|
|
455
|
+
// INCREMENTAL 后,删除产生的空闲页在此廉价归还文件系统。
|
|
456
|
+
db.pragma('incremental_vacuum');
|
|
214
457
|
}
|
|
215
|
-
//
|
|
216
|
-
|
|
458
|
+
// 启动时回收上次进程遗留的僵尸 SSE 行:未完成、未关闭且超龄,逐行分流
|
|
459
|
+
// (status_code 保持原值不动)——事件流完整(message_stop / OpenAI finish_reason)
|
|
460
|
+
// 的走完成语义:写 completed_at,不写 closed_at/error;不完整的维持
|
|
461
|
+
// closed_at + 'interrupted: proxy restarted'。两条路径都按字段回填 token 列。
|
|
462
|
+
export function interruptStaleRequestsOnStartup(maxAgeMs = 5 * 60000) {
|
|
217
463
|
const db = initDatabase();
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
464
|
+
const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
|
|
465
|
+
const rows = db.prepare(`
|
|
466
|
+
SELECT request_id, session_id, timestamp, response_time
|
|
467
|
+
FROM requests
|
|
468
|
+
WHERE completed_at IS NULL AND closed_at IS NULL AND timestamp < ?
|
|
469
|
+
`).all(cutoff);
|
|
470
|
+
let completed = 0;
|
|
471
|
+
let interrupted = 0;
|
|
472
|
+
const nowIso = new Date().toISOString();
|
|
473
|
+
for (const row of rows) {
|
|
474
|
+
const events = loadTargetedEvents(db, row.request_id, row.session_id);
|
|
475
|
+
const usage = reconstructUsageFromEvents(events);
|
|
476
|
+
if (isStreamCompleteEvents(events)) {
|
|
477
|
+
// response_time 原值为 0(pending 占位)时,用 timestamp→现在给合理值
|
|
478
|
+
const responseTime = row.response_time > 0
|
|
479
|
+
? row.response_time
|
|
480
|
+
: Math.max(0, Date.now() - Date.parse(row.timestamp));
|
|
481
|
+
db.prepare('UPDATE requests SET completed_at = ?, response_time = ? WHERE request_id = ? AND session_id = ?').run(nowIso, responseTime, row.request_id, row.session_id);
|
|
482
|
+
completed += 1;
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
db.prepare('UPDATE requests SET closed_at = ?, error = ? WHERE request_id = ? AND session_id = ?').run(nowIso, 'interrupted: proxy restarted', row.request_id, row.session_id);
|
|
486
|
+
interrupted += 1;
|
|
487
|
+
}
|
|
488
|
+
if (usage) {
|
|
489
|
+
fillTokenColumns(db, row.request_id, row.session_id, usage);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return { completed, interrupted };
|
|
493
|
+
}
|
|
494
|
+
// 存量回填(供 CLI repair-requests 使用),幂等可重跑:
|
|
495
|
+
// 扫描 closed_at 非空的行——事件流完整且 completed_at 为空的:清 closed_at/error、
|
|
496
|
+
// 写 completed_at(completed_at 已非空的跳过);对 token 全 NULL 但事件可恢复
|
|
497
|
+
// usage 的行按字段补 token。同样只走定向 SQL。
|
|
498
|
+
export function repairClosedRequests() {
|
|
499
|
+
const db = initDatabase();
|
|
500
|
+
const rows = db.prepare(`
|
|
501
|
+
SELECT
|
|
502
|
+
request_id, session_id, completed_at,
|
|
503
|
+
input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens
|
|
504
|
+
FROM requests
|
|
505
|
+
WHERE closed_at IS NOT NULL
|
|
506
|
+
`).all();
|
|
507
|
+
let recovered = 0;
|
|
508
|
+
let tokensFilled = 0;
|
|
509
|
+
const nowIso = new Date().toISOString();
|
|
510
|
+
for (const row of rows) {
|
|
511
|
+
const events = loadTargetedEvents(db, row.request_id, row.session_id);
|
|
512
|
+
if (row.completed_at === null && isStreamCompleteEvents(events)) {
|
|
513
|
+
db.prepare('UPDATE requests SET closed_at = NULL, error = NULL, completed_at = ? WHERE request_id = ? AND session_id = ?').run(nowIso, row.request_id, row.session_id);
|
|
514
|
+
recovered += 1;
|
|
515
|
+
}
|
|
516
|
+
const allTokensNull = row.input_tokens === null &&
|
|
517
|
+
row.output_tokens === null &&
|
|
518
|
+
row.cache_read_tokens === null &&
|
|
519
|
+
row.cache_creation_tokens === null;
|
|
520
|
+
if (allTokensNull) {
|
|
521
|
+
const usage = reconstructUsageFromEvents(events);
|
|
522
|
+
if (usage && fillTokenColumns(db, row.request_id, row.session_id, usage)) {
|
|
523
|
+
tokensFilled += 1;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
return { recovered, tokensFilled };
|
|
222
528
|
}
|
|
223
529
|
// Load session history for multi-turn chat resume
|
|
224
530
|
// 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;
|