@cc-monitoring/proxy-core 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) 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.B9A39uFv.js → app.DtYNT5zS.js} +1 -1
  5. package/dist/docs/assets/chunks/@localSearchIndexroot.C4sjikMO.js +1 -0
  6. package/dist/docs/assets/chunks/{VPLocalSearchBox.DdhC696L.js → VPLocalSearchBox.DpXF9ZAI.js} +1 -1
  7. package/dist/docs/assets/chunks/{theme.CfB2tOFi.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/tools.js +8 -9
  48. package/dist/server/__tests__/providers-route.test.js +1 -0
  49. package/dist/server/auth.d.ts +0 -1
  50. package/dist/server/auth.js +1 -1
  51. package/dist/server/chat-route.js +48 -162
  52. package/dist/server/data-push.d.ts +0 -1
  53. package/dist/server/data-push.js +0 -7
  54. package/dist/server/proxy.js +128 -224
  55. package/dist/server/ui-route.js +76 -59
  56. package/dist/tools/index.d.ts +1 -1
  57. package/dist/tools/index.js +1 -1
  58. package/dist/tools/registry.d.ts +0 -4
  59. package/dist/tools/registry.js +0 -8
  60. package/dist/types/config.d.ts +0 -13
  61. package/dist/types/pm2.d.ts +1 -2
  62. package/dist/ui/assets/{1c-DAu68mP4.js → 1c-CCx-FOtz.js} +1 -1
  63. package/dist/ui/assets/{abnf-Cu8RHCHK.js → abnf-Bwbi42Z8.js} +1 -1
  64. package/dist/ui/assets/{abnfDiagram-VRR7QNED-BUBToPXF.js → abnfDiagram-VRR7QNED-Dm1-8q0E.js} +1 -1
  65. package/dist/ui/assets/{accesslog-BG-34XOy.js → accesslog-DCytz_-m.js} +1 -1
  66. package/dist/ui/assets/{actionscript-iw0HHMGM.js → actionscript-3udf15oh.js} +1 -1
  67. package/dist/ui/assets/{ada-qRqj6VGQ.js → ada-M5Xa74xG.js} +1 -1
  68. package/dist/ui/assets/{angelscript-BeaXyx_P.js → angelscript-qlrFxfW-.js} +1 -1
  69. package/dist/ui/assets/{apache-CU8d-z9X.js → apache-B-sF-DQH.js} +1 -1
  70. package/dist/ui/assets/{applescript-d1Wxkqz1.js → applescript-4FdcBnbI.js} +1 -1
  71. package/dist/ui/assets/{arc-BMsPIm3j.js → arc-BB3K1enp.js} +1 -1
  72. package/dist/ui/assets/{arcade-CtbgrWTM.js → arcade-B_yqWaaG.js} +1 -1
  73. package/dist/ui/assets/{architectureDiagram-ZJ3FMSHR-CVjC5TrS.js → architectureDiagram-ZJ3FMSHR-B39vkY8V.js} +1 -1
  74. package/dist/ui/assets/{arduino-Bc9L39Hr.js → arduino-yAcBoTWU.js} +1 -1
  75. package/dist/ui/assets/{armasm-DuWmpjWR.js → armasm-wIcY84bI.js} +1 -1
  76. package/dist/ui/assets/{asciidoc-CDIhFTnx.js → asciidoc-Bxnu28-Z.js} +1 -1
  77. package/dist/ui/assets/{aspectj-SYj-57Es.js → aspectj-B2cKJA_O.js} +1 -1
  78. package/dist/ui/assets/{autohotkey-hBi5dq37.js → autohotkey-B_rMWTtE.js} +1 -1
  79. package/dist/ui/assets/{autoit-BSawXzhg.js → autoit-DwcuvMwv.js} +1 -1
  80. package/dist/ui/assets/{avrasm-CwYom8Np.js → avrasm-heGX1PXK.js} +1 -1
  81. package/dist/ui/assets/{awk-BvBRfGo2.js → awk-BiqCQAEf.js} +1 -1
  82. package/dist/ui/assets/{axapta-CqUavA8k.js → axapta-Cv8M-Ih6.js} +1 -1
  83. package/dist/ui/assets/{bash-BS_ZnmEu.js → bash-Divgn3JV.js} +1 -1
  84. package/dist/ui/assets/{basic-xbP4IXrN.js → basic-B9dnAP55.js} +1 -1
  85. package/dist/ui/assets/{blockDiagram-677ZJIJ3-CmpI3f5p.js → blockDiagram-677ZJIJ3-DQ1mf7A_.js} +1 -1
  86. package/dist/ui/assets/{bnf-BECwu6uW.js → bnf-kIL5mSsP.js} +1 -1
  87. package/dist/ui/assets/{brainfuck-QQgu4j4N.js → brainfuck-DqB7xDjH.js} +1 -1
  88. package/dist/ui/assets/{coq-IDMIFfem.js → c-HmsCM6sx.js} +1 -1
  89. package/dist/ui/assets/{c-like-DYrFOtXy.js → c-like-De5MhE7G.js} +1 -1
  90. package/dist/ui/assets/{c4Diagram-LMCZKHZV-B6Hgngz9.js → c4Diagram-LMCZKHZV-DQxtYsAx.js} +1 -1
  91. package/dist/ui/assets/{cal-CNMrJ6v5.js → cal-mYdfz9en.js} +1 -1
  92. package/dist/ui/assets/{capnproto-DYCKl6oY.js → capnproto-D04CRlOt.js} +1 -1
  93. package/dist/ui/assets/{ceylon-mb8tRPl0.js → ceylon-pi9lFCja.js} +1 -1
  94. package/dist/ui/assets/channel-ChTtxQDg.js +1 -0
  95. package/dist/ui/assets/{chunk-2Q5K7J3B-LxvQ-G67.js → chunk-2Q5K7J3B-BDD1nPt8.js} +1 -1
  96. package/dist/ui/assets/{chunk-32BRIVSS-DxzKK6Aw.js → chunk-32BRIVSS-DgeQFBb5.js} +1 -1
  97. package/dist/ui/assets/{chunk-5VM5RSS4-CZEoYJ2W.js → chunk-5VM5RSS4-C7Xf2SnI.js} +1 -1
  98. package/dist/ui/assets/{chunk-EX3LRPZG-DS2PytrN.js → chunk-EX3LRPZG-B_3p1HEv.js} +1 -1
  99. package/dist/ui/assets/{chunk-JWPE2WC7-UX0Sr1Ie.js → chunk-JWPE2WC7-Dvs7u8eY.js} +1 -1
  100. package/dist/ui/assets/{chunk-MOJQB5TN-YbJgT9t4.js → chunk-MOJQB5TN-By21wDCN.js} +1 -1
  101. package/dist/ui/assets/{chunk-RYQCIY6F-DS2VH_U9.js → chunk-RYQCIY6F-6NC700r1.js} +1 -1
  102. package/dist/ui/assets/{chunk-V7JOEXUC-CZr0pkI1.js → chunk-V7JOEXUC-vEUqZ3rh.js} +1 -1
  103. package/dist/ui/assets/{chunk-VR4S4FIN-50opPAD3.js → chunk-VR4S4FIN-6tX2dNN9.js} +1 -1
  104. package/dist/ui/assets/{chunk-XXDRQBXY-DAAX9l7U.js → chunk-XXDRQBXY-qDb2jxAR.js} +1 -1
  105. package/dist/ui/assets/classDiagram-OUVF2IWQ-Ccbvamlu.js +1 -0
  106. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-Ccbvamlu.js +1 -0
  107. package/dist/ui/assets/{clean-C4X7dSkh.js → clean-CLCsDUl1.js} +1 -1
  108. package/dist/ui/assets/{clojure-DSg9gUa7.js → clojure-dVi5Xifj.js} +1 -1
  109. package/dist/ui/assets/{clojure-repl-CagRYx7h.js → clojure-repl-BO_FpFmF.js} +1 -1
  110. package/dist/ui/assets/{cmake-CFdBn53c.js → cmake-CP5aJbyK.js} +1 -1
  111. package/dist/ui/assets/{coffeescript-CJZtMOPx.js → coffeescript-ZEfu_9pF.js} +1 -1
  112. package/dist/ui/assets/{c-BRJEPYra.js → coq-6aKUn3zn.js} +1 -1
  113. package/dist/ui/assets/{cos-Bx2VJuzG.js → cos-BohCnRN2.js} +1 -1
  114. package/dist/ui/assets/{cose-bilkent-JH36ORCC-zWRLsZpZ.js → cose-bilkent-JH36ORCC-DyXCbbro.js} +1 -1
  115. package/dist/ui/assets/{cpp-CsG6DlC4.js → cpp-FOgPWPEt.js} +1 -1
  116. package/dist/ui/assets/{crmsh-DTy9MnmJ.js → crmsh-B0OYb-Oe.js} +1 -1
  117. package/dist/ui/assets/{crystal-BwgrLrZ1.js → crystal-CuWb_dXm.js} +1 -1
  118. package/dist/ui/assets/{csharp-B2VeTPAF.js → csharp-BbcqM09j.js} +1 -1
  119. package/dist/ui/assets/{csp-CTpydNhH.js → csp-rgHnTaDq.js} +1 -1
  120. package/dist/ui/assets/{css-B0mMUbpY.js → css-C-ibh7ZG.js} +1 -1
  121. package/dist/ui/assets/{cynefin-VYW2F7L2-BmjQEj6q.js → cynefin-VYW2F7L2-CkuBhgC4.js} +1 -1
  122. package/dist/ui/assets/{cynefinDiagram-TSTJHNR4-Dr0Zrke0.js → cynefinDiagram-TSTJHNR4-eycFyDao.js} +1 -1
  123. package/dist/ui/assets/{d-DjuDZnbI.js → d-C0gXxJ0O.js} +1 -1
  124. package/dist/ui/assets/{dagre-VKFMJZFB-xoTPT2Uu.js → dagre-VKFMJZFB-DzqX9e49.js} +1 -1
  125. package/dist/ui/assets/{dart-xR3GU9TJ.js → dart-C-fTpuUV.js} +1 -1
  126. package/dist/ui/assets/{delphi-bJas5QnG.js → delphi-Chm0B9xv.js} +1 -1
  127. package/dist/ui/assets/{diagram-FQU43EPY-rL_IU7gU.js → diagram-FQU43EPY-BEgCqfg1.js} +1 -1
  128. package/dist/ui/assets/{diagram-G47NLZAW-EcDiCVGj.js → diagram-G47NLZAW-Cw11Vs2v.js} +1 -1
  129. package/dist/ui/assets/{diagram-NH7WQ7WH-CGGXOjev.js → diagram-NH7WQ7WH-DSG_UWpP.js} +1 -1
  130. package/dist/ui/assets/{diagram-OA4YK3LP-DnE7hDjD.js → diagram-OA4YK3LP-CJz-WOaJ.js} +1 -1
  131. package/dist/ui/assets/{diagram-WEI45ONY-CTJH5eD8.js → diagram-WEI45ONY-CBXjBCvc.js} +1 -1
  132. package/dist/ui/assets/{diff-doJFF3fv.js → diff-C-vyuMSL.js} +1 -1
  133. package/dist/ui/assets/{django-D3b-owa_.js → django-CJK7lReT.js} +1 -1
  134. package/dist/ui/assets/{dns-C42KYV-Z.js → dns-D02SHjSy.js} +1 -1
  135. package/dist/ui/assets/{dockerfile-9KUINc2j.js → dockerfile-trKL1Bqu.js} +1 -1
  136. package/dist/ui/assets/{dos-CxnlJ6qp.js → dos-C52dy-sK.js} +1 -1
  137. package/dist/ui/assets/{dsconfig-6CMMCwmY.js → dsconfig-MzHgzVrt.js} +1 -1
  138. package/dist/ui/assets/{dts-D78rdUIB.js → dts-B137dHyX.js} +1 -1
  139. package/dist/ui/assets/{dust-Dv1uTfJU.js → dust-BcbM0r5C.js} +1 -1
  140. package/dist/ui/assets/{ebnf-BGbG1cFK.js → ebnf-DkbpI7bK.js} +1 -1
  141. package/dist/ui/assets/{ebnfDiagram-CCIWWBDH-z2VgRSUV.js → ebnfDiagram-CCIWWBDH-aI5uQ7w1.js} +1 -1
  142. package/dist/ui/assets/{elixir-ZgAQVY1J.js → elixir-BOtDuqQy.js} +1 -1
  143. package/dist/ui/assets/{elm-CudiFuNu.js → elm-DS8Tyyu-.js} +1 -1
  144. package/dist/ui/assets/{erDiagram-Q63AITRT-X1TODuRv.js → erDiagram-Q63AITRT-2vCbd4Mm.js} +1 -1
  145. package/dist/ui/assets/{erb-Bz_NZh6W.js → erb-CSXECRbn.js} +1 -1
  146. package/dist/ui/assets/{erlang-DNuj1nb2.js → erlang-BMxlgKPJ.js} +1 -1
  147. package/dist/ui/assets/{erlang-repl-SP1Gan9W.js → erlang-repl-DPzlolPg.js} +1 -1
  148. package/dist/ui/assets/{excel-0K77uECF.js → excel-CW2Uxed3.js} +1 -1
  149. package/dist/ui/assets/{fix-CalJq7JD.js → fix-UW84SlCs.js} +1 -1
  150. package/dist/ui/assets/{flix-BlIs11_w.js → flix-4UGiPULd.js} +1 -1
  151. package/dist/ui/assets/{flowDiagram-23GEKE2U-DA2dnmc0.js → flowDiagram-23GEKE2U-R5PbCbZI.js} +1 -1
  152. package/dist/ui/assets/{fortran-ZCobXY2R.js → fortran-nhHsngdu.js} +1 -1
  153. package/dist/ui/assets/{fsharp-Be8rwUtc.js → fsharp-CDyZ1ST5.js} +1 -1
  154. package/dist/ui/assets/{gams-DUat8frQ.js → gams-DHzkkUie.js} +1 -1
  155. package/dist/ui/assets/{ganttDiagram-NO4QXBWP-DdFwaIGZ.js → ganttDiagram-NO4QXBWP-CGcq4Ie_.js} +1 -1
  156. package/dist/ui/assets/{gauss-BB4U88dy.js → gauss-DdhFGyBv.js} +1 -1
  157. package/dist/ui/assets/{gcode-DzeUZuZg.js → gcode-ImHh8OLA.js} +1 -1
  158. package/dist/ui/assets/{gherkin-B_8vW_BO.js → gherkin-CTWAW-XR.js} +1 -1
  159. package/dist/ui/assets/{gitGraphDiagram-IHSO6WYX-B-Dn8x6I.js → gitGraphDiagram-IHSO6WYX-8nM2Z9lD.js} +1 -1
  160. package/dist/ui/assets/{glsl-DGHGjPC1.js → glsl-0_W_27G2.js} +1 -1
  161. package/dist/ui/assets/{gml-BYEku8Yh.js → gml-BoDggu2z.js} +1 -1
  162. package/dist/ui/assets/{go-D8aSgQMc.js → go-DYfFygwl.js} +1 -1
  163. package/dist/ui/assets/{golo-CDjCU_jh.js → golo-Mlq-TCg9.js} +1 -1
  164. package/dist/ui/assets/{gradle-BeUw7tl_.js → gradle-BALAinEB.js} +1 -1
  165. package/dist/ui/assets/{groovy-5iCQOtR3.js → groovy-Dht--dWU.js} +1 -1
  166. package/dist/ui/assets/{haml-BEdL8FJi.js → haml-DpMrxg0d.js} +1 -1
  167. package/dist/ui/assets/{handlebars-BuYQNzoK.js → handlebars-DqHzujNj.js} +1 -1
  168. package/dist/ui/assets/{haskell-I4FCBcW0.js → haskell-DZSchhkY.js} +1 -1
  169. package/dist/ui/assets/{haxe-yigyKfFr.js → haxe-C0zBRjdy.js} +1 -1
  170. package/dist/ui/assets/{hsp-ZUk4j7d1.js → hsp-D_PwbSv2.js} +1 -1
  171. package/dist/ui/assets/{htmlbars-QYP3lT3u.js → htmlbars-DxAFMG8u.js} +1 -1
  172. package/dist/ui/assets/{http-BJpD1O71.js → http-DvTRF0Do.js} +1 -1
  173. package/dist/ui/assets/{hy-CIJ1bP6S.js → hy-lVO-kNyp.js} +1 -1
  174. package/dist/ui/assets/{index-BDXWttnT.js → index-BbMRVVGt.js} +3 -3
  175. package/dist/ui/assets/{index-COAgrx1J.js → index-Ci23SMK2.js} +242 -242
  176. package/dist/ui/assets/index-DlsVXaHT.css +10 -0
  177. package/dist/ui/assets/{infoDiagram-FWYZ7A6U-fTg9eLNt.js → infoDiagram-FWYZ7A6U-C7WYDlvc.js} +1 -1
  178. package/dist/ui/assets/{inform7-DAsu-lC2.js → inform7-B8Tf2n8v.js} +1 -1
  179. package/dist/ui/assets/{ini-Bhz-zHCg.js → ini-DSoYMaLF.js} +1 -1
  180. package/dist/ui/assets/{irpf90-BunhbwBl.js → irpf90-RCPdkB14.js} +1 -1
  181. package/dist/ui/assets/{isbl-q9L6hOhP.js → isbl-C2p75PPj.js} +1 -1
  182. package/dist/ui/assets/{ishikawaDiagram-FXEZZL3T-B8G0sdgd.js → ishikawaDiagram-FXEZZL3T-Cm6jsPlc.js} +1 -1
  183. package/dist/ui/assets/{java-Iks5Pkau.js → java-DeY4Yuia.js} +1 -1
  184. package/dist/ui/assets/{javascript-C4vltXPw.js → javascript-3uX1CO-H.js} +1 -1
  185. package/dist/ui/assets/{jboss-cli-BQBvd2X2.js → jboss-cli-DgnD8mEc.js} +1 -1
  186. package/dist/ui/assets/{journeyDiagram-5HDEW3XC-Crbzgrum.js → journeyDiagram-5HDEW3XC-DEGV1uA5.js} +1 -1
  187. package/dist/ui/assets/{json-DXK0_jUK.js → json-BV2PmJJp.js} +1 -1
  188. package/dist/ui/assets/{julia-CCYoBiYK.js → julia-B-m8kQm7.js} +1 -1
  189. package/dist/ui/assets/{julia-repl-y8v2Oorl.js → julia-repl-C51atU2X.js} +1 -1
  190. package/dist/ui/assets/{kanban-definition-HUTT4EX6-C8sCOsBX.js → kanban-definition-HUTT4EX6-BJ4k5iTX.js} +1 -1
  191. package/dist/ui/assets/{kotlin-Bnjk7_fw.js → kotlin-CYBziIgl.js} +1 -1
  192. package/dist/ui/assets/{lasso-B-al6x63.js → lasso-Dw2SBMDW.js} +1 -1
  193. package/dist/ui/assets/{latex-BUmqlb9r.js → latex-Dpd35yke.js} +1 -1
  194. package/dist/ui/assets/{ldif-D42RWj6Q.js → ldif-Ce9EZU__.js} +1 -1
  195. package/dist/ui/assets/{leaf-CrH4BZ0m.js → leaf-CpkZzQtC.js} +1 -1
  196. package/dist/ui/assets/{less-upmRlQQW.js → less-Uzo7M0FD.js} +1 -1
  197. package/dist/ui/assets/{lisp-DHYS22SA.js → lisp-DWXDlJYm.js} +1 -1
  198. package/dist/ui/assets/{livecodeserver-CeQNmFP3.js → livecodeserver-uEyPEgVJ.js} +1 -1
  199. package/dist/ui/assets/{livescript-PJWpY1JI.js → livescript-BQ5f07oK.js} +1 -1
  200. package/dist/ui/assets/{llvm-BKtKWwCt.js → llvm-BAvP-skE.js} +1 -1
  201. package/dist/ui/assets/{lsl-RWRLRjk7.js → lsl-DhbiIKu6.js} +1 -1
  202. package/dist/ui/assets/{lua-BFUDiPGm.js → lua-COxeUeLx.js} +1 -1
  203. package/dist/ui/assets/{makefile-CUDyOz5D.js → makefile-DhDx-IgL.js} +1 -1
  204. package/dist/ui/assets/{markdown-zZCLypc6.js → markdown-DX5_kSxq.js} +1 -1
  205. package/dist/ui/assets/{mathematica-BHbxKxnq.js → mathematica-D351ZddB.js} +1 -1
  206. package/dist/ui/assets/{matlab-DlGtg--p.js → matlab-CELqIiwF.js} +1 -1
  207. package/dist/ui/assets/{maxima-BBBeS3Ra.js → maxima-B_YljrMm.js} +1 -1
  208. package/dist/ui/assets/{mel-nh8j7W_6.js → mel-DltsbNS8.js} +1 -1
  209. package/dist/ui/assets/{mercury-DyyD-pqr.js → mercury-axX-5Vjj.js} +1 -1
  210. package/dist/ui/assets/{mindmap-definition-LN4V7U3C-CJlhDHqM.js → mindmap-definition-LN4V7U3C-Bl1EJo6p.js} +1 -1
  211. package/dist/ui/assets/{mipsasm-hiEhRRiq.js → mipsasm-BxmerVwX.js} +1 -1
  212. package/dist/ui/assets/{mizar-BZa3iAAL.js → mizar-XNHfbpL2.js} +1 -1
  213. package/dist/ui/assets/{mojolicious-BCIm2V_y.js → mojolicious-BR0U_7zk.js} +1 -1
  214. package/dist/ui/assets/{monkey-zmK-7N8b.js → monkey-lLuu9_f-.js} +1 -1
  215. package/dist/ui/assets/{moonscript-BsS_Mn3D.js → moonscript-DoaZ3DRQ.js} +1 -1
  216. package/dist/ui/assets/{n1ql-D7xVgDP0.js → n1ql-C6TId6Iu.js} +1 -1
  217. package/dist/ui/assets/{nginx-ct2q4dtd.js → nginx-BezSG-JT.js} +1 -1
  218. package/dist/ui/assets/{nim-RO0UOmW3.js → nim-Bb0rfXie.js} +1 -1
  219. package/dist/ui/assets/{nix-BcRJxPKH.js → nix-o3sJ5-54.js} +1 -1
  220. package/dist/ui/assets/{node-repl-DgIefwxW.js → node-repl-Sv5hhcTf.js} +1 -1
  221. package/dist/ui/assets/{nsis-DqHs9QhB.js → nsis-B45BJFhF.js} +1 -1
  222. package/dist/ui/assets/{objectivec-BBcWqc7Y.js → objectivec-CzS6zVgh.js} +1 -1
  223. package/dist/ui/assets/{ocaml-BExfw7D6.js → ocaml-Bqux7PyP.js} +1 -1
  224. package/dist/ui/assets/{openscad-CHPRELQb.js → openscad-4Wf6mF84.js} +1 -1
  225. package/dist/ui/assets/{oxygene-DpS9uMJW.js → oxygene-Fvwqgkkt.js} +1 -1
  226. package/dist/ui/assets/{parser3-CjJ_QdBp.js → parser3-zEfzT5wv.js} +1 -1
  227. package/dist/ui/assets/{pegDiagram-2B236MQR-GM70woGy.js → pegDiagram-2B236MQR-Dd4rIztM.js} +1 -1
  228. package/dist/ui/assets/{perl-BSNM2Kt8.js → perl-CsS1Gs6o.js} +1 -1
  229. package/dist/ui/assets/{pf-Z-hKf_88.js → pf-BNH1jO0R.js} +1 -1
  230. package/dist/ui/assets/{pgsql-DDgznxBg.js → pgsql-DqPigHrq.js} +1 -1
  231. package/dist/ui/assets/{php-BzAhxF-l.js → php-CdOl9bRs.js} +1 -1
  232. package/dist/ui/assets/{php-template-DkgcKHRc.js → php-template-DPfirJg2.js} +1 -1
  233. package/dist/ui/assets/{pieDiagram-ENE6RG2P-Bst7mPyz.js → pieDiagram-ENE6RG2P-DGaJNf4S.js} +1 -1
  234. package/dist/ui/assets/{plaintext-BYEppD0R.js → plaintext-EHbgBKzw.js} +1 -1
  235. package/dist/ui/assets/{pony-BT_kQd1K.js → pony-DmJajtp2.js} +1 -1
  236. package/dist/ui/assets/{powershell-BfRsuSsf.js → powershell-DfGzdWR6.js} +1 -1
  237. package/dist/ui/assets/{processing-DpzWe5Iu.js → processing-BT0ETgPG.js} +1 -1
  238. package/dist/ui/assets/{profile-BCOhS5cM.js → profile-B3I-x5Lt.js} +1 -1
  239. package/dist/ui/assets/{prolog-OxaCCaW8.js → prolog-B_4QJIvI.js} +1 -1
  240. package/dist/ui/assets/{properties-DMFlA2Ca.js → properties-BFVI8weS.js} +1 -1
  241. package/dist/ui/assets/{protobuf-CRDFkXvZ.js → protobuf-PaF39oZZ.js} +1 -1
  242. package/dist/ui/assets/{puppet-DnrVyLzx.js → puppet-BDC6Q8VF.js} +1 -1
  243. package/dist/ui/assets/{purebasic-Dht4Hniv.js → purebasic-B2ejrOZK.js} +1 -1
  244. package/dist/ui/assets/{python-B0aMirWu.js → python-BOxtIk9H.js} +1 -1
  245. package/dist/ui/assets/{python-repl-BlYDBGa7.js → python-repl-BslBh_Mx.js} +1 -1
  246. package/dist/ui/assets/{q-DzrtW9kT.js → q-BPe8WLGW.js} +1 -1
  247. package/dist/ui/assets/{qml-DnfQsR3i.js → qml-BazRR6fz.js} +1 -1
  248. package/dist/ui/assets/{quadrantDiagram-ABIIQ3AL-DNRYurBT.js → quadrantDiagram-ABIIQ3AL-BQ7aPkHk.js} +1 -1
  249. package/dist/ui/assets/{r-DGI_ZuTD.js → r-C09pGNJC.js} +1 -1
  250. package/dist/ui/assets/{railroadDiagram-RFXS5EU6-CmbC3Vz4.js → railroadDiagram-RFXS5EU6-sCO9VGvE.js} +1 -1
  251. package/dist/ui/assets/{reasonml-3SohMgh2.js → reasonml-S7dzwVL9.js} +1 -1
  252. package/dist/ui/assets/{requirementDiagram-TGXJPOKE-8CxrXHco.js → requirementDiagram-TGXJPOKE-CfT5aVZg.js} +1 -1
  253. package/dist/ui/assets/{rib-DfRSd4Qa.js → rib-fM2EwQd4.js} +1 -1
  254. package/dist/ui/assets/{roboconf-CQczGdGW.js → roboconf-D7AaeyrW.js} +1 -1
  255. package/dist/ui/assets/{routeros-DCka-T2i.js → routeros-c6Q7mKuq.js} +1 -1
  256. package/dist/ui/assets/{rsl-Dr8MOwMo.js → rsl-sCpEQBxh.js} +1 -1
  257. package/dist/ui/assets/{ruby-C2zFSkh_.js → ruby-lcKhz2w9.js} +1 -1
  258. package/dist/ui/assets/{ruleslanguage-C97YsgQq.js → ruleslanguage-BW4ATOuX.js} +1 -1
  259. package/dist/ui/assets/{rust-H3h8kd9A.js → rust-BbpU-0VY.js} +1 -1
  260. package/dist/ui/assets/{sankeyDiagram-HTMAVEWB-DBXLWjEq.js → sankeyDiagram-HTMAVEWB-CaweCpvN.js} +1 -1
  261. package/dist/ui/assets/{sas-04z0Xu8P.js → sas-BPt5R0dx.js} +1 -1
  262. package/dist/ui/assets/{scala-DyB9Aoiv.js → scala-DxW_vqXs.js} +1 -1
  263. package/dist/ui/assets/{scheme-DBj6nxUi.js → scheme-T2Q_jWzT.js} +1 -1
  264. package/dist/ui/assets/{scilab-Btj7AD9s.js → scilab-DMORg9lV.js} +1 -1
  265. package/dist/ui/assets/{scss-BXZJyXt7.js → scss-t0VsosqT.js} +1 -1
  266. package/dist/ui/assets/{sequenceDiagram-DBY2YBRQ-DXIkBFKC.js → sequenceDiagram-DBY2YBRQ-o-H_R4zb.js} +1 -1
  267. package/dist/ui/assets/{shell-BsreQR1Z.js → shell-CnCDa1s9.js} +1 -1
  268. package/dist/ui/assets/{sizeCapture-X5ZJPWSS-ocS9jxAQ.js → sizeCapture-X5ZJPWSS-BNLkHGDS.js} +1 -1
  269. package/dist/ui/assets/{smali-D9wQw9zm.js → smali-_n-BxJyG.js} +1 -1
  270. package/dist/ui/assets/{smalltalk-Dku6G_H3.js → smalltalk-B90PXJwK.js} +1 -1
  271. package/dist/ui/assets/{sml-BknyU6ya.js → sml-fuY7bj-n.js} +1 -1
  272. package/dist/ui/assets/{sqf-DRYMaOg8.js → sqf-COpwkyuo.js} +1 -1
  273. package/dist/ui/assets/{sql-Cw3Ax4KA.js → sql-CXIT0j-x.js} +1 -1
  274. package/dist/ui/assets/{sql_more-vWdslLE0.js → sql_more-C1Oxq4rx.js} +1 -1
  275. package/dist/ui/assets/{stan-8XH5bDS6.js → stan-BZEpaHeC.js} +1 -1
  276. package/dist/ui/assets/{stata-4e77wgfe.js → stata-CkBwaiZM.js} +1 -1
  277. package/dist/ui/assets/{stateDiagram-2N3HPSRC-RMmL9jMG.js → stateDiagram-2N3HPSRC-BkdnNF7I.js} +1 -1
  278. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-0JnZ1VSQ.js +1 -0
  279. package/dist/ui/assets/{step21-ByIeDMY3.js → step21-fs9N_U3O.js} +1 -1
  280. package/dist/ui/assets/{stylus-ZAhJyWsw.js → stylus-Bs_9cvKZ.js} +1 -1
  281. package/dist/ui/assets/{subunit-pPW2UGkj.js → subunit-DvgcOCqJ.js} +1 -1
  282. package/dist/ui/assets/{swift-CX3BB5az.js → swift-BE4ONsur.js} +1 -1
  283. package/dist/ui/assets/{swimlanes-5IMT3BWC-C2zAuJ56.js → swimlanes-5IMT3BWC-uqTAc7o7.js} +2 -2
  284. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DQRIIEmi.js +8 -0
  285. package/dist/ui/assets/{taggerscript-BHcjbWIC.js → taggerscript-BhmPJ64C.js} +1 -1
  286. package/dist/ui/assets/{tap-BOl1lBlS.js → tap-DkueIVKV.js} +1 -1
  287. package/dist/ui/assets/{tcl-DZjeOBDh.js → tcl-DyXOOkFi.js} +1 -1
  288. package/dist/ui/assets/{thrift-BxboWg4x.js → thrift-Dhgbk56T.js} +1 -1
  289. package/dist/ui/assets/{timeline-definition-FHXFAJF6-BOxsxyq_.js → timeline-definition-FHXFAJF6-DBAk9Ouc.js} +1 -1
  290. package/dist/ui/assets/{tp-BNM6ql3J.js → tp-BsXyrRGH.js} +1 -1
  291. package/dist/ui/assets/{twig-Dj9ZiXD4.js → twig-J0HqIuHw.js} +1 -1
  292. package/dist/ui/assets/{typescript-7MEJlu_6.js → typescript-Dkwvul39.js} +1 -1
  293. package/dist/ui/assets/{vala-DNqOAgHJ.js → vala-CRGnf8aY.js} +1 -1
  294. package/dist/ui/assets/{vbnet-T0mNKVc_.js → vbnet-BtJAUe3z.js} +1 -1
  295. package/dist/ui/assets/{vbscript-CeuwVMAI.js → vbscript-RgFFNuM3.js} +1 -1
  296. package/dist/ui/assets/{vbscript-html-BbJSt2w6.js → vbscript-html-DO32Io9Y.js} +1 -1
  297. package/dist/ui/assets/{vennDiagram-L72KCM5P-BX9mWeiT.js → vennDiagram-L72KCM5P-BJi6y0hh.js} +1 -1
  298. package/dist/ui/assets/{verilog-DYuhYfkX.js → verilog-C4h6MLcI.js} +1 -1
  299. package/dist/ui/assets/{vhdl-Cf9aT-t7.js → vhdl-DOafePyU.js} +1 -1
  300. package/dist/ui/assets/{vim-DciP44K1.js → vim-BAdTA9TY.js} +1 -1
  301. package/dist/ui/assets/{wardleyDiagram-EHGQE667-CDj2rOzu.js → wardleyDiagram-EHGQE667-C7c_4IJ6.js} +1 -1
  302. package/dist/ui/assets/{x86asm-E-AN_LXO.js → x86asm-BCL6__QH.js} +1 -1
  303. package/dist/ui/assets/{xl-CxYLJelN.js → xl-qIzE4HOe.js} +1 -1
  304. package/dist/ui/assets/{xml-yz1SRLuU.js → xml-DE2sJXYU.js} +1 -1
  305. package/dist/ui/assets/{xquery-BLzBF3tV.js → xquery-CQ35t92y.js} +1 -1
  306. package/dist/ui/assets/{xychartDiagram-FW5EYKEG-Czapk9-Z.js → xychartDiagram-FW5EYKEG-D2ILn0jL.js} +1 -1
  307. package/dist/ui/assets/{yaml-Cv4Y7iN_.js → yaml-5KaAvG5C.js} +1 -1
  308. package/dist/ui/assets/{zephir-KRcdQfEX.js → zephir-CbR3Ryfq.js} +1 -1
  309. package/dist/ui/index.html +2 -2
  310. package/dist/utils/__tests__/abort-signals.test.js +67 -0
  311. package/dist/utils/__tests__/inject-loop.test.js +1 -53
  312. package/dist/utils/__tests__/learn-tasks-db.test.js +82 -0
  313. package/dist/utils/__tests__/openai-converter.test.js +25 -0
  314. package/dist/utils/__tests__/pi-crawl-tools.test.js +15 -4
  315. package/dist/utils/__tests__/pi-dedup-reconcile.test.js +11 -9
  316. package/dist/utils/__tests__/pi-events.test.js +172 -0
  317. package/dist/utils/__tests__/pi-learn-orchestrator.test.js +216 -6
  318. package/dist/utils/__tests__/pi-runtime-json.test.js +38 -3
  319. package/dist/utils/__tests__/providers-db.test.js +40 -2
  320. package/dist/utils/__tests__/request-writer.test.js +271 -39
  321. package/dist/utils/__tests__/sse-protocol.test.d.ts +1 -0
  322. package/dist/utils/__tests__/sse-protocol.test.js +115 -0
  323. package/dist/utils/__tests__/vault.test.d.ts +1 -0
  324. package/dist/utils/__tests__/{knowledge-store.test.js → vault.test.js} +16 -16
  325. package/dist/utils/abort-signals.d.ts +13 -0
  326. package/dist/utils/abort-signals.js +33 -0
  327. package/dist/utils/db.d.ts +1 -0
  328. package/dist/utils/db.js +24 -0
  329. package/dist/utils/esm-dirname.d.ts +0 -15
  330. package/dist/utils/esm-dirname.js +0 -4
  331. package/dist/utils/inject-loop.d.ts +0 -27
  332. package/dist/utils/inject-loop.js +2 -56
  333. package/dist/utils/learn-tasks-db.d.ts +15 -0
  334. package/dist/utils/learn-tasks-db.js +35 -0
  335. package/dist/utils/openai-converter.js +88 -78
  336. package/dist/utils/pi-browser-tools.d.ts +0 -2
  337. package/dist/utils/pi-browser-tools.js +0 -174
  338. package/dist/utils/pi-crawl-tools.d.ts +2 -1
  339. package/dist/utils/pi-crawl-tools.js +16 -11
  340. package/dist/utils/pi-dedup.d.ts +8 -30
  341. package/dist/utils/pi-dedup.js +32 -67
  342. package/dist/utils/pi-events.d.ts +65 -0
  343. package/dist/utils/pi-events.js +98 -0
  344. package/dist/utils/pi-learn-orchestrator.d.ts +6 -5
  345. package/dist/utils/pi-learn-orchestrator.js +71 -106
  346. package/dist/utils/pi-runtime.d.ts +5 -6
  347. package/dist/utils/pi-runtime.js +38 -42
  348. package/dist/utils/pi-sandbox-ops.d.ts +0 -36
  349. package/dist/utils/pi-sandbox-ops.js +5 -190
  350. package/dist/utils/providers-db.d.ts +3 -0
  351. package/dist/utils/providers-db.js +21 -7
  352. package/dist/utils/request-writer.d.ts +59 -30
  353. package/dist/utils/request-writer.js +178 -58
  354. package/dist/utils/sse-protocol.d.ts +34 -0
  355. package/dist/utils/sse-protocol.js +121 -0
  356. package/dist/utils/sse-stream-processor.d.ts +4 -9
  357. package/dist/utils/sse-stream-processor.js +13 -104
  358. package/dist/utils/sse-writer.d.ts +1 -1
  359. package/dist/utils/sse-writer.js +3 -2
  360. package/dist/utils/stats-aggregator.js +3 -0
  361. package/dist/utils/tool-injector.js +7 -0
  362. package/dist/utils/vault.d.ts +111 -0
  363. package/dist/utils/vault.js +434 -0
  364. package/package.json +1 -1
  365. package/dist/docs/assets/chunks/@localSearchIndexroot.B6Qfxe6W.js +0 -1
  366. package/dist/types/api.d.ts +0 -20
  367. package/dist/types/index.d.ts +0 -4
  368. package/dist/types/index.js +0 -4
  369. package/dist/types/log.d.ts +0 -13
  370. package/dist/ui/assets/channel-Bc4Td8eZ.js +0 -1
  371. package/dist/ui/assets/classDiagram-OUVF2IWQ-BicxhZFq.js +0 -1
  372. package/dist/ui/assets/classDiagram-v2-EOCWNBFH-BicxhZFq.js +0 -1
  373. package/dist/ui/assets/index-C0fxlU9d.css +0 -10
  374. package/dist/ui/assets/stateDiagram-v2-6OUMAXLB-QvaEO5U6.js +0 -1
  375. package/dist/ui/assets/swimlanesDiagram-G3AALYLV-DPgCOY0D.js +0 -8
  376. package/dist/utils/__tests__/sse-accumulator.test.js +0 -83
  377. package/dist/utils/knowledge-store.d.ts +0 -51
  378. package/dist/utils/knowledge-store.js +0 -241
  379. package/dist/utils/migrate-files-to-db.d.ts +0 -1
  380. package/dist/utils/migrate-files-to-db.js +0 -138
  381. package/dist/utils/sse-accumulator.d.ts +0 -9
  382. package/dist/utils/sse-accumulator.js +0 -59
  383. /package/dist/docs/assets/{proxy-cli_data-hooks.md.w9Oe1OD3.lean.js → proxy-cli_data-hooks.md.Bz8CVbxO.lean.js} +0 -0
  384. /package/dist/docs/assets/{proxy-core_ui-routes.md.Dyqkeoiv.lean.js → proxy-core_ui-routes.md.B21t1p7R.lean.js} +0 -0
  385. /package/dist/{types/api.js → utils/__tests__/abort-signals.test.d.ts} +0 -0
  386. /package/dist/{types/log.js → utils/__tests__/learn-tasks-db.test.d.ts} +0 -0
  387. /package/dist/utils/__tests__/{knowledge-store.test.d.ts → openai-converter.test.d.ts} +0 -0
  388. /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,58 +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
- userAgent: request.headers['user-agent'],
213
- baseUrl: resolved.baseUrl,
214
- usage,
215
- pendingId: requestId !== request.id ? `${sessionId}:${request.id}` : undefined
216
- }, 'completed');
217
- }
218
159
  export function getErrorMessage(error) {
219
160
  if (error.code === 'ECONNREFUSED') {
220
161
  return 'Target server unreachable';
@@ -227,12 +168,50 @@ export function getErrorMessage(error) {
227
168
  }
228
169
  return 'Proxy error';
229
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
+ }
230
199
  export async function setupProxy(fastify, proxyConfig) {
231
200
  // Load full config to get storage.maxDays
232
201
  const fullConfig = await loadConfig();
233
202
  const maxDays = fullConfig.storage?.maxDays ?? 7;
234
203
  // Initialize SQLite database
235
- 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
+ }
236
215
  // Initialize MCP connections (after DB is ready)
237
216
  try {
238
217
  await mcpManager.init();
@@ -286,9 +265,12 @@ export async function setupProxy(fastify, proxyConfig) {
286
265
  fastify.all('/v1/*', async (request, reply) => {
287
266
  const startTime = Date.now();
288
267
  const resolved = resolveProxyTarget(proxyConfig);
268
+ // 下游客户端中止:整个请求作用域建一次,两处上游 fetch 复用
269
+ const clientSignal = createClientAbortSignal(request.raw);
289
270
  const sessionId = request.headers['x-claude-code-session-id'] || 'unknown-session';
290
271
  // Replace model based on tier matching (getProxyModel)
291
272
  const originalModel = request.body?.model;
273
+ let rec;
292
274
  try {
293
275
  const proxyModel = getProxyModel(originalModel, resolved);
294
276
  if (proxyModel && request.body && typeof request.body === 'object') {
@@ -312,9 +294,9 @@ export async function setupProxy(fastify, proxyConfig) {
312
294
  (forwardedAuthHeader?.startsWith('Bearer ') ? forwardedAuthHeader.slice(7) : undefined);
313
295
  // Log complete request data (Fastify already parsed body)
314
296
  const machineId = getMachineIdSync() ?? undefined;
315
- const requestData = {
316
- requestId: request.id, // Will be updated with cloud x-request-id later
297
+ const meta = {
317
298
  sessionId,
299
+ localRequestId: request.id, // Will be replaced with cloud x-request-id row on completion
318
300
  timestamp: new Date().toISOString(),
319
301
  apiKey,
320
302
  proxyApiKey,
@@ -326,34 +308,12 @@ export async function setupProxy(fastify, proxyConfig) {
326
308
  path: request.url,
327
309
  headers: forwardHeaders,
328
310
  body: request.body // Full payload: model, messages, tools, MCP params, etc.
329
- },
330
- response: {
331
- statusCode: 0, // Will be updated after fetch
332
- events: [] // Only used for JSON responses; streaming uses batch buffer
333
311
  }
334
312
  };
335
- // SSE event batch buffer: flush to DB every ~10 events to avoid in-memory accumulation
336
- // Tail buffer: keep last 5 events for token usage extraction at stream end
337
- const eventBatch = [];
338
- const tailBuffer = [];
339
- const eventIndexRef = { value: 0 };
313
+ rec = createRequestRecorder(meta);
340
314
  request.log.info(`request logged: ${request.id} ${request.method} ${request.url}`);
341
315
  // Save initial record + push pending status to frontend
342
- await saveRequestDB(sessionId, request.id, requestData);
343
- pushNewRequest({
344
- requestId: request.id,
345
- sessionId,
346
- compositeId: `${sessionId}:${request.id}`,
347
- method: request.method,
348
- path: request.url,
349
- timestamp: requestData.timestamp,
350
- statusCode: 0,
351
- responseTime: 0,
352
- model: forwardedModel,
353
- machineId,
354
- userAgent: request.headers['user-agent'],
355
- baseUrl: resolved.baseUrl
356
- }, 'pending');
316
+ await rec.pending();
357
317
  // --- OpenAI Compatible Mode ---
358
318
  if (resolved.is_openai_compatible) {
359
319
  const openaiRequest = convertClaudeToOpenAIRequest(request.body, forwardedModel);
@@ -366,14 +326,11 @@ export async function setupProxy(fastify, proxyConfig) {
366
326
  method: request.method,
367
327
  headers: openaiHeaders,
368
328
  body: JSON.stringify(openaiRequest),
369
- signal: AbortSignal.timeout(300000)
329
+ signal: createTimeoutSignal(300000, clientSignal)
370
330
  });
371
331
  request.log.info(`response status: ${response.status}`);
372
332
  // Extract cloud request ID
373
333
  const cloudRequestId = response.headers.get('x-request-id') || request.id;
374
- requestData.requestId = cloudRequestId;
375
- requestData.response.statusCode = response.status;
376
- requestData.response.headers = Object.fromEntries(response.headers);
377
334
  // Check response type
378
335
  const contentType = response.headers.get('content-type') || '';
379
336
  const isSSE = contentType.includes('text/event-stream');
@@ -386,46 +343,30 @@ export async function setupProxy(fastify, proxyConfig) {
386
343
  const openaiRes = JSON.parse(responseBody);
387
344
  const claudeRes = convertOpenAIToClaudeResponse(openaiRes, forwardedModel || originalModel);
388
345
  claudeResponseBody = JSON.stringify(claudeRes);
389
- requestData.response.events.push(claudeRes);
346
+ rec.appendEvent(claudeRes);
390
347
  }
391
348
  catch {
392
349
  claudeResponseBody = responseBody;
393
350
  try {
394
- requestData.response.events.push(JSON.parse(responseBody));
351
+ rec.appendEvent(JSON.parse(responseBody));
395
352
  }
396
353
  catch {
397
- requestData.response.events.push({ raw: responseBody });
354
+ rec.appendEvent({ raw: responseBody });
398
355
  }
399
356
  }
400
- requestData.response.completedAt = new Date().toISOString();
401
- if (cloudRequestId !== request.id) {
402
- deleteResponseEvents(request.id, sessionId);
403
- deleteRequestRow(request.id, sessionId);
404
- }
405
- await saveRequestDB(sessionId, cloudRequestId, requestData);
406
- const usage = extractTokenUsage(requestData.response.events);
407
- pushNewRequest({
408
- requestId: cloudRequestId,
409
- sessionId,
410
- compositeId: `${sessionId}:${cloudRequestId}`,
411
- method: request.method,
412
- path: request.url,
413
- timestamp: requestData.timestamp,
357
+ await rec.complete({
358
+ cloudRequestId: cloudRequestId !== request.id ? cloudRequestId : undefined,
414
359
  statusCode: response.status,
415
- responseTime: Date.now() - startTime,
416
- model: forwardedModel,
417
- machineId,
418
- userAgent: request.headers['user-agent'],
419
- baseUrl: resolved.baseUrl,
420
- usage,
421
- pendingId: cloudRequestId !== request.id ? `${sessionId}:${request.id}` : undefined
422
- }, 'completed');
360
+ headers: Object.fromEntries(response.headers)
361
+ });
423
362
  const elapsed = Date.now() - startTime;
424
363
  request.log.info(`json response (openai): ${cloudRequestId} ${response.status} (${elapsed}ms)`);
425
364
  reply.code(response.status).headers({ 'Content-Type': 'application/json' }).send(claudeResponseBody);
426
365
  return;
427
366
  }
428
367
  // Handle SSE streaming response
368
+ // 上游响应头已到达:回写真实 status_code(状态仍 pending,保留 spinner)
369
+ rec.headers({ statusCode: response.status, headers: Object.fromEntries(response.headers) });
429
370
  reply.hijack();
430
371
  const responseHeaders = Object.fromEntries(response.headers);
431
372
  // Replace content-type with Claude SSE format
@@ -433,51 +374,35 @@ export async function setupProxy(fastify, proxyConfig) {
433
374
  reply.raw.writeHead(response.status, responseHeaders);
434
375
  if (response.body) {
435
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);
436
383
  const transformStream = createStreamTransformer(forwardedModel || originalModel);
437
- // Record SSE events via batch buffer (memory: ≤10 batch + ≤5 tail)
384
+ // 旁路解码器:只做事件入库,不介入转发管道;[DONE] 走 onDone 留空,天然不入库
385
+ const tapDecoder = createEventDecoder((e) => rec.appendEvent(e));
438
386
  nodeStream.on('data', (chunk) => {
439
- const text = chunk.toString();
440
- const lines = text.split('\n');
441
- for (const line of lines) {
442
- if (line.startsWith('data:')) {
443
- const eventData = line.slice(5).trim();
444
- if (eventData && eventData !== '[DONE]') {
445
- try {
446
- const event = JSON.parse(eventData);
447
- pushEventToBuffers(event, sessionId, cloudRequestId, eventBatch, tailBuffer, eventIndexRef);
448
- }
449
- catch {
450
- // Not valid JSON, skip
451
- }
452
- }
453
- }
454
- }
387
+ tapDecoder.write(chunk);
455
388
  });
456
389
  // Use finished() for reliable stream completion detection
457
390
  finished(nodeStream, async (err) => {
391
+ tapDecoder.end();
458
392
  if (err) {
459
393
  request.log.error(`openai stream error: ${err.message}`);
460
- }
461
- // Convert OpenAI stream usage to Claude format for extractTokenUsage compatibility
462
- const lastChunk = tailBuffer.find((e) => e?.usage);
463
- if (lastChunk?.usage) {
464
- const syntheticEvent = {
465
- type: 'message_delta',
466
- usage: {
467
- output_tokens: lastChunk.usage.completion_tokens || 0
468
- }
469
- };
470
- pushEventToBuffers(syntheticEvent, sessionId, cloudRequestId, eventBatch, tailBuffer, eventIndexRef);
471
- }
472
- if (cloudRequestId !== request.id) {
473
- deleteResponseEvents(request.id, sessionId);
474
- deleteRequestRow(request.id, sessionId);
394
+ rec.interrupt({ statusCode: response.status, error: `stream interrupted: ${err.message}` });
395
+ return;
475
396
  }
476
397
  // Flush remaining batch + complete request
477
398
  try {
478
- 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
+ });
479
404
  const elapsed = Date.now() - startTime;
480
- 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)`);
481
406
  }
482
407
  catch (dbErr) {
483
408
  request.log.error(`openai stream save failed: ${dbErr.message}`);
@@ -498,15 +423,11 @@ export async function setupProxy(fastify, proxyConfig) {
498
423
  method: request.method,
499
424
  headers: forwardHeaders,
500
425
  body: request.method !== 'GET' ? JSON.stringify(request.body) : undefined,
501
- signal: AbortSignal.timeout(300000)
426
+ signal: createTimeoutSignal(300000, clientSignal)
502
427
  });
503
428
  request.log.info(`response status: ${response.status}`);
504
429
  // Extract cloud request ID from response header
505
430
  const cloudRequestId = response.headers.get('x-request-id') || request.id;
506
- requestData.requestId = cloudRequestId;
507
- // Update response status in requestData
508
- requestData.response.statusCode = response.status;
509
- requestData.response.headers = Object.fromEntries(response.headers);
510
431
  // Check response type: SSE stream or JSON
511
432
  const contentType = response.headers.get('content-type') || '';
512
433
  const isSSE = contentType.includes('text/event-stream');
@@ -517,35 +438,16 @@ export async function setupProxy(fastify, proxyConfig) {
517
438
  // Record JSON body as a single event
518
439
  try {
519
440
  const jsonBody = JSON.parse(responseBody);
520
- requestData.response.events.push(jsonBody);
441
+ rec.appendEvent(jsonBody);
521
442
  }
522
443
  catch {
523
- requestData.response.events.push({ raw: responseBody });
524
- }
525
- requestData.response.completedAt = new Date().toISOString();
526
- // Remove pending row if cloudRequestId differs from request.id
527
- if (cloudRequestId !== request.id) {
528
- deleteResponseEvents(request.id, sessionId);
529
- deleteRequestRow(request.id, sessionId);
444
+ rec.appendEvent({ raw: responseBody });
530
445
  }
531
- await saveRequestDB(sessionId, cloudRequestId, requestData);
532
- const usage = extractTokenUsage(requestData.response.events);
533
- pushNewRequest({
534
- requestId: cloudRequestId,
535
- sessionId,
536
- compositeId: `${sessionId}:${cloudRequestId}`,
537
- method: request.method,
538
- path: request.url,
539
- timestamp: requestData.timestamp,
446
+ await rec.complete({
447
+ cloudRequestId: cloudRequestId !== request.id ? cloudRequestId : undefined,
540
448
  statusCode: response.status,
541
- responseTime: Date.now() - startTime,
542
- model: forwardedModel,
543
- machineId,
544
- userAgent: request.headers['user-agent'],
545
- baseUrl: resolved.baseUrl,
546
- usage,
547
- pendingId: cloudRequestId !== request.id ? `${sessionId}:${request.id}` : undefined
548
- }, 'completed');
449
+ headers: Object.fromEntries(response.headers)
450
+ });
549
451
  const elapsed = Date.now() - startTime;
550
452
  request.log.info(`json response: ${cloudRequestId} ${response.status} (${elapsed}ms)`);
551
453
  reply.code(response.status);
@@ -554,6 +456,8 @@ export async function setupProxy(fastify, proxyConfig) {
554
456
  return;
555
457
  }
556
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) });
557
461
  reply.hijack();
558
462
  // Write response headers (preserve original from Aliyun)
559
463
  const responseHeaders = Object.fromEntries(response.headers);
@@ -562,38 +466,33 @@ export async function setupProxy(fastify, proxyConfig) {
562
466
  if (response.body) {
563
467
  // Convert Web ReadableStream to Node Readable stream
564
468
  const nodeStream = Readable.fromWeb(response.body);
565
- // 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));
566
477
  nodeStream.on('data', (chunk) => {
567
- const text = chunk.toString();
568
- const lines = text.split('\n');
569
- for (const line of lines) {
570
- if (line.startsWith('data:')) {
571
- const eventData = line.slice(5).trim();
572
- if (eventData && eventData !== '[DONE]') {
573
- try {
574
- const event = JSON.parse(eventData);
575
- pushEventToBuffers(event, sessionId, cloudRequestId, eventBatch, tailBuffer, eventIndexRef);
576
- }
577
- catch {
578
- // Not valid JSON, skip
579
- }
580
- }
581
- }
582
- }
478
+ tapDecoder.write(chunk);
583
479
  });
584
480
  // Save request data when stream completes
585
481
  finished(nodeStream, async (err) => {
482
+ tapDecoder.end();
586
483
  if (err) {
587
484
  request.log.error(`claude stream error: ${err.message}`);
588
- }
589
- if (cloudRequestId !== request.id) {
590
- deleteResponseEvents(request.id, sessionId);
591
- deleteRequestRow(request.id, sessionId);
485
+ rec.interrupt({ statusCode: response.status, error: `stream interrupted: ${err.message}` });
486
+ return;
592
487
  }
593
488
  try {
594
- 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
+ });
595
494
  const elapsed = Date.now() - startTime;
596
- request.log.info(`stream completed: ${cloudRequestId} ${response.status} (${elapsed}ms, ${eventIndexRef.value} events)`);
495
+ request.log.info(`stream completed: ${cloudRequestId} ${response.status} (${elapsed}ms)`);
597
496
  }
598
497
  catch (dbErr) {
599
498
  request.log.error(`stream save failed: ${dbErr.message}`);
@@ -610,22 +509,27 @@ export async function setupProxy(fastify, proxyConfig) {
610
509
  errorMessage: error.message,
611
510
  errorCode: error.code || 'unknown'
612
511
  }, 'proxy error');
613
- // Fetch failed — no cloudRequestId available, use Fastify request.id
614
- pushNewRequest({
615
- requestId: request.id,
616
- sessionId,
617
- compositeId: `${sessionId}:${request.id}`,
618
- method: request.method,
619
- path: request.url,
620
- timestamp: new Date().toISOString(),
621
- statusCode: getErrorStatusCode(error),
622
- responseTime: Date.now() - startTime,
623
- model: originalModel,
624
- machineId: getMachineIdSync() ?? undefined,
625
- userAgent: request.headers['user-agent'],
626
- baseUrl: resolved.baseUrl
627
- }, 'completed');
628
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
+ }
629
533
  reply.code(statusCode).send({
630
534
  error: getErrorMessage(error),
631
535
  requestId: request.id