@cc-monitoring/proxy-core 0.4.0 → 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.
Files changed (324) hide show
  1. package/dist/cli/__tests__/commands.test.js +19 -0
  2. package/dist/cli/commands/repair.d.ts +1 -0
  3. package/dist/cli/commands/repair.js +15 -0
  4. package/dist/cli/index.js +30 -0
  5. package/dist/docs/404.html +1 -1
  6. package/dist/docs/assets/{app.DtYNT5zS.js → app.g7N9jkzn.js} +1 -1
  7. package/dist/docs/assets/chunks/{@localSearchIndexroot.C4sjikMO.js → @localSearchIndexroot.IHxQqfJH.js} +1 -1
  8. package/dist/docs/assets/chunks/{VPLocalSearchBox.DpXF9ZAI.js → VPLocalSearchBox.BHwI475_.js} +1 -1
  9. package/dist/docs/assets/chunks/{theme.TS_gUyc7.js → theme.FhAJSNDh.js} +2 -2
  10. package/dist/docs/index.html +2 -2
  11. package/dist/docs/overview.html +2 -2
  12. package/dist/docs/packages-utils.html +2 -2
  13. package/dist/docs/proxy-admin/env-and-build.html +2 -2
  14. package/dist/docs/proxy-admin/index.html +2 -2
  15. package/dist/docs/proxy-admin/layout-and-menu.html +2 -2
  16. package/dist/docs/proxy-admin/pages.html +2 -2
  17. package/dist/docs/proxy-admin/routing-and-auth.html +2 -2
  18. package/dist/docs/proxy-admin/services-and-mock.html +2 -2
  19. package/dist/docs/proxy-cli/api-layer.html +2 -2
  20. package/dist/docs/proxy-cli/app-shell.html +2 -2
  21. package/dist/docs/proxy-cli/components-common.html +2 -2
  22. package/dist/docs/proxy-cli/components-config.html +2 -2
  23. package/dist/docs/proxy-cli/components-requests.html +2 -2
  24. package/dist/docs/proxy-cli/components-stats.html +2 -2
  25. package/dist/docs/proxy-cli/components-status.html +2 -2
  26. package/dist/docs/proxy-cli/data-hooks.html +2 -2
  27. package/dist/docs/proxy-cli/index.html +2 -2
  28. package/dist/docs/proxy-cli/utils-and-i18n.html +2 -2
  29. package/dist/docs/proxy-core/chat-api.html +2 -2
  30. package/dist/docs/proxy-core/cli.html +2 -2
  31. package/dist/docs/proxy-core/config.html +2 -2
  32. package/dist/docs/proxy-core/data-layer.html +2 -2
  33. package/dist/docs/proxy-core/entry.html +2 -2
  34. package/dist/docs/proxy-core/index.html +2 -2
  35. package/dist/docs/proxy-core/pm2.html +2 -2
  36. package/dist/docs/proxy-core/providers.html +2 -2
  37. package/dist/docs/proxy-core/proxy.html +2 -2
  38. package/dist/docs/proxy-core/stats.html +2 -2
  39. package/dist/docs/proxy-core/tool.html +2 -2
  40. package/dist/docs/proxy-core/ui-routes.html +2 -2
  41. package/dist/docs/proxy-core/utilities.html +2 -2
  42. package/dist/docs/quickstart.html +2 -2
  43. package/dist/docs/request-flow.html +2 -2
  44. package/dist/server/__tests__/data-push.test.js +44 -0
  45. package/dist/server/__tests__/proxy.test.js +281 -2
  46. package/dist/server/__tests__/server.test.js +15 -10
  47. package/dist/server/__tests__/ui-route.test.js +43 -0
  48. package/dist/server/data-push.d.ts +2 -0
  49. package/dist/server/data-push.js +22 -0
  50. package/dist/server/index.js +4 -3
  51. package/dist/server/proxy.js +81 -21
  52. package/dist/server/ui-route.js +8 -1
  53. package/dist/ui/assets/{1c-CCx-FOtz.js → 1c-CaPSZBmB.js} +1 -1
  54. package/dist/ui/assets/{abnf-Bwbi42Z8.js → abnf-DBDOsmne.js} +1 -1
  55. package/dist/ui/assets/{abnfDiagram-VRR7QNED-Dm1-8q0E.js → abnfDiagram-VRR7QNED-D8zK__Mj.js} +1 -1
  56. package/dist/ui/assets/{accesslog-DCytz_-m.js → accesslog-BOLs2Kig.js} +1 -1
  57. package/dist/ui/assets/{actionscript-3udf15oh.js → actionscript-BZYKhS1B.js} +1 -1
  58. package/dist/ui/assets/{ada-M5Xa74xG.js → ada-DyacnMpg.js} +1 -1
  59. package/dist/ui/assets/{angelscript-qlrFxfW-.js → angelscript-CAN6j0H3.js} +1 -1
  60. package/dist/ui/assets/{apache-B-sF-DQH.js → apache-BE4vouiQ.js} +1 -1
  61. package/dist/ui/assets/{applescript-4FdcBnbI.js → applescript-CS88I1yz.js} +1 -1
  62. package/dist/ui/assets/{arc-BB3K1enp.js → arc-CTMmdrSV.js} +1 -1
  63. package/dist/ui/assets/{arcade-B_yqWaaG.js → arcade-B0f0f5SD.js} +1 -1
  64. package/dist/ui/assets/{architectureDiagram-ZJ3FMSHR-B39vkY8V.js → architectureDiagram-ZJ3FMSHR-Dtvpnopp.js} +1 -1
  65. package/dist/ui/assets/{arduino-yAcBoTWU.js → arduino-Bhm-OSb2.js} +1 -1
  66. package/dist/ui/assets/{armasm-wIcY84bI.js → armasm-CEy-mDHc.js} +1 -1
  67. package/dist/ui/assets/{asciidoc-Bxnu28-Z.js → asciidoc-CrZqQBTj.js} +1 -1
  68. package/dist/ui/assets/{aspectj-B2cKJA_O.js → aspectj-B4IlFyyJ.js} +1 -1
  69. package/dist/ui/assets/{autohotkey-B_rMWTtE.js → autohotkey-Cihy-FjA.js} +1 -1
  70. package/dist/ui/assets/{autoit-DwcuvMwv.js → autoit-Dis_JVJq.js} +1 -1
  71. package/dist/ui/assets/{avrasm-heGX1PXK.js → avrasm-CVhMycHj.js} +1 -1
  72. package/dist/ui/assets/{awk-BiqCQAEf.js → awk-BCViwLf5.js} +1 -1
  73. package/dist/ui/assets/{axapta-Cv8M-Ih6.js → axapta-pWB4JVB_.js} +1 -1
  74. package/dist/ui/assets/{bash-Divgn3JV.js → bash-B6Giryub.js} +1 -1
  75. package/dist/ui/assets/{basic-B9dnAP55.js → basic-DcrjcHB0.js} +1 -1
  76. package/dist/ui/assets/{blockDiagram-677ZJIJ3-DQ1mf7A_.js → blockDiagram-677ZJIJ3-DfhtgI1r.js} +1 -1
  77. package/dist/ui/assets/{bnf-kIL5mSsP.js → bnf-cpKU0967.js} +1 -1
  78. package/dist/ui/assets/{brainfuck-DqB7xDjH.js → brainfuck-CFFdk4cM.js} +1 -1
  79. package/dist/ui/assets/{coq-6aKUn3zn.js → c-CW6KPMeI.js} +1 -1
  80. package/dist/ui/assets/{c-like-De5MhE7G.js → c-like-CWn59vrg.js} +1 -1
  81. package/dist/ui/assets/{c4Diagram-LMCZKHZV-DQxtYsAx.js → c4Diagram-LMCZKHZV-D1Oh6k37.js} +1 -1
  82. package/dist/ui/assets/{cal-mYdfz9en.js → cal-8i26_L39.js} +1 -1
  83. package/dist/ui/assets/{capnproto-D04CRlOt.js → capnproto-CviwnFBf.js} +1 -1
  84. package/dist/ui/assets/{ceylon-pi9lFCja.js → ceylon-CQyc4rWs.js} +1 -1
  85. package/dist/ui/assets/channel-Da2MvpNG.js +1 -0
  86. package/dist/ui/assets/{chunk-2Q5K7J3B-BDD1nPt8.js → chunk-2Q5K7J3B-oswPBwIn.js} +1 -1
  87. package/dist/ui/assets/{chunk-32BRIVSS-DgeQFBb5.js → chunk-32BRIVSS-B5pU_9b9.js} +1 -1
  88. package/dist/ui/assets/{chunk-5VM5RSS4-C7Xf2SnI.js → chunk-5VM5RSS4-gvtfMc4w.js} +1 -1
  89. package/dist/ui/assets/{chunk-EX3LRPZG-B_3p1HEv.js → chunk-EX3LRPZG-BkBaDMy4.js} +1 -1
  90. package/dist/ui/assets/{chunk-JWPE2WC7-Dvs7u8eY.js → chunk-JWPE2WC7-Ch-C75ar.js} +1 -1
  91. package/dist/ui/assets/{chunk-MOJQB5TN-By21wDCN.js → chunk-MOJQB5TN-BfYhj1jN.js} +1 -1
  92. package/dist/ui/assets/{chunk-RYQCIY6F-6NC700r1.js → chunk-RYQCIY6F-D8izfruP.js} +1 -1
  93. package/dist/ui/assets/{chunk-V7JOEXUC-vEUqZ3rh.js → chunk-V7JOEXUC-CbzHnW90.js} +1 -1
  94. package/dist/ui/assets/{chunk-VR4S4FIN-6tX2dNN9.js → chunk-VR4S4FIN-Dr4M5qZA.js} +1 -1
  95. package/dist/ui/assets/{chunk-XXDRQBXY-qDb2jxAR.js → chunk-XXDRQBXY-QE-R8dRe.js} +1 -1
  96. package/dist/ui/assets/classDiagram-OUVF2IWQ-mHUiWjcC.js +1 -0
  97. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-mHUiWjcC.js +1 -0
  98. package/dist/ui/assets/{clean-CLCsDUl1.js → clean-DZeAtQ7H.js} +1 -1
  99. package/dist/ui/assets/{clojure-dVi5Xifj.js → clojure-U4ebZ7NQ.js} +1 -1
  100. package/dist/ui/assets/{clojure-repl-BO_FpFmF.js → clojure-repl-B4QSIzUI.js} +1 -1
  101. package/dist/ui/assets/{cmake-CP5aJbyK.js → cmake-UHexZySb.js} +1 -1
  102. package/dist/ui/assets/{coffeescript-ZEfu_9pF.js → coffeescript-Dg56H9Mr.js} +1 -1
  103. package/dist/ui/assets/{c-HmsCM6sx.js → coq-C1g3mm0X.js} +1 -1
  104. package/dist/ui/assets/{cos-BohCnRN2.js → cos-BL4DdyGh.js} +1 -1
  105. package/dist/ui/assets/{cose-bilkent-JH36ORCC-DyXCbbro.js → cose-bilkent-JH36ORCC-BHQslHP3.js} +1 -1
  106. package/dist/ui/assets/{cpp-FOgPWPEt.js → cpp-keZI-XAd.js} +1 -1
  107. package/dist/ui/assets/{crmsh-B0OYb-Oe.js → crmsh-DdXYVeeA.js} +1 -1
  108. package/dist/ui/assets/{crystal-CuWb_dXm.js → crystal-C4AN0m0I.js} +1 -1
  109. package/dist/ui/assets/{csharp-BbcqM09j.js → csharp-COUyKsNR.js} +1 -1
  110. package/dist/ui/assets/{csp-rgHnTaDq.js → csp-DBc-rgSJ.js} +1 -1
  111. package/dist/ui/assets/{css-C-ibh7ZG.js → css-B8m6O_Pw.js} +1 -1
  112. package/dist/ui/assets/{cynefin-VYW2F7L2-CkuBhgC4.js → cynefin-VYW2F7L2-B3L-WcKn.js} +1 -1
  113. package/dist/ui/assets/{cynefinDiagram-TSTJHNR4-eycFyDao.js → cynefinDiagram-TSTJHNR4-fzaM4qcZ.js} +1 -1
  114. package/dist/ui/assets/{d-C0gXxJ0O.js → d-dgQN4Rko.js} +1 -1
  115. package/dist/ui/assets/{dagre-VKFMJZFB-DzqX9e49.js → dagre-VKFMJZFB-DJHj16mR.js} +1 -1
  116. package/dist/ui/assets/{dart-C-fTpuUV.js → dart-D2Y7LOq-.js} +1 -1
  117. package/dist/ui/assets/{delphi-Chm0B9xv.js → delphi-DaGcSk5A.js} +1 -1
  118. package/dist/ui/assets/{diagram-FQU43EPY-BEgCqfg1.js → diagram-FQU43EPY-iZEZ1f-R.js} +1 -1
  119. package/dist/ui/assets/{diagram-G47NLZAW-Cw11Vs2v.js → diagram-G47NLZAW-rkQb3r-C.js} +1 -1
  120. package/dist/ui/assets/{diagram-NH7WQ7WH-DSG_UWpP.js → diagram-NH7WQ7WH-B4Fy72tP.js} +1 -1
  121. package/dist/ui/assets/{diagram-OA4YK3LP-CJz-WOaJ.js → diagram-OA4YK3LP-BndmuIBq.js} +1 -1
  122. package/dist/ui/assets/{diagram-WEI45ONY-CBXjBCvc.js → diagram-WEI45ONY-CwlAiqOe.js} +1 -1
  123. package/dist/ui/assets/{diff-C-vyuMSL.js → diff-prcRV1Y3.js} +1 -1
  124. package/dist/ui/assets/{django-CJK7lReT.js → django-B1zIoGSx.js} +1 -1
  125. package/dist/ui/assets/{dns-D02SHjSy.js → dns-ZxI_aTwc.js} +1 -1
  126. package/dist/ui/assets/{dockerfile-trKL1Bqu.js → dockerfile-Dp_fT6E-.js} +1 -1
  127. package/dist/ui/assets/{dos-C52dy-sK.js → dos-Cuu5c8vv.js} +1 -1
  128. package/dist/ui/assets/{dsconfig-MzHgzVrt.js → dsconfig-DcGTOhbS.js} +1 -1
  129. package/dist/ui/assets/{dts-B137dHyX.js → dts-DCF8VaRk.js} +1 -1
  130. package/dist/ui/assets/{dust-BcbM0r5C.js → dust-DeCmZWMK.js} +1 -1
  131. package/dist/ui/assets/{ebnf-DkbpI7bK.js → ebnf-BHQQcuF_.js} +1 -1
  132. package/dist/ui/assets/{ebnfDiagram-CCIWWBDH-aI5uQ7w1.js → ebnfDiagram-CCIWWBDH-DJ_RuhTm.js} +1 -1
  133. package/dist/ui/assets/{elixir-BOtDuqQy.js → elixir-BHmweJ4d.js} +1 -1
  134. package/dist/ui/assets/{elm-DS8Tyyu-.js → elm-v76Hd2B3.js} +1 -1
  135. package/dist/ui/assets/{erDiagram-Q63AITRT-2vCbd4Mm.js → erDiagram-Q63AITRT-DVZkY5RZ.js} +1 -1
  136. package/dist/ui/assets/{erb-CSXECRbn.js → erb-xvWF5bfx.js} +1 -1
  137. package/dist/ui/assets/{erlang-BMxlgKPJ.js → erlang-CKBMURym.js} +1 -1
  138. package/dist/ui/assets/{erlang-repl-DPzlolPg.js → erlang-repl-BjcfXt3Z.js} +1 -1
  139. package/dist/ui/assets/{excel-CW2Uxed3.js → excel-Cdrtxhml.js} +1 -1
  140. package/dist/ui/assets/{fix-UW84SlCs.js → fix-CB-So5So.js} +1 -1
  141. package/dist/ui/assets/{flix-4UGiPULd.js → flix-VM9AOrq6.js} +1 -1
  142. package/dist/ui/assets/{flowDiagram-23GEKE2U-R5PbCbZI.js → flowDiagram-23GEKE2U-vyGW67Xm.js} +1 -1
  143. package/dist/ui/assets/{fortran-nhHsngdu.js → fortran-CcwJVO8H.js} +1 -1
  144. package/dist/ui/assets/{fsharp-CDyZ1ST5.js → fsharp-DiATpw1u.js} +1 -1
  145. package/dist/ui/assets/{gams-DHzkkUie.js → gams-Csg9YNPz.js} +1 -1
  146. package/dist/ui/assets/{ganttDiagram-NO4QXBWP-CGcq4Ie_.js → ganttDiagram-NO4QXBWP-C2TRbwLw.js} +1 -1
  147. package/dist/ui/assets/{gauss-DdhFGyBv.js → gauss-Bc4TC8Wh.js} +1 -1
  148. package/dist/ui/assets/{gcode-ImHh8OLA.js → gcode-Rig_2OoA.js} +1 -1
  149. package/dist/ui/assets/{gherkin-CTWAW-XR.js → gherkin-ByBU06QB.js} +1 -1
  150. package/dist/ui/assets/{gitGraphDiagram-IHSO6WYX-8nM2Z9lD.js → gitGraphDiagram-IHSO6WYX-CEiqfFIF.js} +1 -1
  151. package/dist/ui/assets/{glsl-0_W_27G2.js → glsl-C8D6y2Tn.js} +1 -1
  152. package/dist/ui/assets/{gml-BoDggu2z.js → gml-PHpGPHbT.js} +1 -1
  153. package/dist/ui/assets/{go-DYfFygwl.js → go-BL_o_3ez.js} +1 -1
  154. package/dist/ui/assets/{golo-Mlq-TCg9.js → golo-CWQ6dTUz.js} +1 -1
  155. package/dist/ui/assets/{gradle-BALAinEB.js → gradle-Y_I2KN2z.js} +1 -1
  156. package/dist/ui/assets/{groovy-Dht--dWU.js → groovy-JnIv8p2l.js} +1 -1
  157. package/dist/ui/assets/{haml-DpMrxg0d.js → haml-B8W_h6mZ.js} +1 -1
  158. package/dist/ui/assets/{handlebars-DqHzujNj.js → handlebars-DVm8mJuD.js} +1 -1
  159. package/dist/ui/assets/{haskell-DZSchhkY.js → haskell-DlDi2Ty7.js} +1 -1
  160. package/dist/ui/assets/{haxe-C0zBRjdy.js → haxe-CftFNVE-.js} +1 -1
  161. package/dist/ui/assets/{hsp-D_PwbSv2.js → hsp-C67xnq9C.js} +1 -1
  162. package/dist/ui/assets/{htmlbars-DxAFMG8u.js → htmlbars-CmJCm67U.js} +1 -1
  163. package/dist/ui/assets/{http-DvTRF0Do.js → http-b-FPEcHP.js} +1 -1
  164. package/dist/ui/assets/{hy-lVO-kNyp.js → hy-BWD3ncpN.js} +1 -1
  165. package/dist/ui/assets/{index-Ci23SMK2.js → index-C7s1zgJb.js} +21 -21
  166. package/dist/ui/assets/{index-BbMRVVGt.js → index-D2UBwfSG.js} +3 -3
  167. package/dist/ui/assets/{infoDiagram-FWYZ7A6U-C7WYDlvc.js → infoDiagram-FWYZ7A6U-C0Px17IN.js} +1 -1
  168. package/dist/ui/assets/{inform7-B8Tf2n8v.js → inform7-C-OYaMO5.js} +1 -1
  169. package/dist/ui/assets/{ini-DSoYMaLF.js → ini-CVyYmykw.js} +1 -1
  170. package/dist/ui/assets/{irpf90-RCPdkB14.js → irpf90-BcpjWXIz.js} +1 -1
  171. package/dist/ui/assets/{isbl-C2p75PPj.js → isbl-ZraBBeEr.js} +1 -1
  172. package/dist/ui/assets/{ishikawaDiagram-FXEZZL3T-Cm6jsPlc.js → ishikawaDiagram-FXEZZL3T-BjmTMgpO.js} +1 -1
  173. package/dist/ui/assets/{java-DeY4Yuia.js → java-D_mE2DT6.js} +1 -1
  174. package/dist/ui/assets/{javascript-3uX1CO-H.js → javascript-akXESsox.js} +1 -1
  175. package/dist/ui/assets/{jboss-cli-DgnD8mEc.js → jboss-cli-CFe3gTDt.js} +1 -1
  176. package/dist/ui/assets/{journeyDiagram-5HDEW3XC-DEGV1uA5.js → journeyDiagram-5HDEW3XC-BpgJUvs6.js} +1 -1
  177. package/dist/ui/assets/{json-BV2PmJJp.js → json-sjN7AzRC.js} +1 -1
  178. package/dist/ui/assets/{julia-B-m8kQm7.js → julia-BJJYbUMV.js} +1 -1
  179. package/dist/ui/assets/{julia-repl-C51atU2X.js → julia-repl-BwruD8Ix.js} +1 -1
  180. package/dist/ui/assets/{kanban-definition-HUTT4EX6-BJ4k5iTX.js → kanban-definition-HUTT4EX6-DFlE9edA.js} +1 -1
  181. package/dist/ui/assets/{kotlin-CYBziIgl.js → kotlin-CAIQsLCF.js} +1 -1
  182. package/dist/ui/assets/{lasso-Dw2SBMDW.js → lasso-sU67h-5u.js} +1 -1
  183. package/dist/ui/assets/{latex-Dpd35yke.js → latex-CVX-jP88.js} +1 -1
  184. package/dist/ui/assets/{ldif-Ce9EZU__.js → ldif-DGM9xbFZ.js} +1 -1
  185. package/dist/ui/assets/{leaf-CpkZzQtC.js → leaf-AlB_zmwz.js} +1 -1
  186. package/dist/ui/assets/{less-Uzo7M0FD.js → less-CKwfEdZQ.js} +1 -1
  187. package/dist/ui/assets/{lisp-DWXDlJYm.js → lisp-CXYLaAPw.js} +1 -1
  188. package/dist/ui/assets/{livecodeserver-uEyPEgVJ.js → livecodeserver-C02fGGTS.js} +1 -1
  189. package/dist/ui/assets/{livescript-BQ5f07oK.js → livescript-CBMa8QF_.js} +1 -1
  190. package/dist/ui/assets/{llvm-BAvP-skE.js → llvm-WXTIohTC.js} +1 -1
  191. package/dist/ui/assets/{lsl-DhbiIKu6.js → lsl-4obd2U_I.js} +1 -1
  192. package/dist/ui/assets/{lua-COxeUeLx.js → lua-DTSy-TjF.js} +1 -1
  193. package/dist/ui/assets/{makefile-DhDx-IgL.js → makefile-Bf2UEO0i.js} +1 -1
  194. package/dist/ui/assets/{markdown-DX5_kSxq.js → markdown-BgoGmFfJ.js} +1 -1
  195. package/dist/ui/assets/{mathematica-D351ZddB.js → mathematica-CSiA8KQh.js} +1 -1
  196. package/dist/ui/assets/{matlab-CELqIiwF.js → matlab-DoMvLsGB.js} +1 -1
  197. package/dist/ui/assets/{maxima-B_YljrMm.js → maxima-BFO4dfZO.js} +1 -1
  198. package/dist/ui/assets/{mel-DltsbNS8.js → mel-DyBpmDxt.js} +1 -1
  199. package/dist/ui/assets/{mercury-axX-5Vjj.js → mercury-OL5G5uU6.js} +1 -1
  200. package/dist/ui/assets/{mindmap-definition-LN4V7U3C-Bl1EJo6p.js → mindmap-definition-LN4V7U3C-s-nUZuCs.js} +1 -1
  201. package/dist/ui/assets/{mipsasm-BxmerVwX.js → mipsasm-KQwdm39j.js} +1 -1
  202. package/dist/ui/assets/{mizar-XNHfbpL2.js → mizar-BqndJ30I.js} +1 -1
  203. package/dist/ui/assets/{mojolicious-BR0U_7zk.js → mojolicious-Bvc1uJd-.js} +1 -1
  204. package/dist/ui/assets/{monkey-lLuu9_f-.js → monkey-Dl_gLm7-.js} +1 -1
  205. package/dist/ui/assets/{moonscript-DoaZ3DRQ.js → moonscript-BL6R6eAz.js} +1 -1
  206. package/dist/ui/assets/{n1ql-C6TId6Iu.js → n1ql-C09iOJfQ.js} +1 -1
  207. package/dist/ui/assets/{nginx-BezSG-JT.js → nginx-C7W01nBr.js} +1 -1
  208. package/dist/ui/assets/{nim-Bb0rfXie.js → nim-Dj78szvD.js} +1 -1
  209. package/dist/ui/assets/{nix-o3sJ5-54.js → nix-BOtGyPmd.js} +1 -1
  210. package/dist/ui/assets/{node-repl-Sv5hhcTf.js → node-repl-19nZvZ4A.js} +1 -1
  211. package/dist/ui/assets/{nsis-B45BJFhF.js → nsis-ByCl1zIm.js} +1 -1
  212. package/dist/ui/assets/{objectivec-CzS6zVgh.js → objectivec-BhdaT_Jr.js} +1 -1
  213. package/dist/ui/assets/{ocaml-Bqux7PyP.js → ocaml-D_NXvSO7.js} +1 -1
  214. package/dist/ui/assets/{openscad-4Wf6mF84.js → openscad-DOhagvnA.js} +1 -1
  215. package/dist/ui/assets/{oxygene-Fvwqgkkt.js → oxygene-5BnkqMRH.js} +1 -1
  216. package/dist/ui/assets/{parser3-zEfzT5wv.js → parser3-jSWlxi8m.js} +1 -1
  217. package/dist/ui/assets/{pegDiagram-2B236MQR-Dd4rIztM.js → pegDiagram-2B236MQR-CideH-XT.js} +1 -1
  218. package/dist/ui/assets/{perl-CsS1Gs6o.js → perl-CfsqjZ4b.js} +1 -1
  219. package/dist/ui/assets/{pf-BNH1jO0R.js → pf-kOewxO29.js} +1 -1
  220. package/dist/ui/assets/{pgsql-DqPigHrq.js → pgsql-CXm2Xd-Z.js} +1 -1
  221. package/dist/ui/assets/{php-CdOl9bRs.js → php-CRiA_dH8.js} +1 -1
  222. package/dist/ui/assets/{php-template-DPfirJg2.js → php-template-ByMrxqSd.js} +1 -1
  223. package/dist/ui/assets/{pieDiagram-ENE6RG2P-DGaJNf4S.js → pieDiagram-ENE6RG2P-CJkCdB38.js} +1 -1
  224. package/dist/ui/assets/{plaintext-EHbgBKzw.js → plaintext-BJx0R6A5.js} +1 -1
  225. package/dist/ui/assets/{pony-DmJajtp2.js → pony-CozCHtz4.js} +1 -1
  226. package/dist/ui/assets/{powershell-DfGzdWR6.js → powershell-BT7gMMgn.js} +1 -1
  227. package/dist/ui/assets/{processing-BT0ETgPG.js → processing-FOIxn_W_.js} +1 -1
  228. package/dist/ui/assets/{profile-B3I-x5Lt.js → profile-BsoUuD9w.js} +1 -1
  229. package/dist/ui/assets/{prolog-B_4QJIvI.js → prolog-Bd3gvQ2N.js} +1 -1
  230. package/dist/ui/assets/{properties-BFVI8weS.js → properties-BWGFdny9.js} +1 -1
  231. package/dist/ui/assets/{protobuf-PaF39oZZ.js → protobuf-pQSKoOOY.js} +1 -1
  232. package/dist/ui/assets/{puppet-BDC6Q8VF.js → puppet-DnEN_mgS.js} +1 -1
  233. package/dist/ui/assets/{purebasic-B2ejrOZK.js → purebasic-BqoOGoRw.js} +1 -1
  234. package/dist/ui/assets/{python-BOxtIk9H.js → python-TeVYomkE.js} +1 -1
  235. package/dist/ui/assets/{python-repl-BslBh_Mx.js → python-repl-zqu5igFS.js} +1 -1
  236. package/dist/ui/assets/{q-BPe8WLGW.js → q-CZC9Dltd.js} +1 -1
  237. package/dist/ui/assets/{qml-BazRR6fz.js → qml-ZNInP45Q.js} +1 -1
  238. package/dist/ui/assets/{quadrantDiagram-ABIIQ3AL-BQ7aPkHk.js → quadrantDiagram-ABIIQ3AL-Dd7PwxsF.js} +1 -1
  239. package/dist/ui/assets/{r-C09pGNJC.js → r-B39DAmkC.js} +1 -1
  240. package/dist/ui/assets/{railroadDiagram-RFXS5EU6-sCO9VGvE.js → railroadDiagram-RFXS5EU6-DtO5PVFZ.js} +1 -1
  241. package/dist/ui/assets/{reasonml-S7dzwVL9.js → reasonml-B-ZWFJt_.js} +1 -1
  242. package/dist/ui/assets/{requirementDiagram-TGXJPOKE-CfT5aVZg.js → requirementDiagram-TGXJPOKE-DihF4OTj.js} +1 -1
  243. package/dist/ui/assets/{rib-fM2EwQd4.js → rib-CnGG0qMF.js} +1 -1
  244. package/dist/ui/assets/{roboconf-D7AaeyrW.js → roboconf-Ewtfps4u.js} +1 -1
  245. package/dist/ui/assets/{routeros-c6Q7mKuq.js → routeros-CPcmP1c7.js} +1 -1
  246. package/dist/ui/assets/{rsl-sCpEQBxh.js → rsl-NbjWFbPH.js} +1 -1
  247. package/dist/ui/assets/{ruby-lcKhz2w9.js → ruby-DWDdy5yE.js} +1 -1
  248. package/dist/ui/assets/{ruleslanguage-BW4ATOuX.js → ruleslanguage-Cv_DZe2r.js} +1 -1
  249. package/dist/ui/assets/{rust-BbpU-0VY.js → rust-NZnsfER5.js} +1 -1
  250. package/dist/ui/assets/{sankeyDiagram-HTMAVEWB-CaweCpvN.js → sankeyDiagram-HTMAVEWB-D6i-Mzte.js} +1 -1
  251. package/dist/ui/assets/{sas-BPt5R0dx.js → sas-C4wv0P6G.js} +1 -1
  252. package/dist/ui/assets/{scala-DxW_vqXs.js → scala-DUdTOIgx.js} +1 -1
  253. package/dist/ui/assets/{scheme-T2Q_jWzT.js → scheme-DEdFa14t.js} +1 -1
  254. package/dist/ui/assets/{scilab-DMORg9lV.js → scilab-xY51J2bR.js} +1 -1
  255. package/dist/ui/assets/{scss-t0VsosqT.js → scss-BEYp1sXc.js} +1 -1
  256. package/dist/ui/assets/{sequenceDiagram-DBY2YBRQ-o-H_R4zb.js → sequenceDiagram-DBY2YBRQ-njQlqy_J.js} +1 -1
  257. package/dist/ui/assets/{shell-CnCDa1s9.js → shell-fq6bkhOw.js} +1 -1
  258. package/dist/ui/assets/{sizeCapture-X5ZJPWSS-BNLkHGDS.js → sizeCapture-X5ZJPWSS-tLn70-Fb.js} +1 -1
  259. package/dist/ui/assets/{smali-_n-BxJyG.js → smali-CsSAuSYg.js} +1 -1
  260. package/dist/ui/assets/{smalltalk-B90PXJwK.js → smalltalk-DJ7zrd87.js} +1 -1
  261. package/dist/ui/assets/{sml-fuY7bj-n.js → sml-CnDwl0nH.js} +1 -1
  262. package/dist/ui/assets/{sqf-COpwkyuo.js → sqf-Cc2SX4Zy.js} +1 -1
  263. package/dist/ui/assets/{sql-CXIT0j-x.js → sql-DUQA_V_4.js} +1 -1
  264. package/dist/ui/assets/{sql_more-C1Oxq4rx.js → sql_more-BHoH-8oO.js} +1 -1
  265. package/dist/ui/assets/{stan-BZEpaHeC.js → stan-D-7F5jH6.js} +1 -1
  266. package/dist/ui/assets/{stata-CkBwaiZM.js → stata-xKD_DnDE.js} +1 -1
  267. package/dist/ui/assets/{stateDiagram-2N3HPSRC-BkdnNF7I.js → stateDiagram-2N3HPSRC-B4O8weor.js} +1 -1
  268. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-CO881_ht.js +1 -0
  269. package/dist/ui/assets/{step21-fs9N_U3O.js → step21-obc_kzQY.js} +1 -1
  270. package/dist/ui/assets/{stylus-Bs_9cvKZ.js → stylus-CkAUSRd-.js} +1 -1
  271. package/dist/ui/assets/{subunit-DvgcOCqJ.js → subunit-BDv8PGo1.js} +1 -1
  272. package/dist/ui/assets/{swift-BE4ONsur.js → swift-CHsYyW-p.js} +1 -1
  273. package/dist/ui/assets/{swimlanes-5IMT3BWC-uqTAc7o7.js → swimlanes-5IMT3BWC-DSr9Ty4A.js} +2 -2
  274. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DFMCDs8b.js +8 -0
  275. package/dist/ui/assets/{taggerscript-BhmPJ64C.js → taggerscript-C_2JQgO9.js} +1 -1
  276. package/dist/ui/assets/{tap-DkueIVKV.js → tap-Bi497Z2c.js} +1 -1
  277. package/dist/ui/assets/{tcl-DyXOOkFi.js → tcl-B1XMvLaD.js} +1 -1
  278. package/dist/ui/assets/{thrift-Dhgbk56T.js → thrift-D9X0Hmmc.js} +1 -1
  279. package/dist/ui/assets/{timeline-definition-FHXFAJF6-DBAk9Ouc.js → timeline-definition-FHXFAJF6-C4_gj50B.js} +1 -1
  280. package/dist/ui/assets/{tp-BsXyrRGH.js → tp-CJG4Odbx.js} +1 -1
  281. package/dist/ui/assets/{twig-J0HqIuHw.js → twig-flj72_wc.js} +1 -1
  282. package/dist/ui/assets/{typescript-Dkwvul39.js → typescript-CWPwVoLd.js} +1 -1
  283. package/dist/ui/assets/{vala-CRGnf8aY.js → vala-LuCNWNuU.js} +1 -1
  284. package/dist/ui/assets/{vbnet-BtJAUe3z.js → vbnet-CGUT6ss0.js} +1 -1
  285. package/dist/ui/assets/{vbscript-RgFFNuM3.js → vbscript-CNiUBJhn.js} +1 -1
  286. package/dist/ui/assets/{vbscript-html-DO32Io9Y.js → vbscript-html-CJGgjjbc.js} +1 -1
  287. package/dist/ui/assets/{vennDiagram-L72KCM5P-BJi6y0hh.js → vennDiagram-L72KCM5P-BxcAUnYo.js} +1 -1
  288. package/dist/ui/assets/{verilog-C4h6MLcI.js → verilog-C4f9ZBTK.js} +1 -1
  289. package/dist/ui/assets/{vhdl-DOafePyU.js → vhdl-CyDQIZve.js} +1 -1
  290. package/dist/ui/assets/{vim-BAdTA9TY.js → vim-XAUBqa0M.js} +1 -1
  291. package/dist/ui/assets/{wardleyDiagram-EHGQE667-C7c_4IJ6.js → wardleyDiagram-EHGQE667-DlwSH77q.js} +1 -1
  292. package/dist/ui/assets/{x86asm-BCL6__QH.js → x86asm-Cp6vHuUx.js} +1 -1
  293. package/dist/ui/assets/{xl-qIzE4HOe.js → xl-BHgDofIM.js} +1 -1
  294. package/dist/ui/assets/{xml-DE2sJXYU.js → xml-QloVn4s_.js} +1 -1
  295. package/dist/ui/assets/{xquery-CQ35t92y.js → xquery-spJZLmyM.js} +1 -1
  296. package/dist/ui/assets/{xychartDiagram-FW5EYKEG-D2ILn0jL.js → xychartDiagram-FW5EYKEG-BxGVZcnb.js} +1 -1
  297. package/dist/ui/assets/{yaml-5KaAvG5C.js → yaml-CUju4iq0.js} +1 -1
  298. package/dist/ui/assets/{zephir-CbR3Ryfq.js → zephir-ChVpmD0Y.js} +1 -1
  299. package/dist/ui/index.html +1 -1
  300. package/dist/utils/__tests__/db-maintenance.test.d.ts +1 -0
  301. package/dist/utils/__tests__/db-maintenance.test.js +55 -0
  302. package/dist/utils/__tests__/db-migration.test.js +79 -1
  303. package/dist/utils/__tests__/request-writer.test.js +264 -3
  304. package/dist/utils/__tests__/stats-aggregator.test.d.ts +1 -0
  305. package/dist/utils/__tests__/stats-aggregator.test.js +114 -0
  306. package/dist/utils/db-maintenance.d.ts +8 -0
  307. package/dist/utils/db-maintenance.js +18 -0
  308. package/dist/utils/db.d.ts +1 -0
  309. package/dist/utils/db.js +62 -0
  310. package/dist/utils/request-writer.d.ts +23 -1
  311. package/dist/utils/request-writer.js +200 -14
  312. package/dist/utils/stats-aggregator.d.ts +1 -1
  313. package/dist/utils/stats-aggregator.js +44 -27
  314. package/ecosystem.config.cjs +2 -1
  315. package/package.json +1 -1
  316. package/dist/server/middleware/__tests__/request-id.test.js +0 -28
  317. package/dist/server/middleware/request-id.d.ts +0 -2
  318. package/dist/server/middleware/request-id.js +0 -12
  319. package/dist/ui/assets/channel-ChTtxQDg.js +0 -1
  320. package/dist/ui/assets/classDiagram-OUVF2IWQ-Ccbvamlu.js +0 -1
  321. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-Ccbvamlu.js +0 -1
  322. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-0JnZ1VSQ.js +0 -1
  323. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DQRIIEmi.js +0 -8
  324. /package/dist/server/{middleware/__tests__/request-id.test.d.ts → __tests__/data-push.test.d.ts} +0 -0
@@ -20,7 +20,7 @@ function flushEventBatch(sessionId, requestId, batch, startIndex) {
20
20
  const db = getDatabase();
21
21
  ensureStmtCacheValid(db);
22
22
  if (!insertEventStmt) {
23
- 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 (?, ?, ?, ?, ?)');
24
24
  }
25
25
  for (let i = 0; i < batch.length; i++) {
26
26
  const event = batch[i];
@@ -33,6 +33,118 @@ function extractUsage(events) {
33
33
  const messageDelta = events.find((e) => e?.type === 'message_delta');
34
34
  return messageDelta?.usage;
35
35
  }
36
+ // --- 流完整性判定与 usage 重建(纯函数,事件数组入参)---
37
+ /**
38
+ * 判断事件集合是否构成一条完整返回的流。
39
+ * Claude:出现 type === 'message_stop'。
40
+ * OpenAI 兼容:chunk 内 choices[0].finish_reason 非空
41
+ * ([DONE] 不入库,不能作为 DB 判定依据)。
42
+ */
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
+ });
54
+ }
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
+ }
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
+ }
36
148
  function writeCompletedRow(args) {
37
149
  const db = getDatabase();
38
150
  const { meta } = args;
@@ -76,6 +188,13 @@ export function createRequestRecorder(meta) {
76
188
  let eventIndex = 0;
77
189
  const startTime = Date.now();
78
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;
79
198
  function flushRemaining() {
80
199
  if (eventBatch.length > 0) {
81
200
  flushEventBatch(meta.sessionId, meta.localRequestId, eventBatch, eventIndex - eventBatch.length);
@@ -141,7 +260,9 @@ export function createRequestRecorder(meta) {
141
260
  const db = getDatabase();
142
261
  if (finalId !== meta.localRequestId) {
143
262
  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);
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);
145
266
  writeCompletedRow({
146
267
  meta, requestId: finalId, statusCode, responseTime, headers, usage, completedAt
147
268
  });
@@ -156,13 +277,20 @@ export function createRequestRecorder(meta) {
156
277
  }
157
278
  pushNewRequest(buildSummary(meta, finalId, statusCode, responseTime, usage, finalId !== meta.localRequestId), 'completed');
158
279
  },
159
- // 流被截断/挂死:保留真实 status_code,通过 closed_at + error 标记中断
280
+ // 流被截断/挂死:保留真实 status_code,通过 closed_at + error 标记中断;
281
+ // 同时通过定向 SQL(锚点事件 + 尾部事件)重建 usage 并按字段回填 token
160
282
  interrupt({ statusCode, error }) {
161
283
  flushRemaining();
284
+ const db = getDatabase();
162
285
  const responseTime = Date.now() - startTime;
163
286
  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');
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');
166
294
  },
167
295
  fail({ statusCode, error }) {
168
296
  const responseTime = Date.now() - startTime;
@@ -275,7 +403,7 @@ export async function listRequestDB(limit = 1000, before) {
275
403
  SELECT
276
404
  request_id, session_id, timestamp, method, path, status_code, response_time,
277
405
  api_key, proxy_api_key, base_url, model, machine_id, user_agent,
278
- input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, closed_at
406
+ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens, closed_at, error
279
407
  FROM requests
280
408
  ${whereClause}
281
409
  ORDER BY timestamp DESC
@@ -305,7 +433,8 @@ export async function listRequestDB(limit = 1000, before) {
305
433
  cache_read_input_tokens: row.cache_read_tokens,
306
434
  cache_creation_input_tokens: row.cache_creation_tokens
307
435
  } : undefined,
308
- closedAt: row.closed_at || undefined
436
+ closedAt: row.closed_at || undefined,
437
+ error: row.error || undefined
309
438
  })),
310
439
  hasMore
311
440
  };
@@ -322,23 +451,80 @@ export async function cleanOldRequestsDB(daysToKeep = 7) {
322
451
  // Delete response_events first (foreign data), then requests
323
452
  db.prepare(`DELETE FROM response_events WHERE request_id IN (SELECT request_id FROM requests WHERE timestamp < ?)`).run(cutoff);
324
453
  db.prepare(`DELETE FROM requests WHERE timestamp < ?`).run(cutoff);
454
+ // 例行还页:auto_vacuum 未开启时为 no-op;经 ccm vacuum 开启
455
+ // INCREMENTAL 后,删除产生的空闲页在此廉价归还文件系统。
456
+ db.pragma('incremental_vacuum');
325
457
  }
326
- // 启动时回收上次进程遗留的僵尸 SSE 行:未完成、未关闭且超龄,逐行标记为中断
327
- // (status_code 保持原值不动),返回处理行数
458
+ // 启动时回收上次进程遗留的僵尸 SSE 行:未完成、未关闭且超龄,逐行分流
459
+ // (status_code 保持原值不动)——事件流完整(message_stop / OpenAI finish_reason)
460
+ // 的走完成语义:写 completed_at,不写 closed_at/error;不完整的维持
461
+ // closed_at + 'interrupted: proxy restarted'。两条路径都按字段回填 token 列。
328
462
  export function interruptStaleRequestsOnStartup(maxAgeMs = 5 * 60000) {
329
463
  const db = initDatabase();
330
464
  const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
331
465
  const rows = db.prepare(`
332
- SELECT request_id, session_id
466
+ SELECT request_id, session_id, timestamp, response_time
333
467
  FROM requests
334
468
  WHERE completed_at IS NULL AND closed_at IS NULL AND timestamp < ?
335
469
  `).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 = ?');
470
+ let completed = 0;
471
+ let interrupted = 0;
472
+ const nowIso = new Date().toISOString();
338
473
  for (const row of rows) {
339
- stmt.run(closedAt, 'interrupted: proxy restarted', row.request_id, row.session_id);
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
+ }
340
526
  }
341
- return rows.length;
527
+ return { recovered, tokensFilled };
342
528
  }
343
529
  // Load session history for multi-turn chat resume
344
530
  // Returns the last request's messages + assistant response, to prepend to new messages
@@ -16,6 +16,6 @@ export interface TodayStats {
16
16
  request_count: number;
17
17
  models: Record<string, number>;
18
18
  }
19
- export declare function aggregateStats(): void;
19
+ export declare function aggregateStats(maxDays?: number): void;
20
20
  export declare function getStatsData(since?: string): StatsData;
21
21
  export declare function getTodayStats(since: string): TodayStats;
@@ -1,27 +1,47 @@
1
1
  import { initDatabase } from './db.js';
2
+ // 共用 token 聚合列:小时聚合与今日 totals 同口径,避免列漂移
3
+ const TOKEN_AGG_COLUMNS = `
4
+ SUM(input_tokens) as input_tokens,
5
+ SUM(output_tokens) as output_tokens,
6
+ SUM(cache_read_tokens) as cache_read_tokens,
7
+ SUM(cache_creation_tokens) as cache_creation_tokens,
8
+ COUNT(*) as request_count
9
+ `;
10
+ // Build the UTC hourly key ('YYYY-MM-DD-HH') used as stats.period_key
11
+ function toHourKey(date) {
12
+ return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')}-${String(date.getUTCHours()).padStart(2, '0')}`;
13
+ }
2
14
  // Aggregate stats from requests table (called periodically)
3
15
  // Only stores hourly (UTC) entries — daily aggregation is done on the frontend
4
16
  // using the user's local timezone.
5
- export function aggregateStats() {
17
+ // maxDays: hourly retention window in days. A positive integer shrinks the
18
+ // window (capped at 30); undefined / <=0 falls back to the default 30 days.
19
+ export function aggregateStats(maxDays) {
6
20
  const db = initDatabase();
7
21
  const now = new Date();
8
22
  const nowIso = now.toISOString();
9
- // 30 days of hourly data = 720 entries
10
- const hourlyCutoff = new Date(now.getTime() - 30 * 86400000).toISOString();
23
+ // windowDays days of hourly data (30 days = 720 entries)
24
+ const windowDays = Number.isInteger(maxDays) && maxDays > 0
25
+ ? Math.min(30, maxDays)
26
+ : 30;
27
+ const hourlyCutoff = new Date(now.getTime() - windowDays * 86400000).toISOString();
11
28
  // Aggregate hourly stats using SQLite's built-in strftime (UTC)
12
29
  const hourlyRows = db.prepare(`
13
30
  SELECT
14
31
  strftime('%Y-%m-%d-%H', timestamp) as hour,
15
- SUM(input_tokens) as input_tokens,
16
- SUM(output_tokens) as output_tokens,
17
- SUM(cache_read_tokens) as cache_read_tokens,
18
- SUM(cache_creation_tokens) as cache_creation_tokens,
19
- COUNT(*) as request_count
32
+ ${TOKEN_AGG_COLUMNS}
20
33
  FROM requests
21
34
  WHERE timestamp >= ?
22
- AND closed_at IS NULL
23
35
  GROUP BY hour
24
36
  `).all(hourlyCutoff);
37
+ // Recompute the whole window atomically: drop every hourly snapshot inside
38
+ // the window first (source rows may already have been deleted by cleanup, so
39
+ // an upsert-only pass would leave stale snapshots frozen forever), then
40
+ // re-insert from the requests table.
41
+ // Cutoff key uses UTC methods to match the UTC keys stored in the DB.
42
+ // The two deletes (< key / >= key) together clear every hourly row.
43
+ const cutoffKey = toHourKey(new Date(hourlyCutoff));
44
+ const deleteWindow = db.prepare(`DELETE FROM stats WHERE period = 'hourly' AND period_key >= ?`);
25
45
  // Upsert hourly stats
26
46
  const upsertHourly = db.prepare(`
27
47
  INSERT OR REPLACE INTO stats (
@@ -29,16 +49,19 @@ export function aggregateStats() {
29
49
  cache_read_tokens, cache_creation_tokens, request_count, updated_at
30
50
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
31
51
  `);
32
- for (const row of hourlyRows) {
33
- upsertHourly.run('hourly', row.hour, row.input_tokens || 0, row.output_tokens || 0, row.cache_read_tokens || 0, row.cache_creation_tokens || 0, row.request_count, nowIso);
34
- }
35
- // Clean old hourly entries: compute cutoff key using UTC methods
36
- // to match the UTC keys stored in the DB
37
- const cutoffDate = new Date(hourlyCutoff);
38
- const cutoffKey = `${cutoffDate.getUTCFullYear()}-${String(cutoffDate.getUTCMonth() + 1).padStart(2, '0')}-${String(cutoffDate.getUTCDate()).padStart(2, '0')}-${String(cutoffDate.getUTCHours()).padStart(2, '0')}`;
39
- db.prepare(`DELETE FROM stats WHERE period = 'hourly' AND period_key < ?`).run(cutoffKey);
52
+ // Clean hourly entries outside the recomputation window
53
+ const deleteOldKeys = db.prepare(`DELETE FROM stats WHERE period = 'hourly' AND period_key < ?`);
40
54
  // Clean ALL daily entries (legacy data from old +8h approach)
41
- db.prepare(`DELETE FROM stats WHERE period = 'daily'`).run();
55
+ const deleteDaily = db.prepare(`DELETE FROM stats WHERE period = 'daily'`);
56
+ const recompute = db.transaction(() => {
57
+ deleteWindow.run(cutoffKey);
58
+ for (const row of hourlyRows) {
59
+ upsertHourly.run('hourly', row.hour, row.input_tokens || 0, row.output_tokens || 0, row.cache_read_tokens || 0, row.cache_creation_tokens || 0, row.request_count, nowIso);
60
+ }
61
+ deleteOldKeys.run(cutoffKey);
62
+ deleteDaily.run();
63
+ });
64
+ recompute();
42
65
  // WAL checkpoint to keep WAL file size bounded
43
66
  db.pragma('wal_checkpoint(TRUNCATE)');
44
67
  }
@@ -48,8 +71,7 @@ export function getStatsData(since) {
48
71
  let hourlyRows;
49
72
  if (since) {
50
73
  // Convert since (ISO UTC) to UTC hourly key format for filtering
51
- const sinceDate = new Date(since);
52
- const sinceKey = `${sinceDate.getUTCFullYear()}-${String(sinceDate.getUTCMonth() + 1).padStart(2, '0')}-${String(sinceDate.getUTCDate()).padStart(2, '0')}-${String(sinceDate.getUTCHours()).padStart(2, '0')}`;
74
+ const sinceKey = toHourKey(new Date(since));
53
75
  hourlyRows = db.prepare(`
54
76
  SELECT * FROM stats WHERE period = 'hourly' AND period_key >= ? ORDER BY period_key ASC
55
77
  `).all(sinceKey);
@@ -83,22 +105,17 @@ export function getStatsData(since) {
83
105
  export function getTodayStats(since) {
84
106
  const db = initDatabase();
85
107
  // Totals: SUM tokens + COUNT requests since local midnight
108
+ // 多选的 cache_creation_tokens 在返回映射时忽略
86
109
  const totalRow = db.prepare(`
87
- SELECT
88
- SUM(input_tokens) as input_tokens,
89
- SUM(output_tokens) as output_tokens,
90
- SUM(cache_read_tokens) as cache_read_tokens,
91
- COUNT(*) as request_count
110
+ SELECT ${TOKEN_AGG_COLUMNS}
92
111
  FROM requests
93
112
  WHERE timestamp >= ?
94
- AND closed_at IS NULL
95
113
  `).get(since);
96
114
  // Per-model usage count since local midnight
97
115
  const modelRows = db.prepare(`
98
116
  SELECT model, COUNT(*) as count
99
117
  FROM requests
100
118
  WHERE timestamp >= ?
101
- AND closed_at IS NULL
102
119
  AND model IS NOT NULL AND model != ''
103
120
  GROUP BY model
104
121
  ORDER BY count DESC
@@ -15,7 +15,8 @@ module.exports = {
15
15
  exec_mode: 'fork', // Use fork mode for ESM compatibility
16
16
  autorestart: true,
17
17
  watch: false,
18
- max_memory_restart: '200M',
18
+ // 进程 baseline ~184MB 贴近 200M 线导致频繁 OOM kill,内存增长另排查
19
+ max_memory_restart: '600M',
19
20
  env: {
20
21
  NODE_ENV: 'production',
21
22
  CONFIG_PATH: configPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cc-monitoring/proxy-core",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Claude Code 代理工具 + Token 消耗监控面板",
5
5
  "keywords": [
6
6
  "claude-code-proxy",
@@ -1,28 +0,0 @@
1
- import Fastify from 'fastify';
2
- import { requestIdMiddleware } from '../request-id';
3
- describe('requestIdMiddleware', () => {
4
- let fastify;
5
- beforeEach(async () => {
6
- fastify = Fastify();
7
- await requestIdMiddleware(fastify);
8
- fastify.get('/test', async (request) => ({ id: request.id }));
9
- });
10
- afterEach(async () => {
11
- await fastify.close();
12
- });
13
- it('generates nanoid when x-request-id header is absent', async () => {
14
- const response = await fastify.inject({ method: 'GET', url: '/test' });
15
- const body = JSON.parse(response.body);
16
- expect(body.id).toBeDefined();
17
- expect(body.id.length).toBe(12);
18
- });
19
- it('keeps existing id when x-request-id header is present', async () => {
20
- const response = await fastify.inject({
21
- method: 'GET',
22
- url: '/test',
23
- headers: { 'x-request-id': 'custom-id-123' }
24
- });
25
- const body = JSON.parse(response.body);
26
- expect(body.id).toBe('custom-id-123');
27
- });
28
- });
@@ -1,2 +0,0 @@
1
- import { FastifyInstance } from 'fastify';
2
- export declare const requestIdMiddleware: (fastify: FastifyInstance) => Promise<void>;
@@ -1,12 +0,0 @@
1
- import { nanoid } from 'nanoid';
2
- export const requestIdMiddleware = async (fastify) => {
3
- fastify.addHook('onRequest', async (request) => {
4
- const headerId = request.headers['x-request-id'];
5
- if (headerId) {
6
- request.id = headerId;
7
- }
8
- else {
9
- request.id = nanoid(12);
10
- }
11
- });
12
- };
@@ -1 +0,0 @@
1
- import{aj as o,ak as n}from"./index-Ci23SMK2.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-V7JOEXUC-vEUqZ3rh.js";import{_ as i}from"./index-Ci23SMK2.js";import"./chunk-5VM5RSS4-C7Xf2SnI.js";import"./chunk-XXDRQBXY-qDb2jxAR.js";import"./chunk-VR4S4FIN-6tX2dNN9.js";import"./chunk-32BRIVSS-DgeQFBb5.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-V7JOEXUC-vEUqZ3rh.js";import{_ as i}from"./index-Ci23SMK2.js";import"./chunk-5VM5RSS4-C7Xf2SnI.js";import"./chunk-XXDRQBXY-qDb2jxAR.js";import"./chunk-VR4S4FIN-6tX2dNN9.js";import"./chunk-32BRIVSS-DgeQFBb5.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{s as e,b as r,a,S as s}from"./chunk-EX3LRPZG-B_3p1HEv.js";import{_ as i}from"./index-Ci23SMK2.js";import"./chunk-XXDRQBXY-qDb2jxAR.js";import"./chunk-VR4S4FIN-6tX2dNN9.js";import"./chunk-32BRIVSS-DgeQFBb5.js";var p={parser:a,get db(){return new s(2)},renderer:r,styles:e,init:i(t=>{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute},"init")};export{p as diagram};
@@ -1,8 +0,0 @@
1
- import{c as e,s as r}from"./flowDiagram-23GEKE2U-R5PbCbZI.js";import{_ as a}from"./index-Ci23SMK2.js";import"./chunk-5VM5RSS4-C7Xf2SnI.js";import"./chunk-XXDRQBXY-qDb2jxAR.js";import"./chunk-VR4S4FIN-6tX2dNN9.js";import"./chunk-32BRIVSS-DgeQFBb5.js";import"./channel-ChTtxQDg.js";var o=a(t=>`${r(t)}
2
- .swimlane.cluster rect {
3
- stroke: ${t.clusterBorder} !important;
4
- }
5
- [data-look="neo"].cluster rect {
6
- filter: none;
7
- }
8
- `,"getStyles"),s=o,f=e({defaultLayout:"swimlane",styles:s});export{f as diagram};