@cc-monitoring/proxy-core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. package/dist/cli/__tests__/commands.test.js +1 -1
  2. package/dist/cli/commands/exec.js +31 -42
  3. package/dist/docs/404.html +2 -2
  4. package/dist/docs/assets/{app.Dc46Hlqp.js → app.DtYNT5zS.js} +1 -1
  5. package/dist/docs/assets/chunks/@localSearchIndexroot.C4sjikMO.js +1 -0
  6. package/dist/docs/assets/chunks/{VPLocalSearchBox.Snq5jR6J.js → VPLocalSearchBox.DpXF9ZAI.js} +1 -1
  7. package/dist/docs/assets/chunks/{theme.XLtxGM-l.js → theme.TS_gUyc7.js} +2 -2
  8. package/dist/docs/assets/{proxy-cli_data-hooks.md.w9Oe1OD3.js → proxy-cli_data-hooks.md.Bz8CVbxO.js} +1 -1
  9. package/dist/docs/assets/{proxy-core_ui-routes.md.Dyqkeoiv.js → proxy-core_ui-routes.md.B21t1p7R.js} +1 -1
  10. package/dist/docs/hashmap.json +1 -1
  11. package/dist/docs/index.html +3 -3
  12. package/dist/docs/overview.html +3 -3
  13. package/dist/docs/packages-utils.html +3 -3
  14. package/dist/docs/proxy-admin/env-and-build.html +3 -3
  15. package/dist/docs/proxy-admin/index.html +3 -3
  16. package/dist/docs/proxy-admin/layout-and-menu.html +3 -3
  17. package/dist/docs/proxy-admin/pages.html +3 -3
  18. package/dist/docs/proxy-admin/routing-and-auth.html +3 -3
  19. package/dist/docs/proxy-admin/services-and-mock.html +3 -3
  20. package/dist/docs/proxy-cli/api-layer.html +3 -3
  21. package/dist/docs/proxy-cli/app-shell.html +3 -3
  22. package/dist/docs/proxy-cli/components-common.html +3 -3
  23. package/dist/docs/proxy-cli/components-config.html +3 -3
  24. package/dist/docs/proxy-cli/components-requests.html +3 -3
  25. package/dist/docs/proxy-cli/components-stats.html +3 -3
  26. package/dist/docs/proxy-cli/components-status.html +3 -3
  27. package/dist/docs/proxy-cli/data-hooks.html +5 -5
  28. package/dist/docs/proxy-cli/index.html +3 -3
  29. package/dist/docs/proxy-cli/utils-and-i18n.html +3 -3
  30. package/dist/docs/proxy-core/chat-api.html +3 -3
  31. package/dist/docs/proxy-core/cli.html +3 -3
  32. package/dist/docs/proxy-core/config.html +3 -3
  33. package/dist/docs/proxy-core/data-layer.html +3 -3
  34. package/dist/docs/proxy-core/entry.html +3 -3
  35. package/dist/docs/proxy-core/index.html +3 -3
  36. package/dist/docs/proxy-core/pm2.html +3 -3
  37. package/dist/docs/proxy-core/providers.html +3 -3
  38. package/dist/docs/proxy-core/proxy.html +3 -3
  39. package/dist/docs/proxy-core/stats.html +3 -3
  40. package/dist/docs/proxy-core/tool.html +3 -3
  41. package/dist/docs/proxy-core/ui-routes.html +5 -5
  42. package/dist/docs/proxy-core/utilities.html +3 -3
  43. package/dist/docs/quickstart.html +3 -3
  44. package/dist/docs/request-flow.html +3 -3
  45. package/dist/logger/index.d.ts +0 -3
  46. package/dist/logger/index.js +0 -1
  47. package/dist/mcp-server/index.js +5 -3
  48. package/dist/mcp-server/tools.js +31 -10
  49. package/dist/server/__tests__/providers-route.test.js +1 -0
  50. package/dist/server/auth.d.ts +0 -1
  51. package/dist/server/auth.js +1 -1
  52. package/dist/server/chat-route.js +48 -156
  53. package/dist/server/data-push.d.ts +0 -1
  54. package/dist/server/data-push.js +0 -7
  55. package/dist/server/proxy.js +128 -219
  56. package/dist/server/ui-route.js +76 -59
  57. package/dist/tools/index.d.ts +1 -1
  58. package/dist/tools/index.js +1 -1
  59. package/dist/tools/registry.d.ts +0 -4
  60. package/dist/tools/registry.js +0 -8
  61. package/dist/types/config.d.ts +0 -13
  62. package/dist/types/pm2.d.ts +1 -2
  63. package/dist/ui/assets/{1c-Bx3CHH-I.js → 1c-CCx-FOtz.js} +1 -1
  64. package/dist/ui/assets/{abnf-NN4-iXDM.js → abnf-Bwbi42Z8.js} +1 -1
  65. package/dist/ui/assets/{abnfDiagram-VRR7QNED-CXFZgDk7.js → abnfDiagram-VRR7QNED-Dm1-8q0E.js} +1 -1
  66. package/dist/ui/assets/{accesslog-Bq9x4vSZ.js → accesslog-DCytz_-m.js} +1 -1
  67. package/dist/ui/assets/{actionscript-CeaB6gjT.js → actionscript-3udf15oh.js} +1 -1
  68. package/dist/ui/assets/{ada-DObFDSC6.js → ada-M5Xa74xG.js} +1 -1
  69. package/dist/ui/assets/{angelscript-4pIbuWPH.js → angelscript-qlrFxfW-.js} +1 -1
  70. package/dist/ui/assets/{apache-w0LzP4me.js → apache-B-sF-DQH.js} +1 -1
  71. package/dist/ui/assets/{applescript-DXpD6Cc9.js → applescript-4FdcBnbI.js} +1 -1
  72. package/dist/ui/assets/{arc-Dtt1H4m8.js → arc-BB3K1enp.js} +1 -1
  73. package/dist/ui/assets/{arcade-D_zU9Djr.js → arcade-B_yqWaaG.js} +1 -1
  74. package/dist/ui/assets/{architectureDiagram-ZJ3FMSHR-C0E_eQDM.js → architectureDiagram-ZJ3FMSHR-B39vkY8V.js} +1 -1
  75. package/dist/ui/assets/{arduino-BnmN_xp_.js → arduino-yAcBoTWU.js} +1 -1
  76. package/dist/ui/assets/{armasm-CH_xJaHf.js → armasm-wIcY84bI.js} +1 -1
  77. package/dist/ui/assets/{asciidoc-BlvZZ-hO.js → asciidoc-Bxnu28-Z.js} +1 -1
  78. package/dist/ui/assets/{aspectj-DP5DdFKQ.js → aspectj-B2cKJA_O.js} +1 -1
  79. package/dist/ui/assets/{autohotkey-Cy7dy_B1.js → autohotkey-B_rMWTtE.js} +1 -1
  80. package/dist/ui/assets/{autoit-BmQwjQdM.js → autoit-DwcuvMwv.js} +1 -1
  81. package/dist/ui/assets/{avrasm-fcPy4w1X.js → avrasm-heGX1PXK.js} +1 -1
  82. package/dist/ui/assets/{awk-AlcwGSdk.js → awk-BiqCQAEf.js} +1 -1
  83. package/dist/ui/assets/{axapta-NyMN6Mvz.js → axapta-Cv8M-Ih6.js} +1 -1
  84. package/dist/ui/assets/{bash-Bn3yyTUs.js → bash-Divgn3JV.js} +1 -1
  85. package/dist/ui/assets/{basic-gp9eOjjv.js → basic-B9dnAP55.js} +1 -1
  86. package/dist/ui/assets/{blockDiagram-677ZJIJ3-BHAadGGo.js → blockDiagram-677ZJIJ3-DQ1mf7A_.js} +1 -1
  87. package/dist/ui/assets/{bnf-DRAiK-_J.js → bnf-kIL5mSsP.js} +1 -1
  88. package/dist/ui/assets/{brainfuck-IYgPavhh.js → brainfuck-DqB7xDjH.js} +1 -1
  89. package/dist/ui/assets/{coq-BYVsAo31.js → c-HmsCM6sx.js} +1 -1
  90. package/dist/ui/assets/{c-like-B7T39dtK.js → c-like-De5MhE7G.js} +1 -1
  91. package/dist/ui/assets/{c4Diagram-LMCZKHZV-4cXT8R9f.js → c4Diagram-LMCZKHZV-DQxtYsAx.js} +1 -1
  92. package/dist/ui/assets/{cal-DmXm_WLX.js → cal-mYdfz9en.js} +1 -1
  93. package/dist/ui/assets/{capnproto-Cb-rKd-Z.js → capnproto-D04CRlOt.js} +1 -1
  94. package/dist/ui/assets/{ceylon-Bn2aNwEq.js → ceylon-pi9lFCja.js} +1 -1
  95. package/dist/ui/assets/channel-ChTtxQDg.js +1 -0
  96. package/dist/ui/assets/{chunk-2Q5K7J3B-B3N_AddF.js → chunk-2Q5K7J3B-BDD1nPt8.js} +1 -1
  97. package/dist/ui/assets/{chunk-32BRIVSS-CW7iU3gE.js → chunk-32BRIVSS-DgeQFBb5.js} +1 -1
  98. package/dist/ui/assets/{chunk-5VM5RSS4-M8Ep3dJD.js → chunk-5VM5RSS4-C7Xf2SnI.js} +1 -1
  99. package/dist/ui/assets/{chunk-EX3LRPZG-t2hCXH-v.js → chunk-EX3LRPZG-B_3p1HEv.js} +1 -1
  100. package/dist/ui/assets/{chunk-JWPE2WC7-rQK8maXo.js → chunk-JWPE2WC7-Dvs7u8eY.js} +1 -1
  101. package/dist/ui/assets/{chunk-MOJQB5TN-BpU7vp3L.js → chunk-MOJQB5TN-By21wDCN.js} +1 -1
  102. package/dist/ui/assets/{chunk-RYQCIY6F-CJVNOulR.js → chunk-RYQCIY6F-6NC700r1.js} +1 -1
  103. package/dist/ui/assets/{chunk-V7JOEXUC-B--maww3.js → chunk-V7JOEXUC-vEUqZ3rh.js} +1 -1
  104. package/dist/ui/assets/{chunk-VR4S4FIN-QJ5u9nSh.js → chunk-VR4S4FIN-6tX2dNN9.js} +1 -1
  105. package/dist/ui/assets/{chunk-XXDRQBXY-BcM9JOXa.js → chunk-XXDRQBXY-qDb2jxAR.js} +1 -1
  106. package/dist/ui/assets/classDiagram-OUVF2IWQ-Ccbvamlu.js +1 -0
  107. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-Ccbvamlu.js +1 -0
  108. package/dist/ui/assets/{clean-BCfhFoON.js → clean-CLCsDUl1.js} +1 -1
  109. package/dist/ui/assets/{clojure-DtnBj8eB.js → clojure-dVi5Xifj.js} +1 -1
  110. package/dist/ui/assets/{clojure-repl-D8X-urCW.js → clojure-repl-BO_FpFmF.js} +1 -1
  111. package/dist/ui/assets/{cmake-BH2RXBgt.js → cmake-CP5aJbyK.js} +1 -1
  112. package/dist/ui/assets/{coffeescript-CuoLiQ_d.js → coffeescript-ZEfu_9pF.js} +1 -1
  113. package/dist/ui/assets/{c-Dht0EgwX.js → coq-6aKUn3zn.js} +1 -1
  114. package/dist/ui/assets/{cos-t-cDfrf6.js → cos-BohCnRN2.js} +1 -1
  115. package/dist/ui/assets/{cose-bilkent-JH36ORCC-CYip_9u7.js → cose-bilkent-JH36ORCC-DyXCbbro.js} +1 -1
  116. package/dist/ui/assets/{cpp-Cgv0dQ7g.js → cpp-FOgPWPEt.js} +1 -1
  117. package/dist/ui/assets/{crmsh-7pr1Pq_e.js → crmsh-B0OYb-Oe.js} +1 -1
  118. package/dist/ui/assets/{crystal-BHZFifeV.js → crystal-CuWb_dXm.js} +1 -1
  119. package/dist/ui/assets/{csharp-CVMfBRGF.js → csharp-BbcqM09j.js} +1 -1
  120. package/dist/ui/assets/{csp-NEBRDuZY.js → csp-rgHnTaDq.js} +1 -1
  121. package/dist/ui/assets/{css-B0fbMkoQ.js → css-C-ibh7ZG.js} +1 -1
  122. package/dist/ui/assets/{cynefin-VYW2F7L2-CycR2u2l.js → cynefin-VYW2F7L2-CkuBhgC4.js} +1 -1
  123. package/dist/ui/assets/{cynefinDiagram-TSTJHNR4-CvXYb5em.js → cynefinDiagram-TSTJHNR4-eycFyDao.js} +1 -1
  124. package/dist/ui/assets/{d-AzA6F7Ab.js → d-C0gXxJ0O.js} +1 -1
  125. package/dist/ui/assets/{dagre-VKFMJZFB-6NuSYMRG.js → dagre-VKFMJZFB-DzqX9e49.js} +1 -1
  126. package/dist/ui/assets/{dart-D0VXSwKi.js → dart-C-fTpuUV.js} +1 -1
  127. package/dist/ui/assets/{delphi-B-bkLmCx.js → delphi-Chm0B9xv.js} +1 -1
  128. package/dist/ui/assets/{diagram-FQU43EPY-CNNW_5O7.js → diagram-FQU43EPY-BEgCqfg1.js} +1 -1
  129. package/dist/ui/assets/{diagram-G47NLZAW-C60bRph-.js → diagram-G47NLZAW-Cw11Vs2v.js} +1 -1
  130. package/dist/ui/assets/{diagram-NH7WQ7WH-CwERNWac.js → diagram-NH7WQ7WH-DSG_UWpP.js} +1 -1
  131. package/dist/ui/assets/{diagram-OA4YK3LP-9XSTmf1Z.js → diagram-OA4YK3LP-CJz-WOaJ.js} +1 -1
  132. package/dist/ui/assets/{diagram-WEI45ONY-h8K41_YA.js → diagram-WEI45ONY-CBXjBCvc.js} +1 -1
  133. package/dist/ui/assets/{diff-Ch9RlEn8.js → diff-C-vyuMSL.js} +1 -1
  134. package/dist/ui/assets/{django-C00rhzcB.js → django-CJK7lReT.js} +1 -1
  135. package/dist/ui/assets/{dns-C5MKVde0.js → dns-D02SHjSy.js} +1 -1
  136. package/dist/ui/assets/{dockerfile-BpRaVDMB.js → dockerfile-trKL1Bqu.js} +1 -1
  137. package/dist/ui/assets/{dos-CjQOJ_vn.js → dos-C52dy-sK.js} +1 -1
  138. package/dist/ui/assets/{dsconfig-3zd3UkyN.js → dsconfig-MzHgzVrt.js} +1 -1
  139. package/dist/ui/assets/{dts-Bb6PtK5T.js → dts-B137dHyX.js} +1 -1
  140. package/dist/ui/assets/{dust-BEJKezIa.js → dust-BcbM0r5C.js} +1 -1
  141. package/dist/ui/assets/{ebnf-5-TvfsoC.js → ebnf-DkbpI7bK.js} +1 -1
  142. package/dist/ui/assets/{ebnfDiagram-CCIWWBDH-CRmIjeas.js → ebnfDiagram-CCIWWBDH-aI5uQ7w1.js} +1 -1
  143. package/dist/ui/assets/{elixir-B6gSEyen.js → elixir-BOtDuqQy.js} +1 -1
  144. package/dist/ui/assets/{elm-rR0aqyyf.js → elm-DS8Tyyu-.js} +1 -1
  145. package/dist/ui/assets/{erDiagram-Q63AITRT-DS3jYOq8.js → erDiagram-Q63AITRT-2vCbd4Mm.js} +1 -1
  146. package/dist/ui/assets/{erb-DUu22Jxg.js → erb-CSXECRbn.js} +1 -1
  147. package/dist/ui/assets/{erlang-C0m-R-6W.js → erlang-BMxlgKPJ.js} +1 -1
  148. package/dist/ui/assets/{erlang-repl-B7O2MhlI.js → erlang-repl-DPzlolPg.js} +1 -1
  149. package/dist/ui/assets/{excel-CIqnqFs1.js → excel-CW2Uxed3.js} +1 -1
  150. package/dist/ui/assets/{fix-Ds9tcTzQ.js → fix-UW84SlCs.js} +1 -1
  151. package/dist/ui/assets/{flix-ByzuevTB.js → flix-4UGiPULd.js} +1 -1
  152. package/dist/ui/assets/{flowDiagram-23GEKE2U-B9F3S_Hl.js → flowDiagram-23GEKE2U-R5PbCbZI.js} +1 -1
  153. package/dist/ui/assets/{fortran-DieSVGx5.js → fortran-nhHsngdu.js} +1 -1
  154. package/dist/ui/assets/{fsharp-DGP8m6H3.js → fsharp-CDyZ1ST5.js} +1 -1
  155. package/dist/ui/assets/{gams-BiLGBohb.js → gams-DHzkkUie.js} +1 -1
  156. package/dist/ui/assets/{ganttDiagram-NO4QXBWP-CHiCWnJt.js → ganttDiagram-NO4QXBWP-CGcq4Ie_.js} +1 -1
  157. package/dist/ui/assets/{gauss-Btl1fjJ0.js → gauss-DdhFGyBv.js} +1 -1
  158. package/dist/ui/assets/{gcode-DWl2YoL_.js → gcode-ImHh8OLA.js} +1 -1
  159. package/dist/ui/assets/{gherkin-D42ESIJ2.js → gherkin-CTWAW-XR.js} +1 -1
  160. package/dist/ui/assets/{gitGraphDiagram-IHSO6WYX-0pEKZnJg.js → gitGraphDiagram-IHSO6WYX-8nM2Z9lD.js} +1 -1
  161. package/dist/ui/assets/{glsl-Dx1QhGIM.js → glsl-0_W_27G2.js} +1 -1
  162. package/dist/ui/assets/{gml-f0noEVTB.js → gml-BoDggu2z.js} +1 -1
  163. package/dist/ui/assets/{go-DXT6c-0g.js → go-DYfFygwl.js} +1 -1
  164. package/dist/ui/assets/{golo-D3NuJxTg.js → golo-Mlq-TCg9.js} +1 -1
  165. package/dist/ui/assets/{gradle-CUsTLc_e.js → gradle-BALAinEB.js} +1 -1
  166. package/dist/ui/assets/{groovy-BIkOcIpQ.js → groovy-Dht--dWU.js} +1 -1
  167. package/dist/ui/assets/{haml-C5jI7YVN.js → haml-DpMrxg0d.js} +1 -1
  168. package/dist/ui/assets/{handlebars-UOvbWwDx.js → handlebars-DqHzujNj.js} +1 -1
  169. package/dist/ui/assets/{haskell-DuO_Av2n.js → haskell-DZSchhkY.js} +1 -1
  170. package/dist/ui/assets/{haxe-C0Cg5Hjh.js → haxe-C0zBRjdy.js} +1 -1
  171. package/dist/ui/assets/{hsp-CTDajZig.js → hsp-D_PwbSv2.js} +1 -1
  172. package/dist/ui/assets/{htmlbars-_ITuCkOs.js → htmlbars-DxAFMG8u.js} +1 -1
  173. package/dist/ui/assets/{http-Dr26PHfb.js → http-DvTRF0Do.js} +1 -1
  174. package/dist/ui/assets/{hy-B-ThgV4T.js → hy-lVO-kNyp.js} +1 -1
  175. package/dist/ui/assets/{index-CpQr158p.js → index-BbMRVVGt.js} +3 -3
  176. package/dist/ui/assets/{index-CwcnuNUs.js → index-Ci23SMK2.js} +242 -242
  177. package/dist/ui/assets/index-DlsVXaHT.css +10 -0
  178. package/dist/ui/assets/{infoDiagram-FWYZ7A6U-ClKPOdlx.js → infoDiagram-FWYZ7A6U-C7WYDlvc.js} +1 -1
  179. package/dist/ui/assets/{inform7-D7JYYkX9.js → inform7-B8Tf2n8v.js} +1 -1
  180. package/dist/ui/assets/{ini-BZwCkFAf.js → ini-DSoYMaLF.js} +1 -1
  181. package/dist/ui/assets/{irpf90-omMve0rd.js → irpf90-RCPdkB14.js} +1 -1
  182. package/dist/ui/assets/{isbl-C4xosfum.js → isbl-C2p75PPj.js} +1 -1
  183. package/dist/ui/assets/{ishikawaDiagram-FXEZZL3T-PtbNBMgh.js → ishikawaDiagram-FXEZZL3T-Cm6jsPlc.js} +1 -1
  184. package/dist/ui/assets/{java-CWjWDe7Q.js → java-DeY4Yuia.js} +1 -1
  185. package/dist/ui/assets/{javascript-C3dxrGuA.js → javascript-3uX1CO-H.js} +1 -1
  186. package/dist/ui/assets/{jboss-cli-CJE7m0Y-.js → jboss-cli-DgnD8mEc.js} +1 -1
  187. package/dist/ui/assets/{journeyDiagram-5HDEW3XC-DgK9V4yg.js → journeyDiagram-5HDEW3XC-DEGV1uA5.js} +1 -1
  188. package/dist/ui/assets/{json-DFUiNV7v.js → json-BV2PmJJp.js} +1 -1
  189. package/dist/ui/assets/{julia-CUTHpx8X.js → julia-B-m8kQm7.js} +1 -1
  190. package/dist/ui/assets/{julia-repl-_ZaQqdrz.js → julia-repl-C51atU2X.js} +1 -1
  191. package/dist/ui/assets/{kanban-definition-HUTT4EX6-BFrDfKdv.js → kanban-definition-HUTT4EX6-BJ4k5iTX.js} +1 -1
  192. package/dist/ui/assets/{kotlin-CrYjQYp8.js → kotlin-CYBziIgl.js} +1 -1
  193. package/dist/ui/assets/{lasso-CAiVg9m2.js → lasso-Dw2SBMDW.js} +1 -1
  194. package/dist/ui/assets/{latex-BkxnXIrT.js → latex-Dpd35yke.js} +1 -1
  195. package/dist/ui/assets/{ldif-CBOqxiN7.js → ldif-Ce9EZU__.js} +1 -1
  196. package/dist/ui/assets/{leaf-CbBZyOGH.js → leaf-CpkZzQtC.js} +1 -1
  197. package/dist/ui/assets/{less-Ca6uLPP0.js → less-Uzo7M0FD.js} +1 -1
  198. package/dist/ui/assets/{lisp-0Cm7_Bzv.js → lisp-DWXDlJYm.js} +1 -1
  199. package/dist/ui/assets/{livecodeserver-B7ka0vFT.js → livecodeserver-uEyPEgVJ.js} +1 -1
  200. package/dist/ui/assets/{livescript-CGmWmcLd.js → livescript-BQ5f07oK.js} +1 -1
  201. package/dist/ui/assets/{llvm-DCVMvkrH.js → llvm-BAvP-skE.js} +1 -1
  202. package/dist/ui/assets/{lsl-PVrTScpn.js → lsl-DhbiIKu6.js} +1 -1
  203. package/dist/ui/assets/{lua-BTo3z2Ux.js → lua-COxeUeLx.js} +1 -1
  204. package/dist/ui/assets/{makefile-DJGh9r9C.js → makefile-DhDx-IgL.js} +1 -1
  205. package/dist/ui/assets/{markdown-BOloL-q7.js → markdown-DX5_kSxq.js} +1 -1
  206. package/dist/ui/assets/{mathematica-CtMMQM2V.js → mathematica-D351ZddB.js} +1 -1
  207. package/dist/ui/assets/{matlab-Bfg_AWdR.js → matlab-CELqIiwF.js} +1 -1
  208. package/dist/ui/assets/{maxima-B2cdS7BY.js → maxima-B_YljrMm.js} +1 -1
  209. package/dist/ui/assets/{mel-BvfPvpYI.js → mel-DltsbNS8.js} +1 -1
  210. package/dist/ui/assets/{mercury-B6KgNIai.js → mercury-axX-5Vjj.js} +1 -1
  211. package/dist/ui/assets/{mindmap-definition-LN4V7U3C-BkeXo5If.js → mindmap-definition-LN4V7U3C-Bl1EJo6p.js} +1 -1
  212. package/dist/ui/assets/{mipsasm-Csras-cD.js → mipsasm-BxmerVwX.js} +1 -1
  213. package/dist/ui/assets/{mizar-C3WDI1-X.js → mizar-XNHfbpL2.js} +1 -1
  214. package/dist/ui/assets/{mojolicious-MnD2Whic.js → mojolicious-BR0U_7zk.js} +1 -1
  215. package/dist/ui/assets/{monkey-DLvUPYTI.js → monkey-lLuu9_f-.js} +1 -1
  216. package/dist/ui/assets/{moonscript-B0XEb3R3.js → moonscript-DoaZ3DRQ.js} +1 -1
  217. package/dist/ui/assets/{n1ql-BMRF54sY.js → n1ql-C6TId6Iu.js} +1 -1
  218. package/dist/ui/assets/{nginx-DqUyeHb8.js → nginx-BezSG-JT.js} +1 -1
  219. package/dist/ui/assets/{nim-3xwg8mOL.js → nim-Bb0rfXie.js} +1 -1
  220. package/dist/ui/assets/{nix-ByTkLdcH.js → nix-o3sJ5-54.js} +1 -1
  221. package/dist/ui/assets/{node-repl-sGSuIUFG.js → node-repl-Sv5hhcTf.js} +1 -1
  222. package/dist/ui/assets/{nsis-Dng5mFSM.js → nsis-B45BJFhF.js} +1 -1
  223. package/dist/ui/assets/{objectivec-DSQ8vb7n.js → objectivec-CzS6zVgh.js} +1 -1
  224. package/dist/ui/assets/{ocaml-BHOhEgRu.js → ocaml-Bqux7PyP.js} +1 -1
  225. package/dist/ui/assets/{openscad-DcUxQ-FQ.js → openscad-4Wf6mF84.js} +1 -1
  226. package/dist/ui/assets/{oxygene-DNlmqhsR.js → oxygene-Fvwqgkkt.js} +1 -1
  227. package/dist/ui/assets/{parser3-DIR98Q6n.js → parser3-zEfzT5wv.js} +1 -1
  228. package/dist/ui/assets/{pegDiagram-2B236MQR-BrXp_1_9.js → pegDiagram-2B236MQR-Dd4rIztM.js} +1 -1
  229. package/dist/ui/assets/{perl-16cY7fyu.js → perl-CsS1Gs6o.js} +1 -1
  230. package/dist/ui/assets/{pf-KrAq2BW7.js → pf-BNH1jO0R.js} +1 -1
  231. package/dist/ui/assets/{pgsql-BV1Z2bjp.js → pgsql-DqPigHrq.js} +1 -1
  232. package/dist/ui/assets/{php-FGjYSZqs.js → php-CdOl9bRs.js} +1 -1
  233. package/dist/ui/assets/{php-template-B1OW86WT.js → php-template-DPfirJg2.js} +1 -1
  234. package/dist/ui/assets/{pieDiagram-ENE6RG2P-Bh0bhWSa.js → pieDiagram-ENE6RG2P-DGaJNf4S.js} +1 -1
  235. package/dist/ui/assets/{plaintext-Cvn_UgSv.js → plaintext-EHbgBKzw.js} +1 -1
  236. package/dist/ui/assets/{pony-CRWnA3MR.js → pony-DmJajtp2.js} +1 -1
  237. package/dist/ui/assets/{powershell-Cwn155MZ.js → powershell-DfGzdWR6.js} +1 -1
  238. package/dist/ui/assets/{processing-BS6-1lrQ.js → processing-BT0ETgPG.js} +1 -1
  239. package/dist/ui/assets/{profile-C45OLQrv.js → profile-B3I-x5Lt.js} +1 -1
  240. package/dist/ui/assets/{prolog-C5YafSzY.js → prolog-B_4QJIvI.js} +1 -1
  241. package/dist/ui/assets/{properties-BULd-Zhg.js → properties-BFVI8weS.js} +1 -1
  242. package/dist/ui/assets/{protobuf-Qf1IuG5l.js → protobuf-PaF39oZZ.js} +1 -1
  243. package/dist/ui/assets/{puppet-93XdQvnn.js → puppet-BDC6Q8VF.js} +1 -1
  244. package/dist/ui/assets/{purebasic-DlYNScQP.js → purebasic-B2ejrOZK.js} +1 -1
  245. package/dist/ui/assets/{python-D-Do6-F0.js → python-BOxtIk9H.js} +1 -1
  246. package/dist/ui/assets/{python-repl-DGutP04w.js → python-repl-BslBh_Mx.js} +1 -1
  247. package/dist/ui/assets/{q-lmgfrySy.js → q-BPe8WLGW.js} +1 -1
  248. package/dist/ui/assets/{qml-BbjX_mSU.js → qml-BazRR6fz.js} +1 -1
  249. package/dist/ui/assets/{quadrantDiagram-ABIIQ3AL-B891FOO8.js → quadrantDiagram-ABIIQ3AL-BQ7aPkHk.js} +1 -1
  250. package/dist/ui/assets/{r--x8NzO9N.js → r-C09pGNJC.js} +1 -1
  251. package/dist/ui/assets/{railroadDiagram-RFXS5EU6-R3O-GKNe.js → railroadDiagram-RFXS5EU6-sCO9VGvE.js} +1 -1
  252. package/dist/ui/assets/{reasonml-DwHsAflh.js → reasonml-S7dzwVL9.js} +1 -1
  253. package/dist/ui/assets/{requirementDiagram-TGXJPOKE-D4l_xEXt.js → requirementDiagram-TGXJPOKE-CfT5aVZg.js} +1 -1
  254. package/dist/ui/assets/{rib-DMJNtDwV.js → rib-fM2EwQd4.js} +1 -1
  255. package/dist/ui/assets/{roboconf-BNNGTvHr.js → roboconf-D7AaeyrW.js} +1 -1
  256. package/dist/ui/assets/{routeros-BF7SVruD.js → routeros-c6Q7mKuq.js} +1 -1
  257. package/dist/ui/assets/{rsl-1EHeIZqp.js → rsl-sCpEQBxh.js} +1 -1
  258. package/dist/ui/assets/{ruby-B-v_BYYp.js → ruby-lcKhz2w9.js} +1 -1
  259. package/dist/ui/assets/{ruleslanguage-GFeEMSdK.js → ruleslanguage-BW4ATOuX.js} +1 -1
  260. package/dist/ui/assets/{rust-ApqGtMhh.js → rust-BbpU-0VY.js} +1 -1
  261. package/dist/ui/assets/{sankeyDiagram-HTMAVEWB-Dc-2lhBq.js → sankeyDiagram-HTMAVEWB-CaweCpvN.js} +1 -1
  262. package/dist/ui/assets/{sas-YkxX6N9_.js → sas-BPt5R0dx.js} +1 -1
  263. package/dist/ui/assets/{scala-BpHi86GZ.js → scala-DxW_vqXs.js} +1 -1
  264. package/dist/ui/assets/{scheme-D889qY8Y.js → scheme-T2Q_jWzT.js} +1 -1
  265. package/dist/ui/assets/{scilab-C3l-bcRx.js → scilab-DMORg9lV.js} +1 -1
  266. package/dist/ui/assets/{scss-D0iGASxm.js → scss-t0VsosqT.js} +1 -1
  267. package/dist/ui/assets/{sequenceDiagram-DBY2YBRQ-DvppgciC.js → sequenceDiagram-DBY2YBRQ-o-H_R4zb.js} +1 -1
  268. package/dist/ui/assets/{shell-PUnaEPCO.js → shell-CnCDa1s9.js} +1 -1
  269. package/dist/ui/assets/{sizeCapture-X5ZJPWSS-DhvIbxXs.js → sizeCapture-X5ZJPWSS-BNLkHGDS.js} +1 -1
  270. package/dist/ui/assets/{smali-Du_dF9hl.js → smali-_n-BxJyG.js} +1 -1
  271. package/dist/ui/assets/{smalltalk-CSr2Gc1v.js → smalltalk-B90PXJwK.js} +1 -1
  272. package/dist/ui/assets/{sml-D3zkvzP2.js → sml-fuY7bj-n.js} +1 -1
  273. package/dist/ui/assets/{sqf-BZQ34qEZ.js → sqf-COpwkyuo.js} +1 -1
  274. package/dist/ui/assets/{sql-BFKScMsf.js → sql-CXIT0j-x.js} +1 -1
  275. package/dist/ui/assets/{sql_more-C2Lc_Qqq.js → sql_more-C1Oxq4rx.js} +1 -1
  276. package/dist/ui/assets/{stan-CzY8VdxU.js → stan-BZEpaHeC.js} +1 -1
  277. package/dist/ui/assets/{stata-9GxyhPpV.js → stata-CkBwaiZM.js} +1 -1
  278. package/dist/ui/assets/{stateDiagram-2N3HPSRC-CM63y6f0.js → stateDiagram-2N3HPSRC-BkdnNF7I.js} +1 -1
  279. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-0JnZ1VSQ.js +1 -0
  280. package/dist/ui/assets/{step21-BpK_Zw3v.js → step21-fs9N_U3O.js} +1 -1
  281. package/dist/ui/assets/{stylus-DQ4k28M4.js → stylus-Bs_9cvKZ.js} +1 -1
  282. package/dist/ui/assets/{subunit-C6ciOPNF.js → subunit-DvgcOCqJ.js} +1 -1
  283. package/dist/ui/assets/{swift-CJfqqSbT.js → swift-BE4ONsur.js} +1 -1
  284. package/dist/ui/assets/{swimlanes-5IMT3BWC-DS6_HNF7.js → swimlanes-5IMT3BWC-uqTAc7o7.js} +2 -2
  285. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DQRIIEmi.js +8 -0
  286. package/dist/ui/assets/{taggerscript-VouMmJ_v.js → taggerscript-BhmPJ64C.js} +1 -1
  287. package/dist/ui/assets/{tap-wXCy18ot.js → tap-DkueIVKV.js} +1 -1
  288. package/dist/ui/assets/{tcl-ewDOmCFX.js → tcl-DyXOOkFi.js} +1 -1
  289. package/dist/ui/assets/{thrift-BfFA03rE.js → thrift-Dhgbk56T.js} +1 -1
  290. package/dist/ui/assets/{timeline-definition-FHXFAJF6-Dz2m6S6x.js → timeline-definition-FHXFAJF6-DBAk9Ouc.js} +1 -1
  291. package/dist/ui/assets/{tp-HGBcpNf9.js → tp-BsXyrRGH.js} +1 -1
  292. package/dist/ui/assets/{twig-nrQZ0pw8.js → twig-J0HqIuHw.js} +1 -1
  293. package/dist/ui/assets/{typescript-B7tNYFEQ.js → typescript-Dkwvul39.js} +1 -1
  294. package/dist/ui/assets/{vala-BIjQtoo6.js → vala-CRGnf8aY.js} +1 -1
  295. package/dist/ui/assets/{vbnet-Bbspccm6.js → vbnet-BtJAUe3z.js} +1 -1
  296. package/dist/ui/assets/{vbscript-C45_QgOy.js → vbscript-RgFFNuM3.js} +1 -1
  297. package/dist/ui/assets/{vbscript-html-DlF2QBc7.js → vbscript-html-DO32Io9Y.js} +1 -1
  298. package/dist/ui/assets/{vennDiagram-L72KCM5P-BPEphYtX.js → vennDiagram-L72KCM5P-BJi6y0hh.js} +1 -1
  299. package/dist/ui/assets/{verilog-BSitd8W0.js → verilog-C4h6MLcI.js} +1 -1
  300. package/dist/ui/assets/{vhdl-C1bbeiC4.js → vhdl-DOafePyU.js} +1 -1
  301. package/dist/ui/assets/{vim-DchwbT8X.js → vim-BAdTA9TY.js} +1 -1
  302. package/dist/ui/assets/{wardleyDiagram-EHGQE667-BttTCoBT.js → wardleyDiagram-EHGQE667-C7c_4IJ6.js} +1 -1
  303. package/dist/ui/assets/{x86asm-vARxMUvn.js → x86asm-BCL6__QH.js} +1 -1
  304. package/dist/ui/assets/{xl-dx63vvXo.js → xl-qIzE4HOe.js} +1 -1
  305. package/dist/ui/assets/{xml-BUnj27wL.js → xml-DE2sJXYU.js} +1 -1
  306. package/dist/ui/assets/{xquery-T7gpnf0e.js → xquery-CQ35t92y.js} +1 -1
  307. package/dist/ui/assets/{xychartDiagram-FW5EYKEG-BfrNhdrG.js → xychartDiagram-FW5EYKEG-D2ILn0jL.js} +1 -1
  308. package/dist/ui/assets/{yaml-xRgQKzeL.js → yaml-5KaAvG5C.js} +1 -1
  309. package/dist/ui/assets/{zephir-Yu6l5qJj.js → zephir-CbR3Ryfq.js} +1 -1
  310. package/dist/ui/index.html +2 -2
  311. package/dist/utils/__tests__/abort-signals.test.js +67 -0
  312. package/dist/utils/__tests__/inject-loop.test.js +1 -53
  313. package/dist/utils/__tests__/learn-tasks-db.test.js +82 -0
  314. package/dist/utils/__tests__/openai-converter.test.js +25 -0
  315. package/dist/utils/__tests__/pi-crawl-tools.test.js +15 -4
  316. package/dist/utils/__tests__/pi-dedup-reconcile.test.js +11 -9
  317. package/dist/utils/__tests__/pi-events.test.js +172 -0
  318. package/dist/utils/__tests__/pi-learn-orchestrator.test.js +216 -6
  319. package/dist/utils/__tests__/pi-runtime-json.test.js +38 -3
  320. package/dist/utils/__tests__/providers-db.test.js +40 -2
  321. package/dist/utils/__tests__/request-writer.test.js +271 -39
  322. package/dist/utils/__tests__/sse-protocol.test.d.ts +1 -0
  323. package/dist/utils/__tests__/sse-protocol.test.js +115 -0
  324. package/dist/utils/__tests__/vault.test.d.ts +1 -0
  325. package/dist/utils/__tests__/{knowledge-store.test.js → vault.test.js} +16 -16
  326. package/dist/utils/abort-signals.d.ts +13 -0
  327. package/dist/utils/abort-signals.js +33 -0
  328. package/dist/utils/db.d.ts +2 -0
  329. package/dist/utils/db.js +42 -0
  330. package/dist/utils/esm-dirname.d.ts +0 -15
  331. package/dist/utils/esm-dirname.js +0 -4
  332. package/dist/utils/inject-loop.d.ts +0 -27
  333. package/dist/utils/inject-loop.js +2 -56
  334. package/dist/utils/learn-tasks-db.d.ts +15 -0
  335. package/dist/utils/learn-tasks-db.js +35 -0
  336. package/dist/utils/openai-converter.js +88 -78
  337. package/dist/utils/pi-browser-tools.d.ts +0 -2
  338. package/dist/utils/pi-browser-tools.js +0 -174
  339. package/dist/utils/pi-crawl-tools.d.ts +2 -1
  340. package/dist/utils/pi-crawl-tools.js +16 -11
  341. package/dist/utils/pi-dedup.d.ts +8 -30
  342. package/dist/utils/pi-dedup.js +32 -67
  343. package/dist/utils/pi-events.d.ts +65 -0
  344. package/dist/utils/pi-events.js +98 -0
  345. package/dist/utils/pi-learn-orchestrator.d.ts +6 -5
  346. package/dist/utils/pi-learn-orchestrator.js +71 -106
  347. package/dist/utils/pi-runtime.d.ts +5 -6
  348. package/dist/utils/pi-runtime.js +38 -42
  349. package/dist/utils/pi-sandbox-ops.d.ts +0 -36
  350. package/dist/utils/pi-sandbox-ops.js +5 -190
  351. package/dist/utils/providers-db.d.ts +3 -0
  352. package/dist/utils/providers-db.js +21 -7
  353. package/dist/utils/request-writer.d.ts +60 -30
  354. package/dist/utils/request-writer.js +182 -61
  355. package/dist/utils/sse-protocol.d.ts +34 -0
  356. package/dist/utils/sse-protocol.js +121 -0
  357. package/dist/utils/sse-stream-processor.d.ts +4 -9
  358. package/dist/utils/sse-stream-processor.js +13 -104
  359. package/dist/utils/sse-writer.d.ts +1 -1
  360. package/dist/utils/sse-writer.js +3 -2
  361. package/dist/utils/stats-aggregator.js +3 -0
  362. package/dist/utils/tool-injector.js +7 -0
  363. package/dist/utils/vault.d.ts +111 -0
  364. package/dist/utils/vault.js +434 -0
  365. package/package.json +1 -1
  366. package/dist/docs/assets/chunks/@localSearchIndexroot.BN6hB8Jr.js +0 -1
  367. package/dist/types/api.d.ts +0 -20
  368. package/dist/types/index.d.ts +0 -4
  369. package/dist/types/index.js +0 -4
  370. package/dist/types/log.d.ts +0 -13
  371. package/dist/ui/assets/channel-BgAIihW-.js +0 -1
  372. package/dist/ui/assets/classDiagram-OUVF2IWQ-0fsnUoNI.js +0 -1
  373. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-0fsnUoNI.js +0 -1
  374. package/dist/ui/assets/index-C0fxlU9d.css +0 -10
  375. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-OA9dcuA9.js +0 -1
  376. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-BLEnJU_R.js +0 -8
  377. package/dist/utils/__tests__/sse-accumulator.test.js +0 -83
  378. package/dist/utils/knowledge-store.d.ts +0 -44
  379. package/dist/utils/knowledge-store.js +0 -193
  380. package/dist/utils/migrate-files-to-db.d.ts +0 -1
  381. package/dist/utils/migrate-files-to-db.js +0 -138
  382. package/dist/utils/sse-accumulator.d.ts +0 -9
  383. package/dist/utils/sse-accumulator.js +0 -59
  384. /package/dist/docs/assets/{proxy-cli_data-hooks.md.w9Oe1OD3.lean.js → proxy-cli_data-hooks.md.Bz8CVbxO.lean.js} +0 -0
  385. /package/dist/docs/assets/{proxy-core_ui-routes.md.Dyqkeoiv.lean.js → proxy-core_ui-routes.md.B21t1p7R.lean.js} +0 -0
  386. /package/dist/{types/api.js → utils/__tests__/abort-signals.test.d.ts} +0 -0
  387. /package/dist/{types/log.js → utils/__tests__/learn-tasks-db.test.d.ts} +0 -0
  388. /package/dist/utils/__tests__/{knowledge-store.test.d.ts → openai-converter.test.d.ts} +0 -0
  389. /package/dist/utils/__tests__/{sse-accumulator.test.d.ts → pi-events.test.d.ts} +0 -0
@@ -1,16 +1,17 @@
1
1
  import { Readable, finished } from 'stream';
2
2
  import { convertClaudeToOpenAIRequest, convertOpenAIToClaudeResponse, createStreamTransformer, buildOpenAIHeaders } from '../utils/openai-converter.js';
3
3
  import { loadConfig } from '../config/index.js';
4
- import { saveRequestDB, extractTokenUsage, flushEventBatch, deleteResponseEvents, deleteRequestRow, updateRequestTokens, EVENT_BATCH_SIZE } from '../utils/request-writer.js';
5
- import { cleanOldRequestsDB } from '../utils/request-writer.js';
4
+ import { createRequestRecorder } from '../utils/request-writer.js';
5
+ import { cleanOldRequestsDB, interruptStaleRequestsOnStartup } from '../utils/request-writer.js';
6
6
  import { pushNewRequest } from './data-push.js';
7
7
  import { initDatabase, closeDatabase, getDatabase } from '../utils/db.js';
8
+ import { recoverCrashedTasks } from '../utils/learn-tasks-db.js';
9
+ import { getActiveProvider } from '../utils/providers-db.js';
8
10
  import { aggregateStats } from '../utils/stats-aggregator.js';
9
11
  import { mcpManager } from '../utils/mcp-manager.js';
10
12
  import { getMachineIdSync, preloadMachineId } from '../utils/machine-id.js';
11
- // Cached prepared statement for active provider lookup (avoids per-request allocation)
12
- let activeProviderStmt = null;
13
- let cachedDbInstance = null;
13
+ import { createEventDecoder } from '../utils/sse-protocol.js';
14
+ import { createClientAbortSignal, createTimeoutSignal } from '../utils/abort-signals.js';
14
15
  /**
15
16
  * Resolves the proxy target per request:
16
17
  * - If a provider with is_default=1 exists in DB, use its base_url + api_key + tier models (partial replacement)
@@ -36,15 +37,7 @@ export function resolveProxyTarget(proxyConfig) {
36
37
  baseUrl = configUrl.origin;
37
38
  targetPath = configUrl.pathname.replace(/\/$/, '');
38
39
  const db = getDatabase();
39
- // Invalidate cached stmt if DB instance changed (happens in tests with fresh DB per test)
40
- if (db !== cachedDbInstance) {
41
- activeProviderStmt = null;
42
- cachedDbInstance = db;
43
- }
44
- if (!activeProviderStmt) {
45
- activeProviderStmt = db.prepare('SELECT base_url, api_key, model, haiku_model, sonnet_model, opus_model, is_openai_compatible, auth_style FROM providers WHERE is_default = 1 LIMIT 1');
46
- }
47
- const active = activeProviderStmt.get();
40
+ const active = getActiveProvider(db);
48
41
  if (active) {
49
42
  // Replace base_url only if provided
50
43
  if (active.base_url && active.base_url.trim() !== '') {
@@ -163,57 +156,6 @@ export function getErrorStatusCode(error) {
163
156
  }
164
157
  return 500;
165
158
  }
166
- /**
167
- * Push a parsed SSE event into batch/tail buffers.
168
- * Flushes batch to DB when it reaches EVENT_BATCH_SIZE (10).
169
- * Only memory held: current batch (≤10 events) + tail (≤5 events).
170
- */
171
- function pushEventToBuffers(event, sessionId, requestId, eventBatch, tailBuffer, eventIndexRef) {
172
- const entry = { index: eventIndexRef.value, type: event?.type, data: event };
173
- eventBatch.push(entry);
174
- // Maintain tail buffer (last 5 events for usage extraction)
175
- tailBuffer.push(event);
176
- if (tailBuffer.length > 5) {
177
- tailBuffer.shift();
178
- }
179
- // Flush batch to DB when threshold reached
180
- if (eventBatch.length >= EVENT_BATCH_SIZE) {
181
- flushEventBatch(sessionId, requestId, eventBatch, eventIndexRef.value - eventBatch.length + 1);
182
- eventBatch.length = 0; // Reset batch (memory freed)
183
- }
184
- eventIndexRef.value++;
185
- }
186
- /**
187
- * Flush remaining batch + update request completion in DB.
188
- * Extracts token usage from tail buffer (no need for full events array).
189
- */
190
- async function completeStreamSave(sessionId, requestId, requestData, eventBatch, tailBuffer, eventIndexRef, startTime, statusCode, resolved, forwardedModel, originalModel, machineId, request) {
191
- // Flush remaining events in batch
192
- if (eventBatch.length > 0) {
193
- flushEventBatch(sessionId, requestId, eventBatch, eventIndexRef.value - eventBatch.length);
194
- eventBatch.length = 0;
195
- }
196
- requestData.response.completedAt = new Date().toISOString();
197
- requestData.response.events = []; // Not needed for streaming, clear to avoid serialization
198
- await saveRequestDB(sessionId, requestId, requestData);
199
- const usage = extractTokenUsage(tailBuffer);
200
- updateRequestTokens(requestId, sessionId, usage);
201
- pushNewRequest({
202
- requestId,
203
- sessionId,
204
- compositeId: `${sessionId}:${requestId}`,
205
- method: request.method,
206
- path: request.url,
207
- timestamp: requestData.timestamp,
208
- statusCode,
209
- responseTime: Date.now() - startTime,
210
- model: forwardedModel || originalModel,
211
- machineId,
212
- baseUrl: resolved.baseUrl,
213
- usage,
214
- pendingId: requestId !== request.id ? `${sessionId}:${request.id}` : undefined
215
- }, 'completed');
216
- }
217
159
  export function getErrorMessage(error) {
218
160
  if (error.code === 'ECONNREFUSED') {
219
161
  return 'Target server unreachable';
@@ -226,12 +168,50 @@ export function getErrorMessage(error) {
226
168
  }
227
169
  return 'Proxy error';
228
170
  }
171
+ // SSE 流空闲看门狗:超过该时长无上游数据则销毁流,避免挂死产生僵尸行
172
+ const STREAM_IDLE_TIMEOUT_MS = 120000;
173
+ /**
174
+ * 给上游 nodeStream 挂空闲看门狗:data 到达重置定时器;
175
+ * end/close/error 清理定时器;超时且流未销毁时以 idle timeout 销毁。
176
+ */
177
+ function attachIdleWatchdog(nodeStream) {
178
+ let timer = null;
179
+ const clearTimer = () => {
180
+ if (timer) {
181
+ clearTimeout(timer);
182
+ timer = null;
183
+ }
184
+ };
185
+ const resetTimer = () => {
186
+ clearTimer();
187
+ timer = setTimeout(() => {
188
+ if (!nodeStream.destroyed) {
189
+ nodeStream.destroy(new Error('upstream idle timeout'));
190
+ }
191
+ }, STREAM_IDLE_TIMEOUT_MS);
192
+ };
193
+ nodeStream.on('data', resetTimer);
194
+ nodeStream.on('end', clearTimer);
195
+ nodeStream.on('close', clearTimer);
196
+ nodeStream.on('error', clearTimer);
197
+ resetTimer();
198
+ }
229
199
  export async function setupProxy(fastify, proxyConfig) {
230
200
  // Load full config to get storage.maxDays
231
201
  const fullConfig = await loadConfig();
232
202
  const maxDays = fullConfig.storage?.maxDays ?? 7;
233
203
  // Initialize SQLite database
234
- initDatabase();
204
+ const db = initDatabase();
205
+ // 回收上次进程遗留的无主 running learn 任务(进程崩溃/被 kill)
206
+ const recoveredTasks = recoverCrashedTasks(db);
207
+ if (recoveredTasks > 0) {
208
+ console.log(`Recovered ${recoveredTasks} crashed learn task(s) from previous run`);
209
+ }
210
+ // 回收上次进程遗留的僵尸 SSE 请求行(流中断/挂死未回调)
211
+ const interruptedRequests = interruptStaleRequestsOnStartup();
212
+ if (interruptedRequests > 0) {
213
+ console.log(`Interrupted ${interruptedRequests} stale request(s) from previous run`);
214
+ }
235
215
  // Initialize MCP connections (after DB is ready)
236
216
  try {
237
217
  await mcpManager.init();
@@ -285,9 +265,12 @@ export async function setupProxy(fastify, proxyConfig) {
285
265
  fastify.all('/v1/*', async (request, reply) => {
286
266
  const startTime = Date.now();
287
267
  const resolved = resolveProxyTarget(proxyConfig);
268
+ // 下游客户端中止:整个请求作用域建一次,两处上游 fetch 复用
269
+ const clientSignal = createClientAbortSignal(request.raw);
288
270
  const sessionId = request.headers['x-claude-code-session-id'] || 'unknown-session';
289
271
  // Replace model based on tier matching (getProxyModel)
290
272
  const originalModel = request.body?.model;
273
+ let rec;
291
274
  try {
292
275
  const proxyModel = getProxyModel(originalModel, resolved);
293
276
  if (proxyModel && request.body && typeof request.body === 'object') {
@@ -311,9 +294,9 @@ export async function setupProxy(fastify, proxyConfig) {
311
294
  (forwardedAuthHeader?.startsWith('Bearer ') ? forwardedAuthHeader.slice(7) : undefined);
312
295
  // Log complete request data (Fastify already parsed body)
313
296
  const machineId = getMachineIdSync() ?? undefined;
314
- const requestData = {
315
- requestId: request.id, // Will be updated with cloud x-request-id later
297
+ const meta = {
316
298
  sessionId,
299
+ localRequestId: request.id, // Will be replaced with cloud x-request-id row on completion
317
300
  timestamp: new Date().toISOString(),
318
301
  apiKey,
319
302
  proxyApiKey,
@@ -325,33 +308,12 @@ export async function setupProxy(fastify, proxyConfig) {
325
308
  path: request.url,
326
309
  headers: forwardHeaders,
327
310
  body: request.body // Full payload: model, messages, tools, MCP params, etc.
328
- },
329
- response: {
330
- statusCode: 0, // Will be updated after fetch
331
- events: [] // Only used for JSON responses; streaming uses batch buffer
332
311
  }
333
312
  };
334
- // SSE event batch buffer: flush to DB every ~10 events to avoid in-memory accumulation
335
- // Tail buffer: keep last 5 events for token usage extraction at stream end
336
- const eventBatch = [];
337
- const tailBuffer = [];
338
- const eventIndexRef = { value: 0 };
313
+ rec = createRequestRecorder(meta);
339
314
  request.log.info(`request logged: ${request.id} ${request.method} ${request.url}`);
340
315
  // Save initial record + push pending status to frontend
341
- await saveRequestDB(sessionId, request.id, requestData);
342
- pushNewRequest({
343
- requestId: request.id,
344
- sessionId,
345
- compositeId: `${sessionId}:${request.id}`,
346
- method: request.method,
347
- path: request.url,
348
- timestamp: requestData.timestamp,
349
- statusCode: 0,
350
- responseTime: 0,
351
- model: forwardedModel,
352
- machineId,
353
- baseUrl: resolved.baseUrl
354
- }, 'pending');
316
+ await rec.pending();
355
317
  // --- OpenAI Compatible Mode ---
356
318
  if (resolved.is_openai_compatible) {
357
319
  const openaiRequest = convertClaudeToOpenAIRequest(request.body, forwardedModel);
@@ -364,14 +326,11 @@ export async function setupProxy(fastify, proxyConfig) {
364
326
  method: request.method,
365
327
  headers: openaiHeaders,
366
328
  body: JSON.stringify(openaiRequest),
367
- signal: AbortSignal.timeout(300000)
329
+ signal: createTimeoutSignal(300000, clientSignal)
368
330
  });
369
331
  request.log.info(`response status: ${response.status}`);
370
332
  // Extract cloud request ID
371
333
  const cloudRequestId = response.headers.get('x-request-id') || request.id;
372
- requestData.requestId = cloudRequestId;
373
- requestData.response.statusCode = response.status;
374
- requestData.response.headers = Object.fromEntries(response.headers);
375
334
  // Check response type
376
335
  const contentType = response.headers.get('content-type') || '';
377
336
  const isSSE = contentType.includes('text/event-stream');
@@ -384,45 +343,30 @@ export async function setupProxy(fastify, proxyConfig) {
384
343
  const openaiRes = JSON.parse(responseBody);
385
344
  const claudeRes = convertOpenAIToClaudeResponse(openaiRes, forwardedModel || originalModel);
386
345
  claudeResponseBody = JSON.stringify(claudeRes);
387
- requestData.response.events.push(claudeRes);
346
+ rec.appendEvent(claudeRes);
388
347
  }
389
348
  catch {
390
349
  claudeResponseBody = responseBody;
391
350
  try {
392
- requestData.response.events.push(JSON.parse(responseBody));
351
+ rec.appendEvent(JSON.parse(responseBody));
393
352
  }
394
353
  catch {
395
- requestData.response.events.push({ raw: responseBody });
354
+ rec.appendEvent({ raw: responseBody });
396
355
  }
397
356
  }
398
- requestData.response.completedAt = new Date().toISOString();
399
- if (cloudRequestId !== request.id) {
400
- deleteResponseEvents(request.id, sessionId);
401
- deleteRequestRow(request.id, sessionId);
402
- }
403
- await saveRequestDB(sessionId, cloudRequestId, requestData);
404
- const usage = extractTokenUsage(requestData.response.events);
405
- pushNewRequest({
406
- requestId: cloudRequestId,
407
- sessionId,
408
- compositeId: `${sessionId}:${cloudRequestId}`,
409
- method: request.method,
410
- path: request.url,
411
- timestamp: requestData.timestamp,
357
+ await rec.complete({
358
+ cloudRequestId: cloudRequestId !== request.id ? cloudRequestId : undefined,
412
359
  statusCode: response.status,
413
- responseTime: Date.now() - startTime,
414
- model: forwardedModel,
415
- machineId,
416
- baseUrl: resolved.baseUrl,
417
- usage,
418
- pendingId: cloudRequestId !== request.id ? `${sessionId}:${request.id}` : undefined
419
- }, 'completed');
360
+ headers: Object.fromEntries(response.headers)
361
+ });
420
362
  const elapsed = Date.now() - startTime;
421
363
  request.log.info(`json response (openai): ${cloudRequestId} ${response.status} (${elapsed}ms)`);
422
364
  reply.code(response.status).headers({ 'Content-Type': 'application/json' }).send(claudeResponseBody);
423
365
  return;
424
366
  }
425
367
  // Handle SSE streaming response
368
+ // 上游响应头已到达:回写真实 status_code(状态仍 pending,保留 spinner)
369
+ rec.headers({ statusCode: response.status, headers: Object.fromEntries(response.headers) });
426
370
  reply.hijack();
427
371
  const responseHeaders = Object.fromEntries(response.headers);
428
372
  // Replace content-type with Claude SSE format
@@ -430,51 +374,35 @@ export async function setupProxy(fastify, proxyConfig) {
430
374
  reply.raw.writeHead(response.status, responseHeaders);
431
375
  if (response.body) {
432
376
  const nodeStream = Readable.fromWeb(response.body);
377
+ // 客户端断开:销毁上游流,finished 回调走中断落库
378
+ clientSignal.addEventListener('abort', () => {
379
+ if (!nodeStream.destroyed)
380
+ nodeStream.destroy(new Error('client disconnected'));
381
+ });
382
+ attachIdleWatchdog(nodeStream);
433
383
  const transformStream = createStreamTransformer(forwardedModel || originalModel);
434
- // Record SSE events via batch buffer (memory: ≤10 batch + ≤5 tail)
384
+ // 旁路解码器:只做事件入库,不介入转发管道;[DONE] 走 onDone 留空,天然不入库
385
+ const tapDecoder = createEventDecoder((e) => rec.appendEvent(e));
435
386
  nodeStream.on('data', (chunk) => {
436
- const text = chunk.toString();
437
- const lines = text.split('\n');
438
- for (const line of lines) {
439
- if (line.startsWith('data:')) {
440
- const eventData = line.slice(5).trim();
441
- if (eventData && eventData !== '[DONE]') {
442
- try {
443
- const event = JSON.parse(eventData);
444
- pushEventToBuffers(event, sessionId, cloudRequestId, eventBatch, tailBuffer, eventIndexRef);
445
- }
446
- catch {
447
- // Not valid JSON, skip
448
- }
449
- }
450
- }
451
- }
387
+ tapDecoder.write(chunk);
452
388
  });
453
389
  // Use finished() for reliable stream completion detection
454
390
  finished(nodeStream, async (err) => {
391
+ tapDecoder.end();
455
392
  if (err) {
456
393
  request.log.error(`openai stream error: ${err.message}`);
457
- }
458
- // Convert OpenAI stream usage to Claude format for extractTokenUsage compatibility
459
- const lastChunk = tailBuffer.find((e) => e?.usage);
460
- if (lastChunk?.usage) {
461
- const syntheticEvent = {
462
- type: 'message_delta',
463
- usage: {
464
- output_tokens: lastChunk.usage.completion_tokens || 0
465
- }
466
- };
467
- pushEventToBuffers(syntheticEvent, sessionId, cloudRequestId, eventBatch, tailBuffer, eventIndexRef);
468
- }
469
- if (cloudRequestId !== request.id) {
470
- deleteResponseEvents(request.id, sessionId);
471
- deleteRequestRow(request.id, sessionId);
394
+ rec.interrupt({ statusCode: response.status, error: `stream interrupted: ${err.message}` });
395
+ return;
472
396
  }
473
397
  // Flush remaining batch + complete request
474
398
  try {
475
- await completeStreamSave(sessionId, cloudRequestId, requestData, eventBatch, tailBuffer, eventIndexRef, startTime, response.status, resolved, forwardedModel, originalModel, machineId, request);
399
+ await rec.complete({
400
+ cloudRequestId: cloudRequestId !== request.id ? cloudRequestId : undefined,
401
+ statusCode: response.status,
402
+ headers: Object.fromEntries(response.headers)
403
+ });
476
404
  const elapsed = Date.now() - startTime;
477
- request.log.info(`stream completed (openai): ${cloudRequestId} ${response.status} (${elapsed}ms, ${eventIndexRef.value} events)`);
405
+ request.log.info(`stream completed (openai): ${cloudRequestId} ${response.status} (${elapsed}ms)`);
478
406
  }
479
407
  catch (dbErr) {
480
408
  request.log.error(`openai stream save failed: ${dbErr.message}`);
@@ -495,15 +423,11 @@ export async function setupProxy(fastify, proxyConfig) {
495
423
  method: request.method,
496
424
  headers: forwardHeaders,
497
425
  body: request.method !== 'GET' ? JSON.stringify(request.body) : undefined,
498
- signal: AbortSignal.timeout(300000)
426
+ signal: createTimeoutSignal(300000, clientSignal)
499
427
  });
500
428
  request.log.info(`response status: ${response.status}`);
501
429
  // Extract cloud request ID from response header
502
430
  const cloudRequestId = response.headers.get('x-request-id') || request.id;
503
- requestData.requestId = cloudRequestId;
504
- // Update response status in requestData
505
- requestData.response.statusCode = response.status;
506
- requestData.response.headers = Object.fromEntries(response.headers);
507
431
  // Check response type: SSE stream or JSON
508
432
  const contentType = response.headers.get('content-type') || '';
509
433
  const isSSE = contentType.includes('text/event-stream');
@@ -514,34 +438,16 @@ export async function setupProxy(fastify, proxyConfig) {
514
438
  // Record JSON body as a single event
515
439
  try {
516
440
  const jsonBody = JSON.parse(responseBody);
517
- requestData.response.events.push(jsonBody);
441
+ rec.appendEvent(jsonBody);
518
442
  }
519
443
  catch {
520
- requestData.response.events.push({ raw: responseBody });
444
+ rec.appendEvent({ raw: responseBody });
521
445
  }
522
- requestData.response.completedAt = new Date().toISOString();
523
- // Remove pending row if cloudRequestId differs from request.id
524
- if (cloudRequestId !== request.id) {
525
- deleteResponseEvents(request.id, sessionId);
526
- deleteRequestRow(request.id, sessionId);
527
- }
528
- await saveRequestDB(sessionId, cloudRequestId, requestData);
529
- const usage = extractTokenUsage(requestData.response.events);
530
- pushNewRequest({
531
- requestId: cloudRequestId,
532
- sessionId,
533
- compositeId: `${sessionId}:${cloudRequestId}`,
534
- method: request.method,
535
- path: request.url,
536
- timestamp: requestData.timestamp,
446
+ await rec.complete({
447
+ cloudRequestId: cloudRequestId !== request.id ? cloudRequestId : undefined,
537
448
  statusCode: response.status,
538
- responseTime: Date.now() - startTime,
539
- model: forwardedModel,
540
- machineId,
541
- baseUrl: resolved.baseUrl,
542
- usage,
543
- pendingId: cloudRequestId !== request.id ? `${sessionId}:${request.id}` : undefined
544
- }, 'completed');
449
+ headers: Object.fromEntries(response.headers)
450
+ });
545
451
  const elapsed = Date.now() - startTime;
546
452
  request.log.info(`json response: ${cloudRequestId} ${response.status} (${elapsed}ms)`);
547
453
  reply.code(response.status);
@@ -550,6 +456,8 @@ export async function setupProxy(fastify, proxyConfig) {
550
456
  return;
551
457
  }
552
458
  // Hijack reply to take full control of SSE stream
459
+ // 上游响应头已到达:回写真实 status_code(状态仍 pending,保留 spinner)
460
+ rec.headers({ statusCode: response.status, headers: Object.fromEntries(response.headers) });
553
461
  reply.hijack();
554
462
  // Write response headers (preserve original from Aliyun)
555
463
  const responseHeaders = Object.fromEntries(response.headers);
@@ -558,38 +466,33 @@ export async function setupProxy(fastify, proxyConfig) {
558
466
  if (response.body) {
559
467
  // Convert Web ReadableStream to Node Readable stream
560
468
  const nodeStream = Readable.fromWeb(response.body);
561
- // Record SSE events via batch buffer (memory: ≤10 batch + ≤5 tail)
469
+ // 客户端断开:销毁上游流,finished 回调走中断落库
470
+ clientSignal.addEventListener('abort', () => {
471
+ if (!nodeStream.destroyed)
472
+ nodeStream.destroy(new Error('client disconnected'));
473
+ });
474
+ attachIdleWatchdog(nodeStream);
475
+ // 旁路解码器:只做事件入库,不介入转发管道;[DONE] 走 onDone 留空,天然不入库
476
+ const tapDecoder = createEventDecoder((e) => rec.appendEvent(e));
562
477
  nodeStream.on('data', (chunk) => {
563
- const text = chunk.toString();
564
- const lines = text.split('\n');
565
- for (const line of lines) {
566
- if (line.startsWith('data:')) {
567
- const eventData = line.slice(5).trim();
568
- if (eventData && eventData !== '[DONE]') {
569
- try {
570
- const event = JSON.parse(eventData);
571
- pushEventToBuffers(event, sessionId, cloudRequestId, eventBatch, tailBuffer, eventIndexRef);
572
- }
573
- catch {
574
- // Not valid JSON, skip
575
- }
576
- }
577
- }
578
- }
478
+ tapDecoder.write(chunk);
579
479
  });
580
480
  // Save request data when stream completes
581
481
  finished(nodeStream, async (err) => {
482
+ tapDecoder.end();
582
483
  if (err) {
583
484
  request.log.error(`claude stream error: ${err.message}`);
584
- }
585
- if (cloudRequestId !== request.id) {
586
- deleteResponseEvents(request.id, sessionId);
587
- deleteRequestRow(request.id, sessionId);
485
+ rec.interrupt({ statusCode: response.status, error: `stream interrupted: ${err.message}` });
486
+ return;
588
487
  }
589
488
  try {
590
- await completeStreamSave(sessionId, cloudRequestId, requestData, eventBatch, tailBuffer, eventIndexRef, startTime, response.status, resolved, forwardedModel, originalModel, machineId, request);
489
+ await rec.complete({
490
+ cloudRequestId: cloudRequestId !== request.id ? cloudRequestId : undefined,
491
+ statusCode: response.status,
492
+ headers: Object.fromEntries(response.headers)
493
+ });
591
494
  const elapsed = Date.now() - startTime;
592
- request.log.info(`stream completed: ${cloudRequestId} ${response.status} (${elapsed}ms, ${eventIndexRef.value} events)`);
495
+ request.log.info(`stream completed: ${cloudRequestId} ${response.status} (${elapsed}ms)`);
593
496
  }
594
497
  catch (dbErr) {
595
498
  request.log.error(`stream save failed: ${dbErr.message}`);
@@ -606,21 +509,27 @@ export async function setupProxy(fastify, proxyConfig) {
606
509
  errorMessage: error.message,
607
510
  errorCode: error.code || 'unknown'
608
511
  }, 'proxy error');
609
- // Fetch failed — no cloudRequestId available, use Fastify request.id
610
- pushNewRequest({
611
- requestId: request.id,
612
- sessionId,
613
- compositeId: `${sessionId}:${request.id}`,
614
- method: request.method,
615
- path: request.url,
616
- timestamp: new Date().toISOString(),
617
- statusCode: getErrorStatusCode(error),
618
- responseTime: Date.now() - startTime,
619
- model: originalModel,
620
- machineId: getMachineIdSync() ?? undefined,
621
- baseUrl: resolved.baseUrl
622
- }, 'completed');
623
512
  const statusCode = getErrorStatusCode(error);
513
+ if (rec) {
514
+ rec.fail({ statusCode, error: getErrorMessage(error) });
515
+ }
516
+ else {
517
+ // pending() 之前就抛错(header/meta 准备阶段),无 DB 行可更新,仅推送
518
+ pushNewRequest({
519
+ requestId: request.id,
520
+ sessionId,
521
+ compositeId: `${sessionId}:${request.id}`,
522
+ method: request.method,
523
+ path: request.url,
524
+ timestamp: new Date().toISOString(),
525
+ statusCode,
526
+ responseTime: Date.now() - startTime,
527
+ model: originalModel,
528
+ machineId: getMachineIdSync() ?? undefined,
529
+ userAgent: request.headers['user-agent'],
530
+ baseUrl: resolved.baseUrl
531
+ }, 'completed');
532
+ }
624
533
  reply.code(statusCode).send({
625
534
  error: getErrorMessage(error),
626
535
  requestId: request.id